diff --git a/.gitignore b/.gitignore index e4e19156c2..6d97450c7b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ coverage .nyc_output # docs output -out +out docs # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) @@ -44,9 +44,6 @@ node_modules # visual studio code .vscode -# Babel.js -lib/ - # cache folder .cache .eslintcache diff --git a/lib/AccountLockout.js b/lib/AccountLockout.js new file mode 100644 index 0000000000..6aa357302c --- /dev/null +++ b/lib/AccountLockout.js @@ -0,0 +1,172 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AccountLockout = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// This class handles the Account Lockout Policy settings. +class AccountLockout { + constructor(user, config) { + this._user = user; + this._config = config; + } + /** + * set _failed_login_count to value + */ + + + _setFailedLoginCount(value) { + const query = { + username: this._user.username + }; + const updateFields = { + _failed_login_count: value + }; + return this._config.database.update('_User', query, updateFields); + } + /** + * check if the _failed_login_count field has been set + */ + + + _isFailedLoginCountSet() { + const query = { + username: this._user.username, + _failed_login_count: { + $exists: true + } + }; + return this._config.database.find('_User', query).then(users => { + if (Array.isArray(users) && users.length > 0) { + return true; + } else { + return false; + } + }); + } + /** + * if _failed_login_count is NOT set then set it to 0 + * else do nothing + */ + + + _initFailedLoginCount() { + return this._isFailedLoginCountSet().then(failedLoginCountIsSet => { + if (!failedLoginCountIsSet) { + return this._setFailedLoginCount(0); + } + }); + } + /** + * increment _failed_login_count by 1 + */ + + + _incrementFailedLoginCount() { + const query = { + username: this._user.username + }; + const updateFields = { + _failed_login_count: { + __op: 'Increment', + amount: 1 + } + }; + return this._config.database.update('_User', query, updateFields); + } + /** + * if the failed login count is greater than the threshold + * then sets lockout expiration to 'currenttime + accountPolicy.duration', i.e., account is locked out for the next 'accountPolicy.duration' minutes + * else do nothing + */ + + + _setLockoutExpiration() { + const query = { + username: this._user.username, + _failed_login_count: { + $gte: this._config.accountLockout.threshold + } + }; + const now = new Date(); + const updateFields = { + _account_lockout_expires_at: _node.default._encode(new Date(now.getTime() + this._config.accountLockout.duration * 60 * 1000)) + }; + return this._config.database.update('_User', query, updateFields).catch(err => { + if (err && err.code && err.message && err.code === 101 && err.message === 'Object not found.') { + return; // nothing to update so we are good + } else { + throw err; // unknown error + } + }); + } + /** + * if _account_lockout_expires_at > current_time and _failed_login_count > threshold + * reject with account locked error + * else + * resolve + */ + + + _notLocked() { + const query = { + username: this._user.username, + _account_lockout_expires_at: { + $gt: _node.default._encode(new Date()) + }, + _failed_login_count: { + $gte: this._config.accountLockout.threshold + } + }; + return this._config.database.find('_User', query).then(users => { + if (Array.isArray(users) && users.length > 0) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Your account is locked due to multiple failed login attempts. Please try again after ' + this._config.accountLockout.duration + ' minute(s)'); + } + }); + } + /** + * set and/or increment _failed_login_count + * if _failed_login_count > threshold + * set the _account_lockout_expires_at to current_time + accountPolicy.duration + * else + * do nothing + */ + + + _handleFailedLoginAttempt() { + return this._initFailedLoginCount().then(() => { + return this._incrementFailedLoginCount(); + }).then(() => { + return this._setLockoutExpiration(); + }); + } + /** + * handle login attempt if the Account Lockout Policy is enabled + */ + + + handleLoginAttempt(loginSuccessful) { + if (!this._config.accountLockout) { + return Promise.resolve(); + } + + return this._notLocked().then(() => { + if (loginSuccessful) { + return this._setFailedLoginCount(0); + } else { + return this._handleFailedLoginAttempt(); + } + }); + } + +} + +exports.AccountLockout = AccountLockout; +var _default = AccountLockout; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9BY2NvdW50TG9ja291dC5qcyJdLCJuYW1lcyI6WyJBY2NvdW50TG9ja291dCIsImNvbnN0cnVjdG9yIiwidXNlciIsImNvbmZpZyIsIl91c2VyIiwiX2NvbmZpZyIsIl9zZXRGYWlsZWRMb2dpbkNvdW50IiwidmFsdWUiLCJxdWVyeSIsInVzZXJuYW1lIiwidXBkYXRlRmllbGRzIiwiX2ZhaWxlZF9sb2dpbl9jb3VudCIsImRhdGFiYXNlIiwidXBkYXRlIiwiX2lzRmFpbGVkTG9naW5Db3VudFNldCIsIiRleGlzdHMiLCJmaW5kIiwidGhlbiIsInVzZXJzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiX2luaXRGYWlsZWRMb2dpbkNvdW50IiwiZmFpbGVkTG9naW5Db3VudElzU2V0IiwiX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQiLCJfX29wIiwiYW1vdW50IiwiX3NldExvY2tvdXRFeHBpcmF0aW9uIiwiJGd0ZSIsImFjY291bnRMb2Nrb3V0IiwidGhyZXNob2xkIiwibm93IiwiRGF0ZSIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIlBhcnNlIiwiX2VuY29kZSIsImdldFRpbWUiLCJkdXJhdGlvbiIsImNhdGNoIiwiZXJyIiwiY29kZSIsIm1lc3NhZ2UiLCJfbm90TG9ja2VkIiwiJGd0IiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiX2hhbmRsZUZhaWxlZExvZ2luQXR0ZW1wdCIsImhhbmRsZUxvZ2luQXR0ZW1wdCIsImxvZ2luU3VjY2Vzc2Z1bCIsIlByb21pc2UiLCJyZXNvbHZlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7Ozs7QUFEQTtBQUdPLE1BQU1BLGNBQU4sQ0FBcUI7QUFDMUJDLEVBQUFBLFdBQVcsQ0FBQ0MsSUFBRCxFQUFPQyxNQUFQLEVBQWU7QUFDeEIsU0FBS0MsS0FBTCxHQUFhRixJQUFiO0FBQ0EsU0FBS0csT0FBTCxHQUFlRixNQUFmO0FBQ0Q7QUFFRDs7Ozs7QUFHQUcsRUFBQUEsb0JB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QUFBQSxrQkFBa0IsQ0FBQ0MsZUFBRCxFQUFrQjtBQUNsQyxRQUFJLENBQUMsS0FBSzNDLE9BQUwsQ0FBYXdCLGNBQWxCLEVBQWtDO0FBQ2hDLGFBQU9vQixPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNEOztBQUNELFdBQU8sS0FBS1IsVUFBTCxHQUFrQnpCLElBQWxCLENBQXVCLE1BQU07QUFDbEMsVUFBSStCLGVBQUosRUFBcUI7QUFDbkIsZUFBTyxLQUFLMUMsb0JBQUwsQ0FBMEIsQ0FBMUIsQ0FBUDtBQUNELE9BRkQsTUFFTztBQUNMLGVBQU8sS0FBS3dDLHlCQUFMLEVBQVA7QUFDRDtBQUNGLEtBTk0sQ0FBUDtBQU9EOztBQWhLeUI7OztlQW1LYjlDLGMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGlzIGNsYXNzIGhhbmRsZXMgdGhlIEFjY291bnQgTG9ja291dCBQb2xpY3kgc2V0dGluZ3MuXG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5cbmV4cG9ydCBjbGFzcyBBY2NvdW50TG9ja291dCB7XG4gIGNvbnN0cnVjdG9yKHVzZXIsIGNvbmZpZykge1xuICAgIHRoaXMuX3VzZXIgPSB1c2VyO1xuICAgIHRoaXMuX2NvbmZpZyA9IGNvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBzZXQgX2ZhaWxlZF9sb2dpbl9jb3VudCB0byB2YWx1ZVxuICAgKi9cbiAgX3NldEZhaWxlZExvZ2luQ291bnQodmFsdWUpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVGaWVsZHMgPSB7XG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB2YWx1ZSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywgcXVlcnksIHVwZGF0ZUZpZWxkcyk7XG4gIH1cblxuICAvKipcbiAgICogY2hlY2sgaWYgdGhlIF9mYWlsZWRfbG9naW5fY291bnQgZmllbGQgaGFzIGJlZW4gc2V0XG4gICAqL1xuICBfaXNGYWlsZWRMb2dpbkNvdW50U2V0KCkge1xuICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgdXNlcm5hbWU6IHRoaXMuX3VzZXIudXNlcm5hbWUsXG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7ICRleGlzdHM6IHRydWUgfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS5maW5kKCdfVXNlcicsIHF1ZXJ5KS50aGVuKHVzZXJzID0+IHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHVzZXJzKSAmJiB1c2Vycy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIF9mYWlsZWRfbG9naW5fY291bnQgaXMgTk9UIHNldCB0aGVuIHNldCBpdCB0byAwXG4gICAqIGVsc2UgZG8gbm90aGluZ1xuICAgKi9cbiAgX2luaXRGYWlsZWRMb2dpbkNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9pc0ZhaWxlZExvZ2luQ291bnRTZXQoKS50aGVuKGZhaWxlZExvZ2luQ291bnRJc1NldCA9PiB7XG4gICAgICBpZiAoIWZhaWxlZExvZ2luQ291bnRJc1NldCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2V0RmFpbGVkTG9naW5Db3VudCgwKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBpbmNyZW1lbnQgX2ZhaWxlZF9sb2dpbl9jb3VudCBieSAxXG4gICAqL1xuICBfaW5jcmVtZW50RmFpbGVkTG9naW5Db3VudCgpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVGaWVsZHMgPSB7XG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7IF9fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IDEgfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywgcXVlcnksIHVwZGF0ZUZpZWxkcyk7XG4gIH1cblxuICAvKipcbiAgICogaWYgdGhlIGZhaWxlZCBsb2dpbiBjb3VudCBpcyBncmVhdGVyIHRoYW4gdGhlIHRocmVzaG9sZFxuICAgKiB0aGVuIHNldHMgbG9ja291dCBleHBpcmF0aW9uIHRvICdjdXJyZW50dGltZSArIGFjY291bnRQb2xpY3kuZHVyYXRpb24nLCBpLmUuLCBhY2NvdW50IGlzIGxvY2tlZCBvdXQgZm9yIHRoZSBuZXh0ICdhY2NvdW50UG9saWN5LmR1cmF0aW9uJyBtaW51dGVzXG4gICAqIGVsc2UgZG8gbm90aGluZ1xuICAgKi9cbiAgX3NldExvY2tvdXRFeHBpcmF0aW9uKCkge1xuICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgdXNlcm5hbWU6IHRoaXMuX3VzZXIudXNlcm5hbWUsXG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7ICRndGU6IHRoaXMuX2NvbmZpZy5hY2NvdW50TG9ja291dC50aHJlc2hvbGQgfSxcbiAgICB9O1xuXG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcblxuICAgIGNvbnN0IHVwZGF0ZUZpZWxkcyA9IHtcbiAgICAgIF9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdDogUGFyc2UuX2VuY29kZShcbiAgICAgICAgbmV3IERhdGUoXG4gICAgICAgICAgbm93LmdldFRpbWUoKSArIHRoaXMuX2NvbmZpZy5hY2NvdW50TG9ja291dC5kdXJhdGlvbiAqIDYwICogMTAwMFxuICAgICAgICApXG4gICAgICApLFxuICAgIH07XG5cbiAgICByZXR1cm4gdGhpcy5fY29uZmlnLmRhdGFiYXNlXG4gICAgICAudXBkYXRlKCdfVXNlcicsIHF1ZXJ5LCB1cGRhdGVGaWVsZHMpXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGVyciAmJlxuICAgICAgICAgIGVyci5jb2RlICYmXG4gICAgICAgICAgZXJyLm1lc3NhZ2UgJiZcbiAgICAgICAgICBlcnIuY29kZSA9PT0gMTAxICYmXG4gICAgICAgICAgZXJyLm1lc3NhZ2UgPT09ICdPYmplY3Qgbm90IGZvdW5kLidcbiAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuOyAvLyBub3RoaW5nIHRvIHVwZGF0ZSBzbyB3ZSBhcmUgZ29vZFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycjsgLy8gdW5rbm93biBlcnJvclxuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBpZiBfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQgPiBjdXJyZW50X3RpbWUgYW5kIF9mYWlsZWRfbG9naW5fY291bnQgPiB0aHJlc2hvbGRcbiAgICogICByZWplY3Qgd2l0aCBhY2NvdW50IGxvY2tlZCBlcnJvclxuICAgKiBlbHNlXG4gICAqICAgcmVzb2x2ZVxuICAgKi9cbiAgX25vdExvY2tlZCgpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgICAgX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0OiB7ICRndDogUGFyc2UuX2VuY29kZShuZXcgRGF0ZSgpKSB9LFxuICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogeyAkZ3RlOiB0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQudGhyZXNob2xkIH0sXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCBxdWVyeSkudGhlbih1c2VycyA9PiB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh1c2VycykgJiYgdXNlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAnWW91ciBhY2NvdW50IGlzIGxvY2tlZCBkdWUgdG8gbXVsdGlwbGUgZmFpbGVkIGxvZ2luIGF0dGVtcHRzLiBQbGVhc2UgdHJ5IGFnYWluIGFmdGVyICcgK1xuICAgICAgICAgICAgdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0LmR1cmF0aW9uICtcbiAgICAgICAgICAgICcgbWludXRlKHMpJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIHNldCBhbmQvb3IgaW5jcmVtZW50IF9mYWlsZWRfbG9naW5fY291bnRcbiAgICogaWYgX2ZhaWxlZF9sb2dpbl9jb3VudCA+IHRocmVzaG9sZFxuICAgKiAgIHNldCB0aGUgX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0IHRvIGN1cnJlbnRfdGltZSArIGFjY291bnRQb2xpY3kuZHVyYXRpb25cbiAgICogZWxzZVxuICAgKiAgIGRvIG5vdGhpbmdcbiAgICovXG4gIF9oYW5kbGVGYWlsZWRMb2dpbkF0dGVtcHQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2luaXRGYWlsZWRMb2dpbkNvdW50KClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQoKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXRMb2Nrb3V0RXhwaXJhdGlvbigpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogaGFuZGxlIGxvZ2luIGF0dGVtcHQgaWYgdGhlIEFjY291bnQgTG9ja291dCBQb2xpY3kgaXMgZW5hYmxlZFxuICAgKi9cbiAgaGFuZGxlTG9naW5BdHRlbXB0KGxvZ2luU3VjY2Vzc2Z1bCkge1xuICAgIGlmICghdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0KSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9ub3RMb2NrZWQoKS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChsb2dpblN1Y2Nlc3NmdWwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NldEZhaWxlZExvZ2luQ291bnQoMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5faGFuZGxlRmFpbGVkTG9naW5BdHRlbXB0KCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQWNjb3VudExvY2tvdXQ7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/AdapterLoader.js b/lib/Adapters/AdapterLoader.js new file mode 100644 index 0000000000..51cbe9e2a1 --- /dev/null +++ b/lib/Adapters/AdapterLoader.js @@ -0,0 +1,63 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.loadAdapter = loadAdapter; +exports.default = void 0; + +/** + * @module AdapterLoader + */ + +/** + * @static + * Attempt to load an adapter or fallback to the default. + * @param {Adapter} adapter an adapter + * @param {Adapter} defaultAdapter the default adapter to load + * @param {any} options options to pass to the contstructor + * @returns {Object} the loaded adapter + */ +function loadAdapter(adapter, defaultAdapter, options) { + if (!adapter) { + if (!defaultAdapter) { + return options; + } // Load from the default adapter when no adapter is set + + + return loadAdapter(defaultAdapter, undefined, options); + } else if (typeof adapter === 'function') { + try { + return adapter(options); + } catch (e) { + if (e.name === 'TypeError') { + var Adapter = adapter; + return new Adapter(options); + } else { + throw e; + } + } + } else if (typeof adapter === 'string') { + /* eslint-disable */ + adapter = require(adapter); // If it's define as a module, get the default + + if (adapter.default) { + adapter = adapter.default; + } + + return loadAdapter(adapter, undefined, options); + } else if (adapter.module) { + return loadAdapter(adapter.module, undefined, adapter.options); + } else if (adapter.class) { + return loadAdapter(adapter.class, undefined, adapter.options); + } else if (adapter.adapter) { + return loadAdapter(adapter.adapter, undefined, adapter.options); + } // return the adapter as provided + + + return adapter; +} + +var _default = loadAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9BZGFwdGVycy9BZGFwdGVyTG9hZGVyLmpzIl0sIm5hbWVzIjpbImxvYWRBZGFwdGVyIiwiYWRhcHRlciIsImRlZmF1bHRBZGFwdGVyIiwib3B0aW9ucyIsInVuZGVmaW5lZCIsImUiLCJuYW1lIiwiQWRhcHRlciIsInJlcXVpcmUiLCJkZWZhdWx0IiwibW9kdWxlIiwiY2xhc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7Ozs7QUFHQTs7Ozs7Ozs7QUFRTyxTQUFTQSxXQUFULENBQXdCQyxPQUF4QixFQUFpQ0MsY0FBakMsRUFBaURDLE9BQWpELEVBQTZEO0FBQ2xFLE1BQUksQ0FBQ0YsT0FBTCxFQUFjO0FBQ1osUUFBSSxDQUFDQyxjQUFMLEVBQXFCO0FBQ25CLGFBQU9DLE9BQVA7QUFDRCxLQUhXLENBSVo7OztBQUNBLFdBQU9ILFdBQVcsQ0FBQ0UsY0FBRCxFQUFpQkUsU0FBakIsRUFBNEJELE9BQTVCLENBQWxCO0FBQ0QsR0FORCxNQU1PLElBQUksT0FBT0YsT0FBUCxLQUFtQixVQUF2QixFQUFtQztBQUN4QyxRQUFJO0FBQ0YsYUFBT0EsT0FBTyxDQUFDRSxPQUFELENBQWQ7QUFDRCxLQUZELENBRUUsT0FBT0UsQ0FBUCxFQUFVO0FBQ1YsVUFBSUEsQ0FBQyxDQUFDQyxJQUFGLEtBQVcsV0FBZixFQUE0QjtBQUMxQixZQUFJQyxPQUFPLEdBQUdOLE9BQWQ7QUFDQSxlQUFPLElBQUlNLE9BQUosQ0FBWUosT0FBWixDQUFQO0FBQ0QsT0FIRCxNQUdPO0FBQ0wsY0FBTUUsQ0FBTjtBQUNEO0FBQ0Y7QUFDRixHQVhNLE1BV0EsSUFBSSxPQUFPSixPQUFQLEtBQW1CLFFBQXZCLEVBQWlDO0FBQ3RDO0FBQ0FBLElBQUFBLE9BQU8sR0FBR08sT0FBTyxDQUFDUCxPQUFELENBQWpCLENBRnNDLENBR3RDOztBQUNBLFFBQUlBLE9BQU8sQ0FBQ1EsT0FBWixFQUFxQjtBQUNuQlIsTUFBQUEsT0FBTyxHQUFHQSxPQUFPLENBQUNRLE9BQWxCO0FBQ0Q7O0FBQ0QsV0FBT1QsV0FBVyxDQUFDQyxPQUFELEVBQVVHLFNBQVYsRUFBcUJELE9BQXJCLENBQWxCO0FBQ0QsR0FSTSxNQVFBLElBQUlGLE9BQU8sQ0FBQ1MsTUFBWixFQUFvQjtBQUN6QixXQUFPVixXQUFXLENBQUNDLE9BQU8sQ0FBQ1MsTUFBVCxFQUFpQk4sU0FBakIsRUFBNEJILE9BQU8sQ0FBQ0UsT0FBcEMsQ0FBbEI7QUFDRCxHQUZNLE1BRUEsSUFBSUYsT0FBTyxDQUFDVSxLQUFaLEVBQW1CO0FBQ3hCLFdBQU9YLFdBQVcsQ0FBQ0MsT0FBTyxDQUFDVSxLQUFULEVBQWdCUCxTQUFoQixFQUEyQkgsT0FBTyxDQUFDRSxPQUFuQyxDQUFsQjtBQUNELEdBRk0sTUFFQSxJQUFJRixPQUFPLENBQUNBLE9BQVosRUFBcUI7QUFDMUIsV0FBT0QsV0FBVyxDQUFDQyxPQUFPLENBQUNBLE9BQVQsRUFBa0JHLFNBQWxCLEVBQTZCSCxPQUFPLENBQUNFLE9BQXJDLENBQWxCO0FBQ0QsR0FoQ2lFLENBaUNsRTs7O0FBQ0EsU0FBT0YsT0FBUDtBQUNEOztlQUVjRCxXIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbW9kdWxlIEFkYXB0ZXJMb2FkZXJcbiAqL1xuLyoqXG4gKiBAc3RhdGljXG4gKiBBdHRlbXB0IHRvIGxvYWQgYW4gYWRhcHRlciBvciBmYWxsYmFjayB0byB0aGUgZGVmYXVsdC5cbiAqIEBwYXJhbSB7QWRhcHRlcn0gYWRhcHRlciBhbiBhZGFwdGVyXG4gKiBAcGFyYW0ge0FkYXB0ZXJ9IGRlZmF1bHRBZGFwdGVyIHRoZSBkZWZhdWx0IGFkYXB0ZXIgdG8gbG9hZFxuICogQHBhcmFtIHthbnl9IG9wdGlvbnMgb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBjb250c3RydWN0b3JcbiAqIEByZXR1cm5zIHtPYmplY3R9IHRoZSBsb2FkZWQgYWRhcHRlclxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9hZEFkYXB0ZXI8VD4oYWRhcHRlciwgZGVmYXVsdEFkYXB0ZXIsIG9wdGlvbnMpOiBUIHtcbiAgaWYgKCFhZGFwdGVyKSB7XG4gICAgaWYgKCFkZWZhdWx0QWRhcHRlcikge1xuICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgfVxuICAgIC8vIExvYWQgZnJvbSB0aGUgZGVmYXVsdCBhZGFwdGVyIHdoZW4gbm8gYWRhcHRlciBpcyBzZXRcbiAgICByZXR1cm4gbG9hZEFkYXB0ZXIoZGVmYXVsdEFkYXB0ZXIsIHVuZGVmaW5lZCwgb3B0aW9ucyk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGFkYXB0ZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGFkYXB0ZXIob3B0aW9ucyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUubmFtZSA9PT0gJ1R5cGVFcnJvcicpIHtcbiAgICAgICAgdmFyIEFkYXB0ZXIgPSBhZGFwdGVyO1xuICAgICAgICByZXR1cm4gbmV3IEFkYXB0ZXIob3B0aW9ucyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlb2YgYWRhcHRlciA9PT0gJ3N0cmluZycpIHtcbiAgICAvKiBlc2xpbnQtZGlzYWJsZSAqL1xuICAgIGFkYXB0ZXIgPSByZXF1aXJlKGFkYXB0ZXIpO1xuICAgIC8vIElmIGl0J3MgZGVmaW5lIGFzIGEgbW9kdWxlLCBnZXQgdGhlIGRlZmF1bHRcbiAgICBpZiAoYWRhcHRlci5kZWZhdWx0KSB7XG4gICAgICBhZGFwdGVyID0gYWRhcHRlci5kZWZhdWx0O1xuICAgIH1cbiAgICByZXR1cm4gbG9hZEFkYXB0ZXIoYWRhcHRlciwgdW5kZWZpbmVkLCBvcHRpb25zKTtcbiAgfSBlbHNlIGlmIChhZGFwdGVyLm1vZHVsZSkge1xuICAgIHJldHVybiBsb2FkQWRhcHRlcihhZGFwdGVyLm1vZHVsZSwgdW5kZWZpbmVkLCBhZGFwdGVyLm9wdGlvbnMpO1xuICB9IGVsc2UgaWYgKGFkYXB0ZXIuY2xhc3MpIHtcbiAgICByZXR1cm4gbG9hZEFkYXB0ZXIoYWRhcHRlci5jbGFzcywgdW5kZWZpbmVkLCBhZGFwdGVyLm9wdGlvbnMpO1xuICB9IGVsc2UgaWYgKGFkYXB0ZXIuYWRhcHRlcikge1xuICAgIHJldHVybiBsb2FkQWRhcHRlcihhZGFwdGVyLmFkYXB0ZXIsIHVuZGVmaW5lZCwgYWRhcHRlci5vcHRpb25zKTtcbiAgfVxuICAvLyByZXR1cm4gdGhlIGFkYXB0ZXIgYXMgcHJvdmlkZWRcbiAgcmV0dXJuIGFkYXB0ZXI7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGxvYWRBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Analytics/AnalyticsAdapter.js b/lib/Adapters/Analytics/AnalyticsAdapter.js new file mode 100644 index 0000000000..109ac4b3f6 --- /dev/null +++ b/lib/Adapters/Analytics/AnalyticsAdapter.js @@ -0,0 +1,41 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AnalyticsAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ + +/** + * @module Adapters + */ + +/** + * @interface AnalyticsAdapter + */ +class AnalyticsAdapter { + /** + @param {any} parameters: the analytics request body, analytics info will be in the dimensions property + @param {Request} req: the original http request + */ + appOpened(parameters, req) { + return Promise.resolve({}); + } + /** + @param {String} eventName: the name of the custom eventName + @param {any} parameters: the analytics request body, analytics info will be in the dimensions property + @param {Request} req: the original http request + */ + + + trackEvent(eventName, parameters, req) { + return Promise.resolve({}); + } + +} + +exports.AnalyticsAdapter = AnalyticsAdapter; +var _default = AnalyticsAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BbmFseXRpY3MvQW5hbHl0aWNzQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJBbmFseXRpY3NBZGFwdGVyIiwiYXBwT3BlbmVkIiwicGFyYW1ldGVycyIsInJlcSIsIlByb21pc2UiLCJyZXNvbHZlIiwidHJhY2tFdmVudCIsImV2ZW50TmFtZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBR0E7OztBQUdPLE1BQU1BLGdCQUFOLENBQXVCO0FBQzVCOzs7O0FBSUFDLEVBQUFBLFNBQVMsQ0FBQ0MsVUFBRCxFQUFhQyxHQUFiLEVBQWtCO0FBQ3pCLFdBQU9DLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQixFQUFoQixDQUFQO0FBQ0Q7QUFFRDs7Ozs7OztBQUtBQyxFQUFBQSxVQUFVLENBQUNDLFNBQUQsRUFBWUwsVUFBWixFQUF3QkMsR0FBeEIsRUFBNkI7QUFDckMsV0FBT0MsT0FBTyxDQUFDQyxPQUFSLENBQWdCLEVBQWhCLENBQVA7QUFDRDs7QUFoQjJCOzs7ZUFtQmZMLGdCIiwic291cmNlc0NvbnRlbnQiOlsiLyplc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIqL1xuLyoqXG4gKiBAbW9kdWxlIEFkYXB0ZXJzXG4gKi9cbi8qKlxuICogQGludGVyZmFjZSBBbmFseXRpY3NBZGFwdGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBBbmFseXRpY3NBZGFwdGVyIHtcbiAgLyoqXG4gIEBwYXJhbSB7YW55fSBwYXJhbWV0ZXJzOiB0aGUgYW5hbHl0aWNzIHJlcXVlc3QgYm9keSwgYW5hbHl0aWNzIGluZm8gd2lsbCBiZSBpbiB0aGUgZGltZW5zaW9ucyBwcm9wZXJ0eVxuICBAcGFyYW0ge1JlcXVlc3R9IHJlcTogdGhlIG9yaWdpbmFsIGh0dHAgcmVxdWVzdFxuICAgKi9cbiAgYXBwT3BlbmVkKHBhcmFtZXRlcnMsIHJlcSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICB9XG5cbiAgLyoqXG4gIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWU6IHRoZSBuYW1lIG9mIHRoZSBjdXN0b20gZXZlbnROYW1lXG4gIEBwYXJhbSB7YW55fSBwYXJhbWV0ZXJzOiB0aGUgYW5hbHl0aWNzIHJlcXVlc3QgYm9keSwgYW5hbHl0aWNzIGluZm8gd2lsbCBiZSBpbiB0aGUgZGltZW5zaW9ucyBwcm9wZXJ0eVxuICBAcGFyYW0ge1JlcXVlc3R9IHJlcTogdGhlIG9yaWdpbmFsIGh0dHAgcmVxdWVzdFxuICAgKi9cbiAgdHJhY2tFdmVudChldmVudE5hbWUsIHBhcmFtZXRlcnMsIHJlcSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEFuYWx5dGljc0FkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/AuthAdapter.js b/lib/Adapters/Auth/AuthAdapter.js new file mode 100644 index 0000000000..2b1f9ba12b --- /dev/null +++ b/lib/Adapters/Auth/AuthAdapter.js @@ -0,0 +1,34 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AuthAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ +class AuthAdapter { + /* + @param appIds: the specified app ids in the configuration + @param authData: the client provided authData + @param options: additional options + @returns a promise that resolves if the applicationId is valid + */ + validateAppId(appIds, authData, options) { + return Promise.resolve({}); + } + /* + @param authData: the client provided authData + @param options: additional options + */ + + + validateAuthData(authData, options) { + return Promise.resolve({}); + } + +} + +exports.AuthAdapter = AuthAdapter; +var _default = AuthAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL0F1dGhBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIkF1dGhBZGFwdGVyIiwidmFsaWRhdGVBcHBJZCIsImFwcElkcyIsImF1dGhEYXRhIiwib3B0aW9ucyIsIlByb21pc2UiLCJyZXNvbHZlIiwidmFsaWRhdGVBdXRoRGF0YSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBO0FBQ08sTUFBTUEsV0FBTixDQUFrQjtBQUN2Qjs7Ozs7O0FBTUFDLEVBQUFBLGFBQWEsQ0FBQ0MsTUFBRCxFQUFTQyxRQUFULEVBQW1CQyxPQUFuQixFQUE0QjtBQUN2QyxXQUFPQyxPQUFPLENBQUNDLE9BQVIsQ0FBZ0IsRUFBaEIsQ0FBUDtBQUNEO0FBRUQ7Ozs7OztBQUlBQyxFQUFBQSxnQkFBZ0IsQ0FBQ0osUUFBRCxFQUFXQyxPQUFYLEVBQW9CO0FBQ2xDLFdBQU9DLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQixFQUFoQixDQUFQO0FBQ0Q7O0FBakJzQjs7O2VBb0JWTixXIiwic291cmNlc0NvbnRlbnQiOlsiLyplc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIqL1xuZXhwb3J0IGNsYXNzIEF1dGhBZGFwdGVyIHtcbiAgLypcbiAgQHBhcmFtIGFwcElkczogdGhlIHNwZWNpZmllZCBhcHAgaWRzIGluIHRoZSBjb25maWd1cmF0aW9uXG4gIEBwYXJhbSBhdXRoRGF0YTogdGhlIGNsaWVudCBwcm92aWRlZCBhdXRoRGF0YVxuICBAcGFyYW0gb3B0aW9uczogYWRkaXRpb25hbCBvcHRpb25zXG4gIEByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGlmIHRoZSBhcHBsaWNhdGlvbklkIGlzIHZhbGlkXG4gICAqL1xuICB2YWxpZGF0ZUFwcElkKGFwcElkcywgYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgfVxuXG4gIC8qXG4gIEBwYXJhbSBhdXRoRGF0YTogdGhlIGNsaWVudCBwcm92aWRlZCBhdXRoRGF0YVxuICBAcGFyYW0gb3B0aW9uczogYWRkaXRpb25hbCBvcHRpb25zXG4gICAqL1xuICB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQXV0aEFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/OAuth1Client.js b/lib/Adapters/Auth/OAuth1Client.js new file mode 100644 index 0000000000..f9689a6e32 --- /dev/null +++ b/lib/Adapters/Auth/OAuth1Client.js @@ -0,0 +1,227 @@ +"use strict"; + +var https = require('https'), + crypto = require('crypto'); + +var Parse = require('parse/node').Parse; + +var OAuth = function (options) { + if (!options) { + throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'No options passed to OAuth'); + } + + this.consumer_key = options.consumer_key; + this.consumer_secret = options.consumer_secret; + this.auth_token = options.auth_token; + this.auth_token_secret = options.auth_token_secret; + this.host = options.host; + this.oauth_params = options.oauth_params || {}; +}; + +OAuth.prototype.send = function (method, path, params, body) { + var request = this.buildRequest(method, path, params, body); // Encode the body properly, the current Parse Implementation don't do it properly + + return new Promise(function (resolve, reject) { + var httpRequest = https.request(request, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + data = JSON.parse(data); + resolve(data); + }); + }).on('error', function () { + reject('Failed to make an OAuth request'); + }); + + if (request.body) { + httpRequest.write(request.body); + } + + httpRequest.end(); + }); +}; + +OAuth.prototype.buildRequest = function (method, path, params, body) { + if (path.indexOf('/') != 0) { + path = '/' + path; + } + + if (params && Object.keys(params).length > 0) { + path += '?' + OAuth.buildParameterString(params); + } + + var request = { + host: this.host, + path: path, + method: method.toUpperCase() + }; + var oauth_params = this.oauth_params || {}; + oauth_params.oauth_consumer_key = this.consumer_key; + + if (this.auth_token) { + oauth_params['oauth_token'] = this.auth_token; + } + + request = OAuth.signRequest(request, oauth_params, this.consumer_secret, this.auth_token_secret); + + if (body && Object.keys(body).length > 0) { + request.body = OAuth.buildParameterString(body); + } + + return request; +}; + +OAuth.prototype.get = function (path, params) { + return this.send('GET', path, params); +}; + +OAuth.prototype.post = function (path, params, body) { + return this.send('POST', path, params, body); +}; +/* + Proper string %escape encoding +*/ + + +OAuth.encode = function (str) { + // discuss at: http://phpjs.org/functions/rawurlencode/ + // original by: Brett Zamir (http://brett-zamir.me) + // input by: travc + // input by: Brett Zamir (http://brett-zamir.me) + // input by: Michael Grier + // input by: Ratheous + // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // bugfixed by: Brett Zamir (http://brett-zamir.me) + // bugfixed by: Joris + // reimplemented by: Brett Zamir (http://brett-zamir.me) + // reimplemented by: Brett Zamir (http://brett-zamir.me) + // note: This reflects PHP 5.3/6.0+ behavior + // note: Please be aware that this function expects to encode into UTF-8 encoded strings, as found on + // note: pages served as UTF-8 + // example 1: rawurlencode('Kevin van Zonneveld!'); + // returns 1: 'Kevin%20van%20Zonneveld%21' + // example 2: rawurlencode('http://kevin.vanzonneveld.net/'); + // returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F' + // example 3: rawurlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a'); + // returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a' + str = (str + '').toString(); // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current + // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following. + + return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A'); +}; + +OAuth.signatureMethod = 'HMAC-SHA1'; +OAuth.version = '1.0'; +/* + Generate a nonce +*/ + +OAuth.nonce = function () { + var text = ''; + var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + for (var i = 0; i < 30; i++) text += possible.charAt(Math.floor(Math.random() * possible.length)); + + return text; +}; + +OAuth.buildParameterString = function (obj) { + // Sort keys and encode values + if (obj) { + var keys = Object.keys(obj).sort(); // Map key=value, join them by & + + return keys.map(function (key) { + return key + '=' + OAuth.encode(obj[key]); + }).join('&'); + } + + return ''; +}; +/* + Build the signature string from the object +*/ + + +OAuth.buildSignatureString = function (method, url, parameters) { + return [method.toUpperCase(), OAuth.encode(url), OAuth.encode(parameters)].join('&'); +}; +/* + Retuns encoded HMAC-SHA1 from key and text +*/ + + +OAuth.signature = function (text, key) { + crypto = require('crypto'); + return OAuth.encode(crypto.createHmac('sha1', key).update(text).digest('base64')); +}; + +OAuth.signRequest = function (request, oauth_parameters, consumer_secret, auth_token_secret) { + oauth_parameters = oauth_parameters || {}; // Set default values + + if (!oauth_parameters.oauth_nonce) { + oauth_parameters.oauth_nonce = OAuth.nonce(); + } + + if (!oauth_parameters.oauth_timestamp) { + oauth_parameters.oauth_timestamp = Math.floor(new Date().getTime() / 1000); + } + + if (!oauth_parameters.oauth_signature_method) { + oauth_parameters.oauth_signature_method = OAuth.signatureMethod; + } + + if (!oauth_parameters.oauth_version) { + oauth_parameters.oauth_version = OAuth.version; + } + + if (!auth_token_secret) { + auth_token_secret = ''; + } // Force GET method if unset + + + if (!request.method) { + request.method = 'GET'; + } // Collect all the parameters in one signatureParameters object + + + var signatureParams = {}; + var parametersToMerge = [request.params, request.body, oauth_parameters]; + + for (var i in parametersToMerge) { + var parameters = parametersToMerge[i]; + + for (var k in parameters) { + signatureParams[k] = parameters[k]; + } + } // Create a string based on the parameters + + + var parameterString = OAuth.buildParameterString(signatureParams); // Build the signature string + + var url = 'https://' + request.host + '' + request.path; + var signatureString = OAuth.buildSignatureString(request.method, url, parameterString); // Hash the signature string + + var signatureKey = [OAuth.encode(consumer_secret), OAuth.encode(auth_token_secret)].join('&'); + var signature = OAuth.signature(signatureString, signatureKey); // Set the signature in the params + + oauth_parameters.oauth_signature = signature; + + if (!request.headers) { + request.headers = {}; + } // Set the authorization header + + + var authHeader = Object.keys(oauth_parameters).sort().map(function (key) { + var value = oauth_parameters[key]; + return key + '="' + value + '"'; + }).join(', '); + request.headers.Authorization = 'OAuth ' + authHeader; // Set the content type header + + request.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + return request; +}; + +module.exports = OAuth; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL09BdXRoMUNsaWVudC5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJjcnlwdG8iLCJQYXJzZSIsIk9BdXRoIiwib3B0aW9ucyIsIkVycm9yIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiY29uc3VtZXJfa2V5IiwiY29uc3VtZXJfc2VjcmV0IiwiYXV0aF90b2tlbiIsImF1dGhfdG9rZW5fc2VjcmV0IiwiaG9zdCIsIm9hdXRoX3BhcmFtcyIsInByb3RvdHlwZSIsInNlbmQiLCJtZXRob2QiLCJwYXRoIiwicGFyYW1zIiwiYm9keSIsInJlcXVlc3QiLCJidWlsZFJlcXVlc3QiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsImh0dHBSZXF1ZXN0IiwicmVzIiwiZGF0YSIsIm9uIiwiY2h1bmsiLCJKU09OIiwicGFyc2UiLCJ3cml0ZSIsImVuZCIsImluZGV4T2YiLCJPYmplY3QiLCJrZXlzIiwibGVuZ3RoIiwiYnVpbGRQYXJhbWV0ZXJTdHJpbmciLCJ0b1VwcGVyQ2FzZSIsIm9hdXRoX2NvbnN1bWVyX2tleSIsInNpZ25SZXF1ZXN0IiwiZ2V0IiwicG9zdCIsImVuY29kZSIsInN0ciIsInRvU3RyaW5nIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwicmVwbGFjZSIsInNpZ25hdHVyZU1ldGhvZCIsInZlcnNpb24iLCJub25jZSIsInRleHQiLCJwb3NzaWJsZSIsImkiLCJjaGFyQXQiLCJNYXRoIiwiZmxvb3IiLCJyYW5kb20iLCJvYmoiLCJzb3J0IiwibWFwIiwia2V5Iiwiam9pbiIsImJ1aWxkU2lnbmF0dXJlU3RyaW5nIiwidXJsIiwicGFyYW1ldGVycyIsInNpZ25hdHVyZSIsImNyZWF0ZUhtYWMiLCJ1cGRhdGUiLCJkaWdlc3QiLCJvYXV0aF9wYXJhbWV0ZXJzIiwib2F1dGhfbm9uY2UiLCJvYXV0aF90aW1lc3RhbXAiLCJEYXRlIiwiZ2V0VGltZSIsIm9hdXRoX3NpZ25hdHVyZV9tZXRob2QiLCJvYXV0aF92ZXJzaW9uIiwic2lnbmF0dXJlUGFyYW1zIiwicGFyYW1ldGVyc1RvTWVyZ2UiLCJrIiwicGFyYW1ldGVyU3RyaW5nIiwic2lnbmF0dXJlU3RyaW5nIiwic2lnbmF0dXJlS2V5Iiwib2F1dGhfc2lnbmF0dXJlIiwiaGVhZGVycyIsImF1dGhIZWFkZXIiLCJ2YWx1ZSIsIkF1dGhvcml6YXRpb24iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLElBQUlBLEtBQUssR0FBR0MsT0FBTyxDQUFDLE9BQUQsQ0FBbkI7QUFBQSxJQUNFQyxNQUFNLEdBQUdELE9BQU8sQ0FBQyxRQUFELENBRGxCOztBQUVBLElBQUlFLEtBQUssR0FBR0YsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkUsS0FBbEM7O0FBRUEsSUFBSUMsS0FBSyxHQUFHLFVBQVNDLE9BQVQsRUFBa0I7QUFDNUIsTUFBSSxDQUFDQSxPQUFMLEVBQWM7QUFDWixVQUFNLElBQUlGLEtBQUssQ0FBQ0csS0FBVixDQUNKSCxLQUFLLENBQUNHLEtBQU4sQ0FBWUMscUJBRFIsRUFFSiw0QkFGSSxDQUFOO0FBSUQ7O0FBQ0QsT0FBS0MsWUFBTCxHQUFvQkgsT0FBTyxDQUFDRyxZQUE1QjtBQUNBLE9BQUtDLGVBQUwsR0FBdUJKLE9BQU8sQ0FBQ0ksZUFBL0I7QUFDQSxPQUFLQyxVQUFMLEdBQWtCTCxPQUFPLENBQUNLLFVBQTFCO0FBQ0EsT0FBS0MsaUJBQUwsR0FBeUJOLE9BQU8sQ0FBQ00saUJBQWpDO0FBQ0EsT0FBS0MsSUFBTCxHQUFZUCxPQUFPLENBQUNPLElBQXBCO0FBQ0EsT0FBS0MsWUFBTCxHQUFvQlIsT0FBTyxDQUFDUSxZQUFSLElBQXdCLEVBQTVDO0FBQ0QsQ0FiRDs7QUFlQVQsS0FBSyxDQUFDVSxTQUFOLENBQWdCQyxJQUFoQixHQUF1QixVQUFTQyxNQUFULEVBQWlCQyxJQUFqQixFQUF1QkMsTUFBdkIsRUFBK0JDLElBQS9CLEVBQXFDO0FBQzFELE1BQUlDLE9BQU8sR0FBRyxLQUFLQyxZQUFM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Q2lFLE9BQVIsR0FBa0IsRUFBbEI7QUFDRCxHQTFERCxDQTREQTs7O0FBQ0EsTUFBSUMsVUFBVSxHQUFHbkQsTUFBTSxDQUFDQyxJQUFQLENBQVltQyxnQkFBWixFQUNkWCxJQURjLEdBRWRDLEdBRmMsQ0FFVixVQUFTQyxHQUFULEVBQWM7QUFDakIsUUFBSXlCLEtBQUssR0FBR2hCLGdCQUFnQixDQUFDVCxHQUFELENBQTVCO0FBQ0EsV0FBT0EsR0FBRyxHQUFHLElBQU4sR0FBYXlCLEtBQWIsR0FBcUIsR0FBNUI7QUFDRCxHQUxjLEVBTWR4QixJQU5jLENBTVQsSUFOUyxDQUFqQjtBQVFBM0MsRUFBQUEsT0FBTyxDQUFDaUUsT0FBUixDQUFnQkcsYUFBaEIsR0FBZ0MsV0FBV0YsVUFBM0MsQ0FyRUEsQ0F1RUE7O0FBQ0FsRSxFQUFBQSxPQUFPLENBQUNpRSxPQUFSLENBQWdCLGNBQWhCLElBQWtDLG1DQUFsQztBQUNBLFNBQU9qRSxPQUFQO0FBQ0QsQ0EvRUQ7O0FBaUZBcUUsTUFBTSxDQUFDQyxPQUFQLEdBQWlCdEYsS0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpLFxuICBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxudmFyIE9BdXRoID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICBpZiAoIW9wdGlvbnMpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAnTm8gb3B0aW9ucyBwYXNzZWQgdG8gT0F1dGgnXG4gICAgKTtcbiAgfVxuICB0aGlzLmNvbnN1bWVyX2tleSA9IG9wdGlvbnMuY29uc3VtZXJfa2V5O1xuICB0aGlzLmNvbnN1bWVyX3NlY3JldCA9IG9wdGlvbnMuY29uc3VtZXJfc2VjcmV0O1xuICB0aGlzLmF1dGhfdG9rZW4gPSBvcHRpb25zLmF1dGhfdG9rZW47XG4gIHRoaXMuYXV0aF90b2tlbl9zZWNyZXQgPSBvcHRpb25zLmF1dGhfdG9rZW5fc2VjcmV0O1xuICB0aGlzLmhvc3QgPSBvcHRpb25zLmhvc3Q7XG4gIHRoaXMub2F1dGhfcGFyYW1zID0gb3B0aW9ucy5vYXV0aF9wYXJhbXMgfHwge307XG59O1xuXG5PQXV0aC5wcm90b3R5cGUuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGF0aCwgcGFyYW1zLCBib2R5KSB7XG4gIHZhciByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QobWV0aG9kLCBwYXRoLCBwYXJhbXMsIGJvZHkpO1xuICAvLyBFbmNvZGUgdGhlIGJvZHkgcHJvcGVybHksIHRoZSBjdXJyZW50IFBhcnNlIEltcGxlbWVudGF0aW9uIGRvbid0IGRvIGl0IHByb3Blcmx5XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgaHR0cFJlcXVlc3QgPSBodHRwc1xuICAgICAgLnJlcXVlc3QocmVxdWVzdCwgZnVuY3Rpb24ocmVzKSB7XG4gICAgICAgIHZhciBkYXRhID0gJyc7XG4gICAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uKGNodW5rKSB7XG4gICAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgICAgfSk7XG4gICAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICByZWplY3QoJ0ZhaWxlZCB0byBtYWtlIGFuIE9BdXRoIHJlcXVlc3QnKTtcbiAgICAgIH0pO1xuICAgIGlmIChyZXF1ZXN0LmJvZHkpIHtcbiAgICAgIGh0dHBSZXF1ZXN0LndyaXRlKHJlcXVlc3QuYm9keSk7XG4gICAgfVxuICAgIGh0dHBSZXF1ZXN0LmVuZCgpO1xuICB9KTtcbn07XG5cbk9BdXRoLnByb3RvdHlwZS5idWlsZFJlcXVlc3QgPSBmdW5jdGlvbihtZXRob2QsIHBhdGgsIHBhcmFtcywgYm9keSkge1xuICBpZiAocGF0aC5pbmRleE9mKCcvJykgIT0gMCkge1xuICAgIHBhdGggPSAnLycgKyBwYXRoO1xuICB9XG4gIGlmIChwYXJhbXMgJiYgT2JqZWN0LmtleXMocGFyYW1zKS5sZW5ndGggPiAwKSB7XG4gICAgcGF0aCArPSAnPycgKyBPQXV0aC5idWlsZFBhcmFtZXRlclN0cmluZyhwYXJhbXMpO1xuICB9XG5cbiAgdmFyIHJlcXVlc3QgPSB7XG4gICAgaG9zdDogdGhpcy5ob3N0LFxuICAgIHBhdGg6IHBhdGgsXG4gICAgbWV0aG9kOiBtZXRob2QudG9VcHBlckNhc2UoKSxcbiAgfTtcblxuICB2YXIgb2F1dGhfcGFyYW1zID0gdGhpcy5vYXV0aF9wYXJhbXMgfHwge307XG4gIG9hdXRoX3BhcmFtcy5vYXV0aF9jb25zdW1lcl9rZXkgPSB0aGlzLmNvbnN1bWVyX2tleTtcbiAgaWYgKHRoaXMuYXV0aF90b2tlbikge1xuICAgIG9hdXRoX3BhcmFtc1snb2F1dGhfdG9rZW4nXSA9IHRoaXMuYXV0aF90b2tlbjtcbiAgfVxuXG4gIHJlcXVlc3QgPSBPQXV0aC5zaWduUmVxdWVzdChcbiAgICByZXF1ZXN0LFxuICAgIG9hdXRoX3BhcmFtcyxcbiAgICB0aGlzLmNvbnN1bWVyX3NlY3JldCxcbiAgICB0aGlzLmF1dGhfdG9rZW5fc2VjcmV0XG4gICk7XG5cbiAgaWYgKGJvZHkgJiYgT2JqZWN0LmtleXMoYm9keSkubGVuZ3RoID4gMCkge1xuICAgIHJlcXVlc3QuYm9keSA9IE9BdXRoLmJ1aWxkUGFyYW1ldGVyU3RyaW5nKGJvZHkpO1xuICB9XG4gIHJldHVybiByZXF1ZXN0O1xufTtcblxuT0F1dGgucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uKHBhdGgsIHBhcmFtcykge1xuICByZXR1cm4gdGhpcy5zZW5kKCdHRVQnLCBwYXRoLCBwYXJhbXMpO1xufTtcblxuT0F1dGgucHJvdG90eXBlLnBvc3QgPSBmdW5jdGlvbihwYXRoLCBwYXJhbXMsIGJvZHkpIHtcbiAgcmV0dXJuIHRoaXMuc2VuZCgnUE9TVCcsIHBhdGgsIHBhcmFtcywgYm9keSk7XG59O1xuXG4vKlxuXHRQcm9wZXIgc3RyaW5nICVlc2NhcGUgZW5jb2RpbmdcbiovXG5PQXV0aC5lbmNvZGUgPSBmdW5jdGlvbihzdHIpIHtcbiAgLy8gICAgICAgZGlzY3VzcyBhdDogaHR0cDovL3BocGpzLm9yZy9mdW5jdGlvbnMvcmF3dXJsZW5jb2RlL1xuICAvLyAgICAgIG9yaWdpbmFsIGJ5OiBCcmV0dCBaYW1pciAoaHR0cDovL2JyZXR0LXphbWlyLm1lKVxuICAvLyAgICAgICAgIGlucHV0IGJ5OiB0cmF2Y1xuICAvLyAgICAgICAgIGlucHV0IGJ5OiBCcmV0dCBaYW1pciAoaHR0cDovL2JyZXR0LXphbWlyLm1lKVxuICAvLyAgICAgICAgIGlucHV0IGJ5OiBNaWNoYWVsIEdyaWVyXG4gIC8vICAgICAgICAgaW5wdXQgYnk6IFJhdGhlb3VzXG4gIC8vICAgICAgYnVnZml4ZWQgYnk6IEtldmluIHZhbiBab25uZXZlbGQgKGh0dHA6Ly9rZXZpbi52YW56b25uZXZlbGQubmV0KVxuICAvLyAgICAgIGJ1Z2ZpeGVkIGJ5OiBCcmV0dCBaYW1pciAoaHR0cDovL2JyZXR0LXphbWlyLm1lKVxuICAvLyAgICAgIGJ1Z2ZpeGVkIGJ5OiBKb3Jpc1xuICAvLyByZWltcGxlbWVudGVkIGJ5OiBCcmV0dCBaYW1pciAoaHR0cDovL2JyZXR0LXphbWlyLm1lKVxuICAvLyByZWltcGxlbWVudGVkIGJ5OiBCcmV0dCBaYW1pciAoaHR0cDovL2JyZXR0LXphbWlyLm1lKVxuICAvLyAgICAgICAgICAgICBub3RlOiBUaGlzIHJlZmxlY3RzIFBIUCA1LjMvNi4wKyBiZWhhdmlvclxuICAvLyAgICAgICAgICAgICBub3RlOiBQbGVhc2UgYmUgYXdhcmUgdGhhdCB0aGlzIGZ1bmN0aW9uIGV4cGVjdHMgdG8gZW5jb2RlIGludG8gVVRGLTggZW5jb2RlZCBzdHJpbmdzLCBhcyBmb3VuZCBvblxuICAvLyAgICAgICAgICAgICBub3RlOiBwYWdlcyBzZXJ2ZWQgYXMgVVRGLThcbiAgLy8gICAgICAgIGV4YW1wbGUgMTogcmF3dXJsZW5jb2RlKCdLZXZpbiB2YW4gWm9ubmV2ZWxkIScpO1xuICAvLyAgICAgICAgcmV0dXJucyAxOiAnS2V2aW4lMjB2YW4lMjBab25uZXZlbGQlMjEnXG4gIC8vICAgICAgICBleGFtcGxlIDI6IHJhd3VybGVuY29kZSgnaHR0cDovL2tldmluLnZhbnpvbm5ldmVsZC5uZXQvJyk7XG4gIC8vICAgICAgICByZXR1cm5zIDI6ICdodHRwJTNBJTJGJTJGa2V2aW4udmFuem9ubmV2ZWxkLm5ldCUyRidcbiAgLy8gICAgICAgIGV4YW1wbGUgMzogcmF3dXJsZW5jb2RlKCdodHRwOi8vd3d3Lmdvb2dsZS5ubC9zZWFyY2g/cT1waHAuanMmaWU9dXRmLTgmb2U9dXRmLTgmYXE9dCZybHM9Y29tLnVidW50dTplbi1VUzp1bm9mZmljaWFsJmNsaWVudD1maXJlZm94LWEnKTtcbiAgLy8gICAgICAgIHJldHVybnMgMzogJ2h0dHAlM0ElMkYlMkZ3d3cuZ29vZ2xlLm5sJTJGc2VhcmNoJTNGcSUzRHBocC5qcyUyNmllJTNEdXRmLTglMjZvZSUzRHV0Zi04JTI2YXElM0R0JTI2cmxzJTNEY29tLnVidW50dSUzQWVuLVVTJTNBdW5vZmZpY2lhbCUyNmNsaWVudCUzRGZpcmVmb3gtYSdcblxuICBzdHIgPSAoc3RyICsgJycpLnRvU3RyaW5nKCk7XG5cbiAgLy8gVGlsZGUgc2hvdWxkIGJlIGFsbG93ZWQgdW5lc2NhcGVkIGluIGZ1dHVyZSB2ZXJzaW9ucyBvZiBQSFAgKGFzIHJlZmxlY3RlZCBiZWxvdyksIGJ1dCBpZiB5b3Ugd2FudCB0byByZWZsZWN0IGN1cnJlbnRcbiAgLy8gUEhQIGJlaGF2aW9yLCB5b3Ugd291bGQgbmVlZCB0byBhZGQgXCIucmVwbGFjZSgvfi9nLCAnJTdFJyk7XCIgdG8gdGhlIGZvbGxvd2luZy5cbiAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChzdHIpXG4gICAgLnJlcGxhY2UoLyEvZywgJyUyMScpXG4gICAgLnJlcGxhY2UoLycvZywgJyUyNycpXG4gICAgLnJlcGxhY2UoL1xcKC9nLCAnJTI4JylcbiAgICAucmVwbGFjZSgvXFwpL2csICclMjknKVxuICAgIC5yZXBsYWNlKC9cXCovZywgJyUyQScpO1xufTtcblxuT0F1dGguc2lnbmF0dXJlTWV0aG9kID0gJ0hNQUMtU0hBMSc7XG5PQXV0aC52ZXJzaW9uID0gJzEuMCc7XG5cbi8qXG5cdEdlbmVyYXRlIGEgbm9uY2VcbiovXG5PQXV0aC5ub25jZSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgdGV4dCA9ICcnO1xuICB2YXIgcG9zc2libGUgPVxuICAgICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSc7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAzMDsgaSsrKVxuICAgIHRleHQgKz0gcG9zc2libGUuY2hhckF0KE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHBvc3NpYmxlLmxlbmd0aCkpO1xuXG4gIHJldHVybiB0ZXh0O1xufTtcblxuT0F1dGguYnVpbGRQYXJhbWV0ZXJTdHJpbmcgPSBmdW5jdGlvbihvYmopIHtcbiAgLy8gU29ydCBrZXlzIGFuZCBlbmNvZGUgdmFsdWVzXG4gIGlmIChvYmopIHtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaikuc29ydCgpO1xuXG4gICAgLy8gTWFwIGtleT12YWx1ZSwgam9pbiB0aGVtIGJ5ICZcbiAgICByZXR1cm4ga2V5c1xuICAgICAgLm1hcChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSArICc9JyArIE9BdXRoLmVuY29kZShvYmpba2V5XSk7XG4gICAgICB9KVxuICAgICAgLmpvaW4oJyYnKTtcbiAgfVxuXG4gIHJldHVybiAnJztcbn07XG5cbi8qXG5cdEJ1aWxkIHRoZSBzaWduYXR1cmUgc3RyaW5nIGZyb20gdGhlIG9iamVjdFxuKi9cblxuT0F1dGguYnVpbGRTaWduYXR1cmVTdHJpbmcgPSBmdW5jdGlvbihtZXRob2QsIHVybCwgcGFyYW1ldGVycykge1xuICByZXR1cm4gW1xuICAgIG1ldGhvZC50b1VwcGVyQ2FzZSgpLFxuICAgIE9BdXRoLmVuY29kZSh1cmwpLFxuICAgIE9BdXRoLmVuY29kZShwYXJhbWV0ZXJzKSxcbiAgXS5qb2luKCcmJyk7XG59O1xuXG4vKlxuXHRSZXR1bnMgZW5jb2RlZCBITUFDLVNIQTEgZnJvbSBrZXkgYW5kIHRleHRcbiovXG5PQXV0aC5zaWduYXR1cmUgPSBmdW5jdGlvbih0ZXh0LCBrZXkpIHtcbiAgY3J5cHRvID0gcmVxdWlyZSgnY3J5cHRvJyk7XG4gIHJldHVybiBPQXV0aC5lbmNvZGUoXG4gICAgY3J5cHRvXG4gICAgICAuY3JlYXRlSG1hYygnc2hhMScsIGtleSlcbiAgICAgIC51cGRhdGUodGV4dClcbiAgICAgIC5kaWdlc3QoJ2Jhc2U2NCcpXG4gICk7XG59O1xuXG5PQXV0aC5zaWduUmVxdWVzdCA9IGZ1bmN0aW9uKFxuICByZXF1ZXN0LFxuICBvYXV0aF9wYXJhbWV0ZXJzLFxuICBjb25zdW1lcl9zZWNyZXQsXG4gIGF1dGhfdG9rZW5fc2VjcmV0XG4pIHtcbiAgb2F1dGhfcGFyYW1ldGVycyA9IG9hdXRoX3BhcmFtZXRlcnMgfHwge307XG5cbiAgLy8gU2V0IGRlZmF1bHQgdmFsdWVzXG4gIGlmICghb2F1dGhfcGFyYW1ldGVycy5vYXV0aF9ub25jZSkge1xuICAgIG9hdXRoX3BhcmFtZXRlcnMub2F1dGhfbm9uY2UgPSBPQXV0aC5ub25jZSgpO1xuICB9XG4gIGlmICghb2F1dGhfcGFyYW1ldGVycy5vYXV0aF90aW1lc3RhbXApIHtcbiAgICBvYXV0aF9wYXJhbWV0ZXJzLm9hdXRoX3RpbWVzdGFtcCA9IE1hdGguZmxvb3IobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKTtcbiAgfVxuICBpZiAoIW9hdXRoX3BhcmFtZXRlcnMub2F1dGhfc2lnbmF0dXJlX21ldGhvZCkge1xuICAgIG9hdXRoX3BhcmFtZXRlcnMub2F1dGhfc2lnbmF0dXJlX21ldGhvZCA9IE9BdXRoLnNpZ25hdHVyZU1ldGhvZDtcbiAgfVxuICBpZiAoIW9hdXRoX3BhcmFtZXRlcnMub2F1dGhfdmVyc2lvbikge1xuICAgIG9hdXRoX3BhcmFtZXRlcnMub2F1dGhfdmVyc2lvbiA9IE9BdXRoLnZlcnNpb247XG4gIH1cblxuICBpZiAoIWF1dGhfdG9rZW5fc2VjcmV0KSB7XG4gICAgYXV0aF90b2tlbl9zZWNyZXQgPSAnJztcbiAgfVxuICAvLyBGb3JjZSBHRVQgbWV0aG9kIGlmIHVuc2V0XG4gIGlmICghcmVxdWVzdC5tZXRob2QpIHtcbiAgICByZXF1ZXN0Lm1ldGhvZCA9ICdHRVQnO1xuICB9XG5cbiAgLy8gQ29sbGVjdCAgYWxsIHRoZSBwYXJhbWV0ZXJzIGluIG9uZSBzaWduYXR1cmVQYXJhbWV0ZXJzIG9iamVjdFxuICB2YXIgc2lnbmF0dXJlUGFyYW1zID0ge307XG4gIHZhciBwYXJhbWV0ZXJzVG9NZXJnZSA9IFtyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdC5ib2R5LCBvYXV0aF9wYXJhbWV0ZXJzXTtcbiAgZm9yICh2YXIgaSBpbiBwYXJhbWV0ZXJzVG9NZXJnZSkge1xuICAgIHZhciBwYXJhbWV0ZXJzID0gcGFyYW1ldGVyc1RvTWVyZ2VbaV07XG4gICAgZm9yICh2YXIgayBpbiBwYXJhbWV0ZXJzKSB7XG4gICAgICBzaWduYXR1cmVQYXJhbXNba10gPSBwYXJhbWV0ZXJzW2tdO1xuICAgIH1cbiAgfVxuXG4gIC8vIENyZWF0ZSBhIHN0cmluZyBiYXNlZCBvbiB0aGUgcGFyYW1ldGVyc1xuICB2YXIgcGFyYW1ldGVyU3RyaW5nID0gT0F1dGguYnVpbGRQYXJhbWV0ZXJTdHJpbmcoc2lnbmF0dXJlUGFyYW1zKTtcblxuICAvLyBCdWlsZCB0aGUgc2lnbmF0dXJlIHN0cmluZ1xuICB2YXIgdXJsID0gJ2h0dHBzOi8vJyArIHJlcXVlc3QuaG9zdCArICcnICsgcmVxdWVzdC5wYXRoO1xuXG4gIHZhciBzaWduYXR1cmVTdHJpbmcgPSBPQXV0aC5idWlsZFNpZ25hdHVyZVN0cmluZyhcbiAgICByZXF1ZXN0Lm1ldGhvZCxcbiAgICB1cmwsXG4gICAgcGFyYW1ldGVyU3RyaW5nXG4gICk7XG4gIC8vIEhhc2ggdGhlIHNpZ25hdHVyZSBzdHJpbmdcbiAgdmFyIHNpZ25hdHVyZUtleSA9IFtcbiAgICBPQXV0aC5lbmNvZGUoY29uc3VtZXJfc2VjcmV0KSxcbiAgICBPQXV0aC5lbmNvZGUoYXV0aF90b2tlbl9zZWNyZXQpLFxuICBdLmpvaW4oJyYnKTtcblxuICB2YXIgc2lnbmF0dXJlID0gT0F1dGguc2lnbmF0dXJlKHNpZ25hdHVyZVN0cmluZywgc2lnbmF0dXJlS2V5KTtcblxuICAvLyBTZXQgdGhlIHNpZ25hdHVyZSBpbiB0aGUgcGFyYW1zXG4gIG9hdXRoX3BhcmFtZXRlcnMub2F1dGhfc2lnbmF0dXJlID0gc2lnbmF0dXJlO1xuICBpZiAoIXJlcXVlc3QuaGVhZGVycykge1xuICAgIHJlcXVlc3QuaGVhZGVycyA9IHt9O1xuICB9XG5cbiAgLy8gU2V0IHRoZSBhdXRob3JpemF0aW9uIGhlYWRlclxuICB2YXIgYXV0aEhlYWRlciA9IE9iamVjdC5rZXlzKG9hdXRoX3BhcmFtZXRlcnMpXG4gICAgLnNvcnQoKVxuICAgIC5tYXAoZnVuY3Rpb24oa2V5KSB7XG4gICAgICB2YXIgdmFsdWUgPSBvYXV0aF9wYXJhbWV0ZXJzW2tleV07XG4gICAgICByZXR1cm4ga2V5ICsgJz1cIicgKyB2YWx1ZSArICdcIic7XG4gICAgfSlcbiAgICAuam9pbignLCAnKTtcblxuICByZXF1ZXN0LmhlYWRlcnMuQXV0aG9yaXphdGlvbiA9ICdPQXV0aCAnICsgYXV0aEhlYWRlcjtcblxuICAvLyBTZXQgdGhlIGNvbnRlbnQgdHlwZSBoZWFkZXJcbiAgcmVxdWVzdC5oZWFkZXJzWydDb250ZW50LVR5cGUnXSA9ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnO1xuICByZXR1cm4gcmVxdWVzdDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gT0F1dGg7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/apple.js b/lib/Adapters/Auth/apple.js new file mode 100644 index 0000000000..b7676ab6ab --- /dev/null +++ b/lib/Adapters/Auth/apple.js @@ -0,0 +1,81 @@ +"use strict"; + +// Apple SignIn Auth +// https://developer.apple.com/documentation/signinwithapplerestapi +const Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); + +const NodeRSA = require('node-rsa'); + +const jwt = require('jsonwebtoken'); + +const TOKEN_ISSUER = 'https://appleid.apple.com'; +let currentKey; + +const getApplePublicKey = async () => { + let data; + + try { + data = await httpsRequest.get('https://appleid.apple.com/auth/keys'); + } catch (e) { + if (currentKey) { + return currentKey; + } + + throw e; + } + + const key = data.keys[0]; + const pubKey = new NodeRSA(); + pubKey.importKey({ + n: Buffer.from(key.n, 'base64'), + e: Buffer.from(key.e, 'base64') + }, 'components-public'); + currentKey = pubKey.exportKey(['public']); + return currentKey; +}; + +const verifyIdToken = async ({ + token, + id +}, clientID) => { + if (!token) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'id token is invalid for this user.'); + } + + const applePublicKey = await getApplePublicKey(); + const jwtClaims = jwt.verify(token, applePublicKey, { + algorithms: 'RS256' + }); + + if (jwtClaims.iss !== TOKEN_ISSUER) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `id token not issued by correct OpenID provider - expected: ${TOKEN_ISSUER} | from: ${jwtClaims.iss}`); + } + + if (jwtClaims.sub !== id) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `auth data is invalid for this user.`); + } + + if (clientID !== undefined && jwtClaims.aud !== clientID) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `jwt aud parameter does not include this client - is: ${jwtClaims.aud} | expected: ${clientID}`); + } + + return jwtClaims; +}; // Returns a promise that fulfills if this id token is valid + + +function validateAuthData(authData, options = {}) { + return verifyIdToken(authData, options.client_id); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} + +module.exports = { + validateAppId, + validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2FwcGxlLmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsImh0dHBzUmVxdWVzdCIsIk5vZGVSU0EiLCJqd3QiLCJUT0tFTl9JU1NVRVIiLCJjdXJyZW50S2V5IiwiZ2V0QXBwbGVQdWJsaWNLZXkiLCJkYXRhIiwiZ2V0IiwiZSIsImtleSIsImtleXMiLCJwdWJLZXkiLCJpbXBvcnRLZXkiLCJuIiwiQnVmZmVyIiwiZnJvbSIsImV4cG9ydEtleSIsInZlcmlmeUlkVG9rZW4iLCJ0b2tlbiIsImlkIiwiY2xpZW50SUQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJhcHBsZVB1YmxpY0tleSIsImp3dENsYWltcyIsInZlcmlmeSIsImFsZ29yaXRobXMiLCJpc3MiLCJzdWIiLCJ1bmRlZmluZWQiLCJhdWQiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJvcHRpb25zIiwiY2xpZW50X2lkIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBRUEsTUFBTUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFwQzs7QUFDQSxNQUFNRSxZQUFZLEdBQUdELE9BQU8sQ0FBQyxnQkFBRCxDQUE1Qjs7QUFDQSxNQUFNRSxPQUFPLEdBQUdGLE9BQU8sQ0FBQyxVQUFELENBQXZCOztBQUNBLE1BQU1HLEdBQUcsR0FBR0gsT0FBTyxDQUFDLGNBQUQsQ0FBbkI7O0FBRUEsTUFBTUksWUFBWSxHQUFHLDJCQUFyQjtBQUVBLElBQUlDLFVBQUo7O0FBRUEsTUFBTUMsaUJBQWlCLEdBQUcsWUFBWTtBQUNwQyxNQUFJQyxJQUFKOztBQUNBLE1BQUk7QUFDRkEsSUFBQUEsSUFBSSxHQUFHLE1BQU1OLFlBQVksQ0FBQ08sR0FBYixDQUFpQixxQ0FBakIsQ0FBYjtBQUNELEdBRkQsQ0FFRSxPQUFPQyxDQUFQLEVBQVU7QUFDVixRQUFJSixVQUFKLEVBQWdCO0FBQ2QsYUFBT0EsVUFBUDtBQUNEOztBQUNELFVBQU1JLENBQU47QUFDRDs7QUFFRCxRQUFNQyxHQUFHLEdBQUdILElBQUksQ0FBQ0ksSUFBTCxDQUFVLENBQVYsQ0FBWjtBQUVBLFFBQU1DLE1BQU0sR0FBRyxJQUFJVixPQUFKLEVBQWY7QUFDQVUsRUFBQUEsTUFBTSxDQUFDQyxTQUFQLENBQ0U7QUFBRUMsSUFBQUEsQ0FBQyxFQUFFQyxNQUFNLENBQUNDLElBQVAsQ0FBWU4sR0FBRyxDQUFDSSxDQUFoQixFQUFtQixRQUFuQixDQUFMO0FBQW1DTCxJQUFBQSxDQUFDLEVBQUVNLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZTixHQUFHLENBQUNELENBQWhCLEVBQW1CLFFBQW5CO0FBQXRDLEdBREYsRUFFRSxtQkFGRjtBQUlBSixFQUFBQSxVQUFVLEdBQUdPLE1BQU0sQ0FBQ0ssU0FBUCxDQUFpQixDQUFDLFFBQUQsQ0FBakIsQ0FBYjtBQUNBLFNBQU9aLFVBQVA7QUFDRCxDQXBCRDs7QUFzQkEsTUFBTWEsYUFBYSxHQUFHLE9BQU87QUFBRUMsRUFBQUEsS0FBRjtBQUFTQyxFQUFBQTtBQUFULENBQVAsRUFBc0JDLFFBQXRCLEtBQW1DO0FBQ3ZELE1BQUksQ0FBQ0YsS0FBTCxFQUFZO0FBQ1YsVUFBTSxJQUFJcEIsS0FBSyxDQUFDdUIsS0FBVixDQUNKdkIsS0FBSyxDQUFDdUIsS0FBTixDQUFZQyxnQkFEUixFQUVKLG9DQUZJLENBQU47QUFJRDs7QUFDRCxRQUFNQyxjQUFjLEdBQUcsTUFBTWxCLGlCQUFpQixFQUE5QztBQUNBLFFBQU1tQixTQUFTLEdBQUd0QixHQUFHLENBQUN1QixNQUFKLENBQVdQLEtBQVgsRUFBa0JLLGNBQWxCLEVBQWtDO0FBQUVHLElBQUFBLFVBQVUsRUFBRTtBQUFkLEdBQWxDLENBQWxCOztBQUVBLE1BQUlGLFNBQVMsQ0FBQ0csR0FBVixLQUFrQnhCLFlBQXRCLEVBQW9DO0FBQ2xDLFVBQU0sSUFBSUwsS0FBSyxDQUFDdUIsS0FBVixDQUNKdkIsS0FBSyxDQUFDdUIsS0FBTixDQUFZQyxnQkFEUixFQUVILDhEQUE2RG5CLFlBQWEsWUFBV3FCLFNBQVMsQ0FBQ0csR0FBSSxFQUZoRyxDQUFOO0FBSUQ7O0FBQ0QsTUFBSUgsU0FBUyxDQUFDSSxHQUFWLEtBQWtCVCxFQUF0QixFQUEwQjtBQUN4QixVQUFNLElBQUlyQixLQUFLLENBQUN1QixLQUFWLENBQ0p2QixLQUFLLENBQUN1QixLQUFOLENBQVlDLGdCQURSLEVBRUgscUNBRkcsQ0FBTjtBQUlEOztBQUNELE1BQUlGLFFBQVEsS0FBS1MsU0FBYixJQUEwQkwsU0FBUyxDQUFDTSxHQUFWLEtBQWtCVixRQUFoRCxFQUEwRDtBQUN4RCxVQUFNLElBQUl0QixLQUFLLENBQUN1QixLQUFWLENBQ0p2QixLQUFLLENBQUN1QixLQUFOLENBQVlDLGdCQURSLEVBRUgsd0RBQXVERSxTQUFTLENBQUNNLEdBQUksZ0JBQWVWLFFBQVMsRUFGMUYsQ0FBTjtBQUlEOztBQUNELFNBQU9JLFNBQVA7QUFDRCxDQTdCRCxDLENBK0JBOzs7QUFDQSxTQUFTTyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQU8sR0FBRyxFQUE5QyxFQUFrRDtBQUNoRCxTQUFPaEIsYUFBYSxDQUFDZSxRQUFELEVBQVdDLE9BQU8sQ0FBQ0MsU0FBbkIsQ0FBcEI7QUFDRCxDLENBRUQ7OztBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFFREMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZKLEVBQUFBLGFBRGU7QUFFZkosRUFBQUE7QUFGZSxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFwcGxlIFNpZ25JbiBBdXRoXG4vLyBodHRwczovL2RldmVsb3Blci5hcHBsZS5jb20vZG9jdW1lbnRhdGlvbi9zaWduaW53aXRoYXBwbGVyZXN0YXBpXG5cbmNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuY29uc3QgaHR0cHNSZXF1ZXN0ID0gcmVxdWlyZSgnLi9odHRwc1JlcXVlc3QnKTtcbmNvbnN0IE5vZGVSU0EgPSByZXF1aXJlKCdub2RlLXJzYScpO1xuY29uc3Qgand0ID0gcmVxdWlyZSgnanNvbndlYnRva2VuJyk7XG5cbmNvbnN0IFRPS0VOX0lTU1VFUiA9ICdodHRwczovL2FwcGxlaWQuYXBwbGUuY29tJztcblxubGV0IGN1cnJlbnRLZXk7XG5cbmNvbnN0IGdldEFwcGxlUHVibGljS2V5ID0gYXN5bmMgKCkgPT4ge1xuICBsZXQgZGF0YTtcbiAgdHJ5IHtcbiAgICBkYXRhID0gYXdhaXQgaHR0cHNSZXF1ZXN0LmdldCgnaHR0cHM6Ly9hcHBsZWlkLmFwcGxlLmNvbS9hdXRoL2tleXMnKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChjdXJyZW50S2V5KSB7XG4gICAgICByZXR1cm4gY3VycmVudEtleTtcbiAgICB9XG4gICAgdGhyb3cgZTtcbiAgfVxuXG4gIGNvbnN0IGtleSA9IGRhdGEua2V5c1swXTtcblxuICBjb25zdCBwdWJLZXkgPSBuZXcgTm9kZVJTQSgpO1xuICBwdWJLZXkuaW1wb3J0S2V5KFxuICAgIHsgbjogQnVmZmVyLmZyb20oa2V5Lm4sICdiYXNlNjQnKSwgZTogQnVmZmVyLmZyb20oa2V5LmUsICdiYXNlNjQnKSB9LFxuICAgICdjb21wb25lbnRzLXB1YmxpYydcbiAgKTtcbiAgY3VycmVudEtleSA9IHB1YktleS5leHBvcnRLZXkoWydwdWJsaWMnXSk7XG4gIHJldHVybiBjdXJyZW50S2V5O1xufTtcblxuY29uc3QgdmVyaWZ5SWRUb2tlbiA9IGFzeW5jICh7IHRva2VuLCBpZCB9LCBjbGllbnRJRCkgPT4ge1xuICBpZiAoIXRva2VuKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdpZCB0b2tlbiBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH1cbiAgY29uc3QgYXBwbGVQdWJsaWNLZXkgPSBhd2FpdCBnZXRBcHBsZVB1YmxpY0tleSgpO1xuICBjb25zdCBqd3RDbGFpbXMgPSBqd3QudmVyaWZ5KHRva2VuLCBhcHBsZVB1YmxpY0tleSwgeyBhbGdvcml0aG1zOiAnUlMyNTYnIH0pO1xuXG4gIGlmIChqd3RDbGFpbXMuaXNzICE9PSBUT0tFTl9JU1NVRVIpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgYGlkIHRva2VuIG5vdCBpc3N1ZWQgYnkgY29ycmVjdCBPcGVuSUQgcHJvdmlkZXIgLSBleHBlY3RlZDogJHtUT0tFTl9JU1NVRVJ9IHwgZnJvbTogJHtqd3RDbGFpbXMuaXNzfWBcbiAgICApO1xuICB9XG4gIGlmIChqd3RDbGFpbXMuc3ViICE9PSBpZCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICBgYXV0aCBkYXRhIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci5gXG4gICAgKTtcbiAgfVxuICBpZiAoY2xpZW50SUQgIT09IHVuZGVmaW5lZCAmJiBqd3RDbGFpbXMuYXVkICE9PSBjbGllbnRJRCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICBgand0IGF1ZCBwYXJhbWV0ZXIgZG9lcyBub3QgaW5jbHVkZSB0aGlzIGNsaWVudCAtIGlzOiAke2p3dENsYWltcy5hdWR9IHwgZXhwZWN0ZWQ6ICR7Y2xpZW50SUR9YFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIGp3dENsYWltcztcbn07XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyBpZCB0b2tlbiBpcyB2YWxpZFxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSwgb3B0aW9ucyA9IHt9KSB7XG4gIHJldHVybiB2ZXJpZnlJZFRva2VuKGF1dGhEYXRhLCBvcHRpb25zLmNsaWVudF9pZCk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/facebook.js b/lib/Adapters/Auth/facebook.js new file mode 100644 index 0000000000..61bd1b0d5b --- /dev/null +++ b/lib/Adapters/Auth/facebook.js @@ -0,0 +1,62 @@ +"use strict"; + +// Helper functions for accessing the Facebook Graph API. +const httpsRequest = require('./httpsRequest'); + +var Parse = require('parse/node').Parse; + +const crypto = require('crypto'); + +function getAppSecretPath(authData, options = {}) { + const appSecret = options.appSecret; + + if (!appSecret) { + return ''; + } + + const appsecret_proof = crypto.createHmac('sha256', appSecret).update(authData.access_token).digest('hex'); + return `&appsecret_proof=${appsecret_proof}`; +} // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData, options) { + return graphRequest('me?fields=id&access_token=' + authData.access_token + getAppSecretPath(authData, options)).then(data => { + if (data && data.id == authData.id || process.env.TESTING && authData.id === 'test') { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Facebook auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId(appIds, authData, options) { + var access_token = authData.access_token; + + if (process.env.TESTING && access_token === 'test') { + return Promise.resolve(); + } + + if (!appIds.length) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Facebook auth is not configured.'); + } + + return graphRequest('app?access_token=' + access_token + getAppSecretPath(authData, options)).then(data => { + if (data && appIds.indexOf(data.id) != -1) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Facebook auth is invalid for this user.'); + }); +} // A promisey wrapper for FB graph requests. + + +function graphRequest(path) { + return httpsRequest.get('https://graph.facebook.com/' + path); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2ZhY2Vib29rLmpzIl0sIm5hbWVzIjpbImh0dHBzUmVxdWVzdCIsInJlcXVpcmUiLCJQYXJzZSIsImNyeXB0byIsImdldEFwcFNlY3JldFBhdGgiLCJhdXRoRGF0YSIsIm9wdGlvbnMiLCJhcHBTZWNyZXQiLCJhcHBzZWNyZXRfcHJvb2YiLCJjcmVhdGVIbWFjIiwidXBkYXRlIiwiYWNjZXNzX3Rva2VuIiwiZGlnZXN0IiwidmFsaWRhdGVBdXRoRGF0YSIsImdyYXBoUmVxdWVzdCIsInRoZW4iLCJkYXRhIiwiaWQiLCJwcm9jZXNzIiwiZW52IiwiVEVTVElORyIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJhcHBJZHMiLCJQcm9taXNlIiwicmVzb2x2ZSIsImxlbmd0aCIsImluZGV4T2YiLCJwYXRoIiwiZ2V0IiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLE1BQU1BLFlBQVksR0FBR0MsT0FBTyxDQUFDLGdCQUFELENBQTVCOztBQUNBLElBQUlDLEtBQUssR0FBR0QsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkMsS0FBbEM7O0FBQ0EsTUFBTUMsTUFBTSxHQUFHRixPQUFPLENBQUMsUUFBRCxDQUF0Qjs7QUFFQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQU8sR0FBRyxFQUE5QyxFQUFrRDtBQUNoRCxRQUFNQyxTQUFTLEdBQUdELE9BQU8sQ0FBQ0MsU0FBMUI7O0FBQ0EsTUFBSSxDQUFDQSxTQUFMLEVBQWdCO0FBQ2QsV0FBTyxFQUFQO0FBQ0Q7O0FBQ0QsUUFBTUMsZUFBZSxHQUFHTCxNQUFNLENBQzNCTSxVQURxQixDQUNWLFFBRFUsRUFDQUYsU0FEQSxFQUVyQkcsTUFGcUIsQ0FFZEwsUUFBUSxDQUFDTSxZQUZLLEVBR3JCQyxNQUhxQixDQUdkLEtBSGMsQ0FBeEI7QUFLQSxTQUFRLG9CQUFtQkosZUFBZ0IsRUFBM0M7QUFDRCxDLENBRUQ7OztBQUNBLFNBQVNLLGdCQUFULENBQTBCUixRQUExQixFQUFvQ0MsT0FBcEMsRUFBNkM7QUFDM0MsU0FBT1EsWUFBWSxDQUNqQiwrQkFDRVQsUUFBUSxDQUFDTSxZQURYLEdBRUVQLGdCQUFnQixDQUFDQyxRQUFELEVBQVdDLE9BQVgsQ0FIRCxDQUFaLENBSUxTLElBSkssQ0FJQUMsSUFBSSxJQUFJO0FBQ2IsUUFDR0EsSUFBSSxJQUFJQSxJQUFJLENBQUNDLEVBQUwsSUFBV1osUUFBUSxDQUFDWSxFQUE3QixJQUNDQyxPQUFPLENBQUNDLEdBQVIsQ0FBWUMsT0FBWixJQUF1QmYsUUFBUSxDQUFDWSxFQUFULEtBQWdCLE1BRjFDLEVBR0U7QUFDQTtBQUNEOztBQUNELFVBQU0sSUFBSWYsS0FBSyxDQUFDbUIsS0FBVixDQUNKbkIsS0FBSyxDQUFDbUIsS0FBTixDQUFZQyxnQkFEUixFQUVKLHlDQUZJLENBQU47QUFJRCxHQWZNLENBQVA7QUFnQkQsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULENBQXVCQyxNQUF2QixFQUErQm5CLFFBQS9CLEVBQXlDQyxPQUF6QyxFQUFrRDtBQUNoRCxNQUFJSyxZQUFZLEdBQUdOLFFBQVEsQ0FBQ00sWUFBNUI7O0FBQ0EsTUFBSU8sT0FBTyxDQUFDQyxHQUFSLENBQVlDLE9BQVosSUFBdUJULFlBQVksS0FBSyxNQUE1QyxFQUFvRDtBQUNsRCxXQUFPYyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNEOztBQUNELE1BQUksQ0FBQ0YsTUFBTSxDQUFDRyxNQUFaLEVBQW9CO0FBQ2xCLFVBQU0sSUFBSXpCLEtBQUssQ0FBQ21CLEtBQVYsQ0FDSm5CLEtBQUssQ0FBQ21CLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSixrQ0FGSSxDQUFOO0FBSUQ7O0FBQ0QsU0FBT1IsWUFBWSxDQUNqQixzQkFBc0JILFlBQXRCLEdBQXFDUCxnQkFBZ0IsQ0FBQ0MsUUFBRCxFQUFXQyxPQUFYLENBRHBDLENBQVosQ0FFTFMsSUFGSyxDQUVBQyxJQUFJLElBQUk7QUFDYixRQUFJQSxJQUFJLElBQUlRLE1BQU0sQ0FBQ0ksT0FBUCxDQUFlWixJQUFJLENBQUNDLEVBQXBCLEtBQTJCLENBQUMsQ0FBeEMsRUFBMkM7QUFDekM7QUFDRDs7QUFDRCxVQUFNLElBQUlmLEtBQUssQ0FBQ21CLEtBQVYsQ0FDSm5CLEtBQUssQ0FBQ21CLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix5Q0FGSSxDQUFOO0FBSUQsR0FWTSxDQUFQO0FBV0QsQyxDQUVEOzs7QUFDQSxTQUFTUixZQUFULENBQXNCZSxJQUF0QixFQUE0QjtBQUMxQixTQUFPN0IsWUFBWSxDQUFDOEIsR0FBYixDQUFpQixnQ0FBZ0NELElBQWpELENBQVA7QUFDRDs7QUFFREUsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZULEVBQUFBLGFBQWEsRUFBRUEsYUFEQTtBQUVmVixFQUFBQSxnQkFBZ0IsRUFBRUE7QUFGSCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgRmFjZWJvb2sgR3JhcGggQVBJLlxuY29uc3QgaHR0cHNSZXF1ZXN0ID0gcmVxdWlyZSgnLi9odHRwc1JlcXVlc3QnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IGNyeXB0byA9IHJlcXVpcmUoJ2NyeXB0bycpO1xuXG5mdW5jdGlvbiBnZXRBcHBTZWNyZXRQYXRoKGF1dGhEYXRhLCBvcHRpb25zID0ge30pIHtcbiAgY29uc3QgYXBwU2VjcmV0ID0gb3B0aW9ucy5hcHBTZWNyZXQ7XG4gIGlmICghYXBwU2VjcmV0KSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG4gIGNvbnN0IGFwcHNlY3JldF9wcm9vZiA9IGNyeXB0b1xuICAgIC5jcmVhdGVIbWFjKCdzaGEyNTYnLCBhcHBTZWNyZXQpXG4gICAgLnVwZGF0ZShhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pXG4gICAgLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgcmV0dXJuIGAmYXBwc2VjcmV0X3Byb29mPSR7YXBwc2VjcmV0X3Byb29mfWA7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGdyYXBoUmVxdWVzdChcbiAgICAnbWU/ZmllbGRzPWlkJmFjY2Vzc190b2tlbj0nICtcbiAgICAgIGF1dGhEYXRhLmFjY2Vzc190b2tlbiArXG4gICAgICBnZXRBcHBTZWNyZXRQYXRoKGF1dGhEYXRhLCBvcHRpb25zKVxuICApLnRoZW4oZGF0YSA9PiB7XG4gICAgaWYgKFxuICAgICAgKGRhdGEgJiYgZGF0YS5pZCA9PSBhdXRoRGF0YS5pZCkgfHxcbiAgICAgIChwcm9jZXNzLmVudi5URVNUSU5HICYmIGF1dGhEYXRhLmlkID09PSAndGVzdCcpXG4gICAgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnRmFjZWJvb2sgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoYXBwSWRzLCBhdXRoRGF0YSwgb3B0aW9ucykge1xuICB2YXIgYWNjZXNzX3Rva2VuID0gYXV0aERhdGEuYWNjZXNzX3Rva2VuO1xuICBpZiAocHJvY2Vzcy5lbnYuVEVTVElORyAmJiBhY2Nlc3NfdG9rZW4gPT09ICd0ZXN0Jykge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICBpZiAoIWFwcElkcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ0ZhY2Vib29rIGF1dGggaXMgbm90IGNvbmZpZ3VyZWQuJ1xuICAgICk7XG4gIH1cbiAgcmV0dXJuIGdyYXBoUmVxdWVzdChcbiAgICAnYXBwP2FjY2Vzc190b2tlbj0nICsgYWNjZXNzX3Rva2VuICsgZ2V0QXBwU2VjcmV0UGF0aChhdXRoRGF0YSwgb3B0aW9ucylcbiAgKS50aGVuKGRhdGEgPT4ge1xuICAgIGlmIChkYXRhICYmIGFwcElkcy5pbmRleE9mKGRhdGEuaWQpICE9IC0xKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnRmFjZWJvb2sgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIEZCIGdyYXBoIHJlcXVlc3RzLlxuZnVuY3Rpb24gZ3JhcGhSZXF1ZXN0KHBhdGgpIHtcbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5nZXQoJ2h0dHBzOi8vZ3JhcGguZmFjZWJvb2suY29tLycgKyBwYXRoKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGEsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/facebookaccountkit.js b/lib/Adapters/Auth/facebookaccountkit.js new file mode 100644 index 0000000000..76f5fc19c5 --- /dev/null +++ b/lib/Adapters/Auth/facebookaccountkit.js @@ -0,0 +1,57 @@ +"use strict"; + +const crypto = require('crypto'); + +const httpsRequest = require('./httpsRequest'); + +const Parse = require('parse/node').Parse; + +const graphRequest = path => { + return httpsRequest.get(`https://graph.accountkit.com/v1.1/${path}`); +}; + +function getRequestPath(authData, options) { + const access_token = authData.access_token, + appSecret = options && options.appSecret; + + if (appSecret) { + const appsecret_proof = crypto.createHmac('sha256', appSecret).update(access_token).digest('hex'); + return `me?access_token=${access_token}&appsecret_proof=${appsecret_proof}`; + } + + return `me?access_token=${access_token}`; +} + +function validateAppId(appIds, authData, options) { + if (!appIds.length) { + return Promise.reject(new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Facebook app id for Account Kit is not configured.')); + } + + return graphRequest(getRequestPath(authData, options)).then(data => { + if (data && data.application && appIds.indexOf(data.application.id) != -1) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Facebook app id for Account Kit is invalid for this user.'); + }); +} + +function validateAuthData(authData, options) { + return graphRequest(getRequestPath(authData, options)).then(data => { + if (data && data.error) { + throw data.error; + } + + if (data && data.id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Facebook Account Kit auth is invalid for this user.'); + }); +} + +module.exports = { + validateAppId, + validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2ZhY2Vib29rYWNjb3VudGtpdC5qcyJdLCJuYW1lcyI6WyJjcnlwdG8iLCJyZXF1aXJlIiwiaHR0cHNSZXF1ZXN0IiwiUGFyc2UiLCJncmFwaFJlcXVlc3QiLCJwYXRoIiwiZ2V0IiwiZ2V0UmVxdWVzdFBhdGgiLCJhdXRoRGF0YSIsIm9wdGlvbnMiLCJhY2Nlc3NfdG9rZW4iLCJhcHBTZWNyZXQiLCJhcHBzZWNyZXRfcHJvb2YiLCJjcmVhdGVIbWFjIiwidXBkYXRlIiwiZGlnZXN0IiwidmFsaWRhdGVBcHBJZCIsImFwcElkcyIsImxlbmd0aCIsIlByb21pc2UiLCJyZWplY3QiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ0aGVuIiwiZGF0YSIsImFwcGxpY2F0aW9uIiwiaW5kZXhPZiIsImlkIiwidmFsaWRhdGVBdXRoRGF0YSIsImVycm9yIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQSxNQUFNQSxNQUFNLEdBQUdDLE9BQU8sQ0FBQyxRQUFELENBQXRCOztBQUNBLE1BQU1DLFlBQVksR0FBR0QsT0FBTyxDQUFDLGdCQUFELENBQTVCOztBQUNBLE1BQU1FLEtBQUssR0FBR0YsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkUsS0FBcEM7O0FBRUEsTUFBTUMsWUFBWSxHQUFHQyxJQUFJLElBQUk7QUFDM0IsU0FBT0gsWUFBWSxDQUFDSSxHQUFiLENBQWtCLHFDQUFvQ0QsSUFBSyxFQUEzRCxDQUFQO0FBQ0QsQ0FGRDs7QUFJQSxTQUFTRSxjQUFULENBQXdCQyxRQUF4QixFQUFrQ0MsT0FBbEMsRUFBMkM7QUFDekMsUUFBTUMsWUFBWSxHQUFHRixRQUFRLENBQUNFLFlBQTlCO0FBQUEsUUFDRUMsU0FBUyxHQUFHRixPQUFPLElBQUlBLE9BQU8sQ0FBQ0UsU0FEakM7O0FBRUEsTUFBSUEsU0FBSixFQUFlO0FBQ2IsVUFBTUMsZUFBZSxHQUFHWixNQUFNLENBQzNCYSxVQURxQixDQUNWLFFBRFUsRUFDQUYsU0FEQSxFQUVyQkcsTUFGcUIsQ0FFZEosWUFGYyxFQUdyQkssTUFIcUIsQ0FHZCxLQUhjLENBQXhCO0FBSUEsV0FBUSxtQkFBa0JMLFlBQWEsb0JBQW1CRSxlQUFnQixFQUExRTtBQUNEOztBQUNELFNBQVEsbUJBQWtCRixZQUFhLEVBQXZDO0FBQ0Q7O0FBRUQsU0FBU00sYUFBVCxDQUF1QkMsTUFBdkIsRUFBK0JULFFBQS9CLEVBQXlDQyxPQUF6QyxFQUFrRDtBQUNoRCxNQUFJLENBQUNRLE1BQU0sQ0FBQ0MsTUFBWixFQUFvQjtBQUNsQixXQUFPQyxPQUFPLENBQUNDLE1BQVIsQ0FDTCxJQUFJakIsS0FBSyxDQUFDa0IsS0FBVixDQUNFbEIsS0FBSyxDQUFDa0IsS0FBTixDQUFZQyxnQkFEZCxFQUVFLG9EQUZGLENBREssQ0FBUDtBQU1EOztBQUNELFNBQU9sQixZQUFZLENBQUNHLGNBQWMsQ0FBQ0MsUUFBRCxFQUFXQyxPQUFYLENBQWYsQ0FBWixDQUFnRGMsSUFBaEQsQ0FBcURDLElBQUksSUFBSTtBQUNsRSxRQUFJQSxJQUFJLElBQUlBLElBQUksQ0FBQ0MsV0FBYixJQUE0QlIsTUFBTSxDQUFDUyxPQUFQLENBQWVGLElBQUksQ0FBQ0MsV0FBTCxDQUFpQkUsRUFBaEMsS0FBdUMsQ0FBQyxDQUF4RSxFQUEyRTtBQUN6RTtBQUNEOztBQUNELFVBQU0sSUFBSXhCLEtBQUssQ0FBQ2tCLEtBQVYsQ0FDSmxCLEtBQUssQ0FBQ2tCLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSiwyREFGSSxDQUFOO0FBSUQsR0FSTSxDQUFQO0FBU0Q7O0FBRUQsU0FBU00sZ0JBQVQsQ0FBMEJwQixRQUExQixFQUFvQ0MsT0FBcEMsRUFBNkM7QUFDM0MsU0FBT0wsWUFBWSxDQUFDRyxjQUFjLENBQUNDLFFBQUQsRUFBV0MsT0FBWCxDQUFmLENBQVosQ0FBZ0RjLElBQWhELENBQXFEQyxJQUFJLElBQUk7QUFDbEUsUUFBSUEsSUFBSSxJQUFJQSxJQUFJLENBQUNLLEtBQWpCLEVBQXdCO0FBQ3RCLFlBQU1MLElBQUksQ0FBQ0ssS0FBWDtBQUNEOztBQUNELFFBQUlMLElBQUksSUFBSUEsSUFBSSxDQUFDRyxFQUFMLElBQVduQixRQUFRLENBQUNtQixFQUFoQyxFQUFvQztBQUNsQztBQUNEOztBQUNELFVBQU0sSUFBSXhCLEtBQUssQ0FBQ2tCLEtBQVYsQ0FDSmxCLEtBQUssQ0FBQ2tCLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSixxREFGSSxDQUFOO0FBSUQsR0FYTSxDQUFQO0FBWUQ7O0FBRURRLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmZixFQUFBQSxhQURlO0FBRWZZLEVBQUFBO0FBRmUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5jb25zdCBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxuY29uc3QgZ3JhcGhSZXF1ZXN0ID0gcGF0aCA9PiB7XG4gIHJldHVybiBodHRwc1JlcXVlc3QuZ2V0KGBodHRwczovL2dyYXBoLmFjY291bnRraXQuY29tL3YxLjEvJHtwYXRofWApO1xufTtcblxuZnVuY3Rpb24gZ2V0UmVxdWVzdFBhdGgoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgY29uc3QgYWNjZXNzX3Rva2VuID0gYXV0aERhdGEuYWNjZXNzX3Rva2VuLFxuICAgIGFwcFNlY3JldCA9IG9wdGlvbnMgJiYgb3B0aW9ucy5hcHBTZWNyZXQ7XG4gIGlmIChhcHBTZWNyZXQpIHtcbiAgICBjb25zdCBhcHBzZWNyZXRfcHJvb2YgPSBjcnlwdG9cbiAgICAgIC5jcmVhdGVIbWFjKCdzaGEyNTYnLCBhcHBTZWNyZXQpXG4gICAgICAudXBkYXRlKGFjY2Vzc190b2tlbilcbiAgICAgIC5kaWdlc3QoJ2hleCcpO1xuICAgIHJldHVybiBgbWU/YWNjZXNzX3Rva2VuPSR7YWNjZXNzX3Rva2VufSZhcHBzZWNyZXRfcHJvb2Y9JHthcHBzZWNyZXRfcHJvb2Z9YDtcbiAgfVxuICByZXR1cm4gYG1lP2FjY2Vzc190b2tlbj0ke2FjY2Vzc190b2tlbn1gO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKGFwcElkcywgYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgaWYgKCFhcHBJZHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnRmFjZWJvb2sgYXBwIGlkIGZvciBBY2NvdW50IEtpdCBpcyBub3QgY29uZmlndXJlZC4nXG4gICAgICApXG4gICAgKTtcbiAgfVxuICByZXR1cm4gZ3JhcGhSZXF1ZXN0KGdldFJlcXVlc3RQYXRoKGF1dGhEYXRhLCBvcHRpb25zKSkudGhlbihkYXRhID0+IHtcbiAgICBpZiAoZGF0YSAmJiBkYXRhLmFwcGxpY2F0aW9uICYmIGFwcElkcy5pbmRleE9mKGRhdGEuYXBwbGljYXRpb24uaWQpICE9IC0xKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnRmFjZWJvb2sgYXBwIGlkIGZvciBBY2NvdW50IEtpdCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gIHJldHVybiBncmFwaFJlcXVlc3QoZ2V0UmVxdWVzdFBhdGgoYXV0aERhdGEsIG9wdGlvbnMpKS50aGVuKGRhdGEgPT4ge1xuICAgIGlmIChkYXRhICYmIGRhdGEuZXJyb3IpIHtcbiAgICAgIHRocm93IGRhdGEuZXJyb3I7XG4gICAgfVxuICAgIGlmIChkYXRhICYmIGRhdGEuaWQgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdGYWNlYm9vayBBY2NvdW50IEtpdCBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nXG4gICAgKTtcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/gcenter.js b/lib/Adapters/Auth/gcenter.js new file mode 100644 index 0000000000..7753e000a1 --- /dev/null +++ b/lib/Adapters/Auth/gcenter.js @@ -0,0 +1,127 @@ +"use strict"; + +/* Apple Game Center Auth +https://developer.apple.com/documentation/gamekit/gklocalplayer/1515407-generateidentityverificationsign#discussion + +const authData = { + publicKeyUrl: 'https://valid.apple.com/public/timeout.cer', + timestamp: 1460981421303, + signature: 'PoDwf39DCN464B49jJCU0d9Y0J', + salt: 'saltST==', + bundleId: 'com.valid.app' + id: 'playerId', +}; +*/ +const { + Parse +} = require('parse/node'); + +const crypto = require('crypto'); + +const https = require('https'); + +const url = require('url'); + +const cache = {}; // (publicKey -> cert) cache + +function verifyPublicKeyUrl(publicKeyUrl) { + const parsedUrl = url.parse(publicKeyUrl); + + if (parsedUrl.protocol !== 'https:') { + return false; + } + + const hostnameParts = parsedUrl.hostname.split('.'); + const length = hostnameParts.length; + const domainParts = hostnameParts.slice(length - 2, length); + const domain = domainParts.join('.'); + return domain === 'apple.com'; +} + +function convertX509CertToPEM(X509Cert) { + const pemPreFix = '-----BEGIN CERTIFICATE-----\n'; + const pemPostFix = '-----END CERTIFICATE-----'; + const base64 = X509Cert; + const certBody = base64.match(new RegExp('.{0,64}', 'g')).join('\n'); + return pemPreFix + certBody + pemPostFix; +} + +function getAppleCertificate(publicKeyUrl) { + if (!verifyPublicKeyUrl(publicKeyUrl)) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `Apple Game Center - invalid publicKeyUrl: ${publicKeyUrl}`); + } + + if (cache[publicKeyUrl]) { + return cache[publicKeyUrl]; + } + + return new Promise((resolve, reject) => { + https.get(publicKeyUrl, res => { + let data = ''; + res.on('data', chunk => { + data += chunk.toString('base64'); + }); + res.on('end', () => { + const cert = convertX509CertToPEM(data); + + if (res.headers['cache-control']) { + var expire = res.headers['cache-control'].match(/max-age=([0-9]+)/); + + if (expire) { + cache[publicKeyUrl] = cert; // we'll expire the cache entry later, as per max-age + + setTimeout(() => { + delete cache[publicKeyUrl]; + }, parseInt(expire[1], 10) * 1000); + } + } + + resolve(cert); + }); + }).on('error', reject); + }); +} + +function convertTimestampToBigEndian(timestamp) { + const buffer = new Buffer(8); + buffer.fill(0); + const high = ~~(timestamp / 0xffffffff); + const low = timestamp % (0xffffffff + 0x1); + buffer.writeUInt32BE(parseInt(high, 10), 0); + buffer.writeUInt32BE(parseInt(low, 10), 4); + return buffer; +} + +function verifySignature(publicKey, authData) { + const verifier = crypto.createVerify('sha256'); + verifier.update(authData.playerId, 'utf8'); + verifier.update(authData.bundleId, 'utf8'); + verifier.update(convertTimestampToBigEndian(authData.timestamp)); + verifier.update(authData.salt, 'base64'); + + if (!verifier.verify(publicKey, authData.signature, 'base64')) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Apple Game Center - invalid signature'); + } +} // Returns a promise that fulfills if this user id is valid. + + +async function validateAuthData(authData) { + if (!authData.id) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Apple Game Center - authData id missing'); + } + + authData.playerId = authData.id; + const publicKey = await getAppleCertificate(authData.publicKeyUrl); + return verifySignature(publicKey, authData); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} + +module.exports = { + validateAppId, + validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2djZW50ZXIuanMiXSwibmFtZXMiOlsiUGFyc2UiLCJyZXF1aXJlIiwiY3J5cHRvIiwiaHR0cHMiLCJ1cmwiLCJjYWNoZSIsInZlcmlmeVB1YmxpY0tleVVybCIsInB1YmxpY0tleVVybCIsInBhcnNlZFVybCIsInBhcnNlIiwicHJvdG9jb2wiLCJob3N0bmFtZVBhcnRzIiwiaG9zdG5hbWUiLCJzcGxpdCIsImxlbmd0aCIsImRvbWFpblBhcnRzIiwic2xpY2UiLCJkb21haW4iLCJqb2luIiwiY29udmVydFg1MDlDZXJ0VG9QRU0iLCJYNTA5Q2VydCIsInBlbVByZUZpeCIsInBlbVBvc3RGaXgiLCJiYXNlNjQiLCJjZXJ0Qm9keSIsIm1hdGNoIiwiUmVnRXhwIiwiZ2V0QXBwbGVDZXJ0aWZpY2F0ZSIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZ2V0IiwicmVzIiwiZGF0YSIsIm9uIiwiY2h1bmsiLCJ0b1N0cmluZyIsImNlcnQiLCJoZWFkZXJzIiwiZXhwaXJlIiwic2V0VGltZW91dCIsInBhcnNlSW50IiwiY29udmVydFRpbWVzdGFtcFRvQmlnRW5kaWFuIiwidGltZXN0YW1wIiwiYnVmZmVyIiwiQnVmZmVyIiwiZmlsbCIsImhpZ2giLCJsb3ciLCJ3cml0ZVVJbnQzMkJFIiwidmVyaWZ5U2lnbmF0dXJlIiwicHVibGljS2V5IiwiYXV0aERhdGEiLCJ2ZXJpZmllciIsImNyZWF0ZVZlcmlmeSIsInVwZGF0ZSIsInBsYXllcklkIiwiYnVuZGxlSWQiLCJzYWx0IiwidmVyaWZ5Iiwic2lnbmF0dXJlIiwidmFsaWRhdGVBdXRoRGF0YSIsImlkIiwidmFsaWRhdGVBcHBJZCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7Ozs7Ozs7Ozs7OztBQWFBLE1BQU07QUFBRUEsRUFBQUE7QUFBRixJQUFZQyxPQUFPLENBQUMsWUFBRCxD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O0FBQ0FVLEVBQUFBLFFBQVEsQ0FBQ0UsTUFBVCxDQUFnQkgsUUFBUSxDQUFDTSxJQUF6QixFQUErQixRQUEvQjs7QUFFQSxNQUFJLENBQUNMLFFBQVEsQ0FBQ00sTUFBVCxDQUFnQlIsU0FBaEIsRUFBMkJDLFFBQVEsQ0FBQ1EsU0FBcEMsRUFBK0MsUUFBL0MsQ0FBTCxFQUErRDtBQUM3RCxVQUFNLElBQUk5RCxLQUFLLENBQUM0QixLQUFWLENBQ0o1QixLQUFLLENBQUM0QixLQUFOLENBQVlDLGdCQURSLEVBRUosdUNBRkksQ0FBTjtBQUlEO0FBQ0YsQyxDQUVEOzs7QUFDQSxlQUFla0MsZ0JBQWYsQ0FBZ0NULFFBQWhDLEVBQTBDO0FBQ3hDLE1BQUksQ0FBQ0EsUUFBUSxDQUFDVSxFQUFkLEVBQWtCO0FBQ2hCLFVBQU0sSUFBSWhFLEtBQUssQ0FBQzRCLEtBQVYsQ0FDSjVCLEtBQUssQ0FBQzRCLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix5Q0FGSSxDQUFOO0FBSUQ7O0FBQ0R5QixFQUFBQSxRQUFRLENBQUNJLFFBQVQsR0FBb0JKLFFBQVEsQ0FBQ1UsRUFBN0I7QUFDQSxRQUFNWCxTQUFTLEdBQUcsTUFBTTFCLG1CQUFtQixDQUFDMkIsUUFBUSxDQUFDL0MsWUFBVixDQUEzQztBQUNBLFNBQU82QyxlQUFlLENBQUNDLFNBQUQsRUFBWUMsUUFBWixDQUF0QjtBQUNELEMsQ0FFRDs7O0FBQ0EsU0FBU1csYUFBVCxHQUF5QjtBQUN2QixTQUFPbkMsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFFRG1DLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmRixFQUFBQSxhQURlO0FBRWZGLEVBQUFBO0FBRmUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBBcHBsZSBHYW1lIENlbnRlciBBdXRoXG5odHRwczovL2RldmVsb3Blci5hcHBsZS5jb20vZG9jdW1lbnRhdGlvbi9nYW1la2l0L2drbG9jYWxwbGF5ZXIvMTUxNTQwNy1nZW5lcmF0ZWlkZW50aXR5dmVyaWZpY2F0aW9uc2lnbiNkaXNjdXNzaW9uXG5cbmNvbnN0IGF1dGhEYXRhID0ge1xuICBwdWJsaWNLZXlVcmw6ICdodHRwczovL3ZhbGlkLmFwcGxlLmNvbS9wdWJsaWMvdGltZW91dC5jZXInLFxuICB0aW1lc3RhbXA6IDE0NjA5ODE0MjEzMDMsXG4gIHNpZ25hdHVyZTogJ1BvRHdmMzlEQ040NjRCNDlqSkNVMGQ5WTBKJyxcbiAgc2FsdDogJ3NhbHRTVD09JyxcbiAgYnVuZGxlSWQ6ICdjb20udmFsaWQuYXBwJ1xuICBpZDogJ3BsYXllcklkJyxcbn07XG4qL1xuXG5jb25zdCB7IFBhcnNlIH0gPSByZXF1aXJlKCdwYXJzZS9ub2RlJyk7XG5jb25zdCBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKTtcbmNvbnN0IGh0dHBzID0gcmVxdWlyZSgnaHR0cHMnKTtcbmNvbnN0IHVybCA9IHJlcXVpcmUoJ3VybCcpO1xuXG5jb25zdCBjYWNoZSA9IHt9OyAvLyAocHVibGljS2V5IC0+IGNlcnQpIGNhY2hlXG5cbmZ1bmN0aW9uIHZlcmlmeVB1YmxpY0tleVVybChwdWJsaWNLZXlVcmwpIHtcbiAgY29uc3QgcGFyc2VkVXJsID0gdXJsLnBhcnNlKHB1YmxpY0tleVVybCk7XG4gIGlmIChwYXJzZWRVcmwucHJvdG9jb2wgIT09ICdodHRwczonKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGhvc3RuYW1lUGFydHMgPSBwYXJzZWRVcmwuaG9zdG5hbWUuc3BsaXQoJy4nKTtcbiAgY29uc3QgbGVuZ3RoID0gaG9zdG5hbWVQYXJ0cy5sZW5ndGg7XG4gIGNvbnN0IGRvbWFpblBhcnRzID0gaG9zdG5hbWVQYXJ0cy5zbGljZShsZW5ndGggLSAyLCBsZW5ndGgpO1xuICBjb25zdCBkb21haW4gPSBkb21haW5QYXJ0cy5qb2luKCcuJyk7XG4gIHJldHVybiBkb21haW4gPT09ICdhcHBsZS5jb20nO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0WDUwOUNlcnRUb1BFTShYNTA5Q2VydCkge1xuICBjb25zdCBwZW1QcmVGaXggPSAnLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXFxuJztcbiAgY29uc3QgcGVtUG9zdEZpeCA9ICctLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tJztcblxuICBjb25zdCBiYXNlNjQgPSBYNTA5Q2VydDtcbiAgY29uc3QgY2VydEJvZHkgPSBiYXNlNjQubWF0Y2gobmV3IFJlZ0V4cCgnLnswLDY0fScsICdnJykpLmpvaW4oJ1xcbicpO1xuXG4gIHJldHVybiBwZW1QcmVGaXggKyBjZXJ0Qm9keSArIHBlbVBvc3RGaXg7XG59XG5cbmZ1bmN0aW9uIGdldEFwcGxlQ2VydGlmaWNhdGUocHVibGljS2V5VXJsKSB7XG4gIGlmICghdmVyaWZ5UHVibGljS2V5VXJsKHB1YmxpY0tleVVybCkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgYEFwcGxlIEdhbWUgQ2VudGVyIC0gaW52YWxpZCBwdWJsaWNLZXlVcmw6ICR7cHVibGljS2V5VXJsfWBcbiAgICApO1xuICB9XG4gIGlmIChjYWNoZVtwdWJsaWNLZXlVcmxdKSB7XG4gICAgcmV0dXJuIGNhY2hlW3B1YmxpY0tleVVybF07XG4gIH1cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBodHRwc1xuICAgICAgLmdldChwdWJsaWNLZXlVcmwsIHJlcyA9PiB7XG4gICAgICAgIGxldCBkYXRhID0gJyc7XG4gICAgICAgIHJlcy5vbignZGF0YScsIGNodW5rID0+IHtcbiAgICAgICAgICBkYXRhICs9IGNodW5rLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJlcy5vbignZW5kJywgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNlcnQgPSBjb252ZXJ0WDUwOUNlcnRUb1BFTShkYXRhKTtcbiAgICAgICAgICBpZiAocmVzLmhlYWRlcnNbJ2NhY2hlLWNvbnRyb2wnXSkge1xuICAgICAgICAgICAgdmFyIGV4cGlyZSA9IHJlcy5oZWFkZXJzWydjYWNoZS1jb250cm9sJ10ubWF0Y2goL21heC1hZ2U9KFswLTldKykvKTtcbiAgICAgICAgICAgIGlmIChleHBpcmUpIHtcbiAgICAgICAgICAgICAgY2FjaGVbcHVibGljS2V5VXJsXSA9IGNlcnQ7XG4gICAgICAgICAgICAgIC8vIHdlJ2xsIGV4cGlyZSB0aGUgY2FjaGUgZW50cnkgbGF0ZXIsIGFzIHBlciBtYXgtYWdlXG4gICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBjYWNoZVtwdWJsaWNLZXlVcmxdO1xuICAgICAgICAgICAgICB9LCBwYXJzZUludChleHBpcmVbMV0sIDEwKSAqIDEwMDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXNvbHZlKGNlcnQpO1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRUaW1lc3RhbXBUb0JpZ0VuZGlhbih0aW1lc3RhbXApIHtcbiAgY29uc3QgYnVmZmVyID0gbmV3IEJ1ZmZlcig4KTtcbiAgYnVmZmVyLmZpbGwoMCk7XG5cbiAgY29uc3QgaGlnaCA9IH5+KHRpbWVzdGFtcCAvIDB4ZmZmZmZmZmYpO1xuICBjb25zdCBsb3cgPSB0aW1lc3RhbXAgJSAoMHhmZmZmZmZmZiArIDB4MSk7XG5cbiAgYnVmZmVyLndyaXRlVUludDMyQkUocGFyc2VJbnQoaGlnaCwgMTApLCAwKTtcbiAgYnVmZmVyLndyaXRlVUludDMyQkUocGFyc2VJbnQobG93LCAxMCksIDQpO1xuXG4gIHJldHVybiBidWZmZXI7XG59XG5cbmZ1bmN0aW9uIHZlcmlmeVNpZ25hdHVyZShwdWJsaWNLZXksIGF1dGhEYXRhKSB7XG4gIGNvbnN0IHZlcmlmaWVyID0gY3J5cHRvLmNyZWF0ZVZlcmlmeSgnc2hhMjU2Jyk7XG4gIHZlcmlmaWVyLnVwZGF0ZShhdXRoRGF0YS5wbGF5ZXJJZCwgJ3V0ZjgnKTtcbiAgdmVyaWZpZXIudXBkYXRlKGF1dGhEYXRhLmJ1bmRsZUlkLCAndXRmOCcpO1xuICB2ZXJpZmllci51cGRhdGUoY29udmVydFRpbWVzdGFtcFRvQmlnRW5kaWFuKGF1dGhEYXRhLnRpbWVzdGFtcCkpO1xuICB2ZXJpZmllci51cGRhdGUoYXV0aERhdGEuc2FsdCwgJ2Jhc2U2NCcpO1xuXG4gIGlmICghdmVyaWZpZXIudmVyaWZ5KHB1YmxpY0tleSwgYXV0aERhdGEuc2lnbmF0dXJlLCAnYmFzZTY0JykpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ0FwcGxlIEdhbWUgQ2VudGVyIC0gaW52YWxpZCBzaWduYXR1cmUnXG4gICAgKTtcbiAgfVxufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmFzeW5jIGZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgaWYgKCFhdXRoRGF0YS5pZCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnQXBwbGUgR2FtZSBDZW50ZXIgLSBhdXRoRGF0YSBpZCBtaXNzaW5nJ1xuICAgICk7XG4gIH1cbiAgYXV0aERhdGEucGxheWVySWQgPSBhdXRoRGF0YS5pZDtcbiAgY29uc3QgcHVibGljS2V5ID0gYXdhaXQgZ2V0QXBwbGVDZXJ0aWZpY2F0ZShhdXRoRGF0YS5wdWJsaWNLZXlVcmwpO1xuICByZXR1cm4gdmVyaWZ5U2lnbmF0dXJlKHB1YmxpY0tleSwgYXV0aERhdGEpO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YSxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/github.js b/lib/Adapters/Auth/github.js new file mode 100644 index 0000000000..686d718a9c --- /dev/null +++ b/lib/Adapters/Auth/github.js @@ -0,0 +1,40 @@ +"use strict"; + +// Helper functions for accessing the github API. +var Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return request('user', authData.access_token).then(data => { + if (data && data.id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Github auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(path, access_token) { + return httpsRequest.get({ + host: 'api.github.com', + path: '/' + path, + headers: { + Authorization: 'bearer ' + access_token, + 'User-Agent': 'parse-server' + } + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dpdGh1Yi5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJyZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBhdGgiLCJnZXQiLCJob3N0IiwiaGVhZGVycyIsIkF1dGhvcml6YXRpb24iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFsQzs7QUFDQSxNQUFNRSxZQUFZLEdBQUdELE9BQU8sQ0FBQyxnQkFBRCxDQUE1QixDLENBRUE7OztBQUNBLFNBQVNFLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxPQUFPLENBQUMsTUFBRCxFQUFTRCxRQUFRLENBQUNFLFlBQWxCLENBQVAsQ0FBdUNDLElBQXZDLENBQTRDQyxJQUFJLElBQUk7QUFDekQsUUFBSUEsSUFBSSxJQUFJQSxJQUFJLENBQUNDLEVBQUwsSUFBV0wsUUFBUSxDQUFDSyxFQUFoQyxFQUFvQztBQUNsQztBQUNEOztBQUNELFVBQU0sSUFBSVQsS0FBSyxDQUFDVSxLQUFWLENBQ0pWLEtBQUssQ0FBQ1UsS0FBTixDQUFZQyxnQkFEUixFQUVKLHVDQUZJLENBQU47QUFJRCxHQVJNLENBQVA7QUFTRCxDLENBRUQ7OztBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRCxDLENBRUQ7OztBQUNBLFNBQVNULE9BQVQsQ0FBaUJVLElBQWpCLEVBQXVCVCxZQUF2QixFQUFxQztBQUNuQyxTQUFPSixZQUFZLENBQUNjLEdBQWIsQ0FBaUI7QUFDdEJDLElBQUFBLElBQUksRUFBRSxnQkFEZ0I7QUFFdEJGLElBQUFBLElBQUksRUFBRSxNQUFNQSxJQUZVO0FBR3RCRyxJQUFBQSxPQUFPLEVBQUU7QUFDUEMsTUFBQUEsYUFBYSxFQUFFLFlBQVliLFlBRHBCO0FBRVAsb0JBQWM7QUFGUDtBQUhhLEdBQWpCLENBQVA7QUFRRDs7QUFFRGMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZULEVBQUFBLGFBQWEsRUFBRUEsYUFEQTtBQUVmVCxFQUFBQSxnQkFBZ0IsRUFBRUE7QUFGSCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgZ2l0aHViIEFQSS5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoJ3VzZXInLCBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pLnRoZW4oZGF0YSA9PiB7XG4gICAgaWYgKGRhdGEgJiYgZGF0YS5pZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ0dpdGh1YiBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nXG4gICAgKTtcbiAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChwYXRoLCBhY2Nlc3NfdG9rZW4pIHtcbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5nZXQoe1xuICAgIGhvc3Q6ICdhcGkuZ2l0aHViLmNvbScsXG4gICAgcGF0aDogJy8nICsgcGF0aCxcbiAgICBoZWFkZXJzOiB7XG4gICAgICBBdXRob3JpemF0aW9uOiAnYmVhcmVyICcgKyBhY2Nlc3NfdG9rZW4sXG4gICAgICAnVXNlci1BZ2VudCc6ICdwYXJzZS1zZXJ2ZXInLFxuICAgIH0sXG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YSxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/google.js b/lib/Adapters/Auth/google.js new file mode 100644 index 0000000000..717a58df72 --- /dev/null +++ b/lib/Adapters/Auth/google.js @@ -0,0 +1,57 @@ +"use strict"; + +// Helper functions for accessing the google API. +var Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); + +function validateIdToken(id, token) { + return googleRequest('tokeninfo?id_token=' + token).then(response => { + if (response && (response.sub == id || response.user_id == id)) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Google auth is invalid for this user.'); + }); +} + +function validateAuthToken(id, token) { + return googleRequest('tokeninfo?access_token=' + token).then(response => { + if (response && (response.sub == id || response.user_id == id)) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Google auth is invalid for this user.'); + }); +} // Returns a promise that fulfills if this user id is valid. + + +function validateAuthData(authData) { + if (authData.id_token) { + return validateIdToken(authData.id, authData.id_token); + } else { + return validateAuthToken(authData.id, authData.access_token).then(() => { + // Validation with auth token worked + return; + }, () => { + // Try with the id_token param + return validateIdToken(authData.id, authData.access_token); + }); + } +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function googleRequest(path) { + return httpsRequest.get('https://www.googleapis.com/oauth2/v3/' + path); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dvb2dsZS5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJ2YWxpZGF0ZUlkVG9rZW4iLCJpZCIsInRva2VuIiwiZ29vZ2xlUmVxdWVzdCIsInRoZW4iLCJyZXNwb25zZSIsInN1YiIsInVzZXJfaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUF1dGhUb2tlbiIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsImlkX3Rva2VuIiwiYWNjZXNzX3Rva2VuIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsImdldCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxLQUFLLEdBQUdDLE9BQU8sQ0FBQyxZQUFELENBQVAsQ0FBc0JELEtBQWxDOztBQUNBLE1BQU1FLFlBQVksR0FBR0QsT0FBTyxDQUFDLGdCQUFELENBQTVCOztBQUVBLFNBQVNFLGVBQVQsQ0FBeUJDLEVBQXpCLEVBQTZCQyxLQUE3QixFQUFvQztBQUNsQyxTQUFPQyxhQUFhLENBQUMsd0JBQXdCRCxLQUF6QixDQUFiLENBQTZDRSxJQUE3QyxDQUFrREMsUUFBUSxJQUFJO0FBQ25FLFFBQUlBLFFBQVEsS0FBS0EsUUFBUSxDQUFDQyxHQUFULElBQWdCTCxFQUFoQixJQUFzQkksUUFBUSxDQUFDRSxPQUFULElBQW9CTixFQUEvQyxDQUFaLEVBQWdFO0FBQzlEO0FBQ0Q7O0FBQ0QsVUFBTSxJQUFJSixLQUFLLENBQUNXLEtBQVYsQ0FDSlgsS0FBSyxDQUFDVyxLQUFOLENBQVlDLGdCQURSLEVBRUosdUNBRkksQ0FBTjtBQUlELEdBUk0sQ0FBUDtBQVNEOztBQUVELFNBQVNDLGlCQUFULENBQTJCVCxFQUEzQixFQUErQkMsS0FBL0IsRUFBc0M7QUFDcEMsU0FBT0MsYUFBYSxDQUFDLDRCQUE0QkQsS0FBN0IsQ0FBYixDQUFpREUsSUFBakQsQ0FBc0RDLFFBQVEsSUFBSTtBQUN2RSxRQUFJQSxRQUFRLEtBQUtBLFFBQVEsQ0FBQ0MsR0FBVCxJQUFnQkwsRUFBaEIsSUFBc0JJLFFBQVEsQ0FBQ0UsT0FBVCxJQUFvQk4sRUFBL0MsQ0FBWixFQUFnRTtBQUM5RDtBQUNEOztBQUNELFVBQU0sSUFBSUosS0FBSyxDQUFDVyxLQUFWLENBQ0pYLEtBQUssQ0FBQ1csS0FBTixDQUFZQyxnQkFEUixFQUVKLHVDQUZJLENBQU47QUFJRCxHQVJNLENBQVA7QUFTRCxDLENBRUQ7OztBQUNBLFNBQVNFLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxNQUFJQSxRQUFRLENBQUNDLFFBQWIsRUFBdUI7QUFDckIsV0FBT2IsZUFBZSxDQUFDWSxRQUFRLENBQUNYLEVBQVYsRUFBY1csUUFBUSxDQUFDQyxRQUF2QixDQUF0QjtBQUNELEdBRkQsTUFFTztBQUNMLFdBQU9ILGlCQUFpQixDQUFDRSxRQUFRLENBQUNYLEVBQVYsRUFBY1csUUFBUSxDQUFDRSxZQUF2QixDQUFqQixDQUFzRFYsSUFBdEQsQ0FDTCxNQUFNO0FBQ0o7QUFDQTtBQUNELEtBSkksRUFLTCxNQUFNO0FBQ0o7QUFDQSxhQUFPSixlQUFlLENBQUNZLFFBQVEsQ0FBQ1gsRUFBVixFQUFjVyxRQUFRLENBQUNFLFlBQXZCLENBQXRCO0FBQ0QsS0FSSSxDQUFQO0FBVUQ7QUFDRixDLENBRUQ7OztBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRCxDLENBRUQ7OztBQUNBLFNBQVNkLGFBQVQsQ0FBdUJlLElBQXZCLEVBQTZCO0FBQzNCLFNBQU9uQixZQUFZLENBQUNvQixHQUFiLENBQWlCLDBDQUEwQ0QsSUFBM0QsQ0FBUDtBQUNEOztBQUVERSxNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZk4sRUFBQUEsYUFBYSxFQUFFQSxhQURBO0FBRWZKLEVBQUFBLGdCQUFnQixFQUFFQTtBQUZILENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBnb29nbGUgQVBJLlxudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuY29uc3QgaHR0cHNSZXF1ZXN0ID0gcmVxdWlyZSgnLi9odHRwc1JlcXVlc3QnKTtcblxuZnVuY3Rpb24gdmFsaWRhdGVJZFRva2VuKGlkLCB0b2tlbikge1xuICByZXR1cm4gZ29vZ2xlUmVxdWVzdCgndG9rZW5pbmZvP2lkX3Rva2VuPScgKyB0b2tlbikudGhlbihyZXNwb25zZSA9PiB7XG4gICAgaWYgKHJlc3BvbnNlICYmIChyZXNwb25zZS5zdWIgPT0gaWQgfHwgcmVzcG9uc2UudXNlcl9pZCA9PSBpZCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdHb29nbGUgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhUb2tlbihpZCwgdG9rZW4pIHtcbiAgcmV0dXJuIGdvb2dsZVJlcXVlc3QoJ3Rva2VuaW5mbz9hY2Nlc3NfdG9rZW49JyArIHRva2VuKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICBpZiAocmVzcG9uc2UgJiYgKHJlc3BvbnNlLnN1YiA9PSBpZCB8fCByZXNwb25zZS51c2VyX2lkID09IGlkKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ0dvb2dsZSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nXG4gICAgKTtcbiAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyB1c2VyIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSkge1xuICBpZiAoYXV0aERhdGEuaWRfdG9rZW4pIHtcbiAgICByZXR1cm4gdmFsaWRhdGVJZFRva2VuKGF1dGhEYXRhLmlkLCBhdXRoRGF0YS5pZF90b2tlbik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHZhbGlkYXRlQXV0aFRva2VuKGF1dGhEYXRhLmlkLCBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pLnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIC8vIFZhbGlkYXRpb24gd2l0aCBhdXRoIHRva2VuIHdvcmtlZFxuICAgICAgICByZXR1cm47XG4gICAgICB9LFxuICAgICAgKCkgPT4ge1xuICAgICAgICAvLyBUcnkgd2l0aCB0aGUgaWRfdG9rZW4gcGFyYW1cbiAgICAgICAgcmV0dXJuIHZhbGlkYXRlSWRUb2tlbihhdXRoRGF0YS5pZCwgYXV0aERhdGEuYWNjZXNzX3Rva2VuKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgYXBpIHJlcXVlc3RzXG5mdW5jdGlvbiBnb29nbGVSZXF1ZXN0KHBhdGgpIHtcbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5nZXQoJ2h0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92My8nICsgcGF0aCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/gpgames.js b/lib/Adapters/Auth/gpgames.js new file mode 100644 index 0000000000..57d5686d06 --- /dev/null +++ b/lib/Adapters/Auth/gpgames.js @@ -0,0 +1,35 @@ +"use strict"; + +/* Google Play Game Services +https://developers.google.com/games/services/web/api/players/get + +const authData = { + id: 'playerId', + access_token: 'token', +}; +*/ +const { + Parse +} = require('parse/node'); + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills if this user id is valid. + + +async function validateAuthData(authData) { + const response = await httpsRequest.get(`https://www.googleapis.com/games/v1/players/${authData.id}?access_token=${authData.access_token}`); + + if (!(response && response.playerId === authData.id)) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Google Play Games Services - authData is invalid for this user.'); + } +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} + +module.exports = { + validateAppId, + validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dwZ2FtZXMuanMiXSwibmFtZXMiOlsiUGFyc2UiLCJyZXF1aXJlIiwiaHR0cHNSZXF1ZXN0IiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwicmVzcG9uc2UiLCJnZXQiLCJpZCIsImFjY2Vzc190b2tlbiIsInBsYXllcklkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7Ozs7QUFRQSxNQUFNO0FBQUVBLEVBQUFBO0FBQUYsSUFBWUMsT0FBTyxDQUFDLFlBQUQsQ0FBekI7O0FBQ0EsTUFBTUMsWUFBWSxHQUFHRCxPQUFPLENBQUMsZ0JBQUQsQ0FBNUIsQyxDQUVBOzs7QUFDQSxlQUFlRSxnQkFBZixDQUFnQ0MsUUFBaEMsRUFBMEM7QUFDeEMsUUFBTUMsUUFBUSxHQUFHLE1BQU1ILFlBQVksQ0FBQ0ksR0FBYixDQUNwQiwrQ0FBOENGLFFBQVEsQ0FBQ0csRUFBRyxpQkFBZ0JILFFBQVEsQ0FBQ0ksWUFBYSxFQUQ1RSxDQUF2Qjs7QUFHQSxNQUFJLEVBQUVILFFBQVEsSUFBSUEsUUFBUSxDQUFDSSxRQUFULEtBQXNCTCxRQUFRLENBQUNHLEVBQTdDLENBQUosRUFBc0Q7QUFDcEQsVUFBTSxJQUFJUCxLQUFLLENBQUNVLEtBQVYsQ0FDSlYsS0FBSyxDQUFDVSxLQUFOLENBQVlDLGdCQURSLEVBRUosaUVBRkksQ0FBTjtBQUlEO0FBQ0YsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0Q7O0FBRURDLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmSixFQUFBQSxhQURlO0FBRWZULEVBQUFBO0FBRmUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBHb29nbGUgUGxheSBHYW1lIFNlcnZpY2VzXG5odHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9nYW1lcy9zZXJ2aWNlcy93ZWIvYXBpL3BsYXllcnMvZ2V0XG5cbmNvbnN0IGF1dGhEYXRhID0ge1xuICBpZDogJ3BsYXllcklkJyxcbiAgYWNjZXNzX3Rva2VuOiAndG9rZW4nLFxufTtcbiovXG5jb25zdCB7IFBhcnNlIH0gPSByZXF1aXJlKCdwYXJzZS9ub2RlJyk7XG5jb25zdCBodHRwc1JlcXVlc3QgPSByZXF1aXJlKCcuL2h0dHBzUmVxdWVzdCcpO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmFzeW5jIGZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBodHRwc1JlcXVlc3QuZ2V0KFxuICAgIGBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9nYW1lcy92MS9wbGF5ZXJzLyR7YXV0aERhdGEuaWR9P2FjY2Vzc190b2tlbj0ke2F1dGhEYXRhLmFjY2Vzc190b2tlbn1gXG4gICk7XG4gIGlmICghKHJlc3BvbnNlICYmIHJlc3BvbnNlLnBsYXllcklkID09PSBhdXRoRGF0YS5pZCkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ0dvb2dsZSBQbGF5IEdhbWVzIFNlcnZpY2VzIC0gYXV0aERhdGEgaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICApO1xuICB9XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/httpsRequest.js b/lib/Adapters/Auth/httpsRequest.js new file mode 100644 index 0000000000..ba7cba94ca --- /dev/null +++ b/lib/Adapters/Auth/httpsRequest.js @@ -0,0 +1,47 @@ +"use strict"; + +const https = require('https'); + +function makeCallback(resolve, reject, noJSON) { + return function (res) { + let data = ''; + res.on('data', chunk => { + data += chunk; + }); + res.on('end', () => { + if (noJSON) { + return resolve(data); + } + + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + + resolve(data); + }); + res.on('error', reject); + }; +} + +function get(options, noJSON = false) { + return new Promise((resolve, reject) => { + https.get(options, makeCallback(resolve, reject, noJSON)).on('error', reject); + }); +} + +function request(options, postData) { + return new Promise((resolve, reject) => { + const req = https.request(options, makeCallback(resolve, reject)); + req.on('error', reject); + req.write(postData); + req.end(); + }); +} + +module.exports = { + get, + request +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2h0dHBzUmVxdWVzdC5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJtYWtlQ2FsbGJhY2siLCJyZXNvbHZlIiwicmVqZWN0Iiwibm9KU09OIiwicmVzIiwiZGF0YSIsIm9uIiwiY2h1bmsiLCJKU09OIiwicGFyc2UiLCJlIiwiZ2V0Iiwib3B0aW9ucyIsIlByb21pc2UiLCJyZXF1ZXN0IiwicG9zdERhdGEiLCJyZXEiLCJ3cml0ZSIsImVuZCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUEsTUFBTUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsT0FBRCxDQUFyQjs7QUFFQSxTQUFTQyxZQUFULENBQXNCQyxPQUF0QixFQUErQkMsTUFBL0IsRUFBdUNDLE1BQXZDLEVBQStDO0FBQzdDLFNBQU8sVUFBU0MsR0FBVCxFQUFjO0FBQ25CLFFBQUlDLElBQUksR0FBRyxFQUFYO0FBQ0FELElBQUFBLEdBQUcsQ0FBQ0UsRUFBSixDQUFPLE1BQVAsRUFBZUMsS0FBSyxJQUFJO0FBQ3RCRixNQUFBQSxJQUFJLElBQUlFLEtBQVI7QUFDRCxLQUZEO0FBR0FILElBQUFBLEdBQUcsQ0FBQ0UsRUFBSixDQUFPLEtBQVAsRUFBYyxNQUFNO0FBQ2xCLFVBQUlILE1BQUosRUFBWTtBQUNWLGVBQU9GLE9BQU8sQ0FBQ0ksSUFBRCxDQUFkO0FBQ0Q7O0FBQ0QsVUFBSTtBQUNGQSxRQUFBQSxJQUFJLEdBQUdHLElBQUksQ0FBQ0MsS0FBTCxDQUFXSixJQUFYLENBQVA7QUFDRCxPQUZELENBRUUsT0FBT0ssQ0FBUCxFQUFVO0FBQ1YsZUFBT1IsTUFBTSxDQUFDUSxDQUFELENBQWI7QUFDRDs7QUFDRFQsTUFBQUEsT0FBTyxDQUFDSSxJQUFELENBQVA7QUFDRCxLQVZEO0FBV0FELElBQUFBLEdBQUcsQ0FBQ0UsRUFBSixDQUFPLE9BQVAsRUFBZ0JKLE1BQWhCO0FBQ0QsR0FqQkQ7QUFrQkQ7O0FBRUQsU0FBU1MsR0FBVCxDQUFhQyxPQUFiLEVBQXNCVCxNQUFNLEdBQUcsS0FBL0IsRUFBc0M7QUFDcEMsU0FBTyxJQUFJVSxPQUFKLENBQVksQ0FBQ1osT0FBRCxFQUFVQyxNQUFWLEtBQXFCO0FBQ3RDSixJQUFBQSxLQUFLLENBQ0ZhLEdBREgsQ0FDT0MsT0FEUCxFQUNnQlosWUFBWSxDQUFDQyxPQUFELEVBQVVDLE1BQVYsRUFBa0JDLE1BQWxCLENBRDVCLEVBRUdHLEVBRkgsQ0FFTSxPQUZOLEVBRWVKLE1BRmY7QUFHRCxHQUpNLENBQVA7QUFLRDs7QUFFRCxTQUFTWSxPQUFULENBQWlCRixPQUFqQixFQUEwQkcsUUFBMUIsRUFBb0M7QUFDbEMsU0FBTyxJQUFJRixPQUFKLENBQVksQ0FBQ1osT0FBRCxFQUFVQyxNQUFWLEtBQXFCO0FBQ3RDLFVBQU1jLEdBQUcsR0FBR2xCLEtBQUssQ0FBQ2dCLE9BQU4sQ0FBY0YsT0FBZCxFQUF1QlosWUFBWSxDQUFDQyxPQUFELEVBQVVDLE1BQVYsQ0FBbkMsQ0FBWjtBQUNBYyxJQUFBQSxHQUFHLENBQUNWLEVBQUosQ0FBTyxPQUFQLEVBQWdCSixNQUFoQjtBQUNBYyxJQUFBQSxHQUFHLENBQUNDLEtBQUosQ0FBVUYsUUFBVjtBQUNBQyxJQUFBQSxHQUFHLENBQUNFLEdBQUo7QUFDRCxHQUxNLENBQVA7QUFNRDs7QUFFREMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQUVULEVBQUFBLEdBQUY7QUFBT0csRUFBQUE7QUFBUCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGh0dHBzID0gcmVxdWlyZSgnaHR0cHMnKTtcblxuZnVuY3Rpb24gbWFrZUNhbGxiYWNrKHJlc29sdmUsIHJlamVjdCwgbm9KU09OKSB7XG4gIHJldHVybiBmdW5jdGlvbihyZXMpIHtcbiAgICBsZXQgZGF0YSA9ICcnO1xuICAgIHJlcy5vbignZGF0YScsIGNodW5rID0+IHtcbiAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgfSk7XG4gICAgcmVzLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICBpZiAobm9KU09OKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlKGRhdGEpO1xuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiByZWplY3QoZSk7XG4gICAgICB9XG4gICAgICByZXNvbHZlKGRhdGEpO1xuICAgIH0pO1xuICAgIHJlcy5vbignZXJyb3InLCByZWplY3QpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXQob3B0aW9ucywgbm9KU09OID0gZmFsc2UpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBodHRwc1xuICAgICAgLmdldChvcHRpb25zLCBtYWtlQ2FsbGJhY2socmVzb2x2ZSwgcmVqZWN0LCBub0pTT04pKVxuICAgICAgLm9uKCdlcnJvcicsIHJlamVjdCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZXF1ZXN0KG9wdGlvbnMsIHBvc3REYXRhKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgcmVxID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBtYWtlQ2FsbGJhY2socmVzb2x2ZSwgcmVqZWN0KSk7XG4gICAgcmVxLm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgcmVxLndyaXRlKHBvc3REYXRhKTtcbiAgICByZXEuZW5kKCk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHsgZ2V0LCByZXF1ZXN0IH07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/index.js b/lib/Adapters/Auth/index.js new file mode 100755 index 0000000000..7cf18f7aac --- /dev/null +++ b/lib/Adapters/Auth/index.js @@ -0,0 +1,173 @@ +"use strict"; + +var _AdapterLoader = _interopRequireDefault(require("../AdapterLoader")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const apple = require('./apple'); + +const gcenter = require('./gcenter'); + +const gpgames = require('./gpgames'); + +const facebook = require('./facebook'); + +const facebookaccountkit = require('./facebookaccountkit'); + +const instagram = require('./instagram'); + +const linkedin = require('./linkedin'); + +const meetup = require('./meetup'); + +const google = require('./google'); + +const github = require('./github'); + +const twitter = require('./twitter'); + +const spotify = require('./spotify'); + +const digits = require('./twitter'); // digits tokens are validated by twitter + + +const janrainengage = require('./janrainengage'); + +const janraincapture = require('./janraincapture'); + +const line = require('./line'); + +const vkontakte = require('./vkontakte'); + +const qq = require('./qq'); + +const wechat = require('./wechat'); + +const weibo = require('./weibo'); + +const oauth2 = require('./oauth2'); + +const phantauth = require('./phantauth'); + +const microsoft = require('./microsoft'); + +const ldap = require('./ldap'); + +const anonymous = { + validateAuthData: () => { + return Promise.resolve(); + }, + validateAppId: () => { + return Promise.resolve(); + } +}; +const providers = { + apple, + gcenter, + gpgames, + facebook, + facebookaccountkit, + instagram, + linkedin, + meetup, + google, + github, + twitter, + spotify, + anonymous, + digits, + janrainengage, + janraincapture, + line, + vkontakte, + qq, + wechat, + weibo, + phantauth, + microsoft, + ldap +}; + +function authDataValidator(adapter, appIds, options) { + return function (authData) { + return adapter.validateAuthData(authData, options).then(() => { + if (appIds) { + return adapter.validateAppId(appIds, authData, options); + } + + return Promise.resolve(); + }); + }; +} + +function loadAuthAdapter(provider, authOptions) { + let defaultAdapter = providers[provider]; + const providerOptions = authOptions[provider]; + + if (providerOptions && Object.prototype.hasOwnProperty.call(providerOptions, 'oauth2') && providerOptions['oauth2'] === true) { + defaultAdapter = oauth2; + } + + if (!defaultAdapter && !providerOptions) { + return; + } + + const adapter = Object.assign({}, defaultAdapter); + const appIds = providerOptions ? providerOptions.appIds : undefined; // Try the configuration methods + + if (providerOptions) { + const optionalAdapter = (0, _AdapterLoader.default)(providerOptions, undefined, providerOptions); + + if (optionalAdapter) { + ['validateAuthData', 'validateAppId'].forEach(key => { + if (optionalAdapter[key]) { + adapter[key] = optionalAdapter[key]; + } + }); + } + } // TODO: create a new module from validateAdapter() in + // src/Controllers/AdaptableController.js so we can use it here for adapter + // validation based on the src/Adapters/Auth/AuthAdapter.js expected class + // signature. + + + if (!adapter.validateAuthData || !adapter.validateAppId) { + return; + } + + return { + adapter, + appIds, + providerOptions + }; +} + +module.exports = function (authOptions = {}, enableAnonymousUsers = true) { + let _enableAnonymousUsers = enableAnonymousUsers; + + const setEnableAnonymousUsers = function (enable) { + _enableAnonymousUsers = enable; + }; // To handle the test cases on configuration + + + const getValidatorForProvider = function (provider) { + if (provider === 'anonymous' && !_enableAnonymousUsers) { + return; + } + + const { + adapter, + appIds, + providerOptions + } = loadAuthAdapter(provider, authOptions); + return authDataValidator(adapter, appIds, providerOptions); + }; + + return Object.freeze({ + getValidatorForProvider, + setEnableAnonymousUsers + }); +}; + +module.exports.loadAuthAdapter = loadAuthAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2luZGV4LmpzIl0sIm5hbWVzIjpbImFwcGxlIiwicmVxdWlyZSIsImdjZW50ZXIiLCJncGdhbWVzIiwiZmFjZWJvb2siLCJmYWNlYm9va2FjY291bnRraXQiLCJpbnN0YWdyYW0iLCJsaW5rZWRpbiIsIm1lZXR1cCIsImdvb2dsZSIsImdpdGh1YiIsInR3aXR0ZXIiLCJzcG90aWZ5IiwiZGlnaXRzIiwiamFucmFpbmVuZ2FnZSIsImphbnJhaW5jYXB0dXJlIiwibGluZSIsInZrb250YWt0ZSIsInFxIiwid2VjaGF0Iiwid2VpYm8iLCJvYXV0aDIiLCJwaGFudGF1dGgiLCJtaWNyb3NvZnQiLCJsZGFwIiwiYW5vbnltb3VzIiwidmFsaWRhdGVBdXRoRGF0YSIsIlByb21pc2UiLCJyZXNvbHZlIiwidmFsaWRhdGVBcHBJZCIsInByb3ZpZGVycyIsImF1dGhEYXRhVmFsaWRhdG9yIiwiYWRhcHRlciIsImFwcElkcyIsIm9wdGlvbnMiLCJhdXRoRGF0YSIsInRoZW4iLCJsb2FkQXV0aEFkYXB0ZXIiLCJwcm92aWRlciIsImF1dGhPcHRpb25zIiwiZGVmYXVsdEFkYXB0ZXIiLCJwcm92aWRlck9wdGlvbnMiLCJPYmplY3QiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJhc3NpZ24iLCJ1bmRlZmluZWQiLCJvcHRpb25hbEFkYXB0ZXIiLCJmb3JFYWNoIiwia2V5IiwibW9kdWxlIiwiZXhwb3J0cyIsImVuYWJsZUFub255bW91c1VzZXJzIiwiX2VuYWJsZUFub255bW91c1VzZXJzIiwic2V0RW5hYmxlQW5vbnltb3VzVXNlcnMiLCJlbmFibGUiLCJnZXRWYWxpZGF0b3JGb3JQcm92aWRlciIsImZyZWV6ZSJdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7OztBQUVBLE1BQU1BLEtBQUssR0FBR0MsT0FBTyxDQUFDLFNBQUQsQ0FBckI7O0FBQ0EsTUFBTUMsT0FBTyxHQUFHRCxPQUFPLENBQUMsV0FBRCxD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OztBQXlCQUosTUFBTSxDQUFDQyxPQUFQLENBQWVmLGVBQWYsR0FBaUNBLGVBQWpDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGxvYWRBZGFwdGVyIGZyb20gJy4uL0FkYXB0ZXJMb2FkZXInO1xuXG5jb25zdCBhcHBsZSA9IHJlcXVpcmUoJy4vYXBwbGUnKTtcbmNvbnN0IGdjZW50ZXIgPSByZXF1aXJlKCcuL2djZW50ZXInKTtcbmNvbnN0IGdwZ2FtZXMgPSByZXF1aXJlKCcuL2dwZ2FtZXMnKTtcbmNvbnN0IGZhY2Vib29rID0gcmVxdWlyZSgnLi9mYWNlYm9vaycpO1xuY29uc3QgZmFjZWJvb2thY2NvdW50a2l0ID0gcmVxdWlyZSgnLi9mYWNlYm9va2FjY291bnRraXQnKTtcbmNvbnN0IGluc3RhZ3JhbSA9IHJlcXVpcmUoJy4vaW5zdGFncmFtJyk7XG5jb25zdCBsaW5rZWRpbiA9IHJlcXVpcmUoJy4vbGlua2VkaW4nKTtcbmNvbnN0IG1lZXR1cCA9IHJlcXVpcmUoJy4vbWVldHVwJyk7XG5jb25zdCBnb29nbGUgPSByZXF1aXJlKCcuL2dvb2dsZScpO1xuY29uc3QgZ2l0aHViID0gcmVxdWlyZSgnLi9naXRodWInKTtcbmNvbnN0IHR3aXR0ZXIgPSByZXF1aXJlKCcuL3R3aXR0ZXInKTtcbmNvbnN0IHNwb3RpZnkgPSByZXF1aXJlKCcuL3Nwb3RpZnknKTtcbmNvbnN0IGRpZ2l0cyA9IHJlcXVpcmUoJy4vdHdpdHRlcicpOyAvLyBkaWdpdHMgdG9rZW5zIGFyZSB2YWxpZGF0ZWQgYnkgdHdpdHRlclxuY29uc3QgamFucmFpbmVuZ2FnZSA9IHJlcXVpcmUoJy4vamFucmFpbmVuZ2FnZScpO1xuY29uc3QgamFucmFpbmNhcHR1cmUgPSByZXF1aXJlKCcuL2phbnJhaW5jYXB0dXJlJyk7XG5jb25zdCBsaW5lID0gcmVxdWlyZSgnLi9saW5lJyk7XG5jb25zdCB2a29udGFrdGUgPSByZXF1aXJlKCcuL3Zrb250YWt0ZScpO1xuY29uc3QgcXEgPSByZXF1aXJlKCcuL3FxJyk7XG5jb25zdCB3ZWNoYXQgPSByZXF1aXJlKCcuL3dlY2hhdCcpO1xuY29uc3Qgd2VpYm8gPSByZXF1aXJlKCcuL3dlaWJvJyk7XG5jb25zdCBvYXV0aDIgPSByZXF1aXJlKCcuL29hdXRoMicpO1xuY29uc3QgcGhhbnRhdXRoID0gcmVxdWlyZSgnLi9waGFudGF1dGgnKTtcbmNvbnN0IG1pY3Jvc29mdCA9IHJlcXVpcmUoJy4vbWljcm9zb2Z0Jyk7XG5jb25zdCBsZGFwID0gcmVxdWlyZSgnLi9sZGFwJyk7XG5cbmNvbnN0IGFub255bW91cyA9IHtcbiAgdmFsaWRhdGVBdXRoRGF0YTogKCkgPT4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfSxcbiAgdmFsaWRhdGVBcHBJZDogKCkgPT4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfSxcbn07XG5cbmNvbnN0IHByb3ZpZGVycyA9IHtcbiAgYXBwbGUsXG4gIGdjZW50ZXIsXG4gIGdwZ2FtZXMsXG4gIGZhY2Vib29rLFxuICBmYWNlYm9va2FjY291bnRraXQsXG4gIGluc3RhZ3JhbSxcbiAgbGlua2VkaW4sXG4gIG1lZXR1cCxcbiAgZ29vZ2xlLFxuICBnaXRodWIsXG4gIHR3aXR0ZXIsXG4gIHNwb3RpZnksXG4gIGFub255bW91cyxcbiAgZGlnaXRzLFxuICBqYW5yYWluZW5nYWdlLFxuICBqYW5yYWluY2FwdHVyZSxcbiAgbGluZSxcbiAgdmtvbnRha3RlLFxuICBxcSxcbiAgd2VjaGF0LFxuICB3ZWlibyxcbiAgcGhhbnRhdXRoLFxuICBtaWNyb3NvZnQsXG4gIGxkYXAsXG59O1xuXG5mdW5jdGlvbiBhdXRoRGF0YVZhbGlkYXRvcihhZGFwdGVyLCBhcHBJZHMsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKGF1dGhEYXRhKSB7XG4gICAgcmV0dXJuIGFkYXB0ZXIudmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSwgb3B0aW9ucykudGhlbigoKSA9PiB7XG4gICAgICBpZiAoYXBwSWRzKSB7XG4gICAgICAgIHJldHVybiBhZGFwdGVyLnZhbGlkYXRlQXBwSWQoYXBwSWRzLCBhdXRoRGF0YSwgb3B0aW9ucyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGxvYWRBdXRoQWRhcHRlcihwcm92aWRlciwgYXV0aE9wdGlvbnMpIHtcbiAgbGV0IGRlZmF1bHRBZGFwdGVyID0gcHJvdmlkZXJzW3Byb3ZpZGVyXTtcbiAgY29uc3QgcHJvdmlkZXJPcHRpb25zID0gYXV0aE9wdGlvbnNbcHJvdmlkZXJdO1xuICBpZiAoXG4gICAgcHJvdmlkZXJPcHRpb25zICYmXG4gICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHByb3ZpZGVyT3B0aW9ucywgJ29hdXRoMicpICYmXG4gICAgcHJvdmlkZXJPcHRpb25zWydvYXV0aDInXSA9PT0gdHJ1ZVxuICApIHtcbiAgICBkZWZhdWx0QWRhcHRlciA9IG9hdXRoMjtcbiAgfVxuXG4gIGlmICghZGVmYXVsdEFkYXB0ZXIgJiYgIXByb3ZpZGVyT3B0aW9ucykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGFkYXB0ZXIgPSBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0QWRhcHRlcik7XG4gIGNvbnN0IGFwcElkcyA9IHByb3ZpZGVyT3B0aW9ucyA/IHByb3ZpZGVyT3B0aW9ucy5hcHBJZHMgOiB1bmRlZmluZWQ7XG5cbiAgLy8gVHJ5IHRoZSBjb25maWd1cmF0aW9uIG1ldGhvZHNcbiAgaWYgKHByb3ZpZGVyT3B0aW9ucykge1xuICAgIGNvbnN0IG9wdGlvbmFsQWRhcHRlciA9IGxvYWRBZGFwdGVyKFxuICAgICAgcHJvdmlkZXJPcHRpb25zLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgcHJvdmlkZXJPcHRpb25zXG4gICAgKTtcbiAgICBpZiAob3B0aW9uYWxBZGFwdGVyKSB7XG4gICAgICBbJ3ZhbGlkYXRlQXV0aERhdGEnLCAndmFsaWRhdGVBcHBJZCddLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgaWYgKG9wdGlvbmFsQWRhcHRlcltrZXldKSB7XG4gICAgICAgICAgYWRhcHRlcltrZXldID0gb3B0aW9uYWxBZGFwdGVyW2tleV07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRPRE86IGNyZWF0ZSBhIG5ldyBtb2R1bGUgZnJvbSB2YWxpZGF0ZUFkYXB0ZXIoKSBpblxuICAvLyBzcmMvQ29udHJvbGxlcnMvQWRhcHRhYmxlQ29udHJvbGxlci5qcyBzbyB3ZSBjYW4gdXNlIGl0IGhlcmUgZm9yIGFkYXB0ZXJcbiAgLy8gdmFsaWRhdGlvbiBiYXNlZCBvbiB0aGUgc3JjL0FkYXB0ZXJzL0F1dGgvQXV0aEFkYXB0ZXIuanMgZXhwZWN0ZWQgY2xhc3NcbiAgLy8gc2lnbmF0dXJlLlxuICBpZiAoIWFkYXB0ZXIudmFsaWRhdGVBdXRoRGF0YSB8fCAhYWRhcHRlci52YWxpZGF0ZUFwcElkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcmV0dXJuIHsgYWRhcHRlciwgYXBwSWRzLCBwcm92aWRlck9wdGlvbnMgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihhdXRoT3B0aW9ucyA9IHt9LCBlbmFibGVBbm9ueW1vdXNVc2VycyA9IHRydWUpIHtcbiAgbGV0IF9lbmFibGVBbm9ueW1vdXNVc2VycyA9IGVuYWJsZUFub255bW91c1VzZXJzO1xuICBjb25zdCBzZXRFbmFibGVBbm9ueW1vdXNVc2VycyA9IGZ1bmN0aW9uKGVuYWJsZSkge1xuICAgIF9lbmFibGVBbm9ueW1vdXNVc2VycyA9IGVuYWJsZTtcbiAgfTtcbiAgLy8gVG8gaGFuZGxlIHRoZSB0ZXN0IGNhc2VzIG9uIGNvbmZpZ3VyYXRpb25cbiAgY29uc3QgZ2V0VmFsaWRhdG9yRm9yUHJvdmlkZXIgPSBmdW5jdGlvbihwcm92aWRlcikge1xuICAgIGlmIChwcm92aWRlciA9PT0gJ2Fub255bW91cycgJiYgIV9lbmFibGVBbm9ueW1vdXNVc2Vycykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHsgYWRhcHRlciwgYXBwSWRzLCBwcm92aWRlck9wdGlvbnMgfSA9IGxvYWRBdXRoQWRhcHRlcihcbiAgICAgIHByb3ZpZGVyLFxuICAgICAgYXV0aE9wdGlvbnNcbiAgICApO1xuXG4gICAgcmV0dXJuIGF1dGhEYXRhVmFsaWRhdG9yKGFkYXB0ZXIsIGFwcElkcywgcHJvdmlkZXJPcHRpb25zKTtcbiAgfTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgZ2V0VmFsaWRhdG9yRm9yUHJvdmlkZXIsXG4gICAgc2V0RW5hYmxlQW5vbnltb3VzVXNlcnMsXG4gIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMubG9hZEF1dGhBZGFwdGVyID0gbG9hZEF1dGhBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/instagram.js b/lib/Adapters/Auth/instagram.js new file mode 100644 index 0000000000..a12b9e1b6e --- /dev/null +++ b/lib/Adapters/Auth/instagram.js @@ -0,0 +1,33 @@ +"use strict"; + +// Helper functions for accessing the instagram API. +var Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return request('users/self/?access_token=' + authData.access_token).then(response => { + if (response && response.data && response.data.id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Instagram auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(path) { + return httpsRequest.get('https://api.instagram.com/v1/' + path); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2luc3RhZ3JhbS5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJyZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsInJlc3BvbnNlIiwiZGF0YSIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsImdldCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxLQUFLLEdBQUdDLE9BQU8sQ0FBQyxZQUFELENBQVAsQ0FBc0JELEtBQWxDOztBQUNBLE1BQU1FLFlBQVksR0FBR0QsT0FBTyxDQUFDLGdCQUFELENBQTVCLEMsQ0FFQTs7O0FBQ0EsU0FBU0UsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DO0FBQ2xDLFNBQU9DLE9BQU8sQ0FBQyw4QkFBOEJELFFBQVEsQ0FBQ0UsWUFBeEMsQ0FBUCxDQUE2REMsSUFBN0QsQ0FDTEMsUUFBUSxJQUFJO0FBQ1YsUUFBSUEsUUFBUSxJQUFJQSxRQUFRLENBQUNDLElBQXJCLElBQTZCRCxRQUFRLENBQUNDLElBQVQsQ0FBY0MsRUFBZCxJQUFvQk4sUUFBUSxDQUFDTSxFQUE5RCxFQUFrRTtBQUNoRTtBQUNEOztBQUNELFVBQU0sSUFBSVYsS0FBSyxDQUFDVyxLQUFWLENBQ0pYLEtBQUssQ0FBQ1csS0FBTixDQUFZQyxnQkFEUixFQUVKLDBDQUZJLENBQU47QUFJRCxHQVRJLENBQVA7QUFXRCxDLENBRUQ7OztBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRCxDLENBRUQ7OztBQUNBLFNBQVNWLE9BQVQsQ0FBaUJXLElBQWpCLEVBQXVCO0FBQ3JCLFNBQU9kLFlBQVksQ0FBQ2UsR0FBYixDQUFpQixrQ0FBa0NELElBQW5ELENBQVA7QUFDRDs7QUFFREUsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZOLEVBQUFBLGFBQWEsRUFBRUEsYUFEQTtBQUVmVixFQUFBQSxnQkFBZ0IsRUFBRUE7QUFGSCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgaW5zdGFncmFtIEFQSS5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoJ3VzZXJzL3NlbGYvP2FjY2Vzc190b2tlbj0nICsgYXV0aERhdGEuYWNjZXNzX3Rva2VuKS50aGVuKFxuICAgIHJlc3BvbnNlID0+IHtcbiAgICAgIGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5kYXRhICYmIHJlc3BvbnNlLmRhdGEuaWQgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnSW5zdGFncmFtIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICAgICk7XG4gICAgfVxuICApO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIHJlcXVlc3QocGF0aCkge1xuICByZXR1cm4gaHR0cHNSZXF1ZXN0LmdldCgnaHR0cHM6Ly9hcGkuaW5zdGFncmFtLmNvbS92MS8nICsgcGF0aCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/janraincapture.js b/lib/Adapters/Auth/janraincapture.js new file mode 100644 index 0000000000..d113cc5285 --- /dev/null +++ b/lib/Adapters/Auth/janraincapture.js @@ -0,0 +1,46 @@ +"use strict"; + +// Helper functions for accessing the Janrain Capture API. +var Parse = require('parse/node').Parse; + +var querystring = require('querystring'); + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData, options) { + return request(options.janrain_capture_host, authData.access_token).then(data => { + //successful response will have a "stat" (status) of 'ok' and a result node that stores the uuid, because that's all we asked for + //see: https://docs.janrain.com/api/registration/entity/#entity + if (data && data.stat == 'ok' && data.result == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Janrain capture auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + //no-op + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(host, access_token) { + var query_string_data = querystring.stringify({ + access_token: access_token, + attribute_name: 'uuid' // we only need to pull the uuid for this access token to make sure it matches + + }); + return httpsRequest.get({ + host: host, + path: '/entity?' + query_string_data + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2phbnJhaW5jYXB0dXJlLmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsInF1ZXJ5c3RyaW5nIiwiaHR0cHNSZXF1ZXN0IiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwib3B0aW9ucyIsInJlcXVlc3QiLCJqYW5yYWluX2NhcHR1cmVfaG9zdCIsImFjY2Vzc190b2tlbiIsInRoZW4iLCJkYXRhIiwic3RhdCIsInJlc3VsdCIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwiaG9zdCIsInF1ZXJ5X3N0cmluZ19kYXRhIiwic3RyaW5naWZ5IiwiYXR0cmlidXRlX25hbWUiLCJnZXQiLCJwYXRoIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLEtBQUssR0FBR0MsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkQsS0FBbEM7O0FBQ0EsSUFBSUUsV0FBVyxHQUFHRCxPQUFPLENBQUMsYUFBRCxDQUF6Qjs7QUFDQSxNQUFNRSxZQUFZLEdBQUdGLE9BQU8sQ0FBQyxnQkFBRCxDQUE1QixDLENBRUE7OztBQUNBLFNBQVNHLGdCQUFULENBQTBCQyxRQUExQixFQUFvQ0MsT0FBcEMsRUFBNkM7QUFDM0MsU0FBT0MsT0FBTyxDQUFDRCxPQUFPLENBQUNFLG9CQUFULEVBQStCSCxRQUFRLENBQUNJLFlBQXhDLENBQVAsQ0FBNkRDLElBQTdELENBQ0xDLElBQUksSUFBSTtBQUNOO0FBQ0E7QUFDQSxRQUFJQSxJQUFJLElBQUlBLElBQUksQ0FBQ0MsSUFBTCxJQUFhLElBQXJCLElBQTZCRCxJQUFJLENBQUNFLE1BQUwsSUFBZVIsUUFBUSxDQUFDUyxFQUF6RCxFQUE2RDtBQUMzRDtBQUNEOztBQUNELFVBQU0sSUFBSWQsS0FBSyxDQUFDZSxLQUFWLENBQ0pmLEtBQUssQ0FBQ2UsS0FBTixDQUFZQyxnQkFEUixFQUVKLGdEQUZJLENBQU47QUFJRCxHQVhJLENBQVA7QUFhRCxDLENBRUQ7OztBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkI7QUFDQSxTQUFPQyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNELEMsQ0FFRDs7O0FBQ0EsU0FBU1osT0FBVCxDQUFpQmEsSUFBakIsRUFBdUJYLFlBQXZCLEVBQXFDO0FBQ25DLE1BQUlZLGlCQUFpQixHQUFHbkIsV0FBVyxDQUFDb0IsU0FBWixDQUFzQjtBQUM1Q2IsSUFBQUEsWUFBWSxFQUFFQSxZQUQ4QjtBQUU1Q2MsSUFBQUEsY0FBYyxFQUFFLE1BRjRCLENBRXBCOztBQUZvQixHQUF0QixDQUF4QjtBQUtBLFNBQU9wQixZQUFZLENBQUNxQixHQUFiLENBQWlCO0FBQUVKLElBQUFBLElBQUksRUFBRUEsSUFBUjtBQUFjSyxJQUFBQSxJQUFJLEVBQUUsYUFBYUo7QUFBakMsR0FBakIsQ0FBUDtBQUNEOztBQUVESyxNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZlYsRUFBQUEsYUFBYSxFQUFFQSxhQURBO0FBRWZiLEVBQUFBLGdCQUFnQixFQUFFQTtBQUZILENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBKYW5yYWluIENhcHR1cmUgQVBJLlxudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xudmFyIHF1ZXJ5c3RyaW5nID0gcmVxdWlyZSgncXVlcnlzdHJpbmcnKTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHJlcXVlc3Qob3B0aW9ucy5qYW5yYWluX2NhcHR1cmVfaG9zdCwgYXV0aERhdGEuYWNjZXNzX3Rva2VuKS50aGVuKFxuICAgIGRhdGEgPT4ge1xuICAgICAgLy9zdWNjZXNzZnVsIHJlc3BvbnNlIHdpbGwgaGF2ZSBhIFwic3RhdFwiIChzdGF0dXMpIG9mICdvaycgYW5kIGEgcmVzdWx0IG5vZGUgdGhhdCBzdG9yZXMgdGhlIHV1aWQsIGJlY2F1c2UgdGhhdCdzIGFsbCB3ZSBhc2tlZCBmb3JcbiAgICAgIC8vc2VlOiBodHRwczovL2RvY3MuamFucmFpbi5jb20vYXBpL3JlZ2lzdHJhdGlvbi9lbnRpdHkvI2VudGl0eVxuICAgICAgaWYgKGRhdGEgJiYgZGF0YS5zdGF0ID09ICdvaycgJiYgZGF0YS5yZXN1bHQgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnSmFucmFpbiBjYXB0dXJlIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICAgICk7XG4gICAgfVxuICApO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIC8vbm8tb3BcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChob3N0LCBhY2Nlc3NfdG9rZW4pIHtcbiAgdmFyIHF1ZXJ5X3N0cmluZ19kYXRhID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHtcbiAgICBhY2Nlc3NfdG9rZW46IGFjY2Vzc190b2tlbixcbiAgICBhdHRyaWJ1dGVfbmFtZTogJ3V1aWQnLCAvLyB3ZSBvbmx5IG5lZWQgdG8gcHVsbCB0aGUgdXVpZCBmb3IgdGhpcyBhY2Nlc3MgdG9rZW4gdG8gbWFrZSBzdXJlIGl0IG1hdGNoZXNcbiAgfSk7XG5cbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5nZXQoeyBob3N0OiBob3N0LCBwYXRoOiAnL2VudGl0eT8nICsgcXVlcnlfc3RyaW5nX2RhdGEgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/janrainengage.js b/lib/Adapters/Auth/janrainengage.js new file mode 100644 index 0000000000..d7c4774377 --- /dev/null +++ b/lib/Adapters/Auth/janrainengage.js @@ -0,0 +1,52 @@ +"use strict"; + +// Helper functions for accessing the Janrain Engage API. +var httpsRequest = require('./httpsRequest'); + +var Parse = require('parse/node').Parse; + +var querystring = require('querystring'); // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData, options) { + return apiRequest(options.api_key, authData.auth_token).then(data => { + //successful response will have a "stat" (status) of 'ok' and a profile node with an identifier + //see: http://developers.janrain.com/overview/social-login/identity-providers/user-profile-data/#normalized-user-profile-data + if (data && data.stat == 'ok' && data.profile.identifier == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Janrain engage auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + //no-op + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function apiRequest(api_key, auth_token) { + var post_data = querystring.stringify({ + token: auth_token, + apiKey: api_key, + format: 'json' + }); + var post_options = { + host: 'rpxnow.com', + path: '/api/v2/auth_info', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': post_data.length + } + }; + return httpsRequest.request(post_options, post_data); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2phbnJhaW5lbmdhZ2UuanMiXSwibmFtZXMiOlsiaHR0cHNSZXF1ZXN0IiwicmVxdWlyZSIsIlBhcnNlIiwicXVlcnlzdHJpbmciLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJvcHRpb25zIiwiYXBpUmVxdWVzdCIsImFwaV9rZXkiLCJhdXRoX3Rva2VuIiwidGhlbiIsImRhdGEiLCJzdGF0IiwicHJvZmlsZSIsImlkZW50aWZpZXIiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBvc3RfZGF0YSIsInN0cmluZ2lmeSIsInRva2VuIiwiYXBpS2V5IiwiZm9ybWF0IiwicG9zdF9vcHRpb25zIiwiaG9zdCIsInBhdGgiLCJtZXRob2QiLCJoZWFkZXJzIiwibGVuZ3RoIiwicmVxdWVzdCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxZQUFZLEdBQUdDLE9BQU8sQ0FBQyxnQkFBRCxDQUExQjs7QUFDQSxJQUFJQyxLQUFLLEdBQUdELE9BQU8sQ0FBQyxZQUFELENBQVAsQ0FBc0JDLEtBQWxDOztBQUNBLElBQUlDLFdBQVcsR0FBR0YsT0FBTyxDQUFDLGFBQUQsQ0FBekIsQyxDQUVBOzs7QUFDQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQXBDLEVBQTZDO0FBQzNDLFNBQU9DLFVBQVUsQ0FBQ0QsT0FBTyxDQUFDRSxPQUFULEVBQWtCSCxRQUFRLENBQUNJLFVBQTNCLENBQVYsQ0FBaURDLElBQWpELENBQXNEQyxJQUFJLElBQUk7QUFDbkU7QUFDQTtBQUNBLFFBQUlBLElBQUksSUFBSUEsSUFBSSxDQUFDQyxJQUFMLElBQWEsSUFBckIsSUFBNkJELElBQUksQ0FBQ0UsT0FBTCxDQUFhQyxVQUFiLElBQTJCVCxRQUFRLENBQUNVLEVBQXJFLEVBQXlFO0FBQ3ZFO0FBQ0Q7O0FBQ0QsVUFBTSxJQUFJYixLQUFLLENBQUNjLEtBQVYsQ0FDSmQsS0FBSyxDQUFDYyxLQUFOLENBQVlDLGdCQURSLEVBRUosK0NBRkksQ0FBTjtBQUlELEdBVk0sQ0FBUDtBQVdELEMsQ0FFRDs7O0FBQ0EsU0FBU0MsYUFBVCxHQUF5QjtBQUN2QjtBQUNBLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTYixVQUFULENBQW9CQyxPQUFwQixFQUE2QkMsVUFBN0IsRUFBeUM7QUFDdkMsTUFBSVksU0FBUyxHQUFHbEIsV0FBVyxDQUFDbUIsU0FBWixDQUFzQjtBQUNwQ0MsSUFBQUEsS0FBSyxFQUFFZCxVQUQ2QjtBQUVwQ2UsSUFBQUEsTUFBTSxFQUFFaEIsT0FGNEI7QUFHcENpQixJQUFBQSxNQUFNLEVBQUU7QUFINEIsR0FBdEIsQ0FBaEI7QUFNQSxNQUFJQyxZQUFZLEdBQUc7QUFDakJDLElBQUFBLElBQUksRUFBRSxZQURXO0FBRWpCQyxJQUFBQSxJQUFJLEVBQUUsbUJBRlc7QUFHakJDLElBQUFBLE1BQU0sRUFBRSxNQUhTO0FBSWpCQyxJQUFBQSxPQUFPLEVBQUU7QUFDUCxzQkFBZ0IsbUNBRFQ7QUFFUCx3QkFBa0JULFNBQVMsQ0FBQ1U7QUFGckI7QUFKUSxHQUFuQjtBQVVBLFNBQU8vQixZQUFZLENBQUNnQyxPQUFiLENBQXFCTixZQUFyQixFQUFtQ0wsU0FBbkMsQ0FBUDtBQUNEOztBQUVEWSxNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZmhCLEVBQUFBLGFBQWEsRUFBRUEsYUFEQTtBQUVmZCxFQUFBQSxnQkFBZ0IsRUFBRUE7QUFGSCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgSmFucmFpbiBFbmdhZ2UgQVBJLlxudmFyIGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG52YXIgcXVlcnlzdHJpbmcgPSByZXF1aXJlKCdxdWVyeXN0cmluZycpO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gIHJldHVybiBhcGlSZXF1ZXN0KG9wdGlvbnMuYXBpX2tleSwgYXV0aERhdGEuYXV0aF90b2tlbikudGhlbihkYXRhID0+IHtcbiAgICAvL3N1Y2Nlc3NmdWwgcmVzcG9uc2Ugd2lsbCBoYXZlIGEgXCJzdGF0XCIgKHN0YXR1cykgb2YgJ29rJyBhbmQgYSBwcm9maWxlIG5vZGUgd2l0aCBhbiBpZGVudGlmaWVyXG4gICAgLy9zZWU6IGh0dHA6Ly9kZXZlbG9wZXJzLmphbnJhaW4uY29tL292ZXJ2aWV3L3NvY2lhbC1sb2dpbi9pZGVudGl0eS1wcm92aWRlcnMvdXNlci1wcm9maWxlLWRhdGEvI25vcm1hbGl6ZWQtdXNlci1wcm9maWxlLWRhdGFcbiAgICBpZiAoZGF0YSAmJiBkYXRhLnN0YXQgPT0gJ29rJyAmJiBkYXRhLnByb2ZpbGUuaWRlbnRpZmllciA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ0phbnJhaW4gZW5nYWdlIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICApO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICAvL25vLW9wXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIGFwaVJlcXVlc3QoYXBpX2tleSwgYXV0aF90b2tlbikge1xuICB2YXIgcG9zdF9kYXRhID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHtcbiAgICB0b2tlbjogYXV0aF90b2tlbixcbiAgICBhcGlLZXk6IGFwaV9rZXksXG4gICAgZm9ybWF0OiAnanNvbicsXG4gIH0pO1xuXG4gIHZhciBwb3N0X29wdGlvbnMgPSB7XG4gICAgaG9zdDogJ3JweG5vdy5jb20nLFxuICAgIHBhdGg6ICcvYXBpL3YyL2F1dGhfaW5mbycsXG4gICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAgICAgJ0NvbnRlbnQtTGVuZ3RoJzogcG9zdF9kYXRhLmxlbmd0aCxcbiAgICB9LFxuICB9O1xuXG4gIHJldHVybiBodHRwc1JlcXVlc3QucmVxdWVzdChwb3N0X29wdGlvbnMsIHBvc3RfZGF0YSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/ldap.js b/lib/Adapters/Auth/ldap.js new file mode 100644 index 0000000000..4990603518 --- /dev/null +++ b/lib/Adapters/Auth/ldap.js @@ -0,0 +1,83 @@ +"use strict"; + +const ldapjs = require('ldapjs'); + +const Parse = require('parse/node').Parse; + +function validateAuthData(authData, options) { + if (!optionsAreValid(options)) { + return new Promise((_, reject) => { + reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP auth configuration missing')); + }); + } + + const client = ldapjs.createClient({ + url: options.url + }); + const userCn = typeof options.dn === 'string' ? options.dn.replace('{{id}}', authData.id) : `uid=${authData.id},${options.suffix}`; + return new Promise((resolve, reject) => { + client.bind(userCn, authData.password, err => { + if (err) { + client.destroy(err); + return reject(new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAP: Wrong username or password')); + } + + if (typeof options.groupCn === 'string' && typeof options.groupFilter === 'string') { + searchForGroup(client, options, authData.id, resolve, reject); + } else { + client.unbind(); + client.destroy(); + resolve(); + } + }); + }); +} + +function optionsAreValid(options) { + return typeof options === 'object' && typeof options.suffix === 'string' && typeof options.url === 'string' && options.url.startsWith('ldap://'); +} + +function searchForGroup(client, options, id, resolve, reject) { + const filter = options.groupFilter.replace(/{{id}}/gi, id); + const opts = { + scope: 'sub', + filter: filter + }; + let found = false; + client.search(options.suffix, opts, (searchError, res) => { + if (searchError) { + client.unbind(); + client.destroy(); + return reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP group search failed')); + } + + res.on('searchEntry', entry => { + if (entry.object.cn === options.groupCn) { + found = true; + client.unbind(); + client.destroy(); + return resolve(); + } + }); + res.on('end', () => { + if (!found) { + client.unbind(); + client.destroy(); + return reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP: User not in group')); + } + }); + res.on('error', () => { + return reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP group search failed')); + }); + }); +} + +function validateAppId() { + return Promise.resolve(); +} + +module.exports = { + validateAppId, + validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2xkYXAuanMiXSwibmFtZXMiOlsibGRhcGpzIiwicmVxdWlyZSIsIlBhcnNlIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwib3B0aW9ucyIsIm9wdGlvbnNBcmVWYWxpZCIsIlByb21pc2UiLCJfIiwicmVqZWN0IiwiRXJyb3IiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJjbGllbnQiLCJjcmVhdGVDbGllbnQiLCJ1cmwiLCJ1c2VyQ24iLCJkbiIsInJlcGxhY2UiLCJpZCIsInN1ZmZpeCIsInJlc29sdmUiLCJiaW5kIiwicGFzc3dvcmQiLCJlcnIiLCJkZXN0cm95IiwiT0JKRUNUX05PVF9GT1VORCIsImdyb3VwQ24iLCJncm91cEZpbHRlciIsInNlYXJjaEZvckdyb3VwIiwidW5iaW5kIiwic3RhcnRzV2l0aCIsImZpbHRlciIsIm9wdHMiLCJzY29wZSIsImZvdW5kIiwic2VhcmNoIiwic2VhcmNoRXJyb3IiLCJyZXMiLCJvbiIsImVudHJ5Iiwib2JqZWN0IiwiY24iLCJ2YWxpZGF0ZUFwcElkIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQSxNQUFNQSxNQUFNLEdBQUdDLE9BQU8sQ0FBQyxRQUFELENBQXRCOztBQUNBLE1BQU1DLEtBQUssR0FBR0QsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkMsS0FBcEM7O0FBRUEsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DQyxPQUFwQyxFQUE2QztBQUMzQyxNQUFJLENBQUNDLGVBQWUsQ0FBQ0QsT0FBRCxDQUFwQixFQUErQjtBQUM3QixXQUFPLElBQUlFLE9BQUosQ0FBWSxDQUFDQyxDQUFELEVBQUlDLE1BQUosS0FBZTtBQUNoQ0EsTUFBQUEsTUFBTSxDQUNKLElBQUlQLEtBQUssQ0FBQ1EsS0FBVixDQUNFUixLQUFLLENBQUNRLEtBQU4sQ0FBWUMscUJBRGQsRUFFRSxpQ0FGRixDQURJLENBQU47QUFNRCxLQVBN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RUFBeUM7QUFDdkNRLFFBQUFBLEtBQUssR0FBRyxJQUFSO0FBQ0F0QixRQUFBQSxNQUFNLENBQUNpQixNQUFQO0FBQ0FqQixRQUFBQSxNQUFNLENBQUNZLE9BQVA7QUFDQSxlQUFPSixPQUFPLEVBQWQ7QUFDRDtBQUNGLEtBUEQ7QUFRQWlCLElBQUFBLEdBQUcsQ0FBQ0MsRUFBSixDQUFPLEtBQVAsRUFBYyxNQUFNO0FBQ2xCLFVBQUksQ0FBQ0osS0FBTCxFQUFZO0FBQ1Z0QixRQUFBQSxNQUFNLENBQUNpQixNQUFQO0FBQ0FqQixRQUFBQSxNQUFNLENBQUNZLE9BQVA7QUFDQSxlQUFPZixNQUFNLENBQ1gsSUFBSVAsS0FBSyxDQUFDUSxLQUFWLENBQ0VSLEtBQUssQ0FBQ1EsS0FBTixDQUFZQyxxQkFEZCxFQUVFLHlCQUZGLENBRFcsQ0FBYjtBQU1EO0FBQ0YsS0FYRDtBQVlBMEIsSUFBQUEsR0FBRyxDQUFDQyxFQUFKLENBQU8sT0FBUCxFQUFnQixNQUFNO0FBQ3BCLGFBQU83QixNQUFNLENBQ1gsSUFBSVAsS0FBSyxDQUFDUSxLQUFWLENBQ0VSLEtBQUssQ0FBQ1EsS0FBTixDQUFZQyxxQkFEZCxFQUVFLDBCQUZGLENBRFcsQ0FBYjtBQU1ELEtBUEQ7QUFRRCxHQXZDRDtBQXdDRDs7QUFFRCxTQUFTK0IsYUFBVCxHQUF5QjtBQUN2QixTQUFPbkMsT0FBTyxDQUFDYSxPQUFSLEVBQVA7QUFDRDs7QUFFRHVCLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmRixFQUFBQSxhQURlO0FBRWZ2QyxFQUFBQTtBQUZlLENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgbGRhcGpzID0gcmVxdWlyZSgnbGRhcGpzJyk7XG5jb25zdCBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSwgb3B0aW9ucykge1xuICBpZiAoIW9wdGlvbnNBcmVWYWxpZChvcHRpb25zKSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgoXywgcmVqZWN0KSA9PiB7XG4gICAgICByZWplY3QoXG4gICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgICAgJ0xEQVAgYXV0aCBjb25maWd1cmF0aW9uIG1pc3NpbmcnXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBjb25zdCBjbGllbnQgPSBsZGFwanMuY3JlYXRlQ2xpZW50KHsgdXJsOiBvcHRpb25zLnVybCB9KTtcbiAgY29uc3QgdXNlckNuID1cbiAgICB0eXBlb2Ygb3B0aW9ucy5kbiA9PT0gJ3N0cmluZydcbiAgICAgID8gb3B0aW9ucy5kbi5yZXBsYWNlKCd7e2lkfX0nLCBhdXRoRGF0YS5pZClcbiAgICAgIDogYHVpZD0ke2F1dGhEYXRhLmlkfSwke29wdGlvbnMuc3VmZml4fWA7XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjbGllbnQuYmluZCh1c2VyQ24sIGF1dGhEYXRhLnBhc3N3b3JkLCBlcnIgPT4ge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICBjbGllbnQuZGVzdHJveShlcnIpO1xuICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAnTERBUDogV3JvbmcgdXNlcm5hbWUgb3IgcGFzc3dvcmQnXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiBvcHRpb25zLmdyb3VwQ24gPT09ICdzdHJpbmcnICYmXG4gICAgICAgIHR5cGVvZiBvcHRpb25zLmdyb3VwRmlsdGVyID09PSAnc3RyaW5nJ1xuICAgICAgKSB7XG4gICAgICAgIHNlYXJjaEZvckdyb3VwKGNsaWVudCwgb3B0aW9ucywgYXV0aERhdGEuaWQsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjbGllbnQudW5iaW5kKCk7XG4gICAgICAgIGNsaWVudC5kZXN0cm95KCk7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG9wdGlvbnNBcmVWYWxpZChvcHRpb25zKSB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIG9wdGlvbnMgPT09ICdvYmplY3QnICYmXG4gICAgdHlwZW9mIG9wdGlvbnMuc3VmZml4ID09PSAnc3RyaW5nJyAmJlxuICAgIHR5cGVvZiBvcHRpb25zLnVybCA9PT0gJ3N0cmluZycgJiZcbiAgICBvcHRpb25zLnVybC5zdGFydHNXaXRoKCdsZGFwOi8vJylcbiAgKTtcbn1cblxuZnVuY3Rpb24gc2VhcmNoRm9yR3JvdXAoY2xpZW50LCBvcHRpb25zLCBpZCwgcmVzb2x2ZSwgcmVqZWN0KSB7XG4gIGNvbnN0IGZpbHRlciA9IG9wdGlvbnMuZ3JvdXBGaWx0ZXIucmVwbGFjZSgve3tpZH19L2dpLCBpZCk7XG4gIGNvbnN0IG9wdHMgPSB7XG4gICAgc2NvcGU6ICdzdWInLFxuICAgIGZpbHRlcjogZmlsdGVyLFxuICB9O1xuICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgY2xpZW50LnNlYXJjaChvcHRpb25zLnN1ZmZpeCwgb3B0cywgKHNlYXJjaEVycm9yLCByZXMpID0+IHtcbiAgICBpZiAoc2VhcmNoRXJyb3IpIHtcbiAgICAgIGNsaWVudC51bmJpbmQoKTtcbiAgICAgIGNsaWVudC5kZXN0cm95KCk7XG4gICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgICAgICdMREFQIGdyb3VwIHNlYXJjaCBmYWlsZWQnXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICAgIHJlcy5vbignc2VhcmNoRW50cnknLCBlbnRyeSA9PiB7XG4gICAgICBpZiAoZW50cnkub2JqZWN0LmNuID09PSBvcHRpb25zLmdyb3VwQ24pIHtcbiAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICBjbGllbnQudW5iaW5kKCk7XG4gICAgICAgIGNsaWVudC5kZXN0cm95KCk7XG4gICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmVzLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgIGNsaWVudC51bmJpbmQoKTtcbiAgICAgICAgY2xpZW50LmRlc3Ryb3koKTtcbiAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgICAgICAnTERBUDogVXNlciBub3QgaW4gZ3JvdXAnXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJlcy5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgICAgICdMREFQIGdyb3VwIHNlYXJjaCBmYWlsZWQnXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/line.js b/lib/Adapters/Auth/line.js new file mode 100644 index 0000000000..63b271cc2d --- /dev/null +++ b/lib/Adapters/Auth/line.js @@ -0,0 +1,41 @@ +"use strict"; + +// Helper functions for accessing the line API. +var Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills if this user id is valid. + + +function validateAuthData(authData) { + return request('profile', authData.access_token).then(response => { + if (response && response.userId && response.userId === authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Line auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(path, access_token) { + var options = { + host: 'api.line.me', + path: '/v2/' + path, + method: 'GET', + headers: { + Authorization: 'Bearer ' + access_token + } + }; + return httpsRequest.get(options); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2xpbmUuanMiXSwibmFtZXMiOlsiUGFyc2UiLCJyZXF1aXJlIiwiaHR0cHNSZXF1ZXN0IiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwicmVxdWVzdCIsImFjY2Vzc190b2tlbiIsInRoZW4iLCJyZXNwb25zZSIsInVzZXJJZCIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsIm9wdGlvbnMiLCJob3N0IiwibWV0aG9kIiwiaGVhZGVycyIsIkF1dGhvcml6YXRpb24iLCJnZXQiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFsQzs7QUFDQSxNQUFNRSxZQUFZLEdBQUdELE9BQU8sQ0FBQyxnQkFBRCxDQUE1QixDLENBRUE7OztBQUNBLFNBQVNFLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxPQUFPLENBQUMsU0FBRCxFQUFZRCxRQUFRLENBQUNFLFlBQXJCLENBQVAsQ0FBMENDLElBQTFDLENBQStDQyxRQUFRLElBQUk7QUFDaEUsUUFBSUEsUUFBUSxJQUFJQSxRQUFRLENBQUNDLE1BQXJCLElBQStCRCxRQUFRLENBQUNDLE1BQVQsS0FBb0JMLFFBQVEsQ0FBQ00sRUFBaEUsRUFBb0U7QUFDbEU7QUFDRDs7QUFDRCxVQUFNLElBQUlWLEtBQUssQ0FBQ1csS0FBVixDQUNKWCxLQUFLLENBQUNXLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSixxQ0FGSSxDQUFOO0FBSUQsR0FSTSxDQUFQO0FBU0QsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTVixPQUFULENBQWlCVyxJQUFqQixFQUF1QlYsWUFBdkIsRUFBcUM7QUFDbkMsTUFBSVcsT0FBTyxHQUFHO0FBQ1pDLElBQUFBLElBQUksRUFBRSxhQURNO0FBRVpGLElBQUFBLElBQUksRUFBRSxTQUFTQSxJQUZIO0FBR1pHLElBQUFBLE1BQU0sRUFBRSxLQUhJO0FBSVpDLElBQUFBLE9BQU8sRUFBRTtBQUNQQyxNQUFBQSxhQUFhLEVBQUUsWUFBWWY7QUFEcEI7QUFKRyxHQUFkO0FBUUEsU0FBT0osWUFBWSxDQUFDb0IsR0FBYixDQUFpQkwsT0FBakIsQ0FBUDtBQUNEOztBQUVETSxNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZlgsRUFBQUEsYUFBYSxFQUFFQSxhQURBO0FBRWZWLEVBQUFBLGdCQUFnQixFQUFFQTtBQUZILENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBsaW5lIEFQSS5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyB1c2VyIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSkge1xuICByZXR1cm4gcmVxdWVzdCgncHJvZmlsZScsIGF1dGhEYXRhLmFjY2Vzc190b2tlbikudGhlbihyZXNwb25zZSA9PiB7XG4gICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLnVzZXJJZCAmJiByZXNwb25zZS51c2VySWQgPT09IGF1dGhEYXRhLmlkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnTGluZSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nXG4gICAgKTtcbiAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChwYXRoLCBhY2Nlc3NfdG9rZW4pIHtcbiAgdmFyIG9wdGlvbnMgPSB7XG4gICAgaG9zdDogJ2FwaS5saW5lLm1lJyxcbiAgICBwYXRoOiAnL3YyLycgKyBwYXRoLFxuICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgQXV0aG9yaXphdGlvbjogJ0JlYXJlciAnICsgYWNjZXNzX3Rva2VuLFxuICAgIH0sXG4gIH07XG4gIHJldHVybiBodHRwc1JlcXVlc3QuZ2V0KG9wdGlvbnMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YSxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/linkedin.js b/lib/Adapters/Auth/linkedin.js new file mode 100644 index 0000000000..61945e2867 --- /dev/null +++ b/lib/Adapters/Auth/linkedin.js @@ -0,0 +1,46 @@ +"use strict"; + +// Helper functions for accessing the linkedin API. +var Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return request('me', authData.access_token, authData.is_mobile_sdk).then(data => { + if (data && data.id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Linkedin auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(path, access_token, is_mobile_sdk) { + var headers = { + Authorization: 'Bearer ' + access_token, + 'x-li-format': 'json' + }; + + if (is_mobile_sdk) { + headers['x-li-src'] = 'msdk'; + } + + return httpsRequest.get({ + host: 'api.linkedin.com', + path: '/v2/' + path, + headers: headers + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2xpbmtlZGluLmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsImh0dHBzUmVxdWVzdCIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsInJlcXVlc3QiLCJhY2Nlc3NfdG9rZW4iLCJpc19tb2JpbGVfc2RrIiwidGhlbiIsImRhdGEiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBhdGgiLCJoZWFkZXJzIiwiQXV0aG9yaXphdGlvbiIsImdldCIsImhvc3QiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFsQzs7QUFDQSxNQUFNRSxZQUFZLEdBQUdELE9BQU8sQ0FBQyxnQkFBRCxDQUE1QixDLENBRUE7OztBQUNBLFNBQVNFLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxPQUFPLENBQUMsSUFBRCxFQUFPRCxRQUFRLENBQUNFLFlBQWhCLEVBQThCRixRQUFRLENBQUNHLGFBQXZDLENBQVAsQ0FBNkRDLElBQTdELENBQ0xDLElBQUksSUFBSTtBQUNOLFFBQUlBLElBQUksSUFBSUEsSUFBSSxDQUFDQyxFQUFMLElBQVdOLFFBQVEsQ0FBQ00sRUFBaEMsRUFBb0M7QUFDbEM7QUFDRDs7QUFDRCxVQUFNLElBQUlWLEtBQUssQ0FBQ1csS0FBVixDQUNKWCxLQUFLLENBQUNXLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix5Q0FGSSxDQUFOO0FBSUQsR0FUSSxDQUFQO0FBV0QsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTVixPQUFULENBQWlCVyxJQUFqQixFQUF1QlYsWUFBdkIsRUFBcUNDLGFBQXJDLEVBQW9EO0FBQ2xELE1BQUlVLE9BQU8sR0FBRztBQUNaQyxJQUFBQSxhQUFhLEVBQUUsWUFBWVosWUFEZjtBQUVaLG1CQUFlO0FBRkgsR0FBZDs7QUFLQSxNQUFJQyxhQUFKLEVBQW1CO0FBQ2pCVSxJQUFBQSxPQUFPLENBQUMsVUFBRCxDQUFQLEdBQXNCLE1BQXRCO0FBQ0Q7O0FBQ0QsU0FBT2YsWUFBWSxDQUFDaUIsR0FBYixDQUFpQjtBQUN0QkMsSUFBQUEsSUFBSSxFQUFFLGtCQURnQjtBQUV0QkosSUFBQUEsSUFBSSxFQUFFLFNBQVNBLElBRk87QUFHdEJDLElBQUFBLE9BQU8sRUFBRUE7QUFIYSxHQUFqQixDQUFQO0FBS0Q7O0FBRURJLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmVCxFQUFBQSxhQUFhLEVBQUVBLGFBREE7QUFFZlYsRUFBQUEsZ0JBQWdCLEVBQUVBO0FBRkgsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIGxpbmtlZGluIEFQSS5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoJ21lJywgYXV0aERhdGEuYWNjZXNzX3Rva2VuLCBhdXRoRGF0YS5pc19tb2JpbGVfc2RrKS50aGVuKFxuICAgIGRhdGEgPT4ge1xuICAgICAgaWYgKGRhdGEgJiYgZGF0YS5pZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICdMaW5rZWRpbiBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nXG4gICAgICApO1xuICAgIH1cbiAgKTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgYXBpIHJlcXVlc3RzXG5mdW5jdGlvbiByZXF1ZXN0KHBhdGgsIGFjY2Vzc190b2tlbiwgaXNfbW9iaWxlX3Nkaykge1xuICB2YXIgaGVhZGVycyA9IHtcbiAgICBBdXRob3JpemF0aW9uOiAnQmVhcmVyICcgKyBhY2Nlc3NfdG9rZW4sXG4gICAgJ3gtbGktZm9ybWF0JzogJ2pzb24nLFxuICB9O1xuXG4gIGlmIChpc19tb2JpbGVfc2RrKSB7XG4gICAgaGVhZGVyc1sneC1saS1zcmMnXSA9ICdtc2RrJztcbiAgfVxuICByZXR1cm4gaHR0cHNSZXF1ZXN0LmdldCh7XG4gICAgaG9zdDogJ2FwaS5saW5rZWRpbi5jb20nLFxuICAgIHBhdGg6ICcvdjIvJyArIHBhdGgsXG4gICAgaGVhZGVyczogaGVhZGVycyxcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/meetup.js b/lib/Adapters/Auth/meetup.js new file mode 100644 index 0000000000..9065517d05 --- /dev/null +++ b/lib/Adapters/Auth/meetup.js @@ -0,0 +1,39 @@ +"use strict"; + +// Helper functions for accessing the meetup API. +var Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return request('member/self', authData.access_token).then(data => { + if (data && data.id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Meetup auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(path, access_token) { + return httpsRequest.get({ + host: 'api.meetup.com', + path: '/2/' + path, + headers: { + Authorization: 'bearer ' + access_token + } + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL21lZXR1cC5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJyZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBhdGgiLCJnZXQiLCJob3N0IiwiaGVhZGVycyIsIkF1dGhvcml6YXRpb24iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFsQzs7QUFDQSxNQUFNRSxZQUFZLEdBQUdELE9BQU8sQ0FBQyxnQkFBRCxDQUE1QixDLENBRUE7OztBQUNBLFNBQVNFLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxPQUFPLENBQUMsYUFBRCxFQUFnQkQsUUFBUSxDQUFDRSxZQUF6QixDQUFQLENBQThDQyxJQUE5QyxDQUFtREMsSUFBSSxJQUFJO0FBQ2hFLFFBQUlBLElBQUksSUFBSUEsSUFBSSxDQUFDQyxFQUFMLElBQVdMLFFBQVEsQ0FBQ0ssRUFBaEMsRUFBb0M7QUFDbEM7QUFDRDs7QUFDRCxVQUFNLElBQUlULEtBQUssQ0FBQ1UsS0FBVixDQUNKVixLQUFLLENBQUNVLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix1Q0FGSSxDQUFOO0FBSUQsR0FSTSxDQUFQO0FBU0QsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTVCxPQUFULENBQWlCVSxJQUFqQixFQUF1QlQsWUFBdkIsRUFBcUM7QUFDbkMsU0FBT0osWUFBWSxDQUFDYyxHQUFiLENBQWlCO0FBQ3RCQyxJQUFBQSxJQUFJLEVBQUUsZ0JBRGdCO0FBRXRCRixJQUFBQSxJQUFJLEVBQUUsUUFBUUEsSUFGUTtBQUd0QkcsSUFBQUEsT0FBTyxFQUFFO0FBQ1BDLE1BQUFBLGFBQWEsRUFBRSxZQUFZYjtBQURwQjtBQUhhLEdBQWpCLENBQVA7QUFPRDs7QUFFRGMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZULEVBQUFBLGFBQWEsRUFBRUEsYUFEQTtBQUVmVCxFQUFBQSxnQkFBZ0IsRUFBRUE7QUFGSCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgbWVldHVwIEFQSS5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoJ21lbWJlci9zZWxmJywgYXV0aERhdGEuYWNjZXNzX3Rva2VuKS50aGVuKGRhdGEgPT4ge1xuICAgIGlmIChkYXRhICYmIGRhdGEuaWQgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdNZWV0dXAgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIHJlcXVlc3QocGF0aCwgYWNjZXNzX3Rva2VuKSB7XG4gIHJldHVybiBodHRwc1JlcXVlc3QuZ2V0KHtcbiAgICBob3N0OiAnYXBpLm1lZXR1cC5jb20nLFxuICAgIHBhdGg6ICcvMi8nICsgcGF0aCxcbiAgICBoZWFkZXJzOiB7XG4gICAgICBBdXRob3JpemF0aW9uOiAnYmVhcmVyICcgKyBhY2Nlc3NfdG9rZW4sXG4gICAgfSxcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/microsoft.js b/lib/Adapters/Auth/microsoft.js new file mode 100644 index 0000000000..d88bb3cf0e --- /dev/null +++ b/lib/Adapters/Auth/microsoft.js @@ -0,0 +1,39 @@ +"use strict"; + +// Helper functions for accessing the microsoft graph API. +var Parse = require('parse/node').Parse; + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills if this user mail is valid. + + +function validateAuthData(authData) { + return request('me', authData.access_token).then(response => { + if (response && response.id && response.id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Microsoft Graph auth is invalid for this user.'); + }); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(path, access_token) { + return httpsRequest.get({ + host: 'graph.microsoft.com', + path: '/v1.0/' + path, + headers: { + Authorization: 'Bearer ' + access_token + } + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL21pY3Jvc29mdC5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJyZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsInJlc3BvbnNlIiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJwYXRoIiwiZ2V0IiwiaG9zdCIsImhlYWRlcnMiLCJBdXRob3JpemF0aW9uIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLEtBQUssR0FBR0MsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkQsS0FBbEM7O0FBQ0EsTUFBTUUsWUFBWSxHQUFHRCxPQUFPLENBQUMsZ0JBQUQsQ0FBNUIsQyxDQUVBOzs7QUFDQSxTQUFTRSxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsU0FBT0MsT0FBTyxDQUFDLElBQUQsRUFBT0QsUUFBUSxDQUFDRSxZQUFoQixDQUFQLENBQXFDQyxJQUFyQyxDQUNMQyxRQUFRLElBQUk7QUFDVixRQUFJQSxRQUFRLElBQUlBLFFBQVEsQ0FBQ0MsRUFBckIsSUFBMkJELFFBQVEsQ0FBQ0MsRUFBVCxJQUFlTCxRQUFRLENBQUNLLEVBQXZELEVBQTJEO0FBQ3pEO0FBQ0Q7O0FBQ0QsVUFBTSxJQUFJVCxLQUFLLENBQUNVLEtBQVYsQ0FDSlYsS0FBSyxDQUFDVSxLQUFOLENBQVlDLGdCQURSLEVBRUosZ0RBRkksQ0FBTjtBQUlELEdBVEksQ0FBUDtBQVdELEMsQ0FFRDs7O0FBQ0EsU0FBU0MsYUFBVCxHQUF5QjtBQUN2QixTQUFPQyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNELEMsQ0FFRDs7O0FBQ0EsU0FBU1QsT0FBVCxDQUFpQlUsSUFBakIsRUFBdUJULFlBQXZCLEVBQXFDO0FBQ25DLFNBQU9KLFlBQVksQ0FBQ2MsR0FBYixDQUFpQjtBQUN0QkMsSUFBQUEsSUFBSSxFQUFFLHFCQURnQjtBQUV0QkYsSUFBQUEsSUFBSSxFQUFFLFdBQVdBLElBRks7QUFHdEJHLElBQUFBLE9BQU8sRUFBRTtBQUNQQyxNQUFBQSxhQUFhLEVBQUUsWUFBWWI7QUFEcEI7QUFIYSxHQUFqQixDQUFQO0FBT0Q7O0FBRURjLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmVCxFQUFBQSxhQUFhLEVBQUVBLGFBREE7QUFFZlQsRUFBQUEsZ0JBQWdCLEVBQUVBO0FBRkgsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIG1pY3Jvc29mdCBncmFwaCBBUEkuXG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5jb25zdCBodHRwc1JlcXVlc3QgPSByZXF1aXJlKCcuL2h0dHBzUmVxdWVzdCcpO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgdXNlciBtYWlsIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSkge1xuICByZXR1cm4gcmVxdWVzdCgnbWUnLCBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pLnRoZW4oXG4gICAgcmVzcG9uc2UgPT4ge1xuICAgICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLmlkICYmIHJlc3BvbnNlLmlkID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ01pY3Jvc29mdCBHcmFwaCBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nXG4gICAgICApO1xuICAgIH1cbiAgKTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIHJlcXVlc3QocGF0aCwgYWNjZXNzX3Rva2VuKSB7XG4gIHJldHVybiBodHRwc1JlcXVlc3QuZ2V0KHtcbiAgICBob3N0OiAnZ3JhcGgubWljcm9zb2Z0LmNvbScsXG4gICAgcGF0aDogJy92MS4wLycgKyBwYXRoLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgIEF1dGhvcml6YXRpb246ICdCZWFyZXIgJyArIGFjY2Vzc190b2tlbixcbiAgICB9LFxuICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGEsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/oauth2.js b/lib/Adapters/Auth/oauth2.js new file mode 100644 index 0000000000..a7863a5c3f --- /dev/null +++ b/lib/Adapters/Auth/oauth2.js @@ -0,0 +1,142 @@ +"use strict"; + +/* + * This auth adapter is based on the OAuth 2.0 Token Introspection specification. + * See RFC 7662 for details (https://tools.ietf.org/html/rfc7662). + * It's purpose is to validate OAuth2 access tokens using the OAuth2 provider's + * token introspection endpoint (if implemented by the provider). + * + * The adapter accepts the following config parameters: + * + * 1. "tokenIntrospectionEndpointUrl" (string, required) + * The URL of the token introspection endpoint of the OAuth2 provider that + * issued the access token to the client that is to be validated. + * + * 2. "useridField" (string, optional) + * The name of the field in the token introspection response that contains + * the userid. If specified, it will be used to verify the value of the "id" + * field in the "authData" JSON that is coming from the client. + * This can be the "aud" (i.e. audience), the "sub" (i.e. subject) or the + * "username" field in the introspection response, but since only the + * "active" field is required and all other reponse fields are optional + * in the RFC, it has to be optional in this adapter as well. + * Default: - (undefined) + * + * 3. "appidField" (string, optional) + * The name of the field in the token introspection response that contains + * the appId of the client. If specified, it will be used to verify it's + * value against the set of appIds in the adapter config. The concept of + * appIds comes from the two major social login providers + * (Google and Facebook). They have not yet implemented the token + * introspection endpoint, but the concept can be valid for any OAuth2 + * provider. + * Default: - (undefined) + * + * 4. "appIds" (array of strings, required if appidField is defined) + * A set of appIds that are used to restrict accepted access tokens based + * on a specific field's value in the token introspection response. + * Default: - (undefined) + * + * 5. "authorizationHeader" (string, optional) + * The value of the "Authorization" HTTP header in requests sent to the + * introspection endpoint. It must contain the raw value. + * Thus if HTTP Basic authorization is to be used, it must contain the + * "Basic" string, followed by whitespace, then by the base64 encoded + * version of the concatenated + ":" + string. + * Eg. "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" + * + * The adapter expects requests with the following authData JSON: + * + * { + * "someadapter": { + * "id": "user's OAuth2 provider-specific id as a string", + * "access_token": "an authorized OAuth2 access token for the user", + * } + * } + */ +const Parse = require('parse/node').Parse; + +const url = require('url'); + +const querystring = require('querystring'); + +const httpsRequest = require('./httpsRequest'); + +const INVALID_ACCESS = 'OAuth2 access token is invalid for this user.'; +const INVALID_ACCESS_APPID = "OAuth2: the access_token's appID is empty or is not in the list of permitted appIDs in the auth configuration."; +const MISSING_APPIDS = 'OAuth2 configuration is missing the client app IDs ("appIds" config parameter).'; +const MISSING_URL = 'OAuth2 token introspection endpoint URL is missing from configuration!'; // Returns a promise that fulfills if this user id is valid. + +function validateAuthData(authData, options) { + return requestTokenInfo(options, authData.access_token).then(response => { + if (!response || !response.active || options.useridField && authData.id !== response[options.useridField]) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, INVALID_ACCESS); + } + }); +} + +function validateAppId(appIds, authData, options) { + if (!options || !options.appidField) { + return Promise.resolve(); + } + + if (!appIds || appIds.length === 0) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, MISSING_APPIDS); + } + + return requestTokenInfo(options, authData.access_token).then(response => { + if (!response || !response.active) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, INVALID_ACCESS); + } + + const appidField = options.appidField; + + if (!response[appidField]) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, INVALID_ACCESS_APPID); + } + + const responseValue = response[appidField]; + + if (!Array.isArray(responseValue) && appIds.includes(responseValue)) { + return; + } else if (Array.isArray(responseValue) && responseValue.some(appId => appIds.includes(appId))) { + return; + } else { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, INVALID_ACCESS_APPID); + } + }); +} // A promise wrapper for requests to the OAuth2 token introspection endpoint. + + +function requestTokenInfo(options, access_token) { + if (!options || !options.tokenIntrospectionEndpointUrl) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, MISSING_URL); + } + + const parsedUrl = url.parse(options.tokenIntrospectionEndpointUrl); + const postData = querystring.stringify({ + token: access_token + }); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(postData) + }; + + if (options.authorizationHeader) { + headers['Authorization'] = options.authorizationHeader; + } + + const postOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.pathname, + method: 'POST', + headers: headers + }; + return httpsRequest.request(postOptions, postData); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL29hdXRoMi5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJ1cmwiLCJxdWVyeXN0cmluZyIsImh0dHBzUmVxdWVzdCIsIklOVkFMSURfQUNDRVNTIiwiSU5WQUxJRF9BQ0NFU1NfQVBQSUQiLCJNSVNTSU5HX0FQUElEUyIsIk1JU1NJTkdfVVJMIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwib3B0aW9ucyIsInJlcXVlc3RUb2tlbkluZm8iLCJhY2Nlc3NfdG9rZW4iLCJ0aGVuIiwicmVzcG9uc2UiLCJhY3RpdmUiLCJ1c2VyaWRGaWVsZCIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsImFwcElkcyIsImFwcGlkRmllbGQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImxlbmd0aCIsInJlc3BvbnNlVmFsdWUiLCJBcnJheSIsImlzQXJyYXkiLCJpbmNsdWRlcyIsInNvbWUiLCJhcHBJZCIsInRva2VuSW50cm9zcGVjdGlvbkVuZHBvaW50VXJsIiwicGFyc2VkVXJsIiwicGFyc2UiLCJwb3N0RGF0YSIsInN0cmluZ2lmeSIsInRva2VuIiwiaGVhZGVycyIsIkJ1ZmZlciIsImJ5dGVMZW5ndGgiLCJhdXRob3JpemF0aW9uSGVhZGVyIiwicG9zdE9wdGlvbnMiLCJob3N0bmFtZSIsInBhdGgiLCJwYXRobmFtZSIsIm1ldGhvZCIsInJlcXVlc3QiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF1REEsTUFBTUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFwQzs7QUFDQSxNQUFNRSxHQUFHLEdBQUdELE9BQU8sQ0FBQyxLQUFELENBQW5COztBQUNBLE1BQU1FLFdBQVcsR0FBR0YsT0FBTyxDQUFDLGFBQUQs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QUQsSUFBWSxDQUFDQSxPQUFPLENBQUNzQiw2QkFBekIsRUFBd0Q7QUFDdEQsVUFBTSxJQUFJakMsS0FBSyxDQUFDbUIsS0FBVixDQUFnQm5CLEtBQUssQ0FBQ21CLEtBQU4sQ0FBWUMsZ0JBQTVCLEVBQThDWixXQUE5QyxDQUFOO0FBQ0Q7O0FBQ0QsUUFBTTBCLFNBQVMsR0FBR2hDLEdBQUcsQ0FBQ2lDLEtBQUosQ0FBVXhCLE9BQU8sQ0FBQ3NCLDZCQUFsQixDQUFsQjtBQUNBLFFBQU1HLFFBQVEsR0FBR2pDLFdBQVcsQ0FBQ2tDLFNBQVosQ0FBc0I7QUFDckNDLElBQUFBLEtBQUssRUFBRXpCO0FBRDhCLEdBQXRCLENBQWpCO0FBR0EsUUFBTTBCLE9BQU8sR0FBRztBQUNkLG9CQUFnQixtQ0FERjtBQUVkLHNCQUFrQkMsTUFBTSxDQUFDQyxVQUFQLENBQWtCTCxRQUFsQjtBQUZKLEdBQWhCOztBQUlBLE1BQUl6QixPQUFPLENBQUMrQixtQkFBWixFQUFpQztBQUMvQkgsSUFBQUEsT0FBTyxDQUFDLGVBQUQsQ0FBUCxHQUEyQjVCLE9BQU8sQ0FBQytCLG1CQUFuQztBQUNEOztBQUNELFFBQU1DLFdBQVcsR0FBRztBQUNsQkMsSUFBQUEsUUFBUSxFQUFFVixTQUFTLENBQUNVLFFBREY7QUFFbEJDLElBQUFBLElBQUksRUFBRVgsU0FBUyxDQUFDWSxRQUZFO0FBR2xCQyxJQUFBQSxNQUFNLEVBQUUsTUFIVTtBQUlsQlIsSUFBQUEsT0FBTyxFQUFFQTtBQUpTLEdBQXBCO0FBTUEsU0FBT25DLFlBQVksQ0FBQzRDLE9BQWIsQ0FBcUJMLFdBQXJCLEVBQWtDUCxRQUFsQyxDQUFQO0FBQ0Q7O0FBRURhLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmN0IsRUFBQUEsYUFBYSxFQUFFQSxhQURBO0FBRWZaLEVBQUFBLGdCQUFnQixFQUFFQTtBQUZILENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIFRoaXMgYXV0aCBhZGFwdGVyIGlzIGJhc2VkIG9uIHRoZSBPQXV0aCAyLjAgVG9rZW4gSW50cm9zcGVjdGlvbiBzcGVjaWZpY2F0aW9uLlxuICogU2VlIFJGQyA3NjYyIGZvciBkZXRhaWxzIChodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNzY2MikuXG4gKiBJdCdzIHB1cnBvc2UgaXMgdG8gdmFsaWRhdGUgT0F1dGgyIGFjY2VzcyB0b2tlbnMgdXNpbmcgdGhlIE9BdXRoMiBwcm92aWRlcidzXG4gKiB0b2tlbiBpbnRyb3NwZWN0aW9uIGVuZHBvaW50IChpZiBpbXBsZW1lbnRlZCBieSB0aGUgcHJvdmlkZXIpLlxuICpcbiAqIFRoZSBhZGFwdGVyIGFjY2VwdHMgdGhlIGZvbGxvd2luZyBjb25maWcgcGFyYW1ldGVyczpcbiAqXG4gKiAxLiBcInRva2VuSW50cm9zcGVjdGlvbkVuZHBvaW50VXJsXCIgKHN0cmluZywgcmVxdWlyZWQpXG4gKiAgICAgIFRoZSBVUkwgb2YgdGhlIHRva2VuIGludHJvc3BlY3Rpb24gZW5kcG9pbnQgb2YgdGhlIE9BdXRoMiBwcm92aWRlciB0aGF0XG4gKiAgICAgIGlzc3VlZCB0aGUgYWNjZXNzIHRva2VuIHRvIHRoZSBjbGllbnQgdGhhdCBpcyB0byBiZSB2YWxpZGF0ZWQuXG4gKlxuICogMi4gXCJ1c2VyaWRGaWVsZFwiIChzdHJpbmcsIG9wdGlvbmFsKVxuICogICAgICBUaGUgbmFtZSBvZiB0aGUgZmllbGQgaW4gdGhlIHRva2VuIGludHJvc3BlY3Rpb24gcmVzcG9uc2UgdGhhdCBjb250YWluc1xuICogICAgICB0aGUgdXNlcmlkLiBJZiBzcGVjaWZpZWQsIGl0IHdpbGwgYmUgdXNlZCB0byB2ZXJpZnkgdGhlIHZhbHVlIG9mIHRoZSBcImlkXCJcbiAqICAgICAgZmllbGQgaW4gdGhlIFwiYXV0aERhdGFcIiBKU09OIHRoYXQgaXMgY29taW5nIGZyb20gdGhlIGNsaWVudC5cbiAqICAgICAgVGhpcyBjYW4gYmUgdGhlIFwiYXVkXCIgKGkuZS4gYXVkaWVuY2UpLCB0aGUgXCJzdWJcIiAoaS5lLiBzdWJqZWN0KSBvciB0aGVcbiAqICAgICAgXCJ1c2VybmFtZVwiIGZpZWxkIGluIHRoZSBpbnRyb3NwZWN0aW9uIHJlc3BvbnNlLCBidXQgc2luY2Ugb25seSB0aGVcbiAqICAgICAgXCJhY3RpdmVcIiBmaWVsZCBpcyByZXF1aXJlZCBhbmQgYWxsIG90aGVyIHJlcG9uc2UgZmllbGRzIGFyZSBvcHRpb25hbFxuICogICAgICBpbiB0aGUgUkZDLCBpdCBoYXMgdG8gYmUgb3B0aW9uYWwgaW4gdGhpcyBhZGFwdGVyIGFzIHdlbGwuXG4gKiAgICAgIERlZmF1bHQ6IC0gKHVuZGVmaW5lZClcbiAqXG4gKiAzLiBcImFwcGlkRmllbGRcIiAoc3RyaW5nLCBvcHRpb25hbClcbiAqICAgICAgVGhlIG5hbWUgb2YgdGhlIGZpZWxkIGluIHRoZSB0b2tlbiBpbnRyb3NwZWN0aW9uIHJlc3BvbnNlIHRoYXQgY29udGFpbnNcbiAqICAgICAgdGhlIGFwcElkIG9mIHRoZSBjbGllbnQuIElmIHNwZWNpZmllZCwgaXQgd2lsbCBiZSB1c2VkIHRvIHZlcmlmeSBpdCdzXG4gKiAgICAgIHZhbHVlIGFnYWluc3QgdGhlIHNldCBvZiBhcHBJZHMgaW4gdGhlIGFkYXB0ZXIgY29uZmlnLiBUaGUgY29uY2VwdCBvZlxuICogICAgICBhcHBJZHMgY29tZXMgZnJvbSB0aGUgdHdvIG1ham9yIHNvY2lhbCBsb2dpbiBwcm92aWRlcnNcbiAqICAgICAgKEdvb2dsZSBhbmQgRmFjZWJvb2spLiBUaGV5IGhhdmUgbm90IHlldCBpbXBsZW1lbnRlZCB0aGUgdG9rZW5cbiAqICAgICAgaW50cm9zcGVjdGlvbiBlbmRwb2ludCwgYnV0IHRoZSBjb25jZXB0IGNhbiBiZSB2YWxpZCBmb3IgYW55IE9BdXRoMlxuICogICAgICBwcm92aWRlci5cbiAqICAgICAgRGVmYXVsdDogLSAodW5kZWZpbmVkKVxuICpcbiAqIDQuIFwiYXBwSWRzXCIgKGFycmF5IG9mIHN0cmluZ3MsIHJlcXVpcmVkIGlmIGFwcGlkRmllbGQgaXMgZGVmaW5lZClcbiAqICAgICAgQSBzZXQgb2YgYXBwSWRzIHRoYXQgYXJlIHVzZWQgdG8gcmVzdHJpY3QgYWNjZXB0ZWQgYWNjZXNzIHRva2VucyBiYXNlZFxuICogICAgICBvbiBhIHNwZWNpZmljIGZpZWxkJ3MgdmFsdWUgaW4gdGhlIHRva2VuIGludHJvc3BlY3Rpb24gcmVzcG9uc2UuXG4gKiAgICAgIERlZmF1bHQ6IC0gKHVuZGVmaW5lZClcbiAqXG4gKiA1LiBcImF1dGhvcml6YXRpb25IZWFkZXJcIiAoc3RyaW5nLCBvcHRpb25hbClcbiAqICAgICAgVGhlIHZhbHVlIG9mIHRoZSBcIkF1dGhvcml6YXRpb25cIiBIVFRQIGhlYWRlciBpbiByZXF1ZXN0cyBzZW50IHRvIHRoZVxuICogICAgICBpbnRyb3NwZWN0aW9uIGVuZHBvaW50LiBJdCBtdXN0IGNvbnRhaW4gdGhlIHJhdyB2YWx1ZS5cbiAqICAgICAgVGh1cyBpZiBIVFRQIEJhc2ljIGF1dGhvcml6YXRpb24gaXMgdG8gYmUgdXNlZCwgaXQgbXVzdCBjb250YWluIHRoZVxuICogICAgICBcIkJhc2ljXCIgc3RyaW5nLCBmb2xsb3dlZCBieSB3aGl0ZXNwYWNlLCB0aGVuIGJ5IHRoZSBiYXNlNjQgZW5jb2RlZFxuICogICAgICB2ZXJzaW9uIG9mIHRoZSBjb25jYXRlbmF0ZWQgPHVzZXJuYW1lPiArIFwiOlwiICsgPHBhc3N3b3JkPiBzdHJpbmcuXG4gKiAgICAgIEVnLiBcIkJhc2ljIGRYTmxjbTVoYldVNmNHRnpjM2R2Y21RPVwiXG4gKlxuICogVGhlIGFkYXB0ZXIgZXhwZWN0cyByZXF1ZXN0cyB3aXRoIHRoZSBmb2xsb3dpbmcgYXV0aERhdGEgSlNPTjpcbiAqXG4gKiB7XG4gKiAgIFwic29tZWFkYXB0ZXJcIjoge1xuICogICAgIFwiaWRcIjogXCJ1c2VyJ3MgT0F1dGgyIHByb3ZpZGVyLXNwZWNpZmljIGlkIGFzIGEgc3RyaW5nXCIsXG4gKiAgICAgXCJhY2Nlc3NfdG9rZW5cIjogXCJhbiBhdXRob3JpemVkIE9BdXRoMiBhY2Nlc3MgdG9rZW4gZm9yIHRoZSB1c2VyXCIsXG4gKiAgIH1cbiAqIH1cbiAqL1xuXG5jb25zdCBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IHVybCA9IHJlcXVpcmUoJ3VybCcpO1xuY29uc3QgcXVlcnlzdHJpbmcgPSByZXF1aXJlKCdxdWVyeXN0cmluZycpO1xuY29uc3QgaHR0cHNSZXF1ZXN0ID0gcmVxdWlyZSgnLi9odHRwc1JlcXVlc3QnKTtcblxuY29uc3QgSU5WQUxJRF9BQ0NFU1MgPSAnT0F1dGgyIGFjY2VzcyB0b2tlbiBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJztcbmNvbnN0IElOVkFMSURfQUNDRVNTX0FQUElEID1cbiAgXCJPQXV0aDI6IHRoZSBhY2Nlc3NfdG9rZW4ncyBhcHBJRCBpcyBlbXB0eSBvciBpcyBub3QgaW4gdGhlIGxpc3Qgb2YgcGVybWl0dGVkIGFwcElEcyBpbiB0aGUgYXV0aCBjb25maWd1cmF0aW9uLlwiO1xuY29uc3QgTUlTU0lOR19BUFBJRFMgPVxuICAnT0F1dGgyIGNvbmZpZ3VyYXRpb24gaXMgbWlzc2luZyB0aGUgY2xpZW50IGFwcCBJRHMgKFwiYXBwSWRzXCIgY29uZmlnIHBhcmFtZXRlcikuJztcbmNvbnN0IE1JU1NJTkdfVVJMID1cbiAgJ09BdXRoMiB0b2tlbiBpbnRyb3NwZWN0aW9uIGVuZHBvaW50IFVSTCBpcyBtaXNzaW5nIGZyb20gY29uZmlndXJhdGlvbiEnO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHJlcXVlc3RUb2tlbkluZm8ob3B0aW9ucywgYXV0aERhdGEuYWNjZXNzX3Rva2VuKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICBpZiAoXG4gICAgICAhcmVzcG9uc2UgfHxcbiAgICAgICFyZXNwb25zZS5hY3RpdmUgfHxcbiAgICAgIChvcHRpb25zLnVzZXJpZEZpZWxkICYmIGF1dGhEYXRhLmlkICE9PSByZXNwb25zZVtvcHRpb25zLnVzZXJpZEZpZWxkXSlcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCBJTlZBTElEX0FDQ0VTUyk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZChhcHBJZHMsIGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gIGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5hcHBpZEZpZWxkKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIGlmICghYXBwSWRzIHx8IGFwcElkcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgTUlTU0lOR19BUFBJRFMpO1xuICB9XG4gIHJldHVybiByZXF1ZXN0VG9rZW5JbmZvKG9wdGlvbnMsIGF1dGhEYXRhLmFjY2Vzc190b2tlbikudGhlbihyZXNwb25zZSA9PiB7XG4gICAgaWYgKCFyZXNwb25zZSB8fCAhcmVzcG9uc2UuYWN0aXZlKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgSU5WQUxJRF9BQ0NFU1MpO1xuICAgIH1cbiAgICBjb25zdCBhcHBpZEZpZWxkID0gb3B0aW9ucy5hcHBpZEZpZWxkO1xuICAgIGlmICghcmVzcG9uc2VbYXBwaWRGaWVsZF0pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCBJTlZBTElEX0FDQ0VTU19BUFBJRCk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3BvbnNlVmFsdWUgPSByZXNwb25zZVthcHBpZEZpZWxkXTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkocmVzcG9uc2VWYWx1ZSkgJiYgYXBwSWRzLmluY2x1ZGVzKHJlc3BvbnNlVmFsdWUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIEFycmF5LmlzQXJyYXkocmVzcG9uc2VWYWx1ZSkgJiZcbiAgICAgIHJlc3BvbnNlVmFsdWUuc29tZShhcHBJZCA9PiBhcHBJZHMuaW5jbHVkZXMoYXBwSWQpKVxuICAgICkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgSU5WQUxJRF9BQ0NFU1NfQVBQSUQpO1xuICAgIH1cbiAgfSk7XG59XG5cbi8vIEEgcHJvbWlzZSB3cmFwcGVyIGZvciByZXF1ZXN0cyB0byB0aGUgT0F1dGgyIHRva2VuIGludHJvc3BlY3Rpb24gZW5kcG9pbnQuXG5mdW5jdGlvbiByZXF1ZXN0VG9rZW5JbmZvKG9wdGlvbnMsIGFjY2Vzc190b2tlbikge1xuICBpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMudG9rZW5JbnRyb3NwZWN0aW9uRW5kcG9pbnRVcmwpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgTUlTU0lOR19VUkwpO1xuICB9XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShvcHRpb25zLnRva2VuSW50cm9zcGVjdGlvbkVuZHBvaW50VXJsKTtcbiAgY29uc3QgcG9zdERhdGEgPSBxdWVyeXN0cmluZy5zdHJpbmdpZnkoe1xuICAgIHRva2VuOiBhY2Nlc3NfdG9rZW4sXG4gIH0pO1xuICBjb25zdCBoZWFkZXJzID0ge1xuICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyxcbiAgICAnQ29udGVudC1MZW5ndGgnOiBCdWZmZXIuYnl0ZUxlbmd0aChwb3N0RGF0YSksXG4gIH07XG4gIGlmIChvcHRpb25zLmF1dGhvcml6YXRpb25IZWFkZXIpIHtcbiAgICBoZWFkZXJzWydBdXRob3JpemF0aW9uJ10gPSBvcHRpb25zLmF1dGhvcml6YXRpb25IZWFkZXI7XG4gIH1cbiAgY29uc3QgcG9zdE9wdGlvbnMgPSB7XG4gICAgaG9zdG5hbWU6IHBhcnNlZFVybC5ob3N0bmFtZSxcbiAgICBwYXRoOiBwYXJzZWRVcmwucGF0aG5hbWUsXG4gICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgaGVhZGVyczogaGVhZGVycyxcbiAgfTtcbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5yZXF1ZXN0KHBvc3RPcHRpb25zLCBwb3N0RGF0YSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/phantauth.js b/lib/Adapters/Auth/phantauth.js new file mode 100644 index 0000000000..a85547aa55 --- /dev/null +++ b/lib/Adapters/Auth/phantauth.js @@ -0,0 +1,47 @@ +"use strict"; + +/* + * PhantAuth was designed to simplify testing for applications using OpenID Connect + * authentication by making use of random generated users. + * + * To learn more, please go to: https://www.phantauth.net + */ +const { + Parse +} = require('parse/node'); + +const httpsRequest = require('./httpsRequest'); // Returns a promise that fulfills if this user id is valid. + + +function validateAuthData(authData) { + return request('auth/userinfo', authData.access_token).then(data => { + if (data && data.sub == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'PhantAuth auth is invalid for this user.'); + }); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(path, access_token) { + return httpsRequest.get({ + host: 'phantauth.net', + path: '/' + path, + headers: { + Authorization: 'bearer ' + access_token, + 'User-Agent': 'parse-server' + } + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3BoYW50YXV0aC5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJyZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJzdWIiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBhdGgiLCJnZXQiLCJob3N0IiwiaGVhZGVycyIsIkF1dGhvcml6YXRpb24iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7QUFPQSxNQUFNO0FBQUVBLEVBQUFBO0FBQUYsSUFBWUMsT0FBTyxDQUFDLFlBQUQsQ0FBekI7O0FBQ0EsTUFBTUMsWUFBWSxHQUFHRCxPQUFPLENBQUMsZ0JBQUQsQ0FBNUIsQyxDQUVBOzs7QUFDQSxTQUFTRSxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsU0FBT0MsT0FBTyxDQUFDLGVBQUQsRUFBa0JELFFBQVEsQ0FBQ0UsWUFBM0IsQ0FBUCxDQUFnREMsSUFBaEQsQ0FBcURDLElBQUksSUFBSTtBQUNsRSxRQUFJQSxJQUFJLElBQUlBLElBQUksQ0FBQ0MsR0FBTCxJQUFZTCxRQUFRLENBQUNNLEVBQWpDLEVBQXFDO0FBQ25DO0FBQ0Q7O0FBQ0QsVUFBTSxJQUFJVixLQUFLLENBQUNXLEtBQVYsQ0FDSlgsS0FBSyxDQUFDVyxLQUFOLENBQVlDLGdCQURSLEVBRUosMENBRkksQ0FBTjtBQUlELEdBUk0sQ0FBUDtBQVNELEMsQ0FFRDs7O0FBQ0EsU0FBU0MsYUFBVCxHQUF5QjtBQUN2QixTQUFPQyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNELEMsQ0FFRDs7O0FBQ0EsU0FBU1YsT0FBVCxDQUFpQlcsSUFBakIsRUFBdUJWLFlBQXZCLEVBQXFDO0FBQ25DLFNBQU9KLFlBQVksQ0FBQ2UsR0FBYixDQUFpQjtBQUN0QkMsSUFBQUEsSUFBSSxFQUFFLGVBRGdCO0FBRXRCRixJQUFBQSxJQUFJLEVBQUUsTUFBTUEsSUFGVTtBQUd0QkcsSUFBQUEsT0FBTyxFQUFFO0FBQ1BDLE1BQUFBLGFBQWEsRUFBRSxZQUFZZCxZQURwQjtBQUVQLG9CQUFjO0FBRlA7QUFIYSxHQUFqQixDQUFQO0FBUUQ7O0FBRURlLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmVCxFQUFBQSxhQUFhLEVBQUVBLGFBREE7QUFFZlYsRUFBQUEsZ0JBQWdCLEVBQUVBO0FBRkgsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogUGhhbnRBdXRoIHdhcyBkZXNpZ25lZCB0byBzaW1wbGlmeSB0ZXN0aW5nIGZvciBhcHBsaWNhdGlvbnMgdXNpbmcgT3BlbklEIENvbm5lY3RcbiAqIGF1dGhlbnRpY2F0aW9uIGJ5IG1ha2luZyB1c2Ugb2YgcmFuZG9tIGdlbmVyYXRlZCB1c2Vycy5cbiAqXG4gKiBUbyBsZWFybiBtb3JlLCBwbGVhc2UgZ28gdG86IGh0dHBzOi8vd3d3LnBoYW50YXV0aC5uZXRcbiAqL1xuXG5jb25zdCB7IFBhcnNlIH0gPSByZXF1aXJlKCdwYXJzZS9ub2RlJyk7XG5jb25zdCBodHRwc1JlcXVlc3QgPSByZXF1aXJlKCcuL2h0dHBzUmVxdWVzdCcpO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoJ2F1dGgvdXNlcmluZm8nLCBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pLnRoZW4oZGF0YSA9PiB7XG4gICAgaWYgKGRhdGEgJiYgZGF0YS5zdWIgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdQaGFudEF1dGggYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChwYXRoLCBhY2Nlc3NfdG9rZW4pIHtcbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5nZXQoe1xuICAgIGhvc3Q6ICdwaGFudGF1dGgubmV0JyxcbiAgICBwYXRoOiAnLycgKyBwYXRoLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgIEF1dGhvcml6YXRpb246ICdiZWFyZXIgJyArIGFjY2Vzc190b2tlbixcbiAgICAgICdVc2VyLUFnZW50JzogJ3BhcnNlLXNlcnZlcicsXG4gICAgfSxcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/qq.js b/lib/Adapters/Auth/qq.js new file mode 100644 index 0000000000..4d57399ed2 --- /dev/null +++ b/lib/Adapters/Auth/qq.js @@ -0,0 +1,48 @@ +"use strict"; + +// Helper functions for accessing the qq Graph API. +const httpsRequest = require('./httpsRequest'); + +var Parse = require('parse/node').Parse; // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return graphRequest('me?access_token=' + authData.access_token).then(function (data) { + if (data && data.openid == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'qq auth is invalid for this user.'); + }); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for qq graph requests. + + +function graphRequest(path) { + return httpsRequest.get('https://graph.qq.com/oauth2.0/' + path, true).then(data => { + return parseResponseData(data); + }); +} + +function parseResponseData(data) { + const starPos = data.indexOf('('); + const endPos = data.indexOf(')'); + + if (starPos == -1 || endPos == -1) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'qq auth is invalid for this user.'); + } + + data = data.substring(starPos + 1, endPos - 1); + return JSON.parse(data); +} + +module.exports = { + validateAppId, + validateAuthData, + parseResponseData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3FxLmpzIl0sIm5hbWVzIjpbImh0dHBzUmVxdWVzdCIsInJlcXVpcmUiLCJQYXJzZSIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsImdyYXBoUmVxdWVzdCIsImFjY2Vzc190b2tlbiIsInRoZW4iLCJkYXRhIiwib3BlbmlkIiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJwYXRoIiwiZ2V0IiwicGFyc2VSZXNwb25zZURhdGEiLCJzdGFyUG9zIiwiaW5kZXhPZiIsImVuZFBvcyIsInN1YnN0cmluZyIsIkpTT04iLCJwYXJzZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxNQUFNQSxZQUFZLEdBQUdDLE9BQU8sQ0FBQyxnQkFBRCxDQUE1Qjs7QUFDQSxJQUFJQyxLQUFLLEdBQUdELE9BQU8sQ0FBQyxZQUFELENBQVAsQ0FBc0JDLEtBQWxDLEMsQ0FFQTs7O0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DO0FBQ2xDLFNBQU9DLFlBQVksQ0FBQyxxQkFBcUJELFFBQVEsQ0FBQ0UsWUFBL0IsQ0FBWixDQUF5REMsSUFBekQsQ0FBOEQsVUFDbkVDLElBRG1FLEVBRW5FO0FBQ0EsUUFBSUEsSUFBSSxJQUFJQSxJQUFJLENBQUNDLE1BQUwsSUFBZUwsUUFBUSxDQUFDTSxFQUFwQyxFQUF3QztBQUN0QztBQUNEOztBQUNELFVBQU0sSUFBSVIsS0FBSyxDQUFDUyxLQUFWLENBQ0pULEtBQUssQ0FBQ1MsS0FBTixDQUFZQyxnQkFEUixFQUVKLG1DQUZJLENBQU47QUFJRCxHQVZNLENBQVA7QUFXRCxDLENBRUQ7OztBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRCxDLENBRUQ7OztBQUNBLFNBQVNWLFlBQVQsQ0FBc0JXLElBQXRCLEVBQTRCO0FBQzFCLFNBQU9oQixZQUFZLENBQ2hCaUIsR0FESSxDQUNBLG1DQUFtQ0QsSUFEbkMsRUFDeUMsSUFEekMsRUFFSlQsSUFGSSxDQUVDQyxJQUFJLElBQUk7QUFDWixXQUFPVSxpQkFBaUIsQ0FBQ1YsSUFBRCxDQUF4QjtBQUNELEdBSkksQ0FBUDtBQUtEOztBQUVELFNBQVNVLGlCQUFULENBQTJCVixJQUEzQixFQUFpQztBQUMvQixRQUFNVyxPQUFPLEdBQUdYLElBQUksQ0FBQ1ksT0FBTCxDQUFhLEdBQWIsQ0FBaEI7QUFDQSxRQUFNQyxNQUFNLEdBQUdiLElBQUksQ0FBQ1ksT0FBTCxDQUFhLEdBQWIsQ0FBZjs7QUFDQSxNQUFJRCxPQUFPLElBQUksQ0FBQyxDQUFaLElBQWlCRSxNQUFNLElBQUksQ0FBQyxDQUFoQyxFQUFtQztBQUNqQyxVQUFNLElBQUluQixLQUFLLENBQUNTLEtBQVYsQ0FDSlQsS0FBSyxDQUFDUyxLQUFOLENBQVlDLGdCQURSLEVBRUosbUNBRkksQ0FBTjtBQUlEOztBQUNESixFQUFBQSxJQUFJLEdBQUdBLElBQUksQ0FBQ2MsU0FBTCxDQUFlSCxPQUFPLEdBQUcsQ0FBekIsRUFBNEJFLE1BQU0sR0FBRyxDQUFyQyxDQUFQO0FBQ0EsU0FBT0UsSUFBSSxDQUFDQyxLQUFMLENBQVdoQixJQUFYLENBQVA7QUFDRDs7QUFFRGlCLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmYixFQUFBQSxhQURlO0FBRWZWLEVBQUFBLGdCQUZlO0FBR2ZlLEVBQUFBO0FBSGUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIHFxIEdyYXBoIEFQSS5cbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIGdyYXBoUmVxdWVzdCgnbWU/YWNjZXNzX3Rva2VuPScgKyBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pLnRoZW4oZnVuY3Rpb24oXG4gICAgZGF0YVxuICApIHtcbiAgICBpZiAoZGF0YSAmJiBkYXRhLm9wZW5pZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ3FxIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICApO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBxcSBncmFwaCByZXF1ZXN0cy5cbmZ1bmN0aW9uIGdyYXBoUmVxdWVzdChwYXRoKSB7XG4gIHJldHVybiBodHRwc1JlcXVlc3RcbiAgICAuZ2V0KCdodHRwczovL2dyYXBoLnFxLmNvbS9vYXV0aDIuMC8nICsgcGF0aCwgdHJ1ZSlcbiAgICAudGhlbihkYXRhID0+IHtcbiAgICAgIHJldHVybiBwYXJzZVJlc3BvbnNlRGF0YShkYXRhKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcGFyc2VSZXNwb25zZURhdGEoZGF0YSkge1xuICBjb25zdCBzdGFyUG9zID0gZGF0YS5pbmRleE9mKCcoJyk7XG4gIGNvbnN0IGVuZFBvcyA9IGRhdGEuaW5kZXhPZignKScpO1xuICBpZiAoc3RhclBvcyA9PSAtMSB8fCBlbmRQb3MgPT0gLTEpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ3FxIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICApO1xuICB9XG4gIGRhdGEgPSBkYXRhLnN1YnN0cmluZyhzdGFyUG9zICsgMSwgZW5kUG9zIC0gMSk7XG4gIHJldHVybiBKU09OLnBhcnNlKGRhdGEpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YSxcbiAgcGFyc2VSZXNwb25zZURhdGEsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/spotify.js b/lib/Adapters/Auth/spotify.js new file mode 100644 index 0000000000..a4eda323f6 --- /dev/null +++ b/lib/Adapters/Auth/spotify.js @@ -0,0 +1,51 @@ +"use strict"; + +// Helper functions for accessing the Spotify API. +const httpsRequest = require('./httpsRequest'); + +var Parse = require('parse/node').Parse; // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return request('me', authData.access_token).then(data => { + if (data && data.id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Spotify auth is invalid for this user.'); + }); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId(appIds, authData) { + var access_token = authData.access_token; + + if (!appIds.length) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Spotify auth is not configured.'); + } + + return request('me', access_token).then(data => { + if (data && appIds.indexOf(data.id) != -1) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Spotify auth is invalid for this user.'); + }); +} // A promisey wrapper for Spotify API requests. + + +function request(path, access_token) { + return httpsRequest.get({ + host: 'api.spotify.com', + path: '/v1/' + path, + headers: { + Authorization: 'Bearer ' + access_token + } + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3Nwb3RpZnkuanMiXSwibmFtZXMiOlsiaHR0cHNSZXF1ZXN0IiwicmVxdWlyZSIsIlBhcnNlIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwicmVxdWVzdCIsImFjY2Vzc190b2tlbiIsInRoZW4iLCJkYXRhIiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUFwcElkIiwiYXBwSWRzIiwibGVuZ3RoIiwiaW5kZXhPZiIsInBhdGgiLCJnZXQiLCJob3N0IiwiaGVhZGVycyIsIkF1dGhvcml6YXRpb24iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsTUFBTUEsWUFBWSxHQUFHQyxPQUFPLENBQUMsZ0JBQUQsQ0FBNUI7O0FBQ0EsSUFBSUMsS0FBSyxHQUFHRCxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCQyxLQUFsQyxDLENBRUE7OztBQUNBLFNBQVNDLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxPQUFPLENBQUMsSUFBRCxFQUFPRCxRQUFRLENBQUNFLFlBQWhCLENBQVAsQ0FBcUNDLElBQXJDLENBQTBDQyxJQUFJLElBQUk7QUFDdkQsUUFBSUEsSUFBSSxJQUFJQSxJQUFJLENBQUNDLEVBQUwsSUFBV0wsUUFBUSxDQUFDSyxFQUFoQyxFQUFvQztBQUNsQztBQUNEOztBQUNELFVBQU0sSUFBSVAsS0FBSyxDQUFDUSxLQUFWLENBQ0pSLEtBQUssQ0FBQ1EsS0FBTixDQUFZQyxnQkFEUixFQUVKLHdDQUZJLENBQU47QUFJRCxHQVJNLENBQVA7QUFTRCxDLENBRUQ7OztBQUNBLFNBQVNDLGFBQVQsQ0FBdUJDLE1BQXZCLEVBQStCVCxRQUEvQixFQUF5QztBQUN2QyxNQUFJRSxZQUFZLEdBQUdGLFFBQVEsQ0FBQ0UsWUFBNUI7O0FBQ0EsTUFBSSxDQUFDTyxNQUFNLENBQUNDLE1BQVosRUFBb0I7QUFDbEIsVUFBTSxJQUFJWixLQUFLLENBQUNRLEtBQVYsQ0FDSlIsS0FBSyxDQUFDUSxLQUFOLENBQVlDLGdCQURSLEVBRUosaUNBRkksQ0FBTjtBQUlEOztBQUNELFNBQU9OLE9BQU8sQ0FBQyxJQUFELEVBQU9DLFlBQVAsQ0FBUCxDQUE0QkMsSUFBNUIsQ0FBaUNDLElBQUksSUFBSTtBQUM5QyxRQUFJQSxJQUFJLElBQUlLLE1BQU0sQ0FBQ0UsT0FBUCxDQUFlUCxJQUFJLENBQUNDLEVBQXBCLEtBQTJCLENBQUMsQ0FBeEMsRUFBMkM7QUFDekM7QUFDRDs7QUFDRCxVQUFNLElBQUlQLEtBQUssQ0FBQ1EsS0FBVixDQUNKUixLQUFLLENBQUNRLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix3Q0FGSSxDQUFOO0FBSUQsR0FSTSxDQUFQO0FBU0QsQyxDQUVEOzs7QUFDQSxTQUFTTixPQUFULENBQWlCVyxJQUFqQixFQUF1QlYsWUFBdkIsRUFBcUM7QUFDbkMsU0FBT04sWUFBWSxDQUFDaUIsR0FBYixDQUFpQjtBQUN0QkMsSUFBQUEsSUFBSSxFQUFFLGlCQURnQjtBQUV0QkYsSUFBQUEsSUFBSSxFQUFFLFNBQVNBLElBRk87QUFHdEJHLElBQUFBLE9BQU8sRUFBRTtBQUNQQyxNQUFBQSxhQUFhLEVBQUUsWUFBWWQ7QUFEcEI7QUFIYSxHQUFqQixDQUFQO0FBT0Q7O0FBRURlLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmVixFQUFBQSxhQUFhLEVBQUVBLGFBREE7QUFFZlQsRUFBQUEsZ0JBQWdCLEVBQUVBO0FBRkgsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIFNwb3RpZnkgQVBJLlxuY29uc3QgaHR0cHNSZXF1ZXN0ID0gcmVxdWlyZSgnLi9odHRwc1JlcXVlc3QnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyB1c2VyIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSkge1xuICByZXR1cm4gcmVxdWVzdCgnbWUnLCBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pLnRoZW4oZGF0YSA9PiB7XG4gICAgaWYgKGRhdGEgJiYgZGF0YS5pZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ1Nwb3RpZnkgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZChhcHBJZHMsIGF1dGhEYXRhKSB7XG4gIHZhciBhY2Nlc3NfdG9rZW4gPSBhdXRoRGF0YS5hY2Nlc3NfdG9rZW47XG4gIGlmICghYXBwSWRzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnU3BvdGlmeSBhdXRoIGlzIG5vdCBjb25maWd1cmVkLidcbiAgICApO1xuICB9XG4gIHJldHVybiByZXF1ZXN0KCdtZScsIGFjY2Vzc190b2tlbikudGhlbihkYXRhID0+IHtcbiAgICBpZiAoZGF0YSAmJiBhcHBJZHMuaW5kZXhPZihkYXRhLmlkKSAhPSAtMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ1Nwb3RpZnkgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIFNwb3RpZnkgQVBJIHJlcXVlc3RzLlxuZnVuY3Rpb24gcmVxdWVzdChwYXRoLCBhY2Nlc3NfdG9rZW4pIHtcbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5nZXQoe1xuICAgIGhvc3Q6ICdhcGkuc3BvdGlmeS5jb20nLFxuICAgIHBhdGg6ICcvdjEvJyArIHBhdGgsXG4gICAgaGVhZGVyczoge1xuICAgICAgQXV0aG9yaXphdGlvbjogJ0JlYXJlciAnICsgYWNjZXNzX3Rva2VuLFxuICAgIH0sXG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YSxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/twitter.js b/lib/Adapters/Auth/twitter.js new file mode 100644 index 0000000000..75684e3834 --- /dev/null +++ b/lib/Adapters/Auth/twitter.js @@ -0,0 +1,60 @@ +"use strict"; + +// Helper functions for accessing the twitter API. +var OAuth = require('./OAuth1Client'); + +var Parse = require('parse/node').Parse; // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData, options) { + if (!options) { + throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Twitter auth configuration missing'); + } + + options = handleMultipleConfigurations(authData, options); + var client = new OAuth(options); + client.host = 'api.twitter.com'; + client.auth_token = authData.auth_token; + client.auth_token_secret = authData.auth_token_secret; + return client.get('/1.1/account/verify_credentials.json').then(data => { + if (data && data.id_str == '' + authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Twitter auth is invalid for this user.'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} + +function handleMultipleConfigurations(authData, options) { + if (Array.isArray(options)) { + const consumer_key = authData.consumer_key; + + if (!consumer_key) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Twitter auth is invalid for this user.'); + } + + options = options.filter(option => { + return option.consumer_key == consumer_key; + }); + + if (options.length == 0) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Twitter auth is invalid for this user.'); + } + + options = options[0]; + } + + return options; +} + +module.exports = { + validateAppId, + validateAuthData, + handleMultipleConfigurations +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3R3aXR0ZXIuanMiXSwibmFtZXMiOlsiT0F1dGgiLCJyZXF1aXJlIiwiUGFyc2UiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJvcHRpb25zIiwiRXJyb3IiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJoYW5kbGVNdWx0aXBsZUNvbmZpZ3VyYXRpb25zIiwiY2xpZW50IiwiaG9zdCIsImF1dGhfdG9rZW4iLCJhdXRoX3Rva2VuX3NlY3JldCIsImdldCIsInRoZW4iLCJkYXRhIiwiaWRfc3RyIiwiaWQiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwiQXJyYXkiLCJpc0FycmF5IiwiY29uc3VtZXJfa2V5IiwiZmlsdGVyIiwib3B0aW9uIiwibGVuZ3RoIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLEtBQUssR0FBR0MsT0FBTyxDQUFDLGdCQUFELENBQW5COztBQUNBLElBQUlDLEtBQUssR0FBR0QsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkMsS0FBbEMsQyxDQUVBOzs7QUFDQSxTQUFTQyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQXBDLEVBQTZDO0FBQzNDLE1BQUksQ0FBQ0EsT0FBTCxFQUFjO0FBQ1osVUFBTSxJQUFJSCxLQUFLLENBQUNJLEtBQVYsQ0FDSkosS0FBSyxDQUFDSSxLQUFOLENBQVlDLHFCQURSLEVBRUosb0NBRkksQ0FBTjtBQUlEOztBQUNERixFQUFBQSxPQUFPLEdBQUdHLDRCQUE0QixDQUFDSixRQUFELEVBQVdDLE9BQVgsQ0FBdEM7QUFDQSxNQUFJSSxNQUFNLEdBQUcsSUFBSVQsS0FBSixDQUFVSyxPQUFWLENBQWI7QUFDQUksRUFBQUEsTUFBTSxDQUFDQyxJQUFQLEdBQWMsaUJBQWQ7QUFDQUQsRUFBQUEsTUFBTSxDQUFDRSxVQUFQLEdBQW9CUCxRQUFRLENBQUNPLFVBQTdCO0FBQ0FGLEVBQUFBLE1BQU0sQ0FBQ0csaUJBQVAsR0FBMkJSLFFBQVEsQ0FBQ1EsaUJBQXBDO0FBRUEsU0FBT0gsTUFBTSxDQUFDSSxHQUFQLENBQVcsc0NBQVgsRUFBbURDLElBQW5ELENBQXdEQyxJQUFJLElBQUk7QUFDckUsUUFBSUEsSUFBSSxJQUFJQSxJQUFJLENBQUNDLE1BQUwsSUFBZSxLQUFLWixRQUFRLENBQUNhLEVBQXpDLEVBQTZDO0FBQzNDO0FBQ0Q7O0FBQ0QsVUFBTSxJQUFJZixLQUFLLENBQUNJLEtBQVYsQ0FDSkosS0FBSyxDQUFDSSxLQUFOLENBQVlZLGdCQURSLEVBRUosd0NBRkksQ0FBTjtBQUlELEdBUk0sQ0FBUDtBQVNELEMsQ0FFRDs7O0FBQ0EsU0FBU0MsYUFBVCxHQUF5QjtBQUN2QixTQUFPQyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNEOztBQUVELFNBQVNiLDRCQUFULENBQXNDSixRQUF0QyxFQUFnREMsT0FBaEQsRUFBeUQ7QUFDdkQsTUFBSWlCLEtBQUssQ0FBQ0MsT0FBTixDQUFjbEIsT0FBZCxDQUFKLEVBQTRCO0FBQzFCLFVBQU1tQixZQUFZLEdBQUdwQixRQUFRLENBQUNvQixZQUE5Qjs7QUFDQSxRQUFJLENBQUNBLFlBQUwsRUFBbUI7QUFDakIsWUFBTSxJQUFJdEIsS0FBSyxDQUFDSSxLQUFWLENBQ0pKLEtBQUssQ0FBQ0ksS0FBTixDQUFZWSxnQkFEUixFQUVKLHdDQUZJLENBQU47QUFJRDs7QUFDRGIsSUFBQUEsT0FBTyxHQUFHQSxPQUFPLENBQUNvQixNQUFSLENBQWVDLE1BQU0sSUFBSTtBQUNqQyxhQUFPQSxNQUFNLENBQUNGLFlBQVAsSUFBdUJBLFlBQTlCO0FBQ0QsS0FGUyxDQUFWOztBQUlBLFFBQUluQixPQUFPLENBQUNzQixNQUFSLElBQWtCLENBQXRCLEVBQXlCO0FBQ3ZCLFlBQU0sSUFBSXpCLEtBQUssQ0FBQ0ksS0FBVixDQUNKSixLQUFLLENBQUNJLEtBQU4sQ0FBWVksZ0JBRFIsRUFFSix3Q0FGSSxDQUFOO0FBSUQ7O0FBQ0RiLElBQUFBLE9BQU8sR0FBR0EsT0FBTyxDQUFDLENBQUQsQ0FBakI7QUFDRDs7QUFDRCxTQUFPQSxPQUFQO0FBQ0Q7O0FBRUR1QixNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZlYsRUFBQUEsYUFEZTtBQUVmaEIsRUFBQUEsZ0JBRmU7QUFHZkssRUFBQUE7QUFIZSxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgdHdpdHRlciBBUEkuXG52YXIgT0F1dGggPSByZXF1aXJlKCcuL09BdXRoMUNsaWVudCcpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gIGlmICghb3B0aW9ucykge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICdUd2l0dGVyIGF1dGggY29uZmlndXJhdGlvbiBtaXNzaW5nJ1xuICAgICk7XG4gIH1cbiAgb3B0aW9ucyA9IGhhbmRsZU11bHRpcGxlQ29uZmlndXJhdGlvbnMoYXV0aERhdGEsIG9wdGlvbnMpO1xuICB2YXIgY2xpZW50ID0gbmV3IE9BdXRoKG9wdGlvbnMpO1xuICBjbGllbnQuaG9zdCA9ICdhcGkudHdpdHRlci5jb20nO1xuICBjbGllbnQuYXV0aF90b2tlbiA9IGF1dGhEYXRhLmF1dGhfdG9rZW47XG4gIGNsaWVudC5hdXRoX3Rva2VuX3NlY3JldCA9IGF1dGhEYXRhLmF1dGhfdG9rZW5fc2VjcmV0O1xuXG4gIHJldHVybiBjbGllbnQuZ2V0KCcvMS4xL2FjY291bnQvdmVyaWZ5X2NyZWRlbnRpYWxzLmpzb24nKS50aGVuKGRhdGEgPT4ge1xuICAgIGlmIChkYXRhICYmIGRhdGEuaWRfc3RyID09ICcnICsgYXV0aERhdGEuaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdUd2l0dGVyIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICApO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU11bHRpcGxlQ29uZmlndXJhdGlvbnMoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHtcbiAgICBjb25zdCBjb25zdW1lcl9rZXkgPSBhdXRoRGF0YS5jb25zdW1lcl9rZXk7XG4gICAgaWYgKCFjb25zdW1lcl9rZXkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ1R3aXR0ZXIgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMuZmlsdGVyKG9wdGlvbiA9PiB7XG4gICAgICByZXR1cm4gb3B0aW9uLmNvbnN1bWVyX2tleSA9PSBjb25zdW1lcl9rZXk7XG4gICAgfSk7XG5cbiAgICBpZiAob3B0aW9ucy5sZW5ndGggPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnVHdpdHRlciBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nXG4gICAgICApO1xuICAgIH1cbiAgICBvcHRpb25zID0gb3B0aW9uc1swXTtcbiAgfVxuICByZXR1cm4gb3B0aW9ucztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGEsXG4gIGhhbmRsZU11bHRpcGxlQ29uZmlndXJhdGlvbnMsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/vkontakte.js b/lib/Adapters/Auth/vkontakte.js new file mode 100644 index 0000000000..53cda75404 --- /dev/null +++ b/lib/Adapters/Auth/vkontakte.js @@ -0,0 +1,50 @@ +'use strict'; // Helper functions for accessing the vkontakte API. + +const httpsRequest = require('./httpsRequest'); + +var Parse = require('parse/node').Parse; // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData, params) { + return vkOAuth2Request(params).then(function (response) { + if (response && response.access_token) { + return request('api.vk.com', 'method/users.get?access_token=' + authData.access_token + '&v=5.8').then(function (response) { + if (response && response.response && response.response.length && response.response[0].id == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Vk auth is invalid for this user.'); + }); + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Vk appIds or appSecret is incorrect.'); + }); +} + +function vkOAuth2Request(params) { + return new Promise(function (resolve) { + if (!params || !params.appIds || !params.appIds.length || !params.appSecret || !params.appSecret.length) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Vk auth is not configured. Missing appIds or appSecret.'); + } + + resolve(); + }).then(function () { + return request('oauth.vk.com', 'access_token?client_id=' + params.appIds + '&client_secret=' + params.appSecret + '&v=5.59&grant_type=client_credentials'); + }); +} // Returns a promise that fulfills iff this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for api requests + + +function request(host, path) { + return httpsRequest.get('https://' + host + '/' + path); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3Zrb250YWt0ZS5qcyJdLCJuYW1lcyI6WyJodHRwc1JlcXVlc3QiLCJyZXF1aXJlIiwiUGFyc2UiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJwYXJhbXMiLCJ2a09BdXRoMlJlcXVlc3QiLCJ0aGVuIiwicmVzcG9uc2UiLCJhY2Nlc3NfdG9rZW4iLCJyZXF1ZXN0IiwibGVuZ3RoIiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImFwcElkcyIsImFwcFNlY3JldCIsInZhbGlkYXRlQXBwSWQiLCJob3N0IiwicGF0aCIsImdldCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiJBQUFBLGEsQ0FFQTs7QUFFQSxNQUFNQSxZQUFZLEdBQUdDLE9BQU8sQ0FBQyxnQkFBRCxDQUE1Qjs7QUFDQSxJQUFJQyxLQUFLLEdBQUdELE9BQU8sQ0FBQyxZQUFELENBQVAsQ0FBc0JDLEtBQWxDLEMsQ0FFQTs7O0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DQyxNQUFwQyxFQUE0QztBQUMxQyxTQUFPQyxlQUFlLENBQUNELE1BQUQsQ0FBZixDQUF3QkUsSUFBeEIsQ0FBNkIsVUFBU0MsUUFBVCxFQUFtQjtBQUNyRCxRQUFJQSxRQUFRLElBQUlBLFFBQVEsQ0FBQ0MsWUFBekIsRUFBdUM7QUFDckMsYUFBT0MsT0FBTyxDQUNaLFlBRFksRUFFWixtQ0FBbUNOLFFBQVEsQ0FBQ0ssWUFBNUMsR0FBMkQsUUFGL0MsQ0FBUCxDQUdMRixJQUhLLENBR0EsVUFBU0MsUUFBVCxFQUFtQjtBQUN4QixZQUNFQSxRQUFRLElBQ1JBLFFBQVEsQ0FBQ0EsUUFEVCxJQUVBQSxRQUFRLENBQUNBLFFBQVQsQ0FBa0JHLE1BRmxCLElBR0FILFFBQVEsQ0FBQ0EsUUFBVCxDQUFrQixDQUFsQixFQUFxQkksRUFBckIsSUFBMkJSLFFBQVEsQ0FBQ1EsRUFKdEMsRUFLRTtBQUNBO0FBQ0Q7O0FBQ0QsY0FBTSxJQUFJVixLQUFLLENBQUNXLEtBQVYsQ0FDSlgsS0FBSyxDQUFDVyxLQUFOLENBQVlDLGdCQURSLEVBRUosbUNBRkksQ0FBTjtBQUlELE9BaEJNLENBQVA7QUFpQkQ7O0FBQ0QsVUFBTSxJQUFJWixLQUFLLENBQUNXLEtBQVYsQ0FDSlgsS0FBSyxDQUFDVyxLQUFOLENBQVlDLGdCQURSLEVBRUosc0NBRkksQ0FBTjtBQUlELEdBeEJNLENBQVA7QUF5QkQ7O0FBRUQsU0FBU1IsZUFBVCxDQUF5QkQsTUFBekIsRUFBaUM7QUFDL0IsU0FBTyxJQUFJVSxPQUFKLENBQVksVUFBU0MsT0FBVCxFQUFrQjtBQUNuQyxRQUNFLENBQUNYLE1BQUQsSUFDQSxDQUFDQSxNQUFNLENBQUNZLE1BRFIsSUFFQSxDQUFDWixNQUFNLENBQUNZLE1BQVAsQ0FBY04sTUFGZixJQUdBLENBQUNOLE1BQU0sQ0FBQ2EsU0FIUixJQUlBLENBQUNiLE1BQU0sQ0FBQ2EsU0FBUCxDQUFpQlAsTUFMcEIsRUFNRTtBQUNBLFlBQU0sSUFBSVQsS0FBSyxDQUFDVyxLQUFWLENBQ0pYLEtBQUssQ0FBQ1csS0FBTixDQUFZQyxnQkFEUixFQUVKLHlEQUZJLENBQU47QUFJRDs7QUFDREUsSUFBQUEsT0FBTztBQUNSLEdBZE0sRUFjSlQsSUFkSSxDQWNDLFlBQVc7QUFDakIsV0FBT0csT0FBTyxDQUNaLGNBRFksRUFFWiw0QkFDRUwsTUFBTSxDQUFDWSxNQURULEdBRUUsaUJBRkYsR0FHRVosTUFBTSxDQUFDYSxTQUhULEdBSUUsdUNBTlUsQ0FBZDtBQVFELEdBdkJNLENBQVA7QUF3QkQsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9KLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTTixPQUFULENBQWlCVSxJQUFqQixFQUF1QkMsSUFBdkIsRUFBNkI7QUFDM0IsU0FBT3JCLFlBQVksQ0FBQ3NCLEdBQWIsQ0FBaUIsYUFBYUYsSUFBYixHQUFvQixHQUFwQixHQUEwQkMsSUFBM0MsQ0FBUDtBQUNEOztBQUVERSxNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZkwsRUFBQUEsYUFBYSxFQUFFQSxhQURBO0FBRWZoQixFQUFBQSxnQkFBZ0IsRUFBRUE7QUFGSCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSB2a29udGFrdGUgQVBJLlxuXG5jb25zdCBodHRwc1JlcXVlc3QgPSByZXF1aXJlKCcuL2h0dHBzUmVxdWVzdCcpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBwYXJhbXMpIHtcbiAgcmV0dXJuIHZrT0F1dGgyUmVxdWVzdChwYXJhbXMpLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UuYWNjZXNzX3Rva2VuKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdChcbiAgICAgICAgJ2FwaS52ay5jb20nLFxuICAgICAgICAnbWV0aG9kL3VzZXJzLmdldD9hY2Nlc3NfdG9rZW49JyArIGF1dGhEYXRhLmFjY2Vzc190b2tlbiArICcmdj01LjgnXG4gICAgICApLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHJlc3BvbnNlICYmXG4gICAgICAgICAgcmVzcG9uc2UucmVzcG9uc2UgJiZcbiAgICAgICAgICByZXNwb25zZS5yZXNwb25zZS5sZW5ndGggJiZcbiAgICAgICAgICByZXNwb25zZS5yZXNwb25zZVswXS5pZCA9PSBhdXRoRGF0YS5pZFxuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgJ1ZrIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ1ZrIGFwcElkcyBvciBhcHBTZWNyZXQgaXMgaW5jb3JyZWN0LidcbiAgICApO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdmtPQXV0aDJSZXF1ZXN0KHBhcmFtcykge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgIGlmIChcbiAgICAgICFwYXJhbXMgfHxcbiAgICAgICFwYXJhbXMuYXBwSWRzIHx8XG4gICAgICAhcGFyYW1zLmFwcElkcy5sZW5ndGggfHxcbiAgICAgICFwYXJhbXMuYXBwU2VjcmV0IHx8XG4gICAgICAhcGFyYW1zLmFwcFNlY3JldC5sZW5ndGhcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ1ZrIGF1dGggaXMgbm90IGNvbmZpZ3VyZWQuIE1pc3NpbmcgYXBwSWRzIG9yIGFwcFNlY3JldC4nXG4gICAgICApO1xuICAgIH1cbiAgICByZXNvbHZlKCk7XG4gIH0pLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHJlcXVlc3QoXG4gICAgICAnb2F1dGgudmsuY29tJyxcbiAgICAgICdhY2Nlc3NfdG9rZW4/Y2xpZW50X2lkPScgK1xuICAgICAgICBwYXJhbXMuYXBwSWRzICtcbiAgICAgICAgJyZjbGllbnRfc2VjcmV0PScgK1xuICAgICAgICBwYXJhbXMuYXBwU2VjcmV0ICtcbiAgICAgICAgJyZ2PTUuNTkmZ3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMnXG4gICAgKTtcbiAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChob3N0LCBwYXRoKSB7XG4gIHJldHVybiBodHRwc1JlcXVlc3QuZ2V0KCdodHRwczovLycgKyBob3N0ICsgJy8nICsgcGF0aCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/wechat.js b/lib/Adapters/Auth/wechat.js new file mode 100644 index 0000000000..f1c429f593 --- /dev/null +++ b/lib/Adapters/Auth/wechat.js @@ -0,0 +1,33 @@ +"use strict"; + +// Helper functions for accessing the WeChat Graph API. +const httpsRequest = require('./httpsRequest'); + +var Parse = require('parse/node').Parse; // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return graphRequest('auth?access_token=' + authData.access_token + '&openid=' + authData.id).then(function (data) { + if (data.errcode == 0) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'wechat auth is invalid for this user.'); + }); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for WeChat graph requests. + + +function graphRequest(path) { + return httpsRequest.get('https://api.weixin.qq.com/sns/' + path); +} + +module.exports = { + validateAppId, + validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3dlY2hhdC5qcyJdLCJuYW1lcyI6WyJodHRwc1JlcXVlc3QiLCJyZXF1aXJlIiwiUGFyc2UiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJncmFwaFJlcXVlc3QiLCJhY2Nlc3NfdG9rZW4iLCJpZCIsInRoZW4iLCJkYXRhIiwiZXJyY29kZSIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBhdGgiLCJnZXQiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsTUFBTUEsWUFBWSxHQUFHQyxPQUFPLENBQUMsZ0JBQUQsQ0FBNUI7O0FBQ0EsSUFBSUMsS0FBSyxHQUFHRCxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCQyxLQUFsQyxDLENBRUE7OztBQUNBLFNBQVNDLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxZQUFZLENBQ2pCLHVCQUF1QkQsUUFBUSxDQUFDRSxZQUFoQyxHQUErQyxVQUEvQyxHQUE0REYsUUFBUSxDQUFDRyxFQURwRCxDQUFaLENBRUxDLElBRkssQ0FFQSxVQUFTQyxJQUFULEVBQWU7QUFDcEIsUUFBSUEsSUFBSSxDQUFDQyxPQUFMLElBQWdCLENBQXBCLEVBQXVCO0FBQ3JCO0FBQ0Q7O0FBQ0QsVUFBTSxJQUFJUixLQUFLLENBQUNTLEtBQVYsQ0FDSlQsS0FBSyxDQUFDUyxLQUFOLENBQVlDLGdCQURSLEVBRUosdUNBRkksQ0FBTjtBQUlELEdBVk0sQ0FBUDtBQVdELEMsQ0FFRDs7O0FBQ0EsU0FBU0MsYUFBVCxHQUF5QjtBQUN2QixTQUFPQyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNELEMsQ0FFRDs7O0FBQ0EsU0FBU1YsWUFBVCxDQUFzQlcsSUFBdEIsRUFBNEI7QUFDMUIsU0FBT2hCLFlBQVksQ0FBQ2lCLEdBQWIsQ0FBaUIsbUNBQW1DRCxJQUFwRCxDQUFQO0FBQ0Q7O0FBRURFLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmTixFQUFBQSxhQURlO0FBRWZWLEVBQUFBO0FBRmUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIFdlQ2hhdCBHcmFwaCBBUEkuXG5jb25zdCBodHRwc1JlcXVlc3QgPSByZXF1aXJlKCcuL2h0dHBzUmVxdWVzdCcpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIHJldHVybiBncmFwaFJlcXVlc3QoXG4gICAgJ2F1dGg/YWNjZXNzX3Rva2VuPScgKyBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4gKyAnJm9wZW5pZD0nICsgYXV0aERhdGEuaWRcbiAgKS50aGVuKGZ1bmN0aW9uKGRhdGEpIHtcbiAgICBpZiAoZGF0YS5lcnJjb2RlID09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICd3ZWNoYXQgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIFdlQ2hhdCBncmFwaCByZXF1ZXN0cy5cbmZ1bmN0aW9uIGdyYXBoUmVxdWVzdChwYXRoKSB7XG4gIHJldHVybiBodHRwc1JlcXVlc3QuZ2V0KCdodHRwczovL2FwaS53ZWl4aW4ucXEuY29tL3Nucy8nICsgcGF0aCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/weibo.js b/lib/Adapters/Auth/weibo.js new file mode 100644 index 0000000000..701866d6ae --- /dev/null +++ b/lib/Adapters/Auth/weibo.js @@ -0,0 +1,47 @@ +"use strict"; + +// Helper functions for accessing the weibo Graph API. +var httpsRequest = require('./httpsRequest'); + +var Parse = require('parse/node').Parse; + +var querystring = require('querystring'); // Returns a promise that fulfills iff this user id is valid. + + +function validateAuthData(authData) { + return graphRequest(authData.access_token).then(function (data) { + if (data && data.uid == authData.id) { + return; + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'weibo auth is invalid for this user.'); + }); +} // Returns a promise that fulfills if this app id is valid. + + +function validateAppId() { + return Promise.resolve(); +} // A promisey wrapper for weibo graph requests. + + +function graphRequest(access_token) { + var postData = querystring.stringify({ + access_token: access_token + }); + var options = { + hostname: 'api.weibo.com', + path: '/oauth2/get_token_info', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(postData) + } + }; + return httpsRequest.request(options, postData); +} + +module.exports = { + validateAppId, + validateAuthData +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3dlaWJvLmpzIl0sIm5hbWVzIjpbImh0dHBzUmVxdWVzdCIsInJlcXVpcmUiLCJQYXJzZSIsInF1ZXJ5c3RyaW5nIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwiZ3JhcGhSZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJ1aWQiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBvc3REYXRhIiwic3RyaW5naWZ5Iiwib3B0aW9ucyIsImhvc3RuYW1lIiwicGF0aCIsIm1ldGhvZCIsImhlYWRlcnMiLCJCdWZmZXIiLCJieXRlTGVuZ3RoIiwicmVxdWVzdCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxZQUFZLEdBQUdDLE9BQU8sQ0FBQyxnQkFBRCxDQUExQjs7QUFDQSxJQUFJQyxLQUFLLEdBQUdELE9BQU8sQ0FBQyxZQUFELENBQVAsQ0FBc0JDLEtBQWxDOztBQUNBLElBQUlDLFdBQVcsR0FBR0YsT0FBTyxDQUFDLGFBQUQsQ0FBekIsQyxDQUVBOzs7QUFDQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsU0FBT0MsWUFBWSxDQUFDRCxRQUFRLENBQUNFLFlBQVYsQ0FBWixDQUFvQ0MsSUFBcEMsQ0FBeUMsVUFBU0MsSUFBVCxFQUFlO0FBQzdELFFBQUlBLElBQUksSUFBSUEsSUFBSSxDQUFDQyxHQUFMLElBQVlMLFFBQVEsQ0FBQ00sRUFBakMsRUFBcUM7QUFDbkM7QUFDRDs7QUFDRCxVQUFNLElBQUlULEtBQUssQ0FBQ1UsS0FBVixDQUNKVixLQUFLLENBQUNVLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSixzQ0FGSSxDQUFOO0FBSUQsR0FSTSxDQUFQO0FBU0QsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTVixZQUFULENBQXNCQyxZQUF0QixFQUFvQztBQUNsQyxNQUFJVSxRQUFRLEdBQUdkLFdBQVcsQ0FBQ2UsU0FBWixDQUFzQjtBQUNuQ1gsSUFBQUEsWUFBWSxFQUFFQTtBQURxQixHQUF0QixDQUFmO0FBR0EsTUFBSVksT0FBTyxHQUFHO0FBQ1pDLElBQUFBLFFBQVEsRUFBRSxlQURFO0FBRVpDLElBQUFBLElBQUksRUFBRSx3QkFGTTtBQUdaQyxJQUFBQSxNQUFNLEVBQUUsTUFISTtBQUlaQyxJQUFBQSxPQUFPLEVBQUU7QUFDUCxzQkFBZ0IsbUNBRFQ7QUFFUCx3QkFBa0JDLE1BQU0sQ0FBQ0MsVUFBUCxDQUFrQlIsUUFBbEI7QUFGWDtBQUpHLEdBQWQ7QUFTQSxTQUFPakIsWUFBWSxDQUFDMEIsT0FBYixDQUFxQlAsT0FBckIsRUFBOEJGLFFBQTlCLENBQVA7QUFDRDs7QUFFRFUsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZkLEVBQUFBLGFBRGU7QUFFZlYsRUFBQUE7QUFGZSxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgd2VpYm8gR3JhcGggQVBJLlxudmFyIGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG52YXIgcXVlcnlzdHJpbmcgPSByZXF1aXJlKCdxdWVyeXN0cmluZycpO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIHJldHVybiBncmFwaFJlcXVlc3QoYXV0aERhdGEuYWNjZXNzX3Rva2VuKS50aGVuKGZ1bmN0aW9uKGRhdGEpIHtcbiAgICBpZiAoZGF0YSAmJiBkYXRhLnVpZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgJ3dlaWJvIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICApO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciB3ZWlibyBncmFwaCByZXF1ZXN0cy5cbmZ1bmN0aW9uIGdyYXBoUmVxdWVzdChhY2Nlc3NfdG9rZW4pIHtcbiAgdmFyIHBvc3REYXRhID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHtcbiAgICBhY2Nlc3NfdG9rZW46IGFjY2Vzc190b2tlbixcbiAgfSk7XG4gIHZhciBvcHRpb25zID0ge1xuICAgIGhvc3RuYW1lOiAnYXBpLndlaWJvLmNvbScsXG4gICAgcGF0aDogJy9vYXV0aDIvZ2V0X3Rva2VuX2luZm8nLFxuICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyxcbiAgICAgICdDb250ZW50LUxlbmd0aCc6IEJ1ZmZlci5ieXRlTGVuZ3RoKHBvc3REYXRhKSxcbiAgICB9LFxuICB9O1xuICByZXR1cm4gaHR0cHNSZXF1ZXN0LnJlcXVlc3Qob3B0aW9ucywgcG9zdERhdGEpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YSxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Cache/CacheAdapter.js b/lib/Adapters/Cache/CacheAdapter.js new file mode 100644 index 0000000000..60e6d6e501 --- /dev/null +++ b/lib/Adapters/Cache/CacheAdapter.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CacheAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ + +/** + * @module Adapters + */ + +/** + * @interface CacheAdapter + */ +class CacheAdapter { + /** + * Get a value in the cache + * @param {String} key Cache key to get + * @return {Promise} that will eventually resolve to the value in the cache. + */ + get(key) {} + /** + * Set a value in the cache + * @param {String} key Cache key to set + * @param {String} value Value to set the key + * @param {String} ttl Optional TTL + */ + + + put(key, value, ttl) {} + /** + * Remove a value from the cache. + * @param {String} key Cache key to remove + */ + + + del(key) {} + /** + * Empty a cache + */ + + + clear() {} + +} + +exports.CacheAdapter = CacheAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9DYWNoZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsiQ2FjaGVBZGFwdGVyIiwiZ2V0Iiwia2V5IiwicHV0IiwidmFsdWUiLCJ0dGwiLCJkZWwiLCJjbGVhciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBR0E7OztBQUdPLE1BQU1BLFlBQU4sQ0FBbUI7QUFDeEI7Ozs7O0FBS0FDLEVBQUFBLEdBQUcsQ0FBQ0MsR0FBRCxFQUFNLENBQUU7QUFFWDs7Ozs7Ozs7QUFNQUMsRUFBQUEsR0FBRyxDQUFDRCxHQUFELEVBQU1FLEtBQU4sRUFBYUMsR0FBYixFQUFrQixDQUFFO0FBRXZCOzs7Ozs7QUFJQUMsRUFBQUEsR0FBRyxDQUFDSixHQUFELEVBQU0sQ0FBRTtBQUVYOzs7OztBQUdBSyxFQUFBQSxLQUFLLEdBQUcsQ0FBRTs7QUF6QmMiLCJzb3VyY2VzQ29udGVudCI6WyIvKmVzbGludCBuby11bnVzZWQtdmFyczogXCJvZmZcIiovXG4vKipcbiAqIEBtb2R1bGUgQWRhcHRlcnNcbiAqL1xuLyoqXG4gKiBAaW50ZXJmYWNlIENhY2hlQWRhcHRlclxuICovXG5leHBvcnQgY2xhc3MgQ2FjaGVBZGFwdGVyIHtcbiAgLyoqXG4gICAqIEdldCBhIHZhbHVlIGluIHRoZSBjYWNoZVxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5IENhY2hlIGtleSB0byBnZXRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gdGhhdCB3aWxsIGV2ZW50dWFsbHkgcmVzb2x2ZSB0byB0aGUgdmFsdWUgaW4gdGhlIGNhY2hlLlxuICAgKi9cbiAgZ2V0KGtleSkge31cblxuICAvKipcbiAgICogU2V0IGEgdmFsdWUgaW4gdGhlIGNhY2hlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBrZXkgQ2FjaGUga2V5IHRvIHNldFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgVmFsdWUgdG8gc2V0IHRoZSBrZXlcbiAgICogQHBhcmFtIHtTdHJpbmd9IHR0bCBPcHRpb25hbCBUVExcbiAgICovXG4gIHB1dChrZXksIHZhbHVlLCB0dGwpIHt9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBhIHZhbHVlIGZyb20gdGhlIGNhY2hlLlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5IENhY2hlIGtleSB0byByZW1vdmVcbiAgICovXG4gIGRlbChrZXkpIHt9XG5cbiAgLyoqXG4gICAqIEVtcHR5IGEgY2FjaGVcbiAgICovXG4gIGNsZWFyKCkge31cbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Cache/InMemoryCache.js b/lib/Adapters/Cache/InMemoryCache.js new file mode 100644 index 0000000000..b9a6543504 --- /dev/null +++ b/lib/Adapters/Cache/InMemoryCache.js @@ -0,0 +1,76 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.InMemoryCache = void 0; +const DEFAULT_CACHE_TTL = 5 * 1000; + +class InMemoryCache { + constructor({ + ttl = DEFAULT_CACHE_TTL + }) { + this.ttl = ttl; + this.cache = Object.create(null); + } + + get(key) { + const record = this.cache[key]; + + if (record == null) { + return null; + } // Has Record and isnt expired + + + if (isNaN(record.expire) || record.expire >= Date.now()) { + return record.value; + } // Record has expired + + + delete this.cache[key]; + return null; + } + + put(key, value, ttl = this.ttl) { + if (ttl < 0 || isNaN(ttl)) { + ttl = NaN; + } + + var record = { + value: value, + expire: ttl + Date.now() + }; + + if (!isNaN(record.expire)) { + record.timeout = setTimeout(() => { + this.del(key); + }, ttl); + } + + this.cache[key] = record; + } + + del(key) { + var record = this.cache[key]; + + if (record == null) { + return; + } + + if (record.timeout) { + clearTimeout(record.timeout); + } + + delete this.cache[key]; + } + + clear() { + this.cache = Object.create(null); + } + +} + +exports.InMemoryCache = InMemoryCache; +var _default = InMemoryCache; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9Jbk1lbW9yeUNhY2hlLmpzIl0sIm5hbWVzIjpbIkRFRkFVTFRfQ0FDSEVfVFRMIiwiSW5NZW1vcnlDYWNoZSIsImNvbnN0cnVjdG9yIiwidHRsIiwiY2FjaGUiLCJPYmplY3QiLCJjcmVhdGUiLCJnZXQiLCJrZXkiLCJyZWNvcmQiLCJpc05hTiIsImV4cGlyZSIsIkRhdGUiLCJub3ciLCJ2YWx1ZSIsInB1dCIsIk5hTiIsInRpbWVvdXQiLCJzZXRUaW1lb3V0IiwiZGVsIiwiY2xlYXJUaW1lb3V0IiwiY2xlYXIiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLE1BQU1BLGlCQUFpQixHQUFHLElBQUksSUFBOUI7O0FBRU8sTUFBTUMsYUFBTixDQUFvQjtBQUN6QkMsRUFBQUEsV0FBVyxDQUFDO0FBQUVDLElBQUFBLEdBQUcsR0FBR0g7QUFBUixHQUFELEVBQThCO0FBQ3ZDLFNBQUtHLEdBQUwsR0FBV0EsR0FBWDtBQUNBLFNBQUtDLEtBQUwsR0FBYUMsTUFBTSxDQUFDQyxNQUFQLENBQWMsSUFBZCxDQUFiO0FBQ0Q7O0FBRURDLEVBQUFBLEdBQUcsQ0FBQ0MsR0FBRCxFQUFNO0FBQ1AsVUFBTUMsTUFBTSxHQUFHLEtBQUtMLEtBQUwsQ0FBV0ksR0FBWCxDQUFmOztBQUNBLFFBQUlDLE1BQU0sSUFBSSxJQUFkLEVBQW9CO0FBQ2xCLGFBQU8sSUFBUDtBQUNELEtBSk0sQ0FNUDs7O0FBQ0EsUUFBSUMsS0FBSyxDQUFDRCxNQUFNLENBQUNFLE1BQVIsQ0FBTCxJQUF3QkYsTUFBTSxDQUFDRSxNQUFQLElBQWlCQyxJQUFJLENBQUNDLEdBQUwsRUFBN0MsRUFBeUQ7QUFDdkQsYUFBT0osTUFBTSxDQUFDSyxLQUFkO0FBQ0QsS0FUTSxDQVdQOzs7QUFDQSxXQUFPLEtBQUtWLEtBQUwsQ0FBV0ksR0FBWCxDQUFQO0FBQ0EsV0FBTyxJQUFQO0FBQ0Q7O0FBRURPLEVBQUFBLEdBQUcsQ0FBQ1AsR0FBRCxFQUFNTSxLQUFOLEVBQWFYLEdBQUcsR0FBRyxLQUFLQSxHQUF4QixFQUE2QjtBQUM5QixRQUFJQSxHQUFHLEdBQUcsQ0FBTixJQUFXTyxLQUFLLENBQUNQLEdBQUQsQ0FBcEIsRUFBMkI7QUFDekJBLE1BQUFBLEdBQUcsR0FBR2EsR0FBTjtBQUNEOztBQUVELFFBQUlQLE1BQU0sR0FBRztBQUNYSyxNQUFBQSxLQUFLLEVBQUVBLEtBREk7QUFFWEgsTUFBQUEsTUFBTSxFQUFFUixHQUFHLEdBQUdTLElBQUksQ0FBQ0MsR0FBTDtBQUZILEtBQWI7O0FBS0EsUUFBSSxDQUFDSCxLQUFLLENBQUNELE1BQU0sQ0FBQ0UsTUFBUixDQUFWLEVBQTJCO0FBQ3pCRixNQUFBQSxNQUFNLENBQUNRLE9BQVAsR0FBaUJDLFVBQVUsQ0FBQyxNQUFNO0FBQ2hDLGFBQUtDLEdBQUwsQ0FBU1gsR0FBVDtBQUNELE9BRjBCLEVBRXhCTCxHQUZ3QixDQUEzQjtBQUdEOztBQUVELFNBQUtDLEtBQUwsQ0FBV0ksR0FBWCxJQUFrQkMsTUFBbEI7QUFDRDs7QUFFRFUsRUFBQUEsR0FBRyxDQUFDWCxHQUFELEVBQU07QUFDUCxRQUFJQyxNQUFNLEdBQUcsS0FBS0wsS0FBTCxDQUFXSSxHQUFYLENBQWI7O0FBQ0EsUUFBSUMsTUFBTSxJQUFJLElBQWQsRUFBb0I7QUFDbEI7QUFDRDs7QUFFRCxRQUFJQSxNQUFNLENBQUNRLE9BQVgsRUFBb0I7QUFDbEJHLE1BQUFBLFlBQVksQ0FBQ1gsTUFBTSxDQUFDUSxPQUFSLENBQVo7QUFDRDs7QUFDRCxXQUFPLEtBQUtiLEtBQUwsQ0FBV0ksR0FBWCxDQUFQO0FBQ0Q7O0FBRURhLEVBQUFBLEtBQUssR0FBRztBQUNOLFNBQUtqQixLQUFMLEdBQWFDLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjLElBQWQsQ0FBYjtBQUNEOztBQXZEd0I7OztlQTBEWkwsYSIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IERFRkFVTFRfQ0FDSEVfVFRMID0gNSAqIDEwMDA7XG5cbmV4cG9ydCBjbGFzcyBJbk1lbW9yeUNhY2hlIHtcbiAgY29uc3RydWN0b3IoeyB0dGwgPSBERUZBVUxUX0NBQ0hFX1RUTCB9KSB7XG4gICAgdGhpcy50dGwgPSB0dGw7XG4gICAgdGhpcy5jYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gIH1cblxuICBnZXQoa2V5KSB7XG4gICAgY29uc3QgcmVjb3JkID0gdGhpcy5jYWNoZVtrZXldO1xuICAgIGlmIChyZWNvcmQgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gSGFzIFJlY29yZCBhbmQgaXNudCBleHBpcmVkXG4gICAgaWYgKGlzTmFOKHJlY29yZC5leHBpcmUpIHx8IHJlY29yZC5leHBpcmUgPj0gRGF0ZS5ub3coKSkge1xuICAgICAgcmV0dXJuIHJlY29yZC52YWx1ZTtcbiAgICB9XG5cbiAgICAvLyBSZWNvcmQgaGFzIGV4cGlyZWRcbiAgICBkZWxldGUgdGhpcy5jYWNoZVtrZXldO1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHV0KGtleSwgdmFsdWUsIHR0bCA9IHRoaXMudHRsKSB7XG4gICAgaWYgKHR0bCA8IDAgfHwgaXNOYU4odHRsKSkge1xuICAgICAgdHRsID0gTmFOO1xuICAgIH1cblxuICAgIHZhciByZWNvcmQgPSB7XG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICBleHBpcmU6IHR0bCArIERhdGUubm93KCksXG4gICAgfTtcblxuICAgIGlmICghaXNOYU4ocmVjb3JkLmV4cGlyZSkpIHtcbiAgICAgIHJlY29yZC50aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuZGVsKGtleSk7XG4gICAgICB9LCB0dGwpO1xuICAgIH1cblxuICAgIHRoaXMuY2FjaGVba2V5XSA9IHJlY29yZDtcbiAgfVxuXG4gIGRlbChrZXkpIHtcbiAgICB2YXIgcmVjb3JkID0gdGhpcy5jYWNoZVtrZXldO1xuICAgIGlmIChyZWNvcmQgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChyZWNvcmQudGltZW91dCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHJlY29yZC50aW1lb3V0KTtcbiAgICB9XG4gICAgZGVsZXRlIHRoaXMuY2FjaGVba2V5XTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHRoaXMuY2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEluTWVtb3J5Q2FjaGU7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Cache/InMemoryCacheAdapter.js b/lib/Adapters/Cache/InMemoryCacheAdapter.js new file mode 100644 index 0000000000..ffc38ce5ec --- /dev/null +++ b/lib/Adapters/Cache/InMemoryCacheAdapter.js @@ -0,0 +1,45 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.InMemoryCacheAdapter = void 0; + +var _LRUCache = require("./LRUCache"); + +class InMemoryCacheAdapter { + constructor(ctx) { + this.cache = new _LRUCache.LRUCache(ctx); + } + + get(key) { + const record = this.cache.get(key); + + if (record === null) { + return Promise.resolve(null); + } + + return Promise.resolve(record); + } + + put(key, value, ttl) { + this.cache.put(key, value, ttl); + return Promise.resolve(); + } + + del(key) { + this.cache.del(key); + return Promise.resolve(); + } + + clear() { + this.cache.clear(); + return Promise.resolve(); + } + +} + +exports.InMemoryCacheAdapter = InMemoryCacheAdapter; +var _default = InMemoryCacheAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9Jbk1lbW9yeUNhY2hlQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJJbk1lbW9yeUNhY2hlQWRhcHRlciIsImNvbnN0cnVjdG9yIiwiY3R4IiwiY2FjaGUiLCJMUlVDYWNoZSIsImdldCIsImtleSIsInJlY29yZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicHV0IiwidmFsdWUiLCJ0dGwiLCJkZWwiLCJjbGVhciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUVPLE1BQU1BLG9CQUFOLENBQTJCO0FBQ2hDQyxFQUFBQSxXQUFXLENBQUNDLEdBQUQsRUFBTTtBQUNmLFNBQUtDLEtBQUwsR0FBYSxJQUFJQyxrQkFBSixDQUFhRixHQUFiLENBQWI7QUFDRDs7QUFFREcsRUFBQUEsR0FBRyxDQUFDQyxHQUFELEVBQU07QUFDUCxVQUFNQyxNQUFNLEdBQUcsS0FBS0osS0FBTCxDQUFXRSxHQUFYLENBQWVDLEdBQWYsQ0FBZjs7QUFDQSxRQUFJQyxNQUFNLEtBQUssSUFBZixFQUFxQjtBQUNuQixhQUFPQyxPQUFPLENBQUNDLE9BQVIsQ0FBZ0IsSUFBaEIsQ0FBUDtBQUNEOztBQUNELFdBQU9ELE9BQU8sQ0FBQ0MsT0FBUixDQUFnQkYsTUFBaEIsQ0FBUDtBQUNEOztBQUVERyxFQUFBQSxHQUFHLENBQUNKLEdBQUQsRUFBTUssS0FBTixFQUFhQyxHQUFiLEVBQWtCO0FBQ25CLFNBQUtULEtBQUwsQ0FBV08sR0FBWCxDQUFlSixHQUFmLEVBQW9CSyxLQUFwQixFQUEyQkMsR0FBM0I7QUFDQSxXQUFPSixPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNEOztBQUVESSxFQUFBQSxHQUFHLENBQUNQLEdBQUQsRUFBTTtBQUNQLFNBQUtILEtBQUwsQ0FBV1UsR0FBWCxDQUFlUCxHQUFmO0FBQ0EsV0FBT0UsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFFREssRUFBQUEsS0FBSyxHQUFHO0FBQ04sU0FBS1gsS0FBTCxDQUFXVyxLQUFYO0FBQ0EsV0FBT04sT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUExQitCOzs7ZUE2Qm5CVCxvQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExSVUNhY2hlIH0gZnJvbSAnLi9MUlVDYWNoZSc7XG5cbmV4cG9ydCBjbGFzcyBJbk1lbW9yeUNhY2hlQWRhcHRlciB7XG4gIGNvbnN0cnVjdG9yKGN0eCkge1xuICAgIHRoaXMuY2FjaGUgPSBuZXcgTFJVQ2FjaGUoY3R4KTtcbiAgfVxuXG4gIGdldChrZXkpIHtcbiAgICBjb25zdCByZWNvcmQgPSB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgIGlmIChyZWNvcmQgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVjb3JkKTtcbiAgfVxuXG4gIHB1dChrZXksIHZhbHVlLCB0dGwpIHtcbiAgICB0aGlzLmNhY2hlLnB1dChrZXksIHZhbHVlLCB0dGwpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGRlbChrZXkpIHtcbiAgICB0aGlzLmNhY2hlLmRlbChrZXkpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHRoaXMuY2FjaGUuY2xlYXIoKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSW5NZW1vcnlDYWNoZUFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Cache/LRUCache.js b/lib/Adapters/Cache/LRUCache.js new file mode 100644 index 0000000000..9781621ecf --- /dev/null +++ b/lib/Adapters/Cache/LRUCache.js @@ -0,0 +1,46 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.LRUCache = void 0; + +var _lruCache = _interopRequireDefault(require("lru-cache")); + +var _defaults = _interopRequireDefault(require("../../defaults")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class LRUCache { + constructor({ + ttl = _defaults.default.cacheTTL, + maxSize = _defaults.default.cacheMaxSize + }) { + this.cache = new _lruCache.default({ + max: maxSize, + maxAge: ttl + }); + } + + get(key) { + return this.cache.get(key) || null; + } + + put(key, value, ttl = this.ttl) { + this.cache.set(key, value, ttl); + } + + del(key) { + this.cache.del(key); + } + + clear() { + this.cache.reset(); + } + +} + +exports.LRUCache = LRUCache; +var _default = LRUCache; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9MUlVDYWNoZS5qcyJdLCJuYW1lcyI6WyJMUlVDYWNoZSIsImNvbnN0cnVjdG9yIiwidHRsIiwiZGVmYXVsdHMiLCJjYWNoZVRUTCIsIm1heFNpemUiLCJjYWNoZU1heFNpemUiLCJjYWNoZSIsIkxSVSIsIm1heCIsIm1heEFnZSIsImdldCIsImtleSIsInB1dCIsInZhbHVlIiwic2V0IiwiZGVsIiwiY2xlYXIiLCJyZXNldCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBRU8sTUFBTUEsUUFBTixDQUFlO0FBQ3BCQyxFQUFBQSxXQUFXLENBQUM7QUFBRUMsSUFBQUEsR0FBRyxHQUFHQyxrQkFBU0MsUUFBakI7QUFBMkJDLElBQUFBLE9BQU8sR0FBR0Ysa0JBQVNHO0FBQTlDLEdBQUQsRUFBK0Q7QUFDeEUsU0FBS0MsS0FBTCxHQUFhLElBQUlDLGlCQUFKLENBQVE7QUFDbkJDLE1BQUFBLEdBQUcsRUFBRUosT0FEYztBQUVuQkssTUFBQUEsTUFBTSxFQUFFUjtBQUZXLEtBQVIsQ0FBYjtBQUlEOztBQUVEUyxFQUFBQSxHQUFHLENBQUNDLEdBQUQsRUFBTTtBQUNQLFdBQU8sS0FBS0wsS0FBTCxDQUFXSSxHQUFYLENBQWVDLEdBQWYsS0FBdUIsSUFBOUI7QUFDRDs7QUFFREMsRUFBQUEsR0FBRyxDQUFDRCxHQUFELEVBQU1FLEtBQU4sRUFBYVosR0FBRyxHQUFHLEtBQUtBLEdBQXhCLEVBQTZCO0FBQzlCLFNBQUtLLEtBQUwsQ0FBV1EsR0FBWCxDQUFlSCxHQUFmLEVBQW9CRSxLQUFwQixFQUEyQlosR0FBM0I7QUFDRDs7QUFFRGMsRUFBQUEsR0FBRyxDQUFDSixHQUFELEVBQU07QUFDUCxTQUFLTCxLQUFMLENBQVdTLEdBQVgsQ0FBZUosR0FBZjtBQUNEOztBQUVESyxFQUFBQSxLQUFLLEdBQUc7QUFDTixTQUFLVixLQUFMLENBQVdXLEtBQVg7QUFDRDs7QUF0Qm1COzs7ZUF5QlBsQixRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IExSVSBmcm9tICdscnUtY2FjaGUnO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4uLy4uL2RlZmF1bHRzJztcblxuZXhwb3J0IGNsYXNzIExSVUNhY2hlIHtcbiAgY29uc3RydWN0b3IoeyB0dGwgPSBkZWZhdWx0cy5jYWNoZVRUTCwgbWF4U2l6ZSA9IGRlZmF1bHRzLmNhY2hlTWF4U2l6ZSB9KSB7XG4gICAgdGhpcy5jYWNoZSA9IG5ldyBMUlUoe1xuICAgICAgbWF4OiBtYXhTaXplLFxuICAgICAgbWF4QWdlOiB0dGwsXG4gICAgfSk7XG4gIH1cblxuICBnZXQoa2V5KSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0KGtleSkgfHwgbnVsbDtcbiAgfVxuXG4gIHB1dChrZXksIHZhbHVlLCB0dGwgPSB0aGlzLnR0bCkge1xuICAgIHRoaXMuY2FjaGUuc2V0KGtleSwgdmFsdWUsIHR0bCk7XG4gIH1cblxuICBkZWwoa2V5KSB7XG4gICAgdGhpcy5jYWNoZS5kZWwoa2V5KTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHRoaXMuY2FjaGUucmVzZXQoKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBMUlVDYWNoZTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Cache/NullCacheAdapter.js b/lib/Adapters/Cache/NullCacheAdapter.js new file mode 100644 index 0000000000..639c544c94 --- /dev/null +++ b/lib/Adapters/Cache/NullCacheAdapter.js @@ -0,0 +1,34 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.NullCacheAdapter = void 0; + +class NullCacheAdapter { + constructor() {} + + get() { + return new Promise(resolve => { + return resolve(null); + }); + } + + put() { + return Promise.resolve(); + } + + del() { + return Promise.resolve(); + } + + clear() { + return Promise.resolve(); + } + +} + +exports.NullCacheAdapter = NullCacheAdapter; +var _default = NullCacheAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9OdWxsQ2FjaGVBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIk51bGxDYWNoZUFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsImdldCIsIlByb21pc2UiLCJyZXNvbHZlIiwicHV0IiwiZGVsIiwiY2xlYXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBTyxNQUFNQSxnQkFBTixDQUF1QjtBQUM1QkMsRUFBQUEsV0FBVyxHQUFHLENBQUU7O0FBRWhCQyxFQUFBQSxHQUFHLEdBQUc7QUFDSixXQUFPLElBQUlDLE9BQUosQ0FBWUMsT0FBTyxJQUFJO0FBQzVCLGFBQU9BLE9BQU8sQ0FBQyxJQUFELENBQWQ7QUFDRCxLQUZNLENBQVA7QUFHRDs7QUFFREMsRUFBQUEsR0FBRyxHQUFHO0FBQ0osV0FBT0YsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFFREUsRUFBQUEsR0FBRyxHQUFHO0FBQ0osV0FBT0gsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFFREcsRUFBQUEsS0FBSyxHQUFHO0FBQ04sV0FBT0osT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFuQjJCOzs7ZUFzQmZKLGdCIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNsYXNzIE51bGxDYWNoZUFkYXB0ZXIge1xuICBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgIH0pO1xuICB9XG5cbiAgcHV0KCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGRlbCgpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBjbGVhcigpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTnVsbENhY2hlQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Cache/RedisCacheAdapter/KeyPromiseQueue.js b/lib/Adapters/Cache/RedisCacheAdapter/KeyPromiseQueue.js new file mode 100644 index 0000000000..d4303d8803 --- /dev/null +++ b/lib/Adapters/Cache/RedisCacheAdapter/KeyPromiseQueue.js @@ -0,0 +1,59 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.KeyPromiseQueue = void 0; + +// KeyPromiseQueue is a simple promise queue +// used to queue operations per key basis. +// Once the tail promise in the key-queue fulfills, +// the chain on that key will be cleared. +class KeyPromiseQueue { + constructor() { + this.queue = {}; + } + + enqueue(key, operation) { + const tuple = this.beforeOp(key); + const toAwait = tuple[1]; + const nextOperation = toAwait.then(operation); + const wrappedOperation = nextOperation.then(result => { + this.afterOp(key); + return result; + }); + tuple[1] = wrappedOperation; + return wrappedOperation; + } + + beforeOp(key) { + let tuple = this.queue[key]; + + if (!tuple) { + tuple = [0, Promise.resolve()]; + this.queue[key] = tuple; + } + + tuple[0]++; + return tuple; + } + + afterOp(key) { + const tuple = this.queue[key]; + + if (!tuple) { + return; + } + + tuple[0]--; + + if (tuple[0] <= 0) { + delete this.queue[key]; + return; + } + } + +} + +exports.KeyPromiseQueue = KeyPromiseQueue; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9SZWRpc0NhY2hlQWRhcHRlci9LZXlQcm9taXNlUXVldWUuanMiXSwibmFtZXMiOlsiS2V5UHJvbWlzZVF1ZXVlIiwiY29uc3RydWN0b3IiLCJxdWV1ZSIsImVucXVldWUiLCJrZXkiLCJvcGVyYXRpb24iLCJ0dXBsZSIsImJlZm9yZU9wIiwidG9Bd2FpdCIsIm5leHRPcGVyYXRpb24iLCJ0aGVuIiwid3JhcHBlZE9wZXJhdGlvbiIsInJlc3VsdCIsImFmdGVyT3AiLCJQcm9taXNlIiwicmVzb2x2ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sTUFBTUEsZUFBTixDQUFzQjtBQUMzQkMsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxHQUFhLEVBQWI7QUFDRDs7QUFFREMsRUFBQUEsT0FBTyxDQUFDQyxHQUFELEVBQU1DLFNBQU4sRUFBaUI7QUFDdEIsVUFBTUMsS0FBSyxHQUFHLEtBQUtDLFFBQUwsQ0FBY0gsR0FBZCxDQUFkO0FBQ0EsVUFBTUksT0FBTyxHQUFHRixLQUFLLENBQUMsQ0FBRCxDQUFyQjtBQUNBLFVBQU1HLGFBQWEsR0FBR0QsT0FBTyxDQUFDRSxJQUFSLENBQWFMLFNBQWIsQ0FBdEI7QUFDQSxVQUFNTSxnQkFBZ0IsR0FBR0YsYUFBYSxDQUFDQyxJQUFkLENBQW1CRSxNQUFNLElBQUk7QUFDcEQsV0FBS0MsT0FBTCxDQUFhVCxHQUFiO0FBQ0EsYUFBT1EsTUFBUDtBQUNELEtBSHdCLENBQXpCO0FBSUFOLElBQUFBLEtBQUssQ0FBQyxDQUFELENBQUwsR0FBV0ssZ0JBQVg7QUFDQSxXQUFPQSxnQkFBUDtBQUNEOztBQUVESixFQUFBQSxRQUFRLENBQUNILEdBQUQsRUFBTTtBQUNaLFFBQUlFLEtBQUssR0FBRyxLQUFLSixLQUFMLENBQVdFLEdBQVgsQ0FBWjs7QUFDQSxRQUFJLENBQUNFLEtBQUwsRUFBWTtBQUNWQSxNQUFBQSxLQUFLLEdBQUcsQ0FBQyxDQUFELEVBQUlRLE9BQU8sQ0FBQ0MsT0FBUixFQUFKLENBQVI7QUFDQSxXQUFLYixLQUFMLENBQVdFLEdBQVgsSUFBa0JFLEtBQWxCO0FBQ0Q7O0FBQ0RBLElBQUFBLEtBQUssQ0FBQyxDQUFELENBQUw7QUFDQSxXQUFPQSxLQUFQO0FBQ0Q7O0FBRURPLEVBQUFBLE9BQU8sQ0FBQ1QsR0FBRCxFQUFNO0FBQ1gsVUFBTUUsS0FBSyxHQUFHLEtBQUtKLEtBQUwsQ0FBV0UsR0FBWCxDQUFkOztBQUNBLFFBQUksQ0FBQ0UsS0FBTCxFQUFZO0FBQ1Y7QUFDRDs7QUFDREEsSUFBQUEsS0FBSyxDQUFDLENBQUQsQ0FBTDs7QUFDQSxRQUFJQSxLQUFLLENBQUMsQ0FBRCxDQUFMLElBQVksQ0FBaEIsRUFBbUI7QUFDakIsYUFBTyxLQUFLSixLQUFMLENBQVdFLEdBQVgsQ0FBUDtBQUNBO0FBQ0Q7QUFDRjs7QUFyQzBCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gS2V5UHJvbWlzZVF1ZXVlIGlzIGEgc2ltcGxlIHByb21pc2UgcXVldWVcbi8vIHVzZWQgdG8gcXVldWUgb3BlcmF0aW9ucyBwZXIga2V5IGJhc2lzLlxuLy8gT25jZSB0aGUgdGFpbCBwcm9taXNlIGluIHRoZSBrZXktcXVldWUgZnVsZmlsbHMsXG4vLyB0aGUgY2hhaW4gb24gdGhhdCBrZXkgd2lsbCBiZSBjbGVhcmVkLlxuZXhwb3J0IGNsYXNzIEtleVByb21pc2VRdWV1ZSB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucXVldWUgPSB7fTtcbiAgfVxuXG4gIGVucXVldWUoa2V5LCBvcGVyYXRpb24pIHtcbiAgICBjb25zdCB0dXBsZSA9IHRoaXMuYmVmb3JlT3Aoa2V5KTtcbiAgICBjb25zdCB0b0F3YWl0ID0gdHVwbGVbMV07XG4gICAgY29uc3QgbmV4dE9wZXJhdGlvbiA9IHRvQXdhaXQudGhlbihvcGVyYXRpb24pO1xuICAgIGNvbnN0IHdyYXBwZWRPcGVyYXRpb24gPSBuZXh0T3BlcmF0aW9uLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHRoaXMuYWZ0ZXJPcChrZXkpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcbiAgICB0dXBsZVsxXSA9IHdyYXBwZWRPcGVyYXRpb247XG4gICAgcmV0dXJuIHdyYXBwZWRPcGVyYXRpb247XG4gIH1cblxuICBiZWZvcmVPcChrZXkpIHtcbiAgICBsZXQgdHVwbGUgPSB0aGlzLnF1ZXVlW2tleV07XG4gICAgaWYgKCF0dXBsZSkge1xuICAgICAgdHVwbGUgPSBbMCwgUHJvbWlzZS5yZXNvbHZlKCldO1xuICAgICAgdGhpcy5xdWV1ZVtrZXldID0gdHVwbGU7XG4gICAgfVxuICAgIHR1cGxlWzBdKys7XG4gICAgcmV0dXJuIHR1cGxlO1xuICB9XG5cbiAgYWZ0ZXJPcChrZXkpIHtcbiAgICBjb25zdCB0dXBsZSA9IHRoaXMucXVldWVba2V5XTtcbiAgICBpZiAoIXR1cGxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHR1cGxlWzBdLS07XG4gICAgaWYgKHR1cGxlWzBdIDw9IDApIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnF1ZXVlW2tleV07XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Cache/RedisCacheAdapter/index.js b/lib/Adapters/Cache/RedisCacheAdapter/index.js new file mode 100644 index 0000000000..221872d377 --- /dev/null +++ b/lib/Adapters/Cache/RedisCacheAdapter/index.js @@ -0,0 +1,112 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.RedisCacheAdapter = void 0; + +var _redis = _interopRequireDefault(require("redis")); + +var _logger = _interopRequireDefault(require("../../../logger")); + +var _KeyPromiseQueue = require("./KeyPromiseQueue"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const DEFAULT_REDIS_TTL = 30 * 1000; // 30 seconds in milliseconds + +const FLUSH_DB_KEY = '__flush_db__'; + +function debug() { + _logger.default.debug.apply(_logger.default, ['RedisCacheAdapter', ...arguments]); +} + +const isValidTTL = ttl => typeof ttl === 'number' && ttl > 0; + +class RedisCacheAdapter { + constructor(redisCtx, ttl = DEFAULT_REDIS_TTL) { + this.ttl = isValidTTL(ttl) ? ttl : DEFAULT_REDIS_TTL; + this.client = _redis.default.createClient(redisCtx); + this.queue = new _KeyPromiseQueue.KeyPromiseQueue(); + } + + get(key) { + debug('get', key); + return this.queue.enqueue(key, () => new Promise(resolve => { + this.client.get(key, function (err, res) { + debug('-> get', key, res); + + if (!res) { + return resolve(null); + } + + resolve(JSON.parse(res)); + }); + })); + } + + put(key, value, ttl = this.ttl) { + value = JSON.stringify(value); + debug('put', key, value, ttl); + + if (ttl === 0) { + // ttl of zero is a logical no-op, but redis cannot set expire time of zero + return this.queue.enqueue(key, () => Promise.resolve()); + } + + if (ttl === Infinity) { + return this.queue.enqueue(key, () => new Promise(resolve => { + this.client.set(key, value, function () { + resolve(); + }); + })); + } + + if (!isValidTTL(ttl)) { + ttl = this.ttl; + } + + return this.queue.enqueue(key, () => new Promise(resolve => { + this.client.psetex(key, ttl, value, function () { + resolve(); + }); + })); + } + + del(key) { + debug('del', key); + return this.queue.enqueue(key, () => new Promise(resolve => { + this.client.del(key, function () { + resolve(); + }); + })); + } + + clear() { + debug('clear'); + return this.queue.enqueue(FLUSH_DB_KEY, () => new Promise(resolve => { + this.client.flushdb(function () { + resolve(); + }); + })); + } // Used for testing + + + async getAllKeys() { + return new Promise((resolve, reject) => { + this.client.keys('*', (err, keys) => { + if (err) { + reject(err); + } else { + resolve(keys); + } + }); + }); + } + +} + +exports.RedisCacheAdapter = RedisCacheAdapter; +var _default = RedisCacheAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9SZWRpc0NhY2hlQWRhcHRlci9pbmRleC5qcyJdLCJuYW1lcyI6WyJERUZBVUxUX1JFRElTX1RUTCIsIkZMVVNIX0RCX0tFWSIsImRlYnVnIiwibG9nZ2VyIiwiYXBwbHkiLCJhcmd1bWVudHMiLCJpc1ZhbGlkVFRMIiwidHRsIiwiUmVkaXNDYWNoZUFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsInJlZGlzQ3R4IiwiY2xpZW50IiwicmVkaXMiLCJjcmVhdGVDbGllbnQiLCJxdWV1ZSIsIktleVByb21pc2VRdWV1ZSIsImdldCIsImtleSIsImVucXVldWUiLCJQcm9taXNlIiwicmVzb2x2ZSIsImVyciIsInJlcyIsIkpTT04iLCJwYXJzZSIsInB1dCIsInZhbHVlIiwic3RyaW5naWZ5IiwiSW5maW5pdHkiLCJzZXQiLCJwc2V0ZXgiLCJkZWwiLCJjbGVhciIsImZsdXNoZGIiLCJnZXRBbGxLZXlzIiwicmVqZWN0Iiwia2V5cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEsaUJBQWlCLEdBQUcsS0FBSyxJQUEvQixDLENBQXFDOztBQUNyQyxNQUFNQyxZQUFZLEdBQUcsY0FBckI7O0FBRUEsU0FBU0MsS0FBVCxHQUFpQjtBQUNmQyxrQkFBT0QsS0FBUCxDQUFhRSxLQUFiLENBQW1CRCxlQUFuQixFQUEyQixDQUFDLG1CQUFELEVBQXNCLEdBQUdFLFNBQXpCLENBQTNCO0FBQ0Q7O0FBRUQsTUFBTUMsVUFBVSxHQUFHQyxHQUFHLElBQUksT0FBT0EsR0FBUCxLQUFlLFFBQWYsSUFBMkJBLEdBQUcsR0FBRyxDQUEzRDs7QUFFTyxNQUFNQyxpQkFBTixDQUF3QjtBQUM3QkMsRUFBQUEsV0FBVyxDQUFDQyxRQUFELEVBQVdILEdBQUcsR0FBR1AsaUJBQWpCLEVBQW9DO0FBQzdDLFNBQUtPLEdBQUwsR0FBV0QsVUFBVSxDQUFDQyxHQUFELENBQVYsR0FBa0JBLEdBQWxC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QUosQ0FBWUMsT0FBTyxJQUFJO0FBQ3JCLFdBQUtULE1BQUwsQ0FBWXNCLE9BQVosQ0FBb0IsWUFBVztBQUM3QmIsUUFBQUEsT0FBTztBQUNSLE9BRkQ7QUFHRCxLQUpELENBSEcsQ0FBUDtBQVNELEdBcEY0QixDQXNGN0I7OztBQUNBLFFBQU1jLFVBQU4sR0FBbUI7QUFDakIsV0FBTyxJQUFJZixPQUFKLENBQVksQ0FBQ0MsT0FBRCxFQUFVZSxNQUFWLEtBQXFCO0FBQ3RDLFdBQUt4QixNQUFMLENBQVl5QixJQUFaLENBQWlCLEdBQWpCLEVBQXNCLENBQUNmLEdBQUQsRUFBTWUsSUFBTixLQUFlO0FBQ25DLFlBQUlmLEdBQUosRUFBUztBQUNQYyxVQUFBQSxNQUFNLENBQUNkLEdBQUQsQ0FBTjtBQUNELFNBRkQsTUFFTztBQUNMRCxVQUFBQSxPQUFPLENBQUNnQixJQUFELENBQVA7QUFDRDtBQUNGLE9BTkQ7QUFPRCxLQVJNLENBQVA7QUFTRDs7QUFqRzRCOzs7ZUFvR2hCNUIsaUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcmVkaXMgZnJvbSAncmVkaXMnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi8uLi8uLi9sb2dnZXInO1xuaW1wb3J0IHsgS2V5UHJvbWlzZVF1ZXVlIH0gZnJvbSAnLi9LZXlQcm9taXNlUXVldWUnO1xuXG5jb25zdCBERUZBVUxUX1JFRElTX1RUTCA9IDMwICogMTAwMDsgLy8gMzAgc2Vjb25kcyBpbiBtaWxsaXNlY29uZHNcbmNvbnN0IEZMVVNIX0RCX0tFWSA9ICdfX2ZsdXNoX2RiX18nO1xuXG5mdW5jdGlvbiBkZWJ1ZygpIHtcbiAgbG9nZ2VyLmRlYnVnLmFwcGx5KGxvZ2dlciwgWydSZWRpc0NhY2hlQWRhcHRlcicsIC4uLmFyZ3VtZW50c10pO1xufVxuXG5jb25zdCBpc1ZhbGlkVFRMID0gdHRsID0+IHR5cGVvZiB0dGwgPT09ICdudW1iZXInICYmIHR0bCA+IDA7XG5cbmV4cG9ydCBjbGFzcyBSZWRpc0NhY2hlQWRhcHRlciB7XG4gIGNvbnN0cnVjdG9yKHJlZGlzQ3R4LCB0dGwgPSBERUZBVUxUX1JFRElTX1RUTCkge1xuICAgIHRoaXMudHRsID0gaXNWYWxpZFRUTCh0dGwpID8gdHRsIDogREVGQVVMVF9SRURJU19UVEw7XG4gICAgdGhpcy5jbGllbnQgPSByZWRpcy5jcmVhdGVDbGllbnQocmVkaXNDdHgpO1xuICAgIHRoaXMucXVldWUgPSBuZXcgS2V5UHJvbWlzZVF1ZXVlKCk7XG4gIH1cblxuICBnZXQoa2V5KSB7XG4gICAgZGVidWcoJ2dldCcsIGtleSk7XG4gICAgcmV0dXJuIHRoaXMucXVldWUuZW5xdWV1ZShcbiAgICAgIGtleSxcbiAgICAgICgpID0+XG4gICAgICAgIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgIHRoaXMuY2xpZW50LmdldChrZXksIGZ1bmN0aW9uKGVyciwgcmVzKSB7XG4gICAgICAgICAgICBkZWJ1ZygnLT4gZ2V0Jywga2V5LCByZXMpO1xuICAgICAgICAgICAgaWYgKCFyZXMpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNvbHZlKEpTT04ucGFyc2UocmVzKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHB1dChrZXksIHZhbHVlLCB0dGwgPSB0aGlzLnR0bCkge1xuICAgIHZhbHVlID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgIGRlYnVnKCdwdXQnLCBrZXksIHZhbHVlLCB0dGwpO1xuXG4gICAgaWYgKHR0bCA9PT0gMCkge1xuICAgICAgLy8gdHRsIG9mIHplcm8gaXMgYSBsb2dpY2FsIG5vLW9wLCBidXQgcmVkaXMgY2Fubm90IHNldCBleHBpcmUgdGltZSBvZiB6ZXJvXG4gICAgICByZXR1cm4gdGhpcy5xdWV1ZS5lbnF1ZXVlKGtleSwgKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkpO1xuICAgIH1cblxuICAgIGlmICh0dGwgPT09IEluZmluaXR5KSB7XG4gICAgICByZXR1cm4gdGhpcy5xdWV1ZS5lbnF1ZXVlKFxuICAgICAgICBrZXksXG4gICAgICAgICgpID0+XG4gICAgICAgICAgbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsaWVudC5zZXQoa2V5LCB2YWx1ZSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICghaXNWYWxpZFRUTCh0dGwpKSB7XG4gICAgICB0dGwgPSB0aGlzLnR0bDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5lbnF1ZXVlKFxuICAgICAga2V5LFxuICAgICAgKCkgPT5cbiAgICAgICAgbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgdGhpcy5jbGllbnQucHNldGV4KGtleSwgdHRsLCB2YWx1ZSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIGRlbChrZXkpIHtcbiAgICBkZWJ1ZygnZGVsJywga2V5KTtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5lbnF1ZXVlKFxuICAgICAga2V5LFxuICAgICAgKCkgPT5cbiAgICAgICAgbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgdGhpcy5jbGllbnQuZGVsKGtleSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIGRlYnVnKCdjbGVhcicpO1xuICAgIHJldHVybiB0aGlzLnF1ZXVlLmVucXVldWUoXG4gICAgICBGTFVTSF9EQl9LRVksXG4gICAgICAoKSA9PlxuICAgICAgICBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICB0aGlzLmNsaWVudC5mbHVzaGRiKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBVc2VkIGZvciB0ZXN0aW5nXG4gIGFzeW5jIGdldEFsbEtleXMoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuY2xpZW50LmtleXMoJyonLCAoZXJyLCBrZXlzKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKGtleXMpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBSZWRpc0NhY2hlQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Email/MailAdapter.js b/lib/Adapters/Email/MailAdapter.js new file mode 100644 index 0000000000..217860c759 --- /dev/null +++ b/lib/Adapters/Email/MailAdapter.js @@ -0,0 +1,40 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.MailAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ + +/** + * @module Adapters + */ + +/** + * @interface MailAdapter + * Mail Adapter prototype + * A MailAdapter should implement at least sendMail() + */ +class MailAdapter { + /** + * A method for sending mail + * @param options would have the parameters + * - to: the recipient + * - text: the raw text of the message + * - subject: the subject of the email + */ + sendMail(options) {} + /* You can implement those methods if you want + * to provide HTML templates etc... + */ + // sendVerificationEmail({ link, appName, user }) {} + // sendPasswordResetEmail({ link, appName, user }) {} + + +} + +exports.MailAdapter = MailAdapter; +var _default = MailAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9FbWFpbC9NYWlsQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJNYWlsQWRhcHRlciIsInNlbmRNYWlsIiwib3B0aW9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBR0E7Ozs7O0FBS08sTUFBTUEsV0FBTixDQUFrQjtBQUN2Qjs7Ozs7OztBQU9BQyxFQUFBQSxRQUFRLENBQUNDLE9BQUQsRUFBVSxDQUFFO0FBRXBCOzs7QUFHQTtBQUNBOzs7QUFkdUI7OztlQWlCVkYsVyIsInNvdXJjZXNDb250ZW50IjpbIi8qZXNsaW50IG5vLXVudXNlZC12YXJzOiBcIm9mZlwiKi9cbi8qKlxuICogQG1vZHVsZSBBZGFwdGVyc1xuICovXG4vKipcbiAqIEBpbnRlcmZhY2UgTWFpbEFkYXB0ZXJcbiAqIE1haWwgQWRhcHRlciBwcm90b3R5cGVcbiAqIEEgTWFpbEFkYXB0ZXIgc2hvdWxkIGltcGxlbWVudCBhdCBsZWFzdCBzZW5kTWFpbCgpXG4gKi9cbmV4cG9ydCBjbGFzcyBNYWlsQWRhcHRlciB7XG4gIC8qKlxuICAgKiBBIG1ldGhvZCBmb3Igc2VuZGluZyBtYWlsXG4gICAqIEBwYXJhbSBvcHRpb25zIHdvdWxkIGhhdmUgdGhlIHBhcmFtZXRlcnNcbiAgICogLSB0bzogdGhlIHJlY2lwaWVudFxuICAgKiAtIHRleHQ6IHRoZSByYXcgdGV4dCBvZiB0aGUgbWVzc2FnZVxuICAgKiAtIHN1YmplY3Q6IHRoZSBzdWJqZWN0IG9mIHRoZSBlbWFpbFxuICAgKi9cbiAgc2VuZE1haWwob3B0aW9ucykge31cblxuICAvKiBZb3UgY2FuIGltcGxlbWVudCB0aG9zZSBtZXRob2RzIGlmIHlvdSB3YW50XG4gICAqIHRvIHByb3ZpZGUgSFRNTCB0ZW1wbGF0ZXMgZXRjLi4uXG4gICAqL1xuICAvLyBzZW5kVmVyaWZpY2F0aW9uRW1haWwoeyBsaW5rLCBhcHBOYW1lLCB1c2VyIH0pIHt9XG4gIC8vIHNlbmRQYXNzd29yZFJlc2V0RW1haWwoeyBsaW5rLCBhcHBOYW1lLCB1c2VyIH0pIHt9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1haWxBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Files/FilesAdapter.js b/lib/Adapters/Files/FilesAdapter.js new file mode 100644 index 0000000000..18d0a88072 --- /dev/null +++ b/lib/Adapters/Files/FilesAdapter.js @@ -0,0 +1,124 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.validateFilename = validateFilename; +exports.default = exports.FilesAdapter = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/*eslint no-unused-vars: "off"*/ +// Files Adapter +// +// Allows you to change the file storage mechanism. +// +// Adapter classes must implement the following functions: +// * createFile(filename, data, contentType) +// * deleteFile(filename) +// * getFileData(filename) +// * getFileLocation(config, filename) +// Adapter classes should implement the following functions: +// * validateFilename(filename) +// * handleFileStream(filename, req, res, contentType) +// +// Default is GridFSBucketAdapter, which requires mongo +// and for the API server to be using the DatabaseController with Mongo +// database adapter. + +/** + * @module Adapters + */ + +/** + * @interface FilesAdapter + */ +class FilesAdapter { + /** Responsible for storing the file in order to be retrieved later by its filename + * + * @param {string} filename - the filename to save + * @param {*} data - the buffer of data from the file + * @param {string} contentType - the supposed contentType + * @discussion the contentType can be undefined if the controller was not able to determine it + * + * @return {Promise} a promise that should fail if the storage didn't succeed + */ + createFile(filename, data, contentType) {} + /** Responsible for deleting the specified file + * + * @param {string} filename - the filename to delete + * + * @return {Promise} a promise that should fail if the deletion didn't succeed + */ + + + deleteFile(filename) {} + /** Responsible for retrieving the data of the specified file + * + * @param {string} filename - the name of file to retrieve + * + * @return {Promise} a promise that should pass with the file data or fail on error + */ + + + getFileData(filename) {} + /** Returns an absolute URL where the file can be accessed + * + * @param {Config} config - server configuration + * @param {string} filename + * + * @return {string} Absolute URL + */ + + + getFileLocation(config, filename) {} + /** Validate a filename for this adapter type + * + * @param {string} filename + * + * @returns {null|Parse.Error} null if there are no errors + */ + // validateFilename(filename: string): ?Parse.Error {} + + /** Handles Byte-Range Requests for Streaming + * + * @param {string} filename + * @param {object} req + * @param {object} res + * @param {string} contentType + * + * @returns {Promise} Data for byte range + */ + // handleFileStream(filename: string, res: any, req: any, contentType: string): Promise + + +} +/** + * Simple filename validation + * + * @param filename + * @returns {null|Parse.Error} + */ + + +exports.FilesAdapter = FilesAdapter; + +function validateFilename(filename) { + if (filename.length > 128) { + return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Filename too long.'); + } + + const regx = /^[_a-zA-Z0-9][a-zA-Z0-9@. ~_-]*$/; + + if (!filename.match(regx)) { + return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Filename contains invalid characters.'); + } + + return null; +} + +var _default = FilesAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9GaWxlcy9GaWxlc0FkYXB0ZXIuanMiXSwibmFtZXMiOlsiRmlsZXNBZGFwdGVyIiwiY3JlYXRlRmlsZSIsImZpbGVuYW1lIiwiZGF0YSIsImNvbnRlbnRUeXBlIiwiZGVsZXRlRmlsZSIsImdldEZpbGVEYXRhIiwiZ2V0RmlsZUxvY2F0aW9uIiwiY29uZmlnIiwidmFsaWRhdGVGaWxlbmFtZSIsImxlbmd0aCIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX0ZJTEVfTkFNRSIsInJlZ3giLCJtYXRjaCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFtQkE7Ozs7QUFuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFJQTs7OztBQUdBOzs7QUFHTyxNQUFNQSxZQUFOLENBQW1CO0FBQ3hCOzs7Ozs7Ozs7QUFTQUMsRUFBQUEsVUFBVSxDQUFDQyxRQUFELEVBQW1CQyxJQUFuQixFQUF5QkMsV0FBekIsRUFBdUQsQ0FBRTtBQUVuRTs7Ozs7Ozs7QUFNQUMsRUFBQUEsVUFBVSxDQUFDSCxRQUFELEVBQTRCLENBQUU7QUFFeEM7Ozs7Ozs7O0FBTUFJLEVBQUFBLFdBQVcsQ0FBQ0osUUFBRCxFQUFpQyxDQUFFO0FBRTlDOzs7Ozs7Ozs7QUFPQUssRUFBQUEsZUFBZSxDQUFDQyxNQUFELEVBQWlCTixRQUFqQixFQUEyQyxDQUFFO0FBRTVEOzs7Ozs7QUFNQTs7QUFFQTs7Ozs7Ozs7O0FBU0E7OztBQXREd0I7QUF5RDFCOzs7Ozs7Ozs7O0FBTU8sU0FBU08sZ0JBQVQsQ0FBMEJQLFFBQTFCLEVBQWtEO0FBQ3ZELE1BQUlBLFFBQVEsQ0FBQ1EsTUFBVCxHQUFrQixHQUF0QixFQUEyQjtBQUN6QixXQUFPLElBQUlDLGNBQU1DLEtBQVYsQ0FBZ0JELGNBQU1DLEtBQU4sQ0FBWUMsaUJBQTVCLEVBQStDLG9CQUEvQyxDQUFQO0FBQ0Q7O0FBRUQsUUFBTUMsSUFBSSxHQUFHLGtDQUFiOztBQUNBLE1BQUksQ0FBQ1osUUFBUSxDQUFDYSxLQUFULENBQWVELElBQWYsQ0FBTCxFQUEyQjtBQUN6QixXQUFPLElBQUlILGNBQU1DLEtBQVYsQ0FDTEQsY0FBTUMsS0FBTixDQUFZQyxpQkFEUCxFQUVMLHVDQUZLLENBQVA7QUFJRDs7QUFDRCxTQUFPLElBQVA7QUFDRDs7ZUFFY2IsWSIsInNvdXJjZXNDb250ZW50IjpbIi8qZXNsaW50IG5vLXVudXNlZC12YXJzOiBcIm9mZlwiKi9cbi8vIEZpbGVzIEFkYXB0ZXJcbi8vXG4vLyBBbGxvd3MgeW91IHRvIGNoYW5nZSB0aGUgZmlsZSBzdG9yYWdlIG1lY2hhbmlzbS5cbi8vXG4vLyBBZGFwdGVyIGNsYXNzZXMgbXVzdCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBmdW5jdGlvbnM6XG4vLyAqIGNyZWF0ZUZpbGUoZmlsZW5hbWUsIGRhdGEsIGNvbnRlbnRUeXBlKVxuLy8gKiBkZWxldGVGaWxlKGZpbGVuYW1lKVxuLy8gKiBnZXRGaWxlRGF0YShmaWxlbmFtZSlcbi8vICogZ2V0RmlsZUxvY2F0aW9uKGNvbmZpZywgZmlsZW5hbWUpXG4vLyBBZGFwdGVyIGNsYXNzZXMgc2hvdWxkIGltcGxlbWVudCB0aGUgZm9sbG93aW5nIGZ1bmN0aW9uczpcbi8vICogdmFsaWRhdGVGaWxlbmFtZShmaWxlbmFtZSlcbi8vICogaGFuZGxlRmlsZVN0cmVhbShmaWxlbmFtZSwgcmVxLCByZXMsIGNvbnRlbnRUeXBlKVxuLy9cbi8vIERlZmF1bHQgaXMgR3JpZEZTQnVja2V0QWRhcHRlciwgd2hpY2ggcmVxdWlyZXMgbW9uZ29cbi8vIGFuZCBmb3IgdGhlIEFQSSBzZXJ2ZXIgdG8gYmUgdXNpbmcgdGhlIERhdGFiYXNlQ29udHJvbGxlciB3aXRoIE1vbmdvXG4vLyBkYXRhYmFzZSBhZGFwdGVyLlxuXG5pbXBvcnQgdHlwZSB7IENvbmZpZyB9IGZyb20gJy4uLy4uL0NvbmZpZyc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG4vKipcbiAqIEBtb2R1bGUgQWRhcHRlcnNcbiAqL1xuLyoqXG4gKiBAaW50ZXJmYWNlIEZpbGVzQWRhcHRlclxuICovXG5leHBvcnQgY2xhc3MgRmlsZXNBZGFwdGVyIHtcbiAgLyoqIFJlc3BvbnNpYmxlIGZvciBzdG9yaW5nIHRoZSBmaWxlIGluIG9yZGVyIHRvIGJlIHJldHJpZXZlZCBsYXRlciBieSBpdHMgZmlsZW5hbWVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gdGhlIGZpbGVuYW1lIHRvIHNhdmVcbiAgICogQHBhcmFtIHsqfSBkYXRhIC0gdGhlIGJ1ZmZlciBvZiBkYXRhIGZyb20gdGhlIGZpbGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNvbnRlbnRUeXBlIC0gdGhlIHN1cHBvc2VkIGNvbnRlbnRUeXBlXG4gICAqIEBkaXNjdXNzaW9uIHRoZSBjb250ZW50VHlwZSBjYW4gYmUgdW5kZWZpbmVkIGlmIHRoZSBjb250cm9sbGVyIHdhcyBub3QgYWJsZSB0byBkZXRlcm1pbmUgaXRcbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgc2hvdWxkIGZhaWwgaWYgdGhlIHN0b3JhZ2UgZGlkbid0IHN1Y2NlZWRcbiAgICovXG4gIGNyZWF0ZUZpbGUoZmlsZW5hbWU6IHN0cmluZywgZGF0YSwgY29udGVudFR5cGU6IHN0cmluZyk6IFByb21pc2Uge31cblxuICAvKiogUmVzcG9uc2libGUgZm9yIGRlbGV0aW5nIHRoZSBzcGVjaWZpZWQgZmlsZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSB0aGUgZmlsZW5hbWUgdG8gZGVsZXRlXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHNob3VsZCBmYWlsIGlmIHRoZSBkZWxldGlvbiBkaWRuJ3Qgc3VjY2VlZFxuICAgKi9cbiAgZGVsZXRlRmlsZShmaWxlbmFtZTogc3RyaW5nKTogUHJvbWlzZSB7fVxuXG4gIC8qKiBSZXNwb25zaWJsZSBmb3IgcmV0cmlldmluZyB0aGUgZGF0YSBvZiB0aGUgc3BlY2lmaWVkIGZpbGVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gdGhlIG5hbWUgb2YgZmlsZSB0byByZXRyaWV2ZVxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCBzaG91bGQgcGFzcyB3aXRoIHRoZSBmaWxlIGRhdGEgb3IgZmFpbCBvbiBlcnJvclxuICAgKi9cbiAgZ2V0RmlsZURhdGEoZmlsZW5hbWU6IHN0cmluZyk6IFByb21pc2U8YW55PiB7fVxuXG4gIC8qKiBSZXR1cm5zIGFuIGFic29sdXRlIFVSTCB3aGVyZSB0aGUgZmlsZSBjYW4gYmUgYWNjZXNzZWRcbiAgICpcbiAgICogQHBhcmFtIHtDb25maWd9IGNvbmZpZyAtIHNlcnZlciBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZVxuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IEFic29sdXRlIFVSTFxuICAgKi9cbiAgZ2V0RmlsZUxvY2F0aW9uKGNvbmZpZzogQ29uZmlnLCBmaWxlbmFtZTogc3RyaW5nKTogc3RyaW5nIHt9XG5cbiAgLyoqIFZhbGlkYXRlIGEgZmlsZW5hbWUgZm9yIHRoaXMgYWRhcHRlciB0eXBlXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZVxuICAgKlxuICAgKiBAcmV0dXJucyB7bnVsbHxQYXJzZS5FcnJvcn0gbnVsbCBpZiB0aGVyZSBhcmUgbm8gZXJyb3JzXG4gICAqL1xuICAvLyB2YWxpZGF0ZUZpbGVuYW1lKGZpbGVuYW1lOiBzdHJpbmcpOiA/UGFyc2UuRXJyb3Ige31cblxuICAvKiogSGFuZGxlcyBCeXRlLVJhbmdlIFJlcXVlc3RzIGZvciBTdHJlYW1pbmdcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lXG4gICAqIEBwYXJhbSB7b2JqZWN0fSByZXFcbiAgICogQHBhcmFtIHtvYmplY3R9IHJlc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gY29udGVudFR5cGVcbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2V9IERhdGEgZm9yIGJ5dGUgcmFuZ2VcbiAgICovXG4gIC8vIGhhbmRsZUZpbGVTdHJlYW0oZmlsZW5hbWU6IHN0cmluZywgcmVzOiBhbnksIHJlcTogYW55LCBjb250ZW50VHlwZTogc3RyaW5nKTogUHJvbWlzZVxufVxuXG4vKipcbiAqIFNpbXBsZSBmaWxlbmFtZSB2YWxpZGF0aW9uXG4gKlxuICogQHBhcmFtIGZpbGVuYW1lXG4gKiBAcmV0dXJucyB7bnVsbHxQYXJzZS5FcnJvcn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRmlsZW5hbWUoZmlsZW5hbWUpOiA/UGFyc2UuRXJyb3Ige1xuICBpZiAoZmlsZW5hbWUubGVuZ3RoID4gMTI4KSB7XG4gICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSwgJ0ZpbGVuYW1lIHRvbyBsb25nLicpO1xuICB9XG5cbiAgY29uc3QgcmVneCA9IC9eW19hLXpBLVowLTldW2EtekEtWjAtOUAuIH5fLV0qJC87XG4gIGlmICghZmlsZW5hbWUubWF0Y2gocmVneCkpIHtcbiAgICByZXR1cm4gbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9GSUxFX05BTUUsXG4gICAgICAnRmlsZW5hbWUgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzLidcbiAgICApO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZGVmYXVsdCBGaWxlc0FkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Files/GridFSBucketAdapter.js b/lib/Adapters/Files/GridFSBucketAdapter.js new file mode 100644 index 0000000000..9b4a07f592 --- /dev/null +++ b/lib/Adapters/Files/GridFSBucketAdapter.js @@ -0,0 +1,151 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.GridFSBucketAdapter = void 0; + +var _mongodb = require("mongodb"); + +var _FilesAdapter = require("./FilesAdapter"); + +var _defaults = _interopRequireDefault(require("../../defaults")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + GridFSBucketAdapter + Stores files in Mongo using GridStore + Requires the database adapter to be based on mongoclient + + + */ +// -disable-next +class GridFSBucketAdapter extends _FilesAdapter.FilesAdapter { + constructor(mongoDatabaseURI = _defaults.default.DefaultMongoURI, mongoOptions = {}) { + super(); + this._databaseURI = mongoDatabaseURI; + const defaultMongoOptions = { + useNewUrlParser: true, + useUnifiedTopology: true + }; + this._mongoOptions = Object.assign(defaultMongoOptions, mongoOptions); + } + + _connect() { + if (!this._connectionPromise) { + this._connectionPromise = _mongodb.MongoClient.connect(this._databaseURI, this._mongoOptions).then(client => { + this._client = client; + return client.db(client.s.options.dbName); + }); + } + + return this._connectionPromise; + } + + _getBucket() { + return this._connect().then(database => new _mongodb.GridFSBucket(database)); + } // For a given config object, filename, and data, store a file + // Returns a promise + + + async createFile(filename, data) { + const bucket = await this._getBucket(); + const stream = await bucket.openUploadStream(filename); + await stream.write(data); + stream.end(); + return new Promise((resolve, reject) => { + stream.on('finish', resolve); + stream.on('error', reject); + }); + } + + async deleteFile(filename) { + const bucket = await this._getBucket(); + const documents = await bucket.find({ + filename + }).toArray(); + + if (documents.length === 0) { + throw new Error('FileNotFound'); + } + + return Promise.all(documents.map(doc => { + return bucket.delete(doc._id); + })); + } + + async getFileData(filename) { + const bucket = await this._getBucket(); + const stream = bucket.openDownloadStreamByName(filename); + stream.read(); + return new Promise((resolve, reject) => { + const chunks = []; + stream.on('data', data => { + chunks.push(data); + }); + stream.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + stream.on('error', err => { + reject(err); + }); + }); + } + + getFileLocation(config, filename) { + return config.mount + '/files/' + config.applicationId + '/' + encodeURIComponent(filename); + } + + async handleFileStream(filename, req, res, contentType) { + const bucket = await this._getBucket(); + const files = await bucket.find({ + filename + }).toArray(); + + if (files.length === 0) { + throw new Error('FileNotFound'); + } + + const parts = req.get('Range').replace(/bytes=/, '').split('-'); + const partialstart = parts[0]; + const partialend = parts[1]; + const start = parseInt(partialstart, 10); + const end = partialend ? parseInt(partialend, 10) : files[0].length - 1; + res.writeHead(206, { + 'Accept-Ranges': 'bytes', + 'Content-Length': end - start + 1, + 'Content-Range': 'bytes ' + start + '-' + end + '/' + files[0].length, + 'Content-Type': contentType + }); + const stream = bucket.openDownloadStreamByName(filename); + stream.start(start); + stream.on('data', chunk => { + res.write(chunk); + }); + stream.on('error', () => { + res.sendStatus(404); + }); + stream.on('end', () => { + res.end(); + }); + } + + handleShutdown() { + if (!this._client) { + return Promise.resolve(); + } + + return this._client.close(false); + } + + validateFilename(filename) { + return (0, _FilesAdapter.validateFilename)(filename); + } + +} + +exports.GridFSBucketAdapter = GridFSBucketAdapter; +var _default = GridFSBucketAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9GaWxlcy9HcmlkRlNCdWNrZXRBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIkdyaWRGU0J1Y2tldEFkYXB0ZXIiLCJGaWxlc0FkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsIm1vbmdvRGF0YWJhc2VVUkkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsIm1vbmdvT3B0aW9ucyIsIl9kYXRhYmFzZVVSSSIsImRlZmF1bHRNb25nb09wdGlvbnMiLCJ1c2VOZXdVcmxQYXJzZXIiLCJ1c2VVbmlmaWVkVG9wb2xvZ3kiLCJfbW9uZ29PcHRpb25zIiwiT2JqZWN0IiwiYXNzaWduIiwiX2Nvbm5lY3QiLCJfY29ubmVjdGlvblByb21pc2UiLCJNb25nb0NsaWVudCIsImNvbm5lY3QiLCJ0aGVuIiwiY2xpZW50IiwiX2NsaWVudCIsImRiIiwicyIsIm9wdGlvbnMiLCJkYk5hbWUiLCJfZ2V0QnVja2V0IiwiZGF0YWJhc2UiLCJHcmlkRlNCdWNrZXQiLCJjcmVhdGVGaWxlIiwiZmlsZW5hbWUiLCJkYXRhIiwiYnVja2V0Iiwic3RyZWFtIiwib3BlblVwbG9hZFN0cmVhbSIsIndyaXRlIiwiZW5kIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJvbiIsImRlbGV0ZUZpbGUiLCJkb2N1bWVudHMiLCJmaW5kIiwidG9BcnJheSIsImxlbmd0aCIsIkVycm9yIiwiYWxsIiwibWFwIiwiZG9jIiwiZGVsZXRlIiwiX2lkIiwiZ2V0RmlsZURhdGEiLCJvcGVuRG93bmxvYWRTdHJlYW1CeU5hbWUiLCJyZWFkIiwiY2h1bmtzIiwicHVzaCIsIkJ1ZmZlciIsImNvbmNhdCIsImVyciIsImdldEZpbGVMb2NhdGlvbiIsImNvbmZpZyIsIm1vdW50IiwiYXBwbGljYXRpb25JZCIsImVuY29kZVVSSUNvbXBvbmVudCIsImhhbmRsZUZpbGVTdHJlYW0iLCJyZXEiLCJyZXMiLCJjb250ZW50VHlwZSIsImZpbGVzIiwicGFydHMiLCJnZXQiLCJyZXBsYWNlIiwic3BsaXQiLCJwYXJ0aWFsc3RhcnQiLCJwYXJ0aWFsZW5kIiwic3RhcnQiLCJwYXJzZUludCIsIndyaXRlSGVhZCIsImNodW5rIiwic2VuZFN0YXR1cyIsImhhbmRsZVNodXRkb3duIiwiY2xvc2UiLCJ2YWxpZGF0ZUZpbGVuYW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7O0FBQ0E7Ozs7QUFYQTs7Ozs7OztBQVFBO0FBS08sTUFBTUEsbUJBQU4sU0FBa0NDLDBCQUFsQyxDQUErQztBQUtwREMsRUFBQUEsV0FBVyxDQUFDQyxnQkFBZ0IsR0FBR0Msa0JBQVNDLGVBQTdCLEVBQThDQyxZQUFZLEdBQUcsRUFBN0QsRUFBaUU7QUFDMUU7QUFDQSxTQUFLQyxZQUFMLEdBQW9CSixnQkFBcEI7QUFFQSxVQUFNSyxtQkFBbUIsR0FBRztBQUMxQkMsTUFBQUEsZUFBZSxFQUFFLElBRFM7QUFFMUJDLE1BQUFBLGtCQUFrQixFQUFFO0FBRk0sS0FBNUI7QUFJQSxTQUFLQyxhQUFMLEdBQXFCQyxNQUFNLENBQUNDLE1BQVAsQ0FBY0wsbUJBQWQsRUFBbUNGLFlBQW5DLENBQXJCO0FBQ0Q7O0FBRURRLEVBQUFBLFFBQVEsR0FBRztBQUNULFFBQUksQ0FBQyxLQUFLQyxrQkFBVixFQUE4QjtBQUM1QixXQUFLQSxrQkFBTCxHQUEwQkMscUJBQVlDLE9BQVosQ0FDeEIsS0FBS1YsWUFEbUIsRUFFeEIsS0FBS0ksYUFGbUIsRUFHeEJPLElBSHdCLENBR25CQyxNQUFNLElBQUk7QUFDZixhQUFLQyxPQUFMLEdBQWVELE1BQWY7QUFDQSxlQUFPQSxNQUFNLENBQUNFLEVBQVAsQ0FBVUYsTUFBTSxDQUFDRyxDQUFQLENBQVNDLE9BQVQsQ0FBaUJDLE1BQTNCLENBQVA7QUFDRCxPQU55QixDQUExQjtBQU9EOztBQUNELFdBQU8sS0FBS1Qsa0JBQVo7QUFDRDs7QUFFRFUsRUFBQUEsVUFBVSxHQUFHO0FBQ1gsV0FBTyxLQUFLWCxRQUFMLEdBQWdCSSxJQUFoQixDQUFxQlEsUUFBUSxJQUFJLElBQUlD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QUcsQ0FBQ2hDLEtBQUosQ0FBVTRDLEtBQVY7QUFDRCxLQUZEO0FBR0E5QyxJQUFBQSxNQUFNLENBQUNPLEVBQVAsQ0FBVSxPQUFWLEVBQW1CLE1BQU07QUFDdkIyQixNQUFBQSxHQUFHLENBQUNhLFVBQUosQ0FBZSxHQUFmO0FBQ0QsS0FGRDtBQUdBL0MsSUFBQUEsTUFBTSxDQUFDTyxFQUFQLENBQVUsS0FBVixFQUFpQixNQUFNO0FBQ3JCMkIsTUFBQUEsR0FBRyxDQUFDL0IsR0FBSjtBQUNELEtBRkQ7QUFHRDs7QUFFRDZDLEVBQUFBLGNBQWMsR0FBRztBQUNmLFFBQUksQ0FBQyxLQUFLNUQsT0FBVixFQUFtQjtBQUNqQixhQUFPZ0IsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFDRCxXQUFPLEtBQUtqQixPQUFMLENBQWE2RCxLQUFiLENBQW1CLEtBQW5CLENBQVA7QUFDRDs7QUFFREMsRUFBQUEsZ0JBQWdCLENBQUNyRCxRQUFELEVBQVc7QUFDekIsV0FBTyxvQ0FBaUJBLFFBQWpCLENBQVA7QUFDRDs7QUFuSW1EOzs7ZUFzSXZDN0IsbUIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiBHcmlkRlNCdWNrZXRBZGFwdGVyXG4gU3RvcmVzIGZpbGVzIGluIE1vbmdvIHVzaW5nIEdyaWRTdG9yZVxuIFJlcXVpcmVzIHRoZSBkYXRhYmFzZSBhZGFwdGVyIHRvIGJlIGJhc2VkIG9uIG1vbmdvY2xpZW50XG5cbiBAZmxvdyB3ZWFrXG4gKi9cblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgeyBNb25nb0NsaWVudCwgR3JpZEZTQnVja2V0LCBEYiB9IGZyb20gJ21vbmdvZGInO1xuaW1wb3J0IHsgRmlsZXNBZGFwdGVyLCB2YWxpZGF0ZUZpbGVuYW1lIH0gZnJvbSAnLi9GaWxlc0FkYXB0ZXInO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4uLy4uL2RlZmF1bHRzJztcblxuZXhwb3J0IGNsYXNzIEdyaWRGU0J1Y2tldEFkYXB0ZXIgZXh0ZW5kcyBGaWxlc0FkYXB0ZXIge1xuICBfZGF0YWJhc2VVUkk6IHN0cmluZztcbiAgX2Nvbm5lY3Rpb25Qcm9taXNlOiBQcm9taXNlPERiPjtcbiAgX21vbmdvT3B0aW9uczogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKG1vbmdvRGF0YWJhc2VVUkkgPSBkZWZhdWx0cy5EZWZhdWx0TW9uZ29VUkksIG1vbmdvT3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLl9kYXRhYmFzZVVSSSA9IG1vbmdvRGF0YWJhc2VVUkk7XG5cbiAgICBjb25zdCBkZWZhdWx0TW9uZ29PcHRpb25zID0ge1xuICAgICAgdXNlTmV3VXJsUGFyc2VyOiB0cnVlLFxuICAgICAgdXNlVW5pZmllZFRvcG9sb2d5OiB0cnVlLFxuICAgIH07XG4gICAgdGhpcy5fbW9uZ29PcHRpb25zID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0TW9uZ29PcHRpb25zLCBtb25nb09wdGlvbnMpO1xuICB9XG5cbiAgX2Nvbm5lY3QoKSB7XG4gICAgaWYgKCF0aGlzLl9jb25uZWN0aW9uUHJvbWlzZSkge1xuICAgICAgdGhpcy5fY29ubmVjdGlvblByb21pc2UgPSBNb25nb0NsaWVudC5jb25uZWN0KFxuICAgICAgICB0aGlzLl9kYXRhYmFzZVVSSSxcbiAgICAgICAgdGhpcy5fbW9uZ29PcHRpb25zXG4gICAgICApLnRoZW4oY2xpZW50ID0+IHtcbiAgICAgICAgdGhpcy5fY2xpZW50ID0gY2xpZW50O1xuICAgICAgICByZXR1cm4gY2xpZW50LmRiKGNsaWVudC5zLm9wdGlvbnMuZGJOYW1lKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY29ubmVjdGlvblByb21pc2U7XG4gIH1cblxuICBfZ2V0QnVja2V0KCkge1xuICAgIHJldHVybiB0aGlzLl9jb25uZWN0KCkudGhlbihkYXRhYmFzZSA9PiBuZXcgR3JpZEZTQnVja2V0KGRhdGFiYXNlKSk7XG4gIH1cblxuICAvLyBGb3IgYSBnaXZlbiBjb25maWcgb2JqZWN0LCBmaWxlbmFtZSwgYW5kIGRhdGEsIHN0b3JlIGEgZmlsZVxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZVxuICBhc3luYyBjcmVhdGVGaWxlKGZpbGVuYW1lOiBzdHJpbmcsIGRhdGEpIHtcbiAgICBjb25zdCBidWNrZXQgPSBhd2FpdCB0aGlzLl9nZXRCdWNrZXQoKTtcbiAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCBidWNrZXQub3BlblVwbG9hZFN0cmVhbShmaWxlbmFtZSk7XG4gICAgYXdhaXQgc3RyZWFtLndyaXRlKGRhdGEpO1xuICAgIHN0cmVhbS5lbmQoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgc3RyZWFtLm9uKCdmaW5pc2gnLCByZXNvbHZlKTtcbiAgICAgIHN0cmVhbS5vbignZXJyb3InLCByZWplY3QpO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlRmlsZShmaWxlbmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgYnVja2V0ID0gYXdhaXQgdGhpcy5fZ2V0QnVja2V0KCk7XG4gICAgY29uc3QgZG9jdW1lbnRzID0gYXdhaXQgYnVja2V0LmZpbmQoeyBmaWxlbmFtZSB9KS50b0FycmF5KCk7XG4gICAgaWYgKGRvY3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmlsZU5vdEZvdW5kJyk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgIGRvY3VtZW50cy5tYXAoZG9jID0+IHtcbiAgICAgICAgcmV0dXJuIGJ1Y2tldC5kZWxldGUoZG9jLl9pZCk7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICBhc3luYyBnZXRGaWxlRGF0YShmaWxlbmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgYnVja2V0ID0gYXdhaXQgdGhpcy5fZ2V0QnVja2V0KCk7XG4gICAgY29uc3Qgc3RyZWFtID0gYnVja2V0Lm9wZW5Eb3dubG9hZFN0cmVhbUJ5TmFtZShmaWxlbmFtZSk7XG4gICAgc3RyZWFtLnJlYWQoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgY2h1bmtzID0gW107XG4gICAgICBzdHJlYW0ub24oJ2RhdGEnLCBkYXRhID0+IHtcbiAgICAgICAgY2h1bmtzLnB1c2goZGF0YSk7XG4gICAgICB9KTtcbiAgICAgIHN0cmVhbS5vbignZW5kJywgKCkgPT4ge1xuICAgICAgICByZXNvbHZlKEJ1ZmZlci5jb25jYXQoY2h1bmtzKSk7XG4gICAgICB9KTtcbiAgICAgIHN0cmVhbS5vbignZXJyb3InLCBlcnIgPT4ge1xuICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0RmlsZUxvY2F0aW9uKGNvbmZpZywgZmlsZW5hbWUpIHtcbiAgICByZXR1cm4gKFxuICAgICAgY29uZmlnLm1vdW50ICtcbiAgICAgICcvZmlsZXMvJyArXG4gICAgICBjb25maWcuYXBwbGljYXRpb25JZCArXG4gICAgICAnLycgK1xuICAgICAgZW5jb2RlVVJJQ29tcG9uZW50KGZpbGVuYW1lKVxuICAgICk7XG4gIH1cblxuICBhc3luYyBoYW5kbGVGaWxlU3RyZWFtKGZpbGVuYW1lOiBzdHJpbmcsIHJlcSwgcmVzLCBjb250ZW50VHlwZSkge1xuICAgIGNvbnN0IGJ1Y2tldCA9IGF3YWl0IHRoaXMuX2dldEJ1Y2tldCgpO1xuICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgYnVja2V0LmZpbmQoeyBmaWxlbmFtZSB9KS50b0FycmF5KCk7XG4gICAgaWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGaWxlTm90Rm91bmQnKTtcbiAgICB9XG4gICAgY29uc3QgcGFydHMgPSByZXFcbiAgICAgIC5nZXQoJ1JhbmdlJylcbiAgICAgIC5yZXBsYWNlKC9ieXRlcz0vLCAnJylcbiAgICAgIC5zcGxpdCgnLScpO1xuICAgIGNvbnN0IHBhcnRpYWxzdGFydCA9IHBhcnRzWzBdO1xuICAgIGNvbnN0IHBhcnRpYWxlbmQgPSBwYXJ0c1sxXTtcblxuICAgIGNvbnN0IHN0YXJ0ID0gcGFyc2VJbnQocGFydGlhbHN0YXJ0LCAxMCk7XG4gICAgY29uc3QgZW5kID0gcGFydGlhbGVuZCA/IHBhcnNlSW50KHBhcnRpYWxlbmQsIDEwKSA6IGZpbGVzWzBdLmxlbmd0aCAtIDE7XG5cbiAgICByZXMud3JpdGVIZWFkKDIwNiwge1xuICAgICAgJ0FjY2VwdC1SYW5nZXMnOiAnYnl0ZXMnLFxuICAgICAgJ0NvbnRlbnQtTGVuZ3RoJzogZW5kIC0gc3RhcnQgKyAxLFxuICAgICAgJ0NvbnRlbnQtUmFuZ2UnOiAnYnl0ZXMgJyArIHN0YXJ0ICsgJy0nICsgZW5kICsgJy8nICsgZmlsZXNbMF0ubGVuZ3RoLFxuICAgICAgJ0NvbnRlbnQtVHlwZSc6IGNvbnRlbnRUeXBlLFxuICAgIH0pO1xuICAgIGNvbnN0IHN0cmVhbSA9IGJ1Y2tldC5vcGVuRG93bmxvYWRTdHJlYW1CeU5hbWUoZmlsZW5hbWUpO1xuICAgIHN0cmVhbS5zdGFydChzdGFydCk7XG4gICAgc3RyZWFtLm9uKCdkYXRhJywgY2h1bmsgPT4ge1xuICAgICAgcmVzLndyaXRlKGNodW5rKTtcbiAgICB9KTtcbiAgICBzdHJlYW0ub24oJ2Vycm9yJywgKCkgPT4ge1xuICAgICAgcmVzLnNlbmRTdGF0dXMoNDA0KTtcbiAgICB9KTtcbiAgICBzdHJlYW0ub24oJ2VuZCcsICgpID0+IHtcbiAgICAgIHJlcy5lbmQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGlmICghdGhpcy5fY2xpZW50KSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jbGllbnQuY2xvc2UoZmFsc2UpO1xuICB9XG5cbiAgdmFsaWRhdGVGaWxlbmFtZShmaWxlbmFtZSkge1xuICAgIHJldHVybiB2YWxpZGF0ZUZpbGVuYW1lKGZpbGVuYW1lKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBHcmlkRlNCdWNrZXRBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Files/GridStoreAdapter.js b/lib/Adapters/Files/GridStoreAdapter.js new file mode 100644 index 0000000000..5ff3c1e0e3 --- /dev/null +++ b/lib/Adapters/Files/GridStoreAdapter.js @@ -0,0 +1,182 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.GridStoreAdapter = void 0; + +var _mongodb = require("mongodb"); + +var _FilesAdapter = require("./FilesAdapter"); + +var _defaults = _interopRequireDefault(require("../../defaults")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + GridStoreAdapter + Stores files in Mongo using GridStore + Requires the database adapter to be based on mongoclient + (GridStore is deprecated, Please use GridFSBucket instead) + + + */ +// -disable-next +class GridStoreAdapter extends _FilesAdapter.FilesAdapter { + constructor(mongoDatabaseURI = _defaults.default.DefaultMongoURI, mongoOptions = {}) { + super(); + this._databaseURI = mongoDatabaseURI; + const defaultMongoOptions = { + useNewUrlParser: true, + useUnifiedTopology: true + }; + this._mongoOptions = Object.assign(defaultMongoOptions, mongoOptions); + } + + _connect() { + if (!this._connectionPromise) { + this._connectionPromise = _mongodb.MongoClient.connect(this._databaseURI, this._mongoOptions).then(client => { + this._client = client; + return client.db(client.s.options.dbName); + }); + } + + return this._connectionPromise; + } // For a given config object, filename, and data, store a file + // Returns a promise + + + createFile(filename, data) { + return this._connect().then(database => { + const gridStore = new _mongodb.GridStore(database, filename, 'w'); + return gridStore.open(); + }).then(gridStore => { + return gridStore.write(data); + }).then(gridStore => { + return gridStore.close(); + }); + } + + deleteFile(filename) { + return this._connect().then(database => { + const gridStore = new _mongodb.GridStore(database, filename, 'r'); + return gridStore.open(); + }).then(gridStore => { + return gridStore.unlink(); + }).then(gridStore => { + return gridStore.close(); + }); + } + + getFileData(filename) { + return this._connect().then(database => { + return _mongodb.GridStore.exist(database, filename).then(() => { + const gridStore = new _mongodb.GridStore(database, filename, 'r'); + return gridStore.open(); + }); + }).then(gridStore => { + return gridStore.read(); + }); + } + + getFileLocation(config, filename) { + return config.mount + '/files/' + config.applicationId + '/' + encodeURIComponent(filename); + } + + async handleFileStream(filename, req, res, contentType) { + const stream = await this._connect().then(database => { + return _mongodb.GridStore.exist(database, filename).then(() => { + const gridStore = new _mongodb.GridStore(database, filename, 'r'); + return gridStore.open(); + }); + }); + handleRangeRequest(stream, req, res, contentType); + } + + handleShutdown() { + if (!this._client) { + return Promise.resolve(); + } + + return this._client.close(false); + } + + validateFilename(filename) { + return (0, _FilesAdapter.validateFilename)(filename); + } + +} // handleRangeRequest is licensed under Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/). +// Author: LEROIB at weightingformypizza (https://weightingformypizza.wordpress.com/2015/06/24/stream-html5-media-content-like-video-audio-from-mongodb-using-express-and-gridstore/). + + +exports.GridStoreAdapter = GridStoreAdapter; + +function handleRangeRequest(stream, req, res, contentType) { + const buffer_size = 1024 * 1024; //1024Kb + // Range request, partial stream the file + + const parts = req.get('Range').replace(/bytes=/, '').split('-'); + let [start, end] = parts; + const notEnded = !end && end !== 0; + const notStarted = !start && start !== 0; // No end provided, we want all bytes + + if (notEnded) { + end = stream.length - 1; + } // No start provided, we're reading backwards + + + if (notStarted) { + start = stream.length - end; + end = start + end - 1; + } // Data exceeds the buffer_size, cap + + + if (end - start >= buffer_size) { + end = start + buffer_size - 1; + } + + const contentLength = end - start + 1; + res.writeHead(206, { + 'Content-Range': 'bytes ' + start + '-' + end + '/' + stream.length, + 'Accept-Ranges': 'bytes', + 'Content-Length': contentLength, + 'Content-Type': contentType + }); + stream.seek(start, function () { + // Get gridFile stream + const gridFileStream = stream.stream(true); + let bufferAvail = 0; + let remainingBytesToWrite = contentLength; + let totalBytesWritten = 0; // Write to response + + gridFileStream.on('data', function (data) { + bufferAvail += data.length; + + if (bufferAvail > 0) { + // slice returns the same buffer if overflowing + // safe to call in any case + const buffer = data.slice(0, remainingBytesToWrite); // Write the buffer + + res.write(buffer); // Increment total + + totalBytesWritten += buffer.length; // Decrement remaining + + remainingBytesToWrite -= data.length; // Decrement the available buffer + + bufferAvail -= buffer.length; + } // In case of small slices, all values will be good at that point + // we've written enough, end... + + + if (totalBytesWritten >= contentLength) { + stream.close(); + res.end(); + this.destroy(); + } + }); + }); +} + +var _default = GridStoreAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9GaWxlcy9HcmlkU3RvcmVBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIkdyaWRTdG9yZUFkYXB0ZXIiLCJGaWxlc0FkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsIm1vbmdvRGF0YWJhc2VVUkkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsIm1vbmdvT3B0aW9ucyIsIl9kYXRhYmFzZVVSSSIsImRlZmF1bHRNb25nb09wdGlvbnMiLCJ1c2VOZXdVcmxQYXJzZXIiLCJ1c2VVbmlmaWVkVG9wb2xvZ3kiLCJfbW9uZ29PcHRpb25zIiwiT2JqZWN0IiwiYXNzaWduIiwiX2Nvbm5lY3QiLCJfY29ubmVjdGlvblByb21pc2UiLCJNb25nb0NsaWVudCIsImNvbm5lY3QiLCJ0aGVuIiwiY2xpZW50IiwiX2NsaWVudCIsImRiIiwicyIsIm9wdGlvbnMiLCJkYk5hbWUiLCJjcmVhdGVGaWxlIiwiZmlsZW5hbWUiLCJkYXRhIiwiZGF0YWJhc2UiLCJncmlkU3RvcmUiLCJHcmlkU3RvcmUiLCJvcGVuIiwid3JpdGUiLCJjbG9zZSIsImRlbGV0ZUZpbGUiLCJ1bmxpbmsiLCJnZXRGaWxlRGF0YSIsImV4aXN0IiwicmVhZCIsImdldEZpbGVMb2NhdGlvbiIsImNvbmZpZyIsIm1vdW50IiwiYXBwbGljYXRpb25JZCIsImVuY29kZVVSSUNvbXBvbmVudCIsImhhbmRsZUZpbGVTdHJlYW0iLCJyZXEiLCJyZXMiLCJjb250ZW50VHlwZSIsInN0cmVhbSIsImhhbmRsZVJhbmdlUmVxdWVzdCIsImhhbmRsZVNodXRkb3duIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ2YWxpZGF0ZUZpbGVuYW1lIiwiYnVmZmVyX3NpemUiLCJwYXJ0cyIsImdldCIsInJlcGxhY2UiLCJzcGxpdCIsInN0YXJ0IiwiZW5kIiwibm90RW5kZWQiLCJub3RTdGFydGVkIiwibGVuZ3RoIiwiY29udGVudExlbmd0aCIsIndyaXRlSGVhZCIsInNlZWsiLCJncmlkRmlsZVN0cmVhbSIsImJ1ZmZlckF2YWlsIiwicmVtYWluaW5nQnl0ZXNUb1dyaXRlIiwidG90YWxCeXRlc1dyaXR0ZW4iLCJvbiIsImJ1ZmZlciIsInNsaWNlIiwiZGVzdHJveSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVVBOztBQUNBOztBQUNBOzs7O0FBWkE7Ozs7Ozs7O0FBU0E7QUFLTyxNQUFNQSxnQkFBTixTQUErQkMsMEJBQS9CLENBQTRDO0FBS2pEQyxFQUFBQSxXQUFXLENBQUNDLGdCQUFnQixHQUFHQyxrQkFBU0MsZUFBN0IsRUFBOENDLFlBQVksR0FBRyxFQUE3RCxFQUFpRTtBQUMxRTtBQUNBLFNBQUtDLFlBQUwsR0FBb0JKLGdCQUFwQjtBQUVBLFVBQU1LLG1CQUFtQixHQUFHO0FBQzFCQyxNQUFBQSxlQUFlLEVBQUUsSUFEUztBQUUxQkMsTUFBQUEsa0JBQWtCLEVBQUU7QUFGTSxLQUE1QjtBQUlBLFNBQUtDLGFBQUwsR0FBcUJDLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjTCxtQkFBZCxFQUFtQ0YsWUFBbkMsQ0FBckI7QUFDRDs7QUFFRFEsRUFBQUEsUUFBUSxHQUFHO0FBQ1QsUUFBSSxDQUFDLEtBQUtDLGtCQUFWLEVBQThCO0FBQzVCLFdBQUtBLGtCQUFMLEdBQTBCQyxxQkFBWUMsT0FBWixDQUN4QixLQUFLVixZQURtQixFQUV4QixLQUFLSSxhQUZtQixFQUd4Qk8sSUFId0IsQ0FHbkJDLE1BQU0sSUFBSTtBQUNmLGFBQUtDLE9BQUwsR0FBZUQsTUFBZjtBQUNBLGVBQU9BLE1BQU0sQ0FBQ0UsRUFBUCxDQUFVRixNQUFNLENBQUNHLENBQVAsQ0FBU0MsT0FBVCxDQUFpQkMsTUFBM0IsQ0FBUDtBQUNELE9BTnlCLENBQTFCO0FBT0Q7O0FBQ0QsV0FBTyxLQUFLVCxrQkFBWjtBQUNELEdBM0JnRCxDQTZCakQ7QUFDQTs7O0FBQ0FVLEVBQUFBLFVBQVUsQ0FBQ0MsUUFBRCxFQUFtQkMsSUFBbkIsRUFBeUI7QUFDakMsV0FBTyxLQUFLYixRQUFMLEdBQ0pJLElBREksQ0FDQ1UsUUFBUSxJQUFJO0FBQ2hC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QUFMO0FBQ0Q7QUFDRixLQXRCRDtBQXVCRCxHQTlCRDtBQStCRDs7ZUFFYzFFLGdCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gR3JpZFN0b3JlQWRhcHRlclxuIFN0b3JlcyBmaWxlcyBpbiBNb25nbyB1c2luZyBHcmlkU3RvcmVcbiBSZXF1aXJlcyB0aGUgZGF0YWJhc2UgYWRhcHRlciB0byBiZSBiYXNlZCBvbiBtb25nb2NsaWVudFxuIChHcmlkU3RvcmUgaXMgZGVwcmVjYXRlZCwgUGxlYXNlIHVzZSBHcmlkRlNCdWNrZXQgaW5zdGVhZClcblxuIEBmbG93IHdlYWtcbiAqL1xuXG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCB7IE1vbmdvQ2xpZW50LCBHcmlkU3RvcmUsIERiIH0gZnJvbSAnbW9uZ29kYic7XG5pbXBvcnQgeyBGaWxlc0FkYXB0ZXIsIHZhbGlkYXRlRmlsZW5hbWUgfSBmcm9tICcuL0ZpbGVzQWRhcHRlcic7XG5pbXBvcnQgZGVmYXVsdHMgZnJvbSAnLi4vLi4vZGVmYXVsdHMnO1xuXG5leHBvcnQgY2xhc3MgR3JpZFN0b3JlQWRhcHRlciBleHRlbmRzIEZpbGVzQWRhcHRlciB7XG4gIF9kYXRhYmFzZVVSSTogc3RyaW5nO1xuICBfY29ubmVjdGlvblByb21pc2U6IFByb21pc2U8RGI+O1xuICBfbW9uZ29PcHRpb25zOiBPYmplY3Q7XG5cbiAgY29uc3RydWN0b3IobW9uZ29EYXRhYmFzZVVSSSA9IGRlZmF1bHRzLkRlZmF1bHRNb25nb1VSSSwgbW9uZ29PcHRpb25zID0ge30pIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuX2RhdGFiYXNlVVJJID0gbW9uZ29EYXRhYmFzZVVSSTtcblxuICAgIGNvbnN0IGRlZmF1bHRNb25nb09wdGlvbnMgPSB7XG4gICAgICB1c2VOZXdVcmxQYXJzZXI6IHRydWUsXG4gICAgICB1c2VVbmlmaWVkVG9wb2xvZ3k6IHRydWUsXG4gICAgfTtcbiAgICB0aGlzLl9tb25nb09wdGlvbnMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRNb25nb09wdGlvbnMsIG1vbmdvT3B0aW9ucyk7XG4gIH1cblxuICBfY29ubmVjdCgpIHtcbiAgICBpZiAoIXRoaXMuX2Nvbm5lY3Rpb25Qcm9taXNlKSB7XG4gICAgICB0aGlzLl9jb25uZWN0aW9uUHJvbWlzZSA9IE1vbmdvQ2xpZW50LmNvbm5lY3QoXG4gICAgICAgIHRoaXMuX2RhdGFiYXNlVVJJLFxuICAgICAgICB0aGlzLl9tb25nb09wdGlvbnNcbiAgICAgICkudGhlbihjbGllbnQgPT4ge1xuICAgICAgICB0aGlzLl9jbGllbnQgPSBjbGllbnQ7XG4gICAgICAgIHJldHVybiBjbGllbnQuZGIoY2xpZW50LnMub3B0aW9ucy5kYk5hbWUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jb25uZWN0aW9uUHJvbWlzZTtcbiAgfVxuXG4gIC8vIEZvciBhIGdpdmVuIGNvbmZpZyBvYmplY3QsIGZpbGVuYW1lLCBhbmQgZGF0YSwgc3RvcmUgYSBmaWxlXG4gIC8vIFJldHVybnMgYSBwcm9taXNlXG4gIGNyZWF0ZUZpbGUoZmlsZW5hbWU6IHN0cmluZywgZGF0YSkge1xuICAgIHJldHVybiB0aGlzLl9jb25uZWN0KClcbiAgICAgIC50aGVuKGRhdGFiYXNlID0+IHtcbiAgICAgICAgY29uc3QgZ3JpZFN0b3JlID0gbmV3IEdyaWRTdG9yZShkYXRhYmFzZSwgZmlsZW5hbWUsICd3Jyk7XG4gICAgICAgIHJldHVybiBncmlkU3RvcmUub3BlbigpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKGdyaWRTdG9yZSA9PiB7XG4gICAgICAgIHJldHVybiBncmlkU3RvcmUud3JpdGUoZGF0YSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oZ3JpZFN0b3JlID0+IHtcbiAgICAgICAgcmV0dXJuIGdyaWRTdG9yZS5jbG9zZSgpO1xuICAgICAgfSk7XG4gIH1cblxuICBkZWxldGVGaWxlKGZpbGVuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fY29ubmVjdCgpXG4gICAgICAudGhlbihkYXRhYmFzZSA9PiB7XG4gICAgICAgIGNvbnN0IGdyaWRTdG9yZSA9IG5ldyBHcmlkU3RvcmUoZGF0YWJhc2UsIGZpbGVuYW1lLCAncicpO1xuICAgICAgICByZXR1cm4gZ3JpZFN0b3JlLm9wZW4oKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihncmlkU3RvcmUgPT4ge1xuICAgICAgICByZXR1cm4gZ3JpZFN0b3JlLnVubGluaygpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKGdyaWRTdG9yZSA9PiB7XG4gICAgICAgIHJldHVybiBncmlkU3RvcmUuY2xvc2UoKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgZ2V0RmlsZURhdGEoZmlsZW5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9jb25uZWN0KClcbiAgICAgIC50aGVuKGRhdGFiYXNlID0+IHtcbiAgICAgICAgcmV0dXJuIEdyaWRTdG9yZS5leGlzdChkYXRhYmFzZSwgZmlsZW5hbWUpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGdyaWRTdG9yZSA9IG5ldyBHcmlkU3RvcmUoZGF0YWJhc2UsIGZpbGVuYW1lLCAncicpO1xuICAgICAgICAgIHJldHVybiBncmlkU3RvcmUub3BlbigpO1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbihncmlkU3RvcmUgPT4ge1xuICAgICAgICByZXR1cm4gZ3JpZFN0b3JlLnJlYWQoKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgZ2V0RmlsZUxvY2F0aW9uKGNvbmZpZywgZmlsZW5hbWUpIHtcbiAgICByZXR1cm4gKFxuICAgICAgY29uZmlnLm1vdW50ICtcbiAgICAgICcvZmlsZXMvJyArXG4gICAgICBjb25maWcuYXBwbGljYXRpb25JZCArXG4gICAgICAnLycgK1xuICAgICAgZW5jb2RlVVJJQ29tcG9uZW50KGZpbGVuYW1lKVxuICAgICk7XG4gIH1cblxuICBhc3luYyBoYW5kbGVGaWxlU3RyZWFtKGZpbGVuYW1lOiBzdHJpbmcsIHJlcSwgcmVzLCBjb250ZW50VHlwZSkge1xuICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IHRoaXMuX2Nvbm5lY3QoKS50aGVuKGRhdGFiYXNlID0+IHtcbiAgICAgIHJldHVybiBHcmlkU3RvcmUuZXhpc3QoZGF0YWJhc2UsIGZpbGVuYW1lKS50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgZ3JpZFN0b3JlID0gbmV3IEdyaWRTdG9yZShkYXRhYmFzZSwgZmlsZW5hbWUsICdyJyk7XG4gICAgICAgIHJldHVybiBncmlkU3RvcmUub3BlbigpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgaGFuZGxlUmFuZ2VSZXF1ZXN0KHN0cmVhbSwgcmVxLCByZXMsIGNvbnRlbnRUeXBlKTtcbiAgfVxuXG4gIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGlmICghdGhpcy5fY2xpZW50KSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jbGllbnQuY2xvc2UoZmFsc2UpO1xuICB9XG5cbiAgdmFsaWRhdGVGaWxlbmFtZShmaWxlbmFtZSkge1xuICAgIHJldHVybiB2YWxpZGF0ZUZpbGVuYW1lKGZpbGVuYW1lKTtcbiAgfVxufVxuXG4vLyBoYW5kbGVSYW5nZVJlcXVlc3QgaXMgbGljZW5zZWQgdW5kZXIgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbiA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlIChodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnkvNC4wLykuXG4vLyBBdXRob3I6IExFUk9JQiBhdCB3ZWlnaHRpbmdmb3JteXBpenphIChodHRwczovL3dlaWdodGluZ2Zvcm15cGl6emEud29yZHByZXNzLmNvbS8yMDE1LzA2LzI0L3N0cmVhbS1odG1sNS1tZWRpYS1jb250ZW50LWxpa2UtdmlkZW8tYXVkaW8tZnJvbS1tb25nb2RiLXVzaW5nLWV4cHJlc3MtYW5kLWdyaWRzdG9yZS8pLlxuZnVuY3Rpb24gaGFuZGxlUmFuZ2VSZXF1ZXN0KHN0cmVhbSwgcmVxLCByZXMsIGNvbnRlbnRUeXBlKSB7XG4gIGNvbnN0IGJ1ZmZlcl9zaXplID0gMTAyNCAqIDEwMjQ7IC8vMTAyNEtiXG4gIC8vIFJhbmdlIHJlcXVlc3QsIHBhcnRpYWwgc3RyZWFtIHRoZSBmaWxlXG4gIGNvbnN0IHBhcnRzID0gcmVxXG4gICAgLmdldCgnUmFuZ2UnKVxuICAgIC5yZXBsYWNlKC9ieXRlcz0vLCAnJylcbiAgICAuc3BsaXQoJy0nKTtcbiAgbGV0IFtzdGFydCwgZW5kXSA9IHBhcnRzO1xuICBjb25zdCBub3RFbmRlZCA9ICFlbmQgJiYgZW5kICE9PSAwO1xuICBjb25zdCBub3RTdGFydGVkID0gIXN0YXJ0ICYmIHN0YXJ0ICE9PSAwO1xuICAvLyBObyBlbmQgcHJvdmlkZWQsIHdlIHdhbnQgYWxsIGJ5dGVzXG4gIGlmIChub3RFbmRlZCkge1xuICAgIGVuZCA9IHN0cmVhbS5sZW5ndGggLSAxO1xuICB9XG4gIC8vIE5vIHN0YXJ0IHByb3ZpZGVkLCB3ZSdyZSByZWFkaW5nIGJhY2t3YXJkc1xuICBpZiAobm90U3RhcnRlZCkge1xuICAgIHN0YXJ0ID0gc3RyZWFtLmxlbmd0aCAtIGVuZDtcbiAgICBlbmQgPSBzdGFydCArIGVuZCAtIDE7XG4gIH1cblxuICAvLyBEYXRhIGV4Y2VlZHMgdGhlIGJ1ZmZlcl9zaXplLCBjYXBcbiAgaWYgKGVuZCAtIHN0YXJ0ID49IGJ1ZmZlcl9zaXplKSB7XG4gICAgZW5kID0gc3RhcnQgKyBidWZmZXJfc2l6ZSAtIDE7XG4gIH1cblxuICBjb25zdCBjb250ZW50TGVuZ3RoID0gZW5kIC0gc3RhcnQgKyAxO1xuXG4gIHJlcy53cml0ZUhlYWQoMjA2LCB7XG4gICAgJ0NvbnRlbnQtUmFuZ2UnOiAnYnl0ZXMgJyArIHN0YXJ0ICsgJy0nICsgZW5kICsgJy8nICsgc3RyZWFtLmxlbmd0aCxcbiAgICAnQWNjZXB0LVJhbmdlcyc6ICdieXRlcycsXG4gICAgJ0NvbnRlbnQtTGVuZ3RoJzogY29udGVudExlbmd0aCxcbiAgICAnQ29udGVudC1UeXBlJzogY29udGVudFR5cGUsXG4gIH0pO1xuXG4gIHN0cmVhbS5zZWVrKHN0YXJ0LCBmdW5jdGlvbigpIHtcbiAgICAvLyBHZXQgZ3JpZEZpbGUgc3RyZWFtXG4gICAgY29uc3QgZ3JpZEZpbGVTdHJlYW0gPSBzdHJlYW0uc3RyZWFtKHRydWUpO1xuICAgIGxldCBidWZmZXJBdmFpbCA9IDA7XG4gICAgbGV0IHJlbWFpbmluZ0J5dGVzVG9Xcml0ZSA9IGNvbnRlbnRMZW5ndGg7XG4gICAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgICAvLyBXcml0ZSB0byByZXNwb25zZVxuICAgIGdyaWRGaWxlU3RyZWFtLm9uKCdkYXRhJywgZnVuY3Rpb24oZGF0YSkge1xuICAgICAgYnVmZmVyQXZhaWwgKz0gZGF0YS5sZW5ndGg7XG4gICAgICBpZiAoYnVmZmVyQXZhaWwgPiAwKSB7XG4gICAgICAgIC8vIHNsaWNlIHJldHVybnMgdGhlIHNhbWUgYnVmZmVyIGlmIG92ZXJmbG93aW5nXG4gICAgICAgIC8vIHNhZmUgdG8gY2FsbCBpbiBhbnkgY2FzZVxuICAgICAgICBjb25zdCBidWZmZXIgPSBkYXRhLnNsaWNlKDAsIHJlbWFpbmluZ0J5dGVzVG9Xcml0ZSk7XG4gICAgICAgIC8vIFdyaXRlIHRoZSBidWZmZXJcbiAgICAgICAgcmVzLndyaXRlKGJ1ZmZlcik7XG4gICAgICAgIC8vIEluY3JlbWVudCB0b3RhbFxuICAgICAgICB0b3RhbEJ5dGVzV3JpdHRlbiArPSBidWZmZXIubGVuZ3RoO1xuICAgICAgICAvLyBEZWNyZW1lbnQgcmVtYWluaW5nXG4gICAgICAgIHJlbWFpbmluZ0J5dGVzVG9Xcml0ZSAtPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgLy8gRGVjcmVtZW50IHRoZSBhdmFpbGFibGUgYnVmZmVyXG4gICAgICAgIGJ1ZmZlckF2YWlsIC09IGJ1ZmZlci5sZW5ndGg7XG4gICAgICB9XG4gICAgICAvLyBJbiBjYXNlIG9mIHNtYWxsIHNsaWNlcywgYWxsIHZhbHVlcyB3aWxsIGJlIGdvb2QgYXQgdGhhdCBwb2ludFxuICAgICAgLy8gd2UndmUgd3JpdHRlbiBlbm91Z2gsIGVuZC4uLlxuICAgICAgaWYgKHRvdGFsQnl0ZXNXcml0dGVuID49IGNvbnRlbnRMZW5ndGgpIHtcbiAgICAgICAgc3RyZWFtLmNsb3NlKCk7XG4gICAgICAgIHJlcy5lbmQoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZGVmYXVsdCBHcmlkU3RvcmVBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Logger/LoggerAdapter.js b/lib/Adapters/Logger/LoggerAdapter.js new file mode 100644 index 0000000000..ed88ce5000 --- /dev/null +++ b/lib/Adapters/Logger/LoggerAdapter.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.LoggerAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ + +/** + * @module Adapters + */ + +/** + * @interface LoggerAdapter + * Logger Adapter + * Allows you to change the logger mechanism + * Default is WinstonLoggerAdapter.js + */ +class LoggerAdapter { + constructor(options) {} + /** + * log + * @param {String} level + * @param {String} message + * @param {Object} metadata + */ + + + log(level, message + /* meta */ + ) {} + +} + +exports.LoggerAdapter = LoggerAdapter; +var _default = LoggerAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9Mb2dnZXIvTG9nZ2VyQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJMb2dnZXJBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwibG9nIiwibGV2ZWwiLCJtZXNzYWdlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFHQTs7Ozs7O0FBTU8sTUFBTUEsYUFBTixDQUFvQjtBQUN6QkMsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQVUsQ0FBRTtBQUN2Qjs7Ozs7Ozs7QUFNQUMsRUFBQUEsR0FBRyxDQUFDQyxLQUFELEVBQVFDO0FBQVE7QUFBaEIsSUFBNEIsQ0FBRTs7QUFSUjs7O2VBV1pMLGEiLCJzb3VyY2VzQ29udGVudCI6WyIvKmVzbGludCBuby11bnVzZWQtdmFyczogXCJvZmZcIiovXG4vKipcbiAqIEBtb2R1bGUgQWRhcHRlcnNcbiAqL1xuLyoqXG4gKiBAaW50ZXJmYWNlIExvZ2dlckFkYXB0ZXJcbiAqIExvZ2dlciBBZGFwdGVyXG4gKiBBbGxvd3MgeW91IHRvIGNoYW5nZSB0aGUgbG9nZ2VyIG1lY2hhbmlzbVxuICogRGVmYXVsdCBpcyBXaW5zdG9uTG9nZ2VyQWRhcHRlci5qc1xuICovXG5leHBvcnQgY2xhc3MgTG9nZ2VyQWRhcHRlciB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHt9XG4gIC8qKlxuICAgKiBsb2dcbiAgICogQHBhcmFtIHtTdHJpbmd9IGxldmVsXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBtZXRhZGF0YVxuICAgKi9cbiAgbG9nKGxldmVsLCBtZXNzYWdlIC8qIG1ldGEgKi8pIHt9XG59XG5cbmV4cG9ydCBkZWZhdWx0IExvZ2dlckFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Logger/WinstonLogger.js b/lib/Adapters/Logger/WinstonLogger.js new file mode 100644 index 0000000000..f110f52fec --- /dev/null +++ b/lib/Adapters/Logger/WinstonLogger.js @@ -0,0 +1,135 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.configureLogger = configureLogger; +exports.addTransport = addTransport; +exports.removeTransport = removeTransport; +exports.default = exports.logger = void 0; + +var _winston = _interopRequireWildcard(require("winston")); + +var _fs = _interopRequireDefault(require("fs")); + +var _path = _interopRequireDefault(require("path")); + +var _winstonDailyRotateFile = _interopRequireDefault(require("winston-daily-rotate-file")); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _defaults = _interopRequireDefault(require("../../defaults")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +const logger = _winston.default.createLogger(); + +exports.logger = logger; + +function configureTransports(options) { + const transports = []; + + if (options) { + const silent = options.silent; + delete options.silent; + + try { + if (!_lodash.default.isNil(options.dirname)) { + const parseServer = new _winstonDailyRotateFile.default(Object.assign({ + filename: 'parse-server.info', + json: true, + format: _winston.format.combine(_winston.format.timestamp(), _winston.format.splat(), _winston.format.json()) + }, options)); + parseServer.name = 'parse-server'; + transports.push(parseServer); + const parseServerError = new _winstonDailyRotateFile.default(Object.assign({ + filename: 'parse-server.err', + json: true, + format: _winston.format.combine(_winston.format.timestamp(), _winston.format.splat(), _winston.format.json()) + }, options, { + level: 'error' + })); + parseServerError.name = 'parse-server-error'; + transports.push(parseServerError); + } + } catch (e) { + /* */ + } + + const consoleFormat = options.json ? _winston.format.json() : _winston.format.simple(); + const consoleOptions = Object.assign({ + colorize: true, + name: 'console', + silent, + format: consoleFormat + }, options); + transports.push(new _winston.default.transports.Console(consoleOptions)); + } + + logger.configure({ + transports + }); +} + +function configureLogger({ + logsFolder = _defaults.default.logsFolder, + jsonLogs = _defaults.default.jsonLogs, + logLevel = _winston.default.level, + verbose = _defaults.default.verbose, + silent = _defaults.default.silent +} = {}) { + if (verbose) { + logLevel = 'verbose'; + } + + _winston.default.level = logLevel; + const options = {}; + + if (logsFolder) { + if (!_path.default.isAbsolute(logsFolder)) { + logsFolder = _path.default.resolve(process.cwd(), logsFolder); + } + + try { + _fs.default.mkdirSync(logsFolder); + } catch (e) { + /* */ + } + } + + options.dirname = logsFolder; + options.level = logLevel; + options.silent = silent; + + if (jsonLogs) { + options.json = true; + options.stringify = true; + } + + configureTransports(options); +} + +function addTransport(transport) { + // we will remove the existing transport + // before replacing it with a new one + removeTransport(transport.name); + logger.add(transport); +} + +function removeTransport(transport) { + const matchingTransport = logger.transports.find(t1 => { + return typeof transport === 'string' ? t1.name === transport : t1 === transport; + }); + + if (matchingTransport) { + logger.remove(matchingTransport); + } +} + +var _default = logger; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlci5qcyJdLCJuYW1lcyI6WyJsb2dnZXIiLCJ3aW5zdG9uIiwiY3JlYXRlTG9nZ2VyIiwiY29uZmlndXJlVHJhbnNwb3J0cyIsIm9wdGlvbnMiLCJ0cmFuc3BvcnRzIiwic2lsZW50IiwiXyIsImlzTmlsIiwiZGlybmFtZSIsInBhcnNlU2VydmVyIiwiRGFpbHlSb3RhdGVGaWxlIiwiT2JqZWN0IiwiYXNzaWduIiwiZmlsZW5hbWUiLCJqc29uIiwiZm9ybWF0IiwiY29tYmluZSIsInRpbWVzdGFtcCIsInNwbGF0IiwibmFtZSIsInB1c2giLCJwYXJzZVNlcnZlckVycm9yIiwibGV2ZWwiLCJlIiwiY29uc29sZUZvcm1hdCIsInNpbXBsZSIsImNvbnNvbGVPcHRpb25zIiwiY29sb3JpemUiLCJDb25zb2xlIiwiY29uZmlndXJlIiwiY29uZmlndXJlTG9nZ2VyIiwibG9nc0ZvbGRlciIsImRlZmF1bHRzIiwianNvbkxvZ3MiLCJsb2dMZXZlbCIsInZlcmJvc2UiLCJwYXRoIiwiaXNBYnNvbHV0ZSIsInJlc29sdmUiLCJwcm9jZXNzIiwiY3dkIiwiZnMiLCJta2RpclN5bmMiLCJzdHJpbmdpZnkiLCJhZGRUcmFuc3BvcnQiLCJ0cmFuc3BvcnQiLCJyZW1vdmVUcmFuc3BvcnQiLCJhZGQiLCJtYXRjaGluZ1RyYW5zcG9ydCIsImZpbmQiLCJ0MSIsInJlbW92ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVBLE1BQU1BLE1BQU0sR0FBR0MsaUJBQVFDLFlBQVIsRUFBZjs7OztBQUVBLFNBQVNDLG1CQUFULENBQTZCQyxPQUE3QixFQUFzQztBQUNwQyxRQUFNQyxVQUFVLEdBQUcsRUFBbkI7O0FBQ0EsTUFBSUQsT0FBSixFQUFhO0FBQ1gsVUFBTUUsTUFBTSxHQUFHRixPQUFPLENBQUNFLE1BQXZCO0FBQ0EsV0FB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LENBQWFYLFVBQWI7QUFDRCxLQUZELENBRUUsT0FBT1IsQ0FBUCxFQUFVO0FBQ1Y7QUFDRDtBQUNGOztBQUNEcEIsRUFBQUEsT0FBTyxDQUFDSyxPQUFSLEdBQWtCdUIsVUFBbEI7QUFDQTVCLEVBQUFBLE9BQU8sQ0FBQ21CLEtBQVIsR0FBZ0JZLFFBQWhCO0FBQ0EvQixFQUFBQSxPQUFPLENBQUNFLE1BQVIsR0FBaUJBLE1BQWpCOztBQUVBLE1BQUk0QixRQUFKLEVBQWM7QUFDWjlCLElBQUFBLE9BQU8sQ0FBQ1csSUFBUixHQUFlLElBQWY7QUFDQVgsSUFBQUEsT0FBTyxDQUFDd0MsU0FBUixHQUFvQixJQUFwQjtBQUNEOztBQUNEekMsRUFBQUEsbUJBQW1CLENBQUNDLE9BQUQsQ0FBbkI7QUFDRDs7QUFFTSxTQUFTeUMsWUFBVCxDQUFzQkMsU0FBdEIsRUFBaUM7QUFDdEM7QUFDQTtBQUNBQyxFQUFBQSxlQUFlLENBQUNELFNBQVMsQ0FBQzFCLElBQVgsQ0FBZjtBQUVBcEIsRUFBQUEsTUFBTSxDQUFDZ0QsR0FBUCxDQUFXRixTQUFYO0FBQ0Q7O0FBRU0sU0FBU0MsZUFBVCxDQUF5QkQsU0FBekIsRUFBb0M7QUFDekMsUUFBTUcsaUJBQWlCLEdBQUdqRCxNQUFNLENBQUNLLFVBQVAsQ0FBa0I2QyxJQUFsQixDQUF1QkMsRUFBRSxJQUFJO0FBQ3JELFdBQU8sT0FBT0wsU0FBUCxLQUFxQixRQUFyQixHQUNISyxFQUFFLENBQUMvQixJQUFILEtBQVkwQixTQURULEdBRUhLLEVBQUUsS0FBS0wsU0FGWDtBQUdELEdBSnlCLENBQTFCOztBQU1BLE1BQUlHLGlCQUFKLEVBQXVCO0FBQ3JCakQsSUFBQUEsTUFBTSxDQUFDb0QsTUFBUCxDQUFjSCxpQkFBZDtBQUNEO0FBQ0Y7O2VBR2NqRCxNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHdpbnN0b24sIHsgZm9ybWF0IH0gZnJvbSAnd2luc3Rvbic7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgRGFpbHlSb3RhdGVGaWxlIGZyb20gJ3dpbnN0b24tZGFpbHktcm90YXRlLWZpbGUnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBkZWZhdWx0cyBmcm9tICcuLi8uLi9kZWZhdWx0cyc7XG5cbmNvbnN0IGxvZ2dlciA9IHdpbnN0b24uY3JlYXRlTG9nZ2VyKCk7XG5cbmZ1bmN0aW9uIGNvbmZpZ3VyZVRyYW5zcG9ydHMob3B0aW9ucykge1xuICBjb25zdCB0cmFuc3BvcnRzID0gW107XG4gIGlmIChvcHRpb25zKSB7XG4gICAgY29uc3Qgc2lsZW50ID0gb3B0aW9ucy5zaWxlbnQ7XG4gICAgZGVsZXRlIG9wdGlvbnMuc2lsZW50O1xuXG4gICAgdHJ5IHtcbiAgICAgIGlmICghXy5pc05pbChvcHRpb25zLmRpcm5hbWUpKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlU2VydmVyID0gbmV3IERhaWx5Um90YXRlRmlsZShcbiAgICAgICAgICBPYmplY3QuYXNzaWduKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmaWxlbmFtZTogJ3BhcnNlLXNlcnZlci5pbmZvJyxcbiAgICAgICAgICAgICAganNvbjogdHJ1ZSxcbiAgICAgICAgICAgICAgZm9ybWF0OiBmb3JtYXQuY29tYmluZShcbiAgICAgICAgICAgICAgICBmb3JtYXQudGltZXN0YW1wKCksXG4gICAgICAgICAgICAgICAgZm9ybWF0LnNwbGF0KCksXG4gICAgICAgICAgICAgICAgZm9ybWF0Lmpzb24oKVxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHBhcnNlU2VydmVyLm5hbWUgPSAncGFyc2Utc2VydmVyJztcbiAgICAgICAgdHJhbnNwb3J0cy5wdXNoKHBhcnNlU2VydmVyKTtcblxuICAgICAgICBjb25zdCBwYXJzZVNlcnZlckVycm9yID0gbmV3IERhaWx5Um90YXRlRmlsZShcbiAgICAgICAgICBPYmplY3QuYXNzaWduKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmaWxlbmFtZTogJ3BhcnNlLXNlcnZlci5lcnInLFxuICAgICAgICAgICAgICBqc29uOiB0cnVlLFxuICAgICAgICAgICAgICBmb3JtYXQ6IGZvcm1hdC5jb21iaW5lKFxuICAgICAgICAgICAgICAgIGZvcm1hdC50aW1lc3RhbXAoKSxcbiAgICAgICAgICAgICAgICBmb3JtYXQuc3BsYXQoKSxcbiAgICAgICAgICAgICAgICBmb3JtYXQuanNvbigpXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICAgIHsgbGV2ZWw6ICdlcnJvcicgfVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgcGFyc2VTZXJ2ZXJFcnJvci5uYW1lID0gJ3BhcnNlLXNlcnZlci1lcnJvcic7XG4gICAgICAgIHRyYW5zcG9ydHMucHVzaChwYXJzZVNlcnZlckVycm9yKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvKiAqL1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnNvbGVGb3JtYXQgPSBvcHRpb25zLmpzb24gPyBmb3JtYXQuanNvbigpIDogZm9ybWF0LnNpbXBsZSgpO1xuICAgIGNvbnN0IGNvbnNvbGVPcHRpb25zID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHtcbiAgICAgICAgY29sb3JpemU6IHRydWUsXG4gICAgICAgIG5hbWU6ICdjb25zb2xlJyxcbiAgICAgICAgc2lsZW50LFxuICAgICAgICBmb3JtYXQ6IGNvbnNvbGVGb3JtYXQsXG4gICAgICB9LFxuICAgICAgb3B0aW9uc1xuICAgICk7XG5cbiAgICB0cmFuc3BvcnRzLnB1c2gobmV3IHdpbnN0b24udHJhbnNwb3J0cy5Db25zb2xlKGNvbnNvbGVPcHRpb25zKSk7XG4gIH1cblxuICBsb2dnZXIuY29uZmlndXJlKHtcbiAgICB0cmFuc3BvcnRzLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbmZpZ3VyZUxvZ2dlcih7XG4gIGxvZ3NGb2xkZXIgPSBkZWZhdWx0cy5sb2dzRm9sZGVyLFxuICBqc29uTG9ncyA9IGRlZmF1bHRzLmpzb25Mb2dzLFxuICBsb2dMZXZlbCA9IHdpbnN0b24ubGV2ZWwsXG4gIHZlcmJvc2UgPSBkZWZhdWx0cy52ZXJib3NlLFxuICBzaWxlbnQgPSBkZWZhdWx0cy5zaWxlbnQsXG59ID0ge30pIHtcbiAgaWYgKHZlcmJvc2UpIHtcbiAgICBsb2dMZXZlbCA9ICd2ZXJib3NlJztcbiAgfVxuXG4gIHdpbnN0b24ubGV2ZWwgPSBsb2dMZXZlbDtcbiAgY29uc3Qgb3B0aW9ucyA9IHt9O1xuXG4gIGlmIChsb2dzRm9sZGVyKSB7XG4gICAgaWYgKCFwYXRoLmlzQWJzb2x1dGUobG9nc0ZvbGRlcikpIHtcbiAgICAgIGxvZ3NGb2xkZXIgPSBwYXRoLnJlc29sdmUocHJvY2Vzcy5jd2QoKSwgbG9nc0ZvbGRlcik7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBmcy5ta2RpclN5bmMobG9nc0ZvbGRlcik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLyogKi9cbiAgICB9XG4gIH1cbiAgb3B0aW9ucy5kaXJuYW1lID0gbG9nc0ZvbGRlcjtcbiAgb3B0aW9ucy5sZXZlbCA9IGxvZ0xldmVsO1xuICBvcHRpb25zLnNpbGVudCA9IHNpbGVudDtcblxuICBpZiAoanNvbkxvZ3MpIHtcbiAgICBvcHRpb25zLmpzb24gPSB0cnVlO1xuICAgIG9wdGlvbnMuc3RyaW5naWZ5ID0gdHJ1ZTtcbiAgfVxuICBjb25maWd1cmVUcmFuc3BvcnRzKG9wdGlvbnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWRkVHJhbnNwb3J0KHRyYW5zcG9ydCkge1xuICAvLyB3ZSB3aWxsIHJlbW92ZSB0aGUgZXhpc3RpbmcgdHJhbnNwb3J0XG4gIC8vIGJlZm9yZSByZXBsYWNpbmcgaXQgd2l0aCBhIG5ldyBvbmVcbiAgcmVtb3ZlVHJhbnNwb3J0KHRyYW5zcG9ydC5uYW1lKTtcblxuICBsb2dnZXIuYWRkKHRyYW5zcG9ydCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVUcmFuc3BvcnQodHJhbnNwb3J0KSB7XG4gIGNvbnN0IG1hdGNoaW5nVHJhbnNwb3J0ID0gbG9nZ2VyLnRyYW5zcG9ydHMuZmluZCh0MSA9PiB7XG4gICAgcmV0dXJuIHR5cGVvZiB0cmFuc3BvcnQgPT09ICdzdHJpbmcnXG4gICAgICA/IHQxLm5hbWUgPT09IHRyYW5zcG9ydFxuICAgICAgOiB0MSA9PT0gdHJhbnNwb3J0O1xuICB9KTtcblxuICBpZiAobWF0Y2hpbmdUcmFuc3BvcnQpIHtcbiAgICBsb2dnZXIucmVtb3ZlKG1hdGNoaW5nVHJhbnNwb3J0KTtcbiAgfVxufVxuXG5leHBvcnQgeyBsb2dnZXIgfTtcbmV4cG9ydCBkZWZhdWx0IGxvZ2dlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Logger/WinstonLoggerAdapter.js b/lib/Adapters/Logger/WinstonLoggerAdapter.js new file mode 100644 index 0000000000..9731f1816a --- /dev/null +++ b/lib/Adapters/Logger/WinstonLoggerAdapter.js @@ -0,0 +1,75 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.WinstonLoggerAdapter = void 0; + +var _LoggerAdapter = require("./LoggerAdapter"); + +var _WinstonLogger = require("./WinstonLogger"); + +const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000; + +class WinstonLoggerAdapter extends _LoggerAdapter.LoggerAdapter { + constructor(options) { + super(); + + if (options) { + (0, _WinstonLogger.configureLogger)(options); + } + } + + log() { + return _WinstonLogger.logger.log.apply(_WinstonLogger.logger, arguments); + } + + addTransport(transport) { + // Note that this is calling addTransport + // from logger. See import - confusing. + // but this is not recursive. + (0, _WinstonLogger.addTransport)(transport); + } // custom query as winston is currently limited + + + query(options, callback = () => {}) { + if (!options) { + options = {}; + } // defaults to 7 days prior + + + const from = options.from || new Date(Date.now() - 7 * MILLISECONDS_IN_A_DAY); + const until = options.until || new Date(); + const limit = options.size || 10; + const order = options.order || 'desc'; + const level = options.level || 'info'; + const queryOptions = { + from, + until, + limit, + order + }; + return new Promise((resolve, reject) => { + _WinstonLogger.logger.query(queryOptions, (err, res) => { + if (err) { + callback(err); + return reject(err); + } + + if (level === 'error') { + callback(res['parse-server-error']); + resolve(res['parse-server-error']); + } else { + callback(res['parse-server']); + resolve(res['parse-server']); + } + }); + }); + } + +} + +exports.WinstonLoggerAdapter = WinstonLoggerAdapter; +var _default = WinstonLoggerAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlckFkYXB0ZXIuanMiXSwibmFtZXMiOlsiTUlMTElTRUNPTkRTX0lOX0FfREFZIiwiV2luc3RvbkxvZ2dlckFkYXB0ZXIiLCJMb2dnZXJBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwibG9nIiwibG9nZ2VyIiwiYXBwbHkiLCJhcmd1bWVudHMiLCJhZGRUcmFuc3BvcnQiLCJ0cmFuc3BvcnQiLCJxdWVyeSIsImNhbGxiYWNrIiwiZnJvbSIsIkRhdGUiLCJub3ciLCJ1bnRpbCIsImxpbWl0Iiwic2l6ZSIsIm9yZGVyIiwibGV2ZWwiLCJxdWVyeU9wdGlvbnMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsImVyciIsInJlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUVBLE1BQU1BLHFCQUFxQixHQUFHLEtBQUssRUFBTCxHQUFVLEVBQVYsR0FBZSxJQUE3Qzs7QUFFTyxNQUFNQyxvQkFBTixTQUFtQ0MsNEJBQW5DLENBQWlEO0FBQ3REQyxFQUFBQSxXQUFXLENBQUNDLE9BQUQsRUFBVTtBQUNuQjs7QUFDQSxRQUFJQSxPQUFKLEVBQWE7QUFDWCwwQ0FBZ0JBLE9BQWhCO0FBQ0Q7QUFDRjs7QUFFREMsRUFBQUEsR0FBRyxHQUFHO0FBQ0osV0FBT0Msc0JBQU9ELEdBQVAsQ0FBV0UsS0FBWCxDQUFpQkQscUJBQWpCLEVBQXlCRSxTQUF6QixDQUFQO0FBQ0Q7O0FBRURDLEVBQUFBLFlBQVksQ0FBQ0MsU0FBRCxFQUFZO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBLHFDQUFhQSxTQUFiO0FBQ0QsR0FqQnFELENBbUJ0RDs7O0FBQ0FDLEVBQUFBLEtBQUssQ0FBQ1AsT0FBRCxFQUFVUSxRQUFRLEdBQUcsTUFBTSxDQUFFLENBQTdCLEVBQStCO0FBQ2xDLFFBQUksQ0FBQ1IsT0FBTCxFQUFjO0FBQ1pBLE1BQUFBLE9BQU8sR0FBRyxFQUFWO0FBQ0QsS0FIaUMsQ0FJbEM7OztBQUNBLFVBQU1TLElBQUksR0FDUlQsT0FBTyxDQUFDUyxJQUFSLElBQWdCLElBQUlDLElBQUosQ0FBU0EsSUFBSSxDQUFDQyxHQUFMLEtBQWEsSUFBSWYscUJBQTFCLENBRGxCO0FBRUEsVUFBTWdCLEtBQUssR0FBR1osT0FBTyxDQUFDWSxLQUFSLElBQWlCLElBQUlGLElBQUosRUFBL0I7QUFDQSxVQUFNRyxLQUFLLEdBQUdiLE9BQU8sQ0FBQ2MsSUFBUixJQUFnQixFQUE5QjtBQUNBLFVBQU1DLEtBQUssR0FBR2YsT0FBTyxDQUFDZSxLQUFSLElBQWlCLE1BQS9CO0FBQ0EsVUFBTUMsS0FBSyxHQUFHaEIsT0FBTyxDQUFDZ0IsS0FBUixJQUFpQixNQUEvQjtBQUVBLFVBQU1DLFlBQVksR0FBRztBQUNuQlIsTUFBQUEsSUFEbUI7QUFFbkJHLE1BQUFBLEtBRm1CO0FBR25CQyxNQUFBQSxLQUhtQjtBQUluQkUsTUFBQUE7QUFKbUIsS0FBckI7QUFPQSxXQUFPLElBQUlHLE9BQUosQ0FBWSxDQUFDQyxPQUFELEVBQVVDLE1BQVYsS0FBcUI7QUFDdENsQiw0QkFBT0ssS0FBUCxDQUFhVSxZQUFiLEVBQTJCLENBQUNJLEdBQUQsRUFBTUMsR0FBTixLQUFjO0FBQ3ZDLFlBQUlELEdBQUosRUFBUztBQUNQYixVQUFBQSxRQUFRLENBQUNhLEdBQUQsQ0FBUjtBQUNBLGlCQUFPRCxNQUFNLENBQUNDLEdBQUQsQ0FBYjtBQUNEOztBQUVELFlBQUlMLEtBQUssS0FBSyxPQUFkLEVBQXVCO0FBQ3JCUixVQUFBQSxRQUFRLENBQUNjLEdBQUcsQ0FBQyxvQkFBRCxDQUFKLENBQVI7QUFDQUgsVUFBQUEsT0FBTyxDQUFDRyxHQUFHLENBQUMsb0JBQUQsQ0FBSixDQUFQO0FBQ0QsU0FIRCxNQUdPO0FBQ0xkLFVBQUFBLFFBQVEsQ0FBQ2MsR0FBRyxDQUFDLGNBQUQsQ0FBSixDQUFSO0FBQ0FILFVBQUFBLE9BQU8sQ0FBQ0csR0FBRyxDQUFDLGNBQUQsQ0FBSixDQUFQO0FBQ0Q7QUFDRixPQWJEO0FBY0QsS0FmTSxDQUFQO0FBZ0JEOztBQXZEcUQ7OztlQTBEekN6QixvQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExvZ2dlckFkYXB0ZXIgfSBmcm9tICcuL0xvZ2dlckFkYXB0ZXInO1xuaW1wb3J0IHsgbG9nZ2VyLCBhZGRUcmFuc3BvcnQsIGNvbmZpZ3VyZUxvZ2dlciB9IGZyb20gJy4vV2luc3RvbkxvZ2dlcic7XG5cbmNvbnN0IE1JTExJU0VDT05EU19JTl9BX0RBWSA9IDI0ICogNjAgKiA2MCAqIDEwMDA7XG5cbmV4cG9ydCBjbGFzcyBXaW5zdG9uTG9nZ2VyQWRhcHRlciBleHRlbmRzIExvZ2dlckFkYXB0ZXIge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgc3VwZXIoKTtcbiAgICBpZiAob3B0aW9ucykge1xuICAgICAgY29uZmlndXJlTG9nZ2VyKG9wdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIGxvZygpIHtcbiAgICByZXR1cm4gbG9nZ2VyLmxvZy5hcHBseShsb2dnZXIsIGFyZ3VtZW50cyk7XG4gIH1cblxuICBhZGRUcmFuc3BvcnQodHJhbnNwb3J0KSB7XG4gICAgLy8gTm90ZSB0aGF0IHRoaXMgaXMgY2FsbGluZyBhZGRUcmFuc3BvcnRcbiAgICAvLyBmcm9tIGxvZ2dlci4gIFNlZSBpbXBvcnQgLSBjb25mdXNpbmcuXG4gICAgLy8gYnV0IHRoaXMgaXMgbm90IHJlY3Vyc2l2ZS5cbiAgICBhZGRUcmFuc3BvcnQodHJhbnNwb3J0KTtcbiAgfVxuXG4gIC8vIGN1c3RvbSBxdWVyeSBhcyB3aW5zdG9uIGlzIGN1cnJlbnRseSBsaW1pdGVkXG4gIHF1ZXJ5KG9wdGlvbnMsIGNhbGxiYWNrID0gKCkgPT4ge30pIHtcbiAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICB9XG4gICAgLy8gZGVmYXVsdHMgdG8gNyBkYXlzIHByaW9yXG4gICAgY29uc3QgZnJvbSA9XG4gICAgICBvcHRpb25zLmZyb20gfHwgbmV3IERhdGUoRGF0ZS5ub3coKSAtIDcgKiBNSUxMSVNFQ09ORFNfSU5fQV9EQVkpO1xuICAgIGNvbnN0IHVudGlsID0gb3B0aW9ucy51bnRpbCB8fCBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IGxpbWl0ID0gb3B0aW9ucy5zaXplIHx8IDEwO1xuICAgIGNvbnN0IG9yZGVyID0gb3B0aW9ucy5vcmRlciB8fCAnZGVzYyc7XG4gICAgY29uc3QgbGV2ZWwgPSBvcHRpb25zLmxldmVsIHx8ICdpbmZvJztcblxuICAgIGNvbnN0IHF1ZXJ5T3B0aW9ucyA9IHtcbiAgICAgIGZyb20sXG4gICAgICB1bnRpbCxcbiAgICAgIGxpbWl0LFxuICAgICAgb3JkZXIsXG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsb2dnZXIucXVlcnkocXVlcnlPcHRpb25zLCAoZXJyLCByZXMpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxldmVsID09PSAnZXJyb3InKSB7XG4gICAgICAgICAgY2FsbGJhY2socmVzWydwYXJzZS1zZXJ2ZXItZXJyb3InXSk7XG4gICAgICAgICAgcmVzb2x2ZShyZXNbJ3BhcnNlLXNlcnZlci1lcnJvciddKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYWxsYmFjayhyZXNbJ3BhcnNlLXNlcnZlciddKTtcbiAgICAgICAgICByZXNvbHZlKHJlc1sncGFyc2Utc2VydmVyJ10pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBXaW5zdG9uTG9nZ2VyQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/MessageQueue/EventEmitterMQ.js b/lib/Adapters/MessageQueue/EventEmitterMQ.js new file mode 100644 index 0000000000..ddf372cd6d --- /dev/null +++ b/lib/Adapters/MessageQueue/EventEmitterMQ.js @@ -0,0 +1,73 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.EventEmitterMQ = void 0; + +var _events = _interopRequireDefault(require("events")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const emitter = new _events.default.EventEmitter(); +const subscriptions = new Map(); + +function unsubscribe(channel) { + if (!subscriptions.has(channel)) { + //console.log('No channel to unsub from'); + return; + } //console.log('unsub ', channel); + + + emitter.removeListener(channel, subscriptions.get(channel)); + subscriptions.delete(channel); +} + +class Publisher { + constructor(emitter) { + this.emitter = emitter; + } + + publish(channel, message) { + this.emitter.emit(channel, message); + } + +} + +class Consumer extends _events.default.EventEmitter { + constructor(emitter) { + super(); + this.emitter = emitter; + } + + subscribe(channel) { + unsubscribe(channel); + + const handler = message => { + this.emit('message', channel, message); + }; + + subscriptions.set(channel, handler); + this.emitter.on(channel, handler); + } + + unsubscribe(channel) { + unsubscribe(channel); + } + +} + +function createPublisher() { + return new Publisher(emitter); +} + +function createSubscriber() { + return new Consumer(emitter); +} + +const EventEmitterMQ = { + createPublisher, + createSubscriber +}; +exports.EventEmitterMQ = EventEmitterMQ; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9NZXNzYWdlUXVldWUvRXZlbnRFbWl0dGVyTVEuanMiXSwibmFtZXMiOlsiZW1pdHRlciIsImV2ZW50cyIsIkV2ZW50RW1pdHRlciIsInN1YnNjcmlwdGlvbnMiLCJNYXAiLCJ1bnN1YnNjcmliZSIsImNoYW5uZWwiLCJoYXMiLCJyZW1vdmVMaXN0ZW5lciIsImdldCIsImRlbGV0ZSIsIlB1Ymxpc2hlciIsImNvbnN0cnVjdG9yIiwicHVibGlzaCIsIm1lc3NhZ2UiLCJlbWl0IiwiQ29uc3VtZXIiLCJzdWJzY3JpYmUiLCJoYW5kbGVyIiwic2V0Iiwib24iLCJjcmVhdGVQdWJsaXNoZXIiLCJjcmVhdGVTdWJzY3JpYmVyIiwiRXZlbnRFbWl0dGVyTVEiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUVBLE1BQU1BLE9BQU8sR0FBRyxJQUFJQyxnQkFBT0MsWUFBWCxFQUFoQjtBQUNBLE1BQU1DLGFBQWEsR0FBRyxJQUFJQyxHQUFKLEVBQXRCOztBQUVBLFNBQVNDLFdBQVQsQ0FBcUJDLE9BQXJCLEVBQXNDO0FBQ3BDLE1BQUksQ0FBQ0gsYUFBYSxDQUFDSSxHQUFkLENBQWtCRCxPQUFsQixDQUFMLEVBQWlDO0FBQy9CO0FBQ0E7QUFDRCxHQUptQyxDQUtwQzs7O0FBQ0FOLEVBQUFBLE9BQU8sQ0FBQ1EsY0FBUixDQUF1QkYsT0FBdkIsRUFBZ0NILGFBQWEsQ0FBQ00sR0FBZCxDQUFrQkgsT0FBbEIsQ0FBaEM7QUFDQUgsRUFBQUEsYUFBYSxDQUFDTyxNQUFkLENBQXFCSixPQUFyQjtBQUNEOztBQUVELE1BQU1LLFNBQU4sQ0FBZ0I7QUFHZEMsRUFBQUEsV0FBVyxDQUFDWixPQUFELEVBQWU7QUFDeEIsU0FBS0EsT0FBTCxHQUFlQSxPQUFmO0FBQ0Q7O0FBRURhLEVBQUFBLE9BQU8sQ0FBQ1AsT0FBRCxFQUFrQlEsT0FBbEIsRUFBeUM7QUFDOUMsU0FBS2QsT0FBTCxDQUFhZSxJQUFiLENBQWtCVCxPQUFsQixFQUEyQlEsT0FBM0I7QUFDRDs7QUFUYTs7QUFZaEIsTUFBTUUsUUFBTixTQUF1QmYsZ0JBQU9DLFlBQTlCLENBQTJDO0FBR3pDVSxFQUFBQSxXQUFXLENBQUNaLE9BQUQsRUFBZTtBQUN4QjtBQUNBLFNBQUtBLE9BQUwsR0FBZUEsT0FBZjtBQUNEOztBQUVEaUIsRUFBQUEsU0FBUyxDQUFDWCxPQUFELEVBQXdCO0FBQy9CRCxJQUFBQSxXQUFXLENBQUNDLE9BQUQsQ0FBWDs7QUFDQSxVQUFNWSxPQUFPLEdBQUdKLE9BQU8sSUFBSTtBQUN6QixXQUFLQyxJQUFMLENBQVUsU0FBVixFQUFxQlQsT0FBckIsRUFBOEJRLE9BQTlCO0FBQ0QsS0FGRDs7QUFHQVgsSUFBQUEsYUFBYSxDQUFDZ0IsR0FBZCxDQUFrQmIsT0FBbEIsRUFBMkJZLE9BQTNCO0FBQ0EsU0FBS2xCLE9BQUwsQ0FBYW9CLEVBQWIsQ0FBZ0JkLE9BQWhCLEVBQXlCWSxPQUF6QjtBQUNEOztBQUVEYixFQUFBQSxXQUFXLENBQUNDLE9BQUQsRUFBd0I7QUFDakNELElBQUFBLFdBQVcsQ0FBQ0MsT0FBRCxDQUFYO0FBQ0Q7O0FBbkJ3Qzs7QUFzQjNDLFNBQVNlLGVBQVQsR0FBZ0M7QUFDOUIsU0FBTyxJQUFJVixTQUFKLENBQWNYLE9BQWQsQ0FBUDtBQUNEOztBQUVELFNBQVNzQixnQkFBVCxHQUFpQztBQUMvQixTQUFPLElBQUlOLFFBQUosQ0FBYWhCLE9BQWIsQ0FBUDtBQUNEOztBQUVELE1BQU11QixjQUFjLEdBQUc7QUFDckJGLEVBQUFBLGVBRHFCO0FBRXJCQyxFQUFBQTtBQUZxQixDQUF2QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBldmVudHMgZnJvbSAnZXZlbnRzJztcblxuY29uc3QgZW1pdHRlciA9IG5ldyBldmVudHMuRXZlbnRFbWl0dGVyKCk7XG5jb25zdCBzdWJzY3JpcHRpb25zID0gbmV3IE1hcCgpO1xuXG5mdW5jdGlvbiB1bnN1YnNjcmliZShjaGFubmVsOiBzdHJpbmcpIHtcbiAgaWYgKCFzdWJzY3JpcHRpb25zLmhhcyhjaGFubmVsKSkge1xuICAgIC8vY29uc29sZS5sb2coJ05vIGNoYW5uZWwgdG8gdW5zdWIgZnJvbScpO1xuICAgIHJldHVybjtcbiAgfVxuICAvL2NvbnNvbGUubG9nKCd1bnN1YiAnLCBjaGFubmVsKTtcbiAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihjaGFubmVsLCBzdWJzY3JpcHRpb25zLmdldChjaGFubmVsKSk7XG4gIHN1YnNjcmlwdGlvbnMuZGVsZXRlKGNoYW5uZWwpO1xufVxuXG5jbGFzcyBQdWJsaXNoZXIge1xuICBlbWl0dGVyOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoZW1pdHRlcjogYW55KSB7XG4gICAgdGhpcy5lbWl0dGVyID0gZW1pdHRlcjtcbiAgfVxuXG4gIHB1Ymxpc2goY2hhbm5lbDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmVtaXR0ZXIuZW1pdChjaGFubmVsLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5jbGFzcyBDb25zdW1lciBleHRlbmRzIGV2ZW50cy5FdmVudEVtaXR0ZXIge1xuICBlbWl0dGVyOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoZW1pdHRlcjogYW55KSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLmVtaXR0ZXIgPSBlbWl0dGVyO1xuICB9XG5cbiAgc3Vic2NyaWJlKGNoYW5uZWw6IHN0cmluZyk6IHZvaWQge1xuICAgIHVuc3Vic2NyaWJlKGNoYW5uZWwpO1xuICAgIGNvbnN0IGhhbmRsZXIgPSBtZXNzYWdlID0+IHtcbiAgICAgIHRoaXMuZW1pdCgnbWVzc2FnZScsIGNoYW5uZWwsIG1lc3NhZ2UpO1xuICAgIH07XG4gICAgc3Vic2NyaXB0aW9ucy5zZXQoY2hhbm5lbCwgaGFuZGxlcik7XG4gICAgdGhpcy5lbWl0dGVyLm9uKGNoYW5uZWwsIGhhbmRsZXIpO1xuICB9XG5cbiAgdW5zdWJzY3JpYmUoY2hhbm5lbDogc3RyaW5nKTogdm9pZCB7XG4gICAgdW5zdWJzY3JpYmUoY2hhbm5lbCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlUHVibGlzaGVyKCk6IGFueSB7XG4gIHJldHVybiBuZXcgUHVibGlzaGVyKGVtaXR0ZXIpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVTdWJzY3JpYmVyKCk6IGFueSB7XG4gIHJldHVybiBuZXcgQ29uc3VtZXIoZW1pdHRlcik7XG59XG5cbmNvbnN0IEV2ZW50RW1pdHRlck1RID0ge1xuICBjcmVhdGVQdWJsaXNoZXIsXG4gIGNyZWF0ZVN1YnNjcmliZXIsXG59O1xuXG5leHBvcnQgeyBFdmVudEVtaXR0ZXJNUSB9O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/PubSub/EventEmitterPubSub.js b/lib/Adapters/PubSub/EventEmitterPubSub.js new file mode 100644 index 0000000000..e5f1670d83 --- /dev/null +++ b/lib/Adapters/PubSub/EventEmitterPubSub.js @@ -0,0 +1,65 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.EventEmitterPubSub = void 0; + +var _events = _interopRequireDefault(require("events")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const emitter = new _events.default.EventEmitter(); + +class Publisher { + constructor(emitter) { + this.emitter = emitter; + } + + publish(channel, message) { + this.emitter.emit(channel, message); + } + +} + +class Subscriber extends _events.default.EventEmitter { + constructor(emitter) { + super(); + this.emitter = emitter; + this.subscriptions = new Map(); + } + + subscribe(channel) { + const handler = message => { + this.emit('message', channel, message); + }; + + this.subscriptions.set(channel, handler); + this.emitter.on(channel, handler); + } + + unsubscribe(channel) { + if (!this.subscriptions.has(channel)) { + return; + } + + this.emitter.removeListener(channel, this.subscriptions.get(channel)); + this.subscriptions.delete(channel); + } + +} + +function createPublisher() { + return new Publisher(emitter); +} + +function createSubscriber() { + return new Subscriber(emitter); +} + +const EventEmitterPubSub = { + createPublisher, + createSubscriber +}; +exports.EventEmitterPubSub = EventEmitterPubSub; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9QdWJTdWIvRXZlbnRFbWl0dGVyUHViU3ViLmpzIl0sIm5hbWVzIjpbImVtaXR0ZXIiLCJldmVudHMiLCJFdmVudEVtaXR0ZXIiLCJQdWJsaXNoZXIiLCJjb25zdHJ1Y3RvciIsInB1Ymxpc2giLCJjaGFubmVsIiwibWVzc2FnZSIsImVtaXQiLCJTdWJzY3JpYmVyIiwic3Vic2NyaXB0aW9ucyIsIk1hcCIsInN1YnNjcmliZSIsImhhbmRsZXIiLCJzZXQiLCJvbiIsInVuc3Vic2NyaWJlIiwiaGFzIiwicmVtb3ZlTGlzdGVuZXIiLCJnZXQiLCJkZWxldGUiLCJjcmVhdGVQdWJsaXNoZXIiLCJjcmVhdGVTdWJzY3JpYmVyIiwiRXZlbnRFbWl0dGVyUHViU3ViIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFFQSxNQUFNQSxPQUFPLEdBQUcsSUFBSUMsZ0JBQU9DLFlBQVgsRUFBaEI7O0FBRUEsTUFBTUMsU0FBTixDQUFnQjtBQUdkQyxFQUFBQSxXQUFXLENBQUNKLE9BQUQsRUFBZTtBQUN4QixTQUFLQSxPQUFMLEdBQWVBLE9BQWY7QUFDRDs7QUFFREssRUFBQUEsT0FBTyxDQUFDQyxPQUFELEVBQWtCQyxPQUFsQixFQUF5QztBQUM5QyxTQUFLUCxPQUFMLENBQWFRLElBQWIsQ0FBa0JGLE9BQWxCLEVBQTJCQyxPQUEzQjtBQUNEOztBQVRhOztBQVloQixNQUFNRSxVQUFOLFNBQXlCUixnQkFBT0MsWUFBaEMsQ0FBNkM7QUFJM0NFLEVBQUFBLFdBQVcsQ0FBQ0osT0FBRCxFQUFlO0FBQ3hCO0FBQ0EsU0FBS0EsT0FBTCxHQUFlQSxPQUFmO0FBQ0EsU0FBS1UsYUFBTCxHQUFxQixJQUFJQyxHQUFKLEVBQXJCO0FBQ0Q7O0FBRURDLEVBQUFBLFNBQVMsQ0FBQ04sT0FBRCxFQUF3QjtBQUMvQixVQUFNTyxPQUFPLEdBQUdOLE9BQU8sSUFBSTtBQUN6QixXQUFLQyxJQUFMLENBQVUsU0FBVixFQUFxQkYsT0FBckIsRUFBOEJDLE9BQTlCO0FBQ0QsS0FGRDs7QUFHQSxTQUFLRyxhQUFMLENBQW1CSSxHQUFuQixDQUF1QlIsT0FBdkIsRUFBZ0NPLE9BQWhDO0FBQ0EsU0FBS2IsT0FBTCxDQUFhZSxFQUFiLENBQWdCVCxPQUFoQixFQUF5Qk8sT0FBekI7QUFDRDs7QUFFREcsRUFBQUEsV0FBVyxDQUFDVixPQUFELEVBQXdCO0FBQ2pDLFFBQUksQ0FBQyxLQUFLSSxhQUFMLENBQW1CTyxHQUFuQixDQUF1QlgsT0FBdkIsQ0FBTCxFQUFzQztBQUNwQztBQUNEOztBQUNELFNBQUtOLE9BQUwsQ0FBYWtCLGNBQWIsQ0FBNEJaLE9BQTVCLEVBQXFDLEtBQUtJLGFBQUwsQ0FBbUJTLEdBQW5CLENBQXVCYixPQUF2QixDQUFyQztBQUNBLFNBQUtJLGFBQUwsQ0FBbUJVLE1BQW5CLENBQTBCZCxPQUExQjtBQUNEOztBQXhCMEM7O0FBMkI3QyxTQUFTZSxlQUFULEdBQWdDO0FBQzlCLFNBQU8sSUFBSWxCLFNBQUosQ0FBY0gsT0FBZCxDQUFQO0FBQ0Q7O0FBRUQsU0FBU3NCLGdCQUFULEdBQWlDO0FBQy9CLFNBQU8sSUFBSWIsVUFBSixDQUFlVCxPQUFmLENBQVA7QUFDRDs7QUFFRCxNQUFNdUIsa0JBQWtCLEdBQUc7QUFDekJGLEVBQUFBLGVBRHlCO0FBRXpCQyxFQUFBQTtBQUZ5QixDQUEzQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBldmVudHMgZnJvbSAnZXZlbnRzJztcblxuY29uc3QgZW1pdHRlciA9IG5ldyBldmVudHMuRXZlbnRFbWl0dGVyKCk7XG5cbmNsYXNzIFB1Ymxpc2hlciB7XG4gIGVtaXR0ZXI6IGFueTtcblxuICBjb25zdHJ1Y3RvcihlbWl0dGVyOiBhbnkpIHtcbiAgICB0aGlzLmVtaXR0ZXIgPSBlbWl0dGVyO1xuICB9XG5cbiAgcHVibGlzaChjaGFubmVsOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuZW1pdHRlci5lbWl0KGNoYW5uZWwsIG1lc3NhZ2UpO1xuICB9XG59XG5cbmNsYXNzIFN1YnNjcmliZXIgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgZW1pdHRlcjogYW55O1xuICBzdWJzY3JpcHRpb25zOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoZW1pdHRlcjogYW55KSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLmVtaXR0ZXIgPSBlbWl0dGVyO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIHN1YnNjcmliZShjaGFubmVsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBoYW5kbGVyID0gbWVzc2FnZSA9PiB7XG4gICAgICB0aGlzLmVtaXQoJ21lc3NhZ2UnLCBjaGFubmVsLCBtZXNzYWdlKTtcbiAgICB9O1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5zZXQoY2hhbm5lbCwgaGFuZGxlcik7XG4gICAgdGhpcy5lbWl0dGVyLm9uKGNoYW5uZWwsIGhhbmRsZXIpO1xuICB9XG5cbiAgdW5zdWJzY3JpYmUoY2hhbm5lbDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnN1YnNjcmlwdGlvbnMuaGFzKGNoYW5uZWwpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihjaGFubmVsLCB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNoYW5uZWwpKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZGVsZXRlKGNoYW5uZWwpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVB1Ymxpc2hlcigpOiBhbnkge1xuICByZXR1cm4gbmV3IFB1Ymxpc2hlcihlbWl0dGVyKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlU3Vic2NyaWJlcigpOiBhbnkge1xuICByZXR1cm4gbmV3IFN1YnNjcmliZXIoZW1pdHRlcik7XG59XG5cbmNvbnN0IEV2ZW50RW1pdHRlclB1YlN1YiA9IHtcbiAgY3JlYXRlUHVibGlzaGVyLFxuICBjcmVhdGVTdWJzY3JpYmVyLFxufTtcblxuZXhwb3J0IHsgRXZlbnRFbWl0dGVyUHViU3ViIH07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/PubSub/PubSubAdapter.js b/lib/Adapters/PubSub/PubSubAdapter.js new file mode 100644 index 0000000000..77e50d7e44 --- /dev/null +++ b/lib/Adapters/PubSub/PubSubAdapter.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PubSubAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ + +/** + * @module Adapters + */ + +/** + * @interface PubSubAdapter + */ +class PubSubAdapter { + /** + * @returns {PubSubAdapter.Publisher} + */ + static createPublisher() {} + /** + * @returns {PubSubAdapter.Subscriber} + */ + + + static createSubscriber() {} + +} +/** + * @interface Publisher + * @memberof PubSubAdapter + */ + + +exports.PubSubAdapter = PubSubAdapter; +var _default = PubSubAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9QdWJTdWIvUHViU3ViQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJQdWJTdWJBZGFwdGVyIiwiY3JlYXRlUHVibGlzaGVyIiwiY3JlYXRlU3Vic2NyaWJlciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBR0E7OztBQUdPLE1BQU1BLGFBQU4sQ0FBb0I7QUFDekI7OztBQUdBLFNBQU9DLGVBQVAsR0FBeUIsQ0FBRTtBQUMzQjs7Ozs7QUFHQSxTQUFPQyxnQkFBUCxHQUEwQixDQUFFOztBQVJIO0FBVzNCOzs7Ozs7O2VBOEJlRixhIiwic291cmNlc0NvbnRlbnQiOlsiLyplc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIqL1xuLyoqXG4gKiBAbW9kdWxlIEFkYXB0ZXJzXG4gKi9cbi8qKlxuICogQGludGVyZmFjZSBQdWJTdWJBZGFwdGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBQdWJTdWJBZGFwdGVyIHtcbiAgLyoqXG4gICAqIEByZXR1cm5zIHtQdWJTdWJBZGFwdGVyLlB1Ymxpc2hlcn1cbiAgICovXG4gIHN0YXRpYyBjcmVhdGVQdWJsaXNoZXIoKSB7fVxuICAvKipcbiAgICogQHJldHVybnMge1B1YlN1YkFkYXB0ZXIuU3Vic2NyaWJlcn1cbiAgICovXG4gIHN0YXRpYyBjcmVhdGVTdWJzY3JpYmVyKCkge31cbn1cblxuLyoqXG4gKiBAaW50ZXJmYWNlIFB1Ymxpc2hlclxuICogQG1lbWJlcm9mIFB1YlN1YkFkYXB0ZXJcbiAqL1xuaW50ZXJmYWNlIFB1Ymxpc2hlciB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gY2hhbm5lbCB0aGUgY2hhbm5lbCBpbiB3aGljaCB0byBwdWJsaXNoXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIHRoZSBtZXNzYWdlIHRvIHB1Ymxpc2hcbiAgICovXG4gIHB1Ymxpc2goY2hhbm5lbDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpOiB2b2lkO1xufVxuXG4vKipcbiAqIEBpbnRlcmZhY2UgU3Vic2NyaWJlclxuICogQG1lbWJlcm9mIFB1YlN1YkFkYXB0ZXJcbiAqL1xuaW50ZXJmYWNlIFN1YnNjcmliZXIge1xuICAvKipcbiAgICogY2FsbGVkIHdoZW4gYSBuZXcgc3Vic2NyaXB0aW9uIHRoZSBjaGFubmVsIGlzIHJlcXVpcmVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjaGFubmVsIHRoZSBjaGFubmVsIHRvIHN1YnNjcmliZVxuICAgKi9cbiAgc3Vic2NyaWJlKGNoYW5uZWw6IHN0cmluZyk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIGNhbGxlZCB3aGVuIHRoZSBzdWJzY3JpcHRpb24gZnJvbSB0aGUgY2hhbm5lbCBzaG91bGQgYmUgc3RvcHBlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gY2hhbm5lbFxuICAgKi9cbiAgdW5zdWJzY3JpYmUoY2hhbm5lbDogc3RyaW5nKTogdm9pZDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUHViU3ViQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/PubSub/RedisPubSub.js b/lib/Adapters/PubSub/RedisPubSub.js new file mode 100644 index 0000000000..cb4a03c10a --- /dev/null +++ b/lib/Adapters/PubSub/RedisPubSub.js @@ -0,0 +1,33 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RedisPubSub = void 0; + +var _redis = _interopRequireDefault(require("redis")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createPublisher({ + redisURL, + redisOptions = {} +}) { + redisOptions.no_ready_check = true; + return _redis.default.createClient(redisURL, redisOptions); +} + +function createSubscriber({ + redisURL, + redisOptions = {} +}) { + redisOptions.no_ready_check = true; + return _redis.default.createClient(redisURL, redisOptions); +} + +const RedisPubSub = { + createPublisher, + createSubscriber +}; +exports.RedisPubSub = RedisPubSub; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9QdWJTdWIvUmVkaXNQdWJTdWIuanMiXSwibmFtZXMiOlsiY3JlYXRlUHVibGlzaGVyIiwicmVkaXNVUkwiLCJyZWRpc09wdGlvbnMiLCJub19yZWFkeV9jaGVjayIsInJlZGlzIiwiY3JlYXRlQ2xpZW50IiwiY3JlYXRlU3Vic2NyaWJlciIsIlJlZGlzUHViU3ViIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFFQSxTQUFTQSxlQUFULENBQXlCO0FBQUVDLEVBQUFBLFFBQUY7QUFBWUMsRUFBQUEsWUFBWSxHQUFHO0FBQTNCLENBQXpCLEVBQStEO0FBQzdEQSxFQUFBQSxZQUFZLENBQUNDLGNBQWIsR0FBOEIsSUFBOUI7QUFDQSxTQUFPQyxlQUFNQyxZQUFOLENBQW1CSixRQUFuQixFQUE2QkMsWUFBN0IsQ0FBUDtBQUNEOztBQUVELFNBQVNJLGdCQUFULENBQTBCO0FBQUVMLEVBQUFBLFFBQUY7QUFBWUMsRUFBQUEsWUFBWSxHQUFHO0FBQTNCLENBQTFCLEVBQWdFO0FBQzlEQSxFQUFBQSxZQUFZLENBQUNDLGNBQWIsR0FBOEIsSUFBOUI7QUFDQSxTQUFPQyxlQUFNQyxZQUFOLENBQW1CSixRQUFuQixFQUE2QkMsWUFBN0IsQ0FBUDtBQUNEOztBQUVELE1BQU1LLFdBQVcsR0FBRztBQUNsQlAsRUFBQUEsZUFEa0I7QUFFbEJNLEVBQUFBO0FBRmtCLENBQXBCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlZGlzIGZyb20gJ3JlZGlzJztcblxuZnVuY3Rpb24gY3JlYXRlUHVibGlzaGVyKHsgcmVkaXNVUkwsIHJlZGlzT3B0aW9ucyA9IHt9IH0pOiBhbnkge1xuICByZWRpc09wdGlvbnMubm9fcmVhZHlfY2hlY2sgPSB0cnVlO1xuICByZXR1cm4gcmVkaXMuY3JlYXRlQ2xpZW50KHJlZGlzVVJMLCByZWRpc09wdGlvbnMpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVTdWJzY3JpYmVyKHsgcmVkaXNVUkwsIHJlZGlzT3B0aW9ucyA9IHt9IH0pOiBhbnkge1xuICByZWRpc09wdGlvbnMubm9fcmVhZHlfY2hlY2sgPSB0cnVlO1xuICByZXR1cm4gcmVkaXMuY3JlYXRlQ2xpZW50KHJlZGlzVVJMLCByZWRpc09wdGlvbnMpO1xufVxuXG5jb25zdCBSZWRpc1B1YlN1YiA9IHtcbiAgY3JlYXRlUHVibGlzaGVyLFxuICBjcmVhdGVTdWJzY3JpYmVyLFxufTtcblxuZXhwb3J0IHsgUmVkaXNQdWJTdWIgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Push/PushAdapter.js b/lib/Adapters/Push/PushAdapter.js new file mode 100644 index 0000000000..494c52bc1f --- /dev/null +++ b/lib/Adapters/Push/PushAdapter.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PushAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ +// Push Adapter +// +// Allows you to change the push notification mechanism. +// +// Adapter classes must implement the following functions: +// * getValidPushTypes() +// * send(devices, installations, pushStatus) +// +// Default is ParsePushAdapter, which uses GCM for +// android push and APNS for ios push. + +/** + * @module Adapters + */ + +/** + * @interface PushAdapter + */ +class PushAdapter { + /** + * @param {any} body + * @param {Parse.Installation[]} installations + * @param {any} pushStatus + * @returns {Promise} + */ + send(body, installations, pushStatus) {} + /** + * Get an array of valid push types. + * @returns {Array} An array of valid push types + */ + + + getValidPushTypes() { + return []; + } + +} + +exports.PushAdapter = PushAdapter; +var _default = PushAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9QdXNoL1B1c2hBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIlB1c2hBZGFwdGVyIiwic2VuZCIsImJvZHkiLCJpbnN0YWxsYXRpb25zIiwicHVzaFN0YXR1cyIsImdldFZhbGlkUHVzaFR5cGVzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUdBOzs7QUFHTyxNQUFNQSxXQUFOLENBQWtCO0FBQ3ZCOzs7Ozs7QUFNQUMsRUFBQUEsSUFBSSxDQUFDQyxJQUFELEVBQVlDLGFBQVosRUFBa0NDLFVBQWxDLEVBQWdFLENBQUU7QUFFdEU7Ozs7OztBQUlBQyxFQUFBQSxpQkFBaUIsR0FBYTtBQUM1QixXQUFPLEVBQVA7QUFDRDs7QUFmc0I7OztlQWtCVkwsVyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG4vKmVzbGludCBuby11bnVzZWQtdmFyczogXCJvZmZcIiovXG4vLyBQdXNoIEFkYXB0ZXJcbi8vXG4vLyBBbGxvd3MgeW91IHRvIGNoYW5nZSB0aGUgcHVzaCBub3RpZmljYXRpb24gbWVjaGFuaXNtLlxuLy9cbi8vIEFkYXB0ZXIgY2xhc3NlcyBtdXN0IGltcGxlbWVudCB0aGUgZm9sbG93aW5nIGZ1bmN0aW9uczpcbi8vICogZ2V0VmFsaWRQdXNoVHlwZXMoKVxuLy8gKiBzZW5kKGRldmljZXMsIGluc3RhbGxhdGlvbnMsIHB1c2hTdGF0dXMpXG4vL1xuLy8gRGVmYXVsdCBpcyBQYXJzZVB1c2hBZGFwdGVyLCB3aGljaCB1c2VzIEdDTSBmb3Jcbi8vIGFuZHJvaWQgcHVzaCBhbmQgQVBOUyBmb3IgaW9zIHB1c2guXG5cbi8qKlxuICogQG1vZHVsZSBBZGFwdGVyc1xuICovXG4vKipcbiAqIEBpbnRlcmZhY2UgUHVzaEFkYXB0ZXJcbiAqL1xuZXhwb3J0IGNsYXNzIFB1c2hBZGFwdGVyIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7YW55fSBib2R5XG4gICAqIEBwYXJhbSB7UGFyc2UuSW5zdGFsbGF0aW9uW119IGluc3RhbGxhdGlvbnNcbiAgICogQHBhcmFtIHthbnl9IHB1c2hTdGF0dXNcbiAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAqL1xuICBzZW5kKGJvZHk6IGFueSwgaW5zdGFsbGF0aW9uczogYW55W10sIHB1c2hTdGF0dXM6IGFueSk6ID9Qcm9taXNlPCo+IHt9XG5cbiAgLyoqXG4gICAqIEdldCBhbiBhcnJheSBvZiB2YWxpZCBwdXNoIHR5cGVzLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IEFuIGFycmF5IG9mIHZhbGlkIHB1c2ggdHlwZXNcbiAgICovXG4gIGdldFZhbGlkUHVzaFR5cGVzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gW107XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVzaEFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoCollection.js b/lib/Adapters/Storage/Mongo/MongoCollection.js new file mode 100644 index 0000000000..fa8c97eac8 --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoCollection.js @@ -0,0 +1,195 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +const mongodb = require('mongodb'); + +const Collection = mongodb.Collection; + +class MongoCollection { + constructor(mongoCollection) { + this._mongoCollection = mongoCollection; + } // Does a find with "smart indexing". + // Currently this just means, if it needs a geoindex and there is + // none, then build the geoindex. + // This could be improved a lot but it's not clear if that's a good + // idea. Or even if this behavior is a good idea. + + + find(query, { + skip, + limit, + sort, + keys, + maxTimeMS, + readPreference + } = {}) { + // Support for Full Text Search - $text + if (keys && keys.$score) { + delete keys.$score; + keys.score = { + $meta: 'textScore' + }; + } + + return this._rawFind(query, { + skip, + limit, + sort, + keys, + maxTimeMS, + readPreference + }).catch(error => { + // Check for "no geoindex" error + if (error.code != 17007 && !error.message.match(/unable to find index for .geoNear/)) { + throw error; + } // Figure out what key needs an index + + + const key = error.message.match(/field=([A-Za-z_0-9]+) /)[1]; + + if (!key) { + throw error; + } + + var index = {}; + index[key] = '2d'; + return this._mongoCollection.createIndex(index) // Retry, but just once. + .then(() => this._rawFind(query, { + skip, + limit, + sort, + keys, + maxTimeMS, + readPreference + })); + }); + } + + _rawFind(query, { + skip, + limit, + sort, + keys, + maxTimeMS, + readPreference + } = {}) { + let findOperation = this._mongoCollection.find(query, { + skip, + limit, + sort, + readPreference + }); + + if (keys) { + findOperation = findOperation.project(keys); + } + + if (maxTimeMS) { + findOperation = findOperation.maxTimeMS(maxTimeMS); + } + + return findOperation.toArray(); + } + + count(query, { + skip, + limit, + sort, + maxTimeMS, + readPreference + } = {}) { + // If query is empty, then use estimatedDocumentCount instead. + // This is due to countDocuments performing a scan, + // which greatly increases execution time when being run on large collections. + // See https://github.com/Automattic/mongoose/issues/6713 for more info regarding this problem. + if (typeof query !== 'object' || !Object.keys(query).length) { + return this._mongoCollection.estimatedDocumentCount({ + maxTimeMS + }); + } + + const countOperation = this._mongoCollection.countDocuments(query, { + skip, + limit, + sort, + maxTimeMS, + readPreference + }); + + return countOperation; + } + + distinct(field, query) { + return this._mongoCollection.distinct(field, query); + } + + aggregate(pipeline, { + maxTimeMS, + readPreference + } = {}) { + return this._mongoCollection.aggregate(pipeline, { + maxTimeMS, + readPreference + }).toArray(); + } + + insertOne(object, session) { + return this._mongoCollection.insertOne(object, { + session + }); + } // Atomically updates data in the database for a single (first) object that matched the query + // If there is nothing that matches the query - does insert + // Postgres Note: `INSERT ... ON CONFLICT UPDATE` that is available since 9.5. + + + upsertOne(query, update, session) { + return this._mongoCollection.updateOne(query, update, { + upsert: true, + session + }); + } + + updateOne(query, update) { + return this._mongoCollection.updateOne(query, update); + } + + updateMany(query, update, session) { + return this._mongoCollection.updateMany(query, update, { + session + }); + } + + deleteMany(query, session) { + return this._mongoCollection.deleteMany(query, { + session + }); + } + + _ensureSparseUniqueIndexInBackground(indexRequest) { + return new Promise((resolve, reject) => { + this._mongoCollection.createIndex(indexRequest, { + unique: true, + background: true, + sparse: true + }, error => { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); + } + + drop() { + return this._mongoCollection.drop(); + } + +} + +exports.default = MongoCollection; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJtb25nb2RiIiwicmVxdWlyZSIsIkNvbGxlY3Rpb24iLCJNb25nb0NvbGxlY3Rpb24iLCJjb25zdHJ1Y3RvciIsIm1vbmdvQ29sbGVjdGlvbiIsIl9tb25nb0NvbGxlY3Rpb24iLCJmaW5kIiwicXVlcnkiLCJza2lwIiwibGltaXQiLCJzb3J0Iiwia2V5cyIsIm1heFRpbWVNUyIsInJlYWRQcmVmZXJlbmNlIiwiJHNjb3JlIiwic2NvcmUiLCIkbWV0YSIsIl9yYXdGaW5kIiwiY2F0Y2giLCJlcnJvciIsImNvZGUiLCJtZXNzYWdlIiwibWF0Y2giLCJrZXkiLCJpbmRleCIsImNyZWF0ZUluZGV4IiwidGhlbiIsImZpbmRPcGVyYXRpb24iLCJwcm9qZWN0IiwidG9BcnJheSIsImNvdW50IiwiT2JqZWN0IiwibGVuZ3RoIiwiZXN0aW1hdGVkRG9jdW1lbnRDb3VudCIsImNvdW50T3BlcmF0aW9uIiwiY291bnREb2N1bWVudHMiLCJkaXN0aW5jdCIsImZpZWxkIiwiYWdncmVnYXRlIiwicGlwZWxpbmUiLCJpbnNlcnRPbmUiLCJvYmplY3QiLCJzZXNzaW9uIiwidXBzZXJ0T25lIiwidXBkYXRlIiwidXBkYXRlT25lIiwidXBzZXJ0IiwidXBkYXRlTWFueSIsImRlbGV0ZU1hbnkiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJpbmRleFJlcXVlc3QiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsInVuaXF1ZSIsImJhY2tncm91bmQiLCJzcGFyc2UiLCJkcm9wIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUEsTUFBTUEsT0FBTyxHQUFHQyxPQUFPLENBQUMsU0FBRCxDQUF2Qjs7QUFDQSxNQUFNQyxVQUFVLEdBQUdGLE9BQU8sQ0FBQ0UsVUFBM0I7O0FBRWUsTUFBTUMsZUFBTixDQUFzQjtBQUduQ0MsRUFBQUEsV0FBVyxDQUFDQyxlQUFELEVBQThCO0FBQ3ZDLFNBQUtDLGdCQUFMLEdBQXdCRCxlQUF4QjtBQUNELEdBTGtDLENBT25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBRSxFQUFBQSxJQUFJLENBQUNDLEtBQUQsRUFBUTtBQUFFQyxJQUFBQSxJQUFGO0FBQVFDLElBQUFBLEtBQVI7QUFBZUMsSUFBQUEsSUFBZjtBQUFxQkMsSUFBQUEsSUFBckI7QUFBMkJDLElBQUFBLFNBQTNCO0FBQXNDQyxJQUFBQTtBQUF0QyxNQUF5RCxFQUFqRSxFQUFxRTtBQUN2RTtBQUNBLFFBQUlGLElBQUksSUFBSUEsSUFBSSxDQUFDRyxNQUFqQixFQUF5QjtBQUN2QixhQUFPSCxJQUFJLENBQUNHLE1BQVo7QUFDQUgsTUFBQUEsSUFBSSxDQUFDSSxLQUFMLEdBQWE7QUFBRUMsUUFBQUEsS0FBSyxFQUFFO0FBQVQsT0FBYjtBQUNEOztBQUNELFdBQU8sS0FBS0MsUUFBTCxDQUFjVixLQUFkLEVBQXFCO0FBQzFCQyxNQUFBQSxJQUQwQjtBQUUxQkMsTUFBQUEsS0FGMEI7QUFHMUJDLE1BQUFBLElBSDBCO0FBSTFCQyxNQUFBQSxJQUowQjtBQUsxQkMsTUFBQUEsU0FMMEI7QUFNMUJDLE1BQUFBO0FBTjBCLEtBQXJCLEVBT0pLLEtBUEksQ0FPRUMsS0FBSyxJQUFJO0FBQ2hCO0FBQ0EsVUFDRUEsS0FBSyxDQUFDQyxJQUFOLElBQWMsS0FBZCxJQUNBLENBQUNELEtBQUssQ0FBQ0UsT0FBTixDQUFjQyxLQUFkLENBQW9CLG1DQUFwQixDQUZILEVBR0U7QUFDQSxjQUFNSCxLQUFOO0FBQ0QsT0FQZSxDQVFoQjs7O0FBQ0EsWUFBTUksR0FBRyxHQUFHSixLQUFLLENBQUNFLE9BQU4sQ0FBY0MsS0FBZCxDQUFvQix3QkFBcEIsRUFBOEMsQ0FBOUMsQ0FBWjs7QUFDQSxVQUFJLENBQUNDLEdBQUwsRUFBVTtBQUNSLGNBQU1KLEtBQU47QUFDRDs7QUFFRCxVQUFJSyxLQUFLLEdBQUcsRUFBWjtBQUNBQSxNQUFBQSxLQUFLLENBQUNELEdBQUQsQ0FBTCxHQUFhLElBQWI7QUFDQSxhQUNFLEtBQUtsQixnQkFBTCxDQUNHb0IsV0FESCxDQUNlRCxLQURmLEVBRUU7QUFGRixPQUdHRSxJQUhILENBR1EsTUFDSixLQUFLVCxRQUFMLENBQWNWLEtBQWQsRUFBcUI7QUFDbkJDLFFBQUFBLElBRG1CO0FBRW5CQyxRQUFBQSxLQUZtQjtBQUduQkMsUUFBQUEsSUFIbUI7QUFJbkJDLFFBQUFBLElBSm1CO0FBS25CQyxRQUFBQSxTQUxtQjtBQU1uQkMsUUFBQUE7QUFObUIsT0FBckIsQ0FKSixDQURGO0FBZUQsS0F0Q00sQ0FBUDtBQXVDRDs7QUFFREksRUFBQUEsUUFBUSxDQUFDVixLQUFELEVBQVE7QUFBRUMsSUFBQUEsSUFBRjtBQUFRQyxJQUFBQSxLQUFSO0FBQWVDLElBQUFBLElBQWY7QUFBcUJDLElBQUFBLElBQXJCO0FBQTJCQyxJQUFBQSxTQUEzQjtBQUFzQ0MsSUFBQUE7QUFBdEMsTUFBeUQsRUFBakUsRUFBcUU7QUFDM0UsUUFBSWMsYUFBYSxHQUFHLEtBQUt0QixnQkFBTCxDQUFzQkMsSUFBdEIsQ0FBMkJDLEtBQTNCLEVBQWtDO0FBQ3BEQyxNQUFBQSxJQURvRDtBQUVwREMsTUFBQUEsS0FGb0Q7QUFHcERDLE1BQUFBLElBSG9EO0FBSXBERyxNQUFBQTtBQUpvRCxLQUFsQyxDQUFwQjs7QUFPQSxRQUFJRixJQUFKLEVBQVU7QUFDUmdCLE1BQUFBLGFBQWEsR0FBR0EsYUFBYSxDQUFDQyxPQUFkLENBQXNCakIsSUFBdEIsQ0FBaEI7QUFDRDs7QUFFRCxRQUFJQyxTQUFKLEVBQWU7QUFDYmUsTUFBQUEsYUFBYSxHQUFHQSxhQUFhLENBQUNmLFNBQWQsQ0FBd0JBLFNBQXhCLENBQWhCO0FBQ0Q7O0FBRUQsV0FBT2UsYUFBYSxDQUFDRSxPQUFkLEVBQVA7QUFDRDs7QUFFREMsRUFBQUEsS0FBSyxDQUFDdkIsS0FBRCxFQUFRO0FBQUVDLElBQUFBLElBQUY7QUFBUUMsSUFBQUEsS0FBUjtBQUFlQyxJQUFBQSxJQUFmO0FBQXFCRSxJQUFBQSxTQUFyQjtBQUFnQ0MsSUFBQUE7QUFBaEMsTUFBbUQsRUFBM0QsRUFBK0Q7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFJLE9BQU9OLEtBQVAsS0FBaUIsUUFBakIsSUFBNkIsQ0FBQ3dCLE1BQU0sQ0FBQ3BCLElBQVAsQ0FBWUosS0FBWixFQUFtQnlCLE1BQXJELEVBQTZEO0FBQzNELGFBQU8sS0FBSzNCLGdCQUFMLENBQXNCNEIsc0JBQXRCLENBQTZDO0FBQ2xEckIsUUFBQUE7QUFEa0QsT0FBN0MsQ0FBUDtBQUdEOztBQUVELFVBQU1zQixjQUFjLEdBQUcsS0FBSzdCLGdCQUFMLENBQXNCOEIsY0FBdEIsQ0FBcUM1QixLQUFyQyxFQUE0QztBQUNqRUMsTUFBQUEsSUFEaUU7QUFFakVDLE1BQUFBLEtBRmlFO0FBR2pFQyxNQUFBQSxJQUhpRTtBQUlqRUUsTUFBQUEsU0FKaUU7QUFLakVDLE1BQUFBO0FBTGlFLEtBQTVDLENBQXZCOztBQVFBLFdBQU9xQixjQUFQO0FBQ0Q7O0FBRURFLEVBQUFBLFFBQVEsQ0FBQ0MsS0FBRCxFQUFROUIsS0FBUixFQUFlO0FBQ3JCLFdBQU8sS0FBS0YsZ0JBQUwsQ0FBc0IrQixRQUF0QixDQUErQkMsS0FBL0IsRUFBc0M5QixLQUF0QyxDQUFQO0FBQ0Q7O0FBRUQrQixFQUFBQSxTQUFTLENBQUNDLFFBQUQsRUFBVztBQUFFM0IsSUFBQUEsU0FBRjtBQUFhQyxJQUFBQTtBQUFiLE1BQWdDLEVBQTNDLEVBQStDO0FBQ3RELFdBQU8sS0FBS1IsZ0JBQUwsQ0FDSmlDLFNBREksQ0FDTUMsUUFETixFQUNnQjtBQUFFM0IsTUFBQUEsU0FBRjtBQUFhQyxNQUFBQTtBQUFiLEtBRGhCLEVBRUpnQixPQUZJLEVBQVA7QUFHRDs7QUFFRFcsRUFBQUEsU0FBUyxDQUFDQyxNQUFELEVBQVNDLE9BQVQsRUFBa0I7QUFDekIsV0FBTyxLQUFLckMsZ0JBQUwsQ0FBc0JtQyxTQUF0QixDQUFnQ0MsTUFBaEMsRUFBd0M7QUFBRUMsTUFBQUE7QUFBRixLQUF4QyxDQUFQO0FBQ0QsR0FoSGtDLENBa0huQztBQUNBO0FBQ0E7OztBQUNBQyxFQUFBQSxTQUFTLENBQUNwQyxLQUFELEVBQVFxQyxNQUFSLEVBQWdCRixPQUFoQixFQUF5QjtBQUNoQyxXQUFPLEtBQUtyQyxnQkFBTCxDQUFzQndDLFNBQXRCLENBQWdDdEMsS0FBaEMsRUFBdUNxQyxNQUF2QyxFQUErQztBQUNwREUsTUFBQUEsTUFBTSxFQUFFLElBRDRDO0FBRXBESixNQUFBQTtBQUZvRCxLQUEvQyxDQUFQO0FBSUQ7O0FBRURHLEVBQUFBLFNBQVMsQ0FBQ3RDLEtBQUQsRUFBUXFDLE1BQVIsRUFBZ0I7QUFDdkIsV0FBTyxLQUFLdkMsZ0JBQUwsQ0FBc0J3QyxTQUF0QixDQUFnQ3RDLEtBQWhDLEVBQXVDcUMsTUFBdkMsQ0FBUDtBQUNEOztBQUVERyxFQUFBQSxVQUFVLENBQUN4QyxLQUFELEVBQVFxQyxNQUFSLEVBQWdCRixPQUFoQixFQUF5QjtBQUNqQyxXQUFPLEtBQUtyQyxnQkFBTCxDQUFzQjBDLFVBQXRCLENBQWlDeEMsS0FBakMsRUFBd0NxQyxNQUF4QyxFQUFnRDtBQUFFRixNQUFBQTtBQUFGLEtBQWhELENBQVA7QUFDRDs7QUFFRE0sRUFBQUEsVUFBVSxDQUFDekMsS0FBRCxFQUFRbUMsT0FBUixFQUFpQjtBQUN6QixXQUFPLEtBQUtyQyxnQkFBTCxDQUFzQjJDLFVBQXRCLENBQWlDekMsS0FBakMsRUFBd0M7QUFBRW1DLE1BQUFBO0FBQUYsS0FBeEMsQ0FBUDtBQUNEOztBQUVETyxFQUFBQSxvQ0FBb0MsQ0FBQ0MsWUFBRCxFQUFlO0FBQ2pELFdBQU8sSUFBSUMsT0FBSixDQUFZLENBQUNDLE9BQUQsRUFBVUMsTUFBVixLQUFxQjtBQUN0QyxXQUFLaEQsZ0JBQUwsQ0FBc0JvQixXQUF0QixDQUNFeUIsWUFERixFQUVFO0FBQUVJLFFBQUFBLE1BQU0sRUFBRSxJQUFWO0FBQWdCQyxRQUFBQSxVQUFVLEVBQUUsSUFBNUI7QUFBa0NDLFFBQUFBLE1BQU0sRUFBRTtBQUExQyxPQUZGLEVBR0VyQyxLQUFLLElBQUk7QUFDUCxZQUFJQSxLQUFKLEVBQVc7QUFDVGtDLFVBQUFBLE1BQU0sQ0FBQ2xDLEtBQUQsQ0FBTjtBQUNELFNBRkQsTUFFTztBQUNMaUMsVUFBQUEsT0FBTztBQUNSO0FBQ0YsT0FUSDtBQVdELEtBWk0sQ0FBUDtBQWFEOztBQUVESyxFQUFBQSxJQUFJLEdBQUc7QUFDTCxXQUFPLEtBQUtwRCxnQkFBTCxDQUFzQm9ELElBQXRCLEVBQVA7QUFDRDs7QUExSmtDIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgbW9uZ29kYiA9IHJlcXVpcmUoJ21vbmdvZGInKTtcbmNvbnN0IENvbGxlY3Rpb24gPSBtb25nb2RiLkNvbGxlY3Rpb247XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1vbmdvQ29sbGVjdGlvbiB7XG4gIF9tb25nb0NvbGxlY3Rpb246IENvbGxlY3Rpb247XG5cbiAgY29uc3RydWN0b3IobW9uZ29Db2xsZWN0aW9uOiBDb2xsZWN0aW9uKSB7XG4gICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uID0gbW9uZ29Db2xsZWN0aW9uO1xuICB9XG5cbiAgLy8gRG9lcyBhIGZpbmQgd2l0aCBcInNtYXJ0IGluZGV4aW5nXCIuXG4gIC8vIEN1cnJlbnRseSB0aGlzIGp1c3QgbWVhbnMsIGlmIGl0IG5lZWRzIGEgZ2VvaW5kZXggYW5kIHRoZXJlIGlzXG4gIC8vIG5vbmUsIHRoZW4gYnVpbGQgdGhlIGdlb2luZGV4LlxuICAvLyBUaGlzIGNvdWxkIGJlIGltcHJvdmVkIGEgbG90IGJ1dCBpdCdzIG5vdCBjbGVhciBpZiB0aGF0J3MgYSBnb29kXG4gIC8vIGlkZWEuIE9yIGV2ZW4gaWYgdGhpcyBiZWhhdmlvciBpcyBhIGdvb2QgaWRlYS5cbiAgZmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICAvLyBTdXBwb3J0IGZvciBGdWxsIFRleHQgU2VhcmNoIC0gJHRleHRcbiAgICBpZiAoa2V5cyAmJiBrZXlzLiRzY29yZSkge1xuICAgICAgZGVsZXRlIGtleXMuJHNjb3JlO1xuICAgICAga2V5cy5zY29yZSA9IHsgJG1ldGE6ICd0ZXh0U2NvcmUnIH07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9yYXdGaW5kKHF1ZXJ5LCB7XG4gICAgICBza2lwLFxuICAgICAgbGltaXQsXG4gICAgICBzb3J0LFxuICAgICAga2V5cyxcbiAgICAgIG1heFRpbWVNUyxcbiAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIC8vIENoZWNrIGZvciBcIm5vIGdlb2luZGV4XCIgZXJyb3JcbiAgICAgIGlmIChcbiAgICAgICAgZXJyb3IuY29kZSAhPSAxNzAwNyAmJlxuICAgICAgICAhZXJyb3IubWVzc2FnZS5tYXRjaCgvdW5hYmxlIHRvIGZpbmQgaW5kZXggZm9yIC5nZW9OZWFyLylcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIC8vIEZpZ3VyZSBvdXQgd2hhdCBrZXkgbmVlZHMgYW4gaW5kZXhcbiAgICAgIGNvbnN0IGtleSA9IGVycm9yLm1lc3NhZ2UubWF0Y2goL2ZpZWxkPShbQS1aYS16XzAtOV0rKSAvKVsxXTtcbiAgICAgIGlmICgha2V5KSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuXG4gICAgICB2YXIgaW5kZXggPSB7fTtcbiAgICAgIGluZGV4W2tleV0gPSAnMmQnO1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uXG4gICAgICAgICAgLmNyZWF0ZUluZGV4KGluZGV4KVxuICAgICAgICAgIC8vIFJldHJ5LCBidXQganVzdCBvbmNlLlxuICAgICAgICAgIC50aGVuKCgpID0+XG4gICAgICAgICAgICB0aGlzLl9yYXdGaW5kKHF1ZXJ5LCB7XG4gICAgICAgICAgICAgIHNraXAsXG4gICAgICAgICAgICAgIGxpbWl0LFxuICAgICAgICAgICAgICBzb3J0LFxuICAgICAgICAgICAgICBrZXlzLFxuICAgICAgICAgICAgICBtYXhUaW1lTVMsXG4gICAgICAgICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgX3Jhd0ZpbmQocXVlcnksIHsgc2tpcCwgbGltaXQsIHNvcnQsIGtleXMsIG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSA9IHt9KSB7XG4gICAgbGV0IGZpbmRPcGVyYXRpb24gPSB0aGlzLl9tb25nb0NvbGxlY3Rpb24uZmluZChxdWVyeSwge1xuICAgICAgc2tpcCxcbiAgICAgIGxpbWl0LFxuICAgICAgc29ydCxcbiAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgIH0pO1xuXG4gICAgaWYgKGtleXMpIHtcbiAgICAgIGZpbmRPcGVyYXRpb24gPSBmaW5kT3BlcmF0aW9uLnByb2plY3Qoa2V5cyk7XG4gICAgfVxuXG4gICAgaWYgKG1heFRpbWVNUykge1xuICAgICAgZmluZE9wZXJhdGlvbiA9IGZpbmRPcGVyYXRpb24ubWF4VGltZU1TKG1heFRpbWVNUyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbmRPcGVyYXRpb24udG9BcnJheSgpO1xuICB9XG5cbiAgY291bnQocXVlcnksIHsgc2tpcCwgbGltaXQsIHNvcnQsIG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSA9IHt9KSB7XG4gICAgLy8gSWYgcXVlcnkgaXMgZW1wdHksIHRoZW4gdXNlIGVzdGltYXRlZERvY3VtZW50Q291bnQgaW5zdGVhZC5cbiAgICAvLyBUaGlzIGlzIGR1ZSB0byBjb3VudERvY3VtZW50cyBwZXJmb3JtaW5nIGEgc2NhbixcbiAgICAvLyB3aGljaCBncmVhdGx5IGluY3JlYXNlcyBleGVjdXRpb24gdGltZSB3aGVuIGJlaW5nIHJ1biBvbiBsYXJnZSBjb2xsZWN0aW9ucy5cbiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL0F1dG9tYXR0aWMvbW9uZ29vc2UvaXNzdWVzLzY3MTMgZm9yIG1vcmUgaW5mbyByZWdhcmRpbmcgdGhpcyBwcm9ibGVtLlxuICAgIGlmICh0eXBlb2YgcXVlcnkgIT09ICdvYmplY3QnIHx8ICFPYmplY3Qua2V5cyhxdWVyeSkubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmVzdGltYXRlZERvY3VtZW50Q291bnQoe1xuICAgICAgICBtYXhUaW1lTVMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb3VudE9wZXJhdGlvbiA9IHRoaXMuX21vbmdvQ29sbGVjdGlvbi5jb3VudERvY3VtZW50cyhxdWVyeSwge1xuICAgICAgc2tpcCxcbiAgICAgIGxpbWl0LFxuICAgICAgc29ydCxcbiAgICAgIG1heFRpbWVNUyxcbiAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvdW50T3BlcmF0aW9uO1xuICB9XG5cbiAgZGlzdGluY3QoZmllbGQsIHF1ZXJ5KSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5kaXN0aW5jdChmaWVsZCwgcXVlcnkpO1xuICB9XG5cbiAgYWdncmVnYXRlKHBpcGVsaW5lLCB7IG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvblxuICAgICAgLmFnZ3JlZ2F0ZShwaXBlbGluZSwgeyBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0pXG4gICAgICAudG9BcnJheSgpO1xuICB9XG5cbiAgaW5zZXJ0T25lKG9iamVjdCwgc2Vzc2lvbikge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uaW5zZXJ0T25lKG9iamVjdCwgeyBzZXNzaW9uIH0pO1xuICB9XG5cbiAgLy8gQXRvbWljYWxseSB1cGRhdGVzIGRhdGEgaW4gdGhlIGRhdGFiYXNlIGZvciBhIHNpbmdsZSAoZmlyc3QpIG9iamVjdCB0aGF0IG1hdGNoZWQgdGhlIHF1ZXJ5XG4gIC8vIElmIHRoZXJlIGlzIG5vdGhpbmcgdGhhdCBtYXRjaGVzIHRoZSBxdWVyeSAtIGRvZXMgaW5zZXJ0XG4gIC8vIFBvc3RncmVzIE5vdGU6IGBJTlNFUlQgLi4uIE9OIENPTkZMSUNUIFVQREFURWAgdGhhdCBpcyBhdmFpbGFibGUgc2luY2UgOS41LlxuICB1cHNlcnRPbmUocXVlcnksIHVwZGF0ZSwgc2Vzc2lvbikge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24udXBkYXRlT25lKHF1ZXJ5LCB1cGRhdGUsIHtcbiAgICAgIHVwc2VydDogdHJ1ZSxcbiAgICAgIHNlc3Npb24sXG4gICAgfSk7XG4gIH1cblxuICB1cGRhdGVPbmUocXVlcnksIHVwZGF0ZSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24udXBkYXRlT25lKHF1ZXJ5LCB1cGRhdGUpO1xuICB9XG5cbiAgdXBkYXRlTWFueShxdWVyeSwgdXBkYXRlLCBzZXNzaW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi51cGRhdGVNYW55KHF1ZXJ5LCB1cGRhdGUsIHsgc2Vzc2lvbiB9KTtcbiAgfVxuXG4gIGRlbGV0ZU1hbnkocXVlcnksIHNlc3Npb24pIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmRlbGV0ZU1hbnkocXVlcnksIHsgc2Vzc2lvbiB9KTtcbiAgfVxuXG4gIF9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZChpbmRleFJlcXVlc3QpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4KFxuICAgICAgICBpbmRleFJlcXVlc3QsXG4gICAgICAgIHsgdW5pcXVlOiB0cnVlLCBiYWNrZ3JvdW5kOiB0cnVlLCBzcGFyc2U6IHRydWUgfSxcbiAgICAgICAgZXJyb3IgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIGRyb3AoKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5kcm9wKCk7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js b/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js new file mode 100644 index 0000000000..8220f28a5f --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js @@ -0,0 +1,365 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _MongoCollection = _interopRequireDefault(require("./MongoCollection")); + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function mongoFieldToParseSchemaField(type) { + if (type[0] === '*') { + return { + type: 'Pointer', + targetClass: type.slice(1) + }; + } + + if (type.startsWith('relation<')) { + return { + type: 'Relation', + targetClass: type.slice('relation<'.length, type.length - 1) + }; + } + + switch (type) { + case 'number': + return { + type: 'Number' + }; + + case 'string': + return { + type: 'String' + }; + + case 'boolean': + return { + type: 'Boolean' + }; + + case 'date': + return { + type: 'Date' + }; + + case 'map': + case 'object': + return { + type: 'Object' + }; + + case 'array': + return { + type: 'Array' + }; + + case 'geopoint': + return { + type: 'GeoPoint' + }; + + case 'file': + return { + type: 'File' + }; + + case 'bytes': + return { + type: 'Bytes' + }; + + case 'polygon': + return { + type: 'Polygon' + }; + } +} + +const nonFieldSchemaKeys = ['_id', '_metadata', '_client_permissions']; + +function mongoSchemaFieldsToParseSchemaFields(schema) { + var fieldNames = Object.keys(schema).filter(key => nonFieldSchemaKeys.indexOf(key) === -1); + var response = fieldNames.reduce((obj, fieldName) => { + obj[fieldName] = mongoFieldToParseSchemaField(schema[fieldName]); + + if (schema._metadata && schema._metadata.fields_options && schema._metadata.fields_options[fieldName]) { + obj[fieldName] = Object.assign({}, obj[fieldName], schema._metadata.fields_options[fieldName]); + } + + return obj; + }, {}); + response.ACL = { + type: 'ACL' + }; + response.createdAt = { + type: 'Date' + }; + response.updatedAt = { + type: 'Date' + }; + response.objectId = { + type: 'String' + }; + return response; +} + +const emptyCLPS = Object.freeze({ + find: {}, + count: {}, + get: {}, + create: {}, + update: {}, + delete: {}, + addField: {}, + protectedFields: {} +}); +const defaultCLPS = Object.freeze({ + find: { + '*': true + }, + count: { + '*': true + }, + get: { + '*': true + }, + create: { + '*': true + }, + update: { + '*': true + }, + delete: { + '*': true + }, + addField: { + '*': true + }, + protectedFields: { + '*': [] + } +}); + +function mongoSchemaToParseSchema(mongoSchema) { + let clps = defaultCLPS; + let indexes = {}; + + if (mongoSchema._metadata) { + if (mongoSchema._metadata.class_permissions) { + clps = _objectSpread({}, emptyCLPS, {}, mongoSchema._metadata.class_permissions); + } + + if (mongoSchema._metadata.indexes) { + indexes = _objectSpread({}, mongoSchema._metadata.indexes); + } + } + + return { + className: mongoSchema._id, + fields: mongoSchemaFieldsToParseSchemaFields(mongoSchema), + classLevelPermissions: clps, + indexes: indexes + }; +} + +function _mongoSchemaQueryFromNameQuery(name, query) { + const object = { + _id: name + }; + + if (query) { + Object.keys(query).forEach(key => { + object[key] = query[key]; + }); + } + + return object; +} // Returns a type suitable for inserting into mongo _SCHEMA collection. +// Does no validation. That is expected to be done in Parse Server. + + +function parseFieldTypeToMongoFieldType({ + type, + targetClass +}) { + switch (type) { + case 'Pointer': + return `*${targetClass}`; + + case 'Relation': + return `relation<${targetClass}>`; + + case 'Number': + return 'number'; + + case 'String': + return 'string'; + + case 'Boolean': + return 'boolean'; + + case 'Date': + return 'date'; + + case 'Object': + return 'object'; + + case 'Array': + return 'array'; + + case 'GeoPoint': + return 'geopoint'; + + case 'File': + return 'file'; + + case 'Bytes': + return 'bytes'; + + case 'Polygon': + return 'polygon'; + } +} + +class MongoSchemaCollection { + constructor(collection) { + this._collection = collection; + } + + _fetchAllSchemasFrom_SCHEMA() { + return this._collection._rawFind({}).then(schemas => schemas.map(mongoSchemaToParseSchema)); + } + + _fetchOneSchemaFrom_SCHEMA(name) { + return this._collection._rawFind(_mongoSchemaQueryFromNameQuery(name), { + limit: 1 + }).then(results => { + if (results.length === 1) { + return mongoSchemaToParseSchema(results[0]); + } else { + throw undefined; + } + }); + } // Atomically find and delete an object based on query. + + + findAndDeleteSchema(name) { + return this._collection._mongoCollection.findAndRemove(_mongoSchemaQueryFromNameQuery(name), []); + } + + insertSchema(schema) { + return this._collection.insertOne(schema).then(result => mongoSchemaToParseSchema(result.ops[0])).catch(error => { + if (error.code === 11000) { + //Mongo's duplicate key error + throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'Class already exists.'); + } else { + throw error; + } + }); + } + + updateSchema(name, update) { + return this._collection.updateOne(_mongoSchemaQueryFromNameQuery(name), update); + } + + upsertSchema(name, query, update) { + return this._collection.upsertOne(_mongoSchemaQueryFromNameQuery(name, query), update); + } // Add a field to the schema. If database does not support the field + // type (e.g. mongo doesn't support more than one GeoPoint in a class) reject with an "Incorrect Type" + // Parse error with a desciptive message. If the field already exists, this function must + // not modify the schema, and must reject with DUPLICATE_VALUE error. + // If this is called for a class that doesn't exist, this function must create that class. + // TODO: throw an error if an unsupported field type is passed. Deciding whether a type is supported + // should be the job of the adapter. Some adapters may not support GeoPoint at all. Others may + // Support additional types that Mongo doesn't, like Money, or something. + // TODO: don't spend an extra query on finding the schema if the type we are trying to add isn't a GeoPoint. + + + addFieldIfNotExists(className, fieldName, fieldType) { + return this._fetchOneSchemaFrom_SCHEMA(className).then(schema => { + // If a field with this name already exists, it will be handled elsewhere. + if (schema.fields[fieldName] != undefined) { + return; + } // The schema exists. Check for existing GeoPoints. + + + if (fieldType.type === 'GeoPoint') { + // Make sure there are not other geopoint fields + if (Object.keys(schema.fields).some(existingField => schema.fields[existingField].type === 'GeoPoint')) { + throw new _node.default.Error(_node.default.Error.INCORRECT_TYPE, 'MongoDB only supports one GeoPoint field in a class.'); + } + } + + return; + }, error => { + // If error is undefined, the schema doesn't exist, and we can create the schema with the field. + // If some other error, reject with it. + if (error === undefined) { + return; + } + + throw error; + }).then(() => { + const { + type, + targetClass + } = fieldType, + fieldOptions = _objectWithoutProperties(fieldType, ["type", "targetClass"]); // We use $exists and $set to avoid overwriting the field type if it + // already exists. (it could have added inbetween the last query and the update) + + + if (fieldOptions && Object.keys(fieldOptions).length > 0) { + return this.upsertSchema(className, { + [fieldName]: { + $exists: false + } + }, { + $set: { + [fieldName]: parseFieldTypeToMongoFieldType({ + type, + targetClass + }), + [`_metadata.fields_options.${fieldName}`]: fieldOptions + } + }); + } else { + return this.upsertSchema(className, { + [fieldName]: { + $exists: false + } + }, { + $set: { + [fieldName]: parseFieldTypeToMongoFieldType({ + type, + targetClass + }) + } + }); + } + }); + } + +} // Exported for testing reasons and because we haven't moved all mongo schema format +// related logic into the database adapter yet. + + +MongoSchemaCollection._TESTmongoSchemaToParseSchema = mongoSchemaToParseSchema; +MongoSchemaCollection.parseFieldTypeToMongoFieldType = parseFieldTypeToMongoFieldType; +var _default = MongoSchemaCollection; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU2NoZW1hQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJtb25nb0ZpZWxkVG9QYXJzZVNjaGVtYUZpZWxkIiwidHlwZSIsInRhcmdldENsYXNzIiwic2xpY2UiLCJzdGFydHNXaXRoIiwibGVuZ3RoIiwibm9uRmllbGRTY2hlbWFLZXlzIiwibW9uZ29TY2hlbWFGaWVsZHNUb1BhcnNlU2NoZW1hRmllbGRzIiwic2NoZW1hIiwiZmllbGROYW1lcyIsIk9iamVjdCIsImtleXMiLCJmaWx0ZXIiLCJrZXkiLCJpbmRleE9mIiwicmVzcG9uc2UiLCJyZWR1Y2UiLCJvYmoiLCJmaWVsZE5hbWUiLCJfbWV0YWRhdGEiLCJmaWVsZHNfb3B0aW9ucyIsImFzc2lnbiIsIkFDTCIsImNyZWF0ZWRBdCIsInVwZGF0ZWRBdCIsIm9iamVjdElkIiwiZW1wdHlDTFBTIiwiZnJlZXplIiwiZmluZCIsImNvdW50IiwiZ2V0IiwiY3JlYXRlIiwidXBkYXRlIiwiZGVsZXRlIiwiYWRkRmllbGQiLCJwcm90ZWN0ZWRGaWVsZHMiLCJkZWZhdWx0Q0xQUyIsIm1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYSIsIm1vbmdvU2NoZW1hIiwiY2xwcyIsImluZGV4ZXMiLCJjbGFzc19wZXJtaXNzaW9ucyIsImNsYXNzTmFtZSIsIl9pZCIsImZpZWxkcyIsImNsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsIl9tb25nb1NjaGVtYVF1ZXJ5RnJvbU5hbWVRdWVyeSIsIm5hbWUiLCJxdWVyeSIsIm9iamVjdCIsImZvckVhY2giLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJjb25zdHJ1Y3RvciIsImNvbGxlY3Rpb24iLCJfY29sbGVjdGlvbiIsIl9mZXRjaEFsbFNjaGVtYXNGcm9tX1NDSEVNQSIsIl9yYXdGaW5kIiwidGhlbiIsInNjaGVtYXMiLCJtYXAiLCJfZmV0Y2hPbmVTY2hlbWFGcm9tX1NDSEVNQSIsImxpbWl0IiwicmVzdWx0cyIsInVuZGVmaW5lZCIsImZpbmRBbmREZWxldGVTY2hlbWEiLCJfbW9uZ29Db2xsZWN0aW9uIiwiZmluZEFuZFJlbW92ZSIsImluc2VydFNjaGVtYSIsImluc2VydE9uZSIsInJlc3VsdCIsIm9wcyIsImNhdGNoIiwiZXJyb3IiLCJjb2RlIiwiUGFyc2UiLCJFcnJvciIsIkRVUExJQ0FURV9WQUxVRSIsInVwZGF0ZVNjaGVtYSIsInVwZGF0ZU9uZSIsInVwc2VydFNjaGVtYSIsInVwc2VydE9uZSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJmaWVsZFR5cGUiLCJzb21lIiwiZXhpc3RpbmdGaWVsZCIsIklOQ09SUkVDVF9UWVBFIiwiZmllbGRPcHRpb25zIiwiJGV4aXN0cyIsIiRzZXQiLCJfVEVTVG1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7Ozs7Ozs7Ozs7OztBQUVBLFNBQVNBLDRCQUFULENBQXNDQyxJQUF0QyxFQUE0QztBQUMxQyxNQUFJQSxJQUFJLENBQUMsQ0FBRCxDQUFKLEtBQVksR0FBaEIsRUFBcUI7QUFDbkIsV0FBTztBQUNMQSxNQUFBQSxJQUFJLEVBQUUsU0FERDtBQUVMQyxNQUFBQSxXQUFXLEVBQUVELElBQUksQ0FBQ0UsS0FBTCxDQUFXLENBQVg7QUFGUixLQUFQO0FBSUQ7O0FBQ0QsTUFBSUYsSUFBSSxDQUFDRyxVQUFMLENBQWdCLFdBQWhCLENBQUosRUFBa0M7QUFDaEMsV0FBTztBQUNMSCxNQUFBQSxJQUFJLEVBQUUsVUFERDtBQUVMQyxNQUFBQSxXQUFXLEVBQUVELElBQUksQ0FBQ0UsS0FBTCxDQUFXLFlBQVlFLE1BQXZCLEVBQStCSixJQUFJLENBQUNJLE1BQUwsR0FBYyxDQUE3QztBQUZSLEtBQVA7QUFJRDs7QUFDRCxVQUFRSixJQUFSO0FBQ0UsU0FBSyxRQUFMO0FBQ0UsYUFBTztBQUFFQSxRQUFBQSxJQUFJLEVBQUU7QUFBUixPQUFQOztB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Qyw4QkFBOEIsQ0FBQztBQUMxQ2xELGNBQUFBLElBRDBDO0FBRTFDQyxjQUFBQTtBQUYwQyxhQUFEO0FBRHZDO0FBRFIsU0FISyxDQUFQO0FBWUQ7QUFDRixLQWpFSSxDQUFQO0FBa0VEOztBQTlJeUIsQyxDQWlKNUI7QUFDQTs7O0FBQ0FrRCxxQkFBcUIsQ0FBQ3NDLDZCQUF0QixHQUFzRHJELHdCQUF0RDtBQUNBZSxxQkFBcUIsQ0FBQ0QsOEJBQXRCLEdBQXVEQSw4QkFBdkQ7ZUFFZUMscUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgTW9uZ29Db2xsZWN0aW9uIGZyb20gJy4vTW9uZ29Db2xsZWN0aW9uJztcbmltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcblxuZnVuY3Rpb24gbW9uZ29GaWVsZFRvUGFyc2VTY2hlbWFGaWVsZCh0eXBlKSB7XG4gIGlmICh0eXBlWzBdID09PSAnKicpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ1BvaW50ZXInLFxuICAgICAgdGFyZ2V0Q2xhc3M6IHR5cGUuc2xpY2UoMSksXG4gICAgfTtcbiAgfVxuICBpZiAodHlwZS5zdGFydHNXaXRoKCdyZWxhdGlvbjwnKSkge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAnUmVsYXRpb24nLFxuICAgICAgdGFyZ2V0Q2xhc3M6IHR5cGUuc2xpY2UoJ3JlbGF0aW9uPCcubGVuZ3RoLCB0eXBlLmxlbmd0aCAtIDEpLFxuICAgIH07XG4gIH1cbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdOdW1iZXInIH07XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdTdHJpbmcnIH07XG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4geyB0eXBlOiAnQm9vbGVhbicgfTtcbiAgICBjYXNlICdkYXRlJzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdEYXRlJyB9O1xuICAgIGNhc2UgJ21hcCc6XG4gICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdPYmplY3QnIH07XG4gICAgY2FzZSAnYXJyYXknOlxuICAgICAgcmV0dXJuIHsgdHlwZTogJ0FycmF5JyB9O1xuICAgIGNhc2UgJ2dlb3BvaW50JzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdHZW9Qb2ludCcgfTtcbiAgICBjYXNlICdmaWxlJzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdGaWxlJyB9O1xuICAgIGNhc2UgJ2J5dGVzJzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdCeXRlcycgfTtcbiAgICBjYXNlICdwb2x5Z29uJzpcbiAgICAgIHJldHVybiB7IHR5cGU6ICdQb2x5Z29uJyB9O1xuICB9XG59XG5cbmNvbnN0IG5vbkZpZWxkU2NoZW1hS2V5cyA9IFsnX2lkJywgJ19tZXRhZGF0YScsICdfY2xpZW50X3Blcm1pc3Npb25zJ107XG5mdW5jdGlvbiBtb25nb1NjaGVtYUZpZWxkc1RvUGFyc2VTY2hlbWFGaWVsZHMoc2NoZW1hKSB7XG4gIHZhciBmaWVsZE5hbWVzID0gT2JqZWN0LmtleXMoc2NoZW1hKS5maWx0ZXIoXG4gICAga2V5ID0+IG5vbkZpZWxkU2NoZW1hS2V5cy5pbmRleE9mKGtleSkgPT09IC0xXG4gICk7XG4gIHZhciByZXNwb25zZSA9IGZpZWxkTmFtZXMucmVkdWNlKChvYmosIGZpZWxkTmFtZSkgPT4ge1xuICAgIG9ialtmaWVsZE5hbWVdID0gbW9uZ29GaWVsZFRvUGFyc2VTY2hlbWFGaWVsZChzY2hlbWFbZmllbGROYW1lXSk7XG4gICAgaWYgKFxuICAgICAgc2NoZW1hLl9tZXRhZGF0YSAmJlxuICAgICAgc2NoZW1hLl9tZXRhZGF0YS5maWVsZHNfb3B0aW9ucyAmJlxuICAgICAgc2NoZW1hLl9tZXRhZGF0YS5maWVsZHNfb3B0aW9uc1tmaWVsZE5hbWVdXG4gICAgKSB7XG4gICAgICBvYmpbZmllbGROYW1lXSA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgIHt9LFxuICAgICAgICBvYmpbZmllbGROYW1lXSxcbiAgICAgICAgc2NoZW1hLl9tZXRhZGF0YS5maWVsZHNfb3B0aW9uc1tmaWVsZE5hbWVdXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gb2JqO1xuICB9LCB7fSk7XG4gIHJlc3BvbnNlLkFDTCA9IHsgdHlwZTogJ0FDTCcgfTtcbiAgcmVzcG9uc2UuY3JlYXRlZEF0ID0geyB0eXBlOiAnRGF0ZScgfTtcbiAgcmVzcG9uc2UudXBkYXRlZEF0ID0geyB0eXBlOiAnRGF0ZScgfTtcbiAgcmVzcG9uc2Uub2JqZWN0SWQgPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gIHJldHVybiByZXNwb25zZTtcbn1cblxuY29uc3QgZW1wdHlDTFBTID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGZpbmQ6IHt9LFxuICBjb3VudDoge30sXG4gIGdldDoge30sXG4gIGNyZWF0ZToge30sXG4gIHVwZGF0ZToge30sXG4gIGRlbGV0ZToge30sXG4gIGFkZEZpZWxkOiB7fSxcbiAgcHJvdGVjdGVkRmllbGRzOiB7fSxcbn0pO1xuXG5jb25zdCBkZWZhdWx0Q0xQUyA9IE9iamVjdC5mcmVlemUoe1xuICBmaW5kOiB7ICcqJzogdHJ1ZSB9LFxuICBjb3VudDogeyAnKic6IHRydWUgfSxcbiAgZ2V0OiB7ICcqJzogdHJ1ZSB9LFxuICBjcmVhdGU6IHsgJyonOiB0cnVlIH0sXG4gIHVwZGF0ZTogeyAnKic6IHRydWUgfSxcbiAgZGVsZXRlOiB7ICcqJzogdHJ1ZSB9LFxuICBhZGRGaWVsZDogeyAnKic6IHRydWUgfSxcbiAgcHJvdGVjdGVkRmllbGRzOiB7ICcqJzogW10gfSxcbn0pO1xuXG5mdW5jdGlvbiBtb25nb1NjaGVtYVRvUGFyc2VTY2hlbWEobW9uZ29TY2hlbWEpIHtcbiAgbGV0IGNscHMgPSBkZWZhdWx0Q0xQUztcbiAgbGV0IGluZGV4ZXMgPSB7fTtcbiAgaWYgKG1vbmdvU2NoZW1hLl9tZXRhZGF0YSkge1xuICAgIGlmIChtb25nb1NjaGVtYS5fbWV0YWRhdGEuY2xhc3NfcGVybWlzc2lvbnMpIHtcbiAgICAgIGNscHMgPSB7IC4uLmVtcHR5Q0xQUywgLi4ubW9uZ29TY2hlbWEuX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zIH07XG4gICAgfVxuICAgIGlmIChtb25nb1NjaGVtYS5fbWV0YWRhdGEuaW5kZXhlcykge1xuICAgICAgaW5kZXhlcyA9IHsgLi4ubW9uZ29TY2hlbWEuX21ldGFkYXRhLmluZGV4ZXMgfTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBjbGFzc05hbWU6IG1vbmdvU2NoZW1hLl9pZCxcbiAgICBmaWVsZHM6IG1vbmdvU2NoZW1hRmllbGRzVG9QYXJzZVNjaGVtYUZpZWxkcyhtb25nb1NjaGVtYSksXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBjbHBzLFxuICAgIGluZGV4ZXM6IGluZGV4ZXMsXG4gIH07XG59XG5cbmZ1bmN0aW9uIF9tb25nb1NjaGVtYVF1ZXJ5RnJvbU5hbWVRdWVyeShuYW1lOiBzdHJpbmcsIHF1ZXJ5KSB7XG4gIGNvbnN0IG9iamVjdCA9IHsgX2lkOiBuYW1lIH07XG4gIGlmIChxdWVyeSkge1xuICAgIE9iamVjdC5rZXlzKHF1ZXJ5KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBvYmplY3Rba2V5XSA9IHF1ZXJ5W2tleV07XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIG9iamVjdDtcbn1cblxuLy8gUmV0dXJucyBhIHR5cGUgc3VpdGFibGUgZm9yIGluc2VydGluZyBpbnRvIG1vbmdvIF9TQ0hFTUEgY29sbGVjdGlvbi5cbi8vIERvZXMgbm8gdmFsaWRhdGlvbi4gVGhhdCBpcyBleHBlY3RlZCB0byBiZSBkb25lIGluIFBhcnNlIFNlcnZlci5cbmZ1bmN0aW9uIHBhcnNlRmllbGRUeXBlVG9Nb25nb0ZpZWxkVHlwZSh7IHR5cGUsIHRhcmdldENsYXNzIH0pIHtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICByZXR1cm4gYCoke3RhcmdldENsYXNzfWA7XG4gICAgY2FzZSAnUmVsYXRpb24nOlxuICAgICAgcmV0dXJuIGByZWxhdGlvbjwke3RhcmdldENsYXNzfT5gO1xuICAgIGNhc2UgJ051bWJlcic6XG4gICAgICByZXR1cm4gJ251bWJlcic7XG4gICAgY2FzZSAnU3RyaW5nJzpcbiAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICBjYXNlICdCb29sZWFuJzpcbiAgICAgIHJldHVybiAnYm9vbGVhbic7XG4gICAgY2FzZSAnRGF0ZSc6XG4gICAgICByZXR1cm4gJ2RhdGUnO1xuICAgIGNhc2UgJ09iamVjdCc6XG4gICAgICByZXR1cm4gJ29iamVjdCc7XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuICdhcnJheSc7XG4gICAgY2FzZSAnR2VvUG9pbnQnOlxuICAgICAgcmV0dXJuICdnZW9wb2ludCc7XG4gICAgY2FzZSAnRmlsZSc6XG4gICAgICByZXR1cm4gJ2ZpbGUnO1xuICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgIHJldHVybiAnYnl0ZXMnO1xuICAgIGNhc2UgJ1BvbHlnb24nOlxuICAgICAgcmV0dXJuICdwb2x5Z29uJztcbiAgfVxufVxuXG5jbGFzcyBNb25nb1NjaGVtYUNvbGxlY3Rpb24ge1xuICBfY29sbGVjdGlvbjogTW9uZ29Db2xsZWN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKGNvbGxlY3Rpb246IE1vbmdvQ29sbGVjdGlvbikge1xuICAgIHRoaXMuX2NvbGxlY3Rpb24gPSBjb2xsZWN0aW9uO1xuICB9XG5cbiAgX2ZldGNoQWxsU2NoZW1hc0Zyb21fU0NIRU1BKCkge1xuICAgIHJldHVybiB0aGlzLl9jb2xsZWN0aW9uXG4gICAgICAuX3Jhd0ZpbmQoe30pXG4gICAgICAudGhlbihzY2hlbWFzID0+IHNjaGVtYXMubWFwKG1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYSkpO1xuICB9XG5cbiAgX2ZldGNoT25lU2NoZW1hRnJvbV9TQ0hFTUEobmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbGxlY3Rpb25cbiAgICAgIC5fcmF3RmluZChfbW9uZ29TY2hlbWFRdWVyeUZyb21OYW1lUXVlcnkobmFtZSksIHsgbGltaXQ6IDEgfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICByZXR1cm4gbW9uZ29TY2hlbWFUb1BhcnNlU2NoZW1hKHJlc3VsdHNbMF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvLyBBdG9taWNhbGx5IGZpbmQgYW5kIGRlbGV0ZSBhbiBvYmplY3QgYmFzZWQgb24gcXVlcnkuXG4gIGZpbmRBbmREZWxldGVTY2hlbWEobmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5maW5kQW5kUmVtb3ZlKFxuICAgICAgX21vbmdvU2NoZW1hUXVlcnlGcm9tTmFtZVF1ZXJ5KG5hbWUpLFxuICAgICAgW11cbiAgICApO1xuICB9XG5cbiAgaW5zZXJ0U2NoZW1hKHNjaGVtYTogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbGxlY3Rpb25cbiAgICAgIC5pbnNlcnRPbmUoc2NoZW1hKVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IG1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYShyZXN1bHQub3BzWzBdKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkge1xuICAgICAgICAgIC8vTW9uZ28ncyBkdXBsaWNhdGUga2V5IGVycm9yXG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLFxuICAgICAgICAgICAgJ0NsYXNzIGFscmVhZHkgZXhpc3RzLidcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIHVwZGF0ZVNjaGVtYShuYW1lOiBzdHJpbmcsIHVwZGF0ZSkge1xuICAgIHJldHVybiB0aGlzLl9jb2xsZWN0aW9uLnVwZGF0ZU9uZShcbiAgICAgIF9tb25nb1NjaGVtYVF1ZXJ5RnJvbU5hbWVRdWVyeShuYW1lKSxcbiAgICAgIHVwZGF0ZVxuICAgICk7XG4gIH1cblxuICB1cHNlcnRTY2hlbWEobmFtZTogc3RyaW5nLCBxdWVyeTogc3RyaW5nLCB1cGRhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5fY29sbGVjdGlvbi51cHNlcnRPbmUoXG4gICAgICBfbW9uZ29TY2hlbWFRdWVyeUZyb21OYW1lUXVlcnkobmFtZSwgcXVlcnkpLFxuICAgICAgdXBkYXRlXG4gICAgKTtcbiAgfVxuXG4gIC8vIEFkZCBhIGZpZWxkIHRvIHRoZSBzY2hlbWEuIElmIGRhdGFiYXNlIGRvZXMgbm90IHN1cHBvcnQgdGhlIGZpZWxkXG4gIC8vIHR5cGUgKGUuZy4gbW9uZ28gZG9lc24ndCBzdXBwb3J0IG1vcmUgdGhhbiBvbmUgR2VvUG9pbnQgaW4gYSBjbGFzcykgcmVqZWN0IHdpdGggYW4gXCJJbmNvcnJlY3QgVHlwZVwiXG4gIC8vIFBhcnNlIGVycm9yIHdpdGggYSBkZXNjaXB0aXZlIG1lc3NhZ2UuIElmIHRoZSBmaWVsZCBhbHJlYWR5IGV4aXN0cywgdGhpcyBmdW5jdGlvbiBtdXN0XG4gIC8vIG5vdCBtb2RpZnkgdGhlIHNjaGVtYSwgYW5kIG11c3QgcmVqZWN0IHdpdGggRFVQTElDQVRFX1ZBTFVFIGVycm9yLlxuICAvLyBJZiB0aGlzIGlzIGNhbGxlZCBmb3IgYSBjbGFzcyB0aGF0IGRvZXNuJ3QgZXhpc3QsIHRoaXMgZnVuY3Rpb24gbXVzdCBjcmVhdGUgdGhhdCBjbGFzcy5cblxuICAvLyBUT0RPOiB0aHJvdyBhbiBlcnJvciBpZiBhbiB1bnN1cHBvcnRlZCBmaWVsZCB0eXBlIGlzIHBhc3NlZC4gRGVjaWRpbmcgd2hldGhlciBhIHR5cGUgaXMgc3VwcG9ydGVkXG4gIC8vIHNob3VsZCBiZSB0aGUgam9iIG9mIHRoZSBhZGFwdGVyLiBTb21lIGFkYXB0ZXJzIG1heSBub3Qgc3VwcG9ydCBHZW9Qb2ludCBhdCBhbGwuIE90aGVycyBtYXlcbiAgLy8gU3VwcG9ydCBhZGRpdGlvbmFsIHR5cGVzIHRoYXQgTW9uZ28gZG9lc24ndCwgbGlrZSBNb25leSwgb3Igc29tZXRoaW5nLlxuXG4gIC8vIFRPRE86IGRvbid0IHNwZW5kIGFuIGV4dHJhIHF1ZXJ5IG9uIGZpbmRpbmcgdGhlIHNjaGVtYSBpZiB0aGUgdHlwZSB3ZSBhcmUgdHJ5aW5nIHRvIGFkZCBpc24ndCBhIEdlb1BvaW50LlxuICBhZGRGaWVsZElmTm90RXhpc3RzKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZywgZmllbGRUeXBlOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fZmV0Y2hPbmVTY2hlbWFGcm9tX1NDSEVNQShjbGFzc05hbWUpXG4gICAgICAudGhlbihcbiAgICAgICAgc2NoZW1hID0+IHtcbiAgICAgICAgICAvLyBJZiBhIGZpZWxkIHdpdGggdGhpcyBuYW1lIGFscmVhZHkgZXhpc3RzLCBpdCB3aWxsIGJlIGhhbmRsZWQgZWxzZXdoZXJlLlxuICAgICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFRoZSBzY2hlbWEgZXhpc3RzLiBDaGVjayBmb3IgZXhpc3RpbmcgR2VvUG9pbnRzLlxuICAgICAgICAgIGlmIChmaWVsZFR5cGUudHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZXJlIGFyZSBub3Qgb3RoZXIgZ2VvcG9pbnQgZmllbGRzXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLnNvbWUoXG4gICAgICAgICAgICAgICAgZXhpc3RpbmdGaWVsZCA9PlxuICAgICAgICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1tleGlzdGluZ0ZpZWxkXS50eXBlID09PSAnR2VvUG9pbnQnXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgICAgICAgICAgJ01vbmdvREIgb25seSBzdXBwb3J0cyBvbmUgR2VvUG9pbnQgZmllbGQgaW4gYSBjbGFzcy4nXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3IgPT4ge1xuICAgICAgICAgIC8vIElmIGVycm9yIGlzIHVuZGVmaW5lZCwgdGhlIHNjaGVtYSBkb2Vzbid0IGV4aXN0LCBhbmQgd2UgY2FuIGNyZWF0ZSB0aGUgc2NoZW1hIHdpdGggdGhlIGZpZWxkLlxuICAgICAgICAgIC8vIElmIHNvbWUgb3RoZXIgZXJyb3IsIHJlamVjdCB3aXRoIGl0LlxuICAgICAgICAgIGlmIChlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICApXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgdHlwZSwgdGFyZ2V0Q2xhc3MsIC4uLmZpZWxkT3B0aW9ucyB9ID0gZmllbGRUeXBlO1xuICAgICAgICAvLyBXZSB1c2UgJGV4aXN0cyBhbmQgJHNldCB0byBhdm9pZCBvdmVyd3JpdGluZyB0aGUgZmllbGQgdHlwZSBpZiBpdFxuICAgICAgICAvLyBhbHJlYWR5IGV4aXN0cy4gKGl0IGNvdWxkIGhhdmUgYWRkZWQgaW5iZXR3ZWVuIHRoZSBsYXN0IHF1ZXJ5IGFuZCB0aGUgdXBkYXRlKVxuICAgICAgICBpZiAoZmllbGRPcHRpb25zICYmIE9iamVjdC5rZXlzKGZpZWxkT3B0aW9ucykubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLnVwc2VydFNjaGVtYShcbiAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgIHsgW2ZpZWxkTmFtZV06IHsgJGV4aXN0czogZmFsc2UgfSB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAkc2V0OiB7XG4gICAgICAgICAgICAgICAgW2ZpZWxkTmFtZV06IHBhcnNlRmllbGRUeXBlVG9Nb25nb0ZpZWxkVHlwZSh7XG4gICAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgICAgdGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgW2BfbWV0YWRhdGEuZmllbGRzX29wdGlvbnMuJHtmaWVsZE5hbWV9YF06IGZpZWxkT3B0aW9ucyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB0aGlzLnVwc2VydFNjaGVtYShcbiAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgIHsgW2ZpZWxkTmFtZV06IHsgJGV4aXN0czogZmFsc2UgfSB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAkc2V0OiB7XG4gICAgICAgICAgICAgICAgW2ZpZWxkTmFtZV06IHBhcnNlRmllbGRUeXBlVG9Nb25nb0ZpZWxkVHlwZSh7XG4gICAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgICAgdGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cbn1cblxuLy8gRXhwb3J0ZWQgZm9yIHRlc3RpbmcgcmVhc29ucyBhbmQgYmVjYXVzZSB3ZSBoYXZlbid0IG1vdmVkIGFsbCBtb25nbyBzY2hlbWEgZm9ybWF0XG4vLyByZWxhdGVkIGxvZ2ljIGludG8gdGhlIGRhdGFiYXNlIGFkYXB0ZXIgeWV0LlxuTW9uZ29TY2hlbWFDb2xsZWN0aW9uLl9URVNUbW9uZ29TY2hlbWFUb1BhcnNlU2NoZW1hID0gbW9uZ29TY2hlbWFUb1BhcnNlU2NoZW1hO1xuTW9uZ29TY2hlbWFDb2xsZWN0aW9uLnBhcnNlRmllbGRUeXBlVG9Nb25nb0ZpZWxkVHlwZSA9IHBhcnNlRmllbGRUeXBlVG9Nb25nb0ZpZWxkVHlwZTtcblxuZXhwb3J0IGRlZmF1bHQgTW9uZ29TY2hlbWFDb2xsZWN0aW9uO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js new file mode 100644 index 0000000000..022e68dd7d --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -0,0 +1,889 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.MongoStorageAdapter = void 0; + +var _MongoCollection = _interopRequireDefault(require("./MongoCollection")); + +var _MongoSchemaCollection = _interopRequireDefault(require("./MongoSchemaCollection")); + +var _StorageAdapter = require("../StorageAdapter"); + +var _mongodbUrl = require("../../../vendor/mongodbUrl"); + +var _MongoTransform = require("./MongoTransform"); + +var _node = _interopRequireDefault(require("parse/node")); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _defaults = _interopRequireDefault(require("../../../defaults")); + +var _logger = _interopRequireDefault(require("../../../logger")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +// -disable-next +const mongodb = require('mongodb'); + +const MongoClient = mongodb.MongoClient; +const ReadPreference = mongodb.ReadPreference; +const MongoSchemaCollectionName = '_SCHEMA'; + +const storageAdapterAllCollections = mongoAdapter => { + return mongoAdapter.connect().then(() => mongoAdapter.database.collections()).then(collections => { + return collections.filter(collection => { + if (collection.namespace.match(/\.system\./)) { + return false; + } // TODO: If you have one app with a collection prefix that happens to be a prefix of another + // apps prefix, this will go very very badly. We should fix that somehow. + + + return collection.collectionName.indexOf(mongoAdapter._collectionPrefix) == 0; + }); + }); +}; + +const convertParseSchemaToMongoSchema = (_ref) => { + let schema = _extends({}, _ref); + + delete schema.fields._rperm; + delete schema.fields._wperm; + + if (schema.className === '_User') { + // Legacy mongo adapter knows about the difference between password and _hashed_password. + // Future database adapters will only know about _hashed_password. + // Note: Parse Server will bring back password with injectDefaultSchema, so we don't need + // to add _hashed_password back ever. + delete schema.fields._hashed_password; + } + + return schema; +}; // Returns { code, error } if invalid, or { result }, an object +// suitable for inserting into _SCHEMA collection, otherwise. + + +const mongoSchemaFromFieldsAndClassNameAndCLP = (fields, className, classLevelPermissions, indexes) => { + const mongoObject = { + _id: className, + objectId: 'string', + updatedAt: 'string', + createdAt: 'string', + _metadata: undefined + }; + + for (const fieldName in fields) { + const _fields$fieldName = fields[fieldName], + { + type, + targetClass + } = _fields$fieldName, + fieldOptions = _objectWithoutProperties(_fields$fieldName, ["type", "targetClass"]); + + mongoObject[fieldName] = _MongoSchemaCollection.default.parseFieldTypeToMongoFieldType({ + type, + targetClass + }); + + if (fieldOptions && Object.keys(fieldOptions).length > 0) { + mongoObject._metadata = mongoObject._metadata || {}; + mongoObject._metadata.fields_options = mongoObject._metadata.fields_options || {}; + mongoObject._metadata.fields_options[fieldName] = fieldOptions; + } + } + + if (typeof classLevelPermissions !== 'undefined') { + mongoObject._metadata = mongoObject._metadata || {}; + + if (!classLevelPermissions) { + delete mongoObject._metadata.class_permissions; + } else { + mongoObject._metadata.class_permissions = classLevelPermissions; + } + } + + if (indexes && typeof indexes === 'object' && Object.keys(indexes).length > 0) { + mongoObject._metadata = mongoObject._metadata || {}; + mongoObject._metadata.indexes = indexes; + } + + if (!mongoObject._metadata) { + // cleanup the unused _metadata + delete mongoObject._metadata; + } + + return mongoObject; +}; + +class MongoStorageAdapter { + // Private + // Public + constructor({ + uri = _defaults.default.DefaultMongoURI, + collectionPrefix = '', + mongoOptions = {} + }) { + this._uri = uri; + this._collectionPrefix = collectionPrefix; + this._mongoOptions = mongoOptions; + this._mongoOptions.useNewUrlParser = true; + this._mongoOptions.useUnifiedTopology = true; // MaxTimeMS is not a global MongoDB client option, it is applied per operation. + + this._maxTimeMS = mongoOptions.maxTimeMS; + this.canSortOnJoinTables = true; + delete mongoOptions.maxTimeMS; + } + + connect() { + if (this.connectionPromise) { + return this.connectionPromise; + } // parsing and re-formatting causes the auth value (if there) to get URI + // encoded + + + const encodedUri = (0, _mongodbUrl.format)((0, _mongodbUrl.parse)(this._uri)); + this.connectionPromise = MongoClient.connect(encodedUri, this._mongoOptions).then(client => { + // Starting mongoDB 3.0, the MongoClient.connect don't return a DB anymore but a client + // Fortunately, we can get back the options and use them to select the proper DB. + // https://github.com/mongodb/node-mongodb-native/blob/2c35d76f08574225b8db02d7bef687123e6bb018/lib/mongo_client.js#L885 + const options = client.s.options; + const database = client.db(options.dbName); + + if (!database) { + delete this.connectionPromise; + return; + } + + database.on('error', () => { + delete this.connectionPromise; + }); + database.on('close', () => { + delete this.connectionPromise; + }); + this.client = client; + this.database = database; + }).catch(err => { + delete this.connectionPromise; + return Promise.reject(err); + }); + return this.connectionPromise; + } + + handleError(error) { + if (error && error.code === 13) { + // Unauthorized error + delete this.client; + delete this.database; + delete this.connectionPromise; + + _logger.default.error('Received unauthorized error', { + error: error + }); + } + + throw error; + } + + handleShutdown() { + if (!this.client) { + return Promise.resolve(); + } + + return this.client.close(false); + } + + _adaptiveCollection(name) { + return this.connect().then(() => this.database.collection(this._collectionPrefix + name)).then(rawCollection => new _MongoCollection.default(rawCollection)).catch(err => this.handleError(err)); + } + + _schemaCollection() { + return this.connect().then(() => this._adaptiveCollection(MongoSchemaCollectionName)).then(collection => new _MongoSchemaCollection.default(collection)); + } + + classExists(name) { + return this.connect().then(() => { + return this.database.listCollections({ + name: this._collectionPrefix + name + }).toArray(); + }).then(collections => { + return collections.length > 0; + }).catch(err => this.handleError(err)); + } + + setClassLevelPermissions(className, CLPs) { + return this._schemaCollection().then(schemaCollection => schemaCollection.updateSchema(className, { + $set: { + '_metadata.class_permissions': CLPs + } + })).catch(err => this.handleError(err)); + } + + setIndexesWithSchemaFormat(className, submittedIndexes, existingIndexes = {}, fields) { + if (submittedIndexes === undefined) { + return Promise.resolve(); + } + + if (Object.keys(existingIndexes).length === 0) { + existingIndexes = { + _id_: { + _id: 1 + } + }; + } + + const deletePromises = []; + const insertedIndexes = []; + Object.keys(submittedIndexes).forEach(name => { + const field = submittedIndexes[name]; + + if (existingIndexes[name] && field.__op !== 'Delete') { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`); + } + + if (!existingIndexes[name] && field.__op === 'Delete') { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Index ${name} does not exist, cannot delete.`); + } + + if (field.__op === 'Delete') { + const promise = this.dropIndex(className, name); + deletePromises.push(promise); + delete existingIndexes[name]; + } else { + Object.keys(field).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(fields, key)) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Field ${key} does not exist, cannot add index.`); + } + }); + existingIndexes[name] = field; + insertedIndexes.push({ + key: field, + name + }); + } + }); + let insertPromise = Promise.resolve(); + + if (insertedIndexes.length > 0) { + insertPromise = this.createIndexes(className, insertedIndexes); + } + + return Promise.all(deletePromises).then(() => insertPromise).then(() => this._schemaCollection()).then(schemaCollection => schemaCollection.updateSchema(className, { + $set: { + '_metadata.indexes': existingIndexes + } + })).catch(err => this.handleError(err)); + } + + setIndexesFromMongo(className) { + return this.getIndexes(className).then(indexes => { + indexes = indexes.reduce((obj, index) => { + if (index.key._fts) { + delete index.key._fts; + delete index.key._ftsx; + + for (const field in index.weights) { + index.key[field] = 'text'; + } + } + + obj[index.name] = index.key; + return obj; + }, {}); + return this._schemaCollection().then(schemaCollection => schemaCollection.updateSchema(className, { + $set: { + '_metadata.indexes': indexes + } + })); + }).catch(err => this.handleError(err)).catch(() => { + // Ignore if collection not found + return Promise.resolve(); + }); + } + + createClass(className, schema) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoObject = mongoSchemaFromFieldsAndClassNameAndCLP(schema.fields, className, schema.classLevelPermissions, schema.indexes); + mongoObject._id = className; + return this.setIndexesWithSchemaFormat(className, schema.indexes, {}, schema.fields).then(() => this._schemaCollection()).then(schemaCollection => schemaCollection.insertSchema(mongoObject)).catch(err => this.handleError(err)); + } + + addFieldIfNotExists(className, fieldName, type) { + return this._schemaCollection().then(schemaCollection => schemaCollection.addFieldIfNotExists(className, fieldName, type)).then(() => this.createIndexesIfNeeded(className, fieldName, type)).catch(err => this.handleError(err)); + } // Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.) + // and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible. + + + deleteClass(className) { + return this._adaptiveCollection(className).then(collection => collection.drop()).catch(error => { + // 'ns not found' means collection was already gone. Ignore deletion attempt. + if (error.message == 'ns not found') { + return; + } + + throw error; + }) // We've dropped the collection, now remove the _SCHEMA document + .then(() => this._schemaCollection()).then(schemaCollection => schemaCollection.findAndDeleteSchema(className)).catch(err => this.handleError(err)); + } + + deleteAllClasses(fast) { + return storageAdapterAllCollections(this).then(collections => Promise.all(collections.map(collection => fast ? collection.deleteMany({}) : collection.drop()))); + } // Remove the column and all the data. For Relations, the _Join collection is handled + // specially, this function does not delete _Join columns. It should, however, indicate + // that the relation fields does not exist anymore. In mongo, this means removing it from + // the _SCHEMA collection. There should be no actual data in the collection under the same name + // as the relation column, so it's fine to attempt to delete it. If the fields listed to be + // deleted do not exist, this function should return successfully anyways. Checking for + // attempts to delete non-existent fields is the responsibility of Parse Server. + // Pointer field names are passed for legacy reasons: the original mongo + // format stored pointer field names differently in the database, and therefore + // needed to know the type of the field before it could delete it. Future database + // adapters should ignore the pointerFieldNames argument. All the field names are in + // fieldNames, they show up additionally in the pointerFieldNames database for use + // by the mongo adapter, which deals with the legacy mongo format. + // This function is not obligated to delete fields atomically. It is given the field + // names in a list so that databases that are capable of deleting fields atomically + // may do so. + // Returns a Promise. + + + deleteFields(className, schema, fieldNames) { + const mongoFormatNames = fieldNames.map(fieldName => { + if (schema.fields[fieldName].type === 'Pointer') { + return `_p_${fieldName}`; + } else { + return fieldName; + } + }); + const collectionUpdate = { + $unset: {} + }; + mongoFormatNames.forEach(name => { + collectionUpdate['$unset'][name] = null; + }); + const schemaUpdate = { + $unset: {} + }; + fieldNames.forEach(name => { + schemaUpdate['$unset'][name] = null; + schemaUpdate['$unset'][`_metadata.fields_options.${name}`] = null; + }); + return this._adaptiveCollection(className).then(collection => collection.updateMany({}, collectionUpdate)).then(() => this._schemaCollection()).then(schemaCollection => schemaCollection.updateSchema(className, schemaUpdate)).catch(err => this.handleError(err)); + } // Return a promise for all schemas known to this adapter, in Parse format. In case the + // schemas cannot be retrieved, returns a promise that rejects. Requirements for the + // rejection reason are TBD. + + + getAllClasses() { + return this._schemaCollection().then(schemasCollection => schemasCollection._fetchAllSchemasFrom_SCHEMA()).catch(err => this.handleError(err)); + } // Return a promise for the schema with the given name, in Parse format. If + // this adapter doesn't know about the schema, return a promise that rejects with + // undefined as the reason. + + + getClass(className) { + return this._schemaCollection().then(schemasCollection => schemasCollection._fetchOneSchemaFrom_SCHEMA(className)).catch(err => this.handleError(err)); + } // TODO: As yet not particularly well specified. Creates an object. Maybe shouldn't even need the schema, + // and should infer from the type. Or maybe does need the schema for validations. Or maybe needs + // the schema only for the legacy mongo format. We'll figure that out later. + + + createObject(className, schema, object, transactionalSession) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoObject = (0, _MongoTransform.parseObjectToMongoObjectForCreate)(className, object, schema); + return this._adaptiveCollection(className).then(collection => collection.insertOne(mongoObject, transactionalSession)).catch(error => { + if (error.code === 11000) { + // Duplicate value + const err = new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided'); + err.underlyingError = error; + + if (error.message) { + const matches = error.message.match(/index:[\sa-zA-Z0-9_\-\.]+\$?([a-zA-Z_-]+)_1/); + + if (matches && Array.isArray(matches)) { + err.userInfo = { + duplicated_field: matches[1] + }; + } + } + + throw err; + } + + throw error; + }).catch(err => this.handleError(err)); + } // Remove all objects that match the given Parse Query. + // If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined. + // If there is some other error, reject with INTERNAL_SERVER_ERROR. + + + deleteObjectsByQuery(className, schema, query, transactionalSession) { + schema = convertParseSchemaToMongoSchema(schema); + return this._adaptiveCollection(className).then(collection => { + const mongoWhere = (0, _MongoTransform.transformWhere)(className, query, schema); + return collection.deleteMany(mongoWhere, transactionalSession); + }).catch(err => this.handleError(err)).then(({ + result + }) => { + if (result.n === 0) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + + return Promise.resolve(); + }, () => { + throw new _node.default.Error(_node.default.Error.INTERNAL_SERVER_ERROR, 'Database adapter error'); + }); + } // Apply the update to all objects that match the given Parse Query. + + + updateObjectsByQuery(className, schema, query, update, transactionalSession) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoUpdate = (0, _MongoTransform.transformUpdate)(className, update, schema); + const mongoWhere = (0, _MongoTransform.transformWhere)(className, query, schema); + return this._adaptiveCollection(className).then(collection => collection.updateMany(mongoWhere, mongoUpdate, transactionalSession)).catch(err => this.handleError(err)); + } // Atomically finds and updates an object based on query. + // Return value not currently well specified. + + + findOneAndUpdate(className, schema, query, update, transactionalSession) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoUpdate = (0, _MongoTransform.transformUpdate)(className, update, schema); + const mongoWhere = (0, _MongoTransform.transformWhere)(className, query, schema); + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.findOneAndUpdate(mongoWhere, mongoUpdate, { + returnOriginal: false, + session: transactionalSession || undefined + })).then(result => (0, _MongoTransform.mongoObjectToParseObject)(className, result.value, schema)).catch(error => { + if (error.code === 11000) { + throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided'); + } + + throw error; + }).catch(err => this.handleError(err)); + } // Hopefully we can get rid of this. It's only used for config and hooks. + + + upsertOneObject(className, schema, query, update, transactionalSession) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoUpdate = (0, _MongoTransform.transformUpdate)(className, update, schema); + const mongoWhere = (0, _MongoTransform.transformWhere)(className, query, schema); + return this._adaptiveCollection(className).then(collection => collection.upsertOne(mongoWhere, mongoUpdate, transactionalSession)).catch(err => this.handleError(err)); + } // Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }. + + + find(className, schema, query, { + skip, + limit, + sort, + keys, + readPreference + }) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoWhere = (0, _MongoTransform.transformWhere)(className, query, schema); + + const mongoSort = _lodash.default.mapKeys(sort, (value, fieldName) => (0, _MongoTransform.transformKey)(className, fieldName, schema)); + + const mongoKeys = _lodash.default.reduce(keys, (memo, key) => { + if (key === 'ACL') { + memo['_rperm'] = 1; + memo['_wperm'] = 1; + } else { + memo[(0, _MongoTransform.transformKey)(className, key, schema)] = 1; + } + + return memo; + }, {}); + + readPreference = this._parseReadPreference(readPreference); + return this.createTextIndexesIfNeeded(className, query, schema).then(() => this._adaptiveCollection(className)).then(collection => collection.find(mongoWhere, { + skip, + limit, + sort: mongoSort, + keys: mongoKeys, + maxTimeMS: this._maxTimeMS, + readPreference + })).then(objects => objects.map(object => (0, _MongoTransform.mongoObjectToParseObject)(className, object, schema))).catch(err => this.handleError(err)); + } // Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't + // currently know which fields are nullable and which aren't, we ignore that criteria. + // As such, we shouldn't expose this function to users of parse until we have an out-of-band + // Way of determining if a field is nullable. Undefined doesn't count against uniqueness, + // which is why we use sparse indexes. + + + ensureUniqueness(className, schema, fieldNames) { + schema = convertParseSchemaToMongoSchema(schema); + const indexCreationRequest = {}; + const mongoFieldNames = fieldNames.map(fieldName => (0, _MongoTransform.transformKey)(className, fieldName, schema)); + mongoFieldNames.forEach(fieldName => { + indexCreationRequest[fieldName] = 1; + }); + return this._adaptiveCollection(className).then(collection => collection._ensureSparseUniqueIndexInBackground(indexCreationRequest)).catch(error => { + if (error.code === 11000) { + throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'Tried to ensure field uniqueness for a class that already has duplicates.'); + } + + throw error; + }).catch(err => this.handleError(err)); + } // Used in tests + + + _rawFind(className, query) { + return this._adaptiveCollection(className).then(collection => collection.find(query, { + maxTimeMS: this._maxTimeMS + })).catch(err => this.handleError(err)); + } // Executes a count. + + + count(className, schema, query, readPreference) { + schema = convertParseSchemaToMongoSchema(schema); + readPreference = this._parseReadPreference(readPreference); + return this._adaptiveCollection(className).then(collection => collection.count((0, _MongoTransform.transformWhere)(className, query, schema, true), { + maxTimeMS: this._maxTimeMS, + readPreference + })).catch(err => this.handleError(err)); + } + + distinct(className, schema, query, fieldName) { + schema = convertParseSchemaToMongoSchema(schema); + const isPointerField = schema.fields[fieldName] && schema.fields[fieldName].type === 'Pointer'; + const transformField = (0, _MongoTransform.transformKey)(className, fieldName, schema); + return this._adaptiveCollection(className).then(collection => collection.distinct(transformField, (0, _MongoTransform.transformWhere)(className, query, schema))).then(objects => { + objects = objects.filter(obj => obj != null); + return objects.map(object => { + if (isPointerField) { + return (0, _MongoTransform.transformPointerString)(schema, fieldName, object); + } + + return (0, _MongoTransform.mongoObjectToParseObject)(className, object, schema); + }); + }).catch(err => this.handleError(err)); + } + + aggregate(className, schema, pipeline, readPreference) { + let isPointerField = false; + pipeline = pipeline.map(stage => { + if (stage.$group) { + stage.$group = this._parseAggregateGroupArgs(schema, stage.$group); + + if (stage.$group._id && typeof stage.$group._id === 'string' && stage.$group._id.indexOf('$_p_') >= 0) { + isPointerField = true; + } + } + + if (stage.$match) { + stage.$match = this._parseAggregateArgs(schema, stage.$match); + } + + if (stage.$project) { + stage.$project = this._parseAggregateProjectArgs(schema, stage.$project); + } + + return stage; + }); + readPreference = this._parseReadPreference(readPreference); + return this._adaptiveCollection(className).then(collection => collection.aggregate(pipeline, { + readPreference, + maxTimeMS: this._maxTimeMS + })).then(results => { + results.forEach(result => { + if (Object.prototype.hasOwnProperty.call(result, '_id')) { + if (isPointerField && result._id) { + result._id = result._id.split('$')[1]; + } + + if (result._id == null || result._id == undefined || ['object', 'string'].includes(typeof result._id) && _lodash.default.isEmpty(result._id)) { + result._id = null; + } + + result.objectId = result._id; + delete result._id; + } + }); + return results; + }).then(objects => objects.map(object => (0, _MongoTransform.mongoObjectToParseObject)(className, object, schema))).catch(err => this.handleError(err)); + } // This function will recursively traverse the pipeline and convert any Pointer or Date columns. + // If we detect a pointer column we will rename the column being queried for to match the column + // in the database. We also modify the value to what we expect the value to be in the database + // as well. + // For dates, the driver expects a Date object, but we have a string coming in. So we'll convert + // the string to a Date so the driver can perform the necessary comparison. + // + // The goal of this method is to look for the "leaves" of the pipeline and determine if it needs + // to be converted. The pipeline can have a few different forms. For more details, see: + // https://docs.mongodb.com/manual/reference/operator/aggregation/ + // + // If the pipeline is an array, it means we are probably parsing an '$and' or '$or' operator. In + // that case we need to loop through all of it's children to find the columns being operated on. + // If the pipeline is an object, then we'll loop through the keys checking to see if the key name + // matches one of the schema columns. If it does match a column and the column is a Pointer or + // a Date, then we'll convert the value as described above. + // + // As much as I hate recursion...this seemed like a good fit for it. We're essentially traversing + // down a tree to find a "leaf node" and checking to see if it needs to be converted. + + + _parseAggregateArgs(schema, pipeline) { + if (pipeline === null) { + return null; + } else if (Array.isArray(pipeline)) { + return pipeline.map(value => this._parseAggregateArgs(schema, value)); + } else if (typeof pipeline === 'object') { + const returnValue = {}; + + for (const field in pipeline) { + if (schema.fields[field] && schema.fields[field].type === 'Pointer') { + if (typeof pipeline[field] === 'object') { + // Pass objects down to MongoDB...this is more than likely an $exists operator. + returnValue[`_p_${field}`] = pipeline[field]; + } else { + returnValue[`_p_${field}`] = `${schema.fields[field].targetClass}$${pipeline[field]}`; + } + } else if (schema.fields[field] && schema.fields[field].type === 'Date') { + returnValue[field] = this._convertToDate(pipeline[field]); + } else { + returnValue[field] = this._parseAggregateArgs(schema, pipeline[field]); + } + + if (field === 'objectId') { + returnValue['_id'] = returnValue[field]; + delete returnValue[field]; + } else if (field === 'createdAt') { + returnValue['_created_at'] = returnValue[field]; + delete returnValue[field]; + } else if (field === 'updatedAt') { + returnValue['_updated_at'] = returnValue[field]; + delete returnValue[field]; + } + } + + return returnValue; + } + + return pipeline; + } // This function is slightly different than the one above. Rather than trying to combine these + // two functions and making the code even harder to understand, I decided to split it up. The + // difference with this function is we are not transforming the values, only the keys of the + // pipeline. + + + _parseAggregateProjectArgs(schema, pipeline) { + const returnValue = {}; + + for (const field in pipeline) { + if (schema.fields[field] && schema.fields[field].type === 'Pointer') { + returnValue[`_p_${field}`] = pipeline[field]; + } else { + returnValue[field] = this._parseAggregateArgs(schema, pipeline[field]); + } + + if (field === 'objectId') { + returnValue['_id'] = returnValue[field]; + delete returnValue[field]; + } else if (field === 'createdAt') { + returnValue['_created_at'] = returnValue[field]; + delete returnValue[field]; + } else if (field === 'updatedAt') { + returnValue['_updated_at'] = returnValue[field]; + delete returnValue[field]; + } + } + + return returnValue; + } // This function is slightly different than the two above. MongoDB $group aggregate looks like: + // { $group: { _id: , : { : }, ... } } + // The could be a column name, prefixed with the '$' character. We'll look for + // these and check to see if it is a 'Pointer' or if it's one of createdAt, + // updatedAt or objectId and change it accordingly. + + + _parseAggregateGroupArgs(schema, pipeline) { + if (Array.isArray(pipeline)) { + return pipeline.map(value => this._parseAggregateGroupArgs(schema, value)); + } else if (typeof pipeline === 'object') { + const returnValue = {}; + + for (const field in pipeline) { + returnValue[field] = this._parseAggregateGroupArgs(schema, pipeline[field]); + } + + return returnValue; + } else if (typeof pipeline === 'string') { + const field = pipeline.substring(1); + + if (schema.fields[field] && schema.fields[field].type === 'Pointer') { + return `$_p_${field}`; + } else if (field == 'createdAt') { + return '$_created_at'; + } else if (field == 'updatedAt') { + return '$_updated_at'; + } + } + + return pipeline; + } // This function will attempt to convert the provided value to a Date object. Since this is part + // of an aggregation pipeline, the value can either be a string or it can be another object with + // an operator in it (like $gt, $lt, etc). Because of this I felt it was easier to make this a + // recursive method to traverse down to the "leaf node" which is going to be the string. + + + _convertToDate(value) { + if (typeof value === 'string') { + return new Date(value); + } + + const returnValue = {}; + + for (const field in value) { + returnValue[field] = this._convertToDate(value[field]); + } + + return returnValue; + } + + _parseReadPreference(readPreference) { + if (readPreference) { + readPreference = readPreference.toUpperCase(); + } + + switch (readPreference) { + case 'PRIMARY': + readPreference = ReadPreference.PRIMARY; + break; + + case 'PRIMARY_PREFERRED': + readPreference = ReadPreference.PRIMARY_PREFERRED; + break; + + case 'SECONDARY': + readPreference = ReadPreference.SECONDARY; + break; + + case 'SECONDARY_PREFERRED': + readPreference = ReadPreference.SECONDARY_PREFERRED; + break; + + case 'NEAREST': + readPreference = ReadPreference.NEAREST; + break; + + case undefined: + case null: + case '': + break; + + default: + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'Not supported read preference.'); + } + + return readPreference; + } + + performInitialization() { + return Promise.resolve(); + } + + createIndex(className, index) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.createIndex(index)).catch(err => this.handleError(err)); + } + + createIndexes(className, indexes) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.createIndexes(indexes)).catch(err => this.handleError(err)); + } + + createIndexesIfNeeded(className, fieldName, type) { + if (type && type.type === 'Polygon') { + const index = { + [fieldName]: '2dsphere' + }; + return this.createIndex(className, index); + } + + return Promise.resolve(); + } + + createTextIndexesIfNeeded(className, query, schema) { + for (const fieldName in query) { + if (!query[fieldName] || !query[fieldName].$text) { + continue; + } + + const existingIndexes = schema.indexes; + + for (const key in existingIndexes) { + const index = existingIndexes[key]; + + if (Object.prototype.hasOwnProperty.call(index, fieldName)) { + return Promise.resolve(); + } + } + + const indexName = `${fieldName}_text`; + const textIndex = { + [indexName]: { + [fieldName]: 'text' + } + }; + return this.setIndexesWithSchemaFormat(className, textIndex, existingIndexes, schema.fields).catch(error => { + if (error.code === 85) { + // Index exist with different options + return this.setIndexesFromMongo(className); + } + + throw error; + }); + } + + return Promise.resolve(); + } + + getIndexes(className) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.indexes()).catch(err => this.handleError(err)); + } + + dropIndex(className, index) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.dropIndex(index)).catch(err => this.handleError(err)); + } + + dropAllIndexes(className) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.dropIndexes()).catch(err => this.handleError(err)); + } + + updateSchemaWithIndexes() { + return this.getAllClasses().then(classes => { + const promises = classes.map(schema => { + return this.setIndexesFromMongo(schema.className); + }); + return Promise.all(promises); + }).catch(err => this.handleError(err)); + } + + createTransactionalSession() { + const transactionalSection = this.client.startSession(); + transactionalSection.startTransaction(); + return Promise.resolve(transactionalSection); + } + + commitTransactionalSession(transactionalSection) { + return transactionalSection.commitTransaction().then(() => { + transactionalSection.endSession(); + }); + } + + abortTransactionalSession(transactionalSection) { + return transactionalSection.abortTransaction().then(() => { + transactionalSection.endSession(); + }); + } + +} + +exports.MongoStorageAdapter = MongoStorageAdapter; +var _default = MongoStorageAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsibW9uZ29kYiIsInJlcXVpcmUiLCJNb25nb0NsaWVudCIsIlJlYWRQcmVmZXJlbmNlIiwiTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSIsInN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMiLCJtb25nb0FkYXB0ZXIiLCJjb25uZWN0IiwidGhlbiIsImRhdGFiYXNlIiwiY29sbGVjdGlvbnMiLCJmaWx0ZXIiLCJjb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwibWF0Y2giLCJjb2xsZWN0aW9uTmFtZSIsImluZGV4T2YiLCJfY29sbGVjdGlvblByZWZpeCIsImNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEiLCJzY2hlbWEiLCJmaWVsZHMiLCJfcnBlcm0iLCJfd3Blcm0iLCJjbGFzc05hbWUiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vbmdvT2JqZWN0IiwiX2lkIiwib2JqZWN0SWQiLCJ1cGRhdGVkQXQiLCJjcmVhdGVkQXQiLCJfbWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJmaWVsZE5hbWUiLCJ0eXBlIiwidGFyZ2V0Q2xhc3MiLCJmaWVsZE9wdGlvbnMiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJPYmplY3QiLCJrZXlzIiwibGVuZ3RoIiwiZmllbGRzX29wdGlvbnMiLCJjbGFzc19wZXJtaXNzaW9ucyIsIk1vbmdvU3RvcmFnZUFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsInVyaSIsImRlZmF1bHRzIiwiRGVmYXVsdE1vbmdvVVJJIiwiY29sbGVjdGlvblByZWZpeCIsIm1vbmdvT3B0aW9ucyIsIl91cmkiLCJfbW9uZ29PcHRpb25zIiwidXNlTmV3VXJsUGFyc2VyIiwidXNlVW5pZmllZFRvcG9sb2d5IiwiX21heFRpbWVNUyIsIm1heFRpbWVNUyIsImNhblNvcnRPbkpvaW5UYWJsZXMiLCJjb25uZWN0aW9uUHJvbWlzZSIsImVuY29kZWRVcmkiLCJjbGllbnQiLCJvcHRpb25zIiwicyIsImRiIiwiZGJOYW1lIiwib24iLCJjYXRjaCIsImVyciIsIlByb21pc2UiLCJyZWplY3QiLCJoYW5kbGVFcnJvciIsImVycm9yIiwiY29kZSIsImxvZ2dlciIsImhhbmRsZVNodXRkb3duIiwicmVzb2x2ZSIsImNsb3NlIiwiX2FkYXB0aXZlQ29sbGVjdGlvbiIsIm5hbWUiLCJyYXdDb2xsZWN0aW9uIiwiTW9uZ29Db2xsZWN0aW9uIiwiX3NjaGVtYUNvbGxlY3Rpb24iLCJjbGFzc0V4aXN0cyIsImxpc3RDb2xsZWN0aW9ucyIsInRvQXJyYXkiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2NoZW1hQ29sbGVjdGlvbiIsInVwZGF0ZVNjaGVtYSIsIiRzZXQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJfaWRfIiwiZGVsZXRlUHJvbWlzZXMiLCJpbnNlcnRlZEluZGV4ZXMiLCJmb3JFYWNoIiwiZmllbGQiLCJfX29wIiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfUVVFUlkiLCJwcm9taXNlIiwiZHJvcEluZGV4IiwicHVzaCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImluc2VydFByb21pc2UiLCJjcmVhdGVJbmRleGVzIiwiYWxsIiwic2V0SW5kZXhlc0Zyb21Nb25nbyIsImdldEluZGV4ZXMiLCJyZWR1Y2UiLCJvYmoiLCJpbmRleCIsIl9mdHMiLCJfZnRzeCIsIndlaWdodHMiLCJjcmVhdGVDbGFzcyIsImluc2VydFNjaGVtYSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJjcmVhdGVJbmRleGVzSWZOZWVkZWQiLCJkZWxldGVDbGFzcyIsImRyb3AiLCJtZXNzYWdlIiwiZmluZEFuZERlbGV0ZVNjaGVtYSIsImRlbGV0ZUFsbENsYXNzZXMiLCJmYXN0IiwibWFwIiwiZGVsZXRlTWFueSIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJtb25nb0Zvcm1hdE5hbWVzIiwiY29sbGVjdGlvblVwZGF0ZSIsIiR1bnNldCIsInNjaGVtYVVwZGF0ZSIsInVwZGF0ZU1hbnkiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hc0NvbGxlY3Rpb24iLCJfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEiLCJnZXRDbGFzcyIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0IiwidHJhbnNhY3Rpb25hbFNlc3Npb24iLCJpbnNlcnRPbmUiLCJEVVBMSUNBVEVfVkFMVUUiLCJ1bmRlcmx5aW5nRXJyb3IiLCJtYXRjaGVzIiwiQXJyYXkiLCJpc0FycmF5IiwidXNlckluZm8iLCJkdXBsaWNhdGVkX2ZpZWxkIiwiZGVsZXRlT2JqZWN0c0J5UXVlcnkiLCJxdWVyeSIsIm1vbmdvV2hlcmUiLCJyZXN1bHQiLCJuIiwiT0JKRUNUX05PVF9GT1VORCIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsInVwZGF0ZU9iamVjdHNCeVF1ZXJ5IiwidXBkYXRlIiwibW9uZ29VcGRhdGUiLCJmaW5kT25lQW5kVXBkYXRlIiwiX21vbmdvQ29sbGVjdGlvbiIsInJldHVybk9yaWdpbmFsIiwic2Vzc2lvbiIsInZhbHVlIiwidXBzZXJ0T25lT2JqZWN0IiwidXBzZXJ0T25lIiwiZmluZCIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJyZWFkUHJlZmVyZW5jZSIsIm1vbmdvU29ydCIsIl8iLCJtYXBLZXlzIiwibW9uZ29LZXlzIiwibWVtbyIsIl9wYXJzZVJlYWRQcmVmZXJlbmNlIiwiY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZCIsIm9iamVjdHMiLCJlbnN1cmVVbmlxdWVuZXNzIiwiaW5kZXhDcmVhdGlvblJlcXVlc3QiLCJtb25nb0ZpZWxkTmFtZXMiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJfcmF3RmluZCIsImNvdW50IiwiZGlzdGluY3QiLCJpc1BvaW50ZXJGaWVsZCIsInRyYW5zZm9ybUZpZWxkIiwiYWdncmVnYXRlIiwicGlwZWxpbmUiLCJzdGFnZSIsIiRncm91cCIsIl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyIsIiRtYXRjaCIsIl9wYXJzZUFnZ3JlZ2F0ZUFyZ3MiLCIkcHJvamVjdCIsIl9wYXJzZUFnZ3JlZ2F0ZVByb2plY3RBcmdzIiwicmVzdWx0cyIsInNwbGl0IiwiaW5jbHVkZXMiLCJpc0VtcHR5IiwicmV0dXJuVmFsdWUiLCJfY29udmVydFRvRGF0ZSIsInN1YnN0cmluZyIsIkRhdGUiLCJ0b1VwcGVyQ2FzZSIsIlBSSU1BUlkiLCJQUklNQVJZX1BSRUZFUlJFRCIsIlNFQ09OREFSWSIsIlNFQ09OREFSWV9QUkVGRVJSRUQiLCJORUFSRVNUIiwicGVyZm9ybUluaXRpYWxpemF0aW9uIiwiY3JlYXRlSW5kZXgiLCIkdGV4dCIsImluZGV4TmFtZSIsInRleHRJbmRleCIsImRyb3BBbGxJbmRleGVzIiwiZHJvcEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsImNsYXNzZXMiLCJwcm9taXNlcyIsImNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uIiwidHJhbnNhY3Rpb25hbFNlY3Rpb24iLCJzdGFydFNlc3Npb24iLCJzdGFydFRyYW5zYWN0aW9uIiwiY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24iLCJjb21taXRUcmFuc2FjdGlvbiIsImVuZFNlc3Npb24iLCJhYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uIiwiYWJvcnRUcmFuc2FjdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQUNBOztBQUNBOztBQU9BOztBQUlBOztBQVNBOztBQUVBOztBQUNBOztBQUNBOzs7Ozs7Ozs7O0FBRUE7QUFDQSxNQUFNQSxPQUFPLEdBQUdDLE9BQU8s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QVltSCxRQUFaLENBQVA7QUFDRCxLQU5JLEVBT0poSyxLQVBJLENBT0VDLEdBQUcsSUFBSSxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQVBULENBQVA7QUFRRDs7QUFFRGdLLEVBQUFBLDBCQUEwQixHQUFpQjtBQUN6QyxVQUFNQyxvQkFBb0IsR0FBRyxLQUFLeEssTUFBTCxDQUFZeUssWUFBWixFQUE3QjtBQUNBRCxJQUFBQSxvQkFBb0IsQ0FBQ0UsZ0JBQXJCO0FBQ0EsV0FBT2xLLE9BQU8sQ0FBQ08sT0FBUixDQUFnQnlKLG9CQUFoQixDQUFQO0FBQ0Q7O0FBRURHLEVBQUFBLDBCQUEwQixDQUFDSCxvQkFBRCxFQUEyQztBQUNuRSxXQUFPQSxvQkFBb0IsQ0FBQ0ksaUJBQXJCLEdBQXlDbE8sSUFBekMsQ0FBOEMsTUFBTTtBQUN6RDhOLE1BQUFBLG9CQUFvQixDQUFDSyxVQUFyQjtBQUNELEtBRk0sQ0FBUDtBQUdEOztBQUVEQyxFQUFBQSx5QkFBeUIsQ0FBQ04sb0JBQUQsRUFBMkM7QUFDbEUsV0FBT0Esb0JBQW9CLENBQUNPLGdCQUFyQixHQUF3Q3JPLElBQXhDLENBQTZDLE1BQU07QUFDeEQ4TixNQUFBQSxvQkFBb0IsQ0FBQ0ssVUFBckI7QUFDRCxLQUZNLENBQVA7QUFHRDs7QUEvOEJ3RDs7O2VBazlCNUM3TCxtQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG5pbXBvcnQgTW9uZ29Db2xsZWN0aW9uIGZyb20gJy4vTW9uZ29Db2xsZWN0aW9uJztcbmltcG9ydCBNb25nb1NjaGVtYUNvbGxlY3Rpb24gZnJvbSAnLi9Nb25nb1NjaGVtYUNvbGxlY3Rpb24nO1xuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgdHlwZSB7XG4gIFNjaGVtYVR5cGUsXG4gIFF1ZXJ5VHlwZSxcbiAgU3RvcmFnZUNsYXNzLFxuICBRdWVyeU9wdGlvbnMsXG59IGZyb20gJy4uL1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCB7XG4gIHBhcnNlIGFzIHBhcnNlVXJsLFxuICBmb3JtYXQgYXMgZm9ybWF0VXJsLFxufSBmcm9tICcuLi8uLi8uLi92ZW5kb3IvbW9uZ29kYlVybCc7XG5pbXBvcnQge1xuICBwYXJzZU9iamVjdFRvTW9uZ29PYmplY3RGb3JDcmVhdGUsXG4gIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdCxcbiAgdHJhbnNmb3JtS2V5LFxuICB0cmFuc2Zvcm1XaGVyZSxcbiAgdHJhbnNmb3JtVXBkYXRlLFxuICB0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nLFxufSBmcm9tICcuL01vbmdvVHJhbnNmb3JtJztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4uLy4uLy4uL2RlZmF1bHRzJztcbmltcG9ydCBsb2dnZXIgZnJvbSAnLi4vLi4vLi4vbG9nZ2VyJztcblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5jb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgTW9uZ29DbGllbnQgPSBtb25nb2RiLk1vbmdvQ2xpZW50O1xuY29uc3QgUmVhZFByZWZlcmVuY2UgPSBtb25nb2RiLlJlYWRQcmVmZXJlbmNlO1xuXG5jb25zdCBNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lID0gJ19TQ0hFTUEnO1xuXG5jb25zdCBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zID0gbW9uZ29BZGFwdGVyID0+IHtcbiAgcmV0dXJuIG1vbmdvQWRhcHRlclxuICAgIC5jb25uZWN0KClcbiAgICAudGhlbigoKSA9PiBtb25nb0FkYXB0ZXIuZGF0YWJhc2UuY29sbGVjdGlvbnMoKSlcbiAgICAudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbnMuZmlsdGVyKGNvbGxlY3Rpb24gPT4ge1xuICAgICAgICBpZiAoY29sbGVjdGlvbi5uYW1lc3BhY2UubWF0Y2goL1xcLnN5c3RlbVxcLi8pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IElmIHlvdSBoYXZlIG9uZSBhcHAgd2l0aCBhIGNvbGxlY3Rpb24gcHJlZml4IHRoYXQgaGFwcGVucyB0byBiZSBhIHByZWZpeCBvZiBhbm90aGVyXG4gICAgICAgIC8vIGFwcHMgcHJlZml4LCB0aGlzIHdpbGwgZ28gdmVyeSB2ZXJ5IGJhZGx5LiBXZSBzaG91bGQgZml4IHRoYXQgc29tZWhvdy5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBjb2xsZWN0aW9uLmNvbGxlY3Rpb25OYW1lLmluZGV4T2YobW9uZ29BZGFwdGVyLl9jb2xsZWN0aW9uUHJlZml4KSA9PSAwXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcbn07XG5cbmNvbnN0IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEgPSAoeyAuLi5zY2hlbWEgfSkgPT4ge1xuICBkZWxldGUgc2NoZW1hLmZpZWxkcy5fcnBlcm07XG4gIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl93cGVybTtcblxuICBpZiAoc2NoZW1hLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgIC8vIExlZ2FjeSBtb25nbyBhZGFwdGVyIGtub3dzIGFib3V0IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gcGFzc3dvcmQgYW5kIF9oYXNoZWRfcGFzc3dvcmQuXG4gICAgLy8gRnV0dXJlIGRhdGFiYXNlIGFkYXB0ZXJzIHdpbGwgb25seSBrbm93IGFib3V0IF9oYXNoZWRfcGFzc3dvcmQuXG4gICAgLy8gTm90ZTogUGFyc2UgU2VydmVyIHdpbGwgYnJpbmcgYmFjayBwYXNzd29yZCB3aXRoIGluamVjdERlZmF1bHRTY2hlbWEsIHNvIHdlIGRvbid0IG5lZWRcbiAgICAvLyB0byBhZGQgX2hhc2hlZF9wYXNzd29yZCBiYWNrIGV2ZXIuXG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX2hhc2hlZF9wYXNzd29yZDtcbiAgfVxuXG4gIHJldHVybiBzY2hlbWE7XG59O1xuXG4vLyBSZXR1cm5zIHsgY29kZSwgZXJyb3IgfSBpZiBpbnZhbGlkLCBvciB7IHJlc3VsdCB9LCBhbiBvYmplY3Rcbi8vIHN1aXRhYmxlIGZvciBpbnNlcnRpbmcgaW50byBfU0NIRU1BIGNvbGxlY3Rpb24sIG90aGVyd2lzZS5cbmNvbnN0IG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZUFuZENMUCA9IChcbiAgZmllbGRzLFxuICBjbGFzc05hbWUsXG4gIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgaW5kZXhlc1xuKSA9PiB7XG4gIGNvbnN0IG1vbmdvT2JqZWN0ID0ge1xuICAgIF9pZDogY2xhc3NOYW1lLFxuICAgIG9iamVjdElkOiAnc3RyaW5nJyxcbiAgICB1cGRhdGVkQXQ6ICdzdHJpbmcnLFxuICAgIGNyZWF0ZWRBdDogJ3N0cmluZycsXG4gICAgX21ldGFkYXRhOiB1bmRlZmluZWQsXG4gIH07XG5cbiAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gZmllbGRzKSB7XG4gICAgY29uc3QgeyB0eXBlLCB0YXJnZXRDbGFzcywgLi4uZmllbGRPcHRpb25zIH0gPSBmaWVsZHNbZmllbGROYW1lXTtcbiAgICBtb25nb09iamVjdFtcbiAgICAgIGZpZWxkTmFtZVxuICAgIF0gPSBNb25nb1NjaGVtYUNvbGxlY3Rpb24ucGFyc2VGaWVsZFR5cGVUb01vbmdvRmllbGRUeXBlKHtcbiAgICAgIHR5cGUsXG4gICAgICB0YXJnZXRDbGFzcyxcbiAgICB9KTtcbiAgICBpZiAoZmllbGRPcHRpb25zICYmIE9iamVjdC5rZXlzKGZpZWxkT3B0aW9ucykubGVuZ3RoID4gMCkge1xuICAgICAgbW9uZ29PYmplY3QuX21ldGFkYXRhID0gbW9uZ29PYmplY3QuX21ldGFkYXRhIHx8IHt9O1xuICAgICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmZpZWxkc19vcHRpb25zID1cbiAgICAgICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmZpZWxkc19vcHRpb25zIHx8IHt9O1xuICAgICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmZpZWxkc19vcHRpb25zW2ZpZWxkTmFtZV0gPSBmaWVsZE9wdGlvbnM7XG4gICAgfVxuICB9XG5cbiAgaWYgKHR5cGVvZiBjbGFzc0xldmVsUGVybWlzc2lvbnMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhID0gbW9uZ29PYmplY3QuX21ldGFkYXRhIHx8IHt9O1xuICAgIGlmICghY2xhc3NMZXZlbFBlcm1pc3Npb25zKSB7XG4gICAgICBkZWxldGUgbW9uZ29PYmplY3QuX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zO1xuICAgIH0gZWxzZSB7XG4gICAgICBtb25nb09iamVjdC5fbWV0YWRhdGEuY2xhc3NfcGVybWlzc2lvbnMgPSBjbGFzc0xldmVsUGVybWlzc2lvbnM7XG4gICAgfVxuICB9XG5cbiAgaWYgKFxuICAgIGluZGV4ZXMgJiZcbiAgICB0eXBlb2YgaW5kZXhlcyA9PT0gJ29iamVjdCcgJiZcbiAgICBPYmplY3Qua2V5cyhpbmRleGVzKS5sZW5ndGggPiAwXG4gICkge1xuICAgIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSA9IG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSB8fCB7fTtcbiAgICBtb25nb09iamVjdC5fbWV0YWRhdGEuaW5kZXhlcyA9IGluZGV4ZXM7XG4gIH1cblxuICBpZiAoIW1vbmdvT2JqZWN0Ll9tZXRhZGF0YSkge1xuICAgIC8vIGNsZWFudXAgdGhlIHVudXNlZCBfbWV0YWRhdGFcbiAgICBkZWxldGUgbW9uZ29PYmplY3QuX21ldGFkYXRhO1xuICB9XG5cbiAgcmV0dXJuIG1vbmdvT2JqZWN0O1xufTtcblxuZXhwb3J0IGNsYXNzIE1vbmdvU3RvcmFnZUFkYXB0ZXIgaW1wbGVtZW50cyBTdG9yYWdlQWRhcHRlciB7XG4gIC8vIFByaXZhdGVcbiAgX3VyaTogc3RyaW5nO1xuICBfY29sbGVjdGlvblByZWZpeDogc3RyaW5nO1xuICBfbW9uZ29PcHRpb25zOiBPYmplY3Q7XG4gIC8vIFB1YmxpY1xuICBjb25uZWN0aW9uUHJvbWlzZTogP1Byb21pc2U8YW55PjtcbiAgZGF0YWJhc2U6IGFueTtcbiAgY2xpZW50OiBNb25nb0NsaWVudDtcbiAgX21heFRpbWVNUzogP251bWJlcjtcbiAgY2FuU29ydE9uSm9pblRhYmxlczogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcih7XG4gICAgdXJpID0gZGVmYXVsdHMuRGVmYXVsdE1vbmdvVVJJLFxuICAgIGNvbGxlY3Rpb25QcmVmaXggPSAnJyxcbiAgICBtb25nb09wdGlvbnMgPSB7fSxcbiAgfTogYW55KSB7XG4gICAgdGhpcy5fdXJpID0gdXJpO1xuICAgIHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggPSBjb2xsZWN0aW9uUHJlZml4O1xuICAgIHRoaXMuX21vbmdvT3B0aW9ucyA9IG1vbmdvT3B0aW9ucztcbiAgICB0aGlzLl9tb25nb09wdGlvbnMudXNlTmV3VXJsUGFyc2VyID0gdHJ1ZTtcbiAgICB0aGlzLl9tb25nb09wdGlvbnMudXNlVW5pZmllZFRvcG9sb2d5ID0gdHJ1ZTtcblxuICAgIC8vIE1heFRpbWVNUyBpcyBub3QgYSBnbG9iYWwgTW9uZ29EQiBjbGllbnQgb3B0aW9uLCBpdCBpcyBhcHBsaWVkIHBlciBvcGVyYXRpb24uXG4gICAgdGhpcy5fbWF4VGltZU1TID0gbW9uZ29PcHRpb25zLm1heFRpbWVNUztcbiAgICB0aGlzLmNhblNvcnRPbkpvaW5UYWJsZXMgPSB0cnVlO1xuICAgIGRlbGV0ZSBtb25nb09wdGlvbnMubWF4VGltZU1TO1xuICB9XG5cbiAgY29ubmVjdCgpIHtcbiAgICBpZiAodGhpcy5jb25uZWN0aW9uUHJvbWlzZSkge1xuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgfVxuXG4gICAgLy8gcGFyc2luZyBhbmQgcmUtZm9ybWF0dGluZyBjYXVzZXMgdGhlIGF1dGggdmFsdWUgKGlmIHRoZXJlKSB0byBnZXQgVVJJXG4gICAgLy8gZW5jb2RlZFxuICAgIGNvbnN0IGVuY29kZWRVcmkgPSBmb3JtYXRVcmwocGFyc2VVcmwodGhpcy5fdXJpKSk7XG5cbiAgICB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlID0gTW9uZ29DbGllbnQuY29ubmVjdChlbmNvZGVkVXJpLCB0aGlzLl9tb25nb09wdGlvbnMpXG4gICAgICAudGhlbihjbGllbnQgPT4ge1xuICAgICAgICAvLyBTdGFydGluZyBtb25nb0RCIDMuMCwgdGhlIE1vbmdvQ2xpZW50LmNvbm5lY3QgZG9uJ3QgcmV0dXJuIGEgREIgYW55bW9yZSBidXQgYSBjbGllbnRcbiAgICAgICAgLy8gRm9ydHVuYXRlbHksIHdlIGNhbiBnZXQgYmFjayB0aGUgb3B0aW9ucyBhbmQgdXNlIHRoZW0gdG8gc2VsZWN0IHRoZSBwcm9wZXIgREIuXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb25nb2RiL25vZGUtbW9uZ29kYi1uYXRpdmUvYmxvYi8yYzM1ZDc2ZjA4NTc0MjI1YjhkYjAyZDdiZWY2ODcxMjNlNmJiMDE4L2xpYi9tb25nb19jbGllbnQuanMjTDg4NVxuICAgICAgICBjb25zdCBvcHRpb25zID0gY2xpZW50LnMub3B0aW9ucztcbiAgICAgICAgY29uc3QgZGF0YWJhc2UgPSBjbGllbnQuZGIob3B0aW9ucy5kYk5hbWUpO1xuICAgICAgICBpZiAoIWRhdGFiYXNlKSB7XG4gICAgICAgICAgZGVsZXRlIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGRhdGFiYXNlLm9uKCdlcnJvcicsICgpID0+IHtcbiAgICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGRhdGFiYXNlLm9uKCdjbG9zZScsICgpID0+IHtcbiAgICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY2xpZW50ID0gY2xpZW50O1xuICAgICAgICB0aGlzLmRhdGFiYXNlID0gZGF0YWJhc2U7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gIH1cblxuICBoYW5kbGVFcnJvcjxUPihlcnJvcjogPyhFcnJvciB8IFBhcnNlLkVycm9yKSk6IFByb21pc2U8VD4ge1xuICAgIGlmIChlcnJvciAmJiBlcnJvci5jb2RlID09PSAxMykge1xuICAgICAgLy8gVW5hdXRob3JpemVkIGVycm9yXG4gICAgICBkZWxldGUgdGhpcy5jbGllbnQ7XG4gICAgICBkZWxldGUgdGhpcy5kYXRhYmFzZTtcbiAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgbG9nZ2VyLmVycm9yKCdSZWNlaXZlZCB1bmF1dGhvcml6ZWQgZXJyb3InLCB7IGVycm9yOiBlcnJvciB9KTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBoYW5kbGVTaHV0ZG93bigpIHtcbiAgICBpZiAoIXRoaXMuY2xpZW50KSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNsaWVudC5jbG9zZShmYWxzZSk7XG4gIH1cblxuICBfYWRhcHRpdmVDb2xsZWN0aW9uKG5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3QoKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5kYXRhYmFzZS5jb2xsZWN0aW9uKHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggKyBuYW1lKSlcbiAgICAgIC50aGVuKHJhd0NvbGxlY3Rpb24gPT4gbmV3IE1vbmdvQ29sbGVjdGlvbihyYXdDb2xsZWN0aW9uKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIF9zY2hlbWFDb2xsZWN0aW9uKCk6IFByb21pc2U8TW9uZ29TY2hlbWFDb2xsZWN0aW9uPiB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdCgpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSkpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IG5ldyBNb25nb1NjaGVtYUNvbGxlY3Rpb24oY29sbGVjdGlvbikpO1xuICB9XG5cbiAgY2xhc3NFeGlzdHMobmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdCgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGFiYXNlXG4gICAgICAgICAgLmxpc3RDb2xsZWN0aW9ucyh7IG5hbWU6IHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggKyBuYW1lIH0pXG4gICAgICAgICAgLnRvQXJyYXkoKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9ucy5sZW5ndGggPiAwO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWU6IHN0cmluZywgQ0xQczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PlxuICAgICAgICBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuY2xhc3NfcGVybWlzc2lvbnMnOiBDTFBzIH0sXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzdWJtaXR0ZWRJbmRleGVzOiBhbnksXG4gICAgZXhpc3RpbmdJbmRleGVzOiBhbnkgPSB7fSxcbiAgICBmaWVsZHM6IGFueVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoc3VibWl0dGVkSW5kZXhlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIGlmIChPYmplY3Qua2V5cyhleGlzdGluZ0luZGV4ZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZXhpc3RpbmdJbmRleGVzID0geyBfaWRfOiB7IF9pZDogMSB9IH07XG4gICAgfVxuICAgIGNvbnN0IGRlbGV0ZVByb21pc2VzID0gW107XG4gICAgY29uc3QgaW5zZXJ0ZWRJbmRleGVzID0gW107XG4gICAgT2JqZWN0LmtleXMoc3VibWl0dGVkSW5kZXhlcykuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkID0gc3VibWl0dGVkSW5kZXhlc1tuYW1lXTtcbiAgICAgIGlmIChleGlzdGluZ0luZGV4ZXNbbmFtZV0gJiYgZmllbGQuX19vcCAhPT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgYEluZGV4ICR7bmFtZX0gZXhpc3RzLCBjYW5ub3QgdXBkYXRlLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmICghZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgIGBJbmRleCAke25hbWV9IGRvZXMgbm90IGV4aXN0LCBjYW5ub3QgZGVsZXRlLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmIChmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5kcm9wSW5kZXgoY2xhc3NOYW1lLCBuYW1lKTtcbiAgICAgICAgZGVsZXRlUHJvbWlzZXMucHVzaChwcm9taXNlKTtcbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nSW5kZXhlc1tuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGZpZWxkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZmllbGRzLCBrZXkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgICAgIGBGaWVsZCAke2tleX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBhZGQgaW5kZXguYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBleGlzdGluZ0luZGV4ZXNbbmFtZV0gPSBmaWVsZDtcbiAgICAgICAgaW5zZXJ0ZWRJbmRleGVzLnB1c2goe1xuICAgICAgICAgIGtleTogZmllbGQsXG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgbGV0IGluc2VydFByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBpZiAoaW5zZXJ0ZWRJbmRleGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGluc2VydFByb21pc2UgPSB0aGlzLmNyZWF0ZUluZGV4ZXMoY2xhc3NOYW1lLCBpbnNlcnRlZEluZGV4ZXMpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoZGVsZXRlUHJvbWlzZXMpXG4gICAgICAudGhlbigoKSA9PiBpbnNlcnRQcm9taXNlKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PlxuICAgICAgICBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuaW5kZXhlcyc6IGV4aXN0aW5nSW5kZXhlcyB9LFxuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgc2V0SW5kZXhlc0Zyb21Nb25nbyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmdldEluZGV4ZXMoY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oaW5kZXhlcyA9PiB7XG4gICAgICAgIGluZGV4ZXMgPSBpbmRleGVzLnJlZHVjZSgob2JqLCBpbmRleCkgPT4ge1xuICAgICAgICAgIGlmIChpbmRleC5rZXkuX2Z0cykge1xuICAgICAgICAgICAgZGVsZXRlIGluZGV4LmtleS5fZnRzO1xuICAgICAgICAgICAgZGVsZXRlIGluZGV4LmtleS5fZnRzeDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gaW5kZXgud2VpZ2h0cykge1xuICAgICAgICAgICAgICBpbmRleC5rZXlbZmllbGRdID0gJ3RleHQnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBvYmpbaW5kZXgubmFtZV0gPSBpbmRleC5rZXk7XG4gICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgfSwge30pO1xuICAgICAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PlxuICAgICAgICAgIHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAgICAgJHNldDogeyAnX21ldGFkYXRhLmluZGV4ZXMnOiBpbmRleGVzIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSlcbiAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgIC8vIElnbm9yZSBpZiBjb2xsZWN0aW9uIG5vdCBmb3VuZFxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZUNsYXNzKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29PYmplY3QgPSBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWVBbmRDTFAoXG4gICAgICBzY2hlbWEuZmllbGRzLFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgc2NoZW1hLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgICAgIHNjaGVtYS5pbmRleGVzXG4gICAgKTtcbiAgICBtb25nb09iamVjdC5faWQgPSBjbGFzc05hbWU7XG4gICAgcmV0dXJuIHRoaXMuc2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQoXG4gICAgICBjbGFzc05hbWUsXG4gICAgICBzY2hlbWEuaW5kZXhlcyxcbiAgICAgIHt9LFxuICAgICAgc2NoZW1hLmZpZWxkc1xuICAgIClcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKSlcbiAgICAgIC50aGVuKHNjaGVtYUNvbGxlY3Rpb24gPT4gc2NoZW1hQ29sbGVjdGlvbi5pbnNlcnRTY2hlbWEobW9uZ29PYmplY3QpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgYWRkRmllbGRJZk5vdEV4aXN0cyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBmaWVsZE5hbWU6IHN0cmluZyxcbiAgICB0eXBlOiBhbnlcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PlxuICAgICAgICBzY2hlbWFDb2xsZWN0aW9uLmFkZEZpZWxkSWZOb3RFeGlzdHMoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHR5cGUpXG4gICAgICApXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmNyZWF0ZUluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBEcm9wcyBhIGNvbGxlY3Rpb24uIFJlc29sdmVzIHdpdGggdHJ1ZSBpZiBpdCB3YXMgYSBQYXJzZSBTY2hlbWEgKGVnLiBfVXNlciwgQ3VzdG9tLCBldGMuKVxuICAvLyBhbmQgcmVzb2x2ZXMgd2l0aCBmYWxzZSBpZiBpdCB3YXNuJ3QgKGVnLiBhIGpvaW4gdGFibGUpLiBSZWplY3RzIGlmIGRlbGV0aW9uIHdhcyBpbXBvc3NpYmxlLlxuICBkZWxldGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uZHJvcCgpKVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIC8vICducyBub3QgZm91bmQnIG1lYW5zIGNvbGxlY3Rpb24gd2FzIGFscmVhZHkgZ29uZS4gSWdub3JlIGRlbGV0aW9uIGF0dGVtcHQuXG4gICAgICAgICAgaWYgKGVycm9yLm1lc3NhZ2UgPT0gJ25zIG5vdCBmb3VuZCcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH0pXG4gICAgICAgIC8vIFdlJ3ZlIGRyb3BwZWQgdGhlIGNvbGxlY3Rpb24sIG5vdyByZW1vdmUgdGhlIF9TQ0hFTUEgZG9jdW1lbnRcbiAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+XG4gICAgICAgICAgc2NoZW1hQ29sbGVjdGlvbi5maW5kQW5kRGVsZXRlU2NoZW1hKGNsYXNzTmFtZSlcbiAgICAgICAgKVxuICAgICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSlcbiAgICApO1xuICB9XG5cbiAgZGVsZXRlQWxsQ2xhc3NlcyhmYXN0OiBib29sZWFuKSB7XG4gICAgcmV0dXJuIHN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnModGhpcykudGhlbihjb2xsZWN0aW9ucyA9PlxuICAgICAgUHJvbWlzZS5hbGwoXG4gICAgICAgIGNvbGxlY3Rpb25zLm1hcChjb2xsZWN0aW9uID0+XG4gICAgICAgICAgZmFzdCA/IGNvbGxlY3Rpb24uZGVsZXRlTWFueSh7fSkgOiBjb2xsZWN0aW9uLmRyb3AoKVxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSB0aGUgY29sdW1uIGFuZCBhbGwgdGhlIGRhdGEuIEZvciBSZWxhdGlvbnMsIHRoZSBfSm9pbiBjb2xsZWN0aW9uIGlzIGhhbmRsZWRcbiAgLy8gc3BlY2lhbGx5LCB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IGRlbGV0ZSBfSm9pbiBjb2x1bW5zLiBJdCBzaG91bGQsIGhvd2V2ZXIsIGluZGljYXRlXG4gIC8vIHRoYXQgdGhlIHJlbGF0aW9uIGZpZWxkcyBkb2VzIG5vdCBleGlzdCBhbnltb3JlLiBJbiBtb25nbywgdGhpcyBtZWFucyByZW1vdmluZyBpdCBmcm9tXG4gIC8vIHRoZSBfU0NIRU1BIGNvbGxlY3Rpb24uICBUaGVyZSBzaG91bGQgYmUgbm8gYWN0dWFsIGRhdGEgaW4gdGhlIGNvbGxlY3Rpb24gdW5kZXIgdGhlIHNhbWUgbmFtZVxuICAvLyBhcyB0aGUgcmVsYXRpb24gY29sdW1uLCBzbyBpdCdzIGZpbmUgdG8gYXR0ZW1wdCB0byBkZWxldGUgaXQuIElmIHRoZSBmaWVsZHMgbGlzdGVkIHRvIGJlXG4gIC8vIGRlbGV0ZWQgZG8gbm90IGV4aXN0LCB0aGlzIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gc3VjY2Vzc2Z1bGx5IGFueXdheXMuIENoZWNraW5nIGZvclxuICAvLyBhdHRlbXB0cyB0byBkZWxldGUgbm9uLWV4aXN0ZW50IGZpZWxkcyBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgUGFyc2UgU2VydmVyLlxuXG4gIC8vIFBvaW50ZXIgZmllbGQgbmFtZXMgYXJlIHBhc3NlZCBmb3IgbGVnYWN5IHJlYXNvbnM6IHRoZSBvcmlnaW5hbCBtb25nb1xuICAvLyBmb3JtYXQgc3RvcmVkIHBvaW50ZXIgZmllbGQgbmFtZXMgZGlmZmVyZW50bHkgaW4gdGhlIGRhdGFiYXNlLCBhbmQgdGhlcmVmb3JlXG4gIC8vIG5lZWRlZCB0byBrbm93IHRoZSB0eXBlIG9mIHRoZSBmaWVsZCBiZWZvcmUgaXQgY291bGQgZGVsZXRlIGl0LiBGdXR1cmUgZGF0YWJhc2VcbiAgLy8gYWRhcHRlcnMgc2hvdWxkIGlnbm9yZSB0aGUgcG9pbnRlckZpZWxkTmFtZXMgYXJndW1lbnQuIEFsbCB0aGUgZmllbGQgbmFtZXMgYXJlIGluXG4gIC8vIGZpZWxkTmFtZXMsIHRoZXkgc2hvdyB1cCBhZGRpdGlvbmFsbHkgaW4gdGhlIHBvaW50ZXJGaWVsZE5hbWVzIGRhdGFiYXNlIGZvciB1c2VcbiAgLy8gYnkgdGhlIG1vbmdvIGFkYXB0ZXIsIHdoaWNoIGRlYWxzIHdpdGggdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQuXG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBub3Qgb2JsaWdhdGVkIHRvIGRlbGV0ZSBmaWVsZHMgYXRvbWljYWxseS4gSXQgaXMgZ2l2ZW4gdGhlIGZpZWxkXG4gIC8vIG5hbWVzIGluIGEgbGlzdCBzbyB0aGF0IGRhdGFiYXNlcyB0aGF0IGFyZSBjYXBhYmxlIG9mIGRlbGV0aW5nIGZpZWxkcyBhdG9taWNhbGx5XG4gIC8vIG1heSBkbyBzby5cblxuICAvLyBSZXR1cm5zIGEgUHJvbWlzZS5cbiAgZGVsZXRlRmllbGRzKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGZpZWxkTmFtZXM6IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgbW9uZ29Gb3JtYXROYW1lcyA9IGZpZWxkTmFtZXMubWFwKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm4gYF9wXyR7ZmllbGROYW1lfWA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZmllbGROYW1lO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGNvbnN0IGNvbGxlY3Rpb25VcGRhdGUgPSB7ICR1bnNldDoge30gfTtcbiAgICBtb25nb0Zvcm1hdE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb2xsZWN0aW9uVXBkYXRlWyckdW5zZXQnXVtuYW1lXSA9IG51bGw7XG4gICAgfSk7XG5cbiAgICBjb25zdCBzY2hlbWFVcGRhdGUgPSB7ICR1bnNldDoge30gfTtcbiAgICBmaWVsZE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBzY2hlbWFVcGRhdGVbJyR1bnNldCddW25hbWVdID0gbnVsbDtcbiAgICAgIHNjaGVtYVVwZGF0ZVsnJHVuc2V0J11bYF9tZXRhZGF0YS5maWVsZHNfb3B0aW9ucy4ke25hbWV9YF0gPSBudWxsO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24udXBkYXRlTWFueSh7fSwgY29sbGVjdGlvblVwZGF0ZSkpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+XG4gICAgICAgIHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwgc2NoZW1hVXBkYXRlKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgYWxsIHNjaGVtYXMga25vd24gdG8gdGhpcyBhZGFwdGVyLCBpbiBQYXJzZSBmb3JtYXQuIEluIGNhc2UgdGhlXG4gIC8vIHNjaGVtYXMgY2Fubm90IGJlIHJldHJpZXZlZCwgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZWplY3RzLiBSZXF1aXJlbWVudHMgZm9yIHRoZVxuICAvLyByZWplY3Rpb24gcmVhc29uIGFyZSBUQkQuXG4gIGdldEFsbENsYXNzZXMoKTogUHJvbWlzZTxTdG9yYWdlQ2xhc3NbXT4ge1xuICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgIC50aGVuKHNjaGVtYXNDb2xsZWN0aW9uID0+XG4gICAgICAgIHNjaGVtYXNDb2xsZWN0aW9uLl9mZXRjaEFsbFNjaGVtYXNGcm9tX1NDSEVNQSgpXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBSZXR1cm4gYSBwcm9taXNlIGZvciB0aGUgc2NoZW1hIHdpdGggdGhlIGdpdmVuIG5hbWUsIGluIFBhcnNlIGZvcm1hdC4gSWZcbiAgLy8gdGhpcyBhZGFwdGVyIGRvZXNuJ3Qga25vdyBhYm91dCB0aGUgc2NoZW1hLCByZXR1cm4gYSBwcm9taXNlIHRoYXQgcmVqZWN0cyB3aXRoXG4gIC8vIHVuZGVmaW5lZCBhcyB0aGUgcmVhc29uLlxuICBnZXRDbGFzcyhjbGFzc05hbWU6IHN0cmluZyk6IFByb21pc2U8U3RvcmFnZUNsYXNzPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hc0NvbGxlY3Rpb24gPT5cbiAgICAgICAgc2NoZW1hc0NvbGxlY3Rpb24uX2ZldGNoT25lU2NoZW1hRnJvbV9TQ0hFTUEoY2xhc3NOYW1lKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVE9ETzogQXMgeWV0IG5vdCBwYXJ0aWN1bGFybHkgd2VsbCBzcGVjaWZpZWQuIENyZWF0ZXMgYW4gb2JqZWN0LiBNYXliZSBzaG91bGRuJ3QgZXZlbiBuZWVkIHRoZSBzY2hlbWEsXG4gIC8vIGFuZCBzaG91bGQgaW5mZXIgZnJvbSB0aGUgdHlwZS4gT3IgbWF5YmUgZG9lcyBuZWVkIHRoZSBzY2hlbWEgZm9yIHZhbGlkYXRpb25zLiBPciBtYXliZSBuZWVkc1xuICAvLyB0aGUgc2NoZW1hIG9ubHkgZm9yIHRoZSBsZWdhY3kgbW9uZ28gZm9ybWF0LiBXZSdsbCBmaWd1cmUgdGhhdCBvdXQgbGF0ZXIuXG4gIGNyZWF0ZU9iamVjdChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgb2JqZWN0OiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvT2JqZWN0ID0gcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlKFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgb2JqZWN0LFxuICAgICAgc2NoZW1hXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5pbnNlcnRPbmUobW9uZ29PYmplY3QsIHRyYW5zYWN0aW9uYWxTZXNzaW9uKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDExMDAwKSB7XG4gICAgICAgICAgLy8gRHVwbGljYXRlIHZhbHVlXG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLFxuICAgICAgICAgICAgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnXG4gICAgICAgICAgKTtcbiAgICAgICAgICBlcnIudW5kZXJseWluZ0Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgaWYgKGVycm9yLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBlcnJvci5tZXNzYWdlLm1hdGNoKFxuICAgICAgICAgICAgICAvaW5kZXg6W1xcc2EtekEtWjAtOV9cXC1cXC5dK1xcJD8oW2EtekEtWl8tXSspXzEvXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKG1hdGNoZXMgJiYgQXJyYXkuaXNBcnJheShtYXRjaGVzKSkge1xuICAgICAgICAgICAgICBlcnIudXNlckluZm8gPSB7IGR1cGxpY2F0ZWRfZmllbGQ6IG1hdGNoZXNbMV0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgLy8gSWYgbm8gb2JqZWN0cyBtYXRjaCwgcmVqZWN0IHdpdGggT0JKRUNUX05PVF9GT1VORC4gSWYgb2JqZWN0cyBhcmUgZm91bmQgYW5kIGRlbGV0ZWQsIHJlc29sdmUgd2l0aCB1bmRlZmluZWQuXG4gIC8vIElmIHRoZXJlIGlzIHNvbWUgb3RoZXIgZXJyb3IsIHJlamVjdCB3aXRoIElOVEVSTkFMX1NFUlZFUl9FUlJPUi5cbiAgZGVsZXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiB7XG4gICAgICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbi5kZWxldGVNYW55KG1vbmdvV2hlcmUsIHRyYW5zYWN0aW9uYWxTZXNzaW9uKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSlcbiAgICAgIC50aGVuKFxuICAgICAgICAoeyByZXN1bHQgfSkgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQubiA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH0sXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgICAgICAnRGF0YWJhc2UgYWRhcHRlciBlcnJvcidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICApO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgdXBkYXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvVXBkYXRlID0gdHJhbnNmb3JtVXBkYXRlKGNsYXNzTmFtZSwgdXBkYXRlLCBzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PlxuICAgICAgICBjb2xsZWN0aW9uLnVwZGF0ZU1hbnkobW9uZ29XaGVyZSwgbW9uZ29VcGRhdGUsIHRyYW5zYWN0aW9uYWxTZXNzaW9uKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gQXRvbWljYWxseSBmaW5kcyBhbmQgdXBkYXRlcyBhbiBvYmplY3QgYmFzZWQgb24gcXVlcnkuXG4gIC8vIFJldHVybiB2YWx1ZSBub3QgY3VycmVudGx5IHdlbGwgc3BlY2lmaWVkLlxuICBmaW5kT25lQW5kVXBkYXRlKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHVwZGF0ZTogYW55LFxuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uOiA/YW55XG4gICkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmZpbmRPbmVBbmRVcGRhdGUobW9uZ29XaGVyZSwgbW9uZ29VcGRhdGUsIHtcbiAgICAgICAgICByZXR1cm5PcmlnaW5hbDogZmFsc2UsXG4gICAgICAgICAgc2Vzc2lvbjogdHJhbnNhY3Rpb25hbFNlc3Npb24gfHwgdW5kZWZpbmVkLFxuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIHJlc3VsdC52YWx1ZSwgc2NoZW1hKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSxcbiAgICAgICAgICAgICdBIGR1cGxpY2F0ZSB2YWx1ZSBmb3IgYSBmaWVsZCB3aXRoIHVuaXF1ZSB2YWx1ZXMgd2FzIHByb3ZpZGVkJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gSG9wZWZ1bGx5IHdlIGNhbiBnZXQgcmlkIG9mIHRoaXMuIEl0J3Mgb25seSB1c2VkIGZvciBjb25maWcgYW5kIGhvb2tzLlxuICB1cHNlcnRPbmVPYmplY3QoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvVXBkYXRlID0gdHJhbnNmb3JtVXBkYXRlKGNsYXNzTmFtZSwgdXBkYXRlLCBzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PlxuICAgICAgICBjb2xsZWN0aW9uLnVwc2VydE9uZShtb25nb1doZXJlLCBtb25nb1VwZGF0ZSwgdHJhbnNhY3Rpb25hbFNlc3Npb24pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGZpbmQuIEFjY2VwdHM6IGNsYXNzTmFtZSwgcXVlcnkgaW4gUGFyc2UgZm9ybWF0LCBhbmQgeyBza2lwLCBsaW1pdCwgc29ydCB9LlxuICBmaW5kKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHsgc2tpcCwgbGltaXQsIHNvcnQsIGtleXMsIHJlYWRQcmVmZXJlbmNlIH06IFF1ZXJ5T3B0aW9uc1xuICApOiBQcm9taXNlPGFueT4ge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1NvcnQgPSBfLm1hcEtleXMoc29ydCwgKHZhbHVlLCBmaWVsZE5hbWUpID0+XG4gICAgICB0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHNjaGVtYSlcbiAgICApO1xuICAgIGNvbnN0IG1vbmdvS2V5cyA9IF8ucmVkdWNlKFxuICAgICAga2V5cyxcbiAgICAgIChtZW1vLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKGtleSA9PT0gJ0FDTCcpIHtcbiAgICAgICAgICBtZW1vWydfcnBlcm0nXSA9IDE7XG4gICAgICAgICAgbWVtb1snX3dwZXJtJ10gPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG1lbW9bdHJhbnNmb3JtS2V5KGNsYXNzTmFtZSwga2V5LCBzY2hlbWEpXSA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1lbW87XG4gICAgICB9LFxuICAgICAge31cbiAgICApO1xuXG4gICAgcmVhZFByZWZlcmVuY2UgPSB0aGlzLl9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gdGhpcy5jcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PlxuICAgICAgICBjb2xsZWN0aW9uLmZpbmQobW9uZ29XaGVyZSwge1xuICAgICAgICAgIHNraXAsXG4gICAgICAgICAgbGltaXQsXG4gICAgICAgICAgc29ydDogbW9uZ29Tb3J0LFxuICAgICAgICAgIGtleXM6IG1vbmdvS2V5cyxcbiAgICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC50aGVuKG9iamVjdHMgPT5cbiAgICAgICAgb2JqZWN0cy5tYXAob2JqZWN0ID0+XG4gICAgICAgICAgbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpXG4gICAgICAgIClcbiAgICAgIClcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIHVuaXF1ZSBpbmRleC4gVW5pcXVlIGluZGV4ZXMgb24gbnVsbGFibGUgZmllbGRzIGFyZSBub3QgYWxsb3dlZC4gU2luY2Ugd2UgZG9uJ3RcbiAgLy8gY3VycmVudGx5IGtub3cgd2hpY2ggZmllbGRzIGFyZSBudWxsYWJsZSBhbmQgd2hpY2ggYXJlbid0LCB3ZSBpZ25vcmUgdGhhdCBjcml0ZXJpYS5cbiAgLy8gQXMgc3VjaCwgd2Ugc2hvdWxkbid0IGV4cG9zZSB0aGlzIGZ1bmN0aW9uIHRvIHVzZXJzIG9mIHBhcnNlIHVudGlsIHdlIGhhdmUgYW4gb3V0LW9mLWJhbmRcbiAgLy8gV2F5IG9mIGRldGVybWluaW5nIGlmIGEgZmllbGQgaXMgbnVsbGFibGUuIFVuZGVmaW5lZCBkb2Vzbid0IGNvdW50IGFnYWluc3QgdW5pcXVlbmVzcyxcbiAgLy8gd2hpY2ggaXMgd2h5IHdlIHVzZSBzcGFyc2UgaW5kZXhlcy5cbiAgZW5zdXJlVW5pcXVlbmVzcyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgZmllbGROYW1lczogc3RyaW5nW11cbiAgKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IGluZGV4Q3JlYXRpb25SZXF1ZXN0ID0ge307XG4gICAgY29uc3QgbW9uZ29GaWVsZE5hbWVzID0gZmllbGROYW1lcy5tYXAoZmllbGROYW1lID0+XG4gICAgICB0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHNjaGVtYSlcbiAgICApO1xuICAgIG1vbmdvRmllbGROYW1lcy5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpbmRleENyZWF0aW9uUmVxdWVzdFtmaWVsZE5hbWVdID0gMTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5fZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQoaW5kZXhDcmVhdGlvblJlcXVlc3QpXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTEwMDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsXG4gICAgICAgICAgICAnVHJpZWQgdG8gZW5zdXJlIGZpZWxkIHVuaXF1ZW5lc3MgZm9yIGEgY2xhc3MgdGhhdCBhbHJlYWR5IGhhcyBkdXBsaWNhdGVzLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFVzZWQgaW4gdGVzdHNcbiAgX3Jhd0ZpbmQoY2xhc3NOYW1lOiBzdHJpbmcsIHF1ZXJ5OiBRdWVyeVR5cGUpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5maW5kKHF1ZXJ5LCB7XG4gICAgICAgICAgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGNvdW50LlxuICBjb3VudChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgcXVlcnk6IFF1ZXJ5VHlwZSxcbiAgICByZWFkUHJlZmVyZW5jZTogP3N0cmluZ1xuICApIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgcmVhZFByZWZlcmVuY2UgPSB0aGlzLl9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5jb3VudCh0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEsIHRydWUpLCB7XG4gICAgICAgICAgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMsXG4gICAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkaXN0aW5jdChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgcXVlcnk6IFF1ZXJ5VHlwZSxcbiAgICBmaWVsZE5hbWU6IHN0cmluZ1xuICApIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgaXNQb2ludGVyRmllbGQgPVxuICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcic7XG4gICAgY29uc3QgdHJhbnNmb3JtRmllbGQgPSB0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHNjaGVtYSk7XG5cbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5kaXN0aW5jdChcbiAgICAgICAgICB0cmFuc2Zvcm1GaWVsZCxcbiAgICAgICAgICB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpXG4gICAgICAgIClcbiAgICAgIClcbiAgICAgIC50aGVuKG9iamVjdHMgPT4ge1xuICAgICAgICBvYmplY3RzID0gb2JqZWN0cy5maWx0ZXIob2JqID0+IG9iaiAhPSBudWxsKTtcbiAgICAgICAgcmV0dXJuIG9iamVjdHMubWFwKG9iamVjdCA9PiB7XG4gICAgICAgICAgaWYgKGlzUG9pbnRlckZpZWxkKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJhbnNmb3JtUG9pbnRlclN0cmluZyhzY2hlbWEsIGZpZWxkTmFtZSwgb2JqZWN0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgYWdncmVnYXRlKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogYW55LFxuICAgIHBpcGVsaW5lOiBhbnksXG4gICAgcmVhZFByZWZlcmVuY2U6ID9zdHJpbmdcbiAgKSB7XG4gICAgbGV0IGlzUG9pbnRlckZpZWxkID0gZmFsc2U7XG4gICAgcGlwZWxpbmUgPSBwaXBlbGluZS5tYXAoc3RhZ2UgPT4ge1xuICAgICAgaWYgKHN0YWdlLiRncm91cCkge1xuICAgICAgICBzdGFnZS4kZ3JvdXAgPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWEsIHN0YWdlLiRncm91cCk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBzdGFnZS4kZ3JvdXAuX2lkICYmXG4gICAgICAgICAgdHlwZW9mIHN0YWdlLiRncm91cC5faWQgPT09ICdzdHJpbmcnICYmXG4gICAgICAgICAgc3RhZ2UuJGdyb3VwLl9pZC5pbmRleE9mKCckX3BfJykgPj0gMFxuICAgICAgICApIHtcbiAgICAgICAgICBpc1BvaW50ZXJGaWVsZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kbWF0Y2gpIHtcbiAgICAgICAgc3RhZ2UuJG1hdGNoID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYSwgc3RhZ2UuJG1hdGNoKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kcHJvamVjdCkge1xuICAgICAgICBzdGFnZS4kcHJvamVjdCA9IHRoaXMuX3BhcnNlQWdncmVnYXRlUHJvamVjdEFyZ3MoXG4gICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgIHN0YWdlLiRwcm9qZWN0XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RhZ2U7XG4gICAgfSk7XG4gICAgcmVhZFByZWZlcmVuY2UgPSB0aGlzLl9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5hZ2dyZWdhdGUocGlwZWxpbmUsIHtcbiAgICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICByZXN1bHRzLmZvckVhY2gocmVzdWx0ID0+IHtcbiAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3VsdCwgJ19pZCcpKSB7XG4gICAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQgJiYgcmVzdWx0Ll9pZCkge1xuICAgICAgICAgICAgICByZXN1bHQuX2lkID0gcmVzdWx0Ll9pZC5zcGxpdCgnJCcpWzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICByZXN1bHQuX2lkID09IG51bGwgfHxcbiAgICAgICAgICAgICAgcmVzdWx0Ll9pZCA9PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgICAgKFsnb2JqZWN0JywgJ3N0cmluZyddLmluY2x1ZGVzKHR5cGVvZiByZXN1bHQuX2lkKSAmJlxuICAgICAgICAgICAgICAgIF8uaXNFbXB0eShyZXN1bHQuX2lkKSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICByZXN1bHQuX2lkID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdC5vYmplY3RJZCA9IHJlc3VsdC5faWQ7XG4gICAgICAgICAgICBkZWxldGUgcmVzdWx0Ll9pZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgIH0pXG4gICAgICAudGhlbihvYmplY3RzID0+XG4gICAgICAgIG9iamVjdHMubWFwKG9iamVjdCA9PlxuICAgICAgICAgIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKVxuICAgICAgICApXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIHdpbGwgcmVjdXJzaXZlbHkgdHJhdmVyc2UgdGhlIHBpcGVsaW5lIGFuZCBjb252ZXJ0IGFueSBQb2ludGVyIG9yIERhdGUgY29sdW1ucy5cbiAgLy8gSWYgd2UgZGV0ZWN0IGEgcG9pbnRlciBjb2x1bW4gd2Ugd2lsbCByZW5hbWUgdGhlIGNvbHVtbiBiZWluZyBxdWVyaWVkIGZvciB0byBtYXRjaCB0aGUgY29sdW1uXG4gIC8vIGluIHRoZSBkYXRhYmFzZS4gV2UgYWxzbyBtb2RpZnkgdGhlIHZhbHVlIHRvIHdoYXQgd2UgZXhwZWN0IHRoZSB2YWx1ZSB0byBiZSBpbiB0aGUgZGF0YWJhc2VcbiAgLy8gYXMgd2VsbC5cbiAgLy8gRm9yIGRhdGVzLCB0aGUgZHJpdmVyIGV4cGVjdHMgYSBEYXRlIG9iamVjdCwgYnV0IHdlIGhhdmUgYSBzdHJpbmcgY29taW5nIGluLiBTbyB3ZSdsbCBjb252ZXJ0XG4gIC8vIHRoZSBzdHJpbmcgdG8gYSBEYXRlIHNvIHRoZSBkcml2ZXIgY2FuIHBlcmZvcm0gdGhlIG5lY2Vzc2FyeSBjb21wYXJpc29uLlxuICAvL1xuICAvLyBUaGUgZ29hbCBvZiB0aGlzIG1ldGhvZCBpcyB0byBsb29rIGZvciB0aGUgXCJsZWF2ZXNcIiBvZiB0aGUgcGlwZWxpbmUgYW5kIGRldGVybWluZSBpZiBpdCBuZWVkc1xuICAvLyB0byBiZSBjb252ZXJ0ZWQuIFRoZSBwaXBlbGluZSBjYW4gaGF2ZSBhIGZldyBkaWZmZXJlbnQgZm9ybXMuIEZvciBtb3JlIGRldGFpbHMsIHNlZTpcbiAgLy8gICAgIGh0dHBzOi8vZG9jcy5tb25nb2RiLmNvbS9tYW51YWwvcmVmZXJlbmNlL29wZXJhdG9yL2FnZ3JlZ2F0aW9uL1xuICAvL1xuICAvLyBJZiB0aGUgcGlwZWxpbmUgaXMgYW4gYXJyYXksIGl0IG1lYW5zIHdlIGFyZSBwcm9iYWJseSBwYXJzaW5nIGFuICckYW5kJyBvciAnJG9yJyBvcGVyYXRvci4gSW5cbiAgLy8gdGhhdCBjYXNlIHdlIG5lZWQgdG8gbG9vcCB0aHJvdWdoIGFsbCBvZiBpdCdzIGNoaWxkcmVuIHRvIGZpbmQgdGhlIGNvbHVtbnMgYmVpbmcgb3BlcmF0ZWQgb24uXG4gIC8vIElmIHRoZSBwaXBlbGluZSBpcyBhbiBvYmplY3QsIHRoZW4gd2UnbGwgbG9vcCB0aHJvdWdoIHRoZSBrZXlzIGNoZWNraW5nIHRvIHNlZSBpZiB0aGUga2V5IG5hbWVcbiAgLy8gbWF0Y2hlcyBvbmUgb2YgdGhlIHNjaGVtYSBjb2x1bW5zLiBJZiBpdCBkb2VzIG1hdGNoIGEgY29sdW1uIGFuZCB0aGUgY29sdW1uIGlzIGEgUG9pbnRlciBvclxuICAvLyBhIERhdGUsIHRoZW4gd2UnbGwgY29udmVydCB0aGUgdmFsdWUgYXMgZGVzY3JpYmVkIGFib3ZlLlxuICAvL1xuICAvLyBBcyBtdWNoIGFzIEkgaGF0ZSByZWN1cnNpb24uLi50aGlzIHNlZW1lZCBsaWtlIGEgZ29vZCBmaXQgZm9yIGl0LiBXZSdyZSBlc3NlbnRpYWxseSB0cmF2ZXJzaW5nXG4gIC8vIGRvd24gYSB0cmVlIHRvIGZpbmQgYSBcImxlYWYgbm9kZVwiIGFuZCBjaGVja2luZyB0byBzZWUgaWYgaXQgbmVlZHMgdG8gYmUgY29udmVydGVkLlxuICBfcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBpZiAocGlwZWxpbmUgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShwaXBlbGluZSkpIHtcbiAgICAgIHJldHVybiBwaXBlbGluZS5tYXAodmFsdWUgPT4gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYSwgdmFsdWUpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwaXBlbGluZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGNvbnN0IHJldHVyblZhbHVlID0ge307XG4gICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIHBpcGVsaW5lKSB7XG4gICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHBpcGVsaW5lW2ZpZWxkXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIFBhc3Mgb2JqZWN0cyBkb3duIHRvIE1vbmdvREIuLi50aGlzIGlzIG1vcmUgdGhhbiBsaWtlbHkgYW4gJGV4aXN0cyBvcGVyYXRvci5cbiAgICAgICAgICAgIHJldHVyblZhbHVlW2BfcF8ke2ZpZWxkfWBdID0gcGlwZWxpbmVbZmllbGRdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZVtcbiAgICAgICAgICAgICAgYF9wXyR7ZmllbGR9YFxuICAgICAgICAgICAgXSA9IGAke3NjaGVtYS5maWVsZHNbZmllbGRdLnRhcmdldENsYXNzfSQke3BpcGVsaW5lW2ZpZWxkXX1gO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJlxuICAgICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGRdLnR5cGUgPT09ICdEYXRlJ1xuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9jb252ZXJ0VG9EYXRlKHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKFxuICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgcGlwZWxpbmVbZmllbGRdXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWVsZCA9PT0gJ29iamVjdElkJykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfaWQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfY3JlYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbJ191cGRhdGVkX2F0J10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gcGlwZWxpbmU7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIHNsaWdodGx5IGRpZmZlcmVudCB0aGFuIHRoZSBvbmUgYWJvdmUuIFJhdGhlciB0aGFuIHRyeWluZyB0byBjb21iaW5lIHRoZXNlXG4gIC8vIHR3byBmdW5jdGlvbnMgYW5kIG1ha2luZyB0aGUgY29kZSBldmVuIGhhcmRlciB0byB1bmRlcnN0YW5kLCBJIGRlY2lkZWQgdG8gc3BsaXQgaXQgdXAuIFRoZVxuICAvLyBkaWZmZXJlbmNlIHdpdGggdGhpcyBmdW5jdGlvbiBpcyB3ZSBhcmUgbm90IHRyYW5zZm9ybWluZyB0aGUgdmFsdWVzLCBvbmx5IHRoZSBrZXlzIG9mIHRoZVxuICAvLyBwaXBlbGluZS5cbiAgX3BhcnNlQWdncmVnYXRlUHJvamVjdEFyZ3Moc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnkpOiBhbnkge1xuICAgIGNvbnN0IHJldHVyblZhbHVlID0ge307XG4gICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGRdICYmIHNjaGVtYS5maWVsZHNbZmllbGRdLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IHBpcGVsaW5lW2ZpZWxkXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChmaWVsZCA9PT0gJ29iamVjdElkJykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX2lkJ10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX2NyZWF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgIHJldHVyblZhbHVlWydfdXBkYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIHNsaWdodGx5IGRpZmZlcmVudCB0aGFuIHRoZSB0d28gYWJvdmUuIE1vbmdvREIgJGdyb3VwIGFnZ3JlZ2F0ZSBsb29rcyBsaWtlOlxuICAvLyAgICAgeyAkZ3JvdXA6IHsgX2lkOiA8ZXhwcmVzc2lvbj4sIDxmaWVsZDE+OiB7IDxhY2N1bXVsYXRvcjE+IDogPGV4cHJlc3Npb24xPiB9LCAuLi4gfSB9XG4gIC8vIFRoZSA8ZXhwcmVzc2lvbj4gY291bGQgYmUgYSBjb2x1bW4gbmFtZSwgcHJlZml4ZWQgd2l0aCB0aGUgJyQnIGNoYXJhY3Rlci4gV2UnbGwgbG9vayBmb3JcbiAgLy8gdGhlc2UgPGV4cHJlc3Npb24+IGFuZCBjaGVjayB0byBzZWUgaWYgaXQgaXMgYSAnUG9pbnRlcicgb3IgaWYgaXQncyBvbmUgb2YgY3JlYXRlZEF0LFxuICAvLyB1cGRhdGVkQXQgb3Igb2JqZWN0SWQgYW5kIGNoYW5nZSBpdCBhY2NvcmRpbmdseS5cbiAgX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShwaXBlbGluZSkpIHtcbiAgICAgIHJldHVybiBwaXBlbGluZS5tYXAodmFsdWUgPT5cbiAgICAgICAgdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCB2YWx1ZSlcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhcbiAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgcGlwZWxpbmVbZmllbGRdXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCBmaWVsZCA9IHBpcGVsaW5lLnN1YnN0cmluZygxKTtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuIGAkX3BfJHtmaWVsZH1gO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICByZXR1cm4gJyRfY3JlYXRlZF9hdCc7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgIHJldHVybiAnJF91cGRhdGVkX2F0JztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBpcGVsaW5lO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGF0dGVtcHQgdG8gY29udmVydCB0aGUgcHJvdmlkZWQgdmFsdWUgdG8gYSBEYXRlIG9iamVjdC4gU2luY2UgdGhpcyBpcyBwYXJ0XG4gIC8vIG9mIGFuIGFnZ3JlZ2F0aW9uIHBpcGVsaW5lLCB0aGUgdmFsdWUgY2FuIGVpdGhlciBiZSBhIHN0cmluZyBvciBpdCBjYW4gYmUgYW5vdGhlciBvYmplY3Qgd2l0aFxuICAvLyBhbiBvcGVyYXRvciBpbiBpdCAobGlrZSAkZ3QsICRsdCwgZXRjKS4gQmVjYXVzZSBvZiB0aGlzIEkgZmVsdCBpdCB3YXMgZWFzaWVyIHRvIG1ha2UgdGhpcyBhXG4gIC8vIHJlY3Vyc2l2ZSBtZXRob2QgdG8gdHJhdmVyc2UgZG93biB0byB0aGUgXCJsZWFmIG5vZGVcIiB3aGljaCBpcyBnb2luZyB0byBiZSB0aGUgc3RyaW5nLlxuICBfY29udmVydFRvRGF0ZSh2YWx1ZTogYW55KTogYW55IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgIGZvciAoY29uc3QgZmllbGQgaW4gdmFsdWUpIHtcbiAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX2NvbnZlcnRUb0RhdGUodmFsdWVbZmllbGRdKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgX3BhcnNlUmVhZFByZWZlcmVuY2UocmVhZFByZWZlcmVuY2U6ID9zdHJpbmcpOiA/c3RyaW5nIHtcbiAgICBpZiAocmVhZFByZWZlcmVuY2UpIHtcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gcmVhZFByZWZlcmVuY2UudG9VcHBlckNhc2UoKTtcbiAgICB9XG4gICAgc3dpdGNoIChyZWFkUHJlZmVyZW5jZSkge1xuICAgICAgY2FzZSAnUFJJTUFSWSc6XG4gICAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdQUklNQVJZX1BSRUZFUlJFRCc6XG4gICAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWV9QUkVGRVJSRUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnU0VDT05EQVJZJzpcbiAgICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5TRUNPTkRBUlk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnU0VDT05EQVJZX1BSRUZFUlJFRCc6XG4gICAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuU0VDT05EQVJZX1BSRUZFUlJFRDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdORUFSRVNUJzpcbiAgICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5ORUFSRVNUO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgY2FzZSBudWxsOlxuICAgICAgY2FzZSAnJzpcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgICAnTm90IHN1cHBvcnRlZCByZWFkIHByZWZlcmVuY2UuJ1xuICAgICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICBwZXJmb3JtSW5pdGlhbGl6YXRpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXgoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4KGluZGV4KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4ZXMoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4ZXM6IGFueSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uY3JlYXRlSW5kZXhlcyhpbmRleGVzKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWU6IHN0cmluZywgZmllbGROYW1lOiBzdHJpbmcsIHR5cGU6IGFueSkge1xuICAgIGlmICh0eXBlICYmIHR5cGUudHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICBjb25zdCBpbmRleCA9IHtcbiAgICAgICAgW2ZpZWxkTmFtZV06ICcyZHNwaGVyZScsXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlSW5kZXgoY2xhc3NOYW1lLCBpbmRleCk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNyZWF0ZVRleHRJbmRleGVzSWZOZWVkZWQoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgcXVlcnk6IFF1ZXJ5VHlwZSxcbiAgICBzY2hlbWE6IGFueVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiBxdWVyeSkge1xuICAgICAgaWYgKCFxdWVyeVtmaWVsZE5hbWVdIHx8ICFxdWVyeVtmaWVsZE5hbWVdLiR0ZXh0KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZXhpc3RpbmdJbmRleGVzID0gc2NoZW1hLmluZGV4ZXM7XG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiBleGlzdGluZ0luZGV4ZXMpIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBleGlzdGluZ0luZGV4ZXNba2V5XTtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChpbmRleCwgZmllbGROYW1lKSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3QgaW5kZXhOYW1lID0gYCR7ZmllbGROYW1lfV90ZXh0YDtcbiAgICAgIGNvbnN0IHRleHRJbmRleCA9IHtcbiAgICAgICAgW2luZGV4TmFtZV06IHsgW2ZpZWxkTmFtZV06ICd0ZXh0JyB9LFxuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHRleHRJbmRleCxcbiAgICAgICAgZXhpc3RpbmdJbmRleGVzLFxuICAgICAgICBzY2hlbWEuZmllbGRzXG4gICAgICApLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDg1KSB7XG4gICAgICAgICAgLy8gSW5kZXggZXhpc3Qgd2l0aCBkaWZmZXJlbnQgb3B0aW9uc1xuICAgICAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNGcm9tTW9uZ28oY2xhc3NOYW1lKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBnZXRJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5pbmRleGVzKCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wSW5kZXgoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmRyb3BJbmRleChpbmRleCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wQWxsSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uZHJvcEluZGV4ZXMoKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzKCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QWxsQ2xhc3NlcygpXG4gICAgICAudGhlbihjbGFzc2VzID0+IHtcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBjbGFzc2VzLm1hcChzY2hlbWEgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNGcm9tTW9uZ28oc2NoZW1hLmNsYXNzTmFtZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uKCk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgdHJhbnNhY3Rpb25hbFNlY3Rpb24gPSB0aGlzLmNsaWVudC5zdGFydFNlc3Npb24oKTtcbiAgICB0cmFuc2FjdGlvbmFsU2VjdGlvbi5zdGFydFRyYW5zYWN0aW9uKCk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cmFuc2FjdGlvbmFsU2VjdGlvbik7XG4gIH1cblxuICBjb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbih0cmFuc2FjdGlvbmFsU2VjdGlvbjogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRyYW5zYWN0aW9uYWxTZWN0aW9uLmNvbW1pdFRyYW5zYWN0aW9uKCkudGhlbigoKSA9PiB7XG4gICAgICB0cmFuc2FjdGlvbmFsU2VjdGlvbi5lbmRTZXNzaW9uKCk7XG4gICAgfSk7XG4gIH1cblxuICBhYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uKHRyYW5zYWN0aW9uYWxTZWN0aW9uOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdHJhbnNhY3Rpb25hbFNlY3Rpb24uYWJvcnRUcmFuc2FjdGlvbigpLnRoZW4oKCkgPT4ge1xuICAgICAgdHJhbnNhY3Rpb25hbFNlY3Rpb24uZW5kU2Vzc2lvbigpO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1vbmdvU3RvcmFnZUFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoTransform.js b/lib/Adapters/Storage/Mongo/MongoTransform.js new file mode 100644 index 0000000000..373f7cf462 --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoTransform.js @@ -0,0 +1,1795 @@ +"use strict"; + +var _logger = _interopRequireDefault(require("../../../logger")); + +var _lodash = _interopRequireDefault(require("lodash")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var mongodb = require('mongodb'); + +var Parse = require('parse/node').Parse; + +const transformKey = (className, fieldName, schema) => { + // Check if the schema is known since it's a built-in field. + switch (fieldName) { + case 'objectId': + return '_id'; + + case 'createdAt': + return '_created_at'; + + case 'updatedAt': + return '_updated_at'; + + case 'sessionToken': + return '_session_token'; + + case 'lastUsed': + return '_last_used'; + + case 'timesUsed': + return 'times_used'; + } + + if (schema.fields[fieldName] && schema.fields[fieldName].__type == 'Pointer') { + fieldName = '_p_' + fieldName; + } else if (schema.fields[fieldName] && schema.fields[fieldName].type == 'Pointer') { + fieldName = '_p_' + fieldName; + } + + return fieldName; +}; + +const transformKeyValueForUpdate = (className, restKey, restValue, parseFormatSchema) => { + // Check if the schema is known since it's a built-in field. + var key = restKey; + var timeField = false; + + switch (key) { + case 'objectId': + case '_id': + if (['_GlobalConfig', '_GraphQLConfig'].includes(className)) { + return { + key: key, + value: parseInt(restValue) + }; + } + + key = '_id'; + break; + + case 'createdAt': + case '_created_at': + key = '_created_at'; + timeField = true; + break; + + case 'updatedAt': + case '_updated_at': + key = '_updated_at'; + timeField = true; + break; + + case 'sessionToken': + case '_session_token': + key = '_session_token'; + break; + + case 'expiresAt': + case '_expiresAt': + key = 'expiresAt'; + timeField = true; + break; + + case '_email_verify_token_expires_at': + key = '_email_verify_token_expires_at'; + timeField = true; + break; + + case '_account_lockout_expires_at': + key = '_account_lockout_expires_at'; + timeField = true; + break; + + case '_failed_login_count': + key = '_failed_login_count'; + break; + + case '_perishable_token_expires_at': + key = '_perishable_token_expires_at'; + timeField = true; + break; + + case '_password_changed_at': + key = '_password_changed_at'; + timeField = true; + break; + + case '_rperm': + case '_wperm': + return { + key: key, + value: restValue + }; + + case 'lastUsed': + case '_last_used': + key = '_last_used'; + timeField = true; + break; + + case 'timesUsed': + case 'times_used': + key = 'times_used'; + timeField = true; + break; + } + + if (parseFormatSchema.fields[key] && parseFormatSchema.fields[key].type === 'Pointer' || !parseFormatSchema.fields[key] && restValue && restValue.__type == 'Pointer') { + key = '_p_' + key; + } // Handle atomic values + + + var value = transformTopLevelAtom(restValue); + + if (value !== CannotTransform) { + if (timeField && typeof value === 'string') { + value = new Date(value); + } + + if (restKey.indexOf('.') > 0) { + return { + key, + value: restValue + }; + } + + return { + key, + value + }; + } // Handle arrays + + + if (restValue instanceof Array) { + value = restValue.map(transformInteriorValue); + return { + key, + value + }; + } // Handle update operators + + + if (typeof restValue === 'object' && '__op' in restValue) { + return { + key, + value: transformUpdateOperator(restValue, false) + }; + } // Handle normal objects by recursing + + + value = mapValues(restValue, transformInteriorValue); + return { + key, + value + }; +}; + +const isRegex = value => { + return value && value instanceof RegExp; +}; + +const isStartsWithRegex = value => { + if (!isRegex(value)) { + return false; + } + + const matches = value.toString().match(/\/\^\\Q.*\\E\//); + return !!matches; +}; + +const isAllValuesRegexOrNone = values => { + if (!values || !Array.isArray(values) || values.length === 0) { + return true; + } + + const firstValuesIsRegex = isStartsWithRegex(values[0]); + + if (values.length === 1) { + return firstValuesIsRegex; + } + + for (let i = 1, length = values.length; i < length; ++i) { + if (firstValuesIsRegex !== isStartsWithRegex(values[i])) { + return false; + } + } + + return true; +}; + +const isAnyValueRegex = values => { + return values.some(function (value) { + return isRegex(value); + }); +}; + +const transformInteriorValue = restValue => { + if (restValue !== null && typeof restValue === 'object' && Object.keys(restValue).some(key => key.includes('$') || key.includes('.'))) { + throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); + } // Handle atomic values + + + var value = transformInteriorAtom(restValue); + + if (value !== CannotTransform) { + return value; + } // Handle arrays + + + if (restValue instanceof Array) { + return restValue.map(transformInteriorValue); + } // Handle update operators + + + if (typeof restValue === 'object' && '__op' in restValue) { + return transformUpdateOperator(restValue, true); + } // Handle normal objects by recursing + + + return mapValues(restValue, transformInteriorValue); +}; + +const valueAsDate = value => { + if (typeof value === 'string') { + return new Date(value); + } else if (value instanceof Date) { + return value; + } + + return false; +}; + +function transformQueryKeyValue(className, key, value, schema, count = false) { + switch (key) { + case 'createdAt': + if (valueAsDate(value)) { + return { + key: '_created_at', + value: valueAsDate(value) + }; + } + + key = '_created_at'; + break; + + case 'updatedAt': + if (valueAsDate(value)) { + return { + key: '_updated_at', + value: valueAsDate(value) + }; + } + + key = '_updated_at'; + break; + + case 'expiresAt': + if (valueAsDate(value)) { + return { + key: 'expiresAt', + value: valueAsDate(value) + }; + } + + break; + + case '_email_verify_token_expires_at': + if (valueAsDate(value)) { + return { + key: '_email_verify_token_expires_at', + value: valueAsDate(value) + }; + } + + break; + + case 'objectId': + { + if (['_GlobalConfig', '_GraphQLConfig'].includes(className)) { + value = parseInt(value); + } + + return { + key: '_id', + value + }; + } + + case '_account_lockout_expires_at': + if (valueAsDate(value)) { + return { + key: '_account_lockout_expires_at', + value: valueAsDate(value) + }; + } + + break; + + case '_failed_login_count': + return { + key, + value + }; + + case 'sessionToken': + return { + key: '_session_token', + value + }; + + case '_perishable_token_expires_at': + if (valueAsDate(value)) { + return { + key: '_perishable_token_expires_at', + value: valueAsDate(value) + }; + } + + break; + + case '_password_changed_at': + if (valueAsDate(value)) { + return { + key: '_password_changed_at', + value: valueAsDate(value) + }; + } + + break; + + case '_rperm': + case '_wperm': + case '_perishable_token': + case '_email_verify_token': + return { + key, + value + }; + + case '$or': + case '$and': + case '$nor': + return { + key: key, + value: value.map(subQuery => transformWhere(className, subQuery, schema, count)) + }; + + case 'lastUsed': + if (valueAsDate(value)) { + return { + key: '_last_used', + value: valueAsDate(value) + }; + } + + key = '_last_used'; + break; + + case 'timesUsed': + return { + key: 'times_used', + value: value + }; + + default: + { + // Other auth data + const authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/); + + if (authDataMatch) { + const provider = authDataMatch[1]; // Special-case auth data. + + return { + key: `_auth_data_${provider}.id`, + value + }; + } + } + } + + const expectedTypeIsArray = schema && schema.fields[key] && schema.fields[key].type === 'Array'; + const expectedTypeIsPointer = schema && schema.fields[key] && schema.fields[key].type === 'Pointer'; + const field = schema && schema.fields[key]; + + if (expectedTypeIsPointer || !schema && value && value.__type === 'Pointer') { + key = '_p_' + key; + } // Handle query constraints + + + const transformedConstraint = transformConstraint(value, field, count); + + if (transformedConstraint !== CannotTransform) { + if (transformedConstraint.$text) { + return { + key: '$text', + value: transformedConstraint.$text + }; + } + + if (transformedConstraint.$elemMatch) { + return { + key: '$nor', + value: [{ + [key]: transformedConstraint + }] + }; + } + + return { + key, + value: transformedConstraint + }; + } + + if (expectedTypeIsArray && !(value instanceof Array)) { + return { + key, + value: { + $all: [transformInteriorAtom(value)] + } + }; + } // Handle atomic values + + + if (transformTopLevelAtom(value) !== CannotTransform) { + return { + key, + value: transformTopLevelAtom(value) + }; + } else { + throw new Parse.Error(Parse.Error.INVALID_JSON, `You cannot use ${value} as a query parameter.`); + } +} // Main exposed method to help run queries. +// restWhere is the "where" clause in REST API form. +// Returns the mongo form of the query. + + +function transformWhere(className, restWhere, schema, count = false) { + const mongoWhere = {}; + + for (const restKey in restWhere) { + const out = transformQueryKeyValue(className, restKey, restWhere[restKey], schema, count); + mongoWhere[out.key] = out.value; + } + + return mongoWhere; +} + +const parseObjectKeyValueToMongoObjectKeyValue = (restKey, restValue, schema) => { + // Check if the schema is known since it's a built-in field. + let transformedValue; + let coercedToDate; + + switch (restKey) { + case 'objectId': + return { + key: '_id', + value: restValue + }; + + case 'expiresAt': + transformedValue = transformTopLevelAtom(restValue); + coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue; + return { + key: 'expiresAt', + value: coercedToDate + }; + + case '_email_verify_token_expires_at': + transformedValue = transformTopLevelAtom(restValue); + coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue; + return { + key: '_email_verify_token_expires_at', + value: coercedToDate + }; + + case '_account_lockout_expires_at': + transformedValue = transformTopLevelAtom(restValue); + coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue; + return { + key: '_account_lockout_expires_at', + value: coercedToDate + }; + + case '_perishable_token_expires_at': + transformedValue = transformTopLevelAtom(restValue); + coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue; + return { + key: '_perishable_token_expires_at', + value: coercedToDate + }; + + case '_password_changed_at': + transformedValue = transformTopLevelAtom(restValue); + coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue; + return { + key: '_password_changed_at', + value: coercedToDate + }; + + case '_failed_login_count': + case '_rperm': + case '_wperm': + case '_email_verify_token': + case '_hashed_password': + case '_perishable_token': + return { + key: restKey, + value: restValue + }; + + case 'sessionToken': + return { + key: '_session_token', + value: restValue + }; + + default: + // Auth data should have been transformed already + if (restKey.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'can only query on ' + restKey); + } // Trust that the auth data has been transformed and save it directly + + + if (restKey.match(/^_auth_data_[a-zA-Z0-9_]+$/)) { + return { + key: restKey, + value: restValue + }; + } + + } //skip straight to transformTopLevelAtom for Bytes, they don't show up in the schema for some reason + + + if (restValue && restValue.__type !== 'Bytes') { + //Note: We may not know the type of a field here, as the user could be saving (null) to a field + //That never existed before, meaning we can't infer the type. + if (schema.fields[restKey] && schema.fields[restKey].type == 'Pointer' || restValue.__type == 'Pointer') { + restKey = '_p_' + restKey; + } + } // Handle atomic values + + + var value = transformTopLevelAtom(restValue); + + if (value !== CannotTransform) { + return { + key: restKey, + value: value + }; + } // ACLs are handled before this method is called + // If an ACL key still exists here, something is wrong. + + + if (restKey === 'ACL') { + throw 'There was a problem transforming an ACL.'; + } // Handle arrays + + + if (restValue instanceof Array) { + value = restValue.map(transformInteriorValue); + return { + key: restKey, + value: value + }; + } // Handle normal objects by recursing + + + if (Object.keys(restValue).some(key => key.includes('$') || key.includes('.'))) { + throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); + } + + value = mapValues(restValue, transformInteriorValue); + return { + key: restKey, + value + }; +}; + +const parseObjectToMongoObjectForCreate = (className, restCreate, schema) => { + restCreate = addLegacyACL(restCreate); + const mongoCreate = {}; + + for (const restKey in restCreate) { + if (restCreate[restKey] && restCreate[restKey].__type === 'Relation') { + continue; + } + + const { + key, + value + } = parseObjectKeyValueToMongoObjectKeyValue(restKey, restCreate[restKey], schema); + + if (value !== undefined) { + mongoCreate[key] = value; + } + } // Use the legacy mongo format for createdAt and updatedAt + + + if (mongoCreate.createdAt) { + mongoCreate._created_at = new Date(mongoCreate.createdAt.iso || mongoCreate.createdAt); + delete mongoCreate.createdAt; + } + + if (mongoCreate.updatedAt) { + mongoCreate._updated_at = new Date(mongoCreate.updatedAt.iso || mongoCreate.updatedAt); + delete mongoCreate.updatedAt; + } + + return mongoCreate; +}; // Main exposed method to help update old objects. + + +const transformUpdate = (className, restUpdate, parseFormatSchema) => { + const mongoUpdate = {}; + const acl = addLegacyACL(restUpdate); + + if (acl._rperm || acl._wperm || acl._acl) { + mongoUpdate.$set = {}; + + if (acl._rperm) { + mongoUpdate.$set._rperm = acl._rperm; + } + + if (acl._wperm) { + mongoUpdate.$set._wperm = acl._wperm; + } + + if (acl._acl) { + mongoUpdate.$set._acl = acl._acl; + } + } + + for (var restKey in restUpdate) { + if (restUpdate[restKey] && restUpdate[restKey].__type === 'Relation') { + continue; + } + + var out = transformKeyValueForUpdate(className, restKey, restUpdate[restKey], parseFormatSchema); // If the output value is an object with any $ keys, it's an + // operator that needs to be lifted onto the top level update + // object. + + if (typeof out.value === 'object' && out.value !== null && out.value.__op) { + mongoUpdate[out.value.__op] = mongoUpdate[out.value.__op] || {}; + mongoUpdate[out.value.__op][out.key] = out.value.arg; + } else { + mongoUpdate['$set'] = mongoUpdate['$set'] || {}; + mongoUpdate['$set'][out.key] = out.value; + } + } + + return mongoUpdate; +}; // Add the legacy _acl format. + + +const addLegacyACL = restObject => { + const restObjectCopy = _objectSpread({}, restObject); + + const _acl = {}; + + if (restObject._wperm) { + restObject._wperm.forEach(entry => { + _acl[entry] = { + w: true + }; + }); + + restObjectCopy._acl = _acl; + } + + if (restObject._rperm) { + restObject._rperm.forEach(entry => { + if (!(entry in _acl)) { + _acl[entry] = { + r: true + }; + } else { + _acl[entry].r = true; + } + }); + + restObjectCopy._acl = _acl; + } + + return restObjectCopy; +}; // A sentinel value that helper transformations return when they +// cannot perform a transformation + + +function CannotTransform() {} + +const transformInteriorAtom = atom => { + // TODO: check validity harder for the __type-defined types + if (typeof atom === 'object' && atom && !(atom instanceof Date) && atom.__type === 'Pointer') { + return { + __type: 'Pointer', + className: atom.className, + objectId: atom.objectId + }; + } else if (typeof atom === 'function' || typeof atom === 'symbol') { + throw new Parse.Error(Parse.Error.INVALID_JSON, `cannot transform value: ${atom}`); + } else if (DateCoder.isValidJSON(atom)) { + return DateCoder.JSONToDatabase(atom); + } else if (BytesCoder.isValidJSON(atom)) { + return BytesCoder.JSONToDatabase(atom); + } else if (typeof atom === 'object' && atom && atom.$regex !== undefined) { + return new RegExp(atom.$regex); + } else { + return atom; + } +}; // Helper function to transform an atom from REST format to Mongo format. +// An atom is anything that can't contain other expressions. So it +// includes things where objects are used to represent other +// datatypes, like pointers and dates, but it does not include objects +// or arrays with generic stuff inside. +// Raises an error if this cannot possibly be valid REST format. +// Returns CannotTransform if it's just not an atom + + +function transformTopLevelAtom(atom, field) { + switch (typeof atom) { + case 'number': + case 'boolean': + case 'undefined': + return atom; + + case 'string': + if (field && field.type === 'Pointer') { + return `${field.targetClass}$${atom}`; + } + + return atom; + + case 'symbol': + case 'function': + throw new Parse.Error(Parse.Error.INVALID_JSON, `cannot transform value: ${atom}`); + + case 'object': + if (atom instanceof Date) { + // Technically dates are not rest format, but, it seems pretty + // clear what they should be transformed to, so let's just do it. + return atom; + } + + if (atom === null) { + return atom; + } // TODO: check validity harder for the __type-defined types + + + if (atom.__type == 'Pointer') { + return `${atom.className}$${atom.objectId}`; + } + + if (DateCoder.isValidJSON(atom)) { + return DateCoder.JSONToDatabase(atom); + } + + if (BytesCoder.isValidJSON(atom)) { + return BytesCoder.JSONToDatabase(atom); + } + + if (GeoPointCoder.isValidJSON(atom)) { + return GeoPointCoder.JSONToDatabase(atom); + } + + if (PolygonCoder.isValidJSON(atom)) { + return PolygonCoder.JSONToDatabase(atom); + } + + if (FileCoder.isValidJSON(atom)) { + return FileCoder.JSONToDatabase(atom); + } + + return CannotTransform; + + default: + // I don't think typeof can ever let us get here + throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, `really did not expect value: ${atom}`); + } +} + +function relativeTimeToDate(text, now = new Date()) { + text = text.toLowerCase(); + let parts = text.split(' '); // Filter out whitespace + + parts = parts.filter(part => part !== ''); + const future = parts[0] === 'in'; + const past = parts[parts.length - 1] === 'ago'; + + if (!future && !past && text !== 'now') { + return { + status: 'error', + info: "Time should either start with 'in' or end with 'ago'" + }; + } + + if (future && past) { + return { + status: 'error', + info: "Time cannot have both 'in' and 'ago'" + }; + } // strip the 'ago' or 'in' + + + if (future) { + parts = parts.slice(1); + } else { + // past + parts = parts.slice(0, parts.length - 1); + } + + if (parts.length % 2 !== 0 && text !== 'now') { + return { + status: 'error', + info: 'Invalid time string. Dangling unit or number.' + }; + } + + const pairs = []; + + while (parts.length) { + pairs.push([parts.shift(), parts.shift()]); + } + + let seconds = 0; + + for (const [num, interval] of pairs) { + const val = Number(num); + + if (!Number.isInteger(val)) { + return { + status: 'error', + info: `'${num}' is not an integer.` + }; + } + + switch (interval) { + case 'yr': + case 'yrs': + case 'year': + case 'years': + seconds += val * 31536000; // 365 * 24 * 60 * 60 + + break; + + case 'wk': + case 'wks': + case 'week': + case 'weeks': + seconds += val * 604800; // 7 * 24 * 60 * 60 + + break; + + case 'd': + case 'day': + case 'days': + seconds += val * 86400; // 24 * 60 * 60 + + break; + + case 'hr': + case 'hrs': + case 'hour': + case 'hours': + seconds += val * 3600; // 60 * 60 + + break; + + case 'min': + case 'mins': + case 'minute': + case 'minutes': + seconds += val * 60; + break; + + case 'sec': + case 'secs': + case 'second': + case 'seconds': + seconds += val; + break; + + default: + return { + status: 'error', + info: `Invalid interval: '${interval}'` + }; + } + } + + const milliseconds = seconds * 1000; + + if (future) { + return { + status: 'success', + info: 'future', + result: new Date(now.valueOf() + milliseconds) + }; + } else if (past) { + return { + status: 'success', + info: 'past', + result: new Date(now.valueOf() - milliseconds) + }; + } else { + return { + status: 'success', + info: 'present', + result: new Date(now.valueOf()) + }; + } +} // Transforms a query constraint from REST API format to Mongo format. +// A constraint is something with fields like $lt. +// If it is not a valid constraint but it could be a valid something +// else, return CannotTransform. +// inArray is whether this is an array field. + + +function transformConstraint(constraint, field, count = false) { + const inArray = field && field.type && field.type === 'Array'; + + if (typeof constraint !== 'object' || !constraint) { + return CannotTransform; + } + + const transformFunction = inArray ? transformInteriorAtom : transformTopLevelAtom; + + const transformer = atom => { + const result = transformFunction(atom, field); + + if (result === CannotTransform) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${JSON.stringify(atom)}`); + } + + return result; + }; // keys is the constraints in reverse alphabetical order. + // This is a hack so that: + // $regex is handled before $options + // $nearSphere is handled before $maxDistance + + + var keys = Object.keys(constraint).sort().reverse(); + var answer = {}; + + for (var key of keys) { + switch (key) { + case '$lt': + case '$lte': + case '$gt': + case '$gte': + case '$exists': + case '$ne': + case '$eq': + { + const val = constraint[key]; + + if (val && typeof val === 'object' && val.$relativeTime) { + if (field && field.type !== 'Date') { + throw new Parse.Error(Parse.Error.INVALID_JSON, '$relativeTime can only be used with Date field'); + } + + switch (key) { + case '$exists': + case '$ne': + case '$eq': + throw new Parse.Error(Parse.Error.INVALID_JSON, '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators'); + } + + const parserResult = relativeTimeToDate(val.$relativeTime); + + if (parserResult.status === 'success') { + answer[key] = parserResult.result; + break; + } + + _logger.default.info('Error while parsing relative date', parserResult); + + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $relativeTime (${key}) value. ${parserResult.info}`); + } + + answer[key] = transformer(val); + break; + } + + case '$in': + case '$nin': + { + const arr = constraint[key]; + + if (!(arr instanceof Array)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value'); + } + + answer[key] = _lodash.default.flatMap(arr, value => { + return (atom => { + if (Array.isArray(atom)) { + return value.map(transformer); + } else { + return transformer(atom); + } + })(value); + }); + break; + } + + case '$all': + { + const arr = constraint[key]; + + if (!(arr instanceof Array)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value'); + } + + answer[key] = arr.map(transformInteriorAtom); + const values = answer[key]; + + if (isAnyValueRegex(values) && !isAllValuesRegexOrNone(values)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'All $all values must be of regex type or none: ' + values); + } + + break; + } + + case '$regex': + var s = constraint[key]; + + if (typeof s !== 'string') { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad regex: ' + s); + } + + answer[key] = s; + break; + + case '$containedBy': + { + const arr = constraint[key]; + + if (!(arr instanceof Array)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $containedBy: should be an array`); + } + + answer.$elemMatch = { + $nin: arr.map(transformer) + }; + break; + } + + case '$options': + answer[key] = constraint[key]; + break; + + case '$text': + { + const search = constraint[key].$search; + + if (typeof search !== 'object') { + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $search, should be object`); + } + + if (!search.$term || typeof search.$term !== 'string') { + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $term, should be string`); + } else { + answer[key] = { + $search: search.$term + }; + } + + if (search.$language && typeof search.$language !== 'string') { + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $language, should be string`); + } else if (search.$language) { + answer[key].$language = search.$language; + } + + if (search.$caseSensitive && typeof search.$caseSensitive !== 'boolean') { + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $caseSensitive, should be boolean`); + } else if (search.$caseSensitive) { + answer[key].$caseSensitive = search.$caseSensitive; + } + + if (search.$diacriticSensitive && typeof search.$diacriticSensitive !== 'boolean') { + throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $diacriticSensitive, should be boolean`); + } else if (search.$diacriticSensitive) { + answer[key].$diacriticSensitive = search.$diacriticSensitive; + } + + break; + } + + case '$nearSphere': + { + const point = constraint[key]; + + if (count) { + answer.$geoWithin = { + $centerSphere: [[point.longitude, point.latitude], constraint.$maxDistance] + }; + } else { + answer[key] = [point.longitude, point.latitude]; + } + + break; + } + + case '$maxDistance': + { + if (count) { + break; + } + + answer[key] = constraint[key]; + break; + } + // The SDKs don't seem to use these but they are documented in the + // REST API docs. + + case '$maxDistanceInRadians': + answer['$maxDistance'] = constraint[key]; + break; + + case '$maxDistanceInMiles': + answer['$maxDistance'] = constraint[key] / 3959; + break; + + case '$maxDistanceInKilometers': + answer['$maxDistance'] = constraint[key] / 6371; + break; + + case '$select': + case '$dontSelect': + throw new Parse.Error(Parse.Error.COMMAND_UNAVAILABLE, 'the ' + key + ' constraint is not supported yet'); + + case '$within': + var box = constraint[key]['$box']; + + if (!box || box.length != 2) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'malformatted $within arg'); + } + + answer[key] = { + $box: [[box[0].longitude, box[0].latitude], [box[1].longitude, box[1].latitude]] + }; + break; + + case '$geoWithin': + { + const polygon = constraint[key]['$polygon']; + const centerSphere = constraint[key]['$centerSphere']; + + if (polygon !== undefined) { + let points; + + if (typeof polygon === 'object' && polygon.__type === 'Polygon') { + if (!polygon.coordinates || polygon.coordinates.length < 3) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; Polygon.coordinates should contain at least 3 lon/lat pairs'); + } + + points = polygon.coordinates; + } else if (polygon instanceof Array) { + if (polygon.length < 3) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + } + + points = polygon; + } else { + throw new Parse.Error(Parse.Error.INVALID_JSON, "bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint's"); + } + + points = points.map(point => { + if (point instanceof Array && point.length === 2) { + Parse.GeoPoint._validate(point[1], point[0]); + + return point; + } + + if (!GeoPointCoder.isValidJSON(point)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value'); + } else { + Parse.GeoPoint._validate(point.latitude, point.longitude); + } + + return [point.longitude, point.latitude]; + }); + answer[key] = { + $polygon: points + }; + } else if (centerSphere !== undefined) { + if (!(centerSphere instanceof Array) || centerSphere.length < 2) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere should be an array of Parse.GeoPoint and distance'); + } // Get point, convert to geo point if necessary and validate + + + let point = centerSphere[0]; + + if (point instanceof Array && point.length === 2) { + point = new Parse.GeoPoint(point[1], point[0]); + } else if (!GeoPointCoder.isValidJSON(point)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere geo point invalid'); + } + + Parse.GeoPoint._validate(point.latitude, point.longitude); // Get distance and validate + + + const distance = centerSphere[1]; + + if (isNaN(distance) || distance < 0) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere distance invalid'); + } + + answer[key] = { + $centerSphere: [[point.longitude, point.latitude], distance] + }; + } + + break; + } + + case '$geoIntersects': + { + const point = constraint[key]['$point']; + + if (!GeoPointCoder.isValidJSON(point)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoIntersect value; $point should be GeoPoint'); + } else { + Parse.GeoPoint._validate(point.latitude, point.longitude); + } + + answer[key] = { + $geometry: { + type: 'Point', + coordinates: [point.longitude, point.latitude] + } + }; + break; + } + + default: + if (key.match(/^\$+/)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad constraint: ' + key); + } + + return CannotTransform; + } + } + + return answer; +} // Transforms an update operator from REST format to mongo format. +// To be transformed, the input should have an __op field. +// If flatten is true, this will flatten operators to their static +// data format. For example, an increment of 2 would simply become a +// 2. +// The output for a non-flattened operator is a hash with __op being +// the mongo op, and arg being the argument. +// The output for a flattened operator is just a value. +// Returns undefined if this should be a no-op. + + +function transformUpdateOperator({ + __op, + amount, + objects +}, flatten) { + switch (__op) { + case 'Delete': + if (flatten) { + return undefined; + } else { + return { + __op: '$unset', + arg: '' + }; + } + + case 'Increment': + if (typeof amount !== 'number') { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'incrementing must provide a number'); + } + + if (flatten) { + return amount; + } else { + return { + __op: '$inc', + arg: amount + }; + } + + case 'Add': + case 'AddUnique': + if (!(objects instanceof Array)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array'); + } + + var toAdd = objects.map(transformInteriorAtom); + + if (flatten) { + return toAdd; + } else { + var mongoOp = { + Add: '$push', + AddUnique: '$addToSet' + }[__op]; + return { + __op: mongoOp, + arg: { + $each: toAdd + } + }; + } + + case 'Remove': + if (!(objects instanceof Array)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to remove must be an array'); + } + + var toRemove = objects.map(transformInteriorAtom); + + if (flatten) { + return []; + } else { + return { + __op: '$pullAll', + arg: toRemove + }; + } + + default: + throw new Parse.Error(Parse.Error.COMMAND_UNAVAILABLE, `The ${__op} operator is not supported yet.`); + } +} + +function mapValues(object, iterator) { + const result = {}; + Object.keys(object).forEach(key => { + result[key] = iterator(object[key]); + }); + return result; +} + +const nestedMongoObjectToNestedParseObject = mongoObject => { + switch (typeof mongoObject) { + case 'string': + case 'number': + case 'boolean': + case 'undefined': + return mongoObject; + + case 'symbol': + case 'function': + throw 'bad value in nestedMongoObjectToNestedParseObject'; + + case 'object': + if (mongoObject === null) { + return null; + } + + if (mongoObject instanceof Array) { + return mongoObject.map(nestedMongoObjectToNestedParseObject); + } + + if (mongoObject instanceof Date) { + return Parse._encode(mongoObject); + } + + if (mongoObject instanceof mongodb.Long) { + return mongoObject.toNumber(); + } + + if (mongoObject instanceof mongodb.Double) { + return mongoObject.value; + } + + if (BytesCoder.isValidDatabaseObject(mongoObject)) { + return BytesCoder.databaseToJSON(mongoObject); + } + + if (Object.prototype.hasOwnProperty.call(mongoObject, '__type') && mongoObject.__type == 'Date' && mongoObject.iso instanceof Date) { + mongoObject.iso = mongoObject.iso.toJSON(); + return mongoObject; + } + + return mapValues(mongoObject, nestedMongoObjectToNestedParseObject); + + default: + throw 'unknown js type'; + } +}; + +const transformPointerString = (schema, field, pointerString) => { + const objData = pointerString.split('$'); + + if (objData[0] !== schema.fields[field].targetClass) { + throw 'pointer to incorrect className'; + } + + return { + __type: 'Pointer', + className: objData[0], + objectId: objData[1] + }; +}; // Converts from a mongo-format object to a REST-format object. +// Does not strip out anything based on a lack of authentication. + + +const mongoObjectToParseObject = (className, mongoObject, schema) => { + switch (typeof mongoObject) { + case 'string': + case 'number': + case 'boolean': + case 'undefined': + return mongoObject; + + case 'symbol': + case 'function': + throw 'bad value in mongoObjectToParseObject'; + + case 'object': + { + if (mongoObject === null) { + return null; + } + + if (mongoObject instanceof Array) { + return mongoObject.map(nestedMongoObjectToNestedParseObject); + } + + if (mongoObject instanceof Date) { + return Parse._encode(mongoObject); + } + + if (mongoObject instanceof mongodb.Long) { + return mongoObject.toNumber(); + } + + if (mongoObject instanceof mongodb.Double) { + return mongoObject.value; + } + + if (BytesCoder.isValidDatabaseObject(mongoObject)) { + return BytesCoder.databaseToJSON(mongoObject); + } + + const restObject = {}; + + if (mongoObject._rperm || mongoObject._wperm) { + restObject._rperm = mongoObject._rperm || []; + restObject._wperm = mongoObject._wperm || []; + delete mongoObject._rperm; + delete mongoObject._wperm; + } + + for (var key in mongoObject) { + switch (key) { + case '_id': + restObject['objectId'] = '' + mongoObject[key]; + break; + + case '_hashed_password': + restObject._hashed_password = mongoObject[key]; + break; + + case '_acl': + break; + + case '_email_verify_token': + case '_perishable_token': + case '_perishable_token_expires_at': + case '_password_changed_at': + case '_tombstone': + case '_email_verify_token_expires_at': + case '_account_lockout_expires_at': + case '_failed_login_count': + case '_password_history': + // Those keys will be deleted if needed in the DB Controller + restObject[key] = mongoObject[key]; + break; + + case '_session_token': + restObject['sessionToken'] = mongoObject[key]; + break; + + case 'updatedAt': + case '_updated_at': + restObject['updatedAt'] = Parse._encode(new Date(mongoObject[key])).iso; + break; + + case 'createdAt': + case '_created_at': + restObject['createdAt'] = Parse._encode(new Date(mongoObject[key])).iso; + break; + + case 'expiresAt': + case '_expiresAt': + restObject['expiresAt'] = Parse._encode(new Date(mongoObject[key])); + break; + + case 'lastUsed': + case '_last_used': + restObject['lastUsed'] = Parse._encode(new Date(mongoObject[key])).iso; + break; + + case 'timesUsed': + case 'times_used': + restObject['timesUsed'] = mongoObject[key]; + break; + + case 'authData': + if (className === '_User') { + _logger.default.warn('ignoring authData in _User as this key is reserved to be synthesized of `_auth_data_*` keys'); + } else { + restObject['authData'] = mongoObject[key]; + } + + break; + + default: + // Check other auth data keys + var authDataMatch = key.match(/^_auth_data_([a-zA-Z0-9_]+)$/); + + if (authDataMatch && className === '_User') { + var provider = authDataMatch[1]; + restObject['authData'] = restObject['authData'] || {}; + restObject['authData'][provider] = mongoObject[key]; + break; + } + + if (key.indexOf('_p_') == 0) { + var newKey = key.substring(3); + + if (!schema.fields[newKey]) { + _logger.default.info('transform.js', 'Found a pointer column not in the schema, dropping it.', className, newKey); + + break; + } + + if (schema.fields[newKey].type !== 'Pointer') { + _logger.default.info('transform.js', 'Found a pointer in a non-pointer column, dropping it.', className, key); + + break; + } + + if (mongoObject[key] === null) { + break; + } + + restObject[newKey] = transformPointerString(schema, newKey, mongoObject[key]); + break; + } else if (key[0] == '_' && key != '__type') { + throw 'bad key in untransform: ' + key; + } else { + var value = mongoObject[key]; + + if (schema.fields[key] && schema.fields[key].type === 'File' && FileCoder.isValidDatabaseObject(value)) { + restObject[key] = FileCoder.databaseToJSON(value); + break; + } + + if (schema.fields[key] && schema.fields[key].type === 'GeoPoint' && GeoPointCoder.isValidDatabaseObject(value)) { + restObject[key] = GeoPointCoder.databaseToJSON(value); + break; + } + + if (schema.fields[key] && schema.fields[key].type === 'Polygon' && PolygonCoder.isValidDatabaseObject(value)) { + restObject[key] = PolygonCoder.databaseToJSON(value); + break; + } + + if (schema.fields[key] && schema.fields[key].type === 'Bytes' && BytesCoder.isValidDatabaseObject(value)) { + restObject[key] = BytesCoder.databaseToJSON(value); + break; + } + } + + restObject[key] = nestedMongoObjectToNestedParseObject(mongoObject[key]); + } + } + + const relationFieldNames = Object.keys(schema.fields).filter(fieldName => schema.fields[fieldName].type === 'Relation'); + const relationFields = {}; + relationFieldNames.forEach(relationFieldName => { + relationFields[relationFieldName] = { + __type: 'Relation', + className: schema.fields[relationFieldName].targetClass + }; + }); + return _objectSpread({}, restObject, {}, relationFields); + } + + default: + throw 'unknown js type'; + } +}; + +var DateCoder = { + JSONToDatabase(json) { + return new Date(json.iso); + }, + + isValidJSON(value) { + return typeof value === 'object' && value !== null && value.__type === 'Date'; + } + +}; +var BytesCoder = { + base64Pattern: new RegExp('^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'), + + isBase64Value(object) { + if (typeof object !== 'string') { + return false; + } + + return this.base64Pattern.test(object); + }, + + databaseToJSON(object) { + let value; + + if (this.isBase64Value(object)) { + value = object; + } else { + value = object.buffer.toString('base64'); + } + + return { + __type: 'Bytes', + base64: value + }; + }, + + isValidDatabaseObject(object) { + return object instanceof mongodb.Binary || this.isBase64Value(object); + }, + + JSONToDatabase(json) { + return new mongodb.Binary(Buffer.from(json.base64, 'base64')); + }, + + isValidJSON(value) { + return typeof value === 'object' && value !== null && value.__type === 'Bytes'; + } + +}; +var GeoPointCoder = { + databaseToJSON(object) { + return { + __type: 'GeoPoint', + latitude: object[1], + longitude: object[0] + }; + }, + + isValidDatabaseObject(object) { + return object instanceof Array && object.length == 2; + }, + + JSONToDatabase(json) { + return [json.longitude, json.latitude]; + }, + + isValidJSON(value) { + return typeof value === 'object' && value !== null && value.__type === 'GeoPoint'; + } + +}; +var PolygonCoder = { + databaseToJSON(object) { + // Convert lng/lat -> lat/lng + const coords = object.coordinates[0].map(coord => { + return [coord[1], coord[0]]; + }); + return { + __type: 'Polygon', + coordinates: coords + }; + }, + + isValidDatabaseObject(object) { + const coords = object.coordinates[0]; + + if (object.type !== 'Polygon' || !(coords instanceof Array)) { + return false; + } + + for (let i = 0; i < coords.length; i++) { + const point = coords[i]; + + if (!GeoPointCoder.isValidDatabaseObject(point)) { + return false; + } + + Parse.GeoPoint._validate(parseFloat(point[1]), parseFloat(point[0])); + } + + return true; + }, + + JSONToDatabase(json) { + let coords = json.coordinates; // Add first point to the end to close polygon + + if (coords[0][0] !== coords[coords.length - 1][0] || coords[0][1] !== coords[coords.length - 1][1]) { + coords.push(coords[0]); + } + + const unique = coords.filter((item, index, ar) => { + let foundIndex = -1; + + for (let i = 0; i < ar.length; i += 1) { + const pt = ar[i]; + + if (pt[0] === item[0] && pt[1] === item[1]) { + foundIndex = i; + break; + } + } + + return foundIndex === index; + }); + + if (unique.length < 3) { + throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'GeoJSON: Loop must have at least 3 different vertices'); + } // Convert lat/long -> long/lat + + + coords = coords.map(coord => { + return [coord[1], coord[0]]; + }); + return { + type: 'Polygon', + coordinates: [coords] + }; + }, + + isValidJSON(value) { + return typeof value === 'object' && value !== null && value.__type === 'Polygon'; + } + +}; +var FileCoder = { + databaseToJSON(object) { + return { + __type: 'File', + name: object + }; + }, + + isValidDatabaseObject(object) { + return typeof object === 'string'; + }, + + JSONToDatabase(json) { + return json.name; + }, + + isValidJSON(value) { + return typeof value === 'object' && value !== null && value.__type === 'File'; + } + +}; +module.exports = { + transformKey, + parseObjectToMongoObjectForCreate, + transformUpdate, + transformWhere, + mongoObjectToParseObject, + relativeTimeToDate, + transformConstraint, + transformPointerString +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvVHJhbnNmb3JtLmpzIl0sIm5hbWVzIjpbIm1vbmdvZGIiLCJyZXF1aXJlIiwiUGFyc2UiLCJ0cmFuc2Zvcm1LZXkiLCJjbGFzc05hbWUiLCJmaWVsZE5hbWUiLCJzY2hlbWEiLCJmaWVsZHMiLCJfX3R5cGUiLCJ0eXBlIiwidHJhbnNmb3JtS2V5VmFsdWVGb3JVcGRhdGUiLCJyZXN0S2V5IiwicmVzdFZhbHVlIiwicGFyc2VGb3JtYXRTY2hlbWEiLCJrZXkiLCJ0aW1lRmllbGQiLCJpbmNsdWRlcyIsInZhbHVlIiwicGFyc2VJbnQiLCJ0cmFuc2Zvcm1Ub3BMZXZlbEF0b20iLCJDYW5ub3RUcmFuc2Zvcm0iLCJEYXRlIiwiaW5kZXhPZiIsIkFycmF5IiwibWFwIiwidHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSIsInRyYW5zZm9ybVVwZGF0ZU9wZXJhdG9yIiwibWFwVmFsdWVzIiwiaXNSZWdleCIsIlJlZ0V4cCIsImlzU3RhcnRzV2l0aFJlZ2V4IiwibWF0Y2hlcyIsInRvU3RyaW5nIiwibWF0Y2giLCJpc0FsbFZhbHVlc1JlZ2V4T3JOb25lIiwidmFsdWVzIiwiaXNBcnJheSIsImxlbmd0aCIsImZpcnN0VmFsdWVzSXNSZWdleCIsImkiLCJpc0FueVZhbHVlUmVnZXgiLCJzb21lIiwiT2JqZWN0Iiwia2V5cyIsIkVycm9yIiwiSU5WQUxJRF9ORVNURURfS0VZIiwidHJhbnNmb3JtSW50ZXJpb3JBdG9tIiwidmFsdWVBc0RhdGUiLCJ0cmFuc2Zvcm1RdWVyeUtleVZhbHVlIiwiY291bnQiLCJzdWJRdWVyeSIsInRyYW5zZm9ybVdoZXJlIiwiYXV0aERhdGFNYXRjaCIsInByb3ZpZGVyIiwiZXhwZWN0ZWRUeXBlSXNBcnJheSIsImV4cGVjdGVkVHlwZUlzUG9pbnRlciIsImZpZWxkIiwidHJhbnNmb3JtZWRDb25zdHJhaW50IiwidHJhbnNmb3JtQ29uc3RyYWludCIsIiR0ZXh0IiwiJGVsZW1NYXRjaCIsIiRhbGwiLCJJTlZBTElEX0pTT04iLCJyZXN0V2hlcmUiLCJtb25nb1doZXJlIiwib3V0IiwicGFyc2VPYmplY3RLZXlWYWx1ZVRvTW9uZ29PYmplY3RLZXlWYWx1ZSIsInRyYW5zZm9ybWVkVmFsdWUiLCJjb2VyY2VkVG9EYXRlIiwiSU5WQUxJRF9LRVlfTkFNRSIsInBhcnNlT2JqZWN0VG9Nb25nb09iamVjdEZvckNyZWF0ZSIsInJlc3RDcmVhdGUiLCJhZGRMZWdhY3lBQ0wiLCJtb25nb0NyZWF0ZSIsInVuZGVmaW5lZCIsImNyZWF0ZWRBdCIsIl9jcmVhdGVkX2F0IiwiaXNvIiwidXBkYXRlZEF0IiwiX3VwZGF0ZWRfYXQiLCJ0cmFuc2Zvcm1VcGRhdGUiLCJyZXN0VXBkYXRlIiwibW9uZ29VcGRhdGUiLCJhY2wiLCJfcnBlcm0iLCJfd3Blcm0iLCJfYWNsIiwiJHNldCIsIl9fb3AiLCJhcmciLCJyZXN0T2JqZWN0IiwicmVzdE9iamVjdENvcHkiLCJmb3JFYWNoIiwiZW50cnkiLCJ3IiwiciIsImF0b20iLCJvYmplY3RJZCIsIkRhdGVDb2RlciIsImlzVmFsaWRKU09OIiwiSlNPTlRvRGF0YWJhc2UiLCJCeXRlc0NvZGVyIiwiJHJlZ2V4IiwidGFyZ2V0Q2xhc3MiLCJHZW9Qb2ludENvZGVyIiwiUG9seWdvbkNvZGVyIiwiRmlsZUNvZGVyIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwicmVsYXRpdmVUaW1lVG9EYXRlIiwidGV4dCIsIm5vdyIsInRvTG93ZXJDYXNlIiwicGFydHMiLCJzcGxpdCIsImZpbHRlciIsInBhcnQiLCJmdXR1cmUiLCJwYXN0Iiwic3RhdHVzIiwiaW5mbyIsInNsaWNlIiwicGFpcnMiLCJwdXNoIiwic2hpZnQiLCJzZWNvbmRzIiwibnVtIiwiaW50ZXJ2YWwiLCJ2YWwiLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJtaWxsaXNlY29uZHMiLCJyZXN1bHQiLCJ2YWx1ZU9mIiwiY29uc3RyYWludCIsImluQXJyYXkiLCJ0cmFuc2Zvcm1GdW5jdGlvbiIsInRyYW5zZm9ybWVyIiwiSlNPTiIsInN0cmluZ2lmeSIsInNvcnQiLCJyZXZlcnNlIiwiYW5zd2VyIiwiJHJlbGF0aXZlVGltZSIsInBhcnNlclJlc3VsdCIsImxvZyIsImFyciIsIl8iLCJmbGF0TWFwIiwicyIsIiRuaW4iLCJzZWFyY2giLCIkc2VhcmNoIiwiJHRlcm0iLCIkbGFuZ3VhZ2UiLCIkY2FzZVNlbnNpdGl2ZSIsIiRkaWFjcml0aWNTZW5zaXRpdmUiLCJwb2ludCIsIiRnZW9XaXRoaW4iLCIkY2VudGVyU3BoZXJlIiwibG9uZ2l0dWRlIiwibGF0aXR1ZGUiLCIkbWF4RGlzdGFuY2UiLCJDT01NQU5EX1VOQVZBSUxBQkxFIiwiYm94IiwiJGJveCIsInBvbHlnb24iLCJjZW50ZXJTcGhlcmUiLCJwb2ludHMiLCJjb29yZGluYXRlcyIsIkdlb1BvaW50IiwiX3ZhbGlkYXRlIiwiJHBvbHlnb24iLCJkaXN0YW5jZSIsImlzTmFOIiwiJGdlb21ldHJ5IiwiYW1vdW50Iiwib2JqZWN0cyIsImZsYXR0ZW4iLCJ0b0FkZCIsIm1vbmdvT3AiLCJBZGQiLCJBZGRVbmlxdWUiLCIkZWFjaCIsInRvUmVtb3ZlIiwib2JqZWN0IiwiaXRlcmF0b3IiLCJuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QiLCJtb25nb09iamVjdCIsIl9lbmNvZGUiLCJMb25nIiwidG9OdW1iZXIiLCJEb3VibGUiLCJpc1ZhbGlkRGF0YWJhc2VPYmplY3QiLCJkYXRhYmFzZVRvSlNPTiIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsInRvSlNPTiIsInRyYW5zZm9ybVBvaW50ZXJTdHJpbmciLCJwb2ludGVyU3RyaW5nIiwib2JqRGF0YSIsIm1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdCIsIl9oYXNoZWRfcGFzc3dvcmQiLCJ3YXJuIiwibmV3S2V5Iiwic3Vic3RyaW5nIiwicmVsYXRpb25GaWVsZE5hbWVzIiwicmVsYXRpb25GaWVsZHMiLCJyZWxhdGlvbkZpZWxkTmFtZSIsImpzb24iLCJiYXNlNjRQYXR0ZXJuIiwiaXNCYXNlNjRWYWx1ZSIsInRlc3QiLCJidWZmZXIiLCJiYXNlNjQiLCJCaW5hcnkiLCJCdWZmZXIiLCJmcm9tIiwiY29vcmRzIiwiY29vcmQiLCJwYXJzZUZsb2F0IiwidW5pcXVlIiwiaXRlbSIsImluZGV4IiwiYXIiLCJmb3VuZEluZGV4IiwicHQiLCJuYW1lIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7QUFDQTs7Ozs7Ozs7OztBQUNBLElBQUlBLE9BQU8sR0FBR0MsT0FBTyxDQUFDLFNBQUQsQ0FBckI7O0FBQ0EsSUFBSUMsS0FBSyxHQUFHRCxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCQyxLQUFsQzs7QUFFQSxNQUFNQyxZQUFZLEdBQUcsQ0FBQ0MsU0FBRCxFQUFZQyxTQUFaLEVBQXVCQyxNQUF2QixLQUFrQztBQUNyRDtBQUNBLFVBQVFELFNBQVI7QUFDRSxTQUFLLFVBQUw7QUFDRSxhQUFPLEtBQVA7O0FBQ0YsU0FBSyxXQUFMO0FBQ0UsYUFBTyxhQUFQOztBQUNGLFNBQUssV0FBTDtBQUNFLGFBQU8sYUFBUDs7QUFDRixTQUFLLGNBQUw7QUFDRSxhQUFPLGdCQUFQOztBQUNGLFNBQUssVUFBTDtBQUNFLGFBQU8sWUFBUDs7QUFDRixTQUFLLFdBQUw7QUFDRSxhQUFPLFlBQVA7QUFaSjs7QUFlQSxNQUNFQyxNQUFNLENBQUNDLE1BQVAsQ0FBY0YsU0FBZCxLQUNBQyxNQUFNLENBQUNDLE1BQVAsQ0FBY0YsU0FBZCxFQUF5QkcsTUFBekIsSUFBbUMsU0FGckMsRUFHRTtBQUNBSCxJQUFBQSxTQUFTLEdBQUcsUUFBUUEsU0FBcEI7QUFDRCxHQUxELE1BS08sSUFDTEMsTUFBTSxDQUFDQyxNQUFQLENBQWNGLFNBQWQsS0FDQUMsTUFBTSxDQUFDQyxNQUFQLENBQWNGLFNBQWQsRUFBeUJJLElBQXpCLElBQWlDLFNBRjVCLEVBR0w7QUFDQUosSUFBQUEsU0FBUyxHQUFHLFFBQVFBLFNBQXBCO0FBQ0Q7O0FBRUQsU0FBT0EsU0FBUDtBQUNE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QUFLLElBQXZDLElBQStDQSxLQUFLLENBQUNULE1BQU4sS0FBaUIsTUFEbEU7QUFHRDs7QUFwQmEsQ0FBaEI7QUF1QkE0TixNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZmxPLEVBQUFBLFlBRGU7QUFFZm1FLEVBQUFBLGlDQUZlO0FBR2ZVLEVBQUFBLGVBSGU7QUFJZjdCLEVBQUFBLGNBSmU7QUFLZnNKLEVBQUFBLHdCQUxlO0FBTWY3RixFQUFBQSxrQkFOZTtBQU9mbEQsRUFBQUEsbUJBUGU7QUFRZjRJLEVBQUFBO0FBUmUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbG9nIGZyb20gJy4uLy4uLy4uL2xvZ2dlcic7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xudmFyIG1vbmdvZGIgPSByZXF1aXJlKCdtb25nb2RiJyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbmNvbnN0IHRyYW5zZm9ybUtleSA9IChjbGFzc05hbWUsIGZpZWxkTmFtZSwgc2NoZW1hKSA9PiB7XG4gIC8vIENoZWNrIGlmIHRoZSBzY2hlbWEgaXMga25vd24gc2luY2UgaXQncyBhIGJ1aWx0LWluIGZpZWxkLlxuICBzd2l0Y2ggKGZpZWxkTmFtZSkge1xuICAgIGNhc2UgJ29iamVjdElkJzpcbiAgICAgIHJldHVybiAnX2lkJztcbiAgICBjYXNlICdjcmVhdGVkQXQnOlxuICAgICAgcmV0dXJuICdfY3JlYXRlZF9hdCc7XG4gICAgY2FzZSAndXBkYXRlZEF0JzpcbiAgICAgIHJldHVybiAnX3VwZGF0ZWRfYXQnO1xuICAgIGNhc2UgJ3Nlc3Npb25Ub2tlbic6XG4gICAgICByZXR1cm4gJ19zZXNzaW9uX3Rva2VuJztcbiAgICBjYXNlICdsYXN0VXNlZCc6XG4gICAgICByZXR1cm4gJ19sYXN0X3VzZWQnO1xuICAgIGNhc2UgJ3RpbWVzVXNlZCc6XG4gICAgICByZXR1cm4gJ3RpbWVzX3VzZWQnO1xuICB9XG5cbiAgaWYgKFxuICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5fX3R5cGUgPT0gJ1BvaW50ZXInXG4gICkge1xuICAgIGZpZWxkTmFtZSA9ICdfcF8nICsgZmllbGROYW1lO1xuICB9IGVsc2UgaWYgKFxuICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09ICdQb2ludGVyJ1xuICApIHtcbiAgICBmaWVsZE5hbWUgPSAnX3BfJyArIGZpZWxkTmFtZTtcbiAgfVxuXG4gIHJldHVybiBmaWVsZE5hbWU7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1LZXlWYWx1ZUZvclVwZGF0ZSA9IChcbiAgY2xhc3NOYW1lLFxuICByZXN0S2V5LFxuICByZXN0VmFsdWUsXG4gIHBhcnNlRm9ybWF0U2NoZW1hXG4pID0+IHtcbiAgLy8gQ2hlY2sgaWYgdGhlIHNjaGVtYSBpcyBrbm93biBzaW5jZSBpdCdzIGEgYnVpbHQtaW4gZmllbGQuXG4gIHZhciBrZXkgPSByZXN0S2V5O1xuICB2YXIgdGltZUZpZWxkID0gZmFsc2U7XG4gIHN3aXRjaCAoa2V5KSB7XG4gICAgY2FzZSAnb2JqZWN0SWQnOlxuICAgIGNhc2UgJ19pZCc6XG4gICAgICBpZiAoWydfR2xvYmFsQ29uZmlnJywgJ19HcmFwaFFMQ29uZmlnJ10uaW5jbHVkZXMoY2xhc3NOYW1lKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGtleToga2V5LFxuICAgICAgICAgIHZhbHVlOiBwYXJzZUludChyZXN0VmFsdWUpLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAga2V5ID0gJ19pZCc7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdjcmVhdGVkQXQnOlxuICAgIGNhc2UgJ19jcmVhdGVkX2F0JzpcbiAgICAgIGtleSA9ICdfY3JlYXRlZF9hdCc7XG4gICAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndXBkYXRlZEF0JzpcbiAgICBjYXNlICdfdXBkYXRlZF9hdCc6XG4gICAgICBrZXkgPSAnX3VwZGF0ZWRfYXQnO1xuICAgICAgdGltZUZpZWxkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3Nlc3Npb25Ub2tlbic6XG4gICAgY2FzZSAnX3Nlc3Npb25fdG9rZW4nOlxuICAgICAga2V5ID0gJ19zZXNzaW9uX3Rva2VuJztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2V4cGlyZXNBdCc6XG4gICAgY2FzZSAnX2V4cGlyZXNBdCc6XG4gICAgICBrZXkgPSAnZXhwaXJlc0F0JztcbiAgICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAga2V5ID0gJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCc7XG4gICAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JzpcbiAgICAgIGtleSA9ICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnO1xuICAgICAgdGltZUZpZWxkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ19mYWlsZWRfbG9naW5fY291bnQnOlxuICAgICAga2V5ID0gJ19mYWlsZWRfbG9naW5fY291bnQnO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAgICBrZXkgPSAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCc7XG4gICAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnOlxuICAgICAga2V5ID0gJ19wYXNzd29yZF9jaGFuZ2VkX2F0JztcbiAgICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfcnBlcm0nOlxuICAgIGNhc2UgJ193cGVybSc6XG4gICAgICByZXR1cm4geyBrZXk6IGtleSwgdmFsdWU6IHJlc3RWYWx1ZSB9O1xuICAgIGNhc2UgJ2xhc3RVc2VkJzpcbiAgICBjYXNlICdfbGFzdF91c2VkJzpcbiAgICAgIGtleSA9ICdfbGFzdF91c2VkJztcbiAgICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICBjYXNlICd0aW1lc1VzZWQnOlxuICAgIGNhc2UgJ3RpbWVzX3VzZWQnOlxuICAgICAga2V5ID0gJ3RpbWVzX3VzZWQnO1xuICAgICAgdGltZUZpZWxkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgaWYgKFxuICAgIChwYXJzZUZvcm1hdFNjaGVtYS5maWVsZHNba2V5XSAmJlxuICAgICAgcGFyc2VGb3JtYXRTY2hlbWEuZmllbGRzW2tleV0udHlwZSA9PT0gJ1BvaW50ZXInKSB8fFxuICAgICghcGFyc2VGb3JtYXRTY2hlbWEuZmllbGRzW2tleV0gJiZcbiAgICAgIHJlc3RWYWx1ZSAmJlxuICAgICAgcmVzdFZhbHVlLl9fdHlwZSA9PSAnUG9pbnRlcicpXG4gICkge1xuICAgIGtleSA9ICdfcF8nICsga2V5O1xuICB9XG5cbiAgLy8gSGFuZGxlIGF0b21pYyB2YWx1ZXNcbiAgdmFyIHZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gIGlmICh2YWx1ZSAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgaWYgKHRpbWVGaWVsZCAmJiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICB2YWx1ZSA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICB9XG4gICAgaWYgKHJlc3RLZXkuaW5kZXhPZignLicpID4gMCkge1xuICAgICAgcmV0dXJuIHsga2V5LCB2YWx1ZTogcmVzdFZhbHVlIH07XG4gICAgfVxuICAgIHJldHVybiB7IGtleSwgdmFsdWUgfTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBhcnJheXNcbiAgaWYgKHJlc3RWYWx1ZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgdmFsdWUgPSByZXN0VmFsdWUubWFwKHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xuICAgIHJldHVybiB7IGtleSwgdmFsdWUgfTtcbiAgfVxuXG4gIC8vIEhhbmRsZSB1cGRhdGUgb3BlcmF0b3JzXG4gIGlmICh0eXBlb2YgcmVzdFZhbHVlID09PSAnb2JqZWN0JyAmJiAnX19vcCcgaW4gcmVzdFZhbHVlKSB7XG4gICAgcmV0dXJuIHsga2V5LCB2YWx1ZTogdHJhbnNmb3JtVXBkYXRlT3BlcmF0b3IocmVzdFZhbHVlLCBmYWxzZSkgfTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBub3JtYWwgb2JqZWN0cyBieSByZWN1cnNpbmdcbiAgdmFsdWUgPSBtYXBWYWx1ZXMocmVzdFZhbHVlLCB0cmFuc2Zvcm1JbnRlcmlvclZhbHVlKTtcbiAgcmV0dXJuIHsga2V5LCB2YWx1ZSB9O1xufTtcblxuY29uc3QgaXNSZWdleCA9IHZhbHVlID0+IHtcbiAgcmV0dXJuIHZhbHVlICYmIHZhbHVlIGluc3RhbmNlb2YgUmVnRXhwO1xufTtcblxuY29uc3QgaXNTdGFydHNXaXRoUmVnZXggPSB2YWx1ZSA9PiB7XG4gIGlmICghaXNSZWdleCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBtYXRjaGVzID0gdmFsdWUudG9TdHJpbmcoKS5tYXRjaCgvXFwvXFxeXFxcXFEuKlxcXFxFXFwvLyk7XG4gIHJldHVybiAhIW1hdGNoZXM7XG59O1xuXG5jb25zdCBpc0FsbFZhbHVlc1JlZ2V4T3JOb25lID0gdmFsdWVzID0+IHtcbiAgaWYgKCF2YWx1ZXMgfHwgIUFycmF5LmlzQXJyYXkodmFsdWVzKSB8fCB2YWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBmaXJzdFZhbHVlc0lzUmVnZXggPSBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZXNbMF0pO1xuICBpZiAodmFsdWVzLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiBmaXJzdFZhbHVlc0lzUmVnZXg7XG4gIH1cblxuICBmb3IgKGxldCBpID0gMSwgbGVuZ3RoID0gdmFsdWVzLmxlbmd0aDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGZpcnN0VmFsdWVzSXNSZWdleCAhPT0gaXNTdGFydHNXaXRoUmVnZXgodmFsdWVzW2ldKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuY29uc3QgaXNBbnlWYWx1ZVJlZ2V4ID0gdmFsdWVzID0+IHtcbiAgcmV0dXJuIHZhbHVlcy5zb21lKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGlzUmVnZXgodmFsdWUpO1xuICB9KTtcbn07XG5cbmNvbnN0IHRyYW5zZm9ybUludGVyaW9yVmFsdWUgPSByZXN0VmFsdWUgPT4ge1xuICBpZiAoXG4gICAgcmVzdFZhbHVlICE9PSBudWxsICYmXG4gICAgdHlwZW9mIHJlc3RWYWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICBPYmplY3Qua2V5cyhyZXN0VmFsdWUpLnNvbWUoa2V5ID0+IGtleS5pbmNsdWRlcygnJCcpIHx8IGtleS5pbmNsdWRlcygnLicpKVxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX05FU1RFRF9LRVksXG4gICAgICBcIk5lc3RlZCBrZXlzIHNob3VsZCBub3QgY29udGFpbiB0aGUgJyQnIG9yICcuJyBjaGFyYWN0ZXJzXCJcbiAgICApO1xuICB9XG4gIC8vIEhhbmRsZSBhdG9taWMgdmFsdWVzXG4gIHZhciB2YWx1ZSA9IHRyYW5zZm9ybUludGVyaW9yQXRvbShyZXN0VmFsdWUpO1xuICBpZiAodmFsdWUgIT09IENhbm5vdFRyYW5zZm9ybSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBhcnJheXNcbiAgaWYgKHJlc3RWYWx1ZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgcmV0dXJuIHJlc3RWYWx1ZS5tYXAodHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSk7XG4gIH1cblxuICAvLyBIYW5kbGUgdXBkYXRlIG9wZXJhdG9yc1xuICBpZiAodHlwZW9mIHJlc3RWYWx1ZSA9PT0gJ29iamVjdCcgJiYgJ19fb3AnIGluIHJlc3RWYWx1ZSkge1xuICAgIHJldHVybiB0cmFuc2Zvcm1VcGRhdGVPcGVyYXRvcihyZXN0VmFsdWUsIHRydWUpO1xuICB9XG5cbiAgLy8gSGFuZGxlIG5vcm1hbCBvYmplY3RzIGJ5IHJlY3Vyc2luZ1xuICByZXR1cm4gbWFwVmFsdWVzKHJlc3RWYWx1ZSwgdHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSk7XG59O1xuXG5jb25zdCB2YWx1ZUFzRGF0ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gbmV3IERhdGUodmFsdWUpO1xuICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59O1xuXG5mdW5jdGlvbiB0cmFuc2Zvcm1RdWVyeUtleVZhbHVlKGNsYXNzTmFtZSwga2V5LCB2YWx1ZSwgc2NoZW1hLCBjb3VudCA9IGZhbHNlKSB7XG4gIHN3aXRjaCAoa2V5KSB7XG4gICAgY2FzZSAnY3JlYXRlZEF0JzpcbiAgICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHsga2V5OiAnX2NyZWF0ZWRfYXQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpIH07XG4gICAgICB9XG4gICAgICBrZXkgPSAnX2NyZWF0ZWRfYXQnO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndXBkYXRlZEF0JzpcbiAgICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHsga2V5OiAnX3VwZGF0ZWRfYXQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpIH07XG4gICAgICB9XG4gICAgICBrZXkgPSAnX3VwZGF0ZWRfYXQnO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZXhwaXJlc0F0JzpcbiAgICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHsga2V5OiAnZXhwaXJlc0F0JywgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKSB9O1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0JzpcbiAgICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBrZXk6ICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnLFxuICAgICAgICAgIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdvYmplY3RJZCc6IHtcbiAgICAgIGlmIChbJ19HbG9iYWxDb25maWcnLCAnX0dyYXBoUUxDb25maWcnXS5pbmNsdWRlcyhjbGFzc05hbWUpKSB7XG4gICAgICAgIHZhbHVlID0gcGFyc2VJbnQodmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsga2V5OiAnX2lkJywgdmFsdWUgfTtcbiAgICB9XG4gICAgY2FzZSAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JzpcbiAgICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBrZXk6ICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnLFxuICAgICAgICAgIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfZmFpbGVkX2xvZ2luX2NvdW50JzpcbiAgICAgIHJldHVybiB7IGtleSwgdmFsdWUgfTtcbiAgICBjYXNlICdzZXNzaW9uVG9rZW4nOlxuICAgICAgcmV0dXJuIHsga2V5OiAnX3Nlc3Npb25fdG9rZW4nLCB2YWx1ZSB9O1xuICAgIGNhc2UgJ19wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGtleTogJ19wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQnLFxuICAgICAgICAgIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfcGFzc3dvcmRfY2hhbmdlZF9hdCc6XG4gICAgICBpZiAodmFsdWVBc0RhdGUodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB7IGtleTogJ19wYXNzd29yZF9jaGFuZ2VkX2F0JywgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKSB9O1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnX3JwZXJtJzpcbiAgICBjYXNlICdfd3Blcm0nOlxuICAgIGNhc2UgJ19wZXJpc2hhYmxlX3Rva2VuJzpcbiAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuJzpcbiAgICAgIHJldHVybiB7IGtleSwgdmFsdWUgfTtcbiAgICBjYXNlICckb3InOlxuICAgIGNhc2UgJyRhbmQnOlxuICAgIGNhc2UgJyRub3InOlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAga2V5OiBrZXksXG4gICAgICAgIHZhbHVlOiB2YWx1ZS5tYXAoc3ViUXVlcnkgPT5cbiAgICAgICAgICB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHN1YlF1ZXJ5LCBzY2hlbWEsIGNvdW50KVxuICAgICAgICApLFxuICAgICAgfTtcbiAgICBjYXNlICdsYXN0VXNlZCc6XG4gICAgICBpZiAodmFsdWVBc0RhdGUodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB7IGtleTogJ19sYXN0X3VzZWQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpIH07XG4gICAgICB9XG4gICAgICBrZXkgPSAnX2xhc3RfdXNlZCc7XG4gICAgICBicmVhaztcbiAgICBjYXNlICd0aW1lc1VzZWQnOlxuICAgICAgcmV0dXJuIHsga2V5OiAndGltZXNfdXNlZCcsIHZhbHVlOiB2YWx1ZSB9O1xuICAgIGRlZmF1bHQ6IHtcbiAgICAgIC8vIE90aGVyIGF1dGggZGF0YVxuICAgICAgY29uc3QgYXV0aERhdGFNYXRjaCA9IGtleS5tYXRjaCgvXmF1dGhEYXRhXFwuKFthLXpBLVowLTlfXSspXFwuaWQkLyk7XG4gICAgICBpZiAoYXV0aERhdGFNYXRjaCkge1xuICAgICAgICBjb25zdCBwcm92aWRlciA9IGF1dGhEYXRhTWF0Y2hbMV07XG4gICAgICAgIC8vIFNwZWNpYWwtY2FzZSBhdXRoIGRhdGEuXG4gICAgICAgIHJldHVybiB7IGtleTogYF9hdXRoX2RhdGFfJHtwcm92aWRlcn0uaWRgLCB2YWx1ZSB9O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGV4cGVjdGVkVHlwZUlzQXJyYXkgPVxuICAgIHNjaGVtYSAmJiBzY2hlbWEuZmllbGRzW2tleV0gJiYgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdBcnJheSc7XG5cbiAgY29uc3QgZXhwZWN0ZWRUeXBlSXNQb2ludGVyID1cbiAgICBzY2hlbWEgJiYgc2NoZW1hLmZpZWxkc1trZXldICYmIHNjaGVtYS5maWVsZHNba2V5XS50eXBlID09PSAnUG9pbnRlcic7XG5cbiAgY29uc3QgZmllbGQgPSBzY2hlbWEgJiYgc2NoZW1hLmZpZWxkc1trZXldO1xuICBpZiAoXG4gICAgZXhwZWN0ZWRUeXBlSXNQb2ludGVyIHx8XG4gICAgKCFzY2hlbWEgJiYgdmFsdWUgJiYgdmFsdWUuX190eXBlID09PSAnUG9pbnRlcicpXG4gICkge1xuICAgIGtleSA9ICdfcF8nICsga2V5O1xuICB9XG5cbiAgLy8gSGFuZGxlIHF1ZXJ5IGNvbnN0cmFpbnRzXG4gIGNvbnN0IHRyYW5zZm9ybWVkQ29uc3RyYWludCA9IHRyYW5zZm9ybUNvbnN0cmFpbnQodmFsdWUsIGZpZWxkLCBjb3VudCk7XG4gIGlmICh0cmFuc2Zvcm1lZENvbnN0cmFpbnQgIT09IENhbm5vdFRyYW5zZm9ybSkge1xuICAgIGlmICh0cmFuc2Zvcm1lZENvbnN0cmFpbnQuJHRleHQpIHtcbiAgICAgIHJldHVybiB7IGtleTogJyR0ZXh0JywgdmFsdWU6IHRyYW5zZm9ybWVkQ29uc3RyYWludC4kdGV4dCB9O1xuICAgIH1cbiAgICBpZiAodHJhbnNmb3JtZWRDb25zdHJhaW50LiRlbGVtTWF0Y2gpIHtcbiAgICAgIHJldHVybiB7IGtleTogJyRub3InLCB2YWx1ZTogW3sgW2tleV06IHRyYW5zZm9ybWVkQ29uc3RyYWludCB9XSB9O1xuICAgIH1cbiAgICByZXR1cm4geyBrZXksIHZhbHVlOiB0cmFuc2Zvcm1lZENvbnN0cmFpbnQgfTtcbiAgfVxuXG4gIGlmIChleHBlY3RlZFR5cGVJc0FycmF5ICYmICEodmFsdWUgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICByZXR1cm4geyBrZXksIHZhbHVlOiB7ICRhbGw6IFt0cmFuc2Zvcm1JbnRlcmlvckF0b20odmFsdWUpXSB9IH07XG4gIH1cblxuICAvLyBIYW5kbGUgYXRvbWljIHZhbHVlc1xuICBpZiAodHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHZhbHVlKSAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgcmV0dXJuIHsga2V5LCB2YWx1ZTogdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHZhbHVlKSB9O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgIGBZb3UgY2Fubm90IHVzZSAke3ZhbHVlfSBhcyBhIHF1ZXJ5IHBhcmFtZXRlci5gXG4gICAgKTtcbiAgfVxufVxuXG4vLyBNYWluIGV4cG9zZWQgbWV0aG9kIHRvIGhlbHAgcnVuIHF1ZXJpZXMuXG4vLyByZXN0V2hlcmUgaXMgdGhlIFwid2hlcmVcIiBjbGF1c2UgaW4gUkVTVCBBUEkgZm9ybS5cbi8vIFJldHVybnMgdGhlIG1vbmdvIGZvcm0gb2YgdGhlIHF1ZXJ5LlxuZnVuY3Rpb24gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCByZXN0V2hlcmUsIHNjaGVtYSwgY291bnQgPSBmYWxzZSkge1xuICBjb25zdCBtb25nb1doZXJlID0ge307XG4gIGZvciAoY29uc3QgcmVzdEtleSBpbiByZXN0V2hlcmUpIHtcbiAgICBjb25zdCBvdXQgPSB0cmFuc2Zvcm1RdWVyeUtleVZhbHVlKFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgcmVzdEtleSxcbiAgICAgIHJlc3RXaGVyZVtyZXN0S2V5XSxcbiAgICAgIHNjaGVtYSxcbiAgICAgIGNvdW50XG4gICAgKTtcbiAgICBtb25nb1doZXJlW291dC5rZXldID0gb3V0LnZhbHVlO1xuICB9XG4gIHJldHVybiBtb25nb1doZXJlO1xufVxuXG5jb25zdCBwYXJzZU9iamVjdEtleVZhbHVlVG9Nb25nb09iamVjdEtleVZhbHVlID0gKFxuICByZXN0S2V5LFxuICByZXN0VmFsdWUsXG4gIHNjaGVtYVxuKSA9PiB7XG4gIC8vIENoZWNrIGlmIHRoZSBzY2hlbWEgaXMga25vd24gc2luY2UgaXQncyBhIGJ1aWx0LWluIGZpZWxkLlxuICBsZXQgdHJhbnNmb3JtZWRWYWx1ZTtcbiAgbGV0IGNvZXJjZWRUb0RhdGU7XG4gIHN3aXRjaCAocmVzdEtleSkge1xuICAgIGNhc2UgJ29iamVjdElkJzpcbiAgICAgIHJldHVybiB7IGtleTogJ19pZCcsIHZhbHVlOiByZXN0VmFsdWUgfTtcbiAgICBjYXNlICdleHBpcmVzQXQnOlxuICAgICAgdHJhbnNmb3JtZWRWYWx1ZSA9IHRyYW5zZm9ybVRvcExldmVsQXRvbShyZXN0VmFsdWUpO1xuICAgICAgY29lcmNlZFRvRGF0ZSA9XG4gICAgICAgIHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlID09PSAnc3RyaW5nJ1xuICAgICAgICAgID8gbmV3IERhdGUodHJhbnNmb3JtZWRWYWx1ZSlcbiAgICAgICAgICA6IHRyYW5zZm9ybWVkVmFsdWU7XG4gICAgICByZXR1cm4geyBrZXk6ICdleHBpcmVzQXQnLCB2YWx1ZTogY29lcmNlZFRvRGF0ZSB9O1xuICAgIGNhc2UgJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAgICB0cmFuc2Zvcm1lZFZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gICAgICBjb2VyY2VkVG9EYXRlID1cbiAgICAgICAgdHlwZW9mIHRyYW5zZm9ybWVkVmFsdWUgPT09ICdzdHJpbmcnXG4gICAgICAgICAgPyBuZXcgRGF0ZSh0cmFuc2Zvcm1lZFZhbHVlKVxuICAgICAgICAgIDogdHJhbnNmb3JtZWRWYWx1ZTtcbiAgICAgIHJldHVybiB7IGtleTogJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCcsIHZhbHVlOiBjb2VyY2VkVG9EYXRlIH07XG4gICAgY2FzZSAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JzpcbiAgICAgIHRyYW5zZm9ybWVkVmFsdWUgPSB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20ocmVzdFZhbHVlKTtcbiAgICAgIGNvZXJjZWRUb0RhdGUgPVxuICAgICAgICB0eXBlb2YgdHJhbnNmb3JtZWRWYWx1ZSA9PT0gJ3N0cmluZydcbiAgICAgICAgICA/IG5ldyBEYXRlKHRyYW5zZm9ybWVkVmFsdWUpXG4gICAgICAgICAgOiB0cmFuc2Zvcm1lZFZhbHVlO1xuICAgICAgcmV0dXJuIHsga2V5OiAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JywgdmFsdWU6IGNvZXJjZWRUb0RhdGUgfTtcbiAgICBjYXNlICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JzpcbiAgICAgIHRyYW5zZm9ybWVkVmFsdWUgPSB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20ocmVzdFZhbHVlKTtcbiAgICAgIGNvZXJjZWRUb0RhdGUgPVxuICAgICAgICB0eXBlb2YgdHJhbnNmb3JtZWRWYWx1ZSA9PT0gJ3N0cmluZydcbiAgICAgICAgICA/IG5ldyBEYXRlKHRyYW5zZm9ybWVkVmFsdWUpXG4gICAgICAgICAgOiB0cmFuc2Zvcm1lZFZhbHVlO1xuICAgICAgcmV0dXJuIHsga2V5OiAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCcsIHZhbHVlOiBjb2VyY2VkVG9EYXRlIH07XG4gICAgY2FzZSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnOlxuICAgICAgdHJhbnNmb3JtZWRWYWx1ZSA9IHRyYW5zZm9ybVRvcExldmVsQXRvbShyZXN0VmFsdWUpO1xuICAgICAgY29lcmNlZFRvRGF0ZSA9XG4gICAgICAgIHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlID09PSAnc3RyaW5nJ1xuICAgICAgICAgID8gbmV3IERhdGUodHJhbnNmb3JtZWRWYWx1ZSlcbiAgICAgICAgICA6IHRyYW5zZm9ybWVkVmFsdWU7XG4gICAgICByZXR1cm4geyBrZXk6ICdfcGFzc3dvcmRfY2hhbmdlZF9hdCcsIHZhbHVlOiBjb2VyY2VkVG9EYXRlIH07XG4gICAgY2FzZSAnX2ZhaWxlZF9sb2dpbl9jb3VudCc6XG4gICAgY2FzZSAnX3JwZXJtJzpcbiAgICBjYXNlICdfd3Blcm0nOlxuICAgIGNhc2UgJ19lbWFpbF92ZXJpZnlfdG9rZW4nOlxuICAgIGNhc2UgJ19oYXNoZWRfcGFzc3dvcmQnOlxuICAgIGNhc2UgJ19wZXJpc2hhYmxlX3Rva2VuJzpcbiAgICAgIHJldHVybiB7IGtleTogcmVzdEtleSwgdmFsdWU6IHJlc3RWYWx1ZSB9O1xuICAgIGNhc2UgJ3Nlc3Npb25Ub2tlbic6XG4gICAgICByZXR1cm4geyBrZXk6ICdfc2Vzc2lvbl90b2tlbicsIHZhbHVlOiByZXN0VmFsdWUgfTtcbiAgICBkZWZhdWx0OlxuICAgICAgLy8gQXV0aCBkYXRhIHNob3VsZCBoYXZlIGJlZW4gdHJhbnNmb3JtZWQgYWxyZWFkeVxuICAgICAgaWYgKHJlc3RLZXkubWF0Y2goL15hdXRoRGF0YVxcLihbYS16QS1aMC05X10rKVxcLmlkJC8pKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICAgICdjYW4gb25seSBxdWVyeSBvbiAnICsgcmVzdEtleVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy8gVHJ1c3QgdGhhdCB0aGUgYXV0aCBkYXRhIGhhcyBiZWVuIHRyYW5zZm9ybWVkIGFuZCBzYXZlIGl0IGRpcmVjdGx5XG4gICAgICBpZiAocmVzdEtleS5tYXRjaCgvXl9hdXRoX2RhdGFfW2EtekEtWjAtOV9dKyQvKSkge1xuICAgICAgICByZXR1cm4geyBrZXk6IHJlc3RLZXksIHZhbHVlOiByZXN0VmFsdWUgfTtcbiAgICAgIH1cbiAgfVxuICAvL3NraXAgc3RyYWlnaHQgdG8gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tIGZvciBCeXRlcywgdGhleSBkb24ndCBzaG93IHVwIGluIHRoZSBzY2hlbWEgZm9yIHNvbWUgcmVhc29uXG4gIGlmIChyZXN0VmFsdWUgJiYgcmVzdFZhbHVlLl9fdHlwZSAhPT0gJ0J5dGVzJykge1xuICAgIC8vTm90ZTogV2UgbWF5IG5vdCBrbm93IHRoZSB0eXBlIG9mIGEgZmllbGQgaGVyZSwgYXMgdGhlIHVzZXIgY291bGQgYmUgc2F2aW5nIChudWxsKSB0byBhIGZpZWxkXG4gICAgLy9UaGF0IG5ldmVyIGV4aXN0ZWQgYmVmb3JlLCBtZWFuaW5nIHdlIGNhbid0IGluZmVyIHRoZSB0eXBlLlxuICAgIGlmIChcbiAgICAgIChzY2hlbWEuZmllbGRzW3Jlc3RLZXldICYmIHNjaGVtYS5maWVsZHNbcmVzdEtleV0udHlwZSA9PSAnUG9pbnRlcicpIHx8XG4gICAgICByZXN0VmFsdWUuX190eXBlID09ICdQb2ludGVyJ1xuICAgICkge1xuICAgICAgcmVzdEtleSA9ICdfcF8nICsgcmVzdEtleTtcbiAgICB9XG4gIH1cblxuICAvLyBIYW5kbGUgYXRvbWljIHZhbHVlc1xuICB2YXIgdmFsdWUgPSB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20ocmVzdFZhbHVlKTtcbiAgaWYgKHZhbHVlICE9PSBDYW5ub3RUcmFuc2Zvcm0pIHtcbiAgICByZXR1cm4geyBrZXk6IHJlc3RLZXksIHZhbHVlOiB2YWx1ZSB9O1xuICB9XG5cbiAgLy8gQUNMcyBhcmUgaGFuZGxlZCBiZWZvcmUgdGhpcyBtZXRob2QgaXMgY2FsbGVkXG4gIC8vIElmIGFuIEFDTCBrZXkgc3RpbGwgZXhpc3RzIGhlcmUsIHNvbWV0aGluZyBpcyB3cm9uZy5cbiAgaWYgKHJlc3RLZXkgPT09ICdBQ0wnKSB7XG4gICAgdGhyb3cgJ1RoZXJlIHdhcyBhIHByb2JsZW0gdHJhbnNmb3JtaW5nIGFuIEFDTC4nO1xuICB9XG5cbiAgLy8gSGFuZGxlIGFycmF5c1xuICBpZiAocmVzdFZhbHVlIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICB2YWx1ZSA9IHJlc3RWYWx1ZS5tYXAodHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSk7XG4gICAgcmV0dXJuIHsga2V5OiByZXN0S2V5LCB2YWx1ZTogdmFsdWUgfTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBub3JtYWwgb2JqZWN0cyBieSByZWN1cnNpbmdcbiAgaWYgKFxuICAgIE9iamVjdC5rZXlzKHJlc3RWYWx1ZSkuc29tZShrZXkgPT4ga2V5LmluY2x1ZGVzKCckJykgfHwga2V5LmluY2x1ZGVzKCcuJykpXG4gICkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfTkVTVEVEX0tFWSxcbiAgICAgIFwiTmVzdGVkIGtleXMgc2hvdWxkIG5vdCBjb250YWluIHRoZSAnJCcgb3IgJy4nIGNoYXJhY3RlcnNcIlxuICAgICk7XG4gIH1cbiAgdmFsdWUgPSBtYXBWYWx1ZXMocmVzdFZhbHVlLCB0cmFuc2Zvcm1JbnRlcmlvclZhbHVlKTtcbiAgcmV0dXJuIHsga2V5OiByZXN0S2V5LCB2YWx1ZSB9O1xufTtcblxuY29uc3QgcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlID0gKGNsYXNzTmFtZSwgcmVzdENyZWF0ZSwgc2NoZW1hKSA9PiB7XG4gIHJlc3RDcmVhdGUgPSBhZGRMZWdhY3lBQ0wocmVzdENyZWF0ZSk7XG4gIGNvbnN0IG1vbmdvQ3JlYXRlID0ge307XG4gIGZvciAoY29uc3QgcmVzdEtleSBpbiByZXN0Q3JlYXRlKSB7XG4gICAgaWYgKHJlc3RDcmVhdGVbcmVzdEtleV0gJiYgcmVzdENyZWF0ZVtyZXN0S2V5XS5fX3R5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCB7IGtleSwgdmFsdWUgfSA9IHBhcnNlT2JqZWN0S2V5VmFsdWVUb01vbmdvT2JqZWN0S2V5VmFsdWUoXG4gICAgICByZXN0S2V5LFxuICAgICAgcmVzdENyZWF0ZVtyZXN0S2V5XSxcbiAgICAgIHNjaGVtYVxuICAgICk7XG4gICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG1vbmdvQ3JlYXRlW2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICAvLyBVc2UgdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQgZm9yIGNyZWF0ZWRBdCBhbmQgdXBkYXRlZEF0XG4gIGlmIChtb25nb0NyZWF0ZS5jcmVhdGVkQXQpIHtcbiAgICBtb25nb0NyZWF0ZS5fY3JlYXRlZF9hdCA9IG5ldyBEYXRlKFxuICAgICAgbW9uZ29DcmVhdGUuY3JlYXRlZEF0LmlzbyB8fCBtb25nb0NyZWF0ZS5jcmVhdGVkQXRcbiAgICApO1xuICAgIGRlbGV0ZSBtb25nb0NyZWF0ZS5jcmVhdGVkQXQ7XG4gIH1cbiAgaWYgKG1vbmdvQ3JlYXRlLnVwZGF0ZWRBdCkge1xuICAgIG1vbmdvQ3JlYXRlLl91cGRhdGVkX2F0ID0gbmV3IERhdGUoXG4gICAgICBtb25nb0NyZWF0ZS51cGRhdGVkQXQuaXNvIHx8IG1vbmdvQ3JlYXRlLnVwZGF0ZWRBdFxuICAgICk7XG4gICAgZGVsZXRlIG1vbmdvQ3JlYXRlLnVwZGF0ZWRBdDtcbiAgfVxuXG4gIHJldHVybiBtb25nb0NyZWF0ZTtcbn07XG5cbi8vIE1haW4gZXhwb3NlZCBtZXRob2QgdG8gaGVscCB1cGRhdGUgb2xkIG9iamVjdHMuXG5jb25zdCB0cmFuc2Zvcm1VcGRhdGUgPSAoY2xhc3NOYW1lLCByZXN0VXBkYXRlLCBwYXJzZUZvcm1hdFNjaGVtYSkgPT4ge1xuICBjb25zdCBtb25nb1VwZGF0ZSA9IHt9O1xuICBjb25zdCBhY2wgPSBhZGRMZWdhY3lBQ0wocmVzdFVwZGF0ZSk7XG4gIGlmIChhY2wuX3JwZXJtIHx8IGFjbC5fd3Blcm0gfHwgYWNsLl9hY2wpIHtcbiAgICBtb25nb1VwZGF0ZS4kc2V0ID0ge307XG4gICAgaWYgKGFjbC5fcnBlcm0pIHtcbiAgICAgIG1vbmdvVXBkYXRlLiRzZXQuX3JwZXJtID0gYWNsLl9ycGVybTtcbiAgICB9XG4gICAgaWYgKGFjbC5fd3Blcm0pIHtcbiAgICAgIG1vbmdvVXBkYXRlLiRzZXQuX3dwZXJtID0gYWNsLl93cGVybTtcbiAgICB9XG4gICAgaWYgKGFjbC5fYWNsKSB7XG4gICAgICBtb25nb1VwZGF0ZS4kc2V0Ll9hY2wgPSBhY2wuX2FjbDtcbiAgICB9XG4gIH1cbiAgZm9yICh2YXIgcmVzdEtleSBpbiByZXN0VXBkYXRlKSB7XG4gICAgaWYgKHJlc3RVcGRhdGVbcmVzdEtleV0gJiYgcmVzdFVwZGF0ZVtyZXN0S2V5XS5fX3R5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICB2YXIgb3V0ID0gdHJhbnNmb3JtS2V5VmFsdWVGb3JVcGRhdGUoXG4gICAgICBjbGFzc05hbWUsXG4gICAgICByZXN0S2V5LFxuICAgICAgcmVzdFVwZGF0ZVtyZXN0S2V5XSxcbiAgICAgIHBhcnNlRm9ybWF0U2NoZW1hXG4gICAgKTtcblxuICAgIC8vIElmIHRoZSBvdXRwdXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW55ICQga2V5cywgaXQncyBhblxuICAgIC8vIG9wZXJhdG9yIHRoYXQgbmVlZHMgdG8gYmUgbGlmdGVkIG9udG8gdGhlIHRvcCBsZXZlbCB1cGRhdGVcbiAgICAvLyBvYmplY3QuXG4gICAgaWYgKHR5cGVvZiBvdXQudmFsdWUgPT09ICdvYmplY3QnICYmIG91dC52YWx1ZSAhPT0gbnVsbCAmJiBvdXQudmFsdWUuX19vcCkge1xuICAgICAgbW9uZ29VcGRhdGVbb3V0LnZhbHVlLl9fb3BdID0gbW9uZ29VcGRhdGVbb3V0LnZhbHVlLl9fb3BdIHx8IHt9O1xuICAgICAgbW9uZ29VcGRhdGVbb3V0LnZhbHVlLl9fb3BdW291dC5rZXldID0gb3V0LnZhbHVlLmFyZztcbiAgICB9IGVsc2Uge1xuICAgICAgbW9uZ29VcGRhdGVbJyRzZXQnXSA9IG1vbmdvVXBkYXRlWyckc2V0J10gfHwge307XG4gICAgICBtb25nb1VwZGF0ZVsnJHNldCddW291dC5rZXldID0gb3V0LnZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtb25nb1VwZGF0ZTtcbn07XG5cbi8vIEFkZCB0aGUgbGVnYWN5IF9hY2wgZm9ybWF0LlxuY29uc3QgYWRkTGVnYWN5QUNMID0gcmVzdE9iamVjdCA9PiB7XG4gIGNvbnN0IHJlc3RPYmplY3RDb3B5ID0geyAuLi5yZXN0T2JqZWN0IH07XG4gIGNvbnN0IF9hY2wgPSB7fTtcblxuICBpZiAocmVzdE9iamVjdC5fd3Blcm0pIHtcbiAgICByZXN0T2JqZWN0Ll93cGVybS5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIF9hY2xbZW50cnldID0geyB3OiB0cnVlIH07XG4gICAgfSk7XG4gICAgcmVzdE9iamVjdENvcHkuX2FjbCA9IF9hY2w7XG4gIH1cblxuICBpZiAocmVzdE9iamVjdC5fcnBlcm0pIHtcbiAgICByZXN0T2JqZWN0Ll9ycGVybS5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIGlmICghKGVudHJ5IGluIF9hY2wpKSB7XG4gICAgICAgIF9hY2xbZW50cnldID0geyByOiB0cnVlIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfYWNsW2VudHJ5XS5yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXN0T2JqZWN0Q29weS5fYWNsID0gX2FjbDtcbiAgfVxuXG4gIHJldHVybiByZXN0T2JqZWN0Q29weTtcbn07XG5cbi8vIEEgc2VudGluZWwgdmFsdWUgdGhhdCBoZWxwZXIgdHJhbnNmb3JtYXRpb25zIHJldHVybiB3aGVuIHRoZXlcbi8vIGNhbm5vdCBwZXJmb3JtIGEgdHJhbnNmb3JtYXRpb25cbmZ1bmN0aW9uIENhbm5vdFRyYW5zZm9ybSgpIHt9XG5cbmNvbnN0IHRyYW5zZm9ybUludGVyaW9yQXRvbSA9IGF0b20gPT4ge1xuICAvLyBUT0RPOiBjaGVjayB2YWxpZGl0eSBoYXJkZXIgZm9yIHRoZSBfX3R5cGUtZGVmaW5lZCB0eXBlc1xuICBpZiAoXG4gICAgdHlwZW9mIGF0b20gPT09ICdvYmplY3QnICYmXG4gICAgYXRvbSAmJlxuICAgICEoYXRvbSBpbnN0YW5jZW9mIERhdGUpICYmXG4gICAgYXRvbS5fX3R5cGUgPT09ICdQb2ludGVyJ1xuICApIHtcbiAgICByZXR1cm4ge1xuICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICBjbGFzc05hbWU6IGF0b20uY2xhc3NOYW1lLFxuICAgICAgb2JqZWN0SWQ6IGF0b20ub2JqZWN0SWQsXG4gICAgfTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgYXRvbSA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgYXRvbSA9PT0gJ3N5bWJvbCcpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICBgY2Fubm90IHRyYW5zZm9ybSB2YWx1ZTogJHthdG9tfWBcbiAgICApO1xuICB9IGVsc2UgaWYgKERhdGVDb2Rlci5pc1ZhbGlkSlNPTihhdG9tKSkge1xuICAgIHJldHVybiBEYXRlQ29kZXIuSlNPTlRvRGF0YWJhc2UoYXRvbSk7XG4gIH0gZWxzZSBpZiAoQnl0ZXNDb2Rlci5pc1ZhbGlkSlNPTihhdG9tKSkge1xuICAgIHJldHVybiBCeXRlc0NvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBhdG9tID09PSAnb2JqZWN0JyAmJiBhdG9tICYmIGF0b20uJHJlZ2V4ICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChhdG9tLiRyZWdleCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF0b207XG4gIH1cbn07XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byB0cmFuc2Zvcm0gYW4gYXRvbSBmcm9tIFJFU1QgZm9ybWF0IHRvIE1vbmdvIGZvcm1hdC5cbi8vIEFuIGF0b20gaXMgYW55dGhpbmcgdGhhdCBjYW4ndCBjb250YWluIG90aGVyIGV4cHJlc3Npb25zLiBTbyBpdFxuLy8gaW5jbHVkZXMgdGhpbmdzIHdoZXJlIG9iamVjdHMgYXJlIHVzZWQgdG8gcmVwcmVzZW50IG90aGVyXG4vLyBkYXRhdHlwZXMsIGxpa2UgcG9pbnRlcnMgYW5kIGRhdGVzLCBidXQgaXQgZG9lcyBub3QgaW5jbHVkZSBvYmplY3RzXG4vLyBvciBhcnJheXMgd2l0aCBnZW5lcmljIHN0dWZmIGluc2lkZS5cbi8vIFJhaXNlcyBhbiBlcnJvciBpZiB0aGlzIGNhbm5vdCBwb3NzaWJseSBiZSB2YWxpZCBSRVNUIGZvcm1hdC5cbi8vIFJldHVybnMgQ2Fubm90VHJhbnNmb3JtIGlmIGl0J3MganVzdCBub3QgYW4gYXRvbVxuZnVuY3Rpb24gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKGF0b20sIGZpZWxkKSB7XG4gIHN3aXRjaCAodHlwZW9mIGF0b20pIHtcbiAgICBjYXNlICdudW1iZXInOlxuICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICByZXR1cm4gYXRvbTtcbiAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm4gYCR7ZmllbGQudGFyZ2V0Q2xhc3N9JCR7YXRvbX1gO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGF0b207XG4gICAgY2FzZSAnc3ltYm9sJzpcbiAgICBjYXNlICdmdW5jdGlvbic6XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgYGNhbm5vdCB0cmFuc2Zvcm0gdmFsdWU6ICR7YXRvbX1gXG4gICAgICApO1xuICAgIGNhc2UgJ29iamVjdCc6XG4gICAgICBpZiAoYXRvbSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgLy8gVGVjaG5pY2FsbHkgZGF0ZXMgYXJlIG5vdCByZXN0IGZvcm1hdCwgYnV0LCBpdCBzZWVtcyBwcmV0dHlcbiAgICAgICAgLy8gY2xlYXIgd2hhdCB0aGV5IHNob3VsZCBiZSB0cmFuc2Zvcm1lZCB0bywgc28gbGV0J3MganVzdCBkbyBpdC5cbiAgICAgICAgcmV0dXJuIGF0b207XG4gICAgICB9XG5cbiAgICAgIGlmIChhdG9tID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBhdG9tO1xuICAgICAgfVxuXG4gICAgICAvLyBUT0RPOiBjaGVjayB2YWxpZGl0eSBoYXJkZXIgZm9yIHRoZSBfX3R5cGUtZGVmaW5lZCB0eXBlc1xuICAgICAgaWYgKGF0b20uX190eXBlID09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm4gYCR7YXRvbS5jbGFzc05hbWV9JCR7YXRvbS5vYmplY3RJZH1gO1xuICAgICAgfVxuICAgICAgaWYgKERhdGVDb2Rlci5pc1ZhbGlkSlNPTihhdG9tKSkge1xuICAgICAgICByZXR1cm4gRGF0ZUNvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICAgICAgfVxuICAgICAgaWYgKEJ5dGVzQ29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICAgICAgcmV0dXJuIEJ5dGVzQ29kZXIuSlNPTlRvRGF0YWJhc2UoYXRvbSk7XG4gICAgICB9XG4gICAgICBpZiAoR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihhdG9tKSkge1xuICAgICAgICByZXR1cm4gR2VvUG9pbnRDb2Rlci5KU09OVG9EYXRhYmFzZShhdG9tKTtcbiAgICAgIH1cbiAgICAgIGlmIChQb2x5Z29uQ29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICAgICAgcmV0dXJuIFBvbHlnb25Db2Rlci5KU09OVG9EYXRhYmFzZShhdG9tKTtcbiAgICAgIH1cbiAgICAgIGlmIChGaWxlQ29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICAgICAgcmV0dXJuIEZpbGVDb2Rlci5KU09OVG9EYXRhYmFzZShhdG9tKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBDYW5ub3RUcmFuc2Zvcm07XG5cbiAgICBkZWZhdWx0OlxuICAgICAgLy8gSSBkb24ndCB0aGluayB0eXBlb2YgY2FuIGV2ZXIgbGV0IHVzIGdldCBoZXJlXG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgYHJlYWxseSBkaWQgbm90IGV4cGVjdCB2YWx1ZTogJHthdG9tfWBcbiAgICAgICk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVsYXRpdmVUaW1lVG9EYXRlKHRleHQsIG5vdyA9IG5ldyBEYXRlKCkpIHtcbiAgdGV4dCA9IHRleHQudG9Mb3dlckNhc2UoKTtcblxuICBsZXQgcGFydHMgPSB0ZXh0LnNwbGl0KCcgJyk7XG5cbiAgLy8gRmlsdGVyIG91dCB3aGl0ZXNwYWNlXG4gIHBhcnRzID0gcGFydHMuZmlsdGVyKHBhcnQgPT4gcGFydCAhPT0gJycpO1xuXG4gIGNvbnN0IGZ1dHVyZSA9IHBhcnRzWzBdID09PSAnaW4nO1xuICBjb25zdCBwYXN0ID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gPT09ICdhZ28nO1xuXG4gIGlmICghZnV0dXJlICYmICFwYXN0ICYmIHRleHQgIT09ICdub3cnKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogJ2Vycm9yJyxcbiAgICAgIGluZm86IFwiVGltZSBzaG91bGQgZWl0aGVyIHN0YXJ0IHdpdGggJ2luJyBvciBlbmQgd2l0aCAnYWdvJ1wiLFxuICAgIH07XG4gIH1cblxuICBpZiAoZnV0dXJlICYmIHBhc3QpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhdHVzOiAnZXJyb3InLFxuICAgICAgaW5mbzogXCJUaW1lIGNhbm5vdCBoYXZlIGJvdGggJ2luJyBhbmQgJ2FnbydcIixcbiAgICB9O1xuICB9XG5cbiAgLy8gc3RyaXAgdGhlICdhZ28nIG9yICdpbidcbiAgaWYgKGZ1dHVyZSkge1xuICAgIHBhcnRzID0gcGFydHMuc2xpY2UoMSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gcGFzdFxuICAgIHBhcnRzID0gcGFydHMuc2xpY2UoMCwgcGFydHMubGVuZ3RoIC0gMSk7XG4gIH1cblxuICBpZiAocGFydHMubGVuZ3RoICUgMiAhPT0gMCAmJiB0ZXh0ICE9PSAnbm93Jykge1xuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXM6ICdlcnJvcicsXG4gICAgICBpbmZvOiAnSW52YWxpZCB0aW1lIHN0cmluZy4gRGFuZ2xpbmcgdW5pdCBvciBudW1iZXIuJyxcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgcGFpcnMgPSBbXTtcbiAgd2hpbGUgKHBhcnRzLmxlbmd0aCkge1xuICAgIHBhaXJzLnB1c2goW3BhcnRzLnNoaWZ0KCksIHBhcnRzLnNoaWZ0KCldKTtcbiAgfVxuXG4gIGxldCBzZWNvbmRzID0gMDtcbiAgZm9yIChjb25zdCBbbnVtLCBpbnRlcnZhbF0gb2YgcGFpcnMpIHtcbiAgICBjb25zdCB2YWwgPSBOdW1iZXIobnVtKTtcbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIodmFsKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhdHVzOiAnZXJyb3InLFxuICAgICAgICBpbmZvOiBgJyR7bnVtfScgaXMgbm90IGFuIGludGVnZXIuYCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgc3dpdGNoIChpbnRlcnZhbCkge1xuICAgICAgY2FzZSAneXInOlxuICAgICAgY2FzZSAneXJzJzpcbiAgICAgIGNhc2UgJ3llYXInOlxuICAgICAgY2FzZSAneWVhcnMnOlxuICAgICAgICBzZWNvbmRzICs9IHZhbCAqIDMxNTM2MDAwOyAvLyAzNjUgKiAyNCAqIDYwICogNjBcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3drJzpcbiAgICAgIGNhc2UgJ3drcyc6XG4gICAgICBjYXNlICd3ZWVrJzpcbiAgICAgIGNhc2UgJ3dlZWtzJzpcbiAgICAgICAgc2Vjb25kcyArPSB2YWwgKiA2MDQ4MDA7IC8vIDcgKiAyNCAqIDYwICogNjBcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2QnOlxuICAgICAgY2FzZSAnZGF5JzpcbiAgICAgIGNhc2UgJ2RheXMnOlxuICAgICAgICBzZWNvbmRzICs9IHZhbCAqIDg2NDAwOyAvLyAyNCAqIDYwICogNjBcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2hyJzpcbiAgICAgIGNhc2UgJ2hycyc6XG4gICAgICBjYXNlICdob3VyJzpcbiAgICAgIGNhc2UgJ2hvdXJzJzpcbiAgICAgICAgc2Vjb25kcyArPSB2YWwgKiAzNjAwOyAvLyA2MCAqIDYwXG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdtaW4nOlxuICAgICAgY2FzZSAnbWlucyc6XG4gICAgICBjYXNlICdtaW51dGUnOlxuICAgICAgY2FzZSAnbWludXRlcyc6XG4gICAgICAgIHNlY29uZHMgKz0gdmFsICogNjA7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdzZWMnOlxuICAgICAgY2FzZSAnc2Vjcyc6XG4gICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgY2FzZSAnc2Vjb25kcyc6XG4gICAgICAgIHNlY29uZHMgKz0gdmFsO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdGF0dXM6ICdlcnJvcicsXG4gICAgICAgICAgaW5mbzogYEludmFsaWQgaW50ZXJ2YWw6ICcke2ludGVydmFsfSdgLFxuICAgICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG1pbGxpc2Vjb25kcyA9IHNlY29uZHMgKiAxMDAwO1xuICBpZiAoZnV0dXJlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnLFxuICAgICAgaW5mbzogJ2Z1dHVyZScsXG4gICAgICByZXN1bHQ6IG5ldyBEYXRlKG5vdy52YWx1ZU9mKCkgKyBtaWxsaXNlY29uZHMpLFxuICAgIH07XG4gIH0gZWxzZSBpZiAocGFzdCkge1xuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJyxcbiAgICAgIGluZm86ICdwYXN0JyxcbiAgICAgIHJlc3VsdDogbmV3IERhdGUobm93LnZhbHVlT2YoKSAtIG1pbGxpc2Vjb25kcyksXG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhdHVzOiAnc3VjY2VzcycsXG4gICAgICBpbmZvOiAncHJlc2VudCcsXG4gICAgICByZXN1bHQ6IG5ldyBEYXRlKG5vdy52YWx1ZU9mKCkpLFxuICAgIH07XG4gIH1cbn1cblxuLy8gVHJhbnNmb3JtcyBhIHF1ZXJ5IGNvbnN0cmFpbnQgZnJvbSBSRVNUIEFQSSBmb3JtYXQgdG8gTW9uZ28gZm9ybWF0LlxuLy8gQSBjb25zdHJhaW50IGlzIHNvbWV0aGluZyB3aXRoIGZpZWxkcyBsaWtlICRsdC5cbi8vIElmIGl0IGlzIG5vdCBhIHZhbGlkIGNvbnN0cmFpbnQgYnV0IGl0IGNvdWxkIGJlIGEgdmFsaWQgc29tZXRoaW5nXG4vLyBlbHNlLCByZXR1cm4gQ2Fubm90VHJhbnNmb3JtLlxuLy8gaW5BcnJheSBpcyB3aGV0aGVyIHRoaXMgaXMgYW4gYXJyYXkgZmllbGQuXG5mdW5jdGlvbiB0cmFuc2Zvcm1Db25zdHJhaW50KGNvbnN0cmFpbnQsIGZpZWxkLCBjb3VudCA9IGZhbHNlKSB7XG4gIGNvbnN0IGluQXJyYXkgPSBmaWVsZCAmJiBmaWVsZC50eXBlICYmIGZpZWxkLnR5cGUgPT09ICdBcnJheSc7XG4gIGlmICh0eXBlb2YgY29uc3RyYWludCAhPT0gJ29iamVjdCcgfHwgIWNvbnN0cmFpbnQpIHtcbiAgICByZXR1cm4gQ2Fubm90VHJhbnNmb3JtO1xuICB9XG4gIGNvbnN0IHRyYW5zZm9ybUZ1bmN0aW9uID0gaW5BcnJheVxuICAgID8gdHJhbnNmb3JtSW50ZXJpb3JBdG9tXG4gICAgOiB0cmFuc2Zvcm1Ub3BMZXZlbEF0b207XG4gIGNvbnN0IHRyYW5zZm9ybWVyID0gYXRvbSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtRnVuY3Rpb24oYXRvbSwgZmllbGQpO1xuICAgIGlmIChyZXN1bHQgPT09IENhbm5vdFRyYW5zZm9ybSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgIGBiYWQgYXRvbTogJHtKU09OLnN0cmluZ2lmeShhdG9tKX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuICAvLyBrZXlzIGlzIHRoZSBjb25zdHJhaW50cyBpbiByZXZlcnNlIGFscGhhYmV0aWNhbCBvcmRlci5cbiAgLy8gVGhpcyBpcyBhIGhhY2sgc28gdGhhdDpcbiAgLy8gICAkcmVnZXggaXMgaGFuZGxlZCBiZWZvcmUgJG9wdGlvbnNcbiAgLy8gICAkbmVhclNwaGVyZSBpcyBoYW5kbGVkIGJlZm9yZSAkbWF4RGlzdGFuY2VcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhjb25zdHJhaW50KVxuICAgIC5zb3J0KClcbiAgICAucmV2ZXJzZSgpO1xuICB2YXIgYW5zd2VyID0ge307XG4gIGZvciAodmFyIGtleSBvZiBrZXlzKSB7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgIGNhc2UgJyRsdCc6XG4gICAgICBjYXNlICckbHRlJzpcbiAgICAgIGNhc2UgJyRndCc6XG4gICAgICBjYXNlICckZ3RlJzpcbiAgICAgIGNhc2UgJyRleGlzdHMnOlxuICAgICAgY2FzZSAnJG5lJzpcbiAgICAgIGNhc2UgJyRlcSc6IHtcbiAgICAgICAgY29uc3QgdmFsID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAodmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnICYmIHZhbC4kcmVsYXRpdmVUaW1lKSB7XG4gICAgICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLnR5cGUgIT09ICdEYXRlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICckcmVsYXRpdmVUaW1lIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBEYXRlIGZpZWxkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAnJGV4aXN0cyc6XG4gICAgICAgICAgICBjYXNlICckbmUnOlxuICAgICAgICAgICAgY2FzZSAnJGVxJzpcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgICAnJHJlbGF0aXZlVGltZSBjYW4gb25seSBiZSB1c2VkIHdpdGggdGhlICRsdCwgJGx0ZSwgJGd0LCBhbmQgJGd0ZSBvcGVyYXRvcnMnXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcGFyc2VyUmVzdWx0ID0gcmVsYXRpdmVUaW1lVG9EYXRlKHZhbC4kcmVsYXRpdmVUaW1lKTtcbiAgICAgICAgICBpZiAocGFyc2VyUmVzdWx0LnN0YXR1cyA9PT0gJ3N1Y2Nlc3MnKSB7XG4gICAgICAgICAgICBhbnN3ZXJba2V5XSA9IHBhcnNlclJlc3VsdC5yZXN1bHQ7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsb2cuaW5mbygnRXJyb3Igd2hpbGUgcGFyc2luZyByZWxhdGl2ZSBkYXRlJywgcGFyc2VyUmVzdWx0KTtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICBgYmFkICRyZWxhdGl2ZVRpbWUgKCR7a2V5fSkgdmFsdWUuICR7cGFyc2VyUmVzdWx0LmluZm99YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBhbnN3ZXJba2V5XSA9IHRyYW5zZm9ybWVyKHZhbCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBjYXNlICckaW4nOlxuICAgICAgY2FzZSAnJG5pbic6IHtcbiAgICAgICAgY29uc3QgYXJyID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAoIShhcnIgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnYmFkICcgKyBrZXkgKyAnIHZhbHVlJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgYW5zd2VyW2tleV0gPSBfLmZsYXRNYXAoYXJyLCB2YWx1ZSA9PiB7XG4gICAgICAgICAgcmV0dXJuIChhdG9tID0+IHtcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGF0b20pKSB7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5tYXAodHJhbnNmb3JtZXIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybWVyKGF0b20pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKHZhbHVlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnJGFsbCc6IHtcbiAgICAgICAgY29uc3QgYXJyID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAoIShhcnIgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnYmFkICcgKyBrZXkgKyAnIHZhbHVlJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgYW5zd2VyW2tleV0gPSBhcnIubWFwKHRyYW5zZm9ybUludGVyaW9yQXRvbSk7XG5cbiAgICAgICAgY29uc3QgdmFsdWVzID0gYW5zd2VyW2tleV07XG4gICAgICAgIGlmIChpc0FueVZhbHVlUmVnZXgodmFsdWVzKSAmJiAhaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSh2YWx1ZXMpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJ0FsbCAkYWxsIHZhbHVlcyBtdXN0IGJlIG9mIHJlZ2V4IHR5cGUgb3Igbm9uZTogJyArIHZhbHVlc1xuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJyRyZWdleCc6XG4gICAgICAgIHZhciBzID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAodHlwZW9mIHMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCByZWdleDogJyArIHMpO1xuICAgICAgICB9XG4gICAgICAgIGFuc3dlcltrZXldID0gcztcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJyRjb250YWluZWRCeSc6IHtcbiAgICAgICAgY29uc3QgYXJyID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAoIShhcnIgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICBgYmFkICRjb250YWluZWRCeTogc2hvdWxkIGJlIGFuIGFycmF5YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgYW5zd2VyLiRlbGVtTWF0Y2ggPSB7XG4gICAgICAgICAgJG5pbjogYXJyLm1hcCh0cmFuc2Zvcm1lciksXG4gICAgICAgIH07XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnJG9wdGlvbnMnOlxuICAgICAgICBhbnN3ZXJba2V5XSA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJyR0ZXh0Jzoge1xuICAgICAgICBjb25zdCBzZWFyY2ggPSBjb25zdHJhaW50W2tleV0uJHNlYXJjaDtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWFyY2ggIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgYGJhZCAkdGV4dDogJHNlYXJjaCwgc2hvdWxkIGJlIG9iamVjdGBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc2VhcmNoLiR0ZXJtIHx8IHR5cGVvZiBzZWFyY2guJHRlcm0gIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgYGJhZCAkdGV4dDogJHRlcm0sIHNob3VsZCBiZSBzdHJpbmdgXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhbnN3ZXJba2V5XSA9IHtcbiAgICAgICAgICAgICRzZWFyY2g6IHNlYXJjaC4kdGVybSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZWFyY2guJGxhbmd1YWdlICYmIHR5cGVvZiBzZWFyY2guJGxhbmd1YWdlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgIGBiYWQgJHRleHQ6ICRsYW5ndWFnZSwgc2hvdWxkIGJlIHN0cmluZ2BcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKHNlYXJjaC4kbGFuZ3VhZ2UpIHtcbiAgICAgICAgICBhbnN3ZXJba2V5XS4kbGFuZ3VhZ2UgPSBzZWFyY2guJGxhbmd1YWdlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChcbiAgICAgICAgICBzZWFyY2guJGNhc2VTZW5zaXRpdmUgJiZcbiAgICAgICAgICB0eXBlb2Ygc2VhcmNoLiRjYXNlU2Vuc2l0aXZlICE9PSAnYm9vbGVhbidcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgYGJhZCAkdGV4dDogJGNhc2VTZW5zaXRpdmUsIHNob3VsZCBiZSBib29sZWFuYFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoc2VhcmNoLiRjYXNlU2Vuc2l0aXZlKSB7XG4gICAgICAgICAgYW5zd2VyW2tleV0uJGNhc2VTZW5zaXRpdmUgPSBzZWFyY2guJGNhc2VTZW5zaXRpdmU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgIHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlICYmXG4gICAgICAgICAgdHlwZW9mIHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlICE9PSAnYm9vbGVhbidcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgYGJhZCAkdGV4dDogJGRpYWNyaXRpY1NlbnNpdGl2ZSwgc2hvdWxkIGJlIGJvb2xlYW5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZSkge1xuICAgICAgICAgIGFuc3dlcltrZXldLiRkaWFjcml0aWNTZW5zaXRpdmUgPSBzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJyRuZWFyU3BoZXJlJzoge1xuICAgICAgICBjb25zdCBwb2ludCA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICAgICAgaWYgKGNvdW50KSB7XG4gICAgICAgICAgYW5zd2VyLiRnZW9XaXRoaW4gPSB7XG4gICAgICAgICAgICAkY2VudGVyU3BoZXJlOiBbXG4gICAgICAgICAgICAgIFtwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlXSxcbiAgICAgICAgICAgICAgY29uc3RyYWludC4kbWF4RGlzdGFuY2UsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYW5zd2VyW2tleV0gPSBbcG9pbnQubG9uZ2l0dWRlLCBwb2ludC5sYXRpdHVkZV07XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICckbWF4RGlzdGFuY2UnOiB7XG4gICAgICAgIGlmIChjb3VudCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGFuc3dlcltrZXldID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIC8vIFRoZSBTREtzIGRvbid0IHNlZW0gdG8gdXNlIHRoZXNlIGJ1dCB0aGV5IGFyZSBkb2N1bWVudGVkIGluIHRoZVxuICAgICAgLy8gUkVTVCBBUEkgZG9jcy5cbiAgICAgIGNhc2UgJyRtYXhEaXN0YW5jZUluUmFkaWFucyc6XG4gICAgICAgIGFuc3dlclsnJG1heERpc3RhbmNlJ10gPSBjb25zdHJhaW50W2tleV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnJG1heERpc3RhbmNlSW5NaWxlcyc6XG4gICAgICAgIGFuc3dlclsnJG1heERpc3RhbmNlJ10gPSBjb25zdHJhaW50W2tleV0gLyAzOTU5O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJyRtYXhEaXN0YW5jZUluS2lsb21ldGVycyc6XG4gICAgICAgIGFuc3dlclsnJG1heERpc3RhbmNlJ10gPSBjb25zdHJhaW50W2tleV0gLyA2MzcxO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnJHNlbGVjdCc6XG4gICAgICBjYXNlICckZG9udFNlbGVjdCc6XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5DT01NQU5EX1VOQVZBSUxBQkxFLFxuICAgICAgICAgICd0aGUgJyArIGtleSArICcgY29uc3RyYWludCBpcyBub3Qgc3VwcG9ydGVkIHlldCdcbiAgICAgICAgKTtcblxuICAgICAgY2FzZSAnJHdpdGhpbic6XG4gICAgICAgIHZhciBib3ggPSBjb25zdHJhaW50W2tleV1bJyRib3gnXTtcbiAgICAgICAgaWYgKCFib3ggfHwgYm94Lmxlbmd0aCAhPSAyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJ21hbGZvcm1hdHRlZCAkd2l0aGluIGFyZydcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGFuc3dlcltrZXldID0ge1xuICAgICAgICAgICRib3g6IFtcbiAgICAgICAgICAgIFtib3hbMF0ubG9uZ2l0dWRlLCBib3hbMF0ubGF0aXR1ZGVdLFxuICAgICAgICAgICAgW2JveFsxXS5sb25naXR1ZGUsIGJveFsxXS5sYXRpdHVkZV0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJyRnZW9XaXRoaW4nOiB7XG4gICAgICAgIGNvbnN0IHBvbHlnb24gPSBjb25zdHJhaW50W2tleV1bJyRwb2x5Z29uJ107XG4gICAgICAgIGNvbnN0IGNlbnRlclNwaGVyZSA9IGNvbnN0cmFpbnRba2V5XVsnJGNlbnRlclNwaGVyZSddO1xuICAgICAgICBpZiAocG9seWdvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbGV0IHBvaW50cztcbiAgICAgICAgICBpZiAodHlwZW9mIHBvbHlnb24gPT09ICdvYmplY3QnICYmIHBvbHlnb24uX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgICAgIGlmICghcG9seWdvbi5jb29yZGluYXRlcyB8fCBwb2x5Z29uLmNvb3JkaW5hdGVzLmxlbmd0aCA8IDMpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7IFBvbHlnb24uY29vcmRpbmF0ZXMgc2hvdWxkIGNvbnRhaW4gYXQgbGVhc3QgMyBsb24vbGF0IHBhaXJzJ1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9pbnRzID0gcG9seWdvbi5jb29yZGluYXRlcztcbiAgICAgICAgICB9IGVsc2UgaWYgKHBvbHlnb24gaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgaWYgKHBvbHlnb24ubGVuZ3RoIDwgMykge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJHBvbHlnb24gc2hvdWxkIGNvbnRhaW4gYXQgbGVhc3QgMyBHZW9Qb2ludHMnXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwb2ludHMgPSBwb2x5Z29uO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgXCJiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJHBvbHlnb24gc2hvdWxkIGJlIFBvbHlnb24gb2JqZWN0IG9yIEFycmF5IG9mIFBhcnNlLkdlb1BvaW50J3NcIlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcG9pbnRzID0gcG9pbnRzLm1hcChwb2ludCA9PiB7XG4gICAgICAgICAgICBpZiAocG9pbnQgaW5zdGFuY2VvZiBBcnJheSAmJiBwb2ludC5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50WzFdLCBwb2ludFswXSk7XG4gICAgICAgICAgICAgIHJldHVybiBwb2ludDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihwb2ludCkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWUnXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW3BvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGVdO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGFuc3dlcltrZXldID0ge1xuICAgICAgICAgICAgJHBvbHlnb246IHBvaW50cyxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKGNlbnRlclNwaGVyZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKCEoY2VudGVyU3BoZXJlIGluc3RhbmNlb2YgQXJyYXkpIHx8IGNlbnRlclNwaGVyZS5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkY2VudGVyU3BoZXJlIHNob3VsZCBiZSBhbiBhcnJheSBvZiBQYXJzZS5HZW9Qb2ludCBhbmQgZGlzdGFuY2UnXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBHZXQgcG9pbnQsIGNvbnZlcnQgdG8gZ2VvIHBvaW50IGlmIG5lY2Vzc2FyeSBhbmQgdmFsaWRhdGVcbiAgICAgICAgICBsZXQgcG9pbnQgPSBjZW50ZXJTcGhlcmVbMF07XG4gICAgICAgICAgaWYgKHBvaW50IGluc3RhbmNlb2YgQXJyYXkgJiYgcG9pbnQubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgICBwb2ludCA9IG5ldyBQYXJzZS5HZW9Qb2ludChwb2ludFsxXSwgcG9pbnRbMF0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIUdlb1BvaW50Q29kZXIuaXNWYWxpZEpTT04ocG9pbnQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkY2VudGVyU3BoZXJlIGdlbyBwb2ludCBpbnZhbGlkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50LmxhdGl0dWRlLCBwb2ludC5sb25naXR1ZGUpO1xuICAgICAgICAgIC8vIEdldCBkaXN0YW5jZSBhbmQgdmFsaWRhdGVcbiAgICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGNlbnRlclNwaGVyZVsxXTtcbiAgICAgICAgICBpZiAoaXNOYU4oZGlzdGFuY2UpIHx8IGRpc3RhbmNlIDwgMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJGNlbnRlclNwaGVyZSBkaXN0YW5jZSBpbnZhbGlkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICAgICAkY2VudGVyU3BoZXJlOiBbW3BvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGVdLCBkaXN0YW5jZV0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJyRnZW9JbnRlcnNlY3RzJzoge1xuICAgICAgICBjb25zdCBwb2ludCA9IGNvbnN0cmFpbnRba2V5XVsnJHBvaW50J107XG4gICAgICAgIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihwb2ludCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnYmFkICRnZW9JbnRlcnNlY3QgdmFsdWU7ICRwb2ludCBzaG91bGQgYmUgR2VvUG9pbnQnXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAgIH1cbiAgICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICAgJGdlb21ldHJ5OiB7XG4gICAgICAgICAgICB0eXBlOiAnUG9pbnQnLFxuICAgICAgICAgICAgY29vcmRpbmF0ZXM6IFtwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChrZXkubWF0Y2goL15cXCQrLykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnYmFkIGNvbnN0cmFpbnQ6ICcgKyBrZXlcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBDYW5ub3RUcmFuc2Zvcm07XG4gICAgfVxuICB9XG4gIHJldHVybiBhbnN3ZXI7XG59XG5cbi8vIFRyYW5zZm9ybXMgYW4gdXBkYXRlIG9wZXJhdG9yIGZyb20gUkVTVCBmb3JtYXQgdG8gbW9uZ28gZm9ybWF0LlxuLy8gVG8gYmUgdHJhbnNmb3JtZWQsIHRoZSBpbnB1dCBzaG91bGQgaGF2ZSBhbiBfX29wIGZpZWxkLlxuLy8gSWYgZmxhdHRlbiBpcyB0cnVlLCB0aGlzIHdpbGwgZmxhdHRlbiBvcGVyYXRvcnMgdG8gdGhlaXIgc3RhdGljXG4vLyBkYXRhIGZvcm1hdC4gRm9yIGV4YW1wbGUsIGFuIGluY3JlbWVudCBvZiAyIHdvdWxkIHNpbXBseSBiZWNvbWUgYVxuLy8gMi5cbi8vIFRoZSBvdXRwdXQgZm9yIGEgbm9uLWZsYXR0ZW5lZCBvcGVyYXRvciBpcyBhIGhhc2ggd2l0aCBfX29wIGJlaW5nXG4vLyB0aGUgbW9uZ28gb3AsIGFuZCBhcmcgYmVpbmcgdGhlIGFyZ3VtZW50LlxuLy8gVGhlIG91dHB1dCBmb3IgYSBmbGF0dGVuZWQgb3BlcmF0b3IgaXMganVzdCBhIHZhbHVlLlxuLy8gUmV0dXJucyB1bmRlZmluZWQgaWYgdGhpcyBzaG91bGQgYmUgYSBuby1vcC5cblxuZnVuY3Rpb24gdHJhbnNmb3JtVXBkYXRlT3BlcmF0b3IoeyBfX29wLCBhbW91bnQsIG9iamVjdHMgfSwgZmxhdHRlbikge1xuICBzd2l0Y2ggKF9fb3ApIHtcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7IF9fb3A6ICckdW5zZXQnLCBhcmc6ICcnIH07XG4gICAgICB9XG5cbiAgICBjYXNlICdJbmNyZW1lbnQnOlxuICAgICAgaWYgKHR5cGVvZiBhbW91bnQgIT09ICdudW1iZXInKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ2luY3JlbWVudGluZyBtdXN0IHByb3ZpZGUgYSBudW1iZXInXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoZmxhdHRlbikge1xuICAgICAgICByZXR1cm4gYW1vdW50O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHsgX19vcDogJyRpbmMnLCBhcmc6IGFtb3VudCB9O1xuICAgICAgfVxuXG4gICAgY2FzZSAnQWRkJzpcbiAgICBjYXNlICdBZGRVbmlxdWUnOlxuICAgICAgaWYgKCEob2JqZWN0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICdvYmplY3RzIHRvIGFkZCBtdXN0IGJlIGFuIGFycmF5J1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdmFyIHRvQWRkID0gb2JqZWN0cy5tYXAodHJhbnNmb3JtSW50ZXJpb3JBdG9tKTtcbiAgICAgIGlmIChmbGF0dGVuKSB7XG4gICAgICAgIHJldHVybiB0b0FkZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBtb25nb09wID0ge1xuICAgICAgICAgIEFkZDogJyRwdXNoJyxcbiAgICAgICAgICBBZGRVbmlxdWU6ICckYWRkVG9TZXQnLFxuICAgICAgICB9W19fb3BdO1xuICAgICAgICByZXR1cm4geyBfX29wOiBtb25nb09wLCBhcmc6IHsgJGVhY2g6IHRvQWRkIH0gfTtcbiAgICAgIH1cblxuICAgIGNhc2UgJ1JlbW92ZSc6XG4gICAgICBpZiAoIShvYmplY3RzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ29iamVjdHMgdG8gcmVtb3ZlIG11c3QgYmUgYW4gYXJyYXknXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICB2YXIgdG9SZW1vdmUgPSBvYmplY3RzLm1hcCh0cmFuc2Zvcm1JbnRlcmlvckF0b20pO1xuICAgICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHsgX19vcDogJyRwdWxsQWxsJywgYXJnOiB0b1JlbW92ZSB9O1xuICAgICAgfVxuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuQ09NTUFORF9VTkFWQUlMQUJMRSxcbiAgICAgICAgYFRoZSAke19fb3B9IG9wZXJhdG9yIGlzIG5vdCBzdXBwb3J0ZWQgeWV0LmBcbiAgICAgICk7XG4gIH1cbn1cbmZ1bmN0aW9uIG1hcFZhbHVlcyhvYmplY3QsIGl0ZXJhdG9yKSB7XG4gIGNvbnN0IHJlc3VsdCA9IHt9O1xuICBPYmplY3Qua2V5cyhvYmplY3QpLmZvckVhY2goa2V5ID0+IHtcbiAgICByZXN1bHRba2V5XSA9IGl0ZXJhdG9yKG9iamVjdFtrZXldKTtcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmNvbnN0IG5lc3RlZE1vbmdvT2JqZWN0VG9OZXN0ZWRQYXJzZU9iamVjdCA9IG1vbmdvT2JqZWN0ID0+IHtcbiAgc3dpdGNoICh0eXBlb2YgbW9uZ29PYmplY3QpIHtcbiAgICBjYXNlICdzdHJpbmcnOlxuICAgIGNhc2UgJ251bWJlcic6XG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICAgIHJldHVybiBtb25nb09iamVjdDtcbiAgICBjYXNlICdzeW1ib2wnOlxuICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICAgIHRocm93ICdiYWQgdmFsdWUgaW4gbmVzdGVkTW9uZ29PYmplY3RUb05lc3RlZFBhcnNlT2JqZWN0JztcbiAgICBjYXNlICdvYmplY3QnOlxuICAgICAgaWYgKG1vbmdvT2JqZWN0ID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0Lm1hcChuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QpO1xuICAgICAgfVxuXG4gICAgICBpZiAobW9uZ29PYmplY3QgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgIHJldHVybiBQYXJzZS5fZW5jb2RlKG1vbmdvT2JqZWN0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgbW9uZ29kYi5Mb25nKSB7XG4gICAgICAgIHJldHVybiBtb25nb09iamVjdC50b051bWJlcigpO1xuICAgICAgfVxuXG4gICAgICBpZiAobW9uZ29PYmplY3QgaW5zdGFuY2VvZiBtb25nb2RiLkRvdWJsZSkge1xuICAgICAgICByZXR1cm4gbW9uZ29PYmplY3QudmFsdWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChCeXRlc0NvZGVyLmlzVmFsaWREYXRhYmFzZU9iamVjdChtb25nb09iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIEJ5dGVzQ29kZXIuZGF0YWJhc2VUb0pTT04obW9uZ29PYmplY3QpO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb25nb09iamVjdCwgJ19fdHlwZScpICYmXG4gICAgICAgIG1vbmdvT2JqZWN0Ll9fdHlwZSA9PSAnRGF0ZScgJiZcbiAgICAgICAgbW9uZ29PYmplY3QuaXNvIGluc3RhbmNlb2YgRGF0ZVxuICAgICAgKSB7XG4gICAgICAgIG1vbmdvT2JqZWN0LmlzbyA9IG1vbmdvT2JqZWN0Lmlzby50b0pTT04oKTtcbiAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbWFwVmFsdWVzKG1vbmdvT2JqZWN0LCBuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QpO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyAndW5rbm93biBqcyB0eXBlJztcbiAgfVxufTtcblxuY29uc3QgdHJhbnNmb3JtUG9pbnRlclN0cmluZyA9IChzY2hlbWEsIGZpZWxkLCBwb2ludGVyU3RyaW5nKSA9PiB7XG4gIGNvbnN0IG9iakRhdGEgPSBwb2ludGVyU3RyaW5nLnNwbGl0KCckJyk7XG4gIGlmIChvYmpEYXRhWzBdICE9PSBzY2hlbWEuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcykge1xuICAgIHRocm93ICdwb2ludGVyIHRvIGluY29ycmVjdCBjbGFzc05hbWUnO1xuICB9XG4gIHJldHVybiB7XG4gICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgY2xhc3NOYW1lOiBvYmpEYXRhWzBdLFxuICAgIG9iamVjdElkOiBvYmpEYXRhWzFdLFxuICB9O1xufTtcblxuLy8gQ29udmVydHMgZnJvbSBhIG1vbmdvLWZvcm1hdCBvYmplY3QgdG8gYSBSRVNULWZvcm1hdCBvYmplY3QuXG4vLyBEb2VzIG5vdCBzdHJpcCBvdXQgYW55dGhpbmcgYmFzZWQgb24gYSBsYWNrIG9mIGF1dGhlbnRpY2F0aW9uLlxuY29uc3QgbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0ID0gKGNsYXNzTmFtZSwgbW9uZ29PYmplY3QsIHNjaGVtYSkgPT4ge1xuICBzd2l0Y2ggKHR5cGVvZiBtb25nb09iamVjdCkge1xuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgY2FzZSAnbnVtYmVyJzpcbiAgICBjYXNlICdib29sZWFuJzpcbiAgICBjYXNlICd1bmRlZmluZWQnOlxuICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0O1xuICAgIGNhc2UgJ3N5bWJvbCc6XG4gICAgY2FzZSAnZnVuY3Rpb24nOlxuICAgICAgdGhyb3cgJ2JhZCB2YWx1ZSBpbiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QnO1xuICAgIGNhc2UgJ29iamVjdCc6IHtcbiAgICAgIGlmIChtb25nb09iamVjdCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChtb25nb09iamVjdCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgIHJldHVybiBtb25nb09iamVjdC5tYXAobmVzdGVkTW9uZ29PYmplY3RUb05lc3RlZFBhcnNlT2JqZWN0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICByZXR1cm4gUGFyc2UuX2VuY29kZShtb25nb09iamVjdCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtb25nb09iamVjdCBpbnN0YW5jZW9mIG1vbmdvZGIuTG9uZykge1xuICAgICAgICByZXR1cm4gbW9uZ29PYmplY3QudG9OdW1iZXIoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgbW9uZ29kYi5Eb3VibGUpIHtcbiAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0LnZhbHVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoQnl0ZXNDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QobW9uZ29PYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBCeXRlc0NvZGVyLmRhdGFiYXNlVG9KU09OKG1vbmdvT2JqZWN0KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdE9iamVjdCA9IHt9O1xuICAgICAgaWYgKG1vbmdvT2JqZWN0Ll9ycGVybSB8fCBtb25nb09iamVjdC5fd3Blcm0pIHtcbiAgICAgICAgcmVzdE9iamVjdC5fcnBlcm0gPSBtb25nb09iamVjdC5fcnBlcm0gfHwgW107XG4gICAgICAgIHJlc3RPYmplY3QuX3dwZXJtID0gbW9uZ29PYmplY3QuX3dwZXJtIHx8IFtdO1xuICAgICAgICBkZWxldGUgbW9uZ29PYmplY3QuX3JwZXJtO1xuICAgICAgICBkZWxldGUgbW9uZ29PYmplY3QuX3dwZXJtO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBrZXkgaW4gbW9uZ29PYmplY3QpIHtcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICBjYXNlICdfaWQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnb2JqZWN0SWQnXSA9ICcnICsgbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ19oYXNoZWRfcGFzc3dvcmQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdC5faGFzaGVkX3Bhc3N3b3JkID0gbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ19hY2wnOlxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnX2VtYWlsX3ZlcmlmeV90b2tlbic6XG4gICAgICAgICAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW4nOlxuICAgICAgICAgIGNhc2UgJ19wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgICAgIGNhc2UgJ19wYXNzd29yZF9jaGFuZ2VkX2F0JzpcbiAgICAgICAgICBjYXNlICdfdG9tYnN0b25lJzpcbiAgICAgICAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgICAgIGNhc2UgJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCc6XG4gICAgICAgICAgY2FzZSAnX2ZhaWxlZF9sb2dpbl9jb3VudCc6XG4gICAgICAgICAgY2FzZSAnX3Bhc3N3b3JkX2hpc3RvcnknOlxuICAgICAgICAgICAgLy8gVGhvc2Uga2V5cyB3aWxsIGJlIGRlbGV0ZWQgaWYgbmVlZGVkIGluIHRoZSBEQiBDb250cm9sbGVyXG4gICAgICAgICAgICByZXN0T2JqZWN0W2tleV0gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnX3Nlc3Npb25fdG9rZW4nOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnc2Vzc2lvblRva2VuJ10gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAndXBkYXRlZEF0JzpcbiAgICAgICAgICBjYXNlICdfdXBkYXRlZF9hdCc6XG4gICAgICAgICAgICByZXN0T2JqZWN0Wyd1cGRhdGVkQXQnXSA9IFBhcnNlLl9lbmNvZGUoXG4gICAgICAgICAgICAgIG5ldyBEYXRlKG1vbmdvT2JqZWN0W2tleV0pXG4gICAgICAgICAgICApLmlzbztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2NyZWF0ZWRBdCc6XG4gICAgICAgICAgY2FzZSAnX2NyZWF0ZWRfYXQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnY3JlYXRlZEF0J10gPSBQYXJzZS5fZW5jb2RlKFxuICAgICAgICAgICAgICBuZXcgRGF0ZShtb25nb09iamVjdFtrZXldKVxuICAgICAgICAgICAgKS5pc287XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdleHBpcmVzQXQnOlxuICAgICAgICAgIGNhc2UgJ19leHBpcmVzQXQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnZXhwaXJlc0F0J10gPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKG1vbmdvT2JqZWN0W2tleV0pKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2xhc3RVc2VkJzpcbiAgICAgICAgICBjYXNlICdfbGFzdF91c2VkJzpcbiAgICAgICAgICAgIHJlc3RPYmplY3RbJ2xhc3RVc2VkJ10gPSBQYXJzZS5fZW5jb2RlKFxuICAgICAgICAgICAgICBuZXcgRGF0ZShtb25nb09iamVjdFtrZXldKVxuICAgICAgICAgICAgKS5pc287XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICd0aW1lc1VzZWQnOlxuICAgICAgICAgIGNhc2UgJ3RpbWVzX3VzZWQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsndGltZXNVc2VkJ10gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnYXV0aERhdGEnOlxuICAgICAgICAgICAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICAgICAgICBsb2cud2FybihcbiAgICAgICAgICAgICAgICAnaWdub3JpbmcgYXV0aERhdGEgaW4gX1VzZXIgYXMgdGhpcyBrZXkgaXMgcmVzZXJ2ZWQgdG8gYmUgc3ludGhlc2l6ZWQgb2YgYF9hdXRoX2RhdGFfKmAga2V5cydcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJlc3RPYmplY3RbJ2F1dGhEYXRhJ10gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIC8vIENoZWNrIG90aGVyIGF1dGggZGF0YSBrZXlzXG4gICAgICAgICAgICB2YXIgYXV0aERhdGFNYXRjaCA9IGtleS5tYXRjaCgvXl9hdXRoX2RhdGFfKFthLXpBLVowLTlfXSspJC8pO1xuICAgICAgICAgICAgaWYgKGF1dGhEYXRhTWF0Y2ggJiYgY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgICAgICAgICAgIHZhciBwcm92aWRlciA9IGF1dGhEYXRhTWF0Y2hbMV07XG4gICAgICAgICAgICAgIHJlc3RPYmplY3RbJ2F1dGhEYXRhJ10gPSByZXN0T2JqZWN0WydhdXRoRGF0YSddIHx8IHt9O1xuICAgICAgICAgICAgICByZXN0T2JqZWN0WydhdXRoRGF0YSddW3Byb3ZpZGVyXSA9IG1vbmdvT2JqZWN0W2tleV07XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoa2V5LmluZGV4T2YoJ19wXycpID09IDApIHtcbiAgICAgICAgICAgICAgdmFyIG5ld0tleSA9IGtleS5zdWJzdHJpbmcoMyk7XG4gICAgICAgICAgICAgIGlmICghc2NoZW1hLmZpZWxkc1tuZXdLZXldKSB7XG4gICAgICAgICAgICAgICAgbG9nLmluZm8oXG4gICAgICAgICAgICAgICAgICAndHJhbnNmb3JtLmpzJyxcbiAgICAgICAgICAgICAgICAgICdGb3VuZCBhIHBvaW50ZXIgY29sdW1uIG5vdCBpbiB0aGUgc2NoZW1hLCBkcm9wcGluZyBpdC4nLFxuICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgbmV3S2V5XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tuZXdLZXldLnR5cGUgIT09ICdQb2ludGVyJykge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKFxuICAgICAgICAgICAgICAgICAgJ3RyYW5zZm9ybS5qcycsXG4gICAgICAgICAgICAgICAgICAnRm91bmQgYSBwb2ludGVyIGluIGEgbm9uLXBvaW50ZXIgY29sdW1uLCBkcm9wcGluZyBpdC4nLFxuICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAga2V5XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobW9uZ29PYmplY3Rba2V5XSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3RPYmplY3RbbmV3S2V5XSA9IHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcoXG4gICAgICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgICAgIG5ld0tleSxcbiAgICAgICAgICAgICAgICBtb25nb09iamVjdFtrZXldXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXlbMF0gPT0gJ18nICYmIGtleSAhPSAnX190eXBlJykge1xuICAgICAgICAgICAgICB0aHJvdyAnYmFkIGtleSBpbiB1bnRyYW5zZm9ybTogJyArIGtleTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHZhciB2YWx1ZSA9IG1vbmdvT2JqZWN0W2tleV07XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBzY2hlbWEuZmllbGRzW2tleV0gJiZcbiAgICAgICAgICAgICAgICBzY2hlbWEuZmllbGRzW2tleV0udHlwZSA9PT0gJ0ZpbGUnICYmXG4gICAgICAgICAgICAgICAgRmlsZUNvZGVyLmlzVmFsaWREYXRhYmFzZU9iamVjdCh2YWx1ZSlcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmVzdE9iamVjdFtrZXldID0gRmlsZUNvZGVyLmRhdGFiYXNlVG9KU09OKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1trZXldICYmXG4gICAgICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdHZW9Qb2ludCcgJiZcbiAgICAgICAgICAgICAgICBHZW9Qb2ludENvZGVyLmlzVmFsaWREYXRhYmFzZU9iamVjdCh2YWx1ZSlcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmVzdE9iamVjdFtrZXldID0gR2VvUG9pbnRDb2Rlci5kYXRhYmFzZVRvSlNPTih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHNjaGVtYS5maWVsZHNba2V5XSAmJlxuICAgICAgICAgICAgICAgIHNjaGVtYS5maWVsZHNba2V5XS50eXBlID09PSAnUG9seWdvbicgJiZcbiAgICAgICAgICAgICAgICBQb2x5Z29uQ29kZXIuaXNWYWxpZERhdGFiYXNlT2JqZWN0KHZhbHVlKVxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXN0T2JqZWN0W2tleV0gPSBQb2x5Z29uQ29kZXIuZGF0YWJhc2VUb0pTT04odmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBzY2hlbWEuZmllbGRzW2tleV0gJiZcbiAgICAgICAgICAgICAgICBzY2hlbWEuZmllbGRzW2tleV0udHlwZSA9PT0gJ0J5dGVzJyAmJlxuICAgICAgICAgICAgICAgIEJ5dGVzQ29kZXIuaXNWYWxpZERhdGFiYXNlT2JqZWN0KHZhbHVlKVxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXN0T2JqZWN0W2tleV0gPSBCeXRlc0NvZGVyLmRhdGFiYXNlVG9KU09OKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzdE9iamVjdFtrZXldID0gbmVzdGVkTW9uZ29PYmplY3RUb05lc3RlZFBhcnNlT2JqZWN0KFxuICAgICAgICAgICAgICBtb25nb09iamVjdFtrZXldXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlbGF0aW9uRmllbGROYW1lcyA9IE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLmZpbHRlcihcbiAgICAgICAgZmllbGROYW1lID0+IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUmVsYXRpb24nXG4gICAgICApO1xuICAgICAgY29uc3QgcmVsYXRpb25GaWVsZHMgPSB7fTtcbiAgICAgIHJlbGF0aW9uRmllbGROYW1lcy5mb3JFYWNoKHJlbGF0aW9uRmllbGROYW1lID0+IHtcbiAgICAgICAgcmVsYXRpb25GaWVsZHNbcmVsYXRpb25GaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogJ1JlbGF0aW9uJyxcbiAgICAgICAgICBjbGFzc05hbWU6IHNjaGVtYS5maWVsZHNbcmVsYXRpb25GaWVsZE5hbWVdLnRhcmdldENsYXNzLFxuICAgICAgICB9O1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7IC4uLnJlc3RPYmplY3QsIC4uLnJlbGF0aW9uRmllbGRzIH07XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyAndW5rbm93biBqcyB0eXBlJztcbiAgfVxufTtcblxudmFyIERhdGVDb2RlciA9IHtcbiAgSlNPTlRvRGF0YWJhc2UoanNvbikge1xuICAgIHJldHVybiBuZXcgRGF0ZShqc29uLmlzbyk7XG4gIH0sXG5cbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZS5fX3R5cGUgPT09ICdEYXRlJ1xuICAgICk7XG4gIH0sXG59O1xuXG52YXIgQnl0ZXNDb2RlciA9IHtcbiAgYmFzZTY0UGF0dGVybjogbmV3IFJlZ0V4cChcbiAgICAnXig/OltBLVphLXowLTkrL117NH0pKig/OltBLVphLXowLTkrL117Mn09PXxbQS1aYS16MC05Ky9dezN9PSk/JCdcbiAgKSxcbiAgaXNCYXNlNjRWYWx1ZShvYmplY3QpIHtcbiAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYmFzZTY0UGF0dGVybi50ZXN0KG9iamVjdCk7XG4gIH0sXG5cbiAgZGF0YWJhc2VUb0pTT04ob2JqZWN0KSB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGlmICh0aGlzLmlzQmFzZTY0VmFsdWUob2JqZWN0KSkge1xuICAgICAgdmFsdWUgPSBvYmplY3Q7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlID0gb2JqZWN0LmJ1ZmZlci50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdCeXRlcycsXG4gICAgICBiYXNlNjQ6IHZhbHVlLFxuICAgIH07XG4gIH0sXG5cbiAgaXNWYWxpZERhdGFiYXNlT2JqZWN0KG9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3QgaW5zdGFuY2VvZiBtb25nb2RiLkJpbmFyeSB8fCB0aGlzLmlzQmFzZTY0VmFsdWUob2JqZWN0KTtcbiAgfSxcblxuICBKU09OVG9EYXRhYmFzZShqc29uKSB7XG4gICAgcmV0dXJuIG5ldyBtb25nb2RiLkJpbmFyeShCdWZmZXIuZnJvbShqc29uLmJhc2U2NCwgJ2Jhc2U2NCcpKTtcbiAgfSxcblxuICBpc1ZhbGlkSlNPTih2YWx1ZSkge1xuICAgIHJldHVybiAoXG4gICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmIHZhbHVlLl9fdHlwZSA9PT0gJ0J5dGVzJ1xuICAgICk7XG4gIH0sXG59O1xuXG52YXIgR2VvUG9pbnRDb2RlciA9IHtcbiAgZGF0YWJhc2VUb0pTT04ob2JqZWN0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIF9fdHlwZTogJ0dlb1BvaW50JyxcbiAgICAgIGxhdGl0dWRlOiBvYmplY3RbMV0sXG4gICAgICBsb25naXR1ZGU6IG9iamVjdFswXSxcbiAgICB9O1xuICB9LFxuXG4gIGlzVmFsaWREYXRhYmFzZU9iamVjdChvYmplY3QpIHtcbiAgICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgQXJyYXkgJiYgb2JqZWN0Lmxlbmd0aCA9PSAyO1xuICB9LFxuXG4gIEpTT05Ub0RhdGFiYXNlKGpzb24pIHtcbiAgICByZXR1cm4gW2pzb24ubG9uZ2l0dWRlLCBqc29uLmxhdGl0dWRlXTtcbiAgfSxcblxuICBpc1ZhbGlkSlNPTih2YWx1ZSkge1xuICAgIHJldHVybiAoXG4gICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmIHZhbHVlLl9fdHlwZSA9PT0gJ0dlb1BvaW50J1xuICAgICk7XG4gIH0sXG59O1xuXG52YXIgUG9seWdvbkNvZGVyID0ge1xuICBkYXRhYmFzZVRvSlNPTihvYmplY3QpIHtcbiAgICAvLyBDb252ZXJ0IGxuZy9sYXQgLT4gbGF0L2xuZ1xuICAgIGNvbnN0IGNvb3JkcyA9IG9iamVjdC5jb29yZGluYXRlc1swXS5tYXAoY29vcmQgPT4ge1xuICAgICAgcmV0dXJuIFtjb29yZFsxXSwgY29vcmRbMF1dO1xuICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdQb2x5Z29uJyxcbiAgICAgIGNvb3JkaW5hdGVzOiBjb29yZHMsXG4gICAgfTtcbiAgfSxcblxuICBpc1ZhbGlkRGF0YWJhc2VPYmplY3Qob2JqZWN0KSB7XG4gICAgY29uc3QgY29vcmRzID0gb2JqZWN0LmNvb3JkaW5hdGVzWzBdO1xuICAgIGlmIChvYmplY3QudHlwZSAhPT0gJ1BvbHlnb24nIHx8ICEoY29vcmRzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBwb2ludCA9IGNvb3Jkc1tpXTtcbiAgICAgIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QocG9pbnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwYXJzZUZsb2F0KHBvaW50WzFdKSwgcGFyc2VGbG9hdChwb2ludFswXSkpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBKU09OVG9EYXRhYmFzZShqc29uKSB7XG4gICAgbGV0IGNvb3JkcyA9IGpzb24uY29vcmRpbmF0ZXM7XG4gICAgLy8gQWRkIGZpcnN0IHBvaW50IHRvIHRoZSBlbmQgdG8gY2xvc2UgcG9seWdvblxuICAgIGlmIChcbiAgICAgIGNvb3Jkc1swXVswXSAhPT0gY29vcmRzW2Nvb3Jkcy5sZW5ndGggLSAxXVswXSB8fFxuICAgICAgY29vcmRzWzBdWzFdICE9PSBjb29yZHNbY29vcmRzLmxlbmd0aCAtIDFdWzFdXG4gICAgKSB7XG4gICAgICBjb29yZHMucHVzaChjb29yZHNbMF0pO1xuICAgIH1cbiAgICBjb25zdCB1bmlxdWUgPSBjb29yZHMuZmlsdGVyKChpdGVtLCBpbmRleCwgYXIpID0+IHtcbiAgICAgIGxldCBmb3VuZEluZGV4ID0gLTE7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IHB0ID0gYXJbaV07XG4gICAgICAgIGlmIChwdFswXSA9PT0gaXRlbVswXSAmJiBwdFsxXSA9PT0gaXRlbVsxXSkge1xuICAgICAgICAgIGZvdW5kSW5kZXggPSBpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gZm91bmRJbmRleCA9PT0gaW5kZXg7XG4gICAgfSk7XG4gICAgaWYgKHVuaXF1ZS5sZW5ndGggPCAzKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgJ0dlb0pTT046IExvb3AgbXVzdCBoYXZlIGF0IGxlYXN0IDMgZGlmZmVyZW50IHZlcnRpY2VzJ1xuICAgICAgKTtcbiAgICB9XG4gICAgLy8gQ29udmVydCBsYXQvbG9uZyAtPiBsb25nL2xhdFxuICAgIGNvb3JkcyA9IGNvb3Jkcy5tYXAoY29vcmQgPT4ge1xuICAgICAgcmV0dXJuIFtjb29yZFsxXSwgY29vcmRbMF1dO1xuICAgIH0pO1xuICAgIHJldHVybiB7IHR5cGU6ICdQb2x5Z29uJywgY29vcmRpbmF0ZXM6IFtjb29yZHNdIH07XG4gIH0sXG5cbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZS5fX3R5cGUgPT09ICdQb2x5Z29uJ1xuICAgICk7XG4gIH0sXG59O1xuXG52YXIgRmlsZUNvZGVyID0ge1xuICBkYXRhYmFzZVRvSlNPTihvYmplY3QpIHtcbiAgICByZXR1cm4ge1xuICAgICAgX190eXBlOiAnRmlsZScsXG4gICAgICBuYW1lOiBvYmplY3QsXG4gICAgfTtcbiAgfSxcblxuICBpc1ZhbGlkRGF0YWJhc2VPYmplY3Qob2JqZWN0KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBvYmplY3QgPT09ICdzdHJpbmcnO1xuICB9LFxuXG4gIEpTT05Ub0RhdGFiYXNlKGpzb24pIHtcbiAgICByZXR1cm4ganNvbi5uYW1lO1xuICB9LFxuXG4gIGlzVmFsaWRKU09OKHZhbHVlKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgdmFsdWUuX190eXBlID09PSAnRmlsZSdcbiAgICApO1xuICB9LFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHRyYW5zZm9ybUtleSxcbiAgcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlLFxuICB0cmFuc2Zvcm1VcGRhdGUsXG4gIHRyYW5zZm9ybVdoZXJlLFxuICBtb25nb09iamVjdFRvUGFyc2VPYmplY3QsXG4gIHJlbGF0aXZlVGltZVRvRGF0ZSxcbiAgdHJhbnNmb3JtQ29uc3RyYWludCxcbiAgdHJhbnNmb3JtUG9pbnRlclN0cmluZyxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/PostgresClient.js b/lib/Adapters/Storage/Postgres/PostgresClient.js new file mode 100644 index 0000000000..71b1cc7917 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresClient.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createClient = createClient; + +const parser = require('./PostgresConfigParser'); + +function createClient(uri, databaseOptions) { + let dbOptions = {}; + databaseOptions = databaseOptions || {}; + + if (uri) { + dbOptions = parser.getDatabaseOptionsFromURI(uri); + } + + for (const key in databaseOptions) { + dbOptions[key] = databaseOptions[key]; + } + + const initOptions = dbOptions.initOptions || {}; + + const pgp = require('pg-promise')(initOptions); + + const client = pgp(dbOptions); + + if (dbOptions.pgOptions) { + for (const key in dbOptions.pgOptions) { + pgp.pg.defaults[key] = dbOptions.pgOptions[key]; + } + } + + return { + client, + pgp + }; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzQ2xpZW50LmpzIl0sIm5hbWVzIjpbInBhcnNlciIsInJlcXVpcmUiLCJjcmVhdGVDbGllbnQiLCJ1cmkiLCJkYXRhYmFzZU9wdGlvbnMiLCJkYk9wdGlvbnMiLCJnZXREYXRhYmFzZU9wdGlvbnNGcm9tVVJJIiwia2V5IiwiaW5pdE9wdGlvbnMiLCJwZ3AiLCJjbGllbnQiLCJwZ09wdGlvbnMiLCJwZyIsImRlZmF1bHRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUEsTUFBTUEsTUFBTSxHQUFHQyxPQUFPLENBQUMsd0JBQUQsQ0FBdEI7O0FBRU8sU0FBU0MsWUFBVCxDQUFzQkMsR0FBdEIsRUFBMkJDLGVBQTNCLEVBQTRDO0FBQ2pELE1BQUlDLFNBQVMsR0FBRyxFQUFoQjtBQUNBRCxFQUFBQSxlQUFlLEdBQUdBLGVBQWUsSUFBSSxFQUFyQzs7QUFFQSxNQUFJRCxHQUFKLEVBQVM7QUFDUEUsSUFBQUEsU0FBUyxHQUFHTCxNQUFNLENBQUNNLHlCQUFQLENBQWlDSCxHQUFqQyxDQUFaO0FBQ0Q7O0FBRUQsT0FBSyxNQUFNSSxHQUFYLElBQWtCSCxlQUFsQixFQUFtQztBQUNqQ0MsSUFBQUEsU0FBUyxDQUFDRSxHQUFELENBQVQsR0FBaUJILGVBQWUsQ0FBQ0csR0FBRCxDQUFoQztBQUNEOztBQUVELFFBQU1DLFdBQVcsR0FBR0gsU0FBUyxDQUFDRyxXQUFWLElBQXlCLEVBQTdDOztBQUNBLFFBQU1DLEdBQUcsR0FBR1IsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQk8sV0FBdEIsQ0FBWjs7QUFDQSxRQUFNRSxNQUFNLEdBQUdELEdBQUcsQ0FBQ0osU0FBRCxDQUFsQjs7QUFFQSxNQUFJQSxTQUFTLENBQUNNLFNBQWQsRUFBeUI7QUFDdkIsU0FBSyxNQUFNSixHQUFYLElBQWtCRixTQUFTLENBQUNNLFNBQTVCLEVBQXVDO0FBQ3JDRixNQUFBQSxHQUFHLENBQUNHLEVBQUosQ0FBT0MsUUFBUCxDQUFnQk4sR0FBaEIsSUFBdUJGLFNBQVMsQ0FBQ00sU0FBVixDQUFvQkosR0FBcEIsQ0FBdkI7QUFDRDtBQUNGOztBQUVELFNBQU87QUFBRUcsSUFBQUEsTUFBRjtBQUFVRCxJQUFBQTtBQUFWLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHBhcnNlciA9IHJlcXVpcmUoJy4vUG9zdGdyZXNDb25maWdQYXJzZXInKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUNsaWVudCh1cmksIGRhdGFiYXNlT3B0aW9ucykge1xuICBsZXQgZGJPcHRpb25zID0ge307XG4gIGRhdGFiYXNlT3B0aW9ucyA9IGRhdGFiYXNlT3B0aW9ucyB8fCB7fTtcblxuICBpZiAodXJpKSB7XG4gICAgZGJPcHRpb25zID0gcGFyc2VyLmdldERhdGFiYXNlT3B0aW9uc0Zyb21VUkkodXJpKTtcbiAgfVxuXG4gIGZvciAoY29uc3Qga2V5IGluIGRhdGFiYXNlT3B0aW9ucykge1xuICAgIGRiT3B0aW9uc1trZXldID0gZGF0YWJhc2VPcHRpb25zW2tleV07XG4gIH1cblxuICBjb25zdCBpbml0T3B0aW9ucyA9IGRiT3B0aW9ucy5pbml0T3B0aW9ucyB8fCB7fTtcbiAgY29uc3QgcGdwID0gcmVxdWlyZSgncGctcHJvbWlzZScpKGluaXRPcHRpb25zKTtcbiAgY29uc3QgY2xpZW50ID0gcGdwKGRiT3B0aW9ucyk7XG5cbiAgaWYgKGRiT3B0aW9ucy5wZ09wdGlvbnMpIHtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBkYk9wdGlvbnMucGdPcHRpb25zKSB7XG4gICAgICBwZ3AucGcuZGVmYXVsdHNba2V5XSA9IGRiT3B0aW9ucy5wZ09wdGlvbnNba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBjbGllbnQsIHBncCB9O1xufVxuIl19 \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/PostgresConfigParser.js b/lib/Adapters/Storage/Postgres/PostgresConfigParser.js new file mode 100644 index 0000000000..22ddd8241e --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresConfigParser.js @@ -0,0 +1,41 @@ +"use strict"; + +const url = require('url'); + +function getDatabaseOptionsFromURI(uri) { + const databaseOptions = {}; + const parsedURI = url.parse(uri); + const queryParams = parseQueryParams(parsedURI.query); + const authParts = parsedURI.auth ? parsedURI.auth.split(':') : []; + databaseOptions.host = parsedURI.hostname || 'localhost'; + databaseOptions.port = parsedURI.port ? parseInt(parsedURI.port) : 5432; + databaseOptions.database = parsedURI.pathname ? parsedURI.pathname.substr(1) : undefined; + databaseOptions.user = authParts.length > 0 ? authParts[0] : ''; + databaseOptions.password = authParts.length > 1 ? authParts[1] : ''; + databaseOptions.ssl = queryParams.ssl && queryParams.ssl.toLowerCase() === 'true' ? true : false; + databaseOptions.binary = queryParams.binary && queryParams.binary.toLowerCase() === 'true' ? true : false; + databaseOptions.client_encoding = queryParams.client_encoding; + databaseOptions.application_name = queryParams.application_name; + databaseOptions.fallback_application_name = queryParams.fallback_application_name; + + if (queryParams.poolSize) { + databaseOptions.poolSize = parseInt(queryParams.poolSize) || 10; + } + + return databaseOptions; +} + +function parseQueryParams(queryString) { + queryString = queryString || ''; + return queryString.split('&').reduce((p, c) => { + const parts = c.split('='); + p[decodeURIComponent(parts[0])] = parts.length > 1 ? decodeURIComponent(parts.slice(1).join('=')) : ''; + return p; + }, {}); +} + +module.exports = { + parseQueryParams: parseQueryParams, + getDatabaseOptionsFromURI: getDatabaseOptionsFromURI +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzQ29uZmlnUGFyc2VyLmpzIl0sIm5hbWVzIjpbInVybCIsInJlcXVpcmUiLCJnZXREYXRhYmFzZU9wdGlvbnNGcm9tVVJJIiwidXJpIiwiZGF0YWJhc2VPcHRpb25zIiwicGFyc2VkVVJJIiwicGFyc2UiLCJxdWVyeVBhcmFtcyIsInBhcnNlUXVlcnlQYXJhbXMiLCJxdWVyeSIsImF1dGhQYXJ0cyIsImF1dGgiLCJzcGxpdCIsImhvc3QiLCJob3N0bmFtZSIsInBvcnQiLCJwYXJzZUludCIsImRhdGFiYXNlIiwicGF0aG5hbWUiLCJzdWJzdHIiLCJ1bmRlZmluZWQiLCJ1c2VyIiwibGVuZ3RoIiwicGFzc3dvcmQiLCJzc2wiLCJ0b0xvd2VyQ2FzZSIsImJpbmFyeSIsImNsaWVudF9lbmNvZGluZyIsImFwcGxpY2F0aW9uX25hbWUiLCJmYWxsYmFja19hcHBsaWNhdGlvbl9uYW1lIiwicG9vbFNpemUiLCJxdWVyeVN0cmluZyIsInJlZHVjZSIsInAiLCJjIiwicGFydHMiLCJkZWNvZGVVUklDb21wb25lbnQiLCJzbGljZSIsImpvaW4iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLE1BQU1BLEdBQUcsR0FBR0MsT0FBTyxDQUFDLEtBQUQsQ0FBbkI7O0FBRUEsU0FBU0MseUJBQVQsQ0FBbUNDLEdBQW5DLEVBQXdDO0FBQ3RDLFFBQU1DLGVBQWUsR0FBRyxFQUF4QjtBQUVBLFFBQU1DLFNBQVMsR0FBR0wsR0FBRyxDQUFDTSxLQUFKLENBQVVILEdBQVYsQ0FBbEI7QUFDQSxRQUFNSSxXQUFXLEdBQUdDLGdCQUFnQixDQUFDSCxTQUFTLENBQUNJLEtBQVgsQ0FBcEM7QUFDQSxRQUFNQyxTQUFTLEdBQUdMLFNBQVMsQ0FBQ00sSUFBVixHQUFpQk4sU0FBUyxDQUFDTSxJQUFWLENBQWVDLEtBQWYsQ0FBcUIsR0FBckIsQ0FBakIsR0FBNkMsRUFBL0Q7QUFFQVIsRUFBQUEsZUFBZSxDQUFDUyxJQUFoQixHQUF1QlIsU0FBUyxDQUFDUyxRQUFWLElBQXNCLFdBQTdDO0FBQ0FWLEVBQUFBLGVBQWUsQ0FBQ1csSUFBaEIsR0FBdUJWLFNBQVMsQ0FBQ1UsSUFBVixHQUFpQkMsUUFBUSxDQUFDWCxTQUFTLENBQUNVLElBQVgsQ0FBekIsR0FBNEMsSUFBbkU7QUFDQVgsRUFBQUEsZUFBZSxDQUFDYSxRQUFoQixHQUEyQlosU0FBUyxDQUFDYSxRQUFWLEdBQ3ZCYixTQUFTLENBQUNhLFFBQVYsQ0FBbUJDLE1BQW5CLENBQTBCLENBQTFCLENBRHVCLEdBRXZCQyxTQUZKO0FBSUFoQixFQUFBQSxlQUFlLENBQUNpQixJQUFoQixHQUF1QlgsU0FBUyxDQUFDWSxNQUFWLEdBQW1CLENBQW5CLEdBQXVCWixTQUFTLENBQUMsQ0FBRCxDQUFoQyxHQUFzQyxFQUE3RDtBQUNBTixFQUFBQSxlQUFlLENBQUNtQixRQUFoQixHQUEyQmIsU0FBUyxDQUFDWSxNQUFWLEdBQW1CLENBQW5CLEdBQXVCWixTQUFTLENBQUMsQ0FBRCxDQUFoQyxHQUFzQyxFQUFqRTtBQUVBTixFQUFBQSxlQUFlLENBQUNvQixHQUFoQixHQUNFakIsV0FBVyxDQUFDaUIsR0FBWixJQUFtQmpCLFdBQVcsQ0FBQ2lCLEdBQVosQ0FBZ0JDLFdBQWhCLE9BQWtDLE1BQXJELEdBQThELElBQTlELEdBQXFFLEtBRHZFO0FBRUFyQixFQUFBQSxlQUFlLENBQUNzQixNQUFoQixHQUNFbkIsV0FBVyxDQUFDbUIsTUFBWixJQUFzQm5CLFdBQVcsQ0FBQ21CLE1BQVosQ0FBbUJELFdBQW5CLE9BQXFDLE1BQTNELEdBQ0ksSUFESixHQUVJLEtBSE47QUFLQXJCLEVBQUFBLGVBQWUsQ0FBQ3VCLGVBQWhCLEdBQWtDcEIsV0FBVyxDQUFDb0IsZUFBOUM7QUFDQXZCLEVBQUFBLGVBQWUsQ0FBQ3dCLGdCQUFoQixHQUFtQ3JCLFdBQVcsQ0FBQ3FCLGdCQUEvQztBQUNBeEIsRUFBQUEsZUFBZSxDQUFDeUIseUJBQWhCLEdBQ0V0QixXQUFXLENBQUNzQix5QkFEZDs7QUFHQSxNQUFJdEIsV0FBVyxDQUFDdUIsUUFBaEIsRUFBMEI7QUFDeEIxQixJQUFBQSxlQUFlLENBQUMwQixRQUFoQixHQUEyQmQsUUFBUSxDQUFDVCxXQUFXLENBQUN1QixRQUFiLENBQVIsSUFBa0MsRUFBN0Q7QUFDRDs7QUFFRCxTQUFPMUIsZUFBUDtBQUNEOztBQUVELFNBQVNJLGdCQUFULENBQTBCdUIsV0FBMUIsRUFBdUM7QUFDckNBLEVBQUFBLFdBQVcsR0FBR0EsV0FBVyxJQUFJLEVBQTdCO0FBRUEsU0FBT0EsV0FBVyxDQUFDbkIsS0FBWixDQUFrQixHQUFsQixFQUF1Qm9CLE1BQXZCLENBQThCLENBQUNDLENBQUQsRUFBSUMsQ0FBSixLQUFVO0FBQzdDLFVBQU1DLEtBQUssR0FBR0QsQ0FBQyxDQUFDdEIsS0FBRixDQUFRLEdBQVIsQ0FBZDtBQUNBcUIsSUFBQUEsQ0FBQyxDQUFDRyxrQkFBa0IsQ0FBQ0QsS0FBSyxDQUFDLENBQUQsQ0FBTixDQUFuQixDQUFELEdBQ0VBLEtBQUssQ0FBQ2IsTUFBTixHQUFlLENBQWYsR0FBbUJjLGtCQUFrQixDQUFDRCxLQUFLLENBQUNFLEtBQU4sQ0FBWSxDQUFaLEVBQWVDLElBQWYsQ0FBb0IsR0FBcEIsQ0FBRCxDQUFyQyxHQUFrRSxFQURwRTtBQUVBLFdBQU9MLENBQVA7QUFDRCxHQUxNLEVBS0osRUFMSSxDQUFQO0FBTUQ7O0FBRURNLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmaEMsRUFBQUEsZ0JBQWdCLEVBQUVBLGdCQURIO0FBRWZOLEVBQUFBLHlCQUF5QixFQUFFQTtBQUZaLENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgdXJsID0gcmVxdWlyZSgndXJsJyk7XG5cbmZ1bmN0aW9uIGdldERhdGFiYXNlT3B0aW9uc0Zyb21VUkkodXJpKSB7XG4gIGNvbnN0IGRhdGFiYXNlT3B0aW9ucyA9IHt9O1xuXG4gIGNvbnN0IHBhcnNlZFVSSSA9IHVybC5wYXJzZSh1cmkpO1xuICBjb25zdCBxdWVyeVBhcmFtcyA9IHBhcnNlUXVlcnlQYXJhbXMocGFyc2VkVVJJLnF1ZXJ5KTtcbiAgY29uc3QgYXV0aFBhcnRzID0gcGFyc2VkVVJJLmF1dGggPyBwYXJzZWRVUkkuYXV0aC5zcGxpdCgnOicpIDogW107XG5cbiAgZGF0YWJhc2VPcHRpb25zLmhvc3QgPSBwYXJzZWRVUkkuaG9zdG5hbWUgfHwgJ2xvY2FsaG9zdCc7XG4gIGRhdGFiYXNlT3B0aW9ucy5wb3J0ID0gcGFyc2VkVVJJLnBvcnQgPyBwYXJzZUludChwYXJzZWRVUkkucG9ydCkgOiA1NDMyO1xuICBkYXRhYmFzZU9wdGlvbnMuZGF0YWJhc2UgPSBwYXJzZWRVUkkucGF0aG5hbWVcbiAgICA/IHBhcnNlZFVSSS5wYXRobmFtZS5zdWJzdHIoMSlcbiAgICA6IHVuZGVmaW5lZDtcblxuICBkYXRhYmFzZU9wdGlvbnMudXNlciA9IGF1dGhQYXJ0cy5sZW5ndGggPiAwID8gYXV0aFBhcnRzWzBdIDogJyc7XG4gIGRhdGFiYXNlT3B0aW9ucy5wYXNzd29yZCA9IGF1dGhQYXJ0cy5sZW5ndGggPiAxID8gYXV0aFBhcnRzWzFdIDogJyc7XG5cbiAgZGF0YWJhc2VPcHRpb25zLnNzbCA9XG4gICAgcXVlcnlQYXJhbXMuc3NsICYmIHF1ZXJ5UGFyYW1zLnNzbC50b0xvd2VyQ2FzZSgpID09PSAndHJ1ZScgPyB0cnVlIDogZmFsc2U7XG4gIGRhdGFiYXNlT3B0aW9ucy5iaW5hcnkgPVxuICAgIHF1ZXJ5UGFyYW1zLmJpbmFyeSAmJiBxdWVyeVBhcmFtcy5iaW5hcnkudG9Mb3dlckNhc2UoKSA9PT0gJ3RydWUnXG4gICAgICA/IHRydWVcbiAgICAgIDogZmFsc2U7XG5cbiAgZGF0YWJhc2VPcHRpb25zLmNsaWVudF9lbmNvZGluZyA9IHF1ZXJ5UGFyYW1zLmNsaWVudF9lbmNvZGluZztcbiAgZGF0YWJhc2VPcHRpb25zLmFwcGxpY2F0aW9uX25hbWUgPSBxdWVyeVBhcmFtcy5hcHBsaWNhdGlvbl9uYW1lO1xuICBkYXRhYmFzZU9wdGlvbnMuZmFsbGJhY2tfYXBwbGljYXRpb25fbmFtZSA9XG4gICAgcXVlcnlQYXJhbXMuZmFsbGJhY2tfYXBwbGljYXRpb25fbmFtZTtcblxuICBpZiAocXVlcnlQYXJhbXMucG9vbFNpemUpIHtcbiAgICBkYXRhYmFzZU9wdGlvbnMucG9vbFNpemUgPSBwYXJzZUludChxdWVyeVBhcmFtcy5wb29sU2l6ZSkgfHwgMTA7XG4gIH1cblxuICByZXR1cm4gZGF0YWJhc2VPcHRpb25zO1xufVxuXG5mdW5jdGlvbiBwYXJzZVF1ZXJ5UGFyYW1zKHF1ZXJ5U3RyaW5nKSB7XG4gIHF1ZXJ5U3RyaW5nID0gcXVlcnlTdHJpbmcgfHwgJyc7XG5cbiAgcmV0dXJuIHF1ZXJ5U3RyaW5nLnNwbGl0KCcmJykucmVkdWNlKChwLCBjKSA9PiB7XG4gICAgY29uc3QgcGFydHMgPSBjLnNwbGl0KCc9Jyk7XG4gICAgcFtkZWNvZGVVUklDb21wb25lbnQocGFydHNbMF0pXSA9XG4gICAgICBwYXJ0cy5sZW5ndGggPiAxID8gZGVjb2RlVVJJQ29tcG9uZW50KHBhcnRzLnNsaWNlKDEpLmpvaW4oJz0nKSkgOiAnJztcbiAgICByZXR1cm4gcDtcbiAgfSwge30pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgcGFyc2VRdWVyeVBhcmFtczogcGFyc2VRdWVyeVBhcmFtcyxcbiAgZ2V0RGF0YWJhc2VPcHRpb25zRnJvbVVSSTogZ2V0RGF0YWJhc2VPcHRpb25zRnJvbVVSSSxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js new file mode 100644 index 0000000000..a046fccad3 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -0,0 +1,2410 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PostgresStorageAdapter = void 0; + +var _PostgresClient = require("./PostgresClient"); + +var _node = _interopRequireDefault(require("parse/node")); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _sql = _interopRequireDefault(require("./sql")); + +var _StorageAdapter = require("../StorageAdapter"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const PostgresRelationDoesNotExistError = '42P01'; +const PostgresDuplicateRelationError = '42P07'; +const PostgresDuplicateColumnError = '42701'; +const PostgresMissingColumnError = '42703'; +const PostgresDuplicateObjectError = '42710'; +const PostgresUniqueIndexViolationError = '23505'; +const PostgresTransactionAbortedError = '25P02'; + +const logger = require('../../../logger'); + +const debug = function (...args) { + args = ['PG: ' + arguments[0]].concat(args.slice(1, args.length)); + const log = logger.getLogger(); + log.debug.apply(log, args); +}; + +const parseTypeToPostgresType = type => { + switch (type.type) { + case 'String': + return 'text'; + + case 'Date': + return 'timestamp with time zone'; + + case 'Object': + return 'jsonb'; + + case 'File': + return 'text'; + + case 'Boolean': + return 'boolean'; + + case 'Pointer': + return 'char(10)'; + + case 'Number': + return 'double precision'; + + case 'GeoPoint': + return 'point'; + + case 'Bytes': + return 'jsonb'; + + case 'Polygon': + return 'polygon'; + + case 'Array': + if (type.contents && type.contents.type === 'String') { + return 'text[]'; + } else { + return 'jsonb'; + } + + default: + throw `no type for ${JSON.stringify(type)} yet`; + } +}; + +const ParseToPosgresComparator = { + $gt: '>', + $lt: '<', + $gte: '>=', + $lte: '<=' +}; +const mongoAggregateToPostgres = { + $dayOfMonth: 'DAY', + $dayOfWeek: 'DOW', + $dayOfYear: 'DOY', + $isoDayOfWeek: 'ISODOW', + $isoWeekYear: 'ISOYEAR', + $hour: 'HOUR', + $minute: 'MINUTE', + $second: 'SECOND', + $millisecond: 'MILLISECONDS', + $month: 'MONTH', + $week: 'WEEK', + $year: 'YEAR' +}; + +const toPostgresValue = value => { + if (typeof value === 'object') { + if (value.__type === 'Date') { + return value.iso; + } + + if (value.__type === 'File') { + return value.name; + } + } + + return value; +}; + +const transformValue = value => { + if (typeof value === 'object' && value.__type === 'Pointer') { + return value.objectId; + } + + return value; +}; // Duplicate from then mongo adapter... + + +const emptyCLPS = Object.freeze({ + find: {}, + get: {}, + count: {}, + create: {}, + update: {}, + delete: {}, + addField: {}, + protectedFields: {} +}); +const defaultCLPS = Object.freeze({ + find: { + '*': true + }, + get: { + '*': true + }, + count: { + '*': true + }, + create: { + '*': true + }, + update: { + '*': true + }, + delete: { + '*': true + }, + addField: { + '*': true + }, + protectedFields: { + '*': [] + } +}); + +const toParseSchema = schema => { + if (schema.className === '_User') { + delete schema.fields._hashed_password; + } + + if (schema.fields) { + delete schema.fields._wperm; + delete schema.fields._rperm; + } + + let clps = defaultCLPS; + + if (schema.classLevelPermissions) { + clps = _objectSpread({}, emptyCLPS, {}, schema.classLevelPermissions); + } + + let indexes = {}; + + if (schema.indexes) { + indexes = _objectSpread({}, schema.indexes); + } + + return { + className: schema.className, + fields: schema.fields, + classLevelPermissions: clps, + indexes + }; +}; + +const toPostgresSchema = schema => { + if (!schema) { + return schema; + } + + schema.fields = schema.fields || {}; + schema.fields._wperm = { + type: 'Array', + contents: { + type: 'String' + } + }; + schema.fields._rperm = { + type: 'Array', + contents: { + type: 'String' + } + }; + + if (schema.className === '_User') { + schema.fields._hashed_password = { + type: 'String' + }; + schema.fields._password_history = { + type: 'Array' + }; + } + + return schema; +}; + +const handleDotFields = object => { + Object.keys(object).forEach(fieldName => { + if (fieldName.indexOf('.') > -1) { + const components = fieldName.split('.'); + const first = components.shift(); + object[first] = object[first] || {}; + let currentObj = object[first]; + let next; + let value = object[fieldName]; + + if (value && value.__op === 'Delete') { + value = undefined; + } + /* eslint-disable no-cond-assign */ + + + while (next = components.shift()) { + /* eslint-enable no-cond-assign */ + currentObj[next] = currentObj[next] || {}; + + if (components.length === 0) { + currentObj[next] = value; + } + + currentObj = currentObj[next]; + } + + delete object[fieldName]; + } + }); + return object; +}; + +const transformDotFieldToComponents = fieldName => { + return fieldName.split('.').map((cmpt, index) => { + if (index === 0) { + return `"${cmpt}"`; + } + + return `'${cmpt}'`; + }); +}; + +const transformDotField = fieldName => { + if (fieldName.indexOf('.') === -1) { + return `"${fieldName}"`; + } + + const components = transformDotFieldToComponents(fieldName); + let name = components.slice(0, components.length - 1).join('->'); + name += '->>' + components[components.length - 1]; + return name; +}; + +const transformAggregateField = fieldName => { + if (typeof fieldName !== 'string') { + return fieldName; + } + + if (fieldName === '$_created_at') { + return 'createdAt'; + } + + if (fieldName === '$_updated_at') { + return 'updatedAt'; + } + + return fieldName.substr(1); +}; + +const validateKeys = object => { + if (typeof object == 'object') { + for (const key in object) { + if (typeof object[key] == 'object') { + validateKeys(object[key]); + } + + if (key.includes('$') || key.includes('.')) { + throw new _node.default.Error(_node.default.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); + } + } + } +}; // Returns the list of join tables on a schema + + +const joinTablesForSchema = schema => { + const list = []; + + if (schema) { + Object.keys(schema.fields).forEach(field => { + if (schema.fields[field].type === 'Relation') { + list.push(`_Join:${field}:${schema.className}`); + } + }); + } + + return list; +}; + +const buildWhereClause = ({ + schema, + query, + index +}) => { + const patterns = []; + let values = []; + const sorts = []; + schema = toPostgresSchema(schema); + + for (const fieldName in query) { + const isArrayField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array'; + const initialPatternsLength = patterns.length; + const fieldValue = query[fieldName]; // nothing in the schema, it's gonna blow up + + if (!schema.fields[fieldName]) { + // as it won't exist + if (fieldValue && fieldValue.$exists === false) { + continue; + } + } + + if (fieldName.indexOf('.') >= 0) { + let name = transformDotField(fieldName); + + if (fieldValue === null) { + patterns.push(`${name} IS NULL`); + } else { + if (fieldValue.$in) { + name = transformDotFieldToComponents(fieldName).join('->'); + patterns.push(`($${index}:raw)::jsonb @> $${index + 1}::jsonb`); + values.push(name, JSON.stringify(fieldValue.$in)); + index += 2; + } else if (fieldValue.$regex) {// Handle later + } else if (typeof fieldValue !== 'object') { + patterns.push(`$${index}:raw = $${index + 1}::text`); + values.push(name, fieldValue); + index += 2; + } + } + } else if (fieldValue === null || fieldValue === undefined) { + patterns.push(`$${index}:name IS NULL`); + values.push(fieldName); + index += 1; + continue; + } else if (typeof fieldValue === 'string') { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue); + index += 2; + } else if (typeof fieldValue === 'boolean') { + patterns.push(`$${index}:name = $${index + 1}`); // Can't cast boolean to double precision + + if (schema.fields[fieldName] && schema.fields[fieldName].type === 'Number') { + // Should always return zero results + const MAX_INT_PLUS_ONE = 9223372036854775808; + values.push(fieldName, MAX_INT_PLUS_ONE); + } else { + values.push(fieldName, fieldValue); + } + + index += 2; + } else if (typeof fieldValue === 'number') { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue); + index += 2; + } else if (['$or', '$nor', '$and'].includes(fieldName)) { + const clauses = []; + const clauseValues = []; + fieldValue.forEach(subQuery => { + const clause = buildWhereClause({ + schema, + query: subQuery, + index + }); + + if (clause.pattern.length > 0) { + clauses.push(clause.pattern); + clauseValues.push(...clause.values); + index += clause.values.length; + } + }); + const orOrAnd = fieldName === '$and' ? ' AND ' : ' OR '; + const not = fieldName === '$nor' ? ' NOT ' : ''; + patterns.push(`${not}(${clauses.join(orOrAnd)})`); + values.push(...clauseValues); + } + + if (fieldValue.$ne !== undefined) { + if (isArrayField) { + fieldValue.$ne = JSON.stringify([fieldValue.$ne]); + patterns.push(`NOT array_contains($${index}:name, $${index + 1})`); + } else { + if (fieldValue.$ne === null) { + patterns.push(`$${index}:name IS NOT NULL`); + values.push(fieldName); + index += 1; + continue; + } else { + // if not null, we need to manually exclude null + if (fieldValue.$ne.__type === 'GeoPoint') { + patterns.push(`($${index}:name <> POINT($${index + 1}, $${index + 2}) OR $${index}:name IS NULL)`); + } else { + if (fieldName.indexOf('.') >= 0) { + const constraintFieldName = transformDotField(fieldName); + patterns.push(`(${constraintFieldName} <> $${index} OR ${constraintFieldName} IS NULL)`); + } else { + patterns.push(`($${index}:name <> $${index + 1} OR $${index}:name IS NULL)`); + } + } + } + } + + if (fieldValue.$ne.__type === 'GeoPoint') { + const point = fieldValue.$ne; + values.push(fieldName, point.longitude, point.latitude); + index += 3; + } else { + // TODO: support arrays + values.push(fieldName, fieldValue.$ne); + index += 2; + } + } + + if (fieldValue.$eq !== undefined) { + if (fieldValue.$eq === null) { + patterns.push(`$${index}:name IS NULL`); + values.push(fieldName); + index += 1; + } else { + if (fieldName.indexOf('.') >= 0) { + values.push(fieldValue.$eq); + patterns.push(`${transformDotField(fieldName)} = $${index++}`); + } else { + values.push(fieldName, fieldValue.$eq); + patterns.push(`$${index}:name = $${index + 1}`); + index += 2; + } + } + } + + const isInOrNin = Array.isArray(fieldValue.$in) || Array.isArray(fieldValue.$nin); + + if (Array.isArray(fieldValue.$in) && isArrayField && schema.fields[fieldName].contents && schema.fields[fieldName].contents.type === 'String') { + const inPatterns = []; + let allowNull = false; + values.push(fieldName); + fieldValue.$in.forEach((listElem, listIndex) => { + if (listElem === null) { + allowNull = true; + } else { + values.push(listElem); + inPatterns.push(`$${index + 1 + listIndex - (allowNull ? 1 : 0)}`); + } + }); + + if (allowNull) { + patterns.push(`($${index}:name IS NULL OR $${index}:name && ARRAY[${inPatterns.join()}])`); + } else { + patterns.push(`$${index}:name && ARRAY[${inPatterns.join()}]`); + } + + index = index + 1 + inPatterns.length; + } else if (isInOrNin) { + var createConstraint = (baseArray, notIn) => { + const not = notIn ? ' NOT ' : ''; + + if (baseArray.length > 0) { + if (isArrayField) { + patterns.push(`${not} array_contains($${index}:name, $${index + 1})`); + values.push(fieldName, JSON.stringify(baseArray)); + index += 2; + } else { + // Handle Nested Dot Notation Above + if (fieldName.indexOf('.') >= 0) { + return; + } + + const inPatterns = []; + values.push(fieldName); + baseArray.forEach((listElem, listIndex) => { + if (listElem != null) { + values.push(listElem); + inPatterns.push(`$${index + 1 + listIndex}`); + } + }); + patterns.push(`$${index}:name ${not} IN (${inPatterns.join()})`); + index = index + 1 + inPatterns.length; + } + } else if (!notIn) { + values.push(fieldName); + patterns.push(`$${index}:name IS NULL`); + index = index + 1; + } else { + // Handle empty array + if (notIn) { + patterns.push('1 = 1'); // Return all values + } else { + patterns.push('1 = 2'); // Return no values + } + } + }; + + if (fieldValue.$in) { + createConstraint(_lodash.default.flatMap(fieldValue.$in, elt => elt), false); + } + + if (fieldValue.$nin) { + createConstraint(_lodash.default.flatMap(fieldValue.$nin, elt => elt), true); + } + } else if (typeof fieldValue.$in !== 'undefined') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $in value'); + } else if (typeof fieldValue.$nin !== 'undefined') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $nin value'); + } + + if (Array.isArray(fieldValue.$all) && isArrayField) { + if (isAnyValueRegexStartsWith(fieldValue.$all)) { + if (!isAllValuesRegexOrNone(fieldValue.$all)) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'All $all values must be of regex type or none: ' + fieldValue.$all); + } + + for (let i = 0; i < fieldValue.$all.length; i += 1) { + const value = processRegexPattern(fieldValue.$all[i].$regex); + fieldValue.$all[i] = value.substring(1) + '%'; + } + + patterns.push(`array_contains_all_regex($${index}:name, $${index + 1}::jsonb)`); + } else { + patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`); + } + + values.push(fieldName, JSON.stringify(fieldValue.$all)); + index += 2; + } else if (Array.isArray(fieldValue.$all)) { + if (fieldValue.$all.length === 1) { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.$all[0].objectId); + index += 2; + } + } + + if (typeof fieldValue.$exists !== 'undefined') { + if (fieldValue.$exists) { + patterns.push(`$${index}:name IS NOT NULL`); + } else { + patterns.push(`$${index}:name IS NULL`); + } + + values.push(fieldName); + index += 1; + } + + if (fieldValue.$containedBy) { + const arr = fieldValue.$containedBy; + + if (!(arr instanceof Array)) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $containedBy: should be an array`); + } + + patterns.push(`$${index}:name <@ $${index + 1}::jsonb`); + values.push(fieldName, JSON.stringify(arr)); + index += 2; + } + + if (fieldValue.$text) { + const search = fieldValue.$text.$search; + let language = 'english'; + + if (typeof search !== 'object') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $search, should be object`); + } + + if (!search.$term || typeof search.$term !== 'string') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $term, should be string`); + } + + if (search.$language && typeof search.$language !== 'string') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $language, should be string`); + } else if (search.$language) { + language = search.$language; + } + + if (search.$caseSensitive && typeof search.$caseSensitive !== 'boolean') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $caseSensitive, should be boolean`); + } else if (search.$caseSensitive) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $caseSensitive not supported, please use $regex or create a separate lower case column.`); + } + + if (search.$diacriticSensitive && typeof search.$diacriticSensitive !== 'boolean') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $diacriticSensitive, should be boolean`); + } else if (search.$diacriticSensitive === false) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $diacriticSensitive - false not supported, install Postgres Unaccent Extension`); + } + + patterns.push(`to_tsvector($${index}, $${index + 1}:name) @@ to_tsquery($${index + 2}, $${index + 3})`); + values.push(language, fieldName, language, search.$term); + index += 4; + } + + if (fieldValue.$nearSphere) { + const point = fieldValue.$nearSphere; + const distance = fieldValue.$maxDistance; + const distanceInKM = distance * 6371 * 1000; + patterns.push(`ST_distance_sphere($${index}:name::geometry, POINT($${index + 1}, $${index + 2})::geometry) <= $${index + 3}`); + sorts.push(`ST_distance_sphere($${index}:name::geometry, POINT($${index + 1}, $${index + 2})::geometry) ASC`); + values.push(fieldName, point.longitude, point.latitude, distanceInKM); + index += 4; + } + + if (fieldValue.$within && fieldValue.$within.$box) { + const box = fieldValue.$within.$box; + const left = box[0].longitude; + const bottom = box[0].latitude; + const right = box[1].longitude; + const top = box[1].latitude; + patterns.push(`$${index}:name::point <@ $${index + 1}::box`); + values.push(fieldName, `((${left}, ${bottom}), (${right}, ${top}))`); + index += 2; + } + + if (fieldValue.$geoWithin && fieldValue.$geoWithin.$centerSphere) { + const centerSphere = fieldValue.$geoWithin.$centerSphere; + + if (!(centerSphere instanceof Array) || centerSphere.length < 2) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere should be an array of Parse.GeoPoint and distance'); + } // Get point, convert to geo point if necessary and validate + + + let point = centerSphere[0]; + + if (point instanceof Array && point.length === 2) { + point = new _node.default.GeoPoint(point[1], point[0]); + } else if (!GeoPointCoder.isValidJSON(point)) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere geo point invalid'); + } + + _node.default.GeoPoint._validate(point.latitude, point.longitude); // Get distance and validate + + + const distance = centerSphere[1]; + + if (isNaN(distance) || distance < 0) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere distance invalid'); + } + + const distanceInKM = distance * 6371 * 1000; + patterns.push(`ST_distance_sphere($${index}:name::geometry, POINT($${index + 1}, $${index + 2})::geometry) <= $${index + 3}`); + values.push(fieldName, point.longitude, point.latitude, distanceInKM); + index += 4; + } + + if (fieldValue.$geoWithin && fieldValue.$geoWithin.$polygon) { + const polygon = fieldValue.$geoWithin.$polygon; + let points; + + if (typeof polygon === 'object' && polygon.__type === 'Polygon') { + if (!polygon.coordinates || polygon.coordinates.length < 3) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; Polygon.coordinates should contain at least 3 lon/lat pairs'); + } + + points = polygon.coordinates; + } else if (polygon instanceof Array) { + if (polygon.length < 3) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + } + + points = polygon; + } else { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, "bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint's"); + } + + points = points.map(point => { + if (point instanceof Array && point.length === 2) { + _node.default.GeoPoint._validate(point[1], point[0]); + + return `(${point[0]}, ${point[1]})`; + } + + if (typeof point !== 'object' || point.__type !== 'GeoPoint') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value'); + } else { + _node.default.GeoPoint._validate(point.latitude, point.longitude); + } + + return `(${point.longitude}, ${point.latitude})`; + }).join(', '); + patterns.push(`$${index}:name::point <@ $${index + 1}::polygon`); + values.push(fieldName, `(${points})`); + index += 2; + } + + if (fieldValue.$geoIntersects && fieldValue.$geoIntersects.$point) { + const point = fieldValue.$geoIntersects.$point; + + if (typeof point !== 'object' || point.__type !== 'GeoPoint') { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoIntersect value; $point should be GeoPoint'); + } else { + _node.default.GeoPoint._validate(point.latitude, point.longitude); + } + + patterns.push(`$${index}:name::polygon @> $${index + 1}::point`); + values.push(fieldName, `(${point.longitude}, ${point.latitude})`); + index += 2; + } + + if (fieldValue.$regex) { + let regex = fieldValue.$regex; + let operator = '~'; + const opts = fieldValue.$options; + + if (opts) { + if (opts.indexOf('i') >= 0) { + operator = '~*'; + } + + if (opts.indexOf('x') >= 0) { + regex = removeWhiteSpace(regex); + } + } + + const name = transformDotField(fieldName); + regex = processRegexPattern(regex); + patterns.push(`$${index}:raw ${operator} '$${index + 1}:raw'`); + values.push(name, regex); + index += 2; + } + + if (fieldValue.__type === 'Pointer') { + if (isArrayField) { + patterns.push(`array_contains($${index}:name, $${index + 1})`); + values.push(fieldName, JSON.stringify([fieldValue])); + index += 2; + } else { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.objectId); + index += 2; + } + } + + if (fieldValue.__type === 'Date') { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.iso); + index += 2; + } + + if (fieldValue.__type === 'GeoPoint') { + patterns.push(`$${index}:name ~= POINT($${index + 1}, $${index + 2})`); + values.push(fieldName, fieldValue.longitude, fieldValue.latitude); + index += 3; + } + + if (fieldValue.__type === 'Polygon') { + const value = convertPolygonToSQL(fieldValue.coordinates); + patterns.push(`$${index}:name ~= $${index + 1}::polygon`); + values.push(fieldName, value); + index += 2; + } + + Object.keys(ParseToPosgresComparator).forEach(cmp => { + if (fieldValue[cmp] || fieldValue[cmp] === 0) { + const pgComparator = ParseToPosgresComparator[cmp]; + const postgresValue = toPostgresValue(fieldValue[cmp]); + let constraintFieldName; + + if (fieldName.indexOf('.') >= 0) { + let castType; + + switch (typeof postgresValue) { + case 'number': + castType = 'double precision'; + break; + + case 'boolean': + castType = 'boolean'; + break; + + default: + castType = undefined; + } + + constraintFieldName = castType ? `CAST ((${transformDotField(fieldName)}) AS ${castType})` : transformDotField(fieldName); + } else { + constraintFieldName = `$${index++}:name`; + values.push(fieldName); + } + + values.push(postgresValue); + patterns.push(`${constraintFieldName} ${pgComparator} $${index++}`); + } + }); + + if (initialPatternsLength === patterns.length) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, `Postgres doesn't support this query type yet ${JSON.stringify(fieldValue)}`); + } + } + + values = values.map(transformValue); + return { + pattern: patterns.join(' AND '), + values, + sorts + }; +}; + +class PostgresStorageAdapter { + // Private + constructor({ + uri, + collectionPrefix = '', + databaseOptions + }) { + this._collectionPrefix = collectionPrefix; + const { + client, + pgp + } = (0, _PostgresClient.createClient)(uri, databaseOptions); + this._client = client; + this._pgp = pgp; + this.canSortOnJoinTables = false; + } + + handleShutdown() { + if (!this._client) { + return; + } + + this._client.$pool.end(); + } + + _ensureSchemaCollectionExists(conn) { + conn = conn || this._client; + return conn.none('CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )').catch(error => { + if (error.code === PostgresDuplicateRelationError || error.code === PostgresUniqueIndexViolationError || error.code === PostgresDuplicateObjectError) {// Table already exists, must have been created by a different request. Ignore error. + } else { + throw error; + } + }); + } + + classExists(name) { + return this._client.one('SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)', [name], a => a.exists); + } + + setClassLevelPermissions(className, CLPs) { + const self = this; + return this._client.task('set-class-level-permissions', async t => { + await self._ensureSchemaCollectionExists(t); + const values = [className, 'schema', 'classLevelPermissions', JSON.stringify(CLPs)]; + await t.none(`UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className"=$1`, values); + }); + } + + setIndexesWithSchemaFormat(className, submittedIndexes, existingIndexes = {}, fields, conn) { + conn = conn || this._client; + const self = this; + + if (submittedIndexes === undefined) { + return Promise.resolve(); + } + + if (Object.keys(existingIndexes).length === 0) { + existingIndexes = { + _id_: { + _id: 1 + } + }; + } + + const deletedIndexes = []; + const insertedIndexes = []; + Object.keys(submittedIndexes).forEach(name => { + const field = submittedIndexes[name]; + + if (existingIndexes[name] && field.__op !== 'Delete') { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`); + } + + if (!existingIndexes[name] && field.__op === 'Delete') { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Index ${name} does not exist, cannot delete.`); + } + + if (field.__op === 'Delete') { + deletedIndexes.push(name); + delete existingIndexes[name]; + } else { + Object.keys(field).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(fields, key)) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Field ${key} does not exist, cannot add index.`); + } + }); + existingIndexes[name] = field; + insertedIndexes.push({ + key: field, + name + }); + } + }); + return conn.tx('set-indexes-with-schema-format', async t => { + if (insertedIndexes.length > 0) { + await self.createIndexes(className, insertedIndexes, t); + } + + if (deletedIndexes.length > 0) { + await self.dropIndexes(className, deletedIndexes, t); + } + + await self._ensureSchemaCollectionExists(t); + await t.none('UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className"=$1', [className, 'schema', 'indexes', JSON.stringify(existingIndexes)]); + }); + } + + createClass(className, schema, conn) { + conn = conn || this._client; + return conn.tx('create-class', t => { + const q1 = this.createTable(className, schema, t); + const q2 = t.none('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($, $, true)', { + className, + schema + }); + const q3 = this.setIndexesWithSchemaFormat(className, schema.indexes, {}, schema.fields, t); + return t.batch([q1, q2, q3]); + }).then(() => { + return toParseSchema(schema); + }).catch(err => { + if (err.data[0].result.code === PostgresTransactionAbortedError) { + err = err.data[1].result; + } + + if (err.code === PostgresUniqueIndexViolationError && err.detail.includes(className)) { + throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, `Class ${className} already exists.`); + } + + throw err; + }); + } // Just create a table, do not insert in schema + + + createTable(className, schema, conn) { + conn = conn || this._client; + const self = this; + debug('createTable', className, schema); + const valuesArray = []; + const patternsArray = []; + const fields = Object.assign({}, schema.fields); + + if (className === '_User') { + fields._email_verify_token_expires_at = { + type: 'Date' + }; + fields._email_verify_token = { + type: 'String' + }; + fields._account_lockout_expires_at = { + type: 'Date' + }; + fields._failed_login_count = { + type: 'Number' + }; + fields._perishable_token = { + type: 'String' + }; + fields._perishable_token_expires_at = { + type: 'Date' + }; + fields._password_changed_at = { + type: 'Date' + }; + fields._password_history = { + type: 'Array' + }; + } + + let index = 2; + const relations = []; + Object.keys(fields).forEach(fieldName => { + const parseType = fields[fieldName]; // Skip when it's a relation + // We'll create the tables later + + if (parseType.type === 'Relation') { + relations.push(fieldName); + return; + } + + if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) { + parseType.contents = { + type: 'String' + }; + } + + valuesArray.push(fieldName); + valuesArray.push(parseTypeToPostgresType(parseType)); + patternsArray.push(`$${index}:name $${index + 1}:raw`); + + if (fieldName === 'objectId') { + patternsArray.push(`PRIMARY KEY ($${index}:name)`); + } + + index = index + 2; + }); + const qs = `CREATE TABLE IF NOT EXISTS $1:name (${patternsArray.join()})`; + const values = [className, ...valuesArray]; + debug(qs, values); + return conn.task('create-table', async t => { + try { + await self._ensureSchemaCollectionExists(t); + await t.none(qs, values); + } catch (error) { + if (error.code !== PostgresDuplicateRelationError) { + throw error; + } // ELSE: Table already exists, must have been created by a different request. Ignore the error. + + } + + await t.tx('create-table-tx', tx => { + return tx.batch(relations.map(fieldName => { + return tx.none('CREATE TABLE IF NOT EXISTS $ ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', { + joinTable: `_Join:${fieldName}:${className}` + }); + })); + }); + }); + } + + schemaUpgrade(className, schema, conn) { + debug('schemaUpgrade', { + className, + schema + }); + conn = conn || this._client; + const self = this; + return conn.tx('schema-upgrade', async t => { + const columns = await t.map('SELECT column_name FROM information_schema.columns WHERE table_name = $', { + className + }, a => a.column_name); + const newColumns = Object.keys(schema.fields).filter(item => columns.indexOf(item) === -1).map(fieldName => self.addFieldIfNotExists(className, fieldName, schema.fields[fieldName], t)); + await t.batch(newColumns); + }); + } + + addFieldIfNotExists(className, fieldName, type, conn) { + // TODO: Must be revised for invalid logic... + debug('addFieldIfNotExists', { + className, + fieldName, + type + }); + conn = conn || this._client; + const self = this; + return conn.tx('add-field-if-not-exists', async t => { + if (type.type !== 'Relation') { + try { + await t.none('ALTER TABLE $ ADD COLUMN $ $', { + className, + fieldName, + postgresType: parseTypeToPostgresType(type) + }); + } catch (error) { + if (error.code === PostgresRelationDoesNotExistError) { + return await self.createClass(className, { + fields: { + [fieldName]: type + } + }, t); + } + + if (error.code !== PostgresDuplicateColumnError) { + throw error; + } // Column already exists, created by other request. Carry on to see if it's the right type. + + } + } else { + await t.none('CREATE TABLE IF NOT EXISTS $ ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', { + joinTable: `_Join:${fieldName}:${className}` + }); + } + + const result = await t.any('SELECT "schema" FROM "_SCHEMA" WHERE "className" = $ and ("schema"::json->\'fields\'->$) is not null', { + className, + fieldName + }); + + if (result[0]) { + throw 'Attempted to add a field that already exists'; + } else { + const path = `{fields,${fieldName}}`; + await t.none('UPDATE "_SCHEMA" SET "schema"=jsonb_set("schema", $, $) WHERE "className"=$', { + path, + type, + className + }); + } + }); + } // Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.) + // and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible. + + + deleteClass(className) { + const operations = [{ + query: `DROP TABLE IF EXISTS $1:name`, + values: [className] + }, { + query: `DELETE FROM "_SCHEMA" WHERE "className" = $1`, + values: [className] + }]; + return this._client.tx(t => t.none(this._pgp.helpers.concat(operations))).then(() => className.indexOf('_Join:') != 0); // resolves with false when _Join table + } // Delete all data known to this adapter. Used for testing. + + + deleteAllClasses() { + const now = new Date().getTime(); + const helpers = this._pgp.helpers; + debug('deleteAllClasses'); + return this._client.task('delete-all-classes', async t => { + try { + const results = await t.any('SELECT * FROM "_SCHEMA"'); + const joins = results.reduce((list, schema) => { + return list.concat(joinTablesForSchema(schema.schema)); + }, []); + const classes = ['_SCHEMA', '_PushStatus', '_JobStatus', '_JobSchedule', '_Hooks', '_GlobalConfig', '_GraphQLConfig', '_Audience', ...results.map(result => result.className), ...joins]; + const queries = classes.map(className => ({ + query: 'DROP TABLE IF EXISTS $', + values: { + className + } + })); + await t.tx(tx => tx.none(helpers.concat(queries))); + } catch (error) { + if (error.code !== PostgresRelationDoesNotExistError) { + throw error; + } // No _SCHEMA collection. Don't delete anything. + + } + }).then(() => { + debug(`deleteAllClasses done in ${new Date().getTime() - now}`); + }); + } // Remove the column and all the data. For Relations, the _Join collection is handled + // specially, this function does not delete _Join columns. It should, however, indicate + // that the relation fields does not exist anymore. In mongo, this means removing it from + // the _SCHEMA collection. There should be no actual data in the collection under the same name + // as the relation column, so it's fine to attempt to delete it. If the fields listed to be + // deleted do not exist, this function should return successfully anyways. Checking for + // attempts to delete non-existent fields is the responsibility of Parse Server. + // This function is not obligated to delete fields atomically. It is given the field + // names in a list so that databases that are capable of deleting fields atomically + // may do so. + // Returns a Promise. + + + deleteFields(className, schema, fieldNames) { + debug('deleteFields', className, fieldNames); + fieldNames = fieldNames.reduce((list, fieldName) => { + const field = schema.fields[fieldName]; + + if (field.type !== 'Relation') { + list.push(fieldName); + } + + delete schema.fields[fieldName]; + return list; + }, []); + const values = [className, ...fieldNames]; + const columns = fieldNames.map((name, idx) => { + return `$${idx + 2}:name`; + }).join(', DROP COLUMN'); + return this._client.tx('delete-fields', async t => { + await t.none('UPDATE "_SCHEMA" SET "schema"=$ WHERE "className"=$', { + schema, + className + }); + + if (values.length > 1) { + await t.none(`ALTER TABLE $1:name DROP COLUMN ${columns}`, values); + } + }); + } // Return a promise for all schemas known to this adapter, in Parse format. In case the + // schemas cannot be retrieved, returns a promise that rejects. Requirements for the + // rejection reason are TBD. + + + getAllClasses() { + const self = this; + return this._client.task('get-all-classes', async t => { + await self._ensureSchemaCollectionExists(t); + return await t.map('SELECT * FROM "_SCHEMA"', null, row => toParseSchema(_objectSpread({ + className: row.className + }, row.schema))); + }); + } // Return a promise for the schema with the given name, in Parse format. If + // this adapter doesn't know about the schema, return a promise that rejects with + // undefined as the reason. + + + getClass(className) { + debug('getClass', className); + return this._client.any('SELECT * FROM "_SCHEMA" WHERE "className"=$', { + className + }).then(result => { + if (result.length !== 1) { + throw undefined; + } + + return result[0].schema; + }).then(toParseSchema); + } // TODO: remove the mongo format dependency in the return value + + + createObject(className, schema, object, transactionalSession) { + debug('createObject', className, object); + let columnsArray = []; + const valuesArray = []; + schema = toPostgresSchema(schema); + const geoPoints = {}; + object = handleDotFields(object); + validateKeys(object); + Object.keys(object).forEach(fieldName => { + if (object[fieldName] === null) { + return; + } + + var authDataMatch = fieldName.match(/^_auth_data_([a-zA-Z0-9_]+)$/); + + if (authDataMatch) { + var provider = authDataMatch[1]; + object['authData'] = object['authData'] || {}; + object['authData'][provider] = object[fieldName]; + delete object[fieldName]; + fieldName = 'authData'; + } + + columnsArray.push(fieldName); + + if (!schema.fields[fieldName] && className === '_User') { + if (fieldName === '_email_verify_token' || fieldName === '_failed_login_count' || fieldName === '_perishable_token' || fieldName === '_password_history') { + valuesArray.push(object[fieldName]); + } + + if (fieldName === '_email_verify_token_expires_at') { + if (object[fieldName]) { + valuesArray.push(object[fieldName].iso); + } else { + valuesArray.push(null); + } + } + + if (fieldName === '_account_lockout_expires_at' || fieldName === '_perishable_token_expires_at' || fieldName === '_password_changed_at') { + if (object[fieldName]) { + valuesArray.push(object[fieldName].iso); + } else { + valuesArray.push(null); + } + } + + return; + } + + switch (schema.fields[fieldName].type) { + case 'Date': + if (object[fieldName]) { + valuesArray.push(object[fieldName].iso); + } else { + valuesArray.push(null); + } + + break; + + case 'Pointer': + valuesArray.push(object[fieldName].objectId); + break; + + case 'Array': + if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) { + valuesArray.push(object[fieldName]); + } else { + valuesArray.push(JSON.stringify(object[fieldName])); + } + + break; + + case 'Object': + case 'Bytes': + case 'String': + case 'Number': + case 'Boolean': + valuesArray.push(object[fieldName]); + break; + + case 'File': + valuesArray.push(object[fieldName].name); + break; + + case 'Polygon': + { + const value = convertPolygonToSQL(object[fieldName].coordinates); + valuesArray.push(value); + break; + } + + case 'GeoPoint': + // pop the point and process later + geoPoints[fieldName] = object[fieldName]; + columnsArray.pop(); + break; + + default: + throw `Type ${schema.fields[fieldName].type} not supported yet`; + } + }); + columnsArray = columnsArray.concat(Object.keys(geoPoints)); + const initialValues = valuesArray.map((val, index) => { + let termination = ''; + const fieldName = columnsArray[index]; + + if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) { + termination = '::text[]'; + } else if (schema.fields[fieldName] && schema.fields[fieldName].type === 'Array') { + termination = '::jsonb'; + } + + return `$${index + 2 + columnsArray.length}${termination}`; + }); + const geoPointsInjects = Object.keys(geoPoints).map(key => { + const value = geoPoints[key]; + valuesArray.push(value.longitude, value.latitude); + const l = valuesArray.length + columnsArray.length; + return `POINT($${l}, $${l + 1})`; + }); + const columnsPattern = columnsArray.map((col, index) => `$${index + 2}:name`).join(); + const valuesPattern = initialValues.concat(geoPointsInjects).join(); + const qs = `INSERT INTO $1:name (${columnsPattern}) VALUES (${valuesPattern})`; + const values = [className, ...columnsArray, ...valuesArray]; + debug(qs, values); + const promise = (transactionalSession ? transactionalSession.t : this._client).none(qs, values).then(() => ({ + ops: [object] + })).catch(error => { + if (error.code === PostgresUniqueIndexViolationError) { + const err = new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided'); + err.underlyingError = error; + + if (error.constraint) { + const matches = error.constraint.match(/unique_([a-zA-Z]+)/); + + if (matches && Array.isArray(matches)) { + err.userInfo = { + duplicated_field: matches[1] + }; + } + } + + error = err; + } + + throw error; + }); + + if (transactionalSession) { + transactionalSession.batch.push(promise); + } + + return promise; + } // Remove all objects that match the given Parse Query. + // If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined. + // If there is some other error, reject with INTERNAL_SERVER_ERROR. + + + deleteObjectsByQuery(className, schema, query, transactionalSession) { + debug('deleteObjectsByQuery', className, query); + const values = [className]; + const index = 2; + const where = buildWhereClause({ + schema, + index, + query + }); + values.push(...where.values); + + if (Object.keys(query).length === 0) { + where.pattern = 'TRUE'; + } + + const qs = `WITH deleted AS (DELETE FROM $1:name WHERE ${where.pattern} RETURNING *) SELECT count(*) FROM deleted`; + debug(qs, values); + const promise = (transactionalSession ? transactionalSession.t : this._client).one(qs, values, a => +a.count).then(count => { + if (count === 0) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } else { + return count; + } + }).catch(error => { + if (error.code !== PostgresRelationDoesNotExistError) { + throw error; + } // ELSE: Don't delete anything if doesn't exist + + }); + + if (transactionalSession) { + transactionalSession.batch.push(promise); + } + + return promise; + } // Return value not currently well specified. + + + findOneAndUpdate(className, schema, query, update, transactionalSession) { + debug('findOneAndUpdate', className, query, update); + return this.updateObjectsByQuery(className, schema, query, update, transactionalSession).then(val => val[0]); + } // Apply the update to all objects that match the given Parse Query. + + + updateObjectsByQuery(className, schema, query, update, transactionalSession) { + debug('updateObjectsByQuery', className, query, update); + const updatePatterns = []; + const values = [className]; + let index = 2; + schema = toPostgresSchema(schema); + + const originalUpdate = _objectSpread({}, update); // Set flag for dot notation fields + + + const dotNotationOptions = {}; + Object.keys(update).forEach(fieldName => { + if (fieldName.indexOf('.') > -1) { + const components = fieldName.split('.'); + const first = components.shift(); + dotNotationOptions[first] = true; + } else { + dotNotationOptions[fieldName] = false; + } + }); + update = handleDotFields(update); // Resolve authData first, + // So we don't end up with multiple key updates + + for (const fieldName in update) { + const authDataMatch = fieldName.match(/^_auth_data_([a-zA-Z0-9_]+)$/); + + if (authDataMatch) { + var provider = authDataMatch[1]; + const value = update[fieldName]; + delete update[fieldName]; + update['authData'] = update['authData'] || {}; + update['authData'][provider] = value; + } + } + + for (const fieldName in update) { + const fieldValue = update[fieldName]; // Drop any undefined values. + + if (typeof fieldValue === 'undefined') { + delete update[fieldName]; + } else if (fieldValue === null) { + updatePatterns.push(`$${index}:name = NULL`); + values.push(fieldName); + index += 1; + } else if (fieldName == 'authData') { + // This recursively sets the json_object + // Only 1 level deep + const generate = (jsonb, key, value) => { + return `json_object_set_key(COALESCE(${jsonb}, '{}'::jsonb), ${key}, ${value})::jsonb`; + }; + + const lastKey = `$${index}:name`; + const fieldNameIndex = index; + index += 1; + values.push(fieldName); + const update = Object.keys(fieldValue).reduce((lastKey, key) => { + const str = generate(lastKey, `$${index}::text`, `$${index + 1}::jsonb`); + index += 2; + let value = fieldValue[key]; + + if (value) { + if (value.__op === 'Delete') { + value = null; + } else { + value = JSON.stringify(value); + } + } + + values.push(key, value); + return str; + }, lastKey); + updatePatterns.push(`$${fieldNameIndex}:name = ${update}`); + } else if (fieldValue.__op === 'Increment') { + updatePatterns.push(`$${index}:name = COALESCE($${index}:name, 0) + $${index + 1}`); + values.push(fieldName, fieldValue.amount); + index += 2; + } else if (fieldValue.__op === 'Add') { + updatePatterns.push(`$${index}:name = array_add(COALESCE($${index}:name, '[]'::jsonb), $${index + 1}::jsonb)`); + values.push(fieldName, JSON.stringify(fieldValue.objects)); + index += 2; + } else if (fieldValue.__op === 'Delete') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, null); + index += 2; + } else if (fieldValue.__op === 'Remove') { + updatePatterns.push(`$${index}:name = array_remove(COALESCE($${index}:name, '[]'::jsonb), $${index + 1}::jsonb)`); + values.push(fieldName, JSON.stringify(fieldValue.objects)); + index += 2; + } else if (fieldValue.__op === 'AddUnique') { + updatePatterns.push(`$${index}:name = array_add_unique(COALESCE($${index}:name, '[]'::jsonb), $${index + 1}::jsonb)`); + values.push(fieldName, JSON.stringify(fieldValue.objects)); + index += 2; + } else if (fieldName === 'updatedAt') { + //TODO: stop special casing this. It should check for __type === 'Date' and use .iso + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue); + index += 2; + } else if (typeof fieldValue === 'string') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue); + index += 2; + } else if (typeof fieldValue === 'boolean') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue); + index += 2; + } else if (fieldValue.__type === 'Pointer') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.objectId); + index += 2; + } else if (fieldValue.__type === 'Date') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, toPostgresValue(fieldValue)); + index += 2; + } else if (fieldValue instanceof Date) { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue); + index += 2; + } else if (fieldValue.__type === 'File') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, toPostgresValue(fieldValue)); + index += 2; + } else if (fieldValue.__type === 'GeoPoint') { + updatePatterns.push(`$${index}:name = POINT($${index + 1}, $${index + 2})`); + values.push(fieldName, fieldValue.longitude, fieldValue.latitude); + index += 3; + } else if (fieldValue.__type === 'Polygon') { + const value = convertPolygonToSQL(fieldValue.coordinates); + updatePatterns.push(`$${index}:name = $${index + 1}::polygon`); + values.push(fieldName, value); + index += 2; + } else if (fieldValue.__type === 'Relation') {// noop + } else if (typeof fieldValue === 'number') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue); + index += 2; + } else if (typeof fieldValue === 'object' && schema.fields[fieldName] && schema.fields[fieldName].type === 'Object') { + // Gather keys to increment + const keysToIncrement = Object.keys(originalUpdate).filter(k => { + // choose top level fields that have a delete operation set + // Note that Object.keys is iterating over the **original** update object + // and that some of the keys of the original update could be null or undefined: + // (See the above check `if (fieldValue === null || typeof fieldValue == "undefined")`) + const value = originalUpdate[k]; + return value && value.__op === 'Increment' && k.split('.').length === 2 && k.split('.')[0] === fieldName; + }).map(k => k.split('.')[1]); + let incrementPatterns = ''; + + if (keysToIncrement.length > 0) { + incrementPatterns = ' || ' + keysToIncrement.map(c => { + const amount = fieldValue[c].amount; + return `CONCAT('{"${c}":', COALESCE($${index}:name->>'${c}','0')::int + ${amount}, '}')::jsonb`; + }).join(' || '); // Strip the keys + + keysToIncrement.forEach(key => { + delete fieldValue[key]; + }); + } + + const keysToDelete = Object.keys(originalUpdate).filter(k => { + // choose top level fields that have a delete operation set. + const value = originalUpdate[k]; + return value && value.__op === 'Delete' && k.split('.').length === 2 && k.split('.')[0] === fieldName; + }).map(k => k.split('.')[1]); + const deletePatterns = keysToDelete.reduce((p, c, i) => { + return p + ` - '$${index + 1 + i}:value'`; + }, ''); // Override Object + + let updateObject = "'{}'::jsonb"; + + if (dotNotationOptions[fieldName]) { + // Merge Object + updateObject = `COALESCE($${index}:name, '{}'::jsonb)`; + } + + updatePatterns.push(`$${index}:name = (${updateObject} ${deletePatterns} ${incrementPatterns} || $${index + 1 + keysToDelete.length}::jsonb )`); + values.push(fieldName, ...keysToDelete, JSON.stringify(fieldValue)); + index += 2 + keysToDelete.length; + } else if (Array.isArray(fieldValue) && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array') { + const expectedType = parseTypeToPostgresType(schema.fields[fieldName]); + + if (expectedType === 'text[]') { + updatePatterns.push(`$${index}:name = $${index + 1}::text[]`); + values.push(fieldName, fieldValue); + index += 2; + } else { + updatePatterns.push(`$${index}:name = $${index + 1}::jsonb`); + values.push(fieldName, JSON.stringify(fieldValue)); + index += 2; + } + } else { + debug('Not supported update', fieldName, fieldValue); + return Promise.reject(new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, `Postgres doesn't support update ${JSON.stringify(fieldValue)} yet`)); + } + } + + const where = buildWhereClause({ + schema, + index, + query + }); + values.push(...where.values); + const whereClause = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const qs = `UPDATE $1:name SET ${updatePatterns.join()} ${whereClause} RETURNING *`; + debug('update: ', qs, values); + const promise = (transactionalSession ? transactionalSession.t : this._client).any(qs, values); + + if (transactionalSession) { + transactionalSession.batch.push(promise); + } + + return promise; + } // Hopefully, we can get rid of this. It's only used for config and hooks. + + + upsertOneObject(className, schema, query, update, transactionalSession) { + debug('upsertOneObject', { + className, + query, + update + }); + const createValue = Object.assign({}, query, update); + return this.createObject(className, schema, createValue, transactionalSession).catch(error => { + // ignore duplicate value errors as it's upsert + if (error.code !== _node.default.Error.DUPLICATE_VALUE) { + throw error; + } + + return this.findOneAndUpdate(className, schema, query, update, transactionalSession); + }); + } + + find(className, schema, query, { + skip, + limit, + sort, + keys + }) { + debug('find', className, query, { + skip, + limit, + sort, + keys + }); + const hasLimit = limit !== undefined; + const hasSkip = skip !== undefined; + let values = [className]; + const where = buildWhereClause({ + schema, + query, + index: 2 + }); + values.push(...where.values); + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const limitPattern = hasLimit ? `LIMIT $${values.length + 1}` : ''; + + if (hasLimit) { + values.push(limit); + } + + const skipPattern = hasSkip ? `OFFSET $${values.length + 1}` : ''; + + if (hasSkip) { + values.push(skip); + } + + let sortPattern = ''; + + if (sort) { + const sortCopy = sort; + const sorting = Object.keys(sort).map(key => { + const transformKey = transformDotFieldToComponents(key).join('->'); // Using $idx pattern gives: non-integer constant in ORDER BY + + if (sortCopy[key] === 1) { + return `${transformKey} ASC`; + } + + return `${transformKey} DESC`; + }).join(); + sortPattern = sort !== undefined && Object.keys(sort).length > 0 ? `ORDER BY ${sorting}` : ''; + } + + if (where.sorts && Object.keys(where.sorts).length > 0) { + sortPattern = `ORDER BY ${where.sorts.join()}`; + } + + let columns = '*'; + + if (keys) { + // Exclude empty keys + // Replace ACL by it's keys + keys = keys.reduce((memo, key) => { + if (key === 'ACL') { + memo.push('_rperm'); + memo.push('_wperm'); + } else if (key.length > 0) { + memo.push(key); + } + + return memo; + }, []); + columns = keys.map((key, index) => { + if (key === '$score') { + return `ts_rank_cd(to_tsvector($${2}, $${3}:name), to_tsquery($${4}, $${5}), 32) as score`; + } + + return `$${index + values.length + 1}:name`; + }).join(); + values = values.concat(keys); + } + + const qs = `SELECT ${columns} FROM $1:name ${wherePattern} ${sortPattern} ${limitPattern} ${skipPattern}`; + debug(qs, values); + return this._client.any(qs, values).catch(error => { + // Query on non existing table, don't crash + if (error.code !== PostgresRelationDoesNotExistError) { + throw error; + } + + return []; + }).then(results => results.map(object => this.postgresObjectToParseObject(className, object, schema))); + } // Converts from a postgres-format object to a REST-format object. + // Does not strip out anything based on a lack of authentication. + + + postgresObjectToParseObject(className, object, schema) { + Object.keys(schema.fields).forEach(fieldName => { + if (schema.fields[fieldName].type === 'Pointer' && object[fieldName]) { + object[fieldName] = { + objectId: object[fieldName], + __type: 'Pointer', + className: schema.fields[fieldName].targetClass + }; + } + + if (schema.fields[fieldName].type === 'Relation') { + object[fieldName] = { + __type: 'Relation', + className: schema.fields[fieldName].targetClass + }; + } + + if (object[fieldName] && schema.fields[fieldName].type === 'GeoPoint') { + object[fieldName] = { + __type: 'GeoPoint', + latitude: object[fieldName].y, + longitude: object[fieldName].x + }; + } + + if (object[fieldName] && schema.fields[fieldName].type === 'Polygon') { + let coords = object[fieldName]; + coords = coords.substr(2, coords.length - 4).split('),('); + coords = coords.map(point => { + return [parseFloat(point.split(',')[1]), parseFloat(point.split(',')[0])]; + }); + object[fieldName] = { + __type: 'Polygon', + coordinates: coords + }; + } + + if (object[fieldName] && schema.fields[fieldName].type === 'File') { + object[fieldName] = { + __type: 'File', + name: object[fieldName] + }; + } + }); //TODO: remove this reliance on the mongo format. DB adapter shouldn't know there is a difference between created at and any other date field. + + if (object.createdAt) { + object.createdAt = object.createdAt.toISOString(); + } + + if (object.updatedAt) { + object.updatedAt = object.updatedAt.toISOString(); + } + + if (object.expiresAt) { + object.expiresAt = { + __type: 'Date', + iso: object.expiresAt.toISOString() + }; + } + + if (object._email_verify_token_expires_at) { + object._email_verify_token_expires_at = { + __type: 'Date', + iso: object._email_verify_token_expires_at.toISOString() + }; + } + + if (object._account_lockout_expires_at) { + object._account_lockout_expires_at = { + __type: 'Date', + iso: object._account_lockout_expires_at.toISOString() + }; + } + + if (object._perishable_token_expires_at) { + object._perishable_token_expires_at = { + __type: 'Date', + iso: object._perishable_token_expires_at.toISOString() + }; + } + + if (object._password_changed_at) { + object._password_changed_at = { + __type: 'Date', + iso: object._password_changed_at.toISOString() + }; + } + + for (const fieldName in object) { + if (object[fieldName] === null) { + delete object[fieldName]; + } + + if (object[fieldName] instanceof Date) { + object[fieldName] = { + __type: 'Date', + iso: object[fieldName].toISOString() + }; + } + } + + return object; + } // Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't + // currently know which fields are nullable and which aren't, we ignore that criteria. + // As such, we shouldn't expose this function to users of parse until we have an out-of-band + // Way of determining if a field is nullable. Undefined doesn't count against uniqueness, + // which is why we use sparse indexes. + + + ensureUniqueness(className, schema, fieldNames) { + // Use the same name for every ensureUniqueness attempt, because postgres + // Will happily create the same index with multiple names. + const constraintName = `unique_${fieldNames.sort().join('_')}`; + const constraintPatterns = fieldNames.map((fieldName, index) => `$${index + 3}:name`); + const qs = `ALTER TABLE $1:name ADD CONSTRAINT $2:name UNIQUE (${constraintPatterns.join()})`; + return this._client.none(qs, [className, constraintName, ...fieldNames]).catch(error => { + if (error.code === PostgresDuplicateRelationError && error.message.includes(constraintName)) {// Index already exists. Ignore error. + } else if (error.code === PostgresUniqueIndexViolationError && error.message.includes(constraintName)) { + // Cast the error into the proper parse error + throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided'); + } else { + throw error; + } + }); + } // Executes a count. + + + count(className, schema, query, readPreference, estimate = true) { + debug('count', className, query, readPreference, estimate); + const values = [className]; + const where = buildWhereClause({ + schema, + query, + index: 2 + }); + values.push(...where.values); + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + let qs = ''; + + if (where.pattern.length > 0 || !estimate) { + qs = `SELECT count(*) FROM $1:name ${wherePattern}`; + } else { + qs = 'SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = $1'; + } + + return this._client.one(qs, values, a => { + if (a.approximate_row_count != null) { + return +a.approximate_row_count; + } else { + return +a.count; + } + }).catch(error => { + if (error.code !== PostgresRelationDoesNotExistError) { + throw error; + } + + return 0; + }); + } + + distinct(className, schema, query, fieldName) { + debug('distinct', className, query); + let field = fieldName; + let column = fieldName; + const isNested = fieldName.indexOf('.') >= 0; + + if (isNested) { + field = transformDotFieldToComponents(fieldName).join('->'); + column = fieldName.split('.')[0]; + } + + const isArrayField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array'; + const isPointerField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Pointer'; + const values = [field, column, className]; + const where = buildWhereClause({ + schema, + query, + index: 4 + }); + values.push(...where.values); + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const transformer = isArrayField ? 'jsonb_array_elements' : 'ON'; + let qs = `SELECT DISTINCT ${transformer}($1:name) $2:name FROM $3:name ${wherePattern}`; + + if (isNested) { + qs = `SELECT DISTINCT ${transformer}($1:raw) $2:raw FROM $3:name ${wherePattern}`; + } + + debug(qs, values); + return this._client.any(qs, values).catch(error => { + if (error.code === PostgresMissingColumnError) { + return []; + } + + throw error; + }).then(results => { + if (!isNested) { + results = results.filter(object => object[field] !== null); + return results.map(object => { + if (!isPointerField) { + return object[field]; + } + + return { + __type: 'Pointer', + className: schema.fields[fieldName].targetClass, + objectId: object[field] + }; + }); + } + + const child = fieldName.split('.')[1]; + return results.map(object => object[column][child]); + }).then(results => results.map(object => this.postgresObjectToParseObject(className, object, schema))); + } + + aggregate(className, schema, pipeline) { + debug('aggregate', className, pipeline); + const values = [className]; + let index = 2; + let columns = []; + let countField = null; + let groupValues = null; + let wherePattern = ''; + let limitPattern = ''; + let skipPattern = ''; + let sortPattern = ''; + let groupPattern = ''; + + for (let i = 0; i < pipeline.length; i += 1) { + const stage = pipeline[i]; + + if (stage.$group) { + for (const field in stage.$group) { + const value = stage.$group[field]; + + if (value === null || value === undefined) { + continue; + } + + if (field === '_id' && typeof value === 'string' && value !== '') { + columns.push(`$${index}:name AS "objectId"`); + groupPattern = `GROUP BY $${index}:name`; + values.push(transformAggregateField(value)); + index += 1; + continue; + } + + if (field === '_id' && typeof value === 'object' && Object.keys(value).length !== 0) { + groupValues = value; + const groupByFields = []; + + for (const alias in value) { + const operation = Object.keys(value[alias])[0]; + const source = transformAggregateField(value[alias][operation]); + + if (mongoAggregateToPostgres[operation]) { + if (!groupByFields.includes(`"${source}"`)) { + groupByFields.push(`"${source}"`); + } + + columns.push(`EXTRACT(${mongoAggregateToPostgres[operation]} FROM $${index}:name AT TIME ZONE 'UTC') AS $${index + 1}:name`); + values.push(source, alias); + index += 2; + } + } + + groupPattern = `GROUP BY $${index}:raw`; + values.push(groupByFields.join()); + index += 1; + continue; + } + + if (typeof value === 'object') { + if (value.$sum) { + if (typeof value.$sum === 'string') { + columns.push(`SUM($${index}:name) AS $${index + 1}:name`); + values.push(transformAggregateField(value.$sum), field); + index += 2; + } else { + countField = field; + columns.push(`COUNT(*) AS $${index}:name`); + values.push(field); + index += 1; + } + } + + if (value.$max) { + columns.push(`MAX($${index}:name) AS $${index + 1}:name`); + values.push(transformAggregateField(value.$max), field); + index += 2; + } + + if (value.$min) { + columns.push(`MIN($${index}:name) AS $${index + 1}:name`); + values.push(transformAggregateField(value.$min), field); + index += 2; + } + + if (value.$avg) { + columns.push(`AVG($${index}:name) AS $${index + 1}:name`); + values.push(transformAggregateField(value.$avg), field); + index += 2; + } + } + } + } else { + columns.push('*'); + } + + if (stage.$project) { + if (columns.includes('*')) { + columns = []; + } + + for (const field in stage.$project) { + const value = stage.$project[field]; + + if (value === 1 || value === true) { + columns.push(`$${index}:name`); + values.push(field); + index += 1; + } + } + } + + if (stage.$match) { + const patterns = []; + const orOrAnd = Object.prototype.hasOwnProperty.call(stage.$match, '$or') ? ' OR ' : ' AND '; + + if (stage.$match.$or) { + const collapse = {}; + stage.$match.$or.forEach(element => { + for (const key in element) { + collapse[key] = element[key]; + } + }); + stage.$match = collapse; + } + + for (const field in stage.$match) { + const value = stage.$match[field]; + const matchPatterns = []; + Object.keys(ParseToPosgresComparator).forEach(cmp => { + if (value[cmp]) { + const pgComparator = ParseToPosgresComparator[cmp]; + matchPatterns.push(`$${index}:name ${pgComparator} $${index + 1}`); + values.push(field, toPostgresValue(value[cmp])); + index += 2; + } + }); + + if (matchPatterns.length > 0) { + patterns.push(`(${matchPatterns.join(' AND ')})`); + } + + if (schema.fields[field] && schema.fields[field].type && matchPatterns.length === 0) { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(field, value); + index += 2; + } + } + + wherePattern = patterns.length > 0 ? `WHERE ${patterns.join(` ${orOrAnd} `)}` : ''; + } + + if (stage.$limit) { + limitPattern = `LIMIT $${index}`; + values.push(stage.$limit); + index += 1; + } + + if (stage.$skip) { + skipPattern = `OFFSET $${index}`; + values.push(stage.$skip); + index += 1; + } + + if (stage.$sort) { + const sort = stage.$sort; + const keys = Object.keys(sort); + const sorting = keys.map(key => { + const transformer = sort[key] === 1 ? 'ASC' : 'DESC'; + const order = `$${index}:name ${transformer}`; + index += 1; + return order; + }).join(); + values.push(...keys); + sortPattern = sort !== undefined && sorting.length > 0 ? `ORDER BY ${sorting}` : ''; + } + } + + const qs = `SELECT ${columns.join()} FROM $1:name ${wherePattern} ${sortPattern} ${limitPattern} ${skipPattern} ${groupPattern}`; + debug(qs, values); + return this._client.map(qs, values, a => this.postgresObjectToParseObject(className, a, schema)).then(results => { + results.forEach(result => { + if (!Object.prototype.hasOwnProperty.call(result, 'objectId')) { + result.objectId = null; + } + + if (groupValues) { + result.objectId = {}; + + for (const key in groupValues) { + result.objectId[key] = result[key]; + delete result[key]; + } + } + + if (countField) { + result[countField] = parseInt(result[countField], 10); + } + }); + return results; + }); + } + + performInitialization({ + VolatileClassesSchemas + }) { + // TODO: This method needs to be rewritten to make proper use of connections (@vitaly-t) + debug('performInitialization'); + const promises = VolatileClassesSchemas.map(schema => { + return this.createTable(schema.className, schema).catch(err => { + if (err.code === PostgresDuplicateRelationError || err.code === _node.default.Error.INVALID_CLASS_NAME) { + return Promise.resolve(); + } + + throw err; + }).then(() => this.schemaUpgrade(schema.className, schema)); + }); + return Promise.all(promises).then(() => { + return this._client.tx('perform-initialization', t => { + return t.batch([t.none(_sql.default.misc.jsonObjectSetKeys), t.none(_sql.default.array.add), t.none(_sql.default.array.addUnique), t.none(_sql.default.array.remove), t.none(_sql.default.array.containsAll), t.none(_sql.default.array.containsAllRegex), t.none(_sql.default.array.contains)]); + }); + }).then(data => { + debug(`initializationDone in ${data.duration}`); + }).catch(error => { + /* eslint-disable no-console */ + console.error(error); + }); + } + + createIndexes(className, indexes, conn) { + return (conn || this._client).tx(t => t.batch(indexes.map(i => { + return t.none('CREATE INDEX $1:name ON $2:name ($3:name)', [i.name, className, i.key]); + }))); + } + + createIndexesIfNeeded(className, fieldName, type, conn) { + return (conn || this._client).none('CREATE INDEX $1:name ON $2:name ($3:name)', [fieldName, className, type]); + } + + dropIndexes(className, indexes, conn) { + const queries = indexes.map(i => ({ + query: 'DROP INDEX $1:name', + values: i + })); + return (conn || this._client).tx(t => t.none(this._pgp.helpers.concat(queries))); + } + + getIndexes(className) { + const qs = 'SELECT * FROM pg_indexes WHERE tablename = ${className}'; + return this._client.any(qs, { + className + }); + } + + updateSchemaWithIndexes() { + return Promise.resolve(); + } // Used for testing purposes + + + updateEstimatedCount(className) { + return this._client.none('ANALYZE $1:name', [className]); + } + + createTransactionalSession() { + return new Promise(resolve => { + const transactionalSession = {}; + transactionalSession.result = this._client.tx(t => { + transactionalSession.t = t; + transactionalSession.promise = new Promise(resolve => { + transactionalSession.resolve = resolve; + }); + transactionalSession.batch = []; + resolve(transactionalSession); + return transactionalSession.promise; + }); + }); + } + + commitTransactionalSession(transactionalSession) { + transactionalSession.resolve(transactionalSession.t.batch(transactionalSession.batch)); + return transactionalSession.result; + } + + abortTransactionalSession(transactionalSession) { + const result = transactionalSession.result.catch(); + transactionalSession.batch.push(Promise.reject()); + transactionalSession.resolve(transactionalSession.t.batch(transactionalSession.batch)); + return result; + } + +} + +exports.PostgresStorageAdapter = PostgresStorageAdapter; + +function convertPolygonToSQL(polygon) { + if (polygon.length < 3) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, `Polygon must have at least 3 values`); + } + + if (polygon[0][0] !== polygon[polygon.length - 1][0] || polygon[0][1] !== polygon[polygon.length - 1][1]) { + polygon.push(polygon[0]); + } + + const unique = polygon.filter((item, index, ar) => { + let foundIndex = -1; + + for (let i = 0; i < ar.length; i += 1) { + const pt = ar[i]; + + if (pt[0] === item[0] && pt[1] === item[1]) { + foundIndex = i; + break; + } + } + + return foundIndex === index; + }); + + if (unique.length < 3) { + throw new _node.default.Error(_node.default.Error.INTERNAL_SERVER_ERROR, 'GeoJSON: Loop must have at least 3 different vertices'); + } + + const points = polygon.map(point => { + _node.default.GeoPoint._validate(parseFloat(point[1]), parseFloat(point[0])); + + return `(${point[1]}, ${point[0]})`; + }).join(', '); + return `(${points})`; +} + +function removeWhiteSpace(regex) { + if (!regex.endsWith('\n')) { + regex += '\n'; + } // remove non escaped comments + + + return regex.replace(/([^\\])#.*\n/gim, '$1') // remove lines starting with a comment + .replace(/^#.*\n/gim, '') // remove non escaped whitespace + .replace(/([^\\])\s+/gim, '$1') // remove whitespace at the beginning of a line + .replace(/^\s+/, '').trim(); +} + +function processRegexPattern(s) { + if (s && s.startsWith('^')) { + // regex for startsWith + return '^' + literalizeRegexPart(s.slice(1)); + } else if (s && s.endsWith('$')) { + // regex for endsWith + return literalizeRegexPart(s.slice(0, s.length - 1)) + '$'; + } // regex for contains + + + return literalizeRegexPart(s); +} + +function isStartsWithRegex(value) { + if (!value || typeof value !== 'string' || !value.startsWith('^')) { + return false; + } + + const matches = value.match(/\^\\Q.*\\E/); + return !!matches; +} + +function isAllValuesRegexOrNone(values) { + if (!values || !Array.isArray(values) || values.length === 0) { + return true; + } + + const firstValuesIsRegex = isStartsWithRegex(values[0].$regex); + + if (values.length === 1) { + return firstValuesIsRegex; + } + + for (let i = 1, length = values.length; i < length; ++i) { + if (firstValuesIsRegex !== isStartsWithRegex(values[i].$regex)) { + return false; + } + } + + return true; +} + +function isAnyValueRegexStartsWith(values) { + return values.some(function (value) { + return isStartsWithRegex(value.$regex); + }); +} + +function createLiteralRegex(remaining) { + return remaining.split('').map(c => { + const regex = RegExp('[0-9 ]|\\p{L}', 'u'); // Support all unicode letter chars + + if (c.match(regex) !== null) { + // don't escape alphanumeric characters + return c; + } // escape everything else (single quotes with single quotes, everything else with a backslash) + + + return c === `'` ? `''` : `\\${c}`; + }).join(''); +} + +function literalizeRegexPart(s) { + const matcher1 = /\\Q((?!\\E).*)\\E$/; + const result1 = s.match(matcher1); + + if (result1 && result1.length > 1 && result1.index > -1) { + // process regex that has a beginning and an end specified for the literal text + const prefix = s.substr(0, result1.index); + const remaining = result1[1]; + return literalizeRegexPart(prefix) + createLiteralRegex(remaining); + } // process regex that has a beginning specified for the literal text + + + const matcher2 = /\\Q((?!\\E).*)$/; + const result2 = s.match(matcher2); + + if (result2 && result2.length > 1 && result2.index > -1) { + const prefix = s.substr(0, result2.index); + const remaining = result2[1]; + return literalizeRegexPart(prefix) + createLiteralRegex(remaining); + } // remove all instances of \Q and \E from the remaining text & escape single quotes + + + return s.replace(/([^\\])(\\E)/, '$1').replace(/([^\\])(\\Q)/, '$1').replace(/^\\E/, '').replace(/^\\Q/, '').replace(/([^'])'/, `$1''`).replace(/^'([^'])/, `''$1`); +} + +var GeoPointCoder = { + isValidJSON(value) { + return typeof value === 'object' && value !== null && value.__type === 'GeoPoint'; + } + +}; +var _default = PostgresStorageAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsiUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVDb2x1bW5FcnJvciIsIlBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVPYmplY3RFcnJvciIsIlBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciIsIlBvc3RncmVzVHJhbnNhY3Rpb25BYm9ydGVkRXJyb3IiLCJsb2dnZXIiLCJyZXF1aXJlIiwiZGVidWciLCJhcmdzIiwiYXJndW1lbnRzIiwiY29uY2F0Iiwic2xpY2UiLCJsZW5ndGgiLCJsb2ciLCJnZXRMb2dnZXIiLCJhcHBseSIsInBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlIiwidHlwZSIsImNvbnRlbnRzIiwiSlNPTiIsInN0cmluZ2lmeSIsIlBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvciIsIiRndCIsIiRsdCIsIiRndGUiLCIkbHRlIiwibW9uZ29BZ2dyZWdhdGVUb1Bvc3RncmVzIiwiJGRheU9mTW9udGgiLCIkZGF5T2ZXZWVrIiwiJGRheU9mWWVhciIsIiRpc29EYXlPZldlZWsiLCIkaXNvV2Vla1llYXIiLCIkaG91ciIsIiRtaW51dGUiLCIkc2Vjb25kIiwiJG1pbGxpc2Vjb25kIiwiJG1vbnRoIiwiJHdlZWsiLCIkeWVhciIsInRvUG9zdGdyZXNWYWx1ZSIsInZhbHVlIiwiX190eXBlIiwiaXNvIiwibmFtZSIsInRyYW5zZm9ybVZhbHVlIiwib2JqZWN0SWQiLCJlbXB0eUNMUFMiLCJPYmplY3QiLCJmcmVlemUiLCJmaW5kIiwiZ2V0IiwiY291bnQiLCJjcmVhdGUiLCJ1cGRhdGUiLCJkZWxldGUiLCJhZGRGaWVsZCIsInByb3RlY3RlZEZpZWxkcyIsImRlZmF1bHRDTFBTIiwidG9QYXJzZVNjaGVtYSIsInNjaGVtYSIsImNsYXNzTmFtZSIsImZpZWxkcyIsIl9oYXNoZWRfcGFzc3dvcmQiLCJfd3Blcm0iLCJfcnBlcm0iLCJjbHBzIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsInRvUG9zdGdyZXNTY2hlbWEiLCJfcGFzc3dvcmRfaGlzdG9yeSIsImhhbmRsZURvdEZpZWxkcyIsIm9iamVjdCIsImtleXMiLCJmb3JFYWNoIiwiZmllbGROYW1lIiwiaW5kZXhPZiIsImNvbXBvbmVudHMiLCJzcGxpdCIsImZpcnN0Iiwic2hpZnQiLCJjdXJyZW50T2JqIiwibmV4dCIsIl9fb3AiLCJ1bmRlZmluZWQiLCJ0cmFuc2Zvcm1Eb3RGaWVsZFRvQ29tcG9uZW50cyIsIm1hcCIsImNtcHQiLCJpbmRleCIsInRyYW5zZm9ybURvdEZpZWxkIiwiam9pbiIsInRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkIiwic3Vic3RyIiwidmFsaWRhdGVLZXlzIiwia2V5IiwiaW5jbHVkZXMiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9ORVNURURfS0VZIiwiam9pblRhYmxlc0ZvclNjaGVtYSIsImxpc3QiLCJmaWVsZCIsInB1c2giLCJidWlsZFdoZXJlQ2xhdXNlIiwicXVlcnkiLCJwYXR0ZXJucyIsInZhbHVlcyIsInNvcnRzIiwiaXNBcnJheUZpZWxkIiwiaW5pdGlhbFBhdHRlcm5zTGVuZ3RoIiwiZmllbGRWYWx1ZSIsIiRleGlzdHMiLCIkaW4iLCIkcmVnZXgiLCJNQVhfSU5UX1BMVVNfT05FIiwiY2xhdXNlcyIsImNsYXVzZVZhbHVlcyIsInN1YlF1ZXJ5IiwiY2xhdXNlIiwicGF0dGVybiIsIm9yT3JBbmQiLCJub3QiLCIkbmUiLCJjb25zdHJhaW50RmllbGROYW1lIiwicG9pbnQiLCJsb25naXR1ZGUiLCJsYXRpdHVkZSIsIiRlcSIsImlzSW5Pck5pbiIsIkFycmF5IiwiaXNBcnJheSIsIiRuaW4iLCJpblBhdHRlcm5zIiwiYWxsb3dOdWxsIiwibGlzdEVsZW0iLCJsaXN0SW5kZXgiLCJjcmVhdGVDb25zdHJhaW50IiwiYmFzZUFycmF5Iiwibm90SW4iLCJfIiwiZmxhdE1hcCIsImVsdCIsIklOVkFMSURfSlNPTiIsIiRhbGwiLCJpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoIiwiaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSIsImkiLCJwcm9jZXNzUmVnZXhQYXR0ZXJuIiwic3Vic3RyaW5nIiwiJGNvbnRhaW5lZEJ5IiwiYXJyIiwiJHRleHQiLCJzZWFyY2giLCIkc2VhcmNoIiwibGFuZ3VhZ2UiLCIkdGVybSIsIiRsYW5ndWFnZSIsIiRjYXNlU2Vuc2l0aXZlIiwiJGRpYWNyaXRpY1NlbnNpdGl2ZSIsIiRuZWFyU3BoZXJlIiwiZGlzdGFuY2UiLCIkbWF4RGlzdGFuY2UiLCJkaXN0YW5jZUluS00iLCIkd2l0aGluIiwiJGJveCIsImJveCIsImxlZnQiLCJib3R0b20iLCJyaWdodCIsInRvcCIsIiRnZW9XaXRoaW4iLCIkY2VudGVyU3BoZXJlIiwiY2VudGVyU3BoZXJlIiwiR2VvUG9pbnQiLCJHZW9Qb2ludENvZGVyIiwiaXNWYWxpZEpTT04iLCJfdmFsaWRhdGUiLCJpc05hTiIsIiRwb2x5Z29uIiwicG9seWdvbiIsInBvaW50cyIsImNvb3JkaW5hdGVzIiwiJGdlb0ludGVyc2VjdHMiLCIkcG9pbnQiLCJyZWdleCIsIm9wZXJhdG9yIiwib3B0cyIsIiRvcHRpb25zIiwicmVtb3ZlV2hpdGVTcGFjZSIsImNvbnZlcnRQb2x5Z29uVG9TUUwiLCJjbXAiLCJwZ0NvbXBhcmF0b3IiLCJwb3N0Z3Jlc1ZhbHVlIiwiY2FzdFR5cGUiLCJPUEVSQVRJT05fRk9SQklEREVOIiwiUG9zdGdyZXNTdG9yYWdlQWRhcHRlciIsImNvbnN0cnVjdG9yIiwidXJpIiwiY29sbGVjdGlvblByZWZpeCIsImRhdGFiYXNlT3B0aW9ucyIsIl9jb2xsZWN0aW9uUHJlZml4IiwiY2xpZW50IiwicGdwIiwiX2NsaWVudCIsIl9wZ3AiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiaGFuZGxlU2h1dGRvd24iLCIkcG9vbCIsImVuZCIsIl9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzIiwiY29ubiIsIm5vbmUiLCJjYXRjaCIsImVycm9yIiwiY29kZSIsImNsYXNzRXhpc3RzIiwib25lIiwiYSIsImV4aXN0cyIsInNldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsIkNMUHMiLCJzZWxmIiwidGFzayIsInQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsIl9pZF8iLCJfaWQiLCJkZWxldGVkSW5kZXhlcyIsImluc2VydGVkSW5kZXhlcyIsIklOVkFMSURfUVVFUlkiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJ0eCIsImNyZWF0ZUluZGV4ZXMiLCJkcm9wSW5kZXhlcyIsImNyZWF0ZUNsYXNzIiwicTEiLCJjcmVhdGVUYWJsZSIsInEyIiwicTMiLCJiYXRjaCIsInRoZW4iLCJlcnIiLCJkYXRhIiwicmVzdWx0IiwiZGV0YWlsIiwiRFVQTElDQVRFX1ZBTFVFIiwidmFsdWVzQXJyYXkiLCJwYXR0ZXJuc0FycmF5IiwiYXNzaWduIiwiX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0IiwiX2VtYWlsX3ZlcmlmeV90b2tlbiIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIl9mYWlsZWRfbG9naW5fY291bnQiLCJfcGVyaXNoYWJsZV90b2tlbiIsIl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQiLCJfcGFzc3dvcmRfY2hhbmdlZF9hdCIsInJlbGF0aW9ucyIsInBhcnNlVHlwZSIsInFzIiwiam9pblRhYmxlIiwic2NoZW1hVXBncmFkZSIsImNvbHVtbnMiLCJjb2x1bW5fbmFtZSIsIm5ld0NvbHVtbnMiLCJmaWx0ZXIiLCJpdGVtIiwiYWRkRmllbGRJZk5vdEV4aXN0cyIsInBvc3RncmVzVHlwZSIsImFueSIsInBhdGgiLCJkZWxldGVDbGFzcyIsIm9wZXJhdGlvbnMiLCJoZWxwZXJzIiwiZGVsZXRlQWxsQ2xhc3NlcyIsIm5vdyIsIkRhdGUiLCJnZXRUaW1lIiwicmVzdWx0cyIsImpvaW5zIiwicmVkdWNlIiwiY2xhc3NlcyIsInF1ZXJpZXMiLCJkZWxldGVGaWVsZHMiLCJmaWVsZE5hbWVzIiwiaWR4IiwiZ2V0QWxsQ2xhc3NlcyIsInJvdyIsImdldENsYXNzIiwiY3JlYXRlT2JqZWN0IiwidHJhbnNhY3Rpb25hbFNlc3Npb24iLCJjb2x1bW5zQXJyYXkiLCJnZW9Qb2ludHMiLCJhdXRoRGF0YU1hdGNoIiwibWF0Y2giLCJwcm92aWRlciIsInBvcCIsImluaXRpYWxWYWx1ZXMiLCJ2YWwiLCJ0ZXJtaW5hdGlvbiIsImdlb1BvaW50c0luamVjdHMiLCJsIiwiY29sdW1uc1BhdHRlcm4iLCJjb2wiLCJ2YWx1ZXNQYXR0ZXJuIiwicHJvbWlzZSIsIm9wcyIsInVuZGVybHlpbmdFcnJvciIsImNvbnN0cmFpbnQiLCJtYXRjaGVzIiwidXNlckluZm8iLCJkdXBsaWNhdGVkX2ZpZWxkIiwiZGVsZXRlT2JqZWN0c0J5UXVlcnkiLCJ3aGVyZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJmaW5kT25lQW5kVXBkYXRlIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cGRhdGVQYXR0ZXJucyIsIm9yaWdpbmFsVXBkYXRlIiwiZG90Tm90YXRpb25PcHRpb25zIiwiZ2VuZXJhdGUiLCJqc29uYiIsImxhc3RLZXkiLCJmaWVsZE5hbWVJbmRleCIsInN0ciIsImFtb3VudCIsIm9iamVjdHMiLCJrZXlzVG9JbmNyZW1lbnQiLCJrIiwiaW5jcmVtZW50UGF0dGVybnMiLCJjIiwia2V5c1RvRGVsZXRlIiwiZGVsZXRlUGF0dGVybnMiLCJwIiwidXBkYXRlT2JqZWN0IiwiZXhwZWN0ZWRUeXBlIiwicmVqZWN0Iiwid2hlcmVDbGF1c2UiLCJ1cHNlcnRPbmVPYmplY3QiLCJjcmVhdGVWYWx1ZSIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJoYXNMaW1pdCIsImhhc1NraXAiLCJ3aGVyZVBhdHRlcm4iLCJsaW1pdFBhdHRlcm4iLCJza2lwUGF0dGVybiIsInNvcnRQYXR0ZXJuIiwic29ydENvcHkiLCJzb3J0aW5nIiwidHJhbnNmb3JtS2V5IiwibWVtbyIsInBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdCIsInRhcmdldENsYXNzIiwieSIsIngiLCJjb29yZHMiLCJwYXJzZUZsb2F0IiwiY3JlYXRlZEF0IiwidG9JU09TdHJpbmciLCJ1cGRhdGVkQXQiLCJleHBpcmVzQXQiLCJlbnN1cmVVbmlxdWVuZXNzIiwiY29uc3RyYWludE5hbWUiLCJjb25zdHJhaW50UGF0dGVybnMiLCJtZXNzYWdlIiwicmVhZFByZWZlcmVuY2UiLCJlc3RpbWF0ZSIsImFwcHJveGltYXRlX3Jvd19jb3VudCIsImRpc3RpbmN0IiwiY29sdW1uIiwiaXNOZXN0ZWQiLCJpc1BvaW50ZXJGaWVsZCIsInRyYW5zZm9ybWVyIiwiY2hpbGQiLCJhZ2dyZWdhdGUiLCJwaXBlbGluZSIsImNvdW50RmllbGQiLCJncm91cFZhbHVlcyIsImdyb3VwUGF0dGVybiIsInN0YWdlIiwiJGdyb3VwIiwiZ3JvdXBCeUZpZWxkcyIsImFsaWFzIiwib3BlcmF0aW9uIiwic291cmNlIiwiJHN1bSIsIiRtYXgiLCIkbWluIiwiJGF2ZyIsIiRwcm9qZWN0IiwiJG1hdGNoIiwiJG9yIiwiY29sbGFwc2UiLCJlbGVtZW50IiwibWF0Y2hQYXR0ZXJucyIsIiRsaW1pdCIsIiRza2lwIiwiJHNvcnQiLCJvcmRlciIsInBhcnNlSW50IiwicGVyZm9ybUluaXRpYWxpemF0aW9uIiwiVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyIsInByb21pc2VzIiwiSU5WQUxJRF9DTEFTU19OQU1FIiwiYWxsIiwic3FsIiwibWlzYyIsImpzb25PYmplY3RTZXRLZXlzIiwiYXJyYXkiLCJhZGQiLCJhZGRVbmlxdWUiLCJyZW1vdmUiLCJjb250YWluc0FsbCIsImNvbnRhaW5zQWxsUmVnZXgiLCJjb250YWlucyIsImR1cmF0aW9uIiwiY29uc29sZSIsImNyZWF0ZUluZGV4ZXNJZk5lZWRlZCIsImdldEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsInVwZGF0ZUVzdGltYXRlZENvdW50IiwiY3JlYXRlVHJhbnNhY3Rpb25hbFNlc3Npb24iLCJjb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbiIsImFib3J0VHJhbnNhY3Rpb25hbFNlc3Npb24iLCJ1bmlxdWUiLCJhciIsImZvdW5kSW5kZXgiLCJwdCIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImVuZHNXaXRoIiwicmVwbGFjZSIsInRyaW0iLCJzIiwic3RhcnRzV2l0aCIsImxpdGVyYWxpemVSZWdleFBhcnQiLCJpc1N0YXJ0c1dpdGhSZWdleCIsImZpcnN0VmFsdWVzSXNSZWdleCIsInNvbWUiLCJjcmVhdGVMaXRlcmFsUmVnZXgiLCJyZW1haW5pbmciLCJSZWdFeHAiLCJtYXRjaGVyMSIsInJlc3VsdDEiLCJwcmVmaXgiLCJtYXRjaGVyMiIsInJlc3VsdDIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTs7QUFFQTs7QUFFQTs7QUFDQTs7QUFpQkE7Ozs7Ozs7Ozs7QUFmQSxNQUFNQSxpQ0FBaUMsR0FBRyxPQUExQztBQUNBLE1BQU1DLDhCQUE4QixHQUFHLE9BQXZDO0FBQ0EsTUFBTUMsNEJBQTRCLEdBQUcsT0FBckM7QUFDQSxNQUFNQywwQkFBMEIsR0FBRyxPQUFuQztBQUNBLE1BQU1DLDRCQUE0QixHQUFHLE9BQXJDO0FBQ0EsTUFBTUMsaUNBQWlDLEdBQUcsT0FBMUM7QUFDQSxNQUFNQywrQkFBK0IsR0FBRyxPQUF4Qzs7QUFDQSxNQUFNQyxNQUFNLEdBQUdDLE9BQU8sQ0FBQyxpQkFBRCxDQUF0Qjs7QUFFQSxNQUFNQyxLQUFLLEdBQUcsVUFBUyxHQUFHQyxJQUFaLEVBQXVCO0FBQ25DQSxFQUFBQSxJQUFJLEdBQUcsQ0FBQyxTQUFTQyxTQUFTLENBQUMsQ0FBRCxDQUFuQixFQUF3QkMsTUFBeEIsQ0FBK0JGLElBQUksQ0FBQ0csS0FBTCxDQUFXLENBQVgsRUFBY0gsSUFBSSxDQUFDSSxN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QyxTQUFELENBQXZEO0FBQ0QsR0FUcUMsQ0FXdEM7OztBQUNBLFFBQU1LLFFBQVEsR0FBRyxpQkFBakI7QUFDQSxRQUFNQyxPQUFZLEdBQUdiLENBQUMsQ0FBQzVJLEtBQUYsQ0FBUXdKLFFBQVIsQ0FBckI7O0FBQ0EsTUFBSUMsT0FBTyxJQUFJQSxPQUFPLENBQUN2YixNQUFSLEdBQWlCLENBQTVCLElBQWlDdWIsT0FBTyxDQUFDNVcsS0FBUixHQUFnQixDQUFDLENBQXRELEVBQXlEO0FBQ3ZELFVBQU0wVyxNQUFNLEdBQUdYLENBQUMsQ0FBQzNWLE1BQUYsQ0FBUyxDQUFULEVBQVl3VyxPQUFPLENBQUM1VyxLQUFwQixDQUFmO0FBQ0EsVUFBTXNXLFNBQVMsR0FBR00sT0FBTyxDQUFDLENBQUQsQ0FBekI7QUFFQSxXQUFPWCxtQkFBbUIsQ0FBQ1MsTUFBRCxDQUFuQixHQUE4Qkwsa0JBQWtCLENBQUNDLFNBQUQsQ0FBdkQ7QUFDRCxHQW5CcUMsQ0FxQnRDOzs7QUFDQSxTQUFPUCxDQUFDLENBQ0xGLE9BREksQ0FDSSxjQURKLEVBQ29CLElBRHBCLEVBRUpBLE9BRkksQ0FFSSxjQUZKLEVBRW9CLElBRnBCLEVBR0pBLE9BSEksQ0FHSSxNQUhKLEVBR1ksRUFIWixFQUlKQSxPQUpJLENBSUksTUFKSixFQUlZLEVBSlosRUFLSkEsT0FMSSxDQUtJLFNBTEosRUFLZ0IsTUFMaEIsRUFNSkEsT0FOSSxDQU1JLFVBTkosRUFNaUIsTUFOakIsQ0FBUDtBQU9EOztBQUVELElBQUl2USxhQUFhLEdBQUc7QUFDbEJDLEVBQUFBLFdBQVcsQ0FBQ3RJLEtBQUQsRUFBUTtBQUNqQixXQUNFLE9BQU9BLEtBQVAsS0FBaUIsUUFBakIsSUFBNkJBLEtBQUssS0FBSyxJQUF2QyxJQUErQ0EsS0FBSyxDQUFDQyxNQUFOLEtBQWlCLFVBRGxFO0FBR0Q7O0FBTGlCLENBQXBCO2VBUWV5SixzQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG5pbXBvcnQgeyBjcmVhdGVDbGllbnQgfSBmcm9tICcuL1Bvc3RncmVzQ2xpZW50Jztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHNxbCBmcm9tICcuL3NxbCc7XG5cbmNvbnN0IFBvc3RncmVzUmVsYXRpb25Eb2VzTm90RXhpc3RFcnJvciA9ICc0MlAwMSc7XG5jb25zdCBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IgPSAnNDJQMDcnO1xuY29uc3QgUG9zdGdyZXNEdXBsaWNhdGVDb2x1bW5FcnJvciA9ICc0MjcwMSc7XG5jb25zdCBQb3N0Z3Jlc01pc3NpbmdDb2x1bW5FcnJvciA9ICc0MjcwMyc7XG5jb25zdCBQb3N0Z3Jlc0R1cGxpY2F0ZU9iamVjdEVycm9yID0gJzQyNzEwJztcbmNvbnN0IFBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciA9ICcyMzUwNSc7XG5jb25zdCBQb3N0Z3Jlc1RyYW5zYWN0aW9uQWJvcnRlZEVycm9yID0gJzI1UDAyJztcbmNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJy4uLy4uLy4uL2xvZ2dlcicpO1xuXG5jb25zdCBkZWJ1ZyA9IGZ1bmN0aW9uKC4uLmFyZ3M6IGFueSkge1xuICBhcmdzID0gWydQRzogJyArIGFyZ3VtZW50c1swXV0uY29uY2F0KGFyZ3Muc2xpY2UoMSwgYXJncy5sZW5ndGgpKTtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmdldExvZ2dlcigpO1xuICBsb2cuZGVidWcuYXBwbHkobG9nLCBhcmdzKTtcbn07XG5cbmltcG9ydCB7IFN0b3JhZ2VBZGFwdGVyIH0gZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHR5cGUgeyBTY2hlbWFUeXBlLCBRdWVyeVR5cGUsIFF1ZXJ5T3B0aW9ucyB9IGZyb20gJy4uL1N0b3JhZ2VBZGFwdGVyJztcblxuY29uc3QgcGFyc2VUeXBlVG9Qb3N0Z3Jlc1R5cGUgPSB0eXBlID0+IHtcbiAgc3dpdGNoICh0eXBlLnR5cGUpIHtcbiAgICBjYXNlICdTdHJpbmcnOlxuICAgICAgcmV0dXJuICd0ZXh0JztcbiAgICBjYXNlICdEYXRlJzpcbiAgICAgIHJldHVybiAndGltZXN0YW1wIHdpdGggdGltZSB6b25lJztcbiAgICBjYXNlICdPYmplY3QnOlxuICAgICAgcmV0dXJuICdqc29uYic7XG4gICAgY2FzZSAnRmlsZSc6XG4gICAgICByZXR1cm4gJ3RleHQnO1xuICAgIGNhc2UgJ0Jvb2xlYW4nOlxuICAgICAgcmV0dXJuICdib29sZWFuJztcbiAgICBjYXNlICdQb2ludGVyJzpcbiAgICAgIHJldHVybiAnY2hhcigxMCknO1xuICAgIGNhc2UgJ051bWJlcic6XG4gICAgICByZXR1cm4gJ2RvdWJsZSBwcmVjaXNpb24nO1xuICAgIGNhc2UgJ0dlb1BvaW50JzpcbiAgICAgIHJldHVybiAncG9pbnQnO1xuICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgIHJldHVybiAnanNvbmInO1xuICAgIGNhc2UgJ1BvbHlnb24nOlxuICAgICAgcmV0dXJuICdwb2x5Z29uJztcbiAgICBjYXNlICdBcnJheSc6XG4gICAgICBpZiAodHlwZS5jb250ZW50cyAmJiB0eXBlLmNvbnRlbnRzLnR5cGUgPT09ICdTdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiAndGV4dFtdJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAnanNvbmInO1xuICAgICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBgbm8gdHlwZSBmb3IgJHtKU09OLnN0cmluZ2lmeSh0eXBlKX0geWV0YDtcbiAgfVxufTtcblxuY29uc3QgUGFyc2VUb1Bvc2dyZXNDb21wYXJhdG9yID0ge1xuICAkZ3Q6ICc+JyxcbiAgJGx0OiAnPCcsXG4gICRndGU6ICc+PScsXG4gICRsdGU6ICc8PScsXG59O1xuXG5jb25zdCBtb25nb0FnZ3JlZ2F0ZVRvUG9zdGdyZXMgPSB7XG4gICRkYXlPZk1vbnRoOiAnREFZJyxcbiAgJGRheU9mV2VlazogJ0RPVycsXG4gICRkYXlPZlllYXI6ICdET1knLFxuICAkaXNvRGF5T2ZXZWVrOiAnSVNPRE9XJyxcbiAgJGlzb1dlZWtZZWFyOiAnSVNPWUVBUicsXG4gICRob3VyOiAnSE9VUicsXG4gICRtaW51dGU6ICdNSU5VVEUnLFxuICAkc2Vjb25kOiAnU0VDT05EJyxcbiAgJG1pbGxpc2Vjb25kOiAnTUlMTElTRUNPTkRTJyxcbiAgJG1vbnRoOiAnTU9OVEgnLFxuICAkd2VlazogJ1dFRUsnLFxuICAkeWVhcjogJ1lFQVInLFxufTtcblxuY29uc3QgdG9Qb3N0Z3Jlc1ZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgIGlmICh2YWx1ZS5fX3R5cGUgPT09ICdEYXRlJykge1xuICAgICAgcmV0dXJuIHZhbHVlLmlzbztcbiAgICB9XG4gICAgaWYgKHZhbHVlLl9fdHlwZSA9PT0gJ0ZpbGUnKSB7XG4gICAgICByZXR1cm4gdmFsdWUubmFtZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuY29uc3QgdHJhbnNmb3JtVmFsdWUgPSB2YWx1ZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlLl9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgcmV0dXJuIHZhbHVlLm9iamVjdElkO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn07XG5cbi8vIER1cGxpY2F0ZSBmcm9tIHRoZW4gbW9uZ28gYWRhcHRlci4uLlxuY29uc3QgZW1wdHlDTFBTID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGZpbmQ6IHt9LFxuICBnZXQ6IHt9LFxuICBjb3VudDoge30sXG4gIGNyZWF0ZToge30sXG4gIHVwZGF0ZToge30sXG4gIGRlbGV0ZToge30sXG4gIGFkZEZpZWxkOiB7fSxcbiAgcHJvdGVjdGVkRmllbGRzOiB7fSxcbn0pO1xuXG5jb25zdCBkZWZhdWx0Q0xQUyA9IE9iamVjdC5mcmVlemUoe1xuICBmaW5kOiB7ICcqJzogdHJ1ZSB9LFxuICBnZXQ6IHsgJyonOiB0cnVlIH0sXG4gIGNvdW50OiB7ICcqJzogdHJ1ZSB9LFxuICBjcmVhdGU6IHsgJyonOiB0cnVlIH0sXG4gIHVwZGF0ZTogeyAnKic6IHRydWUgfSxcbiAgZGVsZXRlOiB7ICcqJzogdHJ1ZSB9LFxuICBhZGRGaWVsZDogeyAnKic6IHRydWUgfSxcbiAgcHJvdGVjdGVkRmllbGRzOiB7ICcqJzogW10gfSxcbn0pO1xuXG5jb25zdCB0b1BhcnNlU2NoZW1hID0gc2NoZW1hID0+IHtcbiAgaWYgKHNjaGVtYS5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkO1xuICB9XG4gIGlmIChzY2hlbWEuZmllbGRzKSB7XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3dwZXJtO1xuICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9ycGVybTtcbiAgfVxuICBsZXQgY2xwcyA9IGRlZmF1bHRDTFBTO1xuICBpZiAoc2NoZW1hLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucykge1xuICAgIGNscHMgPSB7IC4uLmVtcHR5Q0xQUywgLi4uc2NoZW1hLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucyB9O1xuICB9XG4gIGxldCBpbmRleGVzID0ge307XG4gIGlmIChzY2hlbWEuaW5kZXhlcykge1xuICAgIGluZGV4ZXMgPSB7IC4uLnNjaGVtYS5pbmRleGVzIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBjbGFzc05hbWU6IHNjaGVtYS5jbGFzc05hbWUsXG4gICAgZmllbGRzOiBzY2hlbWEuZmllbGRzLFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogY2xwcyxcbiAgICBpbmRleGVzLFxuICB9O1xufTtcblxuY29uc3QgdG9Qb3N0Z3Jlc1NjaGVtYSA9IHNjaGVtYSA9PiB7XG4gIGlmICghc2NoZW1hKSB7XG4gICAgcmV0dXJuIHNjaGVtYTtcbiAgfVxuICBzY2hlbWEuZmllbGRzID0gc2NoZW1hLmZpZWxkcyB8fCB7fTtcbiAgc2NoZW1hLmZpZWxkcy5fd3Blcm0gPSB7IHR5cGU6ICdBcnJheScsIGNvbnRlbnRzOiB7IHR5cGU6ICdTdHJpbmcnIH0gfTtcbiAgc2NoZW1hLmZpZWxkcy5fcnBlcm0gPSB7IHR5cGU6ICdBcnJheScsIGNvbnRlbnRzOiB7IHR5cGU6ICdTdHJpbmcnIH0gfTtcbiAgaWYgKHNjaGVtYS5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBzY2hlbWEuZmllbGRzLl9oYXNoZWRfcGFzc3dvcmQgPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gICAgc2NoZW1hLmZpZWxkcy5fcGFzc3dvcmRfaGlzdG9yeSA9IHsgdHlwZTogJ0FycmF5JyB9O1xuICB9XG4gIHJldHVybiBzY2hlbWE7XG59O1xuXG5jb25zdCBoYW5kbGVEb3RGaWVsZHMgPSBvYmplY3QgPT4ge1xuICBPYmplY3Qua2V5cyhvYmplY3QpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+IC0xKSB7XG4gICAgICBjb25zdCBjb21wb25lbnRzID0gZmllbGROYW1lLnNwbGl0KCcuJyk7XG4gICAgICBjb25zdCBmaXJzdCA9IGNvbXBvbmVudHMuc2hpZnQoKTtcbiAgICAgIG9iamVjdFtmaXJzdF0gPSBvYmplY3RbZmlyc3RdIHx8IHt9O1xuICAgICAgbGV0IGN1cnJlbnRPYmogPSBvYmplY3RbZmlyc3RdO1xuICAgICAgbGV0IG5leHQ7XG4gICAgICBsZXQgdmFsdWUgPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgIGlmICh2YWx1ZSAmJiB2YWx1ZS5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB2YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbmQtYXNzaWduICovXG4gICAgICB3aGlsZSAoKG5leHQgPSBjb21wb25lbnRzLnNoaWZ0KCkpKSB7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tY29uZC1hc3NpZ24gKi9cbiAgICAgICAgY3VycmVudE9ialtuZXh0XSA9IGN1cnJlbnRPYmpbbmV4dF0gfHwge307XG4gICAgICAgIGlmIChjb21wb25lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGN1cnJlbnRPYmpbbmV4dF0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50T2JqID0gY3VycmVudE9ialtuZXh0XTtcbiAgICAgIH1cbiAgICAgIGRlbGV0ZSBvYmplY3RbZmllbGROYW1lXTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gb2JqZWN0O1xufTtcblxuY29uc3QgdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMgPSBmaWVsZE5hbWUgPT4ge1xuICByZXR1cm4gZmllbGROYW1lLnNwbGl0KCcuJykubWFwKChjbXB0LCBpbmRleCkgPT4ge1xuICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGBcIiR7Y21wdH1cImA7XG4gICAgfVxuICAgIHJldHVybiBgJyR7Y21wdH0nYDtcbiAgfSk7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1Eb3RGaWVsZCA9IGZpZWxkTmFtZSA9PiB7XG4gIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID09PSAtMSkge1xuICAgIHJldHVybiBgXCIke2ZpZWxkTmFtZX1cImA7XG4gIH1cbiAgY29uc3QgY29tcG9uZW50cyA9IHRyYW5zZm9ybURvdEZpZWxkVG9Db21wb25lbnRzKGZpZWxkTmFtZSk7XG4gIGxldCBuYW1lID0gY29tcG9uZW50cy5zbGljZSgwLCBjb21wb25lbnRzLmxlbmd0aCAtIDEpLmpvaW4oJy0+Jyk7XG4gIG5hbWUgKz0gJy0+PicgKyBjb21wb25lbnRzW2NvbXBvbmVudHMubGVuZ3RoIC0gMV07XG4gIHJldHVybiBuYW1lO1xufTtcblxuY29uc3QgdHJhbnNmb3JtQWdncmVnYXRlRmllbGQgPSBmaWVsZE5hbWUgPT4ge1xuICBpZiAodHlwZW9mIGZpZWxkTmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZmllbGROYW1lO1xuICB9XG4gIGlmIChmaWVsZE5hbWUgPT09ICckX2NyZWF0ZWRfYXQnKSB7XG4gICAgcmV0dXJuICdjcmVhdGVkQXQnO1xuICB9XG4gIGlmIChmaWVsZE5hbWUgPT09ICckX3VwZGF0ZWRfYXQnKSB7XG4gICAgcmV0dXJuICd1cGRhdGVkQXQnO1xuICB9XG4gIHJldHVybiBmaWVsZE5hbWUuc3Vic3RyKDEpO1xufTtcblxuY29uc3QgdmFsaWRhdGVLZXlzID0gb2JqZWN0ID0+IHtcbiAgaWYgKHR5cGVvZiBvYmplY3QgPT0gJ29iamVjdCcpIHtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBvYmplY3QpIHtcbiAgICAgIGlmICh0eXBlb2Ygb2JqZWN0W2tleV0gPT0gJ29iamVjdCcpIHtcbiAgICAgICAgdmFsaWRhdGVLZXlzKG9iamVjdFtrZXldKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGtleS5pbmNsdWRlcygnJCcpIHx8IGtleS5pbmNsdWRlcygnLicpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX05FU1RFRF9LRVksXG4gICAgICAgICAgXCJOZXN0ZWQga2V5cyBzaG91bGQgbm90IGNvbnRhaW4gdGhlICckJyBvciAnLicgY2hhcmFjdGVyc1wiXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG4vLyBSZXR1cm5zIHRoZSBsaXN0IG9mIGpvaW4gdGFibGVzIG9uIGEgc2NoZW1hXG5jb25zdCBqb2luVGFibGVzRm9yU2NoZW1hID0gc2NoZW1hID0+IHtcbiAgY29uc3QgbGlzdCA9IFtdO1xuICBpZiAoc2NoZW1hKSB7XG4gICAgT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcykuZm9yRWFjaChmaWVsZCA9PiB7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgICBsaXN0LnB1c2goYF9Kb2luOiR7ZmllbGR9OiR7c2NoZW1hLmNsYXNzTmFtZX1gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gbGlzdDtcbn07XG5cbmludGVyZmFjZSBXaGVyZUNsYXVzZSB7XG4gIHBhdHRlcm46IHN0cmluZztcbiAgdmFsdWVzOiBBcnJheTxhbnk+O1xuICBzb3J0czogQXJyYXk8YW55Pjtcbn1cblxuY29uc3QgYnVpbGRXaGVyZUNsYXVzZSA9ICh7IHNjaGVtYSwgcXVlcnksIGluZGV4IH0pOiBXaGVyZUNsYXVzZSA9PiB7XG4gIGNvbnN0IHBhdHRlcm5zID0gW107XG4gIGxldCB2YWx1ZXMgPSBbXTtcbiAgY29uc3Qgc29ydHMgPSBbXTtcblxuICBzY2hlbWEgPSB0b1Bvc3RncmVzU2NoZW1hKHNjaGVtYSk7XG4gIGZvciAoY29uc3QgZmllbGROYW1lIGluIHF1ZXJ5KSB7XG4gICAgY29uc3QgaXNBcnJheUZpZWxkID1cbiAgICAgIHNjaGVtYS5maWVsZHMgJiZcbiAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdBcnJheSc7XG4gICAgY29uc3QgaW5pdGlhbFBhdHRlcm5zTGVuZ3RoID0gcGF0dGVybnMubGVuZ3RoO1xuICAgIGNvbnN0IGZpZWxkVmFsdWUgPSBxdWVyeVtmaWVsZE5hbWVdO1xuXG4gICAgLy8gbm90aGluZyBpbiB0aGUgc2NoZW1hLCBpdCdzIGdvbm5hIGJsb3cgdXBcbiAgICBpZiAoIXNjaGVtYS5maWVsZHNbZmllbGROYW1lXSkge1xuICAgICAgLy8gYXMgaXQgd29uJ3QgZXhpc3RcbiAgICAgIGlmIChmaWVsZFZhbHVlICYmIGZpZWxkVmFsdWUuJGV4aXN0cyA9PT0gZmFsc2UpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMCkge1xuICAgICAgbGV0IG5hbWUgPSB0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpO1xuICAgICAgaWYgKGZpZWxkVmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJHtuYW1lfSBJUyBOVUxMYCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZmllbGRWYWx1ZS4kaW4pIHtcbiAgICAgICAgICBuYW1lID0gdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMoZmllbGROYW1lKS5qb2luKCctPicpO1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCgkJHtpbmRleH06cmF3KTo6anNvbmIgQD4gJCR7aW5kZXggKyAxfTo6anNvbmJgKTtcbiAgICAgICAgICB2YWx1ZXMucHVzaChuYW1lLCBKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlLiRpbikpO1xuICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS4kcmVnZXgpIHtcbiAgICAgICAgICAvLyBIYW5kbGUgbGF0ZXJcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06cmF3ID0gJCR7aW5kZXggKyAxfTo6dGV4dGApO1xuICAgICAgICAgIHZhbHVlcy5wdXNoKG5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUgPT09IG51bGwgfHwgZmllbGRWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSBJUyBOVUxMYCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgaW5kZXggKz0gMTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAvLyBDYW4ndCBjYXN0IGJvb2xlYW4gdG8gZG91YmxlIHByZWNpc2lvblxuICAgICAgaWYgKFxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiZcbiAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdOdW1iZXInXG4gICAgICApIHtcbiAgICAgICAgLy8gU2hvdWxkIGFsd2F5cyByZXR1cm4gemVybyByZXN1bHRzXG4gICAgICAgIGNvbnN0IE1BWF9JTlRfUExVU19PTkUgPSA5MjIzMzcyMDM2ODU0Nzc1ODA4O1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIE1BWF9JTlRfUExVU19PTkUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfSBlbHNlIGlmIChbJyRvcicsICckbm9yJywgJyRhbmQnXS5pbmNsdWRlcyhmaWVsZE5hbWUpKSB7XG4gICAgICBjb25zdCBjbGF1c2VzID0gW107XG4gICAgICBjb25zdCBjbGF1c2VWYWx1ZXMgPSBbXTtcbiAgICAgIGZpZWxkVmFsdWUuZm9yRWFjaChzdWJRdWVyeSA9PiB7XG4gICAgICAgIGNvbnN0IGNsYXVzZSA9IGJ1aWxkV2hlcmVDbGF1c2UoeyBzY2hlbWEsIHF1ZXJ5OiBzdWJRdWVyeSwgaW5kZXggfSk7XG4gICAgICAgIGlmIChjbGF1c2UucGF0dGVybi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY2xhdXNlcy5wdXNoKGNsYXVzZS5wYXR0ZXJuKTtcbiAgICAgICAgICBjbGF1c2VWYWx1ZXMucHVzaCguLi5jbGF1c2UudmFsdWVzKTtcbiAgICAgICAgICBpbmRleCArPSBjbGF1c2UudmFsdWVzLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IG9yT3JBbmQgPSBmaWVsZE5hbWUgPT09ICckYW5kJyA/ICcgQU5EICcgOiAnIE9SICc7XG4gICAgICBjb25zdCBub3QgPSBmaWVsZE5hbWUgPT09ICckbm9yJyA/ICcgTk9UICcgOiAnJztcblxuICAgICAgcGF0dGVybnMucHVzaChgJHtub3R9KCR7Y2xhdXNlcy5qb2luKG9yT3JBbmQpfSlgKTtcbiAgICAgIHZhbHVlcy5wdXNoKC4uLmNsYXVzZVZhbHVlcyk7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJG5lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChpc0FycmF5RmllbGQpIHtcbiAgICAgICAgZmllbGRWYWx1ZS4kbmUgPSBKU09OLnN0cmluZ2lmeShbZmllbGRWYWx1ZS4kbmVdKTtcbiAgICAgICAgcGF0dGVybnMucHVzaChgTk9UIGFycmF5X2NvbnRhaW5zKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9KWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGZpZWxkVmFsdWUuJG5lID09PSBudWxsKSB7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgSVMgTk9UIE5VTExgKTtcbiAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gaWYgbm90IG51bGwsIHdlIG5lZWQgdG8gbWFudWFsbHkgZXhjbHVkZSBudWxsXG4gICAgICAgICAgaWYgKGZpZWxkVmFsdWUuJG5lLl9fdHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgICAgICAgYCgkJHtpbmRleH06bmFtZSA8PiBQT0lOVCgkJHtpbmRleCArIDF9LCAkJHtpbmRleCArXG4gICAgICAgICAgICAgICAgMn0pIE9SICQke2luZGV4fTpuYW1lIElTIE5VTEwpYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMCkge1xuICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50RmllbGROYW1lID0gdHJhbnNmb3JtRG90RmllbGQoZmllbGROYW1lKTtcbiAgICAgICAgICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgICAgICAgICBgKCR7Y29uc3RyYWludEZpZWxkTmFtZX0gPD4gJCR7aW5kZXh9IE9SICR7Y29uc3RyYWludEZpZWxkTmFtZX0gSVMgTlVMTClgXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgICAgICAgICAgIGAoJCR7aW5kZXh9Om5hbWUgPD4gJCR7aW5kZXggKyAxfSBPUiAkJHtpbmRleH06bmFtZSBJUyBOVUxMKWBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChmaWVsZFZhbHVlLiRuZS5fX3R5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgY29uc3QgcG9pbnQgPSBmaWVsZFZhbHVlLiRuZTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlKTtcbiAgICAgICAgaW5kZXggKz0gMztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRPRE86IHN1cHBvcnQgYXJyYXlzXG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS4kbmUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoZmllbGRWYWx1ZS4kZXEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGZpZWxkVmFsdWUuJGVxID09PSBudWxsKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5VTExgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDApIHtcbiAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZFZhbHVlLiRlcSk7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgJHt0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpfSA9ICQke2luZGV4Kyt9YCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLiRlcSk7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBpc0luT3JOaW4gPVxuICAgICAgQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlLiRpbikgfHwgQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlLiRuaW4pO1xuICAgIGlmIChcbiAgICAgIEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kaW4pICYmXG4gICAgICBpc0FycmF5RmllbGQgJiZcbiAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5jb250ZW50cyAmJlxuICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLmNvbnRlbnRzLnR5cGUgPT09ICdTdHJpbmcnXG4gICAgKSB7XG4gICAgICBjb25zdCBpblBhdHRlcm5zID0gW107XG4gICAgICBsZXQgYWxsb3dOdWxsID0gZmFsc2U7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgZmllbGRWYWx1ZS4kaW4uZm9yRWFjaCgobGlzdEVsZW0sIGxpc3RJbmRleCkgPT4ge1xuICAgICAgICBpZiAobGlzdEVsZW0gPT09IG51bGwpIHtcbiAgICAgICAgICBhbGxvd051bGwgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlcy5wdXNoKGxpc3RFbGVtKTtcbiAgICAgICAgICBpblBhdHRlcm5zLnB1c2goYCQke2luZGV4ICsgMSArIGxpc3RJbmRleCAtIChhbGxvd051bGwgPyAxIDogMCl9YCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgaWYgKGFsbG93TnVsbCkge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGAoJCR7aW5kZXh9Om5hbWUgSVMgTlVMTCBPUiAkJHtpbmRleH06bmFtZSAmJiBBUlJBWVske2luUGF0dGVybnMuam9pbigpfV0pYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgJiYgQVJSQVlbJHtpblBhdHRlcm5zLmpvaW4oKX1dYCk7XG4gICAgICB9XG4gICAgICBpbmRleCA9IGluZGV4ICsgMSArIGluUGF0dGVybnMubGVuZ3RoO1xuICAgIH0gZWxzZSBpZiAoaXNJbk9yTmluKSB7XG4gICAgICB2YXIgY3JlYXRlQ29uc3RyYWludCA9IChiYXNlQXJyYXksIG5vdEluKSA9PiB7XG4gICAgICAgIGNvbnN0IG5vdCA9IG5vdEluID8gJyBOT1QgJyA6ICcnO1xuICAgICAgICBpZiAoYmFzZUFycmF5Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgICAgICAgICBgJHtub3R9IGFycmF5X2NvbnRhaW5zKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9KWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGJhc2VBcnJheSkpO1xuICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSGFuZGxlIE5lc3RlZCBEb3QgTm90YXRpb24gQWJvdmVcbiAgICAgICAgICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDApIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaW5QYXR0ZXJucyA9IFtdO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICAgIGJhc2VBcnJheS5mb3JFYWNoKChsaXN0RWxlbSwgbGlzdEluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIGlmIChsaXN0RWxlbSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzLnB1c2gobGlzdEVsZW0pO1xuICAgICAgICAgICAgICAgIGluUGF0dGVybnMucHVzaChgJCR7aW5kZXggKyAxICsgbGlzdEluZGV4fWApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lICR7bm90fSBJTiAoJHtpblBhdHRlcm5zLmpvaW4oKX0pYCk7XG4gICAgICAgICAgICBpbmRleCA9IGluZGV4ICsgMSArIGluUGF0dGVybnMubGVuZ3RoO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICghbm90SW4pIHtcbiAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5VTExgKTtcbiAgICAgICAgICBpbmRleCA9IGluZGV4ICsgMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBIYW5kbGUgZW1wdHkgYXJyYXlcbiAgICAgICAgICBpZiAobm90SW4pIHtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goJzEgPSAxJyk7IC8vIFJldHVybiBhbGwgdmFsdWVzXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goJzEgPSAyJyk7IC8vIFJldHVybiBubyB2YWx1ZXNcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBpZiAoZmllbGRWYWx1ZS4kaW4pIHtcbiAgICAgICAgY3JlYXRlQ29uc3RyYWludChfLmZsYXRNYXAoZmllbGRWYWx1ZS4kaW4sIGVsdCA9PiBlbHQpLCBmYWxzZSk7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGRWYWx1ZS4kbmluKSB7XG4gICAgICAgIGNyZWF0ZUNvbnN0cmFpbnQoXy5mbGF0TWFwKGZpZWxkVmFsdWUuJG5pbiwgZWx0ID0+IGVsdCksIHRydWUpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUuJGluICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAkaW4gdmFsdWUnKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlLiRuaW4gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICRuaW4gdmFsdWUnKTtcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlLiRhbGwpICYmIGlzQXJyYXlGaWVsZCkge1xuICAgICAgaWYgKGlzQW55VmFsdWVSZWdleFN0YXJ0c1dpdGgoZmllbGRWYWx1ZS4kYWxsKSkge1xuICAgICAgICBpZiAoIWlzQWxsVmFsdWVzUmVnZXhPck5vbmUoZmllbGRWYWx1ZS4kYWxsKSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICdBbGwgJGFsbCB2YWx1ZXMgbXVzdCBiZSBvZiByZWdleCB0eXBlIG9yIG5vbmU6ICcgKyBmaWVsZFZhbHVlLiRhbGxcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaWVsZFZhbHVlLiRhbGwubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHByb2Nlc3NSZWdleFBhdHRlcm4oZmllbGRWYWx1ZS4kYWxsW2ldLiRyZWdleCk7XG4gICAgICAgICAgZmllbGRWYWx1ZS4kYWxsW2ldID0gdmFsdWUuc3Vic3RyaW5nKDEpICsgJyUnO1xuICAgICAgICB9XG4gICAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgYGFycmF5X2NvbnRhaW5zX2FsbF9yZWdleCgkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfTo6anNvbmIpYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgICBgYXJyYXlfY29udGFpbnNfYWxsKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9Ojpqc29uYilgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUuJGFsbCkpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kYWxsKSkge1xuICAgICAgaWYgKGZpZWxkVmFsdWUuJGFsbC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS4kYWxsWzBdLm9iamVjdElkKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGZpZWxkVmFsdWUuJGV4aXN0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmIChmaWVsZFZhbHVlLiRleGlzdHMpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgSVMgTk9UIE5VTExgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5VTExgKTtcbiAgICAgIH1cbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBpbmRleCArPSAxO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRjb250YWluZWRCeSkge1xuICAgICAgY29uc3QgYXJyID0gZmllbGRWYWx1ZS4kY29udGFpbmVkQnk7XG4gICAgICBpZiAoIShhcnIgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICRjb250YWluZWRCeTogc2hvdWxkIGJlIGFuIGFycmF5YFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA8QCAkJHtpbmRleCArIDF9Ojpqc29uYmApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShhcnIpKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJHRleHQpIHtcbiAgICAgIGNvbnN0IHNlYXJjaCA9IGZpZWxkVmFsdWUuJHRleHQuJHNlYXJjaDtcbiAgICAgIGxldCBsYW5ndWFnZSA9ICdlbmdsaXNoJztcbiAgICAgIGlmICh0eXBlb2Ygc2VhcmNoICE9PSAnb2JqZWN0Jykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRzZWFyY2gsIHNob3VsZCBiZSBvYmplY3RgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIXNlYXJjaC4kdGVybSB8fCB0eXBlb2Ygc2VhcmNoLiR0ZXJtICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICR0ZXJtLCBzaG91bGQgYmUgc3RyaW5nYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKHNlYXJjaC4kbGFuZ3VhZ2UgJiYgdHlwZW9mIHNlYXJjaC4kbGFuZ3VhZ2UgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGxhbmd1YWdlLCBzaG91bGQgYmUgc3RyaW5nYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGxhbmd1YWdlKSB7XG4gICAgICAgIGxhbmd1YWdlID0gc2VhcmNoLiRsYW5ndWFnZTtcbiAgICAgIH1cbiAgICAgIGlmIChzZWFyY2guJGNhc2VTZW5zaXRpdmUgJiYgdHlwZW9mIHNlYXJjaC4kY2FzZVNlbnNpdGl2ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGNhc2VTZW5zaXRpdmUsIHNob3VsZCBiZSBib29sZWFuYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGNhc2VTZW5zaXRpdmUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkY2FzZVNlbnNpdGl2ZSBub3Qgc3VwcG9ydGVkLCBwbGVhc2UgdXNlICRyZWdleCBvciBjcmVhdGUgYSBzZXBhcmF0ZSBsb3dlciBjYXNlIGNvbHVtbi5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlICYmXG4gICAgICAgIHR5cGVvZiBzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZSAhPT0gJ2Jvb2xlYW4nXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkZGlhY3JpdGljU2Vuc2l0aXZlLCBzaG91bGQgYmUgYm9vbGVhbmBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VhcmNoLiRkaWFjcml0aWNTZW5zaXRpdmUgPT09IGZhbHNlKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGRpYWNyaXRpY1NlbnNpdGl2ZSAtIGZhbHNlIG5vdCBzdXBwb3J0ZWQsIGluc3RhbGwgUG9zdGdyZXMgVW5hY2NlbnQgRXh0ZW5zaW9uYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgYHRvX3RzdmVjdG9yKCQke2luZGV4fSwgJCR7aW5kZXggKyAxfTpuYW1lKSBAQCB0b190c3F1ZXJ5KCQke2luZGV4ICtcbiAgICAgICAgICAyfSwgJCR7aW5kZXggKyAzfSlgXG4gICAgICApO1xuICAgICAgdmFsdWVzLnB1c2gobGFuZ3VhZ2UsIGZpZWxkTmFtZSwgbGFuZ3VhZ2UsIHNlYXJjaC4kdGVybSk7XG4gICAgICBpbmRleCArPSA0O1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRuZWFyU3BoZXJlKSB7XG4gICAgICBjb25zdCBwb2ludCA9IGZpZWxkVmFsdWUuJG5lYXJTcGhlcmU7XG4gICAgICBjb25zdCBkaXN0YW5jZSA9IGZpZWxkVmFsdWUuJG1heERpc3RhbmNlO1xuICAgICAgY29uc3QgZGlzdGFuY2VJbktNID0gZGlzdGFuY2UgKiA2MzcxICogMTAwMDtcbiAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgIGBTVF9kaXN0YW5jZV9zcGhlcmUoJCR7aW5kZXh9Om5hbWU6Omdlb21ldHJ5LCBQT0lOVCgkJHtpbmRleCArXG4gICAgICAgICAgMX0sICQke2luZGV4ICsgMn0pOjpnZW9tZXRyeSkgPD0gJCR7aW5kZXggKyAzfWBcbiAgICAgICk7XG4gICAgICBzb3J0cy5wdXNoKFxuICAgICAgICBgU1RfZGlzdGFuY2Vfc3BoZXJlKCQke2luZGV4fTpuYW1lOjpnZW9tZXRyeSwgUE9JTlQoJCR7aW5kZXggK1xuICAgICAgICAgIDF9LCAkJHtpbmRleCArIDJ9KTo6Z2VvbWV0cnkpIEFTQ2BcbiAgICAgICk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHBvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGUsIGRpc3RhbmNlSW5LTSk7XG4gICAgICBpbmRleCArPSA0O1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiR3aXRoaW4gJiYgZmllbGRWYWx1ZS4kd2l0aGluLiRib3gpIHtcbiAgICAgIGNvbnN0IGJveCA9IGZpZWxkVmFsdWUuJHdpdGhpbi4kYm94O1xuICAgICAgY29uc3QgbGVmdCA9IGJveFswXS5sb25naXR1ZGU7XG4gICAgICBjb25zdCBib3R0b20gPSBib3hbMF0ubGF0aXR1ZGU7XG4gICAgICBjb25zdCByaWdodCA9IGJveFsxXS5sb25naXR1ZGU7XG4gICAgICBjb25zdCB0b3AgPSBib3hbMV0ubGF0aXR1ZGU7XG5cbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lOjpwb2ludCA8QCAkJHtpbmRleCArIDF9Ojpib3hgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgYCgoJHtsZWZ0fSwgJHtib3R0b219KSwgKCR7cmlnaHR9LCAke3RvcH0pKWApO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kZ2VvV2l0aGluICYmIGZpZWxkVmFsdWUuJGdlb1dpdGhpbi4kY2VudGVyU3BoZXJlKSB7XG4gICAgICBjb25zdCBjZW50ZXJTcGhlcmUgPSBmaWVsZFZhbHVlLiRnZW9XaXRoaW4uJGNlbnRlclNwaGVyZTtcbiAgICAgIGlmICghKGNlbnRlclNwaGVyZSBpbnN0YW5jZW9mIEFycmF5KSB8fCBjZW50ZXJTcGhlcmUubGVuZ3RoIDwgMikge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJGNlbnRlclNwaGVyZSBzaG91bGQgYmUgYW4gYXJyYXkgb2YgUGFyc2UuR2VvUG9pbnQgYW5kIGRpc3RhbmNlJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy8gR2V0IHBvaW50LCBjb252ZXJ0IHRvIGdlbyBwb2ludCBpZiBuZWNlc3NhcnkgYW5kIHZhbGlkYXRlXG4gICAgICBsZXQgcG9pbnQgPSBjZW50ZXJTcGhlcmVbMF07XG4gICAgICBpZiAocG9pbnQgaW5zdGFuY2VvZiBBcnJheSAmJiBwb2ludC5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgcG9pbnQgPSBuZXcgUGFyc2UuR2VvUG9pbnQocG9pbnRbMV0sIHBvaW50WzBdKTtcbiAgICAgIH0gZWxzZSBpZiAoIUdlb1BvaW50Q29kZXIuaXNWYWxpZEpTT04ocG9pbnQpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkY2VudGVyU3BoZXJlIGdlbyBwb2ludCBpbnZhbGlkJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50LmxhdGl0dWRlLCBwb2ludC5sb25naXR1ZGUpO1xuICAgICAgLy8gR2V0IGRpc3RhbmNlIGFuZCB2YWxpZGF0ZVxuICAgICAgY29uc3QgZGlzdGFuY2UgPSBjZW50ZXJTcGhlcmVbMV07XG4gICAgICBpZiAoaXNOYU4oZGlzdGFuY2UpIHx8IGRpc3RhbmNlIDwgMCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJGNlbnRlclNwaGVyZSBkaXN0YW5jZSBpbnZhbGlkJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3QgZGlzdGFuY2VJbktNID0gZGlzdGFuY2UgKiA2MzcxICogMTAwMDtcbiAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgIGBTVF9kaXN0YW5jZV9zcGhlcmUoJCR7aW5kZXh9Om5hbWU6Omdlb21ldHJ5LCBQT0lOVCgkJHtpbmRleCArXG4gICAgICAgICAgMX0sICQke2luZGV4ICsgMn0pOjpnZW9tZXRyeSkgPD0gJCR7aW5kZXggKyAzfWBcbiAgICAgICk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHBvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGUsIGRpc3RhbmNlSW5LTSk7XG4gICAgICBpbmRleCArPSA0O1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRnZW9XaXRoaW4gJiYgZmllbGRWYWx1ZS4kZ2VvV2l0aGluLiRwb2x5Z29uKSB7XG4gICAgICBjb25zdCBwb2x5Z29uID0gZmllbGRWYWx1ZS4kZ2VvV2l0aGluLiRwb2x5Z29uO1xuICAgICAgbGV0IHBvaW50cztcbiAgICAgIGlmICh0eXBlb2YgcG9seWdvbiA9PT0gJ29iamVjdCcgJiYgcG9seWdvbi5fX3R5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgICBpZiAoIXBvbHlnb24uY29vcmRpbmF0ZXMgfHwgcG9seWdvbi5jb29yZGluYXRlcy5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyBQb2x5Z29uLmNvb3JkaW5hdGVzIHNob3VsZCBjb250YWluIGF0IGxlYXN0IDMgbG9uL2xhdCBwYWlycydcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHBvaW50cyA9IHBvbHlnb24uY29vcmRpbmF0ZXM7XG4gICAgICB9IGVsc2UgaWYgKHBvbHlnb24gaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICBpZiAocG9seWdvbi5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkcG9seWdvbiBzaG91bGQgY29udGFpbiBhdCBsZWFzdCAzIEdlb1BvaW50cydcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHBvaW50cyA9IHBvbHlnb247XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIFwiYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRwb2x5Z29uIHNob3VsZCBiZSBQb2x5Z29uIG9iamVjdCBvciBBcnJheSBvZiBQYXJzZS5HZW9Qb2ludCdzXCJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHBvaW50cyA9IHBvaW50c1xuICAgICAgICAubWFwKHBvaW50ID0+IHtcbiAgICAgICAgICBpZiAocG9pbnQgaW5zdGFuY2VvZiBBcnJheSAmJiBwb2ludC5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwb2ludFsxXSwgcG9pbnRbMF0pO1xuICAgICAgICAgICAgcmV0dXJuIGAoJHtwb2ludFswXX0sICR7cG9pbnRbMV19KWA7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0eXBlb2YgcG9pbnQgIT09ICdvYmplY3QnIHx8IHBvaW50Ll9fdHlwZSAhPT0gJ0dlb1BvaW50Jykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZSdcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwb2ludC5sYXRpdHVkZSwgcG9pbnQubG9uZ2l0dWRlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGAoJHtwb2ludC5sb25naXR1ZGV9LCAke3BvaW50LmxhdGl0dWRlfSlgO1xuICAgICAgICB9KVxuICAgICAgICAuam9pbignLCAnKTtcblxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWU6OnBvaW50IDxAICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgYCgke3BvaW50c30pYCk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cbiAgICBpZiAoZmllbGRWYWx1ZS4kZ2VvSW50ZXJzZWN0cyAmJiBmaWVsZFZhbHVlLiRnZW9JbnRlcnNlY3RzLiRwb2ludCkge1xuICAgICAgY29uc3QgcG9pbnQgPSBmaWVsZFZhbHVlLiRnZW9JbnRlcnNlY3RzLiRwb2ludDtcbiAgICAgIGlmICh0eXBlb2YgcG9pbnQgIT09ICdvYmplY3QnIHx8IHBvaW50Ll9fdHlwZSAhPT0gJ0dlb1BvaW50Jykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICdiYWQgJGdlb0ludGVyc2VjdCB2YWx1ZTsgJHBvaW50IHNob3VsZCBiZSBHZW9Qb2ludCdcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwb2ludC5sYXRpdHVkZSwgcG9pbnQubG9uZ2l0dWRlKTtcbiAgICAgIH1cbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lOjpwb2x5Z29uIEA+ICQke2luZGV4ICsgMX06OnBvaW50YCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGAoJHtwb2ludC5sb25naXR1ZGV9LCAke3BvaW50LmxhdGl0dWRlfSlgKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJHJlZ2V4KSB7XG4gICAgICBsZXQgcmVnZXggPSBmaWVsZFZhbHVlLiRyZWdleDtcbiAgICAgIGxldCBvcGVyYXRvciA9ICd+JztcbiAgICAgIGNvbnN0IG9wdHMgPSBmaWVsZFZhbHVlLiRvcHRpb25zO1xuICAgICAgaWYgKG9wdHMpIHtcbiAgICAgICAgaWYgKG9wdHMuaW5kZXhPZignaScpID49IDApIHtcbiAgICAgICAgICBvcGVyYXRvciA9ICd+Kic7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdHMuaW5kZXhPZigneCcpID49IDApIHtcbiAgICAgICAgICByZWdleCA9IHJlbW92ZVdoaXRlU3BhY2UocmVnZXgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5hbWUgPSB0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpO1xuICAgICAgcmVnZXggPSBwcm9jZXNzUmVnZXhQYXR0ZXJuKHJlZ2V4KTtcblxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9OnJhdyAke29wZXJhdG9yfSAnJCR7aW5kZXggKyAxfTpyYXcnYCk7XG4gICAgICB2YWx1ZXMucHVzaChuYW1lLCByZWdleCk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYGFycmF5X2NvbnRhaW5zKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9KWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KFtmaWVsZFZhbHVlXSkpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5vYmplY3RJZCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRGF0ZScpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmlzbyk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgfj0gUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggKyAyfSlgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5sb25naXR1ZGUsIGZpZWxkVmFsdWUubGF0aXR1ZGUpO1xuICAgICAgaW5kZXggKz0gMztcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS5fX3R5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0UG9seWdvblRvU1FMKGZpZWxkVmFsdWUuY29vcmRpbmF0ZXMpO1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgfj0gJCR7aW5kZXggKyAxfTo6cG9seWdvbmApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCB2YWx1ZSk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIE9iamVjdC5rZXlzKFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcikuZm9yRWFjaChjbXAgPT4ge1xuICAgICAgaWYgKGZpZWxkVmFsdWVbY21wXSB8fCBmaWVsZFZhbHVlW2NtcF0gPT09IDApIHtcbiAgICAgICAgY29uc3QgcGdDb21wYXJhdG9yID0gUGFyc2VUb1Bvc2dyZXNDb21wYXJhdG9yW2NtcF07XG4gICAgICAgIGNvbnN0IHBvc3RncmVzVmFsdWUgPSB0b1Bvc3RncmVzVmFsdWUoZmllbGRWYWx1ZVtjbXBdKTtcbiAgICAgICAgbGV0IGNvbnN0cmFpbnRGaWVsZE5hbWU7XG4gICAgICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDApIHtcbiAgICAgICAgICBsZXQgY2FzdFR5cGU7XG4gICAgICAgICAgc3dpdGNoICh0eXBlb2YgcG9zdGdyZXNWYWx1ZSkge1xuICAgICAgICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgICAgICAgY2FzdFR5cGUgPSAnZG91YmxlIHByZWNpc2lvbic7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICAgICAgICAgIGNhc3RUeXBlID0gJ2Jvb2xlYW4nO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIGNhc3RUeXBlID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdHJhaW50RmllbGROYW1lID0gY2FzdFR5cGVcbiAgICAgICAgICAgID8gYENBU1QgKCgke3RyYW5zZm9ybURvdEZpZWxkKGZpZWxkTmFtZSl9KSBBUyAke2Nhc3RUeXBlfSlgXG4gICAgICAgICAgICA6IHRyYW5zZm9ybURvdEZpZWxkKGZpZWxkTmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3RyYWludEZpZWxkTmFtZSA9IGAkJHtpbmRleCsrfTpuYW1lYDtcbiAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHZhbHVlcy5wdXNoKHBvc3RncmVzVmFsdWUpO1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAke2NvbnN0cmFpbnRGaWVsZE5hbWV9ICR7cGdDb21wYXJhdG9yfSAkJHtpbmRleCsrfWApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKGluaXRpYWxQYXR0ZXJuc0xlbmd0aCA9PT0gcGF0dGVybnMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICAgIGBQb3N0Z3JlcyBkb2Vzbid0IHN1cHBvcnQgdGhpcyBxdWVyeSB0eXBlIHlldCAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIGZpZWxkVmFsdWVcbiAgICAgICAgKX1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuICB2YWx1ZXMgPSB2YWx1ZXMubWFwKHRyYW5zZm9ybVZhbHVlKTtcbiAgcmV0dXJuIHsgcGF0dGVybjogcGF0dGVybnMuam9pbignIEFORCAnKSwgdmFsdWVzLCBzb3J0cyB9O1xufTtcblxuZXhwb3J0IGNsYXNzIFBvc3RncmVzU3RvcmFnZUFkYXB0ZXIgaW1wbGVtZW50cyBTdG9yYWdlQWRhcHRlciB7XG4gIGNhblNvcnRPbkpvaW5UYWJsZXM6IGJvb2xlYW47XG5cbiAgLy8gUHJpdmF0ZVxuICBfY29sbGVjdGlvblByZWZpeDogc3RyaW5nO1xuICBfY2xpZW50OiBhbnk7XG4gIF9wZ3A6IGFueTtcblxuICBjb25zdHJ1Y3Rvcih7IHVyaSwgY29sbGVjdGlvblByZWZpeCA9ICcnLCBkYXRhYmFzZU9wdGlvbnMgfTogYW55KSB7XG4gICAgdGhpcy5fY29sbGVjdGlvblByZWZpeCA9IGNvbGxlY3Rpb25QcmVmaXg7XG4gICAgY29uc3QgeyBjbGllbnQsIHBncCB9ID0gY3JlYXRlQ2xpZW50KHVyaSwgZGF0YWJhc2VPcHRpb25zKTtcbiAgICB0aGlzLl9jbGllbnQgPSBjbGllbnQ7XG4gICAgdGhpcy5fcGdwID0gcGdwO1xuICAgIHRoaXMuY2FuU29ydE9uSm9pblRhYmxlcyA9IGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlU2h1dGRvd24oKSB7XG4gICAgaWYgKCF0aGlzLl9jbGllbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fY2xpZW50LiRwb29sLmVuZCgpO1xuICB9XG5cbiAgX2Vuc3VyZVNjaGVtYUNvbGxlY3Rpb25FeGlzdHMoY29ubjogYW55KSB7XG4gICAgY29ubiA9IGNvbm4gfHwgdGhpcy5fY2xpZW50O1xuICAgIHJldHVybiBjb25uXG4gICAgICAubm9uZShcbiAgICAgICAgJ0NSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIFwiX1NDSEVNQVwiICggXCJjbGFzc05hbWVcIiB2YXJDaGFyKDEyMCksIFwic2NoZW1hXCIganNvbmIsIFwiaXNQYXJzZUNsYXNzXCIgYm9vbCwgUFJJTUFSWSBLRVkgKFwiY2xhc3NOYW1lXCIpICknXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yIHx8XG4gICAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yIHx8XG4gICAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVPYmplY3RFcnJvclxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBUYWJsZSBhbHJlYWR5IGV4aXN0cywgbXVzdCBoYXZlIGJlZW4gY3JlYXRlZCBieSBhIGRpZmZlcmVudCByZXF1ZXN0LiBJZ25vcmUgZXJyb3IuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgY2xhc3NFeGlzdHMobmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5vbmUoXG4gICAgICAnU0VMRUNUIEVYSVNUUyAoU0VMRUNUIDEgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIFdIRVJFIHRhYmxlX25hbWUgPSAkMSknLFxuICAgICAgW25hbWVdLFxuICAgICAgYSA9PiBhLmV4aXN0c1xuICAgICk7XG4gIH1cblxuICBzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lOiBzdHJpbmcsIENMUHM6IGFueSkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQudGFzaygnc2V0LWNsYXNzLWxldmVsLXBlcm1pc3Npb25zJywgYXN5bmMgdCA9PiB7XG4gICAgICBhd2FpdCBzZWxmLl9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzKHQpO1xuICAgICAgY29uc3QgdmFsdWVzID0gW1xuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICdzY2hlbWEnLFxuICAgICAgICAnY2xhc3NMZXZlbFBlcm1pc3Npb25zJyxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoQ0xQcyksXG4gICAgICBdO1xuICAgICAgYXdhaXQgdC5ub25lKFxuICAgICAgICBgVVBEQVRFIFwiX1NDSEVNQVwiIFNFVCAkMjpuYW1lID0ganNvbl9vYmplY3Rfc2V0X2tleSgkMjpuYW1lLCAkMzo6dGV4dCwgJDQ6Ompzb25iKSBXSEVSRSBcImNsYXNzTmFtZVwiPSQxYCxcbiAgICAgICAgdmFsdWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgc2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc3VibWl0dGVkSW5kZXhlczogYW55LFxuICAgIGV4aXN0aW5nSW5kZXhlczogYW55ID0ge30sXG4gICAgZmllbGRzOiBhbnksXG4gICAgY29ubjogP2FueVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgaWYgKHN1Ym1pdHRlZEluZGV4ZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICBpZiAoT2JqZWN0LmtleXMoZXhpc3RpbmdJbmRleGVzKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGV4aXN0aW5nSW5kZXhlcyA9IHsgX2lkXzogeyBfaWQ6IDEgfSB9O1xuICAgIH1cbiAgICBjb25zdCBkZWxldGVkSW5kZXhlcyA9IFtdO1xuICAgIGNvbnN0IGluc2VydGVkSW5kZXhlcyA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEluZGV4ZXMpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb25zdCBmaWVsZCA9IHN1Ym1pdHRlZEluZGV4ZXNbbmFtZV07XG4gICAgICBpZiAoZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgIGBJbmRleCAke25hbWV9IGV4aXN0cywgY2Fubm90IHVwZGF0ZS5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4aXN0aW5nSW5kZXhlc1tuYW1lXSAmJiBmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgICBgSW5kZXggJHtuYW1lfSBkb2VzIG5vdCBleGlzdCwgY2Fubm90IGRlbGV0ZS5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgZGVsZXRlZEluZGV4ZXMucHVzaChuYW1lKTtcbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nSW5kZXhlc1tuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGZpZWxkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZmllbGRzLCBrZXkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgICAgIGBGaWVsZCAke2tleX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBhZGQgaW5kZXguYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBleGlzdGluZ0luZGV4ZXNbbmFtZV0gPSBmaWVsZDtcbiAgICAgICAgaW5zZXJ0ZWRJbmRleGVzLnB1c2goe1xuICAgICAgICAgIGtleTogZmllbGQsXG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbm4udHgoJ3NldC1pbmRleGVzLXdpdGgtc2NoZW1hLWZvcm1hdCcsIGFzeW5jIHQgPT4ge1xuICAgICAgaWYgKGluc2VydGVkSW5kZXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IHNlbGYuY3JlYXRlSW5kZXhlcyhjbGFzc05hbWUsIGluc2VydGVkSW5kZXhlcywgdCk7XG4gICAgICB9XG4gICAgICBpZiAoZGVsZXRlZEluZGV4ZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhd2FpdCBzZWxmLmRyb3BJbmRleGVzKGNsYXNzTmFtZSwgZGVsZXRlZEluZGV4ZXMsIHQpO1xuICAgICAgfVxuICAgICAgYXdhaXQgc2VsZi5fZW5zdXJlU2NoZW1hQ29sbGVjdGlvbkV4aXN0cyh0KTtcbiAgICAgIGF3YWl0IHQubm9uZShcbiAgICAgICAgJ1VQREFURSBcIl9TQ0hFTUFcIiBTRVQgJDI6bmFtZSA9IGpzb25fb2JqZWN0X3NldF9rZXkoJDI6bmFtZSwgJDM6OnRleHQsICQ0Ojpqc29uYikgV0hFUkUgXCJjbGFzc05hbWVcIj0kMScsXG4gICAgICAgIFtjbGFzc05hbWUsICdzY2hlbWEnLCAnaW5kZXhlcycsIEpTT04uc3RyaW5naWZ5KGV4aXN0aW5nSW5kZXhlcyldXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgY29ubjogP2FueSkge1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICByZXR1cm4gY29ublxuICAgICAgLnR4KCdjcmVhdGUtY2xhc3MnLCB0ID0+IHtcbiAgICAgICAgY29uc3QgcTEgPSB0aGlzLmNyZWF0ZVRhYmxlKGNsYXNzTmFtZSwgc2NoZW1hLCB0KTtcbiAgICAgICAgY29uc3QgcTIgPSB0Lm5vbmUoXG4gICAgICAgICAgJ0lOU0VSVCBJTlRPIFwiX1NDSEVNQVwiIChcImNsYXNzTmFtZVwiLCBcInNjaGVtYVwiLCBcImlzUGFyc2VDbGFzc1wiKSBWQUxVRVMgKCQ8Y2xhc3NOYW1lPiwgJDxzY2hlbWE+LCB0cnVlKScsXG4gICAgICAgICAgeyBjbGFzc05hbWUsIHNjaGVtYSB9XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHEzID0gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChcbiAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgc2NoZW1hLmluZGV4ZXMsXG4gICAgICAgICAge30sXG4gICAgICAgICAgc2NoZW1hLmZpZWxkcyxcbiAgICAgICAgICB0XG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB0LmJhdGNoKFtxMSwgcTIsIHEzXSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdG9QYXJzZVNjaGVtYShzY2hlbWEpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICBpZiAoZXJyLmRhdGFbMF0ucmVzdWx0LmNvZGUgPT09IFBvc3RncmVzVHJhbnNhY3Rpb25BYm9ydGVkRXJyb3IpIHtcbiAgICAgICAgICBlcnIgPSBlcnIuZGF0YVsxXS5yZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGVyci5jb2RlID09PSBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IgJiZcbiAgICAgICAgICBlcnIuZGV0YWlsLmluY2x1ZGVzKGNsYXNzTmFtZSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLFxuICAgICAgICAgICAgYENsYXNzICR7Y2xhc3NOYW1lfSBhbHJlYWR5IGV4aXN0cy5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIEp1c3QgY3JlYXRlIGEgdGFibGUsIGRvIG5vdCBpbnNlcnQgaW4gc2NoZW1hXG4gIGNyZWF0ZVRhYmxlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGNvbm46IGFueSkge1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBkZWJ1ZygnY3JlYXRlVGFibGUnLCBjbGFzc05hbWUsIHNjaGVtYSk7XG4gICAgY29uc3QgdmFsdWVzQXJyYXkgPSBbXTtcbiAgICBjb25zdCBwYXR0ZXJuc0FycmF5ID0gW107XG4gICAgY29uc3QgZmllbGRzID0gT2JqZWN0LmFzc2lnbih7fSwgc2NoZW1hLmZpZWxkcyk7XG4gICAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgZmllbGRzLl9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCA9IHsgdHlwZTogJ0RhdGUnIH07XG4gICAgICBmaWVsZHMuX2VtYWlsX3ZlcmlmeV90b2tlbiA9IHsgdHlwZTogJ1N0cmluZycgfTtcbiAgICAgIGZpZWxkcy5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQgPSB7IHR5cGU6ICdEYXRlJyB9O1xuICAgICAgZmllbGRzLl9mYWlsZWRfbG9naW5fY291bnQgPSB7IHR5cGU6ICdOdW1iZXInIH07XG4gICAgICBmaWVsZHMuX3BlcmlzaGFibGVfdG9rZW4gPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gICAgICBmaWVsZHMuX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCA9IHsgdHlwZTogJ0RhdGUnIH07XG4gICAgICBmaWVsZHMuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSB7IHR5cGU6ICdEYXRlJyB9O1xuICAgICAgZmllbGRzLl9wYXNzd29yZF9oaXN0b3J5ID0geyB0eXBlOiAnQXJyYXknIH07XG4gICAgfVxuICAgIGxldCBpbmRleCA9IDI7XG4gICAgY29uc3QgcmVsYXRpb25zID0gW107XG4gICAgT2JqZWN0LmtleXMoZmllbGRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBjb25zdCBwYXJzZVR5cGUgPSBmaWVsZHNbZmllbGROYW1lXTtcbiAgICAgIC8vIFNraXAgd2hlbiBpdCdzIGEgcmVsYXRpb25cbiAgICAgIC8vIFdlJ2xsIGNyZWF0ZSB0aGUgdGFibGVzIGxhdGVyXG4gICAgICBpZiAocGFyc2VUeXBlLnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgcmVsYXRpb25zLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKFsnX3JwZXJtJywgJ193cGVybSddLmluZGV4T2YoZmllbGROYW1lKSA+PSAwKSB7XG4gICAgICAgIHBhcnNlVHlwZS5jb250ZW50cyA9IHsgdHlwZTogJ1N0cmluZycgfTtcbiAgICAgIH1cbiAgICAgIHZhbHVlc0FycmF5LnB1c2goZmllbGROYW1lKTtcbiAgICAgIHZhbHVlc0FycmF5LnB1c2gocGFyc2VUeXBlVG9Qb3N0Z3Jlc1R5cGUocGFyc2VUeXBlKSk7XG4gICAgICBwYXR0ZXJuc0FycmF5LnB1c2goYCQke2luZGV4fTpuYW1lICQke2luZGV4ICsgMX06cmF3YCk7XG4gICAgICBpZiAoZmllbGROYW1lID09PSAnb2JqZWN0SWQnKSB7XG4gICAgICAgIHBhdHRlcm5zQXJyYXkucHVzaChgUFJJTUFSWSBLRVkgKCQke2luZGV4fTpuYW1lKWApO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDI7XG4gICAgfSk7XG4gICAgY29uc3QgcXMgPSBgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJDE6bmFtZSAoJHtwYXR0ZXJuc0FycmF5LmpvaW4oKX0pYDtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAuLi52YWx1ZXNBcnJheV07XG5cbiAgICBkZWJ1ZyhxcywgdmFsdWVzKTtcbiAgICByZXR1cm4gY29ubi50YXNrKCdjcmVhdGUtdGFibGUnLCBhc3luYyB0ID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHNlbGYuX2Vuc3VyZVNjaGVtYUNvbGxlY3Rpb25FeGlzdHModCk7XG4gICAgICAgIGF3YWl0IHQubm9uZShxcywgdmFsdWVzKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBFTFNFOiBUYWJsZSBhbHJlYWR5IGV4aXN0cywgbXVzdCBoYXZlIGJlZW4gY3JlYXRlZCBieSBhIGRpZmZlcmVudCByZXF1ZXN0LiBJZ25vcmUgdGhlIGVycm9yLlxuICAgICAgfVxuICAgICAgYXdhaXQgdC50eCgnY3JlYXRlLXRhYmxlLXR4JywgdHggPT4ge1xuICAgICAgICByZXR1cm4gdHguYmF0Y2goXG4gICAgICAgICAgcmVsYXRpb25zLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHR4Lm5vbmUoXG4gICAgICAgICAgICAgICdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAkPGpvaW5UYWJsZTpuYW1lPiAoXCJyZWxhdGVkSWRcIiB2YXJDaGFyKDEyMCksIFwib3duaW5nSWRcIiB2YXJDaGFyKDEyMCksIFBSSU1BUlkgS0VZKFwicmVsYXRlZElkXCIsIFwib3duaW5nSWRcIikgKScsXG4gICAgICAgICAgICAgIHsgam9pblRhYmxlOiBgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBzY2hlbWFVcGdyYWRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGNvbm46IGFueSkge1xuICAgIGRlYnVnKCdzY2hlbWFVcGdyYWRlJywgeyBjbGFzc05hbWUsIHNjaGVtYSB9KTtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICByZXR1cm4gY29ubi50eCgnc2NoZW1hLXVwZ3JhZGUnLCBhc3luYyB0ID0+IHtcbiAgICAgIGNvbnN0IGNvbHVtbnMgPSBhd2FpdCB0Lm1hcChcbiAgICAgICAgJ1NFTEVDVCBjb2x1bW5fbmFtZSBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIFdIRVJFIHRhYmxlX25hbWUgPSAkPGNsYXNzTmFtZT4nLFxuICAgICAgICB7IGNsYXNzTmFtZSB9LFxuICAgICAgICBhID0+IGEuY29sdW1uX25hbWVcbiAgICAgICk7XG4gICAgICBjb25zdCBuZXdDb2x1bW5zID0gT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcylcbiAgICAgICAgLmZpbHRlcihpdGVtID0+IGNvbHVtbnMuaW5kZXhPZihpdGVtKSA9PT0gLTEpXG4gICAgICAgIC5tYXAoZmllbGROYW1lID0+XG4gICAgICAgICAgc2VsZi5hZGRGaWVsZElmTm90RXhpc3RzKFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgZmllbGROYW1lLFxuICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLFxuICAgICAgICAgICAgdFxuICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgYXdhaXQgdC5iYXRjaChuZXdDb2x1bW5zKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFkZEZpZWxkSWZOb3RFeGlzdHMoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZmllbGROYW1lOiBzdHJpbmcsXG4gICAgdHlwZTogYW55LFxuICAgIGNvbm46IGFueVxuICApIHtcbiAgICAvLyBUT0RPOiBNdXN0IGJlIHJldmlzZWQgZm9yIGludmFsaWQgbG9naWMuLi5cbiAgICBkZWJ1ZygnYWRkRmllbGRJZk5vdEV4aXN0cycsIHsgY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHR5cGUgfSk7XG4gICAgY29ubiA9IGNvbm4gfHwgdGhpcy5fY2xpZW50O1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIHJldHVybiBjb25uLnR4KCdhZGQtZmllbGQtaWYtbm90LWV4aXN0cycsIGFzeW5jIHQgPT4ge1xuICAgICAgaWYgKHR5cGUudHlwZSAhPT0gJ1JlbGF0aW9uJykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHQubm9uZShcbiAgICAgICAgICAgICdBTFRFUiBUQUJMRSAkPGNsYXNzTmFtZTpuYW1lPiBBREQgQ09MVU1OICQ8ZmllbGROYW1lOm5hbWU+ICQ8cG9zdGdyZXNUeXBlOnJhdz4nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgICAgICAgcG9zdGdyZXNUeXBlOiBwYXJzZVR5cGVUb1Bvc3RncmVzVHlwZSh0eXBlKSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSBQb3N0Z3Jlc1JlbGF0aW9uRG9lc05vdEV4aXN0RXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBzZWxmLmNyZWF0ZUNsYXNzKFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIHsgZmllbGRzOiB7IFtmaWVsZE5hbWVdOiB0eXBlIH0gfSxcbiAgICAgICAgICAgICAgdFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgIT09IFBvc3RncmVzRHVwbGljYXRlQ29sdW1uRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb2x1bW4gYWxyZWFkeSBleGlzdHMsIGNyZWF0ZWQgYnkgb3RoZXIgcmVxdWVzdC4gQ2Fycnkgb24gdG8gc2VlIGlmIGl0J3MgdGhlIHJpZ2h0IHR5cGUuXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHQubm9uZShcbiAgICAgICAgICAnQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJDxqb2luVGFibGU6bmFtZT4gKFwicmVsYXRlZElkXCIgdmFyQ2hhcigxMjApLCBcIm93bmluZ0lkXCIgdmFyQ2hhcigxMjApLCBQUklNQVJZIEtFWShcInJlbGF0ZWRJZFwiLCBcIm93bmluZ0lkXCIpICknLFxuICAgICAgICAgIHsgam9pblRhYmxlOiBgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0LmFueShcbiAgICAgICAgJ1NFTEVDVCBcInNjaGVtYVwiIEZST00gXCJfU0NIRU1BXCIgV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQ8Y2xhc3NOYW1lPiBhbmQgKFwic2NoZW1hXCI6Ompzb24tPlxcJ2ZpZWxkc1xcJy0+JDxmaWVsZE5hbWU+KSBpcyBub3QgbnVsbCcsXG4gICAgICAgIHsgY2xhc3NOYW1lLCBmaWVsZE5hbWUgfVxuICAgICAgKTtcblxuICAgICAgaWYgKHJlc3VsdFswXSkge1xuICAgICAgICB0aHJvdyAnQXR0ZW1wdGVkIHRvIGFkZCBhIGZpZWxkIHRoYXQgYWxyZWFkeSBleGlzdHMnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcGF0aCA9IGB7ZmllbGRzLCR7ZmllbGROYW1lfX1gO1xuICAgICAgICBhd2FpdCB0Lm5vbmUoXG4gICAgICAgICAgJ1VQREFURSBcIl9TQ0hFTUFcIiBTRVQgXCJzY2hlbWFcIj1qc29uYl9zZXQoXCJzY2hlbWFcIiwgJDxwYXRoPiwgJDx0eXBlPikgIFdIRVJFIFwiY2xhc3NOYW1lXCI9JDxjbGFzc05hbWU+JyxcbiAgICAgICAgICB7IHBhdGgsIHR5cGUsIGNsYXNzTmFtZSB9XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBEcm9wcyBhIGNvbGxlY3Rpb24uIFJlc29sdmVzIHdpdGggdHJ1ZSBpZiBpdCB3YXMgYSBQYXJzZSBTY2hlbWEgKGVnLiBfVXNlciwgQ3VzdG9tLCBldGMuKVxuICAvLyBhbmQgcmVzb2x2ZXMgd2l0aCBmYWxzZSBpZiBpdCB3YXNuJ3QgKGVnLiBhIGpvaW4gdGFibGUpLiBSZWplY3RzIGlmIGRlbGV0aW9uIHdhcyBpbXBvc3NpYmxlLlxuICBkZWxldGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBbXG4gICAgICB7IHF1ZXJ5OiBgRFJPUCBUQUJMRSBJRiBFWElTVFMgJDE6bmFtZWAsIHZhbHVlczogW2NsYXNzTmFtZV0gfSxcbiAgICAgIHtcbiAgICAgICAgcXVlcnk6IGBERUxFVEUgRlJPTSBcIl9TQ0hFTUFcIiBXSEVSRSBcImNsYXNzTmFtZVwiID0gJDFgLFxuICAgICAgICB2YWx1ZXM6IFtjbGFzc05hbWVdLFxuICAgICAgfSxcbiAgICBdO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnRcbiAgICAgIC50eCh0ID0+IHQubm9uZSh0aGlzLl9wZ3AuaGVscGVycy5jb25jYXQob3BlcmF0aW9ucykpKVxuICAgICAgLnRoZW4oKCkgPT4gY2xhc3NOYW1lLmluZGV4T2YoJ19Kb2luOicpICE9IDApOyAvLyByZXNvbHZlcyB3aXRoIGZhbHNlIHdoZW4gX0pvaW4gdGFibGVcbiAgfVxuXG4gIC8vIERlbGV0ZSBhbGwgZGF0YSBrbm93biB0byB0aGlzIGFkYXB0ZXIuIFVzZWQgZm9yIHRlc3RpbmcuXG4gIGRlbGV0ZUFsbENsYXNzZXMoKSB7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgaGVscGVycyA9IHRoaXMuX3BncC5oZWxwZXJzO1xuICAgIGRlYnVnKCdkZWxldGVBbGxDbGFzc2VzJyk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAudGFzaygnZGVsZXRlLWFsbC1jbGFzc2VzJywgYXN5bmMgdCA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHQuYW55KCdTRUxFQ1QgKiBGUk9NIFwiX1NDSEVNQVwiJyk7XG4gICAgICAgICAgY29uc3Qgam9pbnMgPSByZXN1bHRzLnJlZHVjZSgobGlzdDogQXJyYXk8c3RyaW5nPiwgc2NoZW1hOiBhbnkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBsaXN0LmNvbmNhdChqb2luVGFibGVzRm9yU2NoZW1hKHNjaGVtYS5zY2hlbWEpKTtcbiAgICAgICAgICB9LCBbXSk7XG4gICAgICAgICAgY29uc3QgY2xhc3NlcyA9IFtcbiAgICAgICAgICAgICdfU0NIRU1BJyxcbiAgICAgICAgICAgICdfUHVzaFN0YXR1cycsXG4gICAgICAgICAgICAnX0pvYlN0YXR1cycsXG4gICAgICAgICAgICAnX0pvYlNjaGVkdWxlJyxcbiAgICAgICAgICAgICdfSG9va3MnLFxuICAgICAgICAgICAgJ19HbG9iYWxDb25maWcnLFxuICAgICAgICAgICAgJ19HcmFwaFFMQ29uZmlnJyxcbiAgICAgICAgICAgICdfQXVkaWVuY2UnLFxuICAgICAgICAgICAgLi4ucmVzdWx0cy5tYXAocmVzdWx0ID0+IHJlc3VsdC5jbGFzc05hbWUpLFxuICAgICAgICAgICAgLi4uam9pbnMsXG4gICAgICAgICAgXTtcbiAgICAgICAgICBjb25zdCBxdWVyaWVzID0gY2xhc3Nlcy5tYXAoY2xhc3NOYW1lID0+ICh7XG4gICAgICAgICAgICBxdWVyeTogJ0RST1AgVEFCTEUgSUYgRVhJU1RTICQ8Y2xhc3NOYW1lOm5hbWU+JyxcbiAgICAgICAgICAgIHZhbHVlczogeyBjbGFzc05hbWUgfSxcbiAgICAgICAgICB9KSk7XG4gICAgICAgICAgYXdhaXQgdC50eCh0eCA9PiB0eC5ub25lKGhlbHBlcnMuY29uY2F0KHF1ZXJpZXMpKSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgIT09IFBvc3RncmVzUmVsYXRpb25Eb2VzTm90RXhpc3RFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIE5vIF9TQ0hFTUEgY29sbGVjdGlvbi4gRG9uJ3QgZGVsZXRlIGFueXRoaW5nLlxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZGVsZXRlQWxsQ2xhc3NlcyBkb25lIGluICR7bmV3IERhdGUoKS5nZXRUaW1lKCkgLSBub3d9YCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFJlbW92ZSB0aGUgY29sdW1uIGFuZCBhbGwgdGhlIGRhdGEuIEZvciBSZWxhdGlvbnMsIHRoZSBfSm9pbiBjb2xsZWN0aW9uIGlzIGhhbmRsZWRcbiAgLy8gc3BlY2lhbGx5LCB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IGRlbGV0ZSBfSm9pbiBjb2x1bW5zLiBJdCBzaG91bGQsIGhvd2V2ZXIsIGluZGljYXRlXG4gIC8vIHRoYXQgdGhlIHJlbGF0aW9uIGZpZWxkcyBkb2VzIG5vdCBleGlzdCBhbnltb3JlLiBJbiBtb25nbywgdGhpcyBtZWFucyByZW1vdmluZyBpdCBmcm9tXG4gIC8vIHRoZSBfU0NIRU1BIGNvbGxlY3Rpb24uICBUaGVyZSBzaG91bGQgYmUgbm8gYWN0dWFsIGRhdGEgaW4gdGhlIGNvbGxlY3Rpb24gdW5kZXIgdGhlIHNhbWUgbmFtZVxuICAvLyBhcyB0aGUgcmVsYXRpb24gY29sdW1uLCBzbyBpdCdzIGZpbmUgdG8gYXR0ZW1wdCB0byBkZWxldGUgaXQuIElmIHRoZSBmaWVsZHMgbGlzdGVkIHRvIGJlXG4gIC8vIGRlbGV0ZWQgZG8gbm90IGV4aXN0LCB0aGlzIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gc3VjY2Vzc2Z1bGx5IGFueXdheXMuIENoZWNraW5nIGZvclxuICAvLyBhdHRlbXB0cyB0byBkZWxldGUgbm9uLWV4aXN0ZW50IGZpZWxkcyBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgUGFyc2UgU2VydmVyLlxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gaXMgbm90IG9ibGlnYXRlZCB0byBkZWxldGUgZmllbGRzIGF0b21pY2FsbHkuIEl0IGlzIGdpdmVuIHRoZSBmaWVsZFxuICAvLyBuYW1lcyBpbiBhIGxpc3Qgc28gdGhhdCBkYXRhYmFzZXMgdGhhdCBhcmUgY2FwYWJsZSBvZiBkZWxldGluZyBmaWVsZHMgYXRvbWljYWxseVxuICAvLyBtYXkgZG8gc28uXG5cbiAgLy8gUmV0dXJucyBhIFByb21pc2UuXG4gIGRlbGV0ZUZpZWxkcyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgZmllbGROYW1lczogc3RyaW5nW11cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZGVidWcoJ2RlbGV0ZUZpZWxkcycsIGNsYXNzTmFtZSwgZmllbGROYW1lcyk7XG4gICAgZmllbGROYW1lcyA9IGZpZWxkTmFtZXMucmVkdWNlKChsaXN0OiBBcnJheTxzdHJpbmc+LCBmaWVsZE5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgZmllbGQgPSBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICBpZiAoZmllbGQudHlwZSAhPT0gJ1JlbGF0aW9uJykge1xuICAgICAgICBsaXN0LnB1c2goZmllbGROYW1lKTtcbiAgICAgIH1cbiAgICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICByZXR1cm4gbGlzdDtcbiAgICB9LCBbXSk7XG5cbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAuLi5maWVsZE5hbWVzXTtcbiAgICBjb25zdCBjb2x1bW5zID0gZmllbGROYW1lc1xuICAgICAgLm1hcCgobmFtZSwgaWR4KSA9PiB7XG4gICAgICAgIHJldHVybiBgJCR7aWR4ICsgMn06bmFtZWA7XG4gICAgICB9KVxuICAgICAgLmpvaW4oJywgRFJPUCBDT0xVTU4nKTtcblxuICAgIHJldHVybiB0aGlzLl9jbGllbnQudHgoJ2RlbGV0ZS1maWVsZHMnLCBhc3luYyB0ID0+IHtcbiAgICAgIGF3YWl0IHQubm9uZShcbiAgICAgICAgJ1VQREFURSBcIl9TQ0hFTUFcIiBTRVQgXCJzY2hlbWFcIj0kPHNjaGVtYT4gV0hFUkUgXCJjbGFzc05hbWVcIj0kPGNsYXNzTmFtZT4nLFxuICAgICAgICB7IHNjaGVtYSwgY2xhc3NOYW1lIH1cbiAgICAgICk7XG4gICAgICBpZiAodmFsdWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgYXdhaXQgdC5ub25lKGBBTFRFUiBUQUJMRSAkMTpuYW1lIERST1AgQ09MVU1OICR7Y29sdW1uc31gLCB2YWx1ZXMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgYWxsIHNjaGVtYXMga25vd24gdG8gdGhpcyBhZGFwdGVyLCBpbiBQYXJzZSBmb3JtYXQuIEluIGNhc2UgdGhlXG4gIC8vIHNjaGVtYXMgY2Fubm90IGJlIHJldHJpZXZlZCwgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZWplY3RzLiBSZXF1aXJlbWVudHMgZm9yIHRoZVxuICAvLyByZWplY3Rpb24gcmVhc29uIGFyZSBUQkQuXG4gIGdldEFsbENsYXNzZXMoKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC50YXNrKCdnZXQtYWxsLWNsYXNzZXMnLCBhc3luYyB0ID0+IHtcbiAgICAgIGF3YWl0IHNlbGYuX2Vuc3VyZVNjaGVtYUNvbGxlY3Rpb25FeGlzdHModCk7XG4gICAgICByZXR1cm4gYXdhaXQgdC5tYXAoJ1NFTEVDVCAqIEZST00gXCJfU0NIRU1BXCInLCBudWxsLCByb3cgPT5cbiAgICAgICAgdG9QYXJzZVNjaGVtYSh7IGNsYXNzTmFtZTogcm93LmNsYXNzTmFtZSwgLi4ucm93LnNjaGVtYSB9KVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybiBhIHByb21pc2UgZm9yIHRoZSBzY2hlbWEgd2l0aCB0aGUgZ2l2ZW4gbmFtZSwgaW4gUGFyc2UgZm9ybWF0LiBJZlxuICAvLyB0aGlzIGFkYXB0ZXIgZG9lc24ndCBrbm93IGFib3V0IHRoZSBzY2hlbWEsIHJldHVybiBhIHByb21pc2UgdGhhdCByZWplY3RzIHdpdGhcbiAgLy8gdW5kZWZpbmVkIGFzIHRoZSByZWFzb24uXG4gIGdldENsYXNzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgZGVidWcoJ2dldENsYXNzJywgY2xhc3NOYW1lKTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAuYW55KCdTRUxFQ1QgKiBGUk9NIFwiX1NDSEVNQVwiIFdIRVJFIFwiY2xhc3NOYW1lXCI9JDxjbGFzc05hbWU+Jywge1xuICAgICAgICBjbGFzc05hbWUsXG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICB0aHJvdyB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdFswXS5zY2hlbWE7XG4gICAgICB9KVxuICAgICAgLnRoZW4odG9QYXJzZVNjaGVtYSk7XG4gIH1cblxuICAvLyBUT0RPOiByZW1vdmUgdGhlIG1vbmdvIGZvcm1hdCBkZXBlbmRlbmN5IGluIHRoZSByZXR1cm4gdmFsdWVcbiAgY3JlYXRlT2JqZWN0KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBvYmplY3Q6IGFueSxcbiAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbjogP2FueVxuICApIHtcbiAgICBkZWJ1ZygnY3JlYXRlT2JqZWN0JywgY2xhc3NOYW1lLCBvYmplY3QpO1xuICAgIGxldCBjb2x1bW5zQXJyYXkgPSBbXTtcbiAgICBjb25zdCB2YWx1ZXNBcnJheSA9IFtdO1xuICAgIHNjaGVtYSA9IHRvUG9zdGdyZXNTY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBnZW9Qb2ludHMgPSB7fTtcblxuICAgIG9iamVjdCA9IGhhbmRsZURvdEZpZWxkcyhvYmplY3QpO1xuXG4gICAgdmFsaWRhdGVLZXlzKG9iamVjdCk7XG5cbiAgICBPYmplY3Qua2V5cyhvYmplY3QpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgYXV0aERhdGFNYXRjaCA9IGZpZWxkTmFtZS5tYXRjaCgvXl9hdXRoX2RhdGFfKFthLXpBLVowLTlfXSspJC8pO1xuICAgICAgaWYgKGF1dGhEYXRhTWF0Y2gpIHtcbiAgICAgICAgdmFyIHByb3ZpZGVyID0gYXV0aERhdGFNYXRjaFsxXTtcbiAgICAgICAgb2JqZWN0WydhdXRoRGF0YSddID0gb2JqZWN0WydhdXRoRGF0YSddIHx8IHt9O1xuICAgICAgICBvYmplY3RbJ2F1dGhEYXRhJ11bcHJvdmlkZXJdID0gb2JqZWN0W2ZpZWxkTmFtZV07XG4gICAgICAgIGRlbGV0ZSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgZmllbGROYW1lID0gJ2F1dGhEYXRhJztcbiAgICAgIH1cblxuICAgICAgY29sdW1uc0FycmF5LnB1c2goZmllbGROYW1lKTtcbiAgICAgIGlmICghc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZmllbGROYW1lID09PSAnX2VtYWlsX3ZlcmlmeV90b2tlbicgfHxcbiAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfZmFpbGVkX2xvZ2luX2NvdW50JyB8fFxuICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19wZXJpc2hhYmxlX3Rva2VuJyB8fFxuICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19wYXNzd29yZF9oaXN0b3J5J1xuICAgICAgICApIHtcbiAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWVsZE5hbWUgPT09ICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnKSB7XG4gICAgICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdKSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLmlzbyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gobnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCcgfHxcbiAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JyB8fFxuICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19wYXNzd29yZF9jaGFuZ2VkX2F0J1xuICAgICAgICApIHtcbiAgICAgICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0uaXNvKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChudWxsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgc3dpdGNoIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSkge1xuICAgICAgICBjYXNlICdEYXRlJzpcbiAgICAgICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0uaXNvKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChudWxsKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ1BvaW50ZXInOlxuICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0ub2JqZWN0SWQpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdBcnJheSc6XG4gICAgICAgICAgaWYgKFsnX3JwZXJtJywgJ193cGVybSddLmluZGV4T2YoZmllbGROYW1lKSA+PSAwKSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChKU09OLnN0cmluZ2lmeShvYmplY3RbZmllbGROYW1lXSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnT2JqZWN0JzpcbiAgICAgICAgY2FzZSAnQnl0ZXMnOlxuICAgICAgICBjYXNlICdTdHJpbmcnOlxuICAgICAgICBjYXNlICdOdW1iZXInOlxuICAgICAgICBjYXNlICdCb29sZWFuJzpcbiAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnRmlsZSc6XG4gICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXS5uYW1lKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnUG9seWdvbic6IHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbnZlcnRQb2x5Z29uVG9TUUwob2JqZWN0W2ZpZWxkTmFtZV0uY29vcmRpbmF0ZXMpO1xuICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2godmFsdWUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0dlb1BvaW50JzpcbiAgICAgICAgICAvLyBwb3AgdGhlIHBvaW50IGFuZCBwcm9jZXNzIGxhdGVyXG4gICAgICAgICAgZ2VvUG9pbnRzW2ZpZWxkTmFtZV0gPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgICBjb2x1bW5zQXJyYXkucG9wKCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgYFR5cGUgJHtzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZX0gbm90IHN1cHBvcnRlZCB5ZXRgO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29sdW1uc0FycmF5ID0gY29sdW1uc0FycmF5LmNvbmNhdChPYmplY3Qua2V5cyhnZW9Qb2ludHMpKTtcbiAgICBjb25zdCBpbml0aWFsVmFsdWVzID0gdmFsdWVzQXJyYXkubWFwKCh2YWwsIGluZGV4KSA9PiB7XG4gICAgICBsZXQgdGVybWluYXRpb24gPSAnJztcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGNvbHVtbnNBcnJheVtpbmRleF07XG4gICAgICBpZiAoWydfcnBlcm0nLCAnX3dwZXJtJ10uaW5kZXhPZihmaWVsZE5hbWUpID49IDApIHtcbiAgICAgICAgdGVybWluYXRpb24gPSAnOjp0ZXh0W10nO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnQXJyYXknXG4gICAgICApIHtcbiAgICAgICAgdGVybWluYXRpb24gPSAnOjpqc29uYic7XG4gICAgICB9XG4gICAgICByZXR1cm4gYCQke2luZGV4ICsgMiArIGNvbHVtbnNBcnJheS5sZW5ndGh9JHt0ZXJtaW5hdGlvbn1gO1xuICAgIH0pO1xuICAgIGNvbnN0IGdlb1BvaW50c0luamVjdHMgPSBPYmplY3Qua2V5cyhnZW9Qb2ludHMpLm1hcChrZXkgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSBnZW9Qb2ludHNba2V5XTtcbiAgICAgIHZhbHVlc0FycmF5LnB1c2godmFsdWUubG9uZ2l0dWRlLCB2YWx1ZS5sYXRpdHVkZSk7XG4gICAgICBjb25zdCBsID0gdmFsdWVzQXJyYXkubGVuZ3RoICsgY29sdW1uc0FycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBgUE9JTlQoJCR7bH0sICQke2wgKyAxfSlgO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY29sdW1uc1BhdHRlcm4gPSBjb2x1bW5zQXJyYXlcbiAgICAgIC5tYXAoKGNvbCwgaW5kZXgpID0+IGAkJHtpbmRleCArIDJ9Om5hbWVgKVxuICAgICAgLmpvaW4oKTtcbiAgICBjb25zdCB2YWx1ZXNQYXR0ZXJuID0gaW5pdGlhbFZhbHVlcy5jb25jYXQoZ2VvUG9pbnRzSW5qZWN0cykuam9pbigpO1xuXG4gICAgY29uc3QgcXMgPSBgSU5TRVJUIElOVE8gJDE6bmFtZSAoJHtjb2x1bW5zUGF0dGVybn0pIFZBTFVFUyAoJHt2YWx1ZXNQYXR0ZXJufSlgO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtjbGFzc05hbWUsIC4uLmNvbHVtbnNBcnJheSwgLi4udmFsdWVzQXJyYXldO1xuICAgIGRlYnVnKHFzLCB2YWx1ZXMpO1xuICAgIGNvbnN0IHByb21pc2UgPSAodHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICAgID8gdHJhbnNhY3Rpb25hbFNlc3Npb24udFxuICAgICAgOiB0aGlzLl9jbGllbnRcbiAgICApXG4gICAgICAubm9uZShxcywgdmFsdWVzKVxuICAgICAgLnRoZW4oKCkgPT4gKHsgb3BzOiBbb2JqZWN0XSB9KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsXG4gICAgICAgICAgICAnQSBkdXBsaWNhdGUgdmFsdWUgZm9yIGEgZmllbGQgd2l0aCB1bmlxdWUgdmFsdWVzIHdhcyBwcm92aWRlZCdcbiAgICAgICAgICApO1xuICAgICAgICAgIGVyci51bmRlcmx5aW5nRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICBpZiAoZXJyb3IuY29uc3RyYWludCkge1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlcyA9IGVycm9yLmNvbnN0cmFpbnQubWF0Y2goL3VuaXF1ZV8oW2EtekEtWl0rKS8pO1xuICAgICAgICAgICAgaWYgKG1hdGNoZXMgJiYgQXJyYXkuaXNBcnJheShtYXRjaGVzKSkge1xuICAgICAgICAgICAgICBlcnIudXNlckluZm8gPSB7IGR1cGxpY2F0ZWRfZmllbGQ6IG1hdGNoZXNbMV0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgZXJyb3IgPSBlcnI7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgICBpZiAodHJhbnNhY3Rpb25hbFNlc3Npb24pIHtcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoLnB1c2gocHJvbWlzZSk7XG4gICAgfVxuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgLy8gUmVtb3ZlIGFsbCBvYmplY3RzIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIFBhcnNlIFF1ZXJ5LlxuICAvLyBJZiBubyBvYmplY3RzIG1hdGNoLCByZWplY3Qgd2l0aCBPQkpFQ1RfTk9UX0ZPVU5ELiBJZiBvYmplY3RzIGFyZSBmb3VuZCBhbmQgZGVsZXRlZCwgcmVzb2x2ZSB3aXRoIHVuZGVmaW5lZC5cbiAgLy8gSWYgdGhlcmUgaXMgc29tZSBvdGhlciBlcnJvciwgcmVqZWN0IHdpdGggSU5URVJOQUxfU0VSVkVSX0VSUk9SLlxuICBkZWxldGVPYmplY3RzQnlRdWVyeShcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgcXVlcnk6IFF1ZXJ5VHlwZSxcbiAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbjogP2FueVxuICApIHtcbiAgICBkZWJ1ZygnZGVsZXRlT2JqZWN0c0J5UXVlcnknLCBjbGFzc05hbWUsIHF1ZXJ5KTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBjb25zdCBpbmRleCA9IDI7XG4gICAgY29uc3Qgd2hlcmUgPSBidWlsZFdoZXJlQ2xhdXNlKHsgc2NoZW1hLCBpbmRleCwgcXVlcnkgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcbiAgICBpZiAoT2JqZWN0LmtleXMocXVlcnkpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgd2hlcmUucGF0dGVybiA9ICdUUlVFJztcbiAgICB9XG4gICAgY29uc3QgcXMgPSBgV0lUSCBkZWxldGVkIEFTIChERUxFVEUgRlJPTSAkMTpuYW1lIFdIRVJFICR7d2hlcmUucGF0dGVybn0gUkVUVVJOSU5HICopIFNFTEVDVCBjb3VudCgqKSBGUk9NIGRlbGV0ZWRgO1xuICAgIGRlYnVnKHFzLCB2YWx1ZXMpO1xuICAgIGNvbnN0IHByb21pc2UgPSAodHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICAgID8gdHJhbnNhY3Rpb25hbFNlc3Npb24udFxuICAgICAgOiB0aGlzLl9jbGllbnRcbiAgICApXG4gICAgICAub25lKHFzLCB2YWx1ZXMsIGEgPT4gK2EuY291bnQpXG4gICAgICAudGhlbihjb3VudCA9PiB7XG4gICAgICAgIGlmIChjb3VudCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gY291bnQ7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRUxTRTogRG9uJ3QgZGVsZXRlIGFueXRoaW5nIGlmIGRvZXNuJ3QgZXhpc3RcbiAgICAgIH0pO1xuICAgIGlmICh0cmFuc2FjdGlvbmFsU2Vzc2lvbikge1xuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gucHVzaChwcm9taXNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cbiAgLy8gUmV0dXJuIHZhbHVlIG5vdCBjdXJyZW50bHkgd2VsbCBzcGVjaWZpZWQuXG4gIGZpbmRPbmVBbmRVcGRhdGUoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBkZWJ1ZygnZmluZE9uZUFuZFVwZGF0ZScsIGNsYXNzTmFtZSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgICBjbGFzc05hbWUsXG4gICAgICBzY2hlbWEsXG4gICAgICBxdWVyeSxcbiAgICAgIHVwZGF0ZSxcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgKS50aGVuKHZhbCA9PiB2YWxbMF0pO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgdXBkYXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKTogUHJvbWlzZTxbYW55XT4ge1xuICAgIGRlYnVnKCd1cGRhdGVPYmplY3RzQnlRdWVyeScsIGNsYXNzTmFtZSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgY29uc3QgdXBkYXRlUGF0dGVybnMgPSBbXTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBsZXQgaW5kZXggPSAyO1xuICAgIHNjaGVtYSA9IHRvUG9zdGdyZXNTY2hlbWEoc2NoZW1hKTtcblxuICAgIGNvbnN0IG9yaWdpbmFsVXBkYXRlID0geyAuLi51cGRhdGUgfTtcblxuICAgIC8vIFNldCBmbGFnIGZvciBkb3Qgbm90YXRpb24gZmllbGRzXG4gICAgY29uc3QgZG90Tm90YXRpb25PcHRpb25zID0ge307XG4gICAgT2JqZWN0LmtleXModXBkYXRlKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+IC0xKSB7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBmaWVsZE5hbWUuc3BsaXQoJy4nKTtcbiAgICAgICAgY29uc3QgZmlyc3QgPSBjb21wb25lbnRzLnNoaWZ0KCk7XG4gICAgICAgIGRvdE5vdGF0aW9uT3B0aW9uc1tmaXJzdF0gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZG90Tm90YXRpb25PcHRpb25zW2ZpZWxkTmFtZV0gPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB1cGRhdGUgPSBoYW5kbGVEb3RGaWVsZHModXBkYXRlKTtcbiAgICAvLyBSZXNvbHZlIGF1dGhEYXRhIGZpcnN0LFxuICAgIC8vIFNvIHdlIGRvbid0IGVuZCB1cCB3aXRoIG11bHRpcGxlIGtleSB1cGRhdGVzXG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gdXBkYXRlKSB7XG4gICAgICBjb25zdCBhdXRoRGF0YU1hdGNoID0gZmllbGROYW1lLm1hdGNoKC9eX2F1dGhfZGF0YV8oW2EtekEtWjAtOV9dKykkLyk7XG4gICAgICBpZiAoYXV0aERhdGFNYXRjaCkge1xuICAgICAgICB2YXIgcHJvdmlkZXIgPSBhdXRoRGF0YU1hdGNoWzFdO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHVwZGF0ZVtmaWVsZE5hbWVdO1xuICAgICAgICBkZWxldGUgdXBkYXRlW2ZpZWxkTmFtZV07XG4gICAgICAgIHVwZGF0ZVsnYXV0aERhdGEnXSA9IHVwZGF0ZVsnYXV0aERhdGEnXSB8fCB7fTtcbiAgICAgICAgdXBkYXRlWydhdXRoRGF0YSddW3Byb3ZpZGVyXSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZmllbGROYW1lIGluIHVwZGF0ZSkge1xuICAgICAgY29uc3QgZmllbGRWYWx1ZSA9IHVwZGF0ZVtmaWVsZE5hbWVdO1xuICAgICAgLy8gRHJvcCBhbnkgdW5kZWZpbmVkIHZhbHVlcy5cbiAgICAgIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgZGVsZXRlIHVwZGF0ZVtmaWVsZE5hbWVdO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlID09PSBudWxsKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gTlVMTGApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZE5hbWUgPT0gJ2F1dGhEYXRhJykge1xuICAgICAgICAvLyBUaGlzIHJlY3Vyc2l2ZWx5IHNldHMgdGhlIGpzb25fb2JqZWN0XG4gICAgICAgIC8vIE9ubHkgMSBsZXZlbCBkZWVwXG4gICAgICAgIGNvbnN0IGdlbmVyYXRlID0gKGpzb25iOiBzdHJpbmcsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGBqc29uX29iamVjdF9zZXRfa2V5KENPQUxFU0NFKCR7anNvbmJ9LCAne30nOjpqc29uYiksICR7a2V5fSwgJHt2YWx1ZX0pOjpqc29uYmA7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGxhc3RLZXkgPSBgJCR7aW5kZXh9Om5hbWVgO1xuICAgICAgICBjb25zdCBmaWVsZE5hbWVJbmRleCA9IGluZGV4O1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICBjb25zdCB1cGRhdGUgPSBPYmplY3Qua2V5cyhmaWVsZFZhbHVlKS5yZWR1Y2UoXG4gICAgICAgICAgKGxhc3RLZXk6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IGdlbmVyYXRlKFxuICAgICAgICAgICAgICBsYXN0S2V5LFxuICAgICAgICAgICAgICBgJCR7aW5kZXh9Ojp0ZXh0YCxcbiAgICAgICAgICAgICAgYCQke2luZGV4ICsgMX06Ompzb25iYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBmaWVsZFZhbHVlW2tleV07XG4gICAgICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgaWYgKHZhbHVlLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBzdHI7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBsYXN0S2V5XG4gICAgICAgICk7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2ZpZWxkTmFtZUluZGV4fTpuYW1lID0gJHt1cGRhdGV9YCk7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ0luY3JlbWVudCcpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBgJCR7aW5kZXh9Om5hbWUgPSBDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgMCkgKyAkJHtpbmRleCArIDF9YFxuICAgICAgICApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUuYW1vdW50KTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS5fX29wID09PSAnQWRkJykge1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGAkJHtpbmRleH06bmFtZSA9IGFycmF5X2FkZChDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ1tdJzo6anNvbmIpLCAkJHtpbmRleCArXG4gICAgICAgICAgICAxfTo6anNvbmIpYFxuICAgICAgICApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUub2JqZWN0cykpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIG51bGwpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fb3AgPT09ICdSZW1vdmUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgYCQke2luZGV4fTpuYW1lID0gYXJyYXlfcmVtb3ZlKENPQUxFU0NFKCQke2luZGV4fTpuYW1lLCAnW10nOjpqc29uYiksICQke2luZGV4ICtcbiAgICAgICAgICAgIDF9Ojpqc29uYilgXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS5vYmplY3RzKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ0FkZFVuaXF1ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBgJCR7aW5kZXh9Om5hbWUgPSBhcnJheV9hZGRfdW5pcXVlKENPQUxFU0NFKCQke2luZGV4fTpuYW1lLCAnW10nOjpqc29uYiksICQke2luZGV4ICtcbiAgICAgICAgICAgIDF9Ojpqc29uYilgXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS5vYmplY3RzKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkTmFtZSA9PT0gJ3VwZGF0ZWRBdCcpIHtcbiAgICAgICAgLy9UT0RPOiBzdG9wIHNwZWNpYWwgY2FzaW5nIHRoaXMuIEl0IHNob3VsZCBjaGVjayBmb3IgX190eXBlID09PSAnRGF0ZScgYW5kIHVzZSAuaXNvXG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5vYmplY3RJZCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRGF0ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgdG9Qb3N0Z3Jlc1ZhbHVlKGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRmlsZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgdG9Qb3N0Z3Jlc1ZhbHVlKGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS5fX3R5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBgJCR7aW5kZXh9Om5hbWUgPSBQT0lOVCgkJHtpbmRleCArIDF9LCAkJHtpbmRleCArIDJ9KWBcbiAgICAgICAgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmxvbmdpdHVkZSwgZmllbGRWYWx1ZS5sYXRpdHVkZSk7XG4gICAgICAgIGluZGV4ICs9IDM7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0UG9seWdvblRvU1FMKGZpZWxkVmFsdWUuY29vcmRpbmF0ZXMpO1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCB2YWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgdHlwZW9mIGZpZWxkVmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ09iamVjdCdcbiAgICAgICkge1xuICAgICAgICAvLyBHYXRoZXIga2V5cyB0byBpbmNyZW1lbnRcbiAgICAgICAgY29uc3Qga2V5c1RvSW5jcmVtZW50ID0gT2JqZWN0LmtleXMob3JpZ2luYWxVcGRhdGUpXG4gICAgICAgICAgLmZpbHRlcihrID0+IHtcbiAgICAgICAgICAgIC8vIGNob29zZSB0b3AgbGV2ZWwgZmllbGRzIHRoYXQgaGF2ZSBhIGRlbGV0ZSBvcGVyYXRpb24gc2V0XG4gICAgICAgICAgICAvLyBOb3RlIHRoYXQgT2JqZWN0LmtleXMgaXMgaXRlcmF0aW5nIG92ZXIgdGhlICoqb3JpZ2luYWwqKiB1cGRhdGUgb2JqZWN0XG4gICAgICAgICAgICAvLyBhbmQgdGhhdCBzb21lIG9mIHRoZSBrZXlzIG9mIHRoZSBvcmlnaW5hbCB1cGRhdGUgY291bGQgYmUgbnVsbCBvciB1bmRlZmluZWQ6XG4gICAgICAgICAgICAvLyAoU2VlIHRoZSBhYm92ZSBjaGVjayBgaWYgKGZpZWxkVmFsdWUgPT09IG51bGwgfHwgdHlwZW9mIGZpZWxkVmFsdWUgPT0gXCJ1bmRlZmluZWRcIilgKVxuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvcmlnaW5hbFVwZGF0ZVtrXTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgIHZhbHVlICYmXG4gICAgICAgICAgICAgIHZhbHVlLl9fb3AgPT09ICdJbmNyZW1lbnQnICYmXG4gICAgICAgICAgICAgIGsuc3BsaXQoJy4nKS5sZW5ndGggPT09IDIgJiZcbiAgICAgICAgICAgICAgay5zcGxpdCgnLicpWzBdID09PSBmaWVsZE5hbWVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAubWFwKGsgPT4gay5zcGxpdCgnLicpWzFdKTtcblxuICAgICAgICBsZXQgaW5jcmVtZW50UGF0dGVybnMgPSAnJztcbiAgICAgICAgaWYgKGtleXNUb0luY3JlbWVudC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgaW5jcmVtZW50UGF0dGVybnMgPVxuICAgICAgICAgICAgJyB8fCAnICtcbiAgICAgICAgICAgIGtleXNUb0luY3JlbWVudFxuICAgICAgICAgICAgICAubWFwKGMgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFtb3VudCA9IGZpZWxkVmFsdWVbY10uYW1vdW50O1xuICAgICAgICAgICAgICAgIHJldHVybiBgQ09OQ0FUKCd7XCIke2N9XCI6JywgQ09BTEVTQ0UoJCR7aW5kZXh9Om5hbWUtPj4nJHtjfScsJzAnKTo6aW50ICsgJHthbW91bnR9LCAnfScpOjpqc29uYmA7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5qb2luKCcgfHwgJyk7XG4gICAgICAgICAgLy8gU3RyaXAgdGhlIGtleXNcbiAgICAgICAgICBrZXlzVG9JbmNyZW1lbnQuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIGZpZWxkVmFsdWVba2V5XTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGtleXNUb0RlbGV0ZTogQXJyYXk8c3RyaW5nPiA9IE9iamVjdC5rZXlzKG9yaWdpbmFsVXBkYXRlKVxuICAgICAgICAgIC5maWx0ZXIoayA9PiB7XG4gICAgICAgICAgICAvLyBjaG9vc2UgdG9wIGxldmVsIGZpZWxkcyB0aGF0IGhhdmUgYSBkZWxldGUgb3BlcmF0aW9uIHNldC5cbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gb3JpZ2luYWxVcGRhdGVba107XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICB2YWx1ZSAmJlxuICAgICAgICAgICAgICB2YWx1ZS5fX29wID09PSAnRGVsZXRlJyAmJlxuICAgICAgICAgICAgICBrLnNwbGl0KCcuJykubGVuZ3RoID09PSAyICYmXG4gICAgICAgICAgICAgIGsuc3BsaXQoJy4nKVswXSA9PT0gZmllbGROYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLm1hcChrID0+IGsuc3BsaXQoJy4nKVsxXSk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRlUGF0dGVybnMgPSBrZXlzVG9EZWxldGUucmVkdWNlKFxuICAgICAgICAgIChwOiBzdHJpbmcsIGM6IHN0cmluZywgaTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcCArIGAgLSAnJCR7aW5kZXggKyAxICsgaX06dmFsdWUnYDtcbiAgICAgICAgICB9LFxuICAgICAgICAgICcnXG4gICAgICAgICk7XG4gICAgICAgIC8vIE92ZXJyaWRlIE9iamVjdFxuICAgICAgICBsZXQgdXBkYXRlT2JqZWN0ID0gXCIne30nOjpqc29uYlwiO1xuXG4gICAgICAgIGlmIChkb3ROb3RhdGlvbk9wdGlvbnNbZmllbGROYW1lXSkge1xuICAgICAgICAgIC8vIE1lcmdlIE9iamVjdFxuICAgICAgICAgIHVwZGF0ZU9iamVjdCA9IGBDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ3t9Jzo6anNvbmIpYDtcbiAgICAgICAgfVxuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGAkJHtpbmRleH06bmFtZSA9ICgke3VwZGF0ZU9iamVjdH0gJHtkZWxldGVQYXR0ZXJuc30gJHtpbmNyZW1lbnRQYXR0ZXJuc30gfHwgJCR7aW5kZXggK1xuICAgICAgICAgICAgMSArXG4gICAgICAgICAgICBrZXlzVG9EZWxldGUubGVuZ3RofTo6anNvbmIgKWBcbiAgICAgICAgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCAuLi5rZXlzVG9EZWxldGUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMiArIGtleXNUb0RlbGV0ZS5sZW5ndGg7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBBcnJheS5pc0FycmF5KGZpZWxkVmFsdWUpICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0FycmF5J1xuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZSA9IHBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSk7XG4gICAgICAgIGlmIChleHBlY3RlZFR5cGUgPT09ICd0ZXh0W10nKSB7XG4gICAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9Ojp0ZXh0W11gKTtcbiAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9Ojpqc29uYmApO1xuICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZSkpO1xuICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlYnVnKCdOb3Qgc3VwcG9ydGVkIHVwZGF0ZScsIGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgYFBvc3RncmVzIGRvZXNuJ3Qgc3VwcG9ydCB1cGRhdGUgJHtKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKX0geWV0YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2UoeyBzY2hlbWEsIGluZGV4LCBxdWVyeSB9KTtcbiAgICB2YWx1ZXMucHVzaCguLi53aGVyZS52YWx1ZXMpO1xuXG4gICAgY29uc3Qgd2hlcmVDbGF1c2UgPVxuICAgICAgd2hlcmUucGF0dGVybi5sZW5ndGggPiAwID8gYFdIRVJFICR7d2hlcmUucGF0dGVybn1gIDogJyc7XG4gICAgY29uc3QgcXMgPSBgVVBEQVRFICQxOm5hbWUgU0VUICR7dXBkYXRlUGF0dGVybnMuam9pbigpfSAke3doZXJlQ2xhdXNlfSBSRVRVUk5JTkcgKmA7XG4gICAgZGVidWcoJ3VwZGF0ZTogJywgcXMsIHZhbHVlcyk7XG4gICAgY29uc3QgcHJvbWlzZSA9ICh0cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICAgPyB0cmFuc2FjdGlvbmFsU2Vzc2lvbi50XG4gICAgICA6IHRoaXMuX2NsaWVudFxuICAgICkuYW55KHFzLCB2YWx1ZXMpO1xuICAgIGlmICh0cmFuc2FjdGlvbmFsU2Vzc2lvbikge1xuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gucHVzaChwcm9taXNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cblxuICAvLyBIb3BlZnVsbHksIHdlIGNhbiBnZXQgcmlkIG9mIHRoaXMuIEl0J3Mgb25seSB1c2VkIGZvciBjb25maWcgYW5kIGhvb2tzLlxuICB1cHNlcnRPbmVPYmplY3QoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKSB7XG4gICAgZGVidWcoJ3Vwc2VydE9uZU9iamVjdCcsIHsgY2xhc3NOYW1lLCBxdWVyeSwgdXBkYXRlIH0pO1xuICAgIGNvbnN0IGNyZWF0ZVZhbHVlID0gT2JqZWN0LmFzc2lnbih7fSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlT2JqZWN0KFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgc2NoZW1hLFxuICAgICAgY3JlYXRlVmFsdWUsXG4gICAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgLy8gaWdub3JlIGR1cGxpY2F0ZSB2YWx1ZSBlcnJvcnMgYXMgaXQncyB1cHNlcnRcbiAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUpIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5maW5kT25lQW5kVXBkYXRlKFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHNjaGVtYSxcbiAgICAgICAgcXVlcnksXG4gICAgICAgIHVwZGF0ZSxcbiAgICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBmaW5kKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHsgc2tpcCwgbGltaXQsIHNvcnQsIGtleXMgfTogUXVlcnlPcHRpb25zXG4gICkge1xuICAgIGRlYnVnKCdmaW5kJywgY2xhc3NOYW1lLCBxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cyB9KTtcbiAgICBjb25zdCBoYXNMaW1pdCA9IGxpbWl0ICE9PSB1bmRlZmluZWQ7XG4gICAgY29uc3QgaGFzU2tpcCA9IHNraXAgIT09IHVuZGVmaW5lZDtcbiAgICBsZXQgdmFsdWVzID0gW2NsYXNzTmFtZV07XG4gICAgY29uc3Qgd2hlcmUgPSBidWlsZFdoZXJlQ2xhdXNlKHsgc2NoZW1hLCBxdWVyeSwgaW5kZXg6IDIgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcblxuICAgIGNvbnN0IHdoZXJlUGF0dGVybiA9XG4gICAgICB3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgPyBgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufWAgOiAnJztcbiAgICBjb25zdCBsaW1pdFBhdHRlcm4gPSBoYXNMaW1pdCA/IGBMSU1JVCAkJHt2YWx1ZXMubGVuZ3RoICsgMX1gIDogJyc7XG4gICAgaWYgKGhhc0xpbWl0KSB7XG4gICAgICB2YWx1ZXMucHVzaChsaW1pdCk7XG4gICAgfVxuICAgIGNvbnN0IHNraXBQYXR0ZXJuID0gaGFzU2tpcCA/IGBPRkZTRVQgJCR7dmFsdWVzLmxlbmd0aCArIDF9YCA6ICcnO1xuICAgIGlmIChoYXNTa2lwKSB7XG4gICAgICB2YWx1ZXMucHVzaChza2lwKTtcbiAgICB9XG5cbiAgICBsZXQgc29ydFBhdHRlcm4gPSAnJztcbiAgICBpZiAoc29ydCkge1xuICAgICAgY29uc3Qgc29ydENvcHk6IGFueSA9IHNvcnQ7XG4gICAgICBjb25zdCBzb3J0aW5nID0gT2JqZWN0LmtleXMoc29ydClcbiAgICAgICAgLm1hcChrZXkgPT4ge1xuICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybUtleSA9IHRyYW5zZm9ybURvdEZpZWxkVG9Db21wb25lbnRzKGtleSkuam9pbignLT4nKTtcbiAgICAgICAgICAvLyBVc2luZyAkaWR4IHBhdHRlcm4gZ2l2ZXM6ICBub24taW50ZWdlciBjb25zdGFudCBpbiBPUkRFUiBCWVxuICAgICAgICAgIGlmIChzb3J0Q29weVtrZXldID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gYCR7dHJhbnNmb3JtS2V5fSBBU0NgO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYCR7dHJhbnNmb3JtS2V5fSBERVNDYDtcbiAgICAgICAgfSlcbiAgICAgICAgLmpvaW4oKTtcbiAgICAgIHNvcnRQYXR0ZXJuID1cbiAgICAgICAgc29ydCAhPT0gdW5kZWZpbmVkICYmIE9iamVjdC5rZXlzKHNvcnQpLmxlbmd0aCA+IDBcbiAgICAgICAgICA/IGBPUkRFUiBCWSAke3NvcnRpbmd9YFxuICAgICAgICAgIDogJyc7XG4gICAgfVxuICAgIGlmICh3aGVyZS5zb3J0cyAmJiBPYmplY3Qua2V5cygod2hlcmUuc29ydHM6IGFueSkpLmxlbmd0aCA+IDApIHtcbiAgICAgIHNvcnRQYXR0ZXJuID0gYE9SREVSIEJZICR7d2hlcmUuc29ydHMuam9pbigpfWA7XG4gICAgfVxuXG4gICAgbGV0IGNvbHVtbnMgPSAnKic7XG4gICAgaWYgKGtleXMpIHtcbiAgICAgIC8vIEV4Y2x1ZGUgZW1wdHkga2V5c1xuICAgICAgLy8gUmVwbGFjZSBBQ0wgYnkgaXQncyBrZXlzXG4gICAgICBrZXlzID0ga2V5cy5yZWR1Y2UoKG1lbW8sIGtleSkgPT4ge1xuICAgICAgICBpZiAoa2V5ID09PSAnQUNMJykge1xuICAgICAgICAgIG1lbW8ucHVzaCgnX3JwZXJtJyk7XG4gICAgICAgICAgbWVtby5wdXNoKCdfd3Blcm0nKTtcbiAgICAgICAgfSBlbHNlIGlmIChrZXkubGVuZ3RoID4gMCkge1xuICAgICAgICAgIG1lbW8ucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgfSwgW10pO1xuICAgICAgY29sdW1ucyA9IGtleXNcbiAgICAgICAgLm1hcCgoa2V5LCBpbmRleCkgPT4ge1xuICAgICAgICAgIGlmIChrZXkgPT09ICckc2NvcmUnKSB7XG4gICAgICAgICAgICByZXR1cm4gYHRzX3JhbmtfY2QodG9fdHN2ZWN0b3IoJCR7Mn0sICQkezN9Om5hbWUpLCB0b190c3F1ZXJ5KCQkezR9LCAkJHs1fSksIDMyKSBhcyBzY29yZWA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgJCR7aW5kZXggKyB2YWx1ZXMubGVuZ3RoICsgMX06bmFtZWA7XG4gICAgICAgIH0pXG4gICAgICAgIC5qb2luKCk7XG4gICAgICB2YWx1ZXMgPSB2YWx1ZXMuY29uY2F0KGtleXMpO1xuICAgIH1cblxuICAgIGNvbnN0IHFzID0gYFNFTEVDVCAke2NvbHVtbnN9IEZST00gJDE6bmFtZSAke3doZXJlUGF0dGVybn0gJHtzb3J0UGF0dGVybn0gJHtsaW1pdFBhdHRlcm59ICR7c2tpcFBhdHRlcm59YDtcbiAgICBkZWJ1ZyhxcywgdmFsdWVzKTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAuYW55KHFzLCB2YWx1ZXMpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvLyBRdWVyeSBvbiBub24gZXhpc3RpbmcgdGFibGUsIGRvbid0IGNyYXNoXG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc1JlbGF0aW9uRG9lc05vdEV4aXN0RXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW107XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PlxuICAgICAgICByZXN1bHRzLm1hcChvYmplY3QgPT5cbiAgICAgICAgICB0aGlzLnBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKVxuICAgICAgICApXG4gICAgICApO1xuICB9XG5cbiAgLy8gQ29udmVydHMgZnJvbSBhIHBvc3RncmVzLWZvcm1hdCBvYmplY3QgdG8gYSBSRVNULWZvcm1hdCBvYmplY3QuXG4gIC8vIERvZXMgbm90IHN0cmlwIG91dCBhbnl0aGluZyBiYXNlZCBvbiBhIGxhY2sgb2YgYXV0aGVudGljYXRpb24uXG4gIHBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0OiBhbnksIHNjaGVtYTogYW55KSB7XG4gICAgT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcykuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcicgJiYgb2JqZWN0W2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgb2JqZWN0W2ZpZWxkTmFtZV0gPSB7XG4gICAgICAgICAgb2JqZWN0SWQ6IG9iamVjdFtmaWVsZE5hbWVdLFxuICAgICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgIGNsYXNzTmFtZTogc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnRhcmdldENsYXNzLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogJ1JlbGF0aW9uJyxcbiAgICAgICAgICBjbGFzc05hbWU6IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50YXJnZXRDbGFzcyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdHZW9Qb2ludCcsXG4gICAgICAgICAgbGF0aXR1ZGU6IG9iamVjdFtmaWVsZE5hbWVdLnksXG4gICAgICAgICAgbG9uZ2l0dWRlOiBvYmplY3RbZmllbGROYW1lXS54LFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgbGV0IGNvb3JkcyA9IG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgICBjb29yZHMgPSBjb29yZHMuc3Vic3RyKDIsIGNvb3Jkcy5sZW5ndGggLSA0KS5zcGxpdCgnKSwoJyk7XG4gICAgICAgIGNvb3JkcyA9IGNvb3Jkcy5tYXAocG9pbnQgPT4ge1xuICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBwYXJzZUZsb2F0KHBvaW50LnNwbGl0KCcsJylbMV0pLFxuICAgICAgICAgICAgcGFyc2VGbG9hdChwb2ludC5zcGxpdCgnLCcpWzBdKSxcbiAgICAgICAgICBdO1xuICAgICAgICB9KTtcbiAgICAgICAgb2JqZWN0W2ZpZWxkTmFtZV0gPSB7XG4gICAgICAgICAgX190eXBlOiAnUG9seWdvbicsXG4gICAgICAgICAgY29vcmRpbmF0ZXM6IGNvb3JkcyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0ZpbGUnKSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogJ0ZpbGUnLFxuICAgICAgICAgIG5hbWU6IG9iamVjdFtmaWVsZE5hbWVdLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0pO1xuICAgIC8vVE9ETzogcmVtb3ZlIHRoaXMgcmVsaWFuY2Ugb24gdGhlIG1vbmdvIGZvcm1hdC4gREIgYWRhcHRlciBzaG91bGRuJ3Qga25vdyB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgYmV0d2VlbiBjcmVhdGVkIGF0IGFuZCBhbnkgb3RoZXIgZGF0ZSBmaWVsZC5cbiAgICBpZiAob2JqZWN0LmNyZWF0ZWRBdCkge1xuICAgICAgb2JqZWN0LmNyZWF0ZWRBdCA9IG9iamVjdC5jcmVhdGVkQXQudG9JU09TdHJpbmcoKTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC51cGRhdGVkQXQpIHtcbiAgICAgIG9iamVjdC51cGRhdGVkQXQgPSBvYmplY3QudXBkYXRlZEF0LnRvSVNPU3RyaW5nKCk7XG4gICAgfVxuICAgIGlmIChvYmplY3QuZXhwaXJlc0F0KSB7XG4gICAgICBvYmplY3QuZXhwaXJlc0F0ID0ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBvYmplY3QuZXhwaXJlc0F0LnRvSVNPU3RyaW5nKCksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAob2JqZWN0Ll9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCkge1xuICAgICAgb2JqZWN0Ll9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCA9IHtcbiAgICAgICAgX190eXBlOiAnRGF0ZScsXG4gICAgICAgIGlzbzogb2JqZWN0Ll9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdC50b0lTT1N0cmluZygpLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQpIHtcbiAgICAgIG9iamVjdC5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQgPSB7XG4gICAgICAgIF9fdHlwZTogJ0RhdGUnLFxuICAgICAgICBpc286IG9iamVjdC5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQudG9JU09TdHJpbmcoKSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChvYmplY3QuX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCkge1xuICAgICAgb2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQgPSB7XG4gICAgICAgIF9fdHlwZTogJ0RhdGUnLFxuICAgICAgICBpc286IG9iamVjdC5fcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0LnRvSVNPU3RyaW5nKCksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAob2JqZWN0Ll9wYXNzd29yZF9jaGFuZ2VkX2F0KSB7XG4gICAgICBvYmplY3QuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSB7XG4gICAgICAgIF9fdHlwZTogJ0RhdGUnLFxuICAgICAgICBpc286IG9iamVjdC5fcGFzc3dvcmRfY2hhbmdlZF9hdC50b0lTT1N0cmluZygpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSA9PT0gbnVsbCkge1xuICAgICAgICBkZWxldGUgb2JqZWN0W2ZpZWxkTmFtZV07XG4gICAgICB9XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogJ0RhdGUnLFxuICAgICAgICAgIGlzbzogb2JqZWN0W2ZpZWxkTmFtZV0udG9JU09TdHJpbmcoKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG5cbiAgLy8gQ3JlYXRlIGEgdW5pcXVlIGluZGV4LiBVbmlxdWUgaW5kZXhlcyBvbiBudWxsYWJsZSBmaWVsZHMgYXJlIG5vdCBhbGxvd2VkLiBTaW5jZSB3ZSBkb24ndFxuICAvLyBjdXJyZW50bHkga25vdyB3aGljaCBmaWVsZHMgYXJlIG51bGxhYmxlIGFuZCB3aGljaCBhcmVuJ3QsIHdlIGlnbm9yZSB0aGF0IGNyaXRlcmlhLlxuICAvLyBBcyBzdWNoLCB3ZSBzaG91bGRuJ3QgZXhwb3NlIHRoaXMgZnVuY3Rpb24gdG8gdXNlcnMgb2YgcGFyc2UgdW50aWwgd2UgaGF2ZSBhbiBvdXQtb2YtYmFuZFxuICAvLyBXYXkgb2YgZGV0ZXJtaW5pbmcgaWYgYSBmaWVsZCBpcyBudWxsYWJsZS4gVW5kZWZpbmVkIGRvZXNuJ3QgY291bnQgYWdhaW5zdCB1bmlxdWVuZXNzLFxuICAvLyB3aGljaCBpcyB3aHkgd2UgdXNlIHNwYXJzZSBpbmRleGVzLlxuICBlbnN1cmVVbmlxdWVuZXNzKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBmaWVsZE5hbWVzOiBzdHJpbmdbXVxuICApIHtcbiAgICAvLyBVc2UgdGhlIHNhbWUgbmFtZSBmb3IgZXZlcnkgZW5zdXJlVW5pcXVlbmVzcyBhdHRlbXB0LCBiZWNhdXNlIHBvc3RncmVzXG4gICAgLy8gV2lsbCBoYXBwaWx5IGNyZWF0ZSB0aGUgc2FtZSBpbmRleCB3aXRoIG11bHRpcGxlIG5hbWVzLlxuICAgIGNvbnN0IGNvbnN0cmFpbnROYW1lID0gYHVuaXF1ZV8ke2ZpZWxkTmFtZXMuc29ydCgpLmpvaW4oJ18nKX1gO1xuICAgIGNvbnN0IGNvbnN0cmFpbnRQYXR0ZXJucyA9IGZpZWxkTmFtZXMubWFwKFxuICAgICAgKGZpZWxkTmFtZSwgaW5kZXgpID0+IGAkJHtpbmRleCArIDN9Om5hbWVgXG4gICAgKTtcbiAgICBjb25zdCBxcyA9IGBBTFRFUiBUQUJMRSAkMTpuYW1lIEFERCBDT05TVFJBSU5UICQyOm5hbWUgVU5JUVVFICgke2NvbnN0cmFpbnRQYXR0ZXJucy5qb2luKCl9KWA7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudFxuICAgICAgLm5vbmUocXMsIFtjbGFzc05hbWUsIGNvbnN0cmFpbnROYW1lLCAuLi5maWVsZE5hbWVzXSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBlcnJvci5jb2RlID09PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IgJiZcbiAgICAgICAgICBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKGNvbnN0cmFpbnROYW1lKVxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBJbmRleCBhbHJlYWR5IGV4aXN0cy4gSWdub3JlIGVycm9yLlxuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIGVycm9yLmNvZGUgPT09IFBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciAmJlxuICAgICAgICAgIGVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoY29uc3RyYWludE5hbWUpXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIENhc3QgdGhlIGVycm9yIGludG8gdGhlIHByb3BlciBwYXJzZSBlcnJvclxuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSxcbiAgICAgICAgICAgICdBIGR1cGxpY2F0ZSB2YWx1ZSBmb3IgYSBmaWVsZCB3aXRoIHVuaXF1ZSB2YWx1ZXMgd2FzIHByb3ZpZGVkJ1xuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gRXhlY3V0ZXMgYSBjb3VudC5cbiAgY291bnQoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgcmVhZFByZWZlcmVuY2U/OiBzdHJpbmcsXG4gICAgZXN0aW1hdGU/OiBib29sZWFuID0gdHJ1ZVxuICApIHtcbiAgICBkZWJ1ZygnY291bnQnLCBjbGFzc05hbWUsIHF1ZXJ5LCByZWFkUHJlZmVyZW5jZSwgZXN0aW1hdGUpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtjbGFzc05hbWVdO1xuICAgIGNvbnN0IHdoZXJlID0gYnVpbGRXaGVyZUNsYXVzZSh7IHNjaGVtYSwgcXVlcnksIGluZGV4OiAyIH0pO1xuICAgIHZhbHVlcy5wdXNoKC4uLndoZXJlLnZhbHVlcyk7XG5cbiAgICBjb25zdCB3aGVyZVBhdHRlcm4gPVxuICAgICAgd2hlcmUucGF0dGVybi5sZW5ndGggPiAwID8gYFdIRVJFICR7d2hlcmUucGF0dGVybn1gIDogJyc7XG4gICAgbGV0IHFzID0gJyc7XG5cbiAgICBpZiAod2hlcmUucGF0dGVybi5sZW5ndGggPiAwIHx8ICFlc3RpbWF0ZSkge1xuICAgICAgcXMgPSBgU0VMRUNUIGNvdW50KCopIEZST00gJDE6bmFtZSAke3doZXJlUGF0dGVybn1gO1xuICAgIH0gZWxzZSB7XG4gICAgICBxcyA9XG4gICAgICAgICdTRUxFQ1QgcmVsdHVwbGVzIEFTIGFwcHJveGltYXRlX3Jvd19jb3VudCBGUk9NIHBnX2NsYXNzIFdIRVJFIHJlbG5hbWUgPSAkMSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudFxuICAgICAgLm9uZShxcywgdmFsdWVzLCBhID0+IHtcbiAgICAgICAgaWYgKGEuYXBwcm94aW1hdGVfcm93X2NvdW50ICE9IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gK2EuYXBwcm94aW1hdGVfcm93X2NvdW50O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiArYS5jb3VudDtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc1JlbGF0aW9uRG9lc05vdEV4aXN0RXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH0pO1xuICB9XG5cbiAgZGlzdGluY3QoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgZmllbGROYW1lOiBzdHJpbmdcbiAgKSB7XG4gICAgZGVidWcoJ2Rpc3RpbmN0JywgY2xhc3NOYW1lLCBxdWVyeSk7XG4gICAgbGV0IGZpZWxkID0gZmllbGROYW1lO1xuICAgIGxldCBjb2x1bW4gPSBmaWVsZE5hbWU7XG4gICAgY29uc3QgaXNOZXN0ZWQgPSBmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDA7XG4gICAgaWYgKGlzTmVzdGVkKSB7XG4gICAgICBmaWVsZCA9IHRyYW5zZm9ybURvdEZpZWxkVG9Db21wb25lbnRzKGZpZWxkTmFtZSkuam9pbignLT4nKTtcbiAgICAgIGNvbHVtbiA9IGZpZWxkTmFtZS5zcGxpdCgnLicpWzBdO1xuICAgIH1cbiAgICBjb25zdCBpc0FycmF5RmllbGQgPVxuICAgICAgc2NoZW1hLmZpZWxkcyAmJlxuICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmXG4gICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0FycmF5JztcbiAgICBjb25zdCBpc1BvaW50ZXJGaWVsZCA9XG4gICAgICBzY2hlbWEuZmllbGRzICYmXG4gICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiZcbiAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcic7XG4gICAgY29uc3QgdmFsdWVzID0gW2ZpZWxkLCBjb2x1bW4sIGNsYXNzTmFtZV07XG4gICAgY29uc3Qgd2hlcmUgPSBidWlsZFdoZXJlQ2xhdXNlKHsgc2NoZW1hLCBxdWVyeSwgaW5kZXg6IDQgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcblxuICAgIGNvbnN0IHdoZXJlUGF0dGVybiA9XG4gICAgICB3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgPyBgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufWAgOiAnJztcbiAgICBjb25zdCB0cmFuc2Zvcm1lciA9IGlzQXJyYXlGaWVsZCA/ICdqc29uYl9hcnJheV9lbGVtZW50cycgOiAnT04nO1xuICAgIGxldCBxcyA9IGBTRUxFQ1QgRElTVElOQ1QgJHt0cmFuc2Zvcm1lcn0oJDE6bmFtZSkgJDI6bmFtZSBGUk9NICQzOm5hbWUgJHt3aGVyZVBhdHRlcm59YDtcbiAgICBpZiAoaXNOZXN0ZWQpIHtcbiAgICAgIHFzID0gYFNFTEVDVCBESVNUSU5DVCAke3RyYW5zZm9ybWVyfSgkMTpyYXcpICQyOnJhdyBGUk9NICQzOm5hbWUgJHt3aGVyZVBhdHRlcm59YDtcbiAgICB9XG4gICAgZGVidWcocXMsIHZhbHVlcyk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudFxuICAgICAgLmFueShxcywgdmFsdWVzKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAoIWlzTmVzdGVkKSB7XG4gICAgICAgICAgcmVzdWx0cyA9IHJlc3VsdHMuZmlsdGVyKG9iamVjdCA9PiBvYmplY3RbZmllbGRdICE9PSBudWxsKTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICAgIGlmICghaXNQb2ludGVyRmllbGQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdFtmaWVsZF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgICAgICAgY2xhc3NOYW1lOiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICAgIG9iamVjdElkOiBvYmplY3RbZmllbGRdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGlsZCA9IGZpZWxkTmFtZS5zcGxpdCgnLicpWzFdO1xuICAgICAgICByZXR1cm4gcmVzdWx0cy5tYXAob2JqZWN0ID0+IG9iamVjdFtjb2x1bW5dW2NoaWxkXSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PlxuICAgICAgICByZXN1bHRzLm1hcChvYmplY3QgPT5cbiAgICAgICAgICB0aGlzLnBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKVxuICAgICAgICApXG4gICAgICApO1xuICB9XG5cbiAgYWdncmVnYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSkge1xuICAgIGRlYnVnKCdhZ2dyZWdhdGUnLCBjbGFzc05hbWUsIHBpcGVsaW5lKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBsZXQgaW5kZXg6IG51bWJlciA9IDI7XG4gICAgbGV0IGNvbHVtbnM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IGNvdW50RmllbGQgPSBudWxsO1xuICAgIGxldCBncm91cFZhbHVlcyA9IG51bGw7XG4gICAgbGV0IHdoZXJlUGF0dGVybiA9ICcnO1xuICAgIGxldCBsaW1pdFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc2tpcFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc29ydFBhdHRlcm4gPSAnJztcbiAgICBsZXQgZ3JvdXBQYXR0ZXJuID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwaXBlbGluZS5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY29uc3Qgc3RhZ2UgPSBwaXBlbGluZVtpXTtcbiAgICAgIGlmIChzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRncm91cFtmaWVsZF07XG4gICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZmllbGQgPT09ICdfaWQnICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUgIT09ICcnKSB7XG4gICAgICAgICAgICBjb2x1bW5zLnB1c2goYCQke2luZGV4fTpuYW1lIEFTIFwib2JqZWN0SWRcImApO1xuICAgICAgICAgICAgZ3JvdXBQYXR0ZXJuID0gYEdST1VQIEJZICQke2luZGV4fTpuYW1lYDtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlKSk7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGZpZWxkID09PSAnX2lkJyAmJlxuICAgICAgICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgICAgT2JqZWN0LmtleXModmFsdWUpLmxlbmd0aCAhPT0gMFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZ3JvdXBWYWx1ZXMgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwQnlGaWVsZHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYWxpYXMgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gT2JqZWN0LmtleXModmFsdWVbYWxpYXNdKVswXTtcbiAgICAgICAgICAgICAgY29uc3Qgc291cmNlID0gdHJhbnNmb3JtQWdncmVnYXRlRmllbGQodmFsdWVbYWxpYXNdW29wZXJhdGlvbl0pO1xuICAgICAgICAgICAgICBpZiAobW9uZ29BZ2dyZWdhdGVUb1Bvc3RncmVzW29wZXJhdGlvbl0pIHtcbiAgICAgICAgICAgICAgICBpZiAoIWdyb3VwQnlGaWVsZHMuaW5jbHVkZXMoYFwiJHtzb3VyY2V9XCJgKSkge1xuICAgICAgICAgICAgICAgICAgZ3JvdXBCeUZpZWxkcy5wdXNoKGBcIiR7c291cmNlfVwiYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbHVtbnMucHVzaChcbiAgICAgICAgICAgICAgICAgIGBFWFRSQUNUKCR7XG4gICAgICAgICAgICAgICAgICAgIG1vbmdvQWdncmVnYXRlVG9Qb3N0Z3Jlc1tvcGVyYXRpb25dXG4gICAgICAgICAgICAgICAgICB9IEZST00gJCR7aW5kZXh9Om5hbWUgQVQgVElNRSBaT05FICdVVEMnKSBBUyAkJHtpbmRleCArXG4gICAgICAgICAgICAgICAgICAgIDF9Om5hbWVgXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChzb3VyY2UsIGFsaWFzKTtcbiAgICAgICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBncm91cFBhdHRlcm4gPSBgR1JPVVAgQlkgJCR7aW5kZXh9OnJhd2A7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChncm91cEJ5RmllbGRzLmpvaW4oKSk7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUuJHN1bSkge1xuICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlLiRzdW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKGBTVU0oJCR7aW5kZXh9Om5hbWUpIEFTICQke2luZGV4ICsgMX06bmFtZWApO1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRzdW0pLCBmaWVsZCk7XG4gICAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3VudEZpZWxkID0gZmllbGQ7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKGBDT1VOVCgqKSBBUyAkJHtpbmRleH06bmFtZWApO1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJG1heCkge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYE1BWCgkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRtYXgpLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJG1pbikge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYE1JTigkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRtaW4pLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJGF2Zykge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYEFWRygkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRhdmcpLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2x1bW5zLnB1c2goJyonKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kcHJvamVjdCkge1xuICAgICAgICBpZiAoY29sdW1ucy5pbmNsdWRlcygnKicpKSB7XG4gICAgICAgICAgY29sdW1ucyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gc3RhZ2UuJHByb2plY3QpIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRwcm9qZWN0W2ZpZWxkXTtcbiAgICAgICAgICBpZiAodmFsdWUgPT09IDEgfHwgdmFsdWUgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbHVtbnMucHVzaChgJCR7aW5kZXh9Om5hbWVgKTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gW107XG4gICAgICAgIGNvbnN0IG9yT3JBbmQgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoXG4gICAgICAgICAgc3RhZ2UuJG1hdGNoLFxuICAgICAgICAgICckb3InXG4gICAgICAgIClcbiAgICAgICAgICA/ICcgT1IgJ1xuICAgICAgICAgIDogJyBBTkQgJztcblxuICAgICAgICBpZiAoc3RhZ2UuJG1hdGNoLiRvcikge1xuICAgICAgICAgIGNvbnN0IGNvbGxhcHNlID0ge307XG4gICAgICAgICAgc3RhZ2UuJG1hdGNoLiRvci5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZWxlbWVudCkge1xuICAgICAgICAgICAgICBjb2xsYXBzZVtrZXldID0gZWxlbWVudFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHN0YWdlLiRtYXRjaCA9IGNvbGxhcHNlO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBzdGFnZS4kbWF0Y2hbZmllbGRdO1xuICAgICAgICAgIGNvbnN0IG1hdGNoUGF0dGVybnMgPSBbXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3IpLmZvckVhY2goY21wID0+IHtcbiAgICAgICAgICAgIGlmICh2YWx1ZVtjbXBdKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHBnQ29tcGFyYXRvciA9IFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcltjbXBdO1xuICAgICAgICAgICAgICBtYXRjaFBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICAgICAgYCQke2luZGV4fTpuYW1lICR7cGdDb21wYXJhdG9yfSAkJHtpbmRleCArIDF9YFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZCwgdG9Qb3N0Z3Jlc1ZhbHVlKHZhbHVlW2NtcF0pKTtcbiAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAobWF0Y2hQYXR0ZXJucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAoJHttYXRjaFBhdHRlcm5zLmpvaW4oJyBBTkQgJyl9KWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJlxuICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSAmJlxuICAgICAgICAgICAgbWF0Y2hQYXR0ZXJucy5sZW5ndGggPT09IDBcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goZmllbGQsIHZhbHVlKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHdoZXJlUGF0dGVybiA9XG4gICAgICAgICAgcGF0dGVybnMubGVuZ3RoID4gMCA/IGBXSEVSRSAke3BhdHRlcm5zLmpvaW4oYCAke29yT3JBbmR9IGApfWAgOiAnJztcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kbGltaXQpIHtcbiAgICAgICAgbGltaXRQYXR0ZXJuID0gYExJTUlUICQke2luZGV4fWA7XG4gICAgICAgIHZhbHVlcy5wdXNoKHN0YWdlLiRsaW1pdCk7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJHNraXApIHtcbiAgICAgICAgc2tpcFBhdHRlcm4gPSBgT0ZGU0VUICQke2luZGV4fWA7XG4gICAgICAgIHZhbHVlcy5wdXNoKHN0YWdlLiRza2lwKTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kc29ydCkge1xuICAgICAgICBjb25zdCBzb3J0ID0gc3RhZ2UuJHNvcnQ7XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhzb3J0KTtcbiAgICAgICAgY29uc3Qgc29ydGluZyA9IGtleXNcbiAgICAgICAgICAubWFwKGtleSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1lciA9IHNvcnRba2V5XSA9PT0gMSA/ICdBU0MnIDogJ0RFU0MnO1xuICAgICAgICAgICAgY29uc3Qgb3JkZXIgPSBgJCR7aW5kZXh9Om5hbWUgJHt0cmFuc2Zvcm1lcn1gO1xuICAgICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICAgIHJldHVybiBvcmRlcjtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5qb2luKCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKC4uLmtleXMpO1xuICAgICAgICBzb3J0UGF0dGVybiA9XG4gICAgICAgICAgc29ydCAhPT0gdW5kZWZpbmVkICYmIHNvcnRpbmcubGVuZ3RoID4gMCA/IGBPUkRFUiBCWSAke3NvcnRpbmd9YCA6ICcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHFzID0gYFNFTEVDVCAke2NvbHVtbnMuam9pbigpfSBGUk9NICQxOm5hbWUgJHt3aGVyZVBhdHRlcm59ICR7c29ydFBhdHRlcm59ICR7bGltaXRQYXR0ZXJufSAke3NraXBQYXR0ZXJufSAke2dyb3VwUGF0dGVybn1gO1xuICAgIGRlYnVnKHFzLCB2YWx1ZXMpO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnRcbiAgICAgIC5tYXAocXMsIHZhbHVlcywgYSA9PlxuICAgICAgICB0aGlzLnBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIGEsIHNjaGVtYSlcbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICByZXN1bHRzLmZvckVhY2gocmVzdWx0ID0+IHtcbiAgICAgICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsICdvYmplY3RJZCcpKSB7XG4gICAgICAgICAgICByZXN1bHQub2JqZWN0SWQgPSBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZ3JvdXBWYWx1ZXMpIHtcbiAgICAgICAgICAgIHJlc3VsdC5vYmplY3RJZCA9IHt9O1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZ3JvdXBWYWx1ZXMpIHtcbiAgICAgICAgICAgICAgcmVzdWx0Lm9iamVjdElkW2tleV0gPSByZXN1bHRba2V5XTtcbiAgICAgICAgICAgICAgZGVsZXRlIHJlc3VsdFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY291bnRGaWVsZCkge1xuICAgICAgICAgICAgcmVzdWx0W2NvdW50RmllbGRdID0gcGFyc2VJbnQocmVzdWx0W2NvdW50RmllbGRdLCAxMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1Jbml0aWFsaXphdGlvbih7IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMgfTogYW55KSB7XG4gICAgLy8gVE9ETzogVGhpcyBtZXRob2QgbmVlZHMgdG8gYmUgcmV3cml0dGVuIHRvIG1ha2UgcHJvcGVyIHVzZSBvZiBjb25uZWN0aW9ucyAoQHZpdGFseS10KVxuICAgIGRlYnVnKCdwZXJmb3JtSW5pdGlhbGl6YXRpb24nKTtcbiAgICBjb25zdCBwcm9taXNlcyA9IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMubWFwKHNjaGVtYSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5jcmVhdGVUYWJsZShzY2hlbWEuY2xhc3NOYW1lLCBzY2hlbWEpXG4gICAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGVyci5jb2RlID09PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IgfHxcbiAgICAgICAgICAgIGVyci5jb2RlID09PSBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUVcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB0aGlzLnNjaGVtYVVwZ3JhZGUoc2NoZW1hLmNsYXNzTmFtZSwgc2NoZW1hKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xpZW50LnR4KCdwZXJmb3JtLWluaXRpYWxpemF0aW9uJywgdCA9PiB7XG4gICAgICAgICAgcmV0dXJuIHQuYmF0Y2goW1xuICAgICAgICAgICAgdC5ub25lKHNxbC5taXNjLmpzb25PYmplY3RTZXRLZXlzKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuYWRkKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuYWRkVW5pcXVlKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkucmVtb3ZlKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuY29udGFpbnNBbGwpLFxuICAgICAgICAgICAgdC5ub25lKHNxbC5hcnJheS5jb250YWluc0FsbFJlZ2V4KSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuY29udGFpbnMpLFxuICAgICAgICAgIF0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbihkYXRhID0+IHtcbiAgICAgICAgZGVidWcoYGluaXRpYWxpemF0aW9uRG9uZSBpbiAke2RhdGEuZHVyYXRpb259YCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZywgaW5kZXhlczogYW55LCBjb25uOiA/YW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIChjb25uIHx8IHRoaXMuX2NsaWVudCkudHgodCA9PlxuICAgICAgdC5iYXRjaChcbiAgICAgICAgaW5kZXhlcy5tYXAoaSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHQubm9uZSgnQ1JFQVRFIElOREVYICQxOm5hbWUgT04gJDI6bmFtZSAoJDM6bmFtZSknLCBbXG4gICAgICAgICAgICBpLm5hbWUsXG4gICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICBpLmtleSxcbiAgICAgICAgICBdKTtcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlc0lmTmVlZGVkKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGZpZWxkTmFtZTogc3RyaW5nLFxuICAgIHR5cGU6IGFueSxcbiAgICBjb25uOiA/YW55XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiAoY29ubiB8fCB0aGlzLl9jbGllbnQpLm5vbmUoXG4gICAgICAnQ1JFQVRFIElOREVYICQxOm5hbWUgT04gJDI6bmFtZSAoJDM6bmFtZSknLFxuICAgICAgW2ZpZWxkTmFtZSwgY2xhc3NOYW1lLCB0eXBlXVxuICAgICk7XG4gIH1cblxuICBkcm9wSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZywgaW5kZXhlczogYW55LCBjb25uOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBxdWVyaWVzID0gaW5kZXhlcy5tYXAoaSA9PiAoe1xuICAgICAgcXVlcnk6ICdEUk9QIElOREVYICQxOm5hbWUnLFxuICAgICAgdmFsdWVzOiBpLFxuICAgIH0pKTtcbiAgICByZXR1cm4gKGNvbm4gfHwgdGhpcy5fY2xpZW50KS50eCh0ID0+XG4gICAgICB0Lm5vbmUodGhpcy5fcGdwLmhlbHBlcnMuY29uY2F0KHF1ZXJpZXMpKVxuICAgICk7XG4gIH1cblxuICBnZXRJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcXMgPSAnU0VMRUNUICogRlJPTSBwZ19pbmRleGVzIFdIRVJFIHRhYmxlbmFtZSA9ICR7Y2xhc3NOYW1lfSc7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5hbnkocXMsIHsgY2xhc3NOYW1lIH0pO1xuICB9XG5cbiAgdXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgLy8gVXNlZCBmb3IgdGVzdGluZyBwdXJwb3Nlc1xuICB1cGRhdGVFc3RpbWF0ZWRDb3VudChjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQubm9uZSgnQU5BTFlaRSAkMTpuYW1lJywgW2NsYXNzTmFtZV0pO1xuICB9XG5cbiAgY3JlYXRlVHJhbnNhY3Rpb25hbFNlc3Npb24oKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbmFsU2Vzc2lvbiA9IHt9O1xuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzdWx0ID0gdGhpcy5fY2xpZW50LnR4KHQgPT4ge1xuICAgICAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbi50ID0gdDtcbiAgICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucHJvbWlzZSA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICB9KTtcbiAgICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2ggPSBbXTtcbiAgICAgICAgcmVzb2x2ZSh0cmFuc2FjdGlvbmFsU2Vzc2lvbik7XG4gICAgICAgIHJldHVybiB0cmFuc2FjdGlvbmFsU2Vzc2lvbi5wcm9taXNlO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBjb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbih0cmFuc2FjdGlvbmFsU2Vzc2lvbjogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzb2x2ZShcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnQuYmF0Y2godHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gpXG4gICAgKTtcbiAgICByZXR1cm4gdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzdWx0O1xuICB9XG5cbiAgYWJvcnRUcmFuc2FjdGlvbmFsU2Vzc2lvbih0cmFuc2FjdGlvbmFsU2Vzc2lvbjogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzdWx0LmNhdGNoKCk7XG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gucHVzaChQcm9taXNlLnJlamVjdCgpKTtcbiAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbi5yZXNvbHZlKFxuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24udC5iYXRjaCh0cmFuc2FjdGlvbmFsU2Vzc2lvbi5iYXRjaClcbiAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udmVydFBvbHlnb25Ub1NRTChwb2x5Z29uKSB7XG4gIGlmIChwb2x5Z29uLmxlbmd0aCA8IDMpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICBgUG9seWdvbiBtdXN0IGhhdmUgYXQgbGVhc3QgMyB2YWx1ZXNgXG4gICAgKTtcbiAgfVxuICBpZiAoXG4gICAgcG9seWdvblswXVswXSAhPT0gcG9seWdvbltwb2x5Z29uLmxlbmd0aCAtIDFdWzBdIHx8XG4gICAgcG9seWdvblswXVsxXSAhPT0gcG9seWdvbltwb2x5Z29uLmxlbmd0aCAtIDFdWzFdXG4gICkge1xuICAgIHBvbHlnb24ucHVzaChwb2x5Z29uWzBdKTtcbiAgfVxuICBjb25zdCB1bmlxdWUgPSBwb2x5Z29uLmZpbHRlcigoaXRlbSwgaW5kZXgsIGFyKSA9PiB7XG4gICAgbGV0IGZvdW5kSW5kZXggPSAtMTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICBjb25zdCBwdCA9IGFyW2ldO1xuICAgICAgaWYgKHB0WzBdID09PSBpdGVtWzBdICYmIHB0WzFdID09PSBpdGVtWzFdKSB7XG4gICAgICAgIGZvdW5kSW5kZXggPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kSW5kZXggPT09IGluZGV4O1xuICB9KTtcbiAgaWYgKHVuaXF1ZS5sZW5ndGggPCAzKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgJ0dlb0pTT046IExvb3AgbXVzdCBoYXZlIGF0IGxlYXN0IDMgZGlmZmVyZW50IHZlcnRpY2VzJ1xuICAgICk7XG4gIH1cbiAgY29uc3QgcG9pbnRzID0gcG9seWdvblxuICAgIC5tYXAocG9pbnQgPT4ge1xuICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBhcnNlRmxvYXQocG9pbnRbMV0pLCBwYXJzZUZsb2F0KHBvaW50WzBdKSk7XG4gICAgICByZXR1cm4gYCgke3BvaW50WzFdfSwgJHtwb2ludFswXX0pYDtcbiAgICB9KVxuICAgIC5qb2luKCcsICcpO1xuICByZXR1cm4gYCgke3BvaW50c30pYDtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlV2hpdGVTcGFjZShyZWdleCkge1xuICBpZiAoIXJlZ2V4LmVuZHNXaXRoKCdcXG4nKSkge1xuICAgIHJlZ2V4ICs9ICdcXG4nO1xuICB9XG5cbiAgLy8gcmVtb3ZlIG5vbiBlc2NhcGVkIGNvbW1lbnRzXG4gIHJldHVybiAoXG4gICAgcmVnZXhcbiAgICAgIC5yZXBsYWNlKC8oW15cXFxcXSkjLipcXG4vZ2ltLCAnJDEnKVxuICAgICAgLy8gcmVtb3ZlIGxpbmVzIHN0YXJ0aW5nIHdpdGggYSBjb21tZW50XG4gICAgICAucmVwbGFjZSgvXiMuKlxcbi9naW0sICcnKVxuICAgICAgLy8gcmVtb3ZlIG5vbiBlc2NhcGVkIHdoaXRlc3BhY2VcbiAgICAgIC5yZXBsYWNlKC8oW15cXFxcXSlcXHMrL2dpbSwgJyQxJylcbiAgICAgIC8vIHJlbW92ZSB3aGl0ZXNwYWNlIGF0IHRoZSBiZWdpbm5pbmcgb2YgYSBsaW5lXG4gICAgICAucmVwbGFjZSgvXlxccysvLCAnJylcbiAgICAgIC50cmltKClcbiAgKTtcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1JlZ2V4UGF0dGVybihzKSB7XG4gIGlmIChzICYmIHMuc3RhcnRzV2l0aCgnXicpKSB7XG4gICAgLy8gcmVnZXggZm9yIHN0YXJ0c1dpdGhcbiAgICByZXR1cm4gJ14nICsgbGl0ZXJhbGl6ZVJlZ2V4UGFydChzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIGlmIChzICYmIHMuZW5kc1dpdGgoJyQnKSkge1xuICAgIC8vIHJlZ2V4IGZvciBlbmRzV2l0aFxuICAgIHJldHVybiBsaXRlcmFsaXplUmVnZXhQYXJ0KHMuc2xpY2UoMCwgcy5sZW5ndGggLSAxKSkgKyAnJCc7XG4gIH1cblxuICAvLyByZWdleCBmb3IgY29udGFpbnNcbiAgcmV0dXJuIGxpdGVyYWxpemVSZWdleFBhcnQocyk7XG59XG5cbmZ1bmN0aW9uIGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlKSB7XG4gIGlmICghdmFsdWUgfHwgdHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCAhdmFsdWUuc3RhcnRzV2l0aCgnXicpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgbWF0Y2hlcyA9IHZhbHVlLm1hdGNoKC9cXF5cXFxcUS4qXFxcXEUvKTtcbiAgcmV0dXJuICEhbWF0Y2hlcztcbn1cblxuZnVuY3Rpb24gaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSh2YWx1ZXMpIHtcbiAgaWYgKCF2YWx1ZXMgfHwgIUFycmF5LmlzQXJyYXkodmFsdWVzKSB8fCB2YWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBmaXJzdFZhbHVlc0lzUmVnZXggPSBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZXNbMF0uJHJlZ2V4KTtcbiAgaWYgKHZhbHVlcy5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZXNJc1JlZ2V4O1xuICB9XG5cbiAgZm9yIChsZXQgaSA9IDEsIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGg7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGlmIChmaXJzdFZhbHVlc0lzUmVnZXggIT09IGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlc1tpXS4kcmVnZXgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzQW55VmFsdWVSZWdleFN0YXJ0c1dpdGgodmFsdWVzKSB7XG4gIHJldHVybiB2YWx1ZXMuc29tZShmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZS4kcmVnZXgpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlTGl0ZXJhbFJlZ2V4KHJlbWFpbmluZykge1xuICByZXR1cm4gcmVtYWluaW5nXG4gICAgLnNwbGl0KCcnKVxuICAgIC5tYXAoYyA9PiB7XG4gICAgICBjb25zdCByZWdleCA9IFJlZ0V4cCgnWzAtOSBdfFxcXFxwe0x9JywgJ3UnKTsgLy8gU3VwcG9ydCBhbGwgdW5pY29kZSBsZXR0ZXIgY2hhcnNcbiAgICAgIGlmIChjLm1hdGNoKHJlZ2V4KSAhPT0gbnVsbCkge1xuICAgICAgICAvLyBkb24ndCBlc2NhcGUgYWxwaGFudW1lcmljIGNoYXJhY3RlcnNcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgICB9XG4gICAgICAvLyBlc2NhcGUgZXZlcnl0aGluZyBlbHNlIChzaW5nbGUgcXVvdGVzIHdpdGggc2luZ2xlIHF1b3RlcywgZXZlcnl0aGluZyBlbHNlIHdpdGggYSBiYWNrc2xhc2gpXG4gICAgICByZXR1cm4gYyA9PT0gYCdgID8gYCcnYCA6IGBcXFxcJHtjfWA7XG4gICAgfSlcbiAgICAuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIGxpdGVyYWxpemVSZWdleFBhcnQoczogc3RyaW5nKSB7XG4gIGNvbnN0IG1hdGNoZXIxID0gL1xcXFxRKCg/IVxcXFxFKS4qKVxcXFxFJC87XG4gIGNvbnN0IHJlc3VsdDE6IGFueSA9IHMubWF0Y2gobWF0Y2hlcjEpO1xuICBpZiAocmVzdWx0MSAmJiByZXN1bHQxLmxlbmd0aCA+IDEgJiYgcmVzdWx0MS5pbmRleCA+IC0xKSB7XG4gICAgLy8gcHJvY2VzcyByZWdleCB0aGF0IGhhcyBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIHNwZWNpZmllZCBmb3IgdGhlIGxpdGVyYWwgdGV4dFxuICAgIGNvbnN0IHByZWZpeCA9IHMuc3Vic3RyKDAsIHJlc3VsdDEuaW5kZXgpO1xuICAgIGNvbnN0IHJlbWFpbmluZyA9IHJlc3VsdDFbMV07XG5cbiAgICByZXR1cm4gbGl0ZXJhbGl6ZVJlZ2V4UGFydChwcmVmaXgpICsgY3JlYXRlTGl0ZXJhbFJlZ2V4KHJlbWFpbmluZyk7XG4gIH1cblxuICAvLyBwcm9jZXNzIHJlZ2V4IHRoYXQgaGFzIGEgYmVnaW5uaW5nIHNwZWNpZmllZCBmb3IgdGhlIGxpdGVyYWwgdGV4dFxuICBjb25zdCBtYXRjaGVyMiA9IC9cXFxcUSgoPyFcXFxcRSkuKikkLztcbiAgY29uc3QgcmVzdWx0MjogYW55ID0gcy5tYXRjaChtYXRjaGVyMik7XG4gIGlmIChyZXN1bHQyICYmIHJlc3VsdDIubGVuZ3RoID4gMSAmJiByZXN1bHQyLmluZGV4ID4gLTEpIHtcbiAgICBjb25zdCBwcmVmaXggPSBzLnN1YnN0cigwLCByZXN1bHQyLmluZGV4KTtcbiAgICBjb25zdCByZW1haW5pbmcgPSByZXN1bHQyWzFdO1xuXG4gICAgcmV0dXJuIGxpdGVyYWxpemVSZWdleFBhcnQocHJlZml4KSArIGNyZWF0ZUxpdGVyYWxSZWdleChyZW1haW5pbmcpO1xuICB9XG5cbiAgLy8gcmVtb3ZlIGFsbCBpbnN0YW5jZXMgb2YgXFxRIGFuZCBcXEUgZnJvbSB0aGUgcmVtYWluaW5nIHRleHQgJiBlc2NhcGUgc2luZ2xlIHF1b3Rlc1xuICByZXR1cm4gc1xuICAgIC5yZXBsYWNlKC8oW15cXFxcXSkoXFxcXEUpLywgJyQxJylcbiAgICAucmVwbGFjZSgvKFteXFxcXF0pKFxcXFxRKS8sICckMScpXG4gICAgLnJlcGxhY2UoL15cXFxcRS8sICcnKVxuICAgIC5yZXBsYWNlKC9eXFxcXFEvLCAnJylcbiAgICAucmVwbGFjZSgvKFteJ10pJy8sIGAkMScnYClcbiAgICAucmVwbGFjZSgvXicoW14nXSkvLCBgJyckMWApO1xufVxuXG52YXIgR2VvUG9pbnRDb2RlciA9IHtcbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZS5fX3R5cGUgPT09ICdHZW9Qb2ludCdcbiAgICApO1xuICB9LFxufTtcblxuZXhwb3J0IGRlZmF1bHQgUG9zdGdyZXNTdG9yYWdlQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/sql/array/add-unique.sql b/lib/Adapters/Storage/Postgres/sql/array/add-unique.sql new file mode 100644 index 0000000000..aad90d45f5 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/array/add-unique.sql @@ -0,0 +1,11 @@ +CREATE OR REPLACE FUNCTION array_add_unique( + "array" jsonb, + "values" jsonb +) + RETURNS jsonb + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ + SELECT array_to_json(ARRAY(SELECT DISTINCT unnest(ARRAY(SELECT DISTINCT jsonb_array_elements("array")) || ARRAY(SELECT DISTINCT jsonb_array_elements("values")))))::jsonb; +$function$; diff --git a/lib/Adapters/Storage/Postgres/sql/array/add.sql b/lib/Adapters/Storage/Postgres/sql/array/add.sql new file mode 100644 index 0000000000..a0b5859908 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/array/add.sql @@ -0,0 +1,11 @@ +CREATE OR REPLACE FUNCTION array_add( + "array" jsonb, + "values" jsonb +) + RETURNS jsonb + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ + SELECT array_to_json(ARRAY(SELECT unnest(ARRAY(SELECT DISTINCT jsonb_array_elements("array")) || ARRAY(SELECT jsonb_array_elements("values")))))::jsonb; +$function$; diff --git a/lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql b/lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql new file mode 100644 index 0000000000..7ca5853a9f --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql @@ -0,0 +1,14 @@ +CREATE OR REPLACE FUNCTION array_contains_all_regex( + "array" jsonb, + "values" jsonb +) + RETURNS boolean + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ + SELECT CASE + WHEN 0 = jsonb_array_length("values") THEN true = false + ELSE (SELECT RES.CNT = jsonb_array_length("values") FROM (SELECT COUNT(*) as CNT FROM jsonb_array_elements_text("array") as elt WHERE elt LIKE ANY (SELECT jsonb_array_elements_text("values"))) as RES) + END; +$function$; \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql b/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql new file mode 100644 index 0000000000..8db1ca0e7b --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql @@ -0,0 +1,14 @@ +CREATE OR REPLACE FUNCTION array_contains_all( + "array" jsonb, + "values" jsonb +) + RETURNS boolean + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ + SELECT CASE + WHEN 0 = jsonb_array_length("values") THEN true = false + ELSE (SELECT RES.CNT = jsonb_array_length("values") FROM (SELECT COUNT(*) as CNT FROM jsonb_array_elements_text("array") as elt WHERE elt IN (SELECT jsonb_array_elements_text("values"))) as RES) + END; +$function$; diff --git a/lib/Adapters/Storage/Postgres/sql/array/contains.sql b/lib/Adapters/Storage/Postgres/sql/array/contains.sql new file mode 100644 index 0000000000..f7c458782e --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/array/contains.sql @@ -0,0 +1,11 @@ +CREATE OR REPLACE FUNCTION array_contains( + "array" jsonb, + "values" jsonb +) + RETURNS boolean + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ + SELECT RES.CNT >= 1 FROM (SELECT COUNT(*) as CNT FROM jsonb_array_elements("array") as elt WHERE elt IN (SELECT jsonb_array_elements("values"))) as RES; +$function$; diff --git a/lib/Adapters/Storage/Postgres/sql/array/remove.sql b/lib/Adapters/Storage/Postgres/sql/array/remove.sql new file mode 100644 index 0000000000..52895d2f46 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/array/remove.sql @@ -0,0 +1,11 @@ +CREATE OR REPLACE FUNCTION array_remove( + "array" jsonb, + "values" jsonb +) + RETURNS jsonb + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ + SELECT array_to_json(ARRAY(SELECT * FROM jsonb_array_elements("array") as elt WHERE elt NOT IN (SELECT * FROM (SELECT jsonb_array_elements("values")) AS sub)))::jsonb; +$function$; diff --git a/lib/Adapters/Storage/Postgres/sql/index.js b/lib/Adapters/Storage/Postgres/sql/index.js new file mode 100644 index 0000000000..2fc76f3ab1 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/index.js @@ -0,0 +1,35 @@ +'use strict'; + +var QueryFile = require('pg-promise').QueryFile; + +var path = require('path'); + +module.exports = { + array: { + add: sql('array/add.sql'), + addUnique: sql('array/add-unique.sql'), + contains: sql('array/contains.sql'), + containsAll: sql('array/contains-all.sql'), + containsAllRegex: sql('array/contains-all-regex.sql'), + remove: sql('array/remove.sql') + }, + misc: { + jsonObjectSetKeys: sql('misc/json-object-set-keys.sql') + } +}; /////////////////////////////////////////////// +// Helper for linking to external query files; + +function sql(file) { + var fullPath = path.join(__dirname, file); // generating full path; + + var qf = new QueryFile(fullPath, { + minify: true + }); + + if (qf.error) { + throw qf.error; + } + + return qf; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL3NxbC9pbmRleC5qcyJdLCJuYW1lcyI6WyJRdWVyeUZpbGUiLCJyZXF1aXJlIiwicGF0aCIsIm1vZHVsZSIsImV4cG9ydHMiLCJhcnJheSIsImFkZCIsInNxbCIsImFkZFVuaXF1ZSIsImNvbnRhaW5zIiwiY29udGFpbnNBbGwiLCJjb250YWluc0FsbFJlZ2V4IiwicmVtb3ZlIiwibWlzYyIsImpzb25PYmplY3RTZXRLZXlzIiwiZmlsZSIsImZ1bGxQYXRoIiwiam9pbiIsIl9fZGlybmFtZSIsInFmIiwibWluaWZ5IiwiZXJyb3IiXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBLElBQUlBLFNBQVMsR0FBR0MsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkQsU0FBdEM7O0FBQ0EsSUFBSUUsSUFBSSxHQUFHRCxPQUFPLENBQUMsTUFBRCxDQUFsQjs7QUFFQUUsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZDLEVBQUFBLEtBQUssRUFBRTtBQUNMQyxJQUFBQSxHQUFHLEVBQUVDLEdBQUcsQ0FBQyxlQUFELENBREg7QUFFTEMsSUFBQUEsU0FBUyxFQUFFRCxHQUFHLENBQUMsc0JBQUQsQ0FGVDtBQUdMRSxJQUFBQSxRQUFRLEVBQUVGLEdBQUcsQ0FBQyxvQkFBRCxDQUhSO0FBSUxHLElBQUFBLFdBQVcsRUFBRUgsR0FBRyxDQUFDLHdCQUFELENBSlg7QUFLTEksSUFBQUEsZ0JBQWdCLEVBQUVKLEdBQUcsQ0FBQyw4QkFBRCxDQUxoQjtBQU1MSyxJQUFBQSxNQUFNLEVBQUVMLEdBQUcsQ0FBQyxrQkFBRDtBQU5OLEdBRFE7QUFTZk0sRUFBQUEsSUFBSSxFQUFFO0FBQ0pDLElBQUFBLGlCQUFpQixFQUFFUCxHQUFHLENBQUMsK0JBQUQ7QUFEbEI7QUFUUyxDQUFqQixDLENBY0E7QUFDQTs7QUFDQSxTQUFTQSxHQUFULENBQWFRLElBQWIsRUFBbUI7QUFDakIsTUFBSUMsUUFBUSxHQUFHZCxJQUFJLENBQUNlLElBQUwsQ0FBVUMsU0FBVixFQUFxQkgsSUFBckIsQ0FBZixDQURpQixDQUMwQjs7QUFFM0MsTUFBSUksRUFBRSxHQUFHLElBQUluQixTQUFKLENBQWNnQixRQUFkLEVBQXdCO0FBQUVJLElBQUFBLE1BQU0sRUFBRTtBQUFWLEdBQXhCLENBQVQ7O0FBRUEsTUFBSUQsRUFBRSxDQUFDRSxLQUFQLEVBQWM7QUFDWixVQUFNRixFQUFFLENBQUNFLEtBQVQ7QUFDRDs7QUFFRCxTQUFPRixFQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBRdWVyeUZpbGUgPSByZXF1aXJlKCdwZy1wcm9taXNlJykuUXVlcnlGaWxlO1xudmFyIHBhdGggPSByZXF1aXJlKCdwYXRoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBhcnJheToge1xuICAgIGFkZDogc3FsKCdhcnJheS9hZGQuc3FsJyksXG4gICAgYWRkVW5pcXVlOiBzcWwoJ2FycmF5L2FkZC11bmlxdWUuc3FsJyksXG4gICAgY29udGFpbnM6IHNxbCgnYXJyYXkvY29udGFpbnMuc3FsJyksXG4gICAgY29udGFpbnNBbGw6IHNxbCgnYXJyYXkvY29udGFpbnMtYWxsLnNxbCcpLFxuICAgIGNvbnRhaW5zQWxsUmVnZXg6IHNxbCgnYXJyYXkvY29udGFpbnMtYWxsLXJlZ2V4LnNxbCcpLFxuICAgIHJlbW92ZTogc3FsKCdhcnJheS9yZW1vdmUuc3FsJyksXG4gIH0sXG4gIG1pc2M6IHtcbiAgICBqc29uT2JqZWN0U2V0S2V5czogc3FsKCdtaXNjL2pzb24tb2JqZWN0LXNldC1rZXlzLnNxbCcpLFxuICB9LFxufTtcblxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIEhlbHBlciBmb3IgbGlua2luZyB0byBleHRlcm5hbCBxdWVyeSBmaWxlcztcbmZ1bmN0aW9uIHNxbChmaWxlKSB7XG4gIHZhciBmdWxsUGF0aCA9IHBhdGguam9pbihfX2Rpcm5hbWUsIGZpbGUpOyAvLyBnZW5lcmF0aW5nIGZ1bGwgcGF0aDtcblxuICB2YXIgcWYgPSBuZXcgUXVlcnlGaWxlKGZ1bGxQYXRoLCB7IG1pbmlmeTogdHJ1ZSB9KTtcblxuICBpZiAocWYuZXJyb3IpIHtcbiAgICB0aHJvdyBxZi5lcnJvcjtcbiAgfVxuXG4gIHJldHVybiBxZjtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql b/lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql new file mode 100644 index 0000000000..eb28b36928 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql @@ -0,0 +1,19 @@ +-- Function to set a key on a nested JSON document + +CREATE OR REPLACE FUNCTION json_object_set_key( + "json" jsonb, + key_to_set TEXT, + value_to_set anyelement +) + RETURNS jsonb + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ +SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::jsonb + FROM (SELECT * + FROM jsonb_each("json") + WHERE key <> key_to_set + UNION ALL + SELECT key_to_set, to_json("value_to_set")::jsonb) AS fields +$function$; diff --git a/lib/Adapters/Storage/StorageAdapter.js b/lib/Adapters/Storage/StorageAdapter.js new file mode 100644 index 0000000000..4310b4ffac --- /dev/null +++ b/lib/Adapters/Storage/StorageAdapter.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbXX0= \ No newline at end of file diff --git a/lib/Adapters/WebSocketServer/WSAdapter.js b/lib/Adapters/WebSocketServer/WSAdapter.js new file mode 100644 index 0000000000..a586fbcd8a --- /dev/null +++ b/lib/Adapters/WebSocketServer/WSAdapter.js @@ -0,0 +1,45 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.WSAdapter = void 0; + +var _WSSAdapter = require("./WSSAdapter"); + +/*eslint no-unused-vars: "off"*/ +const WebSocketServer = require('ws').Server; +/** + * Wrapper for ws node module + */ + + +class WSAdapter extends _WSSAdapter.WSSAdapter { + constructor(options) { + super(options); + this.options = options; + } + + onListen() {} + + onConnection(ws) {} + + onError(error) {} + + start() { + const wss = new WebSocketServer({ + server: this.options.server + }); + wss.on('listening', this.onListen); + wss.on('connection', this.onConnection); + wss.on('error', this.onError); + } + + close() {} + +} + +exports.WSAdapter = WSAdapter; +var _default = WSAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9XZWJTb2NrZXRTZXJ2ZXIvV1NBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIldlYlNvY2tldFNlcnZlciIsInJlcXVpcmUiLCJTZXJ2ZXIiLCJXU0FkYXB0ZXIiLCJXU1NBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwib25MaXN0ZW4iLCJvbkNvbm5lY3Rpb24iLCJ3cyIsIm9uRXJyb3IiLCJlcnJvciIsInN0YXJ0Iiwid3NzIiwic2VydmVyIiwib24iLCJjbG9zZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQURBO0FBRUEsTUFBTUEsZUFBZSxHQUFHQyxPQUFPLENBQUMsSUFBRCxDQUFQLENBQWNDLE1BQXRDO0FBRUE7Ozs7O0FBR08sTUFBTUMsU0FBTixTQUF3QkMsc0JBQXhCLENBQW1DO0FBQ3hDQyxFQUFBQSxXQUFXLENBQUNDLE9BQUQsRUFBZTtBQUN4QixVQUFNQSxPQUFOO0FBQ0EsU0FBS0EsT0FBTCxHQUFlQSxPQUFmO0FBQ0Q7O0FBRURDLEVBQUFBLFFBQVEsR0FBRyxDQUFFOztBQUNiQyxFQUFBQSxZQUFZLENBQUNDLEVBQUQsRUFBSyxDQUFFOztBQUNuQkMsRUFBQUEsT0FBTyxDQUFDQyxLQUFELEVBQVEsQ0FBRTs7QUFDakJDLEVBQUFBLEtBQUssR0FBRztBQUNOLFVBQU1DLEdBQUcsR0FBRyxJQUFJYixlQUFKLENBQW9CO0FBQUVjLE1BQUFBLE1BQU0sRUFBRSxLQUFLUixPQUFMLENBQWFRO0FBQXZCLEtBQXBCLENBQVo7QUFDQUQsSUFBQUEsR0FBRyxDQUFDRSxFQUFKLENBQU8sV0FBUCxFQUFvQixLQUFLUixRQUF6QjtBQUNBTSxJQUFBQSxHQUFHLENBQUNFLEVBQUosQ0FBTyxZQUFQLEVBQXFCLEtBQUtQLFlBQTFCO0FBQ0FLLElBQUFBLEdBQUcsQ0FBQ0UsRUFBSixDQUFPLE9BQVAsRUFBZ0IsS0FBS0wsT0FBckI7QUFDRDs7QUFDRE0sRUFBQUEsS0FBSyxHQUFHLENBQUU7O0FBZjhCOzs7ZUFrQjNCYixTIiwic291cmNlc0NvbnRlbnQiOlsiLyplc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIqL1xuaW1wb3J0IHsgV1NTQWRhcHRlciB9IGZyb20gJy4vV1NTQWRhcHRlcic7XG5jb25zdCBXZWJTb2NrZXRTZXJ2ZXIgPSByZXF1aXJlKCd3cycpLlNlcnZlcjtcblxuLyoqXG4gKiBXcmFwcGVyIGZvciB3cyBub2RlIG1vZHVsZVxuICovXG5leHBvcnQgY2xhc3MgV1NBZGFwdGVyIGV4dGVuZHMgV1NTQWRhcHRlciB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IGFueSkge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gIH1cblxuICBvbkxpc3RlbigpIHt9XG4gIG9uQ29ubmVjdGlvbih3cykge31cbiAgb25FcnJvcihlcnJvcikge31cbiAgc3RhcnQoKSB7XG4gICAgY29uc3Qgd3NzID0gbmV3IFdlYlNvY2tldFNlcnZlcih7IHNlcnZlcjogdGhpcy5vcHRpb25zLnNlcnZlciB9KTtcbiAgICB3c3Mub24oJ2xpc3RlbmluZycsIHRoaXMub25MaXN0ZW4pO1xuICAgIHdzcy5vbignY29ubmVjdGlvbicsIHRoaXMub25Db25uZWN0aW9uKTtcbiAgICB3c3Mub24oJ2Vycm9yJywgdGhpcy5vbkVycm9yKTtcbiAgfVxuICBjbG9zZSgpIHt9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFdTQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/WebSocketServer/WSSAdapter.js b/lib/Adapters/WebSocketServer/WSSAdapter.js new file mode 100644 index 0000000000..d3a836e02d --- /dev/null +++ b/lib/Adapters/WebSocketServer/WSSAdapter.js @@ -0,0 +1,74 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.WSSAdapter = void 0; + +/*eslint no-unused-vars: "off"*/ +// WebSocketServer Adapter +// +// Adapter classes must implement the following functions: +// * onListen() +// * onConnection(ws) +// * onError(error) +// * start() +// * close() +// +// Default is WSAdapter. The above functions will be binded. + +/** + * @module Adapters + */ + +/** + * @interface WSSAdapter + */ +class WSSAdapter { + /** + * @param {Object} options - {http.Server|https.Server} server + */ + constructor(options) { + this.onListen = () => {}; + + this.onConnection = () => {}; + + this.onError = () => {}; + } // /** + // * Emitted when the underlying server has been bound. + // */ + // onListen() {} + // /** + // * Emitted when the handshake is complete. + // * + // * @param {WebSocket} ws - RFC 6455 WebSocket. + // */ + // onConnection(ws) {} + // /** + // * Emitted when error event is called. + // * + // * @param {Error} error - WebSocketServer error + // */ + // onError(error) {} + + /** + * Initialize Connection. + * + * @param {Object} options + */ + + + start(options) {} + /** + * Closes server. + */ + + + close() {} + +} + +exports.WSSAdapter = WSSAdapter; +var _default = WSSAdapter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9XZWJTb2NrZXRTZXJ2ZXIvV1NTQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJXU1NBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwib25MaXN0ZW4iLCJvbkNvbm5lY3Rpb24iLCJvbkVycm9yIiwic3RhcnQiLCJjbG9zZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7QUFHQTs7O0FBR08sTUFBTUEsVUFBTixDQUFpQjtBQUN0Qjs7O0FBR0FDLEVBQUFBLFdBQVcsQ0FBQ0MsT0FBRCxFQUFVO0FBQ25CLFNBQUtDLFFBQUwsR0FBZ0IsTUFBTSxDQUFFLENBQXhCOztBQUNBLFNBQUtDLFlBQUwsR0FBb0IsTUFBTSxDQUFFLENBQTVCOztBQUNBLFNBQUtDLE9BQUwsR0FBZSxNQUFNLENBQUUsQ0FBdkI7QUFDRCxHQVJxQixDQVV0QjtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7OztBQUtBQyxFQUFBQSxLQUFLLENBQUNKLE9BQUQsRUFBVSxDQUFFO0FBRWpCOzs7OztBQUdBSyxFQUFBQSxLQUFLLEdBQUcsQ0FBRTs7QUF2Q1k7OztlQTBDVFAsVSIsInNvdXJjZXNDb250ZW50IjpbIi8qZXNsaW50IG5vLXVudXNlZC12YXJzOiBcIm9mZlwiKi9cbi8vIFdlYlNvY2tldFNlcnZlciBBZGFwdGVyXG4vL1xuLy8gQWRhcHRlciBjbGFzc2VzIG11c3QgaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgZnVuY3Rpb25zOlxuLy8gKiBvbkxpc3RlbigpXG4vLyAqIG9uQ29ubmVjdGlvbih3cylcbi8vICogb25FcnJvcihlcnJvcilcbi8vICogc3RhcnQoKVxuLy8gKiBjbG9zZSgpXG4vL1xuLy8gRGVmYXVsdCBpcyBXU0FkYXB0ZXIuIFRoZSBhYm92ZSBmdW5jdGlvbnMgd2lsbCBiZSBiaW5kZWQuXG5cbi8qKlxuICogQG1vZHVsZSBBZGFwdGVyc1xuICovXG4vKipcbiAqIEBpbnRlcmZhY2UgV1NTQWRhcHRlclxuICovXG5leHBvcnQgY2xhc3MgV1NTQWRhcHRlciB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIHtodHRwLlNlcnZlcnxodHRwcy5TZXJ2ZXJ9IHNlcnZlclxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIHRoaXMub25MaXN0ZW4gPSAoKSA9PiB7fTtcbiAgICB0aGlzLm9uQ29ubmVjdGlvbiA9ICgpID0+IHt9O1xuICAgIHRoaXMub25FcnJvciA9ICgpID0+IHt9O1xuICB9XG5cbiAgLy8gLyoqXG4gIC8vICAqIEVtaXR0ZWQgd2hlbiB0aGUgdW5kZXJseWluZyBzZXJ2ZXIgaGFzIGJlZW4gYm91bmQuXG4gIC8vICAqL1xuICAvLyBvbkxpc3RlbigpIHt9XG5cbiAgLy8gLyoqXG4gIC8vICAqIEVtaXR0ZWQgd2hlbiB0aGUgaGFuZHNoYWtlIGlzIGNvbXBsZXRlLlxuICAvLyAgKlxuICAvLyAgKiBAcGFyYW0ge1dlYlNvY2tldH0gd3MgLSBSRkMgNjQ1NSBXZWJTb2NrZXQuXG4gIC8vICAqL1xuICAvLyBvbkNvbm5lY3Rpb24od3MpIHt9XG5cbiAgLy8gLyoqXG4gIC8vICAqIEVtaXR0ZWQgd2hlbiBlcnJvciBldmVudCBpcyBjYWxsZWQuXG4gIC8vICAqXG4gIC8vICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIC0gV2ViU29ja2V0U2VydmVyIGVycm9yXG4gIC8vICAqL1xuICAvLyBvbkVycm9yKGVycm9yKSB7fVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIENvbm5lY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqL1xuICBzdGFydChvcHRpb25zKSB7fVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgc2VydmVyLlxuICAgKi9cbiAgY2xvc2UoKSB7fVxufVxuXG5leHBvcnQgZGVmYXVsdCBXU1NBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Auth.js b/lib/Auth.js new file mode 100644 index 0000000000..652beda3cd --- /dev/null +++ b/lib/Auth.js @@ -0,0 +1,373 @@ +"use strict"; + +const cryptoUtils = require('./cryptoUtils'); + +const RestQuery = require('./RestQuery'); + +const Parse = require('parse/node'); // An Auth object tells you who is requesting something and whether +// the master key was used. +// userObject is a Parse.User and can be null if there's no user. + + +function Auth({ + config, + cacheController = undefined, + isMaster = false, + isReadOnly = false, + user, + installationId +}) { + this.config = config; + this.cacheController = cacheController || config && config.cacheController; + this.installationId = installationId; + this.isMaster = isMaster; + this.user = user; + this.isReadOnly = isReadOnly; // Assuming a users roles won't change during a single request, we'll + // only load them once. + + this.userRoles = []; + this.fetchedRoles = false; + this.rolePromise = null; +} // Whether this auth could possibly modify the given user id. +// It still could be forbidden via ACLs even if this returns true. + + +Auth.prototype.isUnauthenticated = function () { + if (this.isMaster) { + return false; + } + + if (this.user) { + return false; + } + + return true; +}; // A helper to get a master-level Auth object + + +function master(config) { + return new Auth({ + config, + isMaster: true + }); +} // A helper to get a master-level Auth object + + +function readOnly(config) { + return new Auth({ + config, + isMaster: true, + isReadOnly: true + }); +} // A helper to get a nobody-level Auth object + + +function nobody(config) { + return new Auth({ + config, + isMaster: false + }); +} // Returns a promise that resolves to an Auth object + + +const getAuthForSessionToken = async function ({ + config, + cacheController, + sessionToken, + installationId +}) { + cacheController = cacheController || config && config.cacheController; + + if (cacheController) { + const userJSON = await cacheController.user.get(sessionToken); + + if (userJSON) { + const cachedUser = Parse.Object.fromJSON(userJSON); + return Promise.resolve(new Auth({ + config, + cacheController, + isMaster: false, + installationId, + user: cachedUser + })); + } + } + + let results; + + if (config) { + const restOptions = { + limit: 1, + include: 'user' + }; + const query = new RestQuery(config, master(config), '_Session', { + sessionToken + }, restOptions); + results = (await query.execute()).results; + } else { + results = (await new Parse.Query(Parse.Session).limit(1).include('user').equalTo('sessionToken', sessionToken).find({ + useMasterKey: true + })).map(obj => obj.toJSON()); + } + + if (results.length !== 1 || !results[0]['user']) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); + } + + const now = new Date(), + expiresAt = results[0].expiresAt ? new Date(results[0].expiresAt.iso) : undefined; + + if (expiresAt < now) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token is expired.'); + } + + const obj = results[0]['user']; + delete obj.password; + obj['className'] = '_User'; + obj['sessionToken'] = sessionToken; + + if (cacheController) { + cacheController.user.put(sessionToken, obj); + } + + const userObject = Parse.Object.fromJSON(obj); + return new Auth({ + config, + cacheController, + isMaster: false, + installationId, + user: userObject + }); +}; + +var getAuthForLegacySessionToken = function ({ + config, + sessionToken, + installationId +}) { + var restOptions = { + limit: 1 + }; + var query = new RestQuery(config, master(config), '_User', { + sessionToken + }, restOptions); + return query.execute().then(response => { + var results = response.results; + + if (results.length !== 1) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid legacy session token'); + } + + const obj = results[0]; + obj.className = '_User'; + const userObject = Parse.Object.fromJSON(obj); + return new Auth({ + config, + isMaster: false, + installationId, + user: userObject + }); + }); +}; // Returns a promise that resolves to an array of role names + + +Auth.prototype.getUserRoles = function () { + if (this.isMaster || !this.user) { + return Promise.resolve([]); + } + + if (this.fetchedRoles) { + return Promise.resolve(this.userRoles); + } + + if (this.rolePromise) { + return this.rolePromise; + } + + this.rolePromise = this._loadRoles(); + return this.rolePromise; +}; + +Auth.prototype.getRolesForUser = async function () { + //Stack all Parse.Role + const results = []; + + if (this.config) { + const restWhere = { + users: { + __type: 'Pointer', + className: '_User', + objectId: this.user.id + } + }; + await new RestQuery(this.config, master(this.config), '_Role', restWhere, {}).each(result => results.push(result)); + } else { + await new Parse.Query(Parse.Role).equalTo('users', this.user).each(result => results.push(result.toJSON()), { + useMasterKey: true + }); + } + + return results; +}; // Iterates through the role tree and compiles a user's roles + + +Auth.prototype._loadRoles = async function () { + if (this.cacheController) { + const cachedRoles = await this.cacheController.role.get(this.user.id); + + if (cachedRoles != null) { + this.fetchedRoles = true; + this.userRoles = cachedRoles; + return cachedRoles; + } + } // First get the role ids this user is directly a member of + + + const results = await this.getRolesForUser(); + + if (!results.length) { + this.userRoles = []; + this.fetchedRoles = true; + this.rolePromise = null; + this.cacheRoles(); + return this.userRoles; + } + + const rolesMap = results.reduce((m, r) => { + m.names.push(r.name); + m.ids.push(r.objectId); + return m; + }, { + ids: [], + names: [] + }); // run the recursive finding + + const roleNames = await this._getAllRolesNamesForRoleIds(rolesMap.ids, rolesMap.names); + this.userRoles = roleNames.map(r => { + return 'role:' + r; + }); + this.fetchedRoles = true; + this.rolePromise = null; + this.cacheRoles(); + return this.userRoles; +}; + +Auth.prototype.cacheRoles = function () { + if (!this.cacheController) { + return false; + } + + this.cacheController.role.put(this.user.id, Array(...this.userRoles)); + return true; +}; + +Auth.prototype.getRolesByIds = async function (ins) { + const results = []; // Build an OR query across all parentRoles + + if (!this.config) { + await new Parse.Query(Parse.Role).containedIn('roles', ins.map(id => { + const role = new Parse.Object(Parse.Role); + role.id = id; + return role; + })).each(result => results.push(result.toJSON()), { + useMasterKey: true + }); + } else { + const roles = ins.map(id => { + return { + __type: 'Pointer', + className: '_Role', + objectId: id + }; + }); + const restWhere = { + roles: { + $in: roles + } + }; + await new RestQuery(this.config, master(this.config), '_Role', restWhere, {}).each(result => results.push(result)); + } + + return results; +}; // Given a list of roleIds, find all the parent roles, returns a promise with all names + + +Auth.prototype._getAllRolesNamesForRoleIds = function (roleIDs, names = [], queriedRoles = {}) { + const ins = roleIDs.filter(roleID => { + const wasQueried = queriedRoles[roleID] !== true; + queriedRoles[roleID] = true; + return wasQueried; + }); // all roles are accounted for, return the names + + if (ins.length == 0) { + return Promise.resolve([...new Set(names)]); + } + + return this.getRolesByIds(ins).then(results => { + // Nothing found + if (!results.length) { + return Promise.resolve(names); + } // Map the results with all Ids and names + + + const resultMap = results.reduce((memo, role) => { + memo.names.push(role.name); + memo.ids.push(role.objectId); + return memo; + }, { + ids: [], + names: [] + }); // store the new found names + + names = names.concat(resultMap.names); // find the next ones, circular roles will be cut + + return this._getAllRolesNamesForRoleIds(resultMap.ids, names, queriedRoles); + }).then(names => { + return Promise.resolve([...new Set(names)]); + }); +}; + +const createSession = function (config, { + userId, + createdWith, + installationId, + additionalSessionData +}) { + const token = 'r:' + cryptoUtils.newToken(); + const expiresAt = config.generateSessionExpiresAt(); + const sessionData = { + sessionToken: token, + user: { + __type: 'Pointer', + className: '_User', + objectId: userId + }, + createdWith, + restricted: false, + expiresAt: Parse._encode(expiresAt) + }; + + if (installationId) { + sessionData.installationId = installationId; + } + + Object.assign(sessionData, additionalSessionData); // We need to import RestWrite at this point for the cyclic dependency it has to it + + const RestWrite = require('./RestWrite'); + + return { + sessionData, + createSession: () => new RestWrite(config, master(config), '_Session', null, sessionData).execute() + }; +}; + +module.exports = { + Auth, + master, + nobody, + readOnly, + getAuthForSessionToken, + getAuthForLegacySessionToken, + createSession +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9BdXRoLmpzIl0sIm5hbWVzIjpbImNyeXB0b1V0aWxzIiwicmVxdWlyZSIsIlJlc3RRdWVyeSIsIlBhcnNlIiwiQXV0aCIsImNvbmZpZyIsImNhY2hlQ29udHJvbGxlciIsInVuZGVmaW5lZCIsImlzTWFzdGVyIiwiaXNSZWFkT25seSIsInVzZXIiLCJpbnN0YWxsYXRpb25JZCIsInVzZXJSb2xlcyIsImZldGNoZWRSb2xlcyIsInJvbGVQcm9taXNlIiwicHJvdG90eXBlIiwiaXNVbmF1dGhlbnRpY2F0ZWQiLCJtYXN0ZXIiLCJyZWFkT25seSIsIm5vYm9keSIsImdldEF1dGhGb3JTZXNzaW9uVG9rZW4iLCJzZXNzaW9uVG9rZW4iLCJ1c2VySlNPTiIsImdldCIsImNhY2hlZFVzZXIiLCJPYmplY3QiLCJmcm9tSlNPTiIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVzdWx0cyIsInJlc3RPcHRpb25zIiwibGltaXQiLCJpbmNsdWRlIiwicXVlcnkiLCJleGVjdXRlIiwiUXVlcnkiLCJTZXNzaW9uIiwiZXF1YWxUbyIsImZpbmQiLCJ1c2VNYXN0ZXJLZXkiLCJtYXAiLCJvYmoiLCJ0b0pTT04iLCJsZW5ndGgiLCJFcnJvciIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsIm5vdyIsIkRhdGUiLCJleHBpcmVzQXQiLCJpc28iLCJwYXNzd29yZCIsInB1dCIsInVzZXJPYmplY3QiLCJnZXRBdXRoRm9yTGVnYWN5U2Vzc2lvblRva2VuIiwidGhlbiIsInJlc3BvbnNlIiwiY2xhc3NOYW1lIiwiZ2V0VXNlclJvbGVzIiwiX2xvYWRSb2xlcyIsImdldFJvbGVzRm9yVXNlciIsInJlc3RXaGVyZSIsInVzZXJzIiwiX190eXBlIiwib2JqZWN0SWQiLCJpZCIsImVhY2giLCJyZXN1bHQiLCJwdXNoIiwiUm9sZSIsImNhY2hlZFJvbGVzIiwicm9sZSIsImNhY2hlUm9sZXMiLCJyb2xlc01hcCIsInJlZHVjZSIsIm0iLCJyIiwibmFtZXMiLCJuYW1lIiwiaWRzIiwicm9sZU5hbWVzIiwiX2dldEFsbFJvbGVzTmFtZXNGb3JSb2xlSWRzIiwiQXJyYXkiLCJnZXRSb2xlc0J5SWRzIiwiaW5zIiwiY29udGFpbmVkSW4iLCJyb2xlcyIsIiRpbiIsInJvbGVJRHMiLCJxdWVyaWVkUm9sZXMiLCJmaWx0ZXIiLCJyb2xlSUQiLCJ3YXNRdWVyaWVkIiwiU2V0IiwicmVzdWx0TWFwIiwibWVtbyIsImNvbmNhdCIsImNyZWF0ZVNlc3Npb24iLCJ1c2VySWQiLCJjcmVhdGVkV2l0aCIsImFkZGl0aW9uYWxTZXNzaW9uRGF0YSIsInRva2VuIiwibmV3VG9rZW4iLCJnZW5lcmF0ZVNlc3Npb25FeHBpcmVzQXQiLCJzZXNzaW9uRGF0YSIsInJlc3RyaWN0ZWQiLCJfZW5jb2RlIiwiYXNzaWduIiwiUmVzdFdyaXRlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQSxNQUFNQSxXQUFXLEdBQUdDLE9BQU8sQ0FBQyxlQUFELENBQTNCOztBQUNBLE1BQU1DLFNBQVMsR0FBR0QsT0FBTyxDQUFDLGFBQUQsQ0FBekI7O0FBQ0EsTUFBTUUsS0FBSyxHQUFHRixPQUFPLENBQUMsWUFBRCxDQUFyQixDLENBRUE7QUFDQTtBQUNBOzs7QUFDQSxTQUFTRyxJQUFULENBQWM7QUFDWkMsRUFBQUEsTUFEWTtBQUVaQyxFQUFBQSxlQUFlLEdBQUdDLFNBRk47QUFHWkMsRUFBQUEsUUFBUSxHQUFHLEtBSEM7QUFJWkMsRUFBQUEsVUFBVSxHQUFHLEtBSkQ7QUFLWkMsRUFBQUEsSUFMWTtBQU1aQyxFQUFBQTtBQU5ZLENBQWQsRUFPRztBQUNELE9BQUtOLE1BQUwsR0FBY0EsTUFBZDtBQUNBLE9BQUtDLGVBQUwsR0FBdUJBLGVBQWUsSUFBS0QsTUFBTSxJQUFJQSxNQUFNLENBQUNDLGVBQTVEO0FBQ0EsT0FBS0ssY0FBTCxHQUFzQkEsY0FBdEI7QUFDQSxPQUFLSCxRQUFMLEdBQWdCQSxRQUFoQjtBQUNBLE9BQUtFLElBQUwsR0FBWUEsSUFBWjtBQUNBLE9BQUtELFVBQUwsR0FBa0JB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RURjLEVBQUFBLE1BQU0sQ0FBQ2lGLE1BQVAsQ0FBY0gsV0FBZCxFQUEyQkoscUJBQTNCLEVBbkJBLENBb0JBOztBQUNBLFFBQU1RLFNBQVMsR0FBRzFHLE9BQU8sQ0FBQyxhQUFELENBQXpCOztBQUVBLFNBQU87QUFDTHNHLElBQUFBLFdBREs7QUFFTFAsSUFBQUEsYUFBYSxFQUFFLE1BQ2IsSUFBSVcsU0FBSixDQUNFdEcsTUFERixFQUVFWSxNQUFNLENBQUNaLE1BQUQsQ0FGUixFQUdFLFVBSEYsRUFJRSxJQUpGLEVBS0VrRyxXQUxGLEVBTUVyRSxPQU5GO0FBSEcsR0FBUDtBQVdELENBckNEOztBQXVDQTBFLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmekcsRUFBQUEsSUFEZTtBQUVmYSxFQUFBQSxNQUZlO0FBR2ZFLEVBQUFBLE1BSGU7QUFJZkQsRUFBQUEsUUFKZTtBQUtmRSxFQUFBQSxzQkFMZTtBQU1maUMsRUFBQUEsNEJBTmU7QUFPZjJDLEVBQUFBO0FBUGUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBjcnlwdG9VdGlscyA9IHJlcXVpcmUoJy4vY3J5cHRvVXRpbHMnKTtcbmNvbnN0IFJlc3RRdWVyeSA9IHJlcXVpcmUoJy4vUmVzdFF1ZXJ5Jyk7XG5jb25zdCBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKTtcblxuLy8gQW4gQXV0aCBvYmplY3QgdGVsbHMgeW91IHdobyBpcyByZXF1ZXN0aW5nIHNvbWV0aGluZyBhbmQgd2hldGhlclxuLy8gdGhlIG1hc3RlciBrZXkgd2FzIHVzZWQuXG4vLyB1c2VyT2JqZWN0IGlzIGEgUGFyc2UuVXNlciBhbmQgY2FuIGJlIG51bGwgaWYgdGhlcmUncyBubyB1c2VyLlxuZnVuY3Rpb24gQXV0aCh7XG4gIGNvbmZpZyxcbiAgY2FjaGVDb250cm9sbGVyID0gdW5kZWZpbmVkLFxuICBpc01hc3RlciA9IGZhbHNlLFxuICBpc1JlYWRPbmx5ID0gZmFsc2UsXG4gIHVzZXIsXG4gIGluc3RhbGxhdGlvbklkLFxufSkge1xuICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgdGhpcy5jYWNoZUNvbnRyb2xsZXIgPSBjYWNoZUNvbnRyb2xsZXIgfHwgKGNvbmZpZyAmJiBjb25maWcuY2FjaGVDb250cm9sbGVyKTtcbiAgdGhpcy5pbnN0YWxsYXRpb25JZCA9IGluc3RhbGxhdGlvbklkO1xuICB0aGlzLmlzTWFzdGVyID0gaXNNYXN0ZXI7XG4gIHRoaXMudXNlciA9IHVzZXI7XG4gIHRoaXMuaXNSZWFkT25seSA9IGlzUmVhZE9ubHk7XG5cbiAgLy8gQXNzdW1pbmcgYSB1c2VycyByb2xlcyB3b24ndCBjaGFuZ2UgZHVyaW5nIGEgc2luZ2xlIHJlcXVlc3QsIHdlJ2xsXG4gIC8vIG9ubHkgbG9hZCB0aGVtIG9uY2UuXG4gIHRoaXMudXNlclJvbGVzID0gW107XG4gIHRoaXMuZmV0Y2hlZFJvbGVzID0gZmFsc2U7XG4gIHRoaXMucm9sZVByb21pc2UgPSBudWxsO1xufVxuXG4vLyBXaGV0aGVyIHRoaXMgYXV0aCBjb3VsZCBwb3NzaWJseSBtb2RpZnkgdGhlIGdpdmVuIHVzZXIgaWQuXG4vLyBJdCBzdGlsbCBjb3VsZCBiZSBmb3JiaWRkZW4gdmlhIEFDTHMgZXZlbiBpZiB0aGlzIHJldHVybnMgdHJ1ZS5cbkF1dGgucHJvdG90eXBlLmlzVW5hdXRoZW50aWNhdGVkID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmlzTWFzdGVyKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICh0aGlzLnVzZXIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59O1xuXG4vLyBBIGhlbHBlciB0byBnZXQgYSBtYXN0ZXItbGV2ZWwgQXV0aCBvYmplY3RcbmZ1bmN0aW9uIG1hc3Rlcihjb25maWcpIHtcbiAgcmV0dXJuIG5ldyBBdXRoKHsgY29uZmlnLCBpc01hc3RlcjogdHJ1ZSB9KTtcbn1cblxuLy8gQSBoZWxwZXIgdG8gZ2V0IGEgbWFzdGVyLWxldmVsIEF1dGggb2JqZWN0XG5mdW5jdGlvbiByZWFkT25seShjb25maWcpIHtcbiAgcmV0dXJuIG5ldyBBdXRoKHsgY29uZmlnLCBpc01hc3RlcjogdHJ1ZSwgaXNSZWFkT25seTogdHJ1ZSB9KTtcbn1cblxuLy8gQSBoZWxwZXIgdG8gZ2V0IGEgbm9ib2R5LWxldmVsIEF1dGggb2JqZWN0XG5mdW5jdGlvbiBub2JvZHkoY29uZmlnKSB7XG4gIHJldHVybiBuZXcgQXV0aCh7IGNvbmZpZywgaXNNYXN0ZXI6IGZhbHNlIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIEF1dGggb2JqZWN0XG5jb25zdCBnZXRBdXRoRm9yU2Vzc2lvblRva2VuID0gYXN5bmMgZnVuY3Rpb24oe1xuICBjb25maWcsXG4gIGNhY2hlQ29udHJvbGxlcixcbiAgc2Vzc2lvblRva2VuLFxuICBpbnN0YWxsYXRpb25JZCxcbn0pIHtcbiAgY2FjaGVDb250cm9sbGVyID0gY2FjaGVDb250cm9sbGVyIHx8IChjb25maWcgJiYgY29uZmlnLmNhY2hlQ29udHJvbGxlcik7XG4gIGlmIChjYWNoZUNvbnRyb2xsZXIpIHtcbiAgICBjb25zdCB1c2VySlNPTiA9IGF3YWl0IGNhY2hlQ29udHJvbGxlci51c2VyLmdldChzZXNzaW9uVG9rZW4pO1xuICAgIGlmICh1c2VySlNPTikge1xuICAgICAgY29uc3QgY2FjaGVkVXNlciA9IFBhcnNlLk9iamVjdC5mcm9tSlNPTih1c2VySlNPTik7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBuZXcgQXV0aCh7XG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGNhY2hlQ29udHJvbGxlcixcbiAgICAgICAgICBpc01hc3RlcjogZmFsc2UsXG4gICAgICAgICAgaW5zdGFsbGF0aW9uSWQsXG4gICAgICAgICAgdXNlcjogY2FjaGVkVXNlcixcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgbGV0IHJlc3VsdHM7XG4gIGlmIChjb25maWcpIHtcbiAgICBjb25zdCByZXN0T3B0aW9ucyA9IHtcbiAgICAgIGxpbWl0OiAxLFxuICAgICAgaW5jbHVkZTogJ3VzZXInLFxuICAgIH07XG5cbiAgICBjb25zdCBxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgICBjb25maWcsXG4gICAgICBtYXN0ZXIoY29uZmlnKSxcbiAgICAgICdfU2Vzc2lvbicsXG4gICAgICB7IHNlc3Npb25Ub2tlbiB9LFxuICAgICAgcmVzdE9wdGlvbnNcbiAgICApO1xuICAgIHJlc3VsdHMgPSAoYXdhaXQgcXVlcnkuZXhlY3V0ZSgpKS5yZXN1bHRzO1xuICB9IGVsc2Uge1xuICAgIHJlc3VsdHMgPSAoYXdhaXQgbmV3IFBhcnNlLlF1ZXJ5KFBhcnNlLlNlc3Npb24pXG4gICAgICAubGltaXQoMSlcbiAgICAgIC5pbmNsdWRlKCd1c2VyJylcbiAgICAgIC5lcXVhbFRvKCdzZXNzaW9uVG9rZW4nLCBzZXNzaW9uVG9rZW4pXG4gICAgICAuZmluZCh7IHVzZU1hc3RlcktleTogdHJ1ZSB9KSkubWFwKG9iaiA9PiBvYmoudG9KU09OKCkpO1xuICB9XG5cbiAgaWYgKHJlc3VsdHMubGVuZ3RoICE9PSAxIHx8ICFyZXN1bHRzWzBdWyd1c2VyJ10pIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1NFU1NJT05fVE9LRU4sXG4gICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICk7XG4gIH1cbiAgY29uc3Qgbm93ID0gbmV3IERhdGUoKSxcbiAgICBleHBpcmVzQXQgPSByZXN1bHRzWzBdLmV4cGlyZXNBdFxuICAgICAgPyBuZXcgRGF0ZShyZXN1bHRzWzBdLmV4cGlyZXNBdC5pc28pXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgaWYgKGV4cGlyZXNBdCA8IG5vdykge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICdTZXNzaW9uIHRva2VuIGlzIGV4cGlyZWQuJ1xuICAgICk7XG4gIH1cbiAgY29uc3Qgb2JqID0gcmVzdWx0c1swXVsndXNlciddO1xuICBkZWxldGUgb2JqLnBhc3N3b3JkO1xuICBvYmpbJ2NsYXNzTmFtZSddID0gJ19Vc2VyJztcbiAgb2JqWydzZXNzaW9uVG9rZW4nXSA9IHNlc3Npb25Ub2tlbjtcbiAgaWYgKGNhY2hlQ29udHJvbGxlcikge1xuICAgIGNhY2hlQ29udHJvbGxlci51c2VyLnB1dChzZXNzaW9uVG9rZW4sIG9iaik7XG4gIH1cbiAgY29uc3QgdXNlck9iamVjdCA9IFBhcnNlLk9iamVjdC5mcm9tSlNPTihvYmopO1xuICByZXR1cm4gbmV3IEF1dGgoe1xuICAgIGNvbmZpZyxcbiAgICBjYWNoZUNvbnRyb2xsZXIsXG4gICAgaXNNYXN0ZXI6IGZhbHNlLFxuICAgIGluc3RhbGxhdGlvbklkLFxuICAgIHVzZXI6IHVzZXJPYmplY3QsXG4gIH0pO1xufTtcblxudmFyIGdldEF1dGhGb3JMZWdhY3lTZXNzaW9uVG9rZW4gPSBmdW5jdGlvbih7XG4gIGNvbmZpZyxcbiAgc2Vzc2lvblRva2VuLFxuICBpbnN0YWxsYXRpb25JZCxcbn0pIHtcbiAgdmFyIHJlc3RPcHRpb25zID0ge1xuICAgIGxpbWl0OiAxLFxuICB9O1xuICB2YXIgcXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgIGNvbmZpZyxcbiAgICBtYXN0ZXIoY29uZmlnKSxcbiAgICAnX1VzZXInLFxuICAgIHsgc2Vzc2lvblRva2VuIH0sXG4gICAgcmVzdE9wdGlvbnNcbiAgKTtcbiAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICB2YXIgcmVzdWx0cyA9IHJlc3BvbnNlLnJlc3VsdHM7XG4gICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICAgJ2ludmFsaWQgbGVnYWN5IHNlc3Npb24gdG9rZW4nXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBvYmogPSByZXN1bHRzWzBdO1xuICAgIG9iai5jbGFzc05hbWUgPSAnX1VzZXInO1xuICAgIGNvbnN0IHVzZXJPYmplY3QgPSBQYXJzZS5PYmplY3QuZnJvbUpTT04ob2JqKTtcbiAgICByZXR1cm4gbmV3IEF1dGgoe1xuICAgICAgY29uZmlnLFxuICAgICAgaXNNYXN0ZXI6IGZhbHNlLFxuICAgICAgaW5zdGFsbGF0aW9uSWQsXG4gICAgICB1c2VyOiB1c2VyT2JqZWN0LFxuICAgIH0pO1xuICB9KTtcbn07XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2Ygcm9sZSBuYW1lc1xuQXV0aC5wcm90b3R5cGUuZ2V0VXNlclJvbGVzID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmlzTWFzdGVyIHx8ICF0aGlzLnVzZXIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFtdKTtcbiAgfVxuICBpZiAodGhpcy5mZXRjaGVkUm9sZXMpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMudXNlclJvbGVzKTtcbiAgfVxuICBpZiAodGhpcy5yb2xlUHJvbWlzZSkge1xuICAgIHJldHVybiB0aGlzLnJvbGVQcm9taXNlO1xuICB9XG4gIHRoaXMucm9sZVByb21pc2UgPSB0aGlzLl9sb2FkUm9sZXMoKTtcbiAgcmV0dXJuIHRoaXMucm9sZVByb21pc2U7XG59O1xuXG5BdXRoLnByb3RvdHlwZS5nZXRSb2xlc0ZvclVzZXIgPSBhc3luYyBmdW5jdGlvbigpIHtcbiAgLy9TdGFjayBhbGwgUGFyc2UuUm9sZVxuICBjb25zdCByZXN1bHRzID0gW107XG4gIGlmICh0aGlzLmNvbmZpZykge1xuICAgIGNvbnN0IHJlc3RXaGVyZSA9IHtcbiAgICAgIHVzZXJzOiB7XG4gICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICBjbGFzc05hbWU6ICdfVXNlcicsXG4gICAgICAgIG9iamVjdElkOiB0aGlzLnVzZXIuaWQsXG4gICAgICB9LFxuICAgIH07XG4gICAgYXdhaXQgbmV3IFJlc3RRdWVyeShcbiAgICAgIHRoaXMuY29uZmlnLFxuICAgICAgbWFzdGVyKHRoaXMuY29uZmlnKSxcbiAgICAgICdfUm9sZScsXG4gICAgICByZXN0V2hlcmUsXG4gICAgICB7fVxuICAgICkuZWFjaChyZXN1bHQgPT4gcmVzdWx0cy5wdXNoKHJlc3VsdCkpO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IG5ldyBQYXJzZS5RdWVyeShQYXJzZS5Sb2xlKVxuICAgICAgLmVxdWFsVG8oJ3VzZXJzJywgdGhpcy51c2VyKVxuICAgICAgLmVhY2gocmVzdWx0ID0+IHJlc3VsdHMucHVzaChyZXN1bHQudG9KU09OKCkpLCB7IHVzZU1hc3RlcktleTogdHJ1ZSB9KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cztcbn07XG5cbi8vIEl0ZXJhdGVzIHRocm91Z2ggdGhlIHJvbGUgdHJlZSBhbmQgY29tcGlsZXMgYSB1c2VyJ3Mgcm9sZXNcbkF1dGgucHJvdG90eXBlLl9sb2FkUm9sZXMgPSBhc3luYyBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuY2FjaGVDb250cm9sbGVyKSB7XG4gICAgY29uc3QgY2FjaGVkUm9sZXMgPSBhd2FpdCB0aGlzLmNhY2hlQ29udHJvbGxlci5yb2xlLmdldCh0aGlzLnVzZXIuaWQpO1xuICAgIGlmIChjYWNoZWRSb2xlcyAhPSBudWxsKSB7XG4gICAgICB0aGlzLmZldGNoZWRSb2xlcyA9IHRydWU7XG4gICAgICB0aGlzLnVzZXJSb2xlcyA9IGNhY2hlZFJvbGVzO1xuICAgICAgcmV0dXJuIGNhY2hlZFJvbGVzO1xuICAgIH1cbiAgfVxuXG4gIC8vIEZpcnN0IGdldCB0aGUgcm9sZSBpZHMgdGhpcyB1c2VyIGlzIGRpcmVjdGx5IGEgbWVtYmVyIG9mXG4gIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmdldFJvbGVzRm9yVXNlcigpO1xuICBpZiAoIXJlc3VsdHMubGVuZ3RoKSB7XG4gICAgdGhpcy51c2VyUm9sZXMgPSBbXTtcbiAgICB0aGlzLmZldGNoZWRSb2xlcyA9IHRydWU7XG4gICAgdGhpcy5yb2xlUHJvbWlzZSA9IG51bGw7XG5cbiAgICB0aGlzLmNhY2hlUm9sZXMoKTtcbiAgICByZXR1cm4gdGhpcy51c2VyUm9sZXM7XG4gIH1cblxuICBjb25zdCByb2xlc01hcCA9IHJlc3VsdHMucmVkdWNlKFxuICAgIChtLCByKSA9PiB7XG4gICAgICBtLm5hbWVzLnB1c2goci5uYW1lKTtcbiAgICAgIG0uaWRzLnB1c2goci5vYmplY3RJZCk7XG4gICAgICByZXR1cm4gbTtcbiAgICB9LFxuICAgIHsgaWRzOiBbXSwgbmFtZXM6IFtdIH1cbiAgKTtcblxuICAvLyBydW4gdGhlIHJlY3Vyc2l2ZSBmaW5kaW5nXG4gIGNvbnN0IHJvbGVOYW1lcyA9IGF3YWl0IHRoaXMuX2dldEFsbFJvbGVzTmFtZXNGb3JSb2xlSWRzKFxuICAgIHJvbGVzTWFwLmlkcyxcbiAgICByb2xlc01hcC5uYW1lc1xuICApO1xuICB0aGlzLnVzZXJSb2xlcyA9IHJvbGVOYW1lcy5tYXAociA9PiB7XG4gICAgcmV0dXJuICdyb2xlOicgKyByO1xuICB9KTtcbiAgdGhpcy5mZXRjaGVkUm9sZXMgPSB0cnVlO1xuICB0aGlzLnJvbGVQcm9taXNlID0gbnVsbDtcbiAgdGhpcy5jYWNoZVJvbGVzKCk7XG4gIHJldHVybiB0aGlzLnVzZXJSb2xlcztcbn07XG5cbkF1dGgucHJvdG90eXBlLmNhY2hlUm9sZXMgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLmNhY2hlQ29udHJvbGxlcikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB0aGlzLmNhY2hlQ29udHJvbGxlci5yb2xlLnB1dCh0aGlzLnVzZXIuaWQsIEFycmF5KC4uLnRoaXMudXNlclJvbGVzKSk7XG4gIHJldHVybiB0cnVlO1xufTtcblxuQXV0aC5wcm90b3R5cGUuZ2V0Um9sZXNCeUlkcyA9IGFzeW5jIGZ1bmN0aW9uKGlucykge1xuICBjb25zdCByZXN1bHRzID0gW107XG4gIC8vIEJ1aWxkIGFuIE9SIHF1ZXJ5IGFjcm9zcyBhbGwgcGFyZW50Um9sZXNcbiAgaWYgKCF0aGlzLmNvbmZpZykge1xuICAgIGF3YWl0IG5ldyBQYXJzZS5RdWVyeShQYXJzZS5Sb2xlKVxuICAgICAgLmNvbnRhaW5lZEluKFxuICAgICAgICAncm9sZXMnLFxuICAgICAgICBpbnMubWFwKGlkID0+IHtcbiAgICAgICAgICBjb25zdCByb2xlID0gbmV3IFBhcnNlLk9iamVjdChQYXJzZS5Sb2xlKTtcbiAgICAgICAgICByb2xlLmlkID0gaWQ7XG4gICAgICAgICAgcmV0dXJuIHJvbGU7XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuZWFjaChyZXN1bHQgPT4gcmVzdWx0cy5wdXNoKHJlc3VsdC50b0pTT04oKSksIHsgdXNlTWFzdGVyS2V5OiB0cnVlIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHJvbGVzID0gaW5zLm1hcChpZCA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgY2xhc3NOYW1lOiAnX1JvbGUnLFxuICAgICAgICBvYmplY3RJZDogaWQsXG4gICAgICB9O1xuICAgIH0pO1xuICAgIGNvbnN0IHJlc3RXaGVyZSA9IHsgcm9sZXM6IHsgJGluOiByb2xlcyB9IH07XG4gICAgYXdhaXQgbmV3IFJlc3RRdWVyeShcbiAgICAgIHRoaXMuY29uZmlnLFxuICAgICAgbWFzdGVyKHRoaXMuY29uZmlnKSxcbiAgICAgICdfUm9sZScsXG4gICAgICByZXN0V2hlcmUsXG4gICAgICB7fVxuICAgICkuZWFjaChyZXN1bHQgPT4gcmVzdWx0cy5wdXNoKHJlc3VsdCkpO1xuICB9XG4gIHJldHVybiByZXN1bHRzO1xufTtcblxuLy8gR2l2ZW4gYSBsaXN0IG9mIHJvbGVJZHMsIGZpbmQgYWxsIHRoZSBwYXJlbnQgcm9sZXMsIHJldHVybnMgYSBwcm9taXNlIHdpdGggYWxsIG5hbWVzXG5BdXRoLnByb3RvdHlwZS5fZ2V0QWxsUm9sZXNOYW1lc0ZvclJvbGVJZHMgPSBmdW5jdGlvbihcbiAgcm9sZUlEcyxcbiAgbmFtZXMgPSBbXSxcbiAgcXVlcmllZFJvbGVzID0ge31cbikge1xuICBjb25zdCBpbnMgPSByb2xlSURzLmZpbHRlcihyb2xlSUQgPT4ge1xuICAgIGNvbnN0IHdhc1F1ZXJpZWQgPSBxdWVyaWVkUm9sZXNbcm9sZUlEXSAhPT0gdHJ1ZTtcbiAgICBxdWVyaWVkUm9sZXNbcm9sZUlEXSA9IHRydWU7XG4gICAgcmV0dXJuIHdhc1F1ZXJpZWQ7XG4gIH0pO1xuXG4gIC8vIGFsbCByb2xlcyBhcmUgYWNjb3VudGVkIGZvciwgcmV0dXJuIHRoZSBuYW1lc1xuICBpZiAoaW5zLmxlbmd0aCA9PSAwKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShbLi4ubmV3IFNldChuYW1lcyldKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzLmdldFJvbGVzQnlJZHMoaW5zKVxuICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgLy8gTm90aGluZyBmb3VuZFxuICAgICAgaWYgKCFyZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5hbWVzKTtcbiAgICAgIH1cbiAgICAgIC8vIE1hcCB0aGUgcmVzdWx0cyB3aXRoIGFsbCBJZHMgYW5kIG5hbWVzXG4gICAgICBjb25zdCByZXN1bHRNYXAgPSByZXN1bHRzLnJlZHVjZShcbiAgICAgICAgKG1lbW8sIHJvbGUpID0+IHtcbiAgICAgICAgICBtZW1vLm5hbWVzLnB1c2gocm9sZS5uYW1lKTtcbiAgICAgICAgICBtZW1vLmlkcy5wdXNoKHJvbGUub2JqZWN0SWQpO1xuICAgICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgICB9LFxuICAgICAgICB7IGlkczogW10sIG5hbWVzOiBbXSB9XG4gICAgICApO1xuICAgICAgLy8gc3RvcmUgdGhlIG5ldyBmb3VuZCBuYW1lc1xuICAgICAgbmFtZXMgPSBuYW1lcy5jb25jYXQocmVzdWx0TWFwLm5hbWVzKTtcbiAgICAgIC8vIGZpbmQgdGhlIG5leHQgb25lcywgY2lyY3VsYXIgcm9sZXMgd2lsbCBiZSBjdXRcbiAgICAgIHJldHVybiB0aGlzLl9nZXRBbGxSb2xlc05hbWVzRm9yUm9sZUlkcyhcbiAgICAgICAgcmVzdWx0TWFwLmlkcyxcbiAgICAgICAgbmFtZXMsXG4gICAgICAgIHF1ZXJpZWRSb2xlc1xuICAgICAgKTtcbiAgICB9KVxuICAgIC50aGVuKG5hbWVzID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoWy4uLm5ldyBTZXQobmFtZXMpXSk7XG4gICAgfSk7XG59O1xuXG5jb25zdCBjcmVhdGVTZXNzaW9uID0gZnVuY3Rpb24oXG4gIGNvbmZpZyxcbiAgeyB1c2VySWQsIGNyZWF0ZWRXaXRoLCBpbnN0YWxsYXRpb25JZCwgYWRkaXRpb25hbFNlc3Npb25EYXRhIH1cbikge1xuICBjb25zdCB0b2tlbiA9ICdyOicgKyBjcnlwdG9VdGlscy5uZXdUb2tlbigpO1xuICBjb25zdCBleHBpcmVzQXQgPSBjb25maWcuZ2VuZXJhdGVTZXNzaW9uRXhwaXJlc0F0KCk7XG4gIGNvbnN0IHNlc3Npb25EYXRhID0ge1xuICAgIHNlc3Npb25Ub2tlbjogdG9rZW4sXG4gICAgdXNlcjoge1xuICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICBjbGFzc05hbWU6ICdfVXNlcicsXG4gICAgICBvYmplY3RJZDogdXNlcklkLFxuICAgIH0sXG4gICAgY3JlYXRlZFdpdGgsXG4gICAgcmVzdHJpY3RlZDogZmFsc2UsXG4gICAgZXhwaXJlc0F0OiBQYXJzZS5fZW5jb2RlKGV4cGlyZXNBdCksXG4gIH07XG5cbiAgaWYgKGluc3RhbGxhdGlvbklkKSB7XG4gICAgc2Vzc2lvbkRhdGEuaW5zdGFsbGF0aW9uSWQgPSBpbnN0YWxsYXRpb25JZDtcbiAgfVxuXG4gIE9iamVjdC5hc3NpZ24oc2Vzc2lvbkRhdGEsIGFkZGl0aW9uYWxTZXNzaW9uRGF0YSk7XG4gIC8vIFdlIG5lZWQgdG8gaW1wb3J0IFJlc3RXcml0ZSBhdCB0aGlzIHBvaW50IGZvciB0aGUgY3ljbGljIGRlcGVuZGVuY3kgaXQgaGFzIHRvIGl0XG4gIGNvbnN0IFJlc3RXcml0ZSA9IHJlcXVpcmUoJy4vUmVzdFdyaXRlJyk7XG5cbiAgcmV0dXJuIHtcbiAgICBzZXNzaW9uRGF0YSxcbiAgICBjcmVhdGVTZXNzaW9uOiAoKSA9PlxuICAgICAgbmV3IFJlc3RXcml0ZShcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBtYXN0ZXIoY29uZmlnKSxcbiAgICAgICAgJ19TZXNzaW9uJyxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgc2Vzc2lvbkRhdGFcbiAgICAgICkuZXhlY3V0ZSgpLFxuICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIEF1dGgsXG4gIG1hc3RlcixcbiAgbm9ib2R5LFxuICByZWFkT25seSxcbiAgZ2V0QXV0aEZvclNlc3Npb25Ub2tlbixcbiAgZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbixcbiAgY3JlYXRlU2Vzc2lvbixcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/ClientSDK.js b/lib/ClientSDK.js new file mode 100644 index 0000000000..4aa9143c9f --- /dev/null +++ b/lib/ClientSDK.js @@ -0,0 +1,47 @@ +"use strict"; + +var semver = require('semver'); + +function compatible(compatibleSDK) { + return function (clientSDK) { + if (typeof clientSDK === 'string') { + clientSDK = fromString(clientSDK); + } // REST API, or custom SDK + + + if (!clientSDK) { + return true; + } + + const clientVersion = clientSDK.version; + const compatiblityVersion = compatibleSDK[clientSDK.sdk]; + return semver.satisfies(clientVersion, compatiblityVersion); + }; +} + +function supportsForwardDelete(clientSDK) { + return compatible({ + js: '>=1.9.0' + })(clientSDK); +} + +function fromString(version) { + const versionRE = /([-a-zA-Z]+)([0-9\.]+)/; + const match = version.toLowerCase().match(versionRE); + + if (match && match.length === 3) { + return { + sdk: match[1], + version: match[2] + }; + } + + return undefined; +} + +module.exports = { + compatible, + supportsForwardDelete, + fromString +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9DbGllbnRTREsuanMiXSwibmFtZXMiOlsic2VtdmVyIiwicmVxdWlyZSIsImNvbXBhdGlibGUiLCJjb21wYXRpYmxlU0RLIiwiY2xpZW50U0RLIiwiZnJvbVN0cmluZyIsImNsaWVudFZlcnNpb24iLCJ2ZXJzaW9uIiwiY29tcGF0aWJsaXR5VmVyc2lvbiIsInNkayIsInNhdGlzZmllcyIsInN1cHBvcnRzRm9yd2FyZERlbGV0ZSIsImpzIiwidmVyc2lvblJFIiwibWF0Y2giLCJ0b0xvd2VyQ2FzZSIsImxlbmd0aCIsInVuZGVmaW5lZCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUEsSUFBSUEsTUFBTSxHQUFHQyxPQUFPLENBQUMsUUFBRCxDQUFwQjs7QUFFQSxTQUFTQyxVQUFULENBQW9CQyxhQUFwQixFQUFtQztBQUNqQyxTQUFPLFVBQVNDLFNBQVQsRUFBb0I7QUFDekIsUUFBSSxPQUFPQSxTQUFQLEtBQXFCLFFBQXpCLEVBQW1DO0FBQ2pDQSxNQUFBQSxTQUFTLEdBQUdDLFVBQVUsQ0FBQ0QsU0FBRCxDQUF0QjtBQUNELEtBSHdCLENBSXpCOzs7QUFDQSxRQUFJLENBQUNBLFNBQUwsRUFBZ0I7QUFDZCxhQUFPLElBQVA7QUFDRDs7QUFDRCxVQUFNRSxhQUFhLEdBQUdGLFNBQVMsQ0FBQ0csT0FBaEM7QUFDQSxVQUFNQyxtQkFBbUIsR0FBR0wsYUFBYSxDQUFDQyxTQUFTLENBQUNLLEdBQVgsQ0FBekM7QUFDQSxXQUFPVCxNQUFNLENBQUNVLFNBQVAsQ0FBaUJKLGFBQWpCLEVBQWdDRSxtQkFBaEMsQ0FBUDtBQUNELEdBWEQ7QUFZRDs7QUFFRCxTQUFTRyxxQkFBVCxDQUErQlAsU0FBL0IsRUFBMEM7QUFDeEMsU0FBT0YsVUFBVSxDQUFDO0FBQ2hCVSxJQUFBQSxFQUFFLEVBQUU7QUFEWSxHQUFELENBQVYsQ0FFSlIsU0FGSSxDQUFQO0FBR0Q7O0FBRUQsU0FBU0MsVUFBVCxDQUFvQkUsT0FBcEIsRUFBNkI7QUFDM0IsUUFBTU0sU0FBUyxHQUFHLHdCQUFsQjtBQUNBLFFBQU1DLEtBQUssR0FBR1AsT0FBTyxDQUFDUSxXQUFSLEdBQXNCRCxLQUF0QixDQUE0QkQsU0FBNUIsQ0FBZDs7QUFDQSxNQUFJQyxLQUFLLElBQUlBLEtBQUssQ0FBQ0UsTUFBTixLQUFpQixDQUE5QixFQUFpQztBQUMvQixXQUFPO0FBQ0xQLE1BQUFBLEdBQUcsRUFBRUssS0FBSyxDQUFDLENBQUQsQ0FETDtBQUVMUCxNQUFBQSxPQUFPLEVBQUVPLEtBQUssQ0FBQyxDQUFEO0FBRlQsS0FBUDtBQUlEOztBQUNELFNBQU9HLFNBQVA7QUFDRDs7QUFFREMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZqQixFQUFBQSxVQURlO0FBRWZTLEVBQUFBLHFCQUZlO0FBR2ZOLEVBQUFBO0FBSGUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgc2VtdmVyID0gcmVxdWlyZSgnc2VtdmVyJyk7XG5cbmZ1bmN0aW9uIGNvbXBhdGlibGUoY29tcGF0aWJsZVNESykge1xuICByZXR1cm4gZnVuY3Rpb24oY2xpZW50U0RLKSB7XG4gICAgaWYgKHR5cGVvZiBjbGllbnRTREsgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjbGllbnRTREsgPSBmcm9tU3RyaW5nKGNsaWVudFNESyk7XG4gICAgfVxuICAgIC8vIFJFU1QgQVBJLCBvciBjdXN0b20gU0RLXG4gICAgaWYgKCFjbGllbnRTREspIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCBjbGllbnRWZXJzaW9uID0gY2xpZW50U0RLLnZlcnNpb247XG4gICAgY29uc3QgY29tcGF0aWJsaXR5VmVyc2lvbiA9IGNvbXBhdGlibGVTREtbY2xpZW50U0RLLnNka107XG4gICAgcmV0dXJuIHNlbXZlci5zYXRpc2ZpZXMoY2xpZW50VmVyc2lvbiwgY29tcGF0aWJsaXR5VmVyc2lvbik7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHN1cHBvcnRzRm9yd2FyZERlbGV0ZShjbGllbnRTREspIHtcbiAgcmV0dXJuIGNvbXBhdGlibGUoe1xuICAgIGpzOiAnPj0xLjkuMCcsXG4gIH0pKGNsaWVudFNESyk7XG59XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmcodmVyc2lvbikge1xuICBjb25zdCB2ZXJzaW9uUkUgPSAvKFstYS16QS1aXSspKFswLTlcXC5dKykvO1xuICBjb25zdCBtYXRjaCA9IHZlcnNpb24udG9Mb3dlckNhc2UoKS5tYXRjaCh2ZXJzaW9uUkUpO1xuICBpZiAobWF0Y2ggJiYgbWF0Y2gubGVuZ3RoID09PSAzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNkazogbWF0Y2hbMV0sXG4gICAgICB2ZXJzaW9uOiBtYXRjaFsyXSxcbiAgICB9O1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBjb21wYXRpYmxlLFxuICBzdXBwb3J0c0ZvcndhcmREZWxldGUsXG4gIGZyb21TdHJpbmcsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Config.js b/lib/Config.js new file mode 100644 index 0000000000..f490971b57 --- /dev/null +++ b/lib/Config.js @@ -0,0 +1,324 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.Config = void 0; + +var _cache = _interopRequireDefault(require("./cache")); + +var _SchemaCache = _interopRequireDefault(require("./Controllers/SchemaCache")); + +var _DatabaseController = _interopRequireDefault(require("./Controllers/DatabaseController")); + +var _net = _interopRequireDefault(require("net")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// A Config object provides information about how a specific app is +// configured. +// mount is the URL for the root of the API; includes http, domain, etc. +function removeTrailingSlash(str) { + if (!str) { + return str; + } + + if (str.endsWith('/')) { + str = str.substr(0, str.length - 1); + } + + return str; +} + +class Config { + static get(applicationId, mount) { + const cacheInfo = _cache.default.get(applicationId); + + if (!cacheInfo) { + return; + } + + const config = new Config(); + config.applicationId = applicationId; + Object.keys(cacheInfo).forEach(key => { + if (key == 'databaseController') { + const schemaCache = new _SchemaCache.default(cacheInfo.cacheController, cacheInfo.schemaCacheTTL, cacheInfo.enableSingleSchemaCache); + config.database = new _DatabaseController.default(cacheInfo.databaseController.adapter, schemaCache, cacheInfo.skipMongoDBServer13732Workaround); + } else { + config[key] = cacheInfo[key]; + } + }); + config.mount = removeTrailingSlash(mount); + config.generateSessionExpiresAt = config.generateSessionExpiresAt.bind(config); + config.generateEmailVerifyTokenExpiresAt = config.generateEmailVerifyTokenExpiresAt.bind(config); + return config; + } + + static put(serverConfiguration) { + Config.validate(serverConfiguration); + + _cache.default.put(serverConfiguration.appId, serverConfiguration); + + Config.setupPasswordValidator(serverConfiguration.passwordPolicy); + return serverConfiguration; + } + + static validate({ + verifyUserEmails, + userController, + appName, + publicServerURL, + revokeSessionOnPasswordReset, + expireInactiveSessions, + sessionLength, + maxLimit, + emailVerifyTokenValidityDuration, + accountLockout, + passwordPolicy, + masterKeyIps, + masterKey, + readOnlyMasterKey, + allowHeaders + }) { + if (masterKey === readOnlyMasterKey) { + throw new Error('masterKey and readOnlyMasterKey should be different'); + } + + const emailAdapter = userController.adapter; + + if (verifyUserEmails) { + this.validateEmailConfiguration({ + emailAdapter, + appName, + publicServerURL, + emailVerifyTokenValidityDuration + }); + } + + this.validateAccountLockoutPolicy(accountLockout); + this.validatePasswordPolicy(passwordPolicy); + + if (typeof revokeSessionOnPasswordReset !== 'boolean') { + throw 'revokeSessionOnPasswordReset must be a boolean value'; + } + + if (publicServerURL) { + if (!publicServerURL.startsWith('http://') && !publicServerURL.startsWith('https://')) { + throw 'publicServerURL should be a valid HTTPS URL starting with https://'; + } + } + + this.validateSessionConfiguration(sessionLength, expireInactiveSessions); + this.validateMasterKeyIps(masterKeyIps); + this.validateMaxLimit(maxLimit); + this.validateAllowHeaders(allowHeaders); + } + + static validateAccountLockoutPolicy(accountLockout) { + if (accountLockout) { + if (typeof accountLockout.duration !== 'number' || accountLockout.duration <= 0 || accountLockout.duration > 99999) { + throw 'Account lockout duration should be greater than 0 and less than 100000'; + } + + if (!Number.isInteger(accountLockout.threshold) || accountLockout.threshold < 1 || accountLockout.threshold > 999) { + throw 'Account lockout threshold should be an integer greater than 0 and less than 1000'; + } + } + } + + static validatePasswordPolicy(passwordPolicy) { + if (passwordPolicy) { + if (passwordPolicy.maxPasswordAge !== undefined && (typeof passwordPolicy.maxPasswordAge !== 'number' || passwordPolicy.maxPasswordAge < 0)) { + throw 'passwordPolicy.maxPasswordAge must be a positive number'; + } + + if (passwordPolicy.resetTokenValidityDuration !== undefined && (typeof passwordPolicy.resetTokenValidityDuration !== 'number' || passwordPolicy.resetTokenValidityDuration <= 0)) { + throw 'passwordPolicy.resetTokenValidityDuration must be a positive number'; + } + + if (passwordPolicy.validatorPattern) { + if (typeof passwordPolicy.validatorPattern === 'string') { + passwordPolicy.validatorPattern = new RegExp(passwordPolicy.validatorPattern); + } else if (!(passwordPolicy.validatorPattern instanceof RegExp)) { + throw 'passwordPolicy.validatorPattern must be a regex string or RegExp object.'; + } + } + + if (passwordPolicy.validatorCallback && typeof passwordPolicy.validatorCallback !== 'function') { + throw 'passwordPolicy.validatorCallback must be a function.'; + } + + if (passwordPolicy.doNotAllowUsername && typeof passwordPolicy.doNotAllowUsername !== 'boolean') { + throw 'passwordPolicy.doNotAllowUsername must be a boolean value.'; + } + + if (passwordPolicy.maxPasswordHistory && (!Number.isInteger(passwordPolicy.maxPasswordHistory) || passwordPolicy.maxPasswordHistory <= 0 || passwordPolicy.maxPasswordHistory > 20)) { + throw 'passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20'; + } + } + } // if the passwordPolicy.validatorPattern is configured then setup a callback to process the pattern + + + static setupPasswordValidator(passwordPolicy) { + if (passwordPolicy && passwordPolicy.validatorPattern) { + passwordPolicy.patternValidator = value => { + return passwordPolicy.validatorPattern.test(value); + }; + } + } + + static validateEmailConfiguration({ + emailAdapter, + appName, + publicServerURL, + emailVerifyTokenValidityDuration + }) { + if (!emailAdapter) { + throw 'An emailAdapter is required for e-mail verification and password resets.'; + } + + if (typeof appName !== 'string') { + throw 'An app name is required for e-mail verification and password resets.'; + } + + if (typeof publicServerURL !== 'string') { + throw 'A public server url is required for e-mail verification and password resets.'; + } + + if (emailVerifyTokenValidityDuration) { + if (isNaN(emailVerifyTokenValidityDuration)) { + throw 'Email verify token validity duration must be a valid number.'; + } else if (emailVerifyTokenValidityDuration <= 0) { + throw 'Email verify token validity duration must be a value greater than 0.'; + } + } + } + + static validateMasterKeyIps(masterKeyIps) { + for (const ip of masterKeyIps) { + if (!_net.default.isIP(ip)) { + throw `Invalid ip in masterKeyIps: ${ip}`; + } + } + } + + get mount() { + var mount = this._mount; + + if (this.publicServerURL) { + mount = this.publicServerURL; + } + + return mount; + } + + set mount(newValue) { + this._mount = newValue; + } + + static validateSessionConfiguration(sessionLength, expireInactiveSessions) { + if (expireInactiveSessions) { + if (isNaN(sessionLength)) { + throw 'Session length must be a valid number.'; + } else if (sessionLength <= 0) { + throw 'Session length must be a value greater than 0.'; + } + } + } + + static validateMaxLimit(maxLimit) { + if (maxLimit <= 0) { + throw 'Max limit must be a value greater than 0.'; + } + } + + static validateAllowHeaders(allowHeaders) { + if (![null, undefined].includes(allowHeaders)) { + if (Array.isArray(allowHeaders)) { + allowHeaders.forEach(header => { + if (typeof header !== 'string') { + throw 'Allow headers must only contain strings'; + } else if (!header.trim().length) { + throw 'Allow headers must not contain empty strings'; + } + }); + } else { + throw 'Allow headers must be an array'; + } + } + } + + generateEmailVerifyTokenExpiresAt() { + if (!this.verifyUserEmails || !this.emailVerifyTokenValidityDuration) { + return undefined; + } + + var now = new Date(); + return new Date(now.getTime() + this.emailVerifyTokenValidityDuration * 1000); + } + + generatePasswordResetTokenExpiresAt() { + if (!this.passwordPolicy || !this.passwordPolicy.resetTokenValidityDuration) { + return undefined; + } + + const now = new Date(); + return new Date(now.getTime() + this.passwordPolicy.resetTokenValidityDuration * 1000); + } + + generateSessionExpiresAt() { + if (!this.expireInactiveSessions) { + return undefined; + } + + var now = new Date(); + return new Date(now.getTime() + this.sessionLength * 1000); + } + + get invalidLinkURL() { + return this.customPages.invalidLink || `${this.publicServerURL}/apps/invalid_link.html`; + } + + get invalidVerificationLinkURL() { + return this.customPages.invalidVerificationLink || `${this.publicServerURL}/apps/invalid_verification_link.html`; + } + + get linkSendSuccessURL() { + return this.customPages.linkSendSuccess || `${this.publicServerURL}/apps/link_send_success.html`; + } + + get linkSendFailURL() { + return this.customPages.linkSendFail || `${this.publicServerURL}/apps/link_send_fail.html`; + } + + get verifyEmailSuccessURL() { + return this.customPages.verifyEmailSuccess || `${this.publicServerURL}/apps/verify_email_success.html`; + } + + get choosePasswordURL() { + return this.customPages.choosePassword || `${this.publicServerURL}/apps/choose_password`; + } + + get requestResetPasswordURL() { + return `${this.publicServerURL}/apps/${this.applicationId}/request_password_reset`; + } + + get passwordResetSuccessURL() { + return this.customPages.passwordResetSuccess || `${this.publicServerURL}/apps/password_reset_success.html`; + } + + get parseFrameURL() { + return this.customPages.parseFrameURL; + } + + get verifyEmailURL() { + return `${this.publicServerURL}/apps/${this.applicationId}/verify_email`; + } + +} + +exports.Config = Config; +var _default = Config; +exports.default = _default; +module.exports = Config; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db25maWcuanMiXSwibmFtZXMiOlsicmVtb3ZlVHJhaWxpbmdTbGFzaCIsInN0ciIsImVuZHNXaXRoIiwic3Vic3RyIiwibGVuZ3RoIiwiQ29uZmlnIiwiZ2V0IiwiYXBwbGljYXRpb25JZCIsIm1vdW50IiwiY2FjaGVJbmZvIiwiQXBwQ2FjaGUiLCJjb25maWciLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsImtleSIsInNjaGVtYUNhY2hlIiwiU2NoZW1hQ2FjaGUiLCJjYWNoZUNvbnRyb2xsZXIiLCJzY2hlbWFDYWNoZVRUTCIsImVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlIiwiZGF0YWJhc2UiLCJEYXRhYmFzZUNvbnRyb2xsZXIiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJhZGFwdGVyIiwic2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQiLCJnZW5lcmF0ZVNlc3Npb25FeHBpcmVzQXQiLCJiaW5kIiwiZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuRXhwaXJlc0F0IiwicHV0Iiwic2VydmVyQ29uZmlndXJhdGlvbiIsInZhbGlkYXRlIiwiYXBwSWQiLCJzZXR1cFBhc3N3b3JkVmFsaWRhdG9yIiwicGFzc3dvcmRQb2xpY3kiLCJ2ZXJpZnlVc2VyRW1haWxzIiwidXNlckNvbnRyb2xsZXIiLCJhcHBOYW1lIiwicHVibGljU2VydmVyVVJMIiwicmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCIsImV4cGlyZUluYWN0aXZlU2Vzc2lvbnMiLCJzZXNzaW9uTGVuZ3RoIiwibWF4TGltaXQiLCJlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbiIsImFjY291bnRMb2Nrb3V0IiwibWFzdGVyS2V5SXBzIiwibWFzdGVyS2V5IiwicmVhZE9ubHlNYXN0ZXJLZXkiLCJhbGxvd0hlYWRlcnMiLCJFcnJvciIsImVtYWlsQWRhcHRlciIsInZhbGlkYXRlRW1haWxDb25maWd1cmF0aW9uIiwidmFsaWRhdGVBY2NvdW50TG9ja291dFBvbGljeSIsInZhbGlkYXRlUGFzc3dvcmRQb2xpY3kiLCJzdGFydHNXaXRoIiwidmFsaWRhdGVTZXNzaW9uQ29uZmlndXJhdGlvbiIsInZhbGlkYXRlTWFzdGVyS2V5SXBzIiwidmFsaWRhdGVNYXhMaW1pdCIsInZhbGlkYXRlQWxsb3dIZWFkZXJzIiwiZHVyYXRpb24iLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJ0aHJlc2hvbGQiLCJtYXhQYXNzd29yZEFnZSIsInVuZGVmaW5lZCIsInJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uIiwidmFsaWRhdG9yUGF0dGVybiIsIlJlZ0V4cCIsInZhbGlkYXRvckNhbGxiYWNrIiwiZG9Ob3RBbGxvd1VzZXJuYW1lIiwibWF4UGFzc3dvcmRIaXN0b3J5IiwicGF0dGVyblZhbGlkYXRvciIsInZhbHVlIiwidGVzdCIsImlzTmFOIiwiaXAiLCJuZXQiLCJpc0lQIiwiX21vdW50IiwibmV3VmFsdWUiLCJpbmNsdWRlcyIsIkFycmF5IiwiaXNBcnJheSIsImhlYWRlciIsInRyaW0iLCJub3ciLCJEYXRlIiwiZ2V0VGltZSIsImdlbmVyYXRlUGFzc3dvcmRSZXNldFRva2VuRXhwaXJlc0F0IiwiaW52YWxpZExpbmtVUkwiLCJjdXN0b21QYWdlcyIsImludmFsaWRMaW5rIiwiaW52YWxpZFZlcmlmaWNhdGlvbkxpbmtVUkwiLCJpbnZhbGlkVmVyaWZpY2F0aW9uTGluayIsImxpbmtTZW5kU3VjY2Vzc1VSTCIsImxpbmtTZW5kU3VjY2VzcyIsImxpbmtTZW5kRmFpbFVSTCIsImxpbmtTZW5kRmFpbCIsInZlcmlmeUVtYWlsU3VjY2Vzc1VSTCIsInZlcmlmeUVtYWlsU3VjY2VzcyIsImNob29zZVBhc3N3b3JkVVJMIiwiY2hvb3NlUGFzc3dvcmQiLCJyZXF1ZXN0UmVzZXRQYXNzd29yZFVSTCIsInBhc3N3b3JkUmVzZXRTdWNjZXNzVVJMIiwicGFzc3dvcmRSZXNldFN1Y2Nlc3MiLCJwYXJzZUZyYW1lVVJMIiwidmVyaWZ5RW1haWxVUkwiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1h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O0FBQ0Q7O0FBMVZpQjs7O2VBNlZMRixNOztBQUNmc0csTUFBTSxDQUFDQyxPQUFQLEdBQWlCdkcsTUFBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBBIENvbmZpZyBvYmplY3QgcHJvdmlkZXMgaW5mb3JtYXRpb24gYWJvdXQgaG93IGEgc3BlY2lmaWMgYXBwIGlzXG4vLyBjb25maWd1cmVkLlxuLy8gbW91bnQgaXMgdGhlIFVSTCBmb3IgdGhlIHJvb3Qgb2YgdGhlIEFQSTsgaW5jbHVkZXMgaHR0cCwgZG9tYWluLCBldGMuXG5cbmltcG9ydCBBcHBDYWNoZSBmcm9tICcuL2NhY2hlJztcbmltcG9ydCBTY2hlbWFDYWNoZSBmcm9tICcuL0NvbnRyb2xsZXJzL1NjaGVtYUNhY2hlJztcbmltcG9ydCBEYXRhYmFzZUNvbnRyb2xsZXIgZnJvbSAnLi9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXInO1xuaW1wb3J0IG5ldCBmcm9tICduZXQnO1xuXG5mdW5jdGlvbiByZW1vdmVUcmFpbGluZ1NsYXNoKHN0cikge1xuICBpZiAoIXN0cikge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbiAgaWYgKHN0ci5lbmRzV2l0aCgnLycpKSB7XG4gICAgc3RyID0gc3RyLnN1YnN0cigwLCBzdHIubGVuZ3RoIC0gMSk7XG4gIH1cbiAgcmV0dXJuIHN0cjtcbn1cblxuZXhwb3J0IGNsYXNzIENvbmZpZyB7XG4gIHN0YXRpYyBnZXQoYXBwbGljYXRpb25JZDogc3RyaW5nLCBtb3VudDogc3RyaW5nKSB7XG4gICAgY29uc3QgY2FjaGVJbmZvID0gQXBwQ2FjaGUuZ2V0KGFwcGxpY2F0aW9uSWQpO1xuICAgIGlmICghY2FjaGVJbmZvKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZyA9IG5ldyBDb25maWcoKTtcbiAgICBjb25maWcuYXBwbGljYXRpb25JZCA9IGFwcGxpY2F0aW9uSWQ7XG4gICAgT2JqZWN0LmtleXMoY2FjaGVJbmZvKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBpZiAoa2V5ID09ICdkYXRhYmFzZUNvbnRyb2xsZXInKSB7XG4gICAgICAgIGNvbnN0IHNjaGVtYUNhY2hlID0gbmV3IFNjaGVtYUNhY2hlKFxuICAgICAgICAgIGNhY2hlSW5mby5jYWNoZUNvbnRyb2xsZXIsXG4gICAgICAgICAgY2FjaGVJbmZvLnNjaGVtYUNhY2hlVFRMLFxuICAgICAgICAgIGNhY2hlSW5mby5lbmFibGVTaW5nbGVTY2hlbWFDYWNoZVxuICAgICAgICApO1xuICAgICAgICBjb25maWcuZGF0YWJhc2UgPSBuZXcgRGF0YWJhc2VDb250cm9sbGVyKFxuICAgICAgICAgIGNhY2hlSW5mby5kYXRhYmFzZUNvbnRyb2xsZXIuYWRhcHRlcixcbiAgICAgICAgICBzY2hlbWFDYWNoZSxcbiAgICAgICAgICBjYWNoZUluZm8uc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmRcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbmZpZ1trZXldID0gY2FjaGVJbmZvW2tleV07XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29uZmlnLm1vdW50ID0gcmVtb3ZlVHJhaWxpbmdTbGFzaChtb3VudCk7XG4gICAgY29uZmlnLmdlbmVyYXRlU2Vzc2lvbkV4cGlyZXNBdCA9IGNvbmZpZy5nZW5lcmF0ZVNlc3Npb25FeHBpcmVzQXQuYmluZChcbiAgICAgIGNvbmZpZ1xuICAgICk7XG4gICAgY29uZmlnLmdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbkV4cGlyZXNBdCA9IGNvbmZpZy5nZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW5FeHBpcmVzQXQuYmluZChcbiAgICAgIGNvbmZpZ1xuICAgICk7XG4gICAgcmV0dXJuIGNvbmZpZztcbiAgfVxuXG4gIHN0YXRpYyBwdXQoc2VydmVyQ29uZmlndXJhdGlvbikge1xuICAgIENvbmZpZy52YWxpZGF0ZShzZXJ2ZXJDb25maWd1cmF0aW9uKTtcbiAgICBBcHBDYWNoZS5wdXQoc2VydmVyQ29uZmlndXJhdGlvbi5hcHBJZCwgc2VydmVyQ29uZmlndXJhdGlvbik7XG4gICAgQ29uZmlnLnNldHVwUGFzc3dvcmRWYWxpZGF0b3Ioc2VydmVyQ29uZmlndXJhdGlvbi5wYXNzd29yZFBvbGljeSk7XG4gICAgcmV0dXJuIHNlcnZlckNvbmZpZ3VyYXRpb247XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGUoe1xuICAgIHZlcmlmeVVzZXJFbWFpbHMsXG4gICAgdXNlckNvbnRyb2xsZXIsXG4gICAgYXBwTmFtZSxcbiAgICBwdWJsaWNTZXJ2ZXJVUkwsXG4gICAgcmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCxcbiAgICBleHBpcmVJbmFjdGl2ZVNlc3Npb25zLFxuICAgIHNlc3Npb25MZW5ndGgsXG4gICAgbWF4TGltaXQsXG4gICAgZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24sXG4gICAgYWNjb3VudExvY2tvdXQsXG4gICAgcGFzc3dvcmRQb2xpY3ksXG4gICAgbWFzdGVyS2V5SXBzLFxuICAgIG1hc3RlcktleSxcbiAgICByZWFkT25seU1hc3RlcktleSxcbiAgICBhbGxvd0hlYWRlcnMsXG4gIH0pIHtcbiAgICBpZiAobWFzdGVyS2V5ID09PSByZWFkT25seU1hc3RlcktleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtYXN0ZXJLZXkgYW5kIHJlYWRPbmx5TWFzdGVyS2V5IHNob3VsZCBiZSBkaWZmZXJlbnQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBlbWFpbEFkYXB0ZXIgPSB1c2VyQ29udHJvbGxlci5hZGFwdGVyO1xuICAgIGlmICh2ZXJpZnlVc2VyRW1haWxzKSB7XG4gICAgICB0aGlzLnZhbGlkYXRlRW1haWxDb25maWd1cmF0aW9uKHtcbiAgICAgICAgZW1haWxBZGFwdGVyLFxuICAgICAgICBhcHBOYW1lLFxuICAgICAgICBwdWJsaWNTZXJ2ZXJVUkwsXG4gICAgICAgIGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy52YWxpZGF0ZUFjY291bnRMb2Nrb3V0UG9saWN5KGFjY291bnRMb2Nrb3V0KTtcblxuICAgIHRoaXMudmFsaWRhdGVQYXNzd29yZFBvbGljeShwYXNzd29yZFBvbGljeSk7XG5cbiAgICBpZiAodHlwZW9mIHJldm9rZVNlc3Npb25PblBhc3N3b3JkUmVzZXQgIT09ICdib29sZWFuJykge1xuICAgICAgdGhyb3cgJ3Jldm9rZVNlc3Npb25PblBhc3N3b3JkUmVzZXQgbXVzdCBiZSBhIGJvb2xlYW4gdmFsdWUnO1xuICAgIH1cblxuICAgIGlmIChwdWJsaWNTZXJ2ZXJVUkwpIHtcbiAgICAgIGlmIChcbiAgICAgICAgIXB1YmxpY1NlcnZlclVSTC5zdGFydHNXaXRoKCdodHRwOi8vJykgJiZcbiAgICAgICAgIXB1YmxpY1NlcnZlclVSTC5zdGFydHNXaXRoKCdodHRwczovLycpXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgJ3B1YmxpY1NlcnZlclVSTCBzaG91bGQgYmUgYSB2YWxpZCBIVFRQUyBVUkwgc3RhcnRpbmcgd2l0aCBodHRwczovLyc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy52YWxpZGF0ZVNlc3Npb25Db25maWd1cmF0aW9uKHNlc3Npb25MZW5ndGgsIGV4cGlyZUluYWN0aXZlU2Vzc2lvbnMpO1xuXG4gICAgdGhpcy52YWxpZGF0ZU1hc3RlcktleUlwcyhtYXN0ZXJLZXlJcHMpO1xuXG4gICAgdGhpcy52YWxpZGF0ZU1heExpbWl0KG1heExpbWl0KTtcblxuICAgIHRoaXMudmFsaWRhdGVBbGxvd0hlYWRlcnMoYWxsb3dIZWFkZXJzKTtcbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZUFjY291bnRMb2Nrb3V0UG9saWN5KGFjY291bnRMb2Nrb3V0KSB7XG4gICAgaWYgKGFjY291bnRMb2Nrb3V0KSB7XG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiBhY2NvdW50TG9ja291dC5kdXJhdGlvbiAhPT0gJ251bWJlcicgfHxcbiAgICAgICAgYWNjb3VudExvY2tvdXQuZHVyYXRpb24gPD0gMCB8fFxuICAgICAgICBhY2NvdW50TG9ja291dC5kdXJhdGlvbiA+IDk5OTk5XG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgJ0FjY291bnQgbG9ja291dCBkdXJhdGlvbiBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIDAgYW5kIGxlc3MgdGhhbiAxMDAwMDAnO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgICFOdW1iZXIuaXNJbnRlZ2VyKGFjY291bnRMb2Nrb3V0LnRocmVzaG9sZCkgfHxcbiAgICAgICAgYWNjb3VudExvY2tvdXQudGhyZXNob2xkIDwgMSB8fFxuICAgICAgICBhY2NvdW50TG9ja291dC50aHJlc2hvbGQgPiA5OTlcbiAgICAgICkge1xuICAgICAgICB0aHJvdyAnQWNjb3VudCBsb2Nrb3V0IHRocmVzaG9sZCBzaG91bGQgYmUgYW4gaW50ZWdlciBncmVhdGVyIHRoYW4gMCBhbmQgbGVzcyB0aGFuIDEwMDAnO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZVBhc3N3b3JkUG9saWN5KHBhc3N3b3JkUG9saWN5KSB7XG4gICAgaWYgKHBhc3N3b3JkUG9saWN5KSB7XG4gICAgICBpZiAoXG4gICAgICAgIHBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgKHR5cGVvZiBwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEFnZSAhPT0gJ251bWJlcicgfHxcbiAgICAgICAgICBwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEFnZSA8IDApXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgJ3Bhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIHBhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgKHR5cGVvZiBwYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbiAhPT0gJ251bWJlcicgfHxcbiAgICAgICAgICBwYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbiA8PSAwKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJztcbiAgICAgIH1cblxuICAgICAgaWYgKHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4pIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4gPSBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgcGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVyblxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoIShwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuIGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuIG11c3QgYmUgYSByZWdleCBzdHJpbmcgb3IgUmVnRXhwIG9iamVjdC4nO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgcGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yQ2FsbGJhY2sgJiZcbiAgICAgICAgdHlwZW9mIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvckNhbGxiYWNrICE9PSAnZnVuY3Rpb24nXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgJ3Bhc3N3b3JkUG9saWN5LnZhbGlkYXRvckNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbi4nO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIHBhc3N3b3JkUG9saWN5LmRvTm90QWxsb3dVc2VybmFtZSAmJlxuICAgICAgICB0eXBlb2YgcGFzc3dvcmRQb2xpY3kuZG9Ob3RBbGxvd1VzZXJuYW1lICE9PSAnYm9vbGVhbidcbiAgICAgICkge1xuICAgICAgICB0aHJvdyAncGFzc3dvcmRQb2xpY3kuZG9Ob3RBbGxvd1VzZXJuYW1lIG11c3QgYmUgYSBib29sZWFuIHZhbHVlLic7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgcGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5ICYmXG4gICAgICAgICghTnVtYmVyLmlzSW50ZWdlcihwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkpIHx8XG4gICAgICAgICAgcGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5IDw9IDAgfHxcbiAgICAgICAgICBwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgPiAyMClcbiAgICAgICkge1xuICAgICAgICB0aHJvdyAncGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5IG11c3QgYmUgYW4gaW50ZWdlciByYW5naW5nIDAgLSAyMCc7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4gaXMgY29uZmlndXJlZCB0aGVuIHNldHVwIGEgY2FsbGJhY2sgdG8gcHJvY2VzcyB0aGUgcGF0dGVyblxuICBzdGF0aWMgc2V0dXBQYXNzd29yZFZhbGlkYXRvcihwYXNzd29yZFBvbGljeSkge1xuICAgIGlmIChwYXNzd29yZFBvbGljeSAmJiBwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuKSB7XG4gICAgICBwYXNzd29yZFBvbGljeS5wYXR0ZXJuVmFsaWRhdG9yID0gdmFsdWUgPT4ge1xuICAgICAgICByZXR1cm4gcGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVybi50ZXN0KHZhbHVlKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlRW1haWxDb25maWd1cmF0aW9uKHtcbiAgICBlbWFpbEFkYXB0ZXIsXG4gICAgYXBwTmFtZSxcbiAgICBwdWJsaWNTZXJ2ZXJVUkwsXG4gICAgZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24sXG4gIH0pIHtcbiAgICBpZiAoIWVtYWlsQWRhcHRlcikge1xuICAgICAgdGhyb3cgJ0FuIGVtYWlsQWRhcHRlciBpcyByZXF1aXJlZCBmb3IgZS1tYWlsIHZlcmlmaWNhdGlvbiBhbmQgcGFzc3dvcmQgcmVzZXRzLic7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYXBwTmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93ICdBbiBhcHAgbmFtZSBpcyByZXF1aXJlZCBmb3IgZS1tYWlsIHZlcmlmaWNhdGlvbiBhbmQgcGFzc3dvcmQgcmVzZXRzLic7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgcHVibGljU2VydmVyVVJMICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgJ0EgcHVibGljIHNlcnZlciB1cmwgaXMgcmVxdWlyZWQgZm9yIGUtbWFpbCB2ZXJpZmljYXRpb24gYW5kIHBhc3N3b3JkIHJlc2V0cy4nO1xuICAgIH1cbiAgICBpZiAoZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24pIHtcbiAgICAgIGlmIChpc05hTihlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbikpIHtcbiAgICAgICAgdGhyb3cgJ0VtYWlsIHZlcmlmeSB0b2tlbiB2YWxpZGl0eSBkdXJhdGlvbiBtdXN0IGJlIGEgdmFsaWQgbnVtYmVyLic7XG4gICAgICB9IGVsc2UgaWYgKGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uIDw9IDApIHtcbiAgICAgICAgdGhyb3cgJ0VtYWlsIHZlcmlmeSB0b2tlbiB2YWxpZGl0eSBkdXJhdGlvbiBtdXN0IGJlIGEgdmFsdWUgZ3JlYXRlciB0aGFuIDAuJztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVNYXN0ZXJLZXlJcHMobWFzdGVyS2V5SXBzKSB7XG4gICAgZm9yIChjb25zdCBpcCBvZiBtYXN0ZXJLZXlJcHMpIHtcbiAgICAgIGlmICghbmV0LmlzSVAoaXApKSB7XG4gICAgICAgIHRocm93IGBJbnZhbGlkIGlwIGluIG1hc3RlcktleUlwczogJHtpcH1gO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldCBtb3VudCgpIHtcbiAgICB2YXIgbW91bnQgPSB0aGlzLl9tb3VudDtcbiAgICBpZiAodGhpcy5wdWJsaWNTZXJ2ZXJVUkwpIHtcbiAgICAgIG1vdW50ID0gdGhpcy5wdWJsaWNTZXJ2ZXJVUkw7XG4gICAgfVxuICAgIHJldHVybiBtb3VudDtcbiAgfVxuXG4gIHNldCBtb3VudChuZXdWYWx1ZSkge1xuICAgIHRoaXMuX21vdW50ID0gbmV3VmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVTZXNzaW9uQ29uZmlndXJhdGlvbihzZXNzaW9uTGVuZ3RoLCBleHBpcmVJbmFjdGl2ZVNlc3Npb25zKSB7XG4gICAgaWYgKGV4cGlyZUluYWN0aXZlU2Vzc2lvbnMpIHtcbiAgICAgIGlmIChpc05hTihzZXNzaW9uTGVuZ3RoKSkge1xuICAgICAgICB0aHJvdyAnU2Vzc2lvbiBsZW5ndGggbXVzdCBiZSBhIHZhbGlkIG51bWJlci4nO1xuICAgICAgfSBlbHNlIGlmIChzZXNzaW9uTGVuZ3RoIDw9IDApIHtcbiAgICAgICAgdGhyb3cgJ1Nlc3Npb24gbGVuZ3RoIG11c3QgYmUgYSB2YWx1ZSBncmVhdGVyIHRoYW4gMC4nO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZU1heExpbWl0KG1heExpbWl0KSB7XG4gICAgaWYgKG1heExpbWl0IDw9IDApIHtcbiAgICAgIHRocm93ICdNYXggbGltaXQgbXVzdCBiZSBhIHZhbHVlIGdyZWF0ZXIgdGhhbiAwLic7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlQWxsb3dIZWFkZXJzKGFsbG93SGVhZGVycykge1xuICAgIGlmICghW251bGwsIHVuZGVmaW5lZF0uaW5jbHVkZXMoYWxsb3dIZWFkZXJzKSkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYWxsb3dIZWFkZXJzKSkge1xuICAgICAgICBhbGxvd0hlYWRlcnMuZm9yRWFjaChoZWFkZXIgPT4ge1xuICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVyICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgJ0FsbG93IGhlYWRlcnMgbXVzdCBvbmx5IGNvbnRhaW4gc3RyaW5ncyc7XG4gICAgICAgICAgfSBlbHNlIGlmICghaGVhZGVyLnRyaW0oKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93ICdBbGxvdyBoZWFkZXJzIG11c3Qgbm90IGNvbnRhaW4gZW1wdHkgc3RyaW5ncyc7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93ICdBbGxvdyBoZWFkZXJzIG11c3QgYmUgYW4gYXJyYXknO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbkV4cGlyZXNBdCgpIHtcbiAgICBpZiAoIXRoaXMudmVyaWZ5VXNlckVtYWlscyB8fCAhdGhpcy5lbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdmFyIG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgcmV0dXJuIG5ldyBEYXRlKFxuICAgICAgbm93LmdldFRpbWUoKSArIHRoaXMuZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24gKiAxMDAwXG4gICAgKTtcbiAgfVxuXG4gIGdlbmVyYXRlUGFzc3dvcmRSZXNldFRva2VuRXhwaXJlc0F0KCkge1xuICAgIGlmIChcbiAgICAgICF0aGlzLnBhc3N3b3JkUG9saWN5IHx8XG4gICAgICAhdGhpcy5wYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvblxuICAgICkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gbmV3IERhdGUoXG4gICAgICBub3cuZ2V0VGltZSgpICsgdGhpcy5wYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbiAqIDEwMDBcbiAgICApO1xuICB9XG5cbiAgZ2VuZXJhdGVTZXNzaW9uRXhwaXJlc0F0KCkge1xuICAgIGlmICghdGhpcy5leHBpcmVJbmFjdGl2ZVNlc3Npb25zKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB2YXIgbm93ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gbmV3IERhdGUobm93LmdldFRpbWUoKSArIHRoaXMuc2Vzc2lvbkxlbmd0aCAqIDEwMDApO1xuICB9XG5cbiAgZ2V0IGludmFsaWRMaW5rVVJMKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmN1c3RvbVBhZ2VzLmludmFsaWRMaW5rIHx8XG4gICAgICBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9pbnZhbGlkX2xpbmsuaHRtbGBcbiAgICApO1xuICB9XG5cbiAgZ2V0IGludmFsaWRWZXJpZmljYXRpb25MaW5rVVJMKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmN1c3RvbVBhZ2VzLmludmFsaWRWZXJpZmljYXRpb25MaW5rIHx8XG4gICAgICBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9pbnZhbGlkX3ZlcmlmaWNhdGlvbl9saW5rLmh0bWxgXG4gICAgKTtcbiAgfVxuXG4gIGdldCBsaW5rU2VuZFN1Y2Nlc3NVUkwoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY3VzdG9tUGFnZXMubGlua1NlbmRTdWNjZXNzIHx8XG4gICAgICBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9saW5rX3NlbmRfc3VjY2Vzcy5odG1sYFxuICAgICk7XG4gIH1cblxuICBnZXQgbGlua1NlbmRGYWlsVVJMKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmN1c3RvbVBhZ2VzLmxpbmtTZW5kRmFpbCB8fFxuICAgICAgYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvbGlua19zZW5kX2ZhaWwuaHRtbGBcbiAgICApO1xuICB9XG5cbiAgZ2V0IHZlcmlmeUVtYWlsU3VjY2Vzc1VSTCgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5jdXN0b21QYWdlcy52ZXJpZnlFbWFpbFN1Y2Nlc3MgfHxcbiAgICAgIGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzL3ZlcmlmeV9lbWFpbF9zdWNjZXNzLmh0bWxgXG4gICAgKTtcbiAgfVxuXG4gIGdldCBjaG9vc2VQYXNzd29yZFVSTCgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5jdXN0b21QYWdlcy5jaG9vc2VQYXNzd29yZCB8fFxuICAgICAgYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvY2hvb3NlX3Bhc3N3b3JkYFxuICAgICk7XG4gIH1cblxuICBnZXQgcmVxdWVzdFJlc2V0UGFzc3dvcmRVUkwoKSB7XG4gICAgcmV0dXJuIGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzLyR7dGhpcy5hcHBsaWNhdGlvbklkfS9yZXF1ZXN0X3Bhc3N3b3JkX3Jlc2V0YDtcbiAgfVxuXG4gIGdldCBwYXNzd29yZFJlc2V0U3VjY2Vzc1VSTCgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5jdXN0b21QYWdlcy5wYXNzd29yZFJlc2V0U3VjY2VzcyB8fFxuICAgICAgYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvcGFzc3dvcmRfcmVzZXRfc3VjY2Vzcy5odG1sYFxuICAgICk7XG4gIH1cblxuICBnZXQgcGFyc2VGcmFtZVVSTCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXN0b21QYWdlcy5wYXJzZUZyYW1lVVJMO1xuICB9XG5cbiAgZ2V0IHZlcmlmeUVtYWlsVVJMKCkge1xuICAgIHJldHVybiBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy8ke3RoaXMuYXBwbGljYXRpb25JZH0vdmVyaWZ5X2VtYWlsYDtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDb25maWc7XG5tb2R1bGUuZXhwb3J0cyA9IENvbmZpZztcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/AdaptableController.js b/lib/Controllers/AdaptableController.js new file mode 100644 index 0000000000..9c2be0c0ff --- /dev/null +++ b/lib/Controllers/AdaptableController.js @@ -0,0 +1,88 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AdaptableController = void 0; + +var _Config = _interopRequireDefault(require("../Config")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* +AdaptableController.js + +AdaptableController is the base class for all controllers +that support adapter, +The super class takes care of creating the right instance for the adapter +based on the parameters passed + + */ +// _adapter is private, use Symbol +var _adapter = Symbol(); + +class AdaptableController { + constructor(adapter, appId, options) { + this.options = options; + this.appId = appId; + this.adapter = adapter; + } + + set adapter(adapter) { + this.validateAdapter(adapter); + this[_adapter] = adapter; + } + + get adapter() { + return this[_adapter]; + } + + get config() { + return _Config.default.get(this.appId); + } + + expectedAdapterType() { + throw new Error('Subclasses should implement expectedAdapterType()'); + } + + validateAdapter(adapter) { + AdaptableController.validateAdapter(adapter, this); + } + + static validateAdapter(adapter, self, ExpectedType) { + if (!adapter) { + throw new Error(this.constructor.name + ' requires an adapter'); + } + + const Type = ExpectedType || self.expectedAdapterType(); // Allow skipping for testing + + if (!Type) { + return; + } // Makes sure the prototype matches + + + const mismatches = Object.getOwnPropertyNames(Type.prototype).reduce((obj, key) => { + const adapterType = typeof adapter[key]; + const expectedType = typeof Type.prototype[key]; + + if (adapterType !== expectedType) { + obj[key] = { + expected: expectedType, + actual: adapterType + }; + } + + return obj; + }, {}); + + if (Object.keys(mismatches).length > 0) { + throw new Error("Adapter prototype don't match expected prototype", adapter, mismatches); + } + } + +} + +exports.AdaptableController = AdaptableController; +var _default = AdaptableController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9BZGFwdGFibGVDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIl9hZGFwdGVyIiwiU3ltYm9sIiwiQWRhcHRhYmxlQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwiYWRhcHRlciIsImFwcElkIiwib3B0aW9ucyIsInZhbGlkYXRlQWRhcHRlciIsImNvbmZpZyIsIkNvbmZpZyIsImdldCIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJFcnJvciIsInNlbGYiLCJFeHBlY3RlZFR5cGUiLCJuYW1lIiwiVHlwZSIsIm1pc21hdGNoZXMiLCJPYmplY3QiLCJnZXRPd25Qcm9wZXJ0eU5hbWVzIiwicHJvdG90eXBlIiwicmVkdWNlIiwib2JqIiwia2V5IiwiYWRhcHRlclR5cGUiLCJleHBlY3RlZFR5cGUiLCJleHBlY3RlZCIsImFjdHVhbCIsImtleXMiLCJsZW5ndGgiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFZQTs7OztBQVpBOzs7Ozs7Ozs7QUFVQTtBQUNBLElBQUlBLFFBQVEsR0FBR0MsTUFBTSxFQUFyQjs7QUFHTyxNQUFNQyxtQkFBTixDQUEwQjtBQUMvQkMsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQVVDLEtBQVYsRUFBaUJDLE9BQWpCLEVBQTBCO0FBQ25DLFNBQUtBLE9BQUwsR0FBZUEsT0FBZjtBQUNBLFNBQUtELEtBQUwsR0FBYUEsS0FBYjtBQUNBLFNBQUtELE9BQUwsR0FBZUEsT0FBZjtBQUNEOztBQUVELE1BQUlBLE9BQUosQ0FBWUEsT0FBWixFQUFxQjtBQUNuQixTQUFLRyxlQUFMLENBQXFCSCxPQUFyQjtBQUNBLFNBQUtKLFFBQUwsSUFBaUJJLE9BQWpCO0FBQ0Q7O0FBRUQsTUFBSUEsT0FBSixHQUFjO0FBQ1osV0FBTyxLQUFLSixRQUFMLENBQVA7QUFDRDs7QUFFRCxNQUFJUSxNQUFKLEdBQWE7QUFDWCxXQUFPQyxnQkFBT0MsR0FBUCxDQUFXLEtBQUtMLEtBQWhCLENBQVA7QUFDRDs7QUFFRE0sRUFBQUEsbUJBQW1CLEdBQUc7QUFDcEIsVUFBTSxJQUFJQyxLQUFKLENBQVUsbURBQVYsQ0FBTjtBQUNEOztBQUVETCxFQUFBQSxlQUFlLENBQUNILE9BQUQsRUFBVTtBQUN2QkYsSUFBQUEsbUJBQW1CLENBQUNLLGVBQXBCLENBQW9DSCxPQUFwQyxFQUE2QyxJQUE3QztBQUNEOztBQUVELFNBQU9HLGVBQVAsQ0FBdUJILE9BQXZCLEVBQWdDUyxJQUFoQyxFQUFzQ0MsWUFBdEMsRUFBb0Q7QUFDbEQsUUFBSSxDQUFDVixPQUFMLEVBQWM7QUFDWixZQUFNLElBQUlRLEtBQUosQ0FBVSxLQUFLVCxXQUFMLENBQWlCWSxJQUFqQixHQUF3QixzQkFBbEMsQ0FBTjtBQUNEOztBQUVELFVBQU1DLElBQUksR0FBR0YsWUFBWSxJQUFJRCxJQUFJLENBQUNGLG1CQUFMLEVBQTdCLENBTGtELENBTWxEOztBQUNBLFFBQUksQ0FBQ0ssSUFBTCxFQUFXO0FBQ1Q7QUFDRCxLQVRpRCxDQVdsRDs7O0FBQ0EsVUFBTUMsVUFBVSxHQUFHQyxNQUFNLENBQUNDLG1CQUFQLENBQTJCSCxJQUFJLENBQUNJLFNBQWhDLEVBQTJDQyxNQUEzQyxDQUNqQixDQUFDQyxHQUFELEVBQU1DLEdBQU4sS0FBYztBQUNaLFlBQU1DLFdBQVcsR0FBRyxPQUFPcEIsT0FBTyxDQUFDbUIsR0FBRCxDQUFsQztBQUNBLFlBQU1FLFlBQVksR0FBRyxPQUFPVCxJQUFJLENBQUNJLFNBQUwsQ0FBZUcsR0FBZixDQUE1Qjs7QUFDQSxVQUFJQyxXQUFXLEtBQUtDLFlBQXBCLEVBQWtDO0FBQ2hDSCxRQUFBQSxHQUFHLENBQUNDLEdBQUQsQ0FBSCxHQUFXO0FBQ1RHLFVBQUFBLFFBQVEsRUFBRUQsWUFERDtBQUVURSxVQUFBQSxNQUFNLEVBQUVIO0FBRkMsU0FBWDtBQUlEOztBQUNELGFBQU9GLEdBQVA7QUFDRCxLQVhnQixFQVlqQixFQVppQixDQUFuQjs7QUFlQSxRQUFJSixNQUFNLENBQUNVLElBQVAsQ0FBWVgsVUFBWixFQUF3QlksTUFBeEIsR0FBaUMsQ0FBckMsRUFBd0M7QUFDdEMsWUFBTSxJQUFJakIsS0FBSixDQUNKLGtEQURJLEVBRUpSLE9BRkksRUFHSmEsVUFISSxDQUFOO0FBS0Q7QUFDRjs7QUE5RDhCOzs7ZUFpRWxCZixtQiIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5BZGFwdGFibGVDb250cm9sbGVyLmpzXG5cbkFkYXB0YWJsZUNvbnRyb2xsZXIgaXMgdGhlIGJhc2UgY2xhc3MgZm9yIGFsbCBjb250cm9sbGVyc1xudGhhdCBzdXBwb3J0IGFkYXB0ZXIsXG5UaGUgc3VwZXIgY2xhc3MgdGFrZXMgY2FyZSBvZiBjcmVhdGluZyB0aGUgcmlnaHQgaW5zdGFuY2UgZm9yIHRoZSBhZGFwdGVyXG5iYXNlZCBvbiB0aGUgcGFyYW1ldGVycyBwYXNzZWRcblxuICovXG5cbi8vIF9hZGFwdGVyIGlzIHByaXZhdGUsIHVzZSBTeW1ib2xcbnZhciBfYWRhcHRlciA9IFN5bWJvbCgpO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuXG5leHBvcnQgY2xhc3MgQWRhcHRhYmxlQ29udHJvbGxlciB7XG4gIGNvbnN0cnVjdG9yKGFkYXB0ZXIsIGFwcElkLCBvcHRpb25zKSB7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLmFwcElkID0gYXBwSWQ7XG4gICAgdGhpcy5hZGFwdGVyID0gYWRhcHRlcjtcbiAgfVxuXG4gIHNldCBhZGFwdGVyKGFkYXB0ZXIpIHtcbiAgICB0aGlzLnZhbGlkYXRlQWRhcHRlcihhZGFwdGVyKTtcbiAgICB0aGlzW19hZGFwdGVyXSA9IGFkYXB0ZXI7XG4gIH1cblxuICBnZXQgYWRhcHRlcigpIHtcbiAgICByZXR1cm4gdGhpc1tfYWRhcHRlcl07XG4gIH1cblxuICBnZXQgY29uZmlnKCkge1xuICAgIHJldHVybiBDb25maWcuZ2V0KHRoaXMuYXBwSWQpO1xuICB9XG5cbiAgZXhwZWN0ZWRBZGFwdGVyVHlwZSgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1N1YmNsYXNzZXMgc2hvdWxkIGltcGxlbWVudCBleHBlY3RlZEFkYXB0ZXJUeXBlKCknKTtcbiAgfVxuXG4gIHZhbGlkYXRlQWRhcHRlcihhZGFwdGVyKSB7XG4gICAgQWRhcHRhYmxlQ29udHJvbGxlci52YWxpZGF0ZUFkYXB0ZXIoYWRhcHRlciwgdGhpcyk7XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVBZGFwdGVyKGFkYXB0ZXIsIHNlbGYsIEV4cGVjdGVkVHlwZSkge1xuICAgIGlmICghYWRhcHRlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMuY29uc3RydWN0b3IubmFtZSArICcgcmVxdWlyZXMgYW4gYWRhcHRlcicpO1xuICAgIH1cblxuICAgIGNvbnN0IFR5cGUgPSBFeHBlY3RlZFR5cGUgfHwgc2VsZi5leHBlY3RlZEFkYXB0ZXJUeXBlKCk7XG4gICAgLy8gQWxsb3cgc2tpcHBpbmcgZm9yIHRlc3RpbmdcbiAgICBpZiAoIVR5cGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBNYWtlcyBzdXJlIHRoZSBwcm90b3R5cGUgbWF0Y2hlc1xuICAgIGNvbnN0IG1pc21hdGNoZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhUeXBlLnByb3RvdHlwZSkucmVkdWNlKFxuICAgICAgKG9iaiwga2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IGFkYXB0ZXJUeXBlID0gdHlwZW9mIGFkYXB0ZXJba2V5XTtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gdHlwZW9mIFR5cGUucHJvdG90eXBlW2tleV07XG4gICAgICAgIGlmIChhZGFwdGVyVHlwZSAhPT0gZXhwZWN0ZWRUeXBlKSB7XG4gICAgICAgICAgb2JqW2tleV0gPSB7XG4gICAgICAgICAgICBleHBlY3RlZDogZXhwZWN0ZWRUeXBlLFxuICAgICAgICAgICAgYWN0dWFsOiBhZGFwdGVyVHlwZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgICB9LFxuICAgICAge31cbiAgICApO1xuXG4gICAgaWYgKE9iamVjdC5rZXlzKG1pc21hdGNoZXMpLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJBZGFwdGVyIHByb3RvdHlwZSBkb24ndCBtYXRjaCBleHBlY3RlZCBwcm90b3R5cGVcIixcbiAgICAgICAgYWRhcHRlcixcbiAgICAgICAgbWlzbWF0Y2hlc1xuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQWRhcHRhYmxlQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/AnalyticsController.js b/lib/Controllers/AnalyticsController.js new file mode 100644 index 0000000000..1416558aca --- /dev/null +++ b/lib/Controllers/AnalyticsController.js @@ -0,0 +1,52 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AnalyticsController = void 0; + +var _AdaptableController = _interopRequireDefault(require("./AdaptableController")); + +var _AnalyticsAdapter = require("../Adapters/Analytics/AnalyticsAdapter"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AnalyticsController extends _AdaptableController.default { + appOpened(req) { + return Promise.resolve().then(() => { + return this.adapter.appOpened(req.body, req); + }).then(response => { + return { + response: response || {} + }; + }).catch(() => { + return { + response: {} + }; + }); + } + + trackEvent(req) { + return Promise.resolve().then(() => { + return this.adapter.trackEvent(req.params.eventName, req.body, req); + }).then(response => { + return { + response: response || {} + }; + }).catch(() => { + return { + response: {} + }; + }); + } + + expectedAdapterType() { + return _AnalyticsAdapter.AnalyticsAdapter; + } + +} + +exports.AnalyticsController = AnalyticsController; +var _default = AnalyticsController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9BbmFseXRpY3NDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkFuYWx5dGljc0NvbnRyb2xsZXIiLCJBZGFwdGFibGVDb250cm9sbGVyIiwiYXBwT3BlbmVkIiwicmVxIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aGVuIiwiYWRhcHRlciIsImJvZHkiLCJyZXNwb25zZSIsImNhdGNoIiwidHJhY2tFdmVudCIsInBhcmFtcyIsImV2ZW50TmFtZSIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJBbmFseXRpY3NBZGFwdGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFFTyxNQUFNQSxtQkFBTixTQUFrQ0MsNEJBQWxDLENBQXNEO0FBQzNEQyxFQUFBQSxTQUFTLENBQUNDLEdBQUQsRUFBTTtBQUNiLFdBQU9DLE9BQU8sQ0FBQ0MsT0FBUixHQUNKQyxJQURJLENBQ0MsTUFBTTtBQUNWLGFBQU8sS0FBS0MsT0FBTCxDQUFhTCxTQUFiLENBQXVCQyxHQUFHLENBQUNLLElBQTNCLEVBQWlDTCxHQUFqQyxDQUFQO0FBQ0QsS0FISSxFQUlKRyxJQUpJLENBSUNHLFFBQVEsSUFBSTtBQUNoQixhQUFPO0FBQUVBLFFBQUFBLFFBQVEsRUFBRUEsUUFBUSxJQUFJO0FBQXhCLE9BQVA7QUFDRCxLQU5JLEVBT0pDLEtBUEksQ0FPRSxNQUFNO0FBQ1gsYUFBTztBQUFFRCxRQUFBQSxRQUFRLEVBQUU7QUFBWixPQUFQO0FBQ0QsS0FUSSxDQUFQO0FBVUQ7O0FBRURFLEVBQUFBLFVBQVUsQ0FBQ1IsR0FBRCxFQUFNO0FBQ2QsV0FBT0MsT0FBTyxDQUFDQyxPQUFSLEdBQ0pDLElBREksQ0FDQyxNQUFNO0FBQ1YsYUFBTyxLQUFLQyxPQUFMLENBQWFJLFVBQWIsQ0FBd0JSLEdBQUcsQ0FBQ1MsTUFBSixDQUFXQyxTQUFuQyxFQUE4Q1YsR0FBRyxDQUFDSyxJQUFsRCxFQUF3REwsR0FBeEQsQ0FBUDtBQUNELEtBSEksRUFJSkcsSUFKSSxDQUlDRyxRQUFRLElBQUk7QUFDaEIsYUFBTztBQUFFQSxRQUFBQSxRQUFRLEVBQUVBLFFBQVEsSUFBSTtBQUF4QixPQUFQO0FBQ0QsS0FOSSxFQU9KQyxLQVBJLENBT0UsTUFBTTtBQUNYLGFBQU87QUFBRUQsUUFBQUEsUUFBUSxFQUFFO0FBQVosT0FBUDtBQUNELEtBVEksQ0FBUDtBQVVEOztBQUVESyxFQUFBQSxtQkFBbUIsR0FBRztBQUNwQixXQUFPQyxrQ0FBUDtBQUNEOztBQTdCMEQ7OztlQWdDOUNmLG1CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEFkYXB0YWJsZUNvbnRyb2xsZXIgZnJvbSAnLi9BZGFwdGFibGVDb250cm9sbGVyJztcbmltcG9ydCB7IEFuYWx5dGljc0FkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9BbmFseXRpY3MvQW5hbHl0aWNzQWRhcHRlcic7XG5cbmV4cG9ydCBjbGFzcyBBbmFseXRpY3NDb250cm9sbGVyIGV4dGVuZHMgQWRhcHRhYmxlQ29udHJvbGxlciB7XG4gIGFwcE9wZW5lZChyZXEpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5hcHBPcGVuZWQocmVxLmJvZHksIHJlcSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICByZXR1cm4geyByZXNwb25zZTogcmVzcG9uc2UgfHwge30gfTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICByZXR1cm4geyByZXNwb25zZToge30gfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgdHJhY2tFdmVudChyZXEpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci50cmFja0V2ZW50KHJlcS5wYXJhbXMuZXZlbnROYW1lLCByZXEuYm9keSwgcmVxKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiByZXNwb25zZSB8fCB7fSB9O1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB7fSB9O1xuICAgICAgfSk7XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHJldHVybiBBbmFseXRpY3NBZGFwdGVyO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEFuYWx5dGljc0NvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/CacheController.js b/lib/Controllers/CacheController.js new file mode 100644 index 0000000000..9feaa778f9 --- /dev/null +++ b/lib/Controllers/CacheController.js @@ -0,0 +1,92 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.CacheController = exports.SubCache = void 0; + +var _AdaptableController = _interopRequireDefault(require("./AdaptableController")); + +var _CacheAdapter = _interopRequireDefault(require("../Adapters/Cache/CacheAdapter")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const KEY_SEPARATOR_CHAR = ':'; + +function joinKeys(...keys) { + return keys.join(KEY_SEPARATOR_CHAR); +} +/** + * Prefix all calls to the cache via a prefix string, useful when grouping Cache by object type. + * + * eg "Role" or "Session" + */ + + +class SubCache { + constructor(prefix, cacheController, ttl) { + this.prefix = prefix; + this.cache = cacheController; + this.ttl = ttl; + } + + get(key) { + const cacheKey = joinKeys(this.prefix, key); + return this.cache.get(cacheKey); + } + + put(key, value, ttl) { + const cacheKey = joinKeys(this.prefix, key); + return this.cache.put(cacheKey, value, ttl); + } + + del(key) { + const cacheKey = joinKeys(this.prefix, key); + return this.cache.del(cacheKey); + } + + clear() { + return this.cache.clear(); + } + +} + +exports.SubCache = SubCache; + +class CacheController extends _AdaptableController.default { + constructor(adapter, appId, options = {}) { + super(adapter, appId, options); + this.role = new SubCache('role', this); + this.user = new SubCache('user', this); + this.graphQL = new SubCache('graphQL', this); + } + + get(key) { + const cacheKey = joinKeys(this.appId, key); + return this.adapter.get(cacheKey).then(null, () => Promise.resolve(null)); + } + + put(key, value, ttl) { + const cacheKey = joinKeys(this.appId, key); + return this.adapter.put(cacheKey, value, ttl); + } + + del(key) { + const cacheKey = joinKeys(this.appId, key); + return this.adapter.del(cacheKey); + } + + clear() { + return this.adapter.clear(); + } + + expectedAdapterType() { + return _CacheAdapter.default; + } + +} + +exports.CacheController = CacheController; +var _default = CacheController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9DYWNoZUNvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiS0VZX1NFUEFSQVRPUl9DSEFSIiwiam9pbktleXMiLCJrZXlzIiwiam9pbiIsIlN1YkNhY2hlIiwiY29uc3RydWN0b3IiLCJwcmVmaXgiLCJjYWNoZUNvbnRyb2xsZXIiLCJ0dGwiLCJjYWNoZSIsImdldCIsImtleSIsImNhY2hlS2V5IiwicHV0IiwidmFsdWUiLCJkZWwiLCJjbGVhciIsIkNhY2hlQ29udHJvbGxlciIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJhZGFwdGVyIiwiYXBwSWQiLCJvcHRpb25zIiwicm9sZSIsInVzZXIiLCJncmFwaFFMIiwidGhlbiIsIlByb21pc2UiLCJyZXNvbHZlIiwiZXhwZWN0ZWRBZGFwdGVyVHlwZSIsIkNhY2hlQWRhcHRlciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBRUEsTUFBTUEsa0JBQWtCLEdBQUcsR0FBM0I7O0FBRUEsU0FBU0MsUUFBVCxDQUFrQixHQUFHQyxJQUFyQixFQUEyQjtBQUN6QixTQUFPQSxJQUFJLENBQUNDLElBQUwsQ0FBVUgsa0JBQVYsQ0FBUDtBQUNEO0FBRUQ7Ozs7Ozs7QUFLTyxNQUFNSSxRQUFOLENBQWU7QUFDcEJDLEVBQUFBLFdBQVcsQ0FBQ0MsTUFBRCxFQUFTQyxlQUFULEVBQTBCQyxHQUExQixFQUErQjtBQUN4QyxTQUFLRixNQUFMLEdBQWNBLE1BQWQ7QUFDQSxTQUFLRyxLQUFMLEdBQWFGLGVBQWI7QUFDQSxTQUFLQyxHQUFMLEdBQVdBLEdBQVg7QUFDRDs7QUFFREUsRUFBQUEsR0FBRyxDQUFDQyxHQUFELEVBQU07QUFDUCxVQUFNQyxRQUFRLEdBQUdYLFFBQVEsQ0FBQyxLQUFLSyxNQUFOLEVBQWNLLEdBQWQsQ0FBekI7QUFDQSxXQUFPLEtBQUtGLEtBQUwsQ0FBV0MsR0FBWCxDQUFlRSxRQUFmLENBQVA7QUFDRDs7QUFFREMsRUFBQUEsR0FBRyxDQUFDRixHQUFELEVBQU1HLEtBQU4sRUFBYU4sR0FBYixFQUFrQjtBQUNuQixVQUFNSSxRQUFRLEdBQUdYLFFBQVEsQ0FBQyxLQUFLSyxNQUFOLEVBQWNLLEdBQWQsQ0FBekI7QUFDQSxXQUFPLEtBQUtGLEtBQUwsQ0FBV0ksR0FBWCxDQUFlRCxRQUFmLEVBQXlCRSxLQUF6QixFQUFnQ04sR0FBaEMsQ0FBUDtBQUNEOztBQUVETyxFQUFBQSxHQUFHLENBQUNKLEdBQUQsRUFBTTtBQUNQLFVBQU1DLFFBQVEsR0FBR1gsUUFBUSxDQUFDLEtBQUtLLE1BQU4sRUFBY0ssR0FBZCxDQUF6QjtBQUNBLFdBQU8sS0FBS0YsS0FBTCxDQUFXTSxHQUFYLENBQWVILFFBQWYsQ0FBUDtBQUNEOztBQUVESSxFQUFBQSxLQUFLLEdBQUc7QUFDTixXQUFPLEtBQUtQLEtBQUwsQ0FBV08sS0FBWCxFQUFQO0FBQ0Q7O0FBeEJtQjs7OztBQTJCZixNQUFNQyxlQUFOLFNBQThCQyw0QkFBOUIsQ0FBa0Q7QUFDdkRiLEVBQUFBLFdBQVcsQ0FBQ2MsT0FBRCxFQUFVQyxLQUFWLEVBQWlCQyxPQUFPLEdBQUcsRUFBM0IsRUFBK0I7QUFDeEMsVUFBTUYsT0FBTixFQUFlQyxLQUFmLEVBQXNCQyxPQUF0QjtBQUVBLFNBQUtDLElBQUwsR0FBWSxJQUFJbEIsUUFBSixDQUFhLE1BQWIsRUFBcUIsSUFBckIsQ0FBWjtBQUNBLFNBQUttQixJQUFMLEdBQVksSUFBSW5CLFFBQUosQ0FBYSxNQUFiLEVBQXFCLElBQXJCLENBQVo7QUFDQSxTQUFLb0IsT0FBTCxHQUFlLElBQUlwQixRQUFKLENBQWEsU0FBYixFQUF3QixJQUF4QixDQUFmO0FBQ0Q7O0FBRURNLEVBQUFBLEdBQUcsQ0FBQ0MsR0FBRCxFQUFNO0FBQ1AsVUFBTUMsUUFBUSxHQUFHWCxRQUFRLENBQUMsS0FBS21CLEtBQU4sRUFBYVQsR0FBYixDQUF6QjtBQUNBLFdBQU8sS0FBS1EsT0FBTCxDQUFhVCxHQUFiLENBQWlCRSxRQUFqQixFQUEyQmEsSUFBM0IsQ0FBZ0MsSUFBaEMsRUFBc0MsTUFBTUMsT0FBTyxDQUFDQyxPQUFSLENBQWdCLElBQWhCLENBQTVDLENBQVA7QUFDRDs7QUFFRGQsRUFBQUEsR0FBRyxDQUFDRixHQUFELEVBQU1HLEtBQU4sRUFBYU4sR0FBYixFQUFrQjtBQUNuQixVQUFNSSxRQUFRLEdBQUdYLFFBQVEsQ0FBQyxLQUFLbUIsS0FBTixFQUFhVCxHQUFiLENBQXpCO0FBQ0EsV0FBTyxLQUFLUSxPQUFMLENBQWFOLEdBQWIsQ0FBaUJELFFBQWpCLEVBQTJCRSxLQUEzQixFQUFrQ04sR0FBbEMsQ0FBUDtBQUNEOztBQUVETyxFQUFBQSxHQUFHLENBQUNKLEdBQUQsRUFBTTtBQUNQLFVBQU1DLFFBQVEsR0FBR1gsUUFBUSxDQUFDLEtBQUttQixLQUFOLEVBQWFULEdBQWIsQ0FBekI7QUFDQSxXQUFPLEtBQUtRLE9BQUwsQ0FBYUosR0FBYixDQUFpQkgsUUFBakIsQ0FBUDtBQUNEOztBQUVESSxFQUFBQSxLQUFLLEdBQUc7QUFDTixXQUFPLEtBQUtHLE9BQUwsQ0FBYUgsS0FBYixFQUFQO0FBQ0Q7O0FBRURZLEVBQUFBLG1CQUFtQixHQUFHO0FBQ3BCLFdBQU9DLHFCQUFQO0FBQ0Q7O0FBOUJzRDs7O2VBaUMxQ1osZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBBZGFwdGFibGVDb250cm9sbGVyIGZyb20gJy4vQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgQ2FjaGVBZGFwdGVyIGZyb20gJy4uL0FkYXB0ZXJzL0NhY2hlL0NhY2hlQWRhcHRlcic7XG5cbmNvbnN0IEtFWV9TRVBBUkFUT1JfQ0hBUiA9ICc6JztcblxuZnVuY3Rpb24gam9pbktleXMoLi4ua2V5cykge1xuICByZXR1cm4ga2V5cy5qb2luKEtFWV9TRVBBUkFUT1JfQ0hBUik7XG59XG5cbi8qKlxuICogUHJlZml4IGFsbCBjYWxscyB0byB0aGUgY2FjaGUgdmlhIGEgcHJlZml4IHN0cmluZywgdXNlZnVsIHdoZW4gZ3JvdXBpbmcgQ2FjaGUgYnkgb2JqZWN0IHR5cGUuXG4gKlxuICogZWcgXCJSb2xlXCIgb3IgXCJTZXNzaW9uXCJcbiAqL1xuZXhwb3J0IGNsYXNzIFN1YkNhY2hlIHtcbiAgY29uc3RydWN0b3IocHJlZml4LCBjYWNoZUNvbnRyb2xsZXIsIHR0bCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICAgIHRoaXMuY2FjaGUgPSBjYWNoZUNvbnRyb2xsZXI7XG4gICAgdGhpcy50dGwgPSB0dGw7XG4gIH1cblxuICBnZXQoa2V5KSB7XG4gICAgY29uc3QgY2FjaGVLZXkgPSBqb2luS2V5cyh0aGlzLnByZWZpeCwga2V5KTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoY2FjaGVLZXkpO1xuICB9XG5cbiAgcHV0KGtleSwgdmFsdWUsIHR0bCkge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gam9pbktleXModGhpcy5wcmVmaXgsIGtleSk7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUucHV0KGNhY2hlS2V5LCB2YWx1ZSwgdHRsKTtcbiAgfVxuXG4gIGRlbChrZXkpIHtcbiAgICBjb25zdCBjYWNoZUtleSA9IGpvaW5LZXlzKHRoaXMucHJlZml4LCBrZXkpO1xuICAgIHJldHVybiB0aGlzLmNhY2hlLmRlbChjYWNoZUtleSk7XG4gIH1cblxuICBjbGVhcigpIHtcbiAgICByZXR1cm4gdGhpcy5jYWNoZS5jbGVhcigpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBDYWNoZUNvbnRyb2xsZXIgZXh0ZW5kcyBBZGFwdGFibGVDb250cm9sbGVyIHtcbiAgY29uc3RydWN0b3IoYWRhcHRlciwgYXBwSWQsIG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIGFwcElkLCBvcHRpb25zKTtcblxuICAgIHRoaXMucm9sZSA9IG5ldyBTdWJDYWNoZSgncm9sZScsIHRoaXMpO1xuICAgIHRoaXMudXNlciA9IG5ldyBTdWJDYWNoZSgndXNlcicsIHRoaXMpO1xuICAgIHRoaXMuZ3JhcGhRTCA9IG5ldyBTdWJDYWNoZSgnZ3JhcGhRTCcsIHRoaXMpO1xuICB9XG5cbiAgZ2V0KGtleSkge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gam9pbktleXModGhpcy5hcHBJZCwga2V5KTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmdldChjYWNoZUtleSkudGhlbihudWxsLCAoKSA9PiBQcm9taXNlLnJlc29sdmUobnVsbCkpO1xuICB9XG5cbiAgcHV0KGtleSwgdmFsdWUsIHR0bCkge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gam9pbktleXModGhpcy5hcHBJZCwga2V5KTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnB1dChjYWNoZUtleSwgdmFsdWUsIHR0bCk7XG4gIH1cblxuICBkZWwoa2V5KSB7XG4gICAgY29uc3QgY2FjaGVLZXkgPSBqb2luS2V5cyh0aGlzLmFwcElkLCBrZXkpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuZGVsKGNhY2hlS2V5KTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuY2xlYXIoKTtcbiAgfVxuXG4gIGV4cGVjdGVkQWRhcHRlclR5cGUoKSB7XG4gICAgcmV0dXJuIENhY2hlQWRhcHRlcjtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDYWNoZUNvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/DatabaseController.js b/lib/Controllers/DatabaseController.js new file mode 100644 index 0000000000..80383db9f9 --- /dev/null +++ b/lib/Controllers/DatabaseController.js @@ -0,0 +1,1364 @@ +"use strict"; + +var _node = require("parse/node"); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _intersect = _interopRequireDefault(require("intersect")); + +var _deepcopy = _interopRequireDefault(require("deepcopy")); + +var _logger = _interopRequireDefault(require("../logger")); + +var SchemaController = _interopRequireWildcard(require("./SchemaController")); + +var _StorageAdapter = require("../Adapters/Storage/StorageAdapter"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } + +function addWriteACL(query, acl) { + const newQuery = _lodash.default.cloneDeep(query); //Can't be any existing '_wperm' query, we don't allow client queries on that, no need to $and + + + newQuery._wperm = { + $in: [null, ...acl] + }; + return newQuery; +} + +function addReadACL(query, acl) { + const newQuery = _lodash.default.cloneDeep(query); //Can't be any existing '_rperm' query, we don't allow client queries on that, no need to $and + + + newQuery._rperm = { + $in: [null, '*', ...acl] + }; + return newQuery; +} // Transforms a REST API formatted ACL object to our two-field mongo format. + + +const transformObjectACL = (_ref) => { + let { + ACL + } = _ref, + result = _objectWithoutProperties(_ref, ["ACL"]); + + if (!ACL) { + return result; + } + + result._wperm = []; + result._rperm = []; + + for (const entry in ACL) { + if (ACL[entry].read) { + result._rperm.push(entry); + } + + if (ACL[entry].write) { + result._wperm.push(entry); + } + } + + return result; +}; + +const specialQuerykeys = ['$and', '$or', '$nor', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count']; + +const isSpecialQueryKey = key => { + return specialQuerykeys.indexOf(key) >= 0; +}; + +const validateQuery = (query, skipMongoDBServer13732Workaround) => { + if (query.ACL) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + } + + if (query.$or) { + if (query.$or instanceof Array) { + query.$or.forEach(el => validateQuery(el, skipMongoDBServer13732Workaround)); + + if (!skipMongoDBServer13732Workaround) { + /* In MongoDB 3.2 & 3.4, $or queries which are not alone at the top + * level of the query can not make efficient use of indexes due to a + * long standing bug known as SERVER-13732. + * + * This bug was fixed in MongoDB version 3.6. + * + * For versions pre-3.6, the below logic produces a substantial + * performance improvement inside the database by avoiding the bug. + * + * For versions 3.6 and above, there is no performance improvement and + * the logic is unnecessary. Some query patterns are even slowed by + * the below logic, due to the bug having been fixed and better + * query plans being chosen. + * + * When versions before 3.4 are no longer supported by this project, + * this logic, and the accompanying `skipMongoDBServer13732Workaround` + * flag, can be removed. + * + * This block restructures queries in which $or is not the sole top + * level element by moving all other top-level predicates inside every + * subdocument of the $or predicate, allowing MongoDB's query planner + * to make full use of the most relevant indexes. + * + * EG: {$or: [{a: 1}, {a: 2}], b: 2} + * Becomes: {$or: [{a: 1, b: 2}, {a: 2, b: 2}]} + * + * The only exceptions are $near and $nearSphere operators, which are + * constrained to only 1 operator per query. As a result, these ops + * remain at the top level + * + * https://jira.mongodb.org/browse/SERVER-13732 + * https://github.com/parse-community/parse-server/issues/3767 + */ + Object.keys(query).forEach(key => { + const noCollisions = !query.$or.some(subq => Object.prototype.hasOwnProperty.call(subq, key)); + let hasNears = false; + + if (query[key] != null && typeof query[key] == 'object') { + hasNears = '$near' in query[key] || '$nearSphere' in query[key]; + } + + if (key != '$or' && noCollisions && !hasNears) { + query.$or.forEach(subquery => { + subquery[key] = query[key]; + }); + delete query[key]; + } + }); + query.$or.forEach(el => validateQuery(el, skipMongoDBServer13732Workaround)); + } + } else { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_QUERY, 'Bad $or format - use an array value.'); + } + } + + if (query.$and) { + if (query.$and instanceof Array) { + query.$and.forEach(el => validateQuery(el, skipMongoDBServer13732Workaround)); + } else { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_QUERY, 'Bad $and format - use an array value.'); + } + } + + if (query.$nor) { + if (query.$nor instanceof Array && query.$nor.length > 0) { + query.$nor.forEach(el => validateQuery(el, skipMongoDBServer13732Workaround)); + } else { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_QUERY, 'Bad $nor format - use an array of at least 1 value.'); + } + } + + Object.keys(query).forEach(key => { + if (query && query[key] && query[key].$regex) { + if (typeof query[key].$options === 'string') { + if (!query[key].$options.match(/^[imxs]+$/)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_QUERY, `Bad $options value for query: ${query[key].$options}`); + } + } + } + + if (!isSpecialQueryKey(key) && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${key}`); + } + }); +}; // Filters out any data that shouldn't be on this REST-formatted object. + + +const filterSensitiveData = (isMaster, aclGroup, auth, operation, schema, className, protectedFields, object) => { + let userId = null; + if (auth && auth.user) userId = auth.user.id; // replace protectedFields when using pointer-permissions + + const perms = schema.getClassLevelPermissions(className); + + if (perms) { + const isReadOperation = ['get', 'find'].indexOf(operation) > -1; + + if (isReadOperation && perms.protectedFields) { + // extract protectedFields added with the pointer-permission prefix + const protectedFieldsPointerPerm = Object.keys(perms.protectedFields).filter(key => key.startsWith('userField:')).map(key => { + return { + key: key.substring(10), + value: perms.protectedFields[key] + }; + }); + const newProtectedFields = []; + let overrideProtectedFields = false; // check if the object grants the current user access based on the extracted fields + + protectedFieldsPointerPerm.forEach(pointerPerm => { + let pointerPermIncludesUser = false; + const readUserFieldValue = object[pointerPerm.key]; + + if (readUserFieldValue) { + if (Array.isArray(readUserFieldValue)) { + pointerPermIncludesUser = readUserFieldValue.some(user => user.objectId && user.objectId === userId); + } else { + pointerPermIncludesUser = readUserFieldValue.objectId && readUserFieldValue.objectId === userId; + } + } + + if (pointerPermIncludesUser) { + overrideProtectedFields = true; + newProtectedFields.push(...pointerPerm.value); + } + }); // if atleast one pointer-permission affected the current user override the protectedFields + + if (overrideProtectedFields) protectedFields = newProtectedFields; + } + } + + const isUserClass = className === '_User'; + /* special treat for the user class: don't filter protectedFields if currently loggedin user is + the retrieved user */ + + if (!(isUserClass && userId && object.objectId === userId)) protectedFields && protectedFields.forEach(k => delete object[k]); + + if (!isUserClass) { + return object; + } + + object.password = object._hashed_password; + delete object._hashed_password; + delete object.sessionToken; + + if (isMaster) { + return object; + } + + delete object._email_verify_token; + delete object._perishable_token; + delete object._perishable_token_expires_at; + delete object._tombstone; + delete object._email_verify_token_expires_at; + delete object._failed_login_count; + delete object._account_lockout_expires_at; + delete object._password_changed_at; + delete object._password_history; + + if (aclGroup.indexOf(object.objectId) > -1) { + return object; + } + + delete object.authData; + return object; +}; + +// Runs an update on the database. +// Returns a promise for an object with the new values for field +// modifications that don't know their results ahead of time, like +// 'increment'. +// Options: +// acl: a list of strings. If the object to be updated has an ACL, +// one of the provided strings must provide the caller with +// write permissions. +const specialKeysForUpdate = ['_hashed_password', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count', '_perishable_token_expires_at', '_password_changed_at', '_password_history']; + +const isSpecialUpdateKey = key => { + return specialKeysForUpdate.indexOf(key) >= 0; +}; + +function expandResultOnKeyPath(object, key, value) { + if (key.indexOf('.') < 0) { + object[key] = value[key]; + return object; + } + + const path = key.split('.'); + const firstKey = path[0]; + const nextPath = path.slice(1).join('.'); + object[firstKey] = expandResultOnKeyPath(object[firstKey] || {}, nextPath, value[firstKey]); + delete object[key]; + return object; +} + +function sanitizeDatabaseResult(originalObject, result) { + const response = {}; + + if (!result) { + return Promise.resolve(response); + } + + Object.keys(originalObject).forEach(key => { + const keyUpdate = originalObject[key]; // determine if that was an op + + if (keyUpdate && typeof keyUpdate === 'object' && keyUpdate.__op && ['Add', 'AddUnique', 'Remove', 'Increment'].indexOf(keyUpdate.__op) > -1) { + // only valid ops that produce an actionable result + // the op may have happend on a keypath + expandResultOnKeyPath(response, key, result); + } + }); + return Promise.resolve(response); +} + +function joinTableName(className, key) { + return `_Join:${key}:${className}`; +} + +const flattenUpdateOperatorsForCreate = object => { + for (const key in object) { + if (object[key] && object[key].__op) { + switch (object[key].__op) { + case 'Increment': + if (typeof object[key].amount !== 'number') { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_JSON, 'objects to add must be an array'); + } + + object[key] = object[key].amount; + break; + + case 'Add': + if (!(object[key].objects instanceof Array)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_JSON, 'objects to add must be an array'); + } + + object[key] = object[key].objects; + break; + + case 'AddUnique': + if (!(object[key].objects instanceof Array)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_JSON, 'objects to add must be an array'); + } + + object[key] = object[key].objects; + break; + + case 'Remove': + if (!(object[key].objects instanceof Array)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_JSON, 'objects to add must be an array'); + } + + object[key] = []; + break; + + case 'Delete': + delete object[key]; + break; + + default: + throw new _node.Parse.Error(_node.Parse.Error.COMMAND_UNAVAILABLE, `The ${object[key].__op} operator is not supported yet.`); + } + } + } +}; + +const transformAuthData = (className, object, schema) => { + if (object.authData && className === '_User') { + Object.keys(object.authData).forEach(provider => { + const providerData = object.authData[provider]; + const fieldName = `_auth_data_${provider}`; + + if (providerData == null) { + object[fieldName] = { + __op: 'Delete' + }; + } else { + object[fieldName] = providerData; + schema.fields[fieldName] = { + type: 'Object' + }; + } + }); + delete object.authData; + } +}; // Transforms a Database format ACL to a REST API format ACL + + +const untransformObjectACL = (_ref2) => { + let { + _rperm, + _wperm + } = _ref2, + output = _objectWithoutProperties(_ref2, ["_rperm", "_wperm"]); + + if (_rperm || _wperm) { + output.ACL = {}; + + (_rperm || []).forEach(entry => { + if (!output.ACL[entry]) { + output.ACL[entry] = { + read: true + }; + } else { + output.ACL[entry]['read'] = true; + } + }); + + (_wperm || []).forEach(entry => { + if (!output.ACL[entry]) { + output.ACL[entry] = { + write: true + }; + } else { + output.ACL[entry]['write'] = true; + } + }); + } + + return output; +}; +/** + * When querying, the fieldName may be compound, extract the root fieldName + * `temperature.celsius` becomes `temperature` + * @param {string} fieldName that may be a compound field name + * @returns {string} the root name of the field + */ + + +const getRootFieldName = fieldName => { + return fieldName.split('.')[0]; +}; + +const relationSchema = { + fields: { + relatedId: { + type: 'String' + }, + owningId: { + type: 'String' + } + } +}; + +class DatabaseController { + constructor(adapter, schemaCache, skipMongoDBServer13732Workaround) { + this.adapter = adapter; + this.schemaCache = schemaCache; // We don't want a mutable this.schema, because then you could have + // one request that uses different schemas for different parts of + // it. Instead, use loadSchema to get a schema. + + this.schemaPromise = null; + this.skipMongoDBServer13732Workaround = skipMongoDBServer13732Workaround; + this._transactionalSession = null; + } + + collectionExists(className) { + return this.adapter.classExists(className); + } + + purgeCollection(className) { + return this.loadSchema().then(schemaController => schemaController.getOneSchema(className)).then(schema => this.adapter.deleteObjectsByQuery(className, schema, {})); + } + + validateClassName(className) { + if (!SchemaController.classNameIsValid(className)) { + return Promise.reject(new _node.Parse.Error(_node.Parse.Error.INVALID_CLASS_NAME, 'invalid className: ' + className)); + } + + return Promise.resolve(); + } // Returns a promise for a schemaController. + + + loadSchema(options = { + clearCache: false + }) { + if (this.schemaPromise != null) { + return this.schemaPromise; + } + + this.schemaPromise = SchemaController.load(this.adapter, this.schemaCache, options); + this.schemaPromise.then(() => delete this.schemaPromise, () => delete this.schemaPromise); + return this.loadSchema(options); + } + + loadSchemaIfNeeded(schemaController, options = { + clearCache: false + }) { + return schemaController ? Promise.resolve(schemaController) : this.loadSchema(options); + } // Returns a promise for the classname that is related to the given + // classname through the key. + // TODO: make this not in the DatabaseController interface + + + redirectClassNameForKey(className, key) { + return this.loadSchema().then(schema => { + var t = schema.getExpectedType(className, key); + + if (t != null && typeof t !== 'string' && t.type === 'Relation') { + return t.targetClass; + } + + return className; + }); + } // Uses the schema to validate the object (REST API format). + // Returns a promise that resolves to the new schema. + // This does not update this.schema, because in a situation like a + // batch request, that could confuse other users of the schema. + + + validateObject(className, object, query, { + acl + }) { + let schema; + const isMaster = acl === undefined; + var aclGroup = acl || []; + return this.loadSchema().then(s => { + schema = s; + + if (isMaster) { + return Promise.resolve(); + } + + return this.canAddField(schema, className, object, aclGroup); + }).then(() => { + return schema.validateObject(className, object, query); + }); + } + + update(className, query, update, { + acl, + many, + upsert + } = {}, skipSanitization = false, validateOnly = false, validSchemaController) { + const originalQuery = query; + const originalUpdate = update; // Make a copy of the object, so we don't mutate the incoming data. + + update = (0, _deepcopy.default)(update); + var relationUpdates = []; + var isMaster = acl === undefined; + var aclGroup = acl || []; + return this.loadSchemaIfNeeded(validSchemaController).then(schemaController => { + return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'update')).then(() => { + relationUpdates = this.collectRelationUpdates(className, originalQuery.objectId, update); + + if (!isMaster) { + query = this.addPointerPermissions(schemaController, className, 'update', query, aclGroup); + } + + if (!query) { + return Promise.resolve(); + } + + if (acl) { + query = addWriteACL(query, acl); + } + + validateQuery(query, this.skipMongoDBServer13732Workaround); + return schemaController.getOneSchema(className, true).catch(error => { + // If the schema doesn't exist, pretend it exists with no fields. This behavior + // will likely need revisiting. + if (error === undefined) { + return { + fields: {} + }; + } + + throw error; + }).then(schema => { + Object.keys(update).forEach(fieldName => { + if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Invalid field name for update: ${fieldName}`); + } + + const rootFieldName = getRootFieldName(fieldName); + + if (!SchemaController.fieldNameIsValid(rootFieldName) && !isSpecialUpdateKey(rootFieldName)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Invalid field name for update: ${fieldName}`); + } + }); + + for (const updateOperation in update) { + if (update[updateOperation] && typeof update[updateOperation] === 'object' && Object.keys(update[updateOperation]).some(innerKey => innerKey.includes('$') || innerKey.includes('.'))) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); + } + } + + update = transformObjectACL(update); + transformAuthData(className, update, schema); + + if (validateOnly) { + return this.adapter.find(className, schema, query, {}).then(result => { + if (!result || !result.length) { + throw new _node.Parse.Error(_node.Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + + return {}; + }); + } + + if (many) { + return this.adapter.updateObjectsByQuery(className, schema, query, update, this._transactionalSession); + } else if (upsert) { + return this.adapter.upsertOneObject(className, schema, query, update, this._transactionalSession); + } else { + return this.adapter.findOneAndUpdate(className, schema, query, update, this._transactionalSession); + } + }); + }).then(result => { + if (!result) { + throw new _node.Parse.Error(_node.Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + + if (validateOnly) { + return result; + } + + return this.handleRelationUpdates(className, originalQuery.objectId, update, relationUpdates).then(() => { + return result; + }); + }).then(result => { + if (skipSanitization) { + return Promise.resolve(result); + } + + return sanitizeDatabaseResult(originalUpdate, result); + }); + }); + } // Collect all relation-updating operations from a REST-format update. + // Returns a list of all relation updates to perform + // This mutates update. + + + collectRelationUpdates(className, objectId, update) { + var ops = []; + var deleteMe = []; + objectId = update.objectId || objectId; + + var process = (op, key) => { + if (!op) { + return; + } + + if (op.__op == 'AddRelation') { + ops.push({ + key, + op + }); + deleteMe.push(key); + } + + if (op.__op == 'RemoveRelation') { + ops.push({ + key, + op + }); + deleteMe.push(key); + } + + if (op.__op == 'Batch') { + for (var x of op.ops) { + process(x, key); + } + } + }; + + for (const key in update) { + process(update[key], key); + } + + for (const key of deleteMe) { + delete update[key]; + } + + return ops; + } // Processes relation-updating operations from a REST-format update. + // Returns a promise that resolves when all updates have been performed + + + handleRelationUpdates(className, objectId, update, ops) { + var pending = []; + objectId = update.objectId || objectId; + ops.forEach(({ + key, + op + }) => { + if (!op) { + return; + } + + if (op.__op == 'AddRelation') { + for (const object of op.objects) { + pending.push(this.addRelation(key, className, objectId, object.objectId)); + } + } + + if (op.__op == 'RemoveRelation') { + for (const object of op.objects) { + pending.push(this.removeRelation(key, className, objectId, object.objectId)); + } + } + }); + return Promise.all(pending); + } // Adds a relation. + // Returns a promise that resolves successfully iff the add was successful. + + + addRelation(key, fromClassName, fromId, toId) { + const doc = { + relatedId: toId, + owningId: fromId + }; + return this.adapter.upsertOneObject(`_Join:${key}:${fromClassName}`, relationSchema, doc, doc, this._transactionalSession); + } // Removes a relation. + // Returns a promise that resolves successfully iff the remove was + // successful. + + + removeRelation(key, fromClassName, fromId, toId) { + var doc = { + relatedId: toId, + owningId: fromId + }; + return this.adapter.deleteObjectsByQuery(`_Join:${key}:${fromClassName}`, relationSchema, doc, this._transactionalSession).catch(error => { + // We don't care if they try to delete a non-existent relation. + if (error.code == _node.Parse.Error.OBJECT_NOT_FOUND) { + return; + } + + throw error; + }); + } // Removes objects matches this query from the database. + // Returns a promise that resolves successfully iff the object was + // deleted. + // Options: + // acl: a list of strings. If the object to be updated has an ACL, + // one of the provided strings must provide the caller with + // write permissions. + + + destroy(className, query, { + acl + } = {}, validSchemaController) { + const isMaster = acl === undefined; + const aclGroup = acl || []; + return this.loadSchemaIfNeeded(validSchemaController).then(schemaController => { + return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'delete')).then(() => { + if (!isMaster) { + query = this.addPointerPermissions(schemaController, className, 'delete', query, aclGroup); + + if (!query) { + throw new _node.Parse.Error(_node.Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + } // delete by query + + + if (acl) { + query = addWriteACL(query, acl); + } + + validateQuery(query, this.skipMongoDBServer13732Workaround); + return schemaController.getOneSchema(className).catch(error => { + // If the schema doesn't exist, pretend it exists with no fields. This behavior + // will likely need revisiting. + if (error === undefined) { + return { + fields: {} + }; + } + + throw error; + }).then(parseFormatSchema => this.adapter.deleteObjectsByQuery(className, parseFormatSchema, query, this._transactionalSession)).catch(error => { + // When deleting sessions while changing passwords, don't throw an error if they don't have any sessions. + if (className === '_Session' && error.code === _node.Parse.Error.OBJECT_NOT_FOUND) { + return Promise.resolve({}); + } + + throw error; + }); + }); + }); + } // Inserts an object into the database. + // Returns a promise that resolves successfully iff the object saved. + + + create(className, object, { + acl + } = {}, validateOnly = false, validSchemaController) { + // Make a copy of the object, so we don't mutate the incoming data. + const originalObject = object; + object = transformObjectACL(object); + object.createdAt = { + iso: object.createdAt, + __type: 'Date' + }; + object.updatedAt = { + iso: object.updatedAt, + __type: 'Date' + }; + var isMaster = acl === undefined; + var aclGroup = acl || []; + const relationUpdates = this.collectRelationUpdates(className, null, object); + return this.validateClassName(className).then(() => this.loadSchemaIfNeeded(validSchemaController)).then(schemaController => { + return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'create')).then(() => schemaController.enforceClassExists(className)).then(() => schemaController.getOneSchema(className, true)).then(schema => { + transformAuthData(className, object, schema); + flattenUpdateOperatorsForCreate(object); + + if (validateOnly) { + return {}; + } + + return this.adapter.createObject(className, SchemaController.convertSchemaToAdapterSchema(schema), object, this._transactionalSession); + }).then(result => { + if (validateOnly) { + return originalObject; + } + + return this.handleRelationUpdates(className, object.objectId, object, relationUpdates).then(() => { + return sanitizeDatabaseResult(originalObject, result.ops[0]); + }); + }); + }); + } + + canAddField(schema, className, object, aclGroup) { + const classSchema = schema.schemaData[className]; + + if (!classSchema) { + return Promise.resolve(); + } + + const fields = Object.keys(object); + const schemaFields = Object.keys(classSchema.fields); + const newKeys = fields.filter(field => { + // Skip fields that are unset + if (object[field] && object[field].__op && object[field].__op === 'Delete') { + return false; + } + + return schemaFields.indexOf(field) < 0; + }); + + if (newKeys.length > 0) { + return schema.validatePermission(className, aclGroup, 'addField'); + } + + return Promise.resolve(); + } // Won't delete collections in the system namespace + + /** + * Delete all classes and clears the schema cache + * + * @param {boolean} fast set to true if it's ok to just delete rows and not indexes + * @returns {Promise} when the deletions completes + */ + + + deleteEverything(fast = false) { + this.schemaPromise = null; + return Promise.all([this.adapter.deleteAllClasses(fast), this.schemaCache.clear()]); + } // Returns a promise for a list of related ids given an owning id. + // className here is the owning className. + + + relatedIds(className, key, owningId, queryOptions) { + const { + skip, + limit, + sort + } = queryOptions; + const findOptions = {}; + + if (sort && sort.createdAt && this.adapter.canSortOnJoinTables) { + findOptions.sort = { + _id: sort.createdAt + }; + findOptions.limit = limit; + findOptions.skip = skip; + queryOptions.skip = 0; + } + + return this.adapter.find(joinTableName(className, key), relationSchema, { + owningId + }, findOptions).then(results => results.map(result => result.relatedId)); + } // Returns a promise for a list of owning ids given some related ids. + // className here is the owning className. + + + owningIds(className, key, relatedIds) { + return this.adapter.find(joinTableName(className, key), relationSchema, { + relatedId: { + $in: relatedIds + } + }, {}).then(results => results.map(result => result.owningId)); + } // Modifies query so that it no longer has $in on relation fields, or + // equal-to-pointer constraints on relation fields. + // Returns a promise that resolves when query is mutated + + + reduceInRelation(className, query, schema) { + // Search for an in-relation or equal-to-relation + // Make it sequential for now, not sure of paralleization side effects + if (query['$or']) { + const ors = query['$or']; + return Promise.all(ors.map((aQuery, index) => { + return this.reduceInRelation(className, aQuery, schema).then(aQuery => { + query['$or'][index] = aQuery; + }); + })).then(() => { + return Promise.resolve(query); + }); + } + + const promises = Object.keys(query).map(key => { + const t = schema.getExpectedType(className, key); + + if (!t || t.type !== 'Relation') { + return Promise.resolve(query); + } + + let queries = null; + + if (query[key] && (query[key]['$in'] || query[key]['$ne'] || query[key]['$nin'] || query[key].__type == 'Pointer')) { + // Build the list of queries + queries = Object.keys(query[key]).map(constraintKey => { + let relatedIds; + let isNegation = false; + + if (constraintKey === 'objectId') { + relatedIds = [query[key].objectId]; + } else if (constraintKey == '$in') { + relatedIds = query[key]['$in'].map(r => r.objectId); + } else if (constraintKey == '$nin') { + isNegation = true; + relatedIds = query[key]['$nin'].map(r => r.objectId); + } else if (constraintKey == '$ne') { + isNegation = true; + relatedIds = [query[key]['$ne'].objectId]; + } else { + return; + } + + return { + isNegation, + relatedIds + }; + }); + } else { + queries = [{ + isNegation: false, + relatedIds: [] + }]; + } // remove the current queryKey as we don,t need it anymore + + + delete query[key]; // execute each query independently to build the list of + // $in / $nin + + const promises = queries.map(q => { + if (!q) { + return Promise.resolve(); + } + + return this.owningIds(className, key, q.relatedIds).then(ids => { + if (q.isNegation) { + this.addNotInObjectIdsIds(ids, query); + } else { + this.addInObjectIdsIds(ids, query); + } + + return Promise.resolve(); + }); + }); + return Promise.all(promises).then(() => { + return Promise.resolve(); + }); + }); + return Promise.all(promises).then(() => { + return Promise.resolve(query); + }); + } // Modifies query so that it no longer has $relatedTo + // Returns a promise that resolves when query is mutated + + + reduceRelationKeys(className, query, queryOptions) { + if (query['$or']) { + return Promise.all(query['$or'].map(aQuery => { + return this.reduceRelationKeys(className, aQuery, queryOptions); + })); + } + + var relatedTo = query['$relatedTo']; + + if (relatedTo) { + return this.relatedIds(relatedTo.object.className, relatedTo.key, relatedTo.object.objectId, queryOptions).then(ids => { + delete query['$relatedTo']; + this.addInObjectIdsIds(ids, query); + return this.reduceRelationKeys(className, query, queryOptions); + }).then(() => {}); + } + } + + addInObjectIdsIds(ids = null, query) { + const idsFromString = typeof query.objectId === 'string' ? [query.objectId] : null; + const idsFromEq = query.objectId && query.objectId['$eq'] ? [query.objectId['$eq']] : null; + const idsFromIn = query.objectId && query.objectId['$in'] ? query.objectId['$in'] : null; // -disable-next + + const allIds = [idsFromString, idsFromEq, idsFromIn, ids].filter(list => list !== null); + const totalLength = allIds.reduce((memo, list) => memo + list.length, 0); + let idsIntersection = []; + + if (totalLength > 125) { + idsIntersection = _intersect.default.big(allIds); + } else { + idsIntersection = (0, _intersect.default)(allIds); + } // Need to make sure we don't clobber existing shorthand $eq constraints on objectId. + + + if (!('objectId' in query)) { + query.objectId = { + $in: undefined + }; + } else if (typeof query.objectId === 'string') { + query.objectId = { + $in: undefined, + $eq: query.objectId + }; + } + + query.objectId['$in'] = idsIntersection; + return query; + } + + addNotInObjectIdsIds(ids = [], query) { + const idsFromNin = query.objectId && query.objectId['$nin'] ? query.objectId['$nin'] : []; + let allIds = [...idsFromNin, ...ids].filter(list => list !== null); // make a set and spread to remove duplicates + + allIds = [...new Set(allIds)]; // Need to make sure we don't clobber existing shorthand $eq constraints on objectId. + + if (!('objectId' in query)) { + query.objectId = { + $nin: undefined + }; + } else if (typeof query.objectId === 'string') { + query.objectId = { + $nin: undefined, + $eq: query.objectId + }; + } + + query.objectId['$nin'] = allIds; + return query; + } // Runs a query on the database. + // Returns a promise that resolves to a list of items. + // Options: + // skip number of results to skip. + // limit limit to this number of results. + // sort an object where keys are the fields to sort by. + // the value is +1 for ascending, -1 for descending. + // count run a count instead of returning results. + // acl restrict this operation with an ACL for the provided array + // of user objectIds and roles. acl: null means no user. + // when this field is not present, don't do anything regarding ACLs. + // TODO: make userIds not needed here. The db adapter shouldn't know + // anything about users, ideally. Then, improve the format of the ACL + // arg to work like the others. + + + find(className, query, { + skip, + limit, + acl, + sort = {}, + count, + keys, + op, + distinct, + pipeline, + readPreference + } = {}, auth = {}, validSchemaController) { + const isMaster = acl === undefined; + const aclGroup = acl || []; + op = op || (typeof query.objectId == 'string' && Object.keys(query).length === 1 ? 'get' : 'find'); // Count operation if counting + + op = count === true ? 'count' : op; + let classExists = true; + return this.loadSchemaIfNeeded(validSchemaController).then(schemaController => { + //Allow volatile classes if querying with Master (for _PushStatus) + //TODO: Move volatile classes concept into mongo adapter, postgres adapter shouldn't care + //that api.parse.com breaks when _PushStatus exists in mongo. + return schemaController.getOneSchema(className, isMaster).catch(error => { + // Behavior for non-existent classes is kinda weird on Parse.com. Probably doesn't matter too much. + // For now, pretend the class exists but has no objects, + if (error === undefined) { + classExists = false; + return { + fields: {} + }; + } + + throw error; + }).then(schema => { + // Parse.com treats queries on _created_at and _updated_at as if they were queries on createdAt and updatedAt, + // so duplicate that behavior here. If both are specified, the correct behavior to match Parse.com is to + // use the one that appears first in the sort list. + if (sort._created_at) { + sort.createdAt = sort._created_at; + delete sort._created_at; + } + + if (sort._updated_at) { + sort.updatedAt = sort._updated_at; + delete sort._updated_at; + } + + const queryOptions = { + skip, + limit, + sort, + keys, + readPreference + }; + Object.keys(sort).forEach(fieldName => { + if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Cannot sort by ${fieldName}`); + } + + const rootFieldName = getRootFieldName(fieldName); + + if (!SchemaController.fieldNameIsValid(rootFieldName)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}.`); + } + }); + return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, op)).then(() => this.reduceRelationKeys(className, query, queryOptions)).then(() => this.reduceInRelation(className, query, schemaController)).then(() => { + let protectedFields; + + if (!isMaster) { + query = this.addPointerPermissions(schemaController, className, op, query, aclGroup); + /* Don't use projections to optimize the protectedFields since the protectedFields + based on pointer-permissions are determined after querying. The filtering can + overwrite the protected fields. */ + + protectedFields = this.addProtectedFields(schemaController, className, query, aclGroup, auth); + } + + if (!query) { + if (op === 'get') { + throw new _node.Parse.Error(_node.Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } else { + return []; + } + } + + if (!isMaster) { + if (op === 'update' || op === 'delete') { + query = addWriteACL(query, aclGroup); + } else { + query = addReadACL(query, aclGroup); + } + } + + validateQuery(query, this.skipMongoDBServer13732Workaround); + + if (count) { + if (!classExists) { + return 0; + } else { + return this.adapter.count(className, schema, query, readPreference); + } + } else if (distinct) { + if (!classExists) { + return []; + } else { + return this.adapter.distinct(className, schema, query, distinct); + } + } else if (pipeline) { + if (!classExists) { + return []; + } else { + return this.adapter.aggregate(className, schema, pipeline, readPreference); + } + } else { + return this.adapter.find(className, schema, query, queryOptions).then(objects => objects.map(object => { + object = untransformObjectACL(object); + return filterSensitiveData(isMaster, aclGroup, auth, op, schemaController, className, protectedFields, object); + })).catch(error => { + throw new _node.Parse.Error(_node.Parse.Error.INTERNAL_SERVER_ERROR, error); + }); + } + }); + }); + }); + } + + deleteSchema(className) { + return this.loadSchema({ + clearCache: true + }).then(schemaController => schemaController.getOneSchema(className, true)).catch(error => { + if (error === undefined) { + return { + fields: {} + }; + } else { + throw error; + } + }).then(schema => { + return this.collectionExists(className).then(() => this.adapter.count(className, { + fields: {} + }, null, '', false)).then(count => { + if (count > 0) { + throw new _node.Parse.Error(255, `Class ${className} is not empty, contains ${count} objects, cannot drop schema.`); + } + + return this.adapter.deleteClass(className); + }).then(wasParseCollection => { + if (wasParseCollection) { + const relationFieldNames = Object.keys(schema.fields).filter(fieldName => schema.fields[fieldName].type === 'Relation'); + return Promise.all(relationFieldNames.map(name => this.adapter.deleteClass(joinTableName(className, name)))).then(() => { + return; + }); + } else { + return Promise.resolve(); + } + }); + }); + } + + addPointerPermissions(schema, className, operation, query, aclGroup = []) { + // Check if class has public permission for operation + // If the BaseCLP pass, let go through + if (schema.testPermissionsForClassName(className, aclGroup, operation)) { + return query; + } + + const perms = schema.getClassLevelPermissions(className); + const field = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields'; + const userACL = aclGroup.filter(acl => { + return acl.indexOf('role:') != 0 && acl != '*'; + }); // the ACL should have exactly 1 user + + if (perms && perms[field] && perms[field].length > 0) { + // No user set return undefined + // If the length is > 1, that means we didn't de-dupe users correctly + if (userACL.length != 1) { + return; + } + + const userId = userACL[0]; + const userPointer = { + __type: 'Pointer', + className: '_User', + objectId: userId + }; + const permFields = perms[field]; + const ors = permFields.flatMap(key => { + // constraint for single pointer setup + const q = { + [key]: userPointer + }; // constraint for users-array setup + + const qa = { + [key]: { + $all: [userPointer] + } + }; // if we already have a constraint on the key, use the $and + + if (Object.prototype.hasOwnProperty.call(query, key)) { + return [{ + $and: [q, query] + }, { + $and: [qa, query] + }]; + } // otherwise just add the constaint + + + return [Object.assign({}, query, q), Object.assign({}, query, qa)]; + }); + return { + $or: ors + }; + } else { + return query; + } + } + + addProtectedFields(schema, className, query = {}, aclGroup = [], auth = {}) { + const perms = schema.getClassLevelPermissions(className); + if (!perms) return null; + const protectedFields = perms.protectedFields; + if (!protectedFields) return null; + if (aclGroup.indexOf(query.objectId) > -1) return null; // remove userField keys since they are filtered after querying + + let protectedKeys = Object.keys(protectedFields).reduce((acc, val) => { + if (val.startsWith('userField:')) return acc; + return acc.concat(protectedFields[val]); + }, []); + [...(auth.userRoles || [])].forEach(role => { + const fields = protectedFields[role]; + + if (fields) { + protectedKeys = protectedKeys.filter(v => fields.includes(v)); + } + }); + return protectedKeys; + } + + createTransactionalSession() { + return this.adapter.createTransactionalSession().then(transactionalSession => { + this._transactionalSession = transactionalSession; + }); + } + + commitTransactionalSession() { + if (!this._transactionalSession) { + throw new Error('There is no transactional session to commit'); + } + + return this.adapter.commitTransactionalSession(this._transactionalSession).then(() => { + this._transactionalSession = null; + }); + } + + abortTransactionalSession() { + if (!this._transactionalSession) { + throw new Error('There is no transactional session to abort'); + } + + return this.adapter.abortTransactionalSession(this._transactionalSession).then(() => { + this._transactionalSession = null; + }); + } // TODO: create indexes on first creation of a _User object. Otherwise it's impossible to + // have a Parse app without it having a _User collection. + + + performInitialization() { + const requiredUserFields = { + fields: _objectSpread({}, SchemaController.defaultColumns._Default, {}, SchemaController.defaultColumns._User) + }; + const requiredRoleFields = { + fields: _objectSpread({}, SchemaController.defaultColumns._Default, {}, SchemaController.defaultColumns._Role) + }; + const userClassPromise = this.loadSchema().then(schema => schema.enforceClassExists('_User')); + const roleClassPromise = this.loadSchema().then(schema => schema.enforceClassExists('_Role')); + const usernameUniqueness = userClassPromise.then(() => this.adapter.ensureUniqueness('_User', requiredUserFields, ['username'])).catch(error => { + _logger.default.warn('Unable to ensure uniqueness for usernames: ', error); + + throw error; + }); + const emailUniqueness = userClassPromise.then(() => this.adapter.ensureUniqueness('_User', requiredUserFields, ['email'])).catch(error => { + _logger.default.warn('Unable to ensure uniqueness for user email addresses: ', error); + + throw error; + }); + const roleUniqueness = roleClassPromise.then(() => this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name'])).catch(error => { + _logger.default.warn('Unable to ensure uniqueness for role name: ', error); + + throw error; + }); + const indexPromise = this.adapter.updateSchemaWithIndexes(); // Create tables for volatile classes + + const adapterInit = this.adapter.performInitialization({ + VolatileClassesSchemas: SchemaController.VolatileClassesSchemas + }); + return Promise.all([usernameUniqueness, emailUniqueness, roleUniqueness, adapterInit, indexPromise]); + } + +} + +module.exports = DatabaseController; // Expose validateQuery for tests + +module.exports._validateQuery = validateQuery; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiYWRkV3JpdGVBQ0wiLCJxdWVyeSIsImFjbCIsIm5ld1F1ZXJ5IiwiXyIsImNsb25lRGVlcCIsIl93cGVybSIsIiRpbiIsImFkZFJlYWRBQ0wiLCJfcnBlcm0iLCJ0cmFuc2Zvcm1PYmplY3RBQ0wiLCJBQ0wiLCJyZXN1bHQiLCJlbnRyeSIsInJlYWQiLCJwdXNoIiwid3JpdGUiLCJzcGVjaWFsUXVlcnlrZXlzIiwiaXNTcGVjaWFsUXVlcnlLZXkiLCJrZXkiLCJpbmRleE9mIiwidmFsaWRhdGVRdWVyeSIsInNraXBNb25nb0RCU2VydmVyMTM3MzJXb3JrYXJvdW5kIiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfUVVFUlkiLCIkb3IiLCJBcnJheSIsImZvckVhY2giLCJlbCIsIk9iamVjdCIsImtleXMiLCJub0NvbGxpc2lvbnMiLCJzb21lIiwic3VicSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImhhc05lYXJzIiwic3VicXVlcnkiLCIkYW5kIiwiJG5vciIsImxlbmd0aCIsIiRyZWdleCIsIiRvcHRpb25zIiwibWF0Y2giLCJJTlZBTElEX0tFWV9OQU1FIiwiZmlsdGVyU2Vuc2l0aXZlRGF0YSIsImlzTWFzdGVyIiwiYWNsR3JvdXAiLCJhdXRoIiwib3BlcmF0aW9uIiwic2NoZW1hIiwiY2xhc3NOYW1lIiwicHJvdGVjdGVkRmllbGRzIiwib2JqZWN0IiwidXNlcklkIiwidXNlciIsImlkIiwicGVybXMiLCJnZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJpc1JlYWRPcGVyYXRpb24iLCJwcm90ZWN0ZWRGaWVsZHNQb2ludGVyUGVybSIsImZpbHRlciIsInN0YXJ0c1dpdGgiLCJtYXAiLCJzdWJzdHJpbmciLCJ2YWx1ZSIsIm5ld1Byb3RlY3RlZEZpZWxkcyIsIm92ZXJyaWRlUHJvdGVjdGVkRmllbGRzIiwicG9pbnRlclBlcm0iLCJwb2ludGVyUGVybUluY2x1ZGVzVXNlciIsInJlYWRVc2VyRmllbGRWYWx1ZSIsImlzQXJyYXkiLCJvYmplY3RJZCIsImlzVXNlckNsYXNzIiwiayIsInBhc3N3b3JkIiwiX2hhc2hlZF9wYXNzd29yZCIsInNlc3Npb25Ub2tlbiIsIl9lbWFpbF92ZXJpZnlfdG9rZW4iLCJfcGVyaXNoYWJsZV90b2tlbiIsIl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQiLCJfdG9tYnN0b25lIiwiX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0IiwiX2ZhaWxlZF9sb2dpbl9jb3VudCIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIl9wYXNzd29yZF9jaGFuZ2VkX2F0IiwiX3Bhc3N3b3JkX2hpc3RvcnkiLCJhdXRoRGF0YSIsInNwZWNpYWxLZXlzRm9yVXBkYXRlIiwiaXNTcGVjaWFsVXBkYXRlS2V5IiwiZXhwYW5kUmVzdWx0T25LZXlQYXRoIiwicGF0aCIsInNwbGl0IiwiZmlyc3RLZXkiLCJuZXh0UGF0aCIsInNsaWNlIiwiam9pbiIsInNhbml0aXplRGF0YWJhc2VSZXN1bHQiLCJvcmlnaW5hbE9iamVjdCIsInJlc3BvbnNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJrZXlVcGRhdGUiLCJfX29wIiwiam9pblRhYmxlTmFtZSIsImZsYXR0ZW5VcGRhdGVPcGVyYXRvcnNGb3JDcmVhdGUiLCJhbW91bnQiLCJJTlZBTElEX0pTT04iLCJvYmplY3RzIiwiQ09NTUFORF9VTkFWQUlMQUJMRSIsInRyYW5zZm9ybUF1dGhEYXRhIiwicHJvdmlkZXIiLCJwcm92aWRlckRhdGEiLCJmaWVsZE5hbWUiLCJmaWVsZHMiLCJ0eXBlIiwidW50cmFuc2Zvcm1PYmplY3RBQ0wiLCJvdXRwdXQiLCJnZXRSb290RmllbGROYW1lIiwicmVsYXRpb25TY2hlbWEiLCJyZWxhdGVkSWQiLCJvd25pbmdJZCIsIkRhdGFiYXNlQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwiYWRhcHRlciIsInNjaGVtYUNhY2hlIiwic2NoZW1hUHJvbWlzZSIsIl90cmFuc2FjdGlvbmFsU2Vzc2lvbiIsImNvbGxlY3Rpb25FeGlzdHMiLCJjbGFzc0V4aXN0cyIsInB1cmdlQ29sbGVjdGlvbiIsImxvYWRTY2hlbWEiLCJ0aGVuIiwic2NoZW1hQ29udHJvbGxlciIsImdldE9uZVNjaGVtYSIsImRlbGV0ZU9iamVjdHNCeVF1ZXJ5IiwidmFsaWRhdGVDbGFzc05hbWUiLCJTY2hlbWFDb250cm9sbGVyIiwiY2xhc3NOYW1lSXNWYWxpZCIsInJlamVjdCIsIklOVkFMSURfQ0xBU1NfTkFNRSIsIm9wdGlvbnMiLCJjbGVhckNhY2hlIiwibG9hZCIsImxvYWRTY2hlbWFJZk5lZWRlZCIsInJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5IiwidCIsImdldEV4cGVjdGVkVHlwZSIsInRhcmdldENsYXNzIiwidmFsaWRhdGVPYmplY3QiLCJ1bmRlZmluZWQiLCJzIiwiY2FuQWRkRmllbGQiLCJ1cGRhdGUiLCJtYW55IiwidXBzZXJ0Iiwic2tpcFNhbml0aXphdGlvbiIsInZhbGlkYXRlT25seSIsInZhbGlkU2NoZW1hQ29udHJvbGxlciIsIm9yaWdpbmFsUXVlcnkiLCJvcmlnaW5hbFVwZGF0ZSIsInJlbGF0aW9uVXBkYXRlcyIsInZhbGlkYXRlUGVybWlzc2lvbiIsImNvbGxlY3RSZWxhdGlvblVwZGF0ZXMiLCJhZGRQb2ludGVyUGVybWlzc2lvbnMiLCJjYXRjaCIsImVycm9yIiwicm9vdEZpZWxkTmFtZSIsImZpZWxkTmFtZUlzVmFsaWQiLCJ1cGRhdGVPcGVyYXRpb24iLCJpbm5lcktleSIsImluY2x1ZGVzIiwiSU5WQUxJRF9ORVNURURfS0VZIiwiZmluZCIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ1cGRhdGVPYmplY3RzQnlRdWVyeSIsInVwc2VydE9uZU9iamVjdCIsImZpbmRPbmVBbmRVcGRhdGUiLCJoYW5kbGVSZWxhdGlvblVwZGF0ZXMiLCJvcHMiLCJkZWxldGVNZSIsInByb2Nlc3MiLCJvcCIsIngiLCJwZW5kaW5nIiwiYWRkUmVsYXRpb24iLCJyZW1vdmVSZWxhdGlvbiIsImFsbCIsImZyb21DbGFzc05hbWUiLCJmcm9tSWQiLCJ0b0lkIiwiZG9jIiwiY29kZSIsImRlc3Ryb3kiLCJwYXJzZUZvcm1hdFNjaGVtYSIsImNyZWF0ZSIsImNyZWF0ZWRBdCIsImlzbyIsIl9fdHlwZSIsInVwZGF0ZWRBdCIsImVuZm9yY2VDbGFzc0V4aXN0cyIsImNyZWF0ZU9iamVjdCIsImNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEiLCJjbGFzc1NjaGVtYSIsInNjaGVtYURhdGEiLCJzY2hlbWFGaWVsZHMiLCJuZXdLZXlzIiwiZmllbGQiLCJkZWxldGVFdmVyeXRoaW5nIiwiZmFzdCIsImRlbGV0ZUFsbENsYXNzZXMiLCJjbGVhciIsInJlbGF0ZWRJZHMiLCJxdWVyeU9wdGlvbnMiLCJza2lwIiwibGltaXQiLCJzb3J0IiwiZmluZE9wdGlvbnMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiX2lkIiwicmVzdWx0cyIsIm93bmluZ0lkcyIsInJlZHVjZUluUmVsYXRpb24iLCJvcnMiLCJhUXVlcnkiLCJpbmRleCIsInByb21pc2VzIiwicXVlcmllcyIsImNvbnN0cmFpbnRLZXkiLCJpc05lZ2F0aW9uIiwiciIsInEiLCJpZHMiLCJhZGROb3RJbk9iamVjdElkc0lkcyIsImFkZEluT2JqZWN0SWRzSWRzIiwicmVkdWNlUmVsYXRpb25LZXlzIiwicmVsYXRlZFRvIiwiaWRzRnJvbVN0cmluZyIsImlkc0Zyb21FcSIsImlkc0Zyb21JbiIsImFsbElkcyIsImxpc3QiLCJ0b3RhbExlbmd0aCIsInJlZHVjZSIsIm1lbW8iLCJpZHNJbnRlcnNlY3Rpb24iLCJpbnRlcnNlY3QiLCJiaWciLCIkZXEiLCJpZHNGcm9tTmluIiwiU2V0IiwiJG5pbiIsImNvdW50IiwiZGlzdGluY3QiLCJwaXBlbGluZSIsInJlYWRQcmVmZXJlbmNlIiwiX2NyZWF0ZWRfYXQiLCJfdXBkYXRlZF9hdCIsImFkZFByb3RlY3RlZEZpZWxkcyIsImFnZ3JlZ2F0ZSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImRlbGV0ZVNjaGVtYSIsImRlbGV0ZUNsYXNzIiwid2FzUGFyc2VDb2xsZWN0aW9uIiwicmVsYXRpb25GaWVsZE5hbWVzIiwibmFtZSIsInRlc3RQZXJtaXNzaW9uc0ZvckNsYXNzTmFtZSIsInVzZXJBQ0wiLCJ1c2VyUG9pbnRlciIsInBlcm1GaWVsZHMiLCJmbGF0TWFwIiwicWEiLCIkYWxsIiwiYXNzaWduIiwicHJvdGVjdGVkS2V5cyIsImFjYyIsInZhbCIsImNvbmNhdCIsInVzZXJSb2xlcyIsInJvbGUiLCJ2IiwiY3JlYXRlVHJhbnNhY3Rpb25hbFNlc3Npb24iLCJ0cmFuc2FjdGlvbmFsU2Vzc2lvbiIsImNvbW1pdFRyYW5zYWN0aW9uYWxTZXNzaW9uIiwiYWJvcnRUcmFuc2FjdGlvbmFsU2Vzc2lvbiIsInBlcmZvcm1Jbml0aWFsaXphdGlvbiIsInJlcXVpcmVkVXNlckZpZWxkcyIsImRlZmF1bHRDb2x1bW5zIiwiX0RlZmF1bHQiLCJfVXNlciIsInJlcXVpcmVkUm9sZUZpZWxkcyIsIl9Sb2xlIiwidXNlckNsYXNzUHJvbWlzZSIsInJvbGVDbGFzc1Byb21pc2UiLCJ1c2VybmFtZVVuaXF1ZW5lc3MiLCJlbnN1cmVVbmlxdWVuZXNzIiwibG9nZ2VyIiwid2FybiIsImVtYWlsVW5pcXVlbmVzcyIsInJvbGVVbmlxdWVuZXNzIiwiaW5kZXhQcm9taXNlIiwidXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMiLCJhZGFwdGVySW5pdCIsIlZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMiLCJtb2R1bGUiLCJleHBvcnRzIiwiX3ZhbGlkYXRlUXVlcnkiXSwibWFwcGluZ3MiOiI7O0FBS0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQU1BLFNBQVNBLFdBQVQsQ0FBcUJDLEtBQXJCLEVBQTRCQyxHQUE1QixFQUFpQztBQUMvQixRQUFNQyxRQUFRLEdBQUdDLGdCQUFFQyxTQUFGLENBQVlKLEtBQVosQ0FBakIsQ0FEK0IsQ0FFL0I7OztBQUNB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LDZDQUFaLEVBQTJEbkksS0FBM0Q7O0FBQ0EsWUFBTUEsS0FBTjtBQUNELEtBUG9CLENBQXZCO0FBU0EsVUFBTXNJLFlBQVksR0FBRyxLQUFLaEwsT0FBTCxDQUFhaUwsdUJBQWIsRUFBckIsQ0FuRHNCLENBcUR0Qjs7QUFDQSxVQUFNQyxXQUFXLEdBQUcsS0FBS2xMLE9BQUwsQ0FBYWlLLHFCQUFiLENBQW1DO0FBQ3JEa0IsTUFBQUEsc0JBQXNCLEVBQUV0SyxnQkFBZ0IsQ0FBQ3NLO0FBRFksS0FBbkMsQ0FBcEI7QUFHQSxXQUFPM00sT0FBTyxDQUFDdUYsR0FBUixDQUFZLENBQ2pCMkcsa0JBRGlCLEVBRWpCSSxlQUZpQixFQUdqQkMsY0FIaUIsRUFJakJHLFdBSmlCLEVBS2pCRixZQUxpQixDQUFaLENBQVA7QUFPRDs7QUE3c0NzQjs7QUFrdEN6QkksTUFBTSxDQUFDQyxPQUFQLEdBQWlCdkwsa0JBQWpCLEMsQ0FDQTs7QUFDQXNMLE1BQU0sQ0FBQ0MsT0FBUCxDQUFlQyxjQUFmLEdBQWdDL1IsYUFBaEMiLCJzb3VyY2VzQ29udGVudCI6WyLvu78vLyBAZmxvd1xuLy8gQSBkYXRhYmFzZSBhZGFwdGVyIHRoYXQgd29ya3Mgd2l0aCBkYXRhIGV4cG9ydGVkIGZyb20gdGhlIGhvc3RlZFxuLy8gUGFyc2UgZGF0YWJhc2UuXG5cbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IHsgUGFyc2UgfSBmcm9tICdwYXJzZS9ub2RlJztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IGludGVyc2VjdCBmcm9tICdpbnRlcnNlY3QnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgZGVlcGNvcHkgZnJvbSAnZGVlcGNvcHknO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0ICogYXMgU2NoZW1hQ29udHJvbGxlciBmcm9tICcuL1NjaGVtYUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9TdG9yYWdlL1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCB0eXBlIHtcbiAgUXVlcnlPcHRpb25zLFxuICBGdWxsUXVlcnlPcHRpb25zLFxufSBmcm9tICcuLi9BZGFwdGVycy9TdG9yYWdlL1N0b3JhZ2VBZGFwdGVyJztcblxuZnVuY3Rpb24gYWRkV3JpdGVBQ0wocXVlcnksIGFjbCkge1xuICBjb25zdCBuZXdRdWVyeSA9IF8uY2xvbmVEZWVwKHF1ZXJ5KTtcbiAgLy9DYW4ndCBiZSBhbnkgZXhpc3RpbmcgJ193cGVybScgcXVlcnksIHdlIGRvbid0IGFsbG93IGNsaWVudCBxdWVyaWVzIG9uIHRoYXQsIG5vIG5lZWQgdG8gJGFuZFxuICBuZXdRdWVyeS5fd3Blcm0gPSB7ICRpbjogW251bGwsIC4uLmFjbF0gfTtcbiAgcmV0dXJuIG5ld1F1ZXJ5O1xufVxuXG5mdW5jdGlvbiBhZGRSZWFkQUNMKHF1ZXJ5LCBhY2wpIHtcbiAgY29uc3QgbmV3UXVlcnkgPSBfLmNsb25lRGVlcChxdWVyeSk7XG4gIC8vQ2FuJ3QgYmUgYW55IGV4aXN0aW5nICdfcnBlcm0nIHF1ZXJ5LCB3ZSBkb24ndCBhbGxvdyBjbGllbnQgcXVlcmllcyBvbiB0aGF0LCBubyBuZWVkIHRvICRhbmRcbiAgbmV3UXVlcnkuX3JwZXJtID0geyAkaW46IFtudWxsLCAnKicsIC4uLmFjbF0gfTtcbiAgcmV0dXJuIG5ld1F1ZXJ5O1xufVxuXG4vLyBUcmFuc2Zvcm1zIGEgUkVTVCBBUEkgZm9ybWF0dGVkIEFDTCBvYmplY3QgdG8gb3VyIHR3by1maWVsZCBtb25nbyBmb3JtYXQuXG5jb25zdCB0cmFuc2Zvcm1PYmplY3RBQ0wgPSAoeyBBQ0wsIC4uLnJlc3VsdCB9KSA9PiB7XG4gIGlmICghQUNMKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHJlc3VsdC5fd3Blcm0gPSBbXTtcbiAgcmVzdWx0Ll9ycGVybSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZW50cnkgaW4gQUNMKSB7XG4gICAgaWYgKEFDTFtlbnRyeV0ucmVhZCkge1xuICAgICAgcmVzdWx0Ll9ycGVybS5wdXNoKGVudHJ5KTtcbiAgICB9XG4gICAgaWYgKEFDTFtlbnRyeV0ud3JpdGUpIHtcbiAgICAgIHJlc3VsdC5fd3Blcm0ucHVzaChlbnRyeSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5jb25zdCBzcGVjaWFsUXVlcnlrZXlzID0gW1xuICAnJGFuZCcsXG4gICckb3InLFxuICAnJG5vcicsXG4gICdfcnBlcm0nLFxuICAnX3dwZXJtJyxcbiAgJ19wZXJpc2hhYmxlX3Rva2VuJyxcbiAgJ19lbWFpbF92ZXJpZnlfdG9rZW4nLFxuICAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0JyxcbiAgJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCcsXG4gICdfZmFpbGVkX2xvZ2luX2NvdW50Jyxcbl07XG5cbmNvbnN0IGlzU3BlY2lhbFF1ZXJ5S2V5ID0ga2V5ID0+IHtcbiAgcmV0dXJuIHNwZWNpYWxRdWVyeWtleXMuaW5kZXhPZihrZXkpID49IDA7XG59O1xuXG5jb25zdCB2YWxpZGF0ZVF1ZXJ5ID0gKFxuICBxdWVyeTogYW55LFxuICBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZDogYm9vbGVhblxuKTogdm9pZCA9PiB7XG4gIGlmIChxdWVyeS5BQ0wpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgJ0Nhbm5vdCBxdWVyeSBvbiBBQ0wuJyk7XG4gIH1cblxuICBpZiAocXVlcnkuJG9yKSB7XG4gICAgaWYgKHF1ZXJ5LiRvciBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBxdWVyeS4kb3IuZm9yRWFjaChlbCA9PlxuICAgICAgICB2YWxpZGF0ZVF1ZXJ5KGVsLCBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZClcbiAgICAgICk7XG5cbiAgICAgIGlmICghc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQpIHtcbiAgICAgICAgLyogSW4gTW9uZ29EQiAzLjIgJiAzLjQsICRvciBxdWVyaWVzIHdoaWNoIGFyZSBub3QgYWxvbmUgYXQgdGhlIHRvcFxuICAgICAgICAgKiBsZXZlbCBvZiB0aGUgcXVlcnkgY2FuIG5vdCBtYWtlIGVmZmljaWVudCB1c2Ugb2YgaW5kZXhlcyBkdWUgdG8gYVxuICAgICAgICAgKiBsb25nIHN0YW5kaW5nIGJ1ZyBrbm93biBhcyBTRVJWRVItMTM3MzIuXG4gICAgICAgICAqXG4gICAgICAgICAqIFRoaXMgYnVnIHdhcyBmaXhlZCBpbiBNb25nb0RCIHZlcnNpb24gMy42LlxuICAgICAgICAgKlxuICAgICAgICAgKiBGb3IgdmVyc2lvbnMgcHJlLTMuNiwgdGhlIGJlbG93IGxvZ2ljIHByb2R1Y2VzIGEgc3Vic3RhbnRpYWxcbiAgICAgICAgICogcGVyZm9ybWFuY2UgaW1wcm92ZW1lbnQgaW5zaWRlIHRoZSBkYXRhYmFzZSBieSBhdm9pZGluZyB0aGUgYnVnLlxuICAgICAgICAgKlxuICAgICAgICAgKiBGb3IgdmVyc2lvbnMgMy42IGFuZCBhYm92ZSwgdGhlcmUgaXMgbm8gcGVyZm9ybWFuY2UgaW1wcm92ZW1lbnQgYW5kXG4gICAgICAgICAqIHRoZSBsb2dpYyBpcyB1bm5lY2Vzc2FyeS4gU29tZSBxdWVyeSBwYXR0ZXJucyBhcmUgZXZlbiBzbG93ZWQgYnlcbiAgICAgICAgICogdGhlIGJlbG93IGxvZ2ljLCBkdWUgdG8gdGhlIGJ1ZyBoYXZpbmcgYmVlbiBmaXhlZCBhbmQgYmV0dGVyXG4gICAgICAgICAqIHF1ZXJ5IHBsYW5zIGJlaW5nIGNob3Nlbi5cbiAgICAgICAgICpcbiAgICAgICAgICogV2hlbiB2ZXJzaW9ucyBiZWZvcmUgMy40IGFyZSBubyBsb25nZXIgc3VwcG9ydGVkIGJ5IHRoaXMgcHJvamVjdCxcbiAgICAgICAgICogdGhpcyBsb2dpYywgYW5kIHRoZSBhY2NvbXBhbnlpbmcgYHNraXBNb25nb0RCU2VydmVyMTM3MzJXb3JrYXJvdW5kYFxuICAgICAgICAgKiBmbGFnLCBjYW4gYmUgcmVtb3ZlZC5cbiAgICAgICAgICpcbiAgICAgICAgICogVGhpcyBibG9jayByZXN0cnVjdHVyZXMgcXVlcmllcyBpbiB3aGljaCAkb3IgaXMgbm90IHRoZSBzb2xlIHRvcFxuICAgICAgICAgKiBsZXZlbCBlbGVtZW50IGJ5IG1vdmluZyBhbGwgb3RoZXIgdG9wLWxldmVsIHByZWRpY2F0ZXMgaW5zaWRlIGV2ZXJ5XG4gICAgICAgICAqIHN1YmRvY3VtZW50IG9mIHRoZSAkb3IgcHJlZGljYXRlLCBhbGxvd2luZyBNb25nb0RCJ3MgcXVlcnkgcGxhbm5lclxuICAgICAgICAgKiB0byBtYWtlIGZ1bGwgdXNlIG9mIHRoZSBtb3N0IHJlbGV2YW50IGluZGV4ZXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEVHOiAgICAgIHskb3I6IFt7YTogMX0sIHthOiAyfV0sIGI6IDJ9XG4gICAgICAgICAqIEJlY29tZXM6IHskb3I6IFt7YTogMSwgYjogMn0sIHthOiAyLCBiOiAyfV19XG4gICAgICAgICAqXG4gICAgICAgICAqIFRoZSBvbmx5IGV4Y2VwdGlvbnMgYXJlICRuZWFyIGFuZCAkbmVhclNwaGVyZSBvcGVyYXRvcnMsIHdoaWNoIGFyZVxuICAgICAgICAgKiBjb25zdHJhaW5lZCB0byBvbmx5IDEgb3BlcmF0b3IgcGVyIHF1ZXJ5LiBBcyBhIHJlc3VsdCwgdGhlc2Ugb3BzXG4gICAgICAgICAqIHJlbWFpbiBhdCB0aGUgdG9wIGxldmVsXG4gICAgICAgICAqXG4gICAgICAgICAqIGh0dHBzOi8vamlyYS5tb25nb2RiLm9yZy9icm93c2UvU0VSVkVSLTEzNzMyXG4gICAgICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9wYXJzZS1jb21tdW5pdHkvcGFyc2Utc2VydmVyL2lzc3Vlcy8zNzY3XG4gICAgICAgICAqL1xuICAgICAgICBPYmplY3Qua2V5cyhxdWVyeSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgIGNvbnN0IG5vQ29sbGlzaW9ucyA9ICFxdWVyeS4kb3Iuc29tZShzdWJxID0+XG4gICAgICAgICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc3VicSwga2V5KVxuICAgICAgICAgICk7XG4gICAgICAgICAgbGV0IGhhc05lYXJzID0gZmFsc2U7XG4gICAgICAgICAgaWYgKHF1ZXJ5W2tleV0gIT0gbnVsbCAmJiB0eXBlb2YgcXVlcnlba2V5XSA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgaGFzTmVhcnMgPSAnJG5lYXInIGluIHF1ZXJ5W2tleV0gfHwgJyRuZWFyU3BoZXJlJyBpbiBxdWVyeVtrZXldO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoa2V5ICE9ICckb3InICYmIG5vQ29sbGlzaW9ucyAmJiAhaGFzTmVhcnMpIHtcbiAgICAgICAgICAgIHF1ZXJ5LiRvci5mb3JFYWNoKHN1YnF1ZXJ5ID0+IHtcbiAgICAgICAgICAgICAgc3VicXVlcnlba2V5XSA9IHF1ZXJ5W2tleV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSBxdWVyeVtrZXldO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHF1ZXJ5LiRvci5mb3JFYWNoKGVsID0+XG4gICAgICAgICAgdmFsaWRhdGVRdWVyeShlbCwgc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgJ0JhZCAkb3IgZm9ybWF0IC0gdXNlIGFuIGFycmF5IHZhbHVlLidcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHF1ZXJ5LiRhbmQpIHtcbiAgICBpZiAocXVlcnkuJGFuZCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBxdWVyeS4kYW5kLmZvckVhY2goZWwgPT5cbiAgICAgICAgdmFsaWRhdGVRdWVyeShlbCwgc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQpXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICdCYWQgJGFuZCBmb3JtYXQgLSB1c2UgYW4gYXJyYXkgdmFsdWUuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAocXVlcnkuJG5vcikge1xuICAgIGlmIChxdWVyeS4kbm9yIGluc3RhbmNlb2YgQXJyYXkgJiYgcXVlcnkuJG5vci5sZW5ndGggPiAwKSB7XG4gICAgICBxdWVyeS4kbm9yLmZvckVhY2goZWwgPT5cbiAgICAgICAgdmFsaWRhdGVRdWVyeShlbCwgc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQpXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICdCYWQgJG5vciBmb3JtYXQgLSB1c2UgYW4gYXJyYXkgb2YgYXQgbGVhc3QgMSB2YWx1ZS4nXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIE9iamVjdC5rZXlzKHF1ZXJ5KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgaWYgKHF1ZXJ5ICYmIHF1ZXJ5W2tleV0gJiYgcXVlcnlba2V5XS4kcmVnZXgpIHtcbiAgICAgIGlmICh0eXBlb2YgcXVlcnlba2V5XS4kb3B0aW9ucyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKCFxdWVyeVtrZXldLiRvcHRpb25zLm1hdGNoKC9eW2lteHNdKyQvKSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgICBgQmFkICRvcHRpb25zIHZhbHVlIGZvciBxdWVyeTogJHtxdWVyeVtrZXldLiRvcHRpb25zfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmICghaXNTcGVjaWFsUXVlcnlLZXkoa2V5KSAmJiAha2V5Lm1hdGNoKC9eW2EtekEtWl1bYS16QS1aMC05X1xcLl0qJC8pKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsXG4gICAgICAgIGBJbnZhbGlkIGtleSBuYW1lOiAke2tleX1gXG4gICAgICApO1xuICAgIH1cbiAgfSk7XG59O1xuXG4vLyBGaWx0ZXJzIG91dCBhbnkgZGF0YSB0aGF0IHNob3VsZG4ndCBiZSBvbiB0aGlzIFJFU1QtZm9ybWF0dGVkIG9iamVjdC5cbmNvbnN0IGZpbHRlclNlbnNpdGl2ZURhdGEgPSAoXG4gIGlzTWFzdGVyOiBib29sZWFuLFxuICBhY2xHcm91cDogYW55W10sXG4gIGF1dGg6IGFueSxcbiAgb3BlcmF0aW9uOiBhbnksXG4gIHNjaGVtYTogU2NoZW1hQ29udHJvbGxlci5TY2hlbWFDb250cm9sbGVyLFxuICBjbGFzc05hbWU6IHN0cmluZyxcbiAgcHJvdGVjdGVkRmllbGRzOiBudWxsIHwgQXJyYXk8YW55PixcbiAgb2JqZWN0OiBhbnlcbikgPT4ge1xuICBsZXQgdXNlcklkID0gbnVsbDtcbiAgaWYgKGF1dGggJiYgYXV0aC51c2VyKSB1c2VySWQgPSBhdXRoLnVzZXIuaWQ7XG5cbiAgLy8gcmVwbGFjZSBwcm90ZWN0ZWRGaWVsZHMgd2hlbiB1c2luZyBwb2ludGVyLXBlcm1pc3Npb25zXG4gIGNvbnN0IHBlcm1zID0gc2NoZW1hLmdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWUpO1xuICBpZiAocGVybXMpIHtcbiAgICBjb25zdCBpc1JlYWRPcGVyYXRpb24gPSBbJ2dldCcsICdmaW5kJ10uaW5kZXhPZihvcGVyYXRpb24pID4gLTE7XG5cbiAgICBpZiAoaXNSZWFkT3BlcmF0aW9uICYmIHBlcm1zLnByb3RlY3RlZEZpZWxkcykge1xuICAgICAgLy8gZXh0cmFjdCBwcm90ZWN0ZWRGaWVsZHMgYWRkZWQgd2l0aCB0aGUgcG9pbnRlci1wZXJtaXNzaW9uIHByZWZpeFxuICAgICAgY29uc3QgcHJvdGVjdGVkRmllbGRzUG9pbnRlclBlcm0gPSBPYmplY3Qua2V5cyhwZXJtcy5wcm90ZWN0ZWRGaWVsZHMpXG4gICAgICAgIC5maWx0ZXIoa2V5ID0+IGtleS5zdGFydHNXaXRoKCd1c2VyRmllbGQ6JykpXG4gICAgICAgIC5tYXAoa2V5ID0+IHtcbiAgICAgICAgICByZXR1cm4geyBrZXk6IGtleS5zdWJzdHJpbmcoMTApLCB2YWx1ZTogcGVybXMucHJvdGVjdGVkRmllbGRzW2tleV0gfTtcbiAgICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IG5ld1Byb3RlY3RlZEZpZWxkczogQXJyYXk8c3RyaW5nPiA9IFtdO1xuICAgICAgbGV0IG92ZXJyaWRlUHJvdGVjdGVkRmllbGRzID0gZmFsc2U7XG5cbiAgICAgIC8vIGNoZWNrIGlmIHRoZSBvYmplY3QgZ3JhbnRzIHRoZSBjdXJyZW50IHVzZXIgYWNjZXNzIGJhc2VkIG9uIHRoZSBleHRyYWN0ZWQgZmllbGRzXG4gICAgICBwcm90ZWN0ZWRGaWVsZHNQb2ludGVyUGVybS5mb3JFYWNoKHBvaW50ZXJQZXJtID0+IHtcbiAgICAgICAgbGV0IHBvaW50ZXJQZXJtSW5jbHVkZXNVc2VyID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IHJlYWRVc2VyRmllbGRWYWx1ZSA9IG9iamVjdFtwb2ludGVyUGVybS5rZXldO1xuICAgICAgICBpZiAocmVhZFVzZXJGaWVsZFZhbHVlKSB7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVhZFVzZXJGaWVsZFZhbHVlKSkge1xuICAgICAgICAgICAgcG9pbnRlclBlcm1JbmNsdWRlc1VzZXIgPSByZWFkVXNlckZpZWxkVmFsdWUuc29tZShcbiAgICAgICAgICAgICAgdXNlciA9PiB1c2VyLm9iamVjdElkICYmIHVzZXIub2JqZWN0SWQgPT09IHVzZXJJZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9pbnRlclBlcm1JbmNsdWRlc1VzZXIgPVxuICAgICAgICAgICAgICByZWFkVXNlckZpZWxkVmFsdWUub2JqZWN0SWQgJiZcbiAgICAgICAgICAgICAgcmVhZFVzZXJGaWVsZFZhbHVlLm9iamVjdElkID09PSB1c2VySWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvaW50ZXJQZXJtSW5jbHVkZXNVc2VyKSB7XG4gICAgICAgICAgb3ZlcnJpZGVQcm90ZWN0ZWRGaWVsZHMgPSB0cnVlO1xuICAgICAgICAgIG5ld1Byb3RlY3RlZEZpZWxkcy5wdXNoKC4uLnBvaW50ZXJQZXJtLnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIGlmIGF0bGVhc3Qgb25lIHBvaW50ZXItcGVybWlzc2lvbiBhZmZlY3RlZCB0aGUgY3VycmVudCB1c2VyIG92ZXJyaWRlIHRoZSBwcm90ZWN0ZWRGaWVsZHNcbiAgICAgIGlmIChvdmVycmlkZVByb3RlY3RlZEZpZWxkcykgcHJvdGVjdGVkRmllbGRzID0gbmV3UHJvdGVjdGVkRmllbGRzO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGlzVXNlckNsYXNzID0gY2xhc3NOYW1lID09PSAnX1VzZXInO1xuXG4gIC8qIHNwZWNpYWwgdHJlYXQgZm9yIHRoZSB1c2VyIGNsYXNzOiBkb24ndCBmaWx0ZXIgcHJvdGVjdGVkRmllbGRzIGlmIGN1cnJlbnRseSBsb2dnZWRpbiB1c2VyIGlzXG4gIHRoZSByZXRyaWV2ZWQgdXNlciAqL1xuICBpZiAoIShpc1VzZXJDbGFzcyAmJiB1c2VySWQgJiYgb2JqZWN0Lm9iamVjdElkID09PSB1c2VySWQpKVxuICAgIHByb3RlY3RlZEZpZWxkcyAmJiBwcm90ZWN0ZWRGaWVsZHMuZm9yRWFjaChrID0+IGRlbGV0ZSBvYmplY3Rba10pO1xuXG4gIGlmICghaXNVc2VyQ2xhc3MpIHtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG5cbiAgb2JqZWN0LnBhc3N3b3JkID0gb2JqZWN0Ll9oYXNoZWRfcGFzc3dvcmQ7XG4gIGRlbGV0ZSBvYmplY3QuX2hhc2hlZF9wYXNzd29yZDtcblxuICBkZWxldGUgb2JqZWN0LnNlc3Npb25Ub2tlbjtcblxuICBpZiAoaXNNYXN0ZXIpIHtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG4gIGRlbGV0ZSBvYmplY3QuX2VtYWlsX3ZlcmlmeV90b2tlbjtcbiAgZGVsZXRlIG9iamVjdC5fcGVyaXNoYWJsZV90b2tlbjtcbiAgZGVsZXRlIG9iamVjdC5fcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0O1xuICBkZWxldGUgb2JqZWN0Ll90b21ic3RvbmU7XG4gIGRlbGV0ZSBvYmplY3QuX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0O1xuICBkZWxldGUgb2JqZWN0Ll9mYWlsZWRfbG9naW5fY291bnQ7XG4gIGRlbGV0ZSBvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0O1xuICBkZWxldGUgb2JqZWN0Ll9wYXNzd29yZF9jaGFuZ2VkX2F0O1xuICBkZWxldGUgb2JqZWN0Ll9wYXNzd29yZF9oaXN0b3J5O1xuXG4gIGlmIChhY2xHcm91cC5pbmRleE9mKG9iamVjdC5vYmplY3RJZCkgPiAtMSkge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgZGVsZXRlIG9iamVjdC5hdXRoRGF0YTtcbiAgcmV0dXJuIG9iamVjdDtcbn07XG5cbmltcG9ydCB0eXBlIHsgTG9hZFNjaGVtYU9wdGlvbnMgfSBmcm9tICcuL3R5cGVzJztcblxuLy8gUnVucyBhbiB1cGRhdGUgb24gdGhlIGRhdGFiYXNlLlxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGFuIG9iamVjdCB3aXRoIHRoZSBuZXcgdmFsdWVzIGZvciBmaWVsZFxuLy8gbW9kaWZpY2F0aW9ucyB0aGF0IGRvbid0IGtub3cgdGhlaXIgcmVzdWx0cyBhaGVhZCBvZiB0aW1lLCBsaWtlXG4vLyAnaW5jcmVtZW50Jy5cbi8vIE9wdGlvbnM6XG4vLyAgIGFjbDogIGEgbGlzdCBvZiBzdHJpbmdzLiBJZiB0aGUgb2JqZWN0IHRvIGJlIHVwZGF0ZWQgaGFzIGFuIEFDTCxcbi8vICAgICAgICAgb25lIG9mIHRoZSBwcm92aWRlZCBzdHJpbmdzIG11c3QgcHJvdmlkZSB0aGUgY2FsbGVyIHdpdGhcbi8vICAgICAgICAgd3JpdGUgcGVybWlzc2lvbnMuXG5jb25zdCBzcGVjaWFsS2V5c0ZvclVwZGF0ZSA9IFtcbiAgJ19oYXNoZWRfcGFzc3dvcmQnLFxuICAnX3BlcmlzaGFibGVfdG9rZW4nLFxuICAnX2VtYWlsX3ZlcmlmeV90b2tlbicsXG4gICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnLFxuICAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JyxcbiAgJ19mYWlsZWRfbG9naW5fY291bnQnLFxuICAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCcsXG4gICdfcGFzc3dvcmRfY2hhbmdlZF9hdCcsXG4gICdfcGFzc3dvcmRfaGlzdG9yeScsXG5dO1xuXG5jb25zdCBpc1NwZWNpYWxVcGRhdGVLZXkgPSBrZXkgPT4ge1xuICByZXR1cm4gc3BlY2lhbEtleXNGb3JVcGRhdGUuaW5kZXhPZihrZXkpID49IDA7XG59O1xuXG5mdW5jdGlvbiBleHBhbmRSZXN1bHRPbktleVBhdGgob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkuaW5kZXhPZignLicpIDwgMCkge1xuICAgIG9iamVjdFtrZXldID0gdmFsdWVba2V5XTtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG4gIGNvbnN0IHBhdGggPSBrZXkuc3BsaXQoJy4nKTtcbiAgY29uc3QgZmlyc3RLZXkgPSBwYXRoWzBdO1xuICBjb25zdCBuZXh0UGF0aCA9IHBhdGguc2xpY2UoMSkuam9pbignLicpO1xuICBvYmplY3RbZmlyc3RLZXldID0gZXhwYW5kUmVzdWx0T25LZXlQYXRoKFxuICAgIG9iamVjdFtmaXJzdEtleV0gfHwge30sXG4gICAgbmV4dFBhdGgsXG4gICAgdmFsdWVbZmlyc3RLZXldXG4gICk7XG4gIGRlbGV0ZSBvYmplY3Rba2V5XTtcbiAgcmV0dXJuIG9iamVjdDtcbn1cblxuZnVuY3Rpb24gc2FuaXRpemVEYXRhYmFzZVJlc3VsdChvcmlnaW5hbE9iamVjdCwgcmVzdWx0KTogUHJvbWlzZTxhbnk+IHtcbiAgY29uc3QgcmVzcG9uc2UgPSB7fTtcbiAgaWYgKCFyZXN1bHQpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3BvbnNlKTtcbiAgfVxuICBPYmplY3Qua2V5cyhvcmlnaW5hbE9iamVjdCkuZm9yRWFjaChrZXkgPT4ge1xuICAgIGNvbnN0IGtleVVwZGF0ZSA9IG9yaWdpbmFsT2JqZWN0W2tleV07XG4gICAgLy8gZGV0ZXJtaW5lIGlmIHRoYXQgd2FzIGFuIG9wXG4gICAgaWYgKFxuICAgICAga2V5VXBkYXRlICYmXG4gICAgICB0eXBlb2Yga2V5VXBkYXRlID09PSAnb2JqZWN0JyAmJlxuICAgICAga2V5VXBkYXRlLl9fb3AgJiZcbiAgICAgIFsnQWRkJywgJ0FkZFVuaXF1ZScsICdSZW1vdmUnLCAnSW5jcmVtZW50J10uaW5kZXhPZihrZXlVcGRhdGUuX19vcCkgPiAtMVxuICAgICkge1xuICAgICAgLy8gb25seSB2YWxpZCBvcHMgdGhhdCBwcm9kdWNlIGFuIGFjdGlvbmFibGUgcmVzdWx0XG4gICAgICAvLyB0aGUgb3AgbWF5IGhhdmUgaGFwcGVuZCBvbiBhIGtleXBhdGhcbiAgICAgIGV4cGFuZFJlc3VsdE9uS2V5UGF0aChyZXNwb25zZSwga2V5LCByZXN1bHQpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzcG9uc2UpO1xufVxuXG5mdW5jdGlvbiBqb2luVGFibGVOYW1lKGNsYXNzTmFtZSwga2V5KSB7XG4gIHJldHVybiBgX0pvaW46JHtrZXl9OiR7Y2xhc3NOYW1lfWA7XG59XG5cbmNvbnN0IGZsYXR0ZW5VcGRhdGVPcGVyYXRvcnNGb3JDcmVhdGUgPSBvYmplY3QgPT4ge1xuICBmb3IgKGNvbnN0IGtleSBpbiBvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0W2tleV0gJiYgb2JqZWN0W2tleV0uX19vcCkge1xuICAgICAgc3dpdGNoIChvYmplY3Rba2V5XS5fX29wKSB7XG4gICAgICAgIGNhc2UgJ0luY3JlbWVudCc6XG4gICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3Rba2V5XS5hbW91bnQgIT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJ29iamVjdHMgdG8gYWRkIG11c3QgYmUgYW4gYXJyYXknXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvYmplY3Rba2V5XSA9IG9iamVjdFtrZXldLmFtb3VudDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnQWRkJzpcbiAgICAgICAgICBpZiAoIShvYmplY3Rba2V5XS5vYmplY3RzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJ29iamVjdHMgdG8gYWRkIG11c3QgYmUgYW4gYXJyYXknXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvYmplY3Rba2V5XSA9IG9iamVjdFtrZXldLm9iamVjdHM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0FkZFVuaXF1ZSc6XG4gICAgICAgICAgaWYgKCEob2JqZWN0W2tleV0ub2JqZWN0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICdvYmplY3RzIHRvIGFkZCBtdXN0IGJlIGFuIGFycmF5J1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgb2JqZWN0W2tleV0gPSBvYmplY3Rba2V5XS5vYmplY3RzO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdSZW1vdmUnOlxuICAgICAgICAgIGlmICghKG9iamVjdFtrZXldLm9iamVjdHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAnb2JqZWN0cyB0byBhZGQgbXVzdCBiZSBhbiBhcnJheSdcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG9iamVjdFtrZXldID0gW107XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0RlbGV0ZSc6XG4gICAgICAgICAgZGVsZXRlIG9iamVjdFtrZXldO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLkNPTU1BTkRfVU5BVkFJTEFCTEUsXG4gICAgICAgICAgICBgVGhlICR7b2JqZWN0W2tleV0uX19vcH0gb3BlcmF0b3IgaXMgbm90IHN1cHBvcnRlZCB5ZXQuYFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1BdXRoRGF0YSA9IChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKSA9PiB7XG4gIGlmIChvYmplY3QuYXV0aERhdGEgJiYgY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgT2JqZWN0LmtleXMob2JqZWN0LmF1dGhEYXRhKS5mb3JFYWNoKHByb3ZpZGVyID0+IHtcbiAgICAgIGNvbnN0IHByb3ZpZGVyRGF0YSA9IG9iamVjdC5hdXRoRGF0YVtwcm92aWRlcl07XG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSBgX2F1dGhfZGF0YV8ke3Byb3ZpZGVyfWA7XG4gICAgICBpZiAocHJvdmlkZXJEYXRhID09IG51bGwpIHtcbiAgICAgICAgb2JqZWN0W2ZpZWxkTmFtZV0gPSB7XG4gICAgICAgICAgX19vcDogJ0RlbGV0ZScsXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHByb3ZpZGVyRGF0YTtcbiAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdID0geyB0eXBlOiAnT2JqZWN0JyB9O1xuICAgICAgfVxuICAgIH0pO1xuICAgIGRlbGV0ZSBvYmplY3QuYXV0aERhdGE7XG4gIH1cbn07XG4vLyBUcmFuc2Zvcm1zIGEgRGF0YWJhc2UgZm9ybWF0IEFDTCB0byBhIFJFU1QgQVBJIGZvcm1hdCBBQ0xcbmNvbnN0IHVudHJhbnNmb3JtT2JqZWN0QUNMID0gKHsgX3JwZXJtLCBfd3Blcm0sIC4uLm91dHB1dCB9KSA9PiB7XG4gIGlmIChfcnBlcm0gfHwgX3dwZXJtKSB7XG4gICAgb3V0cHV0LkFDTCA9IHt9O1xuXG4gICAgKF9ycGVybSB8fCBbXSkuZm9yRWFjaChlbnRyeSA9PiB7XG4gICAgICBpZiAoIW91dHB1dC5BQ0xbZW50cnldKSB7XG4gICAgICAgIG91dHB1dC5BQ0xbZW50cnldID0geyByZWFkOiB0cnVlIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvdXRwdXQuQUNMW2VudHJ5XVsncmVhZCddID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIChfd3Blcm0gfHwgW10pLmZvckVhY2goZW50cnkgPT4ge1xuICAgICAgaWYgKCFvdXRwdXQuQUNMW2VudHJ5XSkge1xuICAgICAgICBvdXRwdXQuQUNMW2VudHJ5XSA9IHsgd3JpdGU6IHRydWUgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dC5BQ0xbZW50cnldWyd3cml0ZSddID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gb3V0cHV0O1xufTtcblxuLyoqXG4gKiBXaGVuIHF1ZXJ5aW5nLCB0aGUgZmllbGROYW1lIG1heSBiZSBjb21wb3VuZCwgZXh0cmFjdCB0aGUgcm9vdCBmaWVsZE5hbWVcbiAqICAgICBgdGVtcGVyYXR1cmUuY2Vsc2l1c2AgYmVjb21lcyBgdGVtcGVyYXR1cmVgXG4gKiBAcGFyYW0ge3N0cmluZ30gZmllbGROYW1lIHRoYXQgbWF5IGJlIGEgY29tcG91bmQgZmllbGQgbmFtZVxuICogQHJldHVybnMge3N0cmluZ30gdGhlIHJvb3QgbmFtZSBvZiB0aGUgZmllbGRcbiAqL1xuY29uc3QgZ2V0Um9vdEZpZWxkTmFtZSA9IChmaWVsZE5hbWU6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gIHJldHVybiBmaWVsZE5hbWUuc3BsaXQoJy4nKVswXTtcbn07XG5cbmNvbnN0IHJlbGF0aW9uU2NoZW1hID0ge1xuICBmaWVsZHM6IHsgcmVsYXRlZElkOiB7IHR5cGU6ICdTdHJpbmcnIH0sIG93bmluZ0lkOiB7IHR5cGU6ICdTdHJpbmcnIH0gfSxcbn07XG5cbmNsYXNzIERhdGFiYXNlQ29udHJvbGxlciB7XG4gIGFkYXB0ZXI6IFN0b3JhZ2VBZGFwdGVyO1xuICBzY2hlbWFDYWNoZTogYW55O1xuICBzY2hlbWFQcm9taXNlOiA/UHJvbWlzZTxTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXI+O1xuICBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZDogYm9vbGVhbjtcbiAgX3RyYW5zYWN0aW9uYWxTZXNzaW9uOiA/YW55O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGFkYXB0ZXI6IFN0b3JhZ2VBZGFwdGVyLFxuICAgIHNjaGVtYUNhY2hlOiBhbnksXG4gICAgc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQ6IGJvb2xlYW5cbiAgKSB7XG4gICAgdGhpcy5hZGFwdGVyID0gYWRhcHRlcjtcbiAgICB0aGlzLnNjaGVtYUNhY2hlID0gc2NoZW1hQ2FjaGU7XG4gICAgLy8gV2UgZG9uJ3Qgd2FudCBhIG11dGFibGUgdGhpcy5zY2hlbWEsIGJlY2F1c2UgdGhlbiB5b3UgY291bGQgaGF2ZVxuICAgIC8vIG9uZSByZXF1ZXN0IHRoYXQgdXNlcyBkaWZmZXJlbnQgc2NoZW1hcyBmb3IgZGlmZmVyZW50IHBhcnRzIG9mXG4gICAgLy8gaXQuIEluc3RlYWQsIHVzZSBsb2FkU2NoZW1hIHRvIGdldCBhIHNjaGVtYS5cbiAgICB0aGlzLnNjaGVtYVByb21pc2UgPSBudWxsO1xuICAgIHRoaXMuc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQgPSBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZDtcbiAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvbiA9IG51bGw7XG4gIH1cblxuICBjb2xsZWN0aW9uRXhpc3RzKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5jbGFzc0V4aXN0cyhjbGFzc05hbWUpO1xuICB9XG5cbiAgcHVyZ2VDb2xsZWN0aW9uKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYSgpXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSkpXG4gICAgICAudGhlbihzY2hlbWEgPT4gdGhpcy5hZGFwdGVyLmRlbGV0ZU9iamVjdHNCeVF1ZXJ5KGNsYXNzTmFtZSwgc2NoZW1hLCB7fSkpO1xuICB9XG5cbiAgdmFsaWRhdGVDbGFzc05hbWUoY2xhc3NOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIVNjaGVtYUNvbnRyb2xsZXIuY2xhc3NOYW1lSXNWYWxpZChjbGFzc05hbWUpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICAgICAgJ2ludmFsaWQgY2xhc3NOYW1lOiAnICsgY2xhc3NOYW1lXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHNjaGVtYUNvbnRyb2xsZXIuXG4gIGxvYWRTY2hlbWEoXG4gICAgb3B0aW9uczogTG9hZFNjaGVtYU9wdGlvbnMgPSB7IGNsZWFyQ2FjaGU6IGZhbHNlIH1cbiAgKTogUHJvbWlzZTxTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXI+IHtcbiAgICBpZiAodGhpcy5zY2hlbWFQcm9taXNlICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0aGlzLnNjaGVtYVByb21pc2U7XG4gICAgfVxuICAgIHRoaXMuc2NoZW1hUHJvbWlzZSA9IFNjaGVtYUNvbnRyb2xsZXIubG9hZChcbiAgICAgIHRoaXMuYWRhcHRlcixcbiAgICAgIHRoaXMuc2NoZW1hQ2FjaGUsXG4gICAgICBvcHRpb25zXG4gICAgKTtcbiAgICB0aGlzLnNjaGVtYVByb21pc2UudGhlbihcbiAgICAgICgpID0+IGRlbGV0ZSB0aGlzLnNjaGVtYVByb21pc2UsXG4gICAgICAoKSA9PiBkZWxldGUgdGhpcy5zY2hlbWFQcm9taXNlXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hKG9wdGlvbnMpO1xuICB9XG5cbiAgbG9hZFNjaGVtYUlmTmVlZGVkKFxuICAgIHNjaGVtYUNvbnRyb2xsZXI6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcixcbiAgICBvcHRpb25zOiBMb2FkU2NoZW1hT3B0aW9ucyA9IHsgY2xlYXJDYWNoZTogZmFsc2UgfVxuICApOiBQcm9taXNlPFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcj4ge1xuICAgIHJldHVybiBzY2hlbWFDb250cm9sbGVyXG4gICAgICA/IFByb21pc2UucmVzb2x2ZShzY2hlbWFDb250cm9sbGVyKVxuICAgICAgOiB0aGlzLmxvYWRTY2hlbWEob3B0aW9ucyk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgdGhlIGNsYXNzbmFtZSB0aGF0IGlzIHJlbGF0ZWQgdG8gdGhlIGdpdmVuXG4gIC8vIGNsYXNzbmFtZSB0aHJvdWdoIHRoZSBrZXkuXG4gIC8vIFRPRE86IG1ha2UgdGhpcyBub3QgaW4gdGhlIERhdGFiYXNlQ29udHJvbGxlciBpbnRlcmZhY2VcbiAgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXkoY2xhc3NOYW1lOiBzdHJpbmcsIGtleTogc3RyaW5nKTogUHJvbWlzZTw/c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYSgpLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgIHZhciB0ID0gc2NoZW1hLmdldEV4cGVjdGVkVHlwZShjbGFzc05hbWUsIGtleSk7XG4gICAgICBpZiAodCAhPSBudWxsICYmIHR5cGVvZiB0ICE9PSAnc3RyaW5nJyAmJiB0LnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIHQudGFyZ2V0Q2xhc3M7XG4gICAgICB9XG4gICAgICByZXR1cm4gY2xhc3NOYW1lO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gVXNlcyB0aGUgc2NoZW1hIHRvIHZhbGlkYXRlIHRoZSBvYmplY3QgKFJFU1QgQVBJIGZvcm1hdCkuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG5ldyBzY2hlbWEuXG4gIC8vIFRoaXMgZG9lcyBub3QgdXBkYXRlIHRoaXMuc2NoZW1hLCBiZWNhdXNlIGluIGEgc2l0dWF0aW9uIGxpa2UgYVxuICAvLyBiYXRjaCByZXF1ZXN0LCB0aGF0IGNvdWxkIGNvbmZ1c2Ugb3RoZXIgdXNlcnMgb2YgdGhlIHNjaGVtYS5cbiAgdmFsaWRhdGVPYmplY3QoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBhbnksXG4gICAgcXVlcnk6IGFueSxcbiAgICB7IGFjbCB9OiBRdWVyeU9wdGlvbnNcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgbGV0IHNjaGVtYTtcbiAgICBjb25zdCBpc01hc3RlciA9IGFjbCA9PT0gdW5kZWZpbmVkO1xuICAgIHZhciBhY2xHcm91cDogc3RyaW5nW10gPSBhY2wgfHwgW107XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYSgpXG4gICAgICAudGhlbihzID0+IHtcbiAgICAgICAgc2NoZW1hID0gcztcbiAgICAgICAgaWYgKGlzTWFzdGVyKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNhbkFkZEZpZWxkKHNjaGVtYSwgY2xhc3NOYW1lLCBvYmplY3QsIGFjbEdyb3VwKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiBzY2hlbWEudmFsaWRhdGVPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHF1ZXJ5KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5OiBhbnksXG4gICAgdXBkYXRlOiBhbnksXG4gICAgeyBhY2wsIG1hbnksIHVwc2VydCB9OiBGdWxsUXVlcnlPcHRpb25zID0ge30sXG4gICAgc2tpcFNhbml0aXphdGlvbjogYm9vbGVhbiA9IGZhbHNlLFxuICAgIHZhbGlkYXRlT25seTogYm9vbGVhbiA9IGZhbHNlLFxuICAgIHZhbGlkU2NoZW1hQ29udHJvbGxlcjogU2NoZW1hQ29udHJvbGxlci5TY2hlbWFDb250cm9sbGVyXG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3Qgb3JpZ2luYWxRdWVyeSA9IHF1ZXJ5O1xuICAgIGNvbnN0IG9yaWdpbmFsVXBkYXRlID0gdXBkYXRlO1xuICAgIC8vIE1ha2UgYSBjb3B5IG9mIHRoZSBvYmplY3QsIHNvIHdlIGRvbid0IG11dGF0ZSB0aGUgaW5jb21pbmcgZGF0YS5cbiAgICB1cGRhdGUgPSBkZWVwY29weSh1cGRhdGUpO1xuICAgIHZhciByZWxhdGlvblVwZGF0ZXMgPSBbXTtcbiAgICB2YXIgaXNNYXN0ZXIgPSBhY2wgPT09IHVuZGVmaW5lZDtcbiAgICB2YXIgYWNsR3JvdXAgPSBhY2wgfHwgW107XG5cbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hSWZOZWVkZWQodmFsaWRTY2hlbWFDb250cm9sbGVyKS50aGVuKFxuICAgICAgc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgICAgIHJldHVybiAoaXNNYXN0ZXJcbiAgICAgICAgICA/IFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgOiBzY2hlbWFDb250cm9sbGVyLnZhbGlkYXRlUGVybWlzc2lvbihjbGFzc05hbWUsIGFjbEdyb3VwLCAndXBkYXRlJylcbiAgICAgICAgKVxuICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHJlbGF0aW9uVXBkYXRlcyA9IHRoaXMuY29sbGVjdFJlbGF0aW9uVXBkYXRlcyhcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICBvcmlnaW5hbFF1ZXJ5Lm9iamVjdElkLFxuICAgICAgICAgICAgICB1cGRhdGVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoIWlzTWFzdGVyKSB7XG4gICAgICAgICAgICAgIHF1ZXJ5ID0gdGhpcy5hZGRQb2ludGVyUGVybWlzc2lvbnMoXG4gICAgICAgICAgICAgICAgc2NoZW1hQ29udHJvbGxlcixcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgJ3VwZGF0ZScsXG4gICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgYWNsR3JvdXBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghcXVlcnkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFjbCkge1xuICAgICAgICAgICAgICBxdWVyeSA9IGFkZFdyaXRlQUNMKHF1ZXJ5LCBhY2wpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsaWRhdGVRdWVyeShxdWVyeSwgdGhpcy5za2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZCk7XG4gICAgICAgICAgICByZXR1cm4gc2NoZW1hQ29udHJvbGxlclxuICAgICAgICAgICAgICAuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSwgdHJ1ZSlcbiAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgc2NoZW1hIGRvZXNuJ3QgZXhpc3QsIHByZXRlbmQgaXQgZXhpc3RzIHdpdGggbm8gZmllbGRzLiBUaGlzIGJlaGF2aW9yXG4gICAgICAgICAgICAgICAgLy8gd2lsbCBsaWtlbHkgbmVlZCByZXZpc2l0aW5nLlxuICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4geyBmaWVsZHM6IHt9IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKHVwZGF0ZSkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKGZpZWxkTmFtZS5tYXRjaCgvXmF1dGhEYXRhXFwuKFthLXpBLVowLTlfXSspXFwuaWQkLykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsXG4gICAgICAgICAgICAgICAgICAgICAgYEludmFsaWQgZmllbGQgbmFtZSBmb3IgdXBkYXRlOiAke2ZpZWxkTmFtZX1gXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBjb25zdCByb290RmllbGROYW1lID0gZ2V0Um9vdEZpZWxkTmFtZShmaWVsZE5hbWUpO1xuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAhU2NoZW1hQ29udHJvbGxlci5maWVsZE5hbWVJc1ZhbGlkKHJvb3RGaWVsZE5hbWUpICYmXG4gICAgICAgICAgICAgICAgICAgICFpc1NwZWNpYWxVcGRhdGVLZXkocm9vdEZpZWxkTmFtZSlcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICAgICAgICAgICAgICAgICBgSW52YWxpZCBmaWVsZCBuYW1lIGZvciB1cGRhdGU6ICR7ZmllbGROYW1lfWBcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHVwZGF0ZU9wZXJhdGlvbiBpbiB1cGRhdGUpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlW3VwZGF0ZU9wZXJhdGlvbl0gJiZcbiAgICAgICAgICAgICAgICAgICAgdHlwZW9mIHVwZGF0ZVt1cGRhdGVPcGVyYXRpb25dID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyh1cGRhdGVbdXBkYXRlT3BlcmF0aW9uXSkuc29tZShcbiAgICAgICAgICAgICAgICAgICAgICBpbm5lcktleSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgaW5uZXJLZXkuaW5jbHVkZXMoJyQnKSB8fCBpbm5lcktleS5pbmNsdWRlcygnLicpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9ORVNURURfS0VZLFxuICAgICAgICAgICAgICAgICAgICAgIFwiTmVzdGVkIGtleXMgc2hvdWxkIG5vdCBjb250YWluIHRoZSAnJCcgb3IgJy4nIGNoYXJhY3RlcnNcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB1cGRhdGUgPSB0cmFuc2Zvcm1PYmplY3RBQ0wodXBkYXRlKTtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1BdXRoRGF0YShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICAgICAgICAgICAgICBpZiAodmFsaWRhdGVPbmx5KSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyXG4gICAgICAgICAgICAgICAgICAgIC5maW5kKGNsYXNzTmFtZSwgc2NoZW1hLCBxdWVyeSwge30pXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZXN1bHQgfHwgIXJlc3VsdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQuJ1xuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1hbnkpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIudXBkYXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHVwc2VydCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci51cHNlcnRPbmVPYmplY3QoXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5maW5kT25lQW5kVXBkYXRlKFxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgICAgIHNjaGVtYSxcbiAgICAgICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKChyZXN1bHQ6IGFueSkgPT4ge1xuICAgICAgICAgICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQuJ1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHZhbGlkYXRlT25seSkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlUmVsYXRpb25VcGRhdGVzKFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIG9yaWdpbmFsUXVlcnkub2JqZWN0SWQsXG4gICAgICAgICAgICAgIHVwZGF0ZSxcbiAgICAgICAgICAgICAgcmVsYXRpb25VcGRhdGVzXG4gICAgICAgICAgICApLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgICAgaWYgKHNraXBTYW5pdGl6YXRpb24pIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNhbml0aXplRGF0YWJhc2VSZXN1bHQob3JpZ2luYWxVcGRhdGUsIHJlc3VsdCk7XG4gICAgICAgICAgfSk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIC8vIENvbGxlY3QgYWxsIHJlbGF0aW9uLXVwZGF0aW5nIG9wZXJhdGlvbnMgZnJvbSBhIFJFU1QtZm9ybWF0IHVwZGF0ZS5cbiAgLy8gUmV0dXJucyBhIGxpc3Qgb2YgYWxsIHJlbGF0aW9uIHVwZGF0ZXMgdG8gcGVyZm9ybVxuICAvLyBUaGlzIG11dGF0ZXMgdXBkYXRlLlxuICBjb2xsZWN0UmVsYXRpb25VcGRhdGVzKGNsYXNzTmFtZTogc3RyaW5nLCBvYmplY3RJZDogP3N0cmluZywgdXBkYXRlOiBhbnkpIHtcbiAgICB2YXIgb3BzID0gW107XG4gICAgdmFyIGRlbGV0ZU1lID0gW107XG4gICAgb2JqZWN0SWQgPSB1cGRhdGUub2JqZWN0SWQgfHwgb2JqZWN0SWQ7XG5cbiAgICB2YXIgcHJvY2VzcyA9IChvcCwga2V5KSA9PiB7XG4gICAgICBpZiAoIW9wKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChvcC5fX29wID09ICdBZGRSZWxhdGlvbicpIHtcbiAgICAgICAgb3BzLnB1c2goeyBrZXksIG9wIH0pO1xuICAgICAgICBkZWxldGVNZS5wdXNoKGtleSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcC5fX29wID09ICdSZW1vdmVSZWxhdGlvbicpIHtcbiAgICAgICAgb3BzLnB1c2goeyBrZXksIG9wIH0pO1xuICAgICAgICBkZWxldGVNZS5wdXNoKGtleSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcC5fX29wID09ICdCYXRjaCcpIHtcbiAgICAgICAgZm9yICh2YXIgeCBvZiBvcC5vcHMpIHtcbiAgICAgICAgICBwcm9jZXNzKHgsIGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9yIChjb25zdCBrZXkgaW4gdXBkYXRlKSB7XG4gICAgICBwcm9jZXNzKHVwZGF0ZVtrZXldLCBrZXkpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGtleSBvZiBkZWxldGVNZSkge1xuICAgICAgZGVsZXRlIHVwZGF0ZVtrZXldO1xuICAgIH1cbiAgICByZXR1cm4gb3BzO1xuICB9XG5cbiAgLy8gUHJvY2Vzc2VzIHJlbGF0aW9uLXVwZGF0aW5nIG9wZXJhdGlvbnMgZnJvbSBhIFJFU1QtZm9ybWF0IHVwZGF0ZS5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCB1cGRhdGVzIGhhdmUgYmVlbiBwZXJmb3JtZWRcbiAgaGFuZGxlUmVsYXRpb25VcGRhdGVzKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIG9iamVjdElkOiBzdHJpbmcsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgb3BzOiBhbnlcbiAgKSB7XG4gICAgdmFyIHBlbmRpbmcgPSBbXTtcbiAgICBvYmplY3RJZCA9IHVwZGF0ZS5vYmplY3RJZCB8fCBvYmplY3RJZDtcbiAgICBvcHMuZm9yRWFjaCgoeyBrZXksIG9wIH0pID0+IHtcbiAgICAgIGlmICghb3ApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKG9wLl9fb3AgPT0gJ0FkZFJlbGF0aW9uJykge1xuICAgICAgICBmb3IgKGNvbnN0IG9iamVjdCBvZiBvcC5vYmplY3RzKSB7XG4gICAgICAgICAgcGVuZGluZy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5hZGRSZWxhdGlvbihrZXksIGNsYXNzTmFtZSwgb2JqZWN0SWQsIG9iamVjdC5vYmplY3RJZClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChvcC5fX29wID09ICdSZW1vdmVSZWxhdGlvbicpIHtcbiAgICAgICAgZm9yIChjb25zdCBvYmplY3Qgb2Ygb3Aub2JqZWN0cykge1xuICAgICAgICAgIHBlbmRpbmcucHVzaChcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlUmVsYXRpb24oa2V5LCBjbGFzc05hbWUsIG9iamVjdElkLCBvYmplY3Qub2JqZWN0SWQpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHBlbmRpbmcpO1xuICB9XG5cbiAgLy8gQWRkcyBhIHJlbGF0aW9uLlxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSBpZmYgdGhlIGFkZCB3YXMgc3VjY2Vzc2Z1bC5cbiAgYWRkUmVsYXRpb24oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgZnJvbUNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGZyb21JZDogc3RyaW5nLFxuICAgIHRvSWQ6IHN0cmluZ1xuICApIHtcbiAgICBjb25zdCBkb2MgPSB7XG4gICAgICByZWxhdGVkSWQ6IHRvSWQsXG4gICAgICBvd25pbmdJZDogZnJvbUlkLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci51cHNlcnRPbmVPYmplY3QoXG4gICAgICBgX0pvaW46JHtrZXl9OiR7ZnJvbUNsYXNzTmFtZX1gLFxuICAgICAgcmVsYXRpb25TY2hlbWEsXG4gICAgICBkb2MsXG4gICAgICBkb2MsXG4gICAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICk7XG4gIH1cblxuICAvLyBSZW1vdmVzIGEgcmVsYXRpb24uXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgc3VjY2Vzc2Z1bGx5IGlmZiB0aGUgcmVtb3ZlIHdhc1xuICAvLyBzdWNjZXNzZnVsLlxuICByZW1vdmVSZWxhdGlvbihcbiAgICBrZXk6IHN0cmluZyxcbiAgICBmcm9tQ2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZnJvbUlkOiBzdHJpbmcsXG4gICAgdG9JZDogc3RyaW5nXG4gICkge1xuICAgIHZhciBkb2MgPSB7XG4gICAgICByZWxhdGVkSWQ6IHRvSWQsXG4gICAgICBvd25pbmdJZDogZnJvbUlkLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlclxuICAgICAgLmRlbGV0ZU9iamVjdHNCeVF1ZXJ5KFxuICAgICAgICBgX0pvaW46JHtrZXl9OiR7ZnJvbUNsYXNzTmFtZX1gLFxuICAgICAgICByZWxhdGlvblNjaGVtYSxcbiAgICAgICAgZG9jLFxuICAgICAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICAgKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgLy8gV2UgZG9uJ3QgY2FyZSBpZiB0aGV5IHRyeSB0byBkZWxldGUgYSBub24tZXhpc3RlbnQgcmVsYXRpb24uXG4gICAgICAgIGlmIChlcnJvci5jb2RlID09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFJlbW92ZXMgb2JqZWN0cyBtYXRjaGVzIHRoaXMgcXVlcnkgZnJvbSB0aGUgZGF0YWJhc2UuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgc3VjY2Vzc2Z1bGx5IGlmZiB0aGUgb2JqZWN0IHdhc1xuICAvLyBkZWxldGVkLlxuICAvLyBPcHRpb25zOlxuICAvLyAgIGFjbDogIGEgbGlzdCBvZiBzdHJpbmdzLiBJZiB0aGUgb2JqZWN0IHRvIGJlIHVwZGF0ZWQgaGFzIGFuIEFDTCxcbiAgLy8gICAgICAgICBvbmUgb2YgdGhlIHByb3ZpZGVkIHN0cmluZ3MgbXVzdCBwcm92aWRlIHRoZSBjYWxsZXIgd2l0aFxuICAvLyAgICAgICAgIHdyaXRlIHBlcm1pc3Npb25zLlxuICBkZXN0cm95KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5OiBhbnksXG4gICAgeyBhY2wgfTogUXVlcnlPcHRpb25zID0ge30sXG4gICAgdmFsaWRTY2hlbWFDb250cm9sbGVyOiBTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXJcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBpc01hc3RlciA9IGFjbCA9PT0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGFjbEdyb3VwID0gYWNsIHx8IFtdO1xuXG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYUlmTmVlZGVkKHZhbGlkU2NoZW1hQ29udHJvbGxlcikudGhlbihcbiAgICAgIHNjaGVtYUNvbnRyb2xsZXIgPT4ge1xuICAgICAgICByZXR1cm4gKGlzTWFzdGVyXG4gICAgICAgICAgPyBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgIDogc2NoZW1hQ29udHJvbGxlci52YWxpZGF0ZVBlcm1pc3Npb24oY2xhc3NOYW1lLCBhY2xHcm91cCwgJ2RlbGV0ZScpXG4gICAgICAgICkudGhlbigoKSA9PiB7XG4gICAgICAgICAgaWYgKCFpc01hc3Rlcikge1xuICAgICAgICAgICAgcXVlcnkgPSB0aGlzLmFkZFBvaW50ZXJQZXJtaXNzaW9ucyhcbiAgICAgICAgICAgICAgc2NoZW1hQ29udHJvbGxlcixcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAnZGVsZXRlJyxcbiAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgIGFjbEdyb3VwXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKCFxdWVyeSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGRlbGV0ZSBieSBxdWVyeVxuICAgICAgICAgIGlmIChhY2wpIHtcbiAgICAgICAgICAgIHF1ZXJ5ID0gYWRkV3JpdGVBQ0wocXVlcnksIGFjbCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhbGlkYXRlUXVlcnkocXVlcnksIHRoaXMuc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQpO1xuICAgICAgICAgIHJldHVybiBzY2hlbWFDb250cm9sbGVyXG4gICAgICAgICAgICAuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgIC8vIElmIHRoZSBzY2hlbWEgZG9lc24ndCBleGlzdCwgcHJldGVuZCBpdCBleGlzdHMgd2l0aCBubyBmaWVsZHMuIFRoaXMgYmVoYXZpb3JcbiAgICAgICAgICAgICAgLy8gd2lsbCBsaWtlbHkgbmVlZCByZXZpc2l0aW5nLlxuICAgICAgICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGZpZWxkczoge30gfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihwYXJzZUZvcm1hdFNjaGVtYSA9PlxuICAgICAgICAgICAgICB0aGlzLmFkYXB0ZXIuZGVsZXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgIHBhcnNlRm9ybWF0U2NoZW1hLFxuICAgICAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgIC8vIFdoZW4gZGVsZXRpbmcgc2Vzc2lvbnMgd2hpbGUgY2hhbmdpbmcgcGFzc3dvcmRzLCBkb24ndCB0aHJvdyBhbiBlcnJvciBpZiB0aGV5IGRvbid0IGhhdmUgYW55IHNlc3Npb25zLlxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lID09PSAnX1Nlc3Npb24nICYmXG4gICAgICAgICAgICAgICAgZXJyb3IuY29kZSA9PT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORFxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgLy8gSW5zZXJ0cyBhbiBvYmplY3QgaW50byB0aGUgZGF0YWJhc2UuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgc3VjY2Vzc2Z1bGx5IGlmZiB0aGUgb2JqZWN0IHNhdmVkLlxuICBjcmVhdGUoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBhbnksXG4gICAgeyBhY2wgfTogUXVlcnlPcHRpb25zID0ge30sXG4gICAgdmFsaWRhdGVPbmx5OiBib29sZWFuID0gZmFsc2UsXG4gICAgdmFsaWRTY2hlbWFDb250cm9sbGVyOiBTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXJcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICAvLyBNYWtlIGEgY29weSBvZiB0aGUgb2JqZWN0LCBzbyB3ZSBkb24ndCBtdXRhdGUgdGhlIGluY29taW5nIGRhdGEuXG4gICAgY29uc3Qgb3JpZ2luYWxPYmplY3QgPSBvYmplY3Q7XG4gICAgb2JqZWN0ID0gdHJhbnNmb3JtT2JqZWN0QUNMKG9iamVjdCk7XG5cbiAgICBvYmplY3QuY3JlYXRlZEF0ID0geyBpc286IG9iamVjdC5jcmVhdGVkQXQsIF9fdHlwZTogJ0RhdGUnIH07XG4gICAgb2JqZWN0LnVwZGF0ZWRBdCA9IHsgaXNvOiBvYmplY3QudXBkYXRlZEF0LCBfX3R5cGU6ICdEYXRlJyB9O1xuXG4gICAgdmFyIGlzTWFzdGVyID0gYWNsID09PSB1bmRlZmluZWQ7XG4gICAgdmFyIGFjbEdyb3VwID0gYWNsIHx8IFtdO1xuICAgIGNvbnN0IHJlbGF0aW9uVXBkYXRlcyA9IHRoaXMuY29sbGVjdFJlbGF0aW9uVXBkYXRlcyhcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIG51bGwsXG4gICAgICBvYmplY3RcbiAgICApO1xuXG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGVDbGFzc05hbWUoY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5sb2FkU2NoZW1hSWZOZWVkZWQodmFsaWRTY2hlbWFDb250cm9sbGVyKSlcbiAgICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4ge1xuICAgICAgICByZXR1cm4gKGlzTWFzdGVyXG4gICAgICAgICAgPyBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgIDogc2NoZW1hQ29udHJvbGxlci52YWxpZGF0ZVBlcm1pc3Npb24oY2xhc3NOYW1lLCBhY2xHcm91cCwgJ2NyZWF0ZScpXG4gICAgICAgIClcbiAgICAgICAgICAudGhlbigoKSA9PiBzY2hlbWFDb250cm9sbGVyLmVuZm9yY2VDbGFzc0V4aXN0cyhjbGFzc05hbWUpKVxuICAgICAgICAgIC50aGVuKCgpID0+IHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSwgdHJ1ZSkpXG4gICAgICAgICAgLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybUF1dGhEYXRhKGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpO1xuICAgICAgICAgICAgZmxhdHRlblVwZGF0ZU9wZXJhdG9yc0ZvckNyZWF0ZShvYmplY3QpO1xuICAgICAgICAgICAgaWYgKHZhbGlkYXRlT25seSkge1xuICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmNyZWF0ZU9iamVjdChcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICBTY2hlbWFDb250cm9sbGVyLmNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEoc2NoZW1hKSxcbiAgICAgICAgICAgICAgb2JqZWN0LFxuICAgICAgICAgICAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgICBpZiAodmFsaWRhdGVPbmx5KSB7XG4gICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbE9iamVjdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmhhbmRsZVJlbGF0aW9uVXBkYXRlcyhcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICBvYmplY3Qub2JqZWN0SWQsXG4gICAgICAgICAgICAgIG9iamVjdCxcbiAgICAgICAgICAgICAgcmVsYXRpb25VcGRhdGVzXG4gICAgICAgICAgICApLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gc2FuaXRpemVEYXRhYmFzZVJlc3VsdChvcmlnaW5hbE9iamVjdCwgcmVzdWx0Lm9wc1swXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgY2FuQWRkRmllbGQoXG4gICAgc2NoZW1hOiBTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXIsXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBhbnksXG4gICAgYWNsR3JvdXA6IHN0cmluZ1tdXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNsYXNzU2NoZW1hID0gc2NoZW1hLnNjaGVtYURhdGFbY2xhc3NOYW1lXTtcbiAgICBpZiAoIWNsYXNzU2NoZW1hKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIGNvbnN0IGZpZWxkcyA9IE9iamVjdC5rZXlzKG9iamVjdCk7XG4gICAgY29uc3Qgc2NoZW1hRmllbGRzID0gT2JqZWN0LmtleXMoY2xhc3NTY2hlbWEuZmllbGRzKTtcbiAgICBjb25zdCBuZXdLZXlzID0gZmllbGRzLmZpbHRlcihmaWVsZCA9PiB7XG4gICAgICAvLyBTa2lwIGZpZWxkcyB0aGF0IGFyZSB1bnNldFxuICAgICAgaWYgKFxuICAgICAgICBvYmplY3RbZmllbGRdICYmXG4gICAgICAgIG9iamVjdFtmaWVsZF0uX19vcCAmJlxuICAgICAgICBvYmplY3RbZmllbGRdLl9fb3AgPT09ICdEZWxldGUnXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNjaGVtYUZpZWxkcy5pbmRleE9mKGZpZWxkKSA8IDA7XG4gICAgfSk7XG4gICAgaWYgKG5ld0tleXMubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHNjaGVtYS52YWxpZGF0ZVBlcm1pc3Npb24oY2xhc3NOYW1lLCBhY2xHcm91cCwgJ2FkZEZpZWxkJyk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIFdvbid0IGRlbGV0ZSBjb2xsZWN0aW9ucyBpbiB0aGUgc3lzdGVtIG5hbWVzcGFjZVxuICAvKipcbiAgICogRGVsZXRlIGFsbCBjbGFzc2VzIGFuZCBjbGVhcnMgdGhlIHNjaGVtYSBjYWNoZVxuICAgKlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZhc3Qgc2V0IHRvIHRydWUgaWYgaXQncyBvayB0byBqdXN0IGRlbGV0ZSByb3dzIGFuZCBub3QgaW5kZXhlc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gd2hlbiB0aGUgZGVsZXRpb25zIGNvbXBsZXRlc1xuICAgKi9cbiAgZGVsZXRlRXZlcnl0aGluZyhmYXN0OiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPGFueT4ge1xuICAgIHRoaXMuc2NoZW1hUHJvbWlzZSA9IG51bGw7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFtcbiAgICAgIHRoaXMuYWRhcHRlci5kZWxldGVBbGxDbGFzc2VzKGZhc3QpLFxuICAgICAgdGhpcy5zY2hlbWFDYWNoZS5jbGVhcigpLFxuICAgIF0pO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEgbGlzdCBvZiByZWxhdGVkIGlkcyBnaXZlbiBhbiBvd25pbmcgaWQuXG4gIC8vIGNsYXNzTmFtZSBoZXJlIGlzIHRoZSBvd25pbmcgY2xhc3NOYW1lLlxuICByZWxhdGVkSWRzKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGtleTogc3RyaW5nLFxuICAgIG93bmluZ0lkOiBzdHJpbmcsXG4gICAgcXVlcnlPcHRpb25zOiBRdWVyeU9wdGlvbnNcbiAgKTogUHJvbWlzZTxBcnJheTxzdHJpbmc+PiB7XG4gICAgY29uc3QgeyBza2lwLCBsaW1pdCwgc29ydCB9ID0gcXVlcnlPcHRpb25zO1xuICAgIGNvbnN0IGZpbmRPcHRpb25zID0ge307XG4gICAgaWYgKHNvcnQgJiYgc29ydC5jcmVhdGVkQXQgJiYgdGhpcy5hZGFwdGVyLmNhblNvcnRPbkpvaW5UYWJsZXMpIHtcbiAgICAgIGZpbmRPcHRpb25zLnNvcnQgPSB7IF9pZDogc29ydC5jcmVhdGVkQXQgfTtcbiAgICAgIGZpbmRPcHRpb25zLmxpbWl0ID0gbGltaXQ7XG4gICAgICBmaW5kT3B0aW9ucy5za2lwID0gc2tpcDtcbiAgICAgIHF1ZXJ5T3B0aW9ucy5za2lwID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlclxuICAgICAgLmZpbmQoXG4gICAgICAgIGpvaW5UYWJsZU5hbWUoY2xhc3NOYW1lLCBrZXkpLFxuICAgICAgICByZWxhdGlvblNjaGVtYSxcbiAgICAgICAgeyBvd25pbmdJZCB9LFxuICAgICAgICBmaW5kT3B0aW9uc1xuICAgICAgKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiByZXN1bHRzLm1hcChyZXN1bHQgPT4gcmVzdWx0LnJlbGF0ZWRJZCkpO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEgbGlzdCBvZiBvd25pbmcgaWRzIGdpdmVuIHNvbWUgcmVsYXRlZCBpZHMuXG4gIC8vIGNsYXNzTmFtZSBoZXJlIGlzIHRoZSBvd25pbmcgY2xhc3NOYW1lLlxuICBvd25pbmdJZHMoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVsYXRlZElkczogc3RyaW5nW11cbiAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXJcbiAgICAgIC5maW5kKFxuICAgICAgICBqb2luVGFibGVOYW1lKGNsYXNzTmFtZSwga2V5KSxcbiAgICAgICAgcmVsYXRpb25TY2hlbWEsXG4gICAgICAgIHsgcmVsYXRlZElkOiB7ICRpbjogcmVsYXRlZElkcyB9IH0sXG4gICAgICAgIHt9XG4gICAgICApXG4gICAgICAudGhlbihyZXN1bHRzID0+IHJlc3VsdHMubWFwKHJlc3VsdCA9PiByZXN1bHQub3duaW5nSWQpKTtcbiAgfVxuXG4gIC8vIE1vZGlmaWVzIHF1ZXJ5IHNvIHRoYXQgaXQgbm8gbG9uZ2VyIGhhcyAkaW4gb24gcmVsYXRpb24gZmllbGRzLCBvclxuICAvLyBlcXVhbC10by1wb2ludGVyIGNvbnN0cmFpbnRzIG9uIHJlbGF0aW9uIGZpZWxkcy5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHF1ZXJ5IGlzIG11dGF0ZWRcbiAgcmVkdWNlSW5SZWxhdGlvbihjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IGFueSwgc2NoZW1hOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIFNlYXJjaCBmb3IgYW4gaW4tcmVsYXRpb24gb3IgZXF1YWwtdG8tcmVsYXRpb25cbiAgICAvLyBNYWtlIGl0IHNlcXVlbnRpYWwgZm9yIG5vdywgbm90IHN1cmUgb2YgcGFyYWxsZWl6YXRpb24gc2lkZSBlZmZlY3RzXG4gICAgaWYgKHF1ZXJ5Wyckb3InXSkge1xuICAgICAgY29uc3Qgb3JzID0gcXVlcnlbJyRvciddO1xuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgICBvcnMubWFwKChhUXVlcnksIGluZGV4KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucmVkdWNlSW5SZWxhdGlvbihjbGFzc05hbWUsIGFRdWVyeSwgc2NoZW1hKS50aGVuKFxuICAgICAgICAgICAgYVF1ZXJ5ID0+IHtcbiAgICAgICAgICAgICAgcXVlcnlbJyRvciddW2luZGV4XSA9IGFRdWVyeTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICAgKS50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShxdWVyeSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9taXNlcyA9IE9iamVjdC5rZXlzKHF1ZXJ5KS5tYXAoa2V5ID0+IHtcbiAgICAgIGNvbnN0IHQgPSBzY2hlbWEuZ2V0RXhwZWN0ZWRUeXBlKGNsYXNzTmFtZSwga2V5KTtcbiAgICAgIGlmICghdCB8fCB0LnR5cGUgIT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShxdWVyeSk7XG4gICAgICB9XG4gICAgICBsZXQgcXVlcmllczogPyhhbnlbXSkgPSBudWxsO1xuICAgICAgaWYgKFxuICAgICAgICBxdWVyeVtrZXldICYmXG4gICAgICAgIChxdWVyeVtrZXldWyckaW4nXSB8fFxuICAgICAgICAgIHF1ZXJ5W2tleV1bJyRuZSddIHx8XG4gICAgICAgICAgcXVlcnlba2V5XVsnJG5pbiddIHx8XG4gICAgICAgICAgcXVlcnlba2V5XS5fX3R5cGUgPT0gJ1BvaW50ZXInKVxuICAgICAgKSB7XG4gICAgICAgIC8vIEJ1aWxkIHRoZSBsaXN0IG9mIHF1ZXJpZXNcbiAgICAgICAgcXVlcmllcyA9IE9iamVjdC5rZXlzKHF1ZXJ5W2tleV0pLm1hcChjb25zdHJhaW50S2V5ID0+IHtcbiAgICAgICAgICBsZXQgcmVsYXRlZElkcztcbiAgICAgICAgICBsZXQgaXNOZWdhdGlvbiA9IGZhbHNlO1xuICAgICAgICAgIGlmIChjb25zdHJhaW50S2V5ID09PSAnb2JqZWN0SWQnKSB7XG4gICAgICAgICAgICByZWxhdGVkSWRzID0gW3F1ZXJ5W2tleV0ub2JqZWN0SWRdO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY29uc3RyYWludEtleSA9PSAnJGluJykge1xuICAgICAgICAgICAgcmVsYXRlZElkcyA9IHF1ZXJ5W2tleV1bJyRpbiddLm1hcChyID0+IHIub2JqZWN0SWQpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY29uc3RyYWludEtleSA9PSAnJG5pbicpIHtcbiAgICAgICAgICAgIGlzTmVnYXRpb24gPSB0cnVlO1xuICAgICAgICAgICAgcmVsYXRlZElkcyA9IHF1ZXJ5W2tleV1bJyRuaW4nXS5tYXAociA9PiByLm9iamVjdElkKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNvbnN0cmFpbnRLZXkgPT0gJyRuZScpIHtcbiAgICAgICAgICAgIGlzTmVnYXRpb24gPSB0cnVlO1xuICAgICAgICAgICAgcmVsYXRlZElkcyA9IFtxdWVyeVtrZXldWyckbmUnXS5vYmplY3RJZF07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlzTmVnYXRpb24sXG4gICAgICAgICAgICByZWxhdGVkSWRzLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcXVlcmllcyA9IFt7IGlzTmVnYXRpb246IGZhbHNlLCByZWxhdGVkSWRzOiBbXSB9XTtcbiAgICAgIH1cblxuICAgICAgLy8gcmVtb3ZlIHRoZSBjdXJyZW50IHF1ZXJ5S2V5IGFzIHdlIGRvbix0IG5lZWQgaXQgYW55bW9yZVxuICAgICAgZGVsZXRlIHF1ZXJ5W2tleV07XG4gICAgICAvLyBleGVjdXRlIGVhY2ggcXVlcnkgaW5kZXBlbmRlbnRseSB0byBidWlsZCB0aGUgbGlzdCBvZlxuICAgICAgLy8gJGluIC8gJG5pblxuICAgICAgY29uc3QgcHJvbWlzZXMgPSBxdWVyaWVzLm1hcChxID0+IHtcbiAgICAgICAgaWYgKCFxKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm93bmluZ0lkcyhjbGFzc05hbWUsIGtleSwgcS5yZWxhdGVkSWRzKS50aGVuKGlkcyA9PiB7XG4gICAgICAgICAgaWYgKHEuaXNOZWdhdGlvbikge1xuICAgICAgICAgICAgdGhpcy5hZGROb3RJbk9iamVjdElkc0lkcyhpZHMsIHF1ZXJ5KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hZGRJbk9iamVjdElkc0lkcyhpZHMsIHF1ZXJ5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHF1ZXJ5KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIE1vZGlmaWVzIHF1ZXJ5IHNvIHRoYXQgaXQgbm8gbG9uZ2VyIGhhcyAkcmVsYXRlZFRvXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBxdWVyeSBpcyBtdXRhdGVkXG4gIHJlZHVjZVJlbGF0aW9uS2V5cyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBxdWVyeTogYW55LFxuICAgIHF1ZXJ5T3B0aW9uczogYW55XG4gICk6ID9Qcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAocXVlcnlbJyRvciddKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICAgIHF1ZXJ5Wyckb3InXS5tYXAoYVF1ZXJ5ID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5yZWR1Y2VSZWxhdGlvbktleXMoY2xhc3NOYW1lLCBhUXVlcnksIHF1ZXJ5T3B0aW9ucyk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIHZhciByZWxhdGVkVG8gPSBxdWVyeVsnJHJlbGF0ZWRUbyddO1xuICAgIGlmIChyZWxhdGVkVG8pIHtcbiAgICAgIHJldHVybiB0aGlzLnJlbGF0ZWRJZHMoXG4gICAgICAgIHJlbGF0ZWRUby5vYmplY3QuY2xhc3NOYW1lLFxuICAgICAgICByZWxhdGVkVG8ua2V5LFxuICAgICAgICByZWxhdGVkVG8ub2JqZWN0Lm9iamVjdElkLFxuICAgICAgICBxdWVyeU9wdGlvbnNcbiAgICAgIClcbiAgICAgICAgLnRoZW4oaWRzID0+IHtcbiAgICAgICAgICBkZWxldGUgcXVlcnlbJyRyZWxhdGVkVG8nXTtcbiAgICAgICAgICB0aGlzLmFkZEluT2JqZWN0SWRzSWRzKGlkcywgcXVlcnkpO1xuICAgICAgICAgIHJldHVybiB0aGlzLnJlZHVjZVJlbGF0aW9uS2V5cyhjbGFzc05hbWUsIHF1ZXJ5LCBxdWVyeU9wdGlvbnMpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB7fSk7XG4gICAgfVxuICB9XG5cbiAgYWRkSW5PYmplY3RJZHNJZHMoaWRzOiA/QXJyYXk8c3RyaW5nPiA9IG51bGwsIHF1ZXJ5OiBhbnkpIHtcbiAgICBjb25zdCBpZHNGcm9tU3RyaW5nOiA/QXJyYXk8c3RyaW5nPiA9XG4gICAgICB0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT09ICdzdHJpbmcnID8gW3F1ZXJ5Lm9iamVjdElkXSA6IG51bGw7XG4gICAgY29uc3QgaWRzRnJvbUVxOiA/QXJyYXk8c3RyaW5nPiA9XG4gICAgICBxdWVyeS5vYmplY3RJZCAmJiBxdWVyeS5vYmplY3RJZFsnJGVxJ10gPyBbcXVlcnkub2JqZWN0SWRbJyRlcSddXSA6IG51bGw7XG4gICAgY29uc3QgaWRzRnJvbUluOiA/QXJyYXk8c3RyaW5nPiA9XG4gICAgICBxdWVyeS5vYmplY3RJZCAmJiBxdWVyeS5vYmplY3RJZFsnJGluJ10gPyBxdWVyeS5vYmplY3RJZFsnJGluJ10gOiBudWxsO1xuXG4gICAgLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG4gICAgY29uc3QgYWxsSWRzOiBBcnJheTxBcnJheTxzdHJpbmc+PiA9IFtcbiAgICAgIGlkc0Zyb21TdHJpbmcsXG4gICAgICBpZHNGcm9tRXEsXG4gICAgICBpZHNGcm9tSW4sXG4gICAgICBpZHMsXG4gICAgXS5maWx0ZXIobGlzdCA9PiBsaXN0ICE9PSBudWxsKTtcbiAgICBjb25zdCB0b3RhbExlbmd0aCA9IGFsbElkcy5yZWR1Y2UoKG1lbW8sIGxpc3QpID0+IG1lbW8gKyBsaXN0Lmxlbmd0aCwgMCk7XG5cbiAgICBsZXQgaWRzSW50ZXJzZWN0aW9uID0gW107XG4gICAgaWYgKHRvdGFsTGVuZ3RoID4gMTI1KSB7XG4gICAgICBpZHNJbnRlcnNlY3Rpb24gPSBpbnRlcnNlY3QuYmlnKGFsbElkcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlkc0ludGVyc2VjdGlvbiA9IGludGVyc2VjdChhbGxJZHMpO1xuICAgIH1cblxuICAgIC8vIE5lZWQgdG8gbWFrZSBzdXJlIHdlIGRvbid0IGNsb2JiZXIgZXhpc3Rpbmcgc2hvcnRoYW5kICRlcSBjb25zdHJhaW50cyBvbiBvYmplY3RJZC5cbiAgICBpZiAoISgnb2JqZWN0SWQnIGluIHF1ZXJ5KSkge1xuICAgICAgcXVlcnkub2JqZWN0SWQgPSB7XG4gICAgICAgICRpbjogdW5kZWZpbmVkLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBxdWVyeS5vYmplY3RJZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHF1ZXJ5Lm9iamVjdElkID0ge1xuICAgICAgICAkaW46IHVuZGVmaW5lZCxcbiAgICAgICAgJGVxOiBxdWVyeS5vYmplY3RJZCxcbiAgICAgIH07XG4gICAgfVxuICAgIHF1ZXJ5Lm9iamVjdElkWyckaW4nXSA9IGlkc0ludGVyc2VjdGlvbjtcblxuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIGFkZE5vdEluT2JqZWN0SWRzSWRzKGlkczogc3RyaW5nW10gPSBbXSwgcXVlcnk6IGFueSkge1xuICAgIGNvbnN0IGlkc0Zyb21OaW4gPVxuICAgICAgcXVlcnkub2JqZWN0SWQgJiYgcXVlcnkub2JqZWN0SWRbJyRuaW4nXSA/IHF1ZXJ5Lm9iamVjdElkWyckbmluJ10gOiBbXTtcbiAgICBsZXQgYWxsSWRzID0gWy4uLmlkc0Zyb21OaW4sIC4uLmlkc10uZmlsdGVyKGxpc3QgPT4gbGlzdCAhPT0gbnVsbCk7XG5cbiAgICAvLyBtYWtlIGEgc2V0IGFuZCBzcHJlYWQgdG8gcmVtb3ZlIGR1cGxpY2F0ZXNcbiAgICBhbGxJZHMgPSBbLi4ubmV3IFNldChhbGxJZHMpXTtcblxuICAgIC8vIE5lZWQgdG8gbWFrZSBzdXJlIHdlIGRvbid0IGNsb2JiZXIgZXhpc3Rpbmcgc2hvcnRoYW5kICRlcSBjb25zdHJhaW50cyBvbiBvYmplY3RJZC5cbiAgICBpZiAoISgnb2JqZWN0SWQnIGluIHF1ZXJ5KSkge1xuICAgICAgcXVlcnkub2JqZWN0SWQgPSB7XG4gICAgICAgICRuaW46IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBxdWVyeS5vYmplY3RJZCA9IHtcbiAgICAgICAgJG5pbjogdW5kZWZpbmVkLFxuICAgICAgICAkZXE6IHF1ZXJ5Lm9iamVjdElkLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBxdWVyeS5vYmplY3RJZFsnJG5pbiddID0gYWxsSWRzO1xuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIC8vIFJ1bnMgYSBxdWVyeSBvbiB0aGUgZGF0YWJhc2UuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBsaXN0IG9mIGl0ZW1zLlxuICAvLyBPcHRpb25zOlxuICAvLyAgIHNraXAgICAgbnVtYmVyIG9mIHJlc3VsdHMgdG8gc2tpcC5cbiAgLy8gICBsaW1pdCAgIGxpbWl0IHRvIHRoaXMgbnVtYmVyIG9mIHJlc3VsdHMuXG4gIC8vICAgc29ydCAgICBhbiBvYmplY3Qgd2hlcmUga2V5cyBhcmUgdGhlIGZpZWxkcyB0byBzb3J0IGJ5LlxuICAvLyAgICAgICAgICAgdGhlIHZhbHVlIGlzICsxIGZvciBhc2NlbmRpbmcsIC0xIGZvciBkZXNjZW5kaW5nLlxuICAvLyAgIGNvdW50ICAgcnVuIGEgY291bnQgaW5zdGVhZCBvZiByZXR1cm5pbmcgcmVzdWx0cy5cbiAgLy8gICBhY2wgICAgIHJlc3RyaWN0IHRoaXMgb3BlcmF0aW9uIHdpdGggYW4gQUNMIGZvciB0aGUgcHJvdmlkZWQgYXJyYXlcbiAgLy8gICAgICAgICAgIG9mIHVzZXIgb2JqZWN0SWRzIGFuZCByb2xlcy4gYWNsOiBudWxsIG1lYW5zIG5vIHVzZXIuXG4gIC8vICAgICAgICAgICB3aGVuIHRoaXMgZmllbGQgaXMgbm90IHByZXNlbnQsIGRvbid0IGRvIGFueXRoaW5nIHJlZ2FyZGluZyBBQ0xzLlxuICAvLyBUT0RPOiBtYWtlIHVzZXJJZHMgbm90IG5lZWRlZCBoZXJlLiBUaGUgZGIgYWRhcHRlciBzaG91bGRuJ3Qga25vd1xuICAvLyBhbnl0aGluZyBhYm91dCB1c2VycywgaWRlYWxseS4gVGhlbiwgaW1wcm92ZSB0aGUgZm9ybWF0IG9mIHRoZSBBQ0xcbiAgLy8gYXJnIHRvIHdvcmsgbGlrZSB0aGUgb3RoZXJzLlxuICBmaW5kKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5OiBhbnksXG4gICAge1xuICAgICAgc2tpcCxcbiAgICAgIGxpbWl0LFxuICAgICAgYWNsLFxuICAgICAgc29ydCA9IHt9LFxuICAgICAgY291bnQsXG4gICAgICBrZXlzLFxuICAgICAgb3AsXG4gICAgICBkaXN0aW5jdCxcbiAgICAgIHBpcGVsaW5lLFxuICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgfTogYW55ID0ge30sXG4gICAgYXV0aDogYW55ID0ge30sXG4gICAgdmFsaWRTY2hlbWFDb250cm9sbGVyOiBTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXJcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBpc01hc3RlciA9IGFjbCA9PT0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGFjbEdyb3VwID0gYWNsIHx8IFtdO1xuXG4gICAgb3AgPVxuICAgICAgb3AgfHxcbiAgICAgICh0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT0gJ3N0cmluZycgJiYgT2JqZWN0LmtleXMocXVlcnkpLmxlbmd0aCA9PT0gMVxuICAgICAgICA/ICdnZXQnXG4gICAgICAgIDogJ2ZpbmQnKTtcbiAgICAvLyBDb3VudCBvcGVyYXRpb24gaWYgY291bnRpbmdcbiAgICBvcCA9IGNvdW50ID09PSB0cnVlID8gJ2NvdW50JyA6IG9wO1xuXG4gICAgbGV0IGNsYXNzRXhpc3RzID0gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hSWZOZWVkZWQodmFsaWRTY2hlbWFDb250cm9sbGVyKS50aGVuKFxuICAgICAgc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgICAgIC8vQWxsb3cgdm9sYXRpbGUgY2xhc3NlcyBpZiBxdWVyeWluZyB3aXRoIE1hc3RlciAoZm9yIF9QdXNoU3RhdHVzKVxuICAgICAgICAvL1RPRE86IE1vdmUgdm9sYXRpbGUgY2xhc3NlcyBjb25jZXB0IGludG8gbW9uZ28gYWRhcHRlciwgcG9zdGdyZXMgYWRhcHRlciBzaG91bGRuJ3QgY2FyZVxuICAgICAgICAvL3RoYXQgYXBpLnBhcnNlLmNvbSBicmVha3Mgd2hlbiBfUHVzaFN0YXR1cyBleGlzdHMgaW4gbW9uZ28uXG4gICAgICAgIHJldHVybiBzY2hlbWFDb250cm9sbGVyXG4gICAgICAgICAgLmdldE9uZVNjaGVtYShjbGFzc05hbWUsIGlzTWFzdGVyKVxuICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAvLyBCZWhhdmlvciBmb3Igbm9uLWV4aXN0ZW50IGNsYXNzZXMgaXMga2luZGEgd2VpcmQgb24gUGFyc2UuY29tLiBQcm9iYWJseSBkb2Vzbid0IG1hdHRlciB0b28gbXVjaC5cbiAgICAgICAgICAgIC8vIEZvciBub3csIHByZXRlbmQgdGhlIGNsYXNzIGV4aXN0cyBidXQgaGFzIG5vIG9iamVjdHMsXG4gICAgICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjbGFzc0V4aXN0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXR1cm4geyBmaWVsZHM6IHt9IH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKHNjaGVtYSA9PiB7XG4gICAgICAgICAgICAvLyBQYXJzZS5jb20gdHJlYXRzIHF1ZXJpZXMgb24gX2NyZWF0ZWRfYXQgYW5kIF91cGRhdGVkX2F0IGFzIGlmIHRoZXkgd2VyZSBxdWVyaWVzIG9uIGNyZWF0ZWRBdCBhbmQgdXBkYXRlZEF0LFxuICAgICAgICAgICAgLy8gc28gZHVwbGljYXRlIHRoYXQgYmVoYXZpb3IgaGVyZS4gSWYgYm90aCBhcmUgc3BlY2lmaWVkLCB0aGUgY29ycmVjdCBiZWhhdmlvciB0byBtYXRjaCBQYXJzZS5jb20gaXMgdG9cbiAgICAgICAgICAgIC8vIHVzZSB0aGUgb25lIHRoYXQgYXBwZWFycyBmaXJzdCBpbiB0aGUgc29ydCBsaXN0LlxuICAgICAgICAgICAgaWYgKHNvcnQuX2NyZWF0ZWRfYXQpIHtcbiAgICAgICAgICAgICAgc29ydC5jcmVhdGVkQXQgPSBzb3J0Ll9jcmVhdGVkX2F0O1xuICAgICAgICAgICAgICBkZWxldGUgc29ydC5fY3JlYXRlZF9hdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzb3J0Ll91cGRhdGVkX2F0KSB7XG4gICAgICAgICAgICAgIHNvcnQudXBkYXRlZEF0ID0gc29ydC5fdXBkYXRlZF9hdDtcbiAgICAgICAgICAgICAgZGVsZXRlIHNvcnQuX3VwZGF0ZWRfYXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBxdWVyeU9wdGlvbnMgPSB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCByZWFkUHJlZmVyZW5jZSB9O1xuICAgICAgICAgICAgT2JqZWN0LmtleXMoc29ydCkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICBpZiAoZmllbGROYW1lLm1hdGNoKC9eYXV0aERhdGFcXC4oW2EtekEtWjAtOV9dKylcXC5pZCQvKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsXG4gICAgICAgICAgICAgICAgICBgQ2Fubm90IHNvcnQgYnkgJHtmaWVsZE5hbWV9YFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3Qgcm9vdEZpZWxkTmFtZSA9IGdldFJvb3RGaWVsZE5hbWUoZmllbGROYW1lKTtcbiAgICAgICAgICAgICAgaWYgKCFTY2hlbWFDb250cm9sbGVyLmZpZWxkTmFtZUlzVmFsaWQocm9vdEZpZWxkTmFtZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICAgICAgICAgICAgYEludmFsaWQgZmllbGQgbmFtZTogJHtmaWVsZE5hbWV9LmBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiAoaXNNYXN0ZXJcbiAgICAgICAgICAgICAgPyBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgICA6IHNjaGVtYUNvbnRyb2xsZXIudmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZSwgYWNsR3JvdXAsIG9wKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMucmVkdWNlUmVsYXRpb25LZXlzKGNsYXNzTmFtZSwgcXVlcnksIHF1ZXJ5T3B0aW9ucylcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMucmVkdWNlSW5SZWxhdGlvbihjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWFDb250cm9sbGVyKVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgcHJvdGVjdGVkRmllbGRzO1xuICAgICAgICAgICAgICAgIGlmICghaXNNYXN0ZXIpIHtcbiAgICAgICAgICAgICAgICAgIHF1ZXJ5ID0gdGhpcy5hZGRQb2ludGVyUGVybWlzc2lvbnMoXG4gICAgICAgICAgICAgICAgICAgIHNjaGVtYUNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgb3AsXG4gICAgICAgICAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICBhY2xHcm91cFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIC8qIERvbid0IHVzZSBwcm9qZWN0aW9ucyB0byBvcHRpbWl6ZSB0aGUgcHJvdGVjdGVkRmllbGRzIHNpbmNlIHRoZSBwcm90ZWN0ZWRGaWVsZHNcbiAgICAgICAgICAgICAgICAgIGJhc2VkIG9uIHBvaW50ZXItcGVybWlzc2lvbnMgYXJlIGRldGVybWluZWQgYWZ0ZXIgcXVlcnlpbmcuIFRoZSBmaWx0ZXJpbmcgY2FuXG4gICAgICAgICAgICAgICAgICBvdmVyd3JpdGUgdGhlIHByb3RlY3RlZCBmaWVsZHMuICovXG4gICAgICAgICAgICAgICAgICBwcm90ZWN0ZWRGaWVsZHMgPSB0aGlzLmFkZFByb3RlY3RlZEZpZWxkcyhcbiAgICAgICAgICAgICAgICAgICAgc2NoZW1hQ29udHJvbGxlcixcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgYWNsR3JvdXAsXG4gICAgICAgICAgICAgICAgICAgIGF1dGhcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghcXVlcnkpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChvcCA9PT0gJ2dldCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQuJ1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWlzTWFzdGVyKSB7XG4gICAgICAgICAgICAgICAgICBpZiAob3AgPT09ICd1cGRhdGUnIHx8IG9wID09PSAnZGVsZXRlJykge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IGFkZFdyaXRlQUNMKHF1ZXJ5LCBhY2xHcm91cCk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IGFkZFJlYWRBQ0wocXVlcnksIGFjbEdyb3VwKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFsaWRhdGVRdWVyeShxdWVyeSwgdGhpcy5za2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50KSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXNzRXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5jb3VudChcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICAgIHJlYWRQcmVmZXJlbmNlXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkaXN0aW5jdCkge1xuICAgICAgICAgICAgICAgICAgaWYgKCFjbGFzc0V4aXN0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmRpc3RpbmN0KFxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgICAgICAgZGlzdGluY3RcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBpcGVsaW5lKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXNzRXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuYWdncmVnYXRlKFxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgICAgICAgICAgICAgcGlwZWxpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgcmVhZFByZWZlcmVuY2VcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlclxuICAgICAgICAgICAgICAgICAgICAuZmluZChjbGFzc05hbWUsIHNjaGVtYSwgcXVlcnksIHF1ZXJ5T3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4ob2JqZWN0cyA9PlxuICAgICAgICAgICAgICAgICAgICAgIG9iamVjdHMubWFwKG9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QgPSB1bnRyYW5zZm9ybU9iamVjdEFDTChvYmplY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpbHRlclNlbnNpdGl2ZURhdGEoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlzTWFzdGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBhY2xHcm91cCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgb3AsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHNjaGVtYUNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdGVjdGVkRmllbGRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgZGVsZXRlU2NoZW1hKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYSh7IGNsZWFyQ2FjaGU6IHRydWUgfSlcbiAgICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4gc2NoZW1hQ29udHJvbGxlci5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCB0cnVlKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmV0dXJuIHsgZmllbGRzOiB7fSB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLnRoZW4oKHNjaGVtYTogYW55KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbGxlY3Rpb25FeGlzdHMoY2xhc3NOYW1lKVxuICAgICAgICAgIC50aGVuKCgpID0+XG4gICAgICAgICAgICB0aGlzLmFkYXB0ZXIuY291bnQoY2xhc3NOYW1lLCB7IGZpZWxkczoge30gfSwgbnVsbCwgJycsIGZhbHNlKVxuICAgICAgICAgIClcbiAgICAgICAgICAudGhlbihjb3VudCA9PiB7XG4gICAgICAgICAgICBpZiAoY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAyNTUsXG4gICAgICAgICAgICAgICAgYENsYXNzICR7Y2xhc3NOYW1lfSBpcyBub3QgZW1wdHksIGNvbnRhaW5zICR7Y291bnR9IG9iamVjdHMsIGNhbm5vdCBkcm9wIHNjaGVtYS5gXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmRlbGV0ZUNsYXNzKGNsYXNzTmFtZSk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbih3YXNQYXJzZUNvbGxlY3Rpb24gPT4ge1xuICAgICAgICAgICAgaWYgKHdhc1BhcnNlQ29sbGVjdGlvbikge1xuICAgICAgICAgICAgICBjb25zdCByZWxhdGlvbkZpZWxkTmFtZXMgPSBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKS5maWx0ZXIoXG4gICAgICAgICAgICAgICAgZmllbGROYW1lID0+IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUmVsYXRpb24nXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICByZWxhdGlvbkZpZWxkTmFtZXMubWFwKG5hbWUgPT5cbiAgICAgICAgICAgICAgICAgIHRoaXMuYWRhcHRlci5kZWxldGVDbGFzcyhqb2luVGFibGVOYW1lKGNsYXNzTmFtZSwgbmFtZSkpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFkZFBvaW50ZXJQZXJtaXNzaW9ucyhcbiAgICBzY2hlbWE6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcixcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBvcGVyYXRpb246IHN0cmluZyxcbiAgICBxdWVyeTogYW55LFxuICAgIGFjbEdyb3VwOiBhbnlbXSA9IFtdXG4gICkge1xuICAgIC8vIENoZWNrIGlmIGNsYXNzIGhhcyBwdWJsaWMgcGVybWlzc2lvbiBmb3Igb3BlcmF0aW9uXG4gICAgLy8gSWYgdGhlIEJhc2VDTFAgcGFzcywgbGV0IGdvIHRocm91Z2hcbiAgICBpZiAoc2NoZW1hLnRlc3RQZXJtaXNzaW9uc0ZvckNsYXNzTmFtZShjbGFzc05hbWUsIGFjbEdyb3VwLCBvcGVyYXRpb24pKSB7XG4gICAgICByZXR1cm4gcXVlcnk7XG4gICAgfVxuICAgIGNvbnN0IHBlcm1zID0gc2NoZW1hLmdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWUpO1xuICAgIGNvbnN0IGZpZWxkID1cbiAgICAgIFsnZ2V0JywgJ2ZpbmQnXS5pbmRleE9mKG9wZXJhdGlvbikgPiAtMVxuICAgICAgICA/ICdyZWFkVXNlckZpZWxkcydcbiAgICAgICAgOiAnd3JpdGVVc2VyRmllbGRzJztcbiAgICBjb25zdCB1c2VyQUNMID0gYWNsR3JvdXAuZmlsdGVyKGFjbCA9PiB7XG4gICAgICByZXR1cm4gYWNsLmluZGV4T2YoJ3JvbGU6JykgIT0gMCAmJiBhY2wgIT0gJyonO1xuICAgIH0pO1xuICAgIC8vIHRoZSBBQ0wgc2hvdWxkIGhhdmUgZXhhY3RseSAxIHVzZXJcbiAgICBpZiAocGVybXMgJiYgcGVybXNbZmllbGRdICYmIHBlcm1zW2ZpZWxkXS5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBObyB1c2VyIHNldCByZXR1cm4gdW5kZWZpbmVkXG4gICAgICAvLyBJZiB0aGUgbGVuZ3RoIGlzID4gMSwgdGhhdCBtZWFucyB3ZSBkaWRuJ3QgZGUtZHVwZSB1c2VycyBjb3JyZWN0bHlcbiAgICAgIGlmICh1c2VyQUNMLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVzZXJJZCA9IHVzZXJBQ0xbMF07XG4gICAgICBjb25zdCB1c2VyUG9pbnRlciA9IHtcbiAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgIGNsYXNzTmFtZTogJ19Vc2VyJyxcbiAgICAgICAgb2JqZWN0SWQ6IHVzZXJJZCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBlcm1GaWVsZHMgPSBwZXJtc1tmaWVsZF07XG4gICAgICBjb25zdCBvcnMgPSBwZXJtRmllbGRzLmZsYXRNYXAoa2V5ID0+IHtcbiAgICAgICAgLy8gY29uc3RyYWludCBmb3Igc2luZ2xlIHBvaW50ZXIgc2V0dXBcbiAgICAgICAgY29uc3QgcSA9IHtcbiAgICAgICAgICBba2V5XTogdXNlclBvaW50ZXIsXG4gICAgICAgIH07XG4gICAgICAgIC8vIGNvbnN0cmFpbnQgZm9yIHVzZXJzLWFycmF5IHNldHVwXG4gICAgICAgIGNvbnN0IHFhID0ge1xuICAgICAgICAgIFtrZXldOiB7ICRhbGw6IFt1c2VyUG9pbnRlcl0gfSxcbiAgICAgICAgfTtcbiAgICAgICAgLy8gaWYgd2UgYWxyZWFkeSBoYXZlIGEgY29uc3RyYWludCBvbiB0aGUga2V5LCB1c2UgdGhlICRhbmRcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChxdWVyeSwga2V5KSkge1xuICAgICAgICAgIHJldHVybiBbeyAkYW5kOiBbcSwgcXVlcnldIH0sIHsgJGFuZDogW3FhLCBxdWVyeV0gfV07XG4gICAgICAgIH1cbiAgICAgICAgLy8gb3RoZXJ3aXNlIGp1c3QgYWRkIHRoZSBjb25zdGFpbnRcbiAgICAgICAgcmV0dXJuIFtPYmplY3QuYXNzaWduKHt9LCBxdWVyeSwgcSksIE9iamVjdC5hc3NpZ24oe30sIHF1ZXJ5LCBxYSldO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4geyAkb3I6IG9ycyB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcXVlcnk7XG4gICAgfVxuICB9XG5cbiAgYWRkUHJvdGVjdGVkRmllbGRzKFxuICAgIHNjaGVtYTogU2NoZW1hQ29udHJvbGxlci5TY2hlbWFDb250cm9sbGVyLFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5OiBhbnkgPSB7fSxcbiAgICBhY2xHcm91cDogYW55W10gPSBbXSxcbiAgICBhdXRoOiBhbnkgPSB7fVxuICApIHtcbiAgICBjb25zdCBwZXJtcyA9IHNjaGVtYS5nZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lKTtcbiAgICBpZiAoIXBlcm1zKSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IHByb3RlY3RlZEZpZWxkcyA9IHBlcm1zLnByb3RlY3RlZEZpZWxkcztcbiAgICBpZiAoIXByb3RlY3RlZEZpZWxkcykgcmV0dXJuIG51bGw7XG5cbiAgICBpZiAoYWNsR3JvdXAuaW5kZXhPZihxdWVyeS5vYmplY3RJZCkgPiAtMSkgcmV0dXJuIG51bGw7XG5cbiAgICAvLyByZW1vdmUgdXNlckZpZWxkIGtleXMgc2luY2UgdGhleSBhcmUgZmlsdGVyZWQgYWZ0ZXIgcXVlcnlpbmdcbiAgICBsZXQgcHJvdGVjdGVkS2V5cyA9IE9iamVjdC5rZXlzKHByb3RlY3RlZEZpZWxkcykucmVkdWNlKChhY2MsIHZhbCkgPT4ge1xuICAgICAgaWYgKHZhbC5zdGFydHNXaXRoKCd1c2VyRmllbGQ6JykpIHJldHVybiBhY2M7XG4gICAgICByZXR1cm4gYWNjLmNvbmNhdChwcm90ZWN0ZWRGaWVsZHNbdmFsXSk7XG4gICAgfSwgW10pO1xuXG4gICAgWy4uLihhdXRoLnVzZXJSb2xlcyB8fCBbXSldLmZvckVhY2gocm9sZSA9PiB7XG4gICAgICBjb25zdCBmaWVsZHMgPSBwcm90ZWN0ZWRGaWVsZHNbcm9sZV07XG4gICAgICBpZiAoZmllbGRzKSB7XG4gICAgICAgIHByb3RlY3RlZEtleXMgPSBwcm90ZWN0ZWRLZXlzLmZpbHRlcih2ID0+IGZpZWxkcy5pbmNsdWRlcyh2KSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcHJvdGVjdGVkS2V5cztcbiAgfVxuXG4gIGNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uKCkge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXJcbiAgICAgIC5jcmVhdGVUcmFuc2FjdGlvbmFsU2Vzc2lvbigpXG4gICAgICAudGhlbih0cmFuc2FjdGlvbmFsU2Vzc2lvbiA9PiB7XG4gICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uID0gdHJhbnNhY3Rpb25hbFNlc3Npb247XG4gICAgICB9KTtcbiAgfVxuXG4gIGNvbW1pdFRyYW5zYWN0aW9uYWxTZXNzaW9uKCkge1xuICAgIGlmICghdGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgaXMgbm8gdHJhbnNhY3Rpb25hbCBzZXNzaW9uIHRvIGNvbW1pdCcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyXG4gICAgICAuY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24odGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb24pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uID0gbnVsbDtcbiAgICAgIH0pO1xuICB9XG5cbiAgYWJvcnRUcmFuc2FjdGlvbmFsU2Vzc2lvbigpIHtcbiAgICBpZiAoIXRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIHRyYW5zYWN0aW9uYWwgc2Vzc2lvbiB0byBhYm9ydCcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyXG4gICAgICAuYWJvcnRUcmFuc2FjdGlvbmFsU2Vzc2lvbih0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvbilcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb24gPSBudWxsO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBUT0RPOiBjcmVhdGUgaW5kZXhlcyBvbiBmaXJzdCBjcmVhdGlvbiBvZiBhIF9Vc2VyIG9iamVjdC4gT3RoZXJ3aXNlIGl0J3MgaW1wb3NzaWJsZSB0b1xuICAvLyBoYXZlIGEgUGFyc2UgYXBwIHdpdGhvdXQgaXQgaGF2aW5nIGEgX1VzZXIgY29sbGVjdGlvbi5cbiAgcGVyZm9ybUluaXRpYWxpemF0aW9uKCkge1xuICAgIGNvbnN0IHJlcXVpcmVkVXNlckZpZWxkcyA9IHtcbiAgICAgIGZpZWxkczoge1xuICAgICAgICAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0LFxuICAgICAgICAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9Vc2VyLFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IHJlcXVpcmVkUm9sZUZpZWxkcyA9IHtcbiAgICAgIGZpZWxkczoge1xuICAgICAgICAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0LFxuICAgICAgICAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9Sb2xlLFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgY29uc3QgdXNlckNsYXNzUHJvbWlzZSA9IHRoaXMubG9hZFNjaGVtYSgpLnRoZW4oc2NoZW1hID0+XG4gICAgICBzY2hlbWEuZW5mb3JjZUNsYXNzRXhpc3RzKCdfVXNlcicpXG4gICAgKTtcbiAgICBjb25zdCByb2xlQ2xhc3NQcm9taXNlID0gdGhpcy5sb2FkU2NoZW1hKCkudGhlbihzY2hlbWEgPT5cbiAgICAgIHNjaGVtYS5lbmZvcmNlQ2xhc3NFeGlzdHMoJ19Sb2xlJylcbiAgICApO1xuXG4gICAgY29uc3QgdXNlcm5hbWVVbmlxdWVuZXNzID0gdXNlckNsYXNzUHJvbWlzZVxuICAgICAgLnRoZW4oKCkgPT5cbiAgICAgICAgdGhpcy5hZGFwdGVyLmVuc3VyZVVuaXF1ZW5lc3MoJ19Vc2VyJywgcmVxdWlyZWRVc2VyRmllbGRzLCBbJ3VzZXJuYW1lJ10pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBsb2dnZXIud2FybignVW5hYmxlIHRvIGVuc3VyZSB1bmlxdWVuZXNzIGZvciB1c2VybmFtZXM6ICcsIGVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IGVtYWlsVW5pcXVlbmVzcyA9IHVzZXJDbGFzc1Byb21pc2VcbiAgICAgIC50aGVuKCgpID0+XG4gICAgICAgIHRoaXMuYWRhcHRlci5lbnN1cmVVbmlxdWVuZXNzKCdfVXNlcicsIHJlcXVpcmVkVXNlckZpZWxkcywgWydlbWFpbCddKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgJ1VuYWJsZSB0byBlbnN1cmUgdW5pcXVlbmVzcyBmb3IgdXNlciBlbWFpbCBhZGRyZXNzZXM6ICcsXG4gICAgICAgICAgZXJyb3JcbiAgICAgICAgKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IHJvbGVVbmlxdWVuZXNzID0gcm9sZUNsYXNzUHJvbWlzZVxuICAgICAgLnRoZW4oKCkgPT5cbiAgICAgICAgdGhpcy5hZGFwdGVyLmVuc3VyZVVuaXF1ZW5lc3MoJ19Sb2xlJywgcmVxdWlyZWRSb2xlRmllbGRzLCBbJ25hbWUnXSlcbiAgICAgIClcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdVbmFibGUgdG8gZW5zdXJlIHVuaXF1ZW5lc3MgZm9yIHJvbGUgbmFtZTogJywgZXJyb3IpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgaW5kZXhQcm9taXNlID0gdGhpcy5hZGFwdGVyLnVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzKCk7XG5cbiAgICAvLyBDcmVhdGUgdGFibGVzIGZvciB2b2xhdGlsZSBjbGFzc2VzXG4gICAgY29uc3QgYWRhcHRlckluaXQgPSB0aGlzLmFkYXB0ZXIucGVyZm9ybUluaXRpYWxpemF0aW9uKHtcbiAgICAgIFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXM6IFNjaGVtYUNvbnRyb2xsZXIuVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyxcbiAgICB9KTtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoW1xuICAgICAgdXNlcm5hbWVVbmlxdWVuZXNzLFxuICAgICAgZW1haWxVbmlxdWVuZXNzLFxuICAgICAgcm9sZVVuaXF1ZW5lc3MsXG4gICAgICBhZGFwdGVySW5pdCxcbiAgICAgIGluZGV4UHJvbWlzZSxcbiAgICBdKTtcbiAgfVxuXG4gIHN0YXRpYyBfdmFsaWRhdGVRdWVyeTogKGFueSwgYm9vbGVhbikgPT4gdm9pZDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBEYXRhYmFzZUNvbnRyb2xsZXI7XG4vLyBFeHBvc2UgdmFsaWRhdGVRdWVyeSBmb3IgdGVzdHNcbm1vZHVsZS5leHBvcnRzLl92YWxpZGF0ZVF1ZXJ5ID0gdmFsaWRhdGVRdWVyeTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/FilesController.js b/lib/Controllers/FilesController.js new file mode 100644 index 0000000000..118a0bde8a --- /dev/null +++ b/lib/Controllers/FilesController.js @@ -0,0 +1,128 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.FilesController = void 0; + +var _cryptoUtils = require("../cryptoUtils"); + +var _AdaptableController = _interopRequireDefault(require("./AdaptableController")); + +var _FilesAdapter = require("../Adapters/Files/FilesAdapter"); + +var _path = _interopRequireDefault(require("path")); + +var _mime = _interopRequireDefault(require("mime")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// FilesController.js +const Parse = require('parse').Parse; + +const legacyFilesRegex = new RegExp('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}-.*'); + +class FilesController extends _AdaptableController.default { + getFileData(config, filename) { + return this.adapter.getFileData(filename); + } + + createFile(config, filename, data, contentType) { + const extname = _path.default.extname(filename); + + const hasExtension = extname.length > 0; + + if (!hasExtension && contentType && _mime.default.getExtension(contentType)) { + filename = filename + '.' + _mime.default.getExtension(contentType); + } else if (hasExtension && !contentType) { + contentType = _mime.default.getType(filename); + } + + if (!this.options.preserveFileName) { + filename = (0, _cryptoUtils.randomHexString)(32) + '_' + filename; + } + + const location = this.adapter.getFileLocation(config, filename); + return this.adapter.createFile(filename, data, contentType).then(() => { + return Promise.resolve({ + url: location, + name: filename + }); + }); + } + + deleteFile(config, filename) { + return this.adapter.deleteFile(filename); + } + /** + * Find file references in REST-format object and adds the url key + * with the current mount point and app id. + * Object may be a single object or list of REST-format objects. + */ + + + expandFilesInObject(config, object) { + if (object instanceof Array) { + object.map(obj => this.expandFilesInObject(config, obj)); + return; + } + + if (typeof object !== 'object') { + return; + } + + for (const key in object) { + const fileObject = object[key]; + + if (fileObject && fileObject['__type'] === 'File') { + if (fileObject['url']) { + continue; + } + + const filename = fileObject['name']; // all filenames starting with "tfss-" should be from files.parsetfss.com + // all filenames starting with a "-" seperated UUID should be from files.parse.com + // all other filenames have been migrated or created from Parse Server + + if (config.fileKey === undefined) { + fileObject['url'] = this.adapter.getFileLocation(config, filename); + } else { + if (filename.indexOf('tfss-') === 0) { + fileObject['url'] = 'http://files.parsetfss.com/' + config.fileKey + '/' + encodeURIComponent(filename); + } else if (legacyFilesRegex.test(filename)) { + fileObject['url'] = 'http://files.parse.com/' + config.fileKey + '/' + encodeURIComponent(filename); + } else { + fileObject['url'] = this.adapter.getFileLocation(config, filename); + } + } + } + } + } + + expectedAdapterType() { + return _FilesAdapter.FilesAdapter; + } + + handleFileStream(config, filename, req, res, contentType) { + return this.adapter.handleFileStream(filename, req, res, contentType); + } + + validateFilename(filename) { + if (typeof this.adapter.validateFilename === 'function') { + const error = this.adapter.validateFilename(filename); + + if (typeof error !== 'string') { + return error; + } + + return new Parse.Error(Parse.Error.INVALID_FILE_NAME, error); + } + + return (0, _FilesAdapter.validateFilename)(filename); + } + +} + +exports.FilesController = FilesController; +var _default = FilesController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9GaWxlc0NvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiUGFyc2UiLCJyZXF1aXJlIiwibGVnYWN5RmlsZXNSZWdleCIsIlJlZ0V4cCIsIkZpbGVzQ29udHJvbGxlciIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJnZXRGaWxlRGF0YSIsImNvbmZpZyIsImZpbGVuYW1lIiwiYWRhcHRlciIsImNyZWF0ZUZpbGUiLCJkYXRhIiwiY29udGVudFR5cGUiLCJleHRuYW1lIiwicGF0aCIsImhhc0V4dGVuc2lvbiIsImxlbmd0aCIsIm1pbWUiLCJnZXRFeHRlbnNpb24iLCJnZXRUeXBlIiwib3B0aW9ucyIsInByZXNlcnZlRmlsZU5hbWUiLCJsb2NhdGlvbiIsImdldEZpbGVMb2NhdGlvbiIsInRoZW4iLCJQcm9taXNlIiwicmVzb2x2ZSIsInVybCIsIm5hbWUiLCJkZWxldGVGaWxlIiwiZXhwYW5kRmlsZXNJbk9iamVjdCIsIm9iamVjdCIsIkFycmF5IiwibWFwIiwib2JqIiwia2V5IiwiZmlsZU9iamVjdCIsImZpbGVLZXkiLCJ1bmRlZmluZWQiLCJpbmRleE9mIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwidGVzdCIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJGaWxlc0FkYXB0ZXIiLCJoYW5kbGVGaWxlU3RyZWFtIiwicmVxIiwicmVzIiwidmFsaWRhdGVGaWxlbmFtZSIsImVycm9yIiwiRXJyb3IiLCJJTlZBTElEX0ZJTEVfTkFNRSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBTEE7QUFNQSxNQUFNQSxLQUFLLEdBQUdDLE9BQU8sQ0FBQyxPQUFELENBQVAsQ0FBaUJELEtBQS9COztBQUVBLE1BQU1FLGdCQUFnQixHQUFHLElBQUlDLE1BQUosQ0FDdkIsaUZBRHVCLENBQXpCOztBQUlPLE1BQU1DLGVBQU4sU0FBOEJDLDRCQUE5QixDQUFrRDtBQUN2REMsRUFBQUEsV0FBVyxD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LGlCQUE1QixFQUErQ0YsS0FBL0MsQ0FBUDtBQUNEOztBQUNELFdBQU8sb0NBQWlCeEMsUUFBakIsQ0FBUDtBQUNEOztBQWhHc0Q7OztlQW1HMUNKLGUiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBGaWxlc0NvbnRyb2xsZXIuanNcbmltcG9ydCB7IHJhbmRvbUhleFN0cmluZyB9IGZyb20gJy4uL2NyeXB0b1V0aWxzJztcbmltcG9ydCBBZGFwdGFibGVDb250cm9sbGVyIGZyb20gJy4vQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgeyB2YWxpZGF0ZUZpbGVuYW1lLCBGaWxlc0FkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9GaWxlcy9GaWxlc0FkYXB0ZXInO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgbWltZSBmcm9tICdtaW1lJztcbmNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2UnKS5QYXJzZTtcblxuY29uc3QgbGVnYWN5RmlsZXNSZWdleCA9IG5ldyBSZWdFeHAoXG4gICdeWzAtOWEtZkEtRl17OH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17MTJ9LS4qJ1xuKTtcblxuZXhwb3J0IGNsYXNzIEZpbGVzQ29udHJvbGxlciBleHRlbmRzIEFkYXB0YWJsZUNvbnRyb2xsZXIge1xuICBnZXRGaWxlRGF0YShjb25maWcsIGZpbGVuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5nZXRGaWxlRGF0YShmaWxlbmFtZSk7XG4gIH1cblxuICBjcmVhdGVGaWxlKGNvbmZpZywgZmlsZW5hbWUsIGRhdGEsIGNvbnRlbnRUeXBlKSB7XG4gICAgY29uc3QgZXh0bmFtZSA9IHBhdGguZXh0bmFtZShmaWxlbmFtZSk7XG5cbiAgICBjb25zdCBoYXNFeHRlbnNpb24gPSBleHRuYW1lLmxlbmd0aCA+IDA7XG5cbiAgICBpZiAoIWhhc0V4dGVuc2lvbiAmJiBjb250ZW50VHlwZSAmJiBtaW1lLmdldEV4dGVuc2lvbihjb250ZW50VHlwZSkpIHtcbiAgICAgIGZpbGVuYW1lID0gZmlsZW5hbWUgKyAnLicgKyBtaW1lLmdldEV4dGVuc2lvbihjb250ZW50VHlwZSk7XG4gICAgfSBlbHNlIGlmIChoYXNFeHRlbnNpb24gJiYgIWNvbnRlbnRUeXBlKSB7XG4gICAgICBjb250ZW50VHlwZSA9IG1pbWUuZ2V0VHlwZShmaWxlbmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMucHJlc2VydmVGaWxlTmFtZSkge1xuICAgICAgZmlsZW5hbWUgPSByYW5kb21IZXhTdHJpbmcoMzIpICsgJ18nICsgZmlsZW5hbWU7XG4gICAgfVxuXG4gICAgY29uc3QgbG9jYXRpb24gPSB0aGlzLmFkYXB0ZXIuZ2V0RmlsZUxvY2F0aW9uKGNvbmZpZywgZmlsZW5hbWUpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuY3JlYXRlRmlsZShmaWxlbmFtZSwgZGF0YSwgY29udGVudFR5cGUpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgIHVybDogbG9jYXRpb24sXG4gICAgICAgIG5hbWU6IGZpbGVuYW1lLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBkZWxldGVGaWxlKGNvbmZpZywgZmlsZW5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmRlbGV0ZUZpbGUoZmlsZW5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmQgZmlsZSByZWZlcmVuY2VzIGluIFJFU1QtZm9ybWF0IG9iamVjdCBhbmQgYWRkcyB0aGUgdXJsIGtleVxuICAgKiB3aXRoIHRoZSBjdXJyZW50IG1vdW50IHBvaW50IGFuZCBhcHAgaWQuXG4gICAqIE9iamVjdCBtYXkgYmUgYSBzaW5nbGUgb2JqZWN0IG9yIGxpc3Qgb2YgUkVTVC1mb3JtYXQgb2JqZWN0cy5cbiAgICovXG4gIGV4cGFuZEZpbGVzSW5PYmplY3QoY29uZmlnLCBvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgIG9iamVjdC5tYXAob2JqID0+IHRoaXMuZXhwYW5kRmlsZXNJbk9iamVjdChjb25maWcsIG9iaikpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBjb25zdCBmaWxlT2JqZWN0ID0gb2JqZWN0W2tleV07XG4gICAgICBpZiAoZmlsZU9iamVjdCAmJiBmaWxlT2JqZWN0WydfX3R5cGUnXSA9PT0gJ0ZpbGUnKSB7XG4gICAgICAgIGlmIChmaWxlT2JqZWN0Wyd1cmwnXSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZpbGVuYW1lID0gZmlsZU9iamVjdFsnbmFtZSddO1xuICAgICAgICAvLyBhbGwgZmlsZW5hbWVzIHN0YXJ0aW5nIHdpdGggXCJ0ZnNzLVwiIHNob3VsZCBiZSBmcm9tIGZpbGVzLnBhcnNldGZzcy5jb21cbiAgICAgICAgLy8gYWxsIGZpbGVuYW1lcyBzdGFydGluZyB3aXRoIGEgXCItXCIgc2VwZXJhdGVkIFVVSUQgc2hvdWxkIGJlIGZyb20gZmlsZXMucGFyc2UuY29tXG4gICAgICAgIC8vIGFsbCBvdGhlciBmaWxlbmFtZXMgaGF2ZSBiZWVuIG1pZ3JhdGVkIG9yIGNyZWF0ZWQgZnJvbSBQYXJzZSBTZXJ2ZXJcbiAgICAgICAgaWYgKGNvbmZpZy5maWxlS2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBmaWxlT2JqZWN0Wyd1cmwnXSA9IHRoaXMuYWRhcHRlci5nZXRGaWxlTG9jYXRpb24oY29uZmlnLCBmaWxlbmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGZpbGVuYW1lLmluZGV4T2YoJ3Rmc3MtJykgPT09IDApIHtcbiAgICAgICAgICAgIGZpbGVPYmplY3RbJ3VybCddID1cbiAgICAgICAgICAgICAgJ2h0dHA6Ly9maWxlcy5wYXJzZXRmc3MuY29tLycgK1xuICAgICAgICAgICAgICBjb25maWcuZmlsZUtleSArXG4gICAgICAgICAgICAgICcvJyArXG4gICAgICAgICAgICAgIGVuY29kZVVSSUNvbXBvbmVudChmaWxlbmFtZSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChsZWdhY3lGaWxlc1JlZ2V4LnRlc3QoZmlsZW5hbWUpKSB7XG4gICAgICAgICAgICBmaWxlT2JqZWN0Wyd1cmwnXSA9XG4gICAgICAgICAgICAgICdodHRwOi8vZmlsZXMucGFyc2UuY29tLycgK1xuICAgICAgICAgICAgICBjb25maWcuZmlsZUtleSArXG4gICAgICAgICAgICAgICcvJyArXG4gICAgICAgICAgICAgIGVuY29kZVVSSUNvbXBvbmVudChmaWxlbmFtZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVPYmplY3RbJ3VybCddID0gdGhpcy5hZGFwdGVyLmdldEZpbGVMb2NhdGlvbihjb25maWcsIGZpbGVuYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHJldHVybiBGaWxlc0FkYXB0ZXI7XG4gIH1cblxuICBoYW5kbGVGaWxlU3RyZWFtKGNvbmZpZywgZmlsZW5hbWUsIHJlcSwgcmVzLCBjb250ZW50VHlwZSkge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuaGFuZGxlRmlsZVN0cmVhbShmaWxlbmFtZSwgcmVxLCByZXMsIGNvbnRlbnRUeXBlKTtcbiAgfVxuXG4gIHZhbGlkYXRlRmlsZW5hbWUoZmlsZW5hbWUpIHtcbiAgICBpZiAodHlwZW9mIHRoaXMuYWRhcHRlci52YWxpZGF0ZUZpbGVuYW1lID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjb25zdCBlcnJvciA9IHRoaXMuYWRhcHRlci52YWxpZGF0ZUZpbGVuYW1lKGZpbGVuYW1lKTtcbiAgICAgIGlmICh0eXBlb2YgZXJyb3IgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9GSUxFX05BTUUsIGVycm9yKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbGlkYXRlRmlsZW5hbWUoZmlsZW5hbWUpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEZpbGVzQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/HooksController.js b/lib/Controllers/HooksController.js new file mode 100644 index 0000000000..bdd210fedc --- /dev/null +++ b/lib/Controllers/HooksController.js @@ -0,0 +1,301 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.HooksController = void 0; + +var triggers = _interopRequireWildcard(require("../triggers")); + +var Parse = _interopRequireWildcard(require("parse/node")); + +var _request = _interopRequireDefault(require("../request")); + +var _logger = require("../logger"); + +var _http = _interopRequireDefault(require("http")); + +var _https = _interopRequireDefault(require("https")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +// -disable-next +// -disable-next +const DefaultHooksCollectionName = '_Hooks'; +const HTTPAgents = { + http: new _http.default.Agent({ + keepAlive: true + }), + https: new _https.default.Agent({ + keepAlive: true + }) +}; + +class HooksController { + constructor(applicationId, databaseController, webhookKey) { + this._applicationId = applicationId; + this._webhookKey = webhookKey; + this.database = databaseController; + } + + load() { + return this._getHooks().then(hooks => { + hooks = hooks || []; + hooks.forEach(hook => { + this.addHookToTriggers(hook); + }); + }); + } + + getFunction(functionName) { + return this._getHooks({ + functionName: functionName + }).then(results => results[0]); + } + + getFunctions() { + return this._getHooks({ + functionName: { + $exists: true + } + }); + } + + getTrigger(className, triggerName) { + return this._getHooks({ + className: className, + triggerName: triggerName + }).then(results => results[0]); + } + + getTriggers() { + return this._getHooks({ + className: { + $exists: true + }, + triggerName: { + $exists: true + } + }); + } + + deleteFunction(functionName) { + triggers.removeFunction(functionName, this._applicationId); + return this._removeHooks({ + functionName: functionName + }); + } + + deleteTrigger(className, triggerName) { + triggers.removeTrigger(triggerName, className, this._applicationId); + return this._removeHooks({ + className: className, + triggerName: triggerName + }); + } + + _getHooks(query = {}) { + return this.database.find(DefaultHooksCollectionName, query).then(results => { + return results.map(result => { + delete result.objectId; + return result; + }); + }); + } + + _removeHooks(query) { + return this.database.destroy(DefaultHooksCollectionName, query).then(() => { + return Promise.resolve({}); + }); + } + + saveHook(hook) { + var query; + + if (hook.functionName && hook.url) { + query = { + functionName: hook.functionName + }; + } else if (hook.triggerName && hook.className && hook.url) { + query = { + className: hook.className, + triggerName: hook.triggerName + }; + } else { + throw new Parse.Error(143, 'invalid hook declaration'); + } + + return this.database.update(DefaultHooksCollectionName, query, hook, { + upsert: true + }).then(() => { + return Promise.resolve(hook); + }); + } + + addHookToTriggers(hook) { + var wrappedFunction = wrapToHTTPRequest(hook, this._webhookKey); + wrappedFunction.url = hook.url; + + if (hook.className) { + triggers.addTrigger(hook.triggerName, hook.className, wrappedFunction, this._applicationId); + } else { + triggers.addFunction(hook.functionName, wrappedFunction, null, this._applicationId); + } + } + + addHook(hook) { + this.addHookToTriggers(hook); + return this.saveHook(hook); + } + + createOrUpdateHook(aHook) { + var hook; + + if (aHook && aHook.functionName && aHook.url) { + hook = {}; + hook.functionName = aHook.functionName; + hook.url = aHook.url; + } else if (aHook && aHook.className && aHook.url && aHook.triggerName && triggers.Types[aHook.triggerName]) { + hook = {}; + hook.className = aHook.className; + hook.url = aHook.url; + hook.triggerName = aHook.triggerName; + } else { + throw new Parse.Error(143, 'invalid hook declaration'); + } + + return this.addHook(hook); + } + + createHook(aHook) { + if (aHook.functionName) { + return this.getFunction(aHook.functionName).then(result => { + if (result) { + throw new Parse.Error(143, `function name: ${aHook.functionName} already exits`); + } else { + return this.createOrUpdateHook(aHook); + } + }); + } else if (aHook.className && aHook.triggerName) { + return this.getTrigger(aHook.className, aHook.triggerName).then(result => { + if (result) { + throw new Parse.Error(143, `class ${aHook.className} already has trigger ${aHook.triggerName}`); + } + + return this.createOrUpdateHook(aHook); + }); + } + + throw new Parse.Error(143, 'invalid hook declaration'); + } + + updateHook(aHook) { + if (aHook.functionName) { + return this.getFunction(aHook.functionName).then(result => { + if (result) { + return this.createOrUpdateHook(aHook); + } + + throw new Parse.Error(143, `no function named: ${aHook.functionName} is defined`); + }); + } else if (aHook.className && aHook.triggerName) { + return this.getTrigger(aHook.className, aHook.triggerName).then(result => { + if (result) { + return this.createOrUpdateHook(aHook); + } + + throw new Parse.Error(143, `class ${aHook.className} does not exist`); + }); + } + + throw new Parse.Error(143, 'invalid hook declaration'); + } + +} + +exports.HooksController = HooksController; + +function wrapToHTTPRequest(hook, key) { + return req => { + const jsonBody = {}; + + for (var i in req) { + jsonBody[i] = req[i]; + } + + if (req.object) { + jsonBody.object = req.object.toJSON(); + jsonBody.object.className = req.object.className; + } + + if (req.original) { + jsonBody.original = req.original.toJSON(); + jsonBody.original.className = req.original.className; + } + + const jsonRequest = { + url: hook.url, + headers: { + 'Content-Type': 'application/json' + }, + body: jsonBody, + method: 'POST' + }; + const agent = hook.url.startsWith('https') ? HTTPAgents['https'] : HTTPAgents['http']; + jsonRequest.agent = agent; + + if (key) { + jsonRequest.headers['X-Parse-Webhook-Key'] = key; + } else { + _logger.logger.warn('Making outgoing webhook request without webhookKey being set!'); + } + + return (0, _request.default)(jsonRequest).then(response => { + let err; + let result; + let body = response.data; + + if (body) { + if (typeof body === 'string') { + try { + body = JSON.parse(body); + } catch (e) { + err = { + error: 'Malformed response', + code: -1, + partialResponse: body.substring(0, 100) + }; + } + } + + if (!err) { + result = body.success; + err = body.error; + } + } + + if (err) { + throw err; + } else if (hook.triggerName === 'beforeSave') { + if (typeof result === 'object') { + delete result.createdAt; + delete result.updatedAt; + } + + return { + object: result + }; + } else { + return result; + } + }); + }; +} + +var _default = HooksController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9Ib29rc0NvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiRGVmYXVsdEhvb2tzQ29sbGVjdGlvbk5hbWUiLCJIVFRQQWdlbnRzIiwiaHR0cCIsIkFnZW50Iiwia2VlcEFsaXZlIiwiaHR0cHMiLCJIb29rc0NvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImFwcGxpY2F0aW9uSWQiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJ3ZWJob29rS2V5IiwiX2FwcGxpY2F0aW9uSWQiLCJfd2ViaG9va0tleSIsImRhdGFiYXNlIiwibG9hZCIsIl9nZXRIb29rcyIsInRoZW4iLCJob29rcyIsImZvckVhY2giLCJob29rIiwiYWRkSG9va1RvVHJpZ2dlcnMiLCJnZXRGdW5jdGlvbiIsImZ1bmN0aW9uTmFtZSIsInJlc3VsdHMiLCJnZXRGdW5jdGlvbnMiLCIkZXhpc3RzIiwiZ2V0VHJpZ2dlciIsImNsYXNzTmFtZSIsInRyaWdnZXJOYW1lIiwiZ2V0VHJpZ2dlcnMiLCJkZWxldGVGdW5jdGlvbiIsInRyaWdnZXJzIiwicmVtb3ZlRnVuY3Rpb24iLCJfcmVtb3ZlSG9va3MiLCJkZWxldGVUcmlnZ2VyIiwicmVtb3ZlVHJpZ2dlciIsInF1ZXJ5IiwiZmluZCIsIm1hcCIsInJlc3VsdCIsIm9iamVjdElkIiwiZGVzdHJveSIsIlByb21pc2UiLCJyZXNvbHZlIiwic2F2ZUhvb2siLCJ1cmwiLCJQYXJzZSIsIkVycm9yIiwidXBkYXRlIiwidXBzZXJ0Iiwid3JhcHBlZEZ1bmN0aW9uIiwid3JhcFRvSFRUUFJlcXVlc3QiLCJhZGRUcmlnZ2VyIiwiYWRkRnVuY3Rpb24iLCJhZGRIb29rIiwiY3JlYXRlT3JVcGRhdGVIb29rIiwiYUhvb2siLCJUeXBlcyIsImNyZWF0ZUhvb2siLCJ1cGRhdGVIb29rIiwia2V5IiwicmVxIiwianNvbkJvZHkiLCJpIiwib2JqZWN0IiwidG9KU09OIiwib3JpZ2luYWwiLCJqc29uUmVxdWVzdCIsImhlYWRlcnMiLCJib2R5IiwibWV0aG9kIiwiYWdlbnQiLCJzdGFydHNXaXRoIiwibG9nZ2VyIiwid2FybiIsInJlc3BvbnNlIiwiZXJyIiwiZGF0YSIsIkpTT04iLCJwYXJzZSIsImUiLCJlcnJvciIsImNvZGUiLCJwYXJ0aWFsUmVzcG9uc2UiLCJzdWJzdHJpbmciLCJzdWNjZXNzIiwiY3JlYXRlZEF0IiwidXBkYXRlZEF0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBRUE7O0FBRUE7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBTkE7QUFFQTtBQU1BLE1BQU1BLDBCQUEwQixHQUFHLFFBQW5DO0FBQ0EsTUFBTUMsVUFBVSxHQUFHO0FBQ2pCQyxFQUFBQSxJQUFJLEVBQUUsSUFBSUEsY0FBS0MsS0FBVCxDQUFlO0FBQUVDLElBQUFBLFNBQVMsRUFBRTtBQUFiLEdBQWYsQ0FEVztBQUVqQkMsRUFBQUEsS0FBSyxFQUFFLElBQUlBLGVBQU1GLEtBQVYsQ0FBZ0I7QUFBRUMsSUFBQUEsU0FBUyxFQUFFO0FBQWIsR0FBaEI7QUFGVSxDQUFuQjs7QUFLTyxNQUFNRSxlQUFOLENBQXNCO0FBSzNCQyxFQUFBQSxXQUFXLENBQUNDLGFBQUQsRUFBd0JDLGtCQUF4QixFQUE0Q0MsVUFBNUMsRUFBd0Q7QUFDakUsU0FBS0MsY0FBTCxHQUFzQkgsYUFBdEI7QUFDQSxTQUFLSSxXQUFMLEdBQW1CRixVQUFuQjtBQUNBLFNBQUtHLFFBQUwsR0FBZ0JKLGtCQUFoQjtBQUNEOztBQUVESyxFQUFBQSxJQUFJLEdBQUc7QUFDTCxXQUFPLEtBQUtDLFNBQUwsR0FBaUJDLElBQWpCLENBQXNCQyxLQUFLLElBQUk7QUFDcENBLE1BQUFBLEtBQUssR0FBR0EsS0FBSyxJQUFJLEVBQWpCO0FBQ0FBLE1BQUFBLEtBQUssQ0FBQ0MsT0FBTixDQUFjQyxJQUFJLElBQUk7QUFDcEIsYUFBS0MsaUJBQUwsQ0FBdUJELElBQXZCO0FBQ0QsT0FGRDtBQUdELEtBTE0sQ0FBUDtBQU1EOztBQUVERSxFQUFBQSxXQUFXLENBQUNDLFlBQUQsRUFBZTtB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QUEsZUFBZSxFQUFFZCxJQUFJLENBQUNlLFNBQUwsQ0FBZSxDQUFmLEVBQWtCLEdBQWxCO0FBSGIsYUFBTjtBQUtEO0FBQ0Y7O0FBQ0QsWUFBSSxDQUFDUixHQUFMLEVBQVU7QUFDUnJDLFVBQUFBLE1BQU0sR0FBRzhCLElBQUksQ0FBQ2dCLE9BQWQ7QUFDQVQsVUFBQUEsR0FBRyxHQUFHUCxJQUFJLENBQUNZLEtBQVg7QUFDRDtBQUNGOztBQUNELFVBQUlMLEdBQUosRUFBUztBQUNQLGNBQU1BLEdBQU47QUFDRCxPQUZELE1BRU8sSUFBSXpELElBQUksQ0FBQ1MsV0FBTCxLQUFxQixZQUF6QixFQUF1QztBQUM1QyxZQUFJLE9BQU9XLE1BQVAsS0FBa0IsUUFBdEIsRUFBZ0M7QUFDOUIsaUJBQU9BLE1BQU0sQ0FBQytDLFNBQWQ7QUFDQSxpQkFBTy9DLE1BQU0sQ0FBQ2dELFNBQWQ7QUFDRDs7QUFDRCxlQUFPO0FBQUV2QixVQUFBQSxNQUFNLEVBQUV6QjtBQUFWLFNBQVA7QUFDRCxPQU5NLE1BTUE7QUFDTCxlQUFPQSxNQUFQO0FBQ0Q7QUFDRixLQWhDTSxDQUFQO0FBaUNELEdBbkVEO0FBb0VEOztlQUVjakMsZSIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAZmxvdyB3ZWFrICovXG5cbmltcG9ydCAqIGFzIHRyaWdnZXJzIGZyb20gJy4uL3RyaWdnZXJzJztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0ICogYXMgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCByZXF1ZXN0IGZyb20gJy4uL3JlcXVlc3QnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0IGh0dHBzIGZyb20gJ2h0dHBzJztcblxuY29uc3QgRGVmYXVsdEhvb2tzQ29sbGVjdGlvbk5hbWUgPSAnX0hvb2tzJztcbmNvbnN0IEhUVFBBZ2VudHMgPSB7XG4gIGh0dHA6IG5ldyBodHRwLkFnZW50KHsga2VlcEFsaXZlOiB0cnVlIH0pLFxuICBodHRwczogbmV3IGh0dHBzLkFnZW50KHsga2VlcEFsaXZlOiB0cnVlIH0pLFxufTtcblxuZXhwb3J0IGNsYXNzIEhvb2tzQ29udHJvbGxlciB7XG4gIF9hcHBsaWNhdGlvbklkOiBzdHJpbmc7XG4gIF93ZWJob29rS2V5OiBzdHJpbmc7XG4gIGRhdGFiYXNlOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoYXBwbGljYXRpb25JZDogc3RyaW5nLCBkYXRhYmFzZUNvbnRyb2xsZXIsIHdlYmhvb2tLZXkpIHtcbiAgICB0aGlzLl9hcHBsaWNhdGlvbklkID0gYXBwbGljYXRpb25JZDtcbiAgICB0aGlzLl93ZWJob29rS2V5ID0gd2ViaG9va0tleTtcbiAgICB0aGlzLmRhdGFiYXNlID0gZGF0YWJhc2VDb250cm9sbGVyO1xuICB9XG5cbiAgbG9hZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0SG9va3MoKS50aGVuKGhvb2tzID0+IHtcbiAgICAgIGhvb2tzID0gaG9va3MgfHwgW107XG4gICAgICBob29rcy5mb3JFYWNoKGhvb2sgPT4ge1xuICAgICAgICB0aGlzLmFkZEhvb2tUb1RyaWdnZXJzKGhvb2spO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXRGdW5jdGlvbihmdW5jdGlvbk5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0SG9va3MoeyBmdW5jdGlvbk5hbWU6IGZ1bmN0aW9uTmFtZSB9KS50aGVuKFxuICAgICAgcmVzdWx0cyA9PiByZXN1bHRzWzBdXG4gICAgKTtcbiAgfVxuXG4gIGdldEZ1bmN0aW9ucygpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0SG9va3MoeyBmdW5jdGlvbk5hbWU6IHsgJGV4aXN0czogdHJ1ZSB9IH0pO1xuICB9XG5cbiAgZ2V0VHJpZ2dlcihjbGFzc05hbWUsIHRyaWdnZXJOYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldEhvb2tzKHtcbiAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLFxuICAgICAgdHJpZ2dlck5hbWU6IHRyaWdnZXJOYW1lLFxuICAgIH0pLnRoZW4ocmVzdWx0cyA9PiByZXN1bHRzWzBdKTtcbiAgfVxuXG4gIGdldFRyaWdnZXJzKCkge1xuICAgIHJldHVybiB0aGlzLl9nZXRIb29rcyh7XG4gICAgICBjbGFzc05hbWU6IHsgJGV4aXN0czogdHJ1ZSB9LFxuICAgICAgdHJpZ2dlck5hbWU6IHsgJGV4aXN0czogdHJ1ZSB9LFxuICAgIH0pO1xuICB9XG5cbiAgZGVsZXRlRnVuY3Rpb24oZnVuY3Rpb25OYW1lKSB7XG4gICAgdHJpZ2dlcnMucmVtb3ZlRnVuY3Rpb24oZnVuY3Rpb25OYW1lLCB0aGlzLl9hcHBsaWNhdGlvbklkKTtcbiAgICByZXR1cm4gdGhpcy5fcmVtb3ZlSG9va3MoeyBmdW5jdGlvbk5hbWU6IGZ1bmN0aW9uTmFtZSB9KTtcbiAgfVxuXG4gIGRlbGV0ZVRyaWdnZXIoY2xhc3NOYW1lLCB0cmlnZ2VyTmFtZSkge1xuICAgIHRyaWdnZXJzLnJlbW92ZVRyaWdnZXIodHJpZ2dlck5hbWUsIGNsYXNzTmFtZSwgdGhpcy5fYXBwbGljYXRpb25JZCk7XG4gICAgcmV0dXJuIHRoaXMuX3JlbW92ZUhvb2tzKHtcbiAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLFxuICAgICAgdHJpZ2dlck5hbWU6IHRyaWdnZXJOYW1lLFxuICAgIH0pO1xuICB9XG5cbiAgX2dldEhvb2tzKHF1ZXJ5ID0ge30pIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhYmFzZVxuICAgICAgLmZpbmQoRGVmYXVsdEhvb2tzQ29sbGVjdGlvbk5hbWUsIHF1ZXJ5KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHJldHVybiByZXN1bHRzLm1hcChyZXN1bHQgPT4ge1xuICAgICAgICAgIGRlbGV0ZSByZXN1bHQub2JqZWN0SWQ7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIF9yZW1vdmVIb29rcyhxdWVyeSkge1xuICAgIHJldHVybiB0aGlzLmRhdGFiYXNlLmRlc3Ryb3koRGVmYXVsdEhvb2tzQ29sbGVjdGlvbk5hbWUsIHF1ZXJ5KS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICAgIH0pO1xuICB9XG5cbiAgc2F2ZUhvb2soaG9vaykge1xuICAgIHZhciBxdWVyeTtcbiAgICBpZiAoaG9vay5mdW5jdGlvbk5hbWUgJiYgaG9vay51cmwpIHtcbiAgICAgIHF1ZXJ5ID0geyBmdW5jdGlvbk5hbWU6IGhvb2suZnVuY3Rpb25OYW1lIH07XG4gICAgfSBlbHNlIGlmIChob29rLnRyaWdnZXJOYW1lICYmIGhvb2suY2xhc3NOYW1lICYmIGhvb2sudXJsKSB7XG4gICAgICBxdWVyeSA9IHsgY2xhc3NOYW1lOiBob29rLmNsYXNzTmFtZSwgdHJpZ2dlck5hbWU6IGhvb2sudHJpZ2dlck5hbWUgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDE0MywgJ2ludmFsaWQgaG9vayBkZWNsYXJhdGlvbicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5kYXRhYmFzZVxuICAgICAgLnVwZGF0ZShEZWZhdWx0SG9va3NDb2xsZWN0aW9uTmFtZSwgcXVlcnksIGhvb2ssIHsgdXBzZXJ0OiB0cnVlIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoaG9vayk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFkZEhvb2tUb1RyaWdnZXJzKGhvb2spIHtcbiAgICB2YXIgd3JhcHBlZEZ1bmN0aW9uID0gd3JhcFRvSFRUUFJlcXVlc3QoaG9vaywgdGhpcy5fd2ViaG9va0tleSk7XG4gICAgd3JhcHBlZEZ1bmN0aW9uLnVybCA9IGhvb2sudXJsO1xuICAgIGlmIChob29rLmNsYXNzTmFtZSkge1xuICAgICAgdHJpZ2dlcnMuYWRkVHJpZ2dlcihcbiAgICAgICAgaG9vay50cmlnZ2VyTmFtZSxcbiAgICAgICAgaG9vay5jbGFzc05hbWUsXG4gICAgICAgIHdyYXBwZWRGdW5jdGlvbixcbiAgICAgICAgdGhpcy5fYXBwbGljYXRpb25JZFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHJpZ2dlcnMuYWRkRnVuY3Rpb24oXG4gICAgICAgIGhvb2suZnVuY3Rpb25OYW1lLFxuICAgICAgICB3cmFwcGVkRnVuY3Rpb24sXG4gICAgICAgIG51bGwsXG4gICAgICAgIHRoaXMuX2FwcGxpY2F0aW9uSWRcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgYWRkSG9vayhob29rKSB7XG4gICAgdGhpcy5hZGRIb29rVG9UcmlnZ2Vycyhob29rKTtcbiAgICByZXR1cm4gdGhpcy5zYXZlSG9vayhob29rKTtcbiAgfVxuXG4gIGNyZWF0ZU9yVXBkYXRlSG9vayhhSG9vaykge1xuICAgIHZhciBob29rO1xuICAgIGlmIChhSG9vayAmJiBhSG9vay5mdW5jdGlvbk5hbWUgJiYgYUhvb2sudXJsKSB7XG4gICAgICBob29rID0ge307XG4gICAgICBob29rLmZ1bmN0aW9uTmFtZSA9IGFIb29rLmZ1bmN0aW9uTmFtZTtcbiAgICAgIGhvb2sudXJsID0gYUhvb2sudXJsO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICBhSG9vayAmJlxuICAgICAgYUhvb2suY2xhc3NOYW1lICYmXG4gICAgICBhSG9vay51cmwgJiZcbiAgICAgIGFIb29rLnRyaWdnZXJOYW1lICYmXG4gICAgICB0cmlnZ2Vycy5UeXBlc1thSG9vay50cmlnZ2VyTmFtZV1cbiAgICApIHtcbiAgICAgIGhvb2sgPSB7fTtcbiAgICAgIGhvb2suY2xhc3NOYW1lID0gYUhvb2suY2xhc3NOYW1lO1xuICAgICAgaG9vay51cmwgPSBhSG9vay51cmw7XG4gICAgICBob29rLnRyaWdnZXJOYW1lID0gYUhvb2sudHJpZ2dlck5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxNDMsICdpbnZhbGlkIGhvb2sgZGVjbGFyYXRpb24nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5hZGRIb29rKGhvb2spO1xuICB9XG5cbiAgY3JlYXRlSG9vayhhSG9vaykge1xuICAgIGlmIChhSG9vay5mdW5jdGlvbk5hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEZ1bmN0aW9uKGFIb29rLmZ1bmN0aW9uTmFtZSkudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgMTQzLFxuICAgICAgICAgICAgYGZ1bmN0aW9uIG5hbWU6ICR7YUhvb2suZnVuY3Rpb25OYW1lfSBhbHJlYWR5IGV4aXRzYFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlT3JVcGRhdGVIb29rKGFIb29rKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChhSG9vay5jbGFzc05hbWUgJiYgYUhvb2sudHJpZ2dlck5hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldFRyaWdnZXIoYUhvb2suY2xhc3NOYW1lLCBhSG9vay50cmlnZ2VyTmFtZSkudGhlbihcbiAgICAgICAgcmVzdWx0ID0+IHtcbiAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIDE0MyxcbiAgICAgICAgICAgICAgYGNsYXNzICR7YUhvb2suY2xhc3NOYW1lfSBhbHJlYWR5IGhhcyB0cmlnZ2VyICR7XG4gICAgICAgICAgICAgICAgYUhvb2sudHJpZ2dlck5hbWVcbiAgICAgICAgICAgICAgfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU9yVXBkYXRlSG9vayhhSG9vayk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDE0MywgJ2ludmFsaWQgaG9vayBkZWNsYXJhdGlvbicpO1xuICB9XG5cbiAgdXBkYXRlSG9vayhhSG9vaykge1xuICAgIGlmIChhSG9vay5mdW5jdGlvbk5hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEZ1bmN0aW9uKGFIb29rLmZ1bmN0aW9uTmFtZSkudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlT3JVcGRhdGVIb29rKGFIb29rKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgMTQzLFxuICAgICAgICAgIGBubyBmdW5jdGlvbiBuYW1lZDogJHthSG9vay5mdW5jdGlvbk5hbWV9IGlzIGRlZmluZWRgXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGFIb29rLmNsYXNzTmFtZSAmJiBhSG9vay50cmlnZ2VyTmFtZSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VHJpZ2dlcihhSG9vay5jbGFzc05hbWUsIGFIb29rLnRyaWdnZXJOYW1lKS50aGVuKFxuICAgICAgICByZXN1bHQgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU9yVXBkYXRlSG9vayhhSG9vayk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxNDMsIGBjbGFzcyAke2FIb29rLmNsYXNzTmFtZX0gZG9lcyBub3QgZXhpc3RgKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDE0MywgJ2ludmFsaWQgaG9vayBkZWNsYXJhdGlvbicpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHdyYXBUb0hUVFBSZXF1ZXN0KGhvb2ssIGtleSkge1xuICByZXR1cm4gcmVxID0+IHtcbiAgICBjb25zdCBqc29uQm9keSA9IHt9O1xuICAgIGZvciAodmFyIGkgaW4gcmVxKSB7XG4gICAgICBqc29uQm9keVtpXSA9IHJlcVtpXTtcbiAgICB9XG4gICAgaWYgKHJlcS5vYmplY3QpIHtcbiAgICAgIGpzb25Cb2R5Lm9iamVjdCA9IHJlcS5vYmplY3QudG9KU09OKCk7XG4gICAgICBqc29uQm9keS5vYmplY3QuY2xhc3NOYW1lID0gcmVxLm9iamVjdC5jbGFzc05hbWU7XG4gICAgfVxuICAgIGlmIChyZXEub3JpZ2luYWwpIHtcbiAgICAgIGpzb25Cb2R5Lm9yaWdpbmFsID0gcmVxLm9yaWdpbmFsLnRvSlNPTigpO1xuICAgICAganNvbkJvZHkub3JpZ2luYWwuY2xhc3NOYW1lID0gcmVxLm9yaWdpbmFsLmNsYXNzTmFtZTtcbiAgICB9XG4gICAgY29uc3QganNvblJlcXVlc3Q6IGFueSA9IHtcbiAgICAgIHVybDogaG9vay51cmwsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9LFxuICAgICAgYm9keToganNvbkJvZHksXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICB9O1xuXG4gICAgY29uc3QgYWdlbnQgPSBob29rLnVybC5zdGFydHNXaXRoKCdodHRwcycpXG4gICAgICA/IEhUVFBBZ2VudHNbJ2h0dHBzJ11cbiAgICAgIDogSFRUUEFnZW50c1snaHR0cCddO1xuICAgIGpzb25SZXF1ZXN0LmFnZW50ID0gYWdlbnQ7XG5cbiAgICBpZiAoa2V5KSB7XG4gICAgICBqc29uUmVxdWVzdC5oZWFkZXJzWydYLVBhcnNlLVdlYmhvb2stS2V5J10gPSBrZXk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAnTWFraW5nIG91dGdvaW5nIHdlYmhvb2sgcmVxdWVzdCB3aXRob3V0IHdlYmhvb2tLZXkgYmVpbmcgc2V0ISdcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiByZXF1ZXN0KGpzb25SZXF1ZXN0KS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgIGxldCBlcnI7XG4gICAgICBsZXQgcmVzdWx0O1xuICAgICAgbGV0IGJvZHkgPSByZXNwb25zZS5kYXRhO1xuICAgICAgaWYgKGJvZHkpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBib2R5ID0gSlNPTi5wYXJzZShib2R5KTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBlcnIgPSB7XG4gICAgICAgICAgICAgIGVycm9yOiAnTWFsZm9ybWVkIHJlc3BvbnNlJyxcbiAgICAgICAgICAgICAgY29kZTogLTEsXG4gICAgICAgICAgICAgIHBhcnRpYWxSZXNwb25zZTogYm9keS5zdWJzdHJpbmcoMCwgMTAwKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghZXJyKSB7XG4gICAgICAgICAgcmVzdWx0ID0gYm9keS5zdWNjZXNzO1xuICAgICAgICAgIGVyciA9IGJvZHkuZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfSBlbHNlIGlmIChob29rLnRyaWdnZXJOYW1lID09PSAnYmVmb3JlU2F2ZScpIHtcbiAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgZGVsZXRlIHJlc3VsdC5jcmVhdGVkQXQ7XG4gICAgICAgICAgZGVsZXRlIHJlc3VsdC51cGRhdGVkQXQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgb2JqZWN0OiByZXN1bHQgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59XG5cbmV4cG9ydCBkZWZhdWx0IEhvb2tzQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/LiveQueryController.js b/lib/Controllers/LiveQueryController.js new file mode 100644 index 0000000000..d592a17a1b --- /dev/null +++ b/lib/Controllers/LiveQueryController.js @@ -0,0 +1,71 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.LiveQueryController = void 0; + +var _ParseCloudCodePublisher = require("../LiveQuery/ParseCloudCodePublisher"); + +var _Options = require("../Options"); + +class LiveQueryController { + constructor(config) { + // If config is empty, we just assume no classs needs to be registered as LiveQuery + if (!config || !config.classNames) { + this.classNames = new Set(); + } else if (config.classNames instanceof Array) { + this.classNames = new Set(config.classNames); + } else { + throw 'liveQuery.classes should be an array of string'; + } + + this.liveQueryPublisher = new _ParseCloudCodePublisher.ParseCloudCodePublisher(config); + } + + onAfterSave(className, currentObject, originalObject, classLevelPermissions) { + if (!this.hasLiveQuery(className)) { + return; + } + + const req = this._makePublisherRequest(currentObject, originalObject, classLevelPermissions); + + this.liveQueryPublisher.onCloudCodeAfterSave(req); + } + + onAfterDelete(className, currentObject, originalObject, classLevelPermissions) { + if (!this.hasLiveQuery(className)) { + return; + } + + const req = this._makePublisherRequest(currentObject, originalObject, classLevelPermissions); + + this.liveQueryPublisher.onCloudCodeAfterDelete(req); + } + + hasLiveQuery(className) { + return this.classNames.has(className); + } + + _makePublisherRequest(currentObject, originalObject, classLevelPermissions) { + const req = { + object: currentObject + }; + + if (currentObject) { + req.original = originalObject; + } + + if (classLevelPermissions) { + req.classLevelPermissions = classLevelPermissions; + } + + return req; + } + +} + +exports.LiveQueryController = LiveQueryController; +var _default = LiveQueryController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9MaXZlUXVlcnlDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkxpdmVRdWVyeUNvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsImNsYXNzTmFtZXMiLCJTZXQiLCJBcnJheSIsImxpdmVRdWVyeVB1Ymxpc2hlciIsIlBhcnNlQ2xvdWRDb2RlUHVibGlzaGVyIiwib25BZnRlclNhdmUiLCJjbGFzc05hbWUiLCJjdXJyZW50T2JqZWN0Iiwib3JpZ2luYWxPYmplY3QiLCJjbGFzc0xldmVsUGVybWlzc2lvbnMiLCJoYXNMaXZlUXVlcnkiLCJyZXEiLCJfbWFrZVB1Ymxpc2hlclJlcXVlc3QiLCJvbkNsb3VkQ29kZUFmdGVyU2F2ZSIsIm9uQWZ0ZXJEZWxldGUiLCJvbkNsb3VkQ29kZUFmdGVyRGVsZXRlIiwiaGFzIiwib2JqZWN0Iiwib3JpZ2luYWwiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDTyxNQUFNQSxtQkFBTixDQUEwQjtBQUkvQkMsRUFBQUEsV0FBVyxDQUFDQyxNQUFELEVBQTRCO0FBQ3JDO0FBQ0EsUUFBSSxDQUFDQSxNQUFELElBQVcsQ0FBQ0EsTUFBTSxDQUFDQyxVQUF2QixFQUFtQztBQUNqQyxXQUFLQSxVQUFMLEdBQWtCLElBQUlDLEdBQUosRUFBbEI7QUFDRCxLQUZELE1BRU8sSUFBSUYsTUFBTSxDQUFDQyxVQUFQLFlBQTZCRSxLQUFqQyxFQUF3QztBQUM3QyxXQUFLRixVQUFMLEdBQWtCLElBQUlDLEdBQUosQ0FBUUYsTUFBTSxDQUFDQyxVQUFmLENBQWxCO0FBQ0QsS0FGTSxNQUVBO0FBQ0wsWUFBTSxnREFBTjtBQUNEOztBQUNELFNBQUtHLGtCQUFMLEdBQTBCLElBQUlDLGdEQUFKLENBQTRCTCxNQUE1QixDQUExQjtBQUNEOztBQUVETSxFQUFBQSxXQUFXLENBQ1RDLFNBRFMsRUFFVEMsYUFGUyxFQUdUQyxjQUhTLEVBSVRDLHFCQUpTLEVBS1Q7QUFDQSxRQUFJLENBQUMsS0FBS0MsWUFBTCxDQUFrQkosU0FBbEIsQ0FBTCxFQUFtQztBQUNqQztBQUNEOztBQUNELFVBQU1LLEdBQUcsR0FBRyxLQUFLQyxxQkFBTCxDQUNWTCxhQURVLEVBRVZDLGNBRlUsRUFHVkMscUJBSFUsQ0FBWjs7QUFLQSxTQUFLTixrQkFBTCxDQUF3QlUsb0JBQXhCLENBQTZDRixHQUE3QztBQUNEOztBQUVERyxFQUFBQSxhQUFhLENBQ1hSLFNBRFcsRUFFWEMsYUFGVyxFQUdYQyxjQUhXLEVBSVhDLHFCQUpXLEVBS1g7QUFDQSxRQUFJLENBQUMsS0FBS0MsWUFBTCxDQUFrQkosU0FBbEIsQ0FBTCxFQUFtQztBQUNqQztBQUNEOztBQUNELFVBQU1LLEdBQUcsR0FBRyxLQUFLQyxxQkFBTCxDQUNWTCxhQURVLEVBRVZDLGNBRlUsRUFHVkMscUJBSFUsQ0FBWjs7QUFLQSxTQUFLTixrQkFBTCxDQUF3Qlksc0JBQXhCLENBQStDSixHQUEvQztBQUNEOztBQUVERCxFQUFBQSxZQUFZLENBQUNKLFNBQUQsRUFBNkI7QUFDdkMsV0FBTyxLQUFLTixVQUFMLENBQWdCZ0IsR0FBaEIsQ0FBb0JWLFNBQXBCLENBQVA7QUFDRDs7QUFFRE0sRUFBQUEscUJBQXFCLENBQ25CTCxhQURtQixFQUVuQkMsY0FGbUIsRUFHbkJDLHFCQUhtQixFQUlkO0FBQ0wsVUFBTUUsR0FBRyxHQUFHO0FBQ1ZNLE1BQUFBLE1BQU0sRUFBRVY7QUFERSxLQUFaOztBQUdBLFFBQUlBLGFBQUosRUFBbUI7QUFDakJJLE1BQUFBLEdBQUcsQ0FBQ08sUUFBSixHQUFlVixjQUFmO0FBQ0Q7O0FBQ0QsUUFBSUMscUJBQUosRUFBMkI7QUFDekJFLE1BQUFBLEdBQUcsQ0FBQ0YscUJBQUosR0FBNEJBLHFCQUE1QjtBQUNEOztBQUNELFdBQU9FLEdBQVA7QUFDRDs7QUFyRThCOzs7ZUF3RWxCZCxtQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlQ2xvdWRDb2RlUHVibGlzaGVyIH0gZnJvbSAnLi4vTGl2ZVF1ZXJ5L1BhcnNlQ2xvdWRDb2RlUHVibGlzaGVyJztcbmltcG9ydCB7IExpdmVRdWVyeU9wdGlvbnMgfSBmcm9tICcuLi9PcHRpb25zJztcbmV4cG9ydCBjbGFzcyBMaXZlUXVlcnlDb250cm9sbGVyIHtcbiAgY2xhc3NOYW1lczogYW55O1xuICBsaXZlUXVlcnlQdWJsaXNoZXI6IGFueTtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6ID9MaXZlUXVlcnlPcHRpb25zKSB7XG4gICAgLy8gSWYgY29uZmlnIGlzIGVtcHR5LCB3ZSBqdXN0IGFzc3VtZSBubyBjbGFzc3MgbmVlZHMgdG8gYmUgcmVnaXN0ZXJlZCBhcyBMaXZlUXVlcnlcbiAgICBpZiAoIWNvbmZpZyB8fCAhY29uZmlnLmNsYXNzTmFtZXMpIHtcbiAgICAgIHRoaXMuY2xhc3NOYW1lcyA9IG5ldyBTZXQoKTtcbiAgICB9IGVsc2UgaWYgKGNvbmZpZy5jbGFzc05hbWVzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgIHRoaXMuY2xhc3NOYW1lcyA9IG5ldyBTZXQoY29uZmlnLmNsYXNzTmFtZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyAnbGl2ZVF1ZXJ5LmNsYXNzZXMgc2hvdWxkIGJlIGFuIGFycmF5IG9mIHN0cmluZyc7XG4gICAgfVxuICAgIHRoaXMubGl2ZVF1ZXJ5UHVibGlzaGVyID0gbmV3IFBhcnNlQ2xvdWRDb2RlUHVibGlzaGVyKGNvbmZpZyk7XG4gIH1cblxuICBvbkFmdGVyU2F2ZShcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBjdXJyZW50T2JqZWN0OiBhbnksXG4gICAgb3JpZ2luYWxPYmplY3Q6IGFueSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6ID9hbnlcbiAgKSB7XG4gICAgaWYgKCF0aGlzLmhhc0xpdmVRdWVyeShjbGFzc05hbWUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHJlcSA9IHRoaXMuX21ha2VQdWJsaXNoZXJSZXF1ZXN0KFxuICAgICAgY3VycmVudE9iamVjdCxcbiAgICAgIG9yaWdpbmFsT2JqZWN0LFxuICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zXG4gICAgKTtcbiAgICB0aGlzLmxpdmVRdWVyeVB1Ymxpc2hlci5vbkNsb3VkQ29kZUFmdGVyU2F2ZShyZXEpO1xuICB9XG5cbiAgb25BZnRlckRlbGV0ZShcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBjdXJyZW50T2JqZWN0OiBhbnksXG4gICAgb3JpZ2luYWxPYmplY3Q6IGFueSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IGFueVxuICApIHtcbiAgICBpZiAoIXRoaXMuaGFzTGl2ZVF1ZXJ5KGNsYXNzTmFtZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcmVxID0gdGhpcy5fbWFrZVB1Ymxpc2hlclJlcXVlc3QoXG4gICAgICBjdXJyZW50T2JqZWN0LFxuICAgICAgb3JpZ2luYWxPYmplY3QsXG4gICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnNcbiAgICApO1xuICAgIHRoaXMubGl2ZVF1ZXJ5UHVibGlzaGVyLm9uQ2xvdWRDb2RlQWZ0ZXJEZWxldGUocmVxKTtcbiAgfVxuXG4gIGhhc0xpdmVRdWVyeShjbGFzc05hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNsYXNzTmFtZXMuaGFzKGNsYXNzTmFtZSk7XG4gIH1cblxuICBfbWFrZVB1Ymxpc2hlclJlcXVlc3QoXG4gICAgY3VycmVudE9iamVjdDogYW55LFxuICAgIG9yaWdpbmFsT2JqZWN0OiBhbnksXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiA/YW55XG4gICk6IGFueSB7XG4gICAgY29uc3QgcmVxID0ge1xuICAgICAgb2JqZWN0OiBjdXJyZW50T2JqZWN0LFxuICAgIH07XG4gICAgaWYgKGN1cnJlbnRPYmplY3QpIHtcbiAgICAgIHJlcS5vcmlnaW5hbCA9IG9yaWdpbmFsT2JqZWN0O1xuICAgIH1cbiAgICBpZiAoY2xhc3NMZXZlbFBlcm1pc3Npb25zKSB7XG4gICAgICByZXEuY2xhc3NMZXZlbFBlcm1pc3Npb25zID0gY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgIH1cbiAgICByZXR1cm4gcmVxO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IExpdmVRdWVyeUNvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/LoggerController.js b/lib/Controllers/LoggerController.js new file mode 100644 index 0000000000..90514aaac1 --- /dev/null +++ b/lib/Controllers/LoggerController.js @@ -0,0 +1,265 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.LoggerController = exports.LogOrder = exports.LogLevel = void 0; + +var _node = require("parse/node"); + +var _AdaptableController = _interopRequireDefault(require("./AdaptableController")); + +var _LoggerAdapter = require("../Adapters/Logger/LoggerAdapter"); + +var _url = _interopRequireDefault(require("url")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000; +const LOG_STRING_TRUNCATE_LENGTH = 1000; +const truncationMarker = '... (truncated)'; +const LogLevel = { + INFO: 'info', + ERROR: 'error' +}; +exports.LogLevel = LogLevel; +const LogOrder = { + DESCENDING: 'desc', + ASCENDING: 'asc' +}; +exports.LogOrder = LogOrder; +const logLevels = ['error', 'warn', 'info', 'debug', 'verbose', 'silly']; + +class LoggerController extends _AdaptableController.default { + constructor(adapter, appId, options = { + logLevel: 'info' + }) { + super(adapter, appId, options); + let level = 'info'; + + if (options.verbose) { + level = 'verbose'; + } + + if (options.logLevel) { + level = options.logLevel; + } + + const index = logLevels.indexOf(level); // info by default + + logLevels.forEach((level, levelIndex) => { + if (levelIndex > index) { + // silence the levels that are > maxIndex + this[level] = () => {}; + } + }); + } + + maskSensitiveUrl(urlString) { + const urlObj = _url.default.parse(urlString, true); + + const query = urlObj.query; + let sanitizedQuery = '?'; + + for (const key in query) { + if (key !== 'password') { + // normal value + sanitizedQuery += key + '=' + query[key] + '&'; + } else { + // password value, redact it + sanitizedQuery += key + '=' + '********' + '&'; + } + } // trim last character, ? or & + + + sanitizedQuery = sanitizedQuery.slice(0, -1); // return original path name with sanitized params attached + + return urlObj.pathname + sanitizedQuery; + } + + maskSensitive(argArray) { + return argArray.map(e => { + if (!e) { + return e; + } + + if (typeof e === 'string') { + return e.replace(/(password".?:.?")[^"]*"/g, '$1********"'); + } // else it is an object... + // check the url + + + if (e.url) { + // for strings + if (typeof e.url === 'string') { + e.url = this.maskSensitiveUrl(e.url); + } else if (Array.isArray(e.url)) { + // for strings in array + e.url = e.url.map(item => { + if (typeof item === 'string') { + return this.maskSensitiveUrl(item); + } + + return item; + }); + } + } + + if (e.body) { + for (const key of Object.keys(e.body)) { + if (key === 'password') { + e.body[key] = '********'; + break; + } + } + } + + if (e.params) { + for (const key of Object.keys(e.params)) { + if (key === 'password') { + e.params[key] = '********'; + break; + } + } + } + + return e; + }); + } + + log(level, args) { + // make the passed in arguments object an array with the spread operator + args = this.maskSensitive([...args]); + args = [].concat(level, args.map(arg => { + if (typeof arg === 'function') { + return arg(); + } + + return arg; + })); + this.adapter.log.apply(this.adapter, args); + } + + info() { + return this.log('info', arguments); + } + + error() { + return this.log('error', arguments); + } + + warn() { + return this.log('warn', arguments); + } + + verbose() { + return this.log('verbose', arguments); + } + + debug() { + return this.log('debug', arguments); + } + + silly() { + return this.log('silly', arguments); + } + + logRequest({ + method, + url, + headers, + body + }) { + this.verbose(() => { + const stringifiedBody = JSON.stringify(body, null, 2); + return `REQUEST for [${method}] ${url}: ${stringifiedBody}`; + }, { + method, + url, + headers, + body + }); + } + + logResponse({ + method, + url, + result + }) { + this.verbose(() => { + const stringifiedResponse = JSON.stringify(result, null, 2); + return `RESPONSE from [${method}] ${url}: ${stringifiedResponse}`; + }, { + result: result + }); + } // check that date input is valid + + + static validDateTime(date) { + if (!date) { + return null; + } + + date = new Date(date); + + if (!isNaN(date.getTime())) { + return date; + } + + return null; + } + + truncateLogMessage(string) { + if (string && string.length > LOG_STRING_TRUNCATE_LENGTH) { + const truncated = string.substring(0, LOG_STRING_TRUNCATE_LENGTH) + truncationMarker; + return truncated; + } + + return string; + } + + static parseOptions(options = {}) { + const from = LoggerController.validDateTime(options.from) || new Date(Date.now() - 7 * MILLISECONDS_IN_A_DAY); + const until = LoggerController.validDateTime(options.until) || new Date(); + const size = Number(options.size) || 10; + const order = options.order || LogOrder.DESCENDING; + const level = options.level || LogLevel.INFO; + return { + from, + until, + size, + order, + level + }; + } // Returns a promise for a {response} object. + // query params: + // level (optional) Level of logging you want to query for (info || error) + // from (optional) Start time for the search. Defaults to 1 week ago. + // until (optional) End time for the search. Defaults to current time. + // order (optional) Direction of results returned, either “asc” or “desc”. Defaults to “desc”. + // size (optional) Number of rows returned by search. Defaults to 10 + + + getLogs(options = {}) { + if (!this.adapter) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Logger adapter is not available'); + } + + if (typeof this.adapter.query !== 'function') { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Querying logs is not supported with this adapter'); + } + + options = LoggerController.parseOptions(options); + return this.adapter.query(options); + } + + expectedAdapterType() { + return _LoggerAdapter.LoggerAdapter; + } + +} + +exports.LoggerController = LoggerController; +var _default = LoggerController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9Mb2dnZXJDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIk1JTExJU0VDT05EU19JTl9BX0RBWSIsIkxPR19TVFJJTkdfVFJVTkNBVEVfTEVOR1RIIiwidHJ1bmNhdGlvbk1hcmtlciIsIkxvZ0xldmVsIiwiSU5GTyIsIkVSUk9SIiwiTG9nT3JkZXIiLCJERVNDRU5ESU5HIiwiQVNDRU5ESU5HIiwibG9nTGV2ZWxzIiwiTG9nZ2VyQ29udHJvbGxlciIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImFkYXB0ZXIiLCJhcHBJZCIsIm9wdGlvbnMiLCJsb2dMZXZlbCIsImxldmVsIiwidmVyYm9zZSIsImluZGV4IiwiaW5kZXhPZiIsImZvckVhY2giLCJsZXZlbEluZGV4IiwibWFza1NlbnNpdGl2ZVVybCIsInVybFN0cmluZyIsInVybE9iaiIsInVybCIsInBhcnNlIiwicXVlcnkiLCJzYW5pdGl6ZWRRdWVyeSIsImtleSIsInNsaWNlIiwicGF0aG5hbWUiLCJtYXNrU2Vuc2l0aXZlIiwiYXJnQXJyYXkiLCJtYXAiLCJlIiwicmVwbGFjZSIsIkFycmF5IiwiaXNBcnJheSIsIml0ZW0iLCJib2R5IiwiT2JqZWN0Iiwia2V5cyIsInBhcmFtcyIsImxvZyIsImFyZ3MiLCJjb25jYXQiLCJhcmciLCJhcHBseSIsImluZm8iLCJhcmd1bWVudHMiLCJlcnJvciIsIndhcm4iLCJkZWJ1ZyIsInNpbGx5IiwibG9nUmVxdWVzdCIsIm1ldGhvZCIsImhlYWRlcnMiLCJzdHJpbmdpZmllZEJvZHkiLCJKU09OIiwic3RyaW5naWZ5IiwibG9nUmVzcG9uc2UiLCJyZXN1bHQiLCJzdHJpbmdpZmllZFJlc3BvbnNlIiwidmFsaWREYXRlVGltZSIsImRhdGUiLCJEYXRlIiwiaXNOYU4iLCJnZXRUaW1lIiwidHJ1bmNhdGVMb2dNZXNzYWdlIiwic3RyaW5nIiwibGVuZ3RoIiwidHJ1bmNhdGVkIiwic3Vic3RyaW5nIiwicGFyc2VPcHRpb25zIiwiZnJvbSIsIm5vdyIsInVudGlsIiwic2l6ZSIsIk51bWJlciIsIm9yZGVyIiwiZ2V0TG9ncyIsIlBhcnNlIiwiRXJyb3IiLCJQVVNIX01JU0NPTkZJR1VSRUQiLCJleHBlY3RlZEFkYXB0ZXJUeXBlIiwiTG9nZ2VyQWRhcHRlciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEscUJBQXFCLEdBQUcsS0FBSyxFQUFMLEdBQVUsRUFBVixHQUFlLElBQTdDO0FBQ0EsTUFBTUMsMEJBQTBCLEdBQUcsSUFBbkM7QUFDQSxNQUFNQyxnQkFBZ0IsR0FBRyxpQkFBekI7QUFFTyxNQUFNQyxRQUFRLEdBQUc7QUFDdEJDLEVBQUFBLElBQUksRUFBRSxNQURnQjtBQUV0QkMsRUFBQUEsS0FBSyxFQUFFO0FBRmUsQ0FBakI7O0FBS0EsTUFBTUMsUUFBUSxHQUFHO0FBQ3RCQyxFQUFBQSxVQUFVLEVBQUUsTUFEVTtBQUV0QkMsRUFBQUEsU0FBUyxFQUFFO0FBRlcsQ0FBakI7O0FBS1AsTUFBTUMsU0FBUyxHQUFHLENBQUMsT0FBRCxFQUFVLE1BQVYsRUFBa0IsTUFBbEIsRUFBMEIsT0FBMUIsRUFBbUMsU0FBbkMsRUFBOEMsT0FBOUMsQ0FBbEI7O0FBRU8sTUFBTUMsZ0JBQU4sU0FBK0JDLDRCQUEvQixDQUFtRDtBQUN4REMsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQVVDLEtBQVYsRUFBaUJDLE9BQU8sR0FBRztBQUFFQyxJQUFBQSxRQUFRLEVBQUU7QUFBWixHQUEzQixFQUFpRDtBQUMxRCxVQUFNSCxPQUFOLEVBQWVDLEtBQWYsRUFBc0JDLE9BQXRCO0FBQ0EsUUFBSUUsS0FBSyxHQUFHLE1BQVo7O0FBQ0EsUUFBSUYsT0FBTyxDQUFDRyxPQUFaLEVBQXFCO0FBQ25CRCxNQUFBQSxLQUFLLEdBQUcsU0FBUjtBQUNEOztBQUNELFFBQUlGLE9BQU8sQ0FBQ0MsUUFBWixFQUFzQjtBQUNwQkMsTUFBQUEsS0FBSyxHQUFHRixPQUFPLENBQUND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LEtBSks7QUFLTGhFLE1BQUFBO0FBTEssS0FBUDtBQU9ELEdBbE11RCxDQW9NeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBaUUsRUFBQUEsT0FBTyxDQUFDbkUsT0FBTyxHQUFHLEVBQVgsRUFBZTtBQUNwQixRQUFJLENBQUMsS0FBS0YsT0FBVixFQUFtQjtBQUNqQixZQUFNLElBQUlzRSxZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRFIsRUFFSixpQ0FGSSxDQUFOO0FBSUQ7O0FBQ0QsUUFBSSxPQUFPLEtBQUt4RSxPQUFMLENBQWFlLEtBQXBCLEtBQThCLFVBQWxDLEVBQThDO0FBQzVDLFlBQU0sSUFBSXVELFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKLGtEQUZJLENBQU47QUFJRDs7QUFDRHRFLElBQUFBLE9BQU8sR0FBR0wsZ0JBQWdCLENBQUNpRSxZQUFqQixDQUE4QjVELE9BQTlCLENBQVY7QUFDQSxXQUFPLEtBQUtGLE9BQUwsQ0FBYWUsS0FBYixDQUFtQmIsT0FBbkIsQ0FBUDtBQUNEOztBQUVEdUUsRUFBQUEsbUJBQW1CLEdBQUc7QUFDcEIsV0FBT0MsNEJBQVA7QUFDRDs7QUE5TnVEOzs7ZUFpTzNDN0UsZ0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9IGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IEFkYXB0YWJsZUNvbnRyb2xsZXIgZnJvbSAnLi9BZGFwdGFibGVDb250cm9sbGVyJztcbmltcG9ydCB7IExvZ2dlckFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9Mb2dnZXIvTG9nZ2VyQWRhcHRlcic7XG5pbXBvcnQgdXJsIGZyb20gJ3VybCc7XG5cbmNvbnN0IE1JTExJU0VDT05EU19JTl9BX0RBWSA9IDI0ICogNjAgKiA2MCAqIDEwMDA7XG5jb25zdCBMT0dfU1RSSU5HX1RSVU5DQVRFX0xFTkdUSCA9IDEwMDA7XG5jb25zdCB0cnVuY2F0aW9uTWFya2VyID0gJy4uLiAodHJ1bmNhdGVkKSc7XG5cbmV4cG9ydCBjb25zdCBMb2dMZXZlbCA9IHtcbiAgSU5GTzogJ2luZm8nLFxuICBFUlJPUjogJ2Vycm9yJyxcbn07XG5cbmV4cG9ydCBjb25zdCBMb2dPcmRlciA9IHtcbiAgREVTQ0VORElORzogJ2Rlc2MnLFxuICBBU0NFTkRJTkc6ICdhc2MnLFxufTtcblxuY29uc3QgbG9nTGV2ZWxzID0gWydlcnJvcicsICd3YXJuJywgJ2luZm8nLCAnZGVidWcnLCAndmVyYm9zZScsICdzaWxseSddO1xuXG5leHBvcnQgY2xhc3MgTG9nZ2VyQ29udHJvbGxlciBleHRlbmRzIEFkYXB0YWJsZUNvbnRyb2xsZXIge1xuICBjb25zdHJ1Y3RvcihhZGFwdGVyLCBhcHBJZCwgb3B0aW9ucyA9IHsgbG9nTGV2ZWw6ICdpbmZvJyB9KSB7XG4gICAgc3VwZXIoYWRhcHRlciwgYXBwSWQsIG9wdGlvbnMpO1xuICAgIGxldCBsZXZlbCA9ICdpbmZvJztcbiAgICBpZiAob3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICBsZXZlbCA9ICd2ZXJib3NlJztcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMubG9nTGV2ZWwpIHtcbiAgICAgIGxldmVsID0gb3B0aW9ucy5sb2dMZXZlbDtcbiAgICB9XG4gICAgY29uc3QgaW5kZXggPSBsb2dMZXZlbHMuaW5kZXhPZihsZXZlbCk7IC8vIGluZm8gYnkgZGVmYXVsdFxuICAgIGxvZ0xldmVscy5mb3JFYWNoKChsZXZlbCwgbGV2ZWxJbmRleCkgPT4ge1xuICAgICAgaWYgKGxldmVsSW5kZXggPiBpbmRleCkge1xuICAgICAgICAvLyBzaWxlbmNlIHRoZSBsZXZlbHMgdGhhdCBhcmUgPiBtYXhJbmRleFxuICAgICAgICB0aGlzW2xldmVsXSA9ICgpID0+IHt9O1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgbWFza1NlbnNpdGl2ZVVybCh1cmxTdHJpbmcpIHtcbiAgICBjb25zdCB1cmxPYmogPSB1cmwucGFyc2UodXJsU3RyaW5nLCB0cnVlKTtcbiAgICBjb25zdCBxdWVyeSA9IHVybE9iai5xdWVyeTtcbiAgICBsZXQgc2FuaXRpemVkUXVlcnkgPSAnPyc7XG5cbiAgICBmb3IgKGNvbnN0IGtleSBpbiBxdWVyeSkge1xuICAgICAgaWYgKGtleSAhPT0gJ3Bhc3N3b3JkJykge1xuICAgICAgICAvLyBub3JtYWwgdmFsdWVcbiAgICAgICAgc2FuaXRpemVkUXVlcnkgKz0ga2V5ICsgJz0nICsgcXVlcnlba2V5XSArICcmJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHBhc3N3b3JkIHZhbHVlLCByZWRhY3QgaXRcbiAgICAgICAgc2FuaXRpemVkUXVlcnkgKz0ga2V5ICsgJz0nICsgJyoqKioqKioqJyArICcmJztcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0cmltIGxhc3QgY2hhcmFjdGVyLCA/IG9yICZcbiAgICBzYW5pdGl6ZWRRdWVyeSA9IHNhbml0aXplZFF1ZXJ5LnNsaWNlKDAsIC0xKTtcblxuICAgIC8vIHJldHVybiBvcmlnaW5hbCBwYXRoIG5hbWUgd2l0aCBzYW5pdGl6ZWQgcGFyYW1zIGF0dGFjaGVkXG4gICAgcmV0dXJuIHVybE9iai5wYXRobmFtZSArIHNhbml0aXplZFF1ZXJ5O1xuICB9XG5cbiAgbWFza1NlbnNpdGl2ZShhcmdBcnJheSkge1xuICAgIHJldHVybiBhcmdBcnJheS5tYXAoZSA9PiB7XG4gICAgICBpZiAoIWUpIHtcbiAgICAgICAgcmV0dXJuIGU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGUucmVwbGFjZSgvKHBhc3N3b3JkXCIuPzouP1wiKVteXCJdKlwiL2csICckMSoqKioqKioqXCInKTtcbiAgICAgIH1cbiAgICAgIC8vIGVsc2UgaXQgaXMgYW4gb2JqZWN0Li4uXG5cbiAgICAgIC8vIGNoZWNrIHRoZSB1cmxcbiAgICAgIGlmIChlLnVybCkge1xuICAgICAgICAvLyBmb3Igc3RyaW5nc1xuICAgICAgICBpZiAodHlwZW9mIGUudXJsID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGUudXJsID0gdGhpcy5tYXNrU2Vuc2l0aXZlVXJsKGUudXJsKTtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGUudXJsKSkge1xuICAgICAgICAgIC8vIGZvciBzdHJpbmdzIGluIGFycmF5XG4gICAgICAgICAgZS51cmwgPSBlLnVybC5tYXAoaXRlbSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLm1hc2tTZW5zaXRpdmVVcmwoaXRlbSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChlLmJvZHkpIHtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoZS5ib2R5KSkge1xuICAgICAgICAgIGlmIChrZXkgPT09ICdwYXNzd29yZCcpIHtcbiAgICAgICAgICAgIGUuYm9keVtrZXldID0gJyoqKioqKioqJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZS5wYXJhbXMpIHtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoZS5wYXJhbXMpKSB7XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3Bhc3N3b3JkJykge1xuICAgICAgICAgICAgZS5wYXJhbXNba2V5XSA9ICcqKioqKioqKic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGU7XG4gICAgfSk7XG4gIH1cblxuICBsb2cobGV2ZWwsIGFyZ3MpIHtcbiAgICAvLyBtYWtlIHRoZSBwYXNzZWQgaW4gYXJndW1lbnRzIG9iamVjdCBhbiBhcnJheSB3aXRoIHRoZSBzcHJlYWQgb3BlcmF0b3JcbiAgICBhcmdzID0gdGhpcy5tYXNrU2Vuc2l0aXZlKFsuLi5hcmdzXSk7XG4gICAgYXJncyA9IFtdLmNvbmNhdChcbiAgICAgIGxldmVsLFxuICAgICAgYXJncy5tYXAoYXJnID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICByZXR1cm4gYXJnKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFyZztcbiAgICAgIH0pXG4gICAgKTtcbiAgICB0aGlzLmFkYXB0ZXIubG9nLmFwcGx5KHRoaXMuYWRhcHRlciwgYXJncyk7XG4gIH1cblxuICBpbmZvKCkge1xuICAgIHJldHVybiB0aGlzLmxvZygnaW5mbycsIGFyZ3VtZW50cyk7XG4gIH1cblxuICBlcnJvcigpIHtcbiAgICByZXR1cm4gdGhpcy5sb2coJ2Vycm9yJywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHdhcm4oKSB7XG4gICAgcmV0dXJuIHRoaXMubG9nKCd3YXJuJywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHZlcmJvc2UoKSB7XG4gICAgcmV0dXJuIHRoaXMubG9nKCd2ZXJib3NlJywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIGRlYnVnKCkge1xuICAgIHJldHVybiB0aGlzLmxvZygnZGVidWcnLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgc2lsbHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubG9nKCdzaWxseScsIGFyZ3VtZW50cyk7XG4gIH1cblxuICBsb2dSZXF1ZXN0KHsgbWV0aG9kLCB1cmwsIGhlYWRlcnMsIGJvZHkgfSkge1xuICAgIHRoaXMudmVyYm9zZShcbiAgICAgICgpID0+IHtcbiAgICAgICAgY29uc3Qgc3RyaW5naWZpZWRCb2R5ID0gSlNPTi5zdHJpbmdpZnkoYm9keSwgbnVsbCwgMik7XG4gICAgICAgIHJldHVybiBgUkVRVUVTVCBmb3IgWyR7bWV0aG9kfV0gJHt1cmx9OiAke3N0cmluZ2lmaWVkQm9keX1gO1xuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICB1cmwsXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIGJvZHksXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIGxvZ1Jlc3BvbnNlKHsgbWV0aG9kLCB1cmwsIHJlc3VsdCB9KSB7XG4gICAgdGhpcy52ZXJib3NlKFxuICAgICAgKCkgPT4ge1xuICAgICAgICBjb25zdCBzdHJpbmdpZmllZFJlc3BvbnNlID0gSlNPTi5zdHJpbmdpZnkocmVzdWx0LCBudWxsLCAyKTtcbiAgICAgICAgcmV0dXJuIGBSRVNQT05TRSBmcm9tIFske21ldGhvZH1dICR7dXJsfTogJHtzdHJpbmdpZmllZFJlc3BvbnNlfWA7XG4gICAgICB9LFxuICAgICAgeyByZXN1bHQ6IHJlc3VsdCB9XG4gICAgKTtcbiAgfVxuICAvLyBjaGVjayB0aGF0IGRhdGUgaW5wdXQgaXMgdmFsaWRcbiAgc3RhdGljIHZhbGlkRGF0ZVRpbWUoZGF0ZSkge1xuICAgIGlmICghZGF0ZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRhdGUgPSBuZXcgRGF0ZShkYXRlKTtcblxuICAgIGlmICghaXNOYU4oZGF0ZS5nZXRUaW1lKCkpKSB7XG4gICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHRydW5jYXRlTG9nTWVzc2FnZShzdHJpbmcpIHtcbiAgICBpZiAoc3RyaW5nICYmIHN0cmluZy5sZW5ndGggPiBMT0dfU1RSSU5HX1RSVU5DQVRFX0xFTkdUSCkge1xuICAgICAgY29uc3QgdHJ1bmNhdGVkID1cbiAgICAgICAgc3RyaW5nLnN1YnN0cmluZygwLCBMT0dfU1RSSU5HX1RSVU5DQVRFX0xFTkdUSCkgKyB0cnVuY2F0aW9uTWFya2VyO1xuICAgICAgcmV0dXJuIHRydW5jYXRlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc3RyaW5nO1xuICB9XG5cbiAgc3RhdGljIHBhcnNlT3B0aW9ucyhvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBmcm9tID1cbiAgICAgIExvZ2dlckNvbnRyb2xsZXIudmFsaWREYXRlVGltZShvcHRpb25zLmZyb20pIHx8XG4gICAgICBuZXcgRGF0ZShEYXRlLm5vdygpIC0gNyAqIE1JTExJU0VDT05EU19JTl9BX0RBWSk7XG4gICAgY29uc3QgdW50aWwgPSBMb2dnZXJDb250cm9sbGVyLnZhbGlkRGF0ZVRpbWUob3B0aW9ucy51bnRpbCkgfHwgbmV3IERhdGUoKTtcbiAgICBjb25zdCBzaXplID0gTnVtYmVyKG9wdGlvbnMuc2l6ZSkgfHwgMTA7XG4gICAgY29uc3Qgb3JkZXIgPSBvcHRpb25zLm9yZGVyIHx8IExvZ09yZGVyLkRFU0NFTkRJTkc7XG4gICAgY29uc3QgbGV2ZWwgPSBvcHRpb25zLmxldmVsIHx8IExvZ0xldmVsLklORk87XG5cbiAgICByZXR1cm4ge1xuICAgICAgZnJvbSxcbiAgICAgIHVudGlsLFxuICAgICAgc2l6ZSxcbiAgICAgIG9yZGVyLFxuICAgICAgbGV2ZWwsXG4gICAgfTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHtyZXNwb25zZX0gb2JqZWN0LlxuICAvLyBxdWVyeSBwYXJhbXM6XG4gIC8vIGxldmVsIChvcHRpb25hbCkgTGV2ZWwgb2YgbG9nZ2luZyB5b3Ugd2FudCB0byBxdWVyeSBmb3IgKGluZm8gfHwgZXJyb3IpXG4gIC8vIGZyb20gKG9wdGlvbmFsKSBTdGFydCB0aW1lIGZvciB0aGUgc2VhcmNoLiBEZWZhdWx0cyB0byAxIHdlZWsgYWdvLlxuICAvLyB1bnRpbCAob3B0aW9uYWwpIEVuZCB0aW1lIGZvciB0aGUgc2VhcmNoLiBEZWZhdWx0cyB0byBjdXJyZW50IHRpbWUuXG4gIC8vIG9yZGVyIChvcHRpb25hbCkgRGlyZWN0aW9uIG9mIHJlc3VsdHMgcmV0dXJuZWQsIGVpdGhlciDigJxhc2PigJ0gb3Ig4oCcZGVzY+KAnS4gRGVmYXVsdHMgdG8g4oCcZGVzY+KAnS5cbiAgLy8gc2l6ZSAob3B0aW9uYWwpIE51bWJlciBvZiByb3dzIHJldHVybmVkIGJ5IHNlYXJjaC4gRGVmYXVsdHMgdG8gMTBcbiAgZ2V0TG9ncyhvcHRpb25zID0ge30pIHtcbiAgICBpZiAoIXRoaXMuYWRhcHRlcikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdMb2dnZXIgYWRhcHRlciBpcyBub3QgYXZhaWxhYmxlJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB0aGlzLmFkYXB0ZXIucXVlcnkgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnUXVlcnlpbmcgbG9ncyBpcyBub3Qgc3VwcG9ydGVkIHdpdGggdGhpcyBhZGFwdGVyJ1xuICAgICAgKTtcbiAgICB9XG4gICAgb3B0aW9ucyA9IExvZ2dlckNvbnRyb2xsZXIucGFyc2VPcHRpb25zKG9wdGlvbnMpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucXVlcnkob3B0aW9ucyk7XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHJldHVybiBMb2dnZXJBZGFwdGVyO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IExvZ2dlckNvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/ParseGraphQLController.js b/lib/Controllers/ParseGraphQLController.js new file mode 100644 index 0000000000..3d23454926 --- /dev/null +++ b/lib/Controllers/ParseGraphQLController.js @@ -0,0 +1,337 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.GraphQLConfigKey = exports.GraphQLConfigId = exports.GraphQLConfigClassName = exports.default = void 0; + +var _requiredParameter = _interopRequireDefault(require("../../lib/requiredParameter")); + +var _DatabaseController = _interopRequireDefault(require("./DatabaseController")); + +var _CacheController = _interopRequireDefault(require("./CacheController")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } + +function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const GraphQLConfigClassName = '_GraphQLConfig'; +exports.GraphQLConfigClassName = GraphQLConfigClassName; +const GraphQLConfigId = '1'; +exports.GraphQLConfigId = GraphQLConfigId; +const GraphQLConfigKey = 'config'; +exports.GraphQLConfigKey = GraphQLConfigKey; + +class ParseGraphQLController { + constructor(params = {}) { + this.databaseController = params.databaseController || (0, _requiredParameter.default)(`ParseGraphQLController requires a "databaseController" to be instantiated.`); + this.cacheController = params.cacheController; + this.isMounted = !!params.mountGraphQL; + this.configCacheKey = GraphQLConfigKey; + } + + async getGraphQLConfig() { + if (this.isMounted) { + const _cachedConfig = await this._getCachedGraphQLConfig(); + + if (_cachedConfig) { + return _cachedConfig; + } + } + + const results = await this.databaseController.find(GraphQLConfigClassName, { + objectId: GraphQLConfigId + }, { + limit: 1 + }); + let graphQLConfig; + + if (results.length != 1) { + // If there is no config in the database - return empty config. + return {}; + } else { + graphQLConfig = results[0][GraphQLConfigKey]; + } + + if (this.isMounted) { + this._putCachedGraphQLConfig(graphQLConfig); + } + + return graphQLConfig; + } + + async updateGraphQLConfig(graphQLConfig) { + // throws if invalid + this._validateGraphQLConfig(graphQLConfig || (0, _requiredParameter.default)('You must provide a graphQLConfig!')); // Transform in dot notation to make sure it works + + + const update = Object.keys(graphQLConfig).reduce((acc, key) => { + return { + [GraphQLConfigKey]: _objectSpread({}, acc[GraphQLConfigKey], { + [key]: graphQLConfig[key] + }) + }; + }, { + [GraphQLConfigKey]: {} + }); + await this.databaseController.update(GraphQLConfigClassName, { + objectId: GraphQLConfigId + }, update, { + upsert: true + }); + + if (this.isMounted) { + this._putCachedGraphQLConfig(graphQLConfig); + } + + return { + response: { + result: true + } + }; + } + + _getCachedGraphQLConfig() { + return this.cacheController.graphQL.get(this.configCacheKey); + } + + _putCachedGraphQLConfig(graphQLConfig) { + return this.cacheController.graphQL.put(this.configCacheKey, graphQLConfig, 60000); + } + + _validateGraphQLConfig(graphQLConfig) { + const errorMessages = []; + + if (!graphQLConfig) { + errorMessages.push('cannot be undefined, null or empty'); + } else if (!isValidSimpleObject(graphQLConfig)) { + errorMessages.push('must be a valid object'); + } else { + const { + enabledForClasses = null, + disabledForClasses = null, + classConfigs = null + } = graphQLConfig, + invalidKeys = _objectWithoutProperties(graphQLConfig, ["enabledForClasses", "disabledForClasses", "classConfigs"]); + + if (Object.keys(invalidKeys).length) { + errorMessages.push(`encountered invalid keys: [${Object.keys(invalidKeys)}]`); + } + + if (enabledForClasses !== null && !isValidStringArray(enabledForClasses)) { + errorMessages.push(`"enabledForClasses" is not a valid array`); + } + + if (disabledForClasses !== null && !isValidStringArray(disabledForClasses)) { + errorMessages.push(`"disabledForClasses" is not a valid array`); + } + + if (classConfigs !== null) { + if (Array.isArray(classConfigs)) { + classConfigs.forEach(classConfig => { + const errorMessage = this._validateClassConfig(classConfig); + + if (errorMessage) { + errorMessages.push(`classConfig:${classConfig.className} is invalid because ${errorMessage}`); + } + }); + } else { + errorMessages.push(`"classConfigs" is not a valid array`); + } + } + } + + if (errorMessages.length) { + throw new Error(`Invalid graphQLConfig: ${errorMessages.join('; ')}`); + } + } + + _validateClassConfig(classConfig) { + if (!isValidSimpleObject(classConfig)) { + return 'it must be a valid object'; + } else { + const { + className, + type = null, + query = null, + mutation = null + } = classConfig, + invalidKeys = _objectWithoutProperties(classConfig, ["className", "type", "query", "mutation"]); + + if (Object.keys(invalidKeys).length) { + return `"invalidKeys" [${Object.keys(invalidKeys)}] should not be present`; + } + + if (typeof className !== 'string' || !className.trim().length) { + // TODO consider checking class exists in schema? + return `"className" must be a valid string`; + } + + if (type !== null) { + if (!isValidSimpleObject(type)) { + return `"type" must be a valid object`; + } + + const { + inputFields = null, + outputFields = null, + constraintFields = null, + sortFields = null + } = type, + invalidKeys = _objectWithoutProperties(type, ["inputFields", "outputFields", "constraintFields", "sortFields"]); + + if (Object.keys(invalidKeys).length) { + return `"type" contains invalid keys, [${Object.keys(invalidKeys)}]`; + } else if (outputFields !== null && !isValidStringArray(outputFields)) { + return `"outputFields" must be a valid string array`; + } else if (constraintFields !== null && !isValidStringArray(constraintFields)) { + return `"constraintFields" must be a valid string array`; + } + + if (sortFields !== null) { + if (Array.isArray(sortFields)) { + let errorMessage; + sortFields.every((sortField, index) => { + if (!isValidSimpleObject(sortField)) { + errorMessage = `"sortField" at index ${index} is not a valid object`; + return false; + } else { + const { + field, + asc, + desc + } = sortField, + invalidKeys = _objectWithoutProperties(sortField, ["field", "asc", "desc"]); + + if (Object.keys(invalidKeys).length) { + errorMessage = `"sortField" at index ${index} contains invalid keys, [${Object.keys(invalidKeys)}]`; + return false; + } else { + if (typeof field !== 'string' || field.trim().length === 0) { + errorMessage = `"sortField" at index ${index} did not provide the "field" as a string`; + return false; + } else if (typeof asc !== 'boolean' || typeof desc !== 'boolean') { + errorMessage = `"sortField" at index ${index} did not provide "asc" or "desc" as booleans`; + return false; + } + } + } + + return true; + }); + + if (errorMessage) { + return errorMessage; + } + } else { + return `"sortFields" must be a valid array.`; + } + } + + if (inputFields !== null) { + if (isValidSimpleObject(inputFields)) { + const { + create = null, + update = null + } = inputFields, + invalidKeys = _objectWithoutProperties(inputFields, ["create", "update"]); + + if (Object.keys(invalidKeys).length) { + return `"inputFields" contains invalid keys: [${Object.keys(invalidKeys)}]`; + } else { + if (update !== null && !isValidStringArray(update)) { + return `"inputFields.update" must be a valid string array`; + } else if (create !== null) { + if (!isValidStringArray(create)) { + return `"inputFields.create" must be a valid string array`; + } else if (className === '_User') { + if (!create.includes('username') || !create.includes('password')) { + return `"inputFields.create" must include required fields, username and password`; + } + } + } + } + } else { + return `"inputFields" must be a valid object`; + } + } + } + + if (query !== null) { + if (isValidSimpleObject(query)) { + const { + find = null, + get = null + } = query, + invalidKeys = _objectWithoutProperties(query, ["find", "get"]); + + if (Object.keys(invalidKeys).length) { + return `"query" contains invalid keys, [${Object.keys(invalidKeys)}]`; + } else if (find !== null && typeof find !== 'boolean') { + return `"query.find" must be a boolean`; + } else if (get !== null && typeof get !== 'boolean') { + return `"query.get" must be a boolean`; + } + } else { + return `"query" must be a valid object`; + } + } + + if (mutation !== null) { + if (isValidSimpleObject(mutation)) { + const { + create = null, + update = null, + destroy = null + } = mutation, + invalidKeys = _objectWithoutProperties(mutation, ["create", "update", "destroy"]); + + if (Object.keys(invalidKeys).length) { + return `"mutation" contains invalid keys, [${Object.keys(invalidKeys)}]`; + } + + if (create !== null && typeof create !== 'boolean') { + return `"mutation.create" must be a boolean`; + } + + if (update !== null && typeof update !== 'boolean') { + return `"mutation.update" must be a boolean`; + } + + if (destroy !== null && typeof destroy !== 'boolean') { + return `"mutation.destroy" must be a boolean`; + } + } else { + return `"mutation" must be a valid object`; + } + } + } + } + +} + +const isValidStringArray = function (array) { + return Array.isArray(array) ? !array.some(s => typeof s !== 'string' || s.trim().length < 1) : false; +}; +/** + * Ensures the obj is a simple JSON/{} + * object, i.e. not an array, null, date + * etc. + */ + + +const isValidSimpleObject = function (obj) { + return typeof obj === 'object' && !Array.isArray(obj) && obj !== null && obj instanceof Date !== true && obj instanceof Promise !== true; +}; + +var _default = ParseGraphQLController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QYXJzZUdyYXBoUUxDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkdyYXBoUUxDb25maWdDbGFzc05hbWUiLCJHcmFwaFFMQ29uZmlnSWQiLCJHcmFwaFFMQ29uZmlnS2V5IiwiUGFyc2VHcmFwaFFMQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwicGFyYW1zIiwiZGF0YWJhc2VDb250cm9sbGVyIiwiY2FjaGVDb250cm9sbGVyIiwiaXNNb3VudGVkIiwibW91bnRHcmFwaFFMIiwiY29uZmlnQ2FjaGVLZXkiLCJnZXRHcmFwaFFMQ29uZmlnIiwiX2NhY2hlZENvbmZpZyIsIl9nZXRDYWNoZWRHcmFwaFFMQ29uZmlnIiwicmVzdWx0cyIsImZpbmQiLCJvYmplY3RJZCIsImxpbWl0IiwiZ3JhcGhRTENvbmZpZyIsImxlbmd0aCIsIl9wdXRDYWNoZWRHcmFwaFFMQ29uZmlnIiwidXBkYXRlR3JhcGhRTENvbmZpZyIsIl92YWxpZGF0ZUdyYXBoUUxDb25maWciLCJ1cGRhdGUiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwiYWNjIiwia2V5IiwidXBzZXJ0IiwicmVzcG9uc2UiLCJyZXN1bHQiLCJncmFwaFFMIiwiZ2V0IiwicHV0IiwiZXJyb3JNZXNzYWdlcyIsInB1c2giLCJpc1ZhbGlkU2ltcGxlT2JqZWN0IiwiZW5hYmxlZEZvckNsYXNzZXMiLCJkaXNhYmxlZEZvckNsYXNzZXMiLCJjbGFzc0NvbmZpZ3MiLCJpbnZhbGlkS2V5cyIsImlzVmFsaWRTdHJpbmdBcnJheSIsIkFycmF5IiwiaXNBcnJheSIsImZvckVhY2giLCJjbGFzc0NvbmZpZyIsImVycm9yTWVzc2FnZSIsIl92YWxpZGF0ZUNsYXNzQ29uZmlnIiwiY2xhc3NOYW1lIiwiRXJyb3IiLCJqb2luIiwidHlwZSIsInF1ZXJ5IiwibXV0YXRpb24iLCJ0cmltIiwiaW5wdXRGaWVsZHMiLCJvdXRwdXRGaWVsZHMiLCJjb25zdHJhaW50RmllbGRzIiwic29ydEZpZWxkcyIsImV2ZXJ5Iiwic29ydEZpZWxkIiwiaW5kZXgiLCJmaWVsZCIsImFzYyIsImRlc2MiLCJjcmVhdGUiLCJpbmNsdWRlcyIsImRlc3Ryb3kiLCJhcnJheSIsInNvbWUiLCJzIiwib2JqIiwiRGF0ZSIsIlByb21pc2UiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFFQSxNQUFNQSxzQkFBc0IsR0FBRyxnQkFBL0I7O0FBQ0EsTUFBTUMsZUFBZSxHQUFHLEdBQXhCOztBQUNBLE1BQU1DLGdCQUFnQixHQUFHLFFBQXpCOzs7QUFFQSxNQUFNQyxzQkFBTixDQUE2QjtBQU0zQkMsRUFBQUEsV0FBVyxDQUNUQyxNQUdDLEdBQUcsRUFKSyxFQUtUO0FBQ0EsU0FBS0Msa0JBQUwsR0FDRUQsTUFBTSxDQUFDQyxrQkFBUCxJQUNBLGdDQUNHLDRFQURILENBRkY7QUFLQSxTQUFLQyxlQUFMLEdBQXVCRixNQUFNLENBQUNFLGVBQTlCO0FBQ0EsU0FBS0MsU0FBTCxHQUFpQixDQUFDLENBQUNILE1BQU0sQ0FBQ0ksWUFBMUI7QUFDQSxTQUFLQyxjQUFMLEdBQXNCUixnQkFBdEI7QUFDRDs7QUFFRCxRQUFNUyxnQkFBTixHQUFzRDtBQUNwRCxRQUFJLEtBQUtILFNBQVQsRUFBb0I7QUFDbEIsWUFBTUksYUFBYSxHQUFHLE1BQU0sS0FBS0MsdUJBQUwsRUFBNUI7O0FBQ0EsVUFBSUQsYUFBSixFQUFtQjtBQUNqQixlQUFPQSxhQUFQO0FBQ0Q7QUFDRjs7QUFFRCxVQUFNRSxPQUFPLEdBQUcsTUFBTSxLQUFLUixrQkFBTCxDQUF3QlMsSUFBeEIsQ0FDcEJmLHNCQURvQixFQUVwQjtBQUFFZ0IsTUFBQUEsUUFBUSxFQUFFZjtBQUFaLEtBRm9CLEVBR3BCO0FBQUVnQixNQUFBQSxLQUFLLEVBQUU7QUFBVCxLQUhvQixDQUF0QjtBQU1BLFFBQUlDLGFBQUo7O0FBQ0EsUUFBSUosT0FBTyxDQUFDSyxNQUFSLElBQWtCLENBQXRCLEVBQXlCO0FBQ3ZCO0FBQ0EsYUFBTyxF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Q3BELG1CQUFRLHNDQUFSO0FBQ0Q7QUFDRixTQXJCRCxNQXFCTztBQUNMLGlCQUFRLG1DQUFSO0FBQ0Q7QUFDRjtBQUNGO0FBQ0Y7O0FBN1MwQjs7QUFnVDdCLE1BQU0xQixrQkFBa0IsR0FBRyxVQUFTMkIsS0FBVCxFQUF5QjtBQUNsRCxTQUFPMUIsS0FBSyxDQUFDQyxPQUFOLENBQWN5QixLQUFkLElBQ0gsQ0FBQ0EsS0FBSyxDQUFDQyxJQUFOLENBQVdDLENBQUMsSUFBSSxPQUFPQSxDQUFQLEtBQWEsUUFBYixJQUF5QkEsQ0FBQyxDQUFDaEIsSUFBRixHQUFTcEMsTUFBVCxHQUFrQixDQUEzRCxDQURFLEdBRUgsS0FGSjtBQUdELENBSkQ7QUFLQTs7Ozs7OztBQUtBLE1BQU1rQixtQkFBbUIsR0FBRyxVQUFTbUMsR0FBVCxFQUF1QjtBQUNqRCxTQUNFLE9BQU9BLEdBQVAsS0FBZSxRQUFmLElBQ0EsQ0FBQzdCLEtBQUssQ0FBQ0MsT0FBTixDQUFjNEIsR0FBZCxDQURELElBRUFBLEdBQUcsS0FBSyxJQUZSLElBR0FBLEdBQUcsWUFBWUMsSUFBZixLQUF3QixJQUh4QixJQUlBRCxHQUFHLFlBQVlFLE9BQWYsS0FBMkIsSUFMN0I7QUFPRCxDQVJEOztlQW1EZXZFLHNCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlcXVpcmVkUGFyYW1ldGVyIGZyb20gJy4uLy4uL2xpYi9yZXF1aXJlZFBhcmFtZXRlcic7XG5pbXBvcnQgRGF0YWJhc2VDb250cm9sbGVyIGZyb20gJy4vRGF0YWJhc2VDb250cm9sbGVyJztcbmltcG9ydCBDYWNoZUNvbnRyb2xsZXIgZnJvbSAnLi9DYWNoZUNvbnRyb2xsZXInO1xuXG5jb25zdCBHcmFwaFFMQ29uZmlnQ2xhc3NOYW1lID0gJ19HcmFwaFFMQ29uZmlnJztcbmNvbnN0IEdyYXBoUUxDb25maWdJZCA9ICcxJztcbmNvbnN0IEdyYXBoUUxDb25maWdLZXkgPSAnY29uZmlnJztcblxuY2xhc3MgUGFyc2VHcmFwaFFMQ29udHJvbGxlciB7XG4gIGRhdGFiYXNlQ29udHJvbGxlcjogRGF0YWJhc2VDb250cm9sbGVyO1xuICBjYWNoZUNvbnRyb2xsZXI6IENhY2hlQ29udHJvbGxlcjtcbiAgaXNNb3VudGVkOiBib29sZWFuO1xuICBjb25maWdDYWNoZUtleTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHBhcmFtczoge1xuICAgICAgZGF0YWJhc2VDb250cm9sbGVyOiBEYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgICBjYWNoZUNvbnRyb2xsZXI6IENhY2hlQ29udHJvbGxlcixcbiAgICB9ID0ge31cbiAgKSB7XG4gICAgdGhpcy5kYXRhYmFzZUNvbnRyb2xsZXIgPVxuICAgICAgcGFyYW1zLmRhdGFiYXNlQ29udHJvbGxlciB8fFxuICAgICAgcmVxdWlyZWRQYXJhbWV0ZXIoXG4gICAgICAgIGBQYXJzZUdyYXBoUUxDb250cm9sbGVyIHJlcXVpcmVzIGEgXCJkYXRhYmFzZUNvbnRyb2xsZXJcIiB0byBiZSBpbnN0YW50aWF0ZWQuYFxuICAgICAgKTtcbiAgICB0aGlzLmNhY2hlQ29udHJvbGxlciA9IHBhcmFtcy5jYWNoZUNvbnRyb2xsZXI7XG4gICAgdGhpcy5pc01vdW50ZWQgPSAhIXBhcmFtcy5tb3VudEdyYXBoUUw7XG4gICAgdGhpcy5jb25maWdDYWNoZUtleSA9IEdyYXBoUUxDb25maWdLZXk7XG4gIH1cblxuICBhc3luYyBnZXRHcmFwaFFMQ29uZmlnKCk6IFByb21pc2U8UGFyc2VHcmFwaFFMQ29uZmlnPiB7XG4gICAgaWYgKHRoaXMuaXNNb3VudGVkKSB7XG4gICAgICBjb25zdCBfY2FjaGVkQ29uZmlnID0gYXdhaXQgdGhpcy5fZ2V0Q2FjaGVkR3JhcGhRTENvbmZpZygpO1xuICAgICAgaWYgKF9jYWNoZWRDb25maWcpIHtcbiAgICAgICAgcmV0dXJuIF9jYWNoZWRDb25maWc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHRoaXMuZGF0YWJhc2VDb250cm9sbGVyLmZpbmQoXG4gICAgICBHcmFwaFFMQ29uZmlnQ2xhc3NOYW1lLFxuICAgICAgeyBvYmplY3RJZDogR3JhcGhRTENvbmZpZ0lkIH0sXG4gICAgICB7IGxpbWl0OiAxIH1cbiAgICApO1xuXG4gICAgbGV0IGdyYXBoUUxDb25maWc7XG4gICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9IDEpIHtcbiAgICAgIC8vIElmIHRoZXJlIGlzIG5vIGNvbmZpZyBpbiB0aGUgZGF0YWJhc2UgLSByZXR1cm4gZW1wdHkgY29uZmlnLlxuICAgICAgcmV0dXJuIHt9O1xuICAgIH0gZWxzZSB7XG4gICAgICBncmFwaFFMQ29uZmlnID0gcmVzdWx0c1swXVtHcmFwaFFMQ29uZmlnS2V5XTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pc01vdW50ZWQpIHtcbiAgICAgIHRoaXMuX3B1dENhY2hlZEdyYXBoUUxDb25maWcoZ3JhcGhRTENvbmZpZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdyYXBoUUxDb25maWc7XG4gIH1cblxuICBhc3luYyB1cGRhdGVHcmFwaFFMQ29uZmlnKFxuICAgIGdyYXBoUUxDb25maWc6IFBhcnNlR3JhcGhRTENvbmZpZ1xuICApOiBQcm9taXNlPFBhcnNlR3JhcGhRTENvbmZpZz4ge1xuICAgIC8vIHRocm93cyBpZiBpbnZhbGlkXG4gICAgdGhpcy5fdmFsaWRhdGVHcmFwaFFMQ29uZmlnKFxuICAgICAgZ3JhcGhRTENvbmZpZyB8fCByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIGdyYXBoUUxDb25maWchJylcbiAgICApO1xuXG4gICAgLy8gVHJhbnNmb3JtIGluIGRvdCBub3RhdGlvbiB0byBtYWtlIHN1cmUgaXQgd29ya3NcbiAgICBjb25zdCB1cGRhdGUgPSBPYmplY3Qua2V5cyhncmFwaFFMQ29uZmlnKS5yZWR1Y2UoXG4gICAgICAoYWNjLCBrZXkpID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBbR3JhcGhRTENvbmZpZ0tleV06IHtcbiAgICAgICAgICAgIC4uLmFjY1tHcmFwaFFMQ29uZmlnS2V5XSxcbiAgICAgICAgICAgIFtrZXldOiBncmFwaFFMQ29uZmlnW2tleV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICB7IFtHcmFwaFFMQ29uZmlnS2V5XToge30gfVxuICAgICk7XG5cbiAgICBhd2FpdCB0aGlzLmRhdGFiYXNlQ29udHJvbGxlci51cGRhdGUoXG4gICAgICBHcmFwaFFMQ29uZmlnQ2xhc3NOYW1lLFxuICAgICAgeyBvYmplY3RJZDogR3JhcGhRTENvbmZpZ0lkIH0sXG4gICAgICB1cGRhdGUsXG4gICAgICB7IHVwc2VydDogdHJ1ZSB9XG4gICAgKTtcblxuICAgIGlmICh0aGlzLmlzTW91bnRlZCkge1xuICAgICAgdGhpcy5fcHV0Q2FjaGVkR3JhcGhRTENvbmZpZyhncmFwaFFMQ29uZmlnKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyByZXNwb25zZTogeyByZXN1bHQ6IHRydWUgfSB9O1xuICB9XG5cbiAgX2dldENhY2hlZEdyYXBoUUxDb25maWcoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVDb250cm9sbGVyLmdyYXBoUUwuZ2V0KHRoaXMuY29uZmlnQ2FjaGVLZXkpO1xuICB9XG5cbiAgX3B1dENhY2hlZEdyYXBoUUxDb25maWcoZ3JhcGhRTENvbmZpZzogUGFyc2VHcmFwaFFMQ29uZmlnKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVDb250cm9sbGVyLmdyYXBoUUwucHV0KFxuICAgICAgdGhpcy5jb25maWdDYWNoZUtleSxcbiAgICAgIGdyYXBoUUxDb25maWcsXG4gICAgICA2MDAwMFxuICAgICk7XG4gIH1cblxuICBfdmFsaWRhdGVHcmFwaFFMQ29uZmlnKGdyYXBoUUxDb25maWc6ID9QYXJzZUdyYXBoUUxDb25maWcpOiB2b2lkIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2VzOiBzdHJpbmcgPSBbXTtcbiAgICBpZiAoIWdyYXBoUUxDb25maWcpIHtcbiAgICAgIGVycm9yTWVzc2FnZXMucHVzaCgnY2Fubm90IGJlIHVuZGVmaW5lZCwgbnVsbCBvciBlbXB0eScpO1xuICAgIH0gZWxzZSBpZiAoIWlzVmFsaWRTaW1wbGVPYmplY3QoZ3JhcGhRTENvbmZpZykpIHtcbiAgICAgIGVycm9yTWVzc2FnZXMucHVzaCgnbXVzdCBiZSBhIHZhbGlkIG9iamVjdCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGVuYWJsZWRGb3JDbGFzc2VzID0gbnVsbCxcbiAgICAgICAgZGlzYWJsZWRGb3JDbGFzc2VzID0gbnVsbCxcbiAgICAgICAgY2xhc3NDb25maWdzID0gbnVsbCxcbiAgICAgICAgLi4uaW52YWxpZEtleXNcbiAgICAgIH0gPSBncmFwaFFMQ29uZmlnO1xuXG4gICAgICBpZiAoT2JqZWN0LmtleXMoaW52YWxpZEtleXMpLmxlbmd0aCkge1xuICAgICAgICBlcnJvck1lc3NhZ2VzLnB1c2goXG4gICAgICAgICAgYGVuY291bnRlcmVkIGludmFsaWQga2V5czogWyR7T2JqZWN0LmtleXMoaW52YWxpZEtleXMpfV1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIGVuYWJsZWRGb3JDbGFzc2VzICE9PSBudWxsICYmXG4gICAgICAgICFpc1ZhbGlkU3RyaW5nQXJyYXkoZW5hYmxlZEZvckNsYXNzZXMpXG4gICAgICApIHtcbiAgICAgICAgZXJyb3JNZXNzYWdlcy5wdXNoKGBcImVuYWJsZWRGb3JDbGFzc2VzXCIgaXMgbm90IGEgdmFsaWQgYXJyYXlgKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgZGlzYWJsZWRGb3JDbGFzc2VzICE9PSBudWxsICYmXG4gICAgICAgICFpc1ZhbGlkU3RyaW5nQXJyYXkoZGlzYWJsZWRGb3JDbGFzc2VzKVxuICAgICAgKSB7XG4gICAgICAgIGVycm9yTWVzc2FnZXMucHVzaChgXCJkaXNhYmxlZEZvckNsYXNzZXNcIiBpcyBub3QgYSB2YWxpZCBhcnJheWApO1xuICAgICAgfVxuICAgICAgaWYgKGNsYXNzQ29uZmlncyAhPT0gbnVsbCkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjbGFzc0NvbmZpZ3MpKSB7XG4gICAgICAgICAgY2xhc3NDb25maWdzLmZvckVhY2goY2xhc3NDb25maWcgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gdGhpcy5fdmFsaWRhdGVDbGFzc0NvbmZpZyhjbGFzc0NvbmZpZyk7XG4gICAgICAgICAgICBpZiAoZXJyb3JNZXNzYWdlKSB7XG4gICAgICAgICAgICAgIGVycm9yTWVzc2FnZXMucHVzaChcbiAgICAgICAgICAgICAgICBgY2xhc3NDb25maWc6JHtjbGFzc0NvbmZpZy5jbGFzc05hbWV9IGlzIGludmFsaWQgYmVjYXVzZSAke2Vycm9yTWVzc2FnZX1gXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXJyb3JNZXNzYWdlcy5wdXNoKGBcImNsYXNzQ29uZmlnc1wiIGlzIG5vdCBhIHZhbGlkIGFycmF5YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGVycm9yTWVzc2FnZXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZ3JhcGhRTENvbmZpZzogJHtlcnJvck1lc3NhZ2VzLmpvaW4oJzsgJyl9YCk7XG4gICAgfVxuICB9XG5cbiAgX3ZhbGlkYXRlQ2xhc3NDb25maWcoY2xhc3NDb25maWc6ID9QYXJzZUdyYXBoUUxDbGFzc0NvbmZpZyk6IHN0cmluZyB8IHZvaWQge1xuICAgIGlmICghaXNWYWxpZFNpbXBsZU9iamVjdChjbGFzc0NvbmZpZykpIHtcbiAgICAgIHJldHVybiAnaXQgbXVzdCBiZSBhIHZhbGlkIG9iamVjdCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICB0eXBlID0gbnVsbCxcbiAgICAgICAgcXVlcnkgPSBudWxsLFxuICAgICAgICBtdXRhdGlvbiA9IG51bGwsXG4gICAgICAgIC4uLmludmFsaWRLZXlzXG4gICAgICB9ID0gY2xhc3NDb25maWc7XG4gICAgICBpZiAoT2JqZWN0LmtleXMoaW52YWxpZEtleXMpLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gYFwiaW52YWxpZEtleXNcIiBbJHtPYmplY3Qua2V5cyhcbiAgICAgICAgICBpbnZhbGlkS2V5c1xuICAgICAgICApfV0gc2hvdWxkIG5vdCBiZSBwcmVzZW50YDtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgY2xhc3NOYW1lICE9PSAnc3RyaW5nJyB8fCAhY2xhc3NOYW1lLnRyaW0oKS5sZW5ndGgpIHtcbiAgICAgICAgLy8gVE9ETyBjb25zaWRlciBjaGVja2luZyBjbGFzcyBleGlzdHMgaW4gc2NoZW1hP1xuICAgICAgICByZXR1cm4gYFwiY2xhc3NOYW1lXCIgbXVzdCBiZSBhIHZhbGlkIHN0cmluZ2A7XG4gICAgICB9XG4gICAgICBpZiAodHlwZSAhPT0gbnVsbCkge1xuICAgICAgICBpZiAoIWlzVmFsaWRTaW1wbGVPYmplY3QodHlwZSkpIHtcbiAgICAgICAgICByZXR1cm4gYFwidHlwZVwiIG11c3QgYmUgYSB2YWxpZCBvYmplY3RgO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBpbnB1dEZpZWxkcyA9IG51bGwsXG4gICAgICAgICAgb3V0cHV0RmllbGRzID0gbnVsbCxcbiAgICAgICAgICBjb25zdHJhaW50RmllbGRzID0gbnVsbCxcbiAgICAgICAgICBzb3J0RmllbGRzID0gbnVsbCxcbiAgICAgICAgICAuLi5pbnZhbGlkS2V5c1xuICAgICAgICB9ID0gdHlwZTtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKGludmFsaWRLZXlzKS5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm4gYFwidHlwZVwiIGNvbnRhaW5zIGludmFsaWQga2V5cywgWyR7T2JqZWN0LmtleXMoaW52YWxpZEtleXMpfV1gO1xuICAgICAgICB9IGVsc2UgaWYgKG91dHB1dEZpZWxkcyAhPT0gbnVsbCAmJiAhaXNWYWxpZFN0cmluZ0FycmF5KG91dHB1dEZpZWxkcykpIHtcbiAgICAgICAgICByZXR1cm4gYFwib3V0cHV0RmllbGRzXCIgbXVzdCBiZSBhIHZhbGlkIHN0cmluZyBhcnJheWA7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgY29uc3RyYWludEZpZWxkcyAhPT0gbnVsbCAmJlxuICAgICAgICAgICFpc1ZhbGlkU3RyaW5nQXJyYXkoY29uc3RyYWludEZpZWxkcylcbiAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuIGBcImNvbnN0cmFpbnRGaWVsZHNcIiBtdXN0IGJlIGEgdmFsaWQgc3RyaW5nIGFycmF5YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc29ydEZpZWxkcyAhPT0gbnVsbCkge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHNvcnRGaWVsZHMpKSB7XG4gICAgICAgICAgICBsZXQgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgc29ydEZpZWxkcy5ldmVyeSgoc29ydEZpZWxkLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoIWlzVmFsaWRTaW1wbGVPYmplY3Qoc29ydEZpZWxkKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGBcInNvcnRGaWVsZFwiIGF0IGluZGV4ICR7aW5kZXh9IGlzIG5vdCBhIHZhbGlkIG9iamVjdGA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgZmllbGQsIGFzYywgZGVzYywgLi4uaW52YWxpZEtleXMgfSA9IHNvcnRGaWVsZDtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmtleXMoaW52YWxpZEtleXMpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gYFwic29ydEZpZWxkXCIgYXQgaW5kZXggJHtpbmRleH0gY29udGFpbnMgaW52YWxpZCBrZXlzLCBbJHtPYmplY3Qua2V5cyhcbiAgICAgICAgICAgICAgICAgICAgaW52YWxpZEtleXNcbiAgICAgICAgICAgICAgICAgICl9XWA7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZmllbGQgIT09ICdzdHJpbmcnIHx8IGZpZWxkLnRyaW0oKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gYFwic29ydEZpZWxkXCIgYXQgaW5kZXggJHtpbmRleH0gZGlkIG5vdCBwcm92aWRlIHRoZSBcImZpZWxkXCIgYXMgYSBzdHJpbmdgO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgICAgICAgICB0eXBlb2YgYXNjICE9PSAnYm9vbGVhbicgfHxcbiAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGRlc2MgIT09ICdib29sZWFuJ1xuICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGBcInNvcnRGaWVsZFwiIGF0IGluZGV4ICR7aW5kZXh9IGRpZCBub3QgcHJvdmlkZSBcImFzY1wiIG9yIFwiZGVzY1wiIGFzIGJvb2xlYW5zYDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKGVycm9yTWVzc2FnZSkge1xuICAgICAgICAgICAgICByZXR1cm4gZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gYFwic29ydEZpZWxkc1wiIG11c3QgYmUgYSB2YWxpZCBhcnJheS5gO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaW5wdXRGaWVsZHMgIT09IG51bGwpIHtcbiAgICAgICAgICBpZiAoaXNWYWxpZFNpbXBsZU9iamVjdChpbnB1dEZpZWxkcykpIHtcbiAgICAgICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgICAgY3JlYXRlID0gbnVsbCxcbiAgICAgICAgICAgICAgdXBkYXRlID0gbnVsbCxcbiAgICAgICAgICAgICAgLi4uaW52YWxpZEtleXNcbiAgICAgICAgICAgIH0gPSBpbnB1dEZpZWxkcztcbiAgICAgICAgICAgIGlmIChPYmplY3Qua2V5cyhpbnZhbGlkS2V5cykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIHJldHVybiBgXCJpbnB1dEZpZWxkc1wiIGNvbnRhaW5zIGludmFsaWQga2V5czogWyR7T2JqZWN0LmtleXMoXG4gICAgICAgICAgICAgICAgaW52YWxpZEtleXNcbiAgICAgICAgICAgICAgKX1dYDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmICh1cGRhdGUgIT09IG51bGwgJiYgIWlzVmFsaWRTdHJpbmdBcnJheSh1cGRhdGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGBcImlucHV0RmllbGRzLnVwZGF0ZVwiIG11c3QgYmUgYSB2YWxpZCBzdHJpbmcgYXJyYXlgO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNyZWF0ZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICghaXNWYWxpZFN0cmluZ0FycmF5KGNyZWF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgXCJpbnB1dEZpZWxkcy5jcmVhdGVcIiBtdXN0IGJlIGEgdmFsaWQgc3RyaW5nIGFycmF5YDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAhY3JlYXRlLmluY2x1ZGVzKCd1c2VybmFtZScpIHx8XG4gICAgICAgICAgICAgICAgICAgICFjcmVhdGUuaW5jbHVkZXMoJ3Bhc3N3b3JkJylcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYFwiaW5wdXRGaWVsZHMuY3JlYXRlXCIgbXVzdCBpbmNsdWRlIHJlcXVpcmVkIGZpZWxkcywgdXNlcm5hbWUgYW5kIHBhc3N3b3JkYDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGBcImlucHV0RmllbGRzXCIgbXVzdCBiZSBhIHZhbGlkIG9iamVjdGA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocXVlcnkgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKGlzVmFsaWRTaW1wbGVPYmplY3QocXVlcnkpKSB7XG4gICAgICAgICAgY29uc3QgeyBmaW5kID0gbnVsbCwgZ2V0ID0gbnVsbCwgLi4uaW52YWxpZEtleXMgfSA9IHF1ZXJ5O1xuICAgICAgICAgIGlmIChPYmplY3Qua2V5cyhpbnZhbGlkS2V5cykubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gYFwicXVlcnlcIiBjb250YWlucyBpbnZhbGlkIGtleXMsIFske09iamVjdC5rZXlzKFxuICAgICAgICAgICAgICBpbnZhbGlkS2V5c1xuICAgICAgICAgICAgKX1dYDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGZpbmQgIT09IG51bGwgJiYgdHlwZW9mIGZpbmQgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcInF1ZXJ5LmZpbmRcIiBtdXN0IGJlIGEgYm9vbGVhbmA7XG4gICAgICAgICAgfSBlbHNlIGlmIChnZXQgIT09IG51bGwgJiYgdHlwZW9mIGdldCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICByZXR1cm4gYFwicXVlcnkuZ2V0XCIgbXVzdCBiZSBhIGJvb2xlYW5gO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gYFwicXVlcnlcIiBtdXN0IGJlIGEgdmFsaWQgb2JqZWN0YDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG11dGF0aW9uICE9PSBudWxsKSB7XG4gICAgICAgIGlmIChpc1ZhbGlkU2ltcGxlT2JqZWN0KG11dGF0aW9uKSkge1xuICAgICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIGNyZWF0ZSA9IG51bGwsXG4gICAgICAgICAgICB1cGRhdGUgPSBudWxsLFxuICAgICAgICAgICAgZGVzdHJveSA9IG51bGwsXG4gICAgICAgICAgICAuLi5pbnZhbGlkS2V5c1xuICAgICAgICAgIH0gPSBtdXRhdGlvbjtcbiAgICAgICAgICBpZiAoT2JqZWN0LmtleXMoaW52YWxpZEtleXMpLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGBcIm11dGF0aW9uXCIgY29udGFpbnMgaW52YWxpZCBrZXlzLCBbJHtPYmplY3Qua2V5cyhcbiAgICAgICAgICAgICAgaW52YWxpZEtleXNcbiAgICAgICAgICAgICl9XWA7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChjcmVhdGUgIT09IG51bGwgJiYgdHlwZW9mIGNyZWF0ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICByZXR1cm4gYFwibXV0YXRpb24uY3JlYXRlXCIgbXVzdCBiZSBhIGJvb2xlYW5gO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodXBkYXRlICE9PSBudWxsICYmIHR5cGVvZiB1cGRhdGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcIm11dGF0aW9uLnVwZGF0ZVwiIG11c3QgYmUgYSBib29sZWFuYDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGRlc3Ryb3kgIT09IG51bGwgJiYgdHlwZW9mIGRlc3Ryb3kgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcIm11dGF0aW9uLmRlc3Ryb3lcIiBtdXN0IGJlIGEgYm9vbGVhbmA7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBgXCJtdXRhdGlvblwiIG11c3QgYmUgYSB2YWxpZCBvYmplY3RgO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IGlzVmFsaWRTdHJpbmdBcnJheSA9IGZ1bmN0aW9uKGFycmF5KTogYm9vbGVhbiB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGFycmF5KVxuICAgID8gIWFycmF5LnNvbWUocyA9PiB0eXBlb2YgcyAhPT0gJ3N0cmluZycgfHwgcy50cmltKCkubGVuZ3RoIDwgMSlcbiAgICA6IGZhbHNlO1xufTtcbi8qKlxuICogRW5zdXJlcyB0aGUgb2JqIGlzIGEgc2ltcGxlIEpTT04ve31cbiAqIG9iamVjdCwgaS5lLiBub3QgYW4gYXJyYXksIG51bGwsIGRhdGVcbiAqIGV0Yy5cbiAqL1xuY29uc3QgaXNWYWxpZFNpbXBsZU9iamVjdCA9IGZ1bmN0aW9uKG9iaik6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmXG4gICAgIUFycmF5LmlzQXJyYXkob2JqKSAmJlxuICAgIG9iaiAhPT0gbnVsbCAmJlxuICAgIG9iaiBpbnN0YW5jZW9mIERhdGUgIT09IHRydWUgJiZcbiAgICBvYmogaW5zdGFuY2VvZiBQcm9taXNlICE9PSB0cnVlXG4gICk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhcnNlR3JhcGhRTENvbmZpZyB7XG4gIGVuYWJsZWRGb3JDbGFzc2VzPzogc3RyaW5nW107XG4gIGRpc2FibGVkRm9yQ2xhc3Nlcz86IHN0cmluZ1tdO1xuICBjbGFzc0NvbmZpZ3M/OiBQYXJzZUdyYXBoUUxDbGFzc0NvbmZpZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBhcnNlR3JhcGhRTENsYXNzQ29uZmlnIHtcbiAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gIC8qIFRoZSBgdHlwZWAgb2JqZWN0IGNvbnRhaW5zIG9wdGlvbnMgZm9yIGhvdyB0aGUgY2xhc3MgdHlwZXMgYXJlIGdlbmVyYXRlZCAqL1xuICB0eXBlOiA/e1xuICAgIC8qIEZpZWxkcyB0aGF0IGFyZSBhbGxvd2VkIHdoZW4gY3JlYXRpbmcgb3IgdXBkYXRpbmcgYW4gb2JqZWN0LiAqL1xuICAgIGlucHV0RmllbGRzOiA/e1xuICAgICAgLyogTGVhdmUgYmxhbmsgdG8gYWxsb3cgYWxsIGF2YWlsYWJsZSBmaWVsZHMgaW4gdGhlIHNjaGVtYS4gKi9cbiAgICAgIGNyZWF0ZT86IHN0cmluZ1tdLFxuICAgICAgdXBkYXRlPzogc3RyaW5nW10sXG4gICAgfSxcbiAgICAvKiBGaWVsZHMgb24gdGhlIGVkZ2VzIHRoYXQgY2FuIGJlIHJlc29sdmVkIGZyb20gYSBxdWVyeSwgaS5lLiB0aGUgUmVzdWx0IFR5cGUuICovXG4gICAgb3V0cHV0RmllbGRzOiA/KHN0cmluZ1tdKSxcbiAgICAvKiBGaWVsZHMgYnkgd2hpY2ggYSBxdWVyeSBjYW4gYmUgZmlsdGVyZWQsIGkuZS4gdGhlIGB3aGVyZWAgb2JqZWN0LiAqL1xuICAgIGNvbnN0cmFpbnRGaWVsZHM6ID8oc3RyaW5nW10pLFxuICAgIC8qIEZpZWxkcyBieSB3aGljaCBhIHF1ZXJ5IGNhbiBiZSBzb3J0ZWQ7ICovXG4gICAgc29ydEZpZWxkczogPyh7XG4gICAgICBmaWVsZDogc3RyaW5nLFxuICAgICAgYXNjOiBib29sZWFuLFxuICAgICAgZGVzYzogYm9vbGVhbixcbiAgICB9W10pLFxuICB9O1xuICAvKiBUaGUgYHF1ZXJ5YCBvYmplY3QgY29udGFpbnMgb3B0aW9ucyBmb3Igd2hpY2ggY2xhc3MgcXVlcmllcyBhcmUgZ2VuZXJhdGVkICovXG4gIHF1ZXJ5OiA/e1xuICAgIGdldDogP2Jvb2xlYW4sXG4gICAgZmluZDogP2Jvb2xlYW4sXG4gIH07XG4gIC8qIFRoZSBgbXV0YXRpb25gIG9iamVjdCBjb250YWlucyBvcHRpb25zIGZvciB3aGljaCBjbGFzcyBtdXRhdGlvbnMgYXJlIGdlbmVyYXRlZCAqL1xuICBtdXRhdGlvbjogP3tcbiAgICBjcmVhdGU6ID9ib29sZWFuLFxuICAgIHVwZGF0ZTogP2Jvb2xlYW4sXG4gICAgLy8gZGVsZXRlIGlzIGEgcmVzZXJ2ZWQga2V5IHdvcmQgaW4ganNcbiAgICBkZXN0cm95OiA/Ym9vbGVhbixcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUGFyc2VHcmFwaFFMQ29udHJvbGxlcjtcbmV4cG9ydCB7IEdyYXBoUUxDb25maWdDbGFzc05hbWUsIEdyYXBoUUxDb25maWdJZCwgR3JhcGhRTENvbmZpZ0tleSB9O1xuIl19 \ No newline at end of file diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js new file mode 100644 index 0000000000..f97dab4204 --- /dev/null +++ b/lib/Controllers/PushController.js @@ -0,0 +1,257 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PushController = void 0; + +var _node = require("parse/node"); + +var _RestQuery = _interopRequireDefault(require("../RestQuery")); + +var _RestWrite = _interopRequireDefault(require("../RestWrite")); + +var _Auth = require("../Auth"); + +var _StatusHandler = require("../StatusHandler"); + +var _utils = require("../Push/utils"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class PushController { + sendPush(body = {}, where = {}, config, auth, onPushStatusSaved = () => {}, now = new Date()) { + if (!config.hasPushSupport) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Missing push configuration'); + } // Replace the expiration_time and push_time with a valid Unix epoch milliseconds time + + + body.expiration_time = PushController.getExpirationTime(body); + body.expiration_interval = PushController.getExpirationInterval(body); + + if (body.expiration_time && body.expiration_interval) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Both expiration_time and expiration_interval cannot be set'); + } // Immediate push + + + if (body.expiration_interval && !Object.prototype.hasOwnProperty.call(body, 'push_time')) { + const ttlMs = body.expiration_interval * 1000; + body.expiration_time = new Date(now.valueOf() + ttlMs).valueOf(); + } + + const pushTime = PushController.getPushTime(body); + + if (pushTime && pushTime.date !== 'undefined') { + body['push_time'] = PushController.formatPushTime(pushTime); + } // TODO: If the req can pass the checking, we return immediately instead of waiting + // pushes to be sent. We probably change this behaviour in the future. + + + let badgeUpdate = () => { + return Promise.resolve(); + }; + + if (body.data && body.data.badge) { + const badge = body.data.badge; + let restUpdate = {}; + + if (typeof badge == 'string' && badge.toLowerCase() === 'increment') { + restUpdate = { + badge: { + __op: 'Increment', + amount: 1 + } + }; + } else if (typeof badge == 'object' && typeof badge.__op == 'string' && badge.__op.toLowerCase() == 'increment' && Number(badge.amount)) { + restUpdate = { + badge: { + __op: 'Increment', + amount: badge.amount + } + }; + } else if (Number(badge)) { + restUpdate = { + badge: badge + }; + } else { + throw "Invalid value for badge, expected number or 'Increment' or {increment: number}"; + } // Force filtering on only valid device tokens + + + const updateWhere = (0, _utils.applyDeviceTokenExists)(where); + + badgeUpdate = () => { + // Build a real RestQuery so we can use it in RestWrite + const restQuery = new _RestQuery.default(config, (0, _Auth.master)(config), '_Installation', updateWhere); + return restQuery.buildRestWhere().then(() => { + const write = new _RestWrite.default(config, (0, _Auth.master)(config), '_Installation', restQuery.restWhere, restUpdate); + write.runOptions.many = true; + return write.execute(); + }); + }; + } + + const pushStatus = (0, _StatusHandler.pushStatusHandler)(config); + return Promise.resolve().then(() => { + return pushStatus.setInitial(body, where); + }).then(() => { + onPushStatusSaved(pushStatus.objectId); + return badgeUpdate(); + }).then(() => { + // Update audience lastUsed and timesUsed + if (body.audience_id) { + const audienceId = body.audience_id; + var updateAudience = { + lastUsed: { + __type: 'Date', + iso: new Date().toISOString() + }, + timesUsed: { + __op: 'Increment', + amount: 1 + } + }; + const write = new _RestWrite.default(config, (0, _Auth.master)(config), '_Audience', { + objectId: audienceId + }, updateAudience); + write.execute(); + } // Don't wait for the audience update promise to resolve. + + + return Promise.resolve(); + }).then(() => { + if (Object.prototype.hasOwnProperty.call(body, 'push_time') && config.hasPushScheduledSupport) { + return Promise.resolve(); + } + + return config.pushControllerQueue.enqueue(body, where, config, auth, pushStatus); + }).catch(err => { + return pushStatus.fail(err).then(() => { + throw err; + }); + }); + } + /** + * Get expiration time from the request body. + * @param {Object} request A request object + * @returns {Number|undefined} The expiration time if it exists in the request + */ + + + static getExpirationTime(body = {}) { + var hasExpirationTime = Object.prototype.hasOwnProperty.call(body, 'expiration_time'); + + if (!hasExpirationTime) { + return; + } + + var expirationTimeParam = body['expiration_time']; + var expirationTime; + + if (typeof expirationTimeParam === 'number') { + expirationTime = new Date(expirationTimeParam * 1000); + } else if (typeof expirationTimeParam === 'string') { + expirationTime = new Date(expirationTimeParam); + } else { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, body['expiration_time'] + ' is not valid time.'); + } // Check expirationTime is valid or not, if it is not valid, expirationTime is NaN + + + if (!isFinite(expirationTime)) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, body['expiration_time'] + ' is not valid time.'); + } + + return expirationTime.valueOf(); + } + + static getExpirationInterval(body = {}) { + const hasExpirationInterval = Object.prototype.hasOwnProperty.call(body, 'expiration_interval'); + + if (!hasExpirationInterval) { + return; + } + + var expirationIntervalParam = body['expiration_interval']; + + if (typeof expirationIntervalParam !== 'number' || expirationIntervalParam <= 0) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, `expiration_interval must be a number greater than 0`); + } + + return expirationIntervalParam; + } + /** + * Get push time from the request body. + * @param {Object} request A request object + * @returns {Number|undefined} The push time if it exists in the request + */ + + + static getPushTime(body = {}) { + var hasPushTime = Object.prototype.hasOwnProperty.call(body, 'push_time'); + + if (!hasPushTime) { + return; + } + + var pushTimeParam = body['push_time']; + var date; + var isLocalTime = true; + + if (typeof pushTimeParam === 'number') { + date = new Date(pushTimeParam * 1000); + } else if (typeof pushTimeParam === 'string') { + isLocalTime = !PushController.pushTimeHasTimezoneComponent(pushTimeParam); + date = new Date(pushTimeParam); + } else { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, body['push_time'] + ' is not valid time.'); + } // Check pushTime is valid or not, if it is not valid, pushTime is NaN + + + if (!isFinite(date)) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, body['push_time'] + ' is not valid time.'); + } + + return { + date, + isLocalTime + }; + } + /** + * Checks if a ISO8601 formatted date contains a timezone component + * @param pushTimeParam {string} + * @returns {boolean} + */ + + + static pushTimeHasTimezoneComponent(pushTimeParam) { + const offsetPattern = /(.+)([+-])\d\d:\d\d$/; + return pushTimeParam.indexOf('Z') === pushTimeParam.length - 1 || // 2007-04-05T12:30Z + offsetPattern.test(pushTimeParam); // 2007-04-05T12:30.000+02:00, 2007-04-05T12:30.000-02:00 + } + /** + * Converts a date to ISO format in UTC time and strips the timezone if `isLocalTime` is true + * @param date {Date} + * @param isLocalTime {boolean} + * @returns {string} + */ + + + static formatPushTime({ + date, + isLocalTime + }) { + if (isLocalTime) { + // Strip 'Z' + const isoString = date.toISOString(); + return isoString.substring(0, isoString.indexOf('Z')); + } + + return date.toISOString(); + } + +} + +exports.PushController = PushController; +var _default = PushController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsInR0bE1zIiwidmFsdWVPZiIsInB1c2hUaW1lIiwiZ2V0UHVzaFRpbWUiLCJkYXRlIiwiZm9ybWF0UHVzaFRpbWUiLCJiYWRnZVVwZGF0ZSIsIlByb21pc2UiLCJyZXNvbHZlIiwiZGF0YSIsImJhZGdlIiwicmVzdFVwZGF0ZSIsInRvTG93ZXJDYXNlIiwiX19vcCIsImFtb3VudCIsIk51bWJlciIsInVwZGF0ZVdoZXJlIiwicmVzdFF1ZXJ5IiwiUmVzdFF1ZXJ5IiwiYnVpbGRSZXN0V2hlcmUiLCJ0aGVuIiwid3JpdGUiLCJSZXN0V3JpdGUiLCJyZXN0V2hlcmUiLCJydW5PcHRpb25zIiwibWFueSIsImV4ZWN1dGUiLCJwdXNoU3RhdHVzIiwic2V0SW5pdGlhbCIsIm9iamVjdElkIiwiYXVkaWVuY2VfaWQiLCJhdWRpZW5jZUlkIiwidXBkYXRlQXVkaWVuY2UiLCJsYXN0VXNlZCIsIl9fdHlwZSIsImlzbyIsInRvSVNPU3RyaW5nIiwidGltZXNVc2VkIiwiaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQiLCJwdXNoQ29udHJvbGxlclF1ZXVlIiwiZW5xdWV1ZSIsImNhdGNoIiwiZXJyIiwiZmFpbCIsImhhc0V4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvblRpbWVQYXJhbSIsImV4cGlyYXRpb25UaW1lIiwiaXNGaW5pdGUiLCJoYXNFeHBpcmF0aW9uSW50ZXJ2YWwiLCJleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSIsImhhc1B1c2hUaW1lIiwicHVzaFRpbWVQYXJhbSIsImlzTG9jYWxUaW1lIiwicHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudCIsIm9mZnNldFBhdHRlcm4iLCJpbmRleE9mIiwibGVuZ3RoIiwidGVzdCIsImlzb1N0cmluZyIsInN1YnN0cmluZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsY0FBTixDQUFxQjtBQUMxQkMsRUFBQUEsUUFBUSxDQUNOQyxJQUFJLEdBQUcsRUFERCxFQUVOQyxLQUFLLEdBQUcsRUFGRixFQUdOQyxNQUhNLEVBSU5DLElBSk0sRUFLTkMsaUJBQWlCLEdBQUcsTUFBTSxDQUFFLENBTHRCLEVBTU5DLEdBQUcsR0FBRyxJQUFJQyxJQUFKLEVBTkEsRUFPTjtBQUNBLFFBQUksQ0FBQ0osTUFBTSxDQUFDSyxjQUFaLEVBQTRCO0FBQzFCLFlBQU0sSUFBSUMsWUFBTUMsS0FBVixDQUNKRCxZQUFNQyxLQUFOLENBQVlDLGtCQURSLEVBRUosNEJBRkksQ0FBTjtBQUlELEtBTkQsQ0FRQTs7O0FBQ0FWLElBQUFBLElBQUksQ0FBQ1csZUFBTCxHQUF1QmIsY0FBYyxDQUFDYyxpQkFBZixDQUFpQ1osSUFBakMsQ0FBdkI7QUFDQUEsSUFBQUEsSUFBSSxDQUFDYSxtQkFBTCxHQUEyQmYsY0FBYyxDQUFDZ0IscUJBQWYsQ0FBcUNkLElBQXJDLENBQTNCOztBQUNBLFFBQUlBLElBQUksQ0FBQ1csZUFBTCxJQUF3QlgsSUFBSSxDQUFDYSxtQkFBakMsRUFBc0Q7QUFDcEQsWUFBTSxJQUFJTCxZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRFIsRUFFSiw0REFGSSxDQUFOO0FBSUQsS0FoQkQsQ0FrQkE7OztBQUNBLFFBQ0VWLElBQUksQ0FBQ2EsbUJBQUws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UCxDQUFzQjtBQUNwQkQsSUFBQUEsSUFEb0I7QUFFcEJnRCxJQUFBQTtBQUZvQixHQUF0QixFQU1HO0FBQ0QsUUFBSUEsV0FBSixFQUFpQjtBQUNmO0FBQ0EsWUFBTU0sU0FBUyxHQUFHdEQsSUFBSSxDQUFDZ0MsV0FBTCxFQUFsQjtBQUNBLGFBQU9zQixTQUFTLENBQUNDLFNBQVYsQ0FBb0IsQ0FBcEIsRUFBdUJELFNBQVMsQ0FBQ0gsT0FBVixDQUFrQixHQUFsQixDQUF2QixDQUFQO0FBQ0Q7O0FBQ0QsV0FBT25ELElBQUksQ0FBQ2dDLFdBQUwsRUFBUDtBQUNEOztBQTNReUI7OztlQThRYnpELGMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9IGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFJlc3RRdWVyeSBmcm9tICcuLi9SZXN0UXVlcnknO1xuaW1wb3J0IFJlc3RXcml0ZSBmcm9tICcuLi9SZXN0V3JpdGUnO1xuaW1wb3J0IHsgbWFzdGVyIH0gZnJvbSAnLi4vQXV0aCc7XG5pbXBvcnQgeyBwdXNoU3RhdHVzSGFuZGxlciB9IGZyb20gJy4uL1N0YXR1c0hhbmRsZXInO1xuaW1wb3J0IHsgYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyB9IGZyb20gJy4uL1B1c2gvdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgUHVzaENvbnRyb2xsZXIge1xuICBzZW5kUHVzaChcbiAgICBib2R5ID0ge30sXG4gICAgd2hlcmUgPSB7fSxcbiAgICBjb25maWcsXG4gICAgYXV0aCxcbiAgICBvblB1c2hTdGF0dXNTYXZlZCA9ICgpID0+IHt9LFxuICAgIG5vdyA9IG5ldyBEYXRlKClcbiAgKSB7XG4gICAgaWYgKCFjb25maWcuaGFzUHVzaFN1cHBvcnQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnTWlzc2luZyBwdXNoIGNvbmZpZ3VyYXRpb24nXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFJlcGxhY2UgdGhlIGV4cGlyYXRpb25fdGltZSBhbmQgcHVzaF90aW1lIHdpdGggYSB2YWxpZCBVbml4IGVwb2NoIG1pbGxpc2Vjb25kcyB0aW1lXG4gICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uVGltZShib2R5KTtcbiAgICBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSk7XG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl90aW1lICYmIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdCb3RoIGV4cGlyYXRpb25fdGltZSBhbmQgZXhwaXJhdGlvbl9pbnRlcnZhbCBjYW5ub3QgYmUgc2V0J1xuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBJbW1lZGlhdGUgcHVzaFxuICAgIGlmIChcbiAgICAgIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCAmJlxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChib2R5LCAncHVzaF90aW1lJylcbiAgICApIHtcbiAgICAgIGNvbnN0IHR0bE1zID0gYm9keS5leHBpcmF0aW9uX2ludGVydmFsICogMTAwMDtcbiAgICAgIGJvZHkuZXhwaXJhdGlvbl90aW1lID0gbmV3IERhdGUobm93LnZhbHVlT2YoKSArIHR0bE1zKS52YWx1ZU9mKCk7XG4gICAgfVxuXG4gICAgY29uc3QgcHVzaFRpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRQdXNoVGltZShib2R5KTtcbiAgICBpZiAocHVzaFRpbWUgJiYgcHVzaFRpbWUuZGF0ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGJvZHlbJ3B1c2hfdGltZSddID0gUHVzaENvbnRyb2xsZXIuZm9ybWF0UHVzaFRpbWUocHVzaFRpbWUpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IElmIHRoZSByZXEgY2FuIHBhc3MgdGhlIGNoZWNraW5nLCB3ZSByZXR1cm4gaW1tZWRpYXRlbHkgaW5zdGVhZCBvZiB3YWl0aW5nXG4gICAgLy8gcHVzaGVzIHRvIGJlIHNlbnQuIFdlIHByb2JhYmx5IGNoYW5nZSB0aGlzIGJlaGF2aW91ciBpbiB0aGUgZnV0dXJlLlxuICAgIGxldCBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9O1xuXG4gICAgaWYgKGJvZHkuZGF0YSAmJiBib2R5LmRhdGEuYmFkZ2UpIHtcbiAgICAgIGNvbnN0IGJhZGdlID0gYm9keS5kYXRhLmJhZGdlO1xuICAgICAgbGV0IHJlc3RVcGRhdGUgPSB7fTtcbiAgICAgIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ3N0cmluZycgJiYgYmFkZ2UudG9Mb3dlckNhc2UoKSA9PT0gJ2luY3JlbWVudCcpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogMSB9IH07XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICB0eXBlb2YgYmFkZ2UgPT0gJ29iamVjdCcgJiZcbiAgICAgICAgdHlwZW9mIGJhZGdlLl9fb3AgPT0gJ3N0cmluZycgJiZcbiAgICAgICAgYmFkZ2UuX19vcC50b0xvd2VyQ2FzZSgpID09ICdpbmNyZW1lbnQnICYmXG4gICAgICAgIE51bWJlcihiYWRnZS5hbW91bnQpXG4gICAgICApIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogYmFkZ2UuYW1vdW50IH0gfTtcbiAgICAgIH0gZWxzZSBpZiAoTnVtYmVyKGJhZGdlKSkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogYmFkZ2UgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IFwiSW52YWxpZCB2YWx1ZSBmb3IgYmFkZ2UsIGV4cGVjdGVkIG51bWJlciBvciAnSW5jcmVtZW50JyBvciB7aW5jcmVtZW50OiBudW1iZXJ9XCI7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvcmNlIGZpbHRlcmluZyBvbiBvbmx5IHZhbGlkIGRldmljZSB0b2tlbnNcbiAgICAgIGNvbnN0IHVwZGF0ZVdoZXJlID0gYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyh3aGVyZSk7XG4gICAgICBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgICAgLy8gQnVpbGQgYSByZWFsIFJlc3RRdWVyeSBzbyB3ZSBjYW4gdXNlIGl0IGluIFJlc3RXcml0ZVxuICAgICAgICBjb25zdCByZXN0UXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBtYXN0ZXIoY29uZmlnKSxcbiAgICAgICAgICAnX0luc3RhbGxhdGlvbicsXG4gICAgICAgICAgdXBkYXRlV2hlcmVcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHJlc3RRdWVyeS5idWlsZFJlc3RXaGVyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdyaXRlID0gbmV3IFJlc3RXcml0ZShcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIG1hc3Rlcihjb25maWcpLFxuICAgICAgICAgICAgJ19JbnN0YWxsYXRpb24nLFxuICAgICAgICAgICAgcmVzdFF1ZXJ5LnJlc3RXaGVyZSxcbiAgICAgICAgICAgIHJlc3RVcGRhdGVcbiAgICAgICAgICApO1xuICAgICAgICAgIHdyaXRlLnJ1bk9wdGlvbnMubWFueSA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgIH1cbiAgICBjb25zdCBwdXNoU3RhdHVzID0gcHVzaFN0YXR1c0hhbmRsZXIoY29uZmlnKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHB1c2hTdGF0dXMuc2V0SW5pdGlhbChib2R5LCB3aGVyZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBvblB1c2hTdGF0dXNTYXZlZChwdXNoU3RhdHVzLm9iamVjdElkKTtcbiAgICAgICAgcmV0dXJuIGJhZGdlVXBkYXRlKCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBVcGRhdGUgYXVkaWVuY2UgbGFzdFVzZWQgYW5kIHRpbWVzVXNlZFxuICAgICAgICBpZiAoYm9keS5hdWRpZW5jZV9pZCkge1xuICAgICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgICAgdmFyIHVwZGF0ZUF1ZGllbmNlID0ge1xuICAgICAgICAgICAgbGFzdFVzZWQ6IHsgX190eXBlOiAnRGF0ZScsIGlzbzogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH0sXG4gICAgICAgICAgICB0aW1lc1VzZWQ6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogMSB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgbWFzdGVyKGNvbmZpZyksXG4gICAgICAgICAgICAnX0F1ZGllbmNlJyxcbiAgICAgICAgICAgIHsgb2JqZWN0SWQ6IGF1ZGllbmNlSWQgfSxcbiAgICAgICAgICAgIHVwZGF0ZUF1ZGllbmNlXG4gICAgICAgICAgKTtcbiAgICAgICAgICB3cml0ZS5leGVjdXRlKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRG9uJ3Qgd2FpdCBmb3IgdGhlIGF1ZGllbmNlIHVwZGF0ZSBwcm9taXNlIHRvIHJlc29sdmUuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYm9keSwgJ3B1c2hfdGltZScpICYmXG4gICAgICAgICAgY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0XG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShcbiAgICAgICAgICBib2R5LFxuICAgICAgICAgIHdoZXJlLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIHB1c2hTdGF0dXNcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgcmV0dXJuIHB1c2hTdGF0dXMuZmFpbChlcnIpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZXhwaXJhdGlvbiB0aW1lIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcXVlc3QgQSByZXF1ZXN0IG9iamVjdFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfHVuZGVmaW5lZH0gVGhlIGV4cGlyYXRpb24gdGltZSBpZiBpdCBleGlzdHMgaW4gdGhlIHJlcXVlc3RcbiAgICovXG4gIHN0YXRpYyBnZXRFeHBpcmF0aW9uVGltZShib2R5ID0ge30pIHtcbiAgICB2YXIgaGFzRXhwaXJhdGlvblRpbWUgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoXG4gICAgICBib2R5LFxuICAgICAgJ2V4cGlyYXRpb25fdGltZSdcbiAgICApO1xuICAgIGlmICghaGFzRXhwaXJhdGlvblRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV4cGlyYXRpb25UaW1lUGFyYW0gPSBib2R5WydleHBpcmF0aW9uX3RpbWUnXTtcbiAgICB2YXIgZXhwaXJhdGlvblRpbWU7XG4gICAgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwaXJhdGlvblRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGV4cGlyYXRpb25UaW1lID0gbmV3IERhdGUoZXhwaXJhdGlvblRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBib2R5WydleHBpcmF0aW9uX3RpbWUnXSArICcgaXMgbm90IHZhbGlkIHRpbWUuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZXhwaXJhdGlvblRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIGV4cGlyYXRpb25UaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZXhwaXJhdGlvblRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsnZXhwaXJhdGlvbl90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLidcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uVGltZS52YWx1ZU9mKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkgPSB7fSkge1xuICAgIGNvbnN0IGhhc0V4cGlyYXRpb25JbnRlcnZhbCA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChcbiAgICAgIGJvZHksXG4gICAgICAnZXhwaXJhdGlvbl9pbnRlcnZhbCdcbiAgICApO1xuICAgIGlmICghaGFzRXhwaXJhdGlvbkludGVydmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtID0gYm9keVsnZXhwaXJhdGlvbl9pbnRlcnZhbCddO1xuICAgIGlmIChcbiAgICAgIHR5cGVvZiBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSAhPT0gJ251bWJlcicgfHxcbiAgICAgIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIDw9IDBcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBgZXhwaXJhdGlvbl9pbnRlcnZhbCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAwYFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBwdXNoIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgcHVzaCB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldFB1c2hUaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNQdXNoVGltZSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChib2R5LCAncHVzaF90aW1lJyk7XG4gICAgaWYgKCFoYXNQdXNoVGltZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgcHVzaFRpbWVQYXJhbSA9IGJvZHlbJ3B1c2hfdGltZSddO1xuICAgIHZhciBkYXRlO1xuICAgIHZhciBpc0xvY2FsVGltZSA9IHRydWU7XG5cbiAgICBpZiAodHlwZW9mIHB1c2hUaW1lUGFyYW0gPT09ICdudW1iZXInKSB7XG4gICAgICBkYXRlID0gbmV3IERhdGUocHVzaFRpbWVQYXJhbSAqIDEwMDApO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHB1c2hUaW1lUGFyYW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICBpc0xvY2FsVGltZSA9ICFQdXNoQ29udHJvbGxlci5wdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50KHB1c2hUaW1lUGFyYW0pO1xuICAgICAgZGF0ZSA9IG5ldyBEYXRlKHB1c2hUaW1lUGFyYW0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLidcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIENoZWNrIHB1c2hUaW1lIGlzIHZhbGlkIG9yIG5vdCwgaWYgaXQgaXMgbm90IHZhbGlkLCBwdXNoVGltZSBpcyBOYU5cbiAgICBpZiAoIWlzRmluaXRlKGRhdGUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGUsXG4gICAgICBpc0xvY2FsVGltZSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhIElTTzg2MDEgZm9ybWF0dGVkIGRhdGUgY29udGFpbnMgYSB0aW1lem9uZSBjb21wb25lbnRcbiAgICogQHBhcmFtIHB1c2hUaW1lUGFyYW0ge3N0cmluZ31cbiAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAqL1xuICBzdGF0aWMgcHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudChwdXNoVGltZVBhcmFtOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBvZmZzZXRQYXR0ZXJuID0gLyguKykoWystXSlcXGRcXGQ6XFxkXFxkJC87XG4gICAgcmV0dXJuIChcbiAgICAgIHB1c2hUaW1lUGFyYW0uaW5kZXhPZignWicpID09PSBwdXNoVGltZVBhcmFtLmxlbmd0aCAtIDEgfHwgLy8gMjAwNy0wNC0wNVQxMjozMFpcbiAgICAgIG9mZnNldFBhdHRlcm4udGVzdChwdXNoVGltZVBhcmFtKVxuICAgICk7IC8vIDIwMDctMDQtMDVUMTI6MzAuMDAwKzAyOjAwLCAyMDA3LTA0LTA1VDEyOjMwLjAwMC0wMjowMFxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgZGF0ZSB0byBJU08gZm9ybWF0IGluIFVUQyB0aW1lIGFuZCBzdHJpcHMgdGhlIHRpbWV6b25lIGlmIGBpc0xvY2FsVGltZWAgaXMgdHJ1ZVxuICAgKiBAcGFyYW0gZGF0ZSB7RGF0ZX1cbiAgICogQHBhcmFtIGlzTG9jYWxUaW1lIHtib29sZWFufVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgc3RhdGljIGZvcm1hdFB1c2hUaW1lKHtcbiAgICBkYXRlLFxuICAgIGlzTG9jYWxUaW1lLFxuICB9OiB7XG4gICAgZGF0ZTogRGF0ZSxcbiAgICBpc0xvY2FsVGltZTogYm9vbGVhbixcbiAgfSkge1xuICAgIGlmIChpc0xvY2FsVGltZSkge1xuICAgICAgLy8gU3RyaXAgJ1onXG4gICAgICBjb25zdCBpc29TdHJpbmcgPSBkYXRlLnRvSVNPU3RyaW5nKCk7XG4gICAgICByZXR1cm4gaXNvU3RyaW5nLnN1YnN0cmluZygwLCBpc29TdHJpbmcuaW5kZXhPZignWicpKTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGUudG9JU09TdHJpbmcoKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBQdXNoQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/SchemaCache.js b/lib/Controllers/SchemaCache.js new file mode 100644 index 0000000000..09db05e417 --- /dev/null +++ b/lib/Controllers/SchemaCache.js @@ -0,0 +1,75 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _cryptoUtils = require("../cryptoUtils"); + +var _defaults = _interopRequireDefault(require("../defaults")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const MAIN_SCHEMA = '__MAIN_SCHEMA'; +const SCHEMA_CACHE_PREFIX = '__SCHEMA'; + +class SchemaCache { + constructor(cacheController, ttl = _defaults.default.schemaCacheTTL, singleCache = false) { + this.ttl = ttl; + + if (typeof ttl == 'string') { + this.ttl = parseInt(ttl); + } + + this.cache = cacheController; + this.prefix = SCHEMA_CACHE_PREFIX; + + if (!singleCache) { + this.prefix += (0, _cryptoUtils.randomString)(20); + } + } + + getAllClasses() { + if (!this.ttl) { + return Promise.resolve(null); + } + + return this.cache.get(this.prefix + MAIN_SCHEMA); + } + + setAllClasses(schema) { + if (!this.ttl) { + return Promise.resolve(null); + } + + return this.cache.put(this.prefix + MAIN_SCHEMA, schema); + } + + getOneSchema(className) { + if (!this.ttl) { + return Promise.resolve(null); + } + + return this.cache.get(this.prefix + MAIN_SCHEMA).then(cachedSchemas => { + cachedSchemas = cachedSchemas || []; + const schema = cachedSchemas.find(cachedSchema => { + return cachedSchema.className === className; + }); + + if (schema) { + return Promise.resolve(schema); + } + + return Promise.resolve(null); + }); + } + + clear() { + return this.cache.del(this.prefix + MAIN_SCHEMA); + } + +} + +exports.default = SchemaCache; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9TY2hlbWFDYWNoZS5qcyJdLCJuYW1lcyI6WyJNQUlOX1NDSEVNQSIsIlNDSEVNQV9DQUNIRV9QUkVGSVgiLCJTY2hlbWFDYWNoZSIsImNvbnN0cnVjdG9yIiwiY2FjaGVDb250cm9sbGVyIiwidHRsIiwiZGVmYXVsdHMiLCJzY2hlbWFDYWNoZVRUTCIsInNpbmdsZUNhY2hlIiwicGFyc2VJbnQiLCJjYWNoZSIsInByZWZpeCIsImdldEFsbENsYXNzZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsImdldCIsInNldEFsbENsYXNzZXMiLCJzY2hlbWEiLCJwdXQiLCJnZXRPbmVTY2hlbWEiLCJjbGFzc05hbWUiLCJ0aGVuIiwiY2FjaGVkU2NoZW1hcyIsImZpbmQiLCJjYWNoZWRTY2hlbWEiLCJjbGVhciIsImRlbCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUdBOztBQUNBOzs7O0FBSkEsTUFBTUEsV0FBVyxHQUFHLGVBQXBCO0FBQ0EsTUFBTUMsbUJBQW1CLEdBQUcsVUFBNUI7O0FBS2UsTUFBTUMsV0FBTixDQUFrQjtBQUcvQkMsRUFBQUEsV0FBVyxDQUNUQyxlQURTLEVBRVRDLEdBQUcsR0FBR0Msa0JBQVNDLGNBRk4sRUFHVEMsV0FBVyxHQUFHLEtBSEwsRUFJVDtBQUNBLFNBQUtILEdBQUwsR0FBV0EsR0FBWDs7QUFDQSxRQUFJLE9BQU9BLEdBQVAsSUFBYyxRQUFsQixFQUE0QjtBQUMxQixXQUFLQSxHQUFMLEdBQVdJLFFBQVEsQ0FBQ0osR0FBRCxDQUFuQjtBQUNEOztBQUNELFNBQUtLLEtBQUwsR0FBYU4sZUFBYjtBQUNBLFNBQUtPLE1BQUwsR0FBY1YsbUJBQWQ7O0FBQ0EsUUFBSSxDQUFDTyxXQUFMLEVBQWtCO0FBQ2hCLFdBQUtHLE1BQUwsSUFBZSwrQkFBYSxFQUFiLENBQWY7QUFDRDtBQUNGOztBQUVEQyxFQUFBQSxhQUFhLEdBQUc7QUFDZCxRQUFJLENBQUMsS0FBS1AsR0FBVixFQUFlO0FBQ2IsYUFBT1EsT0FBTyxDQUFDQyxPQUFSLENBQWdCLElBQWhCLENBQVA7QUFDRDs7QUFDRCxXQUFPLEtBQUtKLEtBQUwsQ0FBV0ssR0FBWCxDQUFlLEtBQUtKLE1BQUwsR0FBY1gsV0FBN0IsQ0FBUDtBQUNEOztBQUVEZ0IsRUFBQUEsYUFBYSxDQUFDQyxNQUFELEVBQVM7QUFDcEIsUUFBSSxDQUFDLEtBQUtaLEdBQVYsRUFBZTtBQUNiLGFBQU9RLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQixJQUFoQixDQUFQO0FBQ0Q7O0FBQ0QsV0FBTyxLQUFLSixLQUFMLENBQVdRLEdBQVgsQ0FBZSxLQUFLUCxNQUFMLEdBQWNYLFdBQTdCLEVBQTBDaUIsTUFBMUMsQ0FBUDtBQUNEOztBQUVERSxFQUFBQSxZQUFZLENBQUNDLFNBQUQsRUFBWTtBQUN0QixRQUFJLENBQUMsS0FBS2YsR0FBVixFQUFlO0FBQ2IsYUFBT1EsT0FBTyxDQUFDQyxPQUFSLENBQWdCLElBQWhCLENBQVA7QUFDRDs7QUFDRCxXQUFPLEtBQUtKLEtBQUwsQ0FBV0ssR0FBWCxDQUFlLEtBQUtKLE1BQUwsR0FBY1gsV0FBN0IsRUFBMENxQixJQUExQyxDQUErQ0MsYUFBYSxJQUFJO0FBQ3JFQSxNQUFBQSxhQUFhLEdBQUdBLGFBQWEsSUFBSSxFQUFqQztBQUNBLFlBQU1MLE1BQU0sR0FBR0ssYUFBYSxDQUFDQyxJQUFkLENBQW1CQyxZQUFZLElBQUk7QUFDaEQsZUFBT0EsWUFBWSxDQUFDSixTQUFiLEtBQTJCQSxTQUFsQztBQUNELE9BRmMsQ0FBZjs7QUFHQSxVQUFJSCxNQUFKLEVBQVk7QUFDVixlQUFPSixPQUFPLENBQUNDLE9BQVIsQ0FBZ0JHLE1BQWhCLENBQVA7QUFDRDs7QUFDRCxhQUFPSixPQUFPLENBQUNDLE9BQVIsQ0FBZ0IsSUFBaEIsQ0FBUDtBQUNELEtBVE0sQ0FBUDtBQVVEOztBQUVEVyxFQUFBQSxLQUFLLEdBQUc7QUFDTixXQUFPLEtBQUtmLEtBQUwsQ0FBV2dCLEdBQVgsQ0FBZSxLQUFLZixNQUFMLEdBQWNYLFdBQTdCLENBQVA7QUFDRDs7QUFuRDhCIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgTUFJTl9TQ0hFTUEgPSAnX19NQUlOX1NDSEVNQSc7XG5jb25zdCBTQ0hFTUFfQ0FDSEVfUFJFRklYID0gJ19fU0NIRU1BJztcblxuaW1wb3J0IHsgcmFuZG9tU3RyaW5nIH0gZnJvbSAnLi4vY3J5cHRvVXRpbHMnO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4uL2RlZmF1bHRzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2NoZW1hQ2FjaGUge1xuICBjYWNoZTogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGNhY2hlQ29udHJvbGxlcixcbiAgICB0dGwgPSBkZWZhdWx0cy5zY2hlbWFDYWNoZVRUTCxcbiAgICBzaW5nbGVDYWNoZSA9IGZhbHNlXG4gICkge1xuICAgIHRoaXMudHRsID0gdHRsO1xuICAgIGlmICh0eXBlb2YgdHRsID09ICdzdHJpbmcnKSB7XG4gICAgICB0aGlzLnR0bCA9IHBhcnNlSW50KHR0bCk7XG4gICAgfVxuICAgIHRoaXMuY2FjaGUgPSBjYWNoZUNvbnRyb2xsZXI7XG4gICAgdGhpcy5wcmVmaXggPSBTQ0hFTUFfQ0FDSEVfUFJFRklYO1xuICAgIGlmICghc2luZ2xlQ2FjaGUpIHtcbiAgICAgIHRoaXMucHJlZml4ICs9IHJhbmRvbVN0cmluZygyMCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0QWxsQ2xhc3NlcygpIHtcbiAgICBpZiAoIXRoaXMudHRsKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQodGhpcy5wcmVmaXggKyBNQUlOX1NDSEVNQSk7XG4gIH1cblxuICBzZXRBbGxDbGFzc2VzKHNjaGVtYSkge1xuICAgIGlmICghdGhpcy50dGwpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNhY2hlLnB1dCh0aGlzLnByZWZpeCArIE1BSU5fU0NIRU1BLCBzY2hlbWEpO1xuICB9XG5cbiAgZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSkge1xuICAgIGlmICghdGhpcy50dGwpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNhY2hlLmdldCh0aGlzLnByZWZpeCArIE1BSU5fU0NIRU1BKS50aGVuKGNhY2hlZFNjaGVtYXMgPT4ge1xuICAgICAgY2FjaGVkU2NoZW1hcyA9IGNhY2hlZFNjaGVtYXMgfHwgW107XG4gICAgICBjb25zdCBzY2hlbWEgPSBjYWNoZWRTY2hlbWFzLmZpbmQoY2FjaGVkU2NoZW1hID0+IHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNjaGVtYS5jbGFzc05hbWUgPT09IGNsYXNzTmFtZTtcbiAgICAgIH0pO1xuICAgICAgaWYgKHNjaGVtYSkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHNjaGVtYSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xuICAgIH0pO1xuICB9XG5cbiAgY2xlYXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuZGVsKHRoaXMucHJlZml4ICsgTUFJTl9TQ0hFTUEpO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/SchemaController.js b/lib/Controllers/SchemaController.js new file mode 100644 index 0000000000..40f2e544e4 --- /dev/null +++ b/lib/Controllers/SchemaController.js @@ -0,0 +1,1525 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.classNameIsValid = classNameIsValid; +exports.fieldNameIsValid = fieldNameIsValid; +exports.invalidClassNameMessage = invalidClassNameMessage; +exports.buildMergedSchemaObject = buildMergedSchemaObject; +exports.VolatileClassesSchemas = exports.convertSchemaToAdapterSchema = exports.defaultColumns = exports.systemClasses = exports.load = exports.SchemaController = exports.default = void 0; + +var _StorageAdapter = require("../Adapters/Storage/StorageAdapter"); + +var _DatabaseController = _interopRequireDefault(require("./DatabaseController")); + +var _Config = _interopRequireDefault(require("../Config")); + +var _deepcopy = _interopRequireDefault(require("deepcopy")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +// This class handles schema validation, persistence, and modification. +// +// Each individual Schema object should be immutable. The helpers to +// do things with the Schema just return a new schema when the schema +// is changed. +// +// The canonical place to store this Schema is in the database itself, +// in a _SCHEMA collection. This is not the right way to do it for an +// open source framework, but it's backward compatible, so we're +// keeping it this way for now. +// +// In API-handling code, you should only use the Schema class via the +// DatabaseController. This will let us replace the schema logic for +// different databases. +// TODO: hide all schema logic inside the database adapter. +// -disable-next +const Parse = require('parse/node').Parse; + +const defaultColumns = Object.freeze({ + // Contain the default columns for every parse object type (except _Join collection) + _Default: { + objectId: { + type: 'String' + }, + createdAt: { + type: 'Date' + }, + updatedAt: { + type: 'Date' + }, + ACL: { + type: 'ACL' + } + }, + // The additional default columns for the _User collection (in addition to DefaultCols) + _User: { + username: { + type: 'String' + }, + password: { + type: 'String' + }, + email: { + type: 'String' + }, + emailVerified: { + type: 'Boolean' + }, + authData: { + type: 'Object' + } + }, + // The additional default columns for the _Installation collection (in addition to DefaultCols) + _Installation: { + installationId: { + type: 'String' + }, + deviceToken: { + type: 'String' + }, + channels: { + type: 'Array' + }, + deviceType: { + type: 'String' + }, + pushType: { + type: 'String' + }, + GCMSenderId: { + type: 'String' + }, + timeZone: { + type: 'String' + }, + localeIdentifier: { + type: 'String' + }, + badge: { + type: 'Number' + }, + appVersion: { + type: 'String' + }, + appName: { + type: 'String' + }, + appIdentifier: { + type: 'String' + }, + parseVersion: { + type: 'String' + } + }, + // The additional default columns for the _Role collection (in addition to DefaultCols) + _Role: { + name: { + type: 'String' + }, + users: { + type: 'Relation', + targetClass: '_User' + }, + roles: { + type: 'Relation', + targetClass: '_Role' + } + }, + // The additional default columns for the _Session collection (in addition to DefaultCols) + _Session: { + restricted: { + type: 'Boolean' + }, + user: { + type: 'Pointer', + targetClass: '_User' + }, + installationId: { + type: 'String' + }, + sessionToken: { + type: 'String' + }, + expiresAt: { + type: 'Date' + }, + createdWith: { + type: 'Object' + } + }, + _Product: { + productIdentifier: { + type: 'String' + }, + download: { + type: 'File' + }, + downloadName: { + type: 'String' + }, + icon: { + type: 'File' + }, + order: { + type: 'Number' + }, + title: { + type: 'String' + }, + subtitle: { + type: 'String' + } + }, + _PushStatus: { + pushTime: { + type: 'String' + }, + source: { + type: 'String' + }, + // rest or webui + query: { + type: 'String' + }, + // the stringified JSON query + payload: { + type: 'String' + }, + // the stringified JSON payload, + title: { + type: 'String' + }, + expiry: { + type: 'Number' + }, + expiration_interval: { + type: 'Number' + }, + status: { + type: 'String' + }, + numSent: { + type: 'Number' + }, + numFailed: { + type: 'Number' + }, + pushHash: { + type: 'String' + }, + errorMessage: { + type: 'Object' + }, + sentPerType: { + type: 'Object' + }, + failedPerType: { + type: 'Object' + }, + sentPerUTCOffset: { + type: 'Object' + }, + failedPerUTCOffset: { + type: 'Object' + }, + count: { + type: 'Number' + } // tracks # of batches queued and pending + + }, + _JobStatus: { + jobName: { + type: 'String' + }, + source: { + type: 'String' + }, + status: { + type: 'String' + }, + message: { + type: 'String' + }, + params: { + type: 'Object' + }, + // params received when calling the job + finishedAt: { + type: 'Date' + } + }, + _JobSchedule: { + jobName: { + type: 'String' + }, + description: { + type: 'String' + }, + params: { + type: 'String' + }, + startAfter: { + type: 'String' + }, + daysOfWeek: { + type: 'Array' + }, + timeOfDay: { + type: 'String' + }, + lastRun: { + type: 'Number' + }, + repeatMinutes: { + type: 'Number' + } + }, + _Hooks: { + functionName: { + type: 'String' + }, + className: { + type: 'String' + }, + triggerName: { + type: 'String' + }, + url: { + type: 'String' + } + }, + _GlobalConfig: { + objectId: { + type: 'String' + }, + params: { + type: 'Object' + }, + masterKeyOnly: { + type: 'Object' + } + }, + _GraphQLConfig: { + objectId: { + type: 'String' + }, + config: { + type: 'Object' + } + }, + _Audience: { + objectId: { + type: 'String' + }, + name: { + type: 'String' + }, + query: { + type: 'String' + }, + //storing query as JSON string to prevent "Nested keys should not contain the '$' or '.' characters" error + lastUsed: { + type: 'Date' + }, + timesUsed: { + type: 'Number' + } + } +}); +exports.defaultColumns = defaultColumns; +const requiredColumns = Object.freeze({ + _Product: ['productIdentifier', 'icon', 'order', 'title', 'subtitle'], + _Role: ['name', 'ACL'] +}); +const systemClasses = Object.freeze(['_User', '_Installation', '_Role', '_Session', '_Product', '_PushStatus', '_JobStatus', '_JobSchedule', '_Audience']); +exports.systemClasses = systemClasses; +const volatileClasses = Object.freeze(['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig', '_GraphQLConfig', '_JobSchedule', '_Audience']); // 10 alpha numberic chars + uppercase + +const userIdRegex = /^[a-zA-Z0-9]{10}$/; // Anything that start with role + +const roleRegex = /^role:.*/; // Anything that starts with userField + +const pointerPermissionRegex = /^userField:.*/; // * permission + +const publicRegex = /^\*$/; +const requireAuthenticationRegex = /^requiresAuthentication$/; +const permissionKeyRegex = Object.freeze([userIdRegex, roleRegex, pointerPermissionRegex, publicRegex, requireAuthenticationRegex]); + +function verifyPermissionKey(key) { + const result = permissionKeyRegex.reduce((isGood, regEx) => { + isGood = isGood || key.match(regEx) != null; + return isGood; + }, false); + + if (!result) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid key for class level permissions`); + } +} + +const CLPValidKeys = Object.freeze(['find', 'count', 'get', 'create', 'update', 'delete', 'addField', 'readUserFields', 'writeUserFields', 'protectedFields']); + +function validateCLP(perms, fields) { + if (!perms) { + return; + } + + Object.keys(perms).forEach(operation => { + if (CLPValidKeys.indexOf(operation) == -1) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `${operation} is not a valid operation for class level permissions`); + } + + if (!perms[operation]) { + return; + } + + if (operation === 'readUserFields' || operation === 'writeUserFields') { + if (!Array.isArray(perms[operation])) { + // -disable-next + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${perms[operation]}' is not a valid value for class level permissions ${operation}`); + } else { + perms[operation].forEach(key => { + if (!(fields[key] && (fields[key].type == 'Pointer' && fields[key].targetClass == '_User' || fields[key].type == 'Array'))) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid column for class level pointer permissions ${operation}`); + } + }); + } + + return; + } // -disable-next + + + Object.keys(perms[operation]).forEach(key => { + verifyPermissionKey(key); // -disable-next + + const perm = perms[operation][key]; + + if (perm !== true && (operation !== 'protectedFields' || !Array.isArray(perm))) { + // -disable-next + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${perm}' is not a valid value for class level permissions ${operation}:${key}:${perm}`); + } + }); + }); +} + +const joinClassRegex = /^_Join:[A-Za-z0-9_]+:[A-Za-z0-9_]+/; +const classAndFieldRegex = /^[A-Za-z][A-Za-z0-9_]*$/; + +function classNameIsValid(className) { + // Valid classes must: + return (// Be one of _User, _Installation, _Role, _Session OR + systemClasses.indexOf(className) > -1 || // Be a join table OR + joinClassRegex.test(className) || // Include only alpha-numeric and underscores, and not start with an underscore or number + fieldNameIsValid(className) + ); +} // Valid fields must be alpha-numeric, and not start with an underscore or number + + +function fieldNameIsValid(fieldName) { + return classAndFieldRegex.test(fieldName); +} // Checks that it's not trying to clobber one of the default fields of the class. + + +function fieldNameIsValidForClass(fieldName, className) { + if (!fieldNameIsValid(fieldName)) { + return false; + } + + if (defaultColumns._Default[fieldName]) { + return false; + } + + if (defaultColumns[className] && defaultColumns[className][fieldName]) { + return false; + } + + return true; +} + +function invalidClassNameMessage(className) { + return 'Invalid classname: ' + className + ', classnames can only have alphanumeric characters and _, and must start with an alpha character '; +} + +const invalidJsonError = new Parse.Error(Parse.Error.INVALID_JSON, 'invalid JSON'); +const validNonRelationOrPointerTypes = ['Number', 'String', 'Boolean', 'Date', 'Object', 'Array', 'GeoPoint', 'File', 'Bytes', 'Polygon']; // Returns an error suitable for throwing if the type is invalid + +const fieldTypeIsInvalid = ({ + type, + targetClass +}) => { + if (['Pointer', 'Relation'].indexOf(type) >= 0) { + if (!targetClass) { + return new Parse.Error(135, `type ${type} needs a class name`); + } else if (typeof targetClass !== 'string') { + return invalidJsonError; + } else if (!classNameIsValid(targetClass)) { + return new Parse.Error(Parse.Error.INVALID_CLASS_NAME, invalidClassNameMessage(targetClass)); + } else { + return undefined; + } + } + + if (typeof type !== 'string') { + return invalidJsonError; + } + + if (validNonRelationOrPointerTypes.indexOf(type) < 0) { + return new Parse.Error(Parse.Error.INCORRECT_TYPE, `invalid field type: ${type}`); + } + + return undefined; +}; + +const convertSchemaToAdapterSchema = schema => { + schema = injectDefaultSchema(schema); + delete schema.fields.ACL; + schema.fields._rperm = { + type: 'Array' + }; + schema.fields._wperm = { + type: 'Array' + }; + + if (schema.className === '_User') { + delete schema.fields.password; + schema.fields._hashed_password = { + type: 'String' + }; + } + + return schema; +}; + +exports.convertSchemaToAdapterSchema = convertSchemaToAdapterSchema; + +const convertAdapterSchemaToParseSchema = (_ref) => { + let schema = _extends({}, _ref); + + delete schema.fields._rperm; + delete schema.fields._wperm; + schema.fields.ACL = { + type: 'ACL' + }; + + if (schema.className === '_User') { + delete schema.fields.authData; //Auth data is implicit + + delete schema.fields._hashed_password; + schema.fields.password = { + type: 'String' + }; + } + + if (schema.indexes && Object.keys(schema.indexes).length === 0) { + delete schema.indexes; + } + + return schema; +}; + +class SchemaData { + constructor(allSchemas = [], protectedFields = {}) { + this.__data = {}; + this.__protectedFields = protectedFields; + allSchemas.forEach(schema => { + if (volatileClasses.includes(schema.className)) { + return; + } + + Object.defineProperty(this, schema.className, { + get: () => { + if (!this.__data[schema.className]) { + const data = {}; + data.fields = injectDefaultSchema(schema).fields; + data.classLevelPermissions = (0, _deepcopy.default)(schema.classLevelPermissions); + data.indexes = schema.indexes; + const classProtectedFields = this.__protectedFields[schema.className]; + + if (classProtectedFields) { + for (const key in classProtectedFields) { + const unq = new Set([...(data.classLevelPermissions.protectedFields[key] || []), ...classProtectedFields[key]]); + data.classLevelPermissions.protectedFields[key] = Array.from(unq); + } + } + + this.__data[schema.className] = data; + } + + return this.__data[schema.className]; + } + }); + }); // Inject the in-memory classes + + volatileClasses.forEach(className => { + Object.defineProperty(this, className, { + get: () => { + if (!this.__data[className]) { + const schema = injectDefaultSchema({ + className, + fields: {}, + classLevelPermissions: {} + }); + const data = {}; + data.fields = schema.fields; + data.classLevelPermissions = schema.classLevelPermissions; + data.indexes = schema.indexes; + this.__data[className] = data; + } + + return this.__data[className]; + } + }); + }); + } + +} + +const injectDefaultSchema = ({ + className, + fields, + classLevelPermissions, + indexes +}) => { + const defaultSchema = { + className, + fields: _objectSpread({}, defaultColumns._Default, {}, defaultColumns[className] || {}, {}, fields), + classLevelPermissions + }; + + if (indexes && Object.keys(indexes).length !== 0) { + defaultSchema.indexes = indexes; + } + + return defaultSchema; +}; + +const _HooksSchema = { + className: '_Hooks', + fields: defaultColumns._Hooks +}; +const _GlobalConfigSchema = { + className: '_GlobalConfig', + fields: defaultColumns._GlobalConfig +}; +const _GraphQLConfigSchema = { + className: '_GraphQLConfig', + fields: defaultColumns._GraphQLConfig +}; + +const _PushStatusSchema = convertSchemaToAdapterSchema(injectDefaultSchema({ + className: '_PushStatus', + fields: {}, + classLevelPermissions: {} +})); + +const _JobStatusSchema = convertSchemaToAdapterSchema(injectDefaultSchema({ + className: '_JobStatus', + fields: {}, + classLevelPermissions: {} +})); + +const _JobScheduleSchema = convertSchemaToAdapterSchema(injectDefaultSchema({ + className: '_JobSchedule', + fields: {}, + classLevelPermissions: {} +})); + +const _AudienceSchema = convertSchemaToAdapterSchema(injectDefaultSchema({ + className: '_Audience', + fields: defaultColumns._Audience, + classLevelPermissions: {} +})); + +const VolatileClassesSchemas = [_HooksSchema, _JobStatusSchema, _JobScheduleSchema, _PushStatusSchema, _GlobalConfigSchema, _GraphQLConfigSchema, _AudienceSchema]; +exports.VolatileClassesSchemas = VolatileClassesSchemas; + +const dbTypeMatchesObjectType = (dbType, objectType) => { + if (dbType.type !== objectType.type) return false; + if (dbType.targetClass !== objectType.targetClass) return false; + if (dbType === objectType.type) return true; + if (dbType.type === objectType.type) return true; + return false; +}; + +const typeToString = type => { + if (typeof type === 'string') { + return type; + } + + if (type.targetClass) { + return `${type.type}<${type.targetClass}>`; + } + + return `${type.type}`; +}; // Stores the entire schema of the app in a weird hybrid format somewhere between +// the mongo format and the Parse format. Soon, this will all be Parse format. + + +class SchemaController { + constructor(databaseAdapter, schemaCache) { + this._dbAdapter = databaseAdapter; + this._cache = schemaCache; + this.schemaData = new SchemaData(); + this.protectedFields = _Config.default.get(Parse.applicationId).protectedFields; + } + + reloadData(options = { + clearCache: false + }) { + if (this.reloadDataPromise && !options.clearCache) { + return this.reloadDataPromise; + } + + this.reloadDataPromise = this.getAllClasses(options).then(allSchemas => { + this.schemaData = new SchemaData(allSchemas, this.protectedFields); + delete this.reloadDataPromise; + }, err => { + this.schemaData = new SchemaData(); + delete this.reloadDataPromise; + throw err; + }).then(() => {}); + return this.reloadDataPromise; + } + + getAllClasses(options = { + clearCache: false + }) { + if (options.clearCache) { + return this.setAllClasses(); + } + + return this._cache.getAllClasses().then(allClasses => { + if (allClasses && allClasses.length) { + return Promise.resolve(allClasses); + } + + return this.setAllClasses(); + }); + } + + setAllClasses() { + return this._dbAdapter.getAllClasses().then(allSchemas => allSchemas.map(injectDefaultSchema)).then(allSchemas => { + /* eslint-disable no-console */ + this._cache.setAllClasses(allSchemas).catch(error => console.error('Error saving schema to cache:', error)); + /* eslint-enable no-console */ + + + return allSchemas; + }); + } + + getOneSchema(className, allowVolatileClasses = false, options = { + clearCache: false + }) { + let promise = Promise.resolve(); + + if (options.clearCache) { + promise = this._cache.clear(); + } + + return promise.then(() => { + if (allowVolatileClasses && volatileClasses.indexOf(className) > -1) { + const data = this.schemaData[className]; + return Promise.resolve({ + className, + fields: data.fields, + classLevelPermissions: data.classLevelPermissions, + indexes: data.indexes + }); + } + + return this._cache.getOneSchema(className).then(cached => { + if (cached && !options.clearCache) { + return Promise.resolve(cached); + } + + return this.setAllClasses().then(allSchemas => { + const oneSchema = allSchemas.find(schema => schema.className === className); + + if (!oneSchema) { + return Promise.reject(undefined); + } + + return oneSchema; + }); + }); + }); + } // Create a new class that includes the three default fields. + // ACL is an implicit column that does not get an entry in the + // _SCHEMAS database. Returns a promise that resolves with the + // created schema, in mongo format. + // on success, and rejects with an error on fail. Ensure you + // have authorization (master key, or client class creation + // enabled) before calling this function. + + + addClassIfNotExists(className, fields = {}, classLevelPermissions, indexes = {}) { + var validationError = this.validateNewClass(className, fields, classLevelPermissions); + + if (validationError) { + if (validationError instanceof Parse.Error) { + return Promise.reject(validationError); + } else if (validationError.code && validationError.error) { + return Promise.reject(new Parse.Error(validationError.code, validationError.error)); + } + + return Promise.reject(validationError); + } + + return this._dbAdapter.createClass(className, convertSchemaToAdapterSchema({ + fields, + classLevelPermissions, + indexes, + className + })).then(convertAdapterSchemaToParseSchema).catch(error => { + if (error && error.code === Parse.Error.DUPLICATE_VALUE) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, `Class ${className} already exists.`); + } else { + throw error; + } + }); + } + + updateClass(className, submittedFields, classLevelPermissions, indexes, database) { + return this.getOneSchema(className).then(schema => { + const existingFields = schema.fields; + Object.keys(submittedFields).forEach(name => { + const field = submittedFields[name]; + + if (existingFields[name] && field.__op !== 'Delete') { + throw new Parse.Error(255, `Field ${name} exists, cannot update.`); + } + + if (!existingFields[name] && field.__op === 'Delete') { + throw new Parse.Error(255, `Field ${name} does not exist, cannot delete.`); + } + }); + delete existingFields._rperm; + delete existingFields._wperm; + const newSchema = buildMergedSchemaObject(existingFields, submittedFields); + const defaultFields = defaultColumns[className] || defaultColumns._Default; + const fullNewSchema = Object.assign({}, newSchema, defaultFields); + const validationError = this.validateSchemaData(className, newSchema, classLevelPermissions, Object.keys(existingFields)); + + if (validationError) { + throw new Parse.Error(validationError.code, validationError.error); + } // Finally we have checked to make sure the request is valid and we can start deleting fields. + // Do all deletions first, then a single save to _SCHEMA collection to handle all additions. + + + const deletedFields = []; + const insertedFields = []; + Object.keys(submittedFields).forEach(fieldName => { + if (submittedFields[fieldName].__op === 'Delete') { + deletedFields.push(fieldName); + } else { + insertedFields.push(fieldName); + } + }); + let deletePromise = Promise.resolve(); + + if (deletedFields.length > 0) { + deletePromise = this.deleteFields(deletedFields, className, database); + } + + let enforceFields = []; + return deletePromise // Delete Everything + .then(() => this.reloadData({ + clearCache: true + })) // Reload our Schema, so we have all the new values + .then(() => { + const promises = insertedFields.map(fieldName => { + const type = submittedFields[fieldName]; + return this.enforceFieldExists(className, fieldName, type); + }); + return Promise.all(promises); + }).then(results => { + enforceFields = results.filter(result => !!result); + return this.setPermissions(className, classLevelPermissions, newSchema); + }).then(() => this._dbAdapter.setIndexesWithSchemaFormat(className, indexes, schema.indexes, fullNewSchema)).then(() => this.reloadData({ + clearCache: true + })) //TODO: Move this logic into the database adapter + .then(() => { + this.ensureFields(enforceFields); + const schema = this.schemaData[className]; + const reloadedSchema = { + className: className, + fields: schema.fields, + classLevelPermissions: schema.classLevelPermissions + }; + + if (schema.indexes && Object.keys(schema.indexes).length !== 0) { + reloadedSchema.indexes = schema.indexes; + } + + return reloadedSchema; + }); + }).catch(error => { + if (error === undefined) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, `Class ${className} does not exist.`); + } else { + throw error; + } + }); + } // Returns a promise that resolves successfully to the new schema + // object or fails with a reason. + + + enforceClassExists(className) { + if (this.schemaData[className]) { + return Promise.resolve(this); + } // We don't have this class. Update the schema + + + return this.addClassIfNotExists(className) // The schema update succeeded. Reload the schema + .then(() => this.reloadData({ + clearCache: true + })).catch(() => { + // The schema update failed. This can be okay - it might + // have failed because there's a race condition and a different + // client is making the exact same schema update that we want. + // So just reload the schema. + return this.reloadData({ + clearCache: true + }); + }).then(() => { + // Ensure that the schema now validates + if (this.schemaData[className]) { + return this; + } else { + throw new Parse.Error(Parse.Error.INVALID_JSON, `Failed to add ${className}`); + } + }).catch(() => { + // The schema still doesn't validate. Give up + throw new Parse.Error(Parse.Error.INVALID_JSON, 'schema class name does not revalidate'); + }); + } + + validateNewClass(className, fields = {}, classLevelPermissions) { + if (this.schemaData[className]) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, `Class ${className} already exists.`); + } + + if (!classNameIsValid(className)) { + return { + code: Parse.Error.INVALID_CLASS_NAME, + error: invalidClassNameMessage(className) + }; + } + + return this.validateSchemaData(className, fields, classLevelPermissions, []); + } + + validateSchemaData(className, fields, classLevelPermissions, existingFieldNames) { + for (const fieldName in fields) { + if (existingFieldNames.indexOf(fieldName) < 0) { + if (!fieldNameIsValid(fieldName)) { + return { + code: Parse.Error.INVALID_KEY_NAME, + error: 'invalid field name: ' + fieldName + }; + } + + if (!fieldNameIsValidForClass(fieldName, className)) { + return { + code: 136, + error: 'field ' + fieldName + ' cannot be added' + }; + } + + const fieldType = fields[fieldName]; + const error = fieldTypeIsInvalid(fieldType); + if (error) return { + code: error.code, + error: error.message + }; + + if (fieldType.defaultValue !== undefined) { + let defaultValueType = getType(fieldType.defaultValue); + + if (typeof defaultValueType === 'string') { + defaultValueType = { + type: defaultValueType + }; + } else if (typeof defaultValueType === 'object' && fieldType.type === 'Relation') { + return { + code: Parse.Error.INCORRECT_TYPE, + error: `The 'default value' option is not applicable for ${typeToString(fieldType)}` + }; + } + + if (!dbTypeMatchesObjectType(fieldType, defaultValueType)) { + return { + code: Parse.Error.INCORRECT_TYPE, + error: `schema mismatch for ${className}.${fieldName} default value; expected ${typeToString(fieldType)} but got ${typeToString(defaultValueType)}` + }; + } + } else if (fieldType.required) { + if (typeof fieldType === 'object' && fieldType.type === 'Relation') { + return { + code: Parse.Error.INCORRECT_TYPE, + error: `The 'required' option is not applicable for ${typeToString(fieldType)}` + }; + } + } + } + } + + for (const fieldName in defaultColumns[className]) { + fields[fieldName] = defaultColumns[className][fieldName]; + } + + const geoPoints = Object.keys(fields).filter(key => fields[key] && fields[key].type === 'GeoPoint'); + + if (geoPoints.length > 1) { + return { + code: Parse.Error.INCORRECT_TYPE, + error: 'currently, only one GeoPoint field may exist in an object. Adding ' + geoPoints[1] + ' when ' + geoPoints[0] + ' already exists.' + }; + } + + validateCLP(classLevelPermissions, fields); + } // Sets the Class-level permissions for a given className, which must exist. + + + setPermissions(className, perms, newSchema) { + if (typeof perms === 'undefined') { + return Promise.resolve(); + } + + validateCLP(perms, newSchema); + return this._dbAdapter.setClassLevelPermissions(className, perms); + } // Returns a promise that resolves successfully to the new schema + // object if the provided className-fieldName-type tuple is valid. + // The className must already be validated. + // If 'freeze' is true, refuse to update the schema for this field. + + + enforceFieldExists(className, fieldName, type) { + if (fieldName.indexOf('.') > 0) { + // subdocument key (x.y) => ok if x is of type 'object' + fieldName = fieldName.split('.')[0]; + type = 'Object'; + } + + if (!fieldNameIsValid(fieldName)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}.`); + } // If someone tries to create a new field with null/undefined as the value, return; + + + if (!type) { + return undefined; + } + + const expectedType = this.getExpectedType(className, fieldName); + + if (typeof type === 'string') { + type = { + type + }; + } + + if (type.defaultValue !== undefined) { + let defaultValueType = getType(type.defaultValue); + + if (typeof defaultValueType === 'string') { + defaultValueType = { + type: defaultValueType + }; + } + + if (!dbTypeMatchesObjectType(type, defaultValueType)) { + throw new Parse.Error(Parse.Error.INCORRECT_TYPE, `schema mismatch for ${className}.${fieldName} default value; expected ${typeToString(type)} but got ${typeToString(defaultValueType)}`); + } + } + + if (expectedType) { + if (!dbTypeMatchesObjectType(expectedType, type)) { + throw new Parse.Error(Parse.Error.INCORRECT_TYPE, `schema mismatch for ${className}.${fieldName}; expected ${typeToString(expectedType)} but got ${typeToString(type)}`); + } + + return undefined; + } + + return this._dbAdapter.addFieldIfNotExists(className, fieldName, type).catch(error => { + if (error.code == Parse.Error.INCORRECT_TYPE) { + // Make sure that we throw errors when it is appropriate to do so. + throw error; + } // The update failed. This can be okay - it might have been a race + // condition where another client updated the schema in the same + // way that we wanted to. So, just reload the schema + + + return Promise.resolve(); + }).then(() => { + return { + className, + fieldName, + type + }; + }); + } + + ensureFields(fields) { + for (let i = 0; i < fields.length; i += 1) { + const { + className, + fieldName + } = fields[i]; + let { + type + } = fields[i]; + const expectedType = this.getExpectedType(className, fieldName); + + if (typeof type === 'string') { + type = { + type: type + }; + } + + if (!expectedType || !dbTypeMatchesObjectType(expectedType, type)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `Could not add field ${fieldName}`); + } + } + } // maintain compatibility + + + deleteField(fieldName, className, database) { + return this.deleteFields([fieldName], className, database); + } // Delete fields, and remove that data from all objects. This is intended + // to remove unused fields, if other writers are writing objects that include + // this field, the field may reappear. Returns a Promise that resolves with + // no object on success, or rejects with { code, error } on failure. + // Passing the database and prefix is necessary in order to drop relation collections + // and remove fields from objects. Ideally the database would belong to + // a database adapter and this function would close over it or access it via member. + + + deleteFields(fieldNames, className, database) { + if (!classNameIsValid(className)) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, invalidClassNameMessage(className)); + } + + fieldNames.forEach(fieldName => { + if (!fieldNameIsValid(fieldName)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `invalid field name: ${fieldName}`); + } //Don't allow deleting the default fields. + + + if (!fieldNameIsValidForClass(fieldName, className)) { + throw new Parse.Error(136, `field ${fieldName} cannot be changed`); + } + }); + return this.getOneSchema(className, false, { + clearCache: true + }).catch(error => { + if (error === undefined) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, `Class ${className} does not exist.`); + } else { + throw error; + } + }).then(schema => { + fieldNames.forEach(fieldName => { + if (!schema.fields[fieldName]) { + throw new Parse.Error(255, `Field ${fieldName} does not exist, cannot delete.`); + } + }); + + const schemaFields = _objectSpread({}, schema.fields); + + return database.adapter.deleteFields(className, schema, fieldNames).then(() => { + return Promise.all(fieldNames.map(fieldName => { + const field = schemaFields[fieldName]; + + if (field && field.type === 'Relation') { + //For relations, drop the _Join table + return database.adapter.deleteClass(`_Join:${fieldName}:${className}`); + } + + return Promise.resolve(); + })); + }); + }).then(() => this._cache.clear()); + } // Validates an object provided in REST format. + // Returns a promise that resolves to the new schema if this object is + // valid. + + + async validateObject(className, object, query) { + let geocount = 0; + const schema = await this.enforceClassExists(className); + const promises = []; + + for (const fieldName in object) { + if (object[fieldName] === undefined) { + continue; + } + + const expected = getType(object[fieldName]); + + if (expected === 'GeoPoint') { + geocount++; + } + + if (geocount > 1) { + // Make sure all field validation operations run before we return. + // If not - we are continuing to run logic, but already provided response from the server. + return Promise.reject(new Parse.Error(Parse.Error.INCORRECT_TYPE, 'there can only be one geopoint field in a class')); + } + + if (!expected) { + continue; + } + + if (fieldName === 'ACL') { + // Every object has ACL implicitly. + continue; + } + + promises.push(schema.enforceFieldExists(className, fieldName, expected)); + } + + const results = await Promise.all(promises); + const enforceFields = results.filter(result => !!result); + + if (enforceFields.length !== 0) { + await this.reloadData({ + clearCache: true + }); + } + + this.ensureFields(enforceFields); + const promise = Promise.resolve(schema); + return thenValidateRequiredColumns(promise, className, object, query); + } // Validates that all the properties are set for the object + + + validateRequiredColumns(className, object, query) { + const columns = requiredColumns[className]; + + if (!columns || columns.length == 0) { + return Promise.resolve(this); + } + + const missingColumns = columns.filter(function (column) { + if (query && query.objectId) { + if (object[column] && typeof object[column] === 'object') { + // Trying to delete a required column + return object[column].__op == 'Delete'; + } // Not trying to do anything there + + + return false; + } + + return !object[column]; + }); + + if (missingColumns.length > 0) { + throw new Parse.Error(Parse.Error.INCORRECT_TYPE, missingColumns[0] + ' is required.'); + } + + return Promise.resolve(this); + } + + testPermissionsForClassName(className, aclGroup, operation) { + return SchemaController.testPermissions(this.getClassLevelPermissions(className), aclGroup, operation); + } // Tests that the class level permission let pass the operation for a given aclGroup + + + static testPermissions(classPermissions, aclGroup, operation) { + if (!classPermissions || !classPermissions[operation]) { + return true; + } + + const perms = classPermissions[operation]; + + if (perms['*']) { + return true; + } // Check permissions against the aclGroup provided (array of userId/roles) + + + if (aclGroup.some(acl => { + return perms[acl] === true; + })) { + return true; + } + + return false; + } // Validates an operation passes class-level-permissions set in the schema + + + static validatePermission(classPermissions, className, aclGroup, operation) { + if (SchemaController.testPermissions(classPermissions, aclGroup, operation)) { + return Promise.resolve(); + } + + if (!classPermissions || !classPermissions[operation]) { + return true; + } + + const perms = classPermissions[operation]; // If only for authenticated users + // make sure we have an aclGroup + + if (perms['requiresAuthentication']) { + // If aclGroup has * (public) + if (!aclGroup || aclGroup.length == 0) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Permission denied, user needs to be authenticated.'); + } else if (aclGroup.indexOf('*') > -1 && aclGroup.length == 1) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Permission denied, user needs to be authenticated.'); + } // requiresAuthentication passed, just move forward + // probably would be wise at some point to rename to 'authenticatedUser' + + + return Promise.resolve(); + } // No matching CLP, let's check the Pointer permissions + // And handle those later + + + const permissionField = ['get', 'find', 'count'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields'; // Reject create when write lockdown + + if (permissionField == 'writeUserFields' && operation == 'create') { + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, `Permission denied for action ${operation} on class ${className}.`); + } // Process the readUserFields later + + + if (Array.isArray(classPermissions[permissionField]) && classPermissions[permissionField].length > 0) { + return Promise.resolve(); + } + + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, `Permission denied for action ${operation} on class ${className}.`); + } // Validates an operation passes class-level-permissions set in the schema + + + validatePermission(className, aclGroup, operation) { + return SchemaController.validatePermission(this.getClassLevelPermissions(className), className, aclGroup, operation); + } + + getClassLevelPermissions(className) { + return this.schemaData[className] && this.schemaData[className].classLevelPermissions; + } // Returns the expected type for a className+key combination + // or undefined if the schema is not set + + + getExpectedType(className, fieldName) { + if (this.schemaData[className]) { + const expectedType = this.schemaData[className].fields[fieldName]; + return expectedType === 'map' ? 'Object' : expectedType; + } + + return undefined; + } // Checks if a given class is in the schema. + + + hasClass(className) { + if (this.schemaData[className]) { + return Promise.resolve(true); + } + + return this.reloadData().then(() => !!this.schemaData[className]); + } + +} // Returns a promise for a new Schema. + + +exports.SchemaController = exports.default = SchemaController; + +const load = (dbAdapter, schemaCache, options) => { + const schema = new SchemaController(dbAdapter, schemaCache); + return schema.reloadData(options).then(() => schema); +}; // Builds a new schema (in schema API response format) out of an +// existing mongo schema + a schemas API put request. This response +// does not include the default fields, as it is intended to be passed +// to mongoSchemaFromFieldsAndClassName. No validation is done here, it +// is done in mongoSchemaFromFieldsAndClassName. + + +exports.load = load; + +function buildMergedSchemaObject(existingFields, putRequest) { + const newSchema = {}; // -disable-next + + const sysSchemaField = Object.keys(defaultColumns).indexOf(existingFields._id) === -1 ? [] : Object.keys(defaultColumns[existingFields._id]); + + for (const oldField in existingFields) { + if (oldField !== '_id' && oldField !== 'ACL' && oldField !== 'updatedAt' && oldField !== 'createdAt' && oldField !== 'objectId') { + if (sysSchemaField.length > 0 && sysSchemaField.indexOf(oldField) !== -1) { + continue; + } + + const fieldIsDeleted = putRequest[oldField] && putRequest[oldField].__op === 'Delete'; + + if (!fieldIsDeleted) { + newSchema[oldField] = existingFields[oldField]; + } + } + } + + for (const newField in putRequest) { + if (newField !== 'objectId' && putRequest[newField].__op !== 'Delete') { + if (sysSchemaField.length > 0 && sysSchemaField.indexOf(newField) !== -1) { + continue; + } + + newSchema[newField] = putRequest[newField]; + } + } + + return newSchema; +} // Given a schema promise, construct another schema promise that +// validates this field once the schema loads. + + +function thenValidateRequiredColumns(schemaPromise, className, object, query) { + return schemaPromise.then(schema => { + return schema.validateRequiredColumns(className, object, query); + }); +} // Gets the type from a REST API formatted object, where 'type' is +// extended past javascript types to include the rest of the Parse +// type system. +// The output should be a valid schema value. +// TODO: ensure that this is compatible with the format used in Open DB + + +function getType(obj) { + const type = typeof obj; + + switch (type) { + case 'boolean': + return 'Boolean'; + + case 'string': + return 'String'; + + case 'number': + return 'Number'; + + case 'map': + case 'object': + if (!obj) { + return undefined; + } + + return getObjectType(obj); + + case 'function': + case 'symbol': + case 'undefined': + default: + throw 'bad obj: ' + obj; + } +} // This gets the type for non-JSON types like pointers and files, but +// also gets the appropriate type for $ operators. +// Returns null if the type is unknown. + + +function getObjectType(obj) { + if (obj instanceof Array) { + return 'Array'; + } + + if (obj.__type) { + switch (obj.__type) { + case 'Pointer': + if (obj.className) { + return { + type: 'Pointer', + targetClass: obj.className + }; + } + + break; + + case 'Relation': + if (obj.className) { + return { + type: 'Relation', + targetClass: obj.className + }; + } + + break; + + case 'File': + if (obj.name) { + return 'File'; + } + + break; + + case 'Date': + if (obj.iso) { + return 'Date'; + } + + break; + + case 'GeoPoint': + if (obj.latitude != null && obj.longitude != null) { + return 'GeoPoint'; + } + + break; + + case 'Bytes': + if (obj.base64) { + return 'Bytes'; + } + + break; + + case 'Polygon': + if (obj.coordinates) { + return 'Polygon'; + } + + break; + } + + throw new Parse.Error(Parse.Error.INCORRECT_TYPE, 'This is not a valid ' + obj.__type); + } + + if (obj['$ne']) { + return getObjectType(obj['$ne']); + } + + if (obj.__op) { + switch (obj.__op) { + case 'Increment': + return 'Number'; + + case 'Delete': + return null; + + case 'Add': + case 'AddUnique': + case 'Remove': + return 'Array'; + + case 'AddRelation': + case 'RemoveRelation': + return { + type: 'Relation', + targetClass: obj.objects[0].className + }; + + case 'Batch': + return getObjectType(obj.ops[0]); + + default: + throw 'unexpected op: ' + obj.__op; + } + } + + return 'Object'; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9TY2hlbWFDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsImRlZmF1bHRDb2x1bW5zIiwiT2JqZWN0IiwiZnJlZXplIiwiX0RlZmF1bHQiLCJvYmplY3RJZCIsInR5cGUiLCJjcmVhdGVkQXQiLCJ1cGRhdGVkQXQiLCJBQ0wiLCJfVXNlciIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJlbWFpbCIsImVtYWlsVmVyaWZpZWQiLCJhdXRoRGF0YSIsIl9JbnN0YWxsYXRpb24iLCJpbnN0YWxsYXRpb25JZCIsImRldmljZVRva2VuIiwiY2hhbm5lbHMiLCJkZXZpY2VUeXBlIiwicHVzaFR5cGUiLCJHQ01TZW5kZXJJZCIsInRpbWVab25lIiwibG9jYWxlSWRlbnRpZmllciIsImJhZGdlIiwiYXBwVmVyc2lvbiIsImFwcE5hbWUiLCJhcHBJZGVudGlmaWVyIiwicGFyc2VWZXJzaW9uIiwiX1JvbGUiLCJuYW1lIiwidXNlcnMiLCJ0YXJnZXRDbGFzcyIsInJvbGVzIiwiX1Nlc3Npb24iLCJyZXN0cmljdGVkIiwidXNlciIsInNlc3Npb25Ub2tlbiIsImV4cGlyZXNBdCIsImNyZWF0ZWRXaXRoIiwiX1Byb2R1Y3QiLCJwcm9kdWN0SWRlbnRpZmllciIsImRvd25sb2FkIiwiZG93bmxvYWROYW1lIiwiaWNvbiIsIm9yZGVyIiwidGl0bGUiLCJzdWJ0aXRsZSIsIl9QdXNoU3RhdHVzIiwicHVzaFRpbWUiLCJzb3VyY2UiLCJxdWVyeSIsInBheWxvYWQiLCJleHBpcnkiLCJleHBpcmF0aW9uX2ludGVydmFsIiwic3RhdHVzIiwibnVtU2VudCIsIm51bUZhaWxlZCIsInB1c2hIYXNoIiwiZXJyb3JNZXNzYWdlIiwic2VudFBlclR5cGUiLCJmYWlsZWRQZXJUeXBlIiwic2VudFBlclVUQ09mZnNldCIsImZhaWxlZFBlclVUQ09mZnNldCIsImNvdW50IiwiX0pvYlN0YXR1cyIsImpvYk5hbWUiLCJtZXNzYWdlIiwicGFyYW1zIiwiZmluaXNoZWRBdCIsIl9Kb2JTY2hlZHVsZSIsImRlc2NyaXB0aW9uIiwic3RhcnRBZnRlciIsImRheXNPZldlZWsiLCJ0aW1lT2ZEYXkiLCJsYXN0UnVuIiwicmVwZWF0TWludXRlcyIsIl9Ib29rcyIsImZ1bmN0aW9uTmFtZSIsImNsYXNzTmFtZSIsInRyaWdnZXJOYW1lIiwidXJsIiwiX0dsb2JhbENvbmZpZyIsIm1hc3RlcktleU9ubHkiLCJfR3JhcGhRTENvbmZpZyIsImNvbmZpZyIsIl9BdWRpZW5jZSIsImxhc3RVc2VkIiwidGltZXNVc2VkIiwicmVxdWlyZWRDb2x1bW5zIiwic3lzdGVtQ2xhc3NlcyIsInZvbGF0aWxlQ2xhc3NlcyIsInVzZXJJZFJlZ2V4Iiwicm9sZVJlZ2V4IiwicG9pbnRlclBlcm1pc3Npb25SZWdleCIsInB1YmxpY1JlZ2V4IiwicmVxdWlyZUF1dGhlbnRpY2F0aW9uUmVnZXgiLCJwZXJtaXNzaW9uS2V5UmVnZXgiLCJ2ZXJpZnlQZXJtaXNzaW9uS2V5Iiwia2V5IiwicmVzdWx0IiwicmVkdWNlIiwiaXNHb29kIiwicmVnRXgiLCJtYXRjaCIsIkVycm9yIiwiSU5WQUxJRF9KU09OIiwiQ0xQVmFsaWRLZXlzIiwidmFsaWRhdGVDTFAiLCJwZXJtcyIsImZpZWxkcyIsImtleXMiLCJmb3JFYWNoIiwib3BlcmF0aW9uIiwiaW5kZXhPZiIsIkFycmF5IiwiaXNBcnJheSIsInBlcm0iLCJqb2luQ2xhc3NSZWdleCIsImNsYXNzQW5kRmllbGRSZWdleCIsImNsYXNzTmFtZUlzVmFsaWQiLCJ0ZXN0IiwiZmllbGROYW1lSXNWYWxpZCIsImZpZWxkTmFtZSIsImZpZWxkTmFtZUlzVmFsaWRGb3JDbGFzcyIsImludmFsaWRDbGFzc05hbWVNZXNzYWdlIiwiaW52YWxpZEpzb25FcnJvciIsInZhbGlkTm9uUmVsYXRpb25PclBvaW50ZXJUeXBlcyIsImZpZWxkVHlwZUlzSW52YWxpZCIsIklOVkFMSURfQ0xBU1NfTkFNRSIsInVuZGVmaW5lZCIsIklOQ09SUkVDVF9UWVBFIiwiY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYSIsInNjaGVtYSIsImluamVjdERlZmF1bHRTY2hlbWEiLCJfcnBlcm0iLCJfd3Blcm0iLCJfaGFzaGVkX3Bhc3N3b3JkIiwiY29udmVydEFkYXB0ZXJTY2hlbWFUb1BhcnNlU2NoZW1hIiwiaW5kZXhlcyIsImxlbmd0aCIsIlNjaGVtYURhdGEiLCJjb25zdHJ1Y3RvciIsImFsbFNjaGVtYXMiLCJwcm90ZWN0ZWRGaWVsZHMiLCJfX2RhdGEiLCJfX3Byb3RlY3RlZEZpZWxkcyIsImluY2x1ZGVzIiwiZGVmaW5lUHJvcGVydHkiLCJnZXQiLCJkYXRhIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiY2xhc3NQcm90ZWN0ZWRGaWVsZHMiLCJ1bnEiLCJTZXQiLCJmcm9tIiwiZGVmYXVsdFNjaGVtYSIsIl9Ib29rc1NjaGVtYSIsIl9HbG9iYWxDb25maWdTY2hlbWEiLCJfR3JhcGhRTENvbmZpZ1NjaGVtYSIsIl9QdXNoU3RhdHVzU2NoZW1hIiwiX0pvYlN0YXR1c1NjaGVtYSIsIl9Kb2JTY2hlZHVsZVNjaGVtYSIsIl9BdWRpZW5jZVNjaGVtYSIsIlZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMiLCJkYlR5cGVNYXRjaGVzT2JqZWN0VHlwZSIsImRiVHlwZSIsIm9iamVjdFR5cGUiLCJ0eXBlVG9TdHJpbmciLCJTY2hlbWFDb250cm9sbGVyIiwiZGF0YWJhc2VBZGFwdGVyIiwic2NoZW1hQ2FjaGUiLCJfZGJBZGFwdGVyIiwiX2NhY2hlIiwic2NoZW1hRGF0YSIsIkNvbmZpZyIsImFwcGxpY2F0aW9uSWQiLCJyZWxvYWREYXRhIiwib3B0aW9ucyIsImNsZWFyQ2FjaGUiLCJyZWxvYWREYXRhUHJvbWlzZSIsImdldEFsbENsYXNzZXMiLCJ0aGVuIiwiZXJyIiwic2V0QWxsQ2xhc3NlcyIsImFsbENsYXNzZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsIm1hcCIsImNhdGNoIiwiZXJyb3IiLCJjb25zb2xlIiwiZ2V0T25lU2NoZW1hIiwiYWxsb3dWb2xhdGlsZUNsYXNzZXMiLCJwcm9taXNlIiwiY2xlYXIiLCJjYWNoZWQiLCJvbmVTY2hlbWEiLCJmaW5kIiwicmVqZWN0IiwiYWRkQ2xhc3NJZk5vdEV4aXN0cyIsInZhbGlkYXRpb25FcnJvciIsInZhbGlkYXRlTmV3Q2xhc3MiLCJjb2RlIiwiY3JlYXRlQ2xhc3MiLCJEVVBMSUNBVEVfVkFMVUUiLCJ1cGRhdGVDbGFzcyIsInN1Ym1pdHRlZEZpZWxkcyIsImRhdGFiYXNlIiwiZXhpc3RpbmdGaWVsZHMiLCJmaWVsZCIsIl9fb3AiLCJuZXdTY2hlbWEiLCJidWlsZE1lcmdlZFNjaGVtYU9iamVjdCIsImRlZmF1bHRGaWVsZHMiLCJmdWxsTmV3U2NoZW1hIiwiYXNzaWduIiwidmFsaWRhdGVTY2hlbWFEYXRhIiwiZGVsZXRlZEZpZWxkcyIsImluc2VydGVkRmllbGRzIiwicHVzaCIsImRlbGV0ZVByb21pc2UiLCJkZWxldGVGaWVsZHMiLCJlbmZvcmNlRmllbGRzIiwicHJvbWlzZXMiLCJlbmZvcmNlRmllbGRFeGlzdHMiLCJhbGwiLCJyZXN1bHRzIiwiZmlsdGVyIiwic2V0UGVybWlzc2lvbnMiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsImVuc3VyZUZpZWxkcyIsInJlbG9hZGVkU2NoZW1hIiwiZW5mb3JjZUNsYXNzRXhpc3RzIiwiZXhpc3RpbmdGaWVsZE5hbWVzIiwiSU5WQUxJRF9LRVlfTkFNRSIsImZpZWxkVHlwZSIsImRlZmF1bHRWYWx1ZSIsImRlZmF1bHRWYWx1ZVR5cGUiLCJnZXRUeXBlIiwicmVxdWlyZWQiLCJnZW9Qb2ludHMiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJzcGxpdCIsImV4cGVjdGVkVHlwZSIsImdldEV4cGVjdGVkVHlwZSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJpIiwiZGVsZXRlRmllbGQiLCJmaWVsZE5hbWVzIiwic2NoZW1hRmllbGRzIiwiYWRhcHRlciIsImRlbGV0ZUNsYXNzIiwidmFsaWRhdGVPYmplY3QiLCJvYmplY3QiLCJnZW9jb3VudCIsImV4cGVjdGVkIiwidGhlblZhbGlkYXRlUmVxdWlyZWRDb2x1bW5zIiwidmFsaWRhdGVSZXF1aXJlZENvbHVtbnMiLCJjb2x1bW5zIiwibWlzc2luZ0NvbHVtbnMiLCJjb2x1bW4iLCJ0ZXN0UGVybWlzc2lvbnNGb3JDbGFzc05hbWUiLCJhY2xHcm91cCIsInRlc3RQZXJtaXNzaW9ucyIsImdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsImNsYXNzUGVybWlzc2lvbnMiLCJzb21lIiwiYWNsIiwidmFsaWRhdGVQZXJtaXNzaW9uIiwiT0JKRUNUX05PVF9GT1VORCIsInBlcm1pc3Npb25GaWVsZCIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJoYXNDbGFzcyIsImxvYWQiLCJkYkFkYXB0ZXIiLCJwdXRSZXF1ZXN0Iiwic3lzU2NoZW1hRmllbGQiLCJfaWQiLCJvbGRGaWVsZCIsImZpZWxkSXNEZWxldGVkIiwibmV3RmllbGQiLCJzY2hlbWFQcm9taXNlIiwib2JqIiwiZ2V0T2JqZWN0VHlwZSIsIl9fdHlwZSIsImlzbyIsImxhdGl0dWRlIiwibG9uZ2l0dWRlIiwiYmFzZTY0IiwiY29vcmRpbmF0ZXMiLCJvYmplY3RzIiwib3BzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQWtCQTs7QUFDQTs7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7O0FBckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFwQzs7QUFjQSxNQUFNRSxjQUEwQyxHQUFHQyxNQUFNLENBQUNDLE1BQVAsQ0FBYztBQUMvRDtBQUNBQyxFQUFBQSxRQUFRLEVBQUU7QUFDUkMsSUFBQUEsUUFBUSxFQUFFO0FBQUVDLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBREY7QUFFUkMsSUFBQUEsU0FBUyxFQUFFO0FBQUVELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBRkg7QUFH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LENBQUMsS0FBRCxDQUFKLENBQXBCO0FBQ0Q7O0FBQ0QsTUFBSUEsR0FBRyxDQUFDeEUsSUFBUixFQUFjO0FBQ1osWUFBUXdFLEdBQUcsQ0FBQ3hFLElBQVo7QUFDRSxXQUFLLFdBQUw7QUFDRSxlQUFPLFFBQVA7O0FBQ0YsV0FBSyxRQUFMO0FBQ0UsZUFBTyxJQUFQOztBQUNGLFdBQUssS0FBTDtBQUNBLFdBQUssV0FBTDtBQUNBLFdBQUssUUFBTDtBQUNFLGVBQU8sT0FBUDs7QUFDRixXQUFLLGFBQUw7QUFDQSxXQUFLLGdCQUFMO0FBQ0UsZUFBTztBQUNMOU0sVUFBQUEsSUFBSSxFQUFFLFVBREQ7QUFFTDJCLFVBQUFBLFdBQVcsRUFBRTJQLEdBQUcsQ0FBQ1EsT0FBSixDQUFZLENBQVosRUFBZXBOO0FBRnZCLFNBQVA7O0FBSUYsV0FBSyxPQUFMO0FBQ0UsZUFBTzZNLGFBQWEsQ0FBQ0QsR0FBRyxDQUFDUyxHQUFKLENBQVEsQ0FBUixDQUFELENBQXBCOztBQUNGO0FBQ0UsY0FBTSxvQkFBb0JULEdBQUcsQ0FBQ3hFLElBQTlCO0FBbEJKO0FBb0JEOztBQUNELFNBQU8sUUFBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQGZsb3dcbi8vIFRoaXMgY2xhc3MgaGFuZGxlcyBzY2hlbWEgdmFsaWRhdGlvbiwgcGVyc2lzdGVuY2UsIGFuZCBtb2RpZmljYXRpb24uXG4vL1xuLy8gRWFjaCBpbmRpdmlkdWFsIFNjaGVtYSBvYmplY3Qgc2hvdWxkIGJlIGltbXV0YWJsZS4gVGhlIGhlbHBlcnMgdG9cbi8vIGRvIHRoaW5ncyB3aXRoIHRoZSBTY2hlbWEganVzdCByZXR1cm4gYSBuZXcgc2NoZW1hIHdoZW4gdGhlIHNjaGVtYVxuLy8gaXMgY2hhbmdlZC5cbi8vXG4vLyBUaGUgY2Fub25pY2FsIHBsYWNlIHRvIHN0b3JlIHRoaXMgU2NoZW1hIGlzIGluIHRoZSBkYXRhYmFzZSBpdHNlbGYsXG4vLyBpbiBhIF9TQ0hFTUEgY29sbGVjdGlvbi4gVGhpcyBpcyBub3QgdGhlIHJpZ2h0IHdheSB0byBkbyBpdCBmb3IgYW5cbi8vIG9wZW4gc291cmNlIGZyYW1ld29yaywgYnV0IGl0J3MgYmFja3dhcmQgY29tcGF0aWJsZSwgc28gd2UncmVcbi8vIGtlZXBpbmcgaXQgdGhpcyB3YXkgZm9yIG5vdy5cbi8vXG4vLyBJbiBBUEktaGFuZGxpbmcgY29kZSwgeW91IHNob3VsZCBvbmx5IHVzZSB0aGUgU2NoZW1hIGNsYXNzIHZpYSB0aGVcbi8vIERhdGFiYXNlQ29udHJvbGxlci4gVGhpcyB3aWxsIGxldCB1cyByZXBsYWNlIHRoZSBzY2hlbWEgbG9naWMgZm9yXG4vLyBkaWZmZXJlbnQgZGF0YWJhc2VzLlxuLy8gVE9ETzogaGlkZSBhbGwgc2NoZW1hIGxvZ2ljIGluc2lkZSB0aGUgZGF0YWJhc2UgYWRhcHRlci5cbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuY29uc3QgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5pbXBvcnQgeyBTdG9yYWdlQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL1N0b3JhZ2UvU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IERhdGFiYXNlQ29udHJvbGxlciBmcm9tICcuL0RhdGFiYXNlQ29udHJvbGxlcic7XG5pbXBvcnQgQ29uZmlnIGZyb20gJy4uL0NvbmZpZyc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBkZWVwY29weSBmcm9tICdkZWVwY29weSc7XG5pbXBvcnQgdHlwZSB7XG4gIFNjaGVtYSxcbiAgU2NoZW1hRmllbGRzLFxuICBDbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gIFNjaGVtYUZpZWxkLFxuICBMb2FkU2NoZW1hT3B0aW9ucyxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbmNvbnN0IGRlZmF1bHRDb2x1bW5zOiB7IFtzdHJpbmddOiBTY2hlbWFGaWVsZHMgfSA9IE9iamVjdC5mcmVlemUoe1xuICAvLyBDb250YWluIHRoZSBkZWZhdWx0IGNvbHVtbnMgZm9yIGV2ZXJ5IHBhcnNlIG9iamVjdCB0eXBlIChleGNlcHQgX0pvaW4gY29sbGVjdGlvbilcbiAgX0RlZmF1bHQ6IHtcbiAgICBvYmplY3RJZDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGNyZWF0ZWRBdDogeyB0eXBlOiAnRGF0ZScgfSxcbiAgICB1cGRhdGVkQXQ6IHsgdHlwZTogJ0RhdGUnIH0sXG4gICAgQUNMOiB7IHR5cGU6ICdBQ0wnIH0sXG4gIH0sXG4gIC8vIFRoZSBhZGRpdGlvbmFsIGRlZmF1bHQgY29sdW1ucyBmb3IgdGhlIF9Vc2VyIGNvbGxlY3Rpb24gKGluIGFkZGl0aW9uIHRvIERlZmF1bHRDb2xzKVxuICBfVXNlcjoge1xuICAgIHVzZXJuYW1lOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgcGFzc3dvcmQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBlbWFpbDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGVtYWlsVmVyaWZpZWQ6IHsgdHlwZTogJ0Jvb2xlYW4nIH0sXG4gICAgYXV0aERhdGE6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgfSxcbiAgLy8gVGhlIGFkZGl0aW9uYWwgZGVmYXVsdCBjb2x1bW5zIGZvciB0aGUgX0luc3RhbGxhdGlvbiBjb2xsZWN0aW9uIChpbiBhZGRpdGlvbiB0byBEZWZhdWx0Q29scylcbiAgX0luc3RhbGxhdGlvbjoge1xuICAgIGluc3RhbGxhdGlvbklkOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgZGV2aWNlVG9rZW46IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBjaGFubmVsczogeyB0eXBlOiAnQXJyYXknIH0sXG4gICAgZGV2aWNlVHlwZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHB1c2hUeXBlOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgR0NNU2VuZGVySWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICB0aW1lWm9uZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGxvY2FsZUlkZW50aWZpZXI6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBiYWRnZTogeyB0eXBlOiAnTnVtYmVyJyB9LFxuICAgIGFwcFZlcnNpb246IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBhcHBOYW1lOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgYXBwSWRlbnRpZmllcjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHBhcnNlVmVyc2lvbjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICB9LFxuICAvLyBUaGUgYWRkaXRpb25hbCBkZWZhdWx0IGNvbHVtbnMgZm9yIHRoZSBfUm9sZSBjb2xsZWN0aW9uIChpbiBhZGRpdGlvbiB0byBEZWZhdWx0Q29scylcbiAgX1JvbGU6IHtcbiAgICBuYW1lOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgdXNlcnM6IHsgdHlwZTogJ1JlbGF0aW9uJywgdGFyZ2V0Q2xhc3M6ICdfVXNlcicgfSxcbiAgICByb2xlczogeyB0eXBlOiAnUmVsYXRpb24nLCB0YXJnZXRDbGFzczogJ19Sb2xlJyB9LFxuICB9LFxuICAvLyBUaGUgYWRkaXRpb25hbCBkZWZhdWx0IGNvbHVtbnMgZm9yIHRoZSBfU2Vzc2lvbiBjb2xsZWN0aW9uIChpbiBhZGRpdGlvbiB0byBEZWZhdWx0Q29scylcbiAgX1Nlc3Npb246IHtcbiAgICByZXN0cmljdGVkOiB7IHR5cGU6ICdCb29sZWFuJyB9LFxuICAgIHVzZXI6IHsgdHlwZTogJ1BvaW50ZXInLCB0YXJnZXRDbGFzczogJ19Vc2VyJyB9LFxuICAgIGluc3RhbGxhdGlvbklkOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgc2Vzc2lvblRva2VuOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgZXhwaXJlc0F0OiB7IHR5cGU6ICdEYXRlJyB9LFxuICAgIGNyZWF0ZWRXaXRoOiB7IHR5cGU6ICdPYmplY3QnIH0sXG4gIH0sXG4gIF9Qcm9kdWN0OiB7XG4gICAgcHJvZHVjdElkZW50aWZpZXI6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBkb3dubG9hZDogeyB0eXBlOiAnRmlsZScgfSxcbiAgICBkb3dubG9hZE5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBpY29uOiB7IHR5cGU6ICdGaWxlJyB9LFxuICAgIG9yZGVyOiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gICAgdGl0bGU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBzdWJ0aXRsZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICB9LFxuICBfUHVzaFN0YXR1czoge1xuICAgIHB1c2hUaW1lOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgc291cmNlOiB7IHR5cGU6ICdTdHJpbmcnIH0sIC8vIHJlc3Qgb3Igd2VidWlcbiAgICBxdWVyeTogeyB0eXBlOiAnU3RyaW5nJyB9LCAvLyB0aGUgc3RyaW5naWZpZWQgSlNPTiBxdWVyeVxuICAgIHBheWxvYWQ6IHsgdHlwZTogJ1N0cmluZycgfSwgLy8gdGhlIHN0cmluZ2lmaWVkIEpTT04gcGF5bG9hZCxcbiAgICB0aXRsZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGV4cGlyeTogeyB0eXBlOiAnTnVtYmVyJyB9LFxuICAgIGV4cGlyYXRpb25faW50ZXJ2YWw6IHsgdHlwZTogJ051bWJlcicgfSxcbiAgICBzdGF0dXM6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBudW1TZW50OiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gICAgbnVtRmFpbGVkOiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gICAgcHVzaEhhc2g6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBlcnJvck1lc3NhZ2U6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgICBzZW50UGVyVHlwZTogeyB0eXBlOiAnT2JqZWN0JyB9LFxuICAgIGZhaWxlZFBlclR5cGU6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgICBzZW50UGVyVVRDT2Zmc2V0OiB7IHR5cGU6ICdPYmplY3QnIH0sXG4gICAgZmFpbGVkUGVyVVRDT2Zmc2V0OiB7IHR5cGU6ICdPYmplY3QnIH0sXG4gICAgY291bnQ6IHsgdHlwZTogJ051bWJlcicgfSwgLy8gdHJhY2tzICMgb2YgYmF0Y2hlcyBxdWV1ZWQgYW5kIHBlbmRpbmdcbiAgfSxcbiAgX0pvYlN0YXR1czoge1xuICAgIGpvYk5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBzb3VyY2U6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBzdGF0dXM6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBtZXNzYWdlOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgcGFyYW1zOiB7IHR5cGU6ICdPYmplY3QnIH0sIC8vIHBhcmFtcyByZWNlaXZlZCB3aGVuIGNhbGxpbmcgdGhlIGpvYlxuICAgIGZpbmlzaGVkQXQ6IHsgdHlwZTogJ0RhdGUnIH0sXG4gIH0sXG4gIF9Kb2JTY2hlZHVsZToge1xuICAgIGpvYk5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBkZXNjcmlwdGlvbjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHBhcmFtczogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHN0YXJ0QWZ0ZXI6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBkYXlzT2ZXZWVrOiB7IHR5cGU6ICdBcnJheScgfSxcbiAgICB0aW1lT2ZEYXk6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBsYXN0UnVuOiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gICAgcmVwZWF0TWludXRlczogeyB0eXBlOiAnTnVtYmVyJyB9LFxuICB9LFxuICBfSG9va3M6IHtcbiAgICBmdW5jdGlvbk5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBjbGFzc05hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICB0cmlnZ2VyTmFtZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHVybDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICB9LFxuICBfR2xvYmFsQ29uZmlnOiB7XG4gICAgb2JqZWN0SWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBwYXJhbXM6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgICBtYXN0ZXJLZXlPbmx5OiB7IHR5cGU6ICdPYmplY3QnIH0sXG4gIH0sXG4gIF9HcmFwaFFMQ29uZmlnOiB7XG4gICAgb2JqZWN0SWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBjb25maWc6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgfSxcbiAgX0F1ZGllbmNlOiB7XG4gICAgb2JqZWN0SWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBuYW1lOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgcXVlcnk6IHsgdHlwZTogJ1N0cmluZycgfSwgLy9zdG9yaW5nIHF1ZXJ5IGFzIEpTT04gc3RyaW5nIHRvIHByZXZlbnQgXCJOZXN0ZWQga2V5cyBzaG91bGQgbm90IGNvbnRhaW4gdGhlICckJyBvciAnLicgY2hhcmFjdGVyc1wiIGVycm9yXG4gICAgbGFzdFVzZWQ6IHsgdHlwZTogJ0RhdGUnIH0sXG4gICAgdGltZXNVc2VkOiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gIH0sXG59KTtcblxuY29uc3QgcmVxdWlyZWRDb2x1bW5zID0gT2JqZWN0LmZyZWV6ZSh7XG4gIF9Qcm9kdWN0OiBbJ3Byb2R1Y3RJZGVudGlmaWVyJywgJ2ljb24nLCAnb3JkZXInLCAndGl0bGUnLCAnc3VidGl0bGUnXSxcbiAgX1JvbGU6IFsnbmFtZScsICdBQ0wnXSxcbn0pO1xuXG5jb25zdCBzeXN0ZW1DbGFzc2VzID0gT2JqZWN0LmZyZWV6ZShbXG4gICdfVXNlcicsXG4gICdfSW5zdGFsbGF0aW9uJyxcbiAgJ19Sb2xlJyxcbiAgJ19TZXNzaW9uJyxcbiAgJ19Qcm9kdWN0JyxcbiAgJ19QdXNoU3RhdHVzJyxcbiAgJ19Kb2JTdGF0dXMnLFxuICAnX0pvYlNjaGVkdWxlJyxcbiAgJ19BdWRpZW5jZScsXG5dKTtcblxuY29uc3Qgdm9sYXRpbGVDbGFzc2VzID0gT2JqZWN0LmZyZWV6ZShbXG4gICdfSm9iU3RhdHVzJyxcbiAgJ19QdXNoU3RhdHVzJyxcbiAgJ19Ib29rcycsXG4gICdfR2xvYmFsQ29uZmlnJyxcbiAgJ19HcmFwaFFMQ29uZmlnJyxcbiAgJ19Kb2JTY2hlZHVsZScsXG4gICdfQXVkaWVuY2UnLFxuXSk7XG5cbi8vIDEwIGFscGhhIG51bWJlcmljIGNoYXJzICsgdXBwZXJjYXNlXG5jb25zdCB1c2VySWRSZWdleCA9IC9eW2EtekEtWjAtOV17MTB9JC87XG4vLyBBbnl0aGluZyB0aGF0IHN0YXJ0IHdpdGggcm9sZVxuY29uc3Qgcm9sZVJlZ2V4ID0gL15yb2xlOi4qLztcbi8vIEFueXRoaW5nIHRoYXQgc3RhcnRzIHdpdGggdXNlckZpZWxkXG5jb25zdCBwb2ludGVyUGVybWlzc2lvblJlZ2V4ID0gL151c2VyRmllbGQ6LiovO1xuLy8gKiBwZXJtaXNzaW9uXG5jb25zdCBwdWJsaWNSZWdleCA9IC9eXFwqJC87XG5cbmNvbnN0IHJlcXVpcmVBdXRoZW50aWNhdGlvblJlZ2V4ID0gL15yZXF1aXJlc0F1dGhlbnRpY2F0aW9uJC87XG5cbmNvbnN0IHBlcm1pc3Npb25LZXlSZWdleCA9IE9iamVjdC5mcmVlemUoW1xuICB1c2VySWRSZWdleCxcbiAgcm9sZVJlZ2V4LFxuICBwb2ludGVyUGVybWlzc2lvblJlZ2V4LFxuICBwdWJsaWNSZWdleCxcbiAgcmVxdWlyZUF1dGhlbnRpY2F0aW9uUmVnZXgsXG5dKTtcblxuZnVuY3Rpb24gdmVyaWZ5UGVybWlzc2lvbktleShrZXkpIHtcbiAgY29uc3QgcmVzdWx0ID0gcGVybWlzc2lvbktleVJlZ2V4LnJlZHVjZSgoaXNHb29kLCByZWdFeCkgPT4ge1xuICAgIGlzR29vZCA9IGlzR29vZCB8fCBrZXkubWF0Y2gocmVnRXgpICE9IG51bGw7XG4gICAgcmV0dXJuIGlzR29vZDtcbiAgfSwgZmFsc2UpO1xuICBpZiAoIXJlc3VsdCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgIGAnJHtrZXl9JyBpcyBub3QgYSB2YWxpZCBrZXkgZm9yIGNsYXNzIGxldmVsIHBlcm1pc3Npb25zYFxuICAgICk7XG4gIH1cbn1cblxuY29uc3QgQ0xQVmFsaWRLZXlzID0gT2JqZWN0LmZyZWV6ZShbXG4gICdmaW5kJyxcbiAgJ2NvdW50JyxcbiAgJ2dldCcsXG4gICdjcmVhdGUnLFxuICAndXBkYXRlJyxcbiAgJ2RlbGV0ZScsXG4gICdhZGRGaWVsZCcsXG4gICdyZWFkVXNlckZpZWxkcycsXG4gICd3cml0ZVVzZXJGaWVsZHMnLFxuICAncHJvdGVjdGVkRmllbGRzJyxcbl0pO1xuZnVuY3Rpb24gdmFsaWRhdGVDTFAocGVybXM6IENsYXNzTGV2ZWxQZXJtaXNzaW9ucywgZmllbGRzOiBTY2hlbWFGaWVsZHMpIHtcbiAgaWYgKCFwZXJtcykge1xuICAgIHJldHVybjtcbiAgfVxuICBPYmplY3Qua2V5cyhwZXJtcykuZm9yRWFjaChvcGVyYXRpb24gPT4ge1xuICAgIGlmIChDTFBWYWxpZEtleXMuaW5kZXhPZihvcGVyYXRpb24pID09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgYCR7b3BlcmF0aW9ufSBpcyBub3QgYSB2YWxpZCBvcGVyYXRpb24gZm9yIGNsYXNzIGxldmVsIHBlcm1pc3Npb25zYFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFwZXJtc1tvcGVyYXRpb25dKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG9wZXJhdGlvbiA9PT0gJ3JlYWRVc2VyRmllbGRzJyB8fCBvcGVyYXRpb24gPT09ICd3cml0ZVVzZXJGaWVsZHMnKSB7XG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkocGVybXNbb3BlcmF0aW9uXSkpIHtcbiAgICAgICAgLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYCcke3Blcm1zW29wZXJhdGlvbl19JyBpcyBub3QgYSB2YWxpZCB2YWx1ZSBmb3IgY2xhc3MgbGV2ZWwgcGVybWlzc2lvbnMgJHtvcGVyYXRpb259YFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVybXNbb3BlcmF0aW9uXS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgZmllbGRzW2tleV0gJiZcbiAgICAgICAgICAgICAgKChmaWVsZHNba2V5XS50eXBlID09ICdQb2ludGVyJyAmJlxuICAgICAgICAgICAgICAgIGZpZWxkc1trZXldLnRhcmdldENsYXNzID09ICdfVXNlcicpIHx8XG4gICAgICAgICAgICAgICAgZmllbGRzW2tleV0udHlwZSA9PSAnQXJyYXknKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgIGAnJHtrZXl9JyBpcyBub3QgYSB2YWxpZCBjb2x1bW4gZm9yIGNsYXNzIGxldmVsIHBvaW50ZXIgcGVybWlzc2lvbnMgJHtvcGVyYXRpb259YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEBmbG93LWRpc2FibGUtbmV4dFxuICAgIE9iamVjdC5rZXlzKHBlcm1zW29wZXJhdGlvbl0pLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIHZlcmlmeVBlcm1pc3Npb25LZXkoa2V5KTtcbiAgICAgIC8vIEBmbG93LWRpc2FibGUtbmV4dFxuICAgICAgY29uc3QgcGVybSA9IHBlcm1zW29wZXJhdGlvbl1ba2V5XTtcbiAgICAgIGlmIChcbiAgICAgICAgcGVybSAhPT0gdHJ1ZSAmJlxuICAgICAgICAob3BlcmF0aW9uICE9PSAncHJvdGVjdGVkRmllbGRzJyB8fCAhQXJyYXkuaXNBcnJheShwZXJtKSlcbiAgICAgICkge1xuICAgICAgICAvLyBAZmxvdy1kaXNhYmxlLW5leHRcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgJyR7cGVybX0nIGlzIG5vdCBhIHZhbGlkIHZhbHVlIGZvciBjbGFzcyBsZXZlbCBwZXJtaXNzaW9ucyAke29wZXJhdGlvbn06JHtrZXl9OiR7cGVybX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuY29uc3Qgam9pbkNsYXNzUmVnZXggPSAvXl9Kb2luOltBLVphLXowLTlfXSs6W0EtWmEtejAtOV9dKy87XG5jb25zdCBjbGFzc0FuZEZpZWxkUmVnZXggPSAvXltBLVphLXpdW0EtWmEtejAtOV9dKiQvO1xuZnVuY3Rpb24gY2xhc3NOYW1lSXNWYWxpZChjbGFzc05hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAvLyBWYWxpZCBjbGFzc2VzIG11c3Q6XG4gIHJldHVybiAoXG4gICAgLy8gQmUgb25lIG9mIF9Vc2VyLCBfSW5zdGFsbGF0aW9uLCBfUm9sZSwgX1Nlc3Npb24gT1JcbiAgICBzeXN0ZW1DbGFzc2VzLmluZGV4T2YoY2xhc3NOYW1lKSA+IC0xIHx8XG4gICAgLy8gQmUgYSBqb2luIHRhYmxlIE9SXG4gICAgam9pbkNsYXNzUmVnZXgudGVzdChjbGFzc05hbWUpIHx8XG4gICAgLy8gSW5jbHVkZSBvbmx5IGFscGhhLW51bWVyaWMgYW5kIHVuZGVyc2NvcmVzLCBhbmQgbm90IHN0YXJ0IHdpdGggYW4gdW5kZXJzY29yZSBvciBudW1iZXJcbiAgICBmaWVsZE5hbWVJc1ZhbGlkKGNsYXNzTmFtZSlcbiAgKTtcbn1cblxuLy8gVmFsaWQgZmllbGRzIG11c3QgYmUgYWxwaGEtbnVtZXJpYywgYW5kIG5vdCBzdGFydCB3aXRoIGFuIHVuZGVyc2NvcmUgb3IgbnVtYmVyXG5mdW5jdGlvbiBmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBjbGFzc0FuZEZpZWxkUmVnZXgudGVzdChmaWVsZE5hbWUpO1xufVxuXG4vLyBDaGVja3MgdGhhdCBpdCdzIG5vdCB0cnlpbmcgdG8gY2xvYmJlciBvbmUgb2YgdGhlIGRlZmF1bHQgZmllbGRzIG9mIHRoZSBjbGFzcy5cbmZ1bmN0aW9uIGZpZWxkTmFtZUlzVmFsaWRGb3JDbGFzcyhcbiAgZmllbGROYW1lOiBzdHJpbmcsXG4gIGNsYXNzTmFtZTogc3RyaW5nXG4pOiBib29sZWFuIHtcbiAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0W2ZpZWxkTmFtZV0pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0gJiYgZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXVtmaWVsZE5hbWVdKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZShjbGFzc05hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiAoXG4gICAgJ0ludmFsaWQgY2xhc3NuYW1lOiAnICtcbiAgICBjbGFzc05hbWUgK1xuICAgICcsIGNsYXNzbmFtZXMgY2FuIG9ubHkgaGF2ZSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycyBhbmQgXywgYW5kIG11c3Qgc3RhcnQgd2l0aCBhbiBhbHBoYSBjaGFyYWN0ZXIgJ1xuICApO1xufVxuXG5jb25zdCBpbnZhbGlkSnNvbkVycm9yID0gbmV3IFBhcnNlLkVycm9yKFxuICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICdpbnZhbGlkIEpTT04nXG4pO1xuY29uc3QgdmFsaWROb25SZWxhdGlvbk9yUG9pbnRlclR5cGVzID0gW1xuICAnTnVtYmVyJyxcbiAgJ1N0cmluZycsXG4gICdCb29sZWFuJyxcbiAgJ0RhdGUnLFxuICAnT2JqZWN0JyxcbiAgJ0FycmF5JyxcbiAgJ0dlb1BvaW50JyxcbiAgJ0ZpbGUnLFxuICAnQnl0ZXMnLFxuICAnUG9seWdvbicsXG5dO1xuLy8gUmV0dXJucyBhbiBlcnJvciBzdWl0YWJsZSBmb3IgdGhyb3dpbmcgaWYgdGhlIHR5cGUgaXMgaW52YWxpZFxuY29uc3QgZmllbGRUeXBlSXNJbnZhbGlkID0gKHsgdHlwZSwgdGFyZ2V0Q2xhc3MgfSkgPT4ge1xuICBpZiAoWydQb2ludGVyJywgJ1JlbGF0aW9uJ10uaW5kZXhPZih0eXBlKSA+PSAwKSB7XG4gICAgaWYgKCF0YXJnZXRDbGFzcykge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcigxMzUsIGB0eXBlICR7dHlwZX0gbmVlZHMgYSBjbGFzcyBuYW1lYCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdGFyZ2V0Q2xhc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gaW52YWxpZEpzb25FcnJvcjtcbiAgICB9IGVsc2UgaWYgKCFjbGFzc05hbWVJc1ZhbGlkKHRhcmdldENsYXNzKSkge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZSh0YXJnZXRDbGFzcylcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG4gIGlmICh0eXBlb2YgdHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gaW52YWxpZEpzb25FcnJvcjtcbiAgfVxuICBpZiAodmFsaWROb25SZWxhdGlvbk9yUG9pbnRlclR5cGVzLmluZGV4T2YodHlwZSkgPCAwKSB7XG4gICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgYGludmFsaWQgZmllbGQgdHlwZTogJHt0eXBlfWBcbiAgICApO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59O1xuXG5jb25zdCBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hID0gKHNjaGVtYTogYW55KSA9PiB7XG4gIHNjaGVtYSA9IGluamVjdERlZmF1bHRTY2hlbWEoc2NoZW1hKTtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuQUNMO1xuICBzY2hlbWEuZmllbGRzLl9ycGVybSA9IHsgdHlwZTogJ0FycmF5JyB9O1xuICBzY2hlbWEuZmllbGRzLl93cGVybSA9IHsgdHlwZTogJ0FycmF5JyB9O1xuXG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMucGFzc3dvcmQ7XG4gICAgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkID0geyB0eXBlOiAnU3RyaW5nJyB9O1xuICB9XG5cbiAgcmV0dXJuIHNjaGVtYTtcbn07XG5cbmNvbnN0IGNvbnZlcnRBZGFwdGVyU2NoZW1hVG9QYXJzZVNjaGVtYSA9ICh7IC4uLnNjaGVtYSB9KSA9PiB7XG4gIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9ycGVybTtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3dwZXJtO1xuXG4gIHNjaGVtYS5maWVsZHMuQUNMID0geyB0eXBlOiAnQUNMJyB9O1xuXG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuYXV0aERhdGE7IC8vQXV0aCBkYXRhIGlzIGltcGxpY2l0XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX2hhc2hlZF9wYXNzd29yZDtcbiAgICBzY2hlbWEuZmllbGRzLnBhc3N3b3JkID0geyB0eXBlOiAnU3RyaW5nJyB9O1xuICB9XG5cbiAgaWYgKHNjaGVtYS5pbmRleGVzICYmIE9iamVjdC5rZXlzKHNjaGVtYS5pbmRleGVzKS5sZW5ndGggPT09IDApIHtcbiAgICBkZWxldGUgc2NoZW1hLmluZGV4ZXM7XG4gIH1cblxuICByZXR1cm4gc2NoZW1hO1xufTtcblxuY2xhc3MgU2NoZW1hRGF0YSB7XG4gIF9fZGF0YTogYW55O1xuICBfX3Byb3RlY3RlZEZpZWxkczogYW55O1xuICBjb25zdHJ1Y3RvcihhbGxTY2hlbWFzID0gW10sIHByb3RlY3RlZEZpZWxkcyA9IHt9KSB7XG4gICAgdGhpcy5fX2RhdGEgPSB7fTtcbiAgICB0aGlzLl9fcHJvdGVjdGVkRmllbGRzID0gcHJvdGVjdGVkRmllbGRzO1xuICAgIGFsbFNjaGVtYXMuZm9yRWFjaChzY2hlbWEgPT4ge1xuICAgICAgaWYgKHZvbGF0aWxlQ2xhc3Nlcy5pbmNsdWRlcyhzY2hlbWEuY2xhc3NOYW1lKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgc2NoZW1hLmNsYXNzTmFtZSwge1xuICAgICAgICBnZXQ6ICgpID0+IHtcbiAgICAgICAgICBpZiAoIXRoaXMuX19kYXRhW3NjaGVtYS5jbGFzc05hbWVdKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0ge307XG4gICAgICAgICAgICBkYXRhLmZpZWxkcyA9IGluamVjdERlZmF1bHRTY2hlbWEoc2NoZW1hKS5maWVsZHM7XG4gICAgICAgICAgICBkYXRhLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucyA9IGRlZXBjb3B5KHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMpO1xuICAgICAgICAgICAgZGF0YS5pbmRleGVzID0gc2NoZW1hLmluZGV4ZXM7XG5cbiAgICAgICAgICAgIGNvbnN0IGNsYXNzUHJvdGVjdGVkRmllbGRzID0gdGhpcy5fX3Byb3RlY3RlZEZpZWxkc1tcbiAgICAgICAgICAgICAgc2NoZW1hLmNsYXNzTmFtZVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGlmIChjbGFzc1Byb3RlY3RlZEZpZWxkcykge1xuICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBjbGFzc1Byb3RlY3RlZEZpZWxkcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHVucSA9IG5ldyBTZXQoW1xuICAgICAgICAgICAgICAgICAgLi4uKGRhdGEuY2xhc3NMZXZlbFBlcm1pc3Npb25zLnByb3RlY3RlZEZpZWxkc1trZXldIHx8IFtdKSxcbiAgICAgICAgICAgICAgICAgIC4uLmNsYXNzUHJvdGVjdGVkRmllbGRzW2tleV0sXG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgZGF0YS5jbGFzc0xldmVsUGVybWlzc2lvbnMucHJvdGVjdGVkRmllbGRzW2tleV0gPSBBcnJheS5mcm9tKFxuICAgICAgICAgICAgICAgICAgdW5xXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9fZGF0YVtzY2hlbWEuY2xhc3NOYW1lXSA9IGRhdGE7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0aGlzLl9fZGF0YVtzY2hlbWEuY2xhc3NOYW1lXTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gSW5qZWN0IHRoZSBpbi1tZW1vcnkgY2xhc3Nlc1xuICAgIHZvbGF0aWxlQ2xhc3Nlcy5mb3JFYWNoKGNsYXNzTmFtZSA9PiB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgY2xhc3NOYW1lLCB7XG4gICAgICAgIGdldDogKCkgPT4ge1xuICAgICAgICAgIGlmICghdGhpcy5fX2RhdGFbY2xhc3NOYW1lXSkge1xuICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0gaW5qZWN0RGVmYXVsdFNjaGVtYSh7XG4gICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgZmllbGRzOiB7fSxcbiAgICAgICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiB7fSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IHt9O1xuICAgICAgICAgICAgZGF0YS5maWVsZHMgPSBzY2hlbWEuZmllbGRzO1xuICAgICAgICAgICAgZGF0YS5jbGFzc0xldmVsUGVybWlzc2lvbnMgPSBzY2hlbWEuY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgICAgICAgICAgZGF0YS5pbmRleGVzID0gc2NoZW1hLmluZGV4ZXM7XG4gICAgICAgICAgICB0aGlzLl9fZGF0YVtjbGFzc05hbWVdID0gZGF0YTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX19kYXRhW2NsYXNzTmFtZV07XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG5jb25zdCBpbmplY3REZWZhdWx0U2NoZW1hID0gKHtcbiAgY2xhc3NOYW1lLFxuICBmaWVsZHMsXG4gIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgaW5kZXhlcyxcbn06IFNjaGVtYSkgPT4ge1xuICBjb25zdCBkZWZhdWx0U2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgY2xhc3NOYW1lLFxuICAgIGZpZWxkczoge1xuICAgICAgLi4uZGVmYXVsdENvbHVtbnMuX0RlZmF1bHQsXG4gICAgICAuLi4oZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXSB8fCB7fSksXG4gICAgICAuLi5maWVsZHMsXG4gICAgfSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gIH07XG4gIGlmIChpbmRleGVzICYmIE9iamVjdC5rZXlzKGluZGV4ZXMpLmxlbmd0aCAhPT0gMCkge1xuICAgIGRlZmF1bHRTY2hlbWEuaW5kZXhlcyA9IGluZGV4ZXM7XG4gIH1cbiAgcmV0dXJuIGRlZmF1bHRTY2hlbWE7XG59O1xuXG5jb25zdCBfSG9va3NTY2hlbWEgPSB7IGNsYXNzTmFtZTogJ19Ib29rcycsIGZpZWxkczogZGVmYXVsdENvbHVtbnMuX0hvb2tzIH07XG5jb25zdCBfR2xvYmFsQ29uZmlnU2NoZW1hID0ge1xuICBjbGFzc05hbWU6ICdfR2xvYmFsQ29uZmlnJyxcbiAgZmllbGRzOiBkZWZhdWx0Q29sdW1ucy5fR2xvYmFsQ29uZmlnLFxufTtcbmNvbnN0IF9HcmFwaFFMQ29uZmlnU2NoZW1hID0ge1xuICBjbGFzc05hbWU6ICdfR3JhcGhRTENvbmZpZycsXG4gIGZpZWxkczogZGVmYXVsdENvbHVtbnMuX0dyYXBoUUxDb25maWcsXG59O1xuY29uc3QgX1B1c2hTdGF0dXNTY2hlbWEgPSBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hKFxuICBpbmplY3REZWZhdWx0U2NoZW1hKHtcbiAgICBjbGFzc05hbWU6ICdfUHVzaFN0YXR1cycsXG4gICAgZmllbGRzOiB7fSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHt9LFxuICB9KVxuKTtcbmNvbnN0IF9Kb2JTdGF0dXNTY2hlbWEgPSBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hKFxuICBpbmplY3REZWZhdWx0U2NoZW1hKHtcbiAgICBjbGFzc05hbWU6ICdfSm9iU3RhdHVzJyxcbiAgICBmaWVsZHM6IHt9LFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczoge30sXG4gIH0pXG4pO1xuY29uc3QgX0pvYlNjaGVkdWxlU2NoZW1hID0gY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShcbiAgaW5qZWN0RGVmYXVsdFNjaGVtYSh7XG4gICAgY2xhc3NOYW1lOiAnX0pvYlNjaGVkdWxlJyxcbiAgICBmaWVsZHM6IHt9LFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczoge30sXG4gIH0pXG4pO1xuY29uc3QgX0F1ZGllbmNlU2NoZW1hID0gY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShcbiAgaW5qZWN0RGVmYXVsdFNjaGVtYSh7XG4gICAgY2xhc3NOYW1lOiAnX0F1ZGllbmNlJyxcbiAgICBmaWVsZHM6IGRlZmF1bHRDb2x1bW5zLl9BdWRpZW5jZSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHt9LFxuICB9KVxuKTtcbmNvbnN0IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMgPSBbXG4gIF9Ib29rc1NjaGVtYSxcbiAgX0pvYlN0YXR1c1NjaGVtYSxcbiAgX0pvYlNjaGVkdWxlU2NoZW1hLFxuICBfUHVzaFN0YXR1c1NjaGVtYSxcbiAgX0dsb2JhbENvbmZpZ1NjaGVtYSxcbiAgX0dyYXBoUUxDb25maWdTY2hlbWEsXG4gIF9BdWRpZW5jZVNjaGVtYSxcbl07XG5cbmNvbnN0IGRiVHlwZU1hdGNoZXNPYmplY3RUeXBlID0gKFxuICBkYlR5cGU6IFNjaGVtYUZpZWxkIHwgc3RyaW5nLFxuICBvYmplY3RUeXBlOiBTY2hlbWFGaWVsZFxuKSA9PiB7XG4gIGlmIChkYlR5cGUudHlwZSAhPT0gb2JqZWN0VHlwZS50eXBlKSByZXR1cm4gZmFsc2U7XG4gIGlmIChkYlR5cGUudGFyZ2V0Q2xhc3MgIT09IG9iamVjdFR5cGUudGFyZ2V0Q2xhc3MpIHJldHVybiBmYWxzZTtcbiAgaWYgKGRiVHlwZSA9PT0gb2JqZWN0VHlwZS50eXBlKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGRiVHlwZS50eXBlID09PSBvYmplY3RUeXBlLnR5cGUpIHJldHVybiB0cnVlO1xuICByZXR1cm4gZmFsc2U7XG59O1xuXG5jb25zdCB0eXBlVG9TdHJpbmcgPSAodHlwZTogU2NoZW1hRmllbGQgfCBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICBpZiAodHlwZW9mIHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHR5cGU7XG4gIH1cbiAgaWYgKHR5cGUudGFyZ2V0Q2xhc3MpIHtcbiAgICByZXR1cm4gYCR7dHlwZS50eXBlfTwke3R5cGUudGFyZ2V0Q2xhc3N9PmA7XG4gIH1cbiAgcmV0dXJuIGAke3R5cGUudHlwZX1gO1xufTtcblxuLy8gU3RvcmVzIHRoZSBlbnRpcmUgc2NoZW1hIG9mIHRoZSBhcHAgaW4gYSB3ZWlyZCBoeWJyaWQgZm9ybWF0IHNvbWV3aGVyZSBiZXR3ZWVuXG4vLyB0aGUgbW9uZ28gZm9ybWF0IGFuZCB0aGUgUGFyc2UgZm9ybWF0LiBTb29uLCB0aGlzIHdpbGwgYWxsIGJlIFBhcnNlIGZvcm1hdC5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjaGVtYUNvbnRyb2xsZXIge1xuICBfZGJBZGFwdGVyOiBTdG9yYWdlQWRhcHRlcjtcbiAgc2NoZW1hRGF0YTogeyBbc3RyaW5nXTogU2NoZW1hIH07XG4gIF9jYWNoZTogYW55O1xuICByZWxvYWREYXRhUHJvbWlzZTogP1Byb21pc2U8YW55PjtcbiAgcHJvdGVjdGVkRmllbGRzOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoZGF0YWJhc2VBZGFwdGVyOiBTdG9yYWdlQWRhcHRlciwgc2NoZW1hQ2FjaGU6IGFueSkge1xuICAgIHRoaXMuX2RiQWRhcHRlciA9IGRhdGFiYXNlQWRhcHRlcjtcbiAgICB0aGlzLl9jYWNoZSA9IHNjaGVtYUNhY2hlO1xuICAgIHRoaXMuc2NoZW1hRGF0YSA9IG5ldyBTY2hlbWFEYXRhKCk7XG4gICAgdGhpcy5wcm90ZWN0ZWRGaWVsZHMgPSBDb25maWcuZ2V0KFBhcnNlLmFwcGxpY2F0aW9uSWQpLnByb3RlY3RlZEZpZWxkcztcbiAgfVxuXG4gIHJlbG9hZERhdGEob3B0aW9uczogTG9hZFNjaGVtYU9wdGlvbnMgPSB7IGNsZWFyQ2FjaGU6IGZhbHNlIH0pOiBQcm9taXNlPGFueT4ge1xuICAgIGlmICh0aGlzLnJlbG9hZERhdGFQcm9taXNlICYmICFvcHRpb25zLmNsZWFyQ2FjaGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlbG9hZERhdGFQcm9taXNlO1xuICAgIH1cbiAgICB0aGlzLnJlbG9hZERhdGFQcm9taXNlID0gdGhpcy5nZXRBbGxDbGFzc2VzKG9wdGlvbnMpXG4gICAgICAudGhlbihcbiAgICAgICAgYWxsU2NoZW1hcyA9PiB7XG4gICAgICAgICAgdGhpcy5zY2hlbWFEYXRhID0gbmV3IFNjaGVtYURhdGEoYWxsU2NoZW1hcywgdGhpcy5wcm90ZWN0ZWRGaWVsZHMpO1xuICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbG9hZERhdGFQcm9taXNlO1xuICAgICAgICB9LFxuICAgICAgICBlcnIgPT4ge1xuICAgICAgICAgIHRoaXMuc2NoZW1hRGF0YSA9IG5ldyBTY2hlbWFEYXRhKCk7XG4gICAgICAgICAgZGVsZXRlIHRoaXMucmVsb2FkRGF0YVByb21pc2U7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICApXG4gICAgICAudGhlbigoKSA9PiB7fSk7XG4gICAgcmV0dXJuIHRoaXMucmVsb2FkRGF0YVByb21pc2U7XG4gIH1cblxuICBnZXRBbGxDbGFzc2VzKFxuICAgIG9wdGlvbnM6IExvYWRTY2hlbWFPcHRpb25zID0geyBjbGVhckNhY2hlOiBmYWxzZSB9XG4gICk6IFByb21pc2U8QXJyYXk8U2NoZW1hPj4ge1xuICAgIGlmIChvcHRpb25zLmNsZWFyQ2FjaGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnNldEFsbENsYXNzZXMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlLmdldEFsbENsYXNzZXMoKS50aGVuKGFsbENsYXNzZXMgPT4ge1xuICAgICAgaWYgKGFsbENsYXNzZXMgJiYgYWxsQ2xhc3Nlcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShhbGxDbGFzc2VzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnNldEFsbENsYXNzZXMoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHNldEFsbENsYXNzZXMoKTogUHJvbWlzZTxBcnJheTxTY2hlbWE+PiB7XG4gICAgcmV0dXJuIHRoaXMuX2RiQWRhcHRlclxuICAgICAgLmdldEFsbENsYXNzZXMoKVxuICAgICAgLnRoZW4oYWxsU2NoZW1hcyA9PiBhbGxTY2hlbWFzLm1hcChpbmplY3REZWZhdWx0U2NoZW1hKSlcbiAgICAgIC50aGVuKGFsbFNjaGVtYXMgPT4ge1xuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgIHRoaXMuX2NhY2hlXG4gICAgICAgICAgLnNldEFsbENsYXNzZXMoYWxsU2NoZW1hcylcbiAgICAgICAgICAuY2F0Y2goZXJyb3IgPT5cbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNhdmluZyBzY2hlbWEgdG8gY2FjaGU6JywgZXJyb3IpXG4gICAgICAgICAgKTtcbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgIHJldHVybiBhbGxTY2hlbWFzO1xuICAgICAgfSk7XG4gIH1cblxuICBnZXRPbmVTY2hlbWEoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgYWxsb3dWb2xhdGlsZUNsYXNzZXM6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICBvcHRpb25zOiBMb2FkU2NoZW1hT3B0aW9ucyA9IHsgY2xlYXJDYWNoZTogZmFsc2UgfVxuICApOiBQcm9taXNlPFNjaGVtYT4ge1xuICAgIGxldCBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgaWYgKG9wdGlvbnMuY2xlYXJDYWNoZSkge1xuICAgICAgcHJvbWlzZSA9IHRoaXMuX2NhY2hlLmNsZWFyKCk7XG4gICAgfVxuICAgIHJldHVybiBwcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGFsbG93Vm9sYXRpbGVDbGFzc2VzICYmIHZvbGF0aWxlQ2xhc3Nlcy5pbmRleE9mKGNsYXNzTmFtZSkgPiAtMSkge1xuICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV07XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICBmaWVsZHM6IGRhdGEuZmllbGRzLFxuICAgICAgICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogZGF0YS5jbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgaW5kZXhlczogZGF0YS5pbmRleGVzLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lKS50aGVuKGNhY2hlZCA9PiB7XG4gICAgICAgIGlmIChjYWNoZWQgJiYgIW9wdGlvbnMuY2xlYXJDYWNoZSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoY2FjaGVkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5zZXRBbGxDbGFzc2VzKCkudGhlbihhbGxTY2hlbWFzID0+IHtcbiAgICAgICAgICBjb25zdCBvbmVTY2hlbWEgPSBhbGxTY2hlbWFzLmZpbmQoXG4gICAgICAgICAgICBzY2hlbWEgPT4gc2NoZW1hLmNsYXNzTmFtZSA9PT0gY2xhc3NOYW1lXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoIW9uZVNjaGVtYSkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHVuZGVmaW5lZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBvbmVTY2hlbWE7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSBuZXcgY2xhc3MgdGhhdCBpbmNsdWRlcyB0aGUgdGhyZWUgZGVmYXVsdCBmaWVsZHMuXG4gIC8vIEFDTCBpcyBhbiBpbXBsaWNpdCBjb2x1bW4gdGhhdCBkb2VzIG5vdCBnZXQgYW4gZW50cnkgaW4gdGhlXG4gIC8vIF9TQ0hFTUFTIGRhdGFiYXNlLiBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlXG4gIC8vIGNyZWF0ZWQgc2NoZW1hLCBpbiBtb25nbyBmb3JtYXQuXG4gIC8vIG9uIHN1Y2Nlc3MsIGFuZCByZWplY3RzIHdpdGggYW4gZXJyb3Igb24gZmFpbC4gRW5zdXJlIHlvdVxuICAvLyBoYXZlIGF1dGhvcml6YXRpb24gKG1hc3RlciBrZXksIG9yIGNsaWVudCBjbGFzcyBjcmVhdGlvblxuICAvLyBlbmFibGVkKSBiZWZvcmUgY2FsbGluZyB0aGlzIGZ1bmN0aW9uLlxuICBhZGRDbGFzc0lmTm90RXhpc3RzKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGZpZWxkczogU2NoZW1hRmllbGRzID0ge30sXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBhbnksXG4gICAgaW5kZXhlczogYW55ID0ge31cbiAgKTogUHJvbWlzZTx2b2lkIHwgU2NoZW1hPiB7XG4gICAgdmFyIHZhbGlkYXRpb25FcnJvciA9IHRoaXMudmFsaWRhdGVOZXdDbGFzcyhcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIGZpZWxkcyxcbiAgICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uc1xuICAgICk7XG4gICAgaWYgKHZhbGlkYXRpb25FcnJvcikge1xuICAgICAgaWYgKHZhbGlkYXRpb25FcnJvciBpbnN0YW5jZW9mIFBhcnNlLkVycm9yKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh2YWxpZGF0aW9uRXJyb3IpO1xuICAgICAgfSBlbHNlIGlmICh2YWxpZGF0aW9uRXJyb3IuY29kZSAmJiB2YWxpZGF0aW9uRXJyb3IuZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcih2YWxpZGF0aW9uRXJyb3IuY29kZSwgdmFsaWRhdGlvbkVycm9yLmVycm9yKVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHZhbGlkYXRpb25FcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2RiQWRhcHRlclxuICAgICAgLmNyZWF0ZUNsYXNzKFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIGNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEoe1xuICAgICAgICAgIGZpZWxkcyxcbiAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgaW5kZXhlcyxcbiAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAudGhlbihjb252ZXJ0QWRhcHRlclNjaGVtYVRvUGFyc2VTY2hlbWEpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IgJiYgZXJyb3IuY29kZSA9PT0gUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICAgICAgYENsYXNzICR7Y2xhc3NOYW1lfSBhbHJlYWR5IGV4aXN0cy5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICB1cGRhdGVDbGFzcyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzdWJtaXR0ZWRGaWVsZHM6IFNjaGVtYUZpZWxkcyxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IGFueSxcbiAgICBpbmRleGVzOiBhbnksXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlQ29udHJvbGxlclxuICApIHtcbiAgICByZXR1cm4gdGhpcy5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdGaWVsZHMgPSBzY2hlbWEuZmllbGRzO1xuICAgICAgICBPYmplY3Qua2V5cyhzdWJtaXR0ZWRGaWVsZHMpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICAgICAgY29uc3QgZmllbGQgPSBzdWJtaXR0ZWRGaWVsZHNbbmFtZV07XG4gICAgICAgICAgaWYgKGV4aXN0aW5nRmllbGRzW25hbWVdICYmIGZpZWxkLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMjU1LCBgRmllbGQgJHtuYW1lfSBleGlzdHMsIGNhbm5vdCB1cGRhdGUuYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghZXhpc3RpbmdGaWVsZHNbbmFtZV0gJiYgZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgMjU1LFxuICAgICAgICAgICAgICBgRmllbGQgJHtuYW1lfSBkb2VzIG5vdCBleGlzdCwgY2Fubm90IGRlbGV0ZS5gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nRmllbGRzLl9ycGVybTtcbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nRmllbGRzLl93cGVybTtcbiAgICAgICAgY29uc3QgbmV3U2NoZW1hID0gYnVpbGRNZXJnZWRTY2hlbWFPYmplY3QoXG4gICAgICAgICAgZXhpc3RpbmdGaWVsZHMsXG4gICAgICAgICAgc3VibWl0dGVkRmllbGRzXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRGaWVsZHMgPVxuICAgICAgICAgIGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0gfHwgZGVmYXVsdENvbHVtbnMuX0RlZmF1bHQ7XG4gICAgICAgIGNvbnN0IGZ1bGxOZXdTY2hlbWEgPSBPYmplY3QuYXNzaWduKHt9LCBuZXdTY2hlbWEsIGRlZmF1bHRGaWVsZHMpO1xuICAgICAgICBjb25zdCB2YWxpZGF0aW9uRXJyb3IgPSB0aGlzLnZhbGlkYXRlU2NoZW1hRGF0YShcbiAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgbmV3U2NoZW1hLFxuICAgICAgICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgICAgICAgICBPYmplY3Qua2V5cyhleGlzdGluZ0ZpZWxkcylcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHZhbGlkYXRpb25FcnJvcikge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcih2YWxpZGF0aW9uRXJyb3IuY29kZSwgdmFsaWRhdGlvbkVycm9yLmVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZpbmFsbHkgd2UgaGF2ZSBjaGVja2VkIHRvIG1ha2Ugc3VyZSB0aGUgcmVxdWVzdCBpcyB2YWxpZCBhbmQgd2UgY2FuIHN0YXJ0IGRlbGV0aW5nIGZpZWxkcy5cbiAgICAgICAgLy8gRG8gYWxsIGRlbGV0aW9ucyBmaXJzdCwgdGhlbiBhIHNpbmdsZSBzYXZlIHRvIF9TQ0hFTUEgY29sbGVjdGlvbiB0byBoYW5kbGUgYWxsIGFkZGl0aW9ucy5cbiAgICAgICAgY29uc3QgZGVsZXRlZEZpZWxkczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgY29uc3QgaW5zZXJ0ZWRGaWVsZHMgPSBbXTtcbiAgICAgICAgT2JqZWN0LmtleXMoc3VibWl0dGVkRmllbGRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgaWYgKHN1Ym1pdHRlZEZpZWxkc1tmaWVsZE5hbWVdLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgICAgICBkZWxldGVkRmllbGRzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5zZXJ0ZWRGaWVsZHMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IGRlbGV0ZVByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgaWYgKGRlbGV0ZWRGaWVsZHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGRlbGV0ZVByb21pc2UgPSB0aGlzLmRlbGV0ZUZpZWxkcyhkZWxldGVkRmllbGRzLCBjbGFzc05hbWUsIGRhdGFiYXNlKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZW5mb3JjZUZpZWxkcyA9IFtdO1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIGRlbGV0ZVByb21pc2UgLy8gRGVsZXRlIEV2ZXJ5dGhpbmdcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMucmVsb2FkRGF0YSh7IGNsZWFyQ2FjaGU6IHRydWUgfSkpIC8vIFJlbG9hZCBvdXIgU2NoZW1hLCBzbyB3ZSBoYXZlIGFsbCB0aGUgbmV3IHZhbHVlc1xuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IGluc2VydGVkRmllbGRzLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBzdWJtaXR0ZWRGaWVsZHNbZmllbGROYW1lXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lbmZvcmNlRmllbGRFeGlzdHMoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHR5cGUpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgICAgICAgZW5mb3JjZUZpZWxkcyA9IHJlc3VsdHMuZmlsdGVyKHJlc3VsdCA9PiAhIXJlc3VsdCk7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLnNldFBlcm1pc3Npb25zKFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgICAgICAgbmV3U2NoZW1hXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKCkgPT5cbiAgICAgICAgICAgICAgdGhpcy5fZGJBZGFwdGVyLnNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICBpbmRleGVzLFxuICAgICAgICAgICAgICAgIHNjaGVtYS5pbmRleGVzLFxuICAgICAgICAgICAgICAgIGZ1bGxOZXdTY2hlbWFcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5yZWxvYWREYXRhKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KSlcbiAgICAgICAgICAgIC8vVE9ETzogTW92ZSB0aGlzIGxvZ2ljIGludG8gdGhlIGRhdGFiYXNlIGFkYXB0ZXJcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgdGhpcy5lbnN1cmVGaWVsZHMoZW5mb3JjZUZpZWxkcyk7XG4gICAgICAgICAgICAgIGNvbnN0IHNjaGVtYSA9IHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdO1xuICAgICAgICAgICAgICBjb25zdCByZWxvYWRlZFNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgIGZpZWxkczogc2NoZW1hLmZpZWxkcyxcbiAgICAgICAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGlmIChzY2hlbWEuaW5kZXhlcyAmJiBPYmplY3Qua2V5cyhzY2hlbWEuaW5kZXhlcykubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgcmVsb2FkZWRTY2hlbWEuaW5kZXhlcyA9IHNjaGVtYS5pbmRleGVzO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiByZWxvYWRlZFNjaGVtYTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICAgICAgICBgQ2xhc3MgJHtjbGFzc05hbWV9IGRvZXMgbm90IGV4aXN0LmBcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgc3VjY2Vzc2Z1bGx5IHRvIHRoZSBuZXcgc2NoZW1hXG4gIC8vIG9iamVjdCBvciBmYWlscyB3aXRoIGEgcmVhc29uLlxuICBlbmZvcmNlQ2xhc3NFeGlzdHMoY2xhc3NOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFNjaGVtYUNvbnRyb2xsZXI+IHtcbiAgICBpZiAodGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV0pIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcyk7XG4gICAgfVxuICAgIC8vIFdlIGRvbid0IGhhdmUgdGhpcyBjbGFzcy4gVXBkYXRlIHRoZSBzY2hlbWFcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5hZGRDbGFzc0lmTm90RXhpc3RzKGNsYXNzTmFtZSlcbiAgICAgICAgLy8gVGhlIHNjaGVtYSB1cGRhdGUgc3VjY2VlZGVkLiBSZWxvYWQgdGhlIHNjaGVtYVxuICAgICAgICAudGhlbigoKSA9PiB0aGlzLnJlbG9hZERhdGEoeyBjbGVhckNhY2hlOiB0cnVlIH0pKVxuICAgICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIC8vIFRoZSBzY2hlbWEgdXBkYXRlIGZhaWxlZC4gVGhpcyBjYW4gYmUgb2theSAtIGl0IG1pZ2h0XG4gICAgICAgICAgLy8gaGF2ZSBmYWlsZWQgYmVjYXVzZSB0aGVyZSdzIGEgcmFjZSBjb25kaXRpb24gYW5kIGEgZGlmZmVyZW50XG4gICAgICAgICAgLy8gY2xpZW50IGlzIG1ha2luZyB0aGUgZXhhY3Qgc2FtZSBzY2hlbWEgdXBkYXRlIHRoYXQgd2Ugd2FudC5cbiAgICAgICAgICAvLyBTbyBqdXN0IHJlbG9hZCB0aGUgc2NoZW1hLlxuICAgICAgICAgIHJldHVybiB0aGlzLnJlbG9hZERhdGEoeyBjbGVhckNhY2hlOiB0cnVlIH0pO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgLy8gRW5zdXJlIHRoYXQgdGhlIHNjaGVtYSBub3cgdmFsaWRhdGVzXG4gICAgICAgICAgaWYgKHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgIGBGYWlsZWQgdG8gYWRkICR7Y2xhc3NOYW1lfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIC8vIFRoZSBzY2hlbWEgc3RpbGwgZG9lc24ndCB2YWxpZGF0ZS4gR2l2ZSB1cFxuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICdzY2hlbWEgY2xhc3MgbmFtZSBkb2VzIG5vdCByZXZhbGlkYXRlJ1xuICAgICAgICAgICk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHZhbGlkYXRlTmV3Q2xhc3MoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZmllbGRzOiBTY2hlbWFGaWVsZHMgPSB7fSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IGFueVxuICApOiBhbnkge1xuICAgIGlmICh0aGlzLnNjaGVtYURhdGFbY2xhc3NOYW1lXSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICAgIGBDbGFzcyAke2NsYXNzTmFtZX0gYWxyZWFkeSBleGlzdHMuYFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFjbGFzc05hbWVJc1ZhbGlkKGNsYXNzTmFtZSkpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSxcbiAgICAgICAgZXJyb3I6IGludmFsaWRDbGFzc05hbWVNZXNzYWdlKGNsYXNzTmFtZSksXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWxpZGF0ZVNjaGVtYURhdGEoXG4gICAgICBjbGFzc05hbWUsXG4gICAgICBmaWVsZHMsXG4gICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICBbXVxuICAgICk7XG4gIH1cblxuICB2YWxpZGF0ZVNjaGVtYURhdGEoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZmllbGRzOiBTY2hlbWFGaWVsZHMsXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBDbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgZXhpc3RpbmdGaWVsZE5hbWVzOiBBcnJheTxzdHJpbmc+XG4gICkge1xuICAgIGZvciAoY29uc3QgZmllbGROYW1lIGluIGZpZWxkcykge1xuICAgICAgaWYgKGV4aXN0aW5nRmllbGROYW1lcy5pbmRleE9mKGZpZWxkTmFtZSkgPCAwKSB7XG4gICAgICAgIGlmICghZmllbGROYW1lSXNWYWxpZChmaWVsZE5hbWUpKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsXG4gICAgICAgICAgICBlcnJvcjogJ2ludmFsaWQgZmllbGQgbmFtZTogJyArIGZpZWxkTmFtZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghZmllbGROYW1lSXNWYWxpZEZvckNsYXNzKGZpZWxkTmFtZSwgY2xhc3NOYW1lKSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb2RlOiAxMzYsXG4gICAgICAgICAgICBlcnJvcjogJ2ZpZWxkICcgKyBmaWVsZE5hbWUgKyAnIGNhbm5vdCBiZSBhZGRlZCcsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmaWVsZFR5cGUgPSBmaWVsZHNbZmllbGROYW1lXTtcbiAgICAgICAgY29uc3QgZXJyb3IgPSBmaWVsZFR5cGVJc0ludmFsaWQoZmllbGRUeXBlKTtcbiAgICAgICAgaWYgKGVycm9yKSByZXR1cm4geyBjb2RlOiBlcnJvci5jb2RlLCBlcnJvcjogZXJyb3IubWVzc2FnZSB9O1xuICAgICAgICBpZiAoZmllbGRUeXBlLmRlZmF1bHRWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbGV0IGRlZmF1bHRWYWx1ZVR5cGUgPSBnZXRUeXBlKGZpZWxkVHlwZS5kZWZhdWx0VmFsdWUpO1xuICAgICAgICAgIGlmICh0eXBlb2YgZGVmYXVsdFZhbHVlVHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGRlZmF1bHRWYWx1ZVR5cGUgPSB7IHR5cGU6IGRlZmF1bHRWYWx1ZVR5cGUgfTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgdHlwZW9mIGRlZmF1bHRWYWx1ZVR5cGUgPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgICBmaWVsZFR5cGUudHlwZSA9PT0gJ1JlbGF0aW9uJ1xuICAgICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgY29kZTogUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgICAgICAgIGVycm9yOiBgVGhlICdkZWZhdWx0IHZhbHVlJyBvcHRpb24gaXMgbm90IGFwcGxpY2FibGUgZm9yICR7dHlwZVRvU3RyaW5nKFxuICAgICAgICAgICAgICAgIGZpZWxkVHlwZVxuICAgICAgICAgICAgICApfWAsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIWRiVHlwZU1hdGNoZXNPYmplY3RUeXBlKGZpZWxkVHlwZSwgZGVmYXVsdFZhbHVlVHlwZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgICAgICAgICBlcnJvcjogYHNjaGVtYSBtaXNtYXRjaCBmb3IgJHtjbGFzc05hbWV9LiR7ZmllbGROYW1lfSBkZWZhdWx0IHZhbHVlOyBleHBlY3RlZCAke3R5cGVUb1N0cmluZyhcbiAgICAgICAgICAgICAgICBmaWVsZFR5cGVcbiAgICAgICAgICAgICAgKX0gYnV0IGdvdCAke3R5cGVUb1N0cmluZyhkZWZhdWx0VmFsdWVUeXBlKX1gLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGRUeXBlLnJlcXVpcmVkKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBmaWVsZFR5cGUgPT09ICdvYmplY3QnICYmIGZpZWxkVHlwZS50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBjb2RlOiBQYXJzZS5FcnJvci5JTkNPUlJFQ1RfVFlQRSxcbiAgICAgICAgICAgICAgZXJyb3I6IGBUaGUgJ3JlcXVpcmVkJyBvcHRpb24gaXMgbm90IGFwcGxpY2FibGUgZm9yICR7dHlwZVRvU3RyaW5nKFxuICAgICAgICAgICAgICAgIGZpZWxkVHlwZVxuICAgICAgICAgICAgICApfWAsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZmllbGROYW1lIGluIGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0pIHtcbiAgICAgIGZpZWxkc1tmaWVsZE5hbWVdID0gZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXVtmaWVsZE5hbWVdO1xuICAgIH1cblxuICAgIGNvbnN0IGdlb1BvaW50cyA9IE9iamVjdC5rZXlzKGZpZWxkcykuZmlsdGVyKFxuICAgICAga2V5ID0+IGZpZWxkc1trZXldICYmIGZpZWxkc1trZXldLnR5cGUgPT09ICdHZW9Qb2ludCdcbiAgICApO1xuICAgIGlmIChnZW9Qb2ludHMubGVuZ3RoID4gMSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29kZTogUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgIGVycm9yOlxuICAgICAgICAgICdjdXJyZW50bHksIG9ubHkgb25lIEdlb1BvaW50IGZpZWxkIG1heSBleGlzdCBpbiBhbiBvYmplY3QuIEFkZGluZyAnICtcbiAgICAgICAgICBnZW9Qb2ludHNbMV0gK1xuICAgICAgICAgICcgd2hlbiAnICtcbiAgICAgICAgICBnZW9Qb2ludHNbMF0gK1xuICAgICAgICAgICcgYWxyZWFkeSBleGlzdHMuJyxcbiAgICAgIH07XG4gICAgfVxuICAgIHZhbGlkYXRlQ0xQKGNsYXNzTGV2ZWxQZXJtaXNzaW9ucywgZmllbGRzKTtcbiAgfVxuXG4gIC8vIFNldHMgdGhlIENsYXNzLWxldmVsIHBlcm1pc3Npb25zIGZvciBhIGdpdmVuIGNsYXNzTmFtZSwgd2hpY2ggbXVzdCBleGlzdC5cbiAgc2V0UGVybWlzc2lvbnMoY2xhc3NOYW1lOiBzdHJpbmcsIHBlcm1zOiBhbnksIG5ld1NjaGVtYTogU2NoZW1hRmllbGRzKSB7XG4gICAgaWYgKHR5cGVvZiBwZXJtcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgdmFsaWRhdGVDTFAocGVybXMsIG5ld1NjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2RiQWRhcHRlci5zZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lLCBwZXJtcyk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSB0byB0aGUgbmV3IHNjaGVtYVxuICAvLyBvYmplY3QgaWYgdGhlIHByb3ZpZGVkIGNsYXNzTmFtZS1maWVsZE5hbWUtdHlwZSB0dXBsZSBpcyB2YWxpZC5cbiAgLy8gVGhlIGNsYXNzTmFtZSBtdXN0IGFscmVhZHkgYmUgdmFsaWRhdGVkLlxuICAvLyBJZiAnZnJlZXplJyBpcyB0cnVlLCByZWZ1c2UgdG8gdXBkYXRlIHRoZSBzY2hlbWEgZm9yIHRoaXMgZmllbGQuXG4gIGVuZm9yY2VGaWVsZEV4aXN0cyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBmaWVsZE5hbWU6IHN0cmluZyxcbiAgICB0eXBlOiBzdHJpbmcgfCBTY2hlbWFGaWVsZFxuICApIHtcbiAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+IDApIHtcbiAgICAgIC8vIHN1YmRvY3VtZW50IGtleSAoeC55KSA9PiBvayBpZiB4IGlzIG9mIHR5cGUgJ29iamVjdCdcbiAgICAgIGZpZWxkTmFtZSA9IGZpZWxkTmFtZS5zcGxpdCgnLicpWzBdO1xuICAgICAgdHlwZSA9ICdPYmplY3QnO1xuICAgIH1cbiAgICBpZiAoIWZpZWxkTmFtZUlzVmFsaWQoZmllbGROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICBgSW52YWxpZCBmaWVsZCBuYW1lOiAke2ZpZWxkTmFtZX0uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBJZiBzb21lb25lIHRyaWVzIHRvIGNyZWF0ZSBhIG5ldyBmaWVsZCB3aXRoIG51bGwvdW5kZWZpbmVkIGFzIHRoZSB2YWx1ZSwgcmV0dXJuO1xuICAgIGlmICghdHlwZSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBleHBlY3RlZFR5cGUgPSB0aGlzLmdldEV4cGVjdGVkVHlwZShjbGFzc05hbWUsIGZpZWxkTmFtZSk7XG4gICAgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgdHlwZSA9ICh7IHR5cGUgfTogU2NoZW1hRmllbGQpO1xuICAgIH1cblxuICAgIGlmICh0eXBlLmRlZmF1bHRWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBsZXQgZGVmYXVsdFZhbHVlVHlwZSA9IGdldFR5cGUodHlwZS5kZWZhdWx0VmFsdWUpO1xuICAgICAgaWYgKHR5cGVvZiBkZWZhdWx0VmFsdWVUeXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICBkZWZhdWx0VmFsdWVUeXBlID0geyB0eXBlOiBkZWZhdWx0VmFsdWVUeXBlIH07XG4gICAgICB9XG4gICAgICBpZiAoIWRiVHlwZU1hdGNoZXNPYmplY3RUeXBlKHR5cGUsIGRlZmF1bHRWYWx1ZVR5cGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTkNPUlJFQ1RfVFlQRSxcbiAgICAgICAgICBgc2NoZW1hIG1pc21hdGNoIGZvciAke2NsYXNzTmFtZX0uJHtmaWVsZE5hbWV9IGRlZmF1bHQgdmFsdWU7IGV4cGVjdGVkICR7dHlwZVRvU3RyaW5nKFxuICAgICAgICAgICAgdHlwZVxuICAgICAgICAgICl9IGJ1dCBnb3QgJHt0eXBlVG9TdHJpbmcoZGVmYXVsdFZhbHVlVHlwZSl9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChleHBlY3RlZFR5cGUpIHtcbiAgICAgIGlmICghZGJUeXBlTWF0Y2hlc09iamVjdFR5cGUoZXhwZWN0ZWRUeXBlLCB0eXBlKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgICAgYHNjaGVtYSBtaXNtYXRjaCBmb3IgJHtjbGFzc05hbWV9LiR7ZmllbGROYW1lfTsgZXhwZWN0ZWQgJHt0eXBlVG9TdHJpbmcoXG4gICAgICAgICAgICBleHBlY3RlZFR5cGVcbiAgICAgICAgICApfSBidXQgZ290ICR7dHlwZVRvU3RyaW5nKHR5cGUpfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2RiQWRhcHRlclxuICAgICAgLmFkZEZpZWxkSWZOb3RFeGlzdHMoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHR5cGUpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PSBQYXJzZS5FcnJvci5JTkNPUlJFQ1RfVFlQRSkge1xuICAgICAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHdlIHRocm93IGVycm9ycyB3aGVuIGl0IGlzIGFwcHJvcHJpYXRlIHRvIGRvIHNvLlxuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSB1cGRhdGUgZmFpbGVkLiBUaGlzIGNhbiBiZSBva2F5IC0gaXQgbWlnaHQgaGF2ZSBiZWVuIGEgcmFjZVxuICAgICAgICAvLyBjb25kaXRpb24gd2hlcmUgYW5vdGhlciBjbGllbnQgdXBkYXRlZCB0aGUgc2NoZW1hIGluIHRoZSBzYW1lXG4gICAgICAgIC8vIHdheSB0aGF0IHdlIHdhbnRlZCB0by4gU28sIGp1c3QgcmVsb2FkIHRoZSBzY2hlbWFcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgZmllbGROYW1lLFxuICAgICAgICAgIHR5cGUsXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgfVxuXG4gIGVuc3VyZUZpZWxkcyhmaWVsZHM6IGFueSkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmllbGRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICBjb25zdCB7IGNsYXNzTmFtZSwgZmllbGROYW1lIH0gPSBmaWVsZHNbaV07XG4gICAgICBsZXQgeyB0eXBlIH0gPSBmaWVsZHNbaV07XG4gICAgICBjb25zdCBleHBlY3RlZFR5cGUgPSB0aGlzLmdldEV4cGVjdGVkVHlwZShjbGFzc05hbWUsIGZpZWxkTmFtZSk7XG4gICAgICBpZiAodHlwZW9mIHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHR5cGUgPSB7IHR5cGU6IHR5cGUgfTtcbiAgICAgIH1cbiAgICAgIGlmICghZXhwZWN0ZWRUeXBlIHx8ICFkYlR5cGVNYXRjaGVzT2JqZWN0VHlwZShleHBlY3RlZFR5cGUsIHR5cGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYENvdWxkIG5vdCBhZGQgZmllbGQgJHtmaWVsZE5hbWV9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIG1haW50YWluIGNvbXBhdGliaWxpdHlcbiAgZGVsZXRlRmllbGQoXG4gICAgZmllbGROYW1lOiBzdHJpbmcsXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlQ29udHJvbGxlclxuICApIHtcbiAgICByZXR1cm4gdGhpcy5kZWxldGVGaWVsZHMoW2ZpZWxkTmFtZV0sIGNsYXNzTmFtZSwgZGF0YWJhc2UpO1xuICB9XG5cbiAgLy8gRGVsZXRlIGZpZWxkcywgYW5kIHJlbW92ZSB0aGF0IGRhdGEgZnJvbSBhbGwgb2JqZWN0cy4gVGhpcyBpcyBpbnRlbmRlZFxuICAvLyB0byByZW1vdmUgdW51c2VkIGZpZWxkcywgaWYgb3RoZXIgd3JpdGVycyBhcmUgd3JpdGluZyBvYmplY3RzIHRoYXQgaW5jbHVkZVxuICAvLyB0aGlzIGZpZWxkLCB0aGUgZmllbGQgbWF5IHJlYXBwZWFyLiBSZXR1cm5zIGEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGhcbiAgLy8gbm8gb2JqZWN0IG9uIHN1Y2Nlc3MsIG9yIHJlamVjdHMgd2l0aCB7IGNvZGUsIGVycm9yIH0gb24gZmFpbHVyZS5cbiAgLy8gUGFzc2luZyB0aGUgZGF0YWJhc2UgYW5kIHByZWZpeCBpcyBuZWNlc3NhcnkgaW4gb3JkZXIgdG8gZHJvcCByZWxhdGlvbiBjb2xsZWN0aW9uc1xuICAvLyBhbmQgcmVtb3ZlIGZpZWxkcyBmcm9tIG9iamVjdHMuIElkZWFsbHkgdGhlIGRhdGFiYXNlIHdvdWxkIGJlbG9uZyB0b1xuICAvLyBhIGRhdGFiYXNlIGFkYXB0ZXIgYW5kIHRoaXMgZnVuY3Rpb24gd291bGQgY2xvc2Ugb3ZlciBpdCBvciBhY2Nlc3MgaXQgdmlhIG1lbWJlci5cbiAgZGVsZXRlRmllbGRzKFxuICAgIGZpZWxkTmFtZXM6IEFycmF5PHN0cmluZz4sXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlQ29udHJvbGxlclxuICApIHtcbiAgICBpZiAoIWNsYXNzTmFtZUlzVmFsaWQoY2xhc3NOYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICAgIGludmFsaWRDbGFzc05hbWVNZXNzYWdlKGNsYXNzTmFtZSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgZmllbGROYW1lcy5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpZiAoIWZpZWxkTmFtZUlzVmFsaWQoZmllbGROYW1lKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICAgICBgaW52YWxpZCBmaWVsZCBuYW1lOiAke2ZpZWxkTmFtZX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICAvL0Rvbid0IGFsbG93IGRlbGV0aW5nIHRoZSBkZWZhdWx0IGZpZWxkcy5cbiAgICAgIGlmICghZmllbGROYW1lSXNWYWxpZEZvckNsYXNzKGZpZWxkTmFtZSwgY2xhc3NOYW1lKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTM2LCBgZmllbGQgJHtmaWVsZE5hbWV9IGNhbm5vdCBiZSBjaGFuZ2VkYCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCBmYWxzZSwgeyBjbGVhckNhY2hlOiB0cnVlIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSxcbiAgICAgICAgICAgIGBDbGFzcyAke2NsYXNzTmFtZX0gZG9lcyBub3QgZXhpc3QuYFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgICBmaWVsZE5hbWVzLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICBpZiAoIXNjaGVtYS5maWVsZHNbZmllbGROYW1lXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAyNTUsXG4gICAgICAgICAgICAgIGBGaWVsZCAke2ZpZWxkTmFtZX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBkZWxldGUuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHNjaGVtYUZpZWxkcyA9IHsgLi4uc2NoZW1hLmZpZWxkcyB9O1xuICAgICAgICByZXR1cm4gZGF0YWJhc2UuYWRhcHRlclxuICAgICAgICAgIC5kZWxldGVGaWVsZHMoY2xhc3NOYW1lLCBzY2hlbWEsIGZpZWxkTmFtZXMpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgICAgICAgICBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gc2NoZW1hRmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgICAgICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgIC8vRm9yIHJlbGF0aW9ucywgZHJvcCB0aGUgX0pvaW4gdGFibGVcbiAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhYmFzZS5hZGFwdGVyLmRlbGV0ZUNsYXNzKFxuICAgICAgICAgICAgICAgICAgICBgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWBcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fY2FjaGUuY2xlYXIoKSk7XG4gIH1cblxuICAvLyBWYWxpZGF0ZXMgYW4gb2JqZWN0IHByb3ZpZGVkIGluIFJFU1QgZm9ybWF0LlxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBuZXcgc2NoZW1hIGlmIHRoaXMgb2JqZWN0IGlzXG4gIC8vIHZhbGlkLlxuICBhc3luYyB2YWxpZGF0ZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0OiBhbnksIHF1ZXJ5OiBhbnkpIHtcbiAgICBsZXQgZ2VvY291bnQgPSAwO1xuICAgIGNvbnN0IHNjaGVtYSA9IGF3YWl0IHRoaXMuZW5mb3JjZUNsYXNzRXhpc3RzKGNsYXNzTmFtZSk7XG4gICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcblxuICAgIGZvciAoY29uc3QgZmllbGROYW1lIGluIG9iamVjdCkge1xuICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGdldFR5cGUob2JqZWN0W2ZpZWxkTmFtZV0pO1xuICAgICAgaWYgKGV4cGVjdGVkID09PSAnR2VvUG9pbnQnKSB7XG4gICAgICAgIGdlb2NvdW50Kys7XG4gICAgICB9XG4gICAgICBpZiAoZ2VvY291bnQgPiAxKSB7XG4gICAgICAgIC8vIE1ha2Ugc3VyZSBhbGwgZmllbGQgdmFsaWRhdGlvbiBvcGVyYXRpb25zIHJ1biBiZWZvcmUgd2UgcmV0dXJuLlxuICAgICAgICAvLyBJZiBub3QgLSB3ZSBhcmUgY29udGludWluZyB0byBydW4gbG9naWMsIGJ1dCBhbHJlYWR5IHByb3ZpZGVkIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlci5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgICAgICAgJ3RoZXJlIGNhbiBvbmx5IGJlIG9uZSBnZW9wb2ludCBmaWVsZCBpbiBhIGNsYXNzJ1xuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmICghZXhwZWN0ZWQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGROYW1lID09PSAnQUNMJykge1xuICAgICAgICAvLyBFdmVyeSBvYmplY3QgaGFzIEFDTCBpbXBsaWNpdGx5LlxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHByb21pc2VzLnB1c2goc2NoZW1hLmVuZm9yY2VGaWVsZEV4aXN0cyhjbGFzc05hbWUsIGZpZWxkTmFtZSwgZXhwZWN0ZWQpKTtcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICBjb25zdCBlbmZvcmNlRmllbGRzID0gcmVzdWx0cy5maWx0ZXIocmVzdWx0ID0+ICEhcmVzdWx0KTtcblxuICAgIGlmIChlbmZvcmNlRmllbGRzLmxlbmd0aCAhPT0gMCkge1xuICAgICAgYXdhaXQgdGhpcy5yZWxvYWREYXRhKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgdGhpcy5lbnN1cmVGaWVsZHMoZW5mb3JjZUZpZWxkcyk7XG5cbiAgICBjb25zdCBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoZW5WYWxpZGF0ZVJlcXVpcmVkQ29sdW1ucyhwcm9taXNlLCBjbGFzc05hbWUsIG9iamVjdCwgcXVlcnkpO1xuICB9XG5cbiAgLy8gVmFsaWRhdGVzIHRoYXQgYWxsIHRoZSBwcm9wZXJ0aWVzIGFyZSBzZXQgZm9yIHRoZSBvYmplY3RcbiAgdmFsaWRhdGVSZXF1aXJlZENvbHVtbnMoY2xhc3NOYW1lOiBzdHJpbmcsIG9iamVjdDogYW55LCBxdWVyeTogYW55KSB7XG4gICAgY29uc3QgY29sdW1ucyA9IHJlcXVpcmVkQ29sdW1uc1tjbGFzc05hbWVdO1xuICAgIGlmICghY29sdW1ucyB8fCBjb2x1bW5zLmxlbmd0aCA9PSAwKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuICAgIH1cblxuICAgIGNvbnN0IG1pc3NpbmdDb2x1bW5zID0gY29sdW1ucy5maWx0ZXIoZnVuY3Rpb24oY29sdW1uKSB7XG4gICAgICBpZiAocXVlcnkgJiYgcXVlcnkub2JqZWN0SWQpIHtcbiAgICAgICAgaWYgKG9iamVjdFtjb2x1bW5dICYmIHR5cGVvZiBvYmplY3RbY29sdW1uXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAvLyBUcnlpbmcgdG8gZGVsZXRlIGEgcmVxdWlyZWQgY29sdW1uXG4gICAgICAgICAgcmV0dXJuIG9iamVjdFtjb2x1bW5dLl9fb3AgPT0gJ0RlbGV0ZSc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm90IHRyeWluZyB0byBkbyBhbnl0aGluZyB0aGVyZVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gIW9iamVjdFtjb2x1bW5dO1xuICAgIH0pO1xuXG4gICAgaWYgKG1pc3NpbmdDb2x1bW5zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgIG1pc3NpbmdDb2x1bW5zWzBdICsgJyBpcyByZXF1aXJlZC4nXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuICB9XG5cbiAgdGVzdFBlcm1pc3Npb25zRm9yQ2xhc3NOYW1lKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGFjbEdyb3VwOiBzdHJpbmdbXSxcbiAgICBvcGVyYXRpb246IHN0cmluZ1xuICApIHtcbiAgICByZXR1cm4gU2NoZW1hQ29udHJvbGxlci50ZXN0UGVybWlzc2lvbnMoXG4gICAgICB0aGlzLmdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWUpLFxuICAgICAgYWNsR3JvdXAsXG4gICAgICBvcGVyYXRpb25cbiAgICApO1xuICB9XG5cbiAgLy8gVGVzdHMgdGhhdCB0aGUgY2xhc3MgbGV2ZWwgcGVybWlzc2lvbiBsZXQgcGFzcyB0aGUgb3BlcmF0aW9uIGZvciBhIGdpdmVuIGFjbEdyb3VwXG4gIHN0YXRpYyB0ZXN0UGVybWlzc2lvbnMoXG4gICAgY2xhc3NQZXJtaXNzaW9uczogP2FueSxcbiAgICBhY2xHcm91cDogc3RyaW5nW10sXG4gICAgb3BlcmF0aW9uOiBzdHJpbmdcbiAgKTogYm9vbGVhbiB7XG4gICAgaWYgKCFjbGFzc1Blcm1pc3Npb25zIHx8ICFjbGFzc1Blcm1pc3Npb25zW29wZXJhdGlvbl0pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCBwZXJtcyA9IGNsYXNzUGVybWlzc2lvbnNbb3BlcmF0aW9uXTtcbiAgICBpZiAocGVybXNbJyonXSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIC8vIENoZWNrIHBlcm1pc3Npb25zIGFnYWluc3QgdGhlIGFjbEdyb3VwIHByb3ZpZGVkIChhcnJheSBvZiB1c2VySWQvcm9sZXMpXG4gICAgaWYgKFxuICAgICAgYWNsR3JvdXAuc29tZShhY2wgPT4ge1xuICAgICAgICByZXR1cm4gcGVybXNbYWNsXSA9PT0gdHJ1ZTtcbiAgICAgIH0pXG4gICAgKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gVmFsaWRhdGVzIGFuIG9wZXJhdGlvbiBwYXNzZXMgY2xhc3MtbGV2ZWwtcGVybWlzc2lvbnMgc2V0IGluIHRoZSBzY2hlbWFcbiAgc3RhdGljIHZhbGlkYXRlUGVybWlzc2lvbihcbiAgICBjbGFzc1Blcm1pc3Npb25zOiA/YW55LFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGFjbEdyb3VwOiBzdHJpbmdbXSxcbiAgICBvcGVyYXRpb246IHN0cmluZ1xuICApIHtcbiAgICBpZiAoXG4gICAgICBTY2hlbWFDb250cm9sbGVyLnRlc3RQZXJtaXNzaW9ucyhjbGFzc1Blcm1pc3Npb25zLCBhY2xHcm91cCwgb3BlcmF0aW9uKVxuICAgICkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIGlmICghY2xhc3NQZXJtaXNzaW9ucyB8fCAhY2xhc3NQZXJtaXNzaW9uc1tvcGVyYXRpb25dKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3QgcGVybXMgPSBjbGFzc1Blcm1pc3Npb25zW29wZXJhdGlvbl07XG4gICAgLy8gSWYgb25seSBmb3IgYXV0aGVudGljYXRlZCB1c2Vyc1xuICAgIC8vIG1ha2Ugc3VyZSB3ZSBoYXZlIGFuIGFjbEdyb3VwXG4gICAgaWYgKHBlcm1zWydyZXF1aXJlc0F1dGhlbnRpY2F0aW9uJ10pIHtcbiAgICAgIC8vIElmIGFjbEdyb3VwIGhhcyAqIChwdWJsaWMpXG4gICAgICBpZiAoIWFjbEdyb3VwIHx8IGFjbEdyb3VwLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICdQZXJtaXNzaW9uIGRlbmllZCwgdXNlciBuZWVkcyB0byBiZSBhdXRoZW50aWNhdGVkLidcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoYWNsR3JvdXAuaW5kZXhPZignKicpID4gLTEgJiYgYWNsR3JvdXAubGVuZ3RoID09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgJ1Blcm1pc3Npb24gZGVuaWVkLCB1c2VyIG5lZWRzIHRvIGJlIGF1dGhlbnRpY2F0ZWQuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy8gcmVxdWlyZXNBdXRoZW50aWNhdGlvbiBwYXNzZWQsIGp1c3QgbW92ZSBmb3J3YXJkXG4gICAgICAvLyBwcm9iYWJseSB3b3VsZCBiZSB3aXNlIGF0IHNvbWUgcG9pbnQgdG8gcmVuYW1lIHRvICdhdXRoZW50aWNhdGVkVXNlcidcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICAvLyBObyBtYXRjaGluZyBDTFAsIGxldCdzIGNoZWNrIHRoZSBQb2ludGVyIHBlcm1pc3Npb25zXG4gICAgLy8gQW5kIGhhbmRsZSB0aG9zZSBsYXRlclxuICAgIGNvbnN0IHBlcm1pc3Npb25GaWVsZCA9XG4gICAgICBbJ2dldCcsICdmaW5kJywgJ2NvdW50J10uaW5kZXhPZihvcGVyYXRpb24pID4gLTFcbiAgICAgICAgPyAncmVhZFVzZXJGaWVsZHMnXG4gICAgICAgIDogJ3dyaXRlVXNlckZpZWxkcyc7XG5cbiAgICAvLyBSZWplY3QgY3JlYXRlIHdoZW4gd3JpdGUgbG9ja2Rvd25cbiAgICBpZiAocGVybWlzc2lvbkZpZWxkID09ICd3cml0ZVVzZXJGaWVsZHMnICYmIG9wZXJhdGlvbiA9PSAnY3JlYXRlJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICBgUGVybWlzc2lvbiBkZW5pZWQgZm9yIGFjdGlvbiAke29wZXJhdGlvbn0gb24gY2xhc3MgJHtjbGFzc05hbWV9LmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gUHJvY2VzcyB0aGUgcmVhZFVzZXJGaWVsZHMgbGF0ZXJcbiAgICBpZiAoXG4gICAgICBBcnJheS5pc0FycmF5KGNsYXNzUGVybWlzc2lvbnNbcGVybWlzc2lvbkZpZWxkXSkgJiZcbiAgICAgIGNsYXNzUGVybWlzc2lvbnNbcGVybWlzc2lvbkZpZWxkXS5sZW5ndGggPiAwXG4gICAgKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICBgUGVybWlzc2lvbiBkZW5pZWQgZm9yIGFjdGlvbiAke29wZXJhdGlvbn0gb24gY2xhc3MgJHtjbGFzc05hbWV9LmBcbiAgICApO1xuICB9XG5cbiAgLy8gVmFsaWRhdGVzIGFuIG9wZXJhdGlvbiBwYXNzZXMgY2xhc3MtbGV2ZWwtcGVybWlzc2lvbnMgc2V0IGluIHRoZSBzY2hlbWFcbiAgdmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZTogc3RyaW5nLCBhY2xHcm91cDogc3RyaW5nW10sIG9wZXJhdGlvbjogc3RyaW5nKSB7XG4gICAgcmV0dXJuIFNjaGVtYUNvbnRyb2xsZXIudmFsaWRhdGVQZXJtaXNzaW9uKFxuICAgICAgdGhpcy5nZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lKSxcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIGFjbEdyb3VwLFxuICAgICAgb3BlcmF0aW9uXG4gICAgKTtcbiAgfVxuXG4gIGdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWU6IHN0cmluZyk6IGFueSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdICYmXG4gICAgICB0aGlzLnNjaGVtYURhdGFbY2xhc3NOYW1lXS5jbGFzc0xldmVsUGVybWlzc2lvbnNcbiAgICApO1xuICB9XG5cbiAgLy8gUmV0dXJucyB0aGUgZXhwZWN0ZWQgdHlwZSBmb3IgYSBjbGFzc05hbWUra2V5IGNvbWJpbmF0aW9uXG4gIC8vIG9yIHVuZGVmaW5lZCBpZiB0aGUgc2NoZW1hIGlzIG5vdCBzZXRcbiAgZ2V0RXhwZWN0ZWRUeXBlKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGZpZWxkTmFtZTogc3RyaW5nXG4gICk6ID8oU2NoZW1hRmllbGQgfCBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV0pIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZSA9IHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdLmZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgcmV0dXJuIGV4cGVjdGVkVHlwZSA9PT0gJ21hcCcgPyAnT2JqZWN0JyA6IGV4cGVjdGVkVHlwZTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIENoZWNrcyBpZiBhIGdpdmVuIGNsYXNzIGlzIGluIHRoZSBzY2hlbWEuXG4gIGhhc0NsYXNzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5yZWxvYWREYXRhKCkudGhlbigoKSA9PiAhIXRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdKTtcbiAgfVxufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSBuZXcgU2NoZW1hLlxuY29uc3QgbG9hZCA9IChcbiAgZGJBZGFwdGVyOiBTdG9yYWdlQWRhcHRlcixcbiAgc2NoZW1hQ2FjaGU6IGFueSxcbiAgb3B0aW9uczogYW55XG4pOiBQcm9taXNlPFNjaGVtYUNvbnRyb2xsZXI+ID0+IHtcbiAgY29uc3Qgc2NoZW1hID0gbmV3IFNjaGVtYUNvbnRyb2xsZXIoZGJBZGFwdGVyLCBzY2hlbWFDYWNoZSk7XG4gIHJldHVybiBzY2hlbWEucmVsb2FkRGF0YShvcHRpb25zKS50aGVuKCgpID0+IHNjaGVtYSk7XG59O1xuXG4vLyBCdWlsZHMgYSBuZXcgc2NoZW1hIChpbiBzY2hlbWEgQVBJIHJlc3BvbnNlIGZvcm1hdCkgb3V0IG9mIGFuXG4vLyBleGlzdGluZyBtb25nbyBzY2hlbWEgKyBhIHNjaGVtYXMgQVBJIHB1dCByZXF1ZXN0LiBUaGlzIHJlc3BvbnNlXG4vLyBkb2VzIG5vdCBpbmNsdWRlIHRoZSBkZWZhdWx0IGZpZWxkcywgYXMgaXQgaXMgaW50ZW5kZWQgdG8gYmUgcGFzc2VkXG4vLyB0byBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWUuIE5vIHZhbGlkYXRpb24gaXMgZG9uZSBoZXJlLCBpdFxuLy8gaXMgZG9uZSBpbiBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWUuXG5mdW5jdGlvbiBidWlsZE1lcmdlZFNjaGVtYU9iamVjdChcbiAgZXhpc3RpbmdGaWVsZHM6IFNjaGVtYUZpZWxkcyxcbiAgcHV0UmVxdWVzdDogYW55XG4pOiBTY2hlbWFGaWVsZHMge1xuICBjb25zdCBuZXdTY2hlbWEgPSB7fTtcbiAgLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG4gIGNvbnN0IHN5c1NjaGVtYUZpZWxkID1cbiAgICBPYmplY3Qua2V5cyhkZWZhdWx0Q29sdW1ucykuaW5kZXhPZihleGlzdGluZ0ZpZWxkcy5faWQpID09PSAtMVxuICAgICAgPyBbXVxuICAgICAgOiBPYmplY3Qua2V5cyhkZWZhdWx0Q29sdW1uc1tleGlzdGluZ0ZpZWxkcy5faWRdKTtcbiAgZm9yIChjb25zdCBvbGRGaWVsZCBpbiBleGlzdGluZ0ZpZWxkcykge1xuICAgIGlmIChcbiAgICAgIG9sZEZpZWxkICE9PSAnX2lkJyAmJlxuICAgICAgb2xkRmllbGQgIT09ICdBQ0wnICYmXG4gICAgICBvbGRGaWVsZCAhPT0gJ3VwZGF0ZWRBdCcgJiZcbiAgICAgIG9sZEZpZWxkICE9PSAnY3JlYXRlZEF0JyAmJlxuICAgICAgb2xkRmllbGQgIT09ICdvYmplY3RJZCdcbiAgICApIHtcbiAgICAgIGlmIChcbiAgICAgICAgc3lzU2NoZW1hRmllbGQubGVuZ3RoID4gMCAmJlxuICAgICAgICBzeXNTY2hlbWFGaWVsZC5pbmRleE9mKG9sZEZpZWxkKSAhPT0gLTFcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZpZWxkSXNEZWxldGVkID1cbiAgICAgICAgcHV0UmVxdWVzdFtvbGRGaWVsZF0gJiYgcHV0UmVxdWVzdFtvbGRGaWVsZF0uX19vcCA9PT0gJ0RlbGV0ZSc7XG4gICAgICBpZiAoIWZpZWxkSXNEZWxldGVkKSB7XG4gICAgICAgIG5ld1NjaGVtYVtvbGRGaWVsZF0gPSBleGlzdGluZ0ZpZWxkc1tvbGRGaWVsZF07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZvciAoY29uc3QgbmV3RmllbGQgaW4gcHV0UmVxdWVzdCkge1xuICAgIGlmIChuZXdGaWVsZCAhPT0gJ29iamVjdElkJyAmJiBwdXRSZXF1ZXN0W25ld0ZpZWxkXS5fX29wICE9PSAnRGVsZXRlJykge1xuICAgICAgaWYgKFxuICAgICAgICBzeXNTY2hlbWFGaWVsZC5sZW5ndGggPiAwICYmXG4gICAgICAgIHN5c1NjaGVtYUZpZWxkLmluZGV4T2YobmV3RmllbGQpICE9PSAtMVxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgbmV3U2NoZW1hW25ld0ZpZWxkXSA9IHB1dFJlcXVlc3RbbmV3RmllbGRdO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbmV3U2NoZW1hO1xufVxuXG4vLyBHaXZlbiBhIHNjaGVtYSBwcm9taXNlLCBjb25zdHJ1Y3QgYW5vdGhlciBzY2hlbWEgcHJvbWlzZSB0aGF0XG4vLyB2YWxpZGF0ZXMgdGhpcyBmaWVsZCBvbmNlIHRoZSBzY2hlbWEgbG9hZHMuXG5mdW5jdGlvbiB0aGVuVmFsaWRhdGVSZXF1aXJlZENvbHVtbnMoc2NoZW1hUHJvbWlzZSwgY2xhc3NOYW1lLCBvYmplY3QsIHF1ZXJ5KSB7XG4gIHJldHVybiBzY2hlbWFQcm9taXNlLnRoZW4oc2NoZW1hID0+IHtcbiAgICByZXR1cm4gc2NoZW1hLnZhbGlkYXRlUmVxdWlyZWRDb2x1bW5zKGNsYXNzTmFtZSwgb2JqZWN0LCBxdWVyeSk7XG4gIH0pO1xufVxuXG4vLyBHZXRzIHRoZSB0eXBlIGZyb20gYSBSRVNUIEFQSSBmb3JtYXR0ZWQgb2JqZWN0LCB3aGVyZSAndHlwZScgaXNcbi8vIGV4dGVuZGVkIHBhc3QgamF2YXNjcmlwdCB0eXBlcyB0byBpbmNsdWRlIHRoZSByZXN0IG9mIHRoZSBQYXJzZVxuLy8gdHlwZSBzeXN0ZW0uXG4vLyBUaGUgb3V0cHV0IHNob3VsZCBiZSBhIHZhbGlkIHNjaGVtYSB2YWx1ZS5cbi8vIFRPRE86IGVuc3VyZSB0aGF0IHRoaXMgaXMgY29tcGF0aWJsZSB3aXRoIHRoZSBmb3JtYXQgdXNlZCBpbiBPcGVuIERCXG5mdW5jdGlvbiBnZXRUeXBlKG9iajogYW55KTogPyhTY2hlbWFGaWVsZCB8IHN0cmluZykge1xuICBjb25zdCB0eXBlID0gdHlwZW9mIG9iajtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4gJ0Jvb2xlYW4nO1xuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICByZXR1cm4gJ1N0cmluZyc7XG4gICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgIHJldHVybiAnTnVtYmVyJztcbiAgICBjYXNlICdtYXAnOlxuICAgIGNhc2UgJ29iamVjdCc6XG4gICAgICBpZiAoIW9iaikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGdldE9iamVjdFR5cGUob2JqKTtcbiAgICBjYXNlICdmdW5jdGlvbic6XG4gICAgY2FzZSAnc3ltYm9sJzpcbiAgICBjYXNlICd1bmRlZmluZWQnOlxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyAnYmFkIG9iajogJyArIG9iajtcbiAgfVxufVxuXG4vLyBUaGlzIGdldHMgdGhlIHR5cGUgZm9yIG5vbi1KU09OIHR5cGVzIGxpa2UgcG9pbnRlcnMgYW5kIGZpbGVzLCBidXRcbi8vIGFsc28gZ2V0cyB0aGUgYXBwcm9wcmlhdGUgdHlwZSBmb3IgJCBvcGVyYXRvcnMuXG4vLyBSZXR1cm5zIG51bGwgaWYgdGhlIHR5cGUgaXMgdW5rbm93bi5cbmZ1bmN0aW9uIGdldE9iamVjdFR5cGUob2JqKTogPyhTY2hlbWFGaWVsZCB8IHN0cmluZykge1xuICBpZiAob2JqIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICByZXR1cm4gJ0FycmF5JztcbiAgfVxuICBpZiAob2JqLl9fdHlwZSkge1xuICAgIHN3aXRjaCAob2JqLl9fdHlwZSkge1xuICAgICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICAgIGlmIChvYmouY2xhc3NOYW1lKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgICAgIHRhcmdldENsYXNzOiBvYmouY2xhc3NOYW1lLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdSZWxhdGlvbic6XG4gICAgICAgIGlmIChvYmouY2xhc3NOYW1lKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6ICdSZWxhdGlvbicsXG4gICAgICAgICAgICB0YXJnZXRDbGFzczogb2JqLmNsYXNzTmFtZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnRmlsZSc6XG4gICAgICAgIGlmIChvYmoubmFtZSkge1xuICAgICAgICAgIHJldHVybiAnRmlsZSc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdEYXRlJzpcbiAgICAgICAgaWYgKG9iai5pc28pIHtcbiAgICAgICAgICByZXR1cm4gJ0RhdGUnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnR2VvUG9pbnQnOlxuICAgICAgICBpZiAob2JqLmxhdGl0dWRlICE9IG51bGwgJiYgb2JqLmxvbmdpdHVkZSAhPSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuICdHZW9Qb2ludCc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdCeXRlcyc6XG4gICAgICAgIGlmIChvYmouYmFzZTY0KSB7XG4gICAgICAgICAgcmV0dXJuICdCeXRlcyc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdQb2x5Z29uJzpcbiAgICAgICAgaWYgKG9iai5jb29yZGluYXRlcykge1xuICAgICAgICAgIHJldHVybiAnUG9seWdvbic7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgJ1RoaXMgaXMgbm90IGEgdmFsaWQgJyArIG9iai5fX3R5cGVcbiAgICApO1xuICB9XG4gIGlmIChvYmpbJyRuZSddKSB7XG4gICAgcmV0dXJuIGdldE9iamVjdFR5cGUob2JqWyckbmUnXSk7XG4gIH1cbiAgaWYgKG9iai5fX29wKSB7XG4gICAgc3dpdGNoIChvYmouX19vcCkge1xuICAgICAgY2FzZSAnSW5jcmVtZW50JzpcbiAgICAgICAgcmV0dXJuICdOdW1iZXInO1xuICAgICAgY2FzZSAnRGVsZXRlJzpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBjYXNlICdBZGQnOlxuICAgICAgY2FzZSAnQWRkVW5pcXVlJzpcbiAgICAgIGNhc2UgJ1JlbW92ZSc6XG4gICAgICAgIHJldHVybiAnQXJyYXknO1xuICAgICAgY2FzZSAnQWRkUmVsYXRpb24nOlxuICAgICAgY2FzZSAnUmVtb3ZlUmVsYXRpb24nOlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6ICdSZWxhdGlvbicsXG4gICAgICAgICAgdGFyZ2V0Q2xhc3M6IG9iai5vYmplY3RzWzBdLmNsYXNzTmFtZSxcbiAgICAgICAgfTtcbiAgICAgIGNhc2UgJ0JhdGNoJzpcbiAgICAgICAgcmV0dXJuIGdldE9iamVjdFR5cGUob2JqLm9wc1swXSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyAndW5leHBlY3RlZCBvcDogJyArIG9iai5fX29wO1xuICAgIH1cbiAgfVxuICByZXR1cm4gJ09iamVjdCc7XG59XG5cbmV4cG9ydCB7XG4gIGxvYWQsXG4gIGNsYXNzTmFtZUlzVmFsaWQsXG4gIGZpZWxkTmFtZUlzVmFsaWQsXG4gIGludmFsaWRDbGFzc05hbWVNZXNzYWdlLFxuICBidWlsZE1lcmdlZFNjaGVtYU9iamVjdCxcbiAgc3lzdGVtQ2xhc3NlcyxcbiAgZGVmYXVsdENvbHVtbnMsXG4gIGNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEsXG4gIFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMsXG4gIFNjaGVtYUNvbnRyb2xsZXIsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Controllers/UserController.js b/lib/Controllers/UserController.js new file mode 100644 index 0000000000..762ef86fc4 --- /dev/null +++ b/lib/Controllers/UserController.js @@ -0,0 +1,317 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.UserController = void 0; + +var _cryptoUtils = require("../cryptoUtils"); + +var _triggers = require("../triggers"); + +var _AdaptableController = _interopRequireDefault(require("./AdaptableController")); + +var _MailAdapter = _interopRequireDefault(require("../Adapters/Email/MailAdapter")); + +var _rest = _interopRequireDefault(require("../rest")); + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var RestQuery = require('../RestQuery'); + +var Auth = require('../Auth'); + +class UserController extends _AdaptableController.default { + constructor(adapter, appId, options = {}) { + super(adapter, appId, options); + } + + validateAdapter(adapter) { + // Allow no adapter + if (!adapter && !this.shouldVerifyEmails) { + return; + } + + super.validateAdapter(adapter); + } + + expectedAdapterType() { + return _MailAdapter.default; + } + + get shouldVerifyEmails() { + return this.options.verifyUserEmails; + } + + setEmailVerifyToken(user) { + if (this.shouldVerifyEmails) { + user._email_verify_token = (0, _cryptoUtils.randomString)(25); + user.emailVerified = false; + + if (this.config.emailVerifyTokenValidityDuration) { + user._email_verify_token_expires_at = _node.default._encode(this.config.generateEmailVerifyTokenExpiresAt()); + } + } + } + + verifyEmail(username, token) { + if (!this.shouldVerifyEmails) { + // Trying to verify email when not enabled + // TODO: Better error here. + throw undefined; + } + + const query = { + username: username, + _email_verify_token: token + }; + const updateFields = { + emailVerified: true, + _email_verify_token: { + __op: 'Delete' + } + }; // if the email verify token needs to be validated then + // add additional query params and additional fields that need to be updated + + if (this.config.emailVerifyTokenValidityDuration) { + query.emailVerified = false; + query._email_verify_token_expires_at = { + $gt: _node.default._encode(new Date()) + }; + updateFields._email_verify_token_expires_at = { + __op: 'Delete' + }; + } + + const masterAuth = Auth.master(this.config); + var checkIfAlreadyVerified = new RestQuery(this.config, Auth.master(this.config), '_User', { + username: username, + emailVerified: true + }); + return checkIfAlreadyVerified.execute().then(result => { + if (result.results.length) { + return Promise.resolve(result.results.length[0]); + } + + return _rest.default.update(this.config, masterAuth, '_User', query, updateFields); + }); + } + + checkResetTokenValidity(username, token) { + return this.config.database.find('_User', { + username: username, + _perishable_token: token + }, { + limit: 1 + }).then(results => { + if (results.length != 1) { + throw 'Failed to reset password: username / email / token is invalid'; + } + + if (this.config.passwordPolicy && this.config.passwordPolicy.resetTokenValidityDuration) { + let expiresDate = results[0]._perishable_token_expires_at; + + if (expiresDate && expiresDate.__type == 'Date') { + expiresDate = new Date(expiresDate.iso); + } + + if (expiresDate < new Date()) throw 'The password reset link has expired'; + } + + return results[0]; + }); + } + + getUserIfNeeded(user) { + if (user.username && user.email) { + return Promise.resolve(user); + } + + var where = {}; + + if (user.username) { + where.username = user.username; + } + + if (user.email) { + where.email = user.email; + } + + var query = new RestQuery(this.config, Auth.master(this.config), '_User', where); + return query.execute().then(function (result) { + if (result.results.length != 1) { + throw undefined; + } + + return result.results[0]; + }); + } + + sendVerificationEmail(user) { + if (!this.shouldVerifyEmails) { + return; + } + + const token = encodeURIComponent(user._email_verify_token); // We may need to fetch the user in case of update email + + this.getUserIfNeeded(user).then(user => { + const username = encodeURIComponent(user.username); + const link = buildEmailLink(this.config.verifyEmailURL, username, token, this.config); + const options = { + appName: this.config.appName, + link: link, + user: (0, _triggers.inflate)('_User', user) + }; + + if (this.adapter.sendVerificationEmail) { + this.adapter.sendVerificationEmail(options); + } else { + this.adapter.sendMail(this.defaultVerificationEmail(options)); + } + }); + } + /** + * Regenerates the given user's email verification token + * + * @param user + * @returns {*} + */ + + + regenerateEmailVerifyToken(user) { + this.setEmailVerifyToken(user); + return this.config.database.update('_User', { + username: user.username + }, user); + } + + resendVerificationEmail(username) { + return this.getUserIfNeeded({ + username: username + }).then(aUser => { + if (!aUser || aUser.emailVerified) { + throw undefined; + } + + return this.regenerateEmailVerifyToken(aUser).then(() => { + this.sendVerificationEmail(aUser); + }); + }); + } + + setPasswordResetToken(email) { + const token = { + _perishable_token: (0, _cryptoUtils.randomString)(25) + }; + + if (this.config.passwordPolicy && this.config.passwordPolicy.resetTokenValidityDuration) { + token._perishable_token_expires_at = _node.default._encode(this.config.generatePasswordResetTokenExpiresAt()); + } + + return this.config.database.update('_User', { + $or: [{ + email + }, { + username: email, + email: { + $exists: false + } + }] + }, token, {}, true); + } + + sendPasswordResetEmail(email) { + if (!this.adapter) { + throw 'Trying to send a reset password but no adapter is set'; // TODO: No adapter? + } + + return this.setPasswordResetToken(email).then(user => { + const token = encodeURIComponent(user._perishable_token); + const username = encodeURIComponent(user.username); + const link = buildEmailLink(this.config.requestResetPasswordURL, username, token, this.config); + const options = { + appName: this.config.appName, + link: link, + user: (0, _triggers.inflate)('_User', user) + }; + + if (this.adapter.sendPasswordResetEmail) { + this.adapter.sendPasswordResetEmail(options); + } else { + this.adapter.sendMail(this.defaultResetPasswordEmail(options)); + } + + return Promise.resolve(user); + }); + } + + updatePassword(username, token, password) { + return this.checkResetTokenValidity(username, token).then(user => updateUserPassword(user.objectId, password, this.config)).catch(error => { + if (error && error.message) { + // in case of Parse.Error, fail with the error message only + return Promise.reject(error.message); + } else { + return Promise.reject(error); + } + }); + } + + defaultVerificationEmail({ + link, + user, + appName + }) { + const text = 'Hi,\n\n' + 'You are being asked to confirm the e-mail address ' + user.get('email') + ' with ' + appName + '\n\n' + '' + 'Click here to confirm it:\n' + link; + const to = user.get('email'); + const subject = 'Please verify your e-mail for ' + appName; + return { + text, + to, + subject + }; + } + + defaultResetPasswordEmail({ + link, + user, + appName + }) { + const text = 'Hi,\n\n' + 'You requested to reset your password for ' + appName + (user.get('username') ? " (your username is '" + user.get('username') + "')" : '') + '.\n\n' + '' + 'Click here to reset it:\n' + link; + const to = user.get('email') || user.get('username'); + const subject = 'Password Reset for ' + appName; + return { + text, + to, + subject + }; + } + +} // Mark this private + + +exports.UserController = UserController; + +function updateUserPassword(userId, password, config) { + return _rest.default.update(config, Auth.master(config), '_User', { + objectId: userId + }, { + password: password + }); +} + +function buildEmailLink(destination, username, token, config) { + const usernameAndToken = `token=${token}&username=${username}`; + + if (config.parseFrameURL) { + const destinationWithoutHost = destination.replace(config.publicServerURL, ''); + return `${config.parseFrameURL}?link=${encodeURIComponent(destinationWithoutHost)}&${usernameAndToken}`; + } else { + return `${destination}?${usernameAndToken}`; + } +} + +var _default = UserController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9Vc2VyQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJSZXN0UXVlcnkiLCJyZXF1aXJlIiwiQXV0aCIsIlVzZXJDb250cm9sbGVyIiwiQWRhcHRhYmxlQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwiYWRhcHRlciIsImFwcElkIiwib3B0aW9ucyIsInZhbGlkYXRlQWRhcHRlciIsInNob3VsZFZlcmlmeUVtYWlscyIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJNYWlsQWRhcHRlciIsInZlcmlmeVVzZXJFbWFpbHMiLCJzZXRFbWFpbFZlcmlmeVRva2VuIiwidXNlciIsIl9lbWFpbF92ZXJpZnlfdG9rZW4iLCJlbWFpbFZlcmlmaWVkIiwiY29uZmlnIiwiZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQiLCJQYXJzZSIsIl9lbmNvZGUiLCJnZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW5FeHBpcmVzQXQiLCJ2ZXJpZnlFbWFpbCIsInVzZXJuYW1lIiwidG9rZW4iLCJ1bmRlZmluZWQiLCJxdWVyeSIsInVwZGF0ZUZpZWxkcyIsIl9fb3AiLCIkZ3QiLCJEYXRlIiwibWFzdGVyQXV0aCIsIm1hc3RlciIsImNoZWNrSWZBbHJlYWR5VmVyaWZpZWQiLCJleGVjdXRlIiwidGhlbiIsInJlc3VsdCIsInJlc3VsdHMiLCJsZW5ndGgiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlc3QiLCJ1cGRhdGUiLCJjaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSIsImRhdGFiYXNlIiwiZmluZCIsIl9wZXJpc2hhYmxlX3Rva2VuIiwibGltaXQiLCJwYXNzd29yZFBvbGljeSIsInJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uIiwiZXhwaXJlc0RhdGUiLCJfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0IiwiX190eXBlIiwiaXNvIiwiZ2V0VXNlcklmTmVlZGVkIiwiZW1haWwiLCJ3aGVyZSIsInNlbmRWZXJpZmljYXRpb25FbWFpbCIsImVuY29kZVVSSUNvbXBvbmVudCIsImxpbmsiLCJidWlsZEVtYWlsTGluayIsInZlcmlmeUVtYWlsVVJMIiwiYXBwTmFtZSIsInNlbmRNYWlsIiwiZGVmYXVsdFZlcmlmaWNhdGlvbkVtYWlsIiwicmVnZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW4iLCJyZXNlbmRWZXJpZmljYXRpb25FbWFpbCIsImFVc2VyIiwic2V0UGFzc3dvcmRSZXNldFRva2VuIiwiZ2VuZXJhdGVQYXNzd29yZFJlc2V0VG9rZW5FeHBpcmVzQXQiLCIkb3IiLCIkZXhpc3RzIiwic2VuZFBhc3N3b3JkUmVzZXRFbWFpbCIsInJlcXVlc3RSZXNldFBhc3N3b3JkVVJMIiwiZGVmYXVsdFJlc2V0UGFzc3dvcmRFbWFpbCIsInVwZGF0ZVBhc3N3b3JkIiwicGFzc3dvcmQiLCJ1cGRhdGVVc2VyUGFzc3dvcmQiLCJvYmplY3RJZCIsImNhdGNoIiwiZXJyb3IiLCJtZXNzYWdlIiwicmVqZWN0IiwidGV4dCIsImdldCIsInRvIiwic3ViamVjdCIsInVzZXJJZCIsImRlc3RpbmF0aW9uIiwidXNlcm5hbWVBbmRUb2tlbiIsInBhcnNlRnJhbWVVUkwiLCJkZXN0aW5hdGlvbldpdGhvdXRIb3N0IiwicmVwbGFjZSIsInB1YmxpY1NlcnZlclVSTCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsSUFBSUEsU0FBUyxHQUFHQyxPQUFPLENBQUMsY0FBRCxDQUF2Qjs7QUFDQSxJQUFJQyxJQUFJLEdBQUdELE9BQU8sQ0FBQyxTQUFELENBQWxCOztBQUVPLE1BQU1FLGNBQU4sU0FBNkJDLDRCQUE3QixDQUFpRDtBQUN0REMsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQVVDLEtBQVYsRUFBaUJDLE9BQU8sR0FBRyxFQUEzQixFQUErQjtBQUN4QyxVQUFNRixPQUFOLEVBQWVDLEtBQWYsRUFBc0JDLE9BQXRCO0FBQ0Q7O0FBRURDLEVB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SUFBQUEsUUFBUSxFQUFFUztBQUFaLEdBSkssRUFLTDtBQUNFWCxJQUFBQSxRQUFRLEVBQUVBO0FBRFosR0FMSyxDQUFQO0FBU0Q7O0FBRUQsU0FBU2hCLGNBQVQsQ0FBd0I0QixXQUF4QixFQUFxQ2pFLFFBQXJDLEVBQStDQyxLQUEvQyxFQUFzRFIsTUFBdEQsRUFBOEQ7QUFDNUQsUUFBTXlFLGdCQUFnQixHQUFJLFNBQVFqRSxLQUFNLGFBQVlELFFBQVMsRUFBN0Q7O0FBRUEsTUFBSVAsTUFBTSxDQUFDMEUsYUFBWCxFQUEwQjtBQUN4QixVQUFNQyxzQkFBc0IsR0FBR0gsV0FBVyxDQUFDSSxPQUFaLENBQzdCNUUsTUFBTSxDQUFDNkUsZUFEc0IsRUFFN0IsRUFGNkIsQ0FBL0I7QUFLQSxXQUFRLEdBQUU3RSxNQUFNLENBQUMwRSxhQUFjLFNBQVFoQyxrQkFBa0IsQ0FDdkRpQyxzQkFEdUQsQ0FFdkQsSUFBR0YsZ0JBQWlCLEVBRnRCO0FBR0QsR0FURCxNQVNPO0FBQ0wsV0FBUSxHQUFFRCxXQUFZLElBQUdDLGdCQUFpQixFQUExQztBQUNEO0FBQ0Y7O2VBRWN4RixjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tU3RyaW5nIH0gZnJvbSAnLi4vY3J5cHRvVXRpbHMnO1xuaW1wb3J0IHsgaW5mbGF0ZSB9IGZyb20gJy4uL3RyaWdnZXJzJztcbmltcG9ydCBBZGFwdGFibGVDb250cm9sbGVyIGZyb20gJy4vQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgTWFpbEFkYXB0ZXIgZnJvbSAnLi4vQWRhcHRlcnMvRW1haWwvTWFpbEFkYXB0ZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5cbnZhciBSZXN0UXVlcnkgPSByZXF1aXJlKCcuLi9SZXN0UXVlcnknKTtcbnZhciBBdXRoID0gcmVxdWlyZSgnLi4vQXV0aCcpO1xuXG5leHBvcnQgY2xhc3MgVXNlckNvbnRyb2xsZXIgZXh0ZW5kcyBBZGFwdGFibGVDb250cm9sbGVyIHtcbiAgY29uc3RydWN0b3IoYWRhcHRlciwgYXBwSWQsIG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIGFwcElkLCBvcHRpb25zKTtcbiAgfVxuXG4gIHZhbGlkYXRlQWRhcHRlcihhZGFwdGVyKSB7XG4gICAgLy8gQWxsb3cgbm8gYWRhcHRlclxuICAgIGlmICghYWRhcHRlciAmJiAhdGhpcy5zaG91bGRWZXJpZnlFbWFpbHMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3VwZXIudmFsaWRhdGVBZGFwdGVyKGFkYXB0ZXIpO1xuICB9XG5cbiAgZXhwZWN0ZWRBZGFwdGVyVHlwZSgpIHtcbiAgICByZXR1cm4gTWFpbEFkYXB0ZXI7XG4gIH1cblxuICBnZXQgc2hvdWxkVmVyaWZ5RW1haWxzKCkge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMudmVyaWZ5VXNlckVtYWlscztcbiAgfVxuXG4gIHNldEVtYWlsVmVyaWZ5VG9rZW4odXNlcikge1xuICAgIGlmICh0aGlzLnNob3VsZFZlcmlmeUVtYWlscykge1xuICAgICAgdXNlci5fZW1haWxfdmVyaWZ5X3Rva2VuID0gcmFuZG9tU3RyaW5nKDI1KTtcbiAgICAgIHVzZXIuZW1haWxWZXJpZmllZCA9IGZhbHNlO1xuXG4gICAgICBpZiAodGhpcy5jb25maWcuZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24pIHtcbiAgICAgICAgdXNlci5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQgPSBQYXJzZS5fZW5jb2RlKFxuICAgICAgICAgIHRoaXMuY29uZmlnLmdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbkV4cGlyZXNBdCgpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmVyaWZ5RW1haWwodXNlcm5hbWUsIHRva2VuKSB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFZlcmlmeUVtYWlscykge1xuICAgICAgLy8gVHJ5aW5nIHRvIHZlcmlmeSBlbWFpbCB3aGVuIG5vdCBlbmFibGVkXG4gICAgICAvLyBUT0RPOiBCZXR0ZXIgZXJyb3IgaGVyZS5cbiAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBxdWVyeSA9IHsgdXNlcm5hbWU6IHVzZXJuYW1lLCBfZW1haWxfdmVyaWZ5X3Rva2VuOiB0b2tlbiB9O1xuICAgIGNvbnN0IHVwZGF0ZUZpZWxkcyA9IHtcbiAgICAgIGVtYWlsVmVyaWZpZWQ6IHRydWUsXG4gICAgICBfZW1haWxfdmVyaWZ5X3Rva2VuOiB7IF9fb3A6ICdEZWxldGUnIH0sXG4gICAgfTtcblxuICAgIC8vIGlmIHRoZSBlbWFpbCB2ZXJpZnkgdG9rZW4gbmVlZHMgdG8gYmUgdmFsaWRhdGVkIHRoZW5cbiAgICAvLyBhZGQgYWRkaXRpb25hbCBxdWVyeSBwYXJhbXMgYW5kIGFkZGl0aW9uYWwgZmllbGRzIHRoYXQgbmVlZCB0byBiZSB1cGRhdGVkXG4gICAgaWYgKHRoaXMuY29uZmlnLmVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uKSB7XG4gICAgICBxdWVyeS5lbWFpbFZlcmlmaWVkID0gZmFsc2U7XG4gICAgICBxdWVyeS5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQgPSB7ICRndDogUGFyc2UuX2VuY29kZShuZXcgRGF0ZSgpKSB9O1xuXG4gICAgICB1cGRhdGVGaWVsZHMuX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0ID0geyBfX29wOiAnRGVsZXRlJyB9O1xuICAgIH1cbiAgICBjb25zdCBtYXN0ZXJBdXRoID0gQXV0aC5tYXN0ZXIodGhpcy5jb25maWcpO1xuICAgIHZhciBjaGVja0lmQWxyZWFkeVZlcmlmaWVkID0gbmV3IFJlc3RRdWVyeShcbiAgICAgIHRoaXMuY29uZmlnLFxuICAgICAgQXV0aC5tYXN0ZXIodGhpcy5jb25maWcpLFxuICAgICAgJ19Vc2VyJyxcbiAgICAgIHsgdXNlcm5hbWU6IHVzZXJuYW1lLCBlbWFpbFZlcmlmaWVkOiB0cnVlIH1cbiAgICApO1xuICAgIHJldHVybiBjaGVja0lmQWxyZWFkeVZlcmlmaWVkLmV4ZWN1dGUoKS50aGVuKHJlc3VsdCA9PiB7XG4gICAgICBpZiAocmVzdWx0LnJlc3VsdHMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0LnJlc3VsdHMubGVuZ3RoWzBdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN0LnVwZGF0ZSh0aGlzLmNvbmZpZywgbWFzdGVyQXV0aCwgJ19Vc2VyJywgcXVlcnksIHVwZGF0ZUZpZWxkcyk7XG4gICAgfSk7XG4gIH1cblxuICBjaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSh1c2VybmFtZSwgdG9rZW4pIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgIC5maW5kKFxuICAgICAgICAnX1VzZXInLFxuICAgICAgICB7XG4gICAgICAgICAgdXNlcm5hbWU6IHVzZXJuYW1lLFxuICAgICAgICAgIF9wZXJpc2hhYmxlX3Rva2VuOiB0b2tlbixcbiAgICAgICAgfSxcbiAgICAgICAgeyBsaW1pdDogMSB9XG4gICAgICApXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9IDEpIHtcbiAgICAgICAgICB0aHJvdyAnRmFpbGVkIHRvIHJlc2V0IHBhc3N3b3JkOiB1c2VybmFtZSAvIGVtYWlsIC8gdG9rZW4gaXMgaW52YWxpZCc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kgJiZcbiAgICAgICAgICB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICBsZXQgZXhwaXJlc0RhdGUgPSByZXN1bHRzWzBdLl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQ7XG4gICAgICAgICAgaWYgKGV4cGlyZXNEYXRlICYmIGV4cGlyZXNEYXRlLl9fdHlwZSA9PSAnRGF0ZScpIHtcbiAgICAgICAgICAgIGV4cGlyZXNEYXRlID0gbmV3IERhdGUoZXhwaXJlc0RhdGUuaXNvKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGV4cGlyZXNEYXRlIDwgbmV3IERhdGUoKSlcbiAgICAgICAgICAgIHRocm93ICdUaGUgcGFzc3dvcmQgcmVzZXQgbGluayBoYXMgZXhwaXJlZCc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0c1swXTtcbiAgICAgIH0pO1xuICB9XG5cbiAgZ2V0VXNlcklmTmVlZGVkKHVzZXIpIHtcbiAgICBpZiAodXNlci51c2VybmFtZSAmJiB1c2VyLmVtYWlsKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVzZXIpO1xuICAgIH1cbiAgICB2YXIgd2hlcmUgPSB7fTtcbiAgICBpZiAodXNlci51c2VybmFtZSkge1xuICAgICAgd2hlcmUudXNlcm5hbWUgPSB1c2VyLnVzZXJuYW1lO1xuICAgIH1cbiAgICBpZiAodXNlci5lbWFpbCkge1xuICAgICAgd2hlcmUuZW1haWwgPSB1c2VyLmVtYWlsO1xuICAgIH1cblxuICAgIHZhciBxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgICB0aGlzLmNvbmZpZyxcbiAgICAgIEF1dGgubWFzdGVyKHRoaXMuY29uZmlnKSxcbiAgICAgICdfVXNlcicsXG4gICAgICB3aGVyZVxuICAgICk7XG4gICAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgaWYgKHJlc3VsdC5yZXN1bHRzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQucmVzdWx0c1swXTtcbiAgICB9KTtcbiAgfVxuXG4gIHNlbmRWZXJpZmljYXRpb25FbWFpbCh1c2VyKSB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFZlcmlmeUVtYWlscykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB0b2tlbiA9IGVuY29kZVVSSUNvbXBvbmVudCh1c2VyLl9lbWFpbF92ZXJpZnlfdG9rZW4pO1xuICAgIC8vIFdlIG1heSBuZWVkIHRvIGZldGNoIHRoZSB1c2VyIGluIGNhc2Ugb2YgdXBkYXRlIGVtYWlsXG4gICAgdGhpcy5nZXRVc2VySWZOZWVkZWQodXNlcikudGhlbih1c2VyID0+IHtcbiAgICAgIGNvbnN0IHVzZXJuYW1lID0gZW5jb2RlVVJJQ29tcG9uZW50KHVzZXIudXNlcm5hbWUpO1xuXG4gICAgICBjb25zdCBsaW5rID0gYnVpbGRFbWFpbExpbmsoXG4gICAgICAgIHRoaXMuY29uZmlnLnZlcmlmeUVtYWlsVVJMLFxuICAgICAgICB1c2VybmFtZSxcbiAgICAgICAgdG9rZW4sXG4gICAgICAgIHRoaXMuY29uZmlnXG4gICAgICApO1xuICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgYXBwTmFtZTogdGhpcy5jb25maWcuYXBwTmFtZSxcbiAgICAgICAgbGluazogbGluayxcbiAgICAgICAgdXNlcjogaW5mbGF0ZSgnX1VzZXInLCB1c2VyKSxcbiAgICAgIH07XG4gICAgICBpZiAodGhpcy5hZGFwdGVyLnNlbmRWZXJpZmljYXRpb25FbWFpbCkge1xuICAgICAgICB0aGlzLmFkYXB0ZXIuc2VuZFZlcmlmaWNhdGlvbkVtYWlsKG9wdGlvbnMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hZGFwdGVyLnNlbmRNYWlsKHRoaXMuZGVmYXVsdFZlcmlmaWNhdGlvbkVtYWlsKG9wdGlvbnMpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdlbmVyYXRlcyB0aGUgZ2l2ZW4gdXNlcidzIGVtYWlsIHZlcmlmaWNhdGlvbiB0b2tlblxuICAgKlxuICAgKiBAcGFyYW0gdXNlclxuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHJlZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuKHVzZXIpIHtcbiAgICB0aGlzLnNldEVtYWlsVmVyaWZ5VG9rZW4odXNlcik7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLnVwZGF0ZShcbiAgICAgICdfVXNlcicsXG4gICAgICB7IHVzZXJuYW1lOiB1c2VyLnVzZXJuYW1lIH0sXG4gICAgICB1c2VyXG4gICAgKTtcbiAgfVxuXG4gIHJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHVzZXJuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VXNlcklmTmVlZGVkKHsgdXNlcm5hbWU6IHVzZXJuYW1lIH0pLnRoZW4oYVVzZXIgPT4ge1xuICAgICAgaWYgKCFhVXNlciB8fCBhVXNlci5lbWFpbFZlcmlmaWVkKSB7XG4gICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnJlZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuKGFVc2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zZW5kVmVyaWZpY2F0aW9uRW1haWwoYVVzZXIpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBzZXRQYXNzd29yZFJlc2V0VG9rZW4oZW1haWwpIHtcbiAgICBjb25zdCB0b2tlbiA9IHsgX3BlcmlzaGFibGVfdG9rZW46IHJhbmRvbVN0cmluZygyNSkgfTtcblxuICAgIGlmIChcbiAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5ICYmXG4gICAgICB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvblxuICAgICkge1xuICAgICAgdG9rZW4uX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCA9IFBhcnNlLl9lbmNvZGUoXG4gICAgICAgIHRoaXMuY29uZmlnLmdlbmVyYXRlUGFzc3dvcmRSZXNldFRva2VuRXhwaXJlc0F0KClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLnVwZGF0ZShcbiAgICAgICdfVXNlcicsXG4gICAgICB7ICRvcjogW3sgZW1haWwgfSwgeyB1c2VybmFtZTogZW1haWwsIGVtYWlsOiB7ICRleGlzdHM6IGZhbHNlIH0gfV0gfSxcbiAgICAgIHRva2VuLFxuICAgICAge30sXG4gICAgICB0cnVlXG4gICAgKTtcbiAgfVxuXG4gIHNlbmRQYXNzd29yZFJlc2V0RW1haWwoZW1haWwpIHtcbiAgICBpZiAoIXRoaXMuYWRhcHRlcikge1xuICAgICAgdGhyb3cgJ1RyeWluZyB0byBzZW5kIGEgcmVzZXQgcGFzc3dvcmQgYnV0IG5vIGFkYXB0ZXIgaXMgc2V0JztcbiAgICAgIC8vICBUT0RPOiBObyBhZGFwdGVyP1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNldFBhc3N3b3JkUmVzZXRUb2tlbihlbWFpbCkudGhlbih1c2VyID0+IHtcbiAgICAgIGNvbnN0IHRva2VuID0gZW5jb2RlVVJJQ29tcG9uZW50KHVzZXIuX3BlcmlzaGFibGVfdG9rZW4pO1xuICAgICAgY29uc3QgdXNlcm5hbWUgPSBlbmNvZGVVUklDb21wb25lbnQodXNlci51c2VybmFtZSk7XG5cbiAgICAgIGNvbnN0IGxpbmsgPSBidWlsZEVtYWlsTGluayhcbiAgICAgICAgdGhpcy5jb25maWcucmVxdWVzdFJlc2V0UGFzc3dvcmRVUkwsXG4gICAgICAgIHVzZXJuYW1lLFxuICAgICAgICB0b2tlbixcbiAgICAgICAgdGhpcy5jb25maWdcbiAgICAgICk7XG4gICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICBhcHBOYW1lOiB0aGlzLmNvbmZpZy5hcHBOYW1lLFxuICAgICAgICBsaW5rOiBsaW5rLFxuICAgICAgICB1c2VyOiBpbmZsYXRlKCdfVXNlcicsIHVzZXIpLFxuICAgICAgfTtcblxuICAgICAgaWYgKHRoaXMuYWRhcHRlci5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKSB7XG4gICAgICAgIHRoaXMuYWRhcHRlci5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKG9wdGlvbnMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hZGFwdGVyLnNlbmRNYWlsKHRoaXMuZGVmYXVsdFJlc2V0UGFzc3dvcmRFbWFpbChvcHRpb25zKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodXNlcik7XG4gICAgfSk7XG4gIH1cblxuICB1cGRhdGVQYXNzd29yZCh1c2VybmFtZSwgdG9rZW4sIHBhc3N3b3JkKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hlY2tSZXNldFRva2VuVmFsaWRpdHkodXNlcm5hbWUsIHRva2VuKVxuICAgICAgLnRoZW4odXNlciA9PiB1cGRhdGVVc2VyUGFzc3dvcmQodXNlci5vYmplY3RJZCwgcGFzc3dvcmQsIHRoaXMuY29uZmlnKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvciAmJiBlcnJvci5tZXNzYWdlKSB7XG4gICAgICAgICAgLy8gaW4gY2FzZSBvZiBQYXJzZS5FcnJvciwgZmFpbCB3aXRoIHRoZSBlcnJvciBtZXNzYWdlIG9ubHlcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBkZWZhdWx0VmVyaWZpY2F0aW9uRW1haWwoeyBsaW5rLCB1c2VyLCBhcHBOYW1lIH0pIHtcbiAgICBjb25zdCB0ZXh0ID1cbiAgICAgICdIaSxcXG5cXG4nICtcbiAgICAgICdZb3UgYXJlIGJlaW5nIGFza2VkIHRvIGNvbmZpcm0gdGhlIGUtbWFpbCBhZGRyZXNzICcgK1xuICAgICAgdXNlci5nZXQoJ2VtYWlsJykgK1xuICAgICAgJyB3aXRoICcgK1xuICAgICAgYXBwTmFtZSArXG4gICAgICAnXFxuXFxuJyArXG4gICAgICAnJyArXG4gICAgICAnQ2xpY2sgaGVyZSB0byBjb25maXJtIGl0OlxcbicgK1xuICAgICAgbGluaztcbiAgICBjb25zdCB0byA9IHVzZXIuZ2V0KCdlbWFpbCcpO1xuICAgIGNvbnN0IHN1YmplY3QgPSAnUGxlYXNlIHZlcmlmeSB5b3VyIGUtbWFpbCBmb3IgJyArIGFwcE5hbWU7XG4gICAgcmV0dXJuIHsgdGV4dCwgdG8sIHN1YmplY3QgfTtcbiAgfVxuXG4gIGRlZmF1bHRSZXNldFBhc3N3b3JkRW1haWwoeyBsaW5rLCB1c2VyLCBhcHBOYW1lIH0pIHtcbiAgICBjb25zdCB0ZXh0ID1cbiAgICAgICdIaSxcXG5cXG4nICtcbiAgICAgICdZb3UgcmVxdWVzdGVkIHRvIHJlc2V0IHlvdXIgcGFzc3dvcmQgZm9yICcgK1xuICAgICAgYXBwTmFtZSArXG4gICAgICAodXNlci5nZXQoJ3VzZXJuYW1lJylcbiAgICAgICAgPyBcIiAoeW91ciB1c2VybmFtZSBpcyAnXCIgKyB1c2VyLmdldCgndXNlcm5hbWUnKSArIFwiJylcIlxuICAgICAgICA6ICcnKSArXG4gICAgICAnLlxcblxcbicgK1xuICAgICAgJycgK1xuICAgICAgJ0NsaWNrIGhlcmUgdG8gcmVzZXQgaXQ6XFxuJyArXG4gICAgICBsaW5rO1xuICAgIGNvbnN0IHRvID0gdXNlci5nZXQoJ2VtYWlsJykgfHwgdXNlci5nZXQoJ3VzZXJuYW1lJyk7XG4gICAgY29uc3Qgc3ViamVjdCA9ICdQYXNzd29yZCBSZXNldCBmb3IgJyArIGFwcE5hbWU7XG4gICAgcmV0dXJuIHsgdGV4dCwgdG8sIHN1YmplY3QgfTtcbiAgfVxufVxuXG4vLyBNYXJrIHRoaXMgcHJpdmF0ZVxuZnVuY3Rpb24gdXBkYXRlVXNlclBhc3N3b3JkKHVzZXJJZCwgcGFzc3dvcmQsIGNvbmZpZykge1xuICByZXR1cm4gcmVzdC51cGRhdGUoXG4gICAgY29uZmlnLFxuICAgIEF1dGgubWFzdGVyKGNvbmZpZyksXG4gICAgJ19Vc2VyJyxcbiAgICB7IG9iamVjdElkOiB1c2VySWQgfSxcbiAgICB7XG4gICAgICBwYXNzd29yZDogcGFzc3dvcmQsXG4gICAgfVxuICApO1xufVxuXG5mdW5jdGlvbiBidWlsZEVtYWlsTGluayhkZXN0aW5hdGlvbiwgdXNlcm5hbWUsIHRva2VuLCBjb25maWcpIHtcbiAgY29uc3QgdXNlcm5hbWVBbmRUb2tlbiA9IGB0b2tlbj0ke3Rva2VufSZ1c2VybmFtZT0ke3VzZXJuYW1lfWA7XG5cbiAgaWYgKGNvbmZpZy5wYXJzZUZyYW1lVVJMKSB7XG4gICAgY29uc3QgZGVzdGluYXRpb25XaXRob3V0SG9zdCA9IGRlc3RpbmF0aW9uLnJlcGxhY2UoXG4gICAgICBjb25maWcucHVibGljU2VydmVyVVJMLFxuICAgICAgJydcbiAgICApO1xuXG4gICAgcmV0dXJuIGAke2NvbmZpZy5wYXJzZUZyYW1lVVJMfT9saW5rPSR7ZW5jb2RlVVJJQ29tcG9uZW50KFxuICAgICAgZGVzdGluYXRpb25XaXRob3V0SG9zdFxuICAgICl9JiR7dXNlcm5hbWVBbmRUb2tlbn1gO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBgJHtkZXN0aW5hdGlvbn0/JHt1c2VybmFtZUFuZFRva2VufWA7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgVXNlckNvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/index.js b/lib/Controllers/index.js new file mode 100644 index 0000000000..8e682074b2 --- /dev/null +++ b/lib/Controllers/index.js @@ -0,0 +1,310 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getControllers = getControllers; +exports.getLoggerController = getLoggerController; +exports.getFilesController = getFilesController; +exports.getUserController = getUserController; +exports.getCacheController = getCacheController; +exports.getParseGraphQLController = getParseGraphQLController; +exports.getAnalyticsController = getAnalyticsController; +exports.getLiveQueryController = getLiveQueryController; +exports.getDatabaseController = getDatabaseController; +exports.getHooksController = getHooksController; +exports.getPushController = getPushController; +exports.getAuthDataManager = getAuthDataManager; +exports.getDatabaseAdapter = getDatabaseAdapter; + +var _Auth = _interopRequireDefault(require("../Adapters/Auth")); + +var _Options = require("../Options"); + +var _AdapterLoader = require("../Adapters/AdapterLoader"); + +var _defaults = _interopRequireDefault(require("../defaults")); + +var _url = _interopRequireDefault(require("url")); + +var _LoggerController = require("./LoggerController"); + +var _FilesController = require("./FilesController"); + +var _HooksController = require("./HooksController"); + +var _UserController = require("./UserController"); + +var _CacheController = require("./CacheController"); + +var _LiveQueryController = require("./LiveQueryController"); + +var _AnalyticsController = require("./AnalyticsController"); + +var _PushController = require("./PushController"); + +var _PushQueue = require("../Push/PushQueue"); + +var _PushWorker = require("../Push/PushWorker"); + +var _DatabaseController = _interopRequireDefault(require("./DatabaseController")); + +var _SchemaCache = _interopRequireDefault(require("./SchemaCache")); + +var _GridFSBucketAdapter = require("../Adapters/Files/GridFSBucketAdapter"); + +var _WinstonLoggerAdapter = require("../Adapters/Logger/WinstonLoggerAdapter"); + +var _InMemoryCacheAdapter = require("../Adapters/Cache/InMemoryCacheAdapter"); + +var _AnalyticsAdapter = require("../Adapters/Analytics/AnalyticsAdapter"); + +var _MongoStorageAdapter = _interopRequireDefault(require("../Adapters/Storage/Mongo/MongoStorageAdapter")); + +var _PostgresStorageAdapter = _interopRequireDefault(require("../Adapters/Storage/Postgres/PostgresStorageAdapter")); + +var _pushAdapter = _interopRequireDefault(require("@parse/push-adapter")); + +var _ParseGraphQLController = _interopRequireDefault(require("./ParseGraphQLController")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getControllers(options) { + const loggerController = getLoggerController(options); + const filesController = getFilesController(options); + const userController = getUserController(options); + const { + pushController, + hasPushScheduledSupport, + hasPushSupport, + pushControllerQueue, + pushWorker + } = getPushController(options); + const cacheController = getCacheController(options); + const analyticsController = getAnalyticsController(options); + const liveQueryController = getLiveQueryController(options); + const databaseController = getDatabaseController(options, cacheController); + const hooksController = getHooksController(options, databaseController); + const authDataManager = getAuthDataManager(options); + const parseGraphQLController = getParseGraphQLController(options, { + databaseController, + cacheController + }); + return { + loggerController, + filesController, + userController, + pushController, + hasPushScheduledSupport, + hasPushSupport, + pushWorker, + pushControllerQueue, + analyticsController, + cacheController, + parseGraphQLController, + liveQueryController, + databaseController, + hooksController, + authDataManager + }; +} + +function getLoggerController(options) { + const { + appId, + jsonLogs, + logsFolder, + verbose, + logLevel, + silent, + loggerAdapter + } = options; + const loggerOptions = { + jsonLogs, + logsFolder, + verbose, + logLevel, + silent + }; + const loggerControllerAdapter = (0, _AdapterLoader.loadAdapter)(loggerAdapter, _WinstonLoggerAdapter.WinstonLoggerAdapter, loggerOptions); + return new _LoggerController.LoggerController(loggerControllerAdapter, appId, loggerOptions); +} + +function getFilesController(options) { + const { + appId, + databaseURI, + filesAdapter, + databaseAdapter, + preserveFileName + } = options; + + if (!filesAdapter && databaseAdapter) { + throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.'; + } + + const filesControllerAdapter = (0, _AdapterLoader.loadAdapter)(filesAdapter, () => { + return new _GridFSBucketAdapter.GridFSBucketAdapter(databaseURI); + }); + return new _FilesController.FilesController(filesControllerAdapter, appId, { + preserveFileName + }); +} + +function getUserController(options) { + const { + appId, + emailAdapter, + verifyUserEmails + } = options; + const emailControllerAdapter = (0, _AdapterLoader.loadAdapter)(emailAdapter); + return new _UserController.UserController(emailControllerAdapter, appId, { + verifyUserEmails + }); +} + +function getCacheController(options) { + const { + appId, + cacheAdapter, + cacheTTL, + cacheMaxSize + } = options; + const cacheControllerAdapter = (0, _AdapterLoader.loadAdapter)(cacheAdapter, _InMemoryCacheAdapter.InMemoryCacheAdapter, { + appId: appId, + ttl: cacheTTL, + maxSize: cacheMaxSize + }); + return new _CacheController.CacheController(cacheControllerAdapter, appId); +} + +function getParseGraphQLController(options, controllerDeps) { + return new _ParseGraphQLController.default(_objectSpread({ + mountGraphQL: options.mountGraphQL + }, controllerDeps)); +} + +function getAnalyticsController(options) { + const { + analyticsAdapter + } = options; + const analyticsControllerAdapter = (0, _AdapterLoader.loadAdapter)(analyticsAdapter, _AnalyticsAdapter.AnalyticsAdapter); + return new _AnalyticsController.AnalyticsController(analyticsControllerAdapter); +} + +function getLiveQueryController(options) { + return new _LiveQueryController.LiveQueryController(options.liveQuery); +} + +function getDatabaseController(options, cacheController) { + const { + databaseURI, + databaseOptions, + skipMongoDBServer13732Workaround, + collectionPrefix, + schemaCacheTTL, + enableSingleSchemaCache + } = options; + let { + databaseAdapter + } = options; + + if ((databaseOptions || databaseURI && databaseURI !== _defaults.default.databaseURI || collectionPrefix !== _defaults.default.collectionPrefix) && databaseAdapter) { + throw 'You cannot specify both a databaseAdapter and a databaseURI/databaseOptions/collectionPrefix.'; + } else if (!databaseAdapter) { + databaseAdapter = getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions); + } else { + databaseAdapter = (0, _AdapterLoader.loadAdapter)(databaseAdapter); + } + + return new _DatabaseController.default(databaseAdapter, new _SchemaCache.default(cacheController, schemaCacheTTL, enableSingleSchemaCache), skipMongoDBServer13732Workaround); +} + +function getHooksController(options, databaseController) { + const { + appId, + webhookKey + } = options; + return new _HooksController.HooksController(appId, databaseController, webhookKey); +} + +function getPushController(options) { + const { + scheduledPush, + push + } = options; + const pushOptions = Object.assign({}, push); + const pushQueueOptions = pushOptions.queueOptions || {}; + + if (pushOptions.queueOptions) { + delete pushOptions.queueOptions; + } // Pass the push options too as it works with the default + + + const pushAdapter = (0, _AdapterLoader.loadAdapter)(pushOptions && pushOptions.adapter, _pushAdapter.default, pushOptions); // We pass the options and the base class for the adatper, + // Note that passing an instance would work too + + const pushController = new _PushController.PushController(); + const hasPushSupport = !!(pushAdapter && push); + const hasPushScheduledSupport = hasPushSupport && scheduledPush === true; + const { + disablePushWorker + } = pushQueueOptions; + const pushControllerQueue = new _PushQueue.PushQueue(pushQueueOptions); + let pushWorker; + + if (!disablePushWorker) { + pushWorker = new _PushWorker.PushWorker(pushAdapter, pushQueueOptions); + } + + return { + pushController, + hasPushSupport, + hasPushScheduledSupport, + pushControllerQueue, + pushWorker + }; +} + +function getAuthDataManager(options) { + const { + auth, + enableAnonymousUsers + } = options; + return (0, _Auth.default)(auth, enableAnonymousUsers); +} + +function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions) { + let protocol; + + try { + const parsedURI = _url.default.parse(databaseURI); + + protocol = parsedURI.protocol ? parsedURI.protocol.toLowerCase() : null; + } catch (e) { + /* */ + } + + switch (protocol) { + case 'postgres:': + return new _PostgresStorageAdapter.default({ + uri: databaseURI, + collectionPrefix, + databaseOptions + }); + + default: + return new _MongoStorageAdapter.default({ + uri: databaseURI, + collectionPrefix, + mongoOptions: databaseOptions + }); + } +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9pbmRleC5qcyJdLCJuYW1lcyI6WyJnZXRDb250cm9sbGVycyIsIm9wdGlvbnMiLCJsb2dnZXJDb250cm9sbGVyIiwiZ2V0TG9nZ2VyQ29udHJvbGxlciIsImZpbGVzQ29udHJvbGxlciIsImdldEZpbGVzQ29udHJvbGxlciIsInVzZXJDb250cm9sbGVyIiwiZ2V0VXNlckNvbnRyb2xsZXIiLCJwdXNoQ29udHJvbGxlciIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0IiwiaGFzUHVzaFN1cHBvcnQiLCJwdXNoQ29udHJvbGxlclF1ZXVlIiwicHVzaFdvcmtlciIsImdldFB1c2hDb250cm9sbGVyIiwiY2FjaGVDb250cm9sbGVyIiwiZ2V0Q2FjaGVDb250cm9sbGVyIiwiYW5hbHl0aWNzQ29udHJvbGxlciIsImdldEFuYWx5dGljc0NvbnRyb2xsZXIiLCJsaXZlUXVlcnlDb250cm9sbGVyIiwiZ2V0TGl2ZVF1ZXJ5Q29udHJvbGxlciIsImRhdGFiYXNlQ29udHJvbGxlciIsImdldERhdGFiYXNlQ29udHJvbGxlciIsImhvb2tzQ29udHJvbGxlciIsImdldEhvb2tzQ29udHJvbGxlciIsImF1dGhEYXRhTWFuYWdlciIsImdldEF1dGhEYXRhTWFuYWdlciIsInBhcnNlR3JhcGhRTENvbnRyb2xsZXIiLCJnZXRQYXJzZUdyYXBoUUxDb250cm9sbGVyIiwiYXBwSWQiLCJqc29uTG9ncyIsImxvZ3NGb2xkZXIiLCJ2ZXJib3NlIiwibG9nTGV2ZWwiLCJzaWxlbnQiLCJsb2dnZXJBZGFwdGVyIiwibG9nZ2VyT3B0aW9ucyIsImxvZ2dlckNvbnRyb2xsZXJBZGFwdGVyIiwiV2luc3RvbkxvZ2dlckFkYXB0ZXIiLCJMb2dnZXJDb250cm9sbGVyIiwiZGF0YWJhc2VVUkkiLCJmaWxlc0FkYXB0ZXIiLCJkYXRhYmFzZUFkYXB0ZXIiLCJwcmVzZXJ2ZUZpbGVOYW1lIiwiZmlsZXNDb250cm9sbGVyQWRhcHRlciIsIkdyaWRGU0J1Y2tldEFkYXB0ZXIiLCJGaWxlc0NvbnRyb2xsZXIiLCJlbWFpbEFkYXB0ZXIiLCJ2ZXJpZnlVc2VyRW1haWxzIiwiZW1haWxDb250cm9sbGVyQWRhcHRlciIsIlVzZXJDb250cm9sbGVyIiwiY2FjaGVBZGFwdGVyIiwiY2FjaGVUVEwiLCJjYWNoZU1heFNpemUiLCJjYWNoZUNvbnRyb2xsZXJBZGFwdGVyIiwiSW5NZW1vcnlDYWNoZUFkYXB0ZXIiLCJ0dGwiLCJtYXhTaXplIiwiQ2FjaGVDb250cm9sbGVyIiwiY29udHJvbGxlckRlcHMiLCJQYXJzZUdyYXBoUUxDb250cm9sbGVyIiwibW91bnRHcmFwaFFMIiwiYW5hbHl0aWNzQWRhcHRlciIsImFuYWx5dGljc0NvbnRyb2xsZXJBZGFwdGVyIiwiQW5hbHl0aWNzQWRhcHRlciIsIkFuYWx5dGljc0NvbnRyb2xsZXIiLCJMaXZlUXVlcnlDb250cm9sbGVyIiwibGl2ZVF1ZXJ5IiwiZGF0YWJhc2VPcHRpb25zIiwic2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQiLCJjb2xsZWN0aW9uUHJlZml4Iiwic2NoZW1hQ2FjaGVUVEwiLCJlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSIsImRlZmF1bHRzIiwiZ2V0RGF0YWJhc2VBZGFwdGVyIiwiRGF0YWJhc2VDb250cm9sbGVyIiwiU2NoZW1hQ2FjaGUiLCJ3ZWJob29rS2V5IiwiSG9va3NDb250cm9sbGVyIiwic2NoZWR1bGVkUHVzaCIsInB1c2giLCJwdXNoT3B0aW9ucyIsIk9iamVjdCIsImFzc2lnbiIsInB1c2hRdWV1ZU9wdGlvbnMiLCJxdWV1ZU9wdGlvbnMiLCJwdXNoQWRhcHRlciIsImFkYXB0ZXIiLCJQYXJzZVB1c2hBZGFwdGVyIiwiUHVzaENvbnRyb2xsZXIiLCJkaXNhYmxlUHVzaFdvcmtlciIsIlB1c2hRdWV1ZSIsIlB1c2hXb3JrZXIiLCJhdXRoIiwiZW5hYmxlQW5vbnltb3VzVXNlcnMiLCJwcm90b2NvbCIsInBhcnNlZFVSSSIsInVybCIsInBhcnNlIiwidG9Mb3dlckNhc2UiLCJlIiwiUG9zdGdyZXNTdG9yYWdlQWRhcHRlciIsInVyaSIsIk1vbmdvU3RvcmFnZUFkYXB0ZXIiLCJtb25nb09wdGlvbnMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFHQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7OztBQUVPLFNBQVNBLGNBQVQsQ0FBd0JDLE9BQXhCLEVBQXFEO0FBQzFELFFBQU1DLGdCQUFnQixHQUFHQyxtQkFBbUIsQ0FBQ0YsT0FBRCxDQUE1QztBQUNBLFFBQU1HLGVBQWUsR0FBR0Msa0JBQWtCLENBQUNKLE9BQUQsQ0FBMUM7QUFDQSxRQUFNSyxjQUFjLEdBQUdDLGlCQUFpQixDQUFDTixPQUFELENBQXhDO0FBQ0EsUUFBTTtBQUNKTyxJQUFBQSxjQURJO0FBRUpDLElBQUFBLHVCQUZJO0FBR0pDLElBQUFBLGNBSEk7QUFJSkMsSUFBQUEsbUJBSkk7QUFLSkMsSUFBQUE7QUFMSSxNQU1GQyxpQkFBaUIsQ0FBQ1osT0FBRCxDQU5yQjtBQU9BLFFBQU1hLGVBQWUsR0FBR0Msa0JBQWtCLENBQUNkLE9BQUQsQ0FBMUM7QUFDQSxRQUFNZSxtQkFBbUIsR0FBR0Msc0JBQXNCLENBQUNoQixPQUFELENBQWxEO0FBQ0EsUUFBTWlCLG1CQUFtQixHQUFHQyxzQkFBc0IsQ0FBQ2xCLE9BQUQsQ0FBbEQ7QUFDQSxRQUFNbUIsa0JBQWtCLEdBQUdDLHFCQUFxQixDQUFDcEIsT0FBRCxFQUFVYSxlQUFWLENBQWhEO0FBQ0EsUUFBTVEsZUFBZSxHQUFHQyxrQkFBa0IsQ0FBQ3RCLE9BQUQsRUFBVW1CLGtCQUFWLENBQTFDO0FBQ0EsUUFBTUksZUFBZSxHQUFHQyxrQkFBa0IsQ0FBQ3hCLE9BQUQsQ0FBMUM7QUFDQSxRQUFNeUIsc0JBQXNCLEdBQUdDLHlC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QVA7O0FBS0Y7QUFDRSxhQUFPLElBQUltQyw0QkFBSixDQUF3QjtBQUM3QkQsUUFBQUEsR0FBRyxFQUFFOUQsV0FEd0I7QUFFN0I4QixRQUFBQSxnQkFGNkI7QUFHN0JrQyxRQUFBQSxZQUFZLEVBQUVwQztBQUhlLE9BQXhCLENBQVA7QUFSSjtBQWNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGF1dGhEYXRhTWFuYWdlciBmcm9tICcuLi9BZGFwdGVycy9BdXRoJztcbmltcG9ydCB7IFBhcnNlU2VydmVyT3B0aW9ucyB9IGZyb20gJy4uL09wdGlvbnMnO1xuaW1wb3J0IHsgbG9hZEFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9BZGFwdGVyTG9hZGVyJztcbmltcG9ydCBkZWZhdWx0cyBmcm9tICcuLi9kZWZhdWx0cyc7XG5pbXBvcnQgdXJsIGZyb20gJ3VybCc7XG4vLyBDb250cm9sbGVyc1xuaW1wb3J0IHsgTG9nZ2VyQ29udHJvbGxlciB9IGZyb20gJy4vTG9nZ2VyQ29udHJvbGxlcic7XG5pbXBvcnQgeyBGaWxlc0NvbnRyb2xsZXIgfSBmcm9tICcuL0ZpbGVzQ29udHJvbGxlcic7XG5pbXBvcnQgeyBIb29rc0NvbnRyb2xsZXIgfSBmcm9tICcuL0hvb2tzQ29udHJvbGxlcic7XG5pbXBvcnQgeyBVc2VyQ29udHJvbGxlciB9IGZyb20gJy4vVXNlckNvbnRyb2xsZXInO1xuaW1wb3J0IHsgQ2FjaGVDb250cm9sbGVyIH0gZnJvbSAnLi9DYWNoZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgTGl2ZVF1ZXJ5Q29udHJvbGxlciB9IGZyb20gJy4vTGl2ZVF1ZXJ5Q29udHJvbGxlcic7XG5pbXBvcnQgeyBBbmFseXRpY3NDb250cm9sbGVyIH0gZnJvbSAnLi9BbmFseXRpY3NDb250cm9sbGVyJztcbmltcG9ydCB7IFB1c2hDb250cm9sbGVyIH0gZnJvbSAnLi9QdXNoQ29udHJvbGxlcic7XG5pbXBvcnQgeyBQdXNoUXVldWUgfSBmcm9tICcuLi9QdXNoL1B1c2hRdWV1ZSc7XG5pbXBvcnQgeyBQdXNoV29ya2VyIH0gZnJvbSAnLi4vUHVzaC9QdXNoV29ya2VyJztcbmltcG9ydCBEYXRhYmFzZUNvbnRyb2xsZXIgZnJvbSAnLi9EYXRhYmFzZUNvbnRyb2xsZXInO1xuaW1wb3J0IFNjaGVtYUNhY2hlIGZyb20gJy4vU2NoZW1hQ2FjaGUnO1xuXG4vLyBBZGFwdGVyc1xuaW1wb3J0IHsgR3JpZEZTQnVja2V0QWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0ZpbGVzL0dyaWRGU0J1Y2tldEFkYXB0ZXInO1xuaW1wb3J0IHsgV2luc3RvbkxvZ2dlckFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlckFkYXB0ZXInO1xuaW1wb3J0IHsgSW5NZW1vcnlDYWNoZUFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9DYWNoZS9Jbk1lbW9yeUNhY2hlQWRhcHRlcic7XG5pbXBvcnQgeyBBbmFseXRpY3NBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQW5hbHl0aWNzL0FuYWx5dGljc0FkYXB0ZXInO1xuaW1wb3J0IE1vbmdvU3RvcmFnZUFkYXB0ZXIgZnJvbSAnLi4vQWRhcHRlcnMvU3RvcmFnZS9Nb25nby9Nb25nb1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCBQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyIGZyb20gJy4uL0FkYXB0ZXJzL1N0b3JhZ2UvUG9zdGdyZXMvUG9zdGdyZXNTdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgUGFyc2VQdXNoQWRhcHRlciBmcm9tICdAcGFyc2UvcHVzaC1hZGFwdGVyJztcbmltcG9ydCBQYXJzZUdyYXBoUUxDb250cm9sbGVyIGZyb20gJy4vUGFyc2VHcmFwaFFMQ29udHJvbGxlcic7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb250cm9sbGVycyhvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgY29uc3QgbG9nZ2VyQ29udHJvbGxlciA9IGdldExvZ2dlckNvbnRyb2xsZXIob3B0aW9ucyk7XG4gIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGdldEZpbGVzQ29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3QgdXNlckNvbnRyb2xsZXIgPSBnZXRVc2VyQ29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3Qge1xuICAgIHB1c2hDb250cm9sbGVyLFxuICAgIGhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0LFxuICAgIGhhc1B1c2hTdXBwb3J0LFxuICAgIHB1c2hDb250cm9sbGVyUXVldWUsXG4gICAgcHVzaFdvcmtlcixcbiAgfSA9IGdldFB1c2hDb250cm9sbGVyKG9wdGlvbnMpO1xuICBjb25zdCBjYWNoZUNvbnRyb2xsZXIgPSBnZXRDYWNoZUNvbnRyb2xsZXIob3B0aW9ucyk7XG4gIGNvbnN0IGFuYWx5dGljc0NvbnRyb2xsZXIgPSBnZXRBbmFseXRpY3NDb250cm9sbGVyKG9wdGlvbnMpO1xuICBjb25zdCBsaXZlUXVlcnlDb250cm9sbGVyID0gZ2V0TGl2ZVF1ZXJ5Q29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3QgZGF0YWJhc2VDb250cm9sbGVyID0gZ2V0RGF0YWJhc2VDb250cm9sbGVyKG9wdGlvbnMsIGNhY2hlQ29udHJvbGxlcik7XG4gIGNvbnN0IGhvb2tzQ29udHJvbGxlciA9IGdldEhvb2tzQ29udHJvbGxlcihvcHRpb25zLCBkYXRhYmFzZUNvbnRyb2xsZXIpO1xuICBjb25zdCBhdXRoRGF0YU1hbmFnZXIgPSBnZXRBdXRoRGF0YU1hbmFnZXIob3B0aW9ucyk7XG4gIGNvbnN0IHBhcnNlR3JhcGhRTENvbnRyb2xsZXIgPSBnZXRQYXJzZUdyYXBoUUxDb250cm9sbGVyKG9wdGlvbnMsIHtcbiAgICBkYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgY2FjaGVDb250cm9sbGVyLFxuICB9KTtcbiAgcmV0dXJuIHtcbiAgICBsb2dnZXJDb250cm9sbGVyLFxuICAgIGZpbGVzQ29udHJvbGxlcixcbiAgICB1c2VyQ29udHJvbGxlcixcbiAgICBwdXNoQ29udHJvbGxlcixcbiAgICBoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCxcbiAgICBoYXNQdXNoU3VwcG9ydCxcbiAgICBwdXNoV29ya2VyLFxuICAgIHB1c2hDb250cm9sbGVyUXVldWUsXG4gICAgYW5hbHl0aWNzQ29udHJvbGxlcixcbiAgICBjYWNoZUNvbnRyb2xsZXIsXG4gICAgcGFyc2VHcmFwaFFMQ29udHJvbGxlcixcbiAgICBsaXZlUXVlcnlDb250cm9sbGVyLFxuICAgIGRhdGFiYXNlQ29udHJvbGxlcixcbiAgICBob29rc0NvbnRyb2xsZXIsXG4gICAgYXV0aERhdGFNYW5hZ2VyLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9nZ2VyQ29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zXG4pOiBMb2dnZXJDb250cm9sbGVyIHtcbiAgY29uc3Qge1xuICAgIGFwcElkLFxuICAgIGpzb25Mb2dzLFxuICAgIGxvZ3NGb2xkZXIsXG4gICAgdmVyYm9zZSxcbiAgICBsb2dMZXZlbCxcbiAgICBzaWxlbnQsXG4gICAgbG9nZ2VyQWRhcHRlcixcbiAgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGxvZ2dlck9wdGlvbnMgPSB7IGpzb25Mb2dzLCBsb2dzRm9sZGVyLCB2ZXJib3NlLCBsb2dMZXZlbCwgc2lsZW50IH07XG4gIGNvbnN0IGxvZ2dlckNvbnRyb2xsZXJBZGFwdGVyID0gbG9hZEFkYXB0ZXIoXG4gICAgbG9nZ2VyQWRhcHRlcixcbiAgICBXaW5zdG9uTG9nZ2VyQWRhcHRlcixcbiAgICBsb2dnZXJPcHRpb25zXG4gICk7XG4gIHJldHVybiBuZXcgTG9nZ2VyQ29udHJvbGxlcihsb2dnZXJDb250cm9sbGVyQWRhcHRlciwgYXBwSWQsIGxvZ2dlck9wdGlvbnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmlsZXNDb250cm9sbGVyKFxuICBvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnNcbik6IEZpbGVzQ29udHJvbGxlciB7XG4gIGNvbnN0IHtcbiAgICBhcHBJZCxcbiAgICBkYXRhYmFzZVVSSSxcbiAgICBmaWxlc0FkYXB0ZXIsXG4gICAgZGF0YWJhc2VBZGFwdGVyLFxuICAgIHByZXNlcnZlRmlsZU5hbWUsXG4gIH0gPSBvcHRpb25zO1xuICBpZiAoIWZpbGVzQWRhcHRlciAmJiBkYXRhYmFzZUFkYXB0ZXIpIHtcbiAgICB0aHJvdyAnV2hlbiB1c2luZyBhbiBleHBsaWNpdCBkYXRhYmFzZSBhZGFwdGVyLCB5b3UgbXVzdCBhbHNvIHVzZSBhbiBleHBsaWNpdCBmaWxlc0FkYXB0ZXIuJztcbiAgfVxuICBjb25zdCBmaWxlc0NvbnRyb2xsZXJBZGFwdGVyID0gbG9hZEFkYXB0ZXIoZmlsZXNBZGFwdGVyLCAoKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBHcmlkRlNCdWNrZXRBZGFwdGVyKGRhdGFiYXNlVVJJKTtcbiAgfSk7XG4gIHJldHVybiBuZXcgRmlsZXNDb250cm9sbGVyKGZpbGVzQ29udHJvbGxlckFkYXB0ZXIsIGFwcElkLCB7XG4gICAgcHJlc2VydmVGaWxlTmFtZSxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRVc2VyQ29udHJvbGxlcihvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpOiBVc2VyQ29udHJvbGxlciB7XG4gIGNvbnN0IHsgYXBwSWQsIGVtYWlsQWRhcHRlciwgdmVyaWZ5VXNlckVtYWlscyB9ID0gb3B0aW9ucztcbiAgY29uc3QgZW1haWxDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKGVtYWlsQWRhcHRlcik7XG4gIHJldHVybiBuZXcgVXNlckNvbnRyb2xsZXIoZW1haWxDb250cm9sbGVyQWRhcHRlciwgYXBwSWQsIHtcbiAgICB2ZXJpZnlVc2VyRW1haWxzLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENhY2hlQ29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zXG4pOiBDYWNoZUNvbnRyb2xsZXIge1xuICBjb25zdCB7IGFwcElkLCBjYWNoZUFkYXB0ZXIsIGNhY2hlVFRMLCBjYWNoZU1heFNpemUgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGNhY2hlQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihcbiAgICBjYWNoZUFkYXB0ZXIsXG4gICAgSW5NZW1vcnlDYWNoZUFkYXB0ZXIsXG4gICAgeyBhcHBJZDogYXBwSWQsIHR0bDogY2FjaGVUVEwsIG1heFNpemU6IGNhY2hlTWF4U2l6ZSB9XG4gICk7XG4gIHJldHVybiBuZXcgQ2FjaGVDb250cm9sbGVyKGNhY2hlQ29udHJvbGxlckFkYXB0ZXIsIGFwcElkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFBhcnNlR3JhcGhRTENvbnRyb2xsZXIoXG4gIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucyxcbiAgY29udHJvbGxlckRlcHNcbik6IFBhcnNlR3JhcGhRTENvbnRyb2xsZXIge1xuICByZXR1cm4gbmV3IFBhcnNlR3JhcGhRTENvbnRyb2xsZXIoe1xuICAgIG1vdW50R3JhcGhRTDogb3B0aW9ucy5tb3VudEdyYXBoUUwsXG4gICAgLi4uY29udHJvbGxlckRlcHMsXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QW5hbHl0aWNzQ29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zXG4pOiBBbmFseXRpY3NDb250cm9sbGVyIHtcbiAgY29uc3QgeyBhbmFseXRpY3NBZGFwdGVyIH0gPSBvcHRpb25zO1xuICBjb25zdCBhbmFseXRpY3NDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKFxuICAgIGFuYWx5dGljc0FkYXB0ZXIsXG4gICAgQW5hbHl0aWNzQWRhcHRlclxuICApO1xuICByZXR1cm4gbmV3IEFuYWx5dGljc0NvbnRyb2xsZXIoYW5hbHl0aWNzQ29udHJvbGxlckFkYXB0ZXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TGl2ZVF1ZXJ5Q29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zXG4pOiBMaXZlUXVlcnlDb250cm9sbGVyIHtcbiAgcmV0dXJuIG5ldyBMaXZlUXVlcnlDb250cm9sbGVyKG9wdGlvbnMubGl2ZVF1ZXJ5KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERhdGFiYXNlQ29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zLFxuICBjYWNoZUNvbnRyb2xsZXI6IENhY2hlQ29udHJvbGxlclxuKTogRGF0YWJhc2VDb250cm9sbGVyIHtcbiAgY29uc3Qge1xuICAgIGRhdGFiYXNlVVJJLFxuICAgIGRhdGFiYXNlT3B0aW9ucyxcbiAgICBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZCxcbiAgICBjb2xsZWN0aW9uUHJlZml4LFxuICAgIHNjaGVtYUNhY2hlVFRMLFxuICAgIGVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlLFxuICB9ID0gb3B0aW9ucztcbiAgbGV0IHsgZGF0YWJhc2VBZGFwdGVyIH0gPSBvcHRpb25zO1xuICBpZiAoXG4gICAgKGRhdGFiYXNlT3B0aW9ucyB8fFxuICAgICAgKGRhdGFiYXNlVVJJICYmIGRhdGFiYXNlVVJJICE9PSBkZWZhdWx0cy5kYXRhYmFzZVVSSSkgfHxcbiAgICAgIGNvbGxlY3Rpb25QcmVmaXggIT09IGRlZmF1bHRzLmNvbGxlY3Rpb25QcmVmaXgpICYmXG4gICAgZGF0YWJhc2VBZGFwdGVyXG4gICkge1xuICAgIHRocm93ICdZb3UgY2Fubm90IHNwZWNpZnkgYm90aCBhIGRhdGFiYXNlQWRhcHRlciBhbmQgYSBkYXRhYmFzZVVSSS9kYXRhYmFzZU9wdGlvbnMvY29sbGVjdGlvblByZWZpeC4nO1xuICB9IGVsc2UgaWYgKCFkYXRhYmFzZUFkYXB0ZXIpIHtcbiAgICBkYXRhYmFzZUFkYXB0ZXIgPSBnZXREYXRhYmFzZUFkYXB0ZXIoXG4gICAgICBkYXRhYmFzZVVSSSxcbiAgICAgIGNvbGxlY3Rpb25QcmVmaXgsXG4gICAgICBkYXRhYmFzZU9wdGlvbnNcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIGRhdGFiYXNlQWRhcHRlciA9IGxvYWRBZGFwdGVyKGRhdGFiYXNlQWRhcHRlcik7XG4gIH1cbiAgcmV0dXJuIG5ldyBEYXRhYmFzZUNvbnRyb2xsZXIoXG4gICAgZGF0YWJhc2VBZGFwdGVyLFxuICAgIG5ldyBTY2hlbWFDYWNoZShjYWNoZUNvbnRyb2xsZXIsIHNjaGVtYUNhY2hlVFRMLCBlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSksXG4gICAgc2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmRcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEhvb2tzQ29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zLFxuICBkYXRhYmFzZUNvbnRyb2xsZXI6IERhdGFiYXNlQ29udHJvbGxlclxuKTogSG9va3NDb250cm9sbGVyIHtcbiAgY29uc3QgeyBhcHBJZCwgd2ViaG9va0tleSB9ID0gb3B0aW9ucztcbiAgcmV0dXJuIG5ldyBIb29rc0NvbnRyb2xsZXIoYXBwSWQsIGRhdGFiYXNlQ29udHJvbGxlciwgd2ViaG9va0tleSk7XG59XG5cbmludGVyZmFjZSBQdXNoQ29udHJvbGxpbmcge1xuICBwdXNoQ29udHJvbGxlcjogUHVzaENvbnRyb2xsZXI7XG4gIGhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0OiBib29sZWFuO1xuICBwdXNoQ29udHJvbGxlclF1ZXVlOiBQdXNoUXVldWU7XG4gIHB1c2hXb3JrZXI6IFB1c2hXb3JrZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQdXNoQ29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zXG4pOiBQdXNoQ29udHJvbGxpbmcge1xuICBjb25zdCB7IHNjaGVkdWxlZFB1c2gsIHB1c2ggfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgcHVzaE9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBwdXNoKTtcbiAgY29uc3QgcHVzaFF1ZXVlT3B0aW9ucyA9IHB1c2hPcHRpb25zLnF1ZXVlT3B0aW9ucyB8fCB7fTtcbiAgaWYgKHB1c2hPcHRpb25zLnF1ZXVlT3B0aW9ucykge1xuICAgIGRlbGV0ZSBwdXNoT3B0aW9ucy5xdWV1ZU9wdGlvbnM7XG4gIH1cblxuICAvLyBQYXNzIHRoZSBwdXNoIG9wdGlvbnMgdG9vIGFzIGl0IHdvcmtzIHdpdGggdGhlIGRlZmF1bHRcbiAgY29uc3QgcHVzaEFkYXB0ZXIgPSBsb2FkQWRhcHRlcihcbiAgICBwdXNoT3B0aW9ucyAmJiBwdXNoT3B0aW9ucy5hZGFwdGVyLFxuICAgIFBhcnNlUHVzaEFkYXB0ZXIsXG4gICAgcHVzaE9wdGlvbnNcbiAgKTtcbiAgLy8gV2UgcGFzcyB0aGUgb3B0aW9ucyBhbmQgdGhlIGJhc2UgY2xhc3MgZm9yIHRoZSBhZGF0cGVyLFxuICAvLyBOb3RlIHRoYXQgcGFzc2luZyBhbiBpbnN0YW5jZSB3b3VsZCB3b3JrIHRvb1xuICBjb25zdCBwdXNoQ29udHJvbGxlciA9IG5ldyBQdXNoQ29udHJvbGxlcigpO1xuICBjb25zdCBoYXNQdXNoU3VwcG9ydCA9ICEhKHB1c2hBZGFwdGVyICYmIHB1c2gpO1xuICBjb25zdCBoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCA9IGhhc1B1c2hTdXBwb3J0ICYmIHNjaGVkdWxlZFB1c2ggPT09IHRydWU7XG5cbiAgY29uc3QgeyBkaXNhYmxlUHVzaFdvcmtlciB9ID0gcHVzaFF1ZXVlT3B0aW9ucztcblxuICBjb25zdCBwdXNoQ29udHJvbGxlclF1ZXVlID0gbmV3IFB1c2hRdWV1ZShwdXNoUXVldWVPcHRpb25zKTtcbiAgbGV0IHB1c2hXb3JrZXI7XG4gIGlmICghZGlzYWJsZVB1c2hXb3JrZXIpIHtcbiAgICBwdXNoV29ya2VyID0gbmV3IFB1c2hXb3JrZXIocHVzaEFkYXB0ZXIsIHB1c2hRdWV1ZU9wdGlvbnMpO1xuICB9XG4gIHJldHVybiB7XG4gICAgcHVzaENvbnRyb2xsZXIsXG4gICAgaGFzUHVzaFN1cHBvcnQsXG4gICAgaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQsXG4gICAgcHVzaENvbnRyb2xsZXJRdWV1ZSxcbiAgICBwdXNoV29ya2VyLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QXV0aERhdGFNYW5hZ2VyKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICBjb25zdCB7IGF1dGgsIGVuYWJsZUFub255bW91c1VzZXJzIH0gPSBvcHRpb25zO1xuICByZXR1cm4gYXV0aERhdGFNYW5hZ2VyKGF1dGgsIGVuYWJsZUFub255bW91c1VzZXJzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERhdGFiYXNlQWRhcHRlcihcbiAgZGF0YWJhc2VVUkksXG4gIGNvbGxlY3Rpb25QcmVmaXgsXG4gIGRhdGFiYXNlT3B0aW9uc1xuKSB7XG4gIGxldCBwcm90b2NvbDtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWRVUkkgPSB1cmwucGFyc2UoZGF0YWJhc2VVUkkpO1xuICAgIHByb3RvY29sID0gcGFyc2VkVVJJLnByb3RvY29sID8gcGFyc2VkVVJJLnByb3RvY29sLnRvTG93ZXJDYXNlKCkgOiBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLyogKi9cbiAgfVxuICBzd2l0Y2ggKHByb3RvY29sKSB7XG4gICAgY2FzZSAncG9zdGdyZXM6JzpcbiAgICAgIHJldHVybiBuZXcgUG9zdGdyZXNTdG9yYWdlQWRhcHRlcih7XG4gICAgICAgIHVyaTogZGF0YWJhc2VVUkksXG4gICAgICAgIGNvbGxlY3Rpb25QcmVmaXgsXG4gICAgICAgIGRhdGFiYXNlT3B0aW9ucyxcbiAgICAgIH0pO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbmV3IE1vbmdvU3RvcmFnZUFkYXB0ZXIoe1xuICAgICAgICB1cmk6IGRhdGFiYXNlVVJJLFxuICAgICAgICBjb2xsZWN0aW9uUHJlZml4LFxuICAgICAgICBtb25nb09wdGlvbnM6IGRhdGFiYXNlT3B0aW9ucyxcbiAgICAgIH0pO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/types.js b/lib/Controllers/types.js new file mode 100644 index 0000000000..4310b4ffac --- /dev/null +++ b/lib/Controllers/types.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbXX0= \ No newline at end of file diff --git a/lib/FilesController.js b/lib/FilesController.js new file mode 100644 index 0000000000..a4836e6acb --- /dev/null +++ b/lib/FilesController.js @@ -0,0 +1,165 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = exports.FilesController = void 0; + +var _cryptoUtils = require("../cryptoUtils"); + +var _AdaptableController2 = _interopRequireDefault(require("./AdaptableController")); + +var _FilesAdapter = _interopRequireWildcard(require("../Adapters/Files/FilesAdapter")); + +var _path = _interopRequireDefault(require("path")); + +var _mime = _interopRequireDefault(require("mime")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +var legacyFilesRegex = new RegExp('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}-.*'); + +var FilesController = +/*#__PURE__*/ +function (_AdaptableController) { + _inherits(FilesController, _AdaptableController); + + function FilesController() { + _classCallCheck(this, FilesController); + + return _possibleConstructorReturn(this, _getPrototypeOf(FilesController).apply(this, arguments)); + } + + _createClass(FilesController, [{ + key: "getFileData", + value: function getFileData(config, filename) { + return this.adapter.getFileData(filename); + } + }, { + key: "createFile", + value: function createFile(config, filename, data, contentType) { + var extname = _path["default"].extname(filename); + + var hasExtension = extname.length > 0; + + if (!hasExtension && contentType && _mime["default"].getExtension(contentType)) { + filename = filename + '.' + _mime["default"].getExtension(contentType); + } else if (hasExtension && !contentType) { + contentType = _mime["default"].getType(filename); + } + + if (!this.options.preserveFileName) { + filename = (0, _cryptoUtils.randomHexString)(32) + '_' + filename; + } + + var location = this.adapter.getFileLocation(config, filename); + return this.adapter.createFile(filename, data, contentType).then(function () { + return Promise.resolve({ + url: location, + name: filename + }); + }); + } + }, { + key: "deleteFile", + value: function deleteFile(config, filename) { + return this.adapter.deleteFile(filename); + } + /** + * Find file references in REST-format object and adds the url key + * with the current mount point and app id. + * Object may be a single object or list of REST-format objects. + */ + + }, { + key: "expandFilesInObject", + value: function expandFilesInObject(config, object) { + var _this = this; + + if (object instanceof Array) { + object.map(function (obj) { + return _this.expandFilesInObject(config, obj); + }); + return; + } + + if (_typeof(object) !== 'object') { + return; + } + + for (var key in object) { + var fileObject = object[key]; + + if (fileObject && fileObject['__type'] === 'File') { + if (fileObject['url']) { + continue; + } + + var filename = fileObject['name']; // all filenames starting with "tfss-" should be from files.parsetfss.com + // all filenames starting with a "-" seperated UUID should be from files.parse.com + // all other filenames have been migrated or created from Parse Server + + if (config.fileKey === undefined) { + fileObject['url'] = this.adapter.getFileLocation(config, filename); + } else { + if (filename.indexOf('tfss-') === 0) { + fileObject['url'] = 'http://files.parsetfss.com/' + config.fileKey + '/' + encodeURIComponent(filename); + } else if (legacyFilesRegex.test(filename)) { + fileObject['url'] = 'http://files.parse.com/' + config.fileKey + '/' + encodeURIComponent(filename); + } else { + fileObject['url'] = this.adapter.getFileLocation(config, filename); + } + } + } + } + } + }, { + key: "expectedAdapterType", + value: function expectedAdapterType() { + return _FilesAdapter.FilesAdapter; + } + }, { + key: "handleFileStream", + value: function handleFileStream(config, filename, req, res, contentType) { + return this.adapter.handleFileStream(filename, req, res, contentType); + } + }, { + key: "validateFilename", + value: function validateFilename(filename) { + if (typeof this.adapter.validateFilename === 'function') { + return this.adapter.validateFilename(filename); + } + + return (0, _FilesAdapter["default"])(filename); + } + }]); + + return FilesController; +}(_AdaptableController2["default"]); + +exports.FilesController = FilesController; +var _default = FilesController; +exports["default"] = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db250cm9sbGVycy9GaWxlc0NvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsibGVnYWN5RmlsZXNSZWdleCIsIlJlZ0V4cCIsIkZpbGVzQ29udHJvbGxlciIsImNvbmZpZyIsImZpbGVuYW1lIiwiYWRhcHRlciIsImdldEZpbGVEYXRhIiwiZGF0YSIsImNvbnRlbnRUeXBlIiwiZXh0bmFtZSIsInBhdGgiLCJoYXNFeHRlbnNpb24iLCJsZW5ndGgiLCJtaW1lIiwiZ2V0RXh0ZW5zaW9uIiwiZ2V0VHlwZSIsIm9wdGlvbnMiLCJwcmVzZXJ2ZUZpbGVOYW1lIiwibG9jYXRpb24iLCJnZXRGaWxlTG9jYXRpb24iLCJjcmVhdGVGaWxlIiwidGhlbiIsIlByb21pc2UiLCJyZXNvbHZlIiwidXJsIiwibmFtZSIsImRlbGV0ZUZpbGUiLCJvYmplY3QiLCJBcnJheSIsIm1hcCIsIm9iaiIsImV4cGFuZEZpbGVzSW5PYmplY3QiLCJrZXkiLCJmaWxlT2JqZWN0IiwiZmlsZUtleSIsInVuZGVmaW5lZCIsImluZGV4T2YiLCJlbmNvZGVVUklDb21wb25lbnQiLCJ0ZXN0IiwiRmlsZXNBZGFwdGVyIiwicmVxIiwicmVzIiwiaGFuZGxlRmlsZVN0cmVhbSIsInZhbGlkYXRlRmlsZW5hbWUiLCJBZGFwdGFibGVDb250cm9sbGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsSUFBTUEsZ0JBQWdCLEdBQUcsSUFBSUMsTUFBSixDQUN2QixpRkFEdUIsQ0FBekI7O0lBSWFDLGU7Ozs7Ozs7Ozs7Ozs7Z0NBQ0NDLE0sRUFBUUMsUSxFQUFVO0FBQzVCLGFBQU8sS0FBS0MsT0FBTCxDQUFhQyxXQUFiLENBQXlCRixRQUF6QixDQUFQO0FBQ0Q7OzsrQkFFVUQsTSxFQUFRQyxRLEVBQVVHLEksRUFBTUMsVyxFQUFhO0FBQzlDLFVBQU1DLE9BQU8sR0FBR0MsaUJBQUtELE9BQUws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QSxHQUdBRyxrQkFBa0IsQ0FBQ2pDLFFBQUQsQ0FKcEI7QUFLRCxhQU5NLE1BTUE7QUFDTDZCLGNBQUFBLFVBQVUsQ0FBQyxLQUFELENBQVYsR0FBb0IsS0FBSzVCLE9BQUwsQ0FBYWMsZUFBYixDQUE2QmhCLE1BQTdCLEVBQXFDQyxRQUFyQyxDQUFwQjtBQUNEO0FBQ0Y7QUFDRjtBQUNGO0FBQ0Y7OzswQ0FFcUI7QUFDcEIsYUFBT21DLDBCQUFQO0FBQ0Q7OztxQ0FFZ0JwQyxNLEVBQVFDLFEsRUFBVW9DLEcsRUFBS0MsRyxFQUFLakMsVyxFQUFhO0FBQ3hELGFBQU8sS0FBS0gsT0FBTCxDQUFhcUMsZ0JBQWIsQ0FBOEJ0QyxRQUE5QixFQUF3Q29DLEdBQXhDLEVBQTZDQyxHQUE3QyxFQUFrRGpDLFdBQWxELENBQVA7QUFDRDs7O3FDQUVnQkosUSxFQUFVO0FBQ3pCLFVBQUksT0FBTyxLQUFLQyxPQUFMLENBQWFzQyxnQkFBcEIsS0FBeUMsVUFBN0MsRUFBeUQ7QUFDdkQsZUFBTyxLQUFLdEMsT0FBTCxDQUFhc0MsZ0JBQWIsQ0FBOEJ2QyxRQUE5QixDQUFQO0FBQ0Q7O0FBQ0QsYUFBTyw4QkFBaUJBLFFBQWpCLENBQVA7QUFDRDs7OztFQTVGa0N3QyxnQzs7O2VBK0Z0QjFDLGUiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBGaWxlc0NvbnRyb2xsZXIuanNcbmltcG9ydCB7IHJhbmRvbUhleFN0cmluZyB9IGZyb20gJy4uL2NyeXB0b1V0aWxzJztcbmltcG9ydCBBZGFwdGFibGVDb250cm9sbGVyIGZyb20gJy4vQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgdmFsaWRhdGVGaWxlbmFtZSwgeyBGaWxlc0FkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9GaWxlcy9GaWxlc0FkYXB0ZXInO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgbWltZSBmcm9tICdtaW1lJztcblxuY29uc3QgbGVnYWN5RmlsZXNSZWdleCA9IG5ldyBSZWdFeHAoXG4gICdeWzAtOWEtZkEtRl17OH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17MTJ9LS4qJ1xuKTtcblxuZXhwb3J0IGNsYXNzIEZpbGVzQ29udHJvbGxlciBleHRlbmRzIEFkYXB0YWJsZUNvbnRyb2xsZXIge1xuICBnZXRGaWxlRGF0YShjb25maWcsIGZpbGVuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5nZXRGaWxlRGF0YShmaWxlbmFtZSk7XG4gIH1cblxuICBjcmVhdGVGaWxlKGNvbmZpZywgZmlsZW5hbWUsIGRhdGEsIGNvbnRlbnRUeXBlKSB7XG4gICAgY29uc3QgZXh0bmFtZSA9IHBhdGguZXh0bmFtZShmaWxlbmFtZSk7XG5cbiAgICBjb25zdCBoYXNFeHRlbnNpb24gPSBleHRuYW1lLmxlbmd0aCA+IDA7XG5cbiAgICBpZiAoIWhhc0V4dGVuc2lvbiAmJiBjb250ZW50VHlwZSAmJiBtaW1lLmdldEV4dGVuc2lvbihjb250ZW50VHlwZSkpIHtcbiAgICAgIGZpbGVuYW1lID0gZmlsZW5hbWUgKyAnLicgKyBtaW1lLmdldEV4dGVuc2lvbihjb250ZW50VHlwZSk7XG4gICAgfSBlbHNlIGlmIChoYXNFeHRlbnNpb24gJiYgIWNvbnRlbnRUeXBlKSB7XG4gICAgICBjb250ZW50VHlwZSA9IG1pbWUuZ2V0VHlwZShmaWxlbmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMucHJlc2VydmVGaWxlTmFtZSkge1xuICAgICAgZmlsZW5hbWUgPSByYW5kb21IZXhTdHJpbmcoMzIpICsgJ18nICsgZmlsZW5hbWU7XG4gICAgfVxuXG4gICAgY29uc3QgbG9jYXRpb24gPSB0aGlzLmFkYXB0ZXIuZ2V0RmlsZUxvY2F0aW9uKGNvbmZpZywgZmlsZW5hbWUpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuY3JlYXRlRmlsZShmaWxlbmFtZSwgZGF0YSwgY29udGVudFR5cGUpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgIHVybDogbG9jYXRpb24sXG4gICAgICAgIG5hbWU6IGZpbGVuYW1lLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBkZWxldGVGaWxlKGNvbmZpZywgZmlsZW5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmRlbGV0ZUZpbGUoZmlsZW5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmQgZmlsZSByZWZlcmVuY2VzIGluIFJFU1QtZm9ybWF0IG9iamVjdCBhbmQgYWRkcyB0aGUgdXJsIGtleVxuICAgKiB3aXRoIHRoZSBjdXJyZW50IG1vdW50IHBvaW50IGFuZCBhcHAgaWQuXG4gICAqIE9iamVjdCBtYXkgYmUgYSBzaW5nbGUgb2JqZWN0IG9yIGxpc3Qgb2YgUkVTVC1mb3JtYXQgb2JqZWN0cy5cbiAgICovXG4gIGV4cGFuZEZpbGVzSW5PYmplY3QoY29uZmlnLCBvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgIG9iamVjdC5tYXAob2JqID0+IHRoaXMuZXhwYW5kRmlsZXNJbk9iamVjdChjb25maWcsIG9iaikpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBjb25zdCBmaWxlT2JqZWN0ID0gb2JqZWN0W2tleV07XG4gICAgICBpZiAoZmlsZU9iamVjdCAmJiBmaWxlT2JqZWN0WydfX3R5cGUnXSA9PT0gJ0ZpbGUnKSB7XG4gICAgICAgIGlmIChmaWxlT2JqZWN0Wyd1cmwnXSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZpbGVuYW1lID0gZmlsZU9iamVjdFsnbmFtZSddO1xuICAgICAgICAvLyBhbGwgZmlsZW5hbWVzIHN0YXJ0aW5nIHdpdGggXCJ0ZnNzLVwiIHNob3VsZCBiZSBmcm9tIGZpbGVzLnBhcnNldGZzcy5jb21cbiAgICAgICAgLy8gYWxsIGZpbGVuYW1lcyBzdGFydGluZyB3aXRoIGEgXCItXCIgc2VwZXJhdGVkIFVVSUQgc2hvdWxkIGJlIGZyb20gZmlsZXMucGFyc2UuY29tXG4gICAgICAgIC8vIGFsbCBvdGhlciBmaWxlbmFtZXMgaGF2ZSBiZWVuIG1pZ3JhdGVkIG9yIGNyZWF0ZWQgZnJvbSBQYXJzZSBTZXJ2ZXJcbiAgICAgICAgaWYgKGNvbmZpZy5maWxlS2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBmaWxlT2JqZWN0Wyd1cmwnXSA9IHRoaXMuYWRhcHRlci5nZXRGaWxlTG9jYXRpb24oY29uZmlnLCBmaWxlbmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGZpbGVuYW1lLmluZGV4T2YoJ3Rmc3MtJykgPT09IDApIHtcbiAgICAgICAgICAgIGZpbGVPYmplY3RbJ3VybCddID1cbiAgICAgICAgICAgICAgJ2h0dHA6Ly9maWxlcy5wYXJzZXRmc3MuY29tLycgK1xuICAgICAgICAgICAgICBjb25maWcuZmlsZUtleSArXG4gICAgICAgICAgICAgICcvJyArXG4gICAgICAgICAgICAgIGVuY29kZVVSSUNvbXBvbmVudChmaWxlbmFtZSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChsZWdhY3lGaWxlc1JlZ2V4LnRlc3QoZmlsZW5hbWUpKSB7XG4gICAgICAgICAgICBmaWxlT2JqZWN0Wyd1cmwnXSA9XG4gICAgICAgICAgICAgICdodHRwOi8vZmlsZXMucGFyc2UuY29tLycgK1xuICAgICAgICAgICAgICBjb25maWcuZmlsZUtleSArXG4gICAgICAgICAgICAgICcvJyArXG4gICAgICAgICAgICAgIGVuY29kZVVSSUNvbXBvbmVudChmaWxlbmFtZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVPYmplY3RbJ3VybCddID0gdGhpcy5hZGFwdGVyLmdldEZpbGVMb2NhdGlvbihjb25maWcsIGZpbGVuYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHJldHVybiBGaWxlc0FkYXB0ZXI7XG4gIH1cblxuICBoYW5kbGVGaWxlU3RyZWFtKGNvbmZpZywgZmlsZW5hbWUsIHJlcSwgcmVzLCBjb250ZW50VHlwZSkge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuaGFuZGxlRmlsZVN0cmVhbShmaWxlbmFtZSwgcmVxLCByZXMsIGNvbnRlbnRUeXBlKTtcbiAgfVxuXG4gIHZhbGlkYXRlRmlsZW5hbWUoZmlsZW5hbWUpIHtcbiAgICBpZiAodHlwZW9mIHRoaXMuYWRhcHRlci52YWxpZGF0ZUZpbGVuYW1lID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnZhbGlkYXRlRmlsZW5hbWUoZmlsZW5hbWUpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsaWRhdGVGaWxlbmFtZShmaWxlbmFtZSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRmlsZXNDb250cm9sbGVyO1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/ParseGraphQLSchema.js b/lib/GraphQL/ParseGraphQLSchema.js new file mode 100644 index 0000000000..b2faaea8bd --- /dev/null +++ b/lib/GraphQL/ParseGraphQLSchema.js @@ -0,0 +1,378 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseGraphQLSchema = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _graphql = require("graphql"); + +var _graphqlTools = require("graphql-tools"); + +var _requiredParameter = _interopRequireDefault(require("../requiredParameter")); + +var defaultGraphQLTypes = _interopRequireWildcard(require("./loaders/defaultGraphQLTypes")); + +var parseClassTypes = _interopRequireWildcard(require("./loaders/parseClassTypes")); + +var parseClassQueries = _interopRequireWildcard(require("./loaders/parseClassQueries")); + +var parseClassMutations = _interopRequireWildcard(require("./loaders/parseClassMutations")); + +var defaultGraphQLQueries = _interopRequireWildcard(require("./loaders/defaultGraphQLQueries")); + +var defaultGraphQLMutations = _interopRequireWildcard(require("./loaders/defaultGraphQLMutations")); + +var _ParseGraphQLController = _interopRequireWildcard(require("../Controllers/ParseGraphQLController")); + +var _DatabaseController = _interopRequireDefault(require("../Controllers/DatabaseController")); + +var _parseGraphQLUtils = require("./parseGraphQLUtils"); + +var schemaDirectives = _interopRequireWildcard(require("./loaders/schemaDirectives")); + +var schemaTypes = _interopRequireWildcard(require("./loaders/schemaTypes")); + +var _triggers = require("../triggers"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const RESERVED_GRAPHQL_TYPE_NAMES = ['String', 'Boolean', 'Int', 'Float', 'ID', 'ArrayResult', 'Query', 'Mutation', 'Subscription', 'Viewer', 'SignUpFieldsInput', 'LogInFieldsInput', 'CloudCodeFunction']; +const RESERVED_GRAPHQL_QUERY_NAMES = ['health', 'viewer', 'class', 'classes']; +const RESERVED_GRAPHQL_MUTATION_NAMES = ['signUp', 'logIn', 'logOut', 'createFile', 'callCloudCode', 'createClass', 'updateClass', 'deleteClass']; + +class ParseGraphQLSchema { + constructor(params = {}) { + this.parseGraphQLController = params.parseGraphQLController || (0, _requiredParameter.default)('You must provide a parseGraphQLController instance!'); + this.databaseController = params.databaseController || (0, _requiredParameter.default)('You must provide a databaseController instance!'); + this.log = params.log || (0, _requiredParameter.default)('You must provide a log instance!'); + this.graphQLCustomTypeDefs = params.graphQLCustomTypeDefs; + this.appId = params.appId || (0, _requiredParameter.default)('You must provide the appId!'); + } + + async load() { + const { + parseGraphQLConfig + } = await this._initializeSchemaAndConfig(); + const parseClasses = await this._getClassesForSchema(parseGraphQLConfig); + const parseClassesString = JSON.stringify(parseClasses); + const functionNames = await this._getFunctionNames(); + const functionNamesString = JSON.stringify(functionNames); + + if (this.graphQLSchema && !this._hasSchemaInputChanged({ + parseClasses, + parseClassesString, + parseGraphQLConfig, + functionNamesString + })) { + return this.graphQLSchema; + } + + this.parseClasses = parseClasses; + this.parseClassesString = parseClassesString; + this.parseGraphQLConfig = parseGraphQLConfig; + this.functionNames = functionNames; + this.functionNamesString = functionNamesString; + this.parseClassTypes = {}; + this.viewerType = null; + this.graphQLAutoSchema = null; + this.graphQLSchema = null; + this.graphQLTypes = []; + this.graphQLQueries = {}; + this.graphQLMutations = {}; + this.graphQLSubscriptions = {}; + this.graphQLSchemaDirectivesDefinitions = null; + this.graphQLSchemaDirectives = {}; + defaultGraphQLTypes.load(this); + schemaTypes.load(this); + + this._getParseClassesWithConfig(parseClasses, parseGraphQLConfig).forEach(([parseClass, parseClassConfig]) => { + parseClassTypes.load(this, parseClass, parseClassConfig); + parseClassQueries.load(this, parseClass, parseClassConfig); + parseClassMutations.load(this, parseClass, parseClassConfig); + }); + + defaultGraphQLTypes.loadArrayResult(this, parseClasses); + defaultGraphQLQueries.load(this); + defaultGraphQLMutations.load(this); + let graphQLQuery = undefined; + + if (Object.keys(this.graphQLQueries).length > 0) { + graphQLQuery = new _graphql.GraphQLObjectType({ + name: 'Query', + description: 'Query is the top level type for queries.', + fields: this.graphQLQueries + }); + this.addGraphQLType(graphQLQuery, true, true); + } + + let graphQLMutation = undefined; + + if (Object.keys(this.graphQLMutations).length > 0) { + graphQLMutation = new _graphql.GraphQLObjectType({ + name: 'Mutation', + description: 'Mutation is the top level type for mutations.', + fields: this.graphQLMutations + }); + this.addGraphQLType(graphQLMutation, true, true); + } + + let graphQLSubscription = undefined; + + if (Object.keys(this.graphQLSubscriptions).length > 0) { + graphQLSubscription = new _graphql.GraphQLObjectType({ + name: 'Subscription', + description: 'Subscription is the top level type for subscriptions.', + fields: this.graphQLSubscriptions + }); + this.addGraphQLType(graphQLSubscription, true, true); + } + + this.graphQLAutoSchema = new _graphql.GraphQLSchema({ + types: this.graphQLTypes, + query: graphQLQuery, + mutation: graphQLMutation, + subscription: graphQLSubscription + }); + + if (this.graphQLCustomTypeDefs) { + schemaDirectives.load(this); + this.graphQLSchema = (0, _graphqlTools.mergeSchemas)({ + schemas: [this.graphQLSchemaDirectivesDefinitions, this.graphQLAutoSchema, this.graphQLCustomTypeDefs], + mergeDirectives: true + }); + const graphQLSchemaTypeMap = this.graphQLSchema.getTypeMap(); + Object.keys(graphQLSchemaTypeMap).forEach(graphQLSchemaTypeName => { + const graphQLSchemaType = graphQLSchemaTypeMap[graphQLSchemaTypeName]; + + if (typeof graphQLSchemaType.getFields === 'function') { + const graphQLCustomTypeDef = this.graphQLCustomTypeDefs.definitions.find(definition => definition.name.value === graphQLSchemaTypeName); + + if (graphQLCustomTypeDef) { + const graphQLSchemaTypeFieldMap = graphQLSchemaType.getFields(); + Object.keys(graphQLSchemaTypeFieldMap).forEach(graphQLSchemaTypeFieldName => { + const graphQLSchemaTypeField = graphQLSchemaTypeFieldMap[graphQLSchemaTypeFieldName]; + + if (!graphQLSchemaTypeField.astNode) { + const astNode = graphQLCustomTypeDef.fields.find(field => field.name.value === graphQLSchemaTypeFieldName); + + if (astNode) { + graphQLSchemaTypeField.astNode = astNode; + } + } + }); + } + } + }); + + _graphqlTools.SchemaDirectiveVisitor.visitSchemaDirectives(this.graphQLSchema, this.graphQLSchemaDirectives); + } else { + this.graphQLSchema = this.graphQLAutoSchema; + } + + return this.graphQLSchema; + } + + addGraphQLType(type, throwError = false, ignoreReserved = false) { + if (!ignoreReserved && RESERVED_GRAPHQL_TYPE_NAMES.includes(type.name) || this.graphQLTypes.find(existingType => existingType.name === type.name)) { + const message = `Type ${type.name} could not be added to the auto schema because it collided with an existing type.`; + + if (throwError) { + throw new Error(message); + } + + this.log.warn(message); + return undefined; + } + + this.graphQLTypes.push(type); + return type; + } + + addGraphQLQuery(fieldName, field, throwError = false, ignoreReserved = false) { + if (!ignoreReserved && RESERVED_GRAPHQL_QUERY_NAMES.includes(fieldName) || this.graphQLQueries[fieldName]) { + const message = `Query ${fieldName} could not be added to the auto schema because it collided with an existing field.`; + + if (throwError) { + throw new Error(message); + } + + this.log.warn(message); + return undefined; + } + + this.graphQLQueries[fieldName] = field; + return field; + } + + addGraphQLMutation(fieldName, field, throwError = false, ignoreReserved = false) { + if (!ignoreReserved && RESERVED_GRAPHQL_MUTATION_NAMES.includes(fieldName) || this.graphQLMutations[fieldName]) { + const message = `Mutation ${fieldName} could not be added to the auto schema because it collided with an existing field.`; + + if (throwError) { + throw new Error(message); + } + + this.log.warn(message); + return undefined; + } + + this.graphQLMutations[fieldName] = field; + return field; + } + + handleError(error) { + if (error instanceof _node.default.Error) { + this.log.error('Parse error: ', error); + } else { + this.log.error('Uncaught internal server error.', error, error.stack); + } + + throw (0, _parseGraphQLUtils.toGraphQLError)(error); + } + + async _initializeSchemaAndConfig() { + const [schemaController, parseGraphQLConfig] = await Promise.all([this.databaseController.loadSchema(), this.parseGraphQLController.getGraphQLConfig()]); + this.schemaController = schemaController; + return { + parseGraphQLConfig + }; + } + /** + * Gets all classes found by the `schemaController` + * minus those filtered out by the app's parseGraphQLConfig. + */ + + + async _getClassesForSchema(parseGraphQLConfig) { + const { + enabledForClasses, + disabledForClasses + } = parseGraphQLConfig; + const allClasses = await this.schemaController.getAllClasses(); + + if (Array.isArray(enabledForClasses) || Array.isArray(disabledForClasses)) { + let includedClasses = allClasses; + + if (enabledForClasses) { + includedClasses = allClasses.filter(clazz => { + return enabledForClasses.includes(clazz.className); + }); + } + + if (disabledForClasses) { + // Classes included in `enabledForClasses` that + // are also present in `disabledForClasses` will + // still be filtered out + includedClasses = includedClasses.filter(clazz => { + return !disabledForClasses.includes(clazz.className); + }); + } + + this.isUsersClassDisabled = !includedClasses.some(clazz => { + return clazz.className === '_User'; + }); + return includedClasses; + } else { + return allClasses; + } + } + /** + * This method returns a list of tuples + * that provide the parseClass along with + * its parseClassConfig where provided. + */ + + + _getParseClassesWithConfig(parseClasses, parseGraphQLConfig) { + const { + classConfigs + } = parseGraphQLConfig; // Make sures that the default classes and classes that + // starts with capitalized letter will be generated first. + + const sortClasses = (a, b) => { + a = a.className; + b = b.className; + + if (a[0] === '_') { + if (b[0] !== '_') { + return -1; + } + } + + if (b[0] === '_') { + if (a[0] !== '_') { + return 1; + } + } + + if (a === b) { + return 0; + } else if (a < b) { + return -1; + } else { + return 1; + } + }; + + return parseClasses.sort(sortClasses).map(parseClass => { + let parseClassConfig; + + if (classConfigs) { + parseClassConfig = classConfigs.find(c => c.className === parseClass.className); + } + + return [parseClass, parseClassConfig]; + }); + } + + async _getFunctionNames() { + return await (0, _triggers.getFunctionNames)(this.appId).filter(functionName => { + if (/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(functionName)) { + return true; + } else { + this.log.warn(`Function ${functionName} could not be added to the auto schema because GraphQL names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/.`); + return false; + } + }); + } + /** + * Checks for changes to the parseClasses + * objects (i.e. database schema) or to + * the parseGraphQLConfig object. If no + * changes are found, return true; + */ + + + _hasSchemaInputChanged(params) { + const { + parseClasses, + parseClassesString, + parseGraphQLConfig, + functionNamesString + } = params; + + if (JSON.stringify(this.parseGraphQLConfig) === JSON.stringify(parseGraphQLConfig) && this.functionNamesString === functionNamesString) { + if (this.parseClasses === parseClasses) { + return false; + } + + if (this.parseClassesString === parseClassesString) { + this.parseClasses = parseClasses; + return false; + } + } + + return true; + } + +} + +exports.ParseGraphQLSchema = ParseGraphQLSchema; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HcmFwaFFML1BhcnNlR3JhcGhRTFNjaGVtYS5qcyJdLCJuYW1lcyI6WyJSRVNFUlZFRF9HUkFQSFFMX1RZUEVfTkFNRVMiLCJSRVNFUlZFRF9HUkFQSFFMX1FVRVJZX05BTUVTIiwiUkVTRVJWRURfR1JBUEhRTF9NVVRBVElPTl9OQU1FUyIsIlBhcnNlR3JhcGhRTFNjaGVtYSIsImNvbnN0cnVjdG9yIiwicGFyYW1zIiwicGFyc2VHcmFwaFFMQ29udHJvbGxlciIsImRhdGFiYXNlQ29udHJvbGxlciIsImxvZyIsImdyYXBoUUxDdXN0b21UeXBlRGVmcyIsImFwcElkIiwibG9hZCIsInBhcnNlR3JhcGhRTENvbmZpZyIsIl9pbml0aWFsaXplU2NoZW1hQW5kQ29uZmlnIiwicGFyc2VDbGFzc2VzIiwiX2dldENsYXNzZXNGb3JTY2hlbWEiLCJwYXJzZUNsYXNzZXNTdHJpbmciLCJKU09OIiwic3RyaW5naWZ5IiwiZnVuY3Rpb25OYW1lcyIsIl9nZXRGdW5jdGlvbk5hbWVzIiwiZnVuY3Rpb25OYW1lc1N0cmluZyIsImdyYXBoUUxTY2hlbWEiLCJfaGFzU2NoZW1hSW5wdXRDaGFuZ2VkIiwicGFyc2VDbGFzc1R5cGVzIiwidmlld2VyVHlwZSIsImdyYXBoUUxBdXRvU2NoZW1hIiwiZ3JhcGhRTFR5cGVzIiwiZ3JhcGhRTFF1ZXJpZXMiLCJncmFwaFFMTXV0YXRpb25zIiwiZ3JhcGhRTFN1YnNjcmlwdGlvbnMiLCJncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zIiwiZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXMiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwic2NoZW1hVHlwZXMiLCJfZ2V0UGFyc2VDbGFzc2VzV2l0aENvbmZpZyIsImZvckVhY2giLCJwYXJzZUNsYXNzIiwicGFyc2VDbGFzc0NvbmZpZyIsInBhcnNlQ2xhc3NRdWVyaWVzIiwicGFyc2VDbGFzc011dGF0aW9ucyIsImxvYWRBcnJheVJlc3VsdCIsImRlZmF1bHRHcmFwaFFMUXVlcmllcyIsImRlZmF1bHRHcmFwaFFMTXV0YXRpb25zIiwiZ3JhcGhRTFF1ZXJ5IiwidW5kZWZpbmVkIiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsIkdyYXBoUUxPYmplY3RUeXBlIiwibmFtZSIsImRlc2NyaXB0aW9uIiwiZmllbGRzIiwiYWRkR3JhcGhRTFR5cGUiLCJncmFwaFFMTXV0YXRpb24iLCJncmFwaFFMU3Vic2NyaXB0aW9uIiwiR3JhcGhRTFNjaGVtYSIsInR5cGVzIiwicXVlcnkiLCJtdXRhdGlvbiIsInN1YnNjcmlwdGlvbiIsInNjaGVtYURpcmVjdGl2ZXMiLCJzY2hlbWFzIiwibWVyZ2VEaXJlY3RpdmVzIiwiZ3JhcGhRTFNjaGVtYVR5cGVNYXAiLCJnZXRUeXBlTWFwIiwiZ3JhcGhRTFNjaGVtYVR5cGVOYW1lIiwiZ3JhcGhRTFNjaGVtYVR5cGUiLCJnZXRGaWVsZHMiLCJncmFwaFFMQ3VzdG9tVHlwZURlZiIsImRlZmluaXRpb25zIiwiZmluZCIsImRlZmluaXRpb24iLCJ2YWx1ZSIsImdyYXBoUUxTY2hlbWFUeXBlRmllbGRNYXAiLCJncmFwaFFMU2NoZW1hVHlwZUZpZWxkTmFtZSIsImdyYXBoUUxTY2hlbWFUeXBlRmllbGQiLCJhc3ROb2RlIiwiZmllbGQiLCJTY2hlbWFEaXJlY3RpdmVWaXNpdG9yIiwidmlzaXRTY2hlbWFEaXJlY3RpdmVzIiwidHlwZSIsInRocm93RXJyb3IiLCJpZ25vcmVSZXNlcnZlZCIsImluY2x1ZGVzIiwiZXhpc3RpbmdUeXBlIiwibWVzc2FnZSIsIkVycm9yIiwid2FybiIsInB1c2giLCJhZGRHcmFwaFFMUXVlcnkiLCJmaWVsZE5hbWUiLCJhZGRHcmFwaFFMTXV0YXRpb24iLCJoYW5kbGVFcnJvciIsImVycm9yIiwiUGFyc2UiLCJzdGFjayIsInNjaGVtYUNvbnRyb2xsZXIiLCJQcm9taXNlIiwiYWxsIiwibG9hZFNjaGVtYSIsImdldEdyYXBoUUxDb25maWciLCJlbmFibGVkRm9yQ2xhc3NlcyIsImRpc2FibGVkRm9yQ2xhc3NlcyIsImFsbENsYXNzZXMiLCJnZXRBbGxDbGFzc2VzIiwiQXJyYXkiLCJpc0FycmF5IiwiaW5jbHVkZWRDbGFzc2VzIiwiZmlsdGVyIiwiY2xhenoiLCJjbGFzc05hbWUiLCJpc1VzZXJzQ2xhc3NEaXNhYmxlZCIsInNvbWUiLCJjbGFzc0NvbmZpZ3MiLCJzb3J0Q2xhc3NlcyIsImEiLCJiIiwic29ydCIsIm1hcCIsImMiLCJmdW5jdGlvbk5hbWUiLCJ0ZXN0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBR0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBRUEsTUFBTUEsMkJBQTJCLEdBQUcsQ0FDbEMsUUFEa0MsRUFFbEMsU0FGa0MsRUFHbEMsS0FIa0MsRUFJbEMsT0FKa0MsRUFLbEMsSUFMa0MsRUFNbEMsYUFOa0MsRUFPbEMsT0FQa0MsRUFRbEMsVUFSa0MsRUFTbEMsY0FUa0MsRUFVbEMsUUFWa0MsRUFXbEMsbUJBWGtDLEVBWWxDLGtCQVprQyxFQWFsQyxtQkFia0MsQ0FBcEM7QUFlQSxNQUFNQyw0QkFBNEIsR0FBRyxDQUFDLFFBQUQsRUFBVyxRQUFYLEVBQXFCLE9BQXJCLEVBQThCLFNBQTlCLENBQXJDO0FBQ0EsTUFBTUMsK0JBQStCLEdBQUcsQ0FDdEMsUUFEc0MsRUFFdEMsT0FGc0MsRUFHdEMsUUFIc0MsRUFJdEMsWUFKc0MsRUFLdEMsZUFMc0MsRUFNdEMsYUFOc0MsRUFPdEMsYUFQc0MsRUFRdEMsYUFSc0MsQ0FBeEM7O0FBV0EsTUFBTUMsa0JBQU4sQ0FBeUI7QUFNdkJDLEVBQUFBLFdBQVcsQ0FDVEMsTUFLQyxHQUFHLEVBTkssRUFPVDtBQUNBLFNBQUtDLHNCQUFMLEdBQ0VELE1BQU0sQ0FBQ0Msc0JBQVAsSUFDQSxnQ0FBa0IscURBQWxCLENBRkY7QUFHQSxTQUFLQyxrQkFBTCxHQUNFRixNQUFNLENBQUNFLGtCQUFQLElBQ0EsZ0NBQWtCLGlEQUFsQixDQUZGO0FBR0EsU0FBS0MsR0FBTCxHQUNFSCxNQUFNLENBQUNHLEdBQVAsSUFBYyxnQ0FBa0Isa0NBQWxCLENBRGhCO0FBRUEsU0FBS0MscUJBQUwsR0FBNkJKLE1BQU0sQ0FBQ0kscUJBQXBDO0FBQ0EsU0FBS0MsS0FBTCxHQUNFTCxNQUFNLENBQUNLLEtBQVAsSUFBZ0IsZ0NBQWtCLDZCQUFsQixDQURsQjtBQUVEOztBQUVELFFBQU1DLElBQU4sR0FBYTtBQUNYLFVBQU07QUFBRUMsTUFBQUE7QUFBRixRQUF5QixNQUFNLEtBQUtDLDBCQUFMLEVBQXJDO0FBQ0EsVUFBTUMsWUFBWSxHQUFHLE1BQU0sS0FBS0Msb0JBQUwsQ0FBMEJILGtCQUExQixDQUEzQjtBQUNBLFVBQU1JLGtCQUFrQixHQUFHQyxJQUFJLENBQUNDLFNBQUwsQ0FBZUosWUFBZixDQUEzQjtBQUNBLFVBQU1LLGFBQWEsR0FBRyxNQUFNLEtBQUtDLGlCQUFMLEVBQTVCO0FBQ0EsVUFBTUMsbUJBQW1CLEdBQUdKLElBQUksQ0FBQ0MsU0FBTCxDQUFlQyxhQUFmLENBQTVCOztBQUVBLFFBQ0UsS0FBS0csYUFBTCxJQUNBLENBQUMsS0FBS0Msc0JBQUwsQ0FBNEI7QUFDM0JULE1BQUFBLFlBRDJCO0FBRTNCRSxNQUFBQSxrQkFGMkI7QUFHM0JKLE1BQUFBLGtCQUgyQjtBQUkzQlMsTUFBQUE7QUFKMkIsS0FBNUIsQ0FGSCxFQVFFO0FBQ0EsYUFBTyxLQUFLQyxhQUFaO0FBQ0Q7O0FBRUQsU0FBS1IsWUFBTCxHQUFvQkEsWUFBcEI7QUFDQSxTQUFLRSxrQkFBTCxHQUEwQkEsa0JBQTFCO0FBQ0EsU0FBS0osa0JBQUwsR0FBMEJBLGtCQUExQjtBQUNBLFNBQUtPLGFBQUwsR0FBcUJBLGFBQXJCO0FBQ0EsU0FBS0UsbUJBQUwsR0FBMkJBLG1CQUEzQjtBQUNBLFNBQUtHLGVBQUwsR0FBdUIsRUFBdkI7QUFDQSxTQUFLQyxVQUFMLEdBQWtCLElBQWxCO0FBQ0EsU0FBS0MsaUJBQUwsR0FBeUIsSUFBekI7QUFDQSxTQUFLSixhQUFMLEdBQXFCLElBQXJCO0FBQ0EsU0FBS0ssWUFBTCxHQUFvQixFQUFwQjtBQUNBLFNBQUtDLGNBQUwsR0FBc0IsRUFBdEI7QUFDQSxTQUFLQyxnQkFBTCxHQUF3QixFQUF4QjtBQUNBLFNBQUtDLG9CQUFMLEdBQTRCLEVBQTVCO0FBQ0EsU0FBS0Msa0NBQUwsR0FBMEMsSUFBMUM7QUFDQSxTQUFLQyx1QkFBTCxHQUErQixFQUEvQjtBQUVBQyxJQUFBQSxtQkFBbUIsQ0FBQ3RCLElBQXBCLENBQXlCLElBQXpCO0FBQ0F1QixJQUFBQSxXQUFXLENBQUN2QixJQUFaLENBQWlCLElBQWpCOztBQUVBLFNBQUt3QiwwQkFBTCxDQUFnQ3JCLFlBQWhDLEVBQThDRixrQkFBOUMsRUFBa0V3QixPQUFsRSxDQUNFLENBQUMsQ0FBQ0MsVUFBRCxFQUFhQyxnQkFBYixDQUFELEtBQW9DO0FBQ2xDZCxNQUFBQSxlQUFlLENBQUNiLElBQWhCLENBQXFCLElBQXJCLEVBQTJCMEIsVUFBM0IsRUFBdUNDLGdCQUF2QztBQUNBQyxNQUFBQSxpQkFBaUIsQ0FBQzVCLElBQWxCLENBQXVCLElBQXZCLEVBQTZCMEIsVUFBN0IsRUFBeUNDLGdCQUF6QztBQUNBRSxNQUFBQSxtQkFBbUIsQ0FBQzdCLElBQXBCLENBQXlCLElBQXpCLEVBQStCMEIsVUFBL0IsRUFBMkNDLGdCQUEzQztBQUNELEtBTEg7O0FBUUFMLElBQUFBLG1CQUFtQixDQUFDUSxlQUFwQixDQUFvQyxJQUFwQyxFQUEwQzNCLFlBQTFDO0FBQ0E0QixJQUFBQSxxQkFBcUIsQ0FBQy9CLElBQXRCLENBQTJCLElBQTNCO0FBQ0FnQyxJQUFBQSx1QkFBdUIsQ0FBQ2hDLElBQXhCLENBQTZCLElBQTdCO0FBRUEsUUFBSWlDLFlBQVksR0FBR0MsU0FBbkI7O0FBQ0EsUUFBSUMsTUFBTSxDQUFDQyxJQUFQLENBQVksS0FBS25CLGNBQWpCLEVBQWlDb0IsTUFBakMsR0FBMEMsQ0FBOUMsRUFBaUQ7QUFDL0NKLE1BQUFBLFlBQVksR0FBRyxJQUFJSywwQkFBSixDQUFzQjtBQUNuQ0MsUUFBQUEsSUFBSSxFQUFFLE9BRDZCO0FBRW5DQyxRQUFBQSxXQUFXLEVBQUUsMENBRnNCO0FBR25DQyxRQUFBQSxNQUFNLEVBQUUsS0FBS3hCO0FBSHNCLE9BQXRCLENBQWY7QUFLQSxXQUFLeUIsY0FBTCxDQUFvQlQsWUFBcEIsRUFBa0MsSUFBbEMsRUFBd0MsSUFBeEM7QUFDRDs7QUFFRCxRQUFJVSxlQUFlLEdBQUdULFNBQXRCOztBQUNBLFFBQUlDLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZLEtBQUtsQixnQkFBakIsRUFBbUNtQixNQUFuQyxHQUE0QyxDQUFoRCxFQUFtRDtBQUNqRE0sTUFBQUEsZUFBZSxHQUFHLElBQUlMLDBCQUFKLENBQXNCO0FBQ3RDQyxRQUFBQSxJQUFJLEVBQUUsVUFEZ0M7QUFFdENDLFFBQUFBLFdBQVcsRUFBRSwrQ0FGeUI7QUFHdENDLFFBQUFBLE1BQU0sRUFBRSxLQUFLdkI7QUFIeUIsT0FBdEIsQ0FBbEI7QUFLQSxXQUFLd0IsY0FBTCxDQUFvQkMsZUFBcEIsRUFBcUMsSUFBckMsRUFBMkMsSUFBM0M7QUFDRDs7QUFFRCxRQUFJQyxtQkFBbUIsR0FBR1YsU0FBMUI7O0FBQ0EsUUFBSUMsTUFBTSxDQUFDQyxJQUFQLENBQVksS0FBS2pCLG9CQUFqQixFQUF1Q2tCLE1BQXZDLEdBQWdELENBQXBELEVBQXVEO0FBQ3JETyxNQUFBQSxtQkFBbUIsR0FBRyxJQUFJTiwwQkFBSixDQUFzQjtBQUMxQ0MsUUFBQUEsSUFBSSxFQUFFLGNBRG9DO0FBRTFDQyxRQUFBQSxXQUFXLEVBQUUsdURBRjZCO0FBRzFDQyxRQUFBQSxNQUFNLEVBQUUsS0FBS3RCO0FBSDZCLE9BQXRCLENBQXRCO0FBS0EsV0FBS3VCLGNBQUwsQ0FBb0JFLG1CQUFwQixFQUF5QyxJQUF6QyxFQUErQyxJQUEvQztBQUNEOztBQUVELFNBQUs3QixpQkFBTCxHQUF5QixJQUFJOEIsc0JBQUosQ0FBa0I7QUFDekNDLE1BQUFBLEtBQUssRUFBRSxLQUFLOUIsWUFENkI7QUFFekMrQixNQUFBQSxLQUFLLEVBQUVkLFlBRmtDO0FBR3pDZSxNQUFBQSxRQUFRLEVBQUVMLGVBSCtCO0FBSXpDTSxNQUFBQSxZQUFZLEVBQUVMO0FBSjJCLEtBQWxCLENBQXpCOztBQU9BLFFBQUksS0FBSzlDLHFCQUFULEVBQWdDO0FBQzlCb0QsTUFBQUEsZ0JBQWdCLENBQUNsRCxJQUFqQixDQUFzQixJQUF0QjtBQUVBLFdBQUtXLGFBQUwsR0FBcUIsZ0NBQWE7QUFDaEN3QyxRQUFBQSxPQUFPLEVBQUUsQ0FDUCxLQUFLL0Isa0NBREUsRUFFUCxLQUFLTCxpQkFGRSxFQUdQLEtBQUtqQixxQkFIRSxDQUR1QjtBQU1oQ3NELFFBQUFBLGVBQWUsRUFBRTtBQU5lLE9BQWIsQ0FBckI7QUFTQSxZQUFNQyxvQkFBb0IsR0FBRyxLQUFLMUMsYUFBTCxDQUFtQjJDLFVBQW5CLEVBQTdCO0FBQ0FuQixNQUFBQSxNQUFNLENBQUNDLElBQVAsQ0FBWWlCLG9CQUFaLEVBQWtDNUIsT0FBbEMsQ0FBMEM4QixxQkFBcUIsSUFBSTtBQUNqRSxjQUFNQyxpQkFBaUIsR0FBR0gsb0JBQW9CLENBQUNFLHFCQUFELENBQTlDOztBQUNBLFlBQUksT0FBT0MsaUJBQWlCLENBQUNDLFNBQXpCLEtBQXVDLFVBQTNDLEVBQXVEO0FBQ3JELGdCQUFNQyxvQkFBb0IsR0FBRyxLQUFLNUQscUJBQUwsQ0FBMkI2RCxXQUEzQixDQUF1Q0MsSUFBdkMsQ0FDM0JDLFVBQVUsSUFBSUEsVUFBVSxDQUFDdEIsSUFBWCxDQUFnQnVCLEtBQWhCLEtBQTBCUCxxQkFEYixDQUE3Qjs7QUFHQSxjQUFJRyxvQkFBSixFQUEwQjtBQUN4QixrQkFBTUsseUJBQXlCLEdBQUdQLGlCQUFpQixDQUFDQyxTQUFsQixFQUFsQztBQUNBdEIsWUFBQUEsTUFBTSxDQUFDQyxJQUFQLENBQVkyQix5QkFBWixFQUF1Q3RDLE9BQXZDLENBQ0V1QywwQkFBMEIsSUFBSTtBQUM1QixvQkFBTUMsc0JBQXNCLEdBQzFCRix5QkFBeUIsQ0FBQ0MsMEJBQUQsQ0FEM0I7O0FBRUEsa0JBQUksQ0FBQ0Msc0JBQXNCLENBQUNDLE9BQTVCLEVBQXFDO0FBQ25DLHNCQUFNQSxPQUFPLEdBQUdSLG9CQUFvQixDQUFDakIsTUFBckIsQ0FBNEJtQixJQUE1QixDQUNkTyxLQUFLLElBQUlBLEtBQUssQ0FBQzVCLElBQU4sQ0FBV3VCLEtBQVgsS0FBcUJFLDBCQURoQixDQUFoQjs7QUFHQSxvQkFBSUUsT0FBSixFQUFhO0FBQ1hELGtCQUFBQSxzQkFBc0IsQ0FBQ0MsT0FBdkIsR0FBaUNBLE9BQWpDO0FBQ0Q7QUFDRjtBQUNGLGFBWkg7QUFjRDtBQUNGO0FBQ0YsT0F4QkQ7O0FBMEJBRSwyQ0FBdUJDLHFCQUF2QixDQUNFLEtBQUsxRCxhQURQLEVBRUUsS0FBS1UsdUJBRlA7QUFJRCxLQTNDRCxNQTJDTztBQUNMLFdBQUtWLGFBQUwsR0FBcUIsS0FBS0ksaUJBQTFCO0FBQ0Q7O0FBRUQsV0FBTyxLQUFLSixhQUFaO0FBQ0Q7O0FBRUQrQixFQUFBQSxjQUFjLENBQUM0QixJQUFELEVBQU9DLFVBQVUsR0FBRyxLQUFwQixFQUEyQkMsY0FBYyxHQUFHLEtBQTVDLEVBQW1EO0FBQy9ELFFBQ0csQ0FBQ0EsY0FBRCxJQUFtQm5GLDJCQUEyQixDQUFDb0YsUUFBNUIsQ0FBcUNILElBQUksQ0FBQy9CLElBQTFDLENBQXBCLElBQ0EsS0FBS3ZCLFlBQUwsQ0FBa0I0QyxJQUFsQixDQUF1QmMsWUFBWSxJQUFJQSxZQUFZLENBQUNuQyxJQUFiLEtBQXNCK0IsSUFBSSxDQUFDL0IsSUFBbEUsQ0FGRixFQUdFO0FBQ0EsWUFBTW9DLE9BQU8sR0FBSSxRQUFPTCxJQUFJLENBQUMvQixJQUFLLG1GQUFsQzs7QUFDQSxVQUFJZ0MsVUFBSixFQUFnQjtBQUNkLGNBQU0sSUFBSUssS0FBSixDQUFVRCxPQUFWLENBQU47QUFDRDs7QUFDRCxXQUFLOUUsR0FBTCxDQUFTZ0YsSUFBVCxDQUFjRixPQUFkO0FBQ0EsYUFBT3pDLFNBQVA7QUFDRDs7QUFDRCxTQUFLbEIsWUFBTCxDQUFrQjhELElBQWxCLENBQXVCUixJQUF2QjtBQUNBLFdBQU9BLElBQVA7QUFDRDs7QUFFRFMsRUFBQUEsZUFBZSxDQUNiQyxTQURhLEVBRWJiLEtBRmEsRUFHYkksVUFBVSxHQUFHLEtBSEEsRUFJYkMsY0FBYyxHQUFHLEtBSkosRUFLYjtBQUNBLFFBQ0csQ0FBQ0EsY0FBRCxJQUFtQmxGLDRCQUE0QixDQUFDbUYsUUFBN0IsQ0FBc0NPLFNBQXRDLENBQXBCLElBQ0EsS0FBSy9ELGNBQUwsQ0FBb0IrRCxTQUFwQixDQUZGLEVBR0U7QUFDQSxZQUFNTCxPQUFPLEdBQUksU0FBUUssU0FBVSxvRkFBbkM7O0FBQ0EsVUFBSVQsVUFBSixFQUFnQjtBQUNkLGNBQU0sSUFBSUssS0FBSixDQUFVRCxPQUFWLENBQU47QUFDRDs7QUFDRCxXQUFLOUUsR0FBTCxDQUFTZ0YsSUFBVCxDQUFjRixPQUFkO0FBQ0EsYUFBT3pDLFNBQVA7QUFDRDs7QUFDRCxTQUFLakIsY0FBTCxDQUFvQitELFNBQXBCLElBQWlDYixLQUFqQztBQUNBLFdBQU9BLEtBQVA7QUFDRDs7QUFFRGMsRUFBQUEsa0JBQWtCLENBQ2hCRCxTQURnQixFQUVoQmIsS0FGZ0IsRUFHaEJJLFVBQVUsR0FBRyxLQUhHLEVBSWhCQyxjQUFjLEdBQUcsS0FKRCxFQUtoQjtBQUNBLFFBQ0csQ0FBQ0EsY0FBRCxJQUNDakYsK0JBQStCLENBQUNrRixRQUFoQyxDQUF5Q08sU0FBekMsQ0FERixJQUVBLEtBQUs5RCxnQkFBTCxDQUFzQjhELFNBQXRCLENBSEYsRUFJRTtBQUNBLFlBQU1MLE9BQU8sR0FBSSxZQUFXSyxTQUFVLG9GQUF0Qzs7QUFDQSxVQUFJVCxVQUFKLEVBQWdCO0FBQ2QsY0FBTSxJQUFJSyxLQUFKLENBQVVELE9BQVYsQ0FBTjtBQUNEOztBQUNELFdBQUs5RSxHQUFMLENBQVNnRixJQUFULENBQWNGLE9BQWQ7QUFDQSxhQUFPekMsU0FBUDtBQUNEOztBQUNELFNBQUtoQixnQkFBTCxDQUFzQjhELFNBQXRCLElBQW1DYixLQUFuQztBQUNBLFdBQU9BLEtBQVA7QUFDRDs7QUFFRGUsRUFBQUEsV0FBVyxDQUFDQyxLQUFELEVBQVE7QUFDakIsUUFBSUEsS0FBSyxZQUFZQyxjQUFNUixLQUEzQixFQUFrQztBQUNoQyxXQUFLL0UsR0FBTCxDQUFTc0YsS0FBVCxDQUFlLGVBQWYsRUFBZ0NBLEtBQWhDO0FBQ0QsS0FGRCxNQUVPO0FBQ0wsV0FBS3RGLEdBQUwsQ0FBU3NGLEtBQVQsQ0FBZSxpQ0FBZixFQUFrREEsS0FBbEQsRUFBeURBLEtBQUssQ0FBQ0UsS0FBL0Q7QUFDRDs7QUFDRCxVQUFNLHVDQUFlRixLQUFmLENBQU47QUFDRDs7QUFFRCxRQUFNakYsMEJBQU4sR0FBbUM7QUFDakMsVUFBTSxDQUFDb0YsZ0JBQUQsRUFBbUJyRixrQkFBbkIsSUFBeUMsTUFBTXNGLE9BQU8sQ0FBQ0MsR0FBUixDQUFZLENBQy9ELEtBQUs1RixrQkFBTCxDQUF3QjZGLFVBQXhCLEVBRCtELEVBRS9ELEtBQUs5RixzQkFBTCxDQUE0QitGLGdCQUE1QixFQUYrRCxDQUFaLENBQXJEO0FBS0EsU0FBS0osZ0JBQUwsR0FBd0JBLGdCQUF4QjtBQUVBLFdBQU87QUFDTHJGLE1BQUFBO0FBREssS0FBUDtBQUdEO0FBRUQ7Ozs7OztBQUlBLFFBQU1HLG9CQUFOLENBQTJCSCxrQkFBM0IsRUFBbUU7QUFDakUsVUFBTTtBQUFFMEYsTUFBQUEsaUJBQUY7QUFBcUJDLE1BQUFBO0FBQXJCLFFBQTRDM0Ysa0JBQWxEO0FBQ0EsVUFBTTRGLFVBQVUsR0FBRyxNQUFNLEtBQUtQLGdCQUFMLENBQXNCUSxhQUF0QixFQUF6Qjs7QUFFQSxRQUFJQyxLQUFLLENBQUNDLE9BQU4sQ0FBY0wsaUJBQWQsS0FBb0NJLEtBQUssQ0FBQ0MsT0FBTixDQUFjSixrQkFBZCxDQUF4QyxFQUEyRTtBQUN6RSxVQUFJSyxlQUFlLEdBQUdKLFVBQXRCOztBQUNBLFVBQUlGLGlCQUFKLEVBQXVCO0FBQ3JCTSxRQUFBQSxlQUFlLEdBQUdKLFVBQVUsQ0FBQ0ssTUFBWCxDQUFrQkMsS0FBSyxJQUFJO0FBQzNDLGlCQUFPUixpQkFBaUIsQ0FBQ2xCLFFBQWxCLENBQTJCMEIsS0FBSyxDQUFDQyxTQUFqQyxDQUFQO0FBQ0QsU0FGaUIsQ0FBbEI7QUFHRDs7QUFDRCxVQUFJUixrQkFBSixFQUF3QjtBQUN0QjtBQUNBO0FBQ0E7QUFDQUssUUFBQUEsZUFBZSxHQUFHQSxlQUFlLENBQUNDLE1BQWhCLENBQXVCQyxLQUFLLElBQUk7QUFDaEQsaUJBQU8sQ0FBQ1Asa0JBQWtCLENBQUNuQixRQUFuQixDQUE0QjBCLEtBQUssQ0FBQ0MsU0FBbEMsQ0FBUjtBQUNELFNBRmlCLENBQWxCO0FBR0Q7O0FBRUQsV0FBS0Msb0JBQUwsR0FBNEIsQ0FBQ0osZUFBZSxDQUFDSyxJQUFoQixDQUFxQkgsS0FBSyxJQUFJO0FBQ3pELGVBQU9BLEtBQUssQ0FBQ0MsU0FBTixLQUFvQixPQUEzQjtBQUNELE9BRjRCLENBQTdCO0FBSUEsYUFBT0gsZUFBUDtBQUNELEtBckJELE1BcUJPO0FBQ0wsYUFBT0osVUFBUDtBQUNEO0FBQ0Y7QUFFRDs7Ozs7OztBQUtBckUsRUFBQUEsMEJBQTBCLENBQ3hCckIsWUFEd0IsRUFFeEJGLGtCQUZ3QixFQUd4QjtBQUNBLFVBQU07QUFBRXNHLE1BQUFBO0FBQUYsUUFBbUJ0RyxrQkFBekIsQ0FEQSxDQUdBO0FBQ0E7O0FBQ0EsVUFBTXVHLFdBQVcsR0FBRyxDQUFDQyxDQUFELEVBQUlDLENBQUosS0FBVTtBQUM1QkQsTUFBQUEsQ0FBQyxHQUFHQSxDQUFDLENBQUNMLFNBQU47QUFDQU0sTUFBQUEsQ0FBQyxHQUFHQSxDQUFDLENBQUNOLFNBQU47O0FBQ0EsVUFBSUssQ0FBQyxDQUFDLENBQUQsQ0FBRCxLQUFTLEdBQWIsRUFBa0I7QUFDaEIsWUFBSUMsQ0FBQyxDQUFDLENBQUQsQ0FBRCxLQUFTLEdBQWIsRUFBa0I7QUFDaEIsaUJBQU8sQ0FBQyxDQUFSO0FBQ0Q7QUFDRjs7QUFDRCxVQUFJQSxDQUFDLENBQUMsQ0FBRCxDQUFELEtBQVMsR0FBYixFQUFrQjtBQUNoQixZQUFJRCxDQUFDLENBQUMsQ0FBRCxDQUFELEtBQVMsR0FBYixFQUFrQjtBQUNoQixpQkFBTyxDQUFQO0FBQ0Q7QUFDRjs7QUFDRCxVQUFJQSxDQUFDLEtBQUtDLENBQVYsRUFBYTtBQUNYLGVBQU8sQ0FBUDtBQUNELE9BRkQsTUFFTyxJQUFJRCxDQUFDLEdBQUdDLENBQVIsRUFBVztBQUNoQixlQUFPLENBQUMsQ0FBUjtBQUNELE9BRk0sTUFFQTtBQUNMLGVBQU8sQ0FBUDtBQUNEO0FBQ0YsS0FwQkQ7O0FBc0JBLFdBQU92RyxZQUFZLENBQUN3RyxJQUFiLENBQWtCSCxXQUFsQixFQUErQkksR0FBL0IsQ0FBbUNsRixVQUFVLElBQUk7QUFDdEQsVUFBSUMsZ0JBQUo7O0FBQ0EsVUFBSTRFLFlBQUosRUFBa0I7QUFDaEI1RSxRQUFBQSxnQkFBZ0IsR0FBRzRFLFlBQVksQ0FBQzNDLElBQWIsQ0FDakJpRCxDQUFDLElBQUlBLENBQUMsQ0FBQ1QsU0FBRixLQUFnQjFFLFVBQVUsQ0FBQzBFLFNBRGYsQ0FBbkI7QUFHRDs7QUFDRCxhQUFPLENBQUMxRSxVQUFELEVBQWFDLGdCQUFiLENBQVA7QUFDRCxLQVJNLENBQVA7QUFTRDs7QUFFRCxRQUFNbEIsaUJBQU4sR0FBMEI7QUFDeEIsV0FBTyxNQUFNLGdDQUFpQixLQUFLVixLQUF0QixFQUE2Qm1HLE1BQTdCLENBQW9DWSxZQUFZLElBQUk7QUFDL0QsVUFBSSwyQkFBMkJDLElBQTNCLENBQWdDRCxZQUFoQyxDQUFKLEVBQW1EO0FBQ2pELGVBQU8sSUFBUDtBQUNELE9BRkQsTUFFTztBQUNMLGFBQUtqSCxHQUFMLENBQVNnRixJQUFULENBQ0csWUFBV2lDLFlBQWEscUdBRDNCO0FBR0EsZUFBTyxLQUFQO0FBQ0Q7QUFDRixLQVRZLENBQWI7QUFVRDtBQUVEOzs7Ozs7OztBQU1BbEcsRUFBQUEsc0JBQXNCLENBQUNsQixNQUFELEVBS1Y7QUFDVixVQUFNO0FBQ0pTLE1BQUFBLFlBREk7QUFFSkUsTUFBQUEsa0JBRkk7QUFHSkosTUFBQUEsa0JBSEk7QUFJSlMsTUFBQUE7QUFKSSxRQUtGaEIsTUFMSjs7QUFPQSxRQUNFWSxJQUFJLENBQUNDLFNBQUwsQ0FBZSxLQUFLTixrQkFBcEIsTUFDRUssSUFBSSxDQUFDQyxTQUFMLENBQWVOLGtCQUFmLENBREYsSUFFQSxLQUFLUyxtQkFBTCxLQUE2QkEsbUJBSC9CLEVBSUU7QUFDQSxVQUFJLEtBQUtQLFlBQUwsS0FBc0JBLFlBQTFCLEVBQXdDO0FBQ3RDLGVBQU8sS0FBUDtBQUNEOztBQUVELFVBQUksS0FBS0Usa0JBQUwsS0FBNEJBLGtCQUFoQyxFQUFvRDtBQUNsRCxhQUFLRixZQUFMLEdBQW9CQSxZQUFwQjtBQUNBLGVBQU8sS0FBUDtBQUNEO0FBQ0Y7O0FBRUQsV0FBTyxJQUFQO0FBQ0Q7O0FBclhzQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCB7IEdyYXBoUUxTY2hlbWEsIEdyYXBoUUxPYmplY3RUeXBlIH0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgeyBtZXJnZVNjaGVtYXMsIFNjaGVtYURpcmVjdGl2ZVZpc2l0b3IgfSBmcm9tICdncmFwaHFsLXRvb2xzJztcbmltcG9ydCByZXF1aXJlZFBhcmFtZXRlciBmcm9tICcuLi9yZXF1aXJlZFBhcmFtZXRlcic7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4vbG9hZGVycy9kZWZhdWx0R3JhcGhRTFR5cGVzJztcbmltcG9ydCAqIGFzIHBhcnNlQ2xhc3NUeXBlcyBmcm9tICcuL2xvYWRlcnMvcGFyc2VDbGFzc1R5cGVzJztcbmltcG9ydCAqIGFzIHBhcnNlQ2xhc3NRdWVyaWVzIGZyb20gJy4vbG9hZGVycy9wYXJzZUNsYXNzUXVlcmllcyc7XG5pbXBvcnQgKiBhcyBwYXJzZUNsYXNzTXV0YXRpb25zIGZyb20gJy4vbG9hZGVycy9wYXJzZUNsYXNzTXV0YXRpb25zJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMUXVlcmllcyBmcm9tICcuL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxRdWVyaWVzJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMTXV0YXRpb25zIGZyb20gJy4vbG9hZGVycy9kZWZhdWx0R3JhcGhRTE11dGF0aW9ucyc7XG5pbXBvcnQgUGFyc2VHcmFwaFFMQ29udHJvbGxlciwge1xuICBQYXJzZUdyYXBoUUxDb25maWcsXG59IGZyb20gJy4uL0NvbnRyb2xsZXJzL1BhcnNlR3JhcGhRTENvbnRyb2xsZXInO1xuaW1wb3J0IERhdGFiYXNlQ29udHJvbGxlciBmcm9tICcuLi9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgdG9HcmFwaFFMRXJyb3IgfSBmcm9tICcuL3BhcnNlR3JhcGhRTFV0aWxzJztcbmltcG9ydCAqIGFzIHNjaGVtYURpcmVjdGl2ZXMgZnJvbSAnLi9sb2FkZXJzL3NjaGVtYURpcmVjdGl2ZXMnO1xuaW1wb3J0ICogYXMgc2NoZW1hVHlwZXMgZnJvbSAnLi9sb2FkZXJzL3NjaGVtYVR5cGVzJztcbmltcG9ydCB7IGdldEZ1bmN0aW9uTmFtZXMgfSBmcm9tICcuLi90cmlnZ2Vycyc7XG5cbmNvbnN0IFJFU0VSVkVEX0dSQVBIUUxfVFlQRV9OQU1FUyA9IFtcbiAgJ1N0cmluZycsXG4gICdCb29sZWFuJyxcbiAgJ0ludCcsXG4gICdGbG9hdCcsXG4gICdJRCcsXG4gICdBcnJheVJlc3VsdCcsXG4gICdRdWVyeScsXG4gICdNdXRhdGlvbicsXG4gICdTdWJzY3JpcHRpb24nLFxuICAnVmlld2VyJyxcbiAgJ1NpZ25VcEZpZWxkc0lucHV0JyxcbiAgJ0xvZ0luRmllbGRzSW5wdXQnLFxuICAnQ2xvdWRDb2RlRnVuY3Rpb24nLFxuXTtcbmNvbnN0IFJFU0VSVkVEX0dSQVBIUUxfUVVFUllfTkFNRVMgPSBbJ2hlYWx0aCcsICd2aWV3ZXInLCAnY2xhc3MnLCAnY2xhc3NlcyddO1xuY29uc3QgUkVTRVJWRURfR1JBUEhRTF9NVVRBVElPTl9OQU1FUyA9IFtcbiAgJ3NpZ25VcCcsXG4gICdsb2dJbicsXG4gICdsb2dPdXQnLFxuICAnY3JlYXRlRmlsZScsXG4gICdjYWxsQ2xvdWRDb2RlJyxcbiAgJ2NyZWF0ZUNsYXNzJyxcbiAgJ3VwZGF0ZUNsYXNzJyxcbiAgJ2RlbGV0ZUNsYXNzJyxcbl07XG5cbmNsYXNzIFBhcnNlR3JhcGhRTFNjaGVtYSB7XG4gIGRhdGFiYXNlQ29udHJvbGxlcjogRGF0YWJhc2VDb250cm9sbGVyO1xuICBwYXJzZUdyYXBoUUxDb250cm9sbGVyOiBQYXJzZUdyYXBoUUxDb250cm9sbGVyO1xuICBwYXJzZUdyYXBoUUxDb25maWc6IFBhcnNlR3JhcGhRTENvbmZpZztcbiAgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcGFyYW1zOiB7XG4gICAgICBkYXRhYmFzZUNvbnRyb2xsZXI6IERhdGFiYXNlQ29udHJvbGxlcixcbiAgICAgIHBhcnNlR3JhcGhRTENvbnRyb2xsZXI6IFBhcnNlR3JhcGhRTENvbnRyb2xsZXIsXG4gICAgICBsb2c6IGFueSxcbiAgICAgIGFwcElkOiBzdHJpbmcsXG4gICAgfSA9IHt9XG4gICkge1xuICAgIHRoaXMucGFyc2VHcmFwaFFMQ29udHJvbGxlciA9XG4gICAgICBwYXJhbXMucGFyc2VHcmFwaFFMQ29udHJvbGxlciB8fFxuICAgICAgcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYSBwYXJzZUdyYXBoUUxDb250cm9sbGVyIGluc3RhbmNlIScpO1xuICAgIHRoaXMuZGF0YWJhc2VDb250cm9sbGVyID1cbiAgICAgIHBhcmFtcy5kYXRhYmFzZUNvbnRyb2xsZXIgfHxcbiAgICAgIHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIGEgZGF0YWJhc2VDb250cm9sbGVyIGluc3RhbmNlIScpO1xuICAgIHRoaXMubG9nID1cbiAgICAgIHBhcmFtcy5sb2cgfHwgcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYSBsb2cgaW5zdGFuY2UhJyk7XG4gICAgdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMgPSBwYXJhbXMuZ3JhcGhRTEN1c3RvbVR5cGVEZWZzO1xuICAgIHRoaXMuYXBwSWQgPVxuICAgICAgcGFyYW1zLmFwcElkIHx8IHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIHRoZSBhcHBJZCEnKTtcbiAgfVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgY29uc3QgeyBwYXJzZUdyYXBoUUxDb25maWcgfSA9IGF3YWl0IHRoaXMuX2luaXRpYWxpemVTY2hlbWFBbmRDb25maWcoKTtcbiAgICBjb25zdCBwYXJzZUNsYXNzZXMgPSBhd2FpdCB0aGlzLl9nZXRDbGFzc2VzRm9yU2NoZW1hKHBhcnNlR3JhcGhRTENvbmZpZyk7XG4gICAgY29uc3QgcGFyc2VDbGFzc2VzU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkocGFyc2VDbGFzc2VzKTtcbiAgICBjb25zdCBmdW5jdGlvbk5hbWVzID0gYXdhaXQgdGhpcy5fZ2V0RnVuY3Rpb25OYW1lcygpO1xuICAgIGNvbnN0IGZ1bmN0aW9uTmFtZXNTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShmdW5jdGlvbk5hbWVzKTtcblxuICAgIGlmIChcbiAgICAgIHRoaXMuZ3JhcGhRTFNjaGVtYSAmJlxuICAgICAgIXRoaXMuX2hhc1NjaGVtYUlucHV0Q2hhbmdlZCh7XG4gICAgICAgIHBhcnNlQ2xhc3NlcyxcbiAgICAgICAgcGFyc2VDbGFzc2VzU3RyaW5nLFxuICAgICAgICBwYXJzZUdyYXBoUUxDb25maWcsXG4gICAgICAgIGZ1bmN0aW9uTmFtZXNTdHJpbmcsXG4gICAgICB9KVxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuZ3JhcGhRTFNjaGVtYTtcbiAgICB9XG5cbiAgICB0aGlzLnBhcnNlQ2xhc3NlcyA9IHBhcnNlQ2xhc3NlcztcbiAgICB0aGlzLnBhcnNlQ2xhc3Nlc1N0cmluZyA9IHBhcnNlQ2xhc3Nlc1N0cmluZztcbiAgICB0aGlzLnBhcnNlR3JhcGhRTENvbmZpZyA9IHBhcnNlR3JhcGhRTENvbmZpZztcbiAgICB0aGlzLmZ1bmN0aW9uTmFtZXMgPSBmdW5jdGlvbk5hbWVzO1xuICAgIHRoaXMuZnVuY3Rpb25OYW1lc1N0cmluZyA9IGZ1bmN0aW9uTmFtZXNTdHJpbmc7XG4gICAgdGhpcy5wYXJzZUNsYXNzVHlwZXMgPSB7fTtcbiAgICB0aGlzLnZpZXdlclR5cGUgPSBudWxsO1xuICAgIHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEgPSBudWxsO1xuICAgIHRoaXMuZ3JhcGhRTFNjaGVtYSA9IG51bGw7XG4gICAgdGhpcy5ncmFwaFFMVHlwZXMgPSBbXTtcbiAgICB0aGlzLmdyYXBoUUxRdWVyaWVzID0ge307XG4gICAgdGhpcy5ncmFwaFFMTXV0YXRpb25zID0ge307XG4gICAgdGhpcy5ncmFwaFFMU3Vic2NyaXB0aW9ucyA9IHt9O1xuICAgIHRoaXMuZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXNEZWZpbml0aW9ucyA9IG51bGw7XG4gICAgdGhpcy5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlcyA9IHt9O1xuXG4gICAgZGVmYXVsdEdyYXBoUUxUeXBlcy5sb2FkKHRoaXMpO1xuICAgIHNjaGVtYVR5cGVzLmxvYWQodGhpcyk7XG5cbiAgICB0aGlzLl9nZXRQYXJzZUNsYXNzZXNXaXRoQ29uZmlnKHBhcnNlQ2xhc3NlcywgcGFyc2VHcmFwaFFMQ29uZmlnKS5mb3JFYWNoKFxuICAgICAgKFtwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnXSkgPT4ge1xuICAgICAgICBwYXJzZUNsYXNzVHlwZXMubG9hZCh0aGlzLCBwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnKTtcbiAgICAgICAgcGFyc2VDbGFzc1F1ZXJpZXMubG9hZCh0aGlzLCBwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnKTtcbiAgICAgICAgcGFyc2VDbGFzc011dGF0aW9ucy5sb2FkKHRoaXMsIHBhcnNlQ2xhc3MsIHBhcnNlQ2xhc3NDb25maWcpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICBkZWZhdWx0R3JhcGhRTFR5cGVzLmxvYWRBcnJheVJlc3VsdCh0aGlzLCBwYXJzZUNsYXNzZXMpO1xuICAgIGRlZmF1bHRHcmFwaFFMUXVlcmllcy5sb2FkKHRoaXMpO1xuICAgIGRlZmF1bHRHcmFwaFFMTXV0YXRpb25zLmxvYWQodGhpcyk7XG5cbiAgICBsZXQgZ3JhcGhRTFF1ZXJ5ID0gdW5kZWZpbmVkO1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLmdyYXBoUUxRdWVyaWVzKS5sZW5ndGggPiAwKSB7XG4gICAgICBncmFwaFFMUXVlcnkgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICAgICAgICBuYW1lOiAnUXVlcnknLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ1F1ZXJ5IGlzIHRoZSB0b3AgbGV2ZWwgdHlwZSBmb3IgcXVlcmllcy4nLFxuICAgICAgICBmaWVsZHM6IHRoaXMuZ3JhcGhRTFF1ZXJpZXMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkR3JhcGhRTFR5cGUoZ3JhcGhRTFF1ZXJ5LCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBsZXQgZ3JhcGhRTE11dGF0aW9uID0gdW5kZWZpbmVkO1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLmdyYXBoUUxNdXRhdGlvbnMpLmxlbmd0aCA+IDApIHtcbiAgICAgIGdyYXBoUUxNdXRhdGlvbiA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gICAgICAgIG5hbWU6ICdNdXRhdGlvbicsXG4gICAgICAgIGRlc2NyaXB0aW9uOiAnTXV0YXRpb24gaXMgdGhlIHRvcCBsZXZlbCB0eXBlIGZvciBtdXRhdGlvbnMuJyxcbiAgICAgICAgZmllbGRzOiB0aGlzLmdyYXBoUUxNdXRhdGlvbnMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkR3JhcGhRTFR5cGUoZ3JhcGhRTE11dGF0aW9uLCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBsZXQgZ3JhcGhRTFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5ncmFwaFFMU3Vic2NyaXB0aW9ucykubGVuZ3RoID4gMCkge1xuICAgICAgZ3JhcGhRTFN1YnNjcmlwdGlvbiA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gICAgICAgIG5hbWU6ICdTdWJzY3JpcHRpb24nLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ1N1YnNjcmlwdGlvbiBpcyB0aGUgdG9wIGxldmVsIHR5cGUgZm9yIHN1YnNjcmlwdGlvbnMuJyxcbiAgICAgICAgZmllbGRzOiB0aGlzLmdyYXBoUUxTdWJzY3JpcHRpb25zLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmFkZEdyYXBoUUxUeXBlKGdyYXBoUUxTdWJzY3JpcHRpb24sIHRydWUsIHRydWUpO1xuICAgIH1cblxuICAgIHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEgPSBuZXcgR3JhcGhRTFNjaGVtYSh7XG4gICAgICB0eXBlczogdGhpcy5ncmFwaFFMVHlwZXMsXG4gICAgICBxdWVyeTogZ3JhcGhRTFF1ZXJ5LFxuICAgICAgbXV0YXRpb246IGdyYXBoUUxNdXRhdGlvbixcbiAgICAgIHN1YnNjcmlwdGlvbjogZ3JhcGhRTFN1YnNjcmlwdGlvbixcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcykge1xuICAgICAgc2NoZW1hRGlyZWN0aXZlcy5sb2FkKHRoaXMpO1xuXG4gICAgICB0aGlzLmdyYXBoUUxTY2hlbWEgPSBtZXJnZVNjaGVtYXMoe1xuICAgICAgICBzY2hlbWFzOiBbXG4gICAgICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zLFxuICAgICAgICAgIHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEsXG4gICAgICAgICAgdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMsXG4gICAgICAgIF0sXG4gICAgICAgIG1lcmdlRGlyZWN0aXZlczogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBncmFwaFFMU2NoZW1hVHlwZU1hcCA9IHRoaXMuZ3JhcGhRTFNjaGVtYS5nZXRUeXBlTWFwKCk7XG4gICAgICBPYmplY3Qua2V5cyhncmFwaFFMU2NoZW1hVHlwZU1hcCkuZm9yRWFjaChncmFwaFFMU2NoZW1hVHlwZU5hbWUgPT4ge1xuICAgICAgICBjb25zdCBncmFwaFFMU2NoZW1hVHlwZSA9IGdyYXBoUUxTY2hlbWFUeXBlTWFwW2dyYXBoUUxTY2hlbWFUeXBlTmFtZV07XG4gICAgICAgIGlmICh0eXBlb2YgZ3JhcGhRTFNjaGVtYVR5cGUuZ2V0RmllbGRzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgY29uc3QgZ3JhcGhRTEN1c3RvbVR5cGVEZWYgPSB0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcy5kZWZpbml0aW9ucy5maW5kKFxuICAgICAgICAgICAgZGVmaW5pdGlvbiA9PiBkZWZpbml0aW9uLm5hbWUudmFsdWUgPT09IGdyYXBoUUxTY2hlbWFUeXBlTmFtZVxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKGdyYXBoUUxDdXN0b21UeXBlRGVmKSB7XG4gICAgICAgICAgICBjb25zdCBncmFwaFFMU2NoZW1hVHlwZUZpZWxkTWFwID0gZ3JhcGhRTFNjaGVtYVR5cGUuZ2V0RmllbGRzKCk7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhncmFwaFFMU2NoZW1hVHlwZUZpZWxkTWFwKS5mb3JFYWNoKFxuICAgICAgICAgICAgICBncmFwaFFMU2NoZW1hVHlwZUZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZCA9XG4gICAgICAgICAgICAgICAgICBncmFwaFFMU2NoZW1hVHlwZUZpZWxkTWFwW2dyYXBoUUxTY2hlbWFUeXBlRmllbGROYW1lXTtcbiAgICAgICAgICAgICAgICBpZiAoIWdyYXBoUUxTY2hlbWFUeXBlRmllbGQuYXN0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgY29uc3QgYXN0Tm9kZSA9IGdyYXBoUUxDdXN0b21UeXBlRGVmLmZpZWxkcy5maW5kKFxuICAgICAgICAgICAgICAgICAgICBmaWVsZCA9PiBmaWVsZC5uYW1lLnZhbHVlID09PSBncmFwaFFMU2NoZW1hVHlwZUZpZWxkTmFtZVxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIGlmIChhc3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGdyYXBoUUxTY2hlbWFUeXBlRmllbGQuYXN0Tm9kZSA9IGFzdE5vZGU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIFNjaGVtYURpcmVjdGl2ZVZpc2l0b3IudmlzaXRTY2hlbWFEaXJlY3RpdmVzKFxuICAgICAgICB0aGlzLmdyYXBoUUxTY2hlbWEsXG4gICAgICAgIHRoaXMuZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXNcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZ3JhcGhRTFNjaGVtYSA9IHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWE7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZ3JhcGhRTFNjaGVtYTtcbiAgfVxuXG4gIGFkZEdyYXBoUUxUeXBlKHR5cGUsIHRocm93RXJyb3IgPSBmYWxzZSwgaWdub3JlUmVzZXJ2ZWQgPSBmYWxzZSkge1xuICAgIGlmIChcbiAgICAgICghaWdub3JlUmVzZXJ2ZWQgJiYgUkVTRVJWRURfR1JBUEhRTF9UWVBFX05BTUVTLmluY2x1ZGVzKHR5cGUubmFtZSkpIHx8XG4gICAgICB0aGlzLmdyYXBoUUxUeXBlcy5maW5kKGV4aXN0aW5nVHlwZSA9PiBleGlzdGluZ1R5cGUubmFtZSA9PT0gdHlwZS5uYW1lKVxuICAgICkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGBUeXBlICR7dHlwZS5uYW1lfSBjb3VsZCBub3QgYmUgYWRkZWQgdG8gdGhlIGF1dG8gc2NoZW1hIGJlY2F1c2UgaXQgY29sbGlkZWQgd2l0aCBhbiBleGlzdGluZyB0eXBlLmA7XG4gICAgICBpZiAodGhyb3dFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICB9XG4gICAgICB0aGlzLmxvZy53YXJuKG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5ncmFwaFFMVHlwZXMucHVzaCh0eXBlKTtcbiAgICByZXR1cm4gdHlwZTtcbiAgfVxuXG4gIGFkZEdyYXBoUUxRdWVyeShcbiAgICBmaWVsZE5hbWUsXG4gICAgZmllbGQsXG4gICAgdGhyb3dFcnJvciA9IGZhbHNlLFxuICAgIGlnbm9yZVJlc2VydmVkID0gZmFsc2VcbiAgKSB7XG4gICAgaWYgKFxuICAgICAgKCFpZ25vcmVSZXNlcnZlZCAmJiBSRVNFUlZFRF9HUkFQSFFMX1FVRVJZX05BTUVTLmluY2x1ZGVzKGZpZWxkTmFtZSkpIHx8XG4gICAgICB0aGlzLmdyYXBoUUxRdWVyaWVzW2ZpZWxkTmFtZV1cbiAgICApIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgUXVlcnkgJHtmaWVsZE5hbWV9IGNvdWxkIG5vdCBiZSBhZGRlZCB0byB0aGUgYXV0byBzY2hlbWEgYmVjYXVzZSBpdCBjb2xsaWRlZCB3aXRoIGFuIGV4aXN0aW5nIGZpZWxkLmA7XG4gICAgICBpZiAodGhyb3dFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICB9XG4gICAgICB0aGlzLmxvZy53YXJuKG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5ncmFwaFFMUXVlcmllc1tmaWVsZE5hbWVdID0gZmllbGQ7XG4gICAgcmV0dXJuIGZpZWxkO1xuICB9XG5cbiAgYWRkR3JhcGhRTE11dGF0aW9uKFxuICAgIGZpZWxkTmFtZSxcbiAgICBmaWVsZCxcbiAgICB0aHJvd0Vycm9yID0gZmFsc2UsXG4gICAgaWdub3JlUmVzZXJ2ZWQgPSBmYWxzZVxuICApIHtcbiAgICBpZiAoXG4gICAgICAoIWlnbm9yZVJlc2VydmVkICYmXG4gICAgICAgIFJFU0VSVkVEX0dSQVBIUUxfTVVUQVRJT05fTkFNRVMuaW5jbHVkZXMoZmllbGROYW1lKSkgfHxcbiAgICAgIHRoaXMuZ3JhcGhRTE11dGF0aW9uc1tmaWVsZE5hbWVdXG4gICAgKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYE11dGF0aW9uICR7ZmllbGROYW1lfSBjb3VsZCBub3QgYmUgYWRkZWQgdG8gdGhlIGF1dG8gc2NoZW1hIGJlY2F1c2UgaXQgY29sbGlkZWQgd2l0aCBhbiBleGlzdGluZyBmaWVsZC5gO1xuICAgICAgaWYgKHRocm93RXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cud2FybihtZXNzYWdlKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuZ3JhcGhRTE11dGF0aW9uc1tmaWVsZE5hbWVdID0gZmllbGQ7XG4gICAgcmV0dXJuIGZpZWxkO1xuICB9XG5cbiAgaGFuZGxlRXJyb3IoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgICAgdGhpcy5sb2cuZXJyb3IoJ1BhcnNlIGVycm9yOiAnLCBlcnJvcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9nLmVycm9yKCdVbmNhdWdodCBpbnRlcm5hbCBzZXJ2ZXIgZXJyb3IuJywgZXJyb3IsIGVycm9yLnN0YWNrKTtcbiAgICB9XG4gICAgdGhyb3cgdG9HcmFwaFFMRXJyb3IoZXJyb3IpO1xuICB9XG5cbiAgYXN5bmMgX2luaXRpYWxpemVTY2hlbWFBbmRDb25maWcoKSB7XG4gICAgY29uc3QgW3NjaGVtYUNvbnRyb2xsZXIsIHBhcnNlR3JhcGhRTENvbmZpZ10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICB0aGlzLmRhdGFiYXNlQ29udHJvbGxlci5sb2FkU2NoZW1hKCksXG4gICAgICB0aGlzLnBhcnNlR3JhcGhRTENvbnRyb2xsZXIuZ2V0R3JhcGhRTENvbmZpZygpLFxuICAgIF0pO1xuXG4gICAgdGhpcy5zY2hlbWFDb250cm9sbGVyID0gc2NoZW1hQ29udHJvbGxlcjtcblxuICAgIHJldHVybiB7XG4gICAgICBwYXJzZUdyYXBoUUxDb25maWcsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGFsbCBjbGFzc2VzIGZvdW5kIGJ5IHRoZSBgc2NoZW1hQ29udHJvbGxlcmBcbiAgICogbWludXMgdGhvc2UgZmlsdGVyZWQgb3V0IGJ5IHRoZSBhcHAncyBwYXJzZUdyYXBoUUxDb25maWcuXG4gICAqL1xuICBhc3luYyBfZ2V0Q2xhc3Nlc0ZvclNjaGVtYShwYXJzZUdyYXBoUUxDb25maWc6IFBhcnNlR3JhcGhRTENvbmZpZykge1xuICAgIGNvbnN0IHsgZW5hYmxlZEZvckNsYXNzZXMsIGRpc2FibGVkRm9yQ2xhc3NlcyB9ID0gcGFyc2VHcmFwaFFMQ29uZmlnO1xuICAgIGNvbnN0IGFsbENsYXNzZXMgPSBhd2FpdCB0aGlzLnNjaGVtYUNvbnRyb2xsZXIuZ2V0QWxsQ2xhc3NlcygpO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZW5hYmxlZEZvckNsYXNzZXMpIHx8IEFycmF5LmlzQXJyYXkoZGlzYWJsZWRGb3JDbGFzc2VzKSkge1xuICAgICAgbGV0IGluY2x1ZGVkQ2xhc3NlcyA9IGFsbENsYXNzZXM7XG4gICAgICBpZiAoZW5hYmxlZEZvckNsYXNzZXMpIHtcbiAgICAgICAgaW5jbHVkZWRDbGFzc2VzID0gYWxsQ2xhc3Nlcy5maWx0ZXIoY2xhenogPT4ge1xuICAgICAgICAgIHJldHVybiBlbmFibGVkRm9yQ2xhc3Nlcy5pbmNsdWRlcyhjbGF6ei5jbGFzc05hbWUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChkaXNhYmxlZEZvckNsYXNzZXMpIHtcbiAgICAgICAgLy8gQ2xhc3NlcyBpbmNsdWRlZCBpbiBgZW5hYmxlZEZvckNsYXNzZXNgIHRoYXRcbiAgICAgICAgLy8gYXJlIGFsc28gcHJlc2VudCBpbiBgZGlzYWJsZWRGb3JDbGFzc2VzYCB3aWxsXG4gICAgICAgIC8vIHN0aWxsIGJlIGZpbHRlcmVkIG91dFxuICAgICAgICBpbmNsdWRlZENsYXNzZXMgPSBpbmNsdWRlZENsYXNzZXMuZmlsdGVyKGNsYXp6ID0+IHtcbiAgICAgICAgICByZXR1cm4gIWRpc2FibGVkRm9yQ2xhc3Nlcy5pbmNsdWRlcyhjbGF6ei5jbGFzc05hbWUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5pc1VzZXJzQ2xhc3NEaXNhYmxlZCA9ICFpbmNsdWRlZENsYXNzZXMuc29tZShjbGF6eiA9PiB7XG4gICAgICAgIHJldHVybiBjbGF6ei5jbGFzc05hbWUgPT09ICdfVXNlcic7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGluY2x1ZGVkQ2xhc3NlcztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGFsbENsYXNzZXM7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHJldHVybnMgYSBsaXN0IG9mIHR1cGxlc1xuICAgKiB0aGF0IHByb3ZpZGUgdGhlIHBhcnNlQ2xhc3MgYWxvbmcgd2l0aFxuICAgKiBpdHMgcGFyc2VDbGFzc0NvbmZpZyB3aGVyZSBwcm92aWRlZC5cbiAgICovXG4gIF9nZXRQYXJzZUNsYXNzZXNXaXRoQ29uZmlnKFxuICAgIHBhcnNlQ2xhc3NlcyxcbiAgICBwYXJzZUdyYXBoUUxDb25maWc6IFBhcnNlR3JhcGhRTENvbmZpZ1xuICApIHtcbiAgICBjb25zdCB7IGNsYXNzQ29uZmlncyB9ID0gcGFyc2VHcmFwaFFMQ29uZmlnO1xuXG4gICAgLy8gTWFrZSBzdXJlcyB0aGF0IHRoZSBkZWZhdWx0IGNsYXNzZXMgYW5kIGNsYXNzZXMgdGhhdFxuICAgIC8vIHN0YXJ0cyB3aXRoIGNhcGl0YWxpemVkIGxldHRlciB3aWxsIGJlIGdlbmVyYXRlZCBmaXJzdC5cbiAgICBjb25zdCBzb3J0Q2xhc3NlcyA9IChhLCBiKSA9PiB7XG4gICAgICBhID0gYS5jbGFzc05hbWU7XG4gICAgICBiID0gYi5jbGFzc05hbWU7XG4gICAgICBpZiAoYVswXSA9PT0gJ18nKSB7XG4gICAgICAgIGlmIChiWzBdICE9PSAnXycpIHtcbiAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChiWzBdID09PSAnXycpIHtcbiAgICAgICAgaWYgKGFbMF0gIT09ICdfJykge1xuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH0gZWxzZSBpZiAoYSA8IGIpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBwYXJzZUNsYXNzZXMuc29ydChzb3J0Q2xhc3NlcykubWFwKHBhcnNlQ2xhc3MgPT4ge1xuICAgICAgbGV0IHBhcnNlQ2xhc3NDb25maWc7XG4gICAgICBpZiAoY2xhc3NDb25maWdzKSB7XG4gICAgICAgIHBhcnNlQ2xhc3NDb25maWcgPSBjbGFzc0NvbmZpZ3MuZmluZChcbiAgICAgICAgICBjID0+IGMuY2xhc3NOYW1lID09PSBwYXJzZUNsYXNzLmNsYXNzTmFtZVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnXTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIF9nZXRGdW5jdGlvbk5hbWVzKCkge1xuICAgIHJldHVybiBhd2FpdCBnZXRGdW5jdGlvbk5hbWVzKHRoaXMuYXBwSWQpLmZpbHRlcihmdW5jdGlvbk5hbWUgPT4ge1xuICAgICAgaWYgKC9eW19hLXpBLVpdW19hLXpBLVowLTldKiQvLnRlc3QoZnVuY3Rpb25OYW1lKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubG9nLndhcm4oXG4gICAgICAgICAgYEZ1bmN0aW9uICR7ZnVuY3Rpb25OYW1lfSBjb3VsZCBub3QgYmUgYWRkZWQgdG8gdGhlIGF1dG8gc2NoZW1hIGJlY2F1c2UgR3JhcGhRTCBuYW1lcyBtdXN0IG1hdGNoIC9eW19hLXpBLVpdW19hLXpBLVowLTldKiQvLmBcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBmb3IgY2hhbmdlcyB0byB0aGUgcGFyc2VDbGFzc2VzXG4gICAqIG9iamVjdHMgKGkuZS4gZGF0YWJhc2Ugc2NoZW1hKSBvciB0b1xuICAgKiB0aGUgcGFyc2VHcmFwaFFMQ29uZmlnIG9iamVjdC4gSWYgbm9cbiAgICogY2hhbmdlcyBhcmUgZm91bmQsIHJldHVybiB0cnVlO1xuICAgKi9cbiAgX2hhc1NjaGVtYUlucHV0Q2hhbmdlZChwYXJhbXM6IHtcbiAgICBwYXJzZUNsYXNzZXM6IGFueSxcbiAgICBwYXJzZUNsYXNzZXNTdHJpbmc6IHN0cmluZyxcbiAgICBwYXJzZUdyYXBoUUxDb25maWc6ID9QYXJzZUdyYXBoUUxDb25maWcsXG4gICAgZnVuY3Rpb25OYW1lc1N0cmluZzogc3RyaW5nLFxuICB9KTogYm9vbGVhbiB7XG4gICAgY29uc3Qge1xuICAgICAgcGFyc2VDbGFzc2VzLFxuICAgICAgcGFyc2VDbGFzc2VzU3RyaW5nLFxuICAgICAgcGFyc2VHcmFwaFFMQ29uZmlnLFxuICAgICAgZnVuY3Rpb25OYW1lc1N0cmluZyxcbiAgICB9ID0gcGFyYW1zO1xuXG4gICAgaWYgKFxuICAgICAgSlNPTi5zdHJpbmdpZnkodGhpcy5wYXJzZUdyYXBoUUxDb25maWcpID09PVxuICAgICAgICBKU09OLnN0cmluZ2lmeShwYXJzZUdyYXBoUUxDb25maWcpICYmXG4gICAgICB0aGlzLmZ1bmN0aW9uTmFtZXNTdHJpbmcgPT09IGZ1bmN0aW9uTmFtZXNTdHJpbmdcbiAgICApIHtcbiAgICAgIGlmICh0aGlzLnBhcnNlQ2xhc3NlcyA9PT0gcGFyc2VDbGFzc2VzKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMucGFyc2VDbGFzc2VzU3RyaW5nID09PSBwYXJzZUNsYXNzZXNTdHJpbmcpIHtcbiAgICAgICAgdGhpcy5wYXJzZUNsYXNzZXMgPSBwYXJzZUNsYXNzZXM7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufVxuXG5leHBvcnQgeyBQYXJzZUdyYXBoUUxTY2hlbWEgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/ParseGraphQLServer.js b/lib/GraphQL/ParseGraphQLServer.js new file mode 100644 index 0000000000..145b8204f6 --- /dev/null +++ b/lib/GraphQL/ParseGraphQLServer.js @@ -0,0 +1,139 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseGraphQLServer = void 0; + +var _cors = _interopRequireDefault(require("cors")); + +var _bodyParser = _interopRequireDefault(require("body-parser")); + +var _graphqlUpload = require("graphql-upload"); + +var _expressApollo = require("apollo-server-express/dist/expressApollo"); + +var _graphqlPlaygroundHtml = require("@apollographql/graphql-playground-html"); + +var _graphql = require("graphql"); + +var _subscriptionsTransportWs = require("subscriptions-transport-ws"); + +var _middlewares = require("../middlewares"); + +var _requiredParameter = _interopRequireDefault(require("../requiredParameter")); + +var _logger = _interopRequireDefault(require("../logger")); + +var _ParseGraphQLSchema = require("./ParseGraphQLSchema"); + +var _ParseGraphQLController = _interopRequireWildcard(require("../Controllers/ParseGraphQLController")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class ParseGraphQLServer { + constructor(parseServer, config) { + this.parseServer = parseServer || (0, _requiredParameter.default)('You must provide a parseServer instance!'); + + if (!config || !config.graphQLPath) { + (0, _requiredParameter.default)('You must provide a config.graphQLPath!'); + } + + this.config = config; + this.parseGraphQLController = this.parseServer.config.parseGraphQLController; + this.log = this.parseServer.config && this.parseServer.config.loggerController || _logger.default; + this.parseGraphQLSchema = new _ParseGraphQLSchema.ParseGraphQLSchema({ + parseGraphQLController: this.parseGraphQLController, + databaseController: this.parseServer.config.databaseController, + log: this.log, + graphQLCustomTypeDefs: this.config.graphQLCustomTypeDefs, + appId: this.parseServer.config.appId + }); + } + + async _getGraphQLOptions(req) { + try { + return { + schema: await this.parseGraphQLSchema.load(), + context: { + info: req.info, + config: req.config, + auth: req.auth + }, + formatError: error => { + // Allow to console.log here to debug + return error; + } + }; + } catch (e) { + this.log.error(e.stack || typeof e.toString === 'function' && e.toString() || e); + throw e; + } + } + + _transformMaxUploadSizeToBytes(maxUploadSize) { + const unitMap = { + kb: 1, + mb: 2, + gb: 3 + }; + return Number(maxUploadSize.slice(0, -2)) * Math.pow(1024, unitMap[maxUploadSize.slice(-2).toLowerCase()]); + } + + applyGraphQL(app) { + if (!app || !app.use) { + (0, _requiredParameter.default)('You must provide an Express.js app instance!'); + } + + app.use(this.config.graphQLPath, (0, _graphqlUpload.graphqlUploadExpress)({ + maxFileSize: this._transformMaxUploadSizeToBytes(this.parseServer.config.maxUploadSize || '20mb') + })); + app.use(this.config.graphQLPath, (0, _cors.default)()); + app.use(this.config.graphQLPath, _bodyParser.default.json()); + app.use(this.config.graphQLPath, _middlewares.handleParseHeaders); + app.use(this.config.graphQLPath, _middlewares.handleParseErrors); + app.use(this.config.graphQLPath, (0, _expressApollo.graphqlExpress)(async req => await this._getGraphQLOptions(req))); + } + + applyPlayground(app) { + if (!app || !app.get) { + (0, _requiredParameter.default)('You must provide an Express.js app instance!'); + } + + app.get(this.config.playgroundPath || (0, _requiredParameter.default)('You must provide a config.playgroundPath to applyPlayground!'), (_req, res) => { + res.setHeader('Content-Type', 'text/html'); + res.write((0, _graphqlPlaygroundHtml.renderPlaygroundPage)({ + endpoint: this.config.graphQLPath, + subscriptionEndpoint: this.config.subscriptionsPath, + headers: { + 'X-Parse-Application-Id': this.parseServer.config.appId, + 'X-Parse-Master-Key': this.parseServer.config.masterKey + } + })); + res.end(); + }); + } + + createSubscriptions(server) { + _subscriptionsTransportWs.SubscriptionServer.create({ + execute: _graphql.execute, + subscribe: _graphql.subscribe, + onOperation: async (_message, params, webSocket) => Object.assign({}, params, (await this._getGraphQLOptions(webSocket.upgradeReq))) + }, { + server, + path: this.config.subscriptionsPath || (0, _requiredParameter.default)('You must provide a config.subscriptionsPath to createSubscriptions!') + }); + } + + setGraphQLConfig(graphQLConfig) { + return this.parseGraphQLController.updateGraphQLConfig(graphQLConfig); + } + +} + +exports.ParseGraphQLServer = ParseGraphQLServer; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HcmFwaFFML1BhcnNlR3JhcGhRTFNlcnZlci5qcyJdLCJuYW1lcyI6WyJQYXJzZUdyYXBoUUxTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsInBhcnNlU2VydmVyIiwiY29uZmlnIiwiZ3JhcGhRTFBhdGgiLCJwYXJzZUdyYXBoUUxDb250cm9sbGVyIiwibG9nIiwibG9nZ2VyQ29udHJvbGxlciIsImRlZmF1bHRMb2dnZXIiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJQYXJzZUdyYXBoUUxTY2hlbWEiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJncmFwaFFMQ3VzdG9tVHlwZURlZnMiLCJhcHBJZCIsIl9nZXRHcmFwaFFMT3B0aW9ucyIsInJlcSIsInNjaGVtYSIsImxvYWQiLCJjb250ZXh0IiwiaW5mbyIsImF1dGgiLCJmb3JtYXRFcnJvciIsImVycm9yIiwiZSIsInN0YWNrIiwidG9TdHJpbmciLCJfdHJhbnNmb3JtTWF4VXBsb2FkU2l6ZVRvQnl0ZXMiLCJtYXhVcGxvYWRTaXplIiwidW5pdE1hcCIsImtiIiwibWIiLCJnYiIsIk51bWJlciIsInNsaWNlIiwiTWF0aCIsInBvdyIsInRvTG93ZXJDYXNlIiwiYXBwbHlHcmFwaFFMIiwiYXBwIiwidXNlIiwibWF4RmlsZVNpemUiLCJib2R5UGFyc2VyIiwianNvbiIsImhhbmRsZVBhcnNlSGVhZGVycyIsImhhbmRsZVBhcnNlRXJyb3JzIiwiYXBwbHlQbGF5Z3JvdW5kIiwiZ2V0IiwicGxheWdyb3VuZFBhdGgiLCJfcmVxIiwicmVzIiwic2V0SGVhZGVyIiwid3JpdGUiLCJlbmRwb2ludCIsInN1YnNjcmlwdGlvbkVuZHBvaW50Iiwic3Vic2NyaXB0aW9uc1BhdGgiLCJoZWFkZXJzIiwibWFzdGVyS2V5IiwiZW5kIiwiY3JlYXRlU3Vic2NyaXB0aW9ucyIsInNlcnZlciIsIlN1YnNjcmlwdGlvblNlcnZlciIsImNyZWF0ZSIsImV4ZWN1dGUiLCJzdWJzY3JpYmUiLCJvbk9wZXJhdGlvbiIsIl9tZXNzYWdlIiwicGFyYW1zIiwid2ViU29ja2V0IiwiT2JqZWN0IiwiYXNzaWduIiwidXBncmFkZVJlcSIsInBhdGgiLCJzZXRHcmFwaFFMQ29uZmlnIiwiZ3JhcGhRTENvbmZpZyIsInVwZGF0ZUdyYXBoUUxDb25maWciXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFJQSxNQUFNQSxrQkFBTixDQUF5QjtBQUd2QkMsRUFBQUEsV0FBVyxDQUFDQyxXQUFELEVBQWNDLE1BQWQsRUFBc0I7QUFDL0IsU0FBS0QsV0FBTCxHQUNFQSxXQUFXLElBQ1gsZ0NBQWtCLDBDQUFsQixDQUZGOztBQUdBLFFBQUksQ0FBQ0MsTUFBRCxJQUFXLENBQUNBLE1BQU0sQ0FBQ0MsV0FBdkIsRUFBb0M7QUFDbEMsc0NBQWtCLHdDQUFsQjtBQUNEOztBQUNELFNBQUtELE1BQUwsR0FBY0EsTUFBZDtBQUNBLFNBQUtFLHNCQUFMLEdBQThCLEtBQUtILFdBQUwsQ0FBaUJDLE1BQWpCLENBQXdCRSxzQkFBdEQ7QUFDQSxTQUFLQyxHQUFMLEdBQ0csS0FBS0osV0FBTCxDQUFpQkMsTUFBakIsSUFBMkIsS0FBS0QsV0FBTCxDQUFpQkMsTUFBakIsQ0FBd0JJLGdCQUFwRCxJQUNBQyxlQUZGO0FBR0EsU0FBS0Msa0JBQUwsR0FBMEIsSUFBSUMsc0NBQUosQ0FBdUI7QUFDL0NMLE1BQUFBLHNCQUFzQixFQUFFLEtBQUtBLHNCQURrQjtBQUUvQ00sTUFBQUEsa0JBQWtCLEVBQUUsS0FBS1QsV0FBTCxDQUFpQkMsTUFBakIsQ0FBd0JRLGtCQUZHO0FBRy9DTCxNQUFBQSxHQUFHLEVBQUUsS0FBS0EsR0FIcUM7QUFJL0NNLE1BQUFBLHFCQUFxQixFQUFFLEtBQUtULE1BQUwsQ0FBWVMscUJBSlk7QUFLL0NDLE1BQUFBLEtBQUssRUFBRSxLQUFLWCxXQUFMLENBQWlCQyxNQUFqQixDQUF3QlU7QUFMZ0IsS0FBdkIs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IjpbImltcG9ydCBjb3JzTWlkZGxld2FyZSBmcm9tICdjb3JzJztcbmltcG9ydCBib2R5UGFyc2VyIGZyb20gJ2JvZHktcGFyc2VyJztcbmltcG9ydCB7IGdyYXBocWxVcGxvYWRFeHByZXNzIH0gZnJvbSAnZ3JhcGhxbC11cGxvYWQnO1xuaW1wb3J0IHsgZ3JhcGhxbEV4cHJlc3MgfSBmcm9tICdhcG9sbG8tc2VydmVyLWV4cHJlc3MvZGlzdC9leHByZXNzQXBvbGxvJztcbmltcG9ydCB7IHJlbmRlclBsYXlncm91bmRQYWdlIH0gZnJvbSAnQGFwb2xsb2dyYXBocWwvZ3JhcGhxbC1wbGF5Z3JvdW5kLWh0bWwnO1xuaW1wb3J0IHsgZXhlY3V0ZSwgc3Vic2NyaWJlIH0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb25TZXJ2ZXIgfSBmcm9tICdzdWJzY3JpcHRpb25zLXRyYW5zcG9ydC13cyc7XG5pbXBvcnQgeyBoYW5kbGVQYXJzZUVycm9ycywgaGFuZGxlUGFyc2VIZWFkZXJzIH0gZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuaW1wb3J0IHJlcXVpcmVkUGFyYW1ldGVyIGZyb20gJy4uL3JlcXVpcmVkUGFyYW1ldGVyJztcbmltcG9ydCBkZWZhdWx0TG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgeyBQYXJzZUdyYXBoUUxTY2hlbWEgfSBmcm9tICcuL1BhcnNlR3JhcGhRTFNjaGVtYSc7XG5pbXBvcnQgUGFyc2VHcmFwaFFMQ29udHJvbGxlciwge1xuICBQYXJzZUdyYXBoUUxDb25maWcsXG59IGZyb20gJy4uL0NvbnRyb2xsZXJzL1BhcnNlR3JhcGhRTENvbnRyb2xsZXInO1xuXG5jbGFzcyBQYXJzZUdyYXBoUUxTZXJ2ZXIge1xuICBwYXJzZUdyYXBoUUxDb250cm9sbGVyOiBQYXJzZUdyYXBoUUxDb250cm9sbGVyO1xuXG4gIGNvbnN0cnVjdG9yKHBhcnNlU2VydmVyLCBjb25maWcpIHtcbiAgICB0aGlzLnBhcnNlU2VydmVyID1cbiAgICAgIHBhcnNlU2VydmVyIHx8XG4gICAgICByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIHBhcnNlU2VydmVyIGluc3RhbmNlIScpO1xuICAgIGlmICghY29uZmlnIHx8ICFjb25maWcuZ3JhcGhRTFBhdGgpIHtcbiAgICAgIHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIGEgY29uZmlnLmdyYXBoUUxQYXRoIScpO1xuICAgIH1cbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICB0aGlzLnBhcnNlR3JhcGhRTENvbnRyb2xsZXIgPSB0aGlzLnBhcnNlU2VydmVyLmNvbmZpZy5wYXJzZUdyYXBoUUxDb250cm9sbGVyO1xuICAgIHRoaXMubG9nID1cbiAgICAgICh0aGlzLnBhcnNlU2VydmVyLmNvbmZpZyAmJiB0aGlzLnBhcnNlU2VydmVyLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyKSB8fFxuICAgICAgZGVmYXVsdExvZ2dlcjtcbiAgICB0aGlzLnBhcnNlR3JhcGhRTFNjaGVtYSA9IG5ldyBQYXJzZUdyYXBoUUxTY2hlbWEoe1xuICAgICAgcGFyc2VHcmFwaFFMQ29udHJvbGxlcjogdGhpcy5wYXJzZUdyYXBoUUxDb250cm9sbGVyLFxuICAgICAgZGF0YWJhc2VDb250cm9sbGVyOiB0aGlzLnBhcnNlU2VydmVyLmNvbmZpZy5kYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgICBsb2c6IHRoaXMubG9nLFxuICAgICAgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzOiB0aGlzLmNvbmZpZy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMsXG4gICAgICBhcHBJZDogdGhpcy5wYXJzZVNlcnZlci5jb25maWcuYXBwSWQsXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBfZ2V0R3JhcGhRTE9wdGlvbnMocmVxKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNjaGVtYTogYXdhaXQgdGhpcy5wYXJzZUdyYXBoUUxTY2hlbWEubG9hZCgpLFxuICAgICAgICBjb250ZXh0OiB7XG4gICAgICAgICAgaW5mbzogcmVxLmluZm8sXG4gICAgICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgICAgIGF1dGg6IHJlcS5hdXRoLFxuICAgICAgICB9LFxuICAgICAgICBmb3JtYXRFcnJvcjogZXJyb3IgPT4ge1xuICAgICAgICAgIC8vIEFsbG93IHRvIGNvbnNvbGUubG9nIGhlcmUgdG8gZGVidWdcbiAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMubG9nLmVycm9yKFxuICAgICAgICBlLnN0YWNrIHx8ICh0eXBlb2YgZS50b1N0cmluZyA9PT0gJ2Z1bmN0aW9uJyAmJiBlLnRvU3RyaW5nKCkpIHx8IGVcbiAgICAgICk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIF90cmFuc2Zvcm1NYXhVcGxvYWRTaXplVG9CeXRlcyhtYXhVcGxvYWRTaXplKSB7XG4gICAgY29uc3QgdW5pdE1hcCA9IHtcbiAgICAgIGtiOiAxLFxuICAgICAgbWI6IDIsXG4gICAgICBnYjogMyxcbiAgICB9O1xuXG4gICAgcmV0dXJuIChcbiAgICAgIE51bWJlcihtYXhVcGxvYWRTaXplLnNsaWNlKDAsIC0yKSkgKlxuICAgICAgTWF0aC5wb3coMTAyNCwgdW5pdE1hcFttYXhVcGxvYWRTaXplLnNsaWNlKC0yKS50b0xvd2VyQ2FzZSgpXSlcbiAgICApO1xuICB9XG5cbiAgYXBwbHlHcmFwaFFMKGFwcCkge1xuICAgIGlmICghYXBwIHx8ICFhcHAudXNlKSB7XG4gICAgICByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhbiBFeHByZXNzLmpzIGFwcCBpbnN0YW5jZSEnKTtcbiAgICB9XG5cbiAgICBhcHAudXNlKFxuICAgICAgdGhpcy5jb25maWcuZ3JhcGhRTFBhdGgsXG4gICAgICBncmFwaHFsVXBsb2FkRXhwcmVzcyh7XG4gICAgICAgIG1heEZpbGVTaXplOiB0aGlzLl90cmFuc2Zvcm1NYXhVcGxvYWRTaXplVG9CeXRlcyhcbiAgICAgICAgICB0aGlzLnBhcnNlU2VydmVyLmNvbmZpZy5tYXhVcGxvYWRTaXplIHx8ICcyMG1iJ1xuICAgICAgICApLFxuICAgICAgfSlcbiAgICApO1xuICAgIGFwcC51c2UodGhpcy5jb25maWcuZ3JhcGhRTFBhdGgsIGNvcnNNaWRkbGV3YXJlKCkpO1xuICAgIGFwcC51c2UodGhpcy5jb25maWcuZ3JhcGhRTFBhdGgsIGJvZHlQYXJzZXIuanNvbigpKTtcbiAgICBhcHAudXNlKHRoaXMuY29uZmlnLmdyYXBoUUxQYXRoLCBoYW5kbGVQYXJzZUhlYWRlcnMpO1xuICAgIGFwcC51c2UodGhpcy5jb25maWcuZ3JhcGhRTFBhdGgsIGhhbmRsZVBhcnNlRXJyb3JzKTtcbiAgICBhcHAudXNlKFxuICAgICAgdGhpcy5jb25maWcuZ3JhcGhRTFBhdGgsXG4gICAgICBncmFwaHFsRXhwcmVzcyhhc3luYyByZXEgPT4gYXdhaXQgdGhpcy5fZ2V0R3JhcGhRTE9wdGlvbnMocmVxKSlcbiAgICApO1xuICB9XG5cbiAgYXBwbHlQbGF5Z3JvdW5kKGFwcCkge1xuICAgIGlmICghYXBwIHx8ICFhcHAuZ2V0KSB7XG4gICAgICByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhbiBFeHByZXNzLmpzIGFwcCBpbnN0YW5jZSEnKTtcbiAgICB9XG4gICAgYXBwLmdldChcbiAgICAgIHRoaXMuY29uZmlnLnBsYXlncm91bmRQYXRoIHx8XG4gICAgICAgIHJlcXVpcmVkUGFyYW1ldGVyKFxuICAgICAgICAgICdZb3UgbXVzdCBwcm92aWRlIGEgY29uZmlnLnBsYXlncm91bmRQYXRoIHRvIGFwcGx5UGxheWdyb3VuZCEnXG4gICAgICAgICksXG4gICAgICAoX3JlcSwgcmVzKSA9PiB7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L2h0bWwnKTtcbiAgICAgICAgcmVzLndyaXRlKFxuICAgICAgICAgIHJlbmRlclBsYXlncm91bmRQYWdlKHtcbiAgICAgICAgICAgIGVuZHBvaW50OiB0aGlzLmNvbmZpZy5ncmFwaFFMUGF0aCxcbiAgICAgICAgICAgIHN1YnNjcmlwdGlvbkVuZHBvaW50OiB0aGlzLmNvbmZpZy5zdWJzY3JpcHRpb25zUGF0aCxcbiAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgJ1gtUGFyc2UtQXBwbGljYXRpb24tSWQnOiB0aGlzLnBhcnNlU2VydmVyLmNvbmZpZy5hcHBJZCxcbiAgICAgICAgICAgICAgJ1gtUGFyc2UtTWFzdGVyLUtleSc6IHRoaXMucGFyc2VTZXJ2ZXIuY29uZmlnLm1hc3RlcktleSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgICAgcmVzLmVuZCgpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBjcmVhdGVTdWJzY3JpcHRpb25zKHNlcnZlcikge1xuICAgIFN1YnNjcmlwdGlvblNlcnZlci5jcmVhdGUoXG4gICAgICB7XG4gICAgICAgIGV4ZWN1dGUsXG4gICAgICAgIHN1YnNjcmliZSxcbiAgICAgICAgb25PcGVyYXRpb246IGFzeW5jIChfbWVzc2FnZSwgcGFyYW1zLCB3ZWJTb2NrZXQpID0+XG4gICAgICAgICAgT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZ2V0R3JhcGhRTE9wdGlvbnMod2ViU29ja2V0LnVwZ3JhZGVSZXEpXG4gICAgICAgICAgKSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcGF0aDpcbiAgICAgICAgICB0aGlzLmNvbmZpZy5zdWJzY3JpcHRpb25zUGF0aCB8fFxuICAgICAgICAgIHJlcXVpcmVkUGFyYW1ldGVyKFxuICAgICAgICAgICAgJ1lvdSBtdXN0IHByb3ZpZGUgYSBjb25maWcuc3Vic2NyaXB0aW9uc1BhdGggdG8gY3JlYXRlU3Vic2NyaXB0aW9ucyEnXG4gICAgICAgICAgKSxcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgc2V0R3JhcGhRTENvbmZpZyhncmFwaFFMQ29uZmlnOiBQYXJzZUdyYXBoUUxDb25maWcpOiBQcm9taXNlIHtcbiAgICByZXR1cm4gdGhpcy5wYXJzZUdyYXBoUUxDb250cm9sbGVyLnVwZGF0ZUdyYXBoUUxDb25maWcoZ3JhcGhRTENvbmZpZyk7XG4gIH1cbn1cblxuZXhwb3J0IHsgUGFyc2VHcmFwaFFMU2VydmVyIH07XG4iXX0= \ No newline at end of file diff --git a/lib/GraphQL/helpers/objectsMutations.js b/lib/GraphQL/helpers/objectsMutations.js new file mode 100644 index 0000000000..cd0f12ff92 --- /dev/null +++ b/lib/GraphQL/helpers/objectsMutations.js @@ -0,0 +1,40 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.deleteObject = exports.updateObject = exports.createObject = void 0; + +var _rest = _interopRequireDefault(require("../../rest")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const createObject = async (className, fields, config, auth, info) => { + if (!fields) { + fields = {}; + } + + return (await _rest.default.create(config, auth, className, fields, info.clientSDK)).response; +}; + +exports.createObject = createObject; + +const updateObject = async (className, objectId, fields, config, auth, info) => { + if (!fields) { + fields = {}; + } + + return (await _rest.default.update(config, auth, className, { + objectId + }, fields, info.clientSDK)).response; +}; + +exports.updateObject = updateObject; + +const deleteObject = async (className, objectId, config, auth, info) => { + await _rest.default.del(config, auth, className, objectId, info.clientSDK); + return true; +}; + +exports.deleteObject = deleteObject; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2hlbHBlcnMvb2JqZWN0c011dGF0aW9ucy5qcyJdLCJuYW1lcyI6WyJjcmVhdGVPYmplY3QiLCJjbGFzc05hbWUiLCJmaWVsZHMiLCJjb25maWciLCJhdXRoIiwiaW5mbyIsInJlc3QiLCJjcmVhdGUiLCJjbGllbnRTREsiLCJyZXNwb25zZSIsInVwZGF0ZU9iamVjdCIsIm9iamVjdElkIiwidXBkYXRlIiwiZGVsZXRlT2JqZWN0IiwiZGVsIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFFQSxNQUFNQSxZQUFZLEdBQUcsT0FBT0MsU0FBUCxFQUFrQkMsTUFBbEIsRUFBMEJDLE1BQTFCLEVBQWtDQyxJQUFsQyxFQUF3Q0MsSUFBeEMsS0FBaUQ7QUFDcEUsTUFBSSxDQUFDSCxNQUFMLEVBQWE7QUFDWEEsSUFBQUEsTUFBTSxHQUFHLEVBQVQ7QUFDRDs7QUFFRCxTQUFPLENBQUMsTUFBTUksY0FBS0MsTUFBTCxDQUFZSixNQUFaLEVBQW9CQyxJQUFwQixFQUEwQkgsU0FBMUIsRUFBcUNDLE1BQXJDLEVBQTZDRyxJQUFJLENBQUNHLFNBQWxELENBQVAsRUFDSkMsUUFESDtBQUVELENBUEQ7Ozs7QUFTQSxNQUFNQyxZQUFZLEdBQUcsT0FDbkJULFNBRG1CLEVBRW5CVSxRQUZtQixFQUduQlQsTUFIbUIsRUFJbkJDLE1BSm1CLEVBS25CQyxJQUxtQixFQU1uQkMsSUFObUIsS0FPaEI7QUFDSCxNQUFJLENBQUNILE1BQUwsRUFBYTtBQUNYQSxJQUFBQSxNQUFNLEdBQUcsRUFBVDtBQUNEOztBQUVELFNBQU8sQ0FBQyxNQUFNSSxjQUFLTSxNQUFMLENBQ1pULE1BRFksRUFFWkMsSUFGWSxFQUdaSCxTQUhZLEVBSVo7QUFBRVUsSUFBQUE7QUFBRixHQUpZLEVBS1pULE1BTFksRUFNWkcsSUFBSSxDQUFDRyxTQU5PLENBQVAsRUFPSkMsUUFQSDtBQVFELENBcEJEOzs7O0FBc0JBLE1BQU1JLFlBQVksR0FBRyxPQUFPWixTQUFQLEVBQWtCVSxRQUFsQixFQUE0QlIsTUFBNUIsRUFBb0NDLElBQXBDLEVBQTBDQyxJQUExQyxLQUFtRDtBQUN0RSxRQUFNQyxjQUFLUSxHQUFMLENBQVNYLE1BQVQsRUFBaUJDLElBQWpCLEVBQXVCSCxTQUF2QixFQUFrQ1UsUUFBbEMsRUFBNENOLElBQUksQ0FBQ0csU0FBakQsQ0FBTjtBQUNBLFNBQU8sSUFBUDtBQUNELENBSEQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcmVzdCBmcm9tICcuLi8uLi9yZXN0JztcblxuY29uc3QgY3JlYXRlT2JqZWN0ID0gYXN5bmMgKGNsYXNzTmFtZSwgZmllbGRzLCBjb25maWcsIGF1dGgsIGluZm8pID0+IHtcbiAgaWYgKCFmaWVsZHMpIHtcbiAgICBmaWVsZHMgPSB7fTtcbiAgfVxuXG4gIHJldHVybiAoYXdhaXQgcmVzdC5jcmVhdGUoY29uZmlnLCBhdXRoLCBjbGFzc05hbWUsIGZpZWxkcywgaW5mby5jbGllbnRTREspKVxuICAgIC5yZXNwb25zZTtcbn07XG5cbmNvbnN0IHVwZGF0ZU9iamVjdCA9IGFzeW5jIChcbiAgY2xhc3NOYW1lLFxuICBvYmplY3RJZCxcbiAgZmllbGRzLFxuICBjb25maWcsXG4gIGF1dGgsXG4gIGluZm9cbikgPT4ge1xuICBpZiAoIWZpZWxkcykge1xuICAgIGZpZWxkcyA9IHt9O1xuICB9XG5cbiAgcmV0dXJuIChhd2FpdCByZXN0LnVwZGF0ZShcbiAgICBjb25maWcsXG4gICAgYXV0aCxcbiAgICBjbGFzc05hbWUsXG4gICAgeyBvYmplY3RJZCB9LFxuICAgIGZpZWxkcyxcbiAgICBpbmZvLmNsaWVudFNES1xuICApKS5yZXNwb25zZTtcbn07XG5cbmNvbnN0IGRlbGV0ZU9iamVjdCA9IGFzeW5jIChjbGFzc05hbWUsIG9iamVjdElkLCBjb25maWcsIGF1dGgsIGluZm8pID0+IHtcbiAgYXdhaXQgcmVzdC5kZWwoY29uZmlnLCBhdXRoLCBjbGFzc05hbWUsIG9iamVjdElkLCBpbmZvLmNsaWVudFNESyk7XG4gIHJldHVybiB0cnVlO1xufTtcblxuZXhwb3J0IHsgY3JlYXRlT2JqZWN0LCB1cGRhdGVPYmplY3QsIGRlbGV0ZU9iamVjdCB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/helpers/objectsQueries.js b/lib/GraphQL/helpers/objectsQueries.js new file mode 100644 index 0000000000..4b3a683c4f --- /dev/null +++ b/lib/GraphQL/helpers/objectsQueries.js @@ -0,0 +1,115 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.findObjects = exports.getObject = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _rest = _interopRequireDefault(require("../../rest")); + +var _query = require("../transformers/query"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const getObject = async (className, objectId, keys, include, readPreference, includeReadPreference, config, auth, info) => { + const options = {}; + + if (keys) { + options.keys = keys; + } + + if (include) { + options.include = include; + + if (includeReadPreference) { + options.includeReadPreference = includeReadPreference; + } + } + + if (readPreference) { + options.readPreference = readPreference; + } + + const response = await _rest.default.get(config, auth, className, objectId, options, info.clientSDK); + + if (!response.results || response.results.length == 0) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + + const object = response.results[0]; + + if (className === '_User') { + delete object.sessionToken; + } + + return object; +}; + +exports.getObject = getObject; + +const findObjects = async (className, where, order, skip, limit, keys, include, includeAll, readPreference, includeReadPreference, subqueryReadPreference, config, auth, info, selectedFields, fields) => { + if (!where) { + where = {}; + } + + (0, _query.transformQueryInputToParse)(where, fields); + const options = {}; + + if (selectedFields.includes('results')) { + if (limit || limit === 0) { + options.limit = limit; + } + + if (options.limit !== 0) { + if (order) { + options.order = order; + } + + if (skip) { + options.skip = skip; + } + + if (config.maxLimit && options.limit > config.maxLimit) { + // Silently replace the limit on the query with the max configured + options.limit = config.maxLimit; + } + + if (keys) { + options.keys = keys; + } + + if (includeAll === true) { + options.includeAll = includeAll; + } + + if (!options.includeAll && include) { + options.include = include; + } + + if ((options.includeAll || options.include) && includeReadPreference) { + options.includeReadPreference = includeReadPreference; + } + } + } else { + options.limit = 0; + } + + if (selectedFields.includes('count')) { + options.count = true; + } + + if (readPreference) { + options.readPreference = readPreference; + } + + if (Object.keys(where).length > 0 && subqueryReadPreference) { + options.subqueryReadPreference = subqueryReadPreference; + } + + return await _rest.default.find(config, auth, className, where, options, info.clientSDK); +}; + +exports.findObjects = findObjects; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2hlbHBlcnMvb2JqZWN0c1F1ZXJpZXMuanMiXSwibmFtZXMiOlsiZ2V0T2JqZWN0IiwiY2xhc3NOYW1lIiwib2JqZWN0SWQiLCJrZXlzIiwiaW5jbHVkZSIsInJlYWRQcmVmZXJlbmNlIiwiaW5jbHVkZVJlYWRQcmVmZXJlbmNlIiwiY29uZmlnIiwiYXV0aCIsImluZm8iLCJvcHRpb25zIiwicmVzcG9uc2UiLCJyZXN0IiwiZ2V0IiwiY2xpZW50U0RLIiwicmVzdWx0cyIsImxlbmd0aCIsIlBhcnNlIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwib2JqZWN0Iiwic2Vzc2lvblRva2VuIiwiZmluZE9iamVjdHMiLCJ3aGVyZSIsIm9yZGVyIiwic2tpcCIsImxpbWl0IiwiaW5jbHVkZUFsbCIsInN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UiLCJzZWxlY3RlZEZpZWxkcyIsImZpZWxkcyIsImluY2x1ZGVzIiwibWF4TGltaXQiLCJjb3VudCIsIk9iamVjdCIsImZpbmQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLFNBQVMsR0FBRyxPQUNoQkMsU0FEZ0IsRUFFaEJDLFFBRmdCLEVBR2hCQyxJQUhnQixFQUloQkMsT0FKZ0IsRUFLaEJDLGNBTGdCLEVBTWhCQyxxQkFOZ0IsRUFPaEJDLE1BUGdCLEVBUWhCQyxJQVJnQixFQVNoQkMsSUFUZ0IsS0FVYjtBQUNILFFBQU1DLE9BQU8sR0FBRyxFQUFoQjs7QUFDQSxNQUFJUCxJQUFKLEVBQVU7QUFDUk8sSUFBQUEsT0FBTyxDQUFDUCxJQUFSLEdBQWVBLElBQWY7QUFDRDs7QUFDRCxNQUFJQyxPQUFKLEVBQWE7QUFDWE0sSUFBQUEsT0FBTyxDQUFDTixPQUFSLEdBQWtCQSxPQUFsQjs7QUFDQSxRQUFJRSxxQkFBSixFQUEyQjtBQUN6QkksTUFBQUEsT0FBTyxDQUFDSixxQkFBUixHQUFnQ0EscUJBQWhDO0FBQ0Q7QUFDRjs7QUFD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S0FBUixHQUFnQixDQUFoQjtBQUNEOztBQUVELE1BQUlHLGNBQWMsQ0FBQ0UsUUFBZixDQUF3QixPQUF4QixDQUFKLEVBQXNDO0FBQ3BDckIsSUFBQUEsT0FBTyxDQUFDdUIsS0FBUixHQUFnQixJQUFoQjtBQUNEOztBQUVELE1BQUk1QixjQUFKLEVBQW9CO0FBQ2xCSyxJQUFBQSxPQUFPLENBQUNMLGNBQVIsR0FBeUJBLGNBQXpCO0FBQ0Q7O0FBQ0QsTUFBSTZCLE1BQU0sQ0FBQy9CLElBQVAsQ0FBWW9CLEtBQVosRUFBbUJQLE1BQW5CLEdBQTRCLENBQTVCLElBQWlDWSxzQkFBckMsRUFBNkQ7QUFDM0RsQixJQUFBQSxPQUFPLENBQUNrQixzQkFBUixHQUFpQ0Esc0JBQWpDO0FBQ0Q7O0FBRUQsU0FBTyxNQUFNaEIsY0FBS3VCLElBQUwsQ0FDWDVCLE1BRFcsRUFFWEMsSUFGVyxFQUdYUCxTQUhXLEVBSVhzQixLQUpXLEVBS1hiLE9BTFcsRUFNWEQsSUFBSSxDQUFDSyxTQU5NLENBQWI7QUFRRCxDQTVFRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCByZXN0IGZyb20gJy4uLy4uL3Jlc3QnO1xuaW1wb3J0IHsgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvcXVlcnknO1xuXG5jb25zdCBnZXRPYmplY3QgPSBhc3luYyAoXG4gIGNsYXNzTmFtZSxcbiAgb2JqZWN0SWQsXG4gIGtleXMsXG4gIGluY2x1ZGUsXG4gIHJlYWRQcmVmZXJlbmNlLFxuICBpbmNsdWRlUmVhZFByZWZlcmVuY2UsXG4gIGNvbmZpZyxcbiAgYXV0aCxcbiAgaW5mb1xuKSA9PiB7XG4gIGNvbnN0IG9wdGlvbnMgPSB7fTtcbiAgaWYgKGtleXMpIHtcbiAgICBvcHRpb25zLmtleXMgPSBrZXlzO1xuICB9XG4gIGlmIChpbmNsdWRlKSB7XG4gICAgb3B0aW9ucy5pbmNsdWRlID0gaW5jbHVkZTtcbiAgICBpZiAoaW5jbHVkZVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgICBvcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZSA9IGluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgICB9XG4gIH1cbiAgaWYgKHJlYWRQcmVmZXJlbmNlKSB7XG4gICAgb3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXN0LmdldChcbiAgICBjb25maWcsXG4gICAgYXV0aCxcbiAgICBjbGFzc05hbWUsXG4gICAgb2JqZWN0SWQsXG4gICAgb3B0aW9ucyxcbiAgICBpbmZvLmNsaWVudFNES1xuICApO1xuXG4gIGlmICghcmVzcG9uc2UucmVzdWx0cyB8fCByZXNwb25zZS5yZXN1bHRzLmxlbmd0aCA9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdPYmplY3Qgbm90IGZvdW5kLicpO1xuICB9XG5cbiAgY29uc3Qgb2JqZWN0ID0gcmVzcG9uc2UucmVzdWx0c1swXTtcbiAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgIGRlbGV0ZSBvYmplY3Quc2Vzc2lvblRva2VuO1xuICB9XG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5jb25zdCBmaW5kT2JqZWN0cyA9IGFzeW5jIChcbiAgY2xhc3NOYW1lLFxuICB3aGVyZSxcbiAgb3JkZXIsXG4gIHNraXAsXG4gIGxpbWl0LFxuICBrZXlzLFxuICBpbmNsdWRlLFxuICBpbmNsdWRlQWxsLFxuICByZWFkUHJlZmVyZW5jZSxcbiAgaW5jbHVkZVJlYWRQcmVmZXJlbmNlLFxuICBzdWJxdWVyeVJlYWRQcmVmZXJlbmNlLFxuICBjb25maWcsXG4gIGF1dGgsXG4gIGluZm8sXG4gIHNlbGVjdGVkRmllbGRzLFxuICBmaWVsZHNcbikgPT4ge1xuICBpZiAoIXdoZXJlKSB7XG4gICAgd2hlcmUgPSB7fTtcbiAgfVxuICB0cmFuc2Zvcm1RdWVyeUlucHV0VG9QYXJzZSh3aGVyZSwgZmllbGRzKTtcblxuICBjb25zdCBvcHRpb25zID0ge307XG5cbiAgaWYgKHNlbGVjdGVkRmllbGRzLmluY2x1ZGVzKCdyZXN1bHRzJykpIHtcbiAgICBpZiAobGltaXQgfHwgbGltaXQgPT09IDApIHtcbiAgICAgIG9wdGlvbnMubGltaXQgPSBsaW1pdDtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMubGltaXQgIT09IDApIHtcbiAgICAgIGlmIChvcmRlcikge1xuICAgICAgICBvcHRpb25zLm9yZGVyID0gb3JkZXI7XG4gICAgICB9XG4gICAgICBpZiAoc2tpcCkge1xuICAgICAgICBvcHRpb25zLnNraXAgPSBza2lwO1xuICAgICAgfVxuICAgICAgaWYgKGNvbmZpZy5tYXhMaW1pdCAmJiBvcHRpb25zLmxpbWl0ID4gY29uZmlnLm1heExpbWl0KSB7XG4gICAgICAgIC8vIFNpbGVudGx5IHJlcGxhY2UgdGhlIGxpbWl0IG9uIHRoZSBxdWVyeSB3aXRoIHRoZSBtYXggY29uZmlndXJlZFxuICAgICAgICBvcHRpb25zLmxpbWl0ID0gY29uZmlnLm1heExpbWl0O1xuICAgICAgfVxuICAgICAgaWYgKGtleXMpIHtcbiAgICAgICAgb3B0aW9ucy5rZXlzID0ga2V5cztcbiAgICAgIH1cbiAgICAgIGlmIChpbmNsdWRlQWxsID09PSB0cnVlKSB7XG4gICAgICAgIG9wdGlvbnMuaW5jbHVkZUFsbCA9IGluY2x1ZGVBbGw7XG4gICAgICB9XG4gICAgICBpZiAoIW9wdGlvbnMuaW5jbHVkZUFsbCAmJiBpbmNsdWRlKSB7XG4gICAgICAgIG9wdGlvbnMuaW5jbHVkZSA9IGluY2x1ZGU7XG4gICAgICB9XG4gICAgICBpZiAoKG9wdGlvbnMuaW5jbHVkZUFsbCB8fCBvcHRpb25zLmluY2x1ZGUpICYmIGluY2x1ZGVSZWFkUHJlZmVyZW5jZSkge1xuICAgICAgICBvcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZSA9IGluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgb3B0aW9ucy5saW1pdCA9IDA7XG4gIH1cblxuICBpZiAoc2VsZWN0ZWRGaWVsZHMuaW5jbHVkZXMoJ2NvdW50JykpIHtcbiAgICBvcHRpb25zLmNvdW50ID0gdHJ1ZTtcbiAgfVxuXG4gIGlmIChyZWFkUHJlZmVyZW5jZSkge1xuICAgIG9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSByZWFkUHJlZmVyZW5jZTtcbiAgfVxuICBpZiAoT2JqZWN0LmtleXMod2hlcmUpLmxlbmd0aCA+IDAgJiYgc3VicXVlcnlSZWFkUHJlZmVyZW5jZSkge1xuICAgIG9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IHN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICByZXR1cm4gYXdhaXQgcmVzdC5maW5kKFxuICAgIGNvbmZpZyxcbiAgICBhdXRoLFxuICAgIGNsYXNzTmFtZSxcbiAgICB3aGVyZSxcbiAgICBvcHRpb25zLFxuICAgIGluZm8uY2xpZW50U0RLXG4gICk7XG59O1xuXG5leHBvcnQgeyBnZXRPYmplY3QsIGZpbmRPYmplY3RzIH07XG4iXX0= \ No newline at end of file diff --git a/lib/GraphQL/loaders/defaultGraphQLMutations.js b/lib/GraphQL/loaders/defaultGraphQLMutations.js new file mode 100644 index 0000000000..afe32cc4fb --- /dev/null +++ b/lib/GraphQL/loaders/defaultGraphQLMutations.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var filesMutations = _interopRequireWildcard(require("./filesMutations")); + +var usersMutations = _interopRequireWildcard(require("./usersMutations")); + +var functionsMutations = _interopRequireWildcard(require("./functionsMutations")); + +var schemaMutations = _interopRequireWildcard(require("./schemaMutations")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +const load = parseGraphQLSchema => { + filesMutations.load(parseGraphQLSchema); + usersMutations.load(parseGraphQLSchema); + functionsMutations.load(parseGraphQLSchema); + schemaMutations.load(parseGraphQLSchema); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxNdXRhdGlvbnMuanMiXSwibmFtZXMiOlsibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsImZpbGVzTXV0YXRpb25zIiwidXNlcnNNdXRhdGlvbnMiLCJmdW5jdGlvbnNNdXRhdGlvbnMiLCJzY2hlbWFNdXRhdGlvbnMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEsSUFBSSxHQUFHQyxrQkFBa0IsSUFBSTtBQUNqQ0MsRUFBQUEsY0FBYyxDQUFDRixJQUFmLENBQW9CQyxrQkFBcEI7QUFDQUUsRUFBQUEsY0FBYyxDQUFDSCxJQUFmLENBQW9CQyxrQkFBcEI7QUFDQUcsRUFBQUEsa0JBQWtCLENBQUNKLElBQW5CLENBQXdCQyxrQkFBeEI7QUFDQUksRUFBQUEsZUFBZSxDQUFDTCxJQUFoQixDQUFxQkMsa0JBQXJCO0FBQ0QsQ0FMRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZpbGVzTXV0YXRpb25zIGZyb20gJy4vZmlsZXNNdXRhdGlvbnMnO1xuaW1wb3J0ICogYXMgdXNlcnNNdXRhdGlvbnMgZnJvbSAnLi91c2Vyc011dGF0aW9ucyc7XG5pbXBvcnQgKiBhcyBmdW5jdGlvbnNNdXRhdGlvbnMgZnJvbSAnLi9mdW5jdGlvbnNNdXRhdGlvbnMnO1xuaW1wb3J0ICogYXMgc2NoZW1hTXV0YXRpb25zIGZyb20gJy4vc2NoZW1hTXV0YXRpb25zJztcblxuY29uc3QgbG9hZCA9IHBhcnNlR3JhcGhRTFNjaGVtYSA9PiB7XG4gIGZpbGVzTXV0YXRpb25zLmxvYWQocGFyc2VHcmFwaFFMU2NoZW1hKTtcbiAgdXNlcnNNdXRhdGlvbnMubG9hZChwYXJzZUdyYXBoUUxTY2hlbWEpO1xuICBmdW5jdGlvbnNNdXRhdGlvbnMubG9hZChwYXJzZUdyYXBoUUxTY2hlbWEpO1xuICBzY2hlbWFNdXRhdGlvbnMubG9hZChwYXJzZUdyYXBoUUxTY2hlbWEpO1xufTtcblxuZXhwb3J0IHsgbG9hZCB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/loaders/defaultGraphQLQueries.js b/lib/GraphQL/loaders/defaultGraphQLQueries.js new file mode 100644 index 0000000000..b8935f3ab1 --- /dev/null +++ b/lib/GraphQL/loaders/defaultGraphQLQueries.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var usersQueries = _interopRequireWildcard(require("./usersQueries")); + +var schemaQueries = _interopRequireWildcard(require("./schemaQueries")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +const load = parseGraphQLSchema => { + parseGraphQLSchema.addGraphQLQuery('health', { + description: 'The health query can be used to check if the server is up and running.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean), + resolve: () => true + }, true, true); + usersQueries.load(parseGraphQLSchema); + schemaQueries.load(parseGraphQLSchema); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxRdWVyaWVzLmpzIl0sIm5hbWVzIjpbImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJhZGRHcmFwaFFMUXVlcnkiLCJkZXNjcmlwdGlvbiIsInR5cGUiLCJHcmFwaFFMTm9uTnVsbCIsIkdyYXBoUUxCb29sZWFuIiwicmVzb2x2ZSIsInVzZXJzUXVlcmllcyIsInNjaGVtYVF1ZXJpZXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEsSUFBSSxHQUFHQyxrQkFBa0IsSUFBSTtBQUNqQ0EsRUFBQUEsa0JBQWtCLENBQUNDLGVBQW5CLENBQ0UsUUFERixFQUVFO0FBQ0VDLElBQUFBLFdBQVcsRUFDVCx3RUFGSjtBQUdFQyxJQUFBQSxJQUFJLEVBQUUsSUFBSUMsdUJBQUosQ0FBbUJDLHVCQUFuQixDQUhSO0FBSUVDLElBQUFBLE9BQU8sRUFBRSxNQUFNO0FBSmpCLEdBRkYsRUFRRSxJQVJGLEVBU0UsSUFURjtBQVlBQyxFQUFBQSxZQUFZLENBQUNSLElBQWIsQ0FBa0JDLGtCQUFsQjtBQUNBUSxFQUFBQSxhQUFhLENBQUNULElBQWQsQ0FBbUJDLGtCQUFuQjtBQUNELENBZkQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBHcmFwaFFMTm9uTnVsbCwgR3JhcGhRTEJvb2xlYW4gfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCAqIGFzIHVzZXJzUXVlcmllcyBmcm9tICcuL3VzZXJzUXVlcmllcyc7XG5pbXBvcnQgKiBhcyBzY2hlbWFRdWVyaWVzIGZyb20gJy4vc2NoZW1hUXVlcmllcyc7XG5cbmNvbnN0IGxvYWQgPSBwYXJzZUdyYXBoUUxTY2hlbWEgPT4ge1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFF1ZXJ5KFxuICAgICdoZWFsdGgnLFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhlIGhlYWx0aCBxdWVyeSBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiB0aGUgc2VydmVyIGlzIHVwIGFuZCBydW5uaW5nLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgICAgcmVzb2x2ZTogKCkgPT4gdHJ1ZSxcbiAgICB9LFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xuXG4gIHVzZXJzUXVlcmllcy5sb2FkKHBhcnNlR3JhcGhRTFNjaGVtYSk7XG4gIHNjaGVtYVF1ZXJpZXMubG9hZChwYXJzZUdyYXBoUUxTY2hlbWEpO1xufTtcblxuZXhwb3J0IHsgbG9hZCB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/loaders/defaultGraphQLTypes.js b/lib/GraphQL/loaders/defaultGraphQLTypes.js new file mode 100644 index 0000000000..3098c39a43 --- /dev/null +++ b/lib/GraphQL/loaders/defaultGraphQLTypes.js @@ -0,0 +1,1231 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.loadArrayResult = exports.load = exports.PUBLIC_ACL = exports.ROLE_ACL = exports.USER_ACL = exports.ACL = exports.PUBLIC_ACL_INPUT = exports.ROLE_ACL_INPUT = exports.USER_ACL_INPUT = exports.ACL_INPUT = exports.ELEMENT = exports.ARRAY_RESULT = exports.FIND_RESULT = exports.POLYGON_WHERE_INPUT = exports.GEO_POINT_WHERE_INPUT = exports.FILE_WHERE_INPUT = exports.BYTES_WHERE_INPUT = exports.DATE_WHERE_INPUT = exports.OBJECT_WHERE_INPUT = exports.KEY_VALUE_INPUT = exports.ARRAY_WHERE_INPUT = exports.BOOLEAN_WHERE_INPUT = exports.NUMBER_WHERE_INPUT = exports.STRING_WHERE_INPUT = exports.options = exports.matchesRegex = exports.notInQueryKey = exports.inQueryKey = exports.exists = exports.notIn = exports.inOp = exports.greaterThanOrEqualTo = exports.greaterThan = exports.lessThanOrEqualTo = exports.lessThan = exports.notEqualTo = exports.equalTo = exports.GEO_INTERSECTS_INPUT = exports.GEO_WITHIN_INPUT = exports.CENTER_SPHERE_INPUT = exports.WITHIN_INPUT = exports.BOX_INPUT = exports.TEXT_INPUT = exports.SEARCH_INPUT = exports.SELECT_INPUT = exports.SUBQUERY_INPUT = exports.COUNT_ATT = exports.LIMIT_ATT = exports.SKIP_ATT = exports.WHERE_ATT = exports.READ_OPTIONS_ATT = exports.READ_OPTIONS_INPUT = exports.SUBQUERY_READ_PREFERENCE_ATT = exports.INCLUDE_READ_PREFERENCE_ATT = exports.READ_PREFERENCE_ATT = exports.READ_PREFERENCE = exports.SESSION_TOKEN_ATT = exports.PARSE_OBJECT = exports.PARSE_OBJECT_FIELDS = exports.UPDATE_RESULT_FIELDS = exports.CREATE_RESULT_FIELDS = exports.INPUT_FIELDS = exports.CREATED_AT_ATT = exports.UPDATED_AT_ATT = exports.OBJECT_ID_ATT = exports.CLASS_NAME_ATT = exports.OBJECT_ID = exports.POLYGON = exports.POLYGON_INPUT = exports.GEO_POINT = exports.GEO_POINT_INPUT = exports.GEO_POINT_FIELDS = exports.FILE_INFO = exports.FILE = exports.parseFileValue = exports.BYTES = exports.DATE = exports.serializeDateIso = exports.parseDateIsoValue = exports.OBJECT = exports.ANY = exports.parseObjectFields = exports.parseListValues = exports.parseValue = exports.parseBooleanValue = exports.parseFloatValue = exports.parseIntValue = exports.parseStringValue = exports.TypeValidationError = void 0; + +var _graphql = require("graphql"); + +var _graphqlUpload = require("graphql-upload"); + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +class TypeValidationError extends Error { + constructor(value, type) { + super(`${value} is not a valid ${type}`); + } + +} + +exports.TypeValidationError = TypeValidationError; + +const parseStringValue = value => { + if (typeof value === 'string') { + return value; + } + + throw new TypeValidationError(value, 'String'); +}; + +exports.parseStringValue = parseStringValue; + +const parseIntValue = value => { + if (typeof value === 'string') { + const int = Number(value); + + if (Number.isInteger(int)) { + return int; + } + } + + throw new TypeValidationError(value, 'Int'); +}; + +exports.parseIntValue = parseIntValue; + +const parseFloatValue = value => { + if (typeof value === 'string') { + const float = Number(value); + + if (!isNaN(float)) { + return float; + } + } + + throw new TypeValidationError(value, 'Float'); +}; + +exports.parseFloatValue = parseFloatValue; + +const parseBooleanValue = value => { + if (typeof value === 'boolean') { + return value; + } + + throw new TypeValidationError(value, 'Boolean'); +}; + +exports.parseBooleanValue = parseBooleanValue; + +const parseValue = value => { + switch (value.kind) { + case _graphql.Kind.STRING: + return parseStringValue(value.value); + + case _graphql.Kind.INT: + return parseIntValue(value.value); + + case _graphql.Kind.FLOAT: + return parseFloatValue(value.value); + + case _graphql.Kind.BOOLEAN: + return parseBooleanValue(value.value); + + case _graphql.Kind.LIST: + return parseListValues(value.values); + + case _graphql.Kind.OBJECT: + return parseObjectFields(value.fields); + + default: + return value.value; + } +}; + +exports.parseValue = parseValue; + +const parseListValues = values => { + if (Array.isArray(values)) { + return values.map(value => parseValue(value)); + } + + throw new TypeValidationError(values, 'List'); +}; + +exports.parseListValues = parseListValues; + +const parseObjectFields = fields => { + if (Array.isArray(fields)) { + return fields.reduce((object, field) => _objectSpread({}, object, { + [field.name.value]: parseValue(field.value) + }), {}); + } + + throw new TypeValidationError(fields, 'Object'); +}; + +exports.parseObjectFields = parseObjectFields; +const ANY = new _graphql.GraphQLScalarType({ + name: 'Any', + description: 'The Any scalar type is used in operations and types that involve any type of value.', + parseValue: value => value, + serialize: value => value, + parseLiteral: ast => parseValue(ast) +}); +exports.ANY = ANY; +const OBJECT = new _graphql.GraphQLScalarType({ + name: 'Object', + description: 'The Object scalar type is used in operations and types that involve objects.', + + parseValue(value) { + if (typeof value === 'object') { + return value; + } + + throw new TypeValidationError(value, 'Object'); + }, + + serialize(value) { + if (typeof value === 'object') { + return value; + } + + throw new TypeValidationError(value, 'Object'); + }, + + parseLiteral(ast) { + if (ast.kind === _graphql.Kind.OBJECT) { + return parseObjectFields(ast.fields); + } + + throw new TypeValidationError(ast.kind, 'Object'); + } + +}); +exports.OBJECT = OBJECT; + +const parseDateIsoValue = value => { + if (typeof value === 'string') { + const date = new Date(value); + + if (!isNaN(date)) { + return date; + } + } else if (value instanceof Date) { + return value; + } + + throw new TypeValidationError(value, 'Date'); +}; + +exports.parseDateIsoValue = parseDateIsoValue; + +const serializeDateIso = value => { + if (typeof value === 'string') { + return value; + } + + if (value instanceof Date) { + return value.toUTCString(); + } + + throw new TypeValidationError(value, 'Date'); +}; + +exports.serializeDateIso = serializeDateIso; + +const parseDateIsoLiteral = ast => { + if (ast.kind === _graphql.Kind.STRING) { + return parseDateIsoValue(ast.value); + } + + throw new TypeValidationError(ast.kind, 'Date'); +}; + +const DATE = new _graphql.GraphQLScalarType({ + name: 'Date', + description: 'The Date scalar type is used in operations and types that involve dates.', + + parseValue(value) { + if (typeof value === 'string' || value instanceof Date) { + return { + __type: 'Date', + iso: parseDateIsoValue(value) + }; + } else if (typeof value === 'object' && value.__type === 'Date' && value.iso) { + return { + __type: value.__type, + iso: parseDateIsoValue(value.iso) + }; + } + + throw new TypeValidationError(value, 'Date'); + }, + + serialize(value) { + if (typeof value === 'string' || value instanceof Date) { + return serializeDateIso(value); + } else if (typeof value === 'object' && value.__type === 'Date' && value.iso) { + return serializeDateIso(value.iso); + } + + throw new TypeValidationError(value, 'Date'); + }, + + parseLiteral(ast) { + if (ast.kind === _graphql.Kind.STRING) { + return { + __type: 'Date', + iso: parseDateIsoLiteral(ast) + }; + } else if (ast.kind === _graphql.Kind.OBJECT) { + const __type = ast.fields.find(field => field.name.value === '__type'); + + const iso = ast.fields.find(field => field.name.value === 'iso'); + + if (__type && __type.value && __type.value.value === 'Date' && iso) { + return { + __type: __type.value.value, + iso: parseDateIsoLiteral(iso.value) + }; + } + } + + throw new TypeValidationError(ast.kind, 'Date'); + } + +}); +exports.DATE = DATE; +const BYTES = new _graphql.GraphQLScalarType({ + name: 'Bytes', + description: 'The Bytes scalar type is used in operations and types that involve base 64 binary data.', + + parseValue(value) { + if (typeof value === 'string') { + return { + __type: 'Bytes', + base64: value + }; + } else if (typeof value === 'object' && value.__type === 'Bytes' && typeof value.base64 === 'string') { + return value; + } + + throw new TypeValidationError(value, 'Bytes'); + }, + + serialize(value) { + if (typeof value === 'string') { + return value; + } else if (typeof value === 'object' && value.__type === 'Bytes' && typeof value.base64 === 'string') { + return value.base64; + } + + throw new TypeValidationError(value, 'Bytes'); + }, + + parseLiteral(ast) { + if (ast.kind === _graphql.Kind.STRING) { + return { + __type: 'Bytes', + base64: ast.value + }; + } else if (ast.kind === _graphql.Kind.OBJECT) { + const __type = ast.fields.find(field => field.name.value === '__type'); + + const base64 = ast.fields.find(field => field.name.value === 'base64'); + + if (__type && __type.value && __type.value.value === 'Bytes' && base64 && base64.value && typeof base64.value.value === 'string') { + return { + __type: __type.value.value, + base64: base64.value.value + }; + } + } + + throw new TypeValidationError(ast.kind, 'Bytes'); + } + +}); +exports.BYTES = BYTES; + +const parseFileValue = value => { + if (typeof value === 'string') { + return { + __type: 'File', + name: value + }; + } else if (typeof value === 'object' && value.__type === 'File' && typeof value.name === 'string' && (value.url === undefined || typeof value.url === 'string')) { + return value; + } + + throw new TypeValidationError(value, 'File'); +}; + +exports.parseFileValue = parseFileValue; +const FILE = new _graphql.GraphQLScalarType({ + name: 'File', + description: 'The File scalar type is used in operations and types that involve files.', + parseValue: parseFileValue, + serialize: value => { + if (typeof value === 'string') { + return value; + } else if (typeof value === 'object' && value.__type === 'File' && typeof value.name === 'string' && (value.url === undefined || typeof value.url === 'string')) { + return value.name; + } + + throw new TypeValidationError(value, 'File'); + }, + + parseLiteral(ast) { + if (ast.kind === _graphql.Kind.STRING) { + return parseFileValue(ast.value); + } else if (ast.kind === _graphql.Kind.OBJECT) { + const __type = ast.fields.find(field => field.name.value === '__type'); + + const name = ast.fields.find(field => field.name.value === 'name'); + const url = ast.fields.find(field => field.name.value === 'url'); + + if (__type && __type.value && name && name.value) { + return parseFileValue({ + __type: __type.value.value, + name: name.value.value, + url: url && url.value ? url.value.value : undefined + }); + } + } + + throw new TypeValidationError(ast.kind, 'File'); + } + +}); +exports.FILE = FILE; +const FILE_INFO = new _graphql.GraphQLObjectType({ + name: 'FileInfo', + description: 'The FileInfo object type is used to return the information about files.', + fields: { + name: { + description: 'This is the file name.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + }, + url: { + description: 'This is the url in which the file can be downloaded.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + } + } +}); +exports.FILE_INFO = FILE_INFO; +const GEO_POINT_FIELDS = { + latitude: { + description: 'This is the latitude.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLFloat) + }, + longitude: { + description: 'This is the longitude.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLFloat) + } +}; +exports.GEO_POINT_FIELDS = GEO_POINT_FIELDS; +const GEO_POINT_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'GeoPointInput', + description: 'The GeoPointInput type is used in operations that involve inputting fields of type geo point.', + fields: GEO_POINT_FIELDS +}); +exports.GEO_POINT_INPUT = GEO_POINT_INPUT; +const GEO_POINT = new _graphql.GraphQLObjectType({ + name: 'GeoPoint', + description: 'The GeoPoint object type is used to return the information about geo point fields.', + fields: GEO_POINT_FIELDS +}); +exports.GEO_POINT = GEO_POINT; +const POLYGON_INPUT = new _graphql.GraphQLList(new _graphql.GraphQLNonNull(GEO_POINT_INPUT)); +exports.POLYGON_INPUT = POLYGON_INPUT; +const POLYGON = new _graphql.GraphQLList(new _graphql.GraphQLNonNull(GEO_POINT)); +exports.POLYGON = POLYGON; +const USER_ACL_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'UserACLInput', + description: 'Allow to manage users in ACL.', + fields: { + userId: { + description: 'ID of the targetted User.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLID) + }, + read: { + description: 'Allow the user to read the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + }, + write: { + description: 'Allow the user to write on the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + } + } +}); +exports.USER_ACL_INPUT = USER_ACL_INPUT; +const ROLE_ACL_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'RoleACLInput', + description: 'Allow to manage roles in ACL.', + fields: { + roleName: { + description: 'Name of the targetted Role.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + }, + read: { + description: 'Allow users who are members of the role to read the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + }, + write: { + description: 'Allow users who are members of the role to write on the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + } + } +}); +exports.ROLE_ACL_INPUT = ROLE_ACL_INPUT; +const PUBLIC_ACL_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'PublicACLInput', + description: 'Allow to manage public rights.', + fields: { + read: { + description: 'Allow anyone to read the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + }, + write: { + description: 'Allow anyone to write on the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + } + } +}); +exports.PUBLIC_ACL_INPUT = PUBLIC_ACL_INPUT; +const ACL_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'ACLInput', + description: 'Allow to manage access rights. If not provided object will be publicly readable and writable', + fields: { + users: { + description: 'Access control list for users.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(USER_ACL_INPUT)) + }, + roles: { + description: 'Access control list for roles.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(ROLE_ACL_INPUT)) + }, + public: { + description: 'Public access control list.', + type: PUBLIC_ACL_INPUT + } + } +}); +exports.ACL_INPUT = ACL_INPUT; +const USER_ACL = new _graphql.GraphQLObjectType({ + name: 'UserACL', + description: 'Allow to manage users in ACL. If read and write are null the users have read and write rights.', + fields: { + userId: { + description: 'ID of the targetted User.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLID) + }, + read: { + description: 'Allow the user to read the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + }, + write: { + description: 'Allow the user to write on the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + } + } +}); +exports.USER_ACL = USER_ACL; +const ROLE_ACL = new _graphql.GraphQLObjectType({ + name: 'RoleACL', + description: 'Allow to manage roles in ACL. If read and write are null the role have read and write rights.', + fields: { + roleName: { + description: 'Name of the targetted Role.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLID) + }, + read: { + description: 'Allow users who are members of the role to read the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + }, + write: { + description: 'Allow users who are members of the role to write on the current object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + } + } +}); +exports.ROLE_ACL = ROLE_ACL; +const PUBLIC_ACL = new _graphql.GraphQLObjectType({ + name: 'PublicACL', + description: 'Allow to manage public rights.', + fields: { + read: { + description: 'Allow anyone to read the current object.', + type: _graphql.GraphQLBoolean + }, + write: { + description: 'Allow anyone to write on the current object.', + type: _graphql.GraphQLBoolean + } + } +}); +exports.PUBLIC_ACL = PUBLIC_ACL; +const ACL = new _graphql.GraphQLObjectType({ + name: 'ACL', + description: 'Current access control list of the current object.', + fields: { + users: { + description: 'Access control list for users.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(USER_ACL)), + + resolve(p) { + const users = []; + Object.keys(p).forEach(rule => { + if (rule !== '*' && rule.indexOf('role:') !== 0) { + users.push({ + userId: rule, + read: p[rule].read ? true : false, + write: p[rule].write ? true : false + }); + } + }); + return users.length ? users : null; + } + + }, + roles: { + description: 'Access control list for roles.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(ROLE_ACL)), + + resolve(p) { + const roles = []; + Object.keys(p).forEach(rule => { + if (rule.indexOf('role:') === 0) { + roles.push({ + roleName: rule.replace('role:', ''), + read: p[rule].read ? true : false, + write: p[rule].write ? true : false + }); + } + }); + return roles.length ? roles : null; + } + + }, + public: { + description: 'Public access control list.', + type: PUBLIC_ACL, + + resolve(p) { + /* eslint-disable */ + return p['*'] ? { + read: p['*'].read ? true : false, + write: p['*'].write ? true : false + } : null; + } + + } + } +}); +exports.ACL = ACL; +const OBJECT_ID = new _graphql.GraphQLNonNull(_graphql.GraphQLID); +exports.OBJECT_ID = OBJECT_ID; +const CLASS_NAME_ATT = { + description: 'This is the class name of the object.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) +}; +exports.CLASS_NAME_ATT = CLASS_NAME_ATT; +const OBJECT_ID_ATT = { + description: 'This is the object id.', + type: OBJECT_ID, + resolve: ({ + objectId + }) => objectId +}; +exports.OBJECT_ID_ATT = OBJECT_ID_ATT; +const CREATED_AT_ATT = { + description: 'This is the date in which the object was created.', + type: new _graphql.GraphQLNonNull(DATE) +}; +exports.CREATED_AT_ATT = CREATED_AT_ATT; +const UPDATED_AT_ATT = { + description: 'This is the date in which the object was las updated.', + type: new _graphql.GraphQLNonNull(DATE) +}; +exports.UPDATED_AT_ATT = UPDATED_AT_ATT; +const INPUT_FIELDS = { + ACL: { + type: ACL + } +}; +exports.INPUT_FIELDS = INPUT_FIELDS; +const CREATE_RESULT_FIELDS = { + id: OBJECT_ID_ATT, + createdAt: CREATED_AT_ATT +}; +exports.CREATE_RESULT_FIELDS = CREATE_RESULT_FIELDS; +const UPDATE_RESULT_FIELDS = { + updatedAt: UPDATED_AT_ATT +}; +exports.UPDATE_RESULT_FIELDS = UPDATE_RESULT_FIELDS; + +const PARSE_OBJECT_FIELDS = _objectSpread({}, CREATE_RESULT_FIELDS, {}, UPDATE_RESULT_FIELDS, {}, INPUT_FIELDS); + +exports.PARSE_OBJECT_FIELDS = PARSE_OBJECT_FIELDS; +const PARSE_OBJECT = new _graphql.GraphQLInterfaceType({ + name: 'ParseObject', + description: 'The ParseObject interface type is used as a base type for the auto generated object types.', + fields: PARSE_OBJECT_FIELDS +}); +exports.PARSE_OBJECT = PARSE_OBJECT; +const SESSION_TOKEN_ATT = { + description: 'The user session token', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) +}; +exports.SESSION_TOKEN_ATT = SESSION_TOKEN_ATT; +const READ_PREFERENCE = new _graphql.GraphQLEnumType({ + name: 'ReadPreference', + description: 'The ReadPreference enum type is used in queries in order to select in which database replica the operation must run.', + values: { + PRIMARY: { + value: 'PRIMARY' + }, + PRIMARY_PREFERRED: { + value: 'PRIMARY_PREFERRED' + }, + SECONDARY: { + value: 'SECONDARY' + }, + SECONDARY_PREFERRED: { + value: 'SECONDARY_PREFERRED' + }, + NEAREST: { + value: 'NEAREST' + } + } +}); +exports.READ_PREFERENCE = READ_PREFERENCE; +const READ_PREFERENCE_ATT = { + description: 'The read preference for the main query to be executed.', + type: READ_PREFERENCE +}; +exports.READ_PREFERENCE_ATT = READ_PREFERENCE_ATT; +const INCLUDE_READ_PREFERENCE_ATT = { + description: 'The read preference for the queries to be executed to include fields.', + type: READ_PREFERENCE +}; +exports.INCLUDE_READ_PREFERENCE_ATT = INCLUDE_READ_PREFERENCE_ATT; +const SUBQUERY_READ_PREFERENCE_ATT = { + description: 'The read preference for the subqueries that may be required.', + type: READ_PREFERENCE +}; +exports.SUBQUERY_READ_PREFERENCE_ATT = SUBQUERY_READ_PREFERENCE_ATT; +const READ_OPTIONS_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'ReadOptionsInput', + description: 'The ReadOptionsInputt type is used in queries in order to set the read preferences.', + fields: { + readPreference: READ_PREFERENCE_ATT, + includeReadPreference: INCLUDE_READ_PREFERENCE_ATT, + subqueryReadPreference: SUBQUERY_READ_PREFERENCE_ATT + } +}); +exports.READ_OPTIONS_INPUT = READ_OPTIONS_INPUT; +const READ_OPTIONS_ATT = { + description: 'The read options for the query to be executed.', + type: READ_OPTIONS_INPUT +}; +exports.READ_OPTIONS_ATT = READ_OPTIONS_ATT; +const WHERE_ATT = { + description: 'These are the conditions that the objects need to match in order to be found', + type: OBJECT +}; +exports.WHERE_ATT = WHERE_ATT; +const SKIP_ATT = { + description: 'This is the number of objects that must be skipped to return.', + type: _graphql.GraphQLInt +}; +exports.SKIP_ATT = SKIP_ATT; +const LIMIT_ATT = { + description: 'This is the limit number of objects that must be returned.', + type: _graphql.GraphQLInt +}; +exports.LIMIT_ATT = LIMIT_ATT; +const COUNT_ATT = { + description: 'This is the total matched objecs count that is returned when the count flag is set.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLInt) +}; +exports.COUNT_ATT = COUNT_ATT; +const SUBQUERY_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SubqueryInput', + description: 'The SubqueryInput type is used to specify a sub query to another class.', + fields: { + className: CLASS_NAME_ATT, + where: Object.assign({}, WHERE_ATT, { + type: new _graphql.GraphQLNonNull(WHERE_ATT.type) + }) + } +}); +exports.SUBQUERY_INPUT = SUBQUERY_INPUT; +const SELECT_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SelectInput', + description: 'The SelectInput type is used to specify an inQueryKey or a notInQueryKey operation on a constraint.', + fields: { + query: { + description: 'This is the subquery to be executed.', + type: new _graphql.GraphQLNonNull(SUBQUERY_INPUT) + }, + key: { + description: 'This is the key in the result of the subquery that must match (not match) the field.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + } + } +}); +exports.SELECT_INPUT = SELECT_INPUT; +const SEARCH_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SearchInput', + description: 'The SearchInput type is used to specifiy a search operation on a full text search.', + fields: { + term: { + description: 'This is the term to be searched.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + }, + language: { + description: 'This is the language to tetermine the list of stop words and the rules for tokenizer.', + type: _graphql.GraphQLString + }, + caseSensitive: { + description: 'This is the flag to enable or disable case sensitive search.', + type: _graphql.GraphQLBoolean + }, + diacriticSensitive: { + description: 'This is the flag to enable or disable diacritic sensitive search.', + type: _graphql.GraphQLBoolean + } + } +}); +exports.SEARCH_INPUT = SEARCH_INPUT; +const TEXT_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'TextInput', + description: 'The TextInput type is used to specify a text operation on a constraint.', + fields: { + search: { + description: 'This is the search to be executed.', + type: new _graphql.GraphQLNonNull(SEARCH_INPUT) + } + } +}); +exports.TEXT_INPUT = TEXT_INPUT; +const BOX_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'BoxInput', + description: 'The BoxInput type is used to specifiy a box operation on a within geo query.', + fields: { + bottomLeft: { + description: 'This is the bottom left coordinates of the box.', + type: new _graphql.GraphQLNonNull(GEO_POINT_INPUT) + }, + upperRight: { + description: 'This is the upper right coordinates of the box.', + type: new _graphql.GraphQLNonNull(GEO_POINT_INPUT) + } + } +}); +exports.BOX_INPUT = BOX_INPUT; +const WITHIN_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'WithinInput', + description: 'The WithinInput type is used to specify a within operation on a constraint.', + fields: { + box: { + description: 'This is the box to be specified.', + type: new _graphql.GraphQLNonNull(BOX_INPUT) + } + } +}); +exports.WITHIN_INPUT = WITHIN_INPUT; +const CENTER_SPHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'CenterSphereInput', + description: 'The CenterSphereInput type is used to specifiy a centerSphere operation on a geoWithin query.', + fields: { + center: { + description: 'This is the center of the sphere.', + type: new _graphql.GraphQLNonNull(GEO_POINT_INPUT) + }, + distance: { + description: 'This is the radius of the sphere.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLFloat) + } + } +}); +exports.CENTER_SPHERE_INPUT = CENTER_SPHERE_INPUT; +const GEO_WITHIN_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'GeoWithinInput', + description: 'The GeoWithinInput type is used to specify a geoWithin operation on a constraint.', + fields: { + polygon: { + description: 'This is the polygon to be specified.', + type: POLYGON_INPUT + }, + centerSphere: { + description: 'This is the sphere to be specified.', + type: CENTER_SPHERE_INPUT + } + } +}); +exports.GEO_WITHIN_INPUT = GEO_WITHIN_INPUT; +const GEO_INTERSECTS_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'GeoIntersectsInput', + description: 'The GeoIntersectsInput type is used to specify a geoIntersects operation on a constraint.', + fields: { + point: { + description: 'This is the point to be specified.', + type: GEO_POINT_INPUT + } + } +}); +exports.GEO_INTERSECTS_INPUT = GEO_INTERSECTS_INPUT; + +const equalTo = type => ({ + description: 'This is the equalTo operator to specify a constraint to select the objects where the value of a field equals to a specified value.', + type +}); + +exports.equalTo = equalTo; + +const notEqualTo = type => ({ + description: 'This is the notEqualTo operator to specify a constraint to select the objects where the value of a field do not equal to a specified value.', + type +}); + +exports.notEqualTo = notEqualTo; + +const lessThan = type => ({ + description: 'This is the lessThan operator to specify a constraint to select the objects where the value of a field is less than a specified value.', + type +}); + +exports.lessThan = lessThan; + +const lessThanOrEqualTo = type => ({ + description: 'This is the lessThanOrEqualTo operator to specify a constraint to select the objects where the value of a field is less than or equal to a specified value.', + type +}); + +exports.lessThanOrEqualTo = lessThanOrEqualTo; + +const greaterThan = type => ({ + description: 'This is the greaterThan operator to specify a constraint to select the objects where the value of a field is greater than a specified value.', + type +}); + +exports.greaterThan = greaterThan; + +const greaterThanOrEqualTo = type => ({ + description: 'This is the greaterThanOrEqualTo operator to specify a constraint to select the objects where the value of a field is greater than or equal to a specified value.', + type +}); + +exports.greaterThanOrEqualTo = greaterThanOrEqualTo; + +const inOp = type => ({ + description: 'This is the in operator to specify a constraint to select the objects where the value of a field equals any value in the specified array.', + type: new _graphql.GraphQLList(type) +}); + +exports.inOp = inOp; + +const notIn = type => ({ + description: 'This is the notIn operator to specify a constraint to select the objects where the value of a field do not equal any value in the specified array.', + type: new _graphql.GraphQLList(type) +}); + +exports.notIn = notIn; +const exists = { + description: 'This is the exists operator to specify a constraint to select the objects where a field exists (or do not exist).', + type: _graphql.GraphQLBoolean +}; +exports.exists = exists; +const inQueryKey = { + description: 'This is the inQueryKey operator to specify a constraint to select the objects where a field equals to a key in the result of a different query.', + type: SELECT_INPUT +}; +exports.inQueryKey = inQueryKey; +const notInQueryKey = { + description: 'This is the notInQueryKey operator to specify a constraint to select the objects where a field do not equal to a key in the result of a different query.', + type: SELECT_INPUT +}; +exports.notInQueryKey = notInQueryKey; +const matchesRegex = { + description: 'This is the matchesRegex operator to specify a constraint to select the objects where the value of a field matches a specified regular expression.', + type: _graphql.GraphQLString +}; +exports.matchesRegex = matchesRegex; +const options = { + description: 'This is the options operator to specify optional flags (such as "i" and "m") to be added to a matchesRegex operation in the same set of constraints.', + type: _graphql.GraphQLString +}; +exports.options = options; +const STRING_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'StringWhereInput', + description: 'The StringWhereInput input type is used in operations that involve filtering objects by a field of type String.', + fields: { + equalTo: equalTo(_graphql.GraphQLString), + notEqualTo: notEqualTo(_graphql.GraphQLString), + lessThan: lessThan(_graphql.GraphQLString), + lessThanOrEqualTo: lessThanOrEqualTo(_graphql.GraphQLString), + greaterThan: greaterThan(_graphql.GraphQLString), + greaterThanOrEqualTo: greaterThanOrEqualTo(_graphql.GraphQLString), + in: inOp(_graphql.GraphQLString), + notIn: notIn(_graphql.GraphQLString), + exists, + inQueryKey, + notInQueryKey, + matchesRegex, + options, + text: { + description: 'This is the $text operator to specify a full text search constraint.', + type: TEXT_INPUT + } + } +}); +exports.STRING_WHERE_INPUT = STRING_WHERE_INPUT; +const NUMBER_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'NumberWhereInput', + description: 'The NumberWhereInput input type is used in operations that involve filtering objects by a field of type Number.', + fields: { + equalTo: equalTo(_graphql.GraphQLFloat), + notEqualTo: notEqualTo(_graphql.GraphQLFloat), + lessThan: lessThan(_graphql.GraphQLFloat), + lessThanOrEqualTo: lessThanOrEqualTo(_graphql.GraphQLFloat), + greaterThan: greaterThan(_graphql.GraphQLFloat), + greaterThanOrEqualTo: greaterThanOrEqualTo(_graphql.GraphQLFloat), + in: inOp(_graphql.GraphQLFloat), + notIn: notIn(_graphql.GraphQLFloat), + exists, + inQueryKey, + notInQueryKey + } +}); +exports.NUMBER_WHERE_INPUT = NUMBER_WHERE_INPUT; +const BOOLEAN_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'BooleanWhereInput', + description: 'The BooleanWhereInput input type is used in operations that involve filtering objects by a field of type Boolean.', + fields: { + equalTo: equalTo(_graphql.GraphQLBoolean), + notEqualTo: notEqualTo(_graphql.GraphQLBoolean), + exists, + inQueryKey, + notInQueryKey + } +}); +exports.BOOLEAN_WHERE_INPUT = BOOLEAN_WHERE_INPUT; +const ARRAY_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'ArrayWhereInput', + description: 'The ArrayWhereInput input type is used in operations that involve filtering objects by a field of type Array.', + fields: { + equalTo: equalTo(ANY), + notEqualTo: notEqualTo(ANY), + lessThan: lessThan(ANY), + lessThanOrEqualTo: lessThanOrEqualTo(ANY), + greaterThan: greaterThan(ANY), + greaterThanOrEqualTo: greaterThanOrEqualTo(ANY), + in: inOp(ANY), + notIn: notIn(ANY), + exists, + inQueryKey, + notInQueryKey, + containedBy: { + description: 'This is the containedBy operator to specify a constraint to select the objects where the values of an array field is contained by another specified array.', + type: new _graphql.GraphQLList(ANY) + }, + contains: { + description: 'This is the contains operator to specify a constraint to select the objects where the values of an array field contain all elements of another specified array.', + type: new _graphql.GraphQLList(ANY) + } + } +}); +exports.ARRAY_WHERE_INPUT = ARRAY_WHERE_INPUT; +const KEY_VALUE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'KeyValueInput', + description: 'An entry from an object, i.e., a pair of key and value.', + fields: { + key: { + description: 'The key used to retrieve the value of this entry.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + }, + value: { + description: 'The value of the entry. Could be any type of scalar data.', + type: new _graphql.GraphQLNonNull(ANY) + } + } +}); +exports.KEY_VALUE_INPUT = KEY_VALUE_INPUT; +const OBJECT_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'ObjectWhereInput', + description: 'The ObjectWhereInput input type is used in operations that involve filtering result by a field of type Object.', + fields: { + equalTo: equalTo(KEY_VALUE_INPUT), + notEqualTo: notEqualTo(KEY_VALUE_INPUT), + in: inOp(KEY_VALUE_INPUT), + notIn: notIn(KEY_VALUE_INPUT), + lessThan: lessThan(KEY_VALUE_INPUT), + lessThanOrEqualTo: lessThanOrEqualTo(KEY_VALUE_INPUT), + greaterThan: greaterThan(KEY_VALUE_INPUT), + greaterThanOrEqualTo: greaterThanOrEqualTo(KEY_VALUE_INPUT), + exists, + inQueryKey, + notInQueryKey + } +}); +exports.OBJECT_WHERE_INPUT = OBJECT_WHERE_INPUT; +const DATE_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'DateWhereInput', + description: 'The DateWhereInput input type is used in operations that involve filtering objects by a field of type Date.', + fields: { + equalTo: equalTo(DATE), + notEqualTo: notEqualTo(DATE), + lessThan: lessThan(DATE), + lessThanOrEqualTo: lessThanOrEqualTo(DATE), + greaterThan: greaterThan(DATE), + greaterThanOrEqualTo: greaterThanOrEqualTo(DATE), + in: inOp(DATE), + notIn: notIn(DATE), + exists, + inQueryKey, + notInQueryKey + } +}); +exports.DATE_WHERE_INPUT = DATE_WHERE_INPUT; +const BYTES_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'BytesWhereInput', + description: 'The BytesWhereInput input type is used in operations that involve filtering objects by a field of type Bytes.', + fields: { + equalTo: equalTo(BYTES), + notEqualTo: notEqualTo(BYTES), + lessThan: lessThan(BYTES), + lessThanOrEqualTo: lessThanOrEqualTo(BYTES), + greaterThan: greaterThan(BYTES), + greaterThanOrEqualTo: greaterThanOrEqualTo(BYTES), + in: inOp(BYTES), + notIn: notIn(BYTES), + exists, + inQueryKey, + notInQueryKey + } +}); +exports.BYTES_WHERE_INPUT = BYTES_WHERE_INPUT; +const FILE_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'FileWhereInput', + description: 'The FileWhereInput input type is used in operations that involve filtering objects by a field of type File.', + fields: { + equalTo: equalTo(FILE), + notEqualTo: notEqualTo(FILE), + lessThan: lessThan(FILE), + lessThanOrEqualTo: lessThanOrEqualTo(FILE), + greaterThan: greaterThan(FILE), + greaterThanOrEqualTo: greaterThanOrEqualTo(FILE), + in: inOp(FILE), + notIn: notIn(FILE), + exists, + inQueryKey, + notInQueryKey, + matchesRegex, + options + } +}); +exports.FILE_WHERE_INPUT = FILE_WHERE_INPUT; +const GEO_POINT_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'GeoPointWhereInput', + description: 'The GeoPointWhereInput input type is used in operations that involve filtering objects by a field of type GeoPoint.', + fields: { + exists, + nearSphere: { + description: 'This is the nearSphere operator to specify a constraint to select the objects where the values of a geo point field is near to another geo point.', + type: GEO_POINT_INPUT + }, + maxDistance: { + description: 'This is the maxDistance operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in radians) from the geo point specified in the $nearSphere operator.', + type: _graphql.GraphQLFloat + }, + maxDistanceInRadians: { + description: 'This is the maxDistanceInRadians operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in radians) from the geo point specified in the $nearSphere operator.', + type: _graphql.GraphQLFloat + }, + maxDistanceInMiles: { + description: 'This is the maxDistanceInMiles operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in miles) from the geo point specified in the $nearSphere operator.', + type: _graphql.GraphQLFloat + }, + maxDistanceInKilometers: { + description: 'This is the maxDistanceInKilometers operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in kilometers) from the geo point specified in the $nearSphere operator.', + type: _graphql.GraphQLFloat + }, + within: { + description: 'This is the within operator to specify a constraint to select the objects where the values of a geo point field is within a specified box.', + type: WITHIN_INPUT + }, + geoWithin: { + description: 'This is the geoWithin operator to specify a constraint to select the objects where the values of a geo point field is within a specified polygon or sphere.', + type: GEO_WITHIN_INPUT + } + } +}); +exports.GEO_POINT_WHERE_INPUT = GEO_POINT_WHERE_INPUT; +const POLYGON_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'PolygonWhereInput', + description: 'The PolygonWhereInput input type is used in operations that involve filtering objects by a field of type Polygon.', + fields: { + exists, + geoIntersects: { + description: 'This is the geoIntersects operator to specify a constraint to select the objects where the values of a polygon field intersect a specified point.', + type: GEO_INTERSECTS_INPUT + } + } +}); +exports.POLYGON_WHERE_INPUT = POLYGON_WHERE_INPUT; +const FIND_RESULT = new _graphql.GraphQLObjectType({ + name: 'FindResult', + description: 'The FindResult object type is used in the find queries to return the data of the matched objects.', + fields: { + results: { + description: 'This is the objects returned by the query', + type: new _graphql.GraphQLNonNull(new _graphql.GraphQLList(new _graphql.GraphQLNonNull(OBJECT))) + }, + count: COUNT_ATT + } +}); +exports.FIND_RESULT = FIND_RESULT; +const ELEMENT = new _graphql.GraphQLObjectType({ + name: 'Element', + description: "The Element object type is used to return array items' value.", + fields: { + value: { + description: 'Return the value of the element in the array', + type: new _graphql.GraphQLNonNull(ANY) + } + } +}); // Default static union type, we update types and resolveType function later + +exports.ELEMENT = ELEMENT; +let ARRAY_RESULT; +exports.ARRAY_RESULT = ARRAY_RESULT; + +const loadArrayResult = (parseGraphQLSchema, parseClasses) => { + const classTypes = parseClasses.filter(parseClass => parseGraphQLSchema.parseClassTypes[parseClass.className].classGraphQLOutputType ? true : false).map(parseClass => parseGraphQLSchema.parseClassTypes[parseClass.className].classGraphQLOutputType); + exports.ARRAY_RESULT = ARRAY_RESULT = new _graphql.GraphQLUnionType({ + name: 'ArrayResult', + description: 'Use Inline Fragment on Array to get results: https://graphql.org/learn/queries/#inline-fragments', + types: () => [ELEMENT, ...classTypes], + resolveType: value => { + if (value.__type === 'Object' && value.className && value.objectId) { + if (parseGraphQLSchema.parseClassTypes[value.className]) { + return parseGraphQLSchema.parseClassTypes[value.className].classGraphQLOutputType; + } else { + return ELEMENT; + } + } else { + return ELEMENT; + } + } + }); + parseGraphQLSchema.graphQLTypes.push(ARRAY_RESULT); +}; + +exports.loadArrayResult = loadArrayResult; + +const load = parseGraphQLSchema => { + parseGraphQLSchema.addGraphQLType(_graphqlUpload.GraphQLUpload, true); + parseGraphQLSchema.addGraphQLType(ANY, true); + parseGraphQLSchema.addGraphQLType(OBJECT, true); + parseGraphQLSchema.addGraphQLType(DATE, true); + parseGraphQLSchema.addGraphQLType(BYTES, true); + parseGraphQLSchema.addGraphQLType(FILE, true); + parseGraphQLSchema.addGraphQLType(FILE_INFO, true); + parseGraphQLSchema.addGraphQLType(GEO_POINT_INPUT, true); + parseGraphQLSchema.addGraphQLType(GEO_POINT, true); + parseGraphQLSchema.addGraphQLType(PARSE_OBJECT, true); + parseGraphQLSchema.addGraphQLType(READ_PREFERENCE, true); + parseGraphQLSchema.addGraphQLType(READ_OPTIONS_INPUT, true); + parseGraphQLSchema.addGraphQLType(SUBQUERY_INPUT, true); + parseGraphQLSchema.addGraphQLType(SELECT_INPUT, true); + parseGraphQLSchema.addGraphQLType(SEARCH_INPUT, true); + parseGraphQLSchema.addGraphQLType(TEXT_INPUT, true); + parseGraphQLSchema.addGraphQLType(BOX_INPUT, true); + parseGraphQLSchema.addGraphQLType(WITHIN_INPUT, true); + parseGraphQLSchema.addGraphQLType(CENTER_SPHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(GEO_WITHIN_INPUT, true); + parseGraphQLSchema.addGraphQLType(GEO_INTERSECTS_INPUT, true); + parseGraphQLSchema.addGraphQLType(STRING_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(NUMBER_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(BOOLEAN_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(ARRAY_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(KEY_VALUE_INPUT, true); + parseGraphQLSchema.addGraphQLType(OBJECT_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(DATE_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(BYTES_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(FILE_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(GEO_POINT_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(POLYGON_WHERE_INPUT, true); + parseGraphQLSchema.addGraphQLType(FIND_RESULT, true); + parseGraphQLSchema.addGraphQLType(ELEMENT, true); + parseGraphQLSchema.addGraphQLType(OBJECT_ID, true); + parseGraphQLSchema.addGraphQLType(ACL_INPUT, true); + parseGraphQLSchema.addGraphQLType(USER_ACL_INPUT, true); + parseGraphQLSchema.addGraphQLType(ROLE_ACL_INPUT, true); + parseGraphQLSchema.addGraphQLType(PUBLIC_ACL_INPUT, true); + parseGraphQLSchema.addGraphQLType(ACL, true); + parseGraphQLSchema.addGraphQLType(USER_ACL, true); + parseGraphQLSchema.addGraphQLType(ROLE_ACL, true); + parseGraphQLSchema.addGraphQLType(PUBLIC_ACL, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcy5qcyJdLCJuYW1lcyI6WyJUeXBlVmFsaWRhdGlvbkVycm9yIiwiRXJyb3IiLCJjb25zdHJ1Y3RvciIsInZhbHVlIiwidHlwZSIsInBhcnNlU3RyaW5nVmFsdWUiLCJwYXJzZUludFZhbHVlIiwiaW50IiwiTnVtYmVyIiwiaXNJbnRlZ2VyIiwicGFyc2VGbG9hdFZhbHVlIiwiZmxvYXQiLCJpc05hTiIsInBhcnNlQm9vbGVhblZhbHVlIiwicGFyc2VWYWx1ZSIsImtpbmQiLCJLaW5kIiwiU1RSSU5HIiwiSU5UIiwiRkxPQVQiLCJCT09MRUFOIiwiTElTVCIsInBhcnNlTGlzdFZhbHVlcyIsInZhbHVlcyIsIk9CSkVDVCIsInBhcnNlT2JqZWN0RmllbGRzIiwiZmllbGRzIiwiQXJyYXkiLCJpc0FycmF5IiwibWFwIiwicmVkdWNlIiwib2JqZWN0IiwiZmllbGQiLCJuYW1lIiwiQU5ZIiwiR3JhcGhRTFNjYWxhclR5cGUiLCJkZXNjcmlwdGlvbiIsInNlcmlhbGl6ZSIsInBhcnNlTGl0ZXJhbCIsImFzdCIsInBhcnNlRGF0ZUlzb1ZhbHVlIiwiZGF0ZSIsIkRhdGUiLCJzZXJpYWxpemVEYXRlSXNvIiwidG9VVENTdHJpbmciLCJwYXJzZURhdGVJc29MaXRlcmFsIiwiREFURSIsIl9fdHlwZSIsImlzbyIsImZpbmQiLCJCWVRFUyIsImJhc2U2NCIsInBhcnNlRmlsZVZhbHVlIiwidXJsIiwidW5kZWZpbmVkIiwiRklMRSIsIkZJTEVfSU5GTyIsIkdyYXBoUUxPYmplY3RUeXBlIiwiR3JhcGhRTE5vbk51bGwiLCJHcmFwaFFMU3RyaW5nIiwiR0VPX1BPSU5UX0ZJRUxEUyIsImxhdGl0dWRlIiwiR3JhcGhRTEZsb2F0IiwibG9uZ2l0dWRlIiwiR0VPX1BPSU5UX0lOUFVUIiwiR3JhcGhRTElucHV0T2JqZWN0VHlwZSIsIkdFT19QT0lOVCIsIlBPTFlHT05fSU5QVVQiLCJHcmFwaFFMTGlzdCIsIlBPTFlHT04iLCJVU0VSX0FDTF9JTlBVVCIsInVzZXJJZCIsIkdyYXBoUUxJRCIsInJlYWQiLCJHcmFwaFFMQm9vbGVhbiIsIndyaXRlIiwiUk9MRV9BQ0xfSU5QVVQiLCJyb2xlTmFtZSIsIlBVQkxJQ19BQ0xfSU5QVVQiLCJBQ0xfSU5QVVQiLCJ1c2VycyIsInJvbGVzIiwicHVibGljIiwiVVNFUl9BQ0wiLCJST0xFX0FDTCIsIlBVQkxJQ19BQ0wiLCJBQ0wiLCJyZXNvbHZlIiwicCIsIk9iamVjdCIsImtleXMiLCJmb3JFYWNoIiwicnVsZSIsImluZGV4T2YiLCJwdXNoIiwibGVuZ3RoIiwicmVwbGFjZSIsIk9CSkVDVF9JRCIsIkNMQVNTX05BTUVfQVRUIiwiT0JKRUNUX0lEX0FUVCIsIm9iamVjdElkIiwiQ1JFQVRFRF9BVF9BVFQiLCJVUERBVEVEX0FUX0FUVCIsIklOUFVUX0ZJRUxEUyIsIkNSRUFURV9SRVNVTFRfRklFTERTIiwiaWQiLCJjcmVhdGVkQXQiLCJVUERBVEVfUkVTVUxUX0ZJRUxEUyIsInVwZGF0ZWRBdCIsIlBBUlNFX09CSkVDVF9GSUVMRFMiLCJQQVJTRV9PQkpFQ1QiLCJHcmFwaFFMSW50ZXJmYWNlVHlwZSIsIlNFU1NJT05fVE9LRU5fQVRUIiwiUkVBRF9QUkVGRVJFTkNFIiwiR3JhcGhRTEVudW1UeXBlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJSRUFEX1BSRUZFUkVOQ0VfQVRUIiwiSU5DTFVERV9SRUFEX1BSRUZFUkVOQ0VfQVRUIiwiU1VCUVVFUllfUkVBRF9QUkVGRVJFTkNFX0FUVCIsIlJFQURfT1BUSU9OU19JTlBVVCIsInJlYWRQcmVmZXJlbmNlIiwiaW5jbHVkZVJlYWRQcmVmZXJlbmNlIiwic3VicXVlcnlSZWFkUHJlZmVyZW5jZSIsIlJFQURfT1BUSU9OU19BVFQiLCJXSEVSRV9BVFQiLCJTS0lQX0FUVCIsIkdyYXBoUUxJbnQiLCJMSU1JVF9BVFQiLCJDT1VOVF9BVFQiLCJTVUJRVUVSWV9JTlBVVCIsImNsYXNzTmFtZSIsIndoZXJlIiwiYXNzaWduIiwiU0VMRUNUX0lOUFVUIiwicXVlcnkiLCJrZXkiLCJTRUFSQ0hfSU5QVVQiLCJ0ZXJtIiwibGFuZ3VhZ2UiLCJjYXNlU2Vuc2l0aXZlIiwiZGlhY3JpdGljU2Vuc2l0aXZlIiwiVEVYVF9JTlBVVCIsInNlYXJjaCIsIkJPWF9JTlBVVCIsImJvdHRvbUxlZnQiLCJ1cHBlclJpZ2h0IiwiV0lUSElOX0lOUFVUIiwiYm94IiwiQ0VOVEVSX1NQSEVSRV9JTlBVVCIsImNlbnRlciIsImRpc3RhbmNlIiwiR0VPX1dJVEhJTl9JTlBVVCIsInBvbHlnb24iLCJjZW50ZXJTcGhlcmUiLCJHRU9fSU5URVJTRUNUU19JTlBVVCIsInBvaW50IiwiZXF1YWxUbyIsIm5vdEVxdWFsVG8iLCJsZXNzVGhhbiIsImxlc3NUaGFuT3JFcXVhbFRvIiwiZ3JlYXRlclRoYW4iLCJncmVhdGVyVGhhbk9yRXF1YWxUbyIsImluT3AiLCJub3RJbiIsImV4aXN0cyIsImluUXVlcnlLZXkiLCJub3RJblF1ZXJ5S2V5IiwibWF0Y2hlc1JlZ2V4Iiwib3B0aW9ucyIsIlNUUklOR19XSEVSRV9JTlBVVCIsImluIiwidGV4dCIsIk5VTUJFUl9XSEVSRV9JTlBVVCIsIkJPT0xFQU5fV0hFUkVfSU5QVVQiLCJBUlJBWV9XSEVSRV9JTlBVVCIsImNvbnRhaW5lZEJ5IiwiY29udGFpbnMiLCJLRVlfVkFMVUVfSU5QVVQiLCJPQkpFQ1RfV0hFUkVfSU5QVVQiLCJEQVRFX1dIRVJFX0lOUFVUIiwiQllURVNfV0hFUkVfSU5QVVQiLCJGSUxFX1dIRVJFX0lOUFVUIiwiR0VPX1BPSU5UX1dIRVJFX0lOUFVUIiwibmVhclNwaGVyZSIsIm1heERpc3RhbmNlIiwibWF4RGlzdGFuY2VJblJhZGlhbnMiLCJtYXhEaXN0YW5jZUluTWlsZXMiLCJtYXhEaXN0YW5jZUluS2lsb21ldGVycyIsIndpdGhpbiIsImdlb1dpdGhpbiIsIlBPTFlHT05fV0hFUkVfSU5QVVQiLCJnZW9JbnRlcnNlY3RzIiwiRklORF9SRVNVTFQiLCJyZXN1bHRzIiwiY291bnQiLCJFTEVNRU5UIiwiQVJSQVlfUkVTVUxUIiwibG9hZEFycmF5UmVzdWx0IiwicGFyc2VHcmFwaFFMU2NoZW1hIiwicGFyc2VDbGFzc2VzIiwiY2xhc3NUeXBlcyIsImZpbHRlciIsInBhcnNlQ2xhc3MiLCJwYXJzZUNsYXNzVHlwZXMiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIiwiR3JhcGhRTFVuaW9uVHlwZSIsInR5cGVzIiwicmVzb2x2ZVR5cGUiLCJncmFwaFFMVHlwZXMiLCJsb2FkIiwiYWRkR3JhcGhRTFR5cGUiLCJHcmFwaFFMVXBsb2FkIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBZ0JBOzs7Ozs7OztBQUVBLE1BQU1BLG1CQUFOLFNBQWtDQyxLQUFsQyxDQUF3QztBQUN0Q0MsRUFBQUEsV0FBVyxDQUFDQyxLQUFELEVBQVFDLElBQVIsRUFBYztBQUN2QixVQUFPLEdBQUVELEtBQU0sbUJBQWtCQyxJQUFLLEVBQXRDO0FBQ0Q7O0FBSHFDOzs7O0FBTXhDLE1BQU1DLGdCQUFnQixHQUFHRixLQUFLLElBQUk7QUFDaEMsTUFBSSxPQUFPQSxLQUFQLEtBQWlCLFFBQXJCLEVBQStCO0FBQzdCLFdBQU9BLEtBQVA7QUFDRDs7QUFFRCxRQUFNLElBQUlILG1CQUFKLENBQXdCRyxLQUF4QixFQUErQixRQUEvQixDQUFOO0FBQ0QsQ0FORDs7OztBQVFBLE1BQU1HLGFBQWEsR0FBR0gsS0FBSyxJQUFJO0FBQzdCLE1BQUksT0FBT0EsS0FBUCxLQUFpQixRQUFyQixFQUErQjtBQUM3QixVQUFNSSxHQUFHLEdBQUdDLE1BQU0sQ0FBQ0wsS0FBRCxDQUFsQjs7QUFDQSxRQUFJSyxNQUFNLENBQUNDLFNBQVAsQ0FBaUJGLEdBQWpCLENBQUosRUFBMkI7QUFDekIsYUFBT0EsR0FBUDtBQUNEO0FBQ0Y7O0FBRUQsUUFBTSxJQUFJUCxtQkFBSixDQUF3QkcsS0FBeEIsRUFBK0IsS0FBL0IsQ0FBTjtB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QTRDLElBQTVDO0FBQ0FzSCxFQUFBQSxrQkFBa0IsQ0FBQ1ksY0FBbkIsQ0FBa0NqSSxVQUFsQyxFQUE4QyxJQUE5QztBQUNELENBNUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgS2luZCxcbiAgR3JhcGhRTE5vbk51bGwsXG4gIEdyYXBoUUxTY2FsYXJUeXBlLFxuICBHcmFwaFFMSUQsXG4gIEdyYXBoUUxTdHJpbmcsXG4gIEdyYXBoUUxPYmplY3RUeXBlLFxuICBHcmFwaFFMSW50ZXJmYWNlVHlwZSxcbiAgR3JhcGhRTEVudW1UeXBlLFxuICBHcmFwaFFMSW50LFxuICBHcmFwaFFMRmxvYXQsXG4gIEdyYXBoUUxMaXN0LFxuICBHcmFwaFFMSW5wdXRPYmplY3RUeXBlLFxuICBHcmFwaFFMQm9vbGVhbixcbiAgR3JhcGhRTFVuaW9uVHlwZSxcbn0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgeyBHcmFwaFFMVXBsb2FkIH0gZnJvbSAnZ3JhcGhxbC11cGxvYWQnO1xuXG5jbGFzcyBUeXBlVmFsaWRhdGlvbkVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih2YWx1ZSwgdHlwZSkge1xuICAgIHN1cGVyKGAke3ZhbHVlfSBpcyBub3QgYSB2YWxpZCAke3R5cGV9YCk7XG4gIH1cbn1cblxuY29uc3QgcGFyc2VTdHJpbmdWYWx1ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ1N0cmluZycpO1xufTtcblxuY29uc3QgcGFyc2VJbnRWYWx1ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCBpbnQgPSBOdW1iZXIodmFsdWUpO1xuICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGludCkpIHtcbiAgICAgIHJldHVybiBpbnQ7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdJbnQnKTtcbn07XG5cbmNvbnN0IHBhcnNlRmxvYXRWYWx1ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCBmbG9hdCA9IE51bWJlcih2YWx1ZSk7XG4gICAgaWYgKCFpc05hTihmbG9hdCkpIHtcbiAgICAgIHJldHVybiBmbG9hdDtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0Zsb2F0Jyk7XG59O1xuXG5jb25zdCBwYXJzZUJvb2xlYW5WYWx1ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdCb29sZWFuJyk7XG59O1xuXG5jb25zdCBwYXJzZVZhbHVlID0gdmFsdWUgPT4ge1xuICBzd2l0Y2ggKHZhbHVlLmtpbmQpIHtcbiAgICBjYXNlIEtpbmQuU1RSSU5HOlxuICAgICAgcmV0dXJuIHBhcnNlU3RyaW5nVmFsdWUodmFsdWUudmFsdWUpO1xuXG4gICAgY2FzZSBLaW5kLklOVDpcbiAgICAgIHJldHVybiBwYXJzZUludFZhbHVlKHZhbHVlLnZhbHVlKTtcblxuICAgIGNhc2UgS2luZC5GTE9BVDpcbiAgICAgIHJldHVybiBwYXJzZUZsb2F0VmFsdWUodmFsdWUudmFsdWUpO1xuXG4gICAgY2FzZSBLaW5kLkJPT0xFQU46XG4gICAgICByZXR1cm4gcGFyc2VCb29sZWFuVmFsdWUodmFsdWUudmFsdWUpO1xuXG4gICAgY2FzZSBLaW5kLkxJU1Q6XG4gICAgICByZXR1cm4gcGFyc2VMaXN0VmFsdWVzKHZhbHVlLnZhbHVlcyk7XG5cbiAgICBjYXNlIEtpbmQuT0JKRUNUOlxuICAgICAgcmV0dXJuIHBhcnNlT2JqZWN0RmllbGRzKHZhbHVlLmZpZWxkcyk7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG59O1xuXG5jb25zdCBwYXJzZUxpc3RWYWx1ZXMgPSB2YWx1ZXMgPT4ge1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZXMpKSB7XG4gICAgcmV0dXJuIHZhbHVlcy5tYXAodmFsdWUgPT4gcGFyc2VWYWx1ZSh2YWx1ZSkpO1xuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWVzLCAnTGlzdCcpO1xufTtcblxuY29uc3QgcGFyc2VPYmplY3RGaWVsZHMgPSBmaWVsZHMgPT4ge1xuICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZHMpKSB7XG4gICAgcmV0dXJuIGZpZWxkcy5yZWR1Y2UoXG4gICAgICAob2JqZWN0LCBmaWVsZCkgPT4gKHtcbiAgICAgICAgLi4ub2JqZWN0LFxuICAgICAgICBbZmllbGQubmFtZS52YWx1ZV06IHBhcnNlVmFsdWUoZmllbGQudmFsdWUpLFxuICAgICAgfSksXG4gICAgICB7fVxuICAgICk7XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcihmaWVsZHMsICdPYmplY3QnKTtcbn07XG5cbmNvbnN0IEFOWSA9IG5ldyBHcmFwaFFMU2NhbGFyVHlwZSh7XG4gIG5hbWU6ICdBbnknLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEFueSBzY2FsYXIgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgYW5kIHR5cGVzIHRoYXQgaW52b2x2ZSBhbnkgdHlwZSBvZiB2YWx1ZS4nLFxuICBwYXJzZVZhbHVlOiB2YWx1ZSA9PiB2YWx1ZSxcbiAgc2VyaWFsaXplOiB2YWx1ZSA9PiB2YWx1ZSxcbiAgcGFyc2VMaXRlcmFsOiBhc3QgPT4gcGFyc2VWYWx1ZShhc3QpLFxufSk7XG5cbmNvbnN0IE9CSkVDVCA9IG5ldyBHcmFwaFFMU2NhbGFyVHlwZSh7XG4gIG5hbWU6ICdPYmplY3QnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIE9iamVjdCBzY2FsYXIgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgYW5kIHR5cGVzIHRoYXQgaW52b2x2ZSBvYmplY3RzLicsXG4gIHBhcnNlVmFsdWUodmFsdWUpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnT2JqZWN0Jyk7XG4gIH0sXG4gIHNlcmlhbGl6ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdPYmplY3QnKTtcbiAgfSxcbiAgcGFyc2VMaXRlcmFsKGFzdCkge1xuICAgIGlmIChhc3Qua2luZCA9PT0gS2luZC5PQkpFQ1QpIHtcbiAgICAgIHJldHVybiBwYXJzZU9iamVjdEZpZWxkcyhhc3QuZmllbGRzKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcihhc3Qua2luZCwgJ09iamVjdCcpO1xuICB9LFxufSk7XG5cbmNvbnN0IHBhcnNlRGF0ZUlzb1ZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgaWYgKCFpc05hTihkYXRlKSkge1xuICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxuICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnRGF0ZScpO1xufTtcblxuY29uc3Qgc2VyaWFsaXplRGF0ZUlzbyA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgIHJldHVybiB2YWx1ZS50b1VUQ1N0cmluZygpO1xuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdEYXRlJyk7XG59O1xuXG5jb25zdCBwYXJzZURhdGVJc29MaXRlcmFsID0gYXN0ID0+IHtcbiAgaWYgKGFzdC5raW5kID09PSBLaW5kLlNUUklORykge1xuICAgIHJldHVybiBwYXJzZURhdGVJc29WYWx1ZShhc3QudmFsdWUpO1xuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IoYXN0LmtpbmQsICdEYXRlJyk7XG59O1xuXG5jb25zdCBEQVRFID0gbmV3IEdyYXBoUUxTY2FsYXJUeXBlKHtcbiAgbmFtZTogJ0RhdGUnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIERhdGUgc2NhbGFyIHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIGFuZCB0eXBlcyB0aGF0IGludm9sdmUgZGF0ZXMuJyxcbiAgcGFyc2VWYWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgX190eXBlOiAnRGF0ZScsXG4gICAgICAgIGlzbzogcGFyc2VEYXRlSXNvVmFsdWUodmFsdWUpLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgdmFsdWUuX190eXBlID09PSAnRGF0ZScgJiZcbiAgICAgIHZhbHVlLmlzb1xuICAgICkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgX190eXBlOiB2YWx1ZS5fX3R5cGUsXG4gICAgICAgIGlzbzogcGFyc2VEYXRlSXNvVmFsdWUodmFsdWUuaXNvKSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdEYXRlJyk7XG4gIH0sXG4gIHNlcmlhbGl6ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgcmV0dXJuIHNlcmlhbGl6ZURhdGVJc28odmFsdWUpO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICB2YWx1ZS5fX3R5cGUgPT09ICdEYXRlJyAmJlxuICAgICAgdmFsdWUuaXNvXG4gICAgKSB7XG4gICAgICByZXR1cm4gc2VyaWFsaXplRGF0ZUlzbyh2YWx1ZS5pc28pO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnRGF0ZScpO1xuICB9LFxuICBwYXJzZUxpdGVyYWwoYXN0KSB7XG4gICAgaWYgKGFzdC5raW5kID09PSBLaW5kLlNUUklORykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgX190eXBlOiAnRGF0ZScsXG4gICAgICAgIGlzbzogcGFyc2VEYXRlSXNvTGl0ZXJhbChhc3QpLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKGFzdC5raW5kID09PSBLaW5kLk9CSkVDVCkge1xuICAgICAgY29uc3QgX190eXBlID0gYXN0LmZpZWxkcy5maW5kKGZpZWxkID0+IGZpZWxkLm5hbWUudmFsdWUgPT09ICdfX3R5cGUnKTtcbiAgICAgIGNvbnN0IGlzbyA9IGFzdC5maWVsZHMuZmluZChmaWVsZCA9PiBmaWVsZC5uYW1lLnZhbHVlID09PSAnaXNvJyk7XG4gICAgICBpZiAoX190eXBlICYmIF9fdHlwZS52YWx1ZSAmJiBfX3R5cGUudmFsdWUudmFsdWUgPT09ICdEYXRlJyAmJiBpc28pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBfX3R5cGU6IF9fdHlwZS52YWx1ZS52YWx1ZSxcbiAgICAgICAgICBpc286IHBhcnNlRGF0ZUlzb0xpdGVyYWwoaXNvLnZhbHVlKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcihhc3Qua2luZCwgJ0RhdGUnKTtcbiAgfSxcbn0pO1xuXG5jb25zdCBCWVRFUyA9IG5ldyBHcmFwaFFMU2NhbGFyVHlwZSh7XG4gIG5hbWU6ICdCeXRlcycsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgQnl0ZXMgc2NhbGFyIHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIGFuZCB0eXBlcyB0aGF0IGludm9sdmUgYmFzZSA2NCBiaW5hcnkgZGF0YS4nLFxuICBwYXJzZVZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIF9fdHlwZTogJ0J5dGVzJyxcbiAgICAgICAgYmFzZTY0OiB2YWx1ZSxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHZhbHVlLl9fdHlwZSA9PT0gJ0J5dGVzJyAmJlxuICAgICAgdHlwZW9mIHZhbHVlLmJhc2U2NCA9PT0gJ3N0cmluZydcbiAgICApIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0J5dGVzJyk7XG4gIH0sXG4gIHNlcmlhbGl6ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHZhbHVlLl9fdHlwZSA9PT0gJ0J5dGVzJyAmJlxuICAgICAgdHlwZW9mIHZhbHVlLmJhc2U2NCA9PT0gJ3N0cmluZydcbiAgICApIHtcbiAgICAgIHJldHVybiB2YWx1ZS5iYXNlNjQ7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdCeXRlcycpO1xuICB9LFxuICBwYXJzZUxpdGVyYWwoYXN0KSB7XG4gICAgaWYgKGFzdC5raW5kID09PSBLaW5kLlNUUklORykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgX190eXBlOiAnQnl0ZXMnLFxuICAgICAgICBiYXNlNjQ6IGFzdC52YWx1ZSxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChhc3Qua2luZCA9PT0gS2luZC5PQkpFQ1QpIHtcbiAgICAgIGNvbnN0IF9fdHlwZSA9IGFzdC5maWVsZHMuZmluZChmaWVsZCA9PiBmaWVsZC5uYW1lLnZhbHVlID09PSAnX190eXBlJyk7XG4gICAgICBjb25zdCBiYXNlNjQgPSBhc3QuZmllbGRzLmZpbmQoZmllbGQgPT4gZmllbGQubmFtZS52YWx1ZSA9PT0gJ2Jhc2U2NCcpO1xuICAgICAgaWYgKFxuICAgICAgICBfX3R5cGUgJiZcbiAgICAgICAgX190eXBlLnZhbHVlICYmXG4gICAgICAgIF9fdHlwZS52YWx1ZS52YWx1ZSA9PT0gJ0J5dGVzJyAmJlxuICAgICAgICBiYXNlNjQgJiZcbiAgICAgICAgYmFzZTY0LnZhbHVlICYmXG4gICAgICAgIHR5cGVvZiBiYXNlNjQudmFsdWUudmFsdWUgPT09ICdzdHJpbmcnXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBfX3R5cGU6IF9fdHlwZS52YWx1ZS52YWx1ZSxcbiAgICAgICAgICBiYXNlNjQ6IGJhc2U2NC52YWx1ZS52YWx1ZSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcihhc3Qua2luZCwgJ0J5dGVzJyk7XG4gIH0sXG59KTtcblxuY29uc3QgcGFyc2VGaWxlVmFsdWUgPSB2YWx1ZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIF9fdHlwZTogJ0ZpbGUnLFxuICAgICAgbmFtZTogdmFsdWUsXG4gICAgfTtcbiAgfSBlbHNlIGlmIChcbiAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgdmFsdWUuX190eXBlID09PSAnRmlsZScgJiZcbiAgICB0eXBlb2YgdmFsdWUubmFtZSA9PT0gJ3N0cmluZycgJiZcbiAgICAodmFsdWUudXJsID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIHZhbHVlLnVybCA9PT0gJ3N0cmluZycpXG4gICkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnRmlsZScpO1xufTtcblxuY29uc3QgRklMRSA9IG5ldyBHcmFwaFFMU2NhbGFyVHlwZSh7XG4gIG5hbWU6ICdGaWxlJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBGaWxlIHNjYWxhciB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyBhbmQgdHlwZXMgdGhhdCBpbnZvbHZlIGZpbGVzLicsXG4gIHBhcnNlVmFsdWU6IHBhcnNlRmlsZVZhbHVlLFxuICBzZXJpYWxpemU6IHZhbHVlID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICB2YWx1ZS5fX3R5cGUgPT09ICdGaWxlJyAmJlxuICAgICAgdHlwZW9mIHZhbHVlLm5hbWUgPT09ICdzdHJpbmcnICYmXG4gICAgICAodmFsdWUudXJsID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIHZhbHVlLnVybCA9PT0gJ3N0cmluZycpXG4gICAgKSB7XG4gICAgICByZXR1cm4gdmFsdWUubmFtZTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0ZpbGUnKTtcbiAgfSxcbiAgcGFyc2VMaXRlcmFsKGFzdCkge1xuICAgIGlmIChhc3Qua2luZCA9PT0gS2luZC5TVFJJTkcpIHtcbiAgICAgIHJldHVybiBwYXJzZUZpbGVWYWx1ZShhc3QudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAoYXN0LmtpbmQgPT09IEtpbmQuT0JKRUNUKSB7XG4gICAgICBjb25zdCBfX3R5cGUgPSBhc3QuZmllbGRzLmZpbmQoZmllbGQgPT4gZmllbGQubmFtZS52YWx1ZSA9PT0gJ19fdHlwZScpO1xuICAgICAgY29uc3QgbmFtZSA9IGFzdC5maWVsZHMuZmluZChmaWVsZCA9PiBmaWVsZC5uYW1lLnZhbHVlID09PSAnbmFtZScpO1xuICAgICAgY29uc3QgdXJsID0gYXN0LmZpZWxkcy5maW5kKGZpZWxkID0+IGZpZWxkLm5hbWUudmFsdWUgPT09ICd1cmwnKTtcbiAgICAgIGlmIChfX3R5cGUgJiYgX190eXBlLnZhbHVlICYmIG5hbWUgJiYgbmFtZS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gcGFyc2VGaWxlVmFsdWUoe1xuICAgICAgICAgIF9fdHlwZTogX190eXBlLnZhbHVlLnZhbHVlLFxuICAgICAgICAgIG5hbWU6IG5hbWUudmFsdWUudmFsdWUsXG4gICAgICAgICAgdXJsOiB1cmwgJiYgdXJsLnZhbHVlID8gdXJsLnZhbHVlLnZhbHVlIDogdW5kZWZpbmVkLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcihhc3Qua2luZCwgJ0ZpbGUnKTtcbiAgfSxcbn0pO1xuXG5jb25zdCBGSUxFX0lORk8gPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnRmlsZUluZm8nLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEZpbGVJbmZvIG9iamVjdCB0eXBlIGlzIHVzZWQgdG8gcmV0dXJuIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBmaWxlcy4nLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGZpbGUgbmFtZS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgIH0sXG4gICAgdXJsOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHVybCBpbiB3aGljaCB0aGUgZmlsZSBjYW4gYmUgZG93bmxvYWRlZC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgR0VPX1BPSU5UX0ZJRUxEUyA9IHtcbiAgbGF0aXR1ZGU6IHtcbiAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGxhdGl0dWRlLicsXG4gICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxGbG9hdCksXG4gIH0sXG4gIGxvbmdpdHVkZToge1xuICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgbG9uZ2l0dWRlLicsXG4gICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxGbG9hdCksXG4gIH0sXG59O1xuXG5jb25zdCBHRU9fUE9JTlRfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdHZW9Qb2ludElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBHZW9Qb2ludElucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBpbnB1dHRpbmcgZmllbGRzIG9mIHR5cGUgZ2VvIHBvaW50LicsXG4gIGZpZWxkczogR0VPX1BPSU5UX0ZJRUxEUyxcbn0pO1xuXG5jb25zdCBHRU9fUE9JTlQgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnR2VvUG9pbnQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEdlb1BvaW50IG9iamVjdCB0eXBlIGlzIHVzZWQgdG8gcmV0dXJuIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBnZW8gcG9pbnQgZmllbGRzLicsXG4gIGZpZWxkczogR0VPX1BPSU5UX0ZJRUxEUyxcbn0pO1xuXG5jb25zdCBQT0xZR09OX0lOUFVUID0gbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChHRU9fUE9JTlRfSU5QVVQpKTtcblxuY29uc3QgUE9MWUdPTiA9IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoR0VPX1BPSU5UKSk7XG5cbmNvbnN0IFVTRVJfQUNMX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnVXNlckFDTElucHV0JyxcbiAgZGVzY3JpcHRpb246ICdBbGxvdyB0byBtYW5hZ2UgdXNlcnMgaW4gQUNMLicsXG4gIGZpZWxkczoge1xuICAgIHVzZXJJZDoge1xuICAgICAgZGVzY3JpcHRpb246ICdJRCBvZiB0aGUgdGFyZ2V0dGVkIFVzZXIuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMSUQpLFxuICAgIH0sXG4gICAgcmVhZDoge1xuICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyB0aGUgdXNlciB0byByZWFkIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICAgIHdyaXRlOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IHRoZSB1c2VyIHRvIHdyaXRlIG9uIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IFJPTEVfQUNMX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnUm9sZUFDTElucHV0JyxcbiAgZGVzY3JpcHRpb246ICdBbGxvdyB0byBtYW5hZ2Ugcm9sZXMgaW4gQUNMLicsXG4gIGZpZWxkczoge1xuICAgIHJvbGVOYW1lOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ05hbWUgb2YgdGhlIHRhcmdldHRlZCBSb2xlLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFN0cmluZyksXG4gICAgfSxcbiAgICByZWFkOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ0FsbG93IHVzZXJzIHdobyBhcmUgbWVtYmVycyBvZiB0aGUgcm9sZSB0byByZWFkIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICAgIHdyaXRlOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ0FsbG93IHVzZXJzIHdobyBhcmUgbWVtYmVycyBvZiB0aGUgcm9sZSB0byB3cml0ZSBvbiB0aGUgY3VycmVudCBvYmplY3QuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbiksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBQVUJMSUNfQUNMX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnUHVibGljQUNMSW5wdXQnLFxuICBkZXNjcmlwdGlvbjogJ0FsbG93IHRvIG1hbmFnZSBwdWJsaWMgcmlnaHRzLicsXG4gIGZpZWxkczoge1xuICAgIHJlYWQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgYW55b25lIHRvIHJlYWQgdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgIH0sXG4gICAgd3JpdGU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgYW55b25lIHRvIHdyaXRlIG9uIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IEFDTF9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ0FDTElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ0FsbG93IHRvIG1hbmFnZSBhY2Nlc3MgcmlnaHRzLiBJZiBub3QgcHJvdmlkZWQgb2JqZWN0IHdpbGwgYmUgcHVibGljbHkgcmVhZGFibGUgYW5kIHdyaXRhYmxlJyxcbiAgZmllbGRzOiB7XG4gICAgdXNlcnM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWNjZXNzIGNvbnRyb2wgbGlzdCBmb3IgdXNlcnMuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoVVNFUl9BQ0xfSU5QVVQpKSxcbiAgICB9LFxuICAgIHJvbGVzOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FjY2VzcyBjb250cm9sIGxpc3QgZm9yIHJvbGVzLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKFJPTEVfQUNMX0lOUFVUKSksXG4gICAgfSxcbiAgICBwdWJsaWM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnUHVibGljIGFjY2VzcyBjb250cm9sIGxpc3QuJyxcbiAgICAgIHR5cGU6IFBVQkxJQ19BQ0xfSU5QVVQsXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBVU0VSX0FDTCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdVc2VyQUNMJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ0FsbG93IHRvIG1hbmFnZSB1c2VycyBpbiBBQ0wuIElmIHJlYWQgYW5kIHdyaXRlIGFyZSBudWxsIHRoZSB1c2VycyBoYXZlIHJlYWQgYW5kIHdyaXRlIHJpZ2h0cy4nLFxuICBmaWVsZHM6IHtcbiAgICB1c2VySWQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnSUQgb2YgdGhlIHRhcmdldHRlZCBVc2VyLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTElEKSxcbiAgICB9LFxuICAgIHJlYWQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgdGhlIHVzZXIgdG8gcmVhZCB0aGUgY3VycmVudCBvYmplY3QuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbiksXG4gICAgfSxcbiAgICB3cml0ZToge1xuICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyB0aGUgdXNlciB0byB3cml0ZSBvbiB0aGUgY3VycmVudCBvYmplY3QuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbiksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBST0xFX0FDTCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdSb2xlQUNMJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ0FsbG93IHRvIG1hbmFnZSByb2xlcyBpbiBBQ0wuIElmIHJlYWQgYW5kIHdyaXRlIGFyZSBudWxsIHRoZSByb2xlIGhhdmUgcmVhZCBhbmQgd3JpdGUgcmlnaHRzLicsXG4gIGZpZWxkczoge1xuICAgIHJvbGVOYW1lOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ05hbWUgb2YgdGhlIHRhcmdldHRlZCBSb2xlLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTElEKSxcbiAgICB9LFxuICAgIHJlYWQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnQWxsb3cgdXNlcnMgd2hvIGFyZSBtZW1iZXJzIG9mIHRoZSByb2xlIHRvIHJlYWQgdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgIH0sXG4gICAgd3JpdGU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnQWxsb3cgdXNlcnMgd2hvIGFyZSBtZW1iZXJzIG9mIHRoZSByb2xlIHRvIHdyaXRlIG9uIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IFBVQkxJQ19BQ0wgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnUHVibGljQUNMJyxcbiAgZGVzY3JpcHRpb246ICdBbGxvdyB0byBtYW5hZ2UgcHVibGljIHJpZ2h0cy4nLFxuICBmaWVsZHM6IHtcbiAgICByZWFkOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IGFueW9uZSB0byByZWFkIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogR3JhcGhRTEJvb2xlYW4sXG4gICAgfSxcbiAgICB3cml0ZToge1xuICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyBhbnlvbmUgdG8gd3JpdGUgb24gdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBHcmFwaFFMQm9vbGVhbixcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IEFDTCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdBQ0wnLFxuICBkZXNjcmlwdGlvbjogJ0N1cnJlbnQgYWNjZXNzIGNvbnRyb2wgbGlzdCBvZiB0aGUgY3VycmVudCBvYmplY3QuJyxcbiAgZmllbGRzOiB7XG4gICAgdXNlcnM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWNjZXNzIGNvbnRyb2wgbGlzdCBmb3IgdXNlcnMuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoVVNFUl9BQ0wpKSxcbiAgICAgIHJlc29sdmUocCkge1xuICAgICAgICBjb25zdCB1c2VycyA9IFtdO1xuICAgICAgICBPYmplY3Qua2V5cyhwKS5mb3JFYWNoKHJ1bGUgPT4ge1xuICAgICAgICAgIGlmIChydWxlICE9PSAnKicgJiYgcnVsZS5pbmRleE9mKCdyb2xlOicpICE9PSAwKSB7XG4gICAgICAgICAgICB1c2Vycy5wdXNoKHtcbiAgICAgICAgICAgICAgdXNlcklkOiBydWxlLFxuICAgICAgICAgICAgICByZWFkOiBwW3J1bGVdLnJlYWQgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgICAgIHdyaXRlOiBwW3J1bGVdLndyaXRlID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHVzZXJzLmxlbmd0aCA/IHVzZXJzIDogbnVsbDtcbiAgICAgIH0sXG4gICAgfSxcbiAgICByb2xlczoge1xuICAgICAgZGVzY3JpcHRpb246ICdBY2Nlc3MgY29udHJvbCBsaXN0IGZvciByb2xlcy4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChST0xFX0FDTCkpLFxuICAgICAgcmVzb2x2ZShwKSB7XG4gICAgICAgIGNvbnN0IHJvbGVzID0gW107XG4gICAgICAgIE9iamVjdC5rZXlzKHApLmZvckVhY2gocnVsZSA9PiB7XG4gICAgICAgICAgaWYgKHJ1bGUuaW5kZXhPZigncm9sZTonKSA9PT0gMCkge1xuICAgICAgICAgICAgcm9sZXMucHVzaCh7XG4gICAgICAgICAgICAgIHJvbGVOYW1lOiBydWxlLnJlcGxhY2UoJ3JvbGU6JywgJycpLFxuICAgICAgICAgICAgICByZWFkOiBwW3J1bGVdLnJlYWQgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgICAgIHdyaXRlOiBwW3J1bGVdLndyaXRlID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJvbGVzLmxlbmd0aCA/IHJvbGVzIDogbnVsbDtcbiAgICAgIH0sXG4gICAgfSxcbiAgICBwdWJsaWM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnUHVibGljIGFjY2VzcyBjb250cm9sIGxpc3QuJyxcbiAgICAgIHR5cGU6IFBVQkxJQ19BQ0wsXG4gICAgICByZXNvbHZlKHApIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgKi9cbiAgICAgICAgcmV0dXJuIHBbJyonXVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICByZWFkOiBwWycqJ10ucmVhZCA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICAgICAgd3JpdGU6IHBbJyonXS53cml0ZSA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICA6IG51bGw7XG4gICAgICB9LFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgT0JKRUNUX0lEID0gbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxJRCk7XG5cbmNvbnN0IENMQVNTX05BTUVfQVRUID0ge1xuICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGNsYXNzIG5hbWUgb2YgdGhlIG9iamVjdC4nLFxuICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFN0cmluZyksXG59O1xuXG5jb25zdCBPQkpFQ1RfSURfQVRUID0ge1xuICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIG9iamVjdCBpZC4nLFxuICB0eXBlOiBPQkpFQ1RfSUQsXG4gIHJlc29sdmU6ICh7IG9iamVjdElkIH0pID0+IG9iamVjdElkLFxufTtcblxuY29uc3QgQ1JFQVRFRF9BVF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgZGF0ZSBpbiB3aGljaCB0aGUgb2JqZWN0IHdhcyBjcmVhdGVkLicsXG4gIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChEQVRFKSxcbn07XG5cbmNvbnN0IFVQREFURURfQVRfQVRUID0ge1xuICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGRhdGUgaW4gd2hpY2ggdGhlIG9iamVjdCB3YXMgbGFzIHVwZGF0ZWQuJyxcbiAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKERBVEUpLFxufTtcblxuY29uc3QgSU5QVVRfRklFTERTID0ge1xuICBBQ0w6IHtcbiAgICB0eXBlOiBBQ0wsXG4gIH0sXG59O1xuXG5jb25zdCBDUkVBVEVfUkVTVUxUX0ZJRUxEUyA9IHtcbiAgaWQ6IE9CSkVDVF9JRF9BVFQsXG4gIGNyZWF0ZWRBdDogQ1JFQVRFRF9BVF9BVFQsXG59O1xuXG5jb25zdCBVUERBVEVfUkVTVUxUX0ZJRUxEUyA9IHtcbiAgdXBkYXRlZEF0OiBVUERBVEVEX0FUX0FUVCxcbn07XG5cbmNvbnN0IFBBUlNFX09CSkVDVF9GSUVMRFMgPSB7XG4gIC4uLkNSRUFURV9SRVNVTFRfRklFTERTLFxuICAuLi5VUERBVEVfUkVTVUxUX0ZJRUxEUyxcbiAgLi4uSU5QVVRfRklFTERTLFxufTtcblxuY29uc3QgUEFSU0VfT0JKRUNUID0gbmV3IEdyYXBoUUxJbnRlcmZhY2VUeXBlKHtcbiAgbmFtZTogJ1BhcnNlT2JqZWN0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBQYXJzZU9iamVjdCBpbnRlcmZhY2UgdHlwZSBpcyB1c2VkIGFzIGEgYmFzZSB0eXBlIGZvciB0aGUgYXV0byBnZW5lcmF0ZWQgb2JqZWN0IHR5cGVzLicsXG4gIGZpZWxkczogUEFSU0VfT0JKRUNUX0ZJRUxEUyxcbn0pO1xuXG5jb25zdCBTRVNTSU9OX1RPS0VOX0FUVCA9IHtcbiAgZGVzY3JpcHRpb246ICdUaGUgdXNlciBzZXNzaW9uIHRva2VuJyxcbiAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxufTtcblxuY29uc3QgUkVBRF9QUkVGRVJFTkNFID0gbmV3IEdyYXBoUUxFbnVtVHlwZSh7XG4gIG5hbWU6ICdSZWFkUHJlZmVyZW5jZScsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgUmVhZFByZWZlcmVuY2UgZW51bSB0eXBlIGlzIHVzZWQgaW4gcXVlcmllcyBpbiBvcmRlciB0byBzZWxlY3QgaW4gd2hpY2ggZGF0YWJhc2UgcmVwbGljYSB0aGUgb3BlcmF0aW9uIG11c3QgcnVuLicsXG4gIHZhbHVlczoge1xuICAgIFBSSU1BUlk6IHsgdmFsdWU6ICdQUklNQVJZJyB9LFxuICAgIFBSSU1BUllfUFJFRkVSUkVEOiB7IHZhbHVlOiAnUFJJTUFSWV9QUkVGRVJSRUQnIH0sXG4gICAgU0VDT05EQVJZOiB7IHZhbHVlOiAnU0VDT05EQVJZJyB9LFxuICAgIFNFQ09OREFSWV9QUkVGRVJSRUQ6IHsgdmFsdWU6ICdTRUNPTkRBUllfUFJFRkVSUkVEJyB9LFxuICAgIE5FQVJFU1Q6IHsgdmFsdWU6ICdORUFSRVNUJyB9LFxuICB9LFxufSk7XG5cbmNvbnN0IFJFQURfUFJFRkVSRU5DRV9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhlIHJlYWQgcHJlZmVyZW5jZSBmb3IgdGhlIG1haW4gcXVlcnkgdG8gYmUgZXhlY3V0ZWQuJyxcbiAgdHlwZTogUkVBRF9QUkVGRVJFTkNFLFxufTtcblxuY29uc3QgSU5DTFVERV9SRUFEX1BSRUZFUkVOQ0VfQVRUID0ge1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIHJlYWQgcHJlZmVyZW5jZSBmb3IgdGhlIHF1ZXJpZXMgdG8gYmUgZXhlY3V0ZWQgdG8gaW5jbHVkZSBmaWVsZHMuJyxcbiAgdHlwZTogUkVBRF9QUkVGRVJFTkNFLFxufTtcblxuY29uc3QgU1VCUVVFUllfUkVBRF9QUkVGRVJFTkNFX0FUVCA9IHtcbiAgZGVzY3JpcHRpb246ICdUaGUgcmVhZCBwcmVmZXJlbmNlIGZvciB0aGUgc3VicXVlcmllcyB0aGF0IG1heSBiZSByZXF1aXJlZC4nLFxuICB0eXBlOiBSRUFEX1BSRUZFUkVOQ0UsXG59O1xuXG5jb25zdCBSRUFEX09QVElPTlNfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdSZWFkT3B0aW9uc0lucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBSZWFkT3B0aW9uc0lucHV0dCB0eXBlIGlzIHVzZWQgaW4gcXVlcmllcyBpbiBvcmRlciB0byBzZXQgdGhlIHJlYWQgcHJlZmVyZW5jZXMuJyxcbiAgZmllbGRzOiB7XG4gICAgcmVhZFByZWZlcmVuY2U6IFJFQURfUFJFRkVSRU5DRV9BVFQsXG4gICAgaW5jbHVkZVJlYWRQcmVmZXJlbmNlOiBJTkNMVURFX1JFQURfUFJFRkVSRU5DRV9BVFQsXG4gICAgc3VicXVlcnlSZWFkUHJlZmVyZW5jZTogU1VCUVVFUllfUkVBRF9QUkVGRVJFTkNFX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBSRUFEX09QVElPTlNfQVRUID0ge1xuICBkZXNjcmlwdGlvbjogJ1RoZSByZWFkIG9wdGlvbnMgZm9yIHRoZSBxdWVyeSB0byBiZSBleGVjdXRlZC4nLFxuICB0eXBlOiBSRUFEX09QVElPTlNfSU5QVVQsXG59O1xuXG5jb25zdCBXSEVSRV9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGVzZSBhcmUgdGhlIGNvbmRpdGlvbnMgdGhhdCB0aGUgb2JqZWN0cyBuZWVkIHRvIG1hdGNoIGluIG9yZGVyIHRvIGJlIGZvdW5kJyxcbiAgdHlwZTogT0JKRUNULFxufTtcblxuY29uc3QgU0tJUF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgbnVtYmVyIG9mIG9iamVjdHMgdGhhdCBtdXN0IGJlIHNraXBwZWQgdG8gcmV0dXJuLicsXG4gIHR5cGU6IEdyYXBoUUxJbnQsXG59O1xuXG5jb25zdCBMSU1JVF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgbGltaXQgbnVtYmVyIG9mIG9iamVjdHMgdGhhdCBtdXN0IGJlIHJldHVybmVkLicsXG4gIHR5cGU6IEdyYXBoUUxJbnQsXG59O1xuXG5jb25zdCBDT1VOVF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSB0b3RhbCBtYXRjaGVkIG9iamVjcyBjb3VudCB0aGF0IGlzIHJldHVybmVkIHdoZW4gdGhlIGNvdW50IGZsYWcgaXMgc2V0LicsXG4gIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMSW50KSxcbn07XG5cbmNvbnN0IFNVQlFVRVJZX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU3VicXVlcnlJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU3VicXVlcnlJbnB1dCB0eXBlIGlzIHVzZWQgdG8gc3BlY2lmeSBhIHN1YiBxdWVyeSB0byBhbm90aGVyIGNsYXNzLicsXG4gIGZpZWxkczoge1xuICAgIGNsYXNzTmFtZTogQ0xBU1NfTkFNRV9BVFQsXG4gICAgd2hlcmU6IE9iamVjdC5hc3NpZ24oe30sIFdIRVJFX0FUVCwge1xuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFdIRVJFX0FUVC50eXBlKSxcbiAgICB9KSxcbiAgfSxcbn0pO1xuXG5jb25zdCBTRUxFQ1RfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTZWxlY3RJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2VsZWN0SW5wdXQgdHlwZSBpcyB1c2VkIHRvIHNwZWNpZnkgYW4gaW5RdWVyeUtleSBvciBhIG5vdEluUXVlcnlLZXkgb3BlcmF0aW9uIG9uIGEgY29uc3RyYWludC4nLFxuICBmaWVsZHM6IHtcbiAgICBxdWVyeToge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBzdWJxdWVyeSB0byBiZSBleGVjdXRlZC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFNVQlFVRVJZX0lOUFVUKSxcbiAgICB9LFxuICAgIGtleToge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBrZXkgaW4gdGhlIHJlc3VsdCBvZiB0aGUgc3VicXVlcnkgdGhhdCBtdXN0IG1hdGNoIChub3QgbWF0Y2gpIHRoZSBmaWVsZC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgU0VBUkNIX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU2VhcmNoSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNlYXJjaElucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZpeSBhIHNlYXJjaCBvcGVyYXRpb24gb24gYSBmdWxsIHRleHQgc2VhcmNoLicsXG4gIGZpZWxkczoge1xuICAgIHRlcm06IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgdGVybSB0byBiZSBzZWFyY2hlZC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgIH0sXG4gICAgbGFuZ3VhZ2U6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUgbGFuZ3VhZ2UgdG8gdGV0ZXJtaW5lIHRoZSBsaXN0IG9mIHN0b3Agd29yZHMgYW5kIHRoZSBydWxlcyBmb3IgdG9rZW5pemVyLicsXG4gICAgICB0eXBlOiBHcmFwaFFMU3RyaW5nLFxuICAgIH0sXG4gICAgY2FzZVNlbnNpdGl2ZToge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBmbGFnIHRvIGVuYWJsZSBvciBkaXNhYmxlIGNhc2Ugc2Vuc2l0aXZlIHNlYXJjaC4nLFxuICAgICAgdHlwZTogR3JhcGhRTEJvb2xlYW4sXG4gICAgfSxcbiAgICBkaWFjcml0aWNTZW5zaXRpdmU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUgZmxhZyB0byBlbmFibGUgb3IgZGlzYWJsZSBkaWFjcml0aWMgc2Vuc2l0aXZlIHNlYXJjaC4nLFxuICAgICAgdHlwZTogR3JhcGhRTEJvb2xlYW4sXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBURVhUX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnVGV4dElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBUZXh0SW5wdXQgdHlwZSBpcyB1c2VkIHRvIHNwZWNpZnkgYSB0ZXh0IG9wZXJhdGlvbiBvbiBhIGNvbnN0cmFpbnQuJyxcbiAgZmllbGRzOiB7XG4gICAgc2VhcmNoOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHNlYXJjaCB0byBiZSBleGVjdXRlZC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFNFQVJDSF9JTlBVVCksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBCT1hfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdCb3hJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgQm94SW5wdXQgdHlwZSBpcyB1c2VkIHRvIHNwZWNpZml5IGEgYm94IG9wZXJhdGlvbiBvbiBhIHdpdGhpbiBnZW8gcXVlcnkuJyxcbiAgZmllbGRzOiB7XG4gICAgYm90dG9tTGVmdDoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBib3R0b20gbGVmdCBjb29yZGluYXRlcyBvZiB0aGUgYm94LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR0VPX1BPSU5UX0lOUFVUKSxcbiAgICB9LFxuICAgIHVwcGVyUmlnaHQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgdXBwZXIgcmlnaHQgY29vcmRpbmF0ZXMgb2YgdGhlIGJveC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdFT19QT0lOVF9JTlBVVCksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBXSVRISU5fSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdXaXRoaW5JbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgV2l0aGluSW5wdXQgdHlwZSBpcyB1c2VkIHRvIHNwZWNpZnkgYSB3aXRoaW4gb3BlcmF0aW9uIG9uIGEgY29uc3RyYWludC4nLFxuICBmaWVsZHM6IHtcbiAgICBib3g6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgYm94IHRvIGJlIHNwZWNpZmllZC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEJPWF9JTlBVVCksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBDRU5URVJfU1BIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnQ2VudGVyU3BoZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIENlbnRlclNwaGVyZUlucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZpeSBhIGNlbnRlclNwaGVyZSBvcGVyYXRpb24gb24gYSBnZW9XaXRoaW4gcXVlcnkuJyxcbiAgZmllbGRzOiB7XG4gICAgY2VudGVyOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGNlbnRlciBvZiB0aGUgc3BoZXJlLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR0VPX1BPSU5UX0lOUFVUKSxcbiAgICB9LFxuICAgIGRpc3RhbmNlOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHJhZGl1cyBvZiB0aGUgc3BoZXJlLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEZsb2F0KSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IEdFT19XSVRISU5fSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdHZW9XaXRoaW5JbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgR2VvV2l0aGluSW5wdXQgdHlwZSBpcyB1c2VkIHRvIHNwZWNpZnkgYSBnZW9XaXRoaW4gb3BlcmF0aW9uIG9uIGEgY29uc3RyYWludC4nLFxuICBmaWVsZHM6IHtcbiAgICBwb2x5Z29uOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHBvbHlnb24gdG8gYmUgc3BlY2lmaWVkLicsXG4gICAgICB0eXBlOiBQT0xZR09OX0lOUFVULFxuICAgIH0sXG4gICAgY2VudGVyU3BoZXJlOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHNwaGVyZSB0byBiZSBzcGVjaWZpZWQuJyxcbiAgICAgIHR5cGU6IENFTlRFUl9TUEhFUkVfSU5QVVQsXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBHRU9fSU5URVJTRUNUU19JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ0dlb0ludGVyc2VjdHNJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgR2VvSW50ZXJzZWN0c0lucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZ5IGEgZ2VvSW50ZXJzZWN0cyBvcGVyYXRpb24gb24gYSBjb25zdHJhaW50LicsXG4gIGZpZWxkczoge1xuICAgIHBvaW50OiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHBvaW50IHRvIGJlIHNwZWNpZmllZC4nLFxuICAgICAgdHlwZTogR0VPX1BPSU5UX0lOUFVULFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgZXF1YWxUbyA9IHR5cGUgPT4gKHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIGVxdWFsVG8gb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIHRoZSB2YWx1ZSBvZiBhIGZpZWxkIGVxdWFscyB0byBhIHNwZWNpZmllZCB2YWx1ZS4nLFxuICB0eXBlLFxufSk7XG5cbmNvbnN0IG5vdEVxdWFsVG8gPSB0eXBlID0+ICh7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBub3RFcXVhbFRvIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBkbyBub3QgZXF1YWwgdG8gYSBzcGVjaWZpZWQgdmFsdWUuJyxcbiAgdHlwZSxcbn0pO1xuXG5jb25zdCBsZXNzVGhhbiA9IHR5cGUgPT4gKHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIGxlc3NUaGFuIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBpcyBsZXNzIHRoYW4gYSBzcGVjaWZpZWQgdmFsdWUuJyxcbiAgdHlwZSxcbn0pO1xuXG5jb25zdCBsZXNzVGhhbk9yRXF1YWxUbyA9IHR5cGUgPT4gKHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIGxlc3NUaGFuT3JFcXVhbFRvIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gYSBzcGVjaWZpZWQgdmFsdWUuJyxcbiAgdHlwZSxcbn0pO1xuXG5jb25zdCBncmVhdGVyVGhhbiA9IHR5cGUgPT4gKHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIGdyZWF0ZXJUaGFuIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBpcyBncmVhdGVyIHRoYW4gYSBzcGVjaWZpZWQgdmFsdWUuJyxcbiAgdHlwZSxcbn0pO1xuXG5jb25zdCBncmVhdGVyVGhhbk9yRXF1YWxUbyA9IHR5cGUgPT4gKHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIGdyZWF0ZXJUaGFuT3JFcXVhbFRvIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYSBzcGVjaWZpZWQgdmFsdWUuJyxcbiAgdHlwZSxcbn0pO1xuXG5jb25zdCBpbk9wID0gdHlwZSA9PiAoe1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhpcyBpcyB0aGUgaW4gb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIHRoZSB2YWx1ZSBvZiBhIGZpZWxkIGVxdWFscyBhbnkgdmFsdWUgaW4gdGhlIHNwZWNpZmllZCBhcnJheS4nLFxuICB0eXBlOiBuZXcgR3JhcGhRTExpc3QodHlwZSksXG59KTtcblxuY29uc3Qgbm90SW4gPSB0eXBlID0+ICh7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBub3RJbiBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlIG9mIGEgZmllbGQgZG8gbm90IGVxdWFsIGFueSB2YWx1ZSBpbiB0aGUgc3BlY2lmaWVkIGFycmF5LicsXG4gIHR5cGU6IG5ldyBHcmFwaFFMTGlzdCh0eXBlKSxcbn0pO1xuXG5jb25zdCBleGlzdHMgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBleGlzdHMgb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIGEgZmllbGQgZXhpc3RzIChvciBkbyBub3QgZXhpc3QpLicsXG4gIHR5cGU6IEdyYXBoUUxCb29sZWFuLFxufTtcblxuY29uc3QgaW5RdWVyeUtleSA9IHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIGluUXVlcnlLZXkgb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIGEgZmllbGQgZXF1YWxzIHRvIGEga2V5IGluIHRoZSByZXN1bHQgb2YgYSBkaWZmZXJlbnQgcXVlcnkuJyxcbiAgdHlwZTogU0VMRUNUX0lOUFVULFxufTtcblxuY29uc3Qgbm90SW5RdWVyeUtleSA9IHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIG5vdEluUXVlcnlLZXkgb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIGEgZmllbGQgZG8gbm90IGVxdWFsIHRvIGEga2V5IGluIHRoZSByZXN1bHQgb2YgYSBkaWZmZXJlbnQgcXVlcnkuJyxcbiAgdHlwZTogU0VMRUNUX0lOUFVULFxufTtcblxuY29uc3QgbWF0Y2hlc1JlZ2V4ID0ge1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhpcyBpcyB0aGUgbWF0Y2hlc1JlZ2V4IG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBtYXRjaGVzIGEgc3BlY2lmaWVkIHJlZ3VsYXIgZXhwcmVzc2lvbi4nLFxuICB0eXBlOiBHcmFwaFFMU3RyaW5nLFxufTtcblxuY29uc3Qgb3B0aW9ucyA9IHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIG9wdGlvbnMgb3BlcmF0b3IgdG8gc3BlY2lmeSBvcHRpb25hbCBmbGFncyAoc3VjaCBhcyBcImlcIiBhbmQgXCJtXCIpIHRvIGJlIGFkZGVkIHRvIGEgbWF0Y2hlc1JlZ2V4IG9wZXJhdGlvbiBpbiB0aGUgc2FtZSBzZXQgb2YgY29uc3RyYWludHMuJyxcbiAgdHlwZTogR3JhcGhRTFN0cmluZyxcbn07XG5cbmNvbnN0IFNUUklOR19XSEVSRV9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1N0cmluZ1doZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFN0cmluZ1doZXJlSW5wdXQgaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIGJ5IGEgZmllbGQgb2YgdHlwZSBTdHJpbmcuJyxcbiAgZmllbGRzOiB7XG4gICAgZXF1YWxUbzogZXF1YWxUbyhHcmFwaFFMU3RyaW5nKSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEdyYXBoUUxTdHJpbmcpLFxuICAgIGxlc3NUaGFuOiBsZXNzVGhhbihHcmFwaFFMU3RyaW5nKSxcbiAgICBsZXNzVGhhbk9yRXF1YWxUbzogbGVzc1RoYW5PckVxdWFsVG8oR3JhcGhRTFN0cmluZyksXG4gICAgZ3JlYXRlclRoYW46IGdyZWF0ZXJUaGFuKEdyYXBoUUxTdHJpbmcpLFxuICAgIGdyZWF0ZXJUaGFuT3JFcXVhbFRvOiBncmVhdGVyVGhhbk9yRXF1YWxUbyhHcmFwaFFMU3RyaW5nKSxcbiAgICBpbjogaW5PcChHcmFwaFFMU3RyaW5nKSxcbiAgICBub3RJbjogbm90SW4oR3JhcGhRTFN0cmluZyksXG4gICAgZXhpc3RzLFxuICAgIGluUXVlcnlLZXksXG4gICAgbm90SW5RdWVyeUtleSxcbiAgICBtYXRjaGVzUmVnZXgsXG4gICAgb3B0aW9ucyxcbiAgICB0ZXh0OiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlICR0ZXh0IG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBmdWxsIHRleHQgc2VhcmNoIGNvbnN0cmFpbnQuJyxcbiAgICAgIHR5cGU6IFRFWFRfSU5QVVQsXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBOVU1CRVJfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdOdW1iZXJXaGVyZUlucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBOdW1iZXJXaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgTnVtYmVyLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oR3JhcGhRTEZsb2F0KSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEdyYXBoUUxGbG9hdCksXG4gICAgbGVzc1RoYW46IGxlc3NUaGFuKEdyYXBoUUxGbG9hdCksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKEdyYXBoUUxGbG9hdCksXG4gICAgZ3JlYXRlclRoYW46IGdyZWF0ZXJUaGFuKEdyYXBoUUxGbG9hdCksXG4gICAgZ3JlYXRlclRoYW5PckVxdWFsVG86IGdyZWF0ZXJUaGFuT3JFcXVhbFRvKEdyYXBoUUxGbG9hdCksXG4gICAgaW46IGluT3AoR3JhcGhRTEZsb2F0KSxcbiAgICBub3RJbjogbm90SW4oR3JhcGhRTEZsb2F0KSxcbiAgICBleGlzdHMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICB9LFxufSk7XG5cbmNvbnN0IEJPT0xFQU5fV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdCb29sZWFuV2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgQm9vbGVhbldoZXJlSW5wdXQgaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIGJ5IGEgZmllbGQgb2YgdHlwZSBCb29sZWFuLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oR3JhcGhRTEJvb2xlYW4pLFxuICAgIG5vdEVxdWFsVG86IG5vdEVxdWFsVG8oR3JhcGhRTEJvb2xlYW4pLFxuICAgIGV4aXN0cyxcbiAgICBpblF1ZXJ5S2V5LFxuICAgIG5vdEluUXVlcnlLZXksXG4gIH0sXG59KTtcblxuY29uc3QgQVJSQVlfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdBcnJheVdoZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEFycmF5V2hlcmVJbnB1dCBpbnB1dCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgZmlsdGVyaW5nIG9iamVjdHMgYnkgYSBmaWVsZCBvZiB0eXBlIEFycmF5LicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oQU5ZKSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEFOWSksXG4gICAgbGVzc1RoYW46IGxlc3NUaGFuKEFOWSksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKEFOWSksXG4gICAgZ3JlYXRlclRoYW46IGdyZWF0ZXJUaGFuKEFOWSksXG4gICAgZ3JlYXRlclRoYW5PckVxdWFsVG86IGdyZWF0ZXJUaGFuT3JFcXVhbFRvKEFOWSksXG4gICAgaW46IGluT3AoQU5ZKSxcbiAgICBub3RJbjogbm90SW4oQU5ZKSxcbiAgICBleGlzdHMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICAgIGNvbnRhaW5lZEJ5OiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIGNvbnRhaW5lZEJ5IG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWVzIG9mIGFuIGFycmF5IGZpZWxkIGlzIGNvbnRhaW5lZCBieSBhbm90aGVyIHNwZWNpZmllZCBhcnJheS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KEFOWSksXG4gICAgfSxcbiAgICBjb250YWluczoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBjb250YWlucyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhbiBhcnJheSBmaWVsZCBjb250YWluIGFsbCBlbGVtZW50cyBvZiBhbm90aGVyIHNwZWNpZmllZCBhcnJheS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KEFOWSksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBLRVlfVkFMVUVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdLZXlWYWx1ZUlucHV0JyxcbiAgZGVzY3JpcHRpb246ICdBbiBlbnRyeSBmcm9tIGFuIG9iamVjdCwgaS5lLiwgYSBwYWlyIG9mIGtleSBhbmQgdmFsdWUuJyxcbiAgZmllbGRzOiB7XG4gICAga2V5OiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBrZXkgdXNlZCB0byByZXRyaWV2ZSB0aGUgdmFsdWUgb2YgdGhpcyBlbnRyeS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgIH0sXG4gICAgdmFsdWU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHZhbHVlIG9mIHRoZSBlbnRyeS4gQ291bGQgYmUgYW55IHR5cGUgb2Ygc2NhbGFyIGRhdGEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChBTlkpLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgT0JKRUNUX1dIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnT2JqZWN0V2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgT2JqZWN0V2hlcmVJbnB1dCBpbnB1dCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgZmlsdGVyaW5nIHJlc3VsdCBieSBhIGZpZWxkIG9mIHR5cGUgT2JqZWN0LicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEtFWV9WQUxVRV9JTlBVVCksXG4gICAgaW46IGluT3AoS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBub3RJbjogbm90SW4oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBsZXNzVGhhbjogbGVzc1RoYW4oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBsZXNzVGhhbk9yRXF1YWxUbzogbGVzc1RoYW5PckVxdWFsVG8oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBncmVhdGVyVGhhbjogZ3JlYXRlclRoYW4oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBncmVhdGVyVGhhbk9yRXF1YWxUbzogZ3JlYXRlclRoYW5PckVxdWFsVG8oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBleGlzdHMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICB9LFxufSk7XG5cbmNvbnN0IERBVEVfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdEYXRlV2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgRGF0ZVdoZXJlSW5wdXQgaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIGJ5IGEgZmllbGQgb2YgdHlwZSBEYXRlLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oREFURSksXG4gICAgbm90RXF1YWxUbzogbm90RXF1YWxUbyhEQVRFKSxcbiAgICBsZXNzVGhhbjogbGVzc1RoYW4oREFURSksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKERBVEUpLFxuICAgIGdyZWF0ZXJUaGFuOiBncmVhdGVyVGhhbihEQVRFKSxcbiAgICBncmVhdGVyVGhhbk9yRXF1YWxUbzogZ3JlYXRlclRoYW5PckVxdWFsVG8oREFURSksXG4gICAgaW46IGluT3AoREFURSksXG4gICAgbm90SW46IG5vdEluKERBVEUpLFxuICAgIGV4aXN0cyxcbiAgICBpblF1ZXJ5S2V5LFxuICAgIG5vdEluUXVlcnlLZXksXG4gIH0sXG59KTtcblxuY29uc3QgQllURVNfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdCeXRlc1doZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEJ5dGVzV2hlcmVJbnB1dCBpbnB1dCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgZmlsdGVyaW5nIG9iamVjdHMgYnkgYSBmaWVsZCBvZiB0eXBlIEJ5dGVzLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oQllURVMpLFxuICAgIG5vdEVxdWFsVG86IG5vdEVxdWFsVG8oQllURVMpLFxuICAgIGxlc3NUaGFuOiBsZXNzVGhhbihCWVRFUyksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKEJZVEVTKSxcbiAgICBncmVhdGVyVGhhbjogZ3JlYXRlclRoYW4oQllURVMpLFxuICAgIGdyZWF0ZXJUaGFuT3JFcXVhbFRvOiBncmVhdGVyVGhhbk9yRXF1YWxUbyhCWVRFUyksXG4gICAgaW46IGluT3AoQllURVMpLFxuICAgIG5vdEluOiBub3RJbihCWVRFUyksXG4gICAgZXhpc3RzLFxuICAgIGluUXVlcnlLZXksXG4gICAgbm90SW5RdWVyeUtleSxcbiAgfSxcbn0pO1xuXG5jb25zdCBGSUxFX1dIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnRmlsZVdoZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEZpbGVXaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgRmlsZS4nLFxuICBmaWVsZHM6IHtcbiAgICBlcXVhbFRvOiBlcXVhbFRvKEZJTEUpLFxuICAgIG5vdEVxdWFsVG86IG5vdEVxdWFsVG8oRklMRSksXG4gICAgbGVzc1RoYW46IGxlc3NUaGFuKEZJTEUpLFxuICAgIGxlc3NUaGFuT3JFcXVhbFRvOiBsZXNzVGhhbk9yRXF1YWxUbyhGSUxFKSxcbiAgICBncmVhdGVyVGhhbjogZ3JlYXRlclRoYW4oRklMRSksXG4gICAgZ3JlYXRlclRoYW5PckVxdWFsVG86IGdyZWF0ZXJUaGFuT3JFcXVhbFRvKEZJTEUpLFxuICAgIGluOiBpbk9wKEZJTEUpLFxuICAgIG5vdEluOiBub3RJbihGSUxFKSxcbiAgICBleGlzdHMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICAgIG1hdGNoZXNSZWdleCxcbiAgICBvcHRpb25zLFxuICB9LFxufSk7XG5cbmNvbnN0IEdFT19QT0lOVF9XSEVSRV9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ0dlb1BvaW50V2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgR2VvUG9pbnRXaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgR2VvUG9pbnQuJyxcbiAgZmllbGRzOiB7XG4gICAgZXhpc3RzLFxuICAgIG5lYXJTcGhlcmU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUgbmVhclNwaGVyZSBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBuZWFyIHRvIGFub3RoZXIgZ2VvIHBvaW50LicsXG4gICAgICB0eXBlOiBHRU9fUE9JTlRfSU5QVVQsXG4gICAgfSxcbiAgICBtYXhEaXN0YW5jZToge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBtYXhEaXN0YW5jZSBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBhdCBhIG1heCBkaXN0YW5jZSAoaW4gcmFkaWFucykgZnJvbSB0aGUgZ2VvIHBvaW50IHNwZWNpZmllZCBpbiB0aGUgJG5lYXJTcGhlcmUgb3BlcmF0b3IuJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxGbG9hdCxcbiAgICB9LFxuICAgIG1heERpc3RhbmNlSW5SYWRpYW5zOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIG1heERpc3RhbmNlSW5SYWRpYW5zIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWVzIG9mIGEgZ2VvIHBvaW50IGZpZWxkIGlzIGF0IGEgbWF4IGRpc3RhbmNlIChpbiByYWRpYW5zKSBmcm9tIHRoZSBnZW8gcG9pbnQgc3BlY2lmaWVkIGluIHRoZSAkbmVhclNwaGVyZSBvcGVyYXRvci4nLFxuICAgICAgdHlwZTogR3JhcGhRTEZsb2F0LFxuICAgIH0sXG4gICAgbWF4RGlzdGFuY2VJbk1pbGVzOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIG1heERpc3RhbmNlSW5NaWxlcyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBhdCBhIG1heCBkaXN0YW5jZSAoaW4gbWlsZXMpIGZyb20gdGhlIGdlbyBwb2ludCBzcGVjaWZpZWQgaW4gdGhlICRuZWFyU3BoZXJlIG9wZXJhdG9yLicsXG4gICAgICB0eXBlOiBHcmFwaFFMRmxvYXQsXG4gICAgfSxcbiAgICBtYXhEaXN0YW5jZUluS2lsb21ldGVyczoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBtYXhEaXN0YW5jZUluS2lsb21ldGVycyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBhdCBhIG1heCBkaXN0YW5jZSAoaW4ga2lsb21ldGVycykgZnJvbSB0aGUgZ2VvIHBvaW50IHNwZWNpZmllZCBpbiB0aGUgJG5lYXJTcGhlcmUgb3BlcmF0b3IuJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxGbG9hdCxcbiAgICB9LFxuICAgIHdpdGhpbjoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSB3aXRoaW4gb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIHRoZSB2YWx1ZXMgb2YgYSBnZW8gcG9pbnQgZmllbGQgaXMgd2l0aGluIGEgc3BlY2lmaWVkIGJveC4nLFxuICAgICAgdHlwZTogV0lUSElOX0lOUFVULFxuICAgIH0sXG4gICAgZ2VvV2l0aGluOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIGdlb1dpdGhpbiBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyB3aXRoaW4gYSBzcGVjaWZpZWQgcG9seWdvbiBvciBzcGhlcmUuJyxcbiAgICAgIHR5cGU6IEdFT19XSVRISU5fSU5QVVQsXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBQT0xZR09OX1dIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnUG9seWdvbldoZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFBvbHlnb25XaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgUG9seWdvbi4nLFxuICBmaWVsZHM6IHtcbiAgICBleGlzdHMsXG4gICAgZ2VvSW50ZXJzZWN0czoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBnZW9JbnRlcnNlY3RzIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWVzIG9mIGEgcG9seWdvbiBmaWVsZCBpbnRlcnNlY3QgYSBzcGVjaWZpZWQgcG9pbnQuJyxcbiAgICAgIHR5cGU6IEdFT19JTlRFUlNFQ1RTX0lOUFVULFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgRklORF9SRVNVTFQgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnRmluZFJlc3VsdCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgRmluZFJlc3VsdCBvYmplY3QgdHlwZSBpcyB1c2VkIGluIHRoZSBmaW5kIHF1ZXJpZXMgdG8gcmV0dXJuIHRoZSBkYXRhIG9mIHRoZSBtYXRjaGVkIG9iamVjdHMuJyxcbiAgZmllbGRzOiB7XG4gICAgcmVzdWx0czoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBvYmplY3RzIHJldHVybmVkIGJ5IHRoZSBxdWVyeScsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwobmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChPQkpFQ1QpKSksXG4gICAgfSxcbiAgICBjb3VudDogQ09VTlRfQVRULFxuICB9LFxufSk7XG5cbmNvbnN0IEVMRU1FTlQgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnRWxlbWVudCcsXG4gIGRlc2NyaXB0aW9uOiBcIlRoZSBFbGVtZW50IG9iamVjdCB0eXBlIGlzIHVzZWQgdG8gcmV0dXJuIGFycmF5IGl0ZW1zJyB2YWx1ZS5cIixcbiAgZmllbGRzOiB7XG4gICAgdmFsdWU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnUmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgZWxlbWVudCBpbiB0aGUgYXJyYXknLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEFOWSksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG4vLyBEZWZhdWx0IHN0YXRpYyB1bmlvbiB0eXBlLCB3ZSB1cGRhdGUgdHlwZXMgYW5kIHJlc29sdmVUeXBlIGZ1bmN0aW9uIGxhdGVyXG5sZXQgQVJSQVlfUkVTVUxUO1xuXG5jb25zdCBsb2FkQXJyYXlSZXN1bHQgPSAocGFyc2VHcmFwaFFMU2NoZW1hLCBwYXJzZUNsYXNzZXMpID0+IHtcbiAgY29uc3QgY2xhc3NUeXBlcyA9IHBhcnNlQ2xhc3Nlc1xuICAgIC5maWx0ZXIocGFyc2VDbGFzcyA9PlxuICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1twYXJzZUNsYXNzLmNsYXNzTmFtZV1cbiAgICAgICAgLmNsYXNzR3JhcGhRTE91dHB1dFR5cGVcbiAgICAgICAgPyB0cnVlXG4gICAgICAgIDogZmFsc2VcbiAgICApXG4gICAgLm1hcChcbiAgICAgIHBhcnNlQ2xhc3MgPT5cbiAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1twYXJzZUNsYXNzLmNsYXNzTmFtZV1cbiAgICAgICAgICAuY2xhc3NHcmFwaFFMT3V0cHV0VHlwZVxuICAgICk7XG4gIEFSUkFZX1JFU1VMVCA9IG5ldyBHcmFwaFFMVW5pb25UeXBlKHtcbiAgICBuYW1lOiAnQXJyYXlSZXN1bHQnLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1VzZSBJbmxpbmUgRnJhZ21lbnQgb24gQXJyYXkgdG8gZ2V0IHJlc3VsdHM6IGh0dHBzOi8vZ3JhcGhxbC5vcmcvbGVhcm4vcXVlcmllcy8jaW5saW5lLWZyYWdtZW50cycsXG4gICAgdHlwZXM6ICgpID0+IFtFTEVNRU5ULCAuLi5jbGFzc1R5cGVzXSxcbiAgICByZXNvbHZlVHlwZTogdmFsdWUgPT4ge1xuICAgICAgaWYgKHZhbHVlLl9fdHlwZSA9PT0gJ09iamVjdCcgJiYgdmFsdWUuY2xhc3NOYW1lICYmIHZhbHVlLm9iamVjdElkKSB7XG4gICAgICAgIGlmIChwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW3ZhbHVlLmNsYXNzTmFtZV0pIHtcbiAgICAgICAgICByZXR1cm4gcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1t2YWx1ZS5jbGFzc05hbWVdXG4gICAgICAgICAgICAuY2xhc3NHcmFwaFFMT3V0cHV0VHlwZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gRUxFTUVOVDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEVMRU1FTlQ7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5ncmFwaFFMVHlwZXMucHVzaChBUlJBWV9SRVNVTFQpO1xufTtcblxuY29uc3QgbG9hZCA9IHBhcnNlR3JhcGhRTFNjaGVtYSA9PiB7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShHcmFwaFFMVXBsb2FkLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEFOWSwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShPQkpFQ1QsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoREFURSwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShCWVRFUywgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShGSUxFLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEZJTEVfSU5GTywgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShHRU9fUE9JTlRfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoR0VPX1BPSU5ULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFBBUlNFX09CSkVDVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShSRUFEX1BSRUZFUkVOQ0UsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoUkVBRF9PUFRJT05TX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFNVQlFVRVJZX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFNFTEVDVF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTRUFSQ0hfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoVEVYVF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShCT1hfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoV0lUSElOX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKENFTlRFUl9TUEhFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoR0VPX1dJVEhJTl9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShHRU9fSU5URVJTRUNUU19JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTVFJJTkdfV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoTlVNQkVSX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEJPT0xFQU5fV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoQVJSQVlfV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoS0VZX1ZBTFVFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKE9CSkVDVF9XSEVSRV9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShEQVRFX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEJZVEVTX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEZJTEVfV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoR0VPX1BPSU5UX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFBPTFlHT05fV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoRklORF9SRVNVTFQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoRUxFTUVOVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShPQkpFQ1RfSUQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoQUNMX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFVTRVJfQUNMX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFJPTEVfQUNMX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFBVQkxJQ19BQ0xfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoQUNMLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFVTRVJfQUNMLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFJPTEVfQUNMLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFBVQkxJQ19BQ0wsIHRydWUpO1xufTtcblxuZXhwb3J0IHtcbiAgVHlwZVZhbGlkYXRpb25FcnJvcixcbiAgcGFyc2VTdHJpbmdWYWx1ZSxcbiAgcGFyc2VJbnRWYWx1ZSxcbiAgcGFyc2VGbG9hdFZhbHVlLFxuICBwYXJzZUJvb2xlYW5WYWx1ZSxcbiAgcGFyc2VWYWx1ZSxcbiAgcGFyc2VMaXN0VmFsdWVzLFxuICBwYXJzZU9iamVjdEZpZWxkcyxcbiAgQU5ZLFxuICBPQkpFQ1QsXG4gIHBhcnNlRGF0ZUlzb1ZhbHVlLFxuICBzZXJpYWxpemVEYXRlSXNvLFxuICBEQVRFLFxuICBCWVRFUyxcbiAgcGFyc2VGaWxlVmFsdWUsXG4gIEZJTEUsXG4gIEZJTEVfSU5GTyxcbiAgR0VPX1BPSU5UX0ZJRUxEUyxcbiAgR0VPX1BPSU5UX0lOUFVULFxuICBHRU9fUE9JTlQsXG4gIFBPTFlHT05fSU5QVVQsXG4gIFBPTFlHT04sXG4gIE9CSkVDVF9JRCxcbiAgQ0xBU1NfTkFNRV9BVFQsXG4gIE9CSkVDVF9JRF9BVFQsXG4gIFVQREFURURfQVRfQVRULFxuICBDUkVBVEVEX0FUX0FUVCxcbiAgSU5QVVRfRklFTERTLFxuICBDUkVBVEVfUkVTVUxUX0ZJRUxEUyxcbiAgVVBEQVRFX1JFU1VMVF9GSUVMRFMsXG4gIFBBUlNFX09CSkVDVF9GSUVMRFMsXG4gIFBBUlNFX09CSkVDVCxcbiAgU0VTU0lPTl9UT0tFTl9BVFQsXG4gIFJFQURfUFJFRkVSRU5DRSxcbiAgUkVBRF9QUkVGRVJFTkNFX0FUVCxcbiAgSU5DTFVERV9SRUFEX1BSRUZFUkVOQ0VfQVRULFxuICBTVUJRVUVSWV9SRUFEX1BSRUZFUkVOQ0VfQVRULFxuICBSRUFEX09QVElPTlNfSU5QVVQsXG4gIFJFQURfT1BUSU9OU19BVFQsXG4gIFdIRVJFX0FUVCxcbiAgU0tJUF9BVFQsXG4gIExJTUlUX0FUVCxcbiAgQ09VTlRfQVRULFxuICBTVUJRVUVSWV9JTlBVVCxcbiAgU0VMRUNUX0lOUFVULFxuICBTRUFSQ0hfSU5QVVQsXG4gIFRFWFRfSU5QVVQsXG4gIEJPWF9JTlBVVCxcbiAgV0lUSElOX0lOUFVULFxuICBDRU5URVJfU1BIRVJFX0lOUFVULFxuICBHRU9fV0lUSElOX0lOUFVULFxuICBHRU9fSU5URVJTRUNUU19JTlBVVCxcbiAgZXF1YWxUbyxcbiAgbm90RXF1YWxUbyxcbiAgbGVzc1RoYW4sXG4gIGxlc3NUaGFuT3JFcXVhbFRvLFxuICBncmVhdGVyVGhhbixcbiAgZ3JlYXRlclRoYW5PckVxdWFsVG8sXG4gIGluT3AsXG4gIG5vdEluLFxuICBleGlzdHMsXG4gIGluUXVlcnlLZXksXG4gIG5vdEluUXVlcnlLZXksXG4gIG1hdGNoZXNSZWdleCxcbiAgb3B0aW9ucyxcbiAgU1RSSU5HX1dIRVJFX0lOUFVULFxuICBOVU1CRVJfV0hFUkVfSU5QVVQsXG4gIEJPT0xFQU5fV0hFUkVfSU5QVVQsXG4gIEFSUkFZX1dIRVJFX0lOUFVULFxuICBLRVlfVkFMVUVfSU5QVVQsXG4gIE9CSkVDVF9XSEVSRV9JTlBVVCxcbiAgREFURV9XSEVSRV9JTlBVVCxcbiAgQllURVNfV0hFUkVfSU5QVVQsXG4gIEZJTEVfV0hFUkVfSU5QVVQsXG4gIEdFT19QT0lOVF9XSEVSRV9JTlBVVCxcbiAgUE9MWUdPTl9XSEVSRV9JTlBVVCxcbiAgRklORF9SRVNVTFQsXG4gIEFSUkFZX1JFU1VMVCxcbiAgRUxFTUVOVCxcbiAgQUNMX0lOUFVULFxuICBVU0VSX0FDTF9JTlBVVCxcbiAgUk9MRV9BQ0xfSU5QVVQsXG4gIFBVQkxJQ19BQ0xfSU5QVVQsXG4gIEFDTCxcbiAgVVNFUl9BQ0wsXG4gIFJPTEVfQUNMLFxuICBQVUJMSUNfQUNMLFxuICBsb2FkLFxuICBsb2FkQXJyYXlSZXN1bHQsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/loaders/filesMutations.js b/lib/GraphQL/loaders/filesMutations.js new file mode 100644 index 0000000000..23810add63 --- /dev/null +++ b/lib/GraphQL/loaders/filesMutations.js @@ -0,0 +1,86 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlUpload = require("graphql-upload"); + +var _node = _interopRequireDefault(require("parse/node")); + +var defaultGraphQLTypes = _interopRequireWildcard(require("./defaultGraphQLTypes")); + +var _logger = _interopRequireDefault(require("../../logger")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const load = parseGraphQLSchema => { + parseGraphQLSchema.addGraphQLMutation('createFile', { + description: 'The create mutation can be used to create and upload a new file.', + args: { + upload: { + description: 'This is the new file to be created and uploaded', + type: new _graphql.GraphQLNonNull(_graphqlUpload.GraphQLUpload) + } + }, + type: new _graphql.GraphQLNonNull(defaultGraphQLTypes.FILE_INFO), + + async resolve(_source, args, context) { + try { + const { + upload + } = args; + const { + config + } = context; + const { + createReadStream, + filename, + mimetype + } = await upload; + let data = null; + + if (createReadStream) { + const stream = createReadStream(); + data = await new Promise((resolve, reject) => { + const chunks = []; + stream.on('error', reject).on('data', chunk => chunks.push(chunk)).on('end', () => resolve(Buffer.concat(chunks))); + }); + } + + if (!data || !data.length) { + throw new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'Invalid file upload.'); + } + + if (filename.length > 128) { + throw new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Filename too long.'); + } + + if (!filename.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) { + throw new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Filename contains invalid characters.'); + } + + try { + return await config.filesController.createFile(config, filename, data, mimetype); + } catch (e) { + _logger.default.error('Error creating a file: ', e); + + throw new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, `Could not store file: ${filename}.`); + } + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZmlsZXNNdXRhdGlvbnMuanMiXSwibmFtZXMiOlsibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsImFkZEdyYXBoUUxNdXRhdGlvbiIsImRlc2NyaXB0aW9uIiwiYXJncyIsInVwbG9hZCIsInR5cGUiLCJHcmFwaFFMTm9uTnVsbCIsIkdyYXBoUUxVcGxvYWQiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiRklMRV9JTkZPIiwicmVzb2x2ZSIsIl9zb3VyY2UiLCJjb250ZXh0IiwiY29uZmlnIiwiY3JlYXRlUmVhZFN0cmVhbSIsImZpbGVuYW1lIiwibWltZXR5cGUiLCJkYXRhIiwic3RyZWFtIiwiUHJvbWlzZSIsInJlamVjdCIsImNodW5rcyIsIm9uIiwiY2h1bmsiLCJwdXNoIiwiQnVmZmVyIiwiY29uY2F0IiwibGVuZ3RoIiwiUGFyc2UiLCJFcnJvciIsIkZJTEVfU0FWRV9FUlJPUiIsIklOVkFMSURfRklMRV9OQU1FIiwibWF0Y2giLCJmaWxlc0NvbnRyb2xsZXIiLCJjcmVhdGVGaWxlIiwiZSIsImxvZ2dlciIsImVycm9yIiwiaGFuZGxlRXJyb3IiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNQSxJQUFJLEdBQUdDLGtCQUFrQixJQUFJO0FBQ2pDQSxFQUFBQSxrQkFBa0IsQ0FBQ0Msa0JBQW5CLENBQ0UsWUFERixFQUVFO0FBQ0VDLElBQUFBLFdBQVcsRUFDVCxrRUFGSjtBQUdFQyxJQUFBQSxJQUFJLEVBQUU7QUFDSkMsTUFBQUEsTUFBTSxFQUFFO0FBQ05GLFFBQUFBLFdBQVcsRUFBRSxpREFEUDtBQUVORyxRQUFBQSxJQUFJLEVBQUUsSUFBSUMsdUJBQUosQ0FBbUJDLDRCQUFuQjtBQUZBO0FBREosS0FIUjtBQVNFRixJQUFBQSxJQUFJLEVBQUUsSUFBSUMsdUJBQUosQ0FBbUJFLG1CQUFtQixDQUFDQyxTQUF2QyxDQVRSOztBQVVFLFVBQU1DLE9BQU4sQ0FBY0MsT0FBZCxFQUF1QlIsSUFBdkIsRUFBNkJTLE9BQTdCLEVBQXNDO0FBQ3BDLFVBQUk7QUFDRixjQUFNO0FBQUVSLFVBQUFBO0FBQUYsWUFBYUQsSUFBbkI7QUFDQSxjQUFNO0FBQUVVLFVBQUFBO0FBQUYsWUFBYUQsT0FBbkI7QUFFQSxjQUFNO0FBQUVFLFVBQUFBLGdCQUFGO0FBQW9CQyxVQUFBQSxRQUFwQjtBQUE4QkMsVUFBQUE7QUFBOUIsWUFBMkMsTUFBTVosTUFBdkQ7QUFDQSxZQUFJYSxJQUFJLEdBQUcsSUFBWDs7QUFDQSxZQUFJSCxnQkFBSixFQUFzQjtBQUNwQixnQkFBTUksTUFBTSxHQUFHSixnQkFBZ0IsRUFBL0I7QUFDQUcsVUFBQUEsSUFBSSxHQUFHLE1BQU0sSUFBSUUsT0FBSixDQUFZLENBQUNULE9BQUQsRUFBVVUsTUFBVixLQUFxQjtBQUM1QyxrQkFBTUMsTUFBTSxHQUFHLEVBQWY7QUFDQUgsWUFBQUEsTUFBTSxDQUNISSxFQURILENBQ00sT0FETixFQUNlRixNQURmLEVBRUdFLEVBRkgsQ0FFTSxNQUZOLEVBRWNDLEtBQUssSUFBSUYsTUFBTSxDQUFDRyxJQUFQLENBQVlELEtBQVosQ0FGdkIsRUFHR0QsRUFISCxDQUdNLEtBSE4sRUFHYSxNQUFNWixPQUFPLENBQUNlLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjTCxNQUFkLENBQUQsQ0FIMUI7QUFJRCxXQU5ZLENBQWI7QUFPRDs7QUFFRCxZQUFJLENBQUNKLElBQUQsSUFBUyxDQUFDQSxJQUFJLENBQUNVLE1BQW5CLEVBQTJCO0FBQ3pCLGdCQUFNLElBQUlDLGNBQU1DLEtBQVYsQ0FDSkQsY0FBTUMsS0FBTixDQUFZQyxlQURSLEVBRUosc0JBRkksQ0FBTjtBQUlEOztBQUVELFlBQUlmLFFBQVEsQ0FBQ1ksTUFBVCxHQUFrQixHQUF0QixFQUEyQjtBQUN6QixnQkFBTSxJQUFJQyxjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUUsaUJBRFIsRUFFSixvQkFGSSxDQUFOO0FBSUQ7O0FBRUQsWUFBSSxDQUFDaEIsUUFBUSxDQUFDaUIsS0FBVCxDQUFlLG9DQUFmLENBQUwsRUFBMkQ7QUFDekQsZ0JBQU0sSUFBSUosY0FBTUMsS0FBVixDQUNKRCxjQUFNQyxLQUFOLENBQVlFLGlCQURSLEVBRUosdUNBRkksQ0FBTjtBQUlEOztBQUVELFlBQUk7QUFDRixpQkFBTyxNQUFNbEIsTUFBTSxDQUFDb0IsZUFBUCxDQUF1QkMsVUFBdkIsQ0FDWHJCLE1BRFcsRUFFWEUsUUFGVyxFQUdYRSxJQUhXLEVBSVhELFFBSlcsQ0FBYjtBQU1ELFNBUEQsQ0FPRSxPQUFPbUIsQ0FBUCxFQUFVO0FBQ1ZDLDBCQUFPQyxLQUFQLENBQWEseUJBQWIsRUFBd0NGLENBQXhDOztBQUNBLGdCQUFNLElBQUlQLGNBQU1DLEtBQVYsQ0FDSkQsY0FBTUMsS0FBTixDQUFZQyxlQURSLEVBRUgseUJBQXdCZixRQUFTLEdBRjlCLENBQU47QUFJRDtBQUNGLE9BcERELENBb0RFLE9BQU9vQixDQUFQLEVBQVU7QUFDVm5DLFFBQUFBLGtCQUFrQixDQUFDc0MsV0FBbkIsQ0FBK0JILENBQS9CO0FBQ0Q7QUFDRjs7QUFsRUgsR0FGRixFQXNFRSxJQXRFRixFQXVFRSxJQXZFRjtBQXlFRCxDQTFFRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEdyYXBoUUxOb25OdWxsIH0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgeyBHcmFwaFFMVXBsb2FkIH0gZnJvbSAnZ3JhcGhxbC11cGxvYWQnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0ICogYXMgZGVmYXVsdEdyYXBoUUxUeXBlcyBmcm9tICcuL2RlZmF1bHRHcmFwaFFMVHlwZXMnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi8uLi9sb2dnZXInO1xuXG5jb25zdCBsb2FkID0gcGFyc2VHcmFwaFFMU2NoZW1hID0+IHtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxNdXRhdGlvbihcbiAgICAnY3JlYXRlRmlsZScsXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGUgY3JlYXRlIG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSBhbmQgdXBsb2FkIGEgbmV3IGZpbGUuJyxcbiAgICAgIGFyZ3M6IHtcbiAgICAgICAgdXBsb2FkOiB7XG4gICAgICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBuZXcgZmlsZSB0byBiZSBjcmVhdGVkIGFuZCB1cGxvYWRlZCcsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxVcGxvYWQpLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChkZWZhdWx0R3JhcGhRTFR5cGVzLkZJTEVfSU5GTyksXG4gICAgICBhc3luYyByZXNvbHZlKF9zb3VyY2UsIGFyZ3MsIGNvbnRleHQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IHVwbG9hZCB9ID0gYXJncztcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZyB9ID0gY29udGV4dDtcblxuICAgICAgICAgIGNvbnN0IHsgY3JlYXRlUmVhZFN0cmVhbSwgZmlsZW5hbWUsIG1pbWV0eXBlIH0gPSBhd2FpdCB1cGxvYWQ7XG4gICAgICAgICAgbGV0IGRhdGEgPSBudWxsO1xuICAgICAgICAgIGlmIChjcmVhdGVSZWFkU3RyZWFtKSB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjcmVhdGVSZWFkU3RyZWFtKCk7XG4gICAgICAgICAgICBkYXRhID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBjaHVua3MgPSBbXTtcbiAgICAgICAgICAgICAgc3RyZWFtXG4gICAgICAgICAgICAgICAgLm9uKCdlcnJvcicsIHJlamVjdClcbiAgICAgICAgICAgICAgICAub24oJ2RhdGEnLCBjaHVuayA9PiBjaHVua3MucHVzaChjaHVuaykpXG4gICAgICAgICAgICAgICAgLm9uKCdlbmQnLCAoKSA9PiByZXNvbHZlKEJ1ZmZlci5jb25jYXQoY2h1bmtzKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsXG4gICAgICAgICAgICAgICdJbnZhbGlkIGZpbGUgdXBsb2FkLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGZpbGVuYW1lLmxlbmd0aCA+IDEyOCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSxcbiAgICAgICAgICAgICAgJ0ZpbGVuYW1lIHRvbyBsb25nLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFmaWxlbmFtZS5tYXRjaCgvXltfYS16QS1aMC05XVthLXpBLVowLTlAXFwuXFwgfl8tXSokLykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9GSUxFX05BTUUsXG4gICAgICAgICAgICAgICdGaWxlbmFtZSBjb250YWlucyBpbnZhbGlkIGNoYXJhY3RlcnMuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGNvbmZpZy5maWxlc0NvbnRyb2xsZXIuY3JlYXRlRmlsZShcbiAgICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgICBmaWxlbmFtZSxcbiAgICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgICAgbWltZXR5cGVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBjcmVhdGluZyBhIGZpbGU6ICcsIGUpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsXG4gICAgICAgICAgICAgIGBDb3VsZCBub3Qgc3RvcmUgZmlsZTogJHtmaWxlbmFtZX0uYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbn07XG5cbmV4cG9ydCB7IGxvYWQgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/loaders/functionsMutations.js b/lib/GraphQL/loaders/functionsMutations.js new file mode 100644 index 0000000000..a8305e796d --- /dev/null +++ b/lib/GraphQL/loaders/functionsMutations.js @@ -0,0 +1,79 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _FunctionsRouter = require("../../Routers/FunctionsRouter"); + +var defaultGraphQLTypes = _interopRequireWildcard(require("./defaultGraphQLTypes")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const load = parseGraphQLSchema => { + if (parseGraphQLSchema.functionNames.length > 0) { + const cloudCodeFunctionEnum = parseGraphQLSchema.addGraphQLType(new _graphql.GraphQLEnumType({ + name: 'CloudCodeFunction', + description: 'The CloudCodeFunction enum type contains a list of all available cloud code functions.', + values: parseGraphQLSchema.functionNames.reduce((values, functionName) => _objectSpread({}, values, { + [functionName]: { + value: functionName + } + }), {}) + }), true, true); + parseGraphQLSchema.addGraphQLMutation('callCloudCode', { + description: 'The call mutation can be used to invoke a cloud code function.', + args: { + functionName: { + description: 'This is the function to be called.', + type: new _graphql.GraphQLNonNull(cloudCodeFunctionEnum) + }, + params: { + description: 'These are the params to be passed to the function.', + type: defaultGraphQLTypes.OBJECT + } + }, + type: defaultGraphQLTypes.ANY, + + async resolve(_source, args, context) { + try { + const { + functionName, + params + } = args; + const { + config, + auth, + info + } = context; + return (await _FunctionsRouter.FunctionsRouter.handleCloudFunction({ + params: { + functionName + }, + config, + auth, + info, + body: params + })).response.result; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }, true, true); + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZnVuY3Rpb25zTXV0YXRpb25zLmpzIl0sIm5hbWVzIjpbImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJmdW5jdGlvbk5hbWVzIiwibGVuZ3RoIiwiY2xvdWRDb2RlRnVuY3Rpb25FbnVtIiwiYWRkR3JhcGhRTFR5cGUiLCJHcmFwaFFMRW51bVR5cGUiLCJuYW1lIiwiZGVzY3JpcHRpb24iLCJ2YWx1ZXMiLCJyZWR1Y2UiLCJmdW5jdGlvbk5hbWUiLCJ2YWx1ZSIsImFkZEdyYXBoUUxNdXRhdGlvbiIsImFyZ3MiLCJ0eXBlIiwiR3JhcGhRTE5vbk51bGwiLCJwYXJhbXMiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiT0JKRUNUIiwiQU5ZIiwicmVzb2x2ZSIsIl9zb3VyY2UiLCJjb250ZXh0IiwiY29uZmlnIiwiYXV0aCIsImluZm8iLCJGdW5jdGlvbnNSb3V0ZXIiLCJoYW5kbGVDbG91ZEZ1bmN0aW9uIiwiYm9keSIsInJlc3BvbnNlIiwicmVzdWx0IiwiZSIsImhhbmRsZUVycm9yIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7OztBQUVBLE1BQU1BLElBQUksR0FBR0Msa0JBQWtCLElBQUk7QUFDakMsTUFBSUEsa0JBQWtCLENBQUNDLGFBQW5CLENBQWlDQyxNQUFqQyxHQUEwQyxDQUE5QyxFQUFpRDtBQUMvQyxVQUFNQyxxQkFBcUIsR0FBR0gsa0JBQWtCLENBQUNJLGNBQW5CLENBQzVCLElBQUlDLHdCQUFKLENBQW9CO0FBQ2xCQyxNQUFBQSxJQUFJLEVBQUUsbUJBRFk7QUFFbEJDLE1BQUFBLFdBQVcsRUFDVCx3RkFIZ0I7QUFJbEJDLE1BQUFBLE1BQU0sRUFBRVIsa0JBQWtCLENBQUNDLGFBQW5CLENBQWlDUSxNQUFqQyxDQUNOLENBQUNELE1BQUQsRUFBU0UsWUFBVCx1QkFDS0YsTUFETDtBQUVFLFNBQUNFLFlBQUQsR0FBZ0I7QUFBRUMsVUFBQUEsS0FBSyxFQUFFRDtBQUFUO0FBRmxCLFFBRE0sRUFLTixFQUxNO0FBSlUsS0FBcEIsQ0FENEIsRUFhNUIsSUFiNEIsRUFjNUIsSUFkNEIsQ0FBOUI7QUFpQkFWLElBQUFBLGtCQUFrQixDQUFDWSxrQkFBbkIsQ0FDRSxlQURGLEVBRUU7QUFDRUwsTUFBQUEsV0FBVyxFQUNULGdFQUZKO0FBR0VNLE1BQUFBLElBQUksRUFBRTtBQUNKSCxRQUFBQSxZQUFZLEVBQUU7QUFDWkgsVUFBQUEsV0FBVyxFQUFFLG9DQUREO0FBRVpPLFVBQUFBLElBQUksRUFBRSxJQUFJQyx1QkFBSixDQUFtQloscUJBQW5CO0FBRk0sU0FEVjtBQUtKYSxRQUFBQSxNQUFNLEVBQUU7QUFDTlQsVUFBQUEsV0FBVyxFQUFFLG9EQURQO0FBRU5PLFVBQUFBLElBQUksRUFBRUcsbUJBQW1CLENBQUNDO0FBRnBCO0FBTEosT0FIUjtBQWFFSixNQUFBQSxJQUFJLEVBQUVHLG1CQUFtQixDQUFDRSxHQWI1Qjs7QUFjRSxZQUFNQyxPQUFOLENBQWNDLE9BQWQsRUFBdUJSLElBQXZCLEVBQTZCUyxPQUE3QixFQUFzQztBQUNwQyxZQUFJO0FBQ0YsZ0JBQU07QUFBRVosWUFBQUEsWUFBRjtBQUFnQk0sWUFBQUE7QUFBaEIsY0FBMkJILElBQWpDO0FBQ0EsZ0JBQU07QUFBRVUsWUFBQUEsTUFBRjtBQUFVQyxZQUFBQSxJQUFWO0FBQWdCQyxZQUFBQTtBQUFoQixjQUF5QkgsT0FBL0I7QUFFQSxpQkFBTyxDQUFDLE1BQU1JLGlDQUFnQkMsbUJBQWhCLENBQW9DO0FBQ2hEWCxZQUFBQSxNQUFNLEVBQUU7QUFDTk4sY0FBQUE7QUFETSxhQUR3QztBQUloRGEsWUFBQUEsTUFKZ0Q7QUFLaERDLFlBQUFBLElBTGdEO0FBTWhEQyxZQUFBQSxJQU5nRDtBQU9oREcsWUFBQUEsSUFBSSxFQUFFWjtBQVAwQyxXQUFwQyxDQUFQLEVBUUhhLFFBUkcsQ0FRTUMsTUFSYjtBQVNELFNBYkQsQ0FhRSxPQUFPQyxDQUFQLEVBQVU7QUFDVi9CLFVBQUFBLGtCQUFrQixDQUFDZ0MsV0FBbkIsQ0FBK0JELENBQS9CO0FBQ0Q7QUFDRjs7QUEvQkgsS0FGRixFQW1DRSxJQW5DRixFQW9DRSxJQXBDRjtBQXNDRDtBQUNGLENBMUREIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR3JhcGhRTE5vbk51bGwsIEdyYXBoUUxFbnVtVHlwZSB9IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0IHsgRnVuY3Rpb25zUm91dGVyIH0gZnJvbSAnLi4vLi4vUm91dGVycy9GdW5jdGlvbnNSb3V0ZXInO1xuaW1wb3J0ICogYXMgZGVmYXVsdEdyYXBoUUxUeXBlcyBmcm9tICcuL2RlZmF1bHRHcmFwaFFMVHlwZXMnO1xuXG5jb25zdCBsb2FkID0gcGFyc2VHcmFwaFFMU2NoZW1hID0+IHtcbiAgaWYgKHBhcnNlR3JhcGhRTFNjaGVtYS5mdW5jdGlvbk5hbWVzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBjbG91ZENvZGVGdW5jdGlvbkVudW0gPSBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgICBuZXcgR3JhcGhRTEVudW1UeXBlKHtcbiAgICAgICAgbmFtZTogJ0Nsb3VkQ29kZUZ1bmN0aW9uJyxcbiAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgJ1RoZSBDbG91ZENvZGVGdW5jdGlvbiBlbnVtIHR5cGUgY29udGFpbnMgYSBsaXN0IG9mIGFsbCBhdmFpbGFibGUgY2xvdWQgY29kZSBmdW5jdGlvbnMuJyxcbiAgICAgICAgdmFsdWVzOiBwYXJzZUdyYXBoUUxTY2hlbWEuZnVuY3Rpb25OYW1lcy5yZWR1Y2UoXG4gICAgICAgICAgKHZhbHVlcywgZnVuY3Rpb25OYW1lKSA9PiAoe1xuICAgICAgICAgICAgLi4udmFsdWVzLFxuICAgICAgICAgICAgW2Z1bmN0aW9uTmFtZV06IHsgdmFsdWU6IGZ1bmN0aW9uTmFtZSB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIHt9XG4gICAgICAgICksXG4gICAgICB9KSxcbiAgICAgIHRydWUsXG4gICAgICB0cnVlXG4gICAgKTtcblxuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgICAnY2FsbENsb3VkQ29kZScsXG4gICAgICB7XG4gICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICdUaGUgY2FsbCBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byBpbnZva2UgYSBjbG91ZCBjb2RlIGZ1bmN0aW9uLicsXG4gICAgICAgIGFyZ3M6IHtcbiAgICAgICAgICBmdW5jdGlvbk5hbWU6IHtcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkLicsXG4gICAgICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoY2xvdWRDb2RlRnVuY3Rpb25FbnVtKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246ICdUaGVzZSBhcmUgdGhlIHBhcmFtcyB0byBiZSBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uLicsXG4gICAgICAgICAgICB0eXBlOiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVCxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB0eXBlOiBkZWZhdWx0R3JhcGhRTFR5cGVzLkFOWSxcbiAgICAgICAgYXN5bmMgcmVzb2x2ZShfc291cmNlLCBhcmdzLCBjb250ZXh0KSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHsgZnVuY3Rpb25OYW1lLCBwYXJhbXMgfSA9IGFyZ3M7XG4gICAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcblxuICAgICAgICAgICAgcmV0dXJuIChhd2FpdCBGdW5jdGlvbnNSb3V0ZXIuaGFuZGxlQ2xvdWRGdW5jdGlvbih7XG4gICAgICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgICBpbmZvLFxuICAgICAgICAgICAgICBib2R5OiBwYXJhbXMsXG4gICAgICAgICAgICB9KSkucmVzcG9uc2UucmVzdWx0O1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgdHJ1ZSxcbiAgICAgIHRydWVcbiAgICApO1xuICB9XG59O1xuXG5leHBvcnQgeyBsb2FkIH07XG4iXX0= \ No newline at end of file diff --git a/lib/GraphQL/loaders/parseClassMutations.js b/lib/GraphQL/loaders/parseClassMutations.js new file mode 100644 index 0000000000..5ace98cb67 --- /dev/null +++ b/lib/GraphQL/loaders/parseClassMutations.js @@ -0,0 +1,234 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlListFields = _interopRequireDefault(require("graphql-list-fields")); + +var defaultGraphQLTypes = _interopRequireWildcard(require("./defaultGraphQLTypes")); + +var _parseGraphQLUtils = require("../parseGraphQLUtils"); + +var objectsMutations = _interopRequireWildcard(require("../helpers/objectsMutations")); + +var objectsQueries = _interopRequireWildcard(require("../helpers/objectsQueries")); + +var _ParseGraphQLController = require("../../Controllers/ParseGraphQLController"); + +var _className = require("../transformers/className"); + +var _mutation = require("../transformers/mutation"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const getOnlyRequiredFields = (updatedFields, selectedFieldsString, includedFieldsString, nativeObjectFields) => { + const includedFields = includedFieldsString.split(','); + const selectedFields = selectedFieldsString.split(','); + const missingFields = selectedFields.filter(field => !nativeObjectFields.includes(field) || includedFields.includes(field)).join(','); + + if (!missingFields.length) { + return { + needGet: false, + keys: '' + }; + } else { + return { + needGet: true, + keys: missingFields + }; + } +}; + +const load = function (parseGraphQLSchema, parseClass, parseClassConfig) { + const className = parseClass.className; + const graphQLClassName = (0, _className.transformClassNameToGraphQL)(className); + const { + create: isCreateEnabled = true, + update: isUpdateEnabled = true, + destroy: isDestroyEnabled = true + } = (0, _parseGraphQLUtils.getParseClassMutationConfig)(parseClassConfig); + const { + classGraphQLCreateType, + classGraphQLUpdateType, + classGraphQLOutputType + } = parseGraphQLSchema.parseClassTypes[className]; + + if (isCreateEnabled) { + const createGraphQLMutationName = `create${graphQLClassName}`; + parseGraphQLSchema.addGraphQLMutation(createGraphQLMutationName, { + description: `The ${createGraphQLMutationName} mutation can be used to create a new object of the ${graphQLClassName} class.`, + args: { + fields: { + description: 'These are the fields used to create the object.', + type: classGraphQLCreateType || defaultGraphQLTypes.OBJECT + } + }, + type: new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT), + + async resolve(_source, args, context, mutationInfo) { + try { + let { + fields + } = args; + if (!fields) fields = {}; + const { + config, + auth, + info + } = context; + const parseFields = await (0, _mutation.transformTypes)('create', fields, { + className, + parseGraphQLSchema, + req: { + config, + auth, + info + } + }); + const createdObject = await objectsMutations.createObject(className, parseFields, config, auth, info); + const selectedFields = (0, _graphqlListFields.default)(mutationInfo); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + const { + keys: requiredKeys, + needGet + } = getOnlyRequiredFields(fields, keys, include, ['id', 'createdAt', 'updatedAt']); + let optimizedObject = {}; + + if (needGet) { + optimizedObject = await objectsQueries.getObject(className, createdObject.objectId, requiredKeys, include, undefined, undefined, config, auth, info); + } + + return _objectSpread({}, createdObject, { + updatedAt: createdObject.createdAt + }, parseFields, {}, optimizedObject); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }); + } + + if (isUpdateEnabled) { + const updateGraphQLMutationName = `update${graphQLClassName}`; + parseGraphQLSchema.addGraphQLMutation(updateGraphQLMutationName, { + description: `The ${updateGraphQLMutationName} mutation can be used to update an object of the ${graphQLClassName} class.`, + args: { + id: defaultGraphQLTypes.OBJECT_ID_ATT, + fields: { + description: 'These are the fields used to update the object.', + type: classGraphQLUpdateType || defaultGraphQLTypes.OBJECT + } + }, + type: new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT), + + async resolve(_source, args, context, mutationInfo) { + try { + const { + id, + fields + } = args; + const { + config, + auth, + info + } = context; + const parseFields = await (0, _mutation.transformTypes)('update', fields, { + className, + parseGraphQLSchema, + req: { + config, + auth, + info + } + }); + const updatedObject = await objectsMutations.updateObject(className, id, parseFields, config, auth, info); + const selectedFields = (0, _graphqlListFields.default)(mutationInfo); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + const { + keys: requiredKeys, + needGet + } = getOnlyRequiredFields(fields, keys, include, ['id', 'updatedAt']); + let optimizedObject = {}; + + if (needGet) { + optimizedObject = await objectsQueries.getObject(className, id, requiredKeys, include, undefined, undefined, config, auth, info); + } + + return _objectSpread({ + id + }, updatedObject, {}, parseFields, {}, optimizedObject); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }); + } + + if (isDestroyEnabled) { + const deleteGraphQLMutationName = `delete${graphQLClassName}`; + parseGraphQLSchema.addGraphQLMutation(deleteGraphQLMutationName, { + description: `The ${deleteGraphQLMutationName} mutation can be used to delete an object of the ${graphQLClassName} class.`, + args: { + id: defaultGraphQLTypes.OBJECT_ID_ATT + }, + type: new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT), + + async resolve(_source, args, context, mutationInfo) { + try { + const { + id + } = args; + const { + config, + auth, + info + } = context; + const selectedFields = (0, _graphqlListFields.default)(mutationInfo); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + let optimizedObject = {}; + const splitedKeys = keys.split(','); + + if (splitedKeys.length > 1 || splitedKeys[0] !== 'id') { + optimizedObject = await objectsQueries.getObject(className, id, keys, include, undefined, undefined, config, auth, info); + } + + await objectsMutations.deleteObject(className, id, config, auth, info); + return _objectSpread({ + id + }, optimizedObject); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }); + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvcGFyc2VDbGFzc011dGF0aW9ucy5qcyJdLCJuYW1lcyI6WyJnZXRPbmx5UmVxdWlyZWRGaWVsZHMiLCJ1cGRhdGVkRmllbGRzIiwic2VsZWN0ZWRGaWVsZHNTdHJpbmciLCJpbmNsdWRlZEZpZWxkc1N0cmluZyIsIm5hdGl2ZU9iamVjdEZpZWxkcyIsImluY2x1ZGVkRmllbGRzIiwic3BsaXQiLCJzZWxlY3RlZEZpZWxkcyIsIm1pc3NpbmdGaWVsZHMiLCJmaWx0ZXIiLCJmaWVsZCIsImluY2x1ZGVzIiwiam9pbiIsImxlbmd0aCIsIm5lZWRHZXQiLCJrZXlzIiwibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsInBhcnNlQ2xhc3MiLCJwYXJzZUNsYXNzQ29uZmlnIiwiY2xhc3NOYW1lIiwiZ3JhcGhRTENsYXNzTmFtZSIsImNyZWF0ZSIsImlzQ3JlYXRlRW5hYmxlZCIsInVwZGF0ZSIsImlzVXBkYXRlRW5hYmxlZCIsImRlc3Ryb3kiLCJpc0Rlc3Ryb3lFbmFibGVkIiwiY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZSIsImNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIiwicGFyc2VDbGFzc1R5cGVzIiwiY3JlYXRlR3JhcGhRTE11dGF0aW9uTmFtZSIsImFkZEdyYXBoUUxNdXRhdGlvbiIsImRlc2NyaXB0aW9uIiwiYXJncyIsImZpZWxkcyIsInR5cGUiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiT0JKRUNUIiwiR3JhcGhRTE5vbk51bGwiLCJyZXNvbHZlIiwiX3NvdXJjZSIsImNvbnRleHQiLCJtdXRhdGlvbkluZm8iLCJjb25maWciLCJhdXRoIiwiaW5mbyIsInBhcnNlRmllbGRzIiwicmVxIiwiY3JlYXRlZE9iamVjdCIsIm9iamVjdHNNdXRhdGlvbnMiLCJjcmVhdGVPYmplY3QiLCJpbmNsdWRlIiwicmVxdWlyZWRLZXlzIiwib3B0aW1pemVkT2JqZWN0Iiwib2JqZWN0c1F1ZXJpZXMiLCJnZXRPYmplY3QiLCJvYmplY3RJZCIsInVuZGVmaW5lZCIsInVwZGF0ZWRBdCIsImNyZWF0ZWRBdCIsImUiLCJoYW5kbGVFcnJvciIsInVwZGF0ZUdyYXBoUUxNdXRhdGlvbk5hbWUiLCJpZCIsIk9CSkVDVF9JRF9BVFQiLCJ1cGRhdGVkT2JqZWN0IiwidXBkYXRlT2JqZWN0IiwiZGVsZXRlR3JhcGhRTE11dGF0aW9uTmFtZSIsInNwbGl0ZWRLZXlzIiwiZGVsZXRlT2JqZWN0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBSUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FBRUEsTUFBTUEscUJBQXFCLEdBQUcsQ0FDNUJDLGFBRDRCLEVBRTVCQyxvQkFGNEIsRUFHNUJDLG9CQUg0QixFQUk1QkMsa0JBSjRCLEtBS3pCO0FBQ0gsUUFBTUMsY0FBYyxHQUFHRixvQkFBb0IsQ0FBQ0csS0FBckIsQ0FBMkIsR0FBM0IsQ0FBdkI7QUFDQSxRQUFNQyxjQUFjLEdBQUdMLG9CQUFvQixDQUFDSSxLQUFyQixDQUEyQixHQUEzQixDQUF2QjtBQUNBLFFBQU1FLGFBQWEsR0FBR0QsY0FBYyxDQUNqQ0UsTUFEbUIsQ0FFbEJDLEtBQUssSUFDSCxDQUFDTixrQkFBa0IsQ0FBQ08sUUFBbkIsQ0FBNEJELEtBQTVCLENBQUQsSUFDQUwsY0FBYyxDQUFDTSxRQUFmLENBQXdCRCxLQUF4QixDQUpnQixFQU1uQkUsSUFObUIsQ0FNZCxHQU5jLENBQXRCOztBQU9BLE1BQUksQ0FBQ0osYUFBYSxDQUFDSyxNQUFuQixFQUEyQjtBQUN6QixXQUFPO0FBQUVDLE1BQUFBLE9BQU8sRUFBRSxLQUFYO0FBQWtCQyxNQUFBQSxJQUFJLEVBQUU7QUFBeEIsS0FBUDtBQUNELEdBRkQsTUFFTztBQUNMLFdBQU87QUFBRUQsTUFBQUEsT0FBTyxFQUFFLElBQVg7QUFBaUJDLE1BQUFBLElBQUksRUFBRVA7QUFBdkIsS0FBUDtBQUNEO0FBQ0YsQ0FwQkQ7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ckIsSUFBMEJ5RCxXQUFXLENBQUMsQ0FBRCxDQUFYLEtBQW1CLElBQWpELEVBQXVEO0FBQ3JEZixZQUFBQSxlQUFlLEdBQUcsTUFBTUMsY0FBYyxDQUFDQyxTQUFmLENBQ3RCckMsU0FEc0IsRUFFdEI2QyxFQUZzQixFQUd0QmxELElBSHNCLEVBSXRCc0MsT0FKc0IsRUFLdEJNLFNBTHNCLEVBTXRCQSxTQU5zQixFQU90QmQsTUFQc0IsRUFRdEJDLElBUnNCLEVBU3RCQyxJQVRzQixDQUF4QjtBQVdEOztBQUNELGdCQUFNSSxnQkFBZ0IsQ0FBQ29CLFlBQWpCLENBQ0puRCxTQURJLEVBRUo2QyxFQUZJLEVBR0pwQixNQUhJLEVBSUpDLElBSkksRUFLSkMsSUFMSSxDQUFOO0FBT0E7QUFBU2tCLFlBQUFBO0FBQVQsYUFBZ0JWLGVBQWhCO0FBQ0QsU0E3QkQsQ0E2QkUsT0FBT08sQ0FBUCxFQUFVO0FBQ1Y3QyxVQUFBQSxrQkFBa0IsQ0FBQzhDLFdBQW5CLENBQStCRCxDQUEvQjtBQUNEO0FBQ0Y7O0FBekM4RCxLQUFqRTtBQTJDRDtBQUNGLENBM01EIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR3JhcGhRTE5vbk51bGwgfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCBnZXRGaWVsZE5hbWVzIGZyb20gJ2dyYXBocWwtbGlzdC1maWVsZHMnO1xuaW1wb3J0ICogYXMgZGVmYXVsdEdyYXBoUUxUeXBlcyBmcm9tICcuL2RlZmF1bHRHcmFwaFFMVHlwZXMnO1xuaW1wb3J0IHtcbiAgZXh0cmFjdEtleXNBbmRJbmNsdWRlLFxuICBnZXRQYXJzZUNsYXNzTXV0YXRpb25Db25maWcsXG59IGZyb20gJy4uL3BhcnNlR3JhcGhRTFV0aWxzJztcbmltcG9ydCAqIGFzIG9iamVjdHNNdXRhdGlvbnMgZnJvbSAnLi4vaGVscGVycy9vYmplY3RzTXV0YXRpb25zJztcbmltcG9ydCAqIGFzIG9iamVjdHNRdWVyaWVzIGZyb20gJy4uL2hlbHBlcnMvb2JqZWN0c1F1ZXJpZXMnO1xuaW1wb3J0IHsgUGFyc2VHcmFwaFFMQ2xhc3NDb25maWcgfSBmcm9tICcuLi8uLi9Db250cm9sbGVycy9QYXJzZUdyYXBoUUxDb250cm9sbGVyJztcbmltcG9ydCB7IHRyYW5zZm9ybUNsYXNzTmFtZVRvR3JhcGhRTCB9IGZyb20gJy4uL3RyYW5zZm9ybWVycy9jbGFzc05hbWUnO1xuaW1wb3J0IHsgdHJhbnNmb3JtVHlwZXMgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvbXV0YXRpb24nO1xuXG5jb25zdCBnZXRPbmx5UmVxdWlyZWRGaWVsZHMgPSAoXG4gIHVwZGF0ZWRGaWVsZHMsXG4gIHNlbGVjdGVkRmllbGRzU3RyaW5nLFxuICBpbmNsdWRlZEZpZWxkc1N0cmluZyxcbiAgbmF0aXZlT2JqZWN0RmllbGRzXG4pID0+IHtcbiAgY29uc3QgaW5jbHVkZWRGaWVsZHMgPSBpbmNsdWRlZEZpZWxkc1N0cmluZy5zcGxpdCgnLCcpO1xuICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IHNlbGVjdGVkRmllbGRzU3RyaW5nLnNwbGl0KCcsJyk7XG4gIGNvbnN0IG1pc3NpbmdGaWVsZHMgPSBzZWxlY3RlZEZpZWxkc1xuICAgIC5maWx0ZXIoXG4gICAgICBmaWVsZCA9PlxuICAgICAgICAhbmF0aXZlT2JqZWN0RmllbGRzLmluY2x1ZGVzKGZpZWxkKSB8fFxuICAgICAgICBpbmNsdWRlZEZpZWxkcy5pbmNsdWRlcyhmaWVsZClcbiAgICApXG4gICAgLmpvaW4oJywnKTtcbiAgaWYgKCFtaXNzaW5nRmllbGRzLmxlbmd0aCkge1xuICAgIHJldHVybiB7IG5lZWRHZXQ6IGZhbHNlLCBrZXlzOiAnJyB9O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB7IG5lZWRHZXQ6IHRydWUsIGtleXM6IG1pc3NpbmdGaWVsZHMgfTtcbiAgfVxufTtcblxuY29uc3QgbG9hZCA9IGZ1bmN0aW9uKFxuICBwYXJzZUdyYXBoUUxTY2hlbWEsXG4gIHBhcnNlQ2xhc3MsXG4gIHBhcnNlQ2xhc3NDb25maWc6ID9QYXJzZUdyYXBoUUxDbGFzc0NvbmZpZ1xuKSB7XG4gIGNvbnN0IGNsYXNzTmFtZSA9IHBhcnNlQ2xhc3MuY2xhc3NOYW1lO1xuICBjb25zdCBncmFwaFFMQ2xhc3NOYW1lID0gdHJhbnNmb3JtQ2xhc3NOYW1lVG9HcmFwaFFMKGNsYXNzTmFtZSk7XG5cbiAgY29uc3Qge1xuICAgIGNyZWF0ZTogaXNDcmVhdGVFbmFibGVkID0gdHJ1ZSxcbiAgICB1cGRhdGU6IGlzVXBkYXRlRW5hYmxlZCA9IHRydWUsXG4gICAgZGVzdHJveTogaXNEZXN0cm95RW5hYmxlZCA9IHRydWUsXG4gIH0gPSBnZXRQYXJzZUNsYXNzTXV0YXRpb25Db25maWcocGFyc2VDbGFzc0NvbmZpZyk7XG5cbiAgY29uc3Qge1xuICAgIGNsYXNzR3JhcGhRTENyZWF0ZVR5cGUsXG4gICAgY2xhc3NHcmFwaFFMVXBkYXRlVHlwZSxcbiAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlLFxuICB9ID0gcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1tjbGFzc05hbWVdO1xuXG4gIGlmIChpc0NyZWF0ZUVuYWJsZWQpIHtcbiAgICBjb25zdCBjcmVhdGVHcmFwaFFMTXV0YXRpb25OYW1lID0gYGNyZWF0ZSR7Z3JhcGhRTENsYXNzTmFtZX1gO1xuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oY3JlYXRlR3JhcGhRTE11dGF0aW9uTmFtZSwge1xuICAgICAgZGVzY3JpcHRpb246IGBUaGUgJHtjcmVhdGVHcmFwaFFMTXV0YXRpb25OYW1lfSBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBuZXcgb2JqZWN0IG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgICBhcmdzOiB7XG4gICAgICAgIGZpZWxkczoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhlc2UgYXJlIHRoZSBmaWVsZHMgdXNlZCB0byBjcmVhdGUgdGhlIG9iamVjdC4nLFxuICAgICAgICAgIHR5cGU6IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGUgfHwgZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1QsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIHx8IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUXG4gICAgICApLFxuICAgICAgYXN5bmMgcmVzb2x2ZShfc291cmNlLCBhcmdzLCBjb250ZXh0LCBtdXRhdGlvbkluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsZXQgeyBmaWVsZHMgfSA9IGFyZ3M7XG4gICAgICAgICAgaWYgKCFmaWVsZHMpIGZpZWxkcyA9IHt9O1xuICAgICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuXG4gICAgICAgICAgY29uc3QgcGFyc2VGaWVsZHMgPSBhd2FpdCB0cmFuc2Zvcm1UeXBlcygnY3JlYXRlJywgZmllbGRzLCB7XG4gICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEsXG4gICAgICAgICAgICByZXE6IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb25zdCBjcmVhdGVkT2JqZWN0ID0gYXdhaXQgb2JqZWN0c011dGF0aW9ucy5jcmVhdGVPYmplY3QoXG4gICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICBwYXJzZUZpZWxkcyxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMobXV0YXRpb25JbmZvKTtcbiAgICAgICAgICBjb25zdCB7IGtleXMsIGluY2x1ZGUgfSA9IGV4dHJhY3RLZXlzQW5kSW5jbHVkZShzZWxlY3RlZEZpZWxkcyk7XG4gICAgICAgICAgY29uc3QgeyBrZXlzOiByZXF1aXJlZEtleXMsIG5lZWRHZXQgfSA9IGdldE9ubHlSZXF1aXJlZEZpZWxkcyhcbiAgICAgICAgICAgIGZpZWxkcyxcbiAgICAgICAgICAgIGtleXMsXG4gICAgICAgICAgICBpbmNsdWRlLFxuICAgICAgICAgICAgWydpZCcsICdjcmVhdGVkQXQnLCAndXBkYXRlZEF0J11cbiAgICAgICAgICApO1xuICAgICAgICAgIGxldCBvcHRpbWl6ZWRPYmplY3QgPSB7fTtcbiAgICAgICAgICBpZiAobmVlZEdldCkge1xuICAgICAgICAgICAgb3B0aW1pemVkT2JqZWN0ID0gYXdhaXQgb2JqZWN0c1F1ZXJpZXMuZ2V0T2JqZWN0KFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIGNyZWF0ZWRPYmplY3Qub2JqZWN0SWQsXG4gICAgICAgICAgICAgIHJlcXVpcmVkS2V5cyxcbiAgICAgICAgICAgICAgaW5jbHVkZSxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgaW5mb1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmNyZWF0ZWRPYmplY3QsXG4gICAgICAgICAgICB1cGRhdGVkQXQ6IGNyZWF0ZWRPYmplY3QuY3JlYXRlZEF0LFxuICAgICAgICAgICAgLi4ucGFyc2VGaWVsZHMsXG4gICAgICAgICAgICAuLi5vcHRpbWl6ZWRPYmplY3QsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChpc1VwZGF0ZUVuYWJsZWQpIHtcbiAgICBjb25zdCB1cGRhdGVHcmFwaFFMTXV0YXRpb25OYW1lID0gYHVwZGF0ZSR7Z3JhcGhRTENsYXNzTmFtZX1gO1xuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24odXBkYXRlR3JhcGhRTE11dGF0aW9uTmFtZSwge1xuICAgICAgZGVzY3JpcHRpb246IGBUaGUgJHt1cGRhdGVHcmFwaFFMTXV0YXRpb25OYW1lfSBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byB1cGRhdGUgYW4gb2JqZWN0IG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgICBhcmdzOiB7XG4gICAgICAgIGlkOiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVF9JRF9BVFQsXG4gICAgICAgIGZpZWxkczoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhlc2UgYXJlIHRoZSBmaWVsZHMgdXNlZCB0byB1cGRhdGUgdGhlIG9iamVjdC4nLFxuICAgICAgICAgIHR5cGU6IGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUgfHwgZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1QsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIHx8IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUXG4gICAgICApLFxuICAgICAgYXN5bmMgcmVzb2x2ZShfc291cmNlLCBhcmdzLCBjb250ZXh0LCBtdXRhdGlvbkluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGlkLCBmaWVsZHMgfSA9IGFyZ3M7XG4gICAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgICBjb25zdCBwYXJzZUZpZWxkcyA9IGF3YWl0IHRyYW5zZm9ybVR5cGVzKCd1cGRhdGUnLCBmaWVsZHMsIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgICAgICAgICAgIHJlcTogeyBjb25maWcsIGF1dGgsIGluZm8gfSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IHVwZGF0ZWRPYmplY3QgPSBhd2FpdCBvYmplY3RzTXV0YXRpb25zLnVwZGF0ZU9iamVjdChcbiAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgIGlkLFxuICAgICAgICAgICAgcGFyc2VGaWVsZHMsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgaW5mb1xuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMobXV0YXRpb25JbmZvKTtcbiAgICAgICAgICBjb25zdCB7IGtleXMsIGluY2x1ZGUgfSA9IGV4dHJhY3RLZXlzQW5kSW5jbHVkZShzZWxlY3RlZEZpZWxkcyk7XG5cbiAgICAgICAgICBjb25zdCB7IGtleXM6IHJlcXVpcmVkS2V5cywgbmVlZEdldCB9ID0gZ2V0T25seVJlcXVpcmVkRmllbGRzKFxuICAgICAgICAgICAgZmllbGRzLFxuICAgICAgICAgICAga2V5cyxcbiAgICAgICAgICAgIGluY2x1ZGUsXG4gICAgICAgICAgICBbJ2lkJywgJ3VwZGF0ZWRBdCddXG4gICAgICAgICAgKTtcbiAgICAgICAgICBsZXQgb3B0aW1pemVkT2JqZWN0ID0ge307XG4gICAgICAgICAgaWYgKG5lZWRHZXQpIHtcbiAgICAgICAgICAgIG9wdGltaXplZE9iamVjdCA9IGF3YWl0IG9iamVjdHNRdWVyaWVzLmdldE9iamVjdChcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgcmVxdWlyZWRLZXlzLFxuICAgICAgICAgICAgICBpbmNsdWRlLFxuICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgICBpbmZvXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAuLi51cGRhdGVkT2JqZWN0LFxuICAgICAgICAgICAgLi4ucGFyc2VGaWVsZHMsXG4gICAgICAgICAgICAuLi5vcHRpbWl6ZWRPYmplY3QsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChpc0Rlc3Ryb3lFbmFibGVkKSB7XG4gICAgY29uc3QgZGVsZXRlR3JhcGhRTE11dGF0aW9uTmFtZSA9IGBkZWxldGUke2dyYXBoUUxDbGFzc05hbWV9YDtcbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTE11dGF0aW9uKGRlbGV0ZUdyYXBoUUxNdXRhdGlvbk5hbWUsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7ZGVsZXRlR3JhcGhRTE11dGF0aW9uTmFtZX0gbXV0YXRpb24gY2FuIGJlIHVzZWQgdG8gZGVsZXRlIGFuIG9iamVjdCBvZiB0aGUgJHtncmFwaFFMQ2xhc3NOYW1lfSBjbGFzcy5gLFxuICAgICAgYXJnczoge1xuICAgICAgICBpZDogZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1RfSURfQVRULFxuICAgICAgfSxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChcbiAgICAgICAgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSB8fCBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVFxuICAgICAgKSxcbiAgICAgIGFzeW5jIHJlc29sdmUoX3NvdXJjZSwgYXJncywgY29udGV4dCwgbXV0YXRpb25JbmZvKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBpZCB9ID0gYXJncztcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcbiAgICAgICAgICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMobXV0YXRpb25JbmZvKTtcbiAgICAgICAgICBjb25zdCB7IGtleXMsIGluY2x1ZGUgfSA9IGV4dHJhY3RLZXlzQW5kSW5jbHVkZShzZWxlY3RlZEZpZWxkcyk7XG5cbiAgICAgICAgICBsZXQgb3B0aW1pemVkT2JqZWN0ID0ge307XG4gICAgICAgICAgY29uc3Qgc3BsaXRlZEtleXMgPSBrZXlzLnNwbGl0KCcsJyk7XG4gICAgICAgICAgaWYgKHNwbGl0ZWRLZXlzLmxlbmd0aCA+IDEgfHwgc3BsaXRlZEtleXNbMF0gIT09ICdpZCcpIHtcbiAgICAgICAgICAgIG9wdGltaXplZE9iamVjdCA9IGF3YWl0IG9iamVjdHNRdWVyaWVzLmdldE9iamVjdChcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAga2V5cyxcbiAgICAgICAgICAgICAgaW5jbHVkZSxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgaW5mb1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXdhaXQgb2JqZWN0c011dGF0aW9ucy5kZWxldGVPYmplY3QoXG4gICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4geyBpZCwgLi4ub3B0aW1pemVkT2JqZWN0IH07XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn07XG5cbmV4cG9ydCB7IGxvYWQgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/loaders/parseClassQueries.js b/lib/GraphQL/loaders/parseClassQueries.js new file mode 100644 index 0000000000..c7662a2fba --- /dev/null +++ b/lib/GraphQL/loaders/parseClassQueries.js @@ -0,0 +1,133 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlListFields = _interopRequireDefault(require("graphql-list-fields")); + +var _pluralize = _interopRequireDefault(require("pluralize")); + +var defaultGraphQLTypes = _interopRequireWildcard(require("./defaultGraphQLTypes")); + +var objectsQueries = _interopRequireWildcard(require("../helpers/objectsQueries")); + +var _ParseGraphQLController = require("../../Controllers/ParseGraphQLController"); + +var _className = require("../transformers/className"); + +var _parseGraphQLUtils = require("../parseGraphQLUtils"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const getParseClassQueryConfig = function (parseClassConfig) { + return parseClassConfig && parseClassConfig.query || {}; +}; + +const getQuery = async (className, _source, args, context, queryInfo) => { + const { + id, + options + } = args; + const { + readPreference, + includeReadPreference + } = options || {}; + const { + config, + auth, + info + } = context; + const selectedFields = (0, _graphqlListFields.default)(queryInfo); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + return await objectsQueries.getObject(className, id, keys, include, readPreference, includeReadPreference, config, auth, info); +}; + +const load = function (parseGraphQLSchema, parseClass, parseClassConfig) { + const className = parseClass.className; + const graphQLClassName = (0, _className.transformClassNameToGraphQL)(className); + const { + get: isGetEnabled = true, + find: isFindEnabled = true + } = getParseClassQueryConfig(parseClassConfig); + const { + classGraphQLOutputType, + classGraphQLFindArgs, + classGraphQLFindResultType + } = parseGraphQLSchema.parseClassTypes[className]; + + if (isGetEnabled) { + const getGraphQLQueryName = graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1); + parseGraphQLSchema.addGraphQLQuery(getGraphQLQueryName, { + description: `The ${getGraphQLQueryName} query can be used to get an object of the ${graphQLClassName} class by its id.`, + args: { + id: defaultGraphQLTypes.OBJECT_ID_ATT, + options: defaultGraphQLTypes.READ_OPTIONS_ATT + }, + type: new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT), + + async resolve(_source, args, context, queryInfo) { + try { + return await getQuery(className, _source, args, context, queryInfo); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }); + } + + if (isFindEnabled) { + const findGraphQLQueryName = (0, _pluralize.default)(graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1)); + parseGraphQLSchema.addGraphQLQuery(findGraphQLQueryName, { + description: `The ${findGraphQLQueryName} query can be used to find objects of the ${graphQLClassName} class.`, + args: classGraphQLFindArgs, + type: new _graphql.GraphQLNonNull(classGraphQLFindResultType || defaultGraphQLTypes.FIND_RESULT), + + async resolve(_source, args, context, queryInfo) { + try { + const { + where, + order, + skip, + limit, + options + } = args; + const { + readPreference, + includeReadPreference, + subqueryReadPreference + } = options || {}; + const { + config, + auth, + info + } = context; + const selectedFields = (0, _graphqlListFields.default)(queryInfo); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields.filter(field => field.includes('.')).map(field => field.slice(field.indexOf('.') + 1))); + const parseOrder = order && order.join(','); + return await objectsQueries.findObjects(className, where, parseOrder, skip, limit, keys, include, false, readPreference, includeReadPreference, subqueryReadPreference, config, auth, info, selectedFields.map(field => field.split('.', 1)[0]), parseClass.fields); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }); + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvcGFyc2VDbGFzc1F1ZXJpZXMuanMiXSwibmFtZXMiOlsiZ2V0UGFyc2VDbGFzc1F1ZXJ5Q29uZmlnIiwicGFyc2VDbGFzc0NvbmZpZyIsInF1ZXJ5IiwiZ2V0UXVlcnkiLCJjbGFzc05hbWUiLCJfc291cmNlIiwiYXJncyIsImNvbnRleHQiLCJxdWVyeUluZm8iLCJpZCIsIm9wdGlvbnMiLCJyZWFkUHJlZmVyZW5jZSIsImluY2x1ZGVSZWFkUHJlZmVyZW5jZSIsImNvbmZpZyIsImF1dGgiLCJpbmZvIiwic2VsZWN0ZWRGaWVsZHMiLCJrZXlzIiwiaW5jbHVkZSIsIm9iamVjdHNRdWVyaWVzIiwiZ2V0T2JqZWN0IiwibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsInBhcnNlQ2xhc3MiLCJncmFwaFFMQ2xhc3NOYW1lIiwiZ2V0IiwiaXNHZXRFbmFibGVkIiwiZmluZCIsImlzRmluZEVuYWJsZWQiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIiwiY2xhc3NHcmFwaFFMRmluZEFyZ3MiLCJjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZSIsInBhcnNlQ2xhc3NUeXBlcyIsImdldEdyYXBoUUxRdWVyeU5hbWUiLCJjaGFyQXQiLCJ0b0xvd2VyQ2FzZSIsInNsaWNlIiwiYWRkR3JhcGhRTFF1ZXJ5IiwiZGVzY3JpcHRpb24iLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiT0JKRUNUX0lEX0FUVCIsIlJFQURfT1BUSU9OU19BVFQiLCJ0eXBlIiwiR3JhcGhRTE5vbk51bGwiLCJPQkpFQ1QiLCJyZXNvbHZlIiwiZSIsImhhbmRsZUVycm9yIiwiZmluZEdyYXBoUUxRdWVyeU5hbWUiLCJGSU5EX1JFU1VMVCIsIndoZXJlIiwib3JkZXIiLCJza2lwIiwibGltaXQiLCJzdWJxdWVyeVJlYWRQcmVmZXJlbmNlIiwiZmlsdGVyIiwiZmllbGQiLCJpbmNsdWRlcyIsIm1hcCIsImluZGV4T2YiLCJwYXJzZU9yZGVyIiwiam9p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Qiw4Q0FDeEJGLGNBQWMsQ0FDWHVDLE1BREgsQ0FDVUMsS0FBSyxJQUFJQSxLQUFLLENBQUNDLFFBQU4sQ0FBZSxHQUFmLENBRG5CLEVBRUdDLEdBRkgsQ0FFT0YsS0FBSyxJQUFJQSxLQUFLLENBQUNwQixLQUFOLENBQVlvQixLQUFLLENBQUNHLE9BQU4sQ0FBYyxHQUFkLElBQXFCLENBQWpDLENBRmhCLENBRHdCLENBQTFCO0FBS0EsZ0JBQU1DLFVBQVUsR0FBR1QsS0FBSyxJQUFJQSxLQUFLLENBQUNVLElBQU4sQ0FBVyxHQUFYLENBQTVCO0FBRUEsaUJBQU8sTUFBTTFDLGNBQWMsQ0FBQzJDLFdBQWYsQ0FDWDFELFNBRFcsRUFFWDhDLEtBRlcsRUFHWFUsVUFIVyxFQUlYUixJQUpXLEVBS1hDLEtBTFcsRUFNWHBDLElBTlcsRUFPWEMsT0FQVyxFQVFYLEtBUlcsRUFTWFAsY0FUVyxFQVVYQyxxQkFWVyxFQVdYMEMsc0JBWFcsRUFZWHpDLE1BWlcsRUFhWEMsSUFiVyxFQWNYQyxJQWRXLEVBZVhDLGNBQWMsQ0FBQzBDLEdBQWYsQ0FBbUJGLEtBQUssSUFBSUEsS0FBSyxDQUFDTyxLQUFOLENBQVksR0FBWixFQUFpQixDQUFqQixFQUFvQixDQUFwQixDQUE1QixDQWZXLEVBZ0JYeEMsVUFBVSxDQUFDeUMsTUFoQkEsQ0FBYjtBQWtCRCxTQW5DRCxDQW1DRSxPQUFPbEIsQ0FBUCxFQUFVO0FBQ1Z4QixVQUFBQSxrQkFBa0IsQ0FBQ3lCLFdBQW5CLENBQStCRCxDQUEvQjtBQUNEO0FBQ0Y7O0FBN0NzRCxLQUF6RDtBQStDRDtBQUNGLENBNUZEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR3JhcGhRTE5vbk51bGwgfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCBnZXRGaWVsZE5hbWVzIGZyb20gJ2dyYXBocWwtbGlzdC1maWVsZHMnO1xuaW1wb3J0IHBsdXJhbGl6ZSBmcm9tICdwbHVyYWxpemUnO1xuaW1wb3J0ICogYXMgZGVmYXVsdEdyYXBoUUxUeXBlcyBmcm9tICcuL2RlZmF1bHRHcmFwaFFMVHlwZXMnO1xuaW1wb3J0ICogYXMgb2JqZWN0c1F1ZXJpZXMgZnJvbSAnLi4vaGVscGVycy9vYmplY3RzUXVlcmllcyc7XG5pbXBvcnQgeyBQYXJzZUdyYXBoUUxDbGFzc0NvbmZpZyB9IGZyb20gJy4uLy4uL0NvbnRyb2xsZXJzL1BhcnNlR3JhcGhRTENvbnRyb2xsZXInO1xuaW1wb3J0IHsgdHJhbnNmb3JtQ2xhc3NOYW1lVG9HcmFwaFFMIH0gZnJvbSAnLi4vdHJhbnNmb3JtZXJzL2NsYXNzTmFtZSc7XG5pbXBvcnQgeyBleHRyYWN0S2V5c0FuZEluY2x1ZGUgfSBmcm9tICcuLi9wYXJzZUdyYXBoUUxVdGlscyc7XG5cbmNvbnN0IGdldFBhcnNlQ2xhc3NRdWVyeUNvbmZpZyA9IGZ1bmN0aW9uKFxuICBwYXJzZUNsYXNzQ29uZmlnOiA/UGFyc2VHcmFwaFFMQ2xhc3NDb25maWdcbikge1xuICByZXR1cm4gKHBhcnNlQ2xhc3NDb25maWcgJiYgcGFyc2VDbGFzc0NvbmZpZy5xdWVyeSkgfHwge307XG59O1xuXG5jb25zdCBnZXRRdWVyeSA9IGFzeW5jIChjbGFzc05hbWUsIF9zb3VyY2UsIGFyZ3MsIGNvbnRleHQsIHF1ZXJ5SW5mbykgPT4ge1xuICBjb25zdCB7IGlkLCBvcHRpb25zIH0gPSBhcmdzO1xuICBjb25zdCB7IHJlYWRQcmVmZXJlbmNlLCBpbmNsdWRlUmVhZFByZWZlcmVuY2UgfSA9IG9wdGlvbnMgfHwge307XG4gIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMocXVlcnlJbmZvKTtcblxuICBjb25zdCB7IGtleXMsIGluY2x1ZGUgfSA9IGV4dHJhY3RLZXlzQW5kSW5jbHVkZShzZWxlY3RlZEZpZWxkcyk7XG5cbiAgcmV0dXJuIGF3YWl0IG9iamVjdHNRdWVyaWVzLmdldE9iamVjdChcbiAgICBjbGFzc05hbWUsXG4gICAgaWQsXG4gICAga2V5cyxcbiAgICBpbmNsdWRlLFxuICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgIGluY2x1ZGVSZWFkUHJlZmVyZW5jZSxcbiAgICBjb25maWcsXG4gICAgYXV0aCxcbiAgICBpbmZvXG4gICk7XG59O1xuXG5jb25zdCBsb2FkID0gZnVuY3Rpb24oXG4gIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgcGFyc2VDbGFzcyxcbiAgcGFyc2VDbGFzc0NvbmZpZzogP1BhcnNlR3JhcGhRTENsYXNzQ29uZmlnXG4pIHtcbiAgY29uc3QgY2xhc3NOYW1lID0gcGFyc2VDbGFzcy5jbGFzc05hbWU7XG4gIGNvbnN0IGdyYXBoUUxDbGFzc05hbWUgPSB0cmFuc2Zvcm1DbGFzc05hbWVUb0dyYXBoUUwoY2xhc3NOYW1lKTtcbiAgY29uc3Qge1xuICAgIGdldDogaXNHZXRFbmFibGVkID0gdHJ1ZSxcbiAgICBmaW5kOiBpc0ZpbmRFbmFibGVkID0gdHJ1ZSxcbiAgfSA9IGdldFBhcnNlQ2xhc3NRdWVyeUNvbmZpZyhwYXJzZUNsYXNzQ29uZmlnKTtcblxuICBjb25zdCB7XG4gICAgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSxcbiAgICBjbGFzc0dyYXBoUUxGaW5kQXJncyxcbiAgICBjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZSxcbiAgfSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNbY2xhc3NOYW1lXTtcblxuICBpZiAoaXNHZXRFbmFibGVkKSB7XG4gICAgY29uc3QgZ2V0R3JhcGhRTFF1ZXJ5TmFtZSA9XG4gICAgICBncmFwaFFMQ2xhc3NOYW1lLmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpICsgZ3JhcGhRTENsYXNzTmFtZS5zbGljZSgxKTtcbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFF1ZXJ5KGdldEdyYXBoUUxRdWVyeU5hbWUsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7Z2V0R3JhcGhRTFF1ZXJ5TmFtZX0gcXVlcnkgY2FuIGJlIHVzZWQgdG8gZ2V0IGFuIG9iamVjdCBvZiB0aGUgJHtncmFwaFFMQ2xhc3NOYW1lfSBjbGFzcyBieSBpdHMgaWQuYCxcbiAgICAgIGFyZ3M6IHtcbiAgICAgICAgaWQ6IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUX0lEX0FUVCxcbiAgICAgICAgb3B0aW9uczogZGVmYXVsdEdyYXBoUUxUeXBlcy5SRUFEX09QVElPTlNfQVRULFxuICAgICAgfSxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChcbiAgICAgICAgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSB8fCBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVFxuICAgICAgKSxcbiAgICAgIGFzeW5jIHJlc29sdmUoX3NvdXJjZSwgYXJncywgY29udGV4dCwgcXVlcnlJbmZvKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGdldFF1ZXJ5KGNsYXNzTmFtZSwgX3NvdXJjZSwgYXJncywgY29udGV4dCwgcXVlcnlJbmZvKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChpc0ZpbmRFbmFibGVkKSB7XG4gICAgY29uc3QgZmluZEdyYXBoUUxRdWVyeU5hbWUgPSBwbHVyYWxpemUoXG4gICAgICBncmFwaFFMQ2xhc3NOYW1lLmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpICsgZ3JhcGhRTENsYXNzTmFtZS5zbGljZSgxKVxuICAgICk7XG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxRdWVyeShmaW5kR3JhcGhRTFF1ZXJ5TmFtZSwge1xuICAgICAgZGVzY3JpcHRpb246IGBUaGUgJHtmaW5kR3JhcGhRTFF1ZXJ5TmFtZX0gcXVlcnkgY2FuIGJlIHVzZWQgdG8gZmluZCBvYmplY3RzIG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgICBhcmdzOiBjbGFzc0dyYXBoUUxGaW5kQXJncyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChcbiAgICAgICAgY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGUgfHwgZGVmYXVsdEdyYXBoUUxUeXBlcy5GSU5EX1JFU1VMVFxuICAgICAgKSxcbiAgICAgIGFzeW5jIHJlc29sdmUoX3NvdXJjZSwgYXJncywgY29udGV4dCwgcXVlcnlJbmZvKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyB3aGVyZSwgb3JkZXIsIHNraXAsIGxpbWl0LCBvcHRpb25zIH0gPSBhcmdzO1xuICAgICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgaW5jbHVkZVJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgc3VicXVlcnlSZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICB9ID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcbiAgICAgICAgICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMocXVlcnlJbmZvKTtcblxuICAgICAgICAgIGNvbnN0IHsga2V5cywgaW5jbHVkZSB9ID0gZXh0cmFjdEtleXNBbmRJbmNsdWRlKFxuICAgICAgICAgICAgc2VsZWN0ZWRGaWVsZHNcbiAgICAgICAgICAgICAgLmZpbHRlcihmaWVsZCA9PiBmaWVsZC5pbmNsdWRlcygnLicpKVxuICAgICAgICAgICAgICAubWFwKGZpZWxkID0+IGZpZWxkLnNsaWNlKGZpZWxkLmluZGV4T2YoJy4nKSArIDEpKVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgcGFyc2VPcmRlciA9IG9yZGVyICYmIG9yZGVyLmpvaW4oJywnKTtcblxuICAgICAgICAgIHJldHVybiBhd2FpdCBvYmplY3RzUXVlcmllcy5maW5kT2JqZWN0cyhcbiAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgIHdoZXJlLFxuICAgICAgICAgICAgcGFyc2VPcmRlcixcbiAgICAgICAgICAgIHNraXAsXG4gICAgICAgICAgICBsaW1pdCxcbiAgICAgICAgICAgIGtleXMsXG4gICAgICAgICAgICBpbmNsdWRlLFxuICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgIGluY2x1ZGVSZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgIHN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgaW5mbyxcbiAgICAgICAgICAgIHNlbGVjdGVkRmllbGRzLm1hcChmaWVsZCA9PiBmaWVsZC5zcGxpdCgnLicsIDEpWzBdKSxcbiAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufTtcblxuZXhwb3J0IHsgbG9hZCB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/loaders/parseClassTypes.js b/lib/GraphQL/loaders/parseClassTypes.js new file mode 100644 index 0000000000..e52ae4771c --- /dev/null +++ b/lib/GraphQL/loaders/parseClassTypes.js @@ -0,0 +1,551 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "extractKeysAndInclude", { + enumerable: true, + get: function () { + return _parseGraphQLUtils.extractKeysAndInclude; + } +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlListFields = _interopRequireDefault(require("graphql-list-fields")); + +var defaultGraphQLTypes = _interopRequireWildcard(require("./defaultGraphQLTypes")); + +var objectsQueries = _interopRequireWildcard(require("../helpers/objectsQueries")); + +var _ParseGraphQLController = require("../../Controllers/ParseGraphQLController"); + +var _className = require("../transformers/className"); + +var _inputType = require("../transformers/inputType"); + +var _outputType = require("../transformers/outputType"); + +var _constraintType = require("../transformers/constraintType"); + +var _parseGraphQLUtils = require("../parseGraphQLUtils"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const getParseClassTypeConfig = function (parseClassConfig) { + return parseClassConfig && parseClassConfig.type || {}; +}; + +const getInputFieldsAndConstraints = function (parseClass, parseClassConfig) { + const classFields = Object.keys(parseClass.fields).filter(field => field !== 'objectId').concat('id'); + const { + inputFields: allowedInputFields, + outputFields: allowedOutputFields, + constraintFields: allowedConstraintFields, + sortFields: allowedSortFields + } = getParseClassTypeConfig(parseClassConfig); + let classOutputFields; + let classCreateFields; + let classUpdateFields; + let classConstraintFields; + let classSortFields; // All allowed customs fields + + const classCustomFields = classFields.filter(field => { + return !Object.keys(defaultGraphQLTypes.PARSE_OBJECT_FIELDS).includes(field); + }); + + if (allowedInputFields && allowedInputFields.create) { + classCreateFields = classCustomFields.filter(field => { + return allowedInputFields.create.includes(field); + }); + } else { + classCreateFields = classCustomFields; + } + + if (allowedInputFields && allowedInputFields.update) { + classUpdateFields = classCustomFields.filter(field => { + return allowedInputFields.update.includes(field); + }); + } else { + classUpdateFields = classCustomFields; + } + + if (allowedOutputFields) { + classOutputFields = classCustomFields.filter(field => { + return allowedOutputFields.includes(field); + }); + } else { + classOutputFields = classCustomFields; + } // Filters the "password" field from class _User + + + if (parseClass.className === '_User') { + classOutputFields = classOutputFields.filter(outputField => outputField !== 'password'); + } + + if (allowedConstraintFields) { + classConstraintFields = classCustomFields.filter(field => { + return allowedConstraintFields.includes(field); + }); + } else { + classConstraintFields = classFields; + } + + if (allowedSortFields) { + classSortFields = allowedSortFields; + + if (!classSortFields.length) { + // must have at least 1 order field + // otherwise the FindArgs Input Type will throw. + classSortFields.push({ + field: 'id', + asc: true, + desc: true + }); + } + } else { + classSortFields = classFields.map(field => { + return { + field, + asc: true, + desc: true + }; + }); + } + + return { + classCreateFields, + classUpdateFields, + classConstraintFields, + classOutputFields, + classSortFields + }; +}; + +const load = (parseGraphQLSchema, parseClass, parseClassConfig) => { + const className = parseClass.className; + const graphQLClassName = (0, _className.transformClassNameToGraphQL)(className); + const { + classCreateFields, + classUpdateFields, + classOutputFields, + classConstraintFields, + classSortFields + } = getInputFieldsAndConstraints(parseClass, parseClassConfig); + const { + create: isCreateEnabled = true, + update: isUpdateEnabled = true + } = (0, _parseGraphQLUtils.getParseClassMutationConfig)(parseClassConfig); + const classGraphQLCreateTypeName = `Create${graphQLClassName}FieldsInput`; + let classGraphQLCreateType = new _graphql.GraphQLInputObjectType({ + name: classGraphQLCreateTypeName, + description: `The ${classGraphQLCreateTypeName} input type is used in operations that involve creation of objects in the ${graphQLClassName} class.`, + fields: () => classCreateFields.reduce((fields, field) => { + const type = (0, _inputType.transformInputTypeToGraphQL)(parseClass.fields[field].type, parseClass.fields[field].targetClass, parseGraphQLSchema.parseClassTypes); + + if (type) { + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + type + } + }); + } else { + return fields; + } + }, { + ACL: { + type: defaultGraphQLTypes.ACL_INPUT + } + }) + }); + classGraphQLCreateType = parseGraphQLSchema.addGraphQLType(classGraphQLCreateType); + const classGraphQLUpdateTypeName = `Update${graphQLClassName}FieldsInput`; + let classGraphQLUpdateType = new _graphql.GraphQLInputObjectType({ + name: classGraphQLUpdateTypeName, + description: `The ${classGraphQLUpdateTypeName} input type is used in operations that involve creation of objects in the ${graphQLClassName} class.`, + fields: () => classUpdateFields.reduce((fields, field) => { + const type = (0, _inputType.transformInputTypeToGraphQL)(parseClass.fields[field].type, parseClass.fields[field].targetClass, parseGraphQLSchema.parseClassTypes); + + if (type) { + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + type + } + }); + } else { + return fields; + } + }, { + ACL: { + type: defaultGraphQLTypes.ACL_INPUT + } + }) + }); + classGraphQLUpdateType = parseGraphQLSchema.addGraphQLType(classGraphQLUpdateType); + const classGraphQLPointerTypeName = `${graphQLClassName}PointerInput`; + let classGraphQLPointerType = new _graphql.GraphQLInputObjectType({ + name: classGraphQLPointerTypeName, + description: `Allow to link OR add and link an object of the ${graphQLClassName} class.`, + fields: () => { + const fields = { + link: { + description: `Link an existing object from ${graphQLClassName} class.`, + type: _graphql.GraphQLID + } + }; + + if (isCreateEnabled) { + fields['createAndLink'] = { + description: `Create and link an object from ${graphQLClassName} class.`, + type: classGraphQLCreateType + }; + } + + return fields; + } + }); + classGraphQLPointerType = parseGraphQLSchema.addGraphQLType(classGraphQLPointerType) || defaultGraphQLTypes.OBJECT; + const classGraphQLRelationTypeName = `${graphQLClassName}RelationInput`; + let classGraphQLRelationType = new _graphql.GraphQLInputObjectType({ + name: classGraphQLRelationTypeName, + description: `Allow to add, remove, createAndAdd objects of the ${graphQLClassName} class into a relation field.`, + fields: () => { + const fields = { + add: { + description: `Add an existing object from the ${graphQLClassName} class into the relation.`, + type: new _graphql.GraphQLList(defaultGraphQLTypes.OBJECT_ID) + }, + remove: { + description: `Remove an existing object from the ${graphQLClassName} class out of the relation.`, + type: new _graphql.GraphQLList(defaultGraphQLTypes.OBJECT_ID) + } + }; + + if (isCreateEnabled) { + fields['createAndAdd'] = { + description: `Create and add an object of the ${graphQLClassName} class into the relation.`, + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(classGraphQLCreateType)) + }; + } + + return fields; + } + }); + classGraphQLRelationType = parseGraphQLSchema.addGraphQLType(classGraphQLRelationType) || defaultGraphQLTypes.OBJECT; + const classGraphQLConstraintTypeName = `${graphQLClassName}PointerWhereInput`; + let classGraphQLConstraintType = new _graphql.GraphQLInputObjectType({ + name: classGraphQLConstraintTypeName, + description: `The ${classGraphQLConstraintTypeName} input type is used in operations that involve filtering objects by a pointer field to ${graphQLClassName} class.`, + fields: { + equalTo: defaultGraphQLTypes.equalTo(_graphql.GraphQLID), + notEqualTo: defaultGraphQLTypes.notEqualTo(_graphql.GraphQLID), + in: defaultGraphQLTypes.inOp(defaultGraphQLTypes.OBJECT_ID), + notIn: defaultGraphQLTypes.notIn(defaultGraphQLTypes.OBJECT_ID), + exists: defaultGraphQLTypes.exists, + inQueryKey: defaultGraphQLTypes.inQueryKey, + notInQueryKey: defaultGraphQLTypes.notInQueryKey, + inQuery: { + description: 'This is the inQuery operator to specify a constraint to select the objects where a field equals to any of the ids in the result of a different query.', + type: defaultGraphQLTypes.SUBQUERY_INPUT + }, + notInQuery: { + description: 'This is the notInQuery operator to specify a constraint to select the objects where a field do not equal to any of the ids in the result of a different query.', + type: defaultGraphQLTypes.SUBQUERY_INPUT + } + } + }); + classGraphQLConstraintType = parseGraphQLSchema.addGraphQLType(classGraphQLConstraintType); + const classGraphQLConstraintsTypeName = `${graphQLClassName}WhereInput`; + let classGraphQLConstraintsType = new _graphql.GraphQLInputObjectType({ + name: classGraphQLConstraintsTypeName, + description: `The ${classGraphQLConstraintsTypeName} input type is used in operations that involve filtering objects of ${graphQLClassName} class.`, + fields: () => _objectSpread({}, classConstraintFields.reduce((fields, field) => { + if (['OR', 'AND', 'NOR'].includes(field)) { + parseGraphQLSchema.log.warn(`Field ${field} could not be added to the auto schema ${classGraphQLConstraintsTypeName} because it collided with an existing one.`); + return fields; + } + + const parseField = field === 'id' ? 'objectId' : field; + const type = (0, _constraintType.transformConstraintTypeToGraphQL)(parseClass.fields[parseField].type, parseClass.fields[parseField].targetClass, parseGraphQLSchema.parseClassTypes); + + if (type) { + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + type + } + }); + } else { + return fields; + } + }, {}), { + OR: { + description: 'This is the OR operator to compound constraints.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(classGraphQLConstraintsType)) + }, + AND: { + description: 'This is the AND operator to compound constraints.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(classGraphQLConstraintsType)) + }, + NOR: { + description: 'This is the NOR operator to compound constraints.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(classGraphQLConstraintsType)) + } + }) + }); + classGraphQLConstraintsType = parseGraphQLSchema.addGraphQLType(classGraphQLConstraintsType) || defaultGraphQLTypes.OBJECT; + const classGraphQLOrderTypeName = `${graphQLClassName}Order`; + let classGraphQLOrderType = new _graphql.GraphQLEnumType({ + name: classGraphQLOrderTypeName, + description: `The ${classGraphQLOrderTypeName} input type is used when sorting objects of the ${graphQLClassName} class.`, + values: classSortFields.reduce((sortFields, fieldConfig) => { + const { + field, + asc, + desc + } = fieldConfig; + + const updatedSortFields = _objectSpread({}, sortFields); + + if (asc) { + updatedSortFields[`${field}_ASC`] = { + value: field + }; + } + + if (desc) { + updatedSortFields[`${field}_DESC`] = { + value: `-${field}` + }; + } + + return updatedSortFields; + }, {}) + }); + classGraphQLOrderType = parseGraphQLSchema.addGraphQLType(classGraphQLOrderType); + const classGraphQLFindArgs = { + where: { + description: 'These are the conditions that the objects need to match in order to be found.', + type: classGraphQLConstraintsType + }, + order: { + description: 'The fields to be used when sorting the data fetched.', + type: classGraphQLOrderType ? new _graphql.GraphQLList(new _graphql.GraphQLNonNull(classGraphQLOrderType)) : _graphql.GraphQLString + }, + skip: defaultGraphQLTypes.SKIP_ATT, + limit: defaultGraphQLTypes.LIMIT_ATT, + options: defaultGraphQLTypes.READ_OPTIONS_ATT + }; + const classGraphQLOutputTypeName = `${graphQLClassName}`; + + const outputFields = () => { + return classOutputFields.reduce((fields, field) => { + const type = (0, _outputType.transformOutputTypeToGraphQL)(parseClass.fields[field].type, parseClass.fields[field].targetClass, parseGraphQLSchema.parseClassTypes); + + if (parseClass.fields[field].type === 'Relation') { + const targetParseClassTypes = parseGraphQLSchema.parseClassTypes[parseClass.fields[field].targetClass]; + const args = targetParseClassTypes ? targetParseClassTypes.classGraphQLFindArgs : undefined; + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + args, + type, + + async resolve(source, args, context, queryInfo) { + try { + const { + where, + order, + skip, + limit, + options + } = args; + const { + readPreference, + includeReadPreference, + subqueryReadPreference + } = options || {}; + const { + config, + auth, + info + } = context; + const selectedFields = (0, _graphqlListFields.default)(queryInfo); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields.filter(field => field.includes('.')).map(field => field.slice(field.indexOf('.') + 1))); + return await objectsQueries.findObjects(source[field].className, _objectSpread({ + $relatedTo: { + object: { + __type: 'Pointer', + className: className, + objectId: source.objectId + }, + key: field + } + }, where || {}), order, skip, limit, keys, include, false, readPreference, includeReadPreference, subqueryReadPreference, config, auth, info, selectedFields.map(field => field.split('.', 1)[0]), parseClass.fields); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + } + }); + } else if (parseClass.fields[field].type === 'Polygon') { + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + type, + + async resolve(source) { + if (source[field] && source[field].coordinates) { + return source[field].coordinates.map(coordinate => ({ + latitude: coordinate[0], + longitude: coordinate[1] + })); + } else { + return null; + } + } + + } + }); + } else if (parseClass.fields[field].type === 'Array') { + return _objectSpread({}, fields, { + [field]: { + description: `Use Inline Fragment on Array to get results: https://graphql.org/learn/queries/#inline-fragments`, + type, + + async resolve(source) { + if (!source[field]) return null; + return source[field].map(async elem => { + if (elem.className && elem.objectId && elem.__type === 'Object') { + return elem; + } else { + return { + value: elem + }; + } + }); + } + + } + }); + } else if (type) { + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + type + } + }); + } else { + return fields; + } + }, defaultGraphQLTypes.PARSE_OBJECT_FIELDS); + }; + + let classGraphQLOutputType = new _graphql.GraphQLObjectType({ + name: classGraphQLOutputTypeName, + description: `The ${classGraphQLOutputTypeName} object type is used in operations that involve outputting objects of ${graphQLClassName} class.`, + interfaces: [defaultGraphQLTypes.PARSE_OBJECT], + fields: outputFields + }); + classGraphQLOutputType = parseGraphQLSchema.addGraphQLType(classGraphQLOutputType); + const classGraphQLFindResultTypeName = `${graphQLClassName}FindResult`; + let classGraphQLFindResultType = new _graphql.GraphQLObjectType({ + name: classGraphQLFindResultTypeName, + description: `The ${classGraphQLFindResultTypeName} object type is used in the ${graphQLClassName} find query to return the data of the matched objects.`, + fields: { + results: { + description: 'This is the objects returned by the query', + type: new _graphql.GraphQLNonNull(new _graphql.GraphQLList(new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT))) + }, + count: defaultGraphQLTypes.COUNT_ATT + } + }); + classGraphQLFindResultType = parseGraphQLSchema.addGraphQLType(classGraphQLFindResultType); + parseGraphQLSchema.parseClassTypes[className] = { + classGraphQLPointerType, + classGraphQLRelationType, + classGraphQLCreateType, + classGraphQLUpdateType, + classGraphQLConstraintType, + classGraphQLConstraintsType, + classGraphQLFindArgs, + classGraphQLOutputType, + classGraphQLFindResultType, + config: { + parseClassConfig, + isCreateEnabled, + isUpdateEnabled + } + }; + + if (className === '_User') { + const viewerType = new _graphql.GraphQLObjectType({ + name: 'Viewer', + description: `The Viewer object type is used in operations that involve outputting the current user data.`, + interfaces: [defaultGraphQLTypes.PARSE_OBJECT], + fields: () => _objectSpread({}, outputFields(), { + sessionToken: defaultGraphQLTypes.SESSION_TOKEN_ATT + }) + }); + parseGraphQLSchema.viewerType = viewerType; + parseGraphQLSchema.addGraphQLType(viewerType, true, true); + const userSignUpInputTypeName = 'SignUpFieldsInput'; + const userSignUpInputType = new _graphql.GraphQLInputObjectType({ + name: userSignUpInputTypeName, + description: `The ${userSignUpInputTypeName} input type is used in operations that involve inputting objects of ${graphQLClassName} class when signing up.`, + fields: () => classCreateFields.reduce((fields, field) => { + const type = (0, _inputType.transformInputTypeToGraphQL)(parseClass.fields[field].type, parseClass.fields[field].targetClass, parseGraphQLSchema.parseClassTypes); + + if (type) { + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + type: field === 'username' || field === 'password' ? new _graphql.GraphQLNonNull(type) : type + } + }); + } else { + return fields; + } + }, {}) + }); + parseGraphQLSchema.addGraphQLType(userSignUpInputType, true, true); + const userLogInInputTypeName = 'LogInFieldsInput'; + const userLogInInputType = new _graphql.GraphQLInputObjectType({ + name: userLogInInputTypeName, + description: `The ${userLogInInputTypeName} input type is used to login.`, + fields: { + username: { + description: 'This is the username used to log the user in.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + }, + password: { + description: 'This is the password used to log the user in.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + } + } + }); + parseGraphQLSchema.addGraphQLType(userLogInInputType, true, true); + parseGraphQLSchema.parseClassTypes[className].signUpInputType = userSignUpInputType; + parseGraphQLSchema.parseClassTypes[className].logInInputType = userLogInInputType; + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvcGFyc2VDbGFzc1R5cGVzLmpzIl0sIm5hbWVzIjpbImdldFBhcnNlQ2xhc3NUeXBlQ29uZmlnIiwicGFyc2VDbGFzc0NvbmZpZyIsInR5cGUiLCJnZXRJbnB1dEZpZWxkc0FuZENvbnN0cmFpbnRzIiwicGFyc2VDbGFzcyIsImNsYXNzRmllbGRzIiwiT2JqZWN0Iiwia2V5cyIsImZpZWxkcyIsImZpbHRlciIsImZpZWxkIiwiY29uY2F0IiwiaW5wdXRGaWVsZHMiLCJhbGxvd2VkSW5wdXRGaWVsZHMiLCJvdXRwdXRGaWVsZHMiLCJhbGxvd2VkT3V0cHV0RmllbGRzIiwiY29uc3RyYWludEZpZWxkcyIsImFsbG93ZWRDb25zdHJhaW50RmllbGRzIiwic29ydEZpZWxkcyIsImFsbG93ZWRTb3J0RmllbGRzIiwiY2xhc3NPdXRwdXRGaWVsZHMiLCJjbGFzc0NyZWF0ZUZpZWxkcyIsImNsYXNzVXBkYXRlRmllbGRzIiwiY2xhc3NDb25zdHJhaW50RmllbGRzIiwiY2xhc3NTb3J0RmllbGRzIiwiY2xhc3NDdXN0b21GaWVsZHMiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiUEFSU0VfT0JKRUNUX0ZJRUxEUyIsImluY2x1ZGVzIiwiY3JlYXRlIiwidXBkYXRlIiwiY2xhc3NOYW1lIiwib3V0cHV0RmllbGQiLCJsZW5ndGgiLCJwdXNoIiwiYXNjIiwiZGVzYyIsIm1hcCIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJncmFwaFFMQ2xhc3NOYW1lIiwiaXNDcmVhdGVFbmFibGVkIiwiaXNVcGRhdGVFbmFibGVkIiwiY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZU5hbWUiLCJjbGFzc0dyYXBoUUxDcmVhdGVUeXBlIiwiR3JhcGhRTElucHV0T2JqZWN0VHlwZSIsIm5hbWUiLCJkZXNjcmlwdGlvbiIsInJlZHVjZSIsInRhcmdldENsYXNzIiwicGFyc2VDbGFzc1R5cGVzIiwiQUNMIiwiQUNMX0lOUFVUIiwiYWRkR3JhcGhRTFR5cGUiLCJjbGFzc0dyYXBoUUxVcGRhdGVUeXBlTmFtZSIsImNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUiLCJjbGFzc0dyYXBoUUxQb2ludGVyVHlwZU5hbWUiLCJjbGFzc0dyYXBoUUxQb2ludGVyVHlwZSIsImxpbmsiLCJHcmFwaFFMSUQiLCJPQkpFQ1QiLCJjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGVOYW1lIiwiY2xhc3NHcmFwaFFMUmVsYXRpb25UeXBlIiwiYWRkIiwiR3JhcGhRTExpc3QiLCJPQkpFQ1RfSUQiLCJyZW1vdmUiLCJHcmFwaFFMTm9uTnVsbCIsImNsYXNzR3JhcGhRTENvbnN0cmFpbnRUeXBlTmFtZSIsImNsYXNzR3JhcGhRTENvbnN0cmFpbnRUeXBlIiwiZXF1YWxUbyIsIm5vdEVxdWFsVG8iLCJpbiIsImluT3AiLCJub3RJbiIsImV4aXN0cyIsImluUXVlcnlLZXkiLCJub3RJblF1ZXJ5S2V5IiwiaW5RdWVyeSIsIlNVQlFVRVJZX0lOUFVUIiwibm90SW5RdWVyeSIsImNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZU5hbWUiLCJjbGFzc0dyYXBoUUxDb25zdHJhaW50c1R5cGUiLCJsb2ciLCJ3YXJuIiwicGFyc2VGaWVsZCIsIk9SIiwiQU5EIiwiTk9SIiwiY2xhc3NHcmFwaFFMT3JkZXJUeXBlTmFtZSIsImNsYXNzR3JhcGhRTE9yZGVyVHlwZSIsIkdyYXBoUUxFbnVtVHlwZSIsInZhbHVlcyIsImZpZWxkQ29uZmlnIiwidXBkYXRlZFNvcnRGaWVsZHMiLCJ2YWx1ZSIsImNsYXNzR3JhcGhRTEZpbmRBcmdzIiwid2hlcmUiLCJvcmRlciIsIkdyYXBoUUxTdHJpbmciLCJza2lwIiwiU0tJUF9BVFQiLCJsaW1pdCIsIkxJTUlUX0FUVCIsIm9wdGlvbnMiLCJSRUFEX09QVElPTlNfQVRUIiwiY2xhc3NHcmFwaFFMT3V0cHV0VHlwZU5hbWUiLCJ0YXJnZXRQYXJzZUNsYXNzVHlwZXMiLCJhcmdzIiwidW5kZWZpbmVkIiwicmVzb2x2ZSIsInNvdXJjZSIsImNvbnRleHQiLCJxdWVyeUluZm8iLCJyZWFkUHJlZmVyZW5jZSIsImluY2x1ZGVSZWFkUHJlZmVyZW5jZSIsInN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UiLCJjb25maWciLCJhdXRoIiwiaW5mbyIsInNlbGVjdGVkRmllbGRzIiwiaW5jbHVkZSIsInNsaWNlIiwiaW5kZXhPZiIsIm9iamVjdHNRdWVyaWVzIiwiZmluZE9iamVjdHMiLCIkcmVsYXRlZFRvIiwib2JqZWN0IiwiX190eXBlIiwib2JqZWN0SWQiLCJrZXkiLCJzcGxpdCIsImUiLCJoYW5kbGVFcnJvciIsImNvb3JkaW5hdGVzIiwiY29vcmRpbmF0ZSIsImxhdGl0dWRlIiwibG9uZ2l0dWRlIiwiZWxlbSIsImNsYXNzR3JhcGhRTE91dHB1dFR5cGUiLCJHcmFwaFFMT2JqZWN0VHlwZSIsImludGVyZmFjZXMiLCJQQVJTRV9PQkpFQ1QiLCJjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZU5hbWUiLCJjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZSIsInJlc3VsdHMiLCJjb3VudCIsIkNPVU5UX0FUVCIsInZpZXdlclR5cGUiLCJzZXNzaW9uVG9rZW4iLCJTRVNTSU9OX1RPS0VOX0FUVCIsInVzZXJTaWduVXBJbnB1dFR5cGVOYW1lIiwidXNlclNpZ25VcElucHV0VHlwZSIsInVzZXJMb2dJbklucHV0VHlwZU5hbWUiLCJ1c2VyTG9nSW5JbnB1dFR5cGUiLCJ1c2VybmFtZSIsInBhc3N3b3JkIiwic2lnblVwSW5wdXRUeXBlIiwibG9nSW5JbnB1dFR5cGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFBQTs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFLQSxNQUFNQSx1QkFBdUIsR0FBRyxVQUM5QkMsZ0JBRDhCLEVBRTlCO0FBQ0EsU0FBUUEsZ0JBQWdCLElBQUlBLGdCQUFnQixDQUFDQyxJQUF0QyxJQUErQyxFQUF0RDtBQUNELENBSkQ7O0FBTUEsTUFBTUMsNEJBQTRCLEdBQUcs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aFFMU3RyaW5nLFxuICBHcmFwaFFMTGlzdCxcbiAgR3JhcGhRTElucHV0T2JqZWN0VHlwZSxcbiAgR3JhcGhRTE5vbk51bGwsXG4gIEdyYXBoUUxFbnVtVHlwZSxcbn0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgZ2V0RmllbGROYW1lcyBmcm9tICdncmFwaHFsLWxpc3QtZmllbGRzJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMVHlwZXMgZnJvbSAnLi9kZWZhdWx0R3JhcGhRTFR5cGVzJztcbmltcG9ydCAqIGFzIG9iamVjdHNRdWVyaWVzIGZyb20gJy4uL2hlbHBlcnMvb2JqZWN0c1F1ZXJpZXMnO1xuaW1wb3J0IHsgUGFyc2VHcmFwaFFMQ2xhc3NDb25maWcgfSBmcm9tICcuLi8uLi9Db250cm9sbGVycy9QYXJzZUdyYXBoUUxDb250cm9sbGVyJztcbmltcG9ydCB7IHRyYW5zZm9ybUNsYXNzTmFtZVRvR3JhcGhRTCB9IGZyb20gJy4uL3RyYW5zZm9ybWVycy9jbGFzc05hbWUnO1xuaW1wb3J0IHsgdHJhbnNmb3JtSW5wdXRUeXBlVG9HcmFwaFFMIH0gZnJvbSAnLi4vdHJhbnNmb3JtZXJzL2lucHV0VHlwZSc7XG5pbXBvcnQgeyB0cmFuc2Zvcm1PdXRwdXRUeXBlVG9HcmFwaFFMIH0gZnJvbSAnLi4vdHJhbnNmb3JtZXJzL291dHB1dFR5cGUnO1xuaW1wb3J0IHsgdHJhbnNmb3JtQ29uc3RyYWludFR5cGVUb0dyYXBoUUwgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvY29uc3RyYWludFR5cGUnO1xuaW1wb3J0IHtcbiAgZXh0cmFjdEtleXNBbmRJbmNsdWRlLFxuICBnZXRQYXJzZUNsYXNzTXV0YXRpb25Db25maWcsXG59IGZyb20gJy4uL3BhcnNlR3JhcGhRTFV0aWxzJztcblxuY29uc3QgZ2V0UGFyc2VDbGFzc1R5cGVDb25maWcgPSBmdW5jdGlvbihcbiAgcGFyc2VDbGFzc0NvbmZpZzogP1BhcnNlR3JhcGhRTENsYXNzQ29uZmlnXG4pIHtcbiAgcmV0dXJuIChwYXJzZUNsYXNzQ29uZmlnICYmIHBhcnNlQ2xhc3NDb25maWcudHlwZSkgfHwge307XG59O1xuXG5jb25zdCBnZXRJbnB1dEZpZWxkc0FuZENvbnN0cmFpbnRzID0gZnVuY3Rpb24oXG4gIHBhcnNlQ2xhc3MsXG4gIHBhcnNlQ2xhc3NDb25maWc6ID9QYXJzZUdyYXBoUUxDbGFzc0NvbmZpZ1xuKSB7XG4gIGNvbnN0IGNsYXNzRmllbGRzID0gT2JqZWN0LmtleXMocGFyc2VDbGFzcy5maWVsZHMpXG4gICAgLmZpbHRlcihmaWVsZCA9PiBmaWVsZCAhPT0gJ29iamVjdElkJylcbiAgICAuY29uY2F0KCdpZCcpO1xuICBjb25zdCB7XG4gICAgaW5wdXRGaWVsZHM6IGFsbG93ZWRJbnB1dEZpZWxkcyxcbiAgICBvdXRwdXRGaWVsZHM6IGFsbG93ZWRPdXRwdXRGaWVsZHMsXG4gICAgY29uc3RyYWludEZpZWxkczogYWxsb3dlZENvbnN0cmFpbnRGaWVsZHMsXG4gICAgc29ydEZpZWxkczogYWxsb3dlZFNvcnRGaWVsZHMsXG4gIH0gPSBnZXRQYXJzZUNsYXNzVHlwZUNvbmZpZyhwYXJzZUNsYXNzQ29uZmlnKTtcblxuICBsZXQgY2xhc3NPdXRwdXRGaWVsZHM7XG4gIGxldCBjbGFzc0NyZWF0ZUZpZWxkcztcbiAgbGV0IGNsYXNzVXBkYXRlRmllbGRzO1xuICBsZXQgY2xhc3NDb25zdHJhaW50RmllbGRzO1xuICBsZXQgY2xhc3NTb3J0RmllbGRzO1xuXG4gIC8vIEFsbCBhbGxvd2VkIGN1c3RvbXMgZmllbGRzXG4gIGNvbnN0IGNsYXNzQ3VzdG9tRmllbGRzID0gY2xhc3NGaWVsZHMuZmlsdGVyKGZpZWxkID0+IHtcbiAgICByZXR1cm4gIU9iamVjdC5rZXlzKGRlZmF1bHRHcmFwaFFMVHlwZXMuUEFSU0VfT0JKRUNUX0ZJRUxEUykuaW5jbHVkZXMoXG4gICAgICBmaWVsZFxuICAgICk7XG4gIH0pO1xuXG4gIGlmIChhbGxvd2VkSW5wdXRGaWVsZHMgJiYgYWxsb3dlZElucHV0RmllbGRzLmNyZWF0ZSkge1xuICAgIGNsYXNzQ3JlYXRlRmllbGRzID0gY2xhc3NDdXN0b21GaWVsZHMuZmlsdGVyKGZpZWxkID0+IHtcbiAgICAgIHJldHVybiBhbGxvd2VkSW5wdXRGaWVsZHMuY3JlYXRlLmluY2x1ZGVzKGZpZWxkKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjbGFzc0NyZWF0ZUZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzO1xuICB9XG4gIGlmIChhbGxvd2VkSW5wdXRGaWVsZHMgJiYgYWxsb3dlZElucHV0RmllbGRzLnVwZGF0ZSkge1xuICAgIGNsYXNzVXBkYXRlRmllbGRzID0gY2xhc3NDdXN0b21GaWVsZHMuZmlsdGVyKGZpZWxkID0+IHtcbiAgICAgIHJldHVybiBhbGxvd2VkSW5wdXRGaWVsZHMudXBkYXRlLmluY2x1ZGVzKGZpZWxkKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjbGFzc1VwZGF0ZUZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzO1xuICB9XG5cbiAgaWYgKGFsbG93ZWRPdXRwdXRGaWVsZHMpIHtcbiAgICBjbGFzc091dHB1dEZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzLmZpbHRlcihmaWVsZCA9PiB7XG4gICAgICByZXR1cm4gYWxsb3dlZE91dHB1dEZpZWxkcy5pbmNsdWRlcyhmaWVsZCk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY2xhc3NPdXRwdXRGaWVsZHMgPSBjbGFzc0N1c3RvbUZpZWxkcztcbiAgfVxuICAvLyBGaWx0ZXJzIHRoZSBcInBhc3N3b3JkXCIgZmllbGQgZnJvbSBjbGFzcyBfVXNlclxuICBpZiAocGFyc2VDbGFzcy5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBjbGFzc091dHB1dEZpZWxkcyA9IGNsYXNzT3V0cHV0RmllbGRzLmZpbHRlcihcbiAgICAgIG91dHB1dEZpZWxkID0+IG91dHB1dEZpZWxkICE9PSAncGFzc3dvcmQnXG4gICAgKTtcbiAgfVxuXG4gIGlmIChhbGxvd2VkQ29uc3RyYWludEZpZWxkcykge1xuICAgIGNsYXNzQ29uc3RyYWludEZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzLmZpbHRlcihmaWVsZCA9PiB7XG4gICAgICByZXR1cm4gYWxsb3dlZENvbnN0cmFpbnRGaWVsZHMuaW5jbHVkZXMoZmllbGQpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNsYXNzQ29uc3RyYWludEZpZWxkcyA9IGNsYXNzRmllbGRzO1xuICB9XG5cbiAgaWYgKGFsbG93ZWRTb3J0RmllbGRzKSB7XG4gICAgY2xhc3NTb3J0RmllbGRzID0gYWxsb3dlZFNvcnRGaWVsZHM7XG4gICAgaWYgKCFjbGFzc1NvcnRGaWVsZHMubGVuZ3RoKSB7XG4gICAgICAvLyBtdXN0IGhhdmUgYXQgbGVhc3QgMSBvcmRlciBmaWVsZFxuICAgICAgLy8gb3RoZXJ3aXNlIHRoZSBGaW5kQXJncyBJbnB1dCBUeXBlIHdpbGwgdGhyb3cuXG4gICAgICBjbGFzc1NvcnRGaWVsZHMucHVzaCh7XG4gICAgICAgIGZpZWxkOiAnaWQnLFxuICAgICAgICBhc2M6IHRydWUsXG4gICAgICAgIGRlc2M6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY2xhc3NTb3J0RmllbGRzID0gY2xhc3NGaWVsZHMubWFwKGZpZWxkID0+IHtcbiAgICAgIHJldHVybiB7IGZpZWxkLCBhc2M6IHRydWUsIGRlc2M6IHRydWUgfTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY2xhc3NDcmVhdGVGaWVsZHMsXG4gICAgY2xhc3NVcGRhdGVGaWVsZHMsXG4gICAgY2xhc3NDb25zdHJhaW50RmllbGRzLFxuICAgIGNsYXNzT3V0cHV0RmllbGRzLFxuICAgIGNsYXNzU29ydEZpZWxkcyxcbiAgfTtcbn07XG5cbmNvbnN0IGxvYWQgPSAoXG4gIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgcGFyc2VDbGFzcyxcbiAgcGFyc2VDbGFzc0NvbmZpZzogP1BhcnNlR3JhcGhRTENsYXNzQ29uZmlnXG4pID0+IHtcbiAgY29uc3QgY2xhc3NOYW1lID0gcGFyc2VDbGFzcy5jbGFzc05hbWU7XG4gIGNvbnN0IGdyYXBoUUxDbGFzc05hbWUgPSB0cmFuc2Zvcm1DbGFzc05hbWVUb0dyYXBoUUwoY2xhc3NOYW1lKTtcbiAgY29uc3Qge1xuICAgIGNsYXNzQ3JlYXRlRmllbGRzLFxuICAgIGNsYXNzVXBkYXRlRmllbGRzLFxuICAgIGNsYXNzT3V0cHV0RmllbGRzLFxuICAgIGNsYXNzQ29uc3RyYWludEZpZWxkcyxcbiAgICBjbGFzc1NvcnRGaWVsZHMsXG4gIH0gPSBnZXRJbnB1dEZpZWxkc0FuZENvbnN0cmFpbnRzKHBhcnNlQ2xhc3MsIHBhcnNlQ2xhc3NDb25maWcpO1xuXG4gIGNvbnN0IHtcbiAgICBjcmVhdGU6IGlzQ3JlYXRlRW5hYmxlZCA9IHRydWUsXG4gICAgdXBkYXRlOiBpc1VwZGF0ZUVuYWJsZWQgPSB0cnVlLFxuICB9ID0gZ2V0UGFyc2VDbGFzc011dGF0aW9uQ29uZmlnKHBhcnNlQ2xhc3NDb25maWcpO1xuXG4gIGNvbnN0IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGVOYW1lID0gYENyZWF0ZSR7Z3JhcGhRTENsYXNzTmFtZX1GaWVsZHNJbnB1dGA7XG4gIGxldCBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgIG5hbWU6IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7Y2xhc3NHcmFwaFFMQ3JlYXRlVHlwZU5hbWV9IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBjcmVhdGlvbiBvZiBvYmplY3RzIGluIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgZmllbGRzOiAoKSA9PlxuICAgICAgY2xhc3NDcmVhdGVGaWVsZHMucmVkdWNlKFxuICAgICAgICAoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHR5cGUgPSB0cmFuc2Zvcm1JbnB1dFR5cGVUb0dyYXBoUUwoXG4gICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSxcbiAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcyxcbiAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICh0eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgICAgIFtmaWVsZF06IHtcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogYFRoaXMgaXMgdGhlIG9iamVjdCAke2ZpZWxkfS5gLFxuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmllbGRzO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIEFDTDogeyB0eXBlOiBkZWZhdWx0R3JhcGhRTFR5cGVzLkFDTF9JTlBVVCB9LFxuICAgICAgICB9XG4gICAgICApLFxuICB9KTtcbiAgY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlXG4gICk7XG5cbiAgY29uc3QgY2xhc3NHcmFwaFFMVXBkYXRlVHlwZU5hbWUgPSBgVXBkYXRlJHtncmFwaFFMQ2xhc3NOYW1lfUZpZWxkc0lucHV0YDtcbiAgbGV0IGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gICAgbmFtZTogY2xhc3NHcmFwaFFMVXBkYXRlVHlwZU5hbWUsXG4gICAgZGVzY3JpcHRpb246IGBUaGUgJHtjbGFzc0dyYXBoUUxVcGRhdGVUeXBlTmFtZX0gaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGNyZWF0aW9uIG9mIG9iamVjdHMgaW4gdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICBmaWVsZHM6ICgpID0+XG4gICAgICBjbGFzc1VwZGF0ZUZpZWxkcy5yZWR1Y2UoXG4gICAgICAgIChmaWVsZHMsIGZpZWxkKSA9PiB7XG4gICAgICAgICAgY29uc3QgdHlwZSA9IHRyYW5zZm9ybUlucHV0VHlwZVRvR3JhcGhRTChcbiAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50eXBlLFxuICAgICAgICAgICAgcGFyc2VDbGFzcy5maWVsZHNbZmllbGRdLnRhcmdldENsYXNzLFxuICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1xuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKHR5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIC4uLmZpZWxkcyxcbiAgICAgICAgICAgICAgW2ZpZWxkXToge1xuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgVGhpcyBpcyB0aGUgb2JqZWN0ICR7ZmllbGR9LmAsXG4gICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmaWVsZHM7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgQUNMOiB7IHR5cGU6IGRlZmF1bHRHcmFwaFFMVHlwZXMuQUNMX0lOUFVUIH0sXG4gICAgICAgIH1cbiAgICAgICksXG4gIH0pO1xuICBjbGFzc0dyYXBoUUxVcGRhdGVUeXBlID0gcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGVcbiAgKTtcblxuICBjb25zdCBjbGFzc0dyYXBoUUxQb2ludGVyVHlwZU5hbWUgPSBgJHtncmFwaFFMQ2xhc3NOYW1lfVBvaW50ZXJJbnB1dGA7XG4gIGxldCBjbGFzc0dyYXBoUUxQb2ludGVyVHlwZSA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgICBuYW1lOiBjbGFzc0dyYXBoUUxQb2ludGVyVHlwZU5hbWUsXG4gICAgZGVzY3JpcHRpb246IGBBbGxvdyB0byBsaW5rIE9SIGFkZCBhbmQgbGluayBhbiBvYmplY3Qgb2YgdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICBmaWVsZHM6ICgpID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkcyA9IHtcbiAgICAgICAgbGluazoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBgTGluayBhbiBleGlzdGluZyBvYmplY3QgZnJvbSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgICAgICAgdHlwZTogR3JhcGhRTElELFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIGlmIChpc0NyZWF0ZUVuYWJsZWQpIHtcbiAgICAgICAgZmllbGRzWydjcmVhdGVBbmRMaW5rJ10gPSB7XG4gICAgICAgICAgZGVzY3JpcHRpb246IGBDcmVhdGUgYW5kIGxpbmsgYW4gb2JqZWN0IGZyb20gJHtncmFwaFFMQ2xhc3NOYW1lfSBjbGFzcy5gLFxuICAgICAgICAgIHR5cGU6IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGUsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gZmllbGRzO1xuICAgIH0sXG4gIH0pO1xuICBjbGFzc0dyYXBoUUxQb2ludGVyVHlwZSA9XG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKGNsYXNzR3JhcGhRTFBvaW50ZXJUeXBlKSB8fFxuICAgIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuXG4gIGNvbnN0IGNsYXNzR3JhcGhRTFJlbGF0aW9uVHlwZU5hbWUgPSBgJHtncmFwaFFMQ2xhc3NOYW1lfVJlbGF0aW9uSW5wdXRgO1xuICBsZXQgY2xhc3NHcmFwaFFMUmVsYXRpb25UeXBlID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgIG5hbWU6IGNsYXNzR3JhcGhRTFJlbGF0aW9uVHlwZU5hbWUsXG4gICAgZGVzY3JpcHRpb246IGBBbGxvdyB0byBhZGQsIHJlbW92ZSwgY3JlYXRlQW5kQWRkIG9iamVjdHMgb2YgdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MgaW50byBhIHJlbGF0aW9uIGZpZWxkLmAsXG4gICAgZmllbGRzOiAoKSA9PiB7XG4gICAgICBjb25zdCBmaWVsZHMgPSB7XG4gICAgICAgIGFkZDoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBgQWRkIGFuIGV4aXN0aW5nIG9iamVjdCBmcm9tIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzIGludG8gdGhlIHJlbGF0aW9uLmAsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUX0lEKSxcbiAgICAgICAgfSxcbiAgICAgICAgcmVtb3ZlOiB7XG4gICAgICAgICAgZGVzY3JpcHRpb246IGBSZW1vdmUgYW4gZXhpc3Rpbmcgb2JqZWN0IGZyb20gdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3Mgb3V0IG9mIHRoZSByZWxhdGlvbi5gLFxuICAgICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVF9JRCksXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgICAgaWYgKGlzQ3JlYXRlRW5hYmxlZCkge1xuICAgICAgICBmaWVsZHNbJ2NyZWF0ZUFuZEFkZCddID0ge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBgQ3JlYXRlIGFuZCBhZGQgYW4gb2JqZWN0IG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzIGludG8gdGhlIHJlbGF0aW9uLmAsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChjbGFzc0dyYXBoUUxDcmVhdGVUeXBlKSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gZmllbGRzO1xuICAgIH0sXG4gIH0pO1xuICBjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGUgPVxuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGUpIHx8XG4gICAgZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1Q7XG5cbiAgY29uc3QgY2xhc3NHcmFwaFFMQ29uc3RyYWludFR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1Qb2ludGVyV2hlcmVJbnB1dGA7XG4gIGxldCBjbGFzc0dyYXBoUUxDb25zdHJhaW50VHlwZSA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgICBuYW1lOiBjbGFzc0dyYXBoUUxDb25zdHJhaW50VHlwZU5hbWUsXG4gICAgZGVzY3JpcHRpb246IGBUaGUgJHtjbGFzc0dyYXBoUUxDb25zdHJhaW50VHlwZU5hbWV9IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIHBvaW50ZXIgZmllbGQgdG8gJHtncmFwaFFMQ2xhc3NOYW1lfSBjbGFzcy5gLFxuICAgIGZpZWxkczoge1xuICAgICAgZXF1YWxUbzogZGVmYXVsdEdyYXBoUUxUeXBlcy5lcXVhbFRvKEdyYXBoUUxJRCksXG4gICAgICBub3RFcXVhbFRvOiBkZWZhdWx0R3JhcGhRTFR5cGVzLm5vdEVxdWFsVG8oR3JhcGhRTElEKSxcbiAgICAgIGluOiBkZWZhdWx0R3JhcGhRTFR5cGVzLmluT3AoZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1RfSUQpLFxuICAgICAgbm90SW46IGRlZmF1bHRHcmFwaFFMVHlwZXMubm90SW4oZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1RfSUQpLFxuICAgICAgZXhpc3RzOiBkZWZhdWx0R3JhcGhRTFR5cGVzLmV4aXN0cyxcbiAgICAgIGluUXVlcnlLZXk6IGRlZmF1bHRHcmFwaFFMVHlwZXMuaW5RdWVyeUtleSxcbiAgICAgIG5vdEluUXVlcnlLZXk6IGRlZmF1bHRHcmFwaFFMVHlwZXMubm90SW5RdWVyeUtleSxcbiAgICAgIGluUXVlcnk6IHtcbiAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgJ1RoaXMgaXMgdGhlIGluUXVlcnkgb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIGEgZmllbGQgZXF1YWxzIHRvIGFueSBvZiB0aGUgaWRzIGluIHRoZSByZXN1bHQgb2YgYSBkaWZmZXJlbnQgcXVlcnkuJyxcbiAgICAgICAgdHlwZTogZGVmYXVsdEdyYXBoUUxUeXBlcy5TVUJRVUVSWV9JTlBVVCxcbiAgICAgIH0sXG4gICAgICBub3RJblF1ZXJ5OiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICdUaGlzIGlzIHRoZSBub3RJblF1ZXJ5IG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSBhIGZpZWxkIGRvIG5vdCBlcXVhbCB0byBhbnkgb2YgdGhlIGlkcyBpbiB0aGUgcmVzdWx0IG9mIGEgZGlmZmVyZW50IHF1ZXJ5LicsXG4gICAgICAgIHR5cGU6IGRlZmF1bHRHcmFwaFFMVHlwZXMuU1VCUVVFUllfSU5QVVQsXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuICBjbGFzc0dyYXBoUUxDb25zdHJhaW50VHlwZSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICBjbGFzc0dyYXBoUUxDb25zdHJhaW50VHlwZVxuICApO1xuXG4gIGNvbnN0IGNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZU5hbWUgPSBgJHtncmFwaFFMQ2xhc3NOYW1lfVdoZXJlSW5wdXRgO1xuICBsZXQgY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgIG5hbWU6IGNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZU5hbWUsXG4gICAgZGVzY3JpcHRpb246IGBUaGUgJHtjbGFzc0dyYXBoUUxDb25zdHJhaW50c1R5cGVOYW1lfSBpbnB1dCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgZmlsdGVyaW5nIG9iamVjdHMgb2YgJHtncmFwaFFMQ2xhc3NOYW1lfSBjbGFzcy5gLFxuICAgIGZpZWxkczogKCkgPT4gKHtcbiAgICAgIC4uLmNsYXNzQ29uc3RyYWludEZpZWxkcy5yZWR1Y2UoKGZpZWxkcywgZmllbGQpID0+IHtcbiAgICAgICAgaWYgKFsnT1InLCAnQU5EJywgJ05PUiddLmluY2x1ZGVzKGZpZWxkKSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5sb2cud2FybihcbiAgICAgICAgICAgIGBGaWVsZCAke2ZpZWxkfSBjb3VsZCBub3QgYmUgYWRkZWQgdG8gdGhlIGF1dG8gc2NoZW1hICR7Y2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlTmFtZX0gYmVjYXVzZSBpdCBjb2xsaWRlZCB3aXRoIGFuIGV4aXN0aW5nIG9uZS5gXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gZmllbGRzO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhcnNlRmllbGQgPSBmaWVsZCA9PT0gJ2lkJyA/ICdvYmplY3RJZCcgOiBmaWVsZDtcbiAgICAgICAgY29uc3QgdHlwZSA9IHRyYW5zZm9ybUNvbnN0cmFpbnRUeXBlVG9HcmFwaFFMKFxuICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW3BhcnNlRmllbGRdLnR5cGUsXG4gICAgICAgICAgcGFyc2VDbGFzcy5maWVsZHNbcGFyc2VGaWVsZF0udGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1xuICAgICAgICApO1xuICAgICAgICBpZiAodHlwZSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgICBbZmllbGRdOiB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgVGhpcyBpcyB0aGUgb2JqZWN0ICR7ZmllbGR9LmAsXG4gICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGZpZWxkcztcbiAgICAgICAgfVxuICAgICAgfSwge30pLFxuICAgICAgT1I6IHtcbiAgICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBPUiBvcGVyYXRvciB0byBjb21wb3VuZCBjb25zdHJhaW50cy4nLFxuICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKGNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZSkpLFxuICAgICAgfSxcbiAgICAgIEFORDoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIEFORCBvcGVyYXRvciB0byBjb21wb3VuZCBjb25zdHJhaW50cy4nLFxuICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKGNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZSkpLFxuICAgICAgfSxcbiAgICAgIE5PUjoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIE5PUiBvcGVyYXRvciB0byBjb21wb3VuZCBjb25zdHJhaW50cy4nLFxuICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKGNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZSkpLFxuICAgICAgfSxcbiAgICB9KSxcbiAgfSk7XG4gIGNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZSA9XG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKGNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZSkgfHxcbiAgICBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcblxuICBjb25zdCBjbGFzc0dyYXBoUUxPcmRlclR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1PcmRlcmA7XG4gIGxldCBjbGFzc0dyYXBoUUxPcmRlclR5cGUgPSBuZXcgR3JhcGhRTEVudW1UeXBlKHtcbiAgICBuYW1lOiBjbGFzc0dyYXBoUUxPcmRlclR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7Y2xhc3NHcmFwaFFMT3JkZXJUeXBlTmFtZX0gaW5wdXQgdHlwZSBpcyB1c2VkIHdoZW4gc29ydGluZyBvYmplY3RzIG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgdmFsdWVzOiBjbGFzc1NvcnRGaWVsZHMucmVkdWNlKChzb3J0RmllbGRzLCBmaWVsZENvbmZpZykgPT4ge1xuICAgICAgY29uc3QgeyBmaWVsZCwgYXNjLCBkZXNjIH0gPSBmaWVsZENvbmZpZztcbiAgICAgIGNvbnN0IHVwZGF0ZWRTb3J0RmllbGRzID0ge1xuICAgICAgICAuLi5zb3J0RmllbGRzLFxuICAgICAgfTtcbiAgICAgIGlmIChhc2MpIHtcbiAgICAgICAgdXBkYXRlZFNvcnRGaWVsZHNbYCR7ZmllbGR9X0FTQ2BdID0geyB2YWx1ZTogZmllbGQgfTtcbiAgICAgIH1cbiAgICAgIGlmIChkZXNjKSB7XG4gICAgICAgIHVwZGF0ZWRTb3J0RmllbGRzW2Ake2ZpZWxkfV9ERVNDYF0gPSB7IHZhbHVlOiBgLSR7ZmllbGR9YCB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHVwZGF0ZWRTb3J0RmllbGRzO1xuICAgIH0sIHt9KSxcbiAgfSk7XG4gIGNsYXNzR3JhcGhRTE9yZGVyVHlwZSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICBjbGFzc0dyYXBoUUxPcmRlclR5cGVcbiAgKTtcblxuICBjb25zdCBjbGFzc0dyYXBoUUxGaW5kQXJncyA9IHtcbiAgICB3aGVyZToge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGVzZSBhcmUgdGhlIGNvbmRpdGlvbnMgdGhhdCB0aGUgb2JqZWN0cyBuZWVkIHRvIG1hdGNoIGluIG9yZGVyIHRvIGJlIGZvdW5kLicsXG4gICAgICB0eXBlOiBjbGFzc0dyYXBoUUxDb25zdHJhaW50c1R5cGUsXG4gICAgfSxcbiAgICBvcmRlcjoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgZmllbGRzIHRvIGJlIHVzZWQgd2hlbiBzb3J0aW5nIHRoZSBkYXRhIGZldGNoZWQuJyxcbiAgICAgIHR5cGU6IGNsYXNzR3JhcGhRTE9yZGVyVHlwZVxuICAgICAgICA/IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoY2xhc3NHcmFwaFFMT3JkZXJUeXBlKSlcbiAgICAgICAgOiBHcmFwaFFMU3RyaW5nLFxuICAgIH0sXG4gICAgc2tpcDogZGVmYXVsdEdyYXBoUUxUeXBlcy5TS0lQX0FUVCxcbiAgICBsaW1pdDogZGVmYXVsdEdyYXBoUUxUeXBlcy5MSU1JVF9BVFQsXG4gICAgb3B0aW9uczogZGVmYXVsdEdyYXBoUUxUeXBlcy5SRUFEX09QVElPTlNfQVRULFxuICB9O1xuXG4gIGNvbnN0IGNsYXNzR3JhcGhRTE91dHB1dFR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1gO1xuICBjb25zdCBvdXRwdXRGaWVsZHMgPSAoKSA9PiB7XG4gICAgcmV0dXJuIGNsYXNzT3V0cHV0RmllbGRzLnJlZHVjZSgoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgY29uc3QgdHlwZSA9IHRyYW5zZm9ybU91dHB1dFR5cGVUb0dyYXBoUUwoXG4gICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50eXBlLFxuICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udGFyZ2V0Q2xhc3MsXG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNcbiAgICAgICk7XG4gICAgICBpZiAocGFyc2VDbGFzcy5maWVsZHNbZmllbGRdLnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgY29uc3QgdGFyZ2V0UGFyc2VDbGFzc1R5cGVzID1cbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW1xuICAgICAgICAgICAgcGFyc2VDbGFzcy5maWVsZHNbZmllbGRdLnRhcmdldENsYXNzXG4gICAgICAgICAgXTtcbiAgICAgICAgY29uc3QgYXJncyA9IHRhcmdldFBhcnNlQ2xhc3NUeXBlc1xuICAgICAgICAgID8gdGFyZ2V0UGFyc2VDbGFzc1R5cGVzLmNsYXNzR3JhcGhRTEZpbmRBcmdzXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4uZmllbGRzLFxuICAgICAgICAgIFtmaWVsZF06IHtcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgVGhpcyBpcyB0aGUgb2JqZWN0ICR7ZmllbGR9LmAsXG4gICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIGFzeW5jIHJlc29sdmUoc291cmNlLCBhcmdzLCBjb250ZXh0LCBxdWVyeUluZm8pIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCB7IHdoZXJlLCBvcmRlciwgc2tpcCwgbGltaXQsIG9wdGlvbnMgfSA9IGFyZ3M7XG4gICAgICAgICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICAgICAgICBpbmNsdWRlUmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICAgICAgICBzdWJxdWVyeVJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgICAgIH0gPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkRmllbGRzID0gZ2V0RmllbGROYW1lcyhxdWVyeUluZm8pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgeyBrZXlzLCBpbmNsdWRlIH0gPSBleHRyYWN0S2V5c0FuZEluY2x1ZGUoXG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZEZpZWxkc1xuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGZpZWxkID0+IGZpZWxkLmluY2x1ZGVzKCcuJykpXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoZmllbGQgPT4gZmllbGQuc2xpY2UoZmllbGQuaW5kZXhPZignLicpICsgMSkpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgb2JqZWN0c1F1ZXJpZXMuZmluZE9iamVjdHMoXG4gICAgICAgICAgICAgICAgICBzb3VyY2VbZmllbGRdLmNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgJHJlbGF0ZWRUbzoge1xuICAgICAgICAgICAgICAgICAgICAgIG9iamVjdDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdElkOiBzb3VyY2Uub2JqZWN0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICBrZXk6IGZpZWxkLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAuLi4od2hlcmUgfHwge30pLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIG9yZGVyLFxuICAgICAgICAgICAgICAgICAgc2tpcCxcbiAgICAgICAgICAgICAgICAgIGxpbWl0LFxuICAgICAgICAgICAgICAgICAga2V5cyxcbiAgICAgICAgICAgICAgICAgIGluY2x1ZGUsXG4gICAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgICAgICAgaW5jbHVkZVJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgICAgICAgc3VicXVlcnlSZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgICAgICBpbmZvLFxuICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRGaWVsZHMubWFwKGZpZWxkID0+IGZpZWxkLnNwbGl0KCcuJywgMSlbMF0pLFxuICAgICAgICAgICAgICAgICAgcGFyc2VDbGFzcy5maWVsZHNcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmhhbmRsZUVycm9yKGUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgW2ZpZWxkXToge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246IGBUaGlzIGlzIHRoZSBvYmplY3QgJHtmaWVsZH0uYCxcbiAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICBhc3luYyByZXNvbHZlKHNvdXJjZSkge1xuICAgICAgICAgICAgICBpZiAoc291cmNlW2ZpZWxkXSAmJiBzb3VyY2VbZmllbGRdLmNvb3JkaW5hdGVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNvdXJjZVtmaWVsZF0uY29vcmRpbmF0ZXMubWFwKGNvb3JkaW5hdGUgPT4gKHtcbiAgICAgICAgICAgICAgICAgIGxhdGl0dWRlOiBjb29yZGluYXRlWzBdLFxuICAgICAgICAgICAgICAgICAgbG9uZ2l0dWRlOiBjb29yZGluYXRlWzFdLFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ0FycmF5Jykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLmZpZWxkcyxcbiAgICAgICAgICBbZmllbGRdOiB7XG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogYFVzZSBJbmxpbmUgRnJhZ21lbnQgb24gQXJyYXkgdG8gZ2V0IHJlc3VsdHM6IGh0dHBzOi8vZ3JhcGhxbC5vcmcvbGVhcm4vcXVlcmllcy8jaW5saW5lLWZyYWdtZW50c2AsXG4gICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgYXN5bmMgcmVzb2x2ZShzb3VyY2UpIHtcbiAgICAgICAgICAgICAgaWYgKCFzb3VyY2VbZmllbGRdKSByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgcmV0dXJuIHNvdXJjZVtmaWVsZF0ubWFwKGFzeW5jIGVsZW0gPT4ge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgIGVsZW0uY2xhc3NOYW1lICYmXG4gICAgICAgICAgICAgICAgICBlbGVtLm9iamVjdElkICYmXG4gICAgICAgICAgICAgICAgICBlbGVtLl9fdHlwZSA9PT0gJ09iamVjdCdcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogZWxlbSB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgW2ZpZWxkXToge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246IGBUaGlzIGlzIHRoZSBvYmplY3QgJHtmaWVsZH0uYCxcbiAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmaWVsZHM7XG4gICAgICB9XG4gICAgfSwgZGVmYXVsdEdyYXBoUUxUeXBlcy5QQVJTRV9PQkpFQ1RfRklFTERTKTtcbiAgfTtcbiAgbGV0IGNsYXNzR3JhcGhRTE91dHB1dFR5cGUgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICAgIG5hbWU6IGNsYXNzR3JhcGhRTE91dHB1dFR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7Y2xhc3NHcmFwaFFMT3V0cHV0VHlwZU5hbWV9IG9iamVjdCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgb3V0cHV0dGluZyBvYmplY3RzIG9mICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICBpbnRlcmZhY2VzOiBbZGVmYXVsdEdyYXBoUUxUeXBlcy5QQVJTRV9PQkpFQ1RdLFxuICAgIGZpZWxkczogb3V0cHV0RmllbGRzLFxuICB9KTtcbiAgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlXG4gICk7XG5cbiAgY29uc3QgY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1GaW5kUmVzdWx0YDtcbiAgbGV0IGNsYXNzR3JhcGhRTEZpbmRSZXN1bHRUeXBlID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgICBuYW1lOiBjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZU5hbWUsXG4gICAgZGVzY3JpcHRpb246IGBUaGUgJHtjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZU5hbWV9IG9iamVjdCB0eXBlIGlzIHVzZWQgaW4gdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gZmluZCBxdWVyeSB0byByZXR1cm4gdGhlIGRhdGEgb2YgdGhlIG1hdGNoZWQgb2JqZWN0cy5gLFxuICAgIGZpZWxkczoge1xuICAgICAgcmVzdWx0czoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIG9iamVjdHMgcmV0dXJuZWQgYnkgdGhlIHF1ZXJ5JyxcbiAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICAgIG5ldyBHcmFwaFFMTGlzdChcbiAgICAgICAgICAgIG5ldyBHcmFwaFFMTm9uTnVsbChcbiAgICAgICAgICAgICAgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSB8fCBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVFxuICAgICAgICAgICAgKVxuICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgIH0sXG4gICAgICBjb3VudDogZGVmYXVsdEdyYXBoUUxUeXBlcy5DT1VOVF9BVFQsXG4gICAgfSxcbiAgfSk7XG4gIGNsYXNzR3JhcGhRTEZpbmRSZXN1bHRUeXBlID0gcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIGNsYXNzR3JhcGhRTEZpbmRSZXN1bHRUeXBlXG4gICk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1tjbGFzc05hbWVdID0ge1xuICAgIGNsYXNzR3JhcGhRTFBvaW50ZXJUeXBlLFxuICAgIGNsYXNzR3JhcGhRTFJlbGF0aW9uVHlwZSxcbiAgICBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlLFxuICAgIGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUsXG4gICAgY2xhc3NHcmFwaFFMQ29uc3RyYWludFR5cGUsXG4gICAgY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlLFxuICAgIGNsYXNzR3JhcGhRTEZpbmRBcmdzLFxuICAgIGNsYXNzR3JhcGhRTE91dHB1dFR5cGUsXG4gICAgY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGUsXG4gICAgY29uZmlnOiB7XG4gICAgICBwYXJzZUNsYXNzQ29uZmlnLFxuICAgICAgaXNDcmVhdGVFbmFibGVkLFxuICAgICAgaXNVcGRhdGVFbmFibGVkLFxuICAgIH0sXG4gIH07XG5cbiAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgIGNvbnN0IHZpZXdlclR5cGUgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICAgICAgbmFtZTogJ1ZpZXdlcicsXG4gICAgICBkZXNjcmlwdGlvbjogYFRoZSBWaWV3ZXIgb2JqZWN0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBvdXRwdXR0aW5nIHRoZSBjdXJyZW50IHVzZXIgZGF0YS5gLFxuICAgICAgaW50ZXJmYWNlczogW2RlZmF1bHRHcmFwaFFMVHlwZXMuUEFSU0VfT0JKRUNUXSxcbiAgICAgIGZpZWxkczogKCkgPT4gKHtcbiAgICAgICAgLi4ub3V0cHV0RmllbGRzKCksXG4gICAgICAgIHNlc3Npb25Ub2tlbjogZGVmYXVsdEdyYXBoUUxUeXBlcy5TRVNTSU9OX1RPS0VOX0FUVCxcbiAgICAgIH0pLFxuICAgIH0pO1xuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS52aWV3ZXJUeXBlID0gdmlld2VyVHlwZTtcbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUodmlld2VyVHlwZSwgdHJ1ZSwgdHJ1ZSk7XG5cbiAgICBjb25zdCB1c2VyU2lnblVwSW5wdXRUeXBlTmFtZSA9ICdTaWduVXBGaWVsZHNJbnB1dCc7XG4gICAgY29uc3QgdXNlclNpZ25VcElucHV0VHlwZSA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgICAgIG5hbWU6IHVzZXJTaWduVXBJbnB1dFR5cGVOYW1lLFxuICAgICAgZGVzY3JpcHRpb246IGBUaGUgJHt1c2VyU2lnblVwSW5wdXRUeXBlTmFtZX0gaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGlucHV0dGluZyBvYmplY3RzIG9mICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3Mgd2hlbiBzaWduaW5nIHVwLmAsXG4gICAgICBmaWVsZHM6ICgpID0+XG4gICAgICAgIGNsYXNzQ3JlYXRlRmllbGRzLnJlZHVjZSgoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHR5cGUgPSB0cmFuc2Zvcm1JbnB1dFR5cGVUb0dyYXBoUUwoXG4gICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSxcbiAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcyxcbiAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICh0eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgICAgIFtmaWVsZF06IHtcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogYFRoaXMgaXMgdGhlIG9iamVjdCAke2ZpZWxkfS5gLFxuICAgICAgICAgICAgICAgIHR5cGU6XG4gICAgICAgICAgICAgICAgICBmaWVsZCA9PT0gJ3VzZXJuYW1lJyB8fCBmaWVsZCA9PT0gJ3Bhc3N3b3JkJ1xuICAgICAgICAgICAgICAgICAgICA/IG5ldyBHcmFwaFFMTm9uTnVsbCh0eXBlKVxuICAgICAgICAgICAgICAgICAgICA6IHR5cGUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmllbGRzO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwge30pLFxuICAgIH0pO1xuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZSh1c2VyU2lnblVwSW5wdXRUeXBlLCB0cnVlLCB0cnVlKTtcblxuICAgIGNvbnN0IHVzZXJMb2dJbklucHV0VHlwZU5hbWUgPSAnTG9nSW5GaWVsZHNJbnB1dCc7XG4gICAgY29uc3QgdXNlckxvZ0luSW5wdXRUeXBlID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgICAgbmFtZTogdXNlckxvZ0luSW5wdXRUeXBlTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7dXNlckxvZ0luSW5wdXRUeXBlTmFtZX0gaW5wdXQgdHlwZSBpcyB1c2VkIHRvIGxvZ2luLmAsXG4gICAgICBmaWVsZHM6IHtcbiAgICAgICAgdXNlcm5hbWU6IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHVzZXJuYW1lIHVzZWQgdG8gbG9nIHRoZSB1c2VyIGluLicsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgICAgICB9LFxuICAgICAgICBwYXNzd29yZDoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgcGFzc3dvcmQgdXNlZCB0byBsb2cgdGhlIHVzZXIgaW4uJyxcbiAgICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFN0cmluZyksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZSh1c2VyTG9nSW5JbnB1dFR5cGUsIHRydWUsIHRydWUpO1xuXG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1tcbiAgICAgIGNsYXNzTmFtZVxuICAgIF0uc2lnblVwSW5wdXRUeXBlID0gdXNlclNpZ25VcElucHV0VHlwZTtcbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW1xuICAgICAgY2xhc3NOYW1lXG4gICAgXS5sb2dJbklucHV0VHlwZSA9IHVzZXJMb2dJbklucHV0VHlwZTtcbiAgfVxufTtcblxuZXhwb3J0IHsgZXh0cmFjdEtleXNBbmRJbmNsdWRlLCBsb2FkIH07XG4iXX0= \ No newline at end of file diff --git a/lib/GraphQL/loaders/schemaDirectives.js b/lib/GraphQL/loaders/schemaDirectives.js new file mode 100644 index 0000000000..966fa1eb10 --- /dev/null +++ b/lib/GraphQL/loaders/schemaDirectives.js @@ -0,0 +1,72 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = exports.definitions = void 0; + +var _graphqlTag = _interopRequireDefault(require("graphql-tag")); + +var _graphqlTools = require("graphql-tools"); + +var _FunctionsRouter = require("../../Routers/FunctionsRouter"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const definitions = _graphqlTag.default` + directive @resolve(to: String) on FIELD_DEFINITION + directive @mock(with: Any!) on FIELD_DEFINITION +`; +exports.definitions = definitions; + +const load = parseGraphQLSchema => { + parseGraphQLSchema.graphQLSchemaDirectivesDefinitions = definitions; + + class ResolveDirectiveVisitor extends _graphqlTools.SchemaDirectiveVisitor { + visitFieldDefinition(field) { + field.resolve = async (_source, args, context) => { + try { + const { + config, + auth, + info + } = context; + let functionName = field.name; + + if (this.args.to) { + functionName = this.args.to; + } + + return (await _FunctionsRouter.FunctionsRouter.handleCloudFunction({ + params: { + functionName + }, + config, + auth, + info, + body: args + })).response.result; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + }; + } + + } + + parseGraphQLSchema.graphQLSchemaDirectives.resolve = ResolveDirectiveVisitor; + + class MockDirectiveVisitor extends _graphqlTools.SchemaDirectiveVisitor { + visitFieldDefinition(field) { + field.resolve = () => { + return this.args.with; + }; + } + + } + + parseGraphQLSchema.graphQLSchemaDirectives.mock = MockDirectiveVisitor; +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvc2NoZW1hRGlyZWN0aXZlcy5qcyJdLCJuYW1lcyI6WyJkZWZpbml0aW9ucyIsImdxbCIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zIiwiUmVzb2x2ZURpcmVjdGl2ZVZpc2l0b3IiLCJTY2hlbWFEaXJlY3RpdmVWaXNpdG9yIiwidmlzaXRGaWVsZERlZmluaXRpb24iLCJmaWVsZCIsInJlc29sdmUiLCJfc291cmNlIiwiYXJncyIsImNvbnRleHQiLCJjb25maWciLCJhdXRoIiwiaW5mbyIsImZ1bmN0aW9uTmFtZSIsIm5hbWUiLCJ0byIsIkZ1bmN0aW9uc1JvdXRlciIsImhhbmRsZUNsb3VkRnVuY3Rpb24iLCJwYXJhbXMiLCJib2R5IiwicmVzcG9uc2UiLCJyZXN1bHQiLCJlIiwiaGFuZGxlRXJyb3IiLCJncmFwaFFMU2NoZW1hRGlyZWN0aXZlcyIsIk1vY2tEaXJlY3RpdmVWaXNpdG9yIiwid2l0aCIsIm1vY2siXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLFdBQVcsR0FBR0MsbUJBQUk7OztDQUF4Qjs7O0FBS1AsTUFBTUMsSUFBSSxHQUFHQyxrQkFBa0IsSUFBSTtBQUNqQ0EsRUFBQUEsa0JBQWtCLENBQUNDLGtDQUFuQixHQUF3REosV0FBeEQ7O0FBRUEsUUFBTUssdUJBQU4sU0FBc0NDLG9DQUF0QyxDQUE2RDtBQUMzREMsSUFBQUEsb0JBQW9CLENBQUNDLEtBQUQsRUFBUTtBQUMxQkEsTUFBQUEsS0FBSyxDQUFDQyxPQUFOLEdBQWdCLE9BQU9DLE9BQVAsRUFBZ0JDLElBQWhCLEVBQXNCQyxPQUF0QixLQUFrQztBQUNoRCxZQUFJO0FBQ0YsZ0JBQU07QUFBRUMsWUFBQUEsTUFBRjtBQUFVQyxZQUFBQSxJQUFWO0FBQWdCQyxZQUFBQTtBQUFoQixjQUF5QkgsT0FBL0I7QUFFQSxjQUFJSSxZQUFZLEdBQUdSLEtBQUssQ0FBQ1MsSUFBekI7O0FBQ0EsY0FBSSxLQUFLTixJQUFMLENBQVVPLEVBQWQsRUFBa0I7QUFDaEJGLFlBQUFBLFlBQVksR0FBRyxLQUFLTCxJQUFMLENBQVVPLEVBQXpCO0FBQ0Q7O0FBRUQsaUJBQU8sQ0FBQyxNQUFNQyxpQ0FBZ0JDLG1CQUFoQixDQUFvQztBQUNoREMsWUFBQUEsTUFBTSxFQUFFO0FBQ05MLGNBQUFBO0FBRE0sYUFEd0M7QUFJaERILFlBQUFBLE1BSmdEO0FBS2hEQyxZQUFBQSxJQUxnRDtBQU1oREMsWUFBQUEsSUFOZ0Q7QUFPaERPLFlBQUFBLElBQUksRUFBRVg7QUFQMEMsV0FBcEMsQ0FBUCxFQVFIWSxRQVJHLENBUU1DLE1BUmI7QUFTRCxTQWpCRCxDQWlCRSxPQUFPQyxDQUFQLEVBQVU7QUFDVnRCLFVBQUFBLGtCQUFrQixDQUFDdUIsV0FBbkIsQ0FBK0JELENBQS9CO0FBQ0Q7QUFDRixPQXJCRDtBQXNCRDs7QUF4QjBEOztBQTJCN0R0QixFQUFBQSxrQkFBa0IsQ0FBQ3dCLHVCQUFuQixDQUEyQ2xCLE9BQTNDLEdBQXFESix1QkFBckQ7O0FBRUEsUUFBTXVCLG9CQUFOLFNBQW1DdEIsb0NBQW5DLENBQTBEO0FBQ3hEQyxJQUFBQSxvQkFBb0IsQ0FBQ0MsS0FBRCxFQUFRO0FBQzFCQSxNQUFBQSxLQUFLLENBQUNDLE9BQU4sR0FBZ0IsTUFBTTtBQUNwQixlQUFPLEtBQUtFLElBQUwsQ0FBVWtCLElBQWpCO0FBQ0QsT0FGRDtBQUdEOztBQUx1RDs7QUFRMUQxQixFQUFBQSxrQkFBa0IsQ0FBQ3dCLHVCQUFuQixDQUEyQ0csSUFBM0MsR0FBa0RGLG9CQUFsRDtBQUNELENBekNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGdxbCBmcm9tICdncmFwaHFsLXRhZyc7XG5pbXBvcnQgeyBTY2hlbWFEaXJlY3RpdmVWaXNpdG9yIH0gZnJvbSAnZ3JhcGhxbC10b29scyc7XG5pbXBvcnQgeyBGdW5jdGlvbnNSb3V0ZXIgfSBmcm9tICcuLi8uLi9Sb3V0ZXJzL0Z1bmN0aW9uc1JvdXRlcic7XG5cbmV4cG9ydCBjb25zdCBkZWZpbml0aW9ucyA9IGdxbGBcbiAgZGlyZWN0aXZlIEByZXNvbHZlKHRvOiBTdHJpbmcpIG9uIEZJRUxEX0RFRklOSVRJT05cbiAgZGlyZWN0aXZlIEBtb2NrKHdpdGg6IEFueSEpIG9uIEZJRUxEX0RFRklOSVRJT05cbmA7XG5cbmNvbnN0IGxvYWQgPSBwYXJzZUdyYXBoUUxTY2hlbWEgPT4ge1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXNEZWZpbml0aW9ucyA9IGRlZmluaXRpb25zO1xuXG4gIGNsYXNzIFJlc29sdmVEaXJlY3RpdmVWaXNpdG9yIGV4dGVuZHMgU2NoZW1hRGlyZWN0aXZlVmlzaXRvciB7XG4gICAgdmlzaXRGaWVsZERlZmluaXRpb24oZmllbGQpIHtcbiAgICAgIGZpZWxkLnJlc29sdmUgPSBhc3luYyAoX3NvdXJjZSwgYXJncywgY29udGV4dCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuXG4gICAgICAgICAgbGV0IGZ1bmN0aW9uTmFtZSA9IGZpZWxkLm5hbWU7XG4gICAgICAgICAgaWYgKHRoaXMuYXJncy50bykge1xuICAgICAgICAgICAgZnVuY3Rpb25OYW1lID0gdGhpcy5hcmdzLnRvO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiAoYXdhaXQgRnVuY3Rpb25zUm91dGVyLmhhbmRsZUNsb3VkRnVuY3Rpb24oe1xuICAgICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICAgIGZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgaW5mbyxcbiAgICAgICAgICAgIGJvZHk6IGFyZ3MsXG4gICAgICAgICAgfSkpLnJlc3BvbnNlLnJlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXMucmVzb2x2ZSA9IFJlc29sdmVEaXJlY3RpdmVWaXNpdG9yO1xuXG4gIGNsYXNzIE1vY2tEaXJlY3RpdmVWaXNpdG9yIGV4dGVuZHMgU2NoZW1hRGlyZWN0aXZlVmlzaXRvciB7XG4gICAgdmlzaXRGaWVsZERlZmluaXRpb24oZmllbGQpIHtcbiAgICAgIGZpZWxkLnJlc29sdmUgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmFyZ3Mud2l0aDtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzLm1vY2sgPSBNb2NrRGlyZWN0aXZlVmlzaXRvcjtcbn07XG5cbmV4cG9ydCB7IGxvYWQgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/loaders/schemaMutations.js b/lib/GraphQL/loaders/schemaMutations.js new file mode 100644 index 0000000000..9e6a244da8 --- /dev/null +++ b/lib/GraphQL/loaders/schemaMutations.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _graphql = require("graphql"); + +var schemaTypes = _interopRequireWildcard(require("./schemaTypes")); + +var _schemaFields = require("../transformers/schemaFields"); + +var _parseGraphQLUtils = require("../parseGraphQLUtils"); + +var _schemaQueries = require("./schemaQueries"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const load = parseGraphQLSchema => { + parseGraphQLSchema.addGraphQLMutation('createClass', { + description: 'The createClass mutation can be used to create the schema for a new object class.', + args: { + name: schemaTypes.CLASS_NAME_ATT, + schemaFields: { + description: "These are the schema's fields of the object class.", + type: schemaTypes.SCHEMA_FIELDS_INPUT + } + }, + type: new _graphql.GraphQLNonNull(schemaTypes.CLASS), + resolve: async (_source, args, context) => { + try { + const { + name, + schemaFields + } = args; + const { + config, + auth + } = context; + (0, _parseGraphQLUtils.enforceMasterKeyAccess)(auth); + + if (auth.isReadOnly) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to create a schema."); + } + + const schema = await config.database.loadSchema({ + clearCache: true + }); + const parseClass = await schema.addClassIfNotExists(name, (0, _schemaFields.transformToParse)(schemaFields)); + return { + name: parseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(parseClass.fields) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }, true, true); + parseGraphQLSchema.addGraphQLMutation('updateClass', { + description: 'The updateClass mutation can be used to update the schema for an existing object class.', + args: { + name: schemaTypes.CLASS_NAME_ATT, + schemaFields: { + description: "These are the schema's fields of the object class.", + type: schemaTypes.SCHEMA_FIELDS_INPUT + } + }, + type: new _graphql.GraphQLNonNull(schemaTypes.CLASS), + resolve: async (_source, args, context) => { + try { + const { + name, + schemaFields + } = args; + const { + config, + auth + } = context; + (0, _parseGraphQLUtils.enforceMasterKeyAccess)(auth); + + if (auth.isReadOnly) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to update a schema."); + } + + const schema = await config.database.loadSchema({ + clearCache: true + }); + const existingParseClass = await (0, _schemaQueries.getClass)(name, schema); + const parseClass = await schema.updateClass(name, (0, _schemaFields.transformToParse)(schemaFields, existingParseClass.fields), undefined, undefined, config.database); + return { + name: parseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(parseClass.fields) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }, true, true); + parseGraphQLSchema.addGraphQLMutation('deleteClass', { + description: 'The deleteClass mutation can be used to delete an existing object class.', + args: { + name: schemaTypes.CLASS_NAME_ATT + }, + type: new _graphql.GraphQLNonNull(schemaTypes.CLASS), + resolve: async (_source, args, context) => { + try { + const { + name + } = args; + const { + config, + auth + } = context; + (0, _parseGraphQLUtils.enforceMasterKeyAccess)(auth); + + if (auth.isReadOnly) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to delete a schema."); + } + + const schema = await config.database.loadSchema({ + clearCache: true + }); + const existingParseClass = await (0, _schemaQueries.getClass)(name, schema); + await config.database.deleteSchema(name); + return { + name: existingParseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(existingParseClass.fields) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvc2NoZW1hTXV0YXRpb25zLmpzIl0sIm5hbWVzIjpbImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJhZGRHcmFwaFFMTXV0YXRpb24iLCJkZXNjcmlwdGlvbiIsImFyZ3MiLCJuYW1lIiwic2NoZW1hVHlwZXMiLCJDTEFTU19OQU1FX0FUVCIsInNjaGVtYUZpZWxkcyIsInR5cGUiLCJTQ0hFTUFfRklFTERTX0lOUFVUIiwiR3JhcGhRTE5vbk51bGwiLCJDTEFTUyIsInJlc29sdmUiLCJfc291cmNlIiwiY29udGV4dCIsImNvbmZpZyIsImF1dGgiLCJpc1JlYWRPbmx5IiwiUGFyc2UiLCJFcnJvciIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJzY2hlbWEiLCJkYXRhYmFzZSIsImxvYWRTY2hlbWEiLCJjbGVhckNhY2hlIiwicGFyc2VDbGFzcyIsImFkZENsYXNzSWZOb3RFeGlzdHMiLCJjbGFzc05hbWUiLCJmaWVsZHMiLCJlIiwiaGFuZGxlRXJyb3IiLCJleGlzdGluZ1BhcnNlQ2xhc3MiLCJ1cGRhdGVDbGFzcyIsInVuZGVmaW5lZCIsImRlbGV0ZVNjaGVtYSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUlBOztBQUNBOzs7Ozs7OztBQUVBLE1BQU1BLElBQUksR0FBR0Msa0JBQWtCLElBQUk7QUFDakNBLEVBQUFBLGtCQUFrQixDQUFDQyxrQkFBbkIsQ0FDRSxhQURGLEVBRUU7QUFDRUMsSUFBQUEsV0FBVyxFQUNULG1GQUZKO0FBR0VDLElBQUFBLElBQUksRUFBRTtBQUNKQyxNQUFBQSxJQUFJLEVBQUVDLFdBQVcsQ0FBQ0MsY0FEZDtBQUVKQyxNQUFBQSxZQUFZLEVBQUU7QUFDWkwsUUFBQUEsV0FBVyxFQUFFLG9EQUREO0FBRVpNLFFBQUFBLElBQUksRUFBRUgsV0FBVyxDQUFDSTtBQUZOO0FBRlYsS0FIUjtBQVVFRCxJQUFBQSxJQUFJLEVBQUUsSUFBSUUs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LGVBQU87QUFDTEEsVUFBQUEsSUFBSSxFQUFFMkIsa0JBQWtCLENBQUNKLFNBRHBCO0FBRUxwQixVQUFBQSxZQUFZLEVBQUUsc0NBQW1Cd0Isa0JBQWtCLENBQUNILE1BQXRDO0FBRlQsU0FBUDtBQUlELE9BcEJELENBb0JFLE9BQU9DLENBQVAsRUFBVTtBQUNWN0IsUUFBQUEsa0JBQWtCLENBQUM4QixXQUFuQixDQUErQkQsQ0FBL0I7QUFDRDtBQUNGO0FBL0JILEdBRkYsRUFtQ0UsSUFuQ0YsRUFvQ0UsSUFwQ0Y7QUFzQ0QsQ0FySUQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBHcmFwaFFMTm9uTnVsbCB9IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0ICogYXMgc2NoZW1hVHlwZXMgZnJvbSAnLi9zY2hlbWFUeXBlcyc7XG5pbXBvcnQge1xuICB0cmFuc2Zvcm1Ub1BhcnNlLFxuICB0cmFuc2Zvcm1Ub0dyYXBoUUwsXG59IGZyb20gJy4uL3RyYW5zZm9ybWVycy9zY2hlbWFGaWVsZHMnO1xuaW1wb3J0IHsgZW5mb3JjZU1hc3RlcktleUFjY2VzcyB9IGZyb20gJy4uL3BhcnNlR3JhcGhRTFV0aWxzJztcbmltcG9ydCB7IGdldENsYXNzIH0gZnJvbSAnLi9zY2hlbWFRdWVyaWVzJztcblxuY29uc3QgbG9hZCA9IHBhcnNlR3JhcGhRTFNjaGVtYSA9PiB7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgJ2NyZWF0ZUNsYXNzJyxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoZSBjcmVhdGVDbGFzcyBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byBjcmVhdGUgdGhlIHNjaGVtYSBmb3IgYSBuZXcgb2JqZWN0IGNsYXNzLicsXG4gICAgICBhcmdzOiB7XG4gICAgICAgIG5hbWU6IHNjaGVtYVR5cGVzLkNMQVNTX05BTUVfQVRULFxuICAgICAgICBzY2hlbWFGaWVsZHM6IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjogXCJUaGVzZSBhcmUgdGhlIHNjaGVtYSdzIGZpZWxkcyBvZiB0aGUgb2JqZWN0IGNsYXNzLlwiLFxuICAgICAgICAgIHR5cGU6IHNjaGVtYVR5cGVzLlNDSEVNQV9GSUVMRFNfSU5QVVQsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKHNjaGVtYVR5cGVzLkNMQVNTKSxcbiAgICAgIHJlc29sdmU6IGFzeW5jIChfc291cmNlLCBhcmdzLCBjb250ZXh0KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBuYW1lLCBzY2hlbWFGaWVsZHMgfSA9IGFyZ3M7XG4gICAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGggfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgICBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzKGF1dGgpO1xuXG4gICAgICAgICAgaWYgKGF1dGguaXNSZWFkT25seSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgICBcInJlYWQtb25seSBtYXN0ZXJLZXkgaXNuJ3QgYWxsb3dlZCB0byBjcmVhdGUgYSBzY2hlbWEuXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgY29uZmlnLmRhdGFiYXNlLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlIH0pO1xuICAgICAgICAgIGNvbnN0IHBhcnNlQ2xhc3MgPSBhd2FpdCBzY2hlbWEuYWRkQ2xhc3NJZk5vdEV4aXN0cyhcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICB0cmFuc2Zvcm1Ub1BhcnNlKHNjaGVtYUZpZWxkcylcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuYW1lOiBwYXJzZUNsYXNzLmNsYXNzTmFtZSxcbiAgICAgICAgICAgIHNjaGVtYUZpZWxkczogdHJhbnNmb3JtVG9HcmFwaFFMKHBhcnNlQ2xhc3MuZmllbGRzKSxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmhhbmRsZUVycm9yKGUpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxNdXRhdGlvbihcbiAgICAndXBkYXRlQ2xhc3MnLFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhlIHVwZGF0ZUNsYXNzIG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIHVwZGF0ZSB0aGUgc2NoZW1hIGZvciBhbiBleGlzdGluZyBvYmplY3QgY2xhc3MuJyxcbiAgICAgIGFyZ3M6IHtcbiAgICAgICAgbmFtZTogc2NoZW1hVHlwZXMuQ0xBU1NfTkFNRV9BVFQsXG4gICAgICAgIHNjaGVtYUZpZWxkczoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBcIlRoZXNlIGFyZSB0aGUgc2NoZW1hJ3MgZmllbGRzIG9mIHRoZSBvYmplY3QgY2xhc3MuXCIsXG4gICAgICAgICAgdHlwZTogc2NoZW1hVHlwZXMuU0NIRU1BX0ZJRUxEU19JTlBVVCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoc2NoZW1hVHlwZXMuQ0xBU1MpLFxuICAgICAgcmVzb2x2ZTogYXN5bmMgKF9zb3VyY2UsIGFyZ3MsIGNvbnRleHQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IG5hbWUsIHNjaGVtYUZpZWxkcyB9ID0gYXJncztcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCB9ID0gY29udGV4dDtcblxuICAgICAgICAgIGVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MoYXV0aCk7XG5cbiAgICAgICAgICBpZiAoYXV0aC5pc1JlYWRPbmx5KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICAgICAgICAgIFwicmVhZC1vbmx5IG1hc3RlcktleSBpc24ndCBhbGxvd2VkIHRvIHVwZGF0ZSBhIHNjaGVtYS5cIlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCBjb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSh7IGNsZWFyQ2FjaGU6IHRydWUgfSk7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJzZUNsYXNzID0gYXdhaXQgZ2V0Q2xhc3MobmFtZSwgc2NoZW1hKTtcbiAgICAgICAgICBjb25zdCBwYXJzZUNsYXNzID0gYXdhaXQgc2NoZW1hLnVwZGF0ZUNsYXNzKFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIHRyYW5zZm9ybVRvUGFyc2Uoc2NoZW1hRmllbGRzLCBleGlzdGluZ1BhcnNlQ2xhc3MuZmllbGRzKSxcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGNvbmZpZy5kYXRhYmFzZVxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5hbWU6IHBhcnNlQ2xhc3MuY2xhc3NOYW1lLFxuICAgICAgICAgICAgc2NoZW1hRmllbGRzOiB0cmFuc2Zvcm1Ub0dyYXBoUUwocGFyc2VDbGFzcy5maWVsZHMpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTE11dGF0aW9uKFxuICAgICdkZWxldGVDbGFzcycsXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGUgZGVsZXRlQ2xhc3MgbXV0YXRpb24gY2FuIGJlIHVzZWQgdG8gZGVsZXRlIGFuIGV4aXN0aW5nIG9iamVjdCBjbGFzcy4nLFxuICAgICAgYXJnczoge1xuICAgICAgICBuYW1lOiBzY2hlbWFUeXBlcy5DTEFTU19OQU1FX0FUVCxcbiAgICAgIH0sXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoc2NoZW1hVHlwZXMuQ0xBU1MpLFxuICAgICAgcmVzb2x2ZTogYXN5bmMgKF9zb3VyY2UsIGFyZ3MsIGNvbnRleHQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IG5hbWUgfSA9IGFyZ3M7XG4gICAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGggfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgICBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzKGF1dGgpO1xuXG4gICAgICAgICAgaWYgKGF1dGguaXNSZWFkT25seSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgICBcInJlYWQtb25seSBtYXN0ZXJLZXkgaXNuJ3QgYWxsb3dlZCB0byBkZWxldGUgYSBzY2hlbWEuXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgY29uZmlnLmRhdGFiYXNlLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlIH0pO1xuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nUGFyc2VDbGFzcyA9IGF3YWl0IGdldENsYXNzKG5hbWUsIHNjaGVtYSk7XG4gICAgICAgICAgYXdhaXQgY29uZmlnLmRhdGFiYXNlLmRlbGV0ZVNjaGVtYShuYW1lKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbmFtZTogZXhpc3RpbmdQYXJzZUNsYXNzLmNsYXNzTmFtZSxcbiAgICAgICAgICAgIHNjaGVtYUZpZWxkczogdHJhbnNmb3JtVG9HcmFwaFFMKGV4aXN0aW5nUGFyc2VDbGFzcy5maWVsZHMpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbn07XG5cbmV4cG9ydCB7IGxvYWQgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/loaders/schemaQueries.js b/lib/GraphQL/loaders/schemaQueries.js new file mode 100644 index 0000000000..e1df2aa6b3 --- /dev/null +++ b/lib/GraphQL/loaders/schemaQueries.js @@ -0,0 +1,93 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = exports.getClass = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _graphql = require("graphql"); + +var _schemaFields = require("../transformers/schemaFields"); + +var schemaTypes = _interopRequireWildcard(require("./schemaTypes")); + +var _parseGraphQLUtils = require("../parseGraphQLUtils"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const getClass = async (name, schema) => { + try { + return await schema.getOneSchema(name, true); + } catch (e) { + if (e === undefined) { + throw new _node.default.Error(_node.default.Error.INVALID_CLASS_NAME, `Class ${name} does not exist.`); + } else { + throw new _node.default.Error(_node.default.Error.INTERNAL_SERVER_ERROR, 'Database adapter error.'); + } + } +}; + +exports.getClass = getClass; + +const load = parseGraphQLSchema => { + parseGraphQLSchema.addGraphQLQuery('class', { + description: 'The class query can be used to retrieve an existing object class.', + args: { + name: schemaTypes.CLASS_NAME_ATT + }, + type: new _graphql.GraphQLNonNull(schemaTypes.CLASS), + resolve: async (_source, args, context) => { + try { + const { + name + } = args; + const { + config, + auth + } = context; + (0, _parseGraphQLUtils.enforceMasterKeyAccess)(auth); + const schema = await config.database.loadSchema({ + clearCache: true + }); + const parseClass = await getClass(name, schema); + return { + name: parseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(parseClass.fields) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }, true, true); + parseGraphQLSchema.addGraphQLQuery('classes', { + description: 'The classes query can be used to retrieve the existing object classes.', + type: new _graphql.GraphQLNonNull(new _graphql.GraphQLList(new _graphql.GraphQLNonNull(schemaTypes.CLASS))), + resolve: async (_source, _args, context) => { + try { + const { + config, + auth + } = context; + (0, _parseGraphQLUtils.enforceMasterKeyAccess)(auth); + const schema = await config.database.loadSchema({ + clearCache: true + }); + return (await schema.getAllClasses(true)).map(parseClass => ({ + name: parseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(parseClass.fields) + })); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvc2NoZW1hUXVlcmllcy5qcyJdLCJuYW1lcyI6WyJnZXRDbGFzcyIsIm5hbWUiLCJzY2hlbWEiLCJnZXRPbmVTY2hlbWEiLCJlIiwidW5kZWZpbmVkIiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfQ0xBU1NfTkFNRSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJhZGRHcmFwaFFMUXVlcnkiLCJkZXNjcmlwdGlvbiIsImFyZ3MiLCJzY2hlbWFUeXBlcyIsIkNMQVNTX05BTUVfQVRUIiwidHlwZSIsIkdyYXBoUUxOb25OdWxsIiwiQ0xBU1MiLCJyZXNvbHZlIiwiX3NvdXJjZSIsImNvbnRleHQiLCJjb25maWciLCJhdXRoIiwiZGF0YWJhc2UiLCJsb2FkU2NoZW1hIiwiY2xlYXJDYWNoZSIsInBhcnNlQ2xhc3MiLCJjbGFzc05hbWUiLCJzY2hlbWFGaWVsZHMiLCJmaWVsZHMiLCJoYW5kbGVFcnJvciIsIkdyYXBoUUxMaXN0IiwiX2FyZ3MiLCJnZXRBbGxDbGFzc2VzIiwibWFwIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBRUEsTUFBTUEsUUFBUSxHQUFHLE9BQU9DLElBQVAsRUFBYUMsTUFBYixLQUF3QjtBQUN2QyxNQUFJO0FBQ0YsV0FBTyxNQUFNQSxNQUFNLENBQUNDLFlBQVAsQ0FBb0JGLElBQXBCLEVBQTBCLElBQTFCLENBQWI7QUFDRCxHQUZELENBRUUsT0FBT0csQ0FBUCxFQUFVO0FBQ1YsUUFBSUEsQ0FBQyxLQUFLQyxTQUFWLEVBQXFCO0FBQ25CLFlBQU0sSUFBSUMsY0FBTUMsS0FBVixDQUNKRCxjQUFNQyxLQUFOLENBQVlDLGtCQURSLEVBRUgsU0FBUVAsSUFBSyxrQkFGVixDQUFOO0FBSUQsS0FMRCxNQUtPO0FBQ0wsWUFBTSxJQUFJSyxjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUUscUJBRFIsRUFFSix5QkFGSSxDQUFOO0FBSUQ7QUFDRjtBQUNGLENBaEJEOzs7O0FBa0JBLE1BQU1DLElBQUksR0FBR0Msa0JBQWtCLElBQUk7QUFDakNBLEVBQUFBLGtCQUFrQixDQUFDQyxlQUFuQixDQUNFLE9BREYsRUFFRTtBQUNFQyxJQUFBQSxXQUFXLEVBQ1QsbUVBRko7QUFHRUMsSUFBQUEsSUFBSSxFQUFFO0FBQ0piLE1BQUFBLElBQUksRUFBRWMsV0FBVyxDQUFDQztBQURkLEtBSFI7QUFNRUMsSUFBQUEsSUFBSSxFQUFFLElBQUlDLHVCQUFKLENBQW1CSCxXQUFXLENBQUNJLEtBQS9CLENBTlI7QUFPRUMsSUFBQUEsT0FBTyxFQUFFLE9BQU9DLE9BQVAsRUFBZ0JQLElBQWhCLEVBQXNCUSxPQUF0QixLQUFrQztBQUN6QyxVQUFJO0FBQ0YsY0FBTTtBQUFFckIsVUFBQUE7QUFBRixZQUFXYSxJQUFqQjtBQUNBLGNBQU07QUFBRVMsVUFBQUEsTUFBRjtBQUFVQyxVQUFBQTtBQUFWLFlBQW1CRixPQUF6QjtBQUVBLHVEQUF1QkUsSUFBdkI7QUFFQSxjQUFNdEIsTUFBTSxHQUFHLE1BQU1xQixNQUFNLENBQUNFLFFBQVAsQ0FBZ0JDLFVBQWhCLENBQTJCO0FBQUVDLFVBQUFBLFVBQVUsRUFBRTtBQUFkLFNBQTNCLENBQXJCO0FBQ0EsY0FBTUMsVUFBVSxHQUFHLE1BQU01QixRQUFRLENBQUNDLElBQUQsRUFBT0MsTUFBUCxDQUFqQztBQUNBLGVBQU87QUFDTEQsVUFBQUEsSUFBSSxFQUFFMkIsVUFBVSxDQUFDQyxTQURaO0FBRUxDLFVBQUFBLFlBQVksRUFBRSxzQ0FBbUJGLFVBQVUsQ0FBQ0csTUFBOUI7QUFGVCxTQUFQO0FBSUQsT0FaRCxDQVlFLE9BQU8zQixDQUFQLEVBQVU7QUFDVk8sUUFBQUEsa0JBQWtCLENBQUNxQixXQUFuQixDQUErQjVCLENBQS9CO0FBQ0Q7QUFDRjtBQXZCSCxHQUZGLEVBMkJFLElBM0JGLEVBNEJFLElBNUJGO0FBK0JBTyxFQUFBQSxrQkFBa0IsQ0FBQ0MsZUFBbkIsQ0FDRSxTQURGLEVBRUU7QUFDRUMsSUFBQUEsV0FBVyxFQUNULHdFQUZKO0FBR0VJLElBQUFBLElBQUksRUFBRSxJQUFJQyx1QkFBSixDQUNKLElBQUllLG9CQUFKLENBQWdCLElBQUlmLHVCQUFKLENBQW1CSCxXQUFXLENBQUNJLEtBQS9CLENBQWhCLENBREksQ0FIUjtBQU1FQyxJQUFBQSxPQUFPLEVBQUUsT0FBT0MsT0FBUCxFQUFnQmEsS0FBaEIsRUFBdUJaLE9BQXZCLEtBQW1DO0FBQzFDLFVBQUk7QUFDRixjQUFNO0FBQUVDLFVBQUFBLE1BQUY7QUFBVUMsVUFBQUE7QUFBVixZQUFtQkYsT0FBekI7QUFFQSx1REFBdUJFLElBQXZCO0FBRUEsY0FBTXRCLE1BQU0sR0FBRyxNQUFNcUIsTUFBTSxDQUFDRSxRQUFQLENBQWdCQyxVQUFoQixDQUEyQjtBQUFFQyxVQUFBQSxVQUFVLEVBQUU7QUFBZCxTQUEzQixDQUFyQjtBQUNBLGVBQU8sQ0FBQyxNQUFNekIsTUFBTSxDQUFDaUMsYUFBUCxDQUFxQixJQUFyQixDQUFQLEVBQW1DQyxHQUFuQyxDQUF1Q1IsVUFBVSxLQUFLO0FBQzNEM0IsVUFBQUEsSUFBSSxFQUFFMkIsVUFBVSxDQUFDQyxTQUQwQztBQUUzREMsVUFBQUEsWUFBWSxFQUFFLHNDQUFtQkYsVUFBVSxDQUFDRyxNQUE5QjtBQUY2QyxTQUFMLENBQWpELENBQVA7QUFJRCxPQVZELENBVUUsT0FBTzNCLENBQVAsRUFBVTtBQUNWTyxRQUFBQSxrQkFBa0IsQ0FBQ3FCLFdBQW5CLENBQStCNUIsQ0FBL0I7QUFDRDtBQUNGO0FBcEJILEdBRkYsRUF3QkUsSUF4QkYsRUF5QkUsSUF6QkY7QUEyQkQsQ0EzREQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBHcmFwaFFMTm9uTnVsbCwgR3JhcGhRTExpc3QgfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCB7IHRyYW5zZm9ybVRvR3JhcGhRTCB9IGZyb20gJy4uL3RyYW5zZm9ybWVycy9zY2hlbWFGaWVsZHMnO1xuaW1wb3J0ICogYXMgc2NoZW1hVHlwZXMgZnJvbSAnLi9zY2hlbWFUeXBlcyc7XG5pbXBvcnQgeyBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzIH0gZnJvbSAnLi4vcGFyc2VHcmFwaFFMVXRpbHMnO1xuXG5jb25zdCBnZXRDbGFzcyA9IGFzeW5jIChuYW1lLCBzY2hlbWEpID0+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgc2NoZW1hLmdldE9uZVNjaGVtYShuYW1lLCB0cnVlKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICBgQ2xhc3MgJHtuYW1lfSBkb2VzIG5vdCBleGlzdC5gXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgJ0RhdGFiYXNlIGFkYXB0ZXIgZXJyb3IuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cbn07XG5cbmNvbnN0IGxvYWQgPSBwYXJzZUdyYXBoUUxTY2hlbWEgPT4ge1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFF1ZXJ5KFxuICAgICdjbGFzcycsXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGUgY2xhc3MgcXVlcnkgY2FuIGJlIHVzZWQgdG8gcmV0cmlldmUgYW4gZXhpc3Rpbmcgb2JqZWN0IGNsYXNzLicsXG4gICAgICBhcmdzOiB7XG4gICAgICAgIG5hbWU6IHNjaGVtYVR5cGVzLkNMQVNTX05BTUVfQVRULFxuICAgICAgfSxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChzY2hlbWFUeXBlcy5DTEFTUyksXG4gICAgICByZXNvbHZlOiBhc3luYyAoX3NvdXJjZSwgYXJncywgY29udGV4dCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHsgbmFtZSB9ID0gYXJncztcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCB9ID0gY29udGV4dDtcblxuICAgICAgICAgIGVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MoYXV0aCk7XG5cbiAgICAgICAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCBjb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSh7IGNsZWFyQ2FjaGU6IHRydWUgfSk7XG4gICAgICAgICAgY29uc3QgcGFyc2VDbGFzcyA9IGF3YWl0IGdldENsYXNzKG5hbWUsIHNjaGVtYSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5hbWU6IHBhcnNlQ2xhc3MuY2xhc3NOYW1lLFxuICAgICAgICAgICAgc2NoZW1hRmllbGRzOiB0cmFuc2Zvcm1Ub0dyYXBoUUwocGFyc2VDbGFzcy5maWVsZHMpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFF1ZXJ5KFxuICAgICdjbGFzc2VzJyxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoZSBjbGFzc2VzIHF1ZXJ5IGNhbiBiZSB1c2VkIHRvIHJldHJpZXZlIHRoZSBleGlzdGluZyBvYmplY3QgY2xhc3Nlcy4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKHNjaGVtYVR5cGVzLkNMQVNTKSlcbiAgICAgICksXG4gICAgICByZXNvbHZlOiBhc3luYyAoX3NvdXJjZSwgX2FyZ3MsIGNvbnRleHQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCB9ID0gY29udGV4dDtcblxuICAgICAgICAgIGVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MoYXV0aCk7XG5cbiAgICAgICAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCBjb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSh7IGNsZWFyQ2FjaGU6IHRydWUgfSk7XG4gICAgICAgICAgcmV0dXJuIChhd2FpdCBzY2hlbWEuZ2V0QWxsQ2xhc3Nlcyh0cnVlKSkubWFwKHBhcnNlQ2xhc3MgPT4gKHtcbiAgICAgICAgICAgIG5hbWU6IHBhcnNlQ2xhc3MuY2xhc3NOYW1lLFxuICAgICAgICAgICAgc2NoZW1hRmllbGRzOiB0cmFuc2Zvcm1Ub0dyYXBoUUwocGFyc2VDbGFzcy5maWVsZHMpLFxuICAgICAgICAgIH0pKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9LFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xufTtcblxuZXhwb3J0IHsgZ2V0Q2xhc3MsIGxvYWQgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/loaders/schemaTypes.js b/lib/GraphQL/loaders/schemaTypes.js new file mode 100644 index 0000000000..face4b3b4b --- /dev/null +++ b/lib/GraphQL/loaders/schemaTypes.js @@ -0,0 +1,376 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = exports.CLASS = exports.CLASS_NAME_ATT = exports.SCHEMA_FIELDS_INPUT = exports.SCHEMA_ACL_FIELD = exports.SCHEMA_RELATION_FIELD = exports.SCHEMA_RELATION_FIELD_INPUT = exports.SCHEMA_POINTER_FIELD = exports.SCHEMA_POINTER_FIELD_INPUT = exports.TARGET_CLASS_ATT = exports.SCHEMA_BYTES_FIELD = exports.SCHEMA_BYTES_FIELD_INPUT = exports.SCHEMA_POLYGON_FIELD = exports.SCHEMA_POLYGON_FIELD_INPUT = exports.SCHEMA_GEO_POINT_FIELD = exports.SCHEMA_GEO_POINT_FIELD_INPUT = exports.SCHEMA_FILE_FIELD = exports.SCHEMA_FILE_FIELD_INPUT = exports.SCHEMA_DATE_FIELD = exports.SCHEMA_DATE_FIELD_INPUT = exports.SCHEMA_OBJECT_FIELD = exports.SCHEMA_OBJECT_FIELD_INPUT = exports.SCHEMA_ARRAY_FIELD = exports.SCHEMA_ARRAY_FIELD_INPUT = exports.SCHEMA_BOOLEAN_FIELD = exports.SCHEMA_BOOLEAN_FIELD_INPUT = exports.SCHEMA_NUMBER_FIELD = exports.SCHEMA_NUMBER_FIELD_INPUT = exports.SCHEMA_STRING_FIELD = exports.SCHEMA_STRING_FIELD_INPUT = exports.SCHEMA_FIELD_INPUT = exports.SCHEMA_FIELD_NAME_ATT = void 0; + +var _graphql = require("graphql"); + +const SCHEMA_FIELD_NAME_ATT = { + description: 'This is the field name.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) +}; +exports.SCHEMA_FIELD_NAME_ATT = SCHEMA_FIELD_NAME_ATT; +const SCHEMA_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaFieldInput', + description: 'The SchemaFieldInput is used to specify a field of an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_FIELD_INPUT = SCHEMA_FIELD_INPUT; +const SCHEMA_FIELD = new _graphql.GraphQLInterfaceType({ + name: 'SchemaField', + description: 'The SchemaField interface type is used as a base type for the different supported fields of an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + }, + resolveType: value => ({ + String: SCHEMA_STRING_FIELD, + Number: SCHEMA_NUMBER_FIELD, + Boolean: SCHEMA_BOOLEAN_FIELD, + Array: SCHEMA_ARRAY_FIELD, + Object: SCHEMA_OBJECT_FIELD, + Date: SCHEMA_DATE_FIELD, + File: SCHEMA_FILE_FIELD, + GeoPoint: SCHEMA_GEO_POINT_FIELD, + Polygon: SCHEMA_POLYGON_FIELD, + Bytes: SCHEMA_BYTES_FIELD, + Pointer: SCHEMA_POINTER_FIELD, + Relation: SCHEMA_RELATION_FIELD, + ACL: SCHEMA_ACL_FIELD + })[value.type] +}); +const SCHEMA_STRING_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaStringFieldInput', + description: 'The SchemaStringFieldInput is used to specify a field of type string for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_STRING_FIELD_INPUT = SCHEMA_STRING_FIELD_INPUT; +const SCHEMA_STRING_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaStringField', + description: 'The SchemaStringField is used to return information of a String field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_STRING_FIELD = SCHEMA_STRING_FIELD; +const SCHEMA_NUMBER_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaNumberFieldInput', + description: 'The SchemaNumberFieldInput is used to specify a field of type number for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_NUMBER_FIELD_INPUT = SCHEMA_NUMBER_FIELD_INPUT; +const SCHEMA_NUMBER_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaNumberField', + description: 'The SchemaNumberField is used to return information of a Number field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_NUMBER_FIELD = SCHEMA_NUMBER_FIELD; +const SCHEMA_BOOLEAN_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaBooleanFieldInput', + description: 'The SchemaBooleanFieldInput is used to specify a field of type boolean for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_BOOLEAN_FIELD_INPUT = SCHEMA_BOOLEAN_FIELD_INPUT; +const SCHEMA_BOOLEAN_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaBooleanField', + description: 'The SchemaBooleanField is used to return information of a Boolean field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_BOOLEAN_FIELD = SCHEMA_BOOLEAN_FIELD; +const SCHEMA_ARRAY_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaArrayFieldInput', + description: 'The SchemaArrayFieldInput is used to specify a field of type array for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_ARRAY_FIELD_INPUT = SCHEMA_ARRAY_FIELD_INPUT; +const SCHEMA_ARRAY_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaArrayField', + description: 'The SchemaArrayField is used to return information of an Array field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_ARRAY_FIELD = SCHEMA_ARRAY_FIELD; +const SCHEMA_OBJECT_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaObjectFieldInput', + description: 'The SchemaObjectFieldInput is used to specify a field of type object for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_OBJECT_FIELD_INPUT = SCHEMA_OBJECT_FIELD_INPUT; +const SCHEMA_OBJECT_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaObjectField', + description: 'The SchemaObjectField is used to return information of an Object field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_OBJECT_FIELD = SCHEMA_OBJECT_FIELD; +const SCHEMA_DATE_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaDateFieldInput', + description: 'The SchemaDateFieldInput is used to specify a field of type date for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_DATE_FIELD_INPUT = SCHEMA_DATE_FIELD_INPUT; +const SCHEMA_DATE_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaDateField', + description: 'The SchemaDateField is used to return information of a Date field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_DATE_FIELD = SCHEMA_DATE_FIELD; +const SCHEMA_FILE_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaFileFieldInput', + description: 'The SchemaFileFieldInput is used to specify a field of type file for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_FILE_FIELD_INPUT = SCHEMA_FILE_FIELD_INPUT; +const SCHEMA_FILE_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaFileField', + description: 'The SchemaFileField is used to return information of a File field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_FILE_FIELD = SCHEMA_FILE_FIELD; +const SCHEMA_GEO_POINT_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaGeoPointFieldInput', + description: 'The SchemaGeoPointFieldInput is used to specify a field of type geo point for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_GEO_POINT_FIELD_INPUT = SCHEMA_GEO_POINT_FIELD_INPUT; +const SCHEMA_GEO_POINT_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaGeoPointField', + description: 'The SchemaGeoPointField is used to return information of a Geo Point field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_GEO_POINT_FIELD = SCHEMA_GEO_POINT_FIELD; +const SCHEMA_POLYGON_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaPolygonFieldInput', + description: 'The SchemaPolygonFieldInput is used to specify a field of type polygon for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_POLYGON_FIELD_INPUT = SCHEMA_POLYGON_FIELD_INPUT; +const SCHEMA_POLYGON_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaPolygonField', + description: 'The SchemaPolygonField is used to return information of a Polygon field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_POLYGON_FIELD = SCHEMA_POLYGON_FIELD; +const SCHEMA_BYTES_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaBytesFieldInput', + description: 'The SchemaBytesFieldInput is used to specify a field of type bytes for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_BYTES_FIELD_INPUT = SCHEMA_BYTES_FIELD_INPUT; +const SCHEMA_BYTES_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaBytesField', + description: 'The SchemaBytesField is used to return information of a Bytes field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_BYTES_FIELD = SCHEMA_BYTES_FIELD; +const TARGET_CLASS_ATT = { + description: 'This is the name of the target class for the field.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) +}; +exports.TARGET_CLASS_ATT = TARGET_CLASS_ATT; +const SCHEMA_POINTER_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'PointerFieldInput', + description: 'The PointerFieldInput is used to specify a field of type pointer for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT, + targetClassName: TARGET_CLASS_ATT + } +}); +exports.SCHEMA_POINTER_FIELD_INPUT = SCHEMA_POINTER_FIELD_INPUT; +const SCHEMA_POINTER_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaPointerField', + description: 'The SchemaPointerField is used to return information of a Pointer field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT, + targetClassName: TARGET_CLASS_ATT + } +}); +exports.SCHEMA_POINTER_FIELD = SCHEMA_POINTER_FIELD; +const SCHEMA_RELATION_FIELD_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'RelationFieldInput', + description: 'The RelationFieldInput is used to specify a field of type relation for an object class schema.', + fields: { + name: SCHEMA_FIELD_NAME_ATT, + targetClassName: TARGET_CLASS_ATT + } +}); +exports.SCHEMA_RELATION_FIELD_INPUT = SCHEMA_RELATION_FIELD_INPUT; +const SCHEMA_RELATION_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaRelationField', + description: 'The SchemaRelationField is used to return information of a Relation field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT, + targetClassName: TARGET_CLASS_ATT + } +}); +exports.SCHEMA_RELATION_FIELD = SCHEMA_RELATION_FIELD; +const SCHEMA_ACL_FIELD = new _graphql.GraphQLObjectType({ + name: 'SchemaACLField', + description: 'The SchemaACLField is used to return information of an ACL field.', + interfaces: [SCHEMA_FIELD], + fields: { + name: SCHEMA_FIELD_NAME_ATT + } +}); +exports.SCHEMA_ACL_FIELD = SCHEMA_ACL_FIELD; +const SCHEMA_FIELDS_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'SchemaFieldsInput', + description: `The CreateClassSchemaInput type is used to specify the schema for a new object class to be created.`, + fields: { + addStrings: { + description: 'These are the String fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_STRING_FIELD_INPUT)) + }, + addNumbers: { + description: 'These are the Number fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_NUMBER_FIELD_INPUT)) + }, + addBooleans: { + description: 'These are the Boolean fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_BOOLEAN_FIELD_INPUT)) + }, + addArrays: { + description: 'These are the Array fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_ARRAY_FIELD_INPUT)) + }, + addObjects: { + description: 'These are the Object fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_OBJECT_FIELD_INPUT)) + }, + addDates: { + description: 'These are the Date fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_DATE_FIELD_INPUT)) + }, + addFiles: { + description: 'These are the File fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_FILE_FIELD_INPUT)) + }, + addGeoPoint: { + description: 'This is the Geo Point field to be added to the class schema. Currently it is supported only one GeoPoint field per Class.', + type: SCHEMA_GEO_POINT_FIELD_INPUT + }, + addPolygons: { + description: 'These are the Polygon fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_POLYGON_FIELD_INPUT)) + }, + addBytes: { + description: 'These are the Bytes fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_BYTES_FIELD_INPUT)) + }, + addPointers: { + description: 'These are the Pointer fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_POINTER_FIELD_INPUT)) + }, + addRelations: { + description: 'These are the Relation fields to be added to the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_RELATION_FIELD_INPUT)) + }, + remove: { + description: 'These are the fields to be removed from the class schema.', + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_FIELD_INPUT)) + } + } +}); +exports.SCHEMA_FIELDS_INPUT = SCHEMA_FIELDS_INPUT; +const CLASS_NAME_ATT = { + description: 'This is the name of the object class.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) +}; +exports.CLASS_NAME_ATT = CLASS_NAME_ATT; +const CLASS = new _graphql.GraphQLObjectType({ + name: 'Class', + description: `The Class type is used to return the information about an object class.`, + fields: { + name: CLASS_NAME_ATT, + schemaFields: { + description: "These are the schema's fields of the object class.", + type: new _graphql.GraphQLNonNull(new _graphql.GraphQLList(new _graphql.GraphQLNonNull(SCHEMA_FIELD))) + } + } +}); +exports.CLASS = CLASS; + +const load = parseGraphQLSchema => { + parseGraphQLSchema.addGraphQLType(SCHEMA_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_STRING_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_STRING_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_NUMBER_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_NUMBER_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_BOOLEAN_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_BOOLEAN_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_ARRAY_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_ARRAY_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_OBJECT_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_OBJECT_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_DATE_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_DATE_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_FILE_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_FILE_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_GEO_POINT_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_GEO_POINT_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_POLYGON_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_POLYGON_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_BYTES_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_BYTES_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_POINTER_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_POINTER_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_RELATION_FIELD_INPUT, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_RELATION_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_ACL_FIELD, true); + parseGraphQLSchema.addGraphQLType(SCHEMA_FIELDS_INPUT, true); + parseGraphQLSchema.addGraphQLType(CLASS, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvc2NoZW1hVHlwZXMuanMiXSwibmFtZXMiOlsiU0NIRU1BX0ZJRUxEX05BTUVfQVRUIiwiZGVzY3JpcHRpb24iLCJ0eXBlIiwiR3JhcGhRTE5vbk51bGwiLCJHcmFwaFFMU3RyaW5nIiwiU0NIRU1BX0ZJRUxEX0lOUFVUIiwiR3JhcGhRTElucHV0T2JqZWN0VHlwZSIsIm5hbWUiLCJmaWVsZHMiLCJTQ0hFTUFfRklFTEQiLCJHcmFwaFFMSW50ZXJmYWNlVHlwZSIsInJlc29sdmVUeXBlIiwidmFsdWUiLCJTdHJpbmciLCJTQ0hFTUFfU1RSSU5HX0ZJRUxEIiwiTnVtYmVyIiwiU0NIRU1BX05VTUJFUl9GSUVMRCIsIkJvb2xlYW4iLCJTQ0hFTUFfQk9PTEVBTl9GSUVMRCIsIkFycmF5IiwiU0NIRU1BX0FSUkFZX0ZJRUxEIiwiT2JqZWN0IiwiU0NIRU1BX09CSkVDVF9GSUVMRCIsIkRhdGUiLCJTQ0hFTUFfREFURV9GSUVMRCIsIkZpbGUiLCJTQ0hFTUFfRklMRV9GSUVMRCIsIkdlb1BvaW50IiwiU0NIRU1BX0dFT19QT0lOVF9GSUVMRCIsIlBvbHlnb24iLCJTQ0hFTUFfUE9MWUdPTl9GSUVMRCIsIkJ5dGVzIiwiU0NIRU1BX0JZVEVTX0ZJRUxEIiwiUG9pbnRlciIsIlNDSEVNQV9QT0lOVEVSX0ZJRUxEIiwiUmVsYXRpb24iLCJTQ0hFTUFfUkVMQVRJT05fRklFTEQiLCJBQ0wiLCJTQ0hFTUFfQUNMX0ZJRUxEIiwiU0NIRU1BX1NUUklOR19GSUVMRF9JTlBVVCIsIkdyYXBoUUxPYmplY3RUeXBlIiwiaW50ZXJmYWNlcyIsIlNDSEVNQV9OVU1CRVJfRklFTERfSU5QVVQiLCJTQ0hFTUFfQk9PTEVBTl9GSUVMRF9JTlBVVCIsIlNDSEVNQV9BUlJBWV9GSUVMRF9JTlBVVCIsIlNDSEVNQV9PQkpFQ1RfRklFTERfSU5QVVQiLCJTQ0hFTUFfREFURV9GSUVMRF9JTlBVVCIsIlNDSEVNQV9GSUxFX0ZJRUxEX0lOUFVUIiwiU0NIRU1BX0dFT19QT0lOVF9GSUVMRF9JTlBVVCIsIlNDSEVNQV9QT0xZR09OX0ZJRUxEX0lOUFVUIiwiU0NIRU1BX0JZVEVTX0ZJRUxEX0lOUFVUIiwiVEFSR0VUX0NMQVNTX0FUVCIsIlNDSEVNQV9QT0lOVEVSX0ZJRUxEX0lOUFVUIiwidGFyZ2V0Q2xhc3NOYW1lIiwiU0NIRU1BX1JFTEFUSU9OX0ZJRUxEX0lOUFVUIiwiU0NIRU1BX0ZJRUxEU19JTlBVVCIsImFkZFN0cmluZ3MiLCJHcmFwaFFMTGlzdCIsImFkZE51bWJlcnMiLCJhZGRCb29sZWFucyIsImFkZEFycmF5cyIsImFkZE9iamVjdHMiLCJhZGREYXRlcyIsImFkZEZpbGVzIiwiYWRkR2VvUG9pbnQiLCJhZGRQb2x5Z29ucyIsImFkZEJ5dGVzIiwiYWRkUG9pbnRlcnMiLCJhZGRSZWxhdGlvbnMiLCJyZW1vdmUiLCJDTEFTU19OQU1FX0FUVCIsIkNMQVNTIiwic2NoZW1hRmllbGRzIiwibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsImFkZEdyYXBoUUxUeXBlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBU0EsTUFBTUEscUJBQXFCLEdBQUc7QUFDNUJDLEVBQUFBLFdBQVcsRUFBRSx5QkFEZTtBQUU1QkMsRUFBQUEsSUFBSSxFQUFFLElBQUlDLHVCQUFKLENBQW1CQyxzQkFBbkI7QUFGc0IsQ0FBOUI7O0FBS0EsTUFBTUMsa0JBQWtCLEdBQUcsSUFBSUMsK0JBQUosQ0FBMkI7QUFDcERDLEVBQUFBLElBQUksRUFBRSxrQkFEOEM7QUFFcEROLEVBQUFBLFdBQVcsRUFDVCw0RUFIa0Q7QUFJcERPLEVBQUFBLE1BQU0sRUFBRTtBQUNORCxJQUFBQSxJQUFJLEVBQUVQO0FBREE7QUFKNEMsQ0FBM0IsQ0FBM0I7O0FBU0EsTUFBTVMsWUFBWSxHQUFHLElBQUlDLDZCQUFKLENBQXlCO0FBQzVDSCxFQUFBQSxJQUFJLEVBQUUsYUFEc0M7QUFFNUNOLEVBQUFBLFdBQVcsRUFDVCxxSEFIMEM7QUFJNUNPLEVBQUFBLE1BQU0s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QUFuQixDQUFrQzFCLDBCQUFsQyxFQUE4RCxJQUE5RDtBQUNBeUIsRUFBQUEsa0JBQWtCLENBQUNDLGNBQW5CLENBQWtDN0Msb0JBQWxDLEVBQXdELElBQXhEO0FBQ0E0QyxFQUFBQSxrQkFBa0IsQ0FBQ0MsY0FBbkIsQ0FBa0N6Qix3QkFBbEMsRUFBNEQsSUFBNUQ7QUFDQXdCLEVBQUFBLGtCQUFrQixDQUFDQyxjQUFuQixDQUFrQzNDLGtCQUFsQyxFQUFzRCxJQUF0RDtBQUNBMEMsRUFBQUEsa0JBQWtCLENBQUNDLGNBQW5CLENBQWtDdkIsMEJBQWxDLEVBQThELElBQTlEO0FBQ0FzQixFQUFBQSxrQkFBa0IsQ0FBQ0MsY0FBbkIsQ0FBa0N6QyxvQkFBbEMsRUFBd0QsSUFBeEQ7QUFDQXdDLEVBQUFBLGtCQUFrQixDQUFDQyxjQUFuQixDQUFrQ3JCLDJCQUFsQyxFQUErRCxJQUEvRDtBQUNBb0IsRUFBQUEsa0JBQWtCLENBQUNDLGNBQW5CLENBQWtDdkMscUJBQWxDLEVBQXlELElBQXpEO0FBQ0FzQyxFQUFBQSxrQkFBa0IsQ0FBQ0MsY0FBbkIsQ0FBa0NyQyxnQkFBbEMsRUFBb0QsSUFBcEQ7QUFDQW9DLEVBQUFBLGtCQUFrQixDQUFDQyxjQUFuQixDQUFrQ3BCLG1CQUFsQyxFQUF1RCxJQUF2RDtBQUNBbUIsRUFBQUEsa0JBQWtCLENBQUNDLGNBQW5CLENBQWtDSixLQUFsQyxFQUF5QyxJQUF6QztBQUNELENBN0JEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgR3JhcGhRTE5vbk51bGwsXG4gIEdyYXBoUUxTdHJpbmcsXG4gIEdyYXBoUUxJbnB1dE9iamVjdFR5cGUsXG4gIEdyYXBoUUxMaXN0LFxuICBHcmFwaFFMT2JqZWN0VHlwZSxcbiAgR3JhcGhRTEludGVyZmFjZVR5cGUsXG59IGZyb20gJ2dyYXBocWwnO1xuXG5jb25zdCBTQ0hFTUFfRklFTERfTkFNRV9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgZmllbGQgbmFtZS4nLFxuICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFN0cmluZyksXG59O1xuXG5jb25zdCBTQ0hFTUFfRklFTERfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFGaWVsZElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFGaWVsZElucHV0IGlzIHVzZWQgdG8gc3BlY2lmeSBhIGZpZWxkIG9mIGFuIG9iamVjdCBjbGFzcyBzY2hlbWEuJyxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogU0NIRU1BX0ZJRUxEX05BTUVfQVRULFxuICB9LFxufSk7XG5cbmNvbnN0IFNDSEVNQV9GSUVMRCA9IG5ldyBHcmFwaFFMSW50ZXJmYWNlVHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFGaWVsZCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hRmllbGQgaW50ZXJmYWNlIHR5cGUgaXMgdXNlZCBhcyBhIGJhc2UgdHlwZSBmb3IgdGhlIGRpZmZlcmVudCBzdXBwb3J0ZWQgZmllbGRzIG9mIGFuIG9iamVjdCBjbGFzcyBzY2hlbWEuJyxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogU0NIRU1BX0ZJRUxEX05BTUVfQVRULFxuICB9LFxuICByZXNvbHZlVHlwZTogdmFsdWUgPT5cbiAgICAoe1xuICAgICAgU3RyaW5nOiBTQ0hFTUFfU1RSSU5HX0ZJRUxELFxuICAgICAgTnVtYmVyOiBTQ0hFTUFfTlVNQkVSX0ZJRUxELFxuICAgICAgQm9vbGVhbjogU0NIRU1BX0JPT0xFQU5fRklFTEQsXG4gICAgICBBcnJheTogU0NIRU1BX0FSUkFZX0ZJRUxELFxuICAgICAgT2JqZWN0OiBTQ0hFTUFfT0JKRUNUX0ZJRUxELFxuICAgICAgRGF0ZTogU0NIRU1BX0RBVEVfRklFTEQsXG4gICAgICBGaWxlOiBTQ0hFTUFfRklMRV9GSUVMRCxcbiAgICAgIEdlb1BvaW50OiBTQ0hFTUFfR0VPX1BPSU5UX0ZJRUxELFxuICAgICAgUG9seWdvbjogU0NIRU1BX1BPTFlHT05fRklFTEQsXG4gICAgICBCeXRlczogU0NIRU1BX0JZVEVTX0ZJRUxELFxuICAgICAgUG9pbnRlcjogU0NIRU1BX1BPSU5URVJfRklFTEQsXG4gICAgICBSZWxhdGlvbjogU0NIRU1BX1JFTEFUSU9OX0ZJRUxELFxuICAgICAgQUNMOiBTQ0hFTUFfQUNMX0ZJRUxELFxuICAgIH1bdmFsdWUudHlwZV0pLFxufSk7XG5cbmNvbnN0IFNDSEVNQV9TVFJJTkdfRklFTERfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFTdHJpbmdGaWVsZElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFTdHJpbmdGaWVsZElucHV0IGlzIHVzZWQgdG8gc3BlY2lmeSBhIGZpZWxkIG9mIHR5cGUgc3RyaW5nIGZvciBhbiBvYmplY3QgY2xhc3Mgc2NoZW1hLicsXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfU1RSSU5HX0ZJRUxEID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1NjaGVtYVN0cmluZ0ZpZWxkJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFTdHJpbmdGaWVsZCBpcyB1c2VkIHRvIHJldHVybiBpbmZvcm1hdGlvbiBvZiBhIFN0cmluZyBmaWVsZC4nLFxuICBpbnRlcmZhY2VzOiBbU0NIRU1BX0ZJRUxEXSxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogU0NIRU1BX0ZJRUxEX05BTUVfQVRULFxuICB9LFxufSk7XG5cbmNvbnN0IFNDSEVNQV9OVU1CRVJfRklFTERfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFOdW1iZXJGaWVsZElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFOdW1iZXJGaWVsZElucHV0IGlzIHVzZWQgdG8gc3BlY2lmeSBhIGZpZWxkIG9mIHR5cGUgbnVtYmVyIGZvciBhbiBvYmplY3QgY2xhc3Mgc2NoZW1hLicsXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfTlVNQkVSX0ZJRUxEID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1NjaGVtYU51bWJlckZpZWxkJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFOdW1iZXJGaWVsZCBpcyB1c2VkIHRvIHJldHVybiBpbmZvcm1hdGlvbiBvZiBhIE51bWJlciBmaWVsZC4nLFxuICBpbnRlcmZhY2VzOiBbU0NIRU1BX0ZJRUxEXSxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogU0NIRU1BX0ZJRUxEX05BTUVfQVRULFxuICB9LFxufSk7XG5cbmNvbnN0IFNDSEVNQV9CT09MRUFOX0ZJRUxEX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU2NoZW1hQm9vbGVhbkZpZWxkSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNjaGVtYUJvb2xlYW5GaWVsZElucHV0IGlzIHVzZWQgdG8gc3BlY2lmeSBhIGZpZWxkIG9mIHR5cGUgYm9vbGVhbiBmb3IgYW4gb2JqZWN0IGNsYXNzIHNjaGVtYS4nLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX0JPT0xFQU5fRklFTEQgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU2NoZW1hQm9vbGVhbkZpZWxkJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFCb29sZWFuRmllbGQgaXMgdXNlZCB0byByZXR1cm4gaW5mb3JtYXRpb24gb2YgYSBCb29sZWFuIGZpZWxkLicsXG4gIGludGVyZmFjZXM6IFtTQ0hFTUFfRklFTERdLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX0FSUkFZX0ZJRUxEX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU2NoZW1hQXJyYXlGaWVsZElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFBcnJheUZpZWxkSW5wdXQgaXMgdXNlZCB0byBzcGVjaWZ5IGEgZmllbGQgb2YgdHlwZSBhcnJheSBmb3IgYW4gb2JqZWN0IGNsYXNzIHNjaGVtYS4nLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX0FSUkFZX0ZJRUxEID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1NjaGVtYUFycmF5RmllbGQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNjaGVtYUFycmF5RmllbGQgaXMgdXNlZCB0byByZXR1cm4gaW5mb3JtYXRpb24gb2YgYW4gQXJyYXkgZmllbGQuJyxcbiAgaW50ZXJmYWNlczogW1NDSEVNQV9GSUVMRF0sXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfT0JKRUNUX0ZJRUxEX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU2NoZW1hT2JqZWN0RmllbGRJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hT2JqZWN0RmllbGRJbnB1dCBpcyB1c2VkIHRvIHNwZWNpZnkgYSBmaWVsZCBvZiB0eXBlIG9iamVjdCBmb3IgYW4gb2JqZWN0IGNsYXNzIHNjaGVtYS4nLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX09CSkVDVF9GSUVMRCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFPYmplY3RGaWVsZCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hT2JqZWN0RmllbGQgaXMgdXNlZCB0byByZXR1cm4gaW5mb3JtYXRpb24gb2YgYW4gT2JqZWN0IGZpZWxkLicsXG4gIGludGVyZmFjZXM6IFtTQ0hFTUFfRklFTERdLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX0RBVEVfRklFTERfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFEYXRlRmllbGRJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hRGF0ZUZpZWxkSW5wdXQgaXMgdXNlZCB0byBzcGVjaWZ5IGEgZmllbGQgb2YgdHlwZSBkYXRlIGZvciBhbiBvYmplY3QgY2xhc3Mgc2NoZW1hLicsXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfREFURV9GSUVMRCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFEYXRlRmllbGQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNjaGVtYURhdGVGaWVsZCBpcyB1c2VkIHRvIHJldHVybiBpbmZvcm1hdGlvbiBvZiBhIERhdGUgZmllbGQuJyxcbiAgaW50ZXJmYWNlczogW1NDSEVNQV9GSUVMRF0sXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfRklMRV9GSUVMRF9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1NjaGVtYUZpbGVGaWVsZElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFGaWxlRmllbGRJbnB1dCBpcyB1c2VkIHRvIHNwZWNpZnkgYSBmaWVsZCBvZiB0eXBlIGZpbGUgZm9yIGFuIG9iamVjdCBjbGFzcyBzY2hlbWEuJyxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogU0NIRU1BX0ZJRUxEX05BTUVfQVRULFxuICB9LFxufSk7XG5cbmNvbnN0IFNDSEVNQV9GSUxFX0ZJRUxEID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1NjaGVtYUZpbGVGaWVsZCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hRmlsZUZpZWxkIGlzIHVzZWQgdG8gcmV0dXJuIGluZm9ybWF0aW9uIG9mIGEgRmlsZSBmaWVsZC4nLFxuICBpbnRlcmZhY2VzOiBbU0NIRU1BX0ZJRUxEXSxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogU0NIRU1BX0ZJRUxEX05BTUVfQVRULFxuICB9LFxufSk7XG5cbmNvbnN0IFNDSEVNQV9HRU9fUE9JTlRfRklFTERfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFHZW9Qb2ludEZpZWxkSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNjaGVtYUdlb1BvaW50RmllbGRJbnB1dCBpcyB1c2VkIHRvIHNwZWNpZnkgYSBmaWVsZCBvZiB0eXBlIGdlbyBwb2ludCBmb3IgYW4gb2JqZWN0IGNsYXNzIHNjaGVtYS4nLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX0dFT19QT0lOVF9GSUVMRCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFHZW9Qb2ludEZpZWxkJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFHZW9Qb2ludEZpZWxkIGlzIHVzZWQgdG8gcmV0dXJuIGluZm9ybWF0aW9uIG9mIGEgR2VvIFBvaW50IGZpZWxkLicsXG4gIGludGVyZmFjZXM6IFtTQ0hFTUFfRklFTERdLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX1BPTFlHT05fRklFTERfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFQb2x5Z29uRmllbGRJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hUG9seWdvbkZpZWxkSW5wdXQgaXMgdXNlZCB0byBzcGVjaWZ5IGEgZmllbGQgb2YgdHlwZSBwb2x5Z29uIGZvciBhbiBvYmplY3QgY2xhc3Mgc2NoZW1hLicsXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfUE9MWUdPTl9GSUVMRCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFQb2x5Z29uRmllbGQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNjaGVtYVBvbHlnb25GaWVsZCBpcyB1c2VkIHRvIHJldHVybiBpbmZvcm1hdGlvbiBvZiBhIFBvbHlnb24gZmllbGQuJyxcbiAgaW50ZXJmYWNlczogW1NDSEVNQV9GSUVMRF0sXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfQllURVNfRklFTERfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFCeXRlc0ZpZWxkSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNjaGVtYUJ5dGVzRmllbGRJbnB1dCBpcyB1c2VkIHRvIHNwZWNpZnkgYSBmaWVsZCBvZiB0eXBlIGJ5dGVzIGZvciBhbiBvYmplY3QgY2xhc3Mgc2NoZW1hLicsXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfQllURVNfRklFTEQgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU2NoZW1hQnl0ZXNGaWVsZCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hQnl0ZXNGaWVsZCBpcyB1c2VkIHRvIHJldHVybiBpbmZvcm1hdGlvbiBvZiBhIEJ5dGVzIGZpZWxkLicsXG4gIGludGVyZmFjZXM6IFtTQ0hFTUFfRklFTERdLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgVEFSR0VUX0NMQVNTX0FUVCA9IHtcbiAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgY2xhc3MgZm9yIHRoZSBmaWVsZC4nLFxuICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFN0cmluZyksXG59O1xuXG5jb25zdCBTQ0hFTUFfUE9JTlRFUl9GSUVMRF9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1BvaW50ZXJGaWVsZElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBQb2ludGVyRmllbGRJbnB1dCBpcyB1c2VkIHRvIHNwZWNpZnkgYSBmaWVsZCBvZiB0eXBlIHBvaW50ZXIgZm9yIGFuIG9iamVjdCBjbGFzcyBzY2hlbWEuJyxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogU0NIRU1BX0ZJRUxEX05BTUVfQVRULFxuICAgIHRhcmdldENsYXNzTmFtZTogVEFSR0VUX0NMQVNTX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBTQ0hFTUFfUE9JTlRFUl9GSUVMRCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFQb2ludGVyRmllbGQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNjaGVtYVBvaW50ZXJGaWVsZCBpcyB1c2VkIHRvIHJldHVybiBpbmZvcm1hdGlvbiBvZiBhIFBvaW50ZXIgZmllbGQuJyxcbiAgaW50ZXJmYWNlczogW1NDSEVNQV9GSUVMRF0sXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgICB0YXJnZXRDbGFzc05hbWU6IFRBUkdFVF9DTEFTU19BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX1JFTEFUSU9OX0ZJRUxEX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnUmVsYXRpb25GaWVsZElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBSZWxhdGlvbkZpZWxkSW5wdXQgaXMgdXNlZCB0byBzcGVjaWZ5IGEgZmllbGQgb2YgdHlwZSByZWxhdGlvbiBmb3IgYW4gb2JqZWN0IGNsYXNzIHNjaGVtYS4nLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gICAgdGFyZ2V0Q2xhc3NOYW1lOiBUQVJHRVRfQ0xBU1NfQVRULFxuICB9LFxufSk7XG5cbmNvbnN0IFNDSEVNQV9SRUxBVElPTl9GSUVMRCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFSZWxhdGlvbkZpZWxkJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTY2hlbWFSZWxhdGlvbkZpZWxkIGlzIHVzZWQgdG8gcmV0dXJuIGluZm9ybWF0aW9uIG9mIGEgUmVsYXRpb24gZmllbGQuJyxcbiAgaW50ZXJmYWNlczogW1NDSEVNQV9GSUVMRF0sXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IFNDSEVNQV9GSUVMRF9OQU1FX0FUVCxcbiAgICB0YXJnZXRDbGFzc05hbWU6IFRBUkdFVF9DTEFTU19BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX0FDTF9GSUVMRCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdTY2hlbWFBQ0xGaWVsZCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgU2NoZW1hQUNMRmllbGQgaXMgdXNlZCB0byByZXR1cm4gaW5mb3JtYXRpb24gb2YgYW4gQUNMIGZpZWxkLicsXG4gIGludGVyZmFjZXM6IFtTQ0hFTUFfRklFTERdLFxuICBmaWVsZHM6IHtcbiAgICBuYW1lOiBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIH0sXG59KTtcblxuY29uc3QgU0NIRU1BX0ZJRUxEU19JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1NjaGVtYUZpZWxkc0lucHV0JyxcbiAgZGVzY3JpcHRpb246IGBUaGUgQ3JlYXRlQ2xhc3NTY2hlbWFJbnB1dCB0eXBlIGlzIHVzZWQgdG8gc3BlY2lmeSB0aGUgc2NoZW1hIGZvciBhIG5ldyBvYmplY3QgY2xhc3MgdG8gYmUgY3JlYXRlZC5gLFxuICBmaWVsZHM6IHtcbiAgICBhZGRTdHJpbmdzOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoZXNlIGFyZSB0aGUgU3RyaW5nIGZpZWxkcyB0byBiZSBhZGRlZCB0byB0aGUgY2xhc3Mgc2NoZW1hLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKFNDSEVNQV9TVFJJTkdfRklFTERfSU5QVVQpKSxcbiAgICB9LFxuICAgIGFkZE51bWJlcnM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhlc2UgYXJlIHRoZSBOdW1iZXIgZmllbGRzIHRvIGJlIGFkZGVkIHRvIHRoZSBjbGFzcyBzY2hlbWEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoU0NIRU1BX05VTUJFUl9GSUVMRF9JTlBVVCkpLFxuICAgIH0sXG4gICAgYWRkQm9vbGVhbnM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhlc2UgYXJlIHRoZSBCb29sZWFuIGZpZWxkcyB0byBiZSBhZGRlZCB0byB0aGUgY2xhc3Mgc2NoZW1hLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKFNDSEVNQV9CT09MRUFOX0ZJRUxEX0lOUFVUKSksXG4gICAgfSxcbiAgICBhZGRBcnJheXM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhlc2UgYXJlIHRoZSBBcnJheSBmaWVsZHMgdG8gYmUgYWRkZWQgdG8gdGhlIGNsYXNzIHNjaGVtYS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChTQ0hFTUFfQVJSQVlfRklFTERfSU5QVVQpKSxcbiAgICB9LFxuICAgIGFkZE9iamVjdHM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhlc2UgYXJlIHRoZSBPYmplY3QgZmllbGRzIHRvIGJlIGFkZGVkIHRvIHRoZSBjbGFzcyBzY2hlbWEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoU0NIRU1BX09CSkVDVF9GSUVMRF9JTlBVVCkpLFxuICAgIH0sXG4gICAgYWRkRGF0ZXM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlc2UgYXJlIHRoZSBEYXRlIGZpZWxkcyB0byBiZSBhZGRlZCB0byB0aGUgY2xhc3Mgc2NoZW1hLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKFNDSEVNQV9EQVRFX0ZJRUxEX0lOUFVUKSksXG4gICAgfSxcbiAgICBhZGRGaWxlczoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGVzZSBhcmUgdGhlIEZpbGUgZmllbGRzIHRvIGJlIGFkZGVkIHRvIHRoZSBjbGFzcyBzY2hlbWEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoU0NIRU1BX0ZJTEVfRklFTERfSU5QVVQpKSxcbiAgICB9LFxuICAgIGFkZEdlb1BvaW50OiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIEdlbyBQb2ludCBmaWVsZCB0byBiZSBhZGRlZCB0byB0aGUgY2xhc3Mgc2NoZW1hLiBDdXJyZW50bHkgaXQgaXMgc3VwcG9ydGVkIG9ubHkgb25lIEdlb1BvaW50IGZpZWxkIHBlciBDbGFzcy4nLFxuICAgICAgdHlwZTogU0NIRU1BX0dFT19QT0lOVF9GSUVMRF9JTlBVVCxcbiAgICB9LFxuICAgIGFkZFBvbHlnb25zOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoZXNlIGFyZSB0aGUgUG9seWdvbiBmaWVsZHMgdG8gYmUgYWRkZWQgdG8gdGhlIGNsYXNzIHNjaGVtYS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChTQ0hFTUFfUE9MWUdPTl9GSUVMRF9JTlBVVCkpLFxuICAgIH0sXG4gICAgYWRkQnl0ZXM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhlc2UgYXJlIHRoZSBCeXRlcyBmaWVsZHMgdG8gYmUgYWRkZWQgdG8gdGhlIGNsYXNzIHNjaGVtYS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChTQ0hFTUFfQllURVNfRklFTERfSU5QVVQpKSxcbiAgICB9LFxuICAgIGFkZFBvaW50ZXJzOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoZXNlIGFyZSB0aGUgUG9pbnRlciBmaWVsZHMgdG8gYmUgYWRkZWQgdG8gdGhlIGNsYXNzIHNjaGVtYS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChTQ0hFTUFfUE9JTlRFUl9GSUVMRF9JTlBVVCkpLFxuICAgIH0sXG4gICAgYWRkUmVsYXRpb25zOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoZXNlIGFyZSB0aGUgUmVsYXRpb24gZmllbGRzIHRvIGJlIGFkZGVkIHRvIHRoZSBjbGFzcyBzY2hlbWEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoU0NIRU1BX1JFTEFUSU9OX0ZJRUxEX0lOUFVUKSksXG4gICAgfSxcbiAgICByZW1vdmU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlc2UgYXJlIHRoZSBmaWVsZHMgdG8gYmUgcmVtb3ZlZCBmcm9tIHRoZSBjbGFzcyBzY2hlbWEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoU0NIRU1BX0ZJRUxEX0lOUFVUKSksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBDTEFTU19OQU1FX0FUVCA9IHtcbiAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBuYW1lIG9mIHRoZSBvYmplY3QgY2xhc3MuJyxcbiAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxufTtcblxuY29uc3QgQ0xBU1MgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICBuYW1lOiAnQ2xhc3MnLFxuICBkZXNjcmlwdGlvbjogYFRoZSBDbGFzcyB0eXBlIGlzIHVzZWQgdG8gcmV0dXJuIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBhbiBvYmplY3QgY2xhc3MuYCxcbiAgZmllbGRzOiB7XG4gICAgbmFtZTogQ0xBU1NfTkFNRV9BVFQsXG4gICAgc2NoZW1hRmllbGRzOiB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJUaGVzZSBhcmUgdGhlIHNjaGVtYSdzIGZpZWxkcyBvZiB0aGUgb2JqZWN0IGNsYXNzLlwiLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKFNDSEVNQV9GSUVMRCkpXG4gICAgICApLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgbG9hZCA9IHBhcnNlR3JhcGhRTFNjaGVtYSA9PiB7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfRklFTERfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX1NUUklOR19GSUVMRF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfU1RSSU5HX0ZJRUxELCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFNDSEVNQV9OVU1CRVJfRklFTERfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX05VTUJFUl9GSUVMRCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfQk9PTEVBTl9GSUVMRF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfQk9PTEVBTl9GSUVMRCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfQVJSQVlfRklFTERfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX0FSUkFZX0ZJRUxELCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFNDSEVNQV9PQkpFQ1RfRklFTERfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX09CSkVDVF9GSUVMRCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfREFURV9GSUVMRF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfREFURV9GSUVMRCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfRklMRV9GSUVMRF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfRklMRV9GSUVMRCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfR0VPX1BPSU5UX0ZJRUxEX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFNDSEVNQV9HRU9fUE9JTlRfRklFTEQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX1BPTFlHT05fRklFTERfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX1BPTFlHT05fRklFTEQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX0JZVEVTX0ZJRUxEX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFNDSEVNQV9CWVRFU19GSUVMRCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfUE9JTlRFUl9GSUVMRF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfUE9JTlRFUl9GSUVMRCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTQ0hFTUFfUkVMQVRJT05fRklFTERfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX1JFTEFUSU9OX0ZJRUxELCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFNDSEVNQV9BQ0xfRklFTEQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoU0NIRU1BX0ZJRUxEU19JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShDTEFTUywgdHJ1ZSk7XG59O1xuXG5leHBvcnQge1xuICBTQ0hFTUFfRklFTERfTkFNRV9BVFQsXG4gIFNDSEVNQV9GSUVMRF9JTlBVVCxcbiAgU0NIRU1BX1NUUklOR19GSUVMRF9JTlBVVCxcbiAgU0NIRU1BX1NUUklOR19GSUVMRCxcbiAgU0NIRU1BX05VTUJFUl9GSUVMRF9JTlBVVCxcbiAgU0NIRU1BX05VTUJFUl9GSUVMRCxcbiAgU0NIRU1BX0JPT0xFQU5fRklFTERfSU5QVVQsXG4gIFNDSEVNQV9CT09MRUFOX0ZJRUxELFxuICBTQ0hFTUFfQVJSQVlfRklFTERfSU5QVVQsXG4gIFNDSEVNQV9BUlJBWV9GSUVMRCxcbiAgU0NIRU1BX09CSkVDVF9GSUVMRF9JTlBVVCxcbiAgU0NIRU1BX09CSkVDVF9GSUVMRCxcbiAgU0NIRU1BX0RBVEVfRklFTERfSU5QVVQsXG4gIFNDSEVNQV9EQVRFX0ZJRUxELFxuICBTQ0hFTUFfRklMRV9GSUVMRF9JTlBVVCxcbiAgU0NIRU1BX0ZJTEVfRklFTEQsXG4gIFNDSEVNQV9HRU9fUE9JTlRfRklFTERfSU5QVVQsXG4gIFNDSEVNQV9HRU9fUE9JTlRfRklFTEQsXG4gIFNDSEVNQV9QT0xZR09OX0ZJRUxEX0lOUFVULFxuICBTQ0hFTUFfUE9MWUdPTl9GSUVMRCxcbiAgU0NIRU1BX0JZVEVTX0ZJRUxEX0lOUFVULFxuICBTQ0hFTUFfQllURVNfRklFTEQsXG4gIFRBUkdFVF9DTEFTU19BVFQsXG4gIFNDSEVNQV9QT0lOVEVSX0ZJRUxEX0lOUFVULFxuICBTQ0hFTUFfUE9JTlRFUl9GSUVMRCxcbiAgU0NIRU1BX1JFTEFUSU9OX0ZJRUxEX0lOUFVULFxuICBTQ0hFTUFfUkVMQVRJT05fRklFTEQsXG4gIFNDSEVNQV9BQ0xfRklFTEQsXG4gIFNDSEVNQV9GSUVMRFNfSU5QVVQsXG4gIENMQVNTX05BTUVfQVRULFxuICBDTEFTUyxcbiAgbG9hZCxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/GraphQL/loaders/usersMutations.js b/lib/GraphQL/loaders/usersMutations.js new file mode 100644 index 0000000000..c09349f7e1 --- /dev/null +++ b/lib/GraphQL/loaders/usersMutations.js @@ -0,0 +1,126 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _UsersRouter = _interopRequireDefault(require("../../Routers/UsersRouter")); + +var objectsMutations = _interopRequireWildcard(require("../helpers/objectsMutations")); + +var _usersQueries = require("./usersQueries"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const usersRouter = new _UsersRouter.default(); + +const load = parseGraphQLSchema => { + if (parseGraphQLSchema.isUsersClassDisabled) { + return; + } + + parseGraphQLSchema.addGraphQLMutation('signUp', { + description: 'The signUp mutation can be used to sign the user up.', + args: { + fields: { + descriptions: 'These are the fields of the user.', + type: parseGraphQLSchema.parseClassTypes['_User'].signUpInputType + } + }, + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType), + + async resolve(_source, args, context, mutationInfo) { + try { + const { + fields + } = args; + const { + config, + auth, + info + } = context; + const { + sessionToken + } = await objectsMutations.createObject('_User', fields, config, auth, info); + info.sessionToken = sessionToken; + return await (0, _usersQueries.getUserFromSessionToken)(config, info, mutationInfo); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }, true, true); + parseGraphQLSchema.addGraphQLMutation('logIn', { + description: 'The logIn mutation can be used to log the user in.', + args: { + fields: { + description: 'This is data needed to login', + type: parseGraphQLSchema.parseClassTypes['_User'].logInInputType + } + }, + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType), + + async resolve(_source, args, context) { + try { + const { + fields: { + username, + password + } + } = args; + const { + config, + auth, + info + } = context; + return (await usersRouter.handleLogIn({ + body: { + username, + password + }, + query: {}, + config, + auth, + info + })).response; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }, true, true); + parseGraphQLSchema.addGraphQLMutation('logOut', { + description: 'The logOut mutation can be used to log the user out.', + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType), + + async resolve(_source, _args, context, mutationInfo) { + try { + const { + config, + auth, + info + } = context; + const viewer = await (0, _usersQueries.getUserFromSessionToken)(config, info, mutationInfo); + await usersRouter.handleLogOut({ + config, + auth, + info + }); + return viewer; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvdXNlcnNNdXRhdGlvbnMuanMiXSwibmFtZXMiOlsidXNlcnNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJpc1VzZXJzQ2xhc3NEaXNhYmxlZCIsImFkZEdyYXBoUUxNdXRhdGlvbiIsImRlc2NyaXB0aW9uIiwiYXJncyIsImZpZWxkcyIsImRlc2NyaXB0aW9ucyIsInR5cGUiLCJwYXJzZUNsYXNzVHlwZXMiLCJzaWduVXBJbnB1dFR5cGUiLCJHcmFwaFFMTm9uTnVsbCIsInZpZXdlclR5cGUiLCJyZXNvbHZlIiwiX3NvdXJjZSIsImNvbnRleHQiLCJtdXRhdGlvbkluZm8iLCJjb25maWciLCJhdXRoIiwiaW5mbyIsInNlc3Npb25Ub2tlbiIsIm9iamVjdHNNdXRhdGlvbnMiLCJjcmVhdGVPYmplY3QiLCJlIiwiaGFuZGxlRXJyb3IiLCJsb2dJbklucHV0VHlwZSIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJoYW5kbGVMb2dJbiIsImJvZHkiLCJxdWVyeSIsInJlc3BvbnNlIiwiX2FyZ3MiLCJ2aWV3ZXIiLCJoYW5kbGVMb2dPdXQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNQSxXQUFXLEdBQUcsSUFBSUMsb0JBQUosRUFBcEI7O0FBRUEsTUFBTUMsSUFBSSxHQUFHQyxrQkFBa0IsSUFBSTtBQUNqQyxNQUFJQSxrQkFBa0IsQ0FBQ0Msb0JBQXZCLEVBQTZDO0FBQzNDO0FBQ0Q7O0FBRURELEVBQUFBLGtCQUFrQixDQUFDRSxrQkFBbkIsQ0FDRSxRQURGLEVBRUU7QUFDRUMsSUFBQUEsV0FBVyxFQUFFLHNEQURmO0FBRUVDLElBQUFBLElBQUksRUFBRTtBQUNKQyxNQUFBQSxNQUFNLEVBQUU7QUFDTkMsUUFBQUEsWUFBWSxFQUFFLG1DQURSO0FBRU5DLFFBQUFBLElBQUksRUFBRVAsa0JBQWtCLENB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O0FBQWdCQyxVQUFBQTtBQUFoQixZQUF5QkosT0FBL0I7QUFFQSxjQUFNa0IsTUFBTSxHQUFHLE1BQU0sMkNBQ25CaEIsTUFEbUIsRUFFbkJFLElBRm1CLEVBR25CSCxZQUhtQixDQUFyQjtBQU1BLGNBQU1sQixXQUFXLENBQUNvQyxZQUFaLENBQXlCO0FBQzdCakIsVUFBQUEsTUFENkI7QUFFN0JDLFVBQUFBLElBRjZCO0FBRzdCQyxVQUFBQTtBQUg2QixTQUF6QixDQUFOO0FBTUEsZUFBT2MsTUFBUDtBQUNELE9BaEJELENBZ0JFLE9BQU9WLENBQVAsRUFBVTtBQUNWdEIsUUFBQUEsa0JBQWtCLENBQUN1QixXQUFuQixDQUErQkQsQ0FBL0I7QUFDRDtBQUNGOztBQXZCSCxHQUZGLEVBMkJFLElBM0JGLEVBNEJFLElBNUJGO0FBOEJELENBN0dEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR3JhcGhRTE5vbk51bGwgfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCBVc2Vyc1JvdXRlciBmcm9tICcuLi8uLi9Sb3V0ZXJzL1VzZXJzUm91dGVyJztcbmltcG9ydCAqIGFzIG9iamVjdHNNdXRhdGlvbnMgZnJvbSAnLi4vaGVscGVycy9vYmplY3RzTXV0YXRpb25zJztcbmltcG9ydCB7IGdldFVzZXJGcm9tU2Vzc2lvblRva2VuIH0gZnJvbSAnLi91c2Vyc1F1ZXJpZXMnO1xuXG5jb25zdCB1c2Vyc1JvdXRlciA9IG5ldyBVc2Vyc1JvdXRlcigpO1xuXG5jb25zdCBsb2FkID0gcGFyc2VHcmFwaFFMU2NoZW1hID0+IHtcbiAgaWYgKHBhcnNlR3JhcGhRTFNjaGVtYS5pc1VzZXJzQ2xhc3NEaXNhYmxlZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgJ3NpZ25VcCcsXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgc2lnblVwIG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIHNpZ24gdGhlIHVzZXIgdXAuJyxcbiAgICAgIGFyZ3M6IHtcbiAgICAgICAgZmllbGRzOiB7XG4gICAgICAgICAgZGVzY3JpcHRpb25zOiAnVGhlc2UgYXJlIHRoZSBmaWVsZHMgb2YgdGhlIHVzZXIuJyxcbiAgICAgICAgICB0eXBlOiBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzWydfVXNlciddLnNpZ25VcElucHV0VHlwZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwocGFyc2VHcmFwaFFMU2NoZW1hLnZpZXdlclR5cGUpLFxuICAgICAgYXN5bmMgcmVzb2x2ZShfc291cmNlLCBhcmdzLCBjb250ZXh0LCBtdXRhdGlvbkluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGZpZWxkcyB9ID0gYXJncztcblxuICAgICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuXG4gICAgICAgICAgY29uc3QgeyBzZXNzaW9uVG9rZW4gfSA9IGF3YWl0IG9iamVjdHNNdXRhdGlvbnMuY3JlYXRlT2JqZWN0KFxuICAgICAgICAgICAgJ19Vc2VyJyxcbiAgICAgICAgICAgIGZpZWxkcyxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGluZm8uc2Vzc2lvblRva2VuID0gc2Vzc2lvblRva2VuO1xuXG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGdldFVzZXJGcm9tU2Vzc2lvblRva2VuKGNvbmZpZywgaW5mbywgbXV0YXRpb25JbmZvKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9LFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xuXG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgJ2xvZ0luJyxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBsb2dJbiBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byBsb2cgdGhlIHVzZXIgaW4uJyxcbiAgICAgIGFyZ3M6IHtcbiAgICAgICAgZmllbGRzOiB7XG4gICAgICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIGRhdGEgbmVlZGVkIHRvIGxvZ2luJyxcbiAgICAgICAgICB0eXBlOiBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzWydfVXNlciddLmxvZ0luSW5wdXRUeXBlLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChwYXJzZUdyYXBoUUxTY2hlbWEudmlld2VyVHlwZSksXG4gICAgICBhc3luYyByZXNvbHZlKF9zb3VyY2UsIGFyZ3MsIGNvbnRleHQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBmaWVsZHM6IHsgdXNlcm5hbWUsIHBhc3N3b3JkIH0sXG4gICAgICAgICAgfSA9IGFyZ3M7XG4gICAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgICByZXR1cm4gKGF3YWl0IHVzZXJzUm91dGVyLmhhbmRsZUxvZ0luKHtcbiAgICAgICAgICAgIGJvZHk6IHtcbiAgICAgICAgICAgICAgdXNlcm5hbWUsXG4gICAgICAgICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHF1ZXJ5OiB7fSxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvLFxuICAgICAgICAgIH0pKS5yZXNwb25zZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9LFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xuXG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgJ2xvZ091dCcsXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgbG9nT3V0IG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIGxvZyB0aGUgdXNlciBvdXQuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChwYXJzZUdyYXBoUUxTY2hlbWEudmlld2VyVHlwZSksXG4gICAgICBhc3luYyByZXNvbHZlKF9zb3VyY2UsIF9hcmdzLCBjb250ZXh0LCBtdXRhdGlvbkluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcblxuICAgICAgICAgIGNvbnN0IHZpZXdlciA9IGF3YWl0IGdldFVzZXJGcm9tU2Vzc2lvblRva2VuKFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgaW5mbyxcbiAgICAgICAgICAgIG11dGF0aW9uSW5mb1xuICAgICAgICAgICk7XG5cbiAgICAgICAgICBhd2FpdCB1c2Vyc1JvdXRlci5oYW5kbGVMb2dPdXQoe1xuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgIGluZm8sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4gdmlld2VyO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmhhbmRsZUVycm9yKGUpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG59O1xuXG5leHBvcnQgeyBsb2FkIH07XG4iXX0= \ No newline at end of file diff --git a/lib/GraphQL/loaders/usersQueries.js b/lib/GraphQL/loaders/usersQueries.js new file mode 100644 index 0000000000..cf504c7255 --- /dev/null +++ b/lib/GraphQL/loaders/usersQueries.js @@ -0,0 +1,74 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getUserFromSessionToken = exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlListFields = _interopRequireDefault(require("graphql-list-fields")); + +var _node = _interopRequireDefault(require("parse/node")); + +var _rest = _interopRequireDefault(require("../../rest")); + +var _Auth = _interopRequireDefault(require("../../Auth")); + +var _parseClassTypes = require("./parseClassTypes"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const getUserFromSessionToken = async (config, info, queryInfo) => { + if (!info || !info.sessionToken) { + throw new _node.default.Error(_node.default.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); + } + + const sessionToken = info.sessionToken; + const selectedFields = (0, _graphqlListFields.default)(queryInfo); + const { + include + } = (0, _parseClassTypes.extractKeysAndInclude)(selectedFields); + const response = await _rest.default.find(config, _Auth.default.master(config), '_Session', { + sessionToken + }, { + include: include.split(',').map(included => `user.${included}`).join(',') + }, info.clientVersion); + + if (!response.results || response.results.length == 0 || !response.results[0].user) { + throw new _node.default.Error(_node.default.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); + } else { + const user = response.results[0].user; + user.sessionToken = sessionToken; + return user; + } +}; + +exports.getUserFromSessionToken = getUserFromSessionToken; + +const load = parseGraphQLSchema => { + if (parseGraphQLSchema.isUsersClassDisabled) { + return; + } + + parseGraphQLSchema.addGraphQLQuery('viewer', { + description: 'The viewer query can be used to return the current user data.', + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType), + + async resolve(_source, _args, context, queryInfo) { + try { + const { + config, + info + } = context; + return await getUserFromSessionToken(config, info, queryInfo); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvdXNlcnNRdWVyaWVzLmpzIl0sIm5hbWVzIjpbImdldFVzZXJGcm9tU2Vzc2lvblRva2VuIiwiY29uZmlnIiwiaW5mbyIsInF1ZXJ5SW5mbyIsInNlc3Npb25Ub2tlbiIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJzZWxlY3RlZEZpZWxkcyIsImluY2x1ZGUiLCJyZXNwb25zZSIsInJlc3QiLCJmaW5kIiwiQXV0aCIsIm1hc3RlciIsInNwbGl0IiwibWFwIiwiaW5jbHVkZWQiLCJqb2luIiwiY2xpZW50VmVyc2lvbiIsInJlc3VsdHMiLCJsZW5ndGgiLCJ1c2VyIiwibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsImlzVXNlcnNDbGFzc0Rpc2FibGVkIiwiYWRkR3JhcGhRTFF1ZXJ5IiwiZGVzY3JpcHRpb24iLCJ0eXBlIiwiR3JhcGhRTE5vbk51bGwiLCJ2aWV3ZXJUeXBlIiwicmVzb2x2ZSIsIl9zb3VyY2UiLCJfYXJncyIsImNvbnRleHQiLCJlIiwiaGFuZGxlRXJyb3IiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLHVCQUF1QixHQUFHLE9BQU9DLE1BQVAsRUFBZUMsSUFBZixFQUFxQkMsU0FBckIsS0FBbUM7QUFDakUsTUFBSSxDQUFDRCxJQUFELElBQVMsQ0FBQ0EsSUFBSSxDQUFDRSxZQUFuQixFQUFpQztBQUMvQixVQUFNLElBQUlDLGNBQU1DLEtBQVYsQ0FDSkQsY0FBTUMsS0FBTixDQUFZQyxxQkFEUixFQUVKLHVCQUZJLENBQU47QUFJRDs7QUFDRCxRQUFNSCxZQUFZLEdBQUdGLElBQUksQ0FBQ0UsWUFBMUI7QUFDQSxRQUFNSSxjQUFjLEdBQUcsZ0NBQWNMLFNBQWQsQ0FBdkI7QUFFQSxRQUFNO0FBQUVNLElBQUFBO0FBQUYsTUFBYyw0Q0FBc0JELGNBQXRCLENBQXBCO0FBQ0EsUUFBTUUsUUFBUSxHQUFHLE1BQU1DLGNBQUtDLElBQUwsQ0FDckJYLE1BRHFCLEVBRXJCWSxjQUFLQyxNQUFMLENBQVliLE1BQVosQ0FGcUIsRUFHckIsVUFIcUIsRUFJckI7QUFBRUcsSUFBQUE7QUFBRixHQUpxQixFQUtyQjtBQUNFSyxJQUFBQSxPQUFPLEVBQUVBLE9BQU8sQ0FDYk0sS0FETSxDQUNBLEdBREEsRUFFTkMsR0FGTSxDQUVGQyxRQUFRLElBQUssUUFBT0EsUUFBUyxFQUYzQixFQUdOQyxJQUhNLENBR0QsR0FIQztBQURYLEdBTHFCLEVBV3JCaEIsSUFBSSxDQUFDaUIsYUFYZ0IsQ0FBdkI7O0FBYUEsTUFDRSxDQUFDVCxRQUFRLENBQUNVLE9BQVYsSUFDQVYsUUFBUSxDQUFDVSxPQUFULENBQWlCQyxNQUFqQixJQUEyQixDQUQzQixJQUVBLENBQUNYLFFBQVEsQ0FBQ1UsT0FBVCxDQUFpQixDQUFqQixFQUFvQkUsSUFIdkIsRUFJRTtBQUNBLFVBQU0sSUFBSWpCLGNBQU1DLEtBQVYsQ0FDSkQsY0FBTUMsS0FBTixDQUFZQyxxQkFEUixFQUVKLHVCQUZJLENBQU47QUFJRCxHQVRELE1BU087QUFDTCxVQUFNZSxJQUFJLEdBQUdaLFFBQVEsQ0FBQ1UsT0FBVCxDQUFpQixDQUFqQixFQUFvQkUsSUFBakM7QUFDQUEsSUFBQUEsSUFBSSxDQUFDbEIsWUFBTCxHQUFvQkEsWUFBcEI7QUFDQSxXQUFPa0IsSUFBUDtBQUNEO0FBQ0YsQ0F0Q0Q7Ozs7QUF3Q0EsTUFBTUMsSUFBSSxHQUFHQyxrQkFBa0IsSUFBSTtBQUNqQyxNQUFJQSxrQkFBa0IsQ0FBQ0Msb0JBQXZCLEVBQTZDO0FBQzNDO0FBQ0Q7O0FBRURELEVBQUFBLGtCQUFrQixDQUFDRSxlQUFuQixDQUNFLFFBREYsRUFFRTtBQUNFQyxJQUFBQSxXQUFXLEVBQ1QsK0RBRko7QUFHRUMsSUFBQUEsSUFBSSxFQUFFLElBQUlDLHVCQUFKLENBQW1CTCxrQkFBa0IsQ0FBQ00sVUFBdEMsQ0FIUjs7QUFJRSxVQUFNQyxPQUFOLENBQWNDLE9BQWQsRUFBdUJDLEtBQXZCLEVBQThCQyxPQUE5QixFQUF1Qy9CLFNBQXZDLEVBQWtEO0FBQ2hELFVBQUk7QUFDRixjQUFNO0FBQUVGLFVBQUFBLE1BQUY7QUFBVUMsVUFBQUE7QUFBVixZQUFtQmdDLE9BQXpCO0FBQ0EsZUFBTyxNQUFNbEMsdUJBQXVCLENBQUNDLE1BQUQsRUFBU0MsSUFBVCxFQUFlQyxTQUFmLENBQXBDO0FBQ0QsT0FIRCxDQUdFLE9BQU9nQyxDQUFQLEVBQVU7QUFDVlgsUUFBQUEsa0JBQWtCLENBQUNZLFdBQW5CLENBQStCRCxDQUEvQjtBQUNEO0FBQ0Y7O0FBWEgsR0FGRixFQWVFLElBZkYsRUFnQkUsSUFoQkY7QUFrQkQsQ0F2QkQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBHcmFwaFFMTm9uTnVsbCB9IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0IGdldEZpZWxkTmFtZXMgZnJvbSAnZ3JhcGhxbC1saXN0LWZpZWxkcyc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi8uLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4uLy4uL0F1dGgnO1xuaW1wb3J0IHsgZXh0cmFjdEtleXNBbmRJbmNsdWRlIH0gZnJvbSAnLi9wYXJzZUNsYXNzVHlwZXMnO1xuXG5jb25zdCBnZXRVc2VyRnJvbVNlc3Npb25Ub2tlbiA9IGFzeW5jIChjb25maWcsIGluZm8sIHF1ZXJ5SW5mbykgPT4ge1xuICBpZiAoIWluZm8gfHwgIWluZm8uc2Vzc2lvblRva2VuKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgJ0ludmFsaWQgc2Vzc2lvbiB0b2tlbidcbiAgICApO1xuICB9XG4gIGNvbnN0IHNlc3Npb25Ub2tlbiA9IGluZm8uc2Vzc2lvblRva2VuO1xuICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMocXVlcnlJbmZvKTtcblxuICBjb25zdCB7IGluY2x1ZGUgfSA9IGV4dHJhY3RLZXlzQW5kSW5jbHVkZShzZWxlY3RlZEZpZWxkcyk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVzdC5maW5kKFxuICAgIGNvbmZpZyxcbiAgICBBdXRoLm1hc3Rlcihjb25maWcpLFxuICAgICdfU2Vzc2lvbicsXG4gICAgeyBzZXNzaW9uVG9rZW4gfSxcbiAgICB7XG4gICAgICBpbmNsdWRlOiBpbmNsdWRlXG4gICAgICAgIC5zcGxpdCgnLCcpXG4gICAgICAgIC5tYXAoaW5jbHVkZWQgPT4gYHVzZXIuJHtpbmNsdWRlZH1gKVxuICAgICAgICAuam9pbignLCcpLFxuICAgIH0sXG4gICAgaW5mby5jbGllbnRWZXJzaW9uXG4gICk7XG4gIGlmIChcbiAgICAhcmVzcG9uc2UucmVzdWx0cyB8fFxuICAgIHJlc3BvbnNlLnJlc3VsdHMubGVuZ3RoID09IDAgfHxcbiAgICAhcmVzcG9uc2UucmVzdWx0c1swXS51c2VyXG4gICkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICdJbnZhbGlkIHNlc3Npb24gdG9rZW4nXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCB1c2VyID0gcmVzcG9uc2UucmVzdWx0c1swXS51c2VyO1xuICAgIHVzZXIuc2Vzc2lvblRva2VuID0gc2Vzc2lvblRva2VuO1xuICAgIHJldHVybiB1c2VyO1xuICB9XG59O1xuXG5jb25zdCBsb2FkID0gcGFyc2VHcmFwaFFMU2NoZW1hID0+IHtcbiAgaWYgKHBhcnNlR3JhcGhRTFNjaGVtYS5pc1VzZXJzQ2xhc3NEaXNhYmxlZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMUXVlcnkoXG4gICAgJ3ZpZXdlcicsXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGUgdmlld2VyIHF1ZXJ5IGNhbiBiZSB1c2VkIHRvIHJldHVybiB0aGUgY3VycmVudCB1c2VyIGRhdGEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChwYXJzZUdyYXBoUUxTY2hlbWEudmlld2VyVHlwZSksXG4gICAgICBhc3luYyByZXNvbHZlKF9zb3VyY2UsIF9hcmdzLCBjb250ZXh0LCBxdWVyeUluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgaW5mbyB9ID0gY29udGV4dDtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgZ2V0VXNlckZyb21TZXNzaW9uVG9rZW4oY29uZmlnLCBpbmZvLCBxdWVyeUluZm8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmhhbmRsZUVycm9yKGUpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG59O1xuXG5leHBvcnQgeyBsb2FkLCBnZXRVc2VyRnJvbVNlc3Npb25Ub2tlbiB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/parseGraphQLUtils.js b/lib/GraphQL/parseGraphQLUtils.js new file mode 100644 index 0000000000..b4ddb9cc54 --- /dev/null +++ b/lib/GraphQL/parseGraphQLUtils.js @@ -0,0 +1,80 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.enforceMasterKeyAccess = enforceMasterKeyAccess; +exports.toGraphQLError = toGraphQLError; +exports.getParseClassMutationConfig = exports.extractKeysAndInclude = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _apolloServerCore = require("apollo-server-core"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function enforceMasterKeyAccess(auth) { + if (!auth.isMaster) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'unauthorized: master key is required'); + } +} + +function toGraphQLError(error) { + let code, message; + + if (error instanceof _node.default.Error) { + code = error.code; + message = error.message; + } else { + code = _node.default.Error.INTERNAL_SERVER_ERROR; + message = 'Internal server error'; + } + + return new _apolloServerCore.ApolloError(message, code); +} + +const extractKeysAndInclude = selectedFields => { + selectedFields = selectedFields.filter(field => !field.includes('__typename')); // Handles "id" field for both current and included objects + + selectedFields = selectedFields.map(field => { + if (field === 'id') return 'objectId'; + return field.endsWith('.id') ? `${field.substring(0, field.lastIndexOf('.id'))}.objectId` : field; + }); + let keys = undefined; + let include = undefined; + + if (selectedFields.length > 0) { + keys = selectedFields.join(','); + include = selectedFields.reduce((fields, field) => { + fields = fields.slice(); + let pointIndex = field.lastIndexOf('.'); + + while (pointIndex > 0) { + const lastField = field.slice(pointIndex + 1); + field = field.slice(0, pointIndex); + + if (!fields.includes(field) && lastField !== 'objectId') { + fields.push(field); + } + + pointIndex = field.lastIndexOf('.'); + } + + return fields; + }, []).join(','); + } + + return { + keys, + include + }; +}; + +exports.extractKeysAndInclude = extractKeysAndInclude; + +const getParseClassMutationConfig = function (parseClassConfig) { + return parseClassConfig && parseClassConfig.mutation || {}; +}; + +exports.getParseClassMutationConfig = getParseClassMutationConfig; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HcmFwaFFML3BhcnNlR3JhcGhRTFV0aWxzLmpzIl0sIm5hbWVzIjpbImVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJhdXRoIiwiaXNNYXN0ZXIiLCJQYXJzZSIsIkVycm9yIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsInRvR3JhcGhRTEVycm9yIiwiZXJyb3IiLCJjb2RlIiwibWVzc2FnZSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsIkFwb2xsb0Vycm9yIiwiZXh0cmFjdEtleXNBbmRJbmNsdWRlIiwic2VsZWN0ZWRGaWVsZHMiLCJmaWx0ZXIiLCJmaWVsZCIsImluY2x1ZGVzIiwibWFwIiwiZW5kc1dpdGgiLCJzdWJzdHJpbmciLCJsYXN0SW5kZXhPZiIsImtleXMiLCJ1bmRlZmluZWQiLCJpbmNsdWRlIiwibGVuZ3RoIiwiam9pbiIsInJlZHVjZSIsImZpZWxkcyIsInNsaWNlIiwicG9pbnRJbmRleCIsImxhc3RGaWVsZCIsInB1c2giLCJnZXRQYXJzZUNsYXNzTXV0YXRpb25Db25maWciLCJwYXJzZUNsYXNzQ29uZmlnIiwibXV0YXRpb24iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBOztBQUNBOzs7O0FBRU8sU0FBU0Esc0JBQVQsQ0FBZ0NDLElBQWhDLEVBQXNDO0FBQzNDLE1BQUksQ0FBQ0EsSUFBSSxDQUFDQyxRQUFWLEVBQW9CO0FBQ2xCLFVBQU0sSUFBSUMsY0FBTUMsS0FBVixDQUNKRCxjQUFNQyxLQUFOLENBQVlDLG1CQURSLEVBRUosc0NBRkksQ0FBTjtBQUlEO0FBQ0Y7O0FBRU0sU0FBU0MsY0FBVCxDQUF3QkMsS0FBeEIsRUFBK0I7QUFDcEMsTUFBSUMsSUFBSixFQUFVQyxPQUFWOztBQUNBLE1BQUlGLEtBQUssWUFBWUosY0FBTUMsS0FBM0IsRUFBa0M7QUFDaENJLElBQUFBLElBQUksR0FBR0QsS0FBSyxDQUFDQyxJQUFiO0FBQ0FDLElBQUFBLE9BQU8sR0FBR0YsS0FBSyxDQUFDRSxPQUFoQjtBQUNELEdBSEQsTUFHTztBQUNMRCxJQUFBQSxJQUFJLEdBQUdMLGNBQU1DLEtBQU4sQ0FBWU0scUJBQW5CO0FBQ0FELElBQUFBLE9BQU8sR0FBRyx1QkFBVjtBQUNEOztBQUNELFNBQU8sSUFBSUUsNkJBQUosQ0FBZ0JGLE9BQWhCLEVBQXlCRCxJQUF6QixDQUFQO0FBQ0Q7O0FBRU0sTUFBTUkscUJBQXFCLEdBQUdDLGNBQWMsSUFBSTtBQUNyREEsRUFBQUEsY0FBYyxHQUFHQSxjQUFjLENBQUNDLE1BQWYsQ0FDZkMsS0FBSyxJQUFJLENBQUNBLEtBQUssQ0FBQ0MsUUFBTixDQUFlLFlBQWYsQ0FESyxDQUFqQixDQURxRCxDQUtyRDs7QUFDQUgsRUFBQUEsY0FBYyxHQUFHQSxjQUFjLENBQUNJLEdBQWYsQ0FBbUJGLEtBQUssSUFBSTtBQUMzQyxRQUFJQSxLQUFLLEtBQUssSUFBZCxFQUFvQixPQUFPLFVBQVA7QUFDcEIsV0FBT0EsS0FBSyxDQUFDRyxRQUFOLENBQWUsS0FBZixJQUNGLEdBQUVILEtBQUssQ0FBQ0ksU0FBTixDQUFnQixDQUFoQixFQUFtQkosS0FBSyxDQUFDSyxXQUFOLENBQWtCLEtBQWxCLENBQW5CLENBQTZDLFdBRDdDLEdBRUhMLEtBRko7QUFHRCxHQUxnQixDQUFqQjtBQU1BLE1BQUlNLElBQUksR0FBR0MsU0FBWDtBQUNBLE1BQUlDLE9BQU8sR0FBR0QsU0FBZDs7QUFDQSxNQUFJVCxjQUFjLENBQUNXLE1BQWYsR0FBd0IsQ0FBNUIsRUFBK0I7QUFDN0JILElBQUFBLElBQUksR0FBR1IsY0FBYyxDQUFDWSxJQUFmLENBQW9CLEdBQXBCLENBQVA7QUFDQUYsSUFBQUEsT0FBTyxHQUFHVixjQUFjLENBQ3JCYSxNQURPLENBQ0EsQ0FBQ0MsTUFBRCxFQUFTWixLQUFULEtBQW1CO0FBQ3pCWSxNQUFBQSxNQUFNLEdBQUdBLE1BQU0sQ0FBQ0MsS0FBUCxFQUFUO0FBQ0EsVUFBSUMsVUFBVSxHQUFHZCxLQUFLLENBQUNLLFdBQU4sQ0FBa0IsR0FBbEIsQ0FBakI7O0FBQ0EsYUFBT1MsVUFBVSxHQUFHLENBQXBCLEVBQXVCO0FBQ3JCLGNBQU1DLFNBQVMsR0FBR2YsS0FBSyxDQUFDYSxLQUFOLENBQVlDLFVBQVUsR0FBRyxDQUF6QixDQUFsQjtBQUNBZCxRQUFBQSxLQUFLLEdBQUdBLEtBQUssQ0FBQ2EsS0FBTixDQUFZLENBQVosRUFBZUMsVUFBZixDQUFSOztBQUNBLFlBQUksQ0FBQ0YsTUFBTSxDQUFDWCxRQUFQLENBQWdCRCxLQUFoQixDQUFELElBQTJCZSxTQUFTLEtBQUssVUFBN0MsRUFBeUQ7QUFDdkRILFVBQUFBLE1BQU0sQ0FBQ0ksSUFBUCxDQUFZaEIsS0FBWjtBQUNEOztBQUNEYyxRQUFBQSxVQUFVLEdBQUdkLEtBQUssQ0FBQ0ssV0FBTixDQUFrQixHQUFsQixDQUFiO0FBQ0Q7O0FBQ0QsYUFBT08sTUFBUDtBQUNELEtBYk8sRUFhTCxFQWJLLEVBY1BGLElBZE8sQ0FjRixHQWRFLENBQVY7QUFlRDs7QUFDRCxTQUFPO0FBQUVKLElBQUFBLElBQUY7QUFBUUUsSUFBQUE7QUFBUixHQUFQO0FBQ0QsQ0FqQ007Ozs7QUFtQ0EsTUFBTVMsMkJBQTJCLEdBQUcsVUFBU0MsZ0JBQVQsRUFBMkI7QUFDcEUsU0FBUUEsZ0JBQWdCLElBQUlBLGdCQUFnQixDQUFDQyxRQUF0QyxJQUFtRCxFQUExRDtBQUNELENBRk0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBBcG9sbG9FcnJvciB9IGZyb20gJ2Fwb2xsby1zZXJ2ZXItY29yZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzKGF1dGgpIHtcbiAgaWYgKCFhdXRoLmlzTWFzdGVyKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTixcbiAgICAgICd1bmF1dGhvcml6ZWQ6IG1hc3RlciBrZXkgaXMgcmVxdWlyZWQnXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9HcmFwaFFMRXJyb3IoZXJyb3IpIHtcbiAgbGV0IGNvZGUsIG1lc3NhZ2U7XG4gIGlmIChlcnJvciBpbnN0YW5jZW9mIFBhcnNlLkVycm9yKSB7XG4gICAgY29kZSA9IGVycm9yLmNvZGU7XG4gICAgbWVzc2FnZSA9IGVycm9yLm1lc3NhZ2U7XG4gIH0gZWxzZSB7XG4gICAgY29kZSA9IFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUjtcbiAgICBtZXNzYWdlID0gJ0ludGVybmFsIHNlcnZlciBlcnJvcic7XG4gIH1cbiAgcmV0dXJuIG5ldyBBcG9sbG9FcnJvcihtZXNzYWdlLCBjb2RlKTtcbn1cblxuZXhwb3J0IGNvbnN0IGV4dHJhY3RLZXlzQW5kSW5jbHVkZSA9IHNlbGVjdGVkRmllbGRzID0+IHtcbiAgc2VsZWN0ZWRGaWVsZHMgPSBzZWxlY3RlZEZpZWxkcy5maWx0ZXIoXG4gICAgZmllbGQgPT4gIWZpZWxkLmluY2x1ZGVzKCdfX3R5cGVuYW1lJylcbiAgKTtcblxuICAvLyBIYW5kbGVzIFwiaWRcIiBmaWVsZCBmb3IgYm90aCBjdXJyZW50IGFuZCBpbmNsdWRlZCBvYmplY3RzXG4gIHNlbGVjdGVkRmllbGRzID0gc2VsZWN0ZWRGaWVsZHMubWFwKGZpZWxkID0+IHtcbiAgICBpZiAoZmllbGQgPT09ICdpZCcpIHJldHVybiAnb2JqZWN0SWQnO1xuICAgIHJldHVybiBmaWVsZC5lbmRzV2l0aCgnLmlkJylcbiAgICAgID8gYCR7ZmllbGQuc3Vic3RyaW5nKDAsIGZpZWxkLmxhc3RJbmRleE9mKCcuaWQnKSl9Lm9iamVjdElkYFxuICAgICAgOiBmaWVsZDtcbiAgfSk7XG4gIGxldCBrZXlzID0gdW5kZWZpbmVkO1xuICBsZXQgaW5jbHVkZSA9IHVuZGVmaW5lZDtcbiAgaWYgKHNlbGVjdGVkRmllbGRzLmxlbmd0aCA+IDApIHtcbiAgICBrZXlzID0gc2VsZWN0ZWRGaWVsZHMuam9pbignLCcpO1xuICAgIGluY2x1ZGUgPSBzZWxlY3RlZEZpZWxkc1xuICAgICAgLnJlZHVjZSgoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgICBmaWVsZHMgPSBmaWVsZHMuc2xpY2UoKTtcbiAgICAgICAgbGV0IHBvaW50SW5kZXggPSBmaWVsZC5sYXN0SW5kZXhPZignLicpO1xuICAgICAgICB3aGlsZSAocG9pbnRJbmRleCA+IDApIHtcbiAgICAgICAgICBjb25zdCBsYXN0RmllbGQgPSBmaWVsZC5zbGljZShwb2ludEluZGV4ICsgMSk7XG4gICAgICAgICAgZmllbGQgPSBmaWVsZC5zbGljZSgwLCBwb2ludEluZGV4KTtcbiAgICAgICAgICBpZiAoIWZpZWxkcy5pbmNsdWRlcyhmaWVsZCkgJiYgbGFzdEZpZWxkICE9PSAnb2JqZWN0SWQnKSB7XG4gICAgICAgICAgICBmaWVsZHMucHVzaChmaWVsZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHBvaW50SW5kZXggPSBmaWVsZC5sYXN0SW5kZXhPZignLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaWVsZHM7XG4gICAgICB9LCBbXSlcbiAgICAgIC5qb2luKCcsJyk7XG4gIH1cbiAgcmV0dXJuIHsga2V5cywgaW5jbHVkZSB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFBhcnNlQ2xhc3NNdXRhdGlvbkNvbmZpZyA9IGZ1bmN0aW9uKHBhcnNlQ2xhc3NDb25maWcpIHtcbiAgcmV0dXJuIChwYXJzZUNsYXNzQ29uZmlnICYmIHBhcnNlQ2xhc3NDb25maWcubXV0YXRpb24pIHx8IHt9O1xufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/transformers/className.js b/lib/GraphQL/transformers/className.js new file mode 100644 index 0000000000..a3b221d3fe --- /dev/null +++ b/lib/GraphQL/transformers/className.js @@ -0,0 +1,17 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformClassNameToGraphQL = void 0; + +const transformClassNameToGraphQL = className => { + if (className[0] === '_') { + className = className.slice(1); + } + + return className[0].toUpperCase() + className.slice(1); +}; + +exports.transformClassNameToGraphQL = transformClassNameToGraphQL; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9jbGFzc05hbWUuanMiXSwibmFtZXMiOlsidHJhbnNmb3JtQ2xhc3NOYW1lVG9HcmFwaFFMIiwiY2xhc3NOYW1lIiwic2xpY2UiLCJ0b1VwcGVyQ2FzZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBLE1BQU1BLDJCQUEyQixHQUFHQyxTQUFTLElBQUk7QUFDL0MsTUFBSUEsU0FBUyxDQUFDLENBQUQsQ0FBVCxLQUFpQixHQUFyQixFQUEwQjtBQUN4QkEsSUFBQUEsU0FBUyxHQUFHQSxTQUFTLENBQUNDLEtBQVYsQ0FBZ0IsQ0FBaEIsQ0FBWjtBQUNEOztBQUNELFNBQU9ELFNBQVMsQ0FBQyxDQUFELENBQVQsQ0FBYUUsV0FBYixLQUE2QkYsU0FBUyxDQUFDQyxLQUFWLENBQWdCLENBQWhCLENBQXBDO0FBQ0QsQ0FMRCIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHRyYW5zZm9ybUNsYXNzTmFtZVRvR3JhcGhRTCA9IGNsYXNzTmFtZSA9PiB7XG4gIGlmIChjbGFzc05hbWVbMF0gPT09ICdfJykge1xuICAgIGNsYXNzTmFtZSA9IGNsYXNzTmFtZS5zbGljZSgxKTtcbiAgfVxuICByZXR1cm4gY2xhc3NOYW1lWzBdLnRvVXBwZXJDYXNlKCkgKyBjbGFzc05hbWUuc2xpY2UoMSk7XG59O1xuXG5leHBvcnQgeyB0cmFuc2Zvcm1DbGFzc05hbWVUb0dyYXBoUUwgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/transformers/constraintType.js b/lib/GraphQL/transformers/constraintType.js new file mode 100644 index 0000000000..cdf220ee49 --- /dev/null +++ b/lib/GraphQL/transformers/constraintType.js @@ -0,0 +1,63 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformConstraintTypeToGraphQL = void 0; + +var defaultGraphQLTypes = _interopRequireWildcard(require("../loaders/defaultGraphQLTypes")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +const transformConstraintTypeToGraphQL = (parseType, targetClass, parseClassTypes) => { + switch (parseType) { + case 'String': + return defaultGraphQLTypes.STRING_WHERE_INPUT; + + case 'Number': + return defaultGraphQLTypes.NUMBER_WHERE_INPUT; + + case 'Boolean': + return defaultGraphQLTypes.BOOLEAN_WHERE_INPUT; + + case 'Array': + return defaultGraphQLTypes.ARRAY_WHERE_INPUT; + + case 'Object': + return defaultGraphQLTypes.OBJECT_WHERE_INPUT; + + case 'Date': + return defaultGraphQLTypes.DATE_WHERE_INPUT; + + case 'Pointer': + if (parseClassTypes[targetClass] && parseClassTypes[targetClass].classGraphQLConstraintType) { + return parseClassTypes[targetClass].classGraphQLConstraintType; + } else { + return defaultGraphQLTypes.OBJECT; + } + + case 'File': + return defaultGraphQLTypes.FILE_WHERE_INPUT; + + case 'GeoPoint': + return defaultGraphQLTypes.GEO_POINT_WHERE_INPUT; + + case 'Polygon': + return defaultGraphQLTypes.POLYGON_WHERE_INPUT; + + case 'Bytes': + return defaultGraphQLTypes.BYTES_WHERE_INPUT; + + case 'ACL': + return defaultGraphQLTypes.OBJECT_WHERE_INPUT; + + case 'Relation': + default: + return undefined; + } +}; + +exports.transformConstraintTypeToGraphQL = transformConstraintTypeToGraphQL; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9jb25zdHJhaW50VHlwZS5qcyJdLCJuYW1lcyI6WyJ0cmFuc2Zvcm1Db25zdHJhaW50VHlwZVRvR3JhcGhRTCIsInBhcnNlVHlwZSIsInRhcmdldENsYXNzIiwicGFyc2VDbGFzc1R5cGVzIiwiZGVmYXVsdEdyYXBoUUxUeXBlcyIsIlNUUklOR19XSEVSRV9JTlBVVCIsIk5VTUJFUl9XSEVSRV9JTlBVVCIsIkJPT0xFQU5fV0hFUkVfSU5QVVQiLCJBUlJBWV9XSEVSRV9JTlBVVCIsIk9CSkVDVF9XSEVSRV9JTlBVVCIsIkRBVEVfV0hFUkVfSU5QVVQiLCJjbGFzc0dyYXBoUUxDb25zdHJhaW50VHlwZSIsIk9CSkVDVCIsIkZJTEVfV0hFUkVfSU5QVVQiLCJHRU9fUE9JTlRfV0hFUkVfSU5QVVQiLCJQT0xZR09OX1dIRVJFX0lOUFVUIiwiQllURVNfV0hFUkVfSU5QVVQiLCJ1bmRlZmluZWQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7O0FBRUEsTUFBTUEsZ0NBQWdDLEdBQUcsQ0FDdkNDLFNBRHVDLEVBRXZDQyxXQUZ1QyxFQUd2Q0MsZUFIdUMsS0FJcEM7QUFDSCxVQUFRRixTQUFSO0FBQ0UsU0FBSyxRQUFMO0FBQ0UsYUFBT0csbUJBQW1CLENBQUNDLGtCQUEzQjs7QUFDRixTQUFLLFFBQUw7QUFDRSxhQUFPRCxtQkFBbUIsQ0FBQ0Usa0JBQTNCOztBQUNGLFNBQUssU0FBTDtBQUNFLGFBQU9GLG1CQUFtQixDQUFDRyxtQkFBM0I7O0FBQ0YsU0FBSyxPQUFMO0FBQ0UsYUFBT0gsbUJBQW1CLENBQUNJLGlCQUEzQjs7QUFDRixTQUFLLFFBQUw7QUFDRSxhQUFPSixtQkFBbUIsQ0FBQ0ssa0JBQTNCOztBQUNGLFNBQUssTUFBTDtBQUNFLGFBQU9MLG1CQUFtQixDQUFDTSxnQkFBM0I7O0FBQ0YsU0FBSyxTQUFMO0FBQ0UsVUFDRVAsZUFBZSxDQUFDRCxXQUFELENBQWYsSUFDQUMsZUFBZSxDQUFDRCxXQUFELENBQWYsQ0FBNkJTLDBCQUYvQixFQUdFO0FBQ0EsZUFBT1IsZUFBZSxDQUFDRCxXQUFELENBQWYsQ0FBNkJTLDBCQUFwQztBQUNELE9BTEQsTUFLTztBQUNMLGVBQU9QLG1CQUFtQixDQUFDUSxNQUEzQjtBQUNEOztBQUNILFNBQUssTUFBTDtBQUNFLGFBQU9SLG1CQUFtQixDQUFDUyxnQkFBM0I7O0FBQ0YsU0FBSyxVQUFMO0FBQ0UsYUFBT1QsbUJBQW1CLENBQUNVLHFCQUEzQjs7QUFDRixTQUFLLFNBQUw7QUFDRSxhQUFPVixtQkFBbUIsQ0FBQ1csbUJBQTNCOztBQUNGLFNBQUssT0FBTDtBQUNFLGFBQU9YLG1CQUFtQixDQUFDWSxpQkFBM0I7O0FBQ0YsU0FBSyxLQUFMO0FBQ0UsYUFBT1osbUJBQW1CLENBQUNLLGtCQUEzQjs7QUFDRixTQUFLLFVBQUw7QUFDQTtBQUNFLGFBQU9RLFNBQVA7QUFsQ0o7QUFvQ0QsQ0F6Q0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4uL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5cbmNvbnN0IHRyYW5zZm9ybUNvbnN0cmFpbnRUeXBlVG9HcmFwaFFMID0gKFxuICBwYXJzZVR5cGUsXG4gIHRhcmdldENsYXNzLFxuICBwYXJzZUNsYXNzVHlwZXNcbikgPT4ge1xuICBzd2l0Y2ggKHBhcnNlVHlwZSkge1xuICAgIGNhc2UgJ1N0cmluZyc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5TVFJJTkdfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnTnVtYmVyJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk5VTUJFUl9XSEVSRV9JTlBVVDtcbiAgICBjYXNlICdCb29sZWFuJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkJPT0xFQU5fV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuQVJSQVlfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnT2JqZWN0JzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVF9XSEVSRV9JTlBVVDtcbiAgICBjYXNlICdEYXRlJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkRBVEVfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10gJiZcbiAgICAgICAgcGFyc2VDbGFzc1R5cGVzW3RhcmdldENsYXNzXS5jbGFzc0dyYXBoUUxDb25zdHJhaW50VHlwZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdLmNsYXNzR3JhcGhRTENvbnN0cmFpbnRUeXBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuICAgICAgfVxuICAgIGNhc2UgJ0ZpbGUnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuRklMRV9XSEVSRV9JTlBVVDtcbiAgICBjYXNlICdHZW9Qb2ludCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5HRU9fUE9JTlRfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5QT0xZR09OX1dIRVJFX0lOUFVUO1xuICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkJZVEVTX1dIRVJFX0lOUFVUO1xuICAgIGNhc2UgJ0FDTCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1RfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnUmVsYXRpb24nOlxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG5leHBvcnQgeyB0cmFuc2Zvcm1Db25zdHJhaW50VHlwZVRvR3JhcGhRTCB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/transformers/inputType.js b/lib/GraphQL/transformers/inputType.js new file mode 100644 index 0000000000..e11681a9b0 --- /dev/null +++ b/lib/GraphQL/transformers/inputType.js @@ -0,0 +1,71 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformInputTypeToGraphQL = void 0; + +var _graphql = require("graphql"); + +var defaultGraphQLTypes = _interopRequireWildcard(require("../loaders/defaultGraphQLTypes")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +const transformInputTypeToGraphQL = (parseType, targetClass, parseClassTypes) => { + switch (parseType) { + case 'String': + return _graphql.GraphQLString; + + case 'Number': + return _graphql.GraphQLFloat; + + case 'Boolean': + return _graphql.GraphQLBoolean; + + case 'Array': + return new _graphql.GraphQLList(defaultGraphQLTypes.ANY); + + case 'Object': + return defaultGraphQLTypes.OBJECT; + + case 'Date': + return defaultGraphQLTypes.DATE; + + case 'Pointer': + if (parseClassTypes && parseClassTypes[targetClass] && parseClassTypes[targetClass].classGraphQLPointerType) { + return parseClassTypes[targetClass].classGraphQLPointerType; + } else { + return defaultGraphQLTypes.OBJECT; + } + + case 'Relation': + if (parseClassTypes && parseClassTypes[targetClass] && parseClassTypes[targetClass].classGraphQLRelationType) { + return parseClassTypes[targetClass].classGraphQLRelationType; + } else { + return defaultGraphQLTypes.OBJECT; + } + + case 'File': + return defaultGraphQLTypes.FILE; + + case 'GeoPoint': + return defaultGraphQLTypes.GEO_POINT_INPUT; + + case 'Polygon': + return defaultGraphQLTypes.POLYGON_INPUT; + + case 'Bytes': + return defaultGraphQLTypes.BYTES; + + case 'ACL': + return defaultGraphQLTypes.ACL_INPUT; + + default: + return undefined; + } +}; + +exports.transformInputTypeToGraphQL = transformInputTypeToGraphQL; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9pbnB1dFR5cGUuanMiXSwibmFtZXMiOlsidHJhbnNmb3JtSW5wdXRUeXBlVG9HcmFwaFFMIiwicGFyc2VUeXBlIiwidGFyZ2V0Q2xhc3MiLCJwYXJzZUNsYXNzVHlwZXMiLCJHcmFwaFFMU3RyaW5nIiwiR3JhcGhRTEZsb2F0IiwiR3JhcGhRTEJvb2xlYW4iLCJHcmFwaFFMTGlzdCIsImRlZmF1bHRHcmFwaFFMVHlwZXMiLCJBTlkiLCJPQkpFQ1QiLCJEQVRFIiwiY2xhc3NHcmFwaFFMUG9pbnRlclR5cGUiLCJjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGUiLCJGSUxFIiwiR0VPX1BPSU5UX0lOUFVUIiwiUE9MWUdPTl9JTlBVVCIsIkJZVEVTIiwiQUNMX0lOUFVUIiwidW5kZWZpbmVkIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBTUE7Ozs7OztBQUVBLE1BQU1BLDJCQUEyQixHQUFHLENBQ2xDQyxTQURrQyxFQUVsQ0MsV0FGa0MsRUFHbENDLGVBSGtDLEtBSS9CO0FBQ0gsVUFBUUYsU0FBUjtBQUNFLFNBQUssUUFBTDtBQUNFLGFBQU9HLHNCQUFQOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9DLHFCQUFQOztBQUNGLFNBQUssU0FBTDtBQUNFLGFBQU9DLHVCQUFQOztBQUNGLFNBQUssT0FBTDtBQUNFLGFBQU8sSUFBSUMsb0JBQUosQ0FBZ0JDLG1CQUFtQixDQUFDQyxHQUFwQyxDQUFQOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9ELG1CQUFtQixDQUFDRSxNQUEzQjs7QUFDRixTQUFLLE1BQUw7QUFDRSxhQUFPRixtQkFBbUIsQ0FBQ0csSUFBM0I7O0FBQ0YsU0FBSyxTQUFMO0FBQ0UsVUFDRVIsZUFBZSxJQUNmQSxlQUFlLENBQUNELFdBQUQsQ0FEZixJQUVBQyxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlUsdUJBSC9CLEVBSUU7QUFDQSxlQUFPVCxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlUsdUJBQXBDO0FBQ0QsT0FORCxNQU1PO0FBQ0wsZUFBT0osbUJBQW1CLENBQUNFLE1BQTNCO0FBQ0Q7O0FBQ0gsU0FBSyxVQUFMO0FBQ0UsVUFDRVAsZUFBZSxJQUNmQSxlQUFlLENBQUNELFdBQUQsQ0FEZixJQUVBQyxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2Qlcsd0JBSC9CLEVBSUU7QUFDQSxlQUFPVixlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2Qlcsd0JBQXBDO0FBQ0QsT0FORCxNQU1PO0FBQ0wsZUFBT0wsbUJBQW1CLENBQUNFLE1BQTNCO0FBQ0Q7O0FBQ0gsU0FBSyxNQUFMO0FBQ0UsYUFBT0YsbUJBQW1CLENBQUNNLElBQTNCOztBQUNGLFNBQUssVUFBTDtBQUNFLGFBQU9OLG1CQUFtQixDQUFDTyxlQUEzQjs7QUFDRixTQUFLLFNBQUw7QUFDRSxhQUFPUCxtQkFBbUIsQ0FBQ1EsYUFBM0I7O0FBQ0YsU0FBSyxPQUFMO0FBQ0UsYUFBT1IsbUJBQW1CLENBQUNTLEtBQTNCOztBQUNGLFNBQUssS0FBTDtBQUNFLGFBQU9ULG1CQUFtQixDQUFDVSxTQUEzQjs7QUFDRjtBQUNFLGFBQU9DLFNBQVA7QUE1Q0o7QUE4Q0QsQ0FuREQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBHcmFwaFFMU3RyaW5nLFxuICBHcmFwaFFMRmxvYXQsXG4gIEdyYXBoUUxCb29sZWFuLFxuICBHcmFwaFFMTGlzdCxcbn0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4uL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5cbmNvbnN0IHRyYW5zZm9ybUlucHV0VHlwZVRvR3JhcGhRTCA9IChcbiAgcGFyc2VUeXBlLFxuICB0YXJnZXRDbGFzcyxcbiAgcGFyc2VDbGFzc1R5cGVzXG4pID0+IHtcbiAgc3dpdGNoIChwYXJzZVR5cGUpIHtcbiAgICBjYXNlICdTdHJpbmcnOlxuICAgICAgcmV0dXJuIEdyYXBoUUxTdHJpbmc7XG4gICAgY2FzZSAnTnVtYmVyJzpcbiAgICAgIHJldHVybiBHcmFwaFFMRmxvYXQ7XG4gICAgY2FzZSAnQm9vbGVhbic6XG4gICAgICByZXR1cm4gR3JhcGhRTEJvb2xlYW47XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuIG5ldyBHcmFwaFFMTGlzdChkZWZhdWx0R3JhcGhRTFR5cGVzLkFOWSk7XG4gICAgY2FzZSAnT2JqZWN0JzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcbiAgICBjYXNlICdEYXRlJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkRBVEU7XG4gICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlcyAmJlxuICAgICAgICBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMUG9pbnRlclR5cGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gcGFyc2VDbGFzc1R5cGVzW3RhcmdldENsYXNzXS5jbGFzc0dyYXBoUUxQb2ludGVyVHlwZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcbiAgICAgIH1cbiAgICBjYXNlICdSZWxhdGlvbic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlcyAmJlxuICAgICAgICBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMUmVsYXRpb25UeXBlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMUmVsYXRpb25UeXBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuICAgICAgfVxuICAgIGNhc2UgJ0ZpbGUnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuRklMRTtcbiAgICBjYXNlICdHZW9Qb2ludCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5HRU9fUE9JTlRfSU5QVVQ7XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5QT0xZR09OX0lOUFVUO1xuICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkJZVEVTO1xuICAgIGNhc2UgJ0FDTCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5BQ0xfSU5QVVQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn07XG5cbmV4cG9ydCB7IHRyYW5zZm9ybUlucHV0VHlwZVRvR3JhcGhRTCB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/transformers/mutation.js b/lib/GraphQL/transformers/mutation.js new file mode 100644 index 0000000000..e2747f31c4 --- /dev/null +++ b/lib/GraphQL/transformers/mutation.js @@ -0,0 +1,207 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformTypes = void 0; + +var defaultGraphQLTypes = _interopRequireWildcard(require("../loaders/defaultGraphQLTypes")); + +var objectsMutations = _interopRequireWildcard(require("../helpers/objectsMutations")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const transformTypes = async (inputType, fields, { + className, + parseGraphQLSchema, + req +}) => { + const { + classGraphQLCreateType, + classGraphQLUpdateType, + config: { + isCreateEnabled, + isUpdateEnabled + } + } = parseGraphQLSchema.parseClassTypes[className]; + const parseClass = parseGraphQLSchema.parseClasses.find(clazz => clazz.className === className); + + if (fields) { + const classGraphQLCreateTypeFields = isCreateEnabled && classGraphQLCreateType ? classGraphQLCreateType.getFields() : null; + const classGraphQLUpdateTypeFields = isUpdateEnabled && classGraphQLUpdateType ? classGraphQLUpdateType.getFields() : null; + const promises = Object.keys(fields).map(async field => { + let inputTypeField; + + if (inputType === 'create' && classGraphQLCreateTypeFields) { + inputTypeField = classGraphQLCreateTypeFields[field]; + } else if (classGraphQLUpdateTypeFields) { + inputTypeField = classGraphQLUpdateTypeFields[field]; + } + + if (inputTypeField) { + switch (true) { + case inputTypeField.type === defaultGraphQLTypes.GEO_POINT_INPUT: + fields[field] = transformers.geoPoint(fields[field]); + break; + + case inputTypeField.type === defaultGraphQLTypes.POLYGON_INPUT: + fields[field] = transformers.polygon(fields[field]); + break; + + case parseClass.fields[field].type === 'Relation': + fields[field] = await transformers.relation(parseClass.fields[field].targetClass, field, fields[field], parseGraphQLSchema, req); + break; + + case parseClass.fields[field].type === 'Pointer': + fields[field] = await transformers.pointer(parseClass.fields[field].targetClass, field, fields[field], parseGraphQLSchema, req); + break; + } + } + }); + await Promise.all(promises); + if (fields.ACL) fields.ACL = transformers.ACL(fields.ACL); + } + + return fields; +}; + +exports.transformTypes = transformTypes; +const transformers = { + polygon: value => ({ + __type: 'Polygon', + coordinates: value.map(geoPoint => [geoPoint.latitude, geoPoint.longitude]) + }), + geoPoint: value => _objectSpread({}, value, { + __type: 'GeoPoint' + }), + ACL: value => { + const parseACL = {}; + + if (value.public) { + parseACL['*'] = { + read: value.public.read, + write: value.public.write + }; + } + + if (value.users) { + value.users.forEach(rule => { + parseACL[rule.userId] = { + read: rule.read, + write: rule.write + }; + }); + } + + if (value.roles) { + value.roles.forEach(rule => { + parseACL[`role:${rule.roleName}`] = { + read: rule.read, + write: rule.write + }; + }); + } + + return parseACL; + }, + relation: async (targetClass, field, value, parseGraphQLSchema, { + config, + auth, + info + }) => { + if (Object.keys(value) === 0) throw new Error(`You need to provide atleast one operation on the relation mutation of field ${field}`); + const op = { + __op: 'Batch', + ops: [] + }; + let nestedObjectsToAdd = []; + + if (value.createAndAdd) { + nestedObjectsToAdd = (await Promise.all(value.createAndAdd.map(async input => { + const parseFields = await transformTypes('create', input, { + className: targetClass, + parseGraphQLSchema, + req: { + config, + auth, + info + } + }); + return objectsMutations.createObject(targetClass, parseFields, config, auth, info); + }))).map(object => ({ + __type: 'Pointer', + className: targetClass, + objectId: object.objectId + })); + } + + if (value.add || nestedObjectsToAdd.length > 0) { + if (!value.add) value.add = []; + value.add = value.add.map(input => ({ + __type: 'Pointer', + className: targetClass, + objectId: input + })); + op.ops.push({ + __op: 'AddRelation', + objects: [...value.add, ...nestedObjectsToAdd] + }); + } + + if (value.remove) { + op.ops.push({ + __op: 'RemoveRelation', + objects: value.remove.map(input => ({ + __type: 'Pointer', + className: targetClass, + objectId: input + })) + }); + } + + return op; + }, + pointer: async (targetClass, field, value, parseGraphQLSchema, { + config, + auth, + info + }) => { + if (Object.keys(value) > 1 || Object.keys(value) === 0) throw new Error(`You need to provide link OR createLink on the pointer mutation of field ${field}`); + let nestedObjectToAdd; + + if (value.createAndLink) { + const parseFields = await transformTypes('create', value.createAndLink, { + className: targetClass, + parseGraphQLSchema, + req: { + config, + auth, + info + } + }); + nestedObjectToAdd = await objectsMutations.createObject(targetClass, parseFields, config, auth, info); + return { + __type: 'Pointer', + className: targetClass, + objectId: nestedObjectToAdd.objectId + }; + } + + if (value.link) { + return { + __type: 'Pointer', + className: targetClass, + objectId: value.link + }; + } + } +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9tdXRhdGlvbi5qcyJdLCJuYW1lcyI6WyJ0cmFuc2Zvcm1UeXBlcyIsImlucHV0VHlwZSIsImZpZWxkcyIsImNsYXNzTmFtZSIsInBhcnNlR3JhcGhRTFNjaGVtYSIsInJlcSIsImNsYXNzR3JhcGhRTENyZWF0ZVR5cGUiLCJjbGFzc0dyYXBoUUxVcGRhdGVUeXBlIiwiY29uZmlnIiwiaXNDcmVhdGVFbmFibGVkIiwiaXNVcGRhdGVFbmFibGVkIiwicGFyc2VDbGFzc1R5cGVzIiwicGFyc2VDbGFzcyIsInBhcnNlQ2xhc3NlcyIsImZpbmQiLCJjbGF6eiIsImNsYXNzR3JhcGhRTENyZWF0ZVR5cGVGaWVsZHMiLCJnZXRGaWVsZHMiLCJjbGFzc0dyYXBoUUxVcGRhdGVUeXBlRmllbGRzIiwicHJvbWlzZXMiLCJPYmplY3QiLCJrZXlzIiwibWFwIiwiZmllbGQiLCJpbnB1dFR5cGVGaWVsZCIsInR5cGUiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiR0VPX1BPSU5UX0lOUFVUIiwidHJhbnNmb3JtZXJzIiwiZ2VvUG9pbnQiLCJQT0xZR09OX0lOUFVUIiwicG9seWdvbiIsInJlbGF0aW9uIiwidGFyZ2V0Q2xhc3MiLCJwb2ludGVyIiwiUHJvbWlzZSIsImFsbCIsIkFDTCIsInZhbHVlIiwiX190eXBlIiwiY29vcmRpbmF0ZXMiLCJsYXRpdHVkZSIsImxvbmdpdHVkZSIsInBhcnNlQUNMIiwicHVibGljIiwicmVhZCIsIndyaXRlIiwidXNlcnMiLCJmb3JFYWNoIiwicnVsZSIsInVzZXJJZCIsInJvbGVzIiwicm9sZU5hbWUiLCJhdXRoIiwiaW5mbyIsIkVycm9yIiwib3AiLCJfX29wIiwib3BzIiwibmVzdGVkT2JqZWN0c1RvQWRkIiwiY3JlYXRlQW5kQWRkIiwiaW5wdXQiLCJwYXJzZUZpZWxkcyIsIm9iamVjdHNNdXRhdGlvbnMiLCJjcmVhdGVPYmplY3QiLCJvYmplY3QiLCJvYmplY3RJZCIsImFkZCIsImxlbmd0aCIsInB1c2giLCJvYmplY3RzIiwicmVtb3ZlIiwibmVzdGVkT2JqZWN0VG9BZGQiLCJjcmVhdGVBbmRMaW5rIiwibGluayJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7Ozs7Ozs7Ozs7QUFFQSxNQUFNQSxjQUFjLEdBQUcsT0FDckJDLFNBRHFCLEVBRXJCQyxNQUZxQixFQUdyQjtBQUFFQyxFQUFBQSxTQUFGO0FBQWFDLEVBQUFBLGtCQUFiO0FBQWlDQyxFQUFBQTtBQUFqQyxDQUhxQixLQUlsQjtBQUNILFFBQU07QUFDSkMsSUFBQUEsc0JBREk7QUFFSkMsSUFBQUEsc0JBRkk7QUFHSkMsSUFBQUEsTUFBTSxFQUFFO0FBQUVDLE1BQUFBLGVBQUY7QUFBbUJDLE1BQUFBO0FBQW5CO0FBSEosTUFJRk4sa0JBQWtCLENBQUNPLGVBQW5CLENBQW1DUixTQUFuQyxDQUpKO0FBS0EsUUFBTVMsVUFBVSxHQUFHUixrQkFBa0IsQ0FBQ1MsWUFBbkIsQ0FBZ0NDLElBQWhDLENBQ2pCQyxLQUFLLElBQUlBLEtBQUssQ0FBQ1osU0FBTixLQUFvQkEsU0FEWixDQUFuQjs7QUFHQSxNQUFJRCxNQUFKLEVBQVk7QUFDVixVQUFNYyw0QkFBNEIsR0FDaENQLGVBQWUsSUFBSUgsc0JBQW5CLEdBQ0lBLHNCQUFzQixDQUFDVyxTQUF2QixFQURKLEdBRUksSUFITjtBQUlBLFVBQU1DLDRCQUE0QixHQUNoQ1IsZUFBZSxJQUFJSCxzQkFBbkIsR0FDSUEsc0JBQXNCLENBQUNVLFNBQXZCLEVBREosR0FFSSxJQUhOO0FBSUEsVUFBTUUsUUFBUSxHQUFHQyxNQUFNLENBQUNDLElBQVAsQ0FBWW5CLE1BQVosRUFBb0JvQixHQUFwQixDQUF3QixNQUFNQyxLQUFOLElBQWU7QUFDdEQsVUFBSUMsY0FBSjs7QUFDQSxVQUFJdkIsU0FBUyxLQUFLLFFBQWQsSUFBMEJlLDRCQUE5QixFQUE0RDtBQUMxRFEsUUFBQUEsY0FBYyxHQUFHUiw0QkFBNEIsQ0FBQ08sS0FBRCxDQUE3QztBQUNELE9BRkQsTUFF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QUFBQSxHQUFHLEVBQUU7QUFBRUcsVUFBQUEsTUFBRjtBQUFVNkMsVUFBQUEsSUFBVjtBQUFnQkMsVUFBQUE7QUFBaEI7QUFIaUUsT0FBaEMsQ0FBeEM7QUFLQWtCLE1BQUFBLGlCQUFpQixHQUFHLE1BQU1ULGdCQUFnQixDQUFDQyxZQUFqQixDQUN4Qi9CLFdBRHdCLEVBRXhCNkIsV0FGd0IsRUFHeEJ0RCxNQUh3QixFQUl4QjZDLElBSndCLEVBS3hCQyxJQUx3QixDQUExQjtBQU9BLGFBQU87QUFDTGYsUUFBQUEsTUFBTSxFQUFFLFNBREg7QUFFTHBDLFFBQUFBLFNBQVMsRUFBRThCLFdBRk47QUFHTGlDLFFBQUFBLFFBQVEsRUFBRU0saUJBQWlCLENBQUNOO0FBSHZCLE9BQVA7QUFLRDs7QUFDRCxRQUFJNUIsS0FBSyxDQUFDb0MsSUFBVixFQUFnQjtBQUNkLGFBQU87QUFDTG5DLFFBQUFBLE1BQU0sRUFBRSxTQURIO0FBRUxwQyxRQUFBQSxTQUFTLEVBQUU4QixXQUZOO0FBR0xpQyxRQUFBQSxRQUFRLEVBQUU1QixLQUFLLENBQUNvQztBQUhYLE9BQVA7QUFLRDtBQUNGO0FBNUlrQixDQUFyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMVHlwZXMgZnJvbSAnLi4vbG9hZGVycy9kZWZhdWx0R3JhcGhRTFR5cGVzJztcbmltcG9ydCAqIGFzIG9iamVjdHNNdXRhdGlvbnMgZnJvbSAnLi4vaGVscGVycy9vYmplY3RzTXV0YXRpb25zJztcblxuY29uc3QgdHJhbnNmb3JtVHlwZXMgPSBhc3luYyAoXG4gIGlucHV0VHlwZTogJ2NyZWF0ZScgfCAndXBkYXRlJyxcbiAgZmllbGRzLFxuICB7IGNsYXNzTmFtZSwgcGFyc2VHcmFwaFFMU2NoZW1hLCByZXEgfVxuKSA9PiB7XG4gIGNvbnN0IHtcbiAgICBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlLFxuICAgIGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUsXG4gICAgY29uZmlnOiB7IGlzQ3JlYXRlRW5hYmxlZCwgaXNVcGRhdGVFbmFibGVkIH0sXG4gIH0gPSBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW2NsYXNzTmFtZV07XG4gIGNvbnN0IHBhcnNlQ2xhc3MgPSBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc2VzLmZpbmQoXG4gICAgY2xhenogPT4gY2xhenouY2xhc3NOYW1lID09PSBjbGFzc05hbWVcbiAgKTtcbiAgaWYgKGZpZWxkcykge1xuICAgIGNvbnN0IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGVGaWVsZHMgPVxuICAgICAgaXNDcmVhdGVFbmFibGVkICYmIGNsYXNzR3JhcGhRTENyZWF0ZVR5cGVcbiAgICAgICAgPyBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlLmdldEZpZWxkcygpXG4gICAgICAgIDogbnVsbDtcbiAgICBjb25zdCBjbGFzc0dyYXBoUUxVcGRhdGVUeXBlRmllbGRzID1cbiAgICAgIGlzVXBkYXRlRW5hYmxlZCAmJiBjbGFzc0dyYXBoUUxVcGRhdGVUeXBlXG4gICAgICAgID8gY2xhc3NHcmFwaFFMVXBkYXRlVHlwZS5nZXRGaWVsZHMoKVxuICAgICAgICA6IG51bGw7XG4gICAgY29uc3QgcHJvbWlzZXMgPSBPYmplY3Qua2V5cyhmaWVsZHMpLm1hcChhc3luYyBmaWVsZCA9PiB7XG4gICAgICBsZXQgaW5wdXRUeXBlRmllbGQ7XG4gICAgICBpZiAoaW5wdXRUeXBlID09PSAnY3JlYXRlJyAmJiBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlRmllbGRzKSB7XG4gICAgICAgIGlucHV0VHlwZUZpZWxkID0gY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZUZpZWxkc1tmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGVGaWVsZHMpIHtcbiAgICAgICAgaW5wdXRUeXBlRmllbGQgPSBjbGFzc0dyYXBoUUxVcGRhdGVUeXBlRmllbGRzW2ZpZWxkXTtcbiAgICAgIH1cbiAgICAgIGlmIChpbnB1dFR5cGVGaWVsZCkge1xuICAgICAgICBzd2l0Y2ggKHRydWUpIHtcbiAgICAgICAgICBjYXNlIGlucHV0VHlwZUZpZWxkLnR5cGUgPT09IGRlZmF1bHRHcmFwaFFMVHlwZXMuR0VPX1BPSU5UX0lOUFVUOlxuICAgICAgICAgICAgZmllbGRzW2ZpZWxkXSA9IHRyYW5zZm9ybWVycy5nZW9Qb2ludChmaWVsZHNbZmllbGRdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgaW5wdXRUeXBlRmllbGQudHlwZSA9PT0gZGVmYXVsdEdyYXBoUUxUeXBlcy5QT0xZR09OX0lOUFVUOlxuICAgICAgICAgICAgZmllbGRzW2ZpZWxkXSA9IHRyYW5zZm9ybWVycy5wb2x5Z29uKGZpZWxkc1tmaWVsZF0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1JlbGF0aW9uJzpcbiAgICAgICAgICAgIGZpZWxkc1tmaWVsZF0gPSBhd2FpdCB0cmFuc2Zvcm1lcnMucmVsYXRpb24oXG4gICAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcyxcbiAgICAgICAgICAgICAgZmllbGQsXG4gICAgICAgICAgICAgIGZpZWxkc1tmaWVsZF0sXG4gICAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgICAgICAgICAgICAgcmVxXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInOlxuICAgICAgICAgICAgZmllbGRzW2ZpZWxkXSA9IGF3YWl0IHRyYW5zZm9ybWVycy5wb2ludGVyKFxuICAgICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICAgIGZpZWxkLFxuICAgICAgICAgICAgICBmaWVsZHNbZmllbGRdLFxuICAgICAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEsXG4gICAgICAgICAgICAgIHJlcVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgIGlmIChmaWVsZHMuQUNMKSBmaWVsZHMuQUNMID0gdHJhbnNmb3JtZXJzLkFDTChmaWVsZHMuQUNMKTtcbiAgfVxuICByZXR1cm4gZmllbGRzO1xufTtcblxuY29uc3QgdHJhbnNmb3JtZXJzID0ge1xuICBwb2x5Z29uOiB2YWx1ZSA9PiAoe1xuICAgIF9fdHlwZTogJ1BvbHlnb24nLFxuICAgIGNvb3JkaW5hdGVzOiB2YWx1ZS5tYXAoZ2VvUG9pbnQgPT4gW2dlb1BvaW50LmxhdGl0dWRlLCBnZW9Qb2ludC5sb25naXR1ZGVdKSxcbiAgfSksXG4gIGdlb1BvaW50OiB2YWx1ZSA9PiAoe1xuICAgIC4uLnZhbHVlLFxuICAgIF9fdHlwZTogJ0dlb1BvaW50JyxcbiAgfSksXG4gIEFDTDogdmFsdWUgPT4ge1xuICAgIGNvbnN0IHBhcnNlQUNMID0ge307XG4gICAgaWYgKHZhbHVlLnB1YmxpYykge1xuICAgICAgcGFyc2VBQ0xbJyonXSA9IHtcbiAgICAgICAgcmVhZDogdmFsdWUucHVibGljLnJlYWQsXG4gICAgICAgIHdyaXRlOiB2YWx1ZS5wdWJsaWMud3JpdGUsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodmFsdWUudXNlcnMpIHtcbiAgICAgIHZhbHVlLnVzZXJzLmZvckVhY2gocnVsZSA9PiB7XG4gICAgICAgIHBhcnNlQUNMW3J1bGUudXNlcklkXSA9IHtcbiAgICAgICAgICByZWFkOiBydWxlLnJlYWQsXG4gICAgICAgICAgd3JpdGU6IHJ1bGUud3JpdGUsXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHZhbHVlLnJvbGVzKSB7XG4gICAgICB2YWx1ZS5yb2xlcy5mb3JFYWNoKHJ1bGUgPT4ge1xuICAgICAgICBwYXJzZUFDTFtgcm9sZToke3J1bGUucm9sZU5hbWV9YF0gPSB7XG4gICAgICAgICAgcmVhZDogcnVsZS5yZWFkLFxuICAgICAgICAgIHdyaXRlOiBydWxlLndyaXRlLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBwYXJzZUFDTDtcbiAgfSxcbiAgcmVsYXRpb246IGFzeW5jIChcbiAgICB0YXJnZXRDbGFzcyxcbiAgICBmaWVsZCxcbiAgICB2YWx1ZSxcbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEsXG4gICAgeyBjb25maWcsIGF1dGgsIGluZm8gfVxuICApID0+IHtcbiAgICBpZiAoT2JqZWN0LmtleXModmFsdWUpID09PSAwKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgWW91IG5lZWQgdG8gcHJvdmlkZSBhdGxlYXN0IG9uZSBvcGVyYXRpb24gb24gdGhlIHJlbGF0aW9uIG11dGF0aW9uIG9mIGZpZWxkICR7ZmllbGR9YFxuICAgICAgKTtcblxuICAgIGNvbnN0IG9wID0ge1xuICAgICAgX19vcDogJ0JhdGNoJyxcbiAgICAgIG9wczogW10sXG4gICAgfTtcbiAgICBsZXQgbmVzdGVkT2JqZWN0c1RvQWRkID0gW107XG5cbiAgICBpZiAodmFsdWUuY3JlYXRlQW5kQWRkKSB7XG4gICAgICBuZXN0ZWRPYmplY3RzVG9BZGQgPSAoYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIHZhbHVlLmNyZWF0ZUFuZEFkZC5tYXAoYXN5bmMgaW5wdXQgPT4ge1xuICAgICAgICAgIGNvbnN0IHBhcnNlRmllbGRzID0gYXdhaXQgdHJhbnNmb3JtVHlwZXMoJ2NyZWF0ZScsIGlucHV0LCB7XG4gICAgICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICAgICAgICAgICAgcmVxOiB7IGNvbmZpZywgYXV0aCwgaW5mbyB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBvYmplY3RzTXV0YXRpb25zLmNyZWF0ZU9iamVjdChcbiAgICAgICAgICAgIHRhcmdldENsYXNzLFxuICAgICAgICAgICAgcGFyc2VGaWVsZHMsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgaW5mb1xuICAgICAgICAgICk7XG4gICAgICAgIH0pXG4gICAgICApKS5tYXAob2JqZWN0ID0+ICh7XG4gICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICBvYmplY3RJZDogb2JqZWN0Lm9iamVjdElkLFxuICAgICAgfSkpO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZS5hZGQgfHwgbmVzdGVkT2JqZWN0c1RvQWRkLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmICghdmFsdWUuYWRkKSB2YWx1ZS5hZGQgPSBbXTtcbiAgICAgIHZhbHVlLmFkZCA9IHZhbHVlLmFkZC5tYXAoaW5wdXQgPT4gKHtcbiAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgIGNsYXNzTmFtZTogdGFyZ2V0Q2xhc3MsXG4gICAgICAgIG9iamVjdElkOiBpbnB1dCxcbiAgICAgIH0pKTtcbiAgICAgIG9wLm9wcy5wdXNoKHtcbiAgICAgICAgX19vcDogJ0FkZFJlbGF0aW9uJyxcbiAgICAgICAgb2JqZWN0czogWy4uLnZhbHVlLmFkZCwgLi4ubmVzdGVkT2JqZWN0c1RvQWRkXSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZS5yZW1vdmUpIHtcbiAgICAgIG9wLm9wcy5wdXNoKHtcbiAgICAgICAgX19vcDogJ1JlbW92ZVJlbGF0aW9uJyxcbiAgICAgICAgb2JqZWN0czogdmFsdWUucmVtb3ZlLm1hcChpbnB1dCA9PiAoe1xuICAgICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgIGNsYXNzTmFtZTogdGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgb2JqZWN0SWQ6IGlucHV0LFxuICAgICAgICB9KSksXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG9wO1xuICB9LFxuICBwb2ludGVyOiBhc3luYyAoXG4gICAgdGFyZ2V0Q2xhc3MsXG4gICAgZmllbGQsXG4gICAgdmFsdWUsXG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICAgIHsgY29uZmlnLCBhdXRoLCBpbmZvIH1cbiAgKSA9PiB7XG4gICAgaWYgKE9iamVjdC5rZXlzKHZhbHVlKSA+IDEgfHwgT2JqZWN0LmtleXModmFsdWUpID09PSAwKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgWW91IG5lZWQgdG8gcHJvdmlkZSBsaW5rIE9SIGNyZWF0ZUxpbmsgb24gdGhlIHBvaW50ZXIgbXV0YXRpb24gb2YgZmllbGQgJHtmaWVsZH1gXG4gICAgICApO1xuXG4gICAgbGV0IG5lc3RlZE9iamVjdFRvQWRkO1xuICAgIGlmICh2YWx1ZS5jcmVhdGVBbmRMaW5rKSB7XG4gICAgICBjb25zdCBwYXJzZUZpZWxkcyA9IGF3YWl0IHRyYW5zZm9ybVR5cGVzKCdjcmVhdGUnLCB2YWx1ZS5jcmVhdGVBbmRMaW5rLCB7XG4gICAgICAgIGNsYXNzTmFtZTogdGFyZ2V0Q2xhc3MsXG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgICAgICAgcmVxOiB7IGNvbmZpZywgYXV0aCwgaW5mbyB9LFxuICAgICAgfSk7XG4gICAgICBuZXN0ZWRPYmplY3RUb0FkZCA9IGF3YWl0IG9iamVjdHNNdXRhdGlvbnMuY3JlYXRlT2JqZWN0KFxuICAgICAgICB0YXJnZXRDbGFzcyxcbiAgICAgICAgcGFyc2VGaWVsZHMsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgaW5mb1xuICAgICAgKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICBvYmplY3RJZDogbmVzdGVkT2JqZWN0VG9BZGQub2JqZWN0SWQsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodmFsdWUubGluaykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgIGNsYXNzTmFtZTogdGFyZ2V0Q2xhc3MsXG4gICAgICAgIG9iamVjdElkOiB2YWx1ZS5saW5rLFxuICAgICAgfTtcbiAgICB9XG4gIH0sXG59O1xuXG5leHBvcnQgeyB0cmFuc2Zvcm1UeXBlcyB9O1xuIl19 \ No newline at end of file diff --git a/lib/GraphQL/transformers/outputType.js b/lib/GraphQL/transformers/outputType.js new file mode 100644 index 0000000000..80211765b5 --- /dev/null +++ b/lib/GraphQL/transformers/outputType.js @@ -0,0 +1,71 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformOutputTypeToGraphQL = void 0; + +var defaultGraphQLTypes = _interopRequireWildcard(require("../loaders/defaultGraphQLTypes")); + +var _graphql = require("graphql"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +const transformOutputTypeToGraphQL = (parseType, targetClass, parseClassTypes) => { + switch (parseType) { + case 'String': + return _graphql.GraphQLString; + + case 'Number': + return _graphql.GraphQLFloat; + + case 'Boolean': + return _graphql.GraphQLBoolean; + + case 'Array': + return new _graphql.GraphQLList(defaultGraphQLTypes.ARRAY_RESULT); + + case 'Object': + return defaultGraphQLTypes.OBJECT; + + case 'Date': + return defaultGraphQLTypes.DATE; + + case 'Pointer': + if (parseClassTypes && parseClassTypes[targetClass] && parseClassTypes[targetClass].classGraphQLOutputType) { + return parseClassTypes[targetClass].classGraphQLOutputType; + } else { + return defaultGraphQLTypes.OBJECT; + } + + case 'Relation': + if (parseClassTypes && parseClassTypes[targetClass] && parseClassTypes[targetClass].classGraphQLFindResultType) { + return new _graphql.GraphQLNonNull(parseClassTypes[targetClass].classGraphQLFindResultType); + } else { + return new _graphql.GraphQLNonNull(defaultGraphQLTypes.FIND_RESULT); + } + + case 'File': + return defaultGraphQLTypes.FILE_INFO; + + case 'GeoPoint': + return defaultGraphQLTypes.GEO_POINT; + + case 'Polygon': + return defaultGraphQLTypes.POLYGON; + + case 'Bytes': + return defaultGraphQLTypes.BYTES; + + case 'ACL': + return defaultGraphQLTypes.ACL; + + default: + return undefined; + } +}; + +exports.transformOutputTypeToGraphQL = transformOutputTypeToGraphQL; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9vdXRwdXRUeXBlLmpzIl0sIm5hbWVzIjpbInRyYW5zZm9ybU91dHB1dFR5cGVUb0dyYXBoUUwiLCJwYXJzZVR5cGUiLCJ0YXJnZXRDbGFzcyIsInBhcnNlQ2xhc3NUeXBlcyIsIkdyYXBoUUxTdHJpbmciLCJHcmFwaFFMRmxvYXQiLCJHcmFwaFFMQm9vbGVhbiIsIkdyYXBoUUxMaXN0IiwiZGVmYXVsdEdyYXBoUUxUeXBlcyIsIkFSUkFZX1JFU1VMVCIsIk9CSkVDVCIsIkRBVEUiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIiwiY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGUiLCJHcmFwaFFMTm9uTnVsbCIsIkZJTkRfUkVTVUxUIiwiRklMRV9JTkZPIiwiR0VPX1BPSU5UIiwiUE9MWUdPTiIsIkJZVEVTIiwiQUNMIiwidW5kZWZpbmVkIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7OztBQVFBLE1BQU1BLDRCQUE0QixHQUFHLENBQ25DQyxTQURtQyxFQUVuQ0MsV0FGbUMsRUFHbkNDLGVBSG1DLEtBSWhDO0FBQ0gsVUFBUUYsU0FBUjtBQUNFLFNBQUssUUFBTDtBQUNFLGFBQU9HLHNCQUFQOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9DLHFCQUFQOztBQUNGLFNBQUssU0FBTDtBQUNFLGFBQU9DLHVCQUFQOztBQUNGLFNBQUssT0FBTDtBQUNFLGFBQU8sSUFBSUMsb0JBQUosQ0FBZ0JDLG1CQUFtQixDQUFDQyxZQUFwQyxDQUFQOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9ELG1CQUFtQixDQUFDRSxNQUEzQjs7QUFDRixTQUFLLE1BQUw7QUFDRSxhQUFPRixtQkFBbUIsQ0FBQ0csSUFBM0I7O0FBQ0YsU0FBSyxTQUFMO0FBQ0UsVUFDRVIsZUFBZSxJQUNmQSxlQUFlLENBQUNELFdBQUQsQ0FEZixJQUVBQyxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlUsc0JBSC9CLEVBSUU7QUFDQSxlQUFPVCxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlUsc0JBQXBDO0FBQ0QsT0FORCxNQU1PO0FBQ0wsZUFBT0osbUJBQW1CLENBQUNFLE1BQTNCO0FBQ0Q7O0FBQ0gsU0FBSyxVQUFMO0FBQ0UsVUFDRVAsZUFBZSxJQUNmQSxlQUFlLENBQUNELFdBQUQsQ0FEZixJQUVBQyxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlcsMEJBSC9CLEVBSUU7QUFDQSxlQUFPLElBQUlDLHVCQUFKLENBQ0xYLGVBQWUsQ0FBQ0QsV0FBRCxDQUFmLENBQTZCVywwQkFEeEIsQ0FBUDtBQUdELE9BUkQsTUFRTztBQUNMLGVBQU8sSUFBSUMsdUJBQUosQ0FBbUJOLG1CQUFtQixDQUFDTyxXQUF2QyxDQUFQO0FBQ0Q7O0FBQ0gsU0FBSyxNQUFMO0FBQ0UsYUFBT1AsbUJBQW1CLENBQUNRLFNBQTNCOztBQUNGLFNBQUssVUFBTDtBQUNFLGFBQU9SLG1CQUFtQixDQUFDUyxTQUEzQjs7QUFDRixTQUFLLFNBQUw7QUFDRSxhQUFPVCxtQkFBbUIsQ0FBQ1UsT0FBM0I7O0FBQ0YsU0FBSyxPQUFMO0FBQ0UsYUFBT1YsbUJBQW1CLENBQUNXLEtBQTNCOztBQUNGLFNBQUssS0FBTDtBQUNFLGFBQU9YLG1CQUFtQixDQUFDWSxHQUEzQjs7QUFDRjtBQUNFLGFBQU9DLFNBQVA7QUE5Q0o7QUFnREQsQ0FyREQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4uL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5pbXBvcnQge1xuICBHcmFwaFFMU3RyaW5nLFxuICBHcmFwaFFMRmxvYXQsXG4gIEdyYXBoUUxCb29sZWFuLFxuICBHcmFwaFFMTGlzdCxcbiAgR3JhcGhRTE5vbk51bGwsXG59IGZyb20gJ2dyYXBocWwnO1xuXG5jb25zdCB0cmFuc2Zvcm1PdXRwdXRUeXBlVG9HcmFwaFFMID0gKFxuICBwYXJzZVR5cGUsXG4gIHRhcmdldENsYXNzLFxuICBwYXJzZUNsYXNzVHlwZXNcbikgPT4ge1xuICBzd2l0Y2ggKHBhcnNlVHlwZSkge1xuICAgIGNhc2UgJ1N0cmluZyc6XG4gICAgICByZXR1cm4gR3JhcGhRTFN0cmluZztcbiAgICBjYXNlICdOdW1iZXInOlxuICAgICAgcmV0dXJuIEdyYXBoUUxGbG9hdDtcbiAgICBjYXNlICdCb29sZWFuJzpcbiAgICAgIHJldHVybiBHcmFwaFFMQm9vbGVhbjtcbiAgICBjYXNlICdBcnJheSc6XG4gICAgICByZXR1cm4gbmV3IEdyYXBoUUxMaXN0KGRlZmF1bHRHcmFwaFFMVHlwZXMuQVJSQVlfUkVTVUxUKTtcbiAgICBjYXNlICdPYmplY3QnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuREFURTtcbiAgICBjYXNlICdQb2ludGVyJzpcbiAgICAgIGlmIChcbiAgICAgICAgcGFyc2VDbGFzc1R5cGVzICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10gJiZcbiAgICAgICAgcGFyc2VDbGFzc1R5cGVzW3RhcmdldENsYXNzXS5jbGFzc0dyYXBoUUxPdXRwdXRUeXBlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMT3V0cHV0VHlwZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcbiAgICAgIH1cbiAgICBjYXNlICdSZWxhdGlvbic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlcyAmJlxuICAgICAgICBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGVcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBuZXcgR3JhcGhRTE5vbk51bGwoZGVmYXVsdEdyYXBoUUxUeXBlcy5GSU5EX1JFU1VMVCk7XG4gICAgICB9XG4gICAgY2FzZSAnRmlsZSc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5GSUxFX0lORk87XG4gICAgY2FzZSAnR2VvUG9pbnQnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuR0VPX1BPSU5UO1xuICAgIGNhc2UgJ1BvbHlnb24nOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuUE9MWUdPTjtcbiAgICBjYXNlICdCeXRlcyc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5CWVRFUztcbiAgICBjYXNlICdBQ0wnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuQUNMO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG5leHBvcnQgeyB0cmFuc2Zvcm1PdXRwdXRUeXBlVG9HcmFwaFFMIH07XG4iXX0= \ No newline at end of file diff --git a/lib/GraphQL/transformers/query.js b/lib/GraphQL/transformers/query.js new file mode 100644 index 0000000000..3314eb2677 --- /dev/null +++ b/lib/GraphQL/transformers/query.js @@ -0,0 +1,194 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformQueryInputToParse = exports.transformQueryConstraintInputToParse = void 0; + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const parseQueryMap = { + id: 'objectId', + OR: '$or', + AND: '$and', + NOR: '$nor' +}; +const parseConstraintMap = { + equalTo: '$eq', + notEqualTo: '$ne', + lessThan: '$lt', + lessThanOrEqualTo: '$lte', + greaterThan: '$gt', + greaterThanOrEqualTo: '$gte', + in: '$in', + notIn: '$nin', + exists: '$exists', + inQueryKey: '$select', + notInQueryKey: '$dontSelect', + inQuery: '$inQuery', + notInQuery: '$notInQuery', + containedBy: '$containedBy', + contains: '$all', + matchesRegex: '$regex', + options: '$options', + text: '$text', + search: '$search', + term: '$term', + language: '$language', + caseSensitive: '$caseSensitive', + diacriticSensitive: '$diacriticSensitive', + nearSphere: '$nearSphere', + maxDistance: '$maxDistance', + maxDistanceInRadians: '$maxDistanceInRadians', + maxDistanceInMiles: '$maxDistanceInMiles', + maxDistanceInKilometers: '$maxDistanceInKilometers', + within: '$within', + box: '$box', + geoWithin: '$geoWithin', + polygon: '$polygon', + centerSphere: '$centerSphere', + geoIntersects: '$geoIntersects', + point: '$point' +}; + +const transformQueryConstraintInputToParse = (constraints, fields, parentFieldName, parentConstraints) => { + Object.keys(constraints).forEach(fieldName => { + let fieldValue = constraints[fieldName]; + /** + * If we have a key-value pair, we need to change the way the constraint is structured. + * + * Example: + * From: + * { + * "someField": { + * "lessThan": { + * "key":"foo.bar", + * "value": 100 + * }, + * "greaterThan": { + * "key":"foo.bar", + * "value": 10 + * } + * } + * } + * + * To: + * { + * "someField.foo.bar": { + * "$lt": 100, + * "$gt": 10 + * } + * } + */ + + if (fieldValue.key && fieldValue.value && parentConstraints && parentFieldName) { + delete parentConstraints[parentFieldName]; + parentConstraints[`${parentFieldName}.${fieldValue.key}`] = _objectSpread({}, parentConstraints[`${parentFieldName}.${fieldValue.key}`], { + [parseConstraintMap[fieldName]]: fieldValue.value + }); + } else if (parseConstraintMap[fieldName]) { + delete constraints[fieldName]; + fieldName = parseConstraintMap[fieldName]; + constraints[fieldName] = fieldValue; // If parent field type is Pointer, changes constraint value to format expected + // by Parse. + + if (fields[parentFieldName] && fields[parentFieldName].type === 'Pointer' && typeof fieldValue === 'string') { + const { + targetClass + } = fields[parentFieldName]; + constraints[fieldName] = { + __type: 'Pointer', + className: targetClass, + objectId: fieldValue + }; + } + } + + switch (fieldName) { + case '$point': + case '$nearSphere': + if (typeof fieldValue === 'object' && !fieldValue.__type) { + fieldValue.__type = 'GeoPoint'; + } + + break; + + case '$box': + if (typeof fieldValue === 'object' && fieldValue.bottomLeft && fieldValue.upperRight) { + fieldValue = [_objectSpread({ + __type: 'GeoPoint' + }, fieldValue.bottomLeft), _objectSpread({ + __type: 'GeoPoint' + }, fieldValue.upperRight)]; + constraints[fieldName] = fieldValue; + } + + break; + + case '$polygon': + if (fieldValue instanceof Array) { + fieldValue.forEach(geoPoint => { + if (typeof geoPoint === 'object' && !geoPoint.__type) { + geoPoint.__type = 'GeoPoint'; + } + }); + } + + break; + + case '$centerSphere': + if (typeof fieldValue === 'object' && fieldValue.center && fieldValue.distance) { + fieldValue = [_objectSpread({ + __type: 'GeoPoint' + }, fieldValue.center), fieldValue.distance]; + constraints[fieldName] = fieldValue; + } + + break; + } + + if (typeof fieldValue === 'object') { + if (fieldName === 'where') { + transformQueryInputToParse(fieldValue); + } else { + transformQueryConstraintInputToParse(fieldValue, fields, fieldName, constraints); + } + } + }); +}; + +exports.transformQueryConstraintInputToParse = transformQueryConstraintInputToParse; + +const transformQueryInputToParse = (constraints, fields) => { + if (!constraints || typeof constraints !== 'object') { + return; + } + + Object.keys(constraints).forEach(fieldName => { + const fieldValue = constraints[fieldName]; + + if (parseQueryMap[fieldName]) { + delete constraints[fieldName]; + fieldName = parseQueryMap[fieldName]; + constraints[fieldName] = fieldValue; + + if (fieldName !== 'objectId') { + fieldValue.forEach(fieldValueItem => { + transformQueryInputToParse(fieldValueItem, fields); + }); + return; + } + } + + if (typeof fieldValue === 'object') { + transformQueryConstraintInputToParse(fieldValue, fields, fieldName, constraints); + } + }); +}; + +exports.transformQueryInputToParse = transformQueryInputToParse; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9xdWVyeS5qcyJdLCJuYW1lcyI6WyJwYXJzZVF1ZXJ5TWFwIiwiaWQiLCJPUiIsIkFORCIsIk5PUiIsInBhcnNlQ29uc3RyYWludE1hcCIsImVxdWFsVG8iLCJub3RFcXVhbFRvIiwibGVzc1RoYW4iLCJsZXNzVGhhbk9yRXF1YWxUbyIsImdyZWF0ZXJUaGFuIiwiZ3JlYXRlclRoYW5PckVxdWFsVG8iLCJpbiIsIm5vdEluIiwiZXhpc3RzIiwiaW5RdWVyeUtleSIsIm5vdEluUXVlcnlLZXkiLCJpblF1ZXJ5Iiwibm90SW5RdWVyeSIsImNvbnRhaW5lZEJ5IiwiY29udGFpbnMiLCJtYXRjaGVzUmVnZXgiLCJvcHRpb25zIiwidGV4dCIsInNlYXJjaCIsInRlcm0iLCJsYW5ndWFnZSIsImNhc2VTZW5zaXRpdmUiLCJkaWFjcml0aWNTZW5zaXRpdmUiLCJuZWFyU3BoZXJlIiwibWF4RGlzdGFuY2UiLCJtYXhEaXN0YW5jZUluUmFkaWFucyIsIm1heERpc3RhbmNlSW5NaWxlcyIsIm1heERpc3RhbmNlSW5LaWxvbWV0ZXJzIiwid2l0aGluIiwiYm94IiwiZ2VvV2l0aGluIiwicG9seWdvbiIsImNlbnRlclNwaGVyZSIsImdlb0ludGVyc2VjdHMiLCJwb2ludCIsInRyYW5zZm9ybVF1ZXJ5Q29uc3RyYWludElucHV0VG9QYXJzZSIsImNvbnN0cmFpbnRzIiwiZmllbGRzIiwicGFyZW50RmllbGROYW1lIiwicGFyZW50Q29uc3RyYWludHMiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsImZpZWxkTmFtZSIsImZpZWxkVmFsdWUiLCJrZXkiLCJ2YWx1ZSIsInR5cGUiLCJ0YXJnZXRDbGFzcyIsIl9fdHlwZSIsImNsYXNzTmFtZSIsIm9iamVjdElkIiwiYm90dG9tTGVmdCIsInVwcGVyUmlnaHQiLCJBcnJheSIsImdlb1BvaW50IiwiY2VudGVyIiwiZGlzdGFuY2UiLCJ0cmFuc2Zvcm1RdWVyeUlucHV0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QUF1QixRQUEzQyxFQUFxRDtBQUNuRDtBQUNEOztBQUVESSxFQUFBQSxNQUFNLENBQUNDLElBQVAsQ0FBWUwsV0FBWixFQUF5Qk0sT0FBekIsQ0FBaUNDLFNBQVMsSUFBSTtBQUM1QyxVQUFNQyxVQUFVLEdBQUdSLFdBQVcsQ0FBQ08sU0FBRCxDQUE5Qjs7QUFFQSxRQUFJakQsYUFBYSxDQUFDaUQsU0FBRCxDQUFqQixFQUE4QjtBQUM1QixhQUFPUCxXQUFXLENBQUNPLFNBQUQsQ0FBbEI7QUFDQUEsTUFBQUEsU0FBUyxHQUFHakQsYUFBYSxDQUFDaUQsU0FBRCxDQUF6QjtBQUNBUCxNQUFBQSxXQUFXLENBQUNPLFNBQUQsQ0FBWCxHQUF5QkMsVUFBekI7O0FBRUEsVUFBSUQsU0FBUyxLQUFLLFVBQWxCLEVBQThCO0FBQzVCQyxRQUFBQSxVQUFVLENBQUNGLE9BQVgsQ0FBbUJpQixjQUFjLElBQUk7QUFDbkNELFVBQUFBLDBCQUEwQixDQUFDQyxjQUFELEVBQWlCdEIsTUFBakIsQ0FBMUI7QUFDRCxTQUZEO0FBR0E7QUFDRDtBQUNGOztBQUVELFFBQUksT0FBT08sVUFBUCxLQUFzQixRQUExQixFQUFvQztBQUNsQ1QsTUFBQUEsb0NBQW9DLENBQ2xDUyxVQURrQyxFQUVsQ1AsTUFGa0MsRUFHbENNLFNBSGtDLEVBSWxDUCxXQUprQyxDQUFwQztBQU1EO0FBQ0YsR0F4QkQ7QUF5QkQsQ0E5QkQiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBwYXJzZVF1ZXJ5TWFwID0ge1xuICBpZDogJ29iamVjdElkJyxcbiAgT1I6ICckb3InLFxuICBBTkQ6ICckYW5kJyxcbiAgTk9SOiAnJG5vcicsXG59O1xuXG5jb25zdCBwYXJzZUNvbnN0cmFpbnRNYXAgPSB7XG4gIGVxdWFsVG86ICckZXEnLFxuICBub3RFcXVhbFRvOiAnJG5lJyxcbiAgbGVzc1RoYW46ICckbHQnLFxuICBsZXNzVGhhbk9yRXF1YWxUbzogJyRsdGUnLFxuICBncmVhdGVyVGhhbjogJyRndCcsXG4gIGdyZWF0ZXJUaGFuT3JFcXVhbFRvOiAnJGd0ZScsXG4gIGluOiAnJGluJyxcbiAgbm90SW46ICckbmluJyxcbiAgZXhpc3RzOiAnJGV4aXN0cycsXG4gIGluUXVlcnlLZXk6ICckc2VsZWN0JyxcbiAgbm90SW5RdWVyeUtleTogJyRkb250U2VsZWN0JyxcbiAgaW5RdWVyeTogJyRpblF1ZXJ5JyxcbiAgbm90SW5RdWVyeTogJyRub3RJblF1ZXJ5JyxcbiAgY29udGFpbmVkQnk6ICckY29udGFpbmVkQnknLFxuICBjb250YWluczogJyRhbGwnLFxuICBtYXRjaGVzUmVnZXg6ICckcmVnZXgnLFxuICBvcHRpb25zOiAnJG9wdGlvbnMnLFxuICB0ZXh0OiAnJHRleHQnLFxuICBzZWFyY2g6ICckc2VhcmNoJyxcbiAgdGVybTogJyR0ZXJtJyxcbiAgbGFuZ3VhZ2U6ICckbGFuZ3VhZ2UnLFxuICBjYXNlU2Vuc2l0aXZlOiAnJGNhc2VTZW5zaXRpdmUnLFxuICBkaWFjcml0aWNTZW5zaXRpdmU6ICckZGlhY3JpdGljU2Vuc2l0aXZlJyxcbiAgbmVhclNwaGVyZTogJyRuZWFyU3BoZXJlJyxcbiAgbWF4RGlzdGFuY2U6ICckbWF4RGlzdGFuY2UnLFxuICBtYXhEaXN0YW5jZUluUmFkaWFuczogJyRtYXhEaXN0YW5jZUluUmFkaWFucycsXG4gIG1heERpc3RhbmNlSW5NaWxlczogJyRtYXhEaXN0YW5jZUluTWlsZXMnLFxuICBtYXhEaXN0YW5jZUluS2lsb21ldGVyczogJyRtYXhEaXN0YW5jZUluS2lsb21ldGVycycsXG4gIHdpdGhpbjogJyR3aXRoaW4nLFxuICBib3g6ICckYm94JyxcbiAgZ2VvV2l0aGluOiAnJGdlb1dpdGhpbicsXG4gIHBvbHlnb246ICckcG9seWdvbicsXG4gIGNlbnRlclNwaGVyZTogJyRjZW50ZXJTcGhlcmUnLFxuICBnZW9JbnRlcnNlY3RzOiAnJGdlb0ludGVyc2VjdHMnLFxuICBwb2ludDogJyRwb2ludCcsXG59O1xuXG5jb25zdCB0cmFuc2Zvcm1RdWVyeUNvbnN0cmFpbnRJbnB1dFRvUGFyc2UgPSAoXG4gIGNvbnN0cmFpbnRzLFxuICBmaWVsZHMsXG4gIHBhcmVudEZpZWxkTmFtZSxcbiAgcGFyZW50Q29uc3RyYWludHNcbikgPT4ge1xuICBPYmplY3Qua2V5cyhjb25zdHJhaW50cykuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgIGxldCBmaWVsZFZhbHVlID0gY29uc3RyYWludHNbZmllbGROYW1lXTtcblxuICAgIC8qKlxuICAgICAqIElmIHdlIGhhdmUgYSBrZXktdmFsdWUgcGFpciwgd2UgbmVlZCB0byBjaGFuZ2UgdGhlIHdheSB0aGUgY29uc3RyYWludCBpcyBzdHJ1Y3R1cmVkLlxuICAgICAqXG4gICAgICogRXhhbXBsZTpcbiAgICAgKiAgIEZyb206XG4gICAgICogICB7XG4gICAgICogICAgIFwic29tZUZpZWxkXCI6IHtcbiAgICAgKiAgICAgICBcImxlc3NUaGFuXCI6IHtcbiAgICAgKiAgICAgICAgIFwia2V5XCI6XCJmb28uYmFyXCIsXG4gICAgICogICAgICAgICBcInZhbHVlXCI6IDEwMFxuICAgICAqICAgICAgIH0sXG4gICAgICogICAgICAgXCJncmVhdGVyVGhhblwiOiB7XG4gICAgICogICAgICAgICBcImtleVwiOlwiZm9vLmJhclwiLFxuICAgICAqICAgICAgICAgXCJ2YWx1ZVwiOiAxMFxuICAgICAqICAgICAgIH1cbiAgICAgKiAgICAgfVxuICAgICAqICAgfVxuICAgICAqXG4gICAgICogICBUbzpcbiAgICAgKiAgIHtcbiAgICAgKiAgICAgXCJzb21lRmllbGQuZm9vLmJhclwiOiB7XG4gICAgICogICAgICAgXCIkbHRcIjogMTAwLFxuICAgICAqICAgICAgIFwiJGd0XCI6IDEwXG4gICAgICogICAgICB9XG4gICAgICogICB9XG4gICAgICovXG4gICAgaWYgKFxuICAgICAgZmllbGRWYWx1ZS5rZXkgJiZcbiAgICAgIGZpZWxkVmFsdWUudmFsdWUgJiZcbiAgICAgIHBhcmVudENvbnN0cmFpbnRzICYmXG4gICAgICBwYXJlbnRGaWVsZE5hbWVcbiAgICApIHtcbiAgICAgIGRlbGV0ZSBwYXJlbnRDb25zdHJhaW50c1twYXJlbnRGaWVsZE5hbWVdO1xuICAgICAgcGFyZW50Q29uc3RyYWludHNbYCR7cGFyZW50RmllbGROYW1lfS4ke2ZpZWxkVmFsdWUua2V5fWBdID0ge1xuICAgICAgICAuLi5wYXJlbnRDb25zdHJhaW50c1tgJHtwYXJlbnRGaWVsZE5hbWV9LiR7ZmllbGRWYWx1ZS5rZXl9YF0sXG4gICAgICAgIFtwYXJzZUNvbnN0cmFpbnRNYXBbZmllbGROYW1lXV06IGZpZWxkVmFsdWUudmFsdWUsXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAocGFyc2VDb25zdHJhaW50TWFwW2ZpZWxkTmFtZV0pIHtcbiAgICAgIGRlbGV0ZSBjb25zdHJhaW50c1tmaWVsZE5hbWVdO1xuICAgICAgZmllbGROYW1lID0gcGFyc2VDb25zdHJhaW50TWFwW2ZpZWxkTmFtZV07XG4gICAgICBjb25zdHJhaW50c1tmaWVsZE5hbWVdID0gZmllbGRWYWx1ZTtcblxuICAgICAgLy8gSWYgcGFyZW50IGZpZWxkIHR5cGUgaXMgUG9pbnRlciwgY2hhbmdlcyBjb25zdHJhaW50IHZhbHVlIHRvIGZvcm1hdCBleHBlY3RlZFxuICAgICAgLy8gYnkgUGFyc2UuXG4gICAgICBpZiAoXG4gICAgICAgIGZpZWxkc1twYXJlbnRGaWVsZE5hbWVdICYmXG4gICAgICAgIGZpZWxkc1twYXJlbnRGaWVsZE5hbWVdLnR5cGUgPT09ICdQb2ludGVyJyAmJlxuICAgICAgICB0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3N0cmluZydcbiAgICAgICkge1xuICAgICAgICBjb25zdCB7IHRhcmdldENsYXNzIH0gPSBmaWVsZHNbcGFyZW50RmllbGROYW1lXTtcbiAgICAgICAgY29uc3RyYWludHNbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICAgIG9iamVjdElkOiBmaWVsZFZhbHVlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgICBzd2l0Y2ggKGZpZWxkTmFtZSkge1xuICAgICAgY2FzZSAnJHBvaW50JzpcbiAgICAgIGNhc2UgJyRuZWFyU3BoZXJlJzpcbiAgICAgICAgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnb2JqZWN0JyAmJiAhZmllbGRWYWx1ZS5fX3R5cGUpIHtcbiAgICAgICAgICBmaWVsZFZhbHVlLl9fdHlwZSA9ICdHZW9Qb2ludCc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICckYm94JzpcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHR5cGVvZiBmaWVsZFZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgIGZpZWxkVmFsdWUuYm90dG9tTGVmdCAmJlxuICAgICAgICAgIGZpZWxkVmFsdWUudXBwZXJSaWdodFxuICAgICAgICApIHtcbiAgICAgICAgICBmaWVsZFZhbHVlID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBfX3R5cGU6ICdHZW9Qb2ludCcsXG4gICAgICAgICAgICAgIC4uLmZpZWxkVmFsdWUuYm90dG9tTGVmdCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIF9fdHlwZTogJ0dlb1BvaW50JyxcbiAgICAgICAgICAgICAgLi4uZmllbGRWYWx1ZS51cHBlclJpZ2h0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdO1xuICAgICAgICAgIGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV0gPSBmaWVsZFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnJHBvbHlnb24nOlxuICAgICAgICBpZiAoZmllbGRWYWx1ZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgZmllbGRWYWx1ZS5mb3JFYWNoKGdlb1BvaW50ID0+IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZ2VvUG9pbnQgPT09ICdvYmplY3QnICYmICFnZW9Qb2ludC5fX3R5cGUpIHtcbiAgICAgICAgICAgICAgZ2VvUG9pbnQuX190eXBlID0gJ0dlb1BvaW50JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJyRjZW50ZXJTcGhlcmUnOlxuICAgICAgICBpZiAoXG4gICAgICAgICAgdHlwZW9mIGZpZWxkVmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgZmllbGRWYWx1ZS5jZW50ZXIgJiZcbiAgICAgICAgICBmaWVsZFZhbHVlLmRpc3RhbmNlXG4gICAgICAgICkge1xuICAgICAgICAgIGZpZWxkVmFsdWUgPSBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIF9fdHlwZTogJ0dlb1BvaW50JyxcbiAgICAgICAgICAgICAgLi4uZmllbGRWYWx1ZS5jZW50ZXIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmllbGRWYWx1ZS5kaXN0YW5jZSxcbiAgICAgICAgICBdO1xuICAgICAgICAgIGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV0gPSBmaWVsZFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoZmllbGROYW1lID09PSAnd2hlcmUnKSB7XG4gICAgICAgIHRyYW5zZm9ybVF1ZXJ5SW5wdXRUb1BhcnNlKGZpZWxkVmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJhbnNmb3JtUXVlcnlDb25zdHJhaW50SW5wdXRUb1BhcnNlKFxuICAgICAgICAgIGZpZWxkVmFsdWUsXG4gICAgICAgICAgZmllbGRzLFxuICAgICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgICBjb25zdHJhaW50c1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1RdWVyeUlucHV0VG9QYXJzZSA9IChjb25zdHJhaW50cywgZmllbGRzKSA9PiB7XG4gIGlmICghY29uc3RyYWludHMgfHwgdHlwZW9mIGNvbnN0cmFpbnRzICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIE9iamVjdC5rZXlzKGNvbnN0cmFpbnRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgY29uc3QgZmllbGRWYWx1ZSA9IGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV07XG5cbiAgICBpZiAocGFyc2VRdWVyeU1hcFtmaWVsZE5hbWVdKSB7XG4gICAgICBkZWxldGUgY29uc3RyYWludHNbZmllbGROYW1lXTtcbiAgICAgIGZpZWxkTmFtZSA9IHBhcnNlUXVlcnlNYXBbZmllbGROYW1lXTtcbiAgICAgIGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV0gPSBmaWVsZFZhbHVlO1xuXG4gICAgICBpZiAoZmllbGROYW1lICE9PSAnb2JqZWN0SWQnKSB7XG4gICAgICAgIGZpZWxkVmFsdWUuZm9yRWFjaChmaWVsZFZhbHVlSXRlbSA9PiB7XG4gICAgICAgICAgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UoZmllbGRWYWx1ZUl0ZW0sIGZpZWxkcyk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgdHJhbnNmb3JtUXVlcnlDb25zdHJhaW50SW5wdXRUb1BhcnNlKFxuICAgICAgICBmaWVsZFZhbHVlLFxuICAgICAgICBmaWVsZHMsXG4gICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgY29uc3RyYWludHNcbiAgICAgICk7XG4gICAgfVxuICB9KTtcbn07XG5cbmV4cG9ydCB7IHRyYW5zZm9ybVF1ZXJ5Q29uc3RyYWludElucHV0VG9QYXJzZSwgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/transformers/schemaFields.js b/lib/GraphQL/transformers/schemaFields.js new file mode 100644 index 0000000000..202de969c4 --- /dev/null +++ b/lib/GraphQL/transformers/schemaFields.js @@ -0,0 +1,128 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformToGraphQL = exports.transformToParse = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +const transformToParse = (graphQLSchemaFields, existingFields) => { + if (!graphQLSchemaFields) { + return {}; + } + + let parseSchemaFields = {}; + + const reducerGenerator = type => (parseSchemaFields, field) => { + if (type === 'Remove') { + if (existingFields[field.name]) { + return _objectSpread({}, parseSchemaFields, { + [field.name]: { + __op: 'Delete' + } + }); + } else { + return parseSchemaFields; + } + } + + if (graphQLSchemaFields.remove && graphQLSchemaFields.remove.find(removeField => removeField.name === field.name)) { + return parseSchemaFields; + } + + if (parseSchemaFields[field.name] || existingFields && existingFields[field.name]) { + throw new _node.default.Error(_node.default.Error.INVALID_KEY_NAME, `Duplicated field name: ${field.name}`); + } + + if (type === 'Relation' || type === 'Pointer') { + return _objectSpread({}, parseSchemaFields, { + [field.name]: { + type, + targetClass: field.targetClassName + } + }); + } + + return _objectSpread({}, parseSchemaFields, { + [field.name]: { + type + } + }); + }; + + if (graphQLSchemaFields.addStrings) { + parseSchemaFields = graphQLSchemaFields.addStrings.reduce(reducerGenerator('String'), parseSchemaFields); + } + + if (graphQLSchemaFields.addNumbers) { + parseSchemaFields = graphQLSchemaFields.addNumbers.reduce(reducerGenerator('Number'), parseSchemaFields); + } + + if (graphQLSchemaFields.addBooleans) { + parseSchemaFields = graphQLSchemaFields.addBooleans.reduce(reducerGenerator('Boolean'), parseSchemaFields); + } + + if (graphQLSchemaFields.addArrays) { + parseSchemaFields = graphQLSchemaFields.addArrays.reduce(reducerGenerator('Array'), parseSchemaFields); + } + + if (graphQLSchemaFields.addObjects) { + parseSchemaFields = graphQLSchemaFields.addObjects.reduce(reducerGenerator('Object'), parseSchemaFields); + } + + if (graphQLSchemaFields.addDates) { + parseSchemaFields = graphQLSchemaFields.addDates.reduce(reducerGenerator('Date'), parseSchemaFields); + } + + if (graphQLSchemaFields.addFiles) { + parseSchemaFields = graphQLSchemaFields.addFiles.reduce(reducerGenerator('File'), parseSchemaFields); + } + + if (graphQLSchemaFields.addGeoPoint) { + parseSchemaFields = [graphQLSchemaFields.addGeoPoint].reduce(reducerGenerator('GeoPoint'), parseSchemaFields); + } + + if (graphQLSchemaFields.addPolygons) { + parseSchemaFields = graphQLSchemaFields.addPolygons.reduce(reducerGenerator('Polygon'), parseSchemaFields); + } + + if (graphQLSchemaFields.addBytes) { + parseSchemaFields = graphQLSchemaFields.addBytes.reduce(reducerGenerator('Bytes'), parseSchemaFields); + } + + if (graphQLSchemaFields.addPointers) { + parseSchemaFields = graphQLSchemaFields.addPointers.reduce(reducerGenerator('Pointer'), parseSchemaFields); + } + + if (graphQLSchemaFields.addRelations) { + parseSchemaFields = graphQLSchemaFields.addRelations.reduce(reducerGenerator('Relation'), parseSchemaFields); + } + + if (existingFields && graphQLSchemaFields.remove) { + parseSchemaFields = graphQLSchemaFields.remove.reduce(reducerGenerator('Remove'), parseSchemaFields); + } + + return parseSchemaFields; +}; + +exports.transformToParse = transformToParse; + +const transformToGraphQL = parseSchemaFields => { + return Object.keys(parseSchemaFields).map(name => ({ + name, + type: parseSchemaFields[name].type, + targetClassName: parseSchemaFields[name].targetClass + })); +}; + +exports.transformToGraphQL = transformToGraphQL; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9zY2hlbWFGaWVsZHMuanMiXSwibmFtZXMiOlsidHJhbnNmb3JtVG9QYXJzZSIsImdyYXBoUUxTY2hlbWFGaWVsZHMiLCJleGlzdGluZ0ZpZWxkcyIsInBhcnNlU2NoZW1hRmllbGRzIiwicmVkdWNlckdlbmVyYXRvciIsInR5cGUiLCJmaWVsZCIsIm5hbWUiLCJfX29wIiwicmVtb3ZlIiwiZmluZCIsInJlbW92ZUZpZWxkIiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfS0VZX05BTUUiLCJ0YXJnZXRDbGFzcyIsInRhcmdldENsYXNzTmFtZSIsImFkZFN0cmluZ3MiLCJyZWR1Y2UiLCJhZGROdW1iZXJzIiwiYWRkQm9vbGVhbnMiLCJhZGRBcnJheXMiLCJhZGRPYmplY3RzIiwiYWRkRGF0ZXMiLCJhZGRGaWxlcyIsImFkZEdlb1BvaW50IiwiYWRkUG9seWdvbnMiLCJhZGRCeXRlcyIsImFkZFBvaW50ZXJzIiwiYWRkUmVsYXRpb25zIiwidHJhbnNmb3JtVG9HcmFwaFFMIiwiT2JqZWN0Iiwia2V5cyIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7Ozs7Ozs7O0FBRUEsTUFBTUEsZ0JBQWdCLEdBQUcsQ0FBQ0MsbUJBQUQsRUFBc0JDLGNBQXRCLEtBQXlDO0FBQ2hFLE1BQUksQ0FBQ0QsbUJBQUwsRUFBMEI7QUFDeEIsV0FBTyxFQUFQO0FBQ0Q7O0FBRUQsTUFBSUUsaUJBQWlCLEdBQUcsRUFBeEI7O0FBRUEsUUFBTUMsZ0JBQWdCLEdBQUdDLElBQUksSUFBSSxDQUFDRixpQkFBRCxFQUFvQkcsS0FBcEIsS0FBOEI7QUFDN0QsUUFBSUQsSUFBSSxLQUFLLFFBQWIsRUFBdUI7QUFDckIsVUFBSUgsY0FBYyxDQUFDSSxLQUFLLENBQUNDLElBQVAsQ0FBbEIsRUFBZ0M7QUFDOUIsaUNBQ0tKLGlCQURMO0FBRUUsV0FBQ0csS0FBSyxDQUFDQyxJQUFQLEdBQWM7QUFDWkMsWUFBQUEsSUFB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O0FBd0lBLE1BQU0yQixrQkFBa0IsR0FBRzNCLGlCQUFpQixJQUFJO0FBQzlDLFNBQU80QixNQUFNLENBQUNDLElBQVAsQ0FBWTdCLGlCQUFaLEVBQStCOEIsR0FBL0IsQ0FBbUMxQixJQUFJLEtBQUs7QUFDakRBLElBQUFBLElBRGlEO0FBRWpERixJQUFBQSxJQUFJLEVBQUVGLGlCQUFpQixDQUFDSSxJQUFELENBQWpCLENBQXdCRixJQUZtQjtBQUdqRFcsSUFBQUEsZUFBZSxFQUFFYixpQkFBaUIsQ0FBQ0ksSUFBRCxDQUFqQixDQUF3QlE7QUFIUSxHQUFMLENBQXZDLENBQVA7QUFLRCxDQU5EIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuXG5jb25zdCB0cmFuc2Zvcm1Ub1BhcnNlID0gKGdyYXBoUUxTY2hlbWFGaWVsZHMsIGV4aXN0aW5nRmllbGRzKSA9PiB7XG4gIGlmICghZ3JhcGhRTFNjaGVtYUZpZWxkcykge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGxldCBwYXJzZVNjaGVtYUZpZWxkcyA9IHt9O1xuXG4gIGNvbnN0IHJlZHVjZXJHZW5lcmF0b3IgPSB0eXBlID0+IChwYXJzZVNjaGVtYUZpZWxkcywgZmllbGQpID0+IHtcbiAgICBpZiAodHlwZSA9PT0gJ1JlbW92ZScpIHtcbiAgICAgIGlmIChleGlzdGluZ0ZpZWxkc1tmaWVsZC5uYW1lXSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnBhcnNlU2NoZW1hRmllbGRzLFxuICAgICAgICAgIFtmaWVsZC5uYW1lXToge1xuICAgICAgICAgICAgX19vcDogJ0RlbGV0ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBwYXJzZVNjaGVtYUZpZWxkcztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKFxuICAgICAgZ3JhcGhRTFNjaGVtYUZpZWxkcy5yZW1vdmUgJiZcbiAgICAgIGdyYXBoUUxTY2hlbWFGaWVsZHMucmVtb3ZlLmZpbmQoXG4gICAgICAgIHJlbW92ZUZpZWxkID0+IHJlbW92ZUZpZWxkLm5hbWUgPT09IGZpZWxkLm5hbWVcbiAgICAgIClcbiAgICApIHtcbiAgICAgIHJldHVybiBwYXJzZVNjaGVtYUZpZWxkcztcbiAgICB9XG4gICAgaWYgKFxuICAgICAgcGFyc2VTY2hlbWFGaWVsZHNbZmllbGQubmFtZV0gfHxcbiAgICAgIChleGlzdGluZ0ZpZWxkcyAmJiBleGlzdGluZ0ZpZWxkc1tmaWVsZC5uYW1lXSlcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICAgYER1cGxpY2F0ZWQgZmllbGQgbmFtZTogJHtmaWVsZC5uYW1lfWBcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICh0eXBlID09PSAnUmVsYXRpb24nIHx8IHR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ucGFyc2VTY2hlbWFGaWVsZHMsXG4gICAgICAgIFtmaWVsZC5uYW1lXToge1xuICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgdGFyZ2V0Q2xhc3M6IGZpZWxkLnRhcmdldENsYXNzTmFtZSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAuLi5wYXJzZVNjaGVtYUZpZWxkcyxcbiAgICAgIFtmaWVsZC5uYW1lXToge1xuICAgICAgICB0eXBlLFxuICAgICAgfSxcbiAgICB9O1xuICB9O1xuXG4gIGlmIChncmFwaFFMU2NoZW1hRmllbGRzLmFkZFN0cmluZ3MpIHtcbiAgICBwYXJzZVNjaGVtYUZpZWxkcyA9IGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkU3RyaW5ncy5yZWR1Y2UoXG4gICAgICByZWR1Y2VyR2VuZXJhdG9yKCdTdHJpbmcnKSxcbiAgICAgIHBhcnNlU2NoZW1hRmllbGRzXG4gICAgKTtcbiAgfVxuICBpZiAoZ3JhcGhRTFNjaGVtYUZpZWxkcy5hZGROdW1iZXJzKSB7XG4gICAgcGFyc2VTY2hlbWFGaWVsZHMgPSBncmFwaFFMU2NoZW1hRmllbGRzLmFkZE51bWJlcnMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignTnVtYmVyJyksXG4gICAgICBwYXJzZVNjaGVtYUZpZWxkc1xuICAgICk7XG4gIH1cbiAgaWYgKGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkQm9vbGVhbnMpIHtcbiAgICBwYXJzZVNjaGVtYUZpZWxkcyA9IGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkQm9vbGVhbnMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignQm9vbGVhbicpLFxuICAgICAgcGFyc2VTY2hlbWFGaWVsZHNcbiAgICApO1xuICB9XG4gIGlmIChncmFwaFFMU2NoZW1hRmllbGRzLmFkZEFycmF5cykge1xuICAgIHBhcnNlU2NoZW1hRmllbGRzID0gZ3JhcGhRTFNjaGVtYUZpZWxkcy5hZGRBcnJheXMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignQXJyYXknKSxcbiAgICAgIHBhcnNlU2NoZW1hRmllbGRzXG4gICAgKTtcbiAgfVxuICBpZiAoZ3JhcGhRTFNjaGVtYUZpZWxkcy5hZGRPYmplY3RzKSB7XG4gICAgcGFyc2VTY2hlbWFGaWVsZHMgPSBncmFwaFFMU2NoZW1hRmllbGRzLmFkZE9iamVjdHMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignT2JqZWN0JyksXG4gICAgICBwYXJzZVNjaGVtYUZpZWxkc1xuICAgICk7XG4gIH1cbiAgaWYgKGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkRGF0ZXMpIHtcbiAgICBwYXJzZVNjaGVtYUZpZWxkcyA9IGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkRGF0ZXMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignRGF0ZScpLFxuICAgICAgcGFyc2VTY2hlbWFGaWVsZHNcbiAgICApO1xuICB9XG4gIGlmIChncmFwaFFMU2NoZW1hRmllbGRzLmFkZEZpbGVzKSB7XG4gICAgcGFyc2VTY2hlbWFGaWVsZHMgPSBncmFwaFFMU2NoZW1hRmllbGRzLmFkZEZpbGVzLnJlZHVjZShcbiAgICAgIHJlZHVjZXJHZW5lcmF0b3IoJ0ZpbGUnKSxcbiAgICAgIHBhcnNlU2NoZW1hRmllbGRzXG4gICAgKTtcbiAgfVxuICBpZiAoZ3JhcGhRTFNjaGVtYUZpZWxkcy5hZGRHZW9Qb2ludCkge1xuICAgIHBhcnNlU2NoZW1hRmllbGRzID0gW2dyYXBoUUxTY2hlbWFGaWVsZHMuYWRkR2VvUG9pbnRdLnJlZHVjZShcbiAgICAgIHJlZHVjZXJHZW5lcmF0b3IoJ0dlb1BvaW50JyksXG4gICAgICBwYXJzZVNjaGVtYUZpZWxkc1xuICAgICk7XG4gIH1cbiAgaWYgKGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkUG9seWdvbnMpIHtcbiAgICBwYXJzZVNjaGVtYUZpZWxkcyA9IGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkUG9seWdvbnMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignUG9seWdvbicpLFxuICAgICAgcGFyc2VTY2hlbWFGaWVsZHNcbiAgICApO1xuICB9XG4gIGlmIChncmFwaFFMU2NoZW1hRmllbGRzLmFkZEJ5dGVzKSB7XG4gICAgcGFyc2VTY2hlbWFGaWVsZHMgPSBncmFwaFFMU2NoZW1hRmllbGRzLmFkZEJ5dGVzLnJlZHVjZShcbiAgICAgIHJlZHVjZXJHZW5lcmF0b3IoJ0J5dGVzJyksXG4gICAgICBwYXJzZVNjaGVtYUZpZWxkc1xuICAgICk7XG4gIH1cbiAgaWYgKGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkUG9pbnRlcnMpIHtcbiAgICBwYXJzZVNjaGVtYUZpZWxkcyA9IGdyYXBoUUxTY2hlbWFGaWVsZHMuYWRkUG9pbnRlcnMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignUG9pbnRlcicpLFxuICAgICAgcGFyc2VTY2hlbWFGaWVsZHNcbiAgICApO1xuICB9XG4gIGlmIChncmFwaFFMU2NoZW1hRmllbGRzLmFkZFJlbGF0aW9ucykge1xuICAgIHBhcnNlU2NoZW1hRmllbGRzID0gZ3JhcGhRTFNjaGVtYUZpZWxkcy5hZGRSZWxhdGlvbnMucmVkdWNlKFxuICAgICAgcmVkdWNlckdlbmVyYXRvcignUmVsYXRpb24nKSxcbiAgICAgIHBhcnNlU2NoZW1hRmllbGRzXG4gICAgKTtcbiAgfVxuICBpZiAoZXhpc3RpbmdGaWVsZHMgJiYgZ3JhcGhRTFNjaGVtYUZpZWxkcy5yZW1vdmUpIHtcbiAgICBwYXJzZVNjaGVtYUZpZWxkcyA9IGdyYXBoUUxTY2hlbWFGaWVsZHMucmVtb3ZlLnJlZHVjZShcbiAgICAgIHJlZHVjZXJHZW5lcmF0b3IoJ1JlbW92ZScpLFxuICAgICAgcGFyc2VTY2hlbWFGaWVsZHNcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlU2NoZW1hRmllbGRzO1xufTtcblxuY29uc3QgdHJhbnNmb3JtVG9HcmFwaFFMID0gcGFyc2VTY2hlbWFGaWVsZHMgPT4ge1xuICByZXR1cm4gT2JqZWN0LmtleXMocGFyc2VTY2hlbWFGaWVsZHMpLm1hcChuYW1lID0+ICh7XG4gICAgbmFtZSxcbiAgICB0eXBlOiBwYXJzZVNjaGVtYUZpZWxkc1tuYW1lXS50eXBlLFxuICAgIHRhcmdldENsYXNzTmFtZTogcGFyc2VTY2hlbWFGaWVsZHNbbmFtZV0udGFyZ2V0Q2xhc3MsXG4gIH0pKTtcbn07XG5cbmV4cG9ydCB7IHRyYW5zZm9ybVRvUGFyc2UsIHRyYW5zZm9ybVRvR3JhcGhRTCB9O1xuIl19 \ No newline at end of file diff --git a/lib/LiveQuery/Client.js b/lib/LiveQuery/Client.js new file mode 100644 index 0000000000..1ccc24908a --- /dev/null +++ b/lib/LiveQuery/Client.js @@ -0,0 +1,113 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Client = void 0; + +var _logger = _interopRequireDefault(require("../logger")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const dafaultFields = ['className', 'objectId', 'updatedAt', 'createdAt', 'ACL']; + +class Client { + constructor(id, parseWebSocket, hasMasterKey = false, sessionToken, installationId) { + this.id = id; + this.parseWebSocket = parseWebSocket; + this.hasMasterKey = hasMasterKey; + this.sessionToken = sessionToken; + this.installationId = installationId; + this.roles = []; + this.subscriptionInfos = new Map(); + this.pushConnect = this._pushEvent('connected'); + this.pushSubscribe = this._pushEvent('subscribed'); + this.pushUnsubscribe = this._pushEvent('unsubscribed'); + this.pushCreate = this._pushEvent('create'); + this.pushEnter = this._pushEvent('enter'); + this.pushUpdate = this._pushEvent('update'); + this.pushDelete = this._pushEvent('delete'); + this.pushLeave = this._pushEvent('leave'); + } + + static pushResponse(parseWebSocket, message) { + _logger.default.verbose('Push Response : %j', message); + + parseWebSocket.send(message); + } + + static pushError(parseWebSocket, code, error, reconnect = true) { + Client.pushResponse(parseWebSocket, JSON.stringify({ + op: 'error', + error: error, + code: code, + reconnect: reconnect + })); + } + + addSubscriptionInfo(requestId, subscriptionInfo) { + this.subscriptionInfos.set(requestId, subscriptionInfo); + } + + getSubscriptionInfo(requestId) { + return this.subscriptionInfos.get(requestId); + } + + deleteSubscriptionInfo(requestId) { + return this.subscriptionInfos.delete(requestId); + } + + _pushEvent(type) { + return function (subscriptionId, parseObjectJSON, parseOriginalObjectJSON) { + const response = { + op: type, + clientId: this.id, + installationId: this.installationId + }; + + if (typeof subscriptionId !== 'undefined') { + response['requestId'] = subscriptionId; + } + + if (typeof parseObjectJSON !== 'undefined') { + let fields; + + if (this.subscriptionInfos.has(subscriptionId)) { + fields = this.subscriptionInfos.get(subscriptionId).fields; + } + + response['object'] = this._toJSONWithFields(parseObjectJSON, fields); + + if (parseOriginalObjectJSON) { + response['original'] = this._toJSONWithFields(parseOriginalObjectJSON, fields); + } + } + + Client.pushResponse(this.parseWebSocket, JSON.stringify(response)); + }; + } + + _toJSONWithFields(parseObjectJSON, fields) { + if (!fields) { + return parseObjectJSON; + } + + const limitedParseObject = {}; + + for (const field of dafaultFields) { + limitedParseObject[field] = parseObjectJSON[field]; + } + + for (const field of fields) { + if (field in parseObjectJSON) { + limitedParseObject[field] = parseObjectJSON[field]; + } + } + + return limitedParseObject; + } + +} + +exports.Client = Client; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvQ2xpZW50LmpzIl0sIm5hbWVzIjpbImRhZmF1bHRGaWVsZHMiLCJDbGllbnQiLCJjb25zdHJ1Y3RvciIsImlkIiwicGFyc2VXZWJTb2NrZXQiLCJoYXNNYXN0ZXJLZXkiLCJzZXNzaW9uVG9rZW4iLCJpbnN0YWxsYXRpb25JZCIsInJvbGVzIiwic3Vic2NyaXB0aW9uSW5mb3MiLCJNYXAiLCJwdXNoQ29ubmVjdCIsIl9wdXNoRXZlbnQiLCJwdXNoU3Vic2NyaWJlIiwicHVzaFVuc3Vic2NyaWJlIiwicHVzaENyZWF0ZSIsInB1c2hFbnRlciIsInB1c2hVcGRhdGUiLCJwdXNoRGVsZXRlIiwicHVzaExlYXZlIiwicHVzaFJlc3BvbnNlIiwibWVzc2FnZSIsImxvZ2dlciIsInZlcmJvc2UiLCJzZW5kIiwicHVzaEVycm9yIiwiY29kZSIsImVycm9yIiwicmVjb25uZWN0IiwiSlNPTiIsInN0cmluZ2lmeSIsIm9wIiwiYWRkU3Vic2NyaXB0aW9uSW5mbyIsInJlcXVlc3RJZCIsInN1YnNjcmlwdGlvbkluZm8iLCJzZXQiLCJnZXRTdWJzY3JpcHRpb25JbmZvIiwiZ2V0IiwiZGVsZXRlU3Vic2NyaXB0aW9uSW5mbyIsImRlbGV0ZSIsInR5cGUiLCJzdWJzY3JpcHRpb25JZCIsInBhcnNlT2JqZWN0SlNPTiIsInBhcnNlT3JpZ2luYWxPYmplY3RKU09OIiwicmVzcG9uc2UiLCJjbGllbnRJZCIsImZpZWxkcyIsImhhcyIsIl90b0pTT05XaXRoRmllbGRzIiwibGltaXRlZFBhcnNlT2JqZWN0IiwiZmllbGQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUtBLE1BQU1BLGFBQWEsR0FBRyxDQUNwQixXQURvQixFQUVwQixVQUZvQixFQUdwQixXQUhvQixFQUlwQixXQUpvQixFQUtwQixLQUxvQixDQUF0Qjs7QUFRQSxNQUFNQyxNQUFOLENBQWE7QUFrQlhDLEVBQUFBLFdBQVcsQ0FDVEMsRUFEUyxFQUVUQyxjQUZTLEVB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dHlwZSB7IEZsYXR0ZW5lZE9iamVjdERhdGEgfSBmcm9tICcuL1N1YnNjcmlwdGlvbic7XG5leHBvcnQgdHlwZSBNZXNzYWdlID0geyBbYXR0cjogc3RyaW5nXTogYW55IH07XG5cbmNvbnN0IGRhZmF1bHRGaWVsZHMgPSBbXG4gICdjbGFzc05hbWUnLFxuICAnb2JqZWN0SWQnLFxuICAndXBkYXRlZEF0JyxcbiAgJ2NyZWF0ZWRBdCcsXG4gICdBQ0wnLFxuXTtcblxuY2xhc3MgQ2xpZW50IHtcbiAgaWQ6IG51bWJlcjtcbiAgcGFyc2VXZWJTb2NrZXQ6IGFueTtcbiAgaGFzTWFzdGVyS2V5OiBib29sZWFuO1xuICBzZXNzaW9uVG9rZW46IHN0cmluZztcbiAgaW5zdGFsbGF0aW9uSWQ6IHN0cmluZztcbiAgdXNlcklkOiBzdHJpbmc7XG4gIHJvbGVzOiBBcnJheTxzdHJpbmc+O1xuICBzdWJzY3JpcHRpb25JbmZvczogT2JqZWN0O1xuICBwdXNoQ29ubmVjdDogRnVuY3Rpb247XG4gIHB1c2hTdWJzY3JpYmU6IEZ1bmN0aW9uO1xuICBwdXNoVW5zdWJzY3JpYmU6IEZ1bmN0aW9uO1xuICBwdXNoQ3JlYXRlOiBGdW5jdGlvbjtcbiAgcHVzaEVudGVyOiBGdW5jdGlvbjtcbiAgcHVzaFVwZGF0ZTogRnVuY3Rpb247XG4gIHB1c2hEZWxldGU6IEZ1bmN0aW9uO1xuICBwdXNoTGVhdmU6IEZ1bmN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGlkOiBudW1iZXIsXG4gICAgcGFyc2VXZWJTb2NrZXQ6IGFueSxcbiAgICBoYXNNYXN0ZXJLZXk6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICBzZXNzaW9uVG9rZW46IHN0cmluZyxcbiAgICBpbnN0YWxsYXRpb25JZDogc3RyaW5nXG4gICkge1xuICAgIHRoaXMuaWQgPSBpZDtcbiAgICB0aGlzLnBhcnNlV2ViU29ja2V0ID0gcGFyc2VXZWJTb2NrZXQ7XG4gICAgdGhpcy5oYXNNYXN0ZXJLZXkgPSBoYXNNYXN0ZXJLZXk7XG4gICAgdGhpcy5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uVG9rZW47XG4gICAgdGhpcy5pbnN0YWxsYXRpb25JZCA9IGluc3RhbGxhdGlvbklkO1xuICAgIHRoaXMucm9sZXMgPSBbXTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbkluZm9zID0gbmV3IE1hcCgpO1xuICAgIHRoaXMucHVzaENvbm5lY3QgPSB0aGlzLl9wdXNoRXZlbnQoJ2Nvbm5lY3RlZCcpO1xuICAgIHRoaXMucHVzaFN1YnNjcmliZSA9IHRoaXMuX3B1c2hFdmVudCgnc3Vic2NyaWJlZCcpO1xuICAgIHRoaXMucHVzaFVuc3Vic2NyaWJlID0gdGhpcy5fcHVzaEV2ZW50KCd1bnN1YnNjcmliZWQnKTtcbiAgICB0aGlzLnB1c2hDcmVhdGUgPSB0aGlzLl9wdXNoRXZlbnQoJ2NyZWF0ZScpO1xuICAgIHRoaXMucHVzaEVudGVyID0gdGhpcy5fcHVzaEV2ZW50KCdlbnRlcicpO1xuICAgIHRoaXMucHVzaFVwZGF0ZSA9IHRoaXMuX3B1c2hFdmVudCgndXBkYXRlJyk7XG4gICAgdGhpcy5wdXNoRGVsZXRlID0gdGhpcy5fcHVzaEV2ZW50KCdkZWxldGUnKTtcbiAgICB0aGlzLnB1c2hMZWF2ZSA9IHRoaXMuX3B1c2hFdmVudCgnbGVhdmUnKTtcbiAgfVxuXG4gIHN0YXRpYyBwdXNoUmVzcG9uc2UocGFyc2VXZWJTb2NrZXQ6IGFueSwgbWVzc2FnZTogTWVzc2FnZSk6IHZvaWQge1xuICAgIGxvZ2dlci52ZXJib3NlKCdQdXNoIFJlc3BvbnNlIDogJWonLCBtZXNzYWdlKTtcbiAgICBwYXJzZVdlYlNvY2tldC5zZW5kKG1lc3NhZ2UpO1xuICB9XG5cbiAgc3RhdGljIHB1c2hFcnJvcihcbiAgICBwYXJzZVdlYlNvY2tldDogYW55LFxuICAgIGNvZGU6IG51bWJlcixcbiAgICBlcnJvcjogc3RyaW5nLFxuICAgIHJlY29ubmVjdDogYm9vbGVhbiA9IHRydWVcbiAgKTogdm9pZCB7XG4gICAgQ2xpZW50LnB1c2hSZXNwb25zZShcbiAgICAgIHBhcnNlV2ViU29ja2V0LFxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBvcDogJ2Vycm9yJyxcbiAgICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgICBjb2RlOiBjb2RlLFxuICAgICAgICByZWNvbm5lY3Q6IHJlY29ubmVjdCxcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIGFkZFN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdElkOiBudW1iZXIsIHN1YnNjcmlwdGlvbkluZm86IGFueSk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uSW5mb3Muc2V0KHJlcXVlc3RJZCwgc3Vic2NyaXB0aW9uSW5mbyk7XG4gIH1cblxuICBnZXRTdWJzY3JpcHRpb25JbmZvKHJlcXVlc3RJZDogbnVtYmVyKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5zdWJzY3JpcHRpb25JbmZvcy5nZXQocmVxdWVzdElkKTtcbiAgfVxuXG4gIGRlbGV0ZVN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdElkOiBudW1iZXIpOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5zdWJzY3JpcHRpb25JbmZvcy5kZWxldGUocmVxdWVzdElkKTtcbiAgfVxuXG4gIF9wdXNoRXZlbnQodHlwZTogc3RyaW5nKTogRnVuY3Rpb24ge1xuICAgIHJldHVybiBmdW5jdGlvbihcbiAgICAgIHN1YnNjcmlwdGlvbklkOiBudW1iZXIsXG4gICAgICBwYXJzZU9iamVjdEpTT046IGFueSxcbiAgICAgIHBhcnNlT3JpZ2luYWxPYmplY3RKU09OOiBhbnlcbiAgICApOiB2b2lkIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlOiBNZXNzYWdlID0ge1xuICAgICAgICBvcDogdHlwZSxcbiAgICAgICAgY2xpZW50SWQ6IHRoaXMuaWQsXG4gICAgICAgIGluc3RhbGxhdGlvbklkOiB0aGlzLmluc3RhbGxhdGlvbklkLFxuICAgICAgfTtcbiAgICAgIGlmICh0eXBlb2Ygc3Vic2NyaXB0aW9uSWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJlc3BvbnNlWydyZXF1ZXN0SWQnXSA9IHN1YnNjcmlwdGlvbklkO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwYXJzZU9iamVjdEpTT04gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGxldCBmaWVsZHM7XG4gICAgICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbkluZm9zLmhhcyhzdWJzY3JpcHRpb25JZCkpIHtcbiAgICAgICAgICBmaWVsZHMgPSB0aGlzLnN1YnNjcmlwdGlvbkluZm9zLmdldChzdWJzY3JpcHRpb25JZCkuZmllbGRzO1xuICAgICAgICB9XG4gICAgICAgIHJlc3BvbnNlWydvYmplY3QnXSA9IHRoaXMuX3RvSlNPTldpdGhGaWVsZHMocGFyc2VPYmplY3RKU09OLCBmaWVsZHMpO1xuICAgICAgICBpZiAocGFyc2VPcmlnaW5hbE9iamVjdEpTT04pIHtcbiAgICAgICAgICByZXNwb25zZVsnb3JpZ2luYWwnXSA9IHRoaXMuX3RvSlNPTldpdGhGaWVsZHMoXG4gICAgICAgICAgICBwYXJzZU9yaWdpbmFsT2JqZWN0SlNPTixcbiAgICAgICAgICAgIGZpZWxkc1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIENsaWVudC5wdXNoUmVzcG9uc2UodGhpcy5wYXJzZVdlYlNvY2tldCwgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpKTtcbiAgICB9O1xuICB9XG5cbiAgX3RvSlNPTldpdGhGaWVsZHMocGFyc2VPYmplY3RKU09OOiBhbnksIGZpZWxkczogYW55KTogRmxhdHRlbmVkT2JqZWN0RGF0YSB7XG4gICAgaWYgKCFmaWVsZHMpIHtcbiAgICAgIHJldHVybiBwYXJzZU9iamVjdEpTT047XG4gICAgfVxuICAgIGNvbnN0IGxpbWl0ZWRQYXJzZU9iamVjdCA9IHt9O1xuICAgIGZvciAoY29uc3QgZmllbGQgb2YgZGFmYXVsdEZpZWxkcykge1xuICAgICAgbGltaXRlZFBhcnNlT2JqZWN0W2ZpZWxkXSA9IHBhcnNlT2JqZWN0SlNPTltmaWVsZF07XG4gICAgfVxuICAgIGZvciAoY29uc3QgZmllbGQgb2YgZmllbGRzKSB7XG4gICAgICBpZiAoZmllbGQgaW4gcGFyc2VPYmplY3RKU09OKSB7XG4gICAgICAgIGxpbWl0ZWRQYXJzZU9iamVjdFtmaWVsZF0gPSBwYXJzZU9iamVjdEpTT05bZmllbGRdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbGltaXRlZFBhcnNlT2JqZWN0O1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCB9O1xuIl19 \ No newline at end of file diff --git a/lib/LiveQuery/Id.js b/lib/LiveQuery/Id.js new file mode 100644 index 0000000000..379e29b88d --- /dev/null +++ b/lib/LiveQuery/Id.js @@ -0,0 +1,26 @@ +"use strict"; + +class Id { + constructor(className, objectId) { + this.className = className; + this.objectId = objectId; + } + + toString() { + return this.className + ':' + this.objectId; + } + + static fromString(str) { + var split = str.split(':'); + + if (split.length !== 2) { + throw new TypeError('Cannot create Id object from this string'); + } + + return new Id(split[0], split[1]); + } + +} + +module.exports = Id; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvSWQuanMiXSwibmFtZXMiOlsiSWQiLCJjb25zdHJ1Y3RvciIsImNsYXNzTmFtZSIsIm9iamVjdElkIiwidG9TdHJpbmciLCJmcm9tU3RyaW5nIiwic3RyIiwic3BsaXQiLCJsZW5ndGgiLCJUeXBlRXJyb3IiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLE1BQU1BLEVBQU4sQ0FBUztBQUlQQyxFQUFBQSxXQUFXLENBQUNDLFNBQUQsRUFBb0JDLFFBQXBCLEVBQXNDO0FBQy9DLFNBQUtELFNBQUwsR0FBaUJBLFNBQWpCO0FBQ0EsU0FBS0MsUUFBTCxHQUFnQkEsUUFBaEI7QUFDRDs7QUFDREMsRUFBQUEsUUFBUSxHQUFXO0FBQ2pCLFdBQU8sS0FBS0YsU0FBTCxHQUFpQixHQUFqQixHQUF1QixLQUFLQyxRQUFuQztBQUNEOztBQUVELFNBQU9FLFVBQVAsQ0FBa0JDLEdBQWxCLEVBQStCO0FBQzdCLFFBQUlDLEtBQUssR0FBR0QsR0FBRyxDQUFDQyxLQUFKLENBQVUsR0FBVixDQUFaOztBQUNBLFFBQUlBLEtBQUssQ0FBQ0MsTUFBTixLQUFpQixDQUFyQixFQUF3QjtBQUN0QixZQUFNLElBQUlDLFNBQUosQ0FBYywwQ0FBZCxDQUFOO0FBQ0Q7O0FBQ0QsV0FBTyxJQUFJVCxFQUFKLENBQU9PLEtBQUssQ0FBQyxDQUFELENBQVosRUFBaUJBLEtBQUssQ0FBQyxDQUFELENBQXRCLENBQVA7QUFDRDs7QUFsQk07O0FBcUJURyxNQUFNLENBQUNDLE9BQVAsR0FBaUJYLEVBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgSWQge1xuICBjbGFzc05hbWU6IHN0cmluZztcbiAgb2JqZWN0SWQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0SWQ6IHN0cmluZykge1xuICAgIHRoaXMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgIHRoaXMub2JqZWN0SWQgPSBvYmplY3RJZDtcbiAgfVxuICB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNsYXNzTmFtZSArICc6JyArIHRoaXMub2JqZWN0SWQ7XG4gIH1cblxuICBzdGF0aWMgZnJvbVN0cmluZyhzdHI6IHN0cmluZykge1xuICAgIHZhciBzcGxpdCA9IHN0ci5zcGxpdCgnOicpO1xuICAgIGlmIChzcGxpdC5sZW5ndGggIT09IDIpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjcmVhdGUgSWQgb2JqZWN0IGZyb20gdGhpcyBzdHJpbmcnKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBJZChzcGxpdFswXSwgc3BsaXRbMV0pO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gSWQ7XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/ParseCloudCodePublisher.js b/lib/LiveQuery/ParseCloudCodePublisher.js new file mode 100644 index 0000000000..974770a79f --- /dev/null +++ b/lib/LiveQuery/ParseCloudCodePublisher.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseCloudCodePublisher = void 0; + +var _ParsePubSub = require("./ParsePubSub"); + +var _node = _interopRequireDefault(require("parse/node")); + +var _logger = _interopRequireDefault(require("../logger")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class ParseCloudCodePublisher { + // config object of the publisher, right now it only contains the redisURL, + // but we may extend it later. + constructor(config = {}) { + this.parsePublisher = _ParsePubSub.ParsePubSub.createPublisher(config); + } + + onCloudCodeAfterSave(request) { + this._onCloudCodeMessage(_node.default.applicationId + 'afterSave', request); + } + + onCloudCodeAfterDelete(request) { + this._onCloudCodeMessage(_node.default.applicationId + 'afterDelete', request); + } // Request is the request object from cloud code functions. request.object is a ParseObject. + + + _onCloudCodeMessage(type, request) { + _logger.default.verbose('Raw request from cloud code current : %j | original : %j', request.object, request.original); // We need the full JSON which includes className + + + const message = { + currentParseObject: request.object._toFullJSON() + }; + + if (request.original) { + message.originalParseObject = request.original._toFullJSON(); + } + + this.parsePublisher.publish(type, JSON.stringify(message)); + } + +} + +exports.ParseCloudCodePublisher = ParseCloudCodePublisher; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIuanMiXSwibmFtZXMiOlsiUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsInBhcnNlUHVibGlzaGVyIiwiUGFyc2VQdWJTdWIiLCJjcmVhdGVQdWJsaXNoZXIiLCJvbkNsb3VkQ29kZUFmdGVyU2F2ZSIsInJlcXVlc3QiLCJfb25DbG91ZENvZGVNZXNzYWdlIiwiUGFyc2UiLCJhcHBsaWNhdGlvbklkIiwib25DbG91ZENvZGVBZnRlckRlbGV0ZSIsInR5cGUiLCJsb2dnZXIiLCJ2ZXJib3NlIiwib2JqZWN0Iiwib3JpZ2luYWwiLCJtZXNzYWdlIiwiY3VycmVudFBhcnNlT2JqZWN0IiwiX3RvRnVsbEpTT04iLCJvcmlnaW5hbFBhcnNlT2JqZWN0IiwicHVibGlzaCIsIkpTT04iLCJzdHJpbmdpZnkiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLHVCQUFOLENBQThCO0FBRzVCO0FBQ0E7QUFDQUMsRUFBQUEsV0FBVyxDQUFDQyxNQUFXLEdBQUcsRUFBZixFQUFtQjtBQUM1QixTQUFLQyxjQUFMLEdBQXNCQyx5QkFBWUMsZUFBWixDQUE0QkgsTUFBNUIsQ0FBdEI7QUFDRDs7QUFFREksRUFBQUEsb0JBQW9CLENBQUNDLE9BQUQsRUFBcUI7QUFDdkMsU0FBS0MsbUJBQUwsQ0FBeUJDLGNBQU1DLGFBQU4sR0FBc0IsV0FBL0MsRUFBNERILE9BQTVEO0FBQ0Q7O0FBRURJLEVBQUFBLHNCQUFzQixDQUFDSixPQUFELEVBQXFCO0FBQ3pDLFNBQUtDLG1CQUFMLENBQXlCQyxjQUFNQyxhQUFOLEdBQXNCLGFBQS9DLEVBQThESCxPQUE5RDtBQUNELEdBZjJCLENBaUI1Qjs7O0FBQ0FDLEVBQUFBLG1CQUFtQixDQUFDSSxJQUFELEVBQWVMLE9BQWYsRUFBbUM7QUFDcERNLG9CQUFPQyxPQUFQLENBQ0UsMERBREYsRUFFRVAsT0FBTyxDQUFDUSxNQUZWLEVBR0VSLE9BQU8sQ0FBQ1MsUUFIVixFQURvRCxDQU1wRDs7O0FBQ0EsVUFBTUMsT0FBTyxHQUFHO0FBQ2RDLE1BQUFBLGtCQUFrQixFQUFFWCxPQUFPLENBQUNRLE1BQVIsQ0FBZUksV0FBZjtBQUROLEtBQWhCOztBQUdBLFFBQUlaLE9BQU8sQ0FBQ1MsUUFBWixFQUFzQjtBQUNwQkMsTUFBQUEsT0FBTyxDQUFDRyxtQkFBUixHQUE4QmIsT0FBTyxDQUFDUyxRQUFSLENBQWlCRyxXQUFqQixFQUE5QjtBQUNEOztBQUNELFNBQUtoQixjQUFMLENBQW9Ca0IsT0FBcEIsQ0FBNEJULElBQTVCLEVBQWtDVSxJQUFJLENBQUNDLFNBQUwsQ0FBZU4sT0FBZixDQUFsQztBQUNEOztBQWhDMkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZVB1YlN1YiB9IGZyb20gJy4vUGFyc2VQdWJTdWInO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuXG5jbGFzcyBQYXJzZUNsb3VkQ29kZVB1Ymxpc2hlciB7XG4gIHBhcnNlUHVibGlzaGVyOiBPYmplY3Q7XG5cbiAgLy8gY29uZmlnIG9iamVjdCBvZiB0aGUgcHVibGlzaGVyLCByaWdodCBub3cgaXQgb25seSBjb250YWlucyB0aGUgcmVkaXNVUkwsXG4gIC8vIGJ1dCB3ZSBtYXkgZXh0ZW5kIGl0IGxhdGVyLlxuICBjb25zdHJ1Y3Rvcihjb25maWc6IGFueSA9IHt9KSB7XG4gICAgdGhpcy5wYXJzZVB1Ymxpc2hlciA9IFBhcnNlUHViU3ViLmNyZWF0ZVB1Ymxpc2hlcihjb25maWcpO1xuICB9XG5cbiAgb25DbG91ZENvZGVBZnRlclNhdmUocmVxdWVzdDogYW55KTogdm9pZCB7XG4gICAgdGhpcy5fb25DbG91ZENvZGVNZXNzYWdlKFBhcnNlLmFwcGxpY2F0aW9uSWQgKyAnYWZ0ZXJTYXZlJywgcmVxdWVzdCk7XG4gIH1cblxuICBvbkNsb3VkQ29kZUFmdGVyRGVsZXRlKHJlcXVlc3Q6IGFueSk6IHZvaWQge1xuICAgIHRoaXMuX29uQ2xvdWRDb2RlTWVzc2FnZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyRGVsZXRlJywgcmVxdWVzdCk7XG4gIH1cblxuICAvLyBSZXF1ZXN0IGlzIHRoZSByZXF1ZXN0IG9iamVjdCBmcm9tIGNsb3VkIGNvZGUgZnVuY3Rpb25zLiByZXF1ZXN0Lm9iamVjdCBpcyBhIFBhcnNlT2JqZWN0LlxuICBfb25DbG91ZENvZGVNZXNzYWdlKHR5cGU6IHN0cmluZywgcmVxdWVzdDogYW55KTogdm9pZCB7XG4gICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICAnUmF3IHJlcXVlc3QgZnJvbSBjbG91ZCBjb2RlIGN1cnJlbnQgOiAlaiB8IG9yaWdpbmFsIDogJWonLFxuICAgICAgcmVxdWVzdC5vYmplY3QsXG4gICAgICByZXF1ZXN0Lm9yaWdpbmFsXG4gICAgKTtcbiAgICAvLyBXZSBuZWVkIHRoZSBmdWxsIEpTT04gd2hpY2ggaW5jbHVkZXMgY2xhc3NOYW1lXG4gICAgY29uc3QgbWVzc2FnZSA9IHtcbiAgICAgIGN1cnJlbnRQYXJzZU9iamVjdDogcmVxdWVzdC5vYmplY3QuX3RvRnVsbEpTT04oKSxcbiAgICB9O1xuICAgIGlmIChyZXF1ZXN0Lm9yaWdpbmFsKSB7XG4gICAgICBtZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgPSByZXF1ZXN0Lm9yaWdpbmFsLl90b0Z1bGxKU09OKCk7XG4gICAgfVxuICAgIHRoaXMucGFyc2VQdWJsaXNoZXIucHVibGlzaCh0eXBlLCBKU09OLnN0cmluZ2lmeShtZXNzYWdlKSk7XG4gIH1cbn1cblxuZXhwb3J0IHsgUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/LiveQuery/ParseLiveQueryServer.js b/lib/LiveQuery/ParseLiveQueryServer.js new file mode 100644 index 0000000000..b2d37ee1df --- /dev/null +++ b/lib/LiveQuery/ParseLiveQueryServer.js @@ -0,0 +1,771 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseLiveQueryServer = void 0; + +var _tv = _interopRequireDefault(require("tv4")); + +var _node = _interopRequireDefault(require("parse/node")); + +var _Subscription = require("./Subscription"); + +var _Client = require("./Client"); + +var _ParseWebSocketServer = require("./ParseWebSocketServer"); + +var _logger = _interopRequireDefault(require("../logger")); + +var _RequestSchema = _interopRequireDefault(require("./RequestSchema")); + +var _QueryTools = require("./QueryTools"); + +var _ParsePubSub = require("./ParsePubSub"); + +var _SchemaController = _interopRequireDefault(require("../Controllers/SchemaController")); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _uuid = _interopRequireDefault(require("uuid")); + +var _triggers = require("../triggers"); + +var _Auth = require("../Auth"); + +var _Controllers = require("../Controllers"); + +var _lruCache = _interopRequireDefault(require("lru-cache")); + +var _UsersRouter = _interopRequireDefault(require("../Routers/UsersRouter")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class ParseLiveQueryServer { + // className -> (queryHash -> subscription) + // The subscriber we use to get object update from publisher + constructor(server, config = {}) { + this.server = server; + this.clients = new Map(); + this.subscriptions = new Map(); + config.appId = config.appId || _node.default.applicationId; + config.masterKey = config.masterKey || _node.default.masterKey; // Store keys, convert obj to map + + const keyPairs = config.keyPairs || {}; + this.keyPairs = new Map(); + + for (const key of Object.keys(keyPairs)) { + this.keyPairs.set(key, keyPairs[key]); + } + + _logger.default.verbose('Support key pairs', this.keyPairs); // Initialize Parse + + + _node.default.Object.disableSingleInstance(); + + const serverURL = config.serverURL || _node.default.serverURL; + _node.default.serverURL = serverURL; + + _node.default.initialize(config.appId, _node.default.javaScriptKey, config.masterKey); // The cache controller is a proper cache controller + // with access to User and Roles + + + this.cacheController = (0, _Controllers.getCacheController)(config); // This auth cache stores the promises for each auth resolution. + // The main benefit is to be able to reuse the same user / session token resolution. + + this.authCache = new _lruCache.default({ + max: 500, + // 500 concurrent + maxAge: 60 * 60 * 1000 // 1h + + }); // Initialize websocket server + + this.parseWebSocketServer = new _ParseWebSocketServer.ParseWebSocketServer(server, parseWebsocket => this._onConnect(parseWebsocket), config); // Initialize subscriber + + this.subscriber = _ParsePubSub.ParsePubSub.createSubscriber(config); + this.subscriber.subscribe(_node.default.applicationId + 'afterSave'); + this.subscriber.subscribe(_node.default.applicationId + 'afterDelete'); // Register message handler for subscriber. When publisher get messages, it will publish message + // to the subscribers and the handler will be called. + + this.subscriber.on('message', (channel, messageStr) => { + _logger.default.verbose('Subscribe messsage %j', messageStr); + + let message; + + try { + message = JSON.parse(messageStr); + } catch (e) { + _logger.default.error('unable to parse message', messageStr, e); + + return; + } + + this._inflateParseObject(message); + + if (channel === _node.default.applicationId + 'afterSave') { + this._onAfterSave(message); + } else if (channel === _node.default.applicationId + 'afterDelete') { + this._onAfterDelete(message); + } else { + _logger.default.error('Get message %s from unknown channel %j', message, channel); + } + }); + } // Message is the JSON object from publisher. Message.currentParseObject is the ParseObject JSON after changes. + // Message.originalParseObject is the original ParseObject JSON. + + + _inflateParseObject(message) { + // Inflate merged object + const currentParseObject = message.currentParseObject; + + _UsersRouter.default.removeHiddenProperties(currentParseObject); + + let className = currentParseObject.className; + let parseObject = new _node.default.Object(className); + + parseObject._finishFetch(currentParseObject); + + message.currentParseObject = parseObject; // Inflate original object + + const originalParseObject = message.originalParseObject; + + if (originalParseObject) { + _UsersRouter.default.removeHiddenProperties(originalParseObject); + + className = originalParseObject.className; + parseObject = new _node.default.Object(className); + + parseObject._finishFetch(originalParseObject); + + message.originalParseObject = parseObject; + } + } // Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes. + // Message.originalParseObject is the original ParseObject. + + + _onAfterDelete(message) { + _logger.default.verbose(_node.default.applicationId + 'afterDelete is triggered'); + + const deletedParseObject = message.currentParseObject.toJSON(); + const classLevelPermissions = message.classLevelPermissions; + const className = deletedParseObject.className; + + _logger.default.verbose('ClassName: %j | ObjectId: %s', className, deletedParseObject.id); + + _logger.default.verbose('Current client number : %d', this.clients.size); + + const classSubscriptions = this.subscriptions.get(className); + + if (typeof classSubscriptions === 'undefined') { + _logger.default.debug('Can not find subscriptions under this class ' + className); + + return; + } + + for (const subscription of classSubscriptions.values()) { + const isSubscriptionMatched = this._matchesSubscription(deletedParseObject, subscription); + + if (!isSubscriptionMatched) { + continue; + } + + for (const [clientId, requestIds] of _lodash.default.entries(subscription.clientRequestIds)) { + const client = this.clients.get(clientId); + + if (typeof client === 'undefined') { + continue; + } + + for (const requestId of requestIds) { + const acl = message.currentParseObject.getACL(); // Check CLP + + const op = this._getCLPOperation(subscription.query); + + this._matchesCLP(classLevelPermissions, message.currentParseObject, client, requestId, op).then(() => { + // Check ACL + return this._matchesACL(acl, client, requestId); + }).then(isMatched => { + if (!isMatched) { + return null; + } + + client.pushDelete(requestId, deletedParseObject); + }).catch(error => { + _logger.default.error('Matching ACL error : ', error); + }); + } + } + } + } // Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes. + // Message.originalParseObject is the original ParseObject. + + + _onAfterSave(message) { + _logger.default.verbose(_node.default.applicationId + 'afterSave is triggered'); + + let originalParseObject = null; + + if (message.originalParseObject) { + originalParseObject = message.originalParseObject.toJSON(); + } + + const classLevelPermissions = message.classLevelPermissions; + const currentParseObject = message.currentParseObject.toJSON(); + const className = currentParseObject.className; + + _logger.default.verbose('ClassName: %s | ObjectId: %s', className, currentParseObject.id); + + _logger.default.verbose('Current client number : %d', this.clients.size); + + const classSubscriptions = this.subscriptions.get(className); + + if (typeof classSubscriptions === 'undefined') { + _logger.default.debug('Can not find subscriptions under this class ' + className); + + return; + } + + for (const subscription of classSubscriptions.values()) { + const isOriginalSubscriptionMatched = this._matchesSubscription(originalParseObject, subscription); + + const isCurrentSubscriptionMatched = this._matchesSubscription(currentParseObject, subscription); + + for (const [clientId, requestIds] of _lodash.default.entries(subscription.clientRequestIds)) { + const client = this.clients.get(clientId); + + if (typeof client === 'undefined') { + continue; + } + + for (const requestId of requestIds) { + // Set orignal ParseObject ACL checking promise, if the object does not match + // subscription, we do not need to check ACL + let originalACLCheckingPromise; + + if (!isOriginalSubscriptionMatched) { + originalACLCheckingPromise = Promise.resolve(false); + } else { + let originalACL; + + if (message.originalParseObject) { + originalACL = message.originalParseObject.getACL(); + } + + originalACLCheckingPromise = this._matchesACL(originalACL, client, requestId); + } // Set current ParseObject ACL checking promise, if the object does not match + // subscription, we do not need to check ACL + + + let currentACLCheckingPromise; + + if (!isCurrentSubscriptionMatched) { + currentACLCheckingPromise = Promise.resolve(false); + } else { + const currentACL = message.currentParseObject.getACL(); + currentACLCheckingPromise = this._matchesACL(currentACL, client, requestId); + } + + const op = this._getCLPOperation(subscription.query); + + this._matchesCLP(classLevelPermissions, message.currentParseObject, client, requestId, op).then(() => { + return Promise.all([originalACLCheckingPromise, currentACLCheckingPromise]); + }).then(([isOriginalMatched, isCurrentMatched]) => { + _logger.default.verbose('Original %j | Current %j | Match: %s, %s, %s, %s | Query: %s', originalParseObject, currentParseObject, isOriginalSubscriptionMatched, isCurrentSubscriptionMatched, isOriginalMatched, isCurrentMatched, subscription.hash); // Decide event type + + + let type; + + if (isOriginalMatched && isCurrentMatched) { + type = 'Update'; + } else if (isOriginalMatched && !isCurrentMatched) { + type = 'Leave'; + } else if (!isOriginalMatched && isCurrentMatched) { + if (originalParseObject) { + type = 'Enter'; + } else { + type = 'Create'; + } + } else { + return null; + } + + const functionName = 'push' + type; + client[functionName](requestId, currentParseObject, originalParseObject); + }, error => { + _logger.default.error('Matching ACL error : ', error); + }); + } + } + } + } + + _onConnect(parseWebsocket) { + parseWebsocket.on('message', request => { + if (typeof request === 'string') { + try { + request = JSON.parse(request); + } catch (e) { + _logger.default.error('unable to parse request', request, e); + + return; + } + } + + _logger.default.verbose('Request: %j', request); // Check whether this request is a valid request, return error directly if not + + + if (!_tv.default.validate(request, _RequestSchema.default['general']) || !_tv.default.validate(request, _RequestSchema.default[request.op])) { + _Client.Client.pushError(parseWebsocket, 1, _tv.default.error.message); + + _logger.default.error('Connect message error %s', _tv.default.error.message); + + return; + } + + switch (request.op) { + case 'connect': + this._handleConnect(parseWebsocket, request); + + break; + + case 'subscribe': + this._handleSubscribe(parseWebsocket, request); + + break; + + case 'update': + this._handleUpdateSubscription(parseWebsocket, request); + + break; + + case 'unsubscribe': + this._handleUnsubscribe(parseWebsocket, request); + + break; + + default: + _Client.Client.pushError(parseWebsocket, 3, 'Get unknown operation'); + + _logger.default.error('Get unknown operation', request.op); + + } + }); + parseWebsocket.on('disconnect', () => { + _logger.default.info(`Client disconnect: ${parseWebsocket.clientId}`); + + const clientId = parseWebsocket.clientId; + + if (!this.clients.has(clientId)) { + (0, _triggers.runLiveQueryEventHandlers)({ + event: 'ws_disconnect_error', + clients: this.clients.size, + subscriptions: this.subscriptions.size, + error: `Unable to find client ${clientId}` + }); + + _logger.default.error(`Can not find client ${clientId} on disconnect`); + + return; + } // Delete client + + + const client = this.clients.get(clientId); + this.clients.delete(clientId); // Delete client from subscriptions + + for (const [requestId, subscriptionInfo] of _lodash.default.entries(client.subscriptionInfos)) { + const subscription = subscriptionInfo.subscription; + subscription.deleteClientSubscription(clientId, requestId); // If there is no client which is subscribing this subscription, remove it from subscriptions + + const classSubscriptions = this.subscriptions.get(subscription.className); + + if (!subscription.hasSubscribingClient()) { + classSubscriptions.delete(subscription.hash); + } // If there is no subscriptions under this class, remove it from subscriptions + + + if (classSubscriptions.size === 0) { + this.subscriptions.delete(subscription.className); + } + } + + _logger.default.verbose('Current clients %d', this.clients.size); + + _logger.default.verbose('Current subscriptions %d', this.subscriptions.size); + + (0, _triggers.runLiveQueryEventHandlers)({ + event: 'ws_disconnect', + clients: this.clients.size, + subscriptions: this.subscriptions.size, + useMasterKey: client.hasMasterKey, + installationId: client.installationId + }); + }); + (0, _triggers.runLiveQueryEventHandlers)({ + event: 'ws_connect', + clients: this.clients.size, + subscriptions: this.subscriptions.size + }); + } + + _matchesSubscription(parseObject, subscription) { + // Object is undefined or null, not match + if (!parseObject) { + return false; + } + + return (0, _QueryTools.matchesQuery)(parseObject, subscription.query); + } + + getAuthForSessionToken(sessionToken) { + if (!sessionToken) { + return Promise.resolve({}); + } + + const fromCache = this.authCache.get(sessionToken); + + if (fromCache) { + return fromCache; + } + + const authPromise = (0, _Auth.getAuthForSessionToken)({ + cacheController: this.cacheController, + sessionToken: sessionToken + }).then(auth => { + return { + auth, + userId: auth && auth.user && auth.user.id + }; + }).catch(error => { + // There was an error with the session token + const result = {}; + + if (error && error.code === _node.default.Error.INVALID_SESSION_TOKEN) { + // Store a resolved promise with the error for 10 minutes + result.error = error; + this.authCache.set(sessionToken, Promise.resolve(result), 60 * 10 * 1000); + } else { + this.authCache.del(sessionToken); + } + + return result; + }); + this.authCache.set(sessionToken, authPromise); + return authPromise; + } + + async _matchesCLP(classLevelPermissions, object, client, requestId, op) { + // try to match on user first, less expensive than with roles + const subscriptionInfo = client.getSubscriptionInfo(requestId); + const aclGroup = ['*']; + let userId; + + if (typeof subscriptionInfo !== 'undefined') { + const { + userId + } = await this.getAuthForSessionToken(subscriptionInfo.sessionToken); + + if (userId) { + aclGroup.push(userId); + } + } + + try { + await _SchemaController.default.validatePermission(classLevelPermissions, object.className, aclGroup, op); + return true; + } catch (e) { + _logger.default.verbose(`Failed matching CLP for ${object.id} ${userId} ${e}`); + + return false; + } // TODO: handle roles permissions + // Object.keys(classLevelPermissions).forEach((key) => { + // const perm = classLevelPermissions[key]; + // Object.keys(perm).forEach((key) => { + // if (key.indexOf('role')) + // }); + // }) + // // it's rejected here, check the roles + // var rolesQuery = new Parse.Query(Parse.Role); + // rolesQuery.equalTo("users", user); + // return rolesQuery.find({useMasterKey:true}); + + } + + _getCLPOperation(query) { + return typeof query === 'object' && Object.keys(query).length == 1 && typeof query.objectId === 'string' ? 'get' : 'find'; + } + + async _verifyACL(acl, token) { + if (!token) { + return false; + } + + const { + auth, + userId + } = await this.getAuthForSessionToken(token); // Getting the session token failed + // This means that no additional auth is available + // At this point, just bail out as no additional visibility can be inferred. + + if (!auth || !userId) { + return false; + } + + const isSubscriptionSessionTokenMatched = acl.getReadAccess(userId); + + if (isSubscriptionSessionTokenMatched) { + return true; + } // Check if the user has any roles that match the ACL + + + return Promise.resolve().then(async () => { + // Resolve false right away if the acl doesn't have any roles + const acl_has_roles = Object.keys(acl.permissionsById).some(key => key.startsWith('role:')); + + if (!acl_has_roles) { + return false; + } + + const roleNames = await auth.getUserRoles(); // Finally, see if any of the user's roles allow them read access + + for (const role of roleNames) { + // We use getReadAccess as `role` is in the form `role:roleName` + if (acl.getReadAccess(role)) { + return true; + } + } + + return false; + }).catch(() => { + return false; + }); + } + + async _matchesACL(acl, client, requestId) { + // Return true directly if ACL isn't present, ACL is public read, or client has master key + if (!acl || acl.getPublicReadAccess() || client.hasMasterKey) { + return true; + } // Check subscription sessionToken matches ACL first + + + const subscriptionInfo = client.getSubscriptionInfo(requestId); + + if (typeof subscriptionInfo === 'undefined') { + return false; + } + + const subscriptionToken = subscriptionInfo.sessionToken; + const clientSessionToken = client.sessionToken; + + if (await this._verifyACL(acl, subscriptionToken)) { + return true; + } + + if (await this._verifyACL(acl, clientSessionToken)) { + return true; + } + + return false; + } + + _handleConnect(parseWebsocket, request) { + if (!this._validateKeys(request, this.keyPairs)) { + _Client.Client.pushError(parseWebsocket, 4, 'Key in request is not valid'); + + _logger.default.error('Key in request is not valid'); + + return; + } + + const hasMasterKey = this._hasMasterKey(request, this.keyPairs); + + const clientId = (0, _uuid.default)(); + const client = new _Client.Client(clientId, parseWebsocket, hasMasterKey, request.sessionToken, request.installationId); + parseWebsocket.clientId = clientId; + this.clients.set(parseWebsocket.clientId, client); + + _logger.default.info(`Create new client: ${parseWebsocket.clientId}`); + + client.pushConnect(); + (0, _triggers.runLiveQueryEventHandlers)({ + client, + event: 'connect', + clients: this.clients.size, + subscriptions: this.subscriptions.size, + sessionToken: request.sessionToken, + useMasterKey: client.hasMasterKey, + installationId: request.installationId + }); + } + + _hasMasterKey(request, validKeyPairs) { + if (!validKeyPairs || validKeyPairs.size == 0 || !validKeyPairs.has('masterKey')) { + return false; + } + + if (!request || !Object.prototype.hasOwnProperty.call(request, 'masterKey')) { + return false; + } + + return request.masterKey === validKeyPairs.get('masterKey'); + } + + _validateKeys(request, validKeyPairs) { + if (!validKeyPairs || validKeyPairs.size == 0) { + return true; + } + + let isValid = false; + + for (const [key, secret] of validKeyPairs) { + if (!request[key] || request[key] !== secret) { + continue; + } + + isValid = true; + break; + } + + return isValid; + } + + _handleSubscribe(parseWebsocket, request) { + // If we can not find this client, return error to client + if (!Object.prototype.hasOwnProperty.call(parseWebsocket, 'clientId')) { + _Client.Client.pushError(parseWebsocket, 2, 'Can not find this client, make sure you connect to server before subscribing'); + + _logger.default.error('Can not find this client, make sure you connect to server before subscribing'); + + return; + } + + const client = this.clients.get(parseWebsocket.clientId); // Get subscription from subscriptions, create one if necessary + + const subscriptionHash = (0, _QueryTools.queryHash)(request.query); // Add className to subscriptions if necessary + + const className = request.query.className; + + if (!this.subscriptions.has(className)) { + this.subscriptions.set(className, new Map()); + } + + const classSubscriptions = this.subscriptions.get(className); + let subscription; + + if (classSubscriptions.has(subscriptionHash)) { + subscription = classSubscriptions.get(subscriptionHash); + } else { + subscription = new _Subscription.Subscription(className, request.query.where, subscriptionHash); + classSubscriptions.set(subscriptionHash, subscription); + } // Add subscriptionInfo to client + + + const subscriptionInfo = { + subscription: subscription + }; // Add selected fields, sessionToken and installationId for this subscription if necessary + + if (request.query.fields) { + subscriptionInfo.fields = request.query.fields; + } + + if (request.sessionToken) { + subscriptionInfo.sessionToken = request.sessionToken; + } + + client.addSubscriptionInfo(request.requestId, subscriptionInfo); // Add clientId to subscription + + subscription.addClientSubscription(parseWebsocket.clientId, request.requestId); + client.pushSubscribe(request.requestId); + + _logger.default.verbose(`Create client ${parseWebsocket.clientId} new subscription: ${request.requestId}`); + + _logger.default.verbose('Current client number: %d', this.clients.size); + + (0, _triggers.runLiveQueryEventHandlers)({ + client, + event: 'subscribe', + clients: this.clients.size, + subscriptions: this.subscriptions.size, + sessionToken: request.sessionToken, + useMasterKey: client.hasMasterKey, + installationId: client.installationId + }); + } + + _handleUpdateSubscription(parseWebsocket, request) { + this._handleUnsubscribe(parseWebsocket, request, false); + + this._handleSubscribe(parseWebsocket, request); + } + + _handleUnsubscribe(parseWebsocket, request, notifyClient = true) { + // If we can not find this client, return error to client + if (!Object.prototype.hasOwnProperty.call(parseWebsocket, 'clientId')) { + _Client.Client.pushError(parseWebsocket, 2, 'Can not find this client, make sure you connect to server before unsubscribing'); + + _logger.default.error('Can not find this client, make sure you connect to server before unsubscribing'); + + return; + } + + const requestId = request.requestId; + const client = this.clients.get(parseWebsocket.clientId); + + if (typeof client === 'undefined') { + _Client.Client.pushError(parseWebsocket, 2, 'Cannot find client with clientId ' + parseWebsocket.clientId + '. Make sure you connect to live query server before unsubscribing.'); + + _logger.default.error('Can not find this client ' + parseWebsocket.clientId); + + return; + } + + const subscriptionInfo = client.getSubscriptionInfo(requestId); + + if (typeof subscriptionInfo === 'undefined') { + _Client.Client.pushError(parseWebsocket, 2, 'Cannot find subscription with clientId ' + parseWebsocket.clientId + ' subscriptionId ' + requestId + '. Make sure you subscribe to live query server before unsubscribing.'); + + _logger.default.error('Can not find subscription with clientId ' + parseWebsocket.clientId + ' subscriptionId ' + requestId); + + return; + } // Remove subscription from client + + + client.deleteSubscriptionInfo(requestId); // Remove client from subscription + + const subscription = subscriptionInfo.subscription; + const className = subscription.className; + subscription.deleteClientSubscription(parseWebsocket.clientId, requestId); // If there is no client which is subscribing this subscription, remove it from subscriptions + + const classSubscriptions = this.subscriptions.get(className); + + if (!subscription.hasSubscribingClient()) { + classSubscriptions.delete(subscription.hash); + } // If there is no subscriptions under this class, remove it from subscriptions + + + if (classSubscriptions.size === 0) { + this.subscriptions.delete(className); + } + + (0, _triggers.runLiveQueryEventHandlers)({ + client, + event: 'unsubscribe', + clients: this.clients.size, + subscriptions: this.subscriptions.size, + sessionToken: subscriptionInfo.sessionToken, + useMasterKey: client.hasMasterKey, + installationId: client.installationId + }); + + if (!notifyClient) { + return; + } + + client.pushUnsubscribe(request.requestId); + + _logger.default.verbose(`Delete client: ${parseWebsocket.clientId} | subscription: ${request.requestId}`); + } + +} + +exports.ParseLiveQueryServer = ParseLiveQueryServer; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VMaXZlUXVlcnlTZXJ2ZXIuanMiXSwibmFtZXMiOlsiUGFyc2VMaXZlUXVlcnlTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsInNlcnZlciIsImNvbmZpZyIsImNsaWVudHMiLCJNYXAiLCJzdWJzY3JpcHRpb25zIiwiYXBwSWQiLCJQYXJzZSIsImFwcGxpY2F0aW9uSWQiLCJtYXN0ZXJLZXkiLCJrZXlQYWlycyIsImtleSIsIk9iamVjdCIsImtleXMiLCJzZXQiLCJsb2dnZXIiLCJ2ZXJib3NlIiwiZGlzYWJsZVNpbmdsZUluc3RhbmNlIiwic2VydmVyVVJMIiwiaW5pdGlhbGl6ZSIsImphdmFTY3JpcHRLZXkiLCJjYWNoZUNvbnRyb2xsZXIiLCJhdXRoQ2FjaGUiLCJMUlUiLCJtYXgiLCJtYXhBZ2UiLCJwYXJzZVdlYlNvY2tldFNlcnZlciIsIlBhcnNlV2ViU29ja2V0U2VydmVyIiwicGFyc2VXZWJzb2NrZXQiLCJfb25Db25uZWN0Iiwic3Vic2NyaWJlciIsIlBhcnNlUHViU3ViIiwiY3JlYXRlU3Vic2NyaWJlciIsInN1YnNjcmliZSIsIm9uIiwiY2hhbm5lbCIsIm1lc3NhZ2VTdHIiLCJtZXNzYWdlIiwiSlNPTiIsInBhcnNlIiwiZSIsImVycm9yIiwiX2luZmxhdGVQYXJzZU9iamVjdCIsIl9vbkFmdGVyU2F2ZSIsIl9vbkFmdGVyRGVsZXRlIiwiY3VycmVudFBhcnNlT2JqZWN0IiwiVXNlclJvdXRlciIsInJlbW92ZUhpZGRlblByb3BlcnRpZXMiLCJjbGFzc05hbWUiLCJwYXJzZU9iamVjdCIsIl9maW5pc2hGZXRjaCIsIm9yaWdpbmFsUGFyc2VPYmplY3QiLCJkZWxldGVkUGFyc2VPYmplY3QiLCJ0b0pTT04iLCJjbGFzc0xldmVsUGVybWlzc2lvbnMiLCJpZCIsInNpemUiLCJjbGFzc1N1YnNjcmlwdGlvbnMiLCJnZXQiLCJkZWJ1ZyIsInN1YnNjcmlwdGlvbiIsInZhbHVlcyIsImlzU3Vic2NyaXB0aW9uTWF0Y2hlZCIsIl9tYXRjaGVzU3Vic2NyaXB0aW9uIiwiY2xpZW50SWQiLCJyZXF1ZXN0SWRzIiwiXyIsImVudHJpZXMiLCJjbGllbnRSZXF1ZXN0SWRzIiwiY2xpZW50IiwicmVxdWVzdElkIiwiYWNsIiwiZ2V0QUNMIiwib3AiLCJfZ2V0Q0xQT3BlcmF0aW9uIiwicXVlcnkiLCJfbWF0Y2hlc0NMUCIsInRoZW4iLCJfbWF0Y2hlc0FDTCIsImlzTWF0Y2hlZCIsInB1c2hEZWxldGUiLCJjYXRjaCIsImlzT3JpZ2luYWxTdWJzY3JpcHRpb25NYXRjaGVkIiwiaXNDdXJyZW50U3Vic2NyaXB0aW9uTWF0Y2hlZCIsIm9yaWdpbmFsQUNMQ2hlY2tpbmdQcm9taXNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJvcmlnaW5hbEFDTCIsImN1cnJlbnRBQ0xDaGVja2luZ1Byb21pc2UiLCJjdXJyZW50QUNMIiwiYWxsIiwiaXNPcmlnaW5hbE1hdGNoZWQiLCJpc0N1cnJlbnRNYXRjaGVkIiwiaGFzaCIsInR5cGUiLCJmdW5jdGlvbk5hbWUiLCJyZXF1ZXN0IiwidHY0IiwidmFsaWRhdGUiLCJSZXF1ZXN0U2NoZW1hIiwiQ2xpZW50IiwicHVzaEVycm9yIiwiX2hhbmRsZUNvbm5lY3QiLCJfaGFuZGxlU3Vic2NyaWJlIiwiX2hhbmRsZVVwZGF0ZVN1YnNjcmlwdGlvbiIsIl9oYW5kbGVVbnN1YnNjcmliZSIsImluZm8iLCJoYXMiLCJldmVudCIsImRlbGV0ZSIsInN1YnNjcmlwdGlvbkluZm8iLCJzdWJzY3JpcHRpb25JbmZvcyIsImRlbGV0ZUNsaWVudFN1YnNjcmlwdGlvbiIsImhhc1N1YnNjcmliaW5nQ2xpZW50IiwidXNlTWFzdGVyS2V5IiwiaGFzTWFzdGVyS2V5IiwiaW5zdGFsbGF0aW9uSWQiLCJnZXRBdXRoRm9yU2Vzc2lvblRva2VuIiwic2Vzc2lvblRva2VuIiwiZnJvbUNhY2hlIiwiYXV0aFByb21pc2UiLCJhdXRoIiwidXNlcklkIiwidXNlciIsInJlc3VsdCIsImNvZGUiLCJFcnJvciIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsImRlbCIsIm9iamVjdCIsImdldFN1YnNjcmlwdGlvbkluZm8iLCJhY2xHcm91cCIsInB1c2giLCJTY2hlbWFDb250cm9sbGVyIiwidmFsaWRhdGVQZXJtaXNzaW9uIiwibGVuZ3RoIiwib2JqZWN0SWQiLCJfdmVyaWZ5QUNMIiwidG9rZW4iLCJpc1N1YnNjcmlwdGlvblNlc3Npb25Ub2tlbk1hdGNoZWQiLCJnZXRSZWFkQWNjZXNzIiwiYWNsX2hhc19yb2xlcyIsInBlcm1pc3Npb25zQnlJZCIsInNvbWUiLCJzdGFydHNXaXRoIiwicm9sZU5hbWVzIiwiZ2V0VXNlclJvbGVzIiwicm9sZSIsImdldFB1YmxpY1JlYWRBY2Nlc3MiLCJzdWJzY3JpcHRpb25Ub2tlbiIsImNsaWVudFNlc3Npb25Ub2tlbiIsIl92YWxpZGF0ZUtleXMiLCJfaGFzTWFzdGVyS2V5IiwicHVzaENvbm5lY3QiLCJ2YWxpZEtleVBhaXJzIiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaXNWYWxpZCIsInNlY3JldCIsInN1YnNjcmlwdGlvbkhhc2giLCJTdWJzY3JpcHRpb24iLCJ3aGVyZSIsImZpZWxkcyIsImFkZFN1YnNjcmlwdGlvbkluZm8iLCJhZGRDbGllbnRTdWJzY3JpcHRpb24iLCJwdXNoU3Vic2NyaWJlIiwibm90aWZ5Q2xpZW50IiwiZGVsZXRlU3Vic2NyaXB0aW9uSW5mbyIsInB1c2hVbnN1YnNjcmliZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEsb0JBQU4sQ0FBMkI7QUFFekI7QUFJQTtBQUdBQyxFQUFBQSxXQUFXLENBQUNDLE1BQUQsRUFBY0MsTUFBVyxHQUFHLEVBQTVCLEVBQWdDO0FBQ3pDLFNBQUtELE1BQUwsR0FBY0EsTUFBZDtBQUNBLFNBQUtFLE9B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dCI6WyJpbXBvcnQgdHY0IGZyb20gJ3R2NCc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICcuL1N1YnNjcmlwdGlvbic7XG5pbXBvcnQgeyBDbGllbnQgfSBmcm9tICcuL0NsaWVudCc7XG5pbXBvcnQgeyBQYXJzZVdlYlNvY2tldFNlcnZlciB9IGZyb20gJy4vUGFyc2VXZWJTb2NrZXRTZXJ2ZXInO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IFJlcXVlc3RTY2hlbWEgZnJvbSAnLi9SZXF1ZXN0U2NoZW1hJztcbmltcG9ydCB7IG1hdGNoZXNRdWVyeSwgcXVlcnlIYXNoIH0gZnJvbSAnLi9RdWVyeVRvb2xzJztcbmltcG9ydCB7IFBhcnNlUHViU3ViIH0gZnJvbSAnLi9QYXJzZVB1YlN1Yic7XG5pbXBvcnQgU2NoZW1hQ29udHJvbGxlciBmcm9tICcuLi9Db250cm9sbGVycy9TY2hlbWFDb250cm9sbGVyJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgdXVpZCBmcm9tICd1dWlkJztcbmltcG9ydCB7IHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMgfSBmcm9tICcuLi90cmlnZ2Vycyc7XG5pbXBvcnQgeyBnZXRBdXRoRm9yU2Vzc2lvblRva2VuLCBBdXRoIH0gZnJvbSAnLi4vQXV0aCc7XG5pbXBvcnQgeyBnZXRDYWNoZUNvbnRyb2xsZXIgfSBmcm9tICcuLi9Db250cm9sbGVycyc7XG5pbXBvcnQgTFJVIGZyb20gJ2xydS1jYWNoZSc7XG5pbXBvcnQgVXNlclJvdXRlciBmcm9tICcuLi9Sb3V0ZXJzL1VzZXJzUm91dGVyJztcblxuY2xhc3MgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIge1xuICBjbGllbnRzOiBNYXA7XG4gIC8vIGNsYXNzTmFtZSAtPiAocXVlcnlIYXNoIC0+IHN1YnNjcmlwdGlvbilcbiAgc3Vic2NyaXB0aW9uczogT2JqZWN0O1xuICBwYXJzZVdlYlNvY2tldFNlcnZlcjogT2JqZWN0O1xuICBrZXlQYWlyczogYW55O1xuICAvLyBUaGUgc3Vic2NyaWJlciB3ZSB1c2UgdG8gZ2V0IG9iamVjdCB1cGRhdGUgZnJvbSBwdWJsaXNoZXJcbiAgc3Vic2NyaWJlcjogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcjogYW55LCBjb25maWc6IGFueSA9IHt9KSB7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgdGhpcy5jbGllbnRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucyA9IG5ldyBNYXAoKTtcblxuICAgIGNvbmZpZy5hcHBJZCA9IGNvbmZpZy5hcHBJZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICAgIGNvbmZpZy5tYXN0ZXJLZXkgPSBjb25maWcubWFzdGVyS2V5IHx8IFBhcnNlLm1hc3RlcktleTtcblxuICAgIC8vIFN0b3JlIGtleXMsIGNvbnZlcnQgb2JqIHRvIG1hcFxuICAgIGNvbnN0IGtleVBhaXJzID0gY29uZmlnLmtleVBhaXJzIHx8IHt9O1xuICAgIHRoaXMua2V5UGFpcnMgPSBuZXcgTWFwKCk7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoa2V5UGFpcnMpKSB7XG4gICAgICB0aGlzLmtleVBhaXJzLnNldChrZXksIGtleVBhaXJzW2tleV0pO1xuICAgIH1cbiAgICBsb2dnZXIudmVyYm9zZSgnU3VwcG9ydCBrZXkgcGFpcnMnLCB0aGlzLmtleVBhaXJzKTtcblxuICAgIC8vIEluaXRpYWxpemUgUGFyc2VcbiAgICBQYXJzZS5PYmplY3QuZGlzYWJsZVNpbmdsZUluc3RhbmNlKCk7XG4gICAgY29uc3Qgc2VydmVyVVJMID0gY29uZmlnLnNlcnZlclVSTCB8fCBQYXJzZS5zZXJ2ZXJVUkw7XG4gICAgUGFyc2Uuc2VydmVyVVJMID0gc2VydmVyVVJMO1xuICAgIFBhcnNlLmluaXRpYWxpemUoY29uZmlnLmFwcElkLCBQYXJzZS5qYXZhU2NyaXB0S2V5LCBjb25maWcubWFzdGVyS2V5KTtcblxuICAgIC8vIFRoZSBjYWNoZSBjb250cm9sbGVyIGlzIGEgcHJvcGVyIGNhY2hlIGNvbnRyb2xsZXJcbiAgICAvLyB3aXRoIGFjY2VzcyB0byBVc2VyIGFuZCBSb2xlc1xuICAgIHRoaXMuY2FjaGVDb250cm9sbGVyID0gZ2V0Q2FjaGVDb250cm9sbGVyKGNvbmZpZyk7XG5cbiAgICAvLyBUaGlzIGF1dGggY2FjaGUgc3RvcmVzIHRoZSBwcm9taXNlcyBmb3IgZWFjaCBhdXRoIHJlc29sdXRpb24uXG4gICAgLy8gVGhlIG1haW4gYmVuZWZpdCBpcyB0byBiZSBhYmxlIHRvIHJldXNlIHRoZSBzYW1lIHVzZXIgLyBzZXNzaW9uIHRva2VuIHJlc29sdXRpb24uXG4gICAgdGhpcy5hdXRoQ2FjaGUgPSBuZXcgTFJVKHtcbiAgICAgIG1heDogNTAwLCAvLyA1MDAgY29uY3VycmVudFxuICAgICAgbWF4QWdlOiA2MCAqIDYwICogMTAwMCwgLy8gMWhcbiAgICB9KTtcbiAgICAvLyBJbml0aWFsaXplIHdlYnNvY2tldCBzZXJ2ZXJcbiAgICB0aGlzLnBhcnNlV2ViU29ja2V0U2VydmVyID0gbmV3IFBhcnNlV2ViU29ja2V0U2VydmVyKFxuICAgICAgc2VydmVyLFxuICAgICAgcGFyc2VXZWJzb2NrZXQgPT4gdGhpcy5fb25Db25uZWN0KHBhcnNlV2Vic29ja2V0KSxcbiAgICAgIGNvbmZpZ1xuICAgICk7XG5cbiAgICAvLyBJbml0aWFsaXplIHN1YnNjcmliZXJcbiAgICB0aGlzLnN1YnNjcmliZXIgPSBQYXJzZVB1YlN1Yi5jcmVhdGVTdWJzY3JpYmVyKGNvbmZpZyk7XG4gICAgdGhpcy5zdWJzY3JpYmVyLnN1YnNjcmliZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyU2F2ZScpO1xuICAgIHRoaXMuc3Vic2NyaWJlci5zdWJzY3JpYmUoUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlckRlbGV0ZScpO1xuICAgIC8vIFJlZ2lzdGVyIG1lc3NhZ2UgaGFuZGxlciBmb3Igc3Vic2NyaWJlci4gV2hlbiBwdWJsaXNoZXIgZ2V0IG1lc3NhZ2VzLCBpdCB3aWxsIHB1Ymxpc2ggbWVzc2FnZVxuICAgIC8vIHRvIHRoZSBzdWJzY3JpYmVycyBhbmQgdGhlIGhhbmRsZXIgd2lsbCBiZSBjYWxsZWQuXG4gICAgdGhpcy5zdWJzY3JpYmVyLm9uKCdtZXNzYWdlJywgKGNoYW5uZWwsIG1lc3NhZ2VTdHIpID0+IHtcbiAgICAgIGxvZ2dlci52ZXJib3NlKCdTdWJzY3JpYmUgbWVzc3NhZ2UgJWonLCBtZXNzYWdlU3RyKTtcbiAgICAgIGxldCBtZXNzYWdlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2UobWVzc2FnZVN0cik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcigndW5hYmxlIHRvIHBhcnNlIG1lc3NhZ2UnLCBtZXNzYWdlU3RyLCBlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5faW5mbGF0ZVBhcnNlT2JqZWN0KG1lc3NhZ2UpO1xuICAgICAgaWYgKGNoYW5uZWwgPT09IFBhcnNlLmFwcGxpY2F0aW9uSWQgKyAnYWZ0ZXJTYXZlJykge1xuICAgICAgICB0aGlzLl9vbkFmdGVyU2F2ZShtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhbm5lbCA9PT0gUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlckRlbGV0ZScpIHtcbiAgICAgICAgdGhpcy5fb25BZnRlckRlbGV0ZShtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICAnR2V0IG1lc3NhZ2UgJXMgZnJvbSB1bmtub3duIGNoYW5uZWwgJWonLFxuICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgY2hhbm5lbFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gTWVzc2FnZSBpcyB0aGUgSlNPTiBvYmplY3QgZnJvbSBwdWJsaXNoZXIuIE1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0IGlzIHRoZSBQYXJzZU9iamVjdCBKU09OIGFmdGVyIGNoYW5nZXMuXG4gIC8vIE1lc3NhZ2Uub3JpZ2luYWxQYXJzZU9iamVjdCBpcyB0aGUgb3JpZ2luYWwgUGFyc2VPYmplY3QgSlNPTi5cbiAgX2luZmxhdGVQYXJzZU9iamVjdChtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICAvLyBJbmZsYXRlIG1lcmdlZCBvYmplY3RcbiAgICBjb25zdCBjdXJyZW50UGFyc2VPYmplY3QgPSBtZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdDtcbiAgICBVc2VyUm91dGVyLnJlbW92ZUhpZGRlblByb3BlcnRpZXMoY3VycmVudFBhcnNlT2JqZWN0KTtcbiAgICBsZXQgY2xhc3NOYW1lID0gY3VycmVudFBhcnNlT2JqZWN0LmNsYXNzTmFtZTtcbiAgICBsZXQgcGFyc2VPYmplY3QgPSBuZXcgUGFyc2UuT2JqZWN0KGNsYXNzTmFtZSk7XG4gICAgcGFyc2VPYmplY3QuX2ZpbmlzaEZldGNoKGN1cnJlbnRQYXJzZU9iamVjdCk7XG4gICAgbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QgPSBwYXJzZU9iamVjdDtcbiAgICAvLyBJbmZsYXRlIG9yaWdpbmFsIG9iamVjdFxuICAgIGNvbnN0IG9yaWdpbmFsUGFyc2VPYmplY3QgPSBtZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3Q7XG4gICAgaWYgKG9yaWdpbmFsUGFyc2VPYmplY3QpIHtcbiAgICAgIFVzZXJSb3V0ZXIucmVtb3ZlSGlkZGVuUHJvcGVydGllcyhvcmlnaW5hbFBhcnNlT2JqZWN0KTtcbiAgICAgIGNsYXNzTmFtZSA9IG9yaWdpbmFsUGFyc2VPYmplY3QuY2xhc3NOYW1lO1xuICAgICAgcGFyc2VPYmplY3QgPSBuZXcgUGFyc2UuT2JqZWN0KGNsYXNzTmFtZSk7XG4gICAgICBwYXJzZU9iamVjdC5fZmluaXNoRmV0Y2gob3JpZ2luYWxQYXJzZU9iamVjdCk7XG4gICAgICBtZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgPSBwYXJzZU9iamVjdDtcbiAgICB9XG4gIH1cblxuICAvLyBNZXNzYWdlIGlzIHRoZSBKU09OIG9iamVjdCBmcm9tIHB1Ymxpc2hlciBhZnRlciBpbmZsYXRlZC4gTWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QgaXMgdGhlIFBhcnNlT2JqZWN0IGFmdGVyIGNoYW5nZXMuXG4gIC8vIE1lc3NhZ2Uub3JpZ2luYWxQYXJzZU9iamVjdCBpcyB0aGUgb3JpZ2luYWwgUGFyc2VPYmplY3QuXG4gIF9vbkFmdGVyRGVsZXRlKG1lc3NhZ2U6IGFueSk6IHZvaWQge1xuICAgIGxvZ2dlci52ZXJib3NlKFBhcnNlLmFwcGxpY2F0aW9uSWQgKyAnYWZ0ZXJEZWxldGUgaXMgdHJpZ2dlcmVkJyk7XG5cbiAgICBjb25zdCBkZWxldGVkUGFyc2VPYmplY3QgPSBtZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdC50b0pTT04oKTtcbiAgICBjb25zdCBjbGFzc0xldmVsUGVybWlzc2lvbnMgPSBtZXNzYWdlLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucztcbiAgICBjb25zdCBjbGFzc05hbWUgPSBkZWxldGVkUGFyc2VPYmplY3QuY2xhc3NOYW1lO1xuICAgIGxvZ2dlci52ZXJib3NlKFxuICAgICAgJ0NsYXNzTmFtZTogJWogfCBPYmplY3RJZDogJXMnLFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgZGVsZXRlZFBhcnNlT2JqZWN0LmlkXG4gICAgKTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBjbGllbnQgbnVtYmVyIDogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG5cbiAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgaWYgKHR5cGVvZiBjbGFzc1N1YnNjcmlwdGlvbnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NhbiBub3QgZmluZCBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MgJyArIGNsYXNzTmFtZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc3Vic2NyaXB0aW9uIG9mIGNsYXNzU3Vic2NyaXB0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgY29uc3QgaXNTdWJzY3JpcHRpb25NYXRjaGVkID0gdGhpcy5fbWF0Y2hlc1N1YnNjcmlwdGlvbihcbiAgICAgICAgZGVsZXRlZFBhcnNlT2JqZWN0LFxuICAgICAgICBzdWJzY3JpcHRpb25cbiAgICAgICk7XG4gICAgICBpZiAoIWlzU3Vic2NyaXB0aW9uTWF0Y2hlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgW2NsaWVudElkLCByZXF1ZXN0SWRzXSBvZiBfLmVudHJpZXMoXG4gICAgICAgIHN1YnNjcmlwdGlvbi5jbGllbnRSZXF1ZXN0SWRzXG4gICAgICApKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQoY2xpZW50SWQpO1xuICAgICAgICBpZiAodHlwZW9mIGNsaWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiByZXF1ZXN0SWRzKSB7XG4gICAgICAgICAgY29uc3QgYWNsID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QuZ2V0QUNMKCk7XG4gICAgICAgICAgLy8gQ2hlY2sgQ0xQXG4gICAgICAgICAgY29uc3Qgb3AgPSB0aGlzLl9nZXRDTFBPcGVyYXRpb24oc3Vic2NyaXB0aW9uLnF1ZXJ5KTtcbiAgICAgICAgICB0aGlzLl9tYXRjaGVzQ0xQKFxuICAgICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgICAgICAgbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QsXG4gICAgICAgICAgICBjbGllbnQsXG4gICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICBvcFxuICAgICAgICAgIClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgLy8gQ2hlY2sgQUNMXG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tYXRjaGVzQUNMKGFjbCwgY2xpZW50LCByZXF1ZXN0SWQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKGlzTWF0Y2hlZCA9PiB7XG4gICAgICAgICAgICAgIGlmICghaXNNYXRjaGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY2xpZW50LnB1c2hEZWxldGUocmVxdWVzdElkLCBkZWxldGVkUGFyc2VPYmplY3QpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignTWF0Y2hpbmcgQUNMIGVycm9yIDogJywgZXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBNZXNzYWdlIGlzIHRoZSBKU09OIG9iamVjdCBmcm9tIHB1Ymxpc2hlciBhZnRlciBpbmZsYXRlZC4gTWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QgaXMgdGhlIFBhcnNlT2JqZWN0IGFmdGVyIGNoYW5nZXMuXG4gIC8vIE1lc3NhZ2Uub3JpZ2luYWxQYXJzZU9iamVjdCBpcyB0aGUgb3JpZ2luYWwgUGFyc2VPYmplY3QuXG4gIF9vbkFmdGVyU2F2ZShtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICBsb2dnZXIudmVyYm9zZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyU2F2ZSBpcyB0cmlnZ2VyZWQnKTtcblxuICAgIGxldCBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbnVsbDtcbiAgICBpZiAobWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0LnRvSlNPTigpO1xuICAgIH1cbiAgICBjb25zdCBjbGFzc0xldmVsUGVybWlzc2lvbnMgPSBtZXNzYWdlLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucztcbiAgICBjb25zdCBjdXJyZW50UGFyc2VPYmplY3QgPSBtZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdC50b0pTT04oKTtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBjdXJyZW50UGFyc2VPYmplY3QuY2xhc3NOYW1lO1xuICAgIGxvZ2dlci52ZXJib3NlKFxuICAgICAgJ0NsYXNzTmFtZTogJXMgfCBPYmplY3RJZDogJXMnLFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgY3VycmVudFBhcnNlT2JqZWN0LmlkXG4gICAgKTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBjbGllbnQgbnVtYmVyIDogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG5cbiAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgaWYgKHR5cGVvZiBjbGFzc1N1YnNjcmlwdGlvbnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NhbiBub3QgZmluZCBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MgJyArIGNsYXNzTmFtZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc3Vic2NyaXB0aW9uIG9mIGNsYXNzU3Vic2NyaXB0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgY29uc3QgaXNPcmlnaW5hbFN1YnNjcmlwdGlvbk1hdGNoZWQgPSB0aGlzLl9tYXRjaGVzU3Vic2NyaXB0aW9uKFxuICAgICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICAgICAgICBzdWJzY3JpcHRpb25cbiAgICAgICk7XG4gICAgICBjb25zdCBpc0N1cnJlbnRTdWJzY3JpcHRpb25NYXRjaGVkID0gdGhpcy5fbWF0Y2hlc1N1YnNjcmlwdGlvbihcbiAgICAgICAgY3VycmVudFBhcnNlT2JqZWN0LFxuICAgICAgICBzdWJzY3JpcHRpb25cbiAgICAgICk7XG4gICAgICBmb3IgKGNvbnN0IFtjbGllbnRJZCwgcmVxdWVzdElkc10gb2YgXy5lbnRyaWVzKFxuICAgICAgICBzdWJzY3JpcHRpb24uY2xpZW50UmVxdWVzdElkc1xuICAgICAgKSkge1xuICAgICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudHMuZ2V0KGNsaWVudElkKTtcbiAgICAgICAgaWYgKHR5cGVvZiBjbGllbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCByZXF1ZXN0SWQgb2YgcmVxdWVzdElkcykge1xuICAgICAgICAgIC8vIFNldCBvcmlnbmFsIFBhcnNlT2JqZWN0IEFDTCBjaGVja2luZyBwcm9taXNlLCBpZiB0aGUgb2JqZWN0IGRvZXMgbm90IG1hdGNoXG4gICAgICAgICAgLy8gc3Vic2NyaXB0aW9uLCB3ZSBkbyBub3QgbmVlZCB0byBjaGVjayBBQ0xcbiAgICAgICAgICBsZXQgb3JpZ2luYWxBQ0xDaGVja2luZ1Byb21pc2U7XG4gICAgICAgICAgaWYgKCFpc09yaWdpbmFsU3Vic2NyaXB0aW9uTWF0Y2hlZCkge1xuICAgICAgICAgICAgb3JpZ2luYWxBQ0xDaGVja2luZ1Byb21pc2UgPSBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxBQ0w7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICAgICAgICAgIG9yaWdpbmFsQUNMID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0LmdldEFDTCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3JpZ2luYWxBQ0xDaGVja2luZ1Byb21pc2UgPSB0aGlzLl9tYXRjaGVzQUNMKFxuICAgICAgICAgICAgICBvcmlnaW5hbEFDTCxcbiAgICAgICAgICAgICAgY2xpZW50LFxuICAgICAgICAgICAgICByZXF1ZXN0SWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFNldCBjdXJyZW50IFBhcnNlT2JqZWN0IEFDTCBjaGVja2luZyBwcm9taXNlLCBpZiB0aGUgb2JqZWN0IGRvZXMgbm90IG1hdGNoXG4gICAgICAgICAgLy8gc3Vic2NyaXB0aW9uLCB3ZSBkbyBub3QgbmVlZCB0byBjaGVjayBBQ0xcbiAgICAgICAgICBsZXQgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZTtcbiAgICAgICAgICBpZiAoIWlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRBQ0xDaGVja2luZ1Byb21pc2UgPSBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50QUNMID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QuZ2V0QUNMKCk7XG4gICAgICAgICAgICBjdXJyZW50QUNMQ2hlY2tpbmdQcm9taXNlID0gdGhpcy5fbWF0Y2hlc0FDTChcbiAgICAgICAgICAgICAgY3VycmVudEFDTCxcbiAgICAgICAgICAgICAgY2xpZW50LFxuICAgICAgICAgICAgICByZXF1ZXN0SWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IG9wID0gdGhpcy5fZ2V0Q0xQT3BlcmF0aW9uKHN1YnNjcmlwdGlvbi5xdWVyeSk7XG4gICAgICAgICAgdGhpcy5fbWF0Y2hlc0NMUChcbiAgICAgICAgICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgICAgICAgICAgIG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0LFxuICAgICAgICAgICAgY2xpZW50LFxuICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgb3BcbiAgICAgICAgICApXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgb3JpZ2luYWxBQ0xDaGVja2luZ1Byb21pc2UsXG4gICAgICAgICAgICAgICAgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSxcbiAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oXG4gICAgICAgICAgICAgIChbaXNPcmlnaW5hbE1hdGNoZWQsIGlzQ3VycmVudE1hdGNoZWRdKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICAgICAgICAgICAgICAnT3JpZ2luYWwgJWogfCBDdXJyZW50ICVqIHwgTWF0Y2g6ICVzLCAlcywgJXMsICVzIHwgUXVlcnk6ICVzJyxcbiAgICAgICAgICAgICAgICAgIG9yaWdpbmFsUGFyc2VPYmplY3QsXG4gICAgICAgICAgICAgICAgICBjdXJyZW50UGFyc2VPYmplY3QsXG4gICAgICAgICAgICAgICAgICBpc09yaWdpbmFsU3Vic2NyaXB0aW9uTWF0Y2hlZCxcbiAgICAgICAgICAgICAgICAgIGlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQsXG4gICAgICAgICAgICAgICAgICBpc09yaWdpbmFsTWF0Y2hlZCxcbiAgICAgICAgICAgICAgICAgIGlzQ3VycmVudE1hdGNoZWQsXG4gICAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24uaGFzaFxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWNpZGUgZXZlbnQgdHlwZVxuICAgICAgICAgICAgICAgIGxldCB0eXBlO1xuICAgICAgICAgICAgICAgIGlmIChpc09yaWdpbmFsTWF0Y2hlZCAmJiBpc0N1cnJlbnRNYXRjaGVkKSB7XG4gICAgICAgICAgICAgICAgICB0eXBlID0gJ1VwZGF0ZSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09yaWdpbmFsTWF0Y2hlZCAmJiAhaXNDdXJyZW50TWF0Y2hlZCkge1xuICAgICAgICAgICAgICAgICAgdHlwZSA9ICdMZWF2ZSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNPcmlnaW5hbE1hdGNoZWQgJiYgaXNDdXJyZW50TWF0Y2hlZCkge1xuICAgICAgICAgICAgICAgICAgaWYgKG9yaWdpbmFsUGFyc2VPYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICdFbnRlcic7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0eXBlID0gJ0NyZWF0ZSc7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBmdW5jdGlvbk5hbWUgPSAncHVzaCcgKyB0eXBlO1xuICAgICAgICAgICAgICAgIGNsaWVudFtmdW5jdGlvbk5hbWVdKFxuICAgICAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICAgICAgY3VycmVudFBhcnNlT2JqZWN0LFxuICAgICAgICAgICAgICAgICAgb3JpZ2luYWxQYXJzZU9iamVjdFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ01hdGNoaW5nIEFDTCBlcnJvciA6ICcsIGVycm9yKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9vbkNvbm5lY3QocGFyc2VXZWJzb2NrZXQ6IGFueSk6IHZvaWQge1xuICAgIHBhcnNlV2Vic29ja2V0Lm9uKCdtZXNzYWdlJywgcmVxdWVzdCA9PiB7XG4gICAgICBpZiAodHlwZW9mIHJlcXVlc3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVxdWVzdCA9IEpTT04ucGFyc2UocmVxdWVzdCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoJ3VuYWJsZSB0byBwYXJzZSByZXF1ZXN0JywgcmVxdWVzdCwgZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsb2dnZXIudmVyYm9zZSgnUmVxdWVzdDogJWonLCByZXF1ZXN0KTtcblxuICAgICAgLy8gQ2hlY2sgd2hldGhlciB0aGlzIHJlcXVlc3QgaXMgYSB2YWxpZCByZXF1ZXN0LCByZXR1cm4gZXJyb3IgZGlyZWN0bHkgaWYgbm90XG4gICAgICBpZiAoXG4gICAgICAgICF0djQudmFsaWRhdGUocmVxdWVzdCwgUmVxdWVzdFNjaGVtYVsnZ2VuZXJhbCddKSB8fFxuICAgICAgICAhdHY0LnZhbGlkYXRlKHJlcXVlc3QsIFJlcXVlc3RTY2hlbWFbcmVxdWVzdC5vcF0pXG4gICAgICApIHtcbiAgICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMSwgdHY0LmVycm9yLm1lc3NhZ2UpO1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ0Nvbm5lY3QgbWVzc2FnZSBlcnJvciAlcycsIHR2NC5lcnJvci5tZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzd2l0Y2ggKHJlcXVlc3Qub3ApIHtcbiAgICAgICAgY2FzZSAnY29ubmVjdCc6XG4gICAgICAgICAgdGhpcy5faGFuZGxlQ29ubmVjdChwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3N1YnNjcmliZSc6XG4gICAgICAgICAgdGhpcy5faGFuZGxlU3Vic2NyaWJlKHBhcnNlV2Vic29ja2V0LCByZXF1ZXN0KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndXBkYXRlJzpcbiAgICAgICAgICB0aGlzLl9oYW5kbGVVcGRhdGVTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd1bnN1YnNjcmliZSc6XG4gICAgICAgICAgdGhpcy5faGFuZGxlVW5zdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIDMsICdHZXQgdW5rbm93biBvcGVyYXRpb24nKTtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0dldCB1bmtub3duIG9wZXJhdGlvbicsIHJlcXVlc3Qub3ApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcGFyc2VXZWJzb2NrZXQub24oJ2Rpc2Nvbm5lY3QnLCAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgQ2xpZW50IGRpc2Nvbm5lY3Q6ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9YCk7XG4gICAgICBjb25zdCBjbGllbnRJZCA9IHBhcnNlV2Vic29ja2V0LmNsaWVudElkO1xuICAgICAgaWYgKCF0aGlzLmNsaWVudHMuaGFzKGNsaWVudElkKSkge1xuICAgICAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgICAgICBldmVudDogJ3dzX2Rpc2Nvbm5lY3RfZXJyb3InLFxuICAgICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgICAgIGVycm9yOiBgVW5hYmxlIHRvIGZpbmQgY2xpZW50ICR7Y2xpZW50SWR9YCxcbiAgICAgICAgfSk7XG4gICAgICAgIGxvZ2dlci5lcnJvcihgQ2FuIG5vdCBmaW5kIGNsaWVudCAke2NsaWVudElkfSBvbiBkaXNjb25uZWN0YCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gRGVsZXRlIGNsaWVudFxuICAgICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnRzLmdldChjbGllbnRJZCk7XG4gICAgICB0aGlzLmNsaWVudHMuZGVsZXRlKGNsaWVudElkKTtcblxuICAgICAgLy8gRGVsZXRlIGNsaWVudCBmcm9tIHN1YnNjcmlwdGlvbnNcbiAgICAgIGZvciAoY29uc3QgW3JlcXVlc3RJZCwgc3Vic2NyaXB0aW9uSW5mb10gb2YgXy5lbnRyaWVzKFxuICAgICAgICBjbGllbnQuc3Vic2NyaXB0aW9uSW5mb3NcbiAgICAgICkpIHtcbiAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gc3Vic2NyaXB0aW9uSW5mby5zdWJzY3JpcHRpb247XG4gICAgICAgIHN1YnNjcmlwdGlvbi5kZWxldGVDbGllbnRTdWJzY3JpcHRpb24oY2xpZW50SWQsIHJlcXVlc3RJZCk7XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgbm8gY2xpZW50IHdoaWNoIGlzIHN1YnNjcmliaW5nIHRoaXMgc3Vic2NyaXB0aW9uLCByZW1vdmUgaXQgZnJvbSBzdWJzY3JpcHRpb25zXG4gICAgICAgIGNvbnN0IGNsYXNzU3Vic2NyaXB0aW9ucyA9IHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoXG4gICAgICAgICAgc3Vic2NyaXB0aW9uLmNsYXNzTmFtZVxuICAgICAgICApO1xuICAgICAgICBpZiAoIXN1YnNjcmlwdGlvbi5oYXNTdWJzY3JpYmluZ0NsaWVudCgpKSB7XG4gICAgICAgICAgY2xhc3NTdWJzY3JpcHRpb25zLmRlbGV0ZShzdWJzY3JpcHRpb24uaGFzaCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgbm8gc3Vic2NyaXB0aW9ucyB1bmRlciB0aGlzIGNsYXNzLCByZW1vdmUgaXQgZnJvbSBzdWJzY3JpcHRpb25zXG4gICAgICAgIGlmIChjbGFzc1N1YnNjcmlwdGlvbnMuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5kZWxldGUoc3Vic2NyaXB0aW9uLmNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbG9nZ2VyLnZlcmJvc2UoJ0N1cnJlbnQgY2xpZW50cyAlZCcsIHRoaXMuY2xpZW50cy5zaXplKTtcbiAgICAgIGxvZ2dlci52ZXJib3NlKCdDdXJyZW50IHN1YnNjcmlwdGlvbnMgJWQnLCB0aGlzLnN1YnNjcmlwdGlvbnMuc2l6ZSk7XG4gICAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgICAgZXZlbnQ6ICd3c19kaXNjb25uZWN0JyxcbiAgICAgICAgY2xpZW50czogdGhpcy5jbGllbnRzLnNpemUsXG4gICAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgICB1c2VNYXN0ZXJLZXk6IGNsaWVudC5oYXNNYXN0ZXJLZXksXG4gICAgICAgIGluc3RhbGxhdGlvbklkOiBjbGllbnQuaW5zdGFsbGF0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMoe1xuICAgICAgZXZlbnQ6ICd3c19jb25uZWN0JyxcbiAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgc3Vic2NyaXB0aW9uczogdGhpcy5zdWJzY3JpcHRpb25zLnNpemUsXG4gICAgfSk7XG4gIH1cblxuICBfbWF0Y2hlc1N1YnNjcmlwdGlvbihwYXJzZU9iamVjdDogYW55LCBzdWJzY3JpcHRpb246IGFueSk6IGJvb2xlYW4ge1xuICAgIC8vIE9iamVjdCBpcyB1bmRlZmluZWQgb3IgbnVsbCwgbm90IG1hdGNoXG4gICAgaWYgKCFwYXJzZU9iamVjdCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gbWF0Y2hlc1F1ZXJ5KHBhcnNlT2JqZWN0LCBzdWJzY3JpcHRpb24ucXVlcnkpO1xuICB9XG5cbiAgZ2V0QXV0aEZvclNlc3Npb25Ub2tlbihcbiAgICBzZXNzaW9uVG9rZW46ID9zdHJpbmdcbiAgKTogUHJvbWlzZTx7IGF1dGg6ID9BdXRoLCB1c2VySWQ6ID9zdHJpbmcgfT4ge1xuICAgIGlmICghc2Vzc2lvblRva2VuKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgICB9XG4gICAgY29uc3QgZnJvbUNhY2hlID0gdGhpcy5hdXRoQ2FjaGUuZ2V0KHNlc3Npb25Ub2tlbik7XG4gICAgaWYgKGZyb21DYWNoZSkge1xuICAgICAgcmV0dXJuIGZyb21DYWNoZTtcbiAgICB9XG4gICAgY29uc3QgYXV0aFByb21pc2UgPSBnZXRBdXRoRm9yU2Vzc2lvblRva2VuKHtcbiAgICAgIGNhY2hlQ29udHJvbGxlcjogdGhpcy5jYWNoZUNvbnRyb2xsZXIsXG4gICAgICBzZXNzaW9uVG9rZW46IHNlc3Npb25Ub2tlbixcbiAgICB9KVxuICAgICAgLnRoZW4oYXV0aCA9PiB7XG4gICAgICAgIHJldHVybiB7IGF1dGgsIHVzZXJJZDogYXV0aCAmJiBhdXRoLnVzZXIgJiYgYXV0aC51c2VyLmlkIH07XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgLy8gVGhlcmUgd2FzIGFuIGVycm9yIHdpdGggdGhlIHNlc3Npb24gdG9rZW5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgICAgIGlmIChlcnJvciAmJiBlcnJvci5jb2RlID09PSBQYXJzZS5FcnJvci5JTlZBTElEX1NFU1NJT05fVE9LRU4pIHtcbiAgICAgICAgICAvLyBTdG9yZSBhIHJlc29sdmVkIHByb21pc2Ugd2l0aCB0aGUgZXJyb3IgZm9yIDEwIG1pbnV0ZXNcbiAgICAgICAgICByZXN1bHQuZXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICB0aGlzLmF1dGhDYWNoZS5zZXQoXG4gICAgICAgICAgICBzZXNzaW9uVG9rZW4sXG4gICAgICAgICAgICBQcm9taXNlLnJlc29sdmUocmVzdWx0KSxcbiAgICAgICAgICAgIDYwICogMTAgKiAxMDAwXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmF1dGhDYWNoZS5kZWwoc2Vzc2lvblRva2VuKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgdGhpcy5hdXRoQ2FjaGUuc2V0KHNlc3Npb25Ub2tlbiwgYXV0aFByb21pc2UpO1xuICAgIHJldHVybiBhdXRoUHJvbWlzZTtcbiAgfVxuXG4gIGFzeW5jIF9tYXRjaGVzQ0xQKFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogP2FueSxcbiAgICBvYmplY3Q6IGFueSxcbiAgICBjbGllbnQ6IGFueSxcbiAgICByZXF1ZXN0SWQ6IG51bWJlcixcbiAgICBvcDogc3RyaW5nXG4gICk6IGFueSB7XG4gICAgLy8gdHJ5IHRvIG1hdGNoIG9uIHVzZXIgZmlyc3QsIGxlc3MgZXhwZW5zaXZlIHRoYW4gd2l0aCByb2xlc1xuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIGNvbnN0IGFjbEdyb3VwID0gWycqJ107XG4gICAgbGV0IHVzZXJJZDtcbiAgICBpZiAodHlwZW9mIHN1YnNjcmlwdGlvbkluZm8gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBjb25zdCB7IHVzZXJJZCB9ID0gYXdhaXQgdGhpcy5nZXRBdXRoRm9yU2Vzc2lvblRva2VuKFxuICAgICAgICBzdWJzY3JpcHRpb25JbmZvLnNlc3Npb25Ub2tlblxuICAgICAgKTtcbiAgICAgIGlmICh1c2VySWQpIHtcbiAgICAgICAgYWNsR3JvdXAucHVzaCh1c2VySWQpO1xuICAgICAgfVxuICAgIH1cbiAgICB0cnkge1xuICAgICAgYXdhaXQgU2NoZW1hQ29udHJvbGxlci52YWxpZGF0ZVBlcm1pc3Npb24oXG4gICAgICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgICAgICAgb2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgICAgYWNsR3JvdXAsXG4gICAgICAgIG9wXG4gICAgICApO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoYEZhaWxlZCBtYXRjaGluZyBDTFAgZm9yICR7b2JqZWN0LmlkfSAke3VzZXJJZH0gJHtlfWApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBUT0RPOiBoYW5kbGUgcm9sZXMgcGVybWlzc2lvbnNcbiAgICAvLyBPYmplY3Qua2V5cyhjbGFzc0xldmVsUGVybWlzc2lvbnMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgIC8vICAgY29uc3QgcGVybSA9IGNsYXNzTGV2ZWxQZXJtaXNzaW9uc1trZXldO1xuICAgIC8vICAgT2JqZWN0LmtleXMocGVybSkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgLy8gICAgIGlmIChrZXkuaW5kZXhPZigncm9sZScpKVxuICAgIC8vICAgfSk7XG4gICAgLy8gfSlcbiAgICAvLyAvLyBpdCdzIHJlamVjdGVkIGhlcmUsIGNoZWNrIHRoZSByb2xlc1xuICAgIC8vIHZhciByb2xlc1F1ZXJ5ID0gbmV3IFBhcnNlLlF1ZXJ5KFBhcnNlLlJvbGUpO1xuICAgIC8vIHJvbGVzUXVlcnkuZXF1YWxUbyhcInVzZXJzXCIsIHVzZXIpO1xuICAgIC8vIHJldHVybiByb2xlc1F1ZXJ5LmZpbmQoe3VzZU1hc3RlcktleTp0cnVlfSk7XG4gIH1cblxuICBfZ2V0Q0xQT3BlcmF0aW9uKHF1ZXJ5OiBhbnkpIHtcbiAgICByZXR1cm4gdHlwZW9mIHF1ZXJ5ID09PSAnb2JqZWN0JyAmJlxuICAgICAgT2JqZWN0LmtleXMocXVlcnkpLmxlbmd0aCA9PSAxICYmXG4gICAgICB0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT09ICdzdHJpbmcnXG4gICAgICA/ICdnZXQnXG4gICAgICA6ICdmaW5kJztcbiAgfVxuXG4gIGFzeW5jIF92ZXJpZnlBQ0woYWNsOiBhbnksIHRva2VuOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRva2VuKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgeyBhdXRoLCB1c2VySWQgfSA9IGF3YWl0IHRoaXMuZ2V0QXV0aEZvclNlc3Npb25Ub2tlbih0b2tlbik7XG5cbiAgICAvLyBHZXR0aW5nIHRoZSBzZXNzaW9uIHRva2VuIGZhaWxlZFxuICAgIC8vIFRoaXMgbWVhbnMgdGhhdCBubyBhZGRpdGlvbmFsIGF1dGggaXMgYXZhaWxhYmxlXG4gICAgLy8gQXQgdGhpcyBwb2ludCwganVzdCBiYWlsIG91dCBhcyBubyBhZGRpdGlvbmFsIHZpc2liaWxpdHkgY2FuIGJlIGluZmVycmVkLlxuICAgIGlmICghYXV0aCB8fCAhdXNlcklkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCA9IGFjbC5nZXRSZWFkQWNjZXNzKHVzZXJJZCk7XG4gICAgaWYgKGlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHVzZXIgaGFzIGFueSByb2xlcyB0aGF0IG1hdGNoIHRoZSBBQ0xcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gUmVzb2x2ZSBmYWxzZSByaWdodCBhd2F5IGlmIHRoZSBhY2wgZG9lc24ndCBoYXZlIGFueSByb2xlc1xuICAgICAgICBjb25zdCBhY2xfaGFzX3JvbGVzID0gT2JqZWN0LmtleXMoYWNsLnBlcm1pc3Npb25zQnlJZCkuc29tZShrZXkgPT5cbiAgICAgICAgICBrZXkuc3RhcnRzV2l0aCgncm9sZTonKVxuICAgICAgICApO1xuICAgICAgICBpZiAoIWFjbF9oYXNfcm9sZXMpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByb2xlTmFtZXMgPSBhd2FpdCBhdXRoLmdldFVzZXJSb2xlcygpO1xuICAgICAgICAvLyBGaW5hbGx5LCBzZWUgaWYgYW55IG9mIHRoZSB1c2VyJ3Mgcm9sZXMgYWxsb3cgdGhlbSByZWFkIGFjY2Vzc1xuICAgICAgICBmb3IgKGNvbnN0IHJvbGUgb2Ygcm9sZU5hbWVzKSB7XG4gICAgICAgICAgLy8gV2UgdXNlIGdldFJlYWRBY2Nlc3MgYXMgYHJvbGVgIGlzIGluIHRoZSBmb3JtIGByb2xlOnJvbGVOYW1lYFxuICAgICAgICAgIGlmIChhY2wuZ2V0UmVhZEFjY2Vzcyhyb2xlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIF9tYXRjaGVzQUNMKFxuICAgIGFjbDogYW55LFxuICAgIGNsaWVudDogYW55LFxuICAgIHJlcXVlc3RJZDogbnVtYmVyXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFJldHVybiB0cnVlIGRpcmVjdGx5IGlmIEFDTCBpc24ndCBwcmVzZW50LCBBQ0wgaXMgcHVibGljIHJlYWQsIG9yIGNsaWVudCBoYXMgbWFzdGVyIGtleVxuICAgIGlmICghYWNsIHx8IGFjbC5nZXRQdWJsaWNSZWFkQWNjZXNzKCkgfHwgY2xpZW50Lmhhc01hc3RlcktleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIC8vIENoZWNrIHN1YnNjcmlwdGlvbiBzZXNzaW9uVG9rZW4gbWF0Y2hlcyBBQ0wgZmlyc3RcbiAgICBjb25zdCBzdWJzY3JpcHRpb25JbmZvID0gY2xpZW50LmdldFN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdElkKTtcbiAgICBpZiAodHlwZW9mIHN1YnNjcmlwdGlvbkluZm8gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uVG9rZW4gPSBzdWJzY3JpcHRpb25JbmZvLnNlc3Npb25Ub2tlbjtcbiAgICBjb25zdCBjbGllbnRTZXNzaW9uVG9rZW4gPSBjbGllbnQuc2Vzc2lvblRva2VuO1xuXG4gICAgaWYgKGF3YWl0IHRoaXMuX3ZlcmlmeUFDTChhY2wsIHN1YnNjcmlwdGlvblRva2VuKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKGF3YWl0IHRoaXMuX3ZlcmlmeUFDTChhY2wsIGNsaWVudFNlc3Npb25Ub2tlbikpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIF9oYW5kbGVDb25uZWN0KHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSk6IGFueSB7XG4gICAgaWYgKCF0aGlzLl92YWxpZGF0ZUtleXMocmVxdWVzdCwgdGhpcy5rZXlQYWlycykpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIDQsICdLZXkgaW4gcmVxdWVzdCBpcyBub3QgdmFsaWQnKTtcbiAgICAgIGxvZ2dlci5lcnJvcignS2V5IGluIHJlcXVlc3QgaXMgbm90IHZhbGlkJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGhhc01hc3RlcktleSA9IHRoaXMuX2hhc01hc3RlcktleShyZXF1ZXN0LCB0aGlzLmtleVBhaXJzKTtcbiAgICBjb25zdCBjbGllbnRJZCA9IHV1aWQoKTtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgQ2xpZW50KFxuICAgICAgY2xpZW50SWQsXG4gICAgICBwYXJzZVdlYnNvY2tldCxcbiAgICAgIGhhc01hc3RlcktleSxcbiAgICAgIHJlcXVlc3Quc2Vzc2lvblRva2VuLFxuICAgICAgcmVxdWVzdC5pbnN0YWxsYXRpb25JZFxuICAgICk7XG4gICAgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQgPSBjbGllbnRJZDtcbiAgICB0aGlzLmNsaWVudHMuc2V0KHBhcnNlV2Vic29ja2V0LmNsaWVudElkLCBjbGllbnQpO1xuICAgIGxvZ2dlci5pbmZvKGBDcmVhdGUgbmV3IGNsaWVudDogJHtwYXJzZVdlYnNvY2tldC5jbGllbnRJZH1gKTtcbiAgICBjbGllbnQucHVzaENvbm5lY3QoKTtcbiAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgIGNsaWVudCxcbiAgICAgIGV2ZW50OiAnY29ubmVjdCcsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgc2Vzc2lvblRva2VuOiByZXF1ZXN0LnNlc3Npb25Ub2tlbixcbiAgICAgIHVzZU1hc3RlcktleTogY2xpZW50Lmhhc01hc3RlcktleSxcbiAgICAgIGluc3RhbGxhdGlvbklkOiByZXF1ZXN0Lmluc3RhbGxhdGlvbklkLFxuICAgIH0pO1xuICB9XG5cbiAgX2hhc01hc3RlcktleShyZXF1ZXN0OiBhbnksIHZhbGlkS2V5UGFpcnM6IGFueSk6IGJvb2xlYW4ge1xuICAgIGlmIChcbiAgICAgICF2YWxpZEtleVBhaXJzIHx8XG4gICAgICB2YWxpZEtleVBhaXJzLnNpemUgPT0gMCB8fFxuICAgICAgIXZhbGlkS2V5UGFpcnMuaGFzKCdtYXN0ZXJLZXknKVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICAhcmVxdWVzdCB8fFxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXF1ZXN0LCAnbWFzdGVyS2V5JylcbiAgICApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcXVlc3QubWFzdGVyS2V5ID09PSB2YWxpZEtleVBhaXJzLmdldCgnbWFzdGVyS2V5Jyk7XG4gIH1cblxuICBfdmFsaWRhdGVLZXlzKHJlcXVlc3Q6IGFueSwgdmFsaWRLZXlQYWlyczogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKCF2YWxpZEtleVBhaXJzIHx8IHZhbGlkS2V5UGFpcnMuc2l6ZSA9PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgbGV0IGlzVmFsaWQgPSBmYWxzZTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHNlY3JldF0gb2YgdmFsaWRLZXlQYWlycykge1xuICAgICAgaWYgKCFyZXF1ZXN0W2tleV0gfHwgcmVxdWVzdFtrZXldICE9PSBzZWNyZXQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpc1ZhbGlkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gaXNWYWxpZDtcbiAgfVxuXG4gIF9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQ6IGFueSwgcmVxdWVzdDogYW55KTogYW55IHtcbiAgICAvLyBJZiB3ZSBjYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIHJldHVybiBlcnJvciB0byBjbGllbnRcbiAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwYXJzZVdlYnNvY2tldCwgJ2NsaWVudElkJykpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IoXG4gICAgICAgIHBhcnNlV2Vic29ja2V0LFxuICAgICAgICAyLFxuICAgICAgICAnQ2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCBtYWtlIHN1cmUgeW91IGNvbm5lY3QgdG8gc2VydmVyIGJlZm9yZSBzdWJzY3JpYmluZydcbiAgICAgICk7XG4gICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICdDYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIG1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBzZXJ2ZXIgYmVmb3JlIHN1YnNjcmliaW5nJ1xuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnRzLmdldChwYXJzZVdlYnNvY2tldC5jbGllbnRJZCk7XG5cbiAgICAvLyBHZXQgc3Vic2NyaXB0aW9uIGZyb20gc3Vic2NyaXB0aW9ucywgY3JlYXRlIG9uZSBpZiBuZWNlc3NhcnlcbiAgICBjb25zdCBzdWJzY3JpcHRpb25IYXNoID0gcXVlcnlIYXNoKHJlcXVlc3QucXVlcnkpO1xuICAgIC8vIEFkZCBjbGFzc05hbWUgdG8gc3Vic2NyaXB0aW9ucyBpZiBuZWNlc3NhcnlcbiAgICBjb25zdCBjbGFzc05hbWUgPSByZXF1ZXN0LnF1ZXJ5LmNsYXNzTmFtZTtcbiAgICBpZiAoIXRoaXMuc3Vic2NyaXB0aW9ucy5oYXMoY2xhc3NOYW1lKSkge1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnNldChjbGFzc05hbWUsIG5ldyBNYXAoKSk7XG4gICAgfVxuICAgIGNvbnN0IGNsYXNzU3Vic2NyaXB0aW9ucyA9IHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoY2xhc3NOYW1lKTtcbiAgICBsZXQgc3Vic2NyaXB0aW9uO1xuICAgIGlmIChjbGFzc1N1YnNjcmlwdGlvbnMuaGFzKHN1YnNjcmlwdGlvbkhhc2gpKSB7XG4gICAgICBzdWJzY3JpcHRpb24gPSBjbGFzc1N1YnNjcmlwdGlvbnMuZ2V0KHN1YnNjcmlwdGlvbkhhc2gpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHJlcXVlc3QucXVlcnkud2hlcmUsXG4gICAgICAgIHN1YnNjcmlwdGlvbkhhc2hcbiAgICAgICk7XG4gICAgICBjbGFzc1N1YnNjcmlwdGlvbnMuc2V0KHN1YnNjcmlwdGlvbkhhc2gsIHN1YnNjcmlwdGlvbik7XG4gICAgfVxuXG4gICAgLy8gQWRkIHN1YnNjcmlwdGlvbkluZm8gdG8gY2xpZW50XG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uSW5mbyA9IHtcbiAgICAgIHN1YnNjcmlwdGlvbjogc3Vic2NyaXB0aW9uLFxuICAgIH07XG4gICAgLy8gQWRkIHNlbGVjdGVkIGZpZWxkcywgc2Vzc2lvblRva2VuIGFuZCBpbnN0YWxsYXRpb25JZCBmb3IgdGhpcyBzdWJzY3JpcHRpb24gaWYgbmVjZXNzYXJ5XG4gICAgaWYgKHJlcXVlc3QucXVlcnkuZmllbGRzKSB7XG4gICAgICBzdWJzY3JpcHRpb25JbmZvLmZpZWxkcyA9IHJlcXVlc3QucXVlcnkuZmllbGRzO1xuICAgIH1cbiAgICBpZiAocmVxdWVzdC5zZXNzaW9uVG9rZW4pIHtcbiAgICAgIHN1YnNjcmlwdGlvbkluZm8uc2Vzc2lvblRva2VuID0gcmVxdWVzdC5zZXNzaW9uVG9rZW47XG4gICAgfVxuICAgIGNsaWVudC5hZGRTdWJzY3JpcHRpb25JbmZvKHJlcXVlc3QucmVxdWVzdElkLCBzdWJzY3JpcHRpb25JbmZvKTtcblxuICAgIC8vIEFkZCBjbGllbnRJZCB0byBzdWJzY3JpcHRpb25cbiAgICBzdWJzY3JpcHRpb24uYWRkQ2xpZW50U3Vic2NyaXB0aW9uKFxuICAgICAgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsXG4gICAgICByZXF1ZXN0LnJlcXVlc3RJZFxuICAgICk7XG5cbiAgICBjbGllbnQucHVzaFN1YnNjcmliZShyZXF1ZXN0LnJlcXVlc3RJZCk7XG5cbiAgICBsb2dnZXIudmVyYm9zZShcbiAgICAgIGBDcmVhdGUgY2xpZW50ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9IG5ldyBzdWJzY3JpcHRpb246ICR7cmVxdWVzdC5yZXF1ZXN0SWR9YFxuICAgICk7XG4gICAgbG9nZ2VyLnZlcmJvc2UoJ0N1cnJlbnQgY2xpZW50IG51bWJlcjogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG4gICAgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyh7XG4gICAgICBjbGllbnQsXG4gICAgICBldmVudDogJ3N1YnNjcmliZScsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgc2Vzc2lvblRva2VuOiByZXF1ZXN0LnNlc3Npb25Ub2tlbixcbiAgICAgIHVzZU1hc3RlcktleTogY2xpZW50Lmhhc01hc3RlcktleSxcbiAgICAgIGluc3RhbGxhdGlvbklkOiBjbGllbnQuaW5zdGFsbGF0aW9uSWQsXG4gICAgfSk7XG4gIH1cblxuICBfaGFuZGxlVXBkYXRlU3Vic2NyaXB0aW9uKHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSk6IGFueSB7XG4gICAgdGhpcy5faGFuZGxlVW5zdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QsIGZhbHNlKTtcbiAgICB0aGlzLl9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICB9XG5cbiAgX2hhbmRsZVVuc3Vic2NyaWJlKFxuICAgIHBhcnNlV2Vic29ja2V0OiBhbnksXG4gICAgcmVxdWVzdDogYW55LFxuICAgIG5vdGlmeUNsaWVudDogYm9vbGVhbiA9IHRydWVcbiAgKTogYW55IHtcbiAgICAvLyBJZiB3ZSBjYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIHJldHVybiBlcnJvciB0byBjbGllbnRcbiAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwYXJzZVdlYnNvY2tldCwgJ2NsaWVudElkJykpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IoXG4gICAgICAgIHBhcnNlV2Vic29ja2V0LFxuICAgICAgICAyLFxuICAgICAgICAnQ2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCBtYWtlIHN1cmUgeW91IGNvbm5lY3QgdG8gc2VydmVyIGJlZm9yZSB1bnN1YnNjcmliaW5nJ1xuICAgICAgKTtcbiAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0NhbiBub3QgZmluZCB0aGlzIGNsaWVudCwgbWFrZSBzdXJlIHlvdSBjb25uZWN0IHRvIHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZydcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHJlcXVlc3RJZCA9IHJlcXVlc3QucmVxdWVzdElkO1xuICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQpO1xuICAgIGlmICh0eXBlb2YgY2xpZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgQ2xpZW50LnB1c2hFcnJvcihcbiAgICAgICAgcGFyc2VXZWJzb2NrZXQsXG4gICAgICAgIDIsXG4gICAgICAgICdDYW5ub3QgZmluZCBjbGllbnQgd2l0aCBjbGllbnRJZCAnICtcbiAgICAgICAgICBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCArXG4gICAgICAgICAgJy4gTWFrZSBzdXJlIHlvdSBjb25uZWN0IHRvIGxpdmUgcXVlcnkgc2VydmVyIGJlZm9yZSB1bnN1YnNjcmliaW5nLidcbiAgICAgICk7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0NhbiBub3QgZmluZCB0aGlzIGNsaWVudCAnICsgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIGlmICh0eXBlb2Ygc3Vic2NyaXB0aW9uSW5mbyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IoXG4gICAgICAgIHBhcnNlV2Vic29ja2V0LFxuICAgICAgICAyLFxuICAgICAgICAnQ2Fubm90IGZpbmQgc3Vic2NyaXB0aW9uIHdpdGggY2xpZW50SWQgJyArXG4gICAgICAgICAgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQgK1xuICAgICAgICAgICcgc3Vic2NyaXB0aW9uSWQgJyArXG4gICAgICAgICAgcmVxdWVzdElkICtcbiAgICAgICAgICAnLiBNYWtlIHN1cmUgeW91IHN1YnNjcmliZSB0byBsaXZlIHF1ZXJ5IHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZy4nXG4gICAgICApO1xuICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAnQ2FuIG5vdCBmaW5kIHN1YnNjcmlwdGlvbiB3aXRoIGNsaWVudElkICcgK1xuICAgICAgICAgIHBhcnNlV2Vic29ja2V0LmNsaWVudElkICtcbiAgICAgICAgICAnIHN1YnNjcmlwdGlvbklkICcgK1xuICAgICAgICAgIHJlcXVlc3RJZFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBSZW1vdmUgc3Vic2NyaXB0aW9uIGZyb20gY2xpZW50XG4gICAgY2xpZW50LmRlbGV0ZVN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdElkKTtcbiAgICAvLyBSZW1vdmUgY2xpZW50IGZyb20gc3Vic2NyaXB0aW9uXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gc3Vic2NyaXB0aW9uSW5mby5zdWJzY3JpcHRpb247XG4gICAgY29uc3QgY2xhc3NOYW1lID0gc3Vic2NyaXB0aW9uLmNsYXNzTmFtZTtcbiAgICBzdWJzY3JpcHRpb24uZGVsZXRlQ2xpZW50U3Vic2NyaXB0aW9uKHBhcnNlV2Vic29ja2V0LmNsaWVudElkLCByZXF1ZXN0SWQpO1xuICAgIC8vIElmIHRoZXJlIGlzIG5vIGNsaWVudCB3aGljaCBpcyBzdWJzY3JpYmluZyB0aGlzIHN1YnNjcmlwdGlvbiwgcmVtb3ZlIGl0IGZyb20gc3Vic2NyaXB0aW9uc1xuICAgIGNvbnN0IGNsYXNzU3Vic2NyaXB0aW9ucyA9IHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoY2xhc3NOYW1lKTtcbiAgICBpZiAoIXN1YnNjcmlwdGlvbi5oYXNTdWJzY3JpYmluZ0NsaWVudCgpKSB7XG4gICAgICBjbGFzc1N1YnNjcmlwdGlvbnMuZGVsZXRlKHN1YnNjcmlwdGlvbi5oYXNoKTtcbiAgICB9XG4gICAgLy8gSWYgdGhlcmUgaXMgbm8gc3Vic2NyaXB0aW9ucyB1bmRlciB0aGlzIGNsYXNzLCByZW1vdmUgaXQgZnJvbSBzdWJzY3JpcHRpb25zXG4gICAgaWYgKGNsYXNzU3Vic2NyaXB0aW9ucy5zaXplID09PSAwKSB7XG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZGVsZXRlKGNsYXNzTmFtZSk7XG4gICAgfVxuICAgIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMoe1xuICAgICAgY2xpZW50LFxuICAgICAgZXZlbnQ6ICd1bnN1YnNjcmliZScsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgc2Vzc2lvblRva2VuOiBzdWJzY3JpcHRpb25JbmZvLnNlc3Npb25Ub2tlbixcbiAgICAgIHVzZU1hc3RlcktleTogY2xpZW50Lmhhc01hc3RlcktleSxcbiAgICAgIGluc3RhbGxhdGlvbklkOiBjbGllbnQuaW5zdGFsbGF0aW9uSWQsXG4gICAgfSk7XG5cbiAgICBpZiAoIW5vdGlmeUNsaWVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNsaWVudC5wdXNoVW5zdWJzY3JpYmUocmVxdWVzdC5yZXF1ZXN0SWQpO1xuXG4gICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgRGVsZXRlIGNsaWVudDogJHtwYXJzZVdlYnNvY2tldC5jbGllbnRJZH0gfCBzdWJzY3JpcHRpb246ICR7cmVxdWVzdC5yZXF1ZXN0SWR9YFxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IHsgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/LiveQuery/ParsePubSub.js b/lib/LiveQuery/ParsePubSub.js new file mode 100644 index 0000000000..a8493b7c4b --- /dev/null +++ b/lib/LiveQuery/ParsePubSub.js @@ -0,0 +1,49 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParsePubSub = void 0; + +var _AdapterLoader = require("../Adapters/AdapterLoader"); + +var _EventEmitterPubSub = require("../Adapters/PubSub/EventEmitterPubSub"); + +var _RedisPubSub = require("../Adapters/PubSub/RedisPubSub"); + +const ParsePubSub = {}; +exports.ParsePubSub = ParsePubSub; + +function useRedis(config) { + const redisURL = config.redisURL; + return typeof redisURL !== 'undefined' && redisURL !== ''; +} + +ParsePubSub.createPublisher = function (config) { + if (useRedis(config)) { + return _RedisPubSub.RedisPubSub.createPublisher(config); + } else { + const adapter = (0, _AdapterLoader.loadAdapter)(config.pubSubAdapter, _EventEmitterPubSub.EventEmitterPubSub, config); + + if (typeof adapter.createPublisher !== 'function') { + throw 'pubSubAdapter should have createPublisher()'; + } + + return adapter.createPublisher(config); + } +}; + +ParsePubSub.createSubscriber = function (config) { + if (useRedis(config)) { + return _RedisPubSub.RedisPubSub.createSubscriber(config); + } else { + const adapter = (0, _AdapterLoader.loadAdapter)(config.pubSubAdapter, _EventEmitterPubSub.EventEmitterPubSub, config); + + if (typeof adapter.createSubscriber !== 'function') { + throw 'pubSubAdapter should have createSubscriber()'; + } + + return adapter.createSubscriber(config); + } +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VQdWJTdWIuanMiXSwibmFtZXMiOlsiUGFyc2VQdWJTdWIiLCJ1c2VSZWRpcyIsImNvbmZpZyIsInJlZGlzVVJMIiwiY3JlYXRlUHVibGlzaGVyIiwiUmVkaXNQdWJTdWIiLCJhZGFwdGVyIiwicHViU3ViQWRhcHRlciIsIkV2ZW50RW1pdHRlclB1YlN1YiIsImNyZWF0ZVN1YnNjcmliZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFFQTs7QUFFQSxNQUFNQSxXQUFXLEdBQUcsRUFBcEI7OztBQUVBLFNBQVNDLFFBQVQsQ0FBa0JDLE1BQWxCLEVBQXdDO0FBQ3RDLFFBQU1DLFFBQVEsR0FBR0QsTUFBTSxDQUFDQyxRQUF4QjtBQUNBLFNBQU8sT0FBT0EsUUFBUCxLQUFvQixXQUFwQixJQUFtQ0EsUUFBUSxLQUFLLEVBQXZEO0FBQ0Q7O0FBRURILFdBQVcsQ0FBQ0ksZUFBWixHQUE4QixVQUFTRixNQUFULEVBQTJCO0FBQ3ZELE1BQUlELFFBQVEsQ0FBQ0MsTUFBRCxDQUFaLEVBQXNCO0FBQ3BCLFdBQU9HLHlCQUFZRCxlQUFaLENBQTRCRixNQUE1QixDQUFQO0FBQ0QsR0FGRCxNQUVPO0FBQ0wsVUFBTUksT0FBTyxHQUFHLGdDQUNkSixNQUFNLENBQUNLLGFBRE8sRUFFZEMsc0NBRmMsRUFHZE4sTUFIYyxDQUFoQjs7QUFLQSxRQUFJLE9BQU9JLE9BQU8sQ0FBQ0YsZUFBZixLQUFtQyxVQUF2QyxFQUFtRDtBQUNqRCxZQUFNLDZDQUFOO0FBQ0Q7O0FBQ0QsV0FBT0UsT0FBTyxDQUFDRixlQUFSLENBQXdCRixNQUF4QixDQUFQO0FBQ0Q7QUFDRixDQWREOztBQWdCQUYsV0FBVyxDQUFDUyxnQkFBWixHQUErQixVQUFTUCxNQUFULEVBQTRCO0FBQ3pELE1BQUlELFFBQVEsQ0FBQ0MsTUFBRCxDQUFaLEVBQXNCO0FBQ3BCLFdBQU9HLHlCQUFZSSxnQkFBWixDQUE2QlAsTUFBN0IsQ0FBUDtBQUNELEdBRkQsTUFFTztBQUNMLFVBQU1JLE9BQU8sR0FBRyxnQ0FDZEosTUFBTSxDQUFDSyxhQURPLEVBRWRDLHNDQUZjLEVBR2ROLE1BSGMsQ0FBaEI7O0FBS0EsUUFBSSxPQUFPSSxPQUFPLENBQUNHLGdCQUFmLEtBQW9DLFVBQXhDLEVBQW9EO0FBQ2xELFlBQU0sOENBQU47QUFDRDs7QUFDRCxXQUFPSCxPQUFPLENBQUNHLGdCQUFSLENBQXlCUCxNQUF6QixDQUFQO0FBQ0Q7QUFDRixDQWREIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbG9hZEFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9BZGFwdGVyTG9hZGVyJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlclB1YlN1YiB9IGZyb20gJy4uL0FkYXB0ZXJzL1B1YlN1Yi9FdmVudEVtaXR0ZXJQdWJTdWInO1xuXG5pbXBvcnQgeyBSZWRpc1B1YlN1YiB9IGZyb20gJy4uL0FkYXB0ZXJzL1B1YlN1Yi9SZWRpc1B1YlN1Yic7XG5cbmNvbnN0IFBhcnNlUHViU3ViID0ge307XG5cbmZ1bmN0aW9uIHVzZVJlZGlzKGNvbmZpZzogYW55KTogYm9vbGVhbiB7XG4gIGNvbnN0IHJlZGlzVVJMID0gY29uZmlnLnJlZGlzVVJMO1xuICByZXR1cm4gdHlwZW9mIHJlZGlzVVJMICE9PSAndW5kZWZpbmVkJyAmJiByZWRpc1VSTCAhPT0gJyc7XG59XG5cblBhcnNlUHViU3ViLmNyZWF0ZVB1Ymxpc2hlciA9IGZ1bmN0aW9uKGNvbmZpZzogYW55KTogYW55IHtcbiAgaWYgKHVzZVJlZGlzKGNvbmZpZykpIHtcbiAgICByZXR1cm4gUmVkaXNQdWJTdWIuY3JlYXRlUHVibGlzaGVyKGNvbmZpZyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYWRhcHRlciA9IGxvYWRBZGFwdGVyKFxuICAgICAgY29uZmlnLnB1YlN1YkFkYXB0ZXIsXG4gICAgICBFdmVudEVtaXR0ZXJQdWJTdWIsXG4gICAgICBjb25maWdcbiAgICApO1xuICAgIGlmICh0eXBlb2YgYWRhcHRlci5jcmVhdGVQdWJsaXNoZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93ICdwdWJTdWJBZGFwdGVyIHNob3VsZCBoYXZlIGNyZWF0ZVB1Ymxpc2hlcigpJztcbiAgICB9XG4gICAgcmV0dXJuIGFkYXB0ZXIuY3JlYXRlUHVibGlzaGVyKGNvbmZpZyk7XG4gIH1cbn07XG5cblBhcnNlUHViU3ViLmNyZWF0ZVN1YnNjcmliZXIgPSBmdW5jdGlvbihjb25maWc6IGFueSk6IHZvaWQge1xuICBpZiAodXNlUmVkaXMoY29uZmlnKSkge1xuICAgIHJldHVybiBSZWRpc1B1YlN1Yi5jcmVhdGVTdWJzY3JpYmVyKGNvbmZpZyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYWRhcHRlciA9IGxvYWRBZGFwdGVyKFxuICAgICAgY29uZmlnLnB1YlN1YkFkYXB0ZXIsXG4gICAgICBFdmVudEVtaXR0ZXJQdWJTdWIsXG4gICAgICBjb25maWdcbiAgICApO1xuICAgIGlmICh0eXBlb2YgYWRhcHRlci5jcmVhdGVTdWJzY3JpYmVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyAncHViU3ViQWRhcHRlciBzaG91bGQgaGF2ZSBjcmVhdGVTdWJzY3JpYmVyKCknO1xuICAgIH1cbiAgICByZXR1cm4gYWRhcHRlci5jcmVhdGVTdWJzY3JpYmVyKGNvbmZpZyk7XG4gIH1cbn07XG5cbmV4cG9ydCB7IFBhcnNlUHViU3ViIH07XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/ParseWebSocketServer.js b/lib/LiveQuery/ParseWebSocketServer.js new file mode 100644 index 0000000000..5e928998c7 --- /dev/null +++ b/lib/LiveQuery/ParseWebSocketServer.js @@ -0,0 +1,75 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseWebSocket = exports.ParseWebSocketServer = void 0; + +var _AdapterLoader = require("../Adapters/AdapterLoader"); + +var _WSAdapter = require("../Adapters/WebSocketServer/WSAdapter"); + +var _logger = _interopRequireDefault(require("../logger")); + +var _events = _interopRequireDefault(require("events")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class ParseWebSocketServer { + constructor(server, onConnect, config) { + config.server = server; + const wss = (0, _AdapterLoader.loadAdapter)(config.wssAdapter, _WSAdapter.WSAdapter, config); + + wss.onListen = () => { + _logger.default.info('Parse LiveQuery Server starts running'); + }; + + wss.onConnection = ws => { + onConnect(new ParseWebSocket(ws)); // Send ping to client periodically + + const pingIntervalId = setInterval(() => { + if (ws.readyState == ws.OPEN) { + ws.ping(); + } else { + clearInterval(pingIntervalId); + } + }, config.websocketTimeout || 10 * 1000); + }; + + wss.onError = error => { + _logger.default.error(error); + }; + + wss.start(); + this.server = wss; + } + + close() { + if (this.server && this.server.close) { + this.server.close(); + } + } + +} + +exports.ParseWebSocketServer = ParseWebSocketServer; + +class ParseWebSocket extends _events.default.EventEmitter { + constructor(ws) { + super(); + + ws.onmessage = request => this.emit('message', request && request.data ? request.data : request); + + ws.onclose = () => this.emit('disconnect'); + + this.ws = ws; + } + + send(message) { + this.ws.send(message); + } + +} + +exports.ParseWebSocket = ParseWebSocket; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VXZWJTb2NrZXRTZXJ2ZXIuanMiXSwibmFtZXMiOlsiUGFyc2VXZWJTb2NrZXRTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsInNlcnZlciIsIm9uQ29ubmVjdCIsImNvbmZpZyIsIndzcyIsIndzc0FkYXB0ZXIiLCJXU0FkYXB0ZXIiLCJvbkxpc3RlbiIsImxvZ2dlciIsImluZm8iLCJvbkNvbm5lY3Rpb24iLCJ3cyIsIlBhcnNlV2ViU29ja2V0IiwicGluZ0ludGVydmFsSWQiLCJzZXRJbnRlcnZhbCIsInJlYWR5U3RhdGUiLCJPUEVOIiwicGluZyIsImNsZWFySW50ZXJ2YWwiLCJ3ZWJzb2NrZXRUaW1lb3V0Iiwib25FcnJvciIsImVycm9yIiwic3RhcnQiLCJjbG9zZSIsImV2ZW50cyIsIkV2ZW50RW1pdHRlciIsIm9ubWVzc2FnZSIsInJlcXVlc3QiLCJlbWl0IiwiZGF0YSIsIm9uY2xvc2UiLCJzZW5kIiwibWVzc2FnZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsb0JBQU4sQ0FBMkI7QUFHaENDLEVBQUFBLFdBQVcsQ0FBQ0MsTUFBRCxFQUFjQyxTQUFkLEVBQW1DQyxNQUFuQyxFQUEyQztBQUNwREEsSUFBQUEsTUFBTSxDQUFDRixNQUFQLEdBQWdCQSxNQUFoQjtBQUNBLFVBQU1HLEdBQUcsR0FBRyxnQ0FBWUQsTUFBTSxDQUFDRSxVQUFuQixFQUErQkMsb0JBQS9CLEVBQTBDSCxNQUExQyxDQUFaOztBQUNBQyxJQUFBQSxHQUFHLENBQUNHLFFBQUosR0FBZSxNQUFNO0FBQ25CQyxzQkFBT0MsSUFBUCxDQUFZLHVDQUFaO0FBQ0QsS0FGRDs7QUFHQUwsSUFBQUEsR0FBRyxDQUFDTSxZQUFKLEdBQW1CQyxFQUFFLElBQUk7QUFDdkJULE1BQUFBLFNBQVMsQ0FBQyxJQUFJVSxjQUFKLENBQW1CRCxFQUFuQixDQUFELENBQVQsQ0FEdUIsQ0FFdkI7O0FBQ0EsWUFBTUUsY0FBYyxHQUFHQyxXQUFXLENBQUMsTUFBTTtBQUN2QyxZQUFJSCxFQUFFLENBQUNJLFVBQUgsSUFBaUJKLEVBQUUsQ0FBQ0ssSUFBeEIsRUFBOEI7QUFDNUJMLFVBQUFBLEVBQUUsQ0FBQ00sSUFBSDtBQUNELFNBRkQsTUFFTztBQUNMQyxVQUFBQSxhQUFhLENBQUNMLGNBQUQsQ0FBYjtBQUNEO0FBQ0YsT0FOaUMsRUFNL0JWLE1BQU0sQ0FBQ2dCLGdCQUFQLElBQTJCLEtBQUssSUFORCxDQUFsQztBQU9ELEtBVkQ7O0FBV0FmLElBQUFBLEdBQUcsQ0FBQ2dCLE9BQUosR0FBY0MsS0FBSyxJQUFJO0FBQ3JCYixzQkFBT2EsS0FBUCxDQUFhQSxLQUFiO0FBQ0QsS0FGRDs7QUFHQWpCLElBQUFBLEdBQUcsQ0FBQ2tCLEtBQUo7QUFDQSxTQUFLckIsTUFBTCxHQUFjRyxHQUFkO0FBQ0Q7O0FBRURtQixFQUFBQSxLQUFLLEdBQUc7QUFDTixRQUFJLEtBQUt0QixNQUFMLElBQWUsS0FBS0EsTUFBTCxDQUFZc0IsS0FBL0IsRUFBc0M7QUFDcEMsV0FBS3RCLE1BQUwsQ0FBWXNCLEtBQVo7QUFDRDtBQUNGOztBQS9CK0I7Ozs7QUFrQzNCLE1BQU1YLGNBQU4sU0FBNkJZLGdCQUFPQyxZQUFwQyxDQUFpRDtBQUd0RHpCLEVBQUFBLFdBQVcsQ0FBQ1csRUFBRCxFQUFVO0FBQ25COztBQUNBQSxJQUFBQSxFQUFFLENBQUNlLFNBQUgsR0FBZUMsT0FBTyxJQUNwQixLQUFLQyxJQUFMLENBQVUsU0FBVixFQUFxQkQsT0FBTyxJQUFJQSxPQUFPLENBQUNFLElBQW5CLEdBQTBCRixPQUFPLENBQUNFLElBQWxDLEdBQXlDRixPQUE5RCxDQURGOztBQUVBaEIsSUFBQUEsRUFBRSxDQUFDbUIsT0FBSCxHQUFhLE1BQU0sS0FBS0YsSUFBTCxDQUFVLFlBQVYsQ0FBbkI7O0FBQ0EsU0FBS2pCLEVBQUwsR0FBVUEsRUFBVjtBQUNEOztBQUVEb0IsRUFBQUEsSUFBSSxDQUFDQyxPQUFELEVBQXFCO0FBQ3ZCLFNBQUtyQixFQUFMLENBQVFvQixJQUFSLENBQWFDLE9BQWI7QUFDRDs7QUFicUQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBsb2FkQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0FkYXB0ZXJMb2FkZXInO1xuaW1wb3J0IHsgV1NBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvV2ViU29ja2V0U2VydmVyL1dTQWRhcHRlcic7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgZXZlbnRzIGZyb20gJ2V2ZW50cyc7XG5cbmV4cG9ydCBjbGFzcyBQYXJzZVdlYlNvY2tldFNlcnZlciB7XG4gIHNlcnZlcjogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcjogYW55LCBvbkNvbm5lY3Q6IEZ1bmN0aW9uLCBjb25maWcpIHtcbiAgICBjb25maWcuc2VydmVyID0gc2VydmVyO1xuICAgIGNvbnN0IHdzcyA9IGxvYWRBZGFwdGVyKGNvbmZpZy53c3NBZGFwdGVyLCBXU0FkYXB0ZXIsIGNvbmZpZyk7XG4gICAgd3NzLm9uTGlzdGVuID0gKCkgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oJ1BhcnNlIExpdmVRdWVyeSBTZXJ2ZXIgc3RhcnRzIHJ1bm5pbmcnKTtcbiAgICB9O1xuICAgIHdzcy5vbkNvbm5lY3Rpb24gPSB3cyA9PiB7XG4gICAgICBvbkNvbm5lY3QobmV3IFBhcnNlV2ViU29ja2V0KHdzKSk7XG4gICAgICAvLyBTZW5kIHBpbmcgdG8gY2xpZW50IHBlcmlvZGljYWxseVxuICAgICAgY29uc3QgcGluZ0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09IHdzLk9QRU4pIHtcbiAgICAgICAgICB3cy5waW5nKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2xlYXJJbnRlcnZhbChwaW5nSW50ZXJ2YWxJZCk7XG4gICAgICAgIH1cbiAgICAgIH0sIGNvbmZpZy53ZWJzb2NrZXRUaW1lb3V0IHx8IDEwICogMTAwMCk7XG4gICAgfTtcbiAgICB3c3Mub25FcnJvciA9IGVycm9yID0+IHtcbiAgICAgIGxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgfTtcbiAgICB3c3Muc3RhcnQoKTtcbiAgICB0aGlzLnNlcnZlciA9IHdzcztcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLnNlcnZlciAmJiB0aGlzLnNlcnZlci5jbG9zZSkge1xuICAgICAgdGhpcy5zZXJ2ZXIuY2xvc2UoKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFBhcnNlV2ViU29ja2V0IGV4dGVuZHMgZXZlbnRzLkV2ZW50RW1pdHRlciB7XG4gIHdzOiBhbnk7XG5cbiAgY29uc3RydWN0b3Iod3M6IGFueSkge1xuICAgIHN1cGVyKCk7XG4gICAgd3Mub25tZXNzYWdlID0gcmVxdWVzdCA9PlxuICAgICAgdGhpcy5lbWl0KCdtZXNzYWdlJywgcmVxdWVzdCAmJiByZXF1ZXN0LmRhdGEgPyByZXF1ZXN0LmRhdGEgOiByZXF1ZXN0KTtcbiAgICB3cy5vbmNsb3NlID0gKCkgPT4gdGhpcy5lbWl0KCdkaXNjb25uZWN0Jyk7XG4gICAgdGhpcy53cyA9IHdzO1xuICB9XG5cbiAgc2VuZChtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLndzLnNlbmQobWVzc2FnZSk7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/LiveQuery/QueryTools.js b/lib/LiveQuery/QueryTools.js new file mode 100644 index 0000000000..0330c7e092 --- /dev/null +++ b/lib/LiveQuery/QueryTools.js @@ -0,0 +1,407 @@ +"use strict"; + +var equalObjects = require('./equalObjects'); + +var Id = require('./Id'); + +var Parse = require('parse/node'); +/** + * Query Hashes are deterministic hashes for Parse Queries. + * Any two queries that have the same set of constraints will produce the same + * hash. This lets us reliably group components by the queries they depend upon, + * and quickly determine if a query has changed. + */ + +/** + * Convert $or queries into an array of where conditions + */ + + +function flattenOrQueries(where) { + if (!Object.prototype.hasOwnProperty.call(where, '$or')) { + return where; + } + + var accum = []; + + for (var i = 0; i < where.$or.length; i++) { + accum = accum.concat(where.$or[i]); + } + + return accum; +} +/** + * Deterministically turns an object into a string. Disregards ordering + */ + + +function stringify(object) { + if (typeof object !== 'object' || object === null) { + if (typeof object === 'string') { + return '"' + object.replace(/\|/g, '%|') + '"'; + } + + return object + ''; + } + + if (Array.isArray(object)) { + var copy = object.map(stringify); + copy.sort(); + return '[' + copy.join(',') + ']'; + } + + var sections = []; + var keys = Object.keys(object); + keys.sort(); + + for (var k = 0; k < keys.length; k++) { + sections.push(stringify(keys[k]) + ':' + stringify(object[keys[k]])); + } + + return '{' + sections.join(',') + '}'; +} +/** + * Generate a hash from a query, with unique fields for columns, values, order, + * skip, and limit. + */ + + +function queryHash(query) { + if (query instanceof Parse.Query) { + query = { + className: query.className, + where: query._where + }; + } + + var where = flattenOrQueries(query.where || {}); + var columns = []; + var values = []; + var i; + + if (Array.isArray(where)) { + var uniqueColumns = {}; + + for (i = 0; i < where.length; i++) { + var subValues = {}; + var keys = Object.keys(where[i]); + keys.sort(); + + for (var j = 0; j < keys.length; j++) { + subValues[keys[j]] = where[i][keys[j]]; + uniqueColumns[keys[j]] = true; + } + + values.push(subValues); + } + + columns = Object.keys(uniqueColumns); + columns.sort(); + } else { + columns = Object.keys(where); + columns.sort(); + + for (i = 0; i < columns.length; i++) { + values.push(where[columns[i]]); + } + } + + var sections = [columns.join(','), stringify(values)]; + return query.className + ':' + sections.join('|'); +} +/** + * contains -- Determines if an object is contained in a list with special handling for Parse pointers. + */ + + +function contains(haystack, needle) { + if (needle && needle.__type && needle.__type === 'Pointer') { + for (const i in haystack) { + const ptr = haystack[i]; + + if (typeof ptr === 'string' && ptr === needle.objectId) { + return true; + } + + if (ptr.className === needle.className && ptr.objectId === needle.objectId) { + return true; + } + } + + return false; + } + + return haystack.indexOf(needle) > -1; +} +/** + * matchesQuery -- Determines if an object would be returned by a Parse Query + * It's a lightweight, where-clause only implementation of a full query engine. + * Since we find queries that match objects, rather than objects that match + * queries, we can avoid building a full-blown query tool. + */ + + +function matchesQuery(object, query) { + if (query instanceof Parse.Query) { + var className = object.id instanceof Id ? object.id.className : object.className; + + if (className !== query.className) { + return false; + } + + return matchesQuery(object, query._where); + } + + for (var field in query) { + if (!matchesKeyConstraints(object, field, query[field])) { + return false; + } + } + + return true; +} + +function equalObjectsGeneric(obj, compareTo, eqlFn) { + if (Array.isArray(obj)) { + for (var i = 0; i < obj.length; i++) { + if (eqlFn(obj[i], compareTo)) { + return true; + } + } + + return false; + } + + return eqlFn(obj, compareTo); +} +/** + * Determines whether an object matches a single key's constraints + */ + + +function matchesKeyConstraints(object, key, constraints) { + if (constraints === null) { + return false; + } + + if (key.indexOf('.') >= 0) { + // Key references a subobject + var keyComponents = key.split('.'); + var subObjectKey = keyComponents[0]; + var keyRemainder = keyComponents.slice(1).join('.'); + return matchesKeyConstraints(object[subObjectKey] || {}, keyRemainder, constraints); + } + + var i; + + if (key === '$or') { + for (i = 0; i < constraints.length; i++) { + if (matchesQuery(object, constraints[i])) { + return true; + } + } + + return false; + } + + if (key === '$relatedTo') { + // Bail! We can't handle relational queries locally + return false; + } // Decode Date JSON value + + + if (object[key] && object[key].__type == 'Date') { + object[key] = new Date(object[key].iso); + } // Equality (or Array contains) cases + + + if (typeof constraints !== 'object') { + if (Array.isArray(object[key])) { + return object[key].indexOf(constraints) > -1; + } + + return object[key] === constraints; + } + + var compareTo; + + if (constraints.__type) { + if (constraints.__type === 'Pointer') { + return equalObjectsGeneric(object[key], constraints, function (obj, ptr) { + return typeof obj !== 'undefined' && ptr.className === obj.className && ptr.objectId === obj.objectId; + }); + } + + return equalObjectsGeneric(object[key], Parse._decode(key, constraints), equalObjects); + } // More complex cases + + + for (var condition in constraints) { + compareTo = constraints[condition]; + + if (compareTo.__type) { + compareTo = Parse._decode(key, compareTo); + } + + switch (condition) { + case '$lt': + if (object[key] >= compareTo) { + return false; + } + + break; + + case '$lte': + if (object[key] > compareTo) { + return false; + } + + break; + + case '$gt': + if (object[key] <= compareTo) { + return false; + } + + break; + + case '$gte': + if (object[key] < compareTo) { + return false; + } + + break; + + case '$ne': + if (equalObjects(object[key], compareTo)) { + return false; + } + + break; + + case '$in': + if (!contains(compareTo, object[key])) { + return false; + } + + break; + + case '$nin': + if (contains(compareTo, object[key])) { + return false; + } + + break; + + case '$all': + for (i = 0; i < compareTo.length; i++) { + if (object[key].indexOf(compareTo[i]) < 0) { + return false; + } + } + + break; + + case '$exists': + { + const propertyExists = typeof object[key] !== 'undefined'; + const existenceIsRequired = constraints['$exists']; + + if (typeof constraints['$exists'] !== 'boolean') { + // The SDK will never submit a non-boolean for $exists, but if someone + // tries to submit a non-boolean for $exits outside the SDKs, just ignore it. + break; + } + + if (!propertyExists && existenceIsRequired || propertyExists && !existenceIsRequired) { + return false; + } + + break; + } + + case '$regex': + if (typeof compareTo === 'object') { + return compareTo.test(object[key]); + } // JS doesn't support perl-style escaping + + + var expString = ''; + var escapeEnd = -2; + var escapeStart = compareTo.indexOf('\\Q'); + + while (escapeStart > -1) { + // Add the unescaped portion + expString += compareTo.substring(escapeEnd + 2, escapeStart); + escapeEnd = compareTo.indexOf('\\E', escapeStart); + + if (escapeEnd > -1) { + expString += compareTo.substring(escapeStart + 2, escapeEnd).replace(/\\\\\\\\E/g, '\\E').replace(/\W/g, '\\$&'); + } + + escapeStart = compareTo.indexOf('\\Q', escapeEnd); + } + + expString += compareTo.substring(Math.max(escapeStart, escapeEnd + 2)); + var exp = new RegExp(expString, constraints.$options || ''); + + if (!exp.test(object[key])) { + return false; + } + + break; + + case '$nearSphere': + if (!compareTo || !object[key]) { + return false; + } + + var distance = compareTo.radiansTo(object[key]); + var max = constraints.$maxDistance || Infinity; + return distance <= max; + + case '$within': + if (!compareTo || !object[key]) { + return false; + } + + var southWest = compareTo.$box[0]; + var northEast = compareTo.$box[1]; + + if (southWest.latitude > northEast.latitude || southWest.longitude > northEast.longitude) { + // Invalid box, crosses the date line + return false; + } + + return object[key].latitude > southWest.latitude && object[key].latitude < northEast.latitude && object[key].longitude > southWest.longitude && object[key].longitude < northEast.longitude; + + case '$options': + // Not a query type, but a way to add options to $regex. Ignore and + // avoid the default + break; + + case '$maxDistance': + // Not a query type, but a way to add a cap to $nearSphere. Ignore and + // avoid the default + break; + + case '$select': + return false; + + case '$dontSelect': + return false; + + default: + return false; + } + } + + return true; +} + +var QueryTools = { + queryHash: queryHash, + matchesQuery: matchesQuery +}; +module.exports = QueryTools; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUXVlcnlUb29scy5qcyJdLCJuYW1lcyI6WyJlcXVhbE9iamVjdHMiLCJyZXF1aXJlIiwiSWQiLCJQYXJzZSIsImZsYXR0ZW5PclF1ZXJpZXMiLCJ3aGVyZSIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImFjY3VtIiwiaSIsIiRvciIsImxlbmd0aCIsImNvbmNhdCIsInN0cmluZ2lmeSIsIm9iamVjdCIsInJlcGxhY2UiLCJBcnJheSIsImlzQXJyYXkiLCJjb3B5IiwibWFwIiwic29ydCIsImpvaW4iLCJzZWN0aW9ucyIsImtleXMiLCJrIiwicHVzaCIsInF1ZXJ5SGFzaCIsInF1ZXJ5IiwiUXVlcnkiLCJjbGFzc05hbWUiLCJfd2hlcmUiLCJjb2x1bW5zIiwidmFsdWVzIiwidW5pcXVlQ29sdW1ucyIsInN1YlZhbHVlcyIsImoiLCJjb250YWlucyIsImhheXN0YWNrIiwibmVlZGxlIiwiX190eXBlIiwicHRyIiwib2JqZWN0SWQiLCJpbmRleE9mIiwibWF0Y2hlc1F1ZXJ5IiwiaWQiLCJmaWVsZCIsIm1hdGNoZXNLZXlDb25zdHJhaW50cyIsImVxdWFsT2JqZWN0c0dlbmVyaWMiLCJvYmoiLCJjb21wYXJlVG8iLCJlcWxGbiIsImtleSIsImNvbnN0cmFpbnRzIiwia2V5Q29tcG9uZW50cyIsInNwbGl0Iiwic3ViT2JqZWN0S2V5Iiwia2V5UmVtYWluZGVyIiwic2xpY2UiLCJEYXRlIiwiaXNvIiwiX2RlY29kZSIsImNvbmRpdGlvbiIsInByb3BlcnR5RXhpc3RzIiwiZXhpc3RlbmNlSXNSZXF1aXJlZCIsInRlc3QiLCJleHBTdHJpbmciLCJlc2NhcGVFbmQiLCJlc2NhcGVTdGFydCIsInN1YnN0cmluZyIsIk1hdGgiLCJtYXgiLCJleHAiLCJSZWdFeHAiLCIkb3B0aW9ucyIsImRpc3RhbmNlIiwicmFkaWFuc1RvIiwiJG1heERpc3RhbmNlIiwiSW5maW5pdHkiLCJzb3V0aFdlc3QiLCIkYm94Iiwibm9ydGhFYXN0IiwibGF0aXR1ZGUiLCJsb25naXR1ZGUiLCJRdWVyeVRvb2xzIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQSxJQUFJQSxZQUFZLEdBQUdDLE9BQU8sQ0FBQyxnQkFBRCxDQUExQjs7QUFDQSxJQUFJQyxFQUFFLEdBQUdELE9BQU8sQ0FBQyxNQUFELENBQWhCOztBQUNBLElBQUlFLEtBQUssR0FBR0YsT0FBTyxDQUFDLFlBQUQsQ0FBbkI7QUFFQTs7Ozs7OztBQU9BOzs7OztBQUdBLFNBQVNHLGdCQUFULENBQTBCQyxLQUExQixFQUFpQztBQUMvQixNQUFJLENBQUNDLE1BQU0sQ0FBQ0MsU0FBUCxDQUFpQkMsY0FBakIsQ0FBZ0NDLElBQWhDLENBQXFDSixLQUFyQyxFQUE0QyxLQUE1QyxDQUFMLEVBQXlEO0FBQ3ZELFdBQU9BLEtBQVA7QUFDRDs7QUFDRCxNQUFJSyxLQUFLLEdBQUcsRUFBWjs7QUFDQSxPQUFLLElBQUlDLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUdOLEtBQUssQ0FBQ08sR0FBTixDQUFVQyxNQUE5QixFQUFzQ0YsQ0FBQyxFQUF2QyxFQUEyQztBQUN6Q0QsSUFBQUEsS0FBSyxHQUFHQSxLQUFLLENBQUNJLE1BQU4sQ0FBYVQsS0FBSyxDQUFDTyxHQUFOLENBQVVELENBQVYsQ0FBYixDQUFSO0FBQ0Q7O0FBQ0QsU0FBT0QsS0FBUDtBQUNEO0FBRUQ7Ozs7O0FBR0EsU0FBU0ssU0FBVCxDQUFtQkMsTUFBbkIsRUFBbUM7QUFDakMsTUFBSSxPQUFPQSxNQUFQLEtBQWtCLFFBQWxCLElBQThCQSxNQUFNLEtBQUssSUFBN0MsRUFBbUQ7QUFDakQsUUFBSSxPQUFPQSxNQUFQLEtBQWtCLFFBQXRCLEVBQWdDO0FBQzlCLGFBQU8sTUFBTUEsTUFBTSxDQUFDQyxPQUFQLENBQWUsS0FBZixFQUFzQixJQUF0QixDQUFOLEdBQW9DLEdBQTNDO0FBQ0Q7O0FBQ0QsV0FBT0QsTUFBTSxHQUFHLEVBQWhCO0FBQ0Q7O0FBQ0QsTUFB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T2JqZWN0cycpO1xudmFyIElkID0gcmVxdWlyZSgnLi9JZCcpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpO1xuXG4vKipcbiAqIFF1ZXJ5IEhhc2hlcyBhcmUgZGV0ZXJtaW5pc3RpYyBoYXNoZXMgZm9yIFBhcnNlIFF1ZXJpZXMuXG4gKiBBbnkgdHdvIHF1ZXJpZXMgdGhhdCBoYXZlIHRoZSBzYW1lIHNldCBvZiBjb25zdHJhaW50cyB3aWxsIHByb2R1Y2UgdGhlIHNhbWVcbiAqIGhhc2guIFRoaXMgbGV0cyB1cyByZWxpYWJseSBncm91cCBjb21wb25lbnRzIGJ5IHRoZSBxdWVyaWVzIHRoZXkgZGVwZW5kIHVwb24sXG4gKiBhbmQgcXVpY2tseSBkZXRlcm1pbmUgaWYgYSBxdWVyeSBoYXMgY2hhbmdlZC5cbiAqL1xuXG4vKipcbiAqIENvbnZlcnQgJG9yIHF1ZXJpZXMgaW50byBhbiBhcnJheSBvZiB3aGVyZSBjb25kaXRpb25zXG4gKi9cbmZ1bmN0aW9uIGZsYXR0ZW5PclF1ZXJpZXMod2hlcmUpIHtcbiAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwod2hlcmUsICckb3InKSkge1xuICAgIHJldHVybiB3aGVyZTtcbiAgfVxuICB2YXIgYWNjdW0gPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB3aGVyZS4kb3IubGVuZ3RoOyBpKyspIHtcbiAgICBhY2N1bSA9IGFjY3VtLmNvbmNhdCh3aGVyZS4kb3JbaV0pO1xuICB9XG4gIHJldHVybiBhY2N1bTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmlzdGljYWxseSB0dXJucyBhbiBvYmplY3QgaW50byBhIHN0cmluZy4gRGlzcmVnYXJkcyBvcmRlcmluZ1xuICovXG5mdW5jdGlvbiBzdHJpbmdpZnkob2JqZWN0KTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnIHx8IG9iamVjdCA9PT0gbnVsbCkge1xuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuICdcIicgKyBvYmplY3QucmVwbGFjZSgvXFx8L2csICclfCcpICsgJ1wiJztcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdCArICcnO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KG9iamVjdCkpIHtcbiAgICB2YXIgY29weSA9IG9iamVjdC5tYXAoc3RyaW5naWZ5KTtcbiAgICBjb3B5LnNvcnQoKTtcbiAgICByZXR1cm4gJ1snICsgY29weS5qb2luKCcsJykgKyAnXSc7XG4gIH1cbiAgdmFyIHNlY3Rpb25zID0gW107XG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqZWN0KTtcbiAga2V5cy5zb3J0KCk7XG4gIGZvciAodmFyIGsgPSAwOyBrIDwga2V5cy5sZW5ndGg7IGsrKykge1xuICAgIHNlY3Rpb25zLnB1c2goc3RyaW5naWZ5KGtleXNba10pICsgJzonICsgc3RyaW5naWZ5KG9iamVjdFtrZXlzW2tdXSkpO1xuICB9XG4gIHJldHVybiAneycgKyBzZWN0aW9ucy5qb2luKCcsJykgKyAnfSc7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgYSBoYXNoIGZyb20gYSBxdWVyeSwgd2l0aCB1bmlxdWUgZmllbGRzIGZvciBjb2x1bW5zLCB2YWx1ZXMsIG9yZGVyLFxuICogc2tpcCwgYW5kIGxpbWl0LlxuICovXG5mdW5jdGlvbiBxdWVyeUhhc2gocXVlcnkpIHtcbiAgaWYgKHF1ZXJ5IGluc3RhbmNlb2YgUGFyc2UuUXVlcnkpIHtcbiAgICBxdWVyeSA9IHtcbiAgICAgIGNsYXNzTmFtZTogcXVlcnkuY2xhc3NOYW1lLFxuICAgICAgd2hlcmU6IHF1ZXJ5Ll93aGVyZSxcbiAgICB9O1xuICB9XG4gIHZhciB3aGVyZSA9IGZsYXR0ZW5PclF1ZXJpZXMocXVlcnkud2hlcmUgfHwge30pO1xuICB2YXIgY29sdW1ucyA9IFtdO1xuICB2YXIgdmFsdWVzID0gW107XG4gIHZhciBpO1xuICBpZiAoQXJyYXkuaXNBcnJheSh3aGVyZSkpIHtcbiAgICB2YXIgdW5pcXVlQ29sdW1ucyA9IHt9O1xuICAgIGZvciAoaSA9IDA7IGkgPCB3aGVyZS5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHN1YlZhbHVlcyA9IHt9O1xuICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh3aGVyZVtpXSk7XG4gICAgICBrZXlzLnNvcnQoKTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICBzdWJWYWx1ZXNba2V5c1tqXV0gPSB3aGVyZVtpXVtrZXlzW2pdXTtcbiAgICAgICAgdW5pcXVlQ29sdW1uc1trZXlzW2pdXSA9IHRydWU7XG4gICAgICB9XG4gICAgICB2YWx1ZXMucHVzaChzdWJWYWx1ZXMpO1xuICAgIH1cbiAgICBjb2x1bW5zID0gT2JqZWN0LmtleXModW5pcXVlQ29sdW1ucyk7XG4gICAgY29sdW1ucy5zb3J0KCk7XG4gIH0gZWxzZSB7XG4gICAgY29sdW1ucyA9IE9iamVjdC5rZXlzKHdoZXJlKTtcbiAgICBjb2x1bW5zLnNvcnQoKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgY29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2god2hlcmVbY29sdW1uc1tpXV0pO1xuICAgIH1cbiAgfVxuXG4gIHZhciBzZWN0aW9ucyA9IFtjb2x1bW5zLmpvaW4oJywnKSwgc3RyaW5naWZ5KHZhbHVlcyldO1xuXG4gIHJldHVybiBxdWVyeS5jbGFzc05hbWUgKyAnOicgKyBzZWN0aW9ucy5qb2luKCd8Jyk7XG59XG5cbi8qKlxuICogY29udGFpbnMgLS0gRGV0ZXJtaW5lcyBpZiBhbiBvYmplY3QgaXMgY29udGFpbmVkIGluIGEgbGlzdCB3aXRoIHNwZWNpYWwgaGFuZGxpbmcgZm9yIFBhcnNlIHBvaW50ZXJzLlxuICovXG5mdW5jdGlvbiBjb250YWlucyhoYXlzdGFjazogQXJyYXksIG5lZWRsZTogYW55KTogYm9vbGVhbiB7XG4gIGlmIChuZWVkbGUgJiYgbmVlZGxlLl9fdHlwZSAmJiBuZWVkbGUuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICBmb3IgKGNvbnN0IGkgaW4gaGF5c3RhY2spIHtcbiAgICAgIGNvbnN0IHB0ciA9IGhheXN0YWNrW2ldO1xuICAgICAgaWYgKHR5cGVvZiBwdHIgPT09ICdzdHJpbmcnICYmIHB0ciA9PT0gbmVlZGxlLm9iamVjdElkKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICBwdHIuY2xhc3NOYW1lID09PSBuZWVkbGUuY2xhc3NOYW1lICYmXG4gICAgICAgIHB0ci5vYmplY3RJZCA9PT0gbmVlZGxlLm9iamVjdElkXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gaGF5c3RhY2suaW5kZXhPZihuZWVkbGUpID4gLTE7XG59XG4vKipcbiAqIG1hdGNoZXNRdWVyeSAtLSBEZXRlcm1pbmVzIGlmIGFuIG9iamVjdCB3b3VsZCBiZSByZXR1cm5lZCBieSBhIFBhcnNlIFF1ZXJ5XG4gKiBJdCdzIGEgbGlnaHR3ZWlnaHQsIHdoZXJlLWNsYXVzZSBvbmx5IGltcGxlbWVudGF0aW9uIG9mIGEgZnVsbCBxdWVyeSBlbmdpbmUuXG4gKiBTaW5jZSB3ZSBmaW5kIHF1ZXJpZXMgdGhhdCBtYXRjaCBvYmplY3RzLCByYXRoZXIgdGhhbiBvYmplY3RzIHRoYXQgbWF0Y2hcbiAqIHF1ZXJpZXMsIHdlIGNhbiBhdm9pZCBidWlsZGluZyBhIGZ1bGwtYmxvd24gcXVlcnkgdG9vbC5cbiAqL1xuZnVuY3Rpb24gbWF0Y2hlc1F1ZXJ5KG9iamVjdDogYW55LCBxdWVyeTogYW55KTogYm9vbGVhbiB7XG4gIGlmIChxdWVyeSBpbnN0YW5jZW9mIFBhcnNlLlF1ZXJ5KSB7XG4gICAgdmFyIGNsYXNzTmFtZSA9XG4gICAgICBvYmplY3QuaWQgaW5zdGFuY2VvZiBJZCA/IG9iamVjdC5pZC5jbGFzc05hbWUgOiBvYmplY3QuY2xhc3NOYW1lO1xuICAgIGlmIChjbGFzc05hbWUgIT09IHF1ZXJ5LmNsYXNzTmFtZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gbWF0Y2hlc1F1ZXJ5KG9iamVjdCwgcXVlcnkuX3doZXJlKTtcbiAgfVxuICBmb3IgKHZhciBmaWVsZCBpbiBxdWVyeSkge1xuICAgIGlmICghbWF0Y2hlc0tleUNvbnN0cmFpbnRzKG9iamVjdCwgZmllbGQsIHF1ZXJ5W2ZpZWxkXSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGVxdWFsT2JqZWN0c0dlbmVyaWMob2JqLCBjb21wYXJlVG8sIGVxbEZuKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iai5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGVxbEZuKG9ialtpXSwgY29tcGFyZVRvKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIGVxbEZuKG9iaiwgY29tcGFyZVRvKTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmVzIHdoZXRoZXIgYW4gb2JqZWN0IG1hdGNoZXMgYSBzaW5nbGUga2V5J3MgY29uc3RyYWludHNcbiAqL1xuZnVuY3Rpb24gbWF0Y2hlc0tleUNvbnN0cmFpbnRzKG9iamVjdCwga2V5LCBjb25zdHJhaW50cykge1xuICBpZiAoY29uc3RyYWludHMgPT09IG51bGwpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGtleS5pbmRleE9mKCcuJykgPj0gMCkge1xuICAgIC8vIEtleSByZWZlcmVuY2VzIGEgc3Vib2JqZWN0XG4gICAgdmFyIGtleUNvbXBvbmVudHMgPSBrZXkuc3BsaXQoJy4nKTtcbiAgICB2YXIgc3ViT2JqZWN0S2V5ID0ga2V5Q29tcG9uZW50c1swXTtcbiAgICB2YXIga2V5UmVtYWluZGVyID0ga2V5Q29tcG9uZW50cy5zbGljZSgxKS5qb2luKCcuJyk7XG4gICAgcmV0dXJuIG1hdGNoZXNLZXlDb25zdHJhaW50cyhcbiAgICAgIG9iamVjdFtzdWJPYmplY3RLZXldIHx8IHt9LFxuICAgICAga2V5UmVtYWluZGVyLFxuICAgICAgY29uc3RyYWludHNcbiAgICApO1xuICB9XG4gIHZhciBpO1xuICBpZiAoa2V5ID09PSAnJG9yJykge1xuICAgIGZvciAoaSA9IDA7IGkgPCBjb25zdHJhaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG1hdGNoZXNRdWVyeShvYmplY3QsIGNvbnN0cmFpbnRzW2ldKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChrZXkgPT09ICckcmVsYXRlZFRvJykge1xuICAgIC8vIEJhaWwhIFdlIGNhbid0IGhhbmRsZSByZWxhdGlvbmFsIHF1ZXJpZXMgbG9jYWxseVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBEZWNvZGUgRGF0ZSBKU09OIHZhbHVlXG4gIGlmIChvYmplY3Rba2V5XSAmJiBvYmplY3Rba2V5XS5fX3R5cGUgPT0gJ0RhdGUnKSB7XG4gICAgb2JqZWN0W2tleV0gPSBuZXcgRGF0ZShvYmplY3Rba2V5XS5pc28pO1xuICB9XG4gIC8vIEVxdWFsaXR5IChvciBBcnJheSBjb250YWlucykgY2FzZXNcbiAgaWYgKHR5cGVvZiBjb25zdHJhaW50cyAhPT0gJ29iamVjdCcpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmplY3Rba2V5XSkpIHtcbiAgICAgIHJldHVybiBvYmplY3Rba2V5XS5pbmRleE9mKGNvbnN0cmFpbnRzKSA+IC0xO1xuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0W2tleV0gPT09IGNvbnN0cmFpbnRzO1xuICB9XG4gIHZhciBjb21wYXJlVG87XG4gIGlmIChjb25zdHJhaW50cy5fX3R5cGUpIHtcbiAgICBpZiAoY29uc3RyYWludHMuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgIHJldHVybiBlcXVhbE9iamVjdHNHZW5lcmljKG9iamVjdFtrZXldLCBjb25zdHJhaW50cywgZnVuY3Rpb24ob2JqLCBwdHIpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICB0eXBlb2Ygb2JqICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgIHB0ci5jbGFzc05hbWUgPT09IG9iai5jbGFzc05hbWUgJiZcbiAgICAgICAgICBwdHIub2JqZWN0SWQgPT09IG9iai5vYmplY3RJZFxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVxdWFsT2JqZWN0c0dlbmVyaWMoXG4gICAgICBvYmplY3Rba2V5XSxcbiAgICAgIFBhcnNlLl9kZWNvZGUoa2V5LCBjb25zdHJhaW50cyksXG4gICAgICBlcXVhbE9iamVjdHNcbiAgICApO1xuICB9XG4gIC8vIE1vcmUgY29tcGxleCBjYXNlc1xuICBmb3IgKHZhciBjb25kaXRpb24gaW4gY29uc3RyYWludHMpIHtcbiAgICBjb21wYXJlVG8gPSBjb25zdHJhaW50c1tjb25kaXRpb25dO1xuICAgIGlmIChjb21wYXJlVG8uX190eXBlKSB7XG4gICAgICBjb21wYXJlVG8gPSBQYXJzZS5fZGVjb2RlKGtleSwgY29tcGFyZVRvKTtcbiAgICB9XG4gICAgc3dpdGNoIChjb25kaXRpb24pIHtcbiAgICAgIGNhc2UgJyRsdCc6XG4gICAgICAgIGlmIChvYmplY3Rba2V5XSA+PSBjb21wYXJlVG8pIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICckbHRlJzpcbiAgICAgICAgaWYgKG9iamVjdFtrZXldID4gY29tcGFyZVRvKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnJGd0JzpcbiAgICAgICAgaWYgKG9iamVjdFtrZXldIDw9IGNvbXBhcmVUbykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJyRndGUnOlxuICAgICAgICBpZiAob2JqZWN0W2tleV0gPCBjb21wYXJlVG8pIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICckbmUnOlxuICAgICAgICBpZiAoZXF1YWxPYmplY3RzKG9iamVjdFtrZXldLCBjb21wYXJlVG8pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnJGluJzpcbiAgICAgICAgaWYgKCFjb250YWlucyhjb21wYXJlVG8sIG9iamVjdFtrZXldKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJyRuaW4nOlxuICAgICAgICBpZiAoY29udGFpbnMoY29tcGFyZVRvLCBvYmplY3Rba2V5XSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICckYWxsJzpcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbXBhcmVUby5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGlmIChvYmplY3Rba2V5XS5pbmRleE9mKGNvbXBhcmVUb1tpXSkgPCAwKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnJGV4aXN0cyc6IHtcbiAgICAgICAgY29uc3QgcHJvcGVydHlFeGlzdHMgPSB0eXBlb2Ygb2JqZWN0W2tleV0gIT09ICd1bmRlZmluZWQnO1xuICAgICAgICBjb25zdCBleGlzdGVuY2VJc1JlcXVpcmVkID0gY29uc3RyYWludHNbJyRleGlzdHMnXTtcbiAgICAgICAgaWYgKHR5cGVvZiBjb25zdHJhaW50c1snJGV4aXN0cyddICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAvLyBUaGUgU0RLIHdpbGwgbmV2ZXIgc3VibWl0IGEgbm9uLWJvb2xlYW4gZm9yICRleGlzdHMsIGJ1dCBpZiBzb21lb25lXG4gICAgICAgICAgLy8gdHJpZXMgdG8gc3VibWl0IGEgbm9uLWJvb2xlYW4gZm9yICRleGl0cyBvdXRzaWRlIHRoZSBTREtzLCBqdXN0IGlnbm9yZSBpdC5cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoXG4gICAgICAgICAgKCFwcm9wZXJ0eUV4aXN0cyAmJiBleGlzdGVuY2VJc1JlcXVpcmVkKSB8fFxuICAgICAgICAgIChwcm9wZXJ0eUV4aXN0cyAmJiAhZXhpc3RlbmNlSXNSZXF1aXJlZClcbiAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnJHJlZ2V4JzpcbiAgICAgICAgaWYgKHR5cGVvZiBjb21wYXJlVG8gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbXBhcmVUby50ZXN0KG9iamVjdFtrZXldKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBKUyBkb2Vzbid0IHN1cHBvcnQgcGVybC1zdHlsZSBlc2NhcGluZ1xuICAgICAgICB2YXIgZXhwU3RyaW5nID0gJyc7XG4gICAgICAgIHZhciBlc2NhcGVFbmQgPSAtMjtcbiAgICAgICAgdmFyIGVzY2FwZVN0YXJ0ID0gY29tcGFyZVRvLmluZGV4T2YoJ1xcXFxRJyk7XG4gICAgICAgIHdoaWxlIChlc2NhcGVTdGFydCA+IC0xKSB7XG4gICAgICAgICAgLy8gQWRkIHRoZSB1bmVzY2FwZWQgcG9ydGlvblxuICAgICAgICAgIGV4cFN0cmluZyArPSBjb21wYXJlVG8uc3Vic3RyaW5nKGVzY2FwZUVuZCArIDIsIGVzY2FwZVN0YXJ0KTtcbiAgICAgICAgICBlc2NhcGVFbmQgPSBjb21wYXJlVG8uaW5kZXhPZignXFxcXEUnLCBlc2NhcGVTdGFydCk7XG4gICAgICAgICAgaWYgKGVzY2FwZUVuZCA+IC0xKSB7XG4gICAgICAgICAgICBleHBTdHJpbmcgKz0gY29tcGFyZVRvXG4gICAgICAgICAgICAgIC5zdWJzdHJpbmcoZXNjYXBlU3RhcnQgKyAyLCBlc2NhcGVFbmQpXG4gICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXFxcXFxcXFxcXFxcRS9nLCAnXFxcXEUnKVxuICAgICAgICAgICAgICAucmVwbGFjZSgvXFxXL2csICdcXFxcJCYnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBlc2NhcGVTdGFydCA9IGNvbXBhcmVUby5pbmRleE9mKCdcXFxcUScsIGVzY2FwZUVuZCk7XG4gICAgICAgIH1cbiAgICAgICAgZXhwU3RyaW5nICs9IGNvbXBhcmVUby5zdWJzdHJpbmcoTWF0aC5tYXgoZXNjYXBlU3RhcnQsIGVzY2FwZUVuZCArIDIpKTtcbiAgICAgICAgdmFyIGV4cCA9IG5ldyBSZWdFeHAoZXhwU3RyaW5nLCBjb25zdHJhaW50cy4kb3B0aW9ucyB8fCAnJyk7XG4gICAgICAgIGlmICghZXhwLnRlc3Qob2JqZWN0W2tleV0pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnJG5lYXJTcGhlcmUnOlxuICAgICAgICBpZiAoIWNvbXBhcmVUbyB8fCAhb2JqZWN0W2tleV0pIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRpc3RhbmNlID0gY29tcGFyZVRvLnJhZGlhbnNUbyhvYmplY3Rba2V5XSk7XG4gICAgICAgIHZhciBtYXggPSBjb25zdHJhaW50cy4kbWF4RGlzdGFuY2UgfHwgSW5maW5pdHk7XG4gICAgICAgIHJldHVybiBkaXN0YW5jZSA8PSBtYXg7XG4gICAgICBjYXNlICckd2l0aGluJzpcbiAgICAgICAgaWYgKCFjb21wYXJlVG8gfHwgIW9iamVjdFtrZXldKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzb3V0aFdlc3QgPSBjb21wYXJlVG8uJGJveFswXTtcbiAgICAgICAgdmFyIG5vcnRoRWFzdCA9IGNvbXBhcmVUby4kYm94WzFdO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgc291dGhXZXN0LmxhdGl0dWRlID4gbm9ydGhFYXN0LmxhdGl0dWRlIHx8XG4gICAgICAgICAgc291dGhXZXN0LmxvbmdpdHVkZSA+IG5vcnRoRWFzdC5sb25naXR1ZGVcbiAgICAgICAgKSB7XG4gICAgICAgICAgLy8gSW52YWxpZCBib3gsIGNyb3NzZXMgdGhlIGRhdGUgbGluZVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIG9iamVjdFtrZXldLmxhdGl0dWRlID4gc291dGhXZXN0LmxhdGl0dWRlICYmXG4gICAgICAgICAgb2JqZWN0W2tleV0ubGF0aXR1ZGUgPCBub3J0aEVhc3QubGF0aXR1ZGUgJiZcbiAgICAgICAgICBvYmplY3Rba2V5XS5sb25naXR1ZGUgPiBzb3V0aFdlc3QubG9uZ2l0dWRlICYmXG4gICAgICAgICAgb2JqZWN0W2tleV0ubG9uZ2l0dWRlIDwgbm9ydGhFYXN0LmxvbmdpdHVkZVxuICAgICAgICApO1xuICAgICAgY2FzZSAnJG9wdGlvbnMnOlxuICAgICAgICAvLyBOb3QgYSBxdWVyeSB0eXBlLCBidXQgYSB3YXkgdG8gYWRkIG9wdGlvbnMgdG8gJHJlZ2V4LiBJZ25vcmUgYW5kXG4gICAgICAgIC8vIGF2b2lkIHRoZSBkZWZhdWx0XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnJG1heERpc3RhbmNlJzpcbiAgICAgICAgLy8gTm90IGEgcXVlcnkgdHlwZSwgYnV0IGEgd2F5IHRvIGFkZCBhIGNhcCB0byAkbmVhclNwaGVyZS4gSWdub3JlIGFuZFxuICAgICAgICAvLyBhdm9pZCB0aGUgZGVmYXVsdFxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJyRzZWxlY3QnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICckZG9udFNlbGVjdCc6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBRdWVyeVRvb2xzID0ge1xuICBxdWVyeUhhc2g6IHF1ZXJ5SGFzaCxcbiAgbWF0Y2hlc1F1ZXJ5OiBtYXRjaGVzUXVlcnksXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFF1ZXJ5VG9vbHM7XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/RequestSchema.js b/lib/LiveQuery/RequestSchema.js new file mode 100644 index 0000000000..08cb08c4c0 --- /dev/null +++ b/lib/LiveQuery/RequestSchema.js @@ -0,0 +1,146 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +const general = { + title: 'General request schema', + type: 'object', + properties: { + op: { + type: 'string', + enum: ['connect', 'subscribe', 'unsubscribe', 'update'] + } + }, + required: ['op'] +}; +const connect = { + title: 'Connect operation schema', + type: 'object', + properties: { + op: 'connect', + applicationId: { + type: 'string' + }, + javascriptKey: { + type: 'string' + }, + masterKey: { + type: 'string' + }, + clientKey: { + type: 'string' + }, + windowsKey: { + type: 'string' + }, + restAPIKey: { + type: 'string' + }, + sessionToken: { + type: 'string' + }, + installationId: { + type: 'string' + } + }, + required: ['op', 'applicationId'], + additionalProperties: false +}; +const subscribe = { + title: 'Subscribe operation schema', + type: 'object', + properties: { + op: 'subscribe', + requestId: { + type: 'number' + }, + query: { + title: 'Query field schema', + type: 'object', + properties: { + className: { + type: 'string' + }, + where: { + type: 'object' + }, + fields: { + type: 'array', + items: { + type: 'string' + }, + minItems: 1, + uniqueItems: true + } + }, + required: ['where', 'className'], + additionalProperties: false + }, + sessionToken: { + type: 'string' + } + }, + required: ['op', 'requestId', 'query'], + additionalProperties: false +}; +const update = { + title: 'Update operation schema', + type: 'object', + properties: { + op: 'update', + requestId: { + type: 'number' + }, + query: { + title: 'Query field schema', + type: 'object', + properties: { + className: { + type: 'string' + }, + where: { + type: 'object' + }, + fields: { + type: 'array', + items: { + type: 'string' + }, + minItems: 1, + uniqueItems: true + } + }, + required: ['where', 'className'], + additionalProperties: false + }, + sessionToken: { + type: 'string' + } + }, + required: ['op', 'requestId', 'query'], + additionalProperties: false +}; +const unsubscribe = { + title: 'Unsubscribe operation schema', + type: 'object', + properties: { + op: 'unsubscribe', + requestId: { + type: 'number' + } + }, + required: ['op', 'requestId'], + additionalProperties: false +}; +const RequestSchema = { + general: general, + connect: connect, + subscribe: subscribe, + update: update, + unsubscribe: unsubscribe +}; +var _default = RequestSchema; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUmVxdWVzdFNjaGVtYS5qcyJdLCJuYW1lcyI6WyJnZW5lcmFsIiwidGl0bGUiLCJ0eXBlIiwicHJvcGVydGllcyIsIm9wIiwiZW51bSIsInJlcXVpcmVkIiwiY29ubmVjdCIsImFwcGxpY2F0aW9uSWQiLCJqYXZhc2NyaXB0S2V5IiwibWFzdGVyS2V5IiwiY2xpZW50S2V5Iiwid2luZG93c0tleSIsInJlc3RBUElLZXkiLCJzZXNzaW9uVG9rZW4iLCJpbnN0YWxsYXRpb25JZCIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiwic3Vic2NyaWJlIiwicmVxdWVzdElkIiwicXVlcnkiLCJjbGFzc05hbWUiLCJ3aGVyZSIsImZpZWxkcyIsIml0ZW1zIiwibWluSXRlbXMiLCJ1bmlxdWVJdGVtcyIsInVwZGF0ZSIsInVuc3Vic2NyaWJlIiwiUmVxdWVzdFNjaGVtYSJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsTUFBTUEsT0FBTyxHQUFHO0FBQ2RDLEVBQUFBLEtBQUssRUFBRSx3QkFETztBQUVkQyxFQUFBQSxJQUFJLEVBQUUsUUFGUTtBQUdkQyxFQUFBQSxVQUFVLEVBQUU7QUFDVkMsSUFBQUEsRUFBRSxFQUFFO0FBQ0ZGLE1BQUFBLElBQUksRUFBRSxRQURKO0FBRUZHLE1BQUFBLElBQUksRUFBRSxDQUFDLFNBQUQsRUFBWSxXQUFaLEVBQXlCLGFBQXpCLEVBQXdDLFFBQXhDO0FBRko7QUFETSxHQUhFO0FBU2RDLEVBQUFBLFFBQVEsRUFBRSxDQUFDLElBQUQ7QUFUSSxDQUFoQjtBQVlBLE1BQU1DLE9BQU8sR0FBRztBQUNkTixFQUFBQSxLQUFLLEVBQUUsMEJBRE87QUFFZEMsRUFBQUEsSUFBSSxFQUFFLFFBRlE7QUFHZEMsRUFBQUEsVUFBVSxFQUFFO0FBQ1ZDLElBQUFBLEVBQUUsRUFBRSxTQURNO0FBRVZJLElBQUFBLGFBQWEsRUFBRTtBQUNiTixNQUFBQSxJQUFJLEVBQUU7QUFETyxLQUZMO0FBS1ZPLElBQUFBLGFBQWEs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LENBTEo7QUFNTkMsVUFBQUEsV0FBVyxFQUFFO0FBTlA7QUFQRSxPQUhQO0FBbUJMbkIsTUFBQUEsUUFBUSxFQUFFLENBQUMsT0FBRCxFQUFVLFdBQVYsQ0FuQkw7QUFvQkxVLE1BQUFBLG9CQUFvQixFQUFFO0FBcEJqQixLQUxHO0FBMkJWRixJQUFBQSxZQUFZLEVBQUU7QUFDWlosTUFBQUEsSUFBSSxFQUFFO0FBRE07QUEzQkosR0FIQztBQWtDYkksRUFBQUEsUUFBUSxFQUFFLENBQUMsSUFBRCxFQUFPLFdBQVAsRUFBb0IsT0FBcEIsQ0FsQ0c7QUFtQ2JVLEVBQUFBLG9CQUFvQixFQUFFO0FBbkNULENBQWY7QUFzQ0EsTUFBTVcsV0FBVyxHQUFHO0FBQ2xCMUIsRUFBQUEsS0FBSyxFQUFFLDhCQURXO0FBRWxCQyxFQUFBQSxJQUFJLEVBQUUsUUFGWTtBQUdsQkMsRUFBQUEsVUFBVSxFQUFFO0FBQ1ZDLElBQUFBLEVBQUUsRUFBRSxhQURNO0FBRVZjLElBQUFBLFNBQVMsRUFBRTtBQUNUaEIsTUFBQUEsSUFBSSxFQUFFO0FBREc7QUFGRCxHQUhNO0FBU2xCSSxFQUFBQSxRQUFRLEVBQUUsQ0FBQyxJQUFELEVBQU8sV0FBUCxDQVRRO0FBVWxCVSxFQUFBQSxvQkFBb0IsRUFBRTtBQVZKLENBQXBCO0FBYUEsTUFBTVksYUFBYSxHQUFHO0FBQ3BCNUIsRUFBQUEsT0FBTyxFQUFFQSxPQURXO0FBRXBCTyxFQUFBQSxPQUFPLEVBQUVBLE9BRlc7QUFHcEJVLEVBQUFBLFNBQVMsRUFBRUEsU0FIUztBQUlwQlMsRUFBQUEsTUFBTSxFQUFFQSxNQUpZO0FBS3BCQyxFQUFBQSxXQUFXLEVBQUVBO0FBTE8sQ0FBdEI7ZUFRZUMsYSIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGdlbmVyYWwgPSB7XG4gIHRpdGxlOiAnR2VuZXJhbCByZXF1ZXN0IHNjaGVtYScsXG4gIHR5cGU6ICdvYmplY3QnLFxuICBwcm9wZXJ0aWVzOiB7XG4gICAgb3A6IHtcbiAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgZW51bTogWydjb25uZWN0JywgJ3N1YnNjcmliZScsICd1bnN1YnNjcmliZScsICd1cGRhdGUnXSxcbiAgICB9LFxuICB9LFxuICByZXF1aXJlZDogWydvcCddLFxufTtcblxuY29uc3QgY29ubmVjdCA9IHtcbiAgdGl0bGU6ICdDb25uZWN0IG9wZXJhdGlvbiBzY2hlbWEnLFxuICB0eXBlOiAnb2JqZWN0JyxcbiAgcHJvcGVydGllczoge1xuICAgIG9wOiAnY29ubmVjdCcsXG4gICAgYXBwbGljYXRpb25JZDoge1xuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgfSxcbiAgICBqYXZhc2NyaXB0S2V5OiB7XG4gICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICB9LFxuICAgIG1hc3RlcktleToge1xuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgfSxcbiAgICBjbGllbnRLZXk6IHtcbiAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgIH0sXG4gICAgd2luZG93c0tleToge1xuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgfSxcbiAgICByZXN0QVBJS2V5OiB7XG4gICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICB9LFxuICAgIHNlc3Npb25Ub2tlbjoge1xuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgfSxcbiAgICBpbnN0YWxsYXRpb25JZDoge1xuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgfSxcbiAgfSxcbiAgcmVxdWlyZWQ6IFsnb3AnLCAnYXBwbGljYXRpb25JZCddLFxuICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG59O1xuXG5jb25zdCBzdWJzY3JpYmUgPSB7XG4gIHRpdGxlOiAnU3Vic2NyaWJlIG9wZXJhdGlvbiBzY2hlbWEnLFxuICB0eXBlOiAnb2JqZWN0JyxcbiAgcHJvcGVydGllczoge1xuICAgIG9wOiAnc3Vic2NyaWJlJyxcbiAgICByZXF1ZXN0SWQ6IHtcbiAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgIH0sXG4gICAgcXVlcnk6IHtcbiAgICAgIHRpdGxlOiAnUXVlcnkgZmllbGQgc2NoZW1hJyxcbiAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBjbGFzc05hbWU6IHtcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgfSxcbiAgICAgICAgd2hlcmU6IHtcbiAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgfSxcbiAgICAgICAgZmllbGRzOiB7XG4gICAgICAgICAgdHlwZTogJ2FycmF5JyxcbiAgICAgICAgICBpdGVtczoge1xuICAgICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBtaW5JdGVtczogMSxcbiAgICAgICAgICB1bmlxdWVJdGVtczogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICByZXF1aXJlZDogWyd3aGVyZScsICdjbGFzc05hbWUnXSxcbiAgICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiBmYWxzZSxcbiAgICB9LFxuICAgIHNlc3Npb25Ub2tlbjoge1xuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgfSxcbiAgfSxcbiAgcmVxdWlyZWQ6IFsnb3AnLCAncmVxdWVzdElkJywgJ3F1ZXJ5J10sXG4gIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiBmYWxzZSxcbn07XG5cbmNvbnN0IHVwZGF0ZSA9IHtcbiAgdGl0bGU6ICdVcGRhdGUgb3BlcmF0aW9uIHNjaGVtYScsXG4gIHR5cGU6ICdvYmplY3QnLFxuICBwcm9wZXJ0aWVzOiB7XG4gICAgb3A6ICd1cGRhdGUnLFxuICAgIHJlcXVlc3RJZDoge1xuICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgfSxcbiAgICBxdWVyeToge1xuICAgICAgdGl0bGU6ICdRdWVyeSBmaWVsZCBzY2hlbWEnLFxuICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGNsYXNzTmFtZToge1xuICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICB9LFxuICAgICAgICB3aGVyZToge1xuICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICB9LFxuICAgICAgICBmaWVsZHM6IHtcbiAgICAgICAgICB0eXBlOiAnYXJyYXknLFxuICAgICAgICAgIGl0ZW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIG1pbkl0ZW1zOiAxLFxuICAgICAgICAgIHVuaXF1ZUl0ZW1zOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkOiBbJ3doZXJlJywgJ2NsYXNzTmFtZSddLFxuICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlLFxuICAgIH0sXG4gICAgc2Vzc2lvblRva2VuOiB7XG4gICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICB9LFxuICB9LFxuICByZXF1aXJlZDogWydvcCcsICdyZXF1ZXN0SWQnLCAncXVlcnknXSxcbiAgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlLFxufTtcblxuY29uc3QgdW5zdWJzY3JpYmUgPSB7XG4gIHRpdGxlOiAnVW5zdWJzY3JpYmUgb3BlcmF0aW9uIHNjaGVtYScsXG4gIHR5cGU6ICdvYmplY3QnLFxuICBwcm9wZXJ0aWVzOiB7XG4gICAgb3A6ICd1bnN1YnNjcmliZScsXG4gICAgcmVxdWVzdElkOiB7XG4gICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICB9LFxuICB9LFxuICByZXF1aXJlZDogWydvcCcsICdyZXF1ZXN0SWQnXSxcbiAgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlLFxufTtcblxuY29uc3QgUmVxdWVzdFNjaGVtYSA9IHtcbiAgZ2VuZXJhbDogZ2VuZXJhbCxcbiAgY29ubmVjdDogY29ubmVjdCxcbiAgc3Vic2NyaWJlOiBzdWJzY3JpYmUsXG4gIHVwZGF0ZTogdXBkYXRlLFxuICB1bnN1YnNjcmliZTogdW5zdWJzY3JpYmUsXG59O1xuXG5leHBvcnQgZGVmYXVsdCBSZXF1ZXN0U2NoZW1hO1xuIl19 \ No newline at end of file diff --git a/lib/LiveQuery/SessionTokenCache.js b/lib/LiveQuery/SessionTokenCache.js new file mode 100644 index 0000000000..bc35b81f79 --- /dev/null +++ b/lib/LiveQuery/SessionTokenCache.js @@ -0,0 +1,67 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SessionTokenCache = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _lruCache = _interopRequireDefault(require("lru-cache")); + +var _logger = _interopRequireDefault(require("../logger")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function userForSessionToken(sessionToken) { + var q = new _node.default.Query('_Session'); + q.equalTo('sessionToken', sessionToken); + return q.first({ + useMasterKey: true + }).then(function (session) { + if (!session) { + return Promise.reject('No session found for session token'); + } + + return session.get('user'); + }); +} + +class SessionTokenCache { + constructor(timeout = 30 * 24 * 60 * 60 * 1000, maxSize = 10000) { + this.cache = new _lruCache.default({ + max: maxSize, + maxAge: timeout + }); + } + + getUserId(sessionToken) { + if (!sessionToken) { + return Promise.reject('Empty sessionToken'); + } + + const userId = this.cache.get(sessionToken); + + if (userId) { + _logger.default.verbose('Fetch userId %s of sessionToken %s from Cache', userId, sessionToken); + + return Promise.resolve(userId); + } + + return userForSessionToken(sessionToken).then(user => { + _logger.default.verbose('Fetch userId %s of sessionToken %s from Parse', user.id, sessionToken); + + const userId = user.id; + this.cache.set(sessionToken, userId); + return Promise.resolve(userId); + }, error => { + _logger.default.error('Can not fetch userId for sessionToken %j, error %j', sessionToken, error); + + return Promise.reject(error); + }); + } + +} + +exports.SessionTokenCache = SessionTokenCache; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvU2Vzc2lvblRva2VuQ2FjaGUuanMiXSwibmFtZXMiOlsidXNlckZvclNlc3Npb25Ub2tlbiIsInNlc3Npb25Ub2tlbiIsInEiLCJQYXJzZSIsIlF1ZXJ5IiwiZXF1YWxUbyIsImZpcnN0IiwidXNlTWFzdGVyS2V5IiwidGhlbiIsInNlc3Npb24iLCJQcm9taXNlIiwicmVqZWN0IiwiZ2V0IiwiU2Vzc2lvblRva2VuQ2FjaGUiLCJjb25zdHJ1Y3RvciIsInRpbWVvdXQiLCJtYXhTaXplIiwiY2FjaGUiLCJMUlUiLCJtYXgiLCJtYXhBZ2UiLCJnZXRVc2VySWQiLCJ1c2VySWQiLCJsb2dnZXIiLCJ2ZXJib3NlIiwicmVzb2x2ZSIsInVzZXIiLCJpZCIsInNldCIsImVycm9yIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxTQUFTQSxtQkFBVCxDQUE2QkMsWUFBN0IsRUFBMkM7QUFDekMsTUFBSUMsQ0FBQyxHQUFHLElBQUlDLGNBQU1DLEtBQVYsQ0FBZ0IsVUFBaEIsQ0FBUjtBQUNBRixFQUFBQSxDQUFDLENBQUNHLE9BQUYsQ0FBVSxjQUFWLEVBQTBCSixZQUExQjtBQUNBLFNBQU9DLENBQUMsQ0FBQ0ksS0FBRixDQUFRO0FBQUVDLElBQUFBLFlBQVksRUFBRTtBQUFoQixHQUFSLEVBQWdDQyxJQUFoQyxDQUFxQyxVQUFTQyxPQUFULEVBQWtCO0FBQzVELFFBQUksQ0FBQ0EsT0FBTCxFQUFjO0FBQ1osYUFBT0MsT0FBTyxDQUFDQyxNQUFSLENBQWUsb0NBQWYsQ0FBUDtBQUNEOztBQUNELFdBQU9GLE9BQU8sQ0FBQ0csR0FBUixDQUFZLE1BQVosQ0FBUDtBQUNELEdBTE0sQ0FBUDtBQU1EOztBQUVELE1BQU1DLGlCQUFOLENBQXdCO0FBR3RCQyxFQUFBQSxXQUFXLENBQ1RDLE9BQWUsR0FBRyxLQUFLLEVBQUwsR0FBVSxFQUFWLEdBQWUsRUFBZixHQUFvQixJQUQ3QixFQUVUQyxPQUFlLEdBQUcsS0FGVCxFQUdUO0FBQ0EsU0FBS0MsS0FBTCxHQUFhLElBQUlDLGlCQUFKLENBQVE7QUFDbkJDLE1BQUFBLEdBQUcsRUFBRUgsT0FEYztBQUVuQkksTUFBQUEsTUFBTSxFQUFFTDtBQUZXLEtBQVIsQ0FBYjtBQUlEOztBQUVETSxFQUFBQSxTQUFTLENBQUNwQixZQUFELEVBQTRCO0FBQ25DLFFBQUksQ0FBQ0EsWUFBTCxFQUFtQjtBQUNqQixhQUFPUyxPQUFPLENBQUNDLE1BQVIsQ0FBZSxvQkFBZixDQUFQO0FBQ0Q7O0FBQ0QsVUFBTVcsTUFBTSxHQUFHLEtBQUtMLEtBQUwsQ0FBV0wsR0FBWCxDQUFlWCxZQUFmLENBQWY7O0FBQ0EsUUFBSXFCLE1BQUosRUFBWTtBQUNWQyxzQkFBT0MsT0FBUCxDQUNFLCtDQURGLEVBRUVGLE1BRkYsRUFHRXJCLFlBSEY7O0FBS0EsYUFBT1MsT0FBTyxDQUFDZSxPQUFSLENBQWdCSCxNQUFoQixDQUFQO0FBQ0Q7O0FBQ0QsV0FBT3RCLG1CQUFtQixDQUFDQyxZQUFELENBQW5CLENBQWtDTyxJQUFsQyxDQUNMa0IsSUFBSSxJQUFJO0FBQ05ILHNCQUFPQyxPQUFQLENBQ0UsK0NBREYsRUFFRUUsSUFBSSxDQUFDQyxFQUZQLEVBR0UxQixZQUhGOztBQUtBLFlBQU1xQixNQUFNLEdBQUdJLElBQUksQ0FBQ0MsRUFBcEI7QUFDQSxXQUFLVixLQUFMLENBQVdXLEdBQVgsQ0FBZTNCLFlBQWYsRUFBNkJxQixNQUE3QjtBQUNBLGFBQU9aLE9BQU8sQ0FBQ2UsT0FBUixDQUFnQkgsTUFBaEIsQ0FBUDtBQUNELEtBVkksRUFXTE8sS0FBSyxJQUFJO0FBQ1BOLHNCQUFPTSxLQUFQLENBQ0Usb0RBREYsRUFFRTVCLFlBRkYsRUFHRTRCLEtBSEY7O0FBS0EsYUFBT25CLE9BQU8sQ0FBQ0MsTUFBUixDQUFla0IsS0FBZixDQUFQO0FBQ0QsS0FsQkksQ0FBUDtBQW9CRDs7QUE5Q3FCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IExSVSBmcm9tICdscnUtY2FjaGUnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuXG5mdW5jdGlvbiB1c2VyRm9yU2Vzc2lvblRva2VuKHNlc3Npb25Ub2tlbikge1xuICB2YXIgcSA9IG5ldyBQYXJzZS5RdWVyeSgnX1Nlc3Npb24nKTtcbiAgcS5lcXVhbFRvKCdzZXNzaW9uVG9rZW4nLCBzZXNzaW9uVG9rZW4pO1xuICByZXR1cm4gcS5maXJzdCh7IHVzZU1hc3RlcktleTogdHJ1ZSB9KS50aGVuKGZ1bmN0aW9uKHNlc3Npb24pIHtcbiAgICBpZiAoIXNlc3Npb24pIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnTm8gc2Vzc2lvbiBmb3VuZCBmb3Igc2Vzc2lvbiB0b2tlbicpO1xuICAgIH1cbiAgICByZXR1cm4gc2Vzc2lvbi5nZXQoJ3VzZXInKTtcbiAgfSk7XG59XG5cbmNsYXNzIFNlc3Npb25Ub2tlbkNhY2hlIHtcbiAgY2FjaGU6IE9iamVjdDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICB0aW1lb3V0OiBudW1iZXIgPSAzMCAqIDI0ICogNjAgKiA2MCAqIDEwMDAsXG4gICAgbWF4U2l6ZTogbnVtYmVyID0gMTAwMDBcbiAgKSB7XG4gICAgdGhpcy5jYWNoZSA9IG5ldyBMUlUoe1xuICAgICAgbWF4OiBtYXhTaXplLFxuICAgICAgbWF4QWdlOiB0aW1lb3V0LFxuICAgIH0pO1xuICB9XG5cbiAgZ2V0VXNlcklkKHNlc3Npb25Ub2tlbjogc3RyaW5nKTogYW55IHtcbiAgICBpZiAoIXNlc3Npb25Ub2tlbikge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdFbXB0eSBzZXNzaW9uVG9rZW4nKTtcbiAgICB9XG4gICAgY29uc3QgdXNlcklkID0gdGhpcy5jYWNoZS5nZXQoc2Vzc2lvblRva2VuKTtcbiAgICBpZiAodXNlcklkKSB7XG4gICAgICBsb2dnZXIudmVyYm9zZShcbiAgICAgICAgJ0ZldGNoIHVzZXJJZCAlcyBvZiBzZXNzaW9uVG9rZW4gJXMgZnJvbSBDYWNoZScsXG4gICAgICAgIHVzZXJJZCxcbiAgICAgICAgc2Vzc2lvblRva2VuXG4gICAgICApO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1c2VySWQpO1xuICAgIH1cbiAgICByZXR1cm4gdXNlckZvclNlc3Npb25Ub2tlbihzZXNzaW9uVG9rZW4pLnRoZW4oXG4gICAgICB1c2VyID0+IHtcbiAgICAgICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICAgICAgJ0ZldGNoIHVzZXJJZCAlcyBvZiBzZXNzaW9uVG9rZW4gJXMgZnJvbSBQYXJzZScsXG4gICAgICAgICAgdXNlci5pZCxcbiAgICAgICAgICBzZXNzaW9uVG9rZW5cbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdXNlcklkID0gdXNlci5pZDtcbiAgICAgICAgdGhpcy5jYWNoZS5zZXQoc2Vzc2lvblRva2VuLCB1c2VySWQpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVzZXJJZCk7XG4gICAgICB9LFxuICAgICAgZXJyb3IgPT4ge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICAgJ0NhbiBub3QgZmV0Y2ggdXNlcklkIGZvciBzZXNzaW9uVG9rZW4gJWosIGVycm9yICVqJyxcbiAgICAgICAgICBzZXNzaW9uVG9rZW4sXG4gICAgICAgICAgZXJyb3JcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCB7IFNlc3Npb25Ub2tlbkNhY2hlIH07XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/Subscription.js b/lib/LiveQuery/Subscription.js new file mode 100644 index 0000000000..eef03cf56f --- /dev/null +++ b/lib/LiveQuery/Subscription.js @@ -0,0 +1,61 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Subscription = void 0; + +var _logger = _interopRequireDefault(require("../logger")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Subscription { + // It is query condition eg query.where + constructor(className, query, queryHash) { + this.className = className; + this.query = query; + this.hash = queryHash; + this.clientRequestIds = new Map(); + } + + addClientSubscription(clientId, requestId) { + if (!this.clientRequestIds.has(clientId)) { + this.clientRequestIds.set(clientId, []); + } + + const requestIds = this.clientRequestIds.get(clientId); + requestIds.push(requestId); + } + + deleteClientSubscription(clientId, requestId) { + const requestIds = this.clientRequestIds.get(clientId); + + if (typeof requestIds === 'undefined') { + _logger.default.error('Can not find client %d to delete', clientId); + + return; + } + + const index = requestIds.indexOf(requestId); + + if (index < 0) { + _logger.default.error('Can not find client %d subscription %d to delete', clientId, requestId); + + return; + } + + requestIds.splice(index, 1); // Delete client reference if it has no subscription + + if (requestIds.length == 0) { + this.clientRequestIds.delete(clientId); + } + } + + hasSubscribingClient() { + return this.clientRequestIds.size > 0; + } + +} + +exports.Subscription = Subscription; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvU3Vic2NyaXB0aW9uLmpzIl0sIm5hbWVzIjpbIlN1YnNjcmlwdGlvbiIsImNvbnN0cnVjdG9yIiwiY2xhc3NOYW1lIiwicXVlcnkiLCJxdWVyeUhhc2giLCJoYXNoIiwiY2xpZW50UmVxdWVzdElkcyIsIk1hcCIsImFkZENsaWVudFN1YnNjcmlwdGlvbiIsImNsaWVudElkIiwicmVxdWVzdElkIiwiaGFzIiwic2V0IiwicmVxdWVzdElkcyIsImdldCIsInB1c2giLCJkZWxldGVDbGllbnRTdWJzY3JpcHRpb24iLCJsb2dnZXIiLCJlcnJvciIsImluZGV4IiwiaW5kZXhPZiIsInNwbGljZSIsImxlbmd0aCIsImRlbGV0ZSIsImhhc1N1YnNjcmliaW5nQ2xpZW50Iiwic2l6ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBS0EsTUFBTUEsWUFBTixDQUFtQjtBQUNqQjtBQU1BQyxFQUFBQSxXQUFXLENBQUNDLFNBQUQsRUFBb0JDLEtBQXBCLEVBQXNDQyxTQUF0QyxFQUF5RDtBQUNsRSxTQUFLRixTQUFMLEdBQWlCQSxTQUFqQjtBQUNBLFNBQUtDLEtBQUwsR0FBYUEsS0FBYjtBQUNBLFNBQUtFLElBQUwsR0FBWUQsU0FBWjtBQUNBLFNBQUtFLGdCQUFMLEdBQXdCLElBQUlDLEdBQUosRUFBeEI7QUFDRDs7QUFFREMsRUFBQUEscUJBQXFCLENBQUNDLFFBQUQsRUFBbUJDLFNBQW5CLEVBQTRDO0FBQy9ELFFBQUksQ0FBQyxLQUFLSixnQkFBTCxDQUFzQkssR0FBdEIsQ0FBMEJGLFFBQTFCLENBQUwsRUFBMEM7QUFDeEMsV0FBS0gsZ0JBQUwsQ0FBc0JNLEdBQXRCLENBQTBCSCxRQUExQixFQUFvQyxFQUFwQztBQUNEOztBQUNELFVBQU1JLFVBQVUsR0FBRyxLQUFLUCxnQkFBTCxDQUFzQlEsR0FBdEIsQ0FBMEJMLFFBQTFCLENBQW5CO0FBQ0FJLElBQUFBLFVBQVUsQ0FBQ0UsSUFBWCxDQUFnQkwsU0FBaEI7QUFDRDs7QUFFRE0sRUFBQUEsd0JBQXdCLENBQUNQLFFBQUQsRUFBbUJDLFNBQW5CLEVBQTRDO0FBQ2xFLFVBQU1HLFVBQVUsR0FBRyxLQUFLUCxnQkFBTCxDQUFzQlEsR0FBdEIsQ0FBMEJMLFFBQTFCLENBQW5COztBQUNBLFFBQUksT0FBT0ksVUFBUCxLQUFzQixXQUExQixFQUF1QztBQUNyQ0ksc0JBQU9DLEtBQVAsQ0FBYSxrQ0FBYixFQUFpRFQsUUFBakQ7O0FBQ0E7QUFDRDs7QUFFRCxVQUFNVSxLQUFLLEdBQUdOLFVBQVUsQ0FBQ08sT0FBWCxDQUFtQlYsU0FBbkIsQ0FBZDs7QUFDQSxRQUFJUyxLQUFLLEdBQUcsQ0FBWixFQUFlO0FBQ2JGLHNCQUFPQyxLQUFQLENBQ0Usa0RBREYsRUFFRVQsUUFGRixFQUdFQyxTQUhGOztBQUtBO0FBQ0Q7O0FBQ0RHLElBQUFBLFVBQVUsQ0FBQ1EsTUFBWCxDQUFrQkYsS0FBbEIsRUFBeUIsQ0FBekIsRUFoQmtFLENBaUJsRTs7QUFDQSxRQUFJTixVQUFVLENBQUNTLE1BQVgsSUFBcUIsQ0FBekIsRUFBNEI7QUFDMUIsV0FBS2hCLGdCQUFMLENBQXNCaUIsTUFBdEIsQ0FBNkJkLFFBQTdCO0FBQ0Q7QUFDRjs7QUFFRGUsRUFBQUEsb0JBQW9CLEdBQVk7QUFDOUIsV0FBTyxLQUFLbEIsZ0JBQUwsQ0FBc0JtQixJQUF0QixHQUE2QixDQUFwQztBQUNEOztBQS9DZ0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCB0eXBlIEZsYXR0ZW5lZE9iamVjdERhdGEgPSB7IFthdHRyOiBzdHJpbmddOiBhbnkgfTtcbmV4cG9ydCB0eXBlIFF1ZXJ5RGF0YSA9IHsgW2F0dHI6IHN0cmluZ106IGFueSB9O1xuXG5jbGFzcyBTdWJzY3JpcHRpb24ge1xuICAvLyBJdCBpcyBxdWVyeSBjb25kaXRpb24gZWcgcXVlcnkud2hlcmVcbiAgcXVlcnk6IFF1ZXJ5RGF0YTtcbiAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gIGhhc2g6IHN0cmluZztcbiAgY2xpZW50UmVxdWVzdElkczogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogUXVlcnlEYXRhLCBxdWVyeUhhc2g6IHN0cmluZykge1xuICAgIHRoaXMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgIHRoaXMucXVlcnkgPSBxdWVyeTtcbiAgICB0aGlzLmhhc2ggPSBxdWVyeUhhc2g7XG4gICAgdGhpcy5jbGllbnRSZXF1ZXN0SWRzID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgYWRkQ2xpZW50U3Vic2NyaXB0aW9uKGNsaWVudElkOiBudW1iZXIsIHJlcXVlc3RJZDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNsaWVudFJlcXVlc3RJZHMuaGFzKGNsaWVudElkKSkge1xuICAgICAgdGhpcy5jbGllbnRSZXF1ZXN0SWRzLnNldChjbGllbnRJZCwgW10pO1xuICAgIH1cbiAgICBjb25zdCByZXF1ZXN0SWRzID0gdGhpcy5jbGllbnRSZXF1ZXN0SWRzLmdldChjbGllbnRJZCk7XG4gICAgcmVxdWVzdElkcy5wdXNoKHJlcXVlc3RJZCk7XG4gIH1cblxuICBkZWxldGVDbGllbnRTdWJzY3JpcHRpb24oY2xpZW50SWQ6IG51bWJlciwgcmVxdWVzdElkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCByZXF1ZXN0SWRzID0gdGhpcy5jbGllbnRSZXF1ZXN0SWRzLmdldChjbGllbnRJZCk7XG4gICAgaWYgKHR5cGVvZiByZXF1ZXN0SWRzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgbG9nZ2VyLmVycm9yKCdDYW4gbm90IGZpbmQgY2xpZW50ICVkIHRvIGRlbGV0ZScsIGNsaWVudElkKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBpbmRleCA9IHJlcXVlc3RJZHMuaW5kZXhPZihyZXF1ZXN0SWQpO1xuICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0NhbiBub3QgZmluZCBjbGllbnQgJWQgc3Vic2NyaXB0aW9uICVkIHRvIGRlbGV0ZScsXG4gICAgICAgIGNsaWVudElkLFxuICAgICAgICByZXF1ZXN0SWRcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJlcXVlc3RJZHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAvLyBEZWxldGUgY2xpZW50IHJlZmVyZW5jZSBpZiBpdCBoYXMgbm8gc3Vic2NyaXB0aW9uXG4gICAgaWYgKHJlcXVlc3RJZHMubGVuZ3RoID09IDApIHtcbiAgICAgIHRoaXMuY2xpZW50UmVxdWVzdElkcy5kZWxldGUoY2xpZW50SWQpO1xuICAgIH1cbiAgfVxuXG4gIGhhc1N1YnNjcmliaW5nQ2xpZW50KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNsaWVudFJlcXVlc3RJZHMuc2l6ZSA+IDA7XG4gIH1cbn1cblxuZXhwb3J0IHsgU3Vic2NyaXB0aW9uIH07XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/equalObjects.js b/lib/LiveQuery/equalObjects.js new file mode 100644 index 0000000000..028cc134ac --- /dev/null +++ b/lib/LiveQuery/equalObjects.js @@ -0,0 +1,62 @@ +"use strict"; + +var toString = Object.prototype.toString; +/** + * Determines whether two objects represent the same primitive, special Parse + * type, or full Parse Object. + */ + +function equalObjects(a, b) { + if (typeof a !== typeof b) { + return false; + } + + if (typeof a !== 'object') { + return a === b; + } + + if (a === b) { + return true; + } + + if (toString.call(a) === '[object Date]') { + if (toString.call(b) === '[object Date]') { + return +a === +b; + } + + return false; + } + + if (Array.isArray(a)) { + if (Array.isArray(b)) { + if (a.length !== b.length) { + return false; + } + + for (var i = 0; i < a.length; i++) { + if (!equalObjects(a[i], b[i])) { + return false; + } + } + + return true; + } + + return false; + } + + if (Object.keys(a).length !== Object.keys(b).length) { + return false; + } + + for (var key in a) { + if (!equalObjects(a[key], b[key])) { + return false; + } + } + + return true; +} + +module.exports = equalObjects; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvZXF1YWxPYmplY3RzLmpzIl0sIm5hbWVzIjpbInRvU3RyaW5nIiwiT2JqZWN0IiwicHJvdG90eXBlIiwiZXF1YWxPYmplY3RzIiwiYSIsImIiLCJjYWxsIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiaSIsImtleXMiLCJrZXkiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLElBQUlBLFFBQVEsR0FBR0MsTUFBTSxDQUFDQyxTQUFQLENBQWlCRixRQUFoQztBQUVBOzs7OztBQUlBLFNBQVNHLFlBQVQsQ0FBc0JDLENBQXRCLEVBQXlCQyxDQUF6QixFQUE0QjtBQUMxQixNQUFJLE9BQU9ELENBQVAsS0FBYSxPQUFPQyxDQUF4QixFQUEyQjtBQUN6QixXQUFPLEtBQVA7QUFDRDs7QUFDRCxNQUFJLE9BQU9ELENBQVAsS0FBYSxRQUFqQixFQUEyQjtBQUN6QixXQUFPQSxDQUFDLEtBQUtDLENBQWI7QUFDRDs7QUFDRCxNQUFJRCxDQUFDLEtBQUtDLENBQVYsRUFBYTtBQUNYLFdBQU8sSUFBUDtBQUNEOztBQUNELE1BQUlMLFFBQVEsQ0FBQ00sSUFBVCxDQUFjRixDQUFkLE1BQXFCLGVBQXpCLEVBQTBDO0FBQ3hDLFFBQUlKLFFBQVEsQ0FBQ00sSUFBVCxDQUFjRCxDQUFkLE1BQXFCLGVBQXpCLEVBQTBDO0FBQ3hDLGFBQU8sQ0FBQ0QsQ0FBRCxLQUFPLENBQUNDLENBQWY7QUFDRDs7QUFDRCxXQUFPLEtBQVA7QUFDRDs7QUFDRCxNQUFJRSxLQUFLLENBQUNDLE9BQU4sQ0FBY0osQ0FBZCxDQUFKLEVBQXNCO0FBQ3BCLFFBQUlHLEtBQUssQ0FBQ0MsT0FBTixDQUFjSCxDQUFkLENBQUosRUFBc0I7QUFDcEIsVUFBSUQsQ0FBQyxDQUFDSyxNQUFGLEtBQWFKLENBQUMsQ0FBQ0ksTUFBbkIsRUFBMkI7QUFDekIsZUFBTyxLQUFQO0FBQ0Q7O0FBQ0QsV0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHTixDQUFDLENBQUNLLE1BQXRCLEVBQThCQyxDQUFDLEVBQS9CLEVBQW1DO0FBQ2pDLFlBQUksQ0FBQ1AsWUFBWSxDQUFDQyxDQUFDLENBQUNNLENBQUQsQ0FBRixFQUFPTCxDQUFDLENBQUNLLENBQUQsQ0FBUixDQUFqQixFQUErQjtBQUM3QixpQkFBTyxLQUFQO0FBQ0Q7QUFDRjs7QUFDRCxhQUFPLElBQVA7QUFDRDs7QUFDRCxXQUFPLEtBQVA7QUFDRDs7QUFDRCxNQUFJVCxNQUFNLENBQUNVLElBQVAsQ0FBWVAsQ0FBWixFQUFlSyxNQUFmLEtBQTBCUixNQUFNLENBQUNVLElBQVAsQ0FBWU4sQ0FBWixFQUFlSSxNQUE3QyxFQUFxRDtBQUNuRCxXQUFPLEtBQVA7QUFDRDs7QUFDRCxPQUFLLElBQUlHLEdBQVQsSUFBZ0JSLENBQWhCLEVBQW1CO0FBQ2pCLFFBQUksQ0FBQ0QsWUFBWSxDQUFDQyxDQUFDLENBQUNRLEdBQUQsQ0FBRixFQUFTUCxDQUFDLENBQUNPLEdBQUQsQ0FBVixDQUFqQixFQUFtQztBQUNqQyxhQUFPLEtBQVA7QUFDRDtBQUNGOztBQUNELFNBQU8sSUFBUDtBQUNEOztBQUVEQyxNQUFNLENBQUNDLE9BQVAsR0FBaUJYLFlBQWpCIiwic291cmNlc0NvbnRlbnQiOlsidmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuLyoqXG4gKiBEZXRlcm1pbmVzIHdoZXRoZXIgdHdvIG9iamVjdHMgcmVwcmVzZW50IHRoZSBzYW1lIHByaW1pdGl2ZSwgc3BlY2lhbCBQYXJzZVxuICogdHlwZSwgb3IgZnVsbCBQYXJzZSBPYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGVxdWFsT2JqZWN0cyhhLCBiKSB7XG4gIGlmICh0eXBlb2YgYSAhPT0gdHlwZW9mIGIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKHR5cGVvZiBhICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBhID09PSBiO1xuICB9XG4gIGlmIChhID09PSBiKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKHRvU3RyaW5nLmNhbGwoYSkgPT09ICdbb2JqZWN0IERhdGVdJykge1xuICAgIGlmICh0b1N0cmluZy5jYWxsKGIpID09PSAnW29iamVjdCBEYXRlXScpIHtcbiAgICAgIHJldHVybiArYSA9PT0gK2I7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoQXJyYXkuaXNBcnJheShhKSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGIpKSB7XG4gICAgICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoIWVxdWFsT2JqZWN0cyhhW2ldLCBiW2ldKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoT2JqZWN0LmtleXMoYSkubGVuZ3RoICE9PSBPYmplY3Qua2V5cyhiKS5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgZm9yICh2YXIga2V5IGluIGEpIHtcbiAgICBpZiAoIWVxdWFsT2JqZWN0cyhhW2tleV0sIGJba2V5XSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZXF1YWxPYmplY3RzO1xuIl19 \ No newline at end of file diff --git a/lib/Options/Definitions.js b/lib/Options/Definitions.js new file mode 100644 index 0000000000..c5bfc3be4a --- /dev/null +++ b/lib/Options/Definitions.js @@ -0,0 +1,498 @@ +"use strict"; + +/* +**** GENERATED CODE **** +This code has been generated by resources/buildConfigDefinitions.js +Do not edit manually, but update Options/index.js +*/ +var parsers = require('./parsers'); + +module.exports.ParseServerOptions = { + accountLockout: { + env: 'PARSE_SERVER_ACCOUNT_LOCKOUT', + help: 'account lockout policy for failed login attempts', + action: parsers.objectParser + }, + allowClientClassCreation: { + env: 'PARSE_SERVER_ALLOW_CLIENT_CLASS_CREATION', + help: 'Enable (or disable) client class creation, defaults to true', + action: parsers.booleanParser, + default: true + }, + allowHeaders: { + env: 'PARSE_SERVER_ALLOW_HEADERS', + help: 'Add headers to Access-Control-Allow-Headers', + action: parsers.arrayParser + }, + analyticsAdapter: { + env: 'PARSE_SERVER_ANALYTICS_ADAPTER', + help: 'Adapter module for the analytics', + action: parsers.moduleOrObjectParser + }, + appId: { + env: 'PARSE_SERVER_APPLICATION_ID', + help: 'Your Parse Application ID', + required: true + }, + appName: { + env: 'PARSE_SERVER_APP_NAME', + help: 'Sets the app name' + }, + auth: { + env: 'PARSE_SERVER_AUTH_PROVIDERS', + help: 'Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication', + action: parsers.objectParser + }, + cacheAdapter: { + env: 'PARSE_SERVER_CACHE_ADAPTER', + help: 'Adapter module for the cache', + action: parsers.moduleOrObjectParser + }, + cacheMaxSize: { + env: 'PARSE_SERVER_CACHE_MAX_SIZE', + help: 'Sets the maximum size for the in memory cache, defaults to 10000', + action: parsers.numberParser('cacheMaxSize'), + default: 10000 + }, + cacheTTL: { + env: 'PARSE_SERVER_CACHE_TTL', + help: 'Sets the TTL for the in memory cache (in ms), defaults to 5000 (5 seconds)', + action: parsers.numberParser('cacheTTL'), + default: 5000 + }, + clientKey: { + env: 'PARSE_SERVER_CLIENT_KEY', + help: 'Key for iOS, MacOS, tvOS clients' + }, + cloud: { + env: 'PARSE_SERVER_CLOUD', + help: 'Full path to your cloud code main.js' + }, + cluster: { + env: 'PARSE_SERVER_CLUSTER', + help: 'Run with cluster, optionally set the number of processes default to os.cpus().length', + action: parsers.numberOrBooleanParser + }, + collectionPrefix: { + env: 'PARSE_SERVER_COLLECTION_PREFIX', + help: 'A collection prefix for the classes', + default: '' + }, + customPages: { + env: 'PARSE_SERVER_CUSTOM_PAGES', + help: 'custom pages for password validation and reset', + action: parsers.objectParser, + default: {} + }, + databaseAdapter: { + env: 'PARSE_SERVER_DATABASE_ADAPTER', + help: 'Adapter module for the database', + action: parsers.moduleOrObjectParser + }, + databaseOptions: { + env: 'PARSE_SERVER_DATABASE_OPTIONS', + help: 'Options to pass to the mongodb client', + action: parsers.objectParser + }, + databaseURI: { + env: 'PARSE_SERVER_DATABASE_URI', + help: 'The full URI to your database. Supported databases are mongodb or postgres.', + required: true, + default: 'mongodb://localhost:27017/parse' + }, + directAccess: { + env: 'PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS', + help: 'Replace HTTP Interface when using JS SDK in current node runtime, defaults to false. Caution, this is an experimental feature that may not be appropriate for production.', + action: parsers.booleanParser, + default: false + }, + dotNetKey: { + env: 'PARSE_SERVER_DOT_NET_KEY', + help: 'Key for Unity and .Net SDK' + }, + emailAdapter: { + env: 'PARSE_SERVER_EMAIL_ADAPTER', + help: 'Adapter module for email sending', + action: parsers.moduleOrObjectParser + }, + emailVerifyTokenValidityDuration: { + env: 'PARSE_SERVER_EMAIL_VERIFY_TOKEN_VALIDITY_DURATION', + help: 'Email verification token validity duration, in seconds', + action: parsers.numberParser('emailVerifyTokenValidityDuration') + }, + enableAnonymousUsers: { + env: 'PARSE_SERVER_ENABLE_ANON_USERS', + help: 'Enable (or disable) anon users, defaults to true', + action: parsers.booleanParser, + default: true + }, + enableExpressErrorHandler: { + env: 'PARSE_SERVER_ENABLE_EXPRESS_ERROR_HANDLER', + help: 'Enables the default express error handler for all errors', + action: parsers.booleanParser, + default: false + }, + enableSingleSchemaCache: { + env: 'PARSE_SERVER_ENABLE_SINGLE_SCHEMA_CACHE', + help: 'Use a single schema cache shared across requests. Reduces number of queries made to _SCHEMA, defaults to false, i.e. unique schema cache per request.', + action: parsers.booleanParser, + default: false + }, + expireInactiveSessions: { + env: 'PARSE_SERVER_EXPIRE_INACTIVE_SESSIONS', + help: 'Sets wether we should expire the inactive sessions, defaults to true', + action: parsers.booleanParser, + default: true + }, + fileKey: { + env: 'PARSE_SERVER_FILE_KEY', + help: 'Key for your files' + }, + filesAdapter: { + env: 'PARSE_SERVER_FILES_ADAPTER', + help: 'Adapter module for the files sub-system', + action: parsers.moduleOrObjectParser + }, + graphQLPath: { + env: 'PARSE_SERVER_GRAPHQL_PATH', + help: 'Mount path for the GraphQL endpoint, defaults to /graphql', + default: '/graphql' + }, + graphQLSchema: { + env: 'PARSE_SERVER_GRAPH_QLSCHEMA', + help: 'Full path to your GraphQL custom schema.graphql file' + }, + host: { + env: 'PARSE_SERVER_HOST', + help: 'The host to serve ParseServer on, defaults to 0.0.0.0', + default: '0.0.0.0' + }, + javascriptKey: { + env: 'PARSE_SERVER_JAVASCRIPT_KEY', + help: 'Key for the Javascript SDK' + }, + jsonLogs: { + env: 'JSON_LOGS', + help: 'Log as structured JSON objects', + action: parsers.booleanParser + }, + liveQuery: { + env: 'PARSE_SERVER_LIVE_QUERY', + help: "parse-server's LiveQuery configuration object", + action: parsers.objectParser + }, + liveQueryServerOptions: { + env: 'PARSE_SERVER_LIVE_QUERY_SERVER_OPTIONS', + help: 'Live query server configuration options (will start the liveQuery server)', + action: parsers.objectParser + }, + loggerAdapter: { + env: 'PARSE_SERVER_LOGGER_ADAPTER', + help: 'Adapter module for the logging sub-system', + action: parsers.moduleOrObjectParser + }, + logLevel: { + env: 'PARSE_SERVER_LOG_LEVEL', + help: 'Sets the level for logs' + }, + logsFolder: { + env: 'PARSE_SERVER_LOGS_FOLDER', + help: "Folder for the logs (defaults to './logs'); set to null to disable file based logging", + default: './logs' + }, + masterKey: { + env: 'PARSE_SERVER_MASTER_KEY', + help: 'Your Parse Master Key', + required: true + }, + masterKeyIps: { + env: 'PARSE_SERVER_MASTER_KEY_IPS', + help: 'Restrict masterKey to be used by only these ips, defaults to [] (allow all ips)', + action: parsers.arrayParser, + default: [] + }, + maxLimit: { + env: 'PARSE_SERVER_MAX_LIMIT', + help: 'Max value for limit option on queries, defaults to unlimited', + action: parsers.numberParser('maxLimit') + }, + maxUploadSize: { + env: 'PARSE_SERVER_MAX_UPLOAD_SIZE', + help: 'Max file size for uploads, defaults to 20mb', + default: '20mb' + }, + middleware: { + env: 'PARSE_SERVER_MIDDLEWARE', + help: 'middleware for express server, can be string or function' + }, + mountGraphQL: { + env: 'PARSE_SERVER_MOUNT_GRAPHQL', + help: 'Mounts the GraphQL endpoint', + action: parsers.booleanParser, + default: false + }, + mountPath: { + env: 'PARSE_SERVER_MOUNT_PATH', + help: 'Mount path for the server, defaults to /parse', + default: '/parse' + }, + mountPlayground: { + env: 'PARSE_SERVER_MOUNT_PLAYGROUND', + help: 'Mounts the GraphQL Playground - never use this option in production', + action: parsers.booleanParser, + default: false + }, + objectIdSize: { + env: 'PARSE_SERVER_OBJECT_ID_SIZE', + help: "Sets the number of characters in generated object id's, default 10", + action: parsers.numberParser('objectIdSize'), + default: 10 + }, + passwordPolicy: { + env: 'PARSE_SERVER_PASSWORD_POLICY', + help: 'Password policy for enforcing password related rules', + action: parsers.objectParser + }, + playgroundPath: { + env: 'PARSE_SERVER_PLAYGROUND_PATH', + help: 'Mount path for the GraphQL Playground, defaults to /playground', + default: '/playground' + }, + port: { + env: 'PORT', + help: 'The port to run the ParseServer, defaults to 1337.', + action: parsers.numberParser('port'), + default: 1337 + }, + preserveFileName: { + env: 'PARSE_SERVER_PRESERVE_FILE_NAME', + help: 'Enable (or disable) the addition of a unique hash to the file names', + action: parsers.booleanParser, + default: false + }, + preventLoginWithUnverifiedEmail: { + env: 'PARSE_SERVER_PREVENT_LOGIN_WITH_UNVERIFIED_EMAIL', + help: 'Prevent user from login if email is not verified and PARSE_SERVER_VERIFY_USER_EMAILS is true, defaults to false', + action: parsers.booleanParser, + default: false + }, + protectedFields: { + env: 'PARSE_SERVER_PROTECTED_FIELDS', + help: 'Protected fields that should be treated with extra security when fetching details.', + action: parsers.objectParser, + default: { + _User: { + '*': ['email'] + } + } + }, + publicServerURL: { + env: 'PARSE_PUBLIC_SERVER_URL', + help: 'Public URL to your parse server with http:// or https://.' + }, + push: { + env: 'PARSE_SERVER_PUSH', + help: 'Configuration for push, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#push-notifications', + action: parsers.objectParser + }, + readOnlyMasterKey: { + env: 'PARSE_SERVER_READ_ONLY_MASTER_KEY', + help: 'Read-only key, which has the same capabilities as MasterKey without writes' + }, + restAPIKey: { + env: 'PARSE_SERVER_REST_API_KEY', + help: 'Key for REST calls' + }, + revokeSessionOnPasswordReset: { + env: 'PARSE_SERVER_REVOKE_SESSION_ON_PASSWORD_RESET', + help: "When a user changes their password, either through the reset password email or while logged in, all sessions are revoked if this is true. Set to false if you don't want to revoke sessions.", + action: parsers.booleanParser, + default: true + }, + scheduledPush: { + env: 'PARSE_SERVER_SCHEDULED_PUSH', + help: 'Configuration for push scheduling, defaults to false.', + action: parsers.booleanParser, + default: false + }, + schemaCacheTTL: { + env: 'PARSE_SERVER_SCHEMA_CACHE_TTL', + help: 'The TTL for caching the schema for optimizing read/write operations. You should put a long TTL when your DB is in production. default to 5000; set 0 to disable.', + action: parsers.numberParser('schemaCacheTTL'), + default: 5000 + }, + serverCloseComplete: { + env: 'PARSE_SERVER_SERVER_CLOSE_COMPLETE', + help: 'Callback when server has closed' + }, + serverStartComplete: { + env: 'PARSE_SERVER_SERVER_START_COMPLETE', + help: 'Callback when server has started' + }, + serverURL: { + env: 'PARSE_SERVER_URL', + help: 'URL to your parse server with http:// or https://.', + required: true + }, + sessionLength: { + env: 'PARSE_SERVER_SESSION_LENGTH', + help: 'Session duration, in seconds, defaults to 1 year', + action: parsers.numberParser('sessionLength'), + default: 31536000 + }, + silent: { + env: 'SILENT', + help: 'Disables console output', + action: parsers.booleanParser + }, + skipMongoDBServer13732Workaround: { + env: 'PARSE_SKIP_MONGODB_SERVER_13732_WORKAROUND', + help: 'Circumvent Parse workaround for historical MongoDB bug SERVER-13732', + action: parsers.booleanParser, + default: false + }, + startLiveQueryServer: { + env: 'PARSE_SERVER_START_LIVE_QUERY_SERVER', + help: 'Starts the liveQuery server', + action: parsers.booleanParser + }, + userSensitiveFields: { + env: 'PARSE_SERVER_USER_SENSITIVE_FIELDS', + help: 'Personally identifiable information fields in the user table the should be removed for non-authorized users. Deprecated @see protectedFields', + action: parsers.arrayParser + }, + verbose: { + env: 'VERBOSE', + help: 'Set the logging to verbose', + action: parsers.booleanParser + }, + verifyUserEmails: { + env: 'PARSE_SERVER_VERIFY_USER_EMAILS', + help: 'Enable (or disable) user email validation, defaults to false', + action: parsers.booleanParser, + default: false + }, + webhookKey: { + env: 'PARSE_SERVER_WEBHOOK_KEY', + help: 'Key sent with outgoing webhook calls' + } +}; +module.exports.CustomPagesOptions = { + choosePassword: { + env: 'PARSE_SERVER_CUSTOM_PAGES_CHOOSE_PASSWORD', + help: 'choose password page path' + }, + invalidLink: { + env: 'PARSE_SERVER_CUSTOM_PAGES_INVALID_LINK', + help: 'invalid link page path' + }, + invalidVerificationLink: { + env: 'PARSE_SERVER_CUSTOM_PAGES_INVALID_VERIFICATION_LINK', + help: 'invalid verification link page path' + }, + linkSendFail: { + env: 'PARSE_SERVER_CUSTOM_PAGES_LINK_SEND_FAIL', + help: 'verification link send fail page path' + }, + linkSendSuccess: { + env: 'PARSE_SERVER_CUSTOM_PAGES_LINK_SEND_SUCCESS', + help: 'verification link send success page path' + }, + parseFrameURL: { + env: 'PARSE_SERVER_CUSTOM_PAGES_PARSE_FRAME_URL', + help: 'for masking user-facing pages' + }, + passwordResetSuccess: { + env: 'PARSE_SERVER_CUSTOM_PAGES_PASSWORD_RESET_SUCCESS', + help: 'password reset success page path' + }, + verifyEmailSuccess: { + env: 'PARSE_SERVER_CUSTOM_PAGES_VERIFY_EMAIL_SUCCESS', + help: 'verify email success page path' + } +}; +module.exports.LiveQueryOptions = { + classNames: { + env: 'PARSE_SERVER_LIVEQUERY_CLASSNAMES', + help: "parse-server's LiveQuery classNames", + action: parsers.arrayParser + }, + pubSubAdapter: { + env: 'PARSE_SERVER_LIVEQUERY_PUB_SUB_ADAPTER', + help: 'LiveQuery pubsub adapter', + action: parsers.moduleOrObjectParser + }, + redisOptions: { + env: 'PARSE_SERVER_LIVEQUERY_REDIS_OPTIONS', + help: "parse-server's LiveQuery redisOptions", + action: parsers.objectParser + }, + redisURL: { + env: 'PARSE_SERVER_LIVEQUERY_REDIS_URL', + help: "parse-server's LiveQuery redisURL" + }, + wssAdapter: { + env: 'PARSE_SERVER_LIVEQUERY_WSS_ADAPTER', + help: 'Adapter module for the WebSocketServer', + action: parsers.moduleOrObjectParser + } +}; +module.exports.LiveQueryServerOptions = { + appId: { + env: 'PARSE_LIVE_QUERY_SERVER_APP_ID', + help: 'This string should match the appId in use by your Parse Server. If you deploy the LiveQuery server alongside Parse Server, the LiveQuery server will try to use the same appId.' + }, + cacheTimeout: { + env: 'PARSE_LIVE_QUERY_SERVER_CACHE_TIMEOUT', + help: "Number in milliseconds. When clients provide the sessionToken to the LiveQuery server, the LiveQuery server will try to fetch its ParseUser's objectId from parse server and store it in the cache. The value defines the duration of the cache. Check the following Security section and our protocol specification for details, defaults to 30 * 24 * 60 * 60 * 1000 ms (~30 days).", + action: parsers.numberParser('cacheTimeout') + }, + keyPairs: { + env: 'PARSE_LIVE_QUERY_SERVER_KEY_PAIRS', + help: 'A JSON object that serves as a whitelist of keys. It is used for validating clients when they try to connect to the LiveQuery server. Check the following Security section and our protocol specification for details.', + action: parsers.objectParser + }, + logLevel: { + env: 'PARSE_LIVE_QUERY_SERVER_LOG_LEVEL', + help: 'This string defines the log level of the LiveQuery server. We support VERBOSE, INFO, ERROR, NONE, defaults to INFO.' + }, + masterKey: { + env: 'PARSE_LIVE_QUERY_SERVER_MASTER_KEY', + help: 'This string should match the masterKey in use by your Parse Server. If you deploy the LiveQuery server alongside Parse Server, the LiveQuery server will try to use the same masterKey.' + }, + port: { + env: 'PARSE_LIVE_QUERY_SERVER_PORT', + help: 'The port to run the LiveQuery server, defaults to 1337.', + action: parsers.numberParser('port'), + default: 1337 + }, + pubSubAdapter: { + env: 'PARSE_LIVE_QUERY_SERVER_PUB_SUB_ADAPTER', + help: 'LiveQuery pubsub adapter', + action: parsers.moduleOrObjectParser + }, + redisOptions: { + env: 'PARSE_LIVE_QUERY_SERVER_REDIS_OPTIONS', + help: "parse-server's LiveQuery redisOptions", + action: parsers.objectParser + }, + redisURL: { + env: 'PARSE_LIVE_QUERY_SERVER_REDIS_URL', + help: "parse-server's LiveQuery redisURL" + }, + serverURL: { + env: 'PARSE_LIVE_QUERY_SERVER_SERVER_URL', + help: 'This string should match the serverURL in use by your Parse Server. If you deploy the LiveQuery server alongside Parse Server, the LiveQuery server will try to use the same serverURL.' + }, + websocketTimeout: { + env: 'PARSE_LIVE_QUERY_SERVER_WEBSOCKET_TIMEOUT', + help: 'Number of milliseconds between ping/pong frames. The WebSocket server sends ping/pong frames to the clients to keep the WebSocket alive. This value defines the interval of the ping/pong frame from the server to clients, defaults to 10 * 1000 ms (10 s).', + action: parsers.numberParser('websocketTimeout') + }, + wssAdapter: { + env: 'PARSE_LIVE_QUERY_SERVER_WSS_ADAPTER', + help: 'Adapter module for the WebSocketServer', + action: parsers.moduleOrObjectParser + } +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL0RlZmluaXRpb25zLmpzIl0sIm5hbWVzIjpbInBhcnNlcnMiLCJyZXF1aXJlIiwibW9kdWxlIiwiZXhwb3J0cyIsIlBhcnNlU2VydmVyT3B0aW9ucyIsImFjY291bnRMb2Nrb3V0IiwiZW52IiwiaGVscCIsImFjdGlvbiIsIm9iamVjdFBhcnNlciIsImFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiIsImJvb2xlYW5QYXJzZXIiLCJkZWZhdWx0IiwiYWxsb3dIZWFkZXJzIiwiYXJyYXlQYXJzZXIiLCJhbmFseXRpY3NBZGFwdGVyIiwibW9kdWxlT3JPYmplY3RQYXJzZXIiLCJhcHBJZCIsInJlcXVpcmVkIiwiYXBwTmFtZSIsImF1dGgiLCJjYWNoZUFkYXB0ZXIiLCJjYWNoZU1heFNpemUiLCJudW1iZXJQYXJzZXIiLCJjYWNoZVRUTCIsImNsaWVudEtleSIsImNsb3VkIiwiY2x1c3RlciIsIm51bWJlck9yQm9vbGVhblBhcnNlciIsImNvbGxlY3Rpb25QcmVmaXgiLCJjdXN0b21QYWdlcyIsImRhdGFiYXNlQWRhcHRlciIsImRhdGFiYXNlT3B0aW9ucyIsImRhdGFiYXNlVVJJIiwiZGlyZWN0QWNjZXNzIiwiZG90TmV0S2V5IiwiZW1haWxBZGFwdGVyIiwiZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJlbmFibGVBbm9ueW1vdXNVc2VycyIsImVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXIiLCJlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSIsImV4cGlyZUluYWN0aXZlU2Vzc2lvbnMiLCJmaWxlS2V5IiwiZmlsZXNBZGFwdGVyIiwiZ3JhcGhRTFBhdGgiLCJncmFwaFFMU2NoZW1hIiwiaG9zdCIsImphdmFzY3JpcHRLZXkiLCJqc29uTG9ncyIsImxpdmVRdWVyeSIsImxpdmVRdWVyeVNlcnZlck9wdGlvbnMiLCJsb2dnZXJBZGFwdGVyIiwibG9nTGV2ZWwiLCJsb2dzRm9sZGVyIiwibWFzdGVyS2V5IiwibWFzdGVyS2V5SXBzIiwibWF4TGltaXQiLCJtYXhVcGxvYWRTaXplIiwibWlkZGxld2FyZSIsIm1vdW50R3JhcGhRTCIsIm1vdW50UGF0aCIsIm1vdW50UGxheWdyb3VuZCIsIm9iamVjdElkU2l6ZSIsInBhc3N3b3JkUG9saWN5IiwicGxheWdyb3VuZFBhdGgiLCJwb3J0IiwicHJlc2VydmVGaWxlTmFtZSIsInByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWwiLCJwcm90ZWN0ZWRGaWVsZHMiLCJfVXNlciIsInB1YmxpY1NlcnZlclVSTCIsInB1c2giLCJyZWFkT25seU1hc3RlcktleSIsInJlc3RBUElLZXkiLCJyZXZva2VTZXNzaW9uT25QYXNzd29yZFJlc2V0Iiwic2NoZWR1bGVkUHVzaCIsInNjaGVtYUNhY2hlVFRMIiwic2VydmVyQ2xvc2VDb21wbGV0ZSIsInNlcnZlclN0YXJ0Q29tcGxldGUiLCJzZXJ2ZXJVUkwiLCJzZXNzaW9uTGVuZ3RoIiwic2lsZW50Iiwic2tpcE1vbmdvREJTZXJ2ZXIxMzczMldvcmthcm91bmQiLCJzdGFydExpdmVRdWVyeVNlcnZlciIsInVzZXJTZW5zaXRpdmVGaWVsZHMiLCJ2ZXJib3NlIiwidmVyaWZ5VXNlckVtYWlscyIsIndlYmhvb2tLZXkiLCJDdXN0b21QYWdlc09wdGlvbnMiLCJjaG9vc2VQYXNzd29yZCIsImludmFsaWRMaW5rIiwiaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsiLCJsaW5rU2VuZEZhaWwiLCJsaW5rU2VuZFN1Y2Nlc3MiLCJwYXJzZUZyYW1lVVJMIiwicGFzc3dvcmRSZXNldFN1Y2Nlc3MiLCJ2ZXJpZnlFbWFpbFN1Y2Nlc3MiLCJMaXZlUXVlcnlPcHRpb25zIiwiY2xhc3NOYW1lcyIsInB1YlN1YkFkYXB0ZXIiLCJyZWRpc09wdGlvbnMiLCJyZWRpc1VSTCIsIndzc0FkYXB0ZXIiLCJMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIiwiY2FjaGVUaW1lb3V0Iiwia2V5UGFpcnMiLCJ3ZWJzb2NrZXRUaW1lb3V0Il0sIm1hcHBpbmdzIjoiOztBQUFB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RUFBRSx1Q0FETztBQUVaQyxJQUFBQSxJQUFJLEVBQUUsdUNBRk07QUFHWkMsSUFBQUEsTUFBTSxFQUFFUixPQUFPLENBQUNTO0FBSEosR0F2Q3dCO0FBNEN0QzRGLEVBQUFBLFFBQVEsRUFBRTtBQUNSL0YsSUFBQUEsR0FBRyxFQUFFLG1DQURHO0FBRVJDLElBQUFBLElBQUksRUFBRTtBQUZFLEdBNUM0QjtBQWdEdEN3RSxFQUFBQSxTQUFTLEVBQUU7QUFDVHpFLElBQUFBLEdBQUcsRUFBRSxvQ0FESTtBQUVUQyxJQUFBQSxJQUFJLEVBQ0Y7QUFITyxHQWhEMkI7QUFxRHRDbUcsRUFBQUEsZ0JBQWdCLEVBQUU7QUFDaEJwRyxJQUFBQSxHQUFHLEVBQUUsMkNBRFc7QUFFaEJDLElBQUFBLElBQUksRUFDRiw4UEFIYztBQUloQkMsSUFBQUEsTUFBTSxFQUFFUixPQUFPLENBQUN1QixZQUFSLENBQXFCLGtCQUFyQjtBQUpRLEdBckRvQjtBQTJEdEMrRSxFQUFBQSxVQUFVLEVBQUU7QUFDVmhHLElBQUFBLEdBQUcsRUFBRSxxQ0FESztBQUVWQyxJQUFBQSxJQUFJLEVBQUUsd0NBRkk7QUFHVkMsSUFBQUEsTUFBTSxFQUFFUixPQUFPLENBQUNnQjtBQUhOO0FBM0QwQixDQUF4QyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4qKioqIEdFTkVSQVRFRCBDT0RFICoqKipcblRoaXMgY29kZSBoYXMgYmVlbiBnZW5lcmF0ZWQgYnkgcmVzb3VyY2VzL2J1aWxkQ29uZmlnRGVmaW5pdGlvbnMuanNcbkRvIG5vdCBlZGl0IG1hbnVhbGx5LCBidXQgdXBkYXRlIE9wdGlvbnMvaW5kZXguanNcbiovXG52YXIgcGFyc2VycyA9IHJlcXVpcmUoJy4vcGFyc2VycycpO1xuXG5tb2R1bGUuZXhwb3J0cy5QYXJzZVNlcnZlck9wdGlvbnMgPSB7XG4gIGFjY291bnRMb2Nrb3V0OiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0FDQ09VTlRfTE9DS09VVCcsXG4gICAgaGVscDogJ2FjY291bnQgbG9ja291dCBwb2xpY3kgZm9yIGZhaWxlZCBsb2dpbiBhdHRlbXB0cycsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm9iamVjdFBhcnNlcixcbiAgfSxcbiAgYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0FMTE9XX0NMSUVOVF9DTEFTU19DUkVBVElPTicsXG4gICAgaGVscDogJ0VuYWJsZSAob3IgZGlzYWJsZSkgY2xpZW50IGNsYXNzIGNyZWF0aW9uLCBkZWZhdWx0cyB0byB0cnVlJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiB0cnVlLFxuICB9LFxuICBhbGxvd0hlYWRlcnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQUxMT1dfSEVBREVSUycsXG4gICAgaGVscDogJ0FkZCBoZWFkZXJzIHRvIEFjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5hcnJheVBhcnNlcixcbiAgfSxcbiAgYW5hbHl0aWNzQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9BTkFMWVRJQ1NfQURBUFRFUicsXG4gICAgaGVscDogJ0FkYXB0ZXIgbW9kdWxlIGZvciB0aGUgYW5hbHl0aWNzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIGFwcElkOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0FQUExJQ0FUSU9OX0lEJyxcbiAgICBoZWxwOiAnWW91ciBQYXJzZSBBcHBsaWNhdGlvbiBJRCcsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0sXG4gIGFwcE5hbWU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQVBQX05BTUUnLFxuICAgIGhlbHA6ICdTZXRzIHRoZSBhcHAgbmFtZScsXG4gIH0sXG4gIGF1dGg6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQVVUSF9QUk9WSURFUlMnLFxuICAgIGhlbHA6XG4gICAgICAnQ29uZmlndXJhdGlvbiBmb3IgeW91ciBhdXRoZW50aWNhdGlvbiBwcm92aWRlcnMsIGFzIHN0cmluZ2lmaWVkIEpTT04uIFNlZSBodHRwOi8vZG9jcy5wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvZ3VpZGUvI29hdXRoLWFuZC0zcmQtcGFydHktYXV0aGVudGljYXRpb24nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGNhY2hlQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DQUNIRV9BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBjYWNoZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICB9LFxuICBjYWNoZU1heFNpemU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ0FDSEVfTUFYX1NJWkUnLFxuICAgIGhlbHA6ICdTZXRzIHRoZSBtYXhpbXVtIHNpemUgZm9yIHRoZSBpbiBtZW1vcnkgY2FjaGUsIGRlZmF1bHRzIHRvIDEwMDAwJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubnVtYmVyUGFyc2VyKCdjYWNoZU1heFNpemUnKSxcbiAgICBkZWZhdWx0OiAxMDAwMCxcbiAgfSxcbiAgY2FjaGVUVEw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ0FDSEVfVFRMJyxcbiAgICBoZWxwOlxuICAgICAgJ1NldHMgdGhlIFRUTCBmb3IgdGhlIGluIG1lbW9yeSBjYWNoZSAoaW4gbXMpLCBkZWZhdWx0cyB0byA1MDAwICg1IHNlY29uZHMpJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubnVtYmVyUGFyc2VyKCdjYWNoZVRUTCcpLFxuICAgIGRlZmF1bHQ6IDUwMDAsXG4gIH0sXG4gIGNsaWVudEtleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DTElFTlRfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciBpT1MsIE1hY09TLCB0dk9TIGNsaWVudHMnLFxuICB9LFxuICBjbG91ZDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DTE9VRCcsXG4gICAgaGVscDogJ0Z1bGwgcGF0aCB0byB5b3VyIGNsb3VkIGNvZGUgbWFpbi5qcycsXG4gIH0sXG4gIGNsdXN0ZXI6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ0xVU1RFUicsXG4gICAgaGVscDpcbiAgICAgICdSdW4gd2l0aCBjbHVzdGVyLCBvcHRpb25hbGx5IHNldCB0aGUgbnVtYmVyIG9mIHByb2Nlc3NlcyBkZWZhdWx0IHRvIG9zLmNwdXMoKS5sZW5ndGgnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJPckJvb2xlYW5QYXJzZXIsXG4gIH0sXG4gIGNvbGxlY3Rpb25QcmVmaXg6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ09MTEVDVElPTl9QUkVGSVgnLFxuICAgIGhlbHA6ICdBIGNvbGxlY3Rpb24gcHJlZml4IGZvciB0aGUgY2xhc3NlcycsXG4gICAgZGVmYXVsdDogJycsXG4gIH0sXG4gIGN1c3RvbVBhZ2VzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFUycsXG4gICAgaGVscDogJ2N1c3RvbSBwYWdlcyBmb3IgcGFzc3dvcmQgdmFsaWRhdGlvbiBhbmQgcmVzZXQnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gICAgZGVmYXVsdDoge30sXG4gIH0sXG4gIGRhdGFiYXNlQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9EQVRBQkFTRV9BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBkYXRhYmFzZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICB9LFxuICBkYXRhYmFzZU9wdGlvbnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfREFUQUJBU0VfT1BUSU9OUycsXG4gICAgaGVscDogJ09wdGlvbnMgdG8gcGFzcyB0byB0aGUgbW9uZ29kYiBjbGllbnQnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGRhdGFiYXNlVVJJOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0RBVEFCQVNFX1VSSScsXG4gICAgaGVscDpcbiAgICAgICdUaGUgZnVsbCBVUkkgdG8geW91ciBkYXRhYmFzZS4gU3VwcG9ydGVkIGRhdGFiYXNlcyBhcmUgbW9uZ29kYiBvciBwb3N0Z3Jlcy4nLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgIGRlZmF1bHQ6ICdtb25nb2RiOi8vbG9jYWxob3N0OjI3MDE3L3BhcnNlJyxcbiAgfSxcbiAgZGlyZWN0QWNjZXNzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0VOQUJMRV9FWFBFUklNRU5UQUxfRElSRUNUX0FDQ0VTUycsXG4gICAgaGVscDpcbiAgICAgICdSZXBsYWNlIEhUVFAgSW50ZXJmYWNlIHdoZW4gdXNpbmcgSlMgU0RLIGluIGN1cnJlbnQgbm9kZSBydW50aW1lLCBkZWZhdWx0cyB0byBmYWxzZS4gQ2F1dGlvbiwgdGhpcyBpcyBhbiBleHBlcmltZW50YWwgZmVhdHVyZSB0aGF0IG1heSBub3QgYmUgYXBwcm9wcmlhdGUgZm9yIHByb2R1Y3Rpb24uJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgZG90TmV0S2V5OiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0RPVF9ORVRfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciBVbml0eSBhbmQgLk5ldCBTREsnLFxuICB9LFxuICBlbWFpbEFkYXB0ZXI6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU1BSUxfQURBUFRFUicsXG4gICAgaGVscDogJ0FkYXB0ZXIgbW9kdWxlIGZvciBlbWFpbCBzZW5kaW5nJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0VNQUlMX1ZFUklGWV9UT0tFTl9WQUxJRElUWV9EVVJBVElPTicsXG4gICAgaGVscDogJ0VtYWlsIHZlcmlmaWNhdGlvbiB0b2tlbiB2YWxpZGl0eSBkdXJhdGlvbiwgaW4gc2Vjb25kcycsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm51bWJlclBhcnNlcignZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24nKSxcbiAgfSxcbiAgZW5hYmxlQW5vbnltb3VzVXNlcnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU5BQkxFX0FOT05fVVNFUlMnLFxuICAgIGhlbHA6ICdFbmFibGUgKG9yIGRpc2FibGUpIGFub24gdXNlcnMsIGRlZmF1bHRzIHRvIHRydWUnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IHRydWUsXG4gIH0sXG4gIGVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXI6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU5BQkxFX0VYUFJFU1NfRVJST1JfSEFORExFUicsXG4gICAgaGVscDogJ0VuYWJsZXMgdGhlIGRlZmF1bHQgZXhwcmVzcyBlcnJvciBoYW5kbGVyIGZvciBhbGwgZXJyb3JzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgZW5hYmxlU2luZ2xlU2NoZW1hQ2FjaGU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU5BQkxFX1NJTkdMRV9TQ0hFTUFfQ0FDSEUnLFxuICAgIGhlbHA6XG4gICAgICAnVXNlIGEgc2luZ2xlIHNjaGVtYSBjYWNoZSBzaGFyZWQgYWNyb3NzIHJlcXVlc3RzLiBSZWR1Y2VzIG51bWJlciBvZiBxdWVyaWVzIG1hZGUgdG8gX1NDSEVNQSwgZGVmYXVsdHMgdG8gZmFsc2UsIGkuZS4gdW5pcXVlIHNjaGVtYSBjYWNoZSBwZXIgcmVxdWVzdC4nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBleHBpcmVJbmFjdGl2ZVNlc3Npb25zOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0VYUElSRV9JTkFDVElWRV9TRVNTSU9OUycsXG4gICAgaGVscDpcbiAgICAgICdTZXRzIHdldGhlciB3ZSBzaG91bGQgZXhwaXJlIHRoZSBpbmFjdGl2ZSBzZXNzaW9ucywgZGVmYXVsdHMgdG8gdHJ1ZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgZmlsZUtleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9GSUxFX0tFWScsXG4gICAgaGVscDogJ0tleSBmb3IgeW91ciBmaWxlcycsXG4gIH0sXG4gIGZpbGVzQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9GSUxFU19BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBmaWxlcyBzdWItc3lzdGVtJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIGdyYXBoUUxQYXRoOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0dSQVBIUUxfUEFUSCcsXG4gICAgaGVscDogJ01vdW50IHBhdGggZm9yIHRoZSBHcmFwaFFMIGVuZHBvaW50LCBkZWZhdWx0cyB0byAvZ3JhcGhxbCcsXG4gICAgZGVmYXVsdDogJy9ncmFwaHFsJyxcbiAgfSxcbiAgZ3JhcGhRTFNjaGVtYToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9HUkFQSF9RTFNDSEVNQScsXG4gICAgaGVscDogJ0Z1bGwgcGF0aCB0byB5b3VyIEdyYXBoUUwgY3VzdG9tIHNjaGVtYS5ncmFwaHFsIGZpbGUnLFxuICB9LFxuICBob3N0OiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0hPU1QnLFxuICAgIGhlbHA6ICdUaGUgaG9zdCB0byBzZXJ2ZSBQYXJzZVNlcnZlciBvbiwgZGVmYXVsdHMgdG8gMC4wLjAuMCcsXG4gICAgZGVmYXVsdDogJzAuMC4wLjAnLFxuICB9LFxuICBqYXZhc2NyaXB0S2V5OiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0pBVkFTQ1JJUFRfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciB0aGUgSmF2YXNjcmlwdCBTREsnLFxuICB9LFxuICBqc29uTG9nczoge1xuICAgIGVudjogJ0pTT05fTE9HUycsXG4gICAgaGVscDogJ0xvZyBhcyBzdHJ1Y3R1cmVkIEpTT04gb2JqZWN0cycsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gIH0sXG4gIGxpdmVRdWVyeToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFX1FVRVJZJyxcbiAgICBoZWxwOiBcInBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSBjb25maWd1cmF0aW9uIG9iamVjdFwiLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGxpdmVRdWVyeVNlcnZlck9wdGlvbnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTElWRV9RVUVSWV9TRVJWRVJfT1BUSU9OUycsXG4gICAgaGVscDpcbiAgICAgICdMaXZlIHF1ZXJ5IHNlcnZlciBjb25maWd1cmF0aW9uIG9wdGlvbnMgKHdpbGwgc3RhcnQgdGhlIGxpdmVRdWVyeSBzZXJ2ZXIpJyxcbiAgICBhY3Rpb246IHBhcnNlcnMub2JqZWN0UGFyc2VyLFxuICB9LFxuICBsb2dnZXJBZGFwdGVyOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0xPR0dFUl9BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBsb2dnaW5nIHN1Yi1zeXN0ZW0nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5tb2R1bGVPck9iamVjdFBhcnNlcixcbiAgfSxcbiAgbG9nTGV2ZWw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTE9HX0xFVkVMJyxcbiAgICBoZWxwOiAnU2V0cyB0aGUgbGV2ZWwgZm9yIGxvZ3MnLFxuICB9LFxuICBsb2dzRm9sZGVyOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0xPR1NfRk9MREVSJyxcbiAgICBoZWxwOlxuICAgICAgXCJGb2xkZXIgZm9yIHRoZSBsb2dzIChkZWZhdWx0cyB0byAnLi9sb2dzJyk7IHNldCB0byBudWxsIHRvIGRpc2FibGUgZmlsZSBiYXNlZCBsb2dnaW5nXCIsXG4gICAgZGVmYXVsdDogJy4vbG9ncycsXG4gIH0sXG4gIG1hc3RlcktleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9NQVNURVJfS0VZJyxcbiAgICBoZWxwOiAnWW91ciBQYXJzZSBNYXN0ZXIgS2V5JyxcbiAgICByZXF1aXJlZDogdHJ1ZSxcbiAgfSxcbiAgbWFzdGVyS2V5SXBzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX01BU1RFUl9LRVlfSVBTJyxcbiAgICBoZWxwOlxuICAgICAgJ1Jlc3RyaWN0IG1hc3RlcktleSB0byBiZSB1c2VkIGJ5IG9ubHkgdGhlc2UgaXBzLCBkZWZhdWx0cyB0byBbXSAoYWxsb3cgYWxsIGlwcyknLFxuICAgIGFjdGlvbjogcGFyc2Vycy5hcnJheVBhcnNlcixcbiAgICBkZWZhdWx0OiBbXSxcbiAgfSxcbiAgbWF4TGltaXQ6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTUFYX0xJTUlUJyxcbiAgICBoZWxwOiAnTWF4IHZhbHVlIGZvciBsaW1pdCBvcHRpb24gb24gcXVlcmllcywgZGVmYXVsdHMgdG8gdW5saW1pdGVkJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubnVtYmVyUGFyc2VyKCdtYXhMaW1pdCcpLFxuICB9LFxuICBtYXhVcGxvYWRTaXplOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX01BWF9VUExPQURfU0laRScsXG4gICAgaGVscDogJ01heCBmaWxlIHNpemUgZm9yIHVwbG9hZHMsIGRlZmF1bHRzIHRvIDIwbWInLFxuICAgIGRlZmF1bHQ6ICcyMG1iJyxcbiAgfSxcbiAgbWlkZGxld2FyZToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9NSURETEVXQVJFJyxcbiAgICBoZWxwOiAnbWlkZGxld2FyZSBmb3IgZXhwcmVzcyBzZXJ2ZXIsIGNhbiBiZSBzdHJpbmcgb3IgZnVuY3Rpb24nLFxuICB9LFxuICBtb3VudEdyYXBoUUw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTU9VTlRfR1JBUEhRTCcsXG4gICAgaGVscDogJ01vdW50cyB0aGUgR3JhcGhRTCBlbmRwb2ludCcsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIG1vdW50UGF0aDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9NT1VOVF9QQVRIJyxcbiAgICBoZWxwOiAnTW91bnQgcGF0aCBmb3IgdGhlIHNlcnZlciwgZGVmYXVsdHMgdG8gL3BhcnNlJyxcbiAgICBkZWZhdWx0OiAnL3BhcnNlJyxcbiAgfSxcbiAgbW91bnRQbGF5Z3JvdW5kOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX01PVU5UX1BMQVlHUk9VTkQnLFxuICAgIGhlbHA6ICdNb3VudHMgdGhlIEdyYXBoUUwgUGxheWdyb3VuZCAtIG5ldmVyIHVzZSB0aGlzIG9wdGlvbiBpbiBwcm9kdWN0aW9uJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgb2JqZWN0SWRTaXplOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX09CSkVDVF9JRF9TSVpFJyxcbiAgICBoZWxwOiBcIlNldHMgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzIGluIGdlbmVyYXRlZCBvYmplY3QgaWQncywgZGVmYXVsdCAxMFwiLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJQYXJzZXIoJ29iamVjdElkU2l6ZScpLFxuICAgIGRlZmF1bHQ6IDEwLFxuICB9LFxuICBwYXNzd29yZFBvbGljeToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9QQVNTV09SRF9QT0xJQ1knLFxuICAgIGhlbHA6ICdQYXNzd29yZCBwb2xpY3kgZm9yIGVuZm9yY2luZyBwYXNzd29yZCByZWxhdGVkIHJ1bGVzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMub2JqZWN0UGFyc2VyLFxuICB9LFxuICBwbGF5Z3JvdW5kUGF0aDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9QTEFZR1JPVU5EX1BBVEgnLFxuICAgIGhlbHA6ICdNb3VudCBwYXRoIGZvciB0aGUgR3JhcGhRTCBQbGF5Z3JvdW5kLCBkZWZhdWx0cyB0byAvcGxheWdyb3VuZCcsXG4gICAgZGVmYXVsdDogJy9wbGF5Z3JvdW5kJyxcbiAgfSxcbiAgcG9ydDoge1xuICAgIGVudjogJ1BPUlQnLFxuICAgIGhlbHA6ICdUaGUgcG9ydCB0byBydW4gdGhlIFBhcnNlU2VydmVyLCBkZWZhdWx0cyB0byAxMzM3LicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm51bWJlclBhcnNlcigncG9ydCcpLFxuICAgIGRlZmF1bHQ6IDEzMzcsXG4gIH0sXG4gIHByZXNlcnZlRmlsZU5hbWU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfUFJFU0VSVkVfRklMRV9OQU1FJyxcbiAgICBoZWxwOiAnRW5hYmxlIChvciBkaXNhYmxlKSB0aGUgYWRkaXRpb24gb2YgYSB1bmlxdWUgaGFzaCB0byB0aGUgZmlsZSBuYW1lcycsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIHByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfUFJFVkVOVF9MT0dJTl9XSVRIX1VOVkVSSUZJRURfRU1BSUwnLFxuICAgIGhlbHA6XG4gICAgICAnUHJldmVudCB1c2VyIGZyb20gbG9naW4gaWYgZW1haWwgaXMgbm90IHZlcmlmaWVkIGFuZCBQQVJTRV9TRVJWRVJfVkVSSUZZX1VTRVJfRU1BSUxTIGlzIHRydWUsIGRlZmF1bHRzIHRvIGZhbHNlJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgcHJvdGVjdGVkRmllbGRzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1BST1RFQ1RFRF9GSUVMRFMnLFxuICAgIGhlbHA6XG4gICAgICAnUHJvdGVjdGVkIGZpZWxkcyB0aGF0IHNob3VsZCBiZSB0cmVhdGVkIHdpdGggZXh0cmEgc2VjdXJpdHkgd2hlbiBmZXRjaGluZyBkZXRhaWxzLicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm9iamVjdFBhcnNlcixcbiAgICBkZWZhdWx0OiB7XG4gICAgICBfVXNlcjoge1xuICAgICAgICAnKic6IFsnZW1haWwnXSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbiAgcHVibGljU2VydmVyVVJMOiB7XG4gICAgZW52OiAnUEFSU0VfUFVCTElDX1NFUlZFUl9VUkwnLFxuICAgIGhlbHA6ICdQdWJsaWMgVVJMIHRvIHlvdXIgcGFyc2Ugc2VydmVyIHdpdGggaHR0cDovLyBvciBodHRwczovLy4nLFxuICB9LFxuICBwdXNoOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1BVU0gnLFxuICAgIGhlbHA6XG4gICAgICAnQ29uZmlndXJhdGlvbiBmb3IgcHVzaCwgYXMgc3RyaW5naWZpZWQgSlNPTi4gU2VlIGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8jcHVzaC1ub3RpZmljYXRpb25zJyxcbiAgICBhY3Rpb246IHBhcnNlcnMub2JqZWN0UGFyc2VyLFxuICB9LFxuICByZWFkT25seU1hc3RlcktleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9SRUFEX09OTFlfTUFTVEVSX0tFWScsXG4gICAgaGVscDpcbiAgICAgICdSZWFkLW9ubHkga2V5LCB3aGljaCBoYXMgdGhlIHNhbWUgY2FwYWJpbGl0aWVzIGFzIE1hc3RlcktleSB3aXRob3V0IHdyaXRlcycsXG4gIH0sXG4gIHJlc3RBUElLZXk6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfUkVTVF9BUElfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciBSRVNUIGNhbGxzJyxcbiAgfSxcbiAgcmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9SRVZPS0VfU0VTU0lPTl9PTl9QQVNTV09SRF9SRVNFVCcsXG4gICAgaGVscDpcbiAgICAgIFwiV2hlbiBhIHVzZXIgY2hhbmdlcyB0aGVpciBwYXNzd29yZCwgZWl0aGVyIHRocm91Z2ggdGhlIHJlc2V0IHBhc3N3b3JkIGVtYWlsIG9yIHdoaWxlIGxvZ2dlZCBpbiwgYWxsIHNlc3Npb25zIGFyZSByZXZva2VkIGlmIHRoaXMgaXMgdHJ1ZS4gU2V0IHRvIGZhbHNlIGlmIHlvdSBkb24ndCB3YW50IHRvIHJldm9rZSBzZXNzaW9ucy5cIixcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiB0cnVlLFxuICB9LFxuICBzY2hlZHVsZWRQdXNoOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1NDSEVEVUxFRF9QVVNIJyxcbiAgICBoZWxwOiAnQ29uZmlndXJhdGlvbiBmb3IgcHVzaCBzY2hlZHVsaW5nLCBkZWZhdWx0cyB0byBmYWxzZS4nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBzY2hlbWFDYWNoZVRUTDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TQ0hFTUFfQ0FDSEVfVFRMJyxcbiAgICBoZWxwOlxuICAgICAgJ1RoZSBUVEwgZm9yIGNhY2hpbmcgdGhlIHNjaGVtYSBmb3Igb3B0aW1pemluZyByZWFkL3dyaXRlIG9wZXJhdGlvbnMuIFlvdSBzaG91bGQgcHV0IGEgbG9uZyBUVEwgd2hlbiB5b3VyIERCIGlzIGluIHByb2R1Y3Rpb24uIGRlZmF1bHQgdG8gNTAwMDsgc2V0IDAgdG8gZGlzYWJsZS4nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJQYXJzZXIoJ3NjaGVtYUNhY2hlVFRMJyksXG4gICAgZGVmYXVsdDogNTAwMCxcbiAgfSxcbiAgc2VydmVyQ2xvc2VDb21wbGV0ZToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TRVJWRVJfQ0xPU0VfQ09NUExFVEUnLFxuICAgIGhlbHA6ICdDYWxsYmFjayB3aGVuIHNlcnZlciBoYXMgY2xvc2VkJyxcbiAgfSxcbiAgc2VydmVyU3RhcnRDb21wbGV0ZToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TRVJWRVJfU1RBUlRfQ09NUExFVEUnLFxuICAgIGhlbHA6ICdDYWxsYmFjayB3aGVuIHNlcnZlciBoYXMgc3RhcnRlZCcsXG4gIH0sXG4gIHNlcnZlclVSTDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9VUkwnLFxuICAgIGhlbHA6ICdVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLicsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0sXG4gIHNlc3Npb25MZW5ndGg6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfU0VTU0lPTl9MRU5HVEgnLFxuICAgIGhlbHA6ICdTZXNzaW9uIGR1cmF0aW9uLCBpbiBzZWNvbmRzLCBkZWZhdWx0cyB0byAxIHllYXInLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJQYXJzZXIoJ3Nlc3Npb25MZW5ndGgnKSxcbiAgICBkZWZhdWx0OiAzMTUzNjAwMCxcbiAgfSxcbiAgc2lsZW50OiB7XG4gICAgZW52OiAnU0lMRU5UJyxcbiAgICBoZWxwOiAnRGlzYWJsZXMgY29uc29sZSBvdXRwdXQnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICB9LFxuICBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZDoge1xuICAgIGVudjogJ1BBUlNFX1NLSVBfTU9OR09EQl9TRVJWRVJfMTM3MzJfV09SS0FST1VORCcsXG4gICAgaGVscDogJ0NpcmN1bXZlbnQgUGFyc2Ugd29ya2Fyb3VuZCBmb3IgaGlzdG9yaWNhbCBNb25nb0RCIGJ1ZyBTRVJWRVItMTM3MzInLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBzdGFydExpdmVRdWVyeVNlcnZlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TVEFSVF9MSVZFX1FVRVJZX1NFUlZFUicsXG4gICAgaGVscDogJ1N0YXJ0cyB0aGUgbGl2ZVF1ZXJ5IHNlcnZlcicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gIH0sXG4gIHVzZXJTZW5zaXRpdmVGaWVsZHM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfVVNFUl9TRU5TSVRJVkVfRklFTERTJyxcbiAgICBoZWxwOlxuICAgICAgJ1BlcnNvbmFsbHkgaWRlbnRpZmlhYmxlIGluZm9ybWF0aW9uIGZpZWxkcyBpbiB0aGUgdXNlciB0YWJsZSB0aGUgc2hvdWxkIGJlIHJlbW92ZWQgZm9yIG5vbi1hdXRob3JpemVkIHVzZXJzLiBEZXByZWNhdGVkIEBzZWUgcHJvdGVjdGVkRmllbGRzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYXJyYXlQYXJzZXIsXG4gIH0sXG4gIHZlcmJvc2U6IHtcbiAgICBlbnY6ICdWRVJCT1NFJyxcbiAgICBoZWxwOiAnU2V0IHRoZSBsb2dnaW5nIHRvIHZlcmJvc2UnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICB9LFxuICB2ZXJpZnlVc2VyRW1haWxzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1ZFUklGWV9VU0VSX0VNQUlMUycsXG4gICAgaGVscDogJ0VuYWJsZSAob3IgZGlzYWJsZSkgdXNlciBlbWFpbCB2YWxpZGF0aW9uLCBkZWZhdWx0cyB0byBmYWxzZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIHdlYmhvb2tLZXk6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfV0VCSE9PS19LRVknLFxuICAgIGhlbHA6ICdLZXkgc2VudCB3aXRoIG91dGdvaW5nIHdlYmhvb2sgY2FsbHMnLFxuICB9LFxufTtcbm1vZHVsZS5leHBvcnRzLkN1c3RvbVBhZ2VzT3B0aW9ucyA9IHtcbiAgY2hvb3NlUGFzc3dvcmQ6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ1VTVE9NX1BBR0VTX0NIT09TRV9QQVNTV09SRCcsXG4gICAgaGVscDogJ2Nob29zZSBwYXNzd29yZCBwYWdlIHBhdGgnLFxuICB9LFxuICBpbnZhbGlkTGluazoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfSU5WQUxJRF9MSU5LJyxcbiAgICBoZWxwOiAnaW52YWxpZCBsaW5rIHBhZ2UgcGF0aCcsXG4gIH0sXG4gIGludmFsaWRWZXJpZmljYXRpb25MaW5rOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFU19JTlZBTElEX1ZFUklGSUNBVElPTl9MSU5LJyxcbiAgICBoZWxwOiAnaW52YWxpZCB2ZXJpZmljYXRpb24gbGluayBwYWdlIHBhdGgnLFxuICB9LFxuICBsaW5rU2VuZEZhaWw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ1VTVE9NX1BBR0VTX0xJTktfU0VORF9GQUlMJyxcbiAgICBoZWxwOiAndmVyaWZpY2F0aW9uIGxpbmsgc2VuZCBmYWlsIHBhZ2UgcGF0aCcsXG4gIH0sXG4gIGxpbmtTZW5kU3VjY2Vzczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfTElOS19TRU5EX1NVQ0NFU1MnLFxuICAgIGhlbHA6ICd2ZXJpZmljYXRpb24gbGluayBzZW5kIHN1Y2Nlc3MgcGFnZSBwYXRoJyxcbiAgfSxcbiAgcGFyc2VGcmFtZVVSTDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfUEFSU0VfRlJBTUVfVVJMJyxcbiAgICBoZWxwOiAnZm9yIG1hc2tpbmcgdXNlci1mYWNpbmcgcGFnZXMnLFxuICB9LFxuICBwYXNzd29yZFJlc2V0U3VjY2Vzczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfUEFTU1dPUkRfUkVTRVRfU1VDQ0VTUycsXG4gICAgaGVscDogJ3Bhc3N3b3JkIHJlc2V0IHN1Y2Nlc3MgcGFnZSBwYXRoJyxcbiAgfSxcbiAgdmVyaWZ5RW1haWxTdWNjZXNzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFU19WRVJJRllfRU1BSUxfU1VDQ0VTUycsXG4gICAgaGVscDogJ3ZlcmlmeSBlbWFpbCBzdWNjZXNzIHBhZ2UgcGF0aCcsXG4gIH0sXG59O1xubW9kdWxlLmV4cG9ydHMuTGl2ZVF1ZXJ5T3B0aW9ucyA9IHtcbiAgY2xhc3NOYW1lczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfQ0xBU1NOQU1FUycsXG4gICAgaGVscDogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY2xhc3NOYW1lc1wiLFxuICAgIGFjdGlvbjogcGFyc2Vycy5hcnJheVBhcnNlcixcbiAgfSxcbiAgcHViU3ViQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfUFVCX1NVQl9BREFQVEVSJyxcbiAgICBoZWxwOiAnTGl2ZVF1ZXJ5IHB1YnN1YiBhZGFwdGVyJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIHJlZGlzT3B0aW9uczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfUkVESVNfT1BUSU9OUycsXG4gICAgaGVscDogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNPcHRpb25zXCIsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm9iamVjdFBhcnNlcixcbiAgfSxcbiAgcmVkaXNVUkw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTElWRVFVRVJZX1JFRElTX1VSTCcsXG4gICAgaGVscDogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNVUkxcIixcbiAgfSxcbiAgd3NzQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfV1NTX0FEQVBURVInLFxuICAgIGhlbHA6ICdBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIFdlYlNvY2tldFNlcnZlcicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICB9LFxufTtcbm1vZHVsZS5leHBvcnRzLkxpdmVRdWVyeVNlcnZlck9wdGlvbnMgPSB7XG4gIGFwcElkOiB7XG4gICAgZW52OiAnUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfQVBQX0lEJyxcbiAgICBoZWxwOlxuICAgICAgJ1RoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgYXBwSWQgaW4gdXNlIGJ5IHlvdXIgUGFyc2UgU2VydmVyLiBJZiB5b3UgZGVwbG95IHRoZSBMaXZlUXVlcnkgc2VydmVyIGFsb25nc2lkZSBQYXJzZSBTZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIHVzZSB0aGUgc2FtZSBhcHBJZC4nLFxuICB9LFxuICBjYWNoZVRpbWVvdXQ6IHtcbiAgICBlbnY6ICdQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9DQUNIRV9USU1FT1VUJyxcbiAgICBoZWxwOlxuICAgICAgXCJOdW1iZXIgaW4gbWlsbGlzZWNvbmRzLiBXaGVuIGNsaWVudHMgcHJvdmlkZSB0aGUgc2Vzc2lvblRva2VuIHRvIHRoZSBMaXZlUXVlcnkgc2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byBmZXRjaCBpdHMgUGFyc2VVc2VyJ3Mgb2JqZWN0SWQgZnJvbSBwYXJzZSBzZXJ2ZXIgYW5kIHN0b3JlIGl0IGluIHRoZSBjYWNoZS4gVGhlIHZhbHVlIGRlZmluZXMgdGhlIGR1cmF0aW9uIG9mIHRoZSBjYWNoZS4gQ2hlY2sgdGhlIGZvbGxvd2luZyBTZWN1cml0eSBzZWN0aW9uIGFuZCBvdXIgcHJvdG9jb2wgc3BlY2lmaWNhdGlvbiBmb3IgZGV0YWlscywgZGVmYXVsdHMgdG8gMzAgKiAyNCAqIDYwICogNjAgKiAxMDAwIG1zICh+MzAgZGF5cykuXCIsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm51bWJlclBhcnNlcignY2FjaGVUaW1lb3V0JyksXG4gIH0sXG4gIGtleVBhaXJzOiB7XG4gICAgZW52OiAnUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfS0VZX1BBSVJTJyxcbiAgICBoZWxwOlxuICAgICAgJ0EgSlNPTiBvYmplY3QgdGhhdCBzZXJ2ZXMgYXMgYSB3aGl0ZWxpc3Qgb2Yga2V5cy4gSXQgaXMgdXNlZCBmb3IgdmFsaWRhdGluZyBjbGllbnRzIHdoZW4gdGhleSB0cnkgdG8gY29ubmVjdCB0byB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gQ2hlY2sgdGhlIGZvbGxvd2luZyBTZWN1cml0eSBzZWN0aW9uIGFuZCBvdXIgcHJvdG9jb2wgc3BlY2lmaWNhdGlvbiBmb3IgZGV0YWlscy4nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGxvZ0xldmVsOiB7XG4gICAgZW52OiAnUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfTE9HX0xFVkVMJyxcbiAgICBoZWxwOlxuICAgICAgJ1RoaXMgc3RyaW5nIGRlZmluZXMgdGhlIGxvZyBsZXZlbCBvZiB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gV2Ugc3VwcG9ydCBWRVJCT1NFLCBJTkZPLCBFUlJPUiwgTk9ORSwgZGVmYXVsdHMgdG8gSU5GTy4nLFxuICB9LFxuICBtYXN0ZXJLZXk6IHtcbiAgICBlbnY6ICdQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9NQVNURVJfS0VZJyxcbiAgICBoZWxwOlxuICAgICAgJ1RoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgbWFzdGVyS2V5IGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgbWFzdGVyS2V5LicsXG4gIH0sXG4gIHBvcnQ6IHtcbiAgICBlbnY6ICdQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9QT1JUJyxcbiAgICBoZWxwOiAnVGhlIHBvcnQgdG8gcnVuIHRoZSBMaXZlUXVlcnkgc2VydmVyLCBkZWZhdWx0cyB0byAxMzM3LicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm51bWJlclBhcnNlcigncG9ydCcpLFxuICAgIGRlZmF1bHQ6IDEzMzcsXG4gIH0sXG4gIHB1YlN1YkFkYXB0ZXI6IHtcbiAgICBlbnY6ICdQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9QVUJfU1VCX0FEQVBURVInLFxuICAgIGhlbHA6ICdMaXZlUXVlcnkgcHVic3ViIGFkYXB0ZXInLFxuICAgIGFjdGlvbjogcGFyc2Vycy5tb2R1bGVPck9iamVjdFBhcnNlcixcbiAgfSxcbiAgcmVkaXNPcHRpb25zOiB7XG4gICAgZW52OiAnUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfUkVESVNfT1BUSU9OUycsXG4gICAgaGVscDogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNPcHRpb25zXCIsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm9iamVjdFBhcnNlcixcbiAgfSxcbiAgcmVkaXNVUkw6IHtcbiAgICBlbnY6ICdQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9SRURJU19VUkwnLFxuICAgIGhlbHA6IFwicGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzVVJMXCIsXG4gIH0sXG4gIHNlcnZlclVSTDoge1xuICAgIGVudjogJ1BBUlNFX0xJVkVfUVVFUllfU0VSVkVSX1NFUlZFUl9VUkwnLFxuICAgIGhlbHA6XG4gICAgICAnVGhpcyBzdHJpbmcgc2hvdWxkIG1hdGNoIHRoZSBzZXJ2ZXJVUkwgaW4gdXNlIGJ5IHlvdXIgUGFyc2UgU2VydmVyLiBJZiB5b3UgZGVwbG95IHRoZSBMaXZlUXVlcnkgc2VydmVyIGFsb25nc2lkZSBQYXJzZSBTZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIHVzZSB0aGUgc2FtZSBzZXJ2ZXJVUkwuJyxcbiAgfSxcbiAgd2Vic29ja2V0VGltZW91dDoge1xuICAgIGVudjogJ1BBUlNFX0xJVkVfUVVFUllfU0VSVkVSX1dFQlNPQ0tFVF9USU1FT1VUJyxcbiAgICBoZWxwOlxuICAgICAgJ051bWJlciBvZiBtaWxsaXNlY29uZHMgYmV0d2VlbiBwaW5nL3BvbmcgZnJhbWVzLiBUaGUgV2ViU29ja2V0IHNlcnZlciBzZW5kcyBwaW5nL3BvbmcgZnJhbWVzIHRvIHRoZSBjbGllbnRzIHRvIGtlZXAgdGhlIFdlYlNvY2tldCBhbGl2ZS4gVGhpcyB2YWx1ZSBkZWZpbmVzIHRoZSBpbnRlcnZhbCBvZiB0aGUgcGluZy9wb25nIGZyYW1lIGZyb20gdGhlIHNlcnZlciB0byBjbGllbnRzLCBkZWZhdWx0cyB0byAxMCAqIDEwMDAgbXMgKDEwIHMpLicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm51bWJlclBhcnNlcignd2Vic29ja2V0VGltZW91dCcpLFxuICB9LFxuICB3c3NBZGFwdGVyOiB7XG4gICAgZW52OiAnUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfV1NTX0FEQVBURVInLFxuICAgIGhlbHA6ICdBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIFdlYlNvY2tldFNlcnZlcicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICB9LFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Options/docs.js b/lib/Options/docs.js new file mode 100644 index 0000000000..807b58a2bf --- /dev/null +++ b/lib/Options/docs.js @@ -0,0 +1,113 @@ +/** + * @interface ParseServerOptions + * @property {Any} accountLockout account lockout policy for failed login attempts + * @property {Boolean} allowClientClassCreation Enable (or disable) client class creation, defaults to true + * @property {String[]} allowHeaders Add headers to Access-Control-Allow-Headers + * @property {Adapter} analyticsAdapter Adapter module for the analytics + * @property {String} appId Your Parse Application ID + * @property {String} appName Sets the app name + * @property {Any} auth Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication + * @property {Adapter} cacheAdapter Adapter module for the cache + * @property {Number} cacheMaxSize Sets the maximum size for the in memory cache, defaults to 10000 + * @property {Number} cacheTTL Sets the TTL for the in memory cache (in ms), defaults to 5000 (5 seconds) + * @property {String} clientKey Key for iOS, MacOS, tvOS clients + * @property {String} cloud Full path to your cloud code main.js + * @property {Number|Boolean} cluster Run with cluster, optionally set the number of processes default to os.cpus().length + * @property {String} collectionPrefix A collection prefix for the classes + * @property {CustomPagesOptions} customPages custom pages for password validation and reset + * @property {Adapter} databaseAdapter Adapter module for the database + * @property {Any} databaseOptions Options to pass to the mongodb client + * @property {String} databaseURI The full URI to your database. Supported databases are mongodb or postgres. + * @property {Boolean} directAccess Replace HTTP Interface when using JS SDK in current node runtime, defaults to false. Caution, this is an experimental feature that may not be appropriate for production. + * @property {String} dotNetKey Key for Unity and .Net SDK + * @property {Adapter} emailAdapter Adapter module for email sending + * @property {Number} emailVerifyTokenValidityDuration Email verification token validity duration, in seconds + * @property {Boolean} enableAnonymousUsers Enable (or disable) anon users, defaults to true + * @property {Boolean} enableExpressErrorHandler Enables the default express error handler for all errors + * @property {Boolean} enableSingleSchemaCache Use a single schema cache shared across requests. Reduces number of queries made to _SCHEMA, defaults to false, i.e. unique schema cache per request. + * @property {Boolean} expireInactiveSessions Sets wether we should expire the inactive sessions, defaults to true + * @property {String} fileKey Key for your files + * @property {Adapter} filesAdapter Adapter module for the files sub-system + * @property {String} graphQLPath Mount path for the GraphQL endpoint, defaults to /graphql + * @property {String} graphQLSchema Full path to your GraphQL custom schema.graphql file + * @property {String} host The host to serve ParseServer on, defaults to 0.0.0.0 + * @property {String} javascriptKey Key for the Javascript SDK + * @property {Boolean} jsonLogs Log as structured JSON objects + * @property {LiveQueryOptions} liveQuery parse-server's LiveQuery configuration object + * @property {LiveQueryServerOptions} liveQueryServerOptions Live query server configuration options (will start the liveQuery server) + * @property {Adapter} loggerAdapter Adapter module for the logging sub-system + * @property {String} logLevel Sets the level for logs + * @property {String} logsFolder Folder for the logs (defaults to './logs'); set to null to disable file based logging + * @property {String} masterKey Your Parse Master Key + * @property {String[]} masterKeyIps Restrict masterKey to be used by only these ips, defaults to [] (allow all ips) + * @property {Number} maxLimit Max value for limit option on queries, defaults to unlimited + * @property {String} maxUploadSize Max file size for uploads, defaults to 20mb + * @property {Union} middleware middleware for express server, can be string or function + * @property {Boolean} mountGraphQL Mounts the GraphQL endpoint + * @property {String} mountPath Mount path for the server, defaults to /parse + * @property {Boolean} mountPlayground Mounts the GraphQL Playground - never use this option in production + * @property {Number} objectIdSize Sets the number of characters in generated object id's, default 10 + * @property {Any} passwordPolicy Password policy for enforcing password related rules + * @property {String} playgroundPath Mount path for the GraphQL Playground, defaults to /playground + * @property {Number} port The port to run the ParseServer, defaults to 1337. + * @property {Boolean} preserveFileName Enable (or disable) the addition of a unique hash to the file names + * @property {Boolean} preventLoginWithUnverifiedEmail Prevent user from login if email is not verified and PARSE_SERVER_VERIFY_USER_EMAILS is true, defaults to false + * @property {ProtectedFields} protectedFields Protected fields that should be treated with extra security when fetching details. + * @property {String} publicServerURL Public URL to your parse server with http:// or https://. + * @property {Any} push Configuration for push, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#push-notifications + * @property {String} readOnlyMasterKey Read-only key, which has the same capabilities as MasterKey without writes + * @property {String} restAPIKey Key for REST calls + * @property {Boolean} revokeSessionOnPasswordReset When a user changes their password, either through the reset password email or while logged in, all sessions are revoked if this is true. Set to false if you don't want to revoke sessions. + * @property {Boolean} scheduledPush Configuration for push scheduling, defaults to false. + * @property {Number} schemaCacheTTL The TTL for caching the schema for optimizing read/write operations. You should put a long TTL when your DB is in production. default to 5000; set 0 to disable. + * @property {Function} serverCloseComplete Callback when server has closed + * @property {Function} serverStartComplete Callback when server has started + * @property {String} serverURL URL to your parse server with http:// or https://. + * @property {Number} sessionLength Session duration, in seconds, defaults to 1 year + * @property {Boolean} silent Disables console output + * @property {Boolean} skipMongoDBServer13732Workaround Circumvent Parse workaround for historical MongoDB bug SERVER-13732 + * @property {Boolean} startLiveQueryServer Starts the liveQuery server + * @property {String[]} userSensitiveFields Personally identifiable information fields in the user table the should be removed for non-authorized users. Deprecated @see protectedFields + * @property {Boolean} verbose Set the logging to verbose + * @property {Boolean} verifyUserEmails Enable (or disable) user email validation, defaults to false + * @property {String} webhookKey Key sent with outgoing webhook calls + */ + +/** + * @interface CustomPagesOptions + * @property {String} choosePassword choose password page path + * @property {String} invalidLink invalid link page path + * @property {String} invalidVerificationLink invalid verification link page path + * @property {String} linkSendFail verification link send fail page path + * @property {String} linkSendSuccess verification link send success page path + * @property {String} parseFrameURL for masking user-facing pages + * @property {String} passwordResetSuccess password reset success page path + * @property {String} verifyEmailSuccess verify email success page path + */ + +/** + * @interface LiveQueryOptions + * @property {String[]} classNames parse-server's LiveQuery classNames + * @property {Adapter} pubSubAdapter LiveQuery pubsub adapter + * @property {Any} redisOptions parse-server's LiveQuery redisOptions + * @property {String} redisURL parse-server's LiveQuery redisURL + * @property {Adapter} wssAdapter Adapter module for the WebSocketServer + */ + +/** + * @interface LiveQueryServerOptions + * @property {String} appId This string should match the appId in use by your Parse Server. If you deploy the LiveQuery server alongside Parse Server, the LiveQuery server will try to use the same appId. + * @property {Number} cacheTimeout Number in milliseconds. When clients provide the sessionToken to the LiveQuery server, the LiveQuery server will try to fetch its ParseUser's objectId from parse server and store it in the cache. The value defines the duration of the cache. Check the following Security section and our protocol specification for details, defaults to 30 * 24 * 60 * 60 * 1000 ms (~30 days). + * @property {Any} keyPairs A JSON object that serves as a whitelist of keys. It is used for validating clients when they try to connect to the LiveQuery server. Check the following Security section and our protocol specification for details. + * @property {String} logLevel This string defines the log level of the LiveQuery server. We support VERBOSE, INFO, ERROR, NONE, defaults to INFO. + * @property {String} masterKey This string should match the masterKey in use by your Parse Server. If you deploy the LiveQuery server alongside Parse Server, the LiveQuery server will try to use the same masterKey. + * @property {Number} port The port to run the LiveQuery server, defaults to 1337. + * @property {Adapter} pubSubAdapter LiveQuery pubsub adapter + * @property {Any} redisOptions parse-server's LiveQuery redisOptions + * @property {String} redisURL parse-server's LiveQuery redisURL + * @property {String} serverURL This string should match the serverURL in use by your Parse Server. If you deploy the LiveQuery server alongside Parse Server, the LiveQuery server will try to use the same serverURL. + * @property {Number} websocketTimeout Number of milliseconds between ping/pong frames. The WebSocket server sends ping/pong frames to the clients to keep the WebSocket alive. This value defines the interval of the ping/pong frame from the server to clients, defaults to 10 * 1000 ms (10 s). + * @property {Adapter} wssAdapter Adapter module for the WebSocketServer + */ +"use strict"; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL2RvY3MuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTJFQTs7Ozs7Ozs7Ozs7O0FBWUE7Ozs7Ozs7OztBQVNBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAaW50ZXJmYWNlIFBhcnNlU2VydmVyT3B0aW9uc1xuICogQHByb3BlcnR5IHtBbnl9IGFjY291bnRMb2Nrb3V0IGFjY291bnQgbG9ja291dCBwb2xpY3kgZm9yIGZhaWxlZCBsb2dpbiBhdHRlbXB0c1xuICogQHByb3BlcnR5IHtCb29sZWFufSBhbGxvd0NsaWVudENsYXNzQ3JlYXRpb24gRW5hYmxlIChvciBkaXNhYmxlKSBjbGllbnQgY2xhc3MgY3JlYXRpb24sIGRlZmF1bHRzIHRvIHRydWVcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nW119IGFsbG93SGVhZGVycyBBZGQgaGVhZGVycyB0byBBY2Nlc3MtQ29udHJvbC1BbGxvdy1IZWFkZXJzXG4gKiBAcHJvcGVydHkge0FkYXB0ZXI8QW5hbHl0aWNzQWRhcHRlcj59IGFuYWx5dGljc0FkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBhbmFseXRpY3NcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBhcHBJZCBZb3VyIFBhcnNlIEFwcGxpY2F0aW9uIElEXG4gKiBAcHJvcGVydHkge1N0cmluZ30gYXBwTmFtZSBTZXRzIHRoZSBhcHAgbmFtZVxuICogQHByb3BlcnR5IHtBbnl9IGF1dGggQ29uZmlndXJhdGlvbiBmb3IgeW91ciBhdXRoZW50aWNhdGlvbiBwcm92aWRlcnMsIGFzIHN0cmluZ2lmaWVkIEpTT04uIFNlZSBodHRwOi8vZG9jcy5wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvZ3VpZGUvI29hdXRoLWFuZC0zcmQtcGFydHktYXV0aGVudGljYXRpb25cbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxDYWNoZUFkYXB0ZXI+fSBjYWNoZUFkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBjYWNoZVxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGNhY2hlTWF4U2l6ZSBTZXRzIHRoZSBtYXhpbXVtIHNpemUgZm9yIHRoZSBpbiBtZW1vcnkgY2FjaGUsIGRlZmF1bHRzIHRvIDEwMDAwXG4gKiBAcHJvcGVydHkge051bWJlcn0gY2FjaGVUVEwgU2V0cyB0aGUgVFRMIGZvciB0aGUgaW4gbWVtb3J5IGNhY2hlIChpbiBtcyksIGRlZmF1bHRzIHRvIDUwMDAgKDUgc2Vjb25kcylcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBjbGllbnRLZXkgS2V5IGZvciBpT1MsIE1hY09TLCB0dk9TIGNsaWVudHNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBjbG91ZCBGdWxsIHBhdGggdG8geW91ciBjbG91ZCBjb2RlIG1haW4uanNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfEJvb2xlYW59IGNsdXN0ZXIgUnVuIHdpdGggY2x1c3Rlciwgb3B0aW9uYWxseSBzZXQgdGhlIG51bWJlciBvZiBwcm9jZXNzZXMgZGVmYXVsdCB0byBvcy5jcHVzKCkubGVuZ3RoXG4gKiBAcHJvcGVydHkge1N0cmluZ30gY29sbGVjdGlvblByZWZpeCBBIGNvbGxlY3Rpb24gcHJlZml4IGZvciB0aGUgY2xhc3Nlc1xuICogQHByb3BlcnR5IHtDdXN0b21QYWdlc09wdGlvbnN9IGN1c3RvbVBhZ2VzIGN1c3RvbSBwYWdlcyBmb3IgcGFzc3dvcmQgdmFsaWRhdGlvbiBhbmQgcmVzZXRcbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxTdG9yYWdlQWRhcHRlcj59IGRhdGFiYXNlQWRhcHRlciBBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIGRhdGFiYXNlXG4gKiBAcHJvcGVydHkge0FueX0gZGF0YWJhc2VPcHRpb25zIE9wdGlvbnMgdG8gcGFzcyB0byB0aGUgbW9uZ29kYiBjbGllbnRcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkYXRhYmFzZVVSSSBUaGUgZnVsbCBVUkkgdG8geW91ciBkYXRhYmFzZS4gU3VwcG9ydGVkIGRhdGFiYXNlcyBhcmUgbW9uZ29kYiBvciBwb3N0Z3Jlcy5cbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gZGlyZWN0QWNjZXNzIFJlcGxhY2UgSFRUUCBJbnRlcmZhY2Ugd2hlbiB1c2luZyBKUyBTREsgaW4gY3VycmVudCBub2RlIHJ1bnRpbWUsIGRlZmF1bHRzIHRvIGZhbHNlLiBDYXV0aW9uLCB0aGlzIGlzIGFuIGV4cGVyaW1lbnRhbCBmZWF0dXJlIHRoYXQgbWF5IG5vdCBiZSBhcHByb3ByaWF0ZSBmb3IgcHJvZHVjdGlvbi5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkb3ROZXRLZXkgS2V5IGZvciBVbml0eSBhbmQgLk5ldCBTREtcbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxNYWlsQWRhcHRlcj59IGVtYWlsQWRhcHRlciBBZGFwdGVyIG1vZHVsZSBmb3IgZW1haWwgc2VuZGluZ1xuICogQHByb3BlcnR5IHtOdW1iZXJ9IGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uIEVtYWlsIHZlcmlmaWNhdGlvbiB0b2tlbiB2YWxpZGl0eSBkdXJhdGlvbiwgaW4gc2Vjb25kc1xuICogQHByb3BlcnR5IHtCb29sZWFufSBlbmFibGVBbm9ueW1vdXNVc2VycyBFbmFibGUgKG9yIGRpc2FibGUpIGFub24gdXNlcnMsIGRlZmF1bHRzIHRvIHRydWVcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlciBFbmFibGVzIHRoZSBkZWZhdWx0IGV4cHJlc3MgZXJyb3IgaGFuZGxlciBmb3IgYWxsIGVycm9yc1xuICogQHByb3BlcnR5IHtCb29sZWFufSBlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSBVc2UgYSBzaW5nbGUgc2NoZW1hIGNhY2hlIHNoYXJlZCBhY3Jvc3MgcmVxdWVzdHMuIFJlZHVjZXMgbnVtYmVyIG9mIHF1ZXJpZXMgbWFkZSB0byBfU0NIRU1BLCBkZWZhdWx0cyB0byBmYWxzZSwgaS5lLiB1bmlxdWUgc2NoZW1hIGNhY2hlIHBlciByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtCb29sZWFufSBleHBpcmVJbmFjdGl2ZVNlc3Npb25zIFNldHMgd2V0aGVyIHdlIHNob3VsZCBleHBpcmUgdGhlIGluYWN0aXZlIHNlc3Npb25zLCBkZWZhdWx0cyB0byB0cnVlXG4gKiBAcHJvcGVydHkge1N0cmluZ30gZmlsZUtleSBLZXkgZm9yIHlvdXIgZmlsZXNcbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxGaWxlc0FkYXB0ZXI+fSBmaWxlc0FkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBmaWxlcyBzdWItc3lzdGVtXG4gKiBAcHJvcGVydHkge1N0cmluZ30gZ3JhcGhRTFBhdGggTW91bnQgcGF0aCBmb3IgdGhlIEdyYXBoUUwgZW5kcG9pbnQsIGRlZmF1bHRzIHRvIC9ncmFwaHFsXG4gKiBAcHJvcGVydHkge1N0cmluZ30gZ3JhcGhRTFNjaGVtYSBGdWxsIHBhdGggdG8geW91ciBHcmFwaFFMIGN1c3RvbSBzY2hlbWEuZ3JhcGhxbCBmaWxlXG4gKiBAcHJvcGVydHkge1N0cmluZ30gaG9zdCBUaGUgaG9zdCB0byBzZXJ2ZSBQYXJzZVNlcnZlciBvbiwgZGVmYXVsdHMgdG8gMC4wLjAuMFxuICogQHByb3BlcnR5IHtTdHJpbmd9IGphdmFzY3JpcHRLZXkgS2V5IGZvciB0aGUgSmF2YXNjcmlwdCBTREtcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0ganNvbkxvZ3MgTG9nIGFzIHN0cnVjdHVyZWQgSlNPTiBvYmplY3RzXG4gKiBAcHJvcGVydHkge0xpdmVRdWVyeU9wdGlvbnN9IGxpdmVRdWVyeSBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY29uZmlndXJhdGlvbiBvYmplY3RcbiAqIEBwcm9wZXJ0eSB7TGl2ZVF1ZXJ5U2VydmVyT3B0aW9uc30gbGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyBMaXZlIHF1ZXJ5IHNlcnZlciBjb25maWd1cmF0aW9uIG9wdGlvbnMgKHdpbGwgc3RhcnQgdGhlIGxpdmVRdWVyeSBzZXJ2ZXIpXG4gKiBAcHJvcGVydHkge0FkYXB0ZXI8TG9nZ2VyQWRhcHRlcj59IGxvZ2dlckFkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBsb2dnaW5nIHN1Yi1zeXN0ZW1cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBsb2dMZXZlbCBTZXRzIHRoZSBsZXZlbCBmb3IgbG9nc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IGxvZ3NGb2xkZXIgRm9sZGVyIGZvciB0aGUgbG9ncyAoZGVmYXVsdHMgdG8gJy4vbG9ncycpOyBzZXQgdG8gbnVsbCB0byBkaXNhYmxlIGZpbGUgYmFzZWQgbG9nZ2luZ1xuICogQHByb3BlcnR5IHtTdHJpbmd9IG1hc3RlcktleSBZb3VyIFBhcnNlIE1hc3RlciBLZXlcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nW119IG1hc3RlcktleUlwcyBSZXN0cmljdCBtYXN0ZXJLZXkgdG8gYmUgdXNlZCBieSBvbmx5IHRoZXNlIGlwcywgZGVmYXVsdHMgdG8gW10gKGFsbG93IGFsbCBpcHMpXG4gKiBAcHJvcGVydHkge051bWJlcn0gbWF4TGltaXQgTWF4IHZhbHVlIGZvciBsaW1pdCBvcHRpb24gb24gcXVlcmllcywgZGVmYXVsdHMgdG8gdW5saW1pdGVkXG4gKiBAcHJvcGVydHkge1N0cmluZ30gbWF4VXBsb2FkU2l6ZSBNYXggZmlsZSBzaXplIGZvciB1cGxvYWRzLCBkZWZhdWx0cyB0byAyMG1iXG4gKiBAcHJvcGVydHkge1VuaW9ufSBtaWRkbGV3YXJlIG1pZGRsZXdhcmUgZm9yIGV4cHJlc3Mgc2VydmVyLCBjYW4gYmUgc3RyaW5nIG9yIGZ1bmN0aW9uXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IG1vdW50R3JhcGhRTCBNb3VudHMgdGhlIEdyYXBoUUwgZW5kcG9pbnRcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBtb3VudFBhdGggTW91bnQgcGF0aCBmb3IgdGhlIHNlcnZlciwgZGVmYXVsdHMgdG8gL3BhcnNlXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IG1vdW50UGxheWdyb3VuZCBNb3VudHMgdGhlIEdyYXBoUUwgUGxheWdyb3VuZCAtIG5ldmVyIHVzZSB0aGlzIG9wdGlvbiBpbiBwcm9kdWN0aW9uXG4gKiBAcHJvcGVydHkge051bWJlcn0gb2JqZWN0SWRTaXplIFNldHMgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzIGluIGdlbmVyYXRlZCBvYmplY3QgaWQncywgZGVmYXVsdCAxMFxuICogQHByb3BlcnR5IHtBbnl9IHBhc3N3b3JkUG9saWN5IFBhc3N3b3JkIHBvbGljeSBmb3IgZW5mb3JjaW5nIHBhc3N3b3JkIHJlbGF0ZWQgcnVsZXNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBwbGF5Z3JvdW5kUGF0aCBNb3VudCBwYXRoIGZvciB0aGUgR3JhcGhRTCBQbGF5Z3JvdW5kLCBkZWZhdWx0cyB0byAvcGxheWdyb3VuZFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHBvcnQgVGhlIHBvcnQgdG8gcnVuIHRoZSBQYXJzZVNlcnZlciwgZGVmYXVsdHMgdG8gMTMzNy5cbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gcHJlc2VydmVGaWxlTmFtZSBFbmFibGUgKG9yIGRpc2FibGUpIHRoZSBhZGRpdGlvbiBvZiBhIHVuaXF1ZSBoYXNoIHRvIHRoZSBmaWxlIG5hbWVzXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWwgUHJldmVudCB1c2VyIGZyb20gbG9naW4gaWYgZW1haWwgaXMgbm90IHZlcmlmaWVkIGFuZCBQQVJTRV9TRVJWRVJfVkVSSUZZX1VTRVJfRU1BSUxTIGlzIHRydWUsIGRlZmF1bHRzIHRvIGZhbHNlXG4gKiBAcHJvcGVydHkge1Byb3RlY3RlZEZpZWxkc30gcHJvdGVjdGVkRmllbGRzIFByb3RlY3RlZCBmaWVsZHMgdGhhdCBzaG91bGQgYmUgdHJlYXRlZCB3aXRoIGV4dHJhIHNlY3VyaXR5IHdoZW4gZmV0Y2hpbmcgZGV0YWlscy5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBwdWJsaWNTZXJ2ZXJVUkwgUHVibGljIFVSTCB0byB5b3VyIHBhcnNlIHNlcnZlciB3aXRoIGh0dHA6Ly8gb3IgaHR0cHM6Ly8uXG4gKiBAcHJvcGVydHkge0FueX0gcHVzaCBDb25maWd1cmF0aW9uIGZvciBwdXNoLCBhcyBzdHJpbmdpZmllZCBKU09OLiBTZWUgaHR0cDovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvcGFyc2Utc2VydmVyL2d1aWRlLyNwdXNoLW5vdGlmaWNhdGlvbnNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSByZWFkT25seU1hc3RlcktleSBSZWFkLW9ubHkga2V5LCB3aGljaCBoYXMgdGhlIHNhbWUgY2FwYWJpbGl0aWVzIGFzIE1hc3RlcktleSB3aXRob3V0IHdyaXRlc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IHJlc3RBUElLZXkgS2V5IGZvciBSRVNUIGNhbGxzXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHJldm9rZVNlc3Npb25PblBhc3N3b3JkUmVzZXQgV2hlbiBhIHVzZXIgY2hhbmdlcyB0aGVpciBwYXNzd29yZCwgZWl0aGVyIHRocm91Z2ggdGhlIHJlc2V0IHBhc3N3b3JkIGVtYWlsIG9yIHdoaWxlIGxvZ2dlZCBpbiwgYWxsIHNlc3Npb25zIGFyZSByZXZva2VkIGlmIHRoaXMgaXMgdHJ1ZS4gU2V0IHRvIGZhbHNlIGlmIHlvdSBkb24ndCB3YW50IHRvIHJldm9rZSBzZXNzaW9ucy5cbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gc2NoZWR1bGVkUHVzaCBDb25maWd1cmF0aW9uIGZvciBwdXNoIHNjaGVkdWxpbmcsIGRlZmF1bHRzIHRvIGZhbHNlLlxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHNjaGVtYUNhY2hlVFRMIFRoZSBUVEwgZm9yIGNhY2hpbmcgdGhlIHNjaGVtYSBmb3Igb3B0aW1pemluZyByZWFkL3dyaXRlIG9wZXJhdGlvbnMuIFlvdSBzaG91bGQgcHV0IGEgbG9uZyBUVEwgd2hlbiB5b3VyIERCIGlzIGluIHByb2R1Y3Rpb24uIGRlZmF1bHQgdG8gNTAwMDsgc2V0IDAgdG8gZGlzYWJsZS5cbiAqIEBwcm9wZXJ0eSB7RnVuY3Rpb259IHNlcnZlckNsb3NlQ29tcGxldGUgQ2FsbGJhY2sgd2hlbiBzZXJ2ZXIgaGFzIGNsb3NlZFxuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gc2VydmVyU3RhcnRDb21wbGV0ZSBDYWxsYmFjayB3aGVuIHNlcnZlciBoYXMgc3RhcnRlZFxuICogQHByb3BlcnR5IHtTdHJpbmd9IHNlcnZlclVSTCBVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLlxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHNlc3Npb25MZW5ndGggU2Vzc2lvbiBkdXJhdGlvbiwgaW4gc2Vjb25kcywgZGVmYXVsdHMgdG8gMSB5ZWFyXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHNpbGVudCBEaXNhYmxlcyBjb25zb2xlIG91dHB1dFxuICogQHByb3BlcnR5IHtCb29sZWFufSBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZCBDaXJjdW12ZW50IFBhcnNlIHdvcmthcm91bmQgZm9yIGhpc3RvcmljYWwgTW9uZ29EQiBidWcgU0VSVkVSLTEzNzMyXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHN0YXJ0TGl2ZVF1ZXJ5U2VydmVyIFN0YXJ0cyB0aGUgbGl2ZVF1ZXJ5IHNlcnZlclxuICogQHByb3BlcnR5IHtTdHJpbmdbXX0gdXNlclNlbnNpdGl2ZUZpZWxkcyBQZXJzb25hbGx5IGlkZW50aWZpYWJsZSBpbmZvcm1hdGlvbiBmaWVsZHMgaW4gdGhlIHVzZXIgdGFibGUgdGhlIHNob3VsZCBiZSByZW1vdmVkIGZvciBub24tYXV0aG9yaXplZCB1c2Vycy4gRGVwcmVjYXRlZCBAc2VlIHByb3RlY3RlZEZpZWxkc1xuICogQHByb3BlcnR5IHtCb29sZWFufSB2ZXJib3NlIFNldCB0aGUgbG9nZ2luZyB0byB2ZXJib3NlXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHZlcmlmeVVzZXJFbWFpbHMgRW5hYmxlIChvciBkaXNhYmxlKSB1c2VyIGVtYWlsIHZhbGlkYXRpb24sIGRlZmF1bHRzIHRvIGZhbHNlXG4gKiBAcHJvcGVydHkge1N0cmluZ30gd2ViaG9va0tleSBLZXkgc2VudCB3aXRoIG91dGdvaW5nIHdlYmhvb2sgY2FsbHNcbiAqL1xuXG4vKipcbiAqIEBpbnRlcmZhY2UgQ3VzdG9tUGFnZXNPcHRpb25zXG4gKiBAcHJvcGVydHkge1N0cmluZ30gY2hvb3NlUGFzc3dvcmQgY2hvb3NlIHBhc3N3b3JkIHBhZ2UgcGF0aFxuICogQHByb3BlcnR5IHtTdHJpbmd9IGludmFsaWRMaW5rIGludmFsaWQgbGluayBwYWdlIHBhdGhcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpbnZhbGlkVmVyaWZpY2F0aW9uTGluayBpbnZhbGlkIHZlcmlmaWNhdGlvbiBsaW5rIHBhZ2UgcGF0aFxuICogQHByb3BlcnR5IHtTdHJpbmd9IGxpbmtTZW5kRmFpbCB2ZXJpZmljYXRpb24gbGluayBzZW5kIGZhaWwgcGFnZSBwYXRoXG4gKiBAcHJvcGVydHkge1N0cmluZ30gbGlua1NlbmRTdWNjZXNzIHZlcmlmaWNhdGlvbiBsaW5rIHNlbmQgc3VjY2VzcyBwYWdlIHBhdGhcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBwYXJzZUZyYW1lVVJMIGZvciBtYXNraW5nIHVzZXItZmFjaW5nIHBhZ2VzXG4gKiBAcHJvcGVydHkge1N0cmluZ30gcGFzc3dvcmRSZXNldFN1Y2Nlc3MgcGFzc3dvcmQgcmVzZXQgc3VjY2VzcyBwYWdlIHBhdGhcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSB2ZXJpZnlFbWFpbFN1Y2Nlc3MgdmVyaWZ5IGVtYWlsIHN1Y2Nlc3MgcGFnZSBwYXRoXG4gKi9cblxuLyoqXG4gKiBAaW50ZXJmYWNlIExpdmVRdWVyeU9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nW119IGNsYXNzTmFtZXMgcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IGNsYXNzTmFtZXNcbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxQdWJTdWJBZGFwdGVyPn0gcHViU3ViQWRhcHRlciBMaXZlUXVlcnkgcHVic3ViIGFkYXB0ZXJcbiAqIEBwcm9wZXJ0eSB7QW55fSByZWRpc09wdGlvbnMgcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzT3B0aW9uc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IHJlZGlzVVJMIHBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSByZWRpc1VSTFxuICogQHByb3BlcnR5IHtBZGFwdGVyPFdTU0FkYXB0ZXI+fSB3c3NBZGFwdGVyIEFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgV2ViU29ja2V0U2VydmVyXG4gKi9cblxuLyoqXG4gKiBAaW50ZXJmYWNlIExpdmVRdWVyeVNlcnZlck9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBhcHBJZCBUaGlzIHN0cmluZyBzaG91bGQgbWF0Y2ggdGhlIGFwcElkIGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgYXBwSWQuXG4gKiBAcHJvcGVydHkge051bWJlcn0gY2FjaGVUaW1lb3V0IE51bWJlciBpbiBtaWxsaXNlY29uZHMuIFdoZW4gY2xpZW50cyBwcm92aWRlIHRoZSBzZXNzaW9uVG9rZW4gdG8gdGhlIExpdmVRdWVyeSBzZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIGZldGNoIGl0cyBQYXJzZVVzZXIncyBvYmplY3RJZCBmcm9tIHBhcnNlIHNlcnZlciBhbmQgc3RvcmUgaXQgaW4gdGhlIGNhY2hlLiBUaGUgdmFsdWUgZGVmaW5lcyB0aGUgZHVyYXRpb24gb2YgdGhlIGNhY2hlLiBDaGVjayB0aGUgZm9sbG93aW5nIFNlY3VyaXR5IHNlY3Rpb24gYW5kIG91ciBwcm90b2NvbCBzcGVjaWZpY2F0aW9uIGZvciBkZXRhaWxzLCBkZWZhdWx0cyB0byAzMCAqIDI0ICogNjAgKiA2MCAqIDEwMDAgbXMgKH4zMCBkYXlzKS5cbiAqIEBwcm9wZXJ0eSB7QW55fSBrZXlQYWlycyBBIEpTT04gb2JqZWN0IHRoYXQgc2VydmVzIGFzIGEgd2hpdGVsaXN0IG9mIGtleXMuIEl0IGlzIHVzZWQgZm9yIHZhbGlkYXRpbmcgY2xpZW50cyB3aGVuIHRoZXkgdHJ5IHRvIGNvbm5lY3QgdG8gdGhlIExpdmVRdWVyeSBzZXJ2ZXIuIENoZWNrIHRoZSBmb2xsb3dpbmcgU2VjdXJpdHkgc2VjdGlvbiBhbmQgb3VyIHByb3RvY29sIHNwZWNpZmljYXRpb24gZm9yIGRldGFpbHMuXG4gKiBAcHJvcGVydHkge1N0cmluZ30gbG9nTGV2ZWwgVGhpcyBzdHJpbmcgZGVmaW5lcyB0aGUgbG9nIGxldmVsIG9mIHRoZSBMaXZlUXVlcnkgc2VydmVyLiBXZSBzdXBwb3J0IFZFUkJPU0UsIElORk8sIEVSUk9SLCBOT05FLCBkZWZhdWx0cyB0byBJTkZPLlxuICogQHByb3BlcnR5IHtTdHJpbmd9IG1hc3RlcktleSBUaGlzIHN0cmluZyBzaG91bGQgbWF0Y2ggdGhlIG1hc3RlcktleSBpbiB1c2UgYnkgeW91ciBQYXJzZSBTZXJ2ZXIuIElmIHlvdSBkZXBsb3kgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgYWxvbmdzaWRlIFBhcnNlIFNlcnZlciwgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgd2lsbCB0cnkgdG8gdXNlIHRoZSBzYW1lIG1hc3RlcktleS5cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBwb3J0IFRoZSBwb3J0IHRvIHJ1biB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciwgZGVmYXVsdHMgdG8gMTMzNy5cbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxQdWJTdWJBZGFwdGVyPn0gcHViU3ViQWRhcHRlciBMaXZlUXVlcnkgcHVic3ViIGFkYXB0ZXJcbiAqIEBwcm9wZXJ0eSB7QW55fSByZWRpc09wdGlvbnMgcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzT3B0aW9uc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IHJlZGlzVVJMIHBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSByZWRpc1VSTFxuICogQHByb3BlcnR5IHtTdHJpbmd9IHNlcnZlclVSTCBUaGlzIHN0cmluZyBzaG91bGQgbWF0Y2ggdGhlIHNlcnZlclVSTCBpbiB1c2UgYnkgeW91ciBQYXJzZSBTZXJ2ZXIuIElmIHlvdSBkZXBsb3kgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgYWxvbmdzaWRlIFBhcnNlIFNlcnZlciwgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgd2lsbCB0cnkgdG8gdXNlIHRoZSBzYW1lIHNlcnZlclVSTC5cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB3ZWJzb2NrZXRUaW1lb3V0IE51bWJlciBvZiBtaWxsaXNlY29uZHMgYmV0d2VlbiBwaW5nL3BvbmcgZnJhbWVzLiBUaGUgV2ViU29ja2V0IHNlcnZlciBzZW5kcyBwaW5nL3BvbmcgZnJhbWVzIHRvIHRoZSBjbGllbnRzIHRvIGtlZXAgdGhlIFdlYlNvY2tldCBhbGl2ZS4gVGhpcyB2YWx1ZSBkZWZpbmVzIHRoZSBpbnRlcnZhbCBvZiB0aGUgcGluZy9wb25nIGZyYW1lIGZyb20gdGhlIHNlcnZlciB0byBjbGllbnRzLCBkZWZhdWx0cyB0byAxMCAqIDEwMDAgbXMgKDEwIHMpLlxuICogQHByb3BlcnR5IHtBZGFwdGVyPFdTU0FkYXB0ZXI+fSB3c3NBZGFwdGVyIEFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgV2ViU29ja2V0U2VydmVyXG4gKi9cbiJdfQ== \ No newline at end of file diff --git a/lib/Options/index.js b/lib/Options/index.js new file mode 100644 index 0000000000..bf10f9770f --- /dev/null +++ b/lib/Options/index.js @@ -0,0 +1,18 @@ +"use strict"; + +var _AnalyticsAdapter = require("../Adapters/Analytics/AnalyticsAdapter"); + +var _FilesAdapter = require("../Adapters/Files/FilesAdapter"); + +var _LoggerAdapter = require("../Adapters/Logger/LoggerAdapter"); + +var _StorageAdapter = require("../Adapters/Storage/StorageAdapter"); + +var _CacheAdapter = require("../Adapters/Cache/CacheAdapter"); + +var _MailAdapter = require("../Adapters/Email/MailAdapter"); + +var _PubSubAdapter = require("../Adapters/PubSub/PubSubAdapter"); + +var _WSSAdapter = require("../Adapters/WebSocketServer/WSSAdapter"); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbmFseXRpY3NBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQW5hbHl0aWNzL0FuYWx5dGljc0FkYXB0ZXInO1xuaW1wb3J0IHsgRmlsZXNBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvRmlsZXMvRmlsZXNBZGFwdGVyJztcbmltcG9ydCB7IExvZ2dlckFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9Mb2dnZXIvTG9nZ2VyQWRhcHRlcic7XG5pbXBvcnQgeyBTdG9yYWdlQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL1N0b3JhZ2UvU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHsgQ2FjaGVBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQ2FjaGUvQ2FjaGVBZGFwdGVyJztcbmltcG9ydCB7IE1haWxBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvRW1haWwvTWFpbEFkYXB0ZXInO1xuaW1wb3J0IHsgUHViU3ViQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL1B1YlN1Yi9QdWJTdWJBZGFwdGVyJztcbmltcG9ydCB7IFdTU0FkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9XZWJTb2NrZXRTZXJ2ZXIvV1NTQWRhcHRlcic7XG5cbi8vIEBmbG93XG50eXBlIEFkYXB0ZXI8VD4gPSBzdHJpbmcgfCBhbnkgfCBUO1xudHlwZSBOdW1iZXJPckJvb2xlYW4gPSBudW1iZXIgfCBib29sZWFuO1xudHlwZSBQcm90ZWN0ZWRGaWVsZHMgPSBhbnk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VTZXJ2ZXJPcHRpb25zIHtcbiAgLyogWW91ciBQYXJzZSBBcHBsaWNhdGlvbiBJRFxuICA6RU5WOiBQQVJTRV9TRVJWRVJfQVBQTElDQVRJT05fSUQgKi9cbiAgYXBwSWQ6IHN0cmluZztcbiAgLyogWW91ciBQYXJzZSBNYXN0ZXIgS2V5ICovXG4gIG1hc3RlcktleTogc3RyaW5nO1xuICAvKiBVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLlxuICA6RU5WOiBQQVJTRV9TRVJWRVJfVVJMICovXG4gIHNlcnZlclVSTDogc3RyaW5nO1xuICAvKiBSZXN0cmljdCBtYXN0ZXJLZXkgdG8gYmUgdXNlZCBieSBvbmx5IHRoZXNlIGlwcywgZGVmYXVsdHMgdG8gW10gKGFsbG93IGFsbCBpcHMpXG4gIDpERUZBVUxUOiBbXSAqL1xuICBtYXN0ZXJLZXlJcHM6ID8oc3RyaW5nW10pO1xuICAvKiBTZXRzIHRoZSBhcHAgbmFtZSAqL1xuICBhcHBOYW1lOiA/c3RyaW5nO1xuICAvKiBBZGQgaGVhZGVycyB0byBBY2Nlc3MtQ29udHJvbC1BbGxvdy1IZWFkZXJzICovXG4gIGFsbG93SGVhZGVyczogPyhzdHJpbmdbXSk7XG4gIC8qIEFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgYW5hbHl0aWNzICovXG4gIGFuYWx5dGljc0FkYXB0ZXI6ID9BZGFwdGVyPEFuYWx5dGljc0FkYXB0ZXI+O1xuICAvKiBBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIGZpbGVzIHN1Yi1zeXN0ZW0gKi9cbiAgZmlsZXNBZGFwdGVyOiA/QWRhcHRlcjxGaWxlc0FkYXB0ZXI+O1xuICAvKiBDb25maWd1cmF0aW9uIGZvciBwdXNoLCBhcyBzdHJpbmdpZmllZCBKU09OLiBTZWUgaHR0cDovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvcGFyc2Utc2VydmVyL2d1aWRlLyNwdXNoLW5vdGlmaWNhdGlvbnMgKi9cbiAgcHVzaDogP2FueTtcbiAgLyogQ29uZmlndXJhdGlvbiBmb3IgcHVzaCBzY2hlZHVsaW5nLCBkZWZhdWx0cyB0byBmYWxzZS5cbiAgOkRFRkFVTFQ6IGZhbHNlICovXG4gIHNjaGVkdWxlZFB1c2g6ID9ib29sZWFuO1xuICAvKiBBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIGxvZ2dpbmcgc3ViLXN5c3RlbSAqL1xuICBsb2dnZXJBZGFwdGVyOiA/QWRhcHRlcjxMb2dnZXJBZGFwdGVyPjtcbiAgLyogTG9nIGFzIHN0cnVjdHVyZWQgSlNPTiBvYmplY3RzXG4gIDpFTlY6IEpTT05fTE9HUyAqL1xuICBqc29uTG9nczogP2Jvb2xlYW47XG4gIC8qIEZvbGRlciBmb3IgdGhlIGxvZ3MgKGRlZmF1bHRzIHRvICcuL2xvZ3MnKTsgc2V0IHRvIG51bGwgdG8gZGlzYWJsZSBmaWxlIGJhc2VkIGxvZ2dpbmdcbiAgOkVOVjogUEFSU0VfU0VSVkVSX0xPR1NfRk9MREVSXG4gIDpERUZBVUxUOiAuL2xvZ3MgKi9cbiAgbG9nc0ZvbGRlcjogP3N0cmluZztcbiAgLyogU2V0IHRoZSBsb2dnaW5nIHRvIHZlcmJvc2VcbiAgOkVOVjogVkVSQk9TRSAqL1xuICB2ZXJib3NlOiA/Ym9vbGVhbjtcbiAgLyogU2V0cyB0aGUgbGV2ZWwgZm9yIGxvZ3MgKi9cbiAgbG9nTGV2ZWw6ID9zdHJpbmc7XG4gIC8qIERpc2FibGVzIGNvbnNvbGUgb3V0cHV0XG4gIDpFTlY6IFNJTEVOVCAqL1xuICBzaWxlbnQ6ID9ib29sZWFuO1xuICAvKiBUaGUgZnVsbCBVUkkgdG8geW91ciBkYXRhYmFzZS4gU3VwcG9ydGVkIGRhdGFiYXNlcyBhcmUgbW9uZ29kYiBvciBwb3N0Z3Jlcy5cbiAgOkRFRkFVTFQ6IG1vbmdvZGI6Ly9sb2NhbGhvc3Q6MjcwMTcvcGFyc2UgKi9cbiAgZGF0YWJhc2VVUkk6IHN0cmluZztcbiAgLyogT3B0aW9ucyB0byBwYXNzIHRvIHRoZSBtb25nb2RiIGNsaWVudCAqL1xuICBkYXRhYmFzZU9wdGlvbnM6ID9hbnk7XG4gIC8qIEFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgZGF0YWJhc2UgKi9cbiAgZGF0YWJhc2VBZGFwdGVyOiA/QWRhcHRlcjxTdG9yYWdlQWRhcHRlcj47XG4gIC8qIENpcmN1bXZlbnQgUGFyc2Ugd29ya2Fyb3VuZCBmb3IgaGlzdG9yaWNhbCBNb25nb0RCIGJ1ZyBTRVJWRVItMTM3MzJcbiAgOkVOVjogUEFSU0VfU0tJUF9NT05HT0RCX1NFUlZFUl8xMzczMl9XT1JLQVJPVU5EXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICBza2lwTW9uZ29EQlNlcnZlcjEzNzMyV29ya2Fyb3VuZDogP2Jvb2xlYW47XG4gIC8qIEZ1bGwgcGF0aCB0byB5b3VyIGNsb3VkIGNvZGUgbWFpbi5qcyAqL1xuICBjbG91ZDogP3N0cmluZztcbiAgLyogQSBjb2xsZWN0aW9uIHByZWZpeCBmb3IgdGhlIGNsYXNzZXNcbiAgOkRFRkFVTFQ6ICcnICovXG4gIGNvbGxlY3Rpb25QcmVmaXg6ID9zdHJpbmc7XG4gIC8qIEtleSBmb3IgaU9TLCBNYWNPUywgdHZPUyBjbGllbnRzICovXG4gIGNsaWVudEtleTogP3N0cmluZztcbiAgLyogS2V5IGZvciB0aGUgSmF2YXNjcmlwdCBTREsgKi9cbiAgamF2YXNjcmlwdEtleTogP3N0cmluZztcbiAgLyogS2V5IGZvciBVbml0eSBhbmQgLk5ldCBTREsgKi9cbiAgZG90TmV0S2V5OiA/c3RyaW5nO1xuICAvKiBLZXkgZm9yIFJFU1QgY2FsbHNcbiAgOkVOVjogUEFSU0VfU0VSVkVSX1JFU1RfQVBJX0tFWSAqL1xuICByZXN0QVBJS2V5OiA/c3RyaW5nO1xuICAvKiBSZWFkLW9ubHkga2V5LCB3aGljaCBoYXMgdGhlIHNhbWUgY2FwYWJpbGl0aWVzIGFzIE1hc3RlcktleSB3aXRob3V0IHdyaXRlcyAqL1xuICByZWFkT25seU1hc3RlcktleTogP3N0cmluZztcbiAgLyogS2V5IHNlbnQgd2l0aCBvdXRnb2luZyB3ZWJob29rIGNhbGxzICovXG4gIHdlYmhvb2tLZXk6ID9zdHJpbmc7XG4gIC8qIEtleSBmb3IgeW91ciBmaWxlcyAqL1xuICBmaWxlS2V5OiA/c3RyaW5nO1xuICAvKiBFbmFibGUgKG9yIGRpc2FibGUpIHRoZSBhZGRpdGlvbiBvZiBhIHVuaXF1ZSBoYXNoIHRvIHRoZSBmaWxlIG5hbWVzXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9QUkVTRVJWRV9GSUxFX05BTUVcbiAgOkRFRkFVTFQ6IGZhbHNlICovXG4gIHByZXNlcnZlRmlsZU5hbWU6ID9ib29sZWFuO1xuICAvKiBQZXJzb25hbGx5IGlkZW50aWZpYWJsZSBpbmZvcm1hdGlvbiBmaWVsZHMgaW4gdGhlIHVzZXIgdGFibGUgdGhlIHNob3VsZCBiZSByZW1vdmVkIGZvciBub24tYXV0aG9yaXplZCB1c2Vycy4gRGVwcmVjYXRlZCBAc2VlIHByb3RlY3RlZEZpZWxkcyAqL1xuICB1c2VyU2Vuc2l0aXZlRmllbGRzOiA/KHN0cmluZ1tdKTtcbiAgLyogUHJvdGVjdGVkIGZpZWxkcyB0aGF0IHNob3VsZCBiZSB0cmVhdGVkIHdpdGggZXh0cmEgc2VjdXJpdHkgd2hlbiBmZXRjaGluZyBkZXRhaWxzLlxuICA6REVGQVVMVDoge1wiX1VzZXJcIjoge1wiKlwiOiBbXCJlbWFpbFwiXX19ICovXG4gIHByb3RlY3RlZEZpZWxkczogP1Byb3RlY3RlZEZpZWxkcztcbiAgLyogRW5hYmxlIChvciBkaXNhYmxlKSBhbm9uIHVzZXJzLCBkZWZhdWx0cyB0byB0cnVlXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9FTkFCTEVfQU5PTl9VU0VSU1xuICA6REVGQVVMVDogdHJ1ZSAqL1xuICBlbmFibGVBbm9ueW1vdXNVc2VyczogP2Jvb2xlYW47XG4gIC8qIEVuYWJsZSAob3IgZGlzYWJsZSkgY2xpZW50IGNsYXNzIGNyZWF0aW9uLCBkZWZhdWx0cyB0byB0cnVlXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9BTExPV19DTElFTlRfQ0xBU1NfQ1JFQVRJT05cbiAgOkRFRkFVTFQ6IHRydWUgKi9cbiAgYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uOiA/Ym9vbGVhbjtcbiAgLyogQ29uZmlndXJhdGlvbiBmb3IgeW91ciBhdXRoZW50aWNhdGlvbiBwcm92aWRlcnMsIGFzIHN0cmluZ2lmaWVkIEpTT04uIFNlZSBodHRwOi8vZG9jcy5wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvZ3VpZGUvI29hdXRoLWFuZC0zcmQtcGFydHktYXV0aGVudGljYXRpb25cbiAgOkVOVjogUEFSU0VfU0VSVkVSX0FVVEhfUFJPVklERVJTICovXG4gIGF1dGg6ID9hbnk7XG4gIC8qIE1heCBmaWxlIHNpemUgZm9yIHVwbG9hZHMsIGRlZmF1bHRzIHRvIDIwbWJcbiAgOkRFRkFVTFQ6IDIwbWIgKi9cbiAgbWF4VXBsb2FkU2l6ZTogP3N0cmluZztcbiAgLyogRW5hYmxlIChvciBkaXNhYmxlKSB1c2VyIGVtYWlsIHZhbGlkYXRpb24sIGRlZmF1bHRzIHRvIGZhbHNlXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICB2ZXJpZnlVc2VyRW1haWxzOiA/Ym9vbGVhbjtcbiAgLyogUHJldmVudCB1c2VyIGZyb20gbG9naW4gaWYgZW1haWwgaXMgbm90IHZlcmlmaWVkIGFuZCBQQVJTRV9TRVJWRVJfVkVSSUZZX1VTRVJfRU1BSUxTIGlzIHRydWUsIGRlZmF1bHRzIHRvIGZhbHNlXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICBwcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsOiA/Ym9vbGVhbjtcbiAgLyogRW1haWwgdmVyaWZpY2F0aW9uIHRva2VuIHZhbGlkaXR5IGR1cmF0aW9uLCBpbiBzZWNvbmRzICovXG4gIGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uOiA/bnVtYmVyO1xuICAvKiBhY2NvdW50IGxvY2tvdXQgcG9saWN5IGZvciBmYWlsZWQgbG9naW4gYXR0ZW1wdHMgKi9cbiAgYWNjb3VudExvY2tvdXQ6ID9hbnk7XG4gIC8qIFBhc3N3b3JkIHBvbGljeSBmb3IgZW5mb3JjaW5nIHBhc3N3b3JkIHJlbGF0ZWQgcnVsZXMgKi9cbiAgcGFzc3dvcmRQb2xpY3k6ID9hbnk7XG4gIC8qIEFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgY2FjaGUgKi9cbiAgY2FjaGVBZGFwdGVyOiA/QWRhcHRlcjxDYWNoZUFkYXB0ZXI+O1xuICAvKiBBZGFwdGVyIG1vZHVsZSBmb3IgZW1haWwgc2VuZGluZyAqL1xuICBlbWFpbEFkYXB0ZXI6ID9BZGFwdGVyPE1haWxBZGFwdGVyPjtcbiAgLyogUHVibGljIFVSTCB0byB5b3VyIHBhcnNlIHNlcnZlciB3aXRoIGh0dHA6Ly8gb3IgaHR0cHM6Ly8uXG4gIDpFTlY6IFBBUlNFX1BVQkxJQ19TRVJWRVJfVVJMICovXG4gIHB1YmxpY1NlcnZlclVSTDogP3N0cmluZztcbiAgLyogY3VzdG9tIHBhZ2VzIGZvciBwYXNzd29yZCB2YWxpZGF0aW9uIGFuZCByZXNldFxuICA6REVGQVVMVDoge30gKi9cbiAgY3VzdG9tUGFnZXM6ID9DdXN0b21QYWdlc09wdGlvbnM7XG4gIC8qIHBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSBjb25maWd1cmF0aW9uIG9iamVjdCAqL1xuICBsaXZlUXVlcnk6ID9MaXZlUXVlcnlPcHRpb25zO1xuICAvKiBTZXNzaW9uIGR1cmF0aW9uLCBpbiBzZWNvbmRzLCBkZWZhdWx0cyB0byAxIHllYXJcbiAgOkRFRkFVTFQ6IDMxNTM2MDAwICovXG4gIHNlc3Npb25MZW5ndGg6ID9udW1iZXI7XG4gIC8qIE1heCB2YWx1ZSBmb3IgbGltaXQgb3B0aW9uIG9uIHF1ZXJpZXMsIGRlZmF1bHRzIHRvIHVubGltaXRlZCAqL1xuICBtYXhMaW1pdDogP251bWJlcjtcbiAgLyogU2V0cyB3ZXRoZXIgd2Ugc2hvdWxkIGV4cGlyZSB0aGUgaW5hY3RpdmUgc2Vzc2lvbnMsIGRlZmF1bHRzIHRvIHRydWVcbiAgOkRFRkFVTFQ6IHRydWUgKi9cbiAgZXhwaXJlSW5hY3RpdmVTZXNzaW9uczogP2Jvb2xlYW47XG4gIC8qIFdoZW4gYSB1c2VyIGNoYW5nZXMgdGhlaXIgcGFzc3dvcmQsIGVpdGhlciB0aHJvdWdoIHRoZSByZXNldCBwYXNzd29yZCBlbWFpbCBvciB3aGlsZSBsb2dnZWQgaW4sIGFsbCBzZXNzaW9ucyBhcmUgcmV2b2tlZCBpZiB0aGlzIGlzIHRydWUuIFNldCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0byByZXZva2Ugc2Vzc2lvbnMuXG4gIDpERUZBVUxUOiB0cnVlICovXG4gIHJldm9rZVNlc3Npb25PblBhc3N3b3JkUmVzZXQ6ID9ib29sZWFuO1xuICAvKiBUaGUgVFRMIGZvciBjYWNoaW5nIHRoZSBzY2hlbWEgZm9yIG9wdGltaXppbmcgcmVhZC93cml0ZSBvcGVyYXRpb25zLiBZb3Ugc2hvdWxkIHB1dCBhIGxvbmcgVFRMIHdoZW4geW91ciBEQiBpcyBpbiBwcm9kdWN0aW9uLiBkZWZhdWx0IHRvIDUwMDA7IHNldCAwIHRvIGRpc2FibGUuXG4gIDpERUZBVUxUOiA1MDAwICovXG4gIHNjaGVtYUNhY2hlVFRMOiA/bnVtYmVyO1xuICAvKiBTZXRzIHRoZSBUVEwgZm9yIHRoZSBpbiBtZW1vcnkgY2FjaGUgKGluIG1zKSwgZGVmYXVsdHMgdG8gNTAwMCAoNSBzZWNvbmRzKVxuICA6REVGQVVMVDogNTAwMCAqL1xuICBjYWNoZVRUTDogP251bWJlcjtcbiAgLyogU2V0cyB0aGUgbWF4aW11bSBzaXplIGZvciB0aGUgaW4gbWVtb3J5IGNhY2hlLCBkZWZhdWx0cyB0byAxMDAwMFxuICA6REVGQVVMVDogMTAwMDAgKi9cbiAgY2FjaGVNYXhTaXplOiA/bnVtYmVyO1xuICAvKiBSZXBsYWNlIEhUVFAgSW50ZXJmYWNlIHdoZW4gdXNpbmcgSlMgU0RLIGluIGN1cnJlbnQgbm9kZSBydW50aW1lLCBkZWZhdWx0cyB0byBmYWxzZS4gQ2F1dGlvbiwgdGhpcyBpcyBhbiBleHBlcmltZW50YWwgZmVhdHVyZSB0aGF0IG1heSBub3QgYmUgYXBwcm9wcmlhdGUgZm9yIHByb2R1Y3Rpb24uXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1NcbiAgOkRFRkFVTFQ6IGZhbHNlICovXG4gIGRpcmVjdEFjY2VzczogP2Jvb2xlYW47XG4gIC8qIFVzZSBhIHNpbmdsZSBzY2hlbWEgY2FjaGUgc2hhcmVkIGFjcm9zcyByZXF1ZXN0cy4gUmVkdWNlcyBudW1iZXIgb2YgcXVlcmllcyBtYWRlIHRvIF9TQ0hFTUEsIGRlZmF1bHRzIHRvIGZhbHNlLCBpLmUuIHVuaXF1ZSBzY2hlbWEgY2FjaGUgcGVyIHJlcXVlc3QuXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICBlbmFibGVTaW5nbGVTY2hlbWFDYWNoZTogP2Jvb2xlYW47XG4gIC8qIEVuYWJsZXMgdGhlIGRlZmF1bHQgZXhwcmVzcyBlcnJvciBoYW5kbGVyIGZvciBhbGwgZXJyb3JzXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICBlbmFibGVFeHByZXNzRXJyb3JIYW5kbGVyOiA/Ym9vbGVhbjtcbiAgLyogU2V0cyB0aGUgbnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gZ2VuZXJhdGVkIG9iamVjdCBpZCdzLCBkZWZhdWx0IDEwXG4gIDpERUZBVUxUOiAxMCAqL1xuICBvYmplY3RJZFNpemU6ID9udW1iZXI7XG4gIC8qIFRoZSBwb3J0IHRvIHJ1biB0aGUgUGFyc2VTZXJ2ZXIsIGRlZmF1bHRzIHRvIDEzMzcuXG4gIDpFTlY6IFBPUlRcbiAgOkRFRkFVTFQ6IDEzMzcgKi9cbiAgcG9ydDogP251bWJlcjtcbiAgLyogVGhlIGhvc3QgdG8gc2VydmUgUGFyc2VTZXJ2ZXIgb24sIGRlZmF1bHRzIHRvIDAuMC4wLjBcbiAgOkRFRkFVTFQ6IDAuMC4wLjAgKi9cbiAgaG9zdDogP3N0cmluZztcbiAgLyogTW91bnQgcGF0aCBmb3IgdGhlIHNlcnZlciwgZGVmYXVsdHMgdG8gL3BhcnNlXG4gIDpERUZBVUxUOiAvcGFyc2UgKi9cbiAgbW91bnRQYXRoOiA/c3RyaW5nO1xuICAvKiBSdW4gd2l0aCBjbHVzdGVyLCBvcHRpb25hbGx5IHNldCB0aGUgbnVtYmVyIG9mIHByb2Nlc3NlcyBkZWZhdWx0IHRvIG9zLmNwdXMoKS5sZW5ndGggKi9cbiAgY2x1c3RlcjogP051bWJlck9yQm9vbGVhbjtcbiAgLyogbWlkZGxld2FyZSBmb3IgZXhwcmVzcyBzZXJ2ZXIsIGNhbiBiZSBzdHJpbmcgb3IgZnVuY3Rpb24gKi9cbiAgbWlkZGxld2FyZTogPygoKCkgPT4gdm9pZCkgfCBzdHJpbmcpO1xuICAvKiBTdGFydHMgdGhlIGxpdmVRdWVyeSBzZXJ2ZXIgKi9cbiAgc3RhcnRMaXZlUXVlcnlTZXJ2ZXI6ID9ib29sZWFuO1xuICAvKiBMaXZlIHF1ZXJ5IHNlcnZlciBjb25maWd1cmF0aW9uIG9wdGlvbnMgKHdpbGwgc3RhcnQgdGhlIGxpdmVRdWVyeSBzZXJ2ZXIpICovXG4gIGxpdmVRdWVyeVNlcnZlck9wdGlvbnM6ID9MaXZlUXVlcnlTZXJ2ZXJPcHRpb25zO1xuICAvKiBGdWxsIHBhdGggdG8geW91ciBHcmFwaFFMIGN1c3RvbSBzY2hlbWEuZ3JhcGhxbCBmaWxlICovXG4gIGdyYXBoUUxTY2hlbWE6ID9zdHJpbmc7XG4gIC8qIE1vdW50cyB0aGUgR3JhcGhRTCBlbmRwb2ludFxuICA6RU5WOiBQQVJTRV9TRVJWRVJfTU9VTlRfR1JBUEhRTFxuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgbW91bnRHcmFwaFFMOiA/Ym9vbGVhbjtcbiAgLyogTW91bnQgcGF0aCBmb3IgdGhlIEdyYXBoUUwgZW5kcG9pbnQsIGRlZmF1bHRzIHRvIC9ncmFwaHFsXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9HUkFQSFFMX1BBVEhcbiAgOkRFRkFVTFQ6IC9ncmFwaHFsICovXG4gIGdyYXBoUUxQYXRoOiA/c3RyaW5nO1xuICAvKiBNb3VudHMgdGhlIEdyYXBoUUwgUGxheWdyb3VuZCAtIG5ldmVyIHVzZSB0aGlzIG9wdGlvbiBpbiBwcm9kdWN0aW9uXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9NT1VOVF9QTEFZR1JPVU5EXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICBtb3VudFBsYXlncm91bmQ6ID9ib29sZWFuO1xuICAvKiBNb3VudCBwYXRoIGZvciB0aGUgR3JhcGhRTCBQbGF5Z3JvdW5kLCBkZWZhdWx0cyB0byAvcGxheWdyb3VuZFxuICA6RU5WOiBQQVJTRV9TRVJWRVJfUExBWUdST1VORF9QQVRIXG4gIDpERUZBVUxUOiAvcGxheWdyb3VuZCAqL1xuICBwbGF5Z3JvdW5kUGF0aDogP3N0cmluZztcbiAgLyogQ2FsbGJhY2sgd2hlbiBzZXJ2ZXIgaGFzIHN0YXJ0ZWQgKi9cbiAgc2VydmVyU3RhcnRDb21wbGV0ZTogPyhlcnJvcjogP0Vycm9yKSA9PiB2b2lkO1xuICAvKiBDYWxsYmFjayB3aGVuIHNlcnZlciBoYXMgY2xvc2VkICovXG4gIHNlcnZlckNsb3NlQ29tcGxldGU6ID8oKSA9PiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEN1c3RvbVBhZ2VzT3B0aW9ucyB7XG4gIC8qIGludmFsaWQgbGluayBwYWdlIHBhdGggKi9cbiAgaW52YWxpZExpbms6ID9zdHJpbmc7XG4gIC8qIHZlcmlmeSBlbWFpbCBzdWNjZXNzIHBhZ2UgcGF0aCAqL1xuICB2ZXJpZnlFbWFpbFN1Y2Nlc3M6ID9zdHJpbmc7XG4gIC8qIGludmFsaWQgdmVyaWZpY2F0aW9uIGxpbmsgcGFnZSBwYXRoICovXG4gIGludmFsaWRWZXJpZmljYXRpb25MaW5rOiA/c3RyaW5nO1xuICAvKiB2ZXJpZmljYXRpb24gbGluayBzZW5kIHN1Y2Nlc3MgcGFnZSBwYXRoICovXG4gIGxpbmtTZW5kU3VjY2VzczogP3N0cmluZztcbiAgLyogdmVyaWZpY2F0aW9uIGxpbmsgc2VuZCBmYWlsIHBhZ2UgcGF0aCAqL1xuICBsaW5rU2VuZEZhaWw6ID9zdHJpbmc7XG4gIC8qIGNob29zZSBwYXNzd29yZCBwYWdlIHBhdGggKi9cbiAgY2hvb3NlUGFzc3dvcmQ6ID9zdHJpbmc7XG4gIC8qIHBhc3N3b3JkIHJlc2V0IHN1Y2Nlc3MgcGFnZSBwYXRoICovXG4gIHBhc3N3b3JkUmVzZXRTdWNjZXNzOiA/c3RyaW5nO1xuICAvKiBmb3IgbWFza2luZyB1c2VyLWZhY2luZyBwYWdlcyAqL1xuICBwYXJzZUZyYW1lVVJMOiA/c3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpdmVRdWVyeU9wdGlvbnMge1xuICAvKiBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY2xhc3NOYW1lc1xuICA6RU5WOiBQQVJTRV9TRVJWRVJfTElWRVFVRVJZX0NMQVNTTkFNRVMgKi9cbiAgY2xhc3NOYW1lczogPyhzdHJpbmdbXSk7XG4gIC8qIHBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSByZWRpc09wdGlvbnMgKi9cbiAgcmVkaXNPcHRpb25zOiA/YW55O1xuICAvKiBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNVUkwgKi9cbiAgcmVkaXNVUkw6ID9zdHJpbmc7XG4gIC8qIExpdmVRdWVyeSBwdWJzdWIgYWRhcHRlciAqL1xuICBwdWJTdWJBZGFwdGVyOiA/QWRhcHRlcjxQdWJTdWJBZGFwdGVyPjtcbiAgLyogQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBXZWJTb2NrZXRTZXJ2ZXIgKi9cbiAgd3NzQWRhcHRlcjogP0FkYXB0ZXI8V1NTQWRhcHRlcj47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyB7XG4gIC8qIFRoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgYXBwSWQgaW4gdXNlIGJ5IHlvdXIgUGFyc2UgU2VydmVyLiBJZiB5b3UgZGVwbG95IHRoZSBMaXZlUXVlcnkgc2VydmVyIGFsb25nc2lkZSBQYXJzZSBTZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIHVzZSB0aGUgc2FtZSBhcHBJZC4qL1xuICBhcHBJZDogP3N0cmluZztcbiAgLyogVGhpcyBzdHJpbmcgc2hvdWxkIG1hdGNoIHRoZSBtYXN0ZXJLZXkgaW4gdXNlIGJ5IHlvdXIgUGFyc2UgU2VydmVyLiBJZiB5b3UgZGVwbG95IHRoZSBMaXZlUXVlcnkgc2VydmVyIGFsb25nc2lkZSBQYXJzZSBTZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIHVzZSB0aGUgc2FtZSBtYXN0ZXJLZXkuKi9cbiAgbWFzdGVyS2V5OiA/c3RyaW5nO1xuICAvKiBUaGlzIHN0cmluZyBzaG91bGQgbWF0Y2ggdGhlIHNlcnZlclVSTCBpbiB1c2UgYnkgeW91ciBQYXJzZSBTZXJ2ZXIuIElmIHlvdSBkZXBsb3kgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgYWxvbmdzaWRlIFBhcnNlIFNlcnZlciwgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgd2lsbCB0cnkgdG8gdXNlIHRoZSBzYW1lIHNlcnZlclVSTC4qL1xuICBzZXJ2ZXJVUkw6ID9zdHJpbmc7XG4gIC8qIEEgSlNPTiBvYmplY3QgdGhhdCBzZXJ2ZXMgYXMgYSB3aGl0ZWxpc3Qgb2Yga2V5cy4gSXQgaXMgdXNlZCBmb3IgdmFsaWRhdGluZyBjbGllbnRzIHdoZW4gdGhleSB0cnkgdG8gY29ubmVjdCB0byB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gQ2hlY2sgdGhlIGZvbGxvd2luZyBTZWN1cml0eSBzZWN0aW9uIGFuZCBvdXIgcHJvdG9jb2wgc3BlY2lmaWNhdGlvbiBmb3IgZGV0YWlscy4qL1xuICBrZXlQYWlyczogP2FueTtcbiAgLyogTnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBiZXR3ZWVuIHBpbmcvcG9uZyBmcmFtZXMuIFRoZSBXZWJTb2NrZXQgc2VydmVyIHNlbmRzIHBpbmcvcG9uZyBmcmFtZXMgdG8gdGhlIGNsaWVudHMgdG8ga2VlcCB0aGUgV2ViU29ja2V0IGFsaXZlLiBUaGlzIHZhbHVlIGRlZmluZXMgdGhlIGludGVydmFsIG9mIHRoZSBwaW5nL3BvbmcgZnJhbWUgZnJvbSB0aGUgc2VydmVyIHRvIGNsaWVudHMsIGRlZmF1bHRzIHRvIDEwICogMTAwMCBtcyAoMTAgcykuKi9cbiAgd2Vic29ja2V0VGltZW91dDogP251bWJlcjtcbiAgLyogTnVtYmVyIGluIG1pbGxpc2Vjb25kcy4gV2hlbiBjbGllbnRzIHByb3ZpZGUgdGhlIHNlc3Npb25Ub2tlbiB0byB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciwgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgd2lsbCB0cnkgdG8gZmV0Y2ggaXRzIFBhcnNlVXNlcidzIG9iamVjdElkIGZyb20gcGFyc2Ugc2VydmVyIGFuZCBzdG9yZSBpdCBpbiB0aGUgY2FjaGUuIFRoZSB2YWx1ZSBkZWZpbmVzIHRoZSBkdXJhdGlvbiBvZiB0aGUgY2FjaGUuIENoZWNrIHRoZSBmb2xsb3dpbmcgU2VjdXJpdHkgc2VjdGlvbiBhbmQgb3VyIHByb3RvY29sIHNwZWNpZmljYXRpb24gZm9yIGRldGFpbHMsIGRlZmF1bHRzIHRvIDMwICogMjQgKiA2MCAqIDYwICogMTAwMCBtcyAofjMwIGRheXMpLiovXG4gIGNhY2hlVGltZW91dDogP251bWJlcjtcbiAgLyogVGhpcyBzdHJpbmcgZGVmaW5lcyB0aGUgbG9nIGxldmVsIG9mIHRoZSBMaXZlUXVlcnkgc2VydmVyLiBXZSBzdXBwb3J0IFZFUkJPU0UsIElORk8sIEVSUk9SLCBOT05FLCBkZWZhdWx0cyB0byBJTkZPLiovXG4gIGxvZ0xldmVsOiA/c3RyaW5nO1xuICAvKiBUaGUgcG9ydCB0byBydW4gdGhlIExpdmVRdWVyeSBzZXJ2ZXIsIGRlZmF1bHRzIHRvIDEzMzcuXG4gIDpERUZBVUxUOiAxMzM3ICovXG4gIHBvcnQ6ID9udW1iZXI7XG4gIC8qIHBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSByZWRpc09wdGlvbnMgKi9cbiAgcmVkaXNPcHRpb25zOiA/YW55O1xuICAvKiBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNVUkwgKi9cbiAgcmVkaXNVUkw6ID9zdHJpbmc7XG4gIC8qIExpdmVRdWVyeSBwdWJzdWIgYWRhcHRlciAqL1xuICBwdWJTdWJBZGFwdGVyOiA/QWRhcHRlcjxQdWJTdWJBZGFwdGVyPjtcbiAgLyogQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBXZWJTb2NrZXRTZXJ2ZXIgKi9cbiAgd3NzQWRhcHRlcjogP0FkYXB0ZXI8V1NTQWRhcHRlcj47XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Options/parsers.js b/lib/Options/parsers.js new file mode 100644 index 0000000000..949f1b9ca0 --- /dev/null +++ b/lib/Options/parsers.js @@ -0,0 +1,90 @@ +"use strict"; + +function numberParser(key) { + return function (opt) { + const intOpt = parseInt(opt); + + if (!Number.isInteger(intOpt)) { + throw new Error(`Key ${key} has invalid value ${opt}`); + } + + return intOpt; + }; +} + +function numberOrBoolParser(key) { + return function (opt) { + if (typeof opt === 'boolean') { + return opt; + } + + if (opt === 'true') { + return true; + } + + if (opt === 'false') { + return false; + } + + return numberParser(key)(opt); + }; +} + +function objectParser(opt) { + if (typeof opt == 'object') { + return opt; + } + + return JSON.parse(opt); +} + +function arrayParser(opt) { + if (Array.isArray(opt)) { + return opt; + } else if (typeof opt === 'string') { + return opt.split(','); + } else { + throw new Error(`${opt} should be a comma separated string or an array`); + } +} + +function moduleOrObjectParser(opt) { + if (typeof opt == 'object') { + return opt; + } + + try { + return JSON.parse(opt); + } catch (e) { + /* */ + } + + return opt; +} + +function booleanParser(opt) { + if (opt == true || opt == 'true' || opt == '1') { + return true; + } + + return false; +} + +function nullParser(opt) { + if (opt == 'null') { + return null; + } + + return opt; +} + +module.exports = { + numberParser, + numberOrBoolParser, + nullParser, + booleanParser, + moduleOrObjectParser, + arrayParser, + objectParser +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL3BhcnNlcnMuanMiXSwibmFtZXMiOlsibnVtYmVyUGFyc2VyIiwia2V5Iiwib3B0IiwiaW50T3B0IiwicGFyc2VJbnQiLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJFcnJvciIsIm51bWJlck9yQm9vbFBhcnNlciIsIm9iamVjdFBhcnNlciIsIkpTT04iLCJwYXJzZSIsImFycmF5UGFyc2VyIiwiQXJyYXkiLCJpc0FycmF5Iiwic3BsaXQiLCJtb2R1bGVPck9iamVjdFBhcnNlciIsImUiLCJib29sZWFuUGFyc2VyIiwibnVsbFBhcnNlciIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUEsU0FBU0EsWUFBVCxDQUFzQkMsR0FBdEIsRUFBMkI7QUFDekIsU0FBTyxVQUFTQyxHQUFULEVBQWM7QUFDbkIsVUFBTUMsTUFBTSxHQUFHQyxRQUFRLENBQUNGLEdBQUQsQ0FBdkI7O0FBQ0EsUUFBSSxDQUFDRyxNQUFNLENBQUNDLFNBQVAsQ0FBaUJILE1BQWpCLENBQUwsRUFBK0I7QUFDN0IsWUFBTSxJQUFJSSxLQUFKLENBQVcsT0FBTU4sR0FBSSxzQkFBcUJDLEdBQUksRUFBOUMsQ0FBTjtBQUNEOztBQUNELFdBQU9DLE1BQVA7QUFDRCxHQU5EO0FBT0Q7O0FBRUQsU0FBU0ssa0JBQVQsQ0FBNEJQLEdBQTVCLEVBQWlDO0FBQy9CLFNBQU8sVUFBU0MsR0FBVCxFQUFjO0FBQ25CLFFBQUksT0FBT0EsR0FBUCxLQUFlLFNBQW5CLEVBQThCO0FBQzVCLGFBQU9BLEdBQVA7QUFDRDs7QUFDRCxRQUFJQSxHQUFHLEtBQUssTUFBWixFQUFvQjtBQUNsQixhQUFPLElBQVA7QUFDRDs7QUFDRCxRQUFJQSxHQUFHLEtBQUssT0FBWixFQUFxQjtBQUNuQixhQUFPLEtBQVA7QUFDRDs7QUFDRCxXQUFPRixZQUFZLENBQUNDLEdBQUQsQ0FBWixDQUFrQkMsR0FBbEIsQ0FBUDtBQUNELEdBWEQ7QUFZRDs7QUFFRCxTQUFTTyxZQUFULENBQXNCUCxHQUF0QixFQUEyQjtBQUN6QixNQUFJLE9BQU9BLEdBQVAsSUFBYyxRQUFsQixFQUE0QjtBQUMxQixXQUFPQSxHQUFQO0FBQ0Q7O0FBQ0QsU0FBT1EsSUFBSSxDQUFDQyxLQUFMLENBQVdULEdBQVgsQ0FBUDtBQUNEOztBQUVELFNBQVNVLFdBQVQsQ0FBcUJWLEdBQXJCLEVBQTBCO0FBQ3hCLE1BQUlXLEtBQUssQ0FBQ0MsT0FBTixDQUFjWixHQUFkLENBQUosRUFBd0I7QUFDdEIsV0FBT0EsR0FBUDtBQUNELEdBRkQsTUFFTyxJQUFJLE9BQU9BLEdBQVAsS0FBZSxRQUFuQixFQUE2QjtBQUNsQyxXQUFPQSxHQUFHLENBQUNhLEtBQUosQ0FBVSxHQUFWLENBQVA7QUFDRCxHQUZNLE1BRUE7QUFDTCxVQUFNLElBQUlSLEtBQUosQ0FBVyxHQUFFTCxHQUFJLGlEQUFqQixDQUFOO0FBQ0Q7QUFDRjs7QUFFRCxTQUFTYyxvQkFBVCxDQUE4QmQsR0FBOUIsRUFBbUM7QUFDakMsTUFBSSxPQUFPQSxHQUFQLElBQWMsUUFBbEIsRUFBNEI7QUFDMUIsV0FBT0EsR0FBUDtBQUNEOztBQUNELE1BQUk7QUFDRixXQUFPUSxJQUFJLENBQUNDLEtBQUwsQ0FBV1QsR0FBWCxDQUFQO0FBQ0QsR0FGRCxDQUVFLE9BQU9lLENBQVAsRUFBVTtBQUNWO0FBQ0Q7O0FBQ0QsU0FBT2YsR0FBUDtBQUNEOztBQUVELFNBQVNnQixhQUFULENBQXVCaEIsR0FBdkIsRUFBNEI7QUFDMUIsTUFBSUEsR0FBRyxJQUFJLElBQVAsSUFBZUEsR0FBRyxJQUFJLE1BQXRCLElBQWdDQSxHQUFHLElBQUksR0FBM0MsRUFBZ0Q7QUFDOUMsV0FBTyxJQUFQO0FBQ0Q7O0FBQ0QsU0FBTyxLQUFQO0FBQ0Q7O0FBRUQsU0FBU2lCLFVBQVQsQ0FBb0JqQixHQUFwQixFQUF5QjtBQUN2QixNQUFJQSxHQUFHLElBQUksTUFBWCxFQUFtQjtBQUNqQixXQUFPLElBQVA7QUFDRDs7QUFDRCxTQUFPQSxHQUFQO0FBQ0Q7O0FBRURrQixNQUFNLENBQUNDLE9BQVAsR0FBaUI7QUFDZnJCLEVBQUFBLFlBRGU7QUFFZlEsRUFBQUEsa0JBRmU7QUFHZlcsRUFBQUEsVUFIZTtBQUlmRCxFQUFBQSxhQUplO0FBS2ZGLEVBQUFBLG9CQUxlO0FBTWZKLEVBQUFBLFdBTmU7QUFPZkgsRUFBQUE7QUFQZSxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbImZ1bmN0aW9uIG51bWJlclBhcnNlcihrZXkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKG9wdCkge1xuICAgIGNvbnN0IGludE9wdCA9IHBhcnNlSW50KG9wdCk7XG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGludE9wdCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgS2V5ICR7a2V5fSBoYXMgaW52YWxpZCB2YWx1ZSAke29wdH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGludE9wdDtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbnVtYmVyT3JCb29sUGFyc2VyKGtleSkge1xuICByZXR1cm4gZnVuY3Rpb24ob3B0KSB7XG4gICAgaWYgKHR5cGVvZiBvcHQgPT09ICdib29sZWFuJykge1xuICAgICAgcmV0dXJuIG9wdDtcbiAgICB9XG4gICAgaWYgKG9wdCA9PT0gJ3RydWUnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKG9wdCA9PT0gJ2ZhbHNlJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gbnVtYmVyUGFyc2VyKGtleSkob3B0KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gb2JqZWN0UGFyc2VyKG9wdCkge1xuICBpZiAodHlwZW9mIG9wdCA9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBvcHQ7XG4gIH1cbiAgcmV0dXJuIEpTT04ucGFyc2Uob3B0KTtcbn1cblxuZnVuY3Rpb24gYXJyYXlQYXJzZXIob3B0KSB7XG4gIGlmIChBcnJheS5pc0FycmF5KG9wdCkpIHtcbiAgICByZXR1cm4gb3B0O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBvcHQgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIG9wdC5zcGxpdCgnLCcpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtvcHR9IHNob3VsZCBiZSBhIGNvbW1hIHNlcGFyYXRlZCBzdHJpbmcgb3IgYW4gYXJyYXlgKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtb2R1bGVPck9iamVjdFBhcnNlcihvcHQpIHtcbiAgaWYgKHR5cGVvZiBvcHQgPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gb3B0O1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2Uob3B0KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8qICovXG4gIH1cbiAgcmV0dXJuIG9wdDtcbn1cblxuZnVuY3Rpb24gYm9vbGVhblBhcnNlcihvcHQpIHtcbiAgaWYgKG9wdCA9PSB0cnVlIHx8IG9wdCA9PSAndHJ1ZScgfHwgb3B0ID09ICcxJykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gbnVsbFBhcnNlcihvcHQpIHtcbiAgaWYgKG9wdCA9PSAnbnVsbCcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4gb3B0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgbnVtYmVyUGFyc2VyLFxuICBudW1iZXJPckJvb2xQYXJzZXIsXG4gIG51bGxQYXJzZXIsXG4gIGJvb2xlYW5QYXJzZXIsXG4gIG1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICBhcnJheVBhcnNlcixcbiAgb2JqZWN0UGFyc2VyLFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/ParseMessageQueue.js b/lib/ParseMessageQueue.js new file mode 100644 index 0000000000..c98610a00c --- /dev/null +++ b/lib/ParseMessageQueue.js @@ -0,0 +1,34 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseMessageQueue = void 0; + +var _AdapterLoader = require("./Adapters/AdapterLoader"); + +var _EventEmitterMQ = require("./Adapters/MessageQueue/EventEmitterMQ"); + +const ParseMessageQueue = {}; +exports.ParseMessageQueue = ParseMessageQueue; + +ParseMessageQueue.createPublisher = function (config) { + const adapter = (0, _AdapterLoader.loadAdapter)(config.messageQueueAdapter, _EventEmitterMQ.EventEmitterMQ, config); + + if (typeof adapter.createPublisher !== 'function') { + throw 'pubSubAdapter should have createPublisher()'; + } + + return adapter.createPublisher(config); +}; + +ParseMessageQueue.createSubscriber = function (config) { + const adapter = (0, _AdapterLoader.loadAdapter)(config.messageQueueAdapter, _EventEmitterMQ.EventEmitterMQ, config); + + if (typeof adapter.createSubscriber !== 'function') { + throw 'messageQueueAdapter should have createSubscriber()'; + } + + return adapter.createSubscriber(config); +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZU1lc3NhZ2VRdWV1ZS5qcyJdLCJuYW1lcyI6WyJQYXJzZU1lc3NhZ2VRdWV1ZSIsImNyZWF0ZVB1Ymxpc2hlciIsImNvbmZpZyIsImFkYXB0ZXIiLCJtZXNzYWdlUXVldWVBZGFwdGVyIiwiRXZlbnRFbWl0dGVyTVEiLCJjcmVhdGVTdWJzY3JpYmVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBRUEsTUFBTUEsaUJBQWlCLEdBQUcsRUFBMUI7OztBQUVBQSxpQkFBaUIsQ0FBQ0MsZUFBbEIsR0FBb0MsVUFBU0MsTUFBVCxFQUEyQjtBQUM3RCxRQUFNQyxPQUFPLEdBQUcsZ0NBQ2RELE1BQU0sQ0FBQ0UsbUJBRE8sRUFFZEMsOEJBRmMsRUFHZEgsTUFIYyxDQUFoQjs7QUFLQSxNQUFJLE9BQU9DLE9BQU8sQ0FBQ0YsZUFBZixLQUFtQyxVQUF2QyxFQUFtRDtBQUNqRCxVQUFNLDZDQUFOO0FBQ0Q7O0FBQ0QsU0FBT0UsT0FBTyxDQUFDRixlQUFSLENBQXdCQyxNQUF4QixDQUFQO0FBQ0QsQ0FWRDs7QUFZQUYsaUJBQWlCLENBQUNNLGdCQUFsQixHQUFxQyxVQUFTSixNQUFULEVBQTRCO0FBQy9ELFFBQU1DLE9BQU8sR0FBRyxnQ0FDZEQsTUFBTSxDQUFDRSxtQkFETyxFQUVkQyw4QkFGYyxFQUdkSCxNQUhjLENBQWhCOztBQUtBLE1BQUksT0FBT0MsT0FBTyxDQUFDRyxnQkFBZixLQUFvQyxVQUF4QyxFQUFvRDtBQUNsRCxVQUFNLG9EQUFOO0FBQ0Q7O0FBQ0QsU0FBT0gsT0FBTyxDQUFDRyxnQkFBUixDQUF5QkosTUFBekIsQ0FBUDtBQUNELENBVkQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBsb2FkQWRhcHRlciB9IGZyb20gJy4vQWRhcHRlcnMvQWRhcHRlckxvYWRlcic7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXJNUSB9IGZyb20gJy4vQWRhcHRlcnMvTWVzc2FnZVF1ZXVlL0V2ZW50RW1pdHRlck1RJztcblxuY29uc3QgUGFyc2VNZXNzYWdlUXVldWUgPSB7fTtcblxuUGFyc2VNZXNzYWdlUXVldWUuY3JlYXRlUHVibGlzaGVyID0gZnVuY3Rpb24oY29uZmlnOiBhbnkpOiBhbnkge1xuICBjb25zdCBhZGFwdGVyID0gbG9hZEFkYXB0ZXIoXG4gICAgY29uZmlnLm1lc3NhZ2VRdWV1ZUFkYXB0ZXIsXG4gICAgRXZlbnRFbWl0dGVyTVEsXG4gICAgY29uZmlnXG4gICk7XG4gIGlmICh0eXBlb2YgYWRhcHRlci5jcmVhdGVQdWJsaXNoZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyAncHViU3ViQWRhcHRlciBzaG91bGQgaGF2ZSBjcmVhdGVQdWJsaXNoZXIoKSc7XG4gIH1cbiAgcmV0dXJuIGFkYXB0ZXIuY3JlYXRlUHVibGlzaGVyKGNvbmZpZyk7XG59O1xuXG5QYXJzZU1lc3NhZ2VRdWV1ZS5jcmVhdGVTdWJzY3JpYmVyID0gZnVuY3Rpb24oY29uZmlnOiBhbnkpOiB2b2lkIHtcbiAgY29uc3QgYWRhcHRlciA9IGxvYWRBZGFwdGVyKFxuICAgIGNvbmZpZy5tZXNzYWdlUXVldWVBZGFwdGVyLFxuICAgIEV2ZW50RW1pdHRlck1RLFxuICAgIGNvbmZpZ1xuICApO1xuICBpZiAodHlwZW9mIGFkYXB0ZXIuY3JlYXRlU3Vic2NyaWJlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93ICdtZXNzYWdlUXVldWVBZGFwdGVyIHNob3VsZCBoYXZlIGNyZWF0ZVN1YnNjcmliZXIoKSc7XG4gIH1cbiAgcmV0dXJuIGFkYXB0ZXIuY3JlYXRlU3Vic2NyaWJlcihjb25maWcpO1xufTtcblxuZXhwb3J0IHsgUGFyc2VNZXNzYWdlUXVldWUgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/ParseServer.js b/lib/ParseServer.js new file mode 100644 index 0000000000..a5a7843ce1 --- /dev/null +++ b/lib/ParseServer.js @@ -0,0 +1,484 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Options = require("./Options"); + +var _defaults = _interopRequireDefault(require("./defaults")); + +var logging = _interopRequireWildcard(require("./logger")); + +var _Config = _interopRequireDefault(require("./Config")); + +var _PromiseRouter = _interopRequireDefault(require("./PromiseRouter")); + +var _requiredParameter = _interopRequireDefault(require("./requiredParameter")); + +var _AnalyticsRouter = require("./Routers/AnalyticsRouter"); + +var _ClassesRouter = require("./Routers/ClassesRouter"); + +var _FeaturesRouter = require("./Routers/FeaturesRouter"); + +var _FilesRouter = require("./Routers/FilesRouter"); + +var _FunctionsRouter = require("./Routers/FunctionsRouter"); + +var _GlobalConfigRouter = require("./Routers/GlobalConfigRouter"); + +var _GraphQLRouter = require("./Routers/GraphQLRouter"); + +var _HooksRouter = require("./Routers/HooksRouter"); + +var _IAPValidationRouter = require("./Routers/IAPValidationRouter"); + +var _InstallationsRouter = require("./Routers/InstallationsRouter"); + +var _LogsRouter = require("./Routers/LogsRouter"); + +var _ParseLiveQueryServer = require("./LiveQuery/ParseLiveQueryServer"); + +var _PublicAPIRouter = require("./Routers/PublicAPIRouter"); + +var _PushRouter = require("./Routers/PushRouter"); + +var _CloudCodeRouter = require("./Routers/CloudCodeRouter"); + +var _RolesRouter = require("./Routers/RolesRouter"); + +var _SchemasRouter = require("./Routers/SchemasRouter"); + +var _SessionsRouter = require("./Routers/SessionsRouter"); + +var _UsersRouter = require("./Routers/UsersRouter"); + +var _PurgeRouter = require("./Routers/PurgeRouter"); + +var _AudiencesRouter = require("./Routers/AudiencesRouter"); + +var _AggregateRouter = require("./Routers/AggregateRouter"); + +var _ParseServerRESTController = require("./ParseServerRESTController"); + +var controllers = _interopRequireWildcard(require("./Controllers")); + +var _ParseGraphQLServer = require("./GraphQL/ParseGraphQLServer"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// ParseServer - open-source compatible API Server for Parse apps +var batch = require('./batch'), + bodyParser = require('body-parser'), + express = require('express'), + middlewares = require('./middlewares'), + Parse = require('parse/node').Parse, + { + parse +} = require('graphql'), + path = require('path'), + fs = require('fs'); + +// Mutate the Parse object to add the Cloud Code handlers +addParseCloud(); // ParseServer works like a constructor of an express app. +// https://parseplatform.org/parse-server/api/master/ParseServerOptions.html + +class ParseServer { + /** + * @constructor + * @param {ParseServerOptions} options the parse server initialization options + */ + constructor(options) { + injectDefaults(options); + const { + appId = (0, _requiredParameter.default)('You must provide an appId!'), + masterKey = (0, _requiredParameter.default)('You must provide a masterKey!'), + cloud, + javascriptKey, + serverURL = (0, _requiredParameter.default)('You must provide a serverURL!'), + serverStartComplete + } = options; // Initialize the node client SDK automatically + + Parse.initialize(appId, javascriptKey || 'unused', masterKey); + Parse.serverURL = serverURL; + const allControllers = controllers.getControllers(options); + const { + loggerController, + databaseController, + hooksController + } = allControllers; + this.config = _Config.default.put(Object.assign({}, options, allControllers)); + logging.setLogger(loggerController); + const dbInitPromise = databaseController.performInitialization(); + const hooksLoadPromise = hooksController.load(); // Note: Tests will start to fail if any validation happens after this is called. + + Promise.all([dbInitPromise, hooksLoadPromise]).then(() => { + if (serverStartComplete) { + serverStartComplete(); + } + }).catch(error => { + if (serverStartComplete) { + serverStartComplete(error); + } else { + console.error(error); + process.exit(1); + } + }); + + if (cloud) { + addParseCloud(); + + if (typeof cloud === 'function') { + cloud(Parse); + } else if (typeof cloud === 'string') { + require(path.resolve(process.cwd(), cloud)); + } else { + throw "argument 'cloud' must either be a string or a function"; + } + } + } + + get app() { + if (!this._app) { + this._app = ParseServer.app(this.config); + } + + return this._app; + } + + handleShutdown() { + const promises = []; + const { + adapter: databaseAdapter + } = this.config.databaseController; + + if (databaseAdapter && typeof databaseAdapter.handleShutdown === 'function') { + promises.push(databaseAdapter.handleShutdown()); + } + + const { + adapter: fileAdapter + } = this.config.filesController; + + if (fileAdapter && typeof fileAdapter.handleShutdown === 'function') { + promises.push(fileAdapter.handleShutdown()); + } + + return (promises.length > 0 ? Promise.all(promises) : Promise.resolve()).then(() => { + if (this.config.serverCloseComplete) { + this.config.serverCloseComplete(); + } + }); + } + /** + * @static + * Create an express app for the parse server + * @param {Object} options let you specify the maxUploadSize when creating the express app */ + + + static app({ + maxUploadSize = '20mb', + appId, + directAccess + }) { + // This app serves the Parse API directly. + // It's the equivalent of https://api.parse.com/1 in the hosted Parse API. + var api = express(); //api.use("/apps", express.static(__dirname + "/public")); + + api.use(middlewares.allowCrossDomain(appId)); // File handling needs to be before default middlewares are applied + + api.use('/', new _FilesRouter.FilesRouter().expressRouter({ + maxUploadSize: maxUploadSize + })); + api.use('/health', function (req, res) { + res.json({ + status: 'ok' + }); + }); + api.use('/', bodyParser.urlencoded({ + extended: false + }), new _PublicAPIRouter.PublicAPIRouter().expressRouter()); + api.use(bodyParser.json({ + type: '*/*', + limit: maxUploadSize + })); + api.use(middlewares.allowMethodOverride); + api.use(middlewares.handleParseHeaders); + const appRouter = ParseServer.promiseRouter({ + appId + }); + api.use(appRouter.expressRouter()); + api.use(middlewares.handleParseErrors); // run the following when not testing + + if (!process.env.TESTING) { + //This causes tests to spew some useless warnings, so disable in test + + /* istanbul ignore next */ + process.on('uncaughtException', err => { + if (err.code === 'EADDRINUSE') { + // user-friendly message for this common error + process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`); + process.exit(0); + } else { + throw err; + } + }); // verify the server url after a 'mount' event is received + + /* istanbul ignore next */ + + api.on('mount', function () { + ParseServer.verifyServerUrl(); + }); + } + + if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1' || directAccess) { + Parse.CoreManager.setRESTController((0, _ParseServerRESTController.ParseServerRESTController)(appId, appRouter)); + } + + return api; + } + + static promiseRouter({ + appId + }) { + const routers = [new _ClassesRouter.ClassesRouter(), new _UsersRouter.UsersRouter(), new _SessionsRouter.SessionsRouter(), new _RolesRouter.RolesRouter(), new _AnalyticsRouter.AnalyticsRouter(), new _InstallationsRouter.InstallationsRouter(), new _FunctionsRouter.FunctionsRouter(), new _SchemasRouter.SchemasRouter(), new _PushRouter.PushRouter(), new _LogsRouter.LogsRouter(), new _IAPValidationRouter.IAPValidationRouter(), new _FeaturesRouter.FeaturesRouter(), new _GlobalConfigRouter.GlobalConfigRouter(), new _GraphQLRouter.GraphQLRouter(), new _PurgeRouter.PurgeRouter(), new _HooksRouter.HooksRouter(), new _CloudCodeRouter.CloudCodeRouter(), new _AudiencesRouter.AudiencesRouter(), new _AggregateRouter.AggregateRouter()]; + const routes = routers.reduce((memo, router) => { + return memo.concat(router.routes); + }, []); + const appRouter = new _PromiseRouter.default(routes, appId); + batch.mountOnto(appRouter); + return appRouter; + } + /** + * starts the parse server's express app + * @param {ParseServerOptions} options to use to start the server + * @param {Function} callback called when the server has started + * @returns {ParseServer} the parse server instance + */ + + + start(options, callback) { + const app = express(); + + if (options.middleware) { + let middleware; + + if (typeof options.middleware == 'string') { + middleware = require(path.resolve(process.cwd(), options.middleware)); + } else { + middleware = options.middleware; // use as-is let express fail + } + + app.use(middleware); + } + + app.use(options.mountPath, this.app); + + if (options.mountGraphQL === true || options.mountPlayground === true) { + let graphQLCustomTypeDefs = undefined; + + if (options.graphQLSchema) { + graphQLCustomTypeDefs = parse(fs.readFileSync(options.graphQLSchema, 'utf8')); + } + + const parseGraphQLServer = new _ParseGraphQLServer.ParseGraphQLServer(this, { + graphQLPath: options.graphQLPath, + playgroundPath: options.playgroundPath, + graphQLCustomTypeDefs + }); + + if (options.mountGraphQL) { + parseGraphQLServer.applyGraphQL(app); + } + + if (options.mountPlayground) { + parseGraphQLServer.applyPlayground(app); + } + } + + const server = app.listen(options.port, options.host, callback); + this.server = server; + + if (options.startLiveQueryServer || options.liveQueryServerOptions) { + this.liveQueryServer = ParseServer.createLiveQueryServer(server, options.liveQueryServerOptions); + } + /* istanbul ignore next */ + + + if (!process.env.TESTING) { + configureListeners(this); + } + + this.expressApp = app; + return this; + } + /** + * Creates a new ParseServer and starts it. + * @param {ParseServerOptions} options used to start the server + * @param {Function} callback called when the server has started + * @returns {ParseServer} the parse server instance + */ + + + static start(options, callback) { + const parseServer = new ParseServer(options); + return parseServer.start(options, callback); + } + /** + * Helper method to create a liveQuery server + * @static + * @param {Server} httpServer an optional http server to pass + * @param {LiveQueryServerOptions} config options fot he liveQueryServer + * @returns {ParseLiveQueryServer} the live query server instance + */ + + + static createLiveQueryServer(httpServer, config) { + if (!httpServer || config && config.port) { + var app = express(); + httpServer = require('http').createServer(app); + httpServer.listen(config.port); + } + + return new _ParseLiveQueryServer.ParseLiveQueryServer(httpServer, config); + } + + static verifyServerUrl(callback) { + // perform a health check on the serverURL value + if (Parse.serverURL) { + const request = require('./request'); + + request({ + url: Parse.serverURL.replace(/\/$/, '') + '/health' + }).catch(response => response).then(response => { + const json = response.data || null; + + if (response.status !== 200 || !json || json && json.status !== 'ok') { + /* eslint-disable no-console */ + console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}'.` + ` Cloud code and push notifications may be unavailable!\n`); + /* eslint-enable no-console */ + + if (callback) { + callback(false); + } + } else { + if (callback) { + callback(true); + } + } + }); + } + } + +} + +function addParseCloud() { + const ParseCloud = require('./cloud-code/Parse.Cloud'); + + Object.assign(Parse.Cloud, ParseCloud); + global.Parse = Parse; +} + +function injectDefaults(options) { + Object.keys(_defaults.default).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(options, key)) { + options[key] = _defaults.default[key]; + } + }); + + if (!Object.prototype.hasOwnProperty.call(options, 'serverURL')) { + options.serverURL = `http://localhost:${options.port}${options.mountPath}`; + } // Reserved Characters + + + if (options.appId) { + const regex = /[!#$%'()*+&/:;=?@[\]{}^,|<>]/g; + + if (options.appId.match(regex)) { + console.warn(`\nWARNING, appId that contains special characters can cause issues while using with urls.\n`); + } + } // Backwards compatibility + + + if (options.userSensitiveFields) { + /* eslint-disable no-console */ + !process.env.TESTING && console.warn(`\nDEPRECATED: userSensitiveFields has been replaced by protectedFields allowing the ability to protect fields in all classes with CLP. \n`); + /* eslint-enable no-console */ + + const userSensitiveFields = Array.from(new Set([...(_defaults.default.userSensitiveFields || []), ...(options.userSensitiveFields || [])])); // If the options.protectedFields is unset, + // it'll be assigned the default above. + // Here, protect against the case where protectedFields + // is set, but doesn't have _User. + + if (!('_User' in options.protectedFields)) { + options.protectedFields = Object.assign({ + _User: [] + }, options.protectedFields); + } + + options.protectedFields['_User']['*'] = Array.from(new Set([...(options.protectedFields['_User']['*'] || []), ...userSensitiveFields])); + } // Merge protectedFields options with defaults. + + + Object.keys(_defaults.default.protectedFields).forEach(c => { + const cur = options.protectedFields[c]; + + if (!cur) { + options.protectedFields[c] = _defaults.default.protectedFields[c]; + } else { + Object.keys(_defaults.default.protectedFields[c]).forEach(r => { + const unq = new Set([...(options.protectedFields[c][r] || []), ..._defaults.default.protectedFields[c][r]]); + options.protectedFields[c][r] = Array.from(unq); + }); + } + }); + options.masterKeyIps = Array.from(new Set(options.masterKeyIps.concat(_defaults.default.masterKeyIps, options.masterKeyIps))); +} // Those can't be tested as it requires a subprocess + +/* istanbul ignore next */ + + +function configureListeners(parseServer) { + const server = parseServer.server; + const sockets = {}; + /* Currently, express doesn't shut down immediately after receiving SIGINT/SIGTERM if it has client connections that haven't timed out. (This is a known issue with node - https://github.com/nodejs/node/issues/2642) + This function, along with `destroyAliveConnections()`, intend to fix this behavior such that parse server will close all open connections and initiate the shutdown process as soon as it receives a SIGINT/SIGTERM signal. */ + + server.on('connection', socket => { + const socketId = socket.remoteAddress + ':' + socket.remotePort; + sockets[socketId] = socket; + socket.on('close', () => { + delete sockets[socketId]; + }); + }); + + const destroyAliveConnections = function () { + for (const socketId in sockets) { + try { + sockets[socketId].destroy(); + } catch (e) { + /* */ + } + } + }; + + const handleShutdown = function () { + process.stdout.write('Termination signal received. Shutting down.'); + destroyAliveConnections(); + server.close(); + parseServer.handleShutdown(); + }; + + process.on('SIGTERM', handleShutdown); + process.on('SIGINT', handleShutdown); +} + +var _default = ParseServer; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZVNlcnZlci5qcyJdLCJuYW1lcyI6WyJiYXRjaCIsInJlcXVpcmUiLCJib2R5UGFyc2VyIiwiZXhwcmVzcyIsIm1pZGRsZXdhcmVzIiwiUGFyc2UiLCJwYXJzZSIsInBhdGgiLCJmcyIsImFkZFBhcnNlQ2xvdWQiLCJQYXJzZVNlcnZlciIsImNvbnN0cnVjdG9yIiwib3B0aW9ucyIsImluamVjdERlZmF1bHRzIiwiYXBwSWQiLCJtYXN0ZXJLZXkiLCJjbG91ZCIsImphdmFzY3JpcHRLZXkiLCJzZXJ2ZXJVUkwiLCJzZXJ2ZXJTdGFydENvbXBsZXRlIiwiaW5pdGlhbGl6ZSIsImFsbENvbnRyb2xsZXJzIiwiY29udHJvbGxlcnMiLCJnZXRDb250cm9sbGVycyIsImxvZ2dlckNvbnRyb2xsZXIiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJob29rc0NvbnRyb2xsZXIiLCJjb25maWciLCJDb25maWciLCJwdXQiLCJPYmplY3QiLCJhc3NpZ24iLCJsb2dnaW5nIiwic2V0TG9nZ2VyIiwiZGJJbml0UHJvbWlzZSIsInBlcmZvcm1Jbml0aWFsaXphdGlvbiIsImhvb2tzTG9hZFByb21pc2UiLCJsb2FkIiwiUHJvbWlzZSIsImFsbCIsInRoZW4iLCJjYXRjaCIsImVycm9yIiwiY29uc29sZSIsInByb2Nlc3MiLCJleGl0IiwicmVzb2x2ZSIsImN3ZCIsImFwcCIsIl9hcHAiLCJoYW5kbGVTaHV0ZG93biIsInByb21pc2VzIiwiYWRhcHRlciIsImRhdGFiYXNlQWRhcHRlciIsInB1c2giLCJmaWxlQWRhcHRlciIsImZpbGVzQ29udHJvbGxlciIsImxlbmd0aCIsInNlcnZlckNsb3NlQ29tcGxldGUiLCJtYXhVcGxvYWRTaXplIiwiZGlyZWN0QWNjZXNzIiwiYXBpIiwidXNlIiwiYWxsb3dDcm9zc0RvbWFpbiIsIkZpbGVzUm91dGVyIiwiZXhwcmVzc1JvdXRlciIsInJlcSIsInJlcyIsImpzb24iLCJzdGF0dXMiLCJ1cmxlbmNvZGVkIiwiZXh0ZW5kZWQiLCJQdWJsaWNBUElSb3V0ZXIiLCJ0eXBlIiwibGltaXQiLCJhbGxvd01ldGhvZE92ZXJyaWRlIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwiYXBwUm91dGVyIiwicHJvbWlzZVJvdXRlciIsImhhbmRsZVBhcnNlRXJyb3JzIiwiZW52IiwiVEVTVElORyIsIm9uIiwiZXJyIiwiY29kZSIsInN0ZGVyciIsIndyaXRlIiwicG9ydCIsInZlcmlmeVNlcnZlclVybCIsIlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MiLCJDb3JlTWFuYWdlciIsInNldFJFU1RDb250cm9sbGVyIiwicm91dGVycyIsIkNsYXNzZXNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsIlNlc3Npb25zUm91dGVyIiwiUm9sZXNSb3V0ZXIiLCJBbmFseXRpY3NSb3V0ZXIiLCJJbnN0YWxsYXRpb25zUm91dGVyIiwiRnVuY3Rpb25zUm91dGVyIiwiU2NoZW1hc1JvdXRlciIsIlB1c2hSb3V0ZXIiLCJMb2dzUm91dGVyIiwiSUFQVmFsaWRhdGlvblJvdXRlciIsIkZlYXR1cmVzUm91dGVyIiwiR2xvYmFsQ29uZmlnUm91dGVyIiwiR3JhcGhRTFJvdXRlciIsIlB1cmdlUm91dGVyIiwiSG9va3NSb3V0ZXIiLCJDbG91ZENvZGVSb3V0ZXIiLCJBdWRpZW5jZXNSb3V0ZXIiLCJBZ2dyZWdhdGVSb3V0ZXIiLCJyb3V0ZXMiLCJyZWR1Y2UiLCJtZW1vIiwicm91dGVyIiwiY29uY2F0IiwiUHJvbWlzZVJvdXRlciIsIm1vdW50T250byIsInN0YXJ0IiwiY2FsbGJhY2siLCJtaWRkbGV3YXJlIiwibW91bnRQYXRoIiwibW91bnRHcmFwaFFMIiwibW91bnRQbGF5Z3JvdW5kIiwiZ3JhcGhRTEN1c3RvbVR5cGVEZWZzIiwidW5kZWZpbmVkIiwiZ3JhcGhRTFNjaGVtYSIsInJlYWRGaWxlU3luYyIsInBhcnNlR3JhcGhRTFNlcnZlciIsIlBhcnNlR3JhcGhRTFNlcnZlciIsImdyYXBoUUxQYXRoIiwicGxheWdyb3VuZFBhdGgiLCJhcHBseUdyYXBoUUwiLCJhcHBseVBsYXlncm91bmQiLCJzZXJ2ZXIiLCJsaXN0ZW4iLCJob3N0Iiwic3RhcnRMaXZlUXVlcnlTZXJ2ZXIiLCJsaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIiwibGl2ZVF1ZXJ5U2VydmVyIiwiY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyIiwiY29uZmlndXJlTGlzdGVuZXJzIiwiZXhwcmVzc0FwcCIsInBhcnNlU2VydmVyIiwiaHR0cFNlcnZlciIsImNyZWF0ZVNlcnZlciIsIlBhcnNlTGl2ZVF1ZXJ5U2VydmVyIiwicmVxdWVzdCIsInVybCIsInJlcGxhY2UiLCJyZXNwb25zZSIsImRhdGEiLCJ3YXJuIiwiUGFyc2VDbG91ZCIsIkNsb3VkIiwiZ2xvYmFsIiwia2V5cyIsImRlZmF1bHRzIiwiZm9yRWFjaCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsInJlZ2V4IiwibWF0Y2giLCJ1c2VyU2Vuc2l0aXZlRmllbGRzIiwiQXJyYXkiLCJmcm9tIiwiU2V0IiwicHJvdGVjdGVkRmllbGRzIiwiX1VzZXIiLCJjIiwiY3VyIiwiciIsInVucSIsIm1hc3RlcktleUlwcyIsInNvY2tldHMiLCJzb2NrZXQiLCJzb2NrZXRJZCIsInJlbW90ZUFkZHJlc3MiLCJyZW1vdGVQb3J0IiwiZGVzdHJveUFsaXZlQ29ubmVjdGlvbnMiLCJkZXN0cm95IiwiZSIsInN0ZG91dCIsImNsb3NlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBV0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBekNBO0FBRUEsSUFBSUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsU0FBRCxDQUFuQjtB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K0YsT0FBTyxDQUFDRSxRQUFELENBQWQ7QUFDRCxLQUZEO0FBR0QsR0FORDs7QUFRQSxRQUFNRyx1QkFBdUIsR0FBRyxZQUFXO0FBQ3pDLFNBQUssTUFBTUgsUUFBWCxJQUF1QkYsT0FBdkIsRUFBZ0M7QUFDOUIsVUFBSTtBQUNGQSxRQUFBQSxPQUFPLENBQUNFLFFBQUQsQ0FBUCxDQUFrQkksT0FBbEI7QUFDRCxPQUZELENBRUUsT0FBT0MsQ0FBUCxFQUFVO0FBQ1Y7QUFDRDtBQUNGO0FBQ0YsR0FSRDs7QUFVQSxRQUFNdEksY0FBYyxHQUFHLFlBQVc7QUFDaENOLElBQUFBLE9BQU8sQ0FBQzZJLE1BQVIsQ0FBZW5HLEtBQWYsQ0FBcUIsNkNBQXJCO0FBQ0FnRyxJQUFBQSx1QkFBdUI7QUFDdkIvQyxJQUFBQSxNQUFNLENBQUNtRCxLQUFQO0FBQ0ExQyxJQUFBQSxXQUFXLENBQUM5RixjQUFaO0FBQ0QsR0FMRDs7QUFNQU4sRUFBQUEsT0FBTyxDQUFDc0MsRUFBUixDQUFXLFNBQVgsRUFBc0JoQyxjQUF0QjtBQUNBTixFQUFBQSxPQUFPLENBQUNzQyxFQUFSLENBQVcsUUFBWCxFQUFxQmhDLGNBQXJCO0FBQ0Q7O2VBRWN4QyxXIiwic291cmNlc0NvbnRlbnQiOlsiLy8gUGFyc2VTZXJ2ZXIgLSBvcGVuLXNvdXJjZSBjb21wYXRpYmxlIEFQSSBTZXJ2ZXIgZm9yIFBhcnNlIGFwcHNcblxudmFyIGJhdGNoID0gcmVxdWlyZSgnLi9iYXRjaCcpLFxuICBib2R5UGFyc2VyID0gcmVxdWlyZSgnYm9keS1wYXJzZXInKSxcbiAgZXhwcmVzcyA9IHJlcXVpcmUoJ2V4cHJlc3MnKSxcbiAgbWlkZGxld2FyZXMgPSByZXF1aXJlKCcuL21pZGRsZXdhcmVzJyksXG4gIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlLFxuICB7IHBhcnNlIH0gPSByZXF1aXJlKCdncmFwaHFsJyksXG4gIHBhdGggPSByZXF1aXJlKCdwYXRoJyksXG4gIGZzID0gcmVxdWlyZSgnZnMnKTtcblxuaW1wb3J0IHsgUGFyc2VTZXJ2ZXJPcHRpb25zLCBMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIH0gZnJvbSAnLi9PcHRpb25zJztcbmltcG9ydCBkZWZhdWx0cyBmcm9tICcuL2RlZmF1bHRzJztcbmltcG9ydCAqIGFzIGxvZ2dpbmcgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuL0NvbmZpZyc7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0IHJlcXVpcmVkUGFyYW1ldGVyIGZyb20gJy4vcmVxdWlyZWRQYXJhbWV0ZXInO1xuaW1wb3J0IHsgQW5hbHl0aWNzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0FuYWx5dGljc1JvdXRlcic7XG5pbXBvcnQgeyBDbGFzc2VzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0NsYXNzZXNSb3V0ZXInO1xuaW1wb3J0IHsgRmVhdHVyZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvRmVhdHVyZXNSb3V0ZXInO1xuaW1wb3J0IHsgRmlsZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvRmlsZXNSb3V0ZXInO1xuaW1wb3J0IHsgRnVuY3Rpb25zUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0Z1bmN0aW9uc1JvdXRlcic7XG5pbXBvcnQgeyBHbG9iYWxDb25maWdSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvR2xvYmFsQ29uZmlnUm91dGVyJztcbmltcG9ydCB7IEdyYXBoUUxSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvR3JhcGhRTFJvdXRlcic7XG5pbXBvcnQgeyBIb29rc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9Ib29rc1JvdXRlcic7XG5pbXBvcnQgeyBJQVBWYWxpZGF0aW9uUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0lBUFZhbGlkYXRpb25Sb3V0ZXInO1xuaW1wb3J0IHsgSW5zdGFsbGF0aW9uc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9JbnN0YWxsYXRpb25zUm91dGVyJztcbmltcG9ydCB7IExvZ3NSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvTG9nc1JvdXRlcic7XG5pbXBvcnQgeyBQYXJzZUxpdmVRdWVyeVNlcnZlciB9IGZyb20gJy4vTGl2ZVF1ZXJ5L1BhcnNlTGl2ZVF1ZXJ5U2VydmVyJztcbmltcG9ydCB7IFB1YmxpY0FQSVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9QdWJsaWNBUElSb3V0ZXInO1xuaW1wb3J0IHsgUHVzaFJvdXRlciB9IGZyb20gJy4vUm91dGVycy9QdXNoUm91dGVyJztcbmltcG9ydCB7IENsb3VkQ29kZVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9DbG91ZENvZGVSb3V0ZXInO1xuaW1wb3J0IHsgUm9sZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvUm9sZXNSb3V0ZXInO1xuaW1wb3J0IHsgU2NoZW1hc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9TY2hlbWFzUm91dGVyJztcbmltcG9ydCB7IFNlc3Npb25zUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1Nlc3Npb25zUm91dGVyJztcbmltcG9ydCB7IFVzZXJzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1VzZXJzUm91dGVyJztcbmltcG9ydCB7IFB1cmdlUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1B1cmdlUm91dGVyJztcbmltcG9ydCB7IEF1ZGllbmNlc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9BdWRpZW5jZXNSb3V0ZXInO1xuaW1wb3J0IHsgQWdncmVnYXRlUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0FnZ3JlZ2F0ZVJvdXRlcic7XG5pbXBvcnQgeyBQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIH0gZnJvbSAnLi9QYXJzZVNlcnZlclJFU1RDb250cm9sbGVyJztcbmltcG9ydCAqIGFzIGNvbnRyb2xsZXJzIGZyb20gJy4vQ29udHJvbGxlcnMnO1xuaW1wb3J0IHsgUGFyc2VHcmFwaFFMU2VydmVyIH0gZnJvbSAnLi9HcmFwaFFML1BhcnNlR3JhcGhRTFNlcnZlcic7XG5cbi8vIE11dGF0ZSB0aGUgUGFyc2Ugb2JqZWN0IHRvIGFkZCB0aGUgQ2xvdWQgQ29kZSBoYW5kbGVyc1xuYWRkUGFyc2VDbG91ZCgpO1xuXG4vLyBQYXJzZVNlcnZlciB3b3JrcyBsaWtlIGEgY29uc3RydWN0b3Igb2YgYW4gZXhwcmVzcyBhcHAuXG4vLyBodHRwczovL3BhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9hcGkvbWFzdGVyL1BhcnNlU2VydmVyT3B0aW9ucy5odG1sXG5jbGFzcyBQYXJzZVNlcnZlciB7XG4gIC8qKlxuICAgKiBAY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtQYXJzZVNlcnZlck9wdGlvbnN9IG9wdGlvbnMgdGhlIHBhcnNlIHNlcnZlciBpbml0aWFsaXphdGlvbiBvcHRpb25zXG4gICAqL1xuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgICBpbmplY3REZWZhdWx0cyhvcHRpb25zKTtcbiAgICBjb25zdCB7XG4gICAgICBhcHBJZCA9IHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIGFuIGFwcElkIScpLFxuICAgICAgbWFzdGVyS2V5ID0gcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYSBtYXN0ZXJLZXkhJyksXG4gICAgICBjbG91ZCxcbiAgICAgIGphdmFzY3JpcHRLZXksXG4gICAgICBzZXJ2ZXJVUkwgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIHNlcnZlclVSTCEnKSxcbiAgICAgIHNlcnZlclN0YXJ0Q29tcGxldGUsXG4gICAgfSA9IG9wdGlvbnM7XG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgbm9kZSBjbGllbnQgU0RLIGF1dG9tYXRpY2FsbHlcbiAgICBQYXJzZS5pbml0aWFsaXplKGFwcElkLCBqYXZhc2NyaXB0S2V5IHx8ICd1bnVzZWQnLCBtYXN0ZXJLZXkpO1xuICAgIFBhcnNlLnNlcnZlclVSTCA9IHNlcnZlclVSTDtcblxuICAgIGNvbnN0IGFsbENvbnRyb2xsZXJzID0gY29udHJvbGxlcnMuZ2V0Q29udHJvbGxlcnMob3B0aW9ucyk7XG5cbiAgICBjb25zdCB7XG4gICAgICBsb2dnZXJDb250cm9sbGVyLFxuICAgICAgZGF0YWJhc2VDb250cm9sbGVyLFxuICAgICAgaG9va3NDb250cm9sbGVyLFxuICAgIH0gPSBhbGxDb250cm9sbGVycztcbiAgICB0aGlzLmNvbmZpZyA9IENvbmZpZy5wdXQoT2JqZWN0LmFzc2lnbih7fSwgb3B0aW9ucywgYWxsQ29udHJvbGxlcnMpKTtcblxuICAgIGxvZ2dpbmcuc2V0TG9nZ2VyKGxvZ2dlckNvbnRyb2xsZXIpO1xuICAgIGNvbnN0IGRiSW5pdFByb21pc2UgPSBkYXRhYmFzZUNvbnRyb2xsZXIucGVyZm9ybUluaXRpYWxpemF0aW9uKCk7XG4gICAgY29uc3QgaG9va3NMb2FkUHJvbWlzZSA9IGhvb2tzQ29udHJvbGxlci5sb2FkKCk7XG5cbiAgICAvLyBOb3RlOiBUZXN0cyB3aWxsIHN0YXJ0IHRvIGZhaWwgaWYgYW55IHZhbGlkYXRpb24gaGFwcGVucyBhZnRlciB0aGlzIGlzIGNhbGxlZC5cbiAgICBQcm9taXNlLmFsbChbZGJJbml0UHJvbWlzZSwgaG9va3NMb2FkUHJvbWlzZV0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChzZXJ2ZXJTdGFydENvbXBsZXRlKSB7XG4gICAgICAgICAgc2VydmVyU3RhcnRDb21wbGV0ZSgpO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKHNlcnZlclN0YXJ0Q29tcGxldGUpIHtcbiAgICAgICAgICBzZXJ2ZXJTdGFydENvbXBsZXRlKGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgaWYgKGNsb3VkKSB7XG4gICAgICBhZGRQYXJzZUNsb3VkKCk7XG4gICAgICBpZiAodHlwZW9mIGNsb3VkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNsb3VkKFBhcnNlKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGNsb3VkID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXF1aXJlKHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCBjbG91ZCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgXCJhcmd1bWVudCAnY2xvdWQnIG11c3QgZWl0aGVyIGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb25cIjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXQgYXBwKCkge1xuICAgIGlmICghdGhpcy5fYXBwKSB7XG4gICAgICB0aGlzLl9hcHAgPSBQYXJzZVNlcnZlci5hcHAodGhpcy5jb25maWcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYXBwO1xuICB9XG5cbiAgaGFuZGxlU2h1dGRvd24oKSB7XG4gICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcbiAgICBjb25zdCB7IGFkYXB0ZXI6IGRhdGFiYXNlQWRhcHRlciB9ID0gdGhpcy5jb25maWcuZGF0YWJhc2VDb250cm9sbGVyO1xuICAgIGlmIChcbiAgICAgIGRhdGFiYXNlQWRhcHRlciAmJlxuICAgICAgdHlwZW9mIGRhdGFiYXNlQWRhcHRlci5oYW5kbGVTaHV0ZG93biA9PT0gJ2Z1bmN0aW9uJ1xuICAgICkge1xuICAgICAgcHJvbWlzZXMucHVzaChkYXRhYmFzZUFkYXB0ZXIuaGFuZGxlU2h1dGRvd24oKSk7XG4gICAgfVxuICAgIGNvbnN0IHsgYWRhcHRlcjogZmlsZUFkYXB0ZXIgfSA9IHRoaXMuY29uZmlnLmZpbGVzQ29udHJvbGxlcjtcbiAgICBpZiAoZmlsZUFkYXB0ZXIgJiYgdHlwZW9mIGZpbGVBZGFwdGVyLmhhbmRsZVNodXRkb3duID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKGZpbGVBZGFwdGVyLmhhbmRsZVNodXRkb3duKCkpO1xuICAgIH1cbiAgICByZXR1cm4gKHByb21pc2VzLmxlbmd0aCA+IDBcbiAgICAgID8gUHJvbWlzZS5hbGwocHJvbWlzZXMpXG4gICAgICA6IFByb21pc2UucmVzb2x2ZSgpXG4gICAgKS50aGVuKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmNvbmZpZy5zZXJ2ZXJDbG9zZUNvbXBsZXRlKSB7XG4gICAgICAgIHRoaXMuY29uZmlnLnNlcnZlckNsb3NlQ29tcGxldGUoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3RhdGljXG4gICAqIENyZWF0ZSBhbiBleHByZXNzIGFwcCBmb3IgdGhlIHBhcnNlIHNlcnZlclxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBsZXQgeW91IHNwZWNpZnkgdGhlIG1heFVwbG9hZFNpemUgd2hlbiBjcmVhdGluZyB0aGUgZXhwcmVzcyBhcHAgICovXG4gIHN0YXRpYyBhcHAoeyBtYXhVcGxvYWRTaXplID0gJzIwbWInLCBhcHBJZCwgZGlyZWN0QWNjZXNzIH0pIHtcbiAgICAvLyBUaGlzIGFwcCBzZXJ2ZXMgdGhlIFBhcnNlIEFQSSBkaXJlY3RseS5cbiAgICAvLyBJdCdzIHRoZSBlcXVpdmFsZW50IG9mIGh0dHBzOi8vYXBpLnBhcnNlLmNvbS8xIGluIHRoZSBob3N0ZWQgUGFyc2UgQVBJLlxuICAgIHZhciBhcGkgPSBleHByZXNzKCk7XG4gICAgLy9hcGkudXNlKFwiL2FwcHNcIiwgZXhwcmVzcy5zdGF0aWMoX19kaXJuYW1lICsgXCIvcHVibGljXCIpKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmFsbG93Q3Jvc3NEb21haW4oYXBwSWQpKTtcbiAgICAvLyBGaWxlIGhhbmRsaW5nIG5lZWRzIHRvIGJlIGJlZm9yZSBkZWZhdWx0IG1pZGRsZXdhcmVzIGFyZSBhcHBsaWVkXG4gICAgYXBpLnVzZShcbiAgICAgICcvJyxcbiAgICAgIG5ldyBGaWxlc1JvdXRlcigpLmV4cHJlc3NSb3V0ZXIoe1xuICAgICAgICBtYXhVcGxvYWRTaXplOiBtYXhVcGxvYWRTaXplLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgYXBpLnVzZSgnL2hlYWx0aCcsIGZ1bmN0aW9uKHJlcSwgcmVzKSB7XG4gICAgICByZXMuanNvbih7XG4gICAgICAgIHN0YXR1czogJ29rJyxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgYXBpLnVzZShcbiAgICAgICcvJyxcbiAgICAgIGJvZHlQYXJzZXIudXJsZW5jb2RlZCh7IGV4dGVuZGVkOiBmYWxzZSB9KSxcbiAgICAgIG5ldyBQdWJsaWNBUElSb3V0ZXIoKS5leHByZXNzUm91dGVyKClcbiAgICApO1xuXG4gICAgYXBpLnVzZShib2R5UGFyc2VyLmpzb24oeyB0eXBlOiAnKi8qJywgbGltaXQ6IG1heFVwbG9hZFNpemUgfSkpO1xuICAgIGFwaS51c2UobWlkZGxld2FyZXMuYWxsb3dNZXRob2RPdmVycmlkZSk7XG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMpO1xuXG4gICAgY29uc3QgYXBwUm91dGVyID0gUGFyc2VTZXJ2ZXIucHJvbWlzZVJvdXRlcih7IGFwcElkIH0pO1xuICAgIGFwaS51c2UoYXBwUm91dGVyLmV4cHJlc3NSb3V0ZXIoKSk7XG5cbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlRXJyb3JzKTtcblxuICAgIC8vIHJ1biB0aGUgZm9sbG93aW5nIHdoZW4gbm90IHRlc3RpbmdcbiAgICBpZiAoIXByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICAgIC8vVGhpcyBjYXVzZXMgdGVzdHMgdG8gc3BldyBzb21lIHVzZWxlc3Mgd2FybmluZ3MsIHNvIGRpc2FibGUgaW4gdGVzdFxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHByb2Nlc3Mub24oJ3VuY2F1Z2h0RXhjZXB0aW9uJywgZXJyID0+IHtcbiAgICAgICAgaWYgKGVyci5jb2RlID09PSAnRUFERFJJTlVTRScpIHtcbiAgICAgICAgICAvLyB1c2VyLWZyaWVuZGx5IG1lc3NhZ2UgZm9yIHRoaXMgY29tbW9uIGVycm9yXG4gICAgICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoXG4gICAgICAgICAgICBgVW5hYmxlIHRvIGxpc3RlbiBvbiBwb3J0ICR7ZXJyLnBvcnR9LiBUaGUgcG9ydCBpcyBhbHJlYWR5IGluIHVzZS5gXG4gICAgICAgICAgKTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8vIHZlcmlmeSB0aGUgc2VydmVyIHVybCBhZnRlciBhICdtb3VudCcgZXZlbnQgaXMgcmVjZWl2ZWRcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBhcGkub24oJ21vdW50JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIFBhcnNlU2VydmVyLnZlcmlmeVNlcnZlclVybCgpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHByb2Nlc3MuZW52LlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MgPT09ICcxJyB8fFxuICAgICAgZGlyZWN0QWNjZXNzXG4gICAgKSB7XG4gICAgICBQYXJzZS5Db3JlTWFuYWdlci5zZXRSRVNUQ29udHJvbGxlcihcbiAgICAgICAgUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlcihhcHBJZCwgYXBwUm91dGVyKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGFwaTtcbiAgfVxuXG4gIHN0YXRpYyBwcm9taXNlUm91dGVyKHsgYXBwSWQgfSkge1xuICAgIGNvbnN0IHJvdXRlcnMgPSBbXG4gICAgICBuZXcgQ2xhc3Nlc1JvdXRlcigpLFxuICAgICAgbmV3IFVzZXJzUm91dGVyKCksXG4gICAgICBuZXcgU2Vzc2lvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBSb2xlc1JvdXRlcigpLFxuICAgICAgbmV3IEFuYWx5dGljc1JvdXRlcigpLFxuICAgICAgbmV3IEluc3RhbGxhdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBGdW5jdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBTY2hlbWFzUm91dGVyKCksXG4gICAgICBuZXcgUHVzaFJvdXRlcigpLFxuICAgICAgbmV3IExvZ3NSb3V0ZXIoKSxcbiAgICAgIG5ldyBJQVBWYWxpZGF0aW9uUm91dGVyKCksXG4gICAgICBuZXcgRmVhdHVyZXNSb3V0ZXIoKSxcbiAgICAgIG5ldyBHbG9iYWxDb25maWdSb3V0ZXIoKSxcbiAgICAgIG5ldyBHcmFwaFFMUm91dGVyKCksXG4gICAgICBuZXcgUHVyZ2VSb3V0ZXIoKSxcbiAgICAgIG5ldyBIb29rc1JvdXRlcigpLFxuICAgICAgbmV3IENsb3VkQ29kZVJvdXRlcigpLFxuICAgICAgbmV3IEF1ZGllbmNlc1JvdXRlcigpLFxuICAgICAgbmV3IEFnZ3JlZ2F0ZVJvdXRlcigpLFxuICAgIF07XG5cbiAgICBjb25zdCByb3V0ZXMgPSByb3V0ZXJzLnJlZHVjZSgobWVtbywgcm91dGVyKSA9PiB7XG4gICAgICByZXR1cm4gbWVtby5jb25jYXQocm91dGVyLnJvdXRlcyk7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3QgYXBwUm91dGVyID0gbmV3IFByb21pc2VSb3V0ZXIocm91dGVzLCBhcHBJZCk7XG5cbiAgICBiYXRjaC5tb3VudE9udG8oYXBwUm91dGVyKTtcbiAgICByZXR1cm4gYXBwUm91dGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIHN0YXJ0cyB0aGUgcGFyc2Ugc2VydmVyJ3MgZXhwcmVzcyBhcHBcbiAgICogQHBhcmFtIHtQYXJzZVNlcnZlck9wdGlvbnN9IG9wdGlvbnMgdG8gdXNlIHRvIHN0YXJ0IHRoZSBzZXJ2ZXJcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgY2FsbGVkIHdoZW4gdGhlIHNlcnZlciBoYXMgc3RhcnRlZFxuICAgKiBAcmV0dXJucyB7UGFyc2VTZXJ2ZXJ9IHRoZSBwYXJzZSBzZXJ2ZXIgaW5zdGFuY2VcbiAgICovXG4gIHN0YXJ0KG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucywgY2FsbGJhY2s6ID8oKSA9PiB2b2lkKSB7XG4gICAgY29uc3QgYXBwID0gZXhwcmVzcygpO1xuICAgIGlmIChvcHRpb25zLm1pZGRsZXdhcmUpIHtcbiAgICAgIGxldCBtaWRkbGV3YXJlO1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLm1pZGRsZXdhcmUgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgbWlkZGxld2FyZSA9IHJlcXVpcmUocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIG9wdGlvbnMubWlkZGxld2FyZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWlkZGxld2FyZSA9IG9wdGlvbnMubWlkZGxld2FyZTsgLy8gdXNlIGFzLWlzIGxldCBleHByZXNzIGZhaWxcbiAgICAgIH1cbiAgICAgIGFwcC51c2UobWlkZGxld2FyZSk7XG4gICAgfVxuXG4gICAgYXBwLnVzZShvcHRpb25zLm1vdW50UGF0aCwgdGhpcy5hcHApO1xuXG4gICAgaWYgKG9wdGlvbnMubW91bnRHcmFwaFFMID09PSB0cnVlIHx8IG9wdGlvbnMubW91bnRQbGF5Z3JvdW5kID09PSB0cnVlKSB7XG4gICAgICBsZXQgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKG9wdGlvbnMuZ3JhcGhRTFNjaGVtYSkge1xuICAgICAgICBncmFwaFFMQ3VzdG9tVHlwZURlZnMgPSBwYXJzZShcbiAgICAgICAgICBmcy5yZWFkRmlsZVN5bmMob3B0aW9ucy5ncmFwaFFMU2NoZW1hLCAndXRmOCcpXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBhcnNlR3JhcGhRTFNlcnZlciA9IG5ldyBQYXJzZUdyYXBoUUxTZXJ2ZXIodGhpcywge1xuICAgICAgICBncmFwaFFMUGF0aDogb3B0aW9ucy5ncmFwaFFMUGF0aCxcbiAgICAgICAgcGxheWdyb3VuZFBhdGg6IG9wdGlvbnMucGxheWdyb3VuZFBhdGgsXG4gICAgICAgIGdyYXBoUUxDdXN0b21UeXBlRGVmcyxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAob3B0aW9ucy5tb3VudEdyYXBoUUwpIHtcbiAgICAgICAgcGFyc2VHcmFwaFFMU2VydmVyLmFwcGx5R3JhcGhRTChhcHApO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5tb3VudFBsYXlncm91bmQpIHtcbiAgICAgICAgcGFyc2VHcmFwaFFMU2VydmVyLmFwcGx5UGxheWdyb3VuZChhcHApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHNlcnZlciA9IGFwcC5saXN0ZW4ob3B0aW9ucy5wb3J0LCBvcHRpb25zLmhvc3QsIGNhbGxiYWNrKTtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcblxuICAgIGlmIChvcHRpb25zLnN0YXJ0TGl2ZVF1ZXJ5U2VydmVyIHx8IG9wdGlvbnMubGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucykge1xuICAgICAgdGhpcy5saXZlUXVlcnlTZXJ2ZXIgPSBQYXJzZVNlcnZlci5jcmVhdGVMaXZlUXVlcnlTZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgb3B0aW9ucy5saXZlUXVlcnlTZXJ2ZXJPcHRpb25zXG4gICAgICApO1xuICAgIH1cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICghcHJvY2Vzcy5lbnYuVEVTVElORykge1xuICAgICAgY29uZmlndXJlTGlzdGVuZXJzKHRoaXMpO1xuICAgIH1cbiAgICB0aGlzLmV4cHJlc3NBcHAgPSBhcHA7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBQYXJzZVNlcnZlciBhbmQgc3RhcnRzIGl0LlxuICAgKiBAcGFyYW0ge1BhcnNlU2VydmVyT3B0aW9uc30gb3B0aW9ucyB1c2VkIHRvIHN0YXJ0IHRoZSBzZXJ2ZXJcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgY2FsbGVkIHdoZW4gdGhlIHNlcnZlciBoYXMgc3RhcnRlZFxuICAgKiBAcmV0dXJucyB7UGFyc2VTZXJ2ZXJ9IHRoZSBwYXJzZSBzZXJ2ZXIgaW5zdGFuY2VcbiAgICovXG4gIHN0YXRpYyBzdGFydChvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMsIGNhbGxiYWNrOiA/KCkgPT4gdm9pZCkge1xuICAgIGNvbnN0IHBhcnNlU2VydmVyID0gbmV3IFBhcnNlU2VydmVyKG9wdGlvbnMpO1xuICAgIHJldHVybiBwYXJzZVNlcnZlci5zdGFydChvcHRpb25zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIG1ldGhvZCB0byBjcmVhdGUgYSBsaXZlUXVlcnkgc2VydmVyXG4gICAqIEBzdGF0aWNcbiAgICogQHBhcmFtIHtTZXJ2ZXJ9IGh0dHBTZXJ2ZXIgYW4gb3B0aW9uYWwgaHR0cCBzZXJ2ZXIgdG8gcGFzc1xuICAgKiBAcGFyYW0ge0xpdmVRdWVyeVNlcnZlck9wdGlvbnN9IGNvbmZpZyBvcHRpb25zIGZvdCBoZSBsaXZlUXVlcnlTZXJ2ZXJcbiAgICogQHJldHVybnMge1BhcnNlTGl2ZVF1ZXJ5U2VydmVyfSB0aGUgbGl2ZSBxdWVyeSBzZXJ2ZXIgaW5zdGFuY2VcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVMaXZlUXVlcnlTZXJ2ZXIoaHR0cFNlcnZlciwgY29uZmlnOiBMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zKSB7XG4gICAgaWYgKCFodHRwU2VydmVyIHx8IChjb25maWcgJiYgY29uZmlnLnBvcnQpKSB7XG4gICAgICB2YXIgYXBwID0gZXhwcmVzcygpO1xuICAgICAgaHR0cFNlcnZlciA9IHJlcXVpcmUoJ2h0dHAnKS5jcmVhdGVTZXJ2ZXIoYXBwKTtcbiAgICAgIGh0dHBTZXJ2ZXIubGlzdGVuKGNvbmZpZy5wb3J0KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBQYXJzZUxpdmVRdWVyeVNlcnZlcihodHRwU2VydmVyLCBjb25maWcpO1xuICB9XG5cbiAgc3RhdGljIHZlcmlmeVNlcnZlclVybChjYWxsYmFjaykge1xuICAgIC8vIHBlcmZvcm0gYSBoZWFsdGggY2hlY2sgb24gdGhlIHNlcnZlclVSTCB2YWx1ZVxuICAgIGlmIChQYXJzZS5zZXJ2ZXJVUkwpIHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSByZXF1aXJlKCcuL3JlcXVlc3QnKTtcbiAgICAgIHJlcXVlc3QoeyB1cmw6IFBhcnNlLnNlcnZlclVSTC5yZXBsYWNlKC9cXC8kLywgJycpICsgJy9oZWFsdGgnIH0pXG4gICAgICAgIC5jYXRjaChyZXNwb25zZSA9PiByZXNwb25zZSlcbiAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgIGNvbnN0IGpzb24gPSByZXNwb25zZS5kYXRhIHx8IG51bGw7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzICE9PSAyMDAgfHxcbiAgICAgICAgICAgICFqc29uIHx8XG4gICAgICAgICAgICAoanNvbiAmJiBqc29uLnN0YXR1cyAhPT0gJ29rJylcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgYFxcbldBUk5JTkcsIFVuYWJsZSB0byBjb25uZWN0IHRvICcke1BhcnNlLnNlcnZlclVSTH0nLmAgK1xuICAgICAgICAgICAgICAgIGAgQ2xvdWQgY29kZSBhbmQgcHVzaCBub3RpZmljYXRpb25zIG1heSBiZSB1bmF2YWlsYWJsZSFcXG5gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2sodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gYWRkUGFyc2VDbG91ZCgpIHtcbiAgY29uc3QgUGFyc2VDbG91ZCA9IHJlcXVpcmUoJy4vY2xvdWQtY29kZS9QYXJzZS5DbG91ZCcpO1xuICBPYmplY3QuYXNzaWduKFBhcnNlLkNsb3VkLCBQYXJzZUNsb3VkKTtcbiAgZ2xvYmFsLlBhcnNlID0gUGFyc2U7XG59XG5cbmZ1bmN0aW9uIGluamVjdERlZmF1bHRzKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICBPYmplY3Qua2V5cyhkZWZhdWx0cykuZm9yRWFjaChrZXkgPT4ge1xuICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9wdGlvbnMsIGtleSkpIHtcbiAgICAgIG9wdGlvbnNba2V5XSA9IGRlZmF1bHRzW2tleV07XG4gICAgfVxuICB9KTtcblxuICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvcHRpb25zLCAnc2VydmVyVVJMJykpIHtcbiAgICBvcHRpb25zLnNlcnZlclVSTCA9IGBodHRwOi8vbG9jYWxob3N0OiR7b3B0aW9ucy5wb3J0fSR7b3B0aW9ucy5tb3VudFBhdGh9YDtcbiAgfVxuXG4gIC8vIFJlc2VydmVkIENoYXJhY3RlcnNcbiAgaWYgKG9wdGlvbnMuYXBwSWQpIHtcbiAgICBjb25zdCByZWdleCA9IC9bISMkJScoKSorJi86Oz0/QFtcXF17fV4sfDw+XS9nO1xuICAgIGlmIChvcHRpb25zLmFwcElkLm1hdGNoKHJlZ2V4KSkge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgXFxuV0FSTklORywgYXBwSWQgdGhhdCBjb250YWlucyBzcGVjaWFsIGNoYXJhY3RlcnMgY2FuIGNhdXNlIGlzc3VlcyB3aGlsZSB1c2luZyB3aXRoIHVybHMuXFxuYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICBpZiAob3B0aW9ucy51c2VyU2Vuc2l0aXZlRmllbGRzKSB7XG4gICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICFwcm9jZXNzLmVudi5URVNUSU5HICYmXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBcXG5ERVBSRUNBVEVEOiB1c2VyU2Vuc2l0aXZlRmllbGRzIGhhcyBiZWVuIHJlcGxhY2VkIGJ5IHByb3RlY3RlZEZpZWxkcyBhbGxvd2luZyB0aGUgYWJpbGl0eSB0byBwcm90ZWN0IGZpZWxkcyBpbiBhbGwgY2xhc3NlcyB3aXRoIENMUC4gXFxuYFxuICAgICAgKTtcbiAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi9cblxuICAgIGNvbnN0IHVzZXJTZW5zaXRpdmVGaWVsZHMgPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbXG4gICAgICAgIC4uLihkZWZhdWx0cy51c2VyU2Vuc2l0aXZlRmllbGRzIHx8IFtdKSxcbiAgICAgICAgLi4uKG9wdGlvbnMudXNlclNlbnNpdGl2ZUZpZWxkcyB8fCBbXSksXG4gICAgICBdKVxuICAgICk7XG5cbiAgICAvLyBJZiB0aGUgb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHMgaXMgdW5zZXQsXG4gICAgLy8gaXQnbGwgYmUgYXNzaWduZWQgdGhlIGRlZmF1bHQgYWJvdmUuXG4gICAgLy8gSGVyZSwgcHJvdGVjdCBhZ2FpbnN0IHRoZSBjYXNlIHdoZXJlIHByb3RlY3RlZEZpZWxkc1xuICAgIC8vIGlzIHNldCwgYnV0IGRvZXNuJ3QgaGF2ZSBfVXNlci5cbiAgICBpZiAoISgnX1VzZXInIGluIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzKSkge1xuICAgICAgb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHMgPSBPYmplY3QuYXNzaWduKFxuICAgICAgICB7IF9Vc2VyOiBbXSB9LFxuICAgICAgICBvcHRpb25zLnByb3RlY3RlZEZpZWxkc1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBvcHRpb25zLnByb3RlY3RlZEZpZWxkc1snX1VzZXInXVsnKiddID0gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoW1xuICAgICAgICAuLi4ob3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbJ19Vc2VyJ11bJyonXSB8fCBbXSksXG4gICAgICAgIC4uLnVzZXJTZW5zaXRpdmVGaWVsZHMsXG4gICAgICBdKVxuICAgICk7XG4gIH1cblxuICAvLyBNZXJnZSBwcm90ZWN0ZWRGaWVsZHMgb3B0aW9ucyB3aXRoIGRlZmF1bHRzLlxuICBPYmplY3Qua2V5cyhkZWZhdWx0cy5wcm90ZWN0ZWRGaWVsZHMpLmZvckVhY2goYyA9PiB7XG4gICAgY29uc3QgY3VyID0gb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbY107XG4gICAgaWYgKCFjdXIpIHtcbiAgICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzW2NdID0gZGVmYXVsdHMucHJvdGVjdGVkRmllbGRzW2NdO1xuICAgIH0gZWxzZSB7XG4gICAgICBPYmplY3Qua2V5cyhkZWZhdWx0cy5wcm90ZWN0ZWRGaWVsZHNbY10pLmZvckVhY2gociA9PiB7XG4gICAgICAgIGNvbnN0IHVucSA9IG5ldyBTZXQoW1xuICAgICAgICAgIC4uLihvcHRpb25zLnByb3RlY3RlZEZpZWxkc1tjXVtyXSB8fCBbXSksXG4gICAgICAgICAgLi4uZGVmYXVsdHMucHJvdGVjdGVkRmllbGRzW2NdW3JdLFxuICAgICAgICBdKTtcbiAgICAgICAgb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbY11bcl0gPSBBcnJheS5mcm9tKHVucSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIG9wdGlvbnMubWFzdGVyS2V5SXBzID0gQXJyYXkuZnJvbShcbiAgICBuZXcgU2V0KFxuICAgICAgb3B0aW9ucy5tYXN0ZXJLZXlJcHMuY29uY2F0KGRlZmF1bHRzLm1hc3RlcktleUlwcywgb3B0aW9ucy5tYXN0ZXJLZXlJcHMpXG4gICAgKVxuICApO1xufVxuXG4vLyBUaG9zZSBjYW4ndCBiZSB0ZXN0ZWQgYXMgaXQgcmVxdWlyZXMgYSBzdWJwcm9jZXNzXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuZnVuY3Rpb24gY29uZmlndXJlTGlzdGVuZXJzKHBhcnNlU2VydmVyKSB7XG4gIGNvbnN0IHNlcnZlciA9IHBhcnNlU2VydmVyLnNlcnZlcjtcbiAgY29uc3Qgc29ja2V0cyA9IHt9O1xuICAvKiBDdXJyZW50bHksIGV4cHJlc3MgZG9lc24ndCBzaHV0IGRvd24gaW1tZWRpYXRlbHkgYWZ0ZXIgcmVjZWl2aW5nIFNJR0lOVC9TSUdURVJNIGlmIGl0IGhhcyBjbGllbnQgY29ubmVjdGlvbnMgdGhhdCBoYXZlbid0IHRpbWVkIG91dC4gKFRoaXMgaXMgYSBrbm93biBpc3N1ZSB3aXRoIG5vZGUgLSBodHRwczovL2dpdGh1Yi5jb20vbm9kZWpzL25vZGUvaXNzdWVzLzI2NDIpXG4gICAgVGhpcyBmdW5jdGlvbiwgYWxvbmcgd2l0aCBgZGVzdHJveUFsaXZlQ29ubmVjdGlvbnMoKWAsIGludGVuZCB0byBmaXggdGhpcyBiZWhhdmlvciBzdWNoIHRoYXQgcGFyc2Ugc2VydmVyIHdpbGwgY2xvc2UgYWxsIG9wZW4gY29ubmVjdGlvbnMgYW5kIGluaXRpYXRlIHRoZSBzaHV0ZG93biBwcm9jZXNzIGFzIHNvb24gYXMgaXQgcmVjZWl2ZXMgYSBTSUdJTlQvU0lHVEVSTSBzaWduYWwuICovXG4gIHNlcnZlci5vbignY29ubmVjdGlvbicsIHNvY2tldCA9PiB7XG4gICAgY29uc3Qgc29ja2V0SWQgPSBzb2NrZXQucmVtb3RlQWRkcmVzcyArICc6JyArIHNvY2tldC5yZW1vdGVQb3J0O1xuICAgIHNvY2tldHNbc29ja2V0SWRdID0gc29ja2V0O1xuICAgIHNvY2tldC5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICBkZWxldGUgc29ja2V0c1tzb2NrZXRJZF07XG4gICAgfSk7XG4gIH0pO1xuXG4gIGNvbnN0IGRlc3Ryb3lBbGl2ZUNvbm5lY3Rpb25zID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yIChjb25zdCBzb2NrZXRJZCBpbiBzb2NrZXRzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBzb2NrZXRzW3NvY2tldElkXS5kZXN0cm95KCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8qICovXG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGhhbmRsZVNodXRkb3duID0gZnVuY3Rpb24oKSB7XG4gICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoJ1Rlcm1pbmF0aW9uIHNpZ25hbCByZWNlaXZlZC4gU2h1dHRpbmcgZG93bi4nKTtcbiAgICBkZXN0cm95QWxpdmVDb25uZWN0aW9ucygpO1xuICAgIHNlcnZlci5jbG9zZSgpO1xuICAgIHBhcnNlU2VydmVyLmhhbmRsZVNodXRkb3duKCk7XG4gIH07XG4gIHByb2Nlc3Mub24oJ1NJR1RFUk0nLCBoYW5kbGVTaHV0ZG93bik7XG4gIHByb2Nlc3Mub24oJ1NJR0lOVCcsIGhhbmRsZVNodXRkb3duKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUGFyc2VTZXJ2ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/ParseServerRESTController.js b/lib/ParseServerRESTController.js new file mode 100644 index 0000000000..f239e5568f --- /dev/null +++ b/lib/ParseServerRESTController.js @@ -0,0 +1,155 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseServerRESTController = ParseServerRESTController; +exports.default = void 0; + +const Config = require('./Config'); + +const Auth = require('./Auth'); + +const RESTController = require('parse/lib/node/RESTController'); + +const URL = require('url'); + +const Parse = require('parse/node'); + +function getSessionToken(options) { + if (options && typeof options.sessionToken === 'string') { + return Promise.resolve(options.sessionToken); + } + + return Promise.resolve(null); +} + +function getAuth(options = {}, config) { + const installationId = options.installationId || 'cloud'; + + if (options.useMasterKey) { + return Promise.resolve(new Auth.Auth({ + config, + isMaster: true, + installationId + })); + } + + return getSessionToken(options).then(sessionToken => { + if (sessionToken) { + options.sessionToken = sessionToken; + return Auth.getAuthForSessionToken({ + config, + sessionToken: sessionToken, + installationId + }); + } else { + return Promise.resolve(new Auth.Auth({ + config, + installationId + })); + } + }); +} + +function ParseServerRESTController(applicationId, router) { + function handleRequest(method, path, data = {}, options = {}, config) { + // Store the arguments, for later use if internal fails + const args = arguments; + + if (!config) { + config = Config.get(applicationId); + } + + const serverURL = URL.parse(config.serverURL); + + if (path.indexOf(serverURL.path) === 0) { + path = path.slice(serverURL.path.length, path.length); + } + + if (path[0] !== '/') { + path = '/' + path; + } + + if (path === '/batch') { + let initialPromise = Promise.resolve(); + + if (data.transaction === true) { + initialPromise = config.database.createTransactionalSession(); + } + + return initialPromise.then(() => { + const promises = data.requests.map(request => { + return handleRequest(request.method, request.path, request.body, options, config).then(response => { + return { + success: response + }; + }, error => { + return { + error: { + code: error.code, + error: error.message + } + }; + }); + }); + return Promise.all(promises).then(result => { + if (data.transaction === true) { + if (result.find(resultItem => typeof resultItem.error === 'object')) { + return config.database.abortTransactionalSession().then(() => { + return Promise.reject(result); + }); + } else { + return config.database.commitTransactionalSession().then(() => { + return result; + }); + } + } else { + return result; + } + }); + }); + } + + let query; + + if (method === 'GET') { + query = data; + } + + return new Promise((resolve, reject) => { + getAuth(options, config).then(auth => { + const request = { + body: data, + config, + auth, + info: { + applicationId: applicationId, + sessionToken: options.sessionToken + }, + query + }; + return Promise.resolve().then(() => { + return router.tryRouteRequest(method, path, request); + }).then(response => { + resolve(response.response, response.status, response); + }, err => { + if (err instanceof Parse.Error && err.code == Parse.Error.INVALID_JSON && err.message == `cannot route ${method} ${path}`) { + RESTController.request.apply(null, args).then(resolve, reject); + } else { + reject(err); + } + }); + }, reject); + }); + } + + return { + request: handleRequest, + ajax: RESTController.ajax + }; +} + +var _default = ParseServerRESTController; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZVNlcnZlclJFU1RDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkNvbmZpZyIsInJlcXVpcmUiLCJBdXRoIiwiUkVTVENvbnRyb2xsZXIiLCJVUkwiLCJQYXJzZSIsImdldFNlc3Npb25Ub2tlbiIsIm9wdGlvbnMiLCJzZXNzaW9uVG9rZW4iLCJQcm9taXNlIiwicmVzb2x2ZSIsImdldEF1dGgiLCJjb25maWciLCJpbnN0YWxsYXRpb25JZCIsInVzZU1hc3RlcktleSIsImlzTWFzdGVyIiwidGhlbiIsImdldEF1dGhGb3JTZXNzaW9uVG9rZW4iLCJQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIiwiYXBwbGljYXRpb25JZCIsInJvdXRlciIsImhhbmRsZVJlcXVlc3QiLCJtZXRob2QiLCJwYXRoIiwiZGF0YSIsImFyZ3MiLCJhcmd1bWVudHMiLCJnZXQiLCJzZXJ2ZXJVUkwiLCJwYXJzZSIsImluZGV4T2YiLCJzbGljZSIsImxlbmd0aCIsImluaXRpYWxQcm9taXNlIiwidHJhbnNhY3Rpb24iLCJkYXRhYmFzZSIsImNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uIiwicHJvbWlzZXMiLCJyZXF1ZXN0cyIsIm1hcCIsInJlcXVlc3QiLCJib2R5IiwicmVzcG9uc2UiLCJzdWNjZXNzIiwiZXJyb3IiLCJjb2RlIiwibWVzc2FnZSIsImFsbCIsInJlc3VsdCIsImZpbmQiLCJyZXN1bHRJdGVtIiwiYWJvcnRUcmFuc2FjdGlvbmFsU2Vzc2lvbiIsInJlamVjdCIsImNvbW1pdFRyYW5zYWN0aW9uYWxTZXNzaW9uIiwicXVlcnkiLCJhdXRoIiwiaW5mbyIsInRyeVJvdXRlUmVxdWVzdCIsInN0YXR1cyIsImVyciIsIkVycm9yIiwiSU5WQUxJRF9KU09OIiwiYXBwbHkiLCJhamF4Il0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBLE1BQU1BLE1BQU0sR0FBR0MsT0FBTyxDQUFDLFVBQUQsQ0FBdEI7O0FBQ0EsTUFBTUMsSUFBSSxHQUFHRCxPQUFPLENB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S0FBSyxDQUFDdUQsS0FBckIsSUFDQUQsR0FBRyxDQUFDZCxJQUFKLElBQVl4QyxLQUFLLENBQUN1RCxLQUFOLENBQVlDLFlBRHhCLElBRUFGLEdBQUcsQ0FBQ2IsT0FBSixJQUFnQixnQkFBZXhCLE1BQU8sSUFBR0MsSUFBSyxFQUhoRCxFQUlFO0FBQ0FwQixZQUFBQSxjQUFjLENBQUNxQyxPQUFmLENBQXVCc0IsS0FBdkIsQ0FBNkIsSUFBN0IsRUFBbUNyQyxJQUFuQyxFQUF5Q1QsSUFBekMsQ0FBOENOLE9BQTlDLEVBQXVEMEMsTUFBdkQ7QUFDRCxXQU5ELE1BTU87QUFDTEEsWUFBQUEsTUFBTSxDQUFDTyxHQUFELENBQU47QUFDRDtBQUNGLFNBbEJFLENBQVA7QUFvQkQsT0EvQkQsRUErQkdQLE1BL0JIO0FBZ0NELEtBakNNLENBQVA7QUFrQ0Q7O0FBRUQsU0FBTztBQUNMWixJQUFBQSxPQUFPLEVBQUVuQixhQURKO0FBRUwwQyxJQUFBQSxJQUFJLEVBQUU1RCxjQUFjLENBQUM0RDtBQUZoQixHQUFQO0FBSUQ7O2VBRWM3Qyx5QiIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IENvbmZpZyA9IHJlcXVpcmUoJy4vQ29uZmlnJyk7XG5jb25zdCBBdXRoID0gcmVxdWlyZSgnLi9BdXRoJyk7XG5jb25zdCBSRVNUQ29udHJvbGxlciA9IHJlcXVpcmUoJ3BhcnNlL2xpYi9ub2RlL1JFU1RDb250cm9sbGVyJyk7XG5jb25zdCBVUkwgPSByZXF1aXJlKCd1cmwnKTtcbmNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpO1xuXG5mdW5jdGlvbiBnZXRTZXNzaW9uVG9rZW4ob3B0aW9ucykge1xuICBpZiAob3B0aW9ucyAmJiB0eXBlb2Ygb3B0aW9ucy5zZXNzaW9uVG9rZW4gPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShvcHRpb25zLnNlc3Npb25Ub2tlbik7XG4gIH1cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcbn1cblxuZnVuY3Rpb24gZ2V0QXV0aChvcHRpb25zID0ge30sIGNvbmZpZykge1xuICBjb25zdCBpbnN0YWxsYXRpb25JZCA9IG9wdGlvbnMuaW5zdGFsbGF0aW9uSWQgfHwgJ2Nsb3VkJztcbiAgaWYgKG9wdGlvbnMudXNlTWFzdGVyS2V5KSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShcbiAgICAgIG5ldyBBdXRoLkF1dGgoeyBjb25maWcsIGlzTWFzdGVyOiB0cnVlLCBpbnN0YWxsYXRpb25JZCB9KVxuICAgICk7XG4gIH1cbiAgcmV0dXJuIGdldFNlc3Npb25Ub2tlbihvcHRpb25zKS50aGVuKHNlc3Npb25Ub2tlbiA9PiB7XG4gICAgaWYgKHNlc3Npb25Ub2tlbikge1xuICAgICAgb3B0aW9ucy5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uVG9rZW47XG4gICAgICByZXR1cm4gQXV0aC5nZXRBdXRoRm9yU2Vzc2lvblRva2VuKHtcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBzZXNzaW9uVG9rZW46IHNlc3Npb25Ub2tlbixcbiAgICAgICAgaW5zdGFsbGF0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgQXV0aC5BdXRoKHsgY29uZmlnLCBpbnN0YWxsYXRpb25JZCB9KSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlcihhcHBsaWNhdGlvbklkLCByb3V0ZXIpIHtcbiAgZnVuY3Rpb24gaGFuZGxlUmVxdWVzdChtZXRob2QsIHBhdGgsIGRhdGEgPSB7fSwgb3B0aW9ucyA9IHt9LCBjb25maWcpIHtcbiAgICAvLyBTdG9yZSB0aGUgYXJndW1lbnRzLCBmb3IgbGF0ZXIgdXNlIGlmIGludGVybmFsIGZhaWxzXG4gICAgY29uc3QgYXJncyA9IGFyZ3VtZW50cztcblxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICBjb25maWcgPSBDb25maWcuZ2V0KGFwcGxpY2F0aW9uSWQpO1xuICAgIH1cbiAgICBjb25zdCBzZXJ2ZXJVUkwgPSBVUkwucGFyc2UoY29uZmlnLnNlcnZlclVSTCk7XG4gICAgaWYgKHBhdGguaW5kZXhPZihzZXJ2ZXJVUkwucGF0aCkgPT09IDApIHtcbiAgICAgIHBhdGggPSBwYXRoLnNsaWNlKHNlcnZlclVSTC5wYXRoLmxlbmd0aCwgcGF0aC5sZW5ndGgpO1xuICAgIH1cblxuICAgIGlmIChwYXRoWzBdICE9PSAnLycpIHtcbiAgICAgIHBhdGggPSAnLycgKyBwYXRoO1xuICAgIH1cblxuICAgIGlmIChwYXRoID09PSAnL2JhdGNoJykge1xuICAgICAgbGV0IGluaXRpYWxQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICBpZiAoZGF0YS50cmFuc2FjdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICBpbml0aWFsUHJvbWlzZSA9IGNvbmZpZy5kYXRhYmFzZS5jcmVhdGVUcmFuc2FjdGlvbmFsU2Vzc2lvbigpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGluaXRpYWxQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IGRhdGEucmVxdWVzdHMubWFwKHJlcXVlc3QgPT4ge1xuICAgICAgICAgIHJldHVybiBoYW5kbGVSZXF1ZXN0KFxuICAgICAgICAgICAgcmVxdWVzdC5tZXRob2QsXG4gICAgICAgICAgICByZXF1ZXN0LnBhdGgsXG4gICAgICAgICAgICByZXF1ZXN0LmJvZHksXG4gICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgY29uZmlnXG4gICAgICAgICAgKS50aGVuKFxuICAgICAgICAgICAgcmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiByZXNwb25zZSB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBlcnJvcjogeyBjb2RlOiBlcnJvci5jb2RlLCBlcnJvcjogZXJyb3IubWVzc2FnZSB9LFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICBpZiAoZGF0YS50cmFuc2FjdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICByZXN1bHQuZmluZChyZXN1bHRJdGVtID0+IHR5cGVvZiByZXN1bHRJdGVtLmVycm9yID09PSAnb2JqZWN0JylcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICByZXR1cm4gY29uZmlnLmRhdGFiYXNlLmFib3J0VHJhbnNhY3Rpb25hbFNlc3Npb24oKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QocmVzdWx0KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gY29uZmlnLmRhdGFiYXNlLmNvbW1pdFRyYW5zYWN0aW9uYWxTZXNzaW9uKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCBxdWVyeTtcbiAgICBpZiAobWV0aG9kID09PSAnR0VUJykge1xuICAgICAgcXVlcnkgPSBkYXRhO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBnZXRBdXRoKG9wdGlvbnMsIGNvbmZpZykudGhlbihhdXRoID0+IHtcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHtcbiAgICAgICAgICBib2R5OiBkYXRhLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIGluZm86IHtcbiAgICAgICAgICAgIGFwcGxpY2F0aW9uSWQ6IGFwcGxpY2F0aW9uSWQsXG4gICAgICAgICAgICBzZXNzaW9uVG9rZW46IG9wdGlvbnMuc2Vzc2lvblRva2VuLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcXVlcnksXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiByb3V0ZXIudHJ5Um91dGVSZXF1ZXN0KG1ldGhvZCwgcGF0aCwgcmVxdWVzdCk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbihcbiAgICAgICAgICAgIHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZS5yZXNwb25zZSwgcmVzcG9uc2Uuc3RhdHVzLCByZXNwb25zZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyID0+IHtcbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIFBhcnNlLkVycm9yICYmXG4gICAgICAgICAgICAgICAgZXJyLmNvZGUgPT0gUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OICYmXG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPT0gYGNhbm5vdCByb3V0ZSAke21ldGhvZH0gJHtwYXRofWBcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgUkVTVENvbnRyb2xsZXIucmVxdWVzdC5hcHBseShudWxsLCBhcmdzKS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgfSwgcmVqZWN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcmVxdWVzdDogaGFuZGxlUmVxdWVzdCxcbiAgICBhamF4OiBSRVNUQ29udHJvbGxlci5hamF4LFxuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCBQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyO1xuZXhwb3J0IHsgUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlciB9O1xuIl19 \ No newline at end of file diff --git a/lib/PromiseRouter.js b/lib/PromiseRouter.js new file mode 100644 index 0000000000..8e5f872402 --- /dev/null +++ b/lib/PromiseRouter.js @@ -0,0 +1,255 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _express = _interopRequireDefault(require("express")); + +var _logger = _interopRequireDefault(require("./logger")); + +var _util = require("util"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// A router that is based on promises rather than req/res/next. +// This is intended to replace the use of express.Router to handle +// subsections of the API surface. +// This will make it easier to have methods like 'batch' that +// themselves use our routing information, without disturbing express +// components that external developers may be modifying. +const Layer = require('express/lib/router/layer'); + +function validateParameter(key, value) { + if (key == 'className') { + if (value.match(/_?[A-Za-z][A-Za-z_0-9]*/)) { + return value; + } + } else if (key == 'objectId') { + if (value.match(/[A-Za-z0-9]+/)) { + return value; + } + } else { + return value; + } +} + +class PromiseRouter { + // Each entry should be an object with: + // path: the path to route, in express format + // method: the HTTP method that this route handles. + // Must be one of: POST, GET, PUT, DELETE + // handler: a function that takes request, and returns a promise. + // Successful handlers should resolve to an object with fields: + // status: optional. the http status code. defaults to 200 + // response: a json object with the content of the response + // location: optional. a location header + constructor(routes = [], appId) { + this.routes = routes; + this.appId = appId; + this.mountRoutes(); + } // Leave the opportunity to + // subclasses to mount their routes by overriding + + + mountRoutes() {} // Merge the routes into this one + + + merge(router) { + for (var route of router.routes) { + this.routes.push(route); + } + } + + route(method, path, ...handlers) { + switch (method) { + case 'POST': + case 'GET': + case 'PUT': + case 'DELETE': + break; + + default: + throw 'cannot route method: ' + method; + } + + let handler = handlers[0]; + + if (handlers.length > 1) { + handler = function (req) { + return handlers.reduce((promise, handler) => { + return promise.then(() => { + return handler(req); + }); + }, Promise.resolve()); + }; + } + + this.routes.push({ + path: path, + method: method, + handler: handler, + layer: new Layer(path, null, handler) + }); + } // Returns an object with: + // handler: the handler that should deal with this request + // params: any :-params that got parsed from the path + // Returns undefined if there is no match. + + + match(method, path) { + for (var route of this.routes) { + if (route.method != method) { + continue; + } + + const layer = route.layer || new Layer(route.path, null, route.handler); + const match = layer.match(path); + + if (match) { + const params = layer.params; + Object.keys(params).forEach(key => { + params[key] = validateParameter(key, params[key]); + }); + return { + params: params, + handler: route.handler + }; + } + } + } // Mount the routes on this router onto an express app (or express router) + + + mountOnto(expressApp) { + this.routes.forEach(route => { + const method = route.method.toLowerCase(); + const handler = makeExpressHandler(this.appId, route.handler); + expressApp[method].call(expressApp, route.path, handler); + }); + return expressApp; + } + + expressRouter() { + return this.mountOnto(_express.default.Router()); + } + + tryRouteRequest(method, path, request) { + var match = this.match(method, path); + + if (!match) { + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'cannot route ' + method + ' ' + path); + } + + request.params = match.params; + return new Promise((resolve, reject) => { + match.handler(request).then(resolve, reject); + }); + } + +} // A helper function to make an express handler out of a a promise +// handler. +// Express handlers should never throw; if a promise handler throws we +// just treat it like it resolved to an error. + + +exports.default = PromiseRouter; + +function makeExpressHandler(appId, promiseHandler) { + return function (req, res, next) { + try { + const url = maskSensitiveUrl(req); + const body = Object.assign({}, req.body); + const method = req.method; + const headers = req.headers; + + _logger.default.logRequest({ + method, + url, + headers, + body + }); + + promiseHandler(req).then(result => { + clearSchemaCache(req); + + if (!result.response && !result.location && !result.text) { + _logger.default.error('the handler did not include a "response" or a "location" field'); + + throw 'control should not get here'; + } + + _logger.default.logResponse({ + method, + url, + result + }); + + var status = result.status || 200; + res.status(status); + + if (result.text) { + res.send(result.text); + return; + } + + if (result.location) { + res.set('Location', result.location); // Override the default expressjs response + // as it double encodes %encoded chars in URL + + if (!result.response) { + res.send('Found. Redirecting to ' + result.location); + return; + } + } + + if (result.headers) { + Object.keys(result.headers).forEach(header => { + res.set(header, result.headers[header]); + }); + } + + res.json(result.response); + }, error => { + clearSchemaCache(req); + next(error); + }).catch(e => { + clearSchemaCache(req); + + _logger.default.error(`Error generating response. ${(0, _util.inspect)(e)}`, { + error: e + }); + + next(e); + }); + } catch (e) { + clearSchemaCache(req); + + _logger.default.error(`Error handling request: ${(0, _util.inspect)(e)}`, { + error: e + }); + + next(e); + } + }; +} + +function maskSensitiveUrl(req) { + let maskUrl = req.originalUrl.toString(); + const shouldMaskUrl = req.method === 'GET' && req.originalUrl.includes('/login') && !req.originalUrl.includes('classes'); + + if (shouldMaskUrl) { + maskUrl = _logger.default.maskSensitiveUrl(maskUrl); + } + + return maskUrl; +} + +function clearSchemaCache(req) { + if (req.config && !req.config.enableSingleSchemaCache) { + req.config.database.schemaCache.clear(); + } +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Qcm9taXNlUm91dGVyLmpzIl0sIm5hbWVzIjpbIkxheWVyIiwicmVxdWlyZSIsInZhbGlkYXRlUGFyYW1ldGVyIiwia2V5IiwidmFsdWUiLCJtYXRjaCIsIlByb21pc2VSb3V0ZXIiLCJjb25zdHJ1Y3RvciIsInJvdXRlcyIsImFwcElkIiwibW91bnRSb3V0ZXMiLCJtZXJnZSIsInJvdXRlciIsInJvdXRlIiwicHVzaCIsIm1ldGhvZCIsInBhdGgiLCJoYW5kbGVycyIsImhhbmRsZXIiLCJsZW5ndGgiLCJyZXEiLCJyZWR1Y2UiLCJwcm9taXNlIiwidGhlbiIsIlByb21pc2UiLCJyZXNvbHZlIiwibGF5ZXIiLCJwYXJhbXMiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsIm1vdW50T250byIsImV4cHJlc3NBcHAiLCJ0b0xvd2VyQ2FzZSIsIm1ha2VFeHByZXNzSGFuZGxlciIsImNhbGwiLCJleHByZXNzUm91dGVyIiwiZXhwcmVzcyIsIlJvdXRlciIsInRyeVJvdXRlUmVxdWVzdCIsInJlcXVlc3QiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9KU09OIiwicmVqZWN0IiwicHJvbWlzZUhhbmRsZXIiLCJyZXMiLCJuZXh0IiwidXJsIiwibWFza1NlbnNpdGl2ZVVybCIsImJvZHkiLCJhc3NpZ24iLCJoZWFkZXJzIiwibG9nIiwibG9nUmVxdWVzdCIsInJlc3VsdCIsImNsZWFyU2NoZW1hQ2FjaGUiLCJyZXNwb25zZSIsImxvY2F0aW9uIiwidGV4dCIsImVycm9yIiwibG9nUmVzcG9uc2UiLCJzdGF0dXMiLCJzZW5kIiwic2V0IiwiaGVhZGVyIiwianNvbiIsImNhdGNoIiwiZSIsIm1hc2tVcmwiLCJvcmlnaW5hbFVybCIsInRvU3RyaW5nIiwic2hvdWxkTWFza1VybCIsImluY2x1ZGVzIiwiY29uZmlnIiwiZW5hYmxlU2luZ2xlU2NoZW1hQ2FjaGUiLCJkYXRhYmFzZSIsInNjaGVtYUNhY2hlIiwiY2xlYXIiXSwibWFwcGluZ3MiOiI7Ozs7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LFFBQWhCLENBQXlCLFNBQXpCLENBSEg7O0FBSUEsTUFBSUQsYUFBSixFQUFtQjtBQUNqQkgsSUFBQUEsT0FBTyxHQUFHaEIsZ0JBQUlKLGdCQUFKLENBQXFCb0IsT0FBckIsQ0FBVjtBQUNEOztBQUNELFNBQU9BLE9BQVA7QUFDRDs7QUFFRCxTQUFTYixnQkFBVCxDQUEwQnBDLEdBQTFCLEVBQStCO0FBQzdCLE1BQUlBLEdBQUcsQ0FBQ3NELE1BQUosSUFBYyxDQUFDdEQsR0FBRyxDQUFDc0QsTUFBSixDQUFXQyx1QkFBOUIsRUFBdUQ7QUFDckR2RCxJQUFBQSxHQUFHLENBQUNzRCxNQUFKLENBQVdFLFFBQVgsQ0FBb0JDLFdBQXBCLENBQWdDQyxLQUFoQztBQUNEO0FBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBBIHJvdXRlciB0aGF0IGlzIGJhc2VkIG9uIHByb21pc2VzIHJhdGhlciB0aGFuIHJlcS9yZXMvbmV4dC5cbi8vIFRoaXMgaXMgaW50ZW5kZWQgdG8gcmVwbGFjZSB0aGUgdXNlIG9mIGV4cHJlc3MuUm91dGVyIHRvIGhhbmRsZVxuLy8gc3Vic2VjdGlvbnMgb2YgdGhlIEFQSSBzdXJmYWNlLlxuLy8gVGhpcyB3aWxsIG1ha2UgaXQgZWFzaWVyIHRvIGhhdmUgbWV0aG9kcyBsaWtlICdiYXRjaCcgdGhhdFxuLy8gdGhlbXNlbHZlcyB1c2Ugb3VyIHJvdXRpbmcgaW5mb3JtYXRpb24sIHdpdGhvdXQgZGlzdHVyYmluZyBleHByZXNzXG4vLyBjb21wb25lbnRzIHRoYXQgZXh0ZXJuYWwgZGV2ZWxvcGVycyBtYXkgYmUgbW9kaWZ5aW5nLlxuXG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbmltcG9ydCBsb2cgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHsgaW5zcGVjdCB9IGZyb20gJ3V0aWwnO1xuY29uc3QgTGF5ZXIgPSByZXF1aXJlKCdleHByZXNzL2xpYi9yb3V0ZXIvbGF5ZXInKTtcblxuZnVuY3Rpb24gdmFsaWRhdGVQYXJhbWV0ZXIoa2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5ID09ICdjbGFzc05hbWUnKSB7XG4gICAgaWYgKHZhbHVlLm1hdGNoKC9fP1tBLVphLXpdW0EtWmEtel8wLTldKi8pKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICB9IGVsc2UgaWYgKGtleSA9PSAnb2JqZWN0SWQnKSB7XG4gICAgaWYgKHZhbHVlLm1hdGNoKC9bQS1aYS16MC05XSsvKSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvbWlzZVJvdXRlciB7XG4gIC8vIEVhY2ggZW50cnkgc2hvdWxkIGJlIGFuIG9iamVjdCB3aXRoOlxuICAvLyBwYXRoOiB0aGUgcGF0aCB0byByb3V0ZSwgaW4gZXhwcmVzcyBmb3JtYXRcbiAgLy8gbWV0aG9kOiB0aGUgSFRUUCBtZXRob2QgdGhhdCB0aGlzIHJvdXRlIGhhbmRsZXMuXG4gIC8vICAgTXVzdCBiZSBvbmUgb2Y6IFBPU1QsIEdFVCwgUFVULCBERUxFVEVcbiAgLy8gaGFuZGxlcjogYSBmdW5jdGlvbiB0aGF0IHRha2VzIHJlcXVlc3QsIGFuZCByZXR1cm5zIGEgcHJvbWlzZS5cbiAgLy8gICBTdWNjZXNzZnVsIGhhbmRsZXJzIHNob3VsZCByZXNvbHZlIHRvIGFuIG9iamVjdCB3aXRoIGZpZWxkczpcbiAgLy8gICAgIHN0YXR1czogb3B0aW9uYWwuIHRoZSBodHRwIHN0YXR1cyBjb2RlLiBkZWZhdWx0cyB0byAyMDBcbiAgLy8gICAgIHJlc3BvbnNlOiBhIGpzb24gb2JqZWN0IHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIHJlc3BvbnNlXG4gIC8vICAgICBsb2NhdGlvbjogb3B0aW9uYWwuIGEgbG9jYXRpb24gaGVhZGVyXG4gIGNvbnN0cnVjdG9yKHJvdXRlcyA9IFtdLCBhcHBJZCkge1xuICAgIHRoaXMucm91dGVzID0gcm91dGVzO1xuICAgIHRoaXMuYXBwSWQgPSBhcHBJZDtcbiAgICB0aGlzLm1vdW50Um91dGVzKCk7XG4gIH1cblxuICAvLyBMZWF2ZSB0aGUgb3Bwb3J0dW5pdHkgdG9cbiAgLy8gc3ViY2xhc3NlcyB0byBtb3VudCB0aGVpciByb3V0ZXMgYnkgb3ZlcnJpZGluZ1xuICBtb3VudFJvdXRlcygpIHt9XG5cbiAgLy8gTWVyZ2UgdGhlIHJvdXRlcyBpbnRvIHRoaXMgb25lXG4gIG1lcmdlKHJvdXRlcikge1xuICAgIGZvciAodmFyIHJvdXRlIG9mIHJvdXRlci5yb3V0ZXMpIHtcbiAgICAgIHRoaXMucm91dGVzLnB1c2gocm91dGUpO1xuICAgIH1cbiAgfVxuXG4gIHJvdXRlKG1ldGhvZCwgcGF0aCwgLi4uaGFuZGxlcnMpIHtcbiAgICBzd2l0Y2ggKG1ldGhvZCkge1xuICAgICAgY2FzZSAnUE9TVCc6XG4gICAgICBjYXNlICdHRVQnOlxuICAgICAgY2FzZSAnUFVUJzpcbiAgICAgIGNhc2UgJ0RFTEVURSc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgJ2Nhbm5vdCByb3V0ZSBtZXRob2Q6ICcgKyBtZXRob2Q7XG4gICAgfVxuXG4gICAgbGV0IGhhbmRsZXIgPSBoYW5kbGVyc1swXTtcblxuICAgIGlmIChoYW5kbGVycy5sZW5ndGggPiAxKSB7XG4gICAgICBoYW5kbGVyID0gZnVuY3Rpb24ocmVxKSB7XG4gICAgICAgIHJldHVybiBoYW5kbGVycy5yZWR1Y2UoKHByb21pc2UsIGhhbmRsZXIpID0+IHtcbiAgICAgICAgICByZXR1cm4gcHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGVyKHJlcSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sIFByb21pc2UucmVzb2x2ZSgpKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhpcy5yb3V0ZXMucHVzaCh7XG4gICAgICBwYXRoOiBwYXRoLFxuICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICBoYW5kbGVyOiBoYW5kbGVyLFxuICAgICAgbGF5ZXI6IG5ldyBMYXllcihwYXRoLCBudWxsLCBoYW5kbGVyKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYW4gb2JqZWN0IHdpdGg6XG4gIC8vICAgaGFuZGxlcjogdGhlIGhhbmRsZXIgdGhhdCBzaG91bGQgZGVhbCB3aXRoIHRoaXMgcmVxdWVzdFxuICAvLyAgIHBhcmFtczogYW55IDotcGFyYW1zIHRoYXQgZ290IHBhcnNlZCBmcm9tIHRoZSBwYXRoXG4gIC8vIFJldHVybnMgdW5kZWZpbmVkIGlmIHRoZXJlIGlzIG5vIG1hdGNoLlxuICBtYXRjaChtZXRob2QsIHBhdGgpIHtcbiAgICBmb3IgKHZhciByb3V0ZSBvZiB0aGlzLnJvdXRlcykge1xuICAgICAgaWYgKHJvdXRlLm1ldGhvZCAhPSBtZXRob2QpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBsYXllciA9IHJvdXRlLmxheWVyIHx8IG5ldyBMYXllcihyb3V0ZS5wYXRoLCBudWxsLCByb3V0ZS5oYW5kbGVyKTtcbiAgICAgIGNvbnN0IG1hdGNoID0gbGF5ZXIubWF0Y2gocGF0aCk7XG4gICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gbGF5ZXIucGFyYW1zO1xuICAgICAgICBPYmplY3Qua2V5cyhwYXJhbXMpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICBwYXJhbXNba2V5XSA9IHZhbGlkYXRlUGFyYW1ldGVyKGtleSwgcGFyYW1zW2tleV0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgcGFyYW1zOiBwYXJhbXMsIGhhbmRsZXI6IHJvdXRlLmhhbmRsZXIgfTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBNb3VudCB0aGUgcm91dGVzIG9uIHRoaXMgcm91dGVyIG9udG8gYW4gZXhwcmVzcyBhcHAgKG9yIGV4cHJlc3Mgcm91dGVyKVxuICBtb3VudE9udG8oZXhwcmVzc0FwcCkge1xuICAgIHRoaXMucm91dGVzLmZvckVhY2gocm91dGUgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kID0gcm91dGUubWV0aG9kLnRvTG93ZXJDYXNlKCk7XG4gICAgICBjb25zdCBoYW5kbGVyID0gbWFrZUV4cHJlc3NIYW5kbGVyKHRoaXMuYXBwSWQsIHJvdXRlLmhhbmRsZXIpO1xuICAgICAgZXhwcmVzc0FwcFttZXRob2RdLmNhbGwoZXhwcmVzc0FwcCwgcm91dGUucGF0aCwgaGFuZGxlcik7XG4gICAgfSk7XG4gICAgcmV0dXJuIGV4cHJlc3NBcHA7XG4gIH1cblxuICBleHByZXNzUm91dGVyKCkge1xuICAgIHJldHVybiB0aGlzLm1vdW50T250byhleHByZXNzLlJvdXRlcigpKTtcbiAgfVxuXG4gIHRyeVJvdXRlUmVxdWVzdChtZXRob2QsIHBhdGgsIHJlcXVlc3QpIHtcbiAgICB2YXIgbWF0Y2ggPSB0aGlzLm1hdGNoKG1ldGhvZCwgcGF0aCk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICdjYW5ub3Qgcm91dGUgJyArIG1ldGhvZCArICcgJyArIHBhdGhcbiAgICAgICk7XG4gICAgfVxuICAgIHJlcXVlc3QucGFyYW1zID0gbWF0Y2gucGFyYW1zO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBtYXRjaC5oYW5kbGVyKHJlcXVlc3QpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICB9KTtcbiAgfVxufVxuXG4vLyBBIGhlbHBlciBmdW5jdGlvbiB0byBtYWtlIGFuIGV4cHJlc3MgaGFuZGxlciBvdXQgb2YgYSBhIHByb21pc2Vcbi8vIGhhbmRsZXIuXG4vLyBFeHByZXNzIGhhbmRsZXJzIHNob3VsZCBuZXZlciB0aHJvdzsgaWYgYSBwcm9taXNlIGhhbmRsZXIgdGhyb3dzIHdlXG4vLyBqdXN0IHRyZWF0IGl0IGxpa2UgaXQgcmVzb2x2ZWQgdG8gYW4gZXJyb3IuXG5mdW5jdGlvbiBtYWtlRXhwcmVzc0hhbmRsZXIoYXBwSWQsIHByb21pc2VIYW5kbGVyKSB7XG4gIHJldHVybiBmdW5jdGlvbihyZXEsIHJlcywgbmV4dCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1cmwgPSBtYXNrU2Vuc2l0aXZlVXJsKHJlcSk7XG4gICAgICBjb25zdCBib2R5ID0gT2JqZWN0LmFzc2lnbih7fSwgcmVxLmJvZHkpO1xuICAgICAgY29uc3QgbWV0aG9kID0gcmVxLm1ldGhvZDtcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSByZXEuaGVhZGVycztcbiAgICAgIGxvZy5sb2dSZXF1ZXN0KHtcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICB1cmwsXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIGJvZHksXG4gICAgICB9KTtcbiAgICAgIHByb21pc2VIYW5kbGVyKHJlcSlcbiAgICAgICAgLnRoZW4oXG4gICAgICAgICAgcmVzdWx0ID0+IHtcbiAgICAgICAgICAgIGNsZWFyU2NoZW1hQ2FjaGUocmVxKTtcbiAgICAgICAgICAgIGlmICghcmVzdWx0LnJlc3BvbnNlICYmICFyZXN1bHQubG9jYXRpb24gJiYgIXJlc3VsdC50ZXh0KSB7XG4gICAgICAgICAgICAgIGxvZy5lcnJvcihcbiAgICAgICAgICAgICAgICAndGhlIGhhbmRsZXIgZGlkIG5vdCBpbmNsdWRlIGEgXCJyZXNwb25zZVwiIG9yIGEgXCJsb2NhdGlvblwiIGZpZWxkJ1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB0aHJvdyAnY29udHJvbCBzaG91bGQgbm90IGdldCBoZXJlJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbG9nLmxvZ1Jlc3BvbnNlKHsgbWV0aG9kLCB1cmwsIHJlc3VsdCB9KTtcblxuICAgICAgICAgICAgdmFyIHN0YXR1cyA9IHJlc3VsdC5zdGF0dXMgfHwgMjAwO1xuICAgICAgICAgICAgcmVzLnN0YXR1cyhzdGF0dXMpO1xuXG4gICAgICAgICAgICBpZiAocmVzdWx0LnRleHQpIHtcbiAgICAgICAgICAgICAgcmVzLnNlbmQocmVzdWx0LnRleHQpO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyZXN1bHQubG9jYXRpb24pIHtcbiAgICAgICAgICAgICAgcmVzLnNldCgnTG9jYXRpb24nLCByZXN1bHQubG9jYXRpb24pO1xuICAgICAgICAgICAgICAvLyBPdmVycmlkZSB0aGUgZGVmYXVsdCBleHByZXNzanMgcmVzcG9uc2VcbiAgICAgICAgICAgICAgLy8gYXMgaXQgZG91YmxlIGVuY29kZXMgJWVuY29kZWQgY2hhcnMgaW4gVVJMXG4gICAgICAgICAgICAgIGlmICghcmVzdWx0LnJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgcmVzLnNlbmQoJ0ZvdW5kLiBSZWRpcmVjdGluZyB0byAnICsgcmVzdWx0LmxvY2F0aW9uKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXN1bHQuaGVhZGVycykge1xuICAgICAgICAgICAgICBPYmplY3Qua2V5cyhyZXN1bHQuaGVhZGVycykuZm9yRWFjaChoZWFkZXIgPT4ge1xuICAgICAgICAgICAgICAgIHJlcy5zZXQoaGVhZGVyLCByZXN1bHQuaGVhZGVyc1toZWFkZXJdKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMuanNvbihyZXN1bHQucmVzcG9uc2UpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZXJyb3IgPT4ge1xuICAgICAgICAgICAgY2xlYXJTY2hlbWFDYWNoZShyZXEpO1xuICAgICAgICAgICAgbmV4dChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICApXG4gICAgICAgIC5jYXRjaChlID0+IHtcbiAgICAgICAgICBjbGVhclNjaGVtYUNhY2hlKHJlcSk7XG4gICAgICAgICAgbG9nLmVycm9yKGBFcnJvciBnZW5lcmF0aW5nIHJlc3BvbnNlLiAke2luc3BlY3QoZSl9YCwgeyBlcnJvcjogZSB9KTtcbiAgICAgICAgICBuZXh0KGUpO1xuICAgICAgICB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjbGVhclNjaGVtYUNhY2hlKHJlcSk7XG4gICAgICBsb2cuZXJyb3IoYEVycm9yIGhhbmRsaW5nIHJlcXVlc3Q6ICR7aW5zcGVjdChlKX1gLCB7IGVycm9yOiBlIH0pO1xuICAgICAgbmV4dChlKTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hc2tTZW5zaXRpdmVVcmwocmVxKSB7XG4gIGxldCBtYXNrVXJsID0gcmVxLm9yaWdpbmFsVXJsLnRvU3RyaW5nKCk7XG4gIGNvbnN0IHNob3VsZE1hc2tVcmwgPVxuICAgIHJlcS5tZXRob2QgPT09ICdHRVQnICYmXG4gICAgcmVxLm9yaWdpbmFsVXJsLmluY2x1ZGVzKCcvbG9naW4nKSAmJlxuICAgICFyZXEub3JpZ2luYWxVcmwuaW5jbHVkZXMoJ2NsYXNzZXMnKTtcbiAgaWYgKHNob3VsZE1hc2tVcmwpIHtcbiAgICBtYXNrVXJsID0gbG9nLm1hc2tTZW5zaXRpdmVVcmwobWFza1VybCk7XG4gIH1cbiAgcmV0dXJuIG1hc2tVcmw7XG59XG5cbmZ1bmN0aW9uIGNsZWFyU2NoZW1hQ2FjaGUocmVxKSB7XG4gIGlmIChyZXEuY29uZmlnICYmICFyZXEuY29uZmlnLmVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlKSB7XG4gICAgcmVxLmNvbmZpZy5kYXRhYmFzZS5zY2hlbWFDYWNoZS5jbGVhcigpO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Push/PushQueue.js b/lib/Push/PushQueue.js new file mode 100644 index 0000000000..dd5c0ed208 --- /dev/null +++ b/lib/Push/PushQueue.js @@ -0,0 +1,79 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PushQueue = void 0; + +var _ParseMessageQueue = require("../ParseMessageQueue"); + +var _rest = _interopRequireDefault(require("../rest")); + +var _utils = require("./utils"); + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const PUSH_CHANNEL = 'parse-server-push'; +const DEFAULT_BATCH_SIZE = 100; + +class PushQueue { + // config object of the publisher, right now it only contains the redisURL, + // but we may extend it later. + constructor(config = {}) { + this.channel = config.channel || PushQueue.defaultPushChannel(); + this.batchSize = config.batchSize || DEFAULT_BATCH_SIZE; + this.parsePublisher = _ParseMessageQueue.ParseMessageQueue.createPublisher(config); + } + + static defaultPushChannel() { + return `${_node.default.applicationId}-${PUSH_CHANNEL}`; + } + + enqueue(body, where, config, auth, pushStatus) { + const limit = this.batchSize; + where = (0, _utils.applyDeviceTokenExists)(where); // Order by objectId so no impact on the DB + + const order = 'objectId'; + return Promise.resolve().then(() => { + return _rest.default.find(config, auth, '_Installation', where, { + limit: 0, + count: true + }); + }).then(({ + results, + count + }) => { + if (!results || count == 0) { + return pushStatus.complete(); + } + + pushStatus.setRunning(Math.ceil(count / limit)); + let skip = 0; + + while (skip < count) { + const query = { + where, + limit, + skip, + order + }; + const pushWorkItem = { + body, + query, + pushStatus: { + objectId: pushStatus.objectId + }, + applicationId: config.applicationId + }; + this.parsePublisher.publish(this.channel, JSON.stringify(pushWorkItem)); + skip += limit; + } + }); + } + +} + +exports.PushQueue = PushQueue; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL1B1c2hRdWV1ZS5qcyJdLCJuYW1lcyI6WyJQVVNIX0NIQU5ORUwiLCJERUZBVUxUX0JBVENIX1NJWkUiLCJQdXNoUXVldWUiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsImNoYW5uZWwiLCJkZWZhdWx0UHVzaENoYW5uZWwiLCJiYXRjaFNpemUiLCJwYXJzZVB1Ymxpc2hlciIsIlBhcnNlTWVzc2FnZVF1ZXVlIiwiY3JlYXRlUHVibGlzaGVyIiwiUGFyc2UiLCJhcHBsaWNhdGlvbklkIiwiZW5xdWV1ZSIsImJvZHkiLCJ3aGVyZSIsImF1dGgiLCJwdXNoU3RhdHVzIiwibGltaXQiLCJvcmRlciIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsInJlc3QiLCJmaW5kIiwiY291bnQiLCJyZXN1bHRzIiwiY29tcGxldGUiLCJzZXRSdW5uaW5nIiwiTWF0aCIsImNlaWwiLCJza2lwIiwicXVlcnkiLCJwdXNoV29ya0l0ZW0iLCJvYmplY3RJZCIsInB1Ymxpc2giLCJKU09OIiwic3RyaW5naWZ5Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxNQUFNQSxZQUFZLEdBQUcsbUJBQXJCO0FBQ0EsTUFBTUMsa0JBQWtCLEdBQUcsR0FBM0I7O0FBRU8sTUFBTUMsU0FBTixDQUFnQjtBQUtyQjtBQUNBO0FBQ0FDLEVBQUFBLFdBQVcsQ0FBQ0MsTUFBVyxHQUFHLEVBQWYsRUFBbUI7QUFDNUIsU0FBS0MsT0FBTCxHQUFlRCxNQUFNLENBQUNDLE9BQVAsSUFBa0JILFNBQVMsQ0FBQ0ksa0JBQVYsRUFBakM7QUFDQSxTQUFLQyxTQUFMLEdBQWlCSCxNQUFNLENBQUNHLFNBQVAsSUFBb0JOLGtCQUFyQztBQUNBLFNBQUtPLGNBQUwsR0FBc0JDLHFDQUFrQkMsZUFBbEIsQ0FBa0NOLE1BQWxDLENBQXRCO0FBQ0Q7O0FBRUQsU0FBT0Usa0JBQVAsR0FBNEI7QUFDMUIsV0FBUSxHQUFFSyxjQUFNQyxhQUFjLElBQUdaLFlBQWEsRUFBOUM7QUFDRDs7QUFFRGEsRUFBQUEsT0FBTyxDQUFDQyxJQUFELEVBQU9DLEtBQVAsRUFBY1gsTUFBZCxFQUFzQlksSUFBdEIsRUFBNEJDLFVBQTVCLEVBQXdDO0FBQzdDLFVBQU1DLEtBQUssR0FBRyxLQUFLWCxTQUFuQjtBQUVBUSxJQUFBQSxLQUFLLEdBQUcsbUNBQXVCQSxLQUF2QixDQUFSLENBSDZDLENBSzdDOztBQUNBLFVBQU1JLEtBQUssR0FBRyxVQUFkO0FBQ0EsV0FBT0MsT0FBTyxDQUFDQyxPQUFSLEdBQ0pDLElBREksQ0FDQyxNQUFNO0FBQ1YsYUFBT0MsY0FBS0MsSUFBTCxDQUFVcEIsTUFBVixFQUFrQlksSUFBbEIsRUFBd0IsZUFBeEIsRUFBeUNELEtBQXpDLEVBQWdEO0FBQ3JERyxRQUFBQSxLQUFLLEVBQUUsQ0FEOEM7QUFFckRPLFFBQUFBLEtBQUssRUFBRTtBQUY4QyxPQUFoRCxDQUFQO0FBSUQsS0FOSSxFQU9KSCxJQVBJLENBT0MsQ0FBQztBQUFFSSxNQUFBQSxPQUFGO0FBQVdELE1BQUFBO0FBQVgsS0FBRCxLQUF3QjtBQUM1QixVQUFJLENBQUNDLE9BQUQsSUFBWUQsS0FBSyxJQUFJLENBQXpCLEVBQTRCO0FBQzFCLGVBQU9SLFVBQVUsQ0FBQ1UsUUFBWCxFQUFQO0FBQ0Q7O0FBQ0RWLE1BQUFBLFVBQVUsQ0FBQ1csVUFBWCxDQUFzQkMsSUFBSSxDQUFDQyxJQUFMLENBQVVMLEtBQUssR0FBR1AsS0FBbEIsQ0FBdEI7QUFDQSxVQUFJYSxJQUFJLEdBQUcsQ0FBWDs7QUFDQSxhQUFPQSxJQUFJLEdBQUdOLEtBQWQsRUFBcUI7QUFDbkIsY0FBTU8sS0FBSyxHQUFHO0FBQ1pqQixVQUFBQSxLQURZO0FBRVpHLFVBQUFBLEtBRlk7QUFHWmEsVUFBQUEsSUFIWTtBQUlaWixVQUFBQTtBQUpZLFNBQWQ7QUFPQSxjQUFNYyxZQUFZLEdBQUc7QUFDbkJuQixVQUFBQSxJQURtQjtBQUVuQmtCLFVBQUFBLEtBRm1CO0FBR25CZixVQUFBQSxVQUFVLEVBQUU7QUFBRWlCLFlBQUFBLFFBQVEsRUFBRWpCLFVBQVUsQ0FBQ2lCO0FBQXZCLFdBSE87QUFJbkJ0QixVQUFBQSxhQUFhLEVBQUVSLE1BQU0sQ0FBQ1E7QUFKSCxTQUFyQjtBQU1BLGFBQUtKLGNBQUwsQ0FBb0IyQixPQUFwQixDQUNFLEtBQUs5QixPQURQLEVBRUUrQixJQUFJLENBQUNDLFNBQUwsQ0FBZUosWUFBZixDQUZGO0FBSUFGLFFBQUFBLElBQUksSUFBSWIsS0FBUjtBQUNEO0FBQ0YsS0FqQ0ksQ0FBUDtBQWtDRDs7QUExRG9CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2VNZXNzYWdlUXVldWUgfSBmcm9tICcuLi9QYXJzZU1lc3NhZ2VRdWV1ZSc7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCB7IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMgfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcblxuY29uc3QgUFVTSF9DSEFOTkVMID0gJ3BhcnNlLXNlcnZlci1wdXNoJztcbmNvbnN0IERFRkFVTFRfQkFUQ0hfU0laRSA9IDEwMDtcblxuZXhwb3J0IGNsYXNzIFB1c2hRdWV1ZSB7XG4gIHBhcnNlUHVibGlzaGVyOiBPYmplY3Q7XG4gIGNoYW5uZWw6IFN0cmluZztcbiAgYmF0Y2hTaXplOiBOdW1iZXI7XG5cbiAgLy8gY29uZmlnIG9iamVjdCBvZiB0aGUgcHVibGlzaGVyLCByaWdodCBub3cgaXQgb25seSBjb250YWlucyB0aGUgcmVkaXNVUkwsXG4gIC8vIGJ1dCB3ZSBtYXkgZXh0ZW5kIGl0IGxhdGVyLlxuICBjb25zdHJ1Y3Rvcihjb25maWc6IGFueSA9IHt9KSB7XG4gICAgdGhpcy5jaGFubmVsID0gY29uZmlnLmNoYW5uZWwgfHwgUHVzaFF1ZXVlLmRlZmF1bHRQdXNoQ2hhbm5lbCgpO1xuICAgIHRoaXMuYmF0Y2hTaXplID0gY29uZmlnLmJhdGNoU2l6ZSB8fCBERUZBVUxUX0JBVENIX1NJWkU7XG4gICAgdGhpcy5wYXJzZVB1Ymxpc2hlciA9IFBhcnNlTWVzc2FnZVF1ZXVlLmNyZWF0ZVB1Ymxpc2hlcihjb25maWcpO1xuICB9XG5cbiAgc3RhdGljIGRlZmF1bHRQdXNoQ2hhbm5lbCgpIHtcbiAgICByZXR1cm4gYCR7UGFyc2UuYXBwbGljYXRpb25JZH0tJHtQVVNIX0NIQU5ORUx9YDtcbiAgfVxuXG4gIGVucXVldWUoYm9keSwgd2hlcmUsIGNvbmZpZywgYXV0aCwgcHVzaFN0YXR1cykge1xuICAgIGNvbnN0IGxpbWl0ID0gdGhpcy5iYXRjaFNpemU7XG5cbiAgICB3aGVyZSA9IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMod2hlcmUpO1xuXG4gICAgLy8gT3JkZXIgYnkgb2JqZWN0SWQgc28gbm8gaW1wYWN0IG9uIHRoZSBEQlxuICAgIGNvbnN0IG9yZGVyID0gJ29iamVjdElkJztcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHJlc3QuZmluZChjb25maWcsIGF1dGgsICdfSW5zdGFsbGF0aW9uJywgd2hlcmUsIHtcbiAgICAgICAgICBsaW1pdDogMCxcbiAgICAgICAgICBjb3VudDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKHsgcmVzdWx0cywgY291bnQgfSkgPT4ge1xuICAgICAgICBpZiAoIXJlc3VsdHMgfHwgY291bnQgPT0gMCkge1xuICAgICAgICAgIHJldHVybiBwdXNoU3RhdHVzLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcHVzaFN0YXR1cy5zZXRSdW5uaW5nKE1hdGguY2VpbChjb3VudCAvIGxpbWl0KSk7XG4gICAgICAgIGxldCBza2lwID0gMDtcbiAgICAgICAgd2hpbGUgKHNraXAgPCBjb3VudCkge1xuICAgICAgICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgICAgICAgd2hlcmUsXG4gICAgICAgICAgICBsaW1pdCxcbiAgICAgICAgICAgIHNraXAsXG4gICAgICAgICAgICBvcmRlcixcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgY29uc3QgcHVzaFdvcmtJdGVtID0ge1xuICAgICAgICAgICAgYm9keSxcbiAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgcHVzaFN0YXR1czogeyBvYmplY3RJZDogcHVzaFN0YXR1cy5vYmplY3RJZCB9LFxuICAgICAgICAgICAgYXBwbGljYXRpb25JZDogY29uZmlnLmFwcGxpY2F0aW9uSWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLnBhcnNlUHVibGlzaGVyLnB1Ymxpc2goXG4gICAgICAgICAgICB0aGlzLmNoYW5uZWwsXG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeShwdXNoV29ya0l0ZW0pXG4gICAgICAgICAgKTtcbiAgICAgICAgICBza2lwICs9IGxpbWl0O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/lib/Push/PushWorker.js b/lib/Push/PushWorker.js new file mode 100644 index 0000000000..94a677dca3 --- /dev/null +++ b/lib/Push/PushWorker.js @@ -0,0 +1,130 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PushWorker = void 0; + +var _deepcopy = _interopRequireDefault(require("deepcopy")); + +var _AdaptableController = _interopRequireDefault(require("../Controllers/AdaptableController")); + +var _Auth = require("../Auth"); + +var _Config = _interopRequireDefault(require("../Config")); + +var _PushAdapter = require("../Adapters/Push/PushAdapter"); + +var _rest = _interopRequireDefault(require("../rest")); + +var _StatusHandler = require("../StatusHandler"); + +var utils = _interopRequireWildcard(require("./utils")); + +var _ParseMessageQueue = require("../ParseMessageQueue"); + +var _PushQueue = require("./PushQueue"); + +var _logger = _interopRequireDefault(require("../logger")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// -disable-next +function groupByBadge(installations) { + return installations.reduce((map, installation) => { + const badge = installation.badge + ''; + map[badge] = map[badge] || []; + map[badge].push(installation); + return map; + }, {}); +} + +class PushWorker { + constructor(pushAdapter, subscriberConfig = {}) { + _AdaptableController.default.validateAdapter(pushAdapter, this, _PushAdapter.PushAdapter); + + this.adapter = pushAdapter; + this.channel = subscriberConfig.channel || _PushQueue.PushQueue.defaultPushChannel(); + this.subscriber = _ParseMessageQueue.ParseMessageQueue.createSubscriber(subscriberConfig); + + if (this.subscriber) { + const subscriber = this.subscriber; + subscriber.subscribe(this.channel); + subscriber.on('message', (channel, messageStr) => { + const workItem = JSON.parse(messageStr); + this.run(workItem); + }); + } + } + + run({ + body, + query, + pushStatus, + applicationId, + UTCOffset + }) { + const config = _Config.default.get(applicationId); + + const auth = (0, _Auth.master)(config); + const where = utils.applyDeviceTokenExists(query.where); + delete query.where; + pushStatus = (0, _StatusHandler.pushStatusHandler)(config, pushStatus.objectId); + return _rest.default.find(config, auth, '_Installation', where, query).then(({ + results + }) => { + if (results.length == 0) { + return; + } + + return this.sendToAdapter(body, results, pushStatus, config, UTCOffset); + }); + } + + sendToAdapter(body, installations, pushStatus, config, UTCOffset) { + // Check if we have locales in the push body + const locales = utils.getLocalesFromPush(body); + + if (locales.length > 0) { + // Get all tranformed bodies for each locale + const bodiesPerLocales = utils.bodiesPerLocales(body, locales); // Group installations on the specified locales (en, fr, default etc...) + + const grouppedInstallations = utils.groupByLocaleIdentifier(installations, locales); + const promises = Object.keys(grouppedInstallations).map(locale => { + const installations = grouppedInstallations[locale]; + const body = bodiesPerLocales[locale]; + return this.sendToAdapter(body, installations, pushStatus, config, UTCOffset); + }); + return Promise.all(promises); + } + + if (!utils.isPushIncrementing(body)) { + _logger.default.verbose(`Sending push to ${installations.length}`); + + return this.adapter.send(body, installations, pushStatus.objectId).then(results => { + return pushStatus.trackSent(results, UTCOffset).then(() => results); + }); + } // Collect the badges to reduce the # of calls + + + const badgeInstallationsMap = groupByBadge(installations); // Map the on the badges count and return the send result + + const promises = Object.keys(badgeInstallationsMap).map(badge => { + const payload = (0, _deepcopy.default)(body); + payload.data.badge = parseInt(badge); + const installations = badgeInstallationsMap[badge]; + return this.sendToAdapter(payload, installations, pushStatus, config, UTCOffset); + }); + return Promise.all(promises); + } + +} + +exports.PushWorker = PushWorker; +var _default = PushWorker; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL1B1c2hXb3JrZXIuanMiXSwibmFtZXMiOlsiZ3JvdXBCeUJhZGdlIiwiaW5zdGFsbGF0aW9ucyIsInJlZHVjZSIsIm1hcCIsImluc3RhbGxhdGlvbiIsImJhZGdlIiwicHVzaCIsIlB1c2hXb3JrZXIiLCJjb25zdHJ1Y3RvciIsInB1c2hBZGFwdGVyIiwic3Vic2NyaWJlckNvbmZpZyIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJ2YWxpZGF0ZUFkYXB0ZXIiLCJQdXNoQWRhcHRlciIsImFkYXB0ZXIiLCJjaGFubmVsIiwiUHVzaFF1ZXVlIiwiZGVmYXVsdFB1c2hDaGFubmVsIiwic3Vic2NyaWJlciIsIlBhcnNlTWVzc2FnZVF1ZXVlIiwiY3JlYXRlU3Vic2NyaWJlciIsInN1YnNjcmliZSIsIm9uIiwibWVzc2FnZVN0ciIsIndvcmtJdGVtIiwiSlNPTiIsInBhcnNlIiwicnVuIiwiYm9keSIsInF1ZXJ5IiwicHVzaFN0YXR1cyIsImFwcGxpY2F0aW9uSWQiLCJVVENPZmZzZXQiLCJjb25maWciLCJDb25maWciLCJnZXQiLCJhdXRoIiwid2hlcmUiLCJ1dGlscyIsImFwcGx5RGV2aWNlVG9rZW5FeGlzdHMiLCJvYmplY3RJZCIsInJlc3QiLCJmaW5kIiwidGhlbiIsInJlc3VsdHMiLCJsZW5ndGgiLCJzZW5kVG9BZGFwdGVyIiwibG9jYWxlcyIsImdldExvY2FsZXNGcm9tUHVzaCIsImJvZGllc1BlckxvY2FsZXMiLCJncm91cHBlZEluc3RhbGxhdGlvbnMiLCJncm91cEJ5TG9jYWxlSWRlbnRpZmllciIsInByb21pc2VzIiwiT2JqZWN0Iiwia2V5cyIsImxvY2FsZSIsIlByb21pc2UiLCJhbGwiLCJpc1B1c2hJbmNyZW1lbnRpbmciLCJsb2dnZXIiLCJ2ZXJib3NlIiwic2VuZCIsInRyYWNrU2VudCIsImJhZGdlSW5zdGFsbGF0aW9uc01hcCIsInBheWxvYWQiLCJkYXRhIiwicGFyc2VJbnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7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VUFBTW1CLHFCQUFxQixHQUFHL0QsWUFBWSxDQUFDQyxhQUFELENBQTFDLENBcENZLENBc0NaOztBQUNBLFVBQU1tRCxRQUFRLEdBQUdDLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZUyxxQkFBWixFQUFtQzVELEdBQW5DLENBQXVDRSxLQUFLLElBQUk7QUFDL0QsWUFBTTJELE9BQU8sR0FBRyx1QkFBU3BDLElBQVQsQ0FBaEI7QUFDQW9DLE1BQUFBLE9BQU8sQ0FBQ0MsSUFBUixDQUFhNUQsS0FBYixHQUFxQjZELFFBQVEsQ0FBQzdELEtBQUQsQ0FBN0I7QUFDQSxZQUFNSixhQUFhLEdBQUc4RCxxQkFBcUIsQ0FBQzFELEtBQUQsQ0FBM0M7QUFDQSxhQUFPLEtBQUt5QyxhQUFMLENBQ0xrQixPQURLLEVBRUwvRCxhQUZLLEVBR0w2QixVQUhLLEVBSUxHLE1BSkssRUFLTEQsU0FMSyxDQUFQO0FBT0QsS0FYZ0IsQ0FBakI7QUFZQSxXQUFPd0IsT0FBTyxDQUFDQyxHQUFSLENBQVlMLFFBQVosQ0FBUDtBQUNEOztBQS9GcUI7OztlQWtHVDdDLFUiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgZGVlcGNvcHkgZnJvbSAnZGVlcGNvcHknO1xuaW1wb3J0IEFkYXB0YWJsZUNvbnRyb2xsZXIgZnJvbSAnLi4vQ29udHJvbGxlcnMvQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBtYXN0ZXIgfSBmcm9tICcuLi9BdXRoJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi4vQ29uZmlnJztcbmltcG9ydCB7IFB1c2hBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvUHVzaC9QdXNoQWRhcHRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCB7IHB1c2hTdGF0dXNIYW5kbGVyIH0gZnJvbSAnLi4vU3RhdHVzSGFuZGxlcic7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IFBhcnNlTWVzc2FnZVF1ZXVlIH0gZnJvbSAnLi4vUGFyc2VNZXNzYWdlUXVldWUnO1xuaW1wb3J0IHsgUHVzaFF1ZXVlIH0gZnJvbSAnLi9QdXNoUXVldWUnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuXG5mdW5jdGlvbiBncm91cEJ5QmFkZ2UoaW5zdGFsbGF0aW9ucykge1xuICByZXR1cm4gaW5zdGFsbGF0aW9ucy5yZWR1Y2UoKG1hcCwgaW5zdGFsbGF0aW9uKSA9PiB7XG4gICAgY29uc3QgYmFkZ2UgPSBpbnN0YWxsYXRpb24uYmFkZ2UgKyAnJztcbiAgICBtYXBbYmFkZ2VdID0gbWFwW2JhZGdlXSB8fCBbXTtcbiAgICBtYXBbYmFkZ2VdLnB1c2goaW5zdGFsbGF0aW9uKTtcbiAgICByZXR1cm4gbWFwO1xuICB9LCB7fSk7XG59XG5cbmV4cG9ydCBjbGFzcyBQdXNoV29ya2VyIHtcbiAgc3Vic2NyaWJlcjogP2FueTtcbiAgYWRhcHRlcjogYW55O1xuICBjaGFubmVsOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHVzaEFkYXB0ZXI6IFB1c2hBZGFwdGVyLCBzdWJzY3JpYmVyQ29uZmlnOiBhbnkgPSB7fSkge1xuICAgIEFkYXB0YWJsZUNvbnRyb2xsZXIudmFsaWRhdGVBZGFwdGVyKHB1c2hBZGFwdGVyLCB0aGlzLCBQdXNoQWRhcHRlcik7XG4gICAgdGhpcy5hZGFwdGVyID0gcHVzaEFkYXB0ZXI7XG5cbiAgICB0aGlzLmNoYW5uZWwgPSBzdWJzY3JpYmVyQ29uZmlnLmNoYW5uZWwgfHwgUHVzaFF1ZXVlLmRlZmF1bHRQdXNoQ2hhbm5lbCgpO1xuICAgIHRoaXMuc3Vic2NyaWJlciA9IFBhcnNlTWVzc2FnZVF1ZXVlLmNyZWF0ZVN1YnNjcmliZXIoc3Vic2NyaWJlckNvbmZpZyk7XG4gICAgaWYgKHRoaXMuc3Vic2NyaWJlcikge1xuICAgICAgY29uc3Qgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlcjtcbiAgICAgIHN1YnNjcmliZXIuc3Vic2NyaWJlKHRoaXMuY2hhbm5lbCk7XG4gICAgICBzdWJzY3JpYmVyLm9uKCdtZXNzYWdlJywgKGNoYW5uZWwsIG1lc3NhZ2VTdHIpID0+IHtcbiAgICAgICAgY29uc3Qgd29ya0l0ZW0gPSBKU09OLnBhcnNlKG1lc3NhZ2VTdHIpO1xuICAgICAgICB0aGlzLnJ1bih3b3JrSXRlbSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBydW4oeyBib2R5LCBxdWVyeSwgcHVzaFN0YXR1cywgYXBwbGljYXRpb25JZCwgVVRDT2Zmc2V0IH06IGFueSk6IFByb21pc2U8Kj4ge1xuICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoYXBwbGljYXRpb25JZCk7XG4gICAgY29uc3QgYXV0aCA9IG1hc3Rlcihjb25maWcpO1xuICAgIGNvbnN0IHdoZXJlID0gdXRpbHMuYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyhxdWVyeS53aGVyZSk7XG4gICAgZGVsZXRlIHF1ZXJ5LndoZXJlO1xuICAgIHB1c2hTdGF0dXMgPSBwdXNoU3RhdHVzSGFuZGxlcihjb25maWcsIHB1c2hTdGF0dXMub2JqZWN0SWQpO1xuICAgIHJldHVybiByZXN0XG4gICAgICAuZmluZChjb25maWcsIGF1dGgsICdfSW5zdGFsbGF0aW9uJywgd2hlcmUsIHF1ZXJ5KVxuICAgICAgLnRoZW4oKHsgcmVzdWx0cyB9KSA9PiB7XG4gICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNlbmRUb0FkYXB0ZXIoYm9keSwgcmVzdWx0cywgcHVzaFN0YXR1cywgY29uZmlnLCBVVENPZmZzZXQpO1xuICAgICAgfSk7XG4gIH1cblxuICBzZW5kVG9BZGFwdGVyKFxuICAgIGJvZHk6IGFueSxcbiAgICBpbnN0YWxsYXRpb25zOiBhbnlbXSxcbiAgICBwdXNoU3RhdHVzOiBhbnksXG4gICAgY29uZmlnOiBDb25maWcsXG4gICAgVVRDT2Zmc2V0OiA/YW55XG4gICk6IFByb21pc2U8Kj4ge1xuICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbG9jYWxlcyBpbiB0aGUgcHVzaCBib2R5XG4gICAgY29uc3QgbG9jYWxlcyA9IHV0aWxzLmdldExvY2FsZXNGcm9tUHVzaChib2R5KTtcbiAgICBpZiAobG9jYWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBHZXQgYWxsIHRyYW5mb3JtZWQgYm9kaWVzIGZvciBlYWNoIGxvY2FsZVxuICAgICAgY29uc3QgYm9kaWVzUGVyTG9jYWxlcyA9IHV0aWxzLmJvZGllc1BlckxvY2FsZXMoYm9keSwgbG9jYWxlcyk7XG5cbiAgICAgIC8vIEdyb3VwIGluc3RhbGxhdGlvbnMgb24gdGhlIHNwZWNpZmllZCBsb2NhbGVzIChlbiwgZnIsIGRlZmF1bHQgZXRjLi4uKVxuICAgICAgY29uc3QgZ3JvdXBwZWRJbnN0YWxsYXRpb25zID0gdXRpbHMuZ3JvdXBCeUxvY2FsZUlkZW50aWZpZXIoXG4gICAgICAgIGluc3RhbGxhdGlvbnMsXG4gICAgICAgIGxvY2FsZXNcbiAgICAgICk7XG4gICAgICBjb25zdCBwcm9taXNlcyA9IE9iamVjdC5rZXlzKGdyb3VwcGVkSW5zdGFsbGF0aW9ucykubWFwKGxvY2FsZSA9PiB7XG4gICAgICAgIGNvbnN0IGluc3RhbGxhdGlvbnMgPSBncm91cHBlZEluc3RhbGxhdGlvbnNbbG9jYWxlXTtcbiAgICAgICAgY29uc3QgYm9keSA9IGJvZGllc1BlckxvY2FsZXNbbG9jYWxlXTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VuZFRvQWRhcHRlcihcbiAgICAgICAgICBib2R5LFxuICAgICAgICAgIGluc3RhbGxhdGlvbnMsXG4gICAgICAgICAgcHVzaFN0YXR1cyxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgVVRDT2Zmc2V0XG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgfVxuXG4gICAgaWYgKCF1dGlscy5pc1B1c2hJbmNyZW1lbnRpbmcoYm9keSkpIHtcbiAgICAgIGxvZ2dlci52ZXJib3NlKGBTZW5kaW5nIHB1c2ggdG8gJHtpbnN0YWxsYXRpb25zLmxlbmd0aH1gKTtcbiAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXJcbiAgICAgICAgLnNlbmQoYm9keSwgaW5zdGFsbGF0aW9ucywgcHVzaFN0YXR1cy5vYmplY3RJZClcbiAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgcmV0dXJuIHB1c2hTdGF0dXMudHJhY2tTZW50KHJlc3VsdHMsIFVUQ09mZnNldCkudGhlbigoKSA9PiByZXN1bHRzKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ29sbGVjdCB0aGUgYmFkZ2VzIHRvIHJlZHVjZSB0aGUgIyBvZiBjYWxsc1xuICAgIGNvbnN0IGJhZGdlSW5zdGFsbGF0aW9uc01hcCA9IGdyb3VwQnlCYWRnZShpbnN0YWxsYXRpb25zKTtcblxuICAgIC8vIE1hcCB0aGUgb24gdGhlIGJhZGdlcyBjb3VudCBhbmQgcmV0dXJuIHRoZSBzZW5kIHJlc3VsdFxuICAgIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LmtleXMoYmFkZ2VJbnN0YWxsYXRpb25zTWFwKS5tYXAoYmFkZ2UgPT4ge1xuICAgICAgY29uc3QgcGF5bG9hZCA9IGRlZXBjb3B5KGJvZHkpO1xuICAgICAgcGF5bG9hZC5kYXRhLmJhZGdlID0gcGFyc2VJbnQoYmFkZ2UpO1xuICAgICAgY29uc3QgaW5zdGFsbGF0aW9ucyA9IGJhZGdlSW5zdGFsbGF0aW9uc01hcFtiYWRnZV07XG4gICAgICByZXR1cm4gdGhpcy5zZW5kVG9BZGFwdGVyKFxuICAgICAgICBwYXlsb2FkLFxuICAgICAgICBpbnN0YWxsYXRpb25zLFxuICAgICAgICBwdXNoU3RhdHVzLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIFVUQ09mZnNldFxuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hXb3JrZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Push/utils.js b/lib/Push/utils.js new file mode 100644 index 0000000000..066c531c78 --- /dev/null +++ b/lib/Push/utils.js @@ -0,0 +1,159 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isPushIncrementing = isPushIncrementing; +exports.getLocalesFromPush = getLocalesFromPush; +exports.transformPushBodyForLocale = transformPushBodyForLocale; +exports.stripLocalesFromBody = stripLocalesFromBody; +exports.bodiesPerLocales = bodiesPerLocales; +exports.groupByLocaleIdentifier = groupByLocaleIdentifier; +exports.validatePushType = validatePushType; +exports.applyDeviceTokenExists = applyDeviceTokenExists; + +var _node = _interopRequireDefault(require("parse/node")); + +var _deepcopy = _interopRequireDefault(require("deepcopy")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function isPushIncrementing(body) { + if (!body.data || !body.data.badge) { + return false; + } + + const badge = body.data.badge; + + if (typeof badge == 'string' && badge.toLowerCase() == 'increment') { + return true; + } + + return typeof badge == 'object' && typeof badge.__op == 'string' && badge.__op.toLowerCase() == 'increment' && Number(badge.amount); +} + +const localizableKeys = ['alert', 'title']; + +function getLocalesFromPush(body) { + const data = body.data; + + if (!data) { + return []; + } + + return [...new Set(Object.keys(data).reduce((memo, key) => { + localizableKeys.forEach(localizableKey => { + if (key.indexOf(`${localizableKey}-`) == 0) { + memo.push(key.slice(localizableKey.length + 1)); + } + }); + return memo; + }, []))]; +} + +function transformPushBodyForLocale(body, locale) { + const data = body.data; + + if (!data) { + return body; + } + + body = (0, _deepcopy.default)(body); + localizableKeys.forEach(key => { + const localeValue = body.data[`${key}-${locale}`]; + + if (localeValue) { + body.data[key] = localeValue; + } + }); + return stripLocalesFromBody(body); +} + +function stripLocalesFromBody(body) { + if (!body.data) { + return body; + } + + Object.keys(body.data).forEach(key => { + localizableKeys.forEach(localizableKey => { + if (key.indexOf(`${localizableKey}-`) == 0) { + delete body.data[key]; + } + }); + }); + return body; +} + +function bodiesPerLocales(body, locales = []) { + // Get all tranformed bodies for each locale + const result = locales.reduce((memo, locale) => { + memo[locale] = transformPushBodyForLocale(body, locale); + return memo; + }, {}); // Set the default locale, with the stripped body + + result.default = stripLocalesFromBody(body); + return result; +} + +function groupByLocaleIdentifier(installations, locales = []) { + return installations.reduce((map, installation) => { + let added = false; + locales.forEach(locale => { + if (added) { + return; + } + + if (installation.localeIdentifier && installation.localeIdentifier.indexOf(locale) === 0) { + added = true; + map[locale] = map[locale] || []; + map[locale].push(installation); + } + }); + + if (!added) { + map.default.push(installation); + } + + return map; + }, { + default: [] + }); +} +/** + * Check whether the deviceType parameter in qury condition is valid or not. + * @param {Object} where A query condition + * @param {Array} validPushTypes An array of valid push types(string) + */ + + +function validatePushType(where = {}, validPushTypes = []) { + var deviceTypeField = where.deviceType || {}; + var deviceTypes = []; + + if (typeof deviceTypeField === 'string') { + deviceTypes.push(deviceTypeField); + } else if (Array.isArray(deviceTypeField['$in'])) { + deviceTypes.concat(deviceTypeField['$in']); + } + + for (var i = 0; i < deviceTypes.length; i++) { + var deviceType = deviceTypes[i]; + + if (validPushTypes.indexOf(deviceType) < 0) { + throw new _node.default.Error(_node.default.Error.PUSH_MISCONFIGURED, deviceType + ' is not supported push type.'); + } + } +} + +function applyDeviceTokenExists(where) { + where = (0, _deepcopy.default)(where); + + if (!Object.prototype.hasOwnProperty.call(where, 'deviceToken')) { + where['deviceToken'] = { + $exists: true + }; + } + + return where; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL3V0aWxzLmpzIl0sIm5hbWVzIjpbImlzUHVzaEluY3JlbWVudGluZyIsImJvZHkiLCJkYXRhIiwiYmFkZ2UiLCJ0b0xvd2VyQ2FzZSIsIl9fb3AiLCJOdW1iZXIiLCJhbW91bnQiLCJsb2NhbGl6YWJsZUtleXMiLCJnZXRMb2NhbGVzRnJvbVB1c2giLCJTZXQiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwibWVtbyIsImtleSIsImZvckVhY2giLCJsb2NhbGl6YWJsZUtleSIsImluZGV4T2YiLCJwdXNoIiwic2xpY2UiLCJsZW5ndGgiLCJ0cmFuc2Zvcm1QdXNoQm9keUZvckxvY2FsZSIsImxvY2FsZSIsImxvY2FsZVZhbHVlIiwic3RyaXBMb2NhbGVzRnJvbUJvZHkiLCJib2RpZXNQZXJMb2NhbGVzIiwibG9jYWxlcyIsInJlc3VsdCIsImRlZmF1bHQiLCJncm91cEJ5TG9jYWxlSWRlbnRpZmllciIsImluc3RhbGxhdGlvbnMiLCJtYXAiLCJpbnN0YWxsYXRpb24iLCJhZGRlZCIsImxvY2FsZUlkZW50aWZpZXIiLCJ2YWxpZGF0ZVB1c2hUeXBlIiwid2hlcmUiLCJ2YWxpZFB1c2hUeXBlcyIsImRldmljZVR5cGVGaWVsZCIsImRldmljZVR5cGUiLCJkZXZpY2VUeXBlcyIsIkFycmF5IiwiaXNBcnJheSIsImNvbmNhdCIsImkiLCJQYXJzZSIsIkVycm9yIiwiUFVTSF9NSVNDT05GSUdVUkVEIiwiYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIiRleGlzdHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFFTyxTQUFTQSxrQkFBVCxDQUE0QkMsSUFBNUIsRUFBa0M7QUFDdkMsTUFBSSxDQUFDQSxJQUFJLENBQUNDLElBQU4sSUFBYyxDQUFDRCxJQUFJLENBQUNDLElBQUwsQ0FBVUMsS0FBN0IsRUFBb0M7QUFDbEMsV0FBTyxLQUFQO0FB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TUFBQUEsT0FBTyxFQUFFO0FBQVgsS0FBdkI7QUFDRDs7QUFDRCxTQUFPaEIsS0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IGRlZXBjb3B5IGZyb20gJ2RlZXBjb3B5JztcblxuZXhwb3J0IGZ1bmN0aW9uIGlzUHVzaEluY3JlbWVudGluZyhib2R5KSB7XG4gIGlmICghYm9keS5kYXRhIHx8ICFib2R5LmRhdGEuYmFkZ2UpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBiYWRnZSA9IGJvZHkuZGF0YS5iYWRnZTtcbiAgaWYgKHR5cGVvZiBiYWRnZSA9PSAnc3RyaW5nJyAmJiBiYWRnZS50b0xvd2VyQ2FzZSgpID09ICdpbmNyZW1lbnQnKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gKFxuICAgIHR5cGVvZiBiYWRnZSA9PSAnb2JqZWN0JyAmJlxuICAgIHR5cGVvZiBiYWRnZS5fX29wID09ICdzdHJpbmcnICYmXG4gICAgYmFkZ2UuX19vcC50b0xvd2VyQ2FzZSgpID09ICdpbmNyZW1lbnQnICYmXG4gICAgTnVtYmVyKGJhZGdlLmFtb3VudClcbiAgKTtcbn1cblxuY29uc3QgbG9jYWxpemFibGVLZXlzID0gWydhbGVydCcsICd0aXRsZSddO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9jYWxlc0Zyb21QdXNoKGJvZHkpIHtcbiAgY29uc3QgZGF0YSA9IGJvZHkuZGF0YTtcbiAgaWYgKCFkYXRhKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiBbXG4gICAgLi4ubmV3IFNldChcbiAgICAgIE9iamVjdC5rZXlzKGRhdGEpLnJlZHVjZSgobWVtbywga2V5KSA9PiB7XG4gICAgICAgIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKGxvY2FsaXphYmxlS2V5ID0+IHtcbiAgICAgICAgICBpZiAoa2V5LmluZGV4T2YoYCR7bG9jYWxpemFibGVLZXl9LWApID09IDApIHtcbiAgICAgICAgICAgIG1lbW8ucHVzaChrZXkuc2xpY2UobG9jYWxpemFibGVLZXkubGVuZ3RoICsgMSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgfSwgW10pXG4gICAgKSxcbiAgXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybVB1c2hCb2R5Rm9yTG9jYWxlKGJvZHksIGxvY2FsZSkge1xuICBjb25zdCBkYXRhID0gYm9keS5kYXRhO1xuICBpZiAoIWRhdGEpIHtcbiAgICByZXR1cm4gYm9keTtcbiAgfVxuICBib2R5ID0gZGVlcGNvcHkoYm9keSk7XG4gIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKGtleSA9PiB7XG4gICAgY29uc3QgbG9jYWxlVmFsdWUgPSBib2R5LmRhdGFbYCR7a2V5fS0ke2xvY2FsZX1gXTtcbiAgICBpZiAobG9jYWxlVmFsdWUpIHtcbiAgICAgIGJvZHkuZGF0YVtrZXldID0gbG9jYWxlVmFsdWU7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHN0cmlwTG9jYWxlc0Zyb21Cb2R5KGJvZHkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBMb2NhbGVzRnJvbUJvZHkoYm9keSkge1xuICBpZiAoIWJvZHkuZGF0YSkge1xuICAgIHJldHVybiBib2R5O1xuICB9XG4gIE9iamVjdC5rZXlzKGJvZHkuZGF0YSkuZm9yRWFjaChrZXkgPT4ge1xuICAgIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKGxvY2FsaXphYmxlS2V5ID0+IHtcbiAgICAgIGlmIChrZXkuaW5kZXhPZihgJHtsb2NhbGl6YWJsZUtleX0tYCkgPT0gMCkge1xuICAgICAgICBkZWxldGUgYm9keS5kYXRhW2tleV07XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gYm9keTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJvZGllc1BlckxvY2FsZXMoYm9keSwgbG9jYWxlcyA9IFtdKSB7XG4gIC8vIEdldCBhbGwgdHJhbmZvcm1lZCBib2RpZXMgZm9yIGVhY2ggbG9jYWxlXG4gIGNvbnN0IHJlc3VsdCA9IGxvY2FsZXMucmVkdWNlKChtZW1vLCBsb2NhbGUpID0+IHtcbiAgICBtZW1vW2xvY2FsZV0gPSB0cmFuc2Zvcm1QdXNoQm9keUZvckxvY2FsZShib2R5LCBsb2NhbGUpO1xuICAgIHJldHVybiBtZW1vO1xuICB9LCB7fSk7XG4gIC8vIFNldCB0aGUgZGVmYXVsdCBsb2NhbGUsIHdpdGggdGhlIHN0cmlwcGVkIGJvZHlcbiAgcmVzdWx0LmRlZmF1bHQgPSBzdHJpcExvY2FsZXNGcm9tQm9keShib2R5KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwQnlMb2NhbGVJZGVudGlmaWVyKGluc3RhbGxhdGlvbnMsIGxvY2FsZXMgPSBbXSkge1xuICByZXR1cm4gaW5zdGFsbGF0aW9ucy5yZWR1Y2UoXG4gICAgKG1hcCwgaW5zdGFsbGF0aW9uKSA9PiB7XG4gICAgICBsZXQgYWRkZWQgPSBmYWxzZTtcbiAgICAgIGxvY2FsZXMuZm9yRWFjaChsb2NhbGUgPT4ge1xuICAgICAgICBpZiAoYWRkZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGluc3RhbGxhdGlvbi5sb2NhbGVJZGVudGlmaWVyICYmXG4gICAgICAgICAgaW5zdGFsbGF0aW9uLmxvY2FsZUlkZW50aWZpZXIuaW5kZXhPZihsb2NhbGUpID09PSAwXG4gICAgICAgICkge1xuICAgICAgICAgIGFkZGVkID0gdHJ1ZTtcbiAgICAgICAgICBtYXBbbG9jYWxlXSA9IG1hcFtsb2NhbGVdIHx8IFtdO1xuICAgICAgICAgIG1hcFtsb2NhbGVdLnB1c2goaW5zdGFsbGF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoIWFkZGVkKSB7XG4gICAgICAgIG1hcC5kZWZhdWx0LnB1c2goaW5zdGFsbGF0aW9uKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtYXA7XG4gICAgfSxcbiAgICB7IGRlZmF1bHQ6IFtdIH1cbiAgKTtcbn1cblxuLyoqXG4gKiBDaGVjayB3aGV0aGVyIHRoZSBkZXZpY2VUeXBlIHBhcmFtZXRlciBpbiBxdXJ5IGNvbmRpdGlvbiBpcyB2YWxpZCBvciBub3QuXG4gKiBAcGFyYW0ge09iamVjdH0gd2hlcmUgQSBxdWVyeSBjb25kaXRpb25cbiAqIEBwYXJhbSB7QXJyYXl9IHZhbGlkUHVzaFR5cGVzIEFuIGFycmF5IG9mIHZhbGlkIHB1c2ggdHlwZXMoc3RyaW5nKVxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVQdXNoVHlwZSh3aGVyZSA9IHt9LCB2YWxpZFB1c2hUeXBlcyA9IFtdKSB7XG4gIHZhciBkZXZpY2VUeXBlRmllbGQgPSB3aGVyZS5kZXZpY2VUeXBlIHx8IHt9O1xuICB2YXIgZGV2aWNlVHlwZXMgPSBbXTtcbiAgaWYgKHR5cGVvZiBkZXZpY2VUeXBlRmllbGQgPT09ICdzdHJpbmcnKSB7XG4gICAgZGV2aWNlVHlwZXMucHVzaChkZXZpY2VUeXBlRmllbGQpO1xuICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZGV2aWNlVHlwZUZpZWxkWyckaW4nXSkpIHtcbiAgICBkZXZpY2VUeXBlcy5jb25jYXQoZGV2aWNlVHlwZUZpZWxkWyckaW4nXSk7XG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZXZpY2VUeXBlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBkZXZpY2VUeXBlID0gZGV2aWNlVHlwZXNbaV07XG4gICAgaWYgKHZhbGlkUHVzaFR5cGVzLmluZGV4T2YoZGV2aWNlVHlwZSkgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgZGV2aWNlVHlwZSArICcgaXMgbm90IHN1cHBvcnRlZCBwdXNoIHR5cGUuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMod2hlcmUpIHtcbiAgd2hlcmUgPSBkZWVwY29weSh3aGVyZSk7XG4gIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHdoZXJlLCAnZGV2aWNlVG9rZW4nKSkge1xuICAgIHdoZXJlWydkZXZpY2VUb2tlbiddID0geyAkZXhpc3RzOiB0cnVlIH07XG4gIH1cbiAgcmV0dXJuIHdoZXJlO1xufVxuIl19 \ No newline at end of file diff --git a/lib/RestQuery.js b/lib/RestQuery.js new file mode 100644 index 0000000000..346752a3c1 --- /dev/null +++ b/lib/RestQuery.js @@ -0,0 +1,972 @@ +"use strict"; + +// An object that encapsulates everything we need to run a 'find' +// operation, encoded in the REST API format. +var SchemaController = require('./Controllers/SchemaController'); + +var Parse = require('parse/node').Parse; + +const triggers = require('./triggers'); + +const { + continueWhile +} = require('parse/lib/node/promiseUtils'); + +const AlwaysSelectedKeys = ['objectId', 'createdAt', 'updatedAt', 'ACL']; // restOptions can include: +// skip +// limit +// order +// count +// include +// keys +// excludeKeys +// redirectClassNameForKey +// readPreference +// includeReadPreference +// subqueryReadPreference + +function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, clientSDK, runAfterFind = true) { + this.config = config; + this.auth = auth; + this.className = className; + this.restWhere = restWhere; + this.restOptions = restOptions; + this.clientSDK = clientSDK; + this.runAfterFind = runAfterFind; + this.response = null; + this.findOptions = {}; + + if (!this.auth.isMaster) { + if (this.className == '_Session') { + if (!this.auth.user) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); + } + + this.restWhere = { + $and: [this.restWhere, { + user: { + __type: 'Pointer', + className: '_User', + objectId: this.auth.user.id + } + }] + }; + } + } + + this.doCount = false; + this.includeAll = false; // The format for this.include is not the same as the format for the + // include option - it's the paths we should include, in order, + // stored as arrays, taking into account that we need to include foo + // before including foo.bar. Also it should dedupe. + // For example, passing an arg of include=foo.bar,foo.baz could lead to + // this.include = [['foo'], ['foo', 'baz'], ['foo', 'bar']] + + this.include = []; // If we have keys, we probably want to force some includes (n-1 level) + // See issue: https://github.com/parse-community/parse-server/issues/3185 + + if (Object.prototype.hasOwnProperty.call(restOptions, 'keys')) { + const keysForInclude = restOptions.keys.split(',').filter(key => { + // At least 2 components + return key.split('.').length > 1; + }).map(key => { + // Slice the last component (a.b.c -> a.b) + // Otherwise we'll include one level too much. + return key.slice(0, key.lastIndexOf('.')); + }).join(','); // Concat the possibly present include string with the one from the keys + // Dedup / sorting is handle in 'include' case. + + if (keysForInclude.length > 0) { + if (!restOptions.include || restOptions.include.length == 0) { + restOptions.include = keysForInclude; + } else { + restOptions.include += ',' + keysForInclude; + } + } + } + + for (var option in restOptions) { + switch (option) { + case 'keys': + { + const keys = restOptions.keys.split(',').concat(AlwaysSelectedKeys); + this.keys = Array.from(new Set(keys)); + break; + } + + case 'excludeKeys': + { + const exclude = restOptions.excludeKeys.split(',').filter(k => AlwaysSelectedKeys.indexOf(k) < 0); + this.excludeKeys = Array.from(new Set(exclude)); + break; + } + + case 'count': + this.doCount = true; + break; + + case 'includeAll': + this.includeAll = true; + break; + + case 'distinct': + case 'pipeline': + case 'skip': + case 'limit': + case 'readPreference': + this.findOptions[option] = restOptions[option]; + break; + + case 'order': + var fields = restOptions.order.split(','); + this.findOptions.sort = fields.reduce((sortMap, field) => { + field = field.trim(); + + if (field === '$score') { + sortMap.score = { + $meta: 'textScore' + }; + } else if (field[0] == '-') { + sortMap[field.slice(1)] = -1; + } else { + sortMap[field] = 1; + } + + return sortMap; + }, {}); + break; + + case 'include': + { + const paths = restOptions.include.split(','); + + if (paths.includes('*')) { + this.includeAll = true; + break; + } // Load the existing includes (from keys) + + + const pathSet = paths.reduce((memo, path) => { + // Split each paths on . (a.b.c -> [a,b,c]) + // reduce to create all paths + // ([a,b,c] -> {a: true, 'a.b': true, 'a.b.c': true}) + return path.split('.').reduce((memo, path, index, parts) => { + memo[parts.slice(0, index + 1).join('.')] = true; + return memo; + }, memo); + }, {}); + this.include = Object.keys(pathSet).map(s => { + return s.split('.'); + }).sort((a, b) => { + return a.length - b.length; // Sort by number of components + }); + break; + } + + case 'redirectClassNameForKey': + this.redirectKey = restOptions.redirectClassNameForKey; + this.redirectClassName = null; + break; + + case 'includeReadPreference': + case 'subqueryReadPreference': + break; + + default: + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad option: ' + option); + } + } +} // A convenient method to perform all the steps of processing a query +// in order. +// Returns a promise for the response - an object with optional keys +// 'results' and 'count'. +// TODO: consolidate the replaceX functions + + +RestQuery.prototype.execute = function (executeOptions) { + return Promise.resolve().then(() => { + return this.buildRestWhere(); + }).then(() => { + return this.handleIncludeAll(); + }).then(() => { + return this.handleExcludeKeys(); + }).then(() => { + return this.runFind(executeOptions); + }).then(() => { + return this.runCount(); + }).then(() => { + return this.handleInclude(); + }).then(() => { + return this.runAfterFindTrigger(); + }).then(() => { + return this.response; + }); +}; + +RestQuery.prototype.each = function (callback) { + const { + config, + auth, + className, + restWhere, + restOptions, + clientSDK + } = this; // if the limit is set, use it + + restOptions.limit = restOptions.limit || 100; + restOptions.order = 'objectId'; + let finished = false; + return continueWhile(() => { + return !finished; + }, async () => { + const query = new RestQuery(config, auth, className, restWhere, restOptions, clientSDK); + const { + results + } = await query.execute(); + results.forEach(callback); + finished = results.length < restOptions.limit; + + if (!finished) { + restWhere.objectId = Object.assign({}, restWhere.objectId, { + $gt: results[results.length - 1].objectId + }); + } + }); +}; + +RestQuery.prototype.buildRestWhere = function () { + return Promise.resolve().then(() => { + return this.getUserAndRoleACL(); + }).then(() => { + return this.redirectClassNameForKey(); + }).then(() => { + return this.validateClientClassCreation(); + }).then(() => { + return this.replaceSelect(); + }).then(() => { + return this.replaceDontSelect(); + }).then(() => { + return this.replaceInQuery(); + }).then(() => { + return this.replaceNotInQuery(); + }).then(() => { + return this.replaceEquality(); + }); +}; // Uses the Auth object to get the list of roles, adds the user id + + +RestQuery.prototype.getUserAndRoleACL = function () { + if (this.auth.isMaster) { + return Promise.resolve(); + } + + this.findOptions.acl = ['*']; + + if (this.auth.user) { + return this.auth.getUserRoles().then(roles => { + this.findOptions.acl = this.findOptions.acl.concat(roles, [this.auth.user.id]); + return; + }); + } else { + return Promise.resolve(); + } +}; // Changes the className if redirectClassNameForKey is set. +// Returns a promise. + + +RestQuery.prototype.redirectClassNameForKey = function () { + if (!this.redirectKey) { + return Promise.resolve(); + } // We need to change the class name based on the schema + + + return this.config.database.redirectClassNameForKey(this.className, this.redirectKey).then(newClassName => { + this.className = newClassName; + this.redirectClassName = newClassName; + }); +}; // Validates this operation against the allowClientClassCreation config. + + +RestQuery.prototype.validateClientClassCreation = function () { + if (this.config.allowClientClassCreation === false && !this.auth.isMaster && SchemaController.systemClasses.indexOf(this.className) === -1) { + return this.config.database.loadSchema().then(schemaController => schemaController.hasClass(this.className)).then(hasClass => { + if (hasClass !== true) { + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'This user is not allowed to access ' + 'non-existent class: ' + this.className); + } + }); + } else { + return Promise.resolve(); + } +}; + +function transformInQuery(inQueryObject, className, results) { + var values = []; + + for (var result of results) { + values.push({ + __type: 'Pointer', + className: className, + objectId: result.objectId + }); + } + + delete inQueryObject['$inQuery']; + + if (Array.isArray(inQueryObject['$in'])) { + inQueryObject['$in'] = inQueryObject['$in'].concat(values); + } else { + inQueryObject['$in'] = values; + } +} // Replaces a $inQuery clause by running the subquery, if there is an +// $inQuery clause. +// The $inQuery clause turns into an $in with values that are just +// pointers to the objects returned in the subquery. + + +RestQuery.prototype.replaceInQuery = function () { + var inQueryObject = findObjectWithKey(this.restWhere, '$inQuery'); + + if (!inQueryObject) { + return; + } // The inQuery value must have precisely two keys - where and className + + + var inQueryValue = inQueryObject['$inQuery']; + + if (!inQueryValue.where || !inQueryValue.className) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'improper usage of $inQuery'); + } + + const additionalOptions = { + redirectClassNameForKey: inQueryValue.redirectClassNameForKey + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } else if (this.restOptions.readPreference) { + additionalOptions.readPreference = this.restOptions.readPreference; + } + + var subquery = new RestQuery(this.config, this.auth, inQueryValue.className, inQueryValue.where, additionalOptions); + return subquery.execute().then(response => { + transformInQuery(inQueryObject, subquery.className, response.results); // Recurse to repeat + + return this.replaceInQuery(); + }); +}; + +function transformNotInQuery(notInQueryObject, className, results) { + var values = []; + + for (var result of results) { + values.push({ + __type: 'Pointer', + className: className, + objectId: result.objectId + }); + } + + delete notInQueryObject['$notInQuery']; + + if (Array.isArray(notInQueryObject['$nin'])) { + notInQueryObject['$nin'] = notInQueryObject['$nin'].concat(values); + } else { + notInQueryObject['$nin'] = values; + } +} // Replaces a $notInQuery clause by running the subquery, if there is an +// $notInQuery clause. +// The $notInQuery clause turns into a $nin with values that are just +// pointers to the objects returned in the subquery. + + +RestQuery.prototype.replaceNotInQuery = function () { + var notInQueryObject = findObjectWithKey(this.restWhere, '$notInQuery'); + + if (!notInQueryObject) { + return; + } // The notInQuery value must have precisely two keys - where and className + + + var notInQueryValue = notInQueryObject['$notInQuery']; + + if (!notInQueryValue.where || !notInQueryValue.className) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'improper usage of $notInQuery'); + } + + const additionalOptions = { + redirectClassNameForKey: notInQueryValue.redirectClassNameForKey + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } else if (this.restOptions.readPreference) { + additionalOptions.readPreference = this.restOptions.readPreference; + } + + var subquery = new RestQuery(this.config, this.auth, notInQueryValue.className, notInQueryValue.where, additionalOptions); + return subquery.execute().then(response => { + transformNotInQuery(notInQueryObject, subquery.className, response.results); // Recurse to repeat + + return this.replaceNotInQuery(); + }); +}; // Used to get the deepest object from json using dot notation. + + +const getDeepestObjectFromKey = (json, key, idx, src) => { + if (key in json) { + return json[key]; + } + + src.splice(1); // Exit Early +}; + +const transformSelect = (selectObject, key, objects) => { + var values = []; + + for (var result of objects) { + values.push(key.split('.').reduce(getDeepestObjectFromKey, result)); + } + + delete selectObject['$select']; + + if (Array.isArray(selectObject['$in'])) { + selectObject['$in'] = selectObject['$in'].concat(values); + } else { + selectObject['$in'] = values; + } +}; // Replaces a $select clause by running the subquery, if there is a +// $select clause. +// The $select clause turns into an $in with values selected out of +// the subquery. +// Returns a possible-promise. + + +RestQuery.prototype.replaceSelect = function () { + var selectObject = findObjectWithKey(this.restWhere, '$select'); + + if (!selectObject) { + return; + } // The select value must have precisely two keys - query and key + + + var selectValue = selectObject['$select']; // iOS SDK don't send where if not set, let it pass + + if (!selectValue.query || !selectValue.key || typeof selectValue.query !== 'object' || !selectValue.query.className || Object.keys(selectValue).length !== 2) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'improper usage of $select'); + } + + const additionalOptions = { + redirectClassNameForKey: selectValue.query.redirectClassNameForKey + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } else if (this.restOptions.readPreference) { + additionalOptions.readPreference = this.restOptions.readPreference; + } + + var subquery = new RestQuery(this.config, this.auth, selectValue.query.className, selectValue.query.where, additionalOptions); + return subquery.execute().then(response => { + transformSelect(selectObject, selectValue.key, response.results); // Keep replacing $select clauses + + return this.replaceSelect(); + }); +}; + +const transformDontSelect = (dontSelectObject, key, objects) => { + var values = []; + + for (var result of objects) { + values.push(key.split('.').reduce(getDeepestObjectFromKey, result)); + } + + delete dontSelectObject['$dontSelect']; + + if (Array.isArray(dontSelectObject['$nin'])) { + dontSelectObject['$nin'] = dontSelectObject['$nin'].concat(values); + } else { + dontSelectObject['$nin'] = values; + } +}; // Replaces a $dontSelect clause by running the subquery, if there is a +// $dontSelect clause. +// The $dontSelect clause turns into an $nin with values selected out of +// the subquery. +// Returns a possible-promise. + + +RestQuery.prototype.replaceDontSelect = function () { + var dontSelectObject = findObjectWithKey(this.restWhere, '$dontSelect'); + + if (!dontSelectObject) { + return; + } // The dontSelect value must have precisely two keys - query and key + + + var dontSelectValue = dontSelectObject['$dontSelect']; + + if (!dontSelectValue.query || !dontSelectValue.key || typeof dontSelectValue.query !== 'object' || !dontSelectValue.query.className || Object.keys(dontSelectValue).length !== 2) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'improper usage of $dontSelect'); + } + + const additionalOptions = { + redirectClassNameForKey: dontSelectValue.query.redirectClassNameForKey + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } else if (this.restOptions.readPreference) { + additionalOptions.readPreference = this.restOptions.readPreference; + } + + var subquery = new RestQuery(this.config, this.auth, dontSelectValue.query.className, dontSelectValue.query.where, additionalOptions); + return subquery.execute().then(response => { + transformDontSelect(dontSelectObject, dontSelectValue.key, response.results); // Keep replacing $dontSelect clauses + + return this.replaceDontSelect(); + }); +}; + +const cleanResultAuthData = function (result) { + delete result.password; + + if (result.authData) { + Object.keys(result.authData).forEach(provider => { + if (result.authData[provider] === null) { + delete result.authData[provider]; + } + }); + + if (Object.keys(result.authData).length == 0) { + delete result.authData; + } + } +}; + +const replaceEqualityConstraint = constraint => { + if (typeof constraint !== 'object') { + return constraint; + } + + const equalToObject = {}; + let hasDirectConstraint = false; + let hasOperatorConstraint = false; + + for (const key in constraint) { + if (key.indexOf('$') !== 0) { + hasDirectConstraint = true; + equalToObject[key] = constraint[key]; + } else { + hasOperatorConstraint = true; + } + } + + if (hasDirectConstraint && hasOperatorConstraint) { + constraint['$eq'] = equalToObject; + Object.keys(equalToObject).forEach(key => { + delete constraint[key]; + }); + } + + return constraint; +}; + +RestQuery.prototype.replaceEquality = function () { + if (typeof this.restWhere !== 'object') { + return; + } + + for (const key in this.restWhere) { + this.restWhere[key] = replaceEqualityConstraint(this.restWhere[key]); + } +}; // Returns a promise for whether it was successful. +// Populates this.response with an object that only has 'results'. + + +RestQuery.prototype.runFind = function (options = {}) { + if (this.findOptions.limit === 0) { + this.response = { + results: [] + }; + return Promise.resolve(); + } + + const findOptions = Object.assign({}, this.findOptions); + + if (this.keys) { + findOptions.keys = this.keys.map(key => { + return key.split('.')[0]; + }); + } + + if (options.op) { + findOptions.op = options.op; + } + + return this.config.database.find(this.className, this.restWhere, findOptions, this.auth).then(results => { + if (this.className === '_User') { + for (var result of results) { + cleanResultAuthData(result); + } + } + + this.config.filesController.expandFilesInObject(this.config, results); + + if (this.redirectClassName) { + for (var r of results) { + r.className = this.redirectClassName; + } + } + + this.response = { + results: results + }; + }); +}; // Returns a promise for whether it was successful. +// Populates this.response.count with the count + + +RestQuery.prototype.runCount = function () { + if (!this.doCount) { + return; + } + + this.findOptions.count = true; + delete this.findOptions.skip; + delete this.findOptions.limit; + return this.config.database.find(this.className, this.restWhere, this.findOptions).then(c => { + this.response.count = c; + }); +}; // Augments this.response with all pointers on an object + + +RestQuery.prototype.handleIncludeAll = function () { + if (!this.includeAll) { + return; + } + + return this.config.database.loadSchema().then(schemaController => schemaController.getOneSchema(this.className)).then(schema => { + const includeFields = []; + const keyFields = []; + + for (const field in schema.fields) { + if (schema.fields[field].type && schema.fields[field].type === 'Pointer') { + includeFields.push([field]); + keyFields.push(field); + } + } // Add fields to include, keys, remove dups + + + this.include = [...new Set([...this.include, ...includeFields])]; // if this.keys not set, then all keys are already included + + if (this.keys) { + this.keys = [...new Set([...this.keys, ...keyFields])]; + } + }); +}; // Updates property `this.keys` to contain all keys but the ones unselected. + + +RestQuery.prototype.handleExcludeKeys = function () { + if (!this.excludeKeys) { + return; + } + + if (this.keys) { + this.keys = this.keys.filter(k => !this.excludeKeys.includes(k)); + return; + } + + return this.config.database.loadSchema().then(schemaController => schemaController.getOneSchema(this.className)).then(schema => { + const fields = Object.keys(schema.fields); + this.keys = fields.filter(k => !this.excludeKeys.includes(k)); + }); +}; // Augments this.response with data at the paths provided in this.include. + + +RestQuery.prototype.handleInclude = function () { + if (this.include.length == 0) { + return; + } + + var pathResponse = includePath(this.config, this.auth, this.response, this.include[0], this.restOptions); + + if (pathResponse.then) { + return pathResponse.then(newResponse => { + this.response = newResponse; + this.include = this.include.slice(1); + return this.handleInclude(); + }); + } else if (this.include.length > 0) { + this.include = this.include.slice(1); + return this.handleInclude(); + } + + return pathResponse; +}; //Returns a promise of a processed set of results + + +RestQuery.prototype.runAfterFindTrigger = function () { + if (!this.response) { + return; + } + + if (!this.runAfterFind) { + return; + } // Avoid doing any setup for triggers if there is no 'afterFind' trigger for this class. + + + const hasAfterFindHook = triggers.triggerExists(this.className, triggers.Types.afterFind, this.config.applicationId); + + if (!hasAfterFindHook) { + return Promise.resolve(); + } // Skip Aggregate and Distinct Queries + + + if (this.findOptions.pipeline || this.findOptions.distinct) { + return Promise.resolve(); + } // Run afterFind trigger and set the new results + + + return triggers.maybeRunAfterFindTrigger(triggers.Types.afterFind, this.auth, this.className, this.response.results, this.config).then(results => { + // Ensure we properly set the className back + if (this.redirectClassName) { + this.response.results = results.map(object => { + if (object instanceof Parse.Object) { + object = object.toJSON(); + } + + object.className = this.redirectClassName; + return object; + }); + } else { + this.response.results = results; + } + }); +}; // Adds included values to the response. +// Path is a list of field names. +// Returns a promise for an augmented response. + + +function includePath(config, auth, response, path, restOptions = {}) { + var pointers = findPointers(response.results, path); + + if (pointers.length == 0) { + return response; + } + + const pointersHash = {}; + + for (var pointer of pointers) { + if (!pointer) { + continue; + } + + const className = pointer.className; // only include the good pointers + + if (className) { + pointersHash[className] = pointersHash[className] || new Set(); + pointersHash[className].add(pointer.objectId); + } + } + + const includeRestOptions = {}; + + if (restOptions.keys) { + const keys = new Set(restOptions.keys.split(',')); + const keySet = Array.from(keys).reduce((set, key) => { + const keyPath = key.split('.'); + let i = 0; + + for (i; i < path.length; i++) { + if (path[i] != keyPath[i]) { + return set; + } + } + + if (i < keyPath.length) { + set.add(keyPath[i]); + } + + return set; + }, new Set()); + + if (keySet.size > 0) { + includeRestOptions.keys = Array.from(keySet).join(','); + } + } + + if (restOptions.includeReadPreference) { + includeRestOptions.readPreference = restOptions.includeReadPreference; + includeRestOptions.includeReadPreference = restOptions.includeReadPreference; + } else if (restOptions.readPreference) { + includeRestOptions.readPreference = restOptions.readPreference; + } + + const queryPromises = Object.keys(pointersHash).map(className => { + const objectIds = Array.from(pointersHash[className]); + let where; + + if (objectIds.length === 1) { + where = { + objectId: objectIds[0] + }; + } else { + where = { + objectId: { + $in: objectIds + } + }; + } + + var query = new RestQuery(config, auth, className, where, includeRestOptions); + return query.execute({ + op: 'get' + }).then(results => { + results.className = className; + return Promise.resolve(results); + }); + }); // Get the objects for all these object ids + + return Promise.all(queryPromises).then(responses => { + var replace = responses.reduce((replace, includeResponse) => { + for (var obj of includeResponse.results) { + obj.__type = 'Object'; + obj.className = includeResponse.className; + + if (obj.className == '_User' && !auth.isMaster) { + delete obj.sessionToken; + delete obj.authData; + } + + replace[obj.objectId] = obj; + } + + return replace; + }, {}); + var resp = { + results: replacePointers(response.results, path, replace) + }; + + if (response.count) { + resp.count = response.count; + } + + return resp; + }); +} // Object may be a list of REST-format object to find pointers in, or +// it may be a single object. +// If the path yields things that aren't pointers, this throws an error. +// Path is a list of fields to search into. +// Returns a list of pointers in REST format. + + +function findPointers(object, path) { + if (object instanceof Array) { + var answer = []; + + for (var x of object) { + answer = answer.concat(findPointers(x, path)); + } + + return answer; + } + + if (typeof object !== 'object' || !object) { + return []; + } + + if (path.length == 0) { + if (object === null || object.__type == 'Pointer') { + return [object]; + } + + return []; + } + + var subobject = object[path[0]]; + + if (!subobject) { + return []; + } + + return findPointers(subobject, path.slice(1)); +} // Object may be a list of REST-format objects to replace pointers +// in, or it may be a single object. +// Path is a list of fields to search into. +// replace is a map from object id -> object. +// Returns something analogous to object, but with the appropriate +// pointers inflated. + + +function replacePointers(object, path, replace) { + if (object instanceof Array) { + return object.map(obj => replacePointers(obj, path, replace)).filter(obj => typeof obj !== 'undefined'); + } + + if (typeof object !== 'object' || !object) { + return object; + } + + if (path.length === 0) { + if (object && object.__type === 'Pointer') { + return replace[object.objectId]; + } + + return object; + } + + var subobject = object[path[0]]; + + if (!subobject) { + return object; + } + + var newsub = replacePointers(subobject, path.slice(1), replace); + var answer = {}; + + for (var key in object) { + if (key == path[0]) { + answer[key] = newsub; + } else { + answer[key] = object[key]; + } + } + + return answer; +} // Finds a subobject that has the given key, if there is one. +// Returns undefined otherwise. + + +function findObjectWithKey(root, key) { + if (typeof root !== 'object') { + return; + } + + if (root instanceof Array) { + for (var item of root) { + const answer = findObjectWithKey(item, key); + + if (answer) { + return answer; + } + } + } + + if (root && root[key]) { + return root; + } + + for (var subkey in root) { + const answer = findObjectWithKey(root[subkey], key); + + if (answer) { + return answer; + } + } +} + +module.exports = RestQuery; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9SZXN0UXVlcnkuanMiXSwibmFtZXMiOlsiU2NoZW1hQ29udHJvbGxlciIsInJlcXVpcmUiLCJQYXJzZSIsInRyaWdnZXJzIiwiY29udGludWVXaGlsZSIsIkFsd2F5c1NlbGVjdGVkS2V5cyIsIlJlc3RRdWVyeSIsImNvbmZpZyIsImF1dGgiLCJjbGFzc05hbWUiLCJyZXN0V2hlcmUiLCJyZXN0T3B0aW9ucyIsImNsaWVudFNESyIsInJ1bkFmdGVyRmluZCIsInJlc3BvbnNlIiwiZmluZE9wdGlvbnMiLCJpc01hc3RlciIsInVzZXIiLCJFcnJvciIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsIiRhbmQiLCJfX3R5cGUiLCJvYmplY3RJZCIsImlkIiwiZG9Db3VudCIsImluY2x1ZGVBbGwiLCJpbmNsdWRlIiwiT2JqZWN0IiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwia2V5c0ZvckluY2x1ZGUiLCJrZXlzIiwic3BsaXQiLCJmaWx0ZXIiLCJrZXkiLCJsZW5ndGgiLCJtYXAiLCJzbGljZSIsImxhc3RJbmRleE9mIiwiam9pbiIsIm9wdGlvbiIsImNvbmNhdCIsIkFycmF5IiwiZnJvbSIsIlNldCIsImV4Y2x1ZGUiLCJleGNsdWRlS2V5cyIsImsiLCJpbmRleE9mIiwiZmllbGRzIiwib3JkZXIiLCJzb3J0IiwicmVkdWNlIiwic29ydE1hcCIsImZpZWxkIiwidHJpbSIsInNjb3JlIiwiJG1ldGEiLCJwYXRocyIsImluY2x1ZGVzIiwicGF0aFNldCIsIm1lbW8iLCJwYXRoIiwiaW5kZXgiLCJwYXJ0cyIsInMiLCJhIiwiYiIsInJlZGlyZWN0S2V5IiwicmVkaXJlY3RDbGFzc05hbWVGb3JLZXkiLCJyZWRpcmVjdENsYXNzTmFtZSIsIklOVkFMSURfSlNPTiIsImV4ZWN1dGUiLCJleGVjdXRlT3B0aW9ucyIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsImJ1aWxkUmVzdFdoZXJlIiwiaGFuZGxlSW5jbHVkZUFsbCIsImhhbmRsZUV4Y2x1ZGVLZXlzIiwicnVuRmluZCIsInJ1bkNvdW50IiwiaGFuZGxlSW5jbHVkZSIsInJ1bkFmdGVyRmluZFRyaWdnZXIiLCJlYWNoIiwiY2FsbGJhY2siLCJsaW1pdCIsImZpbmlzaGVkIiwicXVlcnkiLCJyZXN1bHRzIiwiZm9yRWFjaCIsImFzc2lnbiIsIiRndCIsImdldFVzZXJBbmRSb2xlQUNMIiwidmFsaWRhdGVDbGllbnRDbGFzc0NyZWF0aW9uIiwicmVwbGFjZVNlbGVjdCIsInJlcGxhY2VEb250U2VsZWN0IiwicmVwbGFjZUluUXVlcnkiLCJyZXBsYWNlTm90SW5RdWVyeSIsInJlcGxhY2VFcXVhbGl0eSIsImFjbCIsImdldFVzZXJSb2xlcyIsInJvbGVzIiwiZGF0YWJhc2UiLCJuZXdDbGFzc05hbWUiLCJhbGxvd0NsaWVudENsYXNzQ3JlYXRpb24iLCJzeXN0ZW1DbGFzc2VzIiwibG9hZFNjaGVtYSIsInNjaGVtYUNvbnRyb2xsZXIiLCJoYXNDbGFzcyIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJ0cmFuc2Zvcm1JblF1ZXJ5IiwiaW5RdWVyeU9iamVjdCIsInZhbHVlcyIsInJlc3VsdCIsInB1c2giLCJpc0FycmF5IiwiZmluZE9iamVjdFdpdGhLZXkiLCJpblF1ZXJ5VmFsdWUiLCJ3aGVyZSIsIklOVkFMSURfUVVFUlkiLCJhZGRpdGlvbmFsT3B0aW9ucyIsInN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UiLCJyZWFkUHJlZmVyZW5jZSIsInN1YnF1ZXJ5IiwidHJhbnNmb3JtTm90SW5RdWVyeSIsIm5vdEluUXVlcnlPYmplY3QiLCJub3RJblF1ZXJ5VmFsdWUiLCJnZXREZWVwZXN0T2JqZWN0RnJvbUtleSIsImpzb24iLCJpZHgiLCJzcmMiLCJzcGxpY2UiLCJ0cmFuc2Zvcm1TZWxlY3QiLCJzZWxlY3RPYmplY3QiLCJvYmplY3RzIiwic2VsZWN0VmFsdWUiLCJ0cmFuc2Zvcm1Eb250U2VsZWN0IiwiZG9udFNlbGVjdE9iamVjdCIsImRvbnRTZWxlY3RWYWx1ZSIsImNsZWFuUmVzdWx0QXV0aERhdGEiLCJwYXNzd29yZCIsImF1dGhEYXRhIiwicHJvdmlkZXIiLCJyZXBsYWNlRXF1YWxpdHlDb25zdHJhaW50IiwiY29uc3RyYWludCIsImVxdWFsVG9PYmplY3QiLCJoYXNEaXJlY3RDb25zdHJhaW50IiwiaGFzT3BlcmF0b3JDb25zdHJhaW50Iiwib3B0aW9ucyIsIm9wIiwiZmluZCIsImZpbGVzQ29udHJvbGxlciIsImV4cGFuZEZpbGVzSW5PYmplY3QiLCJyIiwiY291bnQiLCJza2lwIiwiYyIsImdldE9uZVNjaGVtYSIsInNjaGVtYSIsImluY2x1ZGVGaWVsZHMiLCJrZXlGaWVsZHMiLCJ0eXBlIiwicGF0aFJlc3BvbnNlIiwiaW5jbHVkZVBhdGgiLCJuZXdSZXNwb25zZSIsImhhc0FmdGVyRmluZEhvb2siLCJ0cmlnZ2VyRXhpc3RzIiwiVHlwZXMiLCJhZnRlckZpbmQiLCJhcHBsaWNhdGlvbklkIiwicGlwZWxpbmUiLCJkaXN0aW5jdCIsIm1heWJlUnVuQWZ0ZXJGaW5kVHJpZ2dlciIsIm9iamVjdCIsInRvSlNPTiIsInBvaW50ZXJzIiwiZmluZFBvaW50ZXJzIiwicG9pbnRlcnNIYXNoIiwicG9pbnRlciIsImFkZCIsImluY2x1ZGVSZXN0T3B0aW9ucyIsImtleVNldCIsInNldCIsImtleVBhdGgiLCJpIiwic2l6ZSIsImluY2x1ZGVSZWFkUHJlZmVyZW5jZSIsInF1ZXJ5UHJvbWlzZXMiLCJvYmplY3RJZHMiLCIkaW4iLCJhbGwiLCJyZXNwb25zZXMiLCJyZXBsYWNlIiwiaW5jbHVkZVJlc3BvbnNlIiwib2JqIiwic2Vzc2lvblRva2VuIiwicmVzcCIsInJlcGxhY2VQb2ludGVycyIsImFuc3dlciIsIngiLCJzdWJvYmplY3QiLCJuZXdzdWIiLCJyb290IiwiaXRlbSIsInN1YmtleSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUVBLElBQUlBLGdCQUFnQixHQUFHQyxPQUFPLENBQUMsZ0NBQUQsQ0FBOUI7O0FBQ0EsSUFBSUMsS0FB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QSxNQUFQO0FBQ0Q7QUFDRjtBQUNGOztBQUVETyxNQUFNLENBQUNDLE9BQVAsR0FBaUIxTSxTQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFuIG9iamVjdCB0aGF0IGVuY2Fwc3VsYXRlcyBldmVyeXRoaW5nIHdlIG5lZWQgdG8gcnVuIGEgJ2ZpbmQnXG4vLyBvcGVyYXRpb24sIGVuY29kZWQgaW4gdGhlIFJFU1QgQVBJIGZvcm1hdC5cblxudmFyIFNjaGVtYUNvbnRyb2xsZXIgPSByZXF1aXJlKCcuL0NvbnRyb2xsZXJzL1NjaGVtYUNvbnRyb2xsZXInKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IHRyaWdnZXJzID0gcmVxdWlyZSgnLi90cmlnZ2VycycpO1xuY29uc3QgeyBjb250aW51ZVdoaWxlIH0gPSByZXF1aXJlKCdwYXJzZS9saWIvbm9kZS9wcm9taXNlVXRpbHMnKTtcbmNvbnN0IEFsd2F5c1NlbGVjdGVkS2V5cyA9IFsnb2JqZWN0SWQnLCAnY3JlYXRlZEF0JywgJ3VwZGF0ZWRBdCcsICdBQ0wnXTtcbi8vIHJlc3RPcHRpb25zIGNhbiBpbmNsdWRlOlxuLy8gICBza2lwXG4vLyAgIGxpbWl0XG4vLyAgIG9yZGVyXG4vLyAgIGNvdW50XG4vLyAgIGluY2x1ZGVcbi8vICAga2V5c1xuLy8gICBleGNsdWRlS2V5c1xuLy8gICByZWRpcmVjdENsYXNzTmFtZUZvcktleVxuLy8gICByZWFkUHJlZmVyZW5jZVxuLy8gICBpbmNsdWRlUmVhZFByZWZlcmVuY2Vcbi8vICAgc3VicXVlcnlSZWFkUHJlZmVyZW5jZVxuZnVuY3Rpb24gUmVzdFF1ZXJ5KFxuICBjb25maWcsXG4gIGF1dGgsXG4gIGNsYXNzTmFtZSxcbiAgcmVzdFdoZXJlID0ge30sXG4gIHJlc3RPcHRpb25zID0ge30sXG4gIGNsaWVudFNESyxcbiAgcnVuQWZ0ZXJGaW5kID0gdHJ1ZVxuKSB7XG4gIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICB0aGlzLmF1dGggPSBhdXRoO1xuICB0aGlzLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgdGhpcy5yZXN0V2hlcmUgPSByZXN0V2hlcmU7XG4gIHRoaXMucmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucztcbiAgdGhpcy5jbGllbnRTREsgPSBjbGllbnRTREs7XG4gIHRoaXMucnVuQWZ0ZXJGaW5kID0gcnVuQWZ0ZXJGaW5kO1xuICB0aGlzLnJlc3BvbnNlID0gbnVsbDtcbiAgdGhpcy5maW5kT3B0aW9ucyA9IHt9O1xuXG4gIGlmICghdGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgaWYgKHRoaXMuY2xhc3NOYW1lID09ICdfU2Vzc2lvbicpIHtcbiAgICAgIGlmICghdGhpcy5hdXRoLnVzZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdGhpcy5yZXN0V2hlcmUgPSB7XG4gICAgICAgICRhbmQ6IFtcbiAgICAgICAgICB0aGlzLnJlc3RXaGVyZSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB1c2VyOiB7XG4gICAgICAgICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgICAgICBjbGFzc05hbWU6ICdfVXNlcicsXG4gICAgICAgICAgICAgIG9iamVjdElkOiB0aGlzLmF1dGgudXNlci5pZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgdGhpcy5kb0NvdW50ID0gZmFsc2U7XG4gIHRoaXMuaW5jbHVkZUFsbCA9IGZhbHNlO1xuXG4gIC8vIFRoZSBmb3JtYXQgZm9yIHRoaXMuaW5jbHVkZSBpcyBub3QgdGhlIHNhbWUgYXMgdGhlIGZvcm1hdCBmb3IgdGhlXG4gIC8vIGluY2x1ZGUgb3B0aW9uIC0gaXQncyB0aGUgcGF0aHMgd2Ugc2hvdWxkIGluY2x1ZGUsIGluIG9yZGVyLFxuICAvLyBzdG9yZWQgYXMgYXJyYXlzLCB0YWtpbmcgaW50byBhY2NvdW50IHRoYXQgd2UgbmVlZCB0byBpbmNsdWRlIGZvb1xuICAvLyBiZWZvcmUgaW5jbHVkaW5nIGZvby5iYXIuIEFsc28gaXQgc2hvdWxkIGRlZHVwZS5cbiAgLy8gRm9yIGV4YW1wbGUsIHBhc3NpbmcgYW4gYXJnIG9mIGluY2x1ZGU9Zm9vLmJhcixmb28uYmF6IGNvdWxkIGxlYWQgdG9cbiAgLy8gdGhpcy5pbmNsdWRlID0gW1snZm9vJ10sIFsnZm9vJywgJ2JheiddLCBbJ2ZvbycsICdiYXInXV1cbiAgdGhpcy5pbmNsdWRlID0gW107XG5cbiAgLy8gSWYgd2UgaGF2ZSBrZXlzLCB3ZSBwcm9iYWJseSB3YW50IHRvIGZvcmNlIHNvbWUgaW5jbHVkZXMgKG4tMSBsZXZlbClcbiAgLy8gU2VlIGlzc3VlOiBodHRwczovL2dpdGh1Yi5jb20vcGFyc2UtY29tbXVuaXR5L3BhcnNlLXNlcnZlci9pc3N1ZXMvMzE4NVxuICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3RPcHRpb25zLCAna2V5cycpKSB7XG4gICAgY29uc3Qga2V5c0ZvckluY2x1ZGUgPSByZXN0T3B0aW9ucy5rZXlzXG4gICAgICAuc3BsaXQoJywnKVxuICAgICAgLmZpbHRlcihrZXkgPT4ge1xuICAgICAgICAvLyBBdCBsZWFzdCAyIGNvbXBvbmVudHNcbiAgICAgICAgcmV0dXJuIGtleS5zcGxpdCgnLicpLmxlbmd0aCA+IDE7XG4gICAgICB9KVxuICAgICAgLm1hcChrZXkgPT4ge1xuICAgICAgICAvLyBTbGljZSB0aGUgbGFzdCBjb21wb25lbnQgKGEuYi5jIC0+IGEuYilcbiAgICAgICAgLy8gT3RoZXJ3aXNlIHdlJ2xsIGluY2x1ZGUgb25lIGxldmVsIHRvbyBtdWNoLlxuICAgICAgICByZXR1cm4ga2V5LnNsaWNlKDAsIGtleS5sYXN0SW5kZXhPZignLicpKTtcbiAgICAgIH0pXG4gICAgICAuam9pbignLCcpO1xuXG4gICAgLy8gQ29uY2F0IHRoZSBwb3NzaWJseSBwcmVzZW50IGluY2x1ZGUgc3RyaW5nIHdpdGggdGhlIG9uZSBmcm9tIHRoZSBrZXlzXG4gICAgLy8gRGVkdXAgLyBzb3J0aW5nIGlzIGhhbmRsZSBpbiAnaW5jbHVkZScgY2FzZS5cbiAgICBpZiAoa2V5c0ZvckluY2x1ZGUubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKCFyZXN0T3B0aW9ucy5pbmNsdWRlIHx8IHJlc3RPcHRpb25zLmluY2x1ZGUubGVuZ3RoID09IDApIHtcbiAgICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZSA9IGtleXNGb3JJbmNsdWRlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZSArPSAnLCcgKyBrZXlzRm9ySW5jbHVkZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmb3IgKHZhciBvcHRpb24gaW4gcmVzdE9wdGlvbnMpIHtcbiAgICBzd2l0Y2ggKG9wdGlvbikge1xuICAgICAgY2FzZSAna2V5cyc6IHtcbiAgICAgICAgY29uc3Qga2V5cyA9IHJlc3RPcHRpb25zLmtleXMuc3BsaXQoJywnKS5jb25jYXQoQWx3YXlzU2VsZWN0ZWRLZXlzKTtcbiAgICAgICAgdGhpcy5rZXlzID0gQXJyYXkuZnJvbShuZXcgU2V0KGtleXMpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdleGNsdWRlS2V5cyc6IHtcbiAgICAgICAgY29uc3QgZXhjbHVkZSA9IHJlc3RPcHRpb25zLmV4Y2x1ZGVLZXlzXG4gICAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgICAuZmlsdGVyKGsgPT4gQWx3YXlzU2VsZWN0ZWRLZXlzLmluZGV4T2YoaykgPCAwKTtcbiAgICAgICAgdGhpcy5leGNsdWRlS2V5cyA9IEFycmF5LmZyb20obmV3IFNldChleGNsdWRlKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnY291bnQnOlxuICAgICAgICB0aGlzLmRvQ291bnQgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2luY2x1ZGVBbGwnOlxuICAgICAgICB0aGlzLmluY2x1ZGVBbGwgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Rpc3RpbmN0JzpcbiAgICAgIGNhc2UgJ3BpcGVsaW5lJzpcbiAgICAgIGNhc2UgJ3NraXAnOlxuICAgICAgY2FzZSAnbGltaXQnOlxuICAgICAgY2FzZSAncmVhZFByZWZlcmVuY2UnOlxuICAgICAgICB0aGlzLmZpbmRPcHRpb25zW29wdGlvbl0gPSByZXN0T3B0aW9uc1tvcHRpb25dO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ29yZGVyJzpcbiAgICAgICAgdmFyIGZpZWxkcyA9IHJlc3RPcHRpb25zLm9yZGVyLnNwbGl0KCcsJyk7XG4gICAgICAgIHRoaXMuZmluZE9wdGlvbnMuc29ydCA9IGZpZWxkcy5yZWR1Y2UoKHNvcnRNYXAsIGZpZWxkKSA9PiB7XG4gICAgICAgICAgZmllbGQgPSBmaWVsZC50cmltKCk7XG4gICAgICAgICAgaWYgKGZpZWxkID09PSAnJHNjb3JlJykge1xuICAgICAgICAgICAgc29ydE1hcC5zY29yZSA9IHsgJG1ldGE6ICd0ZXh0U2NvcmUnIH07XG4gICAgICAgICAgfSBlbHNlIGlmIChmaWVsZFswXSA9PSAnLScpIHtcbiAgICAgICAgICAgIHNvcnRNYXBbZmllbGQuc2xpY2UoMSldID0gLTE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNvcnRNYXBbZmllbGRdID0gMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHNvcnRNYXA7XG4gICAgICAgIH0sIHt9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbmNsdWRlJzoge1xuICAgICAgICBjb25zdCBwYXRocyA9IHJlc3RPcHRpb25zLmluY2x1ZGUuc3BsaXQoJywnKTtcbiAgICAgICAgaWYgKHBhdGhzLmluY2x1ZGVzKCcqJykpIHtcbiAgICAgICAgICB0aGlzLmluY2x1ZGVBbGwgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIC8vIExvYWQgdGhlIGV4aXN0aW5nIGluY2x1ZGVzIChmcm9tIGtleXMpXG4gICAgICAgIGNvbnN0IHBhdGhTZXQgPSBwYXRocy5yZWR1Y2UoKG1lbW8sIHBhdGgpID0+IHtcbiAgICAgICAgICAvLyBTcGxpdCBlYWNoIHBhdGhzIG9uIC4gKGEuYi5jIC0+IFthLGIsY10pXG4gICAgICAgICAgLy8gcmVkdWNlIHRvIGNyZWF0ZSBhbGwgcGF0aHNcbiAgICAgICAgICAvLyAoW2EsYixjXSAtPiB7YTogdHJ1ZSwgJ2EuYic6IHRydWUsICdhLmIuYyc6IHRydWV9KVxuICAgICAgICAgIHJldHVybiBwYXRoLnNwbGl0KCcuJykucmVkdWNlKChtZW1vLCBwYXRoLCBpbmRleCwgcGFydHMpID0+IHtcbiAgICAgICAgICAgIG1lbW9bcGFydHMuc2xpY2UoMCwgaW5kZXggKyAxKS5qb2luKCcuJyldID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgICAgIH0sIG1lbW8pO1xuICAgICAgICB9LCB7fSk7XG5cbiAgICAgICAgdGhpcy5pbmNsdWRlID0gT2JqZWN0LmtleXMocGF0aFNldClcbiAgICAgICAgICAubWFwKHMgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHMuc3BsaXQoJy4nKTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYS5sZW5ndGggLSBiLmxlbmd0aDsgLy8gU29ydCBieSBudW1iZXIgb2YgY29tcG9uZW50c1xuICAgICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3JlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5JzpcbiAgICAgICAgdGhpcy5yZWRpcmVjdEtleSA9IHJlc3RPcHRpb25zLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5O1xuICAgICAgICB0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lID0gbnVsbDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbmNsdWRlUmVhZFByZWZlcmVuY2UnOlxuICAgICAgY2FzZSAnc3VicXVlcnlSZWFkUHJlZmVyZW5jZSc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAnYmFkIG9wdGlvbjogJyArIG9wdGlvblxuICAgICAgICApO1xuICAgIH1cbiAgfVxufVxuXG4vLyBBIGNvbnZlbmllbnQgbWV0aG9kIHRvIHBlcmZvcm0gYWxsIHRoZSBzdGVwcyBvZiBwcm9jZXNzaW5nIGEgcXVlcnlcbi8vIGluIG9yZGVyLlxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSByZXNwb25zZSAtIGFuIG9iamVjdCB3aXRoIG9wdGlvbmFsIGtleXNcbi8vICdyZXN1bHRzJyBhbmQgJ2NvdW50Jy5cbi8vIFRPRE86IGNvbnNvbGlkYXRlIHRoZSByZXBsYWNlWCBmdW5jdGlvbnNcblJlc3RRdWVyeS5wcm90b3R5cGUuZXhlY3V0ZSA9IGZ1bmN0aW9uKGV4ZWN1dGVPcHRpb25zKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmJ1aWxkUmVzdFdoZXJlKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVJbmNsdWRlQWxsKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVFeGNsdWRlS2V5cygpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucnVuRmluZChleGVjdXRlT3B0aW9ucyk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5ydW5Db3VudCgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlSW5jbHVkZSgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucnVuQWZ0ZXJGaW5kVHJpZ2dlcigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVzcG9uc2U7XG4gICAgfSk7XG59O1xuXG5SZXN0UXVlcnkucHJvdG90eXBlLmVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICBjb25zdCB7IGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUsIHJlc3RPcHRpb25zLCBjbGllbnRTREsgfSA9IHRoaXM7XG4gIC8vIGlmIHRoZSBsaW1pdCBpcyBzZXQsIHVzZSBpdFxuICByZXN0T3B0aW9ucy5saW1pdCA9IHJlc3RPcHRpb25zLmxpbWl0IHx8IDEwMDtcbiAgcmVzdE9wdGlvbnMub3JkZXIgPSAnb2JqZWN0SWQnO1xuICBsZXQgZmluaXNoZWQgPSBmYWxzZTtcblxuICByZXR1cm4gY29udGludWVXaGlsZShcbiAgICAoKSA9PiB7XG4gICAgICByZXR1cm4gIWZpbmlzaGVkO1xuICAgIH0sXG4gICAgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGF1dGgsXG4gICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgcmVzdFdoZXJlLFxuICAgICAgICByZXN0T3B0aW9ucyxcbiAgICAgICAgY2xpZW50U0RLXG4gICAgICApO1xuICAgICAgY29uc3QgeyByZXN1bHRzIH0gPSBhd2FpdCBxdWVyeS5leGVjdXRlKCk7XG4gICAgICByZXN1bHRzLmZvckVhY2goY2FsbGJhY2spO1xuICAgICAgZmluaXNoZWQgPSByZXN1bHRzLmxlbmd0aCA8IHJlc3RPcHRpb25zLmxpbWl0O1xuICAgICAgaWYgKCFmaW5pc2hlZCkge1xuICAgICAgICByZXN0V2hlcmUub2JqZWN0SWQgPSBPYmplY3QuYXNzaWduKHt9LCByZXN0V2hlcmUub2JqZWN0SWQsIHtcbiAgICAgICAgICAkZ3Q6IHJlc3VsdHNbcmVzdWx0cy5sZW5ndGggLSAxXS5vYmplY3RJZCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICApO1xufTtcblxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5idWlsZFJlc3RXaGVyZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRVc2VyQW5kUm9sZUFDTCgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVkaXJlY3RDbGFzc05hbWVGb3JLZXkoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlQ2xpZW50Q2xhc3NDcmVhdGlvbigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZVNlbGVjdCgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZURvbnRTZWxlY3QoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlcGxhY2VJblF1ZXJ5KCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5yZXBsYWNlTm90SW5RdWVyeSgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZUVxdWFsaXR5KCk7XG4gICAgfSk7XG59O1xuXG4vLyBVc2VzIHRoZSBBdXRoIG9iamVjdCB0byBnZXQgdGhlIGxpc3Qgb2Ygcm9sZXMsIGFkZHMgdGhlIHVzZXIgaWRcblJlc3RRdWVyeS5wcm90b3R5cGUuZ2V0VXNlckFuZFJvbGVBQ0wgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuYXV0aC5pc01hc3Rlcikge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIHRoaXMuZmluZE9wdGlvbnMuYWNsID0gWycqJ107XG5cbiAgaWYgKHRoaXMuYXV0aC51c2VyKSB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5nZXRVc2VyUm9sZXMoKS50aGVuKHJvbGVzID0+IHtcbiAgICAgIHRoaXMuZmluZE9wdGlvbnMuYWNsID0gdGhpcy5maW5kT3B0aW9ucy5hY2wuY29uY2F0KHJvbGVzLCBbXG4gICAgICAgIHRoaXMuYXV0aC51c2VyLmlkLFxuICAgICAgXSk7XG4gICAgICByZXR1cm47XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG59O1xuXG4vLyBDaGFuZ2VzIHRoZSBjbGFzc05hbWUgaWYgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXkgaXMgc2V0LlxuLy8gUmV0dXJucyBhIHByb21pc2UuXG5SZXN0UXVlcnkucHJvdG90eXBlLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5ID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5yZWRpcmVjdEtleSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIFdlIG5lZWQgdG8gY2hhbmdlIHRoZSBjbGFzcyBuYW1lIGJhc2VkIG9uIHRoZSBzY2hlbWFcbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5KHRoaXMuY2xhc3NOYW1lLCB0aGlzLnJlZGlyZWN0S2V5KVxuICAgIC50aGVuKG5ld0NsYXNzTmFtZSA9PiB7XG4gICAgICB0aGlzLmNsYXNzTmFtZSA9IG5ld0NsYXNzTmFtZTtcbiAgICAgIHRoaXMucmVkaXJlY3RDbGFzc05hbWUgPSBuZXdDbGFzc05hbWU7XG4gICAgfSk7XG59O1xuXG4vLyBWYWxpZGF0ZXMgdGhpcyBvcGVyYXRpb24gYWdhaW5zdCB0aGUgYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uIGNvbmZpZy5cblJlc3RRdWVyeS5wcm90b3R5cGUudmFsaWRhdGVDbGllbnRDbGFzc0NyZWF0aW9uID0gZnVuY3Rpb24oKSB7XG4gIGlmIChcbiAgICB0aGlzLmNvbmZpZy5hbGxvd0NsaWVudENsYXNzQ3JlYXRpb24gPT09IGZhbHNlICYmXG4gICAgIXRoaXMuYXV0aC5pc01hc3RlciAmJlxuICAgIFNjaGVtYUNvbnRyb2xsZXIuc3lzdGVtQ2xhc3Nlcy5pbmRleE9mKHRoaXMuY2xhc3NOYW1lKSA9PT0gLTFcbiAgKSB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgICAubG9hZFNjaGVtYSgpXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuaGFzQ2xhc3ModGhpcy5jbGFzc05hbWUpKVxuICAgICAgLnRoZW4oaGFzQ2xhc3MgPT4ge1xuICAgICAgICBpZiAoaGFzQ2xhc3MgIT09IHRydWUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgJ1RoaXMgdXNlciBpcyBub3QgYWxsb3dlZCB0byBhY2Nlc3MgJyArXG4gICAgICAgICAgICAgICdub24tZXhpc3RlbnQgY2xhc3M6ICcgK1xuICAgICAgICAgICAgICB0aGlzLmNsYXNzTmFtZVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufTtcblxuZnVuY3Rpb24gdHJhbnNmb3JtSW5RdWVyeShpblF1ZXJ5T2JqZWN0LCBjbGFzc05hbWUsIHJlc3VsdHMpIHtcbiAgdmFyIHZhbHVlcyA9IFtdO1xuICBmb3IgKHZhciByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgIHZhbHVlcy5wdXNoKHtcbiAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsXG4gICAgICBvYmplY3RJZDogcmVzdWx0Lm9iamVjdElkLFxuICAgIH0pO1xuICB9XG4gIGRlbGV0ZSBpblF1ZXJ5T2JqZWN0WyckaW5RdWVyeSddO1xuICBpZiAoQXJyYXkuaXNBcnJheShpblF1ZXJ5T2JqZWN0WyckaW4nXSkpIHtcbiAgICBpblF1ZXJ5T2JqZWN0WyckaW4nXSA9IGluUXVlcnlPYmplY3RbJyRpbiddLmNvbmNhdCh2YWx1ZXMpO1xuICB9IGVsc2Uge1xuICAgIGluUXVlcnlPYmplY3RbJyRpbiddID0gdmFsdWVzO1xuICB9XG59XG5cbi8vIFJlcGxhY2VzIGEgJGluUXVlcnkgY2xhdXNlIGJ5IHJ1bm5pbmcgdGhlIHN1YnF1ZXJ5LCBpZiB0aGVyZSBpcyBhblxuLy8gJGluUXVlcnkgY2xhdXNlLlxuLy8gVGhlICRpblF1ZXJ5IGNsYXVzZSB0dXJucyBpbnRvIGFuICRpbiB3aXRoIHZhbHVlcyB0aGF0IGFyZSBqdXN0XG4vLyBwb2ludGVycyB0byB0aGUgb2JqZWN0cyByZXR1cm5lZCBpbiB0aGUgc3VicXVlcnkuXG5SZXN0UXVlcnkucHJvdG90eXBlLnJlcGxhY2VJblF1ZXJ5ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBpblF1ZXJ5T2JqZWN0ID0gZmluZE9iamVjdFdpdGhLZXkodGhpcy5yZXN0V2hlcmUsICckaW5RdWVyeScpO1xuICBpZiAoIWluUXVlcnlPYmplY3QpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBUaGUgaW5RdWVyeSB2YWx1ZSBtdXN0IGhhdmUgcHJlY2lzZWx5IHR3byBrZXlzIC0gd2hlcmUgYW5kIGNsYXNzTmFtZVxuICB2YXIgaW5RdWVyeVZhbHVlID0gaW5RdWVyeU9iamVjdFsnJGluUXVlcnknXTtcbiAgaWYgKCFpblF1ZXJ5VmFsdWUud2hlcmUgfHwgIWluUXVlcnlWYWx1ZS5jbGFzc05hbWUpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgJ2ltcHJvcGVyIHVzYWdlIG9mICRpblF1ZXJ5J1xuICAgICk7XG4gIH1cblxuICBjb25zdCBhZGRpdGlvbmFsT3B0aW9ucyA9IHtcbiAgICByZWRpcmVjdENsYXNzTmFtZUZvcktleTogaW5RdWVyeVZhbHVlLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5LFxuICB9O1xuXG4gIGlmICh0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICB9IGVsc2UgaWYgKHRoaXMucmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICB2YXIgc3VicXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgIHRoaXMuY29uZmlnLFxuICAgIHRoaXMuYXV0aCxcbiAgICBpblF1ZXJ5VmFsdWUuY2xhc3NOYW1lLFxuICAgIGluUXVlcnlWYWx1ZS53aGVyZSxcbiAgICBhZGRpdGlvbmFsT3B0aW9uc1xuICApO1xuICByZXR1cm4gc3VicXVlcnkuZXhlY3V0ZSgpLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgIHRyYW5zZm9ybUluUXVlcnkoaW5RdWVyeU9iamVjdCwgc3VicXVlcnkuY2xhc3NOYW1lLCByZXNwb25zZS5yZXN1bHRzKTtcbiAgICAvLyBSZWN1cnNlIHRvIHJlcGVhdFxuICAgIHJldHVybiB0aGlzLnJlcGxhY2VJblF1ZXJ5KCk7XG4gIH0pO1xufTtcblxuZnVuY3Rpb24gdHJhbnNmb3JtTm90SW5RdWVyeShub3RJblF1ZXJ5T2JqZWN0LCBjbGFzc05hbWUsIHJlc3VsdHMpIHtcbiAgdmFyIHZhbHVlcyA9IFtdO1xuICBmb3IgKHZhciByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgIHZhbHVlcy5wdXNoKHtcbiAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsXG4gICAgICBvYmplY3RJZDogcmVzdWx0Lm9iamVjdElkLFxuICAgIH0pO1xuICB9XG4gIGRlbGV0ZSBub3RJblF1ZXJ5T2JqZWN0Wyckbm90SW5RdWVyeSddO1xuICBpZiAoQXJyYXkuaXNBcnJheShub3RJblF1ZXJ5T2JqZWN0WyckbmluJ10pKSB7XG4gICAgbm90SW5RdWVyeU9iamVjdFsnJG5pbiddID0gbm90SW5RdWVyeU9iamVjdFsnJG5pbiddLmNvbmNhdCh2YWx1ZXMpO1xuICB9IGVsc2Uge1xuICAgIG5vdEluUXVlcnlPYmplY3RbJyRuaW4nXSA9IHZhbHVlcztcbiAgfVxufVxuXG4vLyBSZXBsYWNlcyBhICRub3RJblF1ZXJ5IGNsYXVzZSBieSBydW5uaW5nIHRoZSBzdWJxdWVyeSwgaWYgdGhlcmUgaXMgYW5cbi8vICRub3RJblF1ZXJ5IGNsYXVzZS5cbi8vIFRoZSAkbm90SW5RdWVyeSBjbGF1c2UgdHVybnMgaW50byBhICRuaW4gd2l0aCB2YWx1ZXMgdGhhdCBhcmUganVzdFxuLy8gcG9pbnRlcnMgdG8gdGhlIG9iamVjdHMgcmV0dXJuZWQgaW4gdGhlIHN1YnF1ZXJ5LlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZXBsYWNlTm90SW5RdWVyeSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgbm90SW5RdWVyeU9iamVjdCA9IGZpbmRPYmplY3RXaXRoS2V5KHRoaXMucmVzdFdoZXJlLCAnJG5vdEluUXVlcnknKTtcbiAgaWYgKCFub3RJblF1ZXJ5T2JqZWN0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVGhlIG5vdEluUXVlcnkgdmFsdWUgbXVzdCBoYXZlIHByZWNpc2VseSB0d28ga2V5cyAtIHdoZXJlIGFuZCBjbGFzc05hbWVcbiAgdmFyIG5vdEluUXVlcnlWYWx1ZSA9IG5vdEluUXVlcnlPYmplY3RbJyRub3RJblF1ZXJ5J107XG4gIGlmICghbm90SW5RdWVyeVZhbHVlLndoZXJlIHx8ICFub3RJblF1ZXJ5VmFsdWUuY2xhc3NOYW1lKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICdpbXByb3BlciB1c2FnZSBvZiAkbm90SW5RdWVyeSdcbiAgICApO1xuICB9XG5cbiAgY29uc3QgYWRkaXRpb25hbE9wdGlvbnMgPSB7XG4gICAgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXk6IG5vdEluUXVlcnlWYWx1ZS5yZWRpcmVjdENsYXNzTmFtZUZvcktleSxcbiAgfTtcblxuICBpZiAodGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgfSBlbHNlIGlmICh0aGlzLnJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlKSB7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgdmFyIHN1YnF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShcbiAgICB0aGlzLmNvbmZpZyxcbiAgICB0aGlzLmF1dGgsXG4gICAgbm90SW5RdWVyeVZhbHVlLmNsYXNzTmFtZSxcbiAgICBub3RJblF1ZXJ5VmFsdWUud2hlcmUsXG4gICAgYWRkaXRpb25hbE9wdGlvbnNcbiAgKTtcbiAgcmV0dXJuIHN1YnF1ZXJ5LmV4ZWN1dGUoKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICB0cmFuc2Zvcm1Ob3RJblF1ZXJ5KG5vdEluUXVlcnlPYmplY3QsIHN1YnF1ZXJ5LmNsYXNzTmFtZSwgcmVzcG9uc2UucmVzdWx0cyk7XG4gICAgLy8gUmVjdXJzZSB0byByZXBlYXRcbiAgICByZXR1cm4gdGhpcy5yZXBsYWNlTm90SW5RdWVyeSgpO1xuICB9KTtcbn07XG5cbi8vIFVzZWQgdG8gZ2V0IHRoZSBkZWVwZXN0IG9iamVjdCBmcm9tIGpzb24gdXNpbmcgZG90IG5vdGF0aW9uLlxuY29uc3QgZ2V0RGVlcGVzdE9iamVjdEZyb21LZXkgPSAoanNvbiwga2V5LCBpZHgsIHNyYykgPT4ge1xuICBpZiAoa2V5IGluIGpzb24pIHtcbiAgICByZXR1cm4ganNvbltrZXldO1xuICB9XG4gIHNyYy5zcGxpY2UoMSk7IC8vIEV4aXQgRWFybHlcbn07XG5cbmNvbnN0IHRyYW5zZm9ybVNlbGVjdCA9IChzZWxlY3RPYmplY3QsIGtleSwgb2JqZWN0cykgPT4ge1xuICB2YXIgdmFsdWVzID0gW107XG4gIGZvciAodmFyIHJlc3VsdCBvZiBvYmplY3RzKSB7XG4gICAgdmFsdWVzLnB1c2goa2V5LnNwbGl0KCcuJykucmVkdWNlKGdldERlZXBlc3RPYmplY3RGcm9tS2V5LCByZXN1bHQpKTtcbiAgfVxuICBkZWxldGUgc2VsZWN0T2JqZWN0Wyckc2VsZWN0J107XG4gIGlmIChBcnJheS5pc0FycmF5KHNlbGVjdE9iamVjdFsnJGluJ10pKSB7XG4gICAgc2VsZWN0T2JqZWN0WyckaW4nXSA9IHNlbGVjdE9iamVjdFsnJGluJ10uY29uY2F0KHZhbHVlcyk7XG4gIH0gZWxzZSB7XG4gICAgc2VsZWN0T2JqZWN0WyckaW4nXSA9IHZhbHVlcztcbiAgfVxufTtcblxuLy8gUmVwbGFjZXMgYSAkc2VsZWN0IGNsYXVzZSBieSBydW5uaW5nIHRoZSBzdWJxdWVyeSwgaWYgdGhlcmUgaXMgYVxuLy8gJHNlbGVjdCBjbGF1c2UuXG4vLyBUaGUgJHNlbGVjdCBjbGF1c2UgdHVybnMgaW50byBhbiAkaW4gd2l0aCB2YWx1ZXMgc2VsZWN0ZWQgb3V0IG9mXG4vLyB0aGUgc3VicXVlcnkuXG4vLyBSZXR1cm5zIGEgcG9zc2libGUtcHJvbWlzZS5cblJlc3RRdWVyeS5wcm90b3R5cGUucmVwbGFjZVNlbGVjdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc2VsZWN0T2JqZWN0ID0gZmluZE9iamVjdFdpdGhLZXkodGhpcy5yZXN0V2hlcmUsICckc2VsZWN0Jyk7XG4gIGlmICghc2VsZWN0T2JqZWN0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVGhlIHNlbGVjdCB2YWx1ZSBtdXN0IGhhdmUgcHJlY2lzZWx5IHR3byBrZXlzIC0gcXVlcnkgYW5kIGtleVxuICB2YXIgc2VsZWN0VmFsdWUgPSBzZWxlY3RPYmplY3RbJyRzZWxlY3QnXTtcbiAgLy8gaU9TIFNESyBkb24ndCBzZW5kIHdoZXJlIGlmIG5vdCBzZXQsIGxldCBpdCBwYXNzXG4gIGlmIChcbiAgICAhc2VsZWN0VmFsdWUucXVlcnkgfHxcbiAgICAhc2VsZWN0VmFsdWUua2V5IHx8XG4gICAgdHlwZW9mIHNlbGVjdFZhbHVlLnF1ZXJ5ICE9PSAnb2JqZWN0JyB8fFxuICAgICFzZWxlY3RWYWx1ZS5xdWVyeS5jbGFzc05hbWUgfHxcbiAgICBPYmplY3Qua2V5cyhzZWxlY3RWYWx1ZSkubGVuZ3RoICE9PSAyXG4gICkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAnaW1wcm9wZXIgdXNhZ2Ugb2YgJHNlbGVjdCdcbiAgICApO1xuICB9XG5cbiAgY29uc3QgYWRkaXRpb25hbE9wdGlvbnMgPSB7XG4gICAgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXk6IHNlbGVjdFZhbHVlLnF1ZXJ5LnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5LFxuICB9O1xuXG4gIGlmICh0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICB9IGVsc2UgaWYgKHRoaXMucmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICB2YXIgc3VicXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgIHRoaXMuY29uZmlnLFxuICAgIHRoaXMuYXV0aCxcbiAgICBzZWxlY3RWYWx1ZS5xdWVyeS5jbGFzc05hbWUsXG4gICAgc2VsZWN0VmFsdWUucXVlcnkud2hlcmUsXG4gICAgYWRkaXRpb25hbE9wdGlvbnNcbiAgKTtcbiAgcmV0dXJuIHN1YnF1ZXJ5LmV4ZWN1dGUoKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICB0cmFuc2Zvcm1TZWxlY3Qoc2VsZWN0T2JqZWN0LCBzZWxlY3RWYWx1ZS5rZXksIHJlc3BvbnNlLnJlc3VsdHMpO1xuICAgIC8vIEtlZXAgcmVwbGFjaW5nICRzZWxlY3QgY2xhdXNlc1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2VTZWxlY3QoKTtcbiAgfSk7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1Eb250U2VsZWN0ID0gKGRvbnRTZWxlY3RPYmplY3QsIGtleSwgb2JqZWN0cykgPT4ge1xuICB2YXIgdmFsdWVzID0gW107XG4gIGZvciAodmFyIHJlc3VsdCBvZiBvYmplY3RzKSB7XG4gICAgdmFsdWVzLnB1c2goa2V5LnNwbGl0KCcuJykucmVkdWNlKGdldERlZXBlc3RPYmplY3RGcm9tS2V5LCByZXN1bHQpKTtcbiAgfVxuICBkZWxldGUgZG9udFNlbGVjdE9iamVjdFsnJGRvbnRTZWxlY3QnXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoZG9udFNlbGVjdE9iamVjdFsnJG5pbiddKSkge1xuICAgIGRvbnRTZWxlY3RPYmplY3RbJyRuaW4nXSA9IGRvbnRTZWxlY3RPYmplY3RbJyRuaW4nXS5jb25jYXQodmFsdWVzKTtcbiAgfSBlbHNlIHtcbiAgICBkb250U2VsZWN0T2JqZWN0WyckbmluJ10gPSB2YWx1ZXM7XG4gIH1cbn07XG5cbi8vIFJlcGxhY2VzIGEgJGRvbnRTZWxlY3QgY2xhdXNlIGJ5IHJ1bm5pbmcgdGhlIHN1YnF1ZXJ5LCBpZiB0aGVyZSBpcyBhXG4vLyAkZG9udFNlbGVjdCBjbGF1c2UuXG4vLyBUaGUgJGRvbnRTZWxlY3QgY2xhdXNlIHR1cm5zIGludG8gYW4gJG5pbiB3aXRoIHZhbHVlcyBzZWxlY3RlZCBvdXQgb2Zcbi8vIHRoZSBzdWJxdWVyeS5cbi8vIFJldHVybnMgYSBwb3NzaWJsZS1wcm9taXNlLlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZXBsYWNlRG9udFNlbGVjdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZG9udFNlbGVjdE9iamVjdCA9IGZpbmRPYmplY3RXaXRoS2V5KHRoaXMucmVzdFdoZXJlLCAnJGRvbnRTZWxlY3QnKTtcbiAgaWYgKCFkb250U2VsZWN0T2JqZWN0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVGhlIGRvbnRTZWxlY3QgdmFsdWUgbXVzdCBoYXZlIHByZWNpc2VseSB0d28ga2V5cyAtIHF1ZXJ5IGFuZCBrZXlcbiAgdmFyIGRvbnRTZWxlY3RWYWx1ZSA9IGRvbnRTZWxlY3RPYmplY3RbJyRkb250U2VsZWN0J107XG4gIGlmIChcbiAgICAhZG9udFNlbGVjdFZhbHVlLnF1ZXJ5IHx8XG4gICAgIWRvbnRTZWxlY3RWYWx1ZS5rZXkgfHxcbiAgICB0eXBlb2YgZG9udFNlbGVjdFZhbHVlLnF1ZXJ5ICE9PSAnb2JqZWN0JyB8fFxuICAgICFkb250U2VsZWN0VmFsdWUucXVlcnkuY2xhc3NOYW1lIHx8XG4gICAgT2JqZWN0LmtleXMoZG9udFNlbGVjdFZhbHVlKS5sZW5ndGggIT09IDJcbiAgKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICdpbXByb3BlciB1c2FnZSBvZiAkZG9udFNlbGVjdCdcbiAgICApO1xuICB9XG4gIGNvbnN0IGFkZGl0aW9uYWxPcHRpb25zID0ge1xuICAgIHJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5OiBkb250U2VsZWN0VmFsdWUucXVlcnkucmVkaXJlY3RDbGFzc05hbWVGb3JLZXksXG4gIH07XG5cbiAgaWYgKHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSkge1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gIH0gZWxzZSBpZiAodGhpcy5yZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZSkge1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZTtcbiAgfVxuXG4gIHZhciBzdWJxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgdGhpcy5jb25maWcsXG4gICAgdGhpcy5hdXRoLFxuICAgIGRvbnRTZWxlY3RWYWx1ZS5xdWVyeS5jbGFzc05hbWUsXG4gICAgZG9udFNlbGVjdFZhbHVlLnF1ZXJ5LndoZXJlLFxuICAgIGFkZGl0aW9uYWxPcHRpb25zXG4gICk7XG4gIHJldHVybiBzdWJxdWVyeS5leGVjdXRlKCkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgdHJhbnNmb3JtRG9udFNlbGVjdChcbiAgICAgIGRvbnRTZWxlY3RPYmplY3QsXG4gICAgICBkb250U2VsZWN0VmFsdWUua2V5LFxuICAgICAgcmVzcG9uc2UucmVzdWx0c1xuICAgICk7XG4gICAgLy8gS2VlcCByZXBsYWNpbmcgJGRvbnRTZWxlY3QgY2xhdXNlc1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2VEb250U2VsZWN0KCk7XG4gIH0pO1xufTtcblxuY29uc3QgY2xlYW5SZXN1bHRBdXRoRGF0YSA9IGZ1bmN0aW9uKHJlc3VsdCkge1xuICBkZWxldGUgcmVzdWx0LnBhc3N3b3JkO1xuICBpZiAocmVzdWx0LmF1dGhEYXRhKSB7XG4gICAgT2JqZWN0LmtleXMocmVzdWx0LmF1dGhEYXRhKS5mb3JFYWNoKHByb3ZpZGVyID0+IHtcbiAgICAgIGlmIChyZXN1bHQuYXV0aERhdGFbcHJvdmlkZXJdID09PSBudWxsKSB7XG4gICAgICAgIGRlbGV0ZSByZXN1bHQuYXV0aERhdGFbcHJvdmlkZXJdO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKE9iamVjdC5rZXlzKHJlc3VsdC5hdXRoRGF0YSkubGVuZ3RoID09IDApIHtcbiAgICAgIGRlbGV0ZSByZXN1bHQuYXV0aERhdGE7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCByZXBsYWNlRXF1YWxpdHlDb25zdHJhaW50ID0gY29uc3RyYWludCA9PiB7XG4gIGlmICh0eXBlb2YgY29uc3RyYWludCAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gY29uc3RyYWludDtcbiAgfVxuICBjb25zdCBlcXVhbFRvT2JqZWN0ID0ge307XG4gIGxldCBoYXNEaXJlY3RDb25zdHJhaW50ID0gZmFsc2U7XG4gIGxldCBoYXNPcGVyYXRvckNvbnN0cmFpbnQgPSBmYWxzZTtcbiAgZm9yIChjb25zdCBrZXkgaW4gY29uc3RyYWludCkge1xuICAgIGlmIChrZXkuaW5kZXhPZignJCcpICE9PSAwKSB7XG4gICAgICBoYXNEaXJlY3RDb25zdHJhaW50ID0gdHJ1ZTtcbiAgICAgIGVxdWFsVG9PYmplY3Rba2V5XSA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGFzT3BlcmF0b3JDb25zdHJhaW50ID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgaWYgKGhhc0RpcmVjdENvbnN0cmFpbnQgJiYgaGFzT3BlcmF0b3JDb25zdHJhaW50KSB7XG4gICAgY29uc3RyYWludFsnJGVxJ10gPSBlcXVhbFRvT2JqZWN0O1xuICAgIE9iamVjdC5rZXlzKGVxdWFsVG9PYmplY3QpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIGRlbGV0ZSBjb25zdHJhaW50W2tleV07XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGNvbnN0cmFpbnQ7XG59O1xuXG5SZXN0UXVlcnkucHJvdG90eXBlLnJlcGxhY2VFcXVhbGl0eSA9IGZ1bmN0aW9uKCkge1xuICBpZiAodHlwZW9mIHRoaXMucmVzdFdoZXJlICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybjtcbiAgfVxuICBmb3IgKGNvbnN0IGtleSBpbiB0aGlzLnJlc3RXaGVyZSkge1xuICAgIHRoaXMucmVzdFdoZXJlW2tleV0gPSByZXBsYWNlRXF1YWxpdHlDb25zdHJhaW50KHRoaXMucmVzdFdoZXJlW2tleV0pO1xuICB9XG59O1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3Igd2hldGhlciBpdCB3YXMgc3VjY2Vzc2Z1bC5cbi8vIFBvcHVsYXRlcyB0aGlzLnJlc3BvbnNlIHdpdGggYW4gb2JqZWN0IHRoYXQgb25seSBoYXMgJ3Jlc3VsdHMnLlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5ydW5GaW5kID0gZnVuY3Rpb24ob3B0aW9ucyA9IHt9KSB7XG4gIGlmICh0aGlzLmZpbmRPcHRpb25zLmxpbWl0ID09PSAwKSB7XG4gICAgdGhpcy5yZXNwb25zZSA9IHsgcmVzdWx0czogW10gfTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgY29uc3QgZmluZE9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmZpbmRPcHRpb25zKTtcbiAgaWYgKHRoaXMua2V5cykge1xuICAgIGZpbmRPcHRpb25zLmtleXMgPSB0aGlzLmtleXMubWFwKGtleSA9PiB7XG4gICAgICByZXR1cm4ga2V5LnNwbGl0KCcuJylbMF07XG4gICAgfSk7XG4gIH1cbiAgaWYgKG9wdGlvbnMub3ApIHtcbiAgICBmaW5kT3B0aW9ucy5vcCA9IG9wdGlvbnMub3A7XG4gIH1cbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgLmZpbmQodGhpcy5jbGFzc05hbWUsIHRoaXMucmVzdFdoZXJlLCBmaW5kT3B0aW9ucywgdGhpcy5hdXRoKVxuICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgaWYgKHRoaXMuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgICAgIGZvciAodmFyIHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgICAgICAgY2xlYW5SZXN1bHRBdXRoRGF0YShyZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY29uZmlnLmZpbGVzQ29udHJvbGxlci5leHBhbmRGaWxlc0luT2JqZWN0KHRoaXMuY29uZmlnLCByZXN1bHRzKTtcblxuICAgICAgaWYgKHRoaXMucmVkaXJlY3RDbGFzc05hbWUpIHtcbiAgICAgICAgZm9yICh2YXIgciBvZiByZXN1bHRzKSB7XG4gICAgICAgICAgci5jbGFzc05hbWUgPSB0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLnJlc3BvbnNlID0geyByZXN1bHRzOiByZXN1bHRzIH07XG4gICAgfSk7XG59O1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3Igd2hldGhlciBpdCB3YXMgc3VjY2Vzc2Z1bC5cbi8vIFBvcHVsYXRlcyB0aGlzLnJlc3BvbnNlLmNvdW50IHdpdGggdGhlIGNvdW50XG5SZXN0UXVlcnkucHJvdG90eXBlLnJ1bkNvdW50ID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5kb0NvdW50KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRoaXMuZmluZE9wdGlvbnMuY291bnQgPSB0cnVlO1xuICBkZWxldGUgdGhpcy5maW5kT3B0aW9ucy5za2lwO1xuICBkZWxldGUgdGhpcy5maW5kT3B0aW9ucy5saW1pdDtcbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgLmZpbmQodGhpcy5jbGFzc05hbWUsIHRoaXMucmVzdFdoZXJlLCB0aGlzLmZpbmRPcHRpb25zKVxuICAgIC50aGVuKGMgPT4ge1xuICAgICAgdGhpcy5yZXNwb25zZS5jb3VudCA9IGM7XG4gICAgfSk7XG59O1xuXG4vLyBBdWdtZW50cyB0aGlzLnJlc3BvbnNlIHdpdGggYWxsIHBvaW50ZXJzIG9uIGFuIG9iamVjdFxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5oYW5kbGVJbmNsdWRlQWxsID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5pbmNsdWRlQWxsKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgIC5sb2FkU2NoZW1hKClcbiAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKHRoaXMuY2xhc3NOYW1lKSlcbiAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgY29uc3QgaW5jbHVkZUZpZWxkcyA9IFtdO1xuICAgICAgY29uc3Qga2V5RmllbGRzID0gW107XG4gICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIHNjaGVtYS5maWVsZHMpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGRdLnR5cGUgJiZcbiAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcidcbiAgICAgICAgKSB7XG4gICAgICAgICAgaW5jbHVkZUZpZWxkcy5wdXNoKFtmaWVsZF0pO1xuICAgICAgICAgIGtleUZpZWxkcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gQWRkIGZpZWxkcyB0byBpbmNsdWRlLCBrZXlzLCByZW1vdmUgZHVwc1xuICAgICAgdGhpcy5pbmNsdWRlID0gWy4uLm5ldyBTZXQoWy4uLnRoaXMuaW5jbHVkZSwgLi4uaW5jbHVkZUZpZWxkc10pXTtcbiAgICAgIC8vIGlmIHRoaXMua2V5cyBub3Qgc2V0LCB0aGVuIGFsbCBrZXlzIGFyZSBhbHJlYWR5IGluY2x1ZGVkXG4gICAgICBpZiAodGhpcy5rZXlzKSB7XG4gICAgICAgIHRoaXMua2V5cyA9IFsuLi5uZXcgU2V0KFsuLi50aGlzLmtleXMsIC4uLmtleUZpZWxkc10pXTtcbiAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8vIFVwZGF0ZXMgcHJvcGVydHkgYHRoaXMua2V5c2AgdG8gY29udGFpbiBhbGwga2V5cyBidXQgdGhlIG9uZXMgdW5zZWxlY3RlZC5cblJlc3RRdWVyeS5wcm90b3R5cGUuaGFuZGxlRXhjbHVkZUtleXMgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLmV4Y2x1ZGVLZXlzKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0aGlzLmtleXMpIHtcbiAgICB0aGlzLmtleXMgPSB0aGlzLmtleXMuZmlsdGVyKGsgPT4gIXRoaXMuZXhjbHVkZUtleXMuaW5jbHVkZXMoaykpO1xuICAgIHJldHVybjtcbiAgfVxuICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAubG9hZFNjaGVtYSgpXG4gICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYSh0aGlzLmNsYXNzTmFtZSkpXG4gICAgLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkcyA9IE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpO1xuICAgICAgdGhpcy5rZXlzID0gZmllbGRzLmZpbHRlcihrID0+ICF0aGlzLmV4Y2x1ZGVLZXlzLmluY2x1ZGVzKGspKTtcbiAgICB9KTtcbn07XG5cbi8vIEF1Z21lbnRzIHRoaXMucmVzcG9uc2Ugd2l0aCBkYXRhIGF0IHRoZSBwYXRocyBwcm92aWRlZCBpbiB0aGlzLmluY2x1ZGUuXG5SZXN0UXVlcnkucHJvdG90eXBlLmhhbmRsZUluY2x1ZGUgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuaW5jbHVkZS5sZW5ndGggPT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBwYXRoUmVzcG9uc2UgPSBpbmNsdWRlUGF0aChcbiAgICB0aGlzLmNvbmZpZyxcbiAgICB0aGlzLmF1dGgsXG4gICAgdGhpcy5yZXNwb25zZSxcbiAgICB0aGlzLmluY2x1ZGVbMF0sXG4gICAgdGhpcy5yZXN0T3B0aW9uc1xuICApO1xuICBpZiAocGF0aFJlc3BvbnNlLnRoZW4pIHtcbiAgICByZXR1cm4gcGF0aFJlc3BvbnNlLnRoZW4obmV3UmVzcG9uc2UgPT4ge1xuICAgICAgdGhpcy5yZXNwb25zZSA9IG5ld1Jlc3BvbnNlO1xuICAgICAgdGhpcy5pbmNsdWRlID0gdGhpcy5pbmNsdWRlLnNsaWNlKDEpO1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlSW5jbHVkZSgpO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKHRoaXMuaW5jbHVkZS5sZW5ndGggPiAwKSB7XG4gICAgdGhpcy5pbmNsdWRlID0gdGhpcy5pbmNsdWRlLnNsaWNlKDEpO1xuICAgIHJldHVybiB0aGlzLmhhbmRsZUluY2x1ZGUoKTtcbiAgfVxuXG4gIHJldHVybiBwYXRoUmVzcG9uc2U7XG59O1xuXG4vL1JldHVybnMgYSBwcm9taXNlIG9mIGEgcHJvY2Vzc2VkIHNldCBvZiByZXN1bHRzXG5SZXN0UXVlcnkucHJvdG90eXBlLnJ1bkFmdGVyRmluZFRyaWdnZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLnJlc3BvbnNlKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICghdGhpcy5ydW5BZnRlckZpbmQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gQXZvaWQgZG9pbmcgYW55IHNldHVwIGZvciB0cmlnZ2VycyBpZiB0aGVyZSBpcyBubyAnYWZ0ZXJGaW5kJyB0cmlnZ2VyIGZvciB0aGlzIGNsYXNzLlxuICBjb25zdCBoYXNBZnRlckZpbmRIb29rID0gdHJpZ2dlcnMudHJpZ2dlckV4aXN0cyhcbiAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckZpbmQsXG4gICAgdGhpcy5jb25maWcuYXBwbGljYXRpb25JZFxuICApO1xuICBpZiAoIWhhc0FmdGVyRmluZEhvb2spIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gU2tpcCBBZ2dyZWdhdGUgYW5kIERpc3RpbmN0IFF1ZXJpZXNcbiAgaWYgKHRoaXMuZmluZE9wdGlvbnMucGlwZWxpbmUgfHwgdGhpcy5maW5kT3B0aW9ucy5kaXN0aW5jdCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICAvLyBSdW4gYWZ0ZXJGaW5kIHRyaWdnZXIgYW5kIHNldCB0aGUgbmV3IHJlc3VsdHNcbiAgcmV0dXJuIHRyaWdnZXJzXG4gICAgLm1heWJlUnVuQWZ0ZXJGaW5kVHJpZ2dlcihcbiAgICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyRmluZCxcbiAgICAgIHRoaXMuYXV0aCxcbiAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgdGhpcy5yZXNwb25zZS5yZXN1bHRzLFxuICAgICAgdGhpcy5jb25maWdcbiAgICApXG4gICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAvLyBFbnN1cmUgd2UgcHJvcGVybHkgc2V0IHRoZSBjbGFzc05hbWUgYmFja1xuICAgICAgaWYgKHRoaXMucmVkaXJlY3RDbGFzc05hbWUpIHtcbiAgICAgICAgdGhpcy5yZXNwb25zZS5yZXN1bHRzID0gcmVzdWx0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgUGFyc2UuT2JqZWN0KSB7XG4gICAgICAgICAgICBvYmplY3QgPSBvYmplY3QudG9KU09OKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG9iamVjdC5jbGFzc05hbWUgPSB0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lO1xuICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZXNwb25zZS5yZXN1bHRzID0gcmVzdWx0cztcbiAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8vIEFkZHMgaW5jbHVkZWQgdmFsdWVzIHRvIHRoZSByZXNwb25zZS5cbi8vIFBhdGggaXMgYSBsaXN0IG9mIGZpZWxkIG5hbWVzLlxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGFuIGF1Z21lbnRlZCByZXNwb25zZS5cbmZ1bmN0aW9uIGluY2x1ZGVQYXRoKGNvbmZpZywgYXV0aCwgcmVzcG9uc2UsIHBhdGgsIHJlc3RPcHRpb25zID0ge30pIHtcbiAgdmFyIHBvaW50ZXJzID0gZmluZFBvaW50ZXJzKHJlc3BvbnNlLnJlc3VsdHMsIHBhdGgpO1xuICBpZiAocG9pbnRlcnMubGVuZ3RoID09IDApIHtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cbiAgY29uc3QgcG9pbnRlcnNIYXNoID0ge307XG4gIGZvciAodmFyIHBvaW50ZXIgb2YgcG9pbnRlcnMpIHtcbiAgICBpZiAoIXBvaW50ZXIpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBjbGFzc05hbWUgPSBwb2ludGVyLmNsYXNzTmFtZTtcbiAgICAvLyBvbmx5IGluY2x1ZGUgdGhlIGdvb2QgcG9pbnRlcnNcbiAgICBpZiAoY2xhc3NOYW1lKSB7XG4gICAgICBwb2ludGVyc0hhc2hbY2xhc3NOYW1lXSA9IHBvaW50ZXJzSGFzaFtjbGFzc05hbWVdIHx8IG5ldyBTZXQoKTtcbiAgICAgIHBvaW50ZXJzSGFzaFtjbGFzc05hbWVdLmFkZChwb2ludGVyLm9iamVjdElkKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgaW5jbHVkZVJlc3RPcHRpb25zID0ge307XG4gIGlmIChyZXN0T3B0aW9ucy5rZXlzKSB7XG4gICAgY29uc3Qga2V5cyA9IG5ldyBTZXQocmVzdE9wdGlvbnMua2V5cy5zcGxpdCgnLCcpKTtcbiAgICBjb25zdCBrZXlTZXQgPSBBcnJheS5mcm9tKGtleXMpLnJlZHVjZSgoc2V0LCBrZXkpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhdGggPSBrZXkuc3BsaXQoJy4nKTtcbiAgICAgIGxldCBpID0gMDtcbiAgICAgIGZvciAoaTsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHBhdGhbaV0gIT0ga2V5UGF0aFtpXSkge1xuICAgICAgICAgIHJldHVybiBzZXQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChpIDwga2V5UGF0aC5sZW5ndGgpIHtcbiAgICAgICAgc2V0LmFkZChrZXlQYXRoW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzZXQ7XG4gICAgfSwgbmV3IFNldCgpKTtcbiAgICBpZiAoa2V5U2V0LnNpemUgPiAwKSB7XG4gICAgICBpbmNsdWRlUmVzdE9wdGlvbnMua2V5cyA9IEFycmF5LmZyb20oa2V5U2V0KS5qb2luKCcsJyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlc3RPcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZSkge1xuICAgIGluY2x1ZGVSZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHJlc3RPcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgICBpbmNsdWRlUmVzdE9wdGlvbnMuaW5jbHVkZVJlYWRQcmVmZXJlbmNlID1cbiAgICAgIHJlc3RPcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgfSBlbHNlIGlmIChyZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZSkge1xuICAgIGluY2x1ZGVSZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgY29uc3QgcXVlcnlQcm9taXNlcyA9IE9iamVjdC5rZXlzKHBvaW50ZXJzSGFzaCkubWFwKGNsYXNzTmFtZSA9PiB7XG4gICAgY29uc3Qgb2JqZWN0SWRzID0gQXJyYXkuZnJvbShwb2ludGVyc0hhc2hbY2xhc3NOYW1lXSk7XG4gICAgbGV0IHdoZXJlO1xuICAgIGlmIChvYmplY3RJZHMubGVuZ3RoID09PSAxKSB7XG4gICAgICB3aGVyZSA9IHsgb2JqZWN0SWQ6IG9iamVjdElkc1swXSB9O1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGVyZSA9IHsgb2JqZWN0SWQ6IHsgJGluOiBvYmplY3RJZHMgfSB9O1xuICAgIH1cbiAgICB2YXIgcXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgICAgY29uZmlnLFxuICAgICAgYXV0aCxcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHdoZXJlLFxuICAgICAgaW5jbHVkZVJlc3RPcHRpb25zXG4gICAgKTtcbiAgICByZXR1cm4gcXVlcnkuZXhlY3V0ZSh7IG9wOiAnZ2V0JyB9KS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgcmVzdWx0cy5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdHMpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyBHZXQgdGhlIG9iamVjdHMgZm9yIGFsbCB0aGVzZSBvYmplY3QgaWRzXG4gIHJldHVybiBQcm9taXNlLmFsbChxdWVyeVByb21pc2VzKS50aGVuKHJlc3BvbnNlcyA9PiB7XG4gICAgdmFyIHJlcGxhY2UgPSByZXNwb25zZXMucmVkdWNlKChyZXBsYWNlLCBpbmNsdWRlUmVzcG9uc2UpID0+IHtcbiAgICAgIGZvciAodmFyIG9iaiBvZiBpbmNsdWRlUmVzcG9uc2UucmVzdWx0cykge1xuICAgICAgICBvYmouX190eXBlID0gJ09iamVjdCc7XG4gICAgICAgIG9iai5jbGFzc05hbWUgPSBpbmNsdWRlUmVzcG9uc2UuY2xhc3NOYW1lO1xuXG4gICAgICAgIGlmIChvYmouY2xhc3NOYW1lID09ICdfVXNlcicgJiYgIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgICBkZWxldGUgb2JqLnNlc3Npb25Ub2tlbjtcbiAgICAgICAgICBkZWxldGUgb2JqLmF1dGhEYXRhO1xuICAgICAgICB9XG4gICAgICAgIHJlcGxhY2Vbb2JqLm9iamVjdElkXSA9IG9iajtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXBsYWNlO1xuICAgIH0sIHt9KTtcblxuICAgIHZhciByZXNwID0ge1xuICAgICAgcmVzdWx0czogcmVwbGFjZVBvaW50ZXJzKHJlc3BvbnNlLnJlc3VsdHMsIHBhdGgsIHJlcGxhY2UpLFxuICAgIH07XG4gICAgaWYgKHJlc3BvbnNlLmNvdW50KSB7XG4gICAgICByZXNwLmNvdW50ID0gcmVzcG9uc2UuY291bnQ7XG4gICAgfVxuICAgIHJldHVybiByZXNwO1xuICB9KTtcbn1cblxuLy8gT2JqZWN0IG1heSBiZSBhIGxpc3Qgb2YgUkVTVC1mb3JtYXQgb2JqZWN0IHRvIGZpbmQgcG9pbnRlcnMgaW4sIG9yXG4vLyBpdCBtYXkgYmUgYSBzaW5nbGUgb2JqZWN0LlxuLy8gSWYgdGhlIHBhdGggeWllbGRzIHRoaW5ncyB0aGF0IGFyZW4ndCBwb2ludGVycywgdGhpcyB0aHJvd3MgYW4gZXJyb3IuXG4vLyBQYXRoIGlzIGEgbGlzdCBvZiBmaWVsZHMgdG8gc2VhcmNoIGludG8uXG4vLyBSZXR1cm5zIGEgbGlzdCBvZiBwb2ludGVycyBpbiBSRVNUIGZvcm1hdC5cbmZ1bmN0aW9uIGZpbmRQb2ludGVycyhvYmplY3QsIHBhdGgpIHtcbiAgaWYgKG9iamVjdCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgdmFyIGFuc3dlciA9IFtdO1xuICAgIGZvciAodmFyIHggb2Ygb2JqZWN0KSB7XG4gICAgICBhbnN3ZXIgPSBhbnN3ZXIuY29uY2F0KGZpbmRQb2ludGVycyh4LCBwYXRoKSk7XG4gICAgfVxuICAgIHJldHVybiBhbnN3ZXI7XG4gIH1cblxuICBpZiAodHlwZW9mIG9iamVjdCAhPT0gJ29iamVjdCcgfHwgIW9iamVjdCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGlmIChwYXRoLmxlbmd0aCA9PSAwKSB7XG4gICAgaWYgKG9iamVjdCA9PT0gbnVsbCB8fCBvYmplY3QuX190eXBlID09ICdQb2ludGVyJykge1xuICAgICAgcmV0dXJuIFtvYmplY3RdO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICB2YXIgc3Vib2JqZWN0ID0gb2JqZWN0W3BhdGhbMF1dO1xuICBpZiAoIXN1Ym9iamVjdCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICByZXR1cm4gZmluZFBvaW50ZXJzKHN1Ym9iamVjdCwgcGF0aC5zbGljZSgxKSk7XG59XG5cbi8vIE9iamVjdCBtYXkgYmUgYSBsaXN0IG9mIFJFU1QtZm9ybWF0IG9iamVjdHMgdG8gcmVwbGFjZSBwb2ludGVyc1xuLy8gaW4sIG9yIGl0IG1heSBiZSBhIHNpbmdsZSBvYmplY3QuXG4vLyBQYXRoIGlzIGEgbGlzdCBvZiBmaWVsZHMgdG8gc2VhcmNoIGludG8uXG4vLyByZXBsYWNlIGlzIGEgbWFwIGZyb20gb2JqZWN0IGlkIC0+IG9iamVjdC5cbi8vIFJldHVybnMgc29tZXRoaW5nIGFuYWxvZ291cyB0byBvYmplY3QsIGJ1dCB3aXRoIHRoZSBhcHByb3ByaWF0ZVxuLy8gcG9pbnRlcnMgaW5mbGF0ZWQuXG5mdW5jdGlvbiByZXBsYWNlUG9pbnRlcnMob2JqZWN0LCBwYXRoLCByZXBsYWNlKSB7XG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHJldHVybiBvYmplY3RcbiAgICAgIC5tYXAob2JqID0+IHJlcGxhY2VQb2ludGVycyhvYmosIHBhdGgsIHJlcGxhY2UpKVxuICAgICAgLmZpbHRlcihvYmogPT4gdHlwZW9mIG9iaiAhPT0gJ3VuZGVmaW5lZCcpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnIHx8ICFvYmplY3QpIHtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG5cbiAgaWYgKHBhdGgubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKG9iamVjdCAmJiBvYmplY3QuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgIHJldHVybiByZXBsYWNlW29iamVjdC5vYmplY3RJZF07XG4gICAgfVxuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICB2YXIgc3Vib2JqZWN0ID0gb2JqZWN0W3BhdGhbMF1dO1xuICBpZiAoIXN1Ym9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgdmFyIG5ld3N1YiA9IHJlcGxhY2VQb2ludGVycyhzdWJvYmplY3QsIHBhdGguc2xpY2UoMSksIHJlcGxhY2UpO1xuICB2YXIgYW5zd2VyID0ge307XG4gIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICBpZiAoa2V5ID09IHBhdGhbMF0pIHtcbiAgICAgIGFuc3dlcltrZXldID0gbmV3c3ViO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbnN3ZXJba2V5XSA9IG9iamVjdFtrZXldO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYW5zd2VyO1xufVxuXG4vLyBGaW5kcyBhIHN1Ym9iamVjdCB0aGF0IGhhcyB0aGUgZ2l2ZW4ga2V5LCBpZiB0aGVyZSBpcyBvbmUuXG4vLyBSZXR1cm5zIHVuZGVmaW5lZCBvdGhlcndpc2UuXG5mdW5jdGlvbiBmaW5kT2JqZWN0V2l0aEtleShyb290LCBrZXkpIHtcbiAgaWYgKHR5cGVvZiByb290ICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAocm9vdCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgZm9yICh2YXIgaXRlbSBvZiByb290KSB7XG4gICAgICBjb25zdCBhbnN3ZXIgPSBmaW5kT2JqZWN0V2l0aEtleShpdGVtLCBrZXkpO1xuICAgICAgaWYgKGFuc3dlcikge1xuICAgICAgICByZXR1cm4gYW5zd2VyO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAocm9vdCAmJiByb290W2tleV0pIHtcbiAgICByZXR1cm4gcm9vdDtcbiAgfVxuICBmb3IgKHZhciBzdWJrZXkgaW4gcm9vdCkge1xuICAgIGNvbnN0IGFuc3dlciA9IGZpbmRPYmplY3RXaXRoS2V5KHJvb3Rbc3Via2V5XSwga2V5KTtcbiAgICBpZiAoYW5zd2VyKSB7XG4gICAgICByZXR1cm4gYW5zd2VyO1xuICAgIH1cbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFJlc3RRdWVyeTtcbiJdfQ== \ No newline at end of file diff --git a/lib/RestWrite.js b/lib/RestWrite.js new file mode 100644 index 0000000000..38ed8de6f5 --- /dev/null +++ b/lib/RestWrite.js @@ -0,0 +1,1445 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _RestQuery = _interopRequireDefault(require("./RestQuery")); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _logger = _interopRequireDefault(require("./logger")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// A RestWrite encapsulates everything we need to run an operation +// that writes to the database. +// This could be either a "create" or an "update". +var SchemaController = require('./Controllers/SchemaController'); + +var deepcopy = require('deepcopy'); + +const Auth = require('./Auth'); + +var cryptoUtils = require('./cryptoUtils'); + +var passwordCrypto = require('./password'); + +var Parse = require('parse/node'); + +var triggers = require('./triggers'); + +var ClientSDK = require('./ClientSDK'); + +// query and data are both provided in REST API format. So data +// types are encoded by plain old objects. +// If query is null, this is a "create" and the data in data should be +// created. +// Otherwise this is an "update" - the object matching the query +// should get updated with data. +// RestWrite will handle objectId, createdAt, and updatedAt for +// everything. It also knows to use triggers and special modifications +// for the _User class. +function RestWrite(config, auth, className, query, data, originalData, clientSDK) { + if (auth.isReadOnly) { + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Cannot perform a write operation when using readOnlyMasterKey'); + } + + this.config = config; + this.auth = auth; + this.className = className; + this.clientSDK = clientSDK; + this.storage = {}; + this.runOptions = {}; + this.context = {}; + + if (!query && data.objectId) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId is an invalid field name.'); + } + + if (!query && data.id) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'id is an invalid field name.'); + } // When the operation is complete, this.response may have several + // fields. + // response: the actual data to be returned + // status: the http status code. if not present, treated like a 200 + // location: the location header. if not present, no location header + + + this.response = null; // Processing this operation may mutate our data, so we operate on a + // copy + + this.query = deepcopy(query); + this.data = deepcopy(data); // We never change originalData, so we do not need a deep copy + + this.originalData = originalData; // The timestamp we'll use for this whole operation + + this.updatedAt = Parse._encode(new Date()).iso; // Shared SchemaController to be reused to reduce the number of loadSchema() calls per request + // Once set the schemaData should be immutable + + this.validSchemaController = null; +} // A convenient method to perform all the steps of processing the +// write, in order. +// Returns a promise for a {response, status, location} object. +// status and location are optional. + + +RestWrite.prototype.execute = function () { + return Promise.resolve().then(() => { + return this.getUserAndRoleACL(); + }).then(() => { + return this.validateClientClassCreation(); + }).then(() => { + return this.handleInstallation(); + }).then(() => { + return this.handleSession(); + }).then(() => { + return this.validateAuthData(); + }).then(() => { + return this.runBeforeSaveTrigger(); + }).then(() => { + return this.deleteEmailResetTokenIfNeeded(); + }).then(() => { + return this.validateSchema(); + }).then(schemaController => { + this.validSchemaController = schemaController; + return this.setRequiredFieldsIfNeeded(); + }).then(() => { + return this.transformUser(); + }).then(() => { + return this.expandFilesForExistingObjects(); + }).then(() => { + return this.destroyDuplicatedSessions(); + }).then(() => { + return this.runDatabaseOperation(); + }).then(() => { + return this.createSessionTokenIfNeeded(); + }).then(() => { + return this.handleFollowup(); + }).then(() => { + return this.runAfterSaveTrigger(); + }).then(() => { + return this.cleanUserAuthData(); + }).then(() => { + return this.response; + }); +}; // Uses the Auth object to get the list of roles, adds the user id + + +RestWrite.prototype.getUserAndRoleACL = function () { + if (this.auth.isMaster) { + return Promise.resolve(); + } + + this.runOptions.acl = ['*']; + + if (this.auth.user) { + return this.auth.getUserRoles().then(roles => { + this.runOptions.acl = this.runOptions.acl.concat(roles, [this.auth.user.id]); + return; + }); + } else { + return Promise.resolve(); + } +}; // Validates this operation against the allowClientClassCreation config. + + +RestWrite.prototype.validateClientClassCreation = function () { + if (this.config.allowClientClassCreation === false && !this.auth.isMaster && SchemaController.systemClasses.indexOf(this.className) === -1) { + return this.config.database.loadSchema().then(schemaController => schemaController.hasClass(this.className)).then(hasClass => { + if (hasClass !== true) { + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'This user is not allowed to access ' + 'non-existent class: ' + this.className); + } + }); + } else { + return Promise.resolve(); + } +}; // Validates this operation against the schema. + + +RestWrite.prototype.validateSchema = function () { + return this.config.database.validateObject(this.className, this.data, this.query, this.runOptions); +}; // Runs any beforeSave triggers against this operation. +// Any change leads to our data being mutated. + + +RestWrite.prototype.runBeforeSaveTrigger = function () { + if (this.response) { + return; + } // Avoid doing any setup for triggers if there is no 'beforeSave' trigger for this class. + + + if (!triggers.triggerExists(this.className, triggers.Types.beforeSave, this.config.applicationId)) { + return Promise.resolve(); + } // Cloud code gets a bit of extra data for its objects + + + var extraData = { + className: this.className + }; + + if (this.query && this.query.objectId) { + extraData.objectId = this.query.objectId; + } + + let originalObject = null; + const updatedObject = this.buildUpdatedObject(extraData); + + if (this.query && this.query.objectId) { + // This is an update for existing object. + originalObject = triggers.inflate(extraData, this.originalData); + } + + return Promise.resolve().then(() => { + // Before calling the trigger, validate the permissions for the save operation + let databasePromise = null; + + if (this.query) { + // Validate for updating + databasePromise = this.config.database.update(this.className, this.query, this.data, this.runOptions, false, true); + } else { + // Validate for creating + databasePromise = this.config.database.create(this.className, this.data, this.runOptions, true); + } // In the case that there is no permission for the operation, it throws an error + + + return databasePromise.then(result => { + if (!result || result.length <= 0) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + }); + }).then(() => { + return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config, this.context); + }).then(response => { + if (response && response.object) { + this.storage.fieldsChangedByTrigger = _lodash.default.reduce(response.object, (result, value, key) => { + if (!_lodash.default.isEqual(this.data[key], value)) { + result.push(key); + } + + return result; + }, []); + this.data = response.object; // We should delete the objectId for an update write + + if (this.query && this.query.objectId) { + delete this.data.objectId; + } + } + }); +}; + +RestWrite.prototype.runBeforeLoginTrigger = async function (userData) { + // Avoid doing any setup for triggers if there is no 'beforeLogin' trigger + if (!triggers.triggerExists(this.className, triggers.Types.beforeLogin, this.config.applicationId)) { + return; + } // Cloud code gets a bit of extra data for its objects + + + const extraData = { + className: this.className + }; + const user = triggers.inflate(extraData, userData); // no need to return a response + + await triggers.maybeRunTrigger(triggers.Types.beforeLogin, this.auth, user, null, this.config, this.context); +}; + +RestWrite.prototype.setRequiredFieldsIfNeeded = function () { + if (this.data) { + return this.validSchemaController.getAllClasses().then(allClasses => { + const schema = allClasses.find(oneClass => oneClass.className === this.className); + + const setRequiredFieldIfNeeded = (fieldName, setDefault) => { + if (this.data[fieldName] === undefined || this.data[fieldName] === null || this.data[fieldName] === '' || typeof this.data[fieldName] === 'object' && this.data[fieldName].__op === 'Delete') { + if (setDefault && schema.fields[fieldName] && schema.fields[fieldName].defaultValue !== null && schema.fields[fieldName].defaultValue !== undefined && (this.data[fieldName] === undefined || typeof this.data[fieldName] === 'object' && this.data[fieldName].__op === 'Delete')) { + this.data[fieldName] = schema.fields[fieldName].defaultValue; + this.storage.fieldsChangedByTrigger = this.storage.fieldsChangedByTrigger || []; + + if (this.storage.fieldsChangedByTrigger.indexOf(fieldName) < 0) { + this.storage.fieldsChangedByTrigger.push(fieldName); + } + } else if (schema.fields[fieldName] && schema.fields[fieldName].required === true) { + throw new Parse.Error(Parse.Error.VALIDATION_ERROR, `${fieldName} is required`); + } + } + }; // Add default fields + + + this.data.updatedAt = this.updatedAt; + + if (!this.query) { + this.data.createdAt = this.updatedAt; // Only assign new objectId if we are creating new object + + if (!this.data.objectId) { + this.data.objectId = cryptoUtils.newObjectId(this.config.objectIdSize); + } + + if (schema) { + Object.keys(schema.fields).forEach(fieldName => { + setRequiredFieldIfNeeded(fieldName, true); + }); + } + } else if (schema) { + Object.keys(this.data).forEach(fieldName => { + setRequiredFieldIfNeeded(fieldName, false); + }); + } + }); + } + + return Promise.resolve(); +}; // Transforms auth data for a user object. +// Does nothing if this isn't a user object. +// Returns a promise for when we're done if it can't finish this tick. + + +RestWrite.prototype.validateAuthData = function () { + if (this.className !== '_User') { + return; + } + + if (!this.query && !this.data.authData) { + if (typeof this.data.username !== 'string' || _lodash.default.isEmpty(this.data.username)) { + throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'bad or missing username'); + } + + if (typeof this.data.password !== 'string' || _lodash.default.isEmpty(this.data.password)) { + throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'password is required'); + } + } + + if (this.data.authData && !Object.keys(this.data.authData).length || !Object.prototype.hasOwnProperty.call(this.data, 'authData')) { + // Handle saving authData to {} or if authData doesn't exist + return; + } else if (Object.prototype.hasOwnProperty.call(this.data, 'authData') && !this.data.authData) { + // Handle saving authData to null + throw new Parse.Error(Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.'); + } + + var authData = this.data.authData; + var providers = Object.keys(authData); + + if (providers.length > 0) { + const canHandleAuthData = providers.reduce((canHandle, provider) => { + var providerAuthData = authData[provider]; + var hasToken = providerAuthData && providerAuthData.id; + return canHandle && (hasToken || providerAuthData == null); + }, true); + + if (canHandleAuthData) { + return this.handleAuthData(authData); + } + } + + throw new Parse.Error(Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.'); +}; + +RestWrite.prototype.handleAuthDataValidation = function (authData) { + const validations = Object.keys(authData).map(provider => { + if (authData[provider] === null) { + return Promise.resolve(); + } + + const validateAuthData = this.config.authDataManager.getValidatorForProvider(provider); + + if (!validateAuthData) { + throw new Parse.Error(Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.'); + } + + return validateAuthData(authData[provider]); + }); + return Promise.all(validations); +}; + +RestWrite.prototype.findUsersWithAuthData = function (authData) { + const providers = Object.keys(authData); + const query = providers.reduce((memo, provider) => { + if (!authData[provider]) { + return memo; + } + + const queryKey = `authData.${provider}.id`; + const query = {}; + query[queryKey] = authData[provider].id; + memo.push(query); + return memo; + }, []).filter(q => { + return typeof q !== 'undefined'; + }); + let findPromise = Promise.resolve([]); + + if (query.length > 0) { + findPromise = this.config.database.find(this.className, { + $or: query + }, {}); + } + + return findPromise; +}; + +RestWrite.prototype.filteredObjectsByACL = function (objects) { + if (this.auth.isMaster) { + return objects; + } + + return objects.filter(object => { + if (!object.ACL) { + return true; // legacy users that have no ACL field on them + } // Regular users that have been locked out. + + + return object.ACL && Object.keys(object.ACL).length > 0; + }); +}; + +RestWrite.prototype.handleAuthData = function (authData) { + let results; + return this.findUsersWithAuthData(authData).then(async r => { + results = this.filteredObjectsByACL(r); + + if (results.length == 1) { + this.storage['authProvider'] = Object.keys(authData).join(','); + const userResult = results[0]; + const mutatedAuthData = {}; + Object.keys(authData).forEach(provider => { + const providerData = authData[provider]; + const userAuthData = userResult.authData[provider]; + + if (!_lodash.default.isEqual(providerData, userAuthData)) { + mutatedAuthData[provider] = providerData; + } + }); + const hasMutatedAuthData = Object.keys(mutatedAuthData).length !== 0; + let userId; + + if (this.query && this.query.objectId) { + userId = this.query.objectId; + } else if (this.auth && this.auth.user && this.auth.user.id) { + userId = this.auth.user.id; + } + + if (!userId || userId === userResult.objectId) { + // no user making the call + // OR the user making the call is the right one + // Login with auth data + delete results[0].password; // need to set the objectId first otherwise location has trailing undefined + + this.data.objectId = userResult.objectId; + + if (!this.query || !this.query.objectId) { + // this a login call, no userId passed + this.response = { + response: userResult, + location: this.location() + }; // Run beforeLogin hook before storing any updates + // to authData on the db; changes to userResult + // will be ignored. + + await this.runBeforeLoginTrigger(deepcopy(userResult)); + } // If we didn't change the auth data, just keep going + + + if (!hasMutatedAuthData) { + return; + } // We have authData that is updated on login + // that can happen when token are refreshed, + // We should update the token and let the user in + // We should only check the mutated keys + + + return this.handleAuthDataValidation(mutatedAuthData).then(async () => { + // IF we have a response, we'll skip the database operation / beforeSave / afterSave etc... + // we need to set it up there. + // We are supposed to have a response only on LOGIN with authData, so we skip those + // If we're not logging in, but just updating the current user, we can safely skip that part + if (this.response) { + // Assign the new authData in the response + Object.keys(mutatedAuthData).forEach(provider => { + this.response.response.authData[provider] = mutatedAuthData[provider]; + }); // Run the DB update directly, as 'master' + // Just update the authData part + // Then we're good for the user, early exit of sorts + + return this.config.database.update(this.className, { + objectId: this.data.objectId + }, { + authData: mutatedAuthData + }, {}); + } + }); + } else if (userId) { + // Trying to update auth data but users + // are different + if (userResult.objectId !== userId) { + throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, 'this auth is already used'); + } // No auth data was mutated, just keep going + + + if (!hasMutatedAuthData) { + return; + } + } + } + + return this.handleAuthDataValidation(authData).then(() => { + if (results.length > 1) { + // More than 1 user with the passed id's + throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, 'this auth is already used'); + } + }); + }); +}; // The non-third-party parts of User transformation + + +RestWrite.prototype.transformUser = function () { + var promise = Promise.resolve(); + + if (this.className !== '_User') { + return promise; + } + + if (!this.auth.isMaster && 'emailVerified' in this.data) { + const error = `Clients aren't allowed to manually update email verification.`; + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error); + } // Do not cleanup session if objectId is not set + + + if (this.query && this.objectId()) { + // If we're updating a _User object, we need to clear out the cache for that user. Find all their + // session tokens, and remove them from the cache. + promise = new _RestQuery.default(this.config, Auth.master(this.config), '_Session', { + user: { + __type: 'Pointer', + className: '_User', + objectId: this.objectId() + } + }).execute().then(results => { + results.results.forEach(session => this.config.cacheController.user.del(session.sessionToken)); + }); + } + + return promise.then(() => { + // Transform the password + if (this.data.password === undefined) { + // ignore only if undefined. should proceed if empty ('') + return Promise.resolve(); + } + + if (this.query) { + this.storage['clearSessions'] = true; // Generate a new session only if the user requested + + if (!this.auth.isMaster) { + this.storage['generateNewSession'] = true; + } + } + + return this._validatePasswordPolicy().then(() => { + return passwordCrypto.hash(this.data.password).then(hashedPassword => { + this.data._hashed_password = hashedPassword; + delete this.data.password; + }); + }); + }).then(() => { + return this._validateUserName(); + }).then(() => { + return this._validateEmail(); + }); +}; + +RestWrite.prototype._validateUserName = function () { + // Check for username uniqueness + if (!this.data.username) { + if (!this.query) { + this.data.username = cryptoUtils.randomString(25); + this.responseShouldHaveUsername = true; + } + + return Promise.resolve(); + } // We need to a find to check for duplicate username in case they are missing the unique index on usernames + // TODO: Check if there is a unique index, and if so, skip this query. + + + return this.config.database.find(this.className, { + username: this.data.username, + objectId: { + $ne: this.objectId() + } + }, { + limit: 1 + }, {}, this.validSchemaController).then(results => { + if (results.length > 0) { + throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.'); + } + + return; + }); +}; + +RestWrite.prototype._validateEmail = function () { + if (!this.data.email || this.data.email.__op === 'Delete') { + return Promise.resolve(); + } // Validate basic email address format + + + if (!this.data.email.match(/^.+@.+$/)) { + return Promise.reject(new Parse.Error(Parse.Error.INVALID_EMAIL_ADDRESS, 'Email address format is invalid.')); + } // Same problem for email as above for username + + + return this.config.database.find(this.className, { + email: this.data.email, + objectId: { + $ne: this.objectId() + } + }, { + limit: 1 + }, {}, this.validSchemaController).then(results => { + if (results.length > 0) { + throw new Parse.Error(Parse.Error.EMAIL_TAKEN, 'Account already exists for this email address.'); + } + + if (!this.data.authData || !Object.keys(this.data.authData).length || Object.keys(this.data.authData).length === 1 && Object.keys(this.data.authData)[0] === 'anonymous') { + // We updated the email, send a new validation + this.storage['sendVerificationEmail'] = true; + this.config.userController.setEmailVerifyToken(this.data); + } + }); +}; + +RestWrite.prototype._validatePasswordPolicy = function () { + if (!this.config.passwordPolicy) return Promise.resolve(); + return this._validatePasswordRequirements().then(() => { + return this._validatePasswordHistory(); + }); +}; + +RestWrite.prototype._validatePasswordRequirements = function () { + // check if the password conforms to the defined password policy if configured + // If we specified a custom error in our configuration use it. + // Example: "Passwords must include a Capital Letter, Lowercase Letter, and a number." + // + // This is especially useful on the generic "password reset" page, + // as it allows the programmer to communicate specific requirements instead of: + // a. making the user guess whats wrong + // b. making a custom password reset page that shows the requirements + const policyError = this.config.passwordPolicy.validationError ? this.config.passwordPolicy.validationError : 'Password does not meet the Password Policy requirements.'; + const containsUsernameError = 'Password cannot contain your username.'; // check whether the password meets the password strength requirements + + if (this.config.passwordPolicy.patternValidator && !this.config.passwordPolicy.patternValidator(this.data.password) || this.config.passwordPolicy.validatorCallback && !this.config.passwordPolicy.validatorCallback(this.data.password)) { + return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, policyError)); + } // check whether password contain username + + + if (this.config.passwordPolicy.doNotAllowUsername === true) { + if (this.data.username) { + // username is not passed during password reset + if (this.data.password.indexOf(this.data.username) >= 0) return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, containsUsernameError)); + } else { + // retrieve the User object using objectId during password reset + return this.config.database.find('_User', { + objectId: this.objectId() + }).then(results => { + if (results.length != 1) { + throw undefined; + } + + if (this.data.password.indexOf(results[0].username) >= 0) return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, containsUsernameError)); + return Promise.resolve(); + }); + } + } + + return Promise.resolve(); +}; + +RestWrite.prototype._validatePasswordHistory = function () { + // check whether password is repeating from specified history + if (this.query && this.config.passwordPolicy.maxPasswordHistory) { + return this.config.database.find('_User', { + objectId: this.objectId() + }, { + keys: ['_password_history', '_hashed_password'] + }).then(results => { + if (results.length != 1) { + throw undefined; + } + + const user = results[0]; + let oldPasswords = []; + if (user._password_history) oldPasswords = _lodash.default.take(user._password_history, this.config.passwordPolicy.maxPasswordHistory - 1); + oldPasswords.push(user.password); + const newPassword = this.data.password; // compare the new password hash with all old password hashes + + const promises = oldPasswords.map(function (hash) { + return passwordCrypto.compare(newPassword, hash).then(result => { + if (result) // reject if there is a match + return Promise.reject('REPEAT_PASSWORD'); + return Promise.resolve(); + }); + }); // wait for all comparisons to complete + + return Promise.all(promises).then(() => { + return Promise.resolve(); + }).catch(err => { + if (err === 'REPEAT_PASSWORD') // a match was found + return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, `New password should not be the same as last ${this.config.passwordPolicy.maxPasswordHistory} passwords.`)); + throw err; + }); + }); + } + + return Promise.resolve(); +}; + +RestWrite.prototype.createSessionTokenIfNeeded = function () { + if (this.className !== '_User') { + return; + } // Don't generate session for updating user (this.query is set) unless authData exists + + + if (this.query && !this.data.authData) { + return; + } // Don't generate new sessionToken if linking via sessionToken + + + if (this.auth.user && this.data.authData) { + return; + } + + if (!this.storage['authProvider'] && // signup call, with + this.config.preventLoginWithUnverifiedEmail && // no login without verification + this.config.verifyUserEmails) { + // verification is on + return; // do not create the session token in that case! + } + + return this.createSessionToken(); +}; + +RestWrite.prototype.createSessionToken = async function () { + // cloud installationId from Cloud Code, + // never create session tokens from there. + if (this.auth.installationId && this.auth.installationId === 'cloud') { + return; + } + + const { + sessionData, + createSession + } = Auth.createSession(this.config, { + userId: this.objectId(), + createdWith: { + action: this.storage['authProvider'] ? 'login' : 'signup', + authProvider: this.storage['authProvider'] || 'password' + }, + installationId: this.auth.installationId + }); + + if (this.response && this.response.response) { + this.response.response.sessionToken = sessionData.sessionToken; + } + + return createSession(); +}; // Delete email reset tokens if user is changing password or email. + + +RestWrite.prototype.deleteEmailResetTokenIfNeeded = function () { + if (this.className !== '_User' || this.query === null) { + // null query means create + return; + } + + if ('password' in this.data || 'email' in this.data) { + const addOps = { + _perishable_token: { + __op: 'Delete' + }, + _perishable_token_expires_at: { + __op: 'Delete' + } + }; + this.data = Object.assign(this.data, addOps); + } +}; + +RestWrite.prototype.destroyDuplicatedSessions = function () { + // Only for _Session, and at creation time + if (this.className != '_Session' || this.query) { + return; + } // Destroy the sessions in 'Background' + + + const { + user, + installationId, + sessionToken + } = this.data; + + if (!user || !installationId) { + return; + } + + if (!user.objectId) { + return; + } + + this.config.database.destroy('_Session', { + user, + installationId, + sessionToken: { + $ne: sessionToken + } + }, {}, this.validSchemaController); +}; // Handles any followup logic + + +RestWrite.prototype.handleFollowup = function () { + if (this.storage && this.storage['clearSessions'] && this.config.revokeSessionOnPasswordReset) { + var sessionQuery = { + user: { + __type: 'Pointer', + className: '_User', + objectId: this.objectId() + } + }; + delete this.storage['clearSessions']; + return this.config.database.destroy('_Session', sessionQuery).then(this.handleFollowup.bind(this)); + } + + if (this.storage && this.storage['generateNewSession']) { + delete this.storage['generateNewSession']; + return this.createSessionToken().then(this.handleFollowup.bind(this)); + } + + if (this.storage && this.storage['sendVerificationEmail']) { + delete this.storage['sendVerificationEmail']; // Fire and forget! + + this.config.userController.sendVerificationEmail(this.data); + return this.handleFollowup.bind(this); + } +}; // Handles the _Session class specialness. +// Does nothing if this isn't an _Session object. + + +RestWrite.prototype.handleSession = function () { + if (this.response || this.className !== '_Session') { + return; + } + + if (!this.auth.user && !this.auth.isMaster) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token required.'); + } // TODO: Verify proper error to throw + + + if (this.data.ACL) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Cannot set ' + 'ACL on a Session.'); + } + + if (this.query) { + if (this.data.user && !this.auth.isMaster && this.data.user.objectId != this.auth.user.id) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME); + } else if (this.data.installationId) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME); + } else if (this.data.sessionToken) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME); + } + } + + if (!this.query && !this.auth.isMaster) { + const additionalSessionData = {}; + + for (var key in this.data) { + if (key === 'objectId' || key === 'user') { + continue; + } + + additionalSessionData[key] = this.data[key]; + } + + const { + sessionData, + createSession + } = Auth.createSession(this.config, { + userId: this.auth.user.id, + createdWith: { + action: 'create' + }, + additionalSessionData + }); + return createSession().then(results => { + if (!results.response) { + throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Error creating session.'); + } + + sessionData['objectId'] = results.response['objectId']; + this.response = { + status: 201, + location: results.location, + response: sessionData + }; + }); + } +}; // Handles the _Installation class specialness. +// Does nothing if this isn't an installation object. +// If an installation is found, this can mutate this.query and turn a create +// into an update. +// Returns a promise for when we're done if it can't finish this tick. + + +RestWrite.prototype.handleInstallation = function () { + if (this.response || this.className !== '_Installation') { + return; + } + + if (!this.query && !this.data.deviceToken && !this.data.installationId && !this.auth.installationId) { + throw new Parse.Error(135, 'at least one ID field (deviceToken, installationId) ' + 'must be specified in this operation'); + } // If the device token is 64 characters long, we assume it is for iOS + // and lowercase it. + + + if (this.data.deviceToken && this.data.deviceToken.length == 64) { + this.data.deviceToken = this.data.deviceToken.toLowerCase(); + } // We lowercase the installationId if present + + + if (this.data.installationId) { + this.data.installationId = this.data.installationId.toLowerCase(); + } + + let installationId = this.data.installationId; // If data.installationId is not set and we're not master, we can lookup in auth + + if (!installationId && !this.auth.isMaster) { + installationId = this.auth.installationId; + } + + if (installationId) { + installationId = installationId.toLowerCase(); + } // Updating _Installation but not updating anything critical + + + if (this.query && !this.data.deviceToken && !installationId && !this.data.deviceType) { + return; + } + + var promise = Promise.resolve(); + var idMatch; // Will be a match on either objectId or installationId + + var objectIdMatch; + var installationIdMatch; + var deviceTokenMatches = []; // Instead of issuing 3 reads, let's do it with one OR. + + const orQueries = []; + + if (this.query && this.query.objectId) { + orQueries.push({ + objectId: this.query.objectId + }); + } + + if (installationId) { + orQueries.push({ + installationId: installationId + }); + } + + if (this.data.deviceToken) { + orQueries.push({ + deviceToken: this.data.deviceToken + }); + } + + if (orQueries.length == 0) { + return; + } + + promise = promise.then(() => { + return this.config.database.find('_Installation', { + $or: orQueries + }, {}); + }).then(results => { + results.forEach(result => { + if (this.query && this.query.objectId && result.objectId == this.query.objectId) { + objectIdMatch = result; + } + + if (result.installationId == installationId) { + installationIdMatch = result; + } + + if (result.deviceToken == this.data.deviceToken) { + deviceTokenMatches.push(result); + } + }); // Sanity checks when running a query + + if (this.query && this.query.objectId) { + if (!objectIdMatch) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found for update.'); + } + + if (this.data.installationId && objectIdMatch.installationId && this.data.installationId !== objectIdMatch.installationId) { + throw new Parse.Error(136, 'installationId may not be changed in this ' + 'operation'); + } + + if (this.data.deviceToken && objectIdMatch.deviceToken && this.data.deviceToken !== objectIdMatch.deviceToken && !this.data.installationId && !objectIdMatch.installationId) { + throw new Parse.Error(136, 'deviceToken may not be changed in this ' + 'operation'); + } + + if (this.data.deviceType && this.data.deviceType && this.data.deviceType !== objectIdMatch.deviceType) { + throw new Parse.Error(136, 'deviceType may not be changed in this ' + 'operation'); + } + } + + if (this.query && this.query.objectId && objectIdMatch) { + idMatch = objectIdMatch; + } + + if (installationId && installationIdMatch) { + idMatch = installationIdMatch; + } // need to specify deviceType only if it's new + + + if (!this.query && !this.data.deviceType && !idMatch) { + throw new Parse.Error(135, 'deviceType must be specified in this operation'); + } + }).then(() => { + if (!idMatch) { + if (!deviceTokenMatches.length) { + return; + } else if (deviceTokenMatches.length == 1 && (!deviceTokenMatches[0]['installationId'] || !installationId)) { + // Single match on device token but none on installationId, and either + // the passed object or the match is missing an installationId, so we + // can just return the match. + return deviceTokenMatches[0]['objectId']; + } else if (!this.data.installationId) { + throw new Parse.Error(132, 'Must specify installationId when deviceToken ' + 'matches multiple Installation objects'); + } else { + // Multiple device token matches and we specified an installation ID, + // or a single match where both the passed and matching objects have + // an installation ID. Try cleaning out old installations that match + // the deviceToken, and return nil to signal that a new object should + // be created. + var delQuery = { + deviceToken: this.data.deviceToken, + installationId: { + $ne: installationId + } + }; + + if (this.data.appIdentifier) { + delQuery['appIdentifier'] = this.data.appIdentifier; + } + + this.config.database.destroy('_Installation', delQuery).catch(err => { + if (err.code == Parse.Error.OBJECT_NOT_FOUND) { + // no deletions were made. Can be ignored. + return; + } // rethrow the error + + + throw err; + }); + return; + } + } else { + if (deviceTokenMatches.length == 1 && !deviceTokenMatches[0]['installationId']) { + // Exactly one device token match and it doesn't have an installation + // ID. This is the one case where we want to merge with the existing + // object. + const delQuery = { + objectId: idMatch.objectId + }; + return this.config.database.destroy('_Installation', delQuery).then(() => { + return deviceTokenMatches[0]['objectId']; + }).catch(err => { + if (err.code == Parse.Error.OBJECT_NOT_FOUND) { + // no deletions were made. Can be ignored + return; + } // rethrow the error + + + throw err; + }); + } else { + if (this.data.deviceToken && idMatch.deviceToken != this.data.deviceToken) { + // We're setting the device token on an existing installation, so + // we should try cleaning out old installations that match this + // device token. + const delQuery = { + deviceToken: this.data.deviceToken + }; // We have a unique install Id, use that to preserve + // the interesting installation + + if (this.data.installationId) { + delQuery['installationId'] = { + $ne: this.data.installationId + }; + } else if (idMatch.objectId && this.data.objectId && idMatch.objectId == this.data.objectId) { + // we passed an objectId, preserve that instalation + delQuery['objectId'] = { + $ne: idMatch.objectId + }; + } else { + // What to do here? can't really clean up everything... + return idMatch.objectId; + } + + if (this.data.appIdentifier) { + delQuery['appIdentifier'] = this.data.appIdentifier; + } + + this.config.database.destroy('_Installation', delQuery).catch(err => { + if (err.code == Parse.Error.OBJECT_NOT_FOUND) { + // no deletions were made. Can be ignored. + return; + } // rethrow the error + + + throw err; + }); + } // In non-merge scenarios, just return the installation match id + + + return idMatch.objectId; + } + } + }).then(objId => { + if (objId) { + this.query = { + objectId: objId + }; + delete this.data.objectId; + delete this.data.createdAt; + } // TODO: Validate ops (add/remove on channels, $inc on badge, etc.) + + }); + return promise; +}; // If we short-circuted the object response - then we need to make sure we expand all the files, +// since this might not have a query, meaning it won't return the full result back. +// TODO: (nlutsenko) This should die when we move to per-class based controllers on _Session/_User + + +RestWrite.prototype.expandFilesForExistingObjects = function () { + // Check whether we have a short-circuited response - only then run expansion. + if (this.response && this.response.response) { + this.config.filesController.expandFilesInObject(this.config, this.response.response); + } +}; + +RestWrite.prototype.runDatabaseOperation = function () { + if (this.response) { + return; + } + + if (this.className === '_Role') { + this.config.cacheController.role.clear(); + } + + if (this.className === '_User' && this.query && this.auth.isUnauthenticated()) { + throw new Parse.Error(Parse.Error.SESSION_MISSING, `Cannot modify user ${this.query.objectId}.`); + } + + if (this.className === '_Product' && this.data.download) { + this.data.downloadName = this.data.download.name; + } // TODO: Add better detection for ACL, ensuring a user can't be locked from + // their own user record. + + + if (this.data.ACL && this.data.ACL['*unresolved']) { + throw new Parse.Error(Parse.Error.INVALID_ACL, 'Invalid ACL.'); + } + + if (this.query) { + // Force the user to not lockout + // Matched with parse.com + if (this.className === '_User' && this.data.ACL && this.auth.isMaster !== true) { + this.data.ACL[this.query.objectId] = { + read: true, + write: true + }; + } // update password timestamp if user password is being changed + + + if (this.className === '_User' && this.data._hashed_password && this.config.passwordPolicy && this.config.passwordPolicy.maxPasswordAge) { + this.data._password_changed_at = Parse._encode(new Date()); + } // Ignore createdAt when update + + + delete this.data.createdAt; + let defer = Promise.resolve(); // if password history is enabled then save the current password to history + + if (this.className === '_User' && this.data._hashed_password && this.config.passwordPolicy && this.config.passwordPolicy.maxPasswordHistory) { + defer = this.config.database.find('_User', { + objectId: this.objectId() + }, { + keys: ['_password_history', '_hashed_password'] + }).then(results => { + if (results.length != 1) { + throw undefined; + } + + const user = results[0]; + let oldPasswords = []; + + if (user._password_history) { + oldPasswords = _lodash.default.take(user._password_history, this.config.passwordPolicy.maxPasswordHistory); + } //n-1 passwords go into history including last password + + + while (oldPasswords.length > Math.max(0, this.config.passwordPolicy.maxPasswordHistory - 2)) { + oldPasswords.shift(); + } + + oldPasswords.push(user.password); + this.data._password_history = oldPasswords; + }); + } + + return defer.then(() => { + // Run an update + return this.config.database.update(this.className, this.query, this.data, this.runOptions, false, false, this.validSchemaController).then(response => { + response.updatedAt = this.updatedAt; + + this._updateResponseWithData(response, this.data); + + this.response = { + response + }; + }); + }); + } else { + // Set the default ACL and password timestamp for the new _User + if (this.className === '_User') { + var ACL = this.data.ACL; // default public r/w ACL + + if (!ACL) { + ACL = {}; + ACL['*'] = { + read: true, + write: false + }; + } // make sure the user is not locked down + + + ACL[this.data.objectId] = { + read: true, + write: true + }; + this.data.ACL = ACL; // password timestamp to be used when password expiry policy is enforced + + if (this.config.passwordPolicy && this.config.passwordPolicy.maxPasswordAge) { + this.data._password_changed_at = Parse._encode(new Date()); + } + } // Run a create + + + return this.config.database.create(this.className, this.data, this.runOptions, false, this.validSchemaController).catch(error => { + if (this.className !== '_User' || error.code !== Parse.Error.DUPLICATE_VALUE) { + throw error; + } // Quick check, if we were able to infer the duplicated field name + + + if (error && error.userInfo && error.userInfo.duplicated_field === 'username') { + throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.'); + } + + if (error && error.userInfo && error.userInfo.duplicated_field === 'email') { + throw new Parse.Error(Parse.Error.EMAIL_TAKEN, 'Account already exists for this email address.'); + } // If this was a failed user creation due to username or email already taken, we need to + // check whether it was username or email and return the appropriate error. + // Fallback to the original method + // TODO: See if we can later do this without additional queries by using named indexes. + + + return this.config.database.find(this.className, { + username: this.data.username, + objectId: { + $ne: this.objectId() + } + }, { + limit: 1 + }).then(results => { + if (results.length > 0) { + throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.'); + } + + return this.config.database.find(this.className, { + email: this.data.email, + objectId: { + $ne: this.objectId() + } + }, { + limit: 1 + }); + }).then(results => { + if (results.length > 0) { + throw new Parse.Error(Parse.Error.EMAIL_TAKEN, 'Account already exists for this email address.'); + } + + throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided'); + }); + }).then(response => { + response.objectId = this.data.objectId; + response.createdAt = this.data.createdAt; + + if (this.responseShouldHaveUsername) { + response.username = this.data.username; + } + + this._updateResponseWithData(response, this.data); + + this.response = { + status: 201, + response, + location: this.location() + }; + }); + } +}; // Returns nothing - doesn't wait for the trigger. + + +RestWrite.prototype.runAfterSaveTrigger = function () { + if (!this.response || !this.response.response) { + return; + } // Avoid doing any setup for triggers if there is no 'afterSave' trigger for this class. + + + const hasAfterSaveHook = triggers.triggerExists(this.className, triggers.Types.afterSave, this.config.applicationId); + const hasLiveQuery = this.config.liveQueryController.hasLiveQuery(this.className); + + if (!hasAfterSaveHook && !hasLiveQuery) { + return Promise.resolve(); + } + + var extraData = { + className: this.className + }; + + if (this.query && this.query.objectId) { + extraData.objectId = this.query.objectId; + } // Build the original object, we only do this for a update write. + + + let originalObject; + + if (this.query && this.query.objectId) { + originalObject = triggers.inflate(extraData, this.originalData); + } // Build the inflated object, different from beforeSave, originalData is not empty + // since developers can change data in the beforeSave. + + + const updatedObject = this.buildUpdatedObject(extraData); + + updatedObject._handleSaveResponse(this.response.response, this.response.status || 200); + + this.config.database.loadSchema().then(schemaController => { + // Notifiy LiveQueryServer if possible + const perms = schemaController.getClassLevelPermissions(updatedObject.className); + this.config.liveQueryController.onAfterSave(updatedObject.className, updatedObject, originalObject, perms); + }); // Run afterSave trigger + + return triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config, this.context).then(result => { + if (result && typeof result === 'object') { + this.response.response = result; + } + }).catch(function (err) { + _logger.default.warn('afterSave caught an error', err); + }); +}; // A helper to figure out what location this operation happens at. + + +RestWrite.prototype.location = function () { + var middle = this.className === '_User' ? '/users/' : '/classes/' + this.className + '/'; + return this.config.mount + middle + this.data.objectId; +}; // A helper to get the object id for this operation. +// Because it could be either on the query or on the data + + +RestWrite.prototype.objectId = function () { + return this.data.objectId || this.query.objectId; +}; // Returns a copy of the data and delete bad keys (_auth_data, _hashed_password...) + + +RestWrite.prototype.sanitizedData = function () { + const data = Object.keys(this.data).reduce((data, key) => { + // Regexp comes from Parse.Object.prototype.validate + if (!/^[A-Za-z][0-9A-Za-z_]*$/.test(key)) { + delete data[key]; + } + + return data; + }, deepcopy(this.data)); + return Parse._decode(undefined, data); +}; // Returns an updated copy of the object + + +RestWrite.prototype.buildUpdatedObject = function (extraData) { + const updatedObject = triggers.inflate(extraData, this.originalData); + Object.keys(this.data).reduce(function (data, key) { + if (key.indexOf('.') > 0) { + // subdocument key with dot notation ('x.y':v => 'x':{'y':v}) + const splittedKey = key.split('.'); + const parentProp = splittedKey[0]; + let parentVal = updatedObject.get(parentProp); + + if (typeof parentVal !== 'object') { + parentVal = {}; + } + + parentVal[splittedKey[1]] = data[key]; + updatedObject.set(parentProp, parentVal); + delete data[key]; + } + + return data; + }, deepcopy(this.data)); + updatedObject.set(this.sanitizedData()); + return updatedObject; +}; + +RestWrite.prototype.cleanUserAuthData = function () { + if (this.response && this.response.response && this.className === '_User') { + const user = this.response.response; + + if (user.authData) { + Object.keys(user.authData).forEach(provider => { + if (user.authData[provider] === null) { + delete user.authData[provider]; + } + }); + + if (Object.keys(user.authData).length == 0) { + delete user.authData; + } + } + } +}; + +RestWrite.prototype._updateResponseWithData = function (response, data) { + if (_lodash.default.isEmpty(this.storage.fieldsChangedByTrigger)) { + return response; + } + + const clientSupportsDelete = ClientSDK.supportsForwardDelete(this.clientSDK); + this.storage.fieldsChangedByTrigger.forEach(fieldName => { + const dataValue = data[fieldName]; + + if (!Object.prototype.hasOwnProperty.call(response, fieldName)) { + response[fieldName] = dataValue; + } // Strips operations from responses + + + if (response[fieldName] && response[fieldName].__op) { + delete response[fieldName]; + + if (clientSupportsDelete && dataValue.__op == 'Delete') { + response[fieldName] = dataValue; + } + } + }); + return response; +}; + +var _default = RestWrite; +exports.default = _default; +module.exports = RestWrite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9SZXN0V3JpdGUuanMiXSwibmFtZXMiOlsiU2NoZW1hQ29udHJvbGxlciIsInJlcXVpcmUiLCJkZWVwY29weSIsIkF1dGgiLCJjcnlwdG9VdGlscyIsInBhc3N3b3JkQ3J5cHRvIiwiUGFyc2UiLCJ0cmlnZ2VycyIsIkNsaWVudFNESyIsIlJlc3RXcml0ZSIsImNvbmZpZyIsImF1dGgiLCJjbGFzc05hbWUiLCJxdWVyeSIsImRhdGEiLCJvcmlnaW5hbERhdGEiLCJjbGllbnRTREsiLCJpc1JlYWRPbmx5IiwiRXJyb3IiLCJPUEVSQVRJT05fRk9SQklEREVOIiwic3RvcmFnZSIsInJ1bk9wdGlvbnMiLCJjb250ZXh0Iiwib2JqZWN0SWQiLCJJTlZBTElEX0tFWV9OQU1FIiwiaWQiLCJyZXNwb25zZSIsInVwZGF0ZWRBdCIsIl9lbmNvZGUiLCJEYXRlIiwiaXNvIiwidmFsaWRTY2hlbWFDb250cm9sbGVyIiwicHJvdG90eXBlIiwiZXhlY3V0ZSIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsImdldFVzZXJBbmRSb2xlQUNMIiwidmFsaWRhdGVDbGllbnRDbGFzc0NyZWF0aW9uIiwiaGFuZGxlSW5zdGFsbGF0aW9uIiwiaGFuZGxlU2Vzc2lvbiIsInZhbGlkYXRlQXV0aERhdGEiLCJydW5CZWZvcmVTYXZlVHJpZ2dlciIsImRlbGV0ZUVtYWlsUmVzZXRUb2tlbklmTmVlZGVkIiwidmFsaWRhdGVTY2hlbWEiLCJzY2hlbWFDb250cm9sbGVyIiwic2V0UmVxdWlyZWRGaWVsZHNJZk5lZWRlZCIsInRyYW5zZm9ybVVzZXIiLCJleHBhbmRGaWxlc0ZvckV4aXN0aW5nT2JqZWN0cyIsImRlc3Ryb3lEdXBsaWNhdGVkU2Vzc2lvbnMiLCJydW5EYXRhYmFzZU9wZXJhdGlvbiIsImNyZWF0ZVNlc3Npb25Ub2tlbklmTmVlZGVkIiwiaGFuZGxlRm9sbG93dXAiLCJydW5BZnRlclNhdmVUcmlnZ2VyIiwiY2xlYW5Vc2VyQXV0aERhdGEiLCJpc01hc3RlciIsImFjbCIsInVzZXIiLCJnZXRVc2VyUm9sZXMiLCJyb2xlcyIsImNvbmNhdCIsImFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiIsInN5c3RlbUNsYXNzZXMiLCJpbmRleE9mIiwiZGF0YWJhc2UiLCJsb2FkU2NoZW1hIiwiaGFzQ2xhc3MiLCJ2YWxpZGF0ZU9iamVjdCIsInRyaWdnZXJFeGlzdHMiLCJUeXBlcyIsImJlZm9yZVNhdmUiLCJhcHBsaWNhdGlvbklkIiwiZXh0cmFEYXRhIiwib3JpZ2luYWxPYmplY3QiLCJ1cGRhdGVkT2JqZWN0IiwiYnVpbGRVcGRhdGVkT2JqZWN0IiwiaW5mbGF0ZSIsImRhdGFiYXNlUHJvbWlzZSIsInVwZGF0ZSIsImNyZWF0ZSIsInJlc3VsdCIsImxlbmd0aCIsIk9CSkVDVF9OT1RfRk9VTkQiLCJtYXliZVJ1blRyaWdnZXIiLCJvYmplY3QiLCJmaWVsZHNDaGFuZ2VkQnlUcmlnZ2VyIiwiXyIsInJlZHVjZSIsInZhbHVlIiwia2V5IiwiaXNFcXVhbCIsInB1c2giLCJydW5CZWZvcmVMb2dpblRyaWdnZXIiLCJ1c2VyRGF0YSIsImJlZm9yZUxvZ2luIiwiZ2V0QWxsQ2xhc3NlcyIsImFsbENsYXNzZXMiLCJzY2hlbWEiLCJmaW5kIiwib25lQ2xhc3MiLCJzZXRSZXF1aXJlZEZpZWxkSWZOZWVkZWQiLCJmaWVsZE5hbWUiLCJzZXREZWZhdWx0IiwidW5kZWZpbmVkIiwiX19vcCIsImZpZWxkcyIsImRlZmF1bHRWYWx1ZSIsInJlcXVpcmVkIiwiVkFMSURBVElPTl9FUlJPUiIsImNyZWF0ZWRBdCIsIm5ld09iamVjdElkIiwib2JqZWN0SWRTaXplIiwiT2JqZWN0Iiwia2V5cyIsImZvckVhY2giLCJhdXRoRGF0YSIsInVzZXJuYW1lIiwiaXNFbXB0eSIsIlVTRVJOQU1FX01JU1NJTkciLCJwYXNzd29yZCIsIlBBU1NXT1JEX01JU1NJTkciLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJVTlNVUFBPUlRFRF9TRVJWSUNFIiwicHJvdmlkZXJzIiwiY2FuSGFuZGxlQXV0aERhdGEiLCJjYW5IYW5kbGUiLCJwcm92aWRlciIsInByb3ZpZGVyQXV0aERhdGEiLCJoYXNUb2tlbiIsImhhbmRsZUF1dGhEYXRhIiwiaGFuZGxlQXV0aERhdGFWYWxpZGF0aW9uIiwidmFsaWRhdGlvbnMiLCJtYXAiLCJhdXRoRGF0YU1hbmFnZXIiLCJnZXRWYWxpZGF0b3JGb3JQcm92aWRlciIsImFsbCIsImZpbmRVc2Vyc1dpdGhBdXRoRGF0YSIsIm1lbW8iLCJxdWVyeUtleSIsImZpbHRlciIsInEiLCJmaW5kUHJvbWlzZSIsIiRvciIsImZpbHRlcmVkT2JqZWN0c0J5QUNMIiwib2JqZWN0cyIsIkFDTCIsInJlc3VsdHMiLCJyIiwiam9pbiIsInVzZXJSZXN1bHQiLCJtdXRhdGVkQXV0aERhdGEiLCJwcm92aWRlckRhdGEiLCJ1c2VyQXV0aERhdGEiLCJoYXNNdXRhdGVkQXV0aERhdGEiLCJ1c2VySWQiLCJsb2NhdGlvbiIsIkFDQ09VTlRfQUxSRUFEWV9MSU5LRUQiLCJwcm9taXNlIiwiZXJyb3IiLCJSZXN0UXVlcnkiLCJtYXN0ZXIiLCJfX3R5cGUiLCJzZXNzaW9uIiwiY2FjaGVDb250cm9sbGVyIiwiZGVsIiwic2Vzc2lvblRva2VuIiwiX3ZhbGlkYXRlUGFzc3dvcmRQb2xpY3kiLCJoYXNoIiwiaGFzaGVkUGFzc3dvcmQiLCJfaGFzaGVkX3Bhc3N3b3JkIiwiX3ZhbGlkYXRlVXNlck5hbWUiLCJfdmFsaWRhdGVFbWFpbCIsInJhbmRvbVN0cmluZyIsInJlc3BvbnNlU2hvdWxkSGF2ZVVzZXJuYW1lIiwiJG5lIiwibGltaXQiLCJVU0VSTkFNRV9UQUtFTiIsImVtYWlsIiwibWF0Y2giLCJyZWplY3QiLCJJTlZBTElEX0VNQUlMX0FERFJFU1MiLCJFTUFJTF9UQUtFTiIsInVzZXJDb250cm9sbGVyIiwic2V0RW1haWxWZXJpZnlUb2tlbiIsInBhc3N3b3JkUG9saWN5IiwiX3ZhbGlkYXRlUGFzc3dvcmRSZXF1aXJlbWVudHMiLCJfdmFsaWRhdGVQYXNzd29yZEhpc3RvcnkiLCJwb2xpY3lFcnJvciIsInZhbGlkYXRpb25FcnJvciIsImNvbnRhaW5zVXNlcm5hbWVFcnJvciIsInBhdHRlcm5WYWxpZGF0b3IiLCJ2YWxpZGF0b3JDYWxsYmFjayIsImRvTm90QWxsb3dVc2VybmFtZSIsIm1heFBhc3N3b3JkSGlzdG9yeSIsIm9sZFBhc3N3b3JkcyIsIl9wYXNzd29yZF9oaXN0b3J5IiwidGFrZSIsIm5ld1Bhc3N3b3JkIiwicHJvbWlzZXMiLCJjb21wYXJlIiwiY2F0Y2giLCJlcnIiLCJwcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsIiwidmVyaWZ5VXNlckVtYWlscyIsImNyZWF0ZVNlc3Npb25Ub2tlbiIsImluc3RhbGxhdGlvbklkIiwic2Vzc2lvbkRhdGEiLCJjcmVhdGVTZXNzaW9uIiwiY3JlYXRlZFdpdGgiLCJhY3Rpb24iLCJhdXRoUHJvdmlkZXIiLCJhZGRPcHMiLCJfcGVyaXNoYWJsZV90b2tlbiIsIl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQiLCJhc3NpZ24iLCJkZXN0cm95IiwicmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCIsInNlc3Npb25RdWVyeSIsImJpbmQiLCJzZW5kVmVyaWZpY2F0aW9uRW1haWwiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJhZGRpdGlvbmFsU2Vzc2lvbkRhdGEiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJzdGF0dXMiLCJkZXZpY2VUb2tlbiIsInRvTG93ZXJDYXNlIiwiZGV2aWNlVHlwZSIsImlkTWF0Y2giLCJvYmplY3RJZE1hdGNoIiwiaW5zdGFsbGF0aW9uSWRNYXRjaCIsImRldmljZVRva2VuTWF0Y2hlcyIsIm9yUXVlcmllcyIsImRlbFF1ZXJ5IiwiYXBwSWRlbnRpZmllciIsImNvZGUiLCJvYmpJZCIsImZpbGVzQ29udHJvbGxlciIsImV4cGFuZEZpbGVzSW5PYmplY3QiLCJyb2xlIiwiY2xlYXIiLCJpc1VuYXV0aGVudGljYXRlZCIsIlNFU1NJT05fTUlTU0lORyIsImRvd25sb2FkIiwiZG93bmxvYWROYW1lIiwibmFtZSIsIklOVkFMSURfQUNMIiwicmVhZCIsIndyaXRlIiwibWF4UGFzc3dvcmRBZ2UiLCJfcGFzc3dvcmRfY2hhbmdlZF9hdCIsImRlZmVyIiwiTWF0aCIsIm1heCIsInNoaWZ0IiwiX3VwZGF0ZVJlc3BvbnNlV2l0aERhdGEiLCJEVVBMSUNBVEVfVkFMVUUiLCJ1c2VySW5mbyIsImR1cGxpY2F0ZWRfZmllbGQiLCJoYXNBZnRlclNhdmVIb29rIiwiYWZ0ZXJTYXZlIiwiaGFzTGl2ZVF1ZXJ5IiwibGl2ZVF1ZXJ5Q29udHJvbGxlciIsIl9oYW5kbGVTYXZlUmVzcG9uc2UiLCJwZXJtcyIsImdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsIm9uQWZ0ZXJTYXZlIiwibG9nZ2VyIiwid2FybiIsIm1pZGRsZSIsIm1vdW50Iiwic2FuaXRpemVkRGF0YSIsInRlc3QiLCJfZGVjb2RlIiwic3BsaXR0ZWRLZXkiLCJzcGxpdCIsInBhcmVudFByb3AiLCJwYXJlbnRWYWwiLCJnZXQiLCJzZXQiLCJjbGllbnRTdXBwb3J0c0RlbGV0ZSIsInN1cHBvcnRzRm9yd2FyZERlbGV0ZSIsImRhdGFWYWx1ZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFhQTs7QUFDQTs7QUFDQTs7OztBQWZBO0FBQ0E7QUFDQTtBQUVBLElBQUlBLGdCQUFnQixHQUFHQyxPQUFPLENBQUMsZ0NBQUQsQ0FBOUI7O0FBQ0EsSUFBSUMsUUFBUSxHQUFHRCxPQUFPLENBQUMsVUFBRCxDQUF0Qjs7QUFFQSxNQUFNRSxJQUFJLEdBQUdGLE9BQU8sQ0FBQyxRQUFELENBQXBCOztBQUNBLElBQUlHLFdBQVcsR0FBR0gsT0FBTyxDQUFDLGVBQUQsQ0FBekI7O0FBQ0EsSUFBSUksY0FBYyxHQUFHSixPQUFPLENBQUMsWUFBRCxDQUE1Qjs7QUFDQSxJQUFJSyxLQUFLLEdBQUdMLE9BQU8sQ0FBQyxZQUFELENBQW5COztBQUNBLElBQUlNLFFBQVEsR0FBR04sT0FBTyxDQUFDLFlBQUQsQ0FBdEI7O0FBQ0EsSUFBSU8sU0FBUyxH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UUFBckMsRUFBK0MyRSxTQUEvQyxDQUFMLEVBQWdFO0FBQzlEM0UsTUFBQUEsUUFBUSxDQUFDMkUsU0FBRCxDQUFSLEdBQXNCcUwsU0FBdEI7QUFDRCxLQUxzRCxDQU92RDs7O0FBQ0EsUUFBSWhRLFFBQVEsQ0FBQzJFLFNBQUQsQ0FBUixJQUF1QjNFLFFBQVEsQ0FBQzJFLFNBQUQsQ0FBUixDQUFvQkcsSUFBL0MsRUFBcUQ7QUFDbkQsYUFBTzlFLFFBQVEsQ0FBQzJFLFNBQUQsQ0FBZjs7QUFDQSxVQUFJbUwsb0JBQW9CLElBQUlFLFNBQVMsQ0FBQ2xMLElBQVYsSUFBa0IsUUFBOUMsRUFBd0Q7QUFDdEQ5RSxRQUFBQSxRQUFRLENBQUMyRSxTQUFELENBQVIsR0FBc0JxTCxTQUF0QjtBQUNEO0FBQ0Y7QUFDRixHQWREO0FBZUEsU0FBT2hRLFFBQVA7QUFDRCxDQXJCRDs7ZUF1QmVqQixTOztBQUNma1IsTUFBTSxDQUFDQyxPQUFQLEdBQWlCblIsU0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBBIFJlc3RXcml0ZSBlbmNhcHN1bGF0ZXMgZXZlcnl0aGluZyB3ZSBuZWVkIHRvIHJ1biBhbiBvcGVyYXRpb25cbi8vIHRoYXQgd3JpdGVzIHRvIHRoZSBkYXRhYmFzZS5cbi8vIFRoaXMgY291bGQgYmUgZWl0aGVyIGEgXCJjcmVhdGVcIiBvciBhbiBcInVwZGF0ZVwiLlxuXG52YXIgU2NoZW1hQ29udHJvbGxlciA9IHJlcXVpcmUoJy4vQ29udHJvbGxlcnMvU2NoZW1hQ29udHJvbGxlcicpO1xudmFyIGRlZXBjb3B5ID0gcmVxdWlyZSgnZGVlcGNvcHknKTtcblxuY29uc3QgQXV0aCA9IHJlcXVpcmUoJy4vQXV0aCcpO1xudmFyIGNyeXB0b1V0aWxzID0gcmVxdWlyZSgnLi9jcnlwdG9VdGlscycpO1xudmFyIHBhc3N3b3JkQ3J5cHRvID0gcmVxdWlyZSgnLi9wYXNzd29yZCcpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpO1xudmFyIHRyaWdnZXJzID0gcmVxdWlyZSgnLi90cmlnZ2VycycpO1xudmFyIENsaWVudFNESyA9IHJlcXVpcmUoJy4vQ2xpZW50U0RLJyk7XG5pbXBvcnQgUmVzdFF1ZXJ5IGZyb20gJy4vUmVzdFF1ZXJ5JztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4vbG9nZ2VyJztcblxuLy8gcXVlcnkgYW5kIGRhdGEgYXJlIGJvdGggcHJvdmlkZWQgaW4gUkVTVCBBUEkgZm9ybWF0LiBTbyBkYXRhXG4vLyB0eXBlcyBhcmUgZW5jb2RlZCBieSBwbGFpbiBvbGQgb2JqZWN0cy5cbi8vIElmIHF1ZXJ5IGlzIG51bGwsIHRoaXMgaXMgYSBcImNyZWF0ZVwiIGFuZCB0aGUgZGF0YSBpbiBkYXRhIHNob3VsZCBiZVxuLy8gY3JlYXRlZC5cbi8vIE90aGVyd2lzZSB0aGlzIGlzIGFuIFwidXBkYXRlXCIgLSB0aGUgb2JqZWN0IG1hdGNoaW5nIHRoZSBxdWVyeVxuLy8gc2hvdWxkIGdldCB1cGRhdGVkIHdpdGggZGF0YS5cbi8vIFJlc3RXcml0ZSB3aWxsIGhhbmRsZSBvYmplY3RJZCwgY3JlYXRlZEF0LCBhbmQgdXBkYXRlZEF0IGZvclxuLy8gZXZlcnl0aGluZy4gSXQgYWxzbyBrbm93cyB0byB1c2UgdHJpZ2dlcnMgYW5kIHNwZWNpYWwgbW9kaWZpY2F0aW9uc1xuLy8gZm9yIHRoZSBfVXNlciBjbGFzcy5cbmZ1bmN0aW9uIFJlc3RXcml0ZShcbiAgY29uZmlnLFxuICBhdXRoLFxuICBjbGFzc05hbWUsXG4gIHF1ZXJ5LFxuICBkYXRhLFxuICBvcmlnaW5hbERhdGEsXG4gIGNsaWVudFNES1xuKSB7XG4gIGlmIChhdXRoLmlzUmVhZE9ubHkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgJ0Nhbm5vdCBwZXJmb3JtIGEgd3JpdGUgb3BlcmF0aW9uIHdoZW4gdXNpbmcgcmVhZE9ubHlNYXN0ZXJLZXknXG4gICAgKTtcbiAgfVxuICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgdGhpcy5hdXRoID0gYXV0aDtcbiAgdGhpcy5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gIHRoaXMuY2xpZW50U0RLID0gY2xpZW50U0RLO1xuICB0aGlzLnN0b3JhZ2UgPSB7fTtcbiAgdGhpcy5ydW5PcHRpb25zID0ge307XG4gIHRoaXMuY29udGV4dCA9IHt9O1xuICBpZiAoIXF1ZXJ5ICYmIGRhdGEub2JqZWN0SWQpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgJ29iamVjdElkIGlzIGFuIGludmFsaWQgZmllbGQgbmFtZS4nXG4gICAgKTtcbiAgfVxuICBpZiAoIXF1ZXJ5ICYmIGRhdGEuaWQpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgJ2lkIGlzIGFuIGludmFsaWQgZmllbGQgbmFtZS4nXG4gICAgKTtcbiAgfVxuXG4gIC8vIFdoZW4gdGhlIG9wZXJhdGlvbiBpcyBjb21wbGV0ZSwgdGhpcy5yZXNwb25zZSBtYXkgaGF2ZSBzZXZlcmFsXG4gIC8vIGZpZWxkcy5cbiAgLy8gcmVzcG9uc2U6IHRoZSBhY3R1YWwgZGF0YSB0byBiZSByZXR1cm5lZFxuICAvLyBzdGF0dXM6IHRoZSBodHRwIHN0YXR1cyBjb2RlLiBpZiBub3QgcHJlc2VudCwgdHJlYXRlZCBsaWtlIGEgMjAwXG4gIC8vIGxvY2F0aW9uOiB0aGUgbG9jYXRpb24gaGVhZGVyLiBpZiBub3QgcHJlc2VudCwgbm8gbG9jYXRpb24gaGVhZGVyXG4gIHRoaXMucmVzcG9uc2UgPSBudWxsO1xuXG4gIC8vIFByb2Nlc3NpbmcgdGhpcyBvcGVyYXRpb24gbWF5IG11dGF0ZSBvdXIgZGF0YSwgc28gd2Ugb3BlcmF0ZSBvbiBhXG4gIC8vIGNvcHlcbiAgdGhpcy5xdWVyeSA9IGRlZXBjb3B5KHF1ZXJ5KTtcbiAgdGhpcy5kYXRhID0gZGVlcGNvcHkoZGF0YSk7XG4gIC8vIFdlIG5ldmVyIGNoYW5nZSBvcmlnaW5hbERhdGEsIHNvIHdlIGRvIG5vdCBuZWVkIGEgZGVlcCBjb3B5XG4gIHRoaXMub3JpZ2luYWxEYXRhID0gb3JpZ2luYWxEYXRhO1xuXG4gIC8vIFRoZSB0aW1lc3RhbXAgd2UnbGwgdXNlIGZvciB0aGlzIHdob2xlIG9wZXJhdGlvblxuICB0aGlzLnVwZGF0ZWRBdCA9IFBhcnNlLl9lbmNvZGUobmV3IERhdGUoKSkuaXNvO1xuXG4gIC8vIFNoYXJlZCBTY2hlbWFDb250cm9sbGVyIHRvIGJlIHJldXNlZCB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBsb2FkU2NoZW1hKCkgY2FsbHMgcGVyIHJlcXVlc3RcbiAgLy8gT25jZSBzZXQgdGhlIHNjaGVtYURhdGEgc2hvdWxkIGJlIGltbXV0YWJsZVxuICB0aGlzLnZhbGlkU2NoZW1hQ29udHJvbGxlciA9IG51bGw7XG59XG5cbi8vIEEgY29udmVuaWVudCBtZXRob2QgdG8gcGVyZm9ybSBhbGwgdGhlIHN0ZXBzIG9mIHByb2Nlc3NpbmcgdGhlXG4vLyB3cml0ZSwgaW4gb3JkZXIuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSB7cmVzcG9uc2UsIHN0YXR1cywgbG9jYXRpb259IG9iamVjdC5cbi8vIHN0YXR1cyBhbmQgbG9jYXRpb24gYXJlIG9wdGlvbmFsLlxuUmVzdFdyaXRlLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmdldFVzZXJBbmRSb2xlQUNMKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZUNsaWVudENsYXNzQ3JlYXRpb24oKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUluc3RhbGxhdGlvbigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlU2Vzc2lvbigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVBdXRoRGF0YSgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucnVuQmVmb3JlU2F2ZVRyaWdnZXIoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmRlbGV0ZUVtYWlsUmVzZXRUb2tlbklmTmVlZGVkKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZVNjaGVtYSgpO1xuICAgIH0pXG4gICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgICB0aGlzLnZhbGlkU2NoZW1hQ29udHJvbGxlciA9IHNjaGVtYUNvbnRyb2xsZXI7XG4gICAgICByZXR1cm4gdGhpcy5zZXRSZXF1aXJlZEZpZWxkc0lmTmVlZGVkKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy50cmFuc2Zvcm1Vc2VyKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5leHBhbmRGaWxlc0ZvckV4aXN0aW5nT2JqZWN0cygpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzdHJveUR1cGxpY2F0ZWRTZXNzaW9ucygpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucnVuRGF0YWJhc2VPcGVyYXRpb24oKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVNlc3Npb25Ub2tlbklmTmVlZGVkKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVGb2xsb3d1cCgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucnVuQWZ0ZXJTYXZlVHJpZ2dlcigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuY2xlYW5Vc2VyQXV0aERhdGEoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlc3BvbnNlO1xuICAgIH0pO1xufTtcblxuLy8gVXNlcyB0aGUgQXV0aCBvYmplY3QgdG8gZ2V0IHRoZSBsaXN0IG9mIHJvbGVzLCBhZGRzIHRoZSB1c2VyIGlkXG5SZXN0V3JpdGUucHJvdG90eXBlLmdldFVzZXJBbmRSb2xlQUNMID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICB0aGlzLnJ1bk9wdGlvbnMuYWNsID0gWycqJ107XG5cbiAgaWYgKHRoaXMuYXV0aC51c2VyKSB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5nZXRVc2VyUm9sZXMoKS50aGVuKHJvbGVzID0+IHtcbiAgICAgIHRoaXMucnVuT3B0aW9ucy5hY2wgPSB0aGlzLnJ1bk9wdGlvbnMuYWNsLmNvbmNhdChyb2xlcywgW1xuICAgICAgICB0aGlzLmF1dGgudXNlci5pZCxcbiAgICAgIF0pO1xuICAgICAgcmV0dXJuO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufTtcblxuLy8gVmFsaWRhdGVzIHRoaXMgb3BlcmF0aW9uIGFnYWluc3QgdGhlIGFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiBjb25maWcuXG5SZXN0V3JpdGUucHJvdG90eXBlLnZhbGlkYXRlQ2xpZW50Q2xhc3NDcmVhdGlvbiA9IGZ1bmN0aW9uKCkge1xuICBpZiAoXG4gICAgdGhpcy5jb25maWcuYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uID09PSBmYWxzZSAmJlxuICAgICF0aGlzLmF1dGguaXNNYXN0ZXIgJiZcbiAgICBTY2hlbWFDb250cm9sbGVyLnN5c3RlbUNsYXNzZXMuaW5kZXhPZih0aGlzLmNsYXNzTmFtZSkgPT09IC0xXG4gICkge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgLmxvYWRTY2hlbWEoKVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmhhc0NsYXNzKHRoaXMuY2xhc3NOYW1lKSlcbiAgICAgIC50aGVuKGhhc0NsYXNzID0+IHtcbiAgICAgICAgaWYgKGhhc0NsYXNzICE9PSB0cnVlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTixcbiAgICAgICAgICAgICdUaGlzIHVzZXIgaXMgbm90IGFsbG93ZWQgdG8gYWNjZXNzICcgK1xuICAgICAgICAgICAgICAnbm9uLWV4aXN0ZW50IGNsYXNzOiAnICtcbiAgICAgICAgICAgICAgdGhpcy5jbGFzc05hbWVcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn07XG5cbi8vIFZhbGlkYXRlcyB0aGlzIG9wZXJhdGlvbiBhZ2FpbnN0IHRoZSBzY2hlbWEuXG5SZXN0V3JpdGUucHJvdG90eXBlLnZhbGlkYXRlU2NoZW1hID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS52YWxpZGF0ZU9iamVjdChcbiAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICB0aGlzLmRhdGEsXG4gICAgdGhpcy5xdWVyeSxcbiAgICB0aGlzLnJ1bk9wdGlvbnNcbiAgKTtcbn07XG5cbi8vIFJ1bnMgYW55IGJlZm9yZVNhdmUgdHJpZ2dlcnMgYWdhaW5zdCB0aGlzIG9wZXJhdGlvbi5cbi8vIEFueSBjaGFuZ2UgbGVhZHMgdG8gb3VyIGRhdGEgYmVpbmcgbXV0YXRlZC5cblJlc3RXcml0ZS5wcm90b3R5cGUucnVuQmVmb3JlU2F2ZVRyaWdnZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMucmVzcG9uc2UpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBBdm9pZCBkb2luZyBhbnkgc2V0dXAgZm9yIHRyaWdnZXJzIGlmIHRoZXJlIGlzIG5vICdiZWZvcmVTYXZlJyB0cmlnZ2VyIGZvciB0aGlzIGNsYXNzLlxuICBpZiAoXG4gICAgIXRyaWdnZXJzLnRyaWdnZXJFeGlzdHMoXG4gICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsXG4gICAgICB0aGlzLmNvbmZpZy5hcHBsaWNhdGlvbklkXG4gICAgKVxuICApIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICAvLyBDbG91ZCBjb2RlIGdldHMgYSBiaXQgb2YgZXh0cmEgZGF0YSBmb3IgaXRzIG9iamVjdHNcbiAgdmFyIGV4dHJhRGF0YSA9IHsgY2xhc3NOYW1lOiB0aGlzLmNsYXNzTmFtZSB9O1xuICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgZXh0cmFEYXRhLm9iamVjdElkID0gdGhpcy5xdWVyeS5vYmplY3RJZDtcbiAgfVxuXG4gIGxldCBvcmlnaW5hbE9iamVjdCA9IG51bGw7XG4gIGNvbnN0IHVwZGF0ZWRPYmplY3QgPSB0aGlzLmJ1aWxkVXBkYXRlZE9iamVjdChleHRyYURhdGEpO1xuICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgLy8gVGhpcyBpcyBhbiB1cGRhdGUgZm9yIGV4aXN0aW5nIG9iamVjdC5cbiAgICBvcmlnaW5hbE9iamVjdCA9IHRyaWdnZXJzLmluZmxhdGUoZXh0cmFEYXRhLCB0aGlzLm9yaWdpbmFsRGF0YSk7XG4gIH1cblxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICAvLyBCZWZvcmUgY2FsbGluZyB0aGUgdHJpZ2dlciwgdmFsaWRhdGUgdGhlIHBlcm1pc3Npb25zIGZvciB0aGUgc2F2ZSBvcGVyYXRpb25cbiAgICAgIGxldCBkYXRhYmFzZVByb21pc2UgPSBudWxsO1xuICAgICAgaWYgKHRoaXMucXVlcnkpIHtcbiAgICAgICAgLy8gVmFsaWRhdGUgZm9yIHVwZGF0aW5nXG4gICAgICAgIGRhdGFiYXNlUHJvbWlzZSA9IHRoaXMuY29uZmlnLmRhdGFiYXNlLnVwZGF0ZShcbiAgICAgICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgICAgICB0aGlzLnF1ZXJ5LFxuICAgICAgICAgIHRoaXMuZGF0YSxcbiAgICAgICAgICB0aGlzLnJ1bk9wdGlvbnMsXG4gICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgdHJ1ZVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVmFsaWRhdGUgZm9yIGNyZWF0aW5nXG4gICAgICAgIGRhdGFiYXNlUHJvbWlzZSA9IHRoaXMuY29uZmlnLmRhdGFiYXNlLmNyZWF0ZShcbiAgICAgICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgICAgICB0aGlzLmRhdGEsXG4gICAgICAgICAgdGhpcy5ydW5PcHRpb25zLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIC8vIEluIHRoZSBjYXNlIHRoYXQgdGhlcmUgaXMgbm8gcGVybWlzc2lvbiBmb3IgdGhlIG9wZXJhdGlvbiwgaXQgdGhyb3dzIGFuIGVycm9yXG4gICAgICByZXR1cm4gZGF0YWJhc2VQcm9taXNlLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgaWYgKCFyZXN1bHQgfHwgcmVzdWx0Lmxlbmd0aCA8PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICdPYmplY3Qgbm90IGZvdW5kLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0cmlnZ2Vycy5tYXliZVJ1blRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsXG4gICAgICAgIHRoaXMuYXV0aCxcbiAgICAgICAgdXBkYXRlZE9iamVjdCxcbiAgICAgICAgb3JpZ2luYWxPYmplY3QsXG4gICAgICAgIHRoaXMuY29uZmlnLFxuICAgICAgICB0aGlzLmNvbnRleHRcbiAgICAgICk7XG4gICAgfSlcbiAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2Uub2JqZWN0KSB7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5maWVsZHNDaGFuZ2VkQnlUcmlnZ2VyID0gXy5yZWR1Y2UoXG4gICAgICAgICAgcmVzcG9uc2Uub2JqZWN0LFxuICAgICAgICAgIChyZXN1bHQsIHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICAgIGlmICghXy5pc0VxdWFsKHRoaXMuZGF0YVtrZXldLCB2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBbXVxuICAgICAgICApO1xuICAgICAgICB0aGlzLmRhdGEgPSByZXNwb25zZS5vYmplY3Q7XG4gICAgICAgIC8vIFdlIHNob3VsZCBkZWxldGUgdGhlIG9iamVjdElkIGZvciBhbiB1cGRhdGUgd3JpdGVcbiAgICAgICAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgICAgICAgIGRlbGV0ZSB0aGlzLmRhdGEub2JqZWN0SWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUucnVuQmVmb3JlTG9naW5UcmlnZ2VyID0gYXN5bmMgZnVuY3Rpb24odXNlckRhdGEpIHtcbiAgLy8gQXZvaWQgZG9pbmcgYW55IHNldHVwIGZvciB0cmlnZ2VycyBpZiB0aGVyZSBpcyBubyAnYmVmb3JlTG9naW4nIHRyaWdnZXJcbiAgaWYgKFxuICAgICF0cmlnZ2Vycy50cmlnZ2VyRXhpc3RzKFxuICAgICAgdGhpcy5jbGFzc05hbWUsXG4gICAgICB0cmlnZ2Vycy5UeXBlcy5iZWZvcmVMb2dpbixcbiAgICAgIHRoaXMuY29uZmlnLmFwcGxpY2F0aW9uSWRcbiAgICApXG4gICkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIENsb3VkIGNvZGUgZ2V0cyBhIGJpdCBvZiBleHRyYSBkYXRhIGZvciBpdHMgb2JqZWN0c1xuICBjb25zdCBleHRyYURhdGEgPSB7IGNsYXNzTmFtZTogdGhpcy5jbGFzc05hbWUgfTtcbiAgY29uc3QgdXNlciA9IHRyaWdnZXJzLmluZmxhdGUoZXh0cmFEYXRhLCB1c2VyRGF0YSk7XG5cbiAgLy8gbm8gbmVlZCB0byByZXR1cm4gYSByZXNwb25zZVxuICBhd2FpdCB0cmlnZ2Vycy5tYXliZVJ1blRyaWdnZXIoXG4gICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlTG9naW4sXG4gICAgdGhpcy5hdXRoLFxuICAgIHVzZXIsXG4gICAgbnVsbCxcbiAgICB0aGlzLmNvbmZpZyxcbiAgICB0aGlzLmNvbnRleHRcbiAgKTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuc2V0UmVxdWlyZWRGaWVsZHNJZk5lZWRlZCA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5kYXRhKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyLmdldEFsbENsYXNzZXMoKS50aGVuKGFsbENsYXNzZXMgPT4ge1xuICAgICAgY29uc3Qgc2NoZW1hID0gYWxsQ2xhc3Nlcy5maW5kKFxuICAgICAgICBvbmVDbGFzcyA9PiBvbmVDbGFzcy5jbGFzc05hbWUgPT09IHRoaXMuY2xhc3NOYW1lXG4gICAgICApO1xuICAgICAgY29uc3Qgc2V0UmVxdWlyZWRGaWVsZElmTmVlZGVkID0gKGZpZWxkTmFtZSwgc2V0RGVmYXVsdCkgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5kYXRhW2ZpZWxkTmFtZV0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgIHRoaXMuZGF0YVtmaWVsZE5hbWVdID09PSBudWxsIHx8XG4gICAgICAgICAgdGhpcy5kYXRhW2ZpZWxkTmFtZV0gPT09ICcnIHx8XG4gICAgICAgICAgKHR5cGVvZiB0aGlzLmRhdGFbZmllbGROYW1lXSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgIHRoaXMuZGF0YVtmaWVsZE5hbWVdLl9fb3AgPT09ICdEZWxldGUnKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBzZXREZWZhdWx0ICYmXG4gICAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiZcbiAgICAgICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5kZWZhdWx0VmFsdWUgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5kZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgKHRoaXMuZGF0YVtmaWVsZE5hbWVdID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgICAgKHR5cGVvZiB0aGlzLmRhdGFbZmllbGROYW1lXSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFbZmllbGROYW1lXS5fX29wID09PSAnRGVsZXRlJykpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFbZmllbGROYW1lXSA9IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5kZWZhdWx0VmFsdWU7XG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2UuZmllbGRzQ2hhbmdlZEJ5VHJpZ2dlciA9XG4gICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5maWVsZHNDaGFuZ2VkQnlUcmlnZ2VyIHx8IFtdO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RvcmFnZS5maWVsZHNDaGFuZ2VkQnlUcmlnZ2VyLmluZGV4T2YoZmllbGROYW1lKSA8IDApIHtcbiAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLmZpZWxkc0NoYW5nZWRCeVRyaWdnZXIucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiZcbiAgICAgICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5yZXF1aXJlZCA9PT0gdHJ1ZVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5WQUxJREFUSU9OX0VSUk9SLFxuICAgICAgICAgICAgICBgJHtmaWVsZE5hbWV9IGlzIHJlcXVpcmVkYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vIEFkZCBkZWZhdWx0IGZpZWxkc1xuICAgICAgdGhpcy5kYXRhLnVwZGF0ZWRBdCA9IHRoaXMudXBkYXRlZEF0O1xuICAgICAgaWYgKCF0aGlzLnF1ZXJ5KSB7XG4gICAgICAgIHRoaXMuZGF0YS5jcmVhdGVkQXQgPSB0aGlzLnVwZGF0ZWRBdDtcblxuICAgICAgICAvLyBPbmx5IGFzc2lnbiBuZXcgb2JqZWN0SWQgaWYgd2UgYXJlIGNyZWF0aW5nIG5ldyBvYmplY3RcbiAgICAgICAgaWYgKCF0aGlzLmRhdGEub2JqZWN0SWQpIHtcbiAgICAgICAgICB0aGlzLmRhdGEub2JqZWN0SWQgPSBjcnlwdG9VdGlscy5uZXdPYmplY3RJZChcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLm9iamVjdElkU2l6ZVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNjaGVtYSkge1xuICAgICAgICAgIE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICAgIHNldFJlcXVpcmVkRmllbGRJZk5lZWRlZChmaWVsZE5hbWUsIHRydWUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHNjaGVtYSkge1xuICAgICAgICBPYmplY3Qua2V5cyh0aGlzLmRhdGEpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICBzZXRSZXF1aXJlZEZpZWxkSWZOZWVkZWQoZmllbGROYW1lLCBmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn07XG5cbi8vIFRyYW5zZm9ybXMgYXV0aCBkYXRhIGZvciBhIHVzZXIgb2JqZWN0LlxuLy8gRG9lcyBub3RoaW5nIGlmIHRoaXMgaXNuJ3QgYSB1c2VyIG9iamVjdC5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciB3aGVuIHdlJ3JlIGRvbmUgaWYgaXQgY2FuJ3QgZmluaXNoIHRoaXMgdGljay5cblJlc3RXcml0ZS5wcm90b3R5cGUudmFsaWRhdGVBdXRoRGF0YSA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIXRoaXMucXVlcnkgJiYgIXRoaXMuZGF0YS5hdXRoRGF0YSkge1xuICAgIGlmIChcbiAgICAgIHR5cGVvZiB0aGlzLmRhdGEudXNlcm5hbWUgIT09ICdzdHJpbmcnIHx8XG4gICAgICBfLmlzRW1wdHkodGhpcy5kYXRhLnVzZXJuYW1lKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5VU0VSTkFNRV9NSVNTSU5HLFxuICAgICAgICAnYmFkIG9yIG1pc3NpbmcgdXNlcm5hbWUnXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICB0eXBlb2YgdGhpcy5kYXRhLnBhc3N3b3JkICE9PSAnc3RyaW5nJyB8fFxuICAgICAgXy5pc0VtcHR5KHRoaXMuZGF0YS5wYXNzd29yZClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUEFTU1dPUkRfTUlTU0lORyxcbiAgICAgICAgJ3Bhc3N3b3JkIGlzIHJlcXVpcmVkJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAoXG4gICAgKHRoaXMuZGF0YS5hdXRoRGF0YSAmJiAhT2JqZWN0LmtleXModGhpcy5kYXRhLmF1dGhEYXRhKS5sZW5ndGgpIHx8XG4gICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmRhdGEsICdhdXRoRGF0YScpXG4gICkge1xuICAgIC8vIEhhbmRsZSBzYXZpbmcgYXV0aERhdGEgdG8ge30gb3IgaWYgYXV0aERhdGEgZG9lc24ndCBleGlzdFxuICAgIHJldHVybjtcbiAgfSBlbHNlIGlmIChcbiAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcy5kYXRhLCAnYXV0aERhdGEnKSAmJlxuICAgICF0aGlzLmRhdGEuYXV0aERhdGFcbiAgKSB7XG4gICAgLy8gSGFuZGxlIHNhdmluZyBhdXRoRGF0YSB0byBudWxsXG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuVU5TVVBQT1JURURfU0VSVklDRSxcbiAgICAgICdUaGlzIGF1dGhlbnRpY2F0aW9uIG1ldGhvZCBpcyB1bnN1cHBvcnRlZC4nXG4gICAgKTtcbiAgfVxuXG4gIHZhciBhdXRoRGF0YSA9IHRoaXMuZGF0YS5hdXRoRGF0YTtcbiAgdmFyIHByb3ZpZGVycyA9IE9iamVjdC5rZXlzKGF1dGhEYXRhKTtcbiAgaWYgKHByb3ZpZGVycy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgY2FuSGFuZGxlQXV0aERhdGEgPSBwcm92aWRlcnMucmVkdWNlKChjYW5IYW5kbGUsIHByb3ZpZGVyKSA9PiB7XG4gICAgICB2YXIgcHJvdmlkZXJBdXRoRGF0YSA9IGF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgIHZhciBoYXNUb2tlbiA9IHByb3ZpZGVyQXV0aERhdGEgJiYgcHJvdmlkZXJBdXRoRGF0YS5pZDtcbiAgICAgIHJldHVybiBjYW5IYW5kbGUgJiYgKGhhc1Rva2VuIHx8IHByb3ZpZGVyQXV0aERhdGEgPT0gbnVsbCk7XG4gICAgfSwgdHJ1ZSk7XG4gICAgaWYgKGNhbkhhbmRsZUF1dGhEYXRhKSB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVBdXRoRGF0YShhdXRoRGF0YSk7XG4gICAgfVxuICB9XG4gIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICBQYXJzZS5FcnJvci5VTlNVUFBPUlRFRF9TRVJWSUNFLFxuICAgICdUaGlzIGF1dGhlbnRpY2F0aW9uIG1ldGhvZCBpcyB1bnN1cHBvcnRlZC4nXG4gICk7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLmhhbmRsZUF1dGhEYXRhVmFsaWRhdGlvbiA9IGZ1bmN0aW9uKGF1dGhEYXRhKSB7XG4gIGNvbnN0IHZhbGlkYXRpb25zID0gT2JqZWN0LmtleXMoYXV0aERhdGEpLm1hcChwcm92aWRlciA9PiB7XG4gICAgaWYgKGF1dGhEYXRhW3Byb3ZpZGVyXSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICBjb25zdCB2YWxpZGF0ZUF1dGhEYXRhID0gdGhpcy5jb25maWcuYXV0aERhdGFNYW5hZ2VyLmdldFZhbGlkYXRvckZvclByb3ZpZGVyKFxuICAgICAgcHJvdmlkZXJcbiAgICApO1xuICAgIGlmICghdmFsaWRhdGVBdXRoRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5VTlNVUFBPUlRFRF9TRVJWSUNFLFxuICAgICAgICAnVGhpcyBhdXRoZW50aWNhdGlvbiBtZXRob2QgaXMgdW5zdXBwb3J0ZWQuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGFbcHJvdmlkZXJdKTtcbiAgfSk7XG4gIHJldHVybiBQcm9taXNlLmFsbCh2YWxpZGF0aW9ucyk7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLmZpbmRVc2Vyc1dpdGhBdXRoRGF0YSA9IGZ1bmN0aW9uKGF1dGhEYXRhKSB7XG4gIGNvbnN0IHByb3ZpZGVycyA9IE9iamVjdC5rZXlzKGF1dGhEYXRhKTtcbiAgY29uc3QgcXVlcnkgPSBwcm92aWRlcnNcbiAgICAucmVkdWNlKChtZW1vLCBwcm92aWRlcikgPT4ge1xuICAgICAgaWYgKCFhdXRoRGF0YVtwcm92aWRlcl0pIHtcbiAgICAgICAgcmV0dXJuIG1lbW87XG4gICAgICB9XG4gICAgICBjb25zdCBxdWVyeUtleSA9IGBhdXRoRGF0YS4ke3Byb3ZpZGVyfS5pZGA7XG4gICAgICBjb25zdCBxdWVyeSA9IHt9O1xuICAgICAgcXVlcnlbcXVlcnlLZXldID0gYXV0aERhdGFbcHJvdmlkZXJdLmlkO1xuICAgICAgbWVtby5wdXNoKHF1ZXJ5KTtcbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH0sIFtdKVxuICAgIC5maWx0ZXIocSA9PiB7XG4gICAgICByZXR1cm4gdHlwZW9mIHEgIT09ICd1bmRlZmluZWQnO1xuICAgIH0pO1xuXG4gIGxldCBmaW5kUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShbXSk7XG4gIGlmIChxdWVyeS5sZW5ndGggPiAwKSB7XG4gICAgZmluZFByb21pc2UgPSB0aGlzLmNvbmZpZy5kYXRhYmFzZS5maW5kKHRoaXMuY2xhc3NOYW1lLCB7ICRvcjogcXVlcnkgfSwge30pO1xuICB9XG5cbiAgcmV0dXJuIGZpbmRQcm9taXNlO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5maWx0ZXJlZE9iamVjdHNCeUFDTCA9IGZ1bmN0aW9uKG9iamVjdHMpIHtcbiAgaWYgKHRoaXMuYXV0aC5pc01hc3Rlcikge1xuICAgIHJldHVybiBvYmplY3RzO1xuICB9XG4gIHJldHVybiBvYmplY3RzLmZpbHRlcihvYmplY3QgPT4ge1xuICAgIGlmICghb2JqZWN0LkFDTCkge1xuICAgICAgcmV0dXJuIHRydWU7IC8vIGxlZ2FjeSB1c2VycyB0aGF0IGhhdmUgbm8gQUNMIGZpZWxkIG9uIHRoZW1cbiAgICB9XG4gICAgLy8gUmVndWxhciB1c2VycyB0aGF0IGhhdmUgYmVlbiBsb2NrZWQgb3V0LlxuICAgIHJldHVybiBvYmplY3QuQUNMICYmIE9iamVjdC5rZXlzKG9iamVjdC5BQ0wpLmxlbmd0aCA+IDA7XG4gIH0pO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5oYW5kbGVBdXRoRGF0YSA9IGZ1bmN0aW9uKGF1dGhEYXRhKSB7XG4gIGxldCByZXN1bHRzO1xuICByZXR1cm4gdGhpcy5maW5kVXNlcnNXaXRoQXV0aERhdGEoYXV0aERhdGEpLnRoZW4oYXN5bmMgciA9PiB7XG4gICAgcmVzdWx0cyA9IHRoaXMuZmlsdGVyZWRPYmplY3RzQnlBQ0wocik7XG5cbiAgICBpZiAocmVzdWx0cy5sZW5ndGggPT0gMSkge1xuICAgICAgdGhpcy5zdG9yYWdlWydhdXRoUHJvdmlkZXInXSA9IE9iamVjdC5rZXlzKGF1dGhEYXRhKS5qb2luKCcsJyk7XG5cbiAgICAgIGNvbnN0IHVzZXJSZXN1bHQgPSByZXN1bHRzWzBdO1xuICAgICAgY29uc3QgbXV0YXRlZEF1dGhEYXRhID0ge307XG4gICAgICBPYmplY3Qua2V5cyhhdXRoRGF0YSkuZm9yRWFjaChwcm92aWRlciA9PiB7XG4gICAgICAgIGNvbnN0IHByb3ZpZGVyRGF0YSA9IGF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgICAgY29uc3QgdXNlckF1dGhEYXRhID0gdXNlclJlc3VsdC5hdXRoRGF0YVtwcm92aWRlcl07XG4gICAgICAgIGlmICghXy5pc0VxdWFsKHByb3ZpZGVyRGF0YSwgdXNlckF1dGhEYXRhKSkge1xuICAgICAgICAgIG11dGF0ZWRBdXRoRGF0YVtwcm92aWRlcl0gPSBwcm92aWRlckRhdGE7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgY29uc3QgaGFzTXV0YXRlZEF1dGhEYXRhID0gT2JqZWN0LmtleXMobXV0YXRlZEF1dGhEYXRhKS5sZW5ndGggIT09IDA7XG4gICAgICBsZXQgdXNlcklkO1xuICAgICAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgICAgICB1c2VySWQgPSB0aGlzLnF1ZXJ5Lm9iamVjdElkO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmF1dGggJiYgdGhpcy5hdXRoLnVzZXIgJiYgdGhpcy5hdXRoLnVzZXIuaWQpIHtcbiAgICAgICAgdXNlcklkID0gdGhpcy5hdXRoLnVzZXIuaWQ7XG4gICAgICB9XG4gICAgICBpZiAoIXVzZXJJZCB8fCB1c2VySWQgPT09IHVzZXJSZXN1bHQub2JqZWN0SWQpIHtcbiAgICAgICAgLy8gbm8gdXNlciBtYWtpbmcgdGhlIGNhbGxcbiAgICAgICAgLy8gT1IgdGhlIHVzZXIgbWFraW5nIHRoZSBjYWxsIGlzIHRoZSByaWdodCBvbmVcbiAgICAgICAgLy8gTG9naW4gd2l0aCBhdXRoIGRhdGFcbiAgICAgICAgZGVsZXRlIHJlc3VsdHNbMF0ucGFzc3dvcmQ7XG5cbiAgICAgICAgLy8gbmVlZCB0byBzZXQgdGhlIG9iamVjdElkIGZpcnN0IG90aGVyd2lzZSBsb2NhdGlvbiBoYXMgdHJhaWxpbmcgdW5kZWZpbmVkXG4gICAgICAgIHRoaXMuZGF0YS5vYmplY3RJZCA9IHVzZXJSZXN1bHQub2JqZWN0SWQ7XG5cbiAgICAgICAgaWYgKCF0aGlzLnF1ZXJ5IHx8ICF0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgICAgICAgLy8gdGhpcyBhIGxvZ2luIGNhbGwsIG5vIHVzZXJJZCBwYXNzZWRcbiAgICAgICAgICB0aGlzLnJlc3BvbnNlID0ge1xuICAgICAgICAgICAgcmVzcG9uc2U6IHVzZXJSZXN1bHQsXG4gICAgICAgICAgICBsb2NhdGlvbjogdGhpcy5sb2NhdGlvbigpLFxuICAgICAgICAgIH07XG4gICAgICAgICAgLy8gUnVuIGJlZm9yZUxvZ2luIGhvb2sgYmVmb3JlIHN0b3JpbmcgYW55IHVwZGF0ZXNcbiAgICAgICAgICAvLyB0byBhdXRoRGF0YSBvbiB0aGUgZGI7IGNoYW5nZXMgdG8gdXNlclJlc3VsdFxuICAgICAgICAgIC8vIHdpbGwgYmUgaWdub3JlZC5cbiAgICAgICAgICBhd2FpdCB0aGlzLnJ1bkJlZm9yZUxvZ2luVHJpZ2dlcihkZWVwY29weSh1c2VyUmVzdWx0KSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB3ZSBkaWRuJ3QgY2hhbmdlIHRoZSBhdXRoIGRhdGEsIGp1c3Qga2VlcCBnb2luZ1xuICAgICAgICBpZiAoIWhhc011dGF0ZWRBdXRoRGF0YSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBXZSBoYXZlIGF1dGhEYXRhIHRoYXQgaXMgdXBkYXRlZCBvbiBsb2dpblxuICAgICAgICAvLyB0aGF0IGNhbiBoYXBwZW4gd2hlbiB0b2tlbiBhcmUgcmVmcmVzaGVkLFxuICAgICAgICAvLyBXZSBzaG91bGQgdXBkYXRlIHRoZSB0b2tlbiBhbmQgbGV0IHRoZSB1c2VyIGluXG4gICAgICAgIC8vIFdlIHNob3VsZCBvbmx5IGNoZWNrIHRoZSBtdXRhdGVkIGtleXNcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlQXV0aERhdGFWYWxpZGF0aW9uKG11dGF0ZWRBdXRoRGF0YSkudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgLy8gSUYgd2UgaGF2ZSBhIHJlc3BvbnNlLCB3ZSdsbCBza2lwIHRoZSBkYXRhYmFzZSBvcGVyYXRpb24gLyBiZWZvcmVTYXZlIC8gYWZ0ZXJTYXZlIGV0Yy4uLlxuICAgICAgICAgIC8vIHdlIG5lZWQgdG8gc2V0IGl0IHVwIHRoZXJlLlxuICAgICAgICAgIC8vIFdlIGFyZSBzdXBwb3NlZCB0byBoYXZlIGEgcmVzcG9uc2Ugb25seSBvbiBMT0dJTiB3aXRoIGF1dGhEYXRhLCBzbyB3ZSBza2lwIHRob3NlXG4gICAgICAgICAgLy8gSWYgd2UncmUgbm90IGxvZ2dpbmcgaW4sIGJ1dCBqdXN0IHVwZGF0aW5nIHRoZSBjdXJyZW50IHVzZXIsIHdlIGNhbiBzYWZlbHkgc2tpcCB0aGF0IHBhcnRcbiAgICAgICAgICBpZiAodGhpcy5yZXNwb25zZSkge1xuICAgICAgICAgICAgLy8gQXNzaWduIHRoZSBuZXcgYXV0aERhdGEgaW4gdGhlIHJlc3BvbnNlXG4gICAgICAgICAgICBPYmplY3Qua2V5cyhtdXRhdGVkQXV0aERhdGEpLmZvckVhY2gocHJvdmlkZXIgPT4ge1xuICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlLmF1dGhEYXRhW3Byb3ZpZGVyXSA9XG4gICAgICAgICAgICAgICAgbXV0YXRlZEF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBSdW4gdGhlIERCIHVwZGF0ZSBkaXJlY3RseSwgYXMgJ21hc3RlcidcbiAgICAgICAgICAgIC8vIEp1c3QgdXBkYXRlIHRoZSBhdXRoRGF0YSBwYXJ0XG4gICAgICAgICAgICAvLyBUaGVuIHdlJ3JlIGdvb2QgZm9yIHRoZSB1c2VyLCBlYXJseSBleGl0IG9mIHNvcnRzXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UudXBkYXRlKFxuICAgICAgICAgICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgeyBvYmplY3RJZDogdGhpcy5kYXRhLm9iamVjdElkIH0sXG4gICAgICAgICAgICAgIHsgYXV0aERhdGE6IG11dGF0ZWRBdXRoRGF0YSB9LFxuICAgICAgICAgICAgICB7fVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmICh1c2VySWQpIHtcbiAgICAgICAgLy8gVHJ5aW5nIHRvIHVwZGF0ZSBhdXRoIGRhdGEgYnV0IHVzZXJzXG4gICAgICAgIC8vIGFyZSBkaWZmZXJlbnRcbiAgICAgICAgaWYgKHVzZXJSZXN1bHQub2JqZWN0SWQgIT09IHVzZXJJZCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLkFDQ09VTlRfQUxSRUFEWV9MSU5LRUQsXG4gICAgICAgICAgICAndGhpcyBhdXRoIGlzIGFscmVhZHkgdXNlZCdcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vIGF1dGggZGF0YSB3YXMgbXV0YXRlZCwganVzdCBrZWVwIGdvaW5nXG4gICAgICAgIGlmICghaGFzTXV0YXRlZEF1dGhEYXRhKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmhhbmRsZUF1dGhEYXRhVmFsaWRhdGlvbihhdXRoRGF0YSkudGhlbigoKSA9PiB7XG4gICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIC8vIE1vcmUgdGhhbiAxIHVzZXIgd2l0aCB0aGUgcGFzc2VkIGlkJ3NcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLkFDQ09VTlRfQUxSRUFEWV9MSU5LRUQsXG4gICAgICAgICAgJ3RoaXMgYXV0aCBpcyBhbHJlYWR5IHVzZWQnXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufTtcblxuLy8gVGhlIG5vbi10aGlyZC1wYXJ0eSBwYXJ0cyBvZiBVc2VyIHRyYW5zZm9ybWF0aW9uXG5SZXN0V3JpdGUucHJvdG90eXBlLnRyYW5zZm9ybVVzZXIgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICBpZiAodGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicpIHtcbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfVxuXG4gIGlmICghdGhpcy5hdXRoLmlzTWFzdGVyICYmICdlbWFpbFZlcmlmaWVkJyBpbiB0aGlzLmRhdGEpIHtcbiAgICBjb25zdCBlcnJvciA9IGBDbGllbnRzIGFyZW4ndCBhbGxvd2VkIHRvIG1hbnVhbGx5IHVwZGF0ZSBlbWFpbCB2ZXJpZmljYXRpb24uYDtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTiwgZXJyb3IpO1xuICB9XG5cbiAgLy8gRG8gbm90IGNsZWFudXAgc2Vzc2lvbiBpZiBvYmplY3RJZCBpcyBub3Qgc2V0XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMub2JqZWN0SWQoKSkge1xuICAgIC8vIElmIHdlJ3JlIHVwZGF0aW5nIGEgX1VzZXIgb2JqZWN0LCB3ZSBuZWVkIHRvIGNsZWFyIG91dCB0aGUgY2FjaGUgZm9yIHRoYXQgdXNlci4gRmluZCBhbGwgdGhlaXJcbiAgICAvLyBzZXNzaW9uIHRva2VucywgYW5kIHJlbW92ZSB0aGVtIGZyb20gdGhlIGNhY2hlLlxuICAgIHByb21pc2UgPSBuZXcgUmVzdFF1ZXJ5KHRoaXMuY29uZmlnLCBBdXRoLm1hc3Rlcih0aGlzLmNvbmZpZyksICdfU2Vzc2lvbicsIHtcbiAgICAgIHVzZXI6IHtcbiAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgIGNsYXNzTmFtZTogJ19Vc2VyJyxcbiAgICAgICAgb2JqZWN0SWQ6IHRoaXMub2JqZWN0SWQoKSxcbiAgICAgIH0sXG4gICAgfSlcbiAgICAgIC5leGVjdXRlKClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICByZXN1bHRzLnJlc3VsdHMuZm9yRWFjaChzZXNzaW9uID0+XG4gICAgICAgICAgdGhpcy5jb25maWcuY2FjaGVDb250cm9sbGVyLnVzZXIuZGVsKHNlc3Npb24uc2Vzc2lvblRva2VuKVxuICAgICAgICApO1xuICAgICAgfSk7XG4gIH1cblxuICByZXR1cm4gcHJvbWlzZVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIC8vIFRyYW5zZm9ybSB0aGUgcGFzc3dvcmRcbiAgICAgIGlmICh0aGlzLmRhdGEucGFzc3dvcmQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBpZ25vcmUgb25seSBpZiB1bmRlZmluZWQuIHNob3VsZCBwcm9jZWVkIGlmIGVtcHR5ICgnJylcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5xdWVyeSkge1xuICAgICAgICB0aGlzLnN0b3JhZ2VbJ2NsZWFyU2Vzc2lvbnMnXSA9IHRydWU7XG4gICAgICAgIC8vIEdlbmVyYXRlIGEgbmV3IHNlc3Npb24gb25seSBpZiB0aGUgdXNlciByZXF1ZXN0ZWRcbiAgICAgICAgaWYgKCF0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgICB0aGlzLnN0b3JhZ2VbJ2dlbmVyYXRlTmV3U2Vzc2lvbiddID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5fdmFsaWRhdGVQYXNzd29yZFBvbGljeSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gcGFzc3dvcmRDcnlwdG8uaGFzaCh0aGlzLmRhdGEucGFzc3dvcmQpLnRoZW4oaGFzaGVkUGFzc3dvcmQgPT4ge1xuICAgICAgICAgIHRoaXMuZGF0YS5faGFzaGVkX3Bhc3N3b3JkID0gaGFzaGVkUGFzc3dvcmQ7XG4gICAgICAgICAgZGVsZXRlIHRoaXMuZGF0YS5wYXNzd29yZDtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLl92YWxpZGF0ZVVzZXJOYW1lKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5fdmFsaWRhdGVFbWFpbCgpO1xuICAgIH0pO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5fdmFsaWRhdGVVc2VyTmFtZSA9IGZ1bmN0aW9uKCkge1xuICAvLyBDaGVjayBmb3IgdXNlcm5hbWUgdW5pcXVlbmVzc1xuICBpZiAoIXRoaXMuZGF0YS51c2VybmFtZSkge1xuICAgIGlmICghdGhpcy5xdWVyeSkge1xuICAgICAgdGhpcy5kYXRhLnVzZXJuYW1lID0gY3J5cHRvVXRpbHMucmFuZG9tU3RyaW5nKDI1KTtcbiAgICAgIHRoaXMucmVzcG9uc2VTaG91bGRIYXZlVXNlcm5hbWUgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gV2UgbmVlZCB0byBhIGZpbmQgdG8gY2hlY2sgZm9yIGR1cGxpY2F0ZSB1c2VybmFtZSBpbiBjYXNlIHRoZXkgYXJlIG1pc3NpbmcgdGhlIHVuaXF1ZSBpbmRleCBvbiB1c2VybmFtZXNcbiAgLy8gVE9ETzogQ2hlY2sgaWYgdGhlcmUgaXMgYSB1bmlxdWUgaW5kZXgsIGFuZCBpZiBzbywgc2tpcCB0aGlzIHF1ZXJ5LlxuICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAuZmluZChcbiAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgeyB1c2VybmFtZTogdGhpcy5kYXRhLnVzZXJuYW1lLCBvYmplY3RJZDogeyAkbmU6IHRoaXMub2JqZWN0SWQoKSB9IH0sXG4gICAgICB7IGxpbWl0OiAxIH0sXG4gICAgICB7fSxcbiAgICAgIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyXG4gICAgKVxuICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuVVNFUk5BTUVfVEFLRU4sXG4gICAgICAgICAgJ0FjY291bnQgYWxyZWFkeSBleGlzdHMgZm9yIHRoaXMgdXNlcm5hbWUuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH0pO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5fdmFsaWRhdGVFbWFpbCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuZGF0YS5lbWFpbCB8fCB0aGlzLmRhdGEuZW1haWwuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gVmFsaWRhdGUgYmFzaWMgZW1haWwgYWRkcmVzcyBmb3JtYXRcbiAgaWYgKCF0aGlzLmRhdGEuZW1haWwubWF0Y2goL14uK0AuKyQvKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9FTUFJTF9BRERSRVNTLFxuICAgICAgICAnRW1haWwgYWRkcmVzcyBmb3JtYXQgaXMgaW52YWxpZC4nXG4gICAgICApXG4gICAgKTtcbiAgfVxuICAvLyBTYW1lIHByb2JsZW0gZm9yIGVtYWlsIGFzIGFib3ZlIGZvciB1c2VybmFtZVxuICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAuZmluZChcbiAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgeyBlbWFpbDogdGhpcy5kYXRhLmVtYWlsLCBvYmplY3RJZDogeyAkbmU6IHRoaXMub2JqZWN0SWQoKSB9IH0sXG4gICAgICB7IGxpbWl0OiAxIH0sXG4gICAgICB7fSxcbiAgICAgIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyXG4gICAgKVxuICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuRU1BSUxfVEFLRU4sXG4gICAgICAgICAgJ0FjY291bnQgYWxyZWFkeSBleGlzdHMgZm9yIHRoaXMgZW1haWwgYWRkcmVzcy4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgICF0aGlzLmRhdGEuYXV0aERhdGEgfHxcbiAgICAgICAgIU9iamVjdC5rZXlzKHRoaXMuZGF0YS5hdXRoRGF0YSkubGVuZ3RoIHx8XG4gICAgICAgIChPYmplY3Qua2V5cyh0aGlzLmRhdGEuYXV0aERhdGEpLmxlbmd0aCA9PT0gMSAmJlxuICAgICAgICAgIE9iamVjdC5rZXlzKHRoaXMuZGF0YS5hdXRoRGF0YSlbMF0gPT09ICdhbm9ueW1vdXMnKVxuICAgICAgKSB7XG4gICAgICAgIC8vIFdlIHVwZGF0ZWQgdGhlIGVtYWlsLCBzZW5kIGEgbmV3IHZhbGlkYXRpb25cbiAgICAgICAgdGhpcy5zdG9yYWdlWydzZW5kVmVyaWZpY2F0aW9uRW1haWwnXSA9IHRydWU7XG4gICAgICAgIHRoaXMuY29uZmlnLnVzZXJDb250cm9sbGVyLnNldEVtYWlsVmVyaWZ5VG9rZW4odGhpcy5kYXRhKTtcbiAgICAgIH1cbiAgICB9KTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuX3ZhbGlkYXRlUGFzc3dvcmRQb2xpY3kgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeSkgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICByZXR1cm4gdGhpcy5fdmFsaWRhdGVQYXNzd29yZFJlcXVpcmVtZW50cygpLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLl92YWxpZGF0ZVBhc3N3b3JkSGlzdG9yeSgpO1xuICB9KTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuX3ZhbGlkYXRlUGFzc3dvcmRSZXF1aXJlbWVudHMgPSBmdW5jdGlvbigpIHtcbiAgLy8gY2hlY2sgaWYgdGhlIHBhc3N3b3JkIGNvbmZvcm1zIHRvIHRoZSBkZWZpbmVkIHBhc3N3b3JkIHBvbGljeSBpZiBjb25maWd1cmVkXG4gIC8vIElmIHdlIHNwZWNpZmllZCBhIGN1c3RvbSBlcnJvciBpbiBvdXIgY29uZmlndXJhdGlvbiB1c2UgaXQuXG4gIC8vIEV4YW1wbGU6IFwiUGFzc3dvcmRzIG11c3QgaW5jbHVkZSBhIENhcGl0YWwgTGV0dGVyLCBMb3dlcmNhc2UgTGV0dGVyLCBhbmQgYSBudW1iZXIuXCJcbiAgLy9cbiAgLy8gVGhpcyBpcyBlc3BlY2lhbGx5IHVzZWZ1bCBvbiB0aGUgZ2VuZXJpYyBcInBhc3N3b3JkIHJlc2V0XCIgcGFnZSxcbiAgLy8gYXMgaXQgYWxsb3dzIHRoZSBwcm9ncmFtbWVyIHRvIGNvbW11bmljYXRlIHNwZWNpZmljIHJlcXVpcmVtZW50cyBpbnN0ZWFkIG9mOlxuICAvLyBhLiBtYWtpbmcgdGhlIHVzZXIgZ3Vlc3Mgd2hhdHMgd3JvbmdcbiAgLy8gYi4gbWFraW5nIGEgY3VzdG9tIHBhc3N3b3JkIHJlc2V0IHBhZ2UgdGhhdCBzaG93cyB0aGUgcmVxdWlyZW1lbnRzXG4gIGNvbnN0IHBvbGljeUVycm9yID0gdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kudmFsaWRhdGlvbkVycm9yXG4gICAgPyB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS52YWxpZGF0aW9uRXJyb3JcbiAgICA6ICdQYXNzd29yZCBkb2VzIG5vdCBtZWV0IHRoZSBQYXNzd29yZCBQb2xpY3kgcmVxdWlyZW1lbnRzLic7XG4gIGNvbnN0IGNvbnRhaW5zVXNlcm5hbWVFcnJvciA9ICdQYXNzd29yZCBjYW5ub3QgY29udGFpbiB5b3VyIHVzZXJuYW1lLic7XG5cbiAgLy8gY2hlY2sgd2hldGhlciB0aGUgcGFzc3dvcmQgbWVldHMgdGhlIHBhc3N3b3JkIHN0cmVuZ3RoIHJlcXVpcmVtZW50c1xuICBpZiAoXG4gICAgKHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5LnBhdHRlcm5WYWxpZGF0b3IgJiZcbiAgICAgICF0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5wYXR0ZXJuVmFsaWRhdG9yKHRoaXMuZGF0YS5wYXNzd29yZCkpIHx8XG4gICAgKHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5LnZhbGlkYXRvckNhbGxiYWNrICYmXG4gICAgICAhdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yQ2FsbGJhY2sodGhpcy5kYXRhLnBhc3N3b3JkKSlcbiAgKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsIHBvbGljeUVycm9yKVxuICAgICk7XG4gIH1cblxuICAvLyBjaGVjayB3aGV0aGVyIHBhc3N3b3JkIGNvbnRhaW4gdXNlcm5hbWVcbiAgaWYgKHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5LmRvTm90QWxsb3dVc2VybmFtZSA9PT0gdHJ1ZSkge1xuICAgIGlmICh0aGlzLmRhdGEudXNlcm5hbWUpIHtcbiAgICAgIC8vIHVzZXJuYW1lIGlzIG5vdCBwYXNzZWQgZHVyaW5nIHBhc3N3b3JkIHJlc2V0XG4gICAgICBpZiAodGhpcy5kYXRhLnBhc3N3b3JkLmluZGV4T2YodGhpcy5kYXRhLnVzZXJuYW1lKSA+PSAwKVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsIGNvbnRhaW5zVXNlcm5hbWVFcnJvcilcbiAgICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gcmV0cmlldmUgdGhlIFVzZXIgb2JqZWN0IHVzaW5nIG9iamVjdElkIGR1cmluZyBwYXNzd29yZCByZXNldFxuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgICAgIC5maW5kKCdfVXNlcicsIHsgb2JqZWN0SWQ6IHRoaXMub2JqZWN0SWQoKSB9KVxuICAgICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggIT0gMSkge1xuICAgICAgICAgICAgdGhyb3cgdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodGhpcy5kYXRhLnBhc3N3b3JkLmluZGV4T2YocmVzdWx0c1swXS51c2VybmFtZSkgPj0gMClcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsXG4gICAgICAgICAgICAgICAgY29udGFpbnNVc2VybmFtZUVycm9yXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5fdmFsaWRhdGVQYXNzd29yZEhpc3RvcnkgPSBmdW5jdGlvbigpIHtcbiAgLy8gY2hlY2sgd2hldGhlciBwYXNzd29yZCBpcyByZXBlYXRpbmcgZnJvbSBzcGVjaWZpZWQgaGlzdG9yeVxuICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkpIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgIC5maW5kKFxuICAgICAgICAnX1VzZXInLFxuICAgICAgICB7IG9iamVjdElkOiB0aGlzLm9iamVjdElkKCkgfSxcbiAgICAgICAgeyBrZXlzOiBbJ19wYXNzd29yZF9oaXN0b3J5JywgJ19oYXNoZWRfcGFzc3dvcmQnXSB9XG4gICAgICApXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9IDEpIHtcbiAgICAgICAgICB0aHJvdyB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdXNlciA9IHJlc3VsdHNbMF07XG4gICAgICAgIGxldCBvbGRQYXNzd29yZHMgPSBbXTtcbiAgICAgICAgaWYgKHVzZXIuX3Bhc3N3b3JkX2hpc3RvcnkpXG4gICAgICAgICAgb2xkUGFzc3dvcmRzID0gXy50YWtlKFxuICAgICAgICAgICAgdXNlci5fcGFzc3dvcmRfaGlzdG9yeSxcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeSAtIDFcbiAgICAgICAgICApO1xuICAgICAgICBvbGRQYXNzd29yZHMucHVzaCh1c2VyLnBhc3N3b3JkKTtcbiAgICAgICAgY29uc3QgbmV3UGFzc3dvcmQgPSB0aGlzLmRhdGEucGFzc3dvcmQ7XG4gICAgICAgIC8vIGNvbXBhcmUgdGhlIG5ldyBwYXNzd29yZCBoYXNoIHdpdGggYWxsIG9sZCBwYXNzd29yZCBoYXNoZXNcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBvbGRQYXNzd29yZHMubWFwKGZ1bmN0aW9uKGhhc2gpIHtcbiAgICAgICAgICByZXR1cm4gcGFzc3dvcmRDcnlwdG8uY29tcGFyZShuZXdQYXNzd29yZCwgaGFzaCkudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3VsdClcbiAgICAgICAgICAgICAgLy8gcmVqZWN0IGlmIHRoZXJlIGlzIGEgbWF0Y2hcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdSRVBFQVRfUEFTU1dPUkQnKTtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHdhaXQgZm9yIGFsbCBjb21wYXJpc29ucyB0byBjb21wbGV0ZVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyID09PSAnUkVQRUFUX1BBU1NXT1JEJylcbiAgICAgICAgICAgICAgLy8gYSBtYXRjaCB3YXMgZm91bmRcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsXG4gICAgICAgICAgICAgICAgICBgTmV3IHBhc3N3b3JkIHNob3VsZCBub3QgYmUgdGhlIHNhbWUgYXMgbGFzdCAke3RoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeX0gcGFzc3dvcmRzLmBcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLmNyZWF0ZVNlc3Npb25Ub2tlbklmTmVlZGVkID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmNsYXNzTmFtZSAhPT0gJ19Vc2VyJykge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBEb24ndCBnZW5lcmF0ZSBzZXNzaW9uIGZvciB1cGRhdGluZyB1c2VyICh0aGlzLnF1ZXJ5IGlzIHNldCkgdW5sZXNzIGF1dGhEYXRhIGV4aXN0c1xuICBpZiAodGhpcy5xdWVyeSAmJiAhdGhpcy5kYXRhLmF1dGhEYXRhKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIERvbid0IGdlbmVyYXRlIG5ldyBzZXNzaW9uVG9rZW4gaWYgbGlua2luZyB2aWEgc2Vzc2lvblRva2VuXG4gIGlmICh0aGlzLmF1dGgudXNlciAmJiB0aGlzLmRhdGEuYXV0aERhdGEpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKFxuICAgICF0aGlzLnN0b3JhZ2VbJ2F1dGhQcm92aWRlciddICYmIC8vIHNpZ251cCBjYWxsLCB3aXRoXG4gICAgdGhpcy5jb25maWcucHJldmVudExvZ2luV2l0aFVudmVyaWZpZWRFbWFpbCAmJiAvLyBubyBsb2dpbiB3aXRob3V0IHZlcmlmaWNhdGlvblxuICAgIHRoaXMuY29uZmlnLnZlcmlmeVVzZXJFbWFpbHNcbiAgKSB7XG4gICAgLy8gdmVyaWZpY2F0aW9uIGlzIG9uXG4gICAgcmV0dXJuOyAvLyBkbyBub3QgY3JlYXRlIHRoZSBzZXNzaW9uIHRva2VuIGluIHRoYXQgY2FzZSFcbiAgfVxuICByZXR1cm4gdGhpcy5jcmVhdGVTZXNzaW9uVG9rZW4oKTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuY3JlYXRlU2Vzc2lvblRva2VuID0gYXN5bmMgZnVuY3Rpb24oKSB7XG4gIC8vIGNsb3VkIGluc3RhbGxhdGlvbklkIGZyb20gQ2xvdWQgQ29kZSxcbiAgLy8gbmV2ZXIgY3JlYXRlIHNlc3Npb24gdG9rZW5zIGZyb20gdGhlcmUuXG4gIGlmICh0aGlzLmF1dGguaW5zdGFsbGF0aW9uSWQgJiYgdGhpcy5hdXRoLmluc3RhbGxhdGlvbklkID09PSAnY2xvdWQnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgeyBzZXNzaW9uRGF0YSwgY3JlYXRlU2Vzc2lvbiB9ID0gQXV0aC5jcmVhdGVTZXNzaW9uKHRoaXMuY29uZmlnLCB7XG4gICAgdXNlcklkOiB0aGlzLm9iamVjdElkKCksXG4gICAgY3JlYXRlZFdpdGg6IHtcbiAgICAgIGFjdGlvbjogdGhpcy5zdG9yYWdlWydhdXRoUHJvdmlkZXInXSA/ICdsb2dpbicgOiAnc2lnbnVwJyxcbiAgICAgIGF1dGhQcm92aWRlcjogdGhpcy5zdG9yYWdlWydhdXRoUHJvdmlkZXInXSB8fCAncGFzc3dvcmQnLFxuICAgIH0sXG4gICAgaW5zdGFsbGF0aW9uSWQ6IHRoaXMuYXV0aC5pbnN0YWxsYXRpb25JZCxcbiAgfSk7XG5cbiAgaWYgKHRoaXMucmVzcG9uc2UgJiYgdGhpcy5yZXNwb25zZS5yZXNwb25zZSkge1xuICAgIHRoaXMucmVzcG9uc2UucmVzcG9uc2Uuc2Vzc2lvblRva2VuID0gc2Vzc2lvbkRhdGEuc2Vzc2lvblRva2VuO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZVNlc3Npb24oKTtcbn07XG5cbi8vIERlbGV0ZSBlbWFpbCByZXNldCB0b2tlbnMgaWYgdXNlciBpcyBjaGFuZ2luZyBwYXNzd29yZCBvciBlbWFpbC5cblJlc3RXcml0ZS5wcm90b3R5cGUuZGVsZXRlRW1haWxSZXNldFRva2VuSWZOZWVkZWQgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuY2xhc3NOYW1lICE9PSAnX1VzZXInIHx8IHRoaXMucXVlcnkgPT09IG51bGwpIHtcbiAgICAvLyBudWxsIHF1ZXJ5IG1lYW5zIGNyZWF0ZVxuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICgncGFzc3dvcmQnIGluIHRoaXMuZGF0YSB8fCAnZW1haWwnIGluIHRoaXMuZGF0YSkge1xuICAgIGNvbnN0IGFkZE9wcyA9IHtcbiAgICAgIF9wZXJpc2hhYmxlX3Rva2VuOiB7IF9fb3A6ICdEZWxldGUnIH0sXG4gICAgICBfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0OiB7IF9fb3A6ICdEZWxldGUnIH0sXG4gICAgfTtcbiAgICB0aGlzLmRhdGEgPSBPYmplY3QuYXNzaWduKHRoaXMuZGF0YSwgYWRkT3BzKTtcbiAgfVxufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5kZXN0cm95RHVwbGljYXRlZFNlc3Npb25zID0gZnVuY3Rpb24oKSB7XG4gIC8vIE9ubHkgZm9yIF9TZXNzaW9uLCBhbmQgYXQgY3JlYXRpb24gdGltZVxuICBpZiAodGhpcy5jbGFzc05hbWUgIT0gJ19TZXNzaW9uJyB8fCB0aGlzLnF1ZXJ5KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIERlc3Ryb3kgdGhlIHNlc3Npb25zIGluICdCYWNrZ3JvdW5kJ1xuICBjb25zdCB7IHVzZXIsIGluc3RhbGxhdGlvbklkLCBzZXNzaW9uVG9rZW4gfSA9IHRoaXMuZGF0YTtcbiAgaWYgKCF1c2VyIHx8ICFpbnN0YWxsYXRpb25JZCkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoIXVzZXIub2JqZWN0SWQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdGhpcy5jb25maWcuZGF0YWJhc2UuZGVzdHJveShcbiAgICAnX1Nlc3Npb24nLFxuICAgIHtcbiAgICAgIHVzZXIsXG4gICAgICBpbnN0YWxsYXRpb25JZCxcbiAgICAgIHNlc3Npb25Ub2tlbjogeyAkbmU6IHNlc3Npb25Ub2tlbiB9LFxuICAgIH0sXG4gICAge30sXG4gICAgdGhpcy52YWxpZFNjaGVtYUNvbnRyb2xsZXJcbiAgKTtcbn07XG5cbi8vIEhhbmRsZXMgYW55IGZvbGxvd3VwIGxvZ2ljXG5SZXN0V3JpdGUucHJvdG90eXBlLmhhbmRsZUZvbGxvd3VwID0gZnVuY3Rpb24oKSB7XG4gIGlmIChcbiAgICB0aGlzLnN0b3JhZ2UgJiZcbiAgICB0aGlzLnN0b3JhZ2VbJ2NsZWFyU2Vzc2lvbnMnXSAmJlxuICAgIHRoaXMuY29uZmlnLnJldm9rZVNlc3Npb25PblBhc3N3b3JkUmVzZXRcbiAgKSB7XG4gICAgdmFyIHNlc3Npb25RdWVyeSA9IHtcbiAgICAgIHVzZXI6IHtcbiAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgIGNsYXNzTmFtZTogJ19Vc2VyJyxcbiAgICAgICAgb2JqZWN0SWQ6IHRoaXMub2JqZWN0SWQoKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBkZWxldGUgdGhpcy5zdG9yYWdlWydjbGVhclNlc3Npb25zJ107XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgICAuZGVzdHJveSgnX1Nlc3Npb24nLCBzZXNzaW9uUXVlcnkpXG4gICAgICAudGhlbih0aGlzLmhhbmRsZUZvbGxvd3VwLmJpbmQodGhpcykpO1xuICB9XG5cbiAgaWYgKHRoaXMuc3RvcmFnZSAmJiB0aGlzLnN0b3JhZ2VbJ2dlbmVyYXRlTmV3U2Vzc2lvbiddKSB7XG4gICAgZGVsZXRlIHRoaXMuc3RvcmFnZVsnZ2VuZXJhdGVOZXdTZXNzaW9uJ107XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlU2Vzc2lvblRva2VuKCkudGhlbih0aGlzLmhhbmRsZUZvbGxvd3VwLmJpbmQodGhpcykpO1xuICB9XG5cbiAgaWYgKHRoaXMuc3RvcmFnZSAmJiB0aGlzLnN0b3JhZ2VbJ3NlbmRWZXJpZmljYXRpb25FbWFpbCddKSB7XG4gICAgZGVsZXRlIHRoaXMuc3RvcmFnZVsnc2VuZFZlcmlmaWNhdGlvbkVtYWlsJ107XG4gICAgLy8gRmlyZSBhbmQgZm9yZ2V0IVxuICAgIHRoaXMuY29uZmlnLnVzZXJDb250cm9sbGVyLnNlbmRWZXJpZmljYXRpb25FbWFpbCh0aGlzLmRhdGEpO1xuICAgIHJldHVybiB0aGlzLmhhbmRsZUZvbGxvd3VwLmJpbmQodGhpcyk7XG4gIH1cbn07XG5cbi8vIEhhbmRsZXMgdGhlIF9TZXNzaW9uIGNsYXNzIHNwZWNpYWxuZXNzLlxuLy8gRG9lcyBub3RoaW5nIGlmIHRoaXMgaXNuJ3QgYW4gX1Nlc3Npb24gb2JqZWN0LlxuUmVzdFdyaXRlLnByb3RvdHlwZS5oYW5kbGVTZXNzaW9uID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLnJlc3BvbnNlIHx8IHRoaXMuY2xhc3NOYW1lICE9PSAnX1Nlc3Npb24nKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCF0aGlzLmF1dGgudXNlciAmJiAhdGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgJ1Nlc3Npb24gdG9rZW4gcmVxdWlyZWQuJ1xuICAgICk7XG4gIH1cblxuICAvLyBUT0RPOiBWZXJpZnkgcHJvcGVyIGVycm9yIHRvIHRocm93XG4gIGlmICh0aGlzLmRhdGEuQUNMKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICdDYW5ub3Qgc2V0ICcgKyAnQUNMIG9uIGEgU2Vzc2lvbi4nXG4gICAgKTtcbiAgfVxuXG4gIGlmICh0aGlzLnF1ZXJ5KSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5kYXRhLnVzZXIgJiZcbiAgICAgICF0aGlzLmF1dGguaXNNYXN0ZXIgJiZcbiAgICAgIHRoaXMuZGF0YS51c2VyLm9iamVjdElkICE9IHRoaXMuYXV0aC51c2VyLmlkXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5zZXNzaW9uVG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXRoaXMucXVlcnkgJiYgIXRoaXMuYXV0aC5pc01hc3Rlcikge1xuICAgIGNvbnN0IGFkZGl0aW9uYWxTZXNzaW9uRGF0YSA9IHt9O1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmRhdGEpIHtcbiAgICAgIGlmIChrZXkgPT09ICdvYmplY3RJZCcgfHwga2V5ID09PSAndXNlcicpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBhZGRpdGlvbmFsU2Vzc2lvbkRhdGFba2V5XSA9IHRoaXMuZGF0YVtrZXldO1xuICAgIH1cblxuICAgIGNvbnN0IHsgc2Vzc2lvbkRhdGEsIGNyZWF0ZVNlc3Npb24gfSA9IEF1dGguY3JlYXRlU2Vzc2lvbih0aGlzLmNvbmZpZywge1xuICAgICAgdXNlcklkOiB0aGlzLmF1dGgudXNlci5pZCxcbiAgICAgIGNyZWF0ZWRXaXRoOiB7XG4gICAgICAgIGFjdGlvbjogJ2NyZWF0ZScsXG4gICAgICB9LFxuICAgICAgYWRkaXRpb25hbFNlc3Npb25EYXRhLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNyZWF0ZVNlc3Npb24oKS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgaWYgKCFyZXN1bHRzLnJlc3BvbnNlKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgICAgJ0Vycm9yIGNyZWF0aW5nIHNlc3Npb24uJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgc2Vzc2lvbkRhdGFbJ29iamVjdElkJ10gPSByZXN1bHRzLnJlc3BvbnNlWydvYmplY3RJZCddO1xuICAgICAgdGhpcy5yZXNwb25zZSA9IHtcbiAgICAgICAgc3RhdHVzOiAyMDEsXG4gICAgICAgIGxvY2F0aW9uOiByZXN1bHRzLmxvY2F0aW9uLFxuICAgICAgICByZXNwb25zZTogc2Vzc2lvbkRhdGEsXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG59O1xuXG4vLyBIYW5kbGVzIHRoZSBfSW5zdGFsbGF0aW9uIGNsYXNzIHNwZWNpYWxuZXNzLlxuLy8gRG9lcyBub3RoaW5nIGlmIHRoaXMgaXNuJ3QgYW4gaW5zdGFsbGF0aW9uIG9iamVjdC5cbi8vIElmIGFuIGluc3RhbGxhdGlvbiBpcyBmb3VuZCwgdGhpcyBjYW4gbXV0YXRlIHRoaXMucXVlcnkgYW5kIHR1cm4gYSBjcmVhdGVcbi8vIGludG8gYW4gdXBkYXRlLlxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIHdoZW4gd2UncmUgZG9uZSBpZiBpdCBjYW4ndCBmaW5pc2ggdGhpcyB0aWNrLlxuUmVzdFdyaXRlLnByb3RvdHlwZS5oYW5kbGVJbnN0YWxsYXRpb24gPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMucmVzcG9uc2UgfHwgdGhpcy5jbGFzc05hbWUgIT09ICdfSW5zdGFsbGF0aW9uJykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChcbiAgICAhdGhpcy5xdWVyeSAmJlxuICAgICF0aGlzLmRhdGEuZGV2aWNlVG9rZW4gJiZcbiAgICAhdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkICYmXG4gICAgIXRoaXMuYXV0aC5pbnN0YWxsYXRpb25JZFxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAxMzUsXG4gICAgICAnYXQgbGVhc3Qgb25lIElEIGZpZWxkIChkZXZpY2VUb2tlbiwgaW5zdGFsbGF0aW9uSWQpICcgK1xuICAgICAgICAnbXVzdCBiZSBzcGVjaWZpZWQgaW4gdGhpcyBvcGVyYXRpb24nXG4gICAgKTtcbiAgfVxuXG4gIC8vIElmIHRoZSBkZXZpY2UgdG9rZW4gaXMgNjQgY2hhcmFjdGVycyBsb25nLCB3ZSBhc3N1bWUgaXQgaXMgZm9yIGlPU1xuICAvLyBhbmQgbG93ZXJjYXNlIGl0LlxuICBpZiAodGhpcy5kYXRhLmRldmljZVRva2VuICYmIHRoaXMuZGF0YS5kZXZpY2VUb2tlbi5sZW5ndGggPT0gNjQpIHtcbiAgICB0aGlzLmRhdGEuZGV2aWNlVG9rZW4gPSB0aGlzLmRhdGEuZGV2aWNlVG9rZW4udG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIC8vIFdlIGxvd2VyY2FzZSB0aGUgaW5zdGFsbGF0aW9uSWQgaWYgcHJlc2VudFxuICBpZiAodGhpcy5kYXRhLmluc3RhbGxhdGlvbklkKSB7XG4gICAgdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkID0gdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICBsZXQgaW5zdGFsbGF0aW9uSWQgPSB0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQ7XG5cbiAgLy8gSWYgZGF0YS5pbnN0YWxsYXRpb25JZCBpcyBub3Qgc2V0IGFuZCB3ZSdyZSBub3QgbWFzdGVyLCB3ZSBjYW4gbG9va3VwIGluIGF1dGhcbiAgaWYgKCFpbnN0YWxsYXRpb25JZCAmJiAhdGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgaW5zdGFsbGF0aW9uSWQgPSB0aGlzLmF1dGguaW5zdGFsbGF0aW9uSWQ7XG4gIH1cblxuICBpZiAoaW5zdGFsbGF0aW9uSWQpIHtcbiAgICBpbnN0YWxsYXRpb25JZCA9IGluc3RhbGxhdGlvbklkLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICAvLyBVcGRhdGluZyBfSW5zdGFsbGF0aW9uIGJ1dCBub3QgdXBkYXRpbmcgYW55dGhpbmcgY3JpdGljYWxcbiAgaWYgKFxuICAgIHRoaXMucXVlcnkgJiZcbiAgICAhdGhpcy5kYXRhLmRldmljZVRva2VuICYmXG4gICAgIWluc3RhbGxhdGlvbklkICYmXG4gICAgIXRoaXMuZGF0YS5kZXZpY2VUeXBlXG4gICkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgdmFyIGlkTWF0Y2g7IC8vIFdpbGwgYmUgYSBtYXRjaCBvbiBlaXRoZXIgb2JqZWN0SWQgb3IgaW5zdGFsbGF0aW9uSWRcbiAgdmFyIG9iamVjdElkTWF0Y2g7XG4gIHZhciBpbnN0YWxsYXRpb25JZE1hdGNoO1xuICB2YXIgZGV2aWNlVG9rZW5NYXRjaGVzID0gW107XG5cbiAgLy8gSW5zdGVhZCBvZiBpc3N1aW5nIDMgcmVhZHMsIGxldCdzIGRvIGl0IHdpdGggb25lIE9SLlxuICBjb25zdCBvclF1ZXJpZXMgPSBbXTtcbiAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgIG9yUXVlcmllcy5wdXNoKHtcbiAgICAgIG9iamVjdElkOiB0aGlzLnF1ZXJ5Lm9iamVjdElkLFxuICAgIH0pO1xuICB9XG4gIGlmIChpbnN0YWxsYXRpb25JZCkge1xuICAgIG9yUXVlcmllcy5wdXNoKHtcbiAgICAgIGluc3RhbGxhdGlvbklkOiBpbnN0YWxsYXRpb25JZCxcbiAgICB9KTtcbiAgfVxuICBpZiAodGhpcy5kYXRhLmRldmljZVRva2VuKSB7XG4gICAgb3JRdWVyaWVzLnB1c2goeyBkZXZpY2VUb2tlbjogdGhpcy5kYXRhLmRldmljZVRva2VuIH0pO1xuICB9XG5cbiAgaWYgKG9yUXVlcmllcy5sZW5ndGggPT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHByb21pc2UgPSBwcm9taXNlXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLmZpbmQoXG4gICAgICAgICdfSW5zdGFsbGF0aW9uJyxcbiAgICAgICAge1xuICAgICAgICAgICRvcjogb3JRdWVyaWVzLFxuICAgICAgICB9LFxuICAgICAgICB7fVxuICAgICAgKTtcbiAgICB9KVxuICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgcmVzdWx0cy5mb3JFYWNoKHJlc3VsdCA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLnF1ZXJ5ICYmXG4gICAgICAgICAgdGhpcy5xdWVyeS5vYmplY3RJZCAmJlxuICAgICAgICAgIHJlc3VsdC5vYmplY3RJZCA9PSB0aGlzLnF1ZXJ5Lm9iamVjdElkXG4gICAgICAgICkge1xuICAgICAgICAgIG9iamVjdElkTWF0Y2ggPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdC5pbnN0YWxsYXRpb25JZCA9PSBpbnN0YWxsYXRpb25JZCkge1xuICAgICAgICAgIGluc3RhbGxhdGlvbklkTWF0Y2ggPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdC5kZXZpY2VUb2tlbiA9PSB0aGlzLmRhdGEuZGV2aWNlVG9rZW4pIHtcbiAgICAgICAgICBkZXZpY2VUb2tlbk1hdGNoZXMucHVzaChyZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy8gU2FuaXR5IGNoZWNrcyB3aGVuIHJ1bm5pbmcgYSBxdWVyeVxuICAgICAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgICAgICBpZiAoIW9iamVjdElkTWF0Y2gpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQgZm9yIHVwZGF0ZS4nXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkICYmXG4gICAgICAgICAgb2JqZWN0SWRNYXRjaC5pbnN0YWxsYXRpb25JZCAmJlxuICAgICAgICAgIHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCAhPT0gb2JqZWN0SWRNYXRjaC5pbnN0YWxsYXRpb25JZFxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAxMzYsXG4gICAgICAgICAgICAnaW5zdGFsbGF0aW9uSWQgbWF5IG5vdCBiZSBjaGFuZ2VkIGluIHRoaXMgJyArICdvcGVyYXRpb24nXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5kYXRhLmRldmljZVRva2VuICYmXG4gICAgICAgICAgb2JqZWN0SWRNYXRjaC5kZXZpY2VUb2tlbiAmJlxuICAgICAgICAgIHRoaXMuZGF0YS5kZXZpY2VUb2tlbiAhPT0gb2JqZWN0SWRNYXRjaC5kZXZpY2VUb2tlbiAmJlxuICAgICAgICAgICF0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQgJiZcbiAgICAgICAgICAhb2JqZWN0SWRNYXRjaC5pbnN0YWxsYXRpb25JZFxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAxMzYsXG4gICAgICAgICAgICAnZGV2aWNlVG9rZW4gbWF5IG5vdCBiZSBjaGFuZ2VkIGluIHRoaXMgJyArICdvcGVyYXRpb24nXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5kYXRhLmRldmljZVR5cGUgJiZcbiAgICAgICAgICB0aGlzLmRhdGEuZGV2aWNlVHlwZSAmJlxuICAgICAgICAgIHRoaXMuZGF0YS5kZXZpY2VUeXBlICE9PSBvYmplY3RJZE1hdGNoLmRldmljZVR5cGVcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgMTM2LFxuICAgICAgICAgICAgJ2RldmljZVR5cGUgbWF5IG5vdCBiZSBjaGFuZ2VkIGluIHRoaXMgJyArICdvcGVyYXRpb24nXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkICYmIG9iamVjdElkTWF0Y2gpIHtcbiAgICAgICAgaWRNYXRjaCA9IG9iamVjdElkTWF0Y2g7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbnN0YWxsYXRpb25JZCAmJiBpbnN0YWxsYXRpb25JZE1hdGNoKSB7XG4gICAgICAgIGlkTWF0Y2ggPSBpbnN0YWxsYXRpb25JZE1hdGNoO1xuICAgICAgfVxuICAgICAgLy8gbmVlZCB0byBzcGVjaWZ5IGRldmljZVR5cGUgb25seSBpZiBpdCdzIG5ld1xuICAgICAgaWYgKCF0aGlzLnF1ZXJ5ICYmICF0aGlzLmRhdGEuZGV2aWNlVHlwZSAmJiAhaWRNYXRjaCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgMTM1LFxuICAgICAgICAgICdkZXZpY2VUeXBlIG11c3QgYmUgc3BlY2lmaWVkIGluIHRoaXMgb3BlcmF0aW9uJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKCFpZE1hdGNoKSB7XG4gICAgICAgIGlmICghZGV2aWNlVG9rZW5NYXRjaGVzLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBkZXZpY2VUb2tlbk1hdGNoZXMubGVuZ3RoID09IDEgJiZcbiAgICAgICAgICAoIWRldmljZVRva2VuTWF0Y2hlc1swXVsnaW5zdGFsbGF0aW9uSWQnXSB8fCAhaW5zdGFsbGF0aW9uSWQpXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIFNpbmdsZSBtYXRjaCBvbiBkZXZpY2UgdG9rZW4gYnV0IG5vbmUgb24gaW5zdGFsbGF0aW9uSWQsIGFuZCBlaXRoZXJcbiAgICAgICAgICAvLyB0aGUgcGFzc2VkIG9iamVjdCBvciB0aGUgbWF0Y2ggaXMgbWlzc2luZyBhbiBpbnN0YWxsYXRpb25JZCwgc28gd2VcbiAgICAgICAgICAvLyBjYW4ganVzdCByZXR1cm4gdGhlIG1hdGNoLlxuICAgICAgICAgIHJldHVybiBkZXZpY2VUb2tlbk1hdGNoZXNbMF1bJ29iamVjdElkJ107XG4gICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIDEzMixcbiAgICAgICAgICAgICdNdXN0IHNwZWNpZnkgaW5zdGFsbGF0aW9uSWQgd2hlbiBkZXZpY2VUb2tlbiAnICtcbiAgICAgICAgICAgICAgJ21hdGNoZXMgbXVsdGlwbGUgSW5zdGFsbGF0aW9uIG9iamVjdHMnXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBNdWx0aXBsZSBkZXZpY2UgdG9rZW4gbWF0Y2hlcyBhbmQgd2Ugc3BlY2lmaWVkIGFuIGluc3RhbGxhdGlvbiBJRCxcbiAgICAgICAgICAvLyBvciBhIHNpbmdsZSBtYXRjaCB3aGVyZSBib3RoIHRoZSBwYXNzZWQgYW5kIG1hdGNoaW5nIG9iamVjdHMgaGF2ZVxuICAgICAgICAgIC8vIGFuIGluc3RhbGxhdGlvbiBJRC4gVHJ5IGNsZWFuaW5nIG91dCBvbGQgaW5zdGFsbGF0aW9ucyB0aGF0IG1hdGNoXG4gICAgICAgICAgLy8gdGhlIGRldmljZVRva2VuLCBhbmQgcmV0dXJuIG5pbCB0byBzaWduYWwgdGhhdCBhIG5ldyBvYmplY3Qgc2hvdWxkXG4gICAgICAgICAgLy8gYmUgY3JlYXRlZC5cbiAgICAgICAgICB2YXIgZGVsUXVlcnkgPSB7XG4gICAgICAgICAgICBkZXZpY2VUb2tlbjogdGhpcy5kYXRhLmRldmljZVRva2VuLFxuICAgICAgICAgICAgaW5zdGFsbGF0aW9uSWQ6IHtcbiAgICAgICAgICAgICAgJG5lOiBpbnN0YWxsYXRpb25JZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgICBpZiAodGhpcy5kYXRhLmFwcElkZW50aWZpZXIpIHtcbiAgICAgICAgICAgIGRlbFF1ZXJ5WydhcHBJZGVudGlmaWVyJ10gPSB0aGlzLmRhdGEuYXBwSWRlbnRpZmllcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5jb25maWcuZGF0YWJhc2UuZGVzdHJveSgnX0luc3RhbGxhdGlvbicsIGRlbFF1ZXJ5KS5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgICAgaWYgKGVyci5jb2RlID09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgICAgLy8gbm8gZGVsZXRpb25zIHdlcmUgbWFkZS4gQ2FuIGJlIGlnbm9yZWQuXG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJldGhyb3cgdGhlIGVycm9yXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZGV2aWNlVG9rZW5NYXRjaGVzLmxlbmd0aCA9PSAxICYmXG4gICAgICAgICAgIWRldmljZVRva2VuTWF0Y2hlc1swXVsnaW5zdGFsbGF0aW9uSWQnXVxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBFeGFjdGx5IG9uZSBkZXZpY2UgdG9rZW4gbWF0Y2ggYW5kIGl0IGRvZXNuJ3QgaGF2ZSBhbiBpbnN0YWxsYXRpb25cbiAgICAgICAgICAvLyBJRC4gVGhpcyBpcyB0aGUgb25lIGNhc2Ugd2hlcmUgd2Ugd2FudCB0byBtZXJnZSB3aXRoIHRoZSBleGlzdGluZ1xuICAgICAgICAgIC8vIG9iamVjdC5cbiAgICAgICAgICBjb25zdCBkZWxRdWVyeSA9IHsgb2JqZWN0SWQ6IGlkTWF0Y2gub2JqZWN0SWQgfTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgICAgICAgIC5kZXN0cm95KCdfSW5zdGFsbGF0aW9uJywgZGVsUXVlcnkpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiBkZXZpY2VUb2tlbk1hdGNoZXNbMF1bJ29iamVjdElkJ107XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAgIGlmIChlcnIuY29kZSA9PSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EKSB7XG4gICAgICAgICAgICAgICAgLy8gbm8gZGVsZXRpb25zIHdlcmUgbWFkZS4gQ2FuIGJlIGlnbm9yZWRcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLy8gcmV0aHJvdyB0aGUgZXJyb3JcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5kYXRhLmRldmljZVRva2VuICYmXG4gICAgICAgICAgICBpZE1hdGNoLmRldmljZVRva2VuICE9IHRoaXMuZGF0YS5kZXZpY2VUb2tlblxuICAgICAgICAgICkge1xuICAgICAgICAgICAgLy8gV2UncmUgc2V0dGluZyB0aGUgZGV2aWNlIHRva2VuIG9uIGFuIGV4aXN0aW5nIGluc3RhbGxhdGlvbiwgc29cbiAgICAgICAgICAgIC8vIHdlIHNob3VsZCB0cnkgY2xlYW5pbmcgb3V0IG9sZCBpbnN0YWxsYXRpb25zIHRoYXQgbWF0Y2ggdGhpc1xuICAgICAgICAgICAgLy8gZGV2aWNlIHRva2VuLlxuICAgICAgICAgICAgY29uc3QgZGVsUXVlcnkgPSB7XG4gICAgICAgICAgICAgIGRldmljZVRva2VuOiB0aGlzLmRhdGEuZGV2aWNlVG9rZW4sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gV2UgaGF2ZSBhIHVuaXF1ZSBpbnN0YWxsIElkLCB1c2UgdGhhdCB0byBwcmVzZXJ2ZVxuICAgICAgICAgICAgLy8gdGhlIGludGVyZXN0aW5nIGluc3RhbGxhdGlvblxuICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCkge1xuICAgICAgICAgICAgICBkZWxRdWVyeVsnaW5zdGFsbGF0aW9uSWQnXSA9IHtcbiAgICAgICAgICAgICAgICAkbmU6IHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIGlkTWF0Y2gub2JqZWN0SWQgJiZcbiAgICAgICAgICAgICAgdGhpcy5kYXRhLm9iamVjdElkICYmXG4gICAgICAgICAgICAgIGlkTWF0Y2gub2JqZWN0SWQgPT0gdGhpcy5kYXRhLm9iamVjdElkXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgLy8gd2UgcGFzc2VkIGFuIG9iamVjdElkLCBwcmVzZXJ2ZSB0aGF0IGluc3RhbGF0aW9uXG4gICAgICAgICAgICAgIGRlbFF1ZXJ5WydvYmplY3RJZCddID0ge1xuICAgICAgICAgICAgICAgICRuZTogaWRNYXRjaC5vYmplY3RJZCxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFdoYXQgdG8gZG8gaGVyZT8gY2FuJ3QgcmVhbGx5IGNsZWFuIHVwIGV2ZXJ5dGhpbmcuLi5cbiAgICAgICAgICAgICAgcmV0dXJuIGlkTWF0Y2gub2JqZWN0SWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5kYXRhLmFwcElkZW50aWZpZXIpIHtcbiAgICAgICAgICAgICAgZGVsUXVlcnlbJ2FwcElkZW50aWZpZXInXSA9IHRoaXMuZGF0YS5hcHBJZGVudGlmaWVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgICAgICAgICAgLmRlc3Ryb3koJ19JbnN0YWxsYXRpb24nLCBkZWxRdWVyeSlcbiAgICAgICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVyci5jb2RlID09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgICAgICAgIC8vIG5vIGRlbGV0aW9ucyB3ZXJlIG1hZGUuIENhbiBiZSBpZ25vcmVkLlxuICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyByZXRocm93IHRoZSBlcnJvclxuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIEluIG5vbi1tZXJnZSBzY2VuYXJpb3MsIGp1c3QgcmV0dXJuIHRoZSBpbnN0YWxsYXRpb24gbWF0Y2ggaWRcbiAgICAgICAgICByZXR1cm4gaWRNYXRjaC5vYmplY3RJZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pXG4gICAgLnRoZW4ob2JqSWQgPT4ge1xuICAgICAgaWYgKG9iaklkKSB7XG4gICAgICAgIHRoaXMucXVlcnkgPSB7IG9iamVjdElkOiBvYmpJZCB9O1xuICAgICAgICBkZWxldGUgdGhpcy5kYXRhLm9iamVjdElkO1xuICAgICAgICBkZWxldGUgdGhpcy5kYXRhLmNyZWF0ZWRBdDtcbiAgICAgIH1cbiAgICAgIC8vIFRPRE86IFZhbGlkYXRlIG9wcyAoYWRkL3JlbW92ZSBvbiBjaGFubmVscywgJGluYyBvbiBiYWRnZSwgZXRjLilcbiAgICB9KTtcbiAgcmV0dXJuIHByb21pc2U7XG59O1xuXG4vLyBJZiB3ZSBzaG9ydC1jaXJjdXRlZCB0aGUgb2JqZWN0IHJlc3BvbnNlIC0gdGhlbiB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB3ZSBleHBhbmQgYWxsIHRoZSBmaWxlcyxcbi8vIHNpbmNlIHRoaXMgbWlnaHQgbm90IGhhdmUgYSBxdWVyeSwgbWVhbmluZyBpdCB3b24ndCByZXR1cm4gdGhlIGZ1bGwgcmVzdWx0IGJhY2suXG4vLyBUT0RPOiAobmx1dHNlbmtvKSBUaGlzIHNob3VsZCBkaWUgd2hlbiB3ZSBtb3ZlIHRvIHBlci1jbGFzcyBiYXNlZCBjb250cm9sbGVycyBvbiBfU2Vzc2lvbi9fVXNlclxuUmVzdFdyaXRlLnByb3RvdHlwZS5leHBhbmRGaWxlc0ZvckV4aXN0aW5nT2JqZWN0cyA9IGZ1bmN0aW9uKCkge1xuICAvLyBDaGVjayB3aGV0aGVyIHdlIGhhdmUgYSBzaG9ydC1jaXJjdWl0ZWQgcmVzcG9uc2UgLSBvbmx5IHRoZW4gcnVuIGV4cGFuc2lvbi5cbiAgaWYgKHRoaXMucmVzcG9uc2UgJiYgdGhpcy5yZXNwb25zZS5yZXNwb25zZSkge1xuICAgIHRoaXMuY29uZmlnLmZpbGVzQ29udHJvbGxlci5leHBhbmRGaWxlc0luT2JqZWN0KFxuICAgICAgdGhpcy5jb25maWcsXG4gICAgICB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlXG4gICAgKTtcbiAgfVxufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5ydW5EYXRhYmFzZU9wZXJhdGlvbiA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5yZXNwb25zZSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Sb2xlJykge1xuICAgIHRoaXMuY29uZmlnLmNhY2hlQ29udHJvbGxlci5yb2xlLmNsZWFyKCk7XG4gIH1cblxuICBpZiAoXG4gICAgdGhpcy5jbGFzc05hbWUgPT09ICdfVXNlcicgJiZcbiAgICB0aGlzLnF1ZXJ5ICYmXG4gICAgdGhpcy5hdXRoLmlzVW5hdXRoZW50aWNhdGVkKClcbiAgKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuU0VTU0lPTl9NSVNTSU5HLFxuICAgICAgYENhbm5vdCBtb2RpZnkgdXNlciAke3RoaXMucXVlcnkub2JqZWN0SWR9LmBcbiAgICApO1xuICB9XG5cbiAgaWYgKHRoaXMuY2xhc3NOYW1lID09PSAnX1Byb2R1Y3QnICYmIHRoaXMuZGF0YS5kb3dubG9hZCkge1xuICAgIHRoaXMuZGF0YS5kb3dubG9hZE5hbWUgPSB0aGlzLmRhdGEuZG93bmxvYWQubmFtZTtcbiAgfVxuXG4gIC8vIFRPRE86IEFkZCBiZXR0ZXIgZGV0ZWN0aW9uIGZvciBBQ0wsIGVuc3VyaW5nIGEgdXNlciBjYW4ndCBiZSBsb2NrZWQgZnJvbVxuICAvLyAgICAgICB0aGVpciBvd24gdXNlciByZWNvcmQuXG4gIGlmICh0aGlzLmRhdGEuQUNMICYmIHRoaXMuZGF0YS5BQ0xbJyp1bnJlc29sdmVkJ10pIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9BQ0wsICdJbnZhbGlkIEFDTC4nKTtcbiAgfVxuXG4gIGlmICh0aGlzLnF1ZXJ5KSB7XG4gICAgLy8gRm9yY2UgdGhlIHVzZXIgdG8gbm90IGxvY2tvdXRcbiAgICAvLyBNYXRjaGVkIHdpdGggcGFyc2UuY29tXG4gICAgaWYgKFxuICAgICAgdGhpcy5jbGFzc05hbWUgPT09ICdfVXNlcicgJiZcbiAgICAgIHRoaXMuZGF0YS5BQ0wgJiZcbiAgICAgIHRoaXMuYXV0aC5pc01hc3RlciAhPT0gdHJ1ZVxuICAgICkge1xuICAgICAgdGhpcy5kYXRhLkFDTFt0aGlzLnF1ZXJ5Lm9iamVjdElkXSA9IHsgcmVhZDogdHJ1ZSwgd3JpdGU6IHRydWUgfTtcbiAgICB9XG4gICAgLy8gdXBkYXRlIHBhc3N3b3JkIHRpbWVzdGFtcCBpZiB1c2VyIHBhc3N3b3JkIGlzIGJlaW5nIGNoYW5nZWRcbiAgICBpZiAoXG4gICAgICB0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJlxuICAgICAgdGhpcy5kYXRhLl9oYXNoZWRfcGFzc3dvcmQgJiZcbiAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5ICYmXG4gICAgICB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEFnZVxuICAgICkge1xuICAgICAgdGhpcy5kYXRhLl9wYXNzd29yZF9jaGFuZ2VkX2F0ID0gUGFyc2UuX2VuY29kZShuZXcgRGF0ZSgpKTtcbiAgICB9XG4gICAgLy8gSWdub3JlIGNyZWF0ZWRBdCB3aGVuIHVwZGF0ZVxuICAgIGRlbGV0ZSB0aGlzLmRhdGEuY3JlYXRlZEF0O1xuXG4gICAgbGV0IGRlZmVyID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgLy8gaWYgcGFzc3dvcmQgaGlzdG9yeSBpcyBlbmFibGVkIHRoZW4gc2F2ZSB0aGUgY3VycmVudCBwYXNzd29yZCB0byBoaXN0b3J5XG4gICAgaWYgKFxuICAgICAgdGhpcy5jbGFzc05hbWUgPT09ICdfVXNlcicgJiZcbiAgICAgIHRoaXMuZGF0YS5faGFzaGVkX3Bhc3N3b3JkICYmXG4gICAgICB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeSAmJlxuICAgICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5XG4gICAgKSB7XG4gICAgICBkZWZlciA9IHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgICAgIC5maW5kKFxuICAgICAgICAgICdfVXNlcicsXG4gICAgICAgICAgeyBvYmplY3RJZDogdGhpcy5vYmplY3RJZCgpIH0sXG4gICAgICAgICAgeyBrZXlzOiBbJ19wYXNzd29yZF9oaXN0b3J5JywgJ19oYXNoZWRfcGFzc3dvcmQnXSB9XG4gICAgICAgIClcbiAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9IDEpIHtcbiAgICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgdXNlciA9IHJlc3VsdHNbMF07XG4gICAgICAgICAgbGV0IG9sZFBhc3N3b3JkcyA9IFtdO1xuICAgICAgICAgIGlmICh1c2VyLl9wYXNzd29yZF9oaXN0b3J5KSB7XG4gICAgICAgICAgICBvbGRQYXNzd29yZHMgPSBfLnRha2UoXG4gICAgICAgICAgICAgIHVzZXIuX3Bhc3N3b3JkX2hpc3RvcnksXG4gICAgICAgICAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy9uLTEgcGFzc3dvcmRzIGdvIGludG8gaGlzdG9yeSBpbmNsdWRpbmcgbGFzdCBwYXNzd29yZFxuICAgICAgICAgIHdoaWxlIChcbiAgICAgICAgICAgIG9sZFBhc3N3b3Jkcy5sZW5ndGggPlxuICAgICAgICAgICAgTWF0aC5tYXgoMCwgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5IC0gMilcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIG9sZFBhc3N3b3Jkcy5zaGlmdCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvbGRQYXNzd29yZHMucHVzaCh1c2VyLnBhc3N3b3JkKTtcbiAgICAgICAgICB0aGlzLmRhdGEuX3Bhc3N3b3JkX2hpc3RvcnkgPSBvbGRQYXNzd29yZHM7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBkZWZlci50aGVuKCgpID0+IHtcbiAgICAgIC8vIFJ1biBhbiB1cGRhdGVcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgICAudXBkYXRlKFxuICAgICAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgICAgIHRoaXMucXVlcnksXG4gICAgICAgICAgdGhpcy5kYXRhLFxuICAgICAgICAgIHRoaXMucnVuT3B0aW9ucyxcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICB0aGlzLnZhbGlkU2NoZW1hQ29udHJvbGxlclxuICAgICAgICApXG4gICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICByZXNwb25zZS51cGRhdGVkQXQgPSB0aGlzLnVwZGF0ZWRBdDtcbiAgICAgICAgICB0aGlzLl91cGRhdGVSZXNwb25zZVdpdGhEYXRhKHJlc3BvbnNlLCB0aGlzLmRhdGEpO1xuICAgICAgICAgIHRoaXMucmVzcG9uc2UgPSB7IHJlc3BvbnNlIH07XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIC8vIFNldCB0aGUgZGVmYXVsdCBBQ0wgYW5kIHBhc3N3b3JkIHRpbWVzdGFtcCBmb3IgdGhlIG5ldyBfVXNlclxuICAgIGlmICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgdmFyIEFDTCA9IHRoaXMuZGF0YS5BQ0w7XG4gICAgICAvLyBkZWZhdWx0IHB1YmxpYyByL3cgQUNMXG4gICAgICBpZiAoIUFDTCkge1xuICAgICAgICBBQ0wgPSB7fTtcbiAgICAgICAgQUNMWycqJ10gPSB7IHJlYWQ6IHRydWUsIHdyaXRlOiBmYWxzZSB9O1xuICAgICAgfVxuICAgICAgLy8gbWFrZSBzdXJlIHRoZSB1c2VyIGlzIG5vdCBsb2NrZWQgZG93blxuICAgICAgQUNMW3RoaXMuZGF0YS5vYmplY3RJZF0gPSB7IHJlYWQ6IHRydWUsIHdyaXRlOiB0cnVlIH07XG4gICAgICB0aGlzLmRhdGEuQUNMID0gQUNMO1xuICAgICAgLy8gcGFzc3dvcmQgdGltZXN0YW1wIHRvIGJlIHVzZWQgd2hlbiBwYXNzd29yZCBleHBpcnkgcG9saWN5IGlzIGVuZm9yY2VkXG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5ICYmXG4gICAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlXG4gICAgICApIHtcbiAgICAgICAgdGhpcy5kYXRhLl9wYXNzd29yZF9jaGFuZ2VkX2F0ID0gUGFyc2UuX2VuY29kZShuZXcgRGF0ZSgpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSdW4gYSBjcmVhdGVcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgIC5jcmVhdGUoXG4gICAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgICB0aGlzLmRhdGEsXG4gICAgICAgIHRoaXMucnVuT3B0aW9ucyxcbiAgICAgICAgZmFsc2UsXG4gICAgICAgIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicgfHxcbiAgICAgICAgICBlcnJvci5jb2RlICE9PSBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUVcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBRdWljayBjaGVjaywgaWYgd2Ugd2VyZSBhYmxlIHRvIGluZmVyIHRoZSBkdXBsaWNhdGVkIGZpZWxkIG5hbWVcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGVycm9yICYmXG4gICAgICAgICAgZXJyb3IudXNlckluZm8gJiZcbiAgICAgICAgICBlcnJvci51c2VySW5mby5kdXBsaWNhdGVkX2ZpZWxkID09PSAndXNlcm5hbWUnXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLlVTRVJOQU1FX1RBS0VOLFxuICAgICAgICAgICAgJ0FjY291bnQgYWxyZWFkeSBleGlzdHMgZm9yIHRoaXMgdXNlcm5hbWUuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgZXJyb3IgJiZcbiAgICAgICAgICBlcnJvci51c2VySW5mbyAmJlxuICAgICAgICAgIGVycm9yLnVzZXJJbmZvLmR1cGxpY2F0ZWRfZmllbGQgPT09ICdlbWFpbCdcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRU1BSUxfVEFLRU4sXG4gICAgICAgICAgICAnQWNjb3VudCBhbHJlYWR5IGV4aXN0cyBmb3IgdGhpcyBlbWFpbCBhZGRyZXNzLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhpcyB3YXMgYSBmYWlsZWQgdXNlciBjcmVhdGlvbiBkdWUgdG8gdXNlcm5hbWUgb3IgZW1haWwgYWxyZWFkeSB0YWtlbiwgd2UgbmVlZCB0b1xuICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGl0IHdhcyB1c2VybmFtZSBvciBlbWFpbCBhbmQgcmV0dXJuIHRoZSBhcHByb3ByaWF0ZSBlcnJvci5cbiAgICAgICAgLy8gRmFsbGJhY2sgdG8gdGhlIG9yaWdpbmFsIG1ldGhvZFxuICAgICAgICAvLyBUT0RPOiBTZWUgaWYgd2UgY2FuIGxhdGVyIGRvIHRoaXMgd2l0aG91dCBhZGRpdGlvbmFsIHF1ZXJpZXMgYnkgdXNpbmcgbmFtZWQgaW5kZXhlcy5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgICAgICAgLmZpbmQoXG4gICAgICAgICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdXNlcm5hbWU6IHRoaXMuZGF0YS51c2VybmFtZSxcbiAgICAgICAgICAgICAgb2JqZWN0SWQ6IHsgJG5lOiB0aGlzLm9iamVjdElkKCkgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IGxpbWl0OiAxIH1cbiAgICAgICAgICApXG4gICAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5VU0VSTkFNRV9UQUtFTixcbiAgICAgICAgICAgICAgICAnQWNjb3VudCBhbHJlYWR5IGV4aXN0cyBmb3IgdGhpcyB1c2VybmFtZS4nXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZChcbiAgICAgICAgICAgICAgdGhpcy5jbGFzc05hbWUsXG4gICAgICAgICAgICAgIHsgZW1haWw6IHRoaXMuZGF0YS5lbWFpbCwgb2JqZWN0SWQ6IHsgJG5lOiB0aGlzLm9iamVjdElkKCkgfSB9LFxuICAgICAgICAgICAgICB7IGxpbWl0OiAxIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLkVNQUlMX1RBS0VOLFxuICAgICAgICAgICAgICAgICdBY2NvdW50IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIGVtYWlsIGFkZHJlc3MuJ1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsXG4gICAgICAgICAgICAgICdBIGR1cGxpY2F0ZSB2YWx1ZSBmb3IgYSBmaWVsZCB3aXRoIHVuaXF1ZSB2YWx1ZXMgd2FzIHByb3ZpZGVkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIHJlc3BvbnNlLm9iamVjdElkID0gdGhpcy5kYXRhLm9iamVjdElkO1xuICAgICAgICByZXNwb25zZS5jcmVhdGVkQXQgPSB0aGlzLmRhdGEuY3JlYXRlZEF0O1xuXG4gICAgICAgIGlmICh0aGlzLnJlc3BvbnNlU2hvdWxkSGF2ZVVzZXJuYW1lKSB7XG4gICAgICAgICAgcmVzcG9uc2UudXNlcm5hbWUgPSB0aGlzLmRhdGEudXNlcm5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdXBkYXRlUmVzcG9uc2VXaXRoRGF0YShyZXNwb25zZSwgdGhpcy5kYXRhKTtcbiAgICAgICAgdGhpcy5yZXNwb25zZSA9IHtcbiAgICAgICAgICBzdGF0dXM6IDIwMSxcbiAgICAgICAgICByZXNwb25zZSxcbiAgICAgICAgICBsb2NhdGlvbjogdGhpcy5sb2NhdGlvbigpLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gIH1cbn07XG5cbi8vIFJldHVybnMgbm90aGluZyAtIGRvZXNuJ3Qgd2FpdCBmb3IgdGhlIHRyaWdnZXIuXG5SZXN0V3JpdGUucHJvdG90eXBlLnJ1bkFmdGVyU2F2ZVRyaWdnZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLnJlc3BvbnNlIHx8ICF0aGlzLnJlc3BvbnNlLnJlc3BvbnNlKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gQXZvaWQgZG9pbmcgYW55IHNldHVwIGZvciB0cmlnZ2VycyBpZiB0aGVyZSBpcyBubyAnYWZ0ZXJTYXZlJyB0cmlnZ2VyIGZvciB0aGlzIGNsYXNzLlxuICBjb25zdCBoYXNBZnRlclNhdmVIb29rID0gdHJpZ2dlcnMudHJpZ2dlckV4aXN0cyhcbiAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlclNhdmUsXG4gICAgdGhpcy5jb25maWcuYXBwbGljYXRpb25JZFxuICApO1xuICBjb25zdCBoYXNMaXZlUXVlcnkgPSB0aGlzLmNvbmZpZy5saXZlUXVlcnlDb250cm9sbGVyLmhhc0xpdmVRdWVyeShcbiAgICB0aGlzLmNsYXNzTmFtZVxuICApO1xuICBpZiAoIWhhc0FmdGVyU2F2ZUhvb2sgJiYgIWhhc0xpdmVRdWVyeSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIHZhciBleHRyYURhdGEgPSB7IGNsYXNzTmFtZTogdGhpcy5jbGFzc05hbWUgfTtcbiAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgIGV4dHJhRGF0YS5vYmplY3RJZCA9IHRoaXMucXVlcnkub2JqZWN0SWQ7XG4gIH1cblxuICAvLyBCdWlsZCB0aGUgb3JpZ2luYWwgb2JqZWN0LCB3ZSBvbmx5IGRvIHRoaXMgZm9yIGEgdXBkYXRlIHdyaXRlLlxuICBsZXQgb3JpZ2luYWxPYmplY3Q7XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICBvcmlnaW5hbE9iamVjdCA9IHRyaWdnZXJzLmluZmxhdGUoZXh0cmFEYXRhLCB0aGlzLm9yaWdpbmFsRGF0YSk7XG4gIH1cblxuICAvLyBCdWlsZCB0aGUgaW5mbGF0ZWQgb2JqZWN0LCBkaWZmZXJlbnQgZnJvbSBiZWZvcmVTYXZlLCBvcmlnaW5hbERhdGEgaXMgbm90IGVtcHR5XG4gIC8vIHNpbmNlIGRldmVsb3BlcnMgY2FuIGNoYW5nZSBkYXRhIGluIHRoZSBiZWZvcmVTYXZlLlxuICBjb25zdCB1cGRhdGVkT2JqZWN0ID0gdGhpcy5idWlsZFVwZGF0ZWRPYmplY3QoZXh0cmFEYXRhKTtcbiAgdXBkYXRlZE9iamVjdC5faGFuZGxlU2F2ZVJlc3BvbnNlKFxuICAgIHRoaXMucmVzcG9uc2UucmVzcG9uc2UsXG4gICAgdGhpcy5yZXNwb25zZS5zdGF0dXMgfHwgMjAwXG4gICk7XG5cbiAgdGhpcy5jb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSgpLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgLy8gTm90aWZpeSBMaXZlUXVlcnlTZXJ2ZXIgaWYgcG9zc2libGVcbiAgICBjb25zdCBwZXJtcyA9IHNjaGVtYUNvbnRyb2xsZXIuZ2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKFxuICAgICAgdXBkYXRlZE9iamVjdC5jbGFzc05hbWVcbiAgICApO1xuICAgIHRoaXMuY29uZmlnLmxpdmVRdWVyeUNvbnRyb2xsZXIub25BZnRlclNhdmUoXG4gICAgICB1cGRhdGVkT2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgIHVwZGF0ZWRPYmplY3QsXG4gICAgICBvcmlnaW5hbE9iamVjdCxcbiAgICAgIHBlcm1zXG4gICAgKTtcbiAgfSk7XG5cbiAgLy8gUnVuIGFmdGVyU2F2ZSB0cmlnZ2VyXG4gIHJldHVybiB0cmlnZ2Vyc1xuICAgIC5tYXliZVJ1blRyaWdnZXIoXG4gICAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlclNhdmUsXG4gICAgICB0aGlzLmF1dGgsXG4gICAgICB1cGRhdGVkT2JqZWN0LFxuICAgICAgb3JpZ2luYWxPYmplY3QsXG4gICAgICB0aGlzLmNvbmZpZyxcbiAgICAgIHRoaXMuY29udGV4dFxuICAgIClcbiAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgaWYgKHJlc3VsdCAmJiB0eXBlb2YgcmVzdWx0ID09PSAnb2JqZWN0Jykge1xuICAgICAgICB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlID0gcmVzdWx0O1xuICAgICAgfVxuICAgIH0pXG4gICAgLmNhdGNoKGZ1bmN0aW9uKGVycikge1xuICAgICAgbG9nZ2VyLndhcm4oJ2FmdGVyU2F2ZSBjYXVnaHQgYW4gZXJyb3InLCBlcnIpO1xuICAgIH0pO1xufTtcblxuLy8gQSBoZWxwZXIgdG8gZmlndXJlIG91dCB3aGF0IGxvY2F0aW9uIHRoaXMgb3BlcmF0aW9uIGhhcHBlbnMgYXQuXG5SZXN0V3JpdGUucHJvdG90eXBlLmxvY2F0aW9uID0gZnVuY3Rpb24oKSB7XG4gIHZhciBtaWRkbGUgPVxuICAgIHRoaXMuY2xhc3NOYW1lID09PSAnX1VzZXInID8gJy91c2Vycy8nIDogJy9jbGFzc2VzLycgKyB0aGlzLmNsYXNzTmFtZSArICcvJztcbiAgcmV0dXJuIHRoaXMuY29uZmlnLm1vdW50ICsgbWlkZGxlICsgdGhpcy5kYXRhLm9iamVjdElkO1xufTtcblxuLy8gQSBoZWxwZXIgdG8gZ2V0IHRoZSBvYmplY3QgaWQgZm9yIHRoaXMgb3BlcmF0aW9uLlxuLy8gQmVjYXVzZSBpdCBjb3VsZCBiZSBlaXRoZXIgb24gdGhlIHF1ZXJ5IG9yIG9uIHRoZSBkYXRhXG5SZXN0V3JpdGUucHJvdG90eXBlLm9iamVjdElkID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmRhdGEub2JqZWN0SWQgfHwgdGhpcy5xdWVyeS5vYmplY3RJZDtcbn07XG5cbi8vIFJldHVybnMgYSBjb3B5IG9mIHRoZSBkYXRhIGFuZCBkZWxldGUgYmFkIGtleXMgKF9hdXRoX2RhdGEsIF9oYXNoZWRfcGFzc3dvcmQuLi4pXG5SZXN0V3JpdGUucHJvdG90eXBlLnNhbml0aXplZERhdGEgPSBmdW5jdGlvbigpIHtcbiAgY29uc3QgZGF0YSA9IE9iamVjdC5rZXlzKHRoaXMuZGF0YSkucmVkdWNlKChkYXRhLCBrZXkpID0+IHtcbiAgICAvLyBSZWdleHAgY29tZXMgZnJvbSBQYXJzZS5PYmplY3QucHJvdG90eXBlLnZhbGlkYXRlXG4gICAgaWYgKCEvXltBLVphLXpdWzAtOUEtWmEtel9dKiQvLnRlc3Qoa2V5KSkge1xuICAgICAgZGVsZXRlIGRhdGFba2V5XTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG4gIH0sIGRlZXBjb3B5KHRoaXMuZGF0YSkpO1xuICByZXR1cm4gUGFyc2UuX2RlY29kZSh1bmRlZmluZWQsIGRhdGEpO1xufTtcblxuLy8gUmV0dXJucyBhbiB1cGRhdGVkIGNvcHkgb2YgdGhlIG9iamVjdFxuUmVzdFdyaXRlLnByb3RvdHlwZS5idWlsZFVwZGF0ZWRPYmplY3QgPSBmdW5jdGlvbihleHRyYURhdGEpIHtcbiAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRyaWdnZXJzLmluZmxhdGUoZXh0cmFEYXRhLCB0aGlzLm9yaWdpbmFsRGF0YSk7XG4gIE9iamVjdC5rZXlzKHRoaXMuZGF0YSkucmVkdWNlKGZ1bmN0aW9uKGRhdGEsIGtleSkge1xuICAgIGlmIChrZXkuaW5kZXhPZignLicpID4gMCkge1xuICAgICAgLy8gc3ViZG9jdW1lbnQga2V5IHdpdGggZG90IG5vdGF0aW9uICgneC55Jzp2ID0+ICd4Jzp7J3knOnZ9KVxuICAgICAgY29uc3Qgc3BsaXR0ZWRLZXkgPSBrZXkuc3BsaXQoJy4nKTtcbiAgICAgIGNvbnN0IHBhcmVudFByb3AgPSBzcGxpdHRlZEtleVswXTtcbiAgICAgIGxldCBwYXJlbnRWYWwgPSB1cGRhdGVkT2JqZWN0LmdldChwYXJlbnRQcm9wKTtcbiAgICAgIGlmICh0eXBlb2YgcGFyZW50VmFsICE9PSAnb2JqZWN0Jykge1xuICAgICAgICBwYXJlbnRWYWwgPSB7fTtcbiAgICAgIH1cbiAgICAgIHBhcmVudFZhbFtzcGxpdHRlZEtleVsxXV0gPSBkYXRhW2tleV07XG4gICAgICB1cGRhdGVkT2JqZWN0LnNldChwYXJlbnRQcm9wLCBwYXJlbnRWYWwpO1xuICAgICAgZGVsZXRlIGRhdGFba2V5XTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG4gIH0sIGRlZXBjb3B5KHRoaXMuZGF0YSkpO1xuXG4gIHVwZGF0ZWRPYmplY3Quc2V0KHRoaXMuc2FuaXRpemVkRGF0YSgpKTtcbiAgcmV0dXJuIHVwZGF0ZWRPYmplY3Q7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLmNsZWFuVXNlckF1dGhEYXRhID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLnJlc3BvbnNlICYmIHRoaXMucmVzcG9uc2UucmVzcG9uc2UgJiYgdGhpcy5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBjb25zdCB1c2VyID0gdGhpcy5yZXNwb25zZS5yZXNwb25zZTtcbiAgICBpZiAodXNlci5hdXRoRGF0YSkge1xuICAgICAgT2JqZWN0LmtleXModXNlci5hdXRoRGF0YSkuZm9yRWFjaChwcm92aWRlciA9PiB7XG4gICAgICAgIGlmICh1c2VyLmF1dGhEYXRhW3Byb3ZpZGVyXSA9PT0gbnVsbCkge1xuICAgICAgICAgIGRlbGV0ZSB1c2VyLmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoT2JqZWN0LmtleXModXNlci5hdXRoRGF0YSkubGVuZ3RoID09IDApIHtcbiAgICAgICAgZGVsZXRlIHVzZXIuYXV0aERhdGE7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLl91cGRhdGVSZXNwb25zZVdpdGhEYXRhID0gZnVuY3Rpb24ocmVzcG9uc2UsIGRhdGEpIHtcbiAgaWYgKF8uaXNFbXB0eSh0aGlzLnN0b3JhZ2UuZmllbGRzQ2hhbmdlZEJ5VHJpZ2dlcikpIHtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cbiAgY29uc3QgY2xpZW50U3VwcG9ydHNEZWxldGUgPSBDbGllbnRTREsuc3VwcG9ydHNGb3J3YXJkRGVsZXRlKHRoaXMuY2xpZW50U0RLKTtcbiAgdGhpcy5zdG9yYWdlLmZpZWxkc0NoYW5nZWRCeVRyaWdnZXIuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgIGNvbnN0IGRhdGFWYWx1ZSA9IGRhdGFbZmllbGROYW1lXTtcblxuICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3BvbnNlLCBmaWVsZE5hbWUpKSB7XG4gICAgICByZXNwb25zZVtmaWVsZE5hbWVdID0gZGF0YVZhbHVlO1xuICAgIH1cblxuICAgIC8vIFN0cmlwcyBvcGVyYXRpb25zIGZyb20gcmVzcG9uc2VzXG4gICAgaWYgKHJlc3BvbnNlW2ZpZWxkTmFtZV0gJiYgcmVzcG9uc2VbZmllbGROYW1lXS5fX29wKSB7XG4gICAgICBkZWxldGUgcmVzcG9uc2VbZmllbGROYW1lXTtcbiAgICAgIGlmIChjbGllbnRTdXBwb3J0c0RlbGV0ZSAmJiBkYXRhVmFsdWUuX19vcCA9PSAnRGVsZXRlJykge1xuICAgICAgICByZXNwb25zZVtmaWVsZE5hbWVdID0gZGF0YVZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG4gIHJldHVybiByZXNwb25zZTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IFJlc3RXcml0ZTtcbm1vZHVsZS5leHBvcnRzID0gUmVzdFdyaXRlO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/AggregateRouter.js b/lib/Routers/AggregateRouter.js new file mode 100644 index 0000000000..ae627b9a15 --- /dev/null +++ b/lib/Routers/AggregateRouter.js @@ -0,0 +1,138 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AggregateRouter = void 0; + +var _ClassesRouter = _interopRequireDefault(require("./ClassesRouter")); + +var _rest = _interopRequireDefault(require("../rest")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +var _node = _interopRequireDefault(require("parse/node")); + +var _UsersRouter = _interopRequireDefault(require("./UsersRouter")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const BASE_KEYS = ['where', 'distinct', 'pipeline']; +const PIPELINE_KEYS = ['addFields', 'bucket', 'bucketAuto', 'collStats', 'count', 'currentOp', 'facet', 'geoNear', 'graphLookup', 'group', 'indexStats', 'limit', 'listLocalSessions', 'listSessions', 'lookup', 'match', 'out', 'project', 'redact', 'replaceRoot', 'sample', 'skip', 'sort', 'sortByCount', 'unwind']; +const ALLOWED_KEYS = [...BASE_KEYS, ...PIPELINE_KEYS]; + +class AggregateRouter extends _ClassesRouter.default { + handleFind(req) { + const body = Object.assign(req.body, _ClassesRouter.default.JSONFromQuery(req.query)); + const options = {}; + + if (body.distinct) { + options.distinct = String(body.distinct); + } + + options.pipeline = AggregateRouter.getPipeline(body); + + if (typeof body.where === 'string') { + body.where = JSON.parse(body.where); + } + + return _rest.default.find(req.config, req.auth, this.className(req), body.where, options, req.info.clientSDK).then(response => { + for (const result of response.results) { + if (typeof result === 'object') { + _UsersRouter.default.removeHiddenProperties(result); + } + } + + return { + response + }; + }); + } + /* Builds a pipeline from the body. Originally the body could be passed as a single object, + * and now we support many options + * + * Array + * + * body: [{ + * group: { objectId: '$name' }, + * }] + * + * Object + * + * body: { + * group: { objectId: '$name' }, + * } + * + * + * Pipeline Operator with an Array or an Object + * + * body: { + * pipeline: { + * group: { objectId: '$name' }, + * } + * } + * + */ + + + static getPipeline(body) { + let pipeline = body.pipeline || body; + + if (!Array.isArray(pipeline)) { + pipeline = Object.keys(pipeline).map(key => { + return { + [key]: pipeline[key] + }; + }); + } + + return pipeline.map(stage => { + const keys = Object.keys(stage); + + if (keys.length != 1) { + throw new Error(`Pipeline stages should only have one key found ${keys.join(', ')}`); + } + + return AggregateRouter.transformStage(keys[0], stage); + }); + } + + static transformStage(stageName, stage) { + if (ALLOWED_KEYS.indexOf(stageName) === -1) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Invalid parameter for query: ${stageName}`); + } + + if (stageName === 'group') { + if (Object.prototype.hasOwnProperty.call(stage[stageName], '_id')) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Invalid parameter for query: group. Please use objectId instead of _id`); + } + + if (!Object.prototype.hasOwnProperty.call(stage[stageName], 'objectId')) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Invalid parameter for query: group. objectId is required`); + } + + stage[stageName]._id = stage[stageName].objectId; + delete stage[stageName].objectId; + } + + return { + [`$${stageName}`]: stage[stageName] + }; + } + + mountRoutes() { + this.route('GET', '/aggregate/:className', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handleFind(req); + }); + } + +} + +exports.AggregateRouter = AggregateRouter; +var _default = AggregateRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0FnZ3JlZ2F0ZVJvdXRlci5qcyJdLCJuYW1lcyI6WyJCQVNFX0tFWVMiLCJQSVBFTElORV9LRVlTIiwiQUxMT1dFRF9LRVlTIiwiQWdncmVnYXRlUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImhhbmRsZUZpbmQiLCJyZXEiLCJib2R5IiwiT2JqZWN0IiwiYXNzaWduIiwiSlNPTkZyb21RdWVyeSIsInF1ZXJ5Iiwib3B0aW9ucyIsImRpc3RpbmN0IiwiU3RyaW5nIiwicGlwZWxpbmUiLCJnZXRQaXBlbGluZSIsIndoZXJlIiwiSlNPTiIsInBhcnNlIiwicmVzdCIsImZpbmQiLCJjb25maWciLCJhdXRoIiwiY2xhc3NOYW1lIiwiaW5mbyIsImNsaWVudFNESyIsInRoZW4iLCJyZXNwb25zZSIsInJlc3VsdCIsInJlc3VsdHMiLCJVc2Vyc1JvdXRlciIsInJlbW92ZUhpZGRlblByb3BlcnRpZXMiLCJBcnJheSIsImlzQXJyYXkiLCJrZXlzIiwibWFwIiwia2V5Iiwic3RhZ2UiLCJsZW5ndGgiLCJFcnJvciIsImpvaW4iLCJ0cmFuc2Zvcm1TdGFnZSIsInN0YWdlTmFtZSIsImluZGV4T2YiLCJQYXJzZSIsIklOVkFMSURfUVVFUlkiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJfaWQiLCJvYmplY3RJZCIsIm1vdW50Um91dGVzIiwicm91dGUiLCJtaWRkbGV3YXJlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNQSxTQUFTLEdBQUcsQ0FBQyxPQUFELEVBQVUsVUFBVixFQUFzQixVQUF0QixDQUFsQjtBQUVBLE1BQU1DLGFBQWEsR0FBRyxDQUNwQixXQURvQixFQUVwQixRQUZvQixFQUdwQixZQUhvQixFQUlwQixXQUpvQixFQUtwQixPQUxvQixFQU1wQixXQU5vQixFQU9wQixP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QUQ7QUFBMUIsS0FBUDtBQUNEOztBQUVEUyxFQUFBQSxXQUFXLEdBQUc7QUFDWixTQUFLQyxLQUFMLENBQ0UsS0FERixFQUVFLHVCQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRWpELEdBQUcsSUFBSTtBQUNMLGFBQU8sS0FBS0QsVUFBTCxDQUFnQkMsR0FBaEIsQ0FBUDtBQUNELEtBTkg7QUFRRDs7QUFqSGdEOzs7ZUFvSHBDSCxlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IENsYXNzZXNSb3V0ZXIgZnJvbSAnLi9DbGFzc2VzUm91dGVyJztcbmltcG9ydCByZXN0IGZyb20gJy4uL3Jlc3QnO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgVXNlcnNSb3V0ZXIgZnJvbSAnLi9Vc2Vyc1JvdXRlcic7XG5cbmNvbnN0IEJBU0VfS0VZUyA9IFsnd2hlcmUnLCAnZGlzdGluY3QnLCAncGlwZWxpbmUnXTtcblxuY29uc3QgUElQRUxJTkVfS0VZUyA9IFtcbiAgJ2FkZEZpZWxkcycsXG4gICdidWNrZXQnLFxuICAnYnVja2V0QXV0bycsXG4gICdjb2xsU3RhdHMnLFxuICAnY291bnQnLFxuICAnY3VycmVudE9wJyxcbiAgJ2ZhY2V0JyxcbiAgJ2dlb05lYXInLFxuICAnZ3JhcGhMb29rdXAnLFxuICAnZ3JvdXAnLFxuICAnaW5kZXhTdGF0cycsXG4gICdsaW1pdCcsXG4gICdsaXN0TG9jYWxTZXNzaW9ucycsXG4gICdsaXN0U2Vzc2lvbnMnLFxuICAnbG9va3VwJyxcbiAgJ21hdGNoJyxcbiAgJ291dCcsXG4gICdwcm9qZWN0JyxcbiAgJ3JlZGFjdCcsXG4gICdyZXBsYWNlUm9vdCcsXG4gICdzYW1wbGUnLFxuICAnc2tpcCcsXG4gICdzb3J0JyxcbiAgJ3NvcnRCeUNvdW50JyxcbiAgJ3Vud2luZCcsXG5dO1xuXG5jb25zdCBBTExPV0VEX0tFWVMgPSBbLi4uQkFTRV9LRVlTLCAuLi5QSVBFTElORV9LRVlTXTtcblxuZXhwb3J0IGNsYXNzIEFnZ3JlZ2F0ZVJvdXRlciBleHRlbmRzIENsYXNzZXNSb3V0ZXIge1xuICBoYW5kbGVGaW5kKHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKFxuICAgICAgcmVxLmJvZHksXG4gICAgICBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KVxuICAgICk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHt9O1xuICAgIGlmIChib2R5LmRpc3RpbmN0KSB7XG4gICAgICBvcHRpb25zLmRpc3RpbmN0ID0gU3RyaW5nKGJvZHkuZGlzdGluY3QpO1xuICAgIH1cbiAgICBvcHRpb25zLnBpcGVsaW5lID0gQWdncmVnYXRlUm91dGVyLmdldFBpcGVsaW5lKGJvZHkpO1xuICAgIGlmICh0eXBlb2YgYm9keS53aGVyZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGJvZHkud2hlcmUgPSBKU09OLnBhcnNlKGJvZHkud2hlcmUpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdFxuICAgICAgLmZpbmQoXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIHJlcS5hdXRoLFxuICAgICAgICB0aGlzLmNsYXNzTmFtZShyZXEpLFxuICAgICAgICBib2R5LndoZXJlLFxuICAgICAgICBvcHRpb25zLFxuICAgICAgICByZXEuaW5mby5jbGllbnRTREtcbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzcG9uc2UucmVzdWx0cykge1xuICAgICAgICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgVXNlcnNSb3V0ZXIucmVtb3ZlSGlkZGVuUHJvcGVydGllcyhyZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyByZXNwb25zZSB9O1xuICAgICAgfSk7XG4gIH1cblxuICAvKiBCdWlsZHMgYSBwaXBlbGluZSBmcm9tIHRoZSBib2R5LiBPcmlnaW5hbGx5IHRoZSBib2R5IGNvdWxkIGJlIHBhc3NlZCBhcyBhIHNpbmdsZSBvYmplY3QsXG4gICAqIGFuZCBub3cgd2Ugc3VwcG9ydCBtYW55IG9wdGlvbnNcbiAgICpcbiAgICogQXJyYXlcbiAgICpcbiAgICogYm9keTogW3tcbiAgICogICBncm91cDogeyBvYmplY3RJZDogJyRuYW1lJyB9LFxuICAgKiB9XVxuICAgKlxuICAgKiBPYmplY3RcbiAgICpcbiAgICogYm9keToge1xuICAgKiAgIGdyb3VwOiB7IG9iamVjdElkOiAnJG5hbWUnIH0sXG4gICAqIH1cbiAgICpcbiAgICpcbiAgICogUGlwZWxpbmUgT3BlcmF0b3Igd2l0aCBhbiBBcnJheSBvciBhbiBPYmplY3RcbiAgICpcbiAgICogYm9keToge1xuICAgKiAgIHBpcGVsaW5lOiB7XG4gICAqICAgICBncm91cDogeyBvYmplY3RJZDogJyRuYW1lJyB9LFxuICAgKiAgIH1cbiAgICogfVxuICAgKlxuICAgKi9cbiAgc3RhdGljIGdldFBpcGVsaW5lKGJvZHkpIHtcbiAgICBsZXQgcGlwZWxpbmUgPSBib2R5LnBpcGVsaW5lIHx8IGJvZHk7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICBwaXBlbGluZSA9IE9iamVjdC5rZXlzKHBpcGVsaW5lKS5tYXAoa2V5ID0+IHtcbiAgICAgICAgcmV0dXJuIHsgW2tleV06IHBpcGVsaW5lW2tleV0gfTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBwaXBlbGluZS5tYXAoc3RhZ2UgPT4ge1xuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHN0YWdlKTtcbiAgICAgIGlmIChrZXlzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgUGlwZWxpbmUgc3RhZ2VzIHNob3VsZCBvbmx5IGhhdmUgb25lIGtleSBmb3VuZCAke2tleXMuam9pbignLCAnKX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gQWdncmVnYXRlUm91dGVyLnRyYW5zZm9ybVN0YWdlKGtleXNbMF0sIHN0YWdlKTtcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyB0cmFuc2Zvcm1TdGFnZShzdGFnZU5hbWUsIHN0YWdlKSB7XG4gICAgaWYgKEFMTE9XRURfS0VZUy5pbmRleE9mKHN0YWdlTmFtZSkgPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgIGBJbnZhbGlkIHBhcmFtZXRlciBmb3IgcXVlcnk6ICR7c3RhZ2VOYW1lfWBcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChzdGFnZU5hbWUgPT09ICdncm91cCcpIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc3RhZ2Vbc3RhZ2VOYW1lXSwgJ19pZCcpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgIGBJbnZhbGlkIHBhcmFtZXRlciBmb3IgcXVlcnk6IGdyb3VwLiBQbGVhc2UgdXNlIG9iamVjdElkIGluc3RlYWQgb2YgX2lkYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc3RhZ2Vbc3RhZ2VOYW1lXSwgJ29iamVjdElkJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgYEludmFsaWQgcGFyYW1ldGVyIGZvciBxdWVyeTogZ3JvdXAuIG9iamVjdElkIGlzIHJlcXVpcmVkYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgc3RhZ2Vbc3RhZ2VOYW1lXS5faWQgPSBzdGFnZVtzdGFnZU5hbWVdLm9iamVjdElkO1xuICAgICAgZGVsZXRlIHN0YWdlW3N0YWdlTmFtZV0ub2JqZWN0SWQ7XG4gICAgfVxuICAgIHJldHVybiB7IFtgJCR7c3RhZ2VOYW1lfWBdOiBzdGFnZVtzdGFnZU5hbWVdIH07XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL2FnZ3JlZ2F0ZS86Y2xhc3NOYW1lJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBBZ2dyZWdhdGVSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/AnalyticsRouter.js b/lib/Routers/AnalyticsRouter.js new file mode 100644 index 0000000000..d37290b37f --- /dev/null +++ b/lib/Routers/AnalyticsRouter.js @@ -0,0 +1,32 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AnalyticsRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// AnalyticsRouter.js +function appOpened(req) { + const analyticsController = req.config.analyticsController; + return analyticsController.appOpened(req); +} + +function trackEvent(req) { + const analyticsController = req.config.analyticsController; + return analyticsController.trackEvent(req); +} + +class AnalyticsRouter extends _PromiseRouter.default { + mountRoutes() { + this.route('POST', '/events/AppOpened', appOpened); + this.route('POST', '/events/:eventName', trackEvent); + } + +} + +exports.AnalyticsRouter = AnalyticsRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0FuYWx5dGljc1JvdXRlci5qcyJdLCJuYW1lcyI6WyJhcHBPcGVuZWQiLCJyZXEiLCJhbmFseXRpY3NDb250cm9sbGVyIiwiY29uZmlnIiwidHJhY2tFdmVudCIsIkFuYWx5dGljc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJtb3VudFJvdXRlcyIsInJvdXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7Ozs7QUFEQTtBQUdBLFNBQVNBLFNBQVQsQ0FBbUJDLEdBQW5CLEVBQXdCO0FBQ3RCLFFBQU1DLG1CQUFtQixHQUFHRCxHQUFHLENBQUNFLE1BQUosQ0FBV0QsbUJBQXZDO0FBQ0EsU0FBT0EsbUJBQW1CLENBQUNGLFNBQXBCLENBQThCQyxHQUE5QixDQUFQO0FBQ0Q7O0FBRUQsU0FBU0csVUFBVCxDQUFvQkgsR0FBcEIsRUFBeUI7QUFDdkIsUUFBTUMsbUJBQW1CLEdBQUdELEdBQUcsQ0FBQ0UsTUFBSixDQUFXRCxtQkFBdkM7QUFDQSxTQUFPQSxtQkFBbUIsQ0FBQ0UsVUFBcEIsQ0FBK0JILEdBQS9CLENBQVA7QUFDRDs7QUFFTSxNQUFNSSxlQUFOLFNBQThCQyxzQkFBOUIsQ0FBNEM7QUFDakRDLEVBQUFBLFdBQVcsR0FBRztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLG1CQUFuQixFQUF3Q1IsU0FBeEM7QUFDQSxTQUFLUSxLQUFMLENBQVcsTUFBWCxFQUFtQixvQkFBbkIsRUFBeUNKLFVBQXpDO0FBQ0Q7O0FBSmdEIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQW5hbHl0aWNzUm91dGVyLmpzXG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcblxuZnVuY3Rpb24gYXBwT3BlbmVkKHJlcSkge1xuICBjb25zdCBhbmFseXRpY3NDb250cm9sbGVyID0gcmVxLmNvbmZpZy5hbmFseXRpY3NDb250cm9sbGVyO1xuICByZXR1cm4gYW5hbHl0aWNzQ29udHJvbGxlci5hcHBPcGVuZWQocmVxKTtcbn1cblxuZnVuY3Rpb24gdHJhY2tFdmVudChyZXEpIHtcbiAgY29uc3QgYW5hbHl0aWNzQ29udHJvbGxlciA9IHJlcS5jb25maWcuYW5hbHl0aWNzQ29udHJvbGxlcjtcbiAgcmV0dXJuIGFuYWx5dGljc0NvbnRyb2xsZXIudHJhY2tFdmVudChyZXEpO1xufVxuXG5leHBvcnQgY2xhc3MgQW5hbHl0aWNzUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2V2ZW50cy9BcHBPcGVuZWQnLCBhcHBPcGVuZWQpO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2V2ZW50cy86ZXZlbnROYW1lJywgdHJhY2tFdmVudCk7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/AudiencesRouter.js b/lib/Routers/AudiencesRouter.js new file mode 100644 index 0000000000..9dce665f6b --- /dev/null +++ b/lib/Routers/AudiencesRouter.js @@ -0,0 +1,70 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AudiencesRouter = void 0; + +var _ClassesRouter = _interopRequireDefault(require("./ClassesRouter")); + +var _rest = _interopRequireDefault(require("../rest")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AudiencesRouter extends _ClassesRouter.default { + className() { + return '_Audience'; + } + + handleFind(req) { + const body = Object.assign(req.body, _ClassesRouter.default.JSONFromQuery(req.query)); + + const options = _ClassesRouter.default.optionsFromBody(body); + + return _rest.default.find(req.config, req.auth, '_Audience', body.where, options, req.info.clientSDK).then(response => { + response.results.forEach(item => { + item.query = JSON.parse(item.query); + }); + return { + response: response + }; + }); + } + + handleGet(req) { + return super.handleGet(req).then(data => { + data.response.query = JSON.parse(data.response.query); + return data; + }); + } + + mountRoutes() { + this.route('GET', '/push_audiences', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handleFind(req); + }); + this.route('GET', '/push_audiences/:objectId', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handleGet(req); + }); + this.route('POST', '/push_audiences', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handleCreate(req); + }); + this.route('PUT', '/push_audiences/:objectId', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handleUpdate(req); + }); + this.route('DELETE', '/push_audiences/:objectId', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handleDelete(req); + }); + } + +} + +exports.AudiencesRouter = AudiencesRouter; +var _default = AudiencesRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0F1ZGllbmNlc1JvdXRlci5qcyJdLCJuYW1lcyI6WyJBdWRpZW5jZXNSb3V0ZXIiLCJDbGFzc2VzUm91dGVyIiwiY2xhc3NOYW1lIiwiaGFuZGxlRmluZCIsInJlcSIsImJvZHkiLCJPYmplY3QiLCJhc3NpZ24iLCJKU09ORnJvbVF1ZXJ5IiwicXVlcnkiLCJvcHRpb25zIiwib3B0aW9uc0Zyb21Cb2R5IiwicmVzdCIsImZpbmQiLCJjb25maWciLCJhdXRoIiwid2hlcmUiLCJpbmZvIiwiY2xpZW50U0RLIiwidGhlbiIsInJlc3BvbnNlIiwicmVzdWx0cyIsImZvckVhY2giLCJpdGVtIiwiSlNPTiIsInBhcnNlIiwiaGFuZGxlR2V0IiwiZGF0YSIsIm1vdW50Um91dGVzIiwicm91dGUiLCJtaWRkbGV3YXJlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJoYW5kbGVDcmVhdGUiLCJoYW5kbGVVcGRhdGUiLCJoYW5kbGVEZWxldGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFTyxNQUFNQSxlQUFOLFNBQThCQyxzQkFBOUIsQ0FBNEM7QUFDakRDLEVBQUFBLFNBQVMsR0FBRztBQUNWLFdBQU8sV0FBUDtBQUNEOztBQUVEQyxFQUFBQSxVQUFVLENBQUNDLEdBQUQsRUFBTTtBQUNkLFVBQU1DLElBQUksR0FBR0MsTUFBTSxDQUFDQyxNQUFQLENBQ1hILEdBQUcsQ0FBQ0MsSUFETyxFQUVYSix1QkFBY08sYUFBZCxDQUE0QkosR0FBRyxDQUFDSyxLQUFoQyxDQUZXLENBQWI7O0FBSUEsVUFBTUMsT0FBTyxHQUFHVCx1QkFBY1UsZUFBZCxDQUE4Qk4sSUFBOUIsQ0FBaEI7O0FBRUEsV0FBT08sY0FDSkMsSUFESSxDQUVIVCxHQUFHLENBQUNVLE1BRkQsRUFHSFYsR0FBRyxDQUFDVyxJQUhELEVBSUgsV0FKRyxFQUtIVixJQUFJLENBQUNXLEtBTEYsRUFNSE4sT0FORyxFQU9ITixHQUFHLENBQUNhLElBQUosQ0FBU0MsU0FQTixFQVNKQyxJQVRJLENBU0NDLFFBQVEsSUFBSTtBQUNoQkEsTUFBQUEsUUFBUSxDQUFDQyxPQUFULENBQWlCQyxPQUFqQixDQUF5QkMsSUFBSSxJQUFJO0FBQy9CQSxRQUFBQSxJQUFJLENBQUNkLEtBQUwsR0FBYWUsSUFBSSxDQUFDQyxLQUFMLENBQVdGLElBQUksQ0FBQ2QsS0FBaEIsQ0FBYjtBQUNELE9BRkQ7QUFJQSxhQUFPO0FBQUVXLFFBQUFBLFFBQVEsRUFBRUE7QUFBWixPQUFQO0FBQ0QsS0FmSSxDQUFQO0FBZ0JEOztBQUVETSxFQUFBQSxTQUFTLENBQUN0QixHQUFELEVBQU07QUFDYixXQUFPLE1BQU1zQixTQUFOLENBQWdCdEIsR0FBaEIsRUFBcUJlLElBQXJCLENBQTBCUSxJQUFJLElBQUk7QUFDdkNBLE1BQUFBLElBQUksQ0FBQ1AsUUFBTCxDQUFjWCxLQUFkLEdBQXNCZSxJQUFJLENBQUNDLEtBQUwsQ0FBV0UsSUFBSSxDQUFDUCxRQUFMLENBQWNYLEtBQXpCLENBQXRCO0FBRUEsYUFBT2tCLElBQVA7QUFDRCxLQUpNLENBQVA7QUFLRDs7QUFFREMsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxDQUNFLEtBREYsRUFFRSxpQkFGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUUzQixHQUFHLElBQUk7QUFDTCxhQUFPLEtBQUtELFVBQUwsQ0FBZ0JDLEdBQWhCLENBQVA7QUFDRCxLQU5IO0FBUUEsU0FBS3lCLEtBQUwsQ0FDRSxLQURGLEVBRUUsMkJBRkYsRUFHRUMsVUFBVSxDQUFDQyw2QkFIYixFQUlFM0IsR0FBRyxJQUFJO0FBQ0wsYUFBTyxLQUFLc0IsU0FBTCxDQUFldEIsR0FBZixDQUFQO0FBQ0QsS0FOSDtBQVFBLFNBQUt5QixLQUFMLENBQ0UsTUFERixFQUVFLGlCQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRTNCLEdBQUcsSUFBSTtBQUNMLGFBQU8sS0FBSzRCLFlBQUwsQ0FBa0I1QixHQUFsQixDQUFQO0FBQ0QsS0FOSDtBQVFBLFNBQUt5QixLQUFMLENBQ0UsS0FERixFQUVFLDJCQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRTNCLEdBQUcsSUFBSTtBQUNMLGFBQU8sS0FBSzZCLFlBQUwsQ0FBa0I3QixHQUFsQixDQUFQO0FBQ0QsS0FOSDtBQVFBLFNBQUt5QixLQUFMLENBQ0UsUUFERixFQUVFLDJCQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRTNCLEdBQUcsSUFBSTtBQUNMLGFBQU8sS0FBSzhCLFlBQUwsQ0FBa0I5QixHQUFsQixDQUFQO0FBQ0QsS0FOSDtBQVFEOztBQS9FZ0Q7OztlQWtGcENKLGUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQ2xhc3Nlc1JvdXRlciBmcm9tICcuL0NsYXNzZXNSb3V0ZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgKiBhcyBtaWRkbGV3YXJlIGZyb20gJy4uL21pZGRsZXdhcmVzJztcblxuZXhwb3J0IGNsYXNzIEF1ZGllbmNlc1JvdXRlciBleHRlbmRzIENsYXNzZXNSb3V0ZXIge1xuICBjbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdfQXVkaWVuY2UnO1xuICB9XG5cbiAgaGFuZGxlRmluZChyZXEpIHtcbiAgICBjb25zdCBib2R5ID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHJlcS5ib2R5LFxuICAgICAgQ2xhc3Nlc1JvdXRlci5KU09ORnJvbVF1ZXJ5KHJlcS5xdWVyeSlcbiAgICApO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBDbGFzc2VzUm91dGVyLm9wdGlvbnNGcm9tQm9keShib2R5KTtcblxuICAgIHJldHVybiByZXN0XG4gICAgICAuZmluZChcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGgsXG4gICAgICAgICdfQXVkaWVuY2UnLFxuICAgICAgICBib2R5LndoZXJlLFxuICAgICAgICBvcHRpb25zLFxuICAgICAgICByZXEuaW5mby5jbGllbnRTREtcbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgcmVzcG9uc2UucmVzdWx0cy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICAgIGl0ZW0ucXVlcnkgPSBKU09OLnBhcnNlKGl0ZW0ucXVlcnkpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4geyByZXNwb25zZTogcmVzcG9uc2UgfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlR2V0KHJlcSkge1xuICAgIHJldHVybiBzdXBlci5oYW5kbGVHZXQocmVxKS50aGVuKGRhdGEgPT4ge1xuICAgICAgZGF0YS5yZXNwb25zZS5xdWVyeSA9IEpTT04ucGFyc2UoZGF0YS5yZXNwb25zZS5xdWVyeSk7XG5cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0pO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9wdXNoX2F1ZGllbmNlcycsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRmluZChyZXEpO1xuICAgICAgfVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9wdXNoX2F1ZGllbmNlcy86b2JqZWN0SWQnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZUdldChyZXEpO1xuICAgICAgfVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQT1NUJyxcbiAgICAgICcvcHVzaF9hdWRpZW5jZXMnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZUNyZWF0ZShyZXEpO1xuICAgICAgfVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQVVQnLFxuICAgICAgJy9wdXNoX2F1ZGllbmNlcy86b2JqZWN0SWQnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZVVwZGF0ZShyZXEpO1xuICAgICAgfVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdERUxFVEUnLFxuICAgICAgJy9wdXNoX2F1ZGllbmNlcy86b2JqZWN0SWQnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZURlbGV0ZShyZXEpO1xuICAgICAgfVxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQXVkaWVuY2VzUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/ClassesRouter.js b/lib/Routers/ClassesRouter.js new file mode 100644 index 0000000000..7896ba3bdb --- /dev/null +++ b/lib/Routers/ClassesRouter.js @@ -0,0 +1,217 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.ClassesRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var _rest = _interopRequireDefault(require("../rest")); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const ALLOWED_GET_QUERY_KEYS = ['keys', 'include', 'readPreference', 'includeReadPreference', 'subqueryReadPreference']; + +class ClassesRouter extends _PromiseRouter.default { + className(req) { + return req.params.className; + } + + handleFind(req) { + const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query)); + const options = ClassesRouter.optionsFromBody(body); + + if (req.config.maxLimit && body.limit > req.config.maxLimit) { + // Silently replace the limit on the query with the max configured + options.limit = Number(req.config.maxLimit); + } + + if (body.redirectClassNameForKey) { + options.redirectClassNameForKey = String(body.redirectClassNameForKey); + } + + if (typeof body.where === 'string') { + body.where = JSON.parse(body.where); + } + + return _rest.default.find(req.config, req.auth, this.className(req), body.where, options, req.info.clientSDK).then(response => { + return { + response: response + }; + }); + } // Returns a promise for a {response} object. + + + handleGet(req) { + const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query)); + const options = {}; + + for (const key of Object.keys(body)) { + if (ALLOWED_GET_QUERY_KEYS.indexOf(key) === -1) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'Improper encode of parameter'); + } + } + + if (typeof body.keys === 'string') { + options.keys = body.keys; + } + + if (body.include) { + options.include = String(body.include); + } + + if (typeof body.readPreference === 'string') { + options.readPreference = body.readPreference; + } + + if (typeof body.includeReadPreference === 'string') { + options.includeReadPreference = body.includeReadPreference; + } + + if (typeof body.subqueryReadPreference === 'string') { + options.subqueryReadPreference = body.subqueryReadPreference; + } + + return _rest.default.get(req.config, req.auth, this.className(req), req.params.objectId, options, req.info.clientSDK).then(response => { + if (!response.results || response.results.length == 0) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + + if (this.className(req) === '_User') { + delete response.results[0].sessionToken; + const user = response.results[0]; + + if (req.auth.user && user.objectId == req.auth.user.id) { + // Force the session token + response.results[0].sessionToken = req.info.sessionToken; + } + } + + return { + response: response.results[0] + }; + }); + } + + handleCreate(req) { + return _rest.default.create(req.config, req.auth, this.className(req), req.body, req.info.clientSDK); + } + + handleUpdate(req) { + const where = { + objectId: req.params.objectId + }; + return _rest.default.update(req.config, req.auth, this.className(req), where, req.body, req.info.clientSDK); + } + + handleDelete(req) { + return _rest.default.del(req.config, req.auth, this.className(req), req.params.objectId, req.info.clientSDK).then(() => { + return { + response: {} + }; + }); + } + + static JSONFromQuery(query) { + const json = {}; + + for (const [key, value] of _lodash.default.entries(query)) { + try { + json[key] = JSON.parse(value); + } catch (e) { + json[key] = value; + } + } + + return json; + } + + static optionsFromBody(body) { + const allowConstraints = ['skip', 'limit', 'order', 'count', 'keys', 'excludeKeys', 'include', 'includeAll', 'redirectClassNameForKey', 'where', 'readPreference', 'includeReadPreference', 'subqueryReadPreference']; + + for (const key of Object.keys(body)) { + if (allowConstraints.indexOf(key) === -1) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Invalid parameter for query: ${key}`); + } + } + + const options = {}; + + if (body.skip) { + options.skip = Number(body.skip); + } + + if (body.limit || body.limit === 0) { + options.limit = Number(body.limit); + } else { + options.limit = Number(100); + } + + if (body.order) { + options.order = String(body.order); + } + + if (body.count) { + options.count = true; + } + + if (typeof body.keys == 'string') { + options.keys = body.keys; + } + + if (typeof body.excludeKeys == 'string') { + options.excludeKeys = body.excludeKeys; + } + + if (body.include) { + options.include = String(body.include); + } + + if (body.includeAll) { + options.includeAll = true; + } + + if (typeof body.readPreference === 'string') { + options.readPreference = body.readPreference; + } + + if (typeof body.includeReadPreference === 'string') { + options.includeReadPreference = body.includeReadPreference; + } + + if (typeof body.subqueryReadPreference === 'string') { + options.subqueryReadPreference = body.subqueryReadPreference; + } + + return options; + } + + mountRoutes() { + this.route('GET', '/classes/:className', req => { + return this.handleFind(req); + }); + this.route('GET', '/classes/:className/:objectId', req => { + return this.handleGet(req); + }); + this.route('POST', '/classes/:className', req => { + return this.handleCreate(req); + }); + this.route('PUT', '/classes/:className/:objectId', req => { + return this.handleUpdate(req); + }); + this.route('DELETE', '/classes/:className/:objectId', req => { + return this.handleDelete(req); + }); + } + +} + +exports.ClassesRouter = ClassesRouter; +var _default = ClassesRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0NsYXNzZXNSb3V0ZXIuanMiXSwibmFtZXMiOlsiQUxMT1dFRF9HRVRfUVVFUllfS0VZUyIsIkNsYXNzZXNSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwiY2xhc3NOYW1lIiwicmVxIiwicGFyYW1zIiwiaGFuZGxlRmluZCIsImJvZHkiLCJPYmplY3QiLCJhc3NpZ24iLCJKU09ORnJvbVF1ZXJ5IiwicXVlcnkiLCJvcHRpb25zIiwib3B0aW9uc0Zyb21Cb2R5IiwiY29uZmlnIiwibWF4TGltaXQiLCJsaW1pdCIsIk51bWJlciIsInJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5IiwiU3RyaW5nIiwid2hlcmUiLCJKU09OIiwicGFyc2UiLCJyZXN0IiwiZmluZCIsImF1dGgiLCJpbmZvIiwiY2xpZW50U0RLIiwidGhlbiIsInJlc3BvbnNlIiwiaGFuZGxlR2V0Iiwia2V5Iiwia2V5cyIsImluZGV4T2YiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9RVUVSWSIsImluY2x1ZGUiLCJyZWFkUHJlZmVyZW5jZSIsImluY2x1ZGVSZWFkUHJlZmVyZW5jZSIsInN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UiLCJnZXQiLCJvYmplY3RJZCIsInJlc3VsdHMiLCJsZW5ndGgiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwic2Vzc2lvblRva2VuIiwidXNlciIsImlkIiwiaGFuZGxlQ3JlYXRlIiwiY3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwidXBkYXRlIiwiaGFuZGxlRGVsZXRlIiwiZGVsIiwianNvbiIsInZhbHVlIiwiXyIsImVudHJpZXMiLCJlIiwiYWxsb3dDb25zdHJhaW50cyIsInNraXAiLCJvcmRlciIsImNvdW50IiwiZXhjbHVkZUtleXMiLCJpbmNsdWRlQWxsIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEsc0JBQXNCLEdBQUcsQ0FDN0IsTUFENkIsRUFF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QUFPLEtBQUsrQyxZQUFMLENBQWtCL0MsR0FBbEIsQ0FBUDtBQUNELEtBRkQ7QUFHQSxTQUFLK0QsS0FBTCxDQUFXLFFBQVgsRUFBcUIsK0JBQXJCLEVBQXNEL0QsR0FBRyxJQUFJO0FBQzNELGFBQU8sS0FBS2lELFlBQUwsQ0FBa0JqRCxHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdEOztBQW5POEM7OztlQXNPbENILGEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCByZXN0IGZyb20gJy4uL3Jlc3QnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcblxuY29uc3QgQUxMT1dFRF9HRVRfUVVFUllfS0VZUyA9IFtcbiAgJ2tleXMnLFxuICAnaW5jbHVkZScsXG4gICdyZWFkUHJlZmVyZW5jZScsXG4gICdpbmNsdWRlUmVhZFByZWZlcmVuY2UnLFxuICAnc3VicXVlcnlSZWFkUHJlZmVyZW5jZScsXG5dO1xuXG5leHBvcnQgY2xhc3MgQ2xhc3Nlc1JvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuICBjbGFzc05hbWUocmVxKSB7XG4gICAgcmV0dXJuIHJlcS5wYXJhbXMuY2xhc3NOYW1lO1xuICB9XG5cbiAgaGFuZGxlRmluZChyZXEpIHtcbiAgICBjb25zdCBib2R5ID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHJlcS5ib2R5LFxuICAgICAgQ2xhc3Nlc1JvdXRlci5KU09ORnJvbVF1ZXJ5KHJlcS5xdWVyeSlcbiAgICApO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBDbGFzc2VzUm91dGVyLm9wdGlvbnNGcm9tQm9keShib2R5KTtcbiAgICBpZiAocmVxLmNvbmZpZy5tYXhMaW1pdCAmJiBib2R5LmxpbWl0ID4gcmVxLmNvbmZpZy5tYXhMaW1pdCkge1xuICAgICAgLy8gU2lsZW50bHkgcmVwbGFjZSB0aGUgbGltaXQgb24gdGhlIHF1ZXJ5IHdpdGggdGhlIG1heCBjb25maWd1cmVkXG4gICAgICBvcHRpb25zLmxpbWl0ID0gTnVtYmVyKHJlcS5jb25maWcubWF4TGltaXQpO1xuICAgIH1cbiAgICBpZiAoYm9keS5yZWRpcmVjdENsYXNzTmFtZUZvcktleSkge1xuICAgICAgb3B0aW9ucy5yZWRpcmVjdENsYXNzTmFtZUZvcktleSA9IFN0cmluZyhib2R5LnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5KTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LndoZXJlID09PSAnc3RyaW5nJykge1xuICAgICAgYm9keS53aGVyZSA9IEpTT04ucGFyc2UoYm9keS53aGVyZSk7XG4gICAgfVxuICAgIHJldHVybiByZXN0XG4gICAgICAuZmluZChcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGgsXG4gICAgICAgIHRoaXMuY2xhc3NOYW1lKHJlcSksXG4gICAgICAgIGJvZHkud2hlcmUsXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICAgKVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICByZXR1cm4geyByZXNwb25zZTogcmVzcG9uc2UgfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEge3Jlc3BvbnNlfSBvYmplY3QuXG4gIGhhbmRsZUdldChyZXEpIHtcbiAgICBjb25zdCBib2R5ID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHJlcS5ib2R5LFxuICAgICAgQ2xhc3Nlc1JvdXRlci5KU09ORnJvbVF1ZXJ5KHJlcS5xdWVyeSlcbiAgICApO1xuICAgIGNvbnN0IG9wdGlvbnMgPSB7fTtcblxuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGJvZHkpKSB7XG4gICAgICBpZiAoQUxMT1dFRF9HRVRfUVVFUllfS0VZUy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgICdJbXByb3BlciBlbmNvZGUgb2YgcGFyYW1ldGVyJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlb2YgYm9keS5rZXlzID09PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5rZXlzID0gYm9keS5rZXlzO1xuICAgIH1cbiAgICBpZiAoYm9keS5pbmNsdWRlKSB7XG4gICAgICBvcHRpb25zLmluY2x1ZGUgPSBTdHJpbmcoYm9keS5pbmNsdWRlKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LnJlYWRQcmVmZXJlbmNlID09PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IGJvZHkucmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYm9keS5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZSA9IGJvZHkuaW5jbHVkZVJlYWRQcmVmZXJlbmNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IGJvZHkuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdFxuICAgICAgLmdldChcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGgsXG4gICAgICAgIHRoaXMuY2xhc3NOYW1lKHJlcSksXG4gICAgICAgIHJlcS5wYXJhbXMub2JqZWN0SWQsXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICAgKVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICBpZiAoIXJlc3BvbnNlLnJlc3VsdHMgfHwgcmVzcG9uc2UucmVzdWx0cy5sZW5ndGggPT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmNsYXNzTmFtZShyZXEpID09PSAnX1VzZXInKSB7XG4gICAgICAgICAgZGVsZXRlIHJlc3BvbnNlLnJlc3VsdHNbMF0uc2Vzc2lvblRva2VuO1xuXG4gICAgICAgICAgY29uc3QgdXNlciA9IHJlc3BvbnNlLnJlc3VsdHNbMF07XG5cbiAgICAgICAgICBpZiAocmVxLmF1dGgudXNlciAmJiB1c2VyLm9iamVjdElkID09IHJlcS5hdXRoLnVzZXIuaWQpIHtcbiAgICAgICAgICAgIC8vIEZvcmNlIHRoZSBzZXNzaW9uIHRva2VuXG4gICAgICAgICAgICByZXNwb25zZS5yZXN1bHRzWzBdLnNlc3Npb25Ub2tlbiA9IHJlcS5pbmZvLnNlc3Npb25Ub2tlbjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHJlc3BvbnNlLnJlc3VsdHNbMF0gfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlQ3JlYXRlKHJlcSkge1xuICAgIHJldHVybiByZXN0LmNyZWF0ZShcbiAgICAgIHJlcS5jb25maWcsXG4gICAgICByZXEuYXV0aCxcbiAgICAgIHRoaXMuY2xhc3NOYW1lKHJlcSksXG4gICAgICByZXEuYm9keSxcbiAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICk7XG4gIH1cblxuICBoYW5kbGVVcGRhdGUocmVxKSB7XG4gICAgY29uc3Qgd2hlcmUgPSB7IG9iamVjdElkOiByZXEucGFyYW1zLm9iamVjdElkIH07XG4gICAgcmV0dXJuIHJlc3QudXBkYXRlKFxuICAgICAgcmVxLmNvbmZpZyxcbiAgICAgIHJlcS5hdXRoLFxuICAgICAgdGhpcy5jbGFzc05hbWUocmVxKSxcbiAgICAgIHdoZXJlLFxuICAgICAgcmVxLmJvZHksXG4gICAgICByZXEuaW5mby5jbGllbnRTREtcbiAgICApO1xuICB9XG5cbiAgaGFuZGxlRGVsZXRlKHJlcSkge1xuICAgIHJldHVybiByZXN0XG4gICAgICAuZGVsKFxuICAgICAgICByZXEuY29uZmlnLFxuICAgICAgICByZXEuYXV0aCxcbiAgICAgICAgdGhpcy5jbGFzc05hbWUocmVxKSxcbiAgICAgICAgcmVxLnBhcmFtcy5vYmplY3RJZCxcbiAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgICApXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB7fSB9O1xuICAgICAgfSk7XG4gIH1cblxuICBzdGF0aWMgSlNPTkZyb21RdWVyeShxdWVyeSkge1xuICAgIGNvbnN0IGpzb24gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBfLmVudHJpZXMocXVlcnkpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBqc29uW2tleV0gPSBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAganNvbltrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBqc29uO1xuICB9XG5cbiAgc3RhdGljIG9wdGlvbnNGcm9tQm9keShib2R5KSB7XG4gICAgY29uc3QgYWxsb3dDb25zdHJhaW50cyA9IFtcbiAgICAgICdza2lwJyxcbiAgICAgICdsaW1pdCcsXG4gICAgICAnb3JkZXInLFxuICAgICAgJ2NvdW50JyxcbiAgICAgICdrZXlzJyxcbiAgICAgICdleGNsdWRlS2V5cycsXG4gICAgICAnaW5jbHVkZScsXG4gICAgICAnaW5jbHVkZUFsbCcsXG4gICAgICAncmVkaXJlY3RDbGFzc05hbWVGb3JLZXknLFxuICAgICAgJ3doZXJlJyxcbiAgICAgICdyZWFkUHJlZmVyZW5jZScsXG4gICAgICAnaW5jbHVkZVJlYWRQcmVmZXJlbmNlJyxcbiAgICAgICdzdWJxdWVyeVJlYWRQcmVmZXJlbmNlJyxcbiAgICBdO1xuXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoYm9keSkpIHtcbiAgICAgIGlmIChhbGxvd0NvbnN0cmFpbnRzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgYEludmFsaWQgcGFyYW1ldGVyIGZvciBxdWVyeTogJHtrZXl9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBvcHRpb25zID0ge307XG4gICAgaWYgKGJvZHkuc2tpcCkge1xuICAgICAgb3B0aW9ucy5za2lwID0gTnVtYmVyKGJvZHkuc2tpcCk7XG4gICAgfVxuICAgIGlmIChib2R5LmxpbWl0IHx8IGJvZHkubGltaXQgPT09IDApIHtcbiAgICAgIG9wdGlvbnMubGltaXQgPSBOdW1iZXIoYm9keS5saW1pdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wdGlvbnMubGltaXQgPSBOdW1iZXIoMTAwKTtcbiAgICB9XG4gICAgaWYgKGJvZHkub3JkZXIpIHtcbiAgICAgIG9wdGlvbnMub3JkZXIgPSBTdHJpbmcoYm9keS5vcmRlcik7XG4gICAgfVxuICAgIGlmIChib2R5LmNvdW50KSB7XG4gICAgICBvcHRpb25zLmNvdW50ID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LmtleXMgPT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMua2V5cyA9IGJvZHkua2V5cztcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LmV4Y2x1ZGVLZXlzID09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLmV4Y2x1ZGVLZXlzID0gYm9keS5leGNsdWRlS2V5cztcbiAgICB9XG4gICAgaWYgKGJvZHkuaW5jbHVkZSkge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlID0gU3RyaW5nKGJvZHkuaW5jbHVkZSk7XG4gICAgfVxuICAgIGlmIChib2R5LmluY2x1ZGVBbGwpIHtcbiAgICAgIG9wdGlvbnMuaW5jbHVkZUFsbCA9IHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYm9keS5yZWFkUHJlZmVyZW5jZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSBib2R5LnJlYWRQcmVmZXJlbmNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkuaW5jbHVkZVJlYWRQcmVmZXJlbmNlID09PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPSBib2R5LmluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPSBib2R5LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIHJldHVybiBvcHRpb25zO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRmluZChyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvY2xhc3Nlcy86Y2xhc3NOYW1lLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVHZXQocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlQ3JlYXRlKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUFVUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZVVwZGF0ZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsICcvY2xhc3Nlcy86Y2xhc3NOYW1lLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDbGFzc2VzUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/CloudCodeRouter.js b/lib/Routers/CloudCodeRouter.js new file mode 100644 index 0000000000..836e61b04a --- /dev/null +++ b/lib/Routers/CloudCodeRouter.js @@ -0,0 +1,105 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CloudCodeRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var _node = _interopRequireDefault(require("parse/node")); + +var _rest = _interopRequireDefault(require("../rest")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const triggers = require('../triggers'); + +const middleware = require('../middlewares'); + +function formatJobSchedule(job_schedule) { + if (typeof job_schedule.startAfter === 'undefined') { + job_schedule.startAfter = new Date().toISOString(); + } + + return job_schedule; +} + +function validateJobSchedule(config, job_schedule) { + const jobs = triggers.getJobs(config.applicationId) || {}; + + if (job_schedule.jobName && !jobs[job_schedule.jobName]) { + throw new _node.default.Error(_node.default.Error.INTERNAL_SERVER_ERROR, 'Cannot Schedule a job that is not deployed'); + } +} + +class CloudCodeRouter extends _PromiseRouter.default { + mountRoutes() { + this.route('GET', '/cloud_code/jobs', middleware.promiseEnforceMasterKeyAccess, CloudCodeRouter.getJobs); + this.route('GET', '/cloud_code/jobs/data', middleware.promiseEnforceMasterKeyAccess, CloudCodeRouter.getJobsData); + this.route('POST', '/cloud_code/jobs', middleware.promiseEnforceMasterKeyAccess, CloudCodeRouter.createJob); + this.route('PUT', '/cloud_code/jobs/:objectId', middleware.promiseEnforceMasterKeyAccess, CloudCodeRouter.editJob); + this.route('DELETE', '/cloud_code/jobs/:objectId', middleware.promiseEnforceMasterKeyAccess, CloudCodeRouter.deleteJob); + } + + static getJobs(req) { + return _rest.default.find(req.config, req.auth, '_JobSchedule', {}, {}).then(scheduledJobs => { + return { + response: scheduledJobs.results + }; + }); + } + + static getJobsData(req) { + const config = req.config; + const jobs = triggers.getJobs(config.applicationId) || {}; + return _rest.default.find(req.config, req.auth, '_JobSchedule', {}, {}).then(scheduledJobs => { + return { + response: { + in_use: scheduledJobs.results.map(job => job.jobName), + jobs: Object.keys(jobs) + } + }; + }); + } + + static createJob(req) { + const { + job_schedule + } = req.body; + validateJobSchedule(req.config, job_schedule); + return _rest.default.create(req.config, req.auth, '_JobSchedule', formatJobSchedule(job_schedule), req.client); + } + + static editJob(req) { + const { + objectId + } = req.params; + const { + job_schedule + } = req.body; + validateJobSchedule(req.config, job_schedule); + return _rest.default.update(req.config, req.auth, '_JobSchedule', { + objectId + }, formatJobSchedule(job_schedule)).then(response => { + return { + response + }; + }); + } + + static deleteJob(req) { + const { + objectId + } = req.params; + return _rest.default.del(req.config, req.auth, '_JobSchedule', objectId).then(response => { + return { + response + }; + }); + } + +} + +exports.CloudCodeRouter = CloudCodeRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0Nsb3VkQ29kZVJvdXRlci5qcyJdLCJuYW1lcyI6WyJ0cmlnZ2VycyIsInJlcXVpcmUiLCJtaWRkbGV3YXJlIiwiZm9ybWF0Sm9iU2NoZWR1bGUiLCJqb2Jfc2NoZWR1bGUiLCJzdGFydEFmdGVyIiwiRGF0ZSIsInRvSVNPU3RyaW5nIiwidmFsaWRhdGVKb2JTY2hlZHVsZSIsImNvbmZpZyIsImpvYnMiLCJnZXRKb2JzIiwiYXBwbGljYXRpb25JZCIsImpvYk5hbWUiLCJQYXJzZSIsIkVycm9yIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiQ2xvdWRDb2RlUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsIm1vdW50Um91dGVzIiwicm91dGUiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsImdldEpvYnNEYXRhIiwiY3JlYXRlSm9iIiwiZWRpdEpvYiIsImRlbGV0ZUpvYiIsInJlcSIsInJlc3QiLCJmaW5kIiwiYXV0aCIsInRoZW4iLCJzY2hlZHVsZWRKb2JzIiwicmVzcG9uc2UiLCJyZXN1bHRzIiwiaW5fdXNlIiwibWFwIiwiam9iIiwiT2JqZWN0Iiwia2V5cyIsImJvZHkiLCJjcmVhdGUiLCJjbGllbnQiLCJvYmplY3RJZCIsInBhcmFtcyIsInVwZGF0ZSIsImRlbCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOzs7O0FBQ0EsTUFBTUEsUUFBUSxHQUFHQyxPQUFPLENBQUMsYUFBRCxDQUF4Qjs7QUFDQSxNQUFNQyxVQUFVLEdBQUdELE9BQU8sQ0FBQyxnQkFBRCxDQUExQjs7QUFFQSxTQUFTRSxpQkFBVCxDQUEyQkMsWUFBM0IsRUFBeUM7QUFDdkMsTUFBSSxPQUFPQSxZQUFZLENBQUNDLFVBQXBCLEtBQW1DLFdBQXZDLEVBQW9EO0FBQ2xERCxJQUFBQSxZQUFZLENBQUNDLFVBQWIsR0FBMEIsSUFBSUMsSUFBSixHQUFXQyxXQUFYLEVBQTFCO0FBQ0Q7O0FBQ0QsU0FBT0gsWUFBUDtBQUNE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QyxDQUFQO0FBT0Q7O0FBRUQsU0FBT2pCLE9BQVAsQ0FBZUUsR0FBZixFQUFvQjtBQUNsQixVQUFNO0FBQUVnQixNQUFBQTtBQUFGLFFBQWVoQixHQUFHLENBQUNpQixNQUF6QjtBQUNBLFVBQU07QUFBRXZDLE1BQUFBO0FBQUYsUUFBbUJzQixHQUFHLENBQUNhLElBQTdCO0FBQ0EvQixJQUFBQSxtQkFBbUIsQ0FBQ2tCLEdBQUcsQ0FBQ2pCLE1BQUwsRUFBYUwsWUFBYixDQUFuQjtBQUNBLFdBQU91QixjQUNKaUIsTUFESSxDQUVIbEIsR0FBRyxDQUFDakIsTUFGRCxFQUdIaUIsR0FBRyxDQUFDRyxJQUhELEVBSUgsY0FKRyxFQUtIO0FBQUVhLE1BQUFBO0FBQUYsS0FMRyxFQU1IdkMsaUJBQWlCLENBQUNDLFlBQUQsQ0FOZCxFQVFKMEIsSUFSSSxDQVFDRSxRQUFRLElBQUk7QUFDaEIsYUFBTztBQUNMQSxRQUFBQTtBQURLLE9BQVA7QUFHRCxLQVpJLENBQVA7QUFhRDs7QUFFRCxTQUFPUCxTQUFQLENBQWlCQyxHQUFqQixFQUFzQjtBQUNwQixVQUFNO0FBQUVnQixNQUFBQTtBQUFGLFFBQWVoQixHQUFHLENBQUNpQixNQUF6QjtBQUNBLFdBQU9oQixjQUNKa0IsR0FESSxDQUNBbkIsR0FBRyxDQUFDakIsTUFESixFQUNZaUIsR0FBRyxDQUFDRyxJQURoQixFQUNzQixjQUR0QixFQUNzQ2EsUUFEdEMsRUFFSlosSUFGSSxDQUVDRSxRQUFRLElBQUk7QUFDaEIsYUFBTztBQUNMQSxRQUFBQTtBQURLLE9BQVA7QUFHRCxLQU5JLENBQVA7QUFPRDs7QUFuR2dEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmNvbnN0IHRyaWdnZXJzID0gcmVxdWlyZSgnLi4vdHJpZ2dlcnMnKTtcbmNvbnN0IG1pZGRsZXdhcmUgPSByZXF1aXJlKCcuLi9taWRkbGV3YXJlcycpO1xuXG5mdW5jdGlvbiBmb3JtYXRKb2JTY2hlZHVsZShqb2Jfc2NoZWR1bGUpIHtcbiAgaWYgKHR5cGVvZiBqb2Jfc2NoZWR1bGUuc3RhcnRBZnRlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBqb2Jfc2NoZWR1bGUuc3RhcnRBZnRlciA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgfVxuICByZXR1cm4gam9iX3NjaGVkdWxlO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUpvYlNjaGVkdWxlKGNvbmZpZywgam9iX3NjaGVkdWxlKSB7XG4gIGNvbnN0IGpvYnMgPSB0cmlnZ2Vycy5nZXRKb2JzKGNvbmZpZy5hcHBsaWNhdGlvbklkKSB8fCB7fTtcbiAgaWYgKGpvYl9zY2hlZHVsZS5qb2JOYW1lICYmICFqb2JzW2pvYl9zY2hlZHVsZS5qb2JOYW1lXSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICdDYW5ub3QgU2NoZWR1bGUgYSBqb2IgdGhhdCBpcyBub3QgZGVwbG95ZWQnXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQ2xvdWRDb2RlUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnR0VUJyxcbiAgICAgICcvY2xvdWRfY29kZS9qb2JzJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICBDbG91ZENvZGVSb3V0ZXIuZ2V0Sm9ic1xuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9jbG91ZF9jb2RlL2pvYnMvZGF0YScsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgQ2xvdWRDb2RlUm91dGVyLmdldEpvYnNEYXRhXG4gICAgKTtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ1BPU1QnLFxuICAgICAgJy9jbG91ZF9jb2RlL2pvYnMnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIENsb3VkQ29kZVJvdXRlci5jcmVhdGVKb2JcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUFVUJyxcbiAgICAgICcvY2xvdWRfY29kZS9qb2JzLzpvYmplY3RJZCcsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgQ2xvdWRDb2RlUm91dGVyLmVkaXRKb2JcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnREVMRVRFJyxcbiAgICAgICcvY2xvdWRfY29kZS9qb2JzLzpvYmplY3RJZCcsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgQ2xvdWRDb2RlUm91dGVyLmRlbGV0ZUpvYlxuICAgICk7XG4gIH1cblxuICBzdGF0aWMgZ2V0Sm9icyhyZXEpIHtcbiAgICByZXR1cm4gcmVzdFxuICAgICAgLmZpbmQocmVxLmNvbmZpZywgcmVxLmF1dGgsICdfSm9iU2NoZWR1bGUnLCB7fSwge30pXG4gICAgICAudGhlbihzY2hlZHVsZWRKb2JzID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICByZXNwb25zZTogc2NoZWR1bGVkSm9icy5yZXN1bHRzLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0Sm9ic0RhdGEocmVxKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcbiAgICBjb25zdCBqb2JzID0gdHJpZ2dlcnMuZ2V0Sm9icyhjb25maWcuYXBwbGljYXRpb25JZCkgfHwge307XG4gICAgcmV0dXJuIHJlc3RcbiAgICAgIC5maW5kKHJlcS5jb25maWcsIHJlcS5hdXRoLCAnX0pvYlNjaGVkdWxlJywge30sIHt9KVxuICAgICAgLnRoZW4oc2NoZWR1bGVkSm9icyA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVzcG9uc2U6IHtcbiAgICAgICAgICAgIGluX3VzZTogc2NoZWR1bGVkSm9icy5yZXN1bHRzLm1hcChqb2IgPT4gam9iLmpvYk5hbWUpLFxuICAgICAgICAgICAgam9iczogT2JqZWN0LmtleXMoam9icyksXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZUpvYihyZXEpIHtcbiAgICBjb25zdCB7IGpvYl9zY2hlZHVsZSB9ID0gcmVxLmJvZHk7XG4gICAgdmFsaWRhdGVKb2JTY2hlZHVsZShyZXEuY29uZmlnLCBqb2Jfc2NoZWR1bGUpO1xuICAgIHJldHVybiByZXN0LmNyZWF0ZShcbiAgICAgIHJlcS5jb25maWcsXG4gICAgICByZXEuYXV0aCxcbiAgICAgICdfSm9iU2NoZWR1bGUnLFxuICAgICAgZm9ybWF0Sm9iU2NoZWR1bGUoam9iX3NjaGVkdWxlKSxcbiAgICAgIHJlcS5jbGllbnRcbiAgICApO1xuICB9XG5cbiAgc3RhdGljIGVkaXRKb2IocmVxKSB7XG4gICAgY29uc3QgeyBvYmplY3RJZCB9ID0gcmVxLnBhcmFtcztcbiAgICBjb25zdCB7IGpvYl9zY2hlZHVsZSB9ID0gcmVxLmJvZHk7XG4gICAgdmFsaWRhdGVKb2JTY2hlZHVsZShyZXEuY29uZmlnLCBqb2Jfc2NoZWR1bGUpO1xuICAgIHJldHVybiByZXN0XG4gICAgICAudXBkYXRlKFxuICAgICAgICByZXEuY29uZmlnLFxuICAgICAgICByZXEuYXV0aCxcbiAgICAgICAgJ19Kb2JTY2hlZHVsZScsXG4gICAgICAgIHsgb2JqZWN0SWQgfSxcbiAgICAgICAgZm9ybWF0Sm9iU2NoZWR1bGUoam9iX3NjaGVkdWxlKVxuICAgICAgKVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHJlc3BvbnNlLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZGVsZXRlSm9iKHJlcSkge1xuICAgIGNvbnN0IHsgb2JqZWN0SWQgfSA9IHJlcS5wYXJhbXM7XG4gICAgcmV0dXJuIHJlc3RcbiAgICAgIC5kZWwocmVxLmNvbmZpZywgcmVxLmF1dGgsICdfSm9iU2NoZWR1bGUnLCBvYmplY3RJZClcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICByZXNwb25zZSxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/FeaturesRouter.js b/lib/Routers/FeaturesRouter.js new file mode 100644 index 0000000000..e10b052405 --- /dev/null +++ b/lib/Routers/FeaturesRouter.js @@ -0,0 +1,79 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FeaturesRouter = void 0; + +var _package = require("../../package.json"); + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class FeaturesRouter extends _PromiseRouter.default { + mountRoutes() { + this.route('GET', '/serverInfo', middleware.promiseEnforceMasterKeyAccess, req => { + const { + config + } = req; + const features = { + globalConfig: { + create: true, + read: true, + update: true, + delete: true + }, + hooks: { + create: true, + read: true, + update: true, + delete: true + }, + cloudCode: { + jobs: true + }, + logs: { + level: true, + size: true, + order: true, + until: true, + from: true + }, + push: { + immediatePush: config.hasPushSupport, + scheduledPush: config.hasPushScheduledSupport, + storedPushData: config.hasPushSupport, + pushAudiences: true, + localization: true + }, + schemas: { + addField: true, + removeField: true, + addClass: true, + removeClass: true, + clearAllDataFromClass: true, + exportClass: false, + editClassLevelPermissions: true, + editPointerPermissions: true + } + }; + return { + response: { + features: features, + parseServerVersion: _package.version + } + }; + }); + } + +} + +exports.FeaturesRouter = FeaturesRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZlYXR1cmVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIkZlYXR1cmVzUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsIm1vdW50Um91dGVzIiwicm91dGUiLCJtaWRkbGV3YXJlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJyZXEiLCJjb25maWciLCJmZWF0dXJlcyIsImdsb2JhbENvbmZpZyIsImNyZWF0ZSIsInJlYWQiLCJ1cGRhdGUiLCJkZWxldGUiLCJob29rcyIsImNsb3VkQ29kZSIsImpvYnMiLCJsb2dzIiwibGV2ZWwiLCJzaXplIiwib3JkZXIiLCJ1bnRpbCIsImZyb20iLCJwdXNoIiwiaW1tZWRpYXRlUHVzaCIsImhhc1B1c2hTdXBwb3J0Iiwic2NoZWR1bGVkUHVzaCIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0Iiwic3RvcmVkUHVzaERhdGEiLCJwdXNoQXVkaWVuY2VzIiwibG9jYWxpemF0aW9uIiwic2NoZW1hcyIsImFkZEZpZWxkIiwicmVtb3ZlRmllbGQiLCJhZGRDbGFzcyIsInJlbW92ZUNsYXNzIiwiY2xlYXJBbGxEYXRhRnJvbUNsYXNzIiwiZXhwb3J0Q2xhc3MiLCJlZGl0Q2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiZWRpdFBvaW50ZXJQZXJtaXNzaW9ucyIsInJlc3BvbnNlIiwicGFyc2VTZXJ2ZXJWZXJzaW9uIiwidmVyc2lvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVPLE1BQU1BLGNBQU4sU0FBNkJDLHNCQUE3QixDQUEyQztBQUNoREMsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxDQUNFLEtBREYsRUFFRSxhQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRUMsR0FBRyxJQUFJO0FBQ0wsWUFBTTtBQUFFQyxRQUFBQTtBQUFGLFVBQWFELEdBQW5CO0FBQ0EsWUFBTUUsUUFBUSxHQUFHO0FBQ2ZDLFFBQUFBLFlBQVksRUFBRTtBQUNaQyxVQUFBQSxNQUFNLEVBQUUsSUFESTtBQUVaQyxVQUFBQSxJQUFJLEVBQUUsSUFGTTtBQUdaQyxVQUFBQSxNQUFNLEVBQUUsSUFISTtBQUlaQyxVQUFBQSxNQUFNLEVBQUU7QUFKSSxTQURDO0FBT2ZDLFFBQUFBLEtBQUssRUFBRTtBQUNMSixVQUFBQSxNQUFNLEVBQUUsSUFESDtBQUVMQyxVQUFBQSxJQUFJLEVBQUUsSUFGRDtBQUdMQyxVQUFBQSxNQUFNLEVBQUUsSUFISDtBQUlMQyxVQUFBQSxNQUFNLEVBQUU7QUFKSCxTQVBRO0FBYWZFLFFBQUFBLFNBQVMsRUFBRTtBQUNUQyxVQUFBQSxJQUFJLEVBQUU7QUFERyxTQWJJO0FBZ0JmQyxRQUFBQSxJQUFJLEVBQUU7QUFDSkMsVUFBQUEsS0FBSyxFQUFFLElBREg7QUFFSkMsVUFBQUEsSUFBSSxFQUFFLElBRkY7QUFHSkMsVUFBQUEsS0FBSyxFQUFFLElBSEg7QUFJSkMsVUFBQUEsS0FBSyxFQUFFLElBSkg7QUFLSkMsVUFBQUEsSUFBSSxFQUFFO0FBTEYsU0FoQlM7QUF1QmZDLFFBQUFBLElBQUksRUFBRTtBQUNKQyxVQUFBQSxhQUFhLEVBQUVqQixNQUFNLENBQUNrQixjQURsQjtBQUVKQyxVQUFBQSxhQUFhLEVBQUVuQixNQUFNLENBQUNvQix1QkFGbEI7QUFHSkMsVUFBQUEsY0FBYyxFQUFFckIsTUFBTSxDQUFDa0IsY0FIbkI7QUFJSkksVUFBQUEsYUFBYSxFQUFFLElBSlg7QUFLSkMsVUFBQUEsWUFBWSxFQUFFO0FBTFYsU0F2QlM7QUE4QmZDLFFBQUFBLE9BQU8sRUFBRTtBQUNQQyxVQUFBQSxRQUFRLEVBQUUsSUFESDtBQUVQQyxVQUFBQSxXQUFXLEVBQUUsSUFGTjtBQUdQQyxVQUFBQSxRQUFRLEVBQUUsSUFISDtBQUlQQyxVQUFBQSxXQUFXLEVBQUUsSUFKTjtBQUtQQyxVQUFBQSxxQkFBcUIsRUFBRSxJQUxoQjtBQU1QQyxVQUFBQSxXQUFXLEVBQUUsS0FOTjtBQU9QQyxVQUFBQSx5QkFBeUIsRUFBRSxJQVBwQjtBQVFQQyxVQUFBQSxzQkFBc0IsRUFBRTtBQVJqQjtBQTlCTSxPQUFqQjtBQTBDQSxhQUFPO0FBQ0xDLFFBQUFBLFFBQVEsRUFBRTtBQUNSaEMsVUFBQUEsUUFBUSxFQUFFQSxRQURGO0FBRVJpQyxVQUFBQSxrQkFBa0IsRUFBRUM7QUFGWjtBQURMLE9BQVA7QUFNRCxLQXRESDtBQXdERDs7QUExRCtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4uLy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmUgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuXG5leHBvcnQgY2xhc3MgRmVhdHVyZXNSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9zZXJ2ZXJJbmZvJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICByZXEgPT4ge1xuICAgICAgICBjb25zdCB7IGNvbmZpZyB9ID0gcmVxO1xuICAgICAgICBjb25zdCBmZWF0dXJlcyA9IHtcbiAgICAgICAgICBnbG9iYWxDb25maWc6IHtcbiAgICAgICAgICAgIGNyZWF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIHJlYWQ6IHRydWUsXG4gICAgICAgICAgICB1cGRhdGU6IHRydWUsXG4gICAgICAgICAgICBkZWxldGU6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBob29rczoge1xuICAgICAgICAgICAgY3JlYXRlOiB0cnVlLFxuICAgICAgICAgICAgcmVhZDogdHJ1ZSxcbiAgICAgICAgICAgIHVwZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGRlbGV0ZTogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNsb3VkQ29kZToge1xuICAgICAgICAgICAgam9iczogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGxvZ3M6IHtcbiAgICAgICAgICAgIGxldmVsOiB0cnVlLFxuICAgICAgICAgICAgc2l6ZTogdHJ1ZSxcbiAgICAgICAgICAgIG9yZGVyOiB0cnVlLFxuICAgICAgICAgICAgdW50aWw6IHRydWUsXG4gICAgICAgICAgICBmcm9tOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcHVzaDoge1xuICAgICAgICAgICAgaW1tZWRpYXRlUHVzaDogY29uZmlnLmhhc1B1c2hTdXBwb3J0LFxuICAgICAgICAgICAgc2NoZWR1bGVkUHVzaDogY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0LFxuICAgICAgICAgICAgc3RvcmVkUHVzaERhdGE6IGNvbmZpZy5oYXNQdXNoU3VwcG9ydCxcbiAgICAgICAgICAgIHB1c2hBdWRpZW5jZXM6IHRydWUsXG4gICAgICAgICAgICBsb2NhbGl6YXRpb246IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBzY2hlbWFzOiB7XG4gICAgICAgICAgICBhZGRGaWVsZDogdHJ1ZSxcbiAgICAgICAgICAgIHJlbW92ZUZpZWxkOiB0cnVlLFxuICAgICAgICAgICAgYWRkQ2xhc3M6IHRydWUsXG4gICAgICAgICAgICByZW1vdmVDbGFzczogdHJ1ZSxcbiAgICAgICAgICAgIGNsZWFyQWxsRGF0YUZyb21DbGFzczogdHJ1ZSxcbiAgICAgICAgICAgIGV4cG9ydENsYXNzOiBmYWxzZSxcbiAgICAgICAgICAgIGVkaXRDbGFzc0xldmVsUGVybWlzc2lvbnM6IHRydWUsXG4gICAgICAgICAgICBlZGl0UG9pbnRlclBlcm1pc3Npb25zOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICByZXNwb25zZToge1xuICAgICAgICAgICAgZmVhdHVyZXM6IGZlYXR1cmVzLFxuICAgICAgICAgICAgcGFyc2VTZXJ2ZXJWZXJzaW9uOiB2ZXJzaW9uLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgKTtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/lib/Routers/FilesRouter.js b/lib/Routers/FilesRouter.js new file mode 100644 index 0000000000..e0f62ca598 --- /dev/null +++ b/lib/Routers/FilesRouter.js @@ -0,0 +1,124 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FilesRouter = void 0; + +var _express = _interopRequireDefault(require("express")); + +var _bodyParser = _interopRequireDefault(require("body-parser")); + +var Middlewares = _interopRequireWildcard(require("../middlewares")); + +var _node = _interopRequireDefault(require("parse/node")); + +var _Config = _interopRequireDefault(require("../Config")); + +var _mime = _interopRequireDefault(require("mime")); + +var _logger = _interopRequireDefault(require("../logger")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class FilesRouter { + expressRouter({ + maxUploadSize = '20Mb' + } = {}) { + var router = _express.default.Router(); + + router.get('/files/:appId/:filename', this.getHandler); + router.post('/files', function (req, res, next) { + next(new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Filename not provided.')); + }); + router.post('/files/:filename', _bodyParser.default.raw({ + type: () => { + return true; + }, + limit: maxUploadSize + }), // Allow uploads without Content-Type, or with any Content-Type. + Middlewares.handleParseHeaders, this.createHandler); + router.delete('/files/:filename', Middlewares.handleParseHeaders, Middlewares.enforceMasterKeyAccess, this.deleteHandler); + return router; + } + + getHandler(req, res) { + const config = _Config.default.get(req.params.appId); + + const filesController = config.filesController; + const filename = req.params.filename; + + const contentType = _mime.default.getType(filename); + + if (isFileStreamable(req, filesController)) { + filesController.handleFileStream(config, filename, req, res, contentType).catch(() => { + res.status(404); + res.set('Content-Type', 'text/plain'); + res.end('File not found.'); + }); + } else { + filesController.getFileData(config, filename).then(data => { + res.status(200); + res.set('Content-Type', contentType); + res.set('Content-Length', data.length); + res.end(data); + }).catch(() => { + res.status(404); + res.set('Content-Type', 'text/plain'); + res.end('File not found.'); + }); + } + } + + createHandler(req, res, next) { + const config = req.config; + const filesController = config.filesController; + const filename = req.params.filename; + const contentType = req.get('Content-type'); + + if (!req.body || !req.body.length) { + next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'Invalid file upload.')); + return; + } + + const error = filesController.validateFilename(filename); + + if (error) { + next(error); + return; + } + + filesController.createFile(config, filename, req.body, contentType).then(result => { + res.status(201); + res.set('Location', result.url); + res.json(result); + }).catch(e => { + _logger.default.error('Error creating a file: ', e); + + next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, `Could not store file: ${filename}.`)); + }); + } + + deleteHandler(req, res, next) { + const filesController = req.config.filesController; + filesController.deleteFile(req.config, req.params.filename).then(() => { + res.status(200); // TODO: return useful JSON here? + + res.end(); + }).catch(() => { + next(new _node.default.Error(_node.default.Error.FILE_DELETE_ERROR, 'Could not delete file.')); + }); + } + +} + +exports.FilesRouter = FilesRouter; + +function isFileStreamable(req, filesController) { + return req.get('Range') && typeof filesController.adapter.handleFileStream === 'function'; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZpbGVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIkZpbGVzUm91dGVyIiwiZXhwcmVzc1JvdXRlciIsIm1heFVwbG9hZFNpemUiLCJyb3V0ZXIiLCJleHByZXNzIiwiUm91dGVyIiwiZ2V0IiwiZ2V0SGFuZGxlciIsInBvc3QiLCJyZXEiLCJyZXMiLCJuZXh0IiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfRklMRV9OQU1FIiwiQm9keVBhcnNlciIsInJhdyIsInR5cGUiLCJsaW1pdCIsIk1pZGRsZXdhcmVzIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwiY3JlYXRlSGFuZGxlciIsImRlbGV0ZSIsImVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJkZWxldGVIYW5kbGVyIiwiY29uZmlnIiwiQ29uZmlnIiwicGFyYW1zIiwiYXBwSWQiLCJmaWxlc0NvbnRyb2xsZXIiLCJmaWxlbmFtZSIsImNvbnRlbnRUeXBlIiwibWltZSIsImdldFR5cGUiLCJpc0ZpbGVTdHJlYW1hYmxlIiwiaGFuZGxlRmlsZVN0cmVhbSIsImNhdGNoIiwic3RhdHVzIiwic2V0IiwiZW5kIiwiZ2V0RmlsZURhdGEiLCJ0aGVuIiwiZGF0YSIsImxlbmd0aCIsImJvZHkiLCJGSUxFX1NBVkVfRVJST1IiLCJlcnJvciIsInZhbGlkYXRlRmlsZW5hbWUiLCJjcmVhdGVGaWxlIiwicmVzdWx0IiwidXJsIiwianNvbiIsImUiLCJsb2dnZXIiLCJkZWxldGVGaWxlIiwiRklMRV9ERUxFVEVfRVJST1IiLCJhZGFwdGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBRU8sTUFBTUEsV0FBTixDQUFrQjtBQUN2QkMsRUFBQUEsYUFBYSxDQUFDO0FBQUVDLElBQUFBLGFBQWEsR0FBRztBQUFsQixNQUE2QixFQUE5QixFQUFrQztBQUM3QyxRQUFJQyxNQUFNLEdBQUdDLGlCQUFRQyxNQUFSLEVBQWI7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TixFQUFXQyxJQUFYLEVBQWlCO0FBQzVCLFVBQU1rQixlQUFlLEdBQUdwQixHQUFHLENBQUNnQixNQUFKLENBQVdJLGVBQW5DO0FBQ0FBLElBQUFBLGVBQWUsQ0FDWnlCLFVBREgsQ0FDYzdDLEdBQUcsQ0FBQ2dCLE1BRGxCLEVBQzBCaEIsR0FBRyxDQUFDa0IsTUFBSixDQUFXRyxRQURyQyxFQUVHVyxJQUZILENBRVEsTUFBTTtBQUNWL0IsTUFBQUEsR0FBRyxDQUFDMkIsTUFBSixDQUFXLEdBQVgsRUFEVSxDQUVWOztBQUNBM0IsTUFBQUEsR0FBRyxDQUFDNkIsR0FBSjtBQUNELEtBTkgsRUFPR0gsS0FQSCxDQU9TLE1BQU07QUFDWHpCLE1BQUFBLElBQUksQ0FDRixJQUFJQyxjQUFNQyxLQUFWLENBQ0VELGNBQU1DLEtBQU4sQ0FBWTBDLGlCQURkLEVBRUUsd0JBRkYsQ0FERSxDQUFKO0FBTUQsS0FkSDtBQWVEOztBQXBIc0I7Ozs7QUF1SHpCLFNBQVNyQixnQkFBVCxDQUEwQnpCLEdBQTFCLEVBQStCb0IsZUFBL0IsRUFBZ0Q7QUFDOUMsU0FDRXBCLEdBQUcsQ0FBQ0gsR0FBSixDQUFRLE9BQVIsS0FDQSxPQUFPdUIsZUFBZSxDQUFDMkIsT0FBaEIsQ0FBd0JyQixnQkFBL0IsS0FBb0QsVUFGdEQ7QUFJRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IEJvZHlQYXJzZXIgZnJvbSAnYm9keS1wYXJzZXInO1xuaW1wb3J0ICogYXMgTWlkZGxld2FyZXMgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuaW1wb3J0IG1pbWUgZnJvbSAnbWltZSc7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCBjbGFzcyBGaWxlc1JvdXRlciB7XG4gIGV4cHJlc3NSb3V0ZXIoeyBtYXhVcGxvYWRTaXplID0gJzIwTWInIH0gPSB7fSkge1xuICAgIHZhciByb3V0ZXIgPSBleHByZXNzLlJvdXRlcigpO1xuICAgIHJvdXRlci5nZXQoJy9maWxlcy86YXBwSWQvOmZpbGVuYW1lJywgdGhpcy5nZXRIYW5kbGVyKTtcblxuICAgIHJvdXRlci5wb3N0KCcvZmlsZXMnLCBmdW5jdGlvbihyZXEsIHJlcywgbmV4dCkge1xuICAgICAgbmV4dChcbiAgICAgICAgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLCAnRmlsZW5hbWUgbm90IHByb3ZpZGVkLicpXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgcm91dGVyLnBvc3QoXG4gICAgICAnL2ZpbGVzLzpmaWxlbmFtZScsXG4gICAgICBCb2R5UGFyc2VyLnJhdyh7XG4gICAgICAgIHR5cGU6ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgbGltaXQ6IG1heFVwbG9hZFNpemUsXG4gICAgICB9KSwgLy8gQWxsb3cgdXBsb2FkcyB3aXRob3V0IENvbnRlbnQtVHlwZSwgb3Igd2l0aCBhbnkgQ29udGVudC1UeXBlLlxuICAgICAgTWlkZGxld2FyZXMuaGFuZGxlUGFyc2VIZWFkZXJzLFxuICAgICAgdGhpcy5jcmVhdGVIYW5kbGVyXG4gICAgKTtcblxuICAgIHJvdXRlci5kZWxldGUoXG4gICAgICAnL2ZpbGVzLzpmaWxlbmFtZScsXG4gICAgICBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMsXG4gICAgICBNaWRkbGV3YXJlcy5lbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgdGhpcy5kZWxldGVIYW5kbGVyXG4gICAgKTtcbiAgICByZXR1cm4gcm91dGVyO1xuICB9XG5cbiAgZ2V0SGFuZGxlcihyZXEsIHJlcykge1xuICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQocmVxLnBhcmFtcy5hcHBJZCk7XG4gICAgY29uc3QgZmlsZXNDb250cm9sbGVyID0gY29uZmlnLmZpbGVzQ29udHJvbGxlcjtcbiAgICBjb25zdCBmaWxlbmFtZSA9IHJlcS5wYXJhbXMuZmlsZW5hbWU7XG4gICAgY29uc3QgY29udGVudFR5cGUgPSBtaW1lLmdldFR5cGUoZmlsZW5hbWUpO1xuICAgIGlmIChpc0ZpbGVTdHJlYW1hYmxlKHJlcSwgZmlsZXNDb250cm9sbGVyKSkge1xuICAgICAgZmlsZXNDb250cm9sbGVyXG4gICAgICAgIC5oYW5kbGVGaWxlU3RyZWFtKGNvbmZpZywgZmlsZW5hbWUsIHJlcSwgcmVzLCBjb250ZW50VHlwZSlcbiAgICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICByZXMuc3RhdHVzKDQwNCk7XG4gICAgICAgICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgJ3RleHQvcGxhaW4nKTtcbiAgICAgICAgICByZXMuZW5kKCdGaWxlIG5vdCBmb3VuZC4nKTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZpbGVzQ29udHJvbGxlclxuICAgICAgICAuZ2V0RmlsZURhdGEoY29uZmlnLCBmaWxlbmFtZSlcbiAgICAgICAgLnRoZW4oZGF0YSA9PiB7XG4gICAgICAgICAgcmVzLnN0YXR1cygyMDApO1xuICAgICAgICAgIHJlcy5zZXQoJ0NvbnRlbnQtVHlwZScsIGNvbnRlbnRUeXBlKTtcbiAgICAgICAgICByZXMuc2V0KCdDb250ZW50LUxlbmd0aCcsIGRhdGEubGVuZ3RoKTtcbiAgICAgICAgICByZXMuZW5kKGRhdGEpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIHJlcy5zdGF0dXMoNDA0KTtcbiAgICAgICAgICByZXMuc2V0KCdDb250ZW50LVR5cGUnLCAndGV4dC9wbGFpbicpO1xuICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kLicpO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBjcmVhdGVIYW5kbGVyKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcbiAgICBjb25zdCBmaWxlc0NvbnRyb2xsZXIgPSBjb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgIGNvbnN0IGZpbGVuYW1lID0gcmVxLnBhcmFtcy5maWxlbmFtZTtcbiAgICBjb25zdCBjb250ZW50VHlwZSA9IHJlcS5nZXQoJ0NvbnRlbnQtdHlwZScpO1xuXG4gICAgaWYgKCFyZXEuYm9keSB8fCAhcmVxLmJvZHkubGVuZ3RoKSB7XG4gICAgICBuZXh0KFxuICAgICAgICBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLCAnSW52YWxpZCBmaWxlIHVwbG9hZC4nKVxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBlcnJvciA9IGZpbGVzQ29udHJvbGxlci52YWxpZGF0ZUZpbGVuYW1lKGZpbGVuYW1lKTtcbiAgICBpZiAoZXJyb3IpIHtcbiAgICAgIG5leHQoZXJyb3IpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZpbGVzQ29udHJvbGxlclxuICAgICAgLmNyZWF0ZUZpbGUoY29uZmlnLCBmaWxlbmFtZSwgcmVxLmJvZHksIGNvbnRlbnRUeXBlKVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgcmVzLnN0YXR1cygyMDEpO1xuICAgICAgICByZXMuc2V0KCdMb2NhdGlvbicsIHJlc3VsdC51cmwpO1xuICAgICAgICByZXMuanNvbihyZXN1bHQpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlID0+IHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBjcmVhdGluZyBhIGZpbGU6ICcsIGUpO1xuICAgICAgICBuZXh0KFxuICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLkZJTEVfU0FWRV9FUlJPUixcbiAgICAgICAgICAgIGBDb3VsZCBub3Qgc3RvcmUgZmlsZTogJHtmaWxlbmFtZX0uYFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgZGVsZXRlSGFuZGxlcihyZXEsIHJlcywgbmV4dCkge1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IHJlcS5jb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgIGZpbGVzQ29udHJvbGxlclxuICAgICAgLmRlbGV0ZUZpbGUocmVxLmNvbmZpZywgcmVxLnBhcmFtcy5maWxlbmFtZSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmVzLnN0YXR1cygyMDApO1xuICAgICAgICAvLyBUT0RPOiByZXR1cm4gdXNlZnVsIEpTT04gaGVyZT9cbiAgICAgICAgcmVzLmVuZCgpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgIG5leHQoXG4gICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRklMRV9ERUxFVEVfRVJST1IsXG4gICAgICAgICAgICAnQ291bGQgbm90IGRlbGV0ZSBmaWxlLidcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0ZpbGVTdHJlYW1hYmxlKHJlcSwgZmlsZXNDb250cm9sbGVyKSB7XG4gIHJldHVybiAoXG4gICAgcmVxLmdldCgnUmFuZ2UnKSAmJlxuICAgIHR5cGVvZiBmaWxlc0NvbnRyb2xsZXIuYWRhcHRlci5oYW5kbGVGaWxlU3RyZWFtID09PSAnZnVuY3Rpb24nXG4gICk7XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/FunctionsRouter.js b/lib/Routers/FunctionsRouter.js new file mode 100644 index 0000000000..8d8fb46673 --- /dev/null +++ b/lib/Routers/FunctionsRouter.js @@ -0,0 +1,206 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FunctionsRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var _middlewares = require("../middlewares"); + +var _StatusHandler = require("../StatusHandler"); + +var _lodash = _interopRequireDefault(require("lodash")); + +var _logger = require("../logger"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// FunctionsRouter.js +var Parse = require('parse/node').Parse, + triggers = require('../triggers'); + +function parseObject(obj) { + if (Array.isArray(obj)) { + return obj.map(item => { + return parseObject(item); + }); + } else if (obj && obj.__type == 'Date') { + return Object.assign(new Date(obj.iso), obj); + } else if (obj && obj.__type == 'File') { + return Parse.File.fromJSON(obj); + } else if (obj && typeof obj === 'object') { + return parseParams(obj); + } else { + return obj; + } +} + +function parseParams(params) { + return _lodash.default.mapValues(params, parseObject); +} + +class FunctionsRouter extends _PromiseRouter.default { + mountRoutes() { + this.route('POST', '/functions/:functionName', FunctionsRouter.handleCloudFunction); + this.route('POST', '/jobs/:jobName', _middlewares.promiseEnforceMasterKeyAccess, function (req) { + return FunctionsRouter.handleCloudJob(req); + }); + this.route('POST', '/jobs', _middlewares.promiseEnforceMasterKeyAccess, function (req) { + return FunctionsRouter.handleCloudJob(req); + }); + } + + static handleCloudJob(req) { + const jobName = req.params.jobName || req.body.jobName; + const applicationId = req.config.applicationId; + const jobHandler = (0, _StatusHandler.jobStatusHandler)(req.config); + const jobFunction = triggers.getJob(jobName, applicationId); + + if (!jobFunction) { + throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Invalid job.'); + } + + let params = Object.assign({}, req.body, req.query); + params = parseParams(params); + const request = { + params: params, + log: req.config.loggerController, + headers: req.config.headers, + ip: req.config.ip, + jobName, + message: jobHandler.setMessage.bind(jobHandler) + }; + return jobHandler.setRunning(jobName, params).then(jobStatus => { + request.jobId = jobStatus.objectId; // run the function async + + process.nextTick(() => { + Promise.resolve().then(() => { + return jobFunction(request); + }).then(result => { + jobHandler.setSucceeded(result); + }, error => { + jobHandler.setFailed(error); + }); + }); + return { + headers: { + 'X-Parse-Job-Status-Id': jobStatus.objectId + }, + response: {} + }; + }); + } + + static createResponseObject(resolve, reject, message) { + return { + success: function (result) { + resolve({ + response: { + result: Parse._encode(result) + } + }); + }, + error: function (message) { + // parse error, process away + if (message instanceof Parse.Error) { + return reject(message); + } + + const code = Parse.Error.SCRIPT_FAILED; // If it's an error, mark it as a script failed + + if (typeof message === 'string') { + return reject(new Parse.Error(code, message)); + } + + if (message instanceof Error) { + message = message.message; + } + + reject(new Parse.Error(code, message)); + }, + message: message + }; + } + + static handleCloudFunction(req) { + const functionName = req.params.functionName; + const applicationId = req.config.applicationId; + const theFunction = triggers.getFunction(functionName, applicationId); + const theValidator = triggers.getValidator(req.params.functionName, applicationId); + + if (!theFunction) { + throw new Parse.Error(Parse.Error.SCRIPT_FAILED, `Invalid function: "${functionName}"`); + } + + let params = Object.assign({}, req.body, req.query); + params = parseParams(params); + const request = { + params: params, + master: req.auth && req.auth.isMaster, + user: req.auth && req.auth.user, + installationId: req.info.installationId, + log: req.config.loggerController, + headers: req.config.headers, + ip: req.config.ip, + functionName + }; + + if (theValidator && typeof theValidator === 'function') { + var result = theValidator(request); + + if (!result) { + throw new Parse.Error(Parse.Error.VALIDATION_ERROR, 'Validation failed.'); + } + } + + return new Promise(function (resolve, reject) { + const userString = req.auth && req.auth.user ? req.auth.user.id : undefined; + + const cleanInput = _logger.logger.truncateLogMessage(JSON.stringify(params)); + + const { + success, + error, + message + } = FunctionsRouter.createResponseObject(result => { + try { + const cleanResult = _logger.logger.truncateLogMessage(JSON.stringify(result.response.result)); + + _logger.logger.info(`Ran cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Result: ${cleanResult}`, { + functionName, + params, + user: userString + }); + + resolve(result); + } catch (e) { + reject(e); + } + }, error => { + try { + _logger.logger.error(`Failed running cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Error: ` + JSON.stringify(error), { + functionName, + error, + params, + user: userString + }); + + reject(error); + } catch (e) { + reject(e); + } + }); + return Promise.resolve().then(() => { + return theFunction(request, { + message + }); + }).then(success, error); + }); + } + +} + +exports.FunctionsRouter = FunctionsRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0Z1bmN0aW9uc1JvdXRlci5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJ0cmlnZ2VycyIsInBhcnNlT2JqZWN0Iiwib2JqIiwiQXJyYXkiLCJpc0FycmF5IiwibWFwIiwiaXRlbSIsIl9fdHlwZSIsIk9iamVjdCIsImFzc2lnbiIsIkRhdGUiLCJpc28iLCJGaWxlIiwiZnJvbUpTT04iLCJwYXJzZVBhcmFtcyIsInBhcmFtcyIsIl8iLCJtYXBWYWx1ZXMiLCJGdW5jdGlvbnNSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsImhhbmRsZUNsb3VkRnVuY3Rpb24iLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsInJlcSIsImhhbmRsZUNsb3VkSm9iIiwiam9iTmFtZSIsImJvZHkiLCJhcHBsaWNhdGlvbklkIiwiY29uZmlnIiwiam9iSGFuZGxlciIsImpvYkZ1bmN0aW9uIiwiZ2V0Sm9iIiwiRXJyb3IiLCJTQ1JJUFRfRkFJTEVEIiwicXVlcnkiLCJyZXF1ZXN0IiwibG9nIiwibG9nZ2VyQ29udHJvbGxlciIsImhlYWRlcnMiLCJpcCIsIm1lc3NhZ2UiLCJzZXRNZXNzYWdlIiwiYmluZCIsInNldFJ1bm5pbmciLCJ0aGVuIiwiam9iU3RhdHVzIiwiam9iSWQiLCJvYmplY3RJZCIsInByb2Nlc3MiLCJuZXh0VGljayIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVzdWx0Iiwic2V0U3VjY2VlZGVkIiwiZXJyb3IiLCJzZXRGYWlsZWQiLCJyZXNwb25zZSIsImNyZWF0ZVJlc3BvbnNlT2JqZWN0IiwicmVqZWN0Iiwic3VjY2VzcyIsIl9lbmNvZGUiLCJjb2RlIiwiZnVuY3Rpb25OYW1lIiwidGhlRnVuY3Rpb24iLCJnZXRGdW5jdGlvbiIsInRoZVZhbGlkYXRvciIsImdldFZhbGlkYXRvciIsIm1hc3RlciIsImF1dGgiLCJpc01hc3RlciIsInVzZXIiLCJpbnN0YWxsYXRpb25JZCIsImluZm8iLCJWQUxJREFUSU9OX0VSUk9SIiwidXNlclN0cmluZyIsImlkIiwidW5kZWZpbmVkIiwiY2xlYW5JbnB1dCIsImxvZ2dlciIsInRydW5jYXRlTG9nTWVzc2FnZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJjbGVhblJlc3VsdCIsImUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFLQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQVRBO0FBRUEsSUFBSUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFsQztBQUFBLElBQ0VFLFFBQVEsR0FBR0QsT0FBTyxDQUFDLGFBQUQsQ0FEcEI7O0FBU0EsU0FBU0UsV0FBVCxDQUFxQkMsR0FBckIsRUFBMEI7QUFDeEIsTUFBSUMsS0FBSyxDQUFDQyxPQUFOLENBQWNGLEdBQWQsQ0FBSixFQUF3QjtBQUN0QixXQUFPQSxHQUFHLENBQUNHLEdBQUosQ0FBUUMsSUFBSSxJQUFJO0FBQ3JCLGFBQU9MLFdBQVcsQ0FBQ0ssSUFBRCxDQUFsQjtBQUNELEtBRk0sQ0FBUDtBQUdELEdBSkQsTUFJTyxJQUFJSixHQUFHLElBQUlBLEdBQUcsQ0FBQ0ssTUFBSixJQUFjLE1BQXpCLEVBQWlDO0FBQ3RDLFdBQU9DLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjLElBQUlDLElBQUosQ0FBU1IsR0FBRyxDQUFDUyxHQUFiLENBQWQsRUFBaUNULEdBQWpDLENBQVA7QUFDRCxHQUZNLE1BRUEsSUFBSUEsR0FBRyxJQUFJQSxHQUFHLENBQUNLLE1BQUosSUFBYyxNQUF6QixFQUFpQztBQUN0QyxXQUFPVCxLQUFLLENBQUNjLElBQU4sQ0FBV0MsUUFBWCxDQUFvQlgsR0FBcEIsQ0FBUDtBQUNELEdBRk0sTUFFQSxJQUFJQSxHQUFHLElBQUksT0FBT0EsR0FBUCxLQUFlLFFBQTFCLEVBQW9DO0FBQ3pDLFdBQU9ZLFdBQVcsQ0FBQ1osR0FBRCxDQUFsQjtBQUNELEdBRk0sTUFFQTtBQUNMLFdBQU9BLEdBQVA7QUFDRDtBQUNGOztBQUVELFNBQVNZLFdBQVQs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QUFjSyxXQUFZLEVBRHBILEVBRUU7QUFDRXBCLFlBQUFBLFlBREY7QUFFRWhELFlBQUFBLE1BRkY7QUFHRXdELFlBQUFBLElBQUksRUFBRUk7QUFIUixXQUZGOztBQVFBdkIsVUFBQUEsT0FBTyxDQUFDQyxNQUFELENBQVA7QUFDRCxTQWJELENBYUUsT0FBTytCLENBQVAsRUFBVTtBQUNWekIsVUFBQUEsTUFBTSxDQUFDeUIsQ0FBRCxDQUFOO0FBQ0Q7QUFDRixPQWxCaUMsRUFtQmxDN0IsS0FBSyxJQUFJO0FBQ1AsWUFBSTtBQUNGd0IseUJBQU94QixLQUFQLENBQ0csaUNBQWdDUSxZQUFhLGFBQVlZLFVBQVcsb0JBQW1CRyxVQUFXLGFBQW5HLEdBQ0VHLElBQUksQ0FBQ0MsU0FBTCxDQUFlM0IsS0FBZixDQUZKLEVBR0U7QUFDRVEsWUFBQUEsWUFERjtBQUVFUixZQUFBQSxLQUZGO0FBR0V4QyxZQUFBQSxNQUhGO0FBSUV3RCxZQUFBQSxJQUFJLEVBQUVJO0FBSlIsV0FIRjs7QUFVQWhCLFVBQUFBLE1BQU0sQ0FBQ0osS0FBRCxDQUFOO0FBQ0QsU0FaRCxDQVlFLE9BQU82QixDQUFQLEVBQVU7QUFDVnpCLFVBQUFBLE1BQU0sQ0FBQ3lCLENBQUQsQ0FBTjtBQUNEO0FBQ0YsT0FuQ2lDLENBQXBDO0FBcUNBLGFBQU9qQyxPQUFPLENBQUNDLE9BQVIsR0FDSlAsSUFESSxDQUNDLE1BQU07QUFDVixlQUFPbUIsV0FBVyxDQUFDNUIsT0FBRCxFQUFVO0FBQUVLLFVBQUFBO0FBQUYsU0FBVixDQUFsQjtBQUNELE9BSEksRUFJSkksSUFKSSxDQUlDZSxPQUpELEVBSVVMLEtBSlYsQ0FBUDtBQUtELEtBOUNNLENBQVA7QUErQ0Q7O0FBbExnRCIsInNvdXJjZXNDb250ZW50IjpbIi8vIEZ1bmN0aW9uc1JvdXRlci5qc1xuXG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2UsXG4gIHRyaWdnZXJzID0gcmVxdWlyZSgnLi4vdHJpZ2dlcnMnKTtcblxuaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgeyBwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyB9IGZyb20gJy4uL21pZGRsZXdhcmVzJztcbmltcG9ydCB7IGpvYlN0YXR1c0hhbmRsZXIgfSBmcm9tICcuLi9TdGF0dXNIYW5kbGVyJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi9sb2dnZXInO1xuXG5mdW5jdGlvbiBwYXJzZU9iamVjdChvYmopIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgIHJldHVybiBvYmoubWFwKGl0ZW0gPT4ge1xuICAgICAgcmV0dXJuIHBhcnNlT2JqZWN0KGl0ZW0pO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKG9iaiAmJiBvYmouX190eXBlID09ICdEYXRlJykge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBEYXRlKG9iai5pc28pLCBvYmopO1xuICB9IGVsc2UgaWYgKG9iaiAmJiBvYmouX190eXBlID09ICdGaWxlJykge1xuICAgIHJldHVybiBQYXJzZS5GaWxlLmZyb21KU09OKG9iaik7XG4gIH0gZWxzZSBpZiAob2JqICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIHBhcnNlUGFyYW1zKG9iaik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVBhcmFtcyhwYXJhbXMpIHtcbiAgcmV0dXJuIF8ubWFwVmFsdWVzKHBhcmFtcywgcGFyc2VPYmplY3QpO1xufVxuXG5leHBvcnQgY2xhc3MgRnVuY3Rpb25zUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUE9TVCcsXG4gICAgICAnL2Z1bmN0aW9ucy86ZnVuY3Rpb25OYW1lJyxcbiAgICAgIEZ1bmN0aW9uc1JvdXRlci5oYW5kbGVDbG91ZEZ1bmN0aW9uXG4gICAgKTtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ1BPU1QnLFxuICAgICAgJy9qb2JzLzpqb2JOYW1lJyxcbiAgICAgIHByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgZnVuY3Rpb24ocmVxKSB7XG4gICAgICAgIHJldHVybiBGdW5jdGlvbnNSb3V0ZXIuaGFuZGxlQ2xvdWRKb2IocmVxKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2pvYnMnLCBwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgZnVuY3Rpb24ocmVxKSB7XG4gICAgICByZXR1cm4gRnVuY3Rpb25zUm91dGVyLmhhbmRsZUNsb3VkSm9iKHJlcSk7XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgaGFuZGxlQ2xvdWRKb2IocmVxKSB7XG4gICAgY29uc3Qgam9iTmFtZSA9IHJlcS5wYXJhbXMuam9iTmFtZSB8fCByZXEuYm9keS5qb2JOYW1lO1xuICAgIGNvbnN0IGFwcGxpY2F0aW9uSWQgPSByZXEuY29uZmlnLmFwcGxpY2F0aW9uSWQ7XG4gICAgY29uc3Qgam9iSGFuZGxlciA9IGpvYlN0YXR1c0hhbmRsZXIocmVxLmNvbmZpZyk7XG4gICAgY29uc3Qgam9iRnVuY3Rpb24gPSB0cmlnZ2Vycy5nZXRKb2Ioam9iTmFtZSwgYXBwbGljYXRpb25JZCk7XG4gICAgaWYgKCFqb2JGdW5jdGlvbikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlNDUklQVF9GQUlMRUQsICdJbnZhbGlkIGpvYi4nKTtcbiAgICB9XG4gICAgbGV0IHBhcmFtcyA9IE9iamVjdC5hc3NpZ24oe30sIHJlcS5ib2R5LCByZXEucXVlcnkpO1xuICAgIHBhcmFtcyA9IHBhcnNlUGFyYW1zKHBhcmFtcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IHtcbiAgICAgIHBhcmFtczogcGFyYW1zLFxuICAgICAgbG9nOiByZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIsXG4gICAgICBoZWFkZXJzOiByZXEuY29uZmlnLmhlYWRlcnMsXG4gICAgICBpcDogcmVxLmNvbmZpZy5pcCxcbiAgICAgIGpvYk5hbWUsXG4gICAgICBtZXNzYWdlOiBqb2JIYW5kbGVyLnNldE1lc3NhZ2UuYmluZChqb2JIYW5kbGVyKSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIGpvYkhhbmRsZXIuc2V0UnVubmluZyhqb2JOYW1lLCBwYXJhbXMpLnRoZW4oam9iU3RhdHVzID0+IHtcbiAgICAgIHJlcXVlc3Quam9iSWQgPSBqb2JTdGF0dXMub2JqZWN0SWQ7XG4gICAgICAvLyBydW4gdGhlIGZ1bmN0aW9uIGFzeW5jXG4gICAgICBwcm9jZXNzLm5leHRUaWNrKCgpID0+IHtcbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gam9iRnVuY3Rpb24ocmVxdWVzdCk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbihcbiAgICAgICAgICAgIHJlc3VsdCA9PiB7XG4gICAgICAgICAgICAgIGpvYkhhbmRsZXIuc2V0U3VjY2VlZGVkKHJlc3VsdCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICBqb2JIYW5kbGVyLnNldEZhaWxlZChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdYLVBhcnNlLUpvYi1TdGF0dXMtSWQnOiBqb2JTdGF0dXMub2JqZWN0SWQsXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3BvbnNlOiB7fSxcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlUmVzcG9uc2VPYmplY3QocmVzb2x2ZSwgcmVqZWN0LCBtZXNzYWdlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICByZXNwb25zZToge1xuICAgICAgICAgICAgcmVzdWx0OiBQYXJzZS5fZW5jb2RlKHJlc3VsdCksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgZXJyb3I6IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgLy8gcGFyc2UgZXJyb3IsIHByb2Nlc3MgYXdheVxuICAgICAgICBpZiAobWVzc2FnZSBpbnN0YW5jZW9mIFBhcnNlLkVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChtZXNzYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvZGUgPSBQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVEO1xuICAgICAgICAvLyBJZiBpdCdzIGFuIGVycm9yLCBtYXJrIGl0IGFzIGEgc2NyaXB0IGZhaWxlZFxuICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgUGFyc2UuRXJyb3IoY29kZSwgbWVzc2FnZSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXNzYWdlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICBtZXNzYWdlID0gbWVzc2FnZS5tZXNzYWdlO1xuICAgICAgICB9XG4gICAgICAgIHJlamVjdChuZXcgUGFyc2UuRXJyb3IoY29kZSwgbWVzc2FnZSkpO1xuICAgICAgfSxcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBoYW5kbGVDbG91ZEZ1bmN0aW9uKHJlcSkge1xuICAgIGNvbnN0IGZ1bmN0aW9uTmFtZSA9IHJlcS5wYXJhbXMuZnVuY3Rpb25OYW1lO1xuICAgIGNvbnN0IGFwcGxpY2F0aW9uSWQgPSByZXEuY29uZmlnLmFwcGxpY2F0aW9uSWQ7XG4gICAgY29uc3QgdGhlRnVuY3Rpb24gPSB0cmlnZ2Vycy5nZXRGdW5jdGlvbihmdW5jdGlvbk5hbWUsIGFwcGxpY2F0aW9uSWQpO1xuICAgIGNvbnN0IHRoZVZhbGlkYXRvciA9IHRyaWdnZXJzLmdldFZhbGlkYXRvcihcbiAgICAgIHJlcS5wYXJhbXMuZnVuY3Rpb25OYW1lLFxuICAgICAgYXBwbGljYXRpb25JZFxuICAgICk7XG4gICAgaWYgKCF0aGVGdW5jdGlvbikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVELFxuICAgICAgICBgSW52YWxpZCBmdW5jdGlvbjogXCIke2Z1bmN0aW9uTmFtZX1cImBcbiAgICAgICk7XG4gICAgfVxuICAgIGxldCBwYXJhbXMgPSBPYmplY3QuYXNzaWduKHt9LCByZXEuYm9keSwgcmVxLnF1ZXJ5KTtcbiAgICBwYXJhbXMgPSBwYXJzZVBhcmFtcyhwYXJhbXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICBwYXJhbXM6IHBhcmFtcyxcbiAgICAgIG1hc3RlcjogcmVxLmF1dGggJiYgcmVxLmF1dGguaXNNYXN0ZXIsXG4gICAgICB1c2VyOiByZXEuYXV0aCAmJiByZXEuYXV0aC51c2VyLFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5pbmZvLmluc3RhbGxhdGlvbklkLFxuICAgICAgbG9nOiByZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIsXG4gICAgICBoZWFkZXJzOiByZXEuY29uZmlnLmhlYWRlcnMsXG4gICAgICBpcDogcmVxLmNvbmZpZy5pcCxcbiAgICAgIGZ1bmN0aW9uTmFtZSxcbiAgICB9O1xuXG4gICAgaWYgKHRoZVZhbGlkYXRvciAmJiB0eXBlb2YgdGhlVmFsaWRhdG9yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gdGhlVmFsaWRhdG9yKHJlcXVlc3QpO1xuICAgICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsXG4gICAgICAgICAgJ1ZhbGlkYXRpb24gZmFpbGVkLidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBjb25zdCB1c2VyU3RyaW5nID1cbiAgICAgICAgcmVxLmF1dGggJiYgcmVxLmF1dGgudXNlciA/IHJlcS5hdXRoLnVzZXIuaWQgOiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBjbGVhbklucHV0ID0gbG9nZ2VyLnRydW5jYXRlTG9nTWVzc2FnZShKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgIGNvbnN0IHsgc3VjY2VzcywgZXJyb3IsIG1lc3NhZ2UgfSA9IEZ1bmN0aW9uc1JvdXRlci5jcmVhdGVSZXNwb25zZU9iamVjdChcbiAgICAgICAgcmVzdWx0ID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgY2xlYW5SZXN1bHQgPSBsb2dnZXIudHJ1bmNhdGVMb2dNZXNzYWdlKFxuICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXN1bHQucmVzcG9uc2UucmVzdWx0KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICBgUmFuIGNsb3VkIGZ1bmN0aW9uICR7ZnVuY3Rpb25OYW1lfSBmb3IgdXNlciAke3VzZXJTdHJpbmd9IHdpdGg6XFxuICBJbnB1dDogJHtjbGVhbklucHV0fVxcbiAgUmVzdWx0OiAke2NsZWFuUmVzdWx0fWAsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgICAgICAgIHVzZXI6IHVzZXJTdHJpbmcsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3IgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgIGBGYWlsZWQgcnVubmluZyBjbG91ZCBmdW5jdGlvbiAke2Z1bmN0aW9uTmFtZX0gZm9yIHVzZXIgJHt1c2VyU3RyaW5nfSB3aXRoOlxcbiAgSW5wdXQ6ICR7Y2xlYW5JbnB1dH1cXG4gIEVycm9yOiBgICtcbiAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShlcnJvciksXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgICAgICAgIHVzZXI6IHVzZXJTdHJpbmcsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGVGdW5jdGlvbihyZXF1ZXN0LCB7IG1lc3NhZ2UgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHN1Y2Nlc3MsIGVycm9yKTtcbiAgICB9KTtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/lib/Routers/GlobalConfigRouter.js b/lib/Routers/GlobalConfigRouter.js new file mode 100644 index 0000000000..d17a89383b --- /dev/null +++ b/lib/Routers/GlobalConfigRouter.js @@ -0,0 +1,95 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.GlobalConfigRouter = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// global_config.js +class GlobalConfigRouter extends _PromiseRouter.default { + getGlobalConfig(req) { + return req.config.database.find('_GlobalConfig', { + objectId: '1' + }, { + limit: 1 + }).then(results => { + if (results.length != 1) { + // If there is no config in the database - return empty config. + return { + response: { + params: {} + } + }; + } + + const globalConfig = results[0]; + + if (!req.auth.isMaster && globalConfig.masterKeyOnly !== undefined) { + for (const param in globalConfig.params) { + if (globalConfig.masterKeyOnly[param]) { + delete globalConfig.params[param]; + delete globalConfig.masterKeyOnly[param]; + } + } + } + + return { + response: { + params: globalConfig.params, + masterKeyOnly: globalConfig.masterKeyOnly + } + }; + }); + } + + updateGlobalConfig(req) { + if (req.auth.isReadOnly) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to update the config."); + } + + const params = req.body.params; + const masterKeyOnly = req.body.masterKeyOnly || {}; // Transform in dot notation to make sure it works + + const update = Object.keys(params).reduce((acc, key) => { + acc[`params.${key}`] = params[key]; + acc[`masterKeyOnly.${key}`] = masterKeyOnly[key] || false; + return acc; + }, {}); + return req.config.database.update('_GlobalConfig', { + objectId: '1' + }, update, { + upsert: true + }).then(() => ({ + response: { + result: true + } + })); + } + + mountRoutes() { + this.route('GET', '/config', req => { + return this.getGlobalConfig(req); + }); + this.route('PUT', '/config', middleware.promiseEnforceMasterKeyAccess, req => { + return this.updateGlobalConfig(req); + }); + } + +} + +exports.GlobalConfigRouter = GlobalConfigRouter; +var _default = GlobalConfigRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0dsb2JhbENvbmZpZ1JvdXRlci5qcyJdLCJuYW1lcyI6WyJHbG9iYWxDb25maWdSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwiZ2V0R2xvYmFsQ29uZmlnIiwicmVxIiwiY29uZmlnIiwiZGF0YWJhc2UiLCJmaW5kIiwib2JqZWN0SWQiLCJsaW1pdCIsInRoZW4iLCJyZXN1bHRzIiwibGVuZ3RoIiwicmVzcG9uc2UiLCJwYXJhbXMiLCJnbG9iYWxDb25maWciLCJhdXRoIiwiaXNNYXN0ZXIiLCJtYXN0ZXJLZXlPbmx5IiwidW5kZWZpbmVkIiwicGFyYW0iLCJ1cGRhdGVHbG9iYWxDb25maWciLCJpc1JlYWRPbmx5IiwiUGFyc2UiLCJFcnJvciIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJib2R5IiwidXBkYXRlIiwiT2JqZWN0Iiwia2V5cyIsInJlZHVjZSIsImFjYyIsImtleSIsInVwc2VydCIsInJlc3VsdCIsIm1vdW50Um91dGVzIiwicm91dGUiLCJtaWRkbGV3YXJlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFIQTtBQUtPLE1BQU1BLGtCQUFOLFNBQWlDQyxzQkFBakMsQ0FBK0M7QUFDcERDLEVBQUFBLGVBQWUsQ0FBQ0MsR0FBRCxFQUFNO0FBQ25CLFdBQU9BLEdBQUcsQ0FBQ0MsTUFBSixDQUFXQyxRQUFYLENBQ0pDLElBREksQ0FDQyxlQURELEVBQ2tCO0FBQUVDLE1BQUFBLFFBQVEsRUFBRTtBQUFaLEtBRGxCLEVBQ3FDO0FBQUVDLE1BQUFBLEtBQUssRUFBRTtBQUFULEtBRHJDLEVBRUpDLElBRkksQ0FFQ0MsT0FBTyxJQUFJO0FBQ2YsVUFBSUEsT0FBTyxDQUFDQyxNQUFSLElBQWtCLENBQXRCLEVBQXlCO0FBQ3ZCO0FBQ0EsZUFBTztBQUFFQyxVQUFBQSxRQUFRLEVBQUU7QUFBRUMsWUFBQUEsTUFBTSxFQUFFO0FBQVY7QUFBWixTQUFQO0FBQ0Q7O0FBQ0QsWUFBTUMsWUFBWSxHQUFHSixPQUFPLENBQUMsQ0FBRCxDQUE1Qjs7QUFDQSxVQUFJLENBQUNQLEdBQUcsQ0FBQ1ksSUFBSixDQUFTQyxRQUFWLElBQXNCRixZQUFZLENBQUNHLGFBQWIsS0FBK0JDLFNBQXpELEVBQW9FO0FBQ2xFLGFBQUssTUFBTUMsS0FBWCxJQUFvQkwsWUFBWSxDQUFDRCxNQUFqQyxFQUF5QztBQUN2QyxjQUFJQyxZQUFZLENBQUNHLGFBQWIsQ0FBMkJFLEtBQTNCLENBQUosRUFBdUM7QUFDckMsbUJBQU9MLFlBQVksQ0FBQ0QsTUFBYixDQUFvQk0sS0FBcEIsQ0FBUDtBQUNBLG1CQUFPTCxZQUFZLENBQUNHLGFBQWIsQ0FBMkJFLEtBQTNCLENBQVA7QUFDRDtBQUNGO0FBQ0Y7O0FBQ0QsYUFBTztBQUNMUCxRQUFBQSxRQUFRLEVBQUU7QUFDUkMsVUFBQUEsTUFBTSxFQUFFQyxZQUFZLENBQUNELE1BRGI7QUFFUkksVUFBQUEsYUFBYSxFQUFFSCxZQUFZLENBQUNHO0FBRnBCO0FBREwsT0FBUDtBQU1ELEtBdEJJLENBQVA7QUF1QkQ7O0FBRURHLEVBQUFBLGtCQUFrQixDQUFDakIsR0FBRCxFQUFNO0FBQ3RCLFFBQUlBLEdBQUcsQ0FBQ1ksSUFBSixDQUFTTSxVQUFiLEVBQXlCO0FBQ3ZCLFlBQU0sSUFBSUMsY0FBTUMsS0FBVixDQUNKRCxjQUFNQyxLQUFOLENBQVlDLG1CQURSLEVBRUoseURBRkksQ0FBTjtBQUlEOztBQUNELFVBQU1YLE1BQU0sR0FBR1YsR0FBRyxDQUFDc0IsSUFBSixDQUFTWixNQUF4QjtBQUNBLFVBQU1JLGFBQWEsR0FBR2QsR0FBRyxDQUFDc0IsSUFBSixDQUFTUixhQUFULElBQTBCLEVBQWhELENBUnNCLENBU3RCOztBQUNBLFVBQU1TLE1BQU0sR0FBR0MsTUFBTSxDQUFDQyxJQUFQLENBQVlmLE1BQVosRUFBb0JnQixNQUFwQixDQUEyQixDQUFDQyxHQUFELEVBQU1DLEdBQU4sS0FBYztBQUN0REQsTUFBQUEsR0FBRyxDQUFFLFVBQVNDLEdBQUksRUFBZixDQUFILEdBQXVCbEIsTUFBTSxDQUFDa0IsR0FBRCxDQUE3QjtBQUNBRCxNQUFBQSxHQUFHLENBQUUsaUJBQWdCQyxHQUFJLEVBQXRCLENBQUgsR0FBOEJkLGFBQWEsQ0FBQ2MsR0FBRCxDQUFiLElBQXNCLEtBQXBEO0FBQ0EsYUFBT0QsR0FBUDtBQUNELEtBSmMsRUFJWixFQUpZLENBQWY7QUFLQSxXQUFPM0IsR0FBRyxDQUFDQyxNQUFKLENBQVdDLFFBQVgsQ0FDSnFCLE1BREksQ0FDRyxlQURILEVBQ29CO0FBQUVuQixNQUFBQSxRQUFRLEVBQUU7QUFBWixLQURwQixFQUN1Q21CLE1BRHZDLEVBQytDO0FBQUVNLE1BQUFBLE1BQU0sRUFBRTtBQUFWLEtBRC9DLEVBRUp2QixJQUZJLENBRUMsT0FBTztBQUFFRyxNQUFBQSxRQUFRLEVBQUU7QUFBRXFCLFFBQUFBLE1BQU0sRUFBRTtBQUFWO0FBQVosS0FBUCxDQUZELENBQVA7QUFHRDs7QUFFREMsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxDQUFXLEtBQVgsRUFBa0IsU0FBbEIsRUFBNkJoQyxHQUFHLElBQUk7QUFDbEMsYUFBTyxLQUFLRCxlQUFMLENBQXFCQyxHQUFyQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUtnQyxLQUFMLENBQ0UsS0FERixFQUVFLFNBRkYsRUFHRUMsVUFBVSxDQUFDQyw2QkFIYixFQUlFbEMsR0FBRyxJQUFJO0FBQ0wsYUFBTyxLQUFLaUIsa0JBQUwsQ0FBd0JqQixHQUF4QixDQUFQO0FBQ0QsS0FOSDtBQVFEOztBQTNEbUQ7OztlQThEdkNILGtCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZ2xvYmFsX2NvbmZpZy5qc1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgKiBhcyBtaWRkbGV3YXJlIGZyb20gJy4uL21pZGRsZXdhcmVzJztcblxuZXhwb3J0IGNsYXNzIEdsb2JhbENvbmZpZ1JvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuICBnZXRHbG9iYWxDb25maWcocmVxKSB7XG4gICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2VcbiAgICAgIC5maW5kKCdfR2xvYmFsQ29uZmlnJywgeyBvYmplY3RJZDogJzEnIH0sIHsgbGltaXQ6IDEgfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggIT0gMSkge1xuICAgICAgICAgIC8vIElmIHRoZXJlIGlzIG5vIGNvbmZpZyBpbiB0aGUgZGF0YWJhc2UgLSByZXR1cm4gZW1wdHkgY29uZmlnLlxuICAgICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB7IHBhcmFtczoge30gfSB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGdsb2JhbENvbmZpZyA9IHJlc3VsdHNbMF07XG4gICAgICAgIGlmICghcmVxLmF1dGguaXNNYXN0ZXIgJiYgZ2xvYmFsQ29uZmlnLm1hc3RlcktleU9ubHkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGZvciAoY29uc3QgcGFyYW0gaW4gZ2xvYmFsQ29uZmlnLnBhcmFtcykge1xuICAgICAgICAgICAgaWYgKGdsb2JhbENvbmZpZy5tYXN0ZXJLZXlPbmx5W3BhcmFtXSkge1xuICAgICAgICAgICAgICBkZWxldGUgZ2xvYmFsQ29uZmlnLnBhcmFtc1twYXJhbV07XG4gICAgICAgICAgICAgIGRlbGV0ZSBnbG9iYWxDb25maWcubWFzdGVyS2V5T25seVtwYXJhbV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVzcG9uc2U6IHtcbiAgICAgICAgICAgIHBhcmFtczogZ2xvYmFsQ29uZmlnLnBhcmFtcyxcbiAgICAgICAgICAgIG1hc3RlcktleU9ubHk6IGdsb2JhbENvbmZpZy5tYXN0ZXJLZXlPbmx5LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgfVxuXG4gIHVwZGF0ZUdsb2JhbENvbmZpZyhyZXEpIHtcbiAgICBpZiAocmVxLmF1dGguaXNSZWFkT25seSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICBcInJlYWQtb25seSBtYXN0ZXJLZXkgaXNuJ3QgYWxsb3dlZCB0byB1cGRhdGUgdGhlIGNvbmZpZy5cIlxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgcGFyYW1zID0gcmVxLmJvZHkucGFyYW1zO1xuICAgIGNvbnN0IG1hc3RlcktleU9ubHkgPSByZXEuYm9keS5tYXN0ZXJLZXlPbmx5IHx8IHt9O1xuICAgIC8vIFRyYW5zZm9ybSBpbiBkb3Qgbm90YXRpb24gdG8gbWFrZSBzdXJlIGl0IHdvcmtzXG4gICAgY29uc3QgdXBkYXRlID0gT2JqZWN0LmtleXMocGFyYW1zKS5yZWR1Y2UoKGFjYywga2V5KSA9PiB7XG4gICAgICBhY2NbYHBhcmFtcy4ke2tleX1gXSA9IHBhcmFtc1trZXldO1xuICAgICAgYWNjW2BtYXN0ZXJLZXlPbmx5LiR7a2V5fWBdID0gbWFzdGVyS2V5T25seVtrZXldIHx8IGZhbHNlO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB7fSk7XG4gICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2VcbiAgICAgIC51cGRhdGUoJ19HbG9iYWxDb25maWcnLCB7IG9iamVjdElkOiAnMScgfSwgdXBkYXRlLCB7IHVwc2VydDogdHJ1ZSB9KVxuICAgICAgLnRoZW4oKCkgPT4gKHsgcmVzcG9uc2U6IHsgcmVzdWx0OiB0cnVlIH0gfSkpO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jb25maWcnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0R2xvYmFsQ29uZmlnKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQVVQnLFxuICAgICAgJy9jb25maWcnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnVwZGF0ZUdsb2JhbENvbmZpZyhyZXEpO1xuICAgICAgfVxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgR2xvYmFsQ29uZmlnUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/GraphQLRouter.js b/lib/Routers/GraphQLRouter.js new file mode 100644 index 0000000000..67741f61af --- /dev/null +++ b/lib/Routers/GraphQLRouter.js @@ -0,0 +1,55 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.GraphQLRouter = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const GraphQLConfigPath = '/graphql-config'; + +class GraphQLRouter extends _PromiseRouter.default { + async getGraphQLConfig(req) { + const result = await req.config.parseGraphQLController.getGraphQLConfig(); + return { + response: result + }; + } + + async updateGraphQLConfig(req) { + if (req.auth.isReadOnly) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to update the GraphQL config."); + } + + const data = await req.config.parseGraphQLController.updateGraphQLConfig(req.body.params); + return { + response: data + }; + } + + mountRoutes() { + this.route('GET', GraphQLConfigPath, middleware.promiseEnforceMasterKeyAccess, req => { + return this.getGraphQLConfig(req); + }); + this.route('PUT', GraphQLConfigPath, middleware.promiseEnforceMasterKeyAccess, req => { + return this.updateGraphQLConfig(req); + }); + } + +} + +exports.GraphQLRouter = GraphQLRouter; +var _default = GraphQLRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0dyYXBoUUxSb3V0ZXIuanMiXSwibmFtZXMiOlsiR3JhcGhRTENvbmZpZ1BhdGgiLCJHcmFwaFFMUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsImdldEdyYXBoUUxDb25maWciLCJyZXEiLCJyZXN1bHQiLCJjb25maWciLCJwYXJzZUdyYXBoUUxDb250cm9sbGVyIiwicmVzcG9uc2UiLCJ1cGRhdGVHcmFwaFFMQ29uZmlnIiwiYXV0aCIsImlzUmVhZE9ubHkiLCJQYXJzZSIsIkVycm9yIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsImRhdGEiLCJib2R5IiwicGFyYW1zIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsIm1pZGRsZXdhcmUiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVBLE1BQU1BLGlCQUFpQixHQUFHLGlCQUExQjs7QUFFTyxNQUFNQyxhQUFOLFNBQTRCQyxzQkFBNUIsQ0FBMEM7QUFDL0MsUUFBTUMsZ0JBQU4sQ0FBdUJDLEdBQXZCLEVBQTRCO0FBQzFCLFVBQU1DLE1BQU0sR0FBRyxNQUFNRCxHQUFHLENBQUNFLE1BQUosQ0FBV0Msc0JBQVgsQ0FBa0NKLGdCQUFsQyxFQUFyQjtBQUNBLFdBQU87QUFDTEssTUFBQUEsUUFBUSxFQUFFSDtBQURMLEtBQVA7QUFHRDs7QUFFRCxRQUFNSSxtQkFBTixDQUEwQkwsR0FBMUIsRUFBK0I7QUFDN0IsUUFBSUEsR0FBRyxDQUFDTSxJQUFKLENBQVNDLFVBQWIsRUFBeUI7QUFDdkIsWUFBTSxJQUFJQyxjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUMsbUJBRFIsRUFFSixpRUFGSSxDQUFOO0FBSUQ7O0FBQ0QsVUFBTUMsSUFBSSxHQUFHLE1BQU1YLEdBQUcsQ0FBQ0UsTUFBSixDQUFXQyxzQkFBWCxDQUFrQ0UsbUJBQWxDLENBQ2pCTCxHQUFHLENBQUNZLElBQUosQ0FBU0MsTUFEUSxDQUFuQjtBQUdBLFdBQU87QUFDTFQsTUFBQUEsUUFBUSxFQUFFTztBQURMLEtBQVA7QUFHRDs7QUFFREcsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxDQUNFLEtBREYsRUFFRW5CLGlCQUZGLEVBR0VvQixVQUFVLENBQUNDLDZCQUhiLEVBSUVqQixHQUFHLElBQUk7QUFDTCxhQUFPLEtBQUtELGdCQUFMLENBQXNCQyxHQUF0QixDQUFQO0FBQ0QsS0FOSDtBQVFBLFNBQUtlLEtBQUwsQ0FDRSxLQURGLEVBRUVuQixpQkFGRixFQUdFb0IsVUFBVSxDQUFDQyw2QkFIYixFQUlFakIsR0FBRyxJQUFJO0FBQ0wsYUFBTyxLQUFLSyxtQkFBTCxDQUF5QkwsR0FBekIsQ0FBUDtBQUNELEtBTkg7QUFRRDs7QUF4QzhDOzs7ZUEyQ2xDSCxhIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgKiBhcyBtaWRkbGV3YXJlIGZyb20gJy4uL21pZGRsZXdhcmVzJztcblxuY29uc3QgR3JhcGhRTENvbmZpZ1BhdGggPSAnL2dyYXBocWwtY29uZmlnJztcblxuZXhwb3J0IGNsYXNzIEdyYXBoUUxSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgYXN5bmMgZ2V0R3JhcGhRTENvbmZpZyhyZXEpIHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCByZXEuY29uZmlnLnBhcnNlR3JhcGhRTENvbnRyb2xsZXIuZ2V0R3JhcGhRTENvbmZpZygpO1xuICAgIHJldHVybiB7XG4gICAgICByZXNwb25zZTogcmVzdWx0LFxuICAgIH07XG4gIH1cblxuICBhc3luYyB1cGRhdGVHcmFwaFFMQ29uZmlnKHJlcSkge1xuICAgIGlmIChyZXEuYXV0aC5pc1JlYWRPbmx5KSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICAgIFwicmVhZC1vbmx5IG1hc3RlcktleSBpc24ndCBhbGxvd2VkIHRvIHVwZGF0ZSB0aGUgR3JhcGhRTCBjb25maWcuXCJcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXEuY29uZmlnLnBhcnNlR3JhcGhRTENvbnRyb2xsZXIudXBkYXRlR3JhcGhRTENvbmZpZyhcbiAgICAgIHJlcS5ib2R5LnBhcmFtc1xuICAgICk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3BvbnNlOiBkYXRhLFxuICAgIH07XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICBHcmFwaFFMQ29uZmlnUGF0aCxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRHcmFwaFFMQ29uZmlnKHJlcSk7XG4gICAgICB9XG4gICAgKTtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ1BVVCcsXG4gICAgICBHcmFwaFFMQ29uZmlnUGF0aCxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy51cGRhdGVHcmFwaFFMQ29uZmlnKHJlcSk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBHcmFwaFFMUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/HooksRouter.js b/lib/Routers/HooksRouter.js new file mode 100644 index 0000000000..6bc61dcab0 --- /dev/null +++ b/lib/Routers/HooksRouter.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.HooksRouter = void 0; + +var _node = require("parse/node"); + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class HooksRouter extends _PromiseRouter.default { + createHook(aHook, config) { + return config.hooksController.createHook(aHook).then(hook => ({ + response: hook + })); + } + + updateHook(aHook, config) { + return config.hooksController.updateHook(aHook).then(hook => ({ + response: hook + })); + } + + handlePost(req) { + return this.createHook(req.body, req.config); + } + + handleGetFunctions(req) { + var hooksController = req.config.hooksController; + + if (req.params.functionName) { + return hooksController.getFunction(req.params.functionName).then(foundFunction => { + if (!foundFunction) { + throw new _node.Parse.Error(143, `no function named: ${req.params.functionName} is defined`); + } + + return Promise.resolve({ + response: foundFunction + }); + }); + } + + return hooksController.getFunctions().then(functions => { + return { + response: functions || [] + }; + }, err => { + throw err; + }); + } + + handleGetTriggers(req) { + var hooksController = req.config.hooksController; + + if (req.params.className && req.params.triggerName) { + return hooksController.getTrigger(req.params.className, req.params.triggerName).then(foundTrigger => { + if (!foundTrigger) { + throw new _node.Parse.Error(143, `class ${req.params.className} does not exist`); + } + + return Promise.resolve({ + response: foundTrigger + }); + }); + } + + return hooksController.getTriggers().then(triggers => ({ + response: triggers || [] + })); + } + + handleDelete(req) { + var hooksController = req.config.hooksController; + + if (req.params.functionName) { + return hooksController.deleteFunction(req.params.functionName).then(() => ({ + response: {} + })); + } else if (req.params.className && req.params.triggerName) { + return hooksController.deleteTrigger(req.params.className, req.params.triggerName).then(() => ({ + response: {} + })); + } + + return Promise.resolve({ + response: {} + }); + } + + handleUpdate(req) { + var hook; + + if (req.params.functionName && req.body.url) { + hook = {}; + hook.functionName = req.params.functionName; + hook.url = req.body.url; + } else if (req.params.className && req.params.triggerName && req.body.url) { + hook = {}; + hook.className = req.params.className; + hook.triggerName = req.params.triggerName; + hook.url = req.body.url; + } else { + throw new _node.Parse.Error(143, 'invalid hook declaration'); + } + + return this.updateHook(hook, req.config); + } + + handlePut(req) { + var body = req.body; + + if (body.__op == 'Delete') { + return this.handleDelete(req); + } else { + return this.handleUpdate(req); + } + } + + mountRoutes() { + this.route('GET', '/hooks/functions', middleware.promiseEnforceMasterKeyAccess, this.handleGetFunctions.bind(this)); + this.route('GET', '/hooks/triggers', middleware.promiseEnforceMasterKeyAccess, this.handleGetTriggers.bind(this)); + this.route('GET', '/hooks/functions/:functionName', middleware.promiseEnforceMasterKeyAccess, this.handleGetFunctions.bind(this)); + this.route('GET', '/hooks/triggers/:className/:triggerName', middleware.promiseEnforceMasterKeyAccess, this.handleGetTriggers.bind(this)); + this.route('POST', '/hooks/functions', middleware.promiseEnforceMasterKeyAccess, this.handlePost.bind(this)); + this.route('POST', '/hooks/triggers', middleware.promiseEnforceMasterKeyAccess, this.handlePost.bind(this)); + this.route('PUT', '/hooks/functions/:functionName', middleware.promiseEnforceMasterKeyAccess, this.handlePut.bind(this)); + this.route('PUT', '/hooks/triggers/:className/:triggerName', middleware.promiseEnforceMasterKeyAccess, this.handlePut.bind(this)); + } + +} + +exports.HooksRouter = HooksRouter; +var _default = HooksRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0hvb2tzUm91dGVyLmpzIl0sIm5hbWVzIjpbIkhvb2tzUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsImNyZWF0ZUhvb2siLCJhSG9vayIsImNvbmZpZyIsImhvb2tzQ29udHJvbGxlciIsInRoZW4iLCJob29rIiwicmVzcG9uc2UiLCJ1cGRhdGVIb29rIiwiaGFuZGxlUG9zdCIsInJlcSIsImJvZHkiLCJoYW5kbGVHZXRGdW5jdGlvbnMiLCJwYXJhbXMiLCJmdW5jdGlvbk5hbWUiLCJnZXRGdW5jdGlvbiIsImZvdW5kRnVuY3Rpb24iLCJQYXJzZSIsIkVycm9yIiwiUHJvbWlzZSIsInJlc29sdmUiLCJnZXRGdW5jdGlvbnMiLCJmdW5jdGlvbnMiLCJlcnIiLCJoYW5kbGVHZXRUcmlnZ2VycyIsImNsYXNzTmFtZSIsInRyaWdnZXJOYW1lIiwiZ2V0VHJpZ2dlciIsImZvdW5kVHJpZ2dlciIsImdldFRyaWdnZXJzIiwidHJpZ2dlcnMiLCJoYW5kbGVEZWxldGUiLCJkZWxldGVGdW5jdGlvbiIsImRlbGV0ZVRyaWdnZXIiLCJoYW5kbGVVcGRhdGUiLCJ1cmwiLCJoYW5kbGVQdXQiLCJfX29wIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsIm1pZGRsZXdhcmUiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsImJpbmQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFTyxNQUFNQSxXQUFOLFNBQTBCQyxzQkFBMUIsQ0FBd0M7QUFDN0NDLEVBQUFBLFVBQVUsQ0FBQ0MsS0FBRCxFQUFRQyxNQUFSLEVBQWdCO0FBQ3hCLFdBQU9BLE1BQU0sQ0FBQ0MsZUFBUCxDQUNKSCxVQURJLENBQ09DLEtBRFAsRUFFSkcsSUFGSSxDQUVDQyxJQUFJLEtBQUs7QUFBRUMsTUFBQUEsUUFBUSxFQUFFRDtBQUFaLEtBQUwsQ0FGTCxDQUFQO0FBR0Q7O0FBRURFLEVBQUFBLFVBQVUsQ0FBQ04sS0FBRCxFQUFR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RUUsa0JBRkYsRUFHRUMsVUFBVSxDQUFDQyw2QkFIYixFQUlFLEtBQUtoQyxVQUFMLENBQWdCaUMsSUFBaEIsQ0FBcUIsSUFBckIsQ0FKRjtBQU1BLFNBQUtILEtBQUwsQ0FDRSxNQURGLEVBRUUsaUJBRkYsRUFHRUMsVUFBVSxDQUFDQyw2QkFIYixFQUlFLEtBQUtoQyxVQUFMLENBQWdCaUMsSUFBaEIsQ0FBcUIsSUFBckIsQ0FKRjtBQU1BLFNBQUtILEtBQUwsQ0FDRSxLQURGLEVBRUUsZ0NBRkYsRUFHRUMsVUFBVSxDQUFDQyw2QkFIYixFQUlFLEtBQUtMLFNBQUwsQ0FBZU0sSUFBZixDQUFvQixJQUFwQixDQUpGO0FBTUEsU0FBS0gsS0FBTCxDQUNFLEtBREYsRUFFRSx5Q0FGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUUsS0FBS0wsU0FBTCxDQUFlTSxJQUFmLENBQW9CLElBQXBCLENBSkY7QUFNRDs7QUF6SjRDOzs7ZUE0SmhDM0MsVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlIH0gZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmUgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuXG5leHBvcnQgY2xhc3MgSG9va3NSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgY3JlYXRlSG9vayhhSG9vaywgY29uZmlnKSB7XG4gICAgcmV0dXJuIGNvbmZpZy5ob29rc0NvbnRyb2xsZXJcbiAgICAgIC5jcmVhdGVIb29rKGFIb29rKVxuICAgICAgLnRoZW4oaG9vayA9PiAoeyByZXNwb25zZTogaG9vayB9KSk7XG4gIH1cblxuICB1cGRhdGVIb29rKGFIb29rLCBjb25maWcpIHtcbiAgICByZXR1cm4gY29uZmlnLmhvb2tzQ29udHJvbGxlclxuICAgICAgLnVwZGF0ZUhvb2soYUhvb2spXG4gICAgICAudGhlbihob29rID0+ICh7IHJlc3BvbnNlOiBob29rIH0pKTtcbiAgfVxuXG4gIGhhbmRsZVBvc3QocmVxKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlSG9vayhyZXEuYm9keSwgcmVxLmNvbmZpZyk7XG4gIH1cblxuICBoYW5kbGVHZXRGdW5jdGlvbnMocmVxKSB7XG4gICAgdmFyIGhvb2tzQ29udHJvbGxlciA9IHJlcS5jb25maWcuaG9va3NDb250cm9sbGVyO1xuICAgIGlmIChyZXEucGFyYW1zLmZ1bmN0aW9uTmFtZSkge1xuICAgICAgcmV0dXJuIGhvb2tzQ29udHJvbGxlclxuICAgICAgICAuZ2V0RnVuY3Rpb24ocmVxLnBhcmFtcy5mdW5jdGlvbk5hbWUpXG4gICAgICAgIC50aGVuKGZvdW5kRnVuY3Rpb24gPT4ge1xuICAgICAgICAgIGlmICghZm91bmRGdW5jdGlvbikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAxNDMsXG4gICAgICAgICAgICAgIGBubyBmdW5jdGlvbiBuYW1lZDogJHtyZXEucGFyYW1zLmZ1bmN0aW9uTmFtZX0gaXMgZGVmaW5lZGBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyByZXNwb25zZTogZm91bmRGdW5jdGlvbiB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhvb2tzQ29udHJvbGxlci5nZXRGdW5jdGlvbnMoKS50aGVuKFxuICAgICAgZnVuY3Rpb25zID0+IHtcbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IGZ1bmN0aW9ucyB8fCBbXSB9O1xuICAgICAgfSxcbiAgICAgIGVyciA9PiB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgaGFuZGxlR2V0VHJpZ2dlcnMocmVxKSB7XG4gICAgdmFyIGhvb2tzQ29udHJvbGxlciA9IHJlcS5jb25maWcuaG9va3NDb250cm9sbGVyO1xuICAgIGlmIChyZXEucGFyYW1zLmNsYXNzTmFtZSAmJiByZXEucGFyYW1zLnRyaWdnZXJOYW1lKSB7XG4gICAgICByZXR1cm4gaG9va3NDb250cm9sbGVyXG4gICAgICAgIC5nZXRUcmlnZ2VyKHJlcS5wYXJhbXMuY2xhc3NOYW1lLCByZXEucGFyYW1zLnRyaWdnZXJOYW1lKVxuICAgICAgICAudGhlbihmb3VuZFRyaWdnZXIgPT4ge1xuICAgICAgICAgIGlmICghZm91bmRUcmlnZ2VyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIDE0MyxcbiAgICAgICAgICAgICAgYGNsYXNzICR7cmVxLnBhcmFtcy5jbGFzc05hbWV9IGRvZXMgbm90IGV4aXN0YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IHJlc3BvbnNlOiBmb3VuZFRyaWdnZXIgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBob29rc0NvbnRyb2xsZXJcbiAgICAgIC5nZXRUcmlnZ2VycygpXG4gICAgICAudGhlbih0cmlnZ2VycyA9PiAoeyByZXNwb25zZTogdHJpZ2dlcnMgfHwgW10gfSkpO1xuICB9XG5cbiAgaGFuZGxlRGVsZXRlKHJlcSkge1xuICAgIHZhciBob29rc0NvbnRyb2xsZXIgPSByZXEuY29uZmlnLmhvb2tzQ29udHJvbGxlcjtcbiAgICBpZiAocmVxLnBhcmFtcy5mdW5jdGlvbk5hbWUpIHtcbiAgICAgIHJldHVybiBob29rc0NvbnRyb2xsZXJcbiAgICAgICAgLmRlbGV0ZUZ1bmN0aW9uKHJlcS5wYXJhbXMuZnVuY3Rpb25OYW1lKVxuICAgICAgICAudGhlbigoKSA9PiAoeyByZXNwb25zZToge30gfSkpO1xuICAgIH0gZWxzZSBpZiAocmVxLnBhcmFtcy5jbGFzc05hbWUgJiYgcmVxLnBhcmFtcy50cmlnZ2VyTmFtZSkge1xuICAgICAgcmV0dXJuIGhvb2tzQ29udHJvbGxlclxuICAgICAgICAuZGVsZXRlVHJpZ2dlcihyZXEucGFyYW1zLmNsYXNzTmFtZSwgcmVxLnBhcmFtcy50cmlnZ2VyTmFtZSlcbiAgICAgICAgLnRoZW4oKCkgPT4gKHsgcmVzcG9uc2U6IHt9IH0pKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IHJlc3BvbnNlOiB7fSB9KTtcbiAgfVxuXG4gIGhhbmRsZVVwZGF0ZShyZXEpIHtcbiAgICB2YXIgaG9vaztcbiAgICBpZiAocmVxLnBhcmFtcy5mdW5jdGlvbk5hbWUgJiYgcmVxLmJvZHkudXJsKSB7XG4gICAgICBob29rID0ge307XG4gICAgICBob29rLmZ1bmN0aW9uTmFtZSA9IHJlcS5wYXJhbXMuZnVuY3Rpb25OYW1lO1xuICAgICAgaG9vay51cmwgPSByZXEuYm9keS51cmw7XG4gICAgfSBlbHNlIGlmIChyZXEucGFyYW1zLmNsYXNzTmFtZSAmJiByZXEucGFyYW1zLnRyaWdnZXJOYW1lICYmIHJlcS5ib2R5LnVybCkge1xuICAgICAgaG9vayA9IHt9O1xuICAgICAgaG9vay5jbGFzc05hbWUgPSByZXEucGFyYW1zLmNsYXNzTmFtZTtcbiAgICAgIGhvb2sudHJpZ2dlck5hbWUgPSByZXEucGFyYW1zLnRyaWdnZXJOYW1lO1xuICAgICAgaG9vay51cmwgPSByZXEuYm9keS51cmw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxNDMsICdpbnZhbGlkIGhvb2sgZGVjbGFyYXRpb24nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlSG9vayhob29rLCByZXEuY29uZmlnKTtcbiAgfVxuXG4gIGhhbmRsZVB1dChyZXEpIHtcbiAgICB2YXIgYm9keSA9IHJlcS5ib2R5O1xuICAgIGlmIChib2R5Ll9fb3AgPT0gJ0RlbGV0ZScpIHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZURlbGV0ZShyZXEpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGUocmVxKTtcbiAgICB9XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL2hvb2tzL2Z1bmN0aW9ucycsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgdGhpcy5oYW5kbGVHZXRGdW5jdGlvbnMuYmluZCh0aGlzKVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9ob29rcy90cmlnZ2VycycsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgdGhpcy5oYW5kbGVHZXRUcmlnZ2Vycy5iaW5kKHRoaXMpXG4gICAgKTtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL2hvb2tzL2Z1bmN0aW9ucy86ZnVuY3Rpb25OYW1lJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICB0aGlzLmhhbmRsZUdldEZ1bmN0aW9ucy5iaW5kKHRoaXMpXG4gICAgKTtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL2hvb2tzL3RyaWdnZXJzLzpjbGFzc05hbWUvOnRyaWdnZXJOYW1lJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICB0aGlzLmhhbmRsZUdldFRyaWdnZXJzLmJpbmQodGhpcylcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUE9TVCcsXG4gICAgICAnL2hvb2tzL2Z1bmN0aW9ucycsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgdGhpcy5oYW5kbGVQb3N0LmJpbmQodGhpcylcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUE9TVCcsXG4gICAgICAnL2hvb2tzL3RyaWdnZXJzJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICB0aGlzLmhhbmRsZVBvc3QuYmluZCh0aGlzKVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQVVQnLFxuICAgICAgJy9ob29rcy9mdW5jdGlvbnMvOmZ1bmN0aW9uTmFtZScsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgdGhpcy5oYW5kbGVQdXQuYmluZCh0aGlzKVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQVVQnLFxuICAgICAgJy9ob29rcy90cmlnZ2Vycy86Y2xhc3NOYW1lLzp0cmlnZ2VyTmFtZScsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgdGhpcy5oYW5kbGVQdXQuYmluZCh0aGlzKVxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSG9va3NSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/IAPValidationRouter.js b/lib/Routers/IAPValidationRouter.js new file mode 100644 index 0000000000..44fd6fa751 --- /dev/null +++ b/lib/Routers/IAPValidationRouter.js @@ -0,0 +1,136 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.IAPValidationRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var _node = _interopRequireDefault(require("parse/node")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const request = require('../request'); + +const rest = require('../rest'); + +// TODO move validation logic in IAPValidationController +const IAP_SANDBOX_URL = 'https://sandbox.itunes.apple.com/verifyReceipt'; +const IAP_PRODUCTION_URL = 'https://buy.itunes.apple.com/verifyReceipt'; +const APP_STORE_ERRORS = { + 21000: 'The App Store could not read the JSON object you provided.', + 21002: 'The data in the receipt-data property was malformed or missing.', + 21003: 'The receipt could not be authenticated.', + 21004: 'The shared secret you provided does not match the shared secret on file for your account.', + 21005: 'The receipt server is not currently available.', + 21006: 'This receipt is valid but the subscription has expired.', + 21007: 'This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.', + 21008: 'This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.' +}; + +function appStoreError(status) { + status = parseInt(status); + var errorString = APP_STORE_ERRORS[status] || 'unknown error.'; + return { + status: status, + error: errorString + }; +} + +function validateWithAppStore(url, receipt) { + return request({ + url: url, + method: 'POST', + body: { + 'receipt-data': receipt + }, + headers: { + 'Content-Type': 'application/json' + } + }).then(httpResponse => { + const body = httpResponse.data; + + if (body && body.status === 0) { + // No need to pass anything, status is OK + return; + } // receipt is from test and should go to test + + + throw body; + }); +} + +function getFileForProductIdentifier(productIdentifier, req) { + return rest.find(req.config, req.auth, '_Product', { + productIdentifier: productIdentifier + }, undefined, req.info.clientSDK).then(function (result) { + const products = result.results; + + if (!products || products.length != 1) { + // Error not found or too many + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + + var download = products[0].download; + return Promise.resolve({ + response: download + }); + }); +} + +class IAPValidationRouter extends _PromiseRouter.default { + handleRequest(req) { + let receipt = req.body.receipt; + const productIdentifier = req.body.productIdentifier; + + if (!receipt || !productIdentifier) { + // TODO: Error, malformed request + throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'missing receipt or productIdentifier'); + } // Transform the object if there + // otherwise assume it's in Base64 already + + + if (typeof receipt == 'object') { + if (receipt['__type'] == 'Bytes') { + receipt = receipt.base64; + } + } + + if (process.env.TESTING == '1' && req.body.bypassAppStoreValidation) { + return getFileForProductIdentifier(productIdentifier, req); + } + + function successCallback() { + return getFileForProductIdentifier(productIdentifier, req); + } + + function errorCallback(error) { + return Promise.resolve({ + response: appStoreError(error.status) + }); + } + + return validateWithAppStore(IAP_PRODUCTION_URL, receipt).then(() => { + return successCallback(); + }, error => { + if (error.status == 21007) { + return validateWithAppStore(IAP_SANDBOX_URL, receipt).then(() => { + return successCallback(); + }, error => { + return errorCallback(error); + }); + } + + return errorCallback(error); + }); + } + + mountRoutes() { + this.route('POST', '/validate_purchase', this.handleRequest); + } + +} + +exports.IAPValidationRouter = IAPValidationRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0lBUFZhbGlkYXRpb25Sb3V0ZXIuanMiXSwibmFtZXMiOlsicmVxdWVzdCIsInJlcXVpcmUiLCJyZXN0IiwiSUFQX1NBTkRCT1hfVVJMIiwiSUFQX1BST0RVQ1RJT05fVVJMIiwiQVBQX1NUT1JFX0VSUk9SUyIsImFwcFN0b3JlRXJyb3IiLCJzdGF0dXMiLCJwYXJzZUludCIsImVycm9yU3RyaW5nIiwiZXJyb3IiLCJ2YWxpZGF0ZVdpdGhBcHBTdG9yZSIsInVybCIsInJlY2VpcHQiLCJtZXRob2QiLCJib2R5IiwiaGVhZGVycyIsInRoZW4iLCJodHRwUmVzcG9uc2UiLCJkYXRhIiwiZ2V0RmlsZUZvclByb2R1Y3RJZGVudGlmaWVyIiwicHJvZHVjdElkZW50aWZpZXIiLCJyZXEiLCJmaW5kIiwiY29uZmlnIiwiYXV0aCIsInVuZGVmaW5lZCIsImluZm8iLCJjbGllbnRTREsiLCJyZXN1bHQiLCJwcm9kdWN0cyIsInJlc3VsdHMiLCJsZW5ndGgiLCJQYXJzZSIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsImRvd25sb2FkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZXNwb25zZSIsIklBUFZhbGlkYXRpb25Sb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwiaGFuZGxlUmVxdWVzdCIsIklOVkFMSURfSlNPTiIsImJhc2U2NCIsInByb2Nlc3MiLCJlbnYiLCJURVNUSU5HIiwiYnlwYXNzQXBwU3RvcmVWYWxpZGF0aW9uIiwic3VjY2Vzc0NhbGxiYWNrIiwiZXJyb3JDYWxsYmFjayIsIm1vdW50Um91dGVzIiwicm91dGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFHQTs7OztBQUZBLE1BQU1BLE9BQU8sR0FBR0MsT0FBTyxDQUFDLFlBQUQsQ0FBdkI7O0FBQ0EsTUFBTUMsSUFBSSxHQUFHRCxPQUFPLENBQUMsU0FBRCxDQUFwQjs7QUFHQTtBQUNBLE1BQU1FLGVBQWUsR0FBRyxnREFBeEI7QUFDQSxNQUFNQyxrQkFBa0Is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LE1BQVgsRUFBbUIsb0JBQW5CLEVBQXlDLEtBQUtWLGFBQTlDO0FBQ0Q7O0FBeERvRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuY29uc3QgcmVxdWVzdCA9IHJlcXVpcmUoJy4uL3JlcXVlc3QnKTtcbmNvbnN0IHJlc3QgPSByZXF1aXJlKCcuLi9yZXN0Jyk7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5cbi8vIFRPRE8gbW92ZSB2YWxpZGF0aW9uIGxvZ2ljIGluIElBUFZhbGlkYXRpb25Db250cm9sbGVyXG5jb25zdCBJQVBfU0FOREJPWF9VUkwgPSAnaHR0cHM6Ly9zYW5kYm94Lml0dW5lcy5hcHBsZS5jb20vdmVyaWZ5UmVjZWlwdCc7XG5jb25zdCBJQVBfUFJPRFVDVElPTl9VUkwgPSAnaHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS92ZXJpZnlSZWNlaXB0JztcblxuY29uc3QgQVBQX1NUT1JFX0VSUk9SUyA9IHtcbiAgMjEwMDA6ICdUaGUgQXBwIFN0b3JlIGNvdWxkIG5vdCByZWFkIHRoZSBKU09OIG9iamVjdCB5b3UgcHJvdmlkZWQuJyxcbiAgMjEwMDI6ICdUaGUgZGF0YSBpbiB0aGUgcmVjZWlwdC1kYXRhIHByb3BlcnR5IHdhcyBtYWxmb3JtZWQgb3IgbWlzc2luZy4nLFxuICAyMTAwMzogJ1RoZSByZWNlaXB0IGNvdWxkIG5vdCBiZSBhdXRoZW50aWNhdGVkLicsXG4gIDIxMDA0OiAnVGhlIHNoYXJlZCBzZWNyZXQgeW91IHByb3ZpZGVkIGRvZXMgbm90IG1hdGNoIHRoZSBzaGFyZWQgc2VjcmV0IG9uIGZpbGUgZm9yIHlvdXIgYWNjb3VudC4nLFxuICAyMTAwNTogJ1RoZSByZWNlaXB0IHNlcnZlciBpcyBub3QgY3VycmVudGx5IGF2YWlsYWJsZS4nLFxuICAyMTAwNjogJ1RoaXMgcmVjZWlwdCBpcyB2YWxpZCBidXQgdGhlIHN1YnNjcmlwdGlvbiBoYXMgZXhwaXJlZC4nLFxuICAyMTAwNzogJ1RoaXMgcmVjZWlwdCBpcyBmcm9tIHRoZSB0ZXN0IGVudmlyb25tZW50LCBidXQgaXQgd2FzIHNlbnQgdG8gdGhlIHByb2R1Y3Rpb24gZW52aXJvbm1lbnQgZm9yIHZlcmlmaWNhdGlvbi4gU2VuZCBpdCB0byB0aGUgdGVzdCBlbnZpcm9ubWVudCBpbnN0ZWFkLicsXG4gIDIxMDA4OiAnVGhpcyByZWNlaXB0IGlzIGZyb20gdGhlIHByb2R1Y3Rpb24gZW52aXJvbm1lbnQsIGJ1dCBpdCB3YXMgc2VudCB0byB0aGUgdGVzdCBlbnZpcm9ubWVudCBmb3IgdmVyaWZpY2F0aW9uLiBTZW5kIGl0IHRvIHRoZSBwcm9kdWN0aW9uIGVudmlyb25tZW50IGluc3RlYWQuJyxcbn07XG5cbmZ1bmN0aW9uIGFwcFN0b3JlRXJyb3Ioc3RhdHVzKSB7XG4gIHN0YXR1cyA9IHBhcnNlSW50KHN0YXR1cyk7XG4gIHZhciBlcnJvclN0cmluZyA9IEFQUF9TVE9SRV9FUlJPUlNbc3RhdHVzXSB8fCAndW5rbm93biBlcnJvci4nO1xuICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cywgZXJyb3I6IGVycm9yU3RyaW5nIH07XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlV2l0aEFwcFN0b3JlKHVybCwgcmVjZWlwdCkge1xuICByZXR1cm4gcmVxdWVzdCh7XG4gICAgdXJsOiB1cmwsXG4gICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgYm9keTogeyAncmVjZWlwdC1kYXRhJzogcmVjZWlwdCB9LFxuICAgIGhlYWRlcnM6IHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgfSxcbiAgfSkudGhlbihodHRwUmVzcG9uc2UgPT4ge1xuICAgIGNvbnN0IGJvZHkgPSBodHRwUmVzcG9uc2UuZGF0YTtcbiAgICBpZiAoYm9keSAmJiBib2R5LnN0YXR1cyA9PT0gMCkge1xuICAgICAgLy8gTm8gbmVlZCB0byBwYXNzIGFueXRoaW5nLCBzdGF0dXMgaXMgT0tcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gcmVjZWlwdCBpcyBmcm9tIHRlc3QgYW5kIHNob3VsZCBnbyB0byB0ZXN0XG4gICAgdGhyb3cgYm9keTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEZpbGVGb3JQcm9kdWN0SWRlbnRpZmllcihwcm9kdWN0SWRlbnRpZmllciwgcmVxKSB7XG4gIHJldHVybiByZXN0XG4gICAgLmZpbmQoXG4gICAgICByZXEuY29uZmlnLFxuICAgICAgcmVxLmF1dGgsXG4gICAgICAnX1Byb2R1Y3QnLFxuICAgICAgeyBwcm9kdWN0SWRlbnRpZmllcjogcHJvZHVjdElkZW50aWZpZXIgfSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgIClcbiAgICAudGhlbihmdW5jdGlvbihyZXN1bHQpIHtcbiAgICAgIGNvbnN0IHByb2R1Y3RzID0gcmVzdWx0LnJlc3VsdHM7XG4gICAgICBpZiAoIXByb2R1Y3RzIHx8IHByb2R1Y3RzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIC8vIEVycm9yIG5vdCBmb3VuZCBvciB0b28gbWFueVxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHZhciBkb3dubG9hZCA9IHByb2R1Y3RzWzBdLmRvd25sb2FkO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IHJlc3BvbnNlOiBkb3dubG9hZCB9KTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGNsYXNzIElBUFZhbGlkYXRpb25Sb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgaGFuZGxlUmVxdWVzdChyZXEpIHtcbiAgICBsZXQgcmVjZWlwdCA9IHJlcS5ib2R5LnJlY2VpcHQ7XG4gICAgY29uc3QgcHJvZHVjdElkZW50aWZpZXIgPSByZXEuYm9keS5wcm9kdWN0SWRlbnRpZmllcjtcblxuICAgIGlmICghcmVjZWlwdCB8fCAhcHJvZHVjdElkZW50aWZpZXIpIHtcbiAgICAgIC8vIFRPRE86IEVycm9yLCBtYWxmb3JtZWQgcmVxdWVzdFxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICdtaXNzaW5nIHJlY2VpcHQgb3IgcHJvZHVjdElkZW50aWZpZXInXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFRyYW5zZm9ybSB0aGUgb2JqZWN0IGlmIHRoZXJlXG4gICAgLy8gb3RoZXJ3aXNlIGFzc3VtZSBpdCdzIGluIEJhc2U2NCBhbHJlYWR5XG4gICAgaWYgKHR5cGVvZiByZWNlaXB0ID09ICdvYmplY3QnKSB7XG4gICAgICBpZiAocmVjZWlwdFsnX190eXBlJ10gPT0gJ0J5dGVzJykge1xuICAgICAgICByZWNlaXB0ID0gcmVjZWlwdC5iYXNlNjQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHByb2Nlc3MuZW52LlRFU1RJTkcgPT0gJzEnICYmIHJlcS5ib2R5LmJ5cGFzc0FwcFN0b3JlVmFsaWRhdGlvbikge1xuICAgICAgcmV0dXJuIGdldEZpbGVGb3JQcm9kdWN0SWRlbnRpZmllcihwcm9kdWN0SWRlbnRpZmllciwgcmVxKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdWNjZXNzQ2FsbGJhY2soKSB7XG4gICAgICByZXR1cm4gZ2V0RmlsZUZvclByb2R1Y3RJZGVudGlmaWVyKHByb2R1Y3RJZGVudGlmaWVyLCByZXEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVycm9yQ2FsbGJhY2soZXJyb3IpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyByZXNwb25zZTogYXBwU3RvcmVFcnJvcihlcnJvci5zdGF0dXMpIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB2YWxpZGF0ZVdpdGhBcHBTdG9yZShJQVBfUFJPRFVDVElPTl9VUkwsIHJlY2VpcHQpLnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiBzdWNjZXNzQ2FsbGJhY2soKTtcbiAgICAgIH0sXG4gICAgICBlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5zdGF0dXMgPT0gMjEwMDcpIHtcbiAgICAgICAgICByZXR1cm4gdmFsaWRhdGVXaXRoQXBwU3RvcmUoSUFQX1NBTkRCT1hfVVJMLCByZWNlaXB0KS50aGVuKFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gc3VjY2Vzc0NhbGxiYWNrKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gZXJyb3JDYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvdmFsaWRhdGVfcHVyY2hhc2UnLCB0aGlzLmhhbmRsZVJlcXVlc3QpO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/InstallationsRouter.js b/lib/Routers/InstallationsRouter.js new file mode 100644 index 0000000000..1a54c64406 --- /dev/null +++ b/lib/Routers/InstallationsRouter.js @@ -0,0 +1,55 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.InstallationsRouter = void 0; + +var _ClassesRouter = _interopRequireDefault(require("./ClassesRouter")); + +var _rest = _interopRequireDefault(require("../rest")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// InstallationsRouter.js +class InstallationsRouter extends _ClassesRouter.default { + className() { + return '_Installation'; + } + + handleFind(req) { + const body = Object.assign(req.body, _ClassesRouter.default.JSONFromQuery(req.query)); + + const options = _ClassesRouter.default.optionsFromBody(body); + + return _rest.default.find(req.config, req.auth, '_Installation', body.where, options, req.info.clientSDK).then(response => { + return { + response: response + }; + }); + } + + mountRoutes() { + this.route('GET', '/installations', req => { + return this.handleFind(req); + }); + this.route('GET', '/installations/:objectId', req => { + return this.handleGet(req); + }); + this.route('POST', '/installations', req => { + return this.handleCreate(req); + }); + this.route('PUT', '/installations/:objectId', req => { + return this.handleUpdate(req); + }); + this.route('DELETE', '/installations/:objectId', req => { + return this.handleDelete(req); + }); + } + +} + +exports.InstallationsRouter = InstallationsRouter; +var _default = InstallationsRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0luc3RhbGxhdGlvbnNSb3V0ZXIuanMiXSwibmFtZXMiOlsiSW5zdGFsbGF0aW9uc1JvdXRlciIsIkNsYXNzZXNSb3V0ZXIiLCJjbGFzc05hbWUiLCJoYW5kbGVGaW5kIiwicmVxIiwiYm9keSIsIk9iamVjdCIsImFzc2lnbiIsIkpTT05Gcm9tUXVlcnkiLCJxdWVyeSIsIm9wdGlvbnMiLCJvcHRpb25zRnJvbUJvZHkiLCJyZXN0IiwiZmluZCIsImNvbmZpZyIsImF1dGgiLCJ3aGVyZSIsImluZm8iLCJjbGllbnRTREsiLCJ0aGVuIiwicmVzcG9uc2UiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwiaGFuZGxlR2V0IiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBRUE7O0FBQ0E7Ozs7QUFIQTtBQUtPLE1BQU1BLG1CQUFOLFNBQWtDQyxzQkFBbEMsQ0FBZ0Q7QUFDckRDLEVBQUFBLFNBQVMsR0FBRztBQUNWLFdBQU8sZUFBUDtBQUNEOztBQUVEQyxFQUFBQSxVQUFVLENBQUNDLEdBQUQsRUFBTTtBQUNkLFVBQU1DLElBQUksR0FBR0MsTUFBTSxDQUFDQyxNQUFQLENBQ1hILEdBQUcsQ0FBQ0MsSUFETyxFQUVYSix1QkFBY08sYUFBZCxDQUE0QkosR0FBRyxDQUFDSyxLQUFoQyxDQUZXLENBQWI7O0FBSUEsVUFBTUMsT0FBTyxHQUFHVCx1QkFBY1UsZUFBZCxDQUE4Qk4sSUFBOUIsQ0FBaEI7O0FBQ0EsV0FBT08sY0FDSkMsSUFESSxDQUVIVCxHQUFHLENBQUNVLE1BRkQsRUFHSFYsR0FBRyxDQUFDVyxJQUhELEVBSUgsZUFKRyxFQUtIVixJQUFJLENBQUNXLEtBTEYsRUFNSE4sT0FORyxFQU9ITixHQUFHLENBQUNhLElBQUosQ0FBU0MsU0FQTixFQVNKQyxJQVRJLENBU0NDLFFBQVEsSUFBSTtBQUNoQixhQUFPO0FBQUVBLFFBQUFBLFFBQVEsRUFBRUE7QUFBWixPQUFQO0FBQ0QsS0FYSSxDQUFQO0FBWUQ7O0FBRURDLEVBQUFBLFdBQVcsR0FBRztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxLQUFYLEVBQWtCLGdCQUFsQixFQUFvQ2xCLEdBQUcsSUFBSTtBQUN6QyxhQUFPLEtBQUtELFVBQUwsQ0FBZ0JDLEdBQWhCLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS2tCLEtBQUwsQ0FBVyxLQUFYLEVBQWtCLDBCQUFsQixFQUE4Q2xCLEdBQUcsSUFBSTtBQUNuRCxhQUFPLEtBQUttQixTQUFMLENBQWVuQixHQUFmLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS2tCLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLGdCQUFuQixFQUFxQ2xCLEdBQUcsSUFBSTtBQUMxQyxhQUFPLEtBQUtvQixZQUFMLENBQWtCcEIsR0FBbEIsQ0FBUDtBQUNELEtBRkQ7QUFHQSxTQUFLa0IsS0FBTCxDQUFXLEtBQVgsRUFBa0IsMEJBQWxCLEVBQThDbEIsR0FBRyxJQUFJO0FBQ25ELGFBQU8sS0FBS3FCLFlBQUwsQ0FBa0JyQixHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUtrQixLQUFMLENBQVcsUUFBWCxFQUFxQiwwQkFBckIsRUFBaURsQixHQUFHLElBQUk7QUFDdEQsYUFBTyxLQUFLc0IsWUFBTCxDQUFrQnRCLEdBQWxCLENBQVA7QUFDRCxLQUZEO0FBR0Q7O0FBekNvRDs7O2VBNEN4Q0osbUIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBJbnN0YWxsYXRpb25zUm91dGVyLmpzXG5cbmltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcblxuZXhwb3J0IGNsYXNzIEluc3RhbGxhdGlvbnNSb3V0ZXIgZXh0ZW5kcyBDbGFzc2VzUm91dGVyIHtcbiAgY2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnX0luc3RhbGxhdGlvbic7XG4gIH1cblxuICBoYW5kbGVGaW5kKHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKFxuICAgICAgcmVxLmJvZHksXG4gICAgICBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KVxuICAgICk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IENsYXNzZXNSb3V0ZXIub3B0aW9uc0Zyb21Cb2R5KGJvZHkpO1xuICAgIHJldHVybiByZXN0XG4gICAgICAuZmluZChcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGgsXG4gICAgICAgICdfSW5zdGFsbGF0aW9uJyxcbiAgICAgICAgYm9keS53aGVyZSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgICApXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiByZXNwb25zZSB9O1xuICAgICAgfSk7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL2luc3RhbGxhdGlvbnMnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRmluZChyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvaW5zdGFsbGF0aW9ucy86b2JqZWN0SWQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlR2V0KHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvaW5zdGFsbGF0aW9ucycsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVDcmVhdGUocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCAnL2luc3RhbGxhdGlvbnMvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZVVwZGF0ZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsICcvaW5zdGFsbGF0aW9ucy86b2JqZWN0SWQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRGVsZXRlKHJlcSk7XG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSW5zdGFsbGF0aW9uc1JvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/LogsRouter.js b/lib/Routers/LogsRouter.js new file mode 100644 index 0000000000..a740d50bdb --- /dev/null +++ b/lib/Routers/LogsRouter.js @@ -0,0 +1,71 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.LogsRouter = void 0; + +var _node = require("parse/node"); + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class LogsRouter extends _PromiseRouter.default { + mountRoutes() { + this.route('GET', '/scriptlog', middleware.promiseEnforceMasterKeyAccess, this.validateRequest, req => { + return this.handleGET(req); + }); + } + + validateRequest(req) { + if (!req.config || !req.config.loggerController) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Logger adapter is not available'); + } + } // Returns a promise for a {response} object. + // query params: + // level (optional) Level of logging you want to query for (info || error) + // from (optional) Start time for the search. Defaults to 1 week ago. + // until (optional) End time for the search. Defaults to current time. + // order (optional) Direction of results returned, either “asc” or “desc”. Defaults to “desc”. + // size (optional) Number of rows returned by search. Defaults to 10 + // n same as size, overrides size if set + + + handleGET(req) { + const from = req.query.from; + const until = req.query.until; + let size = req.query.size; + + if (req.query.n) { + size = req.query.n; + } + + const order = req.query.order; + const level = req.query.level; + const options = { + from, + until, + size, + order, + level + }; + return req.config.loggerController.getLogs(options).then(result => { + return Promise.resolve({ + response: result + }); + }); + } + +} + +exports.LogsRouter = LogsRouter; +var _default = LogsRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0xvZ3NSb3V0ZXIuanMiXSwibmFtZXMiOlsiTG9nc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwibWlkZGxld2FyZSIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwidmFsaWRhdGVSZXF1ZXN0IiwicmVxIiwiaGFuZGxlR0VUIiwiY29uZmlnIiwibG9nZ2VyQ29udHJvbGxlciIsIlBhcnNlIiwiRXJyb3IiLCJQVVNIX01JU0NPTkZJR1VSRUQiLCJmcm9tIiwicXVlcnkiLCJ1bnRpbCIsInNpemUiLCJuIiwib3JkZXIiLCJsZXZlbCIsIm9wdGlvbnMiLCJnZXRMb2dzIiwidGhlbiIsInJlc3VsdCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVzcG9uc2UiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFTyxNQUFNQSxVQUFOLFNBQXlCQyxzQkFBekIsQ0FBdUM7QUFDNUNDLEVBQUFBLFdBQVcsR0FBRztBQUNaLFNBQUtDLEtBQUwsQ0FDRSxLQURGLEVBRUUsWUFGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUUsS0FBS0MsZUFKUCxFQUtFQyxHQUFHLElBQUk7QUFDTCxhQUFPLEtBQUtDLFNBQUwsQ0FBZUQsR0FBZixDQUFQO0FBQ0QsS0FQSDtBQVNEOztBQUVERCxFQUFBQSxlQUFlLENBQUNDLEdBQUQsRUFBTTtBQUNuQixRQUFJLENBQUNBLEdBQUcsQ0FBQ0UsTUFBTCxJQUFlLENBQUNGLEdBQUcsQ0FBQ0UsTUFBSixDQUFXQyxnQkFBL0IsRUFBaUQ7QUFDL0MsWUFBTSxJQUFJQyxZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRFIsRUFFSixpQ0FGSSxDQUFOO0FBSUQ7QUFDRixHQXBCMkMsQ0FzQjVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBTCxFQUFBQSxTQUFTLENBQUNELEdBQUQsRUFBTTtBQUNiLFVBQU1PLElBQUksR0FBR1AsR0FBRyxDQUFDUSxLQUFKLENBQVVELElBQXZCO0FBQ0EsVUFBTUUsS0FBSyxHQUFHVCxHQUFHLENBQUNRLEtBQUosQ0FBVUMsS0FBeEI7QUFDQSxRQUFJQyxJQUFJLEdBQUdWLEdBQUcsQ0FBQ1EsS0FBSixDQUFVRSxJQUFyQjs7QUFDQSxRQUFJVixHQUFHLENBQUNRLEtBQUosQ0FBVUcsQ0FBZCxFQUFpQjtBQUNmRCxNQUFBQSxJQUFJLEdBQUdWLEdBQUcsQ0FBQ1EsS0FBSixDQUFVRyxDQUFqQjtBQUNEOztBQUVELFVBQU1DLEtBQUssR0FBR1osR0FBRyxDQUFDUSxLQUFKLENBQVVJLEtBQXhCO0FBQ0EsVUFBTUMsS0FBSyxHQUFHYixHQUFHLENBQUNRLEtBQUosQ0FBVUssS0FBeEI7QUFDQSxVQUFNQyxPQUFPLEdBQUc7QUFDZFAsTUFBQUEsSUFEYztBQUVkRSxNQUFBQSxLQUZjO0FBR2RDLE1BQUFBLElBSGM7QUFJZEUsTUFBQUEsS0FKYztBQUtkQyxNQUFBQTtBQUxjLEtBQWhCO0FBUUEsV0FBT2IsR0FBRyxDQUFDRSxNQUFKLENBQVdDLGdCQUFYLENBQTRCWSxPQUE1QixDQUFvQ0QsT0FBcEMsRUFBNkNFLElBQTdDLENBQWtEQyxNQUFNLElBQUk7QUFDakUsYUFBT0MsT0FBTyxDQUFDQyxPQUFSLENBQWdCO0FBQ3JCQyxRQUFBQSxRQUFRLEVBQUVIO0FBRFcsT0FBaEIsQ0FBUDtBQUdELEtBSk0sQ0FBUDtBQUtEOztBQXJEMkM7OztlQXdEL0J4QixVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2UgfSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5cbmV4cG9ydCBjbGFzcyBMb2dzUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnR0VUJyxcbiAgICAgICcvc2NyaXB0bG9nJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICB0aGlzLnZhbGlkYXRlUmVxdWVzdCxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZUdFVChyZXEpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICB2YWxpZGF0ZVJlcXVlc3QocmVxKSB7XG4gICAgaWYgKCFyZXEuY29uZmlnIHx8ICFyZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnTG9nZ2VyIGFkYXB0ZXIgaXMgbm90IGF2YWlsYWJsZSdcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEge3Jlc3BvbnNlfSBvYmplY3QuXG4gIC8vIHF1ZXJ5IHBhcmFtczpcbiAgLy8gbGV2ZWwgKG9wdGlvbmFsKSBMZXZlbCBvZiBsb2dnaW5nIHlvdSB3YW50IHRvIHF1ZXJ5IGZvciAoaW5mbyB8fCBlcnJvcilcbiAgLy8gZnJvbSAob3B0aW9uYWwpIFN0YXJ0IHRpbWUgZm9yIHRoZSBzZWFyY2guIERlZmF1bHRzIHRvIDEgd2VlayBhZ28uXG4gIC8vIHVudGlsIChvcHRpb25hbCkgRW5kIHRpbWUgZm9yIHRoZSBzZWFyY2guIERlZmF1bHRzIHRvIGN1cnJlbnQgdGltZS5cbiAgLy8gb3JkZXIgKG9wdGlvbmFsKSBEaXJlY3Rpb24gb2YgcmVzdWx0cyByZXR1cm5lZCwgZWl0aGVyIOKAnGFzY+KAnSBvciDigJxkZXNj4oCdLiBEZWZhdWx0cyB0byDigJxkZXNj4oCdLlxuICAvLyBzaXplIChvcHRpb25hbCkgTnVtYmVyIG9mIHJvd3MgcmV0dXJuZWQgYnkgc2VhcmNoLiBEZWZhdWx0cyB0byAxMFxuICAvLyBuIHNhbWUgYXMgc2l6ZSwgb3ZlcnJpZGVzIHNpemUgaWYgc2V0XG4gIGhhbmRsZUdFVChyZXEpIHtcbiAgICBjb25zdCBmcm9tID0gcmVxLnF1ZXJ5LmZyb207XG4gICAgY29uc3QgdW50aWwgPSByZXEucXVlcnkudW50aWw7XG4gICAgbGV0IHNpemUgPSByZXEucXVlcnkuc2l6ZTtcbiAgICBpZiAocmVxLnF1ZXJ5Lm4pIHtcbiAgICAgIHNpemUgPSByZXEucXVlcnkubjtcbiAgICB9XG5cbiAgICBjb25zdCBvcmRlciA9IHJlcS5xdWVyeS5vcmRlcjtcbiAgICBjb25zdCBsZXZlbCA9IHJlcS5xdWVyeS5sZXZlbDtcbiAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgZnJvbSxcbiAgICAgIHVudGlsLFxuICAgICAgc2l6ZSxcbiAgICAgIG9yZGVyLFxuICAgICAgbGV2ZWwsXG4gICAgfTtcblxuICAgIHJldHVybiByZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIuZ2V0TG9ncyhvcHRpb25zKS50aGVuKHJlc3VsdCA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgcmVzcG9uc2U6IHJlc3VsdCxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IExvZ3NSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/PublicAPIRouter.js b/lib/Routers/PublicAPIRouter.js new file mode 100644 index 0000000000..22d7c46824 --- /dev/null +++ b/lib/Routers/PublicAPIRouter.js @@ -0,0 +1,317 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PublicAPIRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var _Config = _interopRequireDefault(require("../Config")); + +var _express = _interopRequireDefault(require("express")); + +var _path = _interopRequireDefault(require("path")); + +var _fs = _interopRequireDefault(require("fs")); + +var _querystring = _interopRequireDefault(require("querystring")); + +var _node = require("parse/node"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const public_html = _path.default.resolve(__dirname, '../../public_html'); + +const views = _path.default.resolve(__dirname, '../../views'); + +class PublicAPIRouter extends _PromiseRouter.default { + verifyEmail(req) { + const { + token, + username + } = req.query; + const appId = req.params.appId; + + const config = _Config.default.get(appId); + + if (!config) { + this.invalidRequest(); + } + + if (!config.publicServerURL) { + return this.missingPublicServerURL(); + } + + if (!token || !username) { + return this.invalidLink(req); + } + + const userController = config.userController; + return userController.verifyEmail(username, token).then(() => { + const params = _querystring.default.stringify({ + username + }); + + return Promise.resolve({ + status: 302, + location: `${config.verifyEmailSuccessURL}?${params}` + }); + }, () => { + return this.invalidVerificationLink(req); + }); + } + + resendVerificationEmail(req) { + const username = req.body.username; + const appId = req.params.appId; + + const config = _Config.default.get(appId); + + if (!config) { + this.invalidRequest(); + } + + if (!config.publicServerURL) { + return this.missingPublicServerURL(); + } + + if (!username) { + return this.invalidLink(req); + } + + const userController = config.userController; + return userController.resendVerificationEmail(username).then(() => { + return Promise.resolve({ + status: 302, + location: `${config.linkSendSuccessURL}` + }); + }, () => { + return Promise.resolve({ + status: 302, + location: `${config.linkSendFailURL}` + }); + }); + } + + changePassword(req) { + return new Promise((resolve, reject) => { + const config = _Config.default.get(req.query.id); + + if (!config) { + this.invalidRequest(); + } + + if (!config.publicServerURL) { + return resolve({ + status: 404, + text: 'Not found.' + }); + } // Should we keep the file in memory or leave like that? + + + _fs.default.readFile(_path.default.resolve(views, 'choose_password'), 'utf-8', (err, data) => { + if (err) { + return reject(err); + } + + data = data.replace('PARSE_SERVER_URL', `'${config.publicServerURL}'`); + resolve({ + text: data + }); + }); + }); + } + + requestResetPassword(req) { + const config = req.config; + + if (!config) { + this.invalidRequest(); + } + + if (!config.publicServerURL) { + return this.missingPublicServerURL(); + } + + const { + username, + token + } = req.query; + + if (!username || !token) { + return this.invalidLink(req); + } + + return config.userController.checkResetTokenValidity(username, token).then(() => { + const params = _querystring.default.stringify({ + token, + id: config.applicationId, + username, + app: config.appName + }); + + return Promise.resolve({ + status: 302, + location: `${config.choosePasswordURL}?${params}` + }); + }, () => { + return this.invalidLink(req); + }); + } + + resetPassword(req) { + const config = req.config; + + if (!config) { + this.invalidRequest(); + } + + if (!config.publicServerURL) { + return this.missingPublicServerURL(); + } + + const { + username, + token, + new_password + } = req.body; + + if ((!username || !token || !new_password) && req.xhr === false) { + return this.invalidLink(req); + } + + if (!username) { + throw new _node.Parse.Error(_node.Parse.Error.USERNAME_MISSING, 'Missing username'); + } + + if (!token) { + throw new _node.Parse.Error(_node.Parse.Error.OTHER_CAUSE, 'Missing token'); + } + + if (!new_password) { + throw new _node.Parse.Error(_node.Parse.Error.PASSWORD_MISSING, 'Missing password'); + } + + return config.userController.updatePassword(username, token, new_password).then(() => { + return Promise.resolve({ + success: true + }); + }, err => { + return Promise.resolve({ + success: false, + err + }); + }).then(result => { + const params = _querystring.default.stringify({ + username: username, + token: token, + id: config.applicationId, + error: result.err, + app: config.appName + }); + + if (req.xhr) { + if (result.success) { + return Promise.resolve({ + status: 200, + response: 'Password successfully reset' + }); + } + + if (result.err) { + throw new _node.Parse.Error(_node.Parse.Error.OTHER_CAUSE, `${result.err}`); + } + } + + return Promise.resolve({ + status: 302, + location: `${result.success ? `${config.passwordResetSuccessURL}?username=${username}` : `${config.choosePasswordURL}?${params}`}` + }); + }); + } + + invalidLink(req) { + return Promise.resolve({ + status: 302, + location: req.config.invalidLinkURL + }); + } + + invalidVerificationLink(req) { + const config = req.config; + + if (req.query.username && req.params.appId) { + const params = _querystring.default.stringify({ + username: req.query.username, + appId: req.params.appId + }); + + return Promise.resolve({ + status: 302, + location: `${config.invalidVerificationLinkURL}?${params}` + }); + } else { + return this.invalidLink(req); + } + } + + missingPublicServerURL() { + return Promise.resolve({ + text: 'Not found.', + status: 404 + }); + } + + invalidRequest() { + const error = new Error(); + error.status = 403; + error.message = 'unauthorized'; + throw error; + } + + setConfig(req) { + req.config = _Config.default.get(req.params.appId); + return Promise.resolve(); + } + + mountRoutes() { + this.route('GET', '/apps/:appId/verify_email', req => { + this.setConfig(req); + }, req => { + return this.verifyEmail(req); + }); + this.route('POST', '/apps/:appId/resend_verification_email', req => { + this.setConfig(req); + }, req => { + return this.resendVerificationEmail(req); + }); + this.route('GET', '/apps/choose_password', req => { + return this.changePassword(req); + }); + this.route('POST', '/apps/:appId/request_password_reset', req => { + this.setConfig(req); + }, req => { + return this.resetPassword(req); + }); + this.route('GET', '/apps/:appId/request_password_reset', req => { + this.setConfig(req); + }, req => { + return this.requestResetPassword(req); + }); + } + + expressRouter() { + const router = _express.default.Router(); + + router.use('/apps', _express.default.static(public_html)); + router.use('/', super.expressRouter()); + return router; + } + +} + +exports.PublicAPIRouter = PublicAPIRouter; +var _default = PublicAPIRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1B1YmxpY0FQSVJvdXRlci5qcyJdLCJuYW1lcyI6WyJwdWJsaWNfaHRtbCIsInBhdGgiLCJyZXNvbHZlIiwiX19kaXJuYW1lIiwidmlld3MiLCJQdWJsaWNBUElSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwidmVyaWZ5RW1haWwiLCJyZXEiLCJ0b2tlbiIsInVzZXJuYW1lIiwicXVlcnkiLCJhcHBJZCIsInBhcmFtcyIsImNvbmZpZyIsIkNvbmZpZyIsImdldCIsImludmFsaWRSZXF1ZXN0IiwicHVibGljU2VydmVyVVJMIiwibWlzc2luZ1B1YmxpY1NlcnZlclVSTCIsImludmFsaWRMaW5rIiwidXNlckNvbnRyb2xsZXIiLCJ0aGVuIiwicXMiLCJzdHJpbmdpZnkiLCJQcm9taXNlIiwic3RhdHVzIiwibG9jYXRpb24iLCJ2ZXJpZnlFbWFpbFN1Y2Nlc3NVUkwiLCJpbnZhbGlkVmVyaWZpY2F0aW9uTGluayIsInJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsIiwiYm9keSIsImxpbmtTZW5kU3VjY2Vzc1VSTCIsImxpbmtTZW5kRmFpbFVSTCIsImNoYW5nZVBhc3N3b3JkIiwicmVqZWN0IiwiaWQiLCJ0ZXh0IiwiZnMiLCJyZWFkRmlsZSIsImVyciIsImRhdGEiLCJyZXBsYWNlIiwicmVxdWVzdFJlc2V0UGFzc3dvcmQiLCJjaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSIsImFwcGxpY2F0aW9uSWQiLCJhcHAiLCJhcHBOYW1lIiwiY2hvb3NlUGFzc3dvcmRVUkwiLCJyZXNldFBhc3N3b3JkIiwibmV3X3Bhc3N3b3JkIiwieGhyIiwiUGFyc2UiLCJFcnJvciIsIlVTRVJOQU1FX01JU1NJTkciLCJPVEhFUl9DQVVTRSIsIlBBU1NXT1JEX01JU1NJTkciLCJ1cGRhdGVQYXNzd29yZCIsInN1Y2Nlc3MiLCJyZXN1bHQiLCJlcnJvciIsInJlc3BvbnNlIiwicGFzc3dvcmRSZXNldFN1Y2Nlc3NVUkwiLCJpbnZhbGlkTGlua1VSTCIsImludmFsaWRWZXJpZmljYXRpb25MaW5rVVJMIiwibWVzc2FnZSIsInNldENvbmZpZyIsIm1vdW50Um91dGVzIiwicm91dGUiLCJleHByZXNzUm91dGVyIiwicm91dGVyIiwiZXhwcmVzcyIsIlJvdXRlciIsInVzZSIsInN0YXRpYyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEsV0FBVyxHQUFHQyxjQUFLQyxPQUFMLENBQWFDLFNBQWIsRUFBd0IsbUJBQXhCLENBQXBCOztBQUNBLE1BQU1DLEtBQUssR0FBR0gsY0FBS0MsT0FBTCxDQUFhQyxTQUFiLEVBQXdCLGFBQXhCLENBQWQ7O0FBRU8sTUFBTUUsZUFBTixTQUE4QkMsc0JBQTlCLENBQTRDO0FBQ2pEQyxFQUFBQSxXQUFXLENBQUNDLEdBQUQsRUFBTTtBQUNmLFVBQU07QUFBRUMsTUFBQUEsS0FBRjtBQUFTQyxNQUFBQTtBQUFULFFBQXNCRixHQUFHLENBQUNHLEtBQWhDO0FBQ0EsVUFBTUMsS0FBSyxHQUFHSixHQUFHLENBQUNLLE1BQUosQ0FBV0QsS0FBekI7O0FBQ0EsVUFBTUUsTUFBTSxHQUFHQyxnQkFBT0MsR0FBUCxDQUFXSixLQUFYLENBQWY7O0FBRUEsUUFBSSxDQUFDRSxNQUFMLEVBQWE7QUFDWCxXQUFLRyxjQUFMO0FBQ0Q7O0FBRUQsUUFBSSxDQUFDSCxNQUFNLENBQUNJLGVBQVosRUFBNkI7QUFDM0IsYUFBTyxLQUFLQyxzQkFBTCxFQUFQO0FBQ0Q7O0FBRUQsUUFBSSxDQUFDVixLQUFELElBQVUsQ0FBQ0MsUUFBZixFQUF5QjtBQUN2QixhQUFPLEtBQUtVLFdBQUwsQ0FBaUJaLEdBQWpCLENBQVA7QUFDRDs7QUFFRCxVQUFNYSxjQUFjLEdBQUdQLE1BQU0sQ0FBQ08sY0FBOUI7QUFDQSxXQUFPQSxjQUFjLENBQUNkLFdBQWYsQ0FBMkJHLFFBQTNCLEVBQXFDRCxLQUFyQyxFQUE0Q2EsSUFBNUMsQ0FDTCxNQUFNO0FBQ0osWUFBTVQsTUFBTSxHQUFH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QUZGLEVBR0U1RCxHQUFHLElBQUk7QUFDTCxXQUFLMEQsU0FBTCxDQUFlMUQsR0FBZjtBQUNELEtBTEgsRUFNRUEsR0FBRyxJQUFJO0FBQ0wsYUFBTyxLQUFLbUMsb0JBQUwsQ0FBMEJuQyxHQUExQixDQUFQO0FBQ0QsS0FSSDtBQVVEOztBQUVENkQsRUFBQUEsYUFBYSxHQUFHO0FBQ2QsVUFBTUMsTUFBTSxHQUFHQyxpQkFBUUMsTUFBUixFQUFmOztBQUNBRixJQUFBQSxNQUFNLENBQUNHLEdBQVAsQ0FBVyxPQUFYLEVBQW9CRixpQkFBUUcsTUFBUixDQUFlMUUsV0FBZixDQUFwQjtBQUNBc0UsSUFBQUEsTUFBTSxDQUFDRyxHQUFQLENBQVcsR0FBWCxFQUFnQixNQUFNSixhQUFOLEVBQWhCO0FBQ0EsV0FBT0MsTUFBUDtBQUNEOztBQXZUZ0Q7OztlQTBUcENqRSxlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgQ29uZmlnIGZyb20gJy4uL0NvbmZpZyc7XG5pbXBvcnQgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBxcyBmcm9tICdxdWVyeXN0cmluZyc7XG5pbXBvcnQgeyBQYXJzZSB9IGZyb20gJ3BhcnNlL25vZGUnO1xuXG5jb25zdCBwdWJsaWNfaHRtbCA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi8uLi9wdWJsaWNfaHRtbCcpO1xuY29uc3Qgdmlld3MgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4vLi4vdmlld3MnKTtcblxuZXhwb3J0IGNsYXNzIFB1YmxpY0FQSVJvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuICB2ZXJpZnlFbWFpbChyZXEpIHtcbiAgICBjb25zdCB7IHRva2VuLCB1c2VybmFtZSB9ID0gcmVxLnF1ZXJ5O1xuICAgIGNvbnN0IGFwcElkID0gcmVxLnBhcmFtcy5hcHBJZDtcbiAgICBjb25zdCBjb25maWcgPSBDb25maWcuZ2V0KGFwcElkKTtcblxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgfVxuXG4gICAgaWYgKCFjb25maWcucHVibGljU2VydmVyVVJMKSB7XG4gICAgICByZXR1cm4gdGhpcy5taXNzaW5nUHVibGljU2VydmVyVVJMKCk7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlbiB8fCAhdXNlcm5hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlckNvbnRyb2xsZXIgPSBjb25maWcudXNlckNvbnRyb2xsZXI7XG4gICAgcmV0dXJuIHVzZXJDb250cm9sbGVyLnZlcmlmeUVtYWlsKHVzZXJuYW1lLCB0b2tlbikudGhlbihcbiAgICAgICgpID0+IHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gcXMuc3RyaW5naWZ5KHsgdXNlcm5hbWUgfSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIHN0YXR1czogMzAyLFxuICAgICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcudmVyaWZ5RW1haWxTdWNjZXNzVVJMfT8ke3BhcmFtc31gLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmludmFsaWRWZXJpZmljYXRpb25MaW5rKHJlcSk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHJlcSkge1xuICAgIGNvbnN0IHVzZXJuYW1lID0gcmVxLmJvZHkudXNlcm5hbWU7XG4gICAgY29uc3QgYXBwSWQgPSByZXEucGFyYW1zLmFwcElkO1xuICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoYXBwSWQpO1xuXG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwpIHtcbiAgICAgIHJldHVybiB0aGlzLm1pc3NpbmdQdWJsaWNTZXJ2ZXJVUkwoKTtcbiAgICB9XG5cbiAgICBpZiAoIXVzZXJuYW1lKSB7XG4gICAgICByZXR1cm4gdGhpcy5pbnZhbGlkTGluayhyZXEpO1xuICAgIH1cblxuICAgIGNvbnN0IHVzZXJDb250cm9sbGVyID0gY29uZmlnLnVzZXJDb250cm9sbGVyO1xuXG4gICAgcmV0dXJuIHVzZXJDb250cm9sbGVyLnJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHVzZXJuYW1lKS50aGVuKFxuICAgICAgKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBzdGF0dXM6IDMwMixcbiAgICAgICAgICBsb2NhdGlvbjogYCR7Y29uZmlnLmxpbmtTZW5kU3VjY2Vzc1VSTH1gLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIHN0YXR1czogMzAyLFxuICAgICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcubGlua1NlbmRGYWlsVVJMfWAsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBjaGFuZ2VQYXNzd29yZChyZXEpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChyZXEucXVlcnkuaWQpO1xuXG4gICAgICBpZiAoIWNvbmZpZykge1xuICAgICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghY29uZmlnLnB1YmxpY1NlcnZlclVSTCkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZSh7XG4gICAgICAgICAgc3RhdHVzOiA0MDQsXG4gICAgICAgICAgdGV4dDogJ05vdCBmb3VuZC4nLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIC8vIFNob3VsZCB3ZSBrZWVwIHRoZSBmaWxlIGluIG1lbW9yeSBvciBsZWF2ZSBsaWtlIHRoYXQ/XG4gICAgICBmcy5yZWFkRmlsZShcbiAgICAgICAgcGF0aC5yZXNvbHZlKHZpZXdzLCAnY2hvb3NlX3Bhc3N3b3JkJyksXG4gICAgICAgICd1dGYtOCcsXG4gICAgICAgIChlcnIsIGRhdGEpID0+IHtcbiAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGRhdGEgPSBkYXRhLnJlcGxhY2UoXG4gICAgICAgICAgICAnUEFSU0VfU0VSVkVSX1VSTCcsXG4gICAgICAgICAgICBgJyR7Y29uZmlnLnB1YmxpY1NlcnZlclVSTH0nYFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgICB0ZXh0OiBkYXRhLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcmVxdWVzdFJlc2V0UGFzc3dvcmQocmVxKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcblxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgfVxuXG4gICAgaWYgKCFjb25maWcucHVibGljU2VydmVyVVJMKSB7XG4gICAgICByZXR1cm4gdGhpcy5taXNzaW5nUHVibGljU2VydmVyVVJMKCk7XG4gICAgfVxuXG4gICAgY29uc3QgeyB1c2VybmFtZSwgdG9rZW4gfSA9IHJlcS5xdWVyeTtcblxuICAgIGlmICghdXNlcm5hbWUgfHwgIXRva2VuKSB7XG4gICAgICByZXR1cm4gdGhpcy5pbnZhbGlkTGluayhyZXEpO1xuICAgIH1cblxuICAgIHJldHVybiBjb25maWcudXNlckNvbnRyb2xsZXIuY2hlY2tSZXNldFRva2VuVmFsaWRpdHkodXNlcm5hbWUsIHRva2VuKS50aGVuKFxuICAgICAgKCkgPT4ge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBxcy5zdHJpbmdpZnkoe1xuICAgICAgICAgIHRva2VuLFxuICAgICAgICAgIGlkOiBjb25maWcuYXBwbGljYXRpb25JZCxcbiAgICAgICAgICB1c2VybmFtZSxcbiAgICAgICAgICBhcHA6IGNvbmZpZy5hcHBOYW1lLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgICAgbG9jYXRpb246IGAke2NvbmZpZy5jaG9vc2VQYXNzd29yZFVSTH0/JHtwYXJhbXN9YCxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pbnZhbGlkTGluayhyZXEpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICByZXNldFBhc3N3b3JkKHJlcSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG5cbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgdGhpcy5pbnZhbGlkUmVxdWVzdCgpO1xuICAgIH1cblxuICAgIGlmICghY29uZmlnLnB1YmxpY1NlcnZlclVSTCkge1xuICAgICAgcmV0dXJuIHRoaXMubWlzc2luZ1B1YmxpY1NlcnZlclVSTCgpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgdXNlcm5hbWUsIHRva2VuLCBuZXdfcGFzc3dvcmQgfSA9IHJlcS5ib2R5O1xuXG4gICAgaWYgKCghdXNlcm5hbWUgfHwgIXRva2VuIHx8ICFuZXdfcGFzc3dvcmQpICYmIHJlcS54aHIgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5pbnZhbGlkTGluayhyZXEpO1xuICAgIH1cblxuICAgIGlmICghdXNlcm5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5VU0VSTkFNRV9NSVNTSU5HLCAnTWlzc2luZyB1c2VybmFtZScpO1xuICAgIH1cblxuICAgIGlmICghdG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PVEhFUl9DQVVTRSwgJ01pc3NpbmcgdG9rZW4nKTtcbiAgICB9XG5cbiAgICBpZiAoIW5ld19wYXNzd29yZCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBBU1NXT1JEX01JU1NJTkcsICdNaXNzaW5nIHBhc3N3b3JkJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZy51c2VyQ29udHJvbGxlclxuICAgICAgLnVwZGF0ZVBhc3N3b3JkKHVzZXJuYW1lLCB0b2tlbiwgbmV3X3Bhc3N3b3JkKVxuICAgICAgLnRoZW4oXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIGVyciA9PiB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIGVycixcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgKVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gcXMuc3RyaW5naWZ5KHtcbiAgICAgICAgICB1c2VybmFtZTogdXNlcm5hbWUsXG4gICAgICAgICAgdG9rZW46IHRva2VuLFxuICAgICAgICAgIGlkOiBjb25maWcuYXBwbGljYXRpb25JZCxcbiAgICAgICAgICBlcnJvcjogcmVzdWx0LmVycixcbiAgICAgICAgICBhcHA6IGNvbmZpZy5hcHBOYW1lLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocmVxLnhocikge1xuICAgICAgICAgIGlmIChyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgICAgIHN0YXR1czogMjAwLFxuICAgICAgICAgICAgICByZXNwb25zZTogJ1Bhc3N3b3JkIHN1Y2Nlc3NmdWxseSByZXNldCcsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHJlc3VsdC5lcnIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PVEhFUl9DQVVTRSwgYCR7cmVzdWx0LmVycn1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBzdGF0dXM6IDMwMixcbiAgICAgICAgICBsb2NhdGlvbjogYCR7XG4gICAgICAgICAgICByZXN1bHQuc3VjY2Vzc1xuICAgICAgICAgICAgICA/IGAke2NvbmZpZy5wYXNzd29yZFJlc2V0U3VjY2Vzc1VSTH0/dXNlcm5hbWU9JHt1c2VybmFtZX1gXG4gICAgICAgICAgICAgIDogYCR7Y29uZmlnLmNob29zZVBhc3N3b3JkVVJMfT8ke3BhcmFtc31gXG4gICAgICAgICAgfWAsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICBpbnZhbGlkTGluayhyZXEpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgIHN0YXR1czogMzAyLFxuICAgICAgbG9jYXRpb246IHJlcS5jb25maWcuaW52YWxpZExpbmtVUkwsXG4gICAgfSk7XG4gIH1cblxuICBpbnZhbGlkVmVyaWZpY2F0aW9uTGluayhyZXEpIHtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuICAgIGlmIChyZXEucXVlcnkudXNlcm5hbWUgJiYgcmVxLnBhcmFtcy5hcHBJZCkge1xuICAgICAgY29uc3QgcGFyYW1zID0gcXMuc3RyaW5naWZ5KHtcbiAgICAgICAgdXNlcm5hbWU6IHJlcS5xdWVyeS51c2VybmFtZSxcbiAgICAgICAgYXBwSWQ6IHJlcS5wYXJhbXMuYXBwSWQsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICBzdGF0dXM6IDMwMixcbiAgICAgICAgbG9jYXRpb246IGAke2NvbmZpZy5pbnZhbGlkVmVyaWZpY2F0aW9uTGlua1VSTH0/JHtwYXJhbXN9YCxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5pbnZhbGlkTGluayhyZXEpO1xuICAgIH1cbiAgfVxuXG4gIG1pc3NpbmdQdWJsaWNTZXJ2ZXJVUkwoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICB0ZXh0OiAnTm90IGZvdW5kLicsXG4gICAgICBzdGF0dXM6IDQwNCxcbiAgICB9KTtcbiAgfVxuXG4gIGludmFsaWRSZXF1ZXN0KCkge1xuICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKCk7XG4gICAgZXJyb3Iuc3RhdHVzID0gNDAzO1xuICAgIGVycm9yLm1lc3NhZ2UgPSAndW5hdXRob3JpemVkJztcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuXG4gIHNldENvbmZpZyhyZXEpIHtcbiAgICByZXEuY29uZmlnID0gQ29uZmlnLmdldChyZXEucGFyYW1zLmFwcElkKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL2FwcHMvOmFwcElkL3ZlcmlmeV9lbWFpbCcsXG4gICAgICByZXEgPT4ge1xuICAgICAgICB0aGlzLnNldENvbmZpZyhyZXEpO1xuICAgICAgfSxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnZlcmlmeUVtYWlsKHJlcSk7XG4gICAgICB9XG4gICAgKTtcblxuICAgIHRoaXMucm91dGUoXG4gICAgICAnUE9TVCcsXG4gICAgICAnL2FwcHMvOmFwcElkL3Jlc2VuZF92ZXJpZmljYXRpb25fZW1haWwnLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgdGhpcy5zZXRDb25maWcocmVxKTtcbiAgICAgIH0sXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXNlbmRWZXJpZmljYXRpb25FbWFpbChyZXEpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL2FwcHMvY2hvb3NlX3Bhc3N3b3JkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmNoYW5nZVBhc3N3b3JkKHJlcSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ1BPU1QnLFxuICAgICAgJy9hcHBzLzphcHBJZC9yZXF1ZXN0X3Bhc3N3b3JkX3Jlc2V0JyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHRoaXMuc2V0Q29uZmlnKHJlcSk7XG4gICAgICB9LFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzZXRQYXNzd29yZChyZXEpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL2FwcHMvOmFwcElkL3JlcXVlc3RfcGFzc3dvcmRfcmVzZXQnLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgdGhpcy5zZXRDb25maWcocmVxKTtcbiAgICAgIH0sXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXF1ZXN0UmVzZXRQYXNzd29yZChyZXEpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBleHByZXNzUm91dGVyKCkge1xuICAgIGNvbnN0IHJvdXRlciA9IGV4cHJlc3MuUm91dGVyKCk7XG4gICAgcm91dGVyLnVzZSgnL2FwcHMnLCBleHByZXNzLnN0YXRpYyhwdWJsaWNfaHRtbCkpO1xuICAgIHJvdXRlci51c2UoJy8nLCBzdXBlci5leHByZXNzUm91dGVyKCkpO1xuICAgIHJldHVybiByb3V0ZXI7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVibGljQVBJUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/PurgeRouter.js b/lib/Routers/PurgeRouter.js new file mode 100644 index 0000000000..982ee0f0c1 --- /dev/null +++ b/lib/Routers/PurgeRouter.js @@ -0,0 +1,60 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PurgeRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +var _node = _interopRequireDefault(require("parse/node")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class PurgeRouter extends _PromiseRouter.default { + handlePurge(req) { + if (req.auth.isReadOnly) { + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to purge a schema."); + } + + return req.config.database.purgeCollection(req.params.className).then(() => { + var cacheAdapter = req.config.cacheController; + + if (req.params.className == '_Session') { + cacheAdapter.user.clear(); + } else if (req.params.className == '_Role') { + cacheAdapter.role.clear(); + } + + return { + response: {} + }; + }).catch(error => { + if (!error || error && error.code === _node.default.Error.OBJECT_NOT_FOUND) { + return { + response: {} + }; + } + + throw error; + }); + } + + mountRoutes() { + this.route('DELETE', '/purge/:className', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handlePurge(req); + }); + } + +} + +exports.PurgeRouter = PurgeRouter; +var _default = PurgeRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1B1cmdlUm91dGVyLmpzIl0sIm5hbWVzIjpbIlB1cmdlUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsImhhbmRsZVB1cmdlIiwicmVxIiwiYXV0aCIsImlzUmVhZE9ubHkiLCJQYXJzZSIsIkVycm9yIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsImNvbmZpZyIsImRhdGFiYXNlIiwicHVyZ2VDb2xsZWN0aW9uIiwicGFyYW1zIiwiY2xhc3NOYW1lIiwidGhlbiIsImNhY2hlQWRhcHRlciIsImNhY2hlQ29udHJvbGxlciIsInVzZXIiLCJjbGVhciIsInJvbGUiLCJyZXNwb25zZSIsImNhdGNoIiwiZXJyb3IiLCJjb2RlIiwiT0JKRUNUX05PVF9GT1VORCIsIm1vdW50Um91dGVzIiwicm91dGUiLCJtaWRkbGV3YXJlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFTyxNQUFNQSxXQUFOLFNBQTBCQyxzQkFBMUIsQ0FBd0M7QUFDN0NDLEVBQUFBLFdBQVcsQ0FBQ0MsR0FBRCxFQUFNO0FBQ2YsUUFBSUEsR0FBRyxDQUFDQyxJQUFKLENBQVNDLFVBQWIsRUFBeUI7QUFDdkIsWUFBTSxJQUFJQyxjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUMsbUJBRFIsRUFFSixzREFGSSxDQUFOO0FBSUQ7O0FBQ0QsV0FBT0wsR0FBRyxDQUFDTSxNQUFKLENBQVdDLFFBQVgsQ0FDSkMsZUFESSxDQUNZUixHQUFHLENBQUNTLE1BQUosQ0FBV0MsU0FEdkIsRUFFSkMsSUFGSSxDQUVDLE1BQU07QUFDVixVQUFJQyxZQUFZLEdBQUdaLEdBQUcsQ0FBQ00sTUFBSixDQUFXTyxlQUE5Qjs7QUFDQSxVQUFJYixHQUFHLENBQUNTLE1BQUosQ0FBV0MsU0FBWCxJQUF3QixVQUE1QixFQUF3QztBQUN0Q0UsUUFBQUEsWUFBWSxDQUFDRSxJQUFiLENBQWtCQyxLQUFsQjtBQUNELE9BRkQsTUFFTyxJQUFJZixHQUFHLENBQUNTLE1BQUosQ0FBV0MsU0FBWCxJQUF3QixPQUE1QixFQUFxQztBQUMxQ0UsUUFBQUEsWUFBWSxDQUFDSSxJQUFiLENBQWtCRCxLQUFsQjtBQUNEOztBQUNELGFBQU87QUFBRUUsUUFBQUEsUUFBUSxFQUFFO0FBQVosT0FBUDtBQUNELEtBVkksRUFXSkMsS0FYSSxDQVdFQyxLQUFLLElBQUk7QUFDZCxVQUFJLENBQUNBLEtBQUQsSUFBV0EsS0FBSyxJQUFJQSxLQUFLLENBQUNDLElBQU4sS0FBZWpCLGNBQU1DLEtBQU4sQ0FBWWlCLGdCQUFuRCxFQUFzRTtBQUNwRSxlQUFPO0FBQUVKLFVBQUFBLFFBQVEsRUFBRTtBQUFaLFNBQVA7QUFDRDs7QUFDRCxZQUFNRSxLQUFOO0FBQ0QsS0FoQkksQ0FBUDtBQWlCRDs7QUFFREcsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxDQUNFLFFBREYsRUFFRSxtQkFGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUV6QixHQUFHLElBQUk7QUFDTCxhQUFPLEtBQUtELFdBQUwsQ0FBaUJDLEdBQWpCLENBQVA7QUFDRCxLQU5IO0FBUUQ7O0FBcEM0Qzs7O2VBdUNoQ0gsVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5cbmV4cG9ydCBjbGFzcyBQdXJnZVJvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuICBoYW5kbGVQdXJnZShyZXEpIHtcbiAgICBpZiAocmVxLmF1dGguaXNSZWFkT25seSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICBcInJlYWQtb25seSBtYXN0ZXJLZXkgaXNuJ3QgYWxsb3dlZCB0byBwdXJnZSBhIHNjaGVtYS5cIlxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2VcbiAgICAgIC5wdXJnZUNvbGxlY3Rpb24ocmVxLnBhcmFtcy5jbGFzc05hbWUpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHZhciBjYWNoZUFkYXB0ZXIgPSByZXEuY29uZmlnLmNhY2hlQ29udHJvbGxlcjtcbiAgICAgICAgaWYgKHJlcS5wYXJhbXMuY2xhc3NOYW1lID09ICdfU2Vzc2lvbicpIHtcbiAgICAgICAgICBjYWNoZUFkYXB0ZXIudXNlci5jbGVhcigpO1xuICAgICAgICB9IGVsc2UgaWYgKHJlcS5wYXJhbXMuY2xhc3NOYW1lID09ICdfUm9sZScpIHtcbiAgICAgICAgICBjYWNoZUFkYXB0ZXIucm9sZS5jbGVhcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB7fSB9O1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmICghZXJyb3IgfHwgKGVycm9yICYmIGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpKSB7XG4gICAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHt9IH07XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnREVMRVRFJyxcbiAgICAgICcvcHVyZ2UvOmNsYXNzTmFtZScsXG4gICAgICBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlUHVyZ2UocmVxKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1cmdlUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/PushRouter.js b/lib/Routers/PushRouter.js new file mode 100644 index 0000000000..2eff9735b6 --- /dev/null +++ b/lib/Routers/PushRouter.js @@ -0,0 +1,92 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.PushRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +var _node = require("parse/node"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class PushRouter extends _PromiseRouter.default { + mountRoutes() { + this.route('POST', '/push', middleware.promiseEnforceMasterKeyAccess, PushRouter.handlePOST); + } + + static handlePOST(req) { + if (req.auth.isReadOnly) { + throw new _node.Parse.Error(_node.Parse.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to send push notifications."); + } + + const pushController = req.config.pushController; + + if (!pushController) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Push controller is not set'); + } + + const where = PushRouter.getQueryCondition(req); + let resolve; + const promise = new Promise(_resolve => { + resolve = _resolve; + }); + let pushStatusId; + pushController.sendPush(req.body, where, req.config, req.auth, objectId => { + pushStatusId = objectId; + resolve({ + headers: { + 'X-Parse-Push-Status-Id': pushStatusId + }, + response: { + result: true + } + }); + }).catch(err => { + req.config.loggerController.error(`_PushStatus ${pushStatusId}: error while sending push`, err); + }); + return promise; + } + /** + * Get query condition from the request body. + * @param {Object} req A request object + * @returns {Object} The query condition, the where field in a query api call + */ + + + static getQueryCondition(req) { + const body = req.body || {}; + const hasWhere = typeof body.where !== 'undefined'; + const hasChannels = typeof body.channels !== 'undefined'; + let where; + + if (hasWhere && hasChannels) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Channels and query can not be set at the same time.'); + } else if (hasWhere) { + where = body.where; + } else if (hasChannels) { + where = { + channels: { + $in: body.channels + } + }; + } else { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Sending a push requires either "channels" or a "where" query.'); + } + + return where; + } + +} + +exports.PushRouter = PushRouter; +var _default = PushRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1B1c2hSb3V0ZXIuanMiXSwibmFtZXMiOlsiUHVzaFJvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwibWlkZGxld2FyZSIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwiaGFuZGxlUE9TVCIsInJlcSIsImF1dGgiLCJpc1JlYWRPbmx5IiwiUGFyc2UiLCJFcnJvciIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJwdXNoQ29udHJvbGxlciIsImNvbmZpZyIsIlBVU0hfTUlTQ09ORklHVVJFRCIsIndoZXJlIiwiZ2V0UXVlcnlDb25kaXRpb24iLCJyZXNvbHZlIiwicHJvbWlzZSIsIlByb21pc2UiLCJfcmVzb2x2ZSIsInB1c2hTdGF0dXNJZCIsInNlbmRQdXNoIiwiYm9keSIsIm9iamVjdElkIiwiaGVhZGVycyIsInJlc3BvbnNlIiwicmVzdWx0IiwiY2F0Y2giLCJlcnIiLCJsb2dnZXJDb250cm9sbGVyIiwiZXJyb3IiLCJoYXNXaGVyZSIsImhhc0NoYW5uZWxzIiwiY2hhbm5lbHMiLCIkaW4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFTyxNQUFNQSxVQUFOLFNBQXlCQyxzQkFBekIsQ0FBdUM7QUFDNUNDLEVBQUFBLFdBQVcsR0FBRztBQUNaLFNBQUtDLEtBQUwsQ0FDRSxNQURGLEVBRUUsT0FGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUVMLFVBQVUsQ0FBQ00sVUFKYjtBQU1EOztBQUVELFNBQU9BLFVBQVAsQ0FBa0JDLEdBQWxCLEVBQXVCO0FBQ3JCLFFBQUlBLEdBQUcsQ0FBQ0MsSUFBSixDQUFTQyxVQUFiLEVBQXlCO0FBQ3ZCLFlBQU0sSUFBSUMsWUFBTUMsS0FBVixDQUNKRCxZQUFNQyxLQUFOLENBQVlDLG1CQURSLEVBRUosK0RBRkksQ0FBTjtBQUlEOztBQUNELFVBQU1DLGNBQWMsR0FBR04sR0FBRyxDQUFDTyxNQUFKLENBQVdELGNBQWxDOztBQUNBLFFBQUksQ0FBQ0EsY0FBTCxFQUFxQjtBQUNuQixZQUFNLElBQUlILFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZSSxrQkFEUixFQUVKLDRCQUZJLENBQU47QUFJRDs7QUFFRCxVQUFNQyxLQUFLLEdBQUdoQixVQUFVLENBQUNpQixpQkFBWCxDQUE2QlYsR0FBN0IsQ0FBZDtBQUNBLFFBQUlXLE9BQUo7QUFDQSxVQUFNQyxPQUFPLEdBQUcsSUFBSUMsT0FBSixDQUFZQyxRQUFRLElBQUk7QUFDdENILE1BQUFBLE9BQU8sR0FBR0csUUFBVjtBQUNELEtBRmUsQ0FBaEI7QUFHQSxRQUFJQyxZQUFKO0FBQ0FULElBQUFBLGNBQWMsQ0FDWFUsUUFESCxDQUNZaEIsR0FBRyxDQUFDaUIsSUFEaEIsRUFDc0JSLEtBRHRCLEVBQzZCVCxHQUFHLENBQUNPLE1BRGpDLEVBQ3lDUCxHQUFHLENBQUNDLElBRDdDLEVBQ21EaUIsUUFBUSxJQUFJO0FBQzNESCxNQUFBQSxZQUFZLEdBQUdHLFFBQWY7QUFDQVAsTUFBQUEsT0FBTyxDQUFDO0FBQ05RLFFBQUFBLE9BQU8sRUFBRTtBQUNQLG9DQUEwQko7QUFEbkIsU0FESDtBQUlOSyxRQUFBQSxRQUFRLEVBQUU7QUFDUkMsVUFBQUEsTUFBTSxFQUFFO0FBREE7QUFKSixPQUFELENBQVA7QUFRRCxLQVhILEVBWUdDLEtBWkgsQ0FZU0MsR0FBRyxJQUFJO0FBQ1p2QixNQUFBQSxHQUFHLENBQUNPLE1BQUosQ0FBV2lCLGdCQUFYLENBQTRCQyxLQUE1QixDQUNHLGVBQWNWLFlBQWEsNEJBRDlCLEVBRUVRLEdBRkY7QUFJRCxLQWpCSDtBQWtCQSxXQUFPWCxPQUFQO0FBQ0Q7QUFFRDs7Ozs7OztBQUtBLFNBQU9GLGlCQUFQLENBQXlCVixHQUF6QixFQUE4QjtBQUM1QixVQUFNaUIsSUFBSSxHQUFHakIsR0FBRyxDQUFDaUIsSUFBSixJQUFZLEVBQXpCO0FBQ0EsVUFBTVMsUUFBUSxHQUFHLE9BQU9ULElBQUksQ0FBQ1IsS0FBWixLQUFzQixXQUF2QztBQUNBLFVBQU1rQixXQUFXLEdBQUcsT0FBT1YsSUFBSSxDQUFDVyxRQUFaLEtBQXlCLFdBQTdDO0FBRUEsUUFBSW5CLEtBQUo7O0FBQ0EsUUFBSWlCLFFBQVEsSUFBSUMsV0FBaEIsRUFBNkI7QUFDM0IsWUFBTSxJQUFJeEIsWUFBTUMsS0FBVixDQUNKRCxZQUFNQyxLQUFOLENBQVlJLGtCQURSLEVBRUoscURBRkksQ0FBTjtBQUlELEtBTEQsTUFLTyxJQUFJa0IsUUFBSixFQUFjO0FBQ25CakIsTUFBQUEsS0FBSyxHQUFHUSxJQUFJLENBQUNSLEtBQWI7QUFDRCxLQUZNLE1BRUEsSUFBSWtCLFdBQUosRUFBaUI7QUFDdEJsQixNQUFBQSxLQUFLLEdBQUc7QUFDTm1CLFFBQUFBLFFBQVEsRUFBRTtBQUNSQyxVQUFBQSxHQUFHLEVBQUVaLElBQUksQ0FBQ1c7QUFERjtBQURKLE9BQVI7QUFLRCxLQU5NLE1BTUE7QUFDTCxZQUFNLElBQUl6QixZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUksa0JBRFIsRUFFSiwrREFGSSxDQUFOO0FBSUQ7O0FBQ0QsV0FBT0MsS0FBUDtBQUNEOztBQW5GMkM7OztlQXNGL0JoQixVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgKiBhcyBtaWRkbGV3YXJlIGZyb20gJy4uL21pZGRsZXdhcmVzJztcbmltcG9ydCB7IFBhcnNlIH0gZnJvbSAncGFyc2Uvbm9kZSc7XG5cbmV4cG9ydCBjbGFzcyBQdXNoUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUE9TVCcsXG4gICAgICAnL3B1c2gnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIFB1c2hSb3V0ZXIuaGFuZGxlUE9TVFxuICAgICk7XG4gIH1cblxuICBzdGF0aWMgaGFuZGxlUE9TVChyZXEpIHtcbiAgICBpZiAocmVxLmF1dGguaXNSZWFkT25seSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICBcInJlYWQtb25seSBtYXN0ZXJLZXkgaXNuJ3QgYWxsb3dlZCB0byBzZW5kIHB1c2ggbm90aWZpY2F0aW9ucy5cIlxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgcHVzaENvbnRyb2xsZXIgPSByZXEuY29uZmlnLnB1c2hDb250cm9sbGVyO1xuICAgIGlmICghcHVzaENvbnRyb2xsZXIpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnUHVzaCBjb250cm9sbGVyIGlzIG5vdCBzZXQnXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHdoZXJlID0gUHVzaFJvdXRlci5nZXRRdWVyeUNvbmRpdGlvbihyZXEpO1xuICAgIGxldCByZXNvbHZlO1xuICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZShfcmVzb2x2ZSA9PiB7XG4gICAgICByZXNvbHZlID0gX3Jlc29sdmU7XG4gICAgfSk7XG4gICAgbGV0IHB1c2hTdGF0dXNJZDtcbiAgICBwdXNoQ29udHJvbGxlclxuICAgICAgLnNlbmRQdXNoKHJlcS5ib2R5LCB3aGVyZSwgcmVxLmNvbmZpZywgcmVxLmF1dGgsIG9iamVjdElkID0+IHtcbiAgICAgICAgcHVzaFN0YXR1c0lkID0gb2JqZWN0SWQ7XG4gICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICdYLVBhcnNlLVB1c2gtU3RhdHVzLUlkJzogcHVzaFN0YXR1c0lkLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVzcG9uc2U6IHtcbiAgICAgICAgICAgIHJlc3VsdDogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyLmVycm9yKFxuICAgICAgICAgIGBfUHVzaFN0YXR1cyAke3B1c2hTdGF0dXNJZH06IGVycm9yIHdoaWxlIHNlbmRpbmcgcHVzaGAsXG4gICAgICAgICAgZXJyXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcXVlcnkgY29uZGl0aW9uIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcSBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBxdWVyeSBjb25kaXRpb24sIHRoZSB3aGVyZSBmaWVsZCBpbiBhIHF1ZXJ5IGFwaSBjYWxsXG4gICAqL1xuICBzdGF0aWMgZ2V0UXVlcnlDb25kaXRpb24ocmVxKSB7XG4gICAgY29uc3QgYm9keSA9IHJlcS5ib2R5IHx8IHt9O1xuICAgIGNvbnN0IGhhc1doZXJlID0gdHlwZW9mIGJvZHkud2hlcmUgIT09ICd1bmRlZmluZWQnO1xuICAgIGNvbnN0IGhhc0NoYW5uZWxzID0gdHlwZW9mIGJvZHkuY2hhbm5lbHMgIT09ICd1bmRlZmluZWQnO1xuXG4gICAgbGV0IHdoZXJlO1xuICAgIGlmIChoYXNXaGVyZSAmJiBoYXNDaGFubmVscykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdDaGFubmVscyBhbmQgcXVlcnkgY2FuIG5vdCBiZSBzZXQgYXQgdGhlIHNhbWUgdGltZS4nXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoaGFzV2hlcmUpIHtcbiAgICAgIHdoZXJlID0gYm9keS53aGVyZTtcbiAgICB9IGVsc2UgaWYgKGhhc0NoYW5uZWxzKSB7XG4gICAgICB3aGVyZSA9IHtcbiAgICAgICAgY2hhbm5lbHM6IHtcbiAgICAgICAgICAkaW46IGJvZHkuY2hhbm5lbHMsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgJ1NlbmRpbmcgYSBwdXNoIHJlcXVpcmVzIGVpdGhlciBcImNoYW5uZWxzXCIgb3IgYSBcIndoZXJlXCIgcXVlcnkuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHdoZXJlO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/RolesRouter.js b/lib/Routers/RolesRouter.js new file mode 100644 index 0000000000..10fd6e7942 --- /dev/null +++ b/lib/Routers/RolesRouter.js @@ -0,0 +1,40 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.RolesRouter = void 0; + +var _ClassesRouter = _interopRequireDefault(require("./ClassesRouter")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class RolesRouter extends _ClassesRouter.default { + className() { + return '_Role'; + } + + mountRoutes() { + this.route('GET', '/roles', req => { + return this.handleFind(req); + }); + this.route('GET', '/roles/:objectId', req => { + return this.handleGet(req); + }); + this.route('POST', '/roles', req => { + return this.handleCreate(req); + }); + this.route('PUT', '/roles/:objectId', req => { + return this.handleUpdate(req); + }); + this.route('DELETE', '/roles/:objectId', req => { + return this.handleDelete(req); + }); + } + +} + +exports.RolesRouter = RolesRouter; +var _default = RolesRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1JvbGVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIlJvbGVzUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsIm1vdW50Um91dGVzIiwicm91dGUiLCJyZXEiLCJoYW5kbGVGaW5kIiwiaGFuZGxlR2V0IiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFFTyxNQUFNQSxXQUFOLFNBQTBCQyxzQkFBMUIsQ0FBd0M7QUFDN0NDLEVBQUFBLFNBQVMsR0FBRztBQUNWLFdBQU8sT0FBUDtBQUNEOztBQUVEQyxFQUFBQSxXQUFXLEdBQUc7QUFDWixTQUFLQyxLQUFMLENBQVcsS0FBWCxFQUFrQixRQUFsQixFQUE0QkMsR0FBRyxJQUFJO0FBQ2pDLGFBQU8sS0FBS0MsVUFBTCxDQUFnQkQsR0FBaEIsQ0FBUDtBQUNELEtBRkQ7QUFHQSxTQUFLRCxLQUFMLENBQVcsS0FBWCxFQUFrQixrQkFBbEIsRUFBc0NDLEdBQUcsSUFBSTtBQUMzQyxhQUFPLEtBQUtFLFNBQUwsQ0FBZUYsR0FBZixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUtELEtBQUwsQ0FBVyxNQUFYLEVBQW1CLFFBQW5CLEVBQTZCQyxHQUFHLElBQUk7QUFDbEMsYUFBTyxLQUFLRyxZQUFMLENBQWtCSCxHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUtELEtBQUwsQ0FBVyxLQUFYLEVBQWtCLGtCQUFsQixFQUFzQ0MsR0FBRyxJQUFJO0FBQzNDLGFBQU8sS0FBS0ksWUFBTCxDQUFrQkosR0FBbEIsQ0FBUDtBQUNELEtBRkQ7QUFHQSxTQUFLRCxLQUFMLENBQVcsUUFBWCxFQUFxQixrQkFBckIsRUFBeUNDLEdBQUcsSUFBSTtBQUM5QyxhQUFPLEtBQUtLLFlBQUwsQ0FBa0JMLEdBQWxCLENBQVA7QUFDRCxLQUZEO0FBR0Q7O0FBckI0Qzs7O2VBd0JoQ0wsVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5cbmV4cG9ydCBjbGFzcyBSb2xlc1JvdXRlciBleHRlbmRzIENsYXNzZXNSb3V0ZXIge1xuICBjbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdfUm9sZSc7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3JvbGVzJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUZpbmQocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3JvbGVzLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVHZXQocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy9yb2xlcycsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVDcmVhdGUocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCAnL3JvbGVzLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGUocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdERUxFVEUnLCAnL3JvbGVzLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBSb2xlc1JvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/SchemasRouter.js b/lib/Routers/SchemasRouter.js new file mode 100644 index 0000000000..f566e3ea8f --- /dev/null +++ b/lib/Routers/SchemasRouter.js @@ -0,0 +1,120 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SchemasRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var middleware = _interopRequireWildcard(require("../middlewares")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// schemas.js +var Parse = require('parse/node').Parse, + SchemaController = require('../Controllers/SchemaController'); + +function classNameMismatchResponse(bodyClass, pathClass) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, `Class name mismatch between ${bodyClass} and ${pathClass}.`); +} + +function getAllSchemas(req) { + return req.config.database.loadSchema({ + clearCache: true + }).then(schemaController => schemaController.getAllClasses(true)).then(schemas => ({ + response: { + results: schemas + } + })); +} + +function getOneSchema(req) { + const className = req.params.className; + return req.config.database.loadSchema({ + clearCache: true + }).then(schemaController => schemaController.getOneSchema(className, true)).then(schema => ({ + response: schema + })).catch(error => { + if (error === undefined) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, `Class ${className} does not exist.`); + } else { + throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Database adapter error.'); + } + }); +} + +function createSchema(req) { + if (req.auth.isReadOnly) { + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to create a schema."); + } + + if (req.params.className && req.body.className) { + if (req.params.className != req.body.className) { + return classNameMismatchResponse(req.body.className, req.params.className); + } + } + + const className = req.params.className || req.body.className; + + if (!className) { + throw new Parse.Error(135, `POST ${req.path} needs a class name.`); + } + + return req.config.database.loadSchema({ + clearCache: true + }).then(schema => schema.addClassIfNotExists(className, req.body.fields, req.body.classLevelPermissions, req.body.indexes)).then(schema => ({ + response: schema + })); +} + +function modifySchema(req) { + if (req.auth.isReadOnly) { + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to update a schema."); + } + + if (req.body.className && req.body.className != req.params.className) { + return classNameMismatchResponse(req.body.className, req.params.className); + } + + const submittedFields = req.body.fields || {}; + const className = req.params.className; + return req.config.database.loadSchema({ + clearCache: true + }).then(schema => schema.updateClass(className, submittedFields, req.body.classLevelPermissions, req.body.indexes, req.config.database)).then(result => ({ + response: result + })); +} + +const deleteSchema = req => { + if (req.auth.isReadOnly) { + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, "read-only masterKey isn't allowed to delete a schema."); + } + + if (!SchemaController.classNameIsValid(req.params.className)) { + throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, SchemaController.invalidClassNameMessage(req.params.className)); + } + + return req.config.database.deleteSchema(req.params.className).then(() => ({ + response: {} + })); +}; + +class SchemasRouter extends _PromiseRouter.default { + mountRoutes() { + this.route('GET', '/schemas', middleware.promiseEnforceMasterKeyAccess, getAllSchemas); + this.route('GET', '/schemas/:className', middleware.promiseEnforceMasterKeyAccess, getOneSchema); + this.route('POST', '/schemas', middleware.promiseEnforceMasterKeyAccess, createSchema); + this.route('POST', '/schemas/:className', middleware.promiseEnforceMasterKeyAccess, createSchema); + this.route('PUT', '/schemas/:className', middleware.promiseEnforceMasterKeyAccess, modifySchema); + this.route('DELETE', '/schemas/:className', middleware.promiseEnforceMasterKeyAccess, deleteSchema); + } + +} + +exports.SchemasRouter = SchemasRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1NjaGVtYXNSb3V0ZXIuanMiXSwibmFtZXMiOlsiUGFyc2UiLCJyZXF1aXJlIiwiU2NoZW1hQ29udHJvbGxlciIsImNsYXNzTmFtZU1pc21hdGNoUmVzcG9uc2UiLCJib2R5Q2xhc3MiLCJwYXRoQ2xhc3MiLCJFcnJvciIsIklOVkFMSURfQ0xBU1NfTkFNRSIsImdldEFsbFNjaGVtYXMiLCJyZXEiLCJjb25maWciLCJkYXRhYmFzZSIsImxvYWRTY2hlbWEiLCJjbGVhckNhY2hlIiwidGhlbiIsInNjaGVtYUNvbnRyb2xsZXIiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hcyIsInJlc3BvbnNlIiwicmVzdWx0cyIsImdldE9uZVNjaGVtYSIsImNsYXNzTmFtZSIsInBhcmFtcyIsInNjaGVtYSIsImNhdGNoIiwiZXJyb3IiLCJ1bmRlZmluZWQiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJjcmVhdGVTY2hlbWEiLCJhdXRoIiwiaXNSZWFkT25seSIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJib2R5IiwicGF0aCIsImFkZENsYXNzSWZOb3RFeGlzdHMiLCJmaWVsZHMiLCJjbGFzc0xldmVsUGVybWlzc2lvbnMiLCJpbmRleGVzIiwibW9kaWZ5U2NoZW1hIiwic3VibWl0dGVkRmllbGRzIiwidXBkYXRlQ2xhc3MiLCJyZXN1bHQiLCJkZWxldGVTY2hlbWEiLCJjbGFzc05hbWVJc1ZhbGlkIiwiaW52YWxpZENsYXNzTmFtZU1lc3NhZ2UiLCJTY2hlbWFzUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsIm1vdW50Um91dGVzIiwicm91dGUiLCJtaWRkbGV3YXJlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFLQTs7QUFDQTs7Ozs7Ozs7QUFOQTtBQUVBLElBQUlBLEtBQUssR0FBR0MsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkQsS0FBbEM7QUFBQSxJQUNFRSxnQkFBZ0IsR0FBR0Qs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LFNBQUt3QyxLQUFMLENBQ0UsS0FERixFQUVFLHFCQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRTlCLFlBSkY7QUFNQSxTQUFLNEIsS0FBTCxDQUNFLE1BREYsRUFFRSxVQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRXRCLFlBSkY7QUFNQSxTQUFLb0IsS0FBTCxDQUNFLE1BREYsRUFFRSxxQkFGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUV0QixZQUpGO0FBTUEsU0FBS29CLEtBQUwsQ0FDRSxLQURGLEVBRUUscUJBRkYsRUFHRUMsVUFBVSxDQUFDQyw2QkFIYixFQUlFWixZQUpGO0FBTUEsU0FBS1UsS0FBTCxDQUNFLFFBREYsRUFFRSxxQkFGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUVSLFlBSkY7QUFNRDs7QUF0QzhDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gc2NoZW1hcy5qc1xuXG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2UsXG4gIFNjaGVtYUNvbnRyb2xsZXIgPSByZXF1aXJlKCcuLi9Db250cm9sbGVycy9TY2hlbWFDb250cm9sbGVyJyk7XG5cbmltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5cbmZ1bmN0aW9uIGNsYXNzTmFtZU1pc21hdGNoUmVzcG9uc2UoYm9keUNsYXNzLCBwYXRoQ2xhc3MpIHtcbiAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgIFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSxcbiAgICBgQ2xhc3MgbmFtZSBtaXNtYXRjaCBiZXR3ZWVuICR7Ym9keUNsYXNzfSBhbmQgJHtwYXRoQ2xhc3N9LmBcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2V0QWxsU2NoZW1hcyhyZXEpIHtcbiAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2VcbiAgICAubG9hZFNjaGVtYSh7IGNsZWFyQ2FjaGU6IHRydWUgfSlcbiAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuZ2V0QWxsQ2xhc3Nlcyh0cnVlKSlcbiAgICAudGhlbihzY2hlbWFzID0+ICh7IHJlc3BvbnNlOiB7IHJlc3VsdHM6IHNjaGVtYXMgfSB9KSk7XG59XG5cbmZ1bmN0aW9uIGdldE9uZVNjaGVtYShyZXEpIHtcbiAgY29uc3QgY2xhc3NOYW1lID0gcmVxLnBhcmFtcy5jbGFzc05hbWU7XG4gIHJldHVybiByZXEuY29uZmlnLmRhdGFiYXNlXG4gICAgLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlIH0pXG4gICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYShjbGFzc05hbWUsIHRydWUpKVxuICAgIC50aGVuKHNjaGVtYSA9PiAoeyByZXNwb25zZTogc2NoZW1hIH0pKVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICAgIGBDbGFzcyAke2NsYXNzTmFtZX0gZG9lcyBub3QgZXhpc3QuYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgICAnRGF0YWJhc2UgYWRhcHRlciBlcnJvci4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVNjaGVtYShyZXEpIHtcbiAgaWYgKHJlcS5hdXRoLmlzUmVhZE9ubHkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgXCJyZWFkLW9ubHkgbWFzdGVyS2V5IGlzbid0IGFsbG93ZWQgdG8gY3JlYXRlIGEgc2NoZW1hLlwiXG4gICAgKTtcbiAgfVxuICBpZiAocmVxLnBhcmFtcy5jbGFzc05hbWUgJiYgcmVxLmJvZHkuY2xhc3NOYW1lKSB7XG4gICAgaWYgKHJlcS5wYXJhbXMuY2xhc3NOYW1lICE9IHJlcS5ib2R5LmNsYXNzTmFtZSkge1xuICAgICAgcmV0dXJuIGNsYXNzTmFtZU1pc21hdGNoUmVzcG9uc2UoXG4gICAgICAgIHJlcS5ib2R5LmNsYXNzTmFtZSxcbiAgICAgICAgcmVxLnBhcmFtcy5jbGFzc05hbWVcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgY2xhc3NOYW1lID0gcmVxLnBhcmFtcy5jbGFzc05hbWUgfHwgcmVxLmJvZHkuY2xhc3NOYW1lO1xuICBpZiAoIWNsYXNzTmFtZSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxMzUsIGBQT1NUICR7cmVxLnBhdGh9IG5lZWRzIGEgY2xhc3MgbmFtZS5gKTtcbiAgfVxuXG4gIHJldHVybiByZXEuY29uZmlnLmRhdGFiYXNlXG4gICAgLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlIH0pXG4gICAgLnRoZW4oc2NoZW1hID0+XG4gICAgICBzY2hlbWEuYWRkQ2xhc3NJZk5vdEV4aXN0cyhcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICByZXEuYm9keS5maWVsZHMsXG4gICAgICAgIHJlcS5ib2R5LmNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgICAgICAgcmVxLmJvZHkuaW5kZXhlc1xuICAgICAgKVxuICAgIClcbiAgICAudGhlbihzY2hlbWEgPT4gKHsgcmVzcG9uc2U6IHNjaGVtYSB9KSk7XG59XG5cbmZ1bmN0aW9uIG1vZGlmeVNjaGVtYShyZXEpIHtcbiAgaWYgKHJlcS5hdXRoLmlzUmVhZE9ubHkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgXCJyZWFkLW9ubHkgbWFzdGVyS2V5IGlzbid0IGFsbG93ZWQgdG8gdXBkYXRlIGEgc2NoZW1hLlwiXG4gICAgKTtcbiAgfVxuICBpZiAocmVxLmJvZHkuY2xhc3NOYW1lICYmIHJlcS5ib2R5LmNsYXNzTmFtZSAhPSByZXEucGFyYW1zLmNsYXNzTmFtZSkge1xuICAgIHJldHVybiBjbGFzc05hbWVNaXNtYXRjaFJlc3BvbnNlKHJlcS5ib2R5LmNsYXNzTmFtZSwgcmVxLnBhcmFtcy5jbGFzc05hbWUpO1xuICB9XG5cbiAgY29uc3Qgc3VibWl0dGVkRmllbGRzID0gcmVxLmJvZHkuZmllbGRzIHx8IHt9O1xuICBjb25zdCBjbGFzc05hbWUgPSByZXEucGFyYW1zLmNsYXNzTmFtZTtcblxuICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZVxuICAgIC5sb2FkU2NoZW1hKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KVxuICAgIC50aGVuKHNjaGVtYSA9PlxuICAgICAgc2NoZW1hLnVwZGF0ZUNsYXNzKFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHN1Ym1pdHRlZEZpZWxkcyxcbiAgICAgICAgcmVxLmJvZHkuY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgICByZXEuYm9keS5pbmRleGVzLFxuICAgICAgICByZXEuY29uZmlnLmRhdGFiYXNlXG4gICAgICApXG4gICAgKVxuICAgIC50aGVuKHJlc3VsdCA9PiAoeyByZXNwb25zZTogcmVzdWx0IH0pKTtcbn1cblxuY29uc3QgZGVsZXRlU2NoZW1hID0gcmVxID0+IHtcbiAgaWYgKHJlcS5hdXRoLmlzUmVhZE9ubHkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgXCJyZWFkLW9ubHkgbWFzdGVyS2V5IGlzbid0IGFsbG93ZWQgdG8gZGVsZXRlIGEgc2NoZW1hLlwiXG4gICAgKTtcbiAgfVxuICBpZiAoIVNjaGVtYUNvbnRyb2xsZXIuY2xhc3NOYW1lSXNWYWxpZChyZXEucGFyYW1zLmNsYXNzTmFtZSkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICBTY2hlbWFDb250cm9sbGVyLmludmFsaWRDbGFzc05hbWVNZXNzYWdlKHJlcS5wYXJhbXMuY2xhc3NOYW1lKVxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2VcbiAgICAuZGVsZXRlU2NoZW1hKHJlcS5wYXJhbXMuY2xhc3NOYW1lKVxuICAgIC50aGVuKCgpID0+ICh7IHJlc3BvbnNlOiB7fSB9KSk7XG59O1xuXG5leHBvcnQgY2xhc3MgU2NoZW1hc1JvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL3NjaGVtYXMnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIGdldEFsbFNjaGVtYXNcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnR0VUJyxcbiAgICAgICcvc2NoZW1hcy86Y2xhc3NOYW1lJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICBnZXRPbmVTY2hlbWFcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUE9TVCcsXG4gICAgICAnL3NjaGVtYXMnLFxuICAgICAgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIGNyZWF0ZVNjaGVtYVxuICAgICk7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQT1NUJyxcbiAgICAgICcvc2NoZW1hcy86Y2xhc3NOYW1lJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICBjcmVhdGVTY2hlbWFcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUFVUJyxcbiAgICAgICcvc2NoZW1hcy86Y2xhc3NOYW1lJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICBtb2RpZnlTY2hlbWFcbiAgICApO1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnREVMRVRFJyxcbiAgICAgICcvc2NoZW1hcy86Y2xhc3NOYW1lJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICBkZWxldGVTY2hlbWFcbiAgICApO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/SessionsRouter.js b/lib/Routers/SessionsRouter.js new file mode 100644 index 0000000000..1b9802db62 --- /dev/null +++ b/lib/Routers/SessionsRouter.js @@ -0,0 +1,107 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.SessionsRouter = void 0; + +var _ClassesRouter = _interopRequireDefault(require("./ClassesRouter")); + +var _node = _interopRequireDefault(require("parse/node")); + +var _rest = _interopRequireDefault(require("../rest")); + +var _Auth = _interopRequireDefault(require("../Auth")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SessionsRouter extends _ClassesRouter.default { + className() { + return '_Session'; + } + + handleMe(req) { + // TODO: Verify correct behavior + if (!req.info || !req.info.sessionToken) { + throw new _node.default.Error(_node.default.Error.INVALID_SESSION_TOKEN, 'Session token required.'); + } + + return _rest.default.find(req.config, _Auth.default.master(req.config), '_Session', { + sessionToken: req.info.sessionToken + }, undefined, req.info.clientSDK).then(response => { + if (!response.results || response.results.length == 0) { + throw new _node.default.Error(_node.default.Error.INVALID_SESSION_TOKEN, 'Session token not found.'); + } + + return { + response: response.results[0] + }; + }); + } + + handleUpdateToRevocableSession(req) { + const config = req.config; + const user = req.auth.user; // Issue #2720 + // Calling without a session token would result in a not found user + + if (!user) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'invalid session'); + } + + const { + sessionData, + createSession + } = _Auth.default.createSession(config, { + userId: user.id, + createdWith: { + action: 'upgrade' + }, + installationId: req.auth.installationId + }); + + return createSession().then(() => { + // delete the session token, use the db to skip beforeSave + return config.database.update('_User', { + objectId: user.id + }, { + sessionToken: { + __op: 'Delete' + } + }); + }).then(() => { + return Promise.resolve({ + response: sessionData + }); + }); + } + + mountRoutes() { + this.route('GET', '/sessions/me', req => { + return this.handleMe(req); + }); + this.route('GET', '/sessions', req => { + return this.handleFind(req); + }); + this.route('GET', '/sessions/:objectId', req => { + return this.handleGet(req); + }); + this.route('POST', '/sessions', req => { + return this.handleCreate(req); + }); + this.route('PUT', '/sessions/:objectId', req => { + return this.handleUpdate(req); + }); + this.route('DELETE', '/sessions/:objectId', req => { + return this.handleDelete(req); + }); + this.route('POST', '/upgradeToRevocableSession', req => { + return this.handleUpdateToRevocableSession(req); + }); + } + +} + +exports.SessionsRouter = SessionsRouter; +var _default = SessionsRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1Nlc3Npb25zUm91dGVyLmpzIl0sIm5hbWVzIjpbIlNlc3Npb25zUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsImhhbmRsZU1lIiwicmVxIiwiaW5mbyIsInNlc3Npb25Ub2tlbiIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJyZXN0IiwiZmluZCIsImNvbmZpZyIsIkF1dGgiLCJtYXN0ZXIiLCJ1bmRlZmluZWQiLCJjbGllbnRTREsiLCJ0aGVuIiwicmVzcG9uc2UiLCJyZXN1bHRzIiwibGVuZ3RoIiwiaGFuZGxlVXBkYXRlVG9SZXZvY2FibGVTZXNzaW9uIiwidXNlciIsImF1dGgiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwic2Vzc2lvbkRhdGEiLCJjcmVhdGVTZXNzaW9uIiwidXNlcklkIiwiaWQiLCJjcmVhdGVkV2l0aCIsImFjdGlvbiIsImluc3RhbGxhdGlvbklkIiwiZGF0YWJhc2UiLCJ1cGRhdGUiLCJvYmplY3RJZCIsIl9fb3AiLCJQcm9taXNlIiwicmVzb2x2ZSIsIm1vdW50Um91dGVzIiwicm91dGUiLCJoYW5kbGVGaW5kIiwiaGFuZGxlR2V0IiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFTyxNQUFNQSxjQUFOLFNBQTZCQyxzQkFBN0IsQ0FBMkM7QUFDaERDLEVBQUFBLFNBQVMsR0FBRztBQUNWLFdBQU8sVUFBUDtBQUNEOztBQUVEQyxFQUFBQSxRQUFRLENBQUNDLEdBQUQsRUFBTTtBQUNaO0FBQ0EsUUFBSSxDQUFDQSxHQUFHLENBQUNDLElBQUwsSUFBYSxDQUFDRCxHQUFHLENBQUNDLElBQUosQ0FBU0MsWUFBM0IsRUFBeUM7QUFDdkMsWUFBTSxJQUFJQyxjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUMscUJBRFIsRUFFSix5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RkQ7QUFHQSxTQUFLbUMsS0FBTCxDQUFXLEtBQVgsRUFBa0IscUJBQWxCLEVBQXlDbkMsR0FBRyxJQUFJO0FBQzlDLGFBQU8sS0FBS3VDLFlBQUwsQ0FBa0J2QyxHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttQyxLQUFMLENBQVcsUUFBWCxFQUFxQixxQkFBckIsRUFBNENuQyxHQUFHLElBQUk7QUFDakQsYUFBTyxLQUFLd0MsWUFBTCxDQUFrQnhDLEdBQWxCLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS21DLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLDRCQUFuQixFQUFpRG5DLEdBQUcsSUFBSTtBQUN0RCxhQUFPLEtBQUtpQiw4QkFBTCxDQUFvQ2pCLEdBQXBDLENBQVA7QUFDRCxLQUZEO0FBR0Q7O0FBM0YrQzs7O2VBOEZuQ0osYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4uL0F1dGgnO1xuXG5leHBvcnQgY2xhc3MgU2Vzc2lvbnNSb3V0ZXIgZXh0ZW5kcyBDbGFzc2VzUm91dGVyIHtcbiAgY2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnX1Nlc3Npb24nO1xuICB9XG5cbiAgaGFuZGxlTWUocmVxKSB7XG4gICAgLy8gVE9ETzogVmVyaWZ5IGNvcnJlY3QgYmVoYXZpb3JcbiAgICBpZiAoIXJlcS5pbmZvIHx8ICFyZXEuaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAnU2Vzc2lvbiB0b2tlbiByZXF1aXJlZC4nXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdFxuICAgICAgLmZpbmQoXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIEF1dGgubWFzdGVyKHJlcS5jb25maWcpLFxuICAgICAgICAnX1Nlc3Npb24nLFxuICAgICAgICB7IHNlc3Npb25Ub2tlbjogcmVxLmluZm8uc2Vzc2lvblRva2VuIH0sXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgICApXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIGlmICghcmVzcG9uc2UucmVzdWx0cyB8fCByZXNwb25zZS5yZXN1bHRzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICAgJ1Nlc3Npb24gdG9rZW4gbm90IGZvdW5kLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVzcG9uc2U6IHJlc3BvbnNlLnJlc3VsdHNbMF0sXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZVVwZGF0ZVRvUmV2b2NhYmxlU2Vzc2lvbihyZXEpIHtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuICAgIGNvbnN0IHVzZXIgPSByZXEuYXV0aC51c2VyO1xuICAgIC8vIElzc3VlICMyNzIwXG4gICAgLy8gQ2FsbGluZyB3aXRob3V0IGEgc2Vzc2lvbiB0b2tlbiB3b3VsZCByZXN1bHQgaW4gYSBub3QgZm91bmQgdXNlclxuICAgIGlmICghdXNlcikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdpbnZhbGlkIHNlc3Npb24nKTtcbiAgICB9XG4gICAgY29uc3QgeyBzZXNzaW9uRGF0YSwgY3JlYXRlU2Vzc2lvbiB9ID0gQXV0aC5jcmVhdGVTZXNzaW9uKGNvbmZpZywge1xuICAgICAgdXNlcklkOiB1c2VyLmlkLFxuICAgICAgY3JlYXRlZFdpdGg6IHtcbiAgICAgICAgYWN0aW9uOiAndXBncmFkZScsXG4gICAgICB9LFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5hdXRoLmluc3RhbGxhdGlvbklkLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNyZWF0ZVNlc3Npb24oKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBkZWxldGUgdGhlIHNlc3Npb24gdG9rZW4sIHVzZSB0aGUgZGIgdG8gc2tpcCBiZWZvcmVTYXZlXG4gICAgICAgIHJldHVybiBjb25maWcuZGF0YWJhc2UudXBkYXRlKFxuICAgICAgICAgICdfVXNlcicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgb2JqZWN0SWQ6IHVzZXIuaWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzZXNzaW9uVG9rZW46IHsgX19vcDogJ0RlbGV0ZScgfSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgcmVzcG9uc2U6IHNlc3Npb25EYXRhIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3Nlc3Npb25zL21lJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZU1lKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9zZXNzaW9ucycsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9zZXNzaW9ucy86b2JqZWN0SWQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlR2V0KHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvc2Vzc2lvbnMnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlQ3JlYXRlKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUFVUJywgJy9zZXNzaW9ucy86b2JqZWN0SWQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlVXBkYXRlKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnREVMRVRFJywgJy9zZXNzaW9ucy86b2JqZWN0SWQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRGVsZXRlKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvdXBncmFkZVRvUmV2b2NhYmxlU2Vzc2lvbicsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGVUb1Jldm9jYWJsZVNlc3Npb24ocmVxKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBTZXNzaW9uc1JvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/UsersRouter.js b/lib/Routers/UsersRouter.js new file mode 100644 index 0000000000..efe550c2a9 --- /dev/null +++ b/lib/Routers/UsersRouter.js @@ -0,0 +1,421 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.UsersRouter = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _Config = _interopRequireDefault(require("../Config")); + +var _AccountLockout = _interopRequireDefault(require("../AccountLockout")); + +var _ClassesRouter = _interopRequireDefault(require("./ClassesRouter")); + +var _rest = _interopRequireDefault(require("../rest")); + +var _Auth = _interopRequireDefault(require("../Auth")); + +var _password = _interopRequireDefault(require("../password")); + +var _triggers = require("../triggers"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// These methods handle the User-related routes. +class UsersRouter extends _ClassesRouter.default { + className() { + return '_User'; + } + /** + * Removes all "_" prefixed properties from an object, except "__type" + * @param {Object} obj An object. + */ + + + static removeHiddenProperties(obj) { + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + // Regexp comes from Parse.Object.prototype.validate + if (key !== '__type' && !/^[A-Za-z][0-9A-Za-z_]*$/.test(key)) { + delete obj[key]; + } + } + } + } + /** + * Validates a password request in login and verifyPassword + * @param {Object} req The request + * @returns {Object} User object + * @private + */ + + + _authenticateUserFromRequest(req) { + return new Promise((resolve, reject) => { + // Use query parameters instead if provided in url + let payload = req.body; + + if (!payload.username && req.query.username || !payload.email && req.query.email) { + payload = req.query; + } + + const { + username, + email, + password + } = payload; // TODO: use the right error codes / descriptions. + + if (!username && !email) { + throw new _node.default.Error(_node.default.Error.USERNAME_MISSING, 'username/email is required.'); + } + + if (!password) { + throw new _node.default.Error(_node.default.Error.PASSWORD_MISSING, 'password is required.'); + } + + if (typeof password !== 'string' || email && typeof email !== 'string' || username && typeof username !== 'string') { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + + let user; + let isValidPassword = false; + let query; + + if (email && username) { + query = { + email, + username + }; + } else if (email) { + query = { + email + }; + } else { + query = { + $or: [{ + username + }, { + email: username + }] + }; + } + + return req.config.database.find('_User', query).then(results => { + if (!results.length) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + + if (results.length > 1) { + // corner case where user1 has username == user2 email + req.config.loggerController.warn("There is a user which email is the same as another user's username, logging in based on username"); + user = results.filter(user => user.username === username)[0]; + } else { + user = results[0]; + } + + return _password.default.compare(password, user.password); + }).then(correct => { + isValidPassword = correct; + const accountLockoutPolicy = new _AccountLockout.default(user, req.config); + return accountLockoutPolicy.handleLoginAttempt(isValidPassword); + }).then(() => { + if (!isValidPassword) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } // Ensure the user isn't locked out + // A locked out user won't be able to login + // To lock a user out, just set the ACL to `masterKey` only ({}). + // Empty ACL is OK + + + if (!req.auth.isMaster && user.ACL && Object.keys(user.ACL).length == 0) { + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + + if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) { + throw new _node.default.Error(_node.default.Error.EMAIL_NOT_FOUND, 'User email is not verified.'); + } + + delete user.password; // Sometimes the authData still has null on that keys + // https://github.com/parse-community/parse-server/issues/935 + + if (user.authData) { + Object.keys(user.authData).forEach(provider => { + if (user.authData[provider] === null) { + delete user.authData[provider]; + } + }); + + if (Object.keys(user.authData).length == 0) { + delete user.authData; + } + } + + return resolve(user); + }).catch(error => { + return reject(error); + }); + }); + } + + handleMe(req) { + if (!req.info || !req.info.sessionToken) { + throw new _node.default.Error(_node.default.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); + } + + const sessionToken = req.info.sessionToken; + return _rest.default.find(req.config, _Auth.default.master(req.config), '_Session', { + sessionToken + }, { + include: 'user' + }, req.info.clientSDK).then(response => { + if (!response.results || response.results.length == 0 || !response.results[0].user) { + throw new _node.default.Error(_node.default.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); + } else { + const user = response.results[0].user; // Send token back on the login, because SDKs expect that. + + user.sessionToken = sessionToken; // Remove hidden properties. + + UsersRouter.removeHiddenProperties(user); + return { + response: user + }; + } + }); + } + + async handleLogIn(req) { + const user = await this._authenticateUserFromRequest(req); // handle password expiry policy + + if (req.config.passwordPolicy && req.config.passwordPolicy.maxPasswordAge) { + let changedAt = user._password_changed_at; + + if (!changedAt) { + // password was created before expiry policy was enabled. + // simply update _User object so that it will start enforcing from now + changedAt = new Date(); + req.config.database.update('_User', { + username: user.username + }, { + _password_changed_at: _node.default._encode(changedAt) + }); + } else { + // check whether the password has expired + if (changedAt.__type == 'Date') { + changedAt = new Date(changedAt.iso); + } // Calculate the expiry time. + + + const expiresAt = new Date(changedAt.getTime() + 86400000 * req.config.passwordPolicy.maxPasswordAge); + if (expiresAt < new Date()) // fail of current time is past password expiry time + throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Your password has expired. Please reset your password.'); + } + } // Remove hidden properties. + + + UsersRouter.removeHiddenProperties(user); + req.config.filesController.expandFilesInObject(req.config, user); // Before login trigger; throws if failure + + await (0, _triggers.maybeRunTrigger)(_triggers.Types.beforeLogin, req.auth, _node.default.User.fromJSON(Object.assign({ + className: '_User' + }, user)), null, req.config); + + const { + sessionData, + createSession + } = _Auth.default.createSession(req.config, { + userId: user.objectId, + createdWith: { + action: 'login', + authProvider: 'password' + }, + installationId: req.info.installationId + }); + + user.sessionToken = sessionData.sessionToken; + await createSession(); + return { + response: user + }; + } + + handleVerifyPassword(req) { + return this._authenticateUserFromRequest(req).then(user => { + // Remove hidden properties. + UsersRouter.removeHiddenProperties(user); + return { + response: user + }; + }).catch(error => { + throw error; + }); + } + + handleLogOut(req) { + const success = { + response: {} + }; + + if (req.info && req.info.sessionToken) { + return _rest.default.find(req.config, _Auth.default.master(req.config), '_Session', { + sessionToken: req.info.sessionToken + }, undefined, req.info.clientSDK).then(records => { + if (records.results && records.results.length) { + return _rest.default.del(req.config, _Auth.default.master(req.config), '_Session', records.results[0].objectId).then(() => { + this._runAfterLogoutTrigger(req, records.results[0]); + + return Promise.resolve(success); + }); + } + + return Promise.resolve(success); + }); + } + + return Promise.resolve(success); + } + + _runAfterLogoutTrigger(req, session) { + // After logout trigger + (0, _triggers.maybeRunTrigger)(_triggers.Types.afterLogout, req.auth, _node.default.Session.fromJSON(Object.assign({ + className: '_Session' + }, session)), null, req.config); + } + + _throwOnBadEmailConfig(req) { + try { + _Config.default.validateEmailConfiguration({ + emailAdapter: req.config.userController.adapter, + appName: req.config.appName, + publicServerURL: req.config.publicServerURL, + emailVerifyTokenValidityDuration: req.config.emailVerifyTokenValidityDuration + }); + } catch (e) { + if (typeof e === 'string') { + // Maybe we need a Bad Configuration error, but the SDKs won't understand it. For now, Internal Server Error. + throw new _node.default.Error(_node.default.Error.INTERNAL_SERVER_ERROR, 'An appName, publicServerURL, and emailAdapter are required for password reset and email verification functionality.'); + } else { + throw e; + } + } + } + + handleResetRequest(req) { + this._throwOnBadEmailConfig(req); + + const { + email + } = req.body; + + if (!email) { + throw new _node.default.Error(_node.default.Error.EMAIL_MISSING, 'you must provide an email'); + } + + if (typeof email !== 'string') { + throw new _node.default.Error(_node.default.Error.INVALID_EMAIL_ADDRESS, 'you must provide a valid email string'); + } + + const userController = req.config.userController; + return userController.sendPasswordResetEmail(email).then(() => { + return Promise.resolve({ + response: {} + }); + }, err => { + if (err.code === _node.default.Error.OBJECT_NOT_FOUND) { + // Return success so that this endpoint can't + // be used to enumerate valid emails + return Promise.resolve({ + response: {} + }); + } else { + throw err; + } + }); + } + + handleVerificationEmailRequest(req) { + this._throwOnBadEmailConfig(req); + + const { + email + } = req.body; + + if (!email) { + throw new _node.default.Error(_node.default.Error.EMAIL_MISSING, 'you must provide an email'); + } + + if (typeof email !== 'string') { + throw new _node.default.Error(_node.default.Error.INVALID_EMAIL_ADDRESS, 'you must provide a valid email string'); + } + + return req.config.database.find('_User', { + email: email + }).then(results => { + if (!results.length || results.length < 1) { + throw new _node.default.Error(_node.default.Error.EMAIL_NOT_FOUND, `No user found with email ${email}`); + } + + const user = results[0]; // remove password field, messes with saving on postgres + + delete user.password; + + if (user.emailVerified) { + throw new _node.default.Error(_node.default.Error.OTHER_CAUSE, `Email ${email} is already verified.`); + } + + const userController = req.config.userController; + return userController.regenerateEmailVerifyToken(user).then(() => { + userController.sendVerificationEmail(user); + return { + response: {} + }; + }); + }); + } + + mountRoutes() { + this.route('GET', '/users', req => { + return this.handleFind(req); + }); + this.route('POST', '/users', req => { + return this.handleCreate(req); + }); + this.route('GET', '/users/me', req => { + return this.handleMe(req); + }); + this.route('GET', '/users/:objectId', req => { + return this.handleGet(req); + }); + this.route('PUT', '/users/:objectId', req => { + return this.handleUpdate(req); + }); + this.route('DELETE', '/users/:objectId', req => { + return this.handleDelete(req); + }); + this.route('GET', '/login', req => { + return this.handleLogIn(req); + }); + this.route('POST', '/login', req => { + return this.handleLogIn(req); + }); + this.route('POST', '/logout', req => { + return this.handleLogOut(req); + }); + this.route('POST', '/requestPasswordReset', req => { + return this.handleResetRequest(req); + }); + this.route('POST', '/verificationEmailRequest', req => { + return this.handleVerificationEmailRequest(req); + }); + this.route('GET', '/verifyPassword', req => { + return this.handleVerifyPassword(req); + }); + } + +} + +exports.UsersRouter = UsersRouter; +var _default = UsersRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1VzZXJzUm91dGVyLmpzIl0sIm5hbWVzIjpbIlVzZXJzUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsInJlbW92ZUhpZGRlblByb3BlcnRpZXMiLCJvYmoiLCJrZXkiLCJPYmplY3QiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJ0ZXN0IiwiX2F1dGhlbnRpY2F0ZVVzZXJGcm9tUmVxdWVzdCIsInJlcSIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwicGF5bG9hZCIsImJvZHkiLCJ1c2VybmFtZSIsInF1ZXJ5IiwiZW1haWwiLCJwYXNzd29yZCIsIlBhcnNlIiwiRXJyb3IiLCJVU0VSTkFNRV9NSVNTSU5HIiwiUEFTU1dPUkRfTUlTU0lORyIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ1c2VyIiwiaXNWYWxpZFBhc3N3b3JkIiwiJG9yIiwiY29uZmlnIiwiZGF0YWJhc2UiLCJmaW5kIiwidGhlbiIsInJlc3VsdHMiLCJsZW5ndGgiLCJsb2dnZXJDb250cm9sbGVyIiwid2FybiIsImZpbHRlciIsInBhc3N3b3JkQ3J5cHRvIiwiY29tcGFyZSIsImNvcnJlY3QiLCJhY2NvdW50TG9ja291dFBvbGljeSIsIkFjY291bnRMb2Nrb3V0IiwiaGFuZGxlTG9naW5BdHRlbXB0IiwiYXV0aCIsImlzTWFzdGVyIiwiQUNMIiwia2V5cyIsInZlcmlmeVVzZXJFbWFpbHMiLCJwcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsIiwiZW1haWxWZXJpZmllZCIsIkVNQUlMX05PVF9GT1VORCIsImF1dGhEYXRhIiwiZm9yRWFjaCIsInByb3ZpZGVyIiwiY2F0Y2giLCJlcnJvciIsImhhbmRsZU1lIiwiaW5mbyIsInNlc3Npb25Ub2tlbiIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsInJlc3QiLCJBdXRoIiwibWFzdGVyIiwiaW5jbHVkZSIsImNsaWVudFNESyIsInJlc3BvbnNlIiwiaGFuZGxlTG9nSW4iLCJwYXNzd29yZFBvbGljeSIsIm1heFBhc3N3b3JkQWdlIiwiY2hhbmdlZEF0IiwiX3Bhc3N3b3JkX2NoYW5nZWRfYXQiLCJEYXRlIiwidXBkYXRlIiwiX2VuY29kZSIsIl9fdHlwZSIsImlzbyIsImV4cGlyZXNBdCIsImdldFRpbWUiLCJmaWxlc0NvbnRyb2xsZXIiLCJleHBhbmRGaWxlc0luT2JqZWN0IiwiVHJpZ2dlclR5cGVzIiwiYmVmb3JlTG9naW4iLCJVc2VyIiwiZnJvbUpTT04iLCJhc3NpZ24iLCJzZXNzaW9uRGF0YSIsImNyZWF0ZVNlc3Npb24iLCJ1c2VySWQiLCJvYmplY3RJZCIsImNyZWF0ZWRXaXRoIiwiYWN0aW9uIiwiYXV0aFByb3ZpZGVyIiwiaW5zdGFsbGF0aW9uSWQiLCJoYW5kbGVWZXJpZnlQYXNzd29yZCIsImhhbmRsZUxvZ091dCIsInN1Y2Nlc3MiLCJ1bmRlZmluZWQiLCJyZWNvcmRzIiwiZGVsIiwiX3J1bkFmdGVyTG9nb3V0VHJpZ2dlciIsInNlc3Npb24iLCJhZnRlckxvZ291dCIsIlNlc3Npb24iLCJfdGhyb3dPbkJhZEVtYWlsQ29uZmlnIiwiQ29uZmlnIiwidmFsaWRhdGVFbWFpbENvbmZpZ3VyYXRpb24iLCJlbWFpbEFkYXB0ZXIiLCJ1c2VyQ29udHJvbGxlciIsImFkYXB0ZXIiLCJhcHBOYW1lIiwicHVibGljU2VydmVyVVJMIiwiZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJlIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiaGFuZGxlUmVzZXRSZXF1ZXN0IiwiRU1BSUxfTUlTU0lORyIsIklOVkFMSURfRU1BSUxfQUREUkVTUyIsInNlbmRQYXNzd29yZFJlc2V0RW1haWwiLCJlcnIiLCJjb2RlIiwiaGFuZGxlVmVyaWZpY2F0aW9uRW1haWxSZXF1ZXN0IiwiT1RIRVJfQ0FVU0UiLCJyZWdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbiIsInNlbmRWZXJpZmljYXRpb25FbWFpbCIsIm1vdW50Um91dGVzIiwicm91dGUiLCJoYW5kbGVGaW5k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a0J4SCxHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttSCxLQUFMLENBQVcsS0FBWCxFQUFrQixRQUFsQixFQUE0Qm5ILEdBQUcsSUFBSTtBQUNqQyxhQUFPLEtBQUt3RCxXQUFMLENBQWlCeEQsR0FBakIsQ0FBUDtBQUNELEtBRkQ7QUFHQSxTQUFLbUgsS0FBTCxDQUFXLE1BQVgsRUFBbUIsUUFBbkIsRUFBNkJuSCxHQUFHLElBQUk7QUFDbEMsYUFBTyxLQUFLd0QsV0FBTCxDQUFpQnhELEdBQWpCLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS21ILEtBQUwsQ0FBVyxNQUFYLEVBQW1CLFNBQW5CLEVBQThCbkgsR0FBRyxJQUFJO0FBQ25DLGFBQU8sS0FBS29GLFlBQUwsQ0FBa0JwRixHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttSCxLQUFMLENBQVcsTUFBWCxFQUFtQix1QkFBbkIsRUFBNENuSCxHQUFHLElBQUk7QUFDakQsYUFBTyxLQUFLd0csa0JBQUwsQ0FBd0J4RyxHQUF4QixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttSCxLQUFMLENBQVcsTUFBWCxFQUFtQiwyQkFBbkIsRUFBZ0RuSCxHQUFHLElBQUk7QUFDckQsYUFBTyxLQUFLOEcsOEJBQUwsQ0FBb0M5RyxHQUFwQyxDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttSCxLQUFMLENBQVcsS0FBWCxFQUFrQixpQkFBbEIsRUFBcUNuSCxHQUFHLElBQUk7QUFDMUMsYUFBTyxLQUFLbUYsb0JBQUwsQ0FBMEJuRixHQUExQixDQUFQO0FBQ0QsS0FGRDtBQUdEOztBQXRjNEM7OztlQXljaENaLFciLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGVzZSBtZXRob2RzIGhhbmRsZSB0aGUgVXNlci1yZWxhdGVkIHJvdXRlcy5cblxuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuaW1wb3J0IEFjY291bnRMb2Nrb3V0IGZyb20gJy4uL0FjY291bnRMb2Nrb3V0JztcbmltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4uL0F1dGgnO1xuaW1wb3J0IHBhc3N3b3JkQ3J5cHRvIGZyb20gJy4uL3Bhc3N3b3JkJztcbmltcG9ydCB7IG1heWJlUnVuVHJpZ2dlciwgVHlwZXMgYXMgVHJpZ2dlclR5cGVzIH0gZnJvbSAnLi4vdHJpZ2dlcnMnO1xuXG5leHBvcnQgY2xhc3MgVXNlcnNSb3V0ZXIgZXh0ZW5kcyBDbGFzc2VzUm91dGVyIHtcbiAgY2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnX1VzZXInO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYWxsIFwiX1wiIHByZWZpeGVkIHByb3BlcnRpZXMgZnJvbSBhbiBvYmplY3QsIGV4Y2VwdCBcIl9fdHlwZVwiXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogQW4gb2JqZWN0LlxuICAgKi9cbiAgc3RhdGljIHJlbW92ZUhpZGRlblByb3BlcnRpZXMob2JqKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSkpIHtcbiAgICAgICAgLy8gUmVnZXhwIGNvbWVzIGZyb20gUGFyc2UuT2JqZWN0LnByb3RvdHlwZS52YWxpZGF0ZVxuICAgICAgICBpZiAoa2V5ICE9PSAnX190eXBlJyAmJiAhL15bQS1aYS16XVswLTlBLVphLXpfXSokLy50ZXN0KGtleSkpIHtcbiAgICAgICAgICBkZWxldGUgb2JqW2tleV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgcGFzc3dvcmQgcmVxdWVzdCBpbiBsb2dpbiBhbmQgdmVyaWZ5UGFzc3dvcmRcbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcSBUaGUgcmVxdWVzdFxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBVc2VyIG9iamVjdFxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2F1dGhlbnRpY2F0ZVVzZXJGcm9tUmVxdWVzdChyZXEpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgLy8gVXNlIHF1ZXJ5IHBhcmFtZXRlcnMgaW5zdGVhZCBpZiBwcm92aWRlZCBpbiB1cmxcbiAgICAgIGxldCBwYXlsb2FkID0gcmVxLmJvZHk7XG4gICAgICBpZiAoXG4gICAgICAgICghcGF5bG9hZC51c2VybmFtZSAmJiByZXEucXVlcnkudXNlcm5hbWUpIHx8XG4gICAgICAgICghcGF5bG9hZC5lbWFpbCAmJiByZXEucXVlcnkuZW1haWwpXG4gICAgICApIHtcbiAgICAgICAgcGF5bG9hZCA9IHJlcS5xdWVyeTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHsgdXNlcm5hbWUsIGVtYWlsLCBwYXNzd29yZCB9ID0gcGF5bG9hZDtcblxuICAgICAgLy8gVE9ETzogdXNlIHRoZSByaWdodCBlcnJvciBjb2RlcyAvIGRlc2NyaXB0aW9ucy5cbiAgICAgIGlmICghdXNlcm5hbWUgJiYgIWVtYWlsKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5VU0VSTkFNRV9NSVNTSU5HLFxuICAgICAgICAgICd1c2VybmFtZS9lbWFpbCBpcyByZXF1aXJlZC4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIXBhc3N3b3JkKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5QQVNTV09SRF9NSVNTSU5HLFxuICAgICAgICAgICdwYXNzd29yZCBpcyByZXF1aXJlZC4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiBwYXNzd29yZCAhPT0gJ3N0cmluZycgfHxcbiAgICAgICAgKGVtYWlsICYmIHR5cGVvZiBlbWFpbCAhPT0gJ3N0cmluZycpIHx8XG4gICAgICAgICh1c2VybmFtZSAmJiB0eXBlb2YgdXNlcm5hbWUgIT09ICdzdHJpbmcnKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICdJbnZhbGlkIHVzZXJuYW1lL3Bhc3N3b3JkLidcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgbGV0IHVzZXI7XG4gICAgICBsZXQgaXNWYWxpZFBhc3N3b3JkID0gZmFsc2U7XG4gICAgICBsZXQgcXVlcnk7XG4gICAgICBpZiAoZW1haWwgJiYgdXNlcm5hbWUpIHtcbiAgICAgICAgcXVlcnkgPSB7IGVtYWlsLCB1c2VybmFtZSB9O1xuICAgICAgfSBlbHNlIGlmIChlbWFpbCkge1xuICAgICAgICBxdWVyeSA9IHsgZW1haWwgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXJ5ID0geyAkb3I6IFt7IHVzZXJuYW1lIH0sIHsgZW1haWw6IHVzZXJuYW1lIH1dIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgICAuZmluZCgnX1VzZXInLCBxdWVyeSlcbiAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgaWYgKCFyZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgICAnSW52YWxpZCB1c2VybmFtZS9wYXNzd29yZC4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIC8vIGNvcm5lciBjYXNlIHdoZXJlIHVzZXIxIGhhcyB1c2VybmFtZSA9PSB1c2VyMiBlbWFpbFxuICAgICAgICAgICAgcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyLndhcm4oXG4gICAgICAgICAgICAgIFwiVGhlcmUgaXMgYSB1c2VyIHdoaWNoIGVtYWlsIGlzIHRoZSBzYW1lIGFzIGFub3RoZXIgdXNlcidzIHVzZXJuYW1lLCBsb2dnaW5nIGluIGJhc2VkIG9uIHVzZXJuYW1lXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB1c2VyID0gcmVzdWx0cy5maWx0ZXIodXNlciA9PiB1c2VyLnVzZXJuYW1lID09PSB1c2VybmFtZSlbMF07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHVzZXIgPSByZXN1bHRzWzBdO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBwYXNzd29yZENyeXB0by5jb21wYXJlKHBhc3N3b3JkLCB1c2VyLnBhc3N3b3JkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oY29ycmVjdCA9PiB7XG4gICAgICAgICAgaXNWYWxpZFBhc3N3b3JkID0gY29ycmVjdDtcbiAgICAgICAgICBjb25zdCBhY2NvdW50TG9ja291dFBvbGljeSA9IG5ldyBBY2NvdW50TG9ja291dCh1c2VyLCByZXEuY29uZmlnKTtcbiAgICAgICAgICByZXR1cm4gYWNjb3VudExvY2tvdXRQb2xpY3kuaGFuZGxlTG9naW5BdHRlbXB0KGlzVmFsaWRQYXNzd29yZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICBpZiAoIWlzVmFsaWRQYXNzd29yZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgICAnSW52YWxpZCB1c2VybmFtZS9wYXNzd29yZC4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBFbnN1cmUgdGhlIHVzZXIgaXNuJ3QgbG9ja2VkIG91dFxuICAgICAgICAgIC8vIEEgbG9ja2VkIG91dCB1c2VyIHdvbid0IGJlIGFibGUgdG8gbG9naW5cbiAgICAgICAgICAvLyBUbyBsb2NrIGEgdXNlciBvdXQsIGp1c3Qgc2V0IHRoZSBBQ0wgdG8gYG1hc3RlcktleWAgb25seSAgKHt9KS5cbiAgICAgICAgICAvLyBFbXB0eSBBQ0wgaXMgT0tcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhcmVxLmF1dGguaXNNYXN0ZXIgJiZcbiAgICAgICAgICAgIHVzZXIuQUNMICYmXG4gICAgICAgICAgICBPYmplY3Qua2V5cyh1c2VyLkFDTCkubGVuZ3RoID09IDBcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgJ0ludmFsaWQgdXNlcm5hbWUvcGFzc3dvcmQuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcmVxLmNvbmZpZy52ZXJpZnlVc2VyRW1haWxzICYmXG4gICAgICAgICAgICByZXEuY29uZmlnLnByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWwgJiZcbiAgICAgICAgICAgICF1c2VyLmVtYWlsVmVyaWZpZWRcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuRU1BSUxfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgICAnVXNlciBlbWFpbCBpcyBub3QgdmVyaWZpZWQuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkZWxldGUgdXNlci5wYXNzd29yZDtcblxuICAgICAgICAgIC8vIFNvbWV0aW1lcyB0aGUgYXV0aERhdGEgc3RpbGwgaGFzIG51bGwgb24gdGhhdCBrZXlzXG4gICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3BhcnNlLWNvbW11bml0eS9wYXJzZS1zZXJ2ZXIvaXNzdWVzLzkzNVxuICAgICAgICAgIGlmICh1c2VyLmF1dGhEYXRhKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyh1c2VyLmF1dGhEYXRhKS5mb3JFYWNoKHByb3ZpZGVyID0+IHtcbiAgICAgICAgICAgICAgaWYgKHVzZXIuYXV0aERhdGFbcHJvdmlkZXJdID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHVzZXIuYXV0aERhdGFbcHJvdmlkZXJdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChPYmplY3Qua2V5cyh1c2VyLmF1dGhEYXRhKS5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgICBkZWxldGUgdXNlci5hdXRoRGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh1c2VyKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBoYW5kbGVNZShyZXEpIHtcbiAgICBpZiAoIXJlcS5pbmZvIHx8ICFyZXEuaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3Qgc2Vzc2lvblRva2VuID0gcmVxLmluZm8uc2Vzc2lvblRva2VuO1xuICAgIHJldHVybiByZXN0XG4gICAgICAuZmluZChcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgQXV0aC5tYXN0ZXIocmVxLmNvbmZpZyksXG4gICAgICAgICdfU2Vzc2lvbicsXG4gICAgICAgIHsgc2Vzc2lvblRva2VuIH0sXG4gICAgICAgIHsgaW5jbHVkZTogJ3VzZXInIH0sXG4gICAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICAgKVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgIXJlc3BvbnNlLnJlc3VsdHMgfHxcbiAgICAgICAgICByZXNwb25zZS5yZXN1bHRzLmxlbmd0aCA9PSAwIHx8XG4gICAgICAgICAgIXJlc3BvbnNlLnJlc3VsdHNbMF0udXNlclxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1NFU1NJT05fVE9LRU4sXG4gICAgICAgICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgdXNlciA9IHJlc3BvbnNlLnJlc3VsdHNbMF0udXNlcjtcbiAgICAgICAgICAvLyBTZW5kIHRva2VuIGJhY2sgb24gdGhlIGxvZ2luLCBiZWNhdXNlIFNES3MgZXhwZWN0IHRoYXQuXG4gICAgICAgICAgdXNlci5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uVG9rZW47XG5cbiAgICAgICAgICAvLyBSZW1vdmUgaGlkZGVuIHByb3BlcnRpZXMuXG4gICAgICAgICAgVXNlcnNSb3V0ZXIucmVtb3ZlSGlkZGVuUHJvcGVydGllcyh1c2VyKTtcblxuICAgICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB1c2VyIH07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgaGFuZGxlTG9nSW4ocmVxKSB7XG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuX2F1dGhlbnRpY2F0ZVVzZXJGcm9tUmVxdWVzdChyZXEpO1xuXG4gICAgLy8gaGFuZGxlIHBhc3N3b3JkIGV4cGlyeSBwb2xpY3lcbiAgICBpZiAocmVxLmNvbmZpZy5wYXNzd29yZFBvbGljeSAmJiByZXEuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlKSB7XG4gICAgICBsZXQgY2hhbmdlZEF0ID0gdXNlci5fcGFzc3dvcmRfY2hhbmdlZF9hdDtcblxuICAgICAgaWYgKCFjaGFuZ2VkQXQpIHtcbiAgICAgICAgLy8gcGFzc3dvcmQgd2FzIGNyZWF0ZWQgYmVmb3JlIGV4cGlyeSBwb2xpY3kgd2FzIGVuYWJsZWQuXG4gICAgICAgIC8vIHNpbXBseSB1cGRhdGUgX1VzZXIgb2JqZWN0IHNvIHRoYXQgaXQgd2lsbCBzdGFydCBlbmZvcmNpbmcgZnJvbSBub3dcbiAgICAgICAgY2hhbmdlZEF0ID0gbmV3IERhdGUoKTtcbiAgICAgICAgcmVxLmNvbmZpZy5kYXRhYmFzZS51cGRhdGUoXG4gICAgICAgICAgJ19Vc2VyJyxcbiAgICAgICAgICB7IHVzZXJuYW1lOiB1c2VyLnVzZXJuYW1lIH0sXG4gICAgICAgICAgeyBfcGFzc3dvcmRfY2hhbmdlZF9hdDogUGFyc2UuX2VuY29kZShjaGFuZ2VkQXQpIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIHBhc3N3b3JkIGhhcyBleHBpcmVkXG4gICAgICAgIGlmIChjaGFuZ2VkQXQuX190eXBlID09ICdEYXRlJykge1xuICAgICAgICAgIGNoYW5nZWRBdCA9IG5ldyBEYXRlKGNoYW5nZWRBdC5pc28pO1xuICAgICAgICB9XG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZXhwaXJ5IHRpbWUuXG4gICAgICAgIGNvbnN0IGV4cGlyZXNBdCA9IG5ldyBEYXRlKFxuICAgICAgICAgIGNoYW5nZWRBdC5nZXRUaW1lKCkgK1xuICAgICAgICAgICAgODY0MDAwMDAgKiByZXEuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChleHBpcmVzQXQgPCBuZXcgRGF0ZSgpKVxuICAgICAgICAgIC8vIGZhaWwgb2YgY3VycmVudCB0aW1lIGlzIHBhc3QgcGFzc3dvcmQgZXhwaXJ5IHRpbWVcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgJ1lvdXIgcGFzc3dvcmQgaGFzIGV4cGlyZWQuIFBsZWFzZSByZXNldCB5b3VyIHBhc3N3b3JkLidcbiAgICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlbW92ZSBoaWRkZW4gcHJvcGVydGllcy5cbiAgICBVc2Vyc1JvdXRlci5yZW1vdmVIaWRkZW5Qcm9wZXJ0aWVzKHVzZXIpO1xuXG4gICAgcmVxLmNvbmZpZy5maWxlc0NvbnRyb2xsZXIuZXhwYW5kRmlsZXNJbk9iamVjdChyZXEuY29uZmlnLCB1c2VyKTtcblxuICAgIC8vIEJlZm9yZSBsb2dpbiB0cmlnZ2VyOyB0aHJvd3MgaWYgZmFpbHVyZVxuICAgIGF3YWl0IG1heWJlUnVuVHJpZ2dlcihcbiAgICAgIFRyaWdnZXJUeXBlcy5iZWZvcmVMb2dpbixcbiAgICAgIHJlcS5hdXRoLFxuICAgICAgUGFyc2UuVXNlci5mcm9tSlNPTihPYmplY3QuYXNzaWduKHsgY2xhc3NOYW1lOiAnX1VzZXInIH0sIHVzZXIpKSxcbiAgICAgIG51bGwsXG4gICAgICByZXEuY29uZmlnXG4gICAgKTtcblxuICAgIGNvbnN0IHsgc2Vzc2lvbkRhdGEsIGNyZWF0ZVNlc3Npb24gfSA9IEF1dGguY3JlYXRlU2Vzc2lvbihyZXEuY29uZmlnLCB7XG4gICAgICB1c2VySWQ6IHVzZXIub2JqZWN0SWQsXG4gICAgICBjcmVhdGVkV2l0aDoge1xuICAgICAgICBhY3Rpb246ICdsb2dpbicsXG4gICAgICAgIGF1dGhQcm92aWRlcjogJ3Bhc3N3b3JkJyxcbiAgICAgIH0sXG4gICAgICBpbnN0YWxsYXRpb25JZDogcmVxLmluZm8uaW5zdGFsbGF0aW9uSWQsXG4gICAgfSk7XG5cbiAgICB1c2VyLnNlc3Npb25Ub2tlbiA9IHNlc3Npb25EYXRhLnNlc3Npb25Ub2tlbjtcblxuICAgIGF3YWl0IGNyZWF0ZVNlc3Npb24oKTtcbiAgICByZXR1cm4geyByZXNwb25zZTogdXNlciB9O1xuICB9XG5cbiAgaGFuZGxlVmVyaWZ5UGFzc3dvcmQocmVxKSB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dGhlbnRpY2F0ZVVzZXJGcm9tUmVxdWVzdChyZXEpXG4gICAgICAudGhlbih1c2VyID0+IHtcbiAgICAgICAgLy8gUmVtb3ZlIGhpZGRlbiBwcm9wZXJ0aWVzLlxuICAgICAgICBVc2Vyc1JvdXRlci5yZW1vdmVIaWRkZW5Qcm9wZXJ0aWVzKHVzZXIpO1xuXG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB1c2VyIH07XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZUxvZ091dChyZXEpIHtcbiAgICBjb25zdCBzdWNjZXNzID0geyByZXNwb25zZToge30gfTtcbiAgICBpZiAocmVxLmluZm8gJiYgcmVxLmluZm8uc2Vzc2lvblRva2VuKSB7XG4gICAgICByZXR1cm4gcmVzdFxuICAgICAgICAuZmluZChcbiAgICAgICAgICByZXEuY29uZmlnLFxuICAgICAgICAgIEF1dGgubWFzdGVyKHJlcS5jb25maWcpLFxuICAgICAgICAgICdfU2Vzc2lvbicsXG4gICAgICAgICAgeyBzZXNzaW9uVG9rZW46IHJlcS5pbmZvLnNlc3Npb25Ub2tlbiB9LFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICByZXEuaW5mby5jbGllbnRTREtcbiAgICAgICAgKVxuICAgICAgICAudGhlbihyZWNvcmRzID0+IHtcbiAgICAgICAgICBpZiAocmVjb3Jkcy5yZXN1bHRzICYmIHJlY29yZHMucmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN0XG4gICAgICAgICAgICAgIC5kZWwoXG4gICAgICAgICAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgICAgICAgICBBdXRoLm1hc3RlcihyZXEuY29uZmlnKSxcbiAgICAgICAgICAgICAgICAnX1Nlc3Npb24nLFxuICAgICAgICAgICAgICAgIHJlY29yZHMucmVzdWx0c1swXS5vYmplY3RJZFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9ydW5BZnRlckxvZ291dFRyaWdnZXIocmVxLCByZWNvcmRzLnJlc3VsdHNbMF0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc3VjY2Vzcyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHN1Y2Nlc3MpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShzdWNjZXNzKTtcbiAgfVxuXG4gIF9ydW5BZnRlckxvZ291dFRyaWdnZXIocmVxLCBzZXNzaW9uKSB7XG4gICAgLy8gQWZ0ZXIgbG9nb3V0IHRyaWdnZXJcbiAgICBtYXliZVJ1blRyaWdnZXIoXG4gICAgICBUcmlnZ2VyVHlwZXMuYWZ0ZXJMb2dvdXQsXG4gICAgICByZXEuYXV0aCxcbiAgICAgIFBhcnNlLlNlc3Npb24uZnJvbUpTT04oT2JqZWN0LmFzc2lnbih7IGNsYXNzTmFtZTogJ19TZXNzaW9uJyB9LCBzZXNzaW9uKSksXG4gICAgICBudWxsLFxuICAgICAgcmVxLmNvbmZpZ1xuICAgICk7XG4gIH1cblxuICBfdGhyb3dPbkJhZEVtYWlsQ29uZmlnKHJlcSkge1xuICAgIHRyeSB7XG4gICAgICBDb25maWcudmFsaWRhdGVFbWFpbENvbmZpZ3VyYXRpb24oe1xuICAgICAgICBlbWFpbEFkYXB0ZXI6IHJlcS5jb25maWcudXNlckNvbnRyb2xsZXIuYWRhcHRlcixcbiAgICAgICAgYXBwTmFtZTogcmVxLmNvbmZpZy5hcHBOYW1lLFxuICAgICAgICBwdWJsaWNTZXJ2ZXJVUkw6IHJlcS5jb25maWcucHVibGljU2VydmVyVVJMLFxuICAgICAgICBlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbjpcbiAgICAgICAgICByZXEuY29uZmlnLmVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKHR5cGVvZiBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAvLyBNYXliZSB3ZSBuZWVkIGEgQmFkIENvbmZpZ3VyYXRpb24gZXJyb3IsIGJ1dCB0aGUgU0RLcyB3b24ndCB1bmRlcnN0YW5kIGl0LiBGb3Igbm93LCBJbnRlcm5hbCBTZXJ2ZXIgRXJyb3IuXG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgICAgJ0FuIGFwcE5hbWUsIHB1YmxpY1NlcnZlclVSTCwgYW5kIGVtYWlsQWRhcHRlciBhcmUgcmVxdWlyZWQgZm9yIHBhc3N3b3JkIHJlc2V0IGFuZCBlbWFpbCB2ZXJpZmljYXRpb24gZnVuY3Rpb25hbGl0eS4nXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGhhbmRsZVJlc2V0UmVxdWVzdChyZXEpIHtcbiAgICB0aGlzLl90aHJvd09uQmFkRW1haWxDb25maWcocmVxKTtcblxuICAgIGNvbnN0IHsgZW1haWwgfSA9IHJlcS5ib2R5O1xuICAgIGlmICghZW1haWwpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuRU1BSUxfTUlTU0lORyxcbiAgICAgICAgJ3lvdSBtdXN0IHByb3ZpZGUgYW4gZW1haWwnXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGVtYWlsICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0VNQUlMX0FERFJFU1MsXG4gICAgICAgICd5b3UgbXVzdCBwcm92aWRlIGEgdmFsaWQgZW1haWwgc3RyaW5nJ1xuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgdXNlckNvbnRyb2xsZXIgPSByZXEuY29uZmlnLnVzZXJDb250cm9sbGVyO1xuICAgIHJldHVybiB1c2VyQ29udHJvbGxlci5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKGVtYWlsKS50aGVuKFxuICAgICAgKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICByZXNwb25zZToge30sXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIGVyciA9PiB7XG4gICAgICAgIGlmIChlcnIuY29kZSA9PT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCkge1xuICAgICAgICAgIC8vIFJldHVybiBzdWNjZXNzIHNvIHRoYXQgdGhpcyBlbmRwb2ludCBjYW4ndFxuICAgICAgICAgIC8vIGJlIHVzZWQgdG8gZW51bWVyYXRlIHZhbGlkIGVtYWlsc1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgICAgcmVzcG9uc2U6IHt9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBoYW5kbGVWZXJpZmljYXRpb25FbWFpbFJlcXVlc3QocmVxKSB7XG4gICAgdGhpcy5fdGhyb3dPbkJhZEVtYWlsQ29uZmlnKHJlcSk7XG5cbiAgICBjb25zdCB7IGVtYWlsIH0gPSByZXEuYm9keTtcbiAgICBpZiAoIWVtYWlsKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLkVNQUlMX01JU1NJTkcsXG4gICAgICAgICd5b3UgbXVzdCBwcm92aWRlIGFuIGVtYWlsJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBlbWFpbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9FTUFJTF9BRERSRVNTLFxuICAgICAgICAneW91IG11c3QgcHJvdmlkZSBhIHZhbGlkIGVtYWlsIHN0cmluZydcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCB7IGVtYWlsOiBlbWFpbCB9KS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgaWYgKCFyZXN1bHRzLmxlbmd0aCB8fCByZXN1bHRzLmxlbmd0aCA8IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLkVNQUlMX05PVF9GT1VORCxcbiAgICAgICAgICBgTm8gdXNlciBmb3VuZCB3aXRoIGVtYWlsICR7ZW1haWx9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3QgdXNlciA9IHJlc3VsdHNbMF07XG5cbiAgICAgIC8vIHJlbW92ZSBwYXNzd29yZCBmaWVsZCwgbWVzc2VzIHdpdGggc2F2aW5nIG9uIHBvc3RncmVzXG4gICAgICBkZWxldGUgdXNlci5wYXNzd29yZDtcblxuICAgICAgaWYgKHVzZXIuZW1haWxWZXJpZmllZCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuT1RIRVJfQ0FVU0UsXG4gICAgICAgICAgYEVtYWlsICR7ZW1haWx9IGlzIGFscmVhZHkgdmVyaWZpZWQuYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB1c2VyQ29udHJvbGxlciA9IHJlcS5jb25maWcudXNlckNvbnRyb2xsZXI7XG4gICAgICByZXR1cm4gdXNlckNvbnRyb2xsZXIucmVnZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW4odXNlcikudGhlbigoKSA9PiB7XG4gICAgICAgIHVzZXJDb250cm9sbGVyLnNlbmRWZXJpZmljYXRpb25FbWFpbCh1c2VyKTtcbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHt9IH07XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvdXNlcnMnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRmluZChyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL3VzZXJzJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUNyZWF0ZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvdXNlcnMvbWUnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlTWUocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3VzZXJzLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVHZXQocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCAnL3VzZXJzLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGUocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdERUxFVEUnLCAnL3VzZXJzLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL2xvZ2luJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUxvZ0luKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvbG9naW4nLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlTG9nSW4ocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy9sb2dvdXQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlTG9nT3V0KHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvcmVxdWVzdFBhc3N3b3JkUmVzZXQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlUmVzZXRSZXF1ZXN0KHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvdmVyaWZpY2F0aW9uRW1haWxSZXF1ZXN0JywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZVZlcmlmaWNhdGlvbkVtYWlsUmVxdWVzdChyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvdmVyaWZ5UGFzc3dvcmQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlVmVyaWZ5UGFzc3dvcmQocmVxKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBVc2Vyc1JvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/StatusHandler.js b/lib/StatusHandler.js new file mode 100644 index 0000000000..3da94483db --- /dev/null +++ b/lib/StatusHandler.js @@ -0,0 +1,382 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.flatten = flatten; +exports.jobStatusHandler = jobStatusHandler; +exports.pushStatusHandler = pushStatusHandler; + +var _cryptoUtils = require("./cryptoUtils"); + +var _logger = require("./logger"); + +var _rest = _interopRequireDefault(require("./rest")); + +var _Auth = _interopRequireDefault(require("./Auth")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const PUSH_STATUS_COLLECTION = '_PushStatus'; +const JOB_STATUS_COLLECTION = '_JobStatus'; + +const incrementOp = function (object = {}, key, amount = 1) { + if (!object[key]) { + object[key] = { + __op: 'Increment', + amount: amount + }; + } else { + object[key].amount += amount; + } + + return object[key]; +}; + +function flatten(array) { + var flattened = []; + + for (var i = 0; i < array.length; i++) { + if (Array.isArray(array[i])) { + flattened = flattened.concat(flatten(array[i])); + } else { + flattened.push(array[i]); + } + } + + return flattened; +} + +function statusHandler(className, database) { + let lastPromise = Promise.resolve(); + + function create(object) { + lastPromise = lastPromise.then(() => { + return database.create(className, object).then(() => { + return Promise.resolve(object); + }); + }); + return lastPromise; + } + + function update(where, object) { + lastPromise = lastPromise.then(() => { + return database.update(className, where, object); + }); + return lastPromise; + } + + return Object.freeze({ + create, + update + }); +} + +function restStatusHandler(className, config) { + let lastPromise = Promise.resolve(); + + const auth = _Auth.default.master(config); + + function create(object) { + lastPromise = lastPromise.then(() => { + return _rest.default.create(config, auth, className, object).then(({ + response + }) => { + // merge the objects + return Promise.resolve(Object.assign({}, object, response)); + }); + }); + return lastPromise; + } + + function update(where, object) { + // TODO: when we have updateWhere, use that for proper interfacing + lastPromise = lastPromise.then(() => { + return _rest.default.update(config, auth, className, { + objectId: where.objectId + }, object).then(({ + response + }) => { + // merge the objects + return Promise.resolve(Object.assign({}, object, response)); + }); + }); + return lastPromise; + } + + return Object.freeze({ + create, + update + }); +} + +function jobStatusHandler(config) { + let jobStatus; + const objectId = (0, _cryptoUtils.newObjectId)(config.objectIdSize); + const database = config.database; + const handler = statusHandler(JOB_STATUS_COLLECTION, database); + + const setRunning = function (jobName, params) { + const now = new Date(); + jobStatus = { + objectId, + jobName, + params, + status: 'running', + source: 'api', + createdAt: now, + // lockdown! + ACL: {} + }; + return handler.create(jobStatus); + }; + + const setMessage = function (message) { + if (!message || typeof message !== 'string') { + return Promise.resolve(); + } + + return handler.update({ + objectId + }, { + message + }); + }; + + const setSucceeded = function (message) { + return setFinalStatus('succeeded', message); + }; + + const setFailed = function (message) { + return setFinalStatus('failed', message); + }; + + const setFinalStatus = function (status, message = undefined) { + const finishedAt = new Date(); + const update = { + status, + finishedAt + }; + + if (message && typeof message === 'string') { + update.message = message; + } + + return handler.update({ + objectId + }, update); + }; + + return Object.freeze({ + setRunning, + setSucceeded, + setMessage, + setFailed + }); +} + +function pushStatusHandler(config, existingObjectId) { + let pushStatus; + const database = config.database; + const handler = restStatusHandler(PUSH_STATUS_COLLECTION, config); + let objectId = existingObjectId; + + const setInitial = function (body = {}, where, options = { + source: 'rest' + }) { + const now = new Date(); + let pushTime = now.toISOString(); + let status = 'pending'; + + if (Object.prototype.hasOwnProperty.call(body, 'push_time')) { + if (config.hasPushScheduledSupport) { + pushTime = body.push_time; + status = 'scheduled'; + } else { + _logger.logger.warn('Trying to schedule a push while server is not configured.'); + + _logger.logger.warn('Push will be sent immediately'); + } + } + + const data = body.data || {}; + const payloadString = JSON.stringify(data); + let pushHash; + + if (typeof data.alert === 'string') { + pushHash = (0, _cryptoUtils.md5Hash)(data.alert); + } else if (typeof data.alert === 'object') { + pushHash = (0, _cryptoUtils.md5Hash)(JSON.stringify(data.alert)); + } else { + pushHash = 'd41d8cd98f00b204e9800998ecf8427e'; + } + + const object = { + pushTime, + query: JSON.stringify(where), + payload: payloadString, + source: options.source, + title: options.title, + expiry: body.expiration_time, + expiration_interval: body.expiration_interval, + status: status, + numSent: 0, + pushHash, + // lockdown! + ACL: {} + }; + return handler.create(object).then(result => { + objectId = result.objectId; + pushStatus = { + objectId + }; + return Promise.resolve(pushStatus); + }); + }; + + const setRunning = function (batches) { + _logger.logger.verbose(`_PushStatus ${objectId}: sending push to installations with %d batches`, batches); + + return handler.update({ + status: 'pending', + objectId: objectId + }, { + status: 'running', + count: batches + }); + }; + + const trackSent = function (results, UTCOffset, cleanupInstallations = process.env.PARSE_SERVER_CLEANUP_INVALID_INSTALLATIONS) { + const update = { + numSent: 0, + numFailed: 0 + }; + const devicesToRemove = []; + + if (Array.isArray(results)) { + results = flatten(results); + results.reduce((memo, result) => { + // Cannot handle that + if (!result || !result.device || !result.device.deviceType) { + return memo; + } + + const deviceType = result.device.deviceType; + const key = result.transmitted ? `sentPerType.${deviceType}` : `failedPerType.${deviceType}`; + memo[key] = incrementOp(memo, key); + + if (typeof UTCOffset !== 'undefined') { + const offsetKey = result.transmitted ? `sentPerUTCOffset.${UTCOffset}` : `failedPerUTCOffset.${UTCOffset}`; + memo[offsetKey] = incrementOp(memo, offsetKey); + } + + if (result.transmitted) { + memo.numSent++; + } else { + if (result && result.response && result.response.error && result.device && result.device.deviceToken) { + const token = result.device.deviceToken; + const error = result.response.error; // GCM errors + + if (error === 'NotRegistered' || error === 'InvalidRegistration') { + devicesToRemove.push(token); + } // APNS errors + + + if (error === 'Unregistered' || error === 'BadDeviceToken') { + devicesToRemove.push(token); + } + } + + memo.numFailed++; + } + + return memo; + }, update); + } + + _logger.logger.verbose(`_PushStatus ${objectId}: sent push! %d success, %d failures`, update.numSent, update.numFailed); + + _logger.logger.verbose(`_PushStatus ${objectId}: needs cleanup`, { + devicesToRemove + }); + + ['numSent', 'numFailed'].forEach(key => { + if (update[key] > 0) { + update[key] = { + __op: 'Increment', + amount: update[key] + }; + } else { + delete update[key]; + } + }); + + if (devicesToRemove.length > 0 && cleanupInstallations) { + _logger.logger.info(`Removing device tokens on ${devicesToRemove.length} _Installations`); + + database.update('_Installation', { + deviceToken: { + $in: devicesToRemove + } + }, { + deviceToken: { + __op: 'Delete' + } + }, { + acl: undefined, + many: true + }); + } // indicate this batch is complete + + + incrementOp(update, 'count', -1); + return handler.update({ + objectId + }, update).then(res => { + if (res && res.count === 0) { + return this.complete(); + } + }); + }; + + const complete = function () { + return handler.update({ + objectId + }, { + status: 'succeeded', + count: { + __op: 'Delete' + } + }); + }; + + const fail = function (err) { + if (typeof err === 'string') { + err = { + message: err + }; + } + + const update = { + errorMessage: err, + status: 'failed' + }; + return handler.update({ + objectId + }, update); + }; + + const rval = { + setInitial, + setRunning, + trackSent, + complete, + fail + }; // define objectId to be dynamic + + Object.defineProperty(rval, 'objectId', { + get: () => objectId + }); + return Object.freeze(rval); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9TdGF0dXNIYW5kbGVyLmpzIl0sIm5hbWVzIjpbIlBVU0hfU1RBVFVTX0NPTExFQ1RJT04iLCJKT0JfU1RBVFVTX0NPTExFQ1RJT04iLCJpbmNyZW1lbnRPcCIsIm9iamVjdCIsImtleSIsImFtb3VudCIsIl9fb3AiLCJmbGF0dGVuIiwiYXJyYXkiLCJmbGF0dGVuZWQiLCJpIiwibGVuZ3RoIiwiQXJyYXkiLCJpc0FycmF5IiwiY29uY2F0IiwicHVzaCIsInN0YXR1c0hhbmRsZXIiLCJjbGFzc05hbWUiLCJkYXRhYmFzZSIsImxhc3RQcm9taXNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJjcmVhdGUiLCJ0aGVuIiwidXBkYXRlIiwid2hlcmUiLCJPYmplY3QiLCJmcmVlemUiLCJyZXN0U3RhdHVzSGFuZGxlciIsImNvbmZpZyIsImF1dGgiLCJBdXRoIiwibWFzdGVyIiwicmVzdCIsInJlc3BvbnNlIiwiYXNzaWduIiwib2JqZWN0SWQiLCJqb2JTdGF0dXNIYW5kbGVyIiwiam9iU3RhdHVzIiwib2JqZWN0SWRTaXplIiwiaGFuZGxlciIsInNldFJ1bm5pbmciLCJqb2JOYW1lIiwicGFyYW1zIiwibm93IiwiRGF0ZSIsInN0YXR1cyIsInNvdXJjZSIsImNyZWF0ZWRBdCIsIkFDTCIsInNldE1lc3NhZ2UiLCJtZXNzYWdlIiwic2V0U3VjY2VlZGVkIiwic2V0RmluYWxTdGF0dXMiLCJzZXRGYWlsZWQiLCJ1bmRlZmluZWQiLCJmaW5pc2hlZEF0IiwicHVzaFN0YXR1c0hhbmRsZXIiLCJleGlzdGluZ09iamVjdElkIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJib2R5Iiwib3B0aW9ucyIsInB1c2hUaW1lIiwidG9JU09TdHJpbmciLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCIsInB1c2hfdGltZSIsImxvZ2dlciIsIndhcm4iLCJkYXRhIiwicGF5bG9hZFN0cmluZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJwdXNoSGFzaCIsImFsZXJ0IiwicXVlcnkiLCJwYXlsb2FkIiwidGl0bGUiLCJleHBpcnkiLCJleHBpcmF0aW9uX3RpbWUiLCJleHBpcmF0aW9uX2ludGVydmFsIiwibnVtU2VudCIsInJlc3VsdCIsImJhdGNoZXMiLCJ2ZXJib3NlIiwiY291bnQiLCJ0cmFja1NlbnQiLCJyZXN1bHRzIiwiVVRDT2Zmc2V0IiwiY2xlYW51cEluc3RhbGxhdGlvbnMiLCJwcm9jZXNzIiwiZW52IiwiUEFSU0VfU0VSVkVSX0NMRUFOVVBfSU5WQUxJRF9JTlNUQUxMQVRJT05TIiwibnVtRmFpbGVkIiwiZGV2aWNlc1RvUmVtb3ZlIiwicmVkdWNlIiwibWVtbyIsImRldmljZSIsImRldmljZVR5cGUiLCJ0cmFuc21pdHRlZCIsIm9mZnNldEtleSIsImVycm9yIiwiZGV2aWNlVG9rZW4iLCJ0b2tlbiIsImZvckVhY2giLCJpbmZvIiwiJGluIiwiYWNsIiwibWFueSIsInJlcyIsImNvbXBsZXRlIiwiZmFpbCIsImVyciIsImVycm9yTWVzc2FnZSIsInJ2YWwiLCJkZWZpbmVQcm9wZXJ0eSIsImdldCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxNQUFNQSxzQkFBc0IsR0FBRyxhQUEvQjtBQUNBLE1BQU1DLHFCQUFxQixHQUFHLFlBQTlCOztBQUVBLE1BQU1DLFdBQVcsR0FBRyxVQUFTQyxNQUFNLEdBQUcsRUFBbEIsRUFBc0JDLEdBQXRCLEVBQTJCQyxNQUFNLEdBQUcsQ0FBcEMsRUFBdUM7QUFDekQsTUFBSSxDQUFDRixNQUFNLENBQUNDLEdBQUQsQ0FBWCxFQUFrQjtBQUNoQkQsSUFBQUEsTUFBTSxDQUFDQyxHQUFELENBQU4sR0FBYztBQUFFRSxNQUFBQSxJQUFJLEVBQUUsV0FBUjtBQUFxQkQsTUFBQUEsTUFBTSxFQUFFQTtBQUE3QixLQUFkO0FBQ0QsR0FGRCxNQUVPO0FBQ0xGLElBQUFBLE1BQU0sQ0FBQ0MsR0FBRCxDQUFOLENBQVlDLE1B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QUFQLENBQXNCRCxJQUF0QixFQUE0QixVQUE1QixFQUF3QztBQUN0Q0UsSUFBQUEsR0FBRyxFQUFFLE1BQU1uRjtBQUQyQixHQUF4QztBQUlBLFNBQU9WLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjMEYsSUFBZCxDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBtZDVIYXNoLCBuZXdPYmplY3RJZCB9IGZyb20gJy4vY3J5cHRvVXRpbHMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4vQXV0aCc7XG5cbmNvbnN0IFBVU0hfU1RBVFVTX0NPTExFQ1RJT04gPSAnX1B1c2hTdGF0dXMnO1xuY29uc3QgSk9CX1NUQVRVU19DT0xMRUNUSU9OID0gJ19Kb2JTdGF0dXMnO1xuXG5jb25zdCBpbmNyZW1lbnRPcCA9IGZ1bmN0aW9uKG9iamVjdCA9IHt9LCBrZXksIGFtb3VudCA9IDEpIHtcbiAgaWYgKCFvYmplY3Rba2V5XSkge1xuICAgIG9iamVjdFtrZXldID0geyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBhbW91bnQgfTtcbiAgfSBlbHNlIHtcbiAgICBvYmplY3Rba2V5XS5hbW91bnQgKz0gYW1vdW50O1xuICB9XG4gIHJldHVybiBvYmplY3Rba2V5XTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuKGFycmF5KSB7XG4gIHZhciBmbGF0dGVuZWQgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGFycmF5W2ldKSkge1xuICAgICAgZmxhdHRlbmVkID0gZmxhdHRlbmVkLmNvbmNhdChmbGF0dGVuKGFycmF5W2ldKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZsYXR0ZW5lZC5wdXNoKGFycmF5W2ldKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZsYXR0ZW5lZDtcbn1cblxuZnVuY3Rpb24gc3RhdHVzSGFuZGxlcihjbGFzc05hbWUsIGRhdGFiYXNlKSB7XG4gIGxldCBsYXN0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZShvYmplY3QpIHtcbiAgICBsYXN0UHJvbWlzZSA9IGxhc3RQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIGRhdGFiYXNlLmNyZWF0ZShjbGFzc05hbWUsIG9iamVjdCkudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUob2JqZWN0KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBsYXN0UHJvbWlzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZSh3aGVyZSwgb2JqZWN0KSB7XG4gICAgbGFzdFByb21pc2UgPSBsYXN0UHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBkYXRhYmFzZS51cGRhdGUoY2xhc3NOYW1lLCB3aGVyZSwgb2JqZWN0KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgY3JlYXRlLFxuICAgIHVwZGF0ZSxcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlc3RTdGF0dXNIYW5kbGVyKGNsYXNzTmFtZSwgY29uZmlnKSB7XG4gIGxldCBsYXN0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICBjb25zdCBhdXRoID0gQXV0aC5tYXN0ZXIoY29uZmlnKTtcbiAgZnVuY3Rpb24gY3JlYXRlKG9iamVjdCkge1xuICAgIGxhc3RQcm9taXNlID0gbGFzdFByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gcmVzdFxuICAgICAgICAuY3JlYXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCBvYmplY3QpXG4gICAgICAgIC50aGVuKCh7IHJlc3BvbnNlIH0pID0+IHtcbiAgICAgICAgICAvLyBtZXJnZSB0aGUgb2JqZWN0c1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoT2JqZWN0LmFzc2lnbih7fSwgb2JqZWN0LCByZXNwb25zZSkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGUod2hlcmUsIG9iamVjdCkge1xuICAgIC8vIFRPRE86IHdoZW4gd2UgaGF2ZSB1cGRhdGVXaGVyZSwgdXNlIHRoYXQgZm9yIHByb3BlciBpbnRlcmZhY2luZ1xuICAgIGxhc3RQcm9taXNlID0gbGFzdFByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gcmVzdFxuICAgICAgICAudXBkYXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCB7IG9iamVjdElkOiB3aGVyZS5vYmplY3RJZCB9LCBvYmplY3QpXG4gICAgICAgIC50aGVuKCh7IHJlc3BvbnNlIH0pID0+IHtcbiAgICAgICAgICAvLyBtZXJnZSB0aGUgb2JqZWN0c1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoT2JqZWN0LmFzc2lnbih7fSwgb2JqZWN0LCByZXNwb25zZSkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgY3JlYXRlLFxuICAgIHVwZGF0ZSxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBqb2JTdGF0dXNIYW5kbGVyKGNvbmZpZykge1xuICBsZXQgam9iU3RhdHVzO1xuICBjb25zdCBvYmplY3RJZCA9IG5ld09iamVjdElkKGNvbmZpZy5vYmplY3RJZFNpemUpO1xuICBjb25zdCBkYXRhYmFzZSA9IGNvbmZpZy5kYXRhYmFzZTtcbiAgY29uc3QgaGFuZGxlciA9IHN0YXR1c0hhbmRsZXIoSk9CX1NUQVRVU19DT0xMRUNUSU9OLCBkYXRhYmFzZSk7XG4gIGNvbnN0IHNldFJ1bm5pbmcgPSBmdW5jdGlvbihqb2JOYW1lLCBwYXJhbXMpIHtcbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIGpvYlN0YXR1cyA9IHtcbiAgICAgIG9iamVjdElkLFxuICAgICAgam9iTmFtZSxcbiAgICAgIHBhcmFtcyxcbiAgICAgIHN0YXR1czogJ3J1bm5pbmcnLFxuICAgICAgc291cmNlOiAnYXBpJyxcbiAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgLy8gbG9ja2Rvd24hXG4gICAgICBBQ0w6IHt9LFxuICAgIH07XG5cbiAgICByZXR1cm4gaGFuZGxlci5jcmVhdGUoam9iU3RhdHVzKTtcbiAgfTtcblxuICBjb25zdCBzZXRNZXNzYWdlID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgIGlmICghbWVzc2FnZSB8fCB0eXBlb2YgbWVzc2FnZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgeyBtZXNzYWdlIH0pO1xuICB9O1xuXG4gIGNvbnN0IHNldFN1Y2NlZWRlZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICByZXR1cm4gc2V0RmluYWxTdGF0dXMoJ3N1Y2NlZWRlZCcsIG1lc3NhZ2UpO1xuICB9O1xuXG4gIGNvbnN0IHNldEZhaWxlZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICByZXR1cm4gc2V0RmluYWxTdGF0dXMoJ2ZhaWxlZCcsIG1lc3NhZ2UpO1xuICB9O1xuXG4gIGNvbnN0IHNldEZpbmFsU3RhdHVzID0gZnVuY3Rpb24oc3RhdHVzLCBtZXNzYWdlID0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgZmluaXNoZWRBdCA9IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgdXBkYXRlID0geyBzdGF0dXMsIGZpbmlzaGVkQXQgfTtcbiAgICBpZiAobWVzc2FnZSAmJiB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHVwZGF0ZS5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgdXBkYXRlKTtcbiAgfTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgc2V0UnVubmluZyxcbiAgICBzZXRTdWNjZWVkZWQsXG4gICAgc2V0TWVzc2FnZSxcbiAgICBzZXRGYWlsZWQsXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHVzaFN0YXR1c0hhbmRsZXIoY29uZmlnLCBleGlzdGluZ09iamVjdElkKSB7XG4gIGxldCBwdXNoU3RhdHVzO1xuICBjb25zdCBkYXRhYmFzZSA9IGNvbmZpZy5kYXRhYmFzZTtcbiAgY29uc3QgaGFuZGxlciA9IHJlc3RTdGF0dXNIYW5kbGVyKFBVU0hfU1RBVFVTX0NPTExFQ1RJT04sIGNvbmZpZyk7XG4gIGxldCBvYmplY3RJZCA9IGV4aXN0aW5nT2JqZWN0SWQ7XG4gIGNvbnN0IHNldEluaXRpYWwgPSBmdW5jdGlvbihib2R5ID0ge30sIHdoZXJlLCBvcHRpb25zID0geyBzb3VyY2U6ICdyZXN0JyB9KSB7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICBsZXQgcHVzaFRpbWUgPSBub3cudG9JU09TdHJpbmcoKTtcbiAgICBsZXQgc3RhdHVzID0gJ3BlbmRpbmcnO1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYm9keSwgJ3B1c2hfdGltZScpKSB7XG4gICAgICBpZiAoY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0KSB7XG4gICAgICAgIHB1c2hUaW1lID0gYm9keS5wdXNoX3RpbWU7XG4gICAgICAgIHN0YXR1cyA9ICdzY2hlZHVsZWQnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgJ1RyeWluZyB0byBzY2hlZHVsZSBhIHB1c2ggd2hpbGUgc2VydmVyIGlzIG5vdCBjb25maWd1cmVkLidcbiAgICAgICAgKTtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1B1c2ggd2lsbCBiZSBzZW50IGltbWVkaWF0ZWx5Jyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IGJvZHkuZGF0YSB8fCB7fTtcbiAgICBjb25zdCBwYXlsb2FkU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgbGV0IHB1c2hIYXNoO1xuICAgIGlmICh0eXBlb2YgZGF0YS5hbGVydCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHB1c2hIYXNoID0gbWQ1SGFzaChkYXRhLmFsZXJ0KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLmFsZXJ0ID09PSAnb2JqZWN0Jykge1xuICAgICAgcHVzaEhhc2ggPSBtZDVIYXNoKEpTT04uc3RyaW5naWZ5KGRhdGEuYWxlcnQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHVzaEhhc2ggPSAnZDQxZDhjZDk4ZjAwYjIwNGU5ODAwOTk4ZWNmODQyN2UnO1xuICAgIH1cbiAgICBjb25zdCBvYmplY3QgPSB7XG4gICAgICBwdXNoVGltZSxcbiAgICAgIHF1ZXJ5OiBKU09OLnN0cmluZ2lmeSh3aGVyZSksXG4gICAgICBwYXlsb2FkOiBwYXlsb2FkU3RyaW5nLFxuICAgICAgc291cmNlOiBvcHRpb25zLnNvdXJjZSxcbiAgICAgIHRpdGxlOiBvcHRpb25zLnRpdGxlLFxuICAgICAgZXhwaXJ5OiBib2R5LmV4cGlyYXRpb25fdGltZSxcbiAgICAgIGV4cGlyYXRpb25faW50ZXJ2YWw6IGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCxcbiAgICAgIHN0YXR1czogc3RhdHVzLFxuICAgICAgbnVtU2VudDogMCxcbiAgICAgIHB1c2hIYXNoLFxuICAgICAgLy8gbG9ja2Rvd24hXG4gICAgICBBQ0w6IHt9LFxuICAgIH07XG4gICAgcmV0dXJuIGhhbmRsZXIuY3JlYXRlKG9iamVjdCkudGhlbihyZXN1bHQgPT4ge1xuICAgICAgb2JqZWN0SWQgPSByZXN1bHQub2JqZWN0SWQ7XG4gICAgICBwdXNoU3RhdHVzID0ge1xuICAgICAgICBvYmplY3RJZCxcbiAgICAgIH07XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHB1c2hTdGF0dXMpO1xuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IHNldFJ1bm5pbmcgPSBmdW5jdGlvbihiYXRjaGVzKSB7XG4gICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IHNlbmRpbmcgcHVzaCB0byBpbnN0YWxsYXRpb25zIHdpdGggJWQgYmF0Y2hlc2AsXG4gICAgICBiYXRjaGVzXG4gICAgKTtcbiAgICByZXR1cm4gaGFuZGxlci51cGRhdGUoXG4gICAgICB7XG4gICAgICAgIHN0YXR1czogJ3BlbmRpbmcnLFxuICAgICAgICBvYmplY3RJZDogb2JqZWN0SWQsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBzdGF0dXM6ICdydW5uaW5nJyxcbiAgICAgICAgY291bnQ6IGJhdGNoZXMsXG4gICAgICB9XG4gICAgKTtcbiAgfTtcblxuICBjb25zdCB0cmFja1NlbnQgPSBmdW5jdGlvbihcbiAgICByZXN1bHRzLFxuICAgIFVUQ09mZnNldCxcbiAgICBjbGVhbnVwSW5zdGFsbGF0aW9ucyA9IHByb2Nlc3MuZW52XG4gICAgICAuUEFSU0VfU0VSVkVSX0NMRUFOVVBfSU5WQUxJRF9JTlNUQUxMQVRJT05TXG4gICkge1xuICAgIGNvbnN0IHVwZGF0ZSA9IHtcbiAgICAgIG51bVNlbnQ6IDAsXG4gICAgICBudW1GYWlsZWQ6IDAsXG4gICAgfTtcbiAgICBjb25zdCBkZXZpY2VzVG9SZW1vdmUgPSBbXTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHRzKSkge1xuICAgICAgcmVzdWx0cyA9IGZsYXR0ZW4ocmVzdWx0cyk7XG4gICAgICByZXN1bHRzLnJlZHVjZSgobWVtbywgcmVzdWx0KSA9PiB7XG4gICAgICAgIC8vIENhbm5vdCBoYW5kbGUgdGhhdFxuICAgICAgICBpZiAoIXJlc3VsdCB8fCAhcmVzdWx0LmRldmljZSB8fCAhcmVzdWx0LmRldmljZS5kZXZpY2VUeXBlKSB7XG4gICAgICAgICAgcmV0dXJuIG1lbW87XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGV2aWNlVHlwZSA9IHJlc3VsdC5kZXZpY2UuZGV2aWNlVHlwZTtcbiAgICAgICAgY29uc3Qga2V5ID0gcmVzdWx0LnRyYW5zbWl0dGVkXG4gICAgICAgICAgPyBgc2VudFBlclR5cGUuJHtkZXZpY2VUeXBlfWBcbiAgICAgICAgICA6IGBmYWlsZWRQZXJUeXBlLiR7ZGV2aWNlVHlwZX1gO1xuICAgICAgICBtZW1vW2tleV0gPSBpbmNyZW1lbnRPcChtZW1vLCBrZXkpO1xuICAgICAgICBpZiAodHlwZW9mIFVUQ09mZnNldCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb25zdCBvZmZzZXRLZXkgPSByZXN1bHQudHJhbnNtaXR0ZWRcbiAgICAgICAgICAgID8gYHNlbnRQZXJVVENPZmZzZXQuJHtVVENPZmZzZXR9YFxuICAgICAgICAgICAgOiBgZmFpbGVkUGVyVVRDT2Zmc2V0LiR7VVRDT2Zmc2V0fWA7XG4gICAgICAgICAgbWVtb1tvZmZzZXRLZXldID0gaW5jcmVtZW50T3AobWVtbywgb2Zmc2V0S2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0LnRyYW5zbWl0dGVkKSB7XG4gICAgICAgICAgbWVtby5udW1TZW50Kys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcmVzdWx0ICYmXG4gICAgICAgICAgICByZXN1bHQucmVzcG9uc2UgJiZcbiAgICAgICAgICAgIHJlc3VsdC5yZXNwb25zZS5lcnJvciAmJlxuICAgICAgICAgICAgcmVzdWx0LmRldmljZSAmJlxuICAgICAgICAgICAgcmVzdWx0LmRldmljZS5kZXZpY2VUb2tlblxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uc3QgdG9rZW4gPSByZXN1bHQuZGV2aWNlLmRldmljZVRva2VuO1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSByZXN1bHQucmVzcG9uc2UuZXJyb3I7XG4gICAgICAgICAgICAvLyBHQ00gZXJyb3JzXG4gICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdOb3RSZWdpc3RlcmVkJyB8fCBlcnJvciA9PT0gJ0ludmFsaWRSZWdpc3RyYXRpb24nKSB7XG4gICAgICAgICAgICAgIGRldmljZXNUb1JlbW92ZS5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEFQTlMgZXJyb3JzXG4gICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdVbnJlZ2lzdGVyZWQnIHx8IGVycm9yID09PSAnQmFkRGV2aWNlVG9rZW4nKSB7XG4gICAgICAgICAgICAgIGRldmljZXNUb1JlbW92ZS5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgbWVtby5udW1GYWlsZWQrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgIH0sIHVwZGF0ZSk7XG4gICAgfVxuXG4gICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IHNlbnQgcHVzaCEgJWQgc3VjY2VzcywgJWQgZmFpbHVyZXNgLFxuICAgICAgdXBkYXRlLm51bVNlbnQsXG4gICAgICB1cGRhdGUubnVtRmFpbGVkXG4gICAgKTtcbiAgICBsb2dnZXIudmVyYm9zZShgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IG5lZWRzIGNsZWFudXBgLCB7XG4gICAgICBkZXZpY2VzVG9SZW1vdmUsXG4gICAgfSk7XG4gICAgWydudW1TZW50JywgJ251bUZhaWxlZCddLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIGlmICh1cGRhdGVba2V5XSA+IDApIHtcbiAgICAgICAgdXBkYXRlW2tleV0gPSB7XG4gICAgICAgICAgX19vcDogJ0luY3JlbWVudCcsXG4gICAgICAgICAgYW1vdW50OiB1cGRhdGVba2V5XSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSB1cGRhdGVba2V5XTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChkZXZpY2VzVG9SZW1vdmUubGVuZ3RoID4gMCAmJiBjbGVhbnVwSW5zdGFsbGF0aW9ucykge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGBSZW1vdmluZyBkZXZpY2UgdG9rZW5zIG9uICR7ZGV2aWNlc1RvUmVtb3ZlLmxlbmd0aH0gX0luc3RhbGxhdGlvbnNgXG4gICAgICApO1xuICAgICAgZGF0YWJhc2UudXBkYXRlKFxuICAgICAgICAnX0luc3RhbGxhdGlvbicsXG4gICAgICAgIHsgZGV2aWNlVG9rZW46IHsgJGluOiBkZXZpY2VzVG9SZW1vdmUgfSB9LFxuICAgICAgICB7IGRldmljZVRva2VuOiB7IF9fb3A6ICdEZWxldGUnIH0gfSxcbiAgICAgICAge1xuICAgICAgICAgIGFjbDogdW5kZWZpbmVkLFxuICAgICAgICAgIG1hbnk6IHRydWUsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gaW5kaWNhdGUgdGhpcyBiYXRjaCBpcyBjb21wbGV0ZVxuICAgIGluY3JlbWVudE9wKHVwZGF0ZSwgJ2NvdW50JywgLTEpO1xuXG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgdXBkYXRlKS50aGVuKHJlcyA9PiB7XG4gICAgICBpZiAocmVzICYmIHJlcy5jb3VudCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21wbGV0ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IGNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKFxuICAgICAgeyBvYmplY3RJZCB9LFxuICAgICAge1xuICAgICAgICBzdGF0dXM6ICdzdWNjZWVkZWQnLFxuICAgICAgICBjb3VudDogeyBfX29wOiAnRGVsZXRlJyB9LFxuICAgICAgfVxuICAgICk7XG4gIH07XG5cbiAgY29uc3QgZmFpbCA9IGZ1bmN0aW9uKGVycikge1xuICAgIGlmICh0eXBlb2YgZXJyID09PSAnc3RyaW5nJykge1xuICAgICAgZXJyID0geyBtZXNzYWdlOiBlcnIgfTtcbiAgICB9XG4gICAgY29uc3QgdXBkYXRlID0ge1xuICAgICAgZXJyb3JNZXNzYWdlOiBlcnIsXG4gICAgICBzdGF0dXM6ICdmYWlsZWQnLFxuICAgIH07XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgdXBkYXRlKTtcbiAgfTtcblxuICBjb25zdCBydmFsID0ge1xuICAgIHNldEluaXRpYWwsXG4gICAgc2V0UnVubmluZyxcbiAgICB0cmFja1NlbnQsXG4gICAgY29tcGxldGUsXG4gICAgZmFpbCxcbiAgfTtcblxuICAvLyBkZWZpbmUgb2JqZWN0SWQgdG8gYmUgZHluYW1pY1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkocnZhbCwgJ29iamVjdElkJywge1xuICAgIGdldDogKCkgPT4gb2JqZWN0SWQsXG4gIH0pO1xuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKHJ2YWwpO1xufVxuIl19 \ No newline at end of file diff --git a/lib/TestUtils.js b/lib/TestUtils.js new file mode 100644 index 0000000000..043a6dd202 --- /dev/null +++ b/lib/TestUtils.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.destroyAllDataPermanently = destroyAllDataPermanently; + +var _cache = _interopRequireDefault(require("./cache")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Destroys all data in the database + * @param {boolean} fast set to true if it's ok to just drop objects and not indexes. + */ +function destroyAllDataPermanently(fast) { + if (!process.env.TESTING) { + throw 'Only supported in test environment'; + } + + return Promise.all(Object.keys(_cache.default.cache).map(appId => { + const app = _cache.default.get(appId); + + if (app.databaseController) { + return app.databaseController.deleteEverything(fast); + } else { + return Promise.resolve(); + } + })); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9UZXN0VXRpbHMuanMiXSwibmFtZXMiOlsiZGVzdHJveUFsbERhdGFQZXJtYW5lbnRseSIsImZhc3QiLCJwcm9jZXNzIiwiZW52IiwiVEVTVElORyIsIlByb21pc2UiLCJhbGwiLCJPYmplY3QiLCJrZXlzIiwiQXBwQ2FjaGUiLCJjYWNoZSIsIm1hcCIsImFwcElkIiwiYXBwIiwiZ2V0IiwiZGF0YWJhc2VDb250cm9sbGVyIiwiZGVsZXRlRXZlcnl0aGluZyIsInJlc29sdmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUVBOzs7O0FBSU8sU0FBU0EseUJBQVQsQ0FBbUNDLElBQW5DLEVBQXlDO0FBQzlDLE1BQUksQ0FBQ0MsT0FBTyxDQUFDQyxHQUFSLENBQVlDLE9BQWpCLEVBQTBCO0FBQ3hCLFVBQU0sb0NBQU47QUFDRDs7QUFDRCxTQUFPQyxPQUFPLENBQUNDLEdBQVIsQ0FDTEMsTUFBTSxDQUFDQyxJQUFQLENBQVlDLGVBQVNDLEtBQXJCLEVBQTRCQyxHQUE1QixDQUFnQ0MsS0FBSyxJQUFJO0FBQ3ZDLFVBQU1DLEdBQUcsR0FBR0osZUFBU0ssR0FBVCxDQUFhRixLQUFiLENBQVo7O0FBQ0EsUUFBSUMsR0FBRyxDQUFDRSxrQkFBUixFQUE0QjtBQUMxQixhQUFPRixHQUFHLENBQUNFLGtCQUFKLENBQXVCQyxnQkFBdkIsQ0FBd0NmLElBQXhDLENBQVA7QUFDRCxLQUZELE1BRU87QUFDTCxhQUFPSSxPQUFPLENBQUNZLE9BQVIsRUFBUDtBQUNEO0FBQ0YsR0FQRCxDQURLLENBQVA7QUFVRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBBcHBDYWNoZSBmcm9tICcuL2NhY2hlJztcblxuLyoqXG4gKiBEZXN0cm95cyBhbGwgZGF0YSBpbiB0aGUgZGF0YWJhc2VcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZmFzdCBzZXQgdG8gdHJ1ZSBpZiBpdCdzIG9rIHRvIGp1c3QgZHJvcCBvYmplY3RzIGFuZCBub3QgaW5kZXhlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlc3Ryb3lBbGxEYXRhUGVybWFuZW50bHkoZmFzdCkge1xuICBpZiAoIXByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICB0aHJvdyAnT25seSBzdXBwb3J0ZWQgaW4gdGVzdCBlbnZpcm9ubWVudCc7XG4gIH1cbiAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgIE9iamVjdC5rZXlzKEFwcENhY2hlLmNhY2hlKS5tYXAoYXBwSWQgPT4ge1xuICAgICAgY29uc3QgYXBwID0gQXBwQ2FjaGUuZ2V0KGFwcElkKTtcbiAgICAgIGlmIChhcHAuZGF0YWJhc2VDb250cm9sbGVyKSB7XG4gICAgICAgIHJldHVybiBhcHAuZGF0YWJhc2VDb250cm9sbGVyLmRlbGV0ZUV2ZXJ5dGhpbmcoZmFzdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSlcbiAgKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/batch.js b/lib/batch.js new file mode 100644 index 0000000000..2f283d9cbb --- /dev/null +++ b/lib/batch.js @@ -0,0 +1,132 @@ +"use strict"; + +const Parse = require('parse/node').Parse; + +const url = require('url'); + +const path = require('path'); // These methods handle batch requests. + + +const batchPath = '/batch'; // Mounts a batch-handler onto a PromiseRouter. + +function mountOnto(router) { + router.route('POST', batchPath, req => { + return handleBatch(router, req); + }); +} + +function parseURL(URL) { + if (typeof URL === 'string') { + return url.parse(URL); + } + + return undefined; +} + +function makeBatchRoutingPathFunction(originalUrl, serverURL, publicServerURL) { + serverURL = serverURL ? parseURL(serverURL) : undefined; + publicServerURL = publicServerURL ? parseURL(publicServerURL) : undefined; + const apiPrefixLength = originalUrl.length - batchPath.length; + let apiPrefix = originalUrl.slice(0, apiPrefixLength); + + const makeRoutablePath = function (requestPath) { + // The routablePath is the path minus the api prefix + if (requestPath.slice(0, apiPrefix.length) != apiPrefix) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'cannot route batch path ' + requestPath); + } + + return path.posix.join('/', requestPath.slice(apiPrefix.length)); + }; + + if (serverURL && publicServerURL && serverURL.path != publicServerURL.path) { + const localPath = serverURL.path; + const publicPath = publicServerURL.path; // Override the api prefix + + apiPrefix = localPath; + return function (requestPath) { + // Build the new path by removing the public path + // and joining with the local path + const newPath = path.posix.join('/', localPath, '/', requestPath.slice(publicPath.length)); // Use the method for local routing + + return makeRoutablePath(newPath); + }; + } + + return makeRoutablePath; +} // Returns a promise for a {response} object. +// TODO: pass along auth correctly + + +function handleBatch(router, req) { + if (!Array.isArray(req.body.requests)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'requests must be an array'); + } // The batch paths are all from the root of our domain. + // That means they include the API prefix, that the API is mounted + // to. However, our promise router does not route the api prefix. So + // we need to figure out the API prefix, so that we can strip it + // from all the subrequests. + + + if (!req.originalUrl.endsWith(batchPath)) { + throw 'internal routing problem - expected url to end with batch'; + } + + const makeRoutablePath = makeBatchRoutingPathFunction(req.originalUrl, req.config.serverURL, req.config.publicServerURL); + let initialPromise = Promise.resolve(); + + if (req.body.transaction === true) { + initialPromise = req.config.database.createTransactionalSession(); + } + + return initialPromise.then(() => { + const promises = req.body.requests.map(restRequest => { + const routablePath = makeRoutablePath(restRequest.path); // Construct a request that we can send to a handler + + const request = { + body: restRequest.body, + config: req.config, + auth: req.auth, + info: req.info + }; + return router.tryRouteRequest(restRequest.method, routablePath, request).then(response => { + return { + success: response.response + }; + }, error => { + return { + error: { + code: error.code, + error: error.message + } + }; + }); + }); + return Promise.all(promises).then(results => { + if (req.body.transaction === true) { + if (results.find(result => typeof result.error === 'object')) { + return req.config.database.abortTransactionalSession().then(() => { + return Promise.reject({ + response: results + }); + }); + } else { + return req.config.database.commitTransactionalSession().then(() => { + return { + response: results + }; + }); + } + } else { + return { + response: results + }; + } + }); + }); +} + +module.exports = { + mountOnto, + makeBatchRoutingPathFunction +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9iYXRjaC5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJ1cmwiLCJwYXRoIiwiYmF0Y2hQYXRoIiwibW91bnRPbnRvIiwicm91dGVyIiwicm91dGUiLCJyZXEiLCJoYW5kbGVCYXRjaCIsInBhcnNlVVJMIiwiVVJMIiwicGFyc2UiLCJ1bmRlZmluZWQiLCJtYWtlQmF0Y2hSb3V0aW5nUGF0aEZ1bmN0aW9uIiwib3JpZ2luYWxVcmwiLCJzZXJ2ZXJVUkwiLCJwdWJsaWNTZXJ2ZXJVUkwiLCJhcGlQcmVmaXhMZW5ndGgiLCJsZW5ndGgiLCJhcGlQcmVmaXgiLCJzbGljZSIsIm1ha2VSb3V0YWJsZVBhdGgiLCJyZXF1ZXN0UGF0aCIsIkVycm9yIiwiSU5WQUxJRF9KU09OIiwicG9zaXgiLCJqb2luIiwibG9jYWxQYXRoIiwicHVibGljUGF0aCIsIm5ld1BhdGgiLCJBcnJheSIsImlzQXJyYXkiLCJib2R5IiwicmVxdWVzdHMiLCJlbmRzV2l0aCIsImNvbmZpZyIsImluaXRpYWxQcm9taXNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0cmFuc2FjdGlvbiIsImRhdGFiYXNlIiwiY3JlYXRlVHJhbnNhY3Rpb25hbFNlc3Npb24iLCJ0aGVuIiwicHJvbWlzZXMiLCJtYXAiLCJyZXN0UmVxdWVzdCIsInJvdXRhYmxlUGF0aCIsInJlcXVlc3QiLCJhdXRoIiwiaW5mbyIsInRyeVJvdXRlUmVxdWVzdCIsIm1ldGhvZCIsInJlc3BvbnNlIiwic3VjY2VzcyIsImVycm9yIiwiY29kZSIsIm1lc3NhZ2UiLCJhbGwiLCJyZXN1bHRzIiwiZmluZCIsInJlc3VsdCIsImFib3J0VHJhbnNhY3Rpb25hbFNlc3Npb24iLCJyZWplY3QiLCJjb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbiIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUEsTUFBTUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCRCxLQUFwQzs7QUFDQSxN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QUNEO0FBQ0YsS0FkTSxDQUFQO0FBZUQsR0F2Q00sQ0FBUDtBQXdDRDs7QUFFRE0sTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2Y3RCxFQUFBQSxTQURlO0FBRWZTLEVBQUFBO0FBRmUsQ0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IHVybCA9IHJlcXVpcmUoJ3VybCcpO1xuY29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTtcbi8vIFRoZXNlIG1ldGhvZHMgaGFuZGxlIGJhdGNoIHJlcXVlc3RzLlxuY29uc3QgYmF0Y2hQYXRoID0gJy9iYXRjaCc7XG5cbi8vIE1vdW50cyBhIGJhdGNoLWhhbmRsZXIgb250byBhIFByb21pc2VSb3V0ZXIuXG5mdW5jdGlvbiBtb3VudE9udG8ocm91dGVyKSB7XG4gIHJvdXRlci5yb3V0ZSgnUE9TVCcsIGJhdGNoUGF0aCwgcmVxID0+IHtcbiAgICByZXR1cm4gaGFuZGxlQmF0Y2gocm91dGVyLCByZXEpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gcGFyc2VVUkwoVVJMKSB7XG4gIGlmICh0eXBlb2YgVVJMID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiB1cmwucGFyc2UoVVJMKTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBtYWtlQmF0Y2hSb3V0aW5nUGF0aEZ1bmN0aW9uKG9yaWdpbmFsVXJsLCBzZXJ2ZXJVUkwsIHB1YmxpY1NlcnZlclVSTCkge1xuICBzZXJ2ZXJVUkwgPSBzZXJ2ZXJVUkwgPyBwYXJzZVVSTChzZXJ2ZXJVUkwpIDogdW5kZWZpbmVkO1xuICBwdWJsaWNTZXJ2ZXJVUkwgPSBwdWJsaWNTZXJ2ZXJVUkwgPyBwYXJzZVVSTChwdWJsaWNTZXJ2ZXJVUkwpIDogdW5kZWZpbmVkO1xuXG4gIGNvbnN0IGFwaVByZWZpeExlbmd0aCA9IG9yaWdpbmFsVXJsLmxlbmd0aCAtIGJhdGNoUGF0aC5sZW5ndGg7XG4gIGxldCBhcGlQcmVmaXggPSBvcmlnaW5hbFVybC5zbGljZSgwLCBhcGlQcmVmaXhMZW5ndGgpO1xuXG4gIGNvbnN0IG1ha2VSb3V0YWJsZVBhdGggPSBmdW5jdGlvbihyZXF1ZXN0UGF0aCkge1xuICAgIC8vIFRoZSByb3V0YWJsZVBhdGggaXMgdGhlIHBhdGggbWludXMgdGhlIGFwaSBwcmVmaXhcbiAgICBpZiAocmVxdWVzdFBhdGguc2xpY2UoMCwgYXBpUHJlZml4Lmxlbmd0aCkgIT0gYXBpUHJlZml4KSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgJ2Nhbm5vdCByb3V0ZSBiYXRjaCBwYXRoICcgKyByZXF1ZXN0UGF0aFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGgucG9zaXguam9pbignLycsIHJlcXVlc3RQYXRoLnNsaWNlKGFwaVByZWZpeC5sZW5ndGgpKTtcbiAgfTtcblxuICBpZiAoc2VydmVyVVJMICYmIHB1YmxpY1NlcnZlclVSTCAmJiBzZXJ2ZXJVUkwucGF0aCAhPSBwdWJsaWNTZXJ2ZXJVUkwucGF0aCkge1xuICAgIGNvbnN0IGxvY2FsUGF0aCA9IHNlcnZlclVSTC5wYXRoO1xuICAgIGNvbnN0IHB1YmxpY1BhdGggPSBwdWJsaWNTZXJ2ZXJVUkwucGF0aDtcbiAgICAvLyBPdmVycmlkZSB0aGUgYXBpIHByZWZpeFxuICAgIGFwaVByZWZpeCA9IGxvY2FsUGF0aDtcbiAgICByZXR1cm4gZnVuY3Rpb24ocmVxdWVzdFBhdGgpIHtcbiAgICAgIC8vIEJ1aWxkIHRoZSBuZXcgcGF0aCBieSByZW1vdmluZyB0aGUgcHVibGljIHBhdGhcbiAgICAgIC8vIGFuZCBqb2luaW5nIHdpdGggdGhlIGxvY2FsIHBhdGhcbiAgICAgIGNvbnN0IG5ld1BhdGggPSBwYXRoLnBvc2l4LmpvaW4oXG4gICAgICAgICcvJyxcbiAgICAgICAgbG9jYWxQYXRoLFxuICAgICAgICAnLycsXG4gICAgICAgIHJlcXVlc3RQYXRoLnNsaWNlKHB1YmxpY1BhdGgubGVuZ3RoKVxuICAgICAgKTtcbiAgICAgIC8vIFVzZSB0aGUgbWV0aG9kIGZvciBsb2NhbCByb3V0aW5nXG4gICAgICByZXR1cm4gbWFrZVJvdXRhYmxlUGF0aChuZXdQYXRoKTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIG1ha2VSb3V0YWJsZVBhdGg7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHtyZXNwb25zZX0gb2JqZWN0LlxuLy8gVE9ETzogcGFzcyBhbG9uZyBhdXRoIGNvcnJlY3RseVxuZnVuY3Rpb24gaGFuZGxlQmF0Y2gocm91dGVyLCByZXEpIHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KHJlcS5ib2R5LnJlcXVlc3RzKSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICdyZXF1ZXN0cyBtdXN0IGJlIGFuIGFycmF5J1xuICAgICk7XG4gIH1cblxuICAvLyBUaGUgYmF0Y2ggcGF0aHMgYXJlIGFsbCBmcm9tIHRoZSByb290IG9mIG91ciBkb21haW4uXG4gIC8vIFRoYXQgbWVhbnMgdGhleSBpbmNsdWRlIHRoZSBBUEkgcHJlZml4LCB0aGF0IHRoZSBBUEkgaXMgbW91bnRlZFxuICAvLyB0by4gSG93ZXZlciwgb3VyIHByb21pc2Ugcm91dGVyIGRvZXMgbm90IHJvdXRlIHRoZSBhcGkgcHJlZml4LiBTb1xuICAvLyB3ZSBuZWVkIHRvIGZpZ3VyZSBvdXQgdGhlIEFQSSBwcmVmaXgsIHNvIHRoYXQgd2UgY2FuIHN0cmlwIGl0XG4gIC8vIGZyb20gYWxsIHRoZSBzdWJyZXF1ZXN0cy5cbiAgaWYgKCFyZXEub3JpZ2luYWxVcmwuZW5kc1dpdGgoYmF0Y2hQYXRoKSkge1xuICAgIHRocm93ICdpbnRlcm5hbCByb3V0aW5nIHByb2JsZW0gLSBleHBlY3RlZCB1cmwgdG8gZW5kIHdpdGggYmF0Y2gnO1xuICB9XG5cbiAgY29uc3QgbWFrZVJvdXRhYmxlUGF0aCA9IG1ha2VCYXRjaFJvdXRpbmdQYXRoRnVuY3Rpb24oXG4gICAgcmVxLm9yaWdpbmFsVXJsLFxuICAgIHJlcS5jb25maWcuc2VydmVyVVJMLFxuICAgIHJlcS5jb25maWcucHVibGljU2VydmVyVVJMXG4gICk7XG5cbiAgbGV0IGluaXRpYWxQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIGlmIChyZXEuYm9keS50cmFuc2FjdGlvbiA9PT0gdHJ1ZSkge1xuICAgIGluaXRpYWxQcm9taXNlID0gcmVxLmNvbmZpZy5kYXRhYmFzZS5jcmVhdGVUcmFuc2FjdGlvbmFsU2Vzc2lvbigpO1xuICB9XG5cbiAgcmV0dXJuIGluaXRpYWxQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgIGNvbnN0IHByb21pc2VzID0gcmVxLmJvZHkucmVxdWVzdHMubWFwKHJlc3RSZXF1ZXN0ID0+IHtcbiAgICAgIGNvbnN0IHJvdXRhYmxlUGF0aCA9IG1ha2VSb3V0YWJsZVBhdGgocmVzdFJlcXVlc3QucGF0aCk7XG4gICAgICAvLyBDb25zdHJ1Y3QgYSByZXF1ZXN0IHRoYXQgd2UgY2FuIHNlbmQgdG8gYSBoYW5kbGVyXG5cbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICAgIGJvZHk6IHJlc3RSZXF1ZXN0LmJvZHksXG4gICAgICAgIGNvbmZpZzogcmVxLmNvbmZpZyxcbiAgICAgICAgYXV0aDogcmVxLmF1dGgsXG4gICAgICAgIGluZm86IHJlcS5pbmZvLFxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHJvdXRlclxuICAgICAgICAudHJ5Um91dGVSZXF1ZXN0KHJlc3RSZXF1ZXN0Lm1ldGhvZCwgcm91dGFibGVQYXRoLCByZXF1ZXN0KVxuICAgICAgICAudGhlbihcbiAgICAgICAgICByZXNwb25zZSA9PiB7XG4gICAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiByZXNwb25zZS5yZXNwb25zZSB9O1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZXJyb3IgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHsgZXJyb3I6IHsgY29kZTogZXJyb3IuY29kZSwgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfSB9O1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbihyZXN1bHRzID0+IHtcbiAgICAgIGlmIChyZXEuYm9keS50cmFuc2FjdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICBpZiAocmVzdWx0cy5maW5kKHJlc3VsdCA9PiB0eXBlb2YgcmVzdWx0LmVycm9yID09PSAnb2JqZWN0JykpIHtcbiAgICAgICAgICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZS5hYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoeyByZXNwb25zZTogcmVzdWx0cyB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZS5jb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbigpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHJlc3VsdHMgfTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHJlc3VsdHMgfTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBtb3VudE9udG8sXG4gIG1ha2VCYXRjaFJvdXRpbmdQYXRoRnVuY3Rpb24sXG59O1xuIl19 \ No newline at end of file diff --git a/lib/cache.js b/lib/cache.js new file mode 100644 index 0000000000..ddeda818f9 --- /dev/null +++ b/lib/cache.js @@ -0,0 +1,16 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.AppCache = void 0; + +var _InMemoryCache = require("./Adapters/Cache/InMemoryCache"); + +var AppCache = new _InMemoryCache.InMemoryCache({ + ttl: NaN +}); +exports.AppCache = AppCache; +var _default = AppCache; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jYWNoZS5qcyJdLCJuYW1lcyI6WyJBcHBDYWNoZSIsIkluTWVtb3J5Q2FjaGUiLCJ0dGwiLCJOYU4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFFTyxJQUFJQSxRQUFRLEdBQUcsSUFBSUMsNEJBQUosQ0FBa0I7QUFBRUMsRUFBQUEsR0FBRyxFQUFFQztBQUFQLENBQWxCLENBQWY7O2VBQ1FILFEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbk1lbW9yeUNhY2hlIH0gZnJvbSAnLi9BZGFwdGVycy9DYWNoZS9Jbk1lbW9yeUNhY2hlJztcblxuZXhwb3J0IHZhciBBcHBDYWNoZSA9IG5ldyBJbk1lbW9yeUNhY2hlKHsgdHRsOiBOYU4gfSk7XG5leHBvcnQgZGVmYXVsdCBBcHBDYWNoZTtcbiJdfQ== \ No newline at end of file diff --git a/lib/cli/definitions/parse-live-query-server.js b/lib/cli/definitions/parse-live-query-server.js new file mode 100644 index 0000000000..2aac33fdba --- /dev/null +++ b/lib/cli/definitions/parse-live-query-server.js @@ -0,0 +1,12 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +const LiveQueryServerOptions = require('../../Options/Definitions').LiveQueryServerOptions; + +var _default = LiveQueryServerOptions; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvZGVmaW5pdGlvbnMvcGFyc2UtbGl2ZS1xdWVyeS1zZXJ2ZXIuanMiXSwibmFtZXMiOlsiTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyIsInJlcXVpcmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQSxNQUFNQSxzQkFBc0IsR0FBR0MsT0FBTyxDQUFDLDJCQUFELENBQVAsQ0FDNUJELHNCQURIOztlQUVlQSxzQiIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IExpdmVRdWVyeVNlcnZlck9wdGlvbnMgPSByZXF1aXJlKCcuLi8uLi9PcHRpb25zL0RlZmluaXRpb25zJylcbiAgLkxpdmVRdWVyeVNlcnZlck9wdGlvbnM7XG5leHBvcnQgZGVmYXVsdCBMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zO1xuIl19 \ No newline at end of file diff --git a/lib/cli/definitions/parse-server.js b/lib/cli/definitions/parse-server.js new file mode 100644 index 0000000000..c4089a0626 --- /dev/null +++ b/lib/cli/definitions/parse-server.js @@ -0,0 +1,12 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +const ParseServerDefinitions = require('../../Options/Definitions').ParseServerOptions; + +var _default = ParseServerDefinitions; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvZGVmaW5pdGlvbnMvcGFyc2Utc2VydmVyLmpzIl0sIm5hbWVzIjpbIlBhcnNlU2VydmVyRGVmaW5pdGlvbnMiLCJyZXF1aXJlIiwiUGFyc2VTZXJ2ZXJPcHRpb25zIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUEsTUFBTUEsc0JBQXNCLEdBQUdDLE9BQU8sQ0FBQywyQkFBRCxDQUFQLENBQzVCQyxrQkFESDs7ZUFFZUYsc0IiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBQYXJzZVNlcnZlckRlZmluaXRpb25zID0gcmVxdWlyZSgnLi4vLi4vT3B0aW9ucy9EZWZpbml0aW9ucycpXG4gIC5QYXJzZVNlcnZlck9wdGlvbnM7XG5leHBvcnQgZGVmYXVsdCBQYXJzZVNlcnZlckRlZmluaXRpb25zO1xuIl19 \ No newline at end of file diff --git a/lib/cli/parse-live-query-server.js b/lib/cli/parse-live-query-server.js new file mode 100644 index 0000000000..c1eff20f21 --- /dev/null +++ b/lib/cli/parse-live-query-server.js @@ -0,0 +1,19 @@ +"use strict"; + +var _parseLiveQueryServer = _interopRequireDefault(require("./definitions/parse-live-query-server")); + +var _runner = _interopRequireDefault(require("./utils/runner")); + +var _index = require("../index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +(0, _runner.default)({ + definitions: _parseLiveQueryServer.default, + start: function (program, options, logOptions) { + logOptions(); + + _index.ParseServer.createLiveQueryServer(undefined, options); + } +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGkvcGFyc2UtbGl2ZS1xdWVyeS1zZXJ2ZXIuanMiXSwibmFtZXMiOlsiZGVmaW5pdGlvbnMiLCJzdGFydCIsInByb2dyYW0iLCJvcHRpb25zIiwibG9nT3B0aW9ucyIsIlBhcnNlU2VydmVyIiwiY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyIiwidW5kZWZpbmVkIl0sIm1hcHBpbmdzIjoiOztBQUFBOztBQUNBOztBQUNBOzs7O0FBRUEscUJBQU87QUFDTEEsRUFBQUEsV0FBVyxFQUFYQSw2QkFESztBQUVMQyxFQUFBQSxLQUFLLEVBQUUsVUFBU0MsT0FBVCxFQUFrQkMsT0FBbEIsRUFBMkJDLFVBQTNCLEVBQXVDO0FBQzVDQSxJQUFBQSxVQUFVOztBQUNWQyx1QkFBWUMscUJBQVosQ0FBa0NDLFNBQWxDLEVBQTZDSixPQUE3QztBQUNEO0FBTEksQ0FBUCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBkZWZpbml0aW9ucyBmcm9tICcuL2RlZmluaXRpb25zL3BhcnNlLWxpdmUtcXVlcnktc2VydmVyJztcbmltcG9ydCBydW5uZXIgZnJvbSAnLi91dGlscy9ydW5uZXInO1xuaW1wb3J0IHsgUGFyc2VTZXJ2ZXIgfSBmcm9tICcuLi9pbmRleCc7XG5cbnJ1bm5lcih7XG4gIGRlZmluaXRpb25zLFxuICBzdGFydDogZnVuY3Rpb24ocHJvZ3JhbSwgb3B0aW9ucywgbG9nT3B0aW9ucykge1xuICAgIGxvZ09wdGlvbnMoKTtcbiAgICBQYXJzZVNlcnZlci5jcmVhdGVMaXZlUXVlcnlTZXJ2ZXIodW5kZWZpbmVkLCBvcHRpb25zKTtcbiAgfSxcbn0pO1xuIl19 \ No newline at end of file diff --git a/lib/cli/parse-server.js b/lib/cli/parse-server.js new file mode 100755 index 0000000000..6f081d9d01 --- /dev/null +++ b/lib/cli/parse-server.js @@ -0,0 +1,111 @@ +"use strict"; + +var _index = _interopRequireDefault(require("../index")); + +var _parseServer = _interopRequireDefault(require("./definitions/parse-server")); + +var _cluster = _interopRequireDefault(require("cluster")); + +var _os = _interopRequireDefault(require("os")); + +var _runner = _interopRequireDefault(require("./utils/runner")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* eslint-disable no-console */ +const help = function () { + console.log(' Get Started guide:'); + console.log(''); + console.log(' Please have a look at the get started guide!'); + console.log(' http://docs.parseplatform.org/parse-server/guide/'); + console.log(''); + console.log(''); + console.log(' Usage with npm start'); + console.log(''); + console.log(' $ npm start -- path/to/config.json'); + console.log(' $ npm start -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL'); + console.log(' $ npm start -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL'); + console.log(''); + console.log(''); + console.log(' Usage:'); + console.log(''); + console.log(' $ parse-server path/to/config.json'); + console.log(' $ parse-server -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL'); + console.log(' $ parse-server -- --appId APP_ID --masterKey MASTER_KEY --serverURL serverURL'); + console.log(''); +}; + +(0, _runner.default)({ + definitions: _parseServer.default, + help, + usage: '[options] ', + start: function (program, options, logOptions) { + if (!options.appId || !options.masterKey) { + program.outputHelp(); + console.error(''); + console.error('\u001b[31mERROR: appId and masterKey are required\u001b[0m'); + console.error(''); + process.exit(1); + } + + if (options['liveQuery.classNames']) { + options.liveQuery = options.liveQuery || {}; + options.liveQuery.classNames = options['liveQuery.classNames']; + delete options['liveQuery.classNames']; + } + + if (options['liveQuery.redisURL']) { + options.liveQuery = options.liveQuery || {}; + options.liveQuery.redisURL = options['liveQuery.redisURL']; + delete options['liveQuery.redisURL']; + } + + if (options['liveQuery.redisOptions']) { + options.liveQuery = options.liveQuery || {}; + options.liveQuery.redisOptions = options['liveQuery.redisOptions']; + delete options['liveQuery.redisOptions']; + } + + if (options.cluster) { + const numCPUs = typeof options.cluster === 'number' ? options.cluster : _os.default.cpus().length; + + if (_cluster.default.isMaster) { + logOptions(); + + for (let i = 0; i < numCPUs; i++) { + _cluster.default.fork(); + } + + _cluster.default.on('exit', (worker, code) => { + console.log(`worker ${worker.process.pid} died (${code})... Restarting`); + + _cluster.default.fork(); + }); + } else { + _index.default.start(options, () => { + printSuccessMessage(); + }); + } + } else { + _index.default.start(options, () => { + logOptions(); + console.log(''); + printSuccessMessage(); + }); + } + + function printSuccessMessage() { + console.log('[' + process.pid + '] parse-server running on ' + options.serverURL); + + if (options.mountGraphQL) { + console.log('[' + process.pid + '] GraphQL running on http://localhost:' + options.port + options.graphQLPath); + } + + if (options.mountPlayground) { + console.log('[' + process.pid + '] Playground running on http://localhost:' + options.port + options.playgroundPath); + } + } + } +}); +/* eslint-enable no-console */ +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGkvcGFyc2Utc2VydmVyLmpzIl0sIm5hbWVzIjpbImhlbHAiLCJjb25zb2xlIiwibG9nIiwiZGVmaW5pdGlvbnMiLCJ1c2FnZSIsInN0YXJ0IiwicHJvZ3JhbSIsIm9wdGlvbnMiLCJsb2dPcHRpb25zIiwiYXBwSWQiLCJtYXN0ZXJLZXkiLCJvdXRwdXRIZWxwIiwiZXJyb3IiLCJwcm9jZXNzIiwiZXhpdCIsImxpdmVRdWVyeSIsImNsYXNzTmFtZXMiLCJyZWRpc1VSTCIsInJlZGlzT3B0aW9ucyIsImNsdXN0ZXIiLCJudW1DUFVzIiwib3MiLCJjcHVzIiwibGVuZ3RoIiwiaXNNYXN0ZXIiLCJpIiwiZm9yayIsIm9uIiwid29ya2VyIiwiY29kZSIsInBpZCIsIlBhcnNlU2VydmVyIiwicHJpbnRTdWNjZXNzTWVzc2FnZSIsInNlcnZlclVSTCIsIm1vdW50R3JhcGhRTCIsInBvcnQiLCJncmFwaFFMUGF0aCIsIm1vdW50UGxheWdyb3VuZCIsInBsYXlncm91bmRQYXRoIl0sIm1hcHBpbmdzIjoiOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBTEE7QUFPQSxNQUFNQSxJQUFJLEdBQUcsWUFBVztBQUN0QkMsRUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQVksc0JBQVo7QUFDQUQsRUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQVksRUFBWjtBQUNBRCxFQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FBWSxrREFBWjtBQUNBRCxFQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FBWSx1REFBWjtBQUNBRCxFQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FBWSxFQUFaO0FBQ0FELEVBQUFBLE9BQU8sQ0FBQ0MsR0FBUixDQUFZLEVBQVo7QUFDQUQsRUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQVksd0JBQVo7QUFDQUQsRUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQVksRUFBWjtBQUNBRCxFQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FBWSx3Q0FBWjtBQUNB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LE9BQU8sQ0FBQ0MsR0FBUixDQUNHLFVBQVMwQixNQUFNLENBQUNmLE9BQVAsQ0FBZWlCLEdBQUksVUFBU0QsSUFBSyxpQkFEN0M7O0FBR0FWLDJCQUFRTyxJQUFSO0FBQ0QsU0FMRDtBQU1ELE9BWEQsTUFXTztBQUNMSyx1QkFBWTFCLEtBQVosQ0FBa0JFLE9BQWxCLEVBQTJCLE1BQU07QUFDL0J5QixVQUFBQSxtQkFBbUI7QUFDcEIsU0FGRDtBQUdEO0FBQ0YsS0FyQkQsTUFxQk87QUFDTEQscUJBQVkxQixLQUFaLENBQWtCRSxPQUFsQixFQUEyQixNQUFNO0FBQy9CQyxRQUFBQSxVQUFVO0FBQ1ZQLFFBQUFBLE9BQU8sQ0FBQ0MsR0FBUixDQUFZLEVBQVo7QUFDQThCLFFBQUFBLG1CQUFtQjtBQUNwQixPQUpEO0FBS0Q7O0FBRUQsYUFBU0EsbUJBQVQsR0FBK0I7QUFDN0IvQixNQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FDRSxNQUFNVyxPQUFPLENBQUNpQixHQUFkLEdBQW9CLDRCQUFwQixHQUFtRHZCLE9BQU8sQ0FBQzBCLFNBRDdEOztBQUdBLFVBQUkxQixPQUFPLENBQUMyQixZQUFaLEVBQTBCO0FBQ3hCakMsUUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQ0UsTUFDRVcsT0FBTyxDQUFDaUIsR0FEVixHQUVFLHdDQUZGLEdBR0V2QixPQUFPLENBQUM0QixJQUhWLEdBSUU1QixPQUFPLENBQUM2QixXQUxaO0FBT0Q7O0FBQ0QsVUFBSTdCLE9BQU8sQ0FBQzhCLGVBQVosRUFBNkI7QUFDM0JwQyxRQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FDRSxNQUNFVyxPQUFPLENBQUNpQixHQURWLEdBRUUsMkNBRkYsR0FHRXZCLE9BQU8sQ0FBQzRCLElBSFYsR0FJRTVCLE9BQU8sQ0FBQytCLGNBTFo7QUFPRDtBQUNGO0FBQ0Y7QUFuRkksQ0FBUDtBQXNGQSIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbmltcG9ydCBQYXJzZVNlcnZlciBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgZGVmaW5pdGlvbnMgZnJvbSAnLi9kZWZpbml0aW9ucy9wYXJzZS1zZXJ2ZXInO1xuaW1wb3J0IGNsdXN0ZXIgZnJvbSAnY2x1c3Rlcic7XG5pbXBvcnQgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHJ1bm5lciBmcm9tICcuL3V0aWxzL3J1bm5lcic7XG5cbmNvbnN0IGhlbHAgPSBmdW5jdGlvbigpIHtcbiAgY29uc29sZS5sb2coJyAgR2V0IFN0YXJ0ZWQgZ3VpZGU6Jyk7XG4gIGNvbnNvbGUubG9nKCcnKTtcbiAgY29uc29sZS5sb2coJyAgICBQbGVhc2UgaGF2ZSBhIGxvb2sgYXQgdGhlIGdldCBzdGFydGVkIGd1aWRlIScpO1xuICBjb25zb2xlLmxvZygnICAgIGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8nKTtcbiAgY29uc29sZS5sb2coJycpO1xuICBjb25zb2xlLmxvZygnJyk7XG4gIGNvbnNvbGUubG9nKCcgIFVzYWdlIHdpdGggbnBtIHN0YXJ0Jyk7XG4gIGNvbnNvbGUubG9nKCcnKTtcbiAgY29uc29sZS5sb2coJyAgICAkIG5wbSBzdGFydCAtLSBwYXRoL3RvL2NvbmZpZy5qc29uJyk7XG4gIGNvbnNvbGUubG9nKFxuICAgICcgICAgJCBucG0gc3RhcnQgLS0gLS1hcHBJZCBBUFBfSUQgLS1tYXN0ZXJLZXkgTUFTVEVSX0tFWSAtLXNlcnZlclVSTCBzZXJ2ZXJVUkwnXG4gICk7XG4gIGNvbnNvbGUubG9nKFxuICAgICcgICAgJCBucG0gc3RhcnQgLS0gLS1hcHBJZCBBUFBfSUQgLS1tYXN0ZXJLZXkgTUFTVEVSX0tFWSAtLXNlcnZlclVSTCBzZXJ2ZXJVUkwnXG4gICk7XG4gIGNvbnNvbGUubG9nKCcnKTtcbiAgY29uc29sZS5sb2coJycpO1xuICBjb25zb2xlLmxvZygnICBVc2FnZTonKTtcbiAgY29uc29sZS5sb2coJycpO1xuICBjb25zb2xlLmxvZygnICAgICQgcGFyc2Utc2VydmVyIHBhdGgvdG8vY29uZmlnLmpzb24nKTtcbiAgY29uc29sZS5sb2coXG4gICAgJyAgICAkIHBhcnNlLXNlcnZlciAtLSAtLWFwcElkIEFQUF9JRCAtLW1hc3RlcktleSBNQVNURVJfS0VZIC0tc2VydmVyVVJMIHNlcnZlclVSTCdcbiAgKTtcbiAgY29uc29sZS5sb2coXG4gICAgJyAgICAkIHBhcnNlLXNlcnZlciAtLSAtLWFwcElkIEFQUF9JRCAtLW1hc3RlcktleSBNQVNURVJfS0VZIC0tc2VydmVyVVJMIHNlcnZlclVSTCdcbiAgKTtcbiAgY29uc29sZS5sb2coJycpO1xufTtcblxucnVubmVyKHtcbiAgZGVmaW5pdGlvbnMsXG4gIGhlbHAsXG4gIHVzYWdlOiAnW29wdGlvbnNdIDxwYXRoL3RvL2NvbmZpZ3VyYXRpb24uanNvbj4nLFxuICBzdGFydDogZnVuY3Rpb24ocHJvZ3JhbSwgb3B0aW9ucywgbG9nT3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucy5hcHBJZCB8fCAhb3B0aW9ucy5tYXN0ZXJLZXkpIHtcbiAgICAgIHByb2dyYW0ub3V0cHV0SGVscCgpO1xuICAgICAgY29uc29sZS5lcnJvcignJyk7XG4gICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAnXFx1MDAxYlszMW1FUlJPUjogYXBwSWQgYW5kIG1hc3RlcktleSBhcmUgcmVxdWlyZWRcXHUwMDFiWzBtJ1xuICAgICAgKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJycpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zWydsaXZlUXVlcnkuY2xhc3NOYW1lcyddKSB7XG4gICAgICBvcHRpb25zLmxpdmVRdWVyeSA9IG9wdGlvbnMubGl2ZVF1ZXJ5IHx8IHt9O1xuICAgICAgb3B0aW9ucy5saXZlUXVlcnkuY2xhc3NOYW1lcyA9IG9wdGlvbnNbJ2xpdmVRdWVyeS5jbGFzc05hbWVzJ107XG4gICAgICBkZWxldGUgb3B0aW9uc1snbGl2ZVF1ZXJ5LmNsYXNzTmFtZXMnXTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnNbJ2xpdmVRdWVyeS5yZWRpc1VSTCddKSB7XG4gICAgICBvcHRpb25zLmxpdmVRdWVyeSA9IG9wdGlvbnMubGl2ZVF1ZXJ5IHx8IHt9O1xuICAgICAgb3B0aW9ucy5saXZlUXVlcnkucmVkaXNVUkwgPSBvcHRpb25zWydsaXZlUXVlcnkucmVkaXNVUkwnXTtcbiAgICAgIGRlbGV0ZSBvcHRpb25zWydsaXZlUXVlcnkucmVkaXNVUkwnXTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnNbJ2xpdmVRdWVyeS5yZWRpc09wdGlvbnMnXSkge1xuICAgICAgb3B0aW9ucy5saXZlUXVlcnkgPSBvcHRpb25zLmxpdmVRdWVyeSB8fCB7fTtcbiAgICAgIG9wdGlvbnMubGl2ZVF1ZXJ5LnJlZGlzT3B0aW9ucyA9IG9wdGlvbnNbJ2xpdmVRdWVyeS5yZWRpc09wdGlvbnMnXTtcbiAgICAgIGRlbGV0ZSBvcHRpb25zWydsaXZlUXVlcnkucmVkaXNPcHRpb25zJ107XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuY2x1c3Rlcikge1xuICAgICAgY29uc3QgbnVtQ1BVcyA9XG4gICAgICAgIHR5cGVvZiBvcHRpb25zLmNsdXN0ZXIgPT09ICdudW1iZXInXG4gICAgICAgICAgPyBvcHRpb25zLmNsdXN0ZXJcbiAgICAgICAgICA6IG9zLmNwdXMoKS5sZW5ndGg7XG4gICAgICBpZiAoY2x1c3Rlci5pc01hc3Rlcikge1xuICAgICAgICBsb2dPcHRpb25zKCk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ1BVczsgaSsrKSB7XG4gICAgICAgICAgY2x1c3Rlci5mb3JrKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2x1c3Rlci5vbignZXhpdCcsICh3b3JrZXIsIGNvZGUpID0+IHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIGB3b3JrZXIgJHt3b3JrZXIucHJvY2Vzcy5waWR9IGRpZWQgKCR7Y29kZX0pLi4uIFJlc3RhcnRpbmdgXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjbHVzdGVyLmZvcmsoKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBQYXJzZVNlcnZlci5zdGFydChvcHRpb25zLCAoKSA9PiB7XG4gICAgICAgICAgcHJpbnRTdWNjZXNzTWVzc2FnZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgUGFyc2VTZXJ2ZXIuc3RhcnQob3B0aW9ucywgKCkgPT4ge1xuICAgICAgICBsb2dPcHRpb25zKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgcHJpbnRTdWNjZXNzTWVzc2FnZSgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJpbnRTdWNjZXNzTWVzc2FnZSgpIHtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnWycgKyBwcm9jZXNzLnBpZCArICddIHBhcnNlLXNlcnZlciBydW5uaW5nIG9uICcgKyBvcHRpb25zLnNlcnZlclVSTFxuICAgICAgKTtcbiAgICAgIGlmIChvcHRpb25zLm1vdW50R3JhcGhRTCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAnWycgK1xuICAgICAgICAgICAgcHJvY2Vzcy5waWQgK1xuICAgICAgICAgICAgJ10gR3JhcGhRTCBydW5uaW5nIG9uIGh0dHA6Ly9sb2NhbGhvc3Q6JyArXG4gICAgICAgICAgICBvcHRpb25zLnBvcnQgK1xuICAgICAgICAgICAgb3B0aW9ucy5ncmFwaFFMUGF0aFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMubW91bnRQbGF5Z3JvdW5kKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICdbJyArXG4gICAgICAgICAgICBwcm9jZXNzLnBpZCArXG4gICAgICAgICAgICAnXSBQbGF5Z3JvdW5kIHJ1bm5pbmcgb24gaHR0cDovL2xvY2FsaG9zdDonICtcbiAgICAgICAgICAgIG9wdGlvbnMucG9ydCArXG4gICAgICAgICAgICBvcHRpb25zLnBsYXlncm91bmRQYXRoXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9LFxufSk7XG5cbi8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuIl19 \ No newline at end of file diff --git a/lib/cli/utils/commander.js b/lib/cli/utils/commander.js new file mode 100644 index 0000000000..cff789e0ad --- /dev/null +++ b/lib/cli/utils/commander.js @@ -0,0 +1,163 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _commander = require("commander"); + +var _path = _interopRequireDefault(require("path")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* eslint-disable no-console */ +let _definitions; + +let _reverseDefinitions; + +let _defaults; + +_commander.Command.prototype.loadDefinitions = function (definitions) { + _definitions = definitions; + Object.keys(definitions).reduce((program, opt) => { + if (typeof definitions[opt] == 'object') { + const additionalOptions = definitions[opt]; + + if (additionalOptions.required === true) { + return program.option(`--${opt} <${opt}>`, additionalOptions.help, additionalOptions.action); + } else { + return program.option(`--${opt} [${opt}]`, additionalOptions.help, additionalOptions.action); + } + } + + return program.option(`--${opt} [${opt}]`); + }, this); + _reverseDefinitions = Object.keys(definitions).reduce((object, key) => { + let value = definitions[key]; + + if (typeof value == 'object') { + value = value.env; + } + + if (value) { + object[value] = key; + } + + return object; + }, {}); + _defaults = Object.keys(definitions).reduce((defs, opt) => { + if (_definitions[opt].default) { + defs[opt] = _definitions[opt].default; + } + + return defs; + }, {}); + /* istanbul ignore next */ + + this.on('--help', function () { + console.log(' Configure From Environment:'); + console.log(''); + Object.keys(_reverseDefinitions).forEach(key => { + console.log(` $ ${key}='${_reverseDefinitions[key]}'`); + }); + console.log(''); + }); +}; + +function parseEnvironment(env = {}) { + return Object.keys(_reverseDefinitions).reduce((options, key) => { + if (env[key]) { + const originalKey = _reverseDefinitions[key]; + + let action = option => option; + + if (typeof _definitions[originalKey] === 'object') { + action = _definitions[originalKey].action || action; + } + + options[_reverseDefinitions[key]] = action(env[key]); + } + + return options; + }, {}); +} + +function parseConfigFile(program) { + let options = {}; + + if (program.args.length > 0) { + let jsonPath = program.args[0]; + jsonPath = _path.default.resolve(jsonPath); + + const jsonConfig = require(jsonPath); + + if (jsonConfig.apps) { + if (jsonConfig.apps.length > 1) { + throw 'Multiple apps are not supported'; + } + + options = jsonConfig.apps[0]; + } else { + options = jsonConfig; + } + + Object.keys(options).forEach(key => { + const value = options[key]; + + if (!_definitions[key]) { + throw `error: unknown option ${key}`; + } + + const action = _definitions[key].action; + + if (action) { + options[key] = action(value); + } + }); + console.log(`Configuration loaded from ${jsonPath}`); + } + + return options; +} + +_commander.Command.prototype.setValuesIfNeeded = function (options) { + Object.keys(options).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(this, key)) { + this[key] = options[key]; + } + }); +}; + +_commander.Command.prototype._parse = _commander.Command.prototype.parse; + +_commander.Command.prototype.parse = function (args, env) { + this._parse(args); // Parse the environment first + + + const envOptions = parseEnvironment(env); + const fromFile = parseConfigFile(this); // Load the env if not passed from command line + + this.setValuesIfNeeded(envOptions); // Load from file to override + + this.setValuesIfNeeded(fromFile); // Last set the defaults + + this.setValuesIfNeeded(_defaults); +}; + +_commander.Command.prototype.getOptions = function () { + return Object.keys(_definitions).reduce((options, key) => { + if (typeof this[key] !== 'undefined') { + options[key] = this[key]; + } + + return options; + }, {}); +}; + +var _default = new _commander.Command(); +/* eslint-enable no-console */ + + +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvdXRpbHMvY29tbWFuZGVyLmpzIl0sIm5hbWVzIjpbIl9kZWZpbml0aW9ucyIsIl9yZXZlcnNlRGVmaW5pdGlvbnMiLCJfZGVmYXVsdHMiLCJDb21tYW5kIiwicHJvdG90eXBlIiwibG9hZERlZmluaXRpb25zIiwiZGVmaW5pdGlvbnMiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwicHJvZ3JhbSIsIm9wdCIsImFkZGl0aW9uYWxPcHRpb25zIiwicmVxdWlyZWQiLCJvcHRpb24iLCJoZWxwIiwiYWN0aW9uIiwib2JqZWN0Iiwia2V5IiwidmFsdWUiLCJlbnYiLCJkZWZzIiwiZGVmYXVsdCIsIm9uIiwiY29uc29sZSIsImxvZyIsImZvckVhY2giLCJwYXJzZUVudmlyb25tZW50Iiwib3B0aW9ucyIsIm9yaWdpbmFsS2V5IiwicGFyc2VDb25maWdGaWxlIiwiYXJncyIsImxlbmd0aCIsImpzb25QYXRoIiwicGF0aCIsInJlc29sdmUiLCJqc29uQ29uZmlnIiwicmVxdWlyZSIsImFwcHMiLCJzZXRWYWx1ZXNJZk5lZWRlZCIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIl9wYXJzZSIsInBhcnNlIiwiZW52T3B0aW9ucyIsImZyb21GaWxlIiwiZ2V0T3B0aW9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQUNBOzs7O0FBRkE7QUFHQSxJQUFJQSxZQUFKOztBQUNBLElBQUlDLG1CQUFKOztBQUNBLElBQUlDLFNBQUo7O0FBRUFDLG1CQUFRQyxTQUFSLENBQWtCQyxlQUFsQixHQUFvQyxVQUFTQyxXQUFULEVBQXNCO0FBQ3hETixFQUFBQSxZQUFZLEdBQUdNLFdBQWY7QUFFQUMsRUFBQUEsTUFBTSxDQUFDQyxJQUFQLENBQVlGLFdBQVosRUFBeUJHLE1BQXpCLENBQWdDLENBQUNDLE9BQUQsRUFBVUMsR0FBVixLQUFrQjtBQUNoRCxRQUFJLE9BQU9MLFdBQVcsQ0FBQ0ssR0FBRCxDQUFsQixJQUEyQixRQUEvQixFQUF5QztB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UixDQUFrQjBDLFVBQWxCLEdBQStCLFlBQVc7QUFDeEMsU0FBT3ZDLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZUixZQUFaLEVBQTBCUyxNQUExQixDQUFpQyxDQUFDbUIsT0FBRCxFQUFVVixHQUFWLEtBQWtCO0FBQ3hELFFBQUksT0FBTyxLQUFLQSxHQUFMLENBQVAsS0FBcUIsV0FBekIsRUFBc0M7QUFDcENVLE1BQUFBLE9BQU8sQ0FBQ1YsR0FBRCxDQUFQLEdBQWUsS0FBS0EsR0FBTCxDQUFmO0FBQ0Q7O0FBQ0QsV0FBT1UsT0FBUDtBQUNELEdBTE0sRUFLSixFQUxJLENBQVA7QUFNRCxDQVBEOztlQVNlLElBQUl6QixrQkFBSixFO0FBQ2YiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xubGV0IF9kZWZpbml0aW9ucztcbmxldCBfcmV2ZXJzZURlZmluaXRpb25zO1xubGV0IF9kZWZhdWx0cztcblxuQ29tbWFuZC5wcm90b3R5cGUubG9hZERlZmluaXRpb25zID0gZnVuY3Rpb24oZGVmaW5pdGlvbnMpIHtcbiAgX2RlZmluaXRpb25zID0gZGVmaW5pdGlvbnM7XG5cbiAgT2JqZWN0LmtleXMoZGVmaW5pdGlvbnMpLnJlZHVjZSgocHJvZ3JhbSwgb3B0KSA9PiB7XG4gICAgaWYgKHR5cGVvZiBkZWZpbml0aW9uc1tvcHRdID09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCBhZGRpdGlvbmFsT3B0aW9ucyA9IGRlZmluaXRpb25zW29wdF07XG4gICAgICBpZiAoYWRkaXRpb25hbE9wdGlvbnMucmVxdWlyZWQgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIHByb2dyYW0ub3B0aW9uKFxuICAgICAgICAgIGAtLSR7b3B0fSA8JHtvcHR9PmAsXG4gICAgICAgICAgYWRkaXRpb25hbE9wdGlvbnMuaGVscCxcbiAgICAgICAgICBhZGRpdGlvbmFsT3B0aW9ucy5hY3Rpb25cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBwcm9ncmFtLm9wdGlvbihcbiAgICAgICAgICBgLS0ke29wdH0gWyR7b3B0fV1gLFxuICAgICAgICAgIGFkZGl0aW9uYWxPcHRpb25zLmhlbHAsXG4gICAgICAgICAgYWRkaXRpb25hbE9wdGlvbnMuYWN0aW9uXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwcm9ncmFtLm9wdGlvbihgLS0ke29wdH0gWyR7b3B0fV1gKTtcbiAgfSwgdGhpcyk7XG5cbiAgX3JldmVyc2VEZWZpbml0aW9ucyA9IE9iamVjdC5rZXlzKGRlZmluaXRpb25zKS5yZWR1Y2UoKG9iamVjdCwga2V5KSA9PiB7XG4gICAgbGV0IHZhbHVlID0gZGVmaW5pdGlvbnNba2V5XTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09ICdvYmplY3QnKSB7XG4gICAgICB2YWx1ZSA9IHZhbHVlLmVudjtcbiAgICB9XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICBvYmplY3RbdmFsdWVdID0ga2V5O1xuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0O1xuICB9LCB7fSk7XG5cbiAgX2RlZmF1bHRzID0gT2JqZWN0LmtleXMoZGVmaW5pdGlvbnMpLnJlZHVjZSgoZGVmcywgb3B0KSA9PiB7XG4gICAgaWYgKF9kZWZpbml0aW9uc1tvcHRdLmRlZmF1bHQpIHtcbiAgICAgIGRlZnNbb3B0XSA9IF9kZWZpbml0aW9uc1tvcHRdLmRlZmF1bHQ7XG4gICAgfVxuICAgIHJldHVybiBkZWZzO1xuICB9LCB7fSk7XG5cbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgdGhpcy5vbignLS1oZWxwJywgZnVuY3Rpb24oKSB7XG4gICAgY29uc29sZS5sb2coJyAgQ29uZmlndXJlIEZyb20gRW52aXJvbm1lbnQ6Jyk7XG4gICAgY29uc29sZS5sb2coJycpO1xuICAgIE9iamVjdC5rZXlzKF9yZXZlcnNlRGVmaW5pdGlvbnMpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKGAgICAgJCAke2tleX09JyR7X3JldmVyc2VEZWZpbml0aW9uc1trZXldfSdgKTtcbiAgICB9KTtcbiAgICBjb25zb2xlLmxvZygnJyk7XG4gIH0pO1xufTtcblxuZnVuY3Rpb24gcGFyc2VFbnZpcm9ubWVudChlbnYgPSB7fSkge1xuICByZXR1cm4gT2JqZWN0LmtleXMoX3JldmVyc2VEZWZpbml0aW9ucykucmVkdWNlKChvcHRpb25zLCBrZXkpID0+IHtcbiAgICBpZiAoZW52W2tleV0pIHtcbiAgICAgIGNvbnN0IG9yaWdpbmFsS2V5ID0gX3JldmVyc2VEZWZpbml0aW9uc1trZXldO1xuICAgICAgbGV0IGFjdGlvbiA9IG9wdGlvbiA9PiBvcHRpb247XG4gICAgICBpZiAodHlwZW9mIF9kZWZpbml0aW9uc1tvcmlnaW5hbEtleV0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGFjdGlvbiA9IF9kZWZpbml0aW9uc1tvcmlnaW5hbEtleV0uYWN0aW9uIHx8IGFjdGlvbjtcbiAgICAgIH1cbiAgICAgIG9wdGlvbnNbX3JldmVyc2VEZWZpbml0aW9uc1trZXldXSA9IGFjdGlvbihlbnZba2V5XSk7XG4gICAgfVxuICAgIHJldHVybiBvcHRpb25zO1xuICB9LCB7fSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlQ29uZmlnRmlsZShwcm9ncmFtKSB7XG4gIGxldCBvcHRpb25zID0ge307XG4gIGlmIChwcm9ncmFtLmFyZ3MubGVuZ3RoID4gMCkge1xuICAgIGxldCBqc29uUGF0aCA9IHByb2dyYW0uYXJnc1swXTtcbiAgICBqc29uUGF0aCA9IHBhdGgucmVzb2x2ZShqc29uUGF0aCk7XG4gICAgY29uc3QganNvbkNvbmZpZyA9IHJlcXVpcmUoanNvblBhdGgpO1xuICAgIGlmIChqc29uQ29uZmlnLmFwcHMpIHtcbiAgICAgIGlmIChqc29uQ29uZmlnLmFwcHMubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyAnTXVsdGlwbGUgYXBwcyBhcmUgbm90IHN1cHBvcnRlZCc7XG4gICAgICB9XG4gICAgICBvcHRpb25zID0ganNvbkNvbmZpZy5hcHBzWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICBvcHRpb25zID0ganNvbkNvbmZpZztcbiAgICB9XG4gICAgT2JqZWN0LmtleXMob3B0aW9ucykuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSBvcHRpb25zW2tleV07XG4gICAgICBpZiAoIV9kZWZpbml0aW9uc1trZXldKSB7XG4gICAgICAgIHRocm93IGBlcnJvcjogdW5rbm93biBvcHRpb24gJHtrZXl9YDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFjdGlvbiA9IF9kZWZpbml0aW9uc1trZXldLmFjdGlvbjtcbiAgICAgIGlmIChhY3Rpb24pIHtcbiAgICAgICAgb3B0aW9uc1trZXldID0gYWN0aW9uKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjb25zb2xlLmxvZyhgQ29uZmlndXJhdGlvbiBsb2FkZWQgZnJvbSAke2pzb25QYXRofWApO1xuICB9XG4gIHJldHVybiBvcHRpb25zO1xufVxuXG5Db21tYW5kLnByb3RvdHlwZS5zZXRWYWx1ZXNJZk5lZWRlZCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgT2JqZWN0LmtleXMob3B0aW9ucykuZm9yRWFjaChrZXkgPT4ge1xuICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMsIGtleSkpIHtcbiAgICAgIHRoaXNba2V5XSA9IG9wdGlvbnNba2V5XTtcbiAgICB9XG4gIH0pO1xufTtcblxuQ29tbWFuZC5wcm90b3R5cGUuX3BhcnNlID0gQ29tbWFuZC5wcm90b3R5cGUucGFyc2U7XG5cbkNvbW1hbmQucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24oYXJncywgZW52KSB7XG4gIHRoaXMuX3BhcnNlKGFyZ3MpO1xuICAvLyBQYXJzZSB0aGUgZW52aXJvbm1lbnQgZmlyc3RcbiAgY29uc3QgZW52T3B0aW9ucyA9IHBhcnNlRW52aXJvbm1lbnQoZW52KTtcbiAgY29uc3QgZnJvbUZpbGUgPSBwYXJzZUNvbmZpZ0ZpbGUodGhpcyk7XG4gIC8vIExvYWQgdGhlIGVudiBpZiBub3QgcGFzc2VkIGZyb20gY29tbWFuZCBsaW5lXG4gIHRoaXMuc2V0VmFsdWVzSWZOZWVkZWQoZW52T3B0aW9ucyk7XG4gIC8vIExvYWQgZnJvbSBmaWxlIHRvIG92ZXJyaWRlXG4gIHRoaXMuc2V0VmFsdWVzSWZOZWVkZWQoZnJvbUZpbGUpO1xuICAvLyBMYXN0IHNldCB0aGUgZGVmYXVsdHNcbiAgdGhpcy5zZXRWYWx1ZXNJZk5lZWRlZChfZGVmYXVsdHMpO1xufTtcblxuQ29tbWFuZC5wcm90b3R5cGUuZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMoX2RlZmluaXRpb25zKS5yZWR1Y2UoKG9wdGlvbnMsIGtleSkgPT4ge1xuICAgIGlmICh0eXBlb2YgdGhpc1trZXldICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgb3B0aW9uc1trZXldID0gdGhpc1trZXldO1xuICAgIH1cbiAgICByZXR1cm4gb3B0aW9ucztcbiAgfSwge30pO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgbmV3IENvbW1hbmQoKTtcbi8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuIl19 \ No newline at end of file diff --git a/lib/cli/utils/runner.js b/lib/cli/utils/runner.js new file mode 100644 index 0000000000..5725eaca43 --- /dev/null +++ b/lib/cli/utils/runner.js @@ -0,0 +1,65 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _default; + +var _commander = _interopRequireDefault(require("./commander")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function logStartupOptions(options) { + for (const key in options) { + let value = options[key]; + + if (key == 'masterKey') { + value = '***REDACTED***'; + } + + if (key == 'push' && options.verbose != true) { + value = '***REDACTED***'; + } + + if (typeof value === 'object') { + try { + value = JSON.stringify(value); + } catch (e) { + if (value && value.constructor && value.constructor.name) { + value = value.constructor.name; + } + } + } + /* eslint-disable no-console */ + + + console.log(`${key}: ${value}`); + /* eslint-enable no-console */ + } +} + +function _default({ + definitions, + help, + usage, + start +}) { + _commander.default.loadDefinitions(definitions); + + if (usage) { + _commander.default.usage(usage); + } + + if (help) { + _commander.default.on('--help', help); + } + + _commander.default.parse(process.argv, process.env); + + const options = _commander.default.getOptions(); + + start(_commander.default, options, function () { + logStartupOptions(options); + }); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvdXRpbHMvcnVubmVyLmpzIl0sIm5hbWVzIjpbImxvZ1N0YXJ0dXBPcHRpb25zIiwib3B0aW9ucyIsImtleSIsInZhbHVlIiwidmVyYm9zZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJlIiwiY29uc3RydWN0b3IiLCJuYW1lIiwiY29uc29sZSIsImxvZyIsImRlZmluaXRpb25zIiwiaGVscCIsInVzYWdlIiwic3RhcnQiLCJwcm9ncmFtIiwibG9hZERlZmluaXRpb25zIiwib24iLCJwYXJzZSIsInByb2Nlc3MiLCJhcmd2IiwiZW52IiwiZ2V0T3B0aW9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBRUEsU0FBU0EsaUJBQVQsQ0FBMkJDLE9BQTNCLEVBQW9DO0FBQ2xDLE9BQUssTUFBTUMsR0FBWCxJQUFrQkQsT0FBbEIsRUFBMkI7QUFDekIsUUFBSUUsS0FBSyxHQUFHRixPQUFPLENBQUNDLEdBQUQsQ0FBbkI7O0FBQ0EsUUFBSUEsR0FBRyxJQUFJLFdBQVgsRUFBd0I7QUFDdEJDLE1BQUFBLEtBQUssR0FBRyxnQkFBUjtBQUNEOztBQUNELFFBQUlELEdBQUcsSUFBSSxNQUFQLElBQWlCRCxPQUFPLENBQUNHLE9BQVIsSUFBbUIsSUFBeEMsRUFBOEM7QUFDNUNELE1BQUFBLEtBQUssR0FBRyxnQkFBUjtBQUNEOztBQUNELFFBQUksT0FBT0EsS0FBUCxLQUFpQixRQUFyQixFQUErQjtBQUM3QixVQUFJO0FBQ0ZBLFFBQUFBLEtBQUssR0FBR0UsSUFBSSxDQUFDQyxTQUFMLENBQWVILEtBQWYsQ0FBUjtBQUNELE9BRkQsQ0FFRSxPQUFPSSxDQUFQLEVBQVU7QUFDVixZQUFJSixLQUFLLElBQUlBLEtBQUssQ0FBQ0ssV0FBZixJQUE4QkwsS0FBSyxDQUFDSyxXQUFOLENBQWtCQyxJQUFwRCxFQUEwRDtBQUN4RE4sVUFBQUEsS0FBSyxHQUFHQSxLQUFLLENBQUNLLFdBQU4sQ0FBa0JDLElBQTFCO0FBQ0Q7QUFDRjtBQUNGO0FBQ0Q7OztBQUNBQyxJQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FBYSxHQUFFVCxHQUFJLEtBQUlDLEtBQU0sRUFBN0I7QUFDQTtBQUNEO0FBQ0Y7O0FBRWMsa0JBQVM7QUFBRVMsRUFBQUEsV0FBRjtBQUFlQyxFQUFBQSxJQUFmO0FBQXFCQyxFQUFBQSxLQUFyQjtBQUE0QkMsRUFBQUE7QUFBNUIsQ0FBVCxFQUE4QztBQUMzREMscUJBQVFDLGVBQVIsQ0FBd0JMLFdBQXhCOztBQUNBLE1BQUlFLEtBQUosRUFBVztBQUNURSx1QkFBUUYsS0FBUixDQUFjQSxLQUFkO0FBQ0Q7O0FBQ0QsTUFBSUQsSUFBSixFQUFVO0FBQ1JHLHVCQUFRRSxFQUFSLENBQVcsUUFBWCxFQUFxQkwsSUFBckI7QUFDRDs7QUFDREcscUJBQVFHLEtBQVIsQ0FBY0MsT0FBTyxDQUFDQyxJQUF0QixFQUE0QkQsT0FBTyxDQUFDRSxHQUFwQzs7QUFFQSxRQUFNckIsT0FBTyxHQUFHZSxtQkFBUU8sVUFBUixFQUFoQjs7QUFDQVIsRUFBQUEsS0FBSyxDQUFDQyxrQkFBRCxFQUFVZixPQUFWLEVBQW1CLFlBQVc7QUFDakNELElBQUFBLGlCQUFpQixDQUFDQyxPQUFELENBQWpCO0FBQ0QsR0FGSSxDQUFMO0FBR0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcHJvZ3JhbSBmcm9tICcuL2NvbW1hbmRlcic7XG5cbmZ1bmN0aW9uIGxvZ1N0YXJ0dXBPcHRpb25zKG9wdGlvbnMpIHtcbiAgZm9yIChjb25zdCBrZXkgaW4gb3B0aW9ucykge1xuICAgIGxldCB2YWx1ZSA9IG9wdGlvbnNba2V5XTtcbiAgICBpZiAoa2V5ID09ICdtYXN0ZXJLZXknKSB7XG4gICAgICB2YWx1ZSA9ICcqKipSRURBQ1RFRCoqKic7XG4gICAgfVxuICAgIGlmIChrZXkgPT0gJ3B1c2gnICYmIG9wdGlvbnMudmVyYm9zZSAhPSB0cnVlKSB7XG4gICAgICB2YWx1ZSA9ICcqKipSRURBQ1RFRCoqKic7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YWx1ZSA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKHZhbHVlICYmIHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLm5hbWUpIHtcbiAgICAgICAgICB2YWx1ZSA9IHZhbHVlLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgIGNvbnNvbGUubG9nKGAke2tleX06ICR7dmFsdWV9YCk7XG4gICAgLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24oeyBkZWZpbml0aW9ucywgaGVscCwgdXNhZ2UsIHN0YXJ0IH0pIHtcbiAgcHJvZ3JhbS5sb2FkRGVmaW5pdGlvbnMoZGVmaW5pdGlvbnMpO1xuICBpZiAodXNhZ2UpIHtcbiAgICBwcm9ncmFtLnVzYWdlKHVzYWdlKTtcbiAgfVxuICBpZiAoaGVscCkge1xuICAgIHByb2dyYW0ub24oJy0taGVscCcsIGhlbHApO1xuICB9XG4gIHByb2dyYW0ucGFyc2UocHJvY2Vzcy5hcmd2LCBwcm9jZXNzLmVudik7XG5cbiAgY29uc3Qgb3B0aW9ucyA9IHByb2dyYW0uZ2V0T3B0aW9ucygpO1xuICBzdGFydChwcm9ncmFtLCBvcHRpb25zLCBmdW5jdGlvbigpIHtcbiAgICBsb2dTdGFydHVwT3B0aW9ucyhvcHRpb25zKTtcbiAgfSk7XG59XG4iXX0= \ No newline at end of file diff --git a/lib/cloud-code/HTTPResponse.js b/lib/cloud-code/HTTPResponse.js new file mode 100644 index 0000000000..88c745095b --- /dev/null +++ b/lib/cloud-code/HTTPResponse.js @@ -0,0 +1,73 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +/** + * @typedef Parse.Cloud.HTTPResponse + * @property {Buffer} buffer The raw byte representation of the response body. Use this to receive binary data. See Buffer for more details. + * @property {Object} cookies The cookies sent by the server. The keys in this object are the names of the cookies. The values are Parse.Cloud.Cookie objects. + * @property {Object} data The parsed response body as a JavaScript object. This is only available when the response Content-Type is application/x-www-form-urlencoded or application/json. + * @property {Object} headers The headers sent by the server. The keys in this object are the names of the headers. We do not support multiple response headers with the same name. In the common case of Set-Cookie headers, please use the cookies field instead. + * @property {Number} status The status code. + * @property {String} text The raw text representation of the response body. + */ +class HTTPResponse { + constructor(response, body) { + let _text, _data; + + this.status = response.statusCode; + this.headers = response.headers || {}; + this.cookies = this.headers['set-cookie']; + + if (typeof body == 'string') { + _text = body; + } else if (Buffer.isBuffer(body)) { + this.buffer = body; + } else if (typeof body == 'object') { + _data = body; + } + + const getText = () => { + if (!_text && this.buffer) { + _text = this.buffer.toString('utf-8'); + } else if (!_text && _data) { + _text = JSON.stringify(_data); + } + + return _text; + }; + + const getData = () => { + if (!_data) { + try { + _data = JSON.parse(getText()); + } catch (e) { + /* */ + } + } + + return _data; + }; + + Object.defineProperty(this, 'body', { + get: () => { + return body; + } + }); + Object.defineProperty(this, 'text', { + enumerable: true, + get: getText + }); + Object.defineProperty(this, 'data', { + enumerable: true, + get: getData + }); + } + +} + +exports.default = HTTPResponse; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1jb2RlL0hUVFBSZXNwb25zZS5qcyJdLCJuYW1lcyI6WyJIVFRQUmVzcG9uc2UiLCJjb25zdHJ1Y3RvciIsInJlc3BvbnNlIiwiYm9keSIsIl90ZXh0IiwiX2RhdGEiLCJzdGF0dXMiLCJzdGF0dXNDb2RlIiwiaGVhZGVycyIsImNvb2tpZXMiLCJCdWZmZXIiLCJpc0J1ZmZlciIsImJ1ZmZlciIsImdldFRleHQiLCJ0b1N0cmluZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJnZXREYXRhIiwicGFyc2UiLCJlIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXQiLCJlbnVtZXJhYmxlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7Ozs7OztBQVNlLE1BQU1BLFlBQU4sQ0FBbUI7QUFDaENDLEVBQUFBLFdBQVcsQ0FBQ0MsUUFBRCxFQUFXQyxJQUFYLEVBQWlCO0FBQzFCLFFBQUlDLEtBQUosRUFBV0MsS0FBWDs7QUFDQSxTQUFLQyxNQUFMLEdBQWNKLFFBQVEsQ0FBQ0ssVUFBdkI7QUFDQSxTQUFLQyxPQUFMLEdBQWVOLFFBQVEsQ0FBQ00sT0FBVCxJQUFvQixFQUFuQztBQUNBLFNBQUtDLE9BQUwsR0FBZSxLQUFLRCxPQUFMLENBQWEsWUFBYixDQUFmOztBQUVBLFFBQUksT0FBT0wsSUFBUCxJQUFlLFFBQW5CLEVBQTZCO0FBQzNCQyxNQUFBQSxLQUFLLEdBQUdELElBQVI7QUFDRCxLQUZELE1BRU8sSUFBSU8sTUFBTSxDQUFDQyxRQUFQLENBQWdCUixJQUFoQixDQUFKLEVBQTJCO0FBQ2hDLFdBQUtTLE1BQUwsR0FBY1QsSUFBZDtBQUNELEtBRk0sTUFFQSxJQUFJLE9BQU9BLElBQVAsSUFBZSxRQUFuQixFQUE2QjtBQUNsQ0UsTUFBQUEsS0FBSyxHQUFHRixJQUFSO0FBQ0Q7O0FBRUQsVUFBTVUsT0FBTyxHQUFHLE1BQU07QUFDcEIsVUFBSSxDQUFDVCxLQUFELElBQVUsS0FBS1EsTUFBbkIsRUFBMkI7QUFDekJSLFFBQUFBLEtBQUssR0FBRyxLQUFLUSxNQUFMLENBQVlFLFFBQVosQ0FBcUIsT0FBckIsQ0FBUjtBQUNELE9BRkQsTUFFTyxJQUFJLENBQUNWLEtBQUQsSUFBVUMsS0FBZCxFQUFxQjtBQUMxQkQsUUFBQUEsS0FBSyxHQUFHVyxJQUFJLENBQUNDLFNBQUwsQ0FBZVgsS0FBZixDQUFSO0FBQ0Q7O0FBQ0QsYUFBT0QsS0FBUDtBQUNELEtBUEQ7O0FBU0EsVUFBTWEsT0FBTyxHQUFHLE1BQU07QUFDcEIsVUFBSSxDQUFDWixLQUFMLEVBQVk7QUFDVixZQUFJO0FBQ0ZBLFVBQUFBLEtBQUssR0FBR1UsSUFBSSxDQUFDRyxLQUFMLENBQVdMLE9BQU8sRUFBbEIsQ0FBUjtBQUNELFNBRkQsQ0FFRSxPQUFPTSxDQUFQLEVBQVU7QUFDVjtBQUNEO0FBQ0Y7O0FBQ0QsYUFBT2QsS0FBUDtBQUNELEtBVEQ7O0FBV0FlLElBQUFBLE1BQU0sQ0FBQ0MsY0FBUCxDQUFzQixJQUF0QixFQUE0QixNQUE1QixFQUFvQztBQUNsQ0MsTUFBQUEsR0FBRyxFQUFFLE1BQU07QUFDVCxlQUFPbkIsSUFBUDtBQUNEO0FBSGlDLEtBQXBDO0FBTUFpQixJQUFBQSxNQUFNLENBQUNDLGNBQVAsQ0FBc0IsSUFBdEIsRUFBNEIsTUFBNUIsRUFBb0M7QUFDbENFLE1BQUFBLFVBQVUsRUFBRSxJQURzQjtBQUVsQ0QsTUFBQUEsR0FBRyxFQUFFVDtBQUY2QixLQUFwQztBQUtBTyxJQUFBQSxNQUFNLENBQUNDLGNBQVAsQ0FBc0IsSUFBdEIsRUFBNEIsTUFBNUIsRUFBb0M7QUFDbENFLE1BQUFBLFVBQVUsRUFBRSxJQURzQjtBQUVsQ0QsTUFBQUEsR0FBRyxFQUFFTDtBQUY2QixLQUFwQztBQUlEOztBQWxEK0IiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEB0eXBlZGVmIFBhcnNlLkNsb3VkLkhUVFBSZXNwb25zZVxuICogQHByb3BlcnR5IHtCdWZmZXJ9IGJ1ZmZlciBUaGUgcmF3IGJ5dGUgcmVwcmVzZW50YXRpb24gb2YgdGhlIHJlc3BvbnNlIGJvZHkuIFVzZSB0aGlzIHRvIHJlY2VpdmUgYmluYXJ5IGRhdGEuIFNlZSBCdWZmZXIgZm9yIG1vcmUgZGV0YWlscy5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBjb29raWVzIFRoZSBjb29raWVzIHNlbnQgYnkgdGhlIHNlcnZlci4gVGhlIGtleXMgaW4gdGhpcyBvYmplY3QgYXJlIHRoZSBuYW1lcyBvZiB0aGUgY29va2llcy4gVGhlIHZhbHVlcyBhcmUgUGFyc2UuQ2xvdWQuQ29va2llIG9iamVjdHMuXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YSBUaGUgcGFyc2VkIHJlc3BvbnNlIGJvZHkgYXMgYSBKYXZhU2NyaXB0IG9iamVjdC4gVGhpcyBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIHRoZSByZXNwb25zZSBDb250ZW50LVR5cGUgaXMgYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIG9yIGFwcGxpY2F0aW9uL2pzb24uXG4gKiBAcHJvcGVydHkge09iamVjdH0gaGVhZGVycyBUaGUgaGVhZGVycyBzZW50IGJ5IHRoZSBzZXJ2ZXIuIFRoZSBrZXlzIGluIHRoaXMgb2JqZWN0IGFyZSB0aGUgbmFtZXMgb2YgdGhlIGhlYWRlcnMuIFdlIGRvIG5vdCBzdXBwb3J0IG11bHRpcGxlIHJlc3BvbnNlIGhlYWRlcnMgd2l0aCB0aGUgc2FtZSBuYW1lLiBJbiB0aGUgY29tbW9uIGNhc2Ugb2YgU2V0LUNvb2tpZSBoZWFkZXJzLCBwbGVhc2UgdXNlIHRoZSBjb29raWVzIGZpZWxkIGluc3RlYWQuXG4gKiBAcHJvcGVydHkge051bWJlcn0gc3RhdHVzIFRoZSBzdGF0dXMgY29kZS5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSB0ZXh0IFRoZSByYXcgdGV4dCByZXByZXNlbnRhdGlvbiBvZiB0aGUgcmVzcG9uc2UgYm9keS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSFRUUFJlc3BvbnNlIHtcbiAgY29uc3RydWN0b3IocmVzcG9uc2UsIGJvZHkpIHtcbiAgICBsZXQgX3RleHQsIF9kYXRhO1xuICAgIHRoaXMuc3RhdHVzID0gcmVzcG9uc2Uuc3RhdHVzQ29kZTtcbiAgICB0aGlzLmhlYWRlcnMgPSByZXNwb25zZS5oZWFkZXJzIHx8IHt9O1xuICAgIHRoaXMuY29va2llcyA9IHRoaXMuaGVhZGVyc1snc2V0LWNvb2tpZSddO1xuXG4gICAgaWYgKHR5cGVvZiBib2R5ID09ICdzdHJpbmcnKSB7XG4gICAgICBfdGV4dCA9IGJvZHk7XG4gICAgfSBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIoYm9keSkpIHtcbiAgICAgIHRoaXMuYnVmZmVyID0gYm9keTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBib2R5ID09ICdvYmplY3QnKSB7XG4gICAgICBfZGF0YSA9IGJvZHk7XG4gICAgfVxuXG4gICAgY29uc3QgZ2V0VGV4dCA9ICgpID0+IHtcbiAgICAgIGlmICghX3RleHQgJiYgdGhpcy5idWZmZXIpIHtcbiAgICAgICAgX3RleHQgPSB0aGlzLmJ1ZmZlci50b1N0cmluZygndXRmLTgnKTtcbiAgICAgIH0gZWxzZSBpZiAoIV90ZXh0ICYmIF9kYXRhKSB7XG4gICAgICAgIF90ZXh0ID0gSlNPTi5zdHJpbmdpZnkoX2RhdGEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIF90ZXh0O1xuICAgIH07XG5cbiAgICBjb25zdCBnZXREYXRhID0gKCkgPT4ge1xuICAgICAgaWYgKCFfZGF0YSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIF9kYXRhID0gSlNPTi5wYXJzZShnZXRUZXh0KCkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLyogKi9cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIF9kYXRhO1xuICAgIH07XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ2JvZHknLCB7XG4gICAgICBnZXQ6ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIGJvZHk7XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICd0ZXh0Jywge1xuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogZ2V0VGV4dCxcbiAgICB9KTtcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnZGF0YScsIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBnZXQ6IGdldERhdGEsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/cloud-code/Parse.Cloud.js b/lib/cloud-code/Parse.Cloud.js new file mode 100644 index 0000000000..ed92c5950c --- /dev/null +++ b/lib/cloud-code/Parse.Cloud.js @@ -0,0 +1,369 @@ +"use strict"; + +var _node = require("parse/node"); + +var triggers = _interopRequireWildcard(require("../triggers")); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function isParseObjectConstructor(object) { + return typeof object === 'function' && Object.prototype.hasOwnProperty.call(object, 'className'); +} + +function getClassName(parseClass) { + if (parseClass && parseClass.className) { + return parseClass.className; + } + + return parseClass; +} +/** @namespace + * @name Parse + * @description The Parse SDK. + * see [api docs](https://docs.parseplatform.org/js/api) and [guide](https://docs.parseplatform.org/js/guide) + */ + +/** @namespace + * @name Parse.Cloud + * @memberof Parse + * @description The Parse Cloud Code SDK. + */ + + +var ParseCloud = {}; +/** + * Defines a Cloud Function. + * + * **Available in Cloud Code only.** + + * @static + * @memberof Parse.Cloud + * @param {String} name The name of the Cloud Function + * @param {Function} data The Cloud Function to register. This function can be an async function and should take one parameter a {@link Parse.Cloud.FunctionRequest}. + */ + +ParseCloud.define = function (functionName, handler, validationHandler) { + triggers.addFunction(functionName, handler, validationHandler, _node.Parse.applicationId); +}; +/** + * Defines a Background Job. + * + * **Available in Cloud Code only.** + * + * @method job + * @name Parse.Cloud.job + * @param {String} name The name of the Background Job + * @param {Function} func The Background Job to register. This function can be async should take a single parameters a {@link Parse.Cloud.JobRequest} + * + */ + + +ParseCloud.job = function (functionName, handler) { + triggers.addJob(functionName, handler, _node.Parse.applicationId); +}; +/** + * + * Registers a before save function. + * + * **Available in Cloud Code only.** + * + * If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * + * ``` + * Parse.Cloud.beforeSave('MyCustomClass', (request) => { + * // code here + * }) + * + * Parse.Cloud.beforeSave(Parse.User, (request) => { + * // code here + * }) + * ``` + * + * @method beforeSave + * @name Parse.Cloud.beforeSave + * @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass. + * @param {Function} func The function to run before a save. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest}; + */ + + +ParseCloud.beforeSave = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.beforeSave, className, handler, _node.Parse.applicationId); +}; +/** + * Registers a before delete function. + * + * **Available in Cloud Code only.** + * + * If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * ``` + * Parse.Cloud.beforeDelete('MyCustomClass', (request) => { + * // code here + * }) + * + * Parse.Cloud.beforeDelete(Parse.User, (request) => { + * // code here + * }) + *``` + * + * @method beforeDelete + * @name Parse.Cloud.beforeDelete + * @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the before delete function for. This can instead be a String that is the className of the subclass. + * @param {Function} func The function to run before a delete. This function can be async and should take one parameter, a {@link Parse.Cloud.TriggerRequest}. + */ + + +ParseCloud.beforeDelete = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.beforeDelete, className, handler, _node.Parse.applicationId); +}; +/** + * + * Registers the before login function. + * + * **Available in Cloud Code only.** + * + * This function provides further control + * in validating a login attempt. Specifically, + * it is triggered after a user enters + * correct credentials (or other valid authData), + * but prior to a session being generated. + * + * ``` + * Parse.Cloud.beforeLogin((request) => { + * // code here + * }) + * + * ``` + * + * @method beforeLogin + * @name Parse.Cloud.beforeLogin + * @param {Function} func The function to run before a login. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest}; + */ + + +ParseCloud.beforeLogin = function (handler) { + let className = '_User'; + + if (typeof handler === 'string' || isParseObjectConstructor(handler)) { + // validation will occur downstream, this is to maintain internal + // code consistency with the other hook types. + className = getClassName(handler); + handler = arguments[1]; + } + + triggers.addTrigger(triggers.Types.beforeLogin, className, handler, _node.Parse.applicationId); +}; +/** + * + * Registers the after logout function. + * + * **Available in Cloud Code only.** + * + * This function is triggered after a user logs out. + * + * ``` + * Parse.Cloud.afterLogout((request) => { + * // code here + * }) + * + * ``` + * + * @method afterLogout + * @name Parse.Cloud.afterLogout + * @param {Function} func The function to run after a logout. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest}; + */ + + +ParseCloud.afterLogout = function (handler) { + let className = '_Session'; + + if (typeof handler === 'string' || isParseObjectConstructor(handler)) { + // validation will occur downstream, this is to maintain internal + // code consistency with the other hook types. + className = getClassName(handler); + handler = arguments[1]; + } + + triggers.addTrigger(triggers.Types.afterLogout, className, handler, _node.Parse.applicationId); +}; +/** + * Registers an after save function. + * + * **Available in Cloud Code only.** + * + * If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * + * ``` + * Parse.Cloud.afterSave('MyCustomClass', async function(request) { + * // code here + * }) + * + * Parse.Cloud.afterSave(Parse.User, async function(request) { + * // code here + * }) + * ``` + * + * @method afterSave + * @name Parse.Cloud.afterSave + * @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass. + * @param {Function} func The function to run after a save. This function can be an async function and should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + */ + + +ParseCloud.afterSave = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.afterSave, className, handler, _node.Parse.applicationId); +}; +/** + * Registers an after delete function. + * + * **Available in Cloud Code only.** + * + * If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * ``` + * Parse.Cloud.afterDelete('MyCustomClass', async (request) => { + * // code here + * }) + * + * Parse.Cloud.afterDelete(Parse.User, async (request) => { + * // code here + * }) + *``` + * + * @method afterDelete + * @name Parse.Cloud.afterDelete + * @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after delete function for. This can instead be a String that is the className of the subclass. + * @param {Function} func The function to run after a delete. This function can be async and should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + */ + + +ParseCloud.afterDelete = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.afterDelete, className, handler, _node.Parse.applicationId); +}; +/** + * Registers a before find function. + * + * **Available in Cloud Code only.** + * + * If you want to use beforeFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * ``` + * Parse.Cloud.beforeFind('MyCustomClass', async (request) => { + * // code here + * }) + * + * Parse.Cloud.beforeFind(Parse.User, async (request) => { + * // code here + * }) + *``` + * + * @method beforeFind + * @name Parse.Cloud.beforeFind + * @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the before find function for. This can instead be a String that is the className of the subclass. + * @param {Function} func The function to run before a find. This function can be async and should take just one parameter, {@link Parse.Cloud.BeforeFindRequest}. + */ + + +ParseCloud.beforeFind = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.beforeFind, className, handler, _node.Parse.applicationId); +}; +/** + * Registers an after find function. + * + * **Available in Cloud Code only.** + * + * If you want to use afterFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * ``` + * Parse.Cloud.afterFind('MyCustomClass', async (request) => { + * // code here + * }) + * + * Parse.Cloud.afterFind(Parse.User, async (request) => { + * // code here + * }) + *``` + * + * @method afterFind + * @name Parse.Cloud.afterFind + * @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after find function for. This can instead be a String that is the className of the subclass. + * @param {Function} func The function to run before a find. This function can be async and should take just one parameter, {@link Parse.Cloud.AfterFindRequest}. + */ + + +ParseCloud.afterFind = function (parseClass, handler) { + const className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.afterFind, className, handler, _node.Parse.applicationId); +}; + +ParseCloud.onLiveQueryEvent = function (handler) { + triggers.addLiveQueryEventHandler(handler, _node.Parse.applicationId); +}; + +ParseCloud._removeAllHooks = () => { + triggers._unregisterAll(); +}; + +ParseCloud.useMasterKey = () => { + // eslint-disable-next-line + console.warn('Parse.Cloud.useMasterKey is deprecated (and has no effect anymore) on parse-server, please refer to the cloud code migration notes: http://docs.parseplatform.org/parse-server/guide/#master-key-must-be-passed-explicitly'); +}; + +ParseCloud.httpRequest = require('./httpRequest'); +module.exports = ParseCloud; +/** + * @interface Parse.Cloud.TriggerRequest + * @property {String} installationId If set, the installationId triggering the request. + * @property {Boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Parse.Object} object The object triggering the hook. + * @property {String} ip The IP address of the client making the request. + * @property {Object} headers The original HTTP headers for the request. + * @property {String} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...) + * @property {Object} log The current logger inside Parse Server. + * @property {Parse.Object} original If set, the object, as currently stored. + */ + +/** + * @interface Parse.Cloud.BeforeFindRequest + * @property {String} installationId If set, the installationId triggering the request. + * @property {Boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Parse.Query} query The query triggering the hook. + * @property {String} ip The IP address of the client making the request. + * @property {Object} headers The original HTTP headers for the request. + * @property {String} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...) + * @property {Object} log The current logger inside Parse Server. + * @property {Boolean} isGet wether the query a `get` or a `find` + */ + +/** + * @interface Parse.Cloud.AfterFindRequest + * @property {String} installationId If set, the installationId triggering the request. + * @property {Boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Parse.Query} query The query triggering the hook. + * @property {Array} results The results the query yielded. + * @property {String} ip The IP address of the client making the request. + * @property {Object} headers The original HTTP headers for the request. + * @property {String} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...) + * @property {Object} log The current logger inside Parse Server. + */ + +/** + * @interface Parse.Cloud.FunctionRequest + * @property {String} installationId If set, the installationId triggering the request. + * @property {Boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Object} params The params passed to the cloud function. + */ + +/** + * @interface Parse.Cloud.JobRequest + * @property {Object} params The params passed to the background job. + * @property {function} message If message is called with a string argument, will update the current message to be stored in the job status. + */ +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1jb2RlL1BhcnNlLkNsb3VkLmpzIl0sIm5hbWVzIjpbImlzUGFyc2VPYmplY3RDb25zdHJ1Y3RvciIsIm9iamVjdCIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImdldENsYXNzTmFtZSIsInBhcnNlQ2xhc3MiLCJjbGFzc05hbWUiLCJQYXJzZUNsb3VkIiwiZGVmaW5lIiwiZnVuY3Rpb25OYW1lIiwiaGFuZGxlciIsInZhbGlkYXRpb25IYW5kbGVyIiwidHJpZ2dlcnMiLCJhZGRGdW5jdGlvbiIsIlBhcnNlIiwiYXBwbGljYXRpb25JZCIsImpvYiIsImFkZEpvYiIsImJlZm9yZVNhdmUiLCJhZGRUcmlnZ2VyIiwiVHlwZXMiLCJiZWZvcmVEZWxldGUiLCJiZWZvcmVMb2dpbiIsImFyZ3VtZW50cyIsImFmdGVyTG9nb3V0IiwiYWZ0ZXJTYXZlIiwiYWZ0ZXJEZWxldGUiLCJiZWZvcmVGaW5kIiwiYWZ0ZXJGaW5kIiwib25MaXZlUXVlcnlFdmVudCIsImFkZExpdmVRdWVyeUV2ZW50SGFuZGxlciIsIl9yZW1vdmVBbGxIb29rcyIsIl91bnJlZ2lzdGVyQWxsIiwidXNlTWFzdGVyS2V5IiwiY29uc29sZSIsIndhcm4iLCJodHRwUmVxdWVzdCIsInJlcXVpcmUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOztBQUNBOzs7Ozs7QUFFQSxTQUFTQSx3QkFBVCxDQUFrQ0MsTUFBbEMsRUFBMEM7QUFDeEMsU0FDRSxPQUFPQSxNQUFQLEtBQWtCLFVBQWxCLElBQ0FDLE1BQU0sQ0FBQ0MsU0FBUCxDQUFpQkMsY0FBakIsQ0FBZ0NDLElBQWhDLENBQXFDSixNQUFyQyxFQUE2QyxXQUE3QyxDQUZGO0FBSUQ7O0FBRUQsU0FBU0ssWUFBVCxDQUFzQkMsVUFBdEIsRUFBa0M7QUFDaEMsTUFBSUEsVUFBVSxJQUFJQSxVQUFVLENBQUNDLFNBQTdCLEVBQXdDO0FBQ3RDLFdBQU9ELFVB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WCxHQUE4QixVQUFTbkIsT0FBVCxFQUFrQjtBQUM5Q0UsRUFBQUEsUUFBUSxDQUFDa0Isd0JBQVQsQ0FBa0NwQixPQUFsQyxFQUEyQ0ksWUFBTUMsYUFBakQ7QUFDRCxDQUZEOztBQUlBUixVQUFVLENBQUN3QixlQUFYLEdBQTZCLE1BQU07QUFDakNuQixFQUFBQSxRQUFRLENBQUNvQixjQUFUO0FBQ0QsQ0FGRDs7QUFJQXpCLFVBQVUsQ0FBQzBCLFlBQVgsR0FBMEIsTUFBTTtBQUM5QjtBQUNBQyxFQUFBQSxPQUFPLENBQUNDLElBQVIsQ0FDRSw0TkFERjtBQUdELENBTEQ7O0FBT0E1QixVQUFVLENBQUM2QixXQUFYLEdBQXlCQyxPQUFPLENBQUMsZUFBRCxDQUFoQztBQUVBQyxNQUFNLENBQUNDLE9BQVAsR0FBaUJoQyxVQUFqQjtBQUVBOzs7Ozs7Ozs7Ozs7O0FBYUE7Ozs7Ozs7Ozs7Ozs7QUFhQTs7Ozs7Ozs7Ozs7OztBQWFBOzs7Ozs7OztBQVFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2UgfSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCAqIGFzIHRyaWdnZXJzIGZyb20gJy4uL3RyaWdnZXJzJztcblxuZnVuY3Rpb24gaXNQYXJzZU9iamVjdENvbnN0cnVjdG9yKG9iamVjdCkge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBvYmplY3QgPT09ICdmdW5jdGlvbicgJiZcbiAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCAnY2xhc3NOYW1lJylcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpIHtcbiAgaWYgKHBhcnNlQ2xhc3MgJiYgcGFyc2VDbGFzcy5jbGFzc05hbWUpIHtcbiAgICByZXR1cm4gcGFyc2VDbGFzcy5jbGFzc05hbWU7XG4gIH1cbiAgcmV0dXJuIHBhcnNlQ2xhc3M7XG59XG5cbi8qKiBAbmFtZXNwYWNlXG4gKiBAbmFtZSBQYXJzZVxuICogQGRlc2NyaXB0aW9uIFRoZSBQYXJzZSBTREsuXG4gKiAgc2VlIFthcGkgZG9jc10oaHR0cHM6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL2pzL2FwaSkgYW5kIFtndWlkZV0oaHR0cHM6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL2pzL2d1aWRlKVxuICovXG5cbi8qKiBAbmFtZXNwYWNlXG4gKiBAbmFtZSBQYXJzZS5DbG91ZFxuICogQG1lbWJlcm9mIFBhcnNlXG4gKiBAZGVzY3JpcHRpb24gVGhlIFBhcnNlIENsb3VkIENvZGUgU0RLLlxuICovXG5cbnZhciBQYXJzZUNsb3VkID0ge307XG4vKipcbiAqIERlZmluZXMgYSBDbG91ZCBGdW5jdGlvbi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcblxuICogQHN0YXRpY1xuICogQG1lbWJlcm9mIFBhcnNlLkNsb3VkXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgQ2xvdWQgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGRhdGEgVGhlIENsb3VkIEZ1bmN0aW9uIHRvIHJlZ2lzdGVyLiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSBhbiBhc3luYyBmdW5jdGlvbiBhbmQgc2hvdWxkIHRha2Ugb25lIHBhcmFtZXRlciBhIHtAbGluayBQYXJzZS5DbG91ZC5GdW5jdGlvblJlcXVlc3R9LlxuICovXG5QYXJzZUNsb3VkLmRlZmluZSA9IGZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgaGFuZGxlciwgdmFsaWRhdGlvbkhhbmRsZXIpIHtcbiAgdHJpZ2dlcnMuYWRkRnVuY3Rpb24oXG4gICAgZnVuY3Rpb25OYW1lLFxuICAgIGhhbmRsZXIsXG4gICAgdmFsaWRhdGlvbkhhbmRsZXIsXG4gICAgUGFyc2UuYXBwbGljYXRpb25JZFxuICApO1xufTtcblxuLyoqXG4gKiBEZWZpbmVzIGEgQmFja2dyb3VuZCBKb2IuXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogQG1ldGhvZCBqb2JcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmpvYlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIEJhY2tncm91bmQgSm9iXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBCYWNrZ3JvdW5kIEpvYiB0byByZWdpc3Rlci4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYXN5bmMgc2hvdWxkIHRha2UgYSBzaW5nbGUgcGFyYW1ldGVycyBhIHtAbGluayBQYXJzZS5DbG91ZC5Kb2JSZXF1ZXN0fVxuICpcbiAqL1xuUGFyc2VDbG91ZC5qb2IgPSBmdW5jdGlvbihmdW5jdGlvbk5hbWUsIGhhbmRsZXIpIHtcbiAgdHJpZ2dlcnMuYWRkSm9iKGZ1bmN0aW9uTmFtZSwgaGFuZGxlciwgUGFyc2UuYXBwbGljYXRpb25JZCk7XG59O1xuXG4vKipcbiAqXG4gKiBSZWdpc3RlcnMgYSBiZWZvcmUgc2F2ZSBmdW5jdGlvbi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcbiAqXG4gKiBJZiB5b3Ugd2FudCB0byB1c2UgYmVmb3JlU2F2ZSBmb3IgYSBwcmVkZWZpbmVkIGNsYXNzIGluIHRoZSBQYXJzZSBKYXZhU2NyaXB0IFNESyAoZS5nLiB7QGxpbmsgUGFyc2UuVXNlcn0pLCB5b3Ugc2hvdWxkIHBhc3MgdGhlIGNsYXNzIGl0c2VsZiBhbmQgbm90IHRoZSBTdHJpbmcgZm9yIGFyZzEuXG4gKlxuICogYGBgXG4gKiBQYXJzZS5DbG91ZC5iZWZvcmVTYXZlKCdNeUN1c3RvbUNsYXNzJywgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpcbiAqIFBhcnNlLkNsb3VkLmJlZm9yZVNhdmUoUGFyc2UuVXNlciwgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICogYGBgXG4gKlxuICogQG1ldGhvZCBiZWZvcmVTYXZlXG4gKiBAbmFtZSBQYXJzZS5DbG91ZC5iZWZvcmVTYXZlXG4gKiBAcGFyYW0geyhTdHJpbmd8UGFyc2UuT2JqZWN0KX0gYXJnMSBUaGUgUGFyc2UuT2JqZWN0IHN1YmNsYXNzIHRvIHJlZ2lzdGVyIHRoZSBhZnRlciBzYXZlIGZ1bmN0aW9uIGZvci4gVGhpcyBjYW4gaW5zdGVhZCBiZSBhIFN0cmluZyB0aGF0IGlzIHRoZSBjbGFzc05hbWUgb2YgdGhlIHN1YmNsYXNzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcnVuIGJlZm9yZSBhIHNhdmUuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFzeW5jIGFuZCBzaG91bGQgdGFrZSBvbmUgcGFyYW1ldGVyIGEge0BsaW5rIFBhcnNlLkNsb3VkLlRyaWdnZXJSZXF1ZXN0fTtcbiAqL1xuUGFyc2VDbG91ZC5iZWZvcmVTYXZlID0gZnVuY3Rpb24ocGFyc2VDbGFzcywgaGFuZGxlcikge1xuICB2YXIgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpO1xuICB0cmlnZ2Vycy5hZGRUcmlnZ2VyKFxuICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsXG4gICAgY2xhc3NOYW1lLFxuICAgIGhhbmRsZXIsXG4gICAgUGFyc2UuYXBwbGljYXRpb25JZFxuICApO1xufTtcblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBiZWZvcmUgZGVsZXRlIGZ1bmN0aW9uLlxuICpcbiAqICoqQXZhaWxhYmxlIGluIENsb3VkIENvZGUgb25seS4qKlxuICpcbiAqIElmIHlvdSB3YW50IHRvIHVzZSBiZWZvcmVEZWxldGUgZm9yIGEgcHJlZGVmaW5lZCBjbGFzcyBpbiB0aGUgUGFyc2UgSmF2YVNjcmlwdCBTREsgKGUuZy4ge0BsaW5rIFBhcnNlLlVzZXJ9KSwgeW91IHNob3VsZCBwYXNzIHRoZSBjbGFzcyBpdHNlbGYgYW5kIG5vdCB0aGUgU3RyaW5nIGZvciBhcmcxLlxuICogYGBgXG4gKiBQYXJzZS5DbG91ZC5iZWZvcmVEZWxldGUoJ015Q3VzdG9tQ2xhc3MnLCAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKlxuICogUGFyc2UuQ2xvdWQuYmVmb3JlRGVsZXRlKFBhcnNlLlVzZXIsIChyZXF1ZXN0KSA9PiB7XG4gKiAgIC8vIGNvZGUgaGVyZVxuICogfSlcbiAqYGBgXG4gKlxuICogQG1ldGhvZCBiZWZvcmVEZWxldGVcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmJlZm9yZURlbGV0ZVxuICogQHBhcmFtIHsoU3RyaW5nfFBhcnNlLk9iamVjdCl9IGFyZzEgVGhlIFBhcnNlLk9iamVjdCBzdWJjbGFzcyB0byByZWdpc3RlciB0aGUgYmVmb3JlIGRlbGV0ZSBmdW5jdGlvbiBmb3IuIFRoaXMgY2FuIGluc3RlYWQgYmUgYSBTdHJpbmcgdGhhdCBpcyB0aGUgY2xhc3NOYW1lIG9mIHRoZSBzdWJjbGFzcy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJ1biBiZWZvcmUgYSBkZWxldGUuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFzeW5jIGFuZCBzaG91bGQgdGFrZSBvbmUgcGFyYW1ldGVyLCBhIHtAbGluayBQYXJzZS5DbG91ZC5UcmlnZ2VyUmVxdWVzdH0uXG4gKi9cblBhcnNlQ2xvdWQuYmVmb3JlRGVsZXRlID0gZnVuY3Rpb24ocGFyc2VDbGFzcywgaGFuZGxlcikge1xuICB2YXIgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpO1xuICB0cmlnZ2Vycy5hZGRUcmlnZ2VyKFxuICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZURlbGV0ZSxcbiAgICBjbGFzc05hbWUsXG4gICAgaGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG4vKipcbiAqXG4gKiBSZWdpc3RlcnMgdGhlIGJlZm9yZSBsb2dpbiBmdW5jdGlvbi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHByb3ZpZGVzIGZ1cnRoZXIgY29udHJvbFxuICogaW4gdmFsaWRhdGluZyBhIGxvZ2luIGF0dGVtcHQuIFNwZWNpZmljYWxseSxcbiAqIGl0IGlzIHRyaWdnZXJlZCBhZnRlciBhIHVzZXIgZW50ZXJzXG4gKiBjb3JyZWN0IGNyZWRlbnRpYWxzIChvciBvdGhlciB2YWxpZCBhdXRoRGF0YSksXG4gKiBidXQgcHJpb3IgdG8gYSBzZXNzaW9uIGJlaW5nIGdlbmVyYXRlZC5cbiAqXG4gKiBgYGBcbiAqIFBhcnNlLkNsb3VkLmJlZm9yZUxvZ2luKChyZXF1ZXN0KSA9PiB7XG4gKiAgIC8vIGNvZGUgaGVyZVxuICogfSlcbiAqXG4gKiBgYGBcbiAqXG4gKiBAbWV0aG9kIGJlZm9yZUxvZ2luXG4gKiBAbmFtZSBQYXJzZS5DbG91ZC5iZWZvcmVMb2dpblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcnVuIGJlZm9yZSBhIGxvZ2luLiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSBhc3luYyBhbmQgc2hvdWxkIHRha2Ugb25lIHBhcmFtZXRlciBhIHtAbGluayBQYXJzZS5DbG91ZC5UcmlnZ2VyUmVxdWVzdH07XG4gKi9cblBhcnNlQ2xvdWQuYmVmb3JlTG9naW4gPSBmdW5jdGlvbihoYW5kbGVyKSB7XG4gIGxldCBjbGFzc05hbWUgPSAnX1VzZXInO1xuICBpZiAodHlwZW9mIGhhbmRsZXIgPT09ICdzdHJpbmcnIHx8IGlzUGFyc2VPYmplY3RDb25zdHJ1Y3RvcihoYW5kbGVyKSkge1xuICAgIC8vIHZhbGlkYXRpb24gd2lsbCBvY2N1ciBkb3duc3RyZWFtLCB0aGlzIGlzIHRvIG1haW50YWluIGludGVybmFsXG4gICAgLy8gY29kZSBjb25zaXN0ZW5jeSB3aXRoIHRoZSBvdGhlciBob29rIHR5cGVzLlxuICAgIGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShoYW5kbGVyKTtcbiAgICBoYW5kbGVyID0gYXJndW1lbnRzWzFdO1xuICB9XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIoXG4gICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlTG9naW4sXG4gICAgY2xhc3NOYW1lLFxuICAgIGhhbmRsZXIsXG4gICAgUGFyc2UuYXBwbGljYXRpb25JZFxuICApO1xufTtcblxuLyoqXG4gKlxuICogUmVnaXN0ZXJzIHRoZSBhZnRlciBsb2dvdXQgZnVuY3Rpb24uXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyB0cmlnZ2VyZWQgYWZ0ZXIgYSB1c2VyIGxvZ3Mgb3V0LlxuICpcbiAqIGBgYFxuICogUGFyc2UuQ2xvdWQuYWZ0ZXJMb2dvdXQoKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpcbiAqIGBgYFxuICpcbiAqIEBtZXRob2QgYWZ0ZXJMb2dvdXRcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmFmdGVyTG9nb3V0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBydW4gYWZ0ZXIgYSBsb2dvdXQuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFzeW5jIGFuZCBzaG91bGQgdGFrZSBvbmUgcGFyYW1ldGVyIGEge0BsaW5rIFBhcnNlLkNsb3VkLlRyaWdnZXJSZXF1ZXN0fTtcbiAqL1xuUGFyc2VDbG91ZC5hZnRlckxvZ291dCA9IGZ1bmN0aW9uKGhhbmRsZXIpIHtcbiAgbGV0IGNsYXNzTmFtZSA9ICdfU2Vzc2lvbic7XG4gIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gJ3N0cmluZycgfHwgaXNQYXJzZU9iamVjdENvbnN0cnVjdG9yKGhhbmRsZXIpKSB7XG4gICAgLy8gdmFsaWRhdGlvbiB3aWxsIG9jY3VyIGRvd25zdHJlYW0sIHRoaXMgaXMgdG8gbWFpbnRhaW4gaW50ZXJuYWxcbiAgICAvLyBjb2RlIGNvbnNpc3RlbmN5IHdpdGggdGhlIG90aGVyIGhvb2sgdHlwZXMuXG4gICAgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKGhhbmRsZXIpO1xuICAgIGhhbmRsZXIgPSBhcmd1bWVudHNbMV07XG4gIH1cbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcihcbiAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckxvZ291dCxcbiAgICBjbGFzc05hbWUsXG4gICAgaGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBhZnRlciBzYXZlIGZ1bmN0aW9uLlxuICpcbiAqICoqQXZhaWxhYmxlIGluIENsb3VkIENvZGUgb25seS4qKlxuICpcbiAqIElmIHlvdSB3YW50IHRvIHVzZSBhZnRlclNhdmUgZm9yIGEgcHJlZGVmaW5lZCBjbGFzcyBpbiB0aGUgUGFyc2UgSmF2YVNjcmlwdCBTREsgKGUuZy4ge0BsaW5rIFBhcnNlLlVzZXJ9KSwgeW91IHNob3VsZCBwYXNzIHRoZSBjbGFzcyBpdHNlbGYgYW5kIG5vdCB0aGUgU3RyaW5nIGZvciBhcmcxLlxuICpcbiAqIGBgYFxuICogUGFyc2UuQ2xvdWQuYWZ0ZXJTYXZlKCdNeUN1c3RvbUNsYXNzJywgYXN5bmMgZnVuY3Rpb24ocmVxdWVzdCkge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKlxuICogUGFyc2UuQ2xvdWQuYWZ0ZXJTYXZlKFBhcnNlLlVzZXIsIGFzeW5jIGZ1bmN0aW9uKHJlcXVlc3QpIHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICogYGBgXG4gKlxuICogQG1ldGhvZCBhZnRlclNhdmVcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmFmdGVyU2F2ZVxuICogQHBhcmFtIHsoU3RyaW5nfFBhcnNlLk9iamVjdCl9IGFyZzEgVGhlIFBhcnNlLk9iamVjdCBzdWJjbGFzcyB0byByZWdpc3RlciB0aGUgYWZ0ZXIgc2F2ZSBmdW5jdGlvbiBmb3IuIFRoaXMgY2FuIGluc3RlYWQgYmUgYSBTdHJpbmcgdGhhdCBpcyB0aGUgY2xhc3NOYW1lIG9mIHRoZSBzdWJjbGFzcy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJ1biBhZnRlciBhIHNhdmUuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFuIGFzeW5jIGZ1bmN0aW9uIGFuZCBzaG91bGQgdGFrZSBqdXN0IG9uZSBwYXJhbWV0ZXIsIHtAbGluayBQYXJzZS5DbG91ZC5UcmlnZ2VyUmVxdWVzdH0uXG4gKi9cblBhcnNlQ2xvdWQuYWZ0ZXJTYXZlID0gZnVuY3Rpb24ocGFyc2VDbGFzcywgaGFuZGxlcikge1xuICB2YXIgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpO1xuICB0cmlnZ2Vycy5hZGRUcmlnZ2VyKFxuICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyU2F2ZSxcbiAgICBjbGFzc05hbWUsXG4gICAgaGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBhZnRlciBkZWxldGUgZnVuY3Rpb24uXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogSWYgeW91IHdhbnQgdG8gdXNlIGFmdGVyRGVsZXRlIGZvciBhIHByZWRlZmluZWQgY2xhc3MgaW4gdGhlIFBhcnNlIEphdmFTY3JpcHQgU0RLIChlLmcuIHtAbGluayBQYXJzZS5Vc2VyfSksIHlvdSBzaG91bGQgcGFzcyB0aGUgY2xhc3MgaXRzZWxmIGFuZCBub3QgdGhlIFN0cmluZyBmb3IgYXJnMS5cbiAqIGBgYFxuICogUGFyc2UuQ2xvdWQuYWZ0ZXJEZWxldGUoJ015Q3VzdG9tQ2xhc3MnLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKlxuICogUGFyc2UuQ2xvdWQuYWZ0ZXJEZWxldGUoUGFyc2UuVXNlciwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpgYGBcbiAqXG4gKiBAbWV0aG9kIGFmdGVyRGVsZXRlXG4gKiBAbmFtZSBQYXJzZS5DbG91ZC5hZnRlckRlbGV0ZVxuICogQHBhcmFtIHsoU3RyaW5nfFBhcnNlLk9iamVjdCl9IGFyZzEgVGhlIFBhcnNlLk9iamVjdCBzdWJjbGFzcyB0byByZWdpc3RlciB0aGUgYWZ0ZXIgZGVsZXRlIGZ1bmN0aW9uIGZvci4gVGhpcyBjYW4gaW5zdGVhZCBiZSBhIFN0cmluZyB0aGF0IGlzIHRoZSBjbGFzc05hbWUgb2YgdGhlIHN1YmNsYXNzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcnVuIGFmdGVyIGEgZGVsZXRlLiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSBhc3luYyBhbmQgc2hvdWxkIHRha2UganVzdCBvbmUgcGFyYW1ldGVyLCB7QGxpbmsgUGFyc2UuQ2xvdWQuVHJpZ2dlclJlcXVlc3R9LlxuICovXG5QYXJzZUNsb3VkLmFmdGVyRGVsZXRlID0gZnVuY3Rpb24ocGFyc2VDbGFzcywgaGFuZGxlcikge1xuICB2YXIgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpO1xuICB0cmlnZ2Vycy5hZGRUcmlnZ2VyKFxuICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyRGVsZXRlLFxuICAgIGNsYXNzTmFtZSxcbiAgICBoYW5kbGVyLFxuICAgIFBhcnNlLmFwcGxpY2F0aW9uSWRcbiAgKTtcbn07XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgYmVmb3JlIGZpbmQgZnVuY3Rpb24uXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogSWYgeW91IHdhbnQgdG8gdXNlIGJlZm9yZUZpbmQgZm9yIGEgcHJlZGVmaW5lZCBjbGFzcyBpbiB0aGUgUGFyc2UgSmF2YVNjcmlwdCBTREsgKGUuZy4ge0BsaW5rIFBhcnNlLlVzZXJ9KSwgeW91IHNob3VsZCBwYXNzIHRoZSBjbGFzcyBpdHNlbGYgYW5kIG5vdCB0aGUgU3RyaW5nIGZvciBhcmcxLlxuICogYGBgXG4gKiBQYXJzZS5DbG91ZC5iZWZvcmVGaW5kKCdNeUN1c3RvbUNsYXNzJywgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpcbiAqIFBhcnNlLkNsb3VkLmJlZm9yZUZpbmQoUGFyc2UuVXNlciwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpgYGBcbiAqXG4gKiBAbWV0aG9kIGJlZm9yZUZpbmRcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmJlZm9yZUZpbmRcbiAqIEBwYXJhbSB7KFN0cmluZ3xQYXJzZS5PYmplY3QpfSBhcmcxIFRoZSBQYXJzZS5PYmplY3Qgc3ViY2xhc3MgdG8gcmVnaXN0ZXIgdGhlIGJlZm9yZSBmaW5kIGZ1bmN0aW9uIGZvci4gVGhpcyBjYW4gaW5zdGVhZCBiZSBhIFN0cmluZyB0aGF0IGlzIHRoZSBjbGFzc05hbWUgb2YgdGhlIHN1YmNsYXNzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcnVuIGJlZm9yZSBhIGZpbmQuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFzeW5jIGFuZCBzaG91bGQgdGFrZSBqdXN0IG9uZSBwYXJhbWV0ZXIsIHtAbGluayBQYXJzZS5DbG91ZC5CZWZvcmVGaW5kUmVxdWVzdH0uXG4gKi9cblBhcnNlQ2xvdWQuYmVmb3JlRmluZCA9IGZ1bmN0aW9uKHBhcnNlQ2xhc3MsIGhhbmRsZXIpIHtcbiAgdmFyIGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShwYXJzZUNsYXNzKTtcbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcihcbiAgICB0cmlnZ2Vycy5UeXBlcy5iZWZvcmVGaW5kLFxuICAgIGNsYXNzTmFtZSxcbiAgICBoYW5kbGVyLFxuICAgIFBhcnNlLmFwcGxpY2F0aW9uSWRcbiAgKTtcbn07XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFuIGFmdGVyIGZpbmQgZnVuY3Rpb24uXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogSWYgeW91IHdhbnQgdG8gdXNlIGFmdGVyRmluZCBmb3IgYSBwcmVkZWZpbmVkIGNsYXNzIGluIHRoZSBQYXJzZSBKYXZhU2NyaXB0IFNESyAoZS5nLiB7QGxpbmsgUGFyc2UuVXNlcn0pLCB5b3Ugc2hvdWxkIHBhc3MgdGhlIGNsYXNzIGl0c2VsZiBhbmQgbm90IHRoZSBTdHJpbmcgZm9yIGFyZzEuXG4gKiBgYGBcbiAqIFBhcnNlLkNsb3VkLmFmdGVyRmluZCgnTXlDdXN0b21DbGFzcycsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gKiAgIC8vIGNvZGUgaGVyZVxuICogfSlcbiAqXG4gKiBQYXJzZS5DbG91ZC5hZnRlckZpbmQoUGFyc2UuVXNlciwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpgYGBcbiAqXG4gKiBAbWV0aG9kIGFmdGVyRmluZFxuICogQG5hbWUgUGFyc2UuQ2xvdWQuYWZ0ZXJGaW5kXG4gKiBAcGFyYW0geyhTdHJpbmd8UGFyc2UuT2JqZWN0KX0gYXJnMSBUaGUgUGFyc2UuT2JqZWN0IHN1YmNsYXNzIHRvIHJlZ2lzdGVyIHRoZSBhZnRlciBmaW5kIGZ1bmN0aW9uIGZvci4gVGhpcyBjYW4gaW5zdGVhZCBiZSBhIFN0cmluZyB0aGF0IGlzIHRoZSBjbGFzc05hbWUgb2YgdGhlIHN1YmNsYXNzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcnVuIGJlZm9yZSBhIGZpbmQuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFzeW5jIGFuZCBzaG91bGQgdGFrZSBqdXN0IG9uZSBwYXJhbWV0ZXIsIHtAbGluayBQYXJzZS5DbG91ZC5BZnRlckZpbmRSZXF1ZXN0fS5cbiAqL1xuUGFyc2VDbG91ZC5hZnRlckZpbmQgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIGNvbnN0IGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShwYXJzZUNsYXNzKTtcbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcihcbiAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckZpbmQsXG4gICAgY2xhc3NOYW1lLFxuICAgIGhhbmRsZXIsXG4gICAgUGFyc2UuYXBwbGljYXRpb25JZFxuICApO1xufTtcblxuUGFyc2VDbG91ZC5vbkxpdmVRdWVyeUV2ZW50ID0gZnVuY3Rpb24oaGFuZGxlcikge1xuICB0cmlnZ2Vycy5hZGRMaXZlUXVlcnlFdmVudEhhbmRsZXIoaGFuZGxlciwgUGFyc2UuYXBwbGljYXRpb25JZCk7XG59O1xuXG5QYXJzZUNsb3VkLl9yZW1vdmVBbGxIb29rcyA9ICgpID0+IHtcbiAgdHJpZ2dlcnMuX3VucmVnaXN0ZXJBbGwoKTtcbn07XG5cblBhcnNlQ2xvdWQudXNlTWFzdGVyS2V5ID0gKCkgPT4ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgY29uc29sZS53YXJuKFxuICAgICdQYXJzZS5DbG91ZC51c2VNYXN0ZXJLZXkgaXMgZGVwcmVjYXRlZCAoYW5kIGhhcyBubyBlZmZlY3QgYW55bW9yZSkgb24gcGFyc2Utc2VydmVyLCBwbGVhc2UgcmVmZXIgdG8gdGhlIGNsb3VkIGNvZGUgbWlncmF0aW9uIG5vdGVzOiBodHRwOi8vZG9jcy5wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvZ3VpZGUvI21hc3Rlci1rZXktbXVzdC1iZS1wYXNzZWQtZXhwbGljaXRseSdcbiAgKTtcbn07XG5cblBhcnNlQ2xvdWQuaHR0cFJlcXVlc3QgPSByZXF1aXJlKCcuL2h0dHBSZXF1ZXN0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gUGFyc2VDbG91ZDtcblxuLyoqXG4gKiBAaW50ZXJmYWNlIFBhcnNlLkNsb3VkLlRyaWdnZXJSZXF1ZXN0XG4gKiBAcHJvcGVydHkge1N0cmluZ30gaW5zdGFsbGF0aW9uSWQgSWYgc2V0LCB0aGUgaW5zdGFsbGF0aW9uSWQgdHJpZ2dlcmluZyB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gbWFzdGVyIElmIHRydWUsIG1lYW5zIHRoZSBtYXN0ZXIga2V5IHdhcyB1c2VkLlxuICogQHByb3BlcnR5IHtQYXJzZS5Vc2VyfSB1c2VyIElmIHNldCwgdGhlIHVzZXIgdGhhdCBtYWRlIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtQYXJzZS5PYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRyaWdnZXJpbmcgdGhlIGhvb2suXG4gKiBAcHJvcGVydHkge1N0cmluZ30gaXAgVGhlIElQIGFkZHJlc3Mgb2YgdGhlIGNsaWVudCBtYWtpbmcgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge09iamVjdH0gaGVhZGVycyBUaGUgb3JpZ2luYWwgSFRUUCBoZWFkZXJzIGZvciB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSB0cmlnZ2VyTmFtZSBUaGUgbmFtZSBvZiB0aGUgdHJpZ2dlciAoYGJlZm9yZVNhdmVgLCBgYWZ0ZXJTYXZlYCwgLi4uKVxuICogQHByb3BlcnR5IHtPYmplY3R9IGxvZyBUaGUgY3VycmVudCBsb2dnZXIgaW5zaWRlIFBhcnNlIFNlcnZlci5cbiAqIEBwcm9wZXJ0eSB7UGFyc2UuT2JqZWN0fSBvcmlnaW5hbCBJZiBzZXQsIHRoZSBvYmplY3QsIGFzIGN1cnJlbnRseSBzdG9yZWQuXG4gKi9cblxuLyoqXG4gKiBAaW50ZXJmYWNlIFBhcnNlLkNsb3VkLkJlZm9yZUZpbmRSZXF1ZXN0XG4gKiBAcHJvcGVydHkge1N0cmluZ30gaW5zdGFsbGF0aW9uSWQgSWYgc2V0LCB0aGUgaW5zdGFsbGF0aW9uSWQgdHJpZ2dlcmluZyB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gbWFzdGVyIElmIHRydWUsIG1lYW5zIHRoZSBtYXN0ZXIga2V5IHdhcyB1c2VkLlxuICogQHByb3BlcnR5IHtQYXJzZS5Vc2VyfSB1c2VyIElmIHNldCwgdGhlIHVzZXIgdGhhdCBtYWRlIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtQYXJzZS5RdWVyeX0gcXVlcnkgVGhlIHF1ZXJ5IHRyaWdnZXJpbmcgdGhlIGhvb2suXG4gKiBAcHJvcGVydHkge1N0cmluZ30gaXAgVGhlIElQIGFkZHJlc3Mgb2YgdGhlIGNsaWVudCBtYWtpbmcgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge09iamVjdH0gaGVhZGVycyBUaGUgb3JpZ2luYWwgSFRUUCBoZWFkZXJzIGZvciB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSB0cmlnZ2VyTmFtZSBUaGUgbmFtZSBvZiB0aGUgdHJpZ2dlciAoYGJlZm9yZVNhdmVgLCBgYWZ0ZXJTYXZlYCwgLi4uKVxuICogQHByb3BlcnR5IHtPYmplY3R9IGxvZyBUaGUgY3VycmVudCBsb2dnZXIgaW5zaWRlIFBhcnNlIFNlcnZlci5cbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gaXNHZXQgd2V0aGVyIHRoZSBxdWVyeSBhIGBnZXRgIG9yIGEgYGZpbmRgXG4gKi9cblxuLyoqXG4gKiBAaW50ZXJmYWNlIFBhcnNlLkNsb3VkLkFmdGVyRmluZFJlcXVlc3RcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpbnN0YWxsYXRpb25JZCBJZiBzZXQsIHRoZSBpbnN0YWxsYXRpb25JZCB0cmlnZ2VyaW5nIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtCb29sZWFufSBtYXN0ZXIgSWYgdHJ1ZSwgbWVhbnMgdGhlIG1hc3RlciBrZXkgd2FzIHVzZWQuXG4gKiBAcHJvcGVydHkge1BhcnNlLlVzZXJ9IHVzZXIgSWYgc2V0LCB0aGUgdXNlciB0aGF0IG1hZGUgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge1BhcnNlLlF1ZXJ5fSBxdWVyeSBUaGUgcXVlcnkgdHJpZ2dlcmluZyB0aGUgaG9vay5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8UGFyc2UuT2JqZWN0Pn0gcmVzdWx0cyBUaGUgcmVzdWx0cyB0aGUgcXVlcnkgeWllbGRlZC5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpcCBUaGUgSVAgYWRkcmVzcyBvZiB0aGUgY2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBoZWFkZXJzIFRoZSBvcmlnaW5hbCBIVFRQIGhlYWRlcnMgZm9yIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtTdHJpbmd9IHRyaWdnZXJOYW1lIFRoZSBuYW1lIG9mIHRoZSB0cmlnZ2VyIChgYmVmb3JlU2F2ZWAsIGBhZnRlclNhdmVgLCAuLi4pXG4gKiBAcHJvcGVydHkge09iamVjdH0gbG9nIFRoZSBjdXJyZW50IGxvZ2dlciBpbnNpZGUgUGFyc2UgU2VydmVyLlxuICovXG5cbi8qKlxuICogQGludGVyZmFjZSBQYXJzZS5DbG91ZC5GdW5jdGlvblJlcXVlc3RcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpbnN0YWxsYXRpb25JZCBJZiBzZXQsIHRoZSBpbnN0YWxsYXRpb25JZCB0cmlnZ2VyaW5nIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtCb29sZWFufSBtYXN0ZXIgSWYgdHJ1ZSwgbWVhbnMgdGhlIG1hc3RlciBrZXkgd2FzIHVzZWQuXG4gKiBAcHJvcGVydHkge1BhcnNlLlVzZXJ9IHVzZXIgSWYgc2V0LCB0aGUgdXNlciB0aGF0IG1hZGUgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge09iamVjdH0gcGFyYW1zIFRoZSBwYXJhbXMgcGFzc2VkIHRvIHRoZSBjbG91ZCBmdW5jdGlvbi5cbiAqL1xuXG4vKipcbiAqIEBpbnRlcmZhY2UgUGFyc2UuQ2xvdWQuSm9iUmVxdWVzdFxuICogQHByb3BlcnR5IHtPYmplY3R9IHBhcmFtcyBUaGUgcGFyYW1zIHBhc3NlZCB0byB0aGUgYmFja2dyb3VuZCBqb2IuXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9ufSBtZXNzYWdlIElmIG1lc3NhZ2UgaXMgY2FsbGVkIHdpdGggYSBzdHJpbmcgYXJndW1lbnQsIHdpbGwgdXBkYXRlIHRoZSBjdXJyZW50IG1lc3NhZ2UgdG8gYmUgc3RvcmVkIGluIHRoZSBqb2Igc3RhdHVzLlxuICovXG4iXX0= \ No newline at end of file diff --git a/lib/cloud-code/httpRequest.js b/lib/cloud-code/httpRequest.js new file mode 100644 index 0000000000..20191dffee --- /dev/null +++ b/lib/cloud-code/httpRequest.js @@ -0,0 +1,192 @@ +"use strict"; + +var _HTTPResponse = _interopRequireDefault(require("./HTTPResponse")); + +var _querystring = _interopRequireDefault(require("querystring")); + +var _logger = _interopRequireDefault(require("../logger")); + +var _followRedirects = require("follow-redirects"); + +var _url = require("url"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const clients = { + 'http:': _followRedirects.http, + 'https:': _followRedirects.https +}; + +function makeCallback(resolve, reject) { + return function (response) { + const chunks = []; + response.on('data', chunk => { + chunks.push(chunk); + }); + response.on('end', () => { + const body = Buffer.concat(chunks); + const httpResponse = new _HTTPResponse.default(response, body); // Consider <200 && >= 400 as errors + + if (httpResponse.status < 200 || httpResponse.status >= 400) { + return reject(httpResponse); + } else { + return resolve(httpResponse); + } + }); + response.on('error', reject); + }; +} + +const encodeBody = function ({ + body, + headers = {} +}) { + if (typeof body !== 'object') { + return { + body, + headers + }; + } + + var contentTypeKeys = Object.keys(headers).filter(key => { + return key.match(/content-type/i) != null; + }); + + if (contentTypeKeys.length == 0) { + // no content type + // As per https://parse.com/docs/cloudcode/guide#cloud-code-advanced-sending-a-post-request the default encoding is supposedly x-www-form-urlencoded + body = _querystring.default.stringify(body); + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } else { + /* istanbul ignore next */ + if (contentTypeKeys.length > 1) { + _logger.default.error('Parse.Cloud.httpRequest', 'multiple content-type headers are set.'); + } // There maybe many, we'll just take the 1st one + + + var contentType = contentTypeKeys[0]; + + if (headers[contentType].match(/application\/json/i)) { + body = JSON.stringify(body); + } else if (headers[contentType].match(/application\/x-www-form-urlencoded/i)) { + body = _querystring.default.stringify(body); + } + } + + return { + body, + headers + }; +}; +/** + * Makes an HTTP Request. + * + * **Available in Cloud Code only.** + * + * By default, Parse.Cloud.httpRequest does not follow redirects caused by HTTP 3xx response codes. You can use the followRedirects option in the {@link Parse.Cloud.HTTPOptions} object to change this behavior. + * + * Sample request: + * ``` + * Parse.Cloud.httpRequest({ + * url: 'http://www.parse.com/' + * }).then(function(httpResponse) { + * // success + * console.log(httpResponse.text); + * },function(httpResponse) { + * // error + * console.error('Request failed with response code ' + httpResponse.status); + * }); + * ``` + * + * @method httpRequest + * @name Parse.Cloud.httpRequest + * @param {Parse.Cloud.HTTPOptions} options The Parse.Cloud.HTTPOptions object that makes the request. + * @return {Promise} A promise that will be resolved with a {@link Parse.Cloud.HTTPResponse} object when the request completes. + */ + + +module.exports = function httpRequest(options) { + let url; + + try { + url = (0, _url.parse)(options.url); + } catch (e) { + return Promise.reject(e); + } + + options = Object.assign(options, encodeBody(options)); // support params options + + if (typeof options.params === 'object') { + options.qs = options.params; + } else if (typeof options.params === 'string') { + options.qs = _querystring.default.parse(options.params); + } + + const client = clients[url.protocol]; + + if (!client) { + return Promise.reject(`Unsupported protocol ${url.protocol}`); + } + + const requestOptions = { + method: options.method, + port: Number(url.port), + path: url.pathname, + hostname: url.hostname, + headers: options.headers, + encoding: null, + followRedirects: options.followRedirects === true + }; + + if (requestOptions.headers) { + Object.keys(requestOptions.headers).forEach(key => { + if (typeof requestOptions.headers[key] === 'undefined') { + delete requestOptions.headers[key]; + } + }); + } + + if (url.search) { + options.qs = Object.assign({}, options.qs, _querystring.default.parse(url.query)); + } + + if (url.auth) { + requestOptions.auth = url.auth; + } + + if (options.qs) { + requestOptions.path += `?${_querystring.default.stringify(options.qs)}`; + } + + if (options.agent) { + requestOptions.agent = options.agent; + } + + return new Promise((resolve, reject) => { + const req = client.request(requestOptions, makeCallback(resolve, reject, options)); + + if (options.body) { + req.write(options.body); + } + + req.on('error', error => { + reject(error); + }); + req.end(); + }); +}; +/** + * @typedef Parse.Cloud.HTTPOptions + * @property {String|Object} body The body of the request. If it is a JSON object, then the Content-Type set in the headers must be application/x-www-form-urlencoded or application/json. You can also set this to a {@link Buffer} object to send raw bytes. If you use a Buffer, you should also set the Content-Type header explicitly to describe what these bytes represent. + * @property {function} error The function that is called when the request fails. It will be passed a Parse.Cloud.HTTPResponse object. + * @property {Boolean} followRedirects Whether to follow redirects caused by HTTP 3xx responses. Defaults to false. + * @property {Object} headers The headers for the request. + * @property {String} method The method of the request. GET, POST, PUT, DELETE, HEAD, and OPTIONS are supported. Will default to GET if not specified. + * @property {String|Object} params The query portion of the url. You can pass a JSON object of key value pairs like params: {q : 'Sean Plott'} or a raw string like params:q=Sean Plott. + * @property {function} success The function that is called when the request successfully completes. It will be passed a Parse.Cloud.HTTPResponse object. + * @property {string} url The url to send the request to. + */ + + +module.exports.encodeBody = encodeBody; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1jb2RlL2h0dHBSZXF1ZXN0LmpzIl0sIm5hbWVzIjpbImNsaWVudHMiLCJodHRwIiwiaHR0cHMiLCJtYWtlQ2FsbGJhY2siLCJyZXNvbHZlIiwicmVqZWN0IiwicmVzcG9uc2UiLCJjaHVua3MiLCJvbiIsImNodW5rIiwicHVzaCIsImJvZHkiLCJCdWZmZXIiLCJjb25jYXQiLCJodHRwUmVzcG9uc2UiLCJIVFRQUmVzcG9uc2UiLCJzdGF0dXMiLCJlbmNvZGVCb2R5IiwiaGVhZGVycyIsImNvbnRlbnRUeXBlS2V5cyIsIk9iamVjdCIsImtleXMiLCJmaWx0ZXIiLCJrZXkiLCJtYXRjaCIsImxlbmd0aCIsInF1ZXJ5c3RyaW5nIiwic3RyaW5naWZ5IiwibG9nIiwiZXJyb3IiLCJjb250ZW50VHlwZSIsIkpTT04iLCJtb2R1bGUiLCJleHBvcnRzIiwiaHR0cFJlcXVlc3QiLCJvcHRpb25zIiwidXJsIiwiZSIsIlByb21pc2UiLCJhc3NpZ24iLCJwYXJhbXMiLCJxcyIsInBhcnNlIiwiY2xpZW50IiwicHJvdG9jb2wiLCJyZXF1ZXN0T3B0aW9ucyIsIm1ldGhvZCIsInBvcnQiLCJOdW1iZXIiLCJwYXRoIiwicGF0aG5hbWUiLCJob3N0bmFtZSIsImVuY29kaW5nIiwiZm9sbG93UmVkaXJlY3RzIiwiZm9yRWFjaCIsInNlYXJjaCIsInF1ZXJ5IiwiYXV0aCIsImFnZW50IiwicmVxIiwicmVxdWVzdCIsIndyaXRlIiwiZW5kIl0sIm1hcHBpbmdzIjoiOztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEsT0FBTyxHQUFHO0FBQ2QsV0FBU0MscUJBREs7QUFFZCxZQUFVQztBQUZJLENBQWhCOztBQUtBLFNBQVNDLFlBQVQsQ0FBc0JDLE9BQXRCLEVBQStCQyxNQUEvQixFQUF1QztBQUNyQyxTQUFPLFVBQVNDLFFBQVQsRUFBbUI7QUFDeEIsVUFBTUMsTUFBTSxHQUFHLEVBQWY7QUFDQUQsSUFBQUEsUUFBUSxD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RDs7QUFDRGdELElBQUFBLEdBQUcsQ0FBQ25ELEVBQUosQ0FBTyxPQUFQLEVBQWdCcUIsS0FBSyxJQUFJO0FBQ3ZCeEIsTUFBQUEsTUFBTSxDQUFDd0IsS0FBRCxDQUFOO0FBQ0QsS0FGRDtBQUdBOEIsSUFBQUEsR0FBRyxDQUFDRyxHQUFKO0FBQ0QsR0FaTSxDQUFQO0FBYUQsQ0EzREQ7QUE2REE7Ozs7Ozs7Ozs7Ozs7QUFZQTlCLE1BQU0sQ0FBQ0MsT0FBUCxDQUFlaEIsVUFBZixHQUE0QkEsVUFBNUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgSFRUUFJlc3BvbnNlIGZyb20gJy4vSFRUUFJlc3BvbnNlJztcbmltcG9ydCBxdWVyeXN0cmluZyBmcm9tICdxdWVyeXN0cmluZyc7XG5pbXBvcnQgbG9nIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgeyBodHRwLCBodHRwcyB9IGZyb20gJ2ZvbGxvdy1yZWRpcmVjdHMnO1xuaW1wb3J0IHsgcGFyc2UgfSBmcm9tICd1cmwnO1xuXG5jb25zdCBjbGllbnRzID0ge1xuICAnaHR0cDonOiBodHRwLFxuICAnaHR0cHM6JzogaHR0cHMsXG59O1xuXG5mdW5jdGlvbiBtYWtlQ2FsbGJhY2socmVzb2x2ZSwgcmVqZWN0KSB7XG4gIHJldHVybiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgIGNvbnN0IGNodW5rcyA9IFtdO1xuICAgIHJlc3BvbnNlLm9uKCdkYXRhJywgY2h1bmsgPT4ge1xuICAgICAgY2h1bmtzLnB1c2goY2h1bmspO1xuICAgIH0pO1xuICAgIHJlc3BvbnNlLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBib2R5ID0gQnVmZmVyLmNvbmNhdChjaHVua3MpO1xuICAgICAgY29uc3QgaHR0cFJlc3BvbnNlID0gbmV3IEhUVFBSZXNwb25zZShyZXNwb25zZSwgYm9keSk7XG5cbiAgICAgIC8vIENvbnNpZGVyIDwyMDAgJiYgPj0gNDAwIGFzIGVycm9yc1xuICAgICAgaWYgKGh0dHBSZXNwb25zZS5zdGF0dXMgPCAyMDAgfHwgaHR0cFJlc3BvbnNlLnN0YXR1cyA+PSA0MDApIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChodHRwUmVzcG9uc2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUoaHR0cFJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXNwb25zZS5vbignZXJyb3InLCByZWplY3QpO1xuICB9O1xufVxuXG5jb25zdCBlbmNvZGVCb2R5ID0gZnVuY3Rpb24oeyBib2R5LCBoZWFkZXJzID0ge30gfSkge1xuICBpZiAodHlwZW9mIGJvZHkgIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIHsgYm9keSwgaGVhZGVycyB9O1xuICB9XG4gIHZhciBjb250ZW50VHlwZUtleXMgPSBPYmplY3Qua2V5cyhoZWFkZXJzKS5maWx0ZXIoa2V5ID0+IHtcbiAgICByZXR1cm4ga2V5Lm1hdGNoKC9jb250ZW50LXR5cGUvaSkgIT0gbnVsbDtcbiAgfSk7XG5cbiAgaWYgKGNvbnRlbnRUeXBlS2V5cy5sZW5ndGggPT0gMCkge1xuICAgIC8vIG5vIGNvbnRlbnQgdHlwZVxuICAgIC8vICBBcyBwZXIgaHR0cHM6Ly9wYXJzZS5jb20vZG9jcy9jbG91ZGNvZGUvZ3VpZGUjY2xvdWQtY29kZS1hZHZhbmNlZC1zZW5kaW5nLWEtcG9zdC1yZXF1ZXN0IHRoZSBkZWZhdWx0IGVuY29kaW5nIGlzIHN1cHBvc2VkbHkgeC13d3ctZm9ybS11cmxlbmNvZGVkXG5cbiAgICBib2R5ID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KGJvZHkpO1xuICAgIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddID0gJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCc7XG4gIH0gZWxzZSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAoY29udGVudFR5cGVLZXlzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGxvZy5lcnJvcihcbiAgICAgICAgJ1BhcnNlLkNsb3VkLmh0dHBSZXF1ZXN0JyxcbiAgICAgICAgJ211bHRpcGxlIGNvbnRlbnQtdHlwZSBoZWFkZXJzIGFyZSBzZXQuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgLy8gVGhlcmUgbWF5YmUgbWFueSwgd2UnbGwganVzdCB0YWtlIHRoZSAxc3Qgb25lXG4gICAgdmFyIGNvbnRlbnRUeXBlID0gY29udGVudFR5cGVLZXlzWzBdO1xuICAgIGlmIChoZWFkZXJzW2NvbnRlbnRUeXBlXS5tYXRjaCgvYXBwbGljYXRpb25cXC9qc29uL2kpKSB7XG4gICAgICBib2R5ID0gSlNPTi5zdHJpbmdpZnkoYm9keSk7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIGhlYWRlcnNbY29udGVudFR5cGVdLm1hdGNoKC9hcHBsaWNhdGlvblxcL3gtd3d3LWZvcm0tdXJsZW5jb2RlZC9pKVxuICAgICkge1xuICAgICAgYm9keSA9IHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeShib2R5KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHsgYm9keSwgaGVhZGVycyB9O1xufTtcblxuLyoqXG4gKiBNYWtlcyBhbiBIVFRQIFJlcXVlc3QuXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogQnkgZGVmYXVsdCwgUGFyc2UuQ2xvdWQuaHR0cFJlcXVlc3QgZG9lcyBub3QgZm9sbG93IHJlZGlyZWN0cyBjYXVzZWQgYnkgSFRUUCAzeHggcmVzcG9uc2UgY29kZXMuIFlvdSBjYW4gdXNlIHRoZSBmb2xsb3dSZWRpcmVjdHMgb3B0aW9uIGluIHRoZSB7QGxpbmsgUGFyc2UuQ2xvdWQuSFRUUE9wdGlvbnN9IG9iamVjdCB0byBjaGFuZ2UgdGhpcyBiZWhhdmlvci5cbiAqXG4gKiBTYW1wbGUgcmVxdWVzdDpcbiAqIGBgYFxuICogUGFyc2UuQ2xvdWQuaHR0cFJlcXVlc3Qoe1xuICogICB1cmw6ICdodHRwOi8vd3d3LnBhcnNlLmNvbS8nXG4gKiB9KS50aGVuKGZ1bmN0aW9uKGh0dHBSZXNwb25zZSkge1xuICogICAvLyBzdWNjZXNzXG4gKiAgIGNvbnNvbGUubG9nKGh0dHBSZXNwb25zZS50ZXh0KTtcbiAqIH0sZnVuY3Rpb24oaHR0cFJlc3BvbnNlKSB7XG4gKiAgIC8vIGVycm9yXG4gKiAgIGNvbnNvbGUuZXJyb3IoJ1JlcXVlc3QgZmFpbGVkIHdpdGggcmVzcG9uc2UgY29kZSAnICsgaHR0cFJlc3BvbnNlLnN0YXR1cyk7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBtZXRob2QgaHR0cFJlcXVlc3RcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmh0dHBSZXF1ZXN0XG4gKiBAcGFyYW0ge1BhcnNlLkNsb3VkLkhUVFBPcHRpb25zfSBvcHRpb25zIFRoZSBQYXJzZS5DbG91ZC5IVFRQT3B0aW9ucyBvYmplY3QgdGhhdCBtYWtlcyB0aGUgcmVxdWVzdC5cbiAqIEByZXR1cm4ge1Byb21pc2U8UGFyc2UuQ2xvdWQuSFRUUFJlc3BvbnNlPn0gQSBwcm9taXNlIHRoYXQgd2lsbCBiZSByZXNvbHZlZCB3aXRoIGEge0BsaW5rIFBhcnNlLkNsb3VkLkhUVFBSZXNwb25zZX0gb2JqZWN0IHdoZW4gdGhlIHJlcXVlc3QgY29tcGxldGVzLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGh0dHBSZXF1ZXN0KG9wdGlvbnMpIHtcbiAgbGV0IHVybDtcbiAgdHJ5IHtcbiAgICB1cmwgPSBwYXJzZShvcHRpb25zLnVybCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XG4gIH1cbiAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24ob3B0aW9ucywgZW5jb2RlQm9keShvcHRpb25zKSk7XG4gIC8vIHN1cHBvcnQgcGFyYW1zIG9wdGlvbnNcbiAgaWYgKHR5cGVvZiBvcHRpb25zLnBhcmFtcyA9PT0gJ29iamVjdCcpIHtcbiAgICBvcHRpb25zLnFzID0gb3B0aW9ucy5wYXJhbXM7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMucGFyYW1zID09PSAnc3RyaW5nJykge1xuICAgIG9wdGlvbnMucXMgPSBxdWVyeXN0cmluZy5wYXJzZShvcHRpb25zLnBhcmFtcyk7XG4gIH1cbiAgY29uc3QgY2xpZW50ID0gY2xpZW50c1t1cmwucHJvdG9jb2xdO1xuICBpZiAoIWNsaWVudCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChgVW5zdXBwb3J0ZWQgcHJvdG9jb2wgJHt1cmwucHJvdG9jb2x9YCk7XG4gIH1cbiAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgbWV0aG9kOiBvcHRpb25zLm1ldGhvZCxcbiAgICBwb3J0OiBOdW1iZXIodXJsLnBvcnQpLFxuICAgIHBhdGg6IHVybC5wYXRobmFtZSxcbiAgICBob3N0bmFtZTogdXJsLmhvc3RuYW1lLFxuICAgIGhlYWRlcnM6IG9wdGlvbnMuaGVhZGVycyxcbiAgICBlbmNvZGluZzogbnVsbCxcbiAgICBmb2xsb3dSZWRpcmVjdHM6IG9wdGlvbnMuZm9sbG93UmVkaXJlY3RzID09PSB0cnVlLFxuICB9O1xuICBpZiAocmVxdWVzdE9wdGlvbnMuaGVhZGVycykge1xuICAgIE9iamVjdC5rZXlzKHJlcXVlc3RPcHRpb25zLmhlYWRlcnMpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIGlmICh0eXBlb2YgcmVxdWVzdE9wdGlvbnMuaGVhZGVyc1trZXldID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICBkZWxldGUgcmVxdWVzdE9wdGlvbnMuaGVhZGVyc1trZXldO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIGlmICh1cmwuc2VhcmNoKSB7XG4gICAgb3B0aW9ucy5xcyA9IE9iamVjdC5hc3NpZ24oe30sIG9wdGlvbnMucXMsIHF1ZXJ5c3RyaW5nLnBhcnNlKHVybC5xdWVyeSkpO1xuICB9XG4gIGlmICh1cmwuYXV0aCkge1xuICAgIHJlcXVlc3RPcHRpb25zLmF1dGggPSB1cmwuYXV0aDtcbiAgfVxuICBpZiAob3B0aW9ucy5xcykge1xuICAgIHJlcXVlc3RPcHRpb25zLnBhdGggKz0gYD8ke3F1ZXJ5c3RyaW5nLnN0cmluZ2lmeShvcHRpb25zLnFzKX1gO1xuICB9XG4gIGlmIChvcHRpb25zLmFnZW50KSB7XG4gICAgcmVxdWVzdE9wdGlvbnMuYWdlbnQgPSBvcHRpb25zLmFnZW50O1xuICB9XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgcmVxID0gY2xpZW50LnJlcXVlc3QoXG4gICAgICByZXF1ZXN0T3B0aW9ucyxcbiAgICAgIG1ha2VDYWxsYmFjayhyZXNvbHZlLCByZWplY3QsIG9wdGlvbnMpXG4gICAgKTtcbiAgICBpZiAob3B0aW9ucy5ib2R5KSB7XG4gICAgICByZXEud3JpdGUob3B0aW9ucy5ib2R5KTtcbiAgICB9XG4gICAgcmVxLm9uKCdlcnJvcicsIGVycm9yID0+IHtcbiAgICAgIHJlamVjdChlcnJvcik7XG4gICAgfSk7XG4gICAgcmVxLmVuZCgpO1xuICB9KTtcbn07XG5cbi8qKlxuICogQHR5cGVkZWYgUGFyc2UuQ2xvdWQuSFRUUE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfE9iamVjdH0gYm9keSBUaGUgYm9keSBvZiB0aGUgcmVxdWVzdC4gSWYgaXQgaXMgYSBKU09OIG9iamVjdCwgdGhlbiB0aGUgQ29udGVudC1UeXBlIHNldCBpbiB0aGUgaGVhZGVycyBtdXN0IGJlIGFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCBvciBhcHBsaWNhdGlvbi9qc29uLiBZb3UgY2FuIGFsc28gc2V0IHRoaXMgdG8gYSB7QGxpbmsgQnVmZmVyfSBvYmplY3QgdG8gc2VuZCByYXcgYnl0ZXMuIElmIHlvdSB1c2UgYSBCdWZmZXIsIHlvdSBzaG91bGQgYWxzbyBzZXQgdGhlIENvbnRlbnQtVHlwZSBoZWFkZXIgZXhwbGljaXRseSB0byBkZXNjcmliZSB3aGF0IHRoZXNlIGJ5dGVzIHJlcHJlc2VudC5cbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb259IGVycm9yIFRoZSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSByZXF1ZXN0IGZhaWxzLiBJdCB3aWxsIGJlIHBhc3NlZCBhIFBhcnNlLkNsb3VkLkhUVFBSZXNwb25zZSBvYmplY3QuXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IGZvbGxvd1JlZGlyZWN0cyBXaGV0aGVyIHRvIGZvbGxvdyByZWRpcmVjdHMgY2F1c2VkIGJ5IEhUVFAgM3h4IHJlc3BvbnNlcy4gRGVmYXVsdHMgdG8gZmFsc2UuXG4gKiBAcHJvcGVydHkge09iamVjdH0gaGVhZGVycyBUaGUgaGVhZGVycyBmb3IgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge1N0cmluZ30gbWV0aG9kIFRoZSBtZXRob2Qgb2YgdGhlIHJlcXVlc3QuIEdFVCwgUE9TVCwgUFVULCBERUxFVEUsIEhFQUQsIGFuZCBPUFRJT05TIGFyZSBzdXBwb3J0ZWQuIFdpbGwgZGVmYXVsdCB0byBHRVQgaWYgbm90IHNwZWNpZmllZC5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfE9iamVjdH0gcGFyYW1zIFRoZSBxdWVyeSBwb3J0aW9uIG9mIHRoZSB1cmwuIFlvdSBjYW4gcGFzcyBhIEpTT04gb2JqZWN0IG9mIGtleSB2YWx1ZSBwYWlycyBsaWtlIHBhcmFtczoge3EgOiAnU2VhbiBQbG90dCd9IG9yIGEgcmF3IHN0cmluZyBsaWtlIHBhcmFtczpxPVNlYW4gUGxvdHQuXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9ufSBzdWNjZXNzIFRoZSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSByZXF1ZXN0IHN1Y2Nlc3NmdWxseSBjb21wbGV0ZXMuIEl0IHdpbGwgYmUgcGFzc2VkIGEgUGFyc2UuQ2xvdWQuSFRUUFJlc3BvbnNlIG9iamVjdC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB1cmwgVGhlIHVybCB0byBzZW5kIHRoZSByZXF1ZXN0IHRvLlxuICovXG5cbm1vZHVsZS5leHBvcnRzLmVuY29kZUJvZHkgPSBlbmNvZGVCb2R5O1xuIl19 \ No newline at end of file diff --git a/lib/cryptoUtils.js b/lib/cryptoUtils.js new file mode 100644 index 0000000000..9c6e1b94cc --- /dev/null +++ b/lib/cryptoUtils.js @@ -0,0 +1,62 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.randomHexString = randomHexString; +exports.randomString = randomString; +exports.newObjectId = newObjectId; +exports.newToken = newToken; +exports.md5Hash = md5Hash; + +var _crypto = require("crypto"); + +// Returns a new random hex string of the given even size. +function randomHexString(size) { + if (size === 0) { + throw new Error('Zero-length randomHexString is useless.'); + } + + if (size % 2 !== 0) { + throw new Error('randomHexString size must be divisible by 2.'); + } + + return (0, _crypto.randomBytes)(size / 2).toString('hex'); +} // Returns a new random alphanumeric string of the given size. +// +// Note: to simplify implementation, the result has slight modulo bias, +// because chars length of 62 doesn't divide the number of all bytes +// (256) evenly. Such bias is acceptable for most cases when the output +// length is long enough and doesn't need to be uniform. + + +function randomString(size) { + if (size === 0) { + throw new Error('Zero-length randomString is useless.'); + } + + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789'; + let objectId = ''; + const bytes = (0, _crypto.randomBytes)(size); + + for (let i = 0; i < bytes.length; ++i) { + objectId += chars[bytes.readUInt8(i) % chars.length]; + } + + return objectId; +} // Returns a new random alphanumeric string suitable for object ID. + + +function newObjectId(size = 10) { + return randomString(size); +} // Returns a new random hex string suitable for secure tokens. + + +function newToken() { + return randomHexString(32); +} + +function md5Hash(string) { + return (0, _crypto.createHash)('md5').update(string).digest('hex'); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jcnlwdG9VdGlscy5qcyJdLCJuYW1lcyI6WyJyYW5kb21IZXhTdHJpbmciLCJzaXplIiwiRXJyb3IiLCJ0b1N0cmluZyIsInJhbmRvbVN0cmluZyIsImNoYXJzIiwib2JqZWN0SWQiLCJieXRlcyIsImkiLCJsZW5ndGgiLCJyZWFkVUludDgiLCJuZXdPYmplY3RJZCIsIm5ld1Rva2VuIiwibWQ1SGFzaCIsInN0cmluZyIsInVwZGF0ZSIsImRpZ2VzdCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFFQTs7QUFFQTtBQUNPLFNBQVNBLGVBQVQsQ0FBeUJDLElBQXpCLEVBQStDO0FBQ3BELE1BQUlBLElBQUksS0FBSyxDQUFiLEVBQWdCO0FBQ2QsVUFBTSxJQUFJQyxLQUFKLENBQVUseUNBQVYsQ0FBTjtBQUNEOztBQUNELE1BQUlELElBQUksR0FBRyxDQUFQLEtBQWEsQ0FBakIsRUFBb0I7QUFDbEIsVUFBTSxJQUFJQyxLQUFKLENBQVUsOENBQVYsQ0FBTjtBQUNEOztBQUNELFNBQU8seUJBQVlELElBQUksR0FBRyxDQUFuQixFQUFzQkUsUUFBdEIsQ0FBK0IsS0FBL0IsQ0FBUDtBQUNELEMsQ0FFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNPLFNBQVNDLFlBQVQsQ0FBc0JILElBQXRCLEVBQTRDO0FBQ2pELE1BQUlBLElBQUksS0FBSyxDQUFiLEVBQWdCO0FBQ2QsVUFBTSxJQUFJQyxLQUFKLENBQVUsc0NBQVYsQ0FBTjtBQUNEOztBQUNELFFBQU1HLEtBQUssR0FDVCwrQkFBK0IsNEJBQS9CLEdBQThELFlBRGhFO0FBRUEsTUFBSUMsUUFBUSxHQUFHLEVBQWY7QUFDQSxRQUFNQyxLQUFLLEdBQUcseUJBQVlOLElBQVosQ0FBZDs7QUFDQSxPQUFLLElBQUlPLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUdELEtBQUssQ0FBQ0UsTUFBMUIsRUFBa0MsRUFBRUQsQ0FBcEMsRUFBdUM7QUFDckNGLElBQUFBLFFBQVEsSUFBSUQsS0FBSyxDQUFDRSxLQUFLLENBQUNHLFNBQU4sQ0FBZ0JGLENBQWhCLElBQXFCSCxLQUFLLENBQUNJLE1BQTVCLENBQWpCO0FBQ0Q7O0FBQ0QsU0FBT0gsUUFBUDtBQUNELEMsQ0FFRDs7O0FBQ08sU0FBU0ssV0FBVCxDQUFxQlYsSUFBWSxHQUFHLEVBQXBDLEVBQWdEO0FBQ3JELFNBQU9HLFlBQVksQ0FBQ0gsSUFBRCxDQUFuQjtBQUNELEMsQ0FFRDs7O0FBQ08sU0FBU1csUUFBVCxHQUE0QjtBQUNqQyxTQUFPWixlQUFlLENBQUMsRUFBRCxDQUF0QjtBQUNEOztBQUVNLFNBQVNhLE9BQVQsQ0FBaUJDLE1BQWpCLEVBQXlDO0FBQzlDLFNBQU8sd0JBQVcsS0FBWCxFQUNKQyxNQURJLENBQ0dELE1BREgsRUFFSkUsTUFGSSxDQUVHLEtBRkgsQ0FBUDtBQUdEIiwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuaW1wb3J0IHsgcmFuZG9tQnl0ZXMsIGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuXG4vLyBSZXR1cm5zIGEgbmV3IHJhbmRvbSBoZXggc3RyaW5nIG9mIHRoZSBnaXZlbiBldmVuIHNpemUuXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tSGV4U3RyaW5nKHNpemU6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChzaXplID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdaZXJvLWxlbmd0aCByYW5kb21IZXhTdHJpbmcgaXMgdXNlbGVzcy4nKTtcbiAgfVxuICBpZiAoc2l6ZSAlIDIgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3JhbmRvbUhleFN0cmluZyBzaXplIG11c3QgYmUgZGl2aXNpYmxlIGJ5IDIuJyk7XG4gIH1cbiAgcmV0dXJuIHJhbmRvbUJ5dGVzKHNpemUgLyAyKS50b1N0cmluZygnaGV4Jyk7XG59XG5cbi8vIFJldHVybnMgYSBuZXcgcmFuZG9tIGFscGhhbnVtZXJpYyBzdHJpbmcgb2YgdGhlIGdpdmVuIHNpemUuXG4vL1xuLy8gTm90ZTogdG8gc2ltcGxpZnkgaW1wbGVtZW50YXRpb24sIHRoZSByZXN1bHQgaGFzIHNsaWdodCBtb2R1bG8gYmlhcyxcbi8vIGJlY2F1c2UgY2hhcnMgbGVuZ3RoIG9mIDYyIGRvZXNuJ3QgZGl2aWRlIHRoZSBudW1iZXIgb2YgYWxsIGJ5dGVzXG4vLyAoMjU2KSBldmVubHkuIFN1Y2ggYmlhcyBpcyBhY2NlcHRhYmxlIGZvciBtb3N0IGNhc2VzIHdoZW4gdGhlIG91dHB1dFxuLy8gbGVuZ3RoIGlzIGxvbmcgZW5vdWdoIGFuZCBkb2Vzbid0IG5lZWQgdG8gYmUgdW5pZm9ybS5cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21TdHJpbmcoc2l6ZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKHNpemUgPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1plcm8tbGVuZ3RoIHJhbmRvbVN0cmluZyBpcyB1c2VsZXNzLicpO1xuICB9XG4gIGNvbnN0IGNoYXJzID1cbiAgICAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVonICsgJ2FiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6JyArICcwMTIzNDU2Nzg5JztcbiAgbGV0IG9iamVjdElkID0gJyc7XG4gIGNvbnN0IGJ5dGVzID0gcmFuZG9tQnl0ZXMoc2l6ZSk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyArK2kpIHtcbiAgICBvYmplY3RJZCArPSBjaGFyc1tieXRlcy5yZWFkVUludDgoaSkgJSBjaGFycy5sZW5ndGhdO1xuICB9XG4gIHJldHVybiBvYmplY3RJZDtcbn1cblxuLy8gUmV0dXJucyBhIG5ldyByYW5kb20gYWxwaGFudW1lcmljIHN0cmluZyBzdWl0YWJsZSBmb3Igb2JqZWN0IElELlxuZXhwb3J0IGZ1bmN0aW9uIG5ld09iamVjdElkKHNpemU6IG51bWJlciA9IDEwKTogc3RyaW5nIHtcbiAgcmV0dXJuIHJhbmRvbVN0cmluZyhzaXplKTtcbn1cblxuLy8gUmV0dXJucyBhIG5ldyByYW5kb20gaGV4IHN0cmluZyBzdWl0YWJsZSBmb3Igc2VjdXJlIHRva2Vucy5cbmV4cG9ydCBmdW5jdGlvbiBuZXdUb2tlbigpOiBzdHJpbmcge1xuICByZXR1cm4gcmFuZG9tSGV4U3RyaW5nKDMyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1kNUhhc2goc3RyaW5nOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gY3JlYXRlSGFzaCgnbWQ1JylcbiAgICAudXBkYXRlKHN0cmluZylcbiAgICAuZGlnZXN0KCdoZXgnKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/defaults.js b/lib/defaults.js new file mode 100644 index 0000000000..e29d889415 --- /dev/null +++ b/lib/defaults.js @@ -0,0 +1,60 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DefaultMongoURI = exports.default = void 0; + +var _parsers = require("./Options/parsers"); + +const { + ParseServerOptions +} = require('./Options/Definitions'); + +const logsFolder = (() => { + let folder = './logs/'; + + if (typeof process !== 'undefined' && process.env.TESTING === '1') { + folder = './test_logs/'; + } + + if (process.env.PARSE_SERVER_LOGS_FOLDER) { + folder = (0, _parsers.nullParser)(process.env.PARSE_SERVER_LOGS_FOLDER); + } + + return folder; +})(); + +const { + verbose, + level +} = (() => { + const verbose = process.env.VERBOSE ? true : false; + return { + verbose, + level: verbose ? 'verbose' : undefined + }; +})(); + +const DefinitionDefaults = Object.keys(ParseServerOptions).reduce((memo, key) => { + const def = ParseServerOptions[key]; + + if (Object.prototype.hasOwnProperty.call(def, 'default')) { + memo[key] = def.default; + } + + return memo; +}, {}); +const computedDefaults = { + jsonLogs: process.env.JSON_LOGS || false, + logsFolder, + verbose, + level +}; + +var _default = Object.assign({}, DefinitionDefaults, computedDefaults); + +exports.default = _default; +const DefaultMongoURI = DefinitionDefaults.databaseURI; +exports.DefaultMongoURI = DefaultMongoURI; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9kZWZhdWx0cy5qcyJdLCJuYW1lcyI6WyJQYXJzZVNlcnZlck9wdGlvbnMiLCJyZXF1aXJlIiwibG9nc0ZvbGRlciIsImZvbGRlciIsInByb2Nlc3MiLCJlbnYiLCJURVNUSU5HIiwiUEFSU0VfU0VSVkVSX0xPR1NfRk9MREVSIiwidmVyYm9zZSIsImxldmVsIiwiVkVSQk9TRSIsInVuZGVmaW5lZCIsIkRlZmluaXRpb25EZWZhdWx0cyIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJtZW1vIiwia2V5IiwiZGVmIiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiZGVmYXVsdCIsImNvbXB1dGVkRGVmYXVsdHMiLCJqc29uTG9ncyIsIkpTT05fTE9HUyIsImFzc2lnbiIsIkRlZmF1bHRNb25nb1VSSSIsImRhdGFiYXNlVVJJIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0EsTUFBTTtBQUFFQSxFQUFBQTtBQUFGLElBQXlCQyxPQUFPLENBQUMsdUJBQUQsQ0FBdEM7O0FBQ0EsTUFBTUMsVUFBVSxHQUFHLENBQUMsTUFBTTtBQUN4QixNQUFJQyxNQUFNLEdBQUcsU0FBYjs7QUFDQSxNQUFJLE9BQU9DLE9BQVAsS0FBbUIsV0FBbkIsSUFBa0NBLE9BQU8sQ0FBQ0MsR0FBUixDQUFZQyxPQUFaLEtBQXdCLEdBQTlELEVBQW1FO0FBQ2pFSCxJQUFBQSxNQUFNLEdBQUcsY0FBVDtBQUNEOztBQUNELE1BQUlDLE9BQU8sQ0FBQ0MsR0FBUixDQUFZRSx3QkFBaEIsRUFBMEM7QUFDeENKLElBQUFBLE1BQU0sR0FBRyx5QkFBV0MsT0FBTyxDQUFDQyxHQUFSLENBQVlFLHdCQUF2QixDQUFUO0FBQ0Q7O0FBQ0QsU0FBT0osTUFBUDtBQUNELENBVGtCLEdBQW5COztBQVdBLE1BQU07QUFBRUssRUFBQUEsT0FBRjtBQUFXQyxFQUFBQTtBQUFYLElBQXFCLENBQUMsTUFBTTtBQUNoQyxRQUFNRCxPQUFPLEdBQUdKLE9BQU8sQ0FBQ0MsR0FBUixDQUFZSyxPQUFaLEdBQXNCLElBQXRCLEdBQTZCLEtBQTdDO0FBQ0EsU0FBTztBQUFFRixJQUFBQSxPQUFGO0FBQVdDLElBQUFBLEtBQUssRUFBRUQsT0FBTyxHQUFHLFNBQUgsR0FBZUc7QUFBeEMsR0FBUDtBQUNELENBSDBCLEdBQTNCOztBQUtBLE1BQU1DLGtCQUFrQixHQUFHQyxNQUFNLENBQUNDLElBQVAsQ0FBWWQsa0JBQVosRUFBZ0NlLE1BQWhDLENBQ3pCLENBQUNDLElBQUQsRUFBT0MsR0FBUCxLQUFlO0FBQ2IsUUFBTUMsR0FBRyxHQUFHbEIsa0JBQWtCLENBQUNpQixHQUFELENBQTlCOztBQUNBLE1BQUlKLE1BQU0sQ0FBQ00sU0FBUCxDQUFpQkMsY0FBakIsQ0FBZ0NDLElBQWhDLENBQXFDSCxHQUFyQyxFQUEwQyxTQUExQyxDQUFKLEVBQTBEO0FBQ3hERixJQUFBQSxJQUFJLENBQUNDLEdBQUQsQ0FBSixHQUFZQyxHQUFHLENBQUNJLE9BQWhCO0FBQ0Q7O0FBQ0QsU0FBT04sSUFBUDtBQUNELENBUHdCLEVBUXpCLEVBUnlCLENBQTNCO0FBV0EsTUFBTU8sZ0JBQWdCLEdBQUc7QUFDdkJDLEVBQUFBLFFBQVEsRUFBRXBCLE9BQU8sQ0FBQ0MsR0FBUixDQUFZb0IsU0FBWixJQUF5QixLQURaO0FBRXZCdkIsRUFBQUEsVUFGdUI7QUFHdkJNLEVBQUFBLE9BSHVCO0FBSXZCQyxFQUFBQTtBQUp1QixDQUF6Qjs7ZUFPZUksTUFBTSxDQUFDYSxNQUFQLENBQWMsRUFBZCxFQUFrQmQsa0JBQWxCLEVBQXNDVyxnQkFBdEMsQzs7O0FBQ1IsTUFBTUksZUFBZSxHQUFHZixrQkFBa0IsQ0FBQ2dCLFdBQTNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbnVsbFBhcnNlciB9IGZyb20gJy4vT3B0aW9ucy9wYXJzZXJzJztcbmNvbnN0IHsgUGFyc2VTZXJ2ZXJPcHRpb25zIH0gPSByZXF1aXJlKCcuL09wdGlvbnMvRGVmaW5pdGlvbnMnKTtcbmNvbnN0IGxvZ3NGb2xkZXIgPSAoKCkgPT4ge1xuICBsZXQgZm9sZGVyID0gJy4vbG9ncy8nO1xuICBpZiAodHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHByb2Nlc3MuZW52LlRFU1RJTkcgPT09ICcxJykge1xuICAgIGZvbGRlciA9ICcuL3Rlc3RfbG9ncy8nO1xuICB9XG4gIGlmIChwcm9jZXNzLmVudi5QQVJTRV9TRVJWRVJfTE9HU19GT0xERVIpIHtcbiAgICBmb2xkZXIgPSBudWxsUGFyc2VyKHByb2Nlc3MuZW52LlBBUlNFX1NFUlZFUl9MT0dTX0ZPTERFUik7XG4gIH1cbiAgcmV0dXJuIGZvbGRlcjtcbn0pKCk7XG5cbmNvbnN0IHsgdmVyYm9zZSwgbGV2ZWwgfSA9ICgoKSA9PiB7XG4gIGNvbnN0IHZlcmJvc2UgPSBwcm9jZXNzLmVudi5WRVJCT1NFID8gdHJ1ZSA6IGZhbHNlO1xuICByZXR1cm4geyB2ZXJib3NlLCBsZXZlbDogdmVyYm9zZSA/ICd2ZXJib3NlJyA6IHVuZGVmaW5lZCB9O1xufSkoKTtcblxuY29uc3QgRGVmaW5pdGlvbkRlZmF1bHRzID0gT2JqZWN0LmtleXMoUGFyc2VTZXJ2ZXJPcHRpb25zKS5yZWR1Y2UoXG4gIChtZW1vLCBrZXkpID0+IHtcbiAgICBjb25zdCBkZWYgPSBQYXJzZVNlcnZlck9wdGlvbnNba2V5XTtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGRlZiwgJ2RlZmF1bHQnKSkge1xuICAgICAgbWVtb1trZXldID0gZGVmLmRlZmF1bHQ7XG4gICAgfVxuICAgIHJldHVybiBtZW1vO1xuICB9LFxuICB7fVxuKTtcblxuY29uc3QgY29tcHV0ZWREZWZhdWx0cyA9IHtcbiAganNvbkxvZ3M6IHByb2Nlc3MuZW52LkpTT05fTE9HUyB8fCBmYWxzZSxcbiAgbG9nc0ZvbGRlcixcbiAgdmVyYm9zZSxcbiAgbGV2ZWwsXG59O1xuXG5leHBvcnQgZGVmYXVsdCBPYmplY3QuYXNzaWduKHt9LCBEZWZpbml0aW9uRGVmYXVsdHMsIGNvbXB1dGVkRGVmYXVsdHMpO1xuZXhwb3J0IGNvbnN0IERlZmF1bHRNb25nb1VSSSA9IERlZmluaXRpb25EZWZhdWx0cy5kYXRhYmFzZVVSSTtcbiJdfQ== \ No newline at end of file diff --git a/lib/deprecated.js b/lib/deprecated.js new file mode 100644 index 0000000000..3a36ad962a --- /dev/null +++ b/lib/deprecated.js @@ -0,0 +1,13 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.useExternal = useExternal; + +function useExternal(name, moduleName) { + return function () { + throw `${name} is not provided by parse-server anymore; please install ${moduleName}`; + }; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXByZWNhdGVkLmpzIl0sIm5hbWVzIjpbInVzZUV4dGVybmFsIiwibmFtZSIsIm1vZHVsZU5hbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBTyxTQUFTQSxXQUFULENBQXFCQyxJQUFyQixFQUEyQkMsVUFBM0IsRUFBdUM7QUFDNUMsU0FBTyxZQUFXO0FBQ2hCLFVBQU8sR0FBRUQsSUFBSyw0REFBMkRDLFVBQVcsRUFBcEY7QUFDRCxHQUZEO0FBR0QiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gdXNlRXh0ZXJuYWwobmFtZSwgbW9kdWxlTmFtZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdGhyb3cgYCR7bmFtZX0gaXMgbm90IHByb3ZpZGVkIGJ5IHBhcnNlLXNlcnZlciBhbnltb3JlOyBwbGVhc2UgaW5zdGFsbCAke21vZHVsZU5hbWV9YDtcbiAgfTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000000..9fd1bf74a0 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,107 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "S3Adapter", { + enumerable: true, + get: function () { + return _s3FilesAdapter.default; + } +}); +Object.defineProperty(exports, "FileSystemAdapter", { + enumerable: true, + get: function () { + return _fsFilesAdapter.default; + } +}); +Object.defineProperty(exports, "InMemoryCacheAdapter", { + enumerable: true, + get: function () { + return _InMemoryCacheAdapter.default; + } +}); +Object.defineProperty(exports, "NullCacheAdapter", { + enumerable: true, + get: function () { + return _NullCacheAdapter.default; + } +}); +Object.defineProperty(exports, "RedisCacheAdapter", { + enumerable: true, + get: function () { + return _RedisCacheAdapter.default; + } +}); +Object.defineProperty(exports, "LRUCacheAdapter", { + enumerable: true, + get: function () { + return _LRUCache.default; + } +}); +Object.defineProperty(exports, "PushWorker", { + enumerable: true, + get: function () { + return _PushWorker.PushWorker; + } +}); +Object.defineProperty(exports, "ParseGraphQLServer", { + enumerable: true, + get: function () { + return _ParseGraphQLServer.ParseGraphQLServer; + } +}); +exports.TestUtils = exports.ParseServer = exports.GCSAdapter = exports.default = void 0; + +var _ParseServer2 = _interopRequireDefault(require("./ParseServer")); + +var _s3FilesAdapter = _interopRequireDefault(require("@parse/s3-files-adapter")); + +var _fsFilesAdapter = _interopRequireDefault(require("@parse/fs-files-adapter")); + +var _InMemoryCacheAdapter = _interopRequireDefault(require("./Adapters/Cache/InMemoryCacheAdapter")); + +var _NullCacheAdapter = _interopRequireDefault(require("./Adapters/Cache/NullCacheAdapter")); + +var _RedisCacheAdapter = _interopRequireDefault(require("./Adapters/Cache/RedisCacheAdapter")); + +var _LRUCache = _interopRequireDefault(require("./Adapters/Cache/LRUCache.js")); + +var TestUtils = _interopRequireWildcard(require("./TestUtils")); + +exports.TestUtils = TestUtils; + +var _deprecated = require("./deprecated"); + +var _logger = require("./logger"); + +var _PushWorker = require("./Push/PushWorker"); + +var _Options = require("./Options"); + +var _ParseGraphQLServer = require("./GraphQL/ParseGraphQLServer"); + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Factory function +const _ParseServer = function (options) { + const server = new _ParseServer2.default(options); + return server.app; +}; // Mount the create liveQueryServer + + +exports.ParseServer = _ParseServer; +_ParseServer.createLiveQueryServer = _ParseServer2.default.createLiveQueryServer; +_ParseServer.start = _ParseServer2.default.start; +const GCSAdapter = (0, _deprecated.useExternal)('GCSAdapter', '@parse/gcs-files-adapter'); +exports.GCSAdapter = GCSAdapter; +Object.defineProperty(module.exports, 'logger', { + get: _logger.getLogger +}); +var _default = _ParseServer2.default; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6WyJfUGFyc2VTZXJ2ZXIiLCJvcHRpb25zIiwic2VydmVyIiwiUGFyc2VTZXJ2ZXIiLCJhcHAiLCJjcmVhdGVMaXZlUXVlcnlTZXJ2ZXIiLCJzdGFydCIsIkdDU0FkYXB0ZXIiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsIm1vZHVsZSIsImV4cG9ydHMiLCJnZXQiLCJnZXRMb2dnZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVBO0FBQ0EsTUFBTUEsWUFBWSxHQUFHLFVBQVNDLE9BQVQsRUFBc0M7QUFDekQsUUFBTUMsTUFBTSxHQUFHLElBQUlDLHFCQUFKLENBQWdCRixPQUFoQixDQUFmO0FBQ0EsU0FBT0MsTUFBTSxDQUFDRSxHQUFkO0FBQ0QsQ0FIRCxDLENBSUE7Ozs7QUFDQUosWUFBWSxDQUFDSyxxQkFBYixHQUFxQ0Ysc0JBQVlFLHFCQUFqRDtBQUNBTCxZQUFZLENBQUNNLEtBQWIsR0FBcUJILHNCQUFZRyxLQUFqQztBQUVBLE1BQU1DLFVBQVUsR0FBRyw2QkFBWSxZQUFaLEVBQTBCLDBCQUExQixDQUFuQjs7QUFFQUMsTUFBTSxDQUFDQyxjQUFQLENBQXNCQyxNQUFNLENBQUNDLE9BQTdCLEVBQXNDLFFBQXRDLEVBQWdEO0FBQzlDQyxFQUFBQSxHQUFHLEVBQUVDO0FBRHlDLENBQWhEO2VBSWVWLHFCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlU2VydmVyIGZyb20gJy4vUGFyc2VTZXJ2ZXInO1xuaW1wb3J0IFMzQWRhcHRlciBmcm9tICdAcGFyc2UvczMtZmlsZXMtYWRhcHRlcic7XG5pbXBvcnQgRmlsZVN5c3RlbUFkYXB0ZXIgZnJvbSAnQHBhcnNlL2ZzLWZpbGVzLWFkYXB0ZXInO1xuaW1wb3J0IEluTWVtb3J5Q2FjaGVBZGFwdGVyIGZyb20gJy4vQWRhcHRlcnMvQ2FjaGUvSW5NZW1vcnlDYWNoZUFkYXB0ZXInO1xuaW1wb3J0IE51bGxDYWNoZUFkYXB0ZXIgZnJvbSAnLi9BZGFwdGVycy9DYWNoZS9OdWxsQ2FjaGVBZGFwdGVyJztcbmltcG9ydCBSZWRpc0NhY2hlQWRhcHRlciBmcm9tICcuL0FkYXB0ZXJzL0NhY2hlL1JlZGlzQ2FjaGVBZGFwdGVyJztcbmltcG9ydCBMUlVDYWNoZUFkYXB0ZXIgZnJvbSAnLi9BZGFwdGVycy9DYWNoZS9MUlVDYWNoZS5qcyc7XG5pbXBvcnQgKiBhcyBUZXN0VXRpbHMgZnJvbSAnLi9UZXN0VXRpbHMnO1xuaW1wb3J0IHsgdXNlRXh0ZXJuYWwgfSBmcm9tICcuL2RlcHJlY2F0ZWQnO1xuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHsgUHVzaFdvcmtlciB9IGZyb20gJy4vUHVzaC9QdXNoV29ya2VyJztcbmltcG9ydCB7IFBhcnNlU2VydmVyT3B0aW9ucyB9IGZyb20gJy4vT3B0aW9ucyc7XG5pbXBvcnQgeyBQYXJzZUdyYXBoUUxTZXJ2ZXIgfSBmcm9tICcuL0dyYXBoUUwvUGFyc2VHcmFwaFFMU2VydmVyJztcblxuLy8gRmFjdG9yeSBmdW5jdGlvblxuY29uc3QgX1BhcnNlU2VydmVyID0gZnVuY3Rpb24ob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKSB7XG4gIGNvbnN0IHNlcnZlciA9IG5ldyBQYXJzZVNlcnZlcihvcHRpb25zKTtcbiAgcmV0dXJuIHNlcnZlci5hcHA7XG59O1xuLy8gTW91bnQgdGhlIGNyZWF0ZSBsaXZlUXVlcnlTZXJ2ZXJcbl9QYXJzZVNlcnZlci5jcmVhdGVMaXZlUXVlcnlTZXJ2ZXIgPSBQYXJzZVNlcnZlci5jcmVhdGVMaXZlUXVlcnlTZXJ2ZXI7XG5fUGFyc2VTZXJ2ZXIuc3RhcnQgPSBQYXJzZVNlcnZlci5zdGFydDtcblxuY29uc3QgR0NTQWRhcHRlciA9IHVzZUV4dGVybmFsKCdHQ1NBZGFwdGVyJywgJ0BwYXJzZS9nY3MtZmlsZXMtYWRhcHRlcicpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobW9kdWxlLmV4cG9ydHMsICdsb2dnZXInLCB7XG4gIGdldDogZ2V0TG9nZ2VyLFxufSk7XG5cbmV4cG9ydCBkZWZhdWx0IFBhcnNlU2VydmVyO1xuZXhwb3J0IHtcbiAgUzNBZGFwdGVyLFxuICBHQ1NBZGFwdGVyLFxuICBGaWxlU3lzdGVtQWRhcHRlcixcbiAgSW5NZW1vcnlDYWNoZUFkYXB0ZXIsXG4gIE51bGxDYWNoZUFkYXB0ZXIsXG4gIFJlZGlzQ2FjaGVBZGFwdGVyLFxuICBMUlVDYWNoZUFkYXB0ZXIsXG4gIFRlc3RVdGlscyxcbiAgUHVzaFdvcmtlcixcbiAgUGFyc2VHcmFwaFFMU2VydmVyLFxuICBfUGFyc2VTZXJ2ZXIgYXMgUGFyc2VTZXJ2ZXIsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/logger.js b/lib/logger.js new file mode 100644 index 0000000000..bd58e6bce9 --- /dev/null +++ b/lib/logger.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.setLogger = setLogger; +exports.getLogger = getLogger; + +var _defaults = _interopRequireDefault(require("./defaults")); + +var _WinstonLoggerAdapter = require("./Adapters/Logger/WinstonLoggerAdapter"); + +var _LoggerController = require("./Controllers/LoggerController"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Used for Separate Live Query Server +function defaultLogger() { + const options = { + logsFolder: _defaults.default.logsFolder, + jsonLogs: _defaults.default.jsonLogs, + verbose: _defaults.default.verbose, + silent: _defaults.default.silent + }; + const adapter = new _WinstonLoggerAdapter.WinstonLoggerAdapter(options); + return new _LoggerController.LoggerController(adapter, null, options); +} + +let logger = defaultLogger(); + +function setLogger(aLogger) { + logger = aLogger; +} + +function getLogger() { + return logger; +} // for: `import logger from './logger'` + + +Object.defineProperty(module.exports, 'default', { + get: getLogger +}); // for: `import { logger } from './logger'` + +Object.defineProperty(module.exports, 'logger', { + get: getLogger +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9sb2dnZXIuanMiXSwibmFtZXMiOlsiZGVmYXVsdExvZ2dlciIsIm9wdGlvbnMiLCJsb2dzRm9sZGVyIiwiZGVmYXVsdHMiLCJqc29uTG9ncyIsInZlcmJvc2UiLCJzaWxlbnQiLCJhZGFwdGVyIiwiV2luc3RvbkxvZ2dlckFkYXB0ZXIiLCJMb2dnZXJDb250cm9sbGVyIiwibG9nZ2VyIiwic2V0TG9nZ2VyIiwiYUxvZ2dlciIsImdldExvZ2dlciIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwibW9kdWxlIiwiZXhwb3J0cyIsImdldCJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFQTtBQUNBLFNBQVNBLGFBQVQsR0FBeUI7QUFDdkIsUUFBTUMsT0FBTyxHQUFHO0FBQ2RDLElBQUFBLFVBQVUsRUFBRUMsa0JBQVNELFVBRFA7QUFFZEUsSUFBQUEsUUFBUSxFQUFFRCxrQkFBU0MsUUFGTDtBQUdkQyxJQUFBQSxPQUFPLEVBQUVGLGtCQUFTRSxPQUhKO0FBSWRDLElBQUFBLE1BQU0sRUFBRUgsa0JBQVNHO0FBSkgsR0FBaEI7QUFNQSxRQUFNQyxPQUFPLEdBQUcsSUFBSUMsMENBQUosQ0FBeUJQLE9BQXpCLENBQWhCO0FBQ0EsU0FBTyxJQUFJUSxrQ0FBSixDQUFxQkYsT0FBckIsRUFBOEIsSUFBOUIsRUFBb0NOLE9BQXBDLENBQVA7QUFDRDs7QUFFRCxJQUFJUyxNQUFNLEdBQUdWLGFBQWEsRUFBMUI7O0FBRU8sU0FBU1csU0FBVCxDQUFtQkMsT0FBbkIsRUFBNEI7QUFDakNGLEVBQUFBLE1BQU0sR0FBR0UsT0FBVDtBQUNEOztBQUVNLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsU0FBT0gsTUFBUDtBQUNELEMsQ0FFRDs7O0FBQ0FJLE1BQU0sQ0FBQ0MsY0FBUCxDQUFzQkMsTUFBTSxDQUFDQyxPQUE3QixFQUFzQyxTQUF0QyxFQUFpRDtBQUMvQ0MsRUFBQUEsR0FBRyxFQUFFTDtBQUQwQyxDQUFqRCxFLENBSUE7O0FBQ0FDLE1BQU0sQ0FBQ0MsY0FBUCxDQUFzQkMsTUFBTSxDQUFDQyxPQUE3QixFQUFzQyxRQUF0QyxFQUFnRDtBQUM5Q0MsRUFBQUEsR0FBRyxFQUFFTDtBQUR5QyxDQUFoRCIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcbmltcG9ydCBkZWZhdWx0cyBmcm9tICcuL2RlZmF1bHRzJztcbmltcG9ydCB7IFdpbnN0b25Mb2dnZXJBZGFwdGVyIH0gZnJvbSAnLi9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlckFkYXB0ZXInO1xuaW1wb3J0IHsgTG9nZ2VyQ29udHJvbGxlciB9IGZyb20gJy4vQ29udHJvbGxlcnMvTG9nZ2VyQ29udHJvbGxlcic7XG5cbi8vIFVzZWQgZm9yIFNlcGFyYXRlIExpdmUgUXVlcnkgU2VydmVyXG5mdW5jdGlvbiBkZWZhdWx0TG9nZ2VyKCkge1xuICBjb25zdCBvcHRpb25zID0ge1xuICAgIGxvZ3NGb2xkZXI6IGRlZmF1bHRzLmxvZ3NGb2xkZXIsXG4gICAganNvbkxvZ3M6IGRlZmF1bHRzLmpzb25Mb2dzLFxuICAgIHZlcmJvc2U6IGRlZmF1bHRzLnZlcmJvc2UsXG4gICAgc2lsZW50OiBkZWZhdWx0cy5zaWxlbnQsXG4gIH07XG4gIGNvbnN0IGFkYXB0ZXIgPSBuZXcgV2luc3RvbkxvZ2dlckFkYXB0ZXIob3B0aW9ucyk7XG4gIHJldHVybiBuZXcgTG9nZ2VyQ29udHJvbGxlcihhZGFwdGVyLCBudWxsLCBvcHRpb25zKTtcbn1cblxubGV0IGxvZ2dlciA9IGRlZmF1bHRMb2dnZXIoKTtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldExvZ2dlcihhTG9nZ2VyKSB7XG4gIGxvZ2dlciA9IGFMb2dnZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2dnZXIoKSB7XG4gIHJldHVybiBsb2dnZXI7XG59XG5cbi8vIGZvcjogYGltcG9ydCBsb2dnZXIgZnJvbSAnLi9sb2dnZXInYFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZS5leHBvcnRzLCAnZGVmYXVsdCcsIHtcbiAgZ2V0OiBnZXRMb2dnZXIsXG59KTtcblxuLy8gZm9yOiBgaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInYFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZS5leHBvcnRzLCAnbG9nZ2VyJywge1xuICBnZXQ6IGdldExvZ2dlcixcbn0pO1xuIl19 \ No newline at end of file diff --git a/lib/middlewares.js b/lib/middlewares.js new file mode 100644 index 0000000000..20535e9e60 --- /dev/null +++ b/lib/middlewares.js @@ -0,0 +1,391 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.handleParseHeaders = handleParseHeaders; +exports.allowCrossDomain = allowCrossDomain; +exports.allowMethodOverride = allowMethodOverride; +exports.handleParseErrors = handleParseErrors; +exports.enforceMasterKeyAccess = enforceMasterKeyAccess; +exports.promiseEnforceMasterKeyAccess = promiseEnforceMasterKeyAccess; +exports.DEFAULT_ALLOWED_HEADERS = void 0; + +var _cache = _interopRequireDefault(require("./cache")); + +var _node = _interopRequireDefault(require("parse/node")); + +var _Auth = _interopRequireDefault(require("./Auth")); + +var _Config = _interopRequireDefault(require("./Config")); + +var _ClientSDK = _interopRequireDefault(require("./ClientSDK")); + +var _logger = _interopRequireDefault(require("./logger")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const DEFAULT_ALLOWED_HEADERS = 'X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, Content-Type, Pragma, Cache-Control'; +exports.DEFAULT_ALLOWED_HEADERS = DEFAULT_ALLOWED_HEADERS; + +const getMountForRequest = function (req) { + const mountPathLength = req.originalUrl.length - req.url.length; + const mountPath = req.originalUrl.slice(0, mountPathLength); + return req.protocol + '://' + req.get('host') + mountPath; +}; // Checks that the request is authorized for this app and checks user +// auth too. +// The bodyparser should run before this middleware. +// Adds info to the request: +// req.config - the Config for this app +// req.auth - the Auth for this request + + +function handleParseHeaders(req, res, next) { + var mount = getMountForRequest(req); + var info = { + appId: req.get('X-Parse-Application-Id'), + sessionToken: req.get('X-Parse-Session-Token'), + masterKey: req.get('X-Parse-Master-Key'), + installationId: req.get('X-Parse-Installation-Id'), + clientKey: req.get('X-Parse-Client-Key'), + javascriptKey: req.get('X-Parse-Javascript-Key'), + dotNetKey: req.get('X-Parse-Windows-Key'), + restAPIKey: req.get('X-Parse-REST-API-Key'), + clientVersion: req.get('X-Parse-Client-Version') + }; + var basicAuth = httpAuth(req); + + if (basicAuth) { + var basicAuthAppId = basicAuth.appId; + + if (_cache.default.get(basicAuthAppId)) { + info.appId = basicAuthAppId; + info.masterKey = basicAuth.masterKey || info.masterKey; + info.javascriptKey = basicAuth.javascriptKey || info.javascriptKey; + } + } + + if (req.body) { + // Unity SDK sends a _noBody key which needs to be removed. + // Unclear at this point if action needs to be taken. + delete req.body._noBody; + } + + var fileViaJSON = false; + + if (!info.appId || !_cache.default.get(info.appId)) { + // See if we can find the app id on the body. + if (req.body instanceof Buffer) { + // The only chance to find the app id is if this is a file + // upload that actually is a JSON body. So try to parse it. + req.body = JSON.parse(req.body); + fileViaJSON = true; + } + + if (req.body) { + delete req.body._RevocableSession; + } + + if (req.body && req.body._ApplicationId && _cache.default.get(req.body._ApplicationId) && (!info.masterKey || _cache.default.get(req.body._ApplicationId).masterKey === info.masterKey)) { + info.appId = req.body._ApplicationId; + info.javascriptKey = req.body._JavaScriptKey || ''; + delete req.body._ApplicationId; + delete req.body._JavaScriptKey; // TODO: test that the REST API formats generated by the other + // SDKs are handled ok + + if (req.body._ClientVersion) { + info.clientVersion = req.body._ClientVersion; + delete req.body._ClientVersion; + } + + if (req.body._InstallationId) { + info.installationId = req.body._InstallationId; + delete req.body._InstallationId; + } + + if (req.body._SessionToken) { + info.sessionToken = req.body._SessionToken; + delete req.body._SessionToken; + } + + if (req.body._MasterKey) { + info.masterKey = req.body._MasterKey; + delete req.body._MasterKey; + } + + if (req.body._ContentType) { + req.headers['content-type'] = req.body._ContentType; + delete req.body._ContentType; + } + } else { + return invalidRequest(req, res); + } + } + + if (info.clientVersion) { + info.clientSDK = _ClientSDK.default.fromString(info.clientVersion); + } + + if (fileViaJSON) { + // We need to repopulate req.body with a buffer + var base64 = req.body.base64; + req.body = Buffer.from(base64, 'base64'); + } + + const clientIp = getClientIp(req); + info.app = _cache.default.get(info.appId); + req.config = _Config.default.get(info.appId, mount); + req.config.headers = req.headers || {}; + req.config.ip = clientIp; + req.info = info; + + if (info.masterKey && req.config.masterKeyIps && req.config.masterKeyIps.length !== 0 && req.config.masterKeyIps.indexOf(clientIp) === -1) { + return invalidRequest(req, res); + } + + var isMaster = info.masterKey === req.config.masterKey; + + if (isMaster) { + req.auth = new _Auth.default.Auth({ + config: req.config, + installationId: info.installationId, + isMaster: true + }); + next(); + return; + } + + var isReadOnlyMaster = info.masterKey === req.config.readOnlyMasterKey; + + if (typeof req.config.readOnlyMasterKey != 'undefined' && req.config.readOnlyMasterKey && isReadOnlyMaster) { + req.auth = new _Auth.default.Auth({ + config: req.config, + installationId: info.installationId, + isMaster: true, + isReadOnly: true + }); + next(); + return; + } // Client keys are not required in parse-server, but if any have been configured in the server, validate them + // to preserve original behavior. + + + const keys = ['clientKey', 'javascriptKey', 'dotNetKey', 'restAPIKey']; + const oneKeyConfigured = keys.some(function (key) { + return req.config[key] !== undefined; + }); + const oneKeyMatches = keys.some(function (key) { + return req.config[key] !== undefined && info[key] === req.config[key]; + }); + + if (oneKeyConfigured && !oneKeyMatches) { + return invalidRequest(req, res); + } + + if (req.url == '/login') { + delete info.sessionToken; + } + + if (!info.sessionToken) { + req.auth = new _Auth.default.Auth({ + config: req.config, + installationId: info.installationId, + isMaster: false + }); + next(); + return; + } + + return Promise.resolve().then(() => { + // handle the upgradeToRevocableSession path on it's own + if (info.sessionToken && req.url === '/upgradeToRevocableSession' && info.sessionToken.indexOf('r:') != 0) { + return _Auth.default.getAuthForLegacySessionToken({ + config: req.config, + installationId: info.installationId, + sessionToken: info.sessionToken + }); + } else { + return _Auth.default.getAuthForSessionToken({ + config: req.config, + installationId: info.installationId, + sessionToken: info.sessionToken + }); + } + }).then(auth => { + if (auth) { + req.auth = auth; + next(); + } + }).catch(error => { + if (error instanceof _node.default.Error) { + next(error); + return; + } else { + // TODO: Determine the correct error scenario. + req.config.loggerController.error('error getting auth for sessionToken', error); + throw new _node.default.Error(_node.default.Error.UNKNOWN_ERROR, error); + } + }); +} + +function getClientIp(req) { + if (req.headers['x-forwarded-for']) { + // try to get from x-forwared-for if it set (behind reverse proxy) + return req.headers['x-forwarded-for'].split(',')[0]; + } else if (req.connection && req.connection.remoteAddress) { + // no proxy, try getting from connection.remoteAddress + return req.connection.remoteAddress; + } else if (req.socket) { + // try to get it from req.socket + return req.socket.remoteAddress; + } else if (req.connection && req.connection.socket) { + // try to get it form the connection.socket + return req.connection.socket.remoteAddress; + } else { + // if non above, fallback. + return req.ip; + } +} + +function httpAuth(req) { + if (!(req.req || req).headers.authorization) return; + var header = (req.req || req).headers.authorization; + var appId, masterKey, javascriptKey; // parse header + + var authPrefix = 'basic '; + var match = header.toLowerCase().indexOf(authPrefix); + + if (match == 0) { + var encodedAuth = header.substring(authPrefix.length, header.length); + var credentials = decodeBase64(encodedAuth).split(':'); + + if (credentials.length == 2) { + appId = credentials[0]; + var key = credentials[1]; + var jsKeyPrefix = 'javascript-key='; + var matchKey = key.indexOf(jsKeyPrefix); + + if (matchKey == 0) { + javascriptKey = key.substring(jsKeyPrefix.length, key.length); + } else { + masterKey = key; + } + } + } + + return { + appId: appId, + masterKey: masterKey, + javascriptKey: javascriptKey + }; +} + +function decodeBase64(str) { + return Buffer.from(str, 'base64').toString(); +} + +function allowCrossDomain(appId) { + return (req, res, next) => { + const config = _Config.default.get(appId, getMountForRequest(req)); + + let allowHeaders = DEFAULT_ALLOWED_HEADERS; + + if (config && config.allowHeaders) { + allowHeaders += `, ${config.allowHeaders.join(', ')}`; + } + + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); + res.header('Access-Control-Allow-Headers', allowHeaders); + res.header('Access-Control-Expose-Headers', 'X-Parse-Job-Status-Id, X-Parse-Push-Status-Id'); // intercept OPTIONS method + + if ('OPTIONS' == req.method) { + res.sendStatus(200); + } else { + next(); + } + }; +} + +function allowMethodOverride(req, res, next) { + if (req.method === 'POST' && req.body._method) { + req.originalMethod = req.method; + req.method = req.body._method; + delete req.body._method; + } + + next(); +} + +function handleParseErrors(err, req, res, next) { + const log = req.config && req.config.loggerController || _logger.default; + + if (err instanceof _node.default.Error) { + let httpStatus; // TODO: fill out this mapping + + switch (err.code) { + case _node.default.Error.INTERNAL_SERVER_ERROR: + httpStatus = 500; + break; + + case _node.default.Error.OBJECT_NOT_FOUND: + httpStatus = 404; + break; + + default: + httpStatus = 400; + } + + res.status(httpStatus); + res.json({ + code: err.code, + error: err.message + }); + log.error('Parse error: ', err); + + if (req.config && req.config.enableExpressErrorHandler) { + next(err); + } + } else if (err.status && err.message) { + res.status(err.status); + res.json({ + error: err.message + }); + next(err); + } else { + log.error('Uncaught internal server error.', err, err.stack); + res.status(500); + res.json({ + code: _node.default.Error.INTERNAL_SERVER_ERROR, + message: 'Internal server error.' + }); + next(err); + } +} + +function enforceMasterKeyAccess(req, res, next) { + if (!req.auth.isMaster) { + res.status(403); + res.end('{"error":"unauthorized: master key is required"}'); + return; + } + + next(); +} + +function promiseEnforceMasterKeyAccess(request) { + if (!request.auth.isMaster) { + const error = new Error(); + error.status = 403; + error.message = 'unauthorized: master key is required'; + throw error; + } + + return Promise.resolve(); +} + +function invalidRequest(req, res) { + res.status(403); + res.end('{"error":"unauthorized"}'); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9taWRkbGV3YXJlcy5qcyJdLCJuYW1lcyI6WyJERUZBVUxUX0FMTE9XRURfSEVBREVSUyIsImdldE1vdW50Rm9yUmVxdWVzdCIsInJlcSIsIm1vdW50UGF0aExlbmd0aCIsIm9yaWdpbmFsVXJsIiwibGVuZ3RoIiwidXJsIiwibW91bnRQYXRoIiwic2xpY2UiLCJwcm90b2NvbCIsImdldCIsImhhbmRsZVBhcnNlSGVhZGVycyIsInJlcyIsIm5leHQiLCJtb3VudCIsImluZm8iLCJhcHBJZCIsInNlc3Npb25Ub2tlbiIsIm1hc3RlcktleSIsImluc3RhbGxhdGlvbklkIiwiY2xpZW50S2V5IiwiamF2YXNjcmlwdEtleSIsImRvdE5ldEtleSIsInJlc3RBUElLZXkiLCJjbGllbnRWZXJzaW9uIiwiYmFzaWNBdXRoIiwiaHR0cEF1dGgiLCJiYXNpY0F1dGhBcHBJZCIsIkFwcENhY2hlIiwiYm9keSIsIl9ub0JvZHkiLCJmaWxlVmlhSlNPTiIsIkJ1ZmZlciIsIkpTT04iLCJwYXJzZSIsIl9SZXZvY2FibGVTZXNzaW9uIiwiX0FwcGxpY2F0aW9uSWQiLCJfSmF2YVNjcmlwdEtleSIsIl9DbGllbnRWZXJzaW9uIiwiX0luc3RhbGxhdGlvbklkIiwiX1Nlc3Npb25Ub2tlbiIsIl9NYXN0ZXJLZXkiLCJfQ29udGVudFR5cGUiLCJoZWFkZXJzIiwiaW52YWxpZFJlcXVlc3QiLCJjbGllbnRTREsiLCJDbGllbnRTREsiLCJmcm9tU3RyaW5nIiwiYmFzZTY0IiwiZnJvbSIsImNsaWVudElwIiwiZ2V0Q2xpZW50SXAiLCJhcHAiLCJjb25maWciLCJDb25maWciLCJpcCIsIm1hc3RlcktleUlwcyIsImluZGV4T2YiLCJpc01hc3RlciIsImF1dGgiLCJBdXRoIiwiaXNSZWFkT25seU1hc3RlciIsInJlYWRPbmx5TWFzdGVyS2V5IiwiaXNSZWFkT25seSIsImtleXMiLCJvbmVLZXlDb25maWd1cmVkIiwic29tZSIsImtleSIsInVuZGVmaW5lZCIsIm9uZUtleU1hdGNoZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInRoZW4iLCJnZXRBdXRoRm9yTGVnYWN5U2Vzc2lvblRva2VuIiwiZ2V0QXV0aEZvclNlc3Npb25Ub2tlbiIsImNhdGNoIiwiZXJyb3IiLCJQYXJzZSIsIkVycm9yIiwibG9nZ2VyQ29udHJvbGxlciIsIlVOS05PV05fRVJST1IiLCJzcGxpdCIsImNvbm5lY3Rpb24iLCJyZW1vdGVBZGRyZXNzIiwic29ja2V0IiwiYXV0aG9yaXphdGlvbiIsImhlYWRlciIsImF1dGhQcmVmaXgiLCJtYXRjaCIsInRvTG93ZXJDYXNlIiwiZW5jb2RlZEF1dGgiLCJzdWJzdHJpbmciLCJjcmVkZW50aWFscyIsImRlY29kZUJhc2U2NCIsImpzS2V5UHJlZml4IiwibWF0Y2hLZXkiLCJzdHIiLCJ0b1N0cmluZyIsImFsbG93Q3Jvc3NEb21haW4iLCJhbGxvd0hlYWRlcnMiLCJqb2luIiwibWV0aG9kIiwic2VuZFN0YXR1cyIsImFsbG93TWV0aG9kT3ZlcnJpZGUiLCJfbWV0aG9kIiwib3JpZ2luYWxNZXRob2QiLCJoYW5kbGVQYXJzZUVycm9ycyIsImVyciIsImxvZyIsImRlZmF1bHRMb2dnZXIiLCJodHRwU3RhdHVzIiwiY29kZSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsIk9CSkVDVF9OT1RfRk9VTkQiLCJzdGF0dXMiLCJqc29uIiwibWVzc2FnZSIsImVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXIiLCJzdGFjayIsImVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJlbmQiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsInJlcXVlc3QiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLHVCQUF1QixHQUNsQywyTkFESzs7O0FBR1AsTUFBTUMsa0JBQWtCLEdBQUcsVUFBU0MsR0FBVCxFQUFjO0FBQ3ZDLFFBQU1DLGVBQWUsR0FBR0QsR0FBRyxDQUFDRSxXQUFKLENBQWdCQyxN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RCxNQUFJLENBQUNYLEdBQUcsQ0FBQ3lELElBQUosQ0FBU0QsUUFBZCxFQUF3QjtBQUN0QjlDLElBQUFBLEdBQUcsQ0FBQ3NHLE1BQUosQ0FBVyxHQUFYO0FBQ0F0RyxJQUFBQSxHQUFHLENBQUM0RyxHQUFKLENBQVEsa0RBQVI7QUFDQTtBQUNEOztBQUNEM0csRUFBQUEsSUFBSTtBQUNMOztBQUVNLFNBQVM0Ryw2QkFBVCxDQUF1Q0MsT0FBdkMsRUFBZ0Q7QUFDckQsTUFBSSxDQUFDQSxPQUFPLENBQUMvRCxJQUFSLENBQWFELFFBQWxCLEVBQTRCO0FBQzFCLFVBQU1rQixLQUFLLEdBQUcsSUFBSUUsS0FBSixFQUFkO0FBQ0FGLElBQUFBLEtBQUssQ0FBQ3NDLE1BQU4sR0FBZSxHQUFmO0FBQ0F0QyxJQUFBQSxLQUFLLENBQUN3QyxPQUFOLEdBQWdCLHNDQUFoQjtBQUNBLFVBQU14QyxLQUFOO0FBQ0Q7O0FBQ0QsU0FBT04sT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFFRCxTQUFTM0IsY0FBVCxDQUF3QjFDLEdBQXhCLEVBQTZCVSxHQUE3QixFQUFrQztBQUNoQ0EsRUFBQUEsR0FBRyxDQUFDc0csTUFBSixDQUFXLEdBQVg7QUFDQXRHLEVBQUFBLEdBQUcsQ0FBQzRHLEdBQUosQ0FBUSwwQkFBUjtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEFwcENhY2hlIGZyb20gJy4vY2FjaGUnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IGF1dGggZnJvbSAnLi9BdXRoJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi9Db25maWcnO1xuaW1wb3J0IENsaWVudFNESyBmcm9tICcuL0NsaWVudFNESyc7XG5pbXBvcnQgZGVmYXVsdExvZ2dlciBmcm9tICcuL2xvZ2dlcic7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0FMTE9XRURfSEVBREVSUyA9XG4gICdYLVBhcnNlLU1hc3Rlci1LZXksIFgtUGFyc2UtUkVTVC1BUEktS2V5LCBYLVBhcnNlLUphdmFzY3JpcHQtS2V5LCBYLVBhcnNlLUFwcGxpY2F0aW9uLUlkLCBYLVBhcnNlLUNsaWVudC1WZXJzaW9uLCBYLVBhcnNlLVNlc3Npb24tVG9rZW4sIFgtUmVxdWVzdGVkLVdpdGgsIFgtUGFyc2UtUmV2b2NhYmxlLVNlc3Npb24sIENvbnRlbnQtVHlwZSwgUHJhZ21hLCBDYWNoZS1Db250cm9sJztcblxuY29uc3QgZ2V0TW91bnRGb3JSZXF1ZXN0ID0gZnVuY3Rpb24ocmVxKSB7XG4gIGNvbnN0IG1vdW50UGF0aExlbmd0aCA9IHJlcS5vcmlnaW5hbFVybC5sZW5ndGggLSByZXEudXJsLmxlbmd0aDtcbiAgY29uc3QgbW91bnRQYXRoID0gcmVxLm9yaWdpbmFsVXJsLnNsaWNlKDAsIG1vdW50UGF0aExlbmd0aCk7XG4gIHJldHVybiByZXEucHJvdG9jb2wgKyAnOi8vJyArIHJlcS5nZXQoJ2hvc3QnKSArIG1vdW50UGF0aDtcbn07XG5cbi8vIENoZWNrcyB0aGF0IHRoZSByZXF1ZXN0IGlzIGF1dGhvcml6ZWQgZm9yIHRoaXMgYXBwIGFuZCBjaGVja3MgdXNlclxuLy8gYXV0aCB0b28uXG4vLyBUaGUgYm9keXBhcnNlciBzaG91bGQgcnVuIGJlZm9yZSB0aGlzIG1pZGRsZXdhcmUuXG4vLyBBZGRzIGluZm8gdG8gdGhlIHJlcXVlc3Q6XG4vLyByZXEuY29uZmlnIC0gdGhlIENvbmZpZyBmb3IgdGhpcyBhcHBcbi8vIHJlcS5hdXRoIC0gdGhlIEF1dGggZm9yIHRoaXMgcmVxdWVzdFxuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZVBhcnNlSGVhZGVycyhyZXEsIHJlcywgbmV4dCkge1xuICB2YXIgbW91bnQgPSBnZXRNb3VudEZvclJlcXVlc3QocmVxKTtcblxuICB2YXIgaW5mbyA9IHtcbiAgICBhcHBJZDogcmVxLmdldCgnWC1QYXJzZS1BcHBsaWNhdGlvbi1JZCcpLFxuICAgIHNlc3Npb25Ub2tlbjogcmVxLmdldCgnWC1QYXJzZS1TZXNzaW9uLVRva2VuJyksXG4gICAgbWFzdGVyS2V5OiByZXEuZ2V0KCdYLVBhcnNlLU1hc3Rlci1LZXknKSxcbiAgICBpbnN0YWxsYXRpb25JZDogcmVxLmdldCgnWC1QYXJzZS1JbnN0YWxsYXRpb24tSWQnKSxcbiAgICBjbGllbnRLZXk6IHJlcS5nZXQoJ1gtUGFyc2UtQ2xpZW50LUtleScpLFxuICAgIGphdmFzY3JpcHRLZXk6IHJlcS5nZXQoJ1gtUGFyc2UtSmF2YXNjcmlwdC1LZXknKSxcbiAgICBkb3ROZXRLZXk6IHJlcS5nZXQoJ1gtUGFyc2UtV2luZG93cy1LZXknKSxcbiAgICByZXN0QVBJS2V5OiByZXEuZ2V0KCdYLVBhcnNlLVJFU1QtQVBJLUtleScpLFxuICAgIGNsaWVudFZlcnNpb246IHJlcS5nZXQoJ1gtUGFyc2UtQ2xpZW50LVZlcnNpb24nKSxcbiAgfTtcblxuICB2YXIgYmFzaWNBdXRoID0gaHR0cEF1dGgocmVxKTtcblxuICBpZiAoYmFzaWNBdXRoKSB7XG4gICAgdmFyIGJhc2ljQXV0aEFwcElkID0gYmFzaWNBdXRoLmFwcElkO1xuICAgIGlmIChBcHBDYWNoZS5nZXQoYmFzaWNBdXRoQXBwSWQpKSB7XG4gICAgICBpbmZvLmFwcElkID0gYmFzaWNBdXRoQXBwSWQ7XG4gICAgICBpbmZvLm1hc3RlcktleSA9IGJhc2ljQXV0aC5tYXN0ZXJLZXkgfHwgaW5mby5tYXN0ZXJLZXk7XG4gICAgICBpbmZvLmphdmFzY3JpcHRLZXkgPSBiYXNpY0F1dGguamF2YXNjcmlwdEtleSB8fCBpbmZvLmphdmFzY3JpcHRLZXk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlcS5ib2R5KSB7XG4gICAgLy8gVW5pdHkgU0RLIHNlbmRzIGEgX25vQm9keSBrZXkgd2hpY2ggbmVlZHMgdG8gYmUgcmVtb3ZlZC5cbiAgICAvLyBVbmNsZWFyIGF0IHRoaXMgcG9pbnQgaWYgYWN0aW9uIG5lZWRzIHRvIGJlIHRha2VuLlxuICAgIGRlbGV0ZSByZXEuYm9keS5fbm9Cb2R5O1xuICB9XG5cbiAgdmFyIGZpbGVWaWFKU09OID0gZmFsc2U7XG5cbiAgaWYgKCFpbmZvLmFwcElkIHx8ICFBcHBDYWNoZS5nZXQoaW5mby5hcHBJZCkpIHtcbiAgICAvLyBTZWUgaWYgd2UgY2FuIGZpbmQgdGhlIGFwcCBpZCBvbiB0aGUgYm9keS5cbiAgICBpZiAocmVxLmJvZHkgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgIC8vIFRoZSBvbmx5IGNoYW5jZSB0byBmaW5kIHRoZSBhcHAgaWQgaXMgaWYgdGhpcyBpcyBhIGZpbGVcbiAgICAgIC8vIHVwbG9hZCB0aGF0IGFjdHVhbGx5IGlzIGEgSlNPTiBib2R5LiBTbyB0cnkgdG8gcGFyc2UgaXQuXG4gICAgICByZXEuYm9keSA9IEpTT04ucGFyc2UocmVxLmJvZHkpO1xuICAgICAgZmlsZVZpYUpTT04gPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZXEuYm9keSkge1xuICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9SZXZvY2FibGVTZXNzaW9uO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHJlcS5ib2R5ICYmXG4gICAgICByZXEuYm9keS5fQXBwbGljYXRpb25JZCAmJlxuICAgICAgQXBwQ2FjaGUuZ2V0KHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkKSAmJlxuICAgICAgKCFpbmZvLm1hc3RlcktleSB8fFxuICAgICAgICBBcHBDYWNoZS5nZXQocmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQpLm1hc3RlcktleSA9PT0gaW5mby5tYXN0ZXJLZXkpXG4gICAgKSB7XG4gICAgICBpbmZvLmFwcElkID0gcmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQ7XG4gICAgICBpbmZvLmphdmFzY3JpcHRLZXkgPSByZXEuYm9keS5fSmF2YVNjcmlwdEtleSB8fCAnJztcbiAgICAgIGRlbGV0ZSByZXEuYm9keS5fQXBwbGljYXRpb25JZDtcbiAgICAgIGRlbGV0ZSByZXEuYm9keS5fSmF2YVNjcmlwdEtleTtcbiAgICAgIC8vIFRPRE86IHRlc3QgdGhhdCB0aGUgUkVTVCBBUEkgZm9ybWF0cyBnZW5lcmF0ZWQgYnkgdGhlIG90aGVyXG4gICAgICAvLyBTREtzIGFyZSBoYW5kbGVkIG9rXG4gICAgICBpZiAocmVxLmJvZHkuX0NsaWVudFZlcnNpb24pIHtcbiAgICAgICAgaW5mby5jbGllbnRWZXJzaW9uID0gcmVxLmJvZHkuX0NsaWVudFZlcnNpb247XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fQ2xpZW50VmVyc2lvbjtcbiAgICAgIH1cbiAgICAgIGlmIChyZXEuYm9keS5fSW5zdGFsbGF0aW9uSWQpIHtcbiAgICAgICAgaW5mby5pbnN0YWxsYXRpb25JZCA9IHJlcS5ib2R5Ll9JbnN0YWxsYXRpb25JZDtcbiAgICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9JbnN0YWxsYXRpb25JZDtcbiAgICAgIH1cbiAgICAgIGlmIChyZXEuYm9keS5fU2Vzc2lvblRva2VuKSB7XG4gICAgICAgIGluZm8uc2Vzc2lvblRva2VuID0gcmVxLmJvZHkuX1Nlc3Npb25Ub2tlbjtcbiAgICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9TZXNzaW9uVG9rZW47XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX01hc3RlcktleSkge1xuICAgICAgICBpbmZvLm1hc3RlcktleSA9IHJlcS5ib2R5Ll9NYXN0ZXJLZXk7XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fTWFzdGVyS2V5O1xuICAgICAgfVxuICAgICAgaWYgKHJlcS5ib2R5Ll9Db250ZW50VHlwZSkge1xuICAgICAgICByZXEuaGVhZGVyc1snY29udGVudC10eXBlJ10gPSByZXEuYm9keS5fQ29udGVudFR5cGU7XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fQ29udGVudFR5cGU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGluZm8uY2xpZW50VmVyc2lvbikge1xuICAgIGluZm8uY2xpZW50U0RLID0gQ2xpZW50U0RLLmZyb21TdHJpbmcoaW5mby5jbGllbnRWZXJzaW9uKTtcbiAgfVxuXG4gIGlmIChmaWxlVmlhSlNPTikge1xuICAgIC8vIFdlIG5lZWQgdG8gcmVwb3B1bGF0ZSByZXEuYm9keSB3aXRoIGEgYnVmZmVyXG4gICAgdmFyIGJhc2U2NCA9IHJlcS5ib2R5LmJhc2U2NDtcbiAgICByZXEuYm9keSA9IEJ1ZmZlci5mcm9tKGJhc2U2NCwgJ2Jhc2U2NCcpO1xuICB9XG5cbiAgY29uc3QgY2xpZW50SXAgPSBnZXRDbGllbnRJcChyZXEpO1xuXG4gIGluZm8uYXBwID0gQXBwQ2FjaGUuZ2V0KGluZm8uYXBwSWQpO1xuICByZXEuY29uZmlnID0gQ29uZmlnLmdldChpbmZvLmFwcElkLCBtb3VudCk7XG4gIHJlcS5jb25maWcuaGVhZGVycyA9IHJlcS5oZWFkZXJzIHx8IHt9O1xuICByZXEuY29uZmlnLmlwID0gY2xpZW50SXA7XG4gIHJlcS5pbmZvID0gaW5mbztcblxuICBpZiAoXG4gICAgaW5mby5tYXN0ZXJLZXkgJiZcbiAgICByZXEuY29uZmlnLm1hc3RlcktleUlwcyAmJlxuICAgIHJlcS5jb25maWcubWFzdGVyS2V5SXBzLmxlbmd0aCAhPT0gMCAmJlxuICAgIHJlcS5jb25maWcubWFzdGVyS2V5SXBzLmluZGV4T2YoY2xpZW50SXApID09PSAtMVxuICApIHtcbiAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICB9XG5cbiAgdmFyIGlzTWFzdGVyID0gaW5mby5tYXN0ZXJLZXkgPT09IHJlcS5jb25maWcubWFzdGVyS2V5O1xuXG4gIGlmIChpc01hc3Rlcikge1xuICAgIHJlcS5hdXRoID0gbmV3IGF1dGguQXV0aCh7XG4gICAgICBjb25maWc6IHJlcS5jb25maWcsXG4gICAgICBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCxcbiAgICAgIGlzTWFzdGVyOiB0cnVlLFxuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgaXNSZWFkT25seU1hc3RlciA9IGluZm8ubWFzdGVyS2V5ID09PSByZXEuY29uZmlnLnJlYWRPbmx5TWFzdGVyS2V5O1xuICBpZiAoXG4gICAgdHlwZW9mIHJlcS5jb25maWcucmVhZE9ubHlNYXN0ZXJLZXkgIT0gJ3VuZGVmaW5lZCcgJiZcbiAgICByZXEuY29uZmlnLnJlYWRPbmx5TWFzdGVyS2V5ICYmXG4gICAgaXNSZWFkT25seU1hc3RlclxuICApIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoe1xuICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsXG4gICAgICBpc01hc3RlcjogdHJ1ZSxcbiAgICAgIGlzUmVhZE9ubHk6IHRydWUsXG4gICAgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIENsaWVudCBrZXlzIGFyZSBub3QgcmVxdWlyZWQgaW4gcGFyc2Utc2VydmVyLCBidXQgaWYgYW55IGhhdmUgYmVlbiBjb25maWd1cmVkIGluIHRoZSBzZXJ2ZXIsIHZhbGlkYXRlIHRoZW1cbiAgLy8gIHRvIHByZXNlcnZlIG9yaWdpbmFsIGJlaGF2aW9yLlxuICBjb25zdCBrZXlzID0gWydjbGllbnRLZXknLCAnamF2YXNjcmlwdEtleScsICdkb3ROZXRLZXknLCAncmVzdEFQSUtleSddO1xuICBjb25zdCBvbmVLZXlDb25maWd1cmVkID0ga2V5cy5zb21lKGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiByZXEuY29uZmlnW2tleV0gIT09IHVuZGVmaW5lZDtcbiAgfSk7XG4gIGNvbnN0IG9uZUtleU1hdGNoZXMgPSBrZXlzLnNvbWUoZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIHJlcS5jb25maWdba2V5XSAhPT0gdW5kZWZpbmVkICYmIGluZm9ba2V5XSA9PT0gcmVxLmNvbmZpZ1trZXldO1xuICB9KTtcblxuICBpZiAob25lS2V5Q29uZmlndXJlZCAmJiAhb25lS2V5TWF0Y2hlcykge1xuICAgIHJldHVybiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcyk7XG4gIH1cblxuICBpZiAocmVxLnVybCA9PSAnL2xvZ2luJykge1xuICAgIGRlbGV0ZSBpbmZvLnNlc3Npb25Ub2tlbjtcbiAgfVxuXG4gIGlmICghaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoe1xuICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsXG4gICAgICBpc01hc3RlcjogZmFsc2UsXG4gICAgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIC8vIGhhbmRsZSB0aGUgdXBncmFkZVRvUmV2b2NhYmxlU2Vzc2lvbiBwYXRoIG9uIGl0J3Mgb3duXG4gICAgICBpZiAoXG4gICAgICAgIGluZm8uc2Vzc2lvblRva2VuICYmXG4gICAgICAgIHJlcS51cmwgPT09ICcvdXBncmFkZVRvUmV2b2NhYmxlU2Vzc2lvbicgJiZcbiAgICAgICAgaW5mby5zZXNzaW9uVG9rZW4uaW5kZXhPZigncjonKSAhPSAwXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbih7XG4gICAgICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgICAgIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLFxuICAgICAgICAgIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4sXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvclNlc3Npb25Ub2tlbih7XG4gICAgICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgICAgIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLFxuICAgICAgICAgIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pXG4gICAgLnRoZW4oYXV0aCA9PiB7XG4gICAgICBpZiAoYXV0aCkge1xuICAgICAgICByZXEuYXV0aCA9IGF1dGg7XG4gICAgICAgIG5leHQoKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgICAgICBuZXh0KGVycm9yKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVE9ETzogRGV0ZXJtaW5lIHRoZSBjb3JyZWN0IGVycm9yIHNjZW5hcmlvLlxuICAgICAgICByZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIuZXJyb3IoXG4gICAgICAgICAgJ2Vycm9yIGdldHRpbmcgYXV0aCBmb3Igc2Vzc2lvblRva2VuJyxcbiAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVU5LTk9XTl9FUlJPUiwgZXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRDbGllbnRJcChyZXEpIHtcbiAgaWYgKHJlcS5oZWFkZXJzWyd4LWZvcndhcmRlZC1mb3InXSkge1xuICAgIC8vIHRyeSB0byBnZXQgZnJvbSB4LWZvcndhcmVkLWZvciBpZiBpdCBzZXQgKGJlaGluZCByZXZlcnNlIHByb3h5KVxuICAgIHJldHVybiByZXEuaGVhZGVyc1sneC1mb3J3YXJkZWQtZm9yJ10uc3BsaXQoJywnKVswXTtcbiAgfSBlbHNlIGlmIChyZXEuY29ubmVjdGlvbiAmJiByZXEuY29ubmVjdGlvbi5yZW1vdGVBZGRyZXNzKSB7XG4gICAgLy8gbm8gcHJveHksIHRyeSBnZXR0aW5nIGZyb20gY29ubmVjdGlvbi5yZW1vdGVBZGRyZXNzXG4gICAgcmV0dXJuIHJlcS5jb25uZWN0aW9uLnJlbW90ZUFkZHJlc3M7XG4gIH0gZWxzZSBpZiAocmVxLnNvY2tldCkge1xuICAgIC8vIHRyeSB0byBnZXQgaXQgZnJvbSByZXEuc29ja2V0XG4gICAgcmV0dXJuIHJlcS5zb2NrZXQucmVtb3RlQWRkcmVzcztcbiAgfSBlbHNlIGlmIChyZXEuY29ubmVjdGlvbiAmJiByZXEuY29ubmVjdGlvbi5zb2NrZXQpIHtcbiAgICAvLyB0cnkgdG8gZ2V0IGl0IGZvcm0gdGhlIGNvbm5lY3Rpb24uc29ja2V0XG4gICAgcmV0dXJuIHJlcS5jb25uZWN0aW9uLnNvY2tldC5yZW1vdGVBZGRyZXNzO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIG5vbiBhYm92ZSwgZmFsbGJhY2suXG4gICAgcmV0dXJuIHJlcS5pcDtcbiAgfVxufVxuXG5mdW5jdGlvbiBodHRwQXV0aChyZXEpIHtcbiAgaWYgKCEocmVxLnJlcSB8fCByZXEpLmhlYWRlcnMuYXV0aG9yaXphdGlvbikgcmV0dXJuO1xuXG4gIHZhciBoZWFkZXIgPSAocmVxLnJlcSB8fCByZXEpLmhlYWRlcnMuYXV0aG9yaXphdGlvbjtcbiAgdmFyIGFwcElkLCBtYXN0ZXJLZXksIGphdmFzY3JpcHRLZXk7XG5cbiAgLy8gcGFyc2UgaGVhZGVyXG4gIHZhciBhdXRoUHJlZml4ID0gJ2Jhc2ljICc7XG5cbiAgdmFyIG1hdGNoID0gaGVhZGVyLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihhdXRoUHJlZml4KTtcblxuICBpZiAobWF0Y2ggPT0gMCkge1xuICAgIHZhciBlbmNvZGVkQXV0aCA9IGhlYWRlci5zdWJzdHJpbmcoYXV0aFByZWZpeC5sZW5ndGgsIGhlYWRlci5sZW5ndGgpO1xuICAgIHZhciBjcmVkZW50aWFscyA9IGRlY29kZUJhc2U2NChlbmNvZGVkQXV0aCkuc3BsaXQoJzonKTtcblxuICAgIGlmIChjcmVkZW50aWFscy5sZW5ndGggPT0gMikge1xuICAgICAgYXBwSWQgPSBjcmVkZW50aWFsc1swXTtcbiAgICAgIHZhciBrZXkgPSBjcmVkZW50aWFsc1sxXTtcblxuICAgICAgdmFyIGpzS2V5UHJlZml4ID0gJ2phdmFzY3JpcHQta2V5PSc7XG5cbiAgICAgIHZhciBtYXRjaEtleSA9IGtleS5pbmRleE9mKGpzS2V5UHJlZml4KTtcbiAgICAgIGlmIChtYXRjaEtleSA9PSAwKSB7XG4gICAgICAgIGphdmFzY3JpcHRLZXkgPSBrZXkuc3Vic3RyaW5nKGpzS2V5UHJlZml4Lmxlbmd0aCwga2V5Lmxlbmd0aCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXN0ZXJLZXkgPSBrZXk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgYXBwSWQ6IGFwcElkLCBtYXN0ZXJLZXk6IG1hc3RlcktleSwgamF2YXNjcmlwdEtleTogamF2YXNjcmlwdEtleSB9O1xufVxuXG5mdW5jdGlvbiBkZWNvZGVCYXNlNjQoc3RyKSB7XG4gIHJldHVybiBCdWZmZXIuZnJvbShzdHIsICdiYXNlNjQnKS50b1N0cmluZygpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWxsb3dDcm9zc0RvbWFpbihhcHBJZCkge1xuICByZXR1cm4gKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChhcHBJZCwgZ2V0TW91bnRGb3JSZXF1ZXN0KHJlcSkpO1xuICAgIGxldCBhbGxvd0hlYWRlcnMgPSBERUZBVUxUX0FMTE9XRURfSEVBREVSUztcbiAgICBpZiAoY29uZmlnICYmIGNvbmZpZy5hbGxvd0hlYWRlcnMpIHtcbiAgICAgIGFsbG93SGVhZGVycyArPSBgLCAke2NvbmZpZy5hbGxvd0hlYWRlcnMuam9pbignLCAnKX1gO1xuICAgIH1cbiAgICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4nLCAnKicpO1xuICAgIHJlcy5oZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnLCAnR0VULFBVVCxQT1NULERFTEVURSxPUFRJT05TJyk7XG4gICAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycycsIGFsbG93SGVhZGVycyk7XG4gICAgcmVzLmhlYWRlcihcbiAgICAgICdBY2Nlc3MtQ29udHJvbC1FeHBvc2UtSGVhZGVycycsXG4gICAgICAnWC1QYXJzZS1Kb2ItU3RhdHVzLUlkLCBYLVBhcnNlLVB1c2gtU3RhdHVzLUlkJ1xuICAgICk7XG4gICAgLy8gaW50ZXJjZXB0IE9QVElPTlMgbWV0aG9kXG4gICAgaWYgKCdPUFRJT05TJyA9PSByZXEubWV0aG9kKSB7XG4gICAgICByZXMuc2VuZFN0YXR1cygyMDApO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXh0KCk7XG4gICAgfVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWxsb3dNZXRob2RPdmVycmlkZShyZXEsIHJlcywgbmV4dCkge1xuICBpZiAocmVxLm1ldGhvZCA9PT0gJ1BPU1QnICYmIHJlcS5ib2R5Ll9tZXRob2QpIHtcbiAgICByZXEub3JpZ2luYWxNZXRob2QgPSByZXEubWV0aG9kO1xuICAgIHJlcS5tZXRob2QgPSByZXEuYm9keS5fbWV0aG9kO1xuICAgIGRlbGV0ZSByZXEuYm9keS5fbWV0aG9kO1xuICB9XG4gIG5leHQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZVBhcnNlRXJyb3JzKGVyciwgcmVxLCByZXMsIG5leHQpIHtcbiAgY29uc3QgbG9nID0gKHJlcS5jb25maWcgJiYgcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyKSB8fCBkZWZhdWx0TG9nZ2VyO1xuICBpZiAoZXJyIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IpIHtcbiAgICBsZXQgaHR0cFN0YXR1cztcbiAgICAvLyBUT0RPOiBmaWxsIG91dCB0aGlzIG1hcHBpbmdcbiAgICBzd2l0Y2ggKGVyci5jb2RlKSB7XG4gICAgICBjYXNlIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUjpcbiAgICAgICAgaHR0cFN0YXR1cyA9IDUwMDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQ6XG4gICAgICAgIGh0dHBTdGF0dXMgPSA0MDQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaHR0cFN0YXR1cyA9IDQwMDtcbiAgICB9XG5cbiAgICByZXMuc3RhdHVzKGh0dHBTdGF0dXMpO1xuICAgIHJlcy5qc29uKHsgY29kZTogZXJyLmNvZGUsIGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICBsb2cuZXJyb3IoJ1BhcnNlIGVycm9yOiAnLCBlcnIpO1xuICAgIGlmIChyZXEuY29uZmlnICYmIHJlcS5jb25maWcuZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlcikge1xuICAgICAgbmV4dChlcnIpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChlcnIuc3RhdHVzICYmIGVyci5tZXNzYWdlKSB7XG4gICAgcmVzLnN0YXR1cyhlcnIuc3RhdHVzKTtcbiAgICByZXMuanNvbih7IGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICBuZXh0KGVycik7XG4gIH0gZWxzZSB7XG4gICAgbG9nLmVycm9yKCdVbmNhdWdodCBpbnRlcm5hbCBzZXJ2ZXIgZXJyb3IuJywgZXJyLCBlcnIuc3RhY2spO1xuICAgIHJlcy5zdGF0dXMoNTAwKTtcbiAgICByZXMuanNvbih7XG4gICAgICBjb2RlOiBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICBtZXNzYWdlOiAnSW50ZXJuYWwgc2VydmVyIGVycm9yLicsXG4gICAgfSk7XG4gICAgbmV4dChlcnIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzKHJlcSwgcmVzLCBuZXh0KSB7XG4gIGlmICghcmVxLmF1dGguaXNNYXN0ZXIpIHtcbiAgICByZXMuc3RhdHVzKDQwMyk7XG4gICAgcmVzLmVuZCgne1wiZXJyb3JcIjpcInVuYXV0aG9yaXplZDogbWFzdGVyIGtleSBpcyByZXF1aXJlZFwifScpO1xuICAgIHJldHVybjtcbiAgfVxuICBuZXh0KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyhyZXF1ZXN0KSB7XG4gIGlmICghcmVxdWVzdC5hdXRoLmlzTWFzdGVyKSB7XG4gICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoKTtcbiAgICBlcnJvci5zdGF0dXMgPSA0MDM7XG4gICAgZXJyb3IubWVzc2FnZSA9ICd1bmF1dGhvcml6ZWQ6IG1hc3RlciBrZXkgaXMgcmVxdWlyZWQnO1xuICAgIHRocm93IGVycm9yO1xuICB9XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuZnVuY3Rpb24gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpIHtcbiAgcmVzLnN0YXR1cyg0MDMpO1xuICByZXMuZW5kKCd7XCJlcnJvclwiOlwidW5hdXRob3JpemVkXCJ9Jyk7XG59XG4iXX0= \ No newline at end of file diff --git a/lib/password.js b/lib/password.js new file mode 100644 index 0000000000..ab2f6d8219 --- /dev/null +++ b/lib/password.js @@ -0,0 +1,33 @@ +"use strict"; + +// Tools for encrypting and decrypting passwords. +// Basically promise-friendly wrappers for bcrypt. +var bcrypt = require('bcryptjs'); + +try { + bcrypt = require('bcrypt'); +} catch (e) {} +/* */ +// Returns a promise for a hashed password string. + + +function hash(password) { + return bcrypt.hash(password, 10); +} // Returns a promise for whether this password compares to equal this +// hashed password. + + +function compare(password, hashedPassword) { + // Cannot bcrypt compare when one is undefined + if (!password || !hashedPassword) { + return Promise.resolve(false); + } + + return bcrypt.compare(password, hashedPassword); +} + +module.exports = { + hash: hash, + compare: compare +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9wYXNzd29yZC5qcyJdLCJuYW1lcyI6WyJiY3J5cHQiLCJyZXF1aXJlIiwiZSIsImhhc2giLCJwYXNzd29yZCIsImNvbXBhcmUiLCJoYXNoZWRQYXNzd29yZCIsIlByb21pc2UiLCJyZXNvbHZlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0EsSUFBSUEsTUFBTSxHQUFHQyxPQUFPLENBQUMsVUFBRCxDQUFwQjs7QUFFQSxJQUFJO0FBQ0ZELEVBQUFBLE1BQU0sR0FBR0MsT0FBTyxDQUFDLFFBQUQsQ0FBaEI7QUFDRCxDQUZELENBRUUsT0FBT0MsQ0FBUCxFQUFVLENBRVg7QUFEQztBQUdGOzs7QUFDQSxTQUFTQyxJQUFULENBQWNDLFFBQWQsRUFBd0I7QUFDdEIsU0FBT0osTUFBTSxDQUFDRyxJQUFQLENBQVlDLFFBQVosRUFBc0IsRUFBdEIsQ0FBUDtBQUNELEMsQ0FFRDtBQUNBOzs7QUFDQSxTQUFTQyxPQUFULENBQWlCRCxRQUFqQixFQUEyQkUsY0FBM0IsRUFBMkM7QUFDekM7QUFDQSxNQUFJLENBQUNGLFFBQUQsSUFBYSxDQUFDRSxjQUFsQixFQUFrQztBQUNoQyxXQUFPQyxPQUFPLENBQUNDLE9BQVIsQ0FBZ0IsS0FBaEIsQ0FBUDtBQUNEOztBQUNELFNBQU9SLE1BQU0sQ0FBQ0ssT0FBUCxDQUFlRCxRQUFmLEVBQXlCRSxjQUF6QixDQUFQO0FBQ0Q7O0FBRURHLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmUCxFQUFBQSxJQUFJLEVBQUVBLElBRFM7QUFFZkUsRUFBQUEsT0FBTyxFQUFFQTtBQUZNLENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVG9vbHMgZm9yIGVuY3J5cHRpbmcgYW5kIGRlY3J5cHRpbmcgcGFzc3dvcmRzLlxuLy8gQmFzaWNhbGx5IHByb21pc2UtZnJpZW5kbHkgd3JhcHBlcnMgZm9yIGJjcnlwdC5cbnZhciBiY3J5cHQgPSByZXF1aXJlKCdiY3J5cHRqcycpO1xuXG50cnkge1xuICBiY3J5cHQgPSByZXF1aXJlKCdiY3J5cHQnKTtcbn0gY2F0Y2ggKGUpIHtcbiAgLyogKi9cbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEgaGFzaGVkIHBhc3N3b3JkIHN0cmluZy5cbmZ1bmN0aW9uIGhhc2gocGFzc3dvcmQpIHtcbiAgcmV0dXJuIGJjcnlwdC5oYXNoKHBhc3N3b3JkLCAxMCk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciB3aGV0aGVyIHRoaXMgcGFzc3dvcmQgY29tcGFyZXMgdG8gZXF1YWwgdGhpc1xuLy8gaGFzaGVkIHBhc3N3b3JkLlxuZnVuY3Rpb24gY29tcGFyZShwYXNzd29yZCwgaGFzaGVkUGFzc3dvcmQpIHtcbiAgLy8gQ2Fubm90IGJjcnlwdCBjb21wYXJlIHdoZW4gb25lIGlzIHVuZGVmaW5lZFxuICBpZiAoIXBhc3N3b3JkIHx8ICFoYXNoZWRQYXNzd29yZCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICB9XG4gIHJldHVybiBiY3J5cHQuY29tcGFyZShwYXNzd29yZCwgaGFzaGVkUGFzc3dvcmQpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgaGFzaDogaGFzaCxcbiAgY29tcGFyZTogY29tcGFyZSxcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/request.js b/lib/request.js new file mode 100644 index 0000000000..47dae80852 --- /dev/null +++ b/lib/request.js @@ -0,0 +1,4 @@ +"use strict"; + +module.exports = require('./cloud-code/httpRequest'); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9yZXF1ZXN0LmpzIl0sIm5hbWVzIjpbIm1vZHVsZSIsImV4cG9ydHMiLCJyZXF1aXJlIl0sIm1hcHBpbmdzIjoiOztBQUFBQSxNQUFNLENBQUNDLE9BQVAsR0FBaUJDLE9BQU8sQ0FBQywwQkFBRCxDQUF4QiIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9jbG91ZC1jb2RlL2h0dHBSZXF1ZXN0Jyk7XG4iXX0= \ No newline at end of file diff --git a/lib/requiredParameter.js b/lib/requiredParameter.js new file mode 100644 index 0000000000..2a657ca91b --- /dev/null +++ b/lib/requiredParameter.js @@ -0,0 +1,13 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _default = errorMessage => { + throw errorMessage; +}; + +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9yZXF1aXJlZFBhcmFtZXRlci5qcyJdLCJuYW1lcyI6WyJlcnJvck1lc3NhZ2UiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7ZUFDZ0JBLFlBQUQsSUFBK0I7QUFDNUMsUUFBTUEsWUFBTjtBQUNELEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQGZsb3cgKi9cbmV4cG9ydCBkZWZhdWx0IChlcnJvck1lc3NhZ2U6IHN0cmluZyk6IGFueSA9PiB7XG4gIHRocm93IGVycm9yTWVzc2FnZTtcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/rest.js b/lib/rest.js new file mode 100644 index 0000000000..982d233bb6 --- /dev/null +++ b/lib/rest.js @@ -0,0 +1,208 @@ +"use strict"; + +// This file contains helpers for running operations in REST format. +// The goal is that handlers that explicitly handle an express route +// should just be shallow wrappers around things in this file, but +// these functions should not explicitly depend on the request +// object. +// This means that one of these handlers can support multiple +// routes. That's useful for the routes that do really similar +// things. +var Parse = require('parse/node').Parse; + +var RestQuery = require('./RestQuery'); + +var RestWrite = require('./RestWrite'); + +var triggers = require('./triggers'); + +function checkTriggers(className, config, types) { + return types.some(triggerType => { + return triggers.getTrigger(className, triggers.Types[triggerType], config.applicationId); + }); +} + +function checkLiveQuery(className, config) { + return config.liveQueryController && config.liveQueryController.hasLiveQuery(className); +} // Returns a promise for an object with optional keys 'results' and 'count'. + + +function find(config, auth, className, restWhere, restOptions, clientSDK) { + enforceRoleSecurity('find', className, auth); + return triggers.maybeRunQueryTrigger(triggers.Types.beforeFind, className, restWhere, restOptions, config, auth).then(result => { + restWhere = result.restWhere || restWhere; + restOptions = result.restOptions || restOptions; + const query = new RestQuery(config, auth, className, restWhere, restOptions, clientSDK); + return query.execute(); + }); +} // get is just like find but only queries an objectId. + + +const get = (config, auth, className, objectId, restOptions, clientSDK) => { + var restWhere = { + objectId + }; + enforceRoleSecurity('get', className, auth); + return triggers.maybeRunQueryTrigger(triggers.Types.beforeFind, className, restWhere, restOptions, config, auth, true).then(result => { + restWhere = result.restWhere || restWhere; + restOptions = result.restOptions || restOptions; + const query = new RestQuery(config, auth, className, restWhere, restOptions, clientSDK); + return query.execute(); + }); +}; // Returns a promise that doesn't resolve to any useful value. + + +function del(config, auth, className, objectId) { + if (typeof objectId !== 'string') { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad objectId'); + } + + if (className === '_User' && auth.isUnauthenticated()) { + throw new Parse.Error(Parse.Error.SESSION_MISSING, 'Insufficient auth to delete user'); + } + + enforceRoleSecurity('delete', className, auth); + let inflatedObject; + let schemaController; + return Promise.resolve().then(() => { + const hasTriggers = checkTriggers(className, config, ['beforeDelete', 'afterDelete']); + const hasLiveQuery = checkLiveQuery(className, config); + + if (hasTriggers || hasLiveQuery || className == '_Session') { + return new RestQuery(config, auth, className, { + objectId + }).execute({ + op: 'delete' + }).then(response => { + if (response && response.results && response.results.length) { + const firstResult = response.results[0]; + firstResult.className = className; + + if (className === '_Session' && !auth.isMaster) { + if (!auth.user || firstResult.user.objectId !== auth.user.id) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); + } + } + + var cacheAdapter = config.cacheController; + cacheAdapter.user.del(firstResult.sessionToken); + inflatedObject = Parse.Object.fromJSON(firstResult); + return triggers.maybeRunTrigger(triggers.Types.beforeDelete, auth, inflatedObject, null, config); + } + + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found for delete.'); + }); + } + + return Promise.resolve({}); + }).then(() => { + if (!auth.isMaster) { + return auth.getUserRoles(); + } else { + return; + } + }).then(() => config.database.loadSchema()).then(s => { + schemaController = s; + const options = {}; + + if (!auth.isMaster) { + options.acl = ['*']; + + if (auth.user) { + options.acl.push(auth.user.id); + options.acl = options.acl.concat(auth.userRoles); + } + } + + return config.database.destroy(className, { + objectId: objectId + }, options, schemaController); + }).then(() => { + // Notify LiveQuery server if possible + const perms = schemaController.getClassLevelPermissions(className); + config.liveQueryController.onAfterDelete(className, inflatedObject, null, perms); + return triggers.maybeRunTrigger(triggers.Types.afterDelete, auth, inflatedObject, null, config); + }).catch(error => { + handleSessionMissingError(error, className, auth); + }); +} // Returns a promise for a {response, status, location} object. + + +function create(config, auth, className, restObject, clientSDK) { + enforceRoleSecurity('create', className, auth); + var write = new RestWrite(config, auth, className, null, restObject, null, clientSDK); + return write.execute(); +} // Returns a promise that contains the fields of the update that the +// REST API is supposed to return. +// Usually, this is just updatedAt. + + +function update(config, auth, className, restWhere, restObject, clientSDK) { + enforceRoleSecurity('update', className, auth); + return Promise.resolve().then(() => { + const hasTriggers = checkTriggers(className, config, ['beforeSave', 'afterSave']); + const hasLiveQuery = checkLiveQuery(className, config); + + if (hasTriggers || hasLiveQuery) { + // Do not use find, as it runs the before finds + return new RestQuery(config, auth, className, restWhere, undefined, undefined, false).execute({ + op: 'update' + }); + } + + return Promise.resolve({}); + }).then(({ + results + }) => { + var originalRestObject; + + if (results && results.length) { + originalRestObject = results[0]; + } + + return new RestWrite(config, auth, className, restWhere, restObject, originalRestObject, clientSDK).execute(); + }).catch(error => { + handleSessionMissingError(error, className, auth); + }); +} + +function handleSessionMissingError(error, className, auth) { + // If we're trying to update a user without / with bad session token + if (className === '_User' && error.code === Parse.Error.OBJECT_NOT_FOUND && !auth.isMaster) { + throw new Parse.Error(Parse.Error.SESSION_MISSING, 'Insufficient auth.'); + } + + throw error; +} + +const classesWithMasterOnlyAccess = ['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig', '_JobSchedule']; // Disallowing access to the _Role collection except by master key + +function enforceRoleSecurity(method, className, auth) { + if (className === '_Installation' && !auth.isMaster) { + if (method === 'delete' || method === 'find') { + const error = `Clients aren't allowed to perform the ${method} operation on the installation collection.`; + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error); + } + } //all volatileClasses are masterKey only + + + if (classesWithMasterOnlyAccess.indexOf(className) >= 0 && !auth.isMaster) { + const error = `Clients aren't allowed to perform the ${method} operation on the ${className} collection.`; + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error); + } // readOnly masterKey is not allowed + + + if (auth.isReadOnly && (method === 'delete' || method === 'create' || method === 'update')) { + const error = `read-only masterKey isn't allowed to perform the ${method} operation.`; + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error); + } +} + +module.exports = { + create, + del, + find, + get, + update +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9yZXN0LmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsIlJlc3RRdWVyeSIsIlJlc3RXcml0ZSIsInRyaWdnZXJzIiwiY2hlY2tUcmlnZ2VycyIsImNsYXNzTmFtZSIsImNvbmZpZyIsInR5cGVzIiwic29tZSIsInRyaWdnZXJUeXBlIiwiZ2V0VHJpZ2dlciIsIlR5cGVzIiwiYXBwbGljYXRpb25JZCIsImNoZWNrTGl2ZVF1ZXJ5IiwibGl2ZVF1ZXJ5Q29udHJvbGxlciIsImhhc0xpdmVRdWVyeSIsImZpbmQiLCJhdXRoIiwicmVzdFdoZXJlIiwicmVzdE9wdGlvbnMiLCJjbGllbnRTREsiLCJlbmZvcmNlUm9sZVNlY3VyaXR5IiwibWF5YmVSdW5RdWVyeVRyaWdnZXIiLCJiZWZvcmVGaW5kIiwidGhlbiIsInJlc3VsdCIsInF1ZXJ5IiwiZXhlY3V0ZSIsImdldCIsIm9iamVjdElkIiwiZGVsIiwiRXJyb3IiLCJJTlZBTElEX0pTT04iLCJpc1VuYXV0aGVudGljYXRlZCIsIlNFU1NJT05fTUlTU0lORyIsImluZmxhdGVkT2JqZWN0Iiwic2NoZW1hQ29udHJvbGxlciIsIlByb21pc2UiLCJyZXNvbHZlIiwiaGFzVHJpZ2dlcnMiLCJvcCIsInJlc3BvbnNlIiwicmVzdWx0cyIsImxlbmd0aCIsImZpcnN0UmVzdWx0IiwiaXNNYXN0ZXIiLCJ1c2VyIiwiaWQiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJjYWNoZUFkYXB0ZXIiLCJjYWNoZUNvbnRyb2xsZXIiLCJzZXNzaW9uVG9rZW4iLCJPYmplY3QiLCJmcm9tSlNPTiIsIm1heWJlUnVuVHJpZ2dlciIsImJlZm9yZURlbGV0ZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJnZXRVc2VyUm9sZXMiLCJkYXRhYmFzZSIsImxvYWRTY2hlbWEiLCJzIiwib3B0aW9ucyIsImFjbCIsInB1c2giLCJjb25jYXQiLCJ1c2VyUm9sZXMiLCJkZXN0cm95IiwicGVybXMiLCJnZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJvbkFmdGVyRGVsZXRlIiwiYWZ0ZXJEZWxldGUiLCJjYXRjaCIsImVycm9yIiwiaGFuZGxlU2Vzc2lvbk1pc3NpbmdFcnJvciIsImNyZWF0ZSIsInJlc3RPYmplY3QiLCJ3cml0ZSIsInVwZGF0ZSIsInVuZGVmaW5lZCIsIm9yaWdpbmFsUmVzdE9iamVjdCIsImNvZGUiLCJjbGFzc2VzV2l0aE1hc3Rlck9ubHlBY2Nlc3MiLCJtZXRob2QiLCJPUEVSQVRJT05fRk9SQklEREVOIiwiaW5kZXhPZiIsImlzUmVhZE9ubHkiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQSxJQUFJQSxLQUFLLEdBQUdDLE9BQU8sQ0FBQyxZQUFELENBQVAsQ0FBc0JELEtBQWxDOztBQUVBLElBQUlFLFNBQVMsR0FBR0QsT0FBTyxDQUFDLGFBQUQsQ0FBdkI7O0FBQ0EsSUFBSUUsU0FBUyxHQUFHRixPQUFPLENBQUMsYUFBRCxDQUF2Qjs7QUFDQSxJQUFJRyxRQUFRLEdBQUdILE9BQU8sQ0FBQyxZQUFELENBQXRCOztBQUVBLFNBQVNJLGFBQVQsQ0FBdUJDLFNBQXZCLEVBQWtDQyxNQUFsQyxFQUEwQ0MsS0FBMUMsRUFBaUQ7QUFDL0MsU0FBT0EsS0FBSyxDQUFDQyxJQUFOLENBQVdDLFdBQVcsSUFBSTtBQUMvQixXQUFPTixRQUFRLENBQUNPLFVBQVQsQ0FDTEwsU0FESyxFQUVMRixRQUFRLENBQUNRLEtBQVQsQ0FBZUYsV0FBZixDQUZLLEVBR0xILE1BQU0sQ0FBQ00sYUFIRixDQUFQO0FBS0QsR0FOTSxDQUFQO0FBT0Q7O0FBRUQsU0FBU0MsY0FBVCxDQUF3QlIsU0FBeEIsRUFBbUNDLE1BQW5DLEVBQTJDO0FBQ3pDLFNBQ0VBLE1BQU0sQ0FBQ1EsbUJBQVAsSUFDQVIsTUFBTSxDQUFDUSxtQkFBUCxDQUEyQkMsWUFBM0IsQ0FBd0NWLFNBQXhDLENBRkY7QUFJRCxDLENBRUQ7OztBQUNBLFNBQVNXLElBQVQsQ0FB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QUFvQy9FLFNBQXBDLEtBQWtELENBQWxELElBQXVELENBQUNZLElBQUksQ0FBQzRCLFFBQWpFLEVBQTJFO0FBQ3pFLFVBQU0yQixLQUFLLEdBQUkseUNBQXdDVSxNQUFPLHFCQUFvQjdFLFNBQVUsY0FBNUY7QUFDQSxVQUFNLElBQUlOLEtBQUssQ0FBQ2dDLEtBQVYsQ0FBZ0JoQyxLQUFLLENBQUNnQyxLQUFOLENBQVlvRCxtQkFBNUIsRUFBaURYLEtBQWpELENBQU47QUFDRCxHQVptRCxDQWNwRDs7O0FBQ0EsTUFDRXZELElBQUksQ0FBQ29FLFVBQUwsS0FDQ0gsTUFBTSxLQUFLLFFBQVgsSUFBdUJBLE1BQU0sS0FBSyxRQUFsQyxJQUE4Q0EsTUFBTSxLQUFLLFFBRDFELENBREYsRUFHRTtBQUNBLFVBQU1WLEtBQUssR0FBSSxvREFBbURVLE1BQU8sYUFBekU7QUFDQSxVQUFNLElBQUluRixLQUFLLENBQUNnQyxLQUFWLENBQWdCaEMsS0FBSyxDQUFDZ0MsS0FBTixDQUFZb0QsbUJBQTVCLEVBQWlEWCxLQUFqRCxDQUFOO0FBQ0Q7QUFDRjs7QUFFRGMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZiLEVBQUFBLE1BRGU7QUFFZjVDLEVBQUFBLEdBRmU7QUFHZmQsRUFBQUEsSUFIZTtBQUlmWSxFQUFBQSxHQUplO0FBS2ZpRCxFQUFBQTtBQUxlLENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhpcyBmaWxlIGNvbnRhaW5zIGhlbHBlcnMgZm9yIHJ1bm5pbmcgb3BlcmF0aW9ucyBpbiBSRVNUIGZvcm1hdC5cbi8vIFRoZSBnb2FsIGlzIHRoYXQgaGFuZGxlcnMgdGhhdCBleHBsaWNpdGx5IGhhbmRsZSBhbiBleHByZXNzIHJvdXRlXG4vLyBzaG91bGQganVzdCBiZSBzaGFsbG93IHdyYXBwZXJzIGFyb3VuZCB0aGluZ3MgaW4gdGhpcyBmaWxlLCBidXRcbi8vIHRoZXNlIGZ1bmN0aW9ucyBzaG91bGQgbm90IGV4cGxpY2l0bHkgZGVwZW5kIG9uIHRoZSByZXF1ZXN0XG4vLyBvYmplY3QuXG4vLyBUaGlzIG1lYW5zIHRoYXQgb25lIG9mIHRoZXNlIGhhbmRsZXJzIGNhbiBzdXBwb3J0IG11bHRpcGxlXG4vLyByb3V0ZXMuIFRoYXQncyB1c2VmdWwgZm9yIHRoZSByb3V0ZXMgdGhhdCBkbyByZWFsbHkgc2ltaWxhclxuLy8gdGhpbmdzLlxuXG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbnZhciBSZXN0UXVlcnkgPSByZXF1aXJlKCcuL1Jlc3RRdWVyeScpO1xudmFyIFJlc3RXcml0ZSA9IHJlcXVpcmUoJy4vUmVzdFdyaXRlJyk7XG52YXIgdHJpZ2dlcnMgPSByZXF1aXJlKCcuL3RyaWdnZXJzJyk7XG5cbmZ1bmN0aW9uIGNoZWNrVHJpZ2dlcnMoY2xhc3NOYW1lLCBjb25maWcsIHR5cGVzKSB7XG4gIHJldHVybiB0eXBlcy5zb21lKHRyaWdnZXJUeXBlID0+IHtcbiAgICByZXR1cm4gdHJpZ2dlcnMuZ2V0VHJpZ2dlcihcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHRyaWdnZXJzLlR5cGVzW3RyaWdnZXJUeXBlXSxcbiAgICAgIGNvbmZpZy5hcHBsaWNhdGlvbklkXG4gICAgKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrTGl2ZVF1ZXJ5KGNsYXNzTmFtZSwgY29uZmlnKSB7XG4gIHJldHVybiAoXG4gICAgY29uZmlnLmxpdmVRdWVyeUNvbnRyb2xsZXIgJiZcbiAgICBjb25maWcubGl2ZVF1ZXJ5Q29udHJvbGxlci5oYXNMaXZlUXVlcnkoY2xhc3NOYW1lKVxuICApO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYW4gb2JqZWN0IHdpdGggb3B0aW9uYWwga2V5cyAncmVzdWx0cycgYW5kICdjb3VudCcuXG5mdW5jdGlvbiBmaW5kKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUsIHJlc3RPcHRpb25zLCBjbGllbnRTREspIHtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZmluZCcsIGNsYXNzTmFtZSwgYXV0aCk7XG4gIHJldHVybiB0cmlnZ2Vyc1xuICAgIC5tYXliZVJ1blF1ZXJ5VHJpZ2dlcihcbiAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZUZpbmQsXG4gICAgICBjbGFzc05hbWUsXG4gICAgICByZXN0V2hlcmUsXG4gICAgICByZXN0T3B0aW9ucyxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGF1dGhcbiAgICApXG4gICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHJlc3RXaGVyZSA9IHJlc3VsdC5yZXN0V2hlcmUgfHwgcmVzdFdoZXJlO1xuICAgICAgcmVzdE9wdGlvbnMgPSByZXN1bHQucmVzdE9wdGlvbnMgfHwgcmVzdE9wdGlvbnM7XG4gICAgICBjb25zdCBxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICByZXN0V2hlcmUsXG4gICAgICAgIHJlc3RPcHRpb25zLFxuICAgICAgICBjbGllbnRTREtcbiAgICAgICk7XG4gICAgICByZXR1cm4gcXVlcnkuZXhlY3V0ZSgpO1xuICAgIH0pO1xufVxuXG4vLyBnZXQgaXMganVzdCBsaWtlIGZpbmQgYnV0IG9ubHkgcXVlcmllcyBhbiBvYmplY3RJZC5cbmNvbnN0IGdldCA9IChjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgb2JqZWN0SWQsIHJlc3RPcHRpb25zLCBjbGllbnRTREspID0+IHtcbiAgdmFyIHJlc3RXaGVyZSA9IHsgb2JqZWN0SWQgfTtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZ2V0JywgY2xhc3NOYW1lLCBhdXRoKTtcbiAgcmV0dXJuIHRyaWdnZXJzXG4gICAgLm1heWJlUnVuUXVlcnlUcmlnZ2VyKFxuICAgICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlRmluZCxcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHJlc3RXaGVyZSxcbiAgICAgIHJlc3RPcHRpb25zLFxuICAgICAgY29uZmlnLFxuICAgICAgYXV0aCxcbiAgICAgIHRydWVcbiAgICApXG4gICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHJlc3RXaGVyZSA9IHJlc3VsdC5yZXN0V2hlcmUgfHwgcmVzdFdoZXJlO1xuICAgICAgcmVzdE9wdGlvbnMgPSByZXN1bHQucmVzdE9wdGlvbnMgfHwgcmVzdE9wdGlvbnM7XG4gICAgICBjb25zdCBxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICByZXN0V2hlcmUsXG4gICAgICAgIHJlc3RPcHRpb25zLFxuICAgICAgICBjbGllbnRTREtcbiAgICAgICk7XG4gICAgICByZXR1cm4gcXVlcnkuZXhlY3V0ZSgpO1xuICAgIH0pO1xufTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBkb2Vzbid0IHJlc29sdmUgdG8gYW55IHVzZWZ1bCB2YWx1ZS5cbmZ1bmN0aW9uIGRlbChjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgb2JqZWN0SWQpIHtcbiAgaWYgKHR5cGVvZiBvYmplY3RJZCAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkIG9iamVjdElkJyk7XG4gIH1cblxuICBpZiAoY2xhc3NOYW1lID09PSAnX1VzZXInICYmIGF1dGguaXNVbmF1dGhlbnRpY2F0ZWQoKSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLlNFU1NJT05fTUlTU0lORyxcbiAgICAgICdJbnN1ZmZpY2llbnQgYXV0aCB0byBkZWxldGUgdXNlcidcbiAgICApO1xuICB9XG5cbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZGVsZXRlJywgY2xhc3NOYW1lLCBhdXRoKTtcblxuICBsZXQgaW5mbGF0ZWRPYmplY3Q7XG4gIGxldCBzY2hlbWFDb250cm9sbGVyO1xuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIGNvbnN0IGhhc1RyaWdnZXJzID0gY2hlY2tUcmlnZ2VycyhjbGFzc05hbWUsIGNvbmZpZywgW1xuICAgICAgICAnYmVmb3JlRGVsZXRlJyxcbiAgICAgICAgJ2FmdGVyRGVsZXRlJyxcbiAgICAgIF0pO1xuICAgICAgY29uc3QgaGFzTGl2ZVF1ZXJ5ID0gY2hlY2tMaXZlUXVlcnkoY2xhc3NOYW1lLCBjb25maWcpO1xuICAgICAgaWYgKGhhc1RyaWdnZXJzIHx8IGhhc0xpdmVRdWVyeSB8fCBjbGFzc05hbWUgPT0gJ19TZXNzaW9uJykge1xuICAgICAgICByZXR1cm4gbmV3IFJlc3RRdWVyeShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgeyBvYmplY3RJZCB9KVxuICAgICAgICAgIC5leGVjdXRlKHsgb3A6ICdkZWxldGUnIH0pXG4gICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLnJlc3VsdHMgJiYgcmVzcG9uc2UucmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgY29uc3QgZmlyc3RSZXN1bHQgPSByZXNwb25zZS5yZXN1bHRzWzBdO1xuICAgICAgICAgICAgICBmaXJzdFJlc3VsdC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgICAgICAgICAgIGlmIChjbGFzc05hbWUgPT09ICdfU2Vzc2lvbicgJiYgIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWF1dGgudXNlciB8fCBmaXJzdFJlc3VsdC51c2VyLm9iamVjdElkICE9PSBhdXRoLnVzZXIuaWQpIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICAgICAgICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdmFyIGNhY2hlQWRhcHRlciA9IGNvbmZpZy5jYWNoZUNvbnRyb2xsZXI7XG4gICAgICAgICAgICAgIGNhY2hlQWRhcHRlci51c2VyLmRlbChmaXJzdFJlc3VsdC5zZXNzaW9uVG9rZW4pO1xuICAgICAgICAgICAgICBpbmZsYXRlZE9iamVjdCA9IFBhcnNlLk9iamVjdC5mcm9tSlNPTihmaXJzdFJlc3VsdCk7XG4gICAgICAgICAgICAgIHJldHVybiB0cmlnZ2Vycy5tYXliZVJ1blRyaWdnZXIoXG4gICAgICAgICAgICAgICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlRGVsZXRlLFxuICAgICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgICAgaW5mbGF0ZWRPYmplY3QsXG4gICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgICBjb25maWdcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQgZm9yIGRlbGV0ZS4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICBpZiAoIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGF1dGguZ2V0VXNlclJvbGVzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiBjb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSgpKVxuICAgIC50aGVuKHMgPT4ge1xuICAgICAgc2NoZW1hQ29udHJvbGxlciA9IHM7XG4gICAgICBjb25zdCBvcHRpb25zID0ge307XG4gICAgICBpZiAoIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgb3B0aW9ucy5hY2wgPSBbJyonXTtcbiAgICAgICAgaWYgKGF1dGgudXNlcikge1xuICAgICAgICAgIG9wdGlvbnMuYWNsLnB1c2goYXV0aC51c2VyLmlkKTtcbiAgICAgICAgICBvcHRpb25zLmFjbCA9IG9wdGlvbnMuYWNsLmNvbmNhdChhdXRoLnVzZXJSb2xlcyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbmZpZy5kYXRhYmFzZS5kZXN0cm95KFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHtcbiAgICAgICAgICBvYmplY3RJZDogb2JqZWN0SWQsXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICAgIHNjaGVtYUNvbnRyb2xsZXJcbiAgICAgICk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICAvLyBOb3RpZnkgTGl2ZVF1ZXJ5IHNlcnZlciBpZiBwb3NzaWJsZVxuICAgICAgY29uc3QgcGVybXMgPSBzY2hlbWFDb250cm9sbGVyLmdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWUpO1xuICAgICAgY29uZmlnLmxpdmVRdWVyeUNvbnRyb2xsZXIub25BZnRlckRlbGV0ZShcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICBpbmZsYXRlZE9iamVjdCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgcGVybXNcbiAgICAgICk7XG4gICAgICByZXR1cm4gdHJpZ2dlcnMubWF5YmVSdW5UcmlnZ2VyKFxuICAgICAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckRlbGV0ZSxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgaW5mbGF0ZWRPYmplY3QsXG4gICAgICAgIG51bGwsXG4gICAgICAgIGNvbmZpZ1xuICAgICAgKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVTZXNzaW9uTWlzc2luZ0Vycm9yKGVycm9yLCBjbGFzc05hbWUsIGF1dGgpO1xuICAgIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSB7cmVzcG9uc2UsIHN0YXR1cywgbG9jYXRpb259IG9iamVjdC5cbmZ1bmN0aW9uIGNyZWF0ZShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgcmVzdE9iamVjdCwgY2xpZW50U0RLKSB7XG4gIGVuZm9yY2VSb2xlU2VjdXJpdHkoJ2NyZWF0ZScsIGNsYXNzTmFtZSwgYXV0aCk7XG4gIHZhciB3cml0ZSA9IG5ldyBSZXN0V3JpdGUoXG4gICAgY29uZmlnLFxuICAgIGF1dGgsXG4gICAgY2xhc3NOYW1lLFxuICAgIG51bGwsXG4gICAgcmVzdE9iamVjdCxcbiAgICBudWxsLFxuICAgIGNsaWVudFNES1xuICApO1xuICByZXR1cm4gd3JpdGUuZXhlY3V0ZSgpO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGNvbnRhaW5zIHRoZSBmaWVsZHMgb2YgdGhlIHVwZGF0ZSB0aGF0IHRoZVxuLy8gUkVTVCBBUEkgaXMgc3VwcG9zZWQgdG8gcmV0dXJuLlxuLy8gVXN1YWxseSwgdGhpcyBpcyBqdXN0IHVwZGF0ZWRBdC5cbmZ1bmN0aW9uIHVwZGF0ZShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgcmVzdFdoZXJlLCByZXN0T2JqZWN0LCBjbGllbnRTREspIHtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgndXBkYXRlJywgY2xhc3NOYW1lLCBhdXRoKTtcblxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICBjb25zdCBoYXNUcmlnZ2VycyA9IGNoZWNrVHJpZ2dlcnMoY2xhc3NOYW1lLCBjb25maWcsIFtcbiAgICAgICAgJ2JlZm9yZVNhdmUnLFxuICAgICAgICAnYWZ0ZXJTYXZlJyxcbiAgICAgIF0pO1xuICAgICAgY29uc3QgaGFzTGl2ZVF1ZXJ5ID0gY2hlY2tMaXZlUXVlcnkoY2xhc3NOYW1lLCBjb25maWcpO1xuICAgICAgaWYgKGhhc1RyaWdnZXJzIHx8IGhhc0xpdmVRdWVyeSkge1xuICAgICAgICAvLyBEbyBub3QgdXNlIGZpbmQsIGFzIGl0IHJ1bnMgdGhlIGJlZm9yZSBmaW5kc1xuICAgICAgICByZXR1cm4gbmV3IFJlc3RRdWVyeShcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgcmVzdFdoZXJlLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgZmFsc2VcbiAgICAgICAgKS5leGVjdXRlKHtcbiAgICAgICAgICBvcDogJ3VwZGF0ZScsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gICAgfSlcbiAgICAudGhlbigoeyByZXN1bHRzIH0pID0+IHtcbiAgICAgIHZhciBvcmlnaW5hbFJlc3RPYmplY3Q7XG4gICAgICBpZiAocmVzdWx0cyAmJiByZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICBvcmlnaW5hbFJlc3RPYmplY3QgPSByZXN1bHRzWzBdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBSZXN0V3JpdGUoXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICByZXN0V2hlcmUsXG4gICAgICAgIHJlc3RPYmplY3QsXG4gICAgICAgIG9yaWdpbmFsUmVzdE9iamVjdCxcbiAgICAgICAgY2xpZW50U0RLXG4gICAgICApLmV4ZWN1dGUoKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVTZXNzaW9uTWlzc2luZ0Vycm9yKGVycm9yLCBjbGFzc05hbWUsIGF1dGgpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTZXNzaW9uTWlzc2luZ0Vycm9yKGVycm9yLCBjbGFzc05hbWUsIGF1dGgpIHtcbiAgLy8gSWYgd2UncmUgdHJ5aW5nIHRvIHVwZGF0ZSBhIHVzZXIgd2l0aG91dCAvIHdpdGggYmFkIHNlc3Npb24gdG9rZW5cbiAgaWYgKFxuICAgIGNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJlxuICAgIGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQgJiZcbiAgICAhYXV0aC5pc01hc3RlclxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuU0VTU0lPTl9NSVNTSU5HLCAnSW5zdWZmaWNpZW50IGF1dGguJyk7XG4gIH1cbiAgdGhyb3cgZXJyb3I7XG59XG5cbmNvbnN0IGNsYXNzZXNXaXRoTWFzdGVyT25seUFjY2VzcyA9IFtcbiAgJ19Kb2JTdGF0dXMnLFxuICAnX1B1c2hTdGF0dXMnLFxuICAnX0hvb2tzJyxcbiAgJ19HbG9iYWxDb25maWcnLFxuICAnX0pvYlNjaGVkdWxlJyxcbl07XG4vLyBEaXNhbGxvd2luZyBhY2Nlc3MgdG8gdGhlIF9Sb2xlIGNvbGxlY3Rpb24gZXhjZXB0IGJ5IG1hc3RlciBrZXlcbmZ1bmN0aW9uIGVuZm9yY2VSb2xlU2VjdXJpdHkobWV0aG9kLCBjbGFzc05hbWUsIGF1dGgpIHtcbiAgaWYgKGNsYXNzTmFtZSA9PT0gJ19JbnN0YWxsYXRpb24nICYmICFhdXRoLmlzTWFzdGVyKSB7XG4gICAgaWYgKG1ldGhvZCA9PT0gJ2RlbGV0ZScgfHwgbWV0aG9kID09PSAnZmluZCcpIHtcbiAgICAgIGNvbnN0IGVycm9yID0gYENsaWVudHMgYXJlbid0IGFsbG93ZWQgdG8gcGVyZm9ybSB0aGUgJHttZXRob2R9IG9wZXJhdGlvbiBvbiB0aGUgaW5zdGFsbGF0aW9uIGNvbGxlY3Rpb24uYDtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCBlcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLy9hbGwgdm9sYXRpbGVDbGFzc2VzIGFyZSBtYXN0ZXJLZXkgb25seVxuICBpZiAoY2xhc3Nlc1dpdGhNYXN0ZXJPbmx5QWNjZXNzLmluZGV4T2YoY2xhc3NOYW1lKSA+PSAwICYmICFhdXRoLmlzTWFzdGVyKSB7XG4gICAgY29uc3QgZXJyb3IgPSBgQ2xpZW50cyBhcmVuJ3QgYWxsb3dlZCB0byBwZXJmb3JtIHRoZSAke21ldGhvZH0gb3BlcmF0aW9uIG9uIHRoZSAke2NsYXNzTmFtZX0gY29sbGVjdGlvbi5gO1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCBlcnJvcik7XG4gIH1cblxuICAvLyByZWFkT25seSBtYXN0ZXJLZXkgaXMgbm90IGFsbG93ZWRcbiAgaWYgKFxuICAgIGF1dGguaXNSZWFkT25seSAmJlxuICAgIChtZXRob2QgPT09ICdkZWxldGUnIHx8IG1ldGhvZCA9PT0gJ2NyZWF0ZScgfHwgbWV0aG9kID09PSAndXBkYXRlJylcbiAgKSB7XG4gICAgY29uc3QgZXJyb3IgPSBgcmVhZC1vbmx5IG1hc3RlcktleSBpc24ndCBhbGxvd2VkIHRvIHBlcmZvcm0gdGhlICR7bWV0aG9kfSBvcGVyYXRpb24uYDtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTiwgZXJyb3IpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBjcmVhdGUsXG4gIGRlbCxcbiAgZmluZCxcbiAgZ2V0LFxuICB1cGRhdGUsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/triggers.js b/lib/triggers.js new file mode 100644 index 0000000000..84a5c29a5d --- /dev/null +++ b/lib/triggers.js @@ -0,0 +1,611 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.addFunction = addFunction; +exports.addJob = addJob; +exports.addTrigger = addTrigger; +exports.addLiveQueryEventHandler = addLiveQueryEventHandler; +exports.removeFunction = removeFunction; +exports.removeTrigger = removeTrigger; +exports._unregisterAll = _unregisterAll; +exports.getTrigger = getTrigger; +exports.triggerExists = triggerExists; +exports.getFunction = getFunction; +exports.getFunctionNames = getFunctionNames; +exports.getJob = getJob; +exports.getJobs = getJobs; +exports.getValidator = getValidator; +exports.getRequestObject = getRequestObject; +exports.getRequestQueryObject = getRequestQueryObject; +exports.getResponseObject = getResponseObject; +exports.maybeRunAfterFindTrigger = maybeRunAfterFindTrigger; +exports.maybeRunQueryTrigger = maybeRunQueryTrigger; +exports.maybeRunTrigger = maybeRunTrigger; +exports.inflate = inflate; +exports.runLiveQueryEventHandlers = runLiveQueryEventHandlers; +exports.Types = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _logger = require("./logger"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// triggers.js +const Types = { + beforeLogin: 'beforeLogin', + afterLogout: 'afterLogout', + beforeSave: 'beforeSave', + afterSave: 'afterSave', + beforeDelete: 'beforeDelete', + afterDelete: 'afterDelete', + beforeFind: 'beforeFind', + afterFind: 'afterFind' +}; +exports.Types = Types; + +const baseStore = function () { + const Validators = {}; + const Functions = {}; + const Jobs = {}; + const LiveQuery = []; + const Triggers = Object.keys(Types).reduce(function (base, key) { + base[key] = {}; + return base; + }, {}); + return Object.freeze({ + Functions, + Jobs, + Validators, + Triggers, + LiveQuery + }); +}; + +function validateClassNameForTriggers(className, type) { + if (type == Types.beforeSave && className === '_PushStatus') { + // _PushStatus uses undocumented nested key increment ops + // allowing beforeSave would mess up the objects big time + // TODO: Allow proper documented way of using nested increment ops + throw 'Only afterSave is allowed on _PushStatus'; + } + + if (type === Types.beforeLogin && className !== '_User') { + // TODO: check if upstream code will handle `Error` instance rather + // than this anti-pattern of throwing strings + throw 'Only the _User class is allowed for the beforeLogin trigger'; + } + + if (type === Types.afterLogout && className !== '_Session') { + // TODO: check if upstream code will handle `Error` instance rather + // than this anti-pattern of throwing strings + throw 'Only the _Session class is allowed for the afterLogout trigger.'; + } + + if (className === '_Session' && type !== Types.afterLogout) { + // TODO: check if upstream code will handle `Error` instance rather + // than this anti-pattern of throwing strings + throw 'Only the afterLogout trigger is allowed for the _Session class.'; + } + + return className; +} + +const _triggerStore = {}; +const Category = { + Functions: 'Functions', + Validators: 'Validators', + Jobs: 'Jobs', + Triggers: 'Triggers' +}; + +function getStore(category, name, applicationId) { + const path = name.split('.'); + path.splice(-1); // remove last component + + applicationId = applicationId || _node.default.applicationId; + _triggerStore[applicationId] = _triggerStore[applicationId] || baseStore(); + let store = _triggerStore[applicationId][category]; + + for (const component of path) { + store = store[component]; + + if (!store) { + return undefined; + } + } + + return store; +} + +function add(category, name, handler, applicationId) { + const lastComponent = name.split('.').splice(-1); + const store = getStore(category, name, applicationId); + store[lastComponent] = handler; +} + +function remove(category, name, applicationId) { + const lastComponent = name.split('.').splice(-1); + const store = getStore(category, name, applicationId); + delete store[lastComponent]; +} + +function get(category, name, applicationId) { + const lastComponent = name.split('.').splice(-1); + const store = getStore(category, name, applicationId); + return store[lastComponent]; +} + +function addFunction(functionName, handler, validationHandler, applicationId) { + add(Category.Functions, functionName, handler, applicationId); + add(Category.Validators, functionName, validationHandler, applicationId); +} + +function addJob(jobName, handler, applicationId) { + add(Category.Jobs, jobName, handler, applicationId); +} + +function addTrigger(type, className, handler, applicationId) { + validateClassNameForTriggers(className, type); + add(Category.Triggers, `${type}.${className}`, handler, applicationId); +} + +function addLiveQueryEventHandler(handler, applicationId) { + applicationId = applicationId || _node.default.applicationId; + _triggerStore[applicationId] = _triggerStore[applicationId] || baseStore(); + + _triggerStore[applicationId].LiveQuery.push(handler); +} + +function removeFunction(functionName, applicationId) { + remove(Category.Functions, functionName, applicationId); +} + +function removeTrigger(type, className, applicationId) { + remove(Category.Triggers, `${type}.${className}`, applicationId); +} + +function _unregisterAll() { + Object.keys(_triggerStore).forEach(appId => delete _triggerStore[appId]); +} + +function getTrigger(className, triggerType, applicationId) { + if (!applicationId) { + throw 'Missing ApplicationID'; + } + + return get(Category.Triggers, `${triggerType}.${className}`, applicationId); +} + +function triggerExists(className, type, applicationId) { + return getTrigger(className, type, applicationId) != undefined; +} + +function getFunction(functionName, applicationId) { + return get(Category.Functions, functionName, applicationId); +} + +function getFunctionNames(applicationId) { + const store = _triggerStore[applicationId] && _triggerStore[applicationId][Category.Functions] || {}; + const functionNames = []; + + const extractFunctionNames = (namespace, store) => { + Object.keys(store).forEach(name => { + const value = store[name]; + + if (namespace) { + name = `${namespace}.${name}`; + } + + if (typeof value === 'function') { + functionNames.push(name); + } else { + extractFunctionNames(name, value); + } + }); + }; + + extractFunctionNames(null, store); + return functionNames; +} + +function getJob(jobName, applicationId) { + return get(Category.Jobs, jobName, applicationId); +} + +function getJobs(applicationId) { + var manager = _triggerStore[applicationId]; + + if (manager && manager.Jobs) { + return manager.Jobs; + } + + return undefined; +} + +function getValidator(functionName, applicationId) { + return get(Category.Validators, functionName, applicationId); +} + +function getRequestObject(triggerType, auth, parseObject, originalParseObject, config, context) { + const request = { + triggerName: triggerType, + object: parseObject, + master: false, + log: config.loggerController, + headers: config.headers, + ip: config.ip + }; + + if (originalParseObject) { + request.original = originalParseObject; + } + + if (triggerType === Types.beforeSave || triggerType === Types.afterSave) { + // Set a copy of the context on the request object. + request.context = Object.assign({}, context); + } + + if (!auth) { + return request; + } + + if (auth.isMaster) { + request['master'] = true; + } + + if (auth.user) { + request['user'] = auth.user; + } + + if (auth.installationId) { + request['installationId'] = auth.installationId; + } + + return request; +} + +function getRequestQueryObject(triggerType, auth, query, count, config, isGet) { + isGet = !!isGet; + var request = { + triggerName: triggerType, + query, + master: false, + count, + log: config.loggerController, + isGet, + headers: config.headers, + ip: config.ip + }; + + if (!auth) { + return request; + } + + if (auth.isMaster) { + request['master'] = true; + } + + if (auth.user) { + request['user'] = auth.user; + } + + if (auth.installationId) { + request['installationId'] = auth.installationId; + } + + return request; +} // Creates the response object, and uses the request object to pass data +// The API will call this with REST API formatted objects, this will +// transform them to Parse.Object instances expected by Cloud Code. +// Any changes made to the object in a beforeSave will be included. + + +function getResponseObject(request, resolve, reject) { + return { + success: function (response) { + if (request.triggerName === Types.afterFind) { + if (!response) { + response = request.objects; + } + + response = response.map(object => { + return object.toJSON(); + }); + return resolve(response); + } // Use the JSON response + + + if (response && typeof response === 'object' && !request.object.equals(response) && request.triggerName === Types.beforeSave) { + return resolve(response); + } + + if (response && typeof response === 'object' && request.triggerName === Types.afterSave) { + return resolve(response); + } + + if (request.triggerName === Types.afterSave) { + return resolve(); + } + + response = {}; + + if (request.triggerName === Types.beforeSave) { + response['object'] = request.object._getSaveJSON(); + } + + return resolve(response); + }, + error: function (error) { + if (error instanceof _node.default.Error) { + reject(error); + } else if (error instanceof Error) { + reject(new _node.default.Error(_node.default.Error.SCRIPT_FAILED, error.message)); + } else { + reject(new _node.default.Error(_node.default.Error.SCRIPT_FAILED, error)); + } + } + }; +} + +function userIdForLog(auth) { + return auth && auth.user ? auth.user.id : undefined; +} + +function logTriggerAfterHook(triggerType, className, input, auth) { + const cleanInput = _logger.logger.truncateLogMessage(JSON.stringify(input)); + + _logger.logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}`, { + className, + triggerType, + user: userIdForLog(auth) + }); +} + +function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth) { + const cleanInput = _logger.logger.truncateLogMessage(JSON.stringify(input)); + + const cleanResult = _logger.logger.truncateLogMessage(JSON.stringify(result)); + + _logger.logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Result: ${cleanResult}`, { + className, + triggerType, + user: userIdForLog(auth) + }); +} + +function logTriggerErrorBeforeHook(triggerType, className, input, auth, error) { + const cleanInput = _logger.logger.truncateLogMessage(JSON.stringify(input)); + + _logger.logger.error(`${triggerType} failed for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Error: ${JSON.stringify(error)}`, { + className, + triggerType, + error, + user: userIdForLog(auth) + }); +} + +function maybeRunAfterFindTrigger(triggerType, auth, className, objects, config) { + return new Promise((resolve, reject) => { + const trigger = getTrigger(className, triggerType, config.applicationId); + + if (!trigger) { + return resolve(); + } + + const request = getRequestObject(triggerType, auth, null, null, config); + const { + success, + error + } = getResponseObject(request, object => { + resolve(object); + }, error => { + reject(error); + }); + logTriggerSuccessBeforeHook(triggerType, className, 'AfterFind', JSON.stringify(objects), auth); + request.objects = objects.map(object => { + //setting the class name to transform into parse object + object.className = className; + return _node.default.Object.fromJSON(object); + }); + return Promise.resolve().then(() => { + const response = trigger(request); + + if (response && typeof response.then === 'function') { + return response.then(results => { + if (!results) { + throw new _node.default.Error(_node.default.Error.SCRIPT_FAILED, 'AfterFind expect results to be returned in the promise'); + } + + return results; + }); + } + + return response; + }).then(success, error); + }).then(results => { + logTriggerAfterHook(triggerType, className, JSON.stringify(results), auth); + return results; + }); +} + +function maybeRunQueryTrigger(triggerType, className, restWhere, restOptions, config, auth, isGet) { + const trigger = getTrigger(className, triggerType, config.applicationId); + + if (!trigger) { + return Promise.resolve({ + restWhere, + restOptions + }); + } + + const json = Object.assign({}, restOptions); + json.where = restWhere; + const parseQuery = new _node.default.Query(className); + parseQuery.withJSON(json); + let count = false; + + if (restOptions) { + count = !!restOptions.count; + } + + const requestObject = getRequestQueryObject(triggerType, auth, parseQuery, count, config, isGet); + return Promise.resolve().then(() => { + return trigger(requestObject); + }).then(result => { + let queryResult = parseQuery; + + if (result && result instanceof _node.default.Query) { + queryResult = result; + } + + const jsonQuery = queryResult.toJSON(); + + if (jsonQuery.where) { + restWhere = jsonQuery.where; + } + + if (jsonQuery.limit) { + restOptions = restOptions || {}; + restOptions.limit = jsonQuery.limit; + } + + if (jsonQuery.skip) { + restOptions = restOptions || {}; + restOptions.skip = jsonQuery.skip; + } + + if (jsonQuery.include) { + restOptions = restOptions || {}; + restOptions.include = jsonQuery.include; + } + + if (jsonQuery.excludeKeys) { + restOptions = restOptions || {}; + restOptions.excludeKeys = jsonQuery.excludeKeys; + } + + if (jsonQuery.keys) { + restOptions = restOptions || {}; + restOptions.keys = jsonQuery.keys; + } + + if (jsonQuery.order) { + restOptions = restOptions || {}; + restOptions.order = jsonQuery.order; + } + + if (requestObject.readPreference) { + restOptions = restOptions || {}; + restOptions.readPreference = requestObject.readPreference; + } + + if (requestObject.includeReadPreference) { + restOptions = restOptions || {}; + restOptions.includeReadPreference = requestObject.includeReadPreference; + } + + if (requestObject.subqueryReadPreference) { + restOptions = restOptions || {}; + restOptions.subqueryReadPreference = requestObject.subqueryReadPreference; + } + + return { + restWhere, + restOptions + }; + }, err => { + if (typeof err === 'string') { + throw new _node.default.Error(1, err); + } else { + throw err; + } + }); +} // To be used as part of the promise chain when saving/deleting an object +// Will resolve successfully if no trigger is configured +// Resolves to an object, empty or containing an object key. A beforeSave +// trigger will set the object key to the rest format object to save. +// originalParseObject is optional, we only need that for before/afterSave functions + + +function maybeRunTrigger(triggerType, auth, parseObject, originalParseObject, config, context) { + if (!parseObject) { + return Promise.resolve({}); + } + + return new Promise(function (resolve, reject) { + var trigger = getTrigger(parseObject.className, triggerType, config.applicationId); + if (!trigger) return resolve(); + var request = getRequestObject(triggerType, auth, parseObject, originalParseObject, config, context); + var { + success, + error + } = getResponseObject(request, object => { + logTriggerSuccessBeforeHook(triggerType, parseObject.className, parseObject.toJSON(), object, auth); + + if (triggerType === Types.beforeSave || triggerType === Types.afterSave) { + Object.assign(context, request.context); + } + + resolve(object); + }, error => { + logTriggerErrorBeforeHook(triggerType, parseObject.className, parseObject.toJSON(), auth, error); + reject(error); + }); // AfterSave and afterDelete triggers can return a promise, which if they + // do, needs to be resolved before this promise is resolved, + // so trigger execution is synced with RestWrite.execute() call. + // If triggers do not return a promise, they can run async code parallel + // to the RestWrite.execute() call. + + return Promise.resolve().then(() => { + const promise = trigger(request); + + if (triggerType === Types.afterSave || triggerType === Types.afterDelete) { + logTriggerAfterHook(triggerType, parseObject.className, parseObject.toJSON(), auth); + } // beforeSave is expected to return null (nothing) + + + if (triggerType === Types.beforeSave) { + if (promise && typeof promise.then === 'function') { + return promise.then(response => { + // response.object may come from express routing before hook + if (response && response.object) { + return response; + } + + return null; + }); + } + + return null; + } + + return promise; + }).then(success, error); + }); +} // Converts a REST-format object to a Parse.Object +// data is either className or an object + + +function inflate(data, restObject) { + var copy = typeof data == 'object' ? data : { + className: data + }; + + for (var key in restObject) { + copy[key] = restObject[key]; + } + + return _node.default.Object.fromJSON(copy); +} + +function runLiveQueryEventHandlers(data, applicationId = _node.default.applicationId) { + if (!_triggerStore || !_triggerStore[applicationId] || !_triggerStore[applicationId].LiveQuery) { + return; + } + + _triggerStore[applicationId].LiveQuery.forEach(handler => handler(data)); +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy90cmlnZ2Vycy5qcyJdLCJuYW1lcyI6WyJUeXBlcyIsImJlZm9yZUxvZ2luIiwiYWZ0ZXJMb2dvdXQiLCJiZWZvcmVTYXZlIiwiYWZ0ZXJTYXZlIiwiYmVmb3JlRGVsZXRlIiwiYWZ0ZXJEZWxldGUiLCJiZWZvcmVGaW5kIiwiYWZ0ZXJGaW5kIiwiYmFzZVN0b3JlIiwiVmFsaWRhdG9ycyIsIkZ1bmN0aW9ucyIsIkpvYnMiLCJMaXZlUXVlcnkiLCJUcmlnZ2VycyIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJiYXNlIiwia2V5IiwiZnJlZXplIiwidmFsaWRhdGVDbGFzc05hbWVGb3JUcmlnZ2VycyIsImNsYXNzTmFtZSIsInR5cGUiLCJfdHJpZ2dlclN0b3JlIiwiQ2F0ZWdvcnkiLCJnZXRTdG9yZSIsImNhdGVnb3J5IiwibmFtZSIsImFwcGxpY2F0aW9uSWQiLCJwYXRoIiwic3BsaXQiLCJzcGxpY2UiLCJQYXJzZSIsInN0b3JlIiwiY29tcG9uZW50IiwidW5kZWZpbmVkIiwiYWRkIiwiaGFuZGxlciIsImxhc3RDb21wb25lbnQiLCJyZW1vdmUiLCJnZXQiLCJhZGRGdW5jdGlvbiIsImZ1bmN0aW9uTmFtZSIsInZhbGlkYXRpb25IYW5kbGVyIiwiYWRkSm9iIiwiam9iTmFtZSIsImFkZFRyaWdnZXIiLCJhZGRMaXZlUXVlcnlFdmVudEhhbmRsZXIiLCJwdXNoIiwicmVtb3ZlRnVuY3Rpb24iLCJyZW1vdmVUcmlnZ2VyIiwiX3VucmVnaXN0ZXJBbGwiLCJmb3JFYWNoIiwiYXBwSWQiLCJnZXRUcmlnZ2VyIiwidHJpZ2dlclR5cGUiLCJ0cmlnZ2VyRXhpc3RzIiwiZ2V0RnVuY3Rpb24iLCJnZXRGdW5jdGlvbk5hbWVzIiwiZnVuY3Rpb25OYW1lcyIsImV4dHJhY3RGdW5jdGlvbk5hbWVzIiwibmFtZXNwYWNlIiwidmFsdWUiLCJnZXRKb2IiLCJnZXRKb2JzIiwibWFuYWdlciIsImdldFZhbGlkYXRvciIsImdldFJlcXVlc3RPYmplY3QiLCJhdXRoIiwicGFyc2VPYmplY3QiLCJvcmlnaW5hbFBhcnNlT2JqZWN0IiwiY29uZmlnIiwiY29udGV4dCIsInJlcXVlc3QiLCJ0cmlnZ2VyTmFtZSIsIm9iamVjdCIsIm1hc3RlciIsImxvZyIsImxvZ2dlckNvbnRyb2xsZXIiLCJoZWFkZXJzIiwiaXAiLCJvcmlnaW5hbCIsImFzc2lnbiIsImlzTWFzdGVyIiwidXNlciIsImluc3RhbGxhdGlvbklkIiwiZ2V0UmVxdWVzdFF1ZXJ5T2JqZWN0IiwicXVlcnkiLCJjb3VudCIsImlzR2V0IiwiZ2V0UmVzcG9uc2VPYmplY3QiLCJyZXNvbHZlIiwicmVqZWN0Iiwic3VjY2VzcyIsInJlc3BvbnNlIiwib2JqZWN0cyIsIm1hcCIsInRvSlNPTiIsImVxdWFscyIsIl9nZXRTYXZlSlNPTiIsImVycm9yIiwiRXJyb3IiLCJTQ1JJUFRfRkFJTEVEIiwibWVzc2FnZSIsInVzZXJJZEZvckxvZyIsImlkIiwibG9nVHJpZ2dlckFmdGVySG9vayIsImlucHV0IiwiY2xlYW5JbnB1dCIsImxvZ2dlciIsInRydW5jYXRlTG9nTWVzc2FnZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJpbmZvIiwibG9nVHJpZ2dlclN1Y2Nlc3NCZWZvcmVIb29rIiwicmVzdWx0IiwiY2xlYW5SZXN1bHQiLCJsb2dUcmlnZ2VyRXJyb3JCZWZvcmVIb29rIiwibWF5YmVSdW5BZnRlckZpbmRUcmlnZ2VyIiwiUHJvbWlzZSIsInRyaWdnZXIiLCJmcm9tSlNPTiIsInRoZW4iLCJyZXN1bHRzIiwibWF5YmVSdW5RdWVyeVRyaWdnZXIiLCJyZXN0V2hlcmUiLCJyZXN0T3B0aW9ucyIsImpzb24iLCJ3aGVyZSIsInBhcnNlUXVlcnkiLCJRdWVyeSIsIndpdGhKU09OIiwicmVxdWVzdE9iamVjdCIsInF1ZXJ5UmVzdWx0IiwianNvblF1ZXJ5IiwibGltaXQiLCJza2lwIiwiaW5jbHVkZSIsImV4Y2x1ZGVLZXlzIiwib3JkZXIiLCJyZWFkUHJlZmVyZW5jZSIsImluY2x1ZGVSZWFkUHJlZmVyZW5jZSIsInN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UiLCJlcnIiLCJtYXliZVJ1blRyaWdnZXIiLCJwcm9taXNlIiwiaW5mbGF0ZSIsImRhdGEiLCJyZXN0T2JqZWN0IiwiY29weSIsInJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0E7O0FBQ0E7Ozs7QUFGQTtBQUlPLE1BQU1BLEtBQUssR0FBRztBQUNuQkMsRUFBQUEsV0FBVyxFQUFFLGFBRE07QUFFbkJDLEVBQUFBLFdBQVcsRUFBRSxhQUZNO0FBR25CQyxFQUFBQSxVQUFVLEVBQUUsWUFITztBQUluQkMsRUFBQUEsU0FBUyxFQUFFLFdBSlE7QUFLbkJDLEVBQUFBLFlBQVksRUFBRSxjQUxLO0FBTW5CQyxFQUFBQSxXQUFXLEVBQUUsYUFOTTtBQU9uQkMsRUFBQUEsVUFBVSxFQUFFLFlBUE87QUFRbkJDLEVBQUFBLFNBQVMsRUFBRTtBQVJRLENBQWQ7OztBQVdQLE1BQU1DLFNBQVMsR0FBRyxZQUFXO0FBQzNCLFFBQU1DLFVBQVUsR0FBRyxFQUFuQjtBQUNBLFFBQU1DLFNBQVMsR0FBRyxFQUFsQjtBQUNBLFFBQU1DLElBQUksR0FBRyxFQUFiO0FBQ0EsUUFBTUMsU0FBUyxHQUFHLEVBQWxCO0FBQ0EsUUFBTUMsUUFBUSxHQUFHQyxNQUFNLENBQUNDLElBQVAsQ0FBWWhCLEtBQVosRUFBbUJpQixNQUFuQixDQUEwQixVQUFTQyxJQUFULEVBQWVDLEdBQWYsRUFBb0I7QUFDN0RELElBQUFBLElBQUksQ0FBQ0MsR0FBRCxDQUFKLEdBQVksRUFBWjtBQUNBLFdBQU9ELElBQVA7QUFDRCxHQUhnQixFQUdkLEVBSGMsQ0FBakI7QUFLQSxTQUFPSCxNQUFNLENBQUNLLE1BQVAsQ0FBYztBQUNuQlQsSUFBQUEsU0FEbUI7QUFFbkJDLElBQUFBLElBRm1CO0FBR25CRixJQUFBQSxVQUhtQjtBQUluQkksSUFBQUEsUUFKbUI7QUFLbkJELElBQUFBO0FBTG1CLEdBQWQsQ0FBUDtBQU9ELENBakJE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SUFBakIsRUFBdUJDLFVBQXZCLEVBQW1DO0FBQ3hDLE1BQUlDLElBQUksR0FBRyxPQUFPRixJQUFQLElBQWUsUUFBZixHQUEwQkEsSUFBMUIsR0FBaUM7QUFBRTlILElBQUFBLFNBQVMsRUFBRThIO0FBQWIsR0FBNUM7O0FBQ0EsT0FBSyxJQUFJakksR0FBVCxJQUFnQmtJLFVBQWhCLEVBQTRCO0FBQzFCQyxJQUFBQSxJQUFJLENBQUNuSSxHQUFELENBQUosR0FBWWtJLFVBQVUsQ0FBQ2xJLEdBQUQsQ0FBdEI7QUFDRDs7QUFDRCxTQUFPYyxjQUFNbEIsTUFBTixDQUFhMkcsUUFBYixDQUFzQjRCLElBQXRCLENBQVA7QUFDRDs7QUFFTSxTQUFTQyx5QkFBVCxDQUNMSCxJQURLLEVBRUx2SCxhQUFhLEdBQUdJLGNBQU1KLGFBRmpCLEVBR0w7QUFDQSxNQUNFLENBQUNMLGFBQUQsSUFDQSxDQUFDQSxhQUFhLENBQUNLLGFBQUQsQ0FEZCxJQUVBLENBQUNMLGFBQWEsQ0FBQ0ssYUFBRCxDQUFiLENBQTZCaEIsU0FIaEMsRUFJRTtBQUNBO0FBQ0Q7O0FBQ0RXLEVBQUFBLGFBQWEsQ0FBQ0ssYUFBRCxDQUFiLENBQTZCaEIsU0FBN0IsQ0FBdUN3QyxPQUF2QyxDQUErQ2YsT0FBTyxJQUFJQSxPQUFPLENBQUM4RyxJQUFELENBQWpFO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0cmlnZ2Vycy5qc1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuXG5leHBvcnQgY29uc3QgVHlwZXMgPSB7XG4gIGJlZm9yZUxvZ2luOiAnYmVmb3JlTG9naW4nLFxuICBhZnRlckxvZ291dDogJ2FmdGVyTG9nb3V0JyxcbiAgYmVmb3JlU2F2ZTogJ2JlZm9yZVNhdmUnLFxuICBhZnRlclNhdmU6ICdhZnRlclNhdmUnLFxuICBiZWZvcmVEZWxldGU6ICdiZWZvcmVEZWxldGUnLFxuICBhZnRlckRlbGV0ZTogJ2FmdGVyRGVsZXRlJyxcbiAgYmVmb3JlRmluZDogJ2JlZm9yZUZpbmQnLFxuICBhZnRlckZpbmQ6ICdhZnRlckZpbmQnLFxufTtcblxuY29uc3QgYmFzZVN0b3JlID0gZnVuY3Rpb24oKSB7XG4gIGNvbnN0IFZhbGlkYXRvcnMgPSB7fTtcbiAgY29uc3QgRnVuY3Rpb25zID0ge307XG4gIGNvbnN0IEpvYnMgPSB7fTtcbiAgY29uc3QgTGl2ZVF1ZXJ5ID0gW107XG4gIGNvbnN0IFRyaWdnZXJzID0gT2JqZWN0LmtleXMoVHlwZXMpLnJlZHVjZShmdW5jdGlvbihiYXNlLCBrZXkpIHtcbiAgICBiYXNlW2tleV0gPSB7fTtcbiAgICByZXR1cm4gYmFzZTtcbiAgfSwge30pO1xuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKHtcbiAgICBGdW5jdGlvbnMsXG4gICAgSm9icyxcbiAgICBWYWxpZGF0b3JzLFxuICAgIFRyaWdnZXJzLFxuICAgIExpdmVRdWVyeSxcbiAgfSk7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZUNsYXNzTmFtZUZvclRyaWdnZXJzKGNsYXNzTmFtZSwgdHlwZSkge1xuICBpZiAodHlwZSA9PSBUeXBlcy5iZWZvcmVTYXZlICYmIGNsYXNzTmFtZSA9PT0gJ19QdXNoU3RhdHVzJykge1xuICAgIC8vIF9QdXNoU3RhdHVzIHVzZXMgdW5kb2N1bWVudGVkIG5lc3RlZCBrZXkgaW5jcmVtZW50IG9wc1xuICAgIC8vIGFsbG93aW5nIGJlZm9yZVNhdmUgd291bGQgbWVzcyB1cCB0aGUgb2JqZWN0cyBiaWcgdGltZVxuICAgIC8vIFRPRE86IEFsbG93IHByb3BlciBkb2N1bWVudGVkIHdheSBvZiB1c2luZyBuZXN0ZWQgaW5jcmVtZW50IG9wc1xuICAgIHRocm93ICdPbmx5IGFmdGVyU2F2ZSBpcyBhbGxvd2VkIG9uIF9QdXNoU3RhdHVzJztcbiAgfVxuICBpZiAodHlwZSA9PT0gVHlwZXMuYmVmb3JlTG9naW4gJiYgY2xhc3NOYW1lICE9PSAnX1VzZXInKSB7XG4gICAgLy8gVE9ETzogY2hlY2sgaWYgdXBzdHJlYW0gY29kZSB3aWxsIGhhbmRsZSBgRXJyb3JgIGluc3RhbmNlIHJhdGhlclxuICAgIC8vIHRoYW4gdGhpcyBhbnRpLXBhdHRlcm4gb2YgdGhyb3dpbmcgc3RyaW5nc1xuICAgIHRocm93ICdPbmx5IHRoZSBfVXNlciBjbGFzcyBpcyBhbGxvd2VkIGZvciB0aGUgYmVmb3JlTG9naW4gdHJpZ2dlcic7XG4gIH1cbiAgaWYgKHR5cGUgPT09IFR5cGVzLmFmdGVyTG9nb3V0ICYmIGNsYXNzTmFtZSAhPT0gJ19TZXNzaW9uJykge1xuICAgIC8vIFRPRE86IGNoZWNrIGlmIHVwc3RyZWFtIGNvZGUgd2lsbCBoYW5kbGUgYEVycm9yYCBpbnN0YW5jZSByYXRoZXJcbiAgICAvLyB0aGFuIHRoaXMgYW50aS1wYXR0ZXJuIG9mIHRocm93aW5nIHN0cmluZ3NcbiAgICB0aHJvdyAnT25seSB0aGUgX1Nlc3Npb24gY2xhc3MgaXMgYWxsb3dlZCBmb3IgdGhlIGFmdGVyTG9nb3V0IHRyaWdnZXIuJztcbiAgfVxuICBpZiAoY2xhc3NOYW1lID09PSAnX1Nlc3Npb24nICYmIHR5cGUgIT09IFR5cGVzLmFmdGVyTG9nb3V0KSB7XG4gICAgLy8gVE9ETzogY2hlY2sgaWYgdXBzdHJlYW0gY29kZSB3aWxsIGhhbmRsZSBgRXJyb3JgIGluc3RhbmNlIHJhdGhlclxuICAgIC8vIHRoYW4gdGhpcyBhbnRpLXBhdHRlcm4gb2YgdGhyb3dpbmcgc3RyaW5nc1xuICAgIHRocm93ICdPbmx5IHRoZSBhZnRlckxvZ291dCB0cmlnZ2VyIGlzIGFsbG93ZWQgZm9yIHRoZSBfU2Vzc2lvbiBjbGFzcy4nO1xuICB9XG4gIHJldHVybiBjbGFzc05hbWU7XG59XG5cbmNvbnN0IF90cmlnZ2VyU3RvcmUgPSB7fTtcblxuY29uc3QgQ2F0ZWdvcnkgPSB7XG4gIEZ1bmN0aW9uczogJ0Z1bmN0aW9ucycsXG4gIFZhbGlkYXRvcnM6ICdWYWxpZGF0b3JzJyxcbiAgSm9iczogJ0pvYnMnLFxuICBUcmlnZ2VyczogJ1RyaWdnZXJzJyxcbn07XG5cbmZ1bmN0aW9uIGdldFN0b3JlKGNhdGVnb3J5LCBuYW1lLCBhcHBsaWNhdGlvbklkKSB7XG4gIGNvbnN0IHBhdGggPSBuYW1lLnNwbGl0KCcuJyk7XG4gIHBhdGguc3BsaWNlKC0xKTsgLy8gcmVtb3ZlIGxhc3QgY29tcG9uZW50XG4gIGFwcGxpY2F0aW9uSWQgPSBhcHBsaWNhdGlvbklkIHx8IFBhcnNlLmFwcGxpY2F0aW9uSWQ7XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0gPSBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdIHx8IGJhc2VTdG9yZSgpO1xuICBsZXQgc3RvcmUgPSBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdW2NhdGVnb3J5XTtcbiAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aCkge1xuICAgIHN0b3JlID0gc3RvcmVbY29tcG9uZW50XTtcbiAgICBpZiAoIXN0b3JlKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RvcmU7XG59XG5cbmZ1bmN0aW9uIGFkZChjYXRlZ29yeSwgbmFtZSwgaGFuZGxlciwgYXBwbGljYXRpb25JZCkge1xuICBjb25zdCBsYXN0Q29tcG9uZW50ID0gbmFtZS5zcGxpdCgnLicpLnNwbGljZSgtMSk7XG4gIGNvbnN0IHN0b3JlID0gZ2V0U3RvcmUoY2F0ZWdvcnksIG5hbWUsIGFwcGxpY2F0aW9uSWQpO1xuICBzdG9yZVtsYXN0Q29tcG9uZW50XSA9IGhhbmRsZXI7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZShjYXRlZ29yeSwgbmFtZSwgYXBwbGljYXRpb25JZCkge1xuICBjb25zdCBsYXN0Q29tcG9uZW50ID0gbmFtZS5zcGxpdCgnLicpLnNwbGljZSgtMSk7XG4gIGNvbnN0IHN0b3JlID0gZ2V0U3RvcmUoY2F0ZWdvcnksIG5hbWUsIGFwcGxpY2F0aW9uSWQpO1xuICBkZWxldGUgc3RvcmVbbGFzdENvbXBvbmVudF07XG59XG5cbmZ1bmN0aW9uIGdldChjYXRlZ29yeSwgbmFtZSwgYXBwbGljYXRpb25JZCkge1xuICBjb25zdCBsYXN0Q29tcG9uZW50ID0gbmFtZS5zcGxpdCgnLicpLnNwbGljZSgtMSk7XG4gIGNvbnN0IHN0b3JlID0gZ2V0U3RvcmUoY2F0ZWdvcnksIG5hbWUsIGFwcGxpY2F0aW9uSWQpO1xuICByZXR1cm4gc3RvcmVbbGFzdENvbXBvbmVudF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRGdW5jdGlvbihcbiAgZnVuY3Rpb25OYW1lLFxuICBoYW5kbGVyLFxuICB2YWxpZGF0aW9uSGFuZGxlcixcbiAgYXBwbGljYXRpb25JZFxuKSB7XG4gIGFkZChDYXRlZ29yeS5GdW5jdGlvbnMsIGZ1bmN0aW9uTmFtZSwgaGFuZGxlciwgYXBwbGljYXRpb25JZCk7XG4gIGFkZChDYXRlZ29yeS5WYWxpZGF0b3JzLCBmdW5jdGlvbk5hbWUsIHZhbGlkYXRpb25IYW5kbGVyLCBhcHBsaWNhdGlvbklkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZEpvYihqb2JOYW1lLCBoYW5kbGVyLCBhcHBsaWNhdGlvbklkKSB7XG4gIGFkZChDYXRlZ29yeS5Kb2JzLCBqb2JOYW1lLCBoYW5kbGVyLCBhcHBsaWNhdGlvbklkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZFRyaWdnZXIodHlwZSwgY2xhc3NOYW1lLCBoYW5kbGVyLCBhcHBsaWNhdGlvbklkKSB7XG4gIHZhbGlkYXRlQ2xhc3NOYW1lRm9yVHJpZ2dlcnMoY2xhc3NOYW1lLCB0eXBlKTtcbiAgYWRkKENhdGVnb3J5LlRyaWdnZXJzLCBgJHt0eXBlfS4ke2NsYXNzTmFtZX1gLCBoYW5kbGVyLCBhcHBsaWNhdGlvbklkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZExpdmVRdWVyeUV2ZW50SGFuZGxlcihoYW5kbGVyLCBhcHBsaWNhdGlvbklkKSB7XG4gIGFwcGxpY2F0aW9uSWQgPSBhcHBsaWNhdGlvbklkIHx8IFBhcnNlLmFwcGxpY2F0aW9uSWQ7XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0gPSBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdIHx8IGJhc2VTdG9yZSgpO1xuICBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdLkxpdmVRdWVyeS5wdXNoKGhhbmRsZXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlRnVuY3Rpb24oZnVuY3Rpb25OYW1lLCBhcHBsaWNhdGlvbklkKSB7XG4gIHJlbW92ZShDYXRlZ29yeS5GdW5jdGlvbnMsIGZ1bmN0aW9uTmFtZSwgYXBwbGljYXRpb25JZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVUcmlnZ2VyKHR5cGUsIGNsYXNzTmFtZSwgYXBwbGljYXRpb25JZCkge1xuICByZW1vdmUoQ2F0ZWdvcnkuVHJpZ2dlcnMsIGAke3R5cGV9LiR7Y2xhc3NOYW1lfWAsIGFwcGxpY2F0aW9uSWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3VucmVnaXN0ZXJBbGwoKSB7XG4gIE9iamVjdC5rZXlzKF90cmlnZ2VyU3RvcmUpLmZvckVhY2goYXBwSWQgPT4gZGVsZXRlIF90cmlnZ2VyU3RvcmVbYXBwSWRdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRyaWdnZXIoY2xhc3NOYW1lLCB0cmlnZ2VyVHlwZSwgYXBwbGljYXRpb25JZCkge1xuICBpZiAoIWFwcGxpY2F0aW9uSWQpIHtcbiAgICB0aHJvdyAnTWlzc2luZyBBcHBsaWNhdGlvbklEJztcbiAgfVxuICByZXR1cm4gZ2V0KENhdGVnb3J5LlRyaWdnZXJzLCBgJHt0cmlnZ2VyVHlwZX0uJHtjbGFzc05hbWV9YCwgYXBwbGljYXRpb25JZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmlnZ2VyRXhpc3RzKFxuICBjbGFzc05hbWU6IHN0cmluZyxcbiAgdHlwZTogc3RyaW5nLFxuICBhcHBsaWNhdGlvbklkOiBzdHJpbmdcbik6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0VHJpZ2dlcihjbGFzc05hbWUsIHR5cGUsIGFwcGxpY2F0aW9uSWQpICE9IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgYXBwbGljYXRpb25JZCkge1xuICByZXR1cm4gZ2V0KENhdGVnb3J5LkZ1bmN0aW9ucywgZnVuY3Rpb25OYW1lLCBhcHBsaWNhdGlvbklkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZ1bmN0aW9uTmFtZXMoYXBwbGljYXRpb25JZCkge1xuICBjb25zdCBzdG9yZSA9XG4gICAgKF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0gJiZcbiAgICAgIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF1bQ2F0ZWdvcnkuRnVuY3Rpb25zXSkgfHxcbiAgICB7fTtcbiAgY29uc3QgZnVuY3Rpb25OYW1lcyA9IFtdO1xuICBjb25zdCBleHRyYWN0RnVuY3Rpb25OYW1lcyA9IChuYW1lc3BhY2UsIHN0b3JlKSA9PiB7XG4gICAgT2JqZWN0LmtleXMoc3RvcmUpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHN0b3JlW25hbWVdO1xuICAgICAgaWYgKG5hbWVzcGFjZSkge1xuICAgICAgICBuYW1lID0gYCR7bmFtZXNwYWNlfS4ke25hbWV9YDtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgZnVuY3Rpb25OYW1lcy5wdXNoKG5hbWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXh0cmFjdEZ1bmN0aW9uTmFtZXMobmFtZSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuICBleHRyYWN0RnVuY3Rpb25OYW1lcyhudWxsLCBzdG9yZSk7XG4gIHJldHVybiBmdW5jdGlvbk5hbWVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Sm9iKGpvYk5hbWUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgcmV0dXJuIGdldChDYXRlZ29yeS5Kb2JzLCBqb2JOYW1lLCBhcHBsaWNhdGlvbklkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEpvYnMoYXBwbGljYXRpb25JZCkge1xuICB2YXIgbWFuYWdlciA9IF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF07XG4gIGlmIChtYW5hZ2VyICYmIG1hbmFnZXIuSm9icykge1xuICAgIHJldHVybiBtYW5hZ2VyLkpvYnM7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFZhbGlkYXRvcihmdW5jdGlvbk5hbWUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgcmV0dXJuIGdldChDYXRlZ29yeS5WYWxpZGF0b3JzLCBmdW5jdGlvbk5hbWUsIGFwcGxpY2F0aW9uSWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVxdWVzdE9iamVjdChcbiAgdHJpZ2dlclR5cGUsXG4gIGF1dGgsXG4gIHBhcnNlT2JqZWN0LFxuICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICBjb25maWcsXG4gIGNvbnRleHRcbikge1xuICBjb25zdCByZXF1ZXN0ID0ge1xuICAgIHRyaWdnZXJOYW1lOiB0cmlnZ2VyVHlwZSxcbiAgICBvYmplY3Q6IHBhcnNlT2JqZWN0LFxuICAgIG1hc3RlcjogZmFsc2UsXG4gICAgbG9nOiBjb25maWcubG9nZ2VyQ29udHJvbGxlcixcbiAgICBoZWFkZXJzOiBjb25maWcuaGVhZGVycyxcbiAgICBpcDogY29uZmlnLmlwLFxuICB9O1xuXG4gIGlmIChvcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgcmVxdWVzdC5vcmlnaW5hbCA9IG9yaWdpbmFsUGFyc2VPYmplY3Q7XG4gIH1cblxuICBpZiAodHJpZ2dlclR5cGUgPT09IFR5cGVzLmJlZm9yZVNhdmUgfHwgdHJpZ2dlclR5cGUgPT09IFR5cGVzLmFmdGVyU2F2ZSkge1xuICAgIC8vIFNldCBhIGNvcHkgb2YgdGhlIGNvbnRleHQgb24gdGhlIHJlcXVlc3Qgb2JqZWN0LlxuICAgIHJlcXVlc3QuY29udGV4dCA9IE9iamVjdC5hc3NpZ24oe30sIGNvbnRleHQpO1xuICB9XG5cbiAgaWYgKCFhdXRoKSB7XG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cbiAgaWYgKGF1dGguaXNNYXN0ZXIpIHtcbiAgICByZXF1ZXN0WydtYXN0ZXInXSA9IHRydWU7XG4gIH1cbiAgaWYgKGF1dGgudXNlcikge1xuICAgIHJlcXVlc3RbJ3VzZXInXSA9IGF1dGgudXNlcjtcbiAgfVxuICBpZiAoYXV0aC5pbnN0YWxsYXRpb25JZCkge1xuICAgIHJlcXVlc3RbJ2luc3RhbGxhdGlvbklkJ10gPSBhdXRoLmluc3RhbGxhdGlvbklkO1xuICB9XG4gIHJldHVybiByZXF1ZXN0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVxdWVzdFF1ZXJ5T2JqZWN0KFxuICB0cmlnZ2VyVHlwZSxcbiAgYXV0aCxcbiAgcXVlcnksXG4gIGNvdW50LFxuICBjb25maWcsXG4gIGlzR2V0XG4pIHtcbiAgaXNHZXQgPSAhIWlzR2V0O1xuXG4gIHZhciByZXF1ZXN0ID0ge1xuICAgIHRyaWdnZXJOYW1lOiB0cmlnZ2VyVHlwZSxcbiAgICBxdWVyeSxcbiAgICBtYXN0ZXI6IGZhbHNlLFxuICAgIGNvdW50LFxuICAgIGxvZzogY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIsXG4gICAgaXNHZXQsXG4gICAgaGVhZGVyczogY29uZmlnLmhlYWRlcnMsXG4gICAgaXA6IGNvbmZpZy5pcCxcbiAgfTtcblxuICBpZiAoIWF1dGgpIHtcbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuICBpZiAoYXV0aC5pc01hc3Rlcikge1xuICAgIHJlcXVlc3RbJ21hc3RlciddID0gdHJ1ZTtcbiAgfVxuICBpZiAoYXV0aC51c2VyKSB7XG4gICAgcmVxdWVzdFsndXNlciddID0gYXV0aC51c2VyO1xuICB9XG4gIGlmIChhdXRoLmluc3RhbGxhdGlvbklkKSB7XG4gICAgcmVxdWVzdFsnaW5zdGFsbGF0aW9uSWQnXSA9IGF1dGguaW5zdGFsbGF0aW9uSWQ7XG4gIH1cbiAgcmV0dXJuIHJlcXVlc3Q7XG59XG5cbi8vIENyZWF0ZXMgdGhlIHJlc3BvbnNlIG9iamVjdCwgYW5kIHVzZXMgdGhlIHJlcXVlc3Qgb2JqZWN0IHRvIHBhc3MgZGF0YVxuLy8gVGhlIEFQSSB3aWxsIGNhbGwgdGhpcyB3aXRoIFJFU1QgQVBJIGZvcm1hdHRlZCBvYmplY3RzLCB0aGlzIHdpbGxcbi8vIHRyYW5zZm9ybSB0aGVtIHRvIFBhcnNlLk9iamVjdCBpbnN0YW5jZXMgZXhwZWN0ZWQgYnkgQ2xvdWQgQ29kZS5cbi8vIEFueSBjaGFuZ2VzIG1hZGUgdG8gdGhlIG9iamVjdCBpbiBhIGJlZm9yZVNhdmUgd2lsbCBiZSBpbmNsdWRlZC5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXNwb25zZU9iamVjdChyZXF1ZXN0LCByZXNvbHZlLCByZWplY3QpIHtcbiAgcmV0dXJuIHtcbiAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgaWYgKHJlcXVlc3QudHJpZ2dlck5hbWUgPT09IFR5cGVzLmFmdGVyRmluZCkge1xuICAgICAgICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgICAgICAgcmVzcG9uc2UgPSByZXF1ZXN0Lm9iamVjdHM7XG4gICAgICAgIH1cbiAgICAgICAgcmVzcG9uc2UgPSByZXNwb25zZS5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICByZXR1cm4gb2JqZWN0LnRvSlNPTigpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHRoZSBKU09OIHJlc3BvbnNlXG4gICAgICBpZiAoXG4gICAgICAgIHJlc3BvbnNlICYmXG4gICAgICAgIHR5cGVvZiByZXNwb25zZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIXJlcXVlc3Qub2JqZWN0LmVxdWFscyhyZXNwb25zZSkgJiZcbiAgICAgICAgcmVxdWVzdC50cmlnZ2VyTmFtZSA9PT0gVHlwZXMuYmVmb3JlU2F2ZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlKHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgcmVzcG9uc2UgJiZcbiAgICAgICAgdHlwZW9mIHJlc3BvbnNlID09PSAnb2JqZWN0JyAmJlxuICAgICAgICByZXF1ZXN0LnRyaWdnZXJOYW1lID09PSBUeXBlcy5hZnRlclNhdmVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXNwb25zZSk7XG4gICAgICB9XG4gICAgICBpZiAocmVxdWVzdC50cmlnZ2VyTmFtZSA9PT0gVHlwZXMuYWZ0ZXJTYXZlKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgaWYgKHJlcXVlc3QudHJpZ2dlck5hbWUgPT09IFR5cGVzLmJlZm9yZVNhdmUpIHtcbiAgICAgICAgcmVzcG9uc2VbJ29iamVjdCddID0gcmVxdWVzdC5vYmplY3QuX2dldFNhdmVKU09OKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzb2x2ZShyZXNwb25zZSk7XG4gICAgfSxcbiAgICBlcnJvcjogZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFBhcnNlLkVycm9yKSB7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9IGVsc2UgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVELCBlcnJvci5tZXNzYWdlKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWplY3QobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlNDUklQVF9GQUlMRUQsIGVycm9yKSk7XG4gICAgICB9XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gdXNlcklkRm9yTG9nKGF1dGgpIHtcbiAgcmV0dXJuIGF1dGggJiYgYXV0aC51c2VyID8gYXV0aC51c2VyLmlkIDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBsb2dUcmlnZ2VyQWZ0ZXJIb29rKHRyaWdnZXJUeXBlLCBjbGFzc05hbWUsIGlucHV0LCBhdXRoKSB7XG4gIGNvbnN0IGNsZWFuSW5wdXQgPSBsb2dnZXIudHJ1bmNhdGVMb2dNZXNzYWdlKEpTT04uc3RyaW5naWZ5KGlucHV0KSk7XG4gIGxvZ2dlci5pbmZvKFxuICAgIGAke3RyaWdnZXJUeXBlfSB0cmlnZ2VyZWQgZm9yICR7Y2xhc3NOYW1lfSBmb3IgdXNlciAke3VzZXJJZEZvckxvZyhcbiAgICAgIGF1dGhcbiAgICApfTpcXG4gIElucHV0OiAke2NsZWFuSW5wdXR9YCxcbiAgICB7XG4gICAgICBjbGFzc05hbWUsXG4gICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgIHVzZXI6IHVzZXJJZEZvckxvZyhhdXRoKSxcbiAgICB9XG4gICk7XG59XG5cbmZ1bmN0aW9uIGxvZ1RyaWdnZXJTdWNjZXNzQmVmb3JlSG9vayhcbiAgdHJpZ2dlclR5cGUsXG4gIGNsYXNzTmFtZSxcbiAgaW5wdXQsXG4gIHJlc3VsdCxcbiAgYXV0aFxuKSB7XG4gIGNvbnN0IGNsZWFuSW5wdXQgPSBsb2dnZXIudHJ1bmNhdGVMb2dNZXNzYWdlKEpTT04uc3RyaW5naWZ5KGlucHV0KSk7XG4gIGNvbnN0IGNsZWFuUmVzdWx0ID0gbG9nZ2VyLnRydW5jYXRlTG9nTWVzc2FnZShKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgbG9nZ2VyLmluZm8oXG4gICAgYCR7dHJpZ2dlclR5cGV9IHRyaWdnZXJlZCBmb3IgJHtjbGFzc05hbWV9IGZvciB1c2VyICR7dXNlcklkRm9yTG9nKFxuICAgICAgYXV0aFxuICAgICl9OlxcbiAgSW5wdXQ6ICR7Y2xlYW5JbnB1dH1cXG4gIFJlc3VsdDogJHtjbGVhblJlc3VsdH1gLFxuICAgIHtcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHRyaWdnZXJUeXBlLFxuICAgICAgdXNlcjogdXNlcklkRm9yTG9nKGF1dGgpLFxuICAgIH1cbiAgKTtcbn1cblxuZnVuY3Rpb24gbG9nVHJpZ2dlckVycm9yQmVmb3JlSG9vayh0cmlnZ2VyVHlwZSwgY2xhc3NOYW1lLCBpbnB1dCwgYXV0aCwgZXJyb3IpIHtcbiAgY29uc3QgY2xlYW5JbnB1dCA9IGxvZ2dlci50cnVuY2F0ZUxvZ01lc3NhZ2UoSlNPTi5zdHJpbmdpZnkoaW5wdXQpKTtcbiAgbG9nZ2VyLmVycm9yKFxuICAgIGAke3RyaWdnZXJUeXBlfSBmYWlsZWQgZm9yICR7Y2xhc3NOYW1lfSBmb3IgdXNlciAke3VzZXJJZEZvckxvZyhcbiAgICAgIGF1dGhcbiAgICApfTpcXG4gIElucHV0OiAke2NsZWFuSW5wdXR9XFxuICBFcnJvcjogJHtKU09OLnN0cmluZ2lmeShlcnJvcil9YCxcbiAgICB7XG4gICAgICBjbGFzc05hbWUsXG4gICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgIGVycm9yLFxuICAgICAgdXNlcjogdXNlcklkRm9yTG9nKGF1dGgpLFxuICAgIH1cbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1heWJlUnVuQWZ0ZXJGaW5kVHJpZ2dlcihcbiAgdHJpZ2dlclR5cGUsXG4gIGF1dGgsXG4gIGNsYXNzTmFtZSxcbiAgb2JqZWN0cyxcbiAgY29uZmlnXG4pIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCB0cmlnZ2VyID0gZ2V0VHJpZ2dlcihjbGFzc05hbWUsIHRyaWdnZXJUeXBlLCBjb25maWcuYXBwbGljYXRpb25JZCk7XG4gICAgaWYgKCF0cmlnZ2VyKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgIH1cbiAgICBjb25zdCByZXF1ZXN0ID0gZ2V0UmVxdWVzdE9iamVjdCh0cmlnZ2VyVHlwZSwgYXV0aCwgbnVsbCwgbnVsbCwgY29uZmlnKTtcbiAgICBjb25zdCB7IHN1Y2Nlc3MsIGVycm9yIH0gPSBnZXRSZXNwb25zZU9iamVjdChcbiAgICAgIHJlcXVlc3QsXG4gICAgICBvYmplY3QgPT4ge1xuICAgICAgICByZXNvbHZlKG9iamVjdCk7XG4gICAgICB9LFxuICAgICAgZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfVxuICAgICk7XG4gICAgbG9nVHJpZ2dlclN1Y2Nlc3NCZWZvcmVIb29rKFxuICAgICAgdHJpZ2dlclR5cGUsXG4gICAgICBjbGFzc05hbWUsXG4gICAgICAnQWZ0ZXJGaW5kJyxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG9iamVjdHMpLFxuICAgICAgYXV0aFxuICAgICk7XG4gICAgcmVxdWVzdC5vYmplY3RzID0gb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgIC8vc2V0dGluZyB0aGUgY2xhc3MgbmFtZSB0byB0cmFuc2Zvcm0gaW50byBwYXJzZSBvYmplY3RcbiAgICAgIG9iamVjdC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgICByZXR1cm4gUGFyc2UuT2JqZWN0LmZyb21KU09OKG9iamVjdCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gdHJpZ2dlcihyZXF1ZXN0KTtcbiAgICAgICAgaWYgKHJlc3BvbnNlICYmIHR5cGVvZiByZXNwb25zZS50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgICBpZiAoIXJlc3VsdHMpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLlNDUklQVF9GQUlMRUQsXG4gICAgICAgICAgICAgICAgJ0FmdGVyRmluZCBleHBlY3QgcmVzdWx0cyB0byBiZSByZXR1cm5lZCBpbiB0aGUgcHJvbWlzZSdcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgIH0pXG4gICAgICAudGhlbihzdWNjZXNzLCBlcnJvcik7XG4gIH0pLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgbG9nVHJpZ2dlckFmdGVySG9vayh0cmlnZ2VyVHlwZSwgY2xhc3NOYW1lLCBKU09OLnN0cmluZ2lmeShyZXN1bHRzKSwgYXV0aCk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF5YmVSdW5RdWVyeVRyaWdnZXIoXG4gIHRyaWdnZXJUeXBlLFxuICBjbGFzc05hbWUsXG4gIHJlc3RXaGVyZSxcbiAgcmVzdE9wdGlvbnMsXG4gIGNvbmZpZyxcbiAgYXV0aCxcbiAgaXNHZXRcbikge1xuICBjb25zdCB0cmlnZ2VyID0gZ2V0VHJpZ2dlcihjbGFzc05hbWUsIHRyaWdnZXJUeXBlLCBjb25maWcuYXBwbGljYXRpb25JZCk7XG4gIGlmICghdHJpZ2dlcikge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgcmVzdFdoZXJlLFxuICAgICAgcmVzdE9wdGlvbnMsXG4gICAgfSk7XG4gIH1cbiAgY29uc3QganNvbiA9IE9iamVjdC5hc3NpZ24oe30sIHJlc3RPcHRpb25zKTtcbiAganNvbi53aGVyZSA9IHJlc3RXaGVyZTtcblxuICBjb25zdCBwYXJzZVF1ZXJ5ID0gbmV3IFBhcnNlLlF1ZXJ5KGNsYXNzTmFtZSk7XG4gIHBhcnNlUXVlcnkud2l0aEpTT04oanNvbik7XG5cbiAgbGV0IGNvdW50ID0gZmFsc2U7XG4gIGlmIChyZXN0T3B0aW9ucykge1xuICAgIGNvdW50ID0gISFyZXN0T3B0aW9ucy5jb3VudDtcbiAgfVxuICBjb25zdCByZXF1ZXN0T2JqZWN0ID0gZ2V0UmVxdWVzdFF1ZXJ5T2JqZWN0KFxuICAgIHRyaWdnZXJUeXBlLFxuICAgIGF1dGgsXG4gICAgcGFyc2VRdWVyeSxcbiAgICBjb3VudCxcbiAgICBjb25maWcsXG4gICAgaXNHZXRcbiAgKTtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRyaWdnZXIocmVxdWVzdE9iamVjdCk7XG4gICAgfSlcbiAgICAudGhlbihcbiAgICAgIHJlc3VsdCA9PiB7XG4gICAgICAgIGxldCBxdWVyeVJlc3VsdCA9IHBhcnNlUXVlcnk7XG4gICAgICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0IGluc3RhbmNlb2YgUGFyc2UuUXVlcnkpIHtcbiAgICAgICAgICBxdWVyeVJlc3VsdCA9IHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBqc29uUXVlcnkgPSBxdWVyeVJlc3VsdC50b0pTT04oKTtcbiAgICAgICAgaWYgKGpzb25RdWVyeS53aGVyZSkge1xuICAgICAgICAgIHJlc3RXaGVyZSA9IGpzb25RdWVyeS53aGVyZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoanNvblF1ZXJ5LmxpbWl0KSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5saW1pdCA9IGpzb25RdWVyeS5saW1pdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoanNvblF1ZXJ5LnNraXApIHtcbiAgICAgICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgICAgIHJlc3RPcHRpb25zLnNraXAgPSBqc29uUXVlcnkuc2tpcDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoanNvblF1ZXJ5LmluY2x1ZGUpIHtcbiAgICAgICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgICAgIHJlc3RPcHRpb25zLmluY2x1ZGUgPSBqc29uUXVlcnkuaW5jbHVkZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoanNvblF1ZXJ5LmV4Y2x1ZGVLZXlzKSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5leGNsdWRlS2V5cyA9IGpzb25RdWVyeS5leGNsdWRlS2V5cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoanNvblF1ZXJ5LmtleXMpIHtcbiAgICAgICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgICAgIHJlc3RPcHRpb25zLmtleXMgPSBqc29uUXVlcnkua2V5cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoanNvblF1ZXJ5Lm9yZGVyKSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5vcmRlciA9IGpzb25RdWVyeS5vcmRlcjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVxdWVzdE9iamVjdC5yZWFkUHJlZmVyZW5jZSkge1xuICAgICAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICAgICAgcmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSByZXF1ZXN0T2JqZWN0LnJlYWRQcmVmZXJlbmNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXF1ZXN0T2JqZWN0LmluY2x1ZGVSZWFkUHJlZmVyZW5jZSkge1xuICAgICAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZVJlYWRQcmVmZXJlbmNlID1cbiAgICAgICAgICAgIHJlcXVlc3RPYmplY3QuaW5jbHVkZVJlYWRQcmVmZXJlbmNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXF1ZXN0T2JqZWN0LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICAgICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgICAgIHJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPVxuICAgICAgICAgICAgcmVxdWVzdE9iamVjdC5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVzdFdoZXJlLFxuICAgICAgICAgIHJlc3RPcHRpb25zLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIGVyciA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgZXJyID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxLCBlcnIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICk7XG59XG5cbi8vIFRvIGJlIHVzZWQgYXMgcGFydCBvZiB0aGUgcHJvbWlzZSBjaGFpbiB3aGVuIHNhdmluZy9kZWxldGluZyBhbiBvYmplY3Rcbi8vIFdpbGwgcmVzb2x2ZSBzdWNjZXNzZnVsbHkgaWYgbm8gdHJpZ2dlciBpcyBjb25maWd1cmVkXG4vLyBSZXNvbHZlcyB0byBhbiBvYmplY3QsIGVtcHR5IG9yIGNvbnRhaW5pbmcgYW4gb2JqZWN0IGtleS4gQSBiZWZvcmVTYXZlXG4vLyB0cmlnZ2VyIHdpbGwgc2V0IHRoZSBvYmplY3Qga2V5IHRvIHRoZSByZXN0IGZvcm1hdCBvYmplY3QgdG8gc2F2ZS5cbi8vIG9yaWdpbmFsUGFyc2VPYmplY3QgaXMgb3B0aW9uYWwsIHdlIG9ubHkgbmVlZCB0aGF0IGZvciBiZWZvcmUvYWZ0ZXJTYXZlIGZ1bmN0aW9uc1xuZXhwb3J0IGZ1bmN0aW9uIG1heWJlUnVuVHJpZ2dlcihcbiAgdHJpZ2dlclR5cGUsXG4gIGF1dGgsXG4gIHBhcnNlT2JqZWN0LFxuICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICBjb25maWcsXG4gIGNvbnRleHRcbikge1xuICBpZiAoIXBhcnNlT2JqZWN0KSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gIH1cbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgIHZhciB0cmlnZ2VyID0gZ2V0VHJpZ2dlcihcbiAgICAgIHBhcnNlT2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgIHRyaWdnZXJUeXBlLFxuICAgICAgY29uZmlnLmFwcGxpY2F0aW9uSWRcbiAgICApO1xuICAgIGlmICghdHJpZ2dlcikgcmV0dXJuIHJlc29sdmUoKTtcbiAgICB2YXIgcmVxdWVzdCA9IGdldFJlcXVlc3RPYmplY3QoXG4gICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgIGF1dGgsXG4gICAgICBwYXJzZU9iamVjdCxcbiAgICAgIG9yaWdpbmFsUGFyc2VPYmplY3QsXG4gICAgICBjb25maWcsXG4gICAgICBjb250ZXh0XG4gICAgKTtcbiAgICB2YXIgeyBzdWNjZXNzLCBlcnJvciB9ID0gZ2V0UmVzcG9uc2VPYmplY3QoXG4gICAgICByZXF1ZXN0LFxuICAgICAgb2JqZWN0ID0+IHtcbiAgICAgICAgbG9nVHJpZ2dlclN1Y2Nlc3NCZWZvcmVIb29rKFxuICAgICAgICAgIHRyaWdnZXJUeXBlLFxuICAgICAgICAgIHBhcnNlT2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgICAgICBwYXJzZU9iamVjdC50b0pTT04oKSxcbiAgICAgICAgICBvYmplY3QsXG4gICAgICAgICAgYXV0aFxuICAgICAgICApO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdHJpZ2dlclR5cGUgPT09IFR5cGVzLmJlZm9yZVNhdmUgfHxcbiAgICAgICAgICB0cmlnZ2VyVHlwZSA9PT0gVHlwZXMuYWZ0ZXJTYXZlXG4gICAgICAgICkge1xuICAgICAgICAgIE9iamVjdC5hc3NpZ24oY29udGV4dCwgcmVxdWVzdC5jb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKG9iamVjdCk7XG4gICAgICB9LFxuICAgICAgZXJyb3IgPT4ge1xuICAgICAgICBsb2dUcmlnZ2VyRXJyb3JCZWZvcmVIb29rKFxuICAgICAgICAgIHRyaWdnZXJUeXBlLFxuICAgICAgICAgIHBhcnNlT2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgICAgICBwYXJzZU9iamVjdC50b0pTT04oKSxcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIGVycm9yXG4gICAgICAgICk7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9XG4gICAgKTtcblxuICAgIC8vIEFmdGVyU2F2ZSBhbmQgYWZ0ZXJEZWxldGUgdHJpZ2dlcnMgY2FuIHJldHVybiBhIHByb21pc2UsIHdoaWNoIGlmIHRoZXlcbiAgICAvLyBkbywgbmVlZHMgdG8gYmUgcmVzb2x2ZWQgYmVmb3JlIHRoaXMgcHJvbWlzZSBpcyByZXNvbHZlZCxcbiAgICAvLyBzbyB0cmlnZ2VyIGV4ZWN1dGlvbiBpcyBzeW5jZWQgd2l0aCBSZXN0V3JpdGUuZXhlY3V0ZSgpIGNhbGwuXG4gICAgLy8gSWYgdHJpZ2dlcnMgZG8gbm90IHJldHVybiBhIHByb21pc2UsIHRoZXkgY2FuIHJ1biBhc3luYyBjb2RlIHBhcmFsbGVsXG4gICAgLy8gdG8gdGhlIFJlc3RXcml0ZS5leGVjdXRlKCkgY2FsbC5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRyaWdnZXIocmVxdWVzdCk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0cmlnZ2VyVHlwZSA9PT0gVHlwZXMuYWZ0ZXJTYXZlIHx8XG4gICAgICAgICAgdHJpZ2dlclR5cGUgPT09IFR5cGVzLmFmdGVyRGVsZXRlXG4gICAgICAgICkge1xuICAgICAgICAgIGxvZ1RyaWdnZXJBZnRlckhvb2soXG4gICAgICAgICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0LnRvSlNPTigpLFxuICAgICAgICAgICAgYXV0aFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYmVmb3JlU2F2ZSBpcyBleHBlY3RlZCB0byByZXR1cm4gbnVsbCAobm90aGluZylcbiAgICAgICAgaWYgKHRyaWdnZXJUeXBlID09PSBUeXBlcy5iZWZvcmVTYXZlKSB7XG4gICAgICAgICAgaWYgKHByb21pc2UgJiYgdHlwZW9mIHByb21pc2UudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHByb21pc2UudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgIC8vIHJlc3BvbnNlLm9iamVjdCBtYXkgY29tZSBmcm9tIGV4cHJlc3Mgcm91dGluZyBiZWZvcmUgaG9va1xuICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2Uub2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICB9KVxuICAgICAgLnRoZW4oc3VjY2VzcywgZXJyb3IpO1xuICB9KTtcbn1cblxuLy8gQ29udmVydHMgYSBSRVNULWZvcm1hdCBvYmplY3QgdG8gYSBQYXJzZS5PYmplY3Rcbi8vIGRhdGEgaXMgZWl0aGVyIGNsYXNzTmFtZSBvciBhbiBvYmplY3RcbmV4cG9ydCBmdW5jdGlvbiBpbmZsYXRlKGRhdGEsIHJlc3RPYmplY3QpIHtcbiAgdmFyIGNvcHkgPSB0eXBlb2YgZGF0YSA9PSAnb2JqZWN0JyA/IGRhdGEgOiB7IGNsYXNzTmFtZTogZGF0YSB9O1xuICBmb3IgKHZhciBrZXkgaW4gcmVzdE9iamVjdCkge1xuICAgIGNvcHlba2V5XSA9IHJlc3RPYmplY3Rba2V5XTtcbiAgfVxuICByZXR1cm4gUGFyc2UuT2JqZWN0LmZyb21KU09OKGNvcHkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyhcbiAgZGF0YSxcbiAgYXBwbGljYXRpb25JZCA9IFBhcnNlLmFwcGxpY2F0aW9uSWRcbikge1xuICBpZiAoXG4gICAgIV90cmlnZ2VyU3RvcmUgfHxcbiAgICAhX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXSB8fFxuICAgICFfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdLkxpdmVRdWVyeVxuICApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXS5MaXZlUXVlcnkuZm9yRWFjaChoYW5kbGVyID0+IGhhbmRsZXIoZGF0YSkpO1xufVxuIl19 \ No newline at end of file diff --git a/lib/vendor/README.md b/lib/vendor/README.md new file mode 100644 index 0000000000..04e3256f72 --- /dev/null +++ b/lib/vendor/README.md @@ -0,0 +1,8 @@ +# mongoUrl + +A fork of node's `url` module, with the modification that commas and colons are +allowed in hostnames. While this results in a slightly incorrect parsed result, +as the hostname field for a mongodb should be an array of replica sets, it's +good enough to let us pull out and escape the auth portion of the URL. + +https://github.com/parse-community/parse-server/pull/986 diff --git a/lib/vendor/mongodbUrl.js b/lib/vendor/mongodbUrl.js new file mode 100644 index 0000000000..cd141db92a --- /dev/null +++ b/lib/vendor/mongodbUrl.js @@ -0,0 +1,1069 @@ +// A slightly patched version of node's url module, with support for mongodb:// +// uris. +// +// See https://github.com/nodejs/node/blob/master/LICENSE for licensing +// information +'use strict'; + +const punycode = require('punycode'); + +exports.parse = urlParse; +exports.resolve = urlResolve; +exports.resolveObject = urlResolveObject; +exports.format = urlFormat; +exports.Url = Url; + +function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; +} // Reference: RFC 3986, RFC 1808, RFC 2396 +// define these here so at least they only have to be +// compiled once on the first module load. + + +const protocolPattern = /^([a-z0-9.+-]+:)/i; +const portPattern = /:[0-9]*$/; // Special case for a simple path URL + +const simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/; +const hostnameMaxLen = 255; // protocols that can allow "unsafe" and "unwise" chars. + +const unsafeProtocol = { + javascript: true, + 'javascript:': true +}; // protocols that never have a hostname. + +const hostlessProtocol = { + javascript: true, + 'javascript:': true +}; // protocols that always contain a // bit. + +const slashedProtocol = { + http: true, + 'http:': true, + https: true, + 'https:': true, + ftp: true, + 'ftp:': true, + gopher: true, + 'gopher:': true, + file: true, + 'file:': true +}; + +const querystring = require('querystring'); +/* istanbul ignore next: improve coverage */ + + +function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url instanceof Url) return url; + var u = new Url(); + u.parse(url, parseQueryString, slashesDenoteHost); + return u; +} +/* istanbul ignore next: improve coverage */ + + +Url.prototype.parse = function (url, parseQueryString, slashesDenoteHost) { + if (typeof url !== 'string') { + throw new TypeError('Parameter "url" must be a string, not ' + typeof url); + } // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + + + var hasHash = false; + var start = -1; + var end = -1; + var rest = ''; + var lastPos = 0; + var i = 0; + + for (var inWs = false, split = false; i < url.length; ++i) { + const code = url.charCodeAt(i); // Find first and last non-whitespace characters for trimming + + const isWs = code === 32 + /* */ + || code === 9 + /*\t*/ + || code === 13 + /*\r*/ + || code === 10 + /*\n*/ + || code === 12 + /*\f*/ + || code === 160 + /*\u00A0*/ + || code === 65279; + /*\uFEFF*/ + + if (start === -1) { + if (isWs) continue; + lastPos = start = i; + } else { + if (inWs) { + if (!isWs) { + end = -1; + inWs = false; + } + } else if (isWs) { + end = i; + inWs = true; + } + } // Only convert backslashes while we haven't seen a split character + + + if (!split) { + switch (code) { + case 35: + // '#' + hasHash = true; + // Fall through + + case 63: + // '?' + split = true; + break; + + case 92: + // '\\' + if (i - lastPos > 0) rest += url.slice(lastPos, i); + rest += '/'; + lastPos = i + 1; + break; + } + } else if (!hasHash && code === 35 + /*#*/ + ) { + hasHash = true; + } + } // Check if string was non-empty (including strings with only whitespace) + + + if (start !== -1) { + if (lastPos === start) { + // We didn't convert any backslashes + if (end === -1) { + if (start === 0) rest = url;else rest = url.slice(start); + } else { + rest = url.slice(start, end); + } + } else if (end === -1 && lastPos < url.length) { + // We converted some backslashes and have only part of the entire string + rest += url.slice(lastPos); + } else if (end !== -1 && lastPos < end) { + // We converted some backslashes and have only part of the entire string + rest += url.slice(lastPos, end); + } + } + + if (!slashesDenoteHost && !hasHash) { + // Try fast path regexp + const simplePath = simplePathPattern.exec(rest); + + if (simplePath) { + this.path = rest; + this.href = rest; + this.pathname = simplePath[1]; + + if (simplePath[2]) { + this.search = simplePath[2]; + + if (parseQueryString) { + this.query = querystring.parse(this.search.slice(1)); + } else { + this.query = this.search.slice(1); + } + } else if (parseQueryString) { + this.search = ''; + this.query = {}; + } + + return this; + } + } + + var proto = protocolPattern.exec(rest); + + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.slice(proto.length); + } // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + + + if (slashesDenoteHost || proto || /^\/\/[^@\/]+@[^@\/]+/.test(rest)) { + var slashes = rest.charCodeAt(0) === 47 + /*/*/ + && rest.charCodeAt(1) === 47; + /*/*/ + + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.slice(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && (slashes || proto && !slashedProtocol[proto])) { + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:b path:/?@c + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + var hostEnd = -1; + var atSign = -1; + var nonHost = -1; + + for (i = 0; i < rest.length; ++i) { + switch (rest.charCodeAt(i)) { + case 9: // '\t' + + case 10: // '\n' + + case 13: // '\r' + + case 32: // ' ' + + case 34: // '"' + + case 37: // '%' + + case 39: // '\'' + + case 59: // ';' + + case 60: // '<' + + case 62: // '>' + + case 92: // '\\' + + case 94: // '^' + + case 96: // '`' + + case 123: // '{' + + case 124: // '|' + + case 125: + // '}' + // Characters that are never ever allowed in a hostname from RFC 2396 + if (nonHost === -1) nonHost = i; + break; + + case 35: // '#' + + case 47: // '/' + + case 63: + // '?' + // Find the first instance of any host-ending characters + if (nonHost === -1) nonHost = i; + hostEnd = i; + break; + + case 64: + // '@' + // At this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + atSign = i; + nonHost = -1; + break; + } + + if (hostEnd !== -1) break; + } + + start = 0; + + if (atSign !== -1) { + this.auth = decodeURIComponent(rest.slice(0, atSign)); + start = atSign + 1; + } + + if (nonHost === -1) { + this.host = rest.slice(start); + rest = ''; + } else { + this.host = rest.slice(start, nonHost); + rest = rest.slice(nonHost); + } // pull out port. + + + this.parseHost(); // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + + if (typeof this.hostname !== 'string') this.hostname = ''; + var hostname = this.hostname; // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + + var ipv6Hostname = hostname.charCodeAt(0) === 91 + /*[*/ + && hostname.charCodeAt(hostname.length - 1) === 93; + /*]*/ + // validate a little. + + if (!ipv6Hostname) { + const result = validateHostname(this, rest, hostname); + if (result !== undefined) rest = result; + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a punycoded representation of "domain". + // It only converts parts of the domain name that + // have non-ASCII characters, i.e. it doesn't matter if + // you call it with a domain that already is ASCII-only. + this.hostname = punycode.toASCII(this.hostname); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; // strip [ and ] from the hostname + // the host field still retains them, though + + if (ipv6Hostname) { + this.hostname = this.hostname.slice(1, -1); + + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } // now rest is set to the post-host stuff. + // chop off any delim chars. + + + if (!unsafeProtocol[lowerProto]) { + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + const result = autoEscapeStr(rest); + if (result !== undefined) rest = result; + } + + var questionIdx = -1; + var hashIdx = -1; + + for (i = 0; i < rest.length; ++i) { + const code = rest.charCodeAt(i); + + if (code === 35 + /*#*/ + ) { + this.hash = rest.slice(i); + hashIdx = i; + break; + } else if (code === 63 + /*?*/ + && questionIdx === -1) { + questionIdx = i; + } + } + + if (questionIdx !== -1) { + if (hashIdx === -1) { + this.search = rest.slice(questionIdx); + this.query = rest.slice(questionIdx + 1); + } else { + this.search = rest.slice(questionIdx, hashIdx); + this.query = rest.slice(questionIdx + 1, hashIdx); + } + + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + + var firstIdx = questionIdx !== -1 && (hashIdx === -1 || questionIdx < hashIdx) ? questionIdx : hashIdx; + + if (firstIdx === -1) { + if (rest.length > 0) this.pathname = rest; + } else if (firstIdx > 0) { + this.pathname = rest.slice(0, firstIdx); + } + + if (slashedProtocol[lowerProto] && this.hostname && !this.pathname) { + this.pathname = '/'; + } // to support http.request + + + if (this.pathname || this.search) { + const p = this.pathname || ''; + const s = this.search || ''; + this.path = p + s; + } // finally, reconstruct the href based on what has been validated. + + + this.href = this.format(); + return this; +}; +/* istanbul ignore next: improve coverage */ + + +function validateHostname(self, rest, hostname) { + for (var i = 0, lastPos; i <= hostname.length; ++i) { + var code; + if (i < hostname.length) code = hostname.charCodeAt(i); + + if (code === 46 + /*.*/ + || i === hostname.length) { + if (i - lastPos > 0) { + if (i - lastPos > 63) { + self.hostname = hostname.slice(0, lastPos + 63); + return '/' + hostname.slice(lastPos + 63) + rest; + } + } + + lastPos = i + 1; + continue; + } else if (code >= 48 + /*0*/ + && code <= 57 || + /*9*/ + code >= 97 + /*a*/ + && code <= 122 + /*z*/ + || code === 45 + /*-*/ + || code >= 65 + /*A*/ + && code <= 90 + /*Z*/ + || code === 43 + /*+*/ + || code === 95 + /*_*/ + || + /* BEGIN MONGO URI PATCH */ + code === 44 + /*,*/ + || code === 58 + /*:*/ + || + /* END MONGO URI PATCH */ + code > 127) { + continue; + } // Invalid host character + + + self.hostname = hostname.slice(0, i); + if (i < hostname.length) return '/' + hostname.slice(i) + rest; + break; + } +} +/* istanbul ignore next: improve coverage */ + + +function autoEscapeStr(rest) { + var newRest = ''; + var lastPos = 0; + + for (var i = 0; i < rest.length; ++i) { + // Automatically escape all delimiters and unwise characters from RFC 2396 + // Also escape single quotes in case of an XSS attack + switch (rest.charCodeAt(i)) { + case 9: + // '\t' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%09'; + lastPos = i + 1; + break; + + case 10: + // '\n' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%0A'; + lastPos = i + 1; + break; + + case 13: + // '\r' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%0D'; + lastPos = i + 1; + break; + + case 32: + // ' ' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%20'; + lastPos = i + 1; + break; + + case 34: + // '"' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%22'; + lastPos = i + 1; + break; + + case 39: + // '\'' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%27'; + lastPos = i + 1; + break; + + case 60: + // '<' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%3C'; + lastPos = i + 1; + break; + + case 62: + // '>' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%3E'; + lastPos = i + 1; + break; + + case 92: + // '\\' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%5C'; + lastPos = i + 1; + break; + + case 94: + // '^' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%5E'; + lastPos = i + 1; + break; + + case 96: + // '`' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%60'; + lastPos = i + 1; + break; + + case 123: + // '{' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%7B'; + lastPos = i + 1; + break; + + case 124: + // '|' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%7C'; + lastPos = i + 1; + break; + + case 125: + // '}' + if (i - lastPos > 0) newRest += rest.slice(lastPos, i); + newRest += '%7D'; + lastPos = i + 1; + break; + } + } + + if (lastPos === 0) return; + if (lastPos < rest.length) return newRest + rest.slice(lastPos);else return newRest; +} // format a parsed object into a url string + +/* istanbul ignore next: improve coverage */ + + +function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (typeof obj === 'string') obj = urlParse(obj);else if (typeof obj !== 'object' || obj === null) throw new TypeError('Parameter "urlObj" must be an object, not ' + obj === null ? 'null' : typeof obj);else if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); +} +/* istanbul ignore next: improve coverage */ + + +Url.prototype.format = function () { + var auth = this.auth || ''; + + if (auth) { + auth = encodeAuth(auth); + auth += '@'; + } + + var protocol = this.protocol || ''; + var pathname = this.pathname || ''; + var hash = this.hash || ''; + var host = false; + var query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? this.hostname : '[' + this.hostname + ']'); + + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query !== null && typeof this.query === 'object') query = querystring.stringify(this.query); + var search = this.search || query && '?' + query || ''; + if (protocol && protocol.charCodeAt(protocol.length - 1) !== 58 + /*:*/ + ) protocol += ':'; + var newPathname = ''; + var lastPos = 0; + + for (var i = 0; i < pathname.length; ++i) { + switch (pathname.charCodeAt(i)) { + case 35: + // '#' + if (i - lastPos > 0) newPathname += pathname.slice(lastPos, i); + newPathname += '%23'; + lastPos = i + 1; + break; + + case 63: + // '?' + if (i - lastPos > 0) newPathname += pathname.slice(lastPos, i); + newPathname += '%3F'; + lastPos = i + 1; + break; + } + } + + if (lastPos > 0) { + if (lastPos !== pathname.length) pathname = newPathname + pathname.slice(lastPos);else pathname = newPathname; + } // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + + + if (this.slashes || (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charCodeAt(0) !== 47 + /*/*/ + ) pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + search = search.replace('#', '%23'); + if (hash && hash.charCodeAt(0) !== 35 + /*#*/ + ) hash = '#' + hash; + if (search && search.charCodeAt(0) !== 63 + /*?*/ + ) search = '?' + search; + return protocol + host + pathname + search + hash; +}; +/* istanbul ignore next: improve coverage */ + + +function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); +} +/* istanbul ignore next: improve coverage */ + + +Url.prototype.resolve = function (relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); +}; +/* istanbul ignore next: improve coverage */ + + +function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); +} +/* istanbul ignore next: improve coverage */ + + +Url.prototype.resolveObject = function (relative) { + if (typeof relative === 'string') { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + var tkeys = Object.keys(this); + + for (var tk = 0; tk < tkeys.length; tk++) { + var tkey = tkeys[tk]; + result[tkey] = this[tkey]; + } // hash is always overridden, no matter what. + // even href="" will remove it. + + + result.hash = relative.hash; // if the relative url is empty, then there's nothing left to do here. + + if (relative.href === '') { + result.href = result.format(); + return result; + } // hrefs like //foo/bar always cut to the protocol. + + + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + var rkeys = Object.keys(relative); + + for (var rk = 0; rk < rkeys.length; rk++) { + var rkey = rkeys[rk]; + if (rkey !== 'protocol') result[rkey] = relative[rkey]; + } //urlParse appends trailing / to urls like http://www.example.com + + + if (slashedProtocol[result.protocol] && result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + var keys = Object.keys(relative); + + for (var v = 0; v < keys.length; v++) { + var k = keys[v]; + result[k] = relative[k]; + } + + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + + if (!relative.host && !/^file:?$/.test(relative.protocol) && !hostlessProtocol[relative.protocol]) { + const relPath = (relative.pathname || '').split('/'); + + while (relPath.length && !(relative.host = relPath.shift())); + + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; // to support http.request + + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = result.pathname && result.pathname.charAt(0) === '/'; + var isRelAbs = relative.host || relative.pathname && relative.pathname.charAt(0) === '/'; + var mustEndAbs = isRelAbs || isSourceAbs || result.host && relative.pathname; + var removeAllDots = mustEndAbs; + var srcPath = result.pathname && result.pathname.split('/') || []; + var relPath = relative.pathname && relative.pathname.split('/') || []; + var psychotic = result.protocol && !slashedProtocol[result.protocol]; // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + + if (psychotic) { + result.hostname = ''; + result.port = null; + + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host;else srcPath.unshift(result.host); + } + + result.host = ''; + + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host;else relPath.unshift(relative.host); + } + + relative.host = null; + } + + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = relative.host || relative.host === '' ? relative.host : result.host; + result.hostname = relative.hostname || relative.hostname === '' ? relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (relative.search !== null && relative.search !== undefined) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); //occasionally the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + + const authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; + + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + result.search = relative.search; + result.query = relative.query; //to support http.request + + if (result.pathname !== null || result.search !== null) { + result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); + } + + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; //to support http.request + + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + + result.href = result.format(); + return result; + } // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + + + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = (result.host || relative.host || srcPath.length > 1) && (last === '.' || last === '..') || last === ''; // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + + var up = 0; + + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + + if (last === '.') { + spliceOne(srcPath, i); + } else if (last === '..') { + spliceOne(srcPath, i); + up++; + } else if (up) { + spliceOne(srcPath, i); + up--; + } + } // if the path is allowed to go above the root, restore leading ..s + + + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && srcPath.join('/').substr(-1) !== '/') { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || srcPath[0] && srcPath[0].charAt(0) === '/'; // put the host back + + if (psychotic) { + if (isAbsolute) { + result.hostname = result.host = ''; + } else { + result.hostname = result.host = srcPath.length ? srcPath.shift() : ''; + } //occasionally the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + + + const authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; + + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || result.host && srcPath.length; + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } //to support request.http + + + if (result.pathname !== null || result.search !== null) { + result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); + } + + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; +}; +/* istanbul ignore next: improve coverage */ + + +Url.prototype.parseHost = function () { + var host = this.host; + var port = portPattern.exec(host); + + if (port) { + port = port[0]; + + if (port !== ':') { + this.port = port.slice(1); + } + + host = host.slice(0, host.length - port.length); + } + + if (host) this.hostname = host; +}; // About 1.5x faster than the two-arg version of Array#splice(). + +/* istanbul ignore next: improve coverage */ + + +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) list[i] = list[k]; + + list.pop(); +} + +var hexTable = new Array(256); + +for (var i = 0; i < 256; ++i) hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase(); +/* istanbul ignore next: improve coverage */ + + +function encodeAuth(str) { + // faster encodeURIComponent alternative for encoding auth uri components + var out = ''; + var lastPos = 0; + + for (var i = 0; i < str.length; ++i) { + var c = str.charCodeAt(i); // These characters do not need escaping: + // ! - . _ ~ + // ' ( ) * : + // digits + // alpha (uppercase) + // alpha (lowercase) + + if (c === 0x21 || c === 0x2d || c === 0x2e || c === 0x5f || c === 0x7e || c >= 0x27 && c <= 0x2a || c >= 0x30 && c <= 0x3a || c >= 0x41 && c <= 0x5a || c >= 0x61 && c <= 0x7a) { + continue; + } + + if (i - lastPos > 0) out += str.slice(lastPos, i); + lastPos = i + 1; // Other ASCII characters + + if (c < 0x80) { + out += hexTable[c]; + continue; + } // Multi-byte characters ... + + + if (c < 0x800) { + out += hexTable[0xc0 | c >> 6] + hexTable[0x80 | c & 0x3f]; + continue; + } + + if (c < 0xd800 || c >= 0xe000) { + out += hexTable[0xe0 | c >> 12] + hexTable[0x80 | c >> 6 & 0x3f] + hexTable[0x80 | c & 0x3f]; + continue; + } // Surrogate pair + + + ++i; + var c2; + if (i < str.length) c2 = str.charCodeAt(i) & 0x3ff;else c2 = 0; + c = 0x10000 + ((c & 0x3ff) << 10 | c2); + out += hexTable[0xf0 | c >> 18] + hexTable[0x80 | c >> 12 & 0x3f] + hexTable[0x80 | c >> 6 & 0x3f] + hexTable[0x80 | c & 0x3f]; + } + + if (lastPos === 0) return str; + if (lastPos < str.length) return out + str.slice(lastPos); + return out; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92ZW5kb3IvbW9uZ29kYlVybC5qcyJdLCJuYW1lcyI6WyJwdW55Y29kZSIsInJlcXVpcmUiLCJleHBvcnRzIiwicGFyc2UiLCJ1cmxQYXJzZSIsInJlc29sdmUiLCJ1cmxSZXNvbHZlIiwicmVzb2x2ZU9iamVjdCIsInVybFJlc29sdmVPYmplY3QiLCJmb3JtYXQiLCJ1cmxGb3JtYXQiLCJVcmwiLCJwcm90b2NvbCIsInNsYXNoZXMiLCJhdXRoIiwiaG9zdCIsInBvcnQiLCJob3N0bmFtZSIsImhhc2giLCJzZWFyY2giLCJxdWVyeSIsInBhdGhuYW1lIiwicGF0aCIsImhyZWYiLCJwcm90b2NvbFBhdHRlcm4iLCJwb3J0UGF0dGVybiIsInNpbXBsZVBhdGhQYXR0ZXJuIiwiaG9zdG5hbWVNYXhMZW4iLCJ1bnNhZmVQcm90b2NvbCIsImphdmFzY3JpcHQiLCJob3N0bGVzc1Byb3RvY29sIiwic2xhc2hlZFByb3RvY29sIiwiaHR0cCIsImh0dHBzIiwiZnRwIiwiZ29waGVyIiwiZmlsZSIsInF1ZXJ5c3RyaW5nIiwidXJsIiwicGFyc2VRdWVyeVN0cmluZyIsInNsYXNoZXNEZW5vdGVIb3N0IiwidSIsInByb3RvdHlwZSIsIlR5cGVFcnJvciIsImhhc0hhc2giLCJzdGFydCIsImVuZCIsInJlc3QiLCJsYXN0UG9zIiwiaSIsImluV3MiLCJzcGxpdCIsImxlbmd0aCIsImNvZGUiLCJjaGFyQ29kZUF0IiwiaXNXcyIsInNsaWNlIiwic2ltcGxlUGF0aCIsImV4ZWMiLCJwcm90byIsImxvd2VyUHJvdG8iLCJ0b0xvd2VyQ2FzZSIsInRlc3QiLCJob3N0RW5kIiwiYXRTaWduIiwibm9uSG9zdCIsImRlY29kZVVSSUNvbXBvbmVudCIsInBhcnNlSG9zdCIsImlwdjZIb3N0bmFtZSIsInJlc3VsdCIsInZhbGlkYXRlSG9zdG5hbWUiLCJ1bmRlZmluZWQiLCJ0b0FTQ0lJIiwicCIsImgiLCJhdXRvRXNjYXBlU3RyIiwicXVlc3Rpb25JZHgiLCJoYXNoSWR4IiwiZmlyc3RJZHgiLCJzIiwic2VsZiIsIm5ld1Jlc3QiLCJvYmoiLCJjYWxsIiwiZW5jb2RlQXV0aCIsImluZGV4T2YiLCJzdHJpbmdpZnkiLCJuZXdQYXRobmFtZSIsInJlcGxhY2UiLCJzb3VyY2UiLCJyZWxhdGl2ZSIsInJlbCIsInRrZXlzIiwiT2JqZWN0Iiwia2V5cyIsInRrIiwidGtleSIsInJrZXlzIiwicmsiLCJya2V5IiwidiIsImsiLCJyZWxQYXRoIiwic2hpZnQiLCJ1bnNoaWZ0Iiwiam9pbiIsImlzU291cmNlQWJzIiwiY2hhckF0IiwiaXNSZWxBYnMiLCJtdXN0RW5kQWJzIiwicmVtb3ZlQWxsRG90cyIsInNyY1BhdGgiLCJwc3ljaG90aWMiLCJwb3AiLCJjb25jYXQiLCJhdXRoSW5Ib3N0IiwibGFzdCIsImhhc1RyYWlsaW5nU2xhc2giLCJ1cCIsInNwbGljZU9uZSIsInN1YnN0ciIsInB1c2giLCJpc0Fic29sdXRlIiwibGlzdCIsImluZGV4IiwibiIsImhleFRhYmxlIiwiQXJyYXkiLCJ0b1N0cmluZyIsInRvVXBwZXJDYXNlIiwic3RyIiwib3V0IiwiYyIsImMyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUEsTUFBTUEsUUFBUSxHQUFHQyxPQUFPLENBQUMsVUFBRCxDQUF4Qjs7QUFFQUMsT0FBTyxDQUFDQyxLQUFSLEdBQWdCQyxRQUFoQjtBQUNBRixPQUFPLENBQUNHLE9BQVIsR0FBa0JDLFVBQWxCO0FBQ0FKLE9BQU8sQ0FBQ0ssYUFBUixHQUF3QkMsZ0JBQXhCO0FBQ0FOLE9BQU8sQ0FBQ08sTUFBUixHQUFpQkMsU0FBakI7QUFFQVIsT0FBTyxDQUFDUyxHQUFSLEdBQWNBLEdBQWQ7O0FBRUEsU0FBU0EsR0FBVCxHQUFlO0FBQ2IsT0FBS0MsUUFBTCxHQUFnQixJQUFoQjtBQUNBLE9BQUtDLE9BQUwsR0FBZSxJQUFmO0FBQ0EsT0FBS0MsSUFBTCxHQUFZLElBQVo7QUFDQSxPQUFLQyxJQUFMLEdBQVksSUFBWjtBQUNBLE9B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QUosQ0FBZUwsQ0FBZixJQUFvQixLQUF6QixDQUFwQixLQUNLb0YsRUFBRSxHQUFHLENBQUw7QUFDTEQsSUFBQUEsQ0FBQyxHQUFHLFdBQVksQ0FBQ0EsQ0FBQyxHQUFHLEtBQUwsS0FBZSxFQUFoQixHQUFzQkMsRUFBakMsQ0FBSjtBQUNBRixJQUFBQSxHQUFHLElBQ0RMLFFBQVEsQ0FBQyxPQUFRTSxDQUFDLElBQUksRUFBZCxDQUFSLEdBQ0FOLFFBQVEsQ0FBQyxPQUFTTSxDQUFDLElBQUksRUFBTixHQUFZLElBQXJCLENBRFIsR0FFQU4sUUFBUSxDQUFDLE9BQVNNLENBQUMsSUFBSSxDQUFOLEdBQVcsSUFBcEIsQ0FGUixHQUdBTixRQUFRLENBQUMsT0FBUU0sQ0FBQyxHQUFHLElBQWIsQ0FKVjtBQUtEOztBQUNELE1BQUlwRixPQUFPLEtBQUssQ0FBaEIsRUFBbUIsT0FBT2tGLEdBQVA7QUFDbkIsTUFBSWxGLE9BQU8sR0FBR2tGLEdBQUcsQ0FBQzlFLE1BQWxCLEVBQTBCLE9BQU8rRSxHQUFHLEdBQUdELEdBQUcsQ0FBQzFFLEtBQUosQ0FBVVIsT0FBVixDQUFiO0FBQzFCLFNBQU9tRixHQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBBIHNsaWdodGx5IHBhdGNoZWQgdmVyc2lvbiBvZiBub2RlJ3MgdXJsIG1vZHVsZSwgd2l0aCBzdXBwb3J0IGZvciBtb25nb2RiOi8vXG4vLyB1cmlzLlxuLy9cbi8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vbm9kZWpzL25vZGUvYmxvYi9tYXN0ZXIvTElDRU5TRSBmb3IgbGljZW5zaW5nXG4vLyBpbmZvcm1hdGlvblxuXG4ndXNlIHN0cmljdCc7XG5cbmNvbnN0IHB1bnljb2RlID0gcmVxdWlyZSgncHVueWNvZGUnKTtcblxuZXhwb3J0cy5wYXJzZSA9IHVybFBhcnNlO1xuZXhwb3J0cy5yZXNvbHZlID0gdXJsUmVzb2x2ZTtcbmV4cG9ydHMucmVzb2x2ZU9iamVjdCA9IHVybFJlc29sdmVPYmplY3Q7XG5leHBvcnRzLmZvcm1hdCA9IHVybEZvcm1hdDtcblxuZXhwb3J0cy5VcmwgPSBVcmw7XG5cbmZ1bmN0aW9uIFVybCgpIHtcbiAgdGhpcy5wcm90b2NvbCA9IG51bGw7XG4gIHRoaXMuc2xhc2hlcyA9IG51bGw7XG4gIHRoaXMuYXV0aCA9IG51bGw7XG4gIHRoaXMuaG9zdCA9IG51bGw7XG4gIHRoaXMucG9ydCA9IG51bGw7XG4gIHRoaXMuaG9zdG5hbWUgPSBudWxsO1xuICB0aGlzLmhhc2ggPSBudWxsO1xuICB0aGlzLnNlYXJjaCA9IG51bGw7XG4gIHRoaXMucXVlcnkgPSBudWxsO1xuICB0aGlzLnBhdGhuYW1lID0gbnVsbDtcbiAgdGhpcy5wYXRoID0gbnVsbDtcbiAgdGhpcy5ocmVmID0gbnVsbDtcbn1cblxuLy8gUmVmZXJlbmNlOiBSRkMgMzk4NiwgUkZDIDE4MDgsIFJGQyAyMzk2XG5cbi8vIGRlZmluZSB0aGVzZSBoZXJlIHNvIGF0IGxlYXN0IHRoZXkgb25seSBoYXZlIHRvIGJlXG4vLyBjb21waWxlZCBvbmNlIG9uIHRoZSBmaXJzdCBtb2R1bGUgbG9hZC5cbmNvbnN0IHByb3RvY29sUGF0dGVybiA9IC9eKFthLXowLTkuKy1dKzopL2k7XG5jb25zdCBwb3J0UGF0dGVybiA9IC86WzAtOV0qJC87XG5cbi8vIFNwZWNpYWwgY2FzZSBmb3IgYSBzaW1wbGUgcGF0aCBVUkxcbmNvbnN0IHNpbXBsZVBhdGhQYXR0ZXJuID0gL14oXFwvXFwvPyg/IVxcLylbXlxcP1xcc10qKShcXD9bXlxcc10qKT8kLztcblxuY29uc3QgaG9zdG5hbWVNYXhMZW4gPSAyNTU7XG4vLyBwcm90b2NvbHMgdGhhdCBjYW4gYWxsb3cgXCJ1bnNhZmVcIiBhbmQgXCJ1bndpc2VcIiBjaGFycy5cbmNvbnN0IHVuc2FmZVByb3RvY29sID0ge1xuICBqYXZhc2NyaXB0OiB0cnVlLFxuICAnamF2YXNjcmlwdDonOiB0cnVlLFxufTtcbi8vIHByb3RvY29scyB0aGF0IG5ldmVyIGhhdmUgYSBob3N0bmFtZS5cbmNvbnN0IGhvc3RsZXNzUHJvdG9jb2wgPSB7XG4gIGphdmFzY3JpcHQ6IHRydWUsXG4gICdqYXZhc2NyaXB0Oic6IHRydWUsXG59O1xuLy8gcHJvdG9jb2xzIHRoYXQgYWx3YXlzIGNvbnRhaW4gYSAvLyBiaXQuXG5jb25zdCBzbGFzaGVkUHJvdG9jb2wgPSB7XG4gIGh0dHA6IHRydWUsXG4gICdodHRwOic6IHRydWUsXG4gIGh0dHBzOiB0cnVlLFxuICAnaHR0cHM6JzogdHJ1ZSxcbiAgZnRwOiB0cnVlLFxuICAnZnRwOic6IHRydWUsXG4gIGdvcGhlcjogdHJ1ZSxcbiAgJ2dvcGhlcjonOiB0cnVlLFxuICBmaWxlOiB0cnVlLFxuICAnZmlsZTonOiB0cnVlLFxufTtcbmNvbnN0IHF1ZXJ5c3RyaW5nID0gcmVxdWlyZSgncXVlcnlzdHJpbmcnKTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cbmZ1bmN0aW9uIHVybFBhcnNlKHVybCwgcGFyc2VRdWVyeVN0cmluZywgc2xhc2hlc0Rlbm90ZUhvc3QpIHtcbiAgaWYgKHVybCBpbnN0YW5jZW9mIFVybCkgcmV0dXJuIHVybDtcblxuICB2YXIgdSA9IG5ldyBVcmwoKTtcbiAgdS5wYXJzZSh1cmwsIHBhcnNlUXVlcnlTdHJpbmcsIHNsYXNoZXNEZW5vdGVIb3N0KTtcbiAgcmV0dXJuIHU7XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5VcmwucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24odXJsLCBwYXJzZVF1ZXJ5U3RyaW5nLCBzbGFzaGVzRGVub3RlSG9zdCkge1xuICBpZiAodHlwZW9mIHVybCAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdQYXJhbWV0ZXIgXCJ1cmxcIiBtdXN0IGJlIGEgc3RyaW5nLCBub3QgJyArIHR5cGVvZiB1cmwpO1xuICB9XG5cbiAgLy8gQ29weSBjaHJvbWUsIElFLCBvcGVyYSBiYWNrc2xhc2gtaGFuZGxpbmcgYmVoYXZpb3IuXG4gIC8vIEJhY2sgc2xhc2hlcyBiZWZvcmUgdGhlIHF1ZXJ5IHN0cmluZyBnZXQgY29udmVydGVkIHRvIGZvcndhcmQgc2xhc2hlc1xuICAvLyBTZWU6IGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD0yNTkxNlxuICB2YXIgaGFzSGFzaCA9IGZhbHNlO1xuICB2YXIgc3RhcnQgPSAtMTtcbiAgdmFyIGVuZCA9IC0xO1xuICB2YXIgcmVzdCA9ICcnO1xuICB2YXIgbGFzdFBvcyA9IDA7XG4gIHZhciBpID0gMDtcbiAgZm9yICh2YXIgaW5XcyA9IGZhbHNlLCBzcGxpdCA9IGZhbHNlOyBpIDwgdXJsLmxlbmd0aDsgKytpKSB7XG4gICAgY29uc3QgY29kZSA9IHVybC5jaGFyQ29kZUF0KGkpO1xuXG4gICAgLy8gRmluZCBmaXJzdCBhbmQgbGFzdCBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXJzIGZvciB0cmltbWluZ1xuICAgIGNvbnN0IGlzV3MgPVxuICAgICAgY29kZSA9PT0gMzIgLyogKi8gfHxcbiAgICAgIGNvZGUgPT09IDkgLypcXHQqLyB8fFxuICAgICAgY29kZSA9PT0gMTMgLypcXHIqLyB8fFxuICAgICAgY29kZSA9PT0gMTAgLypcXG4qLyB8fFxuICAgICAgY29kZSA9PT0gMTIgLypcXGYqLyB8fFxuICAgICAgY29kZSA9PT0gMTYwIC8qXFx1MDBBMCovIHx8XG4gICAgICBjb2RlID09PSA2NTI3OTsgLypcXHVGRUZGKi9cbiAgICBpZiAoc3RhcnQgPT09IC0xKSB7XG4gICAgICBpZiAoaXNXcykgY29udGludWU7XG4gICAgICBsYXN0UG9zID0gc3RhcnQgPSBpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaW5Xcykge1xuICAgICAgICBpZiAoIWlzV3MpIHtcbiAgICAgICAgICBlbmQgPSAtMTtcbiAgICAgICAgICBpbldzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoaXNXcykge1xuICAgICAgICBlbmQgPSBpO1xuICAgICAgICBpbldzID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPbmx5IGNvbnZlcnQgYmFja3NsYXNoZXMgd2hpbGUgd2UgaGF2ZW4ndCBzZWVuIGEgc3BsaXQgY2hhcmFjdGVyXG4gICAgaWYgKCFzcGxpdCkge1xuICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgIGNhc2UgMzU6IC8vICcjJ1xuICAgICAgICAgIGhhc0hhc2ggPSB0cnVlO1xuICAgICAgICAvLyBGYWxsIHRocm91Z2hcbiAgICAgICAgY2FzZSA2MzogLy8gJz8nXG4gICAgICAgICAgc3BsaXQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDkyOiAvLyAnXFxcXCdcbiAgICAgICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSByZXN0ICs9IHVybC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgICByZXN0ICs9ICcvJztcbiAgICAgICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghaGFzSGFzaCAmJiBjb2RlID09PSAzNSAvKiMqLykge1xuICAgICAgaGFzSGFzaCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gQ2hlY2sgaWYgc3RyaW5nIHdhcyBub24tZW1wdHkgKGluY2x1ZGluZyBzdHJpbmdzIHdpdGggb25seSB3aGl0ZXNwYWNlKVxuICBpZiAoc3RhcnQgIT09IC0xKSB7XG4gICAgaWYgKGxhc3RQb3MgPT09IHN0YXJ0KSB7XG4gICAgICAvLyBXZSBkaWRuJ3QgY29udmVydCBhbnkgYmFja3NsYXNoZXNcblxuICAgICAgaWYgKGVuZCA9PT0gLTEpIHtcbiAgICAgICAgaWYgKHN0YXJ0ID09PSAwKSByZXN0ID0gdXJsO1xuICAgICAgICBlbHNlIHJlc3QgPSB1cmwuc2xpY2Uoc3RhcnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdCA9IHVybC5zbGljZShzdGFydCwgZW5kKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGVuZCA9PT0gLTEgJiYgbGFzdFBvcyA8IHVybC5sZW5ndGgpIHtcbiAgICAgIC8vIFdlIGNvbnZlcnRlZCBzb21lIGJhY2tzbGFzaGVzIGFuZCBoYXZlIG9ubHkgcGFydCBvZiB0aGUgZW50aXJlIHN0cmluZ1xuICAgICAgcmVzdCArPSB1cmwuc2xpY2UobGFzdFBvcyk7XG4gICAgfSBlbHNlIGlmIChlbmQgIT09IC0xICYmIGxhc3RQb3MgPCBlbmQpIHtcbiAgICAgIC8vIFdlIGNvbnZlcnRlZCBzb21lIGJhY2tzbGFzaGVzIGFuZCBoYXZlIG9ubHkgcGFydCBvZiB0aGUgZW50aXJlIHN0cmluZ1xuICAgICAgcmVzdCArPSB1cmwuc2xpY2UobGFzdFBvcywgZW5kKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXNsYXNoZXNEZW5vdGVIb3N0ICYmICFoYXNIYXNoKSB7XG4gICAgLy8gVHJ5IGZhc3QgcGF0aCByZWdleHBcbiAgICBjb25zdCBzaW1wbGVQYXRoID0gc2ltcGxlUGF0aFBhdHRlcm4uZXhlYyhyZXN0KTtcbiAgICBpZiAoc2ltcGxlUGF0aCkge1xuICAgICAgdGhpcy5wYXRoID0gcmVzdDtcbiAgICAgIHRoaXMuaHJlZiA9IHJlc3Q7XG4gICAgICB0aGlzLnBhdGhuYW1lID0gc2ltcGxlUGF0aFsxXTtcbiAgICAgIGlmIChzaW1wbGVQYXRoWzJdKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoID0gc2ltcGxlUGF0aFsyXTtcbiAgICAgICAgaWYgKHBhcnNlUXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICB0aGlzLnF1ZXJ5ID0gcXVlcnlzdHJpbmcucGFyc2UodGhpcy5zZWFyY2guc2xpY2UoMSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMucXVlcnkgPSB0aGlzLnNlYXJjaC5zbGljZSgxKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChwYXJzZVF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoID0gJyc7XG4gICAgICAgIHRoaXMucXVlcnkgPSB7fTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfVxuXG4gIHZhciBwcm90byA9IHByb3RvY29sUGF0dGVybi5leGVjKHJlc3QpO1xuICBpZiAocHJvdG8pIHtcbiAgICBwcm90byA9IHByb3RvWzBdO1xuICAgIHZhciBsb3dlclByb3RvID0gcHJvdG8udG9Mb3dlckNhc2UoKTtcbiAgICB0aGlzLnByb3RvY29sID0gbG93ZXJQcm90bztcbiAgICByZXN0ID0gcmVzdC5zbGljZShwcm90by5sZW5ndGgpO1xuICB9XG5cbiAgLy8gZmlndXJlIG91dCBpZiBpdCdzIGdvdCBhIGhvc3RcbiAgLy8gdXNlckBzZXJ2ZXIgaXMgKmFsd2F5cyogaW50ZXJwcmV0ZWQgYXMgYSBob3N0bmFtZSwgYW5kIHVybFxuICAvLyByZXNvbHV0aW9uIHdpbGwgdHJlYXQgLy9mb28vYmFyIGFzIGhvc3Q9Zm9vLHBhdGg9YmFyIGJlY2F1c2UgdGhhdCdzXG4gIC8vIGhvdyB0aGUgYnJvd3NlciByZXNvbHZlcyByZWxhdGl2ZSBVUkxzLlxuICBpZiAoc2xhc2hlc0Rlbm90ZUhvc3QgfHwgcHJvdG8gfHwgL15cXC9cXC9bXkBcXC9dK0BbXkBcXC9dKy8udGVzdChyZXN0KSkge1xuICAgIHZhciBzbGFzaGVzID1cbiAgICAgIHJlc3QuY2hhckNvZGVBdCgwKSA9PT0gNDcgLyovKi8gJiYgcmVzdC5jaGFyQ29kZUF0KDEpID09PSA0NzsgLyovKi9cbiAgICBpZiAoc2xhc2hlcyAmJiAhKHByb3RvICYmIGhvc3RsZXNzUHJvdG9jb2xbcHJvdG9dKSkge1xuICAgICAgcmVzdCA9IHJlc3Quc2xpY2UoMik7XG4gICAgICB0aGlzLnNsYXNoZXMgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmIChcbiAgICAhaG9zdGxlc3NQcm90b2NvbFtwcm90b10gJiZcbiAgICAoc2xhc2hlcyB8fCAocHJvdG8gJiYgIXNsYXNoZWRQcm90b2NvbFtwcm90b10pKVxuICApIHtcbiAgICAvLyB0aGVyZSdzIGEgaG9zdG5hbWUuXG4gICAgLy8gdGhlIGZpcnN0IGluc3RhbmNlIG9mIC8sID8sIDssIG9yICMgZW5kcyB0aGUgaG9zdC5cbiAgICAvL1xuICAgIC8vIElmIHRoZXJlIGlzIGFuIEAgaW4gdGhlIGhvc3RuYW1lLCB0aGVuIG5vbi1ob3N0IGNoYXJzICphcmUqIGFsbG93ZWRcbiAgICAvLyB0byB0aGUgbGVmdCBvZiB0aGUgbGFzdCBAIHNpZ24sIHVubGVzcyBzb21lIGhvc3QtZW5kaW5nIGNoYXJhY3RlclxuICAgIC8vIGNvbWVzICpiZWZvcmUqIHRoZSBALXNpZ24uXG4gICAgLy8gVVJMcyBhcmUgb2Jub3hpb3VzLlxuICAgIC8vXG4gICAgLy8gZXg6XG4gICAgLy8gaHR0cDovL2FAYkBjLyA9PiB1c2VyOmFAYiBob3N0OmNcbiAgICAvLyBodHRwOi8vYUBiP0BjID0+IHVzZXI6YSBob3N0OmIgcGF0aDovP0BjXG5cbiAgICAvLyB2MC4xMiBUT0RPKGlzYWFjcyk6IFRoaXMgaXMgbm90IHF1aXRlIGhvdyBDaHJvbWUgZG9lcyB0aGluZ3MuXG4gICAgLy8gUmV2aWV3IG91ciB0ZXN0IGNhc2UgYWdhaW5zdCBicm93c2VycyBtb3JlIGNvbXByZWhlbnNpdmVseS5cblxuICAgIHZhciBob3N0RW5kID0gLTE7XG4gICAgdmFyIGF0U2lnbiA9IC0xO1xuICAgIHZhciBub25Ib3N0ID0gLTE7XG4gICAgZm9yIChpID0gMDsgaSA8IHJlc3QubGVuZ3RoOyArK2kpIHtcbiAgICAgIHN3aXRjaCAocmVzdC5jaGFyQ29kZUF0KGkpKSB7XG4gICAgICAgIGNhc2UgOTogLy8gJ1xcdCdcbiAgICAgICAgY2FzZSAxMDogLy8gJ1xcbidcbiAgICAgICAgY2FzZSAxMzogLy8gJ1xccidcbiAgICAgICAgY2FzZSAzMjogLy8gJyAnXG4gICAgICAgIGNhc2UgMzQ6IC8vICdcIidcbiAgICAgICAgY2FzZSAzNzogLy8gJyUnXG4gICAgICAgIGNhc2UgMzk6IC8vICdcXCcnXG4gICAgICAgIGNhc2UgNTk6IC8vICc7J1xuICAgICAgICBjYXNlIDYwOiAvLyAnPCdcbiAgICAgICAgY2FzZSA2MjogLy8gJz4nXG4gICAgICAgIGNhc2UgOTI6IC8vICdcXFxcJ1xuICAgICAgICBjYXNlIDk0OiAvLyAnXidcbiAgICAgICAgY2FzZSA5NjogLy8gJ2AnXG4gICAgICAgIGNhc2UgMTIzOiAvLyAneydcbiAgICAgICAgY2FzZSAxMjQ6IC8vICd8J1xuICAgICAgICBjYXNlIDEyNTogLy8gJ30nXG4gICAgICAgICAgLy8gQ2hhcmFjdGVycyB0aGF0IGFyZSBuZXZlciBldmVyIGFsbG93ZWQgaW4gYSBob3N0bmFtZSBmcm9tIFJGQyAyMzk2XG4gICAgICAgICAgaWYgKG5vbkhvc3QgPT09IC0xKSBub25Ib3N0ID0gaTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAzNTogLy8gJyMnXG4gICAgICAgIGNhc2UgNDc6IC8vICcvJ1xuICAgICAgICBjYXNlIDYzOiAvLyAnPydcbiAgICAgICAgICAvLyBGaW5kIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBhbnkgaG9zdC1lbmRpbmcgY2hhcmFjdGVyc1xuICAgICAgICAgIGlmIChub25Ib3N0ID09PSAtMSkgbm9uSG9zdCA9IGk7XG4gICAgICAgICAgaG9zdEVuZCA9IGk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgNjQ6IC8vICdAJ1xuICAgICAgICAgIC8vIEF0IHRoaXMgcG9pbnQsIGVpdGhlciB3ZSBoYXZlIGFuIGV4cGxpY2l0IHBvaW50IHdoZXJlIHRoZVxuICAgICAgICAgIC8vIGF1dGggcG9ydGlvbiBjYW5ub3QgZ28gcGFzdCwgb3IgdGhlIGxhc3QgQCBjaGFyIGlzIHRoZSBkZWNpZGVyLlxuICAgICAgICAgIGF0U2lnbiA9IGk7XG4gICAgICAgICAgbm9uSG9zdCA9IC0xO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKGhvc3RFbmQgIT09IC0xKSBicmVhaztcbiAgICB9XG4gICAgc3RhcnQgPSAwO1xuICAgIGlmIChhdFNpZ24gIT09IC0xKSB7XG4gICAgICB0aGlzLmF1dGggPSBkZWNvZGVVUklDb21wb25lbnQocmVzdC5zbGljZSgwLCBhdFNpZ24pKTtcbiAgICAgIHN0YXJ0ID0gYXRTaWduICsgMTtcbiAgICB9XG4gICAgaWYgKG5vbkhvc3QgPT09IC0xKSB7XG4gICAgICB0aGlzLmhvc3QgPSByZXN0LnNsaWNlKHN0YXJ0KTtcbiAgICAgIHJlc3QgPSAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5ob3N0ID0gcmVzdC5zbGljZShzdGFydCwgbm9uSG9zdCk7XG4gICAgICByZXN0ID0gcmVzdC5zbGljZShub25Ib3N0KTtcbiAgICB9XG5cbiAgICAvLyBwdWxsIG91dCBwb3J0LlxuICAgIHRoaXMucGFyc2VIb3N0KCk7XG5cbiAgICAvLyB3ZSd2ZSBpbmRpY2F0ZWQgdGhhdCB0aGVyZSBpcyBhIGhvc3RuYW1lLFxuICAgIC8vIHNvIGV2ZW4gaWYgaXQncyBlbXB0eSwgaXQgaGFzIHRvIGJlIHByZXNlbnQuXG4gICAgaWYgKHR5cGVvZiB0aGlzLmhvc3RuYW1lICE9PSAnc3RyaW5nJykgdGhpcy5ob3N0bmFtZSA9ICcnO1xuXG4gICAgdmFyIGhvc3RuYW1lID0gdGhpcy5ob3N0bmFtZTtcblxuICAgIC8vIGlmIGhvc3RuYW1lIGJlZ2lucyB3aXRoIFsgYW5kIGVuZHMgd2l0aCBdXG4gICAgLy8gYXNzdW1lIHRoYXQgaXQncyBhbiBJUHY2IGFkZHJlc3MuXG4gICAgdmFyIGlwdjZIb3N0bmFtZSA9XG4gICAgICBob3N0bmFtZS5jaGFyQ29kZUF0KDApID09PSA5MSAvKlsqLyAmJlxuICAgICAgaG9zdG5hbWUuY2hhckNvZGVBdChob3N0bmFtZS5sZW5ndGggLSAxKSA9PT0gOTM7IC8qXSovXG5cbiAgICAvLyB2YWxpZGF0ZSBhIGxpdHRsZS5cbiAgICBpZiAoIWlwdjZIb3N0bmFtZSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gdmFsaWRhdGVIb3N0bmFtZSh0aGlzLCByZXN0LCBob3N0bmFtZSk7XG4gICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHJlc3QgPSByZXN1bHQ7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaG9zdG5hbWUubGVuZ3RoID4gaG9zdG5hbWVNYXhMZW4pIHtcbiAgICAgIHRoaXMuaG9zdG5hbWUgPSAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaG9zdG5hbWVzIGFyZSBhbHdheXMgbG93ZXIgY2FzZS5cbiAgICAgIHRoaXMuaG9zdG5hbWUgPSB0aGlzLmhvc3RuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgaWYgKCFpcHY2SG9zdG5hbWUpIHtcbiAgICAgIC8vIElETkEgU3VwcG9ydDogUmV0dXJucyBhIHB1bnljb2RlZCByZXByZXNlbnRhdGlvbiBvZiBcImRvbWFpblwiLlxuICAgICAgLy8gSXQgb25seSBjb252ZXJ0cyBwYXJ0cyBvZiB0aGUgZG9tYWluIG5hbWUgdGhhdFxuICAgICAgLy8gaGF2ZSBub24tQVNDSUkgY2hhcmFjdGVycywgaS5lLiBpdCBkb2Vzbid0IG1hdHRlciBpZlxuICAgICAgLy8geW91IGNhbGwgaXQgd2l0aCBhIGRvbWFpbiB0aGF0IGFscmVhZHkgaXMgQVNDSUktb25seS5cbiAgICAgIHRoaXMuaG9zdG5hbWUgPSBwdW55Y29kZS50b0FTQ0lJKHRoaXMuaG9zdG5hbWUpO1xuICAgIH1cblxuICAgIHZhciBwID0gdGhpcy5wb3J0ID8gJzonICsgdGhpcy5wb3J0IDogJyc7XG4gICAgdmFyIGggPSB0aGlzLmhvc3RuYW1lIHx8ICcnO1xuICAgIHRoaXMuaG9zdCA9IGggKyBwO1xuXG4gICAgLy8gc3RyaXAgWyBhbmQgXSBmcm9tIHRoZSBob3N0bmFtZVxuICAgIC8vIHRoZSBob3N0IGZpZWxkIHN0aWxsIHJldGFpbnMgdGhlbSwgdGhvdWdoXG4gICAgaWYgKGlwdjZIb3N0bmFtZSkge1xuICAgICAgdGhpcy5ob3N0bmFtZSA9IHRoaXMuaG9zdG5hbWUuc2xpY2UoMSwgLTEpO1xuICAgICAgaWYgKHJlc3RbMF0gIT09ICcvJykge1xuICAgICAgICByZXN0ID0gJy8nICsgcmVzdDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBub3cgcmVzdCBpcyBzZXQgdG8gdGhlIHBvc3QtaG9zdCBzdHVmZi5cbiAgLy8gY2hvcCBvZmYgYW55IGRlbGltIGNoYXJzLlxuICBpZiAoIXVuc2FmZVByb3RvY29sW2xvd2VyUHJvdG9dKSB7XG4gICAgLy8gRmlyc3QsIG1ha2UgMTAwJSBzdXJlIHRoYXQgYW55IFwiYXV0b0VzY2FwZVwiIGNoYXJzIGdldFxuICAgIC8vIGVzY2FwZWQsIGV2ZW4gaWYgZW5jb2RlVVJJQ29tcG9uZW50IGRvZXNuJ3QgdGhpbmsgdGhleVxuICAgIC8vIG5lZWQgdG8gYmUuXG4gICAgY29uc3QgcmVzdWx0ID0gYXV0b0VzY2FwZVN0cihyZXN0KTtcbiAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHJlc3QgPSByZXN1bHQ7XG4gIH1cblxuICB2YXIgcXVlc3Rpb25JZHggPSAtMTtcbiAgdmFyIGhhc2hJZHggPSAtMTtcbiAgZm9yIChpID0gMDsgaSA8IHJlc3QubGVuZ3RoOyArK2kpIHtcbiAgICBjb25zdCBjb2RlID0gcmVzdC5jaGFyQ29kZUF0KGkpO1xuICAgIGlmIChjb2RlID09PSAzNSAvKiMqLykge1xuICAgICAgdGhpcy5oYXNoID0gcmVzdC5zbGljZShpKTtcbiAgICAgIGhhc2hJZHggPSBpO1xuICAgICAgYnJlYWs7XG4gICAgfSBlbHNlIGlmIChjb2RlID09PSA2MyAvKj8qLyAmJiBxdWVzdGlvbklkeCA9PT0gLTEpIHtcbiAgICAgIHF1ZXN0aW9uSWR4ID0gaTtcbiAgICB9XG4gIH1cblxuICBpZiAocXVlc3Rpb25JZHggIT09IC0xKSB7XG4gICAgaWYgKGhhc2hJZHggPT09IC0xKSB7XG4gICAgICB0aGlzLnNlYXJjaCA9IHJlc3Quc2xpY2UocXVlc3Rpb25JZHgpO1xuICAgICAgdGhpcy5xdWVyeSA9IHJlc3Quc2xpY2UocXVlc3Rpb25JZHggKyAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZWFyY2ggPSByZXN0LnNsaWNlKHF1ZXN0aW9uSWR4LCBoYXNoSWR4KTtcbiAgICAgIHRoaXMucXVlcnkgPSByZXN0LnNsaWNlKHF1ZXN0aW9uSWR4ICsgMSwgaGFzaElkeCk7XG4gICAgfVxuICAgIGlmIChwYXJzZVF1ZXJ5U3RyaW5nKSB7XG4gICAgICB0aGlzLnF1ZXJ5ID0gcXVlcnlzdHJpbmcucGFyc2UodGhpcy5xdWVyeSk7XG4gICAgfVxuICB9IGVsc2UgaWYgKHBhcnNlUXVlcnlTdHJpbmcpIHtcbiAgICAvLyBubyBxdWVyeSBzdHJpbmcsIGJ1dCBwYXJzZVF1ZXJ5U3RyaW5nIHN0aWxsIHJlcXVlc3RlZFxuICAgIHRoaXMuc2VhcmNoID0gJyc7XG4gICAgdGhpcy5xdWVyeSA9IHt9O1xuICB9XG5cbiAgdmFyIGZpcnN0SWR4ID1cbiAgICBxdWVzdGlvbklkeCAhPT0gLTEgJiYgKGhhc2hJZHggPT09IC0xIHx8IHF1ZXN0aW9uSWR4IDwgaGFzaElkeClcbiAgICAgID8gcXVlc3Rpb25JZHhcbiAgICAgIDogaGFzaElkeDtcbiAgaWYgKGZpcnN0SWR4ID09PSAtMSkge1xuICAgIGlmIChyZXN0Lmxlbmd0aCA+IDApIHRoaXMucGF0aG5hbWUgPSByZXN0O1xuICB9IGVsc2UgaWYgKGZpcnN0SWR4ID4gMCkge1xuICAgIHRoaXMucGF0aG5hbWUgPSByZXN0LnNsaWNlKDAsIGZpcnN0SWR4KTtcbiAgfVxuICBpZiAoc2xhc2hlZFByb3RvY29sW2xvd2VyUHJvdG9dICYmIHRoaXMuaG9zdG5hbWUgJiYgIXRoaXMucGF0aG5hbWUpIHtcbiAgICB0aGlzLnBhdGhuYW1lID0gJy8nO1xuICB9XG5cbiAgLy8gdG8gc3VwcG9ydCBodHRwLnJlcXVlc3RcbiAgaWYgKHRoaXMucGF0aG5hbWUgfHwgdGhpcy5zZWFyY2gpIHtcbiAgICBjb25zdCBwID0gdGhpcy5wYXRobmFtZSB8fCAnJztcbiAgICBjb25zdCBzID0gdGhpcy5zZWFyY2ggfHwgJyc7XG4gICAgdGhpcy5wYXRoID0gcCArIHM7XG4gIH1cblxuICAvLyBmaW5hbGx5LCByZWNvbnN0cnVjdCB0aGUgaHJlZiBiYXNlZCBvbiB3aGF0IGhhcyBiZWVuIHZhbGlkYXRlZC5cbiAgdGhpcy5ocmVmID0gdGhpcy5mb3JtYXQoKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogaW1wcm92ZSBjb3ZlcmFnZSAqL1xuZnVuY3Rpb24gdmFsaWRhdGVIb3N0bmFtZShzZWxmLCByZXN0LCBob3N0bmFtZSkge1xuICBmb3IgKHZhciBpID0gMCwgbGFzdFBvczsgaSA8PSBob3N0bmFtZS5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjb2RlO1xuICAgIGlmIChpIDwgaG9zdG5hbWUubGVuZ3RoKSBjb2RlID0gaG9zdG5hbWUuY2hhckNvZGVBdChpKTtcbiAgICBpZiAoY29kZSA9PT0gNDYgLyouKi8gfHwgaSA9PT0gaG9zdG5hbWUubGVuZ3RoKSB7XG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSB7XG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDYzKSB7XG4gICAgICAgICAgc2VsZi5ob3N0bmFtZSA9IGhvc3RuYW1lLnNsaWNlKDAsIGxhc3RQb3MgKyA2Myk7XG4gICAgICAgICAgcmV0dXJuICcvJyArIGhvc3RuYW1lLnNsaWNlKGxhc3RQb3MgKyA2MykgKyByZXN0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgKGNvZGUgPj0gNDggLyowKi8gJiYgY29kZSA8PSA1NykgLyo5Ki8gfHxcbiAgICAgIChjb2RlID49IDk3IC8qYSovICYmIGNvZGUgPD0gMTIyKSAvKnoqLyB8fFxuICAgICAgY29kZSA9PT0gNDUgLyotKi8gfHxcbiAgICAgIChjb2RlID49IDY1IC8qQSovICYmIGNvZGUgPD0gOTApIC8qWiovIHx8XG4gICAgICBjb2RlID09PSA0MyAvKisqLyB8fFxuICAgICAgY29kZSA9PT0gOTUgLypfKi8gfHxcbiAgICAgIC8qIEJFR0lOIE1PTkdPIFVSSSBQQVRDSCAqL1xuICAgICAgY29kZSA9PT0gNDQgLyosKi8gfHxcbiAgICAgIGNvZGUgPT09IDU4IC8qOiovIHx8XG4gICAgICAvKiBFTkQgTU9OR08gVVJJIFBBVENIICovXG4gICAgICBjb2RlID4gMTI3XG4gICAgKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgLy8gSW52YWxpZCBob3N0IGNoYXJhY3RlclxuICAgIHNlbGYuaG9zdG5hbWUgPSBob3N0bmFtZS5zbGljZSgwLCBpKTtcbiAgICBpZiAoaSA8IGhvc3RuYW1lLmxlbmd0aCkgcmV0dXJuICcvJyArIGhvc3RuYW1lLnNsaWNlKGkpICsgcmVzdDtcbiAgICBicmVhaztcbiAgfVxufVxuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogaW1wcm92ZSBjb3ZlcmFnZSAqL1xuZnVuY3Rpb24gYXV0b0VzY2FwZVN0cihyZXN0KSB7XG4gIHZhciBuZXdSZXN0ID0gJyc7XG4gIHZhciBsYXN0UG9zID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgLy8gQXV0b21hdGljYWxseSBlc2NhcGUgYWxsIGRlbGltaXRlcnMgYW5kIHVud2lzZSBjaGFyYWN0ZXJzIGZyb20gUkZDIDIzOTZcbiAgICAvLyBBbHNvIGVzY2FwZSBzaW5nbGUgcXVvdGVzIGluIGNhc2Ugb2YgYW4gWFNTIGF0dGFja1xuICAgIHN3aXRjaCAocmVzdC5jaGFyQ29kZUF0KGkpKSB7XG4gICAgICBjYXNlIDk6IC8vICdcXHQnXG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UmVzdCArPSAnJTA5JztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTA6IC8vICdcXG4nXG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UmVzdCArPSAnJTBBJztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTM6IC8vICdcXHInXG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UmVzdCArPSAnJTBEJztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzI6IC8vICcgJ1xuICAgICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICAgIG5ld1Jlc3QgKz0gJyUyMCc7XG4gICAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM0OiAvLyAnXCInXG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UmVzdCArPSAnJTIyJztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzk6IC8vICdcXCcnXG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UmVzdCArPSAnJTI3JztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNjA6IC8vICc8J1xuICAgICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICAgIG5ld1Jlc3QgKz0gJyUzQyc7XG4gICAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDYyOiAvLyAnPidcbiAgICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMCkgbmV3UmVzdCArPSByZXN0LnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgICBuZXdSZXN0ICs9ICclM0UnO1xuICAgICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA5MjogLy8gJ1xcXFwnXG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UmVzdCArPSAnJTVDJztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgOTQ6IC8vICdeJ1xuICAgICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICAgIG5ld1Jlc3QgKz0gJyU1RSc7XG4gICAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDk2OiAvLyAnYCdcbiAgICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMCkgbmV3UmVzdCArPSByZXN0LnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgICBuZXdSZXN0ICs9ICclNjAnO1xuICAgICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAxMjM6IC8vICd7J1xuICAgICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICAgIG5ld1Jlc3QgKz0gJyU3Qic7XG4gICAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDEyNDogLy8gJ3wnXG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UmVzdCArPSAnJTdDJztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTI1OiAvLyAnfSdcbiAgICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMCkgbmV3UmVzdCArPSByZXN0LnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgICBuZXdSZXN0ICs9ICclN0QnO1xuICAgICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBpZiAobGFzdFBvcyA9PT0gMCkgcmV0dXJuO1xuICBpZiAobGFzdFBvcyA8IHJlc3QubGVuZ3RoKSByZXR1cm4gbmV3UmVzdCArIHJlc3Quc2xpY2UobGFzdFBvcyk7XG4gIGVsc2UgcmV0dXJuIG5ld1Jlc3Q7XG59XG5cbi8vIGZvcm1hdCBhIHBhcnNlZCBvYmplY3QgaW50byBhIHVybCBzdHJpbmdcbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5mdW5jdGlvbiB1cmxGb3JtYXQob2JqKSB7XG4gIC8vIGVuc3VyZSBpdCdzIGFuIG9iamVjdCwgYW5kIG5vdCBhIHN0cmluZyB1cmwuXG4gIC8vIElmIGl0J3MgYW4gb2JqLCB0aGlzIGlzIGEgbm8tb3AuXG4gIC8vIHRoaXMgd2F5LCB5b3UgY2FuIGNhbGwgdXJsX2Zvcm1hdCgpIG9uIHN0cmluZ3NcbiAgLy8gdG8gY2xlYW4gdXAgcG90ZW50aWFsbHkgd29ua3kgdXJscy5cbiAgaWYgKHR5cGVvZiBvYmogPT09ICdzdHJpbmcnKSBvYmogPSB1cmxQYXJzZShvYmopO1xuICBlbHNlIGlmICh0eXBlb2Ygb2JqICE9PSAnb2JqZWN0JyB8fCBvYmogPT09IG51bGwpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdQYXJhbWV0ZXIgXCJ1cmxPYmpcIiBtdXN0IGJlIGFuIG9iamVjdCwgbm90ICcgKyBvYmogPT09IG51bGxcbiAgICAgICAgPyAnbnVsbCdcbiAgICAgICAgOiB0eXBlb2Ygb2JqXG4gICAgKTtcbiAgZWxzZSBpZiAoIShvYmogaW5zdGFuY2VvZiBVcmwpKSByZXR1cm4gVXJsLnByb3RvdHlwZS5mb3JtYXQuY2FsbChvYmopO1xuXG4gIHJldHVybiBvYmouZm9ybWF0KCk7XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5VcmwucHJvdG90eXBlLmZvcm1hdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgYXV0aCA9IHRoaXMuYXV0aCB8fCAnJztcbiAgaWYgKGF1dGgpIHtcbiAgICBhdXRoID0gZW5jb2RlQXV0aChhdXRoKTtcbiAgICBhdXRoICs9ICdAJztcbiAgfVxuXG4gIHZhciBwcm90b2NvbCA9IHRoaXMucHJvdG9jb2wgfHwgJyc7XG4gIHZhciBwYXRobmFtZSA9IHRoaXMucGF0aG5hbWUgfHwgJyc7XG4gIHZhciBoYXNoID0gdGhpcy5oYXNoIHx8ICcnO1xuICB2YXIgaG9zdCA9IGZhbHNlO1xuICB2YXIgcXVlcnkgPSAnJztcblxuICBpZiAodGhpcy5ob3N0KSB7XG4gICAgaG9zdCA9IGF1dGggKyB0aGlzLmhvc3Q7XG4gIH0gZWxzZSBpZiAodGhpcy5ob3N0bmFtZSkge1xuICAgIGhvc3QgPVxuICAgICAgYXV0aCArXG4gICAgICAodGhpcy5ob3N0bmFtZS5pbmRleE9mKCc6JykgPT09IC0xXG4gICAgICAgID8gdGhpcy5ob3N0bmFtZVxuICAgICAgICA6ICdbJyArIHRoaXMuaG9zdG5hbWUgKyAnXScpO1xuICAgIGlmICh0aGlzLnBvcnQpIHtcbiAgICAgIGhvc3QgKz0gJzonICsgdGhpcy5wb3J0O1xuICAgIH1cbiAgfVxuXG4gIGlmICh0aGlzLnF1ZXJ5ICE9PSBudWxsICYmIHR5cGVvZiB0aGlzLnF1ZXJ5ID09PSAnb2JqZWN0JylcbiAgICBxdWVyeSA9IHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KTtcblxuICB2YXIgc2VhcmNoID0gdGhpcy5zZWFyY2ggfHwgKHF1ZXJ5ICYmICc/JyArIHF1ZXJ5KSB8fCAnJztcblxuICBpZiAocHJvdG9jb2wgJiYgcHJvdG9jb2wuY2hhckNvZGVBdChwcm90b2NvbC5sZW5ndGggLSAxKSAhPT0gNTggLyo6Ki8pXG4gICAgcHJvdG9jb2wgKz0gJzonO1xuXG4gIHZhciBuZXdQYXRobmFtZSA9ICcnO1xuICB2YXIgbGFzdFBvcyA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0aG5hbWUubGVuZ3RoOyArK2kpIHtcbiAgICBzd2l0Y2ggKHBhdGhuYW1lLmNoYXJDb2RlQXQoaSkpIHtcbiAgICAgIGNhc2UgMzU6IC8vICcjJ1xuICAgICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSBuZXdQYXRobmFtZSArPSBwYXRobmFtZS5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgICAgbmV3UGF0aG5hbWUgKz0gJyUyMyc7XG4gICAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDYzOiAvLyAnPydcbiAgICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMCkgbmV3UGF0aG5hbWUgKz0gcGF0aG5hbWUuc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICAgIG5ld1BhdGhuYW1lICs9ICclM0YnO1xuICAgICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBpZiAobGFzdFBvcyA+IDApIHtcbiAgICBpZiAobGFzdFBvcyAhPT0gcGF0aG5hbWUubGVuZ3RoKVxuICAgICAgcGF0aG5hbWUgPSBuZXdQYXRobmFtZSArIHBhdGhuYW1lLnNsaWNlKGxhc3RQb3MpO1xuICAgIGVsc2UgcGF0aG5hbWUgPSBuZXdQYXRobmFtZTtcbiAgfVxuXG4gIC8vIG9ubHkgdGhlIHNsYXNoZWRQcm90b2NvbHMgZ2V0IHRoZSAvLy4gIE5vdCBtYWlsdG86LCB4bXBwOiwgZXRjLlxuICAvLyB1bmxlc3MgdGhleSBoYWQgdGhlbSB0byBiZWdpbiB3aXRoLlxuICBpZiAoXG4gICAgdGhpcy5zbGFzaGVzIHx8XG4gICAgKCghcHJvdG9jb2wgfHwgc2xhc2hlZFByb3RvY29sW3Byb3RvY29sXSkgJiYgaG9zdCAhPT0gZmFsc2UpXG4gICkge1xuICAgIGhvc3QgPSAnLy8nICsgKGhvc3QgfHwgJycpO1xuICAgIGlmIChwYXRobmFtZSAmJiBwYXRobmFtZS5jaGFyQ29kZUF0KDApICE9PSA0NyAvKi8qLylcbiAgICAgIHBhdGhuYW1lID0gJy8nICsgcGF0aG5hbWU7XG4gIH0gZWxzZSBpZiAoIWhvc3QpIHtcbiAgICBob3N0ID0gJyc7XG4gIH1cblxuICBzZWFyY2ggPSBzZWFyY2gucmVwbGFjZSgnIycsICclMjMnKTtcblxuICBpZiAoaGFzaCAmJiBoYXNoLmNoYXJDb2RlQXQoMCkgIT09IDM1IC8qIyovKSBoYXNoID0gJyMnICsgaGFzaDtcbiAgaWYgKHNlYXJjaCAmJiBzZWFyY2guY2hhckNvZGVBdCgwKSAhPT0gNjMgLyo/Ki8pIHNlYXJjaCA9ICc/JyArIHNlYXJjaDtcblxuICByZXR1cm4gcHJvdG9jb2wgKyBob3N0ICsgcGF0aG5hbWUgKyBzZWFyY2ggKyBoYXNoO1xufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cbmZ1bmN0aW9uIHVybFJlc29sdmUoc291cmNlLCByZWxhdGl2ZSkge1xuICByZXR1cm4gdXJsUGFyc2Uoc291cmNlLCBmYWxzZSwgdHJ1ZSkucmVzb2x2ZShyZWxhdGl2ZSk7XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5VcmwucHJvdG90eXBlLnJlc29sdmUgPSBmdW5jdGlvbihyZWxhdGl2ZSkge1xuICByZXR1cm4gdGhpcy5yZXNvbHZlT2JqZWN0KHVybFBhcnNlKHJlbGF0aXZlLCBmYWxzZSwgdHJ1ZSkpLmZvcm1hdCgpO1xufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cbmZ1bmN0aW9uIHVybFJlc29sdmVPYmplY3Qoc291cmNlLCByZWxhdGl2ZSkge1xuICBpZiAoIXNvdXJjZSkgcmV0dXJuIHJlbGF0aXZlO1xuICByZXR1cm4gdXJsUGFyc2Uoc291cmNlLCBmYWxzZSwgdHJ1ZSkucmVzb2x2ZU9iamVjdChyZWxhdGl2ZSk7XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5VcmwucHJvdG90eXBlLnJlc29sdmVPYmplY3QgPSBmdW5jdGlvbihyZWxhdGl2ZSkge1xuICBpZiAodHlwZW9mIHJlbGF0aXZlID09PSAnc3RyaW5nJykge1xuICAgIHZhciByZWwgPSBuZXcgVXJsKCk7XG4gICAgcmVsLnBhcnNlKHJlbGF0aXZlLCBmYWxzZSwgdHJ1ZSk7XG4gICAgcmVsYXRpdmUgPSByZWw7XG4gIH1cblxuICB2YXIgcmVzdWx0ID0gbmV3IFVybCgpO1xuICB2YXIgdGtleXMgPSBPYmplY3Qua2V5cyh0aGlzKTtcbiAgZm9yICh2YXIgdGsgPSAwOyB0ayA8IHRrZXlzLmxlbmd0aDsgdGsrKykge1xuICAgIHZhciB0a2V5ID0gdGtleXNbdGtdO1xuICAgIHJlc3VsdFt0a2V5XSA9IHRoaXNbdGtleV07XG4gIH1cblxuICAvLyBoYXNoIGlzIGFsd2F5cyBvdmVycmlkZGVuLCBubyBtYXR0ZXIgd2hhdC5cbiAgLy8gZXZlbiBocmVmPVwiXCIgd2lsbCByZW1vdmUgaXQuXG4gIHJlc3VsdC5oYXNoID0gcmVsYXRpdmUuaGFzaDtcblxuICAvLyBpZiB0aGUgcmVsYXRpdmUgdXJsIGlzIGVtcHR5LCB0aGVuIHRoZXJlJ3Mgbm90aGluZyBsZWZ0IHRvIGRvIGhlcmUuXG4gIGlmIChyZWxhdGl2ZS5ocmVmID09PSAnJykge1xuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBocmVmcyBsaWtlIC8vZm9vL2JhciBhbHdheXMgY3V0IHRvIHRoZSBwcm90b2NvbC5cbiAgaWYgKHJlbGF0aXZlLnNsYXNoZXMgJiYgIXJlbGF0aXZlLnByb3RvY29sKSB7XG4gICAgLy8gdGFrZSBldmVyeXRoaW5nIGV4Y2VwdCB0aGUgcHJvdG9jb2wgZnJvbSByZWxhdGl2ZVxuICAgIHZhciBya2V5cyA9IE9iamVjdC5rZXlzKHJlbGF0aXZlKTtcbiAgICBmb3IgKHZhciByayA9IDA7IHJrIDwgcmtleXMubGVuZ3RoOyByaysrKSB7XG4gICAgICB2YXIgcmtleSA9IHJrZXlzW3JrXTtcbiAgICAgIGlmIChya2V5ICE9PSAncHJvdG9jb2wnKSByZXN1bHRbcmtleV0gPSByZWxhdGl2ZVtya2V5XTtcbiAgICB9XG5cbiAgICAvL3VybFBhcnNlIGFwcGVuZHMgdHJhaWxpbmcgLyB0byB1cmxzIGxpa2UgaHR0cDovL3d3dy5leGFtcGxlLmNvbVxuICAgIGlmIChcbiAgICAgIHNsYXNoZWRQcm90b2NvbFtyZXN1bHQucHJvdG9jb2xdICYmXG4gICAgICByZXN1bHQuaG9zdG5hbWUgJiZcbiAgICAgICFyZXN1bHQucGF0aG5hbWVcbiAgICApIHtcbiAgICAgIHJlc3VsdC5wYXRoID0gcmVzdWx0LnBhdGhuYW1lID0gJy8nO1xuICAgIH1cblxuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBpZiAocmVsYXRpdmUucHJvdG9jb2wgJiYgcmVsYXRpdmUucHJvdG9jb2wgIT09IHJlc3VsdC5wcm90b2NvbCkge1xuICAgIC8vIGlmIGl0J3MgYSBrbm93biB1cmwgcHJvdG9jb2wsIHRoZW4gY2hhbmdpbmdcbiAgICAvLyB0aGUgcHJvdG9jb2wgZG9lcyB3ZWlyZCB0aGluZ3NcbiAgICAvLyBmaXJzdCwgaWYgaXQncyBub3QgZmlsZTosIHRoZW4gd2UgTVVTVCBoYXZlIGEgaG9zdCxcbiAgICAvLyBhbmQgaWYgdGhlcmUgd2FzIGEgcGF0aFxuICAgIC8vIHRvIGJlZ2luIHdpdGgsIHRoZW4gd2UgTVVTVCBoYXZlIGEgcGF0aC5cbiAgICAvLyBpZiBpdCBpcyBmaWxlOiwgdGhlbiB0aGUgaG9zdCBpcyBkcm9wcGVkLFxuICAgIC8vIGJlY2F1c2UgdGhhdCdzIGtub3duIHRvIGJlIGhvc3RsZXNzLlxuICAgIC8vIGFueXRoaW5nIGVsc2UgaXMgYXNzdW1lZCB0byBiZSBhYnNvbHV0ZS5cbiAgICBpZiAoIXNsYXNoZWRQcm90b2NvbFtyZWxhdGl2ZS5wcm90b2NvbF0pIHtcbiAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMocmVsYXRpdmUpO1xuICAgICAgZm9yICh2YXIgdiA9IDA7IHYgPCBrZXlzLmxlbmd0aDsgdisrKSB7XG4gICAgICAgIHZhciBrID0ga2V5c1t2XTtcbiAgICAgICAgcmVzdWx0W2tdID0gcmVsYXRpdmVba107XG4gICAgICB9XG4gICAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgcmVzdWx0LnByb3RvY29sID0gcmVsYXRpdmUucHJvdG9jb2w7XG4gICAgaWYgKFxuICAgICAgIXJlbGF0aXZlLmhvc3QgJiZcbiAgICAgICEvXmZpbGU6PyQvLnRlc3QocmVsYXRpdmUucHJvdG9jb2wpICYmXG4gICAgICAhaG9zdGxlc3NQcm90b2NvbFtyZWxhdGl2ZS5wcm90b2NvbF1cbiAgICApIHtcbiAgICAgIGNvbnN0IHJlbFBhdGggPSAocmVsYXRpdmUucGF0aG5hbWUgfHwgJycpLnNwbGl0KCcvJyk7XG4gICAgICB3aGlsZSAocmVsUGF0aC5sZW5ndGggJiYgIShyZWxhdGl2ZS5ob3N0ID0gcmVsUGF0aC5zaGlmdCgpKSk7XG4gICAgICBpZiAoIXJlbGF0aXZlLmhvc3QpIHJlbGF0aXZlLmhvc3QgPSAnJztcbiAgICAgIGlmICghcmVsYXRpdmUuaG9zdG5hbWUpIHJlbGF0aXZlLmhvc3RuYW1lID0gJyc7XG4gICAgICBpZiAocmVsUGF0aFswXSAhPT0gJycpIHJlbFBhdGgudW5zaGlmdCgnJyk7XG4gICAgICBpZiAocmVsUGF0aC5sZW5ndGggPCAyKSByZWxQYXRoLnVuc2hpZnQoJycpO1xuICAgICAgcmVzdWx0LnBhdGhuYW1lID0gcmVsUGF0aC5qb2luKCcvJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdC5wYXRobmFtZSA9IHJlbGF0aXZlLnBhdGhuYW1lO1xuICAgIH1cbiAgICByZXN1bHQuc2VhcmNoID0gcmVsYXRpdmUuc2VhcmNoO1xuICAgIHJlc3VsdC5xdWVyeSA9IHJlbGF0aXZlLnF1ZXJ5O1xuICAgIHJlc3VsdC5ob3N0ID0gcmVsYXRpdmUuaG9zdCB8fCAnJztcbiAgICByZXN1bHQuYXV0aCA9IHJlbGF0aXZlLmF1dGg7XG4gICAgcmVzdWx0Lmhvc3RuYW1lID0gcmVsYXRpdmUuaG9zdG5hbWUgfHwgcmVsYXRpdmUuaG9zdDtcbiAgICByZXN1bHQucG9ydCA9IHJlbGF0aXZlLnBvcnQ7XG4gICAgLy8gdG8gc3VwcG9ydCBodHRwLnJlcXVlc3RcbiAgICBpZiAocmVzdWx0LnBhdGhuYW1lIHx8IHJlc3VsdC5zZWFyY2gpIHtcbiAgICAgIHZhciBwID0gcmVzdWx0LnBhdGhuYW1lIHx8ICcnO1xuICAgICAgdmFyIHMgPSByZXN1bHQuc2VhcmNoIHx8ICcnO1xuICAgICAgcmVzdWx0LnBhdGggPSBwICsgcztcbiAgICB9XG4gICAgcmVzdWx0LnNsYXNoZXMgPSByZXN1bHQuc2xhc2hlcyB8fCByZWxhdGl2ZS5zbGFzaGVzO1xuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICB2YXIgaXNTb3VyY2VBYnMgPSByZXN1bHQucGF0aG5hbWUgJiYgcmVzdWx0LnBhdGhuYW1lLmNoYXJBdCgwKSA9PT0gJy8nO1xuICB2YXIgaXNSZWxBYnMgPVxuICAgIHJlbGF0aXZlLmhvc3QgfHwgKHJlbGF0aXZlLnBhdGhuYW1lICYmIHJlbGF0aXZlLnBhdGhuYW1lLmNoYXJBdCgwKSA9PT0gJy8nKTtcbiAgdmFyIG11c3RFbmRBYnMgPVxuICAgIGlzUmVsQWJzIHx8IGlzU291cmNlQWJzIHx8IChyZXN1bHQuaG9zdCAmJiByZWxhdGl2ZS5wYXRobmFtZSk7XG4gIHZhciByZW1vdmVBbGxEb3RzID0gbXVzdEVuZEFicztcbiAgdmFyIHNyY1BhdGggPSAocmVzdWx0LnBhdGhuYW1lICYmIHJlc3VsdC5wYXRobmFtZS5zcGxpdCgnLycpKSB8fCBbXTtcbiAgdmFyIHJlbFBhdGggPSAocmVsYXRpdmUucGF0aG5hbWUgJiYgcmVsYXRpdmUucGF0aG5hbWUuc3BsaXQoJy8nKSkgfHwgW107XG4gIHZhciBwc3ljaG90aWMgPSByZXN1bHQucHJvdG9jb2wgJiYgIXNsYXNoZWRQcm90b2NvbFtyZXN1bHQucHJvdG9jb2xdO1xuXG4gIC8vIGlmIHRoZSB1cmwgaXMgYSBub24tc2xhc2hlZCB1cmwsIHRoZW4gcmVsYXRpdmVcbiAgLy8gbGlua3MgbGlrZSAuLi8uLiBzaG91bGQgYmUgYWJsZVxuICAvLyB0byBjcmF3bCB1cCB0byB0aGUgaG9zdG5hbWUsIGFzIHdlbGwuICBUaGlzIGlzIHN0cmFuZ2UuXG4gIC8vIHJlc3VsdC5wcm90b2NvbCBoYXMgYWxyZWFkeSBiZWVuIHNldCBieSBub3cuXG4gIC8vIExhdGVyIG9uLCBwdXQgdGhlIGZpcnN0IHBhdGggcGFydCBpbnRvIHRoZSBob3N0IGZpZWxkLlxuICBpZiAocHN5Y2hvdGljKSB7XG4gICAgcmVzdWx0Lmhvc3RuYW1lID0gJyc7XG4gICAgcmVzdWx0LnBvcnQgPSBudWxsO1xuICAgIGlmIChyZXN1bHQuaG9zdCkge1xuICAgICAgaWYgKHNyY1BhdGhbMF0gPT09ICcnKSBzcmNQYXRoWzBdID0gcmVzdWx0Lmhvc3Q7XG4gICAgICBlbHNlIHNyY1BhdGgudW5zaGlmdChyZXN1bHQuaG9zdCk7XG4gICAgfVxuICAgIHJlc3VsdC5ob3N0ID0gJyc7XG4gICAgaWYgKHJlbGF0aXZlLnByb3RvY29sKSB7XG4gICAgICByZWxhdGl2ZS5ob3N0bmFtZSA9IG51bGw7XG4gICAgICByZWxhdGl2ZS5wb3J0ID0gbnVsbDtcbiAgICAgIGlmIChyZWxhdGl2ZS5ob3N0KSB7XG4gICAgICAgIGlmIChyZWxQYXRoWzBdID09PSAnJykgcmVsUGF0aFswXSA9IHJlbGF0aXZlLmhvc3Q7XG4gICAgICAgIGVsc2UgcmVsUGF0aC51bnNoaWZ0KHJlbGF0aXZlLmhvc3QpO1xuICAgICAgfVxuICAgICAgcmVsYXRpdmUuaG9zdCA9IG51bGw7XG4gICAgfVxuICAgIG11c3RFbmRBYnMgPSBtdXN0RW5kQWJzICYmIChyZWxQYXRoWzBdID09PSAnJyB8fCBzcmNQYXRoWzBdID09PSAnJyk7XG4gIH1cblxuICBpZiAoaXNSZWxBYnMpIHtcbiAgICAvLyBpdCdzIGFic29sdXRlLlxuICAgIHJlc3VsdC5ob3N0ID1cbiAgICAgIHJlbGF0aXZlLmhvc3QgfHwgcmVsYXRpdmUuaG9zdCA9PT0gJycgPyByZWxhdGl2ZS5ob3N0IDogcmVzdWx0Lmhvc3Q7XG4gICAgcmVzdWx0Lmhvc3RuYW1lID1cbiAgICAgIHJlbGF0aXZlLmhvc3RuYW1lIHx8IHJlbGF0aXZlLmhvc3RuYW1lID09PSAnJ1xuICAgICAgICA/IHJlbGF0aXZlLmhvc3RuYW1lXG4gICAgICAgIDogcmVzdWx0Lmhvc3RuYW1lO1xuICAgIHJlc3VsdC5zZWFyY2ggPSByZWxhdGl2ZS5zZWFyY2g7XG4gICAgcmVzdWx0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XG4gICAgc3JjUGF0aCA9IHJlbFBhdGg7XG4gICAgLy8gZmFsbCB0aHJvdWdoIHRvIHRoZSBkb3QtaGFuZGxpbmcgYmVsb3cuXG4gIH0gZWxzZSBpZiAocmVsUGF0aC5sZW5ndGgpIHtcbiAgICAvLyBpdCdzIHJlbGF0aXZlXG4gICAgLy8gdGhyb3cgYXdheSB0aGUgZXhpc3RpbmcgZmlsZSwgYW5kIHRha2UgdGhlIG5ldyBwYXRoIGluc3RlYWQuXG4gICAgaWYgKCFzcmNQYXRoKSBzcmNQYXRoID0gW107XG4gICAgc3JjUGF0aC5wb3AoKTtcbiAgICBzcmNQYXRoID0gc3JjUGF0aC5jb25jYXQocmVsUGF0aCk7XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgfSBlbHNlIGlmIChyZWxhdGl2ZS5zZWFyY2ggIT09IG51bGwgJiYgcmVsYXRpdmUuc2VhcmNoICE9PSB1bmRlZmluZWQpIHtcbiAgICAvLyBqdXN0IHB1bGwgb3V0IHRoZSBzZWFyY2guXG4gICAgLy8gbGlrZSBocmVmPSc/Zm9vJy5cbiAgICAvLyBQdXQgdGhpcyBhZnRlciB0aGUgb3RoZXIgdHdvIGNhc2VzIGJlY2F1c2UgaXQgc2ltcGxpZmllcyB0aGUgYm9vbGVhbnNcbiAgICBpZiAocHN5Y2hvdGljKSB7XG4gICAgICByZXN1bHQuaG9zdG5hbWUgPSByZXN1bHQuaG9zdCA9IHNyY1BhdGguc2hpZnQoKTtcbiAgICAgIC8vb2NjYXNpb25hbGx5IHRoZSBhdXRoIGNhbiBnZXQgc3R1Y2sgb25seSBpbiBob3N0XG4gICAgICAvL3RoaXMgZXNwZWNpYWxseSBoYXBwZW5zIGluIGNhc2VzIGxpa2VcbiAgICAgIC8vdXJsLnJlc29sdmVPYmplY3QoJ21haWx0bzpsb2NhbDFAZG9tYWluMScsICdsb2NhbDJAZG9tYWluMicpXG4gICAgICBjb25zdCBhdXRoSW5Ib3N0ID1cbiAgICAgICAgcmVzdWx0Lmhvc3QgJiYgcmVzdWx0Lmhvc3QuaW5kZXhPZignQCcpID4gMFxuICAgICAgICAgID8gcmVzdWx0Lmhvc3Quc3BsaXQoJ0AnKVxuICAgICAgICAgIDogZmFsc2U7XG4gICAgICBpZiAoYXV0aEluSG9zdCkge1xuICAgICAgICByZXN1bHQuYXV0aCA9IGF1dGhJbkhvc3Quc2hpZnQoKTtcbiAgICAgICAgcmVzdWx0Lmhvc3QgPSByZXN1bHQuaG9zdG5hbWUgPSBhdXRoSW5Ib3N0LnNoaWZ0KCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJlc3VsdC5zZWFyY2ggPSByZWxhdGl2ZS5zZWFyY2g7XG4gICAgcmVzdWx0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XG4gICAgLy90byBzdXBwb3J0IGh0dHAucmVxdWVzdFxuICAgIGlmIChyZXN1bHQucGF0aG5hbWUgIT09IG51bGwgfHwgcmVzdWx0LnNlYXJjaCAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0LnBhdGggPVxuICAgICAgICAocmVzdWx0LnBhdGhuYW1lID8gcmVzdWx0LnBhdGhuYW1lIDogJycpICtcbiAgICAgICAgKHJlc3VsdC5zZWFyY2ggPyByZXN1bHQuc2VhcmNoIDogJycpO1xuICAgIH1cbiAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgaWYgKCFzcmNQYXRoLmxlbmd0aCkge1xuICAgIC8vIG5vIHBhdGggYXQgYWxsLiAgZWFzeS5cbiAgICAvLyB3ZSd2ZSBhbHJlYWR5IGhhbmRsZWQgdGhlIG90aGVyIHN0dWZmIGFib3ZlLlxuICAgIHJlc3VsdC5wYXRobmFtZSA9IG51bGw7XG4gICAgLy90byBzdXBwb3J0IGh0dHAucmVxdWVzdFxuICAgIGlmIChyZXN1bHQuc2VhcmNoKSB7XG4gICAgICByZXN1bHQucGF0aCA9ICcvJyArIHJlc3VsdC5zZWFyY2g7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdC5wYXRoID0gbnVsbDtcbiAgICB9XG4gICAgcmVzdWx0LmhyZWYgPSByZXN1bHQuZm9ybWF0KCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIGlmIGEgdXJsIEVORHMgaW4gLiBvciAuLiwgdGhlbiBpdCBtdXN0IGdldCBhIHRyYWlsaW5nIHNsYXNoLlxuICAvLyBob3dldmVyLCBpZiBpdCBlbmRzIGluIGFueXRoaW5nIGVsc2Ugbm9uLXNsYXNoeSxcbiAgLy8gdGhlbiBpdCBtdXN0IE5PVCBnZXQgYSB0cmFpbGluZyBzbGFzaC5cbiAgdmFyIGxhc3QgPSBzcmNQYXRoLnNsaWNlKC0xKVswXTtcbiAgdmFyIGhhc1RyYWlsaW5nU2xhc2ggPVxuICAgICgocmVzdWx0Lmhvc3QgfHwgcmVsYXRpdmUuaG9zdCB8fCBzcmNQYXRoLmxlbmd0aCA+IDEpICYmXG4gICAgICAobGFzdCA9PT0gJy4nIHx8IGxhc3QgPT09ICcuLicpKSB8fFxuICAgIGxhc3QgPT09ICcnO1xuXG4gIC8vIHN0cmlwIHNpbmdsZSBkb3RzLCByZXNvbHZlIGRvdWJsZSBkb3RzIHRvIHBhcmVudCBkaXJcbiAgLy8gaWYgdGhlIHBhdGggdHJpZXMgdG8gZ28gYWJvdmUgdGhlIHJvb3QsIGB1cGAgZW5kcyB1cCA+IDBcbiAgdmFyIHVwID0gMDtcbiAgZm9yICh2YXIgaSA9IHNyY1BhdGgubGVuZ3RoOyBpID49IDA7IGktLSkge1xuICAgIGxhc3QgPSBzcmNQYXRoW2ldO1xuICAgIGlmIChsYXN0ID09PSAnLicpIHtcbiAgICAgIHNwbGljZU9uZShzcmNQYXRoLCBpKTtcbiAgICB9IGVsc2UgaWYgKGxhc3QgPT09ICcuLicpIHtcbiAgICAgIHNwbGljZU9uZShzcmNQYXRoLCBpKTtcbiAgICAgIHVwKys7XG4gICAgfSBlbHNlIGlmICh1cCkge1xuICAgICAgc3BsaWNlT25lKHNyY1BhdGgsIGkpO1xuICAgICAgdXAtLTtcbiAgICB9XG4gIH1cblxuICAvLyBpZiB0aGUgcGF0aCBpcyBhbGxvd2VkIHRvIGdvIGFib3ZlIHRoZSByb290LCByZXN0b3JlIGxlYWRpbmcgLi5zXG4gIGlmICghbXVzdEVuZEFicyAmJiAhcmVtb3ZlQWxsRG90cykge1xuICAgIGZvciAoOyB1cC0tOyB1cCkge1xuICAgICAgc3JjUGF0aC51bnNoaWZ0KCcuLicpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChcbiAgICBtdXN0RW5kQWJzICYmXG4gICAgc3JjUGF0aFswXSAhPT0gJycgJiZcbiAgICAoIXNyY1BhdGhbMF0gfHwgc3JjUGF0aFswXS5jaGFyQXQoMCkgIT09ICcvJylcbiAgKSB7XG4gICAgc3JjUGF0aC51bnNoaWZ0KCcnKTtcbiAgfVxuXG4gIGlmIChoYXNUcmFpbGluZ1NsYXNoICYmIHNyY1BhdGguam9pbignLycpLnN1YnN0cigtMSkgIT09ICcvJykge1xuICAgIHNyY1BhdGgucHVzaCgnJyk7XG4gIH1cblxuICB2YXIgaXNBYnNvbHV0ZSA9XG4gICAgc3JjUGF0aFswXSA9PT0gJycgfHwgKHNyY1BhdGhbMF0gJiYgc3JjUGF0aFswXS5jaGFyQXQoMCkgPT09ICcvJyk7XG5cbiAgLy8gcHV0IHRoZSBob3N0IGJhY2tcbiAgaWYgKHBzeWNob3RpYykge1xuICAgIGlmIChpc0Fic29sdXRlKSB7XG4gICAgICByZXN1bHQuaG9zdG5hbWUgPSByZXN1bHQuaG9zdCA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQuaG9zdG5hbWUgPSByZXN1bHQuaG9zdCA9IHNyY1BhdGgubGVuZ3RoID8gc3JjUGF0aC5zaGlmdCgpIDogJyc7XG4gICAgfVxuICAgIC8vb2NjYXNpb25hbGx5IHRoZSBhdXRoIGNhbiBnZXQgc3R1Y2sgb25seSBpbiBob3N0XG4gICAgLy90aGlzIGVzcGVjaWFsbHkgaGFwcGVucyBpbiBjYXNlcyBsaWtlXG4gICAgLy91cmwucmVzb2x2ZU9iamVjdCgnbWFpbHRvOmxvY2FsMUBkb21haW4xJywgJ2xvY2FsMkBkb21haW4yJylcbiAgICBjb25zdCBhdXRoSW5Ib3N0ID1cbiAgICAgIHJlc3VsdC5ob3N0ICYmIHJlc3VsdC5ob3N0LmluZGV4T2YoJ0AnKSA+IDBcbiAgICAgICAgPyByZXN1bHQuaG9zdC5zcGxpdCgnQCcpXG4gICAgICAgIDogZmFsc2U7XG4gICAgaWYgKGF1dGhJbkhvc3QpIHtcbiAgICAgIHJlc3VsdC5hdXRoID0gYXV0aEluSG9zdC5zaGlmdCgpO1xuICAgICAgcmVzdWx0Lmhvc3QgPSByZXN1bHQuaG9zdG5hbWUgPSBhdXRoSW5Ib3N0LnNoaWZ0KCk7XG4gICAgfVxuICB9XG5cbiAgbXVzdEVuZEFicyA9IG11c3RFbmRBYnMgfHwgKHJlc3VsdC5ob3N0ICYmIHNyY1BhdGgubGVuZ3RoKTtcblxuICBpZiAobXVzdEVuZEFicyAmJiAhaXNBYnNvbHV0ZSkge1xuICAgIHNyY1BhdGgudW5zaGlmdCgnJyk7XG4gIH1cblxuICBpZiAoIXNyY1BhdGgubGVuZ3RoKSB7XG4gICAgcmVzdWx0LnBhdGhuYW1lID0gbnVsbDtcbiAgICByZXN1bHQucGF0aCA9IG51bGw7XG4gIH0gZWxzZSB7XG4gICAgcmVzdWx0LnBhdGhuYW1lID0gc3JjUGF0aC5qb2luKCcvJyk7XG4gIH1cblxuICAvL3RvIHN1cHBvcnQgcmVxdWVzdC5odHRwXG4gIGlmIChyZXN1bHQucGF0aG5hbWUgIT09IG51bGwgfHwgcmVzdWx0LnNlYXJjaCAhPT0gbnVsbCkge1xuICAgIHJlc3VsdC5wYXRoID1cbiAgICAgIChyZXN1bHQucGF0aG5hbWUgPyByZXN1bHQucGF0aG5hbWUgOiAnJykgK1xuICAgICAgKHJlc3VsdC5zZWFyY2ggPyByZXN1bHQuc2VhcmNoIDogJycpO1xuICB9XG4gIHJlc3VsdC5hdXRoID0gcmVsYXRpdmUuYXV0aCB8fCByZXN1bHQuYXV0aDtcbiAgcmVzdWx0LnNsYXNoZXMgPSByZXN1bHQuc2xhc2hlcyB8fCByZWxhdGl2ZS5zbGFzaGVzO1xuICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5VcmwucHJvdG90eXBlLnBhcnNlSG9zdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgaG9zdCA9IHRoaXMuaG9zdDtcbiAgdmFyIHBvcnQgPSBwb3J0UGF0dGVybi5leGVjKGhvc3QpO1xuICBpZiAocG9ydCkge1xuICAgIHBvcnQgPSBwb3J0WzBdO1xuICAgIGlmIChwb3J0ICE9PSAnOicpIHtcbiAgICAgIHRoaXMucG9ydCA9IHBvcnQuc2xpY2UoMSk7XG4gICAgfVxuICAgIGhvc3QgPSBob3N0LnNsaWNlKDAsIGhvc3QubGVuZ3RoIC0gcG9ydC5sZW5ndGgpO1xuICB9XG4gIGlmIChob3N0KSB0aGlzLmhvc3RuYW1lID0gaG9zdDtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5mdW5jdGlvbiBzcGxpY2VPbmUobGlzdCwgaW5kZXgpIHtcbiAgZm9yICh2YXIgaSA9IGluZGV4LCBrID0gaSArIDEsIG4gPSBsaXN0Lmxlbmd0aDsgayA8IG47IGkgKz0gMSwgayArPSAxKVxuICAgIGxpc3RbaV0gPSBsaXN0W2tdO1xuICBsaXN0LnBvcCgpO1xufVxuXG52YXIgaGV4VGFibGUgPSBuZXcgQXJyYXkoMjU2KTtcbmZvciAodmFyIGkgPSAwOyBpIDwgMjU2OyArK2kpXG4gIGhleFRhYmxlW2ldID0gJyUnICsgKChpIDwgMTYgPyAnMCcgOiAnJykgKyBpLnRvU3RyaW5nKDE2KSkudG9VcHBlckNhc2UoKTtcbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5mdW5jdGlvbiBlbmNvZGVBdXRoKHN0cikge1xuICAvLyBmYXN0ZXIgZW5jb2RlVVJJQ29tcG9uZW50IGFsdGVybmF0aXZlIGZvciBlbmNvZGluZyBhdXRoIHVyaSBjb21wb25lbnRzXG4gIHZhciBvdXQgPSAnJztcbiAgdmFyIGxhc3RQb3MgPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjID0gc3RyLmNoYXJDb2RlQXQoaSk7XG5cbiAgICAvLyBUaGVzZSBjaGFyYWN0ZXJzIGRvIG5vdCBuZWVkIGVzY2FwaW5nOlxuICAgIC8vICEgLSAuIF8gflxuICAgIC8vICcgKCApICogOlxuICAgIC8vIGRpZ2l0c1xuICAgIC8vIGFscGhhICh1cHBlcmNhc2UpXG4gICAgLy8gYWxwaGEgKGxvd2VyY2FzZSlcbiAgICBpZiAoXG4gICAgICBjID09PSAweDIxIHx8XG4gICAgICBjID09PSAweDJkIHx8XG4gICAgICBjID09PSAweDJlIHx8XG4gICAgICBjID09PSAweDVmIHx8XG4gICAgICBjID09PSAweDdlIHx8XG4gICAgICAoYyA+PSAweDI3ICYmIGMgPD0gMHgyYSkgfHxcbiAgICAgIChjID49IDB4MzAgJiYgYyA8PSAweDNhKSB8fFxuICAgICAgKGMgPj0gMHg0MSAmJiBjIDw9IDB4NWEpIHx8XG4gICAgICAoYyA+PSAweDYxICYmIGMgPD0gMHg3YSlcbiAgICApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChpIC0gbGFzdFBvcyA+IDApIG91dCArPSBzdHIuc2xpY2UobGFzdFBvcywgaSk7XG5cbiAgICBsYXN0UG9zID0gaSArIDE7XG5cbiAgICAvLyBPdGhlciBBU0NJSSBjaGFyYWN0ZXJzXG4gICAgaWYgKGMgPCAweDgwKSB7XG4gICAgICBvdXQgKz0gaGV4VGFibGVbY107XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBNdWx0aS1ieXRlIGNoYXJhY3RlcnMgLi4uXG4gICAgaWYgKGMgPCAweDgwMCkge1xuICAgICAgb3V0ICs9IGhleFRhYmxlWzB4YzAgfCAoYyA+PiA2KV0gKyBoZXhUYWJsZVsweDgwIHwgKGMgJiAweDNmKV07XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKGMgPCAweGQ4MDAgfHwgYyA+PSAweGUwMDApIHtcbiAgICAgIG91dCArPVxuICAgICAgICBoZXhUYWJsZVsweGUwIHwgKGMgPj4gMTIpXSArXG4gICAgICAgIGhleFRhYmxlWzB4ODAgfCAoKGMgPj4gNikgJiAweDNmKV0gK1xuICAgICAgICBoZXhUYWJsZVsweDgwIHwgKGMgJiAweDNmKV07XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgLy8gU3Vycm9nYXRlIHBhaXJcbiAgICArK2k7XG4gICAgdmFyIGMyO1xuICAgIGlmIChpIDwgc3RyLmxlbmd0aCkgYzIgPSBzdHIuY2hhckNvZGVBdChpKSAmIDB4M2ZmO1xuICAgIGVsc2UgYzIgPSAwO1xuICAgIGMgPSAweDEwMDAwICsgKCgoYyAmIDB4M2ZmKSA8PCAxMCkgfCBjMik7XG4gICAgb3V0ICs9XG4gICAgICBoZXhUYWJsZVsweGYwIHwgKGMgPj4gMTgpXSArXG4gICAgICBoZXhUYWJsZVsweDgwIHwgKChjID4+IDEyKSAmIDB4M2YpXSArXG4gICAgICBoZXhUYWJsZVsweDgwIHwgKChjID4+IDYpICYgMHgzZildICtcbiAgICAgIGhleFRhYmxlWzB4ODAgfCAoYyAmIDB4M2YpXTtcbiAgfVxuICBpZiAobGFzdFBvcyA9PT0gMCkgcmV0dXJuIHN0cjtcbiAgaWYgKGxhc3RQb3MgPCBzdHIubGVuZ3RoKSByZXR1cm4gb3V0ICsgc3RyLnNsaWNlKGxhc3RQb3MpO1xuICByZXR1cm4gb3V0O1xufVxuIl19 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 732200ab88..61dcc9542c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "3.9.0", + "version": "3.9.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -25,9 +25,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", - "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==" + "version": "10.17.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.6.tgz", + "integrity": "sha512-0a2X6cgN3RdPBL2MIlR6Lt0KlM7fOFsutuXcdglcOq6WvLnYXgPQSh0Mx6tO1KCAE8MxbHSOSTWDoUxRq+l3DA==" } } }, @@ -70,9 +70,9 @@ } }, "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { "@babel/highlight": "^7.0.0" @@ -100,6 +100,15 @@ "source-map": "^0.5.0" }, "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, "@babel/generator": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", @@ -186,6 +195,15 @@ "to-fast-properties": "^2.0.0" } }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -210,15 +228,16 @@ } }, "@babel/generator": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", - "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", "dev": true, "requires": { - "@babel/types": "^7.7.2", + "@babel/types": "^7.4.4", "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" }, "dependencies": { "source-map": { @@ -285,6 +304,15 @@ "@babel/types": "^7.7.4" }, "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, "@babel/generator": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", @@ -469,6 +497,15 @@ "@babel/types": "^7.7.4" }, "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, "@babel/generator": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", @@ -573,23 +610,23 @@ } }, "@babel/helper-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", - "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-get-function-arity": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", - "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.0.0" } }, "@babel/helper-hoist-variables": { @@ -834,6 +871,17 @@ "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + } } }, "@babel/types": { @@ -876,6 +924,15 @@ "@babel/types": "^7.7.4" }, "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, "@babel/generator": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", @@ -1020,12 +1077,12 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", - "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.4.4" } }, "@babel/helper-wrap-function": { @@ -1113,6 +1170,17 @@ "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + } } }, "@babel/types": { @@ -1227,6 +1295,17 @@ "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + } } }, "@babel/types": { @@ -1258,9 +1337,9 @@ } }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { "chalk": "^2.0.0", @@ -1269,9 +1348,9 @@ } }, "@babel/parser": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.2.tgz", - "integrity": "sha512-DDaR5e0g4ZTb9aP7cpSZLkACEBdoLGwJDWgHtBhrGX7Q1RjhdoMOfexICj5cqTAtpowjGQWfcvfnQG7G2kAB5w==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -1924,48 +2003,48 @@ } }, "@babel/runtime": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz", - "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", + "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", "requires": { "regenerator-runtime": "^0.13.2" } }, "@babel/runtime-corejs3": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.6.3.tgz", - "integrity": "sha512-933SXHQr7apa95F+3IqkBne8mqOnu1kDh6dnSddC07aW/R51WsOVD7MSczJ6DRpq/L8KLll7TFDxmt30pft44w==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.7.2.tgz", + "integrity": "sha512-odQQZpujq0AHttKrvp4n2KGjK5b5cuq7LeEcsdadwZOemMkmJnlgTXMCf5fIixLLaBxUypwn0krKK51vVMA5cg==", "requires": { "core-js-pure": "^3.0.0", "regenerator-runtime": "^0.13.2" } }, "@babel/template": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", - "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/traverse": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.2.tgz", - "integrity": "sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.11" }, "dependencies": { "debug": { @@ -1980,13 +2059,13 @@ } }, "@babel/types": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.2.tgz", - "integrity": "sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.13", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -2060,6 +2139,23 @@ "parse": "2.8.0" }, "dependencies": { + "@babel/runtime": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz", + "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/runtime-corejs3": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.6.3.tgz", + "integrity": "sha512-933SXHQr7apa95F+3IqkBne8mqOnu1kDh6dnSddC07aW/R51WsOVD7MSczJ6DRpq/L8KLll7TFDxmt30pft44w==", + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.2" + } + }, "parse": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/parse/-/parse-2.8.0.tgz", @@ -2083,11 +2179,11 @@ } }, "@parse/s3-files-adapter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-1.3.0.tgz", - "integrity": "sha512-Sw5P2qLt5wxFv/j8auChfOomZFIZ4jhP5f85qpgOk1OCITFwvd7FWF6Qo3N72Hqn/9MCr76tblb/JBNEU+Qgjw==", + "version": "github:mpatnode/parse-server-s3-adapter#43738f488c6dc1bd76f0646fdc132b37c3613dac", + "from": "github:mpatnode/parse-server-s3-adapter#validate-filename", "requires": { - "aws-sdk": "^2.59.0" + "aws-sdk": "^2.59.0", + "parse": "^2.9.1" } }, "@parse/simple-mailgun-adapter": { @@ -2271,9 +2367,9 @@ "integrity": "sha1-/1QEYtL7TQqIRBzq8n0oewHD2Hg=" }, "@types/koa": { - "version": "2.0.52", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.0.52.tgz", - "integrity": "sha512-cp/GTOhOYwomlSKqEoG0kaVEVJEzP4ojYmfa7EKaGkmkkRwJ4B/1VBLbQZ49Z+WJNvzXejQB/9GIKqMo9XLgFQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.0.tgz", + "integrity": "sha512-Hgx/1/rVlJvqYBrdeCsS7PDiR2qbxlMt1RnmNWD4Uxi5FF9nwkYqIldo7urjc+dfNpk+2NRGcnAYd4L5xEhCcQ==", "requires": { "@types/accepts": "*", "@types/cookies": "*", @@ -2308,9 +2404,9 @@ "dev": true }, "@types/node": { - "version": "12.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.6.tgz", - "integrity": "sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA==" + "version": "8.10.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.40.tgz", + "integrity": "sha512-RRSjdwz63kS4u7edIwJUn8NqKLLQ6LyqF/X4+4jp38MBT3Vwetewi2N4dgJEshLbDwNgOJXNYoOwzVZUSSLhkQ==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -2333,9 +2429,9 @@ } }, "@types/ws": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.3.tgz", - "integrity": "sha512-yBTM0P05Tx9iXGq00BbJPo37ox68R5vaGTXivs6RGh/BQ6QP5zqZDGWdAO6JbRE/iR1l80xeGAwCQS2nMV9S/w==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", "requires": { "@types/node": "*" } @@ -2377,6 +2473,21 @@ "requires": { "mime-types": "~2.1.24", "negotiator": "0.6.2" + }, + "dependencies": { + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + } } }, "acorn": { @@ -2392,9 +2503,9 @@ "dev": true }, "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "requires": { "es6-promisify": "^5.0.0" } @@ -2410,9 +2521,9 @@ } }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz", + "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -2629,15 +2740,28 @@ "apollo-link": "^1.2.13", "apollo-link-http-common": "^0.2.15", "tslib": "^1.9.3" + }, + "dependencies": { + "apollo-link-http-common": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.15.tgz", + "integrity": "sha512-+Heey4S2IPsPyTf8Ag3PugUupASJMW894iVps6hXbvwtg1aHSNMXUYO5VG7iRHkPzqpuzT4HMBanCTXPjtGzxg==", + "dev": true, + "requires": { + "apollo-link": "^1.2.13", + "ts-invariant": "^0.4.0", + "tslib": "^1.9.3" + } + } } }, "apollo-link-http-common": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.15.tgz", - "integrity": "sha512-+Heey4S2IPsPyTf8Ag3PugUupASJMW894iVps6hXbvwtg1aHSNMXUYO5VG7iRHkPzqpuzT4HMBanCTXPjtGzxg==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.14.tgz", + "integrity": "sha512-v6mRU1oN6XuX8beVIRB6OpF4q1ULhSnmy7ScnHnuo1qV6GaFmDcbdvXqxIkAV1Q8SQCo2lsv4HeqJOWhFfApOg==", "dev": true, "requires": { - "apollo-link": "^1.2.13", + "apollo-link": "^1.2.12", "ts-invariant": "^0.4.0", "tslib": "^1.9.3" } @@ -2772,6 +2896,23 @@ "apollo-link": "^1.2.12", "apollo-link-http-common": "^0.2.14", "extract-files": "^5.0.1" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.4.tgz", + "integrity": "sha512-Na84uwyImZZc3FKf4aUF1tysApzwf3p2yuFBIyBfbzT5glzKTdvYI4KVW4kcgjrzoGUjC7w3YyCHcJKaRxsr2Q==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "regenerator-runtime": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==", + "dev": true + } } }, "apollo-utilities": { @@ -2893,9 +3034,9 @@ "optional": true }, "ast-types": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz", - "integrity": "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==" + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.2.tgz", + "integrity": "sha512-8c83xDLJM/dLDyXNLiR6afRRm4dPKN6KAnKqytRK3DBJul9lA+atxdQkNDkSVPdTqea5HiRq3lnnOIZ0MBpvdg==" }, "astral-regex": { "version": "1.0.0", @@ -2904,11 +3045,11 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } }, "async-each": { @@ -2919,9 +3060,9 @@ "optional": true }, "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, "async-retry": { "version": "1.2.3", @@ -2944,9 +3085,9 @@ "optional": true }, "aws-sdk": { - "version": "2.566.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.566.0.tgz", - "integrity": "sha512-AifnTGUUOri1xaOK7UyE4Qol97Cr309SJxA0EKuGBUkCG7KehgPYTMm13JAuXU0lyn7y0X6o1RKvNYeYsZ5DCg==", + "version": "2.580.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.580.0.tgz", + "integrity": "sha512-YUn/LgaSjWuFDCAIOiOvyXbuRpNEzTPLbwRs3GpEmrP1hJrOChXh0p7GH61sTZdeJZarCSETUOWU5ngjpCOjKA==", "requires": { "buffer": "^4.9.1", "events": "^1.1.1", @@ -2981,6 +3122,17 @@ "@babel/types": "^7.0.0", "eslint-visitor-keys": "^1.0.0", "resolve": "^1.12.0" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "babel-plugin-dynamic-import-node": { @@ -3083,14 +3235,6 @@ "requires": { "nan": "2.14.0", "node-pre-gyp": "0.13.0" - }, - "dependencies": { - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "optional": true - } } }, "bcrypt-nodejs": { @@ -3130,9 +3274,9 @@ } }, "bluebird": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", - "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", "dev": true }, "body-parser": { @@ -3152,6 +3296,11 @@ "type-is": "~1.6.17" }, "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -3172,10 +3321,13 @@ "toidentifier": "1.0.0" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ms": { "version": "2.0.0", @@ -3197,6 +3349,11 @@ "iconv-lite": "0.4.24", "unpipe": "1.0.0" } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" } } }, @@ -3263,9 +3420,9 @@ "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==" }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", @@ -3330,9 +3487,9 @@ } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cache-base": { "version": "1.0.1", @@ -3362,6 +3519,30 @@ "make-dir": "^2.0.0", "package-hash": "^3.0.0", "write-file-atomic": "^2.4.2" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } } }, "caller-callsite": { @@ -3403,9 +3584,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001011", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001011.tgz", - "integrity": "sha512-h+Eqyn/YA6o6ZTqpS86PyRmNWOs1r54EBDcd2NTwwfsXQ8re1B38SnB+p2RKF8OUsyEIjeDU8XGec1RGO/wYCg==", + "version": "1.0.30001012", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001012.tgz", + "integrity": "sha512-7RR4Uh04t9K1uYRWzOJmzplgEOAXbfK72oVNokCdMzA67trrhPzy93ahKk1AWHiA0c58tD2P+NHqxrA8FZ+Trg==", "dev": true }, "caseless": { @@ -3443,6 +3624,17 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "chardet": { @@ -3601,12 +3793,6 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -3713,9 +3899,9 @@ "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" }, "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" }, "colorspace": { "version": "1.1.2", @@ -3727,9 +3913,9 @@ } }, "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { "delayed-stream": "~1.0.0" } @@ -3782,15 +3968,9 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, "requires": { "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } } }, "content-type": { @@ -3799,20 +3979,12 @@ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } } }, "cookie": { @@ -3833,14 +4005,14 @@ "optional": true }, "core-js": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.4.1.tgz", - "integrity": "sha512-KX/dnuY/J8FtEwbnrzmAjUYgLqtk+cxM86hfG60LGiW3MmltIc2yAmDgBgEkfm0blZhUrdr1Zd84J2Y14mLxzg==" + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.4.4.tgz", + "integrity": "sha512-vKea1DrcLA80Hrfc7AQgfoGvEaByfR5mH08t+zuWOWY94TFBmabdEL56mUbcijvadG9RxsXR2gUUFrfj4/iTcA==" }, "core-js-compat": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.4.2.tgz", - "integrity": "sha512-W0Aj+LM3EAxxjD0Kp2o4be8UlnxIZHNupBv2znqrheR4aY2nOn91794k/xoSp+SxqqriiZpTsSwBtZr60cbkwQ==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.4.4.tgz", + "integrity": "sha512-hBbxJ6sOkaFSvwAXjJ/t/1usGIPK5gTbtqV8+T+u1pZBkgQ3lDQgAguN1g01PJ0b3eyQxgRIEgxqGoviE1QtIQ==", "dev": true, "requires": { "browserslist": "^4.7.3", @@ -3848,9 +4020,9 @@ } }, "core-js-pure": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.4.0.tgz", - "integrity": "sha512-d49s6GiW3ePYM8vCglfLLo6bueYx+Sff6MYtjohTMSB0AoxVfABXMUSmYHtKAEvW77T9JTKMyHrhE20nZ8gYDA==" + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.4.4.tgz", + "integrity": "sha512-9d1yvRrCdMmO/OtX6/QyEpB0qvUca5Tq7hskGpvuERakgGoG4/PWzwOH09ikpKDWeQ/W2FERSntz8r1x5t6PmA==" }, "core-util-is": { "version": "1.0.2", @@ -3907,6 +4079,13 @@ "log-driver": "^1.2.7", "minimist": "^1.2.0", "request": "^2.86.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } } }, "cp-file": { @@ -3920,6 +4099,30 @@ "nested-error-stacks": "^2.0.0", "pify": "^4.0.1", "safe-buffer": "^5.0.1" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } } }, "cross-env": { @@ -3929,17 +4132,46 @@ "dev": true, "requires": { "cross-spawn": "^7.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.0.tgz", + "integrity": "sha512-6U/8SMK2FBNnB21oQ4+6Nsodxanw1gTkntYA2zBdkFYFu3ZDx65P2ONEXGSvob/QS6REjVHQ9zxzdOafwFdstw==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz", + "integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==", + "dev": true + } } }, "cross-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", - "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } } }, "css-select": { @@ -3983,9 +4215,12 @@ } }, "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.0.tgz", + "integrity": "sha512-YbKCNLPPP4inc0E5If4OaalBc7gpaM2MRv77Pv2VThVComLKfbGYtJcdDCViDyp1Wd4SebhHLz94vp91zbK6bw==", + "requires": { + "@types/node": "^8.0.7" + } }, "date-fns": { "version": "1.30.1", @@ -4244,13 +4479,6 @@ "ast-types": "0.x.x", "escodegen": "1.x.x", "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - } } }, "del": { @@ -4269,6 +4497,12 @@ "slash": "^3.0.0" }, "dependencies": { + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, "rimraf": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", @@ -4342,6 +4576,14 @@ "dev": true, "requires": { "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } } }, "docopt": { @@ -4473,12 +4715,6 @@ "requires": { "pify": "^3.0.0" } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true } } }, @@ -4528,9 +4764,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.311", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.311.tgz", - "integrity": "sha512-7GH6RKCzziLzJ9ejmbiBEdzHZsc6C3eRpav14dmRfTWMpNgMqpP1ukw/FU/Le2fR+ep642naq7a23xNdmh2s+A==", + "version": "1.3.314", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.314.tgz", + "integrity": "sha512-IKDR/xCxKFhPts7h+VaSXS02Z1mznP3fli1BbXWXeN89i2gCzKraU8qLpEid8YzKcmZdZD3Mly3cn5/lY9xsBQ==", "dev": true }, "elegant-spinner": { @@ -4540,9 +4776,9 @@ "dev": true }, "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "enabled": { @@ -4559,9 +4795,9 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -4585,37 +4821,29 @@ "dev": true, "requires": { "is-arrayish": "^0.2.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - } } }, "es-abstract": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", - "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.2.tgz", + "integrity": "sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA==", "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.0", + "has-symbols": "^1.0.1", "is-callable": "^1.1.4", "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", + "object-inspect": "^1.7.0", "object-keys": "^1.1.1", "string.prototype.trimleft": "^2.1.0", "string.prototype.trimright": "^2.1.0" } }, "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -4623,13 +4851,13 @@ } }, "es5-ext": { - "version": "0.10.52", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.52.tgz", - "integrity": "sha512-bWCbE9fbpYQY4CU6hJbJ1vSz70EClMlDgJ7BmwI+zEJhxrwjesZRPglGJlsZhu0334U3hI+gaspwksH9IGD6ag==", + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "requires": { "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.2", + "es6-symbol": "~3.1.3", "next-tick": "~1.0.0" } }, @@ -4663,9 +4891,9 @@ } }, "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" }, "es6-promisify": { "version": "5.0.0", @@ -4744,22 +4972,15 @@ "dev": true }, "escodegen": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", - "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1", "source-map": "~0.6.1" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - } } }, "eslint": { @@ -4807,33 +5028,24 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -4843,6 +5055,12 @@ "ms": "^2.1.1" } }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, "glob-parent": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", @@ -4861,27 +5079,20 @@ "type-fest": "^0.8.1" } }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" } }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -4896,15 +5107,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, @@ -4934,12 +5136,20 @@ "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + } } }, "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true }, "espree": { @@ -4951,12 +5161,20 @@ "acorn": "^7.1.0", "acorn-jsx": "^5.1.0", "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + } } }, "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" }, "esquery": { "version": "1.0.1", @@ -4977,14 +5195,14 @@ } }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "etag": { "version": "1.8.1", @@ -5038,53 +5256,13 @@ "strip-eof": "^1.0.0" }, "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { - "isexe": "^2.0.0" + "pump": "^3.0.0" } } } @@ -5181,6 +5359,14 @@ "vary": "~1.1.2" }, "dependencies": { + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -5199,17 +5385,17 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" } } }, "ext": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.2.0.tgz", - "integrity": "sha512-0ccUQK/9e3NreLFg6K6np8aPyRgwycx+oFGtfx1dSp7Wj00Ozw9r05FgBRlzjf2XBM7LAzwgLyDscRrtSU91hA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.2.1.tgz", + "integrity": "sha512-x+OKKC57tNiLhDW26UmWtvQBpvO+2wxdC/A0jP7RkmjAc4gze9/U98hQyIYJUzo9A+o9ntMHpC+LH3pWMSbrVQ==", "dev": true, "requires": { "type": "^2.0.0" @@ -5279,6 +5465,17 @@ "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "extglob": { @@ -5446,9 +5643,9 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" }, "fastq": { "version": "1.6.0", @@ -5611,6 +5808,16 @@ "path-exists": "^3.0.0" } }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -5626,6 +5833,12 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -5634,6 +5847,12 @@ "requires": { "find-up": "^3.0.0" } + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true } } }, @@ -5662,17 +5881,6 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "flatted": { @@ -5731,15 +5939,6 @@ "pseudomap": "^1.0.2", "yallist": "^2.1.2" } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, @@ -5757,6 +5956,17 @@ "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + } } }, "forwarded": { @@ -5799,6 +6009,14 @@ "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + } } }, "fs-minipass": { @@ -6398,6 +6616,11 @@ "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" } } }, @@ -6454,14 +6677,11 @@ "which": "^1.1.1" }, "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true } } }, @@ -6487,39 +6707,44 @@ "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", "dev": true, "requires": { "pump": "^3.0.0" } }, "get-uri": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", - "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz", + "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==", "requires": { - "data-uri-to-buffer": "1", - "debug": "2", + "data-uri-to-buffer": "2", + "debug": "4", "extend": "~3.0.2", "file-uri-to-path": "1", "ftp": "~0.3.10", - "readable-stream": "2" + "readable-stream": "3" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } } } }, @@ -6539,9 +6764,9 @@ } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6575,9 +6800,9 @@ } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", "dev": true }, "globby": { @@ -6652,9 +6877,9 @@ } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, "graceful-readlink": { @@ -6720,6 +6945,30 @@ "fs-capacitor": "^2.0.4", "http-errors": "^1.7.3", "object-path": "^0.11.4" + }, + "dependencies": { + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } } }, "growl": { @@ -6728,9 +6977,9 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, "handlebars": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz", - "integrity": "sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -6783,9 +7032,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-to-string-tag-x": { "version": "1.4.1", @@ -6846,9 +7095,9 @@ } }, "hosted-git-info": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "htmlparser2": { @@ -6879,15 +7128,14 @@ } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" } }, "http-proxy-agent": { @@ -6925,11 +7173,11 @@ } }, "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "requires": { - "agent-base": "^4.3.0", + "agent-base": "^4.1.0", "debug": "^3.1.0" } }, @@ -6961,9 +7209,9 @@ } }, "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -7033,9 +7281,9 @@ } }, "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", @@ -7069,6 +7317,12 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -7130,6 +7384,12 @@ "loose-envify": "^1.0.0" } }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -7163,9 +7423,10 @@ } }, "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true }, "is-binary-path": { "version": "1.0.1", @@ -7297,6 +7558,12 @@ "requires": { "escape-string-regexp": "^1.0.5" } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true } } }, @@ -7409,11 +7676,11 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "^1.0.1" } }, "is-typedarray": { @@ -7498,6 +7765,28 @@ "supports-color": "^6.1.0" }, "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -7530,6 +7819,28 @@ "requires": { "ms": "^2.1.1" } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true } } }, @@ -7565,6 +7876,22 @@ "requires": { "glob": "^7.1.4", "jasmine-core": "~3.5.0" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "jasmine-core": { @@ -7597,6 +7924,13 @@ "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + } } }, "js2xmlparser": { @@ -7705,6 +8039,14 @@ "dev": true, "requires": { "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } } }, "jsonfile": { @@ -7734,9 +8076,9 @@ }, "dependencies": { "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" } } }, @@ -7800,6 +8142,15 @@ "colornames": "^1.1.1" } }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, "lcov-parse": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", @@ -7911,6 +8262,17 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -7946,15 +8308,6 @@ "to-regex-range": "^5.0.1" } }, - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -7992,6 +8345,27 @@ "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8000,6 +8374,15 @@ "requires": { "is-number": "^7.0.0" } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -8093,12 +8476,6 @@ "requires": { "chalk": "^1.0.0" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, @@ -8169,14 +8546,6 @@ "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } } }, "locate-path": { @@ -8449,9 +8818,9 @@ }, "dependencies": { "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" } } }, @@ -8521,6 +8890,12 @@ "semver": "^5.6.0" }, "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -8534,6 +8909,15 @@ "resolved": "https://registry.npmjs.org/manakin/-/manakin-0.5.2.tgz", "integrity": "sha512-pfDSB7QYoVg0Io4KMV9hhPoXpj6p0uBscgtyUSKCOFZe8bqgbpStfgnKIbF/ulnr6U3ICu4OqdyxAqBgOhZwBQ==" }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -8565,9 +8949,9 @@ } }, "markdown-it-anchor": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz", - "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.4.tgz", + "integrity": "sha512-n8zCGjxA3T+Mx1pG8HEgbJbkB8JFUuRkeTZQuIM8iPY6oQ8sWOPRZJDFC9a/pNg2QkHEjjGkhBEl/RSyzaDZ3A==", "dev": true }, "marked": { @@ -8587,6 +8971,25 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + } + } + }, "memoizee": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", @@ -8676,16 +9079,16 @@ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" }, "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", "requires": { - "mime-db": "1.40.0" + "mime-db": "~1.38.0" } }, "mimic-fn": { @@ -8709,9 +9112,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { "version": "2.9.0", @@ -8767,15 +9170,8 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } + "requires": { + "minimist": "0.0.8" } }, "moment": { @@ -8833,6 +9229,12 @@ "ms": "2.0.0" } }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -8874,6 +9276,12 @@ "ms": "2.0.0" } }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -8924,6 +9332,21 @@ "requires": { "ms": "^2.1.1" } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -8954,12 +9377,6 @@ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, "mkdirp": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", @@ -9035,6 +9452,12 @@ "graceful-fs": "^4.1.9" } }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -9108,9 +9531,9 @@ } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "mute-stream": { "version": "0.0.8", @@ -9157,7 +9580,6 @@ "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, "optional": true }, "nanomatch": { @@ -9322,9 +9744,9 @@ }, "dependencies": { "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true } } @@ -9349,14 +9771,6 @@ "requires": { "config-chain": "^1.1.11", "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } } }, "npm-packlist": { @@ -9376,14 +9790,6 @@ "dev": true, "requires": { "path-key": "^2.0.0" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - } } }, "npmlog": { @@ -9463,6 +9869,16 @@ "path-exists": "^3.0.0" } }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -9478,11 +9894,23 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true } } }, @@ -9536,9 +9964,9 @@ "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==" }, "object-inspect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", - "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" }, "object-keys": { "version": "1.1.1", @@ -9628,9 +10056,9 @@ "dev": true }, "optimism": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.10.3.tgz", - "integrity": "sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw==", + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.10.2.tgz", + "integrity": "sha512-zPfBIxFFWMmQboM9+Z4MSJqc1PXp82v1PFq/GfQaufI69mHKlup7ykGNnfuGIGssXJQkmhSodQ/k9EWwjd8O8A==", "dev": true, "requires": { "@wry/context": "^0.4.0" @@ -9646,25 +10074,25 @@ "wordwrap": "~0.0.2" }, "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true } } }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "requires": { "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", + "fast-levenshtein": "~2.0.4", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "wordwrap": "~1.0.0" } }, "os-homedir": { @@ -9672,6 +10100,17 @@ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -9693,6 +10132,12 @@ "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, "p-event": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", @@ -9708,10 +10153,16 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -9751,47 +10202,18 @@ "dev": true }, "pac-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", - "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", + "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", "requires": { "agent-base": "^4.2.0", - "debug": "^4.1.1", + "debug": "^3.1.0", "get-uri": "^2.0.0", "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", + "https-proxy-agent": "^2.2.1", "pac-resolver": "^3.0.0", "raw-body": "^2.2.0", "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - } } }, "pac-resolver": { @@ -9842,25 +10264,6 @@ "uuid": "3.3.3", "ws": "7.2.0", "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", - "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", - "requires": { - "regenerator-runtime": "^0.13.2" - } - }, - "@babel/runtime-corejs3": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.7.2.tgz", - "integrity": "sha512-odQQZpujq0AHttKrvp4n2KGjK5b5cuq7LeEcsdadwZOemMkmJnlgTXMCf5fIixLLaBxUypwn0krKK51vVMA5cg==", - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.2" - } - } } }, "parse-json": { @@ -9904,9 +10307,9 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz", - "integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { @@ -9936,10 +10339,13 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } }, "pend": { "version": "1.2.0", @@ -10032,9 +10438,9 @@ "dev": true }, "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "pinkie": { @@ -10134,9 +10540,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { "version": "2.0.3", @@ -10213,9 +10619,9 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" }, "pump": { "version": "3.0.0", @@ -10248,13 +10654,13 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", "unpipe": "1.0.0" } }, @@ -10268,6 +10674,14 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } } }, "read-pkg": { @@ -10346,21 +10760,6 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -10386,13 +10785,6 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } } }, "readdirp": { @@ -10418,9 +10810,9 @@ } }, "redis-commands": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", - "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", + "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==" }, "redis-parser": { "version": "2.6.0", @@ -10576,6 +10968,11 @@ "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" } } }, @@ -10601,9 +10998,9 @@ }, "dependencies": { "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" } } }, @@ -10617,9 +11014,9 @@ } }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -10666,9 +11063,9 @@ "dev": true }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "requires": { "glob": "^7.1.3" } @@ -10704,9 +11101,9 @@ } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-json-stringify": { "version": "1.2.0", @@ -10810,15 +11207,27 @@ } } }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" } } }, @@ -10864,9 +11273,9 @@ } }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "sha.js": { "version": "2.4.11", @@ -10878,18 +11287,18 @@ } }, "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { @@ -10903,6 +11312,13 @@ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } } }, "slash": { @@ -10931,9 +11347,9 @@ } }, "smart-buffer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", - "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==" }, "snapdragon": { "version": "0.8.2", @@ -11077,31 +11493,21 @@ } }, "socks": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.3.tgz", + "integrity": "sha512-+2r83WaRT3PXYoO/1z+RDEBE7Z2f9YcdQnJ0K/ncXXbV5gJ6wYfNAebYFYiiUjM6E4JyXnPY8cimwyvFYHVUUA==", "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" + "ip": "^1.1.5", + "smart-buffer": "4.0.2" } }, "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", + "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "requires": { - "es6-promisify": "^5.0.0" - } - } + "agent-base": "~4.2.0", + "socks": "~2.2.0" } }, "sort-keys": { @@ -11159,9 +11565,9 @@ } }, "spawn-wrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", - "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", + "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", "dev": true, "requires": { "foreground-child": "^1.5.6", @@ -11170,17 +11576,6 @@ "rimraf": "^2.6.2", "signal-exit": "^3.0.2", "which": "^1.3.0" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "spdx-correct": { @@ -11210,9 +11605,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, "spex": { @@ -11337,13 +11732,6 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } } }, "stringify-object": { @@ -11430,13 +11818,10 @@ } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true }, "symbol-observable": { "version": "1.2.0", @@ -11455,18 +11840,24 @@ "string-width": "^3.0.0" }, "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -11739,6 +12130,12 @@ "escape-string-regexp": "^1.0.2" } }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -11753,9 +12150,9 @@ } }, "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tsscmp": { "version": "1.0.6", @@ -11812,6 +12209,21 @@ "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.24" + }, + "dependencies": { + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + } } }, "uc.micro": { @@ -11821,20 +12233,20 @@ "dev": true }, "uglify-js": { - "version": "3.6.8", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.8.tgz", - "integrity": "sha512-XhHJ3S3ZyMwP8kY1Gkugqx3CJh2C3O0y8NPiSxtm1tyD/pktLAkFZsFGpuNfTZddKDQ/bbDBLAd2YyA1pbi8HQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, "optional": true, "requires": { - "commander": "~2.20.3", + "commander": "~2.20.0", "source-map": "~0.6.1" }, "dependencies": { "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true, "optional": true } @@ -12115,9 +12527,9 @@ } }, "which": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.1.tgz", - "integrity": "sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -12219,13 +12631,13 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true }, "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "wrap-ansi": { "version": "3.0.1", @@ -12329,11 +12741,6 @@ "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -12351,21 +12758,22 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.0" }, "dependencies": { "ansi-regex": { @@ -12374,12 +12782,6 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", diff --git a/package.json b/package.json index 60e7cd79df..426c1437c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "3.9.0", + "version": "3.9.1", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { @@ -22,7 +22,7 @@ "@apollographql/graphql-playground-html": "1.6.24", "@parse/fs-files-adapter": "1.0.1", "@parse/push-adapter": "3.2.0", - "@parse/s3-files-adapter": "1.3.0", + "@parse/s3-files-adapter": "github:mpatnode/parse-server-s3-adapter#validate-filename", "@parse/simple-mailgun-adapter": "1.1.0", "apollo-server-express": "2.9.12", "bcryptjs": "2.4.3", diff --git a/src/Controllers/FilesController.js b/src/Controllers/FilesController.js index 4d2b60ed1b..461fa229a9 100644 --- a/src/Controllers/FilesController.js +++ b/src/Controllers/FilesController.js @@ -4,6 +4,7 @@ import AdaptableController from './AdaptableController'; import { validateFilename, FilesAdapter } from '../Adapters/Files/FilesAdapter'; import path from 'path'; import mime from 'mime'; +const Parse = require('parse').Parse; const legacyFilesRegex = new RegExp( '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}-.*' @@ -98,7 +99,11 @@ export class FilesController extends AdaptableController { validateFilename(filename) { if (typeof this.adapter.validateFilename === 'function') { - return this.adapter.validateFilename(filename); + const error = this.adapter.validateFilename(filename); + if (typeof error !== 'string') { + return error; + } + return new Parse.Error(Parse.Error.INVALID_FILE_NAME, error); } return validateFilename(filename); }