diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 0000000000..9e9c19e399 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,51 @@ +--- +name: Report an issue +about: Report an issue on parse-server + +--- + +We use GitHub Issues for bugs. + +If you have a non-bug question, ask on Stack Overflow or Server Fault: +- https://stackoverflow.com/questions/tagged/parse.com +- https://serverfault.com/tags/parse + +If you have a vulnerability disclosure, please follow our policy available here https://github.com/parse-community/parse-server/blob/master/SECURITY.md + +You may also search through existing issues before opening a new one: https://github.com/parse-community/parse-server/issues?utf8=%E2%9C%93&q=is%3Aissue + +--- Please use this template. If you don't use this template, your issue may be closed without comment. --- + +### Issue Description + +Describe your issue in as much detail as possible. + +### Steps to reproduce + +Please include a detailed list of steps that reproduce the issue. Include curl commands when applicable. + +#### Expected Results + +What you expected to happen. + +#### Actual Outcome + +What is happening instead. + +### Environment Setup + +- **Server** + - parse-server version (Be specific! Don't say 'latest'.) : [FILL THIS OUT] + - Operating System: [FILL THIS OUT] + - Hardware: [FILL THIS OUT] + - Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): [FILL THIS OUT] + +- **Database** + - MongoDB version: [FILL THIS OUT] + - Storage engine: [FILL THIS OUT] + - Hardware: [FILL THIS OUT] + - Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): [FILL THIS OUT] + +### Logs/Trace + +Include all relevant logs. You can turn on additional logging by configuring VERBOSE=1 in your environment. diff --git a/.gitignore b/.gitignore index e4e19156c2..99c8a1cd56 100644 --- a/.gitignore +++ b/.gitignore @@ -45,7 +45,7 @@ node_modules .vscode # Babel.js -lib/ +#lib/ # cache folder .cache @@ -57,5 +57,8 @@ lib/ # Folder created by FileSystemAdapter /files +# Merge files +*.orig + # Redis Dump dump.rdb 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..1145b1e4eb --- /dev/null +++ b/lib/Adapters/Auth/gcenter.js @@ -0,0 +1,126 @@ +"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 = Buffer.alloc(8); + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2djZW50ZXIuanMiXSwibmFtZXMiOlsiUGFyc2UiLCJyZXF1aXJlIiwiY3J5cHRvIiwiaHR0cHMiLCJ1cmwiLCJjYWNoZSIsInZlcmlmeVB1YmxpY0tleVVybCIsInB1YmxpY0tleVVybCIsInBhcnNlZFVybCIsInBhcnNlIiwicHJvdG9jb2wiLCJob3N0bmFtZVBhcnRzIiwiaG9zdG5hbWUiLCJzcGxpdCIsImxlbmd0aCIsImRvbWFpblBhcnRzIiwic2xpY2UiLCJkb21haW4iLCJqb2luIiwiY29udmVydFg1MDlDZXJ0VG9QRU0iLCJYNTA5Q2VydCIsInBlbVByZUZpeCIsInBlbVBvc3RGaXgiLCJiYXNlNjQiLCJjZXJ0Qm9keSIsIm1hdGNoIiwiUmVnRXhwIiwiZ2V0QXBwbGVDZXJ0aWZpY2F0ZSIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZ2V0IiwicmVzIiwiZGF0YSIsIm9uIiwiY2h1bmsiLCJ0b1N0cmluZyIsImNlcnQiLCJoZWFkZXJzIiwiZXhwaXJlIiwic2V0VGltZW91dCIsInBhcnNlSW50IiwiY29udmVydFRpbWVzdGFtcFRvQmlnRW5kaWFuIiwidGltZXN0YW1wIiwiYnVmZmVyIiwiQnVmZmVyIiwiYWxsb2MiLCJoaWdoIiwibG93Iiwid3JpdGVVSW50MzJCRSIsInZlcmlmeVNpZ25hdHVyZSIsInB1YmxpY0tleSIsImF1dGhEYXRhIiwidmVyaWZpZXIiLCJjcmVhdGVWZXJpZnkiLCJ1cGRhdGUiLCJwbGF5ZXJJZCIsImJ1bmRsZUlkIiwic2FsdCIsInZlcmlmeSIsInNpZ25hdHVyZSIsInZhbGlkYXRlQXV0aERhdGEiLCJpZCIsInZhbGlkYXRlQXBwSWQiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7Ozs7Ozs7QUFhQSxNQUFNO0FBQUVBLEVBQUFBO0FBQUYsSUFBWUMsT0FBTyxDQUFDLFlBQUQs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QWdCSCxRQUFRLENBQUNNLElBQXpCLEVBQStCLFFBQS9COztBQUVBLE1BQUksQ0FBQ0wsUUFBUSxDQUFDTSxNQUFULENBQWdCUixTQUFoQixFQUEyQkMsUUFBUSxDQUFDUSxTQUFwQyxFQUErQyxRQUEvQyxDQUFMLEVBQStEO0FBQzdELFVBQU0sSUFBSTlELEtBQUssQ0FBQzRCLEtBQVYsQ0FDSjVCLEtBQUssQ0FBQzRCLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix1Q0FGSSxDQUFOO0FBSUQ7QUFDRixDLENBRUQ7OztBQUNBLGVBQWVrQyxnQkFBZixDQUFnQ1QsUUFBaEMsRUFBMEM7QUFDeEMsTUFBSSxDQUFDQSxRQUFRLENBQUNVLEVBQWQsRUFBa0I7QUFDaEIsVUFBTSxJQUFJaEUsS0FBSyxDQUFDNEIsS0FBVixDQUNKNUIsS0FBSyxDQUFDNEIsS0FBTixDQUFZQyxnQkFEUixFQUVKLHlDQUZJLENBQU47QUFJRDs7QUFDRHlCLEVBQUFBLFFBQVEsQ0FBQ0ksUUFBVCxHQUFvQkosUUFBUSxDQUFDVSxFQUE3QjtBQUNBLFFBQU1YLFNBQVMsR0FBRyxNQUFNMUIsbUJBQW1CLENBQUMyQixRQUFRLENBQUMvQyxZQUFWLENBQTNDO0FBQ0EsU0FBTzZDLGVBQWUsQ0FBQ0MsU0FBRCxFQUFZQyxRQUFaLENBQXRCO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTVyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9uQyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNEOztBQUVEbUMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZGLEVBQUFBLGFBRGU7QUFFZkYsRUFBQUE7QUFGZSxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8qIEFwcGxlIEdhbWUgQ2VudGVyIEF1dGhcbmh0dHBzOi8vZGV2ZWxvcGVyLmFwcGxlLmNvbS9kb2N1bWVudGF0aW9uL2dhbWVraXQvZ2tsb2NhbHBsYXllci8xNTE1NDA3LWdlbmVyYXRlaWRlbnRpdHl2ZXJpZmljYXRpb25zaWduI2Rpc2N1c3Npb25cblxuY29uc3QgYXV0aERhdGEgPSB7XG4gIHB1YmxpY0tleVVybDogJ2h0dHBzOi8vdmFsaWQuYXBwbGUuY29tL3B1YmxpYy90aW1lb3V0LmNlcicsXG4gIHRpbWVzdGFtcDogMTQ2MDk4MTQyMTMwMyxcbiAgc2lnbmF0dXJlOiAnUG9Ed2YzOURDTjQ2NEI0OWpKQ1UwZDlZMEonLFxuICBzYWx0OiAnc2FsdFNUPT0nLFxuICBidW5kbGVJZDogJ2NvbS52YWxpZC5hcHAnXG4gIGlkOiAncGxheWVySWQnLFxufTtcbiovXG5cbmNvbnN0IHsgUGFyc2UgfSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKTtcbmNvbnN0IGNyeXB0byA9IHJlcXVpcmUoJ2NyeXB0bycpO1xuY29uc3QgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xuY29uc3QgdXJsID0gcmVxdWlyZSgndXJsJyk7XG5cbmNvbnN0IGNhY2hlID0ge307IC8vIChwdWJsaWNLZXkgLT4gY2VydCkgY2FjaGVcblxuZnVuY3Rpb24gdmVyaWZ5UHVibGljS2V5VXJsKHB1YmxpY0tleVVybCkge1xuICBjb25zdCBwYXJzZWRVcmwgPSB1cmwucGFyc2UocHVibGljS2V5VXJsKTtcbiAgaWYgKHBhcnNlZFVybC5wcm90b2NvbCAhPT0gJ2h0dHBzOicpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgaG9zdG5hbWVQYXJ0cyA9IHBhcnNlZFVybC5ob3N0bmFtZS5zcGxpdCgnLicpO1xuICBjb25zdCBsZW5ndGggPSBob3N0bmFtZVBhcnRzLmxlbmd0aDtcbiAgY29uc3QgZG9tYWluUGFydHMgPSBob3N0bmFtZVBhcnRzLnNsaWNlKGxlbmd0aCAtIDIsIGxlbmd0aCk7XG4gIGNvbnN0IGRvbWFpbiA9IGRvbWFpblBhcnRzLmpvaW4oJy4nKTtcbiAgcmV0dXJuIGRvbWFpbiA9PT0gJ2FwcGxlLmNvbSc7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRYNTA5Q2VydFRvUEVNKFg1MDlDZXJ0KSB7XG4gIGNvbnN0IHBlbVByZUZpeCA9ICctLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS1cXG4nO1xuICBjb25zdCBwZW1Qb3N0Rml4ID0gJy0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0nO1xuXG4gIGNvbnN0IGJhc2U2NCA9IFg1MDlDZXJ0O1xuICBjb25zdCBjZXJ0Qm9keSA9IGJhc2U2NC5tYXRjaChuZXcgUmVnRXhwKCcuezAsNjR9JywgJ2cnKSkuam9pbignXFxuJyk7XG5cbiAgcmV0dXJuIHBlbVByZUZpeCArIGNlcnRCb2R5ICsgcGVtUG9zdEZpeDtcbn1cblxuZnVuY3Rpb24gZ2V0QXBwbGVDZXJ0aWZpY2F0ZShwdWJsaWNLZXlVcmwpIHtcbiAgaWYgKCF2ZXJpZnlQdWJsaWNLZXlVcmwocHVibGljS2V5VXJsKSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICBgQXBwbGUgR2FtZSBDZW50ZXIgLSBpbnZhbGlkIHB1YmxpY0tleVVybDogJHtwdWJsaWNLZXlVcmx9YFxuICAgICk7XG4gIH1cbiAgaWYgKGNhY2hlW3B1YmxpY0tleVVybF0pIHtcbiAgICByZXR1cm4gY2FjaGVbcHVibGljS2V5VXJsXTtcbiAgfVxuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGh0dHBzXG4gICAgICAuZ2V0KHB1YmxpY0tleVVybCwgcmVzID0+IHtcbiAgICAgICAgbGV0IGRhdGEgPSAnJztcbiAgICAgICAgcmVzLm9uKCdkYXRhJywgY2h1bmsgPT4ge1xuICAgICAgICAgIGRhdGEgKz0gY2h1bmsudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVzLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgY2VydCA9IGNvbnZlcnRYNTA5Q2VydFRvUEVNKGRhdGEpO1xuICAgICAgICAgIGlmIChyZXMuaGVhZGVyc1snY2FjaGUtY29udHJvbCddKSB7XG4gICAgICAgICAgICB2YXIgZXhwaXJlID0gcmVzLmhlYWRlcnNbJ2NhY2hlLWNvbnRyb2wnXS5tYXRjaCgvbWF4LWFnZT0oWzAtOV0rKS8pO1xuICAgICAgICAgICAgaWYgKGV4cGlyZSkge1xuICAgICAgICAgICAgICBjYWNoZVtwdWJsaWNLZXlVcmxdID0gY2VydDtcbiAgICAgICAgICAgICAgLy8gd2UnbGwgZXhwaXJlIHRoZSBjYWNoZSBlbnRyeSBsYXRlciwgYXMgcGVyIG1heC1hZ2VcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGNhY2hlW3B1YmxpY0tleVVybF07XG4gICAgICAgICAgICAgIH0sIHBhcnNlSW50KGV4cGlyZVsxXSwgMTApICogMTAwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUoY2VydCk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5vbignZXJyb3InLCByZWplY3QpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY29udmVydFRpbWVzdGFtcFRvQmlnRW5kaWFuKHRpbWVzdGFtcCkge1xuICBjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2MoOCk7XG5cbiAgY29uc3QgaGlnaCA9IH5+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..47a79ffe2c --- /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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL21pY3Jvc29mdC5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJyZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsInJlc3BvbnNlIiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJwYXRoIiwiZ2V0IiwiaG9zdCIsImhlYWRlcnMiLCJBdXRob3JpemF0aW9uIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLEtBQUssR0FBR0MsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkQsS0FBbEM7O0FBQ0EsTUFBTUUsWUFBWSxHQUFHRCxPQUFPLENBQUMsZ0JBQUQsQ0FBNUIsQyxDQUVBOzs7QUFDQSxTQUFTRSxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsU0FBT0MsT0FBTyxDQUFDLElBQUQsRUFBT0QsUUFBUSxDQUFDRSxZQUFoQixDQUFQLENBQXFDQyxJQUFyQyxDQUEwQ0MsUUFBUSxJQUFJO0FBQzNELFFBQUlBLFFBQVEsSUFBSUEsUUFBUSxDQUFDQyxFQUFyQixJQUEyQkQsUUFBUSxDQUFDQyxFQUFULElBQWVMLFFBQVEsQ0FBQ0ssRUFBdkQsRUFBMkQ7QUFDekQ7QUFDRDs7QUFDRCxVQUFNLElBQUlULEtBQUssQ0FBQ1UsS0FBVixDQUNKVixLQUFLLENBQUNVLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSixnREFGSSxDQUFOO0FBSUQsR0FSTSxDQUFQO0FBU0QsQyxDQUVEOzs7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0QsQyxDQUVEOzs7QUFDQSxTQUFTVCxPQUFULENBQWlCVSxJQUFqQixFQUF1QlQsWUFBdkIsRUFBcUM7QUFDbkMsU0FBT0osWUFBWSxDQUFDYyxHQUFiLENBQWlCO0FBQ3RCQyxJQUFBQSxJQUFJLEVBQUUscUJBRGdCO0FBRXRCRixJQUFBQSxJQUFJLEVBQUUsV0FBV0EsSUFGSztBQUd0QkcsSUFBQUEsT0FBTyxFQUFFO0FBQ1BDLE1BQUFBLGFBQWEsRUFBRSxZQUFZYjtBQURwQjtBQUhhLEdBQWpCLENBQVA7QUFPRDs7QUFFRGMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZULEVBQUFBLGFBQWEsRUFBRUEsYUFEQTtBQUVmVCxFQUFBQSxnQkFBZ0IsRUFBRUE7QUFGSCxDQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgbWljcm9zb2Z0IGdyYXBoIEFQSS5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyB1c2VyIG1haWwgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIHJldHVybiByZXF1ZXN0KCdtZScsIGF1dGhEYXRhLmFjY2Vzc190b2tlbikudGhlbihyZXNwb25zZSA9PiB7XG4gICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLmlkICYmIHJlc3BvbnNlLmlkID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnTWljcm9zb2Z0IEdyYXBoIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLidcbiAgICApO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIHJlcXVlc3QocGF0aCwgYWNjZXNzX3Rva2VuKSB7XG4gIHJldHVybiBodHRwc1JlcXVlc3QuZ2V0KHtcbiAgICBob3N0OiAnZ3JhcGgubWljcm9zb2Z0LmNvbScsXG4gICAgcGF0aDogJy92MS4wLycgKyBwYXRoLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgIEF1dGhvcml6YXRpb246ICdCZWFyZXIgJyArIGFjY2Vzc190b2tlbixcbiAgICB9LFxuICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGEsXG59O1xuIl19 \ 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..fca457a137 --- /dev/null +++ b/lib/Adapters/Logger/WinstonLogger.js @@ -0,0 +1,137 @@ +"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, + maxLogFiles +} = {}) { + 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; + options.maxFiles = maxLogFiles; + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlci5qcyJdLCJuYW1lcyI6WyJsb2dnZXIiLCJ3aW5zdG9uIiwiY3JlYXRlTG9nZ2VyIiwiY29uZmlndXJlVHJhbnNwb3J0cyIsIm9wdGlvbnMiLCJ0cmFuc3BvcnRzIiwic2lsZW50IiwiXyIsImlzTmlsIiwiZGlybmFtZSIsInBhcnNlU2VydmVyIiwiRGFpbHlSb3RhdGVGaWxlIiwiT2JqZWN0IiwiYXNzaWduIiwiZmlsZW5hbWUiLCJqc29uIiwiZm9ybWF0IiwiY29tYmluZSIsInRpbWVzdGFtcCIsInNwbGF0IiwibmFtZSIsInB1c2giLCJwYXJzZVNlcnZlckVycm9yIiwibGV2ZWwiLCJlIiwiY29uc29sZUZvcm1hdCIsInNpbXBsZSIsImNvbnNvbGVPcHRpb25zIiwiY29sb3JpemUiLCJDb25zb2xlIiwiY29uZmlndXJlIiwiY29uZmlndXJlTG9nZ2VyIiwibG9nc0ZvbGRlciIsImRlZmF1bHRzIiwianNvbkxvZ3MiLCJsb2dMZXZlbCIsInZlcmJvc2UiLCJtYXhMb2dGaWxlcyIsInBhdGgiLCJpc0Fic29sdXRlIiwicmVzb2x2ZSIsInByb2Nlc3MiLCJjd2QiLCJmcyIsIm1rZGlyU3luYyIsIm1heEZpbGVzIiwic3RyaW5naWZ5IiwiYWRkVHJhbnNwb3J0IiwidHJhbnNwb3J0IiwicmVtb3ZlVHJhbnNwb3J0IiwiYWRkIiwibWF0Y2hpbmdUcmFuc3BvcnQiLCJmaW5kIiwidDEiLCJyZW1vdmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNQSxNQUFNLEdBQUdDLGlCQUFRQyxZQUFSLEVBQWY7Ozs7QUFFQSxTQUFTQyxtQkFBVCxDQUE2QkMsT0FBN0IsRUFBc0M7QUFDcEMsUUFBTUMsVUFBVSxHQUFHLEVBQW5COztBQUNBLE1BQUlELE9BQUosRUFBYTtBQUNYLFVBQU1FLE1BQU0sR0FBR0Ys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LCB7IGZvcm1hdCB9IGZyb20gJ3dpbnN0b24nO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IERhaWx5Um90YXRlRmlsZSBmcm9tICd3aW5zdG9uLWRhaWx5LXJvdGF0ZS1maWxlJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgZGVmYXVsdHMgZnJvbSAnLi4vLi4vZGVmYXVsdHMnO1xuXG5jb25zdCBsb2dnZXIgPSB3aW5zdG9uLmNyZWF0ZUxvZ2dlcigpO1xuXG5mdW5jdGlvbiBjb25maWd1cmVUcmFuc3BvcnRzKG9wdGlvbnMpIHtcbiAgY29uc3QgdHJhbnNwb3J0cyA9IFtdO1xuICBpZiAob3B0aW9ucykge1xuICAgIGNvbnN0IHNpbGVudCA9IG9wdGlvbnMuc2lsZW50O1xuICAgIGRlbGV0ZSBvcHRpb25zLnNpbGVudDtcblxuICAgIHRyeSB7XG4gICAgICBpZiAoIV8uaXNOaWwob3B0aW9ucy5kaXJuYW1lKSkge1xuICAgICAgICBjb25zdCBwYXJzZVNlcnZlciA9IG5ldyBEYWlseVJvdGF0ZUZpbGUoXG4gICAgICAgICAgT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZmlsZW5hbWU6ICdwYXJzZS1zZXJ2ZXIuaW5mbycsXG4gICAgICAgICAgICAgIGpzb246IHRydWUsXG4gICAgICAgICAgICAgIGZvcm1hdDogZm9ybWF0LmNvbWJpbmUoXG4gICAgICAgICAgICAgICAgZm9ybWF0LnRpbWVzdGFtcCgpLFxuICAgICAgICAgICAgICAgIGZvcm1hdC5zcGxhdCgpLFxuICAgICAgICAgICAgICAgIGZvcm1hdC5qc29uKClcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25zXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICBwYXJzZVNlcnZlci5uYW1lID0gJ3BhcnNlLXNlcnZlcic7XG4gICAgICAgIHRyYW5zcG9ydHMucHVzaChwYXJzZVNlcnZlcik7XG5cbiAgICAgICAgY29uc3QgcGFyc2VTZXJ2ZXJFcnJvciA9IG5ldyBEYWlseVJvdGF0ZUZpbGUoXG4gICAgICAgICAgT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZmlsZW5hbWU6ICdwYXJzZS1zZXJ2ZXIuZXJyJyxcbiAgICAgICAgICAgICAganNvbjogdHJ1ZSxcbiAgICAgICAgICAgICAgZm9ybWF0OiBmb3JtYXQuY29tYmluZShcbiAgICAgICAgICAgICAgICBmb3JtYXQudGltZXN0YW1wKCksXG4gICAgICAgICAgICAgICAgZm9ybWF0LnNwbGF0KCksXG4gICAgICAgICAgICAgICAgZm9ybWF0Lmpzb24oKVxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgICB7IGxldmVsOiAnZXJyb3InIH1cbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHBhcnNlU2VydmVyRXJyb3IubmFtZSA9ICdwYXJzZS1zZXJ2ZXItZXJyb3InO1xuICAgICAgICB0cmFuc3BvcnRzLnB1c2gocGFyc2VTZXJ2ZXJFcnJvcik7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLyogKi9cbiAgICB9XG5cbiAgICBjb25zdCBjb25zb2xlRm9ybWF0ID0gb3B0aW9ucy5qc29uID8gZm9ybWF0Lmpzb24oKSA6IGZvcm1hdC5zaW1wbGUoKTtcbiAgICBjb25zdCBjb25zb2xlT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICB7XG4gICAgICAgIGNvbG9yaXplOiB0cnVlLFxuICAgICAgICBuYW1lOiAnY29uc29sZScsXG4gICAgICAgIHNpbGVudCxcbiAgICAgICAgZm9ybWF0OiBjb25zb2xlRm9ybWF0LFxuICAgICAgfSxcbiAgICAgIG9wdGlvbnNcbiAgICApO1xuXG4gICAgdHJhbnNwb3J0cy5wdXNoKG5ldyB3aW5zdG9uLnRyYW5zcG9ydHMuQ29uc29sZShjb25zb2xlT3B0aW9ucykpO1xuICB9XG5cbiAgbG9nZ2VyLmNvbmZpZ3VyZSh7XG4gICAgdHJhbnNwb3J0cyxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb25maWd1cmVMb2dnZXIoe1xuICBsb2dzRm9sZGVyID0gZGVmYXVsdHMubG9nc0ZvbGRlcixcbiAganNvbkxvZ3MgPSBkZWZhdWx0cy5qc29uTG9ncyxcbiAgbG9nTGV2ZWwgPSB3aW5zdG9uLmxldmVsLFxuICB2ZXJib3NlID0gZGVmYXVsdHMudmVyYm9zZSxcbiAgc2lsZW50ID0gZGVmYXVsdHMuc2lsZW50LFxuICBtYXhMb2dGaWxlcyxcbn0gPSB7fSkge1xuICBpZiAodmVyYm9zZSkge1xuICAgIGxvZ0xldmVsID0gJ3ZlcmJvc2UnO1xuICB9XG5cbiAgd2luc3Rvbi5sZXZlbCA9IGxvZ0xldmVsO1xuICBjb25zdCBvcHRpb25zID0ge307XG5cbiAgaWYgKGxvZ3NGb2xkZXIpIHtcbiAgICBpZiAoIXBhdGguaXNBYnNvbHV0ZShsb2dzRm9sZGVyKSkge1xuICAgICAgbG9nc0ZvbGRlciA9IHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCBsb2dzRm9sZGVyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGZzLm1rZGlyU3luYyhsb2dzRm9sZGVyKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvKiAqL1xuICAgIH1cbiAgfVxuICBvcHRpb25zLmRpcm5hbWUgPSBsb2dzRm9sZGVyO1xuICBvcHRpb25zLmxldmVsID0gbG9nTGV2ZWw7XG4gIG9wdGlvbnMuc2lsZW50ID0gc2lsZW50O1xuICBvcHRpb25zLm1heEZpbGVzID0gbWF4TG9nRmlsZXM7XG5cbiAgaWYgKGpzb25Mb2dzKSB7XG4gICAgb3B0aW9ucy5qc29uID0gdHJ1ZTtcbiAgICBvcHRpb25zLnN0cmluZ2lmeSA9IHRydWU7XG4gIH1cbiAgY29uZmlndXJlVHJhbnNwb3J0cyhvcHRpb25zKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZFRyYW5zcG9ydCh0cmFuc3BvcnQpIHtcbiAgLy8gd2Ugd2lsbCByZW1vdmUgdGhlIGV4aXN0aW5nIHRyYW5zcG9ydFxuICAvLyBiZWZvcmUgcmVwbGFjaW5nIGl0IHdpdGggYSBuZXcgb25lXG4gIHJlbW92ZVRyYW5zcG9ydCh0cmFuc3BvcnQubmFtZSk7XG5cbiAgbG9nZ2VyLmFkZCh0cmFuc3BvcnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlVHJhbnNwb3J0KHRyYW5zcG9ydCkge1xuICBjb25zdCBtYXRjaGluZ1RyYW5zcG9ydCA9IGxvZ2dlci50cmFuc3BvcnRzLmZpbmQodDEgPT4ge1xuICAgIHJldHVybiB0eXBlb2YgdHJhbnNwb3J0ID09PSAnc3RyaW5nJ1xuICAgICAgPyB0MS5uYW1lID09PSB0cmFuc3BvcnRcbiAgICAgIDogdDEgPT09IHRyYW5zcG9ydDtcbiAgfSk7XG5cbiAgaWYgKG1hdGNoaW5nVHJhbnNwb3J0KSB7XG4gICAgbG9nZ2VyLnJlbW92ZShtYXRjaGluZ1RyYW5zcG9ydCk7XG4gIH1cbn1cblxuZXhwb3J0IHsgbG9nZ2VyIH07XG5leHBvcnQgZGVmYXVsdCBsb2dnZXI7XG4iXX0= \ 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..ab56483953 --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoCollection.js @@ -0,0 +1,231 @@ +"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, + hint, + caseInsensitive, + explain + } = {}) { + // 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, + hint, + caseInsensitive, + explain + }).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, { + background: true + }) // Retry, but just once. + .then(() => this._rawFind(query, { + skip, + limit, + sort, + keys, + maxTimeMS, + readPreference, + hint, + caseInsensitive, + explain + })); + }); + } + /** + * Collation to support case insensitive queries + */ + + + static caseInsensitiveCollation() { + return { + locale: 'en_US', + strength: 2 + }; + } + + _rawFind(query, { + skip, + limit, + sort, + keys, + maxTimeMS, + readPreference, + hint, + caseInsensitive, + explain + } = {}) { + let findOperation = this._mongoCollection.find(query, { + skip, + limit, + sort, + readPreference, + hint + }); + + if (keys) { + findOperation = findOperation.project(keys); + } + + if (caseInsensitive) { + findOperation = findOperation.collation(MongoCollection.caseInsensitiveCollation()); + } + + if (maxTimeMS) { + findOperation = findOperation.maxTimeMS(maxTimeMS); + } + + return explain ? findOperation.explain(explain) : findOperation.toArray(); + } + + count(query, { + skip, + limit, + sort, + maxTimeMS, + readPreference, + hint + } = {}) { + // 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, + hint + }); + + return countOperation; + } + + distinct(field, query) { + return this._mongoCollection.distinct(field, query); + } + + aggregate(pipeline, { + maxTimeMS, + readPreference, + hint, + explain + } = {}) { + return this._mongoCollection.aggregate(pipeline, { + maxTimeMS, + readPreference, + hint, + explain + }).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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJtb25nb2RiIiwicmVxdWlyZSIsIkNvbGxlY3Rpb24iLCJNb25nb0NvbGxlY3Rpb24iLCJjb25zdHJ1Y3RvciIsIm1vbmdvQ29sbGVjdGlvbiIsIl9tb25nb0NvbGxlY3Rpb24iLCJmaW5kIiwicXVlcnkiLCJza2lwIiwibGltaXQiLCJzb3J0Iiwia2V5cyIsIm1heFRpbWVNUyIsInJlYWRQcmVmZXJlbmNlIiwiaGludCIsImNhc2VJbnNlbnNpdGl2ZSIsImV4cGxhaW4iLCIkc2NvcmUiLCJzY29yZSIsIiRtZXRhIiwiX3Jhd0ZpbmQiLCJjYXRjaCIsImVycm9yIiwiY29kZSIsIm1lc3NhZ2UiLCJtYXRjaCIsImtleSIsImluZGV4IiwiY3JlYXRlSW5kZXgiLCJiYWNrZ3JvdW5kIiwidGhlbiIsImNhc2VJbnNlbnNpdGl2ZUNvbGxhdGlvbiIsImxvY2FsZSIsInN0cmVuZ3RoIiwiZmluZE9wZXJhdGlvbiIsInByb2plY3QiLCJjb2xsYXRpb24iLCJ0b0FycmF5IiwiY291bnQiLCJPYmplY3QiLCJsZW5ndGgiLCJlc3RpbWF0ZWREb2N1bWVudENvdW50IiwiY291bnRPcGVyYXRpb24iLCJjb3VudERvY3VtZW50cyIsImRpc3RpbmN0IiwiZmllbGQiLCJhZ2dyZWdhdGUiLCJwaXBlbGluZSIsImluc2VydE9uZSIsIm9iamVjdCIsInNlc3Npb24iLCJ1cHNlcnRPbmUiLCJ1cGRhdGUiLCJ1cGRhdGVPbmUiLCJ1cHNlcnQiLCJ1cGRhdGVNYW55IiwiZGVsZXRlTWFueSIsIl9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZCIsImluZGV4UmVxdWVzdCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwidW5pcXVlIiwic3BhcnNlIiwiZHJvcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBLE1BQU1BLE9BQU8sR0FBR0Ms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S0FBSzNELGdCQUFMLENBQXNCMkQsSUFBdEIsRUFBUDtBQUNEOztBQXpNa0MiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgQ29sbGVjdGlvbiA9IG1vbmdvZGIuQ29sbGVjdGlvbjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTW9uZ29Db2xsZWN0aW9uIHtcbiAgX21vbmdvQ29sbGVjdGlvbjogQ29sbGVjdGlvbjtcblxuICBjb25zdHJ1Y3Rvcihtb25nb0NvbGxlY3Rpb246IENvbGxlY3Rpb24pIHtcbiAgICB0aGlzLl9tb25nb0NvbGxlY3Rpb24gPSBtb25nb0NvbGxlY3Rpb247XG4gIH1cblxuICAvLyBEb2VzIGEgZmluZCB3aXRoIFwic21hcnQgaW5kZXhpbmdcIi5cbiAgLy8gQ3VycmVudGx5IHRoaXMganVzdCBtZWFucywgaWYgaXQgbmVlZHMgYSBnZW9pbmRleCBhbmQgdGhlcmUgaXNcbiAgLy8gbm9uZSwgdGhlbiBidWlsZCB0aGUgZ2VvaW5kZXguXG4gIC8vIFRoaXMgY291bGQgYmUgaW1wcm92ZWQgYSBsb3QgYnV0IGl0J3Mgbm90IGNsZWFyIGlmIHRoYXQncyBhIGdvb2RcbiAgLy8gaWRlYS4gT3IgZXZlbiBpZiB0aGlzIGJlaGF2aW9yIGlzIGEgZ29vZCBpZGVhLlxuICBmaW5kKFxuICAgIHF1ZXJ5LFxuICAgIHtcbiAgICAgIHNraXAsXG4gICAgICBsaW1pdCxcbiAgICAgIHNvcnQsXG4gICAgICBrZXlzLFxuICAgICAgbWF4VGltZU1TLFxuICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICBoaW50LFxuICAgICAgY2FzZUluc2Vuc2l0aXZlLFxuICAgICAgZXhwbGFpbixcbiAgICB9ID0ge31cbiAgKSB7XG4gICAgLy8gU3VwcG9ydCBmb3IgRnVsbCBUZXh0IFNlYXJjaCAtICR0ZXh0XG4gICAgaWYgKGtleXMgJiYga2V5cy4kc2NvcmUpIHtcbiAgICAgIGRlbGV0ZSBrZXlzLiRzY29yZTtcbiAgICAgIGtleXMuc2NvcmUgPSB7ICRtZXRhOiAndGV4dFNjb3JlJyB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcmF3RmluZChxdWVyeSwge1xuICAgICAgc2tpcCxcbiAgICAgIGxpbWl0LFxuICAgICAgc29ydCxcbiAgICAgIGtleXMsXG4gICAgICBtYXhUaW1lTVMsXG4gICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgIGhpbnQsXG4gICAgICBjYXNlSW5zZW5zaXRpdmUsXG4gICAgICBleHBsYWluLFxuICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIC8vIENoZWNrIGZvciBcIm5vIGdlb2luZGV4XCIgZXJyb3JcbiAgICAgIGlmIChcbiAgICAgICAgZXJyb3IuY29kZSAhPSAxNzAwNyAmJlxuICAgICAgICAhZXJyb3IubWVzc2FnZS5tYXRjaCgvdW5hYmxlIHRvIGZpbmQgaW5kZXggZm9yIC5nZW9OZWFyLylcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIC8vIEZpZ3VyZSBvdXQgd2hhdCBrZXkgbmVlZHMgYW4gaW5kZXhcbiAgICAgIGNvbnN0IGtleSA9IGVycm9yLm1lc3NhZ2UubWF0Y2goL2ZpZWxkPShbQS1aYS16XzAtOV0rKSAvKVsxXTtcbiAgICAgIGlmICgha2V5KSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuXG4gICAgICB2YXIgaW5kZXggPSB7fTtcbiAgICAgIGluZGV4W2tleV0gPSAnMmQnO1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uXG4gICAgICAgICAgLmNyZWF0ZUluZGV4KGluZGV4LCB7IGJhY2tncm91bmQ6IHRydWUgfSlcbiAgICAgICAgICAvLyBSZXRyeSwgYnV0IGp1c3Qgb25jZS5cbiAgICAgICAgICAudGhlbigoKSA9PlxuICAgICAgICAgICAgdGhpcy5fcmF3RmluZChxdWVyeSwge1xuICAgICAgICAgICAgICBza2lwLFxuICAgICAgICAgICAgICBsaW1pdCxcbiAgICAgICAgICAgICAgc29ydCxcbiAgICAgICAgICAgICAga2V5cyxcbiAgICAgICAgICAgICAgbWF4VGltZU1TLFxuICAgICAgICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgICAgaGludCxcbiAgICAgICAgICAgICAgY2FzZUluc2Vuc2l0aXZlLFxuICAgICAgICAgICAgICBleHBsYWluLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbGxhdGlvbiB0byBzdXBwb3J0IGNhc2UgaW5zZW5zaXRpdmUgcXVlcmllc1xuICAgKi9cbiAgc3RhdGljIGNhc2VJbnNlbnNpdGl2ZUNvbGxhdGlvbigpIHtcbiAgICByZXR1cm4geyBsb2NhbGU6ICdlbl9VUycsIHN0cmVuZ3RoOiAyIH07XG4gIH1cblxuICBfcmF3RmluZChcbiAgICBxdWVyeSxcbiAgICB7XG4gICAgICBza2lwLFxuICAgICAgbGltaXQsXG4gICAgICBzb3J0LFxuICAgICAga2V5cyxcbiAgICAgIG1heFRpbWVNUyxcbiAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgaGludCxcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZSxcbiAgICAgIGV4cGxhaW4sXG4gICAgfSA9IHt9XG4gICkge1xuICAgIGxldCBmaW5kT3BlcmF0aW9uID0gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmZpbmQocXVlcnksIHtcbiAgICAgIHNraXAsXG4gICAgICBsaW1pdCxcbiAgICAgIHNvcnQsXG4gICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgIGhpbnQsXG4gICAgfSk7XG5cbiAgICBpZiAoa2V5cykge1xuICAgICAgZmluZE9wZXJhdGlvbiA9IGZpbmRPcGVyYXRpb24ucHJvamVjdChrZXlzKTtcbiAgICB9XG5cbiAgICBpZiAoY2FzZUluc2Vuc2l0aXZlKSB7XG4gICAgICBmaW5kT3BlcmF0aW9uID0gZmluZE9wZXJhdGlvbi5jb2xsYXRpb24oXG4gICAgICAgIE1vbmdvQ29sbGVjdGlvbi5jYXNlSW5zZW5zaXRpdmVDb2xsYXRpb24oKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAobWF4VGltZU1TKSB7XG4gICAgICBmaW5kT3BlcmF0aW9uID0gZmluZE9wZXJhdGlvbi5tYXhUaW1lTVMobWF4VGltZU1TKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZXhwbGFpbiA/IGZpbmRPcGVyYXRpb24uZXhwbGFpbihleHBsYWluKSA6IGZpbmRPcGVyYXRpb24udG9BcnJheSgpO1xuICB9XG5cbiAgY291bnQocXVlcnksIHsgc2tpcCwgbGltaXQsIHNvcnQsIG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UsIGhpbnQgfSA9IHt9KSB7XG4gICAgLy8gSWYgcXVlcnkgaXMgZW1wdHksIHRoZW4gdXNlIGVzdGltYXRlZERvY3VtZW50Q291bnQgaW5zdGVhZC5cbiAgICAvLyBUaGlzIGlzIGR1ZSB0byBjb3VudERvY3VtZW50cyBwZXJmb3JtaW5nIGEgc2NhbixcbiAgICAvLyB3aGljaCBncmVhdGx5IGluY3JlYXNlcyBleGVjdXRpb24gdGltZSB3aGVuIGJlaW5nIHJ1biBvbiBsYXJnZSBjb2xsZWN0aW9ucy5cbiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL0F1dG9tYXR0aWMvbW9uZ29vc2UvaXNzdWVzLzY3MTMgZm9yIG1vcmUgaW5mbyByZWdhcmRpbmcgdGhpcyBwcm9ibGVtLlxuICAgIGlmICh0eXBlb2YgcXVlcnkgIT09ICdvYmplY3QnIHx8ICFPYmplY3Qua2V5cyhxdWVyeSkubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmVzdGltYXRlZERvY3VtZW50Q291bnQoe1xuICAgICAgICBtYXhUaW1lTVMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb3VudE9wZXJhdGlvbiA9IHRoaXMuX21vbmdvQ29sbGVjdGlvbi5jb3VudERvY3VtZW50cyhxdWVyeSwge1xuICAgICAgc2tpcCxcbiAgICAgIGxpbWl0LFxuICAgICAgc29ydCxcbiAgICAgIG1heFRpbWVNUyxcbiAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgaGludCxcbiAgICB9KTtcblxuICAgIHJldHVybiBjb3VudE9wZXJhdGlvbjtcbiAgfVxuXG4gIGRpc3RpbmN0KGZpZWxkLCBxdWVyeSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uZGlzdGluY3QoZmllbGQsIHF1ZXJ5KTtcbiAgfVxuXG4gIGFnZ3JlZ2F0ZShwaXBlbGluZSwgeyBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlLCBoaW50LCBleHBsYWluIH0gPSB7fSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb25cbiAgICAgIC5hZ2dyZWdhdGUocGlwZWxpbmUsIHsgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSwgaGludCwgZXhwbGFpbiB9KVxuICAgICAgLnRvQXJyYXkoKTtcbiAgfVxuXG4gIGluc2VydE9uZShvYmplY3QsIHNlc3Npb24pIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmluc2VydE9uZShvYmplY3QsIHsgc2Vzc2lvbiB9KTtcbiAgfVxuXG4gIC8vIEF0b21pY2FsbHkgdXBkYXRlcyBkYXRhIGluIHRoZSBkYXRhYmFzZSBmb3IgYSBzaW5nbGUgKGZpcnN0KSBvYmplY3QgdGhhdCBtYXRjaGVkIHRoZSBxdWVyeVxuICAvLyBJZiB0aGVyZSBpcyBub3RoaW5nIHRoYXQgbWF0Y2hlcyB0aGUgcXVlcnkgLSBkb2VzIGluc2VydFxuICAvLyBQb3N0Z3JlcyBOb3RlOiBgSU5TRVJUIC4uLiBPTiBDT05GTElDVCBVUERBVEVgIHRoYXQgaXMgYXZhaWxhYmxlIHNpbmNlIDkuNS5cbiAgdXBzZXJ0T25lKHF1ZXJ5LCB1cGRhdGUsIHNlc3Npb24pIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLnVwZGF0ZU9uZShxdWVyeSwgdXBkYXRlLCB7XG4gICAgICB1cHNlcnQ6IHRydWUsXG4gICAgICBzZXNzaW9uLFxuICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlT25lKHF1ZXJ5LCB1cGRhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLnVwZGF0ZU9uZShxdWVyeSwgdXBkYXRlKTtcbiAgfVxuXG4gIHVwZGF0ZU1hbnkocXVlcnksIHVwZGF0ZSwgc2Vzc2lvbikge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24udXBkYXRlTWFueShxdWVyeSwgdXBkYXRlLCB7IHNlc3Npb24gfSk7XG4gIH1cblxuICBkZWxldGVNYW55KHF1ZXJ5LCBzZXNzaW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5kZWxldGVNYW55KHF1ZXJ5LCB7IHNlc3Npb24gfSk7XG4gIH1cblxuICBfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQoaW5kZXhSZXF1ZXN0KSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5jcmVhdGVJbmRleChcbiAgICAgICAgaW5kZXhSZXF1ZXN0LFxuICAgICAgICB7IHVuaXF1ZTogdHJ1ZSwgYmFja2dyb3VuZDogdHJ1ZSwgc3BhcnNlOiB0cnVlIH0sXG4gICAgICAgIGVycm9yID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBkcm9wKCkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uZHJvcCgpO1xuICB9XG59XG4iXX0= \ 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..e3858ee6fd --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -0,0 +1,937 @@ +"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 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 _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, + hint, + caseInsensitive, + explain + }) { + 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, + hint, + caseInsensitive, + explain + })).then(objects => { + if (explain) { + return objects; + } + + return objects.map(object => (0, _MongoTransform.mongoObjectToParseObject)(className, object, schema)); + }).catch(err => this.handleError(err)); + } + + ensureIndex(className, schema, fieldNames, indexName, caseInsensitive = false) { + schema = convertParseSchemaToMongoSchema(schema); + const indexCreationRequest = {}; + const mongoFieldNames = fieldNames.map(fieldName => (0, _MongoTransform.transformKey)(className, fieldName, schema)); + mongoFieldNames.forEach(fieldName => { + indexCreationRequest[fieldName] = 1; + }); + const defaultOptions = { + background: true, + sparse: true + }; + const indexNameOptions = indexName ? { + name: indexName + } : {}; + const caseInsensitiveOptions = caseInsensitive ? { + collation: _MongoCollection.default.caseInsensitiveCollation() + } : {}; + + const indexOptions = _objectSpread({}, defaultOptions, {}, caseInsensitiveOptions, {}, indexNameOptions); + + return this._adaptiveCollection(className).then(collection => new Promise((resolve, reject) => collection._mongoCollection.createIndex(indexCreationRequest, indexOptions, error => error ? reject(error) : resolve()))).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, hint) { + 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, + hint + })).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, hint, explain) { + 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, + hint, + explain + })).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, { + background: true + })).catch(err => this.handleError(err)); + } + + createIndexes(className, indexes) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.createIndexes(indexes, { + background: true + })).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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsibW9uZ29kYiIsInJlcXVpcmUiLCJNb25nb0NsaWVudCIsIlJlYWRQcmVmZXJlbmNlIiwiTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSIsInN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMiLCJtb25nb0FkYXB0ZXIiLCJjb25uZWN0IiwidGhlbiIsImRhdGFiYXNlIiwiY29sbGVjdGlvbnMiLCJmaWx0ZXIiLCJjb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwibWF0Y2giLCJjb2xsZWN0aW9uTmFtZSIsImluZGV4T2YiLCJfY29sbGVjdGlvblByZWZpeCIsImNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEiLCJzY2hlbWEiLCJmaWVsZHMiLCJfcnBlcm0iLCJfd3Blcm0iLCJjbGFzc05hbWUiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vbmdvT2JqZWN0IiwiX2lkIiwib2JqZWN0SWQiLCJ1cGRhdGVkQXQiLCJjcmVhdGVkQXQiLCJfbWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJmaWVsZE5hbWUiLCJ0eXBlIiwidGFyZ2V0Q2xhc3MiLCJmaWVsZE9wdGlvbnMiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJPYmplY3QiLCJrZXlzIiwibGVuZ3RoIiwiZmllbGRzX29wdGlvbnMiLCJjbGFzc19wZXJtaXNzaW9ucyIsIk1vbmdvU3RvcmFnZUFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsInVyaSIsImRlZmF1bHRzIiwiRGVmYXVsdE1vbmdvVVJJIiwiY29sbGVjdGlvblByZWZpeCIsIm1vbmdvT3B0aW9ucyIsIl91cmkiLCJfbW9uZ29PcHRpb25zIiwidXNlTmV3VXJsUGFyc2VyIiwidXNlVW5pZmllZFRvcG9sb2d5IiwiX21heFRpbWVNUyIsIm1heFRpbWVNUyIsImNhblNvcnRPbkpvaW5UYWJsZXMiLCJjb25uZWN0aW9uUHJvbWlzZSIsImVuY29kZWRVcmkiLCJjbGllbnQiLCJvcHRpb25zIiwicyIsImRiIiwiZGJOYW1lIiwib24iLCJjYXRjaCIsImVyciIsIlByb21pc2UiLCJyZWplY3QiLCJoYW5kbGVFcnJvciIsImVycm9yIiwiY29kZSIsImxvZ2dlciIsImhhbmRsZVNodXRkb3duIiwicmVzb2x2ZSIsImNsb3NlIiwiX2FkYXB0aXZlQ29sbGVjdGlvbiIsIm5hbWUiLCJyYXdDb2xsZWN0aW9uIiwiTW9uZ29Db2xsZWN0aW9uIiwiX3NjaGVtYUNvbGxlY3Rpb24iLCJjbGFzc0V4aXN0cyIsImxpc3RDb2xsZWN0aW9ucyIsInRvQXJyYXkiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2NoZW1hQ29sbGVjdGlvbiIsInVwZGF0ZVNjaGVtYSIsIiRzZXQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJfaWRfIiwiZGVsZXRlUHJvbWlzZXMiLCJpbnNlcnRlZEluZGV4ZXMiLCJmb3JFYWNoIiwiZmllbGQiLCJfX29wIiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfUVVFUlkiLCJwcm9taXNlIiwiZHJvcEluZGV4IiwicHVzaCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImluc2VydFByb21pc2UiLCJjcmVhdGVJbmRleGVzIiwiYWxsIiwic2V0SW5kZXhlc0Zyb21Nb25nbyIsImdldEluZGV4ZXMiLCJyZWR1Y2UiLCJvYmoiLCJpbmRleCIsIl9mdHMiLCJfZnRzeCIsIndlaWdodHMiLCJjcmVhdGVDbGFzcyIsImluc2VydFNjaGVtYSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJjcmVhdGVJbmRleGVzSWZOZWVkZWQiLCJkZWxldGVDbGFzcyIsImRyb3AiLCJtZXNzYWdlIiwiZmluZEFuZERlbGV0ZVNjaGVtYSIsImRlbGV0ZUFsbENsYXNzZXMiLCJmYXN0IiwibWFwIiwiZGVsZXRlTWFueSIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJtb25nb0Zvcm1hdE5hbWVzIiwiY29sbGVjdGlvblVwZGF0ZSIsIiR1bnNldCIsInNjaGVtYVVwZGF0ZSIsInVwZGF0ZU1hbnkiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hc0NvbGxlY3Rpb24iLCJfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEiLCJnZXRDbGFzcyIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0IiwidHJhbnNhY3Rpb25hbFNlc3Npb24iLCJpbnNlcnRPbmUiLCJEVVBMSUNBVEVfVkFMVUUiLCJ1bmRlcmx5aW5nRXJyb3IiLCJtYXRjaGVzIiwiQXJyYXkiLCJpc0FycmF5IiwidXNlckluZm8iLCJkdXBsaWNhdGVkX2ZpZWxkIiwiZGVsZXRlT2JqZWN0c0J5UXVlcnkiLCJxdWVyeSIsIm1vbmdvV2hlcmUiLCJyZXN1bHQiLCJuIiwiT0JKRUNUX05PVF9GT1VORCIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsInVwZGF0ZU9iamVjdHNCeVF1ZXJ5IiwidXBkYXRlIiwibW9uZ29VcGRhdGUiLCJmaW5kT25lQW5kVXBkYXRlIiwiX21vbmdvQ29sbGVjdGlvbiIsInJldHVybk9yaWdpbmFsIiwic2Vzc2lvbiIsInZhbHVlIiwidXBzZXJ0T25lT2JqZWN0IiwidXBzZXJ0T25lIiwiZmluZCIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJyZWFkUHJlZmVyZW5jZSIsImhpbnQiLCJjYXNlSW5zZW5zaXRpdmUiLCJleHBsYWluIiwibW9uZ29Tb3J0IiwiXyIsIm1hcEtleXMiLCJtb25nb0tleXMiLCJtZW1vIiwiX3BhcnNlUmVhZFByZWZlcmVuY2UiLCJjcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkIiwib2JqZWN0cyIsImVuc3VyZUluZGV4IiwiaW5kZXhOYW1lIiwiaW5kZXhDcmVhdGlvblJlcXVlc3QiLCJtb25nb0ZpZWxkTmFtZXMiLCJkZWZhdWx0T3B0aW9ucyIsImJhY2tncm91bmQiLCJzcGFyc2UiLCJpbmRleE5hbWVPcHRpb25zIiwiY2FzZUluc2Vuc2l0aXZlT3B0aW9ucyIsImNvbGxhdGlvbiIsImNhc2VJbnNlbnNpdGl2ZUNvbGxhdGlvbiIsImluZGV4T3B0aW9ucyIsImNyZWF0ZUluZGV4IiwiZW5zdXJlVW5pcXVlbmVzcyIsIl9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZCIsIl9yYXdGaW5kIiwiY291bnQiLCJkaXN0aW5jdCIsImlzUG9pbnRlckZpZWxkIiwidHJhbnNmb3JtRmllbGQiLCJhZ2dyZWdhdGUiLCJwaXBlbGluZSIsInN0YWdlIiwiJGdyb3VwIiwiX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzIiwiJG1hdGNoIiwiX3BhcnNlQWdncmVnYXRlQXJncyIsIiRwcm9qZWN0IiwiX3BhcnNlQWdncmVnYXRlUHJvamVjdEFyZ3MiLCJyZXN1bHRzIiwic3BsaXQiLCJpbmNsdWRlcyIsImlzRW1wdHkiLCJyZXR1cm5WYWx1ZSIsIl9jb252ZXJ0VG9EYXRlIiwic3Vic3RyaW5nIiwiRGF0ZSIsInRvVXBwZXJDYXNlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCIkdGV4dCIsInRleHRJbmRleCIsImRyb3BBbGxJbmRleGVzIiwiZHJvcEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsImNsYXNzZXMiLCJwcm9taXNlcyIsImNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uIiwidHJhbnNhY3Rpb25hbFNlY3Rpb24iLCJzdGFydFNlc3Npb24iLCJzdGFydFRyYW5zYWN0aW9uIiwiY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24iLCJjb21taXRUcmFuc2FjdGlvbiIsImVuZFNlc3Npb24iLCJhYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uIiwiYWJvcnRUcmFuc2FjdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQUNBOztBQUNBOztBQU9BOztBQUlBOztBQVNBOztBQUVBOztBQUNBOztBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FBRUE7QUFDQSxNQUFNQSxPQUFPLEdBQUdDLE9BQU8sQ0FBQyxTQUFELENBQXZCOztBQUNBLE1BQU1DLFdBQVcsR0FBR0YsT0FBTyxDQUFDRSxXQUE1QjtBQUNBLE1BQU1DLGNBQWMsR0FBR0gsT0FBTyxDQUFDRyxjQUEvQjtBQUVBLE1BQU1DLHlCQUF5QixHQUFHLFNBQWxDOztBQUVBLE1BQU1DLDRCQUE0QixHQUFHQyxZQUFZLElBQUk7QUFDbkQsU0FBT0EsWUFBWSxDQUNoQkMsT0FESSxHQUVKQyxJQUZJLENBRUMsTUFBTUYsWUFBWSxDQUFDRyxRQUFiLENBQXNCQyxXQUF0QixFQUZQLEVBR0pGLElBSEksQ0FHQ0UsV0FBVyxJQUFJO0FBQ25CLFdBQU9BLFdBQVcsQ0FBQ0MsTUFBWixDQUFtQkMsVUFBVSxJQUFJO0FBQ3RDLFVBQUlBLFVBQVUsQ0FBQ0MsU0FBWCxDQUFxQkMsS0FBckIsQ0FBMkIsWUFBM0IsQ0FBSixFQUE4QztBQUM1QyxlQUFPLEtBQVA7QUFDRCxPQUhxQyxDQUl0QztBQUNBOzs7QUFDQSxhQUNFRixVQUFVLENBQUNHLGNBQVgsQ0FBMEJDLE9BQTFCLENBQWtDVixZQUFZLENBQUNXLGlCQUEvQyxLQUFxRSxDQUR2RTtBQUdELEtBVE0sQ0FBUDtBQVVELEdBZEksQ0FBUDtBQWVELENBaEJEOztBQWtCQSxNQUFNQywrQkFBK0IsR0FBRyxVQUFtQjtBQUFBLE1BQWJDLE1BQWE7O0FBQ3pELFNBQU9BLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjQyxNQUFyQjtBQUNBLFNBQU9GLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjRSxNQUFyQjs7QUFFQSxNQUFJSCxNQUFNLENBQUNJLFNBQVAsS0FBcUIsT0FBekIsRUFB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QnFLLG9CQUFoQixDQUFQO0FBQ0Q7O0FBRURHLEVBQUFBLDBCQUEwQixDQUFDSCxvQkFBRCxFQUEyQztBQUNuRSxXQUFPQSxvQkFBb0IsQ0FBQ0ksaUJBQXJCLEdBQXlDOU8sSUFBekMsQ0FBOEMsTUFBTTtBQUN6RDBPLE1BQUFBLG9CQUFvQixDQUFDSyxVQUFyQjtBQUNELEtBRk0sQ0FBUDtBQUdEOztBQUVEQyxFQUFBQSx5QkFBeUIsQ0FBQ04sb0JBQUQsRUFBMkM7QUFDbEUsV0FBT0Esb0JBQW9CLENBQUNPLGdCQUFyQixHQUF3Q2pQLElBQXhDLENBQTZDLE1BQU07QUFDeEQwTyxNQUFBQSxvQkFBb0IsQ0FBQ0ssVUFBckI7QUFDRCxLQUZNLENBQVA7QUFHRDs7QUFqaEN3RDs7O2VBb2hDNUN6TSxtQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG5pbXBvcnQgTW9uZ29Db2xsZWN0aW9uIGZyb20gJy4vTW9uZ29Db2xsZWN0aW9uJztcbmltcG9ydCBNb25nb1NjaGVtYUNvbGxlY3Rpb24gZnJvbSAnLi9Nb25nb1NjaGVtYUNvbGxlY3Rpb24nO1xuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgdHlwZSB7XG4gIFNjaGVtYVR5cGUsXG4gIFF1ZXJ5VHlwZSxcbiAgU3RvcmFnZUNsYXNzLFxuICBRdWVyeU9wdGlvbnMsXG59IGZyb20gJy4uL1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCB7XG4gIHBhcnNlIGFzIHBhcnNlVXJsLFxuICBmb3JtYXQgYXMgZm9ybWF0VXJsLFxufSBmcm9tICcuLi8uLi8uLi92ZW5kb3IvbW9uZ29kYlVybCc7XG5pbXBvcnQge1xuICBwYXJzZU9iamVjdFRvTW9uZ29PYmplY3RGb3JDcmVhdGUsXG4gIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdCxcbiAgdHJhbnNmb3JtS2V5LFxuICB0cmFuc2Zvcm1XaGVyZSxcbiAgdHJhbnNmb3JtVXBkYXRlLFxuICB0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nLFxufSBmcm9tICcuL01vbmdvVHJhbnNmb3JtJztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4uLy4uLy4uL2RlZmF1bHRzJztcbmltcG9ydCBsb2dnZXIgZnJvbSAnLi4vLi4vLi4vbG9nZ2VyJztcblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5jb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgTW9uZ29DbGllbnQgPSBtb25nb2RiLk1vbmdvQ2xpZW50O1xuY29uc3QgUmVhZFByZWZlcmVuY2UgPSBtb25nb2RiLlJlYWRQcmVmZXJlbmNlO1xuXG5jb25zdCBNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lID0gJ19TQ0hFTUEnO1xuXG5jb25zdCBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zID0gbW9uZ29BZGFwdGVyID0+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+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGZpbmQuIEFjY2VwdHM6IGNsYXNzTmFtZSwgcXVlcnkgaW4gUGFyc2UgZm9ybWF0LCBhbmQgeyBza2lwLCBsaW1pdCwgc29ydCB9LlxuICBmaW5kKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHtcbiAgICAgIHNraXAsXG4gICAgICBsaW1pdCxcbiAgICAgIHNvcnQsXG4gICAgICBrZXlzLFxuICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICBoaW50LFxuICAgICAgY2FzZUluc2Vuc2l0aXZlLFxuICAgICAgZXhwbGFpbixcbiAgICB9OiBRdWVyeU9wdGlvbnNcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29XaGVyZSA9IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29Tb3J0ID0gXy5tYXBLZXlzKHNvcnQsICh2YWx1ZSwgZmllbGROYW1lKSA9PlxuICAgICAgdHJhbnNmb3JtS2V5KGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpXG4gICAgKTtcbiAgICBjb25zdCBtb25nb0tleXMgPSBfLnJlZHVjZShcbiAgICAgIGtleXMsXG4gICAgICAobWVtbywga2V5KSA9PiB7XG4gICAgICAgIGlmIChrZXkgPT09ICdBQ0wnKSB7XG4gICAgICAgICAgbWVtb1snX3JwZXJtJ10gPSAxO1xuICAgICAgICAgIG1lbW9bJ193cGVybSddID0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBtZW1vW3RyYW5zZm9ybUtleShjbGFzc05hbWUsIGtleSwgc2NoZW1hKV0gPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgfSxcbiAgICAgIHt9XG4gICAgKTtcblxuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5maW5kKG1vbmdvV2hlcmUsIHtcbiAgICAgICAgICBza2lwLFxuICAgICAgICAgIGxpbWl0LFxuICAgICAgICAgIHNvcnQ6IG1vbmdvU29ydCxcbiAgICAgICAgICBrZXlzOiBtb25nb0tleXMsXG4gICAgICAgICAgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMsXG4gICAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgaGludCxcbiAgICAgICAgICBjYXNlSW5zZW5zaXRpdmUsXG4gICAgICAgICAgZXhwbGFpbixcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC50aGVuKG9iamVjdHMgPT4ge1xuICAgICAgICBpZiAoZXhwbGFpbikge1xuICAgICAgICAgIHJldHVybiBvYmplY3RzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmplY3RzLm1hcChvYmplY3QgPT5cbiAgICAgICAgICBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSlcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBlbnN1cmVJbmRleChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgZmllbGROYW1lczogc3RyaW5nW10sXG4gICAgaW5kZXhOYW1lOiA/c3RyaW5nLFxuICAgIGNhc2VJbnNlbnNpdGl2ZTogYm9vbGVhbiA9IGZhbHNlXG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IGluZGV4Q3JlYXRpb25SZXF1ZXN0ID0ge307XG4gICAgY29uc3QgbW9uZ29GaWVsZE5hbWVzID0gZmllbGROYW1lcy5tYXAoZmllbGROYW1lID0+XG4gICAgICB0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHNjaGVtYSlcbiAgICApO1xuICAgIG1vbmdvRmllbGROYW1lcy5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpbmRleENyZWF0aW9uUmVxdWVzdFtmaWVsZE5hbWVdID0gMTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlZmF1bHRPcHRpb25zOiBPYmplY3QgPSB7IGJhY2tncm91bmQ6IHRydWUsIHNwYXJzZTogdHJ1ZSB9O1xuICAgIGNvbnN0IGluZGV4TmFtZU9wdGlvbnM6IE9iamVjdCA9IGluZGV4TmFtZSA/IHsgbmFtZTogaW5kZXhOYW1lIH0gOiB7fTtcbiAgICBjb25zdCBjYXNlSW5zZW5zaXRpdmVPcHRpb25zOiBPYmplY3QgPSBjYXNlSW5zZW5zaXRpdmVcbiAgICAgID8geyBjb2xsYXRpb246IE1vbmdvQ29sbGVjdGlvbi5jYXNlSW5zZW5zaXRpdmVDb2xsYXRpb24oKSB9XG4gICAgICA6IHt9O1xuICAgIGNvbnN0IGluZGV4T3B0aW9uczogT2JqZWN0ID0ge1xuICAgICAgLi4uZGVmYXVsdE9wdGlvbnMsXG4gICAgICAuLi5jYXNlSW5zZW5zaXRpdmVPcHRpb25zLFxuICAgICAgLi4uaW5kZXhOYW1lT3B0aW9ucyxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihcbiAgICAgICAgY29sbGVjdGlvbiA9PlxuICAgICAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+XG4gICAgICAgICAgICBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uY3JlYXRlSW5kZXgoXG4gICAgICAgICAgICAgIGluZGV4Q3JlYXRpb25SZXF1ZXN0LFxuICAgICAgICAgICAgICBpbmRleE9wdGlvbnMsXG4gICAgICAgICAgICAgIGVycm9yID0+IChlcnJvciA/IHJlamVjdChlcnJvcikgOiByZXNvbHZlKCkpXG4gICAgICAgICAgICApXG4gICAgICAgICAgKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gQ3JlYXRlIGEgdW5pcXVlIGluZGV4LiBVbmlxdWUgaW5kZXhlcyBvbiBudWxsYWJsZSBmaWVsZHMgYXJlIG5vdCBhbGxvd2VkLiBTaW5jZSB3ZSBkb24ndFxuICAvLyBjdXJyZW50bHkga25vdyB3aGljaCBmaWVsZHMgYXJlIG51bGxhYmxlIGFuZCB3aGljaCBhcmVuJ3QsIHdlIGlnbm9yZSB0aGF0IGNyaXRlcmlhLlxuICAvLyBBcyBzdWNoLCB3ZSBzaG91bGRuJ3QgZXhwb3NlIHRoaXMgZnVuY3Rpb24gdG8gdXNlcnMgb2YgcGFyc2UgdW50aWwgd2UgaGF2ZSBhbiBvdXQtb2YtYmFuZFxuICAvLyBXYXkgb2YgZGV0ZXJtaW5pbmcgaWYgYSBmaWVsZCBpcyBudWxsYWJsZS4gVW5kZWZpbmVkIGRvZXNuJ3QgY291bnQgYWdhaW5zdCB1bmlxdWVuZXNzLFxuICAvLyB3aGljaCBpcyB3aHkgd2UgdXNlIHNwYXJzZSBpbmRleGVzLlxuICBlbnN1cmVVbmlxdWVuZXNzKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBmaWVsZE5hbWVzOiBzdHJpbmdbXVxuICApIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgaW5kZXhDcmVhdGlvblJlcXVlc3QgPSB7fTtcbiAgICBjb25zdCBtb25nb0ZpZWxkTmFtZXMgPSBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT5cbiAgICAgIHRyYW5zZm9ybUtleShjbGFzc05hbWUsIGZpZWxkTmFtZSwgc2NoZW1hKVxuICAgICk7XG4gICAgbW9uZ29GaWVsZE5hbWVzLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgIGluZGV4Q3JlYXRpb25SZXF1ZXN0W2ZpZWxkTmFtZV0gPSAxO1xuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PlxuICAgICAgICBjb2xsZWN0aW9uLl9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZChpbmRleENyZWF0aW9uUmVxdWVzdClcbiAgICAgIClcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSxcbiAgICAgICAgICAgICdUcmllZCB0byBlbnN1cmUgZmllbGQgdW5pcXVlbmVzcyBmb3IgYSBjbGFzcyB0aGF0IGFscmVhZHkgaGFzIGR1cGxpY2F0ZXMuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVXNlZCBpbiB0ZXN0c1xuICBfcmF3RmluZChjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IFF1ZXJ5VHlwZSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PlxuICAgICAgICBjb2xsZWN0aW9uLmZpbmQocXVlcnksIHtcbiAgICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIEV4ZWN1dGVzIGEgY291bnQuXG4gIGNvdW50KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nLFxuICAgIGhpbnQ6ID9taXhlZFxuICApIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgcmVhZFByZWZlcmVuY2UgPSB0aGlzLl9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5jb3VudCh0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEsIHRydWUpLCB7XG4gICAgICAgICAgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMsXG4gICAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgaGludCxcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRpc3RpbmN0KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIGZpZWxkTmFtZTogc3RyaW5nXG4gICkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBpc1BvaW50ZXJGaWVsZCA9XG4gICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdQb2ludGVyJztcbiAgICBjb25zdCB0cmFuc2Zvcm1GaWVsZCA9IHRyYW5zZm9ybUtleShjbGFzc05hbWUsIGZpZWxkTmFtZSwgc2NoZW1hKTtcblxuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PlxuICAgICAgICBjb2xsZWN0aW9uLmRpc3RpbmN0KFxuICAgICAgICAgIHRyYW5zZm9ybUZpZWxkLFxuICAgICAgICAgIHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSlcbiAgICAgICAgKVxuICAgICAgKVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiB7XG4gICAgICAgIG9iamVjdHMgPSBvYmplY3RzLmZpbHRlcihvYmogPT4gb2JqICE9IG51bGwpO1xuICAgICAgICByZXR1cm4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQpIHtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nKHNjaGVtYSwgZmllbGROYW1lLCBvYmplY3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpO1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBhZ2dyZWdhdGUoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBhbnksXG4gICAgcGlwZWxpbmU6IGFueSxcbiAgICByZWFkUHJlZmVyZW5jZTogP3N0cmluZyxcbiAgICBoaW50OiA/bWl4ZWQsXG4gICAgZXhwbGFpbj86IGJvb2xlYW5cbiAgKSB7XG4gICAgbGV0IGlzUG9pbnRlckZpZWxkID0gZmFsc2U7XG4gICAgcGlwZWxpbmUgPSBwaXBlbGluZS5tYXAoc3RhZ2UgPT4ge1xuICAgICAgaWYgKHN0YWdlLiRncm91cCkge1xuICAgICAgICBzdGFnZS4kZ3JvdXAgPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWEsIHN0YWdlLiRncm91cCk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBzdGFnZS4kZ3JvdXAuX2lkICYmXG4gICAgICAgICAgdHlwZW9mIHN0YWdlLiRncm91cC5faWQgPT09ICdzdHJpbmcnICYmXG4gICAgICAgICAgc3RhZ2UuJGdyb3VwLl9pZC5pbmRleE9mKCckX3BfJykgPj0gMFxuICAgICAgICApIHtcbiAgICAgICAgICBpc1BvaW50ZXJGaWVsZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kbWF0Y2gpIHtcbiAgICAgICAgc3RhZ2UuJG1hdGNoID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYSwgc3RhZ2UuJG1hdGNoKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kcHJvamVjdCkge1xuICAgICAgICBzdGFnZS4kcHJvamVjdCA9IHRoaXMuX3BhcnNlQWdncmVnYXRlUHJvamVjdEFyZ3MoXG4gICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgIHN0YWdlLiRwcm9qZWN0XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RhZ2U7XG4gICAgfSk7XG4gICAgcmVhZFByZWZlcmVuY2UgPSB0aGlzLl9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5hZ2dyZWdhdGUocGlwZWxpbmUsIHtcbiAgICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgICBoaW50LFxuICAgICAgICAgIGV4cGxhaW4sXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgcmVzdWx0cy5mb3JFYWNoKHJlc3VsdCA9PiB7XG4gICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsICdfaWQnKSkge1xuICAgICAgICAgICAgaWYgKGlzUG9pbnRlckZpZWxkICYmIHJlc3VsdC5faWQpIHtcbiAgICAgICAgICAgICAgcmVzdWx0Ll9pZCA9IHJlc3VsdC5faWQuc3BsaXQoJyQnKVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgcmVzdWx0Ll9pZCA9PSBudWxsIHx8XG4gICAgICAgICAgICAgIHJlc3VsdC5faWQgPT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICAgIChbJ29iamVjdCcsICdzdHJpbmcnXS5pbmNsdWRlcyh0eXBlb2YgcmVzdWx0Ll9pZCkgJiZcbiAgICAgICAgICAgICAgICBfLmlzRW1wdHkocmVzdWx0Ll9pZCkpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgcmVzdWx0Ll9pZCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQub2JqZWN0SWQgPSByZXN1bHQuX2lkO1xuICAgICAgICAgICAgZGVsZXRlIHJlc3VsdC5faWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PlxuICAgICAgICBvYmplY3RzLm1hcChvYmplY3QgPT5cbiAgICAgICAgICBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSlcbiAgICAgICAgKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIHJlY3Vyc2l2ZWx5IHRyYXZlcnNlIHRoZSBwaXBlbGluZSBhbmQgY29udmVydCBhbnkgUG9pbnRlciBvciBEYXRlIGNvbHVtbnMuXG4gIC8vIElmIHdlIGRldGVjdCBhIHBvaW50ZXIgY29sdW1uIHdlIHdpbGwgcmVuYW1lIHRoZSBjb2x1bW4gYmVpbmcgcXVlcmllZCBmb3IgdG8gbWF0Y2ggdGhlIGNvbHVtblxuICAvLyBpbiB0aGUgZGF0YWJhc2UuIFdlIGFsc28gbW9kaWZ5IHRoZSB2YWx1ZSB0byB3aGF0IHdlIGV4cGVjdCB0aGUgdmFsdWUgdG8gYmUgaW4gdGhlIGRhdGFiYXNlXG4gIC8vIGFzIHdlbGwuXG4gIC8vIEZvciBkYXRlcywgdGhlIGRyaXZlciBleHBlY3RzIGEgRGF0ZSBvYmplY3QsIGJ1dCB3ZSBoYXZlIGEgc3RyaW5nIGNvbWluZyBpbi4gU28gd2UnbGwgY29udmVydFxuICAvLyB0aGUgc3RyaW5nIHRvIGEgRGF0ZSBzbyB0aGUgZHJpdmVyIGNhbiBwZXJmb3JtIHRoZSBuZWNlc3NhcnkgY29tcGFyaXNvbi5cbiAgLy9cbiAgLy8gVGhlIGdvYWwgb2YgdGhpcyBtZXRob2QgaXMgdG8gbG9vayBmb3IgdGhlIFwibGVhdmVzXCIgb2YgdGhlIHBpcGVsaW5lIGFuZCBkZXRlcm1pbmUgaWYgaXQgbmVlZHNcbiAgLy8gdG8gYmUgY29udmVydGVkLiBUaGUgcGlwZWxpbmUgY2FuIGhhdmUgYSBmZXcgZGlmZmVyZW50IGZvcm1zLiBGb3IgbW9yZSBkZXRhaWxzLCBzZWU6XG4gIC8vICAgICBodHRwczovL2RvY3MubW9uZ29kYi5jb20vbWFudWFsL3JlZmVyZW5jZS9vcGVyYXRvci9hZ2dyZWdhdGlvbi9cbiAgLy9cbiAgLy8gSWYgdGhlIHBpcGVsaW5lIGlzIGFuIGFycmF5LCBpdCBtZWFucyB3ZSBhcmUgcHJvYmFibHkgcGFyc2luZyBhbiAnJGFuZCcgb3IgJyRvcicgb3BlcmF0b3IuIEluXG4gIC8vIHRoYXQgY2FzZSB3ZSBuZWVkIHRvIGxvb3AgdGhyb3VnaCBhbGwgb2YgaXQncyBjaGlsZHJlbiB0byBmaW5kIHRoZSBjb2x1bW5zIGJlaW5nIG9wZXJhdGVkIG9uLlxuICAvLyBJZiB0aGUgcGlwZWxpbmUgaXMgYW4gb2JqZWN0LCB0aGVuIHdlJ2xsIGxvb3AgdGhyb3VnaCB0aGUga2V5cyBjaGVja2luZyB0byBzZWUgaWYgdGhlIGtleSBuYW1lXG4gIC8vIG1hdGNoZXMgb25lIG9mIHRoZSBzY2hlbWEgY29sdW1ucy4gSWYgaXQgZG9lcyBtYXRjaCBhIGNvbHVtbiBhbmQgdGhlIGNvbHVtbiBpcyBhIFBvaW50ZXIgb3JcbiAgLy8gYSBEYXRlLCB0aGVuIHdlJ2xsIGNvbnZlcnQgdGhlIHZhbHVlIGFzIGRlc2NyaWJlZCBhYm92ZS5cbiAgLy9cbiAgLy8gQXMgbXVjaCBhcyBJIGhhdGUgcmVjdXJzaW9uLi4udGhpcyBzZWVtZWQgbGlrZSBhIGdvb2QgZml0IGZvciBpdC4gV2UncmUgZXNzZW50aWFsbHkgdHJhdmVyc2luZ1xuICAvLyBkb3duIGEgdHJlZSB0byBmaW5kIGEgXCJsZWFmIG5vZGVcIiBhbmQgY2hlY2tpbmcgdG8gc2VlIGlmIGl0IG5lZWRzIHRvIGJlIGNvbnZlcnRlZC5cbiAgX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSk6IGFueSB7XG4gICAgaWYgKHBpcGVsaW5lID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICByZXR1cm4gcGlwZWxpbmUubWFwKHZhbHVlID0+IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHZhbHVlKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBwaXBlbGluZVtmaWVsZF0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBQYXNzIG9iamVjdHMgZG93biB0byBNb25nb0RCLi4udGhpcyBpcyBtb3JlIHRoYW4gbGlrZWx5IGFuICRleGlzdHMgb3BlcmF0b3IuXG4gICAgICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IHBpcGVsaW5lW2ZpZWxkXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWVbXG4gICAgICAgICAgICAgIGBfcF8ke2ZpZWxkfWBcbiAgICAgICAgICAgIF0gPSBgJHtzY2hlbWEuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzc30kJHtwaXBlbGluZVtmaWVsZF19YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiZcbiAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnRGF0ZSdcbiAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fY29udmVydFRvRGF0ZShwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhcbiAgICAgICAgICAgIHNjaGVtYSxcbiAgICAgICAgICAgIHBpcGVsaW5lW2ZpZWxkXVxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2lkJ10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2NyZWF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfdXBkYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHBpcGVsaW5lO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgb25lIGFib3ZlLiBSYXRoZXIgdGhhbiB0cnlpbmcgdG8gY29tYmluZSB0aGVzZVxuICAvLyB0d28gZnVuY3Rpb25zIGFuZCBtYWtpbmcgdGhlIGNvZGUgZXZlbiBoYXJkZXIgdG8gdW5kZXJzdGFuZCwgSSBkZWNpZGVkIHRvIHNwbGl0IGl0IHVwLiBUaGVcbiAgLy8gZGlmZmVyZW5jZSB3aXRoIHRoaXMgZnVuY3Rpb24gaXMgd2UgYXJlIG5vdCB0cmFuc2Zvcm1pbmcgdGhlIHZhbHVlcywgb25seSB0aGUga2V5cyBvZiB0aGVcbiAgLy8gcGlwZWxpbmUuXG4gIF9wYXJzZUFnZ3JlZ2F0ZVByb2plY3RBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbYF9wXyR7ZmllbGR9YF0gPSBwaXBlbGluZVtmaWVsZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hLCBwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19pZCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19jcmVhdGVkX2F0J10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX3VwZGF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgdHdvIGFib3ZlLiBNb25nb0RCICRncm91cCBhZ2dyZWdhdGUgbG9va3MgbGlrZTpcbiAgLy8gICAgIHsgJGdyb3VwOiB7IF9pZDogPGV4cHJlc3Npb24+LCA8ZmllbGQxPjogeyA8YWNjdW11bGF0b3IxPiA6IDxleHByZXNzaW9uMT4gfSwgLi4uIH0gfVxuICAvLyBUaGUgPGV4cHJlc3Npb24+IGNvdWxkIGJlIGEgY29sdW1uIG5hbWUsIHByZWZpeGVkIHdpdGggdGhlICckJyBjaGFyYWN0ZXIuIFdlJ2xsIGxvb2sgZm9yXG4gIC8vIHRoZXNlIDxleHByZXNzaW9uPiBhbmQgY2hlY2sgdG8gc2VlIGlmIGl0IGlzIGEgJ1BvaW50ZXInIG9yIGlmIGl0J3Mgb25lIG9mIGNyZWF0ZWRBdCxcbiAgLy8gdXBkYXRlZEF0IG9yIG9iamVjdElkIGFuZCBjaGFuZ2UgaXQgYWNjb3JkaW5nbHkuXG4gIF9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSk6IGFueSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICByZXR1cm4gcGlwZWxpbmUubWFwKHZhbHVlID0+XG4gICAgICAgIHRoaXMuX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzKHNjaGVtYSwgdmFsdWUpXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTtcbiAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3MoXG4gICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgIHBpcGVsaW5lW2ZpZWxkXVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgZmllbGQgPSBwaXBlbGluZS5zdWJzdHJpbmcoMSk7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgIHJldHVybiBgJF9wXyR7ZmllbGR9YDtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuICckX2NyZWF0ZWRfYXQnO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm4gJyRfdXBkYXRlZF9hdCc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwaXBlbGluZTtcbiAgfVxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBhdHRlbXB0IHRvIGNvbnZlcnQgdGhlIHByb3ZpZGVkIHZhbHVlIHRvIGEgRGF0ZSBvYmplY3QuIFNpbmNlIHRoaXMgaXMgcGFydFxuICAvLyBvZiBhbiBhZ2dyZWdhdGlvbiBwaXBlbGluZSwgdGhlIHZhbHVlIGNhbiBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgaXQgY2FuIGJlIGFub3RoZXIgb2JqZWN0IHdpdGhcbiAgLy8gYW4gb3BlcmF0b3IgaW4gaXQgKGxpa2UgJGd0LCAkbHQsIGV0YykuIEJlY2F1c2Ugb2YgdGhpcyBJIGZlbHQgaXQgd2FzIGVhc2llciB0byBtYWtlIHRoaXMgYVxuICAvLyByZWN1cnNpdmUgbWV0aG9kIHRvIHRyYXZlcnNlIGRvd24gdG8gdGhlIFwibGVhZiBub2RlXCIgd2hpY2ggaXMgZ29pbmcgdG8gYmUgdGhlIHN0cmluZy5cbiAgX2NvbnZlcnRUb0RhdGUodmFsdWU6IGFueSk6IGFueSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIGluIHZhbHVlKSB7XG4gICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9jb252ZXJ0VG9EYXRlKHZhbHVlW2ZpZWxkXSk7XG4gICAgfVxuICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgfVxuXG4gIF9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKTogP3N0cmluZyB7XG4gICAgaWYgKHJlYWRQcmVmZXJlbmNlKSB7XG4gICAgICByZWFkUHJlZmVyZW5jZSA9IHJlYWRQcmVmZXJlbmNlLnRvVXBwZXJDYXNlKCk7XG4gICAgfVxuICAgIHN3aXRjaCAocmVhZFByZWZlcmVuY2UpIHtcbiAgICAgIGNhc2UgJ1BSSU1BUlknOlxuICAgICAgICByZWFkUHJlZmVyZW5jZSA9IFJlYWRQcmVmZXJlbmNlLlBSSU1BUlk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnUFJJTUFSWV9QUkVGRVJSRUQnOlxuICAgICAgICByZWFkUHJlZmVyZW5jZSA9IFJlYWRQcmVmZXJlbmNlLlBSSU1BUllfUFJFRkVSUkVEO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1NFQ09OREFSWSc6XG4gICAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuU0VDT05EQVJZO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1NFQ09OREFSWV9QUkVGRVJSRUQnOlxuICAgICAgICByZWFkUHJlZmVyZW5jZSA9IFJlYWRQcmVmZXJlbmNlLlNFQ09OREFSWV9QUkVGRVJSRUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnTkVBUkVTVCc6XG4gICAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuTkVBUkVTVDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgIGNhc2UgbnVsbDpcbiAgICAgIGNhc2UgJyc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgJ05vdCBzdXBwb3J0ZWQgcmVhZCBwcmVmZXJlbmNlLidcbiAgICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgcGVyZm9ybUluaXRpYWxpemF0aW9uKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4KGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleDogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+XG4gICAgICAgIGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5jcmVhdGVJbmRleChpbmRleCwgeyBiYWNrZ3JvdW5kOiB0cnVlIH0pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBjcmVhdGVJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleGVzOiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT5cbiAgICAgICAgY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4ZXMoaW5kZXhlcywgeyBiYWNrZ3JvdW5kOiB0cnVlIH0pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBjcmVhdGVJbmRleGVzSWZOZWVkZWQoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpIHtcbiAgICBpZiAodHlwZSAmJiB0eXBlLnR5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgY29uc3QgaW5kZXggPSB7XG4gICAgICAgIFtmaWVsZE5hbWVdOiAnMmRzcGhlcmUnLFxuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUluZGV4KGNsYXNzTmFtZSwgaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBjcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgc2NoZW1hOiBhbnlcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gcXVlcnkpIHtcbiAgICAgIGlmICghcXVlcnlbZmllbGROYW1lXSB8fCAhcXVlcnlbZmllbGROYW1lXS4kdGV4dCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4aXN0aW5nSW5kZXhlcyA9IHNjaGVtYS5pbmRleGVzO1xuICAgICAgZm9yIChjb25zdCBrZXkgaW4gZXhpc3RpbmdJbmRleGVzKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gZXhpc3RpbmdJbmRleGVzW2tleV07XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoaW5kZXgsIGZpZWxkTmFtZSkpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IGluZGV4TmFtZSA9IGAke2ZpZWxkTmFtZX1fdGV4dGA7XG4gICAgICBjb25zdCB0ZXh0SW5kZXggPSB7XG4gICAgICAgIFtpbmRleE5hbWVdOiB7IFtmaWVsZE5hbWVdOiAndGV4dCcgfSxcbiAgICAgIH07XG4gICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICB0ZXh0SW5kZXgsXG4gICAgICAgIGV4aXN0aW5nSW5kZXhlcyxcbiAgICAgICAgc2NoZW1hLmZpZWxkc1xuICAgICAgKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSA4NSkge1xuICAgICAgICAgIC8vIEluZGV4IGV4aXN0IHdpdGggZGlmZmVyZW50IG9wdGlvbnNcbiAgICAgICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzRnJvbU1vbmdvKGNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgZ2V0SW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uaW5kZXhlcygpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgZHJvcEluZGV4KGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleDogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5kcm9wSW5kZXgoaW5kZXgpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgZHJvcEFsbEluZGV4ZXMoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmRyb3BJbmRleGVzKCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICB1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcygpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLmdldEFsbENsYXNzZXMoKVxuICAgICAgLnRoZW4oY2xhc3NlcyA9PiB7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gY2xhc3Nlcy5tYXAoc2NoZW1hID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzRnJvbU1vbmdvKHNjaGVtYS5jbGFzc05hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBjcmVhdGVUcmFuc2FjdGlvbmFsU2Vzc2lvbigpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uYWxTZWN0aW9uID0gdGhpcy5jbGllbnQuc3RhcnRTZXNzaW9uKCk7XG4gICAgdHJhbnNhY3Rpb25hbFNlY3Rpb24uc3RhcnRUcmFuc2FjdGlvbigpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJhbnNhY3Rpb25hbFNlY3Rpb24pO1xuICB9XG5cbiAgY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24odHJhbnNhY3Rpb25hbFNlY3Rpb246IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0cmFuc2FjdGlvbmFsU2VjdGlvbi5jb21taXRUcmFuc2FjdGlvbigpLnRoZW4oKCkgPT4ge1xuICAgICAgdHJhbnNhY3Rpb25hbFNlY3Rpb24uZW5kU2Vzc2lvbigpO1xuICAgIH0pO1xuICB9XG5cbiAgYWJvcnRUcmFuc2FjdGlvbmFsU2Vzc2lvbih0cmFuc2FjdGlvbmFsU2VjdGlvbjogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRyYW5zYWN0aW9uYWxTZWN0aW9uLmFib3J0VHJhbnNhY3Rpb24oKS50aGVuKCgpID0+IHtcbiAgICAgIHRyYW5zYWN0aW9uYWxTZWN0aW9uLmVuZFNlc3Npb24oKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBNb25nb1N0b3JhZ2VBZGFwdGVyO1xuIl19 \ 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..9c2899b4d5 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresClient.js @@ -0,0 +1,40 @@ +"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 || {}; + initOptions.noWarnings = process && process.env.TESTING; + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzQ2xpZW50LmpzIl0sIm5hbWVzIjpbInBhcnNlciIsInJlcXVpcmUiLCJjcmVhdGVDbGllbnQiLCJ1cmkiLCJkYXRhYmFzZU9wdGlvbnMiLCJkYk9wdGlvbnMiLCJnZXREYXRhYmFzZU9wdGlvbnNGcm9tVVJJIiwia2V5IiwiaW5pdE9wdGlvbnMiLCJub1dhcm5pbmdzIiwicHJvY2VzcyIsImVudiIsIlRFU1RJTkciLCJwZ3AiLCJjbGllbnQiLCJwZ09wdGlvbnMiLCJwZyIsImRlZmF1bHRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUEsTUFBTUEsTUFBTSxHQUFHQyxPQUFPLENBQUMsd0JBQUQsQ0FBdEI7O0FBRU8sU0FBU0MsWUFBVCxDQUFzQkMsR0FBdEIsRUFBMkJDLGVBQTNCLEVBQTRDO0FBQ2pELE1BQUlDLFNBQVMsR0FBRyxFQUFoQjtBQUNBRCxFQUFBQSxlQUFlLEdBQUdBLGVBQWUsSUFBSSxFQUFyQzs7QUFFQSxNQUFJRCxHQUFKLEVBQVM7QUFDUEUsSUFBQUEsU0FBUyxHQUFHTCxNQUFNLENBQUNNLHlCQUFQLENBQWlDSCxHQUFqQyxDQUFaO0FBQ0Q7O0FBRUQsT0FBSyxNQUFNSSxHQUFYLElBQWtCSCxlQUFsQixFQUFtQztBQUNqQ0MsSUFBQUEsU0FBUyxDQUFDRSxHQUFELENBQVQsR0FBaUJILGVBQWUsQ0FBQ0csR0FBRCxDQUFoQztBQUNEOztBQUVELFFBQU1DLFdBQVcsR0FBR0gsU0FBUyxDQUFDRyxXQUFWLElBQXlCLEVBQTdDO0FBQ0FBLEVBQUFBLFdBQVcsQ0FBQ0MsVUFBWixHQUF5QkMsT0FBTyxJQUFJQSxPQUFPLENBQUNDLEdBQVIsQ0FBWUMsT0FBaEQ7O0FBRUEsUUFBTUMsR0FBRyxHQUFHWixPQUFPLENBQUMsWUFBRCxDQUFQLENBQXNCTyxXQUF0QixDQUFaOztBQUNBLFFBQU1NLE1BQU0sR0FBR0QsR0FBRyxDQUFDUixTQUFELENBQWxCOztBQUVBLE1BQUlBLFNBQVMsQ0FBQ1UsU0FBZCxFQUF5QjtBQUN2QixTQUFLLE1BQU1SLEdBQVgsSUFBa0JGLFNBQVMsQ0FBQ1UsU0FBNUIsRUFBdUM7QUFDckNGLE1BQUFBLEdBQUcsQ0FBQ0csRUFBSixDQUFPQyxRQUFQLENBQWdCVixHQUFoQixJQUF1QkYsU0FBUyxDQUFDVSxTQUFWLENBQW9CUixHQUFwQixDQUF2QjtBQUNEO0FBQ0Y7O0FBRUQsU0FBTztBQUFFTyxJQUFBQSxNQUFGO0FBQVVELElBQUFBO0FBQVYsR0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgcGFyc2VyID0gcmVxdWlyZSgnLi9Qb3N0Z3Jlc0NvbmZpZ1BhcnNlcicpO1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ2xpZW50KHVyaSwgZGF0YWJhc2VPcHRpb25zKSB7XG4gIGxldCBkYk9wdGlvbnMgPSB7fTtcbiAgZGF0YWJhc2VPcHRpb25zID0gZGF0YWJhc2VPcHRpb25zIHx8IHt9O1xuXG4gIGlmICh1cmkpIHtcbiAgICBkYk9wdGlvbnMgPSBwYXJzZXIuZ2V0RGF0YWJhc2VPcHRpb25zRnJvbVVSSSh1cmkpO1xuICB9XG5cbiAgZm9yIChjb25zdCBrZXkgaW4gZGF0YWJhc2VPcHRpb25zKSB7XG4gICAgZGJPcHRpb25zW2tleV0gPSBkYXRhYmFzZU9wdGlvbnNba2V5XTtcbiAgfVxuXG4gIGNvbnN0IGluaXRPcHRpb25zID0gZGJPcHRpb25zLmluaXRPcHRpb25zIHx8IHt9O1xuICBpbml0T3B0aW9ucy5ub1dhcm5pbmdzID0gcHJvY2VzcyAmJiBwcm9jZXNzLmVudi5URVNUSU5HO1xuXG4gIGNvbnN0IHBncCA9IHJlcXVpcmUoJ3BnLXByb21pc2UnKShpbml0T3B0aW9ucyk7XG4gIGNvbnN0IGNsaWVudCA9IHBncChkYk9wdGlvbnMpO1xuXG4gIGlmIChkYk9wdGlvbnMucGdPcHRpb25zKSB7XG4gICAgZm9yIChjb25zdCBrZXkgaW4gZGJPcHRpb25zLnBnT3B0aW9ucykge1xuICAgICAgcGdwLnBnLmRlZmF1bHRzW2tleV0gPSBkYk9wdGlvbnMucGdPcHRpb25zW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgY2xpZW50LCBwZ3AgfTtcbn1cbiJdfQ== \ 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..441f8d42f4 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -0,0 +1,2438 @@ +"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, + caseInsensitive +}) => { + 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; + } + } + + const authDataMatch = fieldName.match(/^_auth_data_([a-zA-Z0-9_]+)$/); + + if (authDataMatch) { + // TODO: Handle querying by _auth_data_provider, authData is stored in authData field + continue; + } else if (caseInsensitive && (fieldName === 'username' || fieldName === 'email')) { + patterns.push(`LOWER($${index}:name) = LOWER($${index + 1})`); + values.push(fieldName, fieldValue); + index += 2; + } else if (fieldName.indexOf('.') >= 0) { + let name = transformDotField(fieldName); + + if (fieldValue === null) { + patterns.push(`$${index}:raw IS NULL`); + values.push(name); + index += 1; + continue; + } 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, + caseInsensitive + }); + + 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(); + } + + async _ensureSchemaCollectionExists(conn) { + conn = conn || this._client; + await 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; + } + }); + } + + async classExists(name) { + return this._client.one('SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)', [name], a => a.exists); + } + + async setClassLevelPermissions(className, CLPs) { + const self = this; + await 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); + }); + } + + async 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 + }); + } + }); + await 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)]); + }); + } + + async createClass(className, schema, conn) { + conn = conn || this._client; + return conn.tx('create-class', async 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); // TODO: The test should not verify the returned value, and then + // the method can be simplified, to avoid returning useless stuff. + + 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 + + + async 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}` + }); + })); + }); + }); + } + + async schemaUpgrade(className, schema, conn) { + debug('schemaUpgrade', { + className, + schema + }); + conn = conn || this._client; + const self = this; + await 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); + }); + } + + async addFieldIfNotExists(className, fieldName, type, conn) { + // TODO: Must be revised for invalid logic... + debug('addFieldIfNotExists', { + className, + fieldName, + type + }); + conn = conn || this._client; + const self = this; + await 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 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. + + + async 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. + + + async deleteAllClasses() { + const now = new Date().getTime(); + const helpers = this._pgp.helpers; + debug('deleteAllClasses'); + await 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. + + + async 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'); + await 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. + + + async 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. + + + async 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 + + + async 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. + + + async deleteObjectsByQuery(className, schema, query, transactionalSession) { + debug('deleteObjectsByQuery', className, query); + const values = [className]; + const index = 2; + const where = buildWhereClause({ + schema, + index, + query, + caseInsensitive: false + }); + 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. + + + async 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. + + + async 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, + caseInsensitive: false + }); + 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, + caseInsensitive + }) { + debug('find', className, query, { + skip, + limit, + sort, + keys, + caseInsensitive + }); + const hasLimit = limit !== undefined; + const hasSkip = skip !== undefined; + let values = [className]; + const where = buildWhereClause({ + schema, + query, + index: 2, + caseInsensitive + }); + 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. + + + async 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. + + + async count(className, schema, query, readPreference, estimate = true) { + debug('count', className, query, readPreference, estimate); + const values = [className]; + const where = buildWhereClause({ + schema, + query, + index: 2, + caseInsensitive: false + }); + 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; + }); + } + + async 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, + caseInsensitive: false + }); + 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))); + } + + async 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; + }); + } + + async 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); + }); + } + + async 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]); + }))); + } + + async createIndexesIfNeeded(className, fieldName, type, conn) { + await (conn || this._client).none('CREATE INDEX $1:name ON $2:name ($3:name)', [fieldName, className, type]); + } + + async dropIndexes(className, indexes, conn) { + const queries = indexes.map(i => ({ + query: 'DROP INDEX $1:name', + values: i + })); + await (conn || this._client).tx(t => t.none(this._pgp.helpers.concat(queries))); + } + + async getIndexes(className) { + const qs = 'SELECT * FROM pg_indexes WHERE tablename = ${className}'; + return this._client.any(qs, { + className + }); + } + + async updateSchemaWithIndexes() { + return Promise.resolve(); + } // Used for testing purposes + + + async updateEstimatedCount(className) { + return this._client.none('ANALYZE $1:name', [className]); + } + + async 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; + } // TODO: implement? + + + ensureIndex() { + return Promise.resolve(); + } + +} + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsiUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVDb2x1bW5FcnJvciIsIlBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVPYmplY3RFcnJvciIsIlBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciIsIlBvc3RncmVzVHJhbnNhY3Rpb25BYm9ydGVkRXJyb3IiLCJsb2dnZXIiLCJyZXF1aXJlIiwiZGVidWciLCJhcmdzIiwiYXJndW1lbnRzIiwiY29uY2F0Iiwic2xpY2UiLCJsZW5ndGgiLCJsb2ciLCJnZXRMb2dnZXIiLCJhcHBseSIsInBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlIiwidHlwZSIsImNvbnRlbnRzIiwiSlNPTiIsInN0cmluZ2lmeSIsIlBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvciIsIiRndCIsIiRsdCIsIiRndGUiLCIkbHRlIiwibW9uZ29BZ2dyZWdhdGVUb1Bvc3RncmVzIiwiJGRheU9mTW9udGgiLCIkZGF5T2ZXZWVrIiwiJGRheU9mWWVhciIsIiRpc29EYXlPZldlZWsiLCIkaXNvV2Vla1llYXIiLCIkaG91ciIsIiRtaW51dGUiLCIkc2Vjb25kIiwiJG1pbGxpc2Vjb25kIiwiJG1vbnRoIiwiJHdlZWsiLCIkeWVhciIsInRvUG9zdGdyZXNWYWx1ZSIsInZhbHVlIiwiX190eXBlIiwiaXNvIiwibmFtZSIsInRyYW5zZm9ybVZhbHVlIiwib2JqZWN0SWQiLCJlbXB0eUNMUFMiLCJPYmplY3QiLCJmcmVlemUiLCJmaW5kIiwiZ2V0IiwiY291bnQiLCJjcmVhdGUiLCJ1cGRhdGUiLCJkZWxldGUiLCJhZGRGaWVsZCIsInByb3RlY3RlZEZpZWxkcyIsImRlZmF1bHRDTFBTIiwidG9QYXJzZVNjaGVtYSIsInNjaGVtYSIsImNsYXNzTmFtZSIsImZpZWxkcyIsIl9oYXNoZWRfcGFzc3dvcmQiLCJfd3Blcm0iLCJfcnBlcm0iLCJjbHBzIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsInRvUG9zdGdyZXNTY2hlbWEiLCJfcGFzc3dvcmRfaGlzdG9yeSIsImhhbmRsZURvdEZpZWxkcyIsIm9iamVjdCIsImtleXMiLCJmb3JFYWNoIiwiZmllbGROYW1lIiwiaW5kZXhPZiIsImNvbXBvbmVudHMiLCJzcGxpdCIsImZpcnN0Iiwic2hpZnQiLCJjdXJyZW50T2JqIiwibmV4dCIsIl9fb3AiLCJ1bmRlZmluZWQiLCJ0cmFuc2Zvcm1Eb3RGaWVsZFRvQ29tcG9uZW50cyIsIm1hcCIsImNtcHQiLCJpbmRleCIsInRyYW5zZm9ybURvdEZpZWxkIiwiam9pbiIsInRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkIiwic3Vic3RyIiwidmFsaWRhdGVLZXlzIiwia2V5IiwiaW5jbHVkZXMiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9ORVNURURfS0VZIiwiam9pblRhYmxlc0ZvclNjaGVtYSIsImxpc3QiLCJmaWVsZCIsInB1c2giLCJidWlsZFdoZXJlQ2xhdXNlIiwicXVlcnkiLCJjYXNlSW5zZW5zaXRpdmUiLCJwYXR0ZXJucyIsInZhbHVlcyIsInNvcnRzIiwiaXNBcnJheUZpZWxkIiwiaW5pdGlhbFBhdHRlcm5zTGVuZ3RoIiwiZmllbGRWYWx1ZSIsIiRleGlzdHMiLCJhdXRoRGF0YU1hdGNoIiwibWF0Y2giLCIkaW4iLCIkcmVnZXgiLCJNQVhfSU5UX1BMVVNfT05FIiwiY2xhdXNlcyIsImNsYXVzZVZhbHVlcyIsInN1YlF1ZXJ5IiwiY2xhdXNlIiwicGF0dGVybiIsIm9yT3JBbmQiLCJub3QiLCIkbmUiLCJjb25zdHJhaW50RmllbGROYW1lIiwicG9pbnQiLCJsb25naXR1ZGUiLCJsYXRpdHVkZSIsIiRlcSIsImlzSW5Pck5pbiIsIkFycmF5IiwiaXNBcnJheSIsIiRuaW4iLCJpblBhdHRlcm5zIiwiYWxsb3dOdWxsIiwibGlzdEVsZW0iLCJsaXN0SW5kZXgiLCJjcmVhdGVDb25zdHJhaW50IiwiYmFzZUFycmF5Iiwibm90SW4iLCJfIiwiZmxhdE1hcCIsImVsdCIsIklOVkFMSURfSlNPTiIsIiRhbGwiLCJpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoIiwiaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSIsImkiLCJwcm9jZXNzUmVnZXhQYXR0ZXJuIiwic3Vic3RyaW5nIiwiJGNvbnRhaW5lZEJ5IiwiYXJyIiwiJHRleHQiLCJzZWFyY2giLCIkc2VhcmNoIiwibGFuZ3VhZ2UiLCIkdGVybSIsIiRsYW5ndWFnZSIsIiRjYXNlU2Vuc2l0aXZlIiwiJGRpYWNyaXRpY1NlbnNpdGl2ZSIsIiRuZWFyU3BoZXJlIiwiZGlzdGFuY2UiLCIkbWF4RGlzdGFuY2UiLCJkaXN0YW5jZUluS00iLCIkd2l0aGluIiwiJGJveCIsImJveCIsImxlZnQiLCJib3R0b20iLCJyaWdodCIsInRvcCIsIiRnZW9XaXRoaW4iLCIkY2VudGVyU3BoZXJlIiwiY2VudGVyU3BoZXJlIiwiR2VvUG9pbnQiLCJHZW9Qb2ludENvZGVyIiwiaXNWYWxpZEpTT04iLCJfdmFsaWRhdGUiLCJpc05hTiIsIiRwb2x5Z29uIiwicG9seWdvbiIsInBvaW50cyIsImNvb3JkaW5hdGVzIiwiJGdlb0ludGVyc2VjdHMiLCIkcG9pbnQiLCJyZWdleCIsIm9wZXJhdG9yIiwib3B0cyIsIiRvcHRpb25zIiwicmVtb3ZlV2hpdGVTcGFjZSIsImNvbnZlcnRQb2x5Z29uVG9TUUwiLCJjbXAiLCJwZ0NvbXBhcmF0b3IiLCJwb3N0Z3Jlc1ZhbHVlIiwiY2FzdFR5cGUiLCJPUEVSQVRJT05fRk9SQklEREVOIiwiUG9zdGdyZXNTdG9yYWdlQWRhcHRlciIsImNvbnN0cnVjdG9yIiwidXJpIiwiY29sbGVjdGlvblByZWZpeCIsImRhdGFiYXNlT3B0aW9ucyIsIl9jb2xsZWN0aW9uUHJlZml4IiwiY2xpZW50IiwicGdwIiwiX2NsaWVudCIsIl9wZ3AiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiaGFuZGxlU2h1dGRvd24iLCIkcG9vbCIsImVuZCIsIl9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzIiwiY29ubiIsIm5vbmUiLCJjYXRjaCIsImVycm9yIiwiY29kZSIsImNsYXNzRXhpc3RzIiwib25lIiwiYSIsImV4aXN0cyIsInNldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsIkNMUHMiLCJzZWxmIiwidGFzayIsInQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsIl9pZF8iLCJfaWQiLCJkZWxldGVkSW5kZXhlcyIsImluc2VydGVkSW5kZXhlcyIsIklOVkFMSURfUVVFUlkiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJ0eCIsImNyZWF0ZUluZGV4ZXMiLCJkcm9wSW5kZXhlcyIsImNyZWF0ZUNsYXNzIiwicTEiLCJjcmVhdGVUYWJsZSIsInEyIiwicTMiLCJiYXRjaCIsInRoZW4iLCJlcnIiLCJkYXRhIiwicmVzdWx0IiwiZGV0YWlsIiwiRFVQTElDQVRFX1ZBTFVFIiwidmFsdWVzQXJyYXkiLCJwYXR0ZXJuc0FycmF5IiwiYXNzaWduIiwiX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0IiwiX2VtYWlsX3ZlcmlmeV90b2tlbiIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIl9mYWlsZWRfbG9naW5fY291bnQiLCJfcGVyaXNoYWJsZV90b2tlbiIsIl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQiLCJfcGFzc3dvcmRfY2hhbmdlZF9hdCIsInJlbGF0aW9ucyIsInBhcnNlVHlwZSIsInFzIiwiam9pblRhYmxlIiwic2NoZW1hVXBncmFkZSIsImNvbHVtbnMiLCJjb2x1bW5fbmFtZSIsIm5ld0NvbHVtbnMiLCJmaWx0ZXIiLCJpdGVtIiwiYWRkRmllbGRJZk5vdEV4aXN0cyIsInBvc3RncmVzVHlwZSIsImFueSIsInBhdGgiLCJkZWxldGVDbGFzcyIsIm9wZXJhdGlvbnMiLCJoZWxwZXJzIiwiZGVsZXRlQWxsQ2xhc3NlcyIsIm5vdyIsIkRhdGUiLCJnZXRUaW1lIiwicmVzdWx0cyIsImpvaW5zIiwicmVkdWNlIiwiY2xhc3NlcyIsInF1ZXJpZXMiLCJkZWxldGVGaWVsZHMiLCJmaWVsZE5hbWVzIiwiaWR4IiwiZ2V0QWxsQ2xhc3NlcyIsInJvdyIsImdldENsYXNzIiwiY3JlYXRlT2JqZWN0IiwidHJhbnNhY3Rpb25hbFNlc3Npb24iLCJjb2x1bW5zQXJyYXkiLCJnZW9Qb2ludHMiLCJwcm92aWRlciIsInBvcCIsImluaXRpYWxWYWx1ZXMiLCJ2YWwiLCJ0ZXJtaW5hdGlvbiIsImdlb1BvaW50c0luamVjdHMiLCJsIiwiY29sdW1uc1BhdHRlcm4iLCJjb2wiLCJ2YWx1ZXNQYXR0ZXJuIiwicHJvbWlzZSIsIm9wcyIsInVuZGVybHlpbmdFcnJvciIsImNvbnN0cmFpbnQiLCJtYXRjaGVzIiwidXNlckluZm8iLCJkdXBsaWNhdGVkX2ZpZWxkIiwiZGVsZXRlT2JqZWN0c0J5UXVlcnkiLCJ3aGVyZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJmaW5kT25lQW5kVXBkYXRlIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cGRhdGVQYXR0ZXJucyIsIm9yaWdpbmFsVXBkYXRlIiwiZG90Tm90YXRpb25PcHRpb25zIiwiZ2VuZXJhdGUiLCJqc29uYiIsImxhc3RLZXkiLCJmaWVsZE5hbWVJbmRleCIsInN0ciIsImFtb3VudCIsIm9iamVjdHMiLCJrZXlzVG9JbmNyZW1lbnQiLCJrIiwiaW5jcmVtZW50UGF0dGVybnMiLCJjIiwia2V5c1RvRGVsZXRlIiwiZGVsZXRlUGF0dGVybnMiLCJwIiwidXBkYXRlT2JqZWN0IiwiZXhwZWN0ZWRUeXBlIiwicmVqZWN0Iiwid2hlcmVDbGF1c2UiLCJ1cHNlcnRPbmVPYmplY3QiLCJjcmVhdGVWYWx1ZSIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJoYXNMaW1pdCIsImhhc1NraXAiLCJ3aGVyZVBhdHRlcm4iLCJsaW1pdFBhdHRlcm4iLCJza2lwUGF0dGVybiIsInNvcnRQYXR0ZXJuIiwic29ydENvcHkiLCJzb3J0aW5nIiwidHJhbnNmb3JtS2V5IiwibWVtbyIsInBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdCIsInRhcmdldENsYXNzIiwieSIsIngiLCJjb29yZHMiLCJwYXJzZUZsb2F0IiwiY3JlYXRlZEF0IiwidG9JU09TdHJpbmciLCJ1cGRhdGVkQXQiLCJleHBpcmVzQXQiLCJlbnN1cmVVbmlxdWVuZXNzIiwiY29uc3RyYWludE5hbWUiLCJjb25zdHJhaW50UGF0dGVybnMiLCJtZXNzYWdlIiwicmVhZFByZWZlcmVuY2UiLCJlc3RpbWF0ZSIsImFwcHJveGltYXRlX3Jvd19jb3VudCIsImRpc3RpbmN0IiwiY29sdW1uIiwiaXNOZXN0ZWQiLCJpc1BvaW50ZXJGaWVsZCIsInRyYW5zZm9ybWVyIiwiY2hpbGQiLCJhZ2dyZWdhdGUiLCJwaXBlbGluZSIsImNvdW50RmllbGQiLCJncm91cFZhbHVlcyIsImdyb3VwUGF0dGVybiIsInN0YWdlIiwiJGdyb3VwIiwiZ3JvdXBCeUZpZWxkcyIsImFsaWFzIiwib3BlcmF0aW9uIiwic291cmNlIiwiJHN1bSIsIiRtYXgiLCIkbWluIiwiJGF2ZyIsIiRwcm9qZWN0IiwiJG1hdGNoIiwiJG9yIiwiY29sbGFwc2UiLCJlbGVtZW50IiwibWF0Y2hQYXR0ZXJucyIsIiRsaW1pdCIsIiRza2lwIiwiJHNvcnQiLCJvcmRlciIsInBhcnNlSW50IiwicGVyZm9ybUluaXRpYWxpemF0aW9uIiwiVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyIsInByb21pc2VzIiwiSU5WQUxJRF9DTEFTU19OQU1FIiwiYWxsIiwic3FsIiwibWlzYyIsImpzb25PYmplY3RTZXRLZXlzIiwiYXJyYXkiLCJhZGQiLCJhZGRVbmlxdWUiLCJyZW1vdmUiLCJjb250YWluc0FsbCIsImNvbnRhaW5zQWxsUmVnZXgiLCJjb250YWlucyIsImR1cmF0aW9uIiwiY29uc29sZSIsImNyZWF0ZUluZGV4ZXNJZk5lZWRlZCIsImdldEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsInVwZGF0ZUVzdGltYXRlZENvdW50IiwiY3JlYXRlVHJhbnNhY3Rpb25hbFNlc3Npb24iLCJjb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbiIsImFib3J0VHJhbnNhY3Rpb25hbFNlc3Npb24iLCJlbnN1cmVJbmRleCIsInVuaXF1ZSIsImFyIiwiZm91bmRJbmRleCIsInB0IiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiZW5kc1dpdGgiLCJyZXBsYWNlIiwidHJpbSIsInMiLCJzdGFydHNXaXRoIiwibGl0ZXJhbGl6ZVJlZ2V4UGFydCIsImlzU3RhcnRzV2l0aFJlZ2V4IiwiZmlyc3RWYWx1ZXNJc1JlZ2V4Iiwic29tZSIsImNyZWF0ZUxpdGVyYWxSZWdleCIsInJlbWFpbmluZyIsIlJlZ0V4cCIsIm1hdGNoZXIxIiwicmVzdWx0MSIsInByZWZpeCIsIm1hdGNoZXIyIiwicmVzdWx0MiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQUVBOztBQUVBOztBQUNBOztBQWlCQTs7Ozs7Ozs7OztBQWZBLE1BQU1BLGlDQUFpQyxHQUFHLE9BQTFDO0FBQ0EsTUFBTUMsOEJBQThCLEdBQUcsT0FBdkM7QUFDQSxNQUFNQyw0QkFBNEIsR0FBRyxPQUFyQztBQUNBLE1BQU1DLDBCQUEwQixHQUFHLE9BQW5DO0FBQ0EsTUFBTUMsNEJBQTRCLEdBQUcsT0FBckM7QUFDQSxNQUFNQyxpQ0FBaUMsR0FBRyxPQUExQztBQUNBLE1BQU1DLCtCQUErQixHQUFHLE9BQXhDOztBQUNBLE1BQU1DLE1BQU0sR0FBR0MsT0FBTyxDQUFDLGlCQUFELENBQXRCOztBQUVBLE1BQU1DLEtBQUssR0FBRyxVQUFTLEdBQUdDLElBQVosRUFBdUI7QUFDbkNBLEVBQUFBLElBQUksR0FBRyxDQUFDLFNBQVNDLFNBQVMsQ0FBQyxDQUFELENBQW5CLEVBQXdCQyxNQUF4QixDQUErQkYsSUFBSSxDQUFDRyxL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Q0FBQ3piLE1BQVIsR0FBaUIsQ0FBNUIsSUFBaUN5YixPQUFPLENBQUM5VyxLQUFSLEdBQWdCLENBQUMsQ0FBdEQsRUFBeUQ7QUFDdkQsVUFBTTRXLE1BQU0sR0FBR1gsQ0FBQyxDQUFDN1YsTUFBRixDQUFTLENBQVQsRUFBWTBXLE9BQU8sQ0FBQzlXLEtBQXBCLENBQWY7QUFDQSxVQUFNd1csU0FBUyxHQUFHTSxPQUFPLENBQUMsQ0FBRCxDQUF6QjtBQUVBLFdBQU9YLG1CQUFtQixDQUFDUyxNQUFELENBQW5CLEdBQThCTCxrQkFBa0IsQ0FBQ0MsU0FBRCxDQUF2RDtBQUNELEdBbkJxQyxDQXFCdEM7OztBQUNBLFNBQU9QLENBQUMsQ0FDTEYsT0FESSxDQUNJLGNBREosRUFDb0IsSUFEcEIsRUFFSkEsT0FGSSxDQUVJLGNBRkosRUFFb0IsSUFGcEIsRUFHSkEsT0FISSxDQUdJLE1BSEosRUFHWSxFQUhaLEVBSUpBLE9BSkksQ0FJSSxNQUpKLEVBSVksRUFKWixFQUtKQSxPQUxJLENBS0ksU0FMSixFQUtnQixNQUxoQixFQU1KQSxPQU5JLENBTUksVUFOSixFQU1pQixNQU5qQixDQUFQO0FBT0Q7O0FBRUQsSUFBSXRRLGFBQWEsR0FBRztBQUNsQkMsRUFBQUEsV0FBVyxDQUFDekksS0FBRCxFQUFRO0FBQ2pCLFdBQ0UsT0FBT0EsS0FBUCxLQUFpQixRQUFqQixJQUE2QkEsS0FBSyxLQUFLLElBQXZDLElBQStDQSxLQUFLLENBQUNDLE1BQU4sS0FBaUIsVUFEbEU7QUFHRDs7QUFMaUIsQ0FBcEI7ZUFRZTRKLHNCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQGZsb3dcbmltcG9ydCB7IGNyZWF0ZUNsaWVudCB9IGZyb20gJy4vUG9zdGdyZXNDbGllbnQnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgc3FsIGZyb20gJy4vc3FsJztcblxuY29uc3QgUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yID0gJzQyUDAxJztcbmNvbnN0IFBvc3RncmVzRHVwbGljYXRlUmVsYXRpb25FcnJvciA9ICc0MlAwNyc7XG5jb25zdCBQb3N0Z3Jlc0R1cGxpY2F0ZUNvbHVtbkVycm9yID0gJzQyNzAxJztcbmNvbnN0IFBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yID0gJzQyNzAzJztcbmNvbnN0IFBvc3RncmVzRHVwbGljYXRlT2JqZWN0RXJyb3IgPSAnNDI3MTAnO1xuY29uc3QgUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yID0gJzIzNTA1JztcbmNvbnN0IFBvc3RncmVzVHJhbnNhY3Rpb25BYm9ydGVkRXJyb3IgPSAnMjVQMDInO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnLi4vLi4vLi4vbG9nZ2VyJyk7XG5cbmNvbnN0IGRlYnVnID0gZnVuY3Rpb24oLi4uYXJnczogYW55KSB7XG4gIGFyZ3MgPSBbJ1BHOiAnICsgYXJndW1lbnRzWzBdXS5jb25jYXQoYXJncy5zbGljZSgxLCBhcmdzLmxlbmd0aCkpO1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZ2V0TG9nZ2VyKCk7XG4gIGxvZy5kZWJ1Zy5hcHBseShsb2csIGFyZ3MpO1xufTtcblxuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgdHlwZSB7IFNjaGVtYVR5cGUsIFF1ZXJ5VHlwZSwgUXVlcnlPcHRpb25zIH0gZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuXG5jb25zdCBwYXJzZVR5cGVUb1Bvc3RncmVzVHlwZSA9IHR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGUudHlwZSkge1xuICAgIGNhc2UgJ1N0cmluZyc6XG4gICAgICByZXR1cm4gJ3RleHQnO1xuICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgcmV0dXJuICd0aW1lc3RhbXAgd2l0aCB0aW1lIHpvbmUnO1xuICAgIGNhc2UgJ09iamVjdCc6XG4gICAgICByZXR1cm4gJ2pzb25iJztcbiAgICBjYXNlICdGaWxlJzpcbiAgICAgIHJldHVybiAndGV4dCc7XG4gICAgY2FzZSAnQm9vbGVhbic6XG4gICAgICByZXR1cm4gJ2Jvb2xlYW4nO1xuICAgIGNhc2UgJ1BvaW50ZXInOlxuICAgICAgcmV0dXJuICdjaGFyKDEwKSc7XG4gICAgY2FzZSAnTnVtYmVyJzpcbiAgICAgIHJldHVybiAnZG91YmxlIHByZWNpc2lvbic7XG4gICAgY2FzZSAnR2VvUG9pbnQnOlxuICAgICAgcmV0dXJuICdwb2ludCc7XG4gICAgY2FzZSAnQnl0ZXMnOlxuICAgICAgcmV0dXJuICdqc29uYic7XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgICByZXR1cm4gJ3BvbHlnb24nO1xuICAgIGNhc2UgJ0FycmF5JzpcbiAgICAgIGlmICh0eXBlLmNvbnRlbnRzICYmIHR5cGUuY29udGVudHMudHlwZSA9PT0gJ1N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuICd0ZXh0W10nO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuICdqc29uYic7XG4gICAgICB9XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IGBubyB0eXBlIGZvciAke0pTT04uc3RyaW5naWZ5KHR5cGUpfSB5ZXRgO1xuICB9XG59O1xuXG5jb25zdCBQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3IgPSB7XG4gICRndDogJz4nLFxuICAkbHQ6ICc8JyxcbiAgJGd0ZTogJz49JyxcbiAgJGx0ZTogJzw9Jyxcbn07XG5cbmNvbnN0IG1vbmdvQWdncmVnYXRlVG9Qb3N0Z3JlcyA9IHtcbiAgJGRheU9mTW9udGg6ICdEQVknLFxuICAkZGF5T2ZXZWVrOiAnRE9XJyxcbiAgJGRheU9mWWVhcjogJ0RPWScsXG4gICRpc29EYXlPZldlZWs6ICdJU09ET1cnLFxuICAkaXNvV2Vla1llYXI6ICdJU09ZRUFSJyxcbiAgJGhvdXI6ICdIT1VSJyxcbiAgJG1pbnV0ZTogJ01JTlVURScsXG4gICRzZWNvbmQ6ICdTRUNPTkQnLFxuICAkbWlsbGlzZWNvbmQ6ICdNSUxMSVNFQ09ORFMnLFxuICAkbW9udGg6ICdNT05USCcsXG4gICR3ZWVrOiAnV0VFSycsXG4gICR5ZWFyOiAnWUVBUicsXG59O1xuXG5jb25zdCB0b1Bvc3RncmVzVmFsdWUgPSB2YWx1ZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgaWYgKHZhbHVlLl9fdHlwZSA9PT0gJ0RhdGUnKSB7XG4gICAgICByZXR1cm4gdmFsdWUuaXNvO1xuICAgIH1cbiAgICBpZiAodmFsdWUuX190eXBlID09PSAnRmlsZScpIHtcbiAgICAgIHJldHVybiB2YWx1ZS5uYW1lO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1WYWx1ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICByZXR1cm4gdmFsdWUub2JqZWN0SWQ7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuLy8gRHVwbGljYXRlIGZyb20gdGhlbiBtb25nbyBhZGFwdGVyLi4uXG5jb25zdCBlbXB0eUNMUFMgPSBPYmplY3QuZnJlZXplKHtcbiAgZmluZDoge30sXG4gIGdldDoge30sXG4gIGNvdW50OiB7fSxcbiAgY3JlYXRlOiB7fSxcbiAgdXBkYXRlOiB7fSxcbiAgZGVsZXRlOiB7fSxcbiAgYWRkRmllbGQ6IHt9LFxuICBwcm90ZWN0ZWRGaWVsZHM6IHt9LFxufSk7XG5cbmNvbnN0IGRlZmF1bHRDTFBTID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGZpbmQ6IHsgJyonOiB0cnVlIH0sXG4gIGdldDogeyAnKic6IHRydWUgfSxcbiAgY291bnQ6IHsgJyonOiB0cnVlIH0sXG4gIGNyZWF0ZTogeyAnKic6IHRydWUgfSxcbiAgdXBkYXRlOiB7ICcqJzogdHJ1ZSB9LFxuICBkZWxldGU6IHsgJyonOiB0cnVlIH0sXG4gIGFkZEZpZWxkOiB7ICcqJzogdHJ1ZSB9LFxuICBwcm90ZWN0ZWRGaWVsZHM6IHsgJyonOiBbXSB9LFxufSk7XG5cbmNvbnN0IHRvUGFyc2VTY2hlbWEgPSBzY2hlbWEgPT4ge1xuICBpZiAoc2NoZW1hLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9oYXNoZWRfcGFzc3dvcmQ7XG4gIH1cbiAgaWYgKHNjaGVtYS5maWVsZHMpIHtcbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5fd3Blcm07XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3JwZXJtO1xuICB9XG4gIGxldCBjbHBzID0gZGVmYXVsdENMUFM7XG4gIGlmIChzY2hlbWEuY2xhc3NMZXZlbFBlcm1pc3Npb25zKSB7XG4gICAgY2xwcyA9IHsgLi4uZW1wdHlDTFBTLCAuLi5zY2hlbWEuY2xhc3NMZXZlbFBlcm1pc3Npb25zIH07XG4gIH1cbiAgbGV0IGluZGV4ZXMgPSB7fTtcbiAgaWYgKHNjaGVtYS5pbmRleGVzKSB7XG4gICAgaW5kZXhlcyA9IHsgLi4uc2NoZW1hLmluZGV4ZXMgfTtcbiAgfVxuICByZXR1cm4ge1xuICAgIGNsYXNzTmFtZTogc2NoZW1hLmNsYXNzTmFtZSxcbiAgICBmaWVsZHM6IHNjaGVtYS5maWVsZHMsXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBjbHBzLFxuICAgIGluZGV4ZXMsXG4gIH07XG59O1xuXG5jb25zdCB0b1Bvc3RncmVzU2NoZW1hID0gc2NoZW1hID0+IHtcbiAgaWYgKCFzY2hlbWEpIHtcbiAgICByZXR1cm4gc2NoZW1hO1xuICB9XG4gIHNjaGVtYS5maWVsZHMgPSBzY2hlbWEuZmllbGRzIHx8IHt9O1xuICBzY2hlbWEuZmllbGRzLl93cGVybSA9IHsgdHlwZTogJ0FycmF5JywgY29udGVudHM6IHsgdHlwZTogJ1N0cmluZycgfSB9O1xuICBzY2hlbWEuZmllbGRzLl9ycGVybSA9IHsgdHlwZTogJ0FycmF5JywgY29udGVudHM6IHsgdHlwZTogJ1N0cmluZycgfSB9O1xuICBpZiAoc2NoZW1hLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgIHNjaGVtYS5maWVsZHMuX2hhc2hlZF9wYXNzd29yZCA9IHsgdHlwZTogJ1N0cmluZycgfTtcbiAgICBzY2hlbWEuZmllbGRzLl9wYXNzd29yZF9oaXN0b3J5ID0geyB0eXBlOiAnQXJyYXknIH07XG4gIH1cbiAgcmV0dXJuIHNjaGVtYTtcbn07XG5cbmNvbnN0IGhhbmRsZURvdEZpZWxkcyA9IG9iamVjdCA9PiB7XG4gIE9iamVjdC5rZXlzKG9iamVjdCkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID4gLTEpIHtcbiAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBmaWVsZE5hbWUuc3BsaXQoJy4nKTtcbiAgICAgIGNvbnN0IGZpcnN0ID0gY29tcG9uZW50cy5zaGlmdCgpO1xuICAgICAgb2JqZWN0W2ZpcnN0XSA9IG9iamVjdFtmaXJzdF0gfHwge307XG4gICAgICBsZXQgY3VycmVudE9iaiA9IG9iamVjdFtmaXJzdF07XG4gICAgICBsZXQgbmV4dDtcbiAgICAgIGxldCB2YWx1ZSA9IG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgaWYgKHZhbHVlICYmIHZhbHVlLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uZC1hc3NpZ24gKi9cbiAgICAgIHdoaWxlICgobmV4dCA9IGNvbXBvbmVudHMuc2hpZnQoKSkpIHtcbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby1jb25kLWFzc2lnbiAqL1xuICAgICAgICBjdXJyZW50T2JqW25leHRdID0gY3VycmVudE9ialtuZXh0XSB8fCB7fTtcbiAgICAgICAgaWYgKGNvbXBvbmVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgY3VycmVudE9ialtuZXh0XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRPYmogPSBjdXJyZW50T2JqW25leHRdO1xuICAgICAgfVxuICAgICAgZGVsZXRlIG9iamVjdFtmaWVsZE5hbWVdO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1Eb3RGaWVsZFRvQ29tcG9uZW50cyA9IGZpZWxkTmFtZSA9PiB7XG4gIHJldHVybiBmaWVsZE5hbWUuc3BsaXQoJy4nKS5tYXAoKGNtcHQsIGluZGV4KSA9PiB7XG4gICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICByZXR1cm4gYFwiJHtjbXB0fVwiYDtcbiAgICB9XG4gICAgcmV0dXJuIGAnJHtjbXB0fSdgO1xuICB9KTtcbn07XG5cbmNvbnN0IHRyYW5zZm9ybURvdEZpZWxkID0gZmllbGROYW1lID0+IHtcbiAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPT09IC0xKSB7XG4gICAgcmV0dXJuIGBcIiR7ZmllbGROYW1lfVwiYDtcbiAgfVxuICBjb25zdCBjb21wb25lbnRzID0gdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMoZmllbGROYW1lKTtcbiAgbGV0IG5hbWUgPSBjb21wb25lbnRzLnNsaWNlKDAsIGNvbXBvbmVudHMubGVuZ3RoIC0gMSkuam9pbignLT4nKTtcbiAgbmFtZSArPSAnLT4+JyArIGNvbXBvbmVudHNbY29tcG9uZW50cy5sZW5ndGggLSAxXTtcbiAgcmV0dXJuIG5hbWU7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1BZ2dyZWdhdGVGaWVsZCA9IGZpZWxkTmFtZSA9PiB7XG4gIGlmICh0eXBlb2YgZmllbGROYW1lICE9PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmaWVsZE5hbWU7XG4gIH1cbiAgaWYgKGZpZWxkTmFtZSA9PT0gJyRfY3JlYXRlZF9hdCcpIHtcbiAgICByZXR1cm4gJ2NyZWF0ZWRBdCc7XG4gIH1cbiAgaWYgKGZpZWxkTmFtZSA9PT0gJyRfdXBkYXRlZF9hdCcpIHtcbiAgICByZXR1cm4gJ3VwZGF0ZWRBdCc7XG4gIH1cbiAgcmV0dXJuIGZpZWxkTmFtZS5zdWJzdHIoMSk7XG59O1xuXG5jb25zdCB2YWxpZGF0ZUtleXMgPSBvYmplY3QgPT4ge1xuICBpZiAodHlwZW9mIG9iamVjdCA9PSAnb2JqZWN0Jykge1xuICAgIGZvciAoY29uc3Qga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKHR5cGVvZiBvYmplY3Rba2V5XSA9PSAnb2JqZWN0Jykge1xuICAgICAgICB2YWxpZGF0ZUtleXMob2JqZWN0W2tleV0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoa2V5LmluY2x1ZGVzKCckJykgfHwga2V5LmluY2x1ZGVzKCcuJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfTkVTVEVEX0tFWSxcbiAgICAgICAgICBcIk5lc3RlZCBrZXlzIHNob3VsZCBub3QgY29udGFpbiB0aGUgJyQnIG9yICcuJyBjaGFyYWN0ZXJzXCJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cbi8vIFJldHVybnMgdGhlIGxpc3Qgb2Ygam9pbiB0YWJsZXMgb24gYSBzY2hlbWFcbmNvbnN0IGpvaW5UYWJsZXNGb3JTY2hlbWEgPSBzY2hlbWEgPT4ge1xuICBjb25zdCBsaXN0ID0gW107XG4gIGlmIChzY2hlbWEpIHtcbiAgICBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKS5mb3JFYWNoKGZpZWxkID0+IHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIGxpc3QucHVzaChgX0pvaW46JHtmaWVsZH06JHtzY2hlbWEuY2xhc3NOYW1lfWApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBsaXN0O1xufTtcblxuaW50ZXJmYWNlIFdoZXJlQ2xhdXNlIHtcbiAgcGF0dGVybjogc3RyaW5nO1xuICB2YWx1ZXM6IEFycmF5PGFueT47XG4gIHNvcnRzOiBBcnJheTxhbnk+O1xufVxuXG5jb25zdCBidWlsZFdoZXJlQ2xhdXNlID0gKHtcbiAgc2NoZW1hLFxuICBxdWVyeSxcbiAgaW5kZXgsXG4gIGNhc2VJbnNlbnNpdGl2ZSxcbn0pOiBXaGVyZUNsYXVzZSA9PiB7XG4gIGNvbnN0IHBhdHRlcm5zID0gW107XG4gIGxldCB2YWx1ZXMgPSBbXTtcbiAgY29uc3Qgc29ydHMgPSBbXTtcblxuICBzY2hlbWEgPSB0b1Bvc3RncmVzU2NoZW1hKHNjaGVtYSk7XG4gIGZvciAoY29uc3QgZmllbGROYW1lIGluIHF1ZXJ5KSB7XG4gICAgY29uc3QgaXNBcnJheUZpZWxkID1cbiAgICAgIHNjaGVtYS5maWVsZHMgJiZcbiAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdBcnJheSc7XG4gICAgY29uc3QgaW5pdGlhbFBhdHRlcm5zTGVuZ3RoID0gcGF0dGVybnMubGVuZ3RoO1xuICAgIGNvbnN0IGZpZWxkVmFsdWUgPSBxdWVyeVtmaWVsZE5hbWVdO1xuXG4gICAgLy8gbm90aGluZyBpbiB0aGUgc2NoZW1hLCBpdCdzIGdvbm5hIGJsb3cgdXBcbiAgICBpZiAoIXNjaGVtYS5maWVsZHNbZmllbGROYW1lXSkge1xuICAgICAgLy8gYXMgaXQgd29uJ3QgZXhpc3RcbiAgICAgIGlmIChmaWVsZFZhbHVlICYmIGZpZWxkVmFsdWUuJGV4aXN0cyA9PT0gZmFsc2UpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYXV0aERhdGFNYXRjaCA9IGZpZWxkTmFtZS5tYXRjaCgvXl9hdXRoX2RhdGFfKFthLXpBLVowLTlfXSspJC8pO1xuICAgIGlmIChhdXRoRGF0YU1hdGNoKSB7XG4gICAgICAvLyBUT0RPOiBIYW5kbGUgcXVlcnlpbmcgYnkgX2F1dGhfZGF0YV9wcm92aWRlciwgYXV0aERhdGEgaXMgc3RvcmVkIGluIGF1dGhEYXRhIGZpZWxkXG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgY2FzZUluc2Vuc2l0aXZlICYmXG4gICAgICAoZmllbGROYW1lID09PSAndXNlcm5hbWUnIHx8IGZpZWxkTmFtZSA9PT0gJ2VtYWlsJylcbiAgICApIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYExPV0VSKCQke2luZGV4fTpuYW1lKSA9IExPV0VSKCQke2luZGV4ICsgMX0pYCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMCkge1xuICAgICAgbGV0IG5hbWUgPSB0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpO1xuICAgICAgaWYgKGZpZWxkVmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9OnJhdyBJUyBOVUxMYCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKG5hbWUpO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmaWVsZFZhbHVlLiRpbikge1xuICAgICAgICAgIG5hbWUgPSB0cmFuc2Zvcm1Eb3RGaWVsZFRvQ29tcG9uZW50cyhmaWVsZE5hbWUpLmpvaW4oJy0+Jyk7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgKCQke2luZGV4fTpyYXcpOjpqc29uYiBAPiAkJHtpbmRleCArIDF9Ojpqc29uYmApO1xuICAgICAgICAgIHZhbHVlcy5wdXNoKG5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUuJGluKSk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLiRyZWdleCkge1xuICAgICAgICAgIC8vIEhhbmRsZSBsYXRlclxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpyYXcgPSAkJHtpbmRleCArIDF9Ojp0ZXh0YCk7XG4gICAgICAgICAgdmFsdWVzLnB1c2gobmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZSA9PT0gbnVsbCB8fCBmaWVsZFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5VTExgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBpbmRleCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgIC8vIENhbid0IGNhc3QgYm9vbGVhbiB0byBkb3VibGUgcHJlY2lzaW9uXG4gICAgICBpZiAoXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ051bWJlcidcbiAgICAgICkge1xuICAgICAgICAvLyBTaG91bGQgYWx3YXlzIHJldHVybiB6ZXJvIHJlc3VsdHNcbiAgICAgICAgY29uc3QgTUFYX0lOVF9QTFVTX09ORSA9IDkyMjMzNzIwMzY4NTQ3NzU4MDg7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgTUFYX0lOVF9QTFVTX09ORSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgfVxuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKFsnJG9yJywgJyRub3InLCAnJGFuZCddLmluY2x1ZGVzKGZpZWxkTmFtZSkpIHtcbiAgICAgIGNvbnN0IGNsYXVzZXMgPSBbXTtcbiAgICAgIGNvbnN0IGNsYXVzZVZhbHVlcyA9IFtdO1xuICAgICAgZmllbGRWYWx1ZS5mb3JFYWNoKHN1YlF1ZXJ5ID0+IHtcbiAgICAgICAgY29uc3QgY2xhdXNlID0gYnVpbGRXaGVyZUNsYXVzZSh7XG4gICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgIHF1ZXJ5OiBzdWJRdWVyeSxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgICBjYXNlSW5zZW5zaXRpdmUsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoY2xhdXNlLnBhdHRlcm4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNsYXVzZXMucHVzaChjbGF1c2UucGF0dGVybik7XG4gICAgICAgICAgY2xhdXNlVmFsdWVzLnB1c2goLi4uY2xhdXNlLnZhbHVlcyk7XG4gICAgICAgICAgaW5kZXggKz0gY2xhdXNlLnZhbHVlcy5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBvck9yQW5kID0gZmllbGROYW1lID09PSAnJGFuZCcgPyAnIEFORCAnIDogJyBPUiAnO1xuICAgICAgY29uc3Qgbm90ID0gZmllbGROYW1lID09PSAnJG5vcicgPyAnIE5PVCAnIDogJyc7XG5cbiAgICAgIHBhdHRlcm5zLnB1c2goYCR7bm90fSgke2NsYXVzZXMuam9pbihvck9yQW5kKX0pYCk7XG4gICAgICB2YWx1ZXMucHVzaCguLi5jbGF1c2VWYWx1ZXMpO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRuZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgIGZpZWxkVmFsdWUuJG5lID0gSlNPTi5zdHJpbmdpZnkoW2ZpZWxkVmFsdWUuJG5lXSk7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYE5PVCBhcnJheV9jb250YWlucygkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfSlgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmaWVsZFZhbHVlLiRuZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5PVCBOVUxMYCk7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGlmIG5vdCBudWxsLCB3ZSBuZWVkIHRvIG1hbnVhbGx5IGV4Y2x1ZGUgbnVsbFxuICAgICAgICAgIGlmIChmaWVsZFZhbHVlLiRuZS5fX3R5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICAgIGAoJCR7aW5kZXh9Om5hbWUgPD4gUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggK1xuICAgICAgICAgICAgICAgIDJ9KSBPUiAkJHtpbmRleH06bmFtZSBJUyBOVUxMKWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDApIHtcbiAgICAgICAgICAgICAgY29uc3QgY29uc3RyYWludEZpZWxkTmFtZSA9IHRyYW5zZm9ybURvdEZpZWxkKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICAgICAgYCgke2NvbnN0cmFpbnRGaWVsZE5hbWV9IDw+ICQke2luZGV4fSBPUiAke2NvbnN0cmFpbnRGaWVsZE5hbWV9IElTIE5VTEwpYFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgICAgICAgICBgKCQke2luZGV4fTpuYW1lIDw+ICQke2luZGV4ICsgMX0gT1IgJCR7aW5kZXh9Om5hbWUgSVMgTlVMTClgXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZmllbGRWYWx1ZS4kbmUuX190eXBlID09PSAnR2VvUG9pbnQnKSB7XG4gICAgICAgIGNvbnN0IHBvaW50ID0gZmllbGRWYWx1ZS4kbmU7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgcG9pbnQubG9uZ2l0dWRlLCBwb2ludC5sYXRpdHVkZSk7XG4gICAgICAgIGluZGV4ICs9IDM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBUT0RPOiBzdXBwb3J0IGFycmF5c1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUuJG5lKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGZpZWxkVmFsdWUuJGVxICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChmaWVsZFZhbHVlLiRlcSA9PT0gbnVsbCkge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSBJUyBOVUxMYCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+PSAwKSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGRWYWx1ZS4kZXEpO1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCR7dHJhbnNmb3JtRG90RmllbGQoZmllbGROYW1lKX0gPSAkJHtpbmRleCsrfWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS4kZXEpO1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaXNJbk9yTmluID1cbiAgICAgIEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kaW4pIHx8IEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kbmluKTtcbiAgICBpZiAoXG4gICAgICBBcnJheS5pc0FycmF5KGZpZWxkVmFsdWUuJGluKSAmJlxuICAgICAgaXNBcnJheUZpZWxkICYmXG4gICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0uY29udGVudHMgJiZcbiAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5jb250ZW50cy50eXBlID09PSAnU3RyaW5nJ1xuICAgICkge1xuICAgICAgY29uc3QgaW5QYXR0ZXJucyA9IFtdO1xuICAgICAgbGV0IGFsbG93TnVsbCA9IGZhbHNlO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgIGZpZWxkVmFsdWUuJGluLmZvckVhY2goKGxpc3RFbGVtLCBsaXN0SW5kZXgpID0+IHtcbiAgICAgICAgaWYgKGxpc3RFbGVtID09PSBudWxsKSB7XG4gICAgICAgICAgYWxsb3dOdWxsID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWx1ZXMucHVzaChsaXN0RWxlbSk7XG4gICAgICAgICAgaW5QYXR0ZXJucy5wdXNoKGAkJHtpbmRleCArIDEgKyBsaXN0SW5kZXggLSAoYWxsb3dOdWxsID8gMSA6IDApfWApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGlmIChhbGxvd051bGwpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgICBgKCQke2luZGV4fTpuYW1lIElTIE5VTEwgT1IgJCR7aW5kZXh9Om5hbWUgJiYgQVJSQVlbJHtpblBhdHRlcm5zLmpvaW4oKX1dKWBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lICYmIEFSUkFZWyR7aW5QYXR0ZXJucy5qb2luKCl9XWApO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDEgKyBpblBhdHRlcm5zLmxlbmd0aDtcbiAgICB9IGVsc2UgaWYgKGlzSW5Pck5pbikge1xuICAgICAgdmFyIGNyZWF0ZUNvbnN0cmFpbnQgPSAoYmFzZUFycmF5LCBub3RJbikgPT4ge1xuICAgICAgICBjb25zdCBub3QgPSBub3RJbiA/ICcgTk9UICcgOiAnJztcbiAgICAgICAgaWYgKGJhc2VBcnJheS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgaWYgKGlzQXJyYXlGaWVsZCkge1xuICAgICAgICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgICAgICAgYCR7bm90fSBhcnJheV9jb250YWlucygkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfSlgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShiYXNlQXJyYXkpKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBOZXN0ZWQgRG90IE5vdGF0aW9uIEFib3ZlXG4gICAgICAgICAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+PSAwKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGluUGF0dGVybnMgPSBbXTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICBiYXNlQXJyYXkuZm9yRWFjaCgobGlzdEVsZW0sIGxpc3RJbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAobGlzdEVsZW0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGxpc3RFbGVtKTtcbiAgICAgICAgICAgICAgICBpblBhdHRlcm5zLnB1c2goYCQke2luZGV4ICsgMSArIGxpc3RJbmRleH1gKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSAke25vdH0gSU4gKCR7aW5QYXR0ZXJucy5qb2luKCl9KWApO1xuICAgICAgICAgICAgaW5kZXggPSBpbmRleCArIDEgKyBpblBhdHRlcm5zLmxlbmd0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIW5vdEluKSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSBJUyBOVUxMYCk7XG4gICAgICAgICAgaW5kZXggPSBpbmRleCArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gSGFuZGxlIGVtcHR5IGFycmF5XG4gICAgICAgICAgaWYgKG5vdEluKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKCcxID0gMScpOyAvLyBSZXR1cm4gYWxsIHZhbHVlc1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKCcxID0gMicpOyAvLyBSZXR1cm4gbm8gdmFsdWVzXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaWYgKGZpZWxkVmFsdWUuJGluKSB7XG4gICAgICAgIGNyZWF0ZUNvbnN0cmFpbnQoXG4gICAgICAgICAgXy5mbGF0TWFwKGZpZWxkVmFsdWUuJGluLCBlbHQgPT4gZWx0KSxcbiAgICAgICAgICBmYWxzZVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKGZpZWxkVmFsdWUuJG5pbikge1xuICAgICAgICBjcmVhdGVDb25zdHJhaW50KFxuICAgICAgICAgIF8uZmxhdE1hcChmaWVsZFZhbHVlLiRuaW4sIGVsdCA9PiBlbHQpLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlLiRpbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdiYWQgJGluIHZhbHVlJyk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZS4kbmluICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAkbmluIHZhbHVlJyk7XG4gICAgfVxuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kYWxsKSAmJiBpc0FycmF5RmllbGQpIHtcbiAgICAgIGlmIChpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoKGZpZWxkVmFsdWUuJGFsbCkpIHtcbiAgICAgICAgaWYgKCFpc0FsbFZhbHVlc1JlZ2V4T3JOb25lKGZpZWxkVmFsdWUuJGFsbCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnQWxsICRhbGwgdmFsdWVzIG11c3QgYmUgb2YgcmVnZXggdHlwZSBvciBub25lOiAnICsgZmllbGRWYWx1ZS4kYWxsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmllbGRWYWx1ZS4kYWxsLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBwcm9jZXNzUmVnZXhQYXR0ZXJuKGZpZWxkVmFsdWUuJGFsbFtpXS4kcmVnZXgpO1xuICAgICAgICAgIGZpZWxkVmFsdWUuJGFsbFtpXSA9IHZhbHVlLnN1YnN0cmluZygxKSArICclJztcbiAgICAgICAgfVxuICAgICAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGBhcnJheV9jb250YWluc19hbGxfcmVnZXgoJCR7aW5kZXh9Om5hbWUsICQke2luZGV4ICsgMX06Ompzb25iKWBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgYGFycmF5X2NvbnRhaW5zX2FsbCgkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfTo6anNvbmIpYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlLiRhbGwpKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGZpZWxkVmFsdWUuJGFsbCkpIHtcbiAgICAgIGlmIChmaWVsZFZhbHVlLiRhbGwubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUuJGFsbFswXS5vYmplY3RJZCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBmaWVsZFZhbHVlLiRleGlzdHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBpZiAoZmllbGRWYWx1ZS4kZXhpc3RzKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5PVCBOVUxMYCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSBJUyBOVUxMYCk7XG4gICAgICB9XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgaW5kZXggKz0gMTtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kY29udGFpbmVkQnkpIHtcbiAgICAgIGNvbnN0IGFyciA9IGZpZWxkVmFsdWUuJGNvbnRhaW5lZEJ5O1xuICAgICAgaWYgKCEoYXJyIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkY29udGFpbmVkQnk6IHNob3VsZCBiZSBhbiBhcnJheWBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPEAgJCR7aW5kZXggKyAxfTo6anNvbmJgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoYXJyKSk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiR0ZXh0KSB7XG4gICAgICBjb25zdCBzZWFyY2ggPSBmaWVsZFZhbHVlLiR0ZXh0LiRzZWFyY2g7XG4gICAgICBsZXQgbGFuZ3VhZ2UgPSAnZW5nbGlzaCc7XG4gICAgICBpZiAodHlwZW9mIHNlYXJjaCAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkc2VhcmNoLCBzaG91bGQgYmUgb2JqZWN0YFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKCFzZWFyY2guJHRlcm0gfHwgdHlwZW9mIHNlYXJjaC4kdGVybSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkdGVybSwgc2hvdWxkIGJlIHN0cmluZ2BcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmIChzZWFyY2guJGxhbmd1YWdlICYmIHR5cGVvZiBzZWFyY2guJGxhbmd1YWdlICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRsYW5ndWFnZSwgc2hvdWxkIGJlIHN0cmluZ2BcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VhcmNoLiRsYW5ndWFnZSkge1xuICAgICAgICBsYW5ndWFnZSA9IHNlYXJjaC4kbGFuZ3VhZ2U7XG4gICAgICB9XG4gICAgICBpZiAoc2VhcmNoLiRjYXNlU2Vuc2l0aXZlICYmIHR5cGVvZiBzZWFyY2guJGNhc2VTZW5zaXRpdmUgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRjYXNlU2Vuc2l0aXZlLCBzaG91bGQgYmUgYm9vbGVhbmBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VhcmNoLiRjYXNlU2Vuc2l0aXZlKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGNhc2VTZW5zaXRpdmUgbm90IHN1cHBvcnRlZCwgcGxlYXNlIHVzZSAkcmVnZXggb3IgY3JlYXRlIGEgc2VwYXJhdGUgbG93ZXIgY2FzZSBjb2x1bW4uYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICBzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZSAmJlxuICAgICAgICB0eXBlb2Ygc2VhcmNoLiRkaWFjcml0aWNTZW5zaXRpdmUgIT09ICdib29sZWFuJ1xuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGRpYWNyaXRpY1NlbnNpdGl2ZSwgc2hvdWxkIGJlIGJvb2xlYW5gXG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlID09PSBmYWxzZSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRkaWFjcml0aWNTZW5zaXRpdmUgLSBmYWxzZSBub3Qgc3VwcG9ydGVkLCBpbnN0YWxsIFBvc3RncmVzIFVuYWNjZW50IEV4dGVuc2lvbmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgIGB0b190c3ZlY3RvcigkJHtpbmRleH0sICQke2luZGV4ICsgMX06bmFtZSkgQEAgdG9fdHNxdWVyeSgkJHtpbmRleCArXG4gICAgICAgICAgMn0sICQke2luZGV4ICsgM30pYFxuICAgICAgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGxhbmd1YWdlLCBmaWVsZE5hbWUsIGxhbmd1YWdlLCBzZWFyY2guJHRlcm0pO1xuICAgICAgaW5kZXggKz0gNDtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kbmVhclNwaGVyZSkge1xuICAgICAgY29uc3QgcG9pbnQgPSBmaWVsZFZhbHVlLiRuZWFyU3BoZXJlO1xuICAgICAgY29uc3QgZGlzdGFuY2UgPSBmaWVsZFZhbHVlLiRtYXhEaXN0YW5jZTtcbiAgICAgIGNvbnN0IGRpc3RhbmNlSW5LTSA9IGRpc3RhbmNlICogNjM3MSAqIDEwMDA7XG4gICAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgICBgU1RfZGlzdGFuY2Vfc3BoZXJlKCQke2luZGV4fTpuYW1lOjpnZW9tZXRyeSwgUE9JTlQoJCR7aW5kZXggK1xuICAgICAgICAgIDF9LCAkJHtpbmRleCArIDJ9KTo6Z2VvbWV0cnkpIDw9ICQke2luZGV4ICsgM31gXG4gICAgICApO1xuICAgICAgc29ydHMucHVzaChcbiAgICAgICAgYFNUX2Rpc3RhbmNlX3NwaGVyZSgkJHtpbmRleH06bmFtZTo6Z2VvbWV0cnksIFBPSU5UKCQke2luZGV4ICtcbiAgICAgICAgICAxfSwgJCR7aW5kZXggKyAyfSk6Omdlb21ldHJ5KSBBU0NgXG4gICAgICApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlLCBkaXN0YW5jZUluS00pO1xuICAgICAgaW5kZXggKz0gNDtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kd2l0aGluICYmIGZpZWxkVmFsdWUuJHdpdGhpbi4kYm94KSB7XG4gICAgICBjb25zdCBib3ggPSBmaWVsZFZhbHVlLiR3aXRoaW4uJGJveDtcbiAgICAgIGNvbnN0IGxlZnQgPSBib3hbMF0ubG9uZ2l0dWRlO1xuICAgICAgY29uc3QgYm90dG9tID0gYm94WzBdLmxhdGl0dWRlO1xuICAgICAgY29uc3QgcmlnaHQgPSBib3hbMV0ubG9uZ2l0dWRlO1xuICAgICAgY29uc3QgdG9wID0gYm94WzFdLmxhdGl0dWRlO1xuXG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZTo6cG9pbnQgPEAgJCR7aW5kZXggKyAxfTo6Ym94YCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGAoKCR7bGVmdH0sICR7Ym90dG9tfSksICgke3JpZ2h0fSwgJHt0b3B9KSlgKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJGdlb1dpdGhpbiAmJiBmaWVsZFZhbHVlLiRnZW9XaXRoaW4uJGNlbnRlclNwaGVyZSkge1xuICAgICAgY29uc3QgY2VudGVyU3BoZXJlID0gZmllbGRWYWx1ZS4kZ2VvV2l0aGluLiRjZW50ZXJTcGhlcmU7XG4gICAgICBpZiAoIShjZW50ZXJTcGhlcmUgaW5zdGFuY2VvZiBBcnJheSkgfHwgY2VudGVyU3BoZXJlLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRjZW50ZXJTcGhlcmUgc2hvdWxkIGJlIGFuIGFycmF5IG9mIFBhcnNlLkdlb1BvaW50IGFuZCBkaXN0YW5jZSdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIC8vIEdldCBwb2ludCwgY29udmVydCB0byBnZW8gcG9pbnQgaWYgbmVjZXNzYXJ5IGFuZCB2YWxpZGF0ZVxuICAgICAgbGV0IHBvaW50ID0gY2VudGVyU3BoZXJlWzBdO1xuICAgICAgaWYgKHBvaW50IGluc3RhbmNlb2YgQXJyYXkgJiYgcG9pbnQubGVuZ3RoID09PSAyKSB7XG4gICAgICAgIHBvaW50ID0gbmV3IFBhcnNlLkdlb1BvaW50KHBvaW50WzFdLCBwb2ludFswXSk7XG4gICAgICB9IGVsc2UgaWYgKCFHZW9Qb2ludENvZGVyLmlzVmFsaWRKU09OKHBvaW50KSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJGNlbnRlclNwaGVyZSBnZW8gcG9pbnQgaW52YWxpZCdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwb2ludC5sYXRpdHVkZSwgcG9pbnQubG9uZ2l0dWRlKTtcbiAgICAgIC8vIEdldCBkaXN0YW5jZSBhbmQgdmFsaWRhdGVcbiAgICAgIGNvbnN0IGRpc3RhbmNlID0gY2VudGVyU3BoZXJlWzFdO1xuICAgICAgaWYgKGlzTmFOKGRpc3RhbmNlKSB8fCBkaXN0YW5jZSA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRjZW50ZXJTcGhlcmUgZGlzdGFuY2UgaW52YWxpZCdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRpc3RhbmNlSW5LTSA9IGRpc3RhbmNlICogNjM3MSAqIDEwMDA7XG4gICAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgICBgU1RfZGlzdGFuY2Vfc3BoZXJlKCQke2luZGV4fTpuYW1lOjpnZW9tZXRyeSwgUE9JTlQoJCR7aW5kZXggK1xuICAgICAgICAgIDF9LCAkJHtpbmRleCArIDJ9KTo6Z2VvbWV0cnkpIDw9ICQke2luZGV4ICsgM31gXG4gICAgICApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlLCBkaXN0YW5jZUluS00pO1xuICAgICAgaW5kZXggKz0gNDtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kZ2VvV2l0aGluICYmIGZpZWxkVmFsdWUuJGdlb1dpdGhpbi4kcG9seWdvbikge1xuICAgICAgY29uc3QgcG9seWdvbiA9IGZpZWxkVmFsdWUuJGdlb1dpdGhpbi4kcG9seWdvbjtcbiAgICAgIGxldCBwb2ludHM7XG4gICAgICBpZiAodHlwZW9mIHBvbHlnb24gPT09ICdvYmplY3QnICYmIHBvbHlnb24uX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgaWYgKCFwb2x5Z29uLmNvb3JkaW5hdGVzIHx8IHBvbHlnb24uY29vcmRpbmF0ZXMubGVuZ3RoIDwgMykge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgUG9seWdvbi5jb29yZGluYXRlcyBzaG91bGQgY29udGFpbiBhdCBsZWFzdCAzIGxvbi9sYXQgcGFpcnMnXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBwb2ludHMgPSBwb2x5Z29uLmNvb3JkaW5hdGVzO1xuICAgICAgfSBlbHNlIGlmIChwb2x5Z29uIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgaWYgKHBvbHlnb24ubGVuZ3RoIDwgMykge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJHBvbHlnb24gc2hvdWxkIGNvbnRhaW4gYXQgbGVhc3QgMyBHZW9Qb2ludHMnXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBwb2ludHMgPSBwb2x5Z29uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBcImJhZCAkZ2VvV2l0aGluIHZhbHVlOyAkcG9seWdvbiBzaG91bGQgYmUgUG9seWdvbiBvYmplY3Qgb3IgQXJyYXkgb2YgUGFyc2UuR2VvUG9pbnQnc1wiXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBwb2ludHMgPSBwb2ludHNcbiAgICAgICAgLm1hcChwb2ludCA9PiB7XG4gICAgICAgICAgaWYgKHBvaW50IGluc3RhbmNlb2YgQXJyYXkgJiYgcG9pbnQubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnRbMV0sIHBvaW50WzBdKTtcbiAgICAgICAgICAgIHJldHVybiBgKCR7cG9pbnRbMF19LCAke3BvaW50WzFdfSlgO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodHlwZW9mIHBvaW50ICE9PSAnb2JqZWN0JyB8fCBwb2ludC5fX3R5cGUgIT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWUnXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgKCR7cG9pbnQubG9uZ2l0dWRlfSwgJHtwb2ludC5sYXRpdHVkZX0pYDtcbiAgICAgICAgfSlcbiAgICAgICAgLmpvaW4oJywgJyk7XG5cbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lOjpwb2ludCA8QCAkJHtpbmRleCArIDF9Ojpwb2x5Z29uYCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGAoJHtwb2ludHN9KWApO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG4gICAgaWYgKGZpZWxkVmFsdWUuJGdlb0ludGVyc2VjdHMgJiYgZmllbGRWYWx1ZS4kZ2VvSW50ZXJzZWN0cy4kcG9pbnQpIHtcbiAgICAgIGNvbnN0IHBvaW50ID0gZmllbGRWYWx1ZS4kZ2VvSW50ZXJzZWN0cy4kcG9pbnQ7XG4gICAgICBpZiAodHlwZW9mIHBvaW50ICE9PSAnb2JqZWN0JyB8fCBwb2ludC5fX3R5cGUgIT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAnYmFkICRnZW9JbnRlcnNlY3QgdmFsdWU7ICRwb2ludCBzaG91bGQgYmUgR2VvUG9pbnQnXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICB9XG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZTo6cG9seWdvbiBAPiAkJHtpbmRleCArIDF9Ojpwb2ludGApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBgKCR7cG9pbnQubG9uZ2l0dWRlfSwgJHtwb2ludC5sYXRpdHVkZX0pYCk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRyZWdleCkge1xuICAgICAgbGV0IHJlZ2V4ID0gZmllbGRWYWx1ZS4kcmVnZXg7XG4gICAgICBsZXQgb3BlcmF0b3IgPSAnfic7XG4gICAgICBjb25zdCBvcHRzID0gZmllbGRWYWx1ZS4kb3B0aW9ucztcbiAgICAgIGlmIChvcHRzKSB7XG4gICAgICAgIGlmIChvcHRzLmluZGV4T2YoJ2knKSA+PSAwKSB7XG4gICAgICAgICAgb3BlcmF0b3IgPSAnfionO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRzLmluZGV4T2YoJ3gnKSA+PSAwKSB7XG4gICAgICAgICAgcmVnZXggPSByZW1vdmVXaGl0ZVNwYWNlKHJlZ2V4KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBuYW1lID0gdHJhbnNmb3JtRG90RmllbGQoZmllbGROYW1lKTtcbiAgICAgIHJlZ2V4ID0gcHJvY2Vzc1JlZ2V4UGF0dGVybihyZWdleCk7XG5cbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpyYXcgJHtvcGVyYXRvcn0gJyQke2luZGV4ICsgMX06cmF3J2ApO1xuICAgICAgdmFsdWVzLnB1c2gobmFtZSwgcmVnZXgpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS5fX3R5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgaWYgKGlzQXJyYXlGaWVsZCkge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGBhcnJheV9jb250YWlucygkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfSlgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShbZmllbGRWYWx1ZV0pKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUub2JqZWN0SWQpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ0RhdGUnKSB7XG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5pc28pO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS5fX3R5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIH49IFBPSU5UKCQke2luZGV4ICsgMX0sICQke2luZGV4ICsgMn0pYCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUubG9uZ2l0dWRlLCBmaWVsZFZhbHVlLmxhdGl0dWRlKTtcbiAgICAgIGluZGV4ICs9IDM7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFBvbHlnb25Ub1NRTChmaWVsZFZhbHVlLmNvb3JkaW5hdGVzKTtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIH49ICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgdmFsdWUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBPYmplY3Qua2V5cyhQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3IpLmZvckVhY2goY21wID0+IHtcbiAgICAgIGlmIChmaWVsZFZhbHVlW2NtcF0gfHwgZmllbGRWYWx1ZVtjbXBdID09PSAwKSB7XG4gICAgICAgIGNvbnN0IHBnQ29tcGFyYXRvciA9IFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcltjbXBdO1xuICAgICAgICBjb25zdCBwb3N0Z3Jlc1ZhbHVlID0gdG9Qb3N0Z3Jlc1ZhbHVlKGZpZWxkVmFsdWVbY21wXSk7XG4gICAgICAgIGxldCBjb25zdHJhaW50RmllbGROYW1lO1xuICAgICAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+PSAwKSB7XG4gICAgICAgICAgbGV0IGNhc3RUeXBlO1xuICAgICAgICAgIHN3aXRjaCAodHlwZW9mIHBvc3RncmVzVmFsdWUpIHtcbiAgICAgICAgICAgIGNhc2UgJ251bWJlcic6XG4gICAgICAgICAgICAgIGNhc3RUeXBlID0gJ2RvdWJsZSBwcmVjaXNpb24nO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgICAgICAgICAgICBjYXN0VHlwZSA9ICdib29sZWFuJztcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICBjYXN0VHlwZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3RyYWludEZpZWxkTmFtZSA9IGNhc3RUeXBlXG4gICAgICAgICAgICA/IGBDQVNUICgoJHt0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpfSkgQVMgJHtjYXN0VHlwZX0pYFxuICAgICAgICAgICAgOiB0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0cmFpbnRGaWVsZE5hbWUgPSBgJCR7aW5kZXgrK306bmFtZWA7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZXMucHVzaChwb3N0Z3Jlc1ZhbHVlKTtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJHtjb25zdHJhaW50RmllbGROYW1lfSAke3BnQ29tcGFyYXRvcn0gJCR7aW5kZXgrK31gKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChpbml0aWFsUGF0dGVybnNMZW5ndGggPT09IHBhdHRlcm5zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICBgUG9zdGdyZXMgZG9lc24ndCBzdXBwb3J0IHRoaXMgcXVlcnkgdHlwZSB5ZXQgJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICBmaWVsZFZhbHVlXG4gICAgICAgICl9YFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgdmFsdWVzID0gdmFsdWVzLm1hcCh0cmFuc2Zvcm1WYWx1ZSk7XG4gIHJldHVybiB7IHBhdHRlcm46IHBhdHRlcm5zLmpvaW4oJyBBTkQgJyksIHZhbHVlcywgc29ydHMgfTtcbn07XG5cbmV4cG9ydCBjbGFzcyBQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyIGltcGxlbWVudHMgU3RvcmFnZUFkYXB0ZXIge1xuICBjYW5Tb3J0T25Kb2luVGFibGVzOiBib29sZWFuO1xuXG4gIC8vIFByaXZhdGVcbiAgX2NvbGxlY3Rpb25QcmVmaXg6IHN0cmluZztcbiAgX2NsaWVudDogYW55O1xuICBfcGdwOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoeyB1cmksIGNvbGxlY3Rpb25QcmVmaXggPSAnJywgZGF0YWJhc2VPcHRpb25zIH06IGFueSkge1xuICAgIHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggPSBjb2xsZWN0aW9uUHJlZml4O1xuICAgIGNvbnN0IHsgY2xpZW50LCBwZ3AgfSA9IGNyZWF0ZUNsaWVudCh1cmksIGRhdGFiYXNlT3B0aW9ucyk7XG4gICAgdGhpcy5fY2xpZW50ID0gY2xpZW50O1xuICAgIHRoaXMuX3BncCA9IHBncDtcbiAgICB0aGlzLmNhblNvcnRPbkpvaW5UYWJsZXMgPSBmYWxzZTtcbiAgfVxuXG4gIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGlmICghdGhpcy5fY2xpZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX2NsaWVudC4kcG9vbC5lbmQoKTtcbiAgfVxuXG4gIGFzeW5jIF9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzKGNvbm46IGFueSkge1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICBhd2FpdCBjb25uXG4gICAgICAubm9uZShcbiAgICAgICAgJ0NSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIFwiX1NDSEVNQVwiICggXCJjbGFzc05hbWVcIiB2YXJDaGFyKDEyMCksIFwic2NoZW1hXCIganNvbmIsIFwiaXNQYXJzZUNsYXNzXCIgYm9vbCwgUFJJTUFSWSBLRVkgKFwiY2xhc3NOYW1lXCIpICknXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yIHx8XG4gICAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yIHx8XG4gICAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVPYmplY3RFcnJvclxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBUYWJsZSBhbHJlYWR5IGV4aXN0cywgbXVzdCBoYXZlIGJlZW4gY3JlYXRlZCBieSBhIGRpZmZlcmVudCByZXF1ZXN0LiBJZ25vcmUgZXJyb3IuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgY2xhc3NFeGlzdHMobmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5vbmUoXG4gICAgICAnU0VMRUNUIEVYSVNUUyAoU0VMRUNUIDEgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIFdIRVJFIHRhYmxlX25hbWUgPSAkMSknLFxuICAgICAgW25hbWVdLFxuICAgICAgYSA9PiBhLmV4aXN0c1xuICAgICk7XG4gIH1cblxuICBhc3luYyBzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lOiBzdHJpbmcsIENMUHM6IGFueSkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGF3YWl0IHRoaXMuX2NsaWVudC50YXNrKCdzZXQtY2xhc3MtbGV2ZWwtcGVybWlzc2lvbnMnLCBhc3luYyB0ID0+IHtcbiAgICAgIGF3YWl0IHNlbGYuX2Vuc3VyZVNjaGVtYUNvbGxlY3Rpb25FeGlzdHModCk7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBbXG4gICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgJ3NjaGVtYScsXG4gICAgICAgICdjbGFzc0xldmVsUGVybWlzc2lvbnMnLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShDTFBzKSxcbiAgICAgIF07XG4gICAgICBhd2FpdCB0Lm5vbmUoXG4gICAgICAgIGBVUERBVEUgXCJfU0NIRU1BXCIgU0VUICQyOm5hbWUgPSBqc29uX29iamVjdF9zZXRfa2V5KCQyOm5hbWUsICQzOjp0ZXh0LCAkNDo6anNvbmIpIFdIRVJFIFwiY2xhc3NOYW1lXCIgPSAkMWAsXG4gICAgICAgIHZhbHVlc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHN1Ym1pdHRlZEluZGV4ZXM6IGFueSxcbiAgICBleGlzdGluZ0luZGV4ZXM6IGFueSA9IHt9LFxuICAgIGZpZWxkczogYW55LFxuICAgIGNvbm46ID9hbnlcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29ubiA9IGNvbm4gfHwgdGhpcy5fY2xpZW50O1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGlmIChzdWJtaXR0ZWRJbmRleGVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKGV4aXN0aW5nSW5kZXhlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICBleGlzdGluZ0luZGV4ZXMgPSB7IF9pZF86IHsgX2lkOiAxIH0gfTtcbiAgICB9XG4gICAgY29uc3QgZGVsZXRlZEluZGV4ZXMgPSBbXTtcbiAgICBjb25zdCBpbnNlcnRlZEluZGV4ZXMgPSBbXTtcbiAgICBPYmplY3Qua2V5cyhzdWJtaXR0ZWRJbmRleGVzKS5mb3JFYWNoKG5hbWUgPT4ge1xuICAgICAgY29uc3QgZmllbGQgPSBzdWJtaXR0ZWRJbmRleGVzW25hbWVdO1xuICAgICAgaWYgKGV4aXN0aW5nSW5kZXhlc1tuYW1lXSAmJiBmaWVsZC5fX29wICE9PSAnRGVsZXRlJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgICBgSW5kZXggJHtuYW1lfSBleGlzdHMsIGNhbm5vdCB1cGRhdGUuYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKCFleGlzdGluZ0luZGV4ZXNbbmFtZV0gJiYgZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgYEluZGV4ICR7bmFtZX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBkZWxldGUuYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKGZpZWxkLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIGRlbGV0ZWRJbmRleGVzLnB1c2gobmFtZSk7XG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0luZGV4ZXNbbmFtZV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBPYmplY3Qua2V5cyhmaWVsZCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGZpZWxkcywga2V5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgICAgICBgRmllbGQgJHtrZXl9IGRvZXMgbm90IGV4aXN0LCBjYW5ub3QgYWRkIGluZGV4LmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZXhpc3RpbmdJbmRleGVzW25hbWVdID0gZmllbGQ7XG4gICAgICAgIGluc2VydGVkSW5kZXhlcy5wdXNoKHtcbiAgICAgICAgICBrZXk6IGZpZWxkLFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGF3YWl0IGNvbm4udHgoJ3NldC1pbmRleGVzLXdpdGgtc2NoZW1hLWZvcm1hdCcsIGFzeW5jIHQgPT4ge1xuICAgICAgaWYgKGluc2VydGVkSW5kZXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IHNlbGYuY3JlYXRlSW5kZXhlcyhjbGFzc05hbWUsIGluc2VydGVkSW5kZXhlcywgdCk7XG4gICAgICB9XG4gICAgICBpZiAoZGVsZXRlZEluZGV4ZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhd2FpdCBzZWxmLmRyb3BJbmRleGVzKGNsYXNzTmFtZSwgZGVsZXRlZEluZGV4ZXMsIHQpO1xuICAgICAgfVxuICAgICAgYXdhaXQgc2VsZi5fZW5zdXJlU2NoZW1hQ29sbGVjdGlvbkV4aXN0cyh0KTtcbiAgICAgIGF3YWl0IHQubm9uZShcbiAgICAgICAgJ1VQREFURSBcIl9TQ0hFTUFcIiBTRVQgJDI6bmFtZSA9IGpzb25fb2JqZWN0X3NldF9rZXkoJDI6bmFtZSwgJDM6OnRleHQsICQ0Ojpqc29uYikgV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQxJyxcbiAgICAgICAgW2NsYXNzTmFtZSwgJ3NjaGVtYScsICdpbmRleGVzJywgSlNPTi5zdHJpbmdpZnkoZXhpc3RpbmdJbmRleGVzKV1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBjcmVhdGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBjb25uOiA/YW55KSB7XG4gICAgY29ubiA9IGNvbm4gfHwgdGhpcy5fY2xpZW50O1xuICAgIHJldHVybiBjb25uXG4gICAgICAudHgoJ2NyZWF0ZS1jbGFzcycsIGFzeW5jIHQgPT4ge1xuICAgICAgICBjb25zdCBxMSA9IHRoaXMuY3JlYXRlVGFibGUoY2xhc3NOYW1lLCBzY2hlbWEsIHQpO1xuICAgICAgICBjb25zdCBxMiA9IHQubm9uZShcbiAgICAgICAgICAnSU5TRVJUIElOVE8gXCJfU0NIRU1BXCIgKFwiY2xhc3NOYW1lXCIsIFwic2NoZW1hXCIsIFwiaXNQYXJzZUNsYXNzXCIpIFZBTFVFUyAoJDxjbGFzc05hbWU+LCAkPHNjaGVtYT4sIHRydWUpJyxcbiAgICAgICAgICB7IGNsYXNzTmFtZSwgc2NoZW1hIH1cbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgcTMgPSB0aGlzLnNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KFxuICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICBzY2hlbWEuaW5kZXhlcyxcbiAgICAgICAgICB7fSxcbiAgICAgICAgICBzY2hlbWEuZmllbGRzLFxuICAgICAgICAgIHRcbiAgICAgICAgKTtcbiAgICAgICAgLy8gVE9ETzogVGhlIHRlc3Qgc2hvdWxkIG5vdCB2ZXJpZnkgdGhlIHJldHVybmVkIHZhbHVlLCBhbmQgdGhlblxuICAgICAgICAvLyAgdGhlIG1ldGhvZCBjYW4gYmUgc2ltcGxpZmllZCwgdG8gYXZvaWQgcmV0dXJuaW5nIHVzZWxlc3Mgc3R1ZmYuXG4gICAgICAgIHJldHVybiB0LmJhdGNoKFtxMSwgcTIsIHEzXSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdG9QYXJzZVNjaGVtYShzY2hlbWEpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICBpZiAoZXJyLmRhdGFbMF0ucmVzdWx0LmNvZGUgPT09IFBvc3RncmVzVHJhbnNhY3Rpb25BYm9ydGVkRXJyb3IpIHtcbiAgICAgICAgICBlcnIgPSBlcnIuZGF0YVsxXS5yZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGVyci5jb2RlID09PSBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IgJiZcbiAgICAgICAgICBlcnIuZGV0YWlsLmluY2x1ZGVzKGNsYXNzTmFtZSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLFxuICAgICAgICAgICAgYENsYXNzICR7Y2xhc3NOYW1lfSBhbHJlYWR5IGV4aXN0cy5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIEp1c3QgY3JlYXRlIGEgdGFibGUsIGRvIG5vdCBpbnNlcnQgaW4gc2NoZW1hXG4gIGFzeW5jIGNyZWF0ZVRhYmxlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGNvbm46IGFueSkge1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBkZWJ1ZygnY3JlYXRlVGFibGUnLCBjbGFzc05hbWUsIHNjaGVtYSk7XG4gICAgY29uc3QgdmFsdWVzQXJyYXkgPSBbXTtcbiAgICBjb25zdCBwYXR0ZXJuc0FycmF5ID0gW107XG4gICAgY29uc3QgZmllbGRzID0gT2JqZWN0LmFzc2lnbih7fSwgc2NoZW1hLmZpZWxkcyk7XG4gICAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgZmllbGRzLl9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCA9IHsgdHlwZTogJ0RhdGUnIH07XG4gICAgICBmaWVsZHMuX2VtYWlsX3ZlcmlmeV90b2tlbiA9IHsgdHlwZTogJ1N0cmluZycgfTtcbiAgICAgIGZpZWxkcy5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQgPSB7IHR5cGU6ICdEYXRlJyB9O1xuICAgICAgZmllbGRzLl9mYWlsZWRfbG9naW5fY291bnQgPSB7IHR5cGU6ICdOdW1iZXInIH07XG4gICAgICBmaWVsZHMuX3BlcmlzaGFibGVfdG9rZW4gPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gICAgICBmaWVsZHMuX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCA9IHsgdHlwZTogJ0RhdGUnIH07XG4gICAgICBmaWVsZHMuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSB7IHR5cGU6ICdEYXRlJyB9O1xuICAgICAgZmllbGRzLl9wYXNzd29yZF9oaXN0b3J5ID0geyB0eXBlOiAnQXJyYXknIH07XG4gICAgfVxuICAgIGxldCBpbmRleCA9IDI7XG4gICAgY29uc3QgcmVsYXRpb25zID0gW107XG4gICAgT2JqZWN0LmtleXMoZmllbGRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBjb25zdCBwYXJzZVR5cGUgPSBmaWVsZHNbZmllbGROYW1lXTtcbiAgICAgIC8vIFNraXAgd2hlbiBpdCdzIGEgcmVsYXRpb25cbiAgICAgIC8vIFdlJ2xsIGNyZWF0ZSB0aGUgdGFibGVzIGxhdGVyXG4gICAgICBpZiAocGFyc2VUeXBlLnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgcmVsYXRpb25zLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKFsnX3JwZXJtJywgJ193cGVybSddLmluZGV4T2YoZmllbGROYW1lKSA+PSAwKSB7XG4gICAgICAgIHBhcnNlVHlwZS5jb250ZW50cyA9IHsgdHlwZTogJ1N0cmluZycgfTtcbiAgICAgIH1cbiAgICAgIHZhbHVlc0FycmF5LnB1c2goZmllbGROYW1lKTtcbiAgICAgIHZhbHVlc0FycmF5LnB1c2gocGFyc2VUeXBlVG9Qb3N0Z3Jlc1R5cGUocGFyc2VUeXBlKSk7XG4gICAgICBwYXR0ZXJuc0FycmF5LnB1c2goYCQke2luZGV4fTpuYW1lICQke2luZGV4ICsgMX06cmF3YCk7XG4gICAgICBpZiAoZmllbGROYW1lID09PSAnb2JqZWN0SWQnKSB7XG4gICAgICAgIHBhdHRlcm5zQXJyYXkucHVzaChgUFJJTUFSWSBLRVkgKCQke2luZGV4fTpuYW1lKWApO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDI7XG4gICAgfSk7XG4gICAgY29uc3QgcXMgPSBgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJDE6bmFtZSAoJHtwYXR0ZXJuc0FycmF5LmpvaW4oKX0pYDtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAuLi52YWx1ZXNBcnJheV07XG5cbiAgICBkZWJ1ZyhxcywgdmFsdWVzKTtcbiAgICByZXR1cm4gY29ubi50YXNrKCdjcmVhdGUtdGFibGUnLCBhc3luYyB0ID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHNlbGYuX2Vuc3VyZVNjaGVtYUNvbGxlY3Rpb25FeGlzdHModCk7XG4gICAgICAgIGF3YWl0IHQubm9uZShxcywgdmFsdWVzKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBFTFNFOiBUYWJsZSBhbHJlYWR5IGV4aXN0cywgbXVzdCBoYXZlIGJlZW4gY3JlYXRlZCBieSBhIGRpZmZlcmVudCByZXF1ZXN0LiBJZ25vcmUgdGhlIGVycm9yLlxuICAgICAgfVxuICAgICAgYXdhaXQgdC50eCgnY3JlYXRlLXRhYmxlLXR4JywgdHggPT4ge1xuICAgICAgICByZXR1cm4gdHguYmF0Y2goXG4gICAgICAgICAgcmVsYXRpb25zLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHR4Lm5vbmUoXG4gICAgICAgICAgICAgICdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAkPGpvaW5UYWJsZTpuYW1lPiAoXCJyZWxhdGVkSWRcIiB2YXJDaGFyKDEyMCksIFwib3duaW5nSWRcIiB2YXJDaGFyKDEyMCksIFBSSU1BUlkgS0VZKFwicmVsYXRlZElkXCIsIFwib3duaW5nSWRcIikgKScsXG4gICAgICAgICAgICAgIHsgam9pblRhYmxlOiBgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBzY2hlbWFVcGdyYWRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGNvbm46IGFueSkge1xuICAgIGRlYnVnKCdzY2hlbWFVcGdyYWRlJywgeyBjbGFzc05hbWUsIHNjaGVtYSB9KTtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBhd2FpdCBjb25uLnR4KCdzY2hlbWEtdXBncmFkZScsIGFzeW5jIHQgPT4ge1xuICAgICAgY29uc3QgY29sdW1ucyA9IGF3YWl0IHQubWFwKFxuICAgICAgICAnU0VMRUNUIGNvbHVtbl9uYW1lIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLmNvbHVtbnMgV0hFUkUgdGFibGVfbmFtZSA9ICQ8Y2xhc3NOYW1lPicsXG4gICAgICAgIHsgY2xhc3NOYW1lIH0sXG4gICAgICAgIGEgPT4gYS5jb2x1bW5fbmFtZVxuICAgICAgKTtcbiAgICAgIGNvbnN0IG5ld0NvbHVtbnMgPSBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKVxuICAgICAgICAuZmlsdGVyKGl0ZW0gPT4gY29sdW1ucy5pbmRleE9mKGl0ZW0pID09PSAtMSlcbiAgICAgICAgLm1hcChmaWVsZE5hbWUgPT5cbiAgICAgICAgICBzZWxmLmFkZEZpZWxkSWZOb3RFeGlzdHMoXG4gICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICBmaWVsZE5hbWUsXG4gICAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0sXG4gICAgICAgICAgICB0XG4gICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICBhd2FpdCB0LmJhdGNoKG5ld0NvbHVtbnMpO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgYWRkRmllbGRJZk5vdEV4aXN0cyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBmaWVsZE5hbWU6IHN0cmluZyxcbiAgICB0eXBlOiBhbnksXG4gICAgY29ubjogYW55XG4gICkge1xuICAgIC8vIFRPRE86IE11c3QgYmUgcmV2aXNlZCBmb3IgaW52YWxpZCBsb2dpYy4uLlxuICAgIGRlYnVnKCdhZGRGaWVsZElmTm90RXhpc3RzJywgeyBjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSB9KTtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgYXdhaXQgY29ubi50eCgnYWRkLWZpZWxkLWlmLW5vdC1leGlzdHMnLCBhc3luYyB0ID0+IHtcbiAgICAgIGlmICh0eXBlLnR5cGUgIT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0Lm5vbmUoXG4gICAgICAgICAgICAnQUxURVIgVEFCTEUgJDxjbGFzc05hbWU6bmFtZT4gQUREIENPTFVNTiAkPGZpZWxkTmFtZTpuYW1lPiAkPHBvc3RncmVzVHlwZTpyYXc+JyxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICBmaWVsZE5hbWUsXG4gICAgICAgICAgICAgIHBvc3RncmVzVHlwZTogcGFyc2VUeXBlVG9Qb3N0Z3Jlc1R5cGUodHlwZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi5jcmVhdGVDbGFzcyhcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICB7IGZpZWxkczogeyBbZmllbGROYW1lXTogdHlwZSB9IH0sXG4gICAgICAgICAgICAgIHRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc0R1cGxpY2F0ZUNvbHVtbkVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29sdW1uIGFscmVhZHkgZXhpc3RzLCBjcmVhdGVkIGJ5IG90aGVyIHJlcXVlc3QuIENhcnJ5IG9uIHRvIHNlZSBpZiBpdCdzIHRoZSByaWdodCB0eXBlLlxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCB0Lm5vbmUoXG4gICAgICAgICAgJ0NSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTICQ8am9pblRhYmxlOm5hbWU+IChcInJlbGF0ZWRJZFwiIHZhckNoYXIoMTIwKSwgXCJvd25pbmdJZFwiIHZhckNoYXIoMTIwKSwgUFJJTUFSWSBLRVkoXCJyZWxhdGVkSWRcIiwgXCJvd25pbmdJZFwiKSApJyxcbiAgICAgICAgICB7IGpvaW5UYWJsZTogYF9Kb2luOiR7ZmllbGROYW1lfToke2NsYXNzTmFtZX1gIH1cbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdC5hbnkoXG4gICAgICAgICdTRUxFQ1QgXCJzY2hlbWFcIiBGUk9NIFwiX1NDSEVNQVwiIFdIRVJFIFwiY2xhc3NOYW1lXCIgPSAkPGNsYXNzTmFtZT4gYW5kIChcInNjaGVtYVwiOjpqc29uLT5cXCdmaWVsZHNcXCctPiQ8ZmllbGROYW1lPikgaXMgbm90IG51bGwnLFxuICAgICAgICB7IGNsYXNzTmFtZSwgZmllbGROYW1lIH1cbiAgICAgICk7XG5cbiAgICAgIGlmIChyZXN1bHRbMF0pIHtcbiAgICAgICAgdGhyb3cgJ0F0dGVtcHRlZCB0byBhZGQgYSBmaWVsZCB0aGF0IGFscmVhZHkgZXhpc3RzJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHBhdGggPSBge2ZpZWxkcywke2ZpZWxkTmFtZX19YDtcbiAgICAgICAgYXdhaXQgdC5ub25lKFxuICAgICAgICAgICdVUERBVEUgXCJfU0NIRU1BXCIgU0VUIFwic2NoZW1hXCI9anNvbmJfc2V0KFwic2NoZW1hXCIsICQ8cGF0aD4sICQ8dHlwZT4pICBXSEVSRSBcImNsYXNzTmFtZVwiPSQ8Y2xhc3NOYW1lPicsXG4gICAgICAgICAgeyBwYXRoLCB0eXBlLCBjbGFzc05hbWUgfVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gRHJvcHMgYSBjb2xsZWN0aW9uLiBSZXNvbHZlcyB3aXRoIHRydWUgaWYgaXQgd2FzIGEgUGFyc2UgU2NoZW1hIChlZy4gX1VzZXIsIEN1c3RvbSwgZXRjLilcbiAgLy8gYW5kIHJlc29sdmVzIHdpdGggZmFsc2UgaWYgaXQgd2Fzbid0IChlZy4gYSBqb2luIHRhYmxlKS4gUmVqZWN0cyBpZiBkZWxldGlvbiB3YXMgaW1wb3NzaWJsZS5cbiAgYXN5bmMgZGVsZXRlQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBvcGVyYXRpb25zID0gW1xuICAgICAgeyBxdWVyeTogYERST1AgVEFCTEUgSUYgRVhJU1RTICQxOm5hbWVgLCB2YWx1ZXM6IFtjbGFzc05hbWVdIH0sXG4gICAgICB7XG4gICAgICAgIHF1ZXJ5OiBgREVMRVRFIEZST00gXCJfU0NIRU1BXCIgV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQxYCxcbiAgICAgICAgdmFsdWVzOiBbY2xhc3NOYW1lXSxcbiAgICAgIH0sXG4gICAgXTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAudHgodCA9PiB0Lm5vbmUodGhpcy5fcGdwLmhlbHBlcnMuY29uY2F0KG9wZXJhdGlvbnMpKSlcbiAgICAgIC50aGVuKCgpID0+IGNsYXNzTmFtZS5pbmRleE9mKCdfSm9pbjonKSAhPSAwKTsgLy8gcmVzb2x2ZXMgd2l0aCBmYWxzZSB3aGVuIF9Kb2luIHRhYmxlXG4gIH1cblxuICAvLyBEZWxldGUgYWxsIGRhdGEga25vd24gdG8gdGhpcyBhZGFwdGVyLiBVc2VkIGZvciB0ZXN0aW5nLlxuICBhc3luYyBkZWxldGVBbGxDbGFzc2VzKCkge1xuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIGNvbnN0IGhlbHBlcnMgPSB0aGlzLl9wZ3AuaGVscGVycztcbiAgICBkZWJ1ZygnZGVsZXRlQWxsQ2xhc3NlcycpO1xuXG4gICAgYXdhaXQgdGhpcy5fY2xpZW50XG4gICAgICAudGFzaygnZGVsZXRlLWFsbC1jbGFzc2VzJywgYXN5bmMgdCA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHQuYW55KCdTRUxFQ1QgKiBGUk9NIFwiX1NDSEVNQVwiJyk7XG4gICAgICAgICAgY29uc3Qgam9pbnMgPSByZXN1bHRzLnJlZHVjZSgobGlzdDogQXJyYXk8c3RyaW5nPiwgc2NoZW1hOiBhbnkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBsaXN0LmNvbmNhdChqb2luVGFibGVzRm9yU2NoZW1hKHNjaGVtYS5zY2hlbWEpKTtcbiAgICAgICAgICB9LCBbXSk7XG4gICAgICAgICAgY29uc3QgY2xhc3NlcyA9IFtcbiAgICAgICAgICAgICdfU0NIRU1BJyxcbiAgICAgICAgICAgICdfUHVzaFN0YXR1cycsXG4gICAgICAgICAgICAnX0pvYlN0YXR1cycsXG4gICAgICAgICAgICAnX0pvYlNjaGVkdWxlJyxcbiAgICAgICAgICAgICdfSG9va3MnLFxuICAgICAgICAgICAgJ19HbG9iYWxDb25maWcnLFxuICAgICAgICAgICAgJ19HcmFwaFFMQ29uZmlnJyxcbiAgICAgICAgICAgICdfQXVkaWVuY2UnLFxuICAgICAgICAgICAgLi4ucmVzdWx0cy5tYXAocmVzdWx0ID0+IHJlc3VsdC5jbGFzc05hbWUpLFxuICAgICAgICAgICAgLi4uam9pbnMsXG4gICAgICAgICAgXTtcbiAgICAgICAgICBjb25zdCBxdWVyaWVzID0gY2xhc3Nlcy5tYXAoY2xhc3NOYW1lID0+ICh7XG4gICAgICAgICAgICBxdWVyeTogJ0RST1AgVEFCTEUgSUYgRVhJU1RTICQ8Y2xhc3NOYW1lOm5hbWU+JyxcbiAgICAgICAgICAgIHZhbHVlczogeyBjbGFzc05hbWUgfSxcbiAgICAgICAgICB9KSk7XG4gICAgICAgICAgYXdhaXQgdC50eCh0eCA9PiB0eC5ub25lKGhlbHBlcnMuY29uY2F0KHF1ZXJpZXMpKSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgIT09IFBvc3RncmVzUmVsYXRpb25Eb2VzTm90RXhpc3RFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIE5vIF9TQ0hFTUEgY29sbGVjdGlvbi4gRG9uJ3QgZGVsZXRlIGFueXRoaW5nLlxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZGVsZXRlQWxsQ2xhc3NlcyBkb25lIGluICR7bmV3IERhdGUoKS5nZXRUaW1lKCkgLSBub3d9YCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFJlbW92ZSB0aGUgY29sdW1uIGFuZCBhbGwgdGhlIGRhdGEuIEZvciBSZWxhdGlvbnMsIHRoZSBfSm9pbiBjb2xsZWN0aW9uIGlzIGhhbmRsZWRcbiAgLy8gc3BlY2lhbGx5LCB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IGRlbGV0ZSBfSm9pbiBjb2x1bW5zLiBJdCBzaG91bGQsIGhvd2V2ZXIsIGluZGljYXRlXG4gIC8vIHRoYXQgdGhlIHJlbGF0aW9uIGZpZWxkcyBkb2VzIG5vdCBleGlzdCBhbnltb3JlLiBJbiBtb25nbywgdGhpcyBtZWFucyByZW1vdmluZyBpdCBmcm9tXG4gIC8vIHRoZSBfU0NIRU1BIGNvbGxlY3Rpb24uICBUaGVyZSBzaG91bGQgYmUgbm8gYWN0dWFsIGRhdGEgaW4gdGhlIGNvbGxlY3Rpb24gdW5kZXIgdGhlIHNhbWUgbmFtZVxuICAvLyBhcyB0aGUgcmVsYXRpb24gY29sdW1uLCBzbyBpdCdzIGZpbmUgdG8gYXR0ZW1wdCB0byBkZWxldGUgaXQuIElmIHRoZSBmaWVsZHMgbGlzdGVkIHRvIGJlXG4gIC8vIGRlbGV0ZWQgZG8gbm90IGV4aXN0LCB0aGlzIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gc3VjY2Vzc2Z1bGx5IGFueXdheXMuIENoZWNraW5nIGZvclxuICAvLyBhdHRlbXB0cyB0byBkZWxldGUgbm9uLWV4aXN0ZW50IGZpZWxkcyBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgUGFyc2UgU2VydmVyLlxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gaXMgbm90IG9ibGlnYXRlZCB0byBkZWxldGUgZmllbGRzIGF0b21pY2FsbHkuIEl0IGlzIGdpdmVuIHRoZSBmaWVsZFxuICAvLyBuYW1lcyBpbiBhIGxpc3Qgc28gdGhhdCBkYXRhYmFzZXMgdGhhdCBhcmUgY2FwYWJsZSBvZiBkZWxldGluZyBmaWVsZHMgYXRvbWljYWxseVxuICAvLyBtYXkgZG8gc28uXG5cbiAgLy8gUmV0dXJucyBhIFByb21pc2UuXG4gIGFzeW5jIGRlbGV0ZUZpZWxkcyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgZmllbGROYW1lczogc3RyaW5nW11cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZGVidWcoJ2RlbGV0ZUZpZWxkcycsIGNsYXNzTmFtZSwgZmllbGROYW1lcyk7XG4gICAgZmllbGROYW1lcyA9IGZpZWxkTmFtZXMucmVkdWNlKChsaXN0OiBBcnJheTxzdHJpbmc+LCBmaWVsZE5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgZmllbGQgPSBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICBpZiAoZmllbGQudHlwZSAhPT0gJ1JlbGF0aW9uJykge1xuICAgICAgICBsaXN0LnB1c2goZmllbGROYW1lKTtcbiAgICAgIH1cbiAgICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICByZXR1cm4gbGlzdDtcbiAgICB9LCBbXSk7XG5cbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAuLi5maWVsZE5hbWVzXTtcbiAgICBjb25zdCBjb2x1bW5zID0gZmllbGROYW1lc1xuICAgICAgLm1hcCgobmFtZSwgaWR4KSA9PiB7XG4gICAgICAgIHJldHVybiBgJCR7aWR4ICsgMn06bmFtZWA7XG4gICAgICB9KVxuICAgICAgLmpvaW4oJywgRFJPUCBDT0xVTU4nKTtcblxuICAgIGF3YWl0IHRoaXMuX2NsaWVudC50eCgnZGVsZXRlLWZpZWxkcycsIGFzeW5jIHQgPT4ge1xuICAgICAgYXdhaXQgdC5ub25lKFxuICAgICAgICAnVVBEQVRFIFwiX1NDSEVNQVwiIFNFVCBcInNjaGVtYVwiID0gJDxzY2hlbWE+IFdIRVJFIFwiY2xhc3NOYW1lXCIgPSAkPGNsYXNzTmFtZT4nLFxuICAgICAgICB7IHNjaGVtYSwgY2xhc3NOYW1lIH1cbiAgICAgICk7XG4gICAgICBpZiAodmFsdWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgYXdhaXQgdC5ub25lKGBBTFRFUiBUQUJMRSAkMTpuYW1lIERST1AgQ09MVU1OICR7Y29sdW1uc31gLCB2YWx1ZXMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgYWxsIHNjaGVtYXMga25vd24gdG8gdGhpcyBhZGFwdGVyLCBpbiBQYXJzZSBmb3JtYXQuIEluIGNhc2UgdGhlXG4gIC8vIHNjaGVtYXMgY2Fubm90IGJlIHJldHJpZXZlZCwgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZWplY3RzLiBSZXF1aXJlbWVudHMgZm9yIHRoZVxuICAvLyByZWplY3Rpb24gcmVhc29uIGFyZSBUQkQuXG4gIGFzeW5jIGdldEFsbENsYXNzZXMoKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC50YXNrKCdnZXQtYWxsLWNsYXNzZXMnLCBhc3luYyB0ID0+IHtcbiAgICAgIGF3YWl0IHNlbGYuX2Vuc3VyZVNjaGVtYUNvbGxlY3Rpb25FeGlzdHModCk7XG4gICAgICByZXR1cm4gYXdhaXQgdC5tYXAoJ1NFTEVDVCAqIEZST00gXCJfU0NIRU1BXCInLCBudWxsLCByb3cgPT5cbiAgICAgICAgdG9QYXJzZVNjaGVtYSh7IGNsYXNzTmFtZTogcm93LmNsYXNzTmFtZSwgLi4ucm93LnNjaGVtYSB9KVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybiBhIHByb21pc2UgZm9yIHRoZSBzY2hlbWEgd2l0aCB0aGUgZ2l2ZW4gbmFtZSwgaW4gUGFyc2UgZm9ybWF0LiBJZlxuICAvLyB0aGlzIGFkYXB0ZXIgZG9lc24ndCBrbm93IGFib3V0IHRoZSBzY2hlbWEsIHJldHVybiBhIHByb21pc2UgdGhhdCByZWplY3RzIHdpdGhcbiAgLy8gdW5kZWZpbmVkIGFzIHRoZSByZWFzb24uXG4gIGFzeW5jIGdldENsYXNzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgZGVidWcoJ2dldENsYXNzJywgY2xhc3NOYW1lKTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAuYW55KCdTRUxFQ1QgKiBGUk9NIFwiX1NDSEVNQVwiIFdIRVJFIFwiY2xhc3NOYW1lXCIgPSAkPGNsYXNzTmFtZT4nLCB7XG4gICAgICAgIGNsYXNzTmFtZSxcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0WzBdLnNjaGVtYTtcbiAgICAgIH0pXG4gICAgICAudGhlbih0b1BhcnNlU2NoZW1hKTtcbiAgfVxuXG4gIC8vIFRPRE86IHJlbW92ZSB0aGUgbW9uZ28gZm9ybWF0IGRlcGVuZGVuY3kgaW4gdGhlIHJldHVybiB2YWx1ZVxuICBhc3luYyBjcmVhdGVPYmplY3QoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIG9iamVjdDogYW55LFxuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uOiA/YW55XG4gICkge1xuICAgIGRlYnVnKCdjcmVhdGVPYmplY3QnLCBjbGFzc05hbWUsIG9iamVjdCk7XG4gICAgbGV0IGNvbHVtbnNBcnJheSA9IFtdO1xuICAgIGNvbnN0IHZhbHVlc0FycmF5ID0gW107XG4gICAgc2NoZW1hID0gdG9Qb3N0Z3Jlc1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IGdlb1BvaW50cyA9IHt9O1xuXG4gICAgb2JqZWN0ID0gaGFuZGxlRG90RmllbGRzKG9iamVjdCk7XG5cbiAgICB2YWxpZGF0ZUtleXMob2JqZWN0KTtcblxuICAgIE9iamVjdC5rZXlzKG9iamVjdCkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBhdXRoRGF0YU1hdGNoID0gZmllbGROYW1lLm1hdGNoKC9eX2F1dGhfZGF0YV8oW2EtekEtWjAtOV9dKykkLyk7XG4gICAgICBpZiAoYXV0aERhdGFNYXRjaCkge1xuICAgICAgICB2YXIgcHJvdmlkZXIgPSBhdXRoRGF0YU1hdGNoWzFdO1xuICAgICAgICBvYmplY3RbJ2F1dGhEYXRhJ10gPSBvYmplY3RbJ2F1dGhEYXRhJ10gfHwge307XG4gICAgICAgIG9iamVjdFsnYXV0aERhdGEnXVtwcm92aWRlcl0gPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgZGVsZXRlIG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgICBmaWVsZE5hbWUgPSAnYXV0aERhdGEnO1xuICAgICAgfVxuXG4gICAgICBjb2x1bW5zQXJyYXkucHVzaChmaWVsZE5hbWUpO1xuICAgICAgaWYgKCFzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiYgY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfZW1haWxfdmVyaWZ5X3Rva2VuJyB8fFxuICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19mYWlsZWRfbG9naW5fY291bnQnIHx8XG4gICAgICAgICAgZmllbGROYW1lID09PSAnX3BlcmlzaGFibGVfdG9rZW4nIHx8XG4gICAgICAgICAgZmllbGROYW1lID09PSAnX3Bhc3N3b3JkX2hpc3RvcnknXG4gICAgICAgICkge1xuICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpZWxkTmFtZSA9PT0gJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCcpIHtcbiAgICAgICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0uaXNvKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChudWxsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgZmllbGROYW1lID09PSAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JyB8fFxuICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQnIHx8XG4gICAgICAgICAgZmllbGROYW1lID09PSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnXG4gICAgICAgICkge1xuICAgICAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSkge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXS5pc28pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG51bGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzd2l0Y2ggKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSkge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXS5pc28pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG51bGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXS5vYmplY3RJZCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0FycmF5JzpcbiAgICAgICAgICBpZiAoWydfcnBlcm0nLCAnX3dwZXJtJ10uaW5kZXhPZihmaWVsZE5hbWUpID49IDApIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKEpTT04uc3RyaW5naWZ5KG9iamVjdFtmaWVsZE5hbWVdKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdPYmplY3QnOlxuICAgICAgICBjYXNlICdCeXRlcyc6XG4gICAgICAgIGNhc2UgJ1N0cmluZyc6XG4gICAgICAgIGNhc2UgJ051bWJlcic6XG4gICAgICAgIGNhc2UgJ0Jvb2xlYW4nOlxuICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdGaWxlJzpcbiAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLm5hbWUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdQb2x5Z29uJzoge1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFBvbHlnb25Ub1NRTChvYmplY3RbZmllbGROYW1lXS5jb29yZGluYXRlcyk7XG4gICAgICAgICAgdmFsdWVzQXJyYXkucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnR2VvUG9pbnQnOlxuICAgICAgICAgIC8vIHBvcCB0aGUgcG9pbnQgYW5kIHByb2Nlc3MgbGF0ZXJcbiAgICAgICAgICBnZW9Qb2ludHNbZmllbGROYW1lXSA9IG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgICAgIGNvbHVtbnNBcnJheS5wb3AoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBgVHlwZSAke3NjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlfSBub3Qgc3VwcG9ydGVkIHlldGA7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb2x1bW5zQXJyYXkgPSBjb2x1bW5zQXJyYXkuY29uY2F0KE9iamVjdC5rZXlzKGdlb1BvaW50cykpO1xuICAgIGNvbnN0IGluaXRpYWxWYWx1ZXMgPSB2YWx1ZXNBcnJheS5tYXAoKHZhbCwgaW5kZXgpID0+IHtcbiAgICAgIGxldCB0ZXJtaW5hdGlvbiA9ICcnO1xuICAgICAgY29uc3QgZmllbGROYW1lID0gY29sdW1uc0FycmF5W2luZGV4XTtcbiAgICAgIGlmIChbJ19ycGVybScsICdfd3Blcm0nXS5pbmRleE9mKGZpZWxkTmFtZSkgPj0gMCkge1xuICAgICAgICB0ZXJtaW5hdGlvbiA9ICc6OnRleHRbXSc7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiZcbiAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdBcnJheSdcbiAgICAgICkge1xuICAgICAgICB0ZXJtaW5hdGlvbiA9ICc6Ompzb25iJztcbiAgICAgIH1cbiAgICAgIHJldHVybiBgJCR7aW5kZXggKyAyICsgY29sdW1uc0FycmF5Lmxlbmd0aH0ke3Rlcm1pbmF0aW9ufWA7XG4gICAgfSk7XG4gICAgY29uc3QgZ2VvUG9pbnRzSW5qZWN0cyA9IE9iamVjdC5rZXlzKGdlb1BvaW50cykubWFwKGtleSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGdlb1BvaW50c1trZXldO1xuICAgICAgdmFsdWVzQXJyYXkucHVzaCh2YWx1ZS5sb25naXR1ZGUsIHZhbHVlLmxhdGl0dWRlKTtcbiAgICAgIGNvbnN0IGwgPSB2YWx1ZXNBcnJheS5sZW5ndGggKyBjb2x1bW5zQXJyYXkubGVuZ3RoO1xuICAgICAgcmV0dXJuIGBQT0lOVCgkJHtsfSwgJCR7bCArIDF9KWA7XG4gICAgfSk7XG5cbiAgICBjb25zdCBjb2x1bW5zUGF0dGVybiA9IGNvbHVtbnNBcnJheVxuICAgICAgLm1hcCgoY29sLCBpbmRleCkgPT4gYCQke2luZGV4ICsgMn06bmFtZWApXG4gICAgICAuam9pbigpO1xuICAgIGNvbnN0IHZhbHVlc1BhdHRlcm4gPSBpbml0aWFsVmFsdWVzLmNvbmNhdChnZW9Qb2ludHNJbmplY3RzKS5qb2luKCk7XG5cbiAgICBjb25zdCBxcyA9IGBJTlNFUlQgSU5UTyAkMTpuYW1lICgke2NvbHVtbnNQYXR0ZXJufSkgVkFMVUVTICgke3ZhbHVlc1BhdHRlcm59KWA7XG4gICAgY29uc3QgdmFsdWVzID0gW2NsYXNzTmFtZSwgLi4uY29sdW1uc0FycmF5LCAuLi52YWx1ZXNBcnJheV07XG4gICAgZGVidWcocXMsIHZhbHVlcyk7XG4gICAgY29uc3QgcHJvbWlzZSA9ICh0cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICAgPyB0cmFuc2FjdGlvbmFsU2Vzc2lvbi50XG4gICAgICA6IHRoaXMuX2NsaWVudFxuICAgIClcbiAgICAgIC5ub25lKHFzLCB2YWx1ZXMpXG4gICAgICAudGhlbigoKSA9PiAoeyBvcHM6IFtvYmplY3RdIH0pKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvcikge1xuICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSxcbiAgICAgICAgICAgICdBIGR1cGxpY2F0ZSB2YWx1ZSBmb3IgYSBmaWVsZCB3aXRoIHVuaXF1ZSB2YWx1ZXMgd2FzIHByb3ZpZGVkJ1xuICAgICAgICAgICk7XG4gICAgICAgICAgZXJyLnVuZGVybHlpbmdFcnJvciA9IGVycm9yO1xuICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50KSB7XG4gICAgICAgICAgICBjb25zdCBtYXRjaGVzID0gZXJyb3IuY29uc3RyYWludC5tYXRjaCgvdW5pcXVlXyhbYS16QS1aXSspLyk7XG4gICAgICAgICAgICBpZiAobWF0Y2hlcyAmJiBBcnJheS5pc0FycmF5KG1hdGNoZXMpKSB7XG4gICAgICAgICAgICAgIGVyci51c2VySW5mbyA9IHsgZHVwbGljYXRlZF9maWVsZDogbWF0Y2hlc1sxXSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBlcnJvciA9IGVycjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuICAgIGlmICh0cmFuc2FjdGlvbmFsU2Vzc2lvbikge1xuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gucHVzaChwcm9taXNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cblxuICAvLyBSZW1vdmUgYWxsIG9iamVjdHMgdGhhdCBtYXRjaCB0aGUgZ2l2ZW4gUGFyc2UgUXVlcnkuXG4gIC8vIElmIG5vIG9iamVjdHMgbWF0Y2gsIHJlamVjdCB3aXRoIE9CSkVDVF9OT1RfRk9VTkQuIElmIG9iamVjdHMgYXJlIGZvdW5kIGFuZCBkZWxldGVkLCByZXNvbHZlIHdpdGggdW5kZWZpbmVkLlxuICAvLyBJZiB0aGVyZSBpcyBzb21lIG90aGVyIGVycm9yLCByZWplY3Qgd2l0aCBJTlRFUk5BTF9TRVJWRVJfRVJST1IuXG4gIGFzeW5jIGRlbGV0ZU9iamVjdHNCeVF1ZXJ5KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uOiA/YW55XG4gICkge1xuICAgIGRlYnVnKCdkZWxldGVPYmplY3RzQnlRdWVyeScsIGNsYXNzTmFtZSwgcXVlcnkpO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtjbGFzc05hbWVdO1xuICAgIGNvbnN0IGluZGV4ID0gMjtcbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2Uoe1xuICAgICAgc2NoZW1hLFxuICAgICAgaW5kZXgsXG4gICAgICBxdWVyeSxcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZTogZmFsc2UsXG4gICAgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcbiAgICBpZiAoT2JqZWN0LmtleXMocXVlcnkpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgd2hlcmUucGF0dGVybiA9ICdUUlVFJztcbiAgICB9XG4gICAgY29uc3QgcXMgPSBgV0lUSCBkZWxldGVkIEFTIChERUxFVEUgRlJPTSAkMTpuYW1lIFdIRVJFICR7d2hlcmUucGF0dGVybn0gUkVUVVJOSU5HICopIFNFTEVDVCBjb3VudCgqKSBGUk9NIGRlbGV0ZWRgO1xuICAgIGRlYnVnKHFzLCB2YWx1ZXMpO1xuICAgIGNvbnN0IHByb21pc2UgPSAodHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICAgID8gdHJhbnNhY3Rpb25hbFNlc3Npb24udFxuICAgICAgOiB0aGlzLl9jbGllbnRcbiAgICApXG4gICAgICAub25lKHFzLCB2YWx1ZXMsIGEgPT4gK2EuY291bnQpXG4gICAgICAudGhlbihjb3VudCA9PiB7XG4gICAgICAgIGlmIChjb3VudCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gY291bnQ7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRUxTRTogRG9uJ3QgZGVsZXRlIGFueXRoaW5nIGlmIGRvZXNuJ3QgZXhpc3RcbiAgICAgIH0pO1xuICAgIGlmICh0cmFuc2FjdGlvbmFsU2Vzc2lvbikge1xuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gucHVzaChwcm9taXNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cbiAgLy8gUmV0dXJuIHZhbHVlIG5vdCBjdXJyZW50bHkgd2VsbCBzcGVjaWZpZWQuXG4gIGFzeW5jIGZpbmRPbmVBbmRVcGRhdGUoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBkZWJ1ZygnZmluZE9uZUFuZFVwZGF0ZScsIGNsYXNzTmFtZSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgICBjbGFzc05hbWUsXG4gICAgICBzY2hlbWEsXG4gICAgICBxdWVyeSxcbiAgICAgIHVwZGF0ZSxcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgKS50aGVuKHZhbCA9PiB2YWxbMF0pO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgYXN5bmMgdXBkYXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKTogUHJvbWlzZTxbYW55XT4ge1xuICAgIGRlYnVnKCd1cGRhdGVPYmplY3RzQnlRdWVyeScsIGNsYXNzTmFtZSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgY29uc3QgdXBkYXRlUGF0dGVybnMgPSBbXTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBsZXQgaW5kZXggPSAyO1xuICAgIHNjaGVtYSA9IHRvUG9zdGdyZXNTY2hlbWEoc2NoZW1hKTtcblxuICAgIGNvbnN0IG9yaWdpbmFsVXBkYXRlID0geyAuLi51cGRhdGUgfTtcblxuICAgIC8vIFNldCBmbGFnIGZvciBkb3Qgbm90YXRpb24gZmllbGRzXG4gICAgY29uc3QgZG90Tm90YXRpb25PcHRpb25zID0ge307XG4gICAgT2JqZWN0LmtleXModXBkYXRlKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+IC0xKSB7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBmaWVsZE5hbWUuc3BsaXQoJy4nKTtcbiAgICAgICAgY29uc3QgZmlyc3QgPSBjb21wb25lbnRzLnNoaWZ0KCk7XG4gICAgICAgIGRvdE5vdGF0aW9uT3B0aW9uc1tmaXJzdF0gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZG90Tm90YXRpb25PcHRpb25zW2ZpZWxkTmFtZV0gPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB1cGRhdGUgPSBoYW5kbGVEb3RGaWVsZHModXBkYXRlKTtcbiAgICAvLyBSZXNvbHZlIGF1dGhEYXRhIGZpcnN0LFxuICAgIC8vIFNvIHdlIGRvbid0IGVuZCB1cCB3aXRoIG11bHRpcGxlIGtleSB1cGRhdGVzXG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gdXBkYXRlKSB7XG4gICAgICBjb25zdCBhdXRoRGF0YU1hdGNoID0gZmllbGROYW1lLm1hdGNoKC9eX2F1dGhfZGF0YV8oW2EtekEtWjAtOV9dKykkLyk7XG4gICAgICBpZiAoYXV0aERhdGFNYXRjaCkge1xuICAgICAgICB2YXIgcHJvdmlkZXIgPSBhdXRoRGF0YU1hdGNoWzFdO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHVwZGF0ZVtmaWVsZE5hbWVdO1xuICAgICAgICBkZWxldGUgdXBkYXRlW2ZpZWxkTmFtZV07XG4gICAgICAgIHVwZGF0ZVsnYXV0aERhdGEnXSA9IHVwZGF0ZVsnYXV0aERhdGEnXSB8fCB7fTtcbiAgICAgICAgdXBkYXRlWydhdXRoRGF0YSddW3Byb3ZpZGVyXSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZmllbGROYW1lIGluIHVwZGF0ZSkge1xuICAgICAgY29uc3QgZmllbGRWYWx1ZSA9IHVwZGF0ZVtmaWVsZE5hbWVdO1xuICAgICAgLy8gRHJvcCBhbnkgdW5kZWZpbmVkIHZhbHVlcy5cbiAgICAgIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgZGVsZXRlIHVwZGF0ZVtmaWVsZE5hbWVdO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlID09PSBudWxsKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gTlVMTGApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZE5hbWUgPT0gJ2F1dGhEYXRhJykge1xuICAgICAgICAvLyBUaGlzIHJlY3Vyc2l2ZWx5IHNldHMgdGhlIGpzb25fb2JqZWN0XG4gICAgICAgIC8vIE9ubHkgMSBsZXZlbCBkZWVwXG4gICAgICAgIGNvbnN0IGdlbmVyYXRlID0gKGpzb25iOiBzdHJpbmcsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGBqc29uX29iamVjdF9zZXRfa2V5KENPQUxFU0NFKCR7anNvbmJ9LCAne30nOjpqc29uYiksICR7a2V5fSwgJHt2YWx1ZX0pOjpqc29uYmA7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGxhc3RLZXkgPSBgJCR7aW5kZXh9Om5hbWVgO1xuICAgICAgICBjb25zdCBmaWVsZE5hbWVJbmRleCA9IGluZGV4O1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICBjb25zdCB1cGRhdGUgPSBPYmplY3Qua2V5cyhmaWVsZFZhbHVlKS5yZWR1Y2UoXG4gICAgICAgICAgKGxhc3RLZXk6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IGdlbmVyYXRlKFxuICAgICAgICAgICAgICBsYXN0S2V5LFxuICAgICAgICAgICAgICBgJCR7aW5kZXh9Ojp0ZXh0YCxcbiAgICAgICAgICAgICAgYCQke2luZGV4ICsgMX06Ompzb25iYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBmaWVsZFZhbHVlW2tleV07XG4gICAgICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgaWYgKHZhbHVlLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBzdHI7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBsYXN0S2V5XG4gICAgICAgICk7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2ZpZWxkTmFtZUluZGV4fTpuYW1lID0gJHt1cGRhdGV9YCk7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ0luY3JlbWVudCcpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBgJCR7aW5kZXh9Om5hbWUgPSBDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgMCkgKyAkJHtpbmRleCArIDF9YFxuICAgICAgICApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUuYW1vdW50KTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS5fX29wID09PSAnQWRkJykge1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGAkJHtpbmRleH06bmFtZSA9IGFycmF5X2FkZChDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ1tdJzo6anNvbmIpLCAkJHtpbmRleCArXG4gICAgICAgICAgICAxfTo6anNvbmIpYFxuICAgICAgICApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUub2JqZWN0cykpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIG51bGwpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fb3AgPT09ICdSZW1vdmUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgYCQke2luZGV4fTpuYW1lID0gYXJyYXlfcmVtb3ZlKENPQUxFU0NFKCQke2luZGV4fTpuYW1lLCAnW10nOjpqc29uYiksICQke2luZGV4ICtcbiAgICAgICAgICAgIDF9Ojpqc29uYilgXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS5vYmplY3RzKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ0FkZFVuaXF1ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBgJCR7aW5kZXh9Om5hbWUgPSBhcnJheV9hZGRfdW5pcXVlKENPQUxFU0NFKCQke2luZGV4fTpuYW1lLCAnW10nOjpqc29uYiksICQke2luZGV4ICtcbiAgICAgICAgICAgIDF9Ojpqc29uYilgXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS5vYmplY3RzKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkTmFtZSA9PT0gJ3VwZGF0ZWRBdCcpIHtcbiAgICAgICAgLy9UT0RPOiBzdG9wIHNwZWNpYWwgY2FzaW5nIHRoaXMuIEl0IHNob3VsZCBjaGVjayBmb3IgX190eXBlID09PSAnRGF0ZScgYW5kIHVzZSAuaXNvXG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5vYmplY3RJZCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRGF0ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgdG9Qb3N0Z3Jlc1ZhbHVlKGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRmlsZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgdG9Qb3N0Z3Jlc1ZhbHVlKGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS5fX3R5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBgJCR7aW5kZXh9Om5hbWUgPSBQT0lOVCgkJHtpbmRleCArIDF9LCAkJHtpbmRleCArIDJ9KWBcbiAgICAgICAgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmxvbmdpdHVkZSwgZmllbGRWYWx1ZS5sYXRpdHVkZSk7XG4gICAgICAgIGluZGV4ICs9IDM7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0UG9seWdvblRvU1FMKGZpZWxkVmFsdWUuY29vcmRpbmF0ZXMpO1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCB2YWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgdHlwZW9mIGZpZWxkVmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ09iamVjdCdcbiAgICAgICkge1xuICAgICAgICAvLyBHYXRoZXIga2V5cyB0byBpbmNyZW1lbnRcbiAgICAgICAgY29uc3Qga2V5c1RvSW5jcmVtZW50ID0gT2JqZWN0LmtleXMob3JpZ2luYWxVcGRhdGUpXG4gICAgICAgICAgLmZpbHRlcihrID0+IHtcbiAgICAgICAgICAgIC8vIGNob29zZSB0b3AgbGV2ZWwgZmllbGRzIHRoYXQgaGF2ZSBhIGRlbGV0ZSBvcGVyYXRpb24gc2V0XG4gICAgICAgICAgICAvLyBOb3RlIHRoYXQgT2JqZWN0LmtleXMgaXMgaXRlcmF0aW5nIG92ZXIgdGhlICoqb3JpZ2luYWwqKiB1cGRhdGUgb2JqZWN0XG4gICAgICAgICAgICAvLyBhbmQgdGhhdCBzb21lIG9mIHRoZSBrZXlzIG9mIHRoZSBvcmlnaW5hbCB1cGRhdGUgY291bGQgYmUgbnVsbCBvciB1bmRlZmluZWQ6XG4gICAgICAgICAgICAvLyAoU2VlIHRoZSBhYm92ZSBjaGVjayBgaWYgKGZpZWxkVmFsdWUgPT09IG51bGwgfHwgdHlwZW9mIGZpZWxkVmFsdWUgPT0gXCJ1bmRlZmluZWRcIilgKVxuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvcmlnaW5hbFVwZGF0ZVtrXTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgIHZhbHVlICYmXG4gICAgICAgICAgICAgIHZhbHVlLl9fb3AgPT09ICdJbmNyZW1lbnQnICYmXG4gICAgICAgICAgICAgIGsuc3BsaXQoJy4nKS5sZW5ndGggPT09IDIgJiZcbiAgICAgICAgICAgICAgay5zcGxpdCgnLicpWzBdID09PSBmaWVsZE5hbWVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAubWFwKGsgPT4gay5zcGxpdCgnLicpWzFdKTtcblxuICAgICAgICBsZXQgaW5jcmVtZW50UGF0dGVybnMgPSAnJztcbiAgICAgICAgaWYgKGtleXNUb0luY3JlbWVudC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgaW5jcmVtZW50UGF0dGVybnMgPVxuICAgICAgICAgICAgJyB8fCAnICtcbiAgICAgICAgICAgIGtleXNUb0luY3JlbWVudFxuICAgICAgICAgICAgICAubWFwKGMgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFtb3VudCA9IGZpZWxkVmFsdWVbY10uYW1vdW50O1xuICAgICAgICAgICAgICAgIHJldHVybiBgQ09OQ0FUKCd7XCIke2N9XCI6JywgQ09BTEVTQ0UoJCR7aW5kZXh9Om5hbWUtPj4nJHtjfScsJzAnKTo6aW50ICsgJHthbW91bnR9LCAnfScpOjpqc29uYmA7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5qb2luKCcgfHwgJyk7XG4gICAgICAgICAgLy8gU3RyaXAgdGhlIGtleXNcbiAgICAgICAgICBrZXlzVG9JbmNyZW1lbnQuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIGZpZWxkVmFsdWVba2V5XTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGtleXNUb0RlbGV0ZTogQXJyYXk8c3RyaW5nPiA9IE9iamVjdC5rZXlzKG9yaWdpbmFsVXBkYXRlKVxuICAgICAgICAgIC5maWx0ZXIoayA9PiB7XG4gICAgICAgICAgICAvLyBjaG9vc2UgdG9wIGxldmVsIGZpZWxkcyB0aGF0IGhhdmUgYSBkZWxldGUgb3BlcmF0aW9uIHNldC5cbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gb3JpZ2luYWxVcGRhdGVba107XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICB2YWx1ZSAmJlxuICAgICAgICAgICAgICB2YWx1ZS5fX29wID09PSAnRGVsZXRlJyAmJlxuICAgICAgICAgICAgICBrLnNwbGl0KCcuJykubGVuZ3RoID09PSAyICYmXG4gICAgICAgICAgICAgIGsuc3BsaXQoJy4nKVswXSA9PT0gZmllbGROYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLm1hcChrID0+IGsuc3BsaXQoJy4nKVsxXSk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRlUGF0dGVybnMgPSBrZXlzVG9EZWxldGUucmVkdWNlKFxuICAgICAgICAgIChwOiBzdHJpbmcsIGM6IHN0cmluZywgaTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcCArIGAgLSAnJCR7aW5kZXggKyAxICsgaX06dmFsdWUnYDtcbiAgICAgICAgICB9LFxuICAgICAgICAgICcnXG4gICAgICAgICk7XG4gICAgICAgIC8vIE92ZXJyaWRlIE9iamVjdFxuICAgICAgICBsZXQgdXBkYXRlT2JqZWN0ID0gXCIne30nOjpqc29uYlwiO1xuXG4gICAgICAgIGlmIChkb3ROb3RhdGlvbk9wdGlvbnNbZmllbGROYW1lXSkge1xuICAgICAgICAgIC8vIE1lcmdlIE9iamVjdFxuICAgICAgICAgIHVwZGF0ZU9iamVjdCA9IGBDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ3t9Jzo6anNvbmIpYDtcbiAgICAgICAgfVxuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGAkJHtpbmRleH06bmFtZSA9ICgke3VwZGF0ZU9iamVjdH0gJHtkZWxldGVQYXR0ZXJuc30gJHtpbmNyZW1lbnRQYXR0ZXJuc30gfHwgJCR7aW5kZXggK1xuICAgICAgICAgICAgMSArXG4gICAgICAgICAgICBrZXlzVG9EZWxldGUubGVuZ3RofTo6anNvbmIgKWBcbiAgICAgICAgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCAuLi5rZXlzVG9EZWxldGUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMiArIGtleXNUb0RlbGV0ZS5sZW5ndGg7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBBcnJheS5pc0FycmF5KGZpZWxkVmFsdWUpICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0FycmF5J1xuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZSA9IHBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSk7XG4gICAgICAgIGlmIChleHBlY3RlZFR5cGUgPT09ICd0ZXh0W10nKSB7XG4gICAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9Ojp0ZXh0W11gKTtcbiAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9Ojpqc29uYmApO1xuICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZSkpO1xuICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlYnVnKCdOb3Qgc3VwcG9ydGVkIHVwZGF0ZScsIGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgYFBvc3RncmVzIGRvZXNuJ3Qgc3VwcG9ydCB1cGRhdGUgJHtKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKX0geWV0YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2Uoe1xuICAgICAgc2NoZW1hLFxuICAgICAgaW5kZXgsXG4gICAgICBxdWVyeSxcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZTogZmFsc2UsXG4gICAgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcblxuICAgIGNvbnN0IHdoZXJlQ2xhdXNlID1cbiAgICAgIHdoZXJlLnBhdHRlcm4ubGVuZ3RoID4gMCA/IGBXSEVSRSAke3doZXJlLnBhdHRlcm59YCA6ICcnO1xuICAgIGNvbnN0IHFzID0gYFVQREFURSAkMTpuYW1lIFNFVCAke3VwZGF0ZVBhdHRlcm5zLmpvaW4oKX0gJHt3aGVyZUNsYXVzZX0gUkVUVVJOSU5HICpgO1xuICAgIGRlYnVnKCd1cGRhdGU6ICcsIHFzLCB2YWx1ZXMpO1xuICAgIGNvbnN0IHByb21pc2UgPSAodHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICAgID8gdHJhbnNhY3Rpb25hbFNlc3Npb24udFxuICAgICAgOiB0aGlzLl9jbGllbnRcbiAgICApLmFueShxcywgdmFsdWVzKTtcbiAgICBpZiAodHJhbnNhY3Rpb25hbFNlc3Npb24pIHtcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoLnB1c2gocHJvbWlzZSk7XG4gICAgfVxuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgLy8gSG9wZWZ1bGx5LCB3ZSBjYW4gZ2V0IHJpZCBvZiB0aGlzLiBJdCdzIG9ubHkgdXNlZCBmb3IgY29uZmlnIGFuZCBob29rcy5cbiAgdXBzZXJ0T25lT2JqZWN0KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHVwZGF0ZTogYW55LFxuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uOiA/YW55XG4gICkge1xuICAgIGRlYnVnKCd1cHNlcnRPbmVPYmplY3QnLCB7IGNsYXNzTmFtZSwgcXVlcnksIHVwZGF0ZSB9KTtcbiAgICBjb25zdCBjcmVhdGVWYWx1ZSA9IE9iamVjdC5hc3NpZ24oe30sIHF1ZXJ5LCB1cGRhdGUpO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZU9iamVjdChcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHNjaGVtYSxcbiAgICAgIGNyZWF0ZVZhbHVlLFxuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICApLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIC8vIGlnbm9yZSBkdXBsaWNhdGUgdmFsdWUgZXJyb3JzIGFzIGl0J3MgdXBzZXJ0XG4gICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuZmluZE9uZUFuZFVwZGF0ZShcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICBzY2hlbWEsXG4gICAgICAgIHF1ZXJ5LFxuICAgICAgICB1cGRhdGUsXG4gICAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgZmluZChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgcXVlcnk6IFF1ZXJ5VHlwZSxcbiAgICB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCBjYXNlSW5zZW5zaXRpdmUgfTogUXVlcnlPcHRpb25zXG4gICkge1xuICAgIGRlYnVnKCdmaW5kJywgY2xhc3NOYW1lLCBxdWVyeSwge1xuICAgICAgc2tpcCxcbiAgICAgIGxpbWl0LFxuICAgICAgc29ydCxcbiAgICAgIGtleXMsXG4gICAgICBjYXNlSW5zZW5zaXRpdmUsXG4gICAgfSk7XG4gICAgY29uc3QgaGFzTGltaXQgPSBsaW1pdCAhPT0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGhhc1NraXAgPSBza2lwICE9PSB1bmRlZmluZWQ7XG4gICAgbGV0IHZhbHVlcyA9IFtjbGFzc05hbWVdO1xuICAgIGNvbnN0IHdoZXJlID0gYnVpbGRXaGVyZUNsYXVzZSh7XG4gICAgICBzY2hlbWEsXG4gICAgICBxdWVyeSxcbiAgICAgIGluZGV4OiAyLFxuICAgICAgY2FzZUluc2Vuc2l0aXZlLFxuICAgIH0pO1xuICAgIHZhbHVlcy5wdXNoKC4uLndoZXJlLnZhbHVlcyk7XG5cbiAgICBjb25zdCB3aGVyZVBhdHRlcm4gPVxuICAgICAgd2hlcmUucGF0dGVybi5sZW5ndGggPiAwID8gYFdIRVJFICR7d2hlcmUucGF0dGVybn1gIDogJyc7XG4gICAgY29uc3QgbGltaXRQYXR0ZXJuID0gaGFzTGltaXQgPyBgTElNSVQgJCR7dmFsdWVzLmxlbmd0aCArIDF9YCA6ICcnO1xuICAgIGlmIChoYXNMaW1pdCkge1xuICAgICAgdmFsdWVzLnB1c2gobGltaXQpO1xuICAgIH1cbiAgICBjb25zdCBza2lwUGF0dGVybiA9IGhhc1NraXAgPyBgT0ZGU0VUICQke3ZhbHVlcy5sZW5ndGggKyAxfWAgOiAnJztcbiAgICBpZiAoaGFzU2tpcCkge1xuICAgICAgdmFsdWVzLnB1c2goc2tpcCk7XG4gICAgfVxuXG4gICAgbGV0IHNvcnRQYXR0ZXJuID0gJyc7XG4gICAgaWYgKHNvcnQpIHtcbiAgICAgIGNvbnN0IHNvcnRDb3B5OiBhbnkgPSBzb3J0O1xuICAgICAgY29uc3Qgc29ydGluZyA9IE9iamVjdC5rZXlzKHNvcnQpXG4gICAgICAgIC5tYXAoa2V5ID0+IHtcbiAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1LZXkgPSB0cmFuc2Zvcm1Eb3RGaWVsZFRvQ29tcG9uZW50cyhrZXkpLmpvaW4oJy0+Jyk7XG4gICAgICAgICAgLy8gVXNpbmcgJGlkeCBwYXR0ZXJuIGdpdmVzOiAgbm9uLWludGVnZXIgY29uc3RhbnQgaW4gT1JERVIgQllcbiAgICAgICAgICBpZiAoc29ydENvcHlba2V5XSA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIGAke3RyYW5zZm9ybUtleX0gQVNDYDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGAke3RyYW5zZm9ybUtleX0gREVTQ2A7XG4gICAgICAgIH0pXG4gICAgICAgIC5qb2luKCk7XG4gICAgICBzb3J0UGF0dGVybiA9XG4gICAgICAgIHNvcnQgIT09IHVuZGVmaW5lZCAmJiBPYmplY3Qua2V5cyhzb3J0KS5sZW5ndGggPiAwXG4gICAgICAgICAgPyBgT1JERVIgQlkgJHtzb3J0aW5nfWBcbiAgICAgICAgICA6ICcnO1xuICAgIH1cbiAgICBpZiAod2hlcmUuc29ydHMgJiYgT2JqZWN0LmtleXMoKHdoZXJlLnNvcnRzOiBhbnkpKS5sZW5ndGggPiAwKSB7XG4gICAgICBzb3J0UGF0dGVybiA9IGBPUkRFUiBCWSAke3doZXJlLnNvcnRzLmpvaW4oKX1gO1xuICAgIH1cblxuICAgIGxldCBjb2x1bW5zID0gJyonO1xuICAgIGlmIChrZXlzKSB7XG4gICAgICAvLyBFeGNsdWRlIGVtcHR5IGtleXNcbiAgICAgIC8vIFJlcGxhY2UgQUNMIGJ5IGl0J3Mga2V5c1xuICAgICAga2V5cyA9IGtleXMucmVkdWNlKChtZW1vLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKGtleSA9PT0gJ0FDTCcpIHtcbiAgICAgICAgICBtZW1vLnB1c2goJ19ycGVybScpO1xuICAgICAgICAgIG1lbW8ucHVzaCgnX3dwZXJtJyk7XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBtZW1vLnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgIH0sIFtdKTtcbiAgICAgIGNvbHVtbnMgPSBrZXlzXG4gICAgICAgIC5tYXAoKGtleSwgaW5kZXgpID0+IHtcbiAgICAgICAgICBpZiAoa2V5ID09PSAnJHNjb3JlJykge1xuICAgICAgICAgICAgcmV0dXJuIGB0c19yYW5rX2NkKHRvX3RzdmVjdG9yKCQkezJ9LCAkJHszfTpuYW1lKSwgdG9fdHNxdWVyeSgkJHs0fSwgJCR7NX0pLCAzMikgYXMgc2NvcmVgO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYCQke2luZGV4ICsgdmFsdWVzLmxlbmd0aCArIDF9Om5hbWVgO1xuICAgICAgICB9KVxuICAgICAgICAuam9pbigpO1xuICAgICAgdmFsdWVzID0gdmFsdWVzLmNvbmNhdChrZXlzKTtcbiAgICB9XG5cbiAgICBjb25zdCBxcyA9IGBTRUxFQ1QgJHtjb2x1bW5zfSBGUk9NICQxOm5hbWUgJHt3aGVyZVBhdHRlcm59ICR7c29ydFBhdHRlcm59ICR7bGltaXRQYXR0ZXJufSAke3NraXBQYXR0ZXJufWA7XG4gICAgZGVidWcocXMsIHZhbHVlcyk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudFxuICAgICAgLmFueShxcywgdmFsdWVzKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgLy8gUXVlcnkgb24gbm9uIGV4aXN0aW5nIHRhYmxlLCBkb24ndCBjcmFzaFxuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT5cbiAgICAgICAgcmVzdWx0cy5tYXAob2JqZWN0ID0+XG4gICAgICAgICAgdGhpcy5wb3N0Z3Jlc09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSlcbiAgICAgICAgKVxuICAgICAgKTtcbiAgfVxuXG4gIC8vIENvbnZlcnRzIGZyb20gYSBwb3N0Z3Jlcy1mb3JtYXQgb2JqZWN0IHRvIGEgUkVTVC1mb3JtYXQgb2JqZWN0LlxuICAvLyBEb2VzIG5vdCBzdHJpcCBvdXQgYW55dGhpbmcgYmFzZWQgb24gYSBsYWNrIG9mIGF1dGhlbnRpY2F0aW9uLlxuICBwb3N0Z3Jlc09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lOiBzdHJpbmcsIG9iamVjdDogYW55LCBzY2hlbWE6IGFueSkge1xuICAgIE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1BvaW50ZXInICYmIG9iamVjdFtmaWVsZE5hbWVdKSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIG9iamVjdElkOiBvYmplY3RbZmllbGROYW1lXSxcbiAgICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgICBjbGFzc05hbWU6IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50YXJnZXRDbGFzcyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdSZWxhdGlvbicsXG4gICAgICAgICAgY2xhc3NOYW1lOiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udGFyZ2V0Q2xhc3MsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgb2JqZWN0W2ZpZWxkTmFtZV0gPSB7XG4gICAgICAgICAgX190eXBlOiAnR2VvUG9pbnQnLFxuICAgICAgICAgIGxhdGl0dWRlOiBvYmplY3RbZmllbGROYW1lXS55LFxuICAgICAgICAgIGxvbmdpdHVkZTogb2JqZWN0W2ZpZWxkTmFtZV0ueCxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgIGxldCBjb29yZHMgPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgY29vcmRzID0gY29vcmRzLnN1YnN0cigyLCBjb29yZHMubGVuZ3RoIC0gNCkuc3BsaXQoJyksKCcpO1xuICAgICAgICBjb29yZHMgPSBjb29yZHMubWFwKHBvaW50ID0+IHtcbiAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgcGFyc2VGbG9hdChwb2ludC5zcGxpdCgnLCcpWzFdKSxcbiAgICAgICAgICAgIHBhcnNlRmxvYXQocG9pbnQuc3BsaXQoJywnKVswXSksXG4gICAgICAgICAgXTtcbiAgICAgICAgfSk7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogJ1BvbHlnb24nLFxuICAgICAgICAgIGNvb3JkaW5hdGVzOiBjb29yZHMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdGaWxlJykge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdGaWxlJyxcbiAgICAgICAgICBuYW1lOiBvYmplY3RbZmllbGROYW1lXSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICAvL1RPRE86IHJlbW92ZSB0aGlzIHJlbGlhbmNlIG9uIHRoZSBtb25nbyBmb3JtYXQuIERCIGFkYXB0ZXIgc2hvdWxkbid0IGtub3cgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGJldHdlZW4gY3JlYXRlZCBhdCBhbmQgYW55IG90aGVyIGRhdGUgZmllbGQuXG4gICAgaWYgKG9iamVjdC5jcmVhdGVkQXQpIHtcbiAgICAgIG9iamVjdC5jcmVhdGVkQXQgPSBvYmplY3QuY3JlYXRlZEF0LnRvSVNPU3RyaW5nKCk7XG4gICAgfVxuICAgIGlmIChvYmplY3QudXBkYXRlZEF0KSB7XG4gICAgICBvYmplY3QudXBkYXRlZEF0ID0gb2JqZWN0LnVwZGF0ZWRBdC50b0lTT1N0cmluZygpO1xuICAgIH1cbiAgICBpZiAob2JqZWN0LmV4cGlyZXNBdCkge1xuICAgICAgb2JqZWN0LmV4cGlyZXNBdCA9IHtcbiAgICAgICAgX190eXBlOiAnRGF0ZScsXG4gICAgICAgIGlzbzogb2JqZWN0LmV4cGlyZXNBdC50b0lTT1N0cmluZygpLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQpIHtcbiAgICAgIG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQgPSB7XG4gICAgICAgIF9fdHlwZTogJ0RhdGUnLFxuICAgICAgICBpc286IG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQudG9JU09TdHJpbmcoKSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0KSB7XG4gICAgICBvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0ID0ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0LnRvSVNPU3RyaW5nKCksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAob2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQpIHtcbiAgICAgIG9iamVjdC5fcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0ID0ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBvYmplY3QuX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdC50b0lTT1N0cmluZygpLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC5fcGFzc3dvcmRfY2hhbmdlZF9hdCkge1xuICAgICAgb2JqZWN0Ll9wYXNzd29yZF9jaGFuZ2VkX2F0ID0ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBvYmplY3QuX3Bhc3N3b3JkX2NoYW5nZWRfYXQudG9JU09TdHJpbmcoKSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gPT09IG51bGwpIHtcbiAgICAgICAgZGVsZXRlIG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgfVxuICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgICBpc286IG9iamVjdFtmaWVsZE5hbWVdLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9iamVjdDtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIHVuaXF1ZSBpbmRleC4gVW5pcXVlIGluZGV4ZXMgb24gbnVsbGFibGUgZmllbGRzIGFyZSBub3QgYWxsb3dlZC4gU2luY2Ugd2UgZG9uJ3RcbiAgLy8gY3VycmVudGx5IGtub3cgd2hpY2ggZmllbGRzIGFyZSBudWxsYWJsZSBhbmQgd2hpY2ggYXJlbid0LCB3ZSBpZ25vcmUgdGhhdCBjcml0ZXJpYS5cbiAgLy8gQXMgc3VjaCwgd2Ugc2hvdWxkbid0IGV4cG9zZSB0aGlzIGZ1bmN0aW9uIHRvIHVzZXJzIG9mIHBhcnNlIHVudGlsIHdlIGhhdmUgYW4gb3V0LW9mLWJhbmRcbiAgLy8gV2F5IG9mIGRldGVybWluaW5nIGlmIGEgZmllbGQgaXMgbnVsbGFibGUuIFVuZGVmaW5lZCBkb2Vzbid0IGNvdW50IGFnYWluc3QgdW5pcXVlbmVzcyxcbiAgLy8gd2hpY2ggaXMgd2h5IHdlIHVzZSBzcGFyc2UgaW5kZXhlcy5cbiAgYXN5bmMgZW5zdXJlVW5pcXVlbmVzcyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgZmllbGROYW1lczogc3RyaW5nW11cbiAgKSB7XG4gICAgLy8gVXNlIHRoZSBzYW1lIG5hbWUgZm9yIGV2ZXJ5IGVuc3VyZVVuaXF1ZW5lc3MgYXR0ZW1wdCwgYmVjYXVzZSBwb3N0Z3Jlc1xuICAgIC8vIFdpbGwgaGFwcGlseSBjcmVhdGUgdGhlIHNhbWUgaW5kZXggd2l0aCBtdWx0aXBsZSBuYW1lcy5cbiAgICBjb25zdCBjb25zdHJhaW50TmFtZSA9IGB1bmlxdWVfJHtmaWVsZE5hbWVzLnNvcnQoKS5qb2luKCdfJyl9YDtcbiAgICBjb25zdCBjb25zdHJhaW50UGF0dGVybnMgPSBmaWVsZE5hbWVzLm1hcChcbiAgICAgIChmaWVsZE5hbWUsIGluZGV4KSA9PiBgJCR7aW5kZXggKyAzfTpuYW1lYFxuICAgICk7XG4gICAgY29uc3QgcXMgPSBgQUxURVIgVEFCTEUgJDE6bmFtZSBBREQgQ09OU1RSQUlOVCAkMjpuYW1lIFVOSVFVRSAoJHtjb25zdHJhaW50UGF0dGVybnMuam9pbigpfSlgO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnRcbiAgICAgIC5ub25lKHFzLCBbY2xhc3NOYW1lLCBjb25zdHJhaW50TmFtZSwgLi4uZmllbGROYW1lc10pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yICYmXG4gICAgICAgICAgZXJyb3IubWVzc2FnZS5pbmNsdWRlcyhjb25zdHJhaW50TmFtZSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgLy8gSW5kZXggYWxyZWFkeSBleGlzdHMuIElnbm9yZSBlcnJvci5cbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBlcnJvci5jb2RlID09PSBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IgJiZcbiAgICAgICAgICBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKGNvbnN0cmFpbnROYW1lKVxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBDYXN0IHRoZSBlcnJvciBpbnRvIHRoZSBwcm9wZXIgcGFyc2UgZXJyb3JcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsXG4gICAgICAgICAgICAnQSBkdXBsaWNhdGUgdmFsdWUgZm9yIGEgZmllbGQgd2l0aCB1bmlxdWUgdmFsdWVzIHdhcyBwcm92aWRlZCdcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIEV4ZWN1dGVzIGEgY291bnQuXG4gIGFzeW5jIGNvdW50KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHJlYWRQcmVmZXJlbmNlPzogc3RyaW5nLFxuICAgIGVzdGltYXRlPzogYm9vbGVhbiA9IHRydWVcbiAgKSB7XG4gICAgZGVidWcoJ2NvdW50JywgY2xhc3NOYW1lLCBxdWVyeSwgcmVhZFByZWZlcmVuY2UsIGVzdGltYXRlKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2Uoe1xuICAgICAgc2NoZW1hLFxuICAgICAgcXVlcnksXG4gICAgICBpbmRleDogMixcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZTogZmFsc2UsXG4gICAgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcblxuICAgIGNvbnN0IHdoZXJlUGF0dGVybiA9XG4gICAgICB3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgPyBgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufWAgOiAnJztcbiAgICBsZXQgcXMgPSAnJztcblxuICAgIGlmICh3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgfHwgIWVzdGltYXRlKSB7XG4gICAgICBxcyA9IGBTRUxFQ1QgY291bnQoKikgRlJPTSAkMTpuYW1lICR7d2hlcmVQYXR0ZXJufWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHFzID1cbiAgICAgICAgJ1NFTEVDVCByZWx0dXBsZXMgQVMgYXBwcm94aW1hdGVfcm93X2NvdW50IEZST00gcGdfY2xhc3MgV0hFUkUgcmVsbmFtZSA9ICQxJztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAub25lKHFzLCB2YWx1ZXMsIGEgPT4ge1xuICAgICAgICBpZiAoYS5hcHByb3hpbWF0ZV9yb3dfY291bnQgIT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiArYS5hcHByb3hpbWF0ZV9yb3dfY291bnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuICthLmNvdW50O1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgIT09IFBvc3RncmVzUmVsYXRpb25Eb2VzTm90RXhpc3RFcnJvcikge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSk7XG4gIH1cblxuICBhc3luYyBkaXN0aW5jdChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBzY2hlbWE6IFNjaGVtYVR5cGUsXG4gICAgcXVlcnk6IFF1ZXJ5VHlwZSxcbiAgICBmaWVsZE5hbWU6IHN0cmluZ1xuICApIHtcbiAgICBkZWJ1ZygnZGlzdGluY3QnLCBjbGFzc05hbWUsIHF1ZXJ5KTtcbiAgICBsZXQgZmllbGQgPSBmaWVsZE5hbWU7XG4gICAgbGV0IGNvbHVtbiA9IGZpZWxkTmFtZTtcbiAgICBjb25zdCBpc05lc3RlZCA9IGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMDtcbiAgICBpZiAoaXNOZXN0ZWQpIHtcbiAgICAgIGZpZWxkID0gdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMoZmllbGROYW1lKS5qb2luKCctPicpO1xuICAgICAgY29sdW1uID0gZmllbGROYW1lLnNwbGl0KCcuJylbMF07XG4gICAgfVxuICAgIGNvbnN0IGlzQXJyYXlGaWVsZCA9XG4gICAgICBzY2hlbWEuZmllbGRzICYmXG4gICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiZcbiAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnQXJyYXknO1xuICAgIGNvbnN0IGlzUG9pbnRlckZpZWxkID1cbiAgICAgIHNjaGVtYS5maWVsZHMgJiZcbiAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdQb2ludGVyJztcbiAgICBjb25zdCB2YWx1ZXMgPSBbZmllbGQsIGNvbHVtbiwgY2xhc3NOYW1lXTtcbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2Uoe1xuICAgICAgc2NoZW1hLFxuICAgICAgcXVlcnksXG4gICAgICBpbmRleDogNCxcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZTogZmFsc2UsXG4gICAgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcblxuICAgIGNvbnN0IHdoZXJlUGF0dGVybiA9XG4gICAgICB3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgPyBgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufWAgOiAnJztcbiAgICBjb25zdCB0cmFuc2Zvcm1lciA9IGlzQXJyYXlGaWVsZCA/ICdqc29uYl9hcnJheV9lbGVtZW50cycgOiAnT04nO1xuICAgIGxldCBxcyA9IGBTRUxFQ1QgRElTVElOQ1QgJHt0cmFuc2Zvcm1lcn0oJDE6bmFtZSkgJDI6bmFtZSBGUk9NICQzOm5hbWUgJHt3aGVyZVBhdHRlcm59YDtcbiAgICBpZiAoaXNOZXN0ZWQpIHtcbiAgICAgIHFzID0gYFNFTEVDVCBESVNUSU5DVCAke3RyYW5zZm9ybWVyfSgkMTpyYXcpICQyOnJhdyBGUk9NICQzOm5hbWUgJHt3aGVyZVBhdHRlcm59YDtcbiAgICB9XG4gICAgZGVidWcocXMsIHZhbHVlcyk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudFxuICAgICAgLmFueShxcywgdmFsdWVzKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAoIWlzTmVzdGVkKSB7XG4gICAgICAgICAgcmVzdWx0cyA9IHJlc3VsdHMuZmlsdGVyKG9iamVjdCA9PiBvYmplY3RbZmllbGRdICE9PSBudWxsKTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICAgIGlmICghaXNQb2ludGVyRmllbGQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdFtmaWVsZF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgICAgICAgY2xhc3NOYW1lOiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICAgIG9iamVjdElkOiBvYmplY3RbZmllbGRdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGlsZCA9IGZpZWxkTmFtZS5zcGxpdCgnLicpWzFdO1xuICAgICAgICByZXR1cm4gcmVzdWx0cy5tYXAob2JqZWN0ID0+IG9iamVjdFtjb2x1bW5dW2NoaWxkXSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PlxuICAgICAgICByZXN1bHRzLm1hcChvYmplY3QgPT5cbiAgICAgICAgICB0aGlzLnBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKVxuICAgICAgICApXG4gICAgICApO1xuICB9XG5cbiAgYXN5bmMgYWdncmVnYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSkge1xuICAgIGRlYnVnKCdhZ2dyZWdhdGUnLCBjbGFzc05hbWUsIHBpcGVsaW5lKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBsZXQgaW5kZXg6IG51bWJlciA9IDI7XG4gICAgbGV0IGNvbHVtbnM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IGNvdW50RmllbGQgPSBudWxsO1xuICAgIGxldCBncm91cFZhbHVlcyA9IG51bGw7XG4gICAgbGV0IHdoZXJlUGF0dGVybiA9ICcnO1xuICAgIGxldCBsaW1pdFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc2tpcFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc29ydFBhdHRlcm4gPSAnJztcbiAgICBsZXQgZ3JvdXBQYXR0ZXJuID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwaXBlbGluZS5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY29uc3Qgc3RhZ2UgPSBwaXBlbGluZVtpXTtcbiAgICAgIGlmIChzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRncm91cFtmaWVsZF07XG4gICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZmllbGQgPT09ICdfaWQnICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUgIT09ICcnKSB7XG4gICAgICAgICAgICBjb2x1bW5zLnB1c2goYCQke2luZGV4fTpuYW1lIEFTIFwib2JqZWN0SWRcImApO1xuICAgICAgICAgICAgZ3JvdXBQYXR0ZXJuID0gYEdST1VQIEJZICQke2luZGV4fTpuYW1lYDtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlKSk7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGZpZWxkID09PSAnX2lkJyAmJlxuICAgICAgICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgICAgT2JqZWN0LmtleXModmFsdWUpLmxlbmd0aCAhPT0gMFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZ3JvdXBWYWx1ZXMgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwQnlGaWVsZHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYWxpYXMgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gT2JqZWN0LmtleXModmFsdWVbYWxpYXNdKVswXTtcbiAgICAgICAgICAgICAgY29uc3Qgc291cmNlID0gdHJhbnNmb3JtQWdncmVnYXRlRmllbGQodmFsdWVbYWxpYXNdW29wZXJhdGlvbl0pO1xuICAgICAgICAgICAgICBpZiAobW9uZ29BZ2dyZWdhdGVUb1Bvc3RncmVzW29wZXJhdGlvbl0pIHtcbiAgICAgICAgICAgICAgICBpZiAoIWdyb3VwQnlGaWVsZHMuaW5jbHVkZXMoYFwiJHtzb3VyY2V9XCJgKSkge1xuICAgICAgICAgICAgICAgICAgZ3JvdXBCeUZpZWxkcy5wdXNoKGBcIiR7c291cmNlfVwiYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbHVtbnMucHVzaChcbiAgICAgICAgICAgICAgICAgIGBFWFRSQUNUKCR7XG4gICAgICAgICAgICAgICAgICAgIG1vbmdvQWdncmVnYXRlVG9Qb3N0Z3Jlc1tvcGVyYXRpb25dXG4gICAgICAgICAgICAgICAgICB9IEZST00gJCR7aW5kZXh9Om5hbWUgQVQgVElNRSBaT05FICdVVEMnKSBBUyAkJHtpbmRleCArXG4gICAgICAgICAgICAgICAgICAgIDF9Om5hbWVgXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChzb3VyY2UsIGFsaWFzKTtcbiAgICAgICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBncm91cFBhdHRlcm4gPSBgR1JPVVAgQlkgJCR7aW5kZXh9OnJhd2A7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChncm91cEJ5RmllbGRzLmpvaW4oKSk7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUuJHN1bSkge1xuICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlLiRzdW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKGBTVU0oJCR7aW5kZXh9Om5hbWUpIEFTICQke2luZGV4ICsgMX06bmFtZWApO1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRzdW0pLCBmaWVsZCk7XG4gICAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3VudEZpZWxkID0gZmllbGQ7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKGBDT1VOVCgqKSBBUyAkJHtpbmRleH06bmFtZWApO1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJG1heCkge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYE1BWCgkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRtYXgpLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJG1pbikge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYE1JTigkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRtaW4pLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJGF2Zykge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYEFWRygkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRhdmcpLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2x1bW5zLnB1c2goJyonKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kcHJvamVjdCkge1xuICAgICAgICBpZiAoY29sdW1ucy5pbmNsdWRlcygnKicpKSB7XG4gICAgICAgICAgY29sdW1ucyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gc3RhZ2UuJHByb2plY3QpIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRwcm9qZWN0W2ZpZWxkXTtcbiAgICAgICAgICBpZiAodmFsdWUgPT09IDEgfHwgdmFsdWUgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbHVtbnMucHVzaChgJCR7aW5kZXh9Om5hbWVgKTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gW107XG4gICAgICAgIGNvbnN0IG9yT3JBbmQgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoXG4gICAgICAgICAgc3RhZ2UuJG1hdGNoLFxuICAgICAgICAgICckb3InXG4gICAgICAgIClcbiAgICAgICAgICA/ICcgT1IgJ1xuICAgICAgICAgIDogJyBBTkQgJztcblxuICAgICAgICBpZiAoc3RhZ2UuJG1hdGNoLiRvcikge1xuICAgICAgICAgIGNvbnN0IGNvbGxhcHNlID0ge307XG4gICAgICAgICAgc3RhZ2UuJG1hdGNoLiRvci5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZWxlbWVudCkge1xuICAgICAgICAgICAgICBjb2xsYXBzZVtrZXldID0gZWxlbWVudFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHN0YWdlLiRtYXRjaCA9IGNvbGxhcHNlO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBzdGFnZS4kbWF0Y2hbZmllbGRdO1xuICAgICAgICAgIGNvbnN0IG1hdGNoUGF0dGVybnMgPSBbXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3IpLmZvckVhY2goY21wID0+IHtcbiAgICAgICAgICAgIGlmICh2YWx1ZVtjbXBdKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHBnQ29tcGFyYXRvciA9IFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcltjbXBdO1xuICAgICAgICAgICAgICBtYXRjaFBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICAgICAgYCQke2luZGV4fTpuYW1lICR7cGdDb21wYXJhdG9yfSAkJHtpbmRleCArIDF9YFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZCwgdG9Qb3N0Z3Jlc1ZhbHVlKHZhbHVlW2NtcF0pKTtcbiAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAobWF0Y2hQYXR0ZXJucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAoJHttYXRjaFBhdHRlcm5zLmpvaW4oJyBBTkQgJyl9KWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJlxuICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSAmJlxuICAgICAgICAgICAgbWF0Y2hQYXR0ZXJucy5sZW5ndGggPT09IDBcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goZmllbGQsIHZhbHVlKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHdoZXJlUGF0dGVybiA9XG4gICAgICAgICAgcGF0dGVybnMubGVuZ3RoID4gMCA/IGBXSEVSRSAke3BhdHRlcm5zLmpvaW4oYCAke29yT3JBbmR9IGApfWAgOiAnJztcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kbGltaXQpIHtcbiAgICAgICAgbGltaXRQYXR0ZXJuID0gYExJTUlUICQke2luZGV4fWA7XG4gICAgICAgIHZhbHVlcy5wdXNoKHN0YWdlLiRsaW1pdCk7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJHNraXApIHtcbiAgICAgICAgc2tpcFBhdHRlcm4gPSBgT0ZGU0VUICQke2luZGV4fWA7XG4gICAgICAgIHZhbHVlcy5wdXNoKHN0YWdlLiRza2lwKTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kc29ydCkge1xuICAgICAgICBjb25zdCBzb3J0ID0gc3RhZ2UuJHNvcnQ7XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhzb3J0KTtcbiAgICAgICAgY29uc3Qgc29ydGluZyA9IGtleXNcbiAgICAgICAgICAubWFwKGtleSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1lciA9IHNvcnRba2V5XSA9PT0gMSA/ICdBU0MnIDogJ0RFU0MnO1xuICAgICAgICAgICAgY29uc3Qgb3JkZXIgPSBgJCR7aW5kZXh9Om5hbWUgJHt0cmFuc2Zvcm1lcn1gO1xuICAgICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICAgIHJldHVybiBvcmRlcjtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5qb2luKCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKC4uLmtleXMpO1xuICAgICAgICBzb3J0UGF0dGVybiA9XG4gICAgICAgICAgc29ydCAhPT0gdW5kZWZpbmVkICYmIHNvcnRpbmcubGVuZ3RoID4gMCA/IGBPUkRFUiBCWSAke3NvcnRpbmd9YCA6ICcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHFzID0gYFNFTEVDVCAke2NvbHVtbnMuam9pbigpfSBGUk9NICQxOm5hbWUgJHt3aGVyZVBhdHRlcm59ICR7c29ydFBhdHRlcm59ICR7bGltaXRQYXR0ZXJufSAke3NraXBQYXR0ZXJufSAke2dyb3VwUGF0dGVybn1gO1xuICAgIGRlYnVnKHFzLCB2YWx1ZXMpO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnRcbiAgICAgIC5tYXAocXMsIHZhbHVlcywgYSA9PlxuICAgICAgICB0aGlzLnBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIGEsIHNjaGVtYSlcbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICByZXN1bHRzLmZvckVhY2gocmVzdWx0ID0+IHtcbiAgICAgICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsICdvYmplY3RJZCcpKSB7XG4gICAgICAgICAgICByZXN1bHQub2JqZWN0SWQgPSBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZ3JvdXBWYWx1ZXMpIHtcbiAgICAgICAgICAgIHJlc3VsdC5vYmplY3RJZCA9IHt9O1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZ3JvdXBWYWx1ZXMpIHtcbiAgICAgICAgICAgICAgcmVzdWx0Lm9iamVjdElkW2tleV0gPSByZXN1bHRba2V5XTtcbiAgICAgICAgICAgICAgZGVsZXRlIHJlc3VsdFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY291bnRGaWVsZCkge1xuICAgICAgICAgICAgcmVzdWx0W2NvdW50RmllbGRdID0gcGFyc2VJbnQocmVzdWx0W2NvdW50RmllbGRdLCAxMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHBlcmZvcm1Jbml0aWFsaXphdGlvbih7IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMgfTogYW55KSB7XG4gICAgLy8gVE9ETzogVGhpcyBtZXRob2QgbmVlZHMgdG8gYmUgcmV3cml0dGVuIHRvIG1ha2UgcHJvcGVyIHVzZSBvZiBjb25uZWN0aW9ucyAoQHZpdGFseS10KVxuICAgIGRlYnVnKCdwZXJmb3JtSW5pdGlhbGl6YXRpb24nKTtcbiAgICBjb25zdCBwcm9taXNlcyA9IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMubWFwKHNjaGVtYSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5jcmVhdGVUYWJsZShzY2hlbWEuY2xhc3NOYW1lLCBzY2hlbWEpXG4gICAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGVyci5jb2RlID09PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IgfHxcbiAgICAgICAgICAgIGVyci5jb2RlID09PSBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUVcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB0aGlzLnNjaGVtYVVwZ3JhZGUoc2NoZW1hLmNsYXNzTmFtZSwgc2NoZW1hKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xpZW50LnR4KCdwZXJmb3JtLWluaXRpYWxpemF0aW9uJywgdCA9PiB7XG4gICAgICAgICAgcmV0dXJuIHQuYmF0Y2goW1xuICAgICAgICAgICAgdC5ub25lKHNxbC5taXNjLmpzb25PYmplY3RTZXRLZXlzKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuYWRkKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuYWRkVW5pcXVlKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkucmVtb3ZlKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuY29udGFpbnNBbGwpLFxuICAgICAgICAgICAgdC5ub25lKHNxbC5hcnJheS5jb250YWluc0FsbFJlZ2V4KSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuY29udGFpbnMpLFxuICAgICAgICAgIF0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbihkYXRhID0+IHtcbiAgICAgICAgZGVidWcoYGluaXRpYWxpemF0aW9uRG9uZSBpbiAke2RhdGEuZHVyYXRpb259YCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlSW5kZXhlcyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBpbmRleGVzOiBhbnksXG4gICAgY29ubjogP2FueVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gKGNvbm4gfHwgdGhpcy5fY2xpZW50KS50eCh0ID0+XG4gICAgICB0LmJhdGNoKFxuICAgICAgICBpbmRleGVzLm1hcChpID0+IHtcbiAgICAgICAgICByZXR1cm4gdC5ub25lKCdDUkVBVEUgSU5ERVggJDE6bmFtZSBPTiAkMjpuYW1lICgkMzpuYW1lKScsIFtcbiAgICAgICAgICAgIGkubmFtZSxcbiAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgIGkua2V5LFxuICAgICAgICAgIF0pO1xuICAgICAgICB9KVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBhc3luYyBjcmVhdGVJbmRleGVzSWZOZWVkZWQoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZmllbGROYW1lOiBzdHJpbmcsXG4gICAgdHlwZTogYW55LFxuICAgIGNvbm46ID9hbnlcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgKFxuICAgICAgY29ubiB8fCB0aGlzLl9jbGllbnRcbiAgICApLm5vbmUoJ0NSRUFURSBJTkRFWCAkMTpuYW1lIE9OICQyOm5hbWUgKCQzOm5hbWUpJywgW1xuICAgICAgZmllbGROYW1lLFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgdHlwZSxcbiAgICBdKTtcbiAgfVxuXG4gIGFzeW5jIGRyb3BJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleGVzOiBhbnksIGNvbm46IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHF1ZXJpZXMgPSBpbmRleGVzLm1hcChpID0+ICh7XG4gICAgICBxdWVyeTogJ0RST1AgSU5ERVggJDE6bmFtZScsXG4gICAgICB2YWx1ZXM6IGksXG4gICAgfSkpO1xuICAgIGF3YWl0IChjb25uIHx8IHRoaXMuX2NsaWVudCkudHgodCA9PlxuICAgICAgdC5ub25lKHRoaXMuX3BncC5oZWxwZXJzLmNvbmNhdChxdWVyaWVzKSlcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgZ2V0SW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IHFzID0gJ1NFTEVDVCAqIEZST00gcGdfaW5kZXhlcyBXSEVSRSB0YWJsZW5hbWUgPSAke2NsYXNzTmFtZX0nO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQuYW55KHFzLCB7IGNsYXNzTmFtZSB9KTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIFVzZWQgZm9yIHRlc3RpbmcgcHVycG9zZXNcbiAgYXN5bmMgdXBkYXRlRXN0aW1hdGVkQ291bnQoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50Lm5vbmUoJ0FOQUxZWkUgJDE6bmFtZScsIFtjbGFzc05hbWVdKTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uKCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgY29uc3QgdHJhbnNhY3Rpb25hbFNlc3Npb24gPSB7fTtcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc3VsdCA9IHRoaXMuX2NsaWVudC50eCh0ID0+IHtcbiAgICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24udCA9IHQ7XG4gICAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbi5yZXNvbHZlID0gcmVzb2x2ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoID0gW107XG4gICAgICAgIHJlc29sdmUodHJhbnNhY3Rpb25hbFNlc3Npb24pO1xuICAgICAgICByZXR1cm4gdHJhbnNhY3Rpb25hbFNlc3Npb24ucHJvbWlzZTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24odHJhbnNhY3Rpb25hbFNlc3Npb246IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc29sdmUoXG4gICAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbi50LmJhdGNoKHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoKVxuICAgICk7XG4gICAgcmV0dXJuIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc3VsdDtcbiAgfVxuXG4gIGFib3J0VHJhbnNhY3Rpb25hbFNlc3Npb24odHJhbnNhY3Rpb25hbFNlc3Npb246IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc3VsdC5jYXRjaCgpO1xuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoLnB1c2goUHJvbWlzZS5yZWplY3QoKSk7XG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzb2x2ZShcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnQuYmF0Y2godHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gpXG4gICAgKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gVE9ETzogaW1wbGVtZW50P1xuICBlbnN1cmVJbmRleCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udmVydFBvbHlnb25Ub1NRTChwb2x5Z29uKSB7XG4gIGlmIChwb2x5Z29uLmxlbmd0aCA8IDMpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICBgUG9seWdvbiBtdXN0IGhhdmUgYXQgbGVhc3QgMyB2YWx1ZXNgXG4gICAgKTtcbiAgfVxuICBpZiAoXG4gICAgcG9seWdvblswXVswXSAhPT0gcG9seWdvbltwb2x5Z29uLmxlbmd0aCAtIDFdWzBdIHx8XG4gICAgcG9seWdvblswXVsxXSAhPT0gcG9seWdvbltwb2x5Z29uLmxlbmd0aCAtIDFdWzFdXG4gICkge1xuICAgIHBvbHlnb24ucHVzaChwb2x5Z29uWzBdKTtcbiAgfVxuICBjb25zdCB1bmlxdWUgPSBwb2x5Z29uLmZpbHRlcigoaXRlbSwgaW5kZXgsIGFyKSA9PiB7XG4gICAgbGV0IGZvdW5kSW5kZXggPSAtMTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICBjb25zdCBwdCA9IGFyW2ldO1xuICAgICAgaWYgKHB0WzBdID09PSBpdGVtWzBdICYmIHB0WzFdID09PSBpdGVtWzFdKSB7XG4gICAgICAgIGZvdW5kSW5kZXggPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kSW5kZXggPT09IGluZGV4O1xuICB9KTtcbiAgaWYgKHVuaXF1ZS5sZW5ndGggPCAzKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgJ0dlb0pTT046IExvb3AgbXVzdCBoYXZlIGF0IGxlYXN0IDMgZGlmZmVyZW50IHZlcnRpY2VzJ1xuICAgICk7XG4gIH1cbiAgY29uc3QgcG9pbnRzID0gcG9seWdvblxuICAgIC5tYXAocG9pbnQgPT4ge1xuICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBhcnNlRmxvYXQocG9pbnRbMV0pLCBwYXJzZUZsb2F0KHBvaW50WzBdKSk7XG4gICAgICByZXR1cm4gYCgke3BvaW50WzFdfSwgJHtwb2ludFswXX0pYDtcbiAgICB9KVxuICAgIC5qb2luKCcsICcpO1xuICByZXR1cm4gYCgke3BvaW50c30pYDtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlV2hpdGVTcGFjZShyZWdleCkge1xuICBpZiAoIXJlZ2V4LmVuZHNXaXRoKCdcXG4nKSkge1xuICAgIHJlZ2V4ICs9ICdcXG4nO1xuICB9XG5cbiAgLy8gcmVtb3ZlIG5vbiBlc2NhcGVkIGNvbW1lbnRzXG4gIHJldHVybiAoXG4gICAgcmVnZXhcbiAgICAgIC5yZXBsYWNlKC8oW15cXFxcXSkjLipcXG4vZ2ltLCAnJDEnKVxuICAgICAgLy8gcmVtb3ZlIGxpbmVzIHN0YXJ0aW5nIHdpdGggYSBjb21tZW50XG4gICAgICAucmVwbGFjZSgvXiMuKlxcbi9naW0sICcnKVxuICAgICAgLy8gcmVtb3ZlIG5vbiBlc2NhcGVkIHdoaXRlc3BhY2VcbiAgICAgIC5yZXBsYWNlKC8oW15cXFxcXSlcXHMrL2dpbSwgJyQxJylcbiAgICAgIC8vIHJlbW92ZSB3aGl0ZXNwYWNlIGF0IHRoZSBiZWdpbm5pbmcgb2YgYSBsaW5lXG4gICAgICAucmVwbGFjZSgvXlxccysvLCAnJylcbiAgICAgIC50cmltKClcbiAgKTtcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1JlZ2V4UGF0dGVybihzKSB7XG4gIGlmIChzICYmIHMuc3RhcnRzV2l0aCgnXicpKSB7XG4gICAgLy8gcmVnZXggZm9yIHN0YXJ0c1dpdGhcbiAgICByZXR1cm4gJ14nICsgbGl0ZXJhbGl6ZVJlZ2V4UGFydChzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIGlmIChzICYmIHMuZW5kc1dpdGgoJyQnKSkge1xuICAgIC8vIHJlZ2V4IGZvciBlbmRzV2l0aFxuICAgIHJldHVybiBsaXRlcmFsaXplUmVnZXhQYXJ0KHMuc2xpY2UoMCwgcy5sZW5ndGggLSAxKSkgKyAnJCc7XG4gIH1cblxuICAvLyByZWdleCBmb3IgY29udGFpbnNcbiAgcmV0dXJuIGxpdGVyYWxpemVSZWdleFBhcnQocyk7XG59XG5cbmZ1bmN0aW9uIGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlKSB7XG4gIGlmICghdmFsdWUgfHwgdHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCAhdmFsdWUuc3RhcnRzV2l0aCgnXicpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgbWF0Y2hlcyA9IHZhbHVlLm1hdGNoKC9cXF5cXFxcUS4qXFxcXEUvKTtcbiAgcmV0dXJuICEhbWF0Y2hlcztcbn1cblxuZnVuY3Rpb24gaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSh2YWx1ZXMpIHtcbiAgaWYgKCF2YWx1ZXMgfHwgIUFycmF5LmlzQXJyYXkodmFsdWVzKSB8fCB2YWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBmaXJzdFZhbHVlc0lzUmVnZXggPSBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZXNbMF0uJHJlZ2V4KTtcbiAgaWYgKHZhbHVlcy5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZXNJc1JlZ2V4O1xuICB9XG5cbiAgZm9yIChsZXQgaSA9IDEsIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGg7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGlmIChmaXJzdFZhbHVlc0lzUmVnZXggIT09IGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlc1tpXS4kcmVnZXgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzQW55VmFsdWVSZWdleFN0YXJ0c1dpdGgodmFsdWVzKSB7XG4gIHJldHVybiB2YWx1ZXMuc29tZShmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZS4kcmVnZXgpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlTGl0ZXJhbFJlZ2V4KHJlbWFpbmluZykge1xuICByZXR1cm4gcmVtYWluaW5nXG4gICAgLnNwbGl0KCcnKVxuICAgIC5tYXAoYyA9PiB7XG4gICAgICBjb25zdCByZWdleCA9IFJlZ0V4cCgnWzAtOSBdfFxcXFxwe0x9JywgJ3UnKTsgLy8gU3VwcG9ydCBhbGwgdW5pY29kZSBsZXR0ZXIgY2hhcnNcbiAgICAgIGlmIChjLm1hdGNoKHJlZ2V4KSAhPT0gbnVsbCkge1xuICAgICAgICAvLyBkb24ndCBlc2NhcGUgYWxwaGFudW1lcmljIGNoYXJhY3RlcnNcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgICB9XG4gICAgICAvLyBlc2NhcGUgZXZlcnl0aGluZyBlbHNlIChzaW5nbGUgcXVvdGVzIHdpdGggc2luZ2xlIHF1b3RlcywgZXZlcnl0aGluZyBlbHNlIHdpdGggYSBiYWNrc2xhc2gpXG4gICAgICByZXR1cm4gYyA9PT0gYCdgID8gYCcnYCA6IGBcXFxcJHtjfWA7XG4gICAgfSlcbiAgICAuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIGxpdGVyYWxpemVSZWdleFBhcnQoczogc3RyaW5nKSB7XG4gIGNvbnN0IG1hdGNoZXIxID0gL1xcXFxRKCg/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..d62f44f260 --- /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); + } 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db25maWcuanMiXSwibmFtZXMiOlsicmVtb3ZlVHJhaWxpbmdTbGFzaCIsInN0ciIsImVuZHNXaXRoIiwic3Vic3RyIiwibGVuZ3RoIiwiQ29uZmlnIiwiZ2V0IiwiYXBwbGljYXRpb25JZCIsIm1vdW50IiwiY2FjaGVJbmZvIiwiQXBwQ2FjaGUiLCJjb25maWciLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsImtleSIsInNjaGVtYUNhY2hlIiwiU2NoZW1hQ2FjaGUiLCJjYWNoZUNvbnRyb2xsZXIiLCJzY2hlbWFDYWNoZVRUTCIsImVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlIiwiZGF0YWJhc2UiLCJEYXRhYmFzZUNvbnRyb2xsZXIiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJhZGFwdGVyIiwiZ2VuZXJhdGVTZXNzaW9uRXhwaXJlc0F0IiwiYmluZCIsImdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbkV4cGlyZXNBdCIsInB1dCIsInNlcnZlckNvbmZpZ3VyYXRpb24iLCJ2YWxpZGF0ZSIsImFwcElkIiwic2V0dXBQYXNzd29yZFZhbGlkYXRvciIsInBhc3N3b3JkUG9saWN5IiwidmVyaWZ5VXNlckVtYWlscyIsInVzZXJDb250cm9sbGVyIiwiYXBwTmFtZSIsInB1YmxpY1NlcnZlclVSTCIsInJldm9rZVNlc3Npb25PblBhc3N3b3JkUmVzZXQiLCJleHBpcmVJbmFjdGl2ZVNlc3Npb25zIiwic2Vzc2lvbkxlbmd0aCIsIm1heExpbWl0IiwiZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJhY2NvdW50TG9ja291dCIsIm1hc3RlcktleUlwcyIsIm1hc3RlcktleSIsInJlYWRPbmx5TWFzdGVyS2V5IiwiYWxsb3dIZWFkZXJzIiwiRXJyb3IiLCJlbWFpbEFkYXB0ZXIiLCJ2YWxpZGF0ZUVtYWlsQ29uZmlndXJhdGlvbiIsInZhbGlkYXRlQWNjb3VudExvY2tvdXRQb2xpY3kiLCJ2YWxpZGF0ZVBhc3N3b3JkUG9saWN5Iiwic3RhcnRzV2l0aCIsInZhbGlkYXRlU2Vzc2lvbkNvbmZpZ3VyYXRpb24iLCJ2YWxpZGF0ZU1hc3RlcktleUlwcyIsInZhbGlkYXRlTWF4TGltaXQiLCJ2YWxpZGF0ZUFsbG93SGVhZGVycyIsImR1cmF0aW9uIiwiTnVtYmVyIiwiaXNJbnRlZ2VyIiwidGhyZXNob2xkIiwibWF4UGFzc3dvcmRBZ2UiLCJ1bmRlZmluZWQiLCJyZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbiIsInZhbGlkYXRvclBhdHRlcm4iLCJSZWdFeHAiLCJ2YWxpZGF0b3JDYWxsYmFjayIsImRvTm90QWxsb3dVc2VybmFtZSIsIm1heFBhc3N3b3JkSGlzdG9yeSIsInBhdHRlcm5WYWxpZGF0b3IiLCJ2YWx1ZSIsInRlc3QiLCJpc05hTiIsImlwIiwibmV0IiwiaXNJUCIsIl9tb3VudCIsIm5ld1ZhbHVlIiwiaW5jbHVkZXMiLCJBcnJheSIsImlzQXJyYXkiLCJoZWFkZXIiLCJ0cmltIiwibm93IiwiRGF0ZSIsImdldFRpbWUiLCJnZW5lcmF0ZVBhc3N3b3JkUmVzZXRUb2tlbkV4cGlyZXNBdCIsImludmFsaWRMaW5rVVJMIiwiY3VzdG9tUGFnZXMiLCJpbnZhbGlkTGluayIsImludmFsaWRWZXJpZmljYXRpb25MaW5rVVJMIiwiaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsiLCJsaW5rU2VuZFN1Y2Nlc3NVUkwiLCJsaW5rU2VuZFN1Y2Nlc3MiLCJsaW5rU2VuZEZhaWxVUkwiLCJsaW5rU2VuZEZhaWwiLCJ2ZXJpZnlFbWFpbFN1Y2Nlc3NVUkwiLCJ2ZXJpZnlFbWFpbFN1Y2Nlc3MiLCJjaG9vc2VQYXNzd29yZFVSTCIsImNob29zZVBhc3N3b3JkIiwicmVxdWVzdFJlc2V0UGFzc3dvcmRVUkwiLCJwYXNzd29yZFJlc2V0U3VjY2Vzc1VSTCIsInBhc3N3b3JkUmVzZXRTdWNjZXNzIiwicGFyc2VGcmFtZVVSTCIsInZlcmlmeUVtYWlsVVJMIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUlBOztBQUNBOztBQUNBOztB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LCJzb3VyY2VzQ29udGVudCI6WyIvLyBBIENvbmZpZyBvYmplY3QgcHJvdmlkZXMgaW5mb3JtYXRpb24gYWJvdXQgaG93IGEgc3BlY2lmaWMgYXBwIGlzXG4vLyBjb25maWd1cmVkLlxuLy8gbW91bnQgaXMgdGhlIFVSTCBmb3IgdGhlIHJvb3Qgb2YgdGhlIEFQSTsgaW5jbHVkZXMgaHR0cCwgZG9tYWluLCBldGMuXG5cbmltcG9ydCBBcHBDYWNoZSBmcm9tICcuL2NhY2hlJztcbmltcG9ydCBTY2hlbWFDYWNoZSBmcm9tICcuL0NvbnRyb2xsZXJzL1NjaGVtYUNhY2hlJztcbmltcG9ydCBEYXRhYmFzZUNvbnRyb2xsZXIgZnJvbSAnLi9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXInO1xuaW1wb3J0IG5ldCBmcm9tICduZXQnO1xuXG5mdW5jdGlvbiByZW1vdmVUcmFpbGluZ1NsYXNoKHN0cikge1xuICBpZiAoIXN0cikge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbiAgaWYgKHN0ci5lbmRzV2l0aCgnLycpKSB7XG4gICAgc3RyID0gc3RyLnN1YnN0cigwLCBzdHIubGVuZ3RoIC0gMSk7XG4gIH1cbiAgcmV0dXJuIHN0cjtcbn1cblxuZXhwb3J0IGNsYXNzIENvbmZpZyB7XG4gIHN0YXRpYyBnZXQoYXBwbGljYXRpb25JZDogc3RyaW5nLCBtb3VudDogc3RyaW5nKSB7XG4gICAgY29uc3QgY2FjaGVJbmZvID0gQXBwQ2FjaGUuZ2V0KGFwcGxpY2F0aW9uSWQpO1xuICAgIGlmICghY2FjaGVJbmZvKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZyA9IG5ldyBDb25maWcoKTtcbiAgICBjb25maWcuYXBwbGljYXRpb25JZCA9IGFwcGxpY2F0aW9uSWQ7XG4gICAgT2JqZWN0LmtleXMoY2FjaGVJbmZvKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBpZiAoa2V5ID09ICdkYXRhYmFzZUNvbnRyb2xsZXInKSB7XG4gICAgICAgIGNvbnN0IHNjaGVtYUNhY2hlID0gbmV3IFNjaGVtYUNhY2hlKFxuICAgICAgICAgIGNhY2hlSW5mby5jYWNoZUNvbnRyb2xsZXIsXG4gICAgICAgICAgY2FjaGVJbmZvLnNjaGVtYUNhY2hlVFRMLFxuICAgICAgICAgIGNhY2hlSW5mby5lbmFibGVTaW5nbGVTY2hlbWFDYWNoZVxuICAgICAgICApO1xuICAgICAgICBjb25maWcuZGF0YWJhc2UgPSBuZXcgRGF0YWJhc2VDb250cm9sbGVyKFxuICAgICAgICAgIGNhY2hlSW5mby5kYXRhYmFzZUNvbnRyb2xsZXIuYWRhcHRlcixcbiAgICAgICAgICBzY2hlbWFDYWNoZVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uZmlnW2tleV0gPSBjYWNoZUluZm9ba2V5XTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjb25maWcubW91bnQgPSByZW1vdmVUcmFpbGluZ1NsYXNoKG1vdW50KTtcbiAgICBjb25maWcuZ2VuZXJhdGVTZXNzaW9uRXhwaXJlc0F0ID0gY29uZmlnLmdlbmVyYXRlU2Vzc2lvbkV4cGlyZXNBdC5iaW5kKFxuICAgICAgY29uZmlnXG4gICAgKTtcbiAgICBjb25maWcuZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuRXhwaXJlc0F0ID0gY29uZmlnLmdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbkV4cGlyZXNBdC5iaW5kKFxuICAgICAgY29uZmlnXG4gICAgKTtcbiAgICByZXR1cm4gY29uZmlnO1xuICB9XG5cbiAgc3RhdGljIHB1dChzZXJ2ZXJDb25maWd1cmF0aW9uKSB7XG4gICAgQ29uZmlnLnZhbGlkYXRlKHNlcnZlckNvbmZpZ3VyYXRpb24pO1xuICAgIEFwcENhY2hlLnB1dChzZXJ2ZXJDb25maWd1cmF0aW9uLmFwcElkLCBzZXJ2ZXJDb25maWd1cmF0aW9uKTtcbiAgICBDb25maWcuc2V0dXBQYXNzd29yZFZhbGlkYXRvcihzZXJ2ZXJDb25maWd1cmF0aW9uLnBhc3N3b3JkUG9saWN5KTtcbiAgICByZXR1cm4gc2VydmVyQ29uZmlndXJhdGlvbjtcbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZSh7XG4gICAgdmVyaWZ5VXNlckVtYWlscyxcbiAgICB1c2VyQ29udHJvbGxlcixcbiAgICBhcHBOYW1lLFxuICAgIHB1YmxpY1NlcnZlclVSTCxcbiAgICByZXZva2VTZXNzaW9uT25QYXNzd29yZFJlc2V0LFxuICAgIGV4cGlyZUluYWN0aXZlU2Vzc2lvbnMsXG4gICAgc2Vzc2lvbkxlbmd0aCxcbiAgICBtYXhMaW1pdCxcbiAgICBlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbixcbiAgICBhY2NvdW50TG9ja291dCxcbiAgICBwYXNzd29yZFBvbGljeSxcbiAgICBtYXN0ZXJLZXlJcHMsXG4gICAgbWFzdGVyS2V5LFxuICAgIHJlYWRPbmx5TWFzdGVyS2V5LFxuICAgIGFsbG93SGVhZGVycyxcbiAgfSkge1xuICAgIGlmIChtYXN0ZXJLZXkgPT09IHJlYWRPbmx5TWFzdGVyS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21hc3RlcktleSBhbmQgcmVhZE9ubHlNYXN0ZXJLZXkgc2hvdWxkIGJlIGRpZmZlcmVudCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGVtYWlsQWRhcHRlciA9IHVzZXJDb250cm9sbGVyLmFkYXB0ZXI7XG4gICAgaWYgKHZlcmlmeVVzZXJFbWFpbHMpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVFbWFpbENvbmZpZ3VyYXRpb24oe1xuICAgICAgICBlbWFpbEFkYXB0ZXIsXG4gICAgICAgIGFwcE5hbWUsXG4gICAgICAgIHB1YmxpY1NlcnZlclVSTCxcbiAgICAgICAgZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlQWNjb3VudExvY2tvdXRQb2xpY3koYWNjb3VudExvY2tvdXQpO1xuXG4gICAgdGhpcy52YWxpZGF0ZVBhc3N3b3JkUG9saWN5KHBhc3N3b3JkUG9saWN5KTtcblxuICAgIGlmICh0eXBlb2YgcmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICB0aHJvdyAncmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCBtdXN0IGJlIGEgYm9vbGVhbiB2YWx1ZSc7XG4gICAgfVxuXG4gICAgaWYgKHB1YmxpY1NlcnZlclVSTCkge1xuICAgICAgaWYgKFxuICAgICAgICAhcHVibGljU2VydmVyVVJMLnN0YXJ0c1dpdGgoJ2h0dHA6Ly8nKSAmJlxuICAgICAgICAhcHVibGljU2VydmVyVVJMLnN0YXJ0c1dpdGgoJ2h0dHBzOi8vJylcbiAgICAgICkge1xuICAgICAgICB0aHJvdyAncHVibGljU2VydmVyVVJMIHNob3VsZCBiZSBhIHZhbGlkIEhUVFBTIFVSTCBzdGFydGluZyB3aXRoIGh0dHBzOi8vJztcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlU2Vzc2lvbkNvbmZpZ3VyYXRpb24oc2Vzc2lvbkxlbmd0aCwgZXhwaXJlSW5hY3RpdmVTZXNzaW9ucyk7XG5cbiAgICB0aGlzLnZhbGlkYXRlTWFzdGVyS2V5SXBzKG1hc3RlcktleUlwcyk7XG5cbiAgICB0aGlzLnZhbGlkYXRlTWF4TGltaXQobWF4TGltaXQpO1xuXG4gICAgdGhpcy52YWxpZGF0ZUFsbG93SGVhZGVycyhhbGxvd0hlYWRlcnMpO1xuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlQWNjb3VudExvY2tvdXRQb2xpY3koYWNjb3VudExvY2tvdXQpIHtcbiAgICBpZiAoYWNjb3VudExvY2tvdXQpIHtcbiAgICAgIGlmIChcbiAgICAgICAgdHlwZW9mIGFjY291bnRMb2Nrb3V0LmR1cmF0aW9uICE9PSAnbnVtYmVyJyB8fFxuICAgICAgICBhY2NvdW50TG9ja291dC5kdXJhdGlvbiA8PSAwIHx8XG4gICAgICAgIGFjY291bnRMb2Nrb3V0LmR1cmF0aW9uID4gOTk5OTlcbiAgICAgICkge1xuICAgICAgICB0aHJvdyAnQWNjb3VudCBsb2Nrb3V0IGR1cmF0aW9uIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gMCBhbmQgbGVzcyB0aGFuIDEwMDAwMCc7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgIU51bWJlci5pc0ludGVnZXIoYWNjb3VudExvY2tvdXQudGhyZXNob2xkKSB8fFxuICAgICAgICBhY2NvdW50TG9ja291dC50aHJlc2hvbGQgPCAxIHx8XG4gICAgICAgIGFjY291bnRMb2Nrb3V0LnRocmVzaG9sZCA+IDk5OVxuICAgICAgKSB7XG4gICAgICAgIHRocm93ICdBY2NvdW50IGxvY2tvdXQgdGhyZXNob2xkIHNob3VsZCBiZSBhbiBpbnRlZ2VyIGdyZWF0ZXIgdGhhbiAwIGFuZCBsZXNzIHRoYW4gMTAwMCc7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlUGFzc3dvcmRQb2xpY3kocGFzc3dvcmRQb2xpY3kpIHtcbiAgICBpZiAocGFzc3dvcmRQb2xpY3kpIHtcbiAgICAgIGlmIChcbiAgICAgICAgcGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRBZ2UgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAodHlwZW9mIHBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlICE9PSAnbnVtYmVyJyB8fFxuICAgICAgICAgIHBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlIDwgMClcbiAgICAgICkge1xuICAgICAgICB0aHJvdyAncGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRBZ2UgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcic7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgcGFzc3dvcmRQb2xpY3kucmVzZXRUb2tlblZhbGlkaXR5RHVyYXRpb24gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAodHlwZW9mIHBhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uICE9PSAnbnVtYmVyJyB8fFxuICAgICAgICAgIHBhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uIDw9IDApXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgJ3Bhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVybikge1xuICAgICAgICBpZiAodHlwZW9mIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVybiA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICBwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICghKHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4gaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICAgICAgdGhyb3cgJ3Bhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4gbXVzdCBiZSBhIHJlZ2V4IHN0cmluZyBvciBSZWdFeHAgb2JqZWN0Lic7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBwYXNzd29yZFBvbGljeS52YWxpZGF0b3JDYWxsYmFjayAmJlxuICAgICAgICB0eXBlb2YgcGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yQ2FsbGJhY2sgIT09ICdmdW5jdGlvbidcbiAgICAgICkge1xuICAgICAgICB0aHJvdyAncGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yQ2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uLic7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgcGFzc3dvcmRQb2xpY3kuZG9Ob3RBbGxvd1VzZXJuYW1lICYmXG4gICAgICAgIHR5cGVvZiBwYXNzd29yZFBvbGljeS5kb05vdEFsbG93VXNlcm5hbWUgIT09ICdib29sZWFuJ1xuICAgICAgKSB7XG4gICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS5kb05vdEFsbG93VXNlcm5hbWUgbXVzdCBiZSBhIGJvb2xlYW4gdmFsdWUuJztcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgJiZcbiAgICAgICAgKCFOdW1iZXIuaXNJbnRlZ2VyKHBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeSkgfHxcbiAgICAgICAgICBwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgPD0gMCB8fFxuICAgICAgICAgIHBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeSA+IDIwKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgbXVzdCBiZSBhbiBpbnRlZ2VyIHJhbmdpbmcgMCAtIDIwJztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBpZiB0aGUgcGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVybiBpcyBjb25maWd1cmVkIHRoZW4gc2V0dXAgYSBjYWxsYmFjayB0byBwcm9jZXNzIHRoZSBwYXR0ZXJuXG4gIHN0YXRpYyBzZXR1cFBhc3N3b3JkVmFsaWRhdG9yKHBhc3N3b3JkUG9saWN5KSB7XG4gICAgaWYgKHBhc3N3b3JkUG9saWN5ICYmIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4pIHtcbiAgICAgIHBhc3N3b3JkUG9saWN5LnBhdHRlcm5WYWxpZGF0b3IgPSB2YWx1ZSA9PiB7XG4gICAgICAgIHJldHVybiBwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuLnRlc3QodmFsdWUpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVFbWFpbENvbmZpZ3VyYXRpb24oe1xuICAgIGVtYWlsQWRhcHRlcixcbiAgICBhcHBOYW1lLFxuICAgIHB1YmxpY1NlcnZlclVSTCxcbiAgICBlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbixcbiAgfSkge1xuICAgIGlmICghZW1haWxBZGFwdGVyKSB7XG4gICAgICB0aHJvdyAnQW4gZW1haWxBZGFwdGVyIGlzIHJlcXVpcmVkIGZvciBlLW1haWwgdmVyaWZpY2F0aW9uIGFuZCBwYXNzd29yZCByZXNldHMuJztcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBhcHBOYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgJ0FuIGFwcCBuYW1lIGlzIHJlcXVpcmVkIGZvciBlLW1haWwgdmVyaWZpY2F0aW9uIGFuZCBwYXNzd29yZCByZXNldHMuJztcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBwdWJsaWNTZXJ2ZXJVUkwgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyAnQSBwdWJsaWMgc2VydmVyIHVybCBpcyByZXF1aXJlZCBmb3IgZS1tYWlsIHZlcmlmaWNhdGlvbiBhbmQgcGFzc3dvcmQgcmVzZXRzLic7XG4gICAgfVxuICAgIGlmIChlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbikge1xuICAgICAgaWYgKGlzTmFOKGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uKSkge1xuICAgICAgICB0aHJvdyAnRW1haWwgdmVyaWZ5IHRva2VuIHZhbGlkaXR5IGR1cmF0aW9uIG11c3QgYmUgYSB2YWxpZCBudW1iZXIuJztcbiAgICAgIH0gZWxzZSBpZiAoZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24gPD0gMCkge1xuICAgICAgICB0aHJvdyAnRW1haWwgdmVyaWZ5IHRva2VuIHZhbGlkaXR5IGR1cmF0aW9uIG11c3QgYmUgYSB2YWx1ZSBncmVhdGVyIHRoYW4gMC4nO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZU1hc3RlcktleUlwcyhtYXN0ZXJLZXlJcHMpIHtcbiAgICBmb3IgKGNvbnN0IGlwIG9mIG1hc3RlcktleUlwcykge1xuICAgICAgaWYgKCFuZXQuaXNJUChpcCkpIHtcbiAgICAgICAgdGhyb3cgYEludmFsaWQgaXAgaW4gbWFzdGVyS2V5SXBzOiAke2lwfWA7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZ2V0IG1vdW50KCkge1xuICAgIHZhciBtb3VudCA9IHRoaXMuX21vdW50O1xuICAgIGlmICh0aGlzLnB1YmxpY1NlcnZlclVSTCkge1xuICAgICAgbW91bnQgPSB0aGlzLnB1YmxpY1NlcnZlclVSTDtcbiAgICB9XG4gICAgcmV0dXJuIG1vdW50O1xuICB9XG5cbiAgc2V0IG1vdW50KG5ld1ZhbHVlKSB7XG4gICAgdGhpcy5fbW91bnQgPSBuZXdWYWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZVNlc3Npb25Db25maWd1cmF0aW9uKHNlc3Npb25MZW5ndGgsIGV4cGlyZUluYWN0aXZlU2Vzc2lvbnMpIHtcbiAgICBpZiAoZXhwaXJlSW5hY3RpdmVTZXNzaW9ucykge1xuICAgICAgaWYgKGlzTmFOKHNlc3Npb25MZW5ndGgpKSB7XG4gICAgICAgIHRocm93ICdTZXNzaW9uIGxlbmd0aCBtdXN0IGJlIGEgdmFsaWQgbnVtYmVyLic7XG4gICAgICB9IGVsc2UgaWYgKHNlc3Npb25MZW5ndGggPD0gMCkge1xuICAgICAgICB0aHJvdyAnU2Vzc2lvbiBsZW5ndGggbXVzdCBiZSBhIHZhbHVlIGdyZWF0ZXIgdGhhbiAwLic7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlTWF4TGltaXQobWF4TGltaXQpIHtcbiAgICBpZiAobWF4TGltaXQgPD0gMCkge1xuICAgICAgdGhyb3cgJ01heCBsaW1pdCBtdXN0IGJlIGEgdmFsdWUgZ3JlYXRlciB0aGFuIDAuJztcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVBbGxvd0hlYWRlcnMoYWxsb3dIZWFkZXJzKSB7XG4gICAgaWYgKCFbbnVsbCwgdW5kZWZpbmVkXS5pbmNsdWRlcyhhbGxvd0hlYWRlcnMpKSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShhbGxvd0hlYWRlcnMpKSB7XG4gICAgICAgIGFsbG93SGVhZGVycy5mb3JFYWNoKGhlYWRlciA9PiB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aHJvdyAnQWxsb3cgaGVhZGVycyBtdXN0IG9ubHkgY29udGFpbiBzdHJpbmdzJztcbiAgICAgICAgICB9IGVsc2UgaWYgKCFoZWFkZXIudHJpbSgpLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgJ0FsbG93IGhlYWRlcnMgbXVzdCBub3QgY29udGFpbiBlbXB0eSBzdHJpbmdzJztcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgJ0FsbG93IGhlYWRlcnMgbXVzdCBiZSBhbiBhcnJheSc7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuRXhwaXJlc0F0KCkge1xuICAgIGlmICghdGhpcy52ZXJpZnlVc2VyRW1haWxzIHx8ICF0aGlzLmVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB2YXIgbm93ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gbmV3IERhdGUoXG4gICAgICBub3cuZ2V0VGltZSgpICsgdGhpcy5lbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbiAqIDEwMDBcbiAgICApO1xuICB9XG5cbiAgZ2VuZXJhdGVQYXNzd29yZFJlc2V0VG9rZW5FeHBpcmVzQXQoKSB7XG4gICAgaWYgKFxuICAgICAgIXRoaXMucGFzc3dvcmRQb2xpY3kgfHxcbiAgICAgICF0aGlzLnBhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uXG4gICAgKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIHJldHVybiBuZXcgRGF0ZShcbiAgICAgIG5vdy5nZXRUaW1lKCkgKyB0aGlzLnBhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uICogMTAwMFxuICAgICk7XG4gIH1cblxuICBnZW5lcmF0ZVNlc3Npb25FeHBpcmVzQXQoKSB7XG4gICAgaWYgKCF0aGlzLmV4cGlyZUluYWN0aXZlU2Vzc2lvbnMpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIHJldHVybiBuZXcgRGF0ZShub3cuZ2V0VGltZSgpICsgdGhpcy5zZXNzaW9uTGVuZ3RoICogMTAwMCk7XG4gIH1cblxuICBnZXQgaW52YWxpZExpbmtVUkwoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY3VzdG9tUGFnZXMuaW52YWxpZExpbmsgfHxcbiAgICAgIGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzL2ludmFsaWRfbGluay5odG1sYFxuICAgICk7XG4gIH1cblxuICBnZXQgaW52YWxpZFZlcmlmaWNhdGlvbkxpbmtVUkwoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY3VzdG9tUGFnZXMuaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsgfHxcbiAgICAgIGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzL2ludmFsaWRfdmVyaWZpY2F0aW9uX2xpbmsuaHRtbGBcbiAgICApO1xuICB9XG5cbiAgZ2V0IGxpbmtTZW5kU3VjY2Vzc1VSTCgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5jdXN0b21QYWdlcy5saW5rU2VuZFN1Y2Nlc3MgfHxcbiAgICAgIGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzL2xpbmtfc2VuZF9zdWNjZXNzLmh0bWxgXG4gICAgKTtcbiAgfVxuXG4gIGdldCBsaW5rU2VuZEZhaWxVUkwoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY3VzdG9tUGFnZXMubGlua1NlbmRGYWlsIHx8XG4gICAgICBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9saW5rX3NlbmRfZmFpbC5odG1sYFxuICAgICk7XG4gIH1cblxuICBnZXQgdmVyaWZ5RW1haWxTdWNjZXNzVVJMKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmN1c3RvbVBhZ2VzLnZlcmlmeUVtYWlsU3VjY2VzcyB8fFxuICAgICAgYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvdmVyaWZ5X2VtYWlsX3N1Y2Nlc3MuaHRtbGBcbiAgICApO1xuICB9XG5cbiAgZ2V0IGNob29zZVBhc3N3b3JkVVJMKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmN1c3RvbVBhZ2VzLmNob29zZVBhc3N3b3JkIHx8XG4gICAgICBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9jaG9vc2VfcGFzc3dvcmRgXG4gICAgKTtcbiAgfVxuXG4gIGdldCByZXF1ZXN0UmVzZXRQYXNzd29yZFVSTCgpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvJHt0aGlzLmFwcGxpY2F0aW9uSWR9L3JlcXVlc3RfcGFzc3dvcmRfcmVzZXRgO1xuICB9XG5cbiAgZ2V0IHBhc3N3b3JkUmVzZXRTdWNjZXNzVVJMKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmN1c3RvbVBhZ2VzLnBhc3N3b3JkUmVzZXRTdWNjZXNzIHx8XG4gICAgICBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9wYXNzd29yZF9yZXNldF9zdWNjZXNzLmh0bWxgXG4gICAgKTtcbiAgfVxuXG4gIGdldCBwYXJzZUZyYW1lVVJMKCkge1xuICAgIHJldHVybiB0aGlzLmN1c3RvbVBhZ2VzLnBhcnNlRnJhbWVVUkw7XG4gIH1cblxuICBnZXQgdmVyaWZ5RW1haWxVUkwoKSB7XG4gICAgcmV0dXJuIGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzLyR7dGhpcy5hcHBsaWNhdGlvbklkfS92ZXJpZnlfZW1haWxgO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IENvbmZpZztcbm1vZHVsZS5leHBvcnRzID0gQ29uZmlnO1xuIl19 \ 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..c8a854316a --- /dev/null +++ b/lib/Controllers/DatabaseController.js @@ -0,0 +1,1450 @@ +"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 => { + 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(validateQuery); + } 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(validateQuery); + } 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(validateQuery); + } 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 at least one pointer-permission affected the current user + // intersect vs protectedFields from previous stage (@see addProtectedFields) + // Sets theory (intersections): A x (B x C) == (A x B) x C + + if (overrideProtectedFields && protectedFields) { + newProtectedFields.push(protectedFields); + } // intersect all sets of protectedFields + + + newProtectedFields.forEach(fields => { + if (fields) { + // if there're no protctedFields by other criteria ( id / role / auth) + // then we must intersect each set (per userField) + if (!protectedFields) { + protectedFields = fields; + } else { + protectedFields = protectedFields.filter(v => fields.includes(v)); + } + } + }); + } + } + + 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]); // fields not requested by client (excluded), + //but were needed to apply protecttedFields + + perms.protectedFields && perms.protectedFields.temporaryKeys && perms.protectedFields.temporaryKeys.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) { + 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._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, runOptions) { + let schema; + const acl = runOptions.acl; + 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, runOptions); + }).then(() => { + return schema.validateObject(className, object, query); + }); + } + + update(className, query, update, { + acl, + many, + upsert, + addsField + } = {}, 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 (addsField) { + query = { + $and: [query, this.addPointerPermissions(schemaController, className, 'addField', query, aclGroup)] + }; + } + } + + if (!query) { + return Promise.resolve(); + } + + if (acl) { + query = addWriteACL(query, acl); + } + + validateQuery(query); + 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); + 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, runOptions) { + 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) { + // adds a marker that new field is being adding during update + runOptions.addsField = true; + const action = runOptions.action; + return schema.validatePermission(className, aclGroup, 'addField', action); + } + + 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. + // caseInsensitive make string comparisons case insensitive + // 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, + hint, + caseInsensitive = false, + explain + } = {}, 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, + hint, + caseInsensitive, + explain + }; + 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, queryOptions); + } + + 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); + + if (count) { + if (!classExists) { + return 0; + } else { + return this.adapter.count(className, schema, query, readPreference, undefined, hint); + } + } 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, hint, explain); + } + } else if (explain) { + return this.adapter.find(className, schema, query, queryOptions); + } 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(); + } + }); + }); + } // Constraints query using CLP's pointer permissions (PP) if any. + // 1. Etract the user id from caller's ACLgroup; + // 2. Exctract a list of field names that are PP for target collection and operation; + // 3. Constraint the original query so that each PP field must + // point to caller's id (or contain it in case of PP field being an array) + + + 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 userACL = aclGroup.filter(acl => { + return acl.indexOf('role:') != 0 && acl != '*'; + }); + const groupKey = ['get', 'find', 'count'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields'; + const permFields = []; + + if (perms[operation] && perms[operation].pointerFields) { + permFields.push(...perms[operation].pointerFields); + } + + if (perms[groupKey]) { + for (const field of perms[groupKey]) { + if (!permFields.includes(field)) { + permFields.push(field); + } + } + } // the ACL should have exactly 1 user + + + if (permFields.length > 0) { + // the ACL should have exactly 1 user + // 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 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 = {}, queryOptions = {}) { + 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; // for queries where "keys" are set and do not include all 'userField':{field}, + // we have to transparently include it, and then remove before returning to client + // Because if such key not projected the permission won't be enforced properly + // PS this is called when 'excludeKeys' already reduced to 'keys' + + const preserveKeys = queryOptions.keys; // these are keys that need to be included only + // to be able to apply protectedFields by pointer + // and then unset before returning to client (later in filterSensitiveFields) + + const serverOnlyKeys = []; + const authenticated = auth.user; // map to allow check without array search + + const roles = (auth.userRoles || []).reduce((acc, r) => { + acc[r] = protectedFields[r]; + return acc; + }, {}); // array of sets of protected fields. separate item for each applicable criteria + + const protectedKeysSets = []; + + for (const key in protectedFields) { + // skip userFields + if (key.startsWith('userField:')) { + if (preserveKeys) { + const fieldName = key.substring(10); + + if (!preserveKeys.includes(fieldName)) { + // 1. put it there temporarily + queryOptions.keys && queryOptions.keys.push(fieldName); // 2. preserve it delete later + + serverOnlyKeys.push(fieldName); + } + } + + continue; + } // add public tier + + + if (key === '*') { + protectedKeysSets.push(protectedFields[key]); + continue; + } + + if (authenticated) { + if (key === 'authenticated') { + // for logged in users + protectedKeysSets.push(protectedFields[key]); + continue; + } + + if (roles[key] && key.startsWith('role:')) { + // add applicable roles + protectedKeysSets.push(roles[key]); + } + } + } // check if there's a rule for current user's id + + + if (authenticated) { + const userId = auth.user.id; + + if (perms.protectedFields[userId]) { + protectedKeysSets.push(perms.protectedFields[userId]); + } + } // preserve fields to be removed before sending response to client + + + if (serverOnlyKeys.length > 0) { + perms.protectedFields.temporaryKeys = serverOnlyKeys; + } + + let protectedKeys = protectedKeysSets.reduce((acc, next) => { + if (next) { + acc.push(...next); + } + + return acc; + }, []); // intersect all sets of protectedFields + + protectedKeysSets.forEach(fields => { + 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 usernameCaseInsensitiveIndex = userClassPromise.then(() => this.adapter.ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)).catch(error => { + _logger.default.warn('Unable to create case insensitive username index: ', 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 emailCaseInsensitiveIndex = userClassPromise.then(() => this.adapter.ensureIndex('_User', requiredUserFields, ['email'], 'case_insensitive_email', true)).catch(error => { + _logger.default.warn('Unable to create case insensitive email index: ', 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, usernameCaseInsensitiveIndex, emailUniqueness, emailCaseInsensitiveIndex, roleUniqueness, adapterInit, indexPromise]); + } + +} + +module.exports = DatabaseController; // Expose validateQuery for tests + +module.exports._validateQuery = validateQuery; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiYWRkV3JpdGVBQ0wiLCJxdWVyeSIsImFjbCIsIm5ld1F1ZXJ5IiwiXyIsImNsb25lRGVlcCIsIl93cGVybSIsIiRpbiIsImFkZFJlYWRBQ0wiLCJfcnBlcm0iLCJ0cmFuc2Zvcm1PYmplY3RBQ0wiLCJBQ0wiLCJyZXN1bHQiLCJlbnRyeSIsInJlYWQiLCJwdXNoIiwid3JpdGUiLCJzcGVjaWFsUXVlcnlrZXlzIiwiaXNTcGVjaWFsUXVlcnlLZXkiLCJrZXkiLCJpbmRleE9mIiwidmFsaWRhdGVRdWVyeSIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1FVRVJZIiwiJG9yIiwiQXJyYXkiLCJmb3JFYWNoIiwiJGFuZCIsIiRub3IiLCJsZW5ndGgiLCJPYmplY3QiLCJrZXlzIiwiJHJlZ2V4IiwiJG9wdGlvbnMiLCJtYXRjaCIsIklOVkFMSURfS0VZX05BTUUiLCJmaWx0ZXJTZW5zaXRpdmVEYXRhIiwiaXNNYXN0ZXIiLCJhY2xHcm91cCIsImF1dGgiLCJvcGVyYXRpb24iLCJzY2hlbWEiLCJjbGFzc05hbWUiLCJwcm90ZWN0ZWRGaWVsZHMiLCJvYmplY3QiLCJ1c2VySWQiLCJ1c2VyIiwiaWQiLCJwZXJtcyIsImdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsImlzUmVhZE9wZXJhdGlvbiIsInByb3RlY3RlZEZpZWxkc1BvaW50ZXJQZXJtIiwiZmlsdGVyIiwic3RhcnRzV2l0aCIsIm1hcCIsInN1YnN0cmluZyIsInZhbHVlIiwibmV3UHJvdGVjdGVkRmllbGRzIiwib3ZlcnJpZGVQcm90ZWN0ZWRGaWVsZHMiLCJwb2ludGVyUGVybSIsInBvaW50ZXJQZXJtSW5jbHVkZXNVc2VyIiwicmVhZFVzZXJGaWVsZFZhbHVlIiwiaXNBcnJheSIsInNvbWUiLCJvYmplY3RJZCIsImZpZWxkcyIsInYiLCJpbmNsdWRlcyIsImlzVXNlckNsYXNzIiwiayIsInRlbXBvcmFyeUtleXMiLCJwYXNzd29yZCIsIl9oYXNoZWRfcGFzc3dvcmQiLCJzZXNzaW9uVG9rZW4iLCJfZW1haWxfdmVyaWZ5X3Rva2VuIiwiX3BlcmlzaGFibGVfdG9rZW4iLCJfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0IiwiX3RvbWJzdG9uZSIsIl9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCIsIl9mYWlsZWRfbG9naW5fY291bnQiLCJfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQiLCJfcGFzc3dvcmRfY2hhbmdlZF9hdCIsIl9wYXNzd29yZF9oaXN0b3J5IiwiYXV0aERhdGEiLCJzcGVjaWFsS2V5c0ZvclVwZGF0ZSIsImlzU3BlY2lhbFVwZGF0ZUtleSIsImV4cGFuZFJlc3VsdE9uS2V5UGF0aCIsInBhdGgiLCJzcGxpdCIsImZpcnN0S2V5IiwibmV4dFBhdGgiLCJzbGljZSIsImpvaW4iLCJzYW5pdGl6ZURhdGFiYXNlUmVzdWx0Iiwib3JpZ2luYWxPYmplY3QiLCJyZXNwb25zZSIsIlByb21pc2UiLCJyZXNvbHZlIiwia2V5VXBkYXRlIiwiX19vcCIsImpvaW5UYWJsZU5hbWUiLCJmbGF0dGVuVXBkYXRlT3BlcmF0b3JzRm9yQ3JlYXRlIiwiYW1vdW50IiwiSU5WQUxJRF9KU09OIiwib2JqZWN0cyIsIkNPTU1BTkRfVU5BVkFJTEFCTEUiLCJ0cmFuc2Zvcm1BdXRoRGF0YSIsInByb3ZpZGVyIiwicHJvdmlkZXJEYXRhIiwiZmllbGROYW1lIiwidHlwZSIsInVudHJhbnNmb3JtT2JqZWN0QUNMIiwib3V0cHV0IiwiZ2V0Um9vdEZpZWxkTmFtZSIsInJlbGF0aW9uU2NoZW1hIiwicmVsYXRlZElkIiwib3duaW5nSWQiLCJEYXRhYmFzZUNvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImFkYXB0ZXIiLCJzY2hlbWFDYWNoZSIsInNjaGVtYVByb21pc2UiLCJfdHJhbnNhY3Rpb25hbFNlc3Npb24iLCJjb2xsZWN0aW9uRXhpc3RzIiwiY2xhc3NFeGlzdHMiLCJwdXJnZUNvbGxlY3Rpb24iLCJsb2FkU2NoZW1hIiwidGhlbiIsInNjaGVtYUNvbnRyb2xsZXIiLCJnZXRPbmVTY2hlbWEiLCJkZWxldGVPYmplY3RzQnlRdWVyeSIsInZhbGlkYXRlQ2xhc3NOYW1lIiwiU2NoZW1hQ29udHJvbGxlciIsImNsYXNzTmFtZUlzVmFsaWQiLCJyZWplY3QiLCJJTlZBTElEX0NMQVNTX05BTUUiLCJvcHRpb25zIiwiY2xlYXJDYWNoZSIsImxvYWQiLCJsb2FkU2NoZW1hSWZOZWVkZWQiLCJyZWRpcmVjdENsYXNzTmFtZUZvcktleSIsInQiLCJnZXRFeHBlY3RlZFR5cGUiLCJ0YXJnZXRDbGFzcyIsInZhbGlkYXRlT2JqZWN0IiwicnVuT3B0aW9ucyIsInVuZGVmaW5lZCIsInMiLCJjYW5BZGRGaWVsZCIsInVwZGF0ZSIsIm1hbnkiLCJ1cHNlcnQiLCJhZGRzRmllbGQiLCJza2lwU2FuaXRpemF0aW9uIiwidmFsaWRhdGVPbmx5IiwidmFsaWRTY2hlbWFDb250cm9sbGVyIiwib3JpZ2luYWxRdWVyeSIsIm9yaWdpbmFsVXBkYXRlIiwicmVsYXRpb25VcGRhdGVzIiwidmFsaWRhdGVQZXJtaXNzaW9uIiwiY29sbGVjdFJlbGF0aW9uVXBkYXRlcyIsImFkZFBvaW50ZXJQZXJtaXNzaW9ucyIsImNhdGNoIiwiZXJyb3IiLCJyb290RmllbGROYW1lIiwiZmllbGROYW1lSXNWYWxpZCIsInVwZGF0ZU9wZXJhdGlvbiIsImlubmVyS2V5IiwiSU5WQUxJRF9ORVNURURfS0VZIiwiZmluZCIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ1cGRhdGVPYmplY3RzQnlRdWVyeSIsInVwc2VydE9uZU9iamVjdCIsImZpbmRPbmVBbmRVcGRhdGUiLCJoYW5kbGVSZWxhdGlvblVwZGF0ZXMiLCJvcHMiLCJkZWxldGVNZSIsInByb2Nlc3MiLCJvcCIsIngiLCJwZW5kaW5nIiwiYWRkUmVsYXRpb24iLCJyZW1vdmVSZWxhdGlvbiIsImFsbCIsImZyb21DbGFzc05hbWUiLCJmcm9tSWQiLCJ0b0lkIiwiZG9jIiwiY29kZSIsImRlc3Ryb3kiLCJwYXJzZUZvcm1hdFNjaGVtYSIsImNyZWF0ZSIsImNyZWF0ZWRBdCIsImlzbyIsIl9fdHlwZSIsInVwZGF0ZWRBdCIsImVuZm9yY2VDbGFzc0V4aXN0cyIsImNyZWF0ZU9iamVjdCIsImNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEiLCJjbGFzc1NjaGVtYSIsInNjaGVtYURhdGEiLCJzY2hlbWFGaWVsZHMiLCJuZXdLZXlzIiwiZmllbGQiLCJhY3Rpb24iLCJkZWxldGVFdmVyeXRoaW5nIiwiZmFzdCIsImRlbGV0ZUFsbENsYXNzZXMiLCJjbGVhciIsInJlbGF0ZWRJZHMiLCJxdWVyeU9wdGlvbnMiLCJza2lwIiwibGltaXQiLCJzb3J0IiwiZmluZE9wdGlvbnMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiX2lkIiwicmVzdWx0cyIsIm93bmluZ0lkcyIsInJlZHVjZUluUmVsYXRpb24iLCJvcnMiLCJhUXVlcnkiLCJpbmRleCIsInByb21pc2VzIiwicXVlcmllcyIsImNvbnN0cmFpbnRLZXkiLCJpc05lZ2F0aW9uIiwiciIsInEiLCJpZHMiLCJhZGROb3RJbk9iamVjdElkc0lkcyIsImFkZEluT2JqZWN0SWRzSWRzIiwicmVkdWNlUmVsYXRpb25LZXlzIiwicmVsYXRlZFRvIiwiaWRzRnJvbVN0cmluZyIsImlkc0Zyb21FcSIsImlkc0Zyb21JbiIsImFsbElkcyIsImxpc3QiLCJ0b3RhbExlbmd0aCIsInJlZHVjZSIsIm1lbW8iLCJpZHNJbnRlcnNlY3Rpb24iLCJpbnRlcnNlY3QiLCJiaWciLCIkZXEiLCJpZHNGcm9tTmluIiwiU2V0IiwiJG5pbiIsImNvdW50IiwiZGlzdGluY3QiLCJwaXBlbGluZSIsInJlYWRQcmVmZXJlbmNlIiwiaGludCIsImNhc2VJbnNlbnNpdGl2ZSIsImV4cGxhaW4iLCJfY3JlYXRlZF9hdCIsIl91cGRhdGVkX2F0IiwiYWRkUHJvdGVjdGVkRmllbGRzIiwiYWdncmVnYXRlIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiZGVsZXRlU2NoZW1hIiwiZGVsZXRlQ2xhc3MiLCJ3YXNQYXJzZUNvbGxlY3Rpb24iLCJyZWxhdGlvbkZpZWxkTmFtZXMiLCJuYW1lIiwidGVzdFBlcm1pc3Npb25zRm9yQ2xhc3NOYW1lIiwidXNlckFDTCIsImdyb3VwS2V5IiwicGVybUZpZWxkcyIsInBvaW50ZXJGaWVsZHMiLCJ1c2VyUG9pbnRlciIsImZsYXRNYXAiLCJxYSIsIiRhbGwiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJhc3NpZ24iLCJwcmVzZXJ2ZUtleXMiLCJzZXJ2ZXJPbmx5S2V5cyIsImF1dGhlbnRpY2F0ZWQiLCJyb2xlcyIsInVzZXJSb2xlcyIsImFjYyIsInByb3RlY3RlZEtleXNTZXRzIiwicHJvdGVjdGVkS2V5cyIsIm5leHQiLCJjcmVhdGVUcmFuc2FjdGlvbmFsU2Vzc2lvbiIsInRyYW5zYWN0aW9uYWxTZXNzaW9uIiwiY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24iLCJhYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uIiwicGVyZm9ybUluaXRpYWxpemF0aW9uIiwicmVxdWlyZWRVc2VyRmllbGRzIiwiZGVmYXVsdENvbHVtbnMiLCJfRGVmYXVsdCIsIl9Vc2VyIiwicmVxdWlyZWRSb2xlRmllbGRzIiwiX1JvbGUiLCJ1c2VyQ2xhc3NQcm9taXNlIiwicm9sZUNsYXNzUHJvbWlzZSIsInVzZXJuYW1lVW5pcXVlbmVzcyIsImVuc3VyZVVuaXF1ZW5lc3MiLCJsb2dnZXIiLCJ3YXJuIiwidXNlcm5hbWVDYXNlSW5zZW5zaXRpdmVJbmRleCIsImVuc3VyZUluZGV4IiwiZW1haWxVbmlxdWVuZXNzIiwiZW1haWxDYXNlSW5zZW5zaXRpdmVJbmRleCIsInJvbGVVbmlxdWVuZXNzIiwiaW5kZXhQcm9taXNlIiwidXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMiLCJhZGFwdGVySW5pdCIsIlZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMiLCJtb2R1bGUiLCJleHBvcnRzIiwiX3ZhbGlkYXRlUXVlcnkiXSwibWFwcGluZ3MiOiI7O0FBS0E7O0FBRUE7O0FB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QVBvQixDQUF2QjtBQVNBLFVBQU1tSixZQUFZLEdBQUcsS0FBSy9MLE9BQUwsQ0FBYWdNLHVCQUFiLEVBQXJCLENBcEZzQixDQXNGdEI7O0FBQ0EsVUFBTUMsV0FBVyxHQUFHLEtBQUtqTSxPQUFMLENBQWE2SyxxQkFBYixDQUFtQztBQUNyRHFCLE1BQUFBLHNCQUFzQixFQUFFckwsZ0JBQWdCLENBQUNxTDtBQURZLEtBQW5DLENBQXBCO0FBR0EsV0FBT3pOLE9BQU8sQ0FBQ3VGLEdBQVIsQ0FBWSxDQUNqQnNILGtCQURpQixFQUVqQkksNEJBRmlCLEVBR2pCRSxlQUhpQixFQUlqQkMseUJBSmlCLEVBS2pCQyxjQUxpQixFQU1qQkcsV0FOaUIsRUFPakJGLFlBUGlCLENBQVosQ0FBUDtBQVNEOztBQTEzQ3NCOztBQSszQ3pCSSxNQUFNLENBQUNDLE9BQVAsR0FBaUJ0TSxrQkFBakIsQyxDQUNBOztBQUNBcU0sTUFBTSxDQUFDQyxPQUFQLENBQWVDLGNBQWYsR0FBZ0N4UyxhQUFoQyIsInNvdXJjZXNDb250ZW50IjpbIu+7vy8vIEBmbG93XG4vLyBBIGRhdGFiYXNlIGFkYXB0ZXIgdGhhdCB3b3JrcyB3aXRoIGRhdGEgZXhwb3J0ZWQgZnJvbSB0aGUgaG9zdGVkXG4vLyBQYXJzZSBkYXRhYmFzZS5cblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgeyBQYXJzZSB9IGZyb20gJ3BhcnNlL25vZGUnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgaW50ZXJzZWN0IGZyb20gJ2ludGVyc2VjdCc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBkZWVwY29weSBmcm9tICdkZWVwY29weSc7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgKiBhcyBTY2hlbWFDb250cm9sbGVyIGZyb20gJy4vU2NoZW1hQ29udHJvbGxlcic7XG5pbXBvcnQgeyBTdG9yYWdlQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL1N0b3JhZ2UvU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHR5cGUge1xuICBRdWVyeU9wdGlvbnMsXG4gIEZ1bGxRdWVyeU9wdGlvbnMsXG59IGZyb20gJy4uL0FkYXB0ZXJzL1N0b3JhZ2UvU3RvcmFnZUFkYXB0ZXInO1xuXG5mdW5jdGlvbiBhZGRXcml0ZUFDTChxdWVyeSwgYWNsKSB7XG4gIGNvbnN0IG5ld1F1ZXJ5ID0gXy5jbG9uZURlZXAocXVlcnkpO1xuICAvL0Nhbid0IGJlIGFueSBleGlzdGluZyAnX3dwZXJtJyBxdWVyeSwgd2UgZG9uJ3QgYWxsb3cgY2xpZW50IHF1ZXJpZXMgb24gdGhhdCwgbm8gbmVlZCB0byAkYW5kXG4gIG5ld1F1ZXJ5Ll93cGVybSA9IHsgJGluOiBbbnVsbCwgLi4uYWNsXSB9O1xuICByZXR1cm4gbmV3UXVlcnk7XG59XG5cbmZ1bmN0aW9uIGFkZFJlYWRBQ0wocXVlcnksIGFjbCkge1xuICBjb25zdCBuZXdRdWVyeSA9IF8uY2xvbmVEZWVwKHF1ZXJ5KTtcbiAgLy9DYW4ndCBiZSBhbnkgZXhpc3RpbmcgJ19ycGVybScgcXVlcnksIHdlIGRvbid0IGFsbG93IGNsaWVudCBxdWVyaWVzIG9uIHRoYXQsIG5vIG5lZWQgdG8gJGFuZFxuICBuZXdRdWVyeS5fcnBlcm0gPSB7ICRpbjogW251bGwsICcqJywgLi4uYWNsXSB9O1xuICByZXR1cm4gbmV3UXVlcnk7XG59XG5cbi8vIFRyYW5zZm9ybXMgYSBSRVNUIEFQSSBmb3JtYXR0ZWQgQUNMIG9iamVjdCB0byBvdXIgdHdvLWZpZWxkIG1vbmdvIGZvcm1hdC5cbmNvbnN0IHRyYW5zZm9ybU9iamVjdEFDTCA9ICh7IEFDTCwgLi4ucmVzdWx0IH0pID0+IHtcbiAgaWYgKCFBQ0wpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcmVzdWx0Ll93cGVybSA9IFtdO1xuICByZXN1bHQuX3JwZXJtID0gW107XG5cbiAgZm9yIChjb25zdCBlbnRyeSBpbiBBQ0wpIHtcbiAgICBpZiAoQUNMW2VudHJ5XS5yZWFkKSB7XG4gICAgICByZXN1bHQuX3JwZXJtLnB1c2goZW50cnkpO1xuICAgIH1cbiAgICBpZiAoQUNMW2VudHJ5XS53cml0ZSkge1xuICAgICAgcmVzdWx0Ll93cGVybS5wdXNoKGVudHJ5KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbmNvbnN0IHNwZWNpYWxRdWVyeWtleXMgPSBbXG4gICckYW5kJyxcbiAgJyRvcicsXG4gICckbm9yJyxcbiAgJ19ycGVybScsXG4gICdfd3Blcm0nLFxuICAnX3BlcmlzaGFibGVfdG9rZW4nLFxuICAnX2VtYWlsX3ZlcmlmeV90b2tlbicsXG4gICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnLFxuICAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JyxcbiAgJ19mYWlsZWRfbG9naW5fY291bnQnLFxuXTtcblxuY29uc3QgaXNTcGVjaWFsUXVlcnlLZXkgPSBrZXkgPT4ge1xuICByZXR1cm4gc3BlY2lhbFF1ZXJ5a2V5cy5pbmRleE9mKGtleSkgPj0gMDtcbn07XG5cbmNvbnN0IHZhbGlkYXRlUXVlcnkgPSAocXVlcnk6IGFueSk6IHZvaWQgPT4ge1xuICBpZiAocXVlcnkuQUNMKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksICdDYW5ub3QgcXVlcnkgb24gQUNMLicpO1xuICB9XG5cbiAgaWYgKHF1ZXJ5LiRvcikge1xuICAgIGlmIChxdWVyeS4kb3IgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgcXVlcnkuJG9yLmZvckVhY2godmFsaWRhdGVRdWVyeSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgJ0JhZCAkb3IgZm9ybWF0IC0gdXNlIGFuIGFycmF5IHZhbHVlLidcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHF1ZXJ5LiRhbmQpIHtcbiAgICBpZiAocXVlcnkuJGFuZCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBxdWVyeS4kYW5kLmZvckVhY2godmFsaWRhdGVRdWVyeSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgJ0JhZCAkYW5kIGZvcm1hdCAtIHVzZSBhbiBhcnJheSB2YWx1ZS4nXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmIChxdWVyeS4kbm9yKSB7XG4gICAgaWYgKHF1ZXJ5LiRub3IgaW5zdGFuY2VvZiBBcnJheSAmJiBxdWVyeS4kbm9yLmxlbmd0aCA+IDApIHtcbiAgICAgIHF1ZXJ5LiRub3IuZm9yRWFjaCh2YWxpZGF0ZVF1ZXJ5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAnQmFkICRub3IgZm9ybWF0IC0gdXNlIGFuIGFycmF5IG9mIGF0IGxlYXN0IDEgdmFsdWUuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBPYmplY3Qua2V5cyhxdWVyeSkuZm9yRWFjaChrZXkgPT4ge1xuICAgIGlmIChxdWVyeSAmJiBxdWVyeVtrZXldICYmIHF1ZXJ5W2tleV0uJHJlZ2V4KSB7XG4gICAgICBpZiAodHlwZW9mIHF1ZXJ5W2tleV0uJG9wdGlvbnMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGlmICghcXVlcnlba2V5XS4kb3B0aW9ucy5tYXRjaCgvXltpbXhzXSskLykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgICAgYEJhZCAkb3B0aW9ucyB2YWx1ZSBmb3IgcXVlcnk6ICR7cXVlcnlba2V5XS4kb3B0aW9uc31gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWlzU3BlY2lhbFF1ZXJ5S2V5KGtleSkgJiYgIWtleS5tYXRjaCgvXlthLXpBLVpdW2EtekEtWjAtOV9cXC5dKiQvKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICBgSW52YWxpZCBrZXkgbmFtZTogJHtrZXl9YFxuICAgICAgKTtcbiAgICB9XG4gIH0pO1xufTtcblxuLy8gRmlsdGVycyBvdXQgYW55IGRhdGEgdGhhdCBzaG91bGRuJ3QgYmUgb24gdGhpcyBSRVNULWZvcm1hdHRlZCBvYmplY3QuXG5jb25zdCBmaWx0ZXJTZW5zaXRpdmVEYXRhID0gKFxuICBpc01hc3RlcjogYm9vbGVhbixcbiAgYWNsR3JvdXA6IGFueVtdLFxuICBhdXRoOiBhbnksXG4gIG9wZXJhdGlvbjogYW55LFxuICBzY2hlbWE6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcixcbiAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gIHByb3RlY3RlZEZpZWxkczogbnVsbCB8IEFycmF5PGFueT4sXG4gIG9iamVjdDogYW55XG4pID0+IHtcbiAgbGV0IHVzZXJJZCA9IG51bGw7XG4gIGlmIChhdXRoICYmIGF1dGgudXNlcikgdXNlcklkID0gYXV0aC51c2VyLmlkO1xuXG4gIC8vIHJlcGxhY2UgcHJvdGVjdGVkRmllbGRzIHdoZW4gdXNpbmcgcG9pbnRlci1wZXJtaXNzaW9uc1xuICBjb25zdCBwZXJtcyA9IHNjaGVtYS5nZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lKTtcbiAgaWYgKHBlcm1zKSB7XG4gICAgY29uc3QgaXNSZWFkT3BlcmF0aW9uID0gWydnZXQnLCAnZmluZCddLmluZGV4T2Yob3BlcmF0aW9uKSA+IC0xO1xuXG4gICAgaWYgKGlzUmVhZE9wZXJhdGlvbiAmJiBwZXJtcy5wcm90ZWN0ZWRGaWVsZHMpIHtcbiAgICAgIC8vIGV4dHJhY3QgcHJvdGVjdGVkRmllbGRzIGFkZGVkIHdpdGggdGhlIHBvaW50ZXItcGVybWlzc2lvbiBwcmVmaXhcbiAgICAgIGNvbnN0IHByb3RlY3RlZEZpZWxkc1BvaW50ZXJQZXJtID0gT2JqZWN0LmtleXMocGVybXMucHJvdGVjdGVkRmllbGRzKVxuICAgICAgICAuZmlsdGVyKGtleSA9PiBrZXkuc3RhcnRzV2l0aCgndXNlckZpZWxkOicpKVxuICAgICAgICAubWFwKGtleSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHsga2V5OiBrZXkuc3Vic3RyaW5nKDEwKSwgdmFsdWU6IHBlcm1zLnByb3RlY3RlZEZpZWxkc1trZXldIH07XG4gICAgICAgIH0pO1xuXG4gICAgICBjb25zdCBuZXdQcm90ZWN0ZWRGaWVsZHM6IEFycmF5PHN0cmluZz5bXSA9IFtdO1xuICAgICAgbGV0IG92ZXJyaWRlUHJvdGVjdGVkRmllbGRzID0gZmFsc2U7XG5cbiAgICAgIC8vIGNoZWNrIGlmIHRoZSBvYmplY3QgZ3JhbnRzIHRoZSBjdXJyZW50IHVzZXIgYWNjZXNzIGJhc2VkIG9uIHRoZSBleHRyYWN0ZWQgZmllbGRzXG4gICAgICBwcm90ZWN0ZWRGaWVsZHNQb2ludGVyUGVybS5mb3JFYWNoKHBvaW50ZXJQZXJtID0+IHtcbiAgICAgICAgbGV0IHBvaW50ZXJQZXJtSW5jbHVkZXNVc2VyID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IHJlYWRVc2VyRmllbGRWYWx1ZSA9IG9iamVjdFtwb2ludGVyUGVybS5rZXldO1xuICAgICAgICBpZiAocmVhZFVzZXJGaWVsZFZhbHVlKSB7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVhZFVzZXJGaWVsZFZhbHVlKSkge1xuICAgICAgICAgICAgcG9pbnRlclBlcm1JbmNsdWRlc1VzZXIgPSByZWFkVXNlckZpZWxkVmFsdWUuc29tZShcbiAgICAgICAgICAgICAgdXNlciA9PiB1c2VyLm9iamVjdElkICYmIHVzZXIub2JqZWN0SWQgPT09IHVzZXJJZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9pbnRlclBlcm1JbmNsdWRlc1VzZXIgPVxuICAgICAgICAgICAgICByZWFkVXNlckZpZWxkVmFsdWUub2JqZWN0SWQgJiZcbiAgICAgICAgICAgICAgcmVhZFVzZXJGaWVsZFZhbHVlLm9iamVjdElkID09PSB1c2VySWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvaW50ZXJQZXJtSW5jbHVkZXNVc2VyKSB7XG4gICAgICAgICAgb3ZlcnJpZGVQcm90ZWN0ZWRGaWVsZHMgPSB0cnVlO1xuICAgICAgICAgIG5ld1Byb3RlY3RlZEZpZWxkcy5wdXNoKHBvaW50ZXJQZXJtLnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIGlmIGF0IGxlYXN0IG9uZSBwb2ludGVyLXBlcm1pc3Npb24gYWZmZWN0ZWQgdGhlIGN1cnJlbnQgdXNlclxuICAgICAgLy8gaW50ZXJzZWN0IHZzIHByb3RlY3RlZEZpZWxkcyBmcm9tIHByZXZpb3VzIHN0YWdlIChAc2VlIGFkZFByb3RlY3RlZEZpZWxkcylcbiAgICAgIC8vIFNldHMgdGhlb3J5IChpbnRlcnNlY3Rpb25zKTogQSB4IChCIHggQykgPT0gKEEgeCBCKSB4IENcbiAgICAgIGlmIChvdmVycmlkZVByb3RlY3RlZEZpZWxkcyAmJiBwcm90ZWN0ZWRGaWVsZHMpIHtcbiAgICAgICAgbmV3UHJvdGVjdGVkRmllbGRzLnB1c2gocHJvdGVjdGVkRmllbGRzKTtcbiAgICAgIH1cbiAgICAgIC8vIGludGVyc2VjdCBhbGwgc2V0cyBvZiBwcm90ZWN0ZWRGaWVsZHNcbiAgICAgIG5ld1Byb3RlY3RlZEZpZWxkcy5mb3JFYWNoKGZpZWxkcyA9PiB7XG4gICAgICAgIGlmIChmaWVsZHMpIHtcbiAgICAgICAgICAvLyBpZiB0aGVyZSdyZSBubyBwcm90Y3RlZEZpZWxkcyBieSBvdGhlciBjcml0ZXJpYSAoIGlkIC8gcm9sZSAvIGF1dGgpXG4gICAgICAgICAgLy8gdGhlbiB3ZSBtdXN0IGludGVyc2VjdCBlYWNoIHNldCAocGVyIHVzZXJGaWVsZClcbiAgICAgICAgICBpZiAoIXByb3RlY3RlZEZpZWxkcykge1xuICAgICAgICAgICAgcHJvdGVjdGVkRmllbGRzID0gZmllbGRzO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm90ZWN0ZWRGaWVsZHMgPSBwcm90ZWN0ZWRGaWVsZHMuZmlsdGVyKHYgPT4gZmllbGRzLmluY2x1ZGVzKHYpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGlzVXNlckNsYXNzID0gY2xhc3NOYW1lID09PSAnX1VzZXInO1xuXG4gIC8qIHNwZWNpYWwgdHJlYXQgZm9yIHRoZSB1c2VyIGNsYXNzOiBkb24ndCBmaWx0ZXIgcHJvdGVjdGVkRmllbGRzIGlmIGN1cnJlbnRseSBsb2dnZWRpbiB1c2VyIGlzXG4gIHRoZSByZXRyaWV2ZWQgdXNlciAqL1xuICBpZiAoIShpc1VzZXJDbGFzcyAmJiB1c2VySWQgJiYgb2JqZWN0Lm9iamVjdElkID09PSB1c2VySWQpKSB7XG4gICAgcHJvdGVjdGVkRmllbGRzICYmIHByb3RlY3RlZEZpZWxkcy5mb3JFYWNoKGsgPT4gZGVsZXRlIG9iamVjdFtrXSk7XG5cbiAgICAvLyBmaWVsZHMgbm90IHJlcXVlc3RlZCBieSBjbGllbnQgKGV4Y2x1ZGVkKSxcbiAgICAvL2J1dCB3ZXJlIG5lZWRlZCB0byBhcHBseSBwcm90ZWN0dGVkRmllbGRzXG4gICAgcGVybXMucHJvdGVjdGVkRmllbGRzICYmXG4gICAgICBwZXJtcy5wcm90ZWN0ZWRGaWVsZHMudGVtcG9yYXJ5S2V5cyAmJlxuICAgICAgcGVybXMucHJvdGVjdGVkRmllbGRzLnRlbXBvcmFyeUtleXMuZm9yRWFjaChrID0+IGRlbGV0ZSBvYmplY3Rba10pO1xuICB9XG5cbiAgaWYgKCFpc1VzZXJDbGFzcykge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICBvYmplY3QucGFzc3dvcmQgPSBvYmplY3QuX2hhc2hlZF9wYXNzd29yZDtcbiAgZGVsZXRlIG9iamVjdC5faGFzaGVkX3Bhc3N3b3JkO1xuXG4gIGRlbGV0ZSBvYmplY3Quc2Vzc2lvblRva2VuO1xuXG4gIGlmIChpc01hc3Rlcikge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgZGVsZXRlIG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuO1xuICBkZWxldGUgb2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuO1xuICBkZWxldGUgb2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX3RvbWJzdG9uZTtcbiAgZGVsZXRlIG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX2ZhaWxlZF9sb2dpbl9jb3VudDtcbiAgZGVsZXRlIG9iamVjdC5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX3Bhc3N3b3JkX2NoYW5nZWRfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX3Bhc3N3b3JkX2hpc3Rvcnk7XG5cbiAgaWYgKGFjbEdyb3VwLmluZGV4T2Yob2JqZWN0Lm9iamVjdElkKSA+IC0xKSB7XG4gICAgcmV0dXJuIG9iamVjdDtcbiAgfVxuICBkZWxldGUgb2JqZWN0LmF1dGhEYXRhO1xuICByZXR1cm4gb2JqZWN0O1xufTtcblxuaW1wb3J0IHR5cGUgeyBMb2FkU2NoZW1hT3B0aW9ucyB9IGZyb20gJy4vdHlwZXMnO1xuXG4vLyBSdW5zIGFuIHVwZGF0ZSBvbiB0aGUgZGF0YWJhc2UuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYW4gb2JqZWN0IHdpdGggdGhlIG5ldyB2YWx1ZXMgZm9yIGZpZWxkXG4vLyBtb2RpZmljYXRpb25zIHRoYXQgZG9uJ3Qga25vdyB0aGVpciByZXN1bHRzIGFoZWFkIG9mIHRpbWUsIGxpa2Vcbi8vICdpbmNyZW1lbnQnLlxuLy8gT3B0aW9uczpcbi8vICAgYWNsOiAgYSBsaXN0IG9mIHN0cmluZ3MuIElmIHRoZSBvYmplY3QgdG8gYmUgdXBkYXRlZCBoYXMgYW4gQUNMLFxuLy8gICAgICAgICBvbmUgb2YgdGhlIHByb3ZpZGVkIHN0cmluZ3MgbXVzdCBwcm92aWRlIHRoZSBjYWxsZXIgd2l0aFxuLy8gICAgICAgICB3cml0ZSBwZXJtaXNzaW9ucy5cbmNvbnN0IHNwZWNpYWxLZXlzRm9yVXBkYXRlID0gW1xuICAnX2hhc2hlZF9wYXNzd29yZCcsXG4gICdfcGVyaXNoYWJsZV90b2tlbicsXG4gICdfZW1haWxfdmVyaWZ5X3Rva2VuJyxcbiAgJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCcsXG4gICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnLFxuICAnX2ZhaWxlZF9sb2dpbl9jb3VudCcsXG4gICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JyxcbiAgJ19wYXNzd29yZF9jaGFuZ2VkX2F0JyxcbiAgJ19wYXNzd29yZF9oaXN0b3J5Jyxcbl07XG5cbmNvbnN0IGlzU3BlY2lhbFVwZGF0ZUtleSA9IGtleSA9PiB7XG4gIHJldHVybiBzcGVjaWFsS2V5c0ZvclVwZGF0ZS5pbmRleE9mKGtleSkgPj0gMDtcbn07XG5cbmZ1bmN0aW9uIGV4cGFuZFJlc3VsdE9uS2V5UGF0aChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleS5pbmRleE9mKCcuJykgPCAwKSB7XG4gICAgb2JqZWN0W2tleV0gPSB2YWx1ZVtrZXldO1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgY29uc3QgcGF0aCA9IGtleS5zcGxpdCgnLicpO1xuICBjb25zdCBmaXJzdEtleSA9IHBhdGhbMF07XG4gIGNvbnN0IG5leHRQYXRoID0gcGF0aC5zbGljZSgxKS5qb2luKCcuJyk7XG4gIG9iamVjdFtmaXJzdEtleV0gPSBleHBhbmRSZXN1bHRPbktleVBhdGgoXG4gICAgb2JqZWN0W2ZpcnN0S2V5XSB8fCB7fSxcbiAgICBuZXh0UGF0aCxcbiAgICB2YWx1ZVtmaXJzdEtleV1cbiAgKTtcbiAgZGVsZXRlIG9iamVjdFtrZXldO1xuICByZXR1cm4gb2JqZWN0O1xufVxuXG5mdW5jdGlvbiBzYW5pdGl6ZURhdGFiYXNlUmVzdWx0KG9yaWdpbmFsT2JqZWN0LCByZXN1bHQpOiBQcm9taXNlPGFueT4ge1xuICBjb25zdCByZXNwb25zZSA9IHt9O1xuICBpZiAoIXJlc3VsdCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzcG9uc2UpO1xuICB9XG4gIE9iamVjdC5rZXlzKG9yaWdpbmFsT2JqZWN0KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgY29uc3Qga2V5VXBkYXRlID0gb3JpZ2luYWxPYmplY3Rba2V5XTtcbiAgICAvLyBkZXRlcm1pbmUgaWYgdGhhdCB3YXMgYW4gb3BcbiAgICBpZiAoXG4gICAgICBrZXlVcGRhdGUgJiZcbiAgICAgIHR5cGVvZiBrZXlVcGRhdGUgPT09ICdvYmplY3QnICYmXG4gICAgICBrZXlVcGRhdGUuX19vcCAmJlxuICAgICAgWydBZGQnLCAnQWRkVW5pcXVlJywgJ1JlbW92ZScsICdJbmNyZW1lbnQnXS5pbmRleE9mKGtleVVwZGF0ZS5fX29wKSA+IC0xXG4gICAgKSB7XG4gICAgICAvLyBvbmx5IHZhbGlkIG9wcyB0aGF0IHByb2R1Y2UgYW4gYWN0aW9uYWJsZSByZXN1bHRcbiAgICAgIC8vIHRoZSBvcCBtYXkgaGF2ZSBoYXBwZW5kIG9uIGEga2V5cGF0aFxuICAgICAgZXhwYW5kUmVzdWx0T25LZXlQYXRoKHJlc3BvbnNlLCBrZXksIHJlc3VsdCk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXNwb25zZSk7XG59XG5cbmZ1bmN0aW9uIGpvaW5UYWJsZU5hbWUoY2xhc3NOYW1lLCBrZXkpIHtcbiAgcmV0dXJuIGBfSm9pbjoke2tleX06JHtjbGFzc05hbWV9YDtcbn1cblxuY29uc3QgZmxhdHRlblVwZGF0ZU9wZXJhdG9yc0ZvckNyZWF0ZSA9IG9iamVjdCA9PiB7XG4gIGZvciAoY29uc3Qga2V5IGluIG9iamVjdCkge1xuICAgIGlmIChvYmplY3Rba2V5XSAmJiBvYmplY3Rba2V5XS5fX29wKSB7XG4gICAgICBzd2l0Y2ggKG9iamVjdFtrZXldLl9fb3ApIHtcbiAgICAgICAgY2FzZSAnSW5jcmVtZW50JzpcbiAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdFtrZXldLmFtb3VudCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAnb2JqZWN0cyB0byBhZGQgbXVzdCBiZSBhbiBhcnJheSdcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG9iamVjdFtrZXldID0gb2JqZWN0W2tleV0uYW1vdW50O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdBZGQnOlxuICAgICAgICAgIGlmICghKG9iamVjdFtrZXldLm9iamVjdHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAnb2JqZWN0cyB0byBhZGQgbXVzdCBiZSBhbiBhcnJheSdcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG9iamVjdFtrZXldID0gb2JqZWN0W2tleV0ub2JqZWN0cztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnQWRkVW5pcXVlJzpcbiAgICAgICAgICBpZiAoIShvYmplY3Rba2V5XS5vYmplY3RzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJ29iamVjdHMgdG8gYWRkIG11c3QgYmUgYW4gYXJyYXknXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvYmplY3Rba2V5XSA9IG9iamVjdFtrZXldLm9iamVjdHM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ1JlbW92ZSc6XG4gICAgICAgICAgaWYgKCEob2JqZWN0W2tleV0ub2JqZWN0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICdvYmplY3RzIHRvIGFkZCBtdXN0IGJlIGFuIGFycmF5J1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgb2JqZWN0W2tleV0gPSBbXTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnRGVsZXRlJzpcbiAgICAgICAgICBkZWxldGUgb2JqZWN0W2tleV07XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuQ09NTUFORF9VTkFWQUlMQUJMRSxcbiAgICAgICAgICAgIGBUaGUgJHtvYmplY3Rba2V5XS5fX29wfSBvcGVyYXRvciBpcyBub3Qgc3VwcG9ydGVkIHlldC5gXG4gICAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cbmNvbnN0IHRyYW5zZm9ybUF1dGhEYXRhID0gKGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpID0+IHtcbiAgaWYgKG9iamVjdC5hdXRoRGF0YSAmJiBjbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBPYmplY3Qua2V5cyhvYmplY3QuYXV0aERhdGEpLmZvckVhY2gocHJvdmlkZXIgPT4ge1xuICAgICAgY29uc3QgcHJvdmlkZXJEYXRhID0gb2JqZWN0LmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGBfYXV0aF9kYXRhXyR7cHJvdmlkZXJ9YDtcbiAgICAgIGlmIChwcm92aWRlckRhdGEgPT0gbnVsbCkge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX29wOiAnRGVsZXRlJyxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0gcHJvdmlkZXJEYXRhO1xuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gPSB7IHR5cGU6ICdPYmplY3QnIH07XG4gICAgICB9XG4gICAgfSk7XG4gICAgZGVsZXRlIG9iamVjdC5hdXRoRGF0YTtcbiAgfVxufTtcbi8vIFRyYW5zZm9ybXMgYSBEYXRhYmFzZSBmb3JtYXQgQUNMIHRvIGEgUkVTVCBBUEkgZm9ybWF0IEFDTFxuY29uc3QgdW50cmFuc2Zvcm1PYmplY3RBQ0wgPSAoeyBfcnBlcm0sIF93cGVybSwgLi4ub3V0cHV0IH0pID0+IHtcbiAgaWYgKF9ycGVybSB8fCBfd3Blcm0pIHtcbiAgICBvdXRwdXQuQUNMID0ge307XG5cbiAgICAoX3JwZXJtIHx8IFtdKS5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIGlmICghb3V0cHV0LkFDTFtlbnRyeV0pIHtcbiAgICAgICAgb3V0cHV0LkFDTFtlbnRyeV0gPSB7IHJlYWQ6IHRydWUgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dC5BQ0xbZW50cnldWydyZWFkJ10gPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgKF93cGVybSB8fCBbXSkuZm9yRWFjaChlbnRyeSA9PiB7XG4gICAgICBpZiAoIW91dHB1dC5BQ0xbZW50cnldKSB7XG4gICAgICAgIG91dHB1dC5BQ0xbZW50cnldID0geyB3cml0ZTogdHJ1ZSB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0LkFDTFtlbnRyeV1bJ3dyaXRlJ10gPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBvdXRwdXQ7XG59O1xuXG4vKipcbiAqIFdoZW4gcXVlcnlpbmcsIHRoZSBmaWVsZE5hbWUgbWF5IGJlIGNvbXBvdW5kLCBleHRyYWN0IHRoZSByb290IGZpZWxkTmFtZVxuICogICAgIGB0ZW1wZXJhdHVyZS5jZWxzaXVzYCBiZWNvbWVzIGB0ZW1wZXJhdHVyZWBcbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWVsZE5hbWUgdGhhdCBtYXkgYmUgYSBjb21wb3VuZCBmaWVsZCBuYW1lXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB0aGUgcm9vdCBuYW1lIG9mIHRoZSBmaWVsZFxuICovXG5jb25zdCBnZXRSb290RmllbGROYW1lID0gKGZpZWxkTmFtZTogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgcmV0dXJuIGZpZWxkTmFtZS5zcGxpdCgnLicpWzBdO1xufTtcblxuY29uc3QgcmVsYXRpb25TY2hlbWEgPSB7XG4gIGZpZWxkczogeyByZWxhdGVkSWQ6IHsgdHlwZTogJ1N0cmluZycgfSwgb3duaW5nSWQ6IHsgdHlwZTogJ1N0cmluZycgfSB9LFxufTtcblxuY2xhc3MgRGF0YWJhc2VDb250cm9sbGVyIHtcbiAgYWRhcHRlcjogU3RvcmFnZUFkYXB0ZXI7XG4gIHNjaGVtYUNhY2hlOiBhbnk7XG4gIHNjaGVtYVByb21pc2U6ID9Qcm9taXNlPFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcj47XG4gIF90cmFuc2FjdGlvbmFsU2Vzc2lvbjogP2FueTtcblxuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBTdG9yYWdlQWRhcHRlciwgc2NoZW1hQ2FjaGU6IGFueSkge1xuICAgIHRoaXMuYWRhcHRlciA9IGFkYXB0ZXI7XG4gICAgdGhpcy5zY2hlbWFDYWNoZSA9IHNjaGVtYUNhY2hlO1xuICAgIC8vIFdlIGRvbid0IHdhbnQgYSBtdXRhYmxlIHRoaXMuc2NoZW1hLCBiZWNhdXNlIHRoZW4geW91IGNvdWxkIGhhdmVcbiAgICAvLyBvbmUgcmVxdWVzdCB0aGF0IHVzZXMgZGlmZmVyZW50IHNjaGVtYXMgZm9yIGRpZmZlcmVudCBwYXJ0cyBvZlxuICAgIC8vIGl0LiBJbnN0ZWFkLCB1c2UgbG9hZFNjaGVtYSB0byBnZXQgYSBzY2hlbWEuXG4gICAgdGhpcy5zY2hlbWFQcm9taXNlID0gbnVsbDtcbiAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvbiA9IG51bGw7XG4gIH1cblxuICBjb2xsZWN0aW9uRXhpc3RzKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5jbGFzc0V4aXN0cyhjbGFzc05hbWUpO1xuICB9XG5cbiAgcHVyZ2VDb2xsZWN0aW9uKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYSgpXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSkpXG4gICAgICAudGhlbihzY2hlbWEgPT4gdGhpcy5hZGFwdGVyLmRlbGV0ZU9iamVjdHNCeVF1ZXJ5KGNsYXNzTmFtZSwgc2NoZW1hLCB7fSkpO1xuICB9XG5cbiAgdmFsaWRhdGVDbGFzc05hbWUoY2xhc3NOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIVNjaGVtYUNvbnRyb2xsZXIuY2xhc3NOYW1lSXNWYWxpZChjbGFzc05hbWUpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICAgICAgJ2ludmFsaWQgY2xhc3NOYW1lOiAnICsgY2xhc3NOYW1lXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHNjaGVtYUNvbnRyb2xsZXIuXG4gIGxvYWRTY2hlbWEoXG4gICAgb3B0aW9uczogTG9hZFNjaGVtYU9wdGlvbnMgPSB7IGNsZWFyQ2FjaGU6IGZhbHNlIH1cbiAgKTogUHJvbWlzZTxTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXI+IHtcbiAgICBpZiAodGhpcy5zY2hlbWFQcm9taXNlICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0aGlzLnNjaGVtYVByb21pc2U7XG4gICAgfVxuICAgIHRoaXMuc2NoZW1hUHJvbWlzZSA9IFNjaGVtYUNvbnRyb2xsZXIubG9hZChcbiAgICAgIHRoaXMuYWRhcHRlcixcbiAgICAgIHRoaXMuc2NoZW1hQ2FjaGUsXG4gICAgICBvcHRpb25zXG4gICAgKTtcbiAgICB0aGlzLnNjaGVtYVByb21pc2UudGhlbihcbiAgICAgICgpID0+IGRlbGV0ZSB0aGlzLnNjaGVtYVByb21pc2UsXG4gICAgICAoKSA9PiBkZWxldGUgdGhpcy5zY2hlbWFQcm9taXNlXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hKG9wdGlvbnMpO1xuICB9XG5cbiAgbG9hZFNjaGVtYUlmTmVlZGVkKFxuICAgIHNjaGVtYUNvbnRyb2xsZXI6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcixcbiAgICBvcHRpb25zOiBMb2FkU2NoZW1hT3B0aW9ucyA9IHsgY2xlYXJDYWNoZTogZmFsc2UgfVxuICApOiBQcm9taXNlPFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcj4ge1xuICAgIHJldHVybiBzY2hlbWFDb250cm9sbGVyXG4gICAgICA/IFByb21pc2UucmVzb2x2ZShzY2hlbWFDb250cm9sbGVyKVxuICAgICAgOiB0aGlzLmxvYWRTY2hlbWEob3B0aW9ucyk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgdGhlIGNsYXNzbmFtZSB0aGF0IGlzIHJlbGF0ZWQgdG8gdGhlIGdpdmVuXG4gIC8vIGNsYXNzbmFtZSB0aHJvdWdoIHRoZSBrZXkuXG4gIC8vIFRPRE86IG1ha2UgdGhpcyBub3QgaW4gdGhlIERhdGFiYXNlQ29udHJvbGxlciBpbnRlcmZhY2VcbiAgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXkoY2xhc3NOYW1lOiBzdHJpbmcsIGtleTogc3RyaW5nKTogUHJvbWlzZTw/c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYSgpLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgIHZhciB0ID0gc2NoZW1hLmdldEV4cGVjdGVkVHlwZShjbGFzc05hbWUsIGtleSk7XG4gICAgICBpZiAodCAhPSBudWxsICYmIHR5cGVvZiB0ICE9PSAnc3RyaW5nJyAmJiB0LnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIHQudGFyZ2V0Q2xhc3M7XG4gICAgICB9XG4gICAgICByZXR1cm4gY2xhc3NOYW1lO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gVXNlcyB0aGUgc2NoZW1hIHRvIHZhbGlkYXRlIHRoZSBvYmplY3QgKFJFU1QgQVBJIGZvcm1hdCkuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG5ldyBzY2hlbWEuXG4gIC8vIFRoaXMgZG9lcyBub3QgdXBkYXRlIHRoaXMuc2NoZW1hLCBiZWNhdXNlIGluIGEgc2l0dWF0aW9uIGxpa2UgYVxuICAvLyBiYXRjaCByZXF1ZXN0LCB0aGF0IGNvdWxkIGNvbmZ1c2Ugb3RoZXIgdXNlcnMgb2YgdGhlIHNjaGVtYS5cbiAgdmFsaWRhdGVPYmplY3QoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBhbnksXG4gICAgcXVlcnk6IGFueSxcbiAgICBydW5PcHRpb25zOiBRdWVyeU9wdGlvbnNcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgbGV0IHNjaGVtYTtcbiAgICBjb25zdCBhY2wgPSBydW5PcHRpb25zLmFjbDtcbiAgICBjb25zdCBpc01hc3RlciA9IGFjbCA9PT0gdW5kZWZpbmVkO1xuICAgIHZhciBhY2xHcm91cDogc3RyaW5nW10gPSBhY2wgfHwgW107XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYSgpXG4gICAgICAudGhlbihzID0+IHtcbiAgICAgICAgc2NoZW1hID0gcztcbiAgICAgICAgaWYgKGlzTWFzdGVyKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNhbkFkZEZpZWxkKFxuICAgICAgICAgIHNjaGVtYSxcbiAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgb2JqZWN0LFxuICAgICAgICAgIGFjbEdyb3VwLFxuICAgICAgICAgIHJ1bk9wdGlvbnNcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiBzY2hlbWEudmFsaWRhdGVPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHF1ZXJ5KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHF1ZXJ5OiBhbnksXG4gICAgdXBkYXRlOiBhbnksXG4gICAgeyBhY2wsIG1hbnksIHVwc2VydCwgYWRkc0ZpZWxkIH06IEZ1bGxRdWVyeU9wdGlvbnMgPSB7fSxcbiAgICBza2lwU2FuaXRpemF0aW9uOiBib29sZWFuID0gZmFsc2UsXG4gICAgdmFsaWRhdGVPbmx5OiBib29sZWFuID0gZmFsc2UsXG4gICAgdmFsaWRTY2hlbWFDb250cm9sbGVyOiBTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXJcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBvcmlnaW5hbFF1ZXJ5ID0gcXVlcnk7XG4gICAgY29uc3Qgb3JpZ2luYWxVcGRhdGUgPSB1cGRhdGU7XG4gICAgLy8gTWFrZSBhIGNvcHkgb2YgdGhlIG9iamVjdCwgc28gd2UgZG9uJ3QgbXV0YXRlIHRoZSBpbmNvbWluZyBkYXRhLlxuICAgIHVwZGF0ZSA9IGRlZXBjb3B5KHVwZGF0ZSk7XG4gICAgdmFyIHJlbGF0aW9uVXBkYXRlcyA9IFtdO1xuICAgIHZhciBpc01hc3RlciA9IGFjbCA9PT0gdW5kZWZpbmVkO1xuICAgIHZhciBhY2xHcm91cCA9IGFjbCB8fCBbXTtcblxuICAgIHJldHVybiB0aGlzLmxvYWRTY2hlbWFJZk5lZWRlZCh2YWxpZFNjaGVtYUNvbnRyb2xsZXIpLnRoZW4oXG4gICAgICBzY2hlbWFDb250cm9sbGVyID0+IHtcbiAgICAgICAgcmV0dXJuIChpc01hc3RlclxuICAgICAgICAgID8gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICA6IHNjaGVtYUNvbnRyb2xsZXIudmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZSwgYWNsR3JvdXAsICd1cGRhdGUnKVxuICAgICAgICApXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmVsYXRpb25VcGRhdGVzID0gdGhpcy5jb2xsZWN0UmVsYXRpb25VcGRhdGVzKFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIG9yaWdpbmFsUXVlcnkub2JqZWN0SWQsXG4gICAgICAgICAgICAgIHVwZGF0ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmICghaXNNYXN0ZXIpIHtcbiAgICAgICAgICAgICAgcXVlcnkgPSB0aGlzLmFkZFBvaW50ZXJQZXJtaXNzaW9ucyhcbiAgICAgICAgICAgICAgICBzY2hlbWFDb250cm9sbGVyLFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAndXBkYXRlJyxcbiAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICBhY2xHcm91cFxuICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgIGlmIChhZGRzRmllbGQpIHtcbiAgICAgICAgICAgICAgICBxdWVyeSA9IHtcbiAgICAgICAgICAgICAgICAgICRhbmQ6IFtcbiAgICAgICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkUG9pbnRlclBlcm1pc3Npb25zKFxuICAgICAgICAgICAgICAgICAgICAgIHNjaGVtYUNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICdhZGRGaWVsZCcsXG4gICAgICAgICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgICAgICAgYWNsR3JvdXBcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFxdWVyeSkge1xuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYWNsKSB7XG4gICAgICAgICAgICAgIHF1ZXJ5ID0gYWRkV3JpdGVBQ0wocXVlcnksIGFjbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWxpZGF0ZVF1ZXJ5KHF1ZXJ5KTtcbiAgICAgICAgICAgIHJldHVybiBzY2hlbWFDb250cm9sbGVyXG4gICAgICAgICAgICAgIC5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCB0cnVlKVxuICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBzY2hlbWEgZG9lc24ndCBleGlzdCwgcHJldGVuZCBpdCBleGlzdHMgd2l0aCBubyBmaWVsZHMuIFRoaXMgYmVoYXZpb3JcbiAgICAgICAgICAgICAgICAvLyB3aWxsIGxpa2VseSBuZWVkIHJldmlzaXRpbmcuXG4gICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB7IGZpZWxkczoge30gfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC50aGVuKHNjaGVtYSA9PiB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmtleXModXBkYXRlKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoZmllbGROYW1lLm1hdGNoKC9eYXV0aERhdGFcXC4oW2EtekEtWjAtOV9dKylcXC5pZCQvKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICAgICAgICAgICAgICAgICBgSW52YWxpZCBmaWVsZCBuYW1lIGZvciB1cGRhdGU6ICR7ZmllbGROYW1lfWBcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJvb3RGaWVsZE5hbWUgPSBnZXRSb290RmllbGROYW1lKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICFTY2hlbWFDb250cm9sbGVyLmZpZWxkTmFtZUlzVmFsaWQocm9vdEZpZWxkTmFtZSkgJiZcbiAgICAgICAgICAgICAgICAgICAgIWlzU3BlY2lhbFVwZGF0ZUtleShyb290RmllbGROYW1lKVxuICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICAgICAgICAgICAgICAgIGBJbnZhbGlkIGZpZWxkIG5hbWUgZm9yIHVwZGF0ZTogJHtmaWVsZE5hbWV9YFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgdXBkYXRlT3BlcmF0aW9uIGluIHVwZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICB1cGRhdGVbdXBkYXRlT3BlcmF0aW9uXSAmJlxuICAgICAgICAgICAgICAgICAgICB0eXBlb2YgdXBkYXRlW3VwZGF0ZU9wZXJhdGlvbl0gPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKHVwZGF0ZVt1cGRhdGVPcGVyYXRpb25dKS5zb21lKFxuICAgICAgICAgICAgICAgICAgICAgIGlubmVyS2V5ID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBpbm5lcktleS5pbmNsdWRlcygnJCcpIHx8IGlubmVyS2V5LmluY2x1ZGVzKCcuJylcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX05FU1RFRF9LRVksXG4gICAgICAgICAgICAgICAgICAgICAgXCJOZXN0ZWQga2V5cyBzaG91bGQgbm90IGNvbnRhaW4gdGhlICckJyBvciAnLicgY2hhcmFjdGVyc1wiXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHVwZGF0ZSA9IHRyYW5zZm9ybU9iamVjdEFDTCh1cGRhdGUpO1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybUF1dGhEYXRhKGNsYXNzTmFtZSwgdXBkYXRlLCBzY2hlbWEpO1xuICAgICAgICAgICAgICAgIGlmICh2YWxpZGF0ZU9ubHkpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXJcbiAgICAgICAgICAgICAgICAgICAgLmZpbmQoY2xhc3NOYW1lLCBzY2hlbWEsIHF1ZXJ5LCB7fSlcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoIXJlc3VsdCB8fCAhcmVzdWx0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWFueSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci51cGRhdGVPYmplY3RzQnlRdWVyeShcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICB1cGRhdGUsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodXBzZXJ0KSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnVwc2VydE9uZU9iamVjdChcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICB1cGRhdGUsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmZpbmRPbmVBbmRVcGRhdGUoXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvblxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnRoZW4oKHJlc3VsdDogYW55KSA9PiB7XG4gICAgICAgICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZC4nXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsaWRhdGVPbmx5KSB7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oYW5kbGVSZWxhdGlvblVwZGF0ZXMoXG4gICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgb3JpZ2luYWxRdWVyeS5vYmplY3RJZCxcbiAgICAgICAgICAgICAgdXBkYXRlLFxuICAgICAgICAgICAgICByZWxhdGlvblVwZGF0ZXNcbiAgICAgICAgICAgICkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgICBpZiAoc2tpcFNhbml0aXphdGlvbikge1xuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc2FuaXRpemVEYXRhYmFzZVJlc3VsdChvcmlnaW5hbFVwZGF0ZSwgcmVzdWx0KTtcbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgLy8gQ29sbGVjdCBhbGwgcmVsYXRpb24tdXBkYXRpbmcgb3BlcmF0aW9ucyBmcm9tIGEgUkVTVC1mb3JtYXQgdXBkYXRlLlxuICAvLyBSZXR1cm5zIGEgbGlzdCBvZiBhbGwgcmVsYXRpb24gdXBkYXRlcyB0byBwZXJmb3JtXG4gIC8vIFRoaXMgbXV0YXRlcyB1cGRhdGUuXG4gIGNvbGxlY3RSZWxhdGlvblVwZGF0ZXMoY2xhc3NOYW1lOiBzdHJpbmcsIG9iamVjdElkOiA/c3RyaW5nLCB1cGRhdGU6IGFueSkge1xuICAgIHZhciBvcHMgPSBbXTtcbiAgICB2YXIgZGVsZXRlTWUgPSBbXTtcbiAgICBvYmplY3RJZCA9IHVwZGF0ZS5vYmplY3RJZCB8fCBvYmplY3RJZDtcblxuICAgIHZhciBwcm9jZXNzID0gKG9wLCBrZXkpID0+IHtcbiAgICAgIGlmICghb3ApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKG9wLl9fb3AgPT0gJ0FkZFJlbGF0aW9uJykge1xuICAgICAgICBvcHMucHVzaCh7IGtleSwgb3AgfSk7XG4gICAgICAgIGRlbGV0ZU1lLnB1c2goa2V5KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wLl9fb3AgPT0gJ1JlbW92ZVJlbGF0aW9uJykge1xuICAgICAgICBvcHMucHVzaCh7IGtleSwgb3AgfSk7XG4gICAgICAgIGRlbGV0ZU1lLnB1c2goa2V5KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wLl9fb3AgPT0gJ0JhdGNoJykge1xuICAgICAgICBmb3IgKHZhciB4IG9mIG9wLm9wcykge1xuICAgICAgICAgIHByb2Nlc3MoeCwga2V5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IGtleSBpbiB1cGRhdGUpIHtcbiAgICAgIHByb2Nlc3ModXBkYXRlW2tleV0sIGtleSk7XG4gICAgfVxuICAgIGZvciAoY29uc3Qga2V5IG9mIGRlbGV0ZU1lKSB7XG4gICAgICBkZWxldGUgdXBkYXRlW2tleV07XG4gICAgfVxuICAgIHJldHVybiBvcHM7XG4gIH1cblxuICAvLyBQcm9jZXNzZXMgcmVsYXRpb24tdXBkYXRpbmcgb3BlcmF0aW9ucyBmcm9tIGEgUkVTVC1mb3JtYXQgdXBkYXRlLlxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIHVwZGF0ZXMgaGF2ZSBiZWVuIHBlcmZvcm1lZFxuICBoYW5kbGVSZWxhdGlvblVwZGF0ZXMoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0SWQ6IHN0cmluZyxcbiAgICB1cGRhdGU6IGFueSxcbiAgICBvcHM6IGFueVxuICApIHtcbiAgICB2YXIgcGVuZGluZyA9IFtdO1xuICAgIG9iamVjdElkID0gdXBkYXRlLm9iamVjdElkIHx8IG9iamVjdElkO1xuICAgIG9wcy5mb3JFYWNoKCh7IGtleSwgb3AgfSkgPT4ge1xuICAgICAgaWYgKCFvcCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAob3AuX19vcCA9PSAnQWRkUmVsYXRpb24nKSB7XG4gICAgICAgIGZvciAoY29uc3Qgb2JqZWN0IG9mIG9wLm9iamVjdHMpIHtcbiAgICAgICAgICBwZW5kaW5nLnB1c2goXG4gICAgICAgICAgICB0aGlzLmFkZFJlbGF0aW9uKGtleSwgY2xhc3NOYW1lLCBvYmplY3RJZCwgb2JqZWN0Lm9iamVjdElkKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKG9wLl9fb3AgPT0gJ1JlbW92ZVJlbGF0aW9uJykge1xuICAgICAgICBmb3IgKGNvbnN0IG9iamVjdCBvZiBvcC5vYmplY3RzKSB7XG4gICAgICAgICAgcGVuZGluZy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5yZW1vdmVSZWxhdGlvbihrZXksIGNsYXNzTmFtZSwgb2JqZWN0SWQsIG9iamVjdC5vYmplY3RJZClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwocGVuZGluZyk7XG4gIH1cblxuICAvLyBBZGRzIGEgcmVsYXRpb24uXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgc3VjY2Vzc2Z1bGx5IGlmZiB0aGUgYWRkIHdhcyBzdWNjZXNzZnVsLlxuICBhZGRSZWxhdGlvbihcbiAgICBrZXk6IHN0cmluZyxcbiAgICBmcm9tQ2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZnJvbUlkOiBzdHJpbmcsXG4gICAgdG9JZDogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IGRvYyA9IHtcbiAgICAgIHJlbGF0ZWRJZDogdG9JZCxcbiAgICAgIG93bmluZ0lkOiBmcm9tSWQsXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnVwc2VydE9uZU9iamVjdChcbiAgICAgIGBfSm9pbjoke2tleX06JHtmcm9tQ2xhc3NOYW1lfWAsXG4gICAgICByZWxhdGlvblNjaGVtYSxcbiAgICAgIGRvYyxcbiAgICAgIGRvYyxcbiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgKTtcbiAgfVxuXG4gIC8vIFJlbW92ZXMgYSByZWxhdGlvbi5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBzdWNjZXNzZnVsbHkgaWZmIHRoZSByZW1vdmUgd2FzXG4gIC8vIHN1Y2Nlc3NmdWwuXG4gIHJlbW92ZVJlbGF0aW9uKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZyb21DbGFzc05hbWU6IHN0cmluZyxcbiAgICBmcm9tSWQ6IHN0cmluZyxcbiAgICB0b0lkOiBzdHJpbmdcbiAgKSB7XG4gICAgdmFyIGRvYyA9IHtcbiAgICAgIHJlbGF0ZWRJZDogdG9JZCxcbiAgICAgIG93bmluZ0lkOiBmcm9tSWQsXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyXG4gICAgICAuZGVsZXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgICAgIGBfSm9pbjoke2tleX06JHtmcm9tQ2xhc3NOYW1lfWAsXG4gICAgICAgIHJlbGF0aW9uU2NoZW1hLFxuICAgICAgICBkb2MsXG4gICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvLyBXZSBkb24ndCBjYXJlIGlmIHRoZXkgdHJ5IHRvIGRlbGV0ZSBhIG5vbi1leGlzdGVudCByZWxhdGlvbi5cbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gUmVtb3ZlcyBvYmplY3RzIG1hdGNoZXMgdGhpcyBxdWVyeSBmcm9tIHRoZSBkYXRhYmFzZS5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBzdWNjZXNzZnVsbHkgaWZmIHRoZSBvYmplY3Qgd2FzXG4gIC8vIGRlbGV0ZWQuXG4gIC8vIE9wdGlvbnM6XG4gIC8vICAgYWNsOiAgYSBsaXN0IG9mIHN0cmluZ3MuIElmIHRoZSBvYmplY3QgdG8gYmUgdXBkYXRlZCBoYXMgYW4gQUNMLFxuICAvLyAgICAgICAgIG9uZSBvZiB0aGUgcHJvdmlkZWQgc3RyaW5ncyBtdXN0IHByb3ZpZGUgdGhlIGNhbGxlciB3aXRoXG4gIC8vICAgICAgICAgd3JpdGUgcGVybWlzc2lvbnMuXG4gIGRlc3Ryb3koXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgcXVlcnk6IGFueSxcbiAgICB7IGFjbCB9OiBRdWVyeU9wdGlvbnMgPSB7fSxcbiAgICB2YWxpZFNjaGVtYUNvbnRyb2xsZXI6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlclxuICApOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IGlzTWFzdGVyID0gYWNsID09PSB1bmRlZmluZWQ7XG4gICAgY29uc3QgYWNsR3JvdXAgPSBhY2wgfHwgW107XG5cbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hSWZOZWVkZWQodmFsaWRTY2hlbWFDb250cm9sbGVyKS50aGVuKFxuICAgICAgc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgICAgIHJldHVybiAoaXNNYXN0ZXJcbiAgICAgICAgICA/IFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgOiBzY2hlbWFDb250cm9sbGVyLnZhbGlkYXRlUGVybWlzc2lvbihjbGFzc05hbWUsIGFjbEdyb3VwLCAnZGVsZXRlJylcbiAgICAgICAgKS50aGVuKCgpID0+IHtcbiAgICAgICAgICBpZiAoIWlzTWFzdGVyKSB7XG4gICAgICAgICAgICBxdWVyeSA9IHRoaXMuYWRkUG9pbnRlclBlcm1pc3Npb25zKFxuICAgICAgICAgICAgICBzY2hlbWFDb250cm9sbGVyLFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICdkZWxldGUnLFxuICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgYWNsR3JvdXBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoIXF1ZXJ5KSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgICAgICdPYmplY3Qgbm90IGZvdW5kLidcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gZGVsZXRlIGJ5IHF1ZXJ5XG4gICAgICAgICAgaWYgKGFjbCkge1xuICAgICAgICAgICAgcXVlcnkgPSBhZGRXcml0ZUFDTChxdWVyeSwgYWNsKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFsaWRhdGVRdWVyeShxdWVyeSk7XG4gICAgICAgICAgcmV0dXJuIHNjaGVtYUNvbnRyb2xsZXJcbiAgICAgICAgICAgIC5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgLy8gSWYgdGhlIHNjaGVtYSBkb2Vzbid0IGV4aXN0LCBwcmV0ZW5kIGl0IGV4aXN0cyB3aXRoIG5vIGZpZWxkcy4gVGhpcyBiZWhhdmlvclxuICAgICAgICAgICAgICAvLyB3aWxsIGxpa2VseSBuZWVkIHJldmlzaXRpbmcuXG4gICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgZmllbGRzOiB7fSB9O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKHBhcnNlRm9ybWF0U2NoZW1hID0+XG4gICAgICAgICAgICAgIHRoaXMuYWRhcHRlci5kZWxldGVPYmplY3RzQnlRdWVyeShcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgcGFyc2VGb3JtYXRTY2hlbWEsXG4gICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb25cbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgLy8gV2hlbiBkZWxldGluZyBzZXNzaW9ucyB3aGlsZSBjaGFuZ2luZyBwYXNzd29yZHMsIGRvbid0IHRocm93IGFuIGVycm9yIGlmIHRoZXkgZG9uJ3QgaGF2ZSBhbnkgc2Vzc2lvbnMuXG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUgPT09ICdfU2Vzc2lvbicgJiZcbiAgICAgICAgICAgICAgICBlcnJvci5jb2RlID09PSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICAvLyBJbnNlcnRzIGFuIG9iamVjdCBpbnRvIHRoZSBkYXRhYmFzZS5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBzdWNjZXNzZnVsbHkgaWZmIHRoZSBvYmplY3Qgc2F2ZWQuXG4gIGNyZWF0ZShcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBvYmplY3Q6IGFueSxcbiAgICB7IGFjbCB9OiBRdWVyeU9wdGlvbnMgPSB7fSxcbiAgICB2YWxpZGF0ZU9ubHk6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICB2YWxpZFNjaGVtYUNvbnRyb2xsZXI6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlclxuICApOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIE1ha2UgYSBjb3B5IG9mIHRoZSBvYmplY3QsIHNvIHdlIGRvbid0IG11dGF0ZSB0aGUgaW5jb21pbmcgZGF0YS5cbiAgICBjb25zdCBvcmlnaW5hbE9iamVjdCA9IG9iamVjdDtcbiAgICBvYmplY3QgPSB0cmFuc2Zvcm1PYmplY3RBQ0wob2JqZWN0KTtcblxuICAgIG9iamVjdC5jcmVhdGVkQXQgPSB7IGlzbzogb2JqZWN0LmNyZWF0ZWRBdCwgX190eXBlOiAnRGF0ZScgfTtcbiAgICBvYmplY3QudXBkYXRlZEF0ID0geyBpc286IG9iamVjdC51cGRhdGVkQXQsIF9fdHlwZTogJ0RhdGUnIH07XG5cbiAgICB2YXIgaXNNYXN0ZXIgPSBhY2wgPT09IHVuZGVmaW5lZDtcbiAgICB2YXIgYWNsR3JvdXAgPSBhY2wgfHwgW107XG4gICAgY29uc3QgcmVsYXRpb25VcGRhdGVzID0gdGhpcy5jb2xsZWN0UmVsYXRpb25VcGRhdGVzKFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgbnVsbCxcbiAgICAgIG9iamVjdFxuICAgICk7XG5cbiAgICByZXR1cm4gdGhpcy52YWxpZGF0ZUNsYXNzTmFtZShjbGFzc05hbWUpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmxvYWRTY2hlbWFJZk5lZWRlZCh2YWxpZFNjaGVtYUNvbnRyb2xsZXIpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgICAgIHJldHVybiAoaXNNYXN0ZXJcbiAgICAgICAgICA/IFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgOiBzY2hlbWFDb250cm9sbGVyLnZhbGlkYXRlUGVybWlzc2lvbihjbGFzc05hbWUsIGFjbEdyb3VwLCAnY3JlYXRlJylcbiAgICAgICAgKVxuICAgICAgICAgIC50aGVuKCgpID0+IHNjaGVtYUNvbnRyb2xsZXIuZW5mb3JjZUNsYXNzRXhpc3RzKGNsYXNzTmFtZSkpXG4gICAgICAgICAgLnRoZW4oKCkgPT4gc2NoZW1hQ29udHJvbGxlci5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCB0cnVlKSlcbiAgICAgICAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgICAgICAgdHJhbnNmb3JtQXV0aERhdGEoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSk7XG4gICAgICAgICAgICBmbGF0dGVuVXBkYXRlT3BlcmF0b3JzRm9yQ3JlYXRlKG9iamVjdCk7XG4gICAgICAgICAgICBpZiAodmFsaWRhdGVPbmx5KSB7XG4gICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuY3JlYXRlT2JqZWN0KFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIFNjaGVtYUNvbnRyb2xsZXIuY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShzY2hlbWEpLFxuICAgICAgICAgICAgICBvYmplY3QsXG4gICAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0ZU9ubHkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsT2JqZWN0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlUmVsYXRpb25VcGRhdGVzKFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIG9iamVjdC5vYmplY3RJZCxcbiAgICAgICAgICAgICAgb2JqZWN0LFxuICAgICAgICAgICAgICByZWxhdGlvblVwZGF0ZXNcbiAgICAgICAgICAgICkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiBzYW5pdGl6ZURhdGFiYXNlUmVzdWx0KG9yaWdpbmFsT2JqZWN0LCByZXN1bHQub3BzWzBdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICBjYW5BZGRGaWVsZChcbiAgICBzY2hlbWE6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlcixcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBvYmplY3Q6IGFueSxcbiAgICBhY2xHcm91cDogc3RyaW5nW10sXG4gICAgcnVuT3B0aW9uczogUXVlcnlPcHRpb25zXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNsYXNzU2NoZW1hID0gc2NoZW1hLnNjaGVtYURhdGFbY2xhc3NOYW1lXTtcbiAgICBpZiAoIWNsYXNzU2NoZW1hKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIGNvbnN0IGZpZWxkcyA9IE9iamVjdC5rZXlzKG9iamVjdCk7XG4gICAgY29uc3Qgc2NoZW1hRmllbGRzID0gT2JqZWN0LmtleXMoY2xhc3NTY2hlbWEuZmllbGRzKTtcbiAgICBjb25zdCBuZXdLZXlzID0gZmllbGRzLmZpbHRlcihmaWVsZCA9PiB7XG4gICAgICAvLyBTa2lwIGZpZWxkcyB0aGF0IGFyZSB1bnNldFxuICAgICAgaWYgKFxuICAgICAgICBvYmplY3RbZmllbGRdICYmXG4gICAgICAgIG9iamVjdFtmaWVsZF0uX19vcCAmJlxuICAgICAgICBvYmplY3RbZmllbGRdLl9fb3AgPT09ICdEZWxldGUnXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNjaGVtYUZpZWxkcy5pbmRleE9mKGZpZWxkKSA8IDA7XG4gICAgfSk7XG4gICAgaWYgKG5ld0tleXMubGVuZ3RoID4gMCkge1xuICAgICAgLy8gYWRkcyBhIG1hcmtlciB0aGF0IG5ldyBmaWVsZCBpcyBiZWluZyBhZGRpbmcgZHVyaW5nIHVwZGF0ZVxuICAgICAgcnVuT3B0aW9ucy5hZGRzRmllbGQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBhY3Rpb24gPSBydW5PcHRpb25zLmFjdGlvbjtcbiAgICAgIHJldHVybiBzY2hlbWEudmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZSwgYWNsR3JvdXAsICdhZGRGaWVsZCcsIGFjdGlvbik7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIFdvbid0IGRlbGV0ZSBjb2xsZWN0aW9ucyBpbiB0aGUgc3lzdGVtIG5hbWVzcGFjZVxuICAvKipcbiAgICogRGVsZXRlIGFsbCBjbGFzc2VzIGFuZCBjbGVhcnMgdGhlIHNjaGVtYSBjYWNoZVxuICAgKlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZhc3Qgc2V0IHRvIHRydWUgaWYgaXQncyBvayB0byBqdXN0IGRlbGV0ZSByb3dzIGFuZCBub3QgaW5kZXhlc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gd2hlbiB0aGUgZGVsZXRpb25zIGNvbXBsZXRlc1xuICAgKi9cbiAgZGVsZXRlRXZlcnl0aGluZyhmYXN0OiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPGFueT4ge1xuICAgIHRoaXMuc2NoZW1hUHJvbWlzZSA9IG51bGw7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFtcbiAgICAgIHRoaXMuYWRhcHRlci5kZWxldGVBbGxDbGFzc2VzKGZhc3QpLFxuICAgICAgdGhpcy5zY2hlbWFDYWNoZS5jbGVhcigpLFxuICAgIF0pO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEgbGlzdCBvZiByZWxhdGVkIGlkcyBnaXZlbiBhbiBvd25pbmcgaWQuXG4gIC8vIGNsYXNzTmFtZSBoZXJlIGlzIHRoZSBvd25pbmcgY2xhc3NOYW1lLlxuICByZWxhdGVkSWRzKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGtleTogc3RyaW5nLFxuICAgIG93bmluZ0lkOiBzdHJpbmcsXG4gICAgcXVlcnlPcHRpb25zOiBRdWVyeU9wdGlvbnNcbiAgKTogUHJvbWlzZTxBcnJheTxzdHJpbmc+PiB7XG4gICAgY29uc3QgeyBza2lwLCBsaW1pdCwgc29ydCB9ID0gcXVlcnlPcHRpb25zO1xuICAgIGNvbnN0IGZpbmRPcHRpb25zID0ge307XG4gICAgaWYgKHNvcnQgJiYgc29ydC5jcmVhdGVkQXQgJiYgdGhpcy5hZGFwdGVyLmNhblNvcnRPbkpvaW5UYWJsZXMpIHtcbiAgICAgIGZpbmRPcHRpb25zLnNvcnQgPSB7IF9pZDogc29ydC5jcmVhdGVkQXQgfTtcbiAgICAgIGZpbmRPcHRpb25zLmxpbWl0ID0gbGltaXQ7XG4gICAgICBmaW5kT3B0aW9ucy5za2lwID0gc2tpcDtcbiAgICAgIHF1ZXJ5T3B0aW9ucy5za2lwID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlclxuICAgICAgLmZpbmQoXG4gICAgICAgIGpvaW5UYWJsZU5hbWUoY2xhc3NOYW1lLCBrZXkpLFxuICAgICAgICByZWxhdGlvblNjaGVtYSxcbiAgICAgICAgeyBvd25pbmdJZCB9LFxuICAgICAgICBmaW5kT3B0aW9uc1xuICAgICAgKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiByZXN1bHRzLm1hcChyZXN1bHQgPT4gcmVzdWx0LnJlbGF0ZWRJZCkpO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEgbGlzdCBvZiBvd25pbmcgaWRzIGdpdmVuIHNvbWUgcmVsYXRlZCBpZHMuXG4gIC8vIGNsYXNzTmFtZSBoZXJlIGlzIHRoZSBvd25pbmcgY2xhc3NOYW1lLlxuICBvd25pbmdJZHMoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVsYXRlZElkczogc3RyaW5nW11cbiAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXJcbiAgICAgIC5maW5kKFxuICAgICAgICBqb2luVGFibGVOYW1lKGNsYXNzTmFtZSwga2V5KSxcbiAgICAgICAgcmVsYXRpb25TY2hlbWEsXG4gICAgICAgIHsgcmVsYXRlZElkOiB7ICRpbjogcmVsYXRlZElkcyB9IH0sXG4gICAgICAgIHt9XG4gICAgICApXG4gICAgICAudGhlbihyZXN1bHRzID0+IHJlc3VsdHMubWFwKHJlc3VsdCA9PiByZXN1bHQub3duaW5nSWQpKTtcbiAgfVxuXG4gIC8vIE1vZGlmaWVzIHF1ZXJ5IHNvIHRoYXQgaXQgbm8gbG9uZ2VyIGhhcyAkaW4gb24gcmVsYXRpb24gZmllbGRzLCBvclxuICAvLyBlcXVhbC10by1wb2ludGVyIGNvbnN0cmFpbnRzIG9uIHJlbGF0aW9uIGZpZWxkcy5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHF1ZXJ5IGlzIG11dGF0ZWRcbiAgcmVkdWNlSW5SZWxhdGlvbihjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IGFueSwgc2NoZW1hOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIFNlYXJjaCBmb3IgYW4gaW4tcmVsYXRpb24gb3IgZXF1YWwtdG8tcmVsYXRpb25cbiAgICAvLyBNYWtlIGl0IHNlcXVlbnRpYWwgZm9yIG5vdywgbm90IHN1cmUgb2YgcGFyYWxsZWl6YXRpb24gc2lkZSBlZmZlY3RzXG4gICAgaWYgKHF1ZXJ5Wyckb3InXSkge1xuICAgICAgY29uc3Qgb3JzID0gcXVlcnlbJyRvciddO1xuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgICBvcnMubWFwKChhUXVlcnksIGluZGV4KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucmVkdWNlSW5SZWxhdGlvbihjbGFzc05hbWUsIGFRdWVyeSwgc2NoZW1hKS50aGVuKFxuICAgICAgICAgICAgYVF1ZXJ5ID0+IHtcbiAgICAgICAgICAgICAgcXVlcnlbJyRvciddW2luZGV4XSA9IGFRdWVyeTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICAgKS50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShxdWVyeSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9taXNlcyA9IE9iamVjdC5rZXlzKHF1ZXJ5KS5tYXAoa2V5ID0+IHtcbiAgICAgIGNvbnN0IHQgPSBzY2hlbWEuZ2V0RXhwZWN0ZWRUeXBlKGNsYXNzTmFtZSwga2V5KTtcbiAgICAgIGlmICghdCB8fCB0LnR5cGUgIT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShxdWVyeSk7XG4gICAgICB9XG4gICAgICBsZXQgcXVlcmllczogPyhhbnlbXSkgPSBudWxsO1xuICAgICAgaWYgKFxuICAgICAgICBxdWVyeVtrZXldICYmXG4gICAgICAgIChxdWVyeVtrZXldWyckaW4nXSB8fFxuICAgICAgICAgIHF1ZXJ5W2tleV1bJyRuZSddIHx8XG4gICAgICAgICAgcXVlcnlba2V5XVsnJG5pbiddIHx8XG4gICAgICAgICAgcXVlcnlba2V5XS5fX3R5cGUgPT0gJ1BvaW50ZXInKVxuICAgICAgKSB7XG4gICAgICAgIC8vIEJ1aWxkIHRoZSBsaXN0IG9mIHF1ZXJpZXNcbiAgICAgICAgcXVlcmllcyA9IE9iamVjdC5rZXlzKHF1ZXJ5W2tleV0pLm1hcChjb25zdHJhaW50S2V5ID0+IHtcbiAgICAgICAgICBsZXQgcmVsYXRlZElkcztcbiAgICAgICAgICBsZXQgaXNOZWdhdGlvbiA9IGZhbHNlO1xuICAgICAgICAgIGlmIChjb25zdHJhaW50S2V5ID09PSAnb2JqZWN0SWQnKSB7XG4gICAgICAgICAgICByZWxhdGVkSWRzID0gW3F1ZXJ5W2tleV0ub2JqZWN0SWRdO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY29uc3RyYWludEtleSA9PSAnJGluJykge1xuICAgICAgICAgICAgcmVsYXRlZElkcyA9IHF1ZXJ5W2tleV1bJyRpbiddLm1hcChyID0+IHIub2JqZWN0SWQpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY29uc3RyYWludEtleSA9PSAnJG5pbicpIHtcbiAgICAgICAgICAgIGlzTmVnYXRpb24gPSB0cnVlO1xuICAgICAgICAgICAgcmVsYXRlZElkcyA9IHF1ZXJ5W2tleV1bJyRuaW4nXS5tYXAociA9PiByLm9iamVjdElkKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNvbnN0cmFpbnRLZXkgPT0gJyRuZScpIHtcbiAgICAgICAgICAgIGlzTmVnYXRpb24gPSB0cnVlO1xuICAgICAgICAgICAgcmVsYXRlZElkcyA9IFtxdWVyeVtrZXldWyckbmUnXS5vYmplY3RJZF07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlzTmVnYXRpb24sXG4gICAgICAgICAgICByZWxhdGVkSWRzLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcXVlcmllcyA9IFt7IGlzTmVnYXRpb246IGZhbHNlLCByZWxhdGVkSWRzOiBbXSB9XTtcbiAgICAgIH1cblxuICAgICAgLy8gcmVtb3ZlIHRoZSBjdXJyZW50IHF1ZXJ5S2V5IGFzIHdlIGRvbix0IG5lZWQgaXQgYW55bW9yZVxuICAgICAgZGVsZXRlIHF1ZXJ5W2tleV07XG4gICAgICAvLyBleGVjdXRlIGVhY2ggcXVlcnkgaW5kZXBlbmRlbnRseSB0byBidWlsZCB0aGUgbGlzdCBvZlxuICAgICAgLy8gJGluIC8gJG5pblxuICAgICAgY29uc3QgcHJvbWlzZXMgPSBxdWVyaWVzLm1hcChxID0+IHtcbiAgICAgICAgaWYgKCFxKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm93bmluZ0lkcyhjbGFzc05hbWUsIGtleSwgcS5yZWxhdGVkSWRzKS50aGVuKGlkcyA9PiB7XG4gICAgICAgICAgaWYgKHEuaXNOZWdhdGlvbikge1xuICAgICAgICAgICAgdGhpcy5hZGROb3RJbk9iamVjdElkc0lkcyhpZHMsIHF1ZXJ5KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hZGRJbk9iamVjdElkc0lkcyhpZHMsIHF1ZXJ5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHF1ZXJ5KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIE1vZGlmaWVzIHF1ZXJ5IHNvIHRoYXQgaXQgbm8gbG9uZ2VyIGhhcyAkcmVsYXRlZFRvXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBxdWVyeSBpcyBtdXRhdGVkXG4gIHJlZHVjZVJlbGF0aW9uS2V5cyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBxdWVyeTogYW55LFxuICAgIHF1ZXJ5T3B0aW9uczogYW55XG4gICk6ID9Qcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAocXVlcnlbJyRvciddKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICAgIHF1ZXJ5Wyckb3InXS5tYXAoYVF1ZXJ5ID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5yZWR1Y2VSZWxhdGlvbktleXMoY2xhc3NOYW1lLCBhUXVlcnksIHF1ZXJ5T3B0aW9ucyk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIHZhciByZWxhdGVkVG8gPSBxdWVyeVsnJHJlbGF0ZWRUbyddO1xuICAgIGlmIChyZWxhdGVkVG8pIHtcbiAgICAgIHJldHVybiB0aGlzLnJlbGF0ZWRJZHMoXG4gICAgICAgIHJlbGF0ZWRUby5vYmplY3QuY2xhc3NOYW1lLFxuICAgICAgICByZWxhdGVkVG8ua2V5LFxuICAgICAgICByZWxhdGVkVG8ub2JqZWN0Lm9iamVjdElkLFxuICAgICAgICBxdWVyeU9wdGlvbnNcbiAgICAgIClcbiAgICAgICAgLnRoZW4oaWRzID0+IHtcbiAgICAgICAgICBkZWxldGUgcXVlcnlbJyRyZWxhdGVkVG8nXTtcbiAgICAgICAgICB0aGlzLmFkZEluT2JqZWN0SWRzSWRzKGlkcywgcXVlcnkpO1xuICAgICAgICAgIHJldHVybiB0aGlzLnJlZHVjZVJlbGF0aW9uS2V5cyhjbGFzc05hbWUsIHF1ZXJ5LCBxdWVyeU9wdGlvbnMpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB7fSk7XG4gICAgfVxuICB9XG5cbiAgYWRkSW5PYmplY3RJZHNJZHMoaWRzOiA/QXJyYXk8c3RyaW5nPiA9IG51bGwsIHF1ZXJ5OiBhbnkpIHtcbiAgICBjb25zdCBpZHNGcm9tU3RyaW5nOiA/QXJyYXk8c3RyaW5nPiA9XG4gICAgICB0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT09ICdzdHJpbmcnID8gW3F1ZXJ5Lm9iamVjdElkXSA6IG51bGw7XG4gICAgY29uc3QgaWRzRnJvbUVxOiA/QXJyYXk8c3RyaW5nPiA9XG4gICAgICBxdWVyeS5vYmplY3RJZCAmJiBxdWVyeS5vYmplY3RJZFsnJGVxJ10gPyBbcXVlcnkub2JqZWN0SWRbJyRlcSddXSA6IG51bGw7XG4gICAgY29uc3QgaWRzRnJvbUluOiA/QXJyYXk8c3RyaW5nPiA9XG4gICAgICBxdWVyeS5vYmplY3RJZCAmJiBxdWVyeS5vYmplY3RJZFsnJGluJ10gPyBxdWVyeS5vYmplY3RJZFsnJGluJ10gOiBudWxsO1xuXG4gICAgLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG4gICAgY29uc3QgYWxsSWRzOiBBcnJheTxBcnJheTxzdHJpbmc+PiA9IFtcbiAgICAgIGlkc0Zyb21TdHJpbmcsXG4gICAgICBpZHNGcm9tRXEsXG4gICAgICBpZHNGcm9tSW4sXG4gICAgICBpZHMsXG4gICAgXS5maWx0ZXIobGlzdCA9PiBsaXN0ICE9PSBudWxsKTtcbiAgICBjb25zdCB0b3RhbExlbmd0aCA9IGFsbElkcy5yZWR1Y2UoKG1lbW8sIGxpc3QpID0+IG1lbW8gKyBsaXN0Lmxlbmd0aCwgMCk7XG5cbiAgICBsZXQgaWRzSW50ZXJzZWN0aW9uID0gW107XG4gICAgaWYgKHRvdGFsTGVuZ3RoID4gMTI1KSB7XG4gICAgICBpZHNJbnRlcnNlY3Rpb24gPSBpbnRlcnNlY3QuYmlnKGFsbElkcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlkc0ludGVyc2VjdGlvbiA9IGludGVyc2VjdChhbGxJZHMpO1xuICAgIH1cblxuICAgIC8vIE5lZWQgdG8gbWFrZSBzdXJlIHdlIGRvbid0IGNsb2JiZXIgZXhpc3Rpbmcgc2hvcnRoYW5kICRlcSBjb25zdHJhaW50cyBvbiBvYmplY3RJZC5cbiAgICBpZiAoISgnb2JqZWN0SWQnIGluIHF1ZXJ5KSkge1xuICAgICAgcXVlcnkub2JqZWN0SWQgPSB7XG4gICAgICAgICRpbjogdW5kZWZpbmVkLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBxdWVyeS5vYmplY3RJZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHF1ZXJ5Lm9iamVjdElkID0ge1xuICAgICAgICAkaW46IHVuZGVmaW5lZCxcbiAgICAgICAgJGVxOiBxdWVyeS5vYmplY3RJZCxcbiAgICAgIH07XG4gICAgfVxuICAgIHF1ZXJ5Lm9iamVjdElkWyckaW4nXSA9IGlkc0ludGVyc2VjdGlvbjtcblxuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIGFkZE5vdEluT2JqZWN0SWRzSWRzKGlkczogc3RyaW5nW10gPSBbXSwgcXVlcnk6IGFueSkge1xuICAgIGNvbnN0IGlkc0Zyb21OaW4gPVxuICAgICAgcXVlcnkub2JqZWN0SWQgJiYgcXVlcnkub2JqZWN0SWRbJyRuaW4nXSA/IHF1ZXJ5Lm9iamVjdElkWyckbmluJ10gOiBbXTtcbiAgICBsZXQgYWxsSWRzID0gWy4uLmlkc0Zyb21OaW4sIC4uLmlkc10uZmlsdGVyKGxpc3QgPT4gbGlzdCAhPT0gbnVsbCk7XG5cbiAgICAvLyBtYWtlIGEgc2V0IGFuZCBzcHJlYWQgdG8gcmVtb3ZlIGR1cGxpY2F0ZXNcbiAgICBhbGxJZHMgPSBbLi4ubmV3IFNldChhbGxJZHMpXTtcblxuICAgIC8vIE5lZWQgdG8gbWFrZSBzdXJlIHdlIGRvbid0IGNsb2JiZXIgZXhpc3Rpbmcgc2hvcnRoYW5kICRlcSBjb25zdHJhaW50cyBvbiBvYmplY3RJZC5cbiAgICBpZiAoISgnb2JqZWN0SWQnIGluIHF1ZXJ5KSkge1xuICAgICAgcXVlcnkub2JqZWN0SWQgPSB7XG4gICAgICAgICRuaW46IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBxdWVyeS5vYmplY3RJZCA9IHtcbiAgICAgICAgJG5pbjogdW5kZWZpbmVkLFxuICAgICAgICAkZXE6IHF1ZXJ5Lm9iamVjdElkLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBxdWVyeS5vYmplY3RJZFsnJG5pbiddID0gYWxsSWRzO1xuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIC8vIFJ1bnMgYSBxdWVyeSBvbiB0aGUgZGF0YWJhc2UuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBsaXN0IG9mIGl0ZW1zLlxuICAvLyBPcHRpb25zOlxuICAvLyAgIHNraXAgICAgbnVtYmVyIG9mIHJlc3VsdHMgdG8gc2tpcC5cbiAgLy8gICBsaW1pdCAgIGxpbWl0IHRvIHRoaXMgbnVtYmVyIG9mIHJlc3VsdHMuXG4gIC8vICAgc29ydCAgICBhbiBvYmplY3Qgd2hlcmUga2V5cyBhcmUgdGhlIGZpZWxkcyB0byBzb3J0IGJ5LlxuICAvLyAgICAgICAgICAgdGhlIHZhbHVlIGlzICsxIGZvciBhc2NlbmRpbmcsIC0xIGZvciBkZXNjZW5kaW5nLlxuICAvLyAgIGNvdW50ICAgcnVuIGEgY291bnQgaW5zdGVhZCBvZiByZXR1cm5pbmcgcmVzdWx0cy5cbiAgLy8gICBhY2wgICAgIHJlc3RyaWN0IHRoaXMgb3BlcmF0aW9uIHdpdGggYW4gQUNMIGZvciB0aGUgcHJvdmlkZWQgYXJyYXlcbiAgLy8gICAgICAgICAgIG9mIHVzZXIgb2JqZWN0SWRzIGFuZCByb2xlcy4gYWNsOiBudWxsIG1lYW5zIG5vIHVzZXIuXG4gIC8vICAgICAgICAgICB3aGVuIHRoaXMgZmllbGQgaXMgbm90IHByZXNlbnQsIGRvbid0IGRvIGFueXRoaW5nIHJlZ2FyZGluZyBBQ0xzLlxuICAvLyAgY2FzZUluc2Vuc2l0aXZlIG1ha2Ugc3RyaW5nIGNvbXBhcmlzb25zIGNhc2UgaW5zZW5zaXRpdmVcbiAgLy8gVE9ETzogbWFrZSB1c2VySWRzIG5vdCBuZWVkZWQgaGVyZS4gVGhlIGRiIGFkYXB0ZXIgc2hvdWxkbid0IGtub3dcbiAgLy8gYW55dGhpbmcgYWJvdXQgdXNlcnMsIGlkZWFsbHkuIFRoZW4sIGltcHJvdmUgdGhlIGZvcm1hdCBvZiB0aGUgQUNMXG4gIC8vIGFyZyB0byB3b3JrIGxpa2UgdGhlIG90aGVycy5cbiAgZmluZChcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBxdWVyeTogYW55LFxuICAgIHtcbiAgICAgIHNraXAsXG4gICAgICBsaW1pdCxcbiAgICAgIGFjbCxcbiAgICAgIHNvcnQgPSB7fSxcbiAgICAgIGNvdW50LFxuICAgICAga2V5cyxcbiAgICAgIG9wLFxuICAgICAgZGlzdGluY3QsXG4gICAgICBwaXBlbGluZSxcbiAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgaGludCxcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZSA9IGZhbHNlLFxuICAgICAgZXhwbGFpbixcbiAgICB9OiBhbnkgPSB7fSxcbiAgICBhdXRoOiBhbnkgPSB7fSxcbiAgICB2YWxpZFNjaGVtYUNvbnRyb2xsZXI6IFNjaGVtYUNvbnRyb2xsZXIuU2NoZW1hQ29udHJvbGxlclxuICApOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IGlzTWFzdGVyID0gYWNsID09PSB1bmRlZmluZWQ7XG4gICAgY29uc3QgYWNsR3JvdXAgPSBhY2wgfHwgW107XG4gICAgb3AgPVxuICAgICAgb3AgfHxcbiAgICAgICh0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT0gJ3N0cmluZycgJiYgT2JqZWN0LmtleXMocXVlcnkpLmxlbmd0aCA9PT0gMVxuICAgICAgICA/ICdnZXQnXG4gICAgICAgIDogJ2ZpbmQnKTtcbiAgICAvLyBDb3VudCBvcGVyYXRpb24gaWYgY291bnRpbmdcbiAgICBvcCA9IGNvdW50ID09PSB0cnVlID8gJ2NvdW50JyA6IG9wO1xuXG4gICAgbGV0IGNsYXNzRXhpc3RzID0gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hSWZOZWVkZWQodmFsaWRTY2hlbWFDb250cm9sbGVyKS50aGVuKFxuICAgICAgc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgICAgIC8vQWxsb3cgdm9sYXRpbGUgY2xhc3NlcyBpZiBxdWVyeWluZyB3aXRoIE1hc3RlciAoZm9yIF9QdXNoU3RhdHVzKVxuICAgICAgICAvL1RPRE86IE1vdmUgdm9sYXRpbGUgY2xhc3NlcyBjb25jZXB0IGludG8gbW9uZ28gYWRhcHRlciwgcG9zdGdyZXMgYWRhcHRlciBzaG91bGRuJ3QgY2FyZVxuICAgICAgICAvL3RoYXQgYXBpLnBhcnNlLmNvbSBicmVha3Mgd2hlbiBfUHVzaFN0YXR1cyBleGlzdHMgaW4gbW9uZ28uXG4gICAgICAgIHJldHVybiBzY2hlbWFDb250cm9sbGVyXG4gICAgICAgICAgLmdldE9uZVNjaGVtYShjbGFzc05hbWUsIGlzTWFzdGVyKVxuICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAvLyBCZWhhdmlvciBmb3Igbm9uLWV4aXN0ZW50IGNsYXNzZXMgaXMga2luZGEgd2VpcmQgb24gUGFyc2UuY29tLiBQcm9iYWJseSBkb2Vzbid0IG1hdHRlciB0b28gbXVjaC5cbiAgICAgICAgICAgIC8vIEZvciBub3csIHByZXRlbmQgdGhlIGNsYXNzIGV4aXN0cyBidXQgaGFzIG5vIG9iamVjdHMsXG4gICAgICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjbGFzc0V4aXN0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXR1cm4geyBmaWVsZHM6IHt9IH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKHNjaGVtYSA9PiB7XG4gICAgICAgICAgICAvLyBQYXJzZS5jb20gdHJlYXRzIHF1ZXJpZXMgb24gX2NyZWF0ZWRfYXQgYW5kIF91cGRhdGVkX2F0IGFzIGlmIHRoZXkgd2VyZSBxdWVyaWVzIG9uIGNyZWF0ZWRBdCBhbmQgdXBkYXRlZEF0LFxuICAgICAgICAgICAgLy8gc28gZHVwbGljYXRlIHRoYXQgYmVoYXZpb3IgaGVyZS4gSWYgYm90aCBhcmUgc3BlY2lmaWVkLCB0aGUgY29ycmVjdCBiZWhhdmlvciB0byBtYXRjaCBQYXJzZS5jb20gaXMgdG9cbiAgICAgICAgICAgIC8vIHVzZSB0aGUgb25lIHRoYXQgYXBwZWFycyBmaXJzdCBpbiB0aGUgc29ydCBsaXN0LlxuICAgICAgICAgICAgaWYgKHNvcnQuX2NyZWF0ZWRfYXQpIHtcbiAgICAgICAgICAgICAgc29ydC5jcmVhdGVkQXQgPSBzb3J0Ll9jcmVhdGVkX2F0O1xuICAgICAgICAgICAgICBkZWxldGUgc29ydC5fY3JlYXRlZF9hdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzb3J0Ll91cGRhdGVkX2F0KSB7XG4gICAgICAgICAgICAgIHNvcnQudXBkYXRlZEF0ID0gc29ydC5fdXBkYXRlZF9hdDtcbiAgICAgICAgICAgICAgZGVsZXRlIHNvcnQuX3VwZGF0ZWRfYXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBxdWVyeU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgIHNraXAsXG4gICAgICAgICAgICAgIGxpbWl0LFxuICAgICAgICAgICAgICBzb3J0LFxuICAgICAgICAgICAgICBrZXlzLFxuICAgICAgICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgICAgaGludCxcbiAgICAgICAgICAgICAgY2FzZUluc2Vuc2l0aXZlLFxuICAgICAgICAgICAgICBleHBsYWluLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHNvcnQpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICAgICAgaWYgKGZpZWxkTmFtZS5tYXRjaCgvXmF1dGhEYXRhXFwuKFthLXpBLVowLTlfXSspXFwuaWQkLykpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICAgICAgICAgICAgYENhbm5vdCBzb3J0IGJ5ICR7ZmllbGROYW1lfWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNvbnN0IHJvb3RGaWVsZE5hbWUgPSBnZXRSb290RmllbGROYW1lKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICAgIGlmICghU2NoZW1hQ29udHJvbGxlci5maWVsZE5hbWVJc1ZhbGlkKHJvb3RGaWVsZE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICAgICAgICAgICAgIGBJbnZhbGlkIGZpZWxkIG5hbWU6ICR7ZmllbGROYW1lfS5gXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gKGlzTWFzdGVyXG4gICAgICAgICAgICAgID8gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAgICAgOiBzY2hlbWFDb250cm9sbGVyLnZhbGlkYXRlUGVybWlzc2lvbihjbGFzc05hbWUsIGFjbEdyb3VwLCBvcClcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLnRoZW4oKCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnJlZHVjZVJlbGF0aW9uS2V5cyhjbGFzc05hbWUsIHF1ZXJ5LCBxdWVyeU9wdGlvbnMpXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLnRoZW4oKCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnJlZHVjZUluUmVsYXRpb24oY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hQ29udHJvbGxlcilcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IHByb3RlY3RlZEZpZWxkcztcbiAgICAgICAgICAgICAgICBpZiAoIWlzTWFzdGVyKSB7XG4gICAgICAgICAgICAgICAgICBxdWVyeSA9IHRoaXMuYWRkUG9pbnRlclBlcm1pc3Npb25zKFxuICAgICAgICAgICAgICAgICAgICBzY2hlbWFDb250cm9sbGVyLFxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgICAgIG9wLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgYWNsR3JvdXBcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAvKiBEb24ndCB1c2UgcHJvamVjdGlvbnMgdG8gb3B0aW1pemUgdGhlIHByb3RlY3RlZEZpZWxkcyBzaW5jZSB0aGUgcHJvdGVjdGVkRmllbGRzXG4gICAgICAgICAgICAgICAgICBiYXNlZCBvbiBwb2ludGVyLXBlcm1pc3Npb25zIGFyZSBkZXRlcm1pbmVkIGFmdGVyIHF1ZXJ5aW5nLiBUaGUgZmlsdGVyaW5nIGNhblxuICAgICAgICAgICAgICAgICAgb3ZlcndyaXRlIHRoZSBwcm90ZWN0ZWQgZmllbGRzLiAqL1xuICAgICAgICAgICAgICAgICAgcHJvdGVjdGVkRmllbGRzID0gdGhpcy5hZGRQcm90ZWN0ZWRGaWVsZHMoXG4gICAgICAgICAgICAgICAgICAgIHNjaGVtYUNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgICAgIGFjbEdyb3VwLFxuICAgICAgICAgICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeU9wdGlvbnNcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghcXVlcnkpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChvcCA9PT0gJ2dldCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQuJ1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWlzTWFzdGVyKSB7XG4gICAgICAgICAgICAgICAgICBpZiAob3AgPT09ICd1cGRhdGUnIHx8IG9wID09PSAnZGVsZXRlJykge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IGFkZFdyaXRlQUNMKHF1ZXJ5LCBhY2xHcm91cCk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IGFkZFJlYWRBQ0wocXVlcnksIGFjbEdyb3VwKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFsaWRhdGVRdWVyeShxdWVyeSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50KSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXNzRXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5jb3VudChcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICBoaW50XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkaXN0aW5jdCkge1xuICAgICAgICAgICAgICAgICAgaWYgKCFjbGFzc0V4aXN0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmRpc3RpbmN0KFxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgICAgICAgICAgICAgZGlzdGluY3RcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBpcGVsaW5lKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXNzRXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuYWdncmVnYXRlKFxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgICAgICAgICAgICAgcGlwZWxpbmUsXG4gICAgICAgICAgICAgICAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICAgICAgICAgICAgaGludCxcbiAgICAgICAgICAgICAgICAgICAgICBleHBsYWluXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChleHBsYWluKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmZpbmQoXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICBxdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgcXVlcnlPcHRpb25zXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyXG4gICAgICAgICAgICAgICAgICAgIC5maW5kKGNsYXNzTmFtZSwgc2NoZW1hLCBxdWVyeSwgcXVlcnlPcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICAudGhlbihvYmplY3RzID0+XG4gICAgICAgICAgICAgICAgICAgICAgb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdCA9IHVudHJhbnNmb3JtT2JqZWN0QUNMKG9iamVjdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmlsdGVyU2Vuc2l0aXZlRGF0YShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaXNNYXN0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGFjbEdyb3VwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBvcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NoZW1hQ29udHJvbGxlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWN0ZWRGaWVsZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBkZWxldGVTY2hlbWEoY2xhc3NOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYShjbGFzc05hbWUsIHRydWUpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4geyBmaWVsZHM6IHt9IH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAudGhlbigoc2NoZW1hOiBhbnkpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sbGVjdGlvbkV4aXN0cyhjbGFzc05hbWUpXG4gICAgICAgICAgLnRoZW4oKCkgPT5cbiAgICAgICAgICAgIHRoaXMuYWRhcHRlci5jb3VudChjbGFzc05hbWUsIHsgZmllbGRzOiB7fSB9LCBudWxsLCAnJywgZmFsc2UpXG4gICAgICAgICAgKVxuICAgICAgICAgIC50aGVuKGNvdW50ID0+IHtcbiAgICAgICAgICAgIGlmIChjb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIDI1NSxcbiAgICAgICAgICAgICAgICBgQ2xhc3MgJHtjbGFzc05hbWV9IGlzIG5vdCBlbXB0eSwgY29udGFpbnMgJHtjb3VudH0gb2JqZWN0cywgY2Fubm90IGRyb3Agc2NoZW1hLmBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuZGVsZXRlQ2xhc3MoY2xhc3NOYW1lKTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKHdhc1BhcnNlQ29sbGVjdGlvbiA9PiB7XG4gICAgICAgICAgICBpZiAod2FzUGFyc2VDb2xsZWN0aW9uKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJlbGF0aW9uRmllbGROYW1lcyA9IE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLmZpbHRlcihcbiAgICAgICAgICAgICAgICBmaWVsZE5hbWUgPT4gc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdSZWxhdGlvbidcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgICAgICAgICAgIHJlbGF0aW9uRmllbGROYW1lcy5tYXAobmFtZSA9PlxuICAgICAgICAgICAgICAgICAgdGhpcy5hZGFwdGVyLmRlbGV0ZUNsYXNzKGpvaW5UYWJsZU5hbWUoY2xhc3NOYW1lLCBuYW1lKSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gQ29uc3RyYWludHMgcXVlcnkgdXNpbmcgQ0xQJ3MgcG9pbnRlciBwZXJtaXNzaW9ucyAoUFApIGlmIGFueS5cbiAgLy8gMS4gRXRyYWN0IHRoZSB1c2VyIGlkIGZyb20gY2FsbGVyJ3MgQUNMZ3JvdXA7XG4gIC8vIDIuIEV4Y3RyYWN0IGEgbGlzdCBvZiBmaWVsZCBuYW1lcyB0aGF0IGFyZSBQUCBmb3IgdGFyZ2V0IGNvbGxlY3Rpb24gYW5kIG9wZXJhdGlvbjtcbiAgLy8gMy4gQ29uc3RyYWludCB0aGUgb3JpZ2luYWwgcXVlcnkgc28gdGhhdCBlYWNoIFBQIGZpZWxkIG11c3RcbiAgLy8gcG9pbnQgdG8gY2FsbGVyJ3MgaWQgKG9yIGNvbnRhaW4gaXQgaW4gY2FzZSBvZiBQUCBmaWVsZCBiZWluZyBhbiBhcnJheSlcbiAgYWRkUG9pbnRlclBlcm1pc3Npb25zKFxuICAgIHNjaGVtYTogU2NoZW1hQ29udHJvbGxlci5TY2hlbWFDb250cm9sbGVyLFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIG9wZXJhdGlvbjogc3RyaW5nLFxuICAgIHF1ZXJ5OiBhbnksXG4gICAgYWNsR3JvdXA6IGFueVtdID0gW11cbiAgKTogYW55IHtcbiAgICAvLyBDaGVjayBpZiBjbGFzcyBoYXMgcHVibGljIHBlcm1pc3Npb24gZm9yIG9wZXJhdGlvblxuICAgIC8vIElmIHRoZSBCYXNlQ0xQIHBhc3MsIGxldCBnbyB0aHJvdWdoXG4gICAgaWYgKHNjaGVtYS50ZXN0UGVybWlzc2lvbnNGb3JDbGFzc05hbWUoY2xhc3NOYW1lLCBhY2xHcm91cCwgb3BlcmF0aW9uKSkge1xuICAgICAgcmV0dXJuIHF1ZXJ5O1xuICAgIH1cbiAgICBjb25zdCBwZXJtcyA9IHNjaGVtYS5nZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lKTtcblxuICAgIGNvbnN0IHVzZXJBQ0wgPSBhY2xHcm91cC5maWx0ZXIoYWNsID0+IHtcbiAgICAgIHJldHVybiBhY2wuaW5kZXhPZigncm9sZTonKSAhPSAwICYmIGFjbCAhPSAnKic7XG4gICAgfSk7XG5cbiAgICBjb25zdCBncm91cEtleSA9XG4gICAgICBbJ2dldCcsICdmaW5kJywgJ2NvdW50J10uaW5kZXhPZihvcGVyYXRpb24pID4gLTFcbiAgICAgICAgPyAncmVhZFVzZXJGaWVsZHMnXG4gICAgICAgIDogJ3dyaXRlVXNlckZpZWxkcyc7XG5cbiAgICBjb25zdCBwZXJtRmllbGRzID0gW107XG5cbiAgICBpZiAocGVybXNbb3BlcmF0aW9uXSAmJiBwZXJtc1tvcGVyYXRpb25dLnBvaW50ZXJGaWVsZHMpIHtcbiAgICAgIHBlcm1GaWVsZHMucHVzaCguLi5wZXJtc1tvcGVyYXRpb25dLnBvaW50ZXJGaWVsZHMpO1xuICAgIH1cblxuICAgIGlmIChwZXJtc1tncm91cEtleV0pIHtcbiAgICAgIGZvciAoY29uc3QgZmllbGQgb2YgcGVybXNbZ3JvdXBLZXldKSB7XG4gICAgICAgIGlmICghcGVybUZpZWxkcy5pbmNsdWRlcyhmaWVsZCkpIHtcbiAgICAgICAgICBwZXJtRmllbGRzLnB1c2goZmllbGQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIHRoZSBBQ0wgc2hvdWxkIGhhdmUgZXhhY3RseSAxIHVzZXJcbiAgICBpZiAocGVybUZpZWxkcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyB0aGUgQUNMIHNob3VsZCBoYXZlIGV4YWN0bHkgMSB1c2VyXG4gICAgICAvLyBObyB1c2VyIHNldCByZXR1cm4gdW5kZWZpbmVkXG4gICAgICAvLyBJZiB0aGUgbGVuZ3RoIGlzID4gMSwgdGhhdCBtZWFucyB3ZSBkaWRuJ3QgZGUtZHVwZSB1c2VycyBjb3JyZWN0bHlcbiAgICAgIGlmICh1c2VyQUNMLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVzZXJJZCA9IHVzZXJBQ0xbMF07XG4gICAgICBjb25zdCB1c2VyUG9pbnRlciA9IHtcbiAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgIGNsYXNzTmFtZTogJ19Vc2VyJyxcbiAgICAgICAgb2JqZWN0SWQ6IHVzZXJJZCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG9ycyA9IHBlcm1GaWVsZHMuZmxhdE1hcChrZXkgPT4ge1xuICAgICAgICAvLyBjb25zdHJhaW50IGZvciBzaW5nbGUgcG9pbnRlciBzZXR1cFxuICAgICAgICBjb25zdCBxID0ge1xuICAgICAgICAgIFtrZXldOiB1c2VyUG9pbnRlcixcbiAgICAgICAgfTtcbiAgICAgICAgLy8gY29uc3RyYWludCBmb3IgdXNlcnMtYXJyYXkgc2V0dXBcbiAgICAgICAgY29uc3QgcWEgPSB7XG4gICAgICAgICAgW2tleV06IHsgJGFsbDogW3VzZXJQb2ludGVyXSB9LFxuICAgICAgICB9O1xuICAgICAgICAvLyBpZiB3ZSBhbHJlYWR5IGhhdmUgYSBjb25zdHJhaW50IG9uIHRoZSBrZXksIHVzZSB0aGUgJGFuZFxuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHF1ZXJ5LCBrZXkpKSB7XG4gICAgICAgICAgcmV0dXJuIFt7ICRhbmQ6IFtxLCBxdWVyeV0gfSwgeyAkYW5kOiBbcWEsIHF1ZXJ5XSB9XTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UganVzdCBhZGQgdGhlIGNvbnN0YWludFxuICAgICAgICByZXR1cm4gW09iamVjdC5hc3NpZ24oe30sIHF1ZXJ5LCBxKSwgT2JqZWN0LmFzc2lnbih7fSwgcXVlcnksIHFhKV07XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7ICRvcjogb3JzIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBxdWVyeTtcbiAgICB9XG4gIH1cblxuICBhZGRQcm90ZWN0ZWRGaWVsZHMoXG4gICAgc2NoZW1hOiBTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXIsXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgcXVlcnk6IGFueSA9IHt9LFxuICAgIGFjbEdyb3VwOiBhbnlbXSA9IFtdLFxuICAgIGF1dGg6IGFueSA9IHt9LFxuICAgIHF1ZXJ5T3B0aW9uczogRnVsbFF1ZXJ5T3B0aW9ucyA9IHt9XG4gICk6IG51bGwgfCBzdHJpbmdbXSB7XG4gICAgY29uc3QgcGVybXMgPSBzY2hlbWEuZ2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKGNsYXNzTmFtZSk7XG4gICAgaWYgKCFwZXJtcykgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCBwcm90ZWN0ZWRGaWVsZHMgPSBwZXJtcy5wcm90ZWN0ZWRGaWVsZHM7XG4gICAgaWYgKCFwcm90ZWN0ZWRGaWVsZHMpIHJldHVybiBudWxsO1xuXG4gICAgaWYgKGFjbEdyb3VwLmluZGV4T2YocXVlcnkub2JqZWN0SWQpID4gLTEpIHJldHVybiBudWxsO1xuXG4gICAgLy8gZm9yIHF1ZXJpZXMgd2hlcmUgXCJrZXlzXCIgYXJlIHNldCBhbmQgZG8gbm90IGluY2x1ZGUgYWxsICd1c2VyRmllbGQnOntmaWVsZH0sXG4gICAgLy8gd2UgaGF2ZSB0byB0cmFuc3BhcmVudGx5IGluY2x1ZGUgaXQsIGFuZCB0aGVuIHJlbW92ZSBiZWZvcmUgcmV0dXJuaW5nIHRvIGNsaWVudFxuICAgIC8vIEJlY2F1c2UgaWYgc3VjaCBrZXkgbm90IHByb2plY3RlZCB0aGUgcGVybWlzc2lvbiB3b24ndCBiZSBlbmZvcmNlZCBwcm9wZXJseVxuICAgIC8vIFBTIHRoaXMgaXMgY2FsbGVkIHdoZW4gJ2V4Y2x1ZGVLZXlzJyBhbHJlYWR5IHJlZHVjZWQgdG8gJ2tleXMnXG4gICAgY29uc3QgcHJlc2VydmVLZXlzID0gcXVlcnlPcHRpb25zLmtleXM7XG5cbiAgICAvLyB0aGVzZSBhcmUga2V5cyB0aGF0IG5lZWQgdG8gYmUgaW5jbHVkZWQgb25seVxuICAgIC8vIHRvIGJlIGFibGUgdG8gYXBwbHkgcHJvdGVjdGVkRmllbGRzIGJ5IHBvaW50ZXJcbiAgICAvLyBhbmQgdGhlbiB1bnNldCBiZWZvcmUgcmV0dXJuaW5nIHRvIGNsaWVudCAobGF0ZXIgaW4gIGZpbHRlclNlbnNpdGl2ZUZpZWxkcylcbiAgICBjb25zdCBzZXJ2ZXJPbmx5S2V5cyA9IFtdO1xuXG4gICAgY29uc3QgYXV0aGVudGljYXRlZCA9IGF1dGgudXNlcjtcblxuICAgIC8vIG1hcCB0byBhbGxvdyBjaGVjayB3aXRob3V0IGFycmF5IHNlYXJjaFxuICAgIGNvbnN0IHJvbGVzID0gKGF1dGgudXNlclJvbGVzIHx8IFtdKS5yZWR1Y2UoKGFjYywgcikgPT4ge1xuICAgICAgYWNjW3JdID0gcHJvdGVjdGVkRmllbGRzW3JdO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB7fSk7XG5cbiAgICAvLyBhcnJheSBvZiBzZXRzIG9mIHByb3RlY3RlZCBmaWVsZHMuIHNlcGFyYXRlIGl0ZW0gZm9yIGVhY2ggYXBwbGljYWJsZSBjcml0ZXJpYVxuICAgIGNvbnN0IHByb3RlY3RlZEtleXNTZXRzID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGtleSBpbiBwcm90ZWN0ZWRGaWVsZHMpIHtcbiAgICAgIC8vIHNraXAgdXNlckZpZWxkc1xuICAgICAgaWYgKGtleS5zdGFydHNXaXRoKCd1c2VyRmllbGQ6JykpIHtcbiAgICAgICAgaWYgKHByZXNlcnZlS2V5cykge1xuICAgICAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGtleS5zdWJzdHJpbmcoMTApO1xuICAgICAgICAgIGlmICghcHJlc2VydmVLZXlzLmluY2x1ZGVzKGZpZWxkTmFtZSkpIHtcbiAgICAgICAgICAgIC8vIDEuIHB1dCBpdCB0aGVyZSB0ZW1wb3JhcmlseVxuICAgICAgICAgICAgcXVlcnlPcHRpb25zLmtleXMgJiYgcXVlcnlPcHRpb25zLmtleXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICAgICAgLy8gMi4gcHJlc2VydmUgaXQgZGVsZXRlIGxhdGVyXG4gICAgICAgICAgICBzZXJ2ZXJPbmx5S2V5cy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBhZGQgcHVibGljIHRpZXJcbiAgICAgIGlmIChrZXkgPT09ICcqJykge1xuICAgICAgICBwcm90ZWN0ZWRLZXlzU2V0cy5wdXNoKHByb3RlY3RlZEZpZWxkc1trZXldKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChhdXRoZW50aWNhdGVkKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICdhdXRoZW50aWNhdGVkJykge1xuICAgICAgICAgIC8vIGZvciBsb2dnZWQgaW4gdXNlcnNcbiAgICAgICAgICBwcm90ZWN0ZWRLZXlzU2V0cy5wdXNoKHByb3RlY3RlZEZpZWxkc1trZXldKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyb2xlc1trZXldICYmIGtleS5zdGFydHNXaXRoKCdyb2xlOicpKSB7XG4gICAgICAgICAgLy8gYWRkIGFwcGxpY2FibGUgcm9sZXNcbiAgICAgICAgICBwcm90ZWN0ZWRLZXlzU2V0cy5wdXNoKHJvbGVzW2tleV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gY2hlY2sgaWYgdGhlcmUncyBhIHJ1bGUgZm9yIGN1cnJlbnQgdXNlcidzIGlkXG4gICAgaWYgKGF1dGhlbnRpY2F0ZWQpIHtcbiAgICAgIGNvbnN0IHVzZXJJZCA9IGF1dGgudXNlci5pZDtcbiAgICAgIGlmIChwZXJtcy5wcm90ZWN0ZWRGaWVsZHNbdXNlcklkXSkge1xuICAgICAgICBwcm90ZWN0ZWRLZXlzU2V0cy5wdXNoKHBlcm1zLnByb3RlY3RlZEZpZWxkc1t1c2VySWRdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBwcmVzZXJ2ZSBmaWVsZHMgdG8gYmUgcmVtb3ZlZCBiZWZvcmUgc2VuZGluZyByZXNwb25zZSB0byBjbGllbnRcbiAgICBpZiAoc2VydmVyT25seUtleXMubGVuZ3RoID4gMCkge1xuICAgICAgcGVybXMucHJvdGVjdGVkRmllbGRzLnRlbXBvcmFyeUtleXMgPSBzZXJ2ZXJPbmx5S2V5cztcbiAgICB9XG5cbiAgICBsZXQgcHJvdGVjdGVkS2V5cyA9IHByb3RlY3RlZEtleXNTZXRzLnJlZHVjZSgoYWNjLCBuZXh0KSA9PiB7XG4gICAgICBpZiAobmV4dCkge1xuICAgICAgICBhY2MucHVzaCguLi5uZXh0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwgW10pO1xuXG4gICAgLy8gaW50ZXJzZWN0IGFsbCBzZXRzIG9mIHByb3RlY3RlZEZpZWxkc1xuICAgIHByb3RlY3RlZEtleXNTZXRzLmZvckVhY2goZmllbGRzID0+IHtcbiAgICAgIGlmIChmaWVsZHMpIHtcbiAgICAgICAgcHJvdGVjdGVkS2V5cyA9IHByb3RlY3RlZEtleXMuZmlsdGVyKHYgPT4gZmllbGRzLmluY2x1ZGVzKHYpKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBwcm90ZWN0ZWRLZXlzO1xuICB9XG5cbiAgY3JlYXRlVHJhbnNhY3Rpb25hbFNlc3Npb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlclxuICAgICAgLmNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uKClcbiAgICAgIC50aGVuKHRyYW5zYWN0aW9uYWxTZXNzaW9uID0+IHtcbiAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb24gPSB0cmFuc2FjdGlvbmFsU2Vzc2lvbjtcbiAgICAgIH0pO1xuICB9XG5cbiAgY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24oKSB7XG4gICAgaWYgKCF0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGVyZSBpcyBubyB0cmFuc2FjdGlvbmFsIHNlc3Npb24gdG8gY29tbWl0Jyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFkYXB0ZXJcbiAgICAgIC5jb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbih0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvbilcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb24gPSBudWxsO1xuICAgICAgfSk7XG4gIH1cblxuICBhYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uKCkge1xuICAgIGlmICghdGhpcy5fdHJhbnNhY3Rpb25hbFNlc3Npb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgaXMgbm8gdHJhbnNhY3Rpb25hbCBzZXNzaW9uIHRvIGFib3J0Jyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFkYXB0ZXJcbiAgICAgIC5hYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uKHRoaXMuX3RyYW5zYWN0aW9uYWxTZXNzaW9uKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLl90cmFuc2FjdGlvbmFsU2Vzc2lvbiA9IG51bGw7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFRPRE86IGNyZWF0ZSBpbmRleGVzIG9uIGZpcnN0IGNyZWF0aW9uIG9mIGEgX1VzZXIgb2JqZWN0LiBPdGhlcndpc2UgaXQncyBpbXBvc3NpYmxlIHRvXG4gIC8vIGhhdmUgYSBQYXJzZSBhcHAgd2l0aG91dCBpdCBoYXZpbmcgYSBfVXNlciBjb2xsZWN0aW9uLlxuICBwZXJmb3JtSW5pdGlhbGl6YXRpb24oKSB7XG4gICAgY29uc3QgcmVxdWlyZWRVc2VyRmllbGRzID0ge1xuICAgICAgZmllbGRzOiB7XG4gICAgICAgIC4uLlNjaGVtYUNvbnRyb2xsZXIuZGVmYXVsdENvbHVtbnMuX0RlZmF1bHQsXG4gICAgICAgIC4uLlNjaGVtYUNvbnRyb2xsZXIuZGVmYXVsdENvbHVtbnMuX1VzZXIsXG4gICAgICB9LFxuICAgIH07XG4gICAgY29uc3QgcmVxdWlyZWRSb2xlRmllbGRzID0ge1xuICAgICAgZmllbGRzOiB7XG4gICAgICAgIC4uLlNjaGVtYUNvbnRyb2xsZXIuZGVmYXVsdENvbHVtbnMuX0RlZmF1bHQsXG4gICAgICAgIC4uLlNjaGVtYUNvbnRyb2xsZXIuZGVmYXVsdENvbHVtbnMuX1JvbGUsXG4gICAgICB9LFxuICAgIH07XG5cbiAgICBjb25zdCB1c2VyQ2xhc3NQcm9taXNlID0gdGhpcy5sb2FkU2NoZW1hKCkudGhlbihzY2hlbWEgPT5cbiAgICAgIHNjaGVtYS5lbmZvcmNlQ2xhc3NFeGlzdHMoJ19Vc2VyJylcbiAgICApO1xuICAgIGNvbnN0IHJvbGVDbGFzc1Byb21pc2UgPSB0aGlzLmxvYWRTY2hlbWEoKS50aGVuKHNjaGVtYSA9PlxuICAgICAgc2NoZW1hLmVuZm9yY2VDbGFzc0V4aXN0cygnX1JvbGUnKVxuICAgICk7XG5cbiAgICBjb25zdCB1c2VybmFtZVVuaXF1ZW5lc3MgPSB1c2VyQ2xhc3NQcm9taXNlXG4gICAgICAudGhlbigoKSA9PlxuICAgICAgICB0aGlzLmFkYXB0ZXIuZW5zdXJlVW5pcXVlbmVzcygnX1VzZXInLCByZXF1aXJlZFVzZXJGaWVsZHMsIFsndXNlcm5hbWUnXSlcbiAgICAgIClcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdVbmFibGUgdG8gZW5zdXJlIHVuaXF1ZW5lc3MgZm9yIHVzZXJuYW1lczogJywgZXJyb3IpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgdXNlcm5hbWVDYXNlSW5zZW5zaXRpdmVJbmRleCA9IHVzZXJDbGFzc1Byb21pc2VcbiAgICAgIC50aGVuKCgpID0+XG4gICAgICAgIHRoaXMuYWRhcHRlci5lbnN1cmVJbmRleChcbiAgICAgICAgICAnX1VzZXInLFxuICAgICAgICAgIHJlcXVpcmVkVXNlckZpZWxkcyxcbiAgICAgICAgICBbJ3VzZXJuYW1lJ10sXG4gICAgICAgICAgJ2Nhc2VfaW5zZW5zaXRpdmVfdXNlcm5hbWUnLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgJ1VuYWJsZSB0byBjcmVhdGUgY2FzZSBpbnNlbnNpdGl2ZSB1c2VybmFtZSBpbmRleDogJyxcbiAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgZW1haWxVbmlxdWVuZXNzID0gdXNlckNsYXNzUHJvbWlzZVxuICAgICAgLnRoZW4oKCkgPT5cbiAgICAgICAgdGhpcy5hZGFwdGVyLmVuc3VyZVVuaXF1ZW5lc3MoJ19Vc2VyJywgcmVxdWlyZWRVc2VyRmllbGRzLCBbJ2VtYWlsJ10pXG4gICAgICApXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICAnVW5hYmxlIHRvIGVuc3VyZSB1bmlxdWVuZXNzIGZvciB1c2VyIGVtYWlsIGFkZHJlc3NlczogJyxcbiAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgZW1haWxDYXNlSW5zZW5zaXRpdmVJbmRleCA9IHVzZXJDbGFzc1Byb21pc2VcbiAgICAgIC50aGVuKCgpID0+XG4gICAgICAgIHRoaXMuYWRhcHRlci5lbnN1cmVJbmRleChcbiAgICAgICAgICAnX1VzZXInLFxuICAgICAgICAgIHJlcXVpcmVkVXNlckZpZWxkcyxcbiAgICAgICAgICBbJ2VtYWlsJ10sXG4gICAgICAgICAgJ2Nhc2VfaW5zZW5zaXRpdmVfZW1haWwnLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1VuYWJsZSB0byBjcmVhdGUgY2FzZSBpbnNlbnNpdGl2ZSBlbWFpbCBpbmRleDogJywgZXJyb3IpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuXG4gICAgY29uc3Qgcm9sZVVuaXF1ZW5lc3MgPSByb2xlQ2xhc3NQcm9taXNlXG4gICAgICAudGhlbigoKSA9PlxuICAgICAgICB0aGlzLmFkYXB0ZXIuZW5zdXJlVW5pcXVlbmVzcygnX1JvbGUnLCByZXF1aXJlZFJvbGVGaWVsZHMsIFsnbmFtZSddKVxuICAgICAgKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1VuYWJsZSB0byBlbnN1cmUgdW5pcXVlbmVzcyBmb3Igcm9sZSBuYW1lOiAnLCBlcnJvcik7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSk7XG5cbiAgICBjb25zdCBpbmRleFByb21pc2UgPSB0aGlzLmFkYXB0ZXIudXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMoKTtcblxuICAgIC8vIENyZWF0ZSB0YWJsZXMgZm9yIHZvbGF0aWxlIGNsYXNzZXNcbiAgICBjb25zdCBhZGFwdGVySW5pdCA9IHRoaXMuYWRhcHRlci5wZXJmb3JtSW5pdGlhbGl6YXRpb24oe1xuICAgICAgVm9sYXRpbGVDbGFzc2VzU2NoZW1hczogU2NoZW1hQ29udHJvbGxlci5Wb2xhdGlsZUNsYXNzZXNTY2hlbWFzLFxuICAgIH0pO1xuICAgIHJldHVybiBQcm9taXNlLmFsbChbXG4gICAgICB1c2VybmFtZVVuaXF1ZW5lc3MsXG4gICAgICB1c2VybmFtZUNhc2VJbnNlbnNpdGl2ZUluZGV4LFxuICAgICAgZW1haWxVbmlxdWVuZXNzLFxuICAgICAgZW1haWxDYXNlSW5zZW5zaXRpdmVJbmRleCxcbiAgICAgIHJvbGVVbmlxdWVuZXNzLFxuICAgICAgYWRhcHRlckluaXQsXG4gICAgICBpbmRleFByb21pc2UsXG4gICAgXSk7XG4gIH1cblxuICBzdGF0aWMgX3ZhbGlkYXRlUXVlcnk6IGFueSA9PiB2b2lkO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IERhdGFiYXNlQ29udHJvbGxlcjtcbi8vIEV4cG9zZSB2YWxpZGF0ZVF1ZXJ5IGZvciB0ZXN0c1xubW9kdWxlLmV4cG9ydHMuX3ZhbGlkYXRlUXVlcnkgPSB2YWxpZGF0ZVF1ZXJ5O1xuIl19 \ 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9GaWxlc0NvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiUGFyc2UiLCJyZXF1aXJlIiwibGVnYWN5RmlsZXNSZWdleCIsIlJlZ0V4cCIsIkZpbGVzQ29udHJvbGxlciIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJnZXRGaWxlRGF0YSIsImNvbmZpZyIsImZpbGVuYW1lIiwiYWRhcHRlciIsImNyZWF0ZUZpbGUiLCJkYXRhIiwiY29udGVudFR5cGUiLCJleHRuYW1lIiwicGF0aCIsImhhc0V4dGVuc2lvbiIsImxlbmd0aCIsIm1pbWUiLCJnZXRFeHRlbnNpb24iLCJnZXRUeXBlIiwib3B0aW9ucyIsInByZXNlcnZlRmlsZU5hbWUiLCJsb2NhdGlvbiIsImdldEZpbGVMb2NhdGlvbiIsInRoZW4iLCJQcm9taXNlIiwicmVzb2x2ZSIsInVybCIsIm5hbWUiLCJkZWxldGVGaWxlIiwiZXhwYW5kRmlsZXNJbk9iamVjdCIsIm9iamVjdCIsIkFycmF5IiwibWFwIiwib2JqIiwia2V5IiwiZmlsZU9iamVjdCIsImZpbGVLZXkiLCJ1bmRlZmluZWQiLCJpbmRleE9mIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwidGVzdCIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJGaWxlc0FkYXB0ZXIiLCJoYW5kbGVGaWxlU3RyZWFtIiwicmVxIiwicmVzIiwidmFsaWRhdGVGaWxlbmFtZSIsImVycm9yIiwiRXJyb3IiLCJJTlZBTElEX0ZJTEVfTkFNRSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBTEE7QUFNQSxNQUFNQSxLQUFLLEdBQUdDLE9BQU8sQ0FBQyxPQUFELENBQVAsQ0FBaUJELEtBQS9COztBQUVBLE1BQU1FLGdCQUFnQixHQUFHLElBQUlDLE1BQUosQ0FDdkIsaUZBRHVCLENBQXpCOztBQUlPLE1BQU1DLGVBQU4sU0FBOEJDLDRCQUE5QixDQUFrRDtBQUN2REMsRUFBQUEsV0FBVyxDQUFDQyxNQUFELEVBQVNDLFFBQVQsRUFBbUI7QUFDNUIsV0FBTyxLQUFLQyxPQUFMLENBQWFILFdBQWIsQ0FBeUJFLFFBQXpCLENBQVA7QUFDRDs7QUFFREUsRUFBQUEsVUFBVSxDQUFDSCxNQUFELEVBQVNDLFFBQVQsRUFBbUJHLElBQW5CLEVBQXlCQyxXQUF6QixFQUFzQztBQUM5QyxVQUFNQyxPQUFPLEdBQUdDLGNBQUtELE9BQUwsQ0FBYUwsUUFBYixDQUFoQjs7QUFFQSxVQUFNTyxZQUFZLEdBQUdGLE9BQU8sQ0FBQ0csTUFBUixHQUFpQixDQUF0Qzs7QUFFQSxRQUFJLENBQUNELFlBQUQsSUFBaUJILFdBQWpCLElBQWdDSyxjQUFLQyxZQUFMLENBQWtCTixXQUFsQixDQUFwQyxFQUFvRTtBQUNsRUosTUFBQUEsUUFBUSxHQUFHQSxRQUFRLEdBQUcsR0FBWCxHQUFpQlMsY0FBS0MsWUFBTCxDQUFrQk4sV0FBbEIsQ0FBNUI7QUFDRCxLQUZELE1BRU8sSUFBSUcsWUFBWSxJQUFJLENBQUNILFdBQXJCLEVBQWtDO0FBQ3ZDQSxNQUFBQSxXQUFXLEdBQUdLLGNBQUtFLE9BQUwsQ0FBYVgsUUFBYixDQUFkO0FBQ0Q7O0FBRUQsUUFBSSxDQUFDLEtBQUtZLE9BQUwsQ0FBYUMsZ0JBQWxCLEVBQW9DO0FBQ2xDYixNQUFBQSxRQUFRLEdBQUcsa0NBQWdCLEVBQWhCLElBQXNCLEdBQXRCLEdBQTRCQSxRQUF2QztBQUNEOztBQUVELFVBQU1jLFFBQVEsR0FBRyxLQUFLYixPQUFMLENBQWFjLGVBQWIsQ0FBNkJoQixNQUE3QixFQUFxQ0MsUUFBckMsQ0FBakI7QUFDQSxXQUFPLEtBQUtDLE9BQUwsQ0FBYUMsVUFBYixDQUF3QkYsUUFBeEIsRUFBa0NHLElBQWxDLEVBQXdDQyxXQUF4QyxFQUFxRFksSUFBckQsQ0FBMEQsTUFBTTtBQUNyRSxhQUFPQyxPQUFPLENBQUNDLE9BQVIsQ0FBZ0I7QUFDckJDLFFBQUFBLEdBQUcsRUFBRUwsUUFEZ0I7QUFFckJNLFFBQUFBLElBQUksRUFBRXBCO0FBRmUsT0FBaEIsQ0FBUDtBQUlELEtBTE0sQ0FBUDtBQU1EOztBQUVEcUIsRUFBQUEsVUFBVSxDQUFDdEIsTUFBRCxFQUFTQyxRQUFULEVBQW1CO0FBQzNCLFdBQU8sS0FBS0MsT0FBTCxDQUFhb0IsVUFBYixDQUF3QnJCLFFBQXhCLENBQVA7QUFDRDtBQUVEOzs7Ozs7O0FBS0FzQixFQUFBQSxtQkFBbUIsQ0FBQ3ZCLE1BQUQsRUFBU3dCLE1BQVQsRUFBaUI7QUFDbEMsUUFBSUEsTUFBTSxZQUFZQyxLQUF0QixFQUE2QjtBQUMzQkQsTUFBQUEsTUFBTSxDQUFDRSxHQUFQLENBQVdDLEdBQUcsSUFBSSxLQUFLSixtQkFBTCxDQUF5QnZCLE1BQXpCLEVBQWlDMkIsR0FBakMsQ0FBbEI7QUFDQTtBQUNEOztBQUNELFFBQUksT0FBT0gsTUFBUCxLQUFrQixRQUF0QixFQUFnQztBQUM5QjtBQUNEOztBQUNELFNBQUssTUFBTUksR0FBWCxJQUFrQkosTUFBbEIsRUFBMEI7QUFDeEIsWUFBTUssVUFBVSxHQUFHTCxNQUFNLENBQUNJLEdBQUQsQ0FBekI7O0FBQ0EsVUFBSUMsVUFBVSxJQUFJQSxVQUFVLENBQUMsUUFBRCxDQUFWLEtBQXlCLE1BQTNDLEVBQW1EO0FBQ2pELFlBQUlBLFVBQVUsQ0FBQyxLQUFELENBQWQsRUFBdUI7QUFDckI7QUFDRDs7QUFDRCxjQUFNNUIsUUFBUSxHQUFHNEIsVUFBVSxDQUFDLE1BQUQsQ0FBM0IsQ0FKaUQsQ0FLakQ7QUFDQTtBQUNBOztBQUNBLFlBQUk3QixNQUFNLENBQUM4QixPQUFQLEtBQW1CQyxTQUF2QixFQUFrQztBQUNoQ0YsVUFBQUEsVUFBVSxDQUFDLEtBQUQsQ0FBVixHQUFvQixLQUFLM0IsT0FBTCxDQUFhYyxlQUFiLENBQTZCaEIsTUFBN0IsRUFBcUNDLFFBQXJDLENBQXBCO0FBQ0QsU0FGRCxNQUVPO0FBQ0wsY0FBSUEsUUFBUSxDQUFDK0IsT0FBVCxDQUFpQixPQUFqQixNQUE4QixDQUFsQyxFQUFxQztBQUNuQ0gsWUFBQUEsVUFBVSxDQUFDLEtBQUQsQ0FBVixHQUNFLGdDQUNBN0IsTUFBTSxDQUFDOEIsT0FEUCxHQUVBLEdBRkEsR0FHQUcsa0JBQWtCLENBQUNoQyxRQUFELENBSnBCO0FBS0QsV0FORCxNQU1PLElBQUlOLGdCQUFnQixDQUFDdUMsSUFBakIsQ0FBc0JqQyxRQUF0QixDQUFKLEVBQXFDO0FBQzFDNEIsWUFBQUEsVUFBVSxDQUFDLEtBQUQsQ0FBVixHQUNFLDRCQUNBN0IsTUFBTSxDQUFDOEIsT0FEUCxHQUVBLEdBRkEsR0FHQUcsa0JBQWtCLENBQUNoQyxRQUFELENBSnBCO0FBS0QsV0FOTSxNQU1BO0FBQ0w0QixZQUFBQSxVQUFVLENBQUMsS0FBRCxDQUFWLEdBQW9CLEtBQUszQixPQUFMLENBQWFjLGVBQWIsQ0FBNkJoQixNQUE3QixFQUFxQ0MsUUFBckMsQ0FBcEI7QUFDRDtBQUNGO0FBQ0Y7QUFDRjtBQUNGOztBQUVEa0MsRUFBQUEsbUJBQW1CLEdBQUc7QUFDcEIsV0FBT0MsMEJBQVA7QUFDRDs7QUFFREMsRUFBQUEsZ0JBQWdCLENBQUNyQyxNQUFELEVBQVNDLFFBQVQsRUFBbUJxQyxHQUFuQixFQUF3QkMsR0FBeEIsRUFBNkJsQyxXQUE3QixFQUEwQztBQUN4RCxXQUFPLEtBQUtILE9BQUwsQ0FBYW1DLGdCQUFiLENBQThCcEMsUUFBOUIsRUFBd0NxQyxHQUF4QyxFQUE2Q0MsR0FBN0MsRUFBa0RsQyxXQUFsRCxDQUFQO0FBQ0Q7O0FBRURtQyxFQUFBQSxnQkFBZ0IsQ0FBQ3ZDLFFBQUQsRUFBVztBQUN6QixRQUFJLE9BQU8sS0FBS0MsT0FBTCxDQUFhc0MsZ0JBQXBCLEtBQXlDLFVBQTdDLEVBQXlEO0FBQ3ZELFlBQU1DLEtBQUssR0FBRyxLQUFLdkMsT0FBTCxDQUFhc0MsZ0JBQWIsQ0FBOEJ2QyxRQUE5QixDQUFkOztBQUNBLFVBQUksT0FBT3dDLEtBQVAsS0FBaUIsUUFBckIsRUFBK0I7QUFDN0IsZUFBT0EsS0FBUDtBQUNEOztBQUNELGFBQU8sSUFBSWhELEtBQUssQ0FBQ2lELEtBQVYsQ0FBZ0JqRCxLQUFLLENBQUNpRCxLQUFOLENBQVlDLGlCQUE1QixFQUErQ0YsS0FBL0MsQ0FBUDtBQUNEOztBQUNELFdBQU8sb0NBQWlCeEMsUUFBakIsQ0FBUDtBQUNEOztBQWhHc0Q7OztlQW1HMUNKLGUiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBGaWxlc0NvbnRyb2xsZXIuanNcbmltcG9ydCB7IHJhbmRvbUhleFN0cmluZyB9IGZyb20gJy4uL2NyeXB0b1V0aWxzJztcbmltcG9ydCBBZGFwdGFibGVDb250cm9sbGVyIGZyb20gJy4vQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgeyB2YWxpZGF0ZUZpbGVuYW1lLCBGaWxlc0FkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9GaWxlcy9GaWxlc0FkYXB0ZXInO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgbWltZSBmcm9tICdtaW1lJztcbmNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2UnKS5QYXJzZTtcblxuY29uc3QgbGVnYWN5RmlsZXNSZWdleCA9IG5ldyBSZWdFeHAoXG4gICdeWzAtOWEtZkEtRl17OH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17NH0tWzAtOWEtZkEtRl17MTJ9LS4qJ1xuKTtcblxuZXhwb3J0IGNsYXNzIEZpbGVzQ29udHJvbGxlciBleHRlbmRzIEFkYXB0YWJsZUNvbnRyb2xsZXIge1xuICBnZXRGaWxlRGF0YShjb25maWcsIGZpbGVuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5nZXRGaWxlRGF0YShmaWxlbmFtZSk7XG4gIH1cblxuICBjcmVhdGVGaWxlKGNvbmZpZywgZmlsZW5hbWUsIGRhdGEsIGNvbnRlbnRUeXBlKSB7XG4gICAgY29uc3QgZXh0bmFtZSA9IHBhdGguZXh0bmFtZShmaWxlbmFtZSk7XG5cbiAgICBjb25zdCBoYXNFeHRlbnNpb24gPSBleHRuYW1lLmxlbmd0aCA+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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9Ib29rc0NvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiRGVmYXVsdEhvb2tzQ29sbGVjdGlvbk5hbWUiLCJIVFRQQWdlbnRzIiwiaHR0cCIsIkFnZW50Iiwia2VlcEFsaXZlIiwiaHR0cHMiLCJIb29rc0NvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImFwcGxpY2F0aW9uSWQiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJ3ZWJob29rS2V5IiwiX2FwcGxpY2F0aW9uSWQiLCJfd2ViaG9va0tleSIsImRhdGFiYXNlIiwibG9hZCIsIl9nZXRIb29rcyIsInRoZW4iLCJob29rcyIsImZvckVhY2giLCJob29rIiwiYWRkSG9va1RvVHJpZ2dlcnMiLCJnZXRGdW5jdGlvbiIsImZ1bmN0aW9uTmFtZSIsInJlc3VsdHMiLCJnZXRGdW5jdGlvbnMiLCIkZXhpc3RzIiwiZ2V0VHJpZ2dlciIsImNsYXNzTmFtZSIsInRyaWdnZXJOYW1lIiwiZ2V0VHJpZ2dlcnMiLCJkZWxldGVGdW5jdGlvbiIsInRyaWdnZXJzIiwicmVtb3ZlRnVuY3Rpb24iLCJfcmVtb3ZlSG9va3MiLCJkZWxldGVUcmlnZ2VyIiwicmVtb3ZlVHJpZ2dlciIsInF1ZXJ5IiwiZmluZCIsIm1hcCIsInJlc3VsdCIsIm9iamVjdElkIiwiZGVzdHJveSIsIlByb21pc2UiLCJyZXNvbHZlIiwic2F2ZUhvb2siLCJ1cmwiLCJQYXJzZSIsIkVycm9yIiwidXBkYXRlIiwidXBzZXJ0Iiwid3JhcHBlZEZ1bmN0aW9uIiwid3JhcFRvSFRUUFJlcXVlc3QiLCJhZGRUcmlnZ2VyIiwiYWRkRnVuY3Rpb24iLCJhZGRIb29rIiwiY3JlYXRlT3JVcGRhdGVIb29rIiwiYUhvb2siLCJUeXBlcyIsImNyZWF0ZUhvb2siLCJ1cGRhdGVIb29rIiwia2V5IiwicmVxIiwianNvbkJvZHkiLCJpIiwib2JqZWN0IiwidG9KU09OIiwib3JpZ2luYWwiLCJqc29uUmVxdWVzdCIsImhlYWRlcnMiLCJib2R5IiwibWV0aG9kIiwiYWdlbnQiLCJzdGFydHNXaXRoIiwibG9nZ2VyIiwid2FybiIsInJlc3BvbnNlIiwiZXJyIiwiZGF0YSIsIkpTT04iLCJwYXJzZSIsImUiLCJlcnJvciIsImNvZGUiLCJwYXJ0aWFsUmVzcG9uc2UiLCJzdWJzdHJpbmciLCJzdWNjZXNzIiwiY3JlYXRlZEF0IiwidXBkYXRlZEF0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBRUE7O0FBRUE7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBTkE7QUFFQTtBQU1BLE1BQU1BLDBCQUEwQixHQUFHLFFBQW5DO0FBQ0EsTUFBTUMsVUFBVSxHQUFHO0FBQ2pCQyxFQUFBQSxJQUFJLEVBQUUsSUFBSUEsY0FBS0MsS0FBVCxDQUFlO0FBQUVDLElBQUFBLFNBQVMsRUFBRTtBQUFiLEdBQWYsQ0FEVztBQUVqQkMsRUFBQUEsS0FBSyxFQUFFLElBQUlBLGVBQU1GLEtBQVYsQ0FBZ0I7QUFBRUMsSUFBQUEsU0FBUyxFQUFFO0FBQWIsR0FBaEI7QUFGVSxDQUFuQjs7QUFLTyxNQUFNRSxlQUFOLENBQXNCO0FBSzNCQyxFQUFBQSxXQUFXLENBQUNDLGFBQUQsRUFBd0JDLGtCQUF4QixFQUE0Q0MsVUFBNUMsRUFBd0Q7QUFDakUsU0FBS0MsY0FBTCxHQUFzQkgsYUFBdEI7QUFDQSxTQUFLSSxXQUFMLEdBQW1CRixVQUFuQjtBQUNBLFNBQUtHLFFBQUwsR0FBZ0JKLGtCQUFoQjtBQUNEOztBQUVESyxFQUFBQSxJQUFJLEdBQUc7QUFDTCxXQUFPLEtBQUtDLFNBQUwsR0FBaUJDLElBQWpCLENBQXNCQyxLQUFLLElBQUk7QUFDcENBLE1BQUFBLEtBQUssR0FBR0EsS0FBSyxJQUFJLEVBQWpCO0FBQ0FBLE1BQUFBLEtBQUssQ0FBQ0MsT0FBTixDQUFjQyxJQUFJLElBQUk7QUFDcEIsYUFBS0MsaUJBQUwsQ0FBdUJELElBQXZCO0FBQ0QsT0FGRDtBQUdELEtBTE0sQ0FBUDtBQU1EOztBQUVERSxFQUFBQSxXQUFXLENBQUNDLFlBQUQsRUFBZTtBQUN4QixXQUFPLEtBQUtQLFNBQUwsQ0FBZTtBQUFFTyxNQUFBQSxZQUFZLEVBQUVBO0FBQWhCLEtBQWYsRUFBK0NOLElBQS9DLENBQ0xPLE9BQU8sSUFBSUEsT0FBTyxDQUFDLENBQUQsQ0FEYixDQUFQO0FBR0Q7O0FBRURDLEVBQUFBLFlBQVksR0FBRztBQUNiLFdBQU8sS0FBS1QsU0FBTCxDQUFlO0FBQUVPLE1BQUFBLFlBQVksRUFBRTtBQUFFRyxRQUFBQSxPQUFPLEVBQUU7QUFBWDtBQUFoQixLQUFmLENBQVA7QUFDRDs7QUFFREMsRUFBQUEsVUFBVSxDQUFDQyxTQUFELEVBQVlDLFdBQVosRUFBeUI7QUFDakMsV0FBTyxLQUFLYixTQUFMLENBQWU7QUFDcEJZLE1BQUFBLFNBQVMsRUFBRUEsU0FEUztBQUVwQkMsTUFBQUEsV0FBVyxFQUFFQTtBQUZPLEtBQWYsRUFHSlosSUFISSxDQUdDTyxPQUFPLElBQUlBLE9BQU8sQ0FBQyxDQUFELENBSG5CLENBQVA7QUFJRDs7QUFFRE0sRUFBQUEsV0FBVyxHQUFHO0FBQ1osV0FBTyxLQUFLZCxTQUFMLENBQWU7QUFDcEJZLE1BQUFBLFNBQVMsRUFBRTtBQUFFRixRQUFBQSxPQUFPLEVBQUU7QUFBWCxPQURTO0FBRXBCRyxNQUFBQSxXQUFXLEVBQUU7QUFBRUgsUUFBQUEsT0FBTyxFQUFFO0FBQVg7QUFGTyxLQUFmLENBQVA7QUFJRDs7QUFFREssRUFBQUEsY0FBYyxDQUFDUixZQUFELEVBQWU7QUFDM0JTLElBQUFBLFFBQVEsQ0FBQ0MsY0FBVCxDQUF3QlYsWUFBeEIsRUFBc0MsS0FBS1gsY0FBM0M7QUFDQSxXQUFPLEtBQUtzQixZQUFMLENBQWtCO0FBQUVYLE1BQUFBLFlBQVksRUFBRUE7QUFBaEIsS0FBbEIsQ0FBUDtBQUNEOztBQUVEWSxFQUFBQSxhQUFhLENBQUNQLFNBQUQsRUFBWUMsV0FBWixFQUF5QjtBQUNwQ0csSUFBQUEsUUFBUSxDQUFDSSxhQUFULENBQXVCUCxXQUF2QixFQUFvQ0QsU0FBcEMsRUFBK0MsS0FBS2hCLGNBQXBEO0FBQ0EsV0FBTyxLQUFLc0IsWUFBTCxDQUFrQjtBQUN2Qk4sTUFBQUEsU0FBUyxFQUFFQSxTQURZO0FBRXZCQyxNQUFBQSxXQUFXLEVBQUVBO0FBRlUsS0FBbEIsQ0FBUDtBQUlEOztBQUVEYixFQUFBQSxTQUFTLENBQUNxQixLQUFLLEdBQUcsRUFBVCxFQUFhO0FBQ3BCLFdBQU8sS0FBS3ZCLFFBQUwsQ0FDSndCLElBREksQ0FDQ3JDLDBCQURELEVBQzZCb0MsS0FEN0IsRUFFSnBCLElBRkksQ0FFQ08sT0FBTyxJQUFJO0FBQ2YsYUFBT0EsT0FBTyxDQUFDZSxHQUFSLENBQVlDLE1BQU0sSUFBSTtBQUMzQixlQUFPQSxNQUFNLENBQUNDLFFBQWQ7QUFDQSxlQUFPRCxNQUFQO0FBQ0QsT0FITSxDQUFQO0FBSUQsS0FQSSxDQUFQO0FBUUQ7O0FBRUROLEVBQUFBLFlBQVksQ0FBQ0csS0FBRCxFQUFRO0FBQ2xCLFdBQU8sS0FBS3ZCLFFBQUwsQ0FBYzRCLE9BQWQsQ0FBc0J6QywwQkFBdEIsRUFBa0RvQyxLQUFsRCxFQUF5RHBCLElBQXpELENBQThELE1BQU07QUFDekUsYUFBTzBCLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQixFQUFoQixDQUFQO0FBQ0QsS0FGTSxDQUFQO0FBR0Q7O0FBRURDLEVBQUFBLFFBQVEsQ0FBQ3pCLElBQUQsRUFBTztBQUNiLFFBQUlpQixLQUFKOztBQUNBLFFBQUlqQixJQUFJLENBQUNHLFlBQUwsSUFBcUJILElBQUksQ0FBQzBCLEdBQTlCLEVBQW1DO0FBQ2pDVCxNQUFBQSxLQUFLLEdBQUc7QUFBRWQsUUFBQUEsWUFBWSxFQUFFSCxJQUFJLENBQUNHO0FBQXJCLE9BQVI7QUFDRCxLQUZELE1BRU8sSUFBSUgsSUFBSSxDQUFDUyxXQUFMLElBQW9CVCxJQUFJLENBQUNRLFNBQXpCLElBQXNDUixJQUFJLENBQUMwQixHQUEvQyxFQUFvRDtBQUN6RFQsTUFBQUEsS0FBSyxHQUFHO0FBQUVULFFBQUFBLFNBQVMsRUFBRVIsSUFBSSxDQUFDUSxTQUFsQjtBQUE2QkMsUUFBQUEsV0FBVyxFQUFFVCxJQUFJLENBQUNTO0FBQS9DLE9BQVI7QUFDRCxLQUZNLE1BRUE7QUFDTCxZQUFNLElBQUlrQixLQUFLLENBQUNDLEtBQVYsQ0FBZ0IsR0FBaEIsRUFBcUIsMEJBQXJCLENBQU47QUFDRDs7QUFDRCxXQUFPLEtBQUtsQyxRQUFMLENBQ0ptQyxNQURJLENBQ0doRCwwQkFESCxFQUMrQm9DLEtBRC9CLEVBQ3NDakIsSUFEdEMsRUFDNEM7QUFBRThCLE1BQUFBLE1BQU0sRUFBRTtBQUFWLEtBRDVDLEVBRUpqQyxJQUZJLENBRUMsTUFBTTtBQUNWLGFBQU8wQixPQUFPLENBQUNDLE9BQVIsQ0FBZ0J4QixJQUFoQixDQUFQO0FBQ0QsS0FKSSxDQUFQO0FBS0Q7O0FBRURDLEVBQUFBLGlCQUFpQixDQUFDRCxJQUFELEVBQU87QUFDdEIsUUFBSStCLGVBQWUsR0FBR0MsaUJBQWlCLENBQUNoQyxJQUFELEVBQU8sS0FBS1AsV0FBWixDQUF2QztBQUNBc0MsSUFBQUEsZUFBZSxDQUFDTCxHQUFoQixHQUFzQjFCLElBQUksQ0FBQzBCLEdBQTNCOztBQUNBLFFBQUkxQixJQUFJLENBQUNRLFNBQVQsRUFBb0I7QUFDbEJJLE1BQUFBLFFBQVEsQ0FBQ3FCLFVBQVQsQ0FDRWpDLElBQUksQ0FBQ1MsV0FEUCxFQUVFVCxJQUFJLENBQUNRLFNBRlAsRUFHRXVCLGVBSEYsRUFJRSxLQUFLdkMsY0FKUDtBQU1ELEtBUEQsTUFPTztBQUNMb0IsTUFBQUEsUUFBUSxDQUFDc0IsV0FBVCxDQUNFbEMsSUFBSSxDQUFDRyxZQURQLEVBRUU0QixlQUZGLEVBR0UsSUFIRixFQUlFLEtBQUt2QyxjQUpQO0FBTUQ7QUFDRjs7QUFFRDJDLEVBQUFBLE9BQU8sQ0FBQ25DLElBQUQsRUFBTztBQUNaLFNBQUtDLGlCQUFMLENBQXVCRCxJQUF2QjtBQUNBLFdBQU8sS0FBS3lCLFFBQUwsQ0FBY3pCLElBQWQsQ0FBUDtBQUNEOztBQUVEb0MsRUFBQUEsa0JBQWtCLENBQUNDLEtBQUQsRUFBUTtBQUN4QixRQUFJckMsSUFBSjs7QUFDQSxRQUFJcUMsS0FBSyxJQUFJQSxLQUFLLENBQUNsQyxZQUFmLElBQStCa0MsS0FBSyxDQUFDWCxHQUF6QyxFQUE4QztBQUM1QzFCLE1BQUFBLElBQUksR0FBRyxFQUFQO0FBQ0FBLE1BQUFBLElBQUksQ0FBQ0csWUFBTCxHQUFvQmtDLEtBQUssQ0FBQ2xDLFlBQTFCO0FBQ0FILE1BQUFBLElBQUksQ0FBQzBCLEdBQUwsR0FBV1csS0FBSyxDQUFDWCxHQUFqQjtBQUNELEtBSkQsTUFJTyxJQUNMVyxLQUFLLElBQ0xBLEtBQUssQ0FBQzdCLFNBRE4sSUFFQTZCLEtBQUssQ0FBQ1gsR0FGTixJQUdBVyxLQUFLLENBQUM1QixXQUhOLElBSUFHLFFBQVEsQ0FBQzBCLEtBQVQsQ0FBZUQsS0FBSyxDQUFDNUIsV0FBckIsQ0FMSyxFQU1MO0FBQ0FULE1BQUFBLElBQUksR0FBRyxFQUFQO0FBQ0FBLE1BQUFBLElBQUksQ0FBQ1EsU0FBTCxHQUFpQjZCLEtBQUssQ0FBQzdCLFNBQXZCO0FBQ0FSLE1BQUFBLElBQUksQ0FBQzBCLEdBQUwsR0FBV1csS0FBSyxDQUFDWCxHQUFqQjtBQUNBMUIsTUFBQUEsSUFBSSxDQUFDUyxXQUFMLEdBQW1CNEIsS0FBSyxDQUFDNUIsV0FBekI7QUFDRCxLQVhNLE1BV0E7QUFDTCxZQUFNLElBQUlrQixLQUFLLENBQUNDLEtBQVYsQ0FBZ0IsR0FBaEIsRUFBcUIsMEJBQXJCLENBQU47QUFDRDs7QUFFRCxXQUFPLEtBQUtPLE9BQUwsQ0FBYW5DLElBQWIsQ0FBUDtBQUNEOztBQUVEdUMsRUFBQUEsVUFBVSxDQUFDRixLQUFELEVBQVE7QUFDaEIsUUFBSUEsS0FBSyxDQUFDbEMsWUFBVixFQUF3QjtBQUN0QixhQUFPLEtBQUtELFdBQUwsQ0FBaUJtQyxLQUFLLENBQUNsQyxZQUF2QixFQUFxQ04sSUFBckMsQ0FBMEN1QixNQUFNLElBQUk7QUFDekQsWUFBSUEsTUFBSixFQUFZO0FBQ1YsZ0JBQU0sSUFBSU8sS0FBSyxDQUFDQyxLQUFWLENBQ0osR0FESSxFQUVILGtCQUFpQlMsS0FBSyxDQUFDbEMsWUFBYSxnQkFGakMsQ0FBTjtBQUlELFNBTEQsTUFLTztBQUNMLGlCQUFPLEtBQUtpQyxrQkFBTCxDQUF3QkMsS0FBeEIsQ0FBUDtBQUNEO0FBQ0YsT0FUTSxDQUFQO0FBVUQsS0FYRCxNQVdPLElBQUlBLEtBQUssQ0FBQzdCLFNBQU4sSUFBbUI2QixLQUFLLENBQUM1QixXQUE3QixFQUEwQztBQUMvQyxhQUFPLEtBQUtGLFVBQUwsQ0FBZ0I4QixLQUFLLENBQUM3QixTQUF0QixFQUFpQzZCLEtBQUssQ0FBQzVCLFdBQXZDLEVBQW9EWixJQUFwRCxDQUNMdUIsTUFBTSxJQUFJO0FBQ1IsWUFBSUEsTUFBSixFQUFZO0FBQ1YsZ0JBQU0sSUFBSU8sS0FBSyxDQUFDQyxLQUFWLENBQ0osR0FESSxFQUVILFNBQVFTLEtBQUssQ0FBQzdCLFNBQVUsd0JBQ3ZCNkIsS0FBSyxDQUFDNUIsV0FDUCxFQUpHLENBQU47QUFNRDs7QUFDRCxlQUFPLEtBQUsyQixrQkFBTCxDQUF3QkMsS0FBeEIsQ0FBUDtBQUNELE9BWEksQ0FBUDtBQWFEOztBQUVELFVBQU0sSUFBSVYsS0FBSyxDQUFDQyxLQUFWLENBQWdCLEdBQWhCLEVBQXFCLDBCQUFyQixDQUFOO0FBQ0Q7O0FBRURZLEVBQUFBLFVBQVUsQ0FBQ0gsS0FBRCxFQUFRO0FBQ2hCLFFBQUlBLEtBQUssQ0FBQ2xDLFlBQVYsRUFBd0I7QUFDdEIsYUFBTyxLQUFLRCxXQUFMLENBQWlCbUMsS0FBSyxDQUFDbEMsWUFBdkIsRUFBcUNOLElBQXJDLENBQTBDdUIsTUFBTSxJQUFJO0FBQ3pELFlBQUlBLE1BQUosRUFBWTtBQUNWLGlCQUFPLEtBQUtnQixrQkFBTCxDQUF3QkMsS0FBeEIsQ0FBUDtBQUNEOztBQUNELGNBQU0sSUFBSVYsS0FBSyxDQUFDQyxLQUFWLENBQ0osR0FESSxFQUVILHNCQUFxQlMsS0FBSyxDQUFDbEMsWUFBYSxhQUZyQyxDQUFOO0FBSUQsT0FSTSxDQUFQO0FBU0QsS0FWRCxNQVVPLElBQUlrQyxLQUFLLENBQUM3QixTQUFOLElBQW1CNkIsS0FBSyxDQUFDNUIsV0FBN0IsRUFBMEM7QUFDL0MsYUFBTyxLQUFLRixVQUFMLENBQWdCOEIsS0FBSyxDQUFDN0IsU0FBdEIsRUFBaUM2QixLQUFLLENBQUM1QixXQUF2QyxFQUFvRFosSUFBcEQsQ0FDTHVCLE1BQU0sSUFBSTtBQUNSLFlBQUlBLE1BQUosRUFBWTtBQUNWLGlCQUFPLEtBQUtnQixrQkFBTCxDQUF3QkMsS0FBeEIsQ0FBUDtBQUNEOztBQUNELGNBQU0sSUFBSVYsS0FBSyxDQUFDQyxLQUFWLENBQWdCLEdBQWhCLEVBQXNCLFNBQVFTLEtBQUssQ0FBQzdCLFNBQVUsaUJBQTlDLENBQU47QUFDRCxPQU5JLENBQVA7QUFRRDs7QUFDRCxVQUFNLElBQUltQixLQUFLLENBQUNDLEtBQVYsQ0FBZ0IsR0FBaEIsRUFBcUIsMEJBQXJCLENBQU47QUFDRDs7QUFoTTBCOzs7O0FBbU03QixTQUFTSSxpQkFBVCxDQUEyQmhDLElBQTNCLEVBQWlDeUMsR0FBakMsRUFBc0M7QUFDcEMsU0FBT0MsR0FBRyxJQUFJO0FBQ1osVUFBTUMsUUFBUSxHQUFHLEVBQWpCOztBQUNBLFNBQUssSUFBSUMsQ0FBVCxJQUFjRixHQUFkLEVBQW1CO0FBQ2pCQyxNQUFBQSxRQUFRLENBQUNDLENBQUQsQ0FBUixHQUFjRixHQUFHLENBQUNFLENBQUQsQ0FBakI7QUFDRDs7QUFDRCxRQUFJRixHQUFHLENBQUNHLE1BQVIsRUFBZ0I7QUFDZEYsTUFBQUEsUUFBUSxDQUFDRSxNQUFULEdBQWtCSCxHQUFHLENBQUNHLE1BQUosQ0FBV0MsTUFBWCxFQUFsQjtBQUNBSCxNQUFBQSxRQUFRLENBQUNFLE1BQVQsQ0FBZ0JyQyxTQUFoQixHQUE0QmtDLEdBQUcsQ0FBQ0csTUFBSixDQUFXckMsU0FBdkM7QUFDRDs7QUFDRCxRQUFJa0MsR0FBRyxDQUFDSyxRQUFSLEVBQWtCO0FBQ2hCSixNQUFBQSxRQUFRLENBQUNJLFFBQVQsR0FBb0JMLEdBQUcsQ0FBQ0ssUUFBSixDQUFhRCxNQUFiLEVBQXBCO0FBQ0FILE1BQUFBLFFBQVEsQ0FBQ0ksUUFBVCxDQUFrQnZDLFNBQWxCLEdBQThCa0MsR0FBRyxDQUFDSyxRQUFKLENBQWF2QyxTQUEzQztBQUNEOztBQUNELFVBQU13QyxXQUFnQixHQUFHO0FBQ3ZCdEIsTUFBQUEsR0FBRyxFQUFFMUIsSUFBSSxDQUFDMEIsR0FEYTtBQUV2QnVCLE1BQUFBLE9BQU8sRUFBRTtBQUNQLHdCQUFnQjtBQURULE9BRmM7QUFLdkJDLE1BQUFBLElBQUksRUFBRVAsUUFMaUI7QUFNdkJRLE1BQUFBLE1BQU0sRUFBRTtBQU5lLEtBQXpCO0FBU0EsVUFBTUMsS0FBSyxHQUFHcEQsSUFBSSxDQUFDMEIsR0FBTCxDQUFTMkIsVUFBVCxDQUFvQixPQUFwQixJQUNWdkUsVUFBVSxDQUFDLE9BQUQsQ0FEQSxHQUVWQSxVQUFVLENBQUMsTUFBRCxDQUZkO0FBR0FrRSxJQUFBQSxXQUFXLENBQUNJLEtBQVosR0FBb0JBLEtBQXBCOztBQUVBLFFBQUlYLEdBQUosRUFBUztBQUNQTyxNQUFBQSxXQUFXLENBQUNDLE9BQVosQ0FBb0IscUJBQXBCLElBQTZDUixHQUE3QztBQUNELEtBRkQsTUFFTztBQUNMYSxxQkFBT0MsSUFBUCxDQUNFLCtEQURGO0FBR0Q7O0FBQ0QsV0FBTyxzQkFBUVAsV0FBUixFQUFxQm5ELElBQXJCLENBQTBCMkQsUUFBUSxJQUFJO0FBQzNDLFVBQUlDLEdBQUo7QUFDQSxVQUFJckMsTUFBSjtBQUNBLFVBQUk4QixJQUFJLEdBQUdNLFFBQVEsQ0FBQ0UsSUFBcEI7O0FBQ0EsVUFBSVIsSUFBSixFQUFVO0FBQ1IsWUFBSSxPQUFPQSxJQUFQLEtBQWdCLFFBQXBCLEVBQThCO0FBQzVCLGNBQUk7QUFDRkEsWUFBQUEsSUFBSSxHQUFHUyxJQUFJLENBQUNDLEtBQUwsQ0FBV1YsSUFBWCxDQUFQO0FBQ0QsV0FGRCxDQUVFLE9BQU9XLENBQVAsRUFBVTtBQUNWSixZQUFBQSxHQUFHLEdBQUc7QUFDSkssY0FBQUEsS0FBSyxFQUFFLG9CQURIO0FBRUpDLGNBQUFBLElBQUksRUFBRSxDQUFDLENBRkg7QUFHSkMsY0FBQUEsZUFBZSxFQUFFZCxJQUFJLENBQUNlLFNBQUwsQ0FBZSxDQUFmLEVBQWtCLEdBQWxCO0FBSGIsYUFBTjtBQUtEO0FBQ0Y7O0FBQ0QsWUFBSSxDQUFDUixHQUFMLEVBQVU7QUFDUnJDLFVBQUFBLE1BQU0sR0FBRzhCLElBQUksQ0FBQ2dCLE9BQWQ7QUFDQVQsVUFBQUEsR0FBRyxHQUFHUCxJQUFJLENBQUNZLEtBQVg7QUFDRDtBQUNGOztBQUNELFVBQUlMLEdBQUosRUFBUztBQUNQLGNBQU1BLEdBQU47QUFDRCxPQUZELE1BRU8sSUFBSXpELElBQUksQ0FBQ1MsV0FBTCxLQUFxQixZQUF6QixFQUF1QztBQUM1QyxZQUFJLE9BQU9XLE1BQVAsS0FBa0IsUUFBdEIsRUFBZ0M7QUFDOUIsaUJBQU9BLE1BQU0sQ0FBQytDLFNBQWQ7QUFDQSxpQkFBTy9DLE1BQU0sQ0FBQ2dELFNBQWQ7QUFDRDs7QUFDRCxlQUFPO0FBQUV2QixVQUFBQSxNQUFNLEVBQUV6QjtBQUFWLFNBQVA7QUFDRCxPQU5NLE1BTUE7QUFDTCxlQUFPQSxNQUFQO0FBQ0Q7QUFDRixLQWhDTSxDQUFQO0FBaUNELEdBbkVEO0FBb0VEOztlQUVjakMsZSIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAZmxvdyB3ZWFrICovXG5cbmltcG9ydCAqIGFzIHRyaWdnZXJzIGZyb20gJy4uL3RyaWdnZXJzJztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0ICogYXMgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCByZXF1ZXN0IGZyb20gJy4uL3JlcXVlc3QnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0IGh0dHBzIGZyb20gJ2h0dHBzJztcblxuY29uc3QgRGVmYXVsdEhvb2tzQ29sbGVjdGlvbk5hbWUgPSAnX0hvb2tzJztcbmNvbnN0IEhUVFBBZ2VudHMgPSB7XG4gIGh0dHA6IG5ldyBodHRwLkFnZW50KHsga2VlcEFsaXZlOiB0cnVlIH0pLFxuICBodHRwczogbmV3IGh0dHBzLkFnZW50KHsga2VlcEFsaXZlOiB0cnVlIH0pLFxufTtcblxuZXhwb3J0IGNsYXNzIEhvb2tzQ29udHJvbGxlciB7XG4gIF9hcHBsaWNhdGlvbklkOiBzdHJpbmc7XG4gIF93ZWJob29rS2V5OiBzdHJpbmc7XG4gIGRhdGFiYXNlOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoYXBwbGljYXRpb25JZDogc3RyaW5nLCBkYXRhYmFzZUNvbnRyb2xsZXIsIHdlYmhvb2tLZXkpIHtcbiAgICB0aGlzLl9hcHBsaWNhdGlvbklkID0gYXBwbGljYXRpb25JZDtcbiAgICB0aGlzLl93ZWJob29rS2V5ID0gd2ViaG9va0tleTtcbiAgICB0aGlzLmRhdGFiYXNlID0gZGF0YWJhc2VDb250cm9sbGVyO1xuICB9XG5cbiAgbG9hZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0SG9va3MoKS50aGVuKGhvb2tzID0+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..4447a30cfa --- /dev/null +++ b/lib/Controllers/ParseGraphQLController.js @@ -0,0 +1,358 @@ +"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, + findAlias = null, + getAlias = null + } = query, + invalidKeys = _objectWithoutProperties(query, ["find", "get", "findAlias", "getAlias"]); + + 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 if (findAlias !== null && typeof findAlias !== 'string') { + return `"query.findAlias" must be a string`; + } else if (getAlias !== null && typeof getAlias !== 'string') { + return `"query.getAlias" must be a string`; + } + } else { + return `"query" must be a valid object`; + } + } + + if (mutation !== null) { + if (isValidSimpleObject(mutation)) { + const { + create = null, + update = null, + destroy = null, + createAlias = null, + updateAlias = null, + destroyAlias = null + } = mutation, + invalidKeys = _objectWithoutProperties(mutation, ["create", "update", "destroy", "createAlias", "updateAlias", "destroyAlias"]); + + 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`; + } + + if (createAlias !== null && typeof createAlias !== 'string') { + return `"mutation.createAlias" must be a string`; + } + + if (updateAlias !== null && typeof updateAlias !== 'string') { + return `"mutation.updateAlias" must be a string`; + } + + if (destroyAlias !== null && typeof destroyAlias !== 'string') { + return `"mutation.destroyAlias" must be a string`; + } + } 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QYXJzZUdyYXBoUUxDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkdyYXBoUUxDb25maWdDbGFzc05hbWUiLCJHcmFwaFFMQ29uZmlnSWQiLCJHcmFwaFFMQ29uZmlnS2V5IiwiUGFyc2VHcmFwaFFMQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwicGFyYW1zIiwiZGF0YWJhc2VDb250cm9sbGVyIiwiY2FjaGVDb250cm9sbGVyIiwiaXNNb3VudGVkIiwibW91bnRHcmFwaFFMIiwiY29uZmlnQ2FjaGVLZXkiLCJnZXRHcmFwaFFMQ29uZmlnIiwiX2NhY2hlZENvbmZpZyIsIl9nZXRDYWNoZWRHcmFwaFFMQ29uZmlnIiwicmVzdWx0cyIsImZpbmQiLCJvYmplY3RJZCIsImxpbWl0IiwiZ3JhcGhRTENvbmZpZyIsImxlbmd0aCIsIl9wdXRDYWNoZWRHcmFwaFFMQ29uZmlnIiwidXBkYXRlR3JhcGhRTENvbmZpZyIsIl92YWxpZGF0ZUdyYXBoUUxDb25maWciLCJ1cGRhdGUiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwiYWNjIiwia2V5IiwidXBzZXJ0IiwicmVzcG9uc2UiLCJyZXN1bHQiLCJncmFwaFFMIiwiZ2V0IiwicHV0IiwiZXJyb3JNZXNzYWdlcyIsInB1c2giLCJpc1ZhbGlkU2ltcGxlT2JqZWN0IiwiZW5hYmxlZEZvckNsYXNzZXMiLCJkaXNhYmxlZEZvckNsYXNzZXMiLCJjbGFzc0NvbmZpZ3MiLCJpbnZhbGlkS2V5cyIsImlzVmFsaWRTdHJpbmdBcnJheSIsIkFycmF5IiwiaXNBcnJheSIsImZvckVhY2giLCJjbGFzc0NvbmZpZyIsImVycm9yTWVzc2FnZSIsIl92YWxpZGF0ZUNsYXNzQ29uZmlnIiwiY2xhc3NOYW1lIiwiRXJyb3IiLCJqb2luIiwidHlwZSIsInF1ZXJ5IiwibXV0YXRpb24iLCJ0cmltIiwiaW5wdXRGaWVsZHMiLCJvdXRwdXRGaWVsZHMiLCJjb25zdHJhaW50RmllbGRzIiwic29ydEZpZWxkcyIsImV2ZXJ5Iiwic29ydEZpZWxkIiwiaW5kZXgiLCJmaWVsZCIsImFzYyIsImRlc2MiLCJjcmVhdGUiLCJpbmNsdWRlcyIsImZpbmRBbGlhcyIsImdldEFsaWFzIiwiZGVzdHJveSIsImNyZWF0ZUFsaWFzIiwidXBkYXRlQWxpYXMiLCJkZXN0cm95QWxpYXMiLCJhcnJheSIsInNvbWUiLCJzIiwib2JqIiwiRGF0ZSIsIlByb21pc2UiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFFQSxNQUFNQSxzQkFBc0IsR0FBRyxnQkFBL0I7O0FBQ0EsTUFBTUMsZUFBZSxHQUFHLEdBQXhCOztBQUNBLE1BQU1DLGdCQUFnQixHQUFHLFFBQXpCOzs7QUFFQSxNQUFNQyxzQkFBTixDQUE2QjtBQU0zQkMsRUFBQUEsV0FBVyxDQUNUQyxNQUdDLEdBQUcsRUFKSyxFQUtUO0FBQ0EsU0FBS0Msa0JBQUwsR0FDRUQsTUFBTSxDQUFDQyxrQkFBUCxJQUNBLGdDQUNHLDRFQURILENBRkY7QUFLQSxTQUFLQyxlQUFMLEdBQXVCRixNQUFNLENBQUNFLGVBQTlCO0FBQ0EsU0FBS0MsU0FBTCxHQUFpQixDQUFDLENBQUNILE1BQU0sQ0FBQ0ksWUFBMUI7QUFDQSxTQUFLQyxjQUFMLEdBQXNCUixnQkFBdEI7QUFDRDs7QUFFRCxRQUFNUyxnQkFBTixHQUFzRDtBQUNwRCxRQUFJLEtBQUtILFNBQVQsRUFBb0I7QUFDbEIsWUFBTUksYUFBYSxHQUFHLE1BQU0sS0FBS0MsdUJBQUwsRUFBNUI7O0FBQ0EsVUFBSUQsYUFBSixFQUFtQjtBQUNqQixlQUFPQSxhQUFQO0FBQ0Q7QUFDRjs7QUFFRCxVQUFNRSxPQUFPLEdBQUcsTUFBTSxLQUFLUixrQkFBTCxDQUF3QlMsSUFBeEIsQ0FDcEJmLHNCQURvQixFQUVwQjtBQUFFZ0IsTUFBQUEsUUFBUSxFQUFFZjtBQUFaLEtBRm9CLEVBR3BCO0FBQUVnQixNQUFBQSxLQUFLLEVBQUU7QUFBVCxLQUhvQixDQUF0QjtBQU1BLFFBQUlDLGFB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QVQsR0FBa0IsQ0FBM0QsQ0FERSxHQUVILEtBRko7QUFHRCxDQUpEO0FBS0E7Ozs7Ozs7QUFLQSxNQUFNa0IsbUJBQW1CLEdBQUcsVUFBU3dDLEdBQVQsRUFBdUI7QUFDakQsU0FDRSxPQUFPQSxHQUFQLEtBQWUsUUFBZixJQUNBLENBQUNsQyxLQUFLLENBQUNDLE9BQU4sQ0FBY2lDLEdBQWQsQ0FERCxJQUVBQSxHQUFHLEtBQUssSUFGUixJQUdBQSxHQUFHLFlBQVlDLElBQWYsS0FBd0IsSUFIeEIsSUFJQUQsR0FBRyxZQUFZRSxPQUFmLEtBQTJCLElBTDdCO0FBT0QsQ0FSRDs7ZUF3RGU1RSxzQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCByZXF1aXJlZFBhcmFtZXRlciBmcm9tICcuLi8uLi9saWIvcmVxdWlyZWRQYXJhbWV0ZXInO1xuaW1wb3J0IERhdGFiYXNlQ29udHJvbGxlciBmcm9tICcuL0RhdGFiYXNlQ29udHJvbGxlcic7XG5pbXBvcnQgQ2FjaGVDb250cm9sbGVyIGZyb20gJy4vQ2FjaGVDb250cm9sbGVyJztcblxuY29uc3QgR3JhcGhRTENvbmZpZ0NsYXNzTmFtZSA9ICdfR3JhcGhRTENvbmZpZyc7XG5jb25zdCBHcmFwaFFMQ29uZmlnSWQgPSAnMSc7XG5jb25zdCBHcmFwaFFMQ29uZmlnS2V5ID0gJ2NvbmZpZyc7XG5cbmNsYXNzIFBhcnNlR3JhcGhRTENvbnRyb2xsZXIge1xuICBkYXRhYmFzZUNvbnRyb2xsZXI6IERhdGFiYXNlQ29udHJvbGxlcjtcbiAgY2FjaGVDb250cm9sbGVyOiBDYWNoZUNvbnRyb2xsZXI7XG4gIGlzTW91bnRlZDogYm9vbGVhbjtcbiAgY29uZmlnQ2FjaGVLZXk6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwYXJhbXM6IHtcbiAgICAgIGRhdGFiYXNlQ29udHJvbGxlcjogRGF0YWJhc2VDb250cm9sbGVyLFxuICAgICAgY2FjaGVDb250cm9sbGVyOiBDYWNoZUNvbnRyb2xsZXIsXG4gICAgfSA9IHt9XG4gICkge1xuICAgIHRoaXMuZGF0YWJhc2VDb250cm9sbGVyID1cbiAgICAgIHBhcmFtcy5kYXRhYmFzZUNvbnRyb2xsZXIgfHxcbiAgICAgIHJlcXVpcmVkUGFyYW1ldGVyKFxuICAgICAgICBgUGFyc2VHcmFwaFFMQ29udHJvbGxlciByZXF1aXJlcyBhIFwiZGF0YWJhc2VDb250cm9sbGVyXCIgdG8gYmUgaW5zdGFudGlhdGVkLmBcbiAgICAgICk7XG4gICAgdGhpcy5jYWNoZUNvbnRyb2xsZXIgPSBwYXJhbXMuY2FjaGVDb250cm9sbGVyO1xuICAgIHRoaXMuaXNNb3VudGVkID0gISFwYXJhbXMubW91bnRHcmFwaFFMO1xuICAgIHRoaXMuY29uZmlnQ2FjaGVLZXkgPSBHcmFwaFFMQ29uZmlnS2V5O1xuICB9XG5cbiAgYXN5bmMgZ2V0R3JhcGhRTENvbmZpZygpOiBQcm9taXNlPFBhcnNlR3JhcGhRTENvbmZpZz4ge1xuICAgIGlmICh0aGlzLmlzTW91bnRlZCkge1xuICAgICAgY29uc3QgX2NhY2hlZENvbmZpZyA9IGF3YWl0IHRoaXMuX2dldENhY2hlZEdyYXBoUUxDb25maWcoKTtcbiAgICAgIGlmIChfY2FjaGVkQ29uZmlnKSB7XG4gICAgICAgIHJldHVybiBfY2FjaGVkQ29uZmlnO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmRhdGFiYXNlQ29udHJvbGxlci5maW5kKFxuICAgICAgR3JhcGhRTENvbmZpZ0NsYXNzTmFtZSxcbiAgICAgIHsgb2JqZWN0SWQ6IEdyYXBoUUxDb25maWdJZCB9LFxuICAgICAgeyBsaW1pdDogMSB9XG4gICAgKTtcblxuICAgIGxldCBncmFwaFFMQ29uZmlnO1xuICAgIGlmIChyZXN1bHRzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAvLyBJZiB0aGVyZSBpcyBubyBjb25maWcgaW4gdGhlIGRhdGFiYXNlIC0gcmV0dXJuIGVtcHR5IGNvbmZpZy5cbiAgICAgIHJldHVybiB7fTtcbiAgICB9IGVsc2Uge1xuICAgICAgZ3JhcGhRTENvbmZpZyA9IHJlc3VsdHNbMF1bR3JhcGhRTENvbmZpZ0tleV07XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNNb3VudGVkKSB7XG4gICAgICB0aGlzLl9wdXRDYWNoZWRHcmFwaFFMQ29uZmlnKGdyYXBoUUxDb25maWcpO1xuICAgIH1cblxuICAgIHJldHVybiBncmFwaFFMQ29uZmlnO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlR3JhcGhRTENvbmZpZyhcbiAgICBncmFwaFFMQ29uZmlnOiBQYXJzZUdyYXBoUUxDb25maWdcbiAgKTogUHJvbWlzZTxQYXJzZUdyYXBoUUxDb25maWc+IHtcbiAgICAvLyB0aHJvd3MgaWYgaW52YWxpZFxuICAgIHRoaXMuX3ZhbGlkYXRlR3JhcGhRTENvbmZpZyhcbiAgICAgIGdyYXBoUUxDb25maWcgfHwgcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYSBncmFwaFFMQ29uZmlnIScpXG4gICAgKTtcblxuICAgIC8vIFRyYW5zZm9ybSBpbiBkb3Qgbm90YXRpb24gdG8gbWFrZSBzdXJlIGl0IHdvcmtzXG4gICAgY29uc3QgdXBkYXRlID0gT2JqZWN0LmtleXMoZ3JhcGhRTENvbmZpZykucmVkdWNlKFxuICAgICAgKGFjYywga2V5KSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgW0dyYXBoUUxDb25maWdLZXldOiB7XG4gICAgICAgICAgICAuLi5hY2NbR3JhcGhRTENvbmZpZ0tleV0sXG4gICAgICAgICAgICBba2V5XTogZ3JhcGhRTENvbmZpZ1trZXldLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgeyBbR3JhcGhRTENvbmZpZ0tleV06IHt9IH1cbiAgICApO1xuXG4gICAgYXdhaXQgdGhpcy5kYXRhYmFzZUNvbnRyb2xsZXIudXBkYXRlKFxuICAgICAgR3JhcGhRTENvbmZpZ0NsYXNzTmFtZSxcbiAgICAgIHsgb2JqZWN0SWQ6IEdyYXBoUUxDb25maWdJZCB9LFxuICAgICAgdXBkYXRlLFxuICAgICAgeyB1cHNlcnQ6IHRydWUgfVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5pc01vdW50ZWQpIHtcbiAgICAgIHRoaXMuX3B1dENhY2hlZEdyYXBoUUxDb25maWcoZ3JhcGhRTENvbmZpZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgcmVzcG9uc2U6IHsgcmVzdWx0OiB0cnVlIH0gfTtcbiAgfVxuXG4gIF9nZXRDYWNoZWRHcmFwaFFMQ29uZmlnKCkge1xuICAgIHJldHVybiB0aGlzLmNhY2hlQ29udHJvbGxlci5ncmFwaFFMLmdldCh0aGlzLmNvbmZpZ0NhY2hlS2V5KTtcbiAgfVxuXG4gIF9wdXRDYWNoZWRHcmFwaFFMQ29uZmlnKGdyYXBoUUxDb25maWc6IFBhcnNlR3JhcGhRTENvbmZpZykge1xuICAgIHJldHVybiB0aGlzLmNhY2hlQ29udHJvbGxlci5ncmFwaFFMLnB1dChcbiAgICAgIHRoaXMuY29uZmlnQ2FjaGVLZXksXG4gICAgICBncmFwaFFMQ29uZmlnLFxuICAgICAgNjAwMDBcbiAgICApO1xuICB9XG5cbiAgX3ZhbGlkYXRlR3JhcGhRTENvbmZpZyhncmFwaFFMQ29uZmlnOiA/UGFyc2VHcmFwaFFMQ29uZmlnKTogdm9pZCB7XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlczogc3RyaW5nID0gW107XG4gICAgaWYgKCFncmFwaFFMQ29uZmlnKSB7XG4gICAgICBlcnJvck1lc3NhZ2VzLnB1c2goJ2Nhbm5vdCBiZSB1bmRlZmluZWQsIG51bGwgb3IgZW1wdHknKTtcbiAgICB9IGVsc2UgaWYgKCFpc1ZhbGlkU2ltcGxlT2JqZWN0KGdyYXBoUUxDb25maWcpKSB7XG4gICAgICBlcnJvck1lc3NhZ2VzLnB1c2goJ211c3QgYmUgYSB2YWxpZCBvYmplY3QnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qge1xuICAgICAgICBlbmFibGVkRm9yQ2xhc3NlcyA9IG51bGwsXG4gICAgICAgIGRpc2FibGVkRm9yQ2xhc3NlcyA9IG51bGwsXG4gICAgICAgIGNsYXNzQ29uZmlncyA9IG51bGwsXG4gICAgICAgIC4uLmludmFsaWRLZXlzXG4gICAgICB9ID0gZ3JhcGhRTENvbmZpZztcblxuICAgICAgaWYgKE9iamVjdC5rZXlzKGludmFsaWRLZXlzKS5sZW5ndGgpIHtcbiAgICAgICAgZXJyb3JNZXNzYWdlcy5wdXNoKFxuICAgICAgICAgIGBlbmNvdW50ZXJlZCBpbnZhbGlkIGtleXM6IFske09iamVjdC5rZXlzKGludmFsaWRLZXlzKX1dYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICBlbmFibGVkRm9yQ2xhc3NlcyAhPT0gbnVsbCAmJlxuICAgICAgICAhaXNWYWxpZFN0cmluZ0FycmF5KGVuYWJsZWRGb3JDbGFzc2VzKVxuICAgICAgKSB7XG4gICAgICAgIGVycm9yTWVzc2FnZXMucHVzaChgXCJlbmFibGVkRm9yQ2xhc3Nlc1wiIGlzIG5vdCBhIHZhbGlkIGFycmF5YCk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIGRpc2FibGVkRm9yQ2xhc3NlcyAhPT0gbnVsbCAmJlxuICAgICAgICAhaXNWYWxpZFN0cmluZ0FycmF5KGRpc2FibGVkRm9yQ2xhc3NlcylcbiAgICAgICkge1xuICAgICAgICBlcnJvck1lc3NhZ2VzLnB1c2goYFwiZGlzYWJsZWRGb3JDbGFzc2VzXCIgaXMgbm90IGEgdmFsaWQgYXJyYXlgKTtcbiAgICAgIH1cbiAgICAgIGlmIChjbGFzc0NvbmZpZ3MgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY2xhc3NDb25maWdzKSkge1xuICAgICAgICAgIGNsYXNzQ29uZmlncy5mb3JFYWNoKGNsYXNzQ29uZmlnID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IHRoaXMuX3ZhbGlkYXRlQ2xhc3NDb25maWcoY2xhc3NDb25maWcpO1xuICAgICAgICAgICAgaWYgKGVycm9yTWVzc2FnZSkge1xuICAgICAgICAgICAgICBlcnJvck1lc3NhZ2VzLnB1c2goXG4gICAgICAgICAgICAgICAgYGNsYXNzQ29uZmlnOiR7Y2xhc3NDb25maWcuY2xhc3NOYW1lfSBpcyBpbnZhbGlkIGJlY2F1c2UgJHtlcnJvck1lc3NhZ2V9YFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVycm9yTWVzc2FnZXMucHVzaChgXCJjbGFzc0NvbmZpZ3NcIiBpcyBub3QgYSB2YWxpZCBhcnJheWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChlcnJvck1lc3NhZ2VzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGdyYXBoUUxDb25maWc6ICR7ZXJyb3JNZXNzYWdlcy5qb2luKCc7ICcpfWApO1xuICAgIH1cbiAgfVxuXG4gIF92YWxpZGF0ZUNsYXNzQ29uZmlnKGNsYXNzQ29uZmlnOiA/UGFyc2VHcmFwaFFMQ2xhc3NDb25maWcpOiBzdHJpbmcgfCB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRTaW1wbGVPYmplY3QoY2xhc3NDb25maWcpKSB7XG4gICAgICByZXR1cm4gJ2l0IG11c3QgYmUgYSB2YWxpZCBvYmplY3QnO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgdHlwZSA9IG51bGwsXG4gICAgICAgIHF1ZXJ5ID0gbnVsbCxcbiAgICAgICAgbXV0YXRpb24gPSBudWxsLFxuICAgICAgICAuLi5pbnZhbGlkS2V5c1xuICAgICAgfSA9IGNsYXNzQ29uZmlnO1xuICAgICAgaWYgKE9iamVjdC5rZXlzKGludmFsaWRLZXlzKS5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGBcImludmFsaWRLZXlzXCIgWyR7T2JqZWN0LmtleXMoXG4gICAgICAgICAgaW52YWxpZEtleXNcbiAgICAgICAgKX1dIHNob3VsZCBub3QgYmUgcHJlc2VudGA7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIGNsYXNzTmFtZSAhPT0gJ3N0cmluZycgfHwgIWNsYXNzTmFtZS50cmltKCkubGVuZ3RoKSB7XG4gICAgICAgIC8vIFRPRE8gY29uc2lkZXIgY2hlY2tpbmcgY2xhc3MgZXhpc3RzIGluIHNjaGVtYT9cbiAgICAgICAgcmV0dXJuIGBcImNsYXNzTmFtZVwiIG11c3QgYmUgYSB2YWxpZCBzdHJpbmdgO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGUgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkU2ltcGxlT2JqZWN0KHR5cGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGBcInR5cGVcIiBtdXN0IGJlIGEgdmFsaWQgb2JqZWN0YDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgaW5wdXRGaWVsZHMgPSBudWxsLFxuICAgICAgICAgIG91dHB1dEZpZWxkcyA9IG51bGwsXG4gICAgICAgICAgY29uc3RyYWludEZpZWxkcyA9IG51bGwsXG4gICAgICAgICAgc29ydEZpZWxkcyA9IG51bGwsXG4gICAgICAgICAgLi4uaW52YWxpZEtleXNcbiAgICAgICAgfSA9IHR5cGU7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhpbnZhbGlkS2V5cykubGVuZ3RoKSB7XG4gICAgICAgICAgcmV0dXJuIGBcInR5cGVcIiBjb250YWlucyBpbnZhbGlkIGtleXMsIFske09iamVjdC5rZXlzKGludmFsaWRLZXlzKX1dYDtcbiAgICAgICAgfSBlbHNlIGlmIChvdXRwdXRGaWVsZHMgIT09IG51bGwgJiYgIWlzVmFsaWRTdHJpbmdBcnJheShvdXRwdXRGaWVsZHMpKSB7XG4gICAgICAgICAgcmV0dXJuIGBcIm91dHB1dEZpZWxkc1wiIG11c3QgYmUgYSB2YWxpZCBzdHJpbmcgYXJyYXlgO1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIGNvbnN0cmFpbnRGaWVsZHMgIT09IG51bGwgJiZcbiAgICAgICAgICAhaXNWYWxpZFN0cmluZ0FycmF5KGNvbnN0cmFpbnRGaWVsZHMpXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBgXCJjb25zdHJhaW50RmllbGRzXCIgbXVzdCBiZSBhIHZhbGlkIHN0cmluZyBhcnJheWA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNvcnRGaWVsZHMgIT09IG51bGwpIHtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShzb3J0RmllbGRzKSkge1xuICAgICAgICAgICAgbGV0IGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgIHNvcnRGaWVsZHMuZXZlcnkoKHNvcnRGaWVsZCwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkU2ltcGxlT2JqZWN0KHNvcnRGaWVsZCkpIHtcbiAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBgXCJzb3J0RmllbGRcIiBhdCBpbmRleCAke2luZGV4fSBpcyBub3QgYSB2YWxpZCBvYmplY3RgO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCB7IGZpZWxkLCBhc2MsIGRlc2MsIC4uLmludmFsaWRLZXlzIH0gPSBzb3J0RmllbGQ7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKGludmFsaWRLZXlzKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGBcInNvcnRGaWVsZFwiIGF0IGluZGV4ICR7aW5kZXh9IGNvbnRhaW5zIGludmFsaWQga2V5cywgWyR7T2JqZWN0LmtleXMoXG4gICAgICAgICAgICAgICAgICAgIGludmFsaWRLZXlzXG4gICAgICAgICAgICAgICAgICApfV1gO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGZpZWxkICE9PSAnc3RyaW5nJyB8fCBmaWVsZC50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGBcInNvcnRGaWVsZFwiIGF0IGluZGV4ICR7aW5kZXh9IGRpZCBub3QgcHJvdmlkZSB0aGUgXCJmaWVsZFwiIGFzIGEgc3RyaW5nYDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGFzYyAhPT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICAgICAgICAgICAgIHR5cGVvZiBkZXNjICE9PSAnYm9vbGVhbidcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBgXCJzb3J0RmllbGRcIiBhdCBpbmRleCAke2luZGV4fSBkaWQgbm90IHByb3ZpZGUgXCJhc2NcIiBvciBcImRlc2NcIiBhcyBib29sZWFuc2A7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChlcnJvck1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGBcInNvcnRGaWVsZHNcIiBtdXN0IGJlIGEgdmFsaWQgYXJyYXkuYDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlucHV0RmllbGRzICE9PSBudWxsKSB7XG4gICAgICAgICAgaWYgKGlzVmFsaWRTaW1wbGVPYmplY3QoaW5wdXRGaWVsZHMpKSB7XG4gICAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICAgIGNyZWF0ZSA9IG51bGwsXG4gICAgICAgICAgICAgIHVwZGF0ZSA9IG51bGwsXG4gICAgICAgICAgICAgIC4uLmludmFsaWRLZXlzXG4gICAgICAgICAgICB9ID0gaW5wdXRGaWVsZHM7XG4gICAgICAgICAgICBpZiAoT2JqZWN0LmtleXMoaW52YWxpZEtleXMpLmxlbmd0aCkge1xuICAgICAgICAgICAgICByZXR1cm4gYFwiaW5wdXRGaWVsZHNcIiBjb250YWlucyBpbnZhbGlkIGtleXM6IFske09iamVjdC5rZXlzKFxuICAgICAgICAgICAgICAgIGludmFsaWRLZXlzXG4gICAgICAgICAgICAgICl9XWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAodXBkYXRlICE9PSBudWxsICYmICFpc1ZhbGlkU3RyaW5nQXJyYXkodXBkYXRlKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBgXCJpbnB1dEZpZWxkcy51cGRhdGVcIiBtdXN0IGJlIGEgdmFsaWQgc3RyaW5nIGFycmF5YDtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChjcmVhdGUgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWRTdHJpbmdBcnJheShjcmVhdGUpKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYFwiaW5wdXRGaWVsZHMuY3JlYXRlXCIgbXVzdCBiZSBhIHZhbGlkIHN0cmluZyBhcnJheWA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgIWNyZWF0ZS5pbmNsdWRlcygndXNlcm5hbWUnKSB8fFxuICAgICAgICAgICAgICAgICAgICAhY3JlYXRlLmluY2x1ZGVzKCdwYXNzd29yZCcpXG4gICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGBcImlucHV0RmllbGRzLmNyZWF0ZVwiIG11c3QgaW5jbHVkZSByZXF1aXJlZCBmaWVsZHMsIHVzZXJuYW1lIGFuZCBwYXNzd29yZGA7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBgXCJpbnB1dEZpZWxkc1wiIG11c3QgYmUgYSB2YWxpZCBvYmplY3RgO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5ICE9PSBudWxsKSB7XG4gICAgICAgIGlmIChpc1ZhbGlkU2ltcGxlT2JqZWN0KHF1ZXJ5KSkge1xuICAgICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIGZpbmQgPSBudWxsLFxuICAgICAgICAgICAgZ2V0ID0gbnVsbCxcbiAgICAgICAgICAgIGZpbmRBbGlhcyA9IG51bGwsXG4gICAgICAgICAgICBnZXRBbGlhcyA9IG51bGwsXG4gICAgICAgICAgICAuLi5pbnZhbGlkS2V5c1xuICAgICAgICAgIH0gPSBxdWVyeTtcbiAgICAgICAgICBpZiAoT2JqZWN0LmtleXMoaW52YWxpZEtleXMpLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGBcInF1ZXJ5XCIgY29udGFpbnMgaW52YWxpZCBrZXlzLCBbJHtPYmplY3Qua2V5cyhcbiAgICAgICAgICAgICAgaW52YWxpZEtleXNcbiAgICAgICAgICAgICl9XWA7XG4gICAgICAgICAgfSBlbHNlIGlmIChmaW5kICE9PSBudWxsICYmIHR5cGVvZiBmaW5kICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIHJldHVybiBgXCJxdWVyeS5maW5kXCIgbXVzdCBiZSBhIGJvb2xlYW5gO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZ2V0ICE9PSBudWxsICYmIHR5cGVvZiBnZXQgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcInF1ZXJ5LmdldFwiIG11c3QgYmUgYSBib29sZWFuYDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGZpbmRBbGlhcyAhPT0gbnVsbCAmJiB0eXBlb2YgZmluZEFsaWFzICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcInF1ZXJ5LmZpbmRBbGlhc1wiIG11c3QgYmUgYSBzdHJpbmdgO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZ2V0QWxpYXMgIT09IG51bGwgJiYgdHlwZW9mIGdldEFsaWFzICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcInF1ZXJ5LmdldEFsaWFzXCIgbXVzdCBiZSBhIHN0cmluZ2A7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBgXCJxdWVyeVwiIG11c3QgYmUgYSB2YWxpZCBvYmplY3RgO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobXV0YXRpb24gIT09IG51bGwpIHtcbiAgICAgICAgaWYgKGlzVmFsaWRTaW1wbGVPYmplY3QobXV0YXRpb24pKSB7XG4gICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgY3JlYXRlID0gbnVsbCxcbiAgICAgICAgICAgIHVwZGF0ZSA9IG51bGwsXG4gICAgICAgICAgICBkZXN0cm95ID0gbnVsbCxcbiAgICAgICAgICAgIGNyZWF0ZUFsaWFzID0gbnVsbCxcbiAgICAgICAgICAgIHVwZGF0ZUFsaWFzID0gbnVsbCxcbiAgICAgICAgICAgIGRlc3Ryb3lBbGlhcyA9IG51bGwsXG4gICAgICAgICAgICAuLi5pbnZhbGlkS2V5c1xuICAgICAgICAgIH0gPSBtdXRhdGlvbjtcbiAgICAgICAgICBpZiAoT2JqZWN0LmtleXMoaW52YWxpZEtleXMpLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGBcIm11dGF0aW9uXCIgY29udGFpbnMgaW52YWxpZCBrZXlzLCBbJHtPYmplY3Qua2V5cyhcbiAgICAgICAgICAgICAgaW52YWxpZEtleXNcbiAgICAgICAgICAgICl9XWA7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChjcmVhdGUgIT09IG51bGwgJiYgdHlwZW9mIGNyZWF0ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICByZXR1cm4gYFwibXV0YXRpb24uY3JlYXRlXCIgbXVzdCBiZSBhIGJvb2xlYW5gO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodXBkYXRlICE9PSBudWxsICYmIHR5cGVvZiB1cGRhdGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcIm11dGF0aW9uLnVwZGF0ZVwiIG11c3QgYmUgYSBib29sZWFuYDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGRlc3Ryb3kgIT09IG51bGwgJiYgdHlwZW9mIGRlc3Ryb3kgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGBcIm11dGF0aW9uLmRlc3Ryb3lcIiBtdXN0IGJlIGEgYm9vbGVhbmA7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChjcmVhdGVBbGlhcyAhPT0gbnVsbCAmJiB0eXBlb2YgY3JlYXRlQWxpYXMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gYFwibXV0YXRpb24uY3JlYXRlQWxpYXNcIiBtdXN0IGJlIGEgc3RyaW5nYDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHVwZGF0ZUFsaWFzICE9PSBudWxsICYmIHR5cGVvZiB1cGRhdGVBbGlhcyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBgXCJtdXRhdGlvbi51cGRhdGVBbGlhc1wiIG11c3QgYmUgYSBzdHJpbmdgO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZGVzdHJveUFsaWFzICE9PSBudWxsICYmIHR5cGVvZiBkZXN0cm95QWxpYXMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gYFwibXV0YXRpb24uZGVzdHJveUFsaWFzXCIgbXVzdCBiZSBhIHN0cmluZ2A7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBgXCJtdXRhdGlvblwiIG11c3QgYmUgYSB2YWxpZCBvYmplY3RgO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IGlzVmFsaWRTdHJpbmdBcnJheSA9IGZ1bmN0aW9uKGFycmF5KTogYm9vbGVhbiB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGFycmF5KVxuICAgID8gIWFycmF5LnNvbWUocyA9PiB0eXBlb2YgcyAhPT0gJ3N0cmluZycgfHwgcy50cmltKCkubGVuZ3RoIDwgMSlcbiAgICA6IGZhbHNlO1xufTtcbi8qKlxuICogRW5zdXJlcyB0aGUgb2JqIGlzIGEgc2ltcGxlIEpTT04ve31cbiAqIG9iamVjdCwgaS5lLiBub3QgYW4gYXJyYXksIG51bGwsIGRhdGVcbiAqIGV0Yy5cbiAqL1xuY29uc3QgaXNWYWxpZFNpbXBsZU9iamVjdCA9IGZ1bmN0aW9uKG9iaik6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmXG4gICAgIUFycmF5LmlzQXJyYXkob2JqKSAmJlxuICAgIG9iaiAhPT0gbnVsbCAmJlxuICAgIG9iaiBpbnN0YW5jZW9mIERhdGUgIT09IHRydWUgJiZcbiAgICBvYmogaW5zdGFuY2VvZiBQcm9taXNlICE9PSB0cnVlXG4gICk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhcnNlR3JhcGhRTENvbmZpZyB7XG4gIGVuYWJsZWRGb3JDbGFzc2VzPzogc3RyaW5nW107XG4gIGRpc2FibGVkRm9yQ2xhc3Nlcz86IHN0cmluZ1tdO1xuICBjbGFzc0NvbmZpZ3M/OiBQYXJzZUdyYXBoUUxDbGFzc0NvbmZpZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBhcnNlR3JhcGhRTENsYXNzQ29uZmlnIHtcbiAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gIC8qIFRoZSBgdHlwZWAgb2JqZWN0IGNvbnRhaW5zIG9wdGlvbnMgZm9yIGhvdyB0aGUgY2xhc3MgdHlwZXMgYXJlIGdlbmVyYXRlZCAqL1xuICB0eXBlOiA/e1xuICAgIC8qIEZpZWxkcyB0aGF0IGFyZSBhbGxvd2VkIHdoZW4gY3JlYXRpbmcgb3IgdXBkYXRpbmcgYW4gb2JqZWN0LiAqL1xuICAgIGlucHV0RmllbGRzOiA/e1xuICAgICAgLyogTGVhdmUgYmxhbmsgdG8gYWxsb3cgYWxsIGF2YWlsYWJsZSBmaWVsZHMgaW4gdGhlIHNjaGVtYS4gKi9cbiAgICAgIGNyZWF0ZT86IHN0cmluZ1tdLFxuICAgICAgdXBkYXRlPzogc3RyaW5nW10sXG4gICAgfSxcbiAgICAvKiBGaWVsZHMgb24gdGhlIGVkZ2VzIHRoYXQgY2FuIGJlIHJlc29sdmVkIGZyb20gYSBxdWVyeSwgaS5lLiB0aGUgUmVzdWx0IFR5cGUuICovXG4gICAgb3V0cHV0RmllbGRzOiA/KHN0cmluZ1tdKSxcbiAgICAvKiBGaWVsZHMgYnkgd2hpY2ggYSBxdWVyeSBjYW4gYmUgZmlsdGVyZWQsIGkuZS4gdGhlIGB3aGVyZWAgb2JqZWN0LiAqL1xuICAgIGNvbnN0cmFpbnRGaWVsZHM6ID8oc3RyaW5nW10pLFxuICAgIC8qIEZpZWxkcyBieSB3aGljaCBhIHF1ZXJ5IGNhbiBiZSBzb3J0ZWQ7ICovXG4gICAgc29ydEZpZWxkczogPyh7XG4gICAgICBmaWVsZDogc3RyaW5nLFxuICAgICAgYXNjOiBib29sZWFuLFxuICAgICAgZGVzYzogYm9vbGVhbixcbiAgICB9W10pLFxuICB9O1xuICAvKiBUaGUgYHF1ZXJ5YCBvYmplY3QgY29udGFpbnMgb3B0aW9ucyBmb3Igd2hpY2ggY2xhc3MgcXVlcmllcyBhcmUgZ2VuZXJhdGVkICovXG4gIHF1ZXJ5OiA/e1xuICAgIGdldDogP2Jvb2xlYW4sXG4gICAgZmluZDogP2Jvb2xlYW4sXG4gICAgZmluZEFsaWFzOiA/U3RyaW5nLFxuICAgIGdldEFsaWFzOiA/U3RyaW5nLFxuICB9O1xuICAvKiBUaGUgYG11dGF0aW9uYCBvYmplY3QgY29udGFpbnMgb3B0aW9ucyBmb3Igd2hpY2ggY2xhc3MgbXV0YXRpb25zIGFyZSBnZW5lcmF0ZWQgKi9cbiAgbXV0YXRpb246ID97XG4gICAgY3JlYXRlOiA/Ym9vbGVhbixcbiAgICB1cGRhdGU6ID9ib29sZWFuLFxuICAgIC8vIGRlbGV0ZSBpcyBhIHJlc2VydmVkIGtleSB3b3JkIGluIGpzXG4gICAgZGVzdHJveTogP2Jvb2xlYW4sXG4gICAgY3JlYXRlQWxpYXM6ID9TdHJpbmcsXG4gICAgdXBkYXRlQWxpYXM6ID9TdHJpbmcsXG4gICAgZGVzdHJveUFsaWFzOiA/U3RyaW5nLFxuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCBQYXJzZUdyYXBoUUxDb250cm9sbGVyO1xuZXhwb3J0IHsgR3JhcGhRTENvbmZpZ0NsYXNzTmFtZSwgR3JhcGhRTENvbmZpZ0lkLCBHcmFwaFFMQ29uZmlnS2V5IH07XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js new file mode 100644 index 0000000000..adb2b8fc68 --- /dev/null +++ b/lib/Controllers/PushController.js @@ -0,0 +1,268 @@ +"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"); + +var _logger = require("../logger"); + +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().catch(err => { + // add this to ignore badge update errors as default + if (config.stopOnBadgeUpdateError) throw err; + + _logger.logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`); + + _logger.logger.info(err && err.stack && err.stack.toString() || err && err.message || err.toString()); + + return Promise.resolve(); + }); + }).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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsInR0bE1zIiwidmFsdWVPZiIsInB1c2hUaW1lIiwiZ2V0UHVzaFRpbWUiLCJkYXRlIiwiZm9ybWF0UHVzaFRpbWUiLCJiYWRnZVVwZGF0ZSIsIlByb21pc2UiLCJyZXNvbHZlIiwiZGF0YSIsImJhZGdlIiwicmVzdFVwZGF0ZSIsInRvTG93ZXJDYXNlIiwiX19vcCIsImFtb3VudCIsIk51bWJlciIsInVwZGF0ZVdoZXJlIiwicmVzdFF1ZXJ5IiwiUmVzdFF1ZXJ5IiwiYnVpbGRSZXN0V2hlcmUiLCJ0aGVuIiwid3JpdGUiLCJSZXN0V3JpdGUiLCJyZXN0V2hlcmUiLCJydW5PcHRpb25zIiwibWFueSIsImV4ZWN1dGUiLCJwdXNoU3RhdHVzIiwic2V0SW5pdGlhbCIsIm9iamVjdElkIiwiY2F0Y2giLCJlcnIiLCJzdG9wT25CYWRnZVVwZGF0ZUVycm9yIiwibG9nZ2VyIiwiaW5mbyIsInN0YWNrIiwidG9TdHJpbmciLCJtZXNzYWdlIiwiYXVkaWVuY2VfaWQiLCJhdWRpZW5jZUlkIiwidXBkYXRlQXVkaWVuY2UiLCJsYXN0VXNlZCIsIl9fdHlwZSIsImlzbyIsInRvSVNPU3RyaW5nIiwidGltZXNVc2VkIiwiaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQiLCJwdXNoQ29udHJvbGxlclF1ZXVlIiwiZW5xdWV1ZSIsImZhaWwiLCJoYXNFeHBpcmF0aW9uVGltZSIsImV4cGlyYXRpb25UaW1lUGFyYW0iLCJleHBpcmF0aW9uVGltZSIsImlzRmluaXRlIiwiaGFzRXhwaXJhdGlvbkludGVydmFsIiwiZXhwaXJhdGlvbkludGVydmFsUGFyYW0iLCJoYXNQdXNoVGltZSIsInB1c2hUaW1lUGFyYW0iLCJpc0xvY2FsVGltZSIsInB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQiLCJvZmZzZXRQYXR0ZXJuIiwiaW5kZXhPZiIsImxlbmd0aCIsInRlc3QiLCJpc29TdHJpbmciLCJzdWJzdHJpbmciXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLGNBQU4sQ0FBcUI7QUFDMUJDLEVBQUFBLFFBQVEsQ0FDTkMsSUFBSSxHQUFHLEVBREQsRUFFTkMsS0FBSyxHQUFHLEVBRkYsRUFHTkMsTUFITSxFQUlOQyxJQUpNLEVBS05DLGlCQUFpQixHQUFHLE1BQU0sQ0FBRSxDQUx0QixFQU1OQyxHQUFHLEdBQUcsSUFBSUMsSUFBSixFQU5BLEVBT047QUFDQSxRQUFJLENBQUNKLE1BQU0sQ0FBQ0ssY0FBWixFQUE0QjtBQUMxQixZQUFNLElBQUlDLFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKLDRCQUZJLENBQU47QUFJRCxLQU5ELENBUUE7OztBQUNBVixJQUFBQSxJQUFJLENBQUNXLGVBQUwsR0FBdUJiLGNBQWMsQ0FBQ2MsaUJBQWYsQ0FBaUNaLElBQWpDLENBQXZCO0FBQ0FBLElBQUFBLElBQUksQ0FBQ2EsbUJBQUwsR0FBMkJmLGNBQWMsQ0FBQ2dCLHFCQUFmLENBQXFDZCxJQUFyQyxDQUEzQjs7QUFDQSxRQUFJQSxJQUFJLENBQUNXLGVBQUwsSUFBd0JYLElBQUksQ0FBQ2EsbUJBQWpDLEVBQXNEO0FBQ3BELFlBQU0sSUFBSUwsWUFBTUMsS0FBVixDQUNKRCxZQUFNQyxLQUFO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QjtBQUNuQixZQUFNLElBQUlmLFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKVixJQUFJLENBQUMsV0FBRCxDQUFKLEdBQW9CLHFCQUZoQixDQUFOO0FBSUQ7O0FBRUQsV0FBTztBQUNMdUIsTUFBQUEsSUFESztBQUVMc0QsTUFBQUE7QUFGSyxLQUFQO0FBSUQ7QUFFRDs7Ozs7OztBQUtBLFNBQU9DLDRCQUFQLENBQW9DRixhQUFwQyxFQUFvRTtBQUNsRSxVQUFNRyxhQUFhLEdBQUcsc0JBQXRCO0FBQ0EsV0FDRUgsYUFBYSxDQUFDSSxPQUFkLENBQXNCLEdBQXRCLE1BQStCSixhQUFhLENBQUNLLE1BQWQsR0FBdUIsQ0FBdEQsSUFBMkQ7QUFDM0RGLElBQUFBLGFBQWEsQ0FBQ0csSUFBZCxDQUFtQk4sYUFBbkIsQ0FGRixDQUZrRSxDQUsvRDtBQUNKO0FBRUQ7Ozs7Ozs7O0FBTUEsU0FBT3BELGNBQVAsQ0FBc0I7QUFDcEJELElBQUFBLElBRG9CO0FBRXBCc0QsSUFBQUE7QUFGb0IsR0FBdEIsRUFNRztBQUNELFFBQUlBLFdBQUosRUFBaUI7QUFDZjtBQUNBLFlBQU1NLFNBQVMsR0FBRzVELElBQUksQ0FBQ3dDLFdBQUwsRUFBbEI7QUFDQSxhQUFPb0IsU0FBUyxDQUFDQyxTQUFWLENBQW9CLENBQXBCLEVBQXVCRCxTQUFTLENBQUNILE9BQVYsQ0FBa0IsR0FBbEIsQ0FBdkIsQ0FBUDtBQUNEOztBQUNELFdBQU96RCxJQUFJLENBQUN3QyxXQUFMLEVBQVA7QUFDRDs7QUF2UnlCOzs7ZUEwUmJqRSxjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2UgfSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBSZXN0UXVlcnkgZnJvbSAnLi4vUmVzdFF1ZXJ5JztcbmltcG9ydCBSZXN0V3JpdGUgZnJvbSAnLi4vUmVzdFdyaXRlJztcbmltcG9ydCB7IG1hc3RlciB9IGZyb20gJy4uL0F1dGgnO1xuaW1wb3J0IHsgcHVzaFN0YXR1c0hhbmRsZXIgfSBmcm9tICcuLi9TdGF0dXNIYW5kbGVyJztcbmltcG9ydCB7IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMgfSBmcm9tICcuLi9QdXNoL3V0aWxzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCBjbGFzcyBQdXNoQ29udHJvbGxlciB7XG4gIHNlbmRQdXNoKFxuICAgIGJvZHkgPSB7fSxcbiAgICB3aGVyZSA9IHt9LFxuICAgIGNvbmZpZyxcbiAgICBhdXRoLFxuICAgIG9uUHVzaFN0YXR1c1NhdmVkID0gKCkgPT4ge30sXG4gICAgbm93ID0gbmV3IERhdGUoKVxuICApIHtcbiAgICBpZiAoIWNvbmZpZy5oYXNQdXNoU3VwcG9ydCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdNaXNzaW5nIHB1c2ggY29uZmlndXJhdGlvbidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gUmVwbGFjZSB0aGUgZXhwaXJhdGlvbl90aW1lIGFuZCBwdXNoX3RpbWUgd2l0aCBhIHZhbGlkIFVuaXggZXBvY2ggbWlsbGlzZWNvbmRzIHRpbWVcbiAgICBib2R5LmV4cGlyYXRpb25fdGltZSA9IFB1c2hDb250cm9sbGVyLmdldEV4cGlyYXRpb25UaW1lKGJvZHkpO1xuICAgIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCA9IFB1c2hDb250cm9sbGVyLmdldEV4cGlyYXRpb25JbnRlcnZhbChib2R5KTtcbiAgICBpZiAoYm9keS5leHBpcmF0aW9uX3RpbWUgJiYgYm9keS5leHBpcmF0aW9uX2ludGVydmFsKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgJ0JvdGggZXhwaXJhdGlvbl90aW1lIGFuZCBleHBpcmF0aW9uX2ludGVydmFsIGNhbm5vdCBiZSBzZXQnXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEltbWVkaWF0ZSBwdXNoXG4gICAgaWYgKFxuICAgICAgYm9keS5leHBpcmF0aW9uX2ludGVydmFsICYmXG4gICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGJvZHksICdwdXNoX3RpbWUnKVxuICAgICkge1xuICAgICAgY29uc3QgdHRsTXMgPSBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgKiAxMDAwO1xuICAgICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSBuZXcgRGF0ZShub3cudmFsdWVPZigpICsgdHRsTXMpLnZhbHVlT2YoKTtcbiAgICB9XG5cbiAgICBjb25zdCBwdXNoVGltZSA9IFB1c2hDb250cm9sbGVyLmdldFB1c2hUaW1lKGJvZHkpO1xuICAgIGlmIChwdXNoVGltZSAmJiBwdXNoVGltZS5kYXRlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgYm9keVsncHVzaF90aW1lJ10gPSBQdXNoQ29udHJvbGxlci5mb3JtYXRQdXNoVGltZShwdXNoVGltZSk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogSWYgdGhlIHJlcSBjYW4gcGFzcyB0aGUgY2hlY2tpbmcsIHdlIHJldHVybiBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIHdhaXRpbmdcbiAgICAvLyBwdXNoZXMgdG8gYmUgc2VudC4gV2UgcHJvYmFibHkgY2hhbmdlIHRoaXMgYmVoYXZpb3VyIGluIHRoZSBmdXR1cmUuXG4gICAgbGV0IGJhZGdlVXBkYXRlID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG5cbiAgICBpZiAoYm9keS5kYXRhICYmIGJvZHkuZGF0YS5iYWRnZSkge1xuICAgICAgY29uc3QgYmFkZ2UgPSBib2R5LmRhdGEuYmFkZ2U7XG4gICAgICBsZXQgcmVzdFVwZGF0ZSA9IHt9O1xuICAgICAgaWYgKHR5cGVvZiBiYWRnZSA9PSAnc3RyaW5nJyAmJiBiYWRnZS50b0xvd2VyQ2FzZSgpID09PSAnaW5jcmVtZW50Jykge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiAxIH0gfTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIHR5cGVvZiBiYWRnZSA9PSAnb2JqZWN0JyAmJlxuICAgICAgICB0eXBlb2YgYmFkZ2UuX19vcCA9PSAnc3RyaW5nJyAmJlxuICAgICAgICBiYWRnZS5fX29wLnRvTG93ZXJDYXNlKCkgPT0gJ2luY3JlbWVudCcgJiZcbiAgICAgICAgTnVtYmVyKGJhZGdlLmFtb3VudClcbiAgICAgICkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBiYWRnZS5hbW91bnQgfSB9O1xuICAgICAgfSBlbHNlIGlmIChOdW1iZXIoYmFkZ2UpKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiBiYWRnZSB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgXCJJbnZhbGlkIHZhbHVlIGZvciBiYWRnZSwgZXhwZWN0ZWQgbnVtYmVyIG9yICdJbmNyZW1lbnQnIG9yIHtpbmNyZW1lbnQ6IG51bWJlcn1cIjtcbiAgICAgIH1cblxuICAgICAgLy8gRm9yY2UgZmlsdGVyaW5nIG9uIG9ubHkgdmFsaWQgZGV2aWNlIHRva2Vuc1xuICAgICAgY29uc3QgdXBkYXRlV2hlcmUgPSBhcHBseURldmljZVRva2VuRXhpc3RzKHdoZXJlKTtcbiAgICAgIGJhZGdlVXBkYXRlID0gKCkgPT4ge1xuICAgICAgICAvLyBCdWlsZCBhIHJlYWwgUmVzdFF1ZXJ5IHNvIHdlIGNhbiB1c2UgaXQgaW4gUmVzdFdyaXRlXG4gICAgICAgIGNvbnN0IHJlc3RRdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIG1hc3Rlcihjb25maWcpLFxuICAgICAgICAgICdfSW5zdGFsbGF0aW9uJyxcbiAgICAgICAgICB1cGRhdGVXaGVyZVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gcmVzdFF1ZXJ5LmJ1aWxkUmVzdFdoZXJlKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgbWFzdGVyKGNvbmZpZyksXG4gICAgICAgICAgICAnX0luc3RhbGxhdGlvbicsXG4gICAgICAgICAgICByZXN0UXVlcnkucmVzdFdoZXJlLFxuICAgICAgICAgICAgcmVzdFVwZGF0ZVxuICAgICAgICAgICk7XG4gICAgICAgICAgd3JpdGUucnVuT3B0aW9ucy5tYW55ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICAgIGNvbnN0IHB1c2hTdGF0dXMgPSBwdXNoU3RhdHVzSGFuZGxlcihjb25maWcpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gcHVzaFN0YXR1cy5zZXRJbml0aWFsKGJvZHksIHdoZXJlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIG9uUHVzaFN0YXR1c1NhdmVkKHB1c2hTdGF0dXMub2JqZWN0SWQpO1xuICAgICAgICByZXR1cm4gYmFkZ2VVcGRhdGUoKS5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgIC8vIGFkZCB0aGlzIHRvIGlnbm9yZSBiYWRnZSB1cGRhdGUgZXJyb3JzIGFzIGRlZmF1bHRcbiAgICAgICAgICBpZiAoY29uZmlnLnN0b3BPbkJhZGdlVXBkYXRlRXJyb3IpIHRocm93IGVycjtcbiAgICAgICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgICAgIGBCYWRnZSB1cGRhdGUgZXJyb3Igd2lsbCBiZSBpZ25vcmVkIGZvciBwdXNoIHN0YXR1cyAke3B1c2hTdGF0dXMub2JqZWN0SWR9YFxuICAgICAgICAgICk7XG4gICAgICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAoZXJyICYmIGVyci5zdGFjayAmJiBlcnIuc3RhY2sudG9TdHJpbmcoKSkgfHxcbiAgICAgICAgICAgICAgKGVyciAmJiBlcnIubWVzc2FnZSkgfHxcbiAgICAgICAgICAgICAgZXJyLnRvU3RyaW5nKClcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBVcGRhdGUgYXVkaWVuY2UgbGFzdFVzZWQgYW5kIHRpbWVzVXNlZFxuICAgICAgICBpZiAoYm9keS5hdWRpZW5jZV9pZCkge1xuICAgICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgICAgdmFyIHVwZGF0ZUF1ZGllbmNlID0ge1xuICAgICAgICAgICAgbGFzdFVzZWQ6IHsgX190eXBlOiAnRGF0ZScsIGlzbzogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH0sXG4gICAgICAgICAgICB0aW1lc1VzZWQ6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogMSB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgbWFzdGVyKGNvbmZpZyksXG4gICAgICAgICAgICAnX0F1ZGllbmNlJyxcbiAgICAgICAgICAgIHsgb2JqZWN0SWQ6IGF1ZGllbmNlSWQgfSxcbiAgICAgICAgICAgIHVwZGF0ZUF1ZGllbmNlXG4gICAgICAgICAgKTtcbiAgICAgICAgICB3cml0ZS5leGVjdXRlKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRG9uJ3Qgd2FpdCBmb3IgdGhlIGF1ZGllbmNlIHVwZGF0ZSBwcm9taXNlIHRvIHJlc29sdmUuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYm9keSwgJ3B1c2hfdGltZScpICYmXG4gICAgICAgICAgY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0XG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShcbiAgICAgICAgICBib2R5LFxuICAgICAgICAgIHdoZXJlLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIHB1c2hTdGF0dXNcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+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..b545b57a2d --- /dev/null +++ b/lib/Controllers/SchemaController.js @@ -0,0 +1,1662 @@ +"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' + } + }, + _ExportProgress: { + objectId: { + type: 'String' + }, + id: { + type: 'String' + }, + masterKey: { + type: 'String' + }, + applicationId: { + type: 'String' + } + } +}); +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', '_ExportProgress']); +exports.systemClasses = systemClasses; +const volatileClasses = Object.freeze(['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig', '_GraphQLConfig', '_JobSchedule', '_Audience', '_ExportProgress']); // Anything that start with role + +const roleRegex = /^role:.*/; // Anything that starts with userField (allowed for protected fields only) + +const protectedFieldsPointerRegex = /^userField:.*/; // * permission + +const publicRegex = /^\*$/; +const authenticatedRegex = /^authenticated$/; +const requiresAuthenticationRegex = /^requiresAuthentication$/; +const clpPointerRegex = /^pointerFields$/; // regex for validating entities in protectedFields object + +const protectedFieldsRegex = Object.freeze([protectedFieldsPointerRegex, publicRegex, authenticatedRegex, roleRegex]); // clp regex + +const clpFieldsRegex = Object.freeze([clpPointerRegex, publicRegex, requiresAuthenticationRegex, roleRegex]); + +function validatePermissionKey(key, userIdRegExp) { + let matchesSome = false; + + for (const regEx of clpFieldsRegex) { + if (key.match(regEx) !== null) { + matchesSome = true; + break; + } + } // userId depends on startup options so it's dynamic + + + const valid = matchesSome || key.match(userIdRegExp) !== null; + + if (!valid) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid key for class level permissions`); + } +} + +function validateProtectedFieldsKey(key, userIdRegExp) { + let matchesSome = false; + + for (const regEx of protectedFieldsRegex) { + if (key.match(regEx) !== null) { + matchesSome = true; + break; + } + } // userId regex depends on launch options so it's dynamic + + + const valid = matchesSome || key.match(userIdRegExp) !== null; + + if (!valid) { + 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']); // validation before setting class-level permissions on collection + +function validateCLP(perms, fields, userIdRegExp) { + if (!perms) { + return; + } + + for (const operationKey in perms) { + if (CLPValidKeys.indexOf(operationKey) == -1) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `${operationKey} is not a valid operation for class level permissions`); + } + + const operation = perms[operationKey]; // proceed with next operationKey + // throws when root fields are of wrong type + + validateCLPjson(operation, operationKey); + + if (operationKey === 'readUserFields' || operationKey === 'writeUserFields') { + // validate grouped pointer permissions + // must be an array with field names + for (const fieldName of operation) { + validatePointerPermission(fieldName, fields, operationKey); + } // readUserFields and writerUserFields do not have nesdted fields + // proceed with next operationKey + + + continue; + } // validate protected fields + + + if (operationKey === 'protectedFields') { + for (const entity in operation) { + // throws on unexpected key + validateProtectedFieldsKey(entity, userIdRegExp); + const protectedFields = operation[entity]; + + if (!Array.isArray(protectedFields)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${protectedFields}' is not a valid value for protectedFields[${entity}] - expected an array.`); + } // if the field is in form of array + + + for (const field of protectedFields) { + // do not alloow to protect default fields + if (defaultColumns._Default[field]) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `Default field '${field}' can not be protected`); + } // field should exist on collection + + + if (!Object.prototype.hasOwnProperty.call(fields, field)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `Field '${field}' in protectedFields:${entity} does not exist`); + } + } + } // proceed with next operationKey + + + continue; + } // validate other fields + // Entity can be: + // "*" - Public, + // "requiresAuthentication" - authenticated users, + // "objectId" - _User id, + // "role:rolename", + // "pointerFields" - array of field names containing pointers to users + + + for (const entity in operation) { + // throws on unexpected key + validatePermissionKey(entity, userIdRegExp); // entity can be either: + // "pointerFields": string[] + + if (entity === 'pointerFields') { + const pointerFields = operation[entity]; + + if (Array.isArray(pointerFields)) { + for (const pointerField of pointerFields) { + validatePointerPermission(pointerField, fields, operation); + } + } else { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${pointerFields}' is not a valid value for ${operationKey}[${entity}] - expected an array.`); + } // proceed with next entity key + + + continue; + } // or [entity]: boolean + + + const permit = operation[entity]; + + if (permit !== true) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${permit}' is not a valid value for class level permissions ${operationKey}:${entity}:${permit}`); + } + } + } +} + +function validateCLPjson(operation, operationKey) { + if (operationKey === 'readUserFields' || operationKey === 'writeUserFields') { + if (!Array.isArray(operation)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${operation}' is not a valid value for class level permissions ${operationKey} - must be an array`); + } + } else { + if (typeof operation === 'object' && operation !== null) { + // ok to proceed + return; + } else { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${operation}' is not a valid value for class level permissions ${operationKey} - must be an object`); + } + } +} + +function validatePointerPermission(fieldName, fields, operation) { + // Uses collection schema to ensure the field is of type: + // - Pointer<_User> (pointers) + // - Array + // + // It's not possible to enforce type on Array's items in schema + // so we accept any Array field, and later when applying permissions + // only items that are pointers to _User are considered. + if (!(fields[fieldName] && (fields[fieldName].type == 'Pointer' && fields[fieldName].targetClass == '_User' || fields[fieldName].type == 'Array'))) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${fieldName}' is not a valid column for class level pointer permissions ${operation}`); + } +} + +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; + + const customIds = _Config.default.get(Parse.applicationId).allowCustomObjectId; + + const customIdRegEx = /^.{1,}$/u; // 1+ chars + + const autoIdRegEx = /^[a-zA-Z0-9]{1,}$/; + this.userIdRegEx = customIds ? customIdRegEx : autoIdRegEx; + } + + 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, this.userIdRegEx); + } // 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, this.userIdRegEx); + 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, action) { + 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(); + } + + const pointerFields = classPermissions[operation].pointerFields; + + if (Array.isArray(pointerFields) && pointerFields.length > 0) { + // any op except 'addField as part of create' is ok. + if (operation !== 'addField' || action === 'update') { + // We can allow adding field on update flow only. + 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, action) { + return SchemaController.validatePermission(this.getClassLevelPermissions(className), className, aclGroup, operation, action); + } + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9TY2hlbWFDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsImRlZmF1bHRDb2x1bW5zIiwiT2JqZWN0IiwiZnJlZXplIiwiX0RlZmF1bHQiLCJvYmplY3RJZCIsInR5cGUiLCJjcmVhdGVkQXQiLCJ1cGRhdGVkQXQiLCJBQ0wiLCJfVXNlciIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJlbWFpbCIsImVtYWlsVmVyaWZpZWQiLCJhdXRoRGF0YSIsIl9JbnN0YWxsYXRpb24iLCJpbnN0YWxsYXRpb25JZCIsImRldmljZVRva2VuIiwiY2hhbm5lbHMiLCJkZXZpY2VUeXBlIiwicHVzaFR5cGUiLCJHQ01TZW5kZXJJZCIsInRpbWVab25lIiwibG9jYWxlSWRlbnRpZmllciIsImJhZGdlIiwiYXBwVmVyc2lvbiIsImFwcE5hbWUiLCJhcHBJZGVudGlmaWVyIiwicGFyc2VWZXJzaW9uIiwiX1JvbGUiLCJuYW1lIiwidXNlcnMiLCJ0YXJnZXRDbGFzcyIsInJvbGVzIiwiX1Nlc3Npb24iLCJyZXN0cmljdGVkIiwidXNlciIsInNlc3Npb25Ub2tlbiIsImV4cGlyZXNBdCIsImNyZWF0ZWRXaXRoIiwiX1Byb2R1Y3QiLCJwcm9kdWN0SWRlbnRpZmllciIsImRvd25sb2FkIiwiZG93bmxvYWROYW1lIiwiaWNvbiIsIm9yZGVyIiwidGl0bGUiLCJzdWJ0aXRsZSIsIl9QdXNoU3RhdHVzIiwicHVzaFRpbWUiLCJzb3VyY2UiLCJxdWVyeSIsInBheWxvYWQiLCJleHBpcnkiLCJleHBpcmF0aW9uX2ludGVydmFsIiwic3RhdHVzIiwibnVtU2VudCIsIm51bUZhaWxlZCIsInB1c2hIYXNoIiwiZXJyb3JNZXNzYWdlIiwic2VudFBlclR5cGUiLCJmYWlsZWRQZXJUeXBlIiwic2VudFBlclVUQ09mZnNldCIsImZhaWxlZFBlclVUQ09mZnNldCIsImNvdW50IiwiX0pvYlN0YXR1cyIsImpvYk5hbWUiLCJtZXNzYWdlIiwicGFyYW1zIiwiZmluaXNoZWRBdCIsIl9Kb2JTY2hlZHVsZSIsImRlc2NyaXB0aW9uIiwic3RhcnRBZnRlciIsImRheXNPZldlZWsiLCJ0aW1lT2ZEYXkiLCJsYXN0UnVuIiwicmVwZWF0TWludXRlcyIsIl9Ib29rcyIsImZ1bmN0aW9uTmFtZSIsImNsYXNzTmFtZSIsInRyaWdnZXJOYW1lIiwidXJsIiwiX0dsb2JhbENvbmZpZyIsIm1hc3RlcktleU9ubHkiLCJfR3JhcGhRTENvbmZpZyIsImNvbmZpZyIsIl9BdWRpZW5jZSIsImxhc3RVc2VkIiwidGltZXNVc2VkIiwiX0V4cG9ydFByb2dyZXNzIiwiaWQiLCJtYXN0ZXJLZXkiLCJhcHBsaWNhdGlvbklkIiwicmVxdWlyZWRDb2x1bW5zIiwic3lzdGVtQ2xhc3NlcyIsInZvbGF0aWxlQ2xhc3NlcyIsInJvbGVSZWdleCIsInByb3RlY3RlZEZpZWxkc1BvaW50ZXJSZWdleCIsInB1YmxpY1JlZ2V4IiwiYXV0aGVudGljYXRlZFJlZ2V4IiwicmVxdWlyZXNBdXRoZW50aWNhdGlvblJlZ2V4IiwiY2xwUG9pbnRlclJlZ2V4IiwicHJvdGVjdGVkRmllbGRzUmVnZXgiLCJjbHBGaWVsZHNSZWdleCIsInZhbGlkYXRlUGVybWlzc2lvbktleSIsImtleSIsInVzZXJJZFJlZ0V4cCIsIm1hdGNoZXNTb21lIiwicmVnRXgiLCJtYXRjaCIsInZhbGlkIiwiRXJyb3IiLCJJTlZBTElEX0pTT04iLCJ2YWxpZGF0ZVByb3RlY3RlZEZpZWxkc0tleSIsIkNMUFZhbGlkS2V5cyIsInZhbGlkYXRlQ0xQIiwicGVybXMiLCJmaWVsZHMiLCJvcGVyYXRpb25LZXkiLCJpbmRleE9mIiwib3BlcmF0aW9uIiwidmFsaWRhdGVDTFBqc29uIiwiZmllbGROYW1lIiwidmFsaWRhdGVQb2ludGVyUGVybWlzc2lvbiIsImVudGl0eSIsInByb3RlY3RlZEZpZWxkcyIsIkFycmF5IiwiaXNBcnJheSIsImZpZWxkIiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwicG9pbnRlckZpZWxkcyIsInBvaW50ZXJGaWVsZCIsInBlcm1pdCIsImpvaW5DbGFzc1JlZ2V4IiwiY2xhc3NBbmRGaWVsZFJlZ2V4IiwiY2xhc3NOYW1lSXNWYWxpZCIsInRlc3QiLCJmaWVsZE5hbWVJc1ZhbGlkIiwiZmllbGROYW1lSXNWYWxpZEZvckNsYXNzIiwiaW52YWxpZENsYXNzTmFtZU1lc3NhZ2UiLCJpbnZhbGlkSnNvbkVycm9yIiwidmFsaWROb25SZWxhdGlvbk9yUG9pbnRlclR5cGVzIiwiZmllbGRUeXBlSXNJbnZhbGlkIiwiSU5WQUxJRF9DTEFTU19OQU1FIiwidW5kZWZpbmVkIiwiSU5DT1JSRUNUX1RZUEUiLCJjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hIiwic2NoZW1hIiwiaW5qZWN0RGVmYXVsdFNjaGVtYSIsIl9ycGVybSIsIl93cGVybSIsIl9oYXNoZWRfcGFzc3dvcmQiLCJjb252ZXJ0QWRhcHRlclNjaGVtYVRvUGFyc2VTY2hlbWEiLCJpbmRleGVzIiwia2V5cyIsImxlbmd0aCIsIlNjaGVtYURhdGEiLCJjb25zdHJ1Y3RvciIsImFsbFNjaGVtYXMiLCJfX2RhdGEiLCJfX3Byb3RlY3RlZEZpZWxkcyIsImZvckVhY2giLCJpbmNsdWRlcyIsImRlZmluZVByb3BlcnR5IiwiZ2V0IiwiZGF0YSIsImNsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsImNsYXNzUHJvdGVjdGVkRmllbGRzIiwidW5xIiwiU2V0IiwiZnJvbSIsImRlZmF1bHRTY2hlbWEiLCJfSG9va3NTY2hlbWEiLCJfR2xvYmFsQ29uZmlnU2NoZW1hIiwiX0dyYXBoUUxDb25maWdTY2hlbWEiLCJfUHVzaFN0YXR1c1NjaGVtYSIsIl9Kb2JTdGF0dXNTY2hlbWEiLCJfSm9iU2NoZWR1bGVTY2hlbWEiLCJfQXVkaWVuY2VTY2hlbWEiLCJWb2xhdGlsZUNsYXNzZXNTY2hlbWFzIiwiZGJUeXBlTWF0Y2hlc09iamVjdFR5cGUiLCJkYlR5cGUiLCJvYmplY3RUeXBlIiwidHlwZVRvU3RyaW5nIiwiU2NoZW1hQ29udHJvbGxlciIsImRhdGFiYXNlQWRhcHRlciIsInNjaGVtYUNhY2hlIiwiX2RiQWRhcHRlciIsIl9jYWNoZSIsInNjaGVtYURhdGEiLCJDb25maWciLCJjdXN0b21JZHMiLCJhbGxvd0N1c3RvbU9iamVjdElkIiwiY3VzdG9tSWRSZWdFeCIsImF1dG9JZFJlZ0V4IiwidXNlcklkUmVnRXgiLCJyZWxvYWREYXRhIiwib3B0aW9ucyIsImNsZWFyQ2FjaGUiLCJyZWxvYWREYXRhUHJvbWlzZSIsImdldEFsbENsYXNzZXMiLCJ0aGVuIiwiZXJyIiwic2V0QWxsQ2xhc3NlcyIsImFsbENsYXNzZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsIm1hcCIsImNhdGNoIiwiZXJyb3IiLCJjb25zb2xlIiwiZ2V0T25lU2NoZW1hIiwiYWxsb3dWb2xhdGlsZUNsYXNzZXMiLCJwcm9taXNlIiwiY2xlYXIiLCJjYWNoZWQiLCJvbmVTY2hlbWEiLCJmaW5kIiwicmVqZWN0IiwiYWRkQ2xhc3NJZk5vdEV4aXN0cyIsInZhbGlkYXRpb25FcnJvciIsInZhbGlkYXRlTmV3Q2xhc3MiLCJjb2RlIiwiY3JlYXRlQ2xhc3MiLCJEVVBMSUNBVEVfVkFMVUUiLCJ1cGRhdGVDbGFzcyIsInN1Ym1pdHRlZEZpZWxkcyIsImRhdGFiYXNlIiwiZXhpc3RpbmdGaWVsZHMiLCJfX29wIiwibmV3U2NoZW1hIiwiYnVpbGRNZXJnZWRTY2hlbWFPYmplY3QiLCJkZWZhdWx0RmllbGRzIiwiZnVsbE5ld1NjaGVtYSIsImFzc2lnbiIsInZhbGlkYXRlU2NoZW1hRGF0YSIsImRlbGV0ZWRGaWVsZHMiLCJpbnNlcnRlZEZpZWxkcyIsInB1c2giLCJkZWxldGVQcm9taXNlIiwiZGVsZXRlRmllbGRzIiwiZW5mb3JjZUZpZWxkcyIsInByb21pc2VzIiwiZW5mb3JjZUZpZWxkRXhpc3RzIiwiYWxsIiwicmVzdWx0cyIsImZpbHRlciIsInJlc3VsdCIsInNldFBlcm1pc3Npb25zIiwic2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQiLCJlbnN1cmVGaWVsZHMiLCJyZWxvYWRlZFNjaGVtYSIsImVuZm9yY2VDbGFzc0V4aXN0cyIsImV4aXN0aW5nRmllbGROYW1lcyIsIklOVkFMSURfS0VZX05BTUUiLCJmaWVsZFR5cGUiLCJkZWZhdWx0VmFsdWUiLCJkZWZhdWx0VmFsdWVUeXBlIiwiZ2V0VHlwZSIsInJlcXVpcmVkIiwiZ2VvUG9pbnRzIiwic2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zIiwic3BsaXQiLCJleHBlY3RlZFR5cGUiLCJnZXRFeHBlY3RlZFR5cGUiLCJhZGRGaWVsZElmTm90RXhpc3RzIiwiaSIsImRlbGV0ZUZpZWxkIiwiZmllbGROYW1lcyIsInNjaGVtYUZpZWxkcyIsImFkYXB0ZXIiLCJkZWxldGVDbGFzcyIsInZhbGlkYXRlT2JqZWN0Iiwib2JqZWN0IiwiZ2VvY291bnQiLCJleHBlY3RlZCIsInRoZW5WYWxpZGF0ZVJlcXVpcmVkQ29sdW1ucyIsInZhbGlkYXRlUmVxdWlyZWRDb2x1bW5zIiwiY29sdW1ucyIsIm1pc3NpbmdDb2x1bW5zIiwiY29sdW1uIiwidGVzdFBlcm1pc3Npb25zRm9yQ2xhc3NOYW1lIiwiYWNsR3JvdXAiLCJ0ZXN0UGVybWlzc2lvbnMiLCJnZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJjbGFzc1Blcm1pc3Npb25zIiwic29tZSIsImFjbCIsInZhbGlkYXRlUGVybWlzc2lvbiIsImFjdGlvbiIsIk9CSkVDVF9OT1RfRk9VTkQiLCJwZXJtaXNzaW9uRmllbGQiLCJPUEVSQVRJT05fRk9SQklEREVOIiwiaGFzQ2xhc3MiLCJsb2FkIiwiZGJBZGFwdGVyIiwicHV0UmVxdWVzdCIsInN5c1NjaGVtYUZpZWxkIiwiX2lkIiwib2xkRmllbGQiLCJmaWVsZElzRGVsZXRlZCIsIm5ld0ZpZWxkIiwic2NoZW1hUHJvbWlzZSIsIm9iaiIsImdldE9iamVjdFR5cGUiLCJfX3R5cGUiLCJpc28iLCJsYXRpdHVkZSIsImxvbmdpdHVkZSIsImJhc2U2NCIsImNvb3JkaW5hdGVzIiwib2JqZWN0cyIsIm9wcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFrQkE7O0FBQ0E7O0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7OztBQXJCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1BLEtBQUssR0FBR0MsT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkQsS0FBcEM7O0FBY0EsTUFBTUUsY0FBMEMsR0FBR0MsTUFBTSxDQUFDQyxNQUFQLENBQWM7QUFDL0Q7QUFDQUMsRUFBQUEsUUFBUSxFQUFFO0FBQ1JDLElBQUFBLFFBQVEsRUFBRTtBQUFFQyxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQURGO0FBRVJDLElBQUFBLFNBQVMsRUFBRTtBQUFFRCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUZIO0FBR1JFLElBQUFBLFNBQVMsRUFBRTtBQUFFRixNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUhIO0FBSVJHLElBQUFBLEdBQUcsRUFBRTtBQUFFSCxNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQUpHLEdBRnFEO0FBUS9EO0FBQ0FJLEVBQUFBLEtBQUssRUFBRTtBQUNMQyxJQUFBQSxRQUFRLEVBQUU7QUFBRUwsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FETDtBQUVMTSxJQUFBQSxRQUFRLEVBQUU7QUFBRU4sTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FGTDtBQUdMTyxJQUFBQSxLQUFLLEVBQUU7QUFBRVAsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FIRjtBQUlMUSxJQUFBQSxhQUFhLEVBQUU7QUFBRVIsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FKVjtBQUtMUyxJQUFBQSxRQUFRLEVBQUU7QUFBRVQsTUFBQUEsSUFBSSxFQUFFO0FBQVI7QUFMTCxHQVR3RDtBQWdCL0Q7QUFDQVUsRUFBQUEsYUFBYSxFQUFFO0FBQ2JDLElBQUFBLGNBQWMsRUFBRTtBQUFFWCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQURIO0FBRWJZLElBQUFBLFdBQVcsRUFBRTtBQUFFWixNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUZBO0FBR2JhLElBQUFBLFFBQVEsRUFBRTtBQUFFYixNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUhHO0FBSWJjLElBQUFBLFVBQVUsRUFBRTtBQUFFZCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUpDO0FBS2JlLElBQUFBLFFBQVEsRUFBRTtBQUFFZixNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUxHO0FBTWJnQixJQUFBQSxXQUFXLEVBQUU7QUFBRWhCLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBTkE7QUFPYmlCLElBQUFBLFFBQVEsRUFBRTtBQUFFakIsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FQRztBQVFia0IsSUFBQUEsZ0JBQWdCLEVBQUU7QUFBRWxCLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBUkw7QUFTYm1CLElBQUFBLEtBQUssRUFBRTtBQUFFbkIsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FUTTtBQVVib0IsSUFBQUEsVUFBVSxFQUFFO0FBQUVwQixNQUFBQSxJQUFJLEVBQUU7QUFBUixLQVZDO0FBV2JxQixJQUFBQSxPQUFPLEVBQUU7QUFBRXJCLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBWEk7QUFZYnNCLElBQUFBLGFBQWEsRUFBRTtBQUFFdEIsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FaRjtBQWFidUIsSUFBQUEsWUFBWSxFQUFFO0FBQUV2QixNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQWJELEdBakJnRDtBQWdDL0Q7QUFDQXdCLEVBQUFBLEtBQUssRUFBRTtBQUNMQyxJQUFBQSxJQUFJLEVBQUU7QUFBRXpCLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBREQ7QUFFTDBCLElBQUFBLEtBQUssRUFBRTtBQUFFMUIsTUFBQUEsSUFBSSxFQUFFLFVBQVI7QUFBb0IyQixNQUFBQSxXQUFXLEVBQUU7QUFBakMsS0FGRjtBQUdMQyxJQUFBQSxLQUFLLEVBQUU7QUFBRTVCLE1BQUFBLElBQUksRUFBRSxVQUFSO0FBQW9CMkIsTUFBQUEsV0FBVyxFQUFFO0FBQWpDO0FBSEYsR0FqQ3dEO0FBc0MvRDtBQUNBRSxFQUFBQSxRQUFRLEVBQUU7QUFDUkMsSUFBQUEsVUFBVSxFQUFFO0FBQUU5QixNQUFBQSxJQUFJLEVBQUU7QUFBUixLQURKO0FBRVIrQixJQUFBQSxJQUFJLEVBQUU7QUFBRS9CLE1BQUFBLElBQUksRUFBRSxTQUFSO0FBQW1CMkIsTUFBQUEsV0FBVyxFQUFFO0FBQWhDLEtBRkU7QUFHUmhCLElBQUFBLGNBQWMsRUFBRTtBQUFFWCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUhSO0FBSVJnQyxJQUFBQSxZQUFZLEVBQUU7QUFBRWhDLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBSk47QUFLUmlDLElBQUFBLFNBQVMsRUFBRTtBQUFFakMsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FMSDtBQU1Sa0MsSUFBQUEsV0FBVyxFQUFFO0FBQUVsQyxNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQU5MLEdBdkNxRDtBQStDL0RtQyxFQUFBQSxRQUFRLEVBQUU7QUFDUkMsSUFBQUEsaUJBQWlCLEVBQUU7QUFBRXBDLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBRFg7QUFFUnFDLElBQUFBLFFBQVEsRUFBRTtBQUFFckMsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FGRjtBQUdSc0MsSUFBQUEsWUFBWSxFQUFFO0FBQUV0QyxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUhOO0FBSVJ1QyxJQUFBQSxJQUFJLEVBQUU7QUFBRXZDLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBSkU7QUFLUndDLElBQUFBLEtBQUssRUFBRTtBQUFFeEMsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FMQztBQU1SeUMsSUFBQUEsS0FBSyxFQUFFO0FBQUV6QyxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQU5DO0FBT1IwQyxJQUFBQSxRQUFRLEVBQUU7QUFBRTFDLE1BQUFBLElBQUksRUFBRTtBQUFSO0FBUEYsR0EvQ3FEO0FBd0QvRDJDLEVBQUFBLFdBQVcsRUFBRTtBQUNYQyxJQUFBQSxRQUFRLEVBQUU7QUFBRTVDLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBREM7QUFFWDZDLElBQUFBLE1BQU0sRUFBRTtBQUFFN0MsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FGRztBQUVpQjtBQUM1QjhDLElBQUFBLEtBQUssRUFBRTtBQUFFOUMsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FISTtBQUdnQjtBQUMzQitDLElBQUFBLE9BQU8sRUFBRTtBQUFFL0MsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FKRTtBQUlrQjtBQUM3QnlDLElBQUFBLEtBQUssRUFBRTtBQUFFekMsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FMSTtBQU1YZ0QsSUFBQUEsTUFBTSxFQUFFO0FBQUVoRCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQU5HO0FBT1hpRCxJQUFBQSxtQkFBbUIsRUFBRTtBQUFFakQsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FQVjtBQVFYa0QsSUFBQUEsTUFBTSxFQUFFO0FBQUVsRCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQVJHO0FBU1htRCxJQUFBQSxPQUFPLEVBQUU7QUFBRW5ELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBVEU7QUFVWG9ELElBQUFBLFNBQVMsRUFBRTtBQUFFcEQsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FWQTtBQVdYcUQsSUFBQUEsUUFBUSxFQUFFO0FBQUVyRCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQVhDO0FBWVhzRCxJQUFBQSxZQUFZLEVBQUU7QUFBRXRELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBWkg7QUFhWHVELElBQUFBLFdBQVcsRUFBRTtBQUFFdkQsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FiRjtBQWNYd0QsSUFBQUEsYUFBYSxFQUFFO0FBQUV4RCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQWRKO0FBZVh5RCxJQUFBQSxnQkFBZ0IsRUFBRTtBQUFFekQsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FmUDtBQWdCWDBELElBQUFBLGtCQUFrQixFQUFFO0FBQUUxRCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQWhCVDtBQWlCWDJELElBQUFBLEtBQUssRUFBRTtBQUFFM0QsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FqQkksQ0FpQmdCOztBQWpCaEIsR0F4RGtEO0FBMkUvRDRELEVBQUFBLFVBQVUsRUFBRTtBQUNWQyxJQUFBQSxPQUFPLEVBQUU7QUFBRTdELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBREM7QUFFVjZDLElBQUFBLE1BQU0sRUFBRTtBQUFFN0MsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FGRTtBQUdWa0QsSUFBQUEsTUFBTSxFQUFFO0FBQUVsRCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUhFO0FBSVY4RCxJQUFBQSxPQUFPLEVBQUU7QUFBRTlELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBSkM7QUFLVitELElBQUFBLE1BQU0sRUFBRTtBQUFFL0QsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FMRTtBQUtrQjtBQUM1QmdFLElBQUFBLFVBQVUsRUFBRTtBQUFFaEUsTUFBQUEsSUFBSSxFQUFFO0FBQVI7QUFORixHQTNFbUQ7QUFtRi9EaUUsRUFBQUEsWUFBWSxFQUFFO0FBQ1pKLElBQUFBLE9BQU8sRUFBRTtBQUFFN0QsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FERztBQUVaa0UsSUFBQUEsV0FBVyxFQUFFO0FBQUVsRSxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUZEO0FBR1orRCxJQUFBQSxNQUFNLEVBQUU7QUFBRS9ELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBSEk7QUFJWm1FLElBQUFBLFVBQVUsRUFBRTtBQUFFbkUsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FKQTtBQUtab0UsSUFBQUEsVUFBVSxFQUFFO0FBQUVwRSxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUxBO0FBTVpxRSxJQUFBQSxTQUFTLEVBQUU7QUFBRXJFLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBTkM7QUFPWnNFLElBQUFBLE9BQU8sRUFBRTtBQUFFdEUsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FQRztBQVFadUUsSUFBQUEsYUFBYSxFQUFFO0FBQUV2RSxNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQVJILEdBbkZpRDtBQTZGL0R3RSxFQUFBQSxNQUFNLEVBQUU7QUFDTkMsSUFBQUEsWUFBWSxFQUFFO0FBQUV6RSxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQURSO0FBRU4wRSxJQUFBQSxTQUFTLEVBQUU7QUFBRTFFLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBRkw7QUFHTjJFLElBQUFBLFdBQVcsRUFBRTtBQUFFM0UsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FIUDtBQUlONEUsSUFBQUEsR0FBRyxFQUFFO0FBQUU1RSxNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQUpDLEdBN0Z1RDtBQW1HL0Q2RSxFQUFBQSxhQUFhLEVBQUU7QUFDYjlFLElBQUFBLFFBQVEsRUFBRTtBQUFFQyxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQURHO0FBRWIrRCxJQUFBQSxNQUFNLEVBQUU7QUFBRS9ELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBRks7QUFHYjhFLElBQUFBLGFBQWEsRUFBRTtBQUFFOUUsTUFBQUEsSUFBSSxFQUFFO0FBQVI7QUFIRixHQW5HZ0Q7QUF3Ry9EK0UsRUFBQUEsY0FBYyxFQUFFO0FBQ2RoRixJQUFBQSxRQUFRLEVBQUU7QUFBRUMsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FESTtBQUVkZ0YsSUFBQUEsTUFBTSxFQUFFO0FBQUVoRixNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQUZNLEdBeEcrQztBQTRHL0RpRixFQUFBQSxTQUFTLEVBQUU7QUFDVGxGLElBQUFBLFFBQVEsRUFBRTtBQUFFQyxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUREO0FBRVR5QixJQUFBQSxJQUFJLEVBQUU7QUFBRXpCLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBRkc7QUFHVDhDLElBQUFBLEtBQUssRUFBRTtBQUFFOUMsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FIRTtBQUdrQjtBQUMzQmtGLElBQUFBLFFBQVEsRUFBRTtBQUFFbEYsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FKRDtBQUtUbUYsSUFBQUEsU0FBUyxFQUFFO0FBQUVuRixNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQUxGLEdBNUdvRDtBQW1IL0RvRixFQUFBQSxlQUFlLEVBQUU7QUFDZnJGLElBQUFBLFFBQVEsRUFBRTtBQUFFQyxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQURLO0FBRWZxRixJQUFBQSxFQUFFLEVBQUU7QUFBRXJGLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBRlc7QUFHZnNGLElBQUFBLFNBQVMsRUFBRTtBQUFFdEYsTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FISTtBQUlmdUYsSUFBQUEsYUFBYSxFQUFFO0FBQUV2RixNQUFBQSxJQUFJLEVBQUU7QUFBUjtBQUpBO0FBbkg4QyxDQUFkLENBQW5EOztBQTJIQSxNQUFNd0YsZUFBZSxHQUFHNUYsTUFBTSxDQUFDQyxNQUFQLENBQWM7QUFDcENzQyxFQUFBQSxRQUFRLEVBQUUsQ0FBQyxtQkFBRCxFQUFzQixNQUF0QixFQUE4QixPQUE5QixFQUF1QyxPQUF2QyxFQUFnRCxVQUFoRCxDQUQwQjtBQUVwQ1gsRUFBQUEsS0FBSyxFQUFFLENBQUMsTUFBRCxFQUFTLEtBQVQ7QUFGNkIsQ0FBZCxDQUF4QjtBQUtBLE1BQU1pRSxhQUFhLEdBQUc3RixNQUFNLENBQUNDLE1BQVAsQ0FBYyxDQUNsQyxPQURrQyxFQUVsQyxlQUZrQyxFQUdsQyxPQUhrQyxFQUlsQyxVQUprQyxFQUtsQyxVQUxrQyxFQU1sQyxhQU5rQyxFQU9sQyxZQVBrQyxFQVFsQyxjQVJrQyxFQVNsQyxXQVRrQyxFQVVsQyxpQkFWa0MsQ0FBZCxDQUF0Qjs7QUFhQSxNQUFNNkYsZUFBZSxHQUFHOUYsTUFBTSxDQUFDQyxNQUFQLENBQWMsQ0FDcEMsWUFEb0MsRUFFcEMsYUFGb0MsRUFHcEMsUUFIb0MsRUFJcEMsZUFKb0MsRUFLcEMsZ0JBTG9DLEVBTXBDLGNBTm9DLEVBT3BDLFdBUG9DLEVBUXBDLGlCQVJvQyxDQUFkLENBQXhCLEMsQ0FXQTs7QUFDQSxNQUFNOEYsU0FBUyxHQUFHLFVBQWxCLEMsQ0FDQTs7QUFDQSxNQUFNQywyQkFBMkIsR0FBRyxlQUFwQyxDLENBQ0E7O0FBQ0EsTUFBTUMsV0FBVyxHQUFHLE1BQXBCO0FBRUEsTUFBTUMsa0JBQWtCLEdBQUcsaUJBQTNCO0FBRUEsTUFBTUMsMkJBQTJCLEdBQUcsMEJBQXBDO0FBRUEsTUFBTUMsZUFBZSxHQUFHLGlCQUF4QixDLENBRUE7O0FBQ0EsTUFBTUMsb0JBQW9CLEdBQUdyRyxNQUFNLENBQUNDLE1BQVAsQ0FBYyxDQUN6QytGLDJCQUR5QyxFQUV6Q0MsV0FGeUMsRUFHekNDLGtCQUh5QyxFQUl6Q0gsU0FKeUMsQ0FBZCxDQUE3QixDLENBT0E7O0FBQ0EsTUFBTU8sY0FBYyxHQUFHdEcsTUFBTSxDQUFDQyxNQUFQLENBQWMsQ0FDbkNtRyxlQURtQyxFQUVuQ0gsV0FGbUMsRUFHbkNFLDJCQUhtQyxFQUluQ0osU0FKbUMsQ0FBZCxDQUF2Qjs7QUFPQSxTQUFTUSxxQkFBVCxDQUErQkMsR0FBL0IsRUFBb0NDLFlBQXBDLEVBQWtEO0FBQ2hELE1BQUlDLFdBQVcsR0FBRyxLQUFsQjs7QUFDQSxPQUFLLE1BQU1DLEtBQVgsSUFBb0JMLGNBQXBCLEVBQW9DO0FBQ2xDLFFBQUlFLEdBQUcsQ0FBQ0ksS0FBSixDQUFVRCxLQUFWLE1BQXFCLElBQXpCLEVBQStCO0FBQzdCRCxNQUFBQSxXQUFXLEdBQUcsSUFBZDtBQUNBO0FBQ0Q7QUFDRixHQVArQyxDQVNoRDs7O0FBQ0EsUUFBTUcsS0FBSyxHQUFHSCxXQUFXLElBQUlGLEdBQUcsQ0FBQ0ksS0FBSixDQUFVSCxZQUFWLE1BQTRCLElBQXpEOztBQUNBLE1BQUksQ0FBQ0ksS0FBTCxFQUFZO0FBQ1YsVUFBTSxJQUFJaEgsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZQyxZQURSLEVBRUgsSUFBR1AsR0FBSSxrREFGSixDQUFOO0FBSUQ7QUFDRjs7QUFFRCxTQUFTUSwwQkFBVCxDQUFvQ1IsR0FBcEMsRUFBeUNDLFlBQXpDLEVBQXVEO0FBQ3JELE1BQUlDLFdBQVcsR0FBRyxLQUFsQjs7QUFDQSxPQUFLLE1BQU1DLEtBQVgsSUFBb0JOLG9CQUFwQixFQUEwQztBQUN4QyxRQUFJRyxHQUFHLENBQUNJLEtBQUosQ0FBVUQsS0FBVixNQUFxQixJQUF6QixFQUErQjtBQUM3QkQsTUFBQUEsV0FBVyxHQUFHLElBQWQ7QUFDQTtBQUNEO0FBQ0YsR0FQb0QsQ0FTckQ7OztBQUNBLFFBQU1HLEtBQUssR0FBR0gsV0FBVyxJQUFJRixHQUFHLENBQUNJLEtBQUosQ0FBVUgsWUFBVixNQUE0QixJQUF6RDs7QUFDQSxNQUFJLENBQUNJLEtBQUwsRUFBWTtBQUNWLFVBQU0sSUFBSWhILEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWUMsWUFEUixFQUVILElBQUdQLEdBQUksa0RBRkosQ0FBTjtBQUlEO0FBQ0Y7O0FBRUQsTUFBTVMsWUFBWSxHQUFHakgsTUFBTSxDQUFDQyxNQUFQLENBQWMsQ0FDakMsTUFEaUMsRUFFakMsT0FGaUMsRUFHakMsS0FIaUMsRUFJakMsUUFKaUMsRUFLakMsUUFMaUMsRUFNakMsUUFOaUMsRUFPakMsVUFQaUMsRUFRakMsZ0JBUmlDLEVBU2pDLGlCQVRpQyxFQVVqQyxpQkFWaUMsQ0FBZCxDQUFyQixDLENBYUE7O0FBQ0EsU0FBU2lILFdBQVQsQ0FDRUMsS0FERixFQUVFQyxNQUZGLEVBR0VYLFlBSEYsRUFJRTtBQUNBLE1BQUksQ0FBQ1UsS0FBTCxFQUFZO0FBQ1Y7QUFDRDs7QUFDRCxPQUFLLE1BQU1FLFlBQVgsSUFBMkJGLEtBQTNCLEVBQWtDO0FBQ2hDLFFBQUlGLFlBQVksQ0FBQ0ssT0FBYixDQUFxQkQsWUFBckIsS0FBc0MsQ0FBQyxDQUEzQyxFQUE4QztBQUM1QyxZQUFNLElBQUl4SCxLQUFLLENBQUNpSCxLQUFWLENBQ0pqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlDLFlBRFIsRUFFSCxHQUFFTSxZQUFhLHVEQUZaLENBQU47QUFJRDs7QUFFRCxVQUFNRSxTQUFTLEdBQUdKLEtBQUssQ0FBQ0UsWUFBRCxDQUF2QixDQVJnQyxDQVNoQztBQUVBOztBQUNBRyxJQUFBQSxlQUFlLENBQUNELFNBQUQsRUFBWUYsWUFBWixDQUFmOztBQUVBLFFBQ0VBLFlBQVksS0FBSyxnQkFBakIsSUFDQUEsWUFBWSxLQUFLLGlCQUZuQixFQUdFO0FBQ0E7QUFDQTtBQUNBLFdBQUssTUFBTUksU0FBWCxJQUF3QkYsU0FBeEIsRUFBbUM7QUFDakNHLFFBQUFBLHlCQUF5QixDQUFDRCxTQUFELEVBQVlMLE1BQVosRUFBb0JDLFlBQXBCLENBQXpCO0FBQ0QsT0FMRCxDQU1BO0FBQ0E7OztBQUNBO0FBQ0QsS0ExQitCLENBNEJoQzs7O0FBQ0EsUUFBSUEsWUFBWSxLQUFLLGlCQUFyQixFQUF3QztBQUN0QyxXQUFLLE1BQU1NLE1BQVgsSUFBcUJKLFNBQXJCLEVBQWdDO0FBQzlCO0FBQ0FQLFFBQUFBLDBCQUEwQixDQUFDVyxNQUFELEVBQVNsQixZQUFULENBQTFCO0FBRUEsY0FBTW1CLGVBQWUsR0FBR0wsU0FBUyxDQUFDSSxNQUFELENBQWpDOztBQUVBLFlBQUksQ0FBQ0UsS0FBSyxDQUFDQyxPQUFOLENBQWNGLGVBQWQsQ0FBTCxFQUFxQztBQUNuQyxnQkFBTSxJQUFJL0gsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZQyxZQURSLEVBRUgsSUFBR2EsZUFBZ0IsOENBQTZDRCxNQUFPLHdCQUZwRSxDQUFOO0FBSUQsU0FYNkIsQ0FhOUI7OztBQUNBLGFBQUssTUFBTUksS0FBWCxJQUFvQkgsZUFBcEIsRUFBcUM7QUFDbkM7QUFDQSxjQUFJN0gsY0FBYyxDQUFDRyxRQUFmLENBQXdCNkgsS0FBeEIsQ0FBSixFQUFvQztBQUNsQyxrQkFBTSxJQUFJbEksS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZQyxZQURSLEVBRUgsa0JBQWlCZ0IsS0FBTSx3QkFGcEIsQ0FBTjtBQUlELFdBUGtDLENBUW5DOzs7QUFDQSxjQUFJLENBQUMvSCxNQUFNLENBQUNnSSxTQUFQLENBQWlCQyxjQUFqQixDQUFnQ0MsSUFBaEMsQ0FBcUNkLE1BQXJDLEVBQTZDVyxLQUE3QyxDQUFMLEVBQTBEO0FBQ3hELGtCQUFNLElBQUlsSSxLQUFLLENBQUNpSCxLQUFWLENBQ0pqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlDLFlBRFIsRUFFSCxVQUFTZ0IsS0FBTSx3QkFBdUJKLE1BQU8saUJBRjFDLENBQU47QUFJRDtBQUNGO0FBQ0YsT0EvQnFDLENBZ0N0Qzs7O0FBQ0E7QUFDRCxLQS9EK0IsQ0FpRWhDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFLLE1BQU1BLE1BQVgsSUFBcUJKLFNBQXJCLEVBQWdDO0FBQzlCO0FBQ0FoQixNQUFBQSxxQkFBcUIsQ0FBQ29CLE1BQUQsRUFBU2xCLFlBQVQsQ0FBckIsQ0FGOEIsQ0FJOUI7QUFDQTs7QUFDQSxVQUFJa0IsTUFBTSxLQUFLLGVBQWYsRUFBZ0M7QUFDOUIsY0FBTVEsYUFBYSxHQUFHWixTQUFTLENBQUNJLE1BQUQsQ0FBL0I7O0FBRUEsWUFBSUUsS0FBSyxDQUFDQyxPQUFOLENBQWNLLGFBQWQsQ0FBSixFQUFrQztBQUNoQyxlQUFLLE1BQU1DLFlBQVgsSUFBMkJELGFBQTNCLEVBQTBDO0FBQ3hDVCxZQUFBQSx5QkFBeUIsQ0FBQ1UsWUFBRCxFQUFlaEIsTUFBZixFQUF1QkcsU0FBdkIsQ0FBekI7QUFDRDtBQUNGLFNBSkQsTUFJTztBQUNMLGdCQUFNLElBQUkxSCxLQUFLLENBQUNpSCxLQUFWLENBQ0pqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlDLFlBRFIsRUFFSCxJQUFHb0IsYUFBYyw4QkFBNkJkLFlBQWEsSUFBR00sTUFBTyx3QkFGbEUsQ0FBTjtBQUlELFNBWjZCLENBYTlCOzs7QUFDQTtBQUNELE9BckI2QixDQXVCOUI7OztBQUNBLFlBQU1VLE1BQU0sR0FBR2QsU0FBUyxDQUFDSSxNQUFELENBQXhCOztBQUVBLFVBQUlVLE1BQU0sS0FBSyxJQUFmLEVBQXFCO0FBQ25CLGNBQU0sSUFBSXhJLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWUMsWUFEUixFQUVILElBQUdzQixNQUFPLHNEQUFxRGhCLFlBQWEsSUFBR00sTUFBTyxJQUFHVSxNQUFPLEVBRjdGLENBQU47QUFJRDtBQUNGO0FBQ0Y7QUFDRjs7QUFFRCxTQUFTYixlQUFULENBQXlCRCxTQUF6QixFQUF5Q0YsWUFBekMsRUFBK0Q7QUFDN0QsTUFBSUEsWUFBWSxLQUFLLGdCQUFqQixJQUFxQ0EsWUFBWSxLQUFLLGlCQUExRCxFQUE2RTtBQUMzRSxRQUFJLENBQUNRLEtBQUssQ0FBQ0MsT0FBTixDQUFjUCxTQUFkLENBQUwsRUFBK0I7QUFDN0IsWUFBTSxJQUFJMUgsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZQyxZQURSLEVBRUgsSUFBR1EsU0FBVSxzREFBcURGLFlBQWEscUJBRjVFLENBQU47QUFJRDtBQUNGLEdBUEQsTUFPTztBQUNMLFFBQUksT0FBT0UsU0FBUCxLQUFxQixRQUFyQixJQUFpQ0EsU0FBUyxLQUFLLElBQW5ELEVBQXlEO0FBQ3ZEO0FBQ0E7QUFDRCxLQUhELE1BR087QUFDTCxZQUFNLElBQUkxSCxLQUFLLENBQUNpSCxLQUFWLENBQ0pqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlDLFlBRFIsRUFFSCxJQUFHUSxTQUFVLHNEQUFxREYsWUFBYSxzQkFGNUUsQ0FBTjtBQUlEO0FBQ0Y7QUFDRjs7QUFFRCxTQUFTSyx5QkFBVCxDQUNFRCxTQURGLEVBRUVMLE1BRkYsRUFHRUcsU0FIRixFQUlFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUNFLEVBQ0VILE1BQU0sQ0FBQ0ssU0FBRCxDQUFOLEtBQ0VMLE1BQU0sQ0FBQ0ssU0FBRCxDQUFOLENBQWtCckgsSUFBbEIsSUFBMEIsU0FBMUIsSUFDQWdILE1BQU0sQ0FBQ0ssU0FBRCxDQUFOLENBQWtCMUYsV0FBbEIsSUFBaUMsT0FEbEMsSUFFQ3FGLE1BQU0sQ0FBQ0ssU0FBRCxDQUFOLENBQWtCckgsSUFBbEIsSUFBMEIsT0FINUIsQ0FERixDQURGLEVBT0U7QUFDQSxVQUFNLElBQUlQLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWUMsWUFEUixFQUVILElBQUdVLFNBQVUsK0RBQThERixTQUFVLEVBRmxGLENBQU47QUFJRDtBQUNGOztBQUVELE1BQU1lLGNBQWMsR0FBRyxvQ0FBdkI7QUFDQSxNQUFNQyxrQkFBa0IsR0FBRyx5QkFBM0I7O0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEIxRCxTQUExQixFQUFzRDtBQUNwRDtBQUNBLFNBQ0U7QUFDQWUsSUFBQUEsYUFBYSxDQUFDeUIsT0FBZCxDQUFzQnhDLFNBQXRCLElBQW1DLENBQUMsQ0FBcEMsSUFDQTtBQUNBd0QsSUFBQUEsY0FBYyxDQUFDRyxJQUFmLENBQW9CM0QsU0FBcEIsQ0FGQSxJQUdBO0FBQ0E0RCxJQUFBQSxnQkFBZ0IsQ0FBQzVELFNBQUQ7QUFObEI7QUFRRCxDLENBRUQ7OztBQUNBLFNBQVM0RCxnQkFBVCxDQUEwQmpCLFNBQTFCLEVBQXNEO0FBQ3BELFNBQU9jLGtCQUFrQixDQUFDRSxJQUFuQixDQUF3QmhCLFNBQXhCLENBQVA7QUFDRCxDLENBRUQ7OztBQUNBLFNBQVNrQix3QkFBVCxDQUNFbEIsU0FERixFQUVFM0MsU0FGRixFQUdXO0FBQ1QsTUFBSSxDQUFDNEQsZ0JBQWdCLENBQUNqQixTQUFELENBQXJCLEVBQWtDO0FBQ2hDLFdBQU8sS0FBUDtBQUNEOztBQUNELE1BQUkxSCxjQUFjLENBQUNHLFFBQWYsQ0FBd0J1SCxTQUF4QixDQUFKLEVBQXdDO0FBQ3RDLFdBQU8sS0FBUDtBQUNEOztBQUNELE1BQUkxSCxjQUFjLENBQUMrRSxTQUFELENBQWQsSUFBNkIvRSxjQUFjLENBQUMrRSxTQUFELENBQWQsQ0FBMEIyQyxTQUExQixDQUFqQyxFQUF1RTtBQUNyRSxXQUFPLEtBQVA7QUFDRDs7QUFDRCxTQUFPLElBQVA7QUFDRDs7QUFFRCxTQUFTbUIsdUJBQVQsQ0FBaUM5RCxTQUFqQyxFQUE0RDtBQUMxRCxTQUNFLHdCQUNBQSxTQURBLEdBRUEsbUdBSEY7QUFLRDs7QUFFRCxNQUFNK0QsZ0JBQWdCLEdBQUcsSUFBSWhKLEtBQUssQ0FBQ2lILEtBQVYsQ0FDdkJqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlDLFlBRFcsRUFFdkIsY0FGdUIsQ0FBekI7QUFJQSxNQUFNK0IsOEJBQThCLEdBQUcsQ0FDckMsUUFEcUMsRUFFckMsUUFGcUMsRUFHckMsU0FIcUMsRUFJckMsTUFKcUMsRUFLckMsUUFMcUMsRUFNckMsT0FOcUMsRUFPckMsVUFQcUMsRUFRckMsTUFScUMsRUFTckMsT0FUcUMsRUFVckMsU0FWcUMsQ0FBdkMsQyxDQVlBOztBQUNBLE1BQU1DLGtCQUFrQixHQUFHLENBQUM7QUFBRTNJLEVBQUFBLElBQUY7QUFBUTJCLEVBQUFBO0FBQVIsQ0FBRCxLQUEyQjtBQUNwRCxNQUFJLENBQUMsU0FBRCxFQUFZLFVBQVosRUFBd0J1RixPQUF4QixDQUFnQ2xILElBQWhDLEtBQXlDLENBQTdDLEVBQWdEO0FBQzlDLFFBQUksQ0FBQzJCLFdBQUwsRUFBa0I7QUFDaEIsYUFBTyxJQUFJbEMsS0FBSyxDQUFDaUgsS0FBVixDQUFnQixHQUFoQixFQUFzQixRQUFPMUcsSUFBSyxxQkFBbEMsQ0FBUDtBQUNELEtBRkQsTUFFTyxJQUFJLE9BQU8yQixXQUFQLEtBQXVCLFFBQTNCLEVBQXFDO0FBQzFDLGFBQU84RyxnQkFBUDtBQUNELEtBRk0sTUFFQSxJQUFJLENBQUNMLGdCQUFnQixDQUFDekcsV0FBRCxDQUFyQixFQUFvQztBQUN6QyxhQUFPLElBQUlsQyxLQUFLLENBQUNpSCxLQUFWLENBQ0xqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlrQyxrQkFEUCxFQUVMSix1QkFBdUIsQ0FBQzdHLFdBQUQsQ0FGbEIsQ0FBUDtBQUlELEtBTE0sTUFLQTtBQUNMLGFBQU9rSCxTQUFQO0FBQ0Q7QUFDRjs7QUFDRCxNQUFJLE9BQU83SSxJQUFQLEtBQWdCLFFBQXBCLEVBQThCO0FBQzVCLFdBQU95SSxnQkFBUDtBQUNEOztBQUNELE1BQUlDLDhCQUE4QixDQUFDeEIsT0FBL0IsQ0FBdUNsSCxJQUF2QyxJQUErQyxDQUFuRCxFQUFzRDtBQUNwRCxXQUFPLElBQUlQLEtBQUssQ0FBQ2lILEtBQVYsQ0FDTGpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWW9DLGNBRFAsRUFFSix1QkFBc0I5SSxJQUFLLEVBRnZCLENBQVA7QUFJRDs7QUFDRCxTQUFPNkksU0FBUDtBQUNELENBekJEOztBQTJCQSxNQUFNRSw0QkFBNEIsR0FBSUMsTUFBRCxJQUFpQjtBQUNwREEsRUFBQUEsTUFBTSxHQUFHQyxtQkFBbUIsQ0FBQ0QsTUFBRCxDQUE1QjtBQUNBLFNBQU9BLE1BQU0sQ0FBQ2hDLE1BQVAsQ0FBYzdHLEdBQXJCO0FBQ0E2SSxFQUFBQSxNQUFNLENBQUNoQyxNQUFQLENBQWNrQyxNQUFkLEdBQXVCO0FBQUVsSixJQUFBQSxJQUFJLEVBQUU7QUFBUixHQUF2QjtBQUNBZ0osRUFBQUEsTUFBTSxDQUFDaEMsTUFBUCxDQUFjbUMsTUFBZCxHQUF1QjtBQUFFbkosSUFBQUEsSUFBSSxFQUFFO0FBQVIsR0FBdkI7O0FBRUEsTUFBSWdKLE1BQU0sQ0FBQ3RFLFNBQVAsS0FBcUIsT0FBekIsRUFBa0M7QUFDaEMsV0FBT3NFLE1BQU0sQ0FBQ2hDLE1BQVAsQ0FBYzFHLFFBQXJCO0FBQ0EwSSxJQUFBQSxNQUFNLENBQUNoQyxNQUFQLENBQWNvQyxnQkFBZCxHQUFpQztBQUFFcEosTUFBQUEsSUFBSSxFQUFFO0FBQVIsS0FBakM7QUFDRDs7QUFFRCxTQUFPZ0osTUFBUDtBQUNELENBWkQ7Ozs7QUFjQSxNQUFNSyxpQ0FBaUMsR0FBRyxVQUFtQjtBQUFBLE1BQWJMLE1BQWE7O0FBQzNELFNBQU9BLE1BQU0sQ0FBQ2hDLE1BQVAsQ0FBY2tDLE1BQXJCO0FBQ0EsU0FBT0YsTUFBTSxDQUFDaEMsTUFBUCxDQUFjbUMsTUFBckI7QUFFQUgsRUFBQUEsTUFBTSxDQUFDaEMsTUFBUCxDQUFjN0csR0FBZCxHQUFvQjtBQUFFSCxJQUFBQSxJQUFJLEVBQUU7QUFBUixHQUFwQjs7QUFFQSxNQUFJZ0osTUFBTSxDQUFDdEUsU0FBUCxLQUFxQixPQUF6QixFQUFrQztBQUNoQyxXQUFPc0UsTUFBTSxDQUFDaEMsTUFBUCxDQUFjdkcsUUFBckIsQ0FEZ0MsQ0FDRDs7QUFDL0IsV0FBT3VJLE1BQU0sQ0FBQ2hDLE1BQVAsQ0FBY29DLGdCQUFyQjtBQUNBSixJQUFBQSxNQUFNLENBQUNoQyxNQUFQLENBQWMxRyxRQUFkLEdBQXlCO0FBQUVOLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBQXpCO0FBQ0Q7O0FBRUQsTUFBSWdKLE1BQU0sQ0FBQ00sT0FBUCxJQUFrQjFKLE1BQU0sQ0FBQzJKLElBQVAsQ0FBWVAsTUFBTSxDQUFDTSxPQUFuQixFQUE0QkUsTUFBNUIsS0FBdUMsQ0FBN0QsRUFBZ0U7QUFDOUQsV0FBT1IsTUFBTSxDQUFDTSxPQUFkO0FBQ0Q7O0FBRUQsU0FBT04sTUFBUDtBQUNELENBakJEOztBQW1CQSxNQUFNUyxVQUFOLENBQWlCO0FBR2ZDLEVBQUFBLFdBQVcsQ0FBQ0MsVUFBVSxHQUFHLEVBQWQsRUFBa0JuQyxlQUFlLEdBQUcsRUFBcEMsRUFBd0M7QUFDakQsU0FBS29DLE1BQUwsR0FBYyxFQUFkO0FBQ0EsU0FBS0MsaUJBQUwsR0FBeUJyQyxlQUF6QjtBQUNBbUMsSUFBQUEsVUFBVSxDQUFDRyxPQUFYLENBQW1CZCxNQUFNLElBQUk7QUFDM0IsVUFBSXRELGVBQWUsQ0FBQ3FFLFFBQWhCLENBQXlCZixNQUFNLENBQUN0RSxTQUFoQyxDQUFKLEVBQWdEO0FBQzlDO0FBQ0Q7O0FBQ0Q5RSxNQUFBQSxNQUFNLENBQUNvSyxjQUFQLENBQXNCLElBQXRCLEVBQTRCaEIsTUFBTSxDQUFDdEUsU0FBbkMsRUFBOEM7QUFDNUN1RixRQUFBQSxHQUFHLEVBQUUsTUFBTTtBQUNULGNBQUksQ0FBQyxLQUFLTCxNQUFMLENBQVlaLE1BQU0sQ0FBQ3RFLFNBQW5CLENBQUwsRUFBb0M7QUFDbEMsa0JBQU13RixJQUFJLEdBQUcsRUFBYjtBQUNBQSxZQUFBQSxJQUFJLENBQUNsRCxNQUFMLEdBQWNpQyxtQkFBbUIsQ0FBQ0QsTUFBRCxDQUFuQixDQUE0QmhDLE1BQTFDO0FBQ0FrRCxZQUFBQSxJQUFJLENBQUNDLHFCQUFMLEdBQTZCLHVCQUFTbkIsTUFBTSxDQUFDbUIscUJBQWhCLENBQTdCO0FBQ0FELFlBQUFBLElBQUksQ0FBQ1osT0FBTCxHQUFlTixNQUFNLENBQUNNLE9BQXRCO0FBRUEsa0JBQU1jLG9CQUFvQixHQUFHLEtBQUtQLGlCQUFMLENBQzNCYixNQUFNLENBQUN0RSxTQURvQixDQUE3Qjs7QUFHQSxnQkFBSTBGLG9CQUFKLEVBQTBCO0FBQ3hCLG1CQUFLLE1BQU1oRSxHQUFYLElBQWtCZ0Usb0JBQWxCLEVBQXdDO0FBQ3RDLHNCQUFNQyxHQUFHLEdBQUcsSUFBSUMsR0FBSixDQUFRLENBQ2xCLElBQUlKLElBQUksQ0FBQ0MscUJBQUwsQ0FBMkIzQyxlQUEzQixDQUEyQ3BCLEdBQTNDLEtBQW1ELEVBQXZELENBRGtCLEVBRWxCLEdBQUdnRSxvQkFBb0IsQ0FBQ2hFLEdBQUQsQ0FGTCxDQUFSLENBQVo7QUFJQThELGdCQUFBQSxJQUFJLENBQUNDLHFCQUFMLENBQTJCM0MsZUFBM0IsQ0FBMkNwQixHQUEzQyxJQUFrRHFCLEtBQUssQ0FBQzhDLElBQU4sQ0FDaERGLEdBRGdELENBQWxEO0FBR0Q7QUFDRjs7QUFFRCxpQkFBS1QsTUFBTCxDQUFZWixNQUFNLENBQUN0RSxTQUFuQixJQUFnQ3dGLElBQWhDO0FBQ0Q7O0FBQ0QsaUJBQU8sS0FBS04sTUFBTCxDQUFZWixNQUFNLENBQUN0RSxTQUFuQixDQUFQO0FBQ0Q7QUExQjJDLE9BQTlDO0FBNEJELEtBaENELEVBSGlELENBcUNqRDs7QUFDQWdCLElBQUFBLGVBQWUsQ0FBQ29FLE9BQWhCLENBQXdCcEYsU0FBUyxJQUFJO0FBQ25DOUUsTUFBQUEsTUFBTSxDQUFDb0ssY0FBUCxDQUFzQixJQUF0QixFQUE0QnRGLFNBQTVCLEVBQXVDO0FBQ3JDdUYsUUFBQUEsR0FBRyxFQUFFLE1BQU07QUFDVCxjQUFJLENBQUMsS0FBS0wsTUFBTCxDQUFZbEYsU0FBWixDQUFMLEVBQTZCO0FBQzNCLGtCQUFNc0UsTUFBTSxHQUFHQyxtQkFBbUIsQ0FBQztBQUNqQ3ZFLGNBQUFBLFNBRGlDO0FBRWpDc0MsY0FBQUEsTUFBTSxFQUFFLEVBRnlCO0FBR2pDbUQsY0FBQUEscUJBQXFCLEVBQUU7QUFIVSxhQUFELENBQWxDO0FBS0Esa0JBQU1ELElBQUksR0FBRyxFQUFiO0FBQ0FBLFlBQUFBLElBQUksQ0FBQ2xELE1BQUwsR0FBY2dDLE1BQU0sQ0FBQ2hDLE1BQXJCO0FBQ0FrRCxZQUFBQSxJQUFJLENBQUNDLHFCQUFMLEdBQTZCbkIsTUFBTSxDQUFDbUIscUJBQXBDO0FBQ0FELFlBQUFBLElBQUksQ0FBQ1osT0FBTCxHQUFlTixNQUFNLENBQUNNLE9BQXRCO0FBQ0EsaUJBQUtNLE1BQUwsQ0FBWWxGLFNBQVosSUFBeUJ3RixJQUF6QjtBQUNEOztBQUNELGlCQUFPLEtBQUtOLE1BQUwsQ0FBWWxGLFNBQVosQ0FBUDtBQUNEO0FBZm9DLE9BQXZDO0FBaUJELEtBbEJEO0FBbUJEOztBQTVEYzs7QUErRGpCLE1BQU11RSxtQkFBbUIsR0FBRyxDQUFDO0FBQzNCdkUsRUFBQUEsU0FEMkI7QUFFM0JzQyxFQUFBQSxNQUYyQjtBQUczQm1ELEVBQUFBLHFCQUgyQjtBQUkzQmIsRUFBQUE7QUFKMkIsQ0FBRCxLQUtkO0FBQ1osUUFBTWtCLGFBQXFCLEdBQUc7QUFDNUI5RixJQUFBQSxTQUQ0QjtBQUU1QnNDLElBQUFBLE1BQU0sb0JBQ0RySCxjQUFjLENBQUNHLFFBRGQsTUFFQUgsY0FBYyxDQUFDK0UsU0FBRCxDQUFkLElBQTZCLEVBRjdCLE1BR0RzQyxNQUhDLENBRnNCO0FBTzVCbUQsSUFBQUE7QUFQNEIsR0FBOUI7O0FBU0EsTUFBSWIsT0FBTyxJQUFJMUosTUFBTSxDQUFDMkosSUFBUCxDQUFZRCxPQUFaLEVBQXFCRSxNQUFyQixLQUFnQyxDQUEvQyxFQUFrRDtBQUNoRGdCLElBQUFBLGFBQWEsQ0FBQ2xCLE9BQWQsR0FBd0JBLE9BQXhCO0FBQ0Q7O0FBQ0QsU0FBT2tCLGFBQVA7QUFDRCxDQW5CRDs7QUFxQkEsTUFBTUMsWUFBWSxHQUFHO0FBQUUvRixFQUFBQSxTQUFTLEVBQUUsUUFBYjtBQUF1QnNDLEVBQUFBLE1BQU0sRUFBRXJILGNBQWMsQ0FBQzZFO0FBQTlDLENBQXJCO0FBQ0EsTUFBTWtHLG1CQUFtQixHQUFHO0FBQzFCaEcsRUFBQUEsU0FBUyxFQUFFLGVBRGU7QUFFMUJzQyxFQUFBQSxNQUFNLEVBQUVySCxjQUFjLENBQUNrRjtBQUZHLENBQTVCO0FBSUEsTUFBTThGLG9CQUFvQixHQUFHO0FBQzNCakcsRUFBQUEsU0FBUyxFQUFFLGdCQURnQjtBQUUzQnNDLEVBQUFBLE1BQU0sRUFBRXJILGNBQWMsQ0FBQ29GO0FBRkksQ0FBN0I7O0FBSUEsTUFBTTZGLGlCQUFpQixHQUFHN0IsNEJBQTRCLENBQ3BERSxtQkFBbUIsQ0FBQztBQUNsQnZFLEVBQUFBLFNBQVMsRUFBRSxhQURPO0FBRWxCc0MsRUFBQUEsTUFBTSxFQUFFLEVBRlU7QUFHbEJtRCxFQUFBQSxxQkFBcUIsRUFBRTtBQUhMLENBQUQsQ0FEaUMsQ0FBdEQ7O0FBT0EsTUFBTVUsZ0JBQWdCLEdBQUc5Qiw0QkFBNEIsQ0FDbkRFLG1CQUFtQixDQUFDO0FBQ2xCdkUsRUFBQUEsU0FBUyxFQUFFLFlBRE87QUFFbEJzQyxFQUFBQSxNQUFNLEVBQUUsRUFGVTtBQUdsQm1ELEVBQUFBLHFCQUFxQixFQUFFO0FBSEwsQ0FBRCxDQURnQyxDQUFyRDs7QUFPQSxNQUFNVyxrQkFBa0IsR0FBRy9CLDRCQUE0QixDQUNyREUsbUJBQW1CLENBQUM7QUFDbEJ2RSxFQUFBQSxTQUFTLEVBQUUsY0FETztBQUVsQnNDLEVBQUFBLE1BQU0sRUFBRSxFQUZVO0FBR2xCbUQsRUFBQUEscUJBQXFCLEVBQUU7QUFITCxDQUFELENBRGtDLENBQXZEOztBQU9BLE1BQU1ZLGVBQWUsR0FBR2hDLDRCQUE0QixDQUNsREUsbUJBQW1CLENBQUM7QUFDbEJ2RSxFQUFBQSxTQUFTLEVBQUUsV0FETztBQUVsQnNDLEVBQUFBLE1BQU0sRUFBRXJILGNBQWMsQ0FBQ3NGLFNBRkw7QUFHbEJrRixFQUFBQSxxQkFBcUIsRUFBRTtBQUhMLENBQUQsQ0FEK0IsQ0FBcEQ7O0FBT0EsTUFBTWEsc0JBQXNCLEdBQUcsQ0FDN0JQLFlBRDZCLEVBRTdCSSxnQkFGNkIsRUFHN0JDLGtCQUg2QixFQUk3QkYsaUJBSjZCLEVBSzdCRixtQkFMNkIsRUFNN0JDLG9CQU42QixFQU83QkksZUFQNkIsQ0FBL0I7OztBQVVBLE1BQU1FLHVCQUF1QixHQUFHLENBQzlCQyxNQUQ4QixFQUU5QkMsVUFGOEIsS0FHM0I7QUFDSCxNQUFJRCxNQUFNLENBQUNsTCxJQUFQLEtBQWdCbUwsVUFBVSxDQUFDbkwsSUFBL0IsRUFBcUMsT0FBTyxLQUFQO0FBQ3JDLE1BQUlrTCxNQUFNLENBQUN2SixXQUFQLEtBQXVCd0osVUFBVSxDQUFDeEosV0FBdEMsRUFBbUQsT0FBTyxLQUFQO0FBQ25ELE1BQUl1SixNQUFNLEtBQUtDLFVBQVUsQ0FBQ25MLElBQTFCLEVBQWdDLE9BQU8sSUFBUDtBQUNoQyxNQUFJa0wsTUFBTSxDQUFDbEwsSUFBUCxLQUFnQm1MLFVBQVUsQ0FBQ25MLElBQS9CLEVBQXFDLE9BQU8sSUFBUDtBQUNyQyxTQUFPLEtBQVA7QUFDRCxDQVREOztBQVdBLE1BQU1vTCxZQUFZLEdBQUlwTCxJQUFELElBQXdDO0FBQzNELE1BQUksT0FBT0EsSUFBUCxLQUFnQixRQUFwQixFQUE4QjtBQUM1QixXQUFPQSxJQUFQO0FBQ0Q7O0FBQ0QsTUFBSUEsSUFBSSxDQUFDMkIsV0FBVCxFQUFzQjtBQUNwQixXQUFRLEdBQUUzQixJQUFJLENBQUNBLElBQUssSUFBR0EsSUFBSSxDQUFDMkIsV0FBWSxHQUF4QztBQUNEOztBQUNELFNBQVEsR0FBRTNCLElBQUksQ0FBQ0EsSUFBSyxFQUFwQjtBQUNELENBUkQsQyxDQVVBO0FBQ0E7OztBQUNlLE1BQU1xTCxnQkFBTixDQUF1QjtBQVFwQzNCLEVBQUFBLFdBQVcsQ0FBQzRCLGVBQUQsRUFBa0NDLFdBQWxDLEVBQW9EO0FBQzdELFNBQUtDLFVBQUwsR0FBa0JGLGVBQWxCO0FBQ0EsU0FBS0csTUFBTCxHQUFjRixXQUFkO0FBQ0EsU0FBS0csVUFBTCxHQUFrQixJQUFJakMsVUFBSixFQUFsQjtBQUNBLFNBQUtqQyxlQUFMLEdBQXVCbUUsZ0JBQU8xQixHQUFQLENBQVd4SyxLQUFLLENBQUM4RixhQUFqQixFQUFnQ2lDLGVBQXZEOztBQUVBLFVBQU1vRSxTQUFTLEdBQUdELGdCQUFPMUIsR0FBUCxDQUFXeEssS0FBSyxDQUFDOEYsYUFBakIsRUFBZ0NzRyxtQkFBbEQ7O0FBRUEsVUFBTUMsYUFBYSxHQUFHLFVBQXRCLENBUjZELENBUTNCOztBQUNsQyxVQUFNQyxXQUFXLEdBQUcsbUJBQXBCO0FBRUEsU0FBS0MsV0FBTCxHQUFtQkosU0FBUyxHQUFHRSxhQUFILEdBQW1CQyxXQUEvQztBQUNEOztBQUVERSxFQUFBQSxVQUFVLENBQUNDLE9BQTBCLEdBQUc7QUFBRUMsSUFBQUEsVUFBVSxFQUFFO0FBQWQsR0FBOUIsRUFBbUU7QUFDM0UsUUFBSSxLQUFLQyxpQkFBTCxJQUEwQixDQUFDRixPQUFPLENBQUNDLFVBQXZDLEVBQW1EO0FBQ2pELGFBQU8sS0FBS0MsaUJBQVo7QUFDRDs7QUFDRCxTQUFLQSxpQkFBTCxHQUF5QixLQUFLQyxhQUFMLENBQW1CSCxPQUFuQixFQUN0QkksSUFEc0IsQ0FFckIzQyxVQUFVLElBQUk7QUFDWixXQUFLK0IsVUFBTCxHQUFrQixJQUFJakMsVUFBSixDQUFlRSxVQUFmLEVBQTJCLEtBQUtuQyxlQUFoQyxDQUFsQjtBQUNBLGFBQU8sS0FBSzRFLGlCQUFaO0FBQ0QsS0FMb0IsRUFNckJHLEdBQUcsSUFBSTtBQUNMLFdBQUtiLFVBQUwsR0FBa0IsSUFBSWpDLFVBQUosRUFBbEI7QUFDQSxhQUFPLEtBQUsyQyxpQkFBWjtBQUNBLFlBQU1HLEdBQU47QUFDRCxLQVZvQixFQVl0QkQsSUFac0IsQ0FZakIsTUFBTSxDQUFFLENBWlMsQ0FBekI7QUFhQSxXQUFPLEtBQUtGLGlCQUFaO0FBQ0Q7O0FBRURDLEVBQUFBLGFBQWEsQ0FDWEgsT0FBMEIsR0FBRztBQUFFQyxJQUFBQSxVQUFVLEVBQUU7QUFBZCxHQURsQixFQUVhO0FBQ3hCLFFBQUlELE9BQU8sQ0FBQ0MsVUFBWixFQUF3QjtBQUN0QixhQUFPLEtBQUtLLGFBQUwsRUFBUDtBQUNEOztBQUNELFdBQU8sS0FBS2YsTUFBTCxDQUFZWSxhQUFaLEdBQTRCQyxJQUE1QixDQUFpQ0csVUFBVSxJQUFJO0FBQ3BELFVBQUlBLFVBQVUsSUFBSUEsVUFBVSxDQUFDakQsTUFBN0IsRUFBcUM7QUFDbkMsZUFBT2tELE9BQU8sQ0FBQ0MsT0FBUixDQUFnQkYsVUFBaEIsQ0FBUDtBQUNEOztBQUNELGFBQU8sS0FBS0QsYUFBTCxFQUFQO0FBQ0QsS0FMTSxDQUFQO0FBTUQ7O0FBRURBLEVBQUFBLGFBQWEsR0FBMkI7QUFDdEMsV0FBTyxLQUFLaEIsVUFBTCxDQUNKYSxhQURJLEdBRUpDLElBRkksQ0FFQzNDLFVBQVUsSUFBSUEsVUFBVSxDQUFDaUQsR0FBWCxDQUFlM0QsbUJBQWYsQ0FGZixFQUdKcUQsSUFISSxDQUdDM0MsVUFBVSxJQUFJO0FBQ2xCO0FBQ0EsV0FBSzhCLE1BQUwsQ0FDR2UsYUFESCxDQUNpQjdDLFVBRGpCLEVBRUdrRCxLQUZILENBRVNDLEtBQUssSUFDVkMsT0FBTyxDQUFDRCxLQUFSLENBQWMsK0JBQWQsRUFBK0NBLEtBQS9DLENBSEo7QUFLQTs7O0FBQ0EsYUFBT25ELFVBQVA7QUFDRCxLQVpJLENBQVA7QUFhRDs7QUFFRHFELEVBQUFBLFlBQVksQ0FDVnRJLFNBRFUsRUFFVnVJLG9CQUE2QixHQUFHLEtBRnRCLEVBR1ZmLE9BQTBCLEdBQUc7QUFBRUMsSUFBQUEsVUFBVSxFQUFFO0FBQWQsR0FIbkIsRUFJTztBQUNqQixRQUFJZSxPQUFPLEdBQUdSLE9BQU8sQ0FBQ0MsT0FBUixFQUFkOztBQUNBLFFBQUlULE9BQU8sQ0FBQ0MsVUFBWixFQUF3QjtBQUN0QmUsTUFBQUEsT0FBTyxHQUFHLEtBQUt6QixNQUFMLENBQVkwQixLQUFaLEVBQVY7QUFDRDs7QUFDRCxXQUFPRCxPQUFPLENBQUNaLElBQVIsQ0FBYSxNQUFNO0FBQ3hCLFVBQUlXLG9CQUFvQixJQUFJdkgsZUFBZSxDQUFDd0IsT0FBaEIsQ0FBd0J4QyxTQUF4QixJQUFxQyxDQUFDLENBQWxFLEVBQXFFO0FBQ25FLGNBQU13RixJQUFJLEdBQUcsS0FBS3dCLFVBQUwsQ0FBZ0JoSCxTQUFoQixDQUFiO0FBQ0EsZUFBT2dJLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQjtBQUNyQmpJLFVBQUFBLFNBRHFCO0FBRXJCc0MsVUFBQUEsTUFBTSxFQUFFa0QsSUFBSSxDQUFDbEQsTUFGUTtBQUdyQm1ELFVBQUFBLHFCQUFxQixFQUFFRCxJQUFJLENBQUNDLHFCQUhQO0FBSXJCYixVQUFBQSxPQUFPLEVBQUVZLElBQUksQ0FBQ1o7QUFKTyxTQUFoQixDQUFQO0FBTUQ7O0FBQ0QsYUFBTyxLQUFLbUMsTUFBTCxDQUFZdUIsWUFBWixDQUF5QnRJLFNBQXpCLEVBQW9DNEgsSUFBcEMsQ0FBeUNjLE1BQU0sSUFBSTtBQUN4RCxZQUFJQSxNQUFNLElBQUksQ0FBQ2xCLE9BQU8sQ0FBQ0MsVUFBdkIsRUFBbUM7QUFDakMsaUJBQU9PLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQlMsTUFBaEIsQ0FBUDtBQUNEOztBQUNELGVBQU8sS0FBS1osYUFBTCxHQUFxQkYsSUFBckIsQ0FBMEIzQyxVQUFVLElBQUk7QUFDN0MsZ0JBQU0wRCxTQUFTLEdBQUcxRCxVQUFVLENBQUMyRCxJQUFYLENBQ2hCdEUsTUFBTSxJQUFJQSxNQUFNLENBQUN0RSxTQUFQLEtBQXFCQSxTQURmLENBQWxCOztBQUdBLGNBQUksQ0FBQzJJLFNBQUwsRUFBZ0I7QUFDZCxtQkFBT1gsT0FBTyxDQUFDYSxNQUFSLENBQWUxRSxTQUFmLENBQVA7QUFDRDs7QUFDRCxpQkFBT3dFLFNBQVA7QUFDRCxTQVJNLENBQVA7QUFTRCxPQWJNLENBQVA7QUFjRCxLQXhCTSxDQUFQO0FBeUJELEdBMUdtQyxDQTRHcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBRyxFQUFBQSxtQkFBbUIsQ0FDakI5SSxTQURpQixFQUVqQnNDLE1BQW9CLEdBQUcsRUFGTixFQUdqQm1ELHFCQUhpQixFQUlqQmIsT0FBWSxHQUFHLEVBSkUsRUFLTztBQUN4QixRQUFJbUUsZUFBZSxHQUFHLEtBQUtDLGdCQUFMLENBQ3BCaEosU0FEb0IsRUFFcEJzQyxNQUZvQixFQUdwQm1ELHFCQUhvQixDQUF0Qjs7QUFLQSxRQUFJc0QsZUFBSixFQUFxQjtBQUNuQixVQUFJQSxlQUFlLFlBQVloTyxLQUFLLENBQUNpSCxLQUFyQyxFQUE0QztBQUMxQyxlQUFPZ0csT0FBTyxDQUFDYSxNQUFSLENBQWVFLGVBQWYsQ0FBUDtBQUNELE9BRkQsTUFFTyxJQUFJQSxlQUFlLENBQUNFLElBQWhCLElBQXdCRixlQUFlLENBQUNYLEtBQTVDLEVBQW1EO0FBQ3hELGVBQU9KLE9BQU8sQ0FBQ2EsTUFBUixDQUNMLElBQUk5TixLQUFLLENBQUNpSCxLQUFWLENBQWdCK0csZUFBZSxDQUFDRSxJQUFoQyxFQUFzQ0YsZUFBZSxDQUFDWCxLQUF0RCxDQURLLENBQVA7QUFHRDs7QUFDRCxhQUFPSixPQUFPLENBQUNhLE1BQVIsQ0FBZUUsZUFBZixDQUFQO0FBQ0Q7O0FBRUQsV0FBTyxLQUFLakMsVUFBTCxDQUNKb0MsV0FESSxDQUVIbEosU0FGRyxFQUdIcUUsNEJBQTRCLENBQUM7QUFDM0IvQixNQUFBQSxNQUQyQjtBQUUzQm1ELE1BQUFBLHFCQUYyQjtBQUczQmIsTUFBQUEsT0FIMkI7QUFJM0I1RSxNQUFBQTtBQUoyQixLQUFELENBSHpCLEVBVUo0SCxJQVZJLENBVUNqRCxpQ0FWRCxFQVdKd0QsS0FYSSxDQVdFQyxLQUFLLElBQUk7QUFDZCxVQUFJQSxLQUFLLElBQUlBLEtBQUssQ0FBQ2EsSUFBTixLQUFlbE8sS0FBSyxDQUFDaUgsS0FBTixDQUFZbUgsZUFBeEMsRUFBeUQ7QUFDdkQsY0FBTSxJQUFJcE8sS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZa0Msa0JBRFIsRUFFSCxTQUFRbEUsU0FBVSxrQkFGZixDQUFOO0FBSUQsT0FMRCxNQUtPO0FBQ0wsY0FBTW9JLEtBQU47QUFDRDtBQUNGLEtBcEJJLENBQVA7QUFxQkQ7O0FBRURnQixFQUFBQSxXQUFXLENBQ1RwSixTQURTLEVBRVRxSixlQUZTLEVBR1Q1RCxxQkFIUyxFQUlUYixPQUpTLEVBS1QwRSxRQUxTLEVBTVQ7QUFDQSxXQUFPLEtBQUtoQixZQUFMLENBQWtCdEksU0FBbEIsRUFDSjRILElBREksQ0FDQ3RELE1BQU0sSUFBSTtBQUNkLFlBQU1pRixjQUFjLEdBQUdqRixNQUFNLENBQUNoQyxNQUE5QjtBQUNBcEgsTUFBQUEsTUFBTSxDQUFDMkosSUFBUCxDQUFZd0UsZUFBWixFQUE2QmpFLE9BQTdCLENBQXFDckksSUFBSSxJQUFJO0FBQzNDLGNBQU1rRyxLQUFLLEdBQUdvRyxlQUFlLENBQUN0TSxJQUFELENBQTdCOztBQUNBLFlBQUl3TSxjQUFjLENBQUN4TSxJQUFELENBQWQsSUFBd0JrRyxLQUFLLENBQUN1RyxJQUFOLEtBQWUsUUFBM0MsRUFBcUQ7QUFDbkQsZ0JBQU0sSUFBSXpPLEtBQUssQ0FBQ2lILEtBQVYsQ0FBZ0IsR0FBaEIsRUFBc0IsU0FBUWpGLElBQUsseUJBQW5DLENBQU47QUFDRDs7QUFDRCxZQUFJLENBQUN3TSxjQUFjLENBQUN4TSxJQUFELENBQWYsSUFBeUJrRyxLQUFLLENBQUN1RyxJQUFOLEtBQWUsUUFBNUMsRUFBc0Q7QUFDcEQsZ0JBQU0sSUFBSXpPLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSixHQURJLEVBRUgsU0FBUWpGLElBQUssaUNBRlYsQ0FBTjtBQUlEO0FBQ0YsT0FYRDtBQWFBLGFBQU93TSxjQUFjLENBQUMvRSxNQUF0QjtBQUNBLGFBQU8rRSxjQUFjLENBQUM5RSxNQUF0QjtBQUNBLFlBQU1nRixTQUFTLEdBQUdDLHVCQUF1QixDQUN2Q0gsY0FEdUMsRUFFdkNGLGVBRnVDLENBQXpDO0FBSUEsWUFBTU0sYUFBYSxHQUNqQjFPLGNBQWMsQ0FBQytFLFNBQUQsQ0FBZCxJQUE2Qi9FLGNBQWMsQ0FBQ0csUUFEOUM7QUFFQSxZQUFNd08sYUFBYSxHQUFHMU8sTUFBTSxDQUFDMk8sTUFBUCxDQUFjLEVBQWQsRUFBa0JKLFNBQWxCLEVBQTZCRSxhQUE3QixDQUF0QjtBQUNBLFlBQU1aLGVBQWUsR0FBRyxLQUFLZSxrQkFBTCxDQUN0QjlKLFNBRHNCLEVBRXRCeUosU0FGc0IsRUFHdEJoRSxxQkFIc0IsRUFJdEJ2SyxNQUFNLENBQUMySixJQUFQLENBQVkwRSxjQUFaLENBSnNCLENBQXhCOztBQU1BLFVBQUlSLGVBQUosRUFBcUI7QUFDbkIsY0FBTSxJQUFJaE8sS0FBSyxDQUFDaUgsS0FBVixDQUFnQitHLGVBQWUsQ0FBQ0UsSUFBaEMsRUFBc0NGLGVBQWUsQ0FBQ1gsS0FBdEQsQ0FBTjtBQUNELE9BaENhLENBa0NkO0FBQ0E7OztBQUNBLFlBQU0yQixhQUF1QixHQUFHLEVBQWhDO0FBQ0EsWUFBTUMsY0FBYyxHQUFHLEVBQXZCO0FBQ0E5TyxNQUFBQSxNQUFNLENBQUMySixJQUFQLENBQVl3RSxlQUFaLEVBQTZCakUsT0FBN0IsQ0FBcUN6QyxTQUFTLElBQUk7QUFDaEQsWUFBSTBHLGVBQWUsQ0FBQzFHLFNBQUQsQ0FBZixDQUEyQjZHLElBQTNCLEtBQW9DLFFBQXhDLEVBQWtEO0FBQ2hETyxVQUFBQSxhQUFhLENBQUNFLElBQWQsQ0FBbUJ0SCxTQUFuQjtBQUNELFNBRkQsTUFFTztBQUNMcUgsVUFBQUEsY0FBYyxDQUFDQyxJQUFmLENBQW9CdEgsU0FBcEI7QUFDRDtBQUNGLE9BTkQ7QUFRQSxVQUFJdUgsYUFBYSxHQUFHbEMsT0FBTyxDQUFDQyxPQUFSLEVBQXBCOztBQUNBLFVBQUk4QixhQUFhLENBQUNqRixNQUFkLEdBQXVCLENBQTNCLEVBQThCO0FBQzVCb0YsUUFBQUEsYUFBYSxHQUFHLEtBQUtDLFlBQUwsQ0FBa0JKLGFBQWxCLEVBQWlDL0osU0FBakMsRUFBNENzSixRQUE1QyxDQUFoQjtBQUNEOztBQUNELFVBQUljLGFBQWEsR0FBRyxFQUFwQjtBQUNBLGFBQ0VGLGFBQWEsQ0FBQztBQUFELE9BQ1Z0QyxJQURILENBQ1EsTUFBTSxLQUFLTCxVQUFMLENBQWdCO0FBQUVFLFFBQUFBLFVBQVUsRUFBRTtBQUFkLE9BQWhCLENBRGQsRUFDcUQ7QUFEckQsT0FFR0csSUFGSCxDQUVRLE1BQU07QUFDVixjQUFNeUMsUUFBUSxHQUFHTCxjQUFjLENBQUM5QixHQUFmLENBQW1CdkYsU0FBUyxJQUFJO0FBQy9DLGdCQUFNckgsSUFBSSxHQUFHK04sZUFBZSxDQUFDMUcsU0FBRCxDQUE1QjtBQUNBLGlCQUFPLEtBQUsySCxrQkFBTCxDQUF3QnRLLFNBQXhCLEVBQW1DMkMsU0FBbkMsRUFBOENySCxJQUE5QyxDQUFQO0FBQ0QsU0FIZ0IsQ0FBakI7QUFJQSxlQUFPME0sT0FBTyxDQUFDdUMsR0FBUixDQUFZRixRQUFaLENBQVA7QUFDRCxPQVJILEVBU0d6QyxJQVRILENBU1E0QyxPQUFPLElBQUk7QUFDZkosUUFBQUEsYUFBYSxHQUFHSSxPQUFPLENBQUNDLE1BQVIsQ0FBZUMsTUFBTSxJQUFJLENBQUMsQ0FBQ0EsTUFBM0IsQ0FBaEI7QUFDQSxlQUFPLEtBQUtDLGNBQUwsQ0FDTDNLLFNBREssRUFFTHlGLHFCQUZLLEVBR0xnRSxTQUhLLENBQVA7QUFLRCxPQWhCSCxFQWlCRzdCLElBakJILENBaUJRLE1BQ0osS0FBS2QsVUFBTCxDQUFnQjhELDBCQUFoQixDQUNFNUssU0FERixFQUVFNEUsT0FGRixFQUdFTixNQUFNLENBQUNNLE9BSFQsRUFJRWdGLGFBSkYsQ0FsQkosRUF5QkdoQyxJQXpCSCxDQXlCUSxNQUFNLEtBQUtMLFVBQUwsQ0FBZ0I7QUFBRUUsUUFBQUEsVUFBVSxFQUFFO0FBQWQsT0FBaEIsQ0F6QmQsRUEwQkU7QUExQkYsT0EyQkdHLElBM0JILENBMkJRLE1BQU07QUFDVixhQUFLaUQsWUFBTCxDQUFrQlQsYUFBbEI7QUFDQSxjQUFNOUYsTUFBTSxHQUFHLEtBQUswQyxVQUFMLENBQWdCaEgsU0FBaEIsQ0FBZjtBQUNBLGNBQU04SyxjQUFzQixHQUFHO0FBQzdCOUssVUFBQUEsU0FBUyxFQUFFQSxTQURrQjtBQUU3QnNDLFVBQUFBLE1BQU0sRUFBRWdDLE1BQU0sQ0FBQ2hDLE1BRmM7QUFHN0JtRCxVQUFBQSxxQkFBcUIsRUFBRW5CLE1BQU0sQ0FBQ21CO0FBSEQsU0FBL0I7O0FBS0EsWUFBSW5CLE1BQU0sQ0FBQ00sT0FBUCxJQUFrQjFKLE1BQU0sQ0FBQzJKLElBQVAsQ0FBWVAsTUFBTSxDQUFDTSxPQUFuQixFQUE0QkUsTUFBNUIsS0FBdUMsQ0FBN0QsRUFBZ0U7QUFDOURnRyxVQUFBQSxjQUFjLENBQUNsRyxPQUFmLEdBQXlCTixNQUFNLENBQUNNLE9BQWhDO0FBQ0Q7O0FBQ0QsZUFBT2tHLGNBQVA7QUFDRCxPQXZDSCxDQURGO0FBMENELEtBOUZJLEVBK0ZKM0MsS0EvRkksQ0ErRkVDLEtBQUssSUFBSTtBQUNkLFVBQUlBLEtBQUssS0FBS2pFLFNBQWQsRUFBeUI7QUFDdkIsY0FBTSxJQUFJcEosS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZa0Msa0JBRFIsRUFFSCxTQUFRbEUsU0FBVSxrQkFGZixDQUFOO0FBSUQsT0FMRCxNQUtPO0FBQ0wsY0FBTW9JLEtBQU47QUFDRDtBQUNGLEtBeEdJLENBQVA7QUF5R0QsR0FoUm1DLENBa1JwQztBQUNBOzs7QUFDQTJDLEVBQUFBLGtCQUFrQixDQUFDL0ssU0FBRCxFQUErQztBQUMvRCxRQUFJLEtBQUtnSCxVQUFMLENBQWdCaEgsU0FBaEIsQ0FBSixFQUFnQztBQUM5QixhQUFPZ0ksT0FBTyxDQUFDQyxPQUFSLENBQWdCLElBQWhCLENBQVA7QUFDRCxLQUg4RCxDQUkvRDs7O0FBQ0EsV0FDRSxLQUFLYSxtQkFBTCxDQUF5QjlJLFNBQXpCLEVBQ0U7QUFERixLQUVHNEgsSUFGSCxDQUVRLE1BQU0sS0FBS0wsVUFBTCxDQUFnQjtBQUFFRSxNQUFBQSxVQUFVLEVBQUU7QUFBZCxLQUFoQixDQUZkLEVBR0dVLEtBSEgsQ0FHUyxNQUFNO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFPLEtBQUtaLFVBQUwsQ0FBZ0I7QUFBRUUsUUFBQUEsVUFBVSxFQUFFO0FBQWQsT0FBaEIsQ0FBUDtBQUNELEtBVEgsRUFVR0csSUFWSCxDQVVRLE1BQU07QUFDVjtBQUNBLFVBQUksS0FBS1osVUFBTCxDQUFnQmhILFNBQWhCLENBQUosRUFBZ0M7QUFDOUIsZUFBTyxJQUFQO0FBQ0QsT0FGRCxNQUVPO0FBQ0wsY0FBTSxJQUFJakYsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZQyxZQURSLEVBRUgsaUJBQWdCakMsU0FBVSxFQUZ2QixDQUFOO0FBSUQ7QUFDRixLQXBCSCxFQXFCR21JLEtBckJILENBcUJTLE1BQU07QUFDWDtBQUNBLFlBQU0sSUFBSXBOLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWUMsWUFEUixFQUVKLHVDQUZJLENBQU47QUFJRCxLQTNCSCxDQURGO0FBOEJEOztBQUVEK0csRUFBQUEsZ0JBQWdCLENBQ2RoSixTQURjLEVBRWRzQyxNQUFvQixHQUFHLEVBRlQsRUFHZG1ELHFCQUhjLEVBSVQ7QUFDTCxRQUFJLEtBQUt1QixVQUFMLENBQWdCaEgsU0FBaEIsQ0FBSixFQUFnQztBQUM5QixZQUFNLElBQUlqRixLQUFLLENBQUNpSCxLQUFWLENBQ0pqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlrQyxrQkFEUixFQUVILFNBQVFsRSxTQUFVLGtCQUZmLENBQU47QUFJRDs7QUFDRCxRQUFJLENBQUMwRCxnQkFBZ0IsQ0FBQzFELFNBQUQsQ0FBckIsRUFBa0M7QUFDaEMsYUFBTztBQUNMaUosUUFBQUEsSUFBSSxFQUFFbE8sS0FBSyxDQUFDaUgsS0FBTixDQUFZa0Msa0JBRGI7QUFFTGtFLFFBQUFBLEtBQUssRUFBRXRFLHVCQUF1QixDQUFDOUQsU0FBRDtBQUZ6QixPQUFQO0FBSUQ7O0FBQ0QsV0FBTyxLQUFLOEosa0JBQUwsQ0FDTDlKLFNBREssRUFFTHNDLE1BRkssRUFHTG1ELHFCQUhLLEVBSUwsRUFKSyxDQUFQO0FBTUQ7O0FBRURxRSxFQUFBQSxrQkFBa0IsQ0FDaEI5SixTQURnQixFQUVoQnNDLE1BRmdCLEVBR2hCbUQscUJBSGdCLEVBSWhCdUYsa0JBSmdCLEVBS2hCO0FBQ0EsU0FBSyxNQUFNckksU0FBWCxJQUF3QkwsTUFBeEIsRUFBZ0M7QUFDOUIsVUFBSTBJLGtCQUFrQixDQUFDeEksT0FBbkIsQ0FBMkJHLFNBQTNCLElBQXdDLENBQTVDLEVBQStDO0FBQzdDLFlBQUksQ0FBQ2lCLGdCQUFnQixDQUFDakIsU0FBRCxDQUFyQixFQUFrQztBQUNoQyxpQkFBTztBQUNMc0csWUFBQUEsSUFBSSxFQUFFbE8sS0FBSyxDQUFDaUgsS0FBTixDQUFZaUosZ0JBRGI7QUFFTDdDLFlBQUFBLEtBQUssRUFBRSx5QkFBeUJ6RjtBQUYzQixXQUFQO0FBSUQ7O0FBQ0QsWUFBSSxDQUFDa0Isd0JBQXdCLENBQUNsQixTQUFELEVBQVkzQyxTQUFaLENBQTdCLEVBQXFEO0FBQ25ELGlCQUFPO0FBQ0xpSixZQUFBQSxJQUFJLEVBQUUsR0FERDtBQUVMYixZQUFBQSxLQUFLLEVBQUUsV0FBV3pGLFNBQVgsR0FBdUI7QUFGekIsV0FBUDtBQUlEOztBQUNELGNBQU11SSxTQUFTLEdBQUc1SSxNQUFNLENBQUNLLFNBQUQsQ0FBeEI7QUFDQSxjQUFNeUYsS0FBSyxHQUFHbkUsa0JBQWtCLENBQUNpSCxTQUFELENBQWhDO0FBQ0EsWUFBSTlDLEtBQUosRUFBVyxPQUFPO0FBQUVhLFVBQUFBLElBQUksRUFBRWIsS0FBSyxDQUFDYSxJQUFkO0FBQW9CYixVQUFBQSxLQUFLLEVBQUVBLEtBQUssQ0FBQ2hKO0FBQWpDLFNBQVA7O0FBQ1gsWUFBSThMLFNBQVMsQ0FBQ0MsWUFBVixLQUEyQmhILFNBQS9CLEVBQTBDO0FBQ3hDLGNBQUlpSCxnQkFBZ0IsR0FBR0MsT0FBTyxDQUFDSCxTQUFTLENBQUNDLFlBQVgsQ0FBOUI7O0FBQ0EsY0FBSSxPQUFPQyxnQkFBUCxLQUE0QixRQUFoQyxFQUEwQztBQUN4Q0EsWUFBQUEsZ0JBQWdCLEdBQUc7QUFBRTlQLGNBQUFBLElBQUksRUFBRThQO0FBQVIsYUFBbkI7QUFDRCxXQUZELE1BRU8sSUFDTCxPQUFPQSxnQkFBUCxLQUE0QixRQUE1QixJQUNBRixTQUFTLENBQUM1UCxJQUFWLEtBQW1CLFVBRmQsRUFHTDtBQUNBLG1CQUFPO0FBQ0wyTixjQUFBQSxJQUFJLEVBQUVsTyxLQUFLLENBQUNpSCxLQUFOLENBQVlvQyxjQURiO0FBRUxnRSxjQUFBQSxLQUFLLEVBQUcsb0RBQW1EMUIsWUFBWSxDQUNyRXdFLFNBRHFFLENBRXJFO0FBSkcsYUFBUDtBQU1EOztBQUNELGNBQUksQ0FBQzNFLHVCQUF1QixDQUFDMkUsU0FBRCxFQUFZRSxnQkFBWixDQUE1QixFQUEyRDtBQUN6RCxtQkFBTztBQUNMbkMsY0FBQUEsSUFBSSxFQUFFbE8sS0FBSyxDQUFDaUgsS0FBTixDQUFZb0MsY0FEYjtBQUVMZ0UsY0FBQUEsS0FBSyxFQUFHLHVCQUFzQnBJLFNBQVUsSUFBRzJDLFNBQVUsNEJBQTJCK0QsWUFBWSxDQUMxRndFLFNBRDBGLENBRTFGLFlBQVd4RSxZQUFZLENBQUMwRSxnQkFBRCxDQUFtQjtBQUp2QyxhQUFQO0FBTUQ7QUFDRixTQXZCRCxNQXVCTyxJQUFJRixTQUFTLENBQUNJLFFBQWQsRUFBd0I7QUFDN0IsY0FBSSxPQUFPSixTQUFQLEtBQXFCLFFBQXJCLElBQWlDQSxTQUFTLENBQUM1UCxJQUFWLEtBQW1CLFVBQXhELEVBQW9FO0FBQ2xFLG1CQUFPO0FBQ0wyTixjQUFBQSxJQUFJLEVBQUVsTyxLQUFLLENBQUNpSCxLQUFOLENBQVlvQyxjQURiO0FBRUxnRSxjQUFBQSxLQUFLLEVBQUcsK0NBQThDMUIsWUFBWSxDQUNoRXdFLFNBRGdFLENBRWhFO0FBSkcsYUFBUDtBQU1EO0FBQ0Y7QUFDRjtBQUNGOztBQUVELFNBQUssTUFBTXZJLFNBQVgsSUFBd0IxSCxjQUFjLENBQUMrRSxTQUFELENBQXRDLEVBQW1EO0FBQ2pEc0MsTUFBQUEsTUFBTSxDQUFDSyxTQUFELENBQU4sR0FBb0IxSCxjQUFjLENBQUMrRSxTQUFELENBQWQsQ0FBMEIyQyxTQUExQixDQUFwQjtBQUNEOztBQUVELFVBQU00SSxTQUFTLEdBQUdyUSxNQUFNLENBQUMySixJQUFQLENBQVl2QyxNQUFaLEVBQW9CbUksTUFBcEIsQ0FDaEIvSSxHQUFHLElBQUlZLE1BQU0sQ0FBQ1osR0FBRCxDQUFOLElBQWVZLE1BQU0sQ0FBQ1osR0FBRCxDQUFOLENBQVlwRyxJQUFaLEtBQXFCLFVBRDNCLENBQWxCOztBQUdBLFFBQUlpUSxTQUFTLENBQUN6RyxNQUFWLEdBQW1CLENBQXZCLEVBQTBCO0FBQ3hCLGFBQU87QUFDTG1FLFFBQUFBLElBQUksRUFBRWxPLEtBQUssQ0FBQ2lILEtBQU4sQ0FBWW9DLGNBRGI7QUFFTGdFLFFBQUFBLEtBQUssRUFDSCx1RUFDQW1ELFNBQVMsQ0FBQyxDQUFELENBRFQsR0FFQSxRQUZBLEdBR0FBLFNBQVMsQ0FBQyxDQUFELENBSFQsR0FJQTtBQVBHLE9BQVA7QUFTRDs7QUFDRG5KLElBQUFBLFdBQVcsQ0FBQ3FELHFCQUFELEVBQXdCbkQsTUFBeEIsRUFBZ0MsS0FBS2dGLFdBQXJDLENBQVg7QUFDRCxHQWhhbUMsQ0FrYXBDOzs7QUFDQXFELEVBQUFBLGNBQWMsQ0FBQzNLLFNBQUQsRUFBb0JxQyxLQUFwQixFQUFnQ29ILFNBQWhDLEVBQXlEO0FBQ3JFLFFBQUksT0FBT3BILEtBQVAsS0FBaUIsV0FBckIsRUFBa0M7QUFDaEMsYUFBTzJGLE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0Q7O0FBQ0Q3RixJQUFBQSxXQUFXLENBQUNDLEtBQUQsRUFBUW9ILFNBQVIsRUFBbUIsS0FBS25DLFdBQXhCLENBQVg7QUFDQSxXQUFPLEtBQUtSLFVBQUwsQ0FBZ0IwRSx3QkFBaEIsQ0FBeUN4TCxTQUF6QyxFQUFvRHFDLEtBQXBELENBQVA7QUFDRCxHQXphbUMsQ0EyYXBDO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQWlJLEVBQUFBLGtCQUFrQixDQUNoQnRLLFNBRGdCLEVBRWhCMkMsU0FGZ0IsRUFHaEJySCxJQUhnQixFQUloQjtBQUNBLFFBQUlxSCxTQUFTLENBQUNILE9BQVYsQ0FBa0IsR0FBbEIsSUFBeUIsQ0FBN0IsRUFBZ0M7QUFDOUI7QUFDQUcsTUFBQUEsU0FBUyxHQUFHQSxTQUFTLENBQUM4SSxLQUFWLENBQWdCLEdBQWhCLEVBQXFCLENBQXJCLENBQVo7QUFDQW5RLE1BQUFBLElBQUksR0FBRyxRQUFQO0FBQ0Q7O0FBQ0QsUUFBSSxDQUFDc0ksZ0JBQWdCLENBQUNqQixTQUFELENBQXJCLEVBQWtDO0FBQ2hDLFlBQU0sSUFBSTVILEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWWlKLGdCQURSLEVBRUgsdUJBQXNCdEksU0FBVSxHQUY3QixDQUFOO0FBSUQsS0FYRCxDQWFBOzs7QUFDQSxRQUFJLENBQUNySCxJQUFMLEVBQVc7QUFDVCxhQUFPNkksU0FBUDtBQUNEOztBQUVELFVBQU11SCxZQUFZLEdBQUcsS0FBS0MsZUFBTCxDQUFxQjNMLFNBQXJCLEVBQWdDMkMsU0FBaEMsQ0FBckI7O0FBQ0EsUUFBSSxPQUFPckgsSUFBUCxLQUFnQixRQUFwQixFQUE4QjtBQUM1QkEsTUFBQUEsSUFBSSxHQUFJO0FBQUVBLFFBQUFBO0FBQUYsT0FBUjtBQUNEOztBQUVELFFBQUlBLElBQUksQ0FBQzZQLFlBQUwsS0FBc0JoSCxTQUExQixFQUFxQztBQUNuQyxVQUFJaUgsZ0JBQWdCLEdBQUdDLE9BQU8sQ0FBQy9QLElBQUksQ0FBQzZQLFlBQU4sQ0FBOUI7O0FBQ0EsVUFBSSxPQUFPQyxnQkFBUCxLQUE0QixRQUFoQyxFQUEwQztBQUN4Q0EsUUFBQUEsZ0JBQWdCLEdBQUc7QUFBRTlQLFVBQUFBLElBQUksRUFBRThQO0FBQVIsU0FBbkI7QUFDRDs7QUFDRCxVQUFJLENBQUM3RSx1QkFBdUIsQ0FBQ2pMLElBQUQsRUFBTzhQLGdCQUFQLENBQTVCLEVBQXNEO0FBQ3BELGNBQU0sSUFBSXJRLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWW9DLGNBRFIsRUFFSCx1QkFBc0JwRSxTQUFVLElBQUcyQyxTQUFVLDRCQUEyQitELFlBQVksQ0FDbkZwTCxJQURtRixDQUVuRixZQUFXb0wsWUFBWSxDQUFDMEUsZ0JBQUQsQ0FBbUIsRUFKeEMsQ0FBTjtBQU1EO0FBQ0Y7O0FBRUQsUUFBSU0sWUFBSixFQUFrQjtBQUNoQixVQUFJLENBQUNuRix1QkFBdUIsQ0FBQ21GLFlBQUQsRUFBZXBRLElBQWYsQ0FBNUIsRUFBa0Q7QUFDaEQsY0FBTSxJQUFJUCxLQUFLLENBQUNpSCxLQUFWLENBQ0pqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlvQyxjQURSLEVBRUgsdUJBQXNCcEUsU0FBVSxJQUFHMkMsU0FBVSxjQUFhK0QsWUFBWSxDQUNyRWdGLFlBRHFFLENBRXJFLFlBQVdoRixZQUFZLENBQUNwTCxJQUFELENBQU8sRUFKNUIsQ0FBTjtBQU1EOztBQUNELGFBQU82SSxTQUFQO0FBQ0Q7O0FBRUQsV0FBTyxLQUFLMkMsVUFBTCxDQUNKOEUsbUJBREksQ0FDZ0I1TCxTQURoQixFQUMyQjJDLFNBRDNCLEVBQ3NDckgsSUFEdEMsRUFFSjZNLEtBRkksQ0FFRUMsS0FBSyxJQUFJO0FBQ2QsVUFBSUEsS0FBSyxDQUFDYSxJQUFOLElBQWNsTyxLQUFLLENBQUNpSCxLQUFOLENBQVlvQyxjQUE5QixFQUE4QztBQUM1QztBQUNBLGNBQU1nRSxLQUFOO0FBQ0QsT0FKYSxDQUtkO0FBQ0E7QUFDQTs7O0FBQ0EsYUFBT0osT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRCxLQVhJLEVBWUpMLElBWkksQ0FZQyxNQUFNO0FBQ1YsYUFBTztBQUNMNUgsUUFBQUEsU0FESztBQUVMMkMsUUFBQUEsU0FGSztBQUdMckgsUUFBQUE7QUFISyxPQUFQO0FBS0QsS0FsQkksQ0FBUDtBQW1CRDs7QUFFRHVQLEVBQUFBLFlBQVksQ0FBQ3ZJLE1BQUQsRUFBYztBQUN4QixTQUFLLElBQUl1SixDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHdkosTUFBTSxDQUFDd0MsTUFBM0IsRUFBbUMrRyxDQUFDLElBQUksQ0FBeEMsRUFBMkM7QUFDekMsWUFBTTtBQUFFN0wsUUFBQUEsU0FBRjtBQUFhMkMsUUFBQUE7QUFBYixVQUEyQkwsTUFBTSxDQUFDdUosQ0FBRCxDQUF2QztBQUNBLFVBQUk7QUFBRXZRLFFBQUFBO0FBQUYsVUFBV2dILE1BQU0sQ0FBQ3VKLENBQUQsQ0FBckI7QUFDQSxZQUFNSCxZQUFZLEdBQUcsS0FBS0MsZUFBTCxDQUFxQjNMLFNBQXJCLEVBQWdDMkMsU0FBaEMsQ0FBckI7O0FBQ0EsVUFBSSxPQUFPckgsSUFBUCxLQUFnQixRQUFwQixFQUE4QjtBQUM1QkEsUUFBQUEsSUFBSSxHQUFHO0FBQUVBLFVBQUFBLElBQUksRUFBRUE7QUFBUixTQUFQO0FBQ0Q7O0FBQ0QsVUFBSSxDQUFDb1EsWUFBRCxJQUFpQixDQUFDbkYsdUJBQXVCLENBQUNtRixZQUFELEVBQWVwUSxJQUFmLENBQTdDLEVBQW1FO0FBQ2pFLGNBQU0sSUFBSVAsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZQyxZQURSLEVBRUgsdUJBQXNCVSxTQUFVLEVBRjdCLENBQU47QUFJRDtBQUNGO0FBQ0YsR0F6Z0JtQyxDQTJnQnBDOzs7QUFDQW1KLEVBQUFBLFdBQVcsQ0FDVG5KLFNBRFMsRUFFVDNDLFNBRlMsRUFHVHNKLFFBSFMsRUFJVDtBQUNBLFdBQU8sS0FBS2EsWUFBTCxDQUFrQixDQUFDeEgsU0FBRCxDQUFsQixFQUErQjNDLFNBQS9CLEVBQTBDc0osUUFBMUMsQ0FBUDtBQUNELEdBbGhCbUMsQ0FvaEJwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0FhLEVBQUFBLFlBQVksQ0FDVjRCLFVBRFUsRUFFVi9MLFNBRlUsRUFHVnNKLFFBSFUsRUFJVjtBQUNBLFFBQUksQ0FBQzVGLGdCQUFnQixDQUFDMUQsU0FBRCxDQUFyQixFQUFrQztBQUNoQyxZQUFNLElBQUlqRixLQUFLLENBQUNpSCxLQUFWLENBQ0pqSCxLQUFLLENBQUNpSCxLQUFOLENBQVlrQyxrQkFEUixFQUVKSix1QkFBdUIsQ0FBQzlELFNBQUQsQ0FGbkIsQ0FBTjtBQUlEOztBQUVEK0wsSUFBQUEsVUFBVSxDQUFDM0csT0FBWCxDQUFtQnpDLFNBQVMsSUFBSTtBQUM5QixVQUFJLENBQUNpQixnQkFBZ0IsQ0FBQ2pCLFNBQUQsQ0FBckIsRUFBa0M7QUFDaEMsY0FBTSxJQUFJNUgsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZaUosZ0JBRFIsRUFFSCx1QkFBc0J0SSxTQUFVLEVBRjdCLENBQU47QUFJRCxPQU42QixDQU85Qjs7O0FBQ0EsVUFBSSxDQUFDa0Isd0JBQXdCLENBQUNsQixTQUFELEVBQVkzQyxTQUFaLENBQTdCLEVBQXFEO0FBQ25ELGNBQU0sSUFBSWpGLEtBQUssQ0FBQ2lILEtBQVYsQ0FBZ0IsR0FBaEIsRUFBc0IsU0FBUVcsU0FBVSxvQkFBeEMsQ0FBTjtBQUNEO0FBQ0YsS0FYRDtBQWFBLFdBQU8sS0FBSzJGLFlBQUwsQ0FBa0J0SSxTQUFsQixFQUE2QixLQUE3QixFQUFvQztBQUFFeUgsTUFBQUEsVUFBVSxFQUFFO0FBQWQsS0FBcEMsRUFDSlUsS0FESSxDQUNFQyxLQUFLLElBQUk7QUFDZCxVQUFJQSxLQUFLLEtBQUtqRSxTQUFkLEVBQXlCO0FBQ3ZCLGNBQU0sSUFBSXBKLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWWtDLGtCQURSLEVBRUgsU0FBUWxFLFNBQVUsa0JBRmYsQ0FBTjtBQUlELE9BTEQsTUFLTztBQUNMLGNBQU1vSSxLQUFOO0FBQ0Q7QUFDRixLQVZJLEVBV0pSLElBWEksQ0FXQ3RELE1BQU0sSUFBSTtBQUNkeUgsTUFBQUEsVUFBVSxDQUFDM0csT0FBWCxDQUFtQnpDLFNBQVMsSUFBSTtBQUM5QixZQUFJLENBQUMyQixNQUFNLENBQUNoQyxNQUFQLENBQWNLLFNBQWQsQ0FBTCxFQUErQjtBQUM3QixnQkFBTSxJQUFJNUgsS0FBSyxDQUFDaUgsS0FBVixDQUNKLEdBREksRUFFSCxTQUFRVyxTQUFVLGlDQUZmLENBQU47QUFJRDtBQUNGLE9BUEQ7O0FBU0EsWUFBTXFKLFlBQVkscUJBQVExSCxNQUFNLENBQUNoQyxNQUFmLENBQWxCOztBQUNBLGFBQU9nSCxRQUFRLENBQUMyQyxPQUFULENBQ0o5QixZQURJLENBQ1NuSyxTQURULEVBQ29Cc0UsTUFEcEIsRUFDNEJ5SCxVQUQ1QixFQUVKbkUsSUFGSSxDQUVDLE1BQU07QUFDVixlQUFPSSxPQUFPLENBQUN1QyxHQUFSLENBQ0x3QixVQUFVLENBQUM3RCxHQUFYLENBQWV2RixTQUFTLElBQUk7QUFDMUIsZ0JBQU1NLEtBQUssR0FBRytJLFlBQVksQ0FBQ3JKLFNBQUQsQ0FBMUI7O0FBQ0EsY0FBSU0sS0FBSyxJQUFJQSxLQUFLLENBQUMzSCxJQUFOLEtBQWUsVUFBNUIsRUFBd0M7QUFDdEM7QUFDQSxtQkFBT2dPLFFBQVEsQ0FBQzJDLE9BQVQsQ0FBaUJDLFdBQWpCLENBQ0osU0FBUXZKLFNBQVUsSUFBRzNDLFNBQVUsRUFEM0IsQ0FBUDtBQUdEOztBQUNELGlCQUFPZ0ksT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRCxTQVRELENBREssQ0FBUDtBQVlELE9BZkksQ0FBUDtBQWdCRCxLQXRDSSxFQXVDSkwsSUF2Q0ksQ0F1Q0MsTUFBTSxLQUFLYixNQUFMLENBQVkwQixLQUFaLEVBdkNQLENBQVA7QUF3Q0QsR0E1bEJtQyxDQThsQnBDO0FBQ0E7QUFDQTs7O0FBQ0EsUUFBTTBELGNBQU4sQ0FBcUJuTSxTQUFyQixFQUF3Q29NLE1BQXhDLEVBQXFEaE8sS0FBckQsRUFBaUU7QUFDL0QsUUFBSWlPLFFBQVEsR0FBRyxDQUFmO0FBQ0EsVUFBTS9ILE1BQU0sR0FBRyxNQUFNLEtBQUt5RyxrQkFBTCxDQUF3Qi9LLFNBQXhCLENBQXJCO0FBQ0EsVUFBTXFLLFFBQVEsR0FBRyxFQUFqQjs7QUFFQSxTQUFLLE1BQU0xSCxTQUFYLElBQXdCeUosTUFBeEIsRUFBZ0M7QUFDOUIsVUFBSUEsTUFBTSxDQUFDekosU0FBRCxDQUFOLEtBQXNCd0IsU0FBMUIsRUFBcUM7QUFDbkM7QUFDRDs7QUFDRCxZQUFNbUksUUFBUSxHQUFHakIsT0FBTyxDQUFDZSxNQUFNLENBQUN6SixTQUFELENBQVAsQ0FBeEI7O0FBQ0EsVUFBSTJKLFFBQVEsS0FBSyxVQUFqQixFQUE2QjtBQUMzQkQsUUFBQUEsUUFBUTtBQUNUOztBQUNELFVBQUlBLFFBQVEsR0FBRyxDQUFmLEVBQWtCO0FBQ2hCO0FBQ0E7QUFDQSxlQUFPckUsT0FBTyxDQUFDYSxNQUFSLENBQ0wsSUFBSTlOLEtBQUssQ0FBQ2lILEtBQVYsQ0FDRWpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWW9DLGNBRGQsRUFFRSxpREFGRixDQURLLENBQVA7QUFNRDs7QUFDRCxVQUFJLENBQUNrSSxRQUFMLEVBQWU7QUFDYjtBQUNEOztBQUNELFVBQUkzSixTQUFTLEtBQUssS0FBbEIsRUFBeUI7QUFDdkI7QUFDQTtBQUNEOztBQUNEMEgsTUFBQUEsUUFBUSxDQUFDSixJQUFULENBQWMzRixNQUFNLENBQUNnRyxrQkFBUCxDQUEwQnRLLFNBQTFCLEVBQXFDMkMsU0FBckMsRUFBZ0QySixRQUFoRCxDQUFkO0FBQ0Q7O0FBQ0QsVUFBTTlCLE9BQU8sR0FBRyxNQUFNeEMsT0FBTyxDQUFDdUMsR0FBUixDQUFZRixRQUFaLENBQXRCO0FBQ0EsVUFBTUQsYUFBYSxHQUFHSSxPQUFPLENBQUNDLE1BQVIsQ0FBZUMsTUFBTSxJQUFJLENBQUMsQ0FBQ0EsTUFBM0IsQ0FBdEI7O0FBRUEsUUFBSU4sYUFBYSxDQUFDdEYsTUFBZCxLQUF5QixDQUE3QixFQUFnQztBQUM5QixZQUFNLEtBQUt5QyxVQUFMLENBQWdCO0FBQUVFLFFBQUFBLFVBQVUsRUFBRTtBQUFkLE9BQWhCLENBQU47QUFDRDs7QUFDRCxTQUFLb0QsWUFBTCxDQUFrQlQsYUFBbEI7QUFFQSxVQUFNNUIsT0FBTyxHQUFHUixPQUFPLENBQUNDLE9BQVIsQ0FBZ0IzRCxNQUFoQixDQUFoQjtBQUNBLFdBQU9pSSwyQkFBMkIsQ0FBQy9ELE9BQUQsRUFBVXhJLFNBQVYsRUFBcUJvTSxNQUFyQixFQUE2QmhPLEtBQTdCLENBQWxDO0FBQ0QsR0Ezb0JtQyxDQTZvQnBDOzs7QUFDQW9PLEVBQUFBLHVCQUF1QixDQUFDeE0sU0FBRCxFQUFvQm9NLE1BQXBCLEVBQWlDaE8sS0FBakMsRUFBNkM7QUFDbEUsVUFBTXFPLE9BQU8sR0FBRzNMLGVBQWUsQ0FBQ2QsU0FBRCxDQUEvQjs7QUFDQSxRQUFJLENBQUN5TSxPQUFELElBQVlBLE9BQU8sQ0FBQzNILE1BQVIsSUFBa0IsQ0FBbEMsRUFBcUM7QUFDbkMsYUFBT2tELE9BQU8sQ0FBQ0MsT0FBUixDQUFnQixJQUFoQixDQUFQO0FBQ0Q7O0FBRUQsVUFBTXlFLGNBQWMsR0FBR0QsT0FBTyxDQUFDaEMsTUFBUixDQUFlLFVBQVNrQyxNQUFULEVBQWlCO0FBQ3JELFVBQUl2TyxLQUFLLElBQUlBLEtBQUssQ0FBQy9DLFFBQW5CLEVBQTZCO0FBQzNCLFlBQUkrUSxNQUFNLENBQUNPLE1BQUQsQ0FBTixJQUFrQixPQUFPUCxNQUFNLENBQUNPLE1BQUQsQ0FBYixLQUEwQixRQUFoRCxFQUEwRDtBQUN4RDtBQUNBLGlCQUFPUCxNQUFNLENBQUNPLE1BQUQsQ0FBTixDQUFlbkQsSUFBZixJQUF1QixRQUE5QjtBQUNELFNBSjBCLENBSzNCOzs7QUFDQSxlQUFPLEtBQVA7QUFDRDs7QUFDRCxhQUFPLENBQUM0QyxNQUFNLENBQUNPLE1BQUQsQ0FBZDtBQUNELEtBVnNCLENBQXZCOztBQVlBLFFBQUlELGNBQWMsQ0FBQzVILE1BQWYsR0FBd0IsQ0FBNUIsRUFBK0I7QUFDN0IsWUFBTSxJQUFJL0osS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZb0MsY0FEUixFQUVKc0ksY0FBYyxDQUFDLENBQUQsQ0FBZCxHQUFvQixlQUZoQixDQUFOO0FBSUQ7O0FBQ0QsV0FBTzFFLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQixJQUFoQixDQUFQO0FBQ0Q7O0FBRUQyRSxFQUFBQSwyQkFBMkIsQ0FDekI1TSxTQUR5QixFQUV6QjZNLFFBRnlCLEVBR3pCcEssU0FIeUIsRUFJekI7QUFDQSxXQUFPa0UsZ0JBQWdCLENBQUNtRyxlQUFqQixDQUNMLEtBQUtDLHdCQUFMLENBQThCL00sU0FBOUIsQ0FESyxFQUVMNk0sUUFGSyxFQUdMcEssU0FISyxDQUFQO0FBS0QsR0FuckJtQyxDQXFyQnBDOzs7QUFDQSxTQUFPcUssZUFBUCxDQUNFRSxnQkFERixFQUVFSCxRQUZGLEVBR0VwSyxTQUhGLEVBSVc7QUFDVCxRQUFJLENBQUN1SyxnQkFBRCxJQUFxQixDQUFDQSxnQkFBZ0IsQ0FBQ3ZLLFNBQUQsQ0FBMUMsRUFBdUQ7QUFDckQsYUFBTyxJQUFQO0FBQ0Q7O0FBQ0QsVUFBTUosS0FBSyxHQUFHMkssZ0JBQWdCLENBQUN2SyxTQUFELENBQTlCOztBQUNBLFFBQUlKLEtBQUssQ0FBQyxHQUFELENBQVQsRUFBZ0I7QUFDZCxhQUFPLElBQVA7QUFDRCxLQVBRLENBUVQ7OztBQUNBLFFBQ0V3SyxRQUFRLENBQUNJLElBQVQsQ0FBY0MsR0FBRyxJQUFJO0FBQ25CLGFBQU83SyxLQUFLLENBQUM2SyxHQUFELENBQUwsS0FBZSxJQUF0QjtBQUNELEtBRkQsQ0FERixFQUlFO0FBQ0EsYUFBTyxJQUFQO0FBQ0Q7O0FBQ0QsV0FBTyxLQUFQO0FBQ0QsR0Ezc0JtQyxDQTZzQnBDOzs7QUFDQSxTQUFPQyxrQkFBUCxDQUNFSCxnQkFERixFQUVFaE4sU0FGRixFQUdFNk0sUUFIRixFQUlFcEssU0FKRixFQUtFMkssTUFMRixFQU1FO0FBQ0EsUUFDRXpHLGdCQUFnQixDQUFDbUcsZUFBakIsQ0FBaUNFLGdCQUFqQyxFQUFtREgsUUFBbkQsRUFBNkRwSyxTQUE3RCxDQURGLEVBRUU7QUFDQSxhQUFPdUYsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDs7QUFFRCxRQUFJLENBQUMrRSxnQkFBRCxJQUFxQixDQUFDQSxnQkFBZ0IsQ0FBQ3ZLLFNBQUQsQ0FBMUMsRUFBdUQ7QUFDckQsYUFBTyxJQUFQO0FBQ0Q7O0FBQ0QsVUFBTUosS0FBSyxHQUFHMkssZ0JBQWdCLENBQUN2SyxTQUFELENBQTlCLENBVkEsQ0FXQTtBQUNBOztBQUNBLFFBQUlKLEtBQUssQ0FBQyx3QkFBRCxDQUFULEVBQXFDO0FBQ25DO0FBQ0EsVUFBSSxDQUFDd0ssUUFBRCxJQUFhQSxRQUFRLENBQUMvSCxNQUFULElBQW1CLENBQXBDLEVBQXVDO0FBQ3JDLGNBQU0sSUFBSS9KLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWXFMLGdCQURSLEVBRUosb0RBRkksQ0FBTjtBQUlELE9BTEQsTUFLTyxJQUFJUixRQUFRLENBQUNySyxPQUFULENBQWlCLEdBQWpCLElBQXdCLENBQUMsQ0FBekIsSUFBOEJxSyxRQUFRLENBQUMvSCxNQUFULElBQW1CLENBQXJELEVBQXdEO0FBQzdELGNBQU0sSUFBSS9KLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWXFMLGdCQURSLEVBRUosb0RBRkksQ0FBTjtBQUlELE9BWmtDLENBYW5DO0FBQ0E7OztBQUNBLGFBQU9yRixPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNELEtBN0JELENBK0JBO0FBQ0E7OztBQUNBLFVBQU1xRixlQUFlLEdBQ25CLENBQUMsS0FBRCxFQUFRLE1BQVIsRUFBZ0IsT0FBaEIsRUFBeUI5SyxPQUF6QixDQUFpQ0MsU0FBakMsSUFBOEMsQ0FBQyxDQUEvQyxHQUNJLGdCQURKLEdBRUksaUJBSE4sQ0FqQ0EsQ0FzQ0E7O0FBQ0EsUUFBSTZLLGVBQWUsSUFBSSxpQkFBbkIsSUFBd0M3SyxTQUFTLElBQUksUUFBekQsRUFBbUU7QUFDakUsWUFBTSxJQUFJMUgsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZdUwsbUJBRFIsRUFFSCxnQ0FBK0I5SyxTQUFVLGFBQVl6QyxTQUFVLEdBRjVELENBQU47QUFJRCxLQTVDRCxDQThDQTs7O0FBQ0EsUUFDRStDLEtBQUssQ0FBQ0MsT0FBTixDQUFjZ0ssZ0JBQWdCLENBQUNNLGVBQUQsQ0FBOUIsS0FDQU4sZ0JBQWdCLENBQUNNLGVBQUQsQ0FBaEIsQ0FBa0N4SSxNQUFsQyxHQUEyQyxDQUY3QyxFQUdFO0FBQ0EsYUFBT2tELE9BQU8sQ0FBQ0MsT0FBUixFQUFQO0FBQ0Q7O0FBRUQsVUFBTTVFLGFBQWEsR0FBRzJKLGdCQUFnQixDQUFDdkssU0FBRCxDQUFoQixDQUE0QlksYUFBbEQ7O0FBQ0EsUUFBSU4sS0FBSyxDQUFDQyxPQUFOLENBQWNLLGFBQWQsS0FBZ0NBLGFBQWEsQ0FBQ3lCLE1BQWQsR0FBdUIsQ0FBM0QsRUFBOEQ7QUFDNUQ7QUFDQSxVQUFJckMsU0FBUyxLQUFLLFVBQWQsSUFBNEIySyxNQUFNLEtBQUssUUFBM0MsRUFBcUQ7QUFDbkQ7QUFDQSxlQUFPcEYsT0FBTyxDQUFDQyxPQUFSLEVBQVA7QUFDRDtBQUNGOztBQUVELFVBQU0sSUFBSWxOLEtBQUssQ0FBQ2lILEtBQVYsQ0FDSmpILEtBQUssQ0FBQ2lILEtBQU4sQ0FBWXVMLG1CQURSLEVBRUgsZ0NBQStCOUssU0FBVSxhQUFZekMsU0FBVSxHQUY1RCxDQUFOO0FBSUQsR0F2eEJtQyxDQXl4QnBDOzs7QUFDQW1OLEVBQUFBLGtCQUFrQixDQUNoQm5OLFNBRGdCLEVBRWhCNk0sUUFGZ0IsRUFHaEJwSyxTQUhnQixFQUloQjJLLE1BSmdCLEVBS2hCO0FBQ0EsV0FBT3pHLGdCQUFnQixDQUFDd0csa0JBQWpCLENBQ0wsS0FBS0osd0JBQUwsQ0FBOEIvTSxTQUE5QixDQURLLEVBRUxBLFNBRkssRUFHTDZNLFFBSEssRUFJTHBLLFNBSkssRUFLTDJLLE1BTEssQ0FBUDtBQU9EOztBQUVETCxFQUFBQSx3QkFBd0IsQ0FBQy9NLFNBQUQsRUFBeUI7QUFDL0MsV0FDRSxLQUFLZ0gsVUFBTCxDQUFnQmhILFNBQWhCLEtBQ0EsS0FBS2dILFVBQUwsQ0FBZ0JoSCxTQUFoQixFQUEyQnlGLHFCQUY3QjtBQUlELEdBOXlCbUMsQ0FnekJwQztBQUNBOzs7QUFDQWtHLEVBQUFBLGVBQWUsQ0FDYjNMLFNBRGEsRUFFYjJDLFNBRmEsRUFHWTtBQUN6QixRQUFJLEtBQUtxRSxVQUFMLENBQWdCaEgsU0FBaEIsQ0FBSixFQUFnQztBQUM5QixZQUFNMEwsWUFBWSxHQUFHLEtBQUsxRSxVQUFMLENBQWdCaEgsU0FBaEIsRUFBMkJzQyxNQUEzQixDQUFrQ0ssU0FBbEMsQ0FBckI7QUFDQSxhQUFPK0ksWUFBWSxLQUFLLEtBQWpCLEdBQXlCLFFBQXpCLEdBQW9DQSxZQUEzQztBQUNEOztBQUNELFdBQU92SCxTQUFQO0FBQ0QsR0EzekJtQyxDQTZ6QnBDOzs7QUFDQXFKLEVBQUFBLFFBQVEsQ0FBQ3hOLFNBQUQsRUFBb0I7QUFDMUIsUUFBSSxLQUFLZ0gsVUFBTCxDQUFnQmhILFNBQWhCLENBQUosRUFBZ0M7QUFDOUIsYUFBT2dJLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQixJQUFoQixDQUFQO0FBQ0Q7O0FBQ0QsV0FBTyxLQUFLVixVQUFMLEdBQWtCSyxJQUFsQixDQUF1QixNQUFNLENBQUMsQ0FBQyxLQUFLWixVQUFMLENBQWdCaEgsU0FBaEIsQ0FBL0IsQ0FBUDtBQUNEOztBQW4wQm1DLEMsQ0FzMEJ0Qzs7Ozs7QUFDQSxNQUFNeU4sSUFBSSxHQUFHLENBQ1hDLFNBRFcsRUFFWDdHLFdBRlcsRUFHWFcsT0FIVyxLQUltQjtBQUM5QixRQUFNbEQsTUFBTSxHQUFHLElBQUlxQyxnQkFBSixDQUFxQitHLFNBQXJCLEVBQWdDN0csV0FBaEMsQ0FBZjtBQUNBLFNBQU92QyxNQUFNLENBQUNpRCxVQUFQLENBQWtCQyxPQUFsQixFQUEyQkksSUFBM0IsQ0FBZ0MsTUFBTXRELE1BQXRDLENBQVA7QUFDRCxDQVBELEMsQ0FTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUNBLFNBQVNvRix1QkFBVCxDQUNFSCxjQURGLEVBRUVvRSxVQUZGLEVBR2dCO0FBQ2QsUUFBTWxFLFNBQVMsR0FBRyxFQUFsQixDQURjLENBRWQ7O0FBQ0EsUUFBTW1FLGNBQWMsR0FDbEIxUyxNQUFNLENBQUMySixJQUFQLENBQVk1SixjQUFaLEVBQTRCdUgsT0FBNUIsQ0FBb0MrRyxjQUFjLENBQUNzRSxHQUFuRCxNQUE0RCxDQUFDLENBQTdELEdBQ0ksRUFESixHQUVJM1MsTUFBTSxDQUFDMkosSUFBUCxDQUFZNUosY0FBYyxDQUFDc08sY0FBYyxDQUFDc0UsR0FBaEIsQ0FBMUIsQ0FITjs7QUFJQSxPQUFLLE1BQU1DLFFBQVgsSUFBdUJ2RSxjQUF2QixFQUF1QztBQUNyQyxRQUNFdUUsUUFBUSxLQUFLLEtBQWIsSUFDQUEsUUFBUSxLQUFLLEtBRGIsSUFFQUEsUUFBUSxLQUFLLFdBRmIsSUFHQUEsUUFBUSxLQUFLLFdBSGIsSUFJQUEsUUFBUSxLQUFLLFVBTGYsRUFNRTtBQUNBLFVBQ0VGLGNBQWMsQ0FBQzlJLE1BQWYsR0FBd0IsQ0FBeEIsSUFDQThJLGNBQWMsQ0FBQ3BMLE9BQWYsQ0FBdUJzTCxRQUF2QixNQUFxQyxDQUFDLENBRnhDLEVBR0U7QUFDQTtBQUNEOztBQUNELFlBQU1DLGNBQWMsR0FDbEJKLFVBQVUsQ0FBQ0csUUFBRCxDQUFWLElBQXdCSCxVQUFVLENBQUNHLFFBQUQsQ0FBVixDQUFxQnRFLElBQXJCLEtBQThCLFFBRHhEOztBQUVBLFVBQUksQ0FBQ3VFLGNBQUwsRUFBcUI7QUFDbkJ0RSxRQUFBQSxTQUFTLENBQUNxRSxRQUFELENBQVQsR0FBc0J2RSxjQUFjLENBQUN1RSxRQUFELENBQXBDO0FBQ0Q7QUFDRjtBQUNGOztBQUNELE9BQUssTUFBTUUsUUFBWCxJQUF1QkwsVUFBdkIsRUFBbUM7QUFDakMsUUFBSUssUUFBUSxLQUFLLFVBQWIsSUFBMkJMLFVBQVUsQ0FBQ0ssUUFBRCxDQUFWLENBQXFCeEUsSUFBckIsS0FBOEIsUUFBN0QsRUFBdUU7QUFDckUsVUFDRW9FLGNBQWMsQ0FBQzlJLE1BQWYsR0FBd0IsQ0FBeEIsSUFDQThJLGNBQWMsQ0FBQ3BMLE9BQWYsQ0FBdUJ3TCxRQUF2QixNQUFxQyxDQUFDLENBRnhDLEVBR0U7QUFDQTtBQUNEOztBQUNEdkUsTUFBQUEsU0FBUyxDQUFDdUUsUUFBRCxDQUFULEdBQXNCTCxVQUFVLENBQUNLLFFBQUQsQ0FBaEM7QUFDRDtBQUNGOztBQUNELFNBQU92RSxTQUFQO0FBQ0QsQyxDQUVEO0FBQ0E7OztBQUNBLFNBQVM4QywyQkFBVCxDQUFxQzBCLGFBQXJDLEVBQW9Eak8sU0FBcEQsRUFBK0RvTSxNQUEvRCxFQUF1RWhPLEtBQXZFLEVBQThFO0FBQzVFLFNBQU82UCxhQUFhLENBQUNyRyxJQUFkLENBQW1CdEQsTUFBTSxJQUFJO0FBQ2xDLFdBQU9BLE1BQU0sQ0FBQ2tJLHVCQUFQLENBQStCeE0sU0FBL0IsRUFBMENvTSxNQUExQyxFQUFrRGhPLEtBQWxELENBQVA7QUFDRCxHQUZNLENBQVA7QUFHRCxDLENBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBU2lOLE9BQVQsQ0FBaUI2QyxHQUFqQixFQUFvRDtBQUNsRCxRQUFNNVMsSUFBSSxHQUFHLE9BQU80UyxHQUFwQjs7QUFDQSxVQUFRNVMsSUFBUjtBQUNFLFNBQUssU0FBTDtBQUNFLGFBQU8sU0FBUDs7QUFDRixTQUFLLFFBQUw7QUFDRSxhQUFPLFFBQVA7O0FBQ0YsU0FBSyxRQUFMO0FBQ0UsYUFBTyxRQUFQOztBQUNGLFNBQUssS0FBTDtBQUNBLFNBQUssUUFBTDtBQUNFLFVBQUksQ0FBQzRTLEdBQUwsRUFBVTtBQUNSLGVBQU8vSixTQUFQO0FBQ0Q7O0FBQ0QsYUFBT2dLLGFBQWEsQ0FBQ0QsR0FBRCxDQUFwQjs7QUFDRixTQUFLLFVBQUw7QUFDQSxTQUFLLFFBQUw7QUFDQSxTQUFLLFdBQUw7QUFDQTtBQUNFLFlBQU0sY0FBY0EsR0FBcEI7QUFqQko7QUFtQkQsQyxDQUVEO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBU0MsYUFBVCxDQUF1QkQsR0FBdkIsRUFBcUQ7QUFDbkQsTUFBSUEsR0FBRyxZQUFZbkwsS0FBbkIsRUFBMEI7QUFDeEIsV0FBTyxPQUFQO0FBQ0Q7O0FBQ0QsTUFBSW1MLEdBQUcsQ0FBQ0UsTUFBUixFQUFnQjtBQUNkLFlBQVFGLEdBQUcsQ0FBQ0UsTUFBWjtBQUNFLFdBQUssU0FBTDtBQUNFLFlBQUlGLEdBQUcsQ0FBQ2xPLFNBQVIsRUFBbUI7QUFDakIsaUJBQU87QUFDTDFFLFlBQUFBLElBQUksRUFBRSxTQUREO0FBRUwyQixZQUFBQSxXQUFXLEVBQUVpUixHQUFHLENBQUNsTztBQUZaLFdBQVA7QUFJRDs7QUFDRDs7QUFDRixXQUFLLFVBQUw7QUFDRSxZQUFJa08sR0FBRyxDQUFDbE8sU0FBUixFQUFtQjtBQUNqQixpQkFBTztBQUNMMUUsWUFBQUEsSUFBSSxFQUFFLFVBREQ7QUFFTDJCLFlBQUFBLFdBQVcsRUFBRWlSLEdBQUcsQ0FBQ2xPO0FBRlosV0FBUDtBQUlEOztBQUNEOztBQUNGLFdBQUssTUFBTDtBQUNFLFlBQUlrTyxHQUFHLENBQUNuUixJQUFSLEVBQWM7QUFDWixpQkFBTyxNQUFQO0FBQ0Q7O0FBQ0Q7O0FBQ0YsV0FBSyxNQUFMO0FBQ0UsWUFBSW1SLEdBQUcsQ0FBQ0csR0FBUixFQUFhO0FBQ1gsaUJBQU8sTUFBUDtBQUNEOztBQUNEOztBQUNGLFdBQUssVUFBTDtBQUNFLFlBQUlILEdBQUcsQ0FBQ0ksUUFBSixJQUFnQixJQUFoQixJQUF3QkosR0FBRyxDQUFDSyxTQUFKLElBQWlCLElBQTdDLEVBQW1EO0FBQ2pELGlCQUFPLFVBQVA7QUFDRDs7QUFDRDs7QUFDRixXQUFLLE9BQUw7QUFDRSxZQUFJTCxHQUFHLENBQUNNLE1BQVIsRUFBZ0I7QUFDZCxpQkFBTyxPQUFQO0FBQ0Q7O0FBQ0Q7O0FBQ0YsV0FBSyxTQUFMO0FBQ0UsWUFBSU4sR0FBRyxDQUFDTyxXQUFSLEVBQXFCO0FBQ25CLGlCQUFPLFNBQVA7QUFDRDs7QUFDRDtBQXpDSjs7QUEyQ0EsVUFBTSxJQUFJMVQsS0FBSyxDQUFDaUgsS0FBVixDQUNKakgsS0FBSyxDQUFDaUgsS0FBTixDQUFZb0MsY0FEUixFQUVKLHlCQUF5QjhKLEdBQUcsQ0FBQ0UsTUFGekIsQ0FBTjtBQUlEOztBQUNELE1BQUlGLEdBQUcsQ0FBQyxLQUFELENBQVAsRUFBZ0I7QUFDZCxXQUFPQyxhQUFhLENBQUNELEdBQUcsQ0FBQyxLQUFELENBQUosQ0FBcEI7QUFDRDs7QUFDRCxNQUFJQSxHQUFHLENBQUMxRSxJQUFSLEVBQWM7QUFDWixZQUFRMEUsR0FBRyxDQUFDMUUsSUFBWjtBQUNFLFdBQUssV0FBTDtBQUNFLGVBQU8sUUFBUDs7QUFDRixXQUFLLFFBQUw7QUFDRSxlQUFPLElBQVA7O0FBQ0YsV0FBSyxLQUFMO0FBQ0EsV0FBSyxXQUFMO0FBQ0EsV0FBSyxRQUFMO0FBQ0UsZUFBTyxPQUFQOztBQUNGLFdBQUssYUFBTDtBQUNBLFdBQUssZ0JBQUw7QUFDRSxlQUFPO0FBQ0xsTyxVQUFBQSxJQUFJLEVBQUUsVUFERDtBQUVMMkIsVUFBQUEsV0FBVyxFQUFFaVIsR0FBRyxDQUFDUSxPQUFKLENBQVksQ0FBWixFQUFlMU87QUFGdkIsU0FBUDs7QUFJRixXQUFLLE9BQUw7QUFDRSxlQUFPbU8sYUFBYSxDQUFDRCxHQUFHLENBQUNTLEdBQUosQ0FBUSxDQUFSLENBQUQsQ0FBcEI7O0FBQ0Y7QUFDRSxjQUFNLG9CQUFvQlQsR0FBRyxDQUFDMUUsSUFBOUI7QUFsQko7QUFvQkQ7O0FBQ0QsU0FBTyxRQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuLy8gVGhpcyBjbGFzcyBoYW5kbGVzIHNjaGVtYSB2YWxpZGF0aW9uLCBwZXJzaXN0ZW5jZSwgYW5kIG1vZGlmaWNhdGlvbi5cbi8vXG4vLyBFYWNoIGluZGl2aWR1YWwgU2NoZW1hIG9iamVjdCBzaG91bGQgYmUgaW1tdXRhYmxlLiBUaGUgaGVscGVycyB0b1xuLy8gZG8gdGhpbmdzIHdpdGggdGhlIFNjaGVtYSBqdXN0IHJldHVybiBhIG5ldyBzY2hlbWEgd2hlbiB0aGUgc2NoZW1hXG4vLyBpcyBjaGFuZ2VkLlxuLy9cbi8vIFRoZSBjYW5vbmljYWwgcGxhY2UgdG8gc3RvcmUgdGhpcyBTY2hlbWEgaXMgaW4gdGhlIGRhdGFiYXNlIGl0c2VsZixcbi8vIGluIGEgX1NDSEVNQSBjb2xsZWN0aW9uLiBUaGlzIGlzIG5vdCB0aGUgcmlnaHQgd2F5IHRvIGRvIGl0IGZvciBhblxuLy8gb3BlbiBzb3VyY2UgZnJhbWV3b3JrLCBidXQgaXQncyBiYWNrd2FyZCBjb21wYXRpYmxlLCBzbyB3ZSdyZVxuLy8ga2VlcGluZyBpdCB0aGlzIHdheSBmb3Igbm93LlxuLy9cbi8vIEluIEFQSS1oYW5kbGluZyBjb2RlLCB5b3Ugc2hvdWxkIG9ubHkgdXNlIHRoZSBTY2hlbWEgY2xhc3MgdmlhIHRoZVxuLy8gRGF0YWJhc2VDb250cm9sbGVyLiBUaGlzIHdpbGwgbGV0IHVzIHJlcGxhY2UgdGhlIHNjaGVtYSBsb2dpYyBmb3Jcbi8vIGRpZmZlcmVudCBkYXRhYmFzZXMuXG4vLyBUT0RPOiBoaWRlIGFsbCBzY2hlbWEgbG9naWMgaW5zaWRlIHRoZSBkYXRhYmFzZSBhZGFwdGVyLlxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5jb25zdCBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmltcG9ydCB7IFN0b3JhZ2VBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvU3RvcmFnZS9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgRGF0YWJhc2VDb250cm9sbGVyIGZyb20gJy4vRGF0YWJhc2VDb250cm9sbGVyJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi4vQ29uZmlnJztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IGRlZXBjb3B5IGZyb20gJ2RlZXBjb3B5JztcbmltcG9ydCB0eXBlIHtcbiAgU2NoZW1hLFxuICBTY2hlbWFGaWVsZHMsXG4gIENsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgU2NoZW1hRmllbGQsXG4gIExvYWRTY2hlbWFPcHRpb25zLFxufSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgZGVmYXVsdENvbHVtbnM6IHsgW3N0cmluZ106IFNjaGVtYUZpZWxkcyB9ID0gT2JqZWN0LmZyZWV6ZSh7XG4gIC8vIENvbnRhaW4gdGhlIGRlZmF1bHQgY29sdW1ucyBmb3IgZXZlcnkgcGFyc2Ugb2JqZWN0IHR5cGUgKGV4Y2VwdCBfSm9pbiBjb2xsZWN0aW9uKVxuICBfRGVmYXVsdDoge1xuICAgIG9iamVjdElkOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgY3JlYXRlZEF0OiB7IHR5cGU6ICdEYXRlJyB9LFxuICAgIHVwZGF0ZWRBdDogeyB0eXBlOiAnRGF0ZScgfSxcbiAgICBBQ0w6IHsgdHlwZTogJ0FDTCcgfSxcbiAgfSxcbiAgLy8gVGhlIGFkZGl0aW9uYWwgZGVmYXVsdCBjb2x1bW5zIGZvciB0aGUgX1VzZXIgY29sbGVjdGlvbiAoaW4gYWRkaXRpb24gdG8gRGVmYXVsdENvbHMpXG4gIF9Vc2VyOiB7XG4gICAgdXNlcm5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBwYXNzd29yZDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGVtYWlsOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgZW1haWxWZXJpZmllZDogeyB0eXBlOiAnQm9vbGVhbicgfSxcbiAgICBhdXRoRGF0YTogeyB0eXBlOiAnT2JqZWN0JyB9LFxuICB9LFxuICAvLyBUaGUgYWRkaXRpb25hbCBkZWZhdWx0IGNvbHVtbnMgZm9yIHRoZSBfSW5zdGFsbGF0aW9uIGNvbGxlY3Rpb24gKGluIGFkZGl0aW9uIHRvIERlZmF1bHRDb2xzKVxuICBfSW5zdGFsbGF0aW9uOiB7XG4gICAgaW5zdGFsbGF0aW9uSWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBkZXZpY2VUb2tlbjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGNoYW5uZWxzOiB7IHR5cGU6ICdBcnJheScgfSxcbiAgICBkZXZpY2VUeXBlOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgcHVzaFR5cGU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBHQ01TZW5kZXJJZDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHRpbWVab25lOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgbG9jYWxlSWRlbnRpZmllcjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGJhZGdlOiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gICAgYXBwVmVyc2lvbjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGFwcE5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBhcHBJZGVudGlmaWVyOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgcGFyc2VWZXJzaW9uOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gIH0sXG4gIC8vIFRoZSBhZGRpdGlvbmFsIGRlZmF1bHQgY29sdW1ucyBmb3IgdGhlIF9Sb2xlIGNvbGxlY3Rpb24gKGluIGFkZGl0aW9uIHRvIERlZmF1bHRDb2xzKVxuICBfUm9sZToge1xuICAgIG5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICB1c2VyczogeyB0eXBlOiAnUmVsYXRpb24nLCB0YXJnZXRDbGFzczogJ19Vc2VyJyB9LFxuICAgIHJvbGVzOiB7IHR5cGU6ICdSZWxhdGlvbicsIHRhcmdldENsYXNzOiAnX1JvbGUnIH0sXG4gIH0sXG4gIC8vIFRoZSBhZGRpdGlvbmFsIGRlZmF1bHQgY29sdW1ucyBmb3IgdGhlIF9TZXNzaW9uIGNvbGxlY3Rpb24gKGluIGFkZGl0aW9uIHRvIERlZmF1bHRDb2xzKVxuICBfU2Vzc2lvbjoge1xuICAgIHJlc3RyaWN0ZWQ6IHsgdHlwZTogJ0Jvb2xlYW4nIH0sXG4gICAgdXNlcjogeyB0eXBlOiAnUG9pbnRlcicsIHRhcmdldENsYXNzOiAnX1VzZXInIH0sXG4gICAgaW5zdGFsbGF0aW9uSWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBzZXNzaW9uVG9rZW46IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBleHBpcmVzQXQ6IHsgdHlwZTogJ0RhdGUnIH0sXG4gICAgY3JlYXRlZFdpdGg6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgfSxcbiAgX1Byb2R1Y3Q6IHtcbiAgICBwcm9kdWN0SWRlbnRpZmllcjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGRvd25sb2FkOiB7IHR5cGU6ICdGaWxlJyB9LFxuICAgIGRvd25sb2FkTmFtZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGljb246IHsgdHlwZTogJ0ZpbGUnIH0sXG4gICAgb3JkZXI6IHsgdHlwZTogJ051bWJlcicgfSxcbiAgICB0aXRsZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHN1YnRpdGxlOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gIH0sXG4gIF9QdXNoU3RhdHVzOiB7XG4gICAgcHVzaFRpbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBzb3VyY2U6IHsgdHlwZTogJ1N0cmluZycgfSwgLy8gcmVzdCBvciB3ZWJ1aVxuICAgIHF1ZXJ5OiB7IHR5cGU6ICdTdHJpbmcnIH0sIC8vIHRoZSBzdHJpbmdpZmllZCBKU09OIHF1ZXJ5XG4gICAgcGF5bG9hZDogeyB0eXBlOiAnU3RyaW5nJyB9LCAvLyB0aGUgc3RyaW5naWZpZWQgSlNPTiBwYXlsb2FkLFxuICAgIHRpdGxlOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgZXhwaXJ5OiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gICAgZXhwaXJhdGlvbl9pbnRlcnZhbDogeyB0eXBlOiAnTnVtYmVyJyB9LFxuICAgIHN0YXR1czogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIG51bVNlbnQ6IHsgdHlwZTogJ051bWJlcicgfSxcbiAgICBudW1GYWlsZWQ6IHsgdHlwZTogJ051bWJlcicgfSxcbiAgICBwdXNoSGFzaDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGVycm9yTWVzc2FnZTogeyB0eXBlOiAnT2JqZWN0JyB9LFxuICAgIHNlbnRQZXJUeXBlOiB7IHR5cGU6ICdPYmplY3QnIH0sXG4gICAgZmFpbGVkUGVyVHlwZTogeyB0eXBlOiAnT2JqZWN0JyB9LFxuICAgIHNlbnRQZXJVVENPZmZzZXQ6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgICBmYWlsZWRQZXJVVENPZmZzZXQ6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgICBjb3VudDogeyB0eXBlOiAnTnVtYmVyJyB9LCAvLyB0cmFja3MgIyBvZiBiYXRjaGVzIHF1ZXVlZCBhbmQgcGVuZGluZ1xuICB9LFxuICBfSm9iU3RhdHVzOiB7XG4gICAgam9iTmFtZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHNvdXJjZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHN0YXR1czogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIG1lc3NhZ2U6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBwYXJhbXM6IHsgdHlwZTogJ09iamVjdCcgfSwgLy8gcGFyYW1zIHJlY2VpdmVkIHdoZW4gY2FsbGluZyB0aGUgam9iXG4gICAgZmluaXNoZWRBdDogeyB0eXBlOiAnRGF0ZScgfSxcbiAgfSxcbiAgX0pvYlNjaGVkdWxlOiB7XG4gICAgam9iTmFtZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGRlc2NyaXB0aW9uOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgcGFyYW1zOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgc3RhcnRBZnRlcjogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGRheXNPZldlZWs6IHsgdHlwZTogJ0FycmF5JyB9LFxuICAgIHRpbWVPZkRheTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGxhc3RSdW46IHsgdHlwZTogJ051bWJlcicgfSxcbiAgICByZXBlYXRNaW51dGVzOiB7IHR5cGU6ICdOdW1iZXInIH0sXG4gIH0sXG4gIF9Ib29rczoge1xuICAgIGZ1bmN0aW9uTmFtZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGNsYXNzTmFtZTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHRyaWdnZXJOYW1lOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gICAgdXJsOiB7IHR5cGU6ICdTdHJpbmcnIH0sXG4gIH0sXG4gIF9HbG9iYWxDb25maWc6IHtcbiAgICBvYmplY3RJZDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIHBhcmFtczogeyB0eXBlOiAnT2JqZWN0JyB9LFxuICAgIG1hc3RlcktleU9ubHk6IHsgdHlwZTogJ09iamVjdCcgfSxcbiAgfSxcbiAgX0dyYXBoUUxDb25maWc6IHtcbiAgICBvYmplY3RJZDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGNvbmZpZzogeyB0eXBlOiAnT2JqZWN0JyB9LFxuICB9LFxuICBfQXVkaWVuY2U6IHtcbiAgICBvYmplY3RJZDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIG5hbWU6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBxdWVyeTogeyB0eXBlOiAnU3RyaW5nJyB9LCAvL3N0b3JpbmcgcXVlcnkgYXMgSlNPTiBzdHJpbmcgdG8gcHJldmVudCBcIk5lc3RlZCBrZXlzIHNob3VsZCBub3QgY29udGFpbiB0aGUgJyQnIG9yICcuJyBjaGFyYWN0ZXJzXCIgZXJyb3JcbiAgICBsYXN0VXNlZDogeyB0eXBlOiAnRGF0ZScgfSxcbiAgICB0aW1lc1VzZWQ6IHsgdHlwZTogJ051bWJlcicgfSxcbiAgfSxcbiAgX0V4cG9ydFByb2dyZXNzOiB7XG4gICAgb2JqZWN0SWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgICBpZDogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIG1hc3RlcktleTogeyB0eXBlOiAnU3RyaW5nJyB9LFxuICAgIGFwcGxpY2F0aW9uSWQ6IHsgdHlwZTogJ1N0cmluZycgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCByZXF1aXJlZENvbHVtbnMgPSBPYmplY3QuZnJlZXplKHtcbiAgX1Byb2R1Y3Q6IFsncHJvZHVjdElkZW50aWZpZXInLCAnaWNvbicsICdvcmRlcicsICd0aXRsZScsICdzdWJ0aXRsZSddLFxuICBfUm9sZTogWyduYW1lJywgJ0FDTCddLFxufSk7XG5cbmNvbnN0IHN5c3RlbUNsYXNzZXMgPSBPYmplY3QuZnJlZXplKFtcbiAgJ19Vc2VyJyxcbiAgJ19JbnN0YWxsYXRpb24nLFxuICAnX1JvbGUnLFxuICAnX1Nlc3Npb24nLFxuICAnX1Byb2R1Y3QnLFxuICAnX1B1c2hTdGF0dXMnLFxuICAnX0pvYlN0YXR1cycsXG4gICdfSm9iU2NoZWR1bGUnLFxuICAnX0F1ZGllbmNlJyxcbiAgJ19FeHBvcnRQcm9ncmVzcycsXG5dKTtcblxuY29uc3Qgdm9sYXRpbGVDbGFzc2VzID0gT2JqZWN0LmZyZWV6ZShbXG4gICdfSm9iU3RhdHVzJyxcbiAgJ19QdXNoU3RhdHVzJyxcbiAgJ19Ib29rcycsXG4gICdfR2xvYmFsQ29uZmlnJyxcbiAgJ19HcmFwaFFMQ29uZmlnJyxcbiAgJ19Kb2JTY2hlZHVsZScsXG4gICdfQXVkaWVuY2UnLFxuICAnX0V4cG9ydFByb2dyZXNzJyxcbl0pO1xuXG4vLyBBbnl0aGluZyB0aGF0IHN0YXJ0IHdpdGggcm9sZVxuY29uc3Qgcm9sZVJlZ2V4ID0gL15yb2xlOi4qLztcbi8vIEFueXRoaW5nIHRoYXQgc3RhcnRzIHdpdGggdXNlckZpZWxkIChhbGxvd2VkIGZvciBwcm90ZWN0ZWQgZmllbGRzIG9ubHkpXG5jb25zdCBwcm90ZWN0ZWRGaWVsZHNQb2ludGVyUmVnZXggPSAvXnVzZXJGaWVsZDouKi87XG4vLyAqIHBlcm1pc3Npb25cbmNvbnN0IHB1YmxpY1JlZ2V4ID0gL15cXCokLztcblxuY29uc3QgYXV0aGVudGljYXRlZFJlZ2V4ID0gL15hdXRoZW50aWNhdGVkJC87XG5cbmNvbnN0IHJlcXVpcmVzQXV0aGVudGljYXRpb25SZWdleCA9IC9ecmVxdWlyZXNBdXRoZW50aWNhdGlvbiQvO1xuXG5jb25zdCBjbHBQb2ludGVyUmVnZXggPSAvXnBvaW50ZXJGaWVsZHMkLztcblxuLy8gcmVnZXggZm9yIHZhbGlkYXRpbmcgZW50aXRpZXMgaW4gcHJvdGVjdGVkRmllbGRzIG9iamVjdFxuY29uc3QgcHJvdGVjdGVkRmllbGRzUmVnZXggPSBPYmplY3QuZnJlZXplKFtcbiAgcHJvdGVjdGVkRmllbGRzUG9pbnRlclJlZ2V4LFxuICBwdWJsaWNSZWdleCxcbiAgYXV0aGVudGljYXRlZFJlZ2V4LFxuICByb2xlUmVnZXgsXG5dKTtcblxuLy8gY2xwIHJlZ2V4XG5jb25zdCBjbHBGaWVsZHNSZWdleCA9IE9iamVjdC5mcmVlemUoW1xuICBjbHBQb2ludGVyUmVnZXgsXG4gIHB1YmxpY1JlZ2V4LFxuICByZXF1aXJlc0F1dGhlbnRpY2F0aW9uUmVnZXgsXG4gIHJvbGVSZWdleCxcbl0pO1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVBlcm1pc3Npb25LZXkoa2V5LCB1c2VySWRSZWdFeHApIHtcbiAgbGV0IG1hdGNoZXNTb21lID0gZmFsc2U7XG4gIGZvciAoY29uc3QgcmVnRXggb2YgY2xwRmllbGRzUmVnZXgpIHtcbiAgICBpZiAoa2V5Lm1hdGNoKHJlZ0V4KSAhPT0gbnVsbCkge1xuICAgICAgbWF0Y2hlc1NvbWUgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLy8gdXNlcklkIGRlcGVuZHMgb24gc3RhcnR1cCBvcHRpb25zIHNvIGl0J3MgZHluYW1pY1xuICBjb25zdCB2YWxpZCA9IG1hdGNoZXNTb21lIHx8IGtleS5tYXRjaCh1c2VySWRSZWdFeHApICE9PSBudWxsO1xuICBpZiAoIXZhbGlkKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgYCcke2tleX0nIGlzIG5vdCBhIHZhbGlkIGtleSBmb3IgY2xhc3MgbGV2ZWwgcGVybWlzc2lvbnNgXG4gICAgKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZVByb3RlY3RlZEZpZWxkc0tleShrZXksIHVzZXJJZFJlZ0V4cCkge1xuICBsZXQgbWF0Y2hlc1NvbWUgPSBmYWxzZTtcbiAgZm9yIChjb25zdCByZWdFeCBvZiBwcm90ZWN0ZWRGaWVsZHNSZWdleCkge1xuICAgIGlmIChrZXkubWF0Y2gocmVnRXgpICE9PSBudWxsKSB7XG4gICAgICBtYXRjaGVzU29tZSA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvLyB1c2VySWQgcmVnZXggZGVwZW5kcyBvbiBsYXVuY2ggb3B0aW9ucyBzbyBpdCdzIGR5bmFtaWNcbiAgY29uc3QgdmFsaWQgPSBtYXRjaGVzU29tZSB8fCBrZXkubWF0Y2godXNlcklkUmVnRXhwKSAhPT0gbnVsbDtcbiAgaWYgKCF2YWxpZCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgIGAnJHtrZXl9JyBpcyBub3QgYSB2YWxpZCBrZXkgZm9yIGNsYXNzIGxldmVsIHBlcm1pc3Npb25zYFxuICAgICk7XG4gIH1cbn1cblxuY29uc3QgQ0xQVmFsaWRLZXlzID0gT2JqZWN0LmZyZWV6ZShbXG4gICdmaW5kJyxcbiAgJ2NvdW50JyxcbiAgJ2dldCcsXG4gICdjcmVhdGUnLFxuICAndXBkYXRlJyxcbiAgJ2RlbGV0ZScsXG4gICdhZGRGaWVsZCcsXG4gICdyZWFkVXNlckZpZWxkcycsXG4gICd3cml0ZVVzZXJGaWVsZHMnLFxuICAncHJvdGVjdGVkRmllbGRzJyxcbl0pO1xuXG4vLyB2YWxpZGF0aW9uIGJlZm9yZSBzZXR0aW5nIGNsYXNzLWxldmVsIHBlcm1pc3Npb25zIG9uIGNvbGxlY3Rpb25cbmZ1bmN0aW9uIHZhbGlkYXRlQ0xQKFxuICBwZXJtczogQ2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICBmaWVsZHM6IFNjaGVtYUZpZWxkcyxcbiAgdXNlcklkUmVnRXhwOiBSZWdFeHBcbikge1xuICBpZiAoIXBlcm1zKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGZvciAoY29uc3Qgb3BlcmF0aW9uS2V5IGluIHBlcm1zKSB7XG4gICAgaWYgKENMUFZhbGlkS2V5cy5pbmRleE9mKG9wZXJhdGlvbktleSkgPT0gLTEpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICBgJHtvcGVyYXRpb25LZXl9IGlzIG5vdCBhIHZhbGlkIG9wZXJhdGlvbiBmb3IgY2xhc3MgbGV2ZWwgcGVybWlzc2lvbnNgXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IG9wZXJhdGlvbiA9IHBlcm1zW29wZXJhdGlvbktleV07XG4gICAgLy8gcHJvY2VlZCB3aXRoIG5leHQgb3BlcmF0aW9uS2V5XG5cbiAgICAvLyB0aHJvd3Mgd2hlbiByb290IGZpZWxkcyBhcmUgb2Ygd3JvbmcgdHlwZVxuICAgIHZhbGlkYXRlQ0xQanNvbihvcGVyYXRpb24sIG9wZXJhdGlvbktleSk7XG5cbiAgICBpZiAoXG4gICAgICBvcGVyYXRpb25LZXkgPT09ICdyZWFkVXNlckZpZWxkcycgfHxcbiAgICAgIG9wZXJhdGlvbktleSA9PT0gJ3dyaXRlVXNlckZpZWxkcydcbiAgICApIHtcbiAgICAgIC8vIHZhbGlkYXRlIGdyb3VwZWQgcG9pbnRlciBwZXJtaXNzaW9uc1xuICAgICAgLy8gbXVzdCBiZSBhbiBhcnJheSB3aXRoIGZpZWxkIG5hbWVzXG4gICAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBvZiBvcGVyYXRpb24pIHtcbiAgICAgICAgdmFsaWRhdGVQb2ludGVyUGVybWlzc2lvbihmaWVsZE5hbWUsIGZpZWxkcywgb3BlcmF0aW9uS2V5KTtcbiAgICAgIH1cbiAgICAgIC8vIHJlYWRVc2VyRmllbGRzIGFuZCB3cml0ZXJVc2VyRmllbGRzIGRvIG5vdCBoYXZlIG5lc2R0ZWQgZmllbGRzXG4gICAgICAvLyBwcm9jZWVkIHdpdGggbmV4dCBvcGVyYXRpb25LZXlcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIHZhbGlkYXRlIHByb3RlY3RlZCBmaWVsZHNcbiAgICBpZiAob3BlcmF0aW9uS2V5ID09PSAncHJvdGVjdGVkRmllbGRzJykge1xuICAgICAgZm9yIChjb25zdCBlbnRpdHkgaW4gb3BlcmF0aW9uKSB7XG4gICAgICAgIC8vIHRocm93cyBvbiB1bmV4cGVjdGVkIGtleVxuICAgICAgICB2YWxpZGF0ZVByb3RlY3RlZEZpZWxkc0tleShlbnRpdHksIHVzZXJJZFJlZ0V4cCk7XG5cbiAgICAgICAgY29uc3QgcHJvdGVjdGVkRmllbGRzID0gb3BlcmF0aW9uW2VudGl0eV07XG5cbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHByb3RlY3RlZEZpZWxkcykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICBgJyR7cHJvdGVjdGVkRmllbGRzfScgaXMgbm90IGEgdmFsaWQgdmFsdWUgZm9yIHByb3RlY3RlZEZpZWxkc1ske2VudGl0eX1dIC0gZXhwZWN0ZWQgYW4gYXJyYXkuYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB0aGUgZmllbGQgaXMgaW4gZm9ybSBvZiBhcnJheVxuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHByb3RlY3RlZEZpZWxkcykge1xuICAgICAgICAgIC8vIGRvIG5vdCBhbGxvb3cgdG8gcHJvdGVjdCBkZWZhdWx0IGZpZWxkc1xuICAgICAgICAgIGlmIChkZWZhdWx0Q29sdW1ucy5fRGVmYXVsdFtmaWVsZF0pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICBgRGVmYXVsdCBmaWVsZCAnJHtmaWVsZH0nIGNhbiBub3QgYmUgcHJvdGVjdGVkYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gZmllbGQgc2hvdWxkIGV4aXN0IG9uIGNvbGxlY3Rpb25cbiAgICAgICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChmaWVsZHMsIGZpZWxkKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgIGBGaWVsZCAnJHtmaWVsZH0nIGluIHByb3RlY3RlZEZpZWxkczoke2VudGl0eX0gZG9lcyBub3QgZXhpc3RgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gcHJvY2VlZCB3aXRoIG5leHQgb3BlcmF0aW9uS2V5XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyB2YWxpZGF0ZSBvdGhlciBmaWVsZHNcbiAgICAvLyBFbnRpdHkgY2FuIGJlOlxuICAgIC8vIFwiKlwiIC0gUHVibGljLFxuICAgIC8vIFwicmVxdWlyZXNBdXRoZW50aWNhdGlvblwiIC0gYXV0aGVudGljYXRlZCB1c2VycyxcbiAgICAvLyBcIm9iamVjdElkXCIgLSBfVXNlciBpZCxcbiAgICAvLyBcInJvbGU6cm9sZW5hbWVcIixcbiAgICAvLyBcInBvaW50ZXJGaWVsZHNcIiAtIGFycmF5IG9mIGZpZWxkIG5hbWVzIGNvbnRhaW5pbmcgcG9pbnRlcnMgdG8gdXNlcnNcbiAgICBmb3IgKGNvbnN0IGVudGl0eSBpbiBvcGVyYXRpb24pIHtcbiAgICAgIC8vIHRocm93cyBvbiB1bmV4cGVjdGVkIGtleVxuICAgICAgdmFsaWRhdGVQZXJtaXNzaW9uS2V5KGVudGl0eSwgdXNlcklkUmVnRXhwKTtcblxuICAgICAgLy8gZW50aXR5IGNhbiBiZSBlaXRoZXI6XG4gICAgICAvLyBcInBvaW50ZXJGaWVsZHNcIjogc3RyaW5nW11cbiAgICAgIGlmIChlbnRpdHkgPT09ICdwb2ludGVyRmllbGRzJykge1xuICAgICAgICBjb25zdCBwb2ludGVyRmllbGRzID0gb3BlcmF0aW9uW2VudGl0eV07XG5cbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocG9pbnRlckZpZWxkcykpIHtcbiAgICAgICAgICBmb3IgKGNvbnN0IHBvaW50ZXJGaWVsZCBvZiBwb2ludGVyRmllbGRzKSB7XG4gICAgICAgICAgICB2YWxpZGF0ZVBvaW50ZXJQZXJtaXNzaW9uKHBvaW50ZXJGaWVsZCwgZmllbGRzLCBvcGVyYXRpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICBgJyR7cG9pbnRlckZpZWxkc30nIGlzIG5vdCBhIHZhbGlkIHZhbHVlIGZvciAke29wZXJhdGlvbktleX1bJHtlbnRpdHl9XSAtIGV4cGVjdGVkIGFuIGFycmF5LmBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb2NlZWQgd2l0aCBuZXh0IGVudGl0eSBrZXlcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIG9yIFtlbnRpdHldOiBib29sZWFuXG4gICAgICBjb25zdCBwZXJtaXQgPSBvcGVyYXRpb25bZW50aXR5XTtcblxuICAgICAgaWYgKHBlcm1pdCAhPT0gdHJ1ZSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGAnJHtwZXJtaXR9JyBpcyBub3QgYSB2YWxpZCB2YWx1ZSBmb3IgY2xhc3MgbGV2ZWwgcGVybWlzc2lvbnMgJHtvcGVyYXRpb25LZXl9OiR7ZW50aXR5fToke3Blcm1pdH1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQ0xQanNvbihvcGVyYXRpb246IGFueSwgb3BlcmF0aW9uS2V5OiBzdHJpbmcpIHtcbiAgaWYgKG9wZXJhdGlvbktleSA9PT0gJ3JlYWRVc2VyRmllbGRzJyB8fCBvcGVyYXRpb25LZXkgPT09ICd3cml0ZVVzZXJGaWVsZHMnKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KG9wZXJhdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICBgJyR7b3BlcmF0aW9ufScgaXMgbm90IGEgdmFsaWQgdmFsdWUgZm9yIGNsYXNzIGxldmVsIHBlcm1pc3Npb25zICR7b3BlcmF0aW9uS2V5fSAtIG11c3QgYmUgYW4gYXJyYXlgXG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAodHlwZW9mIG9wZXJhdGlvbiA9PT0gJ29iamVjdCcgJiYgb3BlcmF0aW9uICE9PSBudWxsKSB7XG4gICAgICAvLyBvayB0byBwcm9jZWVkXG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICBgJyR7b3BlcmF0aW9ufScgaXMgbm90IGEgdmFsaWQgdmFsdWUgZm9yIGNsYXNzIGxldmVsIHBlcm1pc3Npb25zICR7b3BlcmF0aW9uS2V5fSAtIG11c3QgYmUgYW4gb2JqZWN0YFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVQb2ludGVyUGVybWlzc2lvbihcbiAgZmllbGROYW1lOiBzdHJpbmcsXG4gIGZpZWxkczogT2JqZWN0LFxuICBvcGVyYXRpb246IHN0cmluZ1xuKSB7XG4gIC8vIFVzZXMgY29sbGVjdGlvbiBzY2hlbWEgdG8gZW5zdXJlIHRoZSBmaWVsZCBpcyBvZiB0eXBlOlxuICAvLyAtIFBvaW50ZXI8X1VzZXI+IChwb2ludGVycylcbiAgLy8gLSBBcnJheVxuICAvL1xuICAvLyAgICBJdCdzIG5vdCBwb3NzaWJsZSB0byBlbmZvcmNlIHR5cGUgb24gQXJyYXkncyBpdGVtcyBpbiBzY2hlbWFcbiAgLy8gIHNvIHdlIGFjY2VwdCBhbnkgQXJyYXkgZmllbGQsIGFuZCBsYXRlciB3aGVuIGFwcGx5aW5nIHBlcm1pc3Npb25zXG4gIC8vICBvbmx5IGl0ZW1zIHRoYXQgYXJlIHBvaW50ZXJzIHRvIF9Vc2VyIGFyZSBjb25zaWRlcmVkLlxuICBpZiAoXG4gICAgIShcbiAgICAgIGZpZWxkc1tmaWVsZE5hbWVdICYmXG4gICAgICAoKGZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT0gJ1BvaW50ZXInICYmXG4gICAgICAgIGZpZWxkc1tmaWVsZE5hbWVdLnRhcmdldENsYXNzID09ICdfVXNlcicpIHx8XG4gICAgICAgIGZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT0gJ0FycmF5JylcbiAgICApXG4gICkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgIGAnJHtmaWVsZE5hbWV9JyBpcyBub3QgYSB2YWxpZCBjb2x1bW4gZm9yIGNsYXNzIGxldmVsIHBvaW50ZXIgcGVybWlzc2lvbnMgJHtvcGVyYXRpb259YFxuICAgICk7XG4gIH1cbn1cblxuY29uc3Qgam9pbkNsYXNzUmVnZXggPSAvXl9Kb2luOltBLVphLXowLTlfXSs6W0EtWmEtejAtOV9dKy87XG5jb25zdCBjbGFzc0FuZEZpZWxkUmVnZXggPSAvXltBLVphLXpdW0EtWmEtejAtOV9dKiQvO1xuZnVuY3Rpb24gY2xhc3NOYW1lSXNWYWxpZChjbGFzc05hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAvLyBWYWxpZCBjbGFzc2VzIG11c3Q6XG4gIHJldHVybiAoXG4gICAgLy8gQmUgb25lIG9mIF9Vc2VyLCBfSW5zdGFsbGF0aW9uLCBfUm9sZSwgX1Nlc3Npb24gT1JcbiAgICBzeXN0ZW1DbGFzc2VzLmluZGV4T2YoY2xhc3NOYW1lKSA+IC0xIHx8XG4gICAgLy8gQmUgYSBqb2luIHRhYmxlIE9SXG4gICAgam9pbkNsYXNzUmVnZXgudGVzdChjbGFzc05hbWUpIHx8XG4gICAgLy8gSW5jbHVkZSBvbmx5IGFscGhhLW51bWVyaWMgYW5kIHVuZGVyc2NvcmVzLCBhbmQgbm90IHN0YXJ0IHdpdGggYW4gdW5kZXJzY29yZSBvciBudW1iZXJcbiAgICBmaWVsZE5hbWVJc1ZhbGlkKGNsYXNzTmFtZSlcbiAgKTtcbn1cblxuLy8gVmFsaWQgZmllbGRzIG11c3QgYmUgYWxwaGEtbnVtZXJpYywgYW5kIG5vdCBzdGFydCB3aXRoIGFuIHVuZGVyc2NvcmUgb3IgbnVtYmVyXG5mdW5jdGlvbiBmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBjbGFzc0FuZEZpZWxkUmVnZXgudGVzdChmaWVsZE5hbWUpO1xufVxuXG4vLyBDaGVja3MgdGhhdCBpdCdzIG5vdCB0cnlpbmcgdG8gY2xvYmJlciBvbmUgb2YgdGhlIGRlZmF1bHQgZmllbGRzIG9mIHRoZSBjbGFzcy5cbmZ1bmN0aW9uIGZpZWxkTmFtZUlzVmFsaWRGb3JDbGFzcyhcbiAgZmllbGROYW1lOiBzdHJpbmcsXG4gIGNsYXNzTmFtZTogc3RyaW5nXG4pOiBib29sZWFuIHtcbiAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0W2ZpZWxkTmFtZV0pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0gJiYgZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXVtmaWVsZE5hbWVdKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZShjbGFzc05hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiAoXG4gICAgJ0ludmFsaWQgY2xhc3NuYW1lOiAnICtcbiAgICBjbGFzc05hbWUgK1xuICAgICcsIGNsYXNzbmFtZXMgY2FuIG9ubHkgaGF2ZSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycyBhbmQgXywgYW5kIG11c3Qgc3RhcnQgd2l0aCBhbiBhbHBoYSBjaGFyYWN0ZXIgJ1xuICApO1xufVxuXG5jb25zdCBpbnZhbGlkSnNvbkVycm9yID0gbmV3IFBhcnNlLkVycm9yKFxuICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICdpbnZhbGlkIEpTT04nXG4pO1xuY29uc3QgdmFsaWROb25SZWxhdGlvbk9yUG9pbnRlclR5cGVzID0gW1xuICAnTnVtYmVyJyxcbiAgJ1N0cmluZycsXG4gICdCb29sZWFuJyxcbiAgJ0RhdGUnLFxuICAnT2JqZWN0JyxcbiAgJ0FycmF5JyxcbiAgJ0dlb1BvaW50JyxcbiAgJ0ZpbGUnLFxuICAnQnl0ZXMnLFxuICAnUG9seWdvbicsXG5dO1xuLy8gUmV0dXJucyBhbiBlcnJvciBzdWl0YWJsZSBmb3IgdGhyb3dpbmcgaWYgdGhlIHR5cGUgaXMgaW52YWxpZFxuY29uc3QgZmllbGRUeXBlSXNJbnZhbGlkID0gKHsgdHlwZSwgdGFyZ2V0Q2xhc3MgfSkgPT4ge1xuICBpZiAoWydQb2ludGVyJywgJ1JlbGF0aW9uJ10uaW5kZXhPZih0eXBlKSA+PSAwKSB7XG4gICAgaWYgKCF0YXJnZXRDbGFzcykge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcigxMzUsIGB0eXBlICR7dHlwZX0gbmVlZHMgYSBjbGFzcyBuYW1lYCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdGFyZ2V0Q2xhc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gaW52YWxpZEpzb25FcnJvcjtcbiAgICB9IGVsc2UgaWYgKCFjbGFzc05hbWVJc1ZhbGlkKHRhcmdldENsYXNzKSkge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZSh0YXJnZXRDbGFzcylcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG4gIGlmICh0eXBlb2YgdHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gaW52YWxpZEpzb25FcnJvcjtcbiAgfVxuICBpZiAodmFsaWROb25SZWxhdGlvbk9yUG9pbnRlclR5cGVzLmluZGV4T2YodHlwZSkgPCAwKSB7XG4gICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgYGludmFsaWQgZmllbGQgdHlwZTogJHt0eXBlfWBcbiAgICApO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59O1xuXG5jb25zdCBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hID0gKHNjaGVtYTogYW55KSA9PiB7XG4gIHNjaGVtYSA9IGluamVjdERlZmF1bHRTY2hlbWEoc2NoZW1hKTtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuQUNMO1xuICBzY2hlbWEuZmllbGRzLl9ycGVybSA9IHsgdHlwZTogJ0FycmF5JyB9O1xuICBzY2hlbWEuZmllbGRzLl93cGVybSA9IHsgdHlwZTogJ0FycmF5JyB9O1xuXG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMucGFzc3dvcmQ7XG4gICAgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkID0geyB0eXBlOiAnU3RyaW5nJyB9O1xuICB9XG5cbiAgcmV0dXJuIHNjaGVtYTtcbn07XG5cbmNvbnN0IGNvbnZlcnRBZGFwdGVyU2NoZW1hVG9QYXJzZVNjaGVtYSA9ICh7IC4uLnNjaGVtYSB9KSA9PiB7XG4gIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9ycGVybTtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3dwZXJtO1xuXG4gIHNjaGVtYS5maWVsZHMuQUNMID0geyB0eXBlOiAnQUNMJyB9O1xuXG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuYXV0aERhdGE7IC8vQXV0aCBkYXRhIGlzIGltcGxpY2l0XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX2hhc2hlZF9wYXNzd29yZDtcbiAgICBzY2hlbWEuZmllbGRzLnBhc3N3b3JkID0geyB0eXBlOiAnU3RyaW5nJyB9O1xuICB9XG5cbiAgaWYgKHNjaGVtYS5pbmRleGVzICYmIE9iamVjdC5rZXlzKHNjaGVtYS5pbmRleGVzKS5sZW5ndGggPT09IDApIHtcbiAgICBkZWxldGUgc2NoZW1hLmluZGV4ZXM7XG4gIH1cblxuICByZXR1cm4gc2NoZW1hO1xufTtcblxuY2xhc3MgU2NoZW1hRGF0YSB7XG4gIF9fZGF0YTogYW55O1xuICBfX3Byb3RlY3RlZEZpZWxkczogYW55O1xuICBjb25zdHJ1Y3RvcihhbGxTY2hlbWFzID0gW10sIHByb3RlY3RlZEZpZWxkcyA9IHt9KSB7XG4gICAgdGhpcy5fX2RhdGEgPSB7fTtcbiAgICB0aGlzLl9fcHJvdGVjdGVkRmllbGRzID0gcHJvdGVjdGVkRmllbGRzO1xuICAgIGFsbFNjaGVtYXMuZm9yRWFjaChzY2hlbWEgPT4ge1xuICAgICAgaWYgKHZvbGF0aWxlQ2xhc3Nlcy5pbmNsdWRlcyhzY2hlbWEuY2xhc3NOYW1lKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgc2NoZW1hLmNsYXNzTmFtZSwge1xuICAgICAgICBnZXQ6ICgpID0+IHtcbiAgICAgICAgICBpZiAoIXRoaXMuX19kYXRhW3NjaGVtYS5jbGFzc05hbWVdKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0ge307XG4gICAgICAgICAgICBkYXRhLmZpZWxkcyA9IGluamVjdERlZmF1bHRTY2hlbWEoc2NoZW1hKS5maWVsZHM7XG4gICAgICAgICAgICBkYXRhLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucyA9IGRlZXBjb3B5KHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMpO1xuICAgICAgICAgICAgZGF0YS5pbmRleGVzID0gc2NoZW1hLmluZGV4ZXM7XG5cbiAgICAgICAgICAgIGNvbnN0IGNsYXNzUHJvdGVjdGVkRmllbGRzID0gdGhpcy5fX3Byb3RlY3RlZEZpZWxkc1tcbiAgICAgICAgICAgICAgc2NoZW1hLmNsYXNzTmFtZVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGlmIChjbGFzc1Byb3RlY3RlZEZpZWxkcykge1xuICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBjbGFzc1Byb3RlY3RlZEZpZWxkcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHVucSA9IG5ldyBTZXQoW1xuICAgICAgICAgICAgICAgICAgLi4uKGRhdGEuY2xhc3NMZXZlbFBlcm1pc3Npb25zLnByb3RlY3RlZEZpZWxkc1trZXldIHx8IFtdKSxcbiAgICAgICAgICAgICAgICAgIC4uLmNsYXNzUHJvdGVjdGVkRmllbGRzW2tleV0sXG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgZGF0YS5jbGFzc0xldmVsUGVybWlzc2lvbnMucHJvdGVjdGVkRmllbGRzW2tleV0gPSBBcnJheS5mcm9tKFxuICAgICAgICAgICAgICAgICAgdW5xXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9fZGF0YVtzY2hlbWEuY2xhc3NOYW1lXSA9IGRhdGE7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0aGlzLl9fZGF0YVtzY2hlbWEuY2xhc3NOYW1lXTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gSW5qZWN0IHRoZSBpbi1tZW1vcnkgY2xhc3Nlc1xuICAgIHZvbGF0aWxlQ2xhc3Nlcy5mb3JFYWNoKGNsYXNzTmFtZSA9PiB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgY2xhc3NOYW1lLCB7XG4gICAgICAgIGdldDogKCkgPT4ge1xuICAgICAgICAgIGlmICghdGhpcy5fX2RhdGFbY2xhc3NOYW1lXSkge1xuICAgICAgICAgICAgY29uc3Qgc2NoZW1hID0gaW5qZWN0RGVmYXVsdFNjaGVtYSh7XG4gICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgZmllbGRzOiB7fSxcbiAgICAgICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiB7fSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IHt9O1xuICAgICAgICAgICAgZGF0YS5maWVsZHMgPSBzY2hlbWEuZmllbGRzO1xuICAgICAgICAgICAgZGF0YS5jbGFzc0xldmVsUGVybWlzc2lvbnMgPSBzY2hlbWEuY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgICAgICAgICAgZGF0YS5pbmRleGVzID0gc2NoZW1hLmluZGV4ZXM7XG4gICAgICAgICAgICB0aGlzLl9fZGF0YVtjbGFzc05hbWVdID0gZGF0YTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX19kYXRhW2NsYXNzTmFtZV07XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG5jb25zdCBpbmplY3REZWZhdWx0U2NoZW1hID0gKHtcbiAgY2xhc3NOYW1lLFxuICBmaWVsZHMsXG4gIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgaW5kZXhlcyxcbn06IFNjaGVtYSkgPT4ge1xuICBjb25zdCBkZWZhdWx0U2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgY2xhc3NOYW1lLFxuICAgIGZpZWxkczoge1xuICAgICAgLi4uZGVmYXVsdENvbHVtbnMuX0RlZmF1bHQsXG4gICAgICAuLi4oZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXSB8fCB7fSksXG4gICAgICAuLi5maWVsZHMsXG4gICAgfSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gIH07XG4gIGlmIChpbmRleGVzICYmIE9iamVjdC5rZXlzKGluZGV4ZXMpLmxlbmd0aCAhPT0gMCkge1xuICAgIGRlZmF1bHRTY2hlbWEuaW5kZXhlcyA9IGluZGV4ZXM7XG4gIH1cbiAgcmV0dXJuIGRlZmF1bHRTY2hlbWE7XG59O1xuXG5jb25zdCBfSG9va3NTY2hlbWEgPSB7IGNsYXNzTmFtZTogJ19Ib29rcycsIGZpZWxkczogZGVmYXVsdENvbHVtbnMuX0hvb2tzIH07XG5jb25zdCBfR2xvYmFsQ29uZmlnU2NoZW1hID0ge1xuICBjbGFzc05hbWU6ICdfR2xvYmFsQ29uZmlnJyxcbiAgZmllbGRzOiBkZWZhdWx0Q29sdW1ucy5fR2xvYmFsQ29uZmlnLFxufTtcbmNvbnN0IF9HcmFwaFFMQ29uZmlnU2NoZW1hID0ge1xuICBjbGFzc05hbWU6ICdfR3JhcGhRTENvbmZpZycsXG4gIGZpZWxkczogZGVmYXVsdENvbHVtbnMuX0dyYXBoUUxDb25maWcsXG59O1xuY29uc3QgX1B1c2hTdGF0dXNTY2hlbWEgPSBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hKFxuICBpbmplY3REZWZhdWx0U2NoZW1hKHtcbiAgICBjbGFzc05hbWU6ICdfUHVzaFN0YXR1cycsXG4gICAgZmllbGRzOiB7fSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHt9LFxuICB9KVxuKTtcbmNvbnN0IF9Kb2JTdGF0dXNTY2hlbWEgPSBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hKFxuICBpbmplY3REZWZhdWx0U2NoZW1hKHtcbiAgICBjbGFzc05hbWU6ICdfSm9iU3RhdHVzJyxcbiAgICBmaWVsZHM6IHt9LFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczoge30sXG4gIH0pXG4pO1xuY29uc3QgX0pvYlNjaGVkdWxlU2NoZW1hID0gY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShcbiAgaW5qZWN0RGVmYXVsdFNjaGVtYSh7XG4gICAgY2xhc3NOYW1lOiAnX0pvYlNjaGVkdWxlJyxcbiAgICBmaWVsZHM6IHt9LFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczoge30sXG4gIH0pXG4pO1xuY29uc3QgX0F1ZGllbmNlU2NoZW1hID0gY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShcbiAgaW5qZWN0RGVmYXVsdFNjaGVtYSh7XG4gICAgY2xhc3NOYW1lOiAnX0F1ZGllbmNlJyxcbiAgICBmaWVsZHM6IGRlZmF1bHRDb2x1bW5zLl9BdWRpZW5jZSxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHt9LFxuICB9KVxuKTtcbmNvbnN0IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMgPSBbXG4gIF9Ib29rc1NjaGVtYSxcbiAgX0pvYlN0YXR1c1NjaGVtYSxcbiAgX0pvYlNjaGVkdWxlU2NoZW1hLFxuICBfUHVzaFN0YXR1c1NjaGVtYSxcbiAgX0dsb2JhbENvbmZpZ1NjaGVtYSxcbiAgX0dyYXBoUUxDb25maWdTY2hlbWEsXG4gIF9BdWRpZW5jZVNjaGVtYSxcbl07XG5cbmNvbnN0IGRiVHlwZU1hdGNoZXNPYmplY3RUeXBlID0gKFxuICBkYlR5cGU6IFNjaGVtYUZpZWxkIHwgc3RyaW5nLFxuICBvYmplY3RUeXBlOiBTY2hlbWFGaWVsZFxuKSA9PiB7XG4gIGlmIChkYlR5cGUudHlwZSAhPT0gb2JqZWN0VHlwZS50eXBlKSByZXR1cm4gZmFsc2U7XG4gIGlmIChkYlR5cGUudGFyZ2V0Q2xhc3MgIT09IG9iamVjdFR5cGUudGFyZ2V0Q2xhc3MpIHJldHVybiBmYWxzZTtcbiAgaWYgKGRiVHlwZSA9PT0gb2JqZWN0VHlwZS50eXBlKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGRiVHlwZS50eXBlID09PSBvYmplY3RUeXBlLnR5cGUpIHJldHVybiB0cnVlO1xuICByZXR1cm4gZmFsc2U7XG59O1xuXG5jb25zdCB0eXBlVG9TdHJpbmcgPSAodHlwZTogU2NoZW1hRmllbGQgfCBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICBpZiAodHlwZW9mIHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHR5cGU7XG4gIH1cbiAgaWYgKHR5cGUudGFyZ2V0Q2xhc3MpIHtcbiAgICByZXR1cm4gYCR7dHlwZS50eXBlfTwke3R5cGUudGFyZ2V0Q2xhc3N9PmA7XG4gIH1cbiAgcmV0dXJuIGAke3R5cGUudHlwZX1gO1xufTtcblxuLy8gU3RvcmVzIHRoZSBlbnRpcmUgc2NoZW1hIG9mIHRoZSBhcHAgaW4gYSB3ZWlyZCBoeWJyaWQgZm9ybWF0IHNvbWV3aGVyZSBiZXR3ZWVuXG4vLyB0aGUgbW9uZ28gZm9ybWF0IGFuZCB0aGUgUGFyc2UgZm9ybWF0LiBTb29uLCB0aGlzIHdpbGwgYWxsIGJlIFBhcnNlIGZvcm1hdC5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjaGVtYUNvbnRyb2xsZXIge1xuICBfZGJBZGFwdGVyOiBTdG9yYWdlQWRhcHRlcjtcbiAgc2NoZW1hRGF0YTogeyBbc3RyaW5nXTogU2NoZW1hIH07XG4gIF9jYWNoZTogYW55O1xuICByZWxvYWREYXRhUHJvbWlzZTogP1Byb21pc2U8YW55PjtcbiAgcHJvdGVjdGVkRmllbGRzOiBhbnk7XG4gIHVzZXJJZFJlZ0V4OiBSZWdFeHA7XG5cbiAgY29uc3RydWN0b3IoZGF0YWJhc2VBZGFwdGVyOiBTdG9yYWdlQWRhcHRlciwgc2NoZW1hQ2FjaGU6IGFueSkge1xuICAgIHRoaXMuX2RiQWRhcHRlciA9IGRhdGFiYXNlQWRhcHRlcjtcbiAgICB0aGlzLl9jYWNoZSA9IHNjaGVtYUNhY2hlO1xuICAgIHRoaXMuc2NoZW1hRGF0YSA9IG5ldyBTY2hlbWFEYXRhKCk7XG4gICAgdGhpcy5wcm90ZWN0ZWRGaWVsZHMgPSBDb25maWcuZ2V0KFBhcnNlLmFwcGxpY2F0aW9uSWQpLnByb3RlY3RlZEZpZWxkcztcblxuICAgIGNvbnN0IGN1c3RvbUlkcyA9IENvbmZpZy5nZXQoUGFyc2UuYXBwbGljYXRpb25JZCkuYWxsb3dDdXN0b21PYmplY3RJZDtcblxuICAgIGNvbnN0IGN1c3RvbUlkUmVnRXggPSAvXi57MSx9JC91OyAvLyAxKyBjaGFyc1xuICAgIGNvbnN0IGF1dG9JZFJlZ0V4ID0gL15bYS16QS1aMC05XXsxLH0kLztcblxuICAgIHRoaXMudXNlcklkUmVnRXggPSBjdXN0b21JZHMgPyBjdXN0b21JZFJlZ0V4IDogYXV0b0lkUmVnRXg7XG4gIH1cblxuICByZWxvYWREYXRhKG9wdGlvbnM6IExvYWRTY2hlbWFPcHRpb25zID0geyBjbGVhckNhY2hlOiBmYWxzZSB9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBpZiAodGhpcy5yZWxvYWREYXRhUHJvbWlzZSAmJiAhb3B0aW9ucy5jbGVhckNhY2hlKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWxvYWREYXRhUHJvbWlzZTtcbiAgICB9XG4gICAgdGhpcy5yZWxvYWREYXRhUHJvbWlzZSA9IHRoaXMuZ2V0QWxsQ2xhc3NlcyhvcHRpb25zKVxuICAgICAgLnRoZW4oXG4gICAgICAgIGFsbFNjaGVtYXMgPT4ge1xuICAgICAgICAgIHRoaXMuc2NoZW1hRGF0YSA9IG5ldyBTY2hlbWFEYXRhKGFsbFNjaGVtYXMsIHRoaXMucHJvdGVjdGVkRmllbGRzKTtcbiAgICAgICAgICBkZWxldGUgdGhpcy5yZWxvYWREYXRhUHJvbWlzZTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyID0+IHtcbiAgICAgICAgICB0aGlzLnNjaGVtYURhdGEgPSBuZXcgU2NoZW1hRGF0YSgpO1xuICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbG9hZERhdGFQcm9taXNlO1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgKVxuICAgICAgLnRoZW4oKCkgPT4ge30pO1xuICAgIHJldHVybiB0aGlzLnJlbG9hZERhdGFQcm9taXNlO1xuICB9XG5cbiAgZ2V0QWxsQ2xhc3NlcyhcbiAgICBvcHRpb25zOiBMb2FkU2NoZW1hT3B0aW9ucyA9IHsgY2xlYXJDYWNoZTogZmFsc2UgfVxuICApOiBQcm9taXNlPEFycmF5PFNjaGVtYT4+IHtcbiAgICBpZiAob3B0aW9ucy5jbGVhckNhY2hlKSB7XG4gICAgICByZXR1cm4gdGhpcy5zZXRBbGxDbGFzc2VzKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jYWNoZS5nZXRBbGxDbGFzc2VzKCkudGhlbihhbGxDbGFzc2VzID0+IHtcbiAgICAgIGlmIChhbGxDbGFzc2VzICYmIGFsbENsYXNzZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYWxsQ2xhc3Nlcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5zZXRBbGxDbGFzc2VzKCk7XG4gICAgfSk7XG4gIH1cblxuICBzZXRBbGxDbGFzc2VzKCk6IFByb21pc2U8QXJyYXk8U2NoZW1hPj4ge1xuICAgIHJldHVybiB0aGlzLl9kYkFkYXB0ZXJcbiAgICAgIC5nZXRBbGxDbGFzc2VzKClcbiAgICAgIC50aGVuKGFsbFNjaGVtYXMgPT4gYWxsU2NoZW1hcy5tYXAoaW5qZWN0RGVmYXVsdFNjaGVtYSkpXG4gICAgICAudGhlbihhbGxTY2hlbWFzID0+IHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICB0aGlzLl9jYWNoZVxuICAgICAgICAgIC5zZXRBbGxDbGFzc2VzKGFsbFNjaGVtYXMpXG4gICAgICAgICAgLmNhdGNoKGVycm9yID0+XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzYXZpbmcgc2NoZW1hIHRvIGNhY2hlOicsIGVycm9yKVxuICAgICAgICAgICk7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuICAgICAgICByZXR1cm4gYWxsU2NoZW1hcztcbiAgICAgIH0pO1xuICB9XG5cbiAgZ2V0T25lU2NoZW1hKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGFsbG93Vm9sYXRpbGVDbGFzc2VzOiBib29sZWFuID0gZmFsc2UsXG4gICAgb3B0aW9uczogTG9hZFNjaGVtYU9wdGlvbnMgPSB7IGNsZWFyQ2FjaGU6IGZhbHNlIH1cbiAgKTogUHJvbWlzZTxTY2hlbWE+IHtcbiAgICBsZXQgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIGlmIChvcHRpb25zLmNsZWFyQ2FjaGUpIHtcbiAgICAgIHByb21pc2UgPSB0aGlzLl9jYWNoZS5jbGVhcigpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChhbGxvd1ZvbGF0aWxlQ2xhc3NlcyAmJiB2b2xhdGlsZUNsYXNzZXMuaW5kZXhPZihjbGFzc05hbWUpID4gLTEpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgZmllbGRzOiBkYXRhLmZpZWxkcyxcbiAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IGRhdGEuY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgICAgIGluZGV4ZXM6IGRhdGEuaW5kZXhlcyxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fY2FjaGUuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSkudGhlbihjYWNoZWQgPT4ge1xuICAgICAgICBpZiAoY2FjaGVkICYmICFvcHRpb25zLmNsZWFyQ2FjaGUpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNhY2hlZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0QWxsQ2xhc3NlcygpLnRoZW4oYWxsU2NoZW1hcyA9PiB7XG4gICAgICAgICAgY29uc3Qgb25lU2NoZW1hID0gYWxsU2NoZW1hcy5maW5kKFxuICAgICAgICAgICAgc2NoZW1hID0+IHNjaGVtYS5jbGFzc05hbWUgPT09IGNsYXNzTmFtZVxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKCFvbmVTY2hlbWEpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh1bmRlZmluZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gb25lU2NoZW1hO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gQ3JlYXRlIGEgbmV3IGNsYXNzIHRoYXQgaW5jbHVkZXMgdGhlIHRocmVlIGRlZmF1bHQgZmllbGRzLlxuICAvLyBBQ0wgaXMgYW4gaW1wbGljaXQgY29sdW1uIHRoYXQgZG9lcyBub3QgZ2V0IGFuIGVudHJ5IGluIHRoZVxuICAvLyBfU0NIRU1BUyBkYXRhYmFzZS4gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZVxuICAvLyBjcmVhdGVkIHNjaGVtYSwgaW4gbW9uZ28gZm9ybWF0LlxuICAvLyBvbiBzdWNjZXNzLCBhbmQgcmVqZWN0cyB3aXRoIGFuIGVycm9yIG9uIGZhaWwuIEVuc3VyZSB5b3VcbiAgLy8gaGF2ZSBhdXRob3JpemF0aW9uIChtYXN0ZXIga2V5LCBvciBjbGllbnQgY2xhc3MgY3JlYXRpb25cbiAgLy8gZW5hYmxlZCkgYmVmb3JlIGNhbGxpbmcgdGhpcyBmdW5jdGlvbi5cbiAgYWRkQ2xhc3NJZk5vdEV4aXN0cyhcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBmaWVsZHM6IFNjaGVtYUZpZWxkcyA9IHt9LFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogYW55LFxuICAgIGluZGV4ZXM6IGFueSA9IHt9XG4gICk6IFByb21pc2U8dm9pZCB8IFNjaGVtYT4ge1xuICAgIHZhciB2YWxpZGF0aW9uRXJyb3IgPSB0aGlzLnZhbGlkYXRlTmV3Q2xhc3MoXG4gICAgICBjbGFzc05hbWUsXG4gICAgICBmaWVsZHMsXG4gICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnNcbiAgICApO1xuICAgIGlmICh2YWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgIGlmICh2YWxpZGF0aW9uRXJyb3IgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QodmFsaWRhdGlvbkVycm9yKTtcbiAgICAgIH0gZWxzZSBpZiAodmFsaWRhdGlvbkVycm9yLmNvZGUgJiYgdmFsaWRhdGlvbkVycm9yLmVycm9yKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IodmFsaWRhdGlvbkVycm9yLmNvZGUsIHZhbGlkYXRpb25FcnJvci5lcnJvcilcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh2YWxpZGF0aW9uRXJyb3IpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9kYkFkYXB0ZXJcbiAgICAgIC5jcmVhdGVDbGFzcyhcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hKHtcbiAgICAgICAgICBmaWVsZHMsXG4gICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgICAgIGluZGV4ZXMsXG4gICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgLnRoZW4oY29udmVydEFkYXB0ZXJTY2hlbWFUb1BhcnNlU2NoZW1hKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yICYmIGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSxcbiAgICAgICAgICAgIGBDbGFzcyAke2NsYXNzTmFtZX0gYWxyZWFkeSBleGlzdHMuYFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlQ2xhc3MoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc3VibWl0dGVkRmllbGRzOiBTY2hlbWFGaWVsZHMsXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBhbnksXG4gICAgaW5kZXhlczogYW55LFxuICAgIGRhdGFiYXNlOiBEYXRhYmFzZUNvbnRyb2xsZXJcbiAgKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKHNjaGVtYSA9PiB7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nRmllbGRzID0gc2NoZW1hLmZpZWxkcztcbiAgICAgICAgT2JqZWN0LmtleXMoc3VibWl0dGVkRmllbGRzKS5mb3JFYWNoKG5hbWUgPT4ge1xuICAgICAgICAgIGNvbnN0IGZpZWxkID0gc3VibWl0dGVkRmllbGRzW25hbWVdO1xuICAgICAgICAgIGlmIChleGlzdGluZ0ZpZWxkc1tuYW1lXSAmJiBmaWVsZC5fX29wICE9PSAnRGVsZXRlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDI1NSwgYEZpZWxkICR7bmFtZX0gZXhpc3RzLCBjYW5ub3QgdXBkYXRlLmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIWV4aXN0aW5nRmllbGRzW25hbWVdICYmIGZpZWxkLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIDI1NSxcbiAgICAgICAgICAgICAgYEZpZWxkICR7bmFtZX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBkZWxldGUuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0ZpZWxkcy5fcnBlcm07XG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0ZpZWxkcy5fd3Blcm07XG4gICAgICAgIGNvbnN0IG5ld1NjaGVtYSA9IGJ1aWxkTWVyZ2VkU2NoZW1hT2JqZWN0KFxuICAgICAgICAgIGV4aXN0aW5nRmllbGRzLFxuICAgICAgICAgIHN1Ym1pdHRlZEZpZWxkc1xuICAgICAgICApO1xuICAgICAgICBjb25zdCBkZWZhdWx0RmllbGRzID1cbiAgICAgICAgICBkZWZhdWx0Q29sdW1uc1tjbGFzc05hbWVdIHx8IGRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0O1xuICAgICAgICBjb25zdCBmdWxsTmV3U2NoZW1hID0gT2JqZWN0LmFzc2lnbih7fSwgbmV3U2NoZW1hLCBkZWZhdWx0RmllbGRzKTtcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvbkVycm9yID0gdGhpcy52YWxpZGF0ZVNjaGVtYURhdGEoXG4gICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgIG5ld1NjaGVtYSxcbiAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgT2JqZWN0LmtleXMoZXhpc3RpbmdGaWVsZHMpXG4gICAgICAgICk7XG4gICAgICAgIGlmICh2YWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IodmFsaWRhdGlvbkVycm9yLmNvZGUsIHZhbGlkYXRpb25FcnJvci5lcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaW5hbGx5IHdlIGhhdmUgY2hlY2tlZCB0byBtYWtlIHN1cmUgdGhlIHJlcXVlc3QgaXMgdmFsaWQgYW5kIHdlIGNhbiBzdGFydCBkZWxldGluZyBmaWVsZHMuXG4gICAgICAgIC8vIERvIGFsbCBkZWxldGlvbnMgZmlyc3QsIHRoZW4gYSBzaW5nbGUgc2F2ZSB0byBfU0NIRU1BIGNvbGxlY3Rpb24gdG8gaGFuZGxlIGFsbCBhZGRpdGlvbnMuXG4gICAgICAgIGNvbnN0IGRlbGV0ZWRGaWVsZHM6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGNvbnN0IGluc2VydGVkRmllbGRzID0gW107XG4gICAgICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEZpZWxkcykuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgIGlmIChzdWJtaXR0ZWRGaWVsZHNbZmllbGROYW1lXS5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICAgICAgZGVsZXRlZEZpZWxkcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGluc2VydGVkRmllbGRzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCBkZWxldGVQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIGlmIChkZWxldGVkRmllbGRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBkZWxldGVQcm9taXNlID0gdGhpcy5kZWxldGVGaWVsZHMoZGVsZXRlZEZpZWxkcywgY2xhc3NOYW1lLCBkYXRhYmFzZSk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGVuZm9yY2VGaWVsZHMgPSBbXTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBkZWxldGVQcm9taXNlIC8vIERlbGV0ZSBFdmVyeXRoaW5nXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLnJlbG9hZERhdGEoeyBjbGVhckNhY2hlOiB0cnVlIH0pKSAvLyBSZWxvYWQgb3VyIFNjaGVtYSwgc28gd2UgaGF2ZSBhbGwgdGhlIG5ldyB2YWx1ZXNcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBpbnNlcnRlZEZpZWxkcy5tYXAoZmllbGROYW1lID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCB0eXBlID0gc3VibWl0dGVkRmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5mb3JjZUZpZWxkRXhpc3RzKGNsYXNzTmFtZSwgZmllbGROYW1lLCB0eXBlKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgICAgIGVuZm9yY2VGaWVsZHMgPSByZXN1bHRzLmZpbHRlcihyZXN1bHQgPT4gISFyZXN1bHQpO1xuICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZXRQZXJtaXNzaW9ucyhcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgICAgICAgICAgIG5ld1NjaGVtYVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+XG4gICAgICAgICAgICAgIHRoaXMuX2RiQWRhcHRlci5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgaW5kZXhlcyxcbiAgICAgICAgICAgICAgICBzY2hlbWEuaW5kZXhlcyxcbiAgICAgICAgICAgICAgICBmdWxsTmV3U2NoZW1hXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMucmVsb2FkRGF0YSh7IGNsZWFyQ2FjaGU6IHRydWUgfSkpXG4gICAgICAgICAgICAvL1RPRE86IE1vdmUgdGhpcyBsb2dpYyBpbnRvIHRoZSBkYXRhYmFzZSBhZGFwdGVyXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuZW5zdXJlRmllbGRzKGVuZm9yY2VGaWVsZHMpO1xuICAgICAgICAgICAgICBjb25zdCBzY2hlbWEgPSB0aGlzLnNjaGVtYURhdGFbY2xhc3NOYW1lXTtcbiAgICAgICAgICAgICAgY29uc3QgcmVsb2FkZWRTY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICBmaWVsZHM6IHNjaGVtYS5maWVsZHMsXG4gICAgICAgICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBzY2hlbWEuY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBpZiAoc2NoZW1hLmluZGV4ZXMgJiYgT2JqZWN0LmtleXMoc2NoZW1hLmluZGV4ZXMpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHJlbG9hZGVkU2NoZW1hLmluZGV4ZXMgPSBzY2hlbWEuaW5kZXhlcztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4gcmVsb2FkZWRTY2hlbWE7XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICAgICAgYENsYXNzICR7Y2xhc3NOYW1lfSBkb2VzIG5vdCBleGlzdC5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSB0byB0aGUgbmV3IHNjaGVtYVxuICAvLyBvYmplY3Qgb3IgZmFpbHMgd2l0aCBhIHJlYXNvbi5cbiAgZW5mb3JjZUNsYXNzRXhpc3RzKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTxTY2hlbWFDb250cm9sbGVyPiB7XG4gICAgaWYgKHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuICAgIH1cbiAgICAvLyBXZSBkb24ndCBoYXZlIHRoaXMgY2xhc3MuIFVwZGF0ZSB0aGUgc2NoZW1hXG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuYWRkQ2xhc3NJZk5vdEV4aXN0cyhjbGFzc05hbWUpXG4gICAgICAgIC8vIFRoZSBzY2hlbWEgdXBkYXRlIHN1Y2NlZWRlZC4gUmVsb2FkIHRoZSBzY2hlbWFcbiAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5yZWxvYWREYXRhKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KSlcbiAgICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAvLyBUaGUgc2NoZW1hIHVwZGF0ZSBmYWlsZWQuIFRoaXMgY2FuIGJlIG9rYXkgLSBpdCBtaWdodFxuICAgICAgICAgIC8vIGhhdmUgZmFpbGVkIGJlY2F1c2UgdGhlcmUncyBhIHJhY2UgY29uZGl0aW9uIGFuZCBhIGRpZmZlcmVudFxuICAgICAgICAgIC8vIGNsaWVudCBpcyBtYWtpbmcgdGhlIGV4YWN0IHNhbWUgc2NoZW1hIHVwZGF0ZSB0aGF0IHdlIHdhbnQuXG4gICAgICAgICAgLy8gU28ganVzdCByZWxvYWQgdGhlIHNjaGVtYS5cbiAgICAgICAgICByZXR1cm4gdGhpcy5yZWxvYWREYXRhKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KTtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIC8vIEVuc3VyZSB0aGF0IHRoZSBzY2hlbWEgbm93IHZhbGlkYXRlc1xuICAgICAgICAgIGlmICh0aGlzLnNjaGVtYURhdGFbY2xhc3NOYW1lXSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIGFkZCAke2NsYXNzTmFtZX1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAvLyBUaGUgc2NoZW1hIHN0aWxsIGRvZXNuJ3QgdmFsaWRhdGUuIEdpdmUgdXBcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnc2NoZW1hIGNsYXNzIG5hbWUgZG9lcyBub3QgcmV2YWxpZGF0ZSdcbiAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICB2YWxpZGF0ZU5ld0NsYXNzKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGZpZWxkczogU2NoZW1hRmllbGRzID0ge30sXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBhbnlcbiAgKTogYW55IHtcbiAgICBpZiAodGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV0pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICBgQ2xhc3MgJHtjbGFzc05hbWV9IGFscmVhZHkgZXhpc3RzLmBcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICghY2xhc3NOYW1lSXNWYWxpZChjbGFzc05hbWUpKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2RlOiBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICAgIGVycm9yOiBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZShjbGFzc05hbWUpLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGVTY2hlbWFEYXRhKFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgZmllbGRzLFxuICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgW11cbiAgICApO1xuICB9XG5cbiAgdmFsaWRhdGVTY2hlbWFEYXRhKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGZpZWxkczogU2NoZW1hRmllbGRzLFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogQ2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgIGV4aXN0aW5nRmllbGROYW1lczogQXJyYXk8c3RyaW5nPlxuICApIHtcbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiBmaWVsZHMpIHtcbiAgICAgIGlmIChleGlzdGluZ0ZpZWxkTmFtZXMuaW5kZXhPZihmaWVsZE5hbWUpIDwgMCkge1xuICAgICAgICBpZiAoIWZpZWxkTmFtZUlzVmFsaWQoZmllbGROYW1lKSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb2RlOiBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICAgICAgZXJyb3I6ICdpbnZhbGlkIGZpZWxkIG5hbWU6ICcgKyBmaWVsZE5hbWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZpZWxkTmFtZUlzVmFsaWRGb3JDbGFzcyhmaWVsZE5hbWUsIGNsYXNzTmFtZSkpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29kZTogMTM2LFxuICAgICAgICAgICAgZXJyb3I6ICdmaWVsZCAnICsgZmllbGROYW1lICsgJyBjYW5ub3QgYmUgYWRkZWQnLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZmllbGRUeXBlID0gZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgIGNvbnN0IGVycm9yID0gZmllbGRUeXBlSXNJbnZhbGlkKGZpZWxkVHlwZSk7XG4gICAgICAgIGlmIChlcnJvcikgcmV0dXJuIHsgY29kZTogZXJyb3IuY29kZSwgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfTtcbiAgICAgICAgaWYgKGZpZWxkVHlwZS5kZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGxldCBkZWZhdWx0VmFsdWVUeXBlID0gZ2V0VHlwZShmaWVsZFR5cGUuZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICBpZiAodHlwZW9mIGRlZmF1bHRWYWx1ZVR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVUeXBlID0geyB0eXBlOiBkZWZhdWx0VmFsdWVUeXBlIH07XG4gICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgIHR5cGVvZiBkZWZhdWx0VmFsdWVUeXBlID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgICAgZmllbGRUeXBlLnR5cGUgPT09ICdSZWxhdGlvbidcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgICAgICAgICBlcnJvcjogYFRoZSAnZGVmYXVsdCB2YWx1ZScgb3B0aW9uIGlzIG5vdCBhcHBsaWNhYmxlIGZvciAke3R5cGVUb1N0cmluZyhcbiAgICAgICAgICAgICAgICBmaWVsZFR5cGVcbiAgICAgICAgICAgICAgKX1gLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFkYlR5cGVNYXRjaGVzT2JqZWN0VHlwZShmaWVsZFR5cGUsIGRlZmF1bHRWYWx1ZVR5cGUpKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBjb2RlOiBQYXJzZS5FcnJvci5JTkNPUlJFQ1RfVFlQRSxcbiAgICAgICAgICAgICAgZXJyb3I6IGBzY2hlbWEgbWlzbWF0Y2ggZm9yICR7Y2xhc3NOYW1lfS4ke2ZpZWxkTmFtZX0gZGVmYXVsdCB2YWx1ZTsgZXhwZWN0ZWQgJHt0eXBlVG9TdHJpbmcoXG4gICAgICAgICAgICAgICAgZmllbGRUeXBlXG4gICAgICAgICAgICAgICl9IGJ1dCBnb3QgJHt0eXBlVG9TdHJpbmcoZGVmYXVsdFZhbHVlVHlwZSl9YCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkVHlwZS5yZXF1aXJlZCkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZmllbGRUeXBlID09PSAnb2JqZWN0JyAmJiBmaWVsZFR5cGUudHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgY29kZTogUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgICAgICAgIGVycm9yOiBgVGhlICdyZXF1aXJlZCcgb3B0aW9uIGlzIG5vdCBhcHBsaWNhYmxlIGZvciAke3R5cGVUb1N0cmluZyhcbiAgICAgICAgICAgICAgICBmaWVsZFR5cGVcbiAgICAgICAgICAgICAgKX1gLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiBkZWZhdWx0Q29sdW1uc1tjbGFzc05hbWVdKSB7XG4gICAgICBmaWVsZHNbZmllbGROYW1lXSA9IGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV1bZmllbGROYW1lXTtcbiAgICB9XG5cbiAgICBjb25zdCBnZW9Qb2ludHMgPSBPYmplY3Qua2V5cyhmaWVsZHMpLmZpbHRlcihcbiAgICAgIGtleSA9PiBmaWVsZHNba2V5XSAmJiBmaWVsZHNba2V5XS50eXBlID09PSAnR2VvUG9pbnQnXG4gICAgKTtcbiAgICBpZiAoZ2VvUG9pbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgICBlcnJvcjpcbiAgICAgICAgICAnY3VycmVudGx5LCBvbmx5IG9uZSBHZW9Qb2ludCBmaWVsZCBtYXkgZXhpc3QgaW4gYW4gb2JqZWN0LiBBZGRpbmcgJyArXG4gICAgICAgICAgZ2VvUG9pbnRzWzFdICtcbiAgICAgICAgICAnIHdoZW4gJyArXG4gICAgICAgICAgZ2VvUG9pbnRzWzBdICtcbiAgICAgICAgICAnIGFscmVhZHkgZXhpc3RzLicsXG4gICAgICB9O1xuICAgIH1cbiAgICB2YWxpZGF0ZUNMUChjbGFzc0xldmVsUGVybWlzc2lvbnMsIGZpZWxkcywgdGhpcy51c2VySWRSZWdFeCk7XG4gIH1cblxuICAvLyBTZXRzIHRoZSBDbGFzcy1sZXZlbCBwZXJtaXNzaW9ucyBmb3IgYSBnaXZlbiBjbGFzc05hbWUsIHdoaWNoIG11c3QgZXhpc3QuXG4gIHNldFBlcm1pc3Npb25zKGNsYXNzTmFtZTogc3RyaW5nLCBwZXJtczogYW55LCBuZXdTY2hlbWE6IFNjaGVtYUZpZWxkcykge1xuICAgIGlmICh0eXBlb2YgcGVybXMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHZhbGlkYXRlQ0xQKHBlcm1zLCBuZXdTY2hlbWEsIHRoaXMudXNlcklkUmVnRXgpO1xuICAgIHJldHVybiB0aGlzLl9kYkFkYXB0ZXIuc2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKGNsYXNzTmFtZSwgcGVybXMpO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBzdWNjZXNzZnVsbHkgdG8gdGhlIG5ldyBzY2hlbWFcbiAgLy8gb2JqZWN0IGlmIHRoZSBwcm92aWRlZCBjbGFzc05hbWUtZmllbGROYW1lLXR5cGUgdHVwbGUgaXMgdmFsaWQuXG4gIC8vIFRoZSBjbGFzc05hbWUgbXVzdCBhbHJlYWR5IGJlIHZhbGlkYXRlZC5cbiAgLy8gSWYgJ2ZyZWV6ZScgaXMgdHJ1ZSwgcmVmdXNlIHRvIHVwZGF0ZSB0aGUgc2NoZW1hIGZvciB0aGlzIGZpZWxkLlxuICBlbmZvcmNlRmllbGRFeGlzdHMoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZmllbGROYW1lOiBzdHJpbmcsXG4gICAgdHlwZTogc3RyaW5nIHwgU2NoZW1hRmllbGRcbiAgKSB7XG4gICAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPiAwKSB7XG4gICAgICAvLyBzdWJkb2N1bWVudCBrZXkgKHgueSkgPT4gb2sgaWYgeCBpcyBvZiB0eXBlICdvYmplY3QnXG4gICAgICBmaWVsZE5hbWUgPSBmaWVsZE5hbWUuc3BsaXQoJy4nKVswXTtcbiAgICAgIHR5cGUgPSAnT2JqZWN0JztcbiAgICB9XG4gICAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICAgYEludmFsaWQgZmllbGQgbmFtZTogJHtmaWVsZE5hbWV9LmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gSWYgc29tZW9uZSB0cmllcyB0byBjcmVhdGUgYSBuZXcgZmllbGQgd2l0aCBudWxsL3VuZGVmaW5lZCBhcyB0aGUgdmFsdWUsIHJldHVybjtcbiAgICBpZiAoIXR5cGUpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gdGhpcy5nZXRFeHBlY3RlZFR5cGUoY2xhc3NOYW1lLCBmaWVsZE5hbWUpO1xuICAgIGlmICh0eXBlb2YgdHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHR5cGUgPSAoeyB0eXBlIH06IFNjaGVtYUZpZWxkKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZS5kZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgbGV0IGRlZmF1bHRWYWx1ZVR5cGUgPSBnZXRUeXBlKHR5cGUuZGVmYXVsdFZhbHVlKTtcbiAgICAgIGlmICh0eXBlb2YgZGVmYXVsdFZhbHVlVHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZGVmYXVsdFZhbHVlVHlwZSA9IHsgdHlwZTogZGVmYXVsdFZhbHVlVHlwZSB9O1xuICAgICAgfVxuICAgICAgaWYgKCFkYlR5cGVNYXRjaGVzT2JqZWN0VHlwZSh0eXBlLCBkZWZhdWx0VmFsdWVUeXBlKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgICAgYHNjaGVtYSBtaXNtYXRjaCBmb3IgJHtjbGFzc05hbWV9LiR7ZmllbGROYW1lfSBkZWZhdWx0IHZhbHVlOyBleHBlY3RlZCAke3R5cGVUb1N0cmluZyhcbiAgICAgICAgICAgIHR5cGVcbiAgICAgICAgICApfSBidXQgZ290ICR7dHlwZVRvU3RyaW5nKGRlZmF1bHRWYWx1ZVR5cGUpfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXhwZWN0ZWRUeXBlKSB7XG4gICAgICBpZiAoIWRiVHlwZU1hdGNoZXNPYmplY3RUeXBlKGV4cGVjdGVkVHlwZSwgdHlwZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgICAgIGBzY2hlbWEgbWlzbWF0Y2ggZm9yICR7Y2xhc3NOYW1lfS4ke2ZpZWxkTmFtZX07IGV4cGVjdGVkICR7dHlwZVRvU3RyaW5nKFxuICAgICAgICAgICAgZXhwZWN0ZWRUeXBlXG4gICAgICAgICAgKX0gYnV0IGdvdCAke3R5cGVUb1N0cmluZyh0eXBlKX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9kYkFkYXB0ZXJcbiAgICAgIC5hZGRGaWVsZElmTm90RXhpc3RzKGNsYXNzTmFtZSwgZmllbGROYW1lLCB0eXBlKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT0gUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUpIHtcbiAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhhdCB3ZSB0aHJvdyBlcnJvcnMgd2hlbiBpdCBpcyBhcHByb3ByaWF0ZSB0byBkbyBzby5cbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgdXBkYXRlIGZhaWxlZC4gVGhpcyBjYW4gYmUgb2theSAtIGl0IG1pZ2h0IGhhdmUgYmVlbiBhIHJhY2VcbiAgICAgICAgLy8gY29uZGl0aW9uIHdoZXJlIGFub3RoZXIgY2xpZW50IHVwZGF0ZWQgdGhlIHNjaGVtYSBpbiB0aGUgc2FtZVxuICAgICAgICAvLyB3YXkgdGhhdCB3ZSB3YW50ZWQgdG8uIFNvLCBqdXN0IHJlbG9hZCB0aGUgc2NoZW1hXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgICB0eXBlLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gIH1cblxuICBlbnN1cmVGaWVsZHMoZmllbGRzOiBhbnkpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpZWxkcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY29uc3QgeyBjbGFzc05hbWUsIGZpZWxkTmFtZSB9ID0gZmllbGRzW2ldO1xuICAgICAgbGV0IHsgdHlwZSB9ID0gZmllbGRzW2ldO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gdGhpcy5nZXRFeHBlY3RlZFR5cGUoY2xhc3NOYW1lLCBmaWVsZE5hbWUpO1xuICAgICAgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICB0eXBlID0geyB0eXBlOiB0eXBlIH07XG4gICAgICB9XG4gICAgICBpZiAoIWV4cGVjdGVkVHlwZSB8fCAhZGJUeXBlTWF0Y2hlc09iamVjdFR5cGUoZXhwZWN0ZWRUeXBlLCB0eXBlKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBDb3VsZCBub3QgYWRkIGZpZWxkICR7ZmllbGROYW1lfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBtYWludGFpbiBjb21wYXRpYmlsaXR5XG4gIGRlbGV0ZUZpZWxkKFxuICAgIGZpZWxkTmFtZTogc3RyaW5nLFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGRhdGFiYXNlOiBEYXRhYmFzZUNvbnRyb2xsZXJcbiAgKSB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZXRlRmllbGRzKFtmaWVsZE5hbWVdLCBjbGFzc05hbWUsIGRhdGFiYXNlKTtcbiAgfVxuXG4gIC8vIERlbGV0ZSBmaWVsZHMsIGFuZCByZW1vdmUgdGhhdCBkYXRhIGZyb20gYWxsIG9iamVjdHMuIFRoaXMgaXMgaW50ZW5kZWRcbiAgLy8gdG8gcmVtb3ZlIHVudXNlZCBmaWVsZHMsIGlmIG90aGVyIHdyaXRlcnMgYXJlIHdyaXRpbmcgb2JqZWN0cyB0aGF0IGluY2x1ZGVcbiAgLy8gdGhpcyBmaWVsZCwgdGhlIGZpZWxkIG1heSByZWFwcGVhci4gUmV0dXJucyBhIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoXG4gIC8vIG5vIG9iamVjdCBvbiBzdWNjZXNzLCBvciByZWplY3RzIHdpdGggeyBjb2RlLCBlcnJvciB9IG9uIGZhaWx1cmUuXG4gIC8vIFBhc3NpbmcgdGhlIGRhdGFiYXNlIGFuZCBwcmVmaXggaXMgbmVjZXNzYXJ5IGluIG9yZGVyIHRvIGRyb3AgcmVsYXRpb24gY29sbGVjdGlvbnNcbiAgLy8gYW5kIHJlbW92ZSBmaWVsZHMgZnJvbSBvYmplY3RzLiBJZGVhbGx5IHRoZSBkYXRhYmFzZSB3b3VsZCBiZWxvbmcgdG9cbiAgLy8gYSBkYXRhYmFzZSBhZGFwdGVyIGFuZCB0aGlzIGZ1bmN0aW9uIHdvdWxkIGNsb3NlIG92ZXIgaXQgb3IgYWNjZXNzIGl0IHZpYSBtZW1iZXIuXG4gIGRlbGV0ZUZpZWxkcyhcbiAgICBmaWVsZE5hbWVzOiBBcnJheTxzdHJpbmc+LFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIGRhdGFiYXNlOiBEYXRhYmFzZUNvbnRyb2xsZXJcbiAgKSB7XG4gICAgaWYgKCFjbGFzc05hbWVJc1ZhbGlkKGNsYXNzTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZShjbGFzc05hbWUpXG4gICAgICApO1xuICAgIH1cblxuICAgIGZpZWxkTmFtZXMuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsXG4gICAgICAgICAgYGludmFsaWQgZmllbGQgbmFtZTogJHtmaWVsZE5hbWV9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy9Eb24ndCBhbGxvdyBkZWxldGluZyB0aGUgZGVmYXVsdCBmaWVsZHMuXG4gICAgICBpZiAoIWZpZWxkTmFtZUlzVmFsaWRGb3JDbGFzcyhmaWVsZE5hbWUsIGNsYXNzTmFtZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDEzNiwgYGZpZWxkICR7ZmllbGROYW1lfSBjYW5ub3QgYmUgY2hhbmdlZGApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSwgZmFsc2UsIHsgY2xlYXJDYWNoZTogdHJ1ZSB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsXG4gICAgICAgICAgICBgQ2xhc3MgJHtjbGFzc05hbWV9IGRvZXMgbm90IGV4aXN0LmBcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgICAgZmllbGROYW1lcy5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgaWYgKCFzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgMjU1LFxuICAgICAgICAgICAgICBgRmllbGQgJHtmaWVsZE5hbWV9IGRvZXMgbm90IGV4aXN0LCBjYW5ub3QgZGVsZXRlLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBzY2hlbWFGaWVsZHMgPSB7IC4uLnNjaGVtYS5maWVsZHMgfTtcbiAgICAgICAgcmV0dXJuIGRhdGFiYXNlLmFkYXB0ZXJcbiAgICAgICAgICAuZGVsZXRlRmllbGRzKGNsYXNzTmFtZSwgc2NoZW1hLCBmaWVsZE5hbWVzKVxuICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgZmllbGROYW1lcy5tYXAoZmllbGROYW1lID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWVsZCA9IHNjaGVtYUZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgICAgICAgICAgIGlmIChmaWVsZCAmJiBmaWVsZC50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgICAgICAgICAgICAvL0ZvciByZWxhdGlvbnMsIGRyb3AgdGhlIF9Kb2luIHRhYmxlXG4gICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YWJhc2UuYWRhcHRlci5kZWxldGVDbGFzcyhcbiAgICAgICAgICAgICAgICAgICAgYF9Kb2luOiR7ZmllbGROYW1lfToke2NsYXNzTmFtZX1gXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX2NhY2hlLmNsZWFyKCkpO1xuICB9XG5cbiAgLy8gVmFsaWRhdGVzIGFuIG9iamVjdCBwcm92aWRlZCBpbiBSRVNUIGZvcm1hdC5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbmV3IHNjaGVtYSBpZiB0aGlzIG9iamVjdCBpc1xuICAvLyB2YWxpZC5cbiAgYXN5bmMgdmFsaWRhdGVPYmplY3QoY2xhc3NOYW1lOiBzdHJpbmcsIG9iamVjdDogYW55LCBxdWVyeTogYW55KSB7XG4gICAgbGV0IGdlb2NvdW50ID0gMDtcbiAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCB0aGlzLmVuZm9yY2VDbGFzc0V4aXN0cyhjbGFzc05hbWUpO1xuICAgIGNvbnN0IHByb21pc2VzID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBnZXRUeXBlKG9iamVjdFtmaWVsZE5hbWVdKTtcbiAgICAgIGlmIChleHBlY3RlZCA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICBnZW9jb3VudCsrO1xuICAgICAgfVxuICAgICAgaWYgKGdlb2NvdW50ID4gMSkge1xuICAgICAgICAvLyBNYWtlIHN1cmUgYWxsIGZpZWxkIHZhbGlkYXRpb24gb3BlcmF0aW9ucyBydW4gYmVmb3JlIHdlIHJldHVybi5cbiAgICAgICAgLy8gSWYgbm90IC0gd2UgYXJlIGNvbnRpbnVpbmcgdG8gcnVuIGxvZ2ljLCBidXQgYWxyZWFkeSBwcm92aWRlZCByZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTkNPUlJFQ1RfVFlQRSxcbiAgICAgICAgICAgICd0aGVyZSBjYW4gb25seSBiZSBvbmUgZ2VvcG9pbnQgZmllbGQgaW4gYSBjbGFzcydcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4cGVjdGVkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGZpZWxkTmFtZSA9PT0gJ0FDTCcpIHtcbiAgICAgICAgLy8gRXZlcnkgb2JqZWN0IGhhcyBBQ0wgaW1wbGljaXRseS5cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBwcm9taXNlcy5wdXNoKHNjaGVtYS5lbmZvcmNlRmllbGRFeGlzdHMoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIGV4cGVjdGVkKSk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgY29uc3QgZW5mb3JjZUZpZWxkcyA9IHJlc3VsdHMuZmlsdGVyKHJlc3VsdCA9PiAhIXJlc3VsdCk7XG5cbiAgICBpZiAoZW5mb3JjZUZpZWxkcy5sZW5ndGggIT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMucmVsb2FkRGF0YSh7IGNsZWFyQ2FjaGU6IHRydWUgfSk7XG4gICAgfVxuICAgIHRoaXMuZW5zdXJlRmllbGRzKGVuZm9yY2VGaWVsZHMpO1xuXG4gICAgY29uc3QgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShzY2hlbWEpO1xuICAgIHJldHVybiB0aGVuVmFsaWRhdGVSZXF1aXJlZENvbHVtbnMocHJvbWlzZSwgY2xhc3NOYW1lLCBvYmplY3QsIHF1ZXJ5KTtcbiAgfVxuXG4gIC8vIFZhbGlkYXRlcyB0aGF0IGFsbCB0aGUgcHJvcGVydGllcyBhcmUgc2V0IGZvciB0aGUgb2JqZWN0XG4gIHZhbGlkYXRlUmVxdWlyZWRDb2x1bW5zKGNsYXNzTmFtZTogc3RyaW5nLCBvYmplY3Q6IGFueSwgcXVlcnk6IGFueSkge1xuICAgIGNvbnN0IGNvbHVtbnMgPSByZXF1aXJlZENvbHVtbnNbY2xhc3NOYW1lXTtcbiAgICBpZiAoIWNvbHVtbnMgfHwgY29sdW1ucy5sZW5ndGggPT0gMCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzKTtcbiAgICB9XG5cbiAgICBjb25zdCBtaXNzaW5nQ29sdW1ucyA9IGNvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uKGNvbHVtbikge1xuICAgICAgaWYgKHF1ZXJ5ICYmIHF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgICAgIGlmIChvYmplY3RbY29sdW1uXSAmJiB0eXBlb2Ygb2JqZWN0W2NvbHVtbl0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgLy8gVHJ5aW5nIHRvIGRlbGV0ZSBhIHJlcXVpcmVkIGNvbHVtblxuICAgICAgICAgIHJldHVybiBvYmplY3RbY29sdW1uXS5fX29wID09ICdEZWxldGUnO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vdCB0cnlpbmcgdG8gZG8gYW55dGhpbmcgdGhlcmVcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuICFvYmplY3RbY29sdW1uXTtcbiAgICB9KTtcblxuICAgIGlmIChtaXNzaW5nQ29sdW1ucy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgICBtaXNzaW5nQ29sdW1uc1swXSArICcgaXMgcmVxdWlyZWQuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzKTtcbiAgfVxuXG4gIHRlc3RQZXJtaXNzaW9uc0ZvckNsYXNzTmFtZShcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBhY2xHcm91cDogc3RyaW5nW10sXG4gICAgb3BlcmF0aW9uOiBzdHJpbmdcbiAgKSB7XG4gICAgcmV0dXJuIFNjaGVtYUNvbnRyb2xsZXIudGVzdFBlcm1pc3Npb25zKFxuICAgICAgdGhpcy5nZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lKSxcbiAgICAgIGFjbEdyb3VwLFxuICAgICAgb3BlcmF0aW9uXG4gICAgKTtcbiAgfVxuXG4gIC8vIFRlc3RzIHRoYXQgdGhlIGNsYXNzIGxldmVsIHBlcm1pc3Npb24gbGV0IHBhc3MgdGhlIG9wZXJhdGlvbiBmb3IgYSBnaXZlbiBhY2xHcm91cFxuICBzdGF0aWMgdGVzdFBlcm1pc3Npb25zKFxuICAgIGNsYXNzUGVybWlzc2lvbnM6ID9hbnksXG4gICAgYWNsR3JvdXA6IHN0cmluZ1tdLFxuICAgIG9wZXJhdGlvbjogc3RyaW5nXG4gICk6IGJvb2xlYW4ge1xuICAgIGlmICghY2xhc3NQZXJtaXNzaW9ucyB8fCAhY2xhc3NQZXJtaXNzaW9uc1tvcGVyYXRpb25dKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3QgcGVybXMgPSBjbGFzc1Blcm1pc3Npb25zW29wZXJhdGlvbl07XG4gICAgaWYgKHBlcm1zWycqJ10pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvLyBDaGVjayBwZXJtaXNzaW9ucyBhZ2FpbnN0IHRoZSBhY2xHcm91cCBwcm92aWRlZCAoYXJyYXkgb2YgdXNlcklkL3JvbGVzKVxuICAgIGlmIChcbiAgICAgIGFjbEdyb3VwLnNvbWUoYWNsID0+IHtcbiAgICAgICAgcmV0dXJuIHBlcm1zW2FjbF0gPT09IHRydWU7XG4gICAgICB9KVxuICAgICkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIFZhbGlkYXRlcyBhbiBvcGVyYXRpb24gcGFzc2VzIGNsYXNzLWxldmVsLXBlcm1pc3Npb25zIHNldCBpbiB0aGUgc2NoZW1hXG4gIHN0YXRpYyB2YWxpZGF0ZVBlcm1pc3Npb24oXG4gICAgY2xhc3NQZXJtaXNzaW9uczogP2FueSxcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBhY2xHcm91cDogc3RyaW5nW10sXG4gICAgb3BlcmF0aW9uOiBzdHJpbmcsXG4gICAgYWN0aW9uPzogc3RyaW5nXG4gICkge1xuICAgIGlmIChcbiAgICAgIFNjaGVtYUNvbnRyb2xsZXIudGVzdFBlcm1pc3Npb25zKGNsYXNzUGVybWlzc2lvbnMsIGFjbEdyb3VwLCBvcGVyYXRpb24pXG4gICAgKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYgKCFjbGFzc1Blcm1pc3Npb25zIHx8ICFjbGFzc1Blcm1pc3Npb25zW29wZXJhdGlvbl0pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjb25zdCBwZXJtcyA9IGNsYXNzUGVybWlzc2lvbnNbb3BlcmF0aW9uXTtcbiAgICAvLyBJZiBvbmx5IGZvciBhdXRoZW50aWNhdGVkIHVzZXJzXG4gICAgLy8gbWFrZSBzdXJlIHdlIGhhdmUgYW4gYWNsR3JvdXBcbiAgICBpZiAocGVybXNbJ3JlcXVpcmVzQXV0aGVudGljYXRpb24nXSkge1xuICAgICAgLy8gSWYgYWNsR3JvdXAgaGFzICogKHB1YmxpYylcbiAgICAgIGlmICghYWNsR3JvdXAgfHwgYWNsR3JvdXAubGVuZ3RoID09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgJ1Blcm1pc3Npb24gZGVuaWVkLCB1c2VyIG5lZWRzIHRvIGJlIGF1dGhlbnRpY2F0ZWQuJ1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChhY2xHcm91cC5pbmRleE9mKCcqJykgPiAtMSAmJiBhY2xHcm91cC5sZW5ndGggPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAnUGVybWlzc2lvbiBkZW5pZWQsIHVzZXIgbmVlZHMgdG8gYmUgYXV0aGVudGljYXRlZC4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICAvLyByZXF1aXJlc0F1dGhlbnRpY2F0aW9uIHBhc3NlZCwganVzdCBtb3ZlIGZvcndhcmRcbiAgICAgIC8vIHByb2JhYmx5IHdvdWxkIGJlIHdpc2UgYXQgc29tZSBwb2ludCB0byByZW5hbWUgdG8gJ2F1dGhlbnRpY2F0ZWRVc2VyJ1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIC8vIE5vIG1hdGNoaW5nIENMUCwgbGV0J3MgY2hlY2sgdGhlIFBvaW50ZXIgcGVybWlzc2lvbnNcbiAgICAvLyBBbmQgaGFuZGxlIHRob3NlIGxhdGVyXG4gICAgY29uc3QgcGVybWlzc2lvbkZpZWxkID1cbiAgICAgIFsnZ2V0JywgJ2ZpbmQnLCAnY291bnQnXS5pbmRleE9mKG9wZXJhdGlvbikgPiAtMVxuICAgICAgICA/ICdyZWFkVXNlckZpZWxkcydcbiAgICAgICAgOiAnd3JpdGVVc2VyRmllbGRzJztcblxuICAgIC8vIFJlamVjdCBjcmVhdGUgd2hlbiB3cml0ZSBsb2NrZG93blxuICAgIGlmIChwZXJtaXNzaW9uRmllbGQgPT0gJ3dyaXRlVXNlckZpZWxkcycgJiYgb3BlcmF0aW9uID09ICdjcmVhdGUnKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICAgIGBQZXJtaXNzaW9uIGRlbmllZCBmb3IgYWN0aW9uICR7b3BlcmF0aW9ufSBvbiBjbGFzcyAke2NsYXNzTmFtZX0uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBQcm9jZXNzIHRoZSByZWFkVXNlckZpZWxkcyBsYXRlclxuICAgIGlmIChcbiAgICAgIEFycmF5LmlzQXJyYXkoY2xhc3NQZXJtaXNzaW9uc1twZXJtaXNzaW9uRmllbGRdKSAmJlxuICAgICAgY2xhc3NQZXJtaXNzaW9uc1twZXJtaXNzaW9uRmllbGRdLmxlbmd0aCA+IDBcbiAgICApIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBjb25zdCBwb2ludGVyRmllbGRzID0gY2xhc3NQZXJtaXNzaW9uc1tvcGVyYXRpb25dLnBvaW50ZXJGaWVsZHM7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocG9pbnRlckZpZWxkcykgJiYgcG9pbnRlckZpZWxkcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBhbnkgb3AgZXhjZXB0ICdhZGRGaWVsZCBhcyBwYXJ0IG9mIGNyZWF0ZScgaXMgb2suXG4gICAgICBpZiAob3BlcmF0aW9uICE9PSAnYWRkRmllbGQnIHx8IGFjdGlvbiA9PT0gJ3VwZGF0ZScpIHtcbiAgICAgICAgLy8gV2UgY2FuIGFsbG93IGFkZGluZyBmaWVsZCBvbiB1cGRhdGUgZmxvdyBvbmx5LlxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTixcbiAgICAgIGBQZXJtaXNzaW9uIGRlbmllZCBmb3IgYWN0aW9uICR7b3BlcmF0aW9ufSBvbiBjbGFzcyAke2NsYXNzTmFtZX0uYFxuICAgICk7XG4gIH1cblxuICAvLyBWYWxpZGF0ZXMgYW4gb3BlcmF0aW9uIHBhc3NlcyBjbGFzcy1sZXZlbC1wZXJtaXNzaW9ucyBzZXQgaW4gdGhlIHNjaGVtYVxuICB2YWxpZGF0ZVBlcm1pc3Npb24oXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgYWNsR3JvdXA6IHN0cmluZ1tdLFxuICAgIG9wZXJhdGlvbjogc3RyaW5nLFxuICAgIGFjdGlvbj86IHN0cmluZ1xuICApIHtcbiAgICByZXR1cm4gU2NoZW1hQ29udHJvbGxlci52YWxpZGF0ZVBlcm1pc3Npb24oXG4gICAgICB0aGlzLmdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWUpLFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgYWNsR3JvdXAsXG4gICAgICBvcGVyYXRpb24sXG4gICAgICBhY3Rpb25cbiAgICApO1xuICB9XG5cbiAgZ2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKGNsYXNzTmFtZTogc3RyaW5nKTogYW55IHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV0gJiZcbiAgICAgIHRoaXMuc2NoZW1hRGF0YVtjbGFzc05hbWVdLmNsYXNzTGV2ZWxQZXJtaXNzaW9uc1xuICAgICk7XG4gIH1cblxuICAvLyBSZXR1cm5zIHRoZSBleHBlY3RlZCB0eXBlIGZvciBhIGNsYXNzTmFtZStrZXkgY29tYmluYXRpb25cbiAgLy8gb3IgdW5kZWZpbmVkIGlmIHRoZSBzY2hlbWEgaXMgbm90IHNldFxuICBnZXRFeHBlY3RlZFR5cGUoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZmllbGROYW1lOiBzdHJpbmdcbiAgKTogPyhTY2hlbWFGaWVsZCB8IHN0cmluZykge1xuICAgIGlmICh0aGlzLnNjaGVtYURhdGFbY2xhc3NOYW1lXSkge1xuICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gdGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV0uZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICByZXR1cm4gZXhwZWN0ZWRUeXBlID09PSAnbWFwJyA/ICdPYmplY3QnIDogZXhwZWN0ZWRUeXBlO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gQ2hlY2tzIGlmIGEgZ2l2ZW4gY2xhc3MgaXMgaW4gdGhlIHNjaGVtYS5cbiAgaGFzQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV0pIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJ1ZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnJlbG9hZERhdGEoKS50aGVuKCgpID0+ICEhdGhpcy5zY2hlbWFEYXRhW2NsYXNzTmFtZV0pO1xuICB9XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIG5ldyBTY2hlbWEuXG5jb25zdCBsb2FkID0gKFxuICBkYkFkYXB0ZXI6IFN0b3JhZ2VBZGFwdGVyLFxuICBzY2hlbWFDYWNoZTogYW55LFxuICBvcHRpb25zOiBhbnlcbik6IFByb21pc2U8U2NoZW1hQ29udHJvbGxlcj4gPT4ge1xuICBjb25zdCBzY2hlbWEgPSBuZXcgU2NoZW1hQ29udHJvbGxlcihkYkFkYXB0ZXIsIHNjaGVtYUNhY2hlKTtcbiAgcmV0dXJuIHNjaGVtYS5yZWxvYWREYXRhKG9wdGlvbnMpLnRoZW4oKCkgPT4gc2NoZW1hKTtcbn07XG5cbi8vIEJ1aWxkcyBhIG5ldyBzY2hlbWEgKGluIHNjaGVtYSBBUEkgcmVzcG9uc2UgZm9ybWF0KSBvdXQgb2YgYW5cbi8vIGV4aXN0aW5nIG1vbmdvIHNjaGVtYSArIGEgc2NoZW1hcyBBUEkgcHV0IHJlcXVlc3QuIFRoaXMgcmVzcG9uc2Vcbi8vIGRvZXMgbm90IGluY2x1ZGUgdGhlIGRlZmF1bHQgZmllbGRzLCBhcyBpdCBpcyBpbnRlbmRlZCB0byBiZSBwYXNzZWRcbi8vIHRvIG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZS4gTm8gdmFsaWRhdGlvbiBpcyBkb25lIGhlcmUsIGl0XG4vLyBpcyBkb25lIGluIG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZS5cbmZ1bmN0aW9uIGJ1aWxkTWVyZ2VkU2NoZW1hT2JqZWN0KFxuICBleGlzdGluZ0ZpZWxkczogU2NoZW1hRmllbGRzLFxuICBwdXRSZXF1ZXN0OiBhbnlcbik6IFNjaGVtYUZpZWxkcyB7XG4gIGNvbnN0IG5ld1NjaGVtYSA9IHt9O1xuICAvLyBAZmxvdy1kaXNhYmxlLW5leHRcbiAgY29uc3Qgc3lzU2NoZW1hRmllbGQgPVxuICAgIE9iamVjdC5rZXlzKGRlZmF1bHRDb2x1bW5zKS5pbmRleE9mKGV4aXN0aW5nRmllbGRzLl9pZCkgPT09IC0xXG4gICAgICA/IFtdXG4gICAgICA6IE9iamVjdC5rZXlzKGRlZmF1bHRDb2x1bW5zW2V4aXN0aW5nRmllbGRzLl9pZF0pO1xuICBmb3IgKGNvbnN0IG9sZEZpZWxkIGluIGV4aXN0aW5nRmllbGRzKSB7XG4gICAgaWYgKFxuICAgICAgb2xkRmllbGQgIT09ICdfaWQnICYmXG4gICAgICBvbGRGaWVsZCAhPT0gJ0FDTCcgJiZcbiAgICAgIG9sZEZpZWxkICE9PSAndXBkYXRlZEF0JyAmJlxuICAgICAgb2xkRmllbGQgIT09ICdjcmVhdGVkQXQnICYmXG4gICAgICBvbGRGaWVsZCAhPT0gJ29iamVjdElkJ1xuICAgICkge1xuICAgICAgaWYgKFxuICAgICAgICBzeXNTY2hlbWFGaWVsZC5sZW5ndGggPiAwICYmXG4gICAgICAgIHN5c1NjaGVtYUZpZWxkLmluZGV4T2Yob2xkRmllbGQpICE9PSAtMVxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZmllbGRJc0RlbGV0ZWQgPVxuICAgICAgICBwdXRSZXF1ZXN0W29sZEZpZWxkXSAmJiBwdXRSZXF1ZXN0W29sZEZpZWxkXS5fX29wID09PSAnRGVsZXRlJztcbiAgICAgIGlmICghZmllbGRJc0RlbGV0ZWQpIHtcbiAgICAgICAgbmV3U2NoZW1hW29sZEZpZWxkXSA9IGV4aXN0aW5nRmllbGRzW29sZEZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZm9yIChjb25zdCBuZXdGaWVsZCBpbiBwdXRSZXF1ZXN0KSB7XG4gICAgaWYgKG5ld0ZpZWxkICE9PSAnb2JqZWN0SWQnICYmIHB1dFJlcXVlc3RbbmV3RmllbGRdLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHN5c1NjaGVtYUZpZWxkLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgc3lzU2NoZW1hRmllbGQuaW5kZXhPZihuZXdGaWVsZCkgIT09IC0xXG4gICAgICApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBuZXdTY2hlbWFbbmV3RmllbGRdID0gcHV0UmVxdWVzdFtuZXdGaWVsZF07XG4gICAgfVxuICB9XG4gIHJldHVybiBuZXdTY2hlbWE7XG59XG5cbi8vIEdpdmVuIGEgc2NoZW1hIHByb21pc2UsIGNvbnN0cnVjdCBhbm90aGVyIHNjaGVtYSBwcm9taXNlIHRoYXRcbi8vIHZhbGlkYXRlcyB0aGlzIGZpZWxkIG9uY2UgdGhlIHNjaGVtYSBsb2Fkcy5cbmZ1bmN0aW9uIHRoZW5WYWxpZGF0ZVJlcXVpcmVkQ29sdW1ucyhzY2hlbWFQcm9taXNlLCBjbGFzc05hbWUsIG9iamVjdCwgcXVlcnkpIHtcbiAgcmV0dXJuIHNjaGVtYVByb21pc2UudGhlbihzY2hlbWEgPT4ge1xuICAgIHJldHVybiBzY2hlbWEudmFsaWRhdGVSZXF1aXJlZENvbHVtbnMoY2xhc3NOYW1lLCBvYmplY3QsIHF1ZXJ5KTtcbiAgfSk7XG59XG5cbi8vIEdldHMgdGhlIHR5cGUgZnJvbSBhIFJFU1QgQVBJIGZvcm1hdHRlZCBvYmplY3QsIHdoZXJlICd0eXBlJyBpc1xuLy8gZXh0ZW5kZWQgcGFzdCBqYXZhc2NyaXB0IHR5cGVzIHRvIGluY2x1ZGUgdGhlIHJlc3Qgb2YgdGhlIFBhcnNlXG4vLyB0eXBlIHN5c3RlbS5cbi8vIFRoZSBvdXRwdXQgc2hvdWxkIGJlIGEgdmFsaWQgc2NoZW1hIHZhbHVlLlxuLy8gVE9ETzogZW5zdXJlIHRoYXQgdGhpcyBpcyBjb21wYXRpYmxlIHdpdGggdGhlIGZvcm1hdCB1c2VkIGluIE9wZW4gREJcbmZ1bmN0aW9uIGdldFR5cGUob2JqOiBhbnkpOiA/KFNjaGVtYUZpZWxkIHwgc3RyaW5nKSB7XG4gIGNvbnN0IHR5cGUgPSB0eXBlb2Ygb2JqO1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdib29sZWFuJzpcbiAgICAgIHJldHVybiAnQm9vbGVhbic7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHJldHVybiAnU3RyaW5nJztcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgcmV0dXJuICdOdW1iZXInO1xuICAgIGNhc2UgJ21hcCc6XG4gICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgIGlmICghb2JqKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gZ2V0T2JqZWN0VHlwZShvYmopO1xuICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICBjYXNlICdzeW1ib2wnOlxuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93ICdiYWQgb2JqOiAnICsgb2JqO1xuICB9XG59XG5cbi8vIFRoaXMgZ2V0cyB0aGUgdHlwZSBmb3Igbm9uLUpTT04gdHlwZXMgbGlrZSBwb2ludGVycyBhbmQgZmlsZXMsIGJ1dFxuLy8gYWxzbyBnZXRzIHRoZSBhcHByb3ByaWF0ZSB0eXBlIGZvciAkIG9wZXJhdG9ycy5cbi8vIFJldHVybnMgbnVsbCBpZiB0aGUgdHlwZSBpcyB1bmtub3duLlxuZnVuY3Rpb24gZ2V0T2JqZWN0VHlwZShvYmopOiA/KFNjaGVtYUZpZWxkIHwgc3RyaW5nKSB7XG4gIGlmIChvYmogaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHJldHVybiAnQXJyYXknO1xuICB9XG4gIGlmIChvYmouX190eXBlKSB7XG4gICAgc3dpdGNoIChvYmouX190eXBlKSB7XG4gICAgICBjYXNlICdQb2ludGVyJzpcbiAgICAgICAgaWYgKG9iai5jbGFzc05hbWUpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgICAgdGFyZ2V0Q2xhc3M6IG9iai5jbGFzc05hbWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1JlbGF0aW9uJzpcbiAgICAgICAgaWYgKG9iai5jbGFzc05hbWUpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdHlwZTogJ1JlbGF0aW9uJyxcbiAgICAgICAgICAgIHRhcmdldENsYXNzOiBvYmouY2xhc3NOYW1lLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdGaWxlJzpcbiAgICAgICAgaWYgKG9iai5uYW1lKSB7XG4gICAgICAgICAgcmV0dXJuICdGaWxlJztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgICBpZiAob2JqLmlzbykge1xuICAgICAgICAgIHJldHVybiAnRGF0ZSc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdHZW9Qb2ludCc6XG4gICAgICAgIGlmIChvYmoubGF0aXR1ZGUgIT0gbnVsbCAmJiBvYmoubG9uZ2l0dWRlICE9IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gJ0dlb1BvaW50JztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgICAgaWYgKG9iai5iYXNlNjQpIHtcbiAgICAgICAgICByZXR1cm4gJ0J5dGVzJztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1BvbHlnb24nOlxuICAgICAgICBpZiAob2JqLmNvb3JkaW5hdGVzKSB7XG4gICAgICAgICAgcmV0dXJuICdQb2x5Z29uJztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAnVGhpcyBpcyBub3QgYSB2YWxpZCAnICsgb2JqLl9fdHlwZVxuICAgICk7XG4gIH1cbiAgaWYgKG9ialsnJG5lJ10pIHtcbiAgICByZXR1cm4gZ2V0T2JqZWN0VHlwZShvYmpbJyRuZSddKTtcbiAgfVxuICBpZiAob2JqLl9fb3ApIHtcbiAgICBzd2l0Y2ggKG9iai5fX29wKSB7XG4gICAgICBjYXNlICdJbmNyZW1lbnQnOlxuICAgICAgICByZXR1cm4gJ051bWJlcic7XG4gICAgICBjYXNlICdEZWxldGUnOlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGNhc2UgJ0FkZCc6XG4gICAgICBjYXNlICdBZGRVbmlxdWUnOlxuICAgICAgY2FzZSAnUmVtb3ZlJzpcbiAgICAgICAgcmV0dXJuICdBcnJheSc7XG4gICAgICBjYXNlICdBZGRSZWxhdGlvbic6XG4gICAgICBjYXNlICdSZW1vdmVSZWxhdGlvbic6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogJ1JlbGF0aW9uJyxcbiAgICAgICAgICB0YXJnZXRDbGFzczogb2JqLm9iamVjdHNbMF0uY2xhc3NOYW1lLFxuICAgICAgICB9O1xuICAgICAgY2FzZSAnQmF0Y2gnOlxuICAgICAgICByZXR1cm4gZ2V0T2JqZWN0VHlwZShvYmoub3BzWzBdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93ICd1bmV4cGVjdGVkIG9wOiAnICsgb2JqLl9fb3A7XG4gICAgfVxuICB9XG4gIHJldHVybiAnT2JqZWN0Jztcbn1cblxuZXhwb3J0IHtcbiAgbG9hZCxcbiAgY2xhc3NOYW1lSXNWYWxpZCxcbiAgZmllbGROYW1lSXNWYWxpZCxcbiAgaW52YWxpZENsYXNzTmFtZU1lc3NhZ2UsXG4gIGJ1aWxkTWVyZ2VkU2NoZW1hT2JqZWN0LFxuICBzeXN0ZW1DbGFzc2VzLFxuICBkZWZhdWx0Q29sdW1ucyxcbiAgY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYSxcbiAgVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyxcbiAgU2NoZW1hQ29udHJvbGxlcixcbn07XG4iXX0= \ 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..e316af75cc --- /dev/null +++ b/lib/Controllers/index.js @@ -0,0 +1,311 @@ +"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, + maxLogFiles, + silent, + loggerAdapter + } = options; + const loggerOptions = { + jsonLogs, + logsFolder, + verbose, + logLevel, + silent, + maxLogFiles + }; + 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, + 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)); +} + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9pbmRleC5qcyJdLCJuYW1lcyI6WyJnZXRDb250cm9sbGVycyIsIm9wdGlvbnMiLCJsb2dnZXJDb250cm9sbGVyIiwiZ2V0TG9nZ2VyQ29udHJvbGxlciIsImZpbGVzQ29udHJvbGxlciIsImdldEZpbGVzQ29udHJvbGxlciIsInVzZXJDb250cm9sbGVyIiwiZ2V0VXNlckNvbnRyb2xsZXIiLCJwdXNoQ29udHJvbGxlciIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0IiwiaGFzUHVzaFN1cHBvcnQiLCJwdXNoQ29udHJvbGxlclF1ZXVlIiwicHVzaFdvcmtlciIsImdldFB1c2hDb250cm9sbGVyIiwiY2FjaGVDb250cm9sbGVyIiwiZ2V0Q2FjaGVDb250cm9sbGVyIiwiYW5hbHl0aWNzQ29udHJvbGxlciIsImdldEFuYWx5dGljc0NvbnRyb2xsZXIiLCJsaXZlUXVlcnlDb250cm9sbGVyIiwiZ2V0TGl2ZVF1ZXJ5Q29udHJvbGxlciIsImRhdGFiYXNlQ29udHJvbGxlciIsImdldERhdGFiYXNlQ29udHJvbGxlciIsImhvb2tzQ29udHJvbGxlciIsImdldEhvb2tzQ29udHJvbGxlciIsImF1dGhEYXRhTWFuYWdlciIsImdldEF1dGhEYXRhTWFuYWdlciIsInBhcnNlR3JhcGhRTENvbnRyb2xsZXIiLCJnZXRQYXJzZUdyYXBoUUxDb250cm9sbGVyIiwiYXBwSWQiLCJqc29uTG9ncyIsImxvZ3NGb2xkZXIiLCJ2ZXJib3NlIiwibG9nTGV2ZWwiLCJtYXhMb2dGaWxlcyIsInNpbGVudCIsImxvZ2dlckFkYXB0ZXIiLCJsb2dnZXJPcHRpb25zIiwibG9nZ2VyQ29udHJvbGxlckFkYXB0ZXIiLCJXaW5zdG9uTG9nZ2VyQWRhcHRlciIsIkxvZ2dlckNvbnRyb2xsZXIiLCJkYXRhYmFzZVVSSSIsImZpbGVzQWRhcHRlciIsImRhdGFiYXNlQWRhcHRlciIsInByZXNlcnZlRmlsZU5hbWUiLCJmaWxlc0NvbnRyb2xsZXJBZGFwdGVyIiwiR3JpZEZTQnVja2V0QWRhcHRlciIsIkZpbGVzQ29udHJvbGxlciIsImVtYWlsQWRhcHRlciIsInZlcmlmeVVzZXJFbWFpbHMiLCJlbWFpbENvbnRyb2xsZXJBZGFwdGVyIiwiVXNlckNvbnRyb2xsZXIiLCJjYWNoZUFkYXB0ZXIiLCJjYWNoZVRUTCIsImNhY2hlTWF4U2l6ZSIsImNhY2hlQ29udHJvbGxlckFkYXB0ZXIiLCJJbk1lbW9yeUNhY2hlQWRhcHRlciIsInR0bCIsIm1heFNpemUiLCJDYWNoZUNvbnRyb2xsZXIiLCJjb250cm9sbGVyRGVwcyIsIlBhcnNlR3JhcGhRTENvbnRyb2xsZXIiLCJtb3VudEdyYXBoUUwiLCJhbmFseXRpY3NBZGFwdGVyIiwiYW5hbHl0aWNzQ29udHJvbGxlckFkYXB0ZXIiLCJBbmFseXRpY3NBZGFwdGVyIiwiQW5hbHl0aWNzQ29udHJvbGxlciIsIkxpdmVRdWVyeUNvbnRyb2xsZXIiLCJsaXZlUXVlcnkiLCJkYXRhYmFzZU9wdGlvbnMiLCJjb2xsZWN0aW9uUHJlZml4Iiwic2NoZW1hQ2FjaGVUVEwiLCJlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSIsImRlZmF1bHRzIiwiZ2V0RGF0YWJhc2VBZGFwdGVyIiwiRGF0YWJhc2VDb250cm9sbGVyIiwiU2NoZW1hQ2FjaGUiLCJ3ZWJob29rS2V5IiwiSG9va3NDb250cm9sbGVyIiwic2NoZWR1bGVkUHVzaCIsInB1c2giLCJwdXNoT3B0aW9ucyIsIk9iamVjdCIsImFzc2lnbiIsInB1c2hRdWV1ZU9wdGlvbnMiLCJxdWV1ZU9wdGlvbnMiLCJwdXNoQWRhcHRlciIsImFkYXB0ZXIiLCJQYXJzZVB1c2hBZGFwdGVyIiwiUHVzaENvbnRyb2xsZXIiLCJkaXNhYmxlUHVzaFdvcmtlciIsIlB1c2hRdWV1ZSIsIlB1c2hXb3JrZXIiLCJhdXRoIiwiZW5hYmxlQW5vbnltb3VzVXNlcnMiLCJwcm90b2NvbCIsInBhcnNlZFVSSSIsInVybCIsInBhcnNlIiwidG9Mb3dlckNhc2UiLCJlIiwiUG9zdGdyZXNTdG9yYWdlQWRhcHRl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QUNFLGFBQU8sSUFBSWtDLDRCQUFKLENBQXdCO0FBQzdCRCxRQUFBQSxHQUFHLEVBQUU3RCxXQUR3QjtBQUU3QjZCLFFBQUFBLGdCQUY2QjtBQUc3QmtDLFFBQUFBLFlBQVksRUFBRW5DO0FBSGUsT0FBeEIsQ0FBUDtBQVJKO0FBY0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXV0aERhdGFNYW5hZ2VyIGZyb20gJy4uL0FkYXB0ZXJzL0F1dGgnO1xuaW1wb3J0IHsgUGFyc2VTZXJ2ZXJPcHRpb25zIH0gZnJvbSAnLi4vT3B0aW9ucyc7XG5pbXBvcnQgeyBsb2FkQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0FkYXB0ZXJMb2FkZXInO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4uL2RlZmF1bHRzJztcbmltcG9ydCB1cmwgZnJvbSAndXJsJztcbi8vIENvbnRyb2xsZXJzXG5pbXBvcnQgeyBMb2dnZXJDb250cm9sbGVyIH0gZnJvbSAnLi9Mb2dnZXJDb250cm9sbGVyJztcbmltcG9ydCB7IEZpbGVzQ29udHJvbGxlciB9IGZyb20gJy4vRmlsZXNDb250cm9sbGVyJztcbmltcG9ydCB7IEhvb2tzQ29udHJvbGxlciB9IGZyb20gJy4vSG9va3NDb250cm9sbGVyJztcbmltcG9ydCB7IFVzZXJDb250cm9sbGVyIH0gZnJvbSAnLi9Vc2VyQ29udHJvbGxlcic7XG5pbXBvcnQgeyBDYWNoZUNvbnRyb2xsZXIgfSBmcm9tICcuL0NhY2hlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBMaXZlUXVlcnlDb250cm9sbGVyIH0gZnJvbSAnLi9MaXZlUXVlcnlDb250cm9sbGVyJztcbmltcG9ydCB7IEFuYWx5dGljc0NvbnRyb2xsZXIgfSBmcm9tICcuL0FuYWx5dGljc0NvbnRyb2xsZXInO1xuaW1wb3J0IHsgUHVzaENvbnRyb2xsZXIgfSBmcm9tICcuL1B1c2hDb250cm9sbGVyJztcbmltcG9ydCB7IFB1c2hRdWV1ZSB9IGZyb20gJy4uL1B1c2gvUHVzaFF1ZXVlJztcbmltcG9ydCB7IFB1c2hXb3JrZXIgfSBmcm9tICcuLi9QdXNoL1B1c2hXb3JrZXInO1xuaW1wb3J0IERhdGFiYXNlQ29udHJvbGxlciBmcm9tICcuL0RhdGFiYXNlQ29udHJvbGxlcic7XG5pbXBvcnQgU2NoZW1hQ2FjaGUgZnJvbSAnLi9TY2hlbWFDYWNoZSc7XG5cbi8vIEFkYXB0ZXJzXG5pbXBvcnQgeyBHcmlkRlNCdWNrZXRBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvRmlsZXMvR3JpZEZTQnVja2V0QWRhcHRlcic7XG5pbXBvcnQgeyBXaW5zdG9uTG9nZ2VyQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0xvZ2dlci9XaW5zdG9uTG9nZ2VyQWRhcHRlcic7XG5pbXBvcnQgeyBJbk1lbW9yeUNhY2hlQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0NhY2hlL0luTWVtb3J5Q2FjaGVBZGFwdGVyJztcbmltcG9ydCB7IEFuYWx5dGljc0FkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9BbmFseXRpY3MvQW5hbHl0aWNzQWRhcHRlcic7XG5pbXBvcnQgTW9uZ29TdG9yYWdlQWRhcHRlciBmcm9tICcuLi9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IFBvc3RncmVzU3RvcmFnZUFkYXB0ZXIgZnJvbSAnLi4vQWRhcHRlcnMvU3RvcmFnZS9Qb3N0Z3Jlcy9Qb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCBQYXJzZVB1c2hBZGFwdGVyIGZyb20gJ0BwYXJzZS9wdXNoLWFkYXB0ZXInO1xuaW1wb3J0IFBhcnNlR3JhcGhRTENvbnRyb2xsZXIgZnJvbSAnLi9QYXJzZUdyYXBoUUxDb250cm9sbGVyJztcblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbnRyb2xsZXJzKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICBjb25zdCBsb2dnZXJDb250cm9sbGVyID0gZ2V0TG9nZ2VyQ29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3QgZmlsZXNDb250cm9sbGVyID0gZ2V0RmlsZXNDb250cm9sbGVyKG9wdGlvbnMpO1xuICBjb25zdCB1c2VyQ29udHJvbGxlciA9IGdldFVzZXJDb250cm9sbGVyKG9wdGlvbnMpO1xuICBjb25zdCB7XG4gICAgcHVzaENvbnRyb2xsZXIsXG4gICAgaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQsXG4gICAgaGFzUHVzaFN1cHBvcnQsXG4gICAgcHVzaENvbnRyb2xsZXJRdWV1ZSxcbiAgICBwdXNoV29ya2VyLFxuICB9ID0gZ2V0UHVzaENvbnRyb2xsZXIob3B0aW9ucyk7XG4gIGNvbnN0IGNhY2hlQ29udHJvbGxlciA9IGdldENhY2hlQ29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3QgYW5hbHl0aWNzQ29udHJvbGxlciA9IGdldEFuYWx5dGljc0NvbnRyb2xsZXIob3B0aW9ucyk7XG4gIGNvbnN0IGxpdmVRdWVyeUNvbnRyb2xsZXIgPSBnZXRMaXZlUXVlcnlDb250cm9sbGVyKG9wdGlvbnMpO1xuICBjb25zdCBkYXRhYmFzZUNvbnRyb2xsZXIgPSBnZXREYXRhYmFzZUNvbnRyb2xsZXIob3B0aW9ucywgY2FjaGVDb250cm9sbGVyKTtcbiAgY29uc3QgaG9va3NDb250cm9sbGVyID0gZ2V0SG9va3NDb250cm9sbGVyKG9wdGlvbnMsIGRhdGFiYXNlQ29udHJvbGxlcik7XG4gIGNvbnN0IGF1dGhEYXRhTWFuYWdlciA9IGdldEF1dGhEYXRhTWFuYWdlcihvcHRpb25zKTtcbiAgY29uc3QgcGFyc2VHcmFwaFFMQ29udHJvbGxlciA9IGdldFBhcnNlR3JhcGhRTENvbnRyb2xsZXIob3B0aW9ucywge1xuICAgIGRhdGFiYXNlQ29udHJvbGxlcixcbiAgICBjYWNoZUNvbnRyb2xsZXIsXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIGxvZ2dlckNvbnRyb2xsZXIsXG4gICAgZmlsZXNDb250cm9sbGVyLFxuICAgIHVzZXJDb250cm9sbGVyLFxuICAgIHB1c2hDb250cm9sbGVyLFxuICAgIGhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0LFxuICAgIGhhc1B1c2hTdXBwb3J0LFxuICAgIHB1c2hXb3JrZXIsXG4gICAgcHVzaENvbnRyb2xsZXJRdWV1ZSxcbiAgICBhbmFseXRpY3NDb250cm9sbGVyLFxuICAgIGNhY2hlQ29udHJvbGxlcixcbiAgICBwYXJzZUdyYXBoUUxDb250cm9sbGVyLFxuICAgIGxpdmVRdWVyeUNvbnRyb2xsZXIsXG4gICAgZGF0YWJhc2VDb250cm9sbGVyLFxuICAgIGhvb2tzQ29udHJvbGxlcixcbiAgICBhdXRoRGF0YU1hbmFnZXIsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2dnZXJDb250cm9sbGVyKFxuICBvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnNcbik6IExvZ2dlckNvbnRyb2xsZXIge1xuICBjb25zdCB7XG4gICAgYXBwSWQsXG4gICAganNvbkxvZ3MsXG4gICAgbG9nc0ZvbGRlcixcbiAgICB2ZXJib3NlLFxuICAgIGxvZ0xldmVsLFxuICAgIG1heExvZ0ZpbGVzLFxuICAgIHNpbGVudCxcbiAgICBsb2dnZXJBZGFwdGVyLFxuICB9ID0gb3B0aW9ucztcbiAgY29uc3QgbG9nZ2VyT3B0aW9ucyA9IHtcbiAgICBqc29uTG9ncyxcbiAgICBsb2dzRm9sZGVyLFxuICAgIHZlcmJvc2UsXG4gICAgbG9nTGV2ZWwsXG4gICAgc2lsZW50LFxuICAgIG1heExvZ0ZpbGVzLFxuICB9O1xuICBjb25zdCBsb2dnZXJDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKFxuICAgIGxvZ2dlckFkYXB0ZXIsXG4gICAgV2luc3RvbkxvZ2dlckFkYXB0ZXIsXG4gICAgbG9nZ2VyT3B0aW9uc1xuICApO1xuICByZXR1cm4gbmV3IExvZ2dlckNvbnRyb2xsZXIobG9nZ2VyQ29udHJvbGxlckFkYXB0ZXIsIGFwcElkLCBsb2dnZXJPcHRpb25zKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZpbGVzQ29udHJvbGxlcihcbiAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zXG4pOiBGaWxlc0NvbnRyb2xsZXIge1xuICBjb25zdCB7XG4gICAgYXBwSWQsXG4gICAgZGF0YWJhc2VVUkksXG4gICAgZmlsZXNBZGFwdGVyLFxuICAgIGRhdGFiYXNlQWRhcHRlcixcbiAgICBwcmVzZXJ2ZUZpbGVOYW1lLFxuICB9ID0gb3B0aW9ucztcbiAgaWYgKCFmaWxlc0FkYXB0ZXIgJiYgZGF0YWJhc2VBZGFwdGVyKSB7XG4gICAgdGhyb3cgJ1doZW4gdXNpbmcgYW4gZXhwbGljaXQgZGF0YWJhc2UgYWRhcHRlciwgeW91IG11c3QgYWxzbyB1c2UgYW4gZXhwbGljaXQgZmlsZXNBZGFwdGVyLic7XG4gIH1cbiAgY29uc3QgZmlsZXNDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKGZpbGVzQWRhcHRlciwgKCkgPT4ge1xuICAgIHJldHVybiBuZXcgR3JpZEZTQnVja2V0QWRhcHRlcihkYXRhYmFzZVVSSSk7XG4gIH0pO1xuICByZXR1cm4gbmV3IEZpbGVzQ29udHJvbGxlcihmaWxlc0NvbnRyb2xsZXJBZGFwdGVyLCBhcHBJZCwge1xuICAgIHByZXNlcnZlRmlsZU5hbWUsXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VXNlckNvbnRyb2xsZXIob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKTogVXNlckNvbnRyb2xsZXIge1xuICBjb25zdCB7IGFwcElkLCBlbWFpbEFkYXB0ZXIsIHZlcmlmeVVzZXJFbWFpbHMgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGVtYWlsQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihlbWFpbEFkYXB0ZXIpO1xuICByZXR1cm4gbmV3IFVzZXJDb250cm9sbGVyKGVtYWlsQ29udHJvbGxlckFkYXB0ZXIsIGFwcElkLCB7XG4gICAgdmVyaWZ5VXNlckVtYWlscyxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDYWNoZUNvbnRyb2xsZXIoXG4gIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9uc1xuKTogQ2FjaGVDb250cm9sbGVyIHtcbiAgY29uc3QgeyBhcHBJZCwgY2FjaGVBZGFwdGVyLCBjYWNoZVRUTCwgY2FjaGVNYXhTaXplIH0gPSBvcHRpb25zO1xuICBjb25zdCBjYWNoZUNvbnRyb2xsZXJBZGFwdGVyID0gbG9hZEFkYXB0ZXIoXG4gICAgY2FjaGVBZGFwdGVyLFxuICAgIEluTWVtb3J5Q2FjaGVBZGFwdGVyLFxuICAgIHsgYXBwSWQ6IGFwcElkLCB0dGw6IGNhY2hlVFRMLCBtYXhTaXplOiBjYWNoZU1heFNpemUgfVxuICApO1xuICByZXR1cm4gbmV3IENhY2hlQ29udHJvbGxlcihjYWNoZUNvbnRyb2xsZXJBZGFwdGVyLCBhcHBJZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXJzZUdyYXBoUUxDb250cm9sbGVyKFxuICBvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMsXG4gIGNvbnRyb2xsZXJEZXBzXG4pOiBQYXJzZUdyYXBoUUxDb250cm9sbGVyIHtcbiAgcmV0dXJuIG5ldyBQYXJzZUdyYXBoUUxDb250cm9sbGVyKHtcbiAgICBtb3VudEdyYXBoUUw6IG9wdGlvbnMubW91bnRHcmFwaFFMLFxuICAgIC4uLmNvbnRyb2xsZXJEZXBzLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFuYWx5dGljc0NvbnRyb2xsZXIoXG4gIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9uc1xuKTogQW5hbHl0aWNzQ29udHJvbGxlciB7XG4gIGNvbnN0IHsgYW5hbHl0aWNzQWRhcHRlciB9ID0gb3B0aW9ucztcbiAgY29uc3QgYW5hbHl0aWNzQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihcbiAgICBhbmFseXRpY3NBZGFwdGVyLFxuICAgIEFuYWx5dGljc0FkYXB0ZXJcbiAgKTtcbiAgcmV0dXJuIG5ldyBBbmFseXRpY3NDb250cm9sbGVyKGFuYWx5dGljc0NvbnRyb2xsZXJBZGFwdGVyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExpdmVRdWVyeUNvbnRyb2xsZXIoXG4gIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9uc1xuKTogTGl2ZVF1ZXJ5Q29udHJvbGxlciB7XG4gIHJldHVybiBuZXcgTGl2ZVF1ZXJ5Q29udHJvbGxlcihvcHRpb25zLmxpdmVRdWVyeSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhYmFzZUNvbnRyb2xsZXIoXG4gIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucyxcbiAgY2FjaGVDb250cm9sbGVyOiBDYWNoZUNvbnRyb2xsZXJcbik6IERhdGFiYXNlQ29udHJvbGxlciB7XG4gIGNvbnN0IHtcbiAgICBkYXRhYmFzZVVSSSxcbiAgICBkYXRhYmFzZU9wdGlvbnMsXG4gICAgY29sbGVjdGlvblByZWZpeCxcbiAgICBzY2hlbWFDYWNoZVRUTCxcbiAgICBlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSxcbiAgfSA9IG9wdGlvbnM7XG4gIGxldCB7IGRhdGFiYXNlQWRhcHRlciB9ID0gb3B0aW9ucztcbiAgaWYgKFxuICAgIChkYXRhYmFzZU9wdGlvbnMgfHxcbiAgICAgIChkYXRhYmFzZVVSSSAmJiBkYXRhYmFzZVVSSSAhPT0gZGVmYXVsdHMuZGF0YWJhc2VVUkkpIHx8XG4gICAgICBjb2xsZWN0aW9uUHJlZml4ICE9PSBkZWZhdWx0cy5jb2xsZWN0aW9uUHJlZml4KSAmJlxuICAgIGRhdGFiYXNlQWRhcHRlclxuICApIHtcbiAgICB0aHJvdyAnWW91IGNhbm5vdCBzcGVjaWZ5IGJvdGggYSBkYXRhYmFzZUFkYXB0ZXIgYW5kIGEgZGF0YWJhc2VVUkkvZGF0YWJhc2VPcHRpb25zL2NvbGxlY3Rpb25QcmVmaXguJztcbiAgfSBlbHNlIGlmICghZGF0YWJhc2VBZGFwdGVyKSB7XG4gICAgZGF0YWJhc2VBZGFwdGVyID0gZ2V0RGF0YWJhc2VBZGFwdGVyKFxuICAgICAgZGF0YWJhc2VVUkksXG4gICAgICBjb2xsZWN0aW9uUHJlZml4LFxuICAgICAgZGF0YWJhc2VPcHRpb25zXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICBkYXRhYmFzZUFkYXB0ZXIgPSBsb2FkQWRhcHRlcihkYXRhYmFzZUFkYXB0ZXIpO1xuICB9XG4gIHJldHVybiBuZXcgRGF0YWJhc2VDb250cm9sbGVyKFxuICAgIGRhdGFiYXNlQWRhcHRlcixcbiAgICBuZXcgU2NoZW1hQ2FjaGUoY2FjaGVDb250cm9sbGVyLCBzY2hlbWFDYWNoZVRUTCwgZW5hYmxlU2luZ2xlU2NoZW1hQ2FjaGUpXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRIb29rc0NvbnRyb2xsZXIoXG4gIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucyxcbiAgZGF0YWJhc2VDb250cm9sbGVyOiBEYXRhYmFzZUNvbnRyb2xsZXJcbik6IEhvb2tzQ29udHJvbGxlciB7XG4gIGNvbnN0IHsgYXBwSWQsIHdlYmhvb2tLZXkgfSA9IG9wdGlvbnM7XG4gIHJldHVybiBuZXcgSG9va3NDb250cm9sbGVyKGFwcElkLCBkYXRhYmFzZUNvbnRyb2xsZXIsIHdlYmhvb2tLZXkpO1xufVxuXG5pbnRlcmZhY2UgUHVzaENvbnRyb2xsaW5nIHtcbiAgcHVzaENvbnRyb2xsZXI6IFB1c2hDb250cm9sbGVyO1xuICBoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydDogYm9vbGVhbjtcbiAgcHVzaENvbnRyb2xsZXJRdWV1ZTogUHVzaFF1ZXVlO1xuICBwdXNoV29ya2VyOiBQdXNoV29ya2VyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHVzaENvbnRyb2xsZXIoXG4gIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9uc1xuKTogUHVzaENvbnRyb2xsaW5nIHtcbiAgY29uc3QgeyBzY2hlZHVsZWRQdXNoLCBwdXNoIH0gPSBvcHRpb25zO1xuXG4gIGNvbnN0IHB1c2hPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgcHVzaCk7XG4gIGNvbnN0IHB1c2hRdWV1ZU9wdGlvbnMgPSBwdXNoT3B0aW9ucy5xdWV1ZU9wdGlvbnMgfHwge307XG4gIGlmIChwdXNoT3B0aW9ucy5xdWV1ZU9wdGlvbnMpIHtcbiAgICBkZWxldGUgcHVzaE9wdGlvbnMucXVldWVPcHRpb25zO1xuICB9XG5cbiAgLy8gUGFzcyB0aGUgcHVzaCBvcHRpb25zIHRvbyBhcyBpdCB3b3JrcyB3aXRoIHRoZSBkZWZhdWx0XG4gIGNvbnN0IHB1c2hBZGFwdGVyID0gbG9hZEFkYXB0ZXIoXG4gICAgcHVzaE9wdGlvbnMgJiYgcHVzaE9wdGlvbnMuYWRhcHRlcixcbiAgICBQYXJzZVB1c2hBZGFwdGVyLFxuICAgIHB1c2hPcHRpb25zXG4gICk7XG4gIC8vIFdlIHBhc3MgdGhlIG9wdGlvbnMgYW5kIHRoZSBiYXNlIGNsYXNzIGZvciB0aGUgYWRhdHBlcixcbiAgLy8gTm90ZSB0aGF0IHBhc3NpbmcgYW4gaW5zdGFuY2Ugd291bGQgd29yayB0b29cbiAgY29uc3QgcHVzaENvbnRyb2xsZXIgPSBuZXcgUHVzaENvbnRyb2xsZXIoKTtcbiAgY29uc3QgaGFzUHVzaFN1cHBvcnQgPSAhIShwdXNoQWRhcHRlciAmJiBwdXNoKTtcbiAgY29uc3QgaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQgPSBoYXNQdXNoU3VwcG9ydCAmJiBzY2hlZHVsZWRQdXNoID09PSB0cnVlO1xuXG4gIGNvbnN0IHsgZGlzYWJsZVB1c2hXb3JrZXIgfSA9IHB1c2hRdWV1ZU9wdGlvbnM7XG5cbiAgY29uc3QgcHVzaENvbnRyb2xsZXJRdWV1ZSA9IG5ldyBQdXNoUXVldWUocHVzaFF1ZXVlT3B0aW9ucyk7XG4gIGxldCBwdXNoV29ya2VyO1xuICBpZiAoIWRpc2FibGVQdXNoV29ya2VyKSB7XG4gICAgcHVzaFdvcmtlciA9IG5ldyBQdXNoV29ya2VyKHB1c2hBZGFwdGVyLCBwdXNoUXVldWVPcHRpb25zKTtcbiAgfVxuICByZXR1cm4ge1xuICAgIHB1c2hDb250cm9sbGVyLFxuICAgIGhhc1B1c2hTdXBwb3J0LFxuICAgIGhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0LFxuICAgIHB1c2hDb250cm9sbGVyUXVldWUsXG4gICAgcHVzaFdvcmtlcixcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEF1dGhEYXRhTWFuYWdlcihvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgY29uc3QgeyBhdXRoLCBlbmFibGVBbm9ueW1vdXNVc2VycyB9ID0gb3B0aW9ucztcbiAgcmV0dXJuIGF1dGhEYXRhTWFuYWdlcihhdXRoLCBlbmFibGVBbm9ueW1vdXNVc2Vycyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhYmFzZUFkYXB0ZXIoXG4gIGRhdGFiYXNlVVJJLFxuICBjb2xsZWN0aW9uUHJlZml4LFxuICBkYXRhYmFzZU9wdGlvbnNcbikge1xuICBsZXQgcHJvdG9jb2w7XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkVVJJID0gdXJsLnBhcnNlKGRhdGFiYXNlVVJJKTtcbiAgICBwcm90b2NvbCA9IHBhcnNlZFVSSS5wcm90b2NvbCA/IHBhcnNlZFVSSS5wcm90b2NvbC50b0xvd2VyQ2FzZSgpIDogbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8qICovXG4gIH1cbiAgc3dpdGNoIChwcm90b2NvbCkge1xuICAgIGNhc2UgJ3Bvc3RncmVzOic6XG4gICAgICByZXR1cm4gbmV3IFBvc3RncmVzU3RvcmFnZUFkYXB0ZXIoe1xuICAgICAgICB1cmk6IGRhdGFiYXNlVVJJLFxuICAgICAgICBjb2xsZWN0aW9uUHJlZml4LFxuICAgICAgICBkYXRhYmFzZU9wdGlvbnMsXG4gICAgICB9KTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIG5ldyBNb25nb1N0b3JhZ2VBZGFwdGVyKHtcbiAgICAgICAgdXJpOiBkYXRhYmFzZVVSSSxcbiAgICAgICAgY29sbGVjdGlvblByZWZpeCxcbiAgICAgICAgbW9uZ29PcHRpb25zOiBkYXRhYmFzZU9wdGlvbnMsXG4gICAgICB9KTtcbiAgfVxufVxuIl19 \ 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/GraphQL/ParseGraphQLSchema.js b/lib/GraphQL/ParseGraphQLSchema.js new file mode 100644 index 0000000000..0b63c15147 --- /dev/null +++ b/lib/GraphQL/ParseGraphQLSchema.js @@ -0,0 +1,415 @@ +"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"); + +var defaultRelaySchema = _interopRequireWildcard(require("./loaders/defaultRelaySchema")); + +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 RESERVED_GRAPHQL_TYPE_NAMES = ['String', 'Boolean', 'Int', 'Float', 'ID', 'ArrayResult', 'Query', 'Mutation', 'Subscription', 'CreateFileInput', 'CreateFilePayload', 'Viewer', 'SignUpInput', 'SignUpPayload', 'LogInInput', 'LogInPayload', 'LogOutInput', 'LogOutPayload', 'CloudCodeFunction', 'CallCloudCodeInput', 'CallCloudCodePayload', 'CreateClassInput', 'CreateClassPayload', 'UpdateClassInput', 'UpdateClassPayload', 'DeleteClassInput', 'DeleteClassPayload', 'PageInfo']; +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 = {}; + this.relayNodeInterface = null; + defaultGraphQLTypes.load(this); + defaultRelaySchema.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); + + if (typeof this.graphQLCustomTypeDefs.getTypeMap === 'function') { + const customGraphQLSchemaTypeMap = this.graphQLCustomTypeDefs.getTypeMap(); + Object.values(customGraphQLSchemaTypeMap).forEach(customGraphQLSchemaType => { + if (!customGraphQLSchemaType || !customGraphQLSchemaType.name || customGraphQLSchemaType.name.startsWith('__')) { + return; + } + + const autoGraphQLSchemaType = this.graphQLAutoSchema.getType(customGraphQLSchemaType.name); + + if (autoGraphQLSchemaType) { + autoGraphQLSchemaType._fields = _objectSpread({}, autoGraphQLSchemaType._fields, {}, customGraphQLSchemaType._fields); + } + }); + this.graphQLSchema = (0, _graphqlTools.mergeSchemas)({ + schemas: [this.graphQLSchemaDirectivesDefinitions, this.graphQLCustomTypeDefs, this.graphQLAutoSchema], + mergeDirectives: true + }); + } else if (typeof this.graphQLCustomTypeDefs === 'function') { + this.graphQLSchema = await this.graphQLCustomTypeDefs({ + directivesDefinitionsSchema: this.graphQLSchemaDirectivesDefinitions, + autoSchema: this.graphQLAutoSchema, + mergeSchemas: _graphqlTools.mergeSchemas + }); + } else { + 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' && this.graphQLCustomTypeDefs.definitions) { + 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, ignoreConnection = false) { + if (!ignoreReserved && RESERVED_GRAPHQL_TYPE_NAMES.includes(type.name) || this.graphQLTypes.find(existingType => existingType.name === type.name) || !ignoreConnection && type.name.endsWith('Connection')) { + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HcmFwaFFML1BhcnNlR3JhcGhRTFNjaGVtYS5qcyJdLCJuYW1lcyI6WyJSRVNFUlZFRF9HUkFQSFFMX1RZUEVfTkFNRVMiLCJSRVNFUlZFRF9HUkFQSFFMX1FVRVJZX05BTUVTIiwiUkVTRVJWRURfR1JBUEhRTF9NVVRBVElPTl9OQU1FUyIsIlBhcnNlR3JhcGhRTFNjaGVtYSIsImNvbnN0cnVjdG9yIiwicGFyYW1zIiwicGFyc2VHcmFwaFFMQ29udHJvbGxlciIsImRhdGFiYXNlQ29udHJvbGxlciIsImxvZyIsImdyYXBoUUxDdXN0b21UeXBlRGVmcyIsImFwcElkIiwibG9hZCIsInBhcnNlR3JhcGhRTENvbmZpZyIsIl9pbml0aWFsaXplU2NoZW1hQW5kQ29uZmlnIiwicGFyc2VDbGFzc2VzIiwiX2dldENsYXNzZXNGb3JTY2hlbWEiLCJwYXJzZUNsYXNzZXNTdHJpbmciLCJKU09OIiwic3RyaW5naWZ5IiwiZnVuY3Rpb25OYW1lcyIsIl9nZXRGdW5jdGlvbk5hbWVzIiwiZnVuY3Rpb25OYW1lc1N0cmluZyIsImdyYXBoUUxTY2hlbWEiLCJfaGFzU2NoZW1hSW5wdXRDaGFuZ2VkIiwicGFyc2VDbGFzc1R5cGVzIiwidmlld2VyVHlwZSIsImdyYXBoUUxBdXRvU2NoZW1hIiwiZ3JhcGhRTFR5cGVzIiwiZ3JhcGhRTFF1ZXJpZXMiLCJncmFwaFFMTXV0YXRpb25zIiwiZ3JhcGhRTFN1YnNjcmlwdGlvbnMiLCJncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zIiwiZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXMiLCJyZWxheU5vZGVJbnRlcmZhY2UiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiZGVmYXVsdFJlbGF5U2NoZW1hIiwic2NoZW1hVHlwZXMiLCJfZ2V0UGFyc2VDbGFzc2VzV2l0aENvbmZpZyIsImZvckVhY2giLCJwYXJzZUNsYXNzIiwicGFyc2VDbGFzc0NvbmZpZyIsInBhcnNlQ2xhc3NRdWVyaWVzIiwicGFyc2VDbGFzc011dGF0aW9ucyIsImxvYWRBcnJheVJlc3VsdCIsImRlZmF1bHRHcmFwaFFMUXVlcmllcyIsImRlZmF1bHRHcmFwaFFMTXV0YXRpb25zIiwiZ3JhcGhRTFF1ZXJ5IiwidW5kZWZpbmVkIiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsIkdyYXBoUUxPYmplY3RUeXBlIiwibmFtZSIsImRlc2NyaXB0aW9uIiwiZmllbGRzIiwiYWRkR3JhcGhRTFR5cGUiLCJncmFwaFFMTXV0YXRpb24iLCJncmFwaFFMU3Vic2NyaXB0aW9uIiwiR3JhcGhRTFNjaGVtYSIsInR5cGVzIiwicXVlcnkiLCJtdXRhdGlvbiIsInN1YnNjcmlwdGlvbiIsInNjaGVtYURpcmVjdGl2ZXMiLCJnZXRUeXBlTWFwIiwiY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGVNYXAiLCJ2YWx1ZXMiLCJjdXN0b21HcmFwaFFMU2NoZW1hVHlwZSIsInN0YXJ0c1dpdGgiLCJhdXRvR3JhcGhRTFNjaGVtYVR5cGUiLCJnZXRUeXBlIiwiX2ZpZWxkcyIsInNjaGVtYXMiLCJtZXJnZURpcmVjdGl2ZXMiLCJkaXJlY3RpdmVzRGVmaW5pdGlvbnNTY2hlbWEiLCJhdXRvU2NoZW1hIiwibWVyZ2VTY2hlbWFzIiwiZ3JhcGhRTFNjaGVtYVR5cGVNYXAiLCJncmFwaFFMU2NoZW1hVHlwZU5hbWUiLCJncmFwaFFMU2NoZW1hVHlwZSIsImdldEZpZWxkcyIsImRlZmluaXRpb25zIiwiZ3JhcGhRTEN1c3RvbVR5cGVEZWYiLCJmaW5kIiwiZGVmaW5pdGlvbiIsInZhbHVlIiwiZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZE1hcCIsImdyYXBoUUxTY2hlbWFUeXBlRmllbGROYW1lIiwiZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZCIsImFzdE5vZGUiLCJmaWVsZCIsIlNjaGVtYURpcmVjdGl2ZVZpc2l0b3IiLCJ2aXNpdFNjaGVtYURpcmVjdGl2ZXMiLCJ0eXBlIiwidGhyb3dFcnJvciIsImlnbm9yZVJlc2VydmVkIiwiaWdub3JlQ29ubmVjdGlvbiIsImluY2x1ZGVzIiwiZXhpc3RpbmdUeXBlIiwiZW5kc1dpdGgiLCJtZXNzYWdlIiwiRXJyb3IiLCJ3YXJuIiwicHVzaCIsImFkZEdyYXBoUUxRdWVyeSIsImZpZWxkTmFtZSIsImFkZEdyYXBoUUxNdXRhdGlvbiIsImhhbmRsZUVycm9yIiwiZXJyb3IiLCJQYXJzZSIsInN0YWNrIiwic2NoZW1hQ29udHJvbGxlciIsIlByb21pc2UiLCJhbGwiLCJsb2FkU2NoZW1hIiwiZ2V0R3JhcGhRTENvbmZpZyIsImVuYWJsZWRGb3JDbGFzc2VzIiwiZGlzYWJsZWRGb3JDbGFzc2VzIiwiYWxsQ2xhc3NlcyIsImdldEFsbENsYXNzZXMiLCJBcnJheSIsImlzQXJyYXkiLCJpbmNsdWRlZENsYXNzZXMiLCJmaWx0ZXIiLCJjbGF6eiIsImNsYXNzTmFtZSIsImlzVXNlcnNDbGFzc0Rpc2FibGVkIiwic29tZSIsImNsYXNzQ29uZmlncyIsInNvcnRDbGFzc2VzIiwiYSIsImIiLCJzb3J0IiwibWFwIiwiYyIsImZ1bmN0aW9uTmFtZSIsInRlc3QiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFNQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFHQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFFQSxNQUFNQSwyQkFBMkIsR0FBRyxDQUNsQyxRQURrQyxFQUVsQyxTQUZrQyxFQUdsQyxLQUhrQyxFQUlsQyxPQUprQyxFQUtsQyxJQUxrQyxFQU1sQyxhQU5rQyxFQU9sQyxPQVBrQyxFQVFsQyxVQVJrQyxFQVNsQyxjQVRrQyxFQVVsQyxpQkFWa0MsRUFXbEMsbUJBWGtDLEVBWWxDLFFBWmtDLEVBYWxDLGFBYmtDLEVBY2xDLGVBZGtDLEVBZWxDLFlBZmtDLEVBZ0JsQyxjQWhCa0MsRUFpQmxDLGFBakJrQyxFQWtCbEMsZUFsQmtDLEVBbUJsQyxtQkFuQmtDLEVBb0JsQyxvQkFwQmtDLEVBcUJsQyxzQkFyQmtDLEVBc0JsQyxrQkF0QmtDLEVBdUJsQyxv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b0JBLFlBQXBCO0FBQ0EsZUFBTyxLQUFQO0FBQ0Q7QUFDRjs7QUFFRCxXQUFPLElBQVA7QUFDRDs7QUFuYnNCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IHtcbiAgR3JhcGhRTFNjaGVtYSxcbiAgR3JhcGhRTE9iamVjdFR5cGUsXG4gIERvY3VtZW50Tm9kZSxcbiAgR3JhcGhRTE5hbWVkVHlwZSxcbn0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgeyBtZXJnZVNjaGVtYXMsIFNjaGVtYURpcmVjdGl2ZVZpc2l0b3IgfSBmcm9tICdncmFwaHFsLXRvb2xzJztcbmltcG9ydCByZXF1aXJlZFBhcmFtZXRlciBmcm9tICcuLi9yZXF1aXJlZFBhcmFtZXRlcic7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4vbG9hZGVycy9kZWZhdWx0R3JhcGhRTFR5cGVzJztcbmltcG9ydCAqIGFzIHBhcnNlQ2xhc3NUeXBlcyBmcm9tICcuL2xvYWRlcnMvcGFyc2VDbGFzc1R5cGVzJztcbmltcG9ydCAqIGFzIHBhcnNlQ2xhc3NRdWVyaWVzIGZyb20gJy4vbG9hZGVycy9wYXJzZUNsYXNzUXVlcmllcyc7XG5pbXBvcnQgKiBhcyBwYXJzZUNsYXNzTXV0YXRpb25zIGZyb20gJy4vbG9hZGVycy9wYXJzZUNsYXNzTXV0YXRpb25zJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMUXVlcmllcyBmcm9tICcuL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxRdWVyaWVzJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMTXV0YXRpb25zIGZyb20gJy4vbG9hZGVycy9kZWZhdWx0R3JhcGhRTE11dGF0aW9ucyc7XG5pbXBvcnQgUGFyc2VHcmFwaFFMQ29udHJvbGxlciwge1xuICBQYXJzZUdyYXBoUUxDb25maWcsXG59IGZyb20gJy4uL0NvbnRyb2xsZXJzL1BhcnNlR3JhcGhRTENvbnRyb2xsZXInO1xuaW1wb3J0IERhdGFiYXNlQ29udHJvbGxlciBmcm9tICcuLi9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgdG9HcmFwaFFMRXJyb3IgfSBmcm9tICcuL3BhcnNlR3JhcGhRTFV0aWxzJztcbmltcG9ydCAqIGFzIHNjaGVtYURpcmVjdGl2ZXMgZnJvbSAnLi9sb2FkZXJzL3NjaGVtYURpcmVjdGl2ZXMnO1xuaW1wb3J0ICogYXMgc2NoZW1hVHlwZXMgZnJvbSAnLi9sb2FkZXJzL3NjaGVtYVR5cGVzJztcbmltcG9ydCB7IGdldEZ1bmN0aW9uTmFtZXMgfSBmcm9tICcuLi90cmlnZ2Vycyc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0UmVsYXlTY2hlbWEgZnJvbSAnLi9sb2FkZXJzL2RlZmF1bHRSZWxheVNjaGVtYSc7XG5cbmNvbnN0IFJFU0VSVkVEX0dSQVBIUUxfVFlQRV9OQU1FUyA9IFtcbiAgJ1N0cmluZycsXG4gICdCb29sZWFuJyxcbiAgJ0ludCcsXG4gICdGbG9hdCcsXG4gICdJRCcsXG4gICdBcnJheVJlc3VsdCcsXG4gICdRdWVyeScsXG4gICdNdXRhdGlvbicsXG4gICdTdWJzY3JpcHRpb24nLFxuICAnQ3JlYXRlRmlsZUlucHV0JyxcbiAgJ0NyZWF0ZUZpbGVQYXlsb2FkJyxcbiAgJ1ZpZXdlcicsXG4gICdTaWduVXBJbnB1dCcsXG4gICdTaWduVXBQYXlsb2FkJyxcbiAgJ0xvZ0luSW5wdXQnLFxuICAnTG9nSW5QYXlsb2FkJyxcbiAgJ0xvZ091dElucHV0JyxcbiAgJ0xvZ091dFBheWxvYWQnLFxuICAnQ2xvdWRDb2RlRnVuY3Rpb24nLFxuICAnQ2FsbENsb3VkQ29kZUlucHV0JyxcbiAgJ0NhbGxDbG91ZENvZGVQYXlsb2FkJyxcbiAgJ0NyZWF0ZUNsYXNzSW5wdXQnLFxuICAnQ3JlYXRlQ2xhc3NQYXlsb2FkJyxcbiAgJ1VwZGF0ZUNsYXNzSW5wdXQnLFxuICAnVXBkYXRlQ2xhc3NQYXlsb2FkJyxcbiAgJ0RlbGV0ZUNsYXNzSW5wdXQnLFxuICAnRGVsZXRlQ2xhc3NQYXlsb2FkJyxcbiAgJ1BhZ2VJbmZvJyxcbl07XG5jb25zdCBSRVNFUlZFRF9HUkFQSFFMX1FVRVJZX05BTUVTID0gWydoZWFsdGgnLCAndmlld2VyJywgJ2NsYXNzJywgJ2NsYXNzZXMnXTtcbmNvbnN0IFJFU0VSVkVEX0dSQVBIUUxfTVVUQVRJT05fTkFNRVMgPSBbXG4gICdzaWduVXAnLFxuICAnbG9nSW4nLFxuICAnbG9nT3V0JyxcbiAgJ2NyZWF0ZUZpbGUnLFxuICAnY2FsbENsb3VkQ29kZScsXG4gICdjcmVhdGVDbGFzcycsXG4gICd1cGRhdGVDbGFzcycsXG4gICdkZWxldGVDbGFzcycsXG5dO1xuXG5jbGFzcyBQYXJzZUdyYXBoUUxTY2hlbWEge1xuICBkYXRhYmFzZUNvbnRyb2xsZXI6IERhdGFiYXNlQ29udHJvbGxlcjtcbiAgcGFyc2VHcmFwaFFMQ29udHJvbGxlcjogUGFyc2VHcmFwaFFMQ29udHJvbGxlcjtcbiAgcGFyc2VHcmFwaFFMQ29uZmlnOiBQYXJzZUdyYXBoUUxDb25maWc7XG4gIGxvZzogYW55O1xuICBhcHBJZDogc3RyaW5nO1xuICBncmFwaFFMQ3VzdG9tVHlwZURlZnM6ID8oXG4gICAgfCBzdHJpbmdcbiAgICB8IEdyYXBoUUxTY2hlbWFcbiAgICB8IERvY3VtZW50Tm9kZVxuICAgIHwgR3JhcGhRTE5hbWVkVHlwZVtdXG4gICk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcGFyYW1zOiB7XG4gICAgICBkYXRhYmFzZUNvbnRyb2xsZXI6IERhdGFiYXNlQ29udHJvbGxlcixcbiAgICAgIHBhcnNlR3JhcGhRTENvbnRyb2xsZXI6IFBhcnNlR3JhcGhRTENvbnRyb2xsZXIsXG4gICAgICBsb2c6IGFueSxcbiAgICAgIGFwcElkOiBzdHJpbmcsXG4gICAgICBncmFwaFFMQ3VzdG9tVHlwZURlZnM6ID8oXG4gICAgICAgIHwgc3RyaW5nXG4gICAgICAgIHwgR3JhcGhRTFNjaGVtYVxuICAgICAgICB8IERvY3VtZW50Tm9kZVxuICAgICAgICB8IEdyYXBoUUxOYW1lZFR5cGVbXVxuICAgICAgKSxcbiAgICB9ID0ge31cbiAgKSB7XG4gICAgdGhpcy5wYXJzZUdyYXBoUUxDb250cm9sbGVyID1cbiAgICAgIHBhcmFtcy5wYXJzZUdyYXBoUUxDb250cm9sbGVyIHx8XG4gICAgICByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIHBhcnNlR3JhcGhRTENvbnRyb2xsZXIgaW5zdGFuY2UhJyk7XG4gICAgdGhpcy5kYXRhYmFzZUNvbnRyb2xsZXIgPVxuICAgICAgcGFyYW1zLmRhdGFiYXNlQ29udHJvbGxlciB8fFxuICAgICAgcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYSBkYXRhYmFzZUNvbnRyb2xsZXIgaW5zdGFuY2UhJyk7XG4gICAgdGhpcy5sb2cgPVxuICAgICAgcGFyYW1zLmxvZyB8fCByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIGxvZyBpbnN0YW5jZSEnKTtcbiAgICB0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcyA9IHBhcmFtcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnM7XG4gICAgdGhpcy5hcHBJZCA9XG4gICAgICBwYXJhbXMuYXBwSWQgfHwgcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgdGhlIGFwcElkIScpO1xuICB9XG5cbiAgYXN5bmMgbG9hZCgpIHtcbiAgICBjb25zdCB7IHBhcnNlR3JhcGhRTENvbmZpZyB9ID0gYXdhaXQgdGhpcy5faW5pdGlhbGl6ZVNjaGVtYUFuZENvbmZpZygpO1xuICAgIGNvbnN0IHBhcnNlQ2xhc3NlcyA9IGF3YWl0IHRoaXMuX2dldENsYXNzZXNGb3JTY2hlbWEocGFyc2VHcmFwaFFMQ29uZmlnKTtcbiAgICBjb25zdCBwYXJzZUNsYXNzZXNTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShwYXJzZUNsYXNzZXMpO1xuICAgIGNvbnN0IGZ1bmN0aW9uTmFtZXMgPSBhd2FpdCB0aGlzLl9nZXRGdW5jdGlvbk5hbWVzKCk7XG4gICAgY29uc3QgZnVuY3Rpb25OYW1lc1N0cmluZyA9IEpTT04uc3RyaW5naWZ5KGZ1bmN0aW9uTmFtZXMpO1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hICYmXG4gICAgICAhdGhpcy5faGFzU2NoZW1hSW5wdXRDaGFuZ2VkKHtcbiAgICAgICAgcGFyc2VDbGFzc2VzLFxuICAgICAgICBwYXJzZUNsYXNzZXNTdHJpbmcsXG4gICAgICAgIHBhcnNlR3JhcGhRTENvbmZpZyxcbiAgICAgICAgZnVuY3Rpb25OYW1lc1N0cmluZyxcbiAgICAgIH0pXG4gICAgKSB7XG4gICAgICByZXR1cm4gdGhpcy5ncmFwaFFMU2NoZW1hO1xuICAgIH1cblxuICAgIHRoaXMucGFyc2VDbGFzc2VzID0gcGFyc2VDbGFzc2VzO1xuICAgIHRoaXMucGFyc2VDbGFzc2VzU3RyaW5nID0gcGFyc2VDbGFzc2VzU3RyaW5nO1xuICAgIHRoaXMucGFyc2VHcmFwaFFMQ29uZmlnID0gcGFyc2VHcmFwaFFMQ29uZmlnO1xuICAgIHRoaXMuZnVuY3Rpb25OYW1lcyA9IGZ1bmN0aW9uTmFtZXM7XG4gICAgdGhpcy5mdW5jdGlvbk5hbWVzU3RyaW5nID0gZnVuY3Rpb25OYW1lc1N0cmluZztcbiAgICB0aGlzLnBhcnNlQ2xhc3NUeXBlcyA9IHt9O1xuICAgIHRoaXMudmlld2VyVHlwZSA9IG51bGw7XG4gICAgdGhpcy5ncmFwaFFMQXV0b1NjaGVtYSA9IG51bGw7XG4gICAgdGhpcy5ncmFwaFFMU2NoZW1hID0gbnVsbDtcbiAgICB0aGlzLmdyYXBoUUxUeXBlcyA9IFtdO1xuICAgIHRoaXMuZ3JhcGhRTFF1ZXJpZXMgPSB7fTtcbiAgICB0aGlzLmdyYXBoUUxNdXRhdGlvbnMgPSB7fTtcbiAgICB0aGlzLmdyYXBoUUxTdWJzY3JpcHRpb25zID0ge307XG4gICAgdGhpcy5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zID0gbnVsbDtcbiAgICB0aGlzLmdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzID0ge307XG4gICAgdGhpcy5yZWxheU5vZGVJbnRlcmZhY2UgPSBudWxsO1xuXG4gICAgZGVmYXVsdEdyYXBoUUxUeXBlcy5sb2FkKHRoaXMpO1xuICAgIGRlZmF1bHRSZWxheVNjaGVtYS5sb2FkKHRoaXMpO1xuICAgIHNjaGVtYVR5cGVzLmxvYWQodGhpcyk7XG5cbiAgICB0aGlzLl9nZXRQYXJzZUNsYXNzZXNXaXRoQ29uZmlnKHBhcnNlQ2xhc3NlcywgcGFyc2VHcmFwaFFMQ29uZmlnKS5mb3JFYWNoKFxuICAgICAgKFtwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnXSkgPT4ge1xuICAgICAgICBwYXJzZUNsYXNzVHlwZXMubG9hZCh0aGlzLCBwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnKTtcbiAgICAgICAgcGFyc2VDbGFzc1F1ZXJpZXMubG9hZCh0aGlzLCBwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnKTtcbiAgICAgICAgcGFyc2VDbGFzc011dGF0aW9ucy5sb2FkKHRoaXMsIHBhcnNlQ2xhc3MsIHBhcnNlQ2xhc3NDb25maWcpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICBkZWZhdWx0R3JhcGhRTFR5cGVzLmxvYWRBcnJheVJlc3VsdCh0aGlzLCBwYXJzZUNsYXNzZXMpO1xuICAgIGRlZmF1bHRHcmFwaFFMUXVlcmllcy5sb2FkKHRoaXMpO1xuICAgIGRlZmF1bHRHcmFwaFFMTXV0YXRpb25zLmxvYWQodGhpcyk7XG5cbiAgICBsZXQgZ3JhcGhRTFF1ZXJ5ID0gdW5kZWZpbmVkO1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLmdyYXBoUUxRdWVyaWVzKS5sZW5ndGggPiAwKSB7XG4gICAgICBncmFwaFFMUXVlcnkgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICAgICAgICBuYW1lOiAnUXVlcnknLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ1F1ZXJ5IGlzIHRoZSB0b3AgbGV2ZWwgdHlwZSBmb3IgcXVlcmllcy4nLFxuICAgICAgICBmaWVsZHM6IHRoaXMuZ3JhcGhRTFF1ZXJpZXMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkR3JhcGhRTFR5cGUoZ3JhcGhRTFF1ZXJ5LCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBsZXQgZ3JhcGhRTE11dGF0aW9uID0gdW5kZWZpbmVkO1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLmdyYXBoUUxNdXRhdGlvbnMpLmxlbmd0aCA+IDApIHtcbiAgICAgIGdyYXBoUUxNdXRhdGlvbiA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gICAgICAgIG5hbWU6ICdNdXRhdGlvbicsXG4gICAgICAgIGRlc2NyaXB0aW9uOiAnTXV0YXRpb24gaXMgdGhlIHRvcCBsZXZlbCB0eXBlIGZvciBtdXRhdGlvbnMuJyxcbiAgICAgICAgZmllbGRzOiB0aGlzLmdyYXBoUUxNdXRhdGlvbnMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkR3JhcGhRTFR5cGUoZ3JhcGhRTE11dGF0aW9uLCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBsZXQgZ3JhcGhRTFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5ncmFwaFFMU3Vic2NyaXB0aW9ucykubGVuZ3RoID4gMCkge1xuICAgICAgZ3JhcGhRTFN1YnNjcmlwdGlvbiA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gICAgICAgIG5hbWU6ICdTdWJzY3JpcHRpb24nLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ1N1YnNjcmlwdGlvbiBpcyB0aGUgdG9wIGxldmVsIHR5cGUgZm9yIHN1YnNjcmlwdGlvbnMuJyxcbiAgICAgICAgZmllbGRzOiB0aGlzLmdyYXBoUUxTdWJzY3JpcHRpb25zLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmFkZEdyYXBoUUxUeXBlKGdyYXBoUUxTdWJzY3JpcHRpb24sIHRydWUsIHRydWUpO1xuICAgIH1cblxuICAgIHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEgPSBuZXcgR3JhcGhRTFNjaGVtYSh7XG4gICAgICB0eXBlczogdGhpcy5ncmFwaFFMVHlwZXMsXG4gICAgICBxdWVyeTogZ3JhcGhRTFF1ZXJ5LFxuICAgICAgbXV0YXRpb246IGdyYXBoUUxNdXRhdGlvbixcbiAgICAgIHN1YnNjcmlwdGlvbjogZ3JhcGhRTFN1YnNjcmlwdGlvbixcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcykge1xuICAgICAgc2NoZW1hRGlyZWN0aXZlcy5sb2FkKHRoaXMpO1xuXG4gICAgICBpZiAodHlwZW9mIHRoaXMuZ3JhcGhRTEN1c3RvbVR5cGVEZWZzLmdldFR5cGVNYXAgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29uc3QgY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGVNYXAgPSB0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcy5nZXRUeXBlTWFwKCk7XG4gICAgICAgIE9iamVjdC52YWx1ZXMoY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGVNYXApLmZvckVhY2goXG4gICAgICAgICAgY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGUgPT4ge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAhY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGUgfHxcbiAgICAgICAgICAgICAgIWN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlLm5hbWUgfHxcbiAgICAgICAgICAgICAgY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGUubmFtZS5zdGFydHNXaXRoKCdfXycpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYXV0b0dyYXBoUUxTY2hlbWFUeXBlID0gdGhpcy5ncmFwaFFMQXV0b1NjaGVtYS5nZXRUeXBlKFxuICAgICAgICAgICAgICBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZS5uYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGF1dG9HcmFwaFFMU2NoZW1hVHlwZSkge1xuICAgICAgICAgICAgICBhdXRvR3JhcGhRTFNjaGVtYVR5cGUuX2ZpZWxkcyA9IHtcbiAgICAgICAgICAgICAgICAuLi5hdXRvR3JhcGhRTFNjaGVtYVR5cGUuX2ZpZWxkcyxcbiAgICAgICAgICAgICAgICAuLi5jdXN0b21HcmFwaFFMU2NoZW1hVHlwZS5fZmllbGRzLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hID0gbWVyZ2VTY2hlbWFzKHtcbiAgICAgICAgICBzY2hlbWFzOiBbXG4gICAgICAgICAgICB0aGlzLmdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzRGVmaW5pdGlvbnMsXG4gICAgICAgICAgICB0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcyxcbiAgICAgICAgICAgIHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEsXG4gICAgICAgICAgXSxcbiAgICAgICAgICBtZXJnZURpcmVjdGl2ZXM6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hID0gYXdhaXQgdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMoe1xuICAgICAgICAgIGRpcmVjdGl2ZXNEZWZpbml0aW9uc1NjaGVtYTogdGhpcy5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zLFxuICAgICAgICAgIGF1dG9TY2hlbWE6IHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEsXG4gICAgICAgICAgbWVyZ2VTY2hlbWFzLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuZ3JhcGhRTFNjaGVtYSA9IG1lcmdlU2NoZW1hcyh7XG4gICAgICAgICAgc2NoZW1hczogW1xuICAgICAgICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zLFxuICAgICAgICAgICAgdGhpcy5ncmFwaFFMQXV0b1NjaGVtYSxcbiAgICAgICAgICAgIHRoaXMuZ3JhcGhRTEN1c3RvbVR5cGVEZWZzLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgbWVyZ2VEaXJlY3RpdmVzOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZ3JhcGhRTFNjaGVtYVR5cGVNYXAgPSB0aGlzLmdyYXBoUUxTY2hlbWEuZ2V0VHlwZU1hcCgpO1xuICAgICAgT2JqZWN0LmtleXMoZ3JhcGhRTFNjaGVtYVR5cGVNYXApLmZvckVhY2goZ3JhcGhRTFNjaGVtYVR5cGVOYW1lID0+IHtcbiAgICAgICAgY29uc3QgZ3JhcGhRTFNjaGVtYVR5cGUgPSBncmFwaFFMU2NoZW1hVHlwZU1hcFtncmFwaFFMU2NoZW1hVHlwZU5hbWVdO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdHlwZW9mIGdyYXBoUUxTY2hlbWFUeXBlLmdldEZpZWxkcyA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgICAgIHRoaXMuZ3JhcGhRTEN1c3RvbVR5cGVEZWZzLmRlZmluaXRpb25zXG4gICAgICAgICkge1xuICAgICAgICAgIGNvbnN0IGdyYXBoUUxDdXN0b21UeXBlRGVmID0gdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMuZGVmaW5pdGlvbnMuZmluZChcbiAgICAgICAgICAgIGRlZmluaXRpb24gPT4gZGVmaW5pdGlvbi5uYW1lLnZhbHVlID09PSBncmFwaFFMU2NoZW1hVHlwZU5hbWVcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChncmFwaFFMQ3VzdG9tVHlwZURlZikge1xuICAgICAgICAgICAgY29uc3QgZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZE1hcCA9IGdyYXBoUUxTY2hlbWFUeXBlLmdldEZpZWxkcygpO1xuICAgICAgICAgICAgT2JqZWN0LmtleXMoZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZE1hcCkuZm9yRWFjaChcbiAgICAgICAgICAgICAgZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGdyYXBoUUxTY2hlbWFUeXBlRmllbGQgPVxuICAgICAgICAgICAgICAgICAgZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZE1hcFtncmFwaFFMU2NoZW1hVHlwZUZpZWxkTmFtZV07XG4gICAgICAgICAgICAgICAgaWYgKCFncmFwaFFMU2NoZW1hVHlwZUZpZWxkLmFzdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGFzdE5vZGUgPSBncmFwaFFMQ3VzdG9tVHlwZURlZi5maWVsZHMuZmluZChcbiAgICAgICAgICAgICAgICAgICAgZmllbGQgPT4gZmllbGQubmFtZS52YWx1ZSA9PT0gZ3JhcGhRTFNjaGVtYVR5cGVGaWVsZE5hbWVcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICBpZiAoYXN0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBncmFwaFFMU2NoZW1hVHlwZUZpZWxkLmFzdE5vZGUgPSBhc3ROb2RlO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBTY2hlbWFEaXJlY3RpdmVWaXNpdG9yLnZpc2l0U2NoZW1hRGlyZWN0aXZlcyhcbiAgICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hLFxuICAgICAgICB0aGlzLmdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmdyYXBoUUxTY2hlbWEgPSB0aGlzLmdyYXBoUUxBdXRvU2NoZW1hO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmdyYXBoUUxTY2hlbWE7XG4gIH1cblxuICBhZGRHcmFwaFFMVHlwZShcbiAgICB0eXBlLFxuICAgIHRocm93RXJyb3IgPSBmYWxzZSxcbiAgICBpZ25vcmVSZXNlcnZlZCA9IGZhbHNlLFxuICAgIGlnbm9yZUNvbm5lY3Rpb24gPSBmYWxzZVxuICApIHtcbiAgICBpZiAoXG4gICAgICAoIWlnbm9yZVJlc2VydmVkICYmIFJFU0VSVkVEX0dSQVBIUUxfVFlQRV9OQU1FUy5pbmNsdWRlcyh0eXBlLm5hbWUpKSB8fFxuICAgICAgdGhpcy5ncmFwaFFMVHlwZXMuZmluZChleGlzdGluZ1R5cGUgPT4gZXhpc3RpbmdUeXBlLm5hbWUgPT09IHR5cGUubmFtZSkgfHxcbiAgICAgICghaWdub3JlQ29ubmVjdGlvbiAmJiB0eXBlLm5hbWUuZW5kc1dpdGgoJ0Nvbm5lY3Rpb24nKSlcbiAgICApIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgVHlwZSAke3R5cGUubmFtZX0gY291bGQgbm90IGJlIGFkZGVkIHRvIHRoZSBhdXRvIHNjaGVtYSBiZWNhdXNlIGl0IGNvbGxpZGVkIHdpdGggYW4gZXhpc3RpbmcgdHlwZS5gO1xuICAgICAgaWYgKHRocm93RXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cud2FybihtZXNzYWdlKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuZ3JhcGhRTFR5cGVzLnB1c2godHlwZSk7XG4gICAgcmV0dXJuIHR5cGU7XG4gIH1cblxuICBhZGRHcmFwaFFMUXVlcnkoXG4gICAgZmllbGROYW1lLFxuICAgIGZpZWxkLFxuICAgIHRocm93RXJyb3IgPSBmYWxzZSxcbiAgICBpZ25vcmVSZXNlcnZlZCA9IGZhbHNlXG4gICkge1xuICAgIGlmIChcbiAgICAgICghaWdub3JlUmVzZXJ2ZWQgJiYgUkVTRVJWRURfR1JBUEhRTF9RVUVSWV9OQU1FUy5pbmNsdWRlcyhmaWVsZE5hbWUpKSB8fFxuICAgICAgdGhpcy5ncmFwaFFMUXVlcmllc1tmaWVsZE5hbWVdXG4gICAgKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYFF1ZXJ5ICR7ZmllbGROYW1lfSBjb3VsZCBub3QgYmUgYWRkZWQgdG8gdGhlIGF1dG8gc2NoZW1hIGJlY2F1c2UgaXQgY29sbGlkZWQgd2l0aCBhbiBleGlzdGluZyBmaWVsZC5gO1xuICAgICAgaWYgKHRocm93RXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cud2FybihtZXNzYWdlKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuZ3JhcGhRTFF1ZXJpZXNbZmllbGROYW1lXSA9IGZpZWxkO1xuICAgIHJldHVybiBmaWVsZDtcbiAgfVxuXG4gIGFkZEdyYXBoUUxNdXRhdGlvbihcbiAgICBmaWVsZE5hbWUsXG4gICAgZmllbGQsXG4gICAgdGhyb3dFcnJvciA9IGZhbHNlLFxuICAgIGlnbm9yZVJlc2VydmVkID0gZmFsc2VcbiAgKSB7XG4gICAgaWYgKFxuICAgICAgKCFpZ25vcmVSZXNlcnZlZCAmJlxuICAgICAgICBSRVNFUlZFRF9HUkFQSFFMX01VVEFUSU9OX05BTUVTLmluY2x1ZGVzKGZpZWxkTmFtZSkpIHx8XG4gICAgICB0aGlzLmdyYXBoUUxNdXRhdGlvbnNbZmllbGROYW1lXVxuICAgICkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGBNdXRhdGlvbiAke2ZpZWxkTmFtZX0gY291bGQgbm90IGJlIGFkZGVkIHRvIHRoZSBhdXRvIHNjaGVtYSBiZWNhdXNlIGl0IGNvbGxpZGVkIHdpdGggYW4gZXhpc3RpbmcgZmllbGQuYDtcbiAgICAgIGlmICh0aHJvd0Vycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubG9nLndhcm4obWVzc2FnZSk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0aGlzLmdyYXBoUUxNdXRhdGlvbnNbZmllbGROYW1lXSA9IGZpZWxkO1xuICAgIHJldHVybiBmaWVsZDtcbiAgfVxuXG4gIGhhbmRsZUVycm9yKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IpIHtcbiAgICAgIHRoaXMubG9nLmVycm9yKCdQYXJzZSBlcnJvcjogJywgZXJyb3IpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvZy5lcnJvcignVW5jYXVnaHQgaW50ZXJuYWwgc2VydmVyIGVycm9yLicsIGVycm9yLCBlcnJvci5zdGFjayk7XG4gICAgfVxuICAgIHRocm93IHRvR3JhcGhRTEVycm9yKGVycm9yKTtcbiAgfVxuXG4gIGFzeW5jIF9pbml0aWFsaXplU2NoZW1hQW5kQ29uZmlnKCkge1xuICAgIGNvbnN0IFtzY2hlbWFDb250cm9sbGVyLCBwYXJzZUdyYXBoUUxDb25maWddID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgdGhpcy5kYXRhYmFzZUNvbnRyb2xsZXIubG9hZFNjaGVtYSgpLFxuICAgICAgdGhpcy5wYXJzZUdyYXBoUUxDb250cm9sbGVyLmdldEdyYXBoUUxDb25maWcoKSxcbiAgICBdKTtcblxuICAgIHRoaXMuc2NoZW1hQ29udHJvbGxlciA9IHNjaGVtYUNvbnRyb2xsZXI7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGFyc2VHcmFwaFFMQ29uZmlnLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBhbGwgY2xhc3NlcyBmb3VuZCBieSB0aGUgYHNjaGVtYUNvbnRyb2xsZXJgXG4gICAqIG1pbnVzIHRob3NlIGZpbHRlcmVkIG91dCBieSB0aGUgYXBwJ3MgcGFyc2VHcmFwaFFMQ29uZmlnLlxuICAgKi9cbiAgYXN5bmMgX2dldENsYXNzZXNGb3JTY2hlbWEocGFyc2VHcmFwaFFMQ29uZmlnOiBQYXJzZUdyYXBoUUxDb25maWcpIHtcbiAgICBjb25zdCB7IGVuYWJsZWRGb3JDbGFzc2VzLCBkaXNhYmxlZEZvckNsYXNzZXMgfSA9IHBhcnNlR3JhcGhRTENvbmZpZztcbiAgICBjb25zdCBhbGxDbGFzc2VzID0gYXdhaXQgdGhpcy5zY2hlbWFDb250cm9sbGVyLmdldEFsbENsYXNzZXMoKTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KGVuYWJsZWRGb3JDbGFzc2VzKSB8fCBBcnJheS5pc0FycmF5KGRpc2FibGVkRm9yQ2xhc3NlcykpIHtcbiAgICAgIGxldCBpbmNsdWRlZENsYXNzZXMgPSBhbGxDbGFzc2VzO1xuICAgICAgaWYgKGVuYWJsZWRGb3JDbGFzc2VzKSB7XG4gICAgICAgIGluY2x1ZGVkQ2xhc3NlcyA9IGFsbENsYXNzZXMuZmlsdGVyKGNsYXp6ID0+IHtcbiAgICAgICAgICByZXR1cm4gZW5hYmxlZEZvckNsYXNzZXMuaW5jbHVkZXMoY2xhenouY2xhc3NOYW1lKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBpZiAoZGlzYWJsZWRGb3JDbGFzc2VzKSB7XG4gICAgICAgIC8vIENsYXNzZXMgaW5jbHVkZWQgaW4gYGVuYWJsZWRGb3JDbGFzc2VzYCB0aGF0XG4gICAgICAgIC8vIGFyZSBhbHNvIHByZXNlbnQgaW4gYGRpc2FibGVkRm9yQ2xhc3Nlc2Agd2lsbFxuICAgICAgICAvLyBzdGlsbCBiZSBmaWx0ZXJlZCBvdXRcbiAgICAgICAgaW5jbHVkZWRDbGFzc2VzID0gaW5jbHVkZWRDbGFzc2VzLmZpbHRlcihjbGF6eiA9PiB7XG4gICAgICAgICAgcmV0dXJuICFkaXNhYmxlZEZvckNsYXNzZXMuaW5jbHVkZXMoY2xhenouY2xhc3NOYW1lKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaXNVc2Vyc0NsYXNzRGlzYWJsZWQgPSAhaW5jbHVkZWRDbGFzc2VzLnNvbWUoY2xhenogPT4ge1xuICAgICAgICByZXR1cm4gY2xhenouY2xhc3NOYW1lID09PSAnX1VzZXInO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBpbmNsdWRlZENsYXNzZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBhbGxDbGFzc2VzO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIGEgbGlzdCBvZiB0dXBsZXNcbiAgICogdGhhdCBwcm92aWRlIHRoZSBwYXJzZUNsYXNzIGFsb25nIHdpdGhcbiAgICogaXRzIHBhcnNlQ2xhc3NDb25maWcgd2hlcmUgcHJvdmlkZWQuXG4gICAqL1xuICBfZ2V0UGFyc2VDbGFzc2VzV2l0aENvbmZpZyhcbiAgICBwYXJzZUNsYXNzZXMsXG4gICAgcGFyc2VHcmFwaFFMQ29uZmlnOiBQYXJzZUdyYXBoUUxDb25maWdcbiAgKSB7XG4gICAgY29uc3QgeyBjbGFzc0NvbmZpZ3MgfSA9IHBhcnNlR3JhcGhRTENvbmZpZztcblxuICAgIC8vIE1ha2Ugc3VyZXMgdGhhdCB0aGUgZGVmYXVsdCBjbGFzc2VzIGFuZCBjbGFzc2VzIHRoYXRcbiAgICAvLyBzdGFydHMgd2l0aCBjYXBpdGFsaXplZCBsZXR0ZXIgd2lsbCBiZSBnZW5lcmF0ZWQgZmlyc3QuXG4gICAgY29uc3Qgc29ydENsYXNzZXMgPSAoYSwgYikgPT4ge1xuICAgICAgYSA9IGEuY2xhc3NOYW1lO1xuICAgICAgYiA9IGIuY2xhc3NOYW1lO1xuICAgICAgaWYgKGFbMF0gPT09ICdfJykge1xuICAgICAgICBpZiAoYlswXSAhPT0gJ18nKSB7XG4gICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoYlswXSA9PT0gJ18nKSB7XG4gICAgICAgIGlmIChhWzBdICE9PSAnXycpIHtcbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9IGVsc2UgaWYgKGEgPCBiKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gcGFyc2VDbGFzc2VzLnNvcnQoc29ydENsYXNzZXMpLm1hcChwYXJzZUNsYXNzID0+IHtcbiAgICAgIGxldCBwYXJzZUNsYXNzQ29uZmlnO1xuICAgICAgaWYgKGNsYXNzQ29uZmlncykge1xuICAgICAgICBwYXJzZUNsYXNzQ29uZmlnID0gY2xhc3NDb25maWdzLmZpbmQoXG4gICAgICAgICAgYyA9PiBjLmNsYXNzTmFtZSA9PT0gcGFyc2VDbGFzcy5jbGFzc05hbWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBbcGFyc2VDbGFzcywgcGFyc2VDbGFzc0NvbmZpZ107XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBfZ2V0RnVuY3Rpb25OYW1lcygpIHtcbiAgICByZXR1cm4gYXdhaXQgZ2V0RnVuY3Rpb25OYW1lcyh0aGlzLmFwcElkKS5maWx0ZXIoZnVuY3Rpb25OYW1lID0+IHtcbiAgICAgIGlmICgvXltfYS16QS1aXVtfYS16QS1aMC05XSokLy50ZXN0KGZ1bmN0aW9uTmFtZSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmxvZy53YXJuKFxuICAgICAgICAgIGBGdW5jdGlvbiAke2Z1bmN0aW9uTmFtZX0gY291bGQgbm90IGJlIGFkZGVkIHRvIHRoZSBhdXRvIHNjaGVtYSBiZWNhdXNlIEdyYXBoUUwgbmFtZXMgbXVzdCBtYXRjaCAvXltfYS16QS1aXVtfYS16QS1aMC05XSokLy5gXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgZm9yIGNoYW5nZXMgdG8gdGhlIHBhcnNlQ2xhc3Nlc1xuICAgKiBvYmplY3RzIChpLmUuIGRhdGFiYXNlIHNjaGVtYSkgb3IgdG9cbiAgICogdGhlIHBhcnNlR3JhcGhRTENvbmZpZyBvYmplY3QuIElmIG5vXG4gICAqIGNoYW5nZXMgYXJlIGZvdW5kLCByZXR1cm4gdHJ1ZTtcbiAgICovXG4gIF9oYXNTY2hlbWFJbnB1dENoYW5nZWQocGFyYW1zOiB7XG4gICAgcGFyc2VDbGFzc2VzOiBhbnksXG4gICAgcGFyc2VDbGFzc2VzU3RyaW5nOiBzdHJpbmcsXG4gICAgcGFyc2VHcmFwaFFMQ29uZmlnOiA/UGFyc2VHcmFwaFFMQ29uZmlnLFxuICAgIGZ1bmN0aW9uTmFtZXNTdHJpbmc6IHN0cmluZyxcbiAgfSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHtcbiAgICAgIHBhcnNlQ2xhc3NlcyxcbiAgICAgIHBhcnNlQ2xhc3Nlc1N0cmluZyxcbiAgICAgIHBhcnNlR3JhcGhRTENvbmZpZyxcbiAgICAgIGZ1bmN0aW9uTmFtZXNTdHJpbmcsXG4gICAgfSA9IHBhcmFtcztcblxuICAgIGlmIChcbiAgICAgIEpTT04uc3RyaW5naWZ5KHRoaXMucGFyc2VHcmFwaFFMQ29uZmlnKSA9PT1cbiAgICAgICAgSlNPTi5zdHJpbmdpZnkocGFyc2VHcmFwaFFMQ29uZmlnKSAmJlxuICAgICAgdGhpcy5mdW5jdGlvbk5hbWVzU3RyaW5nID09PSBmdW5jdGlvbk5hbWVzU3RyaW5nXG4gICAgKSB7XG4gICAgICBpZiAodGhpcy5wYXJzZUNsYXNzZXMgPT09IHBhcnNlQ2xhc3Nlcykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnBhcnNlQ2xhc3Nlc1N0cmluZyA9PT0gcGFyc2VDbGFzc2VzU3RyaW5nKSB7XG4gICAgICAgIHRoaXMucGFyc2VDbGFzc2VzID0gcGFyc2VDbGFzc2VzO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cblxuZXhwb3J0IHsgUGFyc2VHcmFwaFFMU2NoZW1hIH07XG4iXX0= \ 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..e102b9950d --- /dev/null +++ b/lib/GraphQL/helpers/objectsQueries.js @@ -0,0 +1,275 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.needToGetAllKeys = exports.calculateSkipAndLimit = exports.findObjects = exports.getObject = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _graphqlRelay = require("graphql-relay"); + +var _rest = _interopRequireDefault(require("../../rest")); + +var _query = require("../transformers/query"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const needToGetAllKeys = (fields, keys) => keys ? !!keys.split(',').find(keyName => !fields[keyName.split('.')[0]]) : true; + +exports.needToGetAllKeys = needToGetAllKeys; + +const getObject = async (className, objectId, keys, include, readPreference, includeReadPreference, config, auth, info, parseClass) => { + const options = {}; + + if (!needToGetAllKeys(parseClass.fields, 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, skipInput, first, after, last, before, keys, include, includeAll, readPreference, includeReadPreference, subqueryReadPreference, config, auth, info, selectedFields, parseClasses) => { + if (!where) { + where = {}; + } + + (0, _query.transformQueryInputToParse)(where, className, parseClasses); + const skipAndLimitCalculation = calculateSkipAndLimit(skipInput, first, after, last, before, config.maxLimit); + let { + skip + } = skipAndLimitCalculation; + const { + limit, + needToPreCount + } = skipAndLimitCalculation; + let preCount = undefined; + + if (needToPreCount) { + const preCountOptions = { + limit: 0, + count: true + }; + + if (readPreference) { + preCountOptions.readPreference = readPreference; + } + + if (Object.keys(where).length > 0 && subqueryReadPreference) { + preCountOptions.subqueryReadPreference = subqueryReadPreference; + } + + preCount = (await _rest.default.find(config, auth, className, where, preCountOptions, info.clientSDK)).count; + + if ((skip || 0) + limit < preCount) { + skip = preCount - limit; + } + } + + const options = {}; + + if (selectedFields.find(field => field.startsWith('edges.') || field.startsWith('pageInfo.'))) { + if (limit || limit === 0) { + options.limit = limit; + } else { + options.limit = 100; + } + + 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 (!needToGetAllKeys(parseClasses.find(({ + className: parseClassName + }) => className === parseClassName).fields, 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') || selectedFields.includes('pageInfo.hasPreviousPage') || selectedFields.includes('pageInfo.hasNextPage')) && !needToPreCount) { + options.count = true; + } + + if (readPreference) { + options.readPreference = readPreference; + } + + if (Object.keys(where).length > 0 && subqueryReadPreference) { + options.subqueryReadPreference = subqueryReadPreference; + } + + let results, count; + + if (options.count || !options.limit || options.limit && options.limit > 0) { + const findResult = await _rest.default.find(config, auth, className, where, options, info.clientSDK); + results = findResult.results; + count = findResult.count; + } + + let edges = null; + let pageInfo = null; + + if (results) { + edges = results.map((result, index) => ({ + cursor: (0, _graphqlRelay.offsetToCursor)((skip || 0) + index), + node: result + })); + pageInfo = { + hasPreviousPage: (preCount && preCount > 0 || count && count > 0) && skip !== undefined && skip > 0, + startCursor: (0, _graphqlRelay.offsetToCursor)(skip || 0), + endCursor: (0, _graphqlRelay.offsetToCursor)((skip || 0) + (results.length || 1) - 1), + hasNextPage: (preCount || count) > (skip || 0) + results.length + }; + } + + return { + edges, + pageInfo, + count: preCount || count + }; +}; + +exports.findObjects = findObjects; + +const calculateSkipAndLimit = (skipInput, first, after, last, before, maxLimit) => { + let skip = undefined; + let limit = undefined; + let needToPreCount = false; // Validates the skip input + + if (skipInput || skipInput === 0) { + if (skipInput < 0) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'Skip should be a positive number'); + } + + skip = skipInput; + } // Validates the after param + + + if (after) { + after = (0, _graphqlRelay.cursorToOffset)(after); + + if (!after && after !== 0 || after < 0) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'After is not a valid cursor'); + } // If skip and after are passed, a new skip is calculated by adding them + + + skip = (skip || 0) + (after + 1); + } // Validates the first param + + + if (first || first === 0) { + if (first < 0) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'First should be a positive number'); + } // The first param is translated to the limit param of the Parse legacy API + + + limit = first; + } // Validates the before param + + + if (before || before === 0) { + // This method converts the cursor to the index of the object + before = (0, _graphqlRelay.cursorToOffset)(before); + + if (!before && before !== 0 || before < 0) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'Before is not a valid cursor'); + } + + if ((skip || 0) >= before) { + // If the before index is less then the skip, no objects will be returned + limit = 0; + } else if (!limit && limit !== 0 || (skip || 0) + limit > before) { + // If there is no limit set, the limit is calculated. Or, if the limit (plus skip) is bigger than the before index, the new limit is set. + limit = before - (skip || 0); + } + } // Validates the last param + + + if (last || last === 0) { + if (last < 0) { + throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'Last should be a positive number'); + } + + if (last > maxLimit) { + // Last can't be bigger than Parse server maxLimit config. + last = maxLimit; + } + + if (limit || limit === 0) { + // If there is a previous limit set, it may be adjusted + if (last < limit) { + // if last is less than the current limit + skip = (skip || 0) + (limit - last); // The skip is adjusted + + limit = last; // the limit is adjusted + } + } else if (last === 0) { + // No objects will be returned + limit = 0; + } else { + // No previous limit set, the limit will be equal to last and pre count is needed. + limit = last; + needToPreCount = true; + } + } + + return { + skip, + limit, + needToPreCount + }; +}; + +exports.calculateSkipAndLimit = calculateSkipAndLimit; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2hlbHBlcnMvb2JqZWN0c1F1ZXJpZXMuanMiXSwibmFtZXMiOlsibmVlZFRvR2V0QWxsS2V5cyIsImZpZWxkcyIsImtleXMiLCJzcGxpdCIsImZpbmQiLCJrZXlOYW1lIiwiZ2V0T2JqZWN0IiwiY2xhc3NOYW1lIiwib2JqZWN0SWQiLCJpbmNsdWRlIiwicmVhZFByZWZlcmVuY2UiLCJpbmNsdWRlUmVhZFByZWZlcmVuY2UiLCJjb25maWciLCJhdXRoIiwiaW5mbyIsInBhcnNlQ2xhc3MiLCJvcHRpb25zIiwicmVzcG9uc2UiLCJyZXN0IiwiZ2V0IiwiY2xpZW50U0RLIiwicmVzdWx0cyIsImxlbmd0aCIsIlBhcnNlIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwib2JqZWN0Iiwic2Vzc2lvblRva2VuIiwiZmluZE9iamVjdHMiLCJ3aGVyZSIsIm9yZGVyIiwic2tpcElucHV0IiwiZmlyc3QiLCJhZnRlciIsImxhc3QiLCJiZWZvcmUiLCJpbmNsdWRlQWxsIiwic3VicXVlcnlSZWFkUHJlZmVyZW5jZSIsInNlbGVjdGVkRmllbGRzIiwicGFyc2VDbGFzc2VzIiwic2tpcEFuZExpbWl0Q2FsY3VsYXRpb24iLCJjYWxjdWxhdGVTa2lwQW5kTGltaXQiLCJtYXhMaW1pdCIsInNraXAiLCJsaW1pdCIsIm5lZWRUb1ByZUNvdW50IiwicHJlQ291bnQiLCJ1bmRlZmluZWQiLCJwcmVDb3VudE9wdGlvbnMiLCJjb3VudCIsIk9iamVjdCIsImZpZWxkIiwic3RhcnRzV2l0aCIsInBhcnNlQ2xhc3NOYW1lIiwiaW5jbHVkZXMiLCJmaW5kUmVzdWx0IiwiZWRnZXMiLCJwYWdlSW5mbyIsIm1hcCIsInJlc3VsdCIsImluZGV4IiwiY3Vyc29yIiwibm9kZSIsImhhc1ByZXZpb3VzUGFnZSIsInN0YXJ0Q3Vyc29yIiwiZW5kQ3Vyc29yIiwiaGFzTmV4dFBhZ2UiLCJJTlZBTElEX1FVRVJZIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FB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QUFSO0FBQ0QsS0FITSxNQUdBO0FBQ0w7QUFDQUEsTUFBQUEsS0FBSyxHQUFHVixJQUFSO0FBQ0FXLE1BQUFBLGNBQWMsR0FBRyxJQUFqQjtBQUNEO0FBQ0Y7O0FBQ0QsU0FBTztBQUNMRixJQUFBQSxJQURLO0FBRUxDLElBQUFBLEtBRks7QUFHTEMsSUFBQUE7QUFISyxHQUFQO0FBS0QsQ0F6R0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBvZmZzZXRUb0N1cnNvciwgY3Vyc29yVG9PZmZzZXQgfSBmcm9tICdncmFwaHFsLXJlbGF5JztcbmltcG9ydCByZXN0IGZyb20gJy4uLy4uL3Jlc3QnO1xuaW1wb3J0IHsgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvcXVlcnknO1xuXG5jb25zdCBuZWVkVG9HZXRBbGxLZXlzID0gKGZpZWxkcywga2V5cykgPT5cbiAga2V5c1xuICAgID8gISFrZXlzLnNwbGl0KCcsJykuZmluZChrZXlOYW1lID0+ICFmaWVsZHNba2V5TmFtZS5zcGxpdCgnLicpWzBdXSlcbiAgICA6IHRydWU7XG5cbmNvbnN0IGdldE9iamVjdCA9IGFzeW5jIChcbiAgY2xhc3NOYW1lLFxuICBvYmplY3RJZCxcbiAga2V5cyxcbiAgaW5jbHVkZSxcbiAgcmVhZFByZWZlcmVuY2UsXG4gIGluY2x1ZGVSZWFkUHJlZmVyZW5jZSxcbiAgY29uZmlnLFxuICBhdXRoLFxuICBpbmZvLFxuICBwYXJzZUNsYXNzXG4pID0+IHtcbiAgY29uc3Qgb3B0aW9ucyA9IHt9O1xuICBpZiAoIW5lZWRUb0dldEFsbEtleXMocGFyc2VDbGFzcy5maWVsZHMsIGtleXMpKSB7XG4gICAgb3B0aW9ucy5rZXlzID0ga2V5cztcbiAgfVxuICBpZiAoaW5jbHVkZSkge1xuICAgIG9wdGlvbnMuaW5jbHVkZSA9IGluY2x1ZGU7XG4gICAgaWYgKGluY2x1ZGVSZWFkUHJlZmVyZW5jZSkge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPSBpbmNsdWRlUmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICB9XG4gIGlmIChyZWFkUHJlZmVyZW5jZSkge1xuICAgIG9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSByZWFkUHJlZmVyZW5jZTtcbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVzdC5nZXQoXG4gICAgY29uZmlnLFxuICAgIGF1dGgsXG4gICAgY2xhc3NOYW1lLFxuICAgIG9iamVjdElkLFxuICAgIG9wdGlvbnMsXG4gICAgaW5mby5jbGllbnRTREtcbiAgKTtcblxuICBpZiAoIXJlc3BvbnNlLnJlc3VsdHMgfHwgcmVzcG9uc2UucmVzdWx0cy5sZW5ndGggPT0gMCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnT2JqZWN0IG5vdCBmb3VuZC4nKTtcbiAgfVxuXG4gIGNvbnN0IG9iamVjdCA9IHJlc3BvbnNlLnJlc3VsdHNbMF07XG4gIGlmIChjbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBkZWxldGUgb2JqZWN0LnNlc3Npb25Ub2tlbjtcbiAgfVxuICByZXR1cm4gb2JqZWN0O1xufTtcblxuY29uc3QgZmluZE9iamVjdHMgPSBhc3luYyAoXG4gIGNsYXNzTmFtZSxcbiAgd2hlcmUsXG4gIG9yZGVyLFxuICBza2lwSW5wdXQsXG4gIGZpcnN0LFxuICBhZnRlcixcbiAgbGFzdCxcbiAgYmVmb3JlLFxuICBrZXlzLFxuICBpbmNsdWRlLFxuICBpbmNsdWRlQWxsLFxuICByZWFkUHJlZmVyZW5jZSxcbiAgaW5jbHVkZVJlYWRQcmVmZXJlbmNlLFxuICBzdWJxdWVyeVJlYWRQcmVmZXJlbmNlLFxuICBjb25maWcsXG4gIGF1dGgsXG4gIGluZm8sXG4gIHNlbGVjdGVkRmllbGRzLFxuICBwYXJzZUNsYXNzZXNcbikgPT4ge1xuICBpZiAoIXdoZXJlKSB7XG4gICAgd2hlcmUgPSB7fTtcbiAgfVxuICB0cmFuc2Zvcm1RdWVyeUlucHV0VG9QYXJzZSh3aGVyZSwgY2xhc3NOYW1lLCBwYXJzZUNsYXNzZXMpO1xuICBjb25zdCBza2lwQW5kTGltaXRDYWxjdWxhdGlvbiA9IGNhbGN1bGF0ZVNraXBBbmRMaW1pdChcbiAgICBza2lwSW5wdXQsXG4gICAgZmlyc3QsXG4gICAgYWZ0ZXIsXG4gICAgbGFzdCxcbiAgICBiZWZvcmUsXG4gICAgY29uZmlnLm1heExpbWl0XG4gICk7XG4gIGxldCB7IHNraXAgfSA9IHNraXBBbmRMaW1pdENhbGN1bGF0aW9uO1xuICBjb25zdCB7IGxpbWl0LCBuZWVkVG9QcmVDb3VudCB9ID0gc2tpcEFuZExpbWl0Q2FsY3VsYXRpb247XG4gIGxldCBwcmVDb3VudCA9IHVuZGVmaW5lZDtcbiAgaWYgKG5lZWRUb1ByZUNvdW50KSB7XG4gICAgY29uc3QgcHJlQ291bnRPcHRpb25zID0ge1xuICAgICAgbGltaXQ6IDAsXG4gICAgICBjb3VudDogdHJ1ZSxcbiAgICB9O1xuICAgIGlmIChyZWFkUHJlZmVyZW5jZSkge1xuICAgICAgcHJlQ291bnRPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gcmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIGlmIChPYmplY3Qua2V5cyh3aGVyZSkubGVuZ3RoID4gMCAmJiBzdWJxdWVyeVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgICBwcmVDb3VudE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IHN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIHByZUNvdW50ID0gKFxuICAgICAgYXdhaXQgcmVzdC5maW5kKFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGF1dGgsXG4gICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgd2hlcmUsXG4gICAgICAgIHByZUNvdW50T3B0aW9ucyxcbiAgICAgICAgaW5mby5jbGllbnRTREtcbiAgICAgIClcbiAgICApLmNvdW50O1xuICAgIGlmICgoc2tpcCB8fCAwKSArIGxpbWl0IDwgcHJlQ291bnQpIHtcbiAgICAgIHNraXAgPSBwcmVDb3VudCAtIGxpbWl0O1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG9wdGlvbnMgPSB7fTtcblxuICBpZiAoXG4gICAgc2VsZWN0ZWRGaWVsZHMuZmluZChcbiAgICAgIGZpZWxkID0+IGZpZWxkLnN0YXJ0c1dpdGgoJ2VkZ2VzLicpIHx8IGZpZWxkLnN0YXJ0c1dpdGgoJ3BhZ2VJbmZvLicpXG4gICAgKVxuICApIHtcbiAgICBpZiAobGltaXQgfHwgbGltaXQgPT09IDApIHtcbiAgICAgIG9wdGlvbnMubGltaXQgPSBsaW1pdDtcbiAgICB9IGVsc2Uge1xuICAgICAgb3B0aW9ucy5saW1pdCA9IDEwMDtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMubGltaXQgIT09IDApIHtcbiAgICAgIGlmIChvcmRlcikge1xuICAgICAgICBvcHRpb25zLm9yZGVyID0gb3JkZXI7XG4gICAgICB9XG4gICAgICBpZiAoc2tpcCkge1xuICAgICAgICBvcHRpb25zLnNraXAgPSBza2lwO1xuICAgICAgfVxuICAgICAgaWYgKGNvbmZpZy5tYXhMaW1pdCAmJiBvcHRpb25zLmxpbWl0ID4gY29uZmlnLm1heExpbWl0KSB7XG4gICAgICAgIC8vIFNpbGVudGx5IHJlcGxhY2UgdGhlIGxpbWl0IG9uIHRoZSBxdWVyeSB3aXRoIHRoZSBtYXggY29uZmlndXJlZFxuICAgICAgICBvcHRpb25zLmxpbWl0ID0gY29uZmlnLm1heExpbWl0O1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICAhbmVlZFRvR2V0QWxsS2V5cyhcbiAgICAgICAgICBwYXJzZUNsYXNzZXMuZmluZChcbiAgICAgICAgICAgICh7IGNsYXNzTmFtZTogcGFyc2VDbGFzc05hbWUgfSkgPT4gY2xhc3NOYW1lID09PSBwYXJzZUNsYXNzTmFtZVxuICAgICAgICAgICkuZmllbGRzLFxuICAgICAgICAgIGtleXNcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIG9wdGlvbnMua2V5cyA9IGtleXM7XG4gICAgICB9XG4gICAgICBpZiAoaW5jbHVkZUFsbCA9PT0gdHJ1ZSkge1xuICAgICAgICBvcHRpb25zLmluY2x1ZGVBbGwgPSBpbmNsdWRlQWxsO1xuICAgICAgfVxuICAgICAgaWYgKCFvcHRpb25zLmluY2x1ZGVBbGwgJiYgaW5jbHVkZSkge1xuICAgICAgICBvcHRpb25zLmluY2x1ZGUgPSBpbmNsdWRlO1xuICAgICAgfVxuICAgICAgaWYgKChvcHRpb25zLmluY2x1ZGVBbGwgfHwgb3B0aW9ucy5pbmNsdWRlKSAmJiBpbmNsdWRlUmVhZFByZWZlcmVuY2UpIHtcbiAgICAgICAgb3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPSBpbmNsdWRlUmVhZFByZWZlcmVuY2U7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIG9wdGlvbnMubGltaXQgPSAwO1xuICB9XG5cbiAgaWYgKFxuICAgIChzZWxlY3RlZEZpZWxkcy5pbmNsdWRlcygnY291bnQnKSB8fFxuICAgICAgc2VsZWN0ZWRGaWVsZHMuaW5jbHVkZXMoJ3BhZ2VJbmZvLmhhc1ByZXZpb3VzUGFnZScpIHx8XG4gICAgICBzZWxlY3RlZEZpZWxkcy5pbmNsdWRlcygncGFnZUluZm8uaGFzTmV4dFBhZ2UnKSkgJiZcbiAgICAhbmVlZFRvUHJlQ291bnRcbiAgKSB7XG4gICAgb3B0aW9ucy5jb3VudCA9IHRydWU7XG4gIH1cblxuICBpZiAocmVhZFByZWZlcmVuY2UpIHtcbiAgICBvcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gcmVhZFByZWZlcmVuY2U7XG4gIH1cbiAgaWYgKE9iamVjdC5rZXlzKHdoZXJlKS5sZW5ndGggPiAwICYmIHN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICBvcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPSBzdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgbGV0IHJlc3VsdHMsIGNvdW50O1xuICBpZiAob3B0aW9ucy5jb3VudCB8fCAhb3B0aW9ucy5saW1pdCB8fCAob3B0aW9ucy5saW1pdCAmJiBvcHRpb25zLmxpbWl0ID4gMCkpIHtcbiAgICBjb25zdCBmaW5kUmVzdWx0ID0gYXdhaXQgcmVzdC5maW5kKFxuICAgICAgY29uZmlnLFxuICAgICAgYXV0aCxcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHdoZXJlLFxuICAgICAgb3B0aW9ucyxcbiAgICAgIGluZm8uY2xpZW50U0RLXG4gICAgKTtcbiAgICByZXN1bHRzID0gZmluZFJlc3VsdC5yZXN1bHRzO1xuICAgIGNvdW50ID0gZmluZFJlc3VsdC5jb3VudDtcbiAgfVxuXG4gIGxldCBlZGdlcyA9IG51bGw7XG4gIGxldCBwYWdlSW5mbyA9IG51bGw7XG4gIGlmIChyZXN1bHRzKSB7XG4gICAgZWRnZXMgPSByZXN1bHRzLm1hcCgocmVzdWx0LCBpbmRleCkgPT4gKHtcbiAgICAgIGN1cnNvcjogb2Zmc2V0VG9DdXJzb3IoKHNraXAgfHwgMCkgKyBpbmRleCksXG4gICAgICBub2RlOiByZXN1bHQsXG4gICAgfSkpO1xuXG4gICAgcGFnZUluZm8gPSB7XG4gICAgICBoYXNQcmV2aW91c1BhZ2U6XG4gICAgICAgICgocHJlQ291bnQgJiYgcHJlQ291bnQgPiAwKSB8fCAoY291bnQgJiYgY291bnQgPiAwKSkgJiZcbiAgICAgICAgc2tpcCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHNraXAgPiAwLFxuICAgICAgc3RhcnRDdXJzb3I6IG9mZnNldFRvQ3Vyc29yKHNraXAgfHwgMCksXG4gICAgICBlbmRDdXJzb3I6IG9mZnNldFRvQ3Vyc29yKChza2lwIHx8IDApICsgKHJlc3VsdHMubGVuZ3RoIHx8IDEpIC0gMSksXG4gICAgICBoYXNOZXh0UGFnZTogKHByZUNvdW50IHx8IGNvdW50KSA+IChza2lwIHx8IDApICsgcmVzdWx0cy5sZW5ndGgsXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZWRnZXMsXG4gICAgcGFnZUluZm8sXG4gICAgY291bnQ6IHByZUNvdW50IHx8IGNvdW50LFxuICB9O1xufTtcblxuY29uc3QgY2FsY3VsYXRlU2tpcEFuZExpbWl0ID0gKFxuICBza2lwSW5wdXQsXG4gIGZpcnN0LFxuICBhZnRlcixcbiAgbGFzdCxcbiAgYmVmb3JlLFxuICBtYXhMaW1pdFxuKSA9PiB7XG4gIGxldCBza2lwID0gdW5kZWZpbmVkO1xuICBsZXQgbGltaXQgPSB1bmRlZmluZWQ7XG4gIGxldCBuZWVkVG9QcmVDb3VudCA9IGZhbHNlO1xuXG4gIC8vIFZhbGlkYXRlcyB0aGUgc2tpcCBpbnB1dFxuICBpZiAoc2tpcElucHV0IHx8IHNraXBJbnB1dCA9PT0gMCkge1xuICAgIGlmIChza2lwSW5wdXQgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICdTa2lwIHNob3VsZCBiZSBhIHBvc2l0aXZlIG51bWJlcidcbiAgICAgICk7XG4gICAgfVxuICAgIHNraXAgPSBza2lwSW5wdXQ7XG4gIH1cblxuICAvLyBWYWxpZGF0ZXMgdGhlIGFmdGVyIHBhcmFtXG4gIGlmIChhZnRlcikge1xuICAgIGFmdGVyID0gY3Vyc29yVG9PZmZzZXQoYWZ0ZXIpO1xuICAgIGlmICgoIWFmdGVyICYmIGFmdGVyICE9PSAwKSB8fCBhZnRlciA8IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgJ0FmdGVyIGlzIG5vdCBhIHZhbGlkIGN1cnNvcidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gSWYgc2tpcCBhbmQgYWZ0ZXIgYXJlIHBhc3NlZCwgYSBuZXcgc2tpcCBpcyBjYWxjdWxhdGVkIGJ5IGFkZGluZyB0aGVtXG4gICAgc2tpcCA9IChza2lwIHx8IDApICsgKGFmdGVyICsgMSk7XG4gIH1cblxuICAvLyBWYWxpZGF0ZXMgdGhlIGZpcnN0IHBhcmFtXG4gIGlmIChmaXJzdCB8fCBmaXJzdCA9PT0gMCkge1xuICAgIGlmIChmaXJzdCA8IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgJ0ZpcnN0IHNob3VsZCBiZSBhIHBvc2l0aXZlIG51bWJlcidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gVGhlIGZpcnN0IHBhcmFtIGlzIHRyYW5zbGF0ZWQgdG8gdGhlIGxpbWl0IHBhcmFtIG9mIHRoZSBQYXJzZSBsZWdhY3kgQVBJXG4gICAgbGltaXQgPSBmaXJzdDtcbiAgfVxuXG4gIC8vIFZhbGlkYXRlcyB0aGUgYmVmb3JlIHBhcmFtXG4gIGlmIChiZWZvcmUgfHwgYmVmb3JlID09PSAwKSB7XG4gICAgLy8gVGhpcyBtZXRob2QgY29udmVydHMgdGhlIGN1cnNvciB0byB0aGUgaW5kZXggb2YgdGhlIG9iamVjdFxuICAgIGJlZm9yZSA9IGN1cnNvclRvT2Zmc2V0KGJlZm9yZSk7XG4gICAgaWYgKCghYmVmb3JlICYmIGJlZm9yZSAhPT0gMCkgfHwgYmVmb3JlIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAnQmVmb3JlIGlzIG5vdCBhIHZhbGlkIGN1cnNvcidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKChza2lwIHx8IDApID49IGJlZm9yZSkge1xuICAgICAgLy8gSWYgdGhlIGJlZm9yZSBpbmRleCBpcyBsZXNzIHRoZW4gdGhlIHNraXAsIG5vIG9iamVjdHMgd2lsbCBiZSByZXR1cm5lZFxuICAgICAgbGltaXQgPSAwO1xuICAgIH0gZWxzZSBpZiAoKCFsaW1pdCAmJiBsaW1pdCAhPT0gMCkgfHwgKHNraXAgfHwgMCkgKyBsaW1pdCA+IGJlZm9yZSkge1xuICAgICAgLy8gSWYgdGhlcmUgaXMgbm8gbGltaXQgc2V0LCB0aGUgbGltaXQgaXMgY2FsY3VsYXRlZC4gT3IsIGlmIHRoZSBsaW1pdCAocGx1cyBza2lwKSBpcyBiaWdnZXIgdGhhbiB0aGUgYmVmb3JlIGluZGV4LCB0aGUgbmV3IGxpbWl0IGlzIHNldC5cbiAgICAgIGxpbWl0ID0gYmVmb3JlIC0gKHNraXAgfHwgMCk7XG4gICAgfVxuICB9XG5cbiAgLy8gVmFsaWRhdGVzIHRoZSBsYXN0IHBhcmFtXG4gIGlmIChsYXN0IHx8IGxhc3QgPT09IDApIHtcbiAgICBpZiAobGFzdCA8IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgJ0xhc3Qgc2hvdWxkIGJlIGEgcG9zaXRpdmUgbnVtYmVyJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAobGFzdCA+IG1heExpbWl0KSB7XG4gICAgICAvLyBMYXN0IGNhbid0IGJlIGJpZ2dlciB0aGFuIFBhcnNlIHNlcnZlciBtYXhMaW1pdCBjb25maWcuXG4gICAgICBsYXN0ID0gbWF4TGltaXQ7XG4gICAgfVxuXG4gICAgaWYgKGxpbWl0IHx8IGxpbWl0ID09PSAwKSB7XG4gICAgICAvLyBJZiB0aGVyZSBpcyBhIHByZXZpb3VzIGxpbWl0IHNldCwgaXQgbWF5IGJlIGFkanVzdGVkXG4gICAgICBpZiAobGFzdCA8IGxpbWl0KSB7XG4gICAgICAgIC8vIGlmIGxhc3QgaXMgbGVzcyB0aGFuIHRoZSBjdXJyZW50IGxpbWl0XG4gICAgICAgIHNraXAgPSAoc2tpcCB8fCAwKSArIChsaW1pdCAtIGxhc3QpOyAvLyBUaGUgc2tpcCBpcyBhZGp1c3RlZFxuICAgICAgICBsaW1pdCA9IGxhc3Q7IC8vIHRoZSBsaW1pdCBpcyBhZGp1c3RlZFxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobGFzdCA9PT0gMCkge1xuICAgICAgLy8gTm8gb2JqZWN0cyB3aWxsIGJlIHJldHVybmVkXG4gICAgICBsaW1pdCA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE5vIHByZXZpb3VzIGxpbWl0IHNldCwgdGhlIGxpbWl0IHdpbGwgYmUgZXF1YWwgdG8gbGFzdCBhbmQgcHJlIGNvdW50IGlzIG5lZWRlZC5cbiAgICAgIGxpbWl0ID0gbGFzdDtcbiAgICAgIG5lZWRUb1ByZUNvdW50ID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBza2lwLFxuICAgIGxpbWl0LFxuICAgIG5lZWRUb1ByZUNvdW50LFxuICB9O1xufTtcblxuZXhwb3J0IHsgZ2V0T2JqZWN0LCBmaW5kT2JqZWN0cywgY2FsY3VsYXRlU2tpcEFuZExpbWl0LCBuZWVkVG9HZXRBbGxLZXlzIH07XG4iXX0= \ 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..47abe0e5e7 --- /dev/null +++ b/lib/GraphQL/loaders/defaultGraphQLTypes.js @@ -0,0 +1,1265 @@ +"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.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.ID_WHERE_INPUT = exports.notInQueryKey = exports.inQueryKey = exports.options = exports.matchesRegex = 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.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.GLOBAL_OR_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_INPUT = exports.FILE_INFO = exports.FILE = exports.SELECT_INPUT = exports.SUBQUERY_INPUT = 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 FILE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'FileInput', + fields: { + file: { + description: 'A File Scalar can be an url or a FileInfo object.', + type: FILE + }, + upload: { + description: 'Use this field if you want to create a new file.', + type: _graphqlUpload.GraphQLUpload + } + } +}); +exports.FILE_INPUT = FILE_INPUT; +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 GLOBAL_OR_OBJECT_ID_ATT = { + description: 'This is the object id. You can use either the global or the object id.', + type: OBJECT_ID +}; +exports.GLOBAL_OR_OBJECT_ID_ATT = GLOBAL_OR_OBJECT_ID_ATT; +const OBJECT_ID_ATT = { + description: 'This is the object id.', + type: OBJECT_ID +}; +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 = { + objectId: 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, { + ACL: { + type: new _graphql.GraphQLNonNull(ACL), + resolve: ({ + ACL + }) => ACL ? ACL : { + '*': { + read: true, + write: true + } + } + } +}); + +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 current 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 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 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 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 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 ID_WHERE_INPUT = new _graphql.GraphQLInputObjectType({ + name: 'IdWhereInput', + description: 'The IdWhereInput input type is used in operations that involve filtering objects by an id.', + fields: { + equalTo: equalTo(_graphql.GraphQLID), + notEqualTo: notEqualTo(_graphql.GraphQLID), + lessThan: lessThan(_graphql.GraphQLID), + lessThanOrEqualTo: lessThanOrEqualTo(_graphql.GraphQLID), + greaterThan: greaterThan(_graphql.GraphQLID), + greaterThanOrEqualTo: greaterThanOrEqualTo(_graphql.GraphQLID), + in: inOp(_graphql.GraphQLID), + notIn: notIn(_graphql.GraphQLID), + exists, + inQueryKey, + notInQueryKey + } +}); +exports.ID_WHERE_INPUT = ID_WHERE_INPUT; +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, + matchesRegex, + options, + text: { + description: 'This is the $text operator to specify a full text search constraint.', + type: TEXT_INPUT + }, + inQueryKey, + notInQueryKey + } +}); +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, + 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) + }, + inQueryKey, + notInQueryKey + } +}); +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, + matchesRegex, + options, + inQueryKey, + notInQueryKey + } +}); +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 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(FILE_INPUT, 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(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(ID_WHERE_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(ELEMENT, 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); + parseGraphQLSchema.addGraphQLType(SUBQUERY_INPUT, true); + parseGraphQLSchema.addGraphQLType(SELECT_INPUT, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcy5qcyJdLCJuYW1lcyI6WyJUeXBlVmFsaWRhdGlvbkVycm9yIiwiRXJyb3IiLCJjb25zdHJ1Y3RvciIsInZhbHVlIiwidHlwZSIsInBhcnNlU3RyaW5nVmFsdWUiLCJwYXJzZUludFZhbHVlIiwiaW50IiwiTnVtYmVyIiwiaXNJbnRlZ2VyIiwicGFyc2VGbG9hdFZhbHVlIiwiZmxvYXQiLCJpc05hTiIsInBhcnNlQm9vbGVhblZhbHVlIiwicGFyc2VWYWx1ZSIsImtpbmQiLCJLaW5kIiwiU1RSSU5HIiwiSU5UIiwiRkxPQVQiLCJCT09MRUFOIiwiTElTVCIsInBhcnNlTGlzdFZhbHVlcyIsInZhbHVlcyIsIk9CSkVDVCIsInBhcnNlT2JqZWN0RmllbGRzIiwiZmllbGRzIiwiQXJyYXkiLCJpc0FycmF5IiwibWFwIiwicmVkdWNlIiwib2JqZWN0IiwiZmllbGQiLCJuYW1lIiwiQU5ZIiwiR3JhcGhRTFNjYWxhclR5cGUiLCJkZXNjcmlwdGlvbiIsInNlcmlhbGl6ZSIsInBhcnNlTGl0ZXJhbCIsImFzdCIsInBhcnNlRGF0ZUlzb1ZhbHVlIiwiZGF0ZSIsIkRhdGUiLCJzZXJpYWxpemVEYXRlSXNvIiwidG9VVENTdHJpbmciLCJwYXJzZURhdGVJc29MaXRlcmFsIiwiREFURSIsIl9fdHlwZSIsImlzbyIsImZpbmQiLCJCWVRFUyIsImJhc2U2NCIsInBhcnNlRmlsZVZhbHVlIiwidXJsIiwidW5kZWZpbmVkIiwiRklMRSIsIkZJTEVfSU5GTyIsIkdyYXBoUUxPYmplY3RUeXBlIiwiR3JhcGhRTE5vbk51bGwiLCJHcmFwaFFMU3RyaW5nIiwiRklMRV9JTlBVVCIsIkdyYXBoUUxJbnB1dE9iamVjdFR5cGUiLCJmaWxlIiwidXBsb2FkIiwiR3JhcGhRTFVwbG9hZCIsIkdFT19QT0lOVF9GSUVMRFMiLCJsYXRpdHVkZSIsIkdyYXBoUUxGbG9hdCIsImxvbmdpdHVkZSIsIkdFT19QT0lOVF9JTlBVVCIsIkdFT19QT0lOVCIsIlBPTFlHT05fSU5QVVQiLCJHcmFwaFFMTGlzdCIsIlBPTFlHT04iLCJVU0VSX0FDTF9JTlBVVCIsInVzZXJJZCIsIkdyYXBoUUxJRCIsInJlYWQiLCJHcmFwaFFMQm9vbGVhbiIsIndyaXRlIiwiUk9MRV9BQ0xfSU5QVVQiLCJyb2xlTmFtZSIsIlBVQkxJQ19BQ0xfSU5QVVQiLCJBQ0xfSU5QVVQiLCJ1c2VycyIsInJvbGVzIiwicHVibGljIiwiVVNFUl9BQ0wiLCJST0xFX0FDTCIsIlBVQkxJQ19BQ0wiLCJBQ0wiLCJyZXNvbHZlIiwicCIsIk9iamVjdCIsImtleXMiLCJmb3JFYWNoIiwicnVsZSIsImluZGV4T2YiLCJwdXNoIiwibGVuZ3RoIiwicmVwbGFjZSIsIk9CSkVDVF9JRCIsIkNMQVNTX05BTUVfQVRUIiwiR0xPQkFMX09SX09CSkVDVF9JRF9BVFQiLCJPQkpFQ1RfSURfQVRUIiwiQ1JFQVRFRF9BVF9BVFQiLCJVUERBVEVEX0FUX0FUVCIsIklOUFVUX0ZJRUxEUyIsIkNSRUFURV9SRVNVTFRfRklFTERTIiwib2JqZWN0SWQiLCJjcmVhdGVkQXQiLCJVUERBVEVfUkVTVUxUX0ZJRUxEUyIsInVwZGF0ZWRBdCIsIlBBUlNFX09CSkVDVF9GSUVMRFMiLCJQQVJTRV9PQkpFQ1QiLCJHcmFwaFFMSW50ZXJmYWNlVHlwZSIsIlNFU1NJT05fVE9LRU5fQVRUIiwiUkVBRF9QUkVGRVJFTkNFIiwiR3JhcGhRTEVudW1UeXBlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJSRUFEX1BSRUZFUkVOQ0VfQVRUIiwiSU5DTFVERV9SRUFEX1BSRUZFUkVOQ0VfQVRUIiwiU1VCUVVFUllfUkVBRF9QUkVGRVJFTkNFX0FUVCIsIlJFQURfT1BUSU9OU19JTlBVVCIsInJlYWRQcmVmZXJlbmNlIiwiaW5jbHVkZVJlYWRQcmVmZXJlbmNlIiwic3VicXVlcnlSZWFkUHJlZmVyZW5jZSIsIlJFQURfT1BUSU9OU19BVFQiLCJXSEVSRV9BVFQiLCJTS0lQX0FUVCIsIkdyYXBoUUxJbnQiLCJMSU1JVF9BVFQiLCJDT1VOVF9BVFQiLCJTRUFSQ0hfSU5QVVQiLCJ0ZXJtIiwibGFuZ3VhZ2UiLCJjYXNlU2Vuc2l0aXZlIiwiZGlhY3JpdGljU2Vuc2l0aXZlIiwiVEVYVF9JTlBVVCIsInNlYXJjaCIsIkJPWF9JTlBVVCIsImJvdHRvbUxlZnQiLCJ1cHBlclJpZ2h0IiwiV0lUSElOX0lOUFVUIiwiYm94IiwiQ0VOVEVSX1NQSEVSRV9JTlBVVCIsImNlbnRlciIsImRpc3RhbmNlIiwiR0VPX1dJVEhJTl9JTlBVVCIsInBvbHlnb24iLCJjZW50ZXJTcGhlcmUiLCJHRU9fSU5URVJTRUNUU19JTlBVVCIsInBvaW50IiwiZXF1YWxUbyIsIm5vdEVxdWFsVG8iLCJsZXNzVGhhbiIsImxlc3NUaGFuT3JFcXVhbFRvIiwiZ3JlYXRlclRoYW4iLCJncmVhdGVyVGhhbk9yRXF1YWxUbyIsImluT3AiLCJub3RJbiIsImV4aXN0cyIsIm1hdGNoZXNSZWdleCIsIm9wdGlvbnMiLCJTVUJRVUVSWV9JTlBVVCIsImNsYXNzTmFtZSIsIndoZXJlIiwiYXNzaWduIiwiU0VMRUNUX0lOUFVUIiwicXVlcnkiLCJrZXkiLCJpblF1ZXJ5S2V5Iiwibm90SW5RdWVyeUtleSIsIklEX1dIRVJFX0lOUFVUIiwiaW4iLCJTVFJJTkdfV0hFUkVfSU5QVVQiLCJ0ZXh0IiwiTlVNQkVSX1dIRVJFX0lOUFVUIiwiQk9PTEVBTl9XSEVSRV9JTlBVVCIsIkFSUkFZX1dIRVJFX0lOUFVUIiwiY29udGFpbmVkQnkiLCJjb250YWlucyIsIktFWV9WQUxVRV9JTlBVVCIsIk9CSkVDVF9XSEVSRV9JTlBVVCIsIkRBVEVfV0hFUkVfSU5QVVQiLCJCWVRFU19XSEVSRV9JTlBVVCIsIkZJTEVfV0hFUkVfSU5QVVQiLCJHRU9fUE9JTlRfV0hFUkVfSU5QVVQiLCJuZWFyU3BoZXJlIiwibWF4RGlzdGFuY2UiLCJtYXhEaXN0YW5jZUluUmFkaWFucyIsIm1heERpc3RhbmNlSW5NaWxlcyIsIm1heERpc3RhbmNlSW5LaWxvbWV0ZXJzIiwid2l0aGluIiwiZ2VvV2l0aGluIiwiUE9MWUdPTl9XSEVSRV9JTlBVVCIsImdlb0ludGVyc2VjdHMiLCJFTEVNRU5UIiwiQVJSQVlfUkVTVUxUIiwibG9hZEFycmF5UmVzdWx0IiwicGFyc2VHcmFwaFFMU2NoZW1hIiwicGFyc2VDbGFzc2VzIiwiY2xhc3NUeXBlcyIsImZpbHRlciIsInBhcnNlQ2xhc3MiLCJwYXJzZUNsYXNzVHlwZXMiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIiwiR3JhcGhRTFVuaW9uVHlwZSIsInR5cGVzIiwicmVzb2x2ZVR5cGUiLCJncmFwaFFMVHlwZXMiLCJsb2FkIiwiYWRkR3JhcGhRTFR5cGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFnQkE7Ozs7Ozs7O0FBRUEsTUFBTUEsbUJBQU4sU0FBa0NDLEtBQWxDLENBQXdDO0FBQ3RDQyxFQUFBQSxXQUFXLENBQUNDLEtBQUQsRUFBUUMsSUFBUixFQUFjO0FBQ3ZCLFVBQU8sR0FBRUQsS0FBTSxtQkFBa0JDLElBQUssRUFBdEM7QUFDRDs7QUFIcUM7Ozs7QUFNeEMsTUFBTUMsZ0JBQWdCLEdBQUdGLEtBQUssSUFBSTtBQUNoQyxNQUFJLE9BQU9BLEtBQVAsS0FBaUIsUUFBckIsRUFBK0I7QUFDN0IsV0FBT0EsS0FBUDtBQUNEOztBQUVELFFBQU0sSUFBSUgsbUJBQUosQ0FBd0JHLEtBQXhCLEVBQStCLFFBQS9CLENBQU47QUFDRCxDQU5EOzs7O0FBUUEsTUFBTUcsYUFBYSxHQUFHSCxLQUFLLElBQUk7QUFDN0IsTUFBSSxPQUFPQSxLQUFQLEtBQWlCLFFBQXJCLEVBQStCO0FBQzdCLFVBQU1JLEdBQUcsR0FBR0MsTUFBTSxDQUFDTCxLQUFELENBQWxCOztBQUNBLFFBQUlLLE1BQU0sQ0FBQ0MsU0FBUCxDQUFpQkYsR0FBakIsQ0FBSixFQUEyQjtBQUN6QixhQUFPQSxHQUFQO0FBQ0Q7QUFDRjs7QUFFRCxRQUFNLElBQUlQLG1C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QUFrQzVDLFlBQWxDLEVBQWdELElBQWhEO0FBQ0QsQ0E1Q0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBLaW5kLFxuICBHcmFwaFFMTm9uTnVsbCxcbiAgR3JhcGhRTFNjYWxhclR5cGUsXG4gIEdyYXBoUUxJRCxcbiAgR3JhcGhRTFN0cmluZyxcbiAgR3JhcGhRTE9iamVjdFR5cGUsXG4gIEdyYXBoUUxJbnRlcmZhY2VUeXBlLFxuICBHcmFwaFFMRW51bVR5cGUsXG4gIEdyYXBoUUxJbnQsXG4gIEdyYXBoUUxGbG9hdCxcbiAgR3JhcGhRTExpc3QsXG4gIEdyYXBoUUxJbnB1dE9iamVjdFR5cGUsXG4gIEdyYXBoUUxCb29sZWFuLFxuICBHcmFwaFFMVW5pb25UeXBlLFxufSBmcm9tICdncmFwaHFsJztcbmltcG9ydCB7IEdyYXBoUUxVcGxvYWQgfSBmcm9tICdncmFwaHFsLXVwbG9hZCc7XG5cbmNsYXNzIFR5cGVWYWxpZGF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKHZhbHVlLCB0eXBlKSB7XG4gICAgc3VwZXIoYCR7dmFsdWV9IGlzIG5vdCBhIHZhbGlkICR7dHlwZX1gKTtcbiAgfVxufVxuXG5jb25zdCBwYXJzZVN0cmluZ1ZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnU3RyaW5nJyk7XG59O1xuXG5jb25zdCBwYXJzZUludFZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IGludCA9IE51bWJlcih2YWx1ZSk7XG4gICAgaWYgKE51bWJlci5pc0ludGVnZXIoaW50KSkge1xuICAgICAgcmV0dXJuIGludDtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0ludCcpO1xufTtcblxuY29uc3QgcGFyc2VGbG9hdFZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IGZsb2F0ID0gTnVtYmVyKHZhbHVlKTtcbiAgICBpZiAoIWlzTmFOKGZsb2F0KSkge1xuICAgICAgcmV0dXJuIGZsb2F0O1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnRmxvYXQnKTtcbn07XG5cbmNvbnN0IHBhcnNlQm9vbGVhblZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0Jvb2xlYW4nKTtcbn07XG5cbmNvbnN0IHBhcnNlVmFsdWUgPSB2YWx1ZSA9PiB7XG4gIHN3aXRjaCAodmFsdWUua2luZCkge1xuICAgIGNhc2UgS2luZC5TVFJJTkc6XG4gICAgICByZXR1cm4gcGFyc2VTdHJpbmdWYWx1ZSh2YWx1ZS52YWx1ZSk7XG5cbiAgICBjYXNlIEtpbmQuSU5UOlxuICAgICAgcmV0dXJuIHBhcnNlSW50VmFsdWUodmFsdWUudmFsdWUpO1xuXG4gICAgY2FzZSBLaW5kLkZMT0FUOlxuICAgICAgcmV0dXJuIHBhcnNlRmxvYXRWYWx1ZSh2YWx1ZS52YWx1ZSk7XG5cbiAgICBjYXNlIEtpbmQuQk9PTEVBTjpcbiAgICAgIHJldHVybiBwYXJzZUJvb2xlYW5WYWx1ZSh2YWx1ZS52YWx1ZSk7XG5cbiAgICBjYXNlIEtpbmQuTElTVDpcbiAgICAgIHJldHVybiBwYXJzZUxpc3RWYWx1ZXModmFsdWUudmFsdWVzKTtcblxuICAgIGNhc2UgS2luZC5PQkpFQ1Q6XG4gICAgICByZXR1cm4gcGFyc2VPYmplY3RGaWVsZHModmFsdWUuZmllbGRzKTtcblxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cbn07XG5cbmNvbnN0IHBhcnNlTGlzdFZhbHVlcyA9IHZhbHVlcyA9PiB7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlcykpIHtcbiAgICByZXR1cm4gdmFsdWVzLm1hcCh2YWx1ZSA9PiBwYXJzZVZhbHVlKHZhbHVlKSk7XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZXMsICdMaXN0Jyk7XG59O1xuXG5jb25zdCBwYXJzZU9iamVjdEZpZWxkcyA9IGZpZWxkcyA9PiB7XG4gIGlmIChBcnJheS5pc0FycmF5KGZpZWxkcykpIHtcbiAgICByZXR1cm4gZmllbGRzLnJlZHVjZShcbiAgICAgIChvYmplY3QsIGZpZWxkKSA9PiAoe1xuICAgICAgICAuLi5vYmplY3QsXG4gICAgICAgIFtmaWVsZC5uYW1lLnZhbHVlXTogcGFyc2VWYWx1ZShmaWVsZC52YWx1ZSksXG4gICAgICB9KSxcbiAgICAgIHt9XG4gICAgKTtcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKGZpZWxkcywgJ09iamVjdCcpO1xufTtcblxuY29uc3QgQU5ZID0gbmV3IEdyYXBoUUxTY2FsYXJUeXBlKHtcbiAgbmFtZTogJ0FueScsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgQW55IHNjYWxhciB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyBhbmQgdHlwZXMgdGhhdCBpbnZvbHZlIGFueSB0eXBlIG9mIHZhbHVlLicsXG4gIHBhcnNlVmFsdWU6IHZhbHVlID0+IHZhbHVlLFxuICBzZXJpYWxpemU6IHZhbHVlID0+IHZhbHVlLFxuICBwYXJzZUxpdGVyYWw6IGFzdCA9PiBwYXJzZVZhbHVlKGFzdCksXG59KTtcblxuY29uc3QgT0JKRUNUID0gbmV3IEdyYXBoUUxTY2FsYXJUeXBlKHtcbiAgbmFtZTogJ09iamVjdCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgT2JqZWN0IHNjYWxhciB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyBhbmQgdHlwZXMgdGhhdCBpbnZvbHZlIG9iamVjdHMuJyxcbiAgcGFyc2VWYWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdPYmplY3QnKTtcbiAgfSxcbiAgc2VyaWFsaXplKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ09iamVjdCcpO1xuICB9LFxuICBwYXJzZUxpdGVyYWwoYXN0KSB7XG4gICAgaWYgKGFzdC5raW5kID09PSBLaW5kLk9CSkVDVCkge1xuICAgICAgcmV0dXJuIHBhcnNlT2JqZWN0RmllbGRzKGFzdC5maWVsZHMpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKGFzdC5raW5kLCAnT2JqZWN0Jyk7XG4gIH0sXG59KTtcblxuY29uc3QgcGFyc2VEYXRlSXNvVmFsdWUgPSB2YWx1ZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICBpZiAoIWlzTmFOKGRhdGUpKSB7XG4gICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdEYXRlJyk7XG59O1xuXG5jb25zdCBzZXJpYWxpemVEYXRlSXNvID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnRvVVRDU3RyaW5nKCk7XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0RhdGUnKTtcbn07XG5cbmNvbnN0IHBhcnNlRGF0ZUlzb0xpdGVyYWwgPSBhc3QgPT4ge1xuICBpZiAoYXN0LmtpbmQgPT09IEtpbmQuU1RSSU5HKSB7XG4gICAgcmV0dXJuIHBhcnNlRGF0ZUlzb1ZhbHVlKGFzdC52YWx1ZSk7XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcihhc3Qua2luZCwgJ0RhdGUnKTtcbn07XG5cbmNvbnN0IERBVEUgPSBuZXcgR3JhcGhRTFNjYWxhclR5cGUoe1xuICBuYW1lOiAnRGF0ZScsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgRGF0ZSBzY2FsYXIgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgYW5kIHR5cGVzIHRoYXQgaW52b2x2ZSBkYXRlcy4nLFxuICBwYXJzZVZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBwYXJzZURhdGVJc29WYWx1ZSh2YWx1ZSksXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICB2YWx1ZS5fX3R5cGUgPT09ICdEYXRlJyAmJlxuICAgICAgdmFsdWUuaXNvXG4gICAgKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBfX3R5cGU6IHZhbHVlLl9fdHlwZSxcbiAgICAgICAgaXNvOiBwYXJzZURhdGVJc29WYWx1ZSh2YWx1ZS5pc28pLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0RhdGUnKTtcbiAgfSxcbiAgc2VyaWFsaXplKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICByZXR1cm4gc2VyaWFsaXplRGF0ZUlzbyh2YWx1ZSk7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHZhbHVlLl9fdHlwZSA9PT0gJ0RhdGUnICYmXG4gICAgICB2YWx1ZS5pc29cbiAgICApIHtcbiAgICAgIHJldHVybiBzZXJpYWxpemVEYXRlSXNvKHZhbHVlLmlzbyk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdEYXRlJyk7XG4gIH0sXG4gIHBhcnNlTGl0ZXJhbChhc3QpIHtcbiAgICBpZiAoYXN0LmtpbmQgPT09IEtpbmQuU1RSSU5HKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBwYXJzZURhdGVJc29MaXRlcmFsKGFzdCksXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAoYXN0LmtpbmQgPT09IEtpbmQuT0JKRUNUKSB7XG4gICAgICBjb25zdCBfX3R5cGUgPSBhc3QuZmllbGRzLmZpbmQoZmllbGQgPT4gZmllbGQubmFtZS52YWx1ZSA9PT0gJ19fdHlwZScpO1xuICAgICAgY29uc3QgaXNvID0gYXN0LmZpZWxkcy5maW5kKGZpZWxkID0+IGZpZWxkLm5hbWUudmFsdWUgPT09ICdpc28nKTtcbiAgICAgIGlmIChfX3R5cGUgJiYgX190eXBlLnZhbHVlICYmIF9fdHlwZS52YWx1ZS52YWx1ZSA9PT0gJ0RhdGUnICYmIGlzbykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIF9fdHlwZTogX190eXBlLnZhbHVlLnZhbHVlLFxuICAgICAgICAgIGlzbzogcGFyc2VEYXRlSXNvTGl0ZXJhbChpc28udmFsdWUpLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKGFzdC5raW5kLCAnRGF0ZScpO1xuICB9LFxufSk7XG5cbmNvbnN0IEJZVEVTID0gbmV3IEdyYXBoUUxTY2FsYXJUeXBlKHtcbiAgbmFtZTogJ0J5dGVzJyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBCeXRlcyBzY2FsYXIgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgYW5kIHR5cGVzIHRoYXQgaW52b2x2ZSBiYXNlIDY0IGJpbmFyeSBkYXRhLicsXG4gIHBhcnNlVmFsdWUodmFsdWUpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgX190eXBlOiAnQnl0ZXMnLFxuICAgICAgICBiYXNlNjQ6IHZhbHVlLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgdmFsdWUuX190eXBlID09PSAnQnl0ZXMnICYmXG4gICAgICB0eXBlb2YgdmFsdWUuYmFzZTY0ID09PSAnc3RyaW5nJ1xuICAgICkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnQnl0ZXMnKTtcbiAgfSxcbiAgc2VyaWFsaXplKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgdmFsdWUuX190eXBlID09PSAnQnl0ZXMnICYmXG4gICAgICB0eXBlb2YgdmFsdWUuYmFzZTY0ID09PSAnc3RyaW5nJ1xuICAgICkge1xuICAgICAgcmV0dXJuIHZhbHVlLmJhc2U2NDtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZVZhbGlkYXRpb25FcnJvcih2YWx1ZSwgJ0J5dGVzJyk7XG4gIH0sXG4gIHBhcnNlTGl0ZXJhbChhc3QpIHtcbiAgICBpZiAoYXN0LmtpbmQgPT09IEtpbmQuU1RSSU5HKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBfX3R5cGU6ICdCeXRlcycsXG4gICAgICAgIGJhc2U2NDogYXN0LnZhbHVlLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKGFzdC5raW5kID09PSBLaW5kLk9CSkVDVCkge1xuICAgICAgY29uc3QgX190eXBlID0gYXN0LmZpZWxkcy5maW5kKGZpZWxkID0+IGZpZWxkLm5hbWUudmFsdWUgPT09ICdfX3R5cGUnKTtcbiAgICAgIGNvbnN0IGJhc2U2NCA9IGFzdC5maWVsZHMuZmluZChmaWVsZCA9PiBmaWVsZC5uYW1lLnZhbHVlID09PSAnYmFzZTY0Jyk7XG4gICAgICBpZiAoXG4gICAgICAgIF9fdHlwZSAmJlxuICAgICAgICBfX3R5cGUudmFsdWUgJiZcbiAgICAgICAgX190eXBlLnZhbHVlLnZhbHVlID09PSAnQnl0ZXMnICYmXG4gICAgICAgIGJhc2U2NCAmJlxuICAgICAgICBiYXNlNjQudmFsdWUgJiZcbiAgICAgICAgdHlwZW9mIGJhc2U2NC52YWx1ZS52YWx1ZSA9PT0gJ3N0cmluZydcbiAgICAgICkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIF9fdHlwZTogX190eXBlLnZhbHVlLnZhbHVlLFxuICAgICAgICAgIGJhc2U2NDogYmFzZTY0LnZhbHVlLnZhbHVlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKGFzdC5raW5kLCAnQnl0ZXMnKTtcbiAgfSxcbn0pO1xuXG5jb25zdCBwYXJzZUZpbGVWYWx1ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4ge1xuICAgICAgX190eXBlOiAnRmlsZScsXG4gICAgICBuYW1lOiB2YWx1ZSxcbiAgICB9O1xuICB9IGVsc2UgaWYgKFxuICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICB2YWx1ZS5fX3R5cGUgPT09ICdGaWxlJyAmJlxuICAgIHR5cGVvZiB2YWx1ZS5uYW1lID09PSAnc3RyaW5nJyAmJlxuICAgICh2YWx1ZS51cmwgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgdmFsdWUudXJsID09PSAnc3RyaW5nJylcbiAgKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVWYWxpZGF0aW9uRXJyb3IodmFsdWUsICdGaWxlJyk7XG59O1xuXG5jb25zdCBGSUxFID0gbmV3IEdyYXBoUUxTY2FsYXJUeXBlKHtcbiAgbmFtZTogJ0ZpbGUnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEZpbGUgc2NhbGFyIHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIGFuZCB0eXBlcyB0aGF0IGludm9sdmUgZmlsZXMuJyxcbiAgcGFyc2VWYWx1ZTogcGFyc2VGaWxlVmFsdWUsXG4gIHNlcmlhbGl6ZTogdmFsdWUgPT4ge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHZhbHVlLl9fdHlwZSA9PT0gJ0ZpbGUnICYmXG4gICAgICB0eXBlb2YgdmFsdWUubmFtZSA9PT0gJ3N0cmluZycgJiZcbiAgICAgICh2YWx1ZS51cmwgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgdmFsdWUudXJsID09PSAnc3RyaW5nJylcbiAgICApIHtcbiAgICAgIHJldHVybiB2YWx1ZS5uYW1lO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKHZhbHVlLCAnRmlsZScpO1xuICB9LFxuICBwYXJzZUxpdGVyYWwoYXN0KSB7XG4gICAgaWYgKGFzdC5raW5kID09PSBLaW5kLlNUUklORykge1xuICAgICAgcmV0dXJuIHBhcnNlRmlsZVZhbHVlKGFzdC52YWx1ZSk7XG4gICAgfSBlbHNlIGlmIChhc3Qua2luZCA9PT0gS2luZC5PQkpFQ1QpIHtcbiAgICAgIGNvbnN0IF9fdHlwZSA9IGFzdC5maWVsZHMuZmluZChmaWVsZCA9PiBmaWVsZC5uYW1lLnZhbHVlID09PSAnX190eXBlJyk7XG4gICAgICBjb25zdCBuYW1lID0gYXN0LmZpZWxkcy5maW5kKGZpZWxkID0+IGZpZWxkLm5hbWUudmFsdWUgPT09ICduYW1lJyk7XG4gICAgICBjb25zdCB1cmwgPSBhc3QuZmllbGRzLmZpbmQoZmllbGQgPT4gZmllbGQubmFtZS52YWx1ZSA9PT0gJ3VybCcpO1xuICAgICAgaWYgKF9fdHlwZSAmJiBfX3R5cGUudmFsdWUgJiYgbmFtZSAmJiBuYW1lLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUZpbGVWYWx1ZSh7XG4gICAgICAgICAgX190eXBlOiBfX3R5cGUudmFsdWUudmFsdWUsXG4gICAgICAgICAgbmFtZTogbmFtZS52YWx1ZS52YWx1ZSxcbiAgICAgICAgICB1cmw6IHVybCAmJiB1cmwudmFsdWUgPyB1cmwudmFsdWUudmFsdWUgOiB1bmRlZmluZWQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBUeXBlVmFsaWRhdGlvbkVycm9yKGFzdC5raW5kLCAnRmlsZScpO1xuICB9LFxufSk7XG5cbmNvbnN0IEZJTEVfSU5GTyA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdGaWxlSW5mbycsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgRmlsZUluZm8gb2JqZWN0IHR5cGUgaXMgdXNlZCB0byByZXR1cm4gdGhlIGluZm9ybWF0aW9uIGFib3V0IGZpbGVzLicsXG4gIGZpZWxkczoge1xuICAgIG5hbWU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgZmlsZSBuYW1lLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFN0cmluZyksXG4gICAgfSxcbiAgICB1cmw6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgdXJsIGluIHdoaWNoIHRoZSBmaWxlIGNhbiBiZSBkb3dubG9hZGVkLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFN0cmluZyksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBGSUxFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnRmlsZUlucHV0JyxcbiAgZmllbGRzOiB7XG4gICAgZmlsZToge1xuICAgICAgZGVzY3JpcHRpb246ICdBIEZpbGUgU2NhbGFyIGNhbiBiZSBhbiB1cmwgb3IgYSBGaWxlSW5mbyBvYmplY3QuJyxcbiAgICAgIHR5cGU6IEZJTEUsXG4gICAgfSxcbiAgICB1cGxvYWQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVXNlIHRoaXMgZmllbGQgaWYgeW91IHdhbnQgdG8gY3JlYXRlIGEgbmV3IGZpbGUuJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxVcGxvYWQsXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBHRU9fUE9JTlRfRklFTERTID0ge1xuICBsYXRpdHVkZToge1xuICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgbGF0aXR1ZGUuJyxcbiAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEZsb2F0KSxcbiAgfSxcbiAgbG9uZ2l0dWRlOiB7XG4gICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBsb25naXR1ZGUuJyxcbiAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEZsb2F0KSxcbiAgfSxcbn07XG5cbmNvbnN0IEdFT19QT0lOVF9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ0dlb1BvaW50SW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEdlb1BvaW50SW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGlucHV0dGluZyBmaWVsZHMgb2YgdHlwZSBnZW8gcG9pbnQuJyxcbiAgZmllbGRzOiBHRU9fUE9JTlRfRklFTERTLFxufSk7XG5cbmNvbnN0IEdFT19QT0lOVCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdHZW9Qb2ludCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgR2VvUG9pbnQgb2JqZWN0IHR5cGUgaXMgdXNlZCB0byByZXR1cm4gdGhlIGluZm9ybWF0aW9uIGFib3V0IGdlbyBwb2ludCBmaWVsZHMuJyxcbiAgZmllbGRzOiBHRU9fUE9JTlRfRklFTERTLFxufSk7XG5cbmNvbnN0IFBPTFlHT05fSU5QVVQgPSBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKEdFT19QT0lOVF9JTlBVVCkpO1xuXG5jb25zdCBQT0xZR09OID0gbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChHRU9fUE9JTlQpKTtcblxuY29uc3QgVVNFUl9BQ0xfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdVc2VyQUNMSW5wdXQnLFxuICBkZXNjcmlwdGlvbjogJ0FsbG93IHRvIG1hbmFnZSB1c2VycyBpbiBBQ0wuJyxcbiAgZmllbGRzOiB7XG4gICAgdXNlcklkOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0lEIG9mIHRoZSB0YXJnZXR0ZWQgVXNlci4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxJRCksXG4gICAgfSxcbiAgICByZWFkOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IHRoZSB1c2VyIHRvIHJlYWQgdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgIH0sXG4gICAgd3JpdGU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgdGhlIHVzZXIgdG8gd3JpdGUgb24gdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgUk9MRV9BQ0xfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdSb2xlQUNMSW5wdXQnLFxuICBkZXNjcmlwdGlvbjogJ0FsbG93IHRvIG1hbmFnZSByb2xlcyBpbiBBQ0wuJyxcbiAgZmllbGRzOiB7XG4gICAgcm9sZU5hbWU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnTmFtZSBvZiB0aGUgdGFyZ2V0dGVkIFJvbGUuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMU3RyaW5nKSxcbiAgICB9LFxuICAgIHJlYWQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnQWxsb3cgdXNlcnMgd2hvIGFyZSBtZW1iZXJzIG9mIHRoZSByb2xlIHRvIHJlYWQgdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgIH0sXG4gICAgd3JpdGU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnQWxsb3cgdXNlcnMgd2hvIGFyZSBtZW1iZXJzIG9mIHRoZSByb2xlIHRvIHdyaXRlIG9uIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IFBVQkxJQ19BQ0xfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdQdWJsaWNBQ0xJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOiAnQWxsb3cgdG8gbWFuYWdlIHB1YmxpYyByaWdodHMuJyxcbiAgZmllbGRzOiB7XG4gICAgcmVhZDoge1xuICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyBhbnlvbmUgdG8gcmVhZCB0aGUgY3VycmVudCBvYmplY3QuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbiksXG4gICAgfSxcbiAgICB3cml0ZToge1xuICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyBhbnlvbmUgdG8gd3JpdGUgb24gdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgQUNMX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnQUNMSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnQWxsb3cgdG8gbWFuYWdlIGFjY2VzcyByaWdodHMuIElmIG5vdCBwcm92aWRlZCBvYmplY3Qgd2lsbCBiZSBwdWJsaWNseSByZWFkYWJsZSBhbmQgd3JpdGFibGUnLFxuICBmaWVsZHM6IHtcbiAgICB1c2Vyczoge1xuICAgICAgZGVzY3JpcHRpb246ICdBY2Nlc3MgY29udHJvbCBsaXN0IGZvciB1c2Vycy4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChVU0VSX0FDTF9JTlBVVCkpLFxuICAgIH0sXG4gICAgcm9sZXM6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWNjZXNzIGNvbnRyb2wgbGlzdCBmb3Igcm9sZXMuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoUk9MRV9BQ0xfSU5QVVQpKSxcbiAgICB9LFxuICAgIHB1YmxpYzoge1xuICAgICAgZGVzY3JpcHRpb246ICdQdWJsaWMgYWNjZXNzIGNvbnRyb2wgbGlzdC4nLFxuICAgICAgdHlwZTogUFVCTElDX0FDTF9JTlBVVCxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IFVTRVJfQUNMID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1VzZXJBQ0wnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnQWxsb3cgdG8gbWFuYWdlIHVzZXJzIGluIEFDTC4gSWYgcmVhZCBhbmQgd3JpdGUgYXJlIG51bGwgdGhlIHVzZXJzIGhhdmUgcmVhZCBhbmQgd3JpdGUgcmlnaHRzLicsXG4gIGZpZWxkczoge1xuICAgIHVzZXJJZDoge1xuICAgICAgZGVzY3JpcHRpb246ICdJRCBvZiB0aGUgdGFyZ2V0dGVkIFVzZXIuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMSUQpLFxuICAgIH0sXG4gICAgcmVhZDoge1xuICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyB0aGUgdXNlciB0byByZWFkIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICAgIHdyaXRlOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IHRoZSB1c2VyIHRvIHdyaXRlIG9uIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxCb29sZWFuKSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IFJPTEVfQUNMID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1JvbGVBQ0wnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnQWxsb3cgdG8gbWFuYWdlIHJvbGVzIGluIEFDTC4gSWYgcmVhZCBhbmQgd3JpdGUgYXJlIG51bGwgdGhlIHJvbGUgaGF2ZSByZWFkIGFuZCB3cml0ZSByaWdodHMuJyxcbiAgZmllbGRzOiB7XG4gICAgcm9sZU5hbWU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnTmFtZSBvZiB0aGUgdGFyZ2V0dGVkIFJvbGUuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMSUQpLFxuICAgIH0sXG4gICAgcmVhZDoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdBbGxvdyB1c2VycyB3aG8gYXJlIG1lbWJlcnMgb2YgdGhlIHJvbGUgdG8gcmVhZCB0aGUgY3VycmVudCBvYmplY3QuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbiksXG4gICAgfSxcbiAgICB3cml0ZToge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdBbGxvdyB1c2VycyB3aG8gYXJlIG1lbWJlcnMgb2YgdGhlIHJvbGUgdG8gd3JpdGUgb24gdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgUFVCTElDX0FDTCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdQdWJsaWNBQ0wnLFxuICBkZXNjcmlwdGlvbjogJ0FsbG93IHRvIG1hbmFnZSBwdWJsaWMgcmlnaHRzLicsXG4gIGZpZWxkczoge1xuICAgIHJlYWQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgYW55b25lIHRvIHJlYWQgdGhlIGN1cnJlbnQgb2JqZWN0LicsXG4gICAgICB0eXBlOiBHcmFwaFFMQm9vbGVhbixcbiAgICB9LFxuICAgIHdyaXRlOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IGFueW9uZSB0byB3cml0ZSBvbiB0aGUgY3VycmVudCBvYmplY3QuJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxCb29sZWFuLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgQUNMID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlKHtcbiAgbmFtZTogJ0FDTCcsXG4gIGRlc2NyaXB0aW9uOiAnQ3VycmVudCBhY2Nlc3MgY29udHJvbCBsaXN0IG9mIHRoZSBjdXJyZW50IG9iamVjdC4nLFxuICBmaWVsZHM6IHtcbiAgICB1c2Vyczoge1xuICAgICAgZGVzY3JpcHRpb246ICdBY2Nlc3MgY29udHJvbCBsaXN0IGZvciB1c2Vycy4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChVU0VSX0FDTCkpLFxuICAgICAgcmVzb2x2ZShwKSB7XG4gICAgICAgIGNvbnN0IHVzZXJzID0gW107XG4gICAgICAgIE9iamVjdC5rZXlzKHApLmZvckVhY2gocnVsZSA9PiB7XG4gICAgICAgICAgaWYgKHJ1bGUgIT09ICcqJyAmJiBydWxlLmluZGV4T2YoJ3JvbGU6JykgIT09IDApIHtcbiAgICAgICAgICAgIHVzZXJzLnB1c2goe1xuICAgICAgICAgICAgICB1c2VySWQ6IHJ1bGUsXG4gICAgICAgICAgICAgIHJlYWQ6IHBbcnVsZV0ucmVhZCA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICAgICAgd3JpdGU6IHBbcnVsZV0ud3JpdGUgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdXNlcnMubGVuZ3RoID8gdXNlcnMgOiBudWxsO1xuICAgICAgfSxcbiAgICB9LFxuICAgIHJvbGVzOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0FjY2VzcyBjb250cm9sIGxpc3QgZm9yIHJvbGVzLicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QobmV3IEdyYXBoUUxOb25OdWxsKFJPTEVfQUNMKSksXG4gICAgICByZXNvbHZlKHApIHtcbiAgICAgICAgY29uc3Qgcm9sZXMgPSBbXTtcbiAgICAgICAgT2JqZWN0LmtleXMocCkuZm9yRWFjaChydWxlID0+IHtcbiAgICAgICAgICBpZiAocnVsZS5pbmRleE9mKCdyb2xlOicpID09PSAwKSB7XG4gICAgICAgICAgICByb2xlcy5wdXNoKHtcbiAgICAgICAgICAgICAgcm9sZU5hbWU6IHJ1bGUucmVwbGFjZSgncm9sZTonLCAnJyksXG4gICAgICAgICAgICAgIHJlYWQ6IHBbcnVsZV0ucmVhZCA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICAgICAgd3JpdGU6IHBbcnVsZV0ud3JpdGUgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcm9sZXMubGVuZ3RoID8gcm9sZXMgOiBudWxsO1xuICAgICAgfSxcbiAgICB9LFxuICAgIHB1YmxpYzoge1xuICAgICAgZGVzY3JpcHRpb246ICdQdWJsaWMgYWNjZXNzIGNvbnRyb2wgbGlzdC4nLFxuICAgICAgdHlwZTogUFVCTElDX0FDTCxcbiAgICAgIHJlc29sdmUocCkge1xuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSAqL1xuICAgICAgICByZXR1cm4gcFsnKiddXG4gICAgICAgICAgPyB7XG4gICAgICAgICAgICAgIHJlYWQ6IHBbJyonXS5yZWFkID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgICAgICAgICB3cml0ZTogcFsnKiddLndyaXRlID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgICAgICAgfVxuICAgICAgICAgIDogbnVsbDtcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBPQkpFQ1RfSUQgPSBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTElEKTtcblxuY29uc3QgQ0xBU1NfTkFNRV9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgY2xhc3MgbmFtZSBvZiB0aGUgb2JqZWN0LicsXG4gIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMU3RyaW5nKSxcbn07XG5cbmNvbnN0IEdMT0JBTF9PUl9PQkpFQ1RfSURfQVRUID0ge1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhpcyBpcyB0aGUgb2JqZWN0IGlkLiBZb3UgY2FuIHVzZSBlaXRoZXIgdGhlIGdsb2JhbCBvciB0aGUgb2JqZWN0IGlkLicsXG4gIHR5cGU6IE9CSkVDVF9JRCxcbn07XG5cbmNvbnN0IE9CSkVDVF9JRF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgb2JqZWN0IGlkLicsXG4gIHR5cGU6IE9CSkVDVF9JRCxcbn07XG5cbmNvbnN0IENSRUFURURfQVRfQVRUID0ge1xuICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGRhdGUgaW4gd2hpY2ggdGhlIG9iamVjdCB3YXMgY3JlYXRlZC4nLFxuICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoREFURSksXG59O1xuXG5jb25zdCBVUERBVEVEX0FUX0FUVCA9IHtcbiAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBkYXRlIGluIHdoaWNoIHRoZSBvYmplY3Qgd2FzIGxhcyB1cGRhdGVkLicsXG4gIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChEQVRFKSxcbn07XG5cbmNvbnN0IElOUFVUX0ZJRUxEUyA9IHtcbiAgQUNMOiB7XG4gICAgdHlwZTogQUNMLFxuICB9LFxufTtcblxuY29uc3QgQ1JFQVRFX1JFU1VMVF9GSUVMRFMgPSB7XG4gIG9iamVjdElkOiBPQkpFQ1RfSURfQVRULFxuICBjcmVhdGVkQXQ6IENSRUFURURfQVRfQVRULFxufTtcblxuY29uc3QgVVBEQVRFX1JFU1VMVF9GSUVMRFMgPSB7XG4gIHVwZGF0ZWRBdDogVVBEQVRFRF9BVF9BVFQsXG59O1xuXG5jb25zdCBQQVJTRV9PQkpFQ1RfRklFTERTID0ge1xuICAuLi5DUkVBVEVfUkVTVUxUX0ZJRUxEUyxcbiAgLi4uVVBEQVRFX1JFU1VMVF9GSUVMRFMsXG4gIC4uLklOUFVUX0ZJRUxEUyxcbiAgQUNMOiB7XG4gICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEFDTCksXG4gICAgcmVzb2x2ZTogKHsgQUNMIH0pID0+IChBQ0wgPyBBQ0wgOiB7ICcqJzogeyByZWFkOiB0cnVlLCB3cml0ZTogdHJ1ZSB9IH0pLFxuICB9LFxufTtcblxuY29uc3QgUEFSU0VfT0JKRUNUID0gbmV3IEdyYXBoUUxJbnRlcmZhY2VUeXBlKHtcbiAgbmFtZTogJ1BhcnNlT2JqZWN0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBQYXJzZU9iamVjdCBpbnRlcmZhY2UgdHlwZSBpcyB1c2VkIGFzIGEgYmFzZSB0eXBlIGZvciB0aGUgYXV0byBnZW5lcmF0ZWQgb2JqZWN0IHR5cGVzLicsXG4gIGZpZWxkczogUEFSU0VfT0JKRUNUX0ZJRUxEUyxcbn0pO1xuXG5jb25zdCBTRVNTSU9OX1RPS0VOX0FUVCA9IHtcbiAgZGVzY3JpcHRpb246ICdUaGUgY3VycmVudCB1c2VyIHNlc3Npb24gdG9rZW4uJyxcbiAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxufTtcblxuY29uc3QgUkVBRF9QUkVGRVJFTkNFID0gbmV3IEdyYXBoUUxFbnVtVHlwZSh7XG4gIG5hbWU6ICdSZWFkUHJlZmVyZW5jZScsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgUmVhZFByZWZlcmVuY2UgZW51bSB0eXBlIGlzIHVzZWQgaW4gcXVlcmllcyBpbiBvcmRlciB0byBzZWxlY3QgaW4gd2hpY2ggZGF0YWJhc2UgcmVwbGljYSB0aGUgb3BlcmF0aW9uIG11c3QgcnVuLicsXG4gIHZhbHVlczoge1xuICAgIFBSSU1BUlk6IHsgdmFsdWU6ICdQUklNQVJZJyB9LFxuICAgIFBSSU1BUllfUFJFRkVSUkVEOiB7IHZhbHVlOiAnUFJJTUFSWV9QUkVGRVJSRUQnIH0sXG4gICAgU0VDT05EQVJZOiB7IHZhbHVlOiAnU0VDT05EQVJZJyB9LFxuICAgIFNFQ09OREFSWV9QUkVGRVJSRUQ6IHsgdmFsdWU6ICdTRUNPTkRBUllfUFJFRkVSUkVEJyB9LFxuICAgIE5FQVJFU1Q6IHsgdmFsdWU6ICdORUFSRVNUJyB9LFxuICB9LFxufSk7XG5cbmNvbnN0IFJFQURfUFJFRkVSRU5DRV9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhlIHJlYWQgcHJlZmVyZW5jZSBmb3IgdGhlIG1haW4gcXVlcnkgdG8gYmUgZXhlY3V0ZWQuJyxcbiAgdHlwZTogUkVBRF9QUkVGRVJFTkNFLFxufTtcblxuY29uc3QgSU5DTFVERV9SRUFEX1BSRUZFUkVOQ0VfQVRUID0ge1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIHJlYWQgcHJlZmVyZW5jZSBmb3IgdGhlIHF1ZXJpZXMgdG8gYmUgZXhlY3V0ZWQgdG8gaW5jbHVkZSBmaWVsZHMuJyxcbiAgdHlwZTogUkVBRF9QUkVGRVJFTkNFLFxufTtcblxuY29uc3QgU1VCUVVFUllfUkVBRF9QUkVGRVJFTkNFX0FUVCA9IHtcbiAgZGVzY3JpcHRpb246ICdUaGUgcmVhZCBwcmVmZXJlbmNlIGZvciB0aGUgc3VicXVlcmllcyB0aGF0IG1heSBiZSByZXF1aXJlZC4nLFxuICB0eXBlOiBSRUFEX1BSRUZFUkVOQ0UsXG59O1xuXG5jb25zdCBSRUFEX09QVElPTlNfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdSZWFkT3B0aW9uc0lucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBSZWFkT3B0aW9uc0lucHV0dCB0eXBlIGlzIHVzZWQgaW4gcXVlcmllcyBpbiBvcmRlciB0byBzZXQgdGhlIHJlYWQgcHJlZmVyZW5jZXMuJyxcbiAgZmllbGRzOiB7XG4gICAgcmVhZFByZWZlcmVuY2U6IFJFQURfUFJFRkVSRU5DRV9BVFQsXG4gICAgaW5jbHVkZVJlYWRQcmVmZXJlbmNlOiBJTkNMVURFX1JFQURfUFJFRkVSRU5DRV9BVFQsXG4gICAgc3VicXVlcnlSZWFkUHJlZmVyZW5jZTogU1VCUVVFUllfUkVBRF9QUkVGRVJFTkNFX0FUVCxcbiAgfSxcbn0pO1xuXG5jb25zdCBSRUFEX09QVElPTlNfQVRUID0ge1xuICBkZXNjcmlwdGlvbjogJ1RoZSByZWFkIG9wdGlvbnMgZm9yIHRoZSBxdWVyeSB0byBiZSBleGVjdXRlZC4nLFxuICB0eXBlOiBSRUFEX09QVElPTlNfSU5QVVQsXG59O1xuXG5jb25zdCBXSEVSRV9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGVzZSBhcmUgdGhlIGNvbmRpdGlvbnMgdGhhdCB0aGUgb2JqZWN0cyBuZWVkIHRvIG1hdGNoIGluIG9yZGVyIHRvIGJlIGZvdW5kJyxcbiAgdHlwZTogT0JKRUNULFxufTtcblxuY29uc3QgU0tJUF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgbnVtYmVyIG9mIG9iamVjdHMgdGhhdCBtdXN0IGJlIHNraXBwZWQgdG8gcmV0dXJuLicsXG4gIHR5cGU6IEdyYXBoUUxJbnQsXG59O1xuXG5jb25zdCBMSU1JVF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgbGltaXQgbnVtYmVyIG9mIG9iamVjdHMgdGhhdCBtdXN0IGJlIHJldHVybmVkLicsXG4gIHR5cGU6IEdyYXBoUUxJbnQsXG59O1xuXG5jb25zdCBDT1VOVF9BVFQgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSB0b3RhbCBtYXRjaGVkIG9iamVjcyBjb3VudCB0aGF0IGlzIHJldHVybmVkIHdoZW4gdGhlIGNvdW50IGZsYWcgaXMgc2V0LicsXG4gIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMSW50KSxcbn07XG5cbmNvbnN0IFNFQVJDSF9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1NlYXJjaElucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBTZWFyY2hJbnB1dCB0eXBlIGlzIHVzZWQgdG8gc3BlY2lmaXkgYSBzZWFyY2ggb3BlcmF0aW9uIG9uIGEgZnVsbCB0ZXh0IHNlYXJjaC4nLFxuICBmaWVsZHM6IHtcbiAgICB0ZXJtOiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHRlcm0gdG8gYmUgc2VhcmNoZWQuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMU3RyaW5nKSxcbiAgICB9LFxuICAgIGxhbmd1YWdlOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIGxhbmd1YWdlIHRvIHRldGVybWluZSB0aGUgbGlzdCBvZiBzdG9wIHdvcmRzIGFuZCB0aGUgcnVsZXMgZm9yIHRva2VuaXplci4nLFxuICAgICAgdHlwZTogR3JhcGhRTFN0cmluZyxcbiAgICB9LFxuICAgIGNhc2VTZW5zaXRpdmU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUgZmxhZyB0byBlbmFibGUgb3IgZGlzYWJsZSBjYXNlIHNlbnNpdGl2ZSBzZWFyY2guJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxCb29sZWFuLFxuICAgIH0sXG4gICAgZGlhY3JpdGljU2Vuc2l0aXZlOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIGZsYWcgdG8gZW5hYmxlIG9yIGRpc2FibGUgZGlhY3JpdGljIHNlbnNpdGl2ZSBzZWFyY2guJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxCb29sZWFuLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgVEVYVF9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1RleHRJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgVGV4dElucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZ5IGEgdGV4dCBvcGVyYXRpb24gb24gYSBjb25zdHJhaW50LicsXG4gIGZpZWxkczoge1xuICAgIHNlYXJjaDoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBzZWFyY2ggdG8gYmUgZXhlY3V0ZWQuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChTRUFSQ0hfSU5QVVQpLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgQk9YX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnQm94SW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEJveElucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZpeSBhIGJveCBvcGVyYXRpb24gb24gYSB3aXRoaW4gZ2VvIHF1ZXJ5LicsXG4gIGZpZWxkczoge1xuICAgIGJvdHRvbUxlZnQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgYm90dG9tIGxlZnQgY29vcmRpbmF0ZXMgb2YgdGhlIGJveC4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdFT19QT0lOVF9JTlBVVCksXG4gICAgfSxcbiAgICB1cHBlclJpZ2h0OiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIHVwcGVyIHJpZ2h0IGNvb3JkaW5hdGVzIG9mIHRoZSBib3guJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHRU9fUE9JTlRfSU5QVVQpLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgV0lUSElOX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnV2l0aGluSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFdpdGhpbklucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZ5IGEgd2l0aGluIG9wZXJhdGlvbiBvbiBhIGNvbnN0cmFpbnQuJyxcbiAgZmllbGRzOiB7XG4gICAgYm94OiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGJveCB0byBiZSBzcGVjaWZpZWQuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChCT1hfSU5QVVQpLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgQ0VOVEVSX1NQSEVSRV9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ0NlbnRlclNwaGVyZUlucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBDZW50ZXJTcGhlcmVJbnB1dCB0eXBlIGlzIHVzZWQgdG8gc3BlY2lmaXkgYSBjZW50ZXJTcGhlcmUgb3BlcmF0aW9uIG9uIGEgZ2VvV2l0aGluIHF1ZXJ5LicsXG4gIGZpZWxkczoge1xuICAgIGNlbnRlcjoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBjZW50ZXIgb2YgdGhlIHNwaGVyZS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdFT19QT0lOVF9JTlBVVCksXG4gICAgfSxcbiAgICBkaXN0YW5jZToge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSByYWRpdXMgb2YgdGhlIHNwaGVyZS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxGbG9hdCksXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBHRU9fV0lUSElOX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnR2VvV2l0aGluSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEdlb1dpdGhpbklucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZ5IGEgZ2VvV2l0aGluIG9wZXJhdGlvbiBvbiBhIGNvbnN0cmFpbnQuJyxcbiAgZmllbGRzOiB7XG4gICAgcG9seWdvbjoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBwb2x5Z29uIHRvIGJlIHNwZWNpZmllZC4nLFxuICAgICAgdHlwZTogUE9MWUdPTl9JTlBVVCxcbiAgICB9LFxuICAgIGNlbnRlclNwaGVyZToge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBzcGhlcmUgdG8gYmUgc3BlY2lmaWVkLicsXG4gICAgICB0eXBlOiBDRU5URVJfU1BIRVJFX0lOUFVULFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgR0VPX0lOVEVSU0VDVFNfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdHZW9JbnRlcnNlY3RzSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEdlb0ludGVyc2VjdHNJbnB1dCB0eXBlIGlzIHVzZWQgdG8gc3BlY2lmeSBhIGdlb0ludGVyc2VjdHMgb3BlcmF0aW9uIG9uIGEgY29uc3RyYWludC4nLFxuICBmaWVsZHM6IHtcbiAgICBwb2ludDoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBwb2ludCB0byBiZSBzcGVjaWZpZWQuJyxcbiAgICAgIHR5cGU6IEdFT19QT0lOVF9JTlBVVCxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IGVxdWFsVG8gPSB0eXBlID0+ICh7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBlcXVhbFRvIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBlcXVhbHMgdG8gYSBzcGVjaWZpZWQgdmFsdWUuJyxcbiAgdHlwZSxcbn0pO1xuXG5jb25zdCBub3RFcXVhbFRvID0gdHlwZSA9PiAoe1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhpcyBpcyB0aGUgbm90RXF1YWxUbyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlIG9mIGEgZmllbGQgZG8gbm90IGVxdWFsIHRvIGEgc3BlY2lmaWVkIHZhbHVlLicsXG4gIHR5cGUsXG59KTtcblxuY29uc3QgbGVzc1RoYW4gPSB0eXBlID0+ICh7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBsZXNzVGhhbiBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlIG9mIGEgZmllbGQgaXMgbGVzcyB0aGFuIGEgc3BlY2lmaWVkIHZhbHVlLicsXG4gIHR5cGUsXG59KTtcblxuY29uc3QgbGVzc1RoYW5PckVxdWFsVG8gPSB0eXBlID0+ICh7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBsZXNzVGhhbk9yRXF1YWxUbyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlIG9mIGEgZmllbGQgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGEgc3BlY2lmaWVkIHZhbHVlLicsXG4gIHR5cGUsXG59KTtcblxuY29uc3QgZ3JlYXRlclRoYW4gPSB0eXBlID0+ICh7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBncmVhdGVyVGhhbiBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlIG9mIGEgZmllbGQgaXMgZ3JlYXRlciB0aGFuIGEgc3BlY2lmaWVkIHZhbHVlLicsXG4gIHR5cGUsXG59KTtcblxuY29uc3QgZ3JlYXRlclRoYW5PckVxdWFsVG8gPSB0eXBlID0+ICh7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBncmVhdGVyVGhhbk9yRXF1YWxUbyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlIG9mIGEgZmllbGQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGEgc3BlY2lmaWVkIHZhbHVlLicsXG4gIHR5cGUsXG59KTtcblxuY29uc3QgaW5PcCA9IHR5cGUgPT4gKHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIGluIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWUgb2YgYSBmaWVsZCBlcXVhbHMgYW55IHZhbHVlIGluIHRoZSBzcGVjaWZpZWQgYXJyYXkuJyxcbiAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KHR5cGUpLFxufSk7XG5cbmNvbnN0IG5vdEluID0gdHlwZSA9PiAoe1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhpcyBpcyB0aGUgbm90SW4gb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIHRoZSB2YWx1ZSBvZiBhIGZpZWxkIGRvIG5vdCBlcXVhbCBhbnkgdmFsdWUgaW4gdGhlIHNwZWNpZmllZCBhcnJheS4nLFxuICB0eXBlOiBuZXcgR3JhcGhRTExpc3QodHlwZSksXG59KTtcblxuY29uc3QgZXhpc3RzID0ge1xuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhpcyBpcyB0aGUgZXhpc3RzIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSBhIGZpZWxkIGV4aXN0cyAob3IgZG8gbm90IGV4aXN0KS4nLFxuICB0eXBlOiBHcmFwaFFMQm9vbGVhbixcbn07XG5cbmNvbnN0IG1hdGNoZXNSZWdleCA9IHtcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoaXMgaXMgdGhlIG1hdGNoZXNSZWdleCBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlIG9mIGEgZmllbGQgbWF0Y2hlcyBhIHNwZWNpZmllZCByZWd1bGFyIGV4cHJlc3Npb24uJyxcbiAgdHlwZTogR3JhcGhRTFN0cmluZyxcbn07XG5cbmNvbnN0IG9wdGlvbnMgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBvcHRpb25zIG9wZXJhdG9yIHRvIHNwZWNpZnkgb3B0aW9uYWwgZmxhZ3MgKHN1Y2ggYXMgXCJpXCIgYW5kIFwibVwiKSB0byBiZSBhZGRlZCB0byBhIG1hdGNoZXNSZWdleCBvcGVyYXRpb24gaW4gdGhlIHNhbWUgc2V0IG9mIGNvbnN0cmFpbnRzLicsXG4gIHR5cGU6IEdyYXBoUUxTdHJpbmcsXG59O1xuXG5jb25zdCBTVUJRVUVSWV9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1N1YnF1ZXJ5SW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFN1YnF1ZXJ5SW5wdXQgdHlwZSBpcyB1c2VkIHRvIHNwZWNpZnkgYSBzdWIgcXVlcnkgdG8gYW5vdGhlciBjbGFzcy4nLFxuICBmaWVsZHM6IHtcbiAgICBjbGFzc05hbWU6IENMQVNTX05BTUVfQVRULFxuICAgIHdoZXJlOiBPYmplY3QuYXNzaWduKHt9LCBXSEVSRV9BVFQsIHtcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChXSEVSRV9BVFQudHlwZSksXG4gICAgfSksXG4gIH0sXG59KTtcblxuY29uc3QgU0VMRUNUX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnU2VsZWN0SW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFNlbGVjdElucHV0IHR5cGUgaXMgdXNlZCB0byBzcGVjaWZ5IGFuIGluUXVlcnlLZXkgb3IgYSBub3RJblF1ZXJ5S2V5IG9wZXJhdGlvbiBvbiBhIGNvbnN0cmFpbnQuJyxcbiAgZmllbGRzOiB7XG4gICAgcXVlcnk6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgc3VicXVlcnkgdG8gYmUgZXhlY3V0ZWQuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChTVUJRVUVSWV9JTlBVVCksXG4gICAgfSxcbiAgICBrZXk6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUga2V5IGluIHRoZSByZXN1bHQgb2YgdGhlIHN1YnF1ZXJ5IHRoYXQgbXVzdCBtYXRjaCAobm90IG1hdGNoKSB0aGUgZmllbGQuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMU3RyaW5nKSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IGluUXVlcnlLZXkgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBpblF1ZXJ5S2V5IG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSBhIGZpZWxkIGVxdWFscyB0byBhIGtleSBpbiB0aGUgcmVzdWx0IG9mIGEgZGlmZmVyZW50IHF1ZXJ5LicsXG4gIHR5cGU6IFNFTEVDVF9JTlBVVCxcbn07XG5cbmNvbnN0IG5vdEluUXVlcnlLZXkgPSB7XG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGlzIGlzIHRoZSBub3RJblF1ZXJ5S2V5IG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSBhIGZpZWxkIGRvIG5vdCBlcXVhbCB0byBhIGtleSBpbiB0aGUgcmVzdWx0IG9mIGEgZGlmZmVyZW50IHF1ZXJ5LicsXG4gIHR5cGU6IFNFTEVDVF9JTlBVVCxcbn07XG5cbmNvbnN0IElEX1dIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnSWRXaGVyZUlucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBJZFdoZXJlSW5wdXQgaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIGJ5IGFuIGlkLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oR3JhcGhRTElEKSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEdyYXBoUUxJRCksXG4gICAgbGVzc1RoYW46IGxlc3NUaGFuKEdyYXBoUUxJRCksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKEdyYXBoUUxJRCksXG4gICAgZ3JlYXRlclRoYW46IGdyZWF0ZXJUaGFuKEdyYXBoUUxJRCksXG4gICAgZ3JlYXRlclRoYW5PckVxdWFsVG86IGdyZWF0ZXJUaGFuT3JFcXVhbFRvKEdyYXBoUUxJRCksXG4gICAgaW46IGluT3AoR3JhcGhRTElEKSxcbiAgICBub3RJbjogbm90SW4oR3JhcGhRTElEKSxcbiAgICBleGlzdHMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICB9LFxufSk7XG5cbmNvbnN0IFNUUklOR19XSEVSRV9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ1N0cmluZ1doZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFN0cmluZ1doZXJlSW5wdXQgaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIGJ5IGEgZmllbGQgb2YgdHlwZSBTdHJpbmcuJyxcbiAgZmllbGRzOiB7XG4gICAgZXF1YWxUbzogZXF1YWxUbyhHcmFwaFFMU3RyaW5nKSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEdyYXBoUUxTdHJpbmcpLFxuICAgIGxlc3NUaGFuOiBsZXNzVGhhbihHcmFwaFFMU3RyaW5nKSxcbiAgICBsZXNzVGhhbk9yRXF1YWxUbzogbGVzc1RoYW5PckVxdWFsVG8oR3JhcGhRTFN0cmluZyksXG4gICAgZ3JlYXRlclRoYW46IGdyZWF0ZXJUaGFuKEdyYXBoUUxTdHJpbmcpLFxuICAgIGdyZWF0ZXJUaGFuT3JFcXVhbFRvOiBncmVhdGVyVGhhbk9yRXF1YWxUbyhHcmFwaFFMU3RyaW5nKSxcbiAgICBpbjogaW5PcChHcmFwaFFMU3RyaW5nKSxcbiAgICBub3RJbjogbm90SW4oR3JhcGhRTFN0cmluZyksXG4gICAgZXhpc3RzLFxuICAgIG1hdGNoZXNSZWdleCxcbiAgICBvcHRpb25zLFxuICAgIHRleHQ6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUgJHRleHQgb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGZ1bGwgdGV4dCBzZWFyY2ggY29uc3RyYWludC4nLFxuICAgICAgdHlwZTogVEVYVF9JTlBVVCxcbiAgICB9LFxuICAgIGluUXVlcnlLZXksXG4gICAgbm90SW5RdWVyeUtleSxcbiAgfSxcbn0pO1xuXG5jb25zdCBOVU1CRVJfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdOdW1iZXJXaGVyZUlucHV0JyxcbiAgZGVzY3JpcHRpb246XG4gICAgJ1RoZSBOdW1iZXJXaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgTnVtYmVyLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oR3JhcGhRTEZsb2F0KSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEdyYXBoUUxGbG9hdCksXG4gICAgbGVzc1RoYW46IGxlc3NUaGFuKEdyYXBoUUxGbG9hdCksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKEdyYXBoUUxGbG9hdCksXG4gICAgZ3JlYXRlclRoYW46IGdyZWF0ZXJUaGFuKEdyYXBoUUxGbG9hdCksXG4gICAgZ3JlYXRlclRoYW5PckVxdWFsVG86IGdyZWF0ZXJUaGFuT3JFcXVhbFRvKEdyYXBoUUxGbG9hdCksXG4gICAgaW46IGluT3AoR3JhcGhRTEZsb2F0KSxcbiAgICBub3RJbjogbm90SW4oR3JhcGhRTEZsb2F0KSxcbiAgICBleGlzdHMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICB9LFxufSk7XG5cbmNvbnN0IEJPT0xFQU5fV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdCb29sZWFuV2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgQm9vbGVhbldoZXJlSW5wdXQgaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIGJ5IGEgZmllbGQgb2YgdHlwZSBCb29sZWFuLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oR3JhcGhRTEJvb2xlYW4pLFxuICAgIG5vdEVxdWFsVG86IG5vdEVxdWFsVG8oR3JhcGhRTEJvb2xlYW4pLFxuICAgIGV4aXN0cyxcbiAgICBpblF1ZXJ5S2V5LFxuICAgIG5vdEluUXVlcnlLZXksXG4gIH0sXG59KTtcblxuY29uc3QgQVJSQVlfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdBcnJheVdoZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEFycmF5V2hlcmVJbnB1dCBpbnB1dCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgZmlsdGVyaW5nIG9iamVjdHMgYnkgYSBmaWVsZCBvZiB0eXBlIEFycmF5LicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oQU5ZKSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEFOWSksXG4gICAgbGVzc1RoYW46IGxlc3NUaGFuKEFOWSksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKEFOWSksXG4gICAgZ3JlYXRlclRoYW46IGdyZWF0ZXJUaGFuKEFOWSksXG4gICAgZ3JlYXRlclRoYW5PckVxdWFsVG86IGdyZWF0ZXJUaGFuT3JFcXVhbFRvKEFOWSksXG4gICAgaW46IGluT3AoQU5ZKSxcbiAgICBub3RJbjogbm90SW4oQU5ZKSxcbiAgICBleGlzdHMsXG4gICAgY29udGFpbmVkQnk6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUgY29udGFpbmVkQnkgb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIHRoZSB2YWx1ZXMgb2YgYW4gYXJyYXkgZmllbGQgaXMgY29udGFpbmVkIGJ5IGFub3RoZXIgc3BlY2lmaWVkIGFycmF5LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QoQU5ZKSxcbiAgICB9LFxuICAgIGNvbnRhaW5zOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIGNvbnRhaW5zIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWVzIG9mIGFuIGFycmF5IGZpZWxkIGNvbnRhaW4gYWxsIGVsZW1lbnRzIG9mIGFub3RoZXIgc3BlY2lmaWVkIGFycmF5LicsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTExpc3QoQU5ZKSxcbiAgICB9LFxuICAgIGluUXVlcnlLZXksXG4gICAgbm90SW5RdWVyeUtleSxcbiAgfSxcbn0pO1xuXG5jb25zdCBLRVlfVkFMVUVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdLZXlWYWx1ZUlucHV0JyxcbiAgZGVzY3JpcHRpb246ICdBbiBlbnRyeSBmcm9tIGFuIG9iamVjdCwgaS5lLiwgYSBwYWlyIG9mIGtleSBhbmQgdmFsdWUuJyxcbiAgZmllbGRzOiB7XG4gICAga2V5OiB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBrZXkgdXNlZCB0byByZXRyaWV2ZSB0aGUgdmFsdWUgb2YgdGhpcyBlbnRyeS4nLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgIH0sXG4gICAgdmFsdWU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHZhbHVlIG9mIHRoZSBlbnRyeS4gQ291bGQgYmUgYW55IHR5cGUgb2Ygc2NhbGFyIGRhdGEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChBTlkpLFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgT0JKRUNUX1dIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnT2JqZWN0V2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgT2JqZWN0V2hlcmVJbnB1dCBpbnB1dCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgZmlsdGVyaW5nIHJlc3VsdCBieSBhIGZpZWxkIG9mIHR5cGUgT2JqZWN0LicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBub3RFcXVhbFRvOiBub3RFcXVhbFRvKEtFWV9WQUxVRV9JTlBVVCksXG4gICAgaW46IGluT3AoS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBub3RJbjogbm90SW4oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBsZXNzVGhhbjogbGVzc1RoYW4oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBsZXNzVGhhbk9yRXF1YWxUbzogbGVzc1RoYW5PckVxdWFsVG8oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBncmVhdGVyVGhhbjogZ3JlYXRlclRoYW4oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBncmVhdGVyVGhhbk9yRXF1YWxUbzogZ3JlYXRlclRoYW5PckVxdWFsVG8oS0VZX1ZBTFVFX0lOUFVUKSxcbiAgICBleGlzdHMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICB9LFxufSk7XG5cbmNvbnN0IERBVEVfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdEYXRlV2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgRGF0ZVdoZXJlSW5wdXQgaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIGJ5IGEgZmllbGQgb2YgdHlwZSBEYXRlLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oREFURSksXG4gICAgbm90RXF1YWxUbzogbm90RXF1YWxUbyhEQVRFKSxcbiAgICBsZXNzVGhhbjogbGVzc1RoYW4oREFURSksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKERBVEUpLFxuICAgIGdyZWF0ZXJUaGFuOiBncmVhdGVyVGhhbihEQVRFKSxcbiAgICBncmVhdGVyVGhhbk9yRXF1YWxUbzogZ3JlYXRlclRoYW5PckVxdWFsVG8oREFURSksXG4gICAgaW46IGluT3AoREFURSksXG4gICAgbm90SW46IG5vdEluKERBVEUpLFxuICAgIGV4aXN0cyxcbiAgICBpblF1ZXJ5S2V5LFxuICAgIG5vdEluUXVlcnlLZXksXG4gIH0sXG59KTtcblxuY29uc3QgQllURVNfV0hFUkVfSU5QVVQgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdCeXRlc1doZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEJ5dGVzV2hlcmVJbnB1dCBpbnB1dCB0eXBlIGlzIHVzZWQgaW4gb3BlcmF0aW9ucyB0aGF0IGludm9sdmUgZmlsdGVyaW5nIG9iamVjdHMgYnkgYSBmaWVsZCBvZiB0eXBlIEJ5dGVzLicsXG4gIGZpZWxkczoge1xuICAgIGVxdWFsVG86IGVxdWFsVG8oQllURVMpLFxuICAgIG5vdEVxdWFsVG86IG5vdEVxdWFsVG8oQllURVMpLFxuICAgIGxlc3NUaGFuOiBsZXNzVGhhbihCWVRFUyksXG4gICAgbGVzc1RoYW5PckVxdWFsVG86IGxlc3NUaGFuT3JFcXVhbFRvKEJZVEVTKSxcbiAgICBncmVhdGVyVGhhbjogZ3JlYXRlclRoYW4oQllURVMpLFxuICAgIGdyZWF0ZXJUaGFuT3JFcXVhbFRvOiBncmVhdGVyVGhhbk9yRXF1YWxUbyhCWVRFUyksXG4gICAgaW46IGluT3AoQllURVMpLFxuICAgIG5vdEluOiBub3RJbihCWVRFUyksXG4gICAgZXhpc3RzLFxuICAgIGluUXVlcnlLZXksXG4gICAgbm90SW5RdWVyeUtleSxcbiAgfSxcbn0pO1xuXG5jb25zdCBGSUxFX1dIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnRmlsZVdoZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIEZpbGVXaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgRmlsZS4nLFxuICBmaWVsZHM6IHtcbiAgICBlcXVhbFRvOiBlcXVhbFRvKEZJTEUpLFxuICAgIG5vdEVxdWFsVG86IG5vdEVxdWFsVG8oRklMRSksXG4gICAgbGVzc1RoYW46IGxlc3NUaGFuKEZJTEUpLFxuICAgIGxlc3NUaGFuT3JFcXVhbFRvOiBsZXNzVGhhbk9yRXF1YWxUbyhGSUxFKSxcbiAgICBncmVhdGVyVGhhbjogZ3JlYXRlclRoYW4oRklMRSksXG4gICAgZ3JlYXRlclRoYW5PckVxdWFsVG86IGdyZWF0ZXJUaGFuT3JFcXVhbFRvKEZJTEUpLFxuICAgIGluOiBpbk9wKEZJTEUpLFxuICAgIG5vdEluOiBub3RJbihGSUxFKSxcbiAgICBleGlzdHMsXG4gICAgbWF0Y2hlc1JlZ2V4LFxuICAgIG9wdGlvbnMsXG4gICAgaW5RdWVyeUtleSxcbiAgICBub3RJblF1ZXJ5S2V5LFxuICB9LFxufSk7XG5cbmNvbnN0IEdFT19QT0lOVF9XSEVSRV9JTlBVVCA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgbmFtZTogJ0dlb1BvaW50V2hlcmVJbnB1dCcsXG4gIGRlc2NyaXB0aW9uOlxuICAgICdUaGUgR2VvUG9pbnRXaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgR2VvUG9pbnQuJyxcbiAgZmllbGRzOiB7XG4gICAgZXhpc3RzLFxuICAgIG5lYXJTcGhlcmU6IHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAnVGhpcyBpcyB0aGUgbmVhclNwaGVyZSBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBuZWFyIHRvIGFub3RoZXIgZ2VvIHBvaW50LicsXG4gICAgICB0eXBlOiBHRU9fUE9JTlRfSU5QVVQsXG4gICAgfSxcbiAgICBtYXhEaXN0YW5jZToge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBtYXhEaXN0YW5jZSBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBhdCBhIG1heCBkaXN0YW5jZSAoaW4gcmFkaWFucykgZnJvbSB0aGUgZ2VvIHBvaW50IHNwZWNpZmllZCBpbiB0aGUgJG5lYXJTcGhlcmUgb3BlcmF0b3IuJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxGbG9hdCxcbiAgICB9LFxuICAgIG1heERpc3RhbmNlSW5SYWRpYW5zOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIG1heERpc3RhbmNlSW5SYWRpYW5zIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWVzIG9mIGEgZ2VvIHBvaW50IGZpZWxkIGlzIGF0IGEgbWF4IGRpc3RhbmNlIChpbiByYWRpYW5zKSBmcm9tIHRoZSBnZW8gcG9pbnQgc3BlY2lmaWVkIGluIHRoZSAkbmVhclNwaGVyZSBvcGVyYXRvci4nLFxuICAgICAgdHlwZTogR3JhcGhRTEZsb2F0LFxuICAgIH0sXG4gICAgbWF4RGlzdGFuY2VJbk1pbGVzOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIG1heERpc3RhbmNlSW5NaWxlcyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBhdCBhIG1heCBkaXN0YW5jZSAoaW4gbWlsZXMpIGZyb20gdGhlIGdlbyBwb2ludCBzcGVjaWZpZWQgaW4gdGhlICRuZWFyU3BoZXJlIG9wZXJhdG9yLicsXG4gICAgICB0eXBlOiBHcmFwaFFMRmxvYXQsXG4gICAgfSxcbiAgICBtYXhEaXN0YW5jZUluS2lsb21ldGVyczoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBtYXhEaXN0YW5jZUluS2lsb21ldGVycyBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyBhdCBhIG1heCBkaXN0YW5jZSAoaW4ga2lsb21ldGVycykgZnJvbSB0aGUgZ2VvIHBvaW50IHNwZWNpZmllZCBpbiB0aGUgJG5lYXJTcGhlcmUgb3BlcmF0b3IuJyxcbiAgICAgIHR5cGU6IEdyYXBoUUxGbG9hdCxcbiAgICB9LFxuICAgIHdpdGhpbjoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSB3aXRoaW4gb3BlcmF0b3IgdG8gc3BlY2lmeSBhIGNvbnN0cmFpbnQgdG8gc2VsZWN0IHRoZSBvYmplY3RzIHdoZXJlIHRoZSB2YWx1ZXMgb2YgYSBnZW8gcG9pbnQgZmllbGQgaXMgd2l0aGluIGEgc3BlY2lmaWVkIGJveC4nLFxuICAgICAgdHlwZTogV0lUSElOX0lOUFVULFxuICAgIH0sXG4gICAgZ2VvV2l0aGluOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoaXMgaXMgdGhlIGdlb1dpdGhpbiBvcGVyYXRvciB0byBzcGVjaWZ5IGEgY29uc3RyYWludCB0byBzZWxlY3QgdGhlIG9iamVjdHMgd2hlcmUgdGhlIHZhbHVlcyBvZiBhIGdlbyBwb2ludCBmaWVsZCBpcyB3aXRoaW4gYSBzcGVjaWZpZWQgcG9seWdvbiBvciBzcGhlcmUuJyxcbiAgICAgIHR5cGU6IEdFT19XSVRISU5fSU5QVVQsXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBQT0xZR09OX1dIRVJFX0lOUFVUID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICBuYW1lOiAnUG9seWdvbldoZXJlSW5wdXQnLFxuICBkZXNjcmlwdGlvbjpcbiAgICAnVGhlIFBvbHlnb25XaGVyZUlucHV0IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBieSBhIGZpZWxkIG9mIHR5cGUgUG9seWdvbi4nLFxuICBmaWVsZHM6IHtcbiAgICBleGlzdHMsXG4gICAgZ2VvSW50ZXJzZWN0czoge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGlzIGlzIHRoZSBnZW9JbnRlcnNlY3RzIG9wZXJhdG9yIHRvIHNwZWNpZnkgYSBjb25zdHJhaW50IHRvIHNlbGVjdCB0aGUgb2JqZWN0cyB3aGVyZSB0aGUgdmFsdWVzIG9mIGEgcG9seWdvbiBmaWVsZCBpbnRlcnNlY3QgYSBzcGVjaWZpZWQgcG9pbnQuJyxcbiAgICAgIHR5cGU6IEdFT19JTlRFUlNFQ1RTX0lOUFVULFxuICAgIH0sXG4gIH0sXG59KTtcblxuY29uc3QgRUxFTUVOVCA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gIG5hbWU6ICdFbGVtZW50JyxcbiAgZGVzY3JpcHRpb246IFwiVGhlIEVsZW1lbnQgb2JqZWN0IHR5cGUgaXMgdXNlZCB0byByZXR1cm4gYXJyYXkgaXRlbXMnIHZhbHVlLlwiLFxuICBmaWVsZHM6IHtcbiAgICB2YWx1ZToge1xuICAgICAgZGVzY3JpcHRpb246ICdSZXR1cm4gdGhlIHZhbHVlIG9mIHRoZSBlbGVtZW50IGluIHRoZSBhcnJheScsXG4gICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoQU5ZKSxcbiAgICB9LFxuICB9LFxufSk7XG5cbi8vIERlZmF1bHQgc3RhdGljIHVuaW9uIHR5cGUsIHdlIHVwZGF0ZSB0eXBlcyBhbmQgcmVzb2x2ZVR5cGUgZnVuY3Rpb24gbGF0ZXJcbmxldCBBUlJBWV9SRVNVTFQ7XG5cbmNvbnN0IGxvYWRBcnJheVJlc3VsdCA9IChwYXJzZUdyYXBoUUxTY2hlbWEsIHBhcnNlQ2xhc3NlcykgPT4ge1xuICBjb25zdCBjbGFzc1R5cGVzID0gcGFyc2VDbGFzc2VzXG4gICAgLmZpbHRlcihwYXJzZUNsYXNzID0+XG4gICAgICBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW3BhcnNlQ2xhc3MuY2xhc3NOYW1lXVxuICAgICAgICAuY2xhc3NHcmFwaFFMT3V0cHV0VHlwZVxuICAgICAgICA/IHRydWVcbiAgICAgICAgOiBmYWxzZVxuICAgIClcbiAgICAubWFwKFxuICAgICAgcGFyc2VDbGFzcyA9PlxuICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW3BhcnNlQ2xhc3MuY2xhc3NOYW1lXVxuICAgICAgICAgIC5jbGFzc0dyYXBoUUxPdXRwdXRUeXBlXG4gICAgKTtcbiAgQVJSQVlfUkVTVUxUID0gbmV3IEdyYXBoUUxVbmlvblR5cGUoe1xuICAgIG5hbWU6ICdBcnJheVJlc3VsdCcsXG4gICAgZGVzY3JpcHRpb246XG4gICAgICAnVXNlIElubGluZSBGcmFnbWVudCBvbiBBcnJheSB0byBnZXQgcmVzdWx0czogaHR0cHM6Ly9ncmFwaHFsLm9yZy9sZWFybi9xdWVyaWVzLyNpbmxpbmUtZnJhZ21lbnRzJyxcbiAgICB0eXBlczogKCkgPT4gW0VMRU1FTlQsIC4uLmNsYXNzVHlwZXNdLFxuICAgIHJlc29sdmVUeXBlOiB2YWx1ZSA9PiB7XG4gICAgICBpZiAodmFsdWUuX190eXBlID09PSAnT2JqZWN0JyAmJiB2YWx1ZS5jbGFzc05hbWUgJiYgdmFsdWUub2JqZWN0SWQpIHtcbiAgICAgICAgaWYgKHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNbdmFsdWUuY2xhc3NOYW1lXSkge1xuICAgICAgICAgIHJldHVybiBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW3ZhbHVlLmNsYXNzTmFtZV1cbiAgICAgICAgICAgIC5jbGFzc0dyYXBoUUxPdXRwdXRUeXBlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBFTEVNRU5UO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gRUxFTUVOVDtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmdyYXBoUUxUeXBlcy5wdXNoKEFSUkFZX1JFU1VMVCk7XG59O1xuXG5jb25zdCBsb2FkID0gcGFyc2VHcmFwaFFMU2NoZW1hID0+IHtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEdyYXBoUUxVcGxvYWQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoQU5ZLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKE9CSkVDVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShEQVRFLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEJZVEVTLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEZJTEUsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoRklMRV9JTkZPLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEZJTEVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoR0VPX1BPSU5UX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEdFT19QT0lOVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShQQVJTRV9PQkpFQ1QsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoUkVBRF9QUkVGRVJFTkNFLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFJFQURfT1BUSU9OU19JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTRUFSQ0hfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoVEVYVF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShCT1hfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoV0lUSElOX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKENFTlRFUl9TUEhFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoR0VPX1dJVEhJTl9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShHRU9fSU5URVJTRUNUU19JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShJRF9XSEVSRV9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTVFJJTkdfV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoTlVNQkVSX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEJPT0xFQU5fV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoQVJSQVlfV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoS0VZX1ZBTFVFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKE9CSkVDVF9XSEVSRV9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShEQVRFX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEJZVEVTX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKEZJTEVfV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoR0VPX1BPSU5UX1dIRVJFX0lOUFVULCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFBPTFlHT05fV0hFUkVfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoRUxFTUVOVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShBQ0xfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoVVNFUl9BQ0xfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoUk9MRV9BQ0xfSU5QVVQsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoUFVCTElDX0FDTF9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShBQ0wsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoVVNFUl9BQ0wsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoUk9MRV9BQ0wsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoUFVCTElDX0FDTCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTVUJRVUVSWV9JTlBVVCwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShTRUxFQ1RfSU5QVVQsIHRydWUpO1xufTtcblxuZXhwb3J0IHtcbiAgVHlwZVZhbGlkYXRpb25FcnJvcixcbiAgcGFyc2VTdHJpbmdWYWx1ZSxcbiAgcGFyc2VJbnRWYWx1ZSxcbiAgcGFyc2VGbG9hdFZhbHVlLFxuICBwYXJzZUJvb2xlYW5WYWx1ZSxcbiAgcGFyc2VWYWx1ZSxcbiAgcGFyc2VMaXN0VmFsdWVzLFxuICBwYXJzZU9iamVjdEZpZWxkcyxcbiAgQU5ZLFxuICBPQkpFQ1QsXG4gIHBhcnNlRGF0ZUlzb1ZhbHVlLFxuICBzZXJpYWxpemVEYXRlSXNvLFxuICBEQVRFLFxuICBCWVRFUyxcbiAgcGFyc2VGaWxlVmFsdWUsXG4gIFNVQlFVRVJZX0lOUFVULFxuICBTRUxFQ1RfSU5QVVQsXG4gIEZJTEUsXG4gIEZJTEVfSU5GTyxcbiAgRklMRV9JTlBVVCxcbiAgR0VPX1BPSU5UX0ZJRUxEUyxcbiAgR0VPX1BPSU5UX0lOUFVULFxuICBHRU9fUE9JTlQsXG4gIFBPTFlHT05fSU5QVVQsXG4gIFBPTFlHT04sXG4gIE9CSkVDVF9JRCxcbiAgQ0xBU1NfTkFNRV9BVFQsXG4gIEdMT0JBTF9PUl9PQkpFQ1RfSURfQVRULFxuICBPQkpFQ1RfSURfQVRULFxuICBVUERBVEVEX0FUX0FUVCxcbiAgQ1JFQVRFRF9BVF9BVFQsXG4gIElOUFVUX0ZJRUxEUyxcbiAgQ1JFQVRFX1JFU1VMVF9GSUVMRFMsXG4gIFVQREFURV9SRVNVTFRfRklFTERTLFxuICBQQVJTRV9PQkpFQ1RfRklFTERTLFxuICBQQVJTRV9PQkpFQ1QsXG4gIFNFU1NJT05fVE9LRU5fQVRULFxuICBSRUFEX1BSRUZFUkVOQ0UsXG4gIFJFQURfUFJFRkVSRU5DRV9BVFQsXG4gIElOQ0xVREVfUkVBRF9QUkVGRVJFTkNFX0FUVCxcbiAgU1VCUVVFUllfUkVBRF9QUkVGRVJFTkNFX0FUVCxcbiAgUkVBRF9PUFRJT05TX0lOUFVULFxuICBSRUFEX09QVElPTlNfQVRULFxuICBXSEVSRV9BVFQsXG4gIFNLSVBfQVRULFxuICBMSU1JVF9BVFQsXG4gIENPVU5UX0FUVCxcbiAgU0VBUkNIX0lOUFVULFxuICBURVhUX0lOUFVULFxuICBCT1hfSU5QVVQsXG4gIFdJVEhJTl9JTlBVVCxcbiAgQ0VOVEVSX1NQSEVSRV9JTlBVVCxcbiAgR0VPX1dJVEhJTl9JTlBVVCxcbiAgR0VPX0lOVEVSU0VDVFNfSU5QVVQsXG4gIGVxdWFsVG8sXG4gIG5vdEVxdWFsVG8sXG4gIGxlc3NUaGFuLFxuICBsZXNzVGhhbk9yRXF1YWxUbyxcbiAgZ3JlYXRlclRoYW4sXG4gIGdyZWF0ZXJUaGFuT3JFcXVhbFRvLFxuICBpbk9wLFxuICBub3RJbixcbiAgZXhpc3RzLFxuICBtYXRjaGVzUmVnZXgsXG4gIG9wdGlvbnMsXG4gIGluUXVlcnlLZXksXG4gIG5vdEluUXVlcnlLZXksXG4gIElEX1dIRVJFX0lOUFVULFxuICBTVFJJTkdfV0hFUkVfSU5QVVQsXG4gIE5VTUJFUl9XSEVSRV9JTlBVVCxcbiAgQk9PTEVBTl9XSEVSRV9JTlBVVCxcbiAgQVJSQVlfV0hFUkVfSU5QVVQsXG4gIEtFWV9WQUxVRV9JTlBVVCxcbiAgT0JKRUNUX1dIRVJFX0lOUFVULFxuICBEQVRFX1dIRVJFX0lOUFVULFxuICBCWVRFU19XSEVSRV9JTlBVVCxcbiAgRklMRV9XSEVSRV9JTlBVVCxcbiAgR0VPX1BPSU5UX1dIRVJFX0lOUFVULFxuICBQT0xZR09OX1dIRVJFX0lOUFVULFxuICBBUlJBWV9SRVNVTFQsXG4gIEVMRU1FTlQsXG4gIEFDTF9JTlBVVCxcbiAgVVNFUl9BQ0xfSU5QVVQsXG4gIFJPTEVfQUNMX0lOUFVULFxuICBQVUJMSUNfQUNMX0lOUFVULFxuICBBQ0wsXG4gIFVTRVJfQUNMLFxuICBST0xFX0FDTCxcbiAgUFVCTElDX0FDTCxcbiAgbG9hZCxcbiAgbG9hZEFycmF5UmVzdWx0LFxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/GraphQL/loaders/defaultRelaySchema.js b/lib/GraphQL/loaders/defaultRelaySchema.js new file mode 100644 index 0000000000..78bb4389cc --- /dev/null +++ b/lib/GraphQL/loaders/defaultRelaySchema.js @@ -0,0 +1,73 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = exports.GLOBAL_ID_ATT = void 0; + +var _graphqlRelay = require("graphql-relay"); + +var _graphqlListFields = _interopRequireDefault(require("graphql-list-fields")); + +var defaultGraphQLTypes = _interopRequireWildcard(require("./defaultGraphQLTypes")); + +var objectsQueries = _interopRequireWildcard(require("../helpers/objectsQueries")); + +var _parseClassTypes = require("./parseClassTypes"); + +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 GLOBAL_ID_ATT = { + description: 'This is the global id.', + type: defaultGraphQLTypes.OBJECT_ID +}; +exports.GLOBAL_ID_ATT = GLOBAL_ID_ATT; + +const load = parseGraphQLSchema => { + const { + nodeInterface, + nodeField + } = (0, _graphqlRelay.nodeDefinitions)(async (globalId, context, queryInfo) => { + try { + const { + type, + id + } = (0, _graphqlRelay.fromGlobalId)(globalId); + const { + config, + auth, + info + } = context; + const selectedFields = (0, _graphqlListFields.default)(queryInfo); + const { + keys, + include + } = (0, _parseClassTypes.extractKeysAndInclude)(selectedFields); + return _objectSpread({ + className: type + }, (await objectsQueries.getObject(type, id, keys, include, undefined, undefined, config, auth, info, parseGraphQLSchema.parseClasses.find(({ + className + }) => type === className)))); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + }, obj => { + return parseGraphQLSchema.parseClassTypes[obj.className].classGraphQLOutputType; + }); + parseGraphQLSchema.addGraphQLType(nodeInterface, true); + parseGraphQLSchema.relayNodeInterface = nodeInterface; + parseGraphQLSchema.addGraphQLQuery('node', nodeField, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZGVmYXVsdFJlbGF5U2NoZW1hLmpzIl0sIm5hbWVzIjpbIkdMT0JBTF9JRF9BVFQiLCJkZXNjcmlwdGlvbiIsInR5cGUiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiT0JKRUNUX0lEIiwibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsIm5vZGVJbnRlcmZhY2UiLCJub2RlRmllbGQiLCJnbG9iYWxJZCIsImNvbnRleHQiLCJxdWVyeUluZm8iLCJpZCIsImNvbmZpZyIsImF1dGgiLCJpbmZvIiwic2VsZWN0ZWRGaWVsZHMiLCJrZXlzIiwiaW5jbHVkZSIsImNsYXNzTmFtZSIsIm9iamVjdHNRdWVyaWVzIiwiZ2V0T2JqZWN0IiwidW5kZWZpbmVkIiwicGFyc2VDbGFzc2VzIiwiZmluZCIsImUiLCJoYW5kbGVFcnJvciIsIm9iaiIsInBhcnNlQ2xhc3NUeXBlcyIsImNsYXNzR3JhcGhRTE91dHB1dFR5cGUiLCJhZGRHcmFwaFFMVHlwZSIsInJlbGF5Tm9kZUludGVyZmFjZSIsImFkZEdyYXBoUUxRdWVyeSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7Ozs7Ozs7OztBQUVBLE1BQU1BLGFBQWEsR0FBRztBQUNwQkMsRUFBQUEsV0FBVyxFQUFFLHdCQURPO0FBRXBCQyxFQUFBQSxJQUFJLEVBQUVDLG1CQUFtQixDQUFDQztBQUZOLENBQXRCOzs7QUFLQSxNQUFNQyxJQUFJLEdBQUdDLGtCQUFrQixJQUFJO0FBQ2pDLFFBQU07QUFBRUMsSUFBQUEsYUFBRjtBQUFpQkMsSUFBQUE7QUFBakIsTUFBK0IsbUNBQ25DLE9BQU9DLFFBQVAsRUFBaUJDLE9BQWpCLEVBQTBCQyxTQUExQixLQUF3QztBQUN0QyxRQUFJO0FBQ0YsWUFBTTtBQUFFVCxRQUFBQSxJQUFGO0FBQVFVLFFBQUFBO0FBQVIsVUFBZSxnQ0FBYUgsUUFBYixDQUFyQjtBQUNBLFlBQU07QUFBRUksUUFBQUEsTUFBRjtBQUFVQyxRQUFBQSxJQUFWO0FBQWdCQyxRQUFBQTtBQUFoQixVQUF5QkwsT0FBL0I7QUFDQSxZQUFNTSxjQUFjLEdBQUcsZ0NBQWNMLFNBQWQsQ0FBdkI7QUFFQSxZQUFNO0FBQUVNLFFBQUFBLElBQUY7QUFBUUMsUUFBQUE7QUFBUixVQUFvQiw0Q0FBc0JGLGNBQXRCLENBQTFCO0FBRUE7QUFDRUcsUUFBQUEsU0FBUyxFQUFFakI7QUFEYixVQUVNLE1BQU1rQixjQUFjLENBQUNDLFNBQWYsQ0FDUm5CLElBRFEsRUFFUlUsRUFGUSxFQUdSSyxJQUhRLEVBSVJDLE9BSlEsRUFLUkksU0FMUSxFQU1SQSxTQU5RLEVBT1JULE1BUFEsRUFRUkMsSUFSUSxFQVNSQyxJQVRRLEVBVVJULGtCQUFrQixDQUFDaUIsWUFBbkIsQ0FBZ0NDLElBQWhDLENBQ0UsQ0FBQztBQUFFTCxRQUFBQTtBQUFGLE9BQUQsS0FBbUJqQixJQUFJLEtBQUtpQixTQUQ5QixDQVZRLENBRlo7QUFpQkQsS0F4QkQsQ0F3QkUsT0FBT00sQ0FBUCxFQUFVO0FBQ1ZuQixNQUFBQSxrQkFBa0IsQ0FBQ29CLFdBQW5CLENBQStCRCxDQUEvQjtBQUNEO0FBQ0YsR0E3QmtDLEVBOEJuQ0UsR0FBRyxJQUFJO0FBQ0wsV0FBT3JCLGtCQUFrQixDQUFDc0IsZUFBbkIsQ0FBbUNELEdBQUcsQ0FBQ1IsU0FBdkMsRUFDSlUsc0JBREg7QUFFRCxHQWpDa0MsQ0FBckM7QUFvQ0F2QixFQUFBQSxrQkFBa0IsQ0FBQ3dCLGNBQW5CLENBQWtDdkIsYUFBbEMsRUFBaUQsSUFBakQ7QUFDQUQsRUFBQUEsa0JBQWtCLENBQUN5QixrQkFBbkIsR0FBd0N4QixhQUF4QztBQUNBRCxFQUFBQSxrQkFBa0IsQ0FBQzBCLGVBQW5CLENBQW1DLE1BQW5DLEVBQTJDeEIsU0FBM0MsRUFBc0QsSUFBdEQ7QUFDRCxDQXhDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vZGVEZWZpbml0aW9ucywgZnJvbUdsb2JhbElkIH0gZnJvbSAnZ3JhcGhxbC1yZWxheSc7XG5pbXBvcnQgZ2V0RmllbGROYW1lcyBmcm9tICdncmFwaHFsLWxpc3QtZmllbGRzJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMVHlwZXMgZnJvbSAnLi9kZWZhdWx0R3JhcGhRTFR5cGVzJztcbmltcG9ydCAqIGFzIG9iamVjdHNRdWVyaWVzIGZyb20gJy4uL2hlbHBlcnMvb2JqZWN0c1F1ZXJpZXMnO1xuaW1wb3J0IHsgZXh0cmFjdEtleXNBbmRJbmNsdWRlIH0gZnJvbSAnLi9wYXJzZUNsYXNzVHlwZXMnO1xuXG5jb25zdCBHTE9CQUxfSURfQVRUID0ge1xuICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGdsb2JhbCBpZC4nLFxuICB0eXBlOiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVF9JRCxcbn07XG5cbmNvbnN0IGxvYWQgPSBwYXJzZUdyYXBoUUxTY2hlbWEgPT4ge1xuICBjb25zdCB7IG5vZGVJbnRlcmZhY2UsIG5vZGVGaWVsZCB9ID0gbm9kZURlZmluaXRpb25zKFxuICAgIGFzeW5jIChnbG9iYWxJZCwgY29udGV4dCwgcXVlcnlJbmZvKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB7IHR5cGUsIGlkIH0gPSBmcm9tR2xvYmFsSWQoZ2xvYmFsSWQpO1xuICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRGaWVsZHMgPSBnZXRGaWVsZE5hbWVzKHF1ZXJ5SW5mbyk7XG5cbiAgICAgICAgY29uc3QgeyBrZXlzLCBpbmNsdWRlIH0gPSBleHRyYWN0S2V5c0FuZEluY2x1ZGUoc2VsZWN0ZWRGaWVsZHMpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY2xhc3NOYW1lOiB0eXBlLFxuICAgICAgICAgIC4uLihhd2FpdCBvYmplY3RzUXVlcmllcy5nZXRPYmplY3QoXG4gICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICBrZXlzLFxuICAgICAgICAgICAgaW5jbHVkZSxcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvLFxuICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3Nlcy5maW5kKFxuICAgICAgICAgICAgICAoeyBjbGFzc05hbWUgfSkgPT4gdHlwZSA9PT0gY2xhc3NOYW1lXG4gICAgICAgICAgICApXG4gICAgICAgICAgKSksXG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIG9iaiA9PiB7XG4gICAgICByZXR1cm4gcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1tvYmouY2xhc3NOYW1lXVxuICAgICAgICAuY2xhc3NHcmFwaFFMT3V0cHV0VHlwZTtcbiAgICB9XG4gICk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKG5vZGVJbnRlcmZhY2UsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEucmVsYXlOb2RlSW50ZXJmYWNlID0gbm9kZUludGVyZmFjZTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxRdWVyeSgnbm9kZScsIG5vZGVGaWVsZCwgdHJ1ZSk7XG59O1xuXG5leHBvcnQgeyBHTE9CQUxfSURfQVRULCBsb2FkIH07XG4iXX0= \ 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..0b44025096 --- /dev/null +++ b/lib/GraphQL/loaders/filesMutations.js @@ -0,0 +1,103 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.handleUpload = exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlRelay = require("graphql-relay"); + +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 handleUpload = async (upload, config) => { + 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 { + fileInfo: 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}.`); + } +}; + +exports.handleUpload = handleUpload; + +const load = parseGraphQLSchema => { + const createMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'CreateFile', + description: 'The createFile mutation can be used to create and upload a new file.', + inputFields: { + upload: { + description: 'This is the new file to be created and uploaded.', + type: new _graphql.GraphQLNonNull(_graphqlUpload.GraphQLUpload) + } + }, + outputFields: { + fileInfo: { + description: 'This is the created file info.', + type: new _graphql.GraphQLNonNull(defaultGraphQLTypes.FILE_INFO) + } + }, + mutateAndGetPayload: async (args, context) => { + try { + const { + upload + } = args; + const { + config + } = context; + return handleUpload(upload, config); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(createMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(createMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('createFile', createMutation, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZmlsZXNNdXRhdGlvbnMuanMiXSwibmFtZXMiOlsiaGFuZGxlVXBsb2FkIiwidXBsb2FkIiwiY29uZmlnIiwiY3JlYXRlUmVhZFN0cmVhbSIsImZpbGVuYW1lIiwibWltZXR5cGUiLCJkYXRhIiwic3RyZWFtIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJjaHVua3MiLCJvbiIsImNodW5rIiwicHVzaCIsIkJ1ZmZlciIsImNvbmNhdCIsImxlbmd0aCIsIlBhcnNlIiwiRXJyb3IiLCJGSUxFX1NBVkVfRVJST1IiLCJJTlZBTElEX0ZJTEVfTkFNRSIsIm1hdGNoIiwiZmlsZUluZm8iLCJmaWxlc0NvbnRyb2xsZXIiLCJjcmVhdGVGaWxlIiwiZSIsImxvZ2dlciIsImVycm9yIiwibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsImNyZWF0ZU11dGF0aW9uIiwibmFtZSIsImRlc2NyaXB0aW9uIiwiaW5wdXRGaWVsZHMiLCJ0eXBlIiwiR3JhcGhRTE5vbk51bGwiLCJHcmFwaFFMVXBsb2FkIiwib3V0cHV0RmllbGRzIiwiZGVmYXVsdEdyYXBoUUxUeXBlcyIsIkZJTEVfSU5GTyIsIm11dGF0ZUFuZEdldFBheWxvYWQiLCJhcmdzIiwiY29udGV4dCIsImhhbmRsZUVycm9yIiwiYWRkR3JhcGhRTFR5cGUiLCJpbnB1dCIsIm9mVHlwZSIsImFkZEdyYXBoUUxNdXRhdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVBLE1BQU1BLFlBQVksR0FBRyxPQUFPQyxNQUFQLEVBQWVDLE1BQWYsS0FBMEI7QUFDN0MsUUFBTTtBQUFFQyxJQUFBQSxnQkFBRjtBQUFvQkMsSUFBQUEsUUFBcEI7QUFBOEJDLElBQUFBO0FBQTlCLE1BQTJDLE1BQU1KLE1BQXZEO0FBQ0EsTUFBSUssSUFBSSxHQUFHLElBQVg7O0FBQ0EsTUFBSUgsZ0JBQUosRUFBc0I7QUFDcEIsVUFBTUksTUFBTSxHQUFHSixnQkFBZ0IsRUFBL0I7QUFDQUcsSUFBQUEsSUFBSSxHQUFHLE1BQU0sSUFBSUUsT0FBSixDQUFZLENBQUNDLE9BQUQsRUFBVUMsTUFBVixLQUFxQjtBQUM1QyxZQUFNQyxNQUFNLEdBQUcsRUFBZjtBQUNBSixNQUFBQSxNQUFNLENBQ0hLLEVBREgsQ0FDTSxPQUROLEVBQ2VGLE1BRGYsRUFFR0UsRUFGSCxDQUVNLE1BRk4sRUFFY0MsS0FBSyxJQUFJRixNQUFNLENBQUNHLElBQVAsQ0FBWUQsS0FBWixDQUZ2QixFQUdHRCxFQUhILENBR00sS0FITixFQUdhLE1BQU1ILE9BQU8sQ0FBQ00sTUFBTSxDQUFDQyxNQUFQLENBQWNMLE1BQWQsQ0FBRCxDQUgxQjtBQUlELEtBTlksQ0FBYjtBQU9EOztBQUVELE1BQUksQ0FBQ0wsSUFBRCxJQUFTLENBQUNBLElBQUksQ0FBQ1csTUFBbkIsRUFBMkI7QUFDekIsVUFBTSxJQUFJQyxjQUFNQyxLQUFWLENBQWdCRCxjQUFNQyxLQUFOLENBQVlDLGVBQTVCLEVBQTZDLHNCQUE3QyxDQUFOO0FBQ0Q7O0FBRUQsTUFBSWhCLFFBQVEsQ0FBQ2EsTUFBVCxHQUFrQixHQUF0QixFQUEyQjtBQUN6QixVQUFNLElBQUlDLGNBQU1DLEtBQVYsQ0FBZ0JELGNBQU1DLEtBQU4sQ0FBWUUsaUJBQTVCLEVBQStDLG9CQUEvQyxDQUFOO0FBQ0Q7O0FBRUQsTUFBSSxDQUFDakIsUUFBUSxDQUFDa0IsS0FBVCxDQUFlLG9DQUFmLENBQUwsRUFBMkQ7QUFDekQsVUFBTSxJQUFJSixjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUUsaUJBRFIsRUFFSix1Q0FGSSxDQUFOO0FBSUQ7O0FBRUQsTUFBSTtBQUNGLFdBQU87QUFDTEUsTUFBQUEsUUFBUSxFQUFFLE1BQU1yQixNQUFNLENBQUNzQixlQUFQLENBQXVCQyxVQUF2QixDQUNkdkIsTUFEYyxFQUVkRSxRQUZjLEVBR2RFLElBSGMsRUFJZEQsUUFKYztBQURYLEtBQVA7QUFRRCxHQVRELENBU0UsT0FBT3FCLENBQVAsRUFBVTtBQUNWQyxvQkFBT0MsS0FBUCxDQUFhLHlCQUFiLEVBQXdDRixDQUF4Qzs7QUFDQSxVQUFNLElBQUlSLGNBQU1DLEtBQVYsQ0FDSkQsY0FBTUMsS0FBTixDQUFZQyxlQURSLEVBRUgseUJBQXdCaEIsUUFBUyxHQUY5QixDQUFOO0FBSUQ7QUFDRixDQTdDRDs7OztBQStDQSxNQUFNeUIsSUFBSSxHQUFHQyxrQkFBa0IsSUFBSTtBQUNqQyxRQUFNQyxjQUFjLEdBQUcsZ0RBQTZCO0FBQ2xEQyxJQUFBQSxJQUFJLEVBQUUsWUFENEM7QUFFbERDLElBQUFBLFdBQVcsRUFDVCxzRUFIZ0Q7QUFJbERDLElBQUFBLFdBQVcsRUFBRTtBQUNYakMsTUFBQUEsTUFBTSxFQUFFO0FBQ05nQyxRQUFBQSxXQUFXLEVBQUUsa0RBRFA7QUFFTkUsUUFBQUEsSUFBSSxFQUFFLElBQUlDLHVCQUFKLENBQW1CQyw0QkFBbkI7QUFGQTtBQURHLEtBSnFDO0FBVWxEQyxJQUFBQSxZQUFZLEVBQUU7QUFDWmYsTUFBQUEsUUFBUSxFQUFFO0FBQ1JVLFFBQUFBLFdBQVcsRUFBRSxnQ0FETDtBQUVSRSxRQUFBQSxJQUFJLEVBQUUsSUFBSUMsdUJBQUosQ0FBbUJHLG1CQUFtQixDQUFDQyxTQUF2QztBQUZFO0FBREUsS0FWb0M7QUFnQmxEQyxJQUFBQSxtQkFBbUIsRUFBRSxPQUFPQyxJQUFQLEVBQWFDLE9BQWIsS0FBeUI7QUFDNUMsVUFBSTtBQUNGLGNBQU07QUFBRTFDLFVBQUFBO0FBQUYsWUFBYXlDLElBQW5CO0FBQ0EsY0FBTTtBQUFFeEMsVUFBQUE7QUFBRixZQUFheUMsT0FBbkI7QUFDQSxlQUFPM0MsWUFBWSxDQUFDQyxNQUFELEVBQVNDLE1BQVQsQ0FBbkI7QUFDRCxPQUpELENBSUUsT0FBT3dCLENBQVAsRUFBVTtBQUNWSSxRQUFBQSxrQkFBa0IsQ0FBQ2MsV0FBbkIsQ0FBK0JsQixDQUEvQjtBQUNEO0FBQ0Y7QUF4QmlELEdBQTdCLENBQXZCO0FBMkJBSSxFQUFBQSxrQkFBa0IsQ0FBQ2UsY0FBbkIsQ0FDRWQsY0FBYyxDQUFDVyxJQUFmLENBQW9CSSxLQUFwQixDQUEwQlgsSUFBMUIsQ0FBK0JZLE1BRGpDLEVBRUUsSUFGRixFQUdFLElBSEY7QUFLQWpCLEVBQUFBLGtCQUFrQixDQUFDZSxjQUFuQixDQUFrQ2QsY0FBYyxDQUFDSSxJQUFqRCxFQUF1RCxJQUF2RCxFQUE2RCxJQUE3RDtBQUNBTCxFQUFBQSxrQkFBa0IsQ0FBQ2tCLGtCQUFuQixDQUNFLFlBREYsRUFFRWpCLGNBRkYsRUFHRSxJQUhGLEVBSUUsSUFKRjtBQU1ELENBeENEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR3JhcGhRTE5vbk51bGwgfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCB7IG11dGF0aW9uV2l0aENsaWVudE11dGF0aW9uSWQgfSBmcm9tICdncmFwaHFsLXJlbGF5JztcbmltcG9ydCB7IEdyYXBoUUxVcGxvYWQgfSBmcm9tICdncmFwaHFsLXVwbG9hZCc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4vZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4uLy4uL2xvZ2dlcic7XG5cbmNvbnN0IGhhbmRsZVVwbG9hZCA9IGFzeW5jICh1cGxvYWQsIGNvbmZpZykgPT4ge1xuICBjb25zdCB7IGNyZWF0ZVJlYWRTdHJlYW0sIGZpbGVuYW1lLCBtaW1ldHlwZSB9ID0gYXdhaXQgdXBsb2FkO1xuICBsZXQgZGF0YSA9IG51bGw7XG4gIGlmIChjcmVhdGVSZWFkU3RyZWFtKSB7XG4gICAgY29uc3Qgc3RyZWFtID0gY3JlYXRlUmVhZFN0cmVhbSgpO1xuICAgIGRhdGEgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBjaHVua3MgPSBbXTtcbiAgICAgIHN0cmVhbVxuICAgICAgICAub24oJ2Vycm9yJywgcmVqZWN0KVxuICAgICAgICAub24oJ2RhdGEnLCBjaHVuayA9PiBjaHVua3MucHVzaChjaHVuaykpXG4gICAgICAgIC5vbignZW5kJywgKCkgPT4gcmVzb2x2ZShCdWZmZXIuY29uY2F0KGNodW5rcykpKTtcbiAgICB9KTtcbiAgfVxuXG4gIGlmICghZGF0YSB8fCAhZGF0YS5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLCAnSW52YWxpZCBmaWxlIHVwbG9hZC4nKTtcbiAgfVxuXG4gIGlmIChmaWxlbmFtZS5sZW5ndGggPiAxMjgpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9GSUxFX05BTUUsICdGaWxlbmFtZSB0b28gbG9uZy4nKTtcbiAgfVxuXG4gIGlmICghZmlsZW5hbWUubWF0Y2goL15bX2EtekEtWjAtOV1bYS16QS1aMC05QFxcLlxcIH5fLV0qJC8pKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9GSUxFX05BTUUsXG4gICAgICAnRmlsZW5hbWUgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzLidcbiAgICApO1xuICB9XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4ge1xuICAgICAgZmlsZUluZm86IGF3YWl0IGNvbmZpZy5maWxlc0NvbnRyb2xsZXIuY3JlYXRlRmlsZShcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBmaWxlbmFtZSxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgbWltZXR5cGVcbiAgICAgICksXG4gICAgfTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxvZ2dlci5lcnJvcignRXJyb3IgY3JlYXRpbmcgYSBmaWxlOiAnLCBlKTtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsXG4gICAgICBgQ291bGQgbm90IHN0b3JlIGZpbGU6ICR7ZmlsZW5hbWV9LmBcbiAgICApO1xuICB9XG59O1xuXG5jb25zdCBsb2FkID0gcGFyc2VHcmFwaFFMU2NoZW1hID0+IHtcbiAgY29uc3QgY3JlYXRlTXV0YXRpb24gPSBtdXRhdGlvbldpdGhDbGllbnRNdXRhdGlvbklkKHtcbiAgICBuYW1lOiAnQ3JlYXRlRmlsZScsXG4gICAgZGVzY3JpcHRpb246XG4gICAgICAnVGhlIGNyZWF0ZUZpbGUgbXV0YXRpb24gY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGFuZCB1cGxvYWQgYSBuZXcgZmlsZS4nLFxuICAgIGlucHV0RmllbGRzOiB7XG4gICAgICB1cGxvYWQ6IHtcbiAgICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSBuZXcgZmlsZSB0byBiZSBjcmVhdGVkIGFuZCB1cGxvYWRlZC4nLFxuICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTFVwbG9hZCksXG4gICAgICB9LFxuICAgIH0sXG4gICAgb3V0cHV0RmllbGRzOiB7XG4gICAgICBmaWxlSW5mbzoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGNyZWF0ZWQgZmlsZSBpbmZvLicsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChkZWZhdWx0R3JhcGhRTFR5cGVzLkZJTEVfSU5GTyksXG4gICAgICB9LFxuICAgIH0sXG4gICAgbXV0YXRlQW5kR2V0UGF5bG9hZDogYXN5bmMgKGFyZ3MsIGNvbnRleHQpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHsgdXBsb2FkIH0gPSBhcmdzO1xuICAgICAgICBjb25zdCB7IGNvbmZpZyB9ID0gY29udGV4dDtcbiAgICAgICAgcmV0dXJuIGhhbmRsZVVwbG9hZCh1cGxvYWQsIGNvbmZpZyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgY3JlYXRlTXV0YXRpb24uYXJncy5pbnB1dC50eXBlLm9mVHlwZSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKGNyZWF0ZU11dGF0aW9uLnR5cGUsIHRydWUsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTE11dGF0aW9uKFxuICAgICdjcmVhdGVGaWxlJyxcbiAgICBjcmVhdGVNdXRhdGlvbixcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbn07XG5cbmV4cG9ydCB7IGxvYWQsIGhhbmRsZVVwbG9hZCB9O1xuIl19 \ 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..94209bb6bf --- /dev/null +++ b/lib/GraphQL/loaders/functionsMutations.js @@ -0,0 +1,90 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlRelay = require("graphql-relay"); + +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); + const callCloudCodeMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'CallCloudCode', + description: 'The callCloudCode mutation can be used to invoke a cloud code function.', + inputFields: { + 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 + } + }, + outputFields: { + result: { + description: 'This is the result value of the cloud code function execution.', + type: defaultGraphQLTypes.ANY + } + }, + mutateAndGetPayload: async (args, context) => { + try { + const { + functionName, + params + } = args; + const { + config, + auth, + info + } = context; + return { + result: (await _FunctionsRouter.FunctionsRouter.handleCloudFunction({ + params: { + functionName + }, + config, + auth, + info, + body: params + })).response.result + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(callCloudCodeMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(callCloudCodeMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('callCloudCode', callCloudCodeMutation, true, true); + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvZnVuY3Rpb25zTXV0YXRpb25zLmpzIl0sIm5hbWVzIjpbImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJmdW5jdGlvbk5hbWVzIiwibGVuZ3RoIiwiY2xvdWRDb2RlRnVuY3Rpb25FbnVtIiwiYWRkR3JhcGhRTFR5cGUiLCJHcmFwaFFMRW51bVR5cGUiLCJuYW1lIiwiZGVzY3JpcHRpb24iLCJ2YWx1ZXMiLCJyZWR1Y2UiLCJmdW5jdGlvbk5hbWUiLCJ2YWx1ZSIsImNhbGxDbG91ZENvZGVNdXRhdGlvbiIsImlucHV0RmllbGRzIiwidHlwZSIsIkdyYXBoUUxOb25OdWxsIiwicGFyYW1zIiwiZGVmYXVsdEdyYXBoUUxUeXBlcyIsIk9CSkVDVCIsIm91dHB1dEZpZWxkcyIsInJlc3VsdCIsIkFOWSIsIm11dGF0ZUFuZEdldFBheWxvYWQiLCJhcmdzIiwiY29udGV4dCIsImNvbmZpZyIsImF1dGgiLCJpbmZvIiwiRnVuY3Rpb25zUm91dGVyIiwiaGFuZGxlQ2xvdWRGdW5jdGlvbiIsImJvZHkiLCJyZXNwb25zZSIsImUiLCJoYW5kbGVFcnJvciIsImlucHV0Iiwib2ZUeXBlIiwiYWRkR3JhcGhRTE11dGF0aW9uIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7OztBQUVBLE1BQU1BLElBQUksR0FBR0Msa0JBQWtCLElBQUk7QUFDakMsTUFBSUEsa0JBQWtCLENBQUNDLGFBQW5CLENBQWlDQyxNQUFqQyxHQUEwQyxDQUE5QyxFQUFpRDtBQUMvQyxVQUFNQyxxQkFBcUIsR0FBR0gsa0JBQWtCLENBQUNJLGNBQW5CLENBQzVCLElBQUlDLHdCQUFKLENBQW9CO0FBQ2xCQyxNQUFBQSxJQUFJLEVBQUUsbUJBRFk7QUFFbEJDLE1BQUFBLFdBQVcsRUFDVCx3RkFIZ0I7QUFJbEJDLE1BQUFBLE1BQU0sRUFBRVIsa0JBQWtCLENBQUNDLGFBQW5CLENBQWlDUSxNQUFqQyxDQUNOLENBQUNELE1BQUQsRUFBU0UsWUFBVCx1QkFDS0YsTUFETDtBQUVFLFNBQUNFLFlBQUQsR0FBZ0I7QUFBRUMsVUFBQUEsS0FBSyxFQUFFRDtBQUFUO0FBRmxCLFFBRE0sRUFLTixFQUxNO0FBSlUsS0FBcEIsQ0FENEIsRUFhNUIsSUFiNEIsRUFjNUIsSUFkNEIsQ0FBOUI7QUFpQkEsVUFBTUUscUJBQXFCLEdBQUcsZ0RBQTZCO0FBQ3pETixNQUFBQSxJQUFJLEVBQUUsZUFEbUQ7QUFFekRDLE1BQUFBLFdBQVcsRUFDVCx5RUFIdUQ7QUFJekRNLE1BQUFBLFdBQVcsRUFBRTtBQUNYSCxRQUFBQSxZQUFZLEVBQUU7QUFDWkgsVUFBQUEsV0FBVyxFQUFFLG9DQUREO0FBRVpPLFVBQUFBLElBQUksRUFBRSxJQUFJQyx1QkFBSixDQUFtQloscUJBQW5CO0FBRk0sU0FESDtBQUtYYSxRQUFBQSxNQUFNLEVBQUU7QUFDTlQsVUFBQUEsV0FBVyxFQUFFLG9EQURQO0FBRU5PLFVBQUFBLElBQUksRUFBRUcsbUJBQW1CLENBQUNDO0FBRnBCO0FBTEcsT0FKNEM7QUFjekRDLE1BQUFBLFlBQVksRUFBRTtBQUNaQyxRQUFBQSxNQUFNLEVBQUU7QUFDTmIsVUFBQUEsV0FBVyxFQUNULGdFQUZJO0FBR05PLFVBQUFBLElBQUksRUFBRUcsbUJBQW1CLENBQUNJO0FBSHBCO0FBREksT0FkMkM7QUFxQnpEQyxNQUFBQSxtQkFBbUIsRUFBRSxPQUFPQyxJQUFQLEVBQWFDLE9BQWIsS0FBeUI7QUFDNUMsWUFBSTtBQUNGLGdCQUFNO0FBQUVkLFlBQUFBLFlBQUY7QUFBZ0JNLFlBQUFBO0FBQWhCLGNBQTJCTyxJQUFqQztBQUNBLGdCQUFNO0FBQUVFLFlBQUFBLE1BQUY7QUFBVUMsWUFBQUEsSUFBVjtBQUFnQkMsWUFBQUE7QUFBaEIsY0FBeUJILE9BQS9CO0FBRUEsaUJBQU87QUFDTEosWUFBQUEsTUFBTSxFQUFFLENBQ04sTUFBTVEsaUNBQWdCQyxtQkFBaEIsQ0FBb0M7QUFDeENiLGNBQUFBLE1BQU0sRUFBRTtBQUNOTixnQkFBQUE7QUFETSxlQURnQztBQUl4Q2UsY0FBQUEsTUFKd0M7QUFLeENDLGNBQUFBLElBTHdDO0FBTXhDQyxjQUFBQSxJQU53QztBQU94Q0csY0FBQUEsSUFBSSxFQUFFZDtBQVBrQyxhQUFwQyxDQURBLEVBVU5lLFFBVk0sQ0FVR1g7QUFYTixXQUFQO0FBYUQsU0FqQkQsQ0FpQkUsT0FBT1ksQ0FBUCxFQUFVO0FBQ1ZoQyxVQUFBQSxrQkFBa0IsQ0FBQ2lDLFdBQW5CLENBQStCRCxDQUEvQjtBQUNEO0FBQ0Y7QUExQ3dELEtBQTdCLENBQTlCO0FBNkNBaEMsSUFBQUEsa0JBQWtCLENBQUNJLGNBQW5CLENBQ0VRLHFCQUFxQixDQUFDVyxJQUF0QixDQUEyQlcsS0FBM0IsQ0FBaUNwQixJQUFqQyxDQUFzQ3FCLE1BRHhDLEVBRUUsSUFGRixFQUdFLElBSEY7QUFLQW5DLElBQUFBLGtCQUFrQixDQUFDSSxjQUFuQixDQUFrQ1EscUJBQXFCLENBQUNFLElBQXhELEVBQThELElBQTlELEVBQW9FLElBQXBFO0FBQ0FkLElBQUFBLGtCQUFrQixDQUFDb0Msa0JBQW5CLENBQ0UsZUFERixFQUVFeEIscUJBRkYsRUFHRSxJQUhGLEVBSUUsSUFKRjtBQU1EO0FBQ0YsQ0E3RUQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBHcmFwaFFMTm9uTnVsbCwgR3JhcGhRTEVudW1UeXBlIH0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgeyBtdXRhdGlvbldpdGhDbGllbnRNdXRhdGlvbklkIH0gZnJvbSAnZ3JhcGhxbC1yZWxheSc7XG5pbXBvcnQgeyBGdW5jdGlvbnNSb3V0ZXIgfSBmcm9tICcuLi8uLi9Sb3V0ZXJzL0Z1bmN0aW9uc1JvdXRlcic7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4vZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5cbmNvbnN0IGxvYWQgPSBwYXJzZUdyYXBoUUxTY2hlbWEgPT4ge1xuICBpZiAocGFyc2VHcmFwaFFMU2NoZW1hLmZ1bmN0aW9uTmFtZXMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGNsb3VkQ29kZUZ1bmN0aW9uRW51bSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICAgIG5ldyBHcmFwaFFMRW51bVR5cGUoe1xuICAgICAgICBuYW1lOiAnQ2xvdWRDb2RlRnVuY3Rpb24nLFxuICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAnVGhlIENsb3VkQ29kZUZ1bmN0aW9uIGVudW0gdHlwZSBjb250YWlucyBhIGxpc3Qgb2YgYWxsIGF2YWlsYWJsZSBjbG91ZCBjb2RlIGZ1bmN0aW9ucy4nLFxuICAgICAgICB2YWx1ZXM6IHBhcnNlR3JhcGhRTFNjaGVtYS5mdW5jdGlvbk5hbWVzLnJlZHVjZShcbiAgICAgICAgICAodmFsdWVzLCBmdW5jdGlvbk5hbWUpID0+ICh7XG4gICAgICAgICAgICAuLi52YWx1ZXMsXG4gICAgICAgICAgICBbZnVuY3Rpb25OYW1lXTogeyB2YWx1ZTogZnVuY3Rpb25OYW1lIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAge31cbiAgICAgICAgKSxcbiAgICAgIH0pLFxuICAgICAgdHJ1ZSxcbiAgICAgIHRydWVcbiAgICApO1xuXG4gICAgY29uc3QgY2FsbENsb3VkQ29kZU11dGF0aW9uID0gbXV0YXRpb25XaXRoQ2xpZW50TXV0YXRpb25JZCh7XG4gICAgICBuYW1lOiAnQ2FsbENsb3VkQ29kZScsXG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgJ1RoZSBjYWxsQ2xvdWRDb2RlIG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIGludm9rZSBhIGNsb3VkIGNvZGUgZnVuY3Rpb24uJyxcbiAgICAgIGlucHV0RmllbGRzOiB7XG4gICAgICAgIGZ1bmN0aW9uTmFtZToge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkLicsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKGNsb3VkQ29kZUZ1bmN0aW9uRW51bSksXG4gICAgICAgIH0sXG4gICAgICAgIHBhcmFtczoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhlc2UgYXJlIHRoZSBwYXJhbXMgdG8gYmUgcGFzc2VkIHRvIHRoZSBmdW5jdGlvbi4nLFxuICAgICAgICAgIHR5cGU6IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNULFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIG91dHB1dEZpZWxkczoge1xuICAgICAgICByZXN1bHQ6IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICdUaGlzIGlzIHRoZSByZXN1bHQgdmFsdWUgb2YgdGhlIGNsb3VkIGNvZGUgZnVuY3Rpb24gZXhlY3V0aW9uLicsXG4gICAgICAgICAgdHlwZTogZGVmYXVsdEdyYXBoUUxUeXBlcy5BTlksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgbXV0YXRlQW5kR2V0UGF5bG9hZDogYXN5bmMgKGFyZ3MsIGNvbnRleHQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGZ1bmN0aW9uTmFtZSwgcGFyYW1zIH0gPSBhcmdzO1xuICAgICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlc3VsdDogKFxuICAgICAgICAgICAgICBhd2FpdCBGdW5jdGlvbnNSb3V0ZXIuaGFuZGxlQ2xvdWRGdW5jdGlvbih7XG4gICAgICAgICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICAgICAgICBmdW5jdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgICBpbmZvLFxuICAgICAgICAgICAgICAgIGJvZHk6IHBhcmFtcyxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICkucmVzcG9uc2UucmVzdWx0LFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgICBjYWxsQ2xvdWRDb2RlTXV0YXRpb24uYXJncy5pbnB1dC50eXBlLm9mVHlwZSxcbiAgICAgIHRydWUsXG4gICAgICB0cnVlXG4gICAgKTtcbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoY2FsbENsb3VkQ29kZU11dGF0aW9uLnR5cGUsIHRydWUsIHRydWUpO1xuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgICAnY2FsbENsb3VkQ29kZScsXG4gICAgICBjYWxsQ2xvdWRDb2RlTXV0YXRpb24sXG4gICAgICB0cnVlLFxuICAgICAgdHJ1ZVxuICAgICk7XG4gIH1cbn07XG5cbmV4cG9ydCB7IGxvYWQgfTtcbiJdfQ== \ 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..577f299c03 --- /dev/null +++ b/lib/GraphQL/loaders/parseClassMutations.js @@ -0,0 +1,288 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlRelay = require("graphql-relay"); + +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 ? includedFieldsString.split(',') : []; + const selectedFields = selectedFieldsString ? 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 getGraphQLQueryName = graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1); + const { + create: isCreateEnabled = true, + update: isUpdateEnabled = true, + destroy: isDestroyEnabled = true, + createAlias = '', + updateAlias = '', + destroyAlias = '' + } = (0, _parseGraphQLUtils.getParseClassMutationConfig)(parseClassConfig); + const { + classGraphQLCreateType, + classGraphQLUpdateType, + classGraphQLOutputType + } = parseGraphQLSchema.parseClassTypes[className]; + + if (isCreateEnabled) { + const createGraphQLMutationName = createAlias || `create${graphQLClassName}`; + const createGraphQLMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: `Create${graphQLClassName}`, + description: `The ${createGraphQLMutationName} mutation can be used to create a new object of the ${graphQLClassName} class.`, + inputFields: { + fields: { + description: 'These are the fields that will be used to create the new object.', + type: classGraphQLCreateType || defaultGraphQLTypes.OBJECT + } + }, + outputFields: { + [getGraphQLQueryName]: { + description: 'This is the created object.', + type: new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT) + } + }, + mutateAndGetPayload: async (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).filter(field => field.startsWith(`${getGraphQLQueryName}.`)).map(field => field.replace(`${getGraphQLQueryName}.`, '')); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + const { + keys: requiredKeys, + needGet + } = getOnlyRequiredFields(fields, keys, include, ['id', 'objectId', 'createdAt', 'updatedAt']); + const needToGetAllKeys = objectsQueries.needToGetAllKeys(parseClass.fields, keys); + let optimizedObject = {}; + + if (needGet && !needToGetAllKeys) { + optimizedObject = await objectsQueries.getObject(className, createdObject.objectId, requiredKeys, include, undefined, undefined, config, auth, info, parseClass); + } else if (needToGetAllKeys) { + optimizedObject = await objectsQueries.getObject(className, createdObject.objectId, undefined, include, undefined, undefined, config, auth, info, parseClass); + } + + return { + [getGraphQLQueryName]: _objectSpread({}, createdObject, { + updatedAt: createdObject.createdAt + }, parseFields, {}, optimizedObject) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + + if (parseGraphQLSchema.addGraphQLType(createGraphQLMutation.args.input.type.ofType) && parseGraphQLSchema.addGraphQLType(createGraphQLMutation.type)) { + parseGraphQLSchema.addGraphQLMutation(createGraphQLMutationName, createGraphQLMutation); + } + } + + if (isUpdateEnabled) { + const updateGraphQLMutationName = updateAlias || `update${graphQLClassName}`; + const updateGraphQLMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: `Update${graphQLClassName}`, + description: `The ${updateGraphQLMutationName} mutation can be used to update an object of the ${graphQLClassName} class.`, + inputFields: { + id: defaultGraphQLTypes.GLOBAL_OR_OBJECT_ID_ATT, + fields: { + description: 'These are the fields that will be used to update the object.', + type: classGraphQLUpdateType || defaultGraphQLTypes.OBJECT + } + }, + outputFields: { + [getGraphQLQueryName]: { + description: 'This is the updated object.', + type: new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT) + } + }, + mutateAndGetPayload: async (args, context, mutationInfo) => { + try { + let { + id, + fields + } = args; + if (!fields) fields = {}; + const { + config, + auth, + info + } = context; + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(id); + + if (globalIdObject.type === className) { + id = globalIdObject.id; + } + + 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).filter(field => field.startsWith(`${getGraphQLQueryName}.`)).map(field => field.replace(`${getGraphQLQueryName}.`, '')); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + const { + keys: requiredKeys, + needGet + } = getOnlyRequiredFields(fields, keys, include, ['id', 'objectId', 'updatedAt']); + const needToGetAllKeys = objectsQueries.needToGetAllKeys(parseClass.fields, keys); + let optimizedObject = {}; + + if (needGet && !needToGetAllKeys) { + optimizedObject = await objectsQueries.getObject(className, id, requiredKeys, include, undefined, undefined, config, auth, info, parseClass); + } else if (needToGetAllKeys) { + optimizedObject = await objectsQueries.getObject(className, id, undefined, include, undefined, undefined, config, auth, info, parseClass); + } + + return { + [getGraphQLQueryName]: _objectSpread({ + objectId: id + }, updatedObject, {}, parseFields, {}, optimizedObject) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + + if (parseGraphQLSchema.addGraphQLType(updateGraphQLMutation.args.input.type.ofType) && parseGraphQLSchema.addGraphQLType(updateGraphQLMutation.type)) { + parseGraphQLSchema.addGraphQLMutation(updateGraphQLMutationName, updateGraphQLMutation); + } + } + + if (isDestroyEnabled) { + const deleteGraphQLMutationName = destroyAlias || `delete${graphQLClassName}`; + const deleteGraphQLMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: `Delete${graphQLClassName}`, + description: `The ${deleteGraphQLMutationName} mutation can be used to delete an object of the ${graphQLClassName} class.`, + inputFields: { + id: defaultGraphQLTypes.GLOBAL_OR_OBJECT_ID_ATT + }, + outputFields: { + [getGraphQLQueryName]: { + description: 'This is the deleted object.', + type: new _graphql.GraphQLNonNull(classGraphQLOutputType || defaultGraphQLTypes.OBJECT) + } + }, + mutateAndGetPayload: async (args, context, mutationInfo) => { + try { + let { + id + } = args; + const { + config, + auth, + info + } = context; + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(id); + + if (globalIdObject.type === className) { + id = globalIdObject.id; + } + + const selectedFields = (0, _graphqlListFields.default)(mutationInfo).filter(field => field.startsWith(`${getGraphQLQueryName}.`)).map(field => field.replace(`${getGraphQLQueryName}.`, '')); + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + let optimizedObject = {}; + + if (keys && keys.split(',').filter(key => !['id', 'objectId'].includes(key)).length > 0) { + optimizedObject = await objectsQueries.getObject(className, id, keys, include, undefined, undefined, config, auth, info, parseClass); + } + + await objectsMutations.deleteObject(className, id, config, auth, info); + return { + [getGraphQLQueryName]: _objectSpread({ + objectId: id + }, optimizedObject) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + + if (parseGraphQLSchema.addGraphQLType(deleteGraphQLMutation.args.input.type.ofType) && parseGraphQLSchema.addGraphQLType(deleteGraphQLMutation.type)) { + parseGraphQLSchema.addGraphQLMutation(deleteGraphQLMutationName, deleteGraphQLMutation); + } + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvcGFyc2VDbGFzc011dGF0aW9ucy5qcyJdLCJuYW1lcyI6WyJnZXRPbmx5UmVxdWlyZWRGaWVsZHMiLCJ1cGRhdGVkRmllbGRzIiwic2VsZWN0ZWRGaWVsZHNTdHJpbmciLCJpbmNsdWRlZEZpZWxkc1N0cmluZyIsIm5hdGl2ZU9iamVjdEZpZWxkcyIsImluY2x1ZGVkRmllbGRzIiwic3BsaXQiLCJzZWxlY3RlZEZpZWxkcyIsIm1pc3NpbmdGaWVsZHMiLCJmaWx0ZXIiLCJmaWVsZCIsImluY2x1ZGVzIiwiam9pbiIsImxlbmd0aCIsIm5lZWRHZXQiLCJrZXlzIiwibG9hZCIsInBhcnNlR3JhcGhRTFNjaGVtYSIsInBhcnNlQ2xhc3MiLCJwYXJzZUNsYXNzQ29uZmlnIiwiY2xhc3NOYW1lIiwiZ3JhcGhRTENsYXNzTmFtZSIsImdldEdyYXBoUUxRdWVyeU5hbWUiLCJjaGFyQXQiLCJ0b0xvd2VyQ2FzZSIsInNsaWNlIiwiY3JlYXRlIiwiaXNDcmVhdGVFbmFibGVkIiwidXBkYXRlIiwiaXNVcGRhdGVFbmFibGVkIiwiZGVzdHJveSIsImlzRGVzdHJveUVuYWJsZWQiLCJjcmVhdGVBbGlhcyIsInVwZGF0ZUFsaWFzIiwiZGVzdHJveUFsaWFzIiwiY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZSIsImNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIiwicGFyc2VDbGFzc1R5cGVzIiwiY3JlYXRlR3JhcGhRTE11dGF0aW9uTmFtZSIsImNyZWF0ZUdyYXBoUUxNdXRhdGlvbiIsIm5hbWUiLCJkZXNjcmlwdGlvbiIsImlucHV0RmllbGRzIiwiZmllbGRzIiwidHlwZSIsImRlZmF1bHRHcmFwaFFMVHlwZXMiLCJPQkpFQ1QiLCJvdXRwdXRGaWVsZHMiLCJHcmFwaFFMTm9uTnVsbCIsIm11dGF0ZUFuZEdldFBheWxvYWQiLCJhcmdzIiwiY29udGV4dCIsIm11dGF0aW9uSW5mbyIsImNvbmZpZyIsImF1dGgiLCJpbmZvIiwicGFyc2VGaWVsZHMiLCJyZXEiLCJjcmVhdGVkT2JqZWN0Iiwib2JqZWN0c011dGF0aW9ucyIsImNyZWF0ZU9iamVjdCIsInN0YXJ0c1dpdGgiLCJtYXAiLCJyZXBsYWNlIiwiaW5jbHVkZSIsInJlcXVpcmVkS2V5cyIsIm5lZWRUb0dldEFsbEtleXMiLCJvYmplY3RzUXVlcmllcyIsIm9wdGltaXplZE9iamVjdCIsImdldE9iamVjdCIsIm9iamVjdElkIiwidW5kZWZpbmVkIiwidXBkYXRlZEF0IiwiY3JlYXRlZEF0IiwiZSIsImhhbmRsZUVycm9yIiwiYWRkR3JhcGhRTFR5cGUiLCJpbnB1dCIsIm9mVHlwZSIsImFkZEdyYXBoUUxNdXRhdGlvbiIsInVwZGF0ZUdyYXBoUUxNdXRhdGlvbk5hbWUiLCJ1cGRhdGVHcmFwaFFMTXV0YXRpb24iLCJpZCIsIkdMT0JBTF9PUl9PQkpFQ1RfSURfQVRUIiwiZ2xvYmFsSWRPYmplY3QiLCJ1cGRhdGVkT2JqZWN0IiwidXBkYXRlT2JqZWN0IiwiZGVsZXRlR3JhcGhRTE11dGF0aW9uTmFtZSIsImRlbGV0ZUdyYXBoUUxNdXRhdGlvbiIsImtleSIsImRlbGV0ZU9iamVjdCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUlBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7Ozs7Ozs7OztBQUVBLE1BQU1BLHFCQUFxQixHQUFHLENBQzVCQyxhQUQ0QixFQUU1QkMsb0JBRjRCLEVBRzVCQyxvQkFINEIsRUFJNUJDLGtCQUo0QixLQUt6QjtBQUNILFFBQU1DLGNBQWMsR0FBR0Ysb0JBQW9CLEdBQ3ZDQSxvQkFBb0IsQ0FBQ0csS0FBckIsQ0FBMkIsR0FBM0IsQ0FEdUMsR0FFdkMsRUFGSjtBQUdBLFFBQU1DLGNBQWMsR0FBR0wsb0JBQW9CLEdBQ3ZDQSxvQkFBb0IsQ0FBQ0ksS0FBckIsQ0FBMkIsR0FBM0IsQ0FEdUMsR0FFdkMsRUFGSjtBQUdBLFFBQU1FLGFBQWEsR0FBR0Qs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SUFBdEIsQ0FBMkIyQixLQUEzQixDQUFpQ2pDLElBQWpDLENBQXNDa0MsTUFEeEMsS0FHQTlELGtCQUFrQixDQUFDNEQsY0FBbkIsQ0FBa0NZLHFCQUFxQixDQUFDNUMsSUFBeEQsQ0FKRixFQUtFO0FBQ0E1QixNQUFBQSxrQkFBa0IsQ0FBQytELGtCQUFuQixDQUNFUSx5QkFERixFQUVFQyxxQkFGRjtBQUlEO0FBQ0Y7QUFDRixDQTlVRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEdyYXBoUUxOb25OdWxsIH0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgeyBmcm9tR2xvYmFsSWQsIG11dGF0aW9uV2l0aENsaWVudE11dGF0aW9uSWQgfSBmcm9tICdncmFwaHFsLXJlbGF5JztcbmltcG9ydCBnZXRGaWVsZE5hbWVzIGZyb20gJ2dyYXBocWwtbGlzdC1maWVsZHMnO1xuaW1wb3J0ICogYXMgZGVmYXVsdEdyYXBoUUxUeXBlcyBmcm9tICcuL2RlZmF1bHRHcmFwaFFMVHlwZXMnO1xuaW1wb3J0IHtcbiAgZXh0cmFjdEtleXNBbmRJbmNsdWRlLFxuICBnZXRQYXJzZUNsYXNzTXV0YXRpb25Db25maWcsXG59IGZyb20gJy4uL3BhcnNlR3JhcGhRTFV0aWxzJztcbmltcG9ydCAqIGFzIG9iamVjdHNNdXRhdGlvbnMgZnJvbSAnLi4vaGVscGVycy9vYmplY3RzTXV0YXRpb25zJztcbmltcG9ydCAqIGFzIG9iamVjdHNRdWVyaWVzIGZyb20gJy4uL2hlbHBlcnMvb2JqZWN0c1F1ZXJpZXMnO1xuaW1wb3J0IHsgUGFyc2VHcmFwaFFMQ2xhc3NDb25maWcgfSBmcm9tICcuLi8uLi9Db250cm9sbGVycy9QYXJzZUdyYXBoUUxDb250cm9sbGVyJztcbmltcG9ydCB7IHRyYW5zZm9ybUNsYXNzTmFtZVRvR3JhcGhRTCB9IGZyb20gJy4uL3RyYW5zZm9ybWVycy9jbGFzc05hbWUnO1xuaW1wb3J0IHsgdHJhbnNmb3JtVHlwZXMgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvbXV0YXRpb24nO1xuXG5jb25zdCBnZXRPbmx5UmVxdWlyZWRGaWVsZHMgPSAoXG4gIHVwZGF0ZWRGaWVsZHMsXG4gIHNlbGVjdGVkRmllbGRzU3RyaW5nLFxuICBpbmNsdWRlZEZpZWxkc1N0cmluZyxcbiAgbmF0aXZlT2JqZWN0RmllbGRzXG4pID0+IHtcbiAgY29uc3QgaW5jbHVkZWRGaWVsZHMgPSBpbmNsdWRlZEZpZWxkc1N0cmluZ1xuICAgID8gaW5jbHVkZWRGaWVsZHNTdHJpbmcuc3BsaXQoJywnKVxuICAgIDogW107XG4gIGNvbnN0IHNlbGVjdGVkRmllbGRzID0gc2VsZWN0ZWRGaWVsZHNTdHJpbmdcbiAgICA/IHNlbGVjdGVkRmllbGRzU3RyaW5nLnNwbGl0KCcsJylcbiAgICA6IFtdO1xuICBjb25zdCBtaXNzaW5nRmllbGRzID0gc2VsZWN0ZWRGaWVsZHNcbiAgICAuZmlsdGVyKFxuICAgICAgZmllbGQgPT5cbiAgICAgICAgIW5hdGl2ZU9iamVjdEZpZWxkcy5pbmNsdWRlcyhmaWVsZCkgfHwgaW5jbHVkZWRGaWVsZHMuaW5jbHVkZXMoZmllbGQpXG4gICAgKVxuICAgIC5qb2luKCcsJyk7XG4gIGlmICghbWlzc2luZ0ZpZWxkcy5sZW5ndGgpIHtcbiAgICByZXR1cm4geyBuZWVkR2V0OiBmYWxzZSwga2V5czogJycgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4geyBuZWVkR2V0OiB0cnVlLCBrZXlzOiBtaXNzaW5nRmllbGRzIH07XG4gIH1cbn07XG5cbmNvbnN0IGxvYWQgPSBmdW5jdGlvbihcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICBwYXJzZUNsYXNzLFxuICBwYXJzZUNsYXNzQ29uZmlnOiA/UGFyc2VHcmFwaFFMQ2xhc3NDb25maWdcbikge1xuICBjb25zdCBjbGFzc05hbWUgPSBwYXJzZUNsYXNzLmNsYXNzTmFtZTtcbiAgY29uc3QgZ3JhcGhRTENsYXNzTmFtZSA9IHRyYW5zZm9ybUNsYXNzTmFtZVRvR3JhcGhRTChjbGFzc05hbWUpO1xuICBjb25zdCBnZXRHcmFwaFFMUXVlcnlOYW1lID1cbiAgICBncmFwaFFMQ2xhc3NOYW1lLmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpICsgZ3JhcGhRTENsYXNzTmFtZS5zbGljZSgxKTtcblxuICBjb25zdCB7XG4gICAgY3JlYXRlOiBpc0NyZWF0ZUVuYWJsZWQgPSB0cnVlLFxuICAgIHVwZGF0ZTogaXNVcGRhdGVFbmFibGVkID0gdHJ1ZSxcbiAgICBkZXN0cm95OiBpc0Rlc3Ryb3lFbmFibGVkID0gdHJ1ZSxcbiAgICBjcmVhdGVBbGlhczogY3JlYXRlQWxpYXMgPSAnJyxcbiAgICB1cGRhdGVBbGlhczogdXBkYXRlQWxpYXMgPSAnJyxcbiAgICBkZXN0cm95QWxpYXM6IGRlc3Ryb3lBbGlhcyA9ICcnLFxuICB9ID0gZ2V0UGFyc2VDbGFzc011dGF0aW9uQ29uZmlnKHBhcnNlQ2xhc3NDb25maWcpO1xuXG4gIGNvbnN0IHtcbiAgICBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlLFxuICAgIGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUsXG4gICAgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSxcbiAgfSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNbY2xhc3NOYW1lXTtcblxuICBpZiAoaXNDcmVhdGVFbmFibGVkKSB7XG4gICAgY29uc3QgY3JlYXRlR3JhcGhRTE11dGF0aW9uTmFtZSA9XG4gICAgICBjcmVhdGVBbGlhcyB8fCBgY3JlYXRlJHtncmFwaFFMQ2xhc3NOYW1lfWA7XG4gICAgY29uc3QgY3JlYXRlR3JhcGhRTE11dGF0aW9uID0gbXV0YXRpb25XaXRoQ2xpZW50TXV0YXRpb25JZCh7XG4gICAgICBuYW1lOiBgQ3JlYXRlJHtncmFwaFFMQ2xhc3NOYW1lfWAsXG4gICAgICBkZXNjcmlwdGlvbjogYFRoZSAke2NyZWF0ZUdyYXBoUUxNdXRhdGlvbk5hbWV9IG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSBhIG5ldyBvYmplY3Qgb2YgdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICAgIGlucHV0RmllbGRzOiB7XG4gICAgICAgIGZpZWxkczoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgJ1RoZXNlIGFyZSB0aGUgZmllbGRzIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSB0aGUgbmV3IG9iamVjdC4nLFxuICAgICAgICAgIHR5cGU6IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGUgfHwgZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1QsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgb3V0cHV0RmllbGRzOiB7XG4gICAgICAgIFtnZXRHcmFwaFFMUXVlcnlOYW1lXToge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgY3JlYXRlZCBvYmplY3QuJyxcbiAgICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoXG4gICAgICAgICAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIHx8IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUXG4gICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBtdXRhdGVBbmRHZXRQYXlsb2FkOiBhc3luYyAoYXJncywgY29udGV4dCwgbXV0YXRpb25JbmZvKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbGV0IHsgZmllbGRzIH0gPSBhcmdzO1xuICAgICAgICAgIGlmICghZmllbGRzKSBmaWVsZHMgPSB7fTtcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcblxuICAgICAgICAgIGNvbnN0IHBhcnNlRmllbGRzID0gYXdhaXQgdHJhbnNmb3JtVHlwZXMoJ2NyZWF0ZScsIGZpZWxkcywge1xuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICAgICAgICAgICAgcmVxOiB7IGNvbmZpZywgYXV0aCwgaW5mbyB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc3QgY3JlYXRlZE9iamVjdCA9IGF3YWl0IG9iamVjdHNNdXRhdGlvbnMuY3JlYXRlT2JqZWN0KFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgcGFyc2VGaWVsZHMsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgaW5mb1xuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3Qgc2VsZWN0ZWRGaWVsZHMgPSBnZXRGaWVsZE5hbWVzKG11dGF0aW9uSW5mbylcbiAgICAgICAgICAgIC5maWx0ZXIoZmllbGQgPT4gZmllbGQuc3RhcnRzV2l0aChgJHtnZXRHcmFwaFFMUXVlcnlOYW1lfS5gKSlcbiAgICAgICAgICAgIC5tYXAoZmllbGQgPT4gZmllbGQucmVwbGFjZShgJHtnZXRHcmFwaFFMUXVlcnlOYW1lfS5gLCAnJykpO1xuICAgICAgICAgIGNvbnN0IHsga2V5cywgaW5jbHVkZSB9ID0gZXh0cmFjdEtleXNBbmRJbmNsdWRlKHNlbGVjdGVkRmllbGRzKTtcbiAgICAgICAgICBjb25zdCB7IGtleXM6IHJlcXVpcmVkS2V5cywgbmVlZEdldCB9ID0gZ2V0T25seVJlcXVpcmVkRmllbGRzKFxuICAgICAgICAgICAgZmllbGRzLFxuICAgICAgICAgICAga2V5cyxcbiAgICAgICAgICAgIGluY2x1ZGUsXG4gICAgICAgICAgICBbJ2lkJywgJ29iamVjdElkJywgJ2NyZWF0ZWRBdCcsICd1cGRhdGVkQXQnXVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgbmVlZFRvR2V0QWxsS2V5cyA9IG9iamVjdHNRdWVyaWVzLm5lZWRUb0dldEFsbEtleXMoXG4gICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkcyxcbiAgICAgICAgICAgIGtleXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGxldCBvcHRpbWl6ZWRPYmplY3QgPSB7fTtcbiAgICAgICAgICBpZiAobmVlZEdldCAmJiAhbmVlZFRvR2V0QWxsS2V5cykge1xuICAgICAgICAgICAgb3B0aW1pemVkT2JqZWN0ID0gYXdhaXQgb2JqZWN0c1F1ZXJpZXMuZ2V0T2JqZWN0KFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIGNyZWF0ZWRPYmplY3Qub2JqZWN0SWQsXG4gICAgICAgICAgICAgIHJlcXVpcmVkS2V5cyxcbiAgICAgICAgICAgICAgaW5jbHVkZSxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgaW5mbyxcbiAgICAgICAgICAgICAgcGFyc2VDbGFzc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKG5lZWRUb0dldEFsbEtleXMpIHtcbiAgICAgICAgICAgIG9wdGltaXplZE9iamVjdCA9IGF3YWl0IG9iamVjdHNRdWVyaWVzLmdldE9iamVjdChcbiAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICBjcmVhdGVkT2JqZWN0Lm9iamVjdElkLFxuICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGluY2x1ZGUsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgIGluZm8sXG4gICAgICAgICAgICAgIHBhcnNlQ2xhc3NcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBbZ2V0R3JhcGhRTFF1ZXJ5TmFtZV06IHtcbiAgICAgICAgICAgICAgLi4uY3JlYXRlZE9iamVjdCxcbiAgICAgICAgICAgICAgdXBkYXRlZEF0OiBjcmVhdGVkT2JqZWN0LmNyZWF0ZWRBdCxcbiAgICAgICAgICAgICAgLi4ucGFyc2VGaWVsZHMsXG4gICAgICAgICAgICAgIC4uLm9wdGltaXplZE9iamVjdCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmIChcbiAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICAgICAgY3JlYXRlR3JhcGhRTE11dGF0aW9uLmFyZ3MuaW5wdXQudHlwZS5vZlR5cGVcbiAgICAgICkgJiZcbiAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShjcmVhdGVHcmFwaFFMTXV0YXRpb24udHlwZSlcbiAgICApIHtcbiAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgICAgIGNyZWF0ZUdyYXBoUUxNdXRhdGlvbk5hbWUsXG4gICAgICAgIGNyZWF0ZUdyYXBoUUxNdXRhdGlvblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAoaXNVcGRhdGVFbmFibGVkKSB7XG4gICAgY29uc3QgdXBkYXRlR3JhcGhRTE11dGF0aW9uTmFtZSA9XG4gICAgICB1cGRhdGVBbGlhcyB8fCBgdXBkYXRlJHtncmFwaFFMQ2xhc3NOYW1lfWA7XG4gICAgY29uc3QgdXBkYXRlR3JhcGhRTE11dGF0aW9uID0gbXV0YXRpb25XaXRoQ2xpZW50TXV0YXRpb25JZCh7XG4gICAgICBuYW1lOiBgVXBkYXRlJHtncmFwaFFMQ2xhc3NOYW1lfWAsXG4gICAgICBkZXNjcmlwdGlvbjogYFRoZSAke3VwZGF0ZUdyYXBoUUxNdXRhdGlvbk5hbWV9IG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIHVwZGF0ZSBhbiBvYmplY3Qgb2YgdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICAgIGlucHV0RmllbGRzOiB7XG4gICAgICAgIGlkOiBkZWZhdWx0R3JhcGhRTFR5cGVzLkdMT0JBTF9PUl9PQkpFQ1RfSURfQVRULFxuICAgICAgICBmaWVsZHM6IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICdUaGVzZSBhcmUgdGhlIGZpZWxkcyB0aGF0IHdpbGwgYmUgdXNlZCB0byB1cGRhdGUgdGhlIG9iamVjdC4nLFxuICAgICAgICAgIHR5cGU6IGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUgfHwgZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1QsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgb3V0cHV0RmllbGRzOiB7XG4gICAgICAgIFtnZXRHcmFwaFFMUXVlcnlOYW1lXToge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgdXBkYXRlZCBvYmplY3QuJyxcbiAgICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoXG4gICAgICAgICAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIHx8IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUXG4gICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBtdXRhdGVBbmRHZXRQYXlsb2FkOiBhc3luYyAoYXJncywgY29udGV4dCwgbXV0YXRpb25JbmZvKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbGV0IHsgaWQsIGZpZWxkcyB9ID0gYXJncztcbiAgICAgICAgICBpZiAoIWZpZWxkcykgZmllbGRzID0ge307XG4gICAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgICBjb25zdCBnbG9iYWxJZE9iamVjdCA9IGZyb21HbG9iYWxJZChpZCk7XG5cbiAgICAgICAgICBpZiAoZ2xvYmFsSWRPYmplY3QudHlwZSA9PT0gY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICBpZCA9IGdsb2JhbElkT2JqZWN0LmlkO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHBhcnNlRmllbGRzID0gYXdhaXQgdHJhbnNmb3JtVHlwZXMoJ3VwZGF0ZScsIGZpZWxkcywge1xuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICAgICAgICAgICAgcmVxOiB7IGNvbmZpZywgYXV0aCwgaW5mbyB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc3QgdXBkYXRlZE9iamVjdCA9IGF3YWl0IG9iamVjdHNNdXRhdGlvbnMudXBkYXRlT2JqZWN0KFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICBwYXJzZUZpZWxkcyxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHNlbGVjdGVkRmllbGRzID0gZ2V0RmllbGROYW1lcyhtdXRhdGlvbkluZm8pXG4gICAgICAgICAgICAuZmlsdGVyKGZpZWxkID0+IGZpZWxkLnN0YXJ0c1dpdGgoYCR7Z2V0R3JhcGhRTFF1ZXJ5TmFtZX0uYCkpXG4gICAgICAgICAgICAubWFwKGZpZWxkID0+IGZpZWxkLnJlcGxhY2UoYCR7Z2V0R3JhcGhRTFF1ZXJ5TmFtZX0uYCwgJycpKTtcbiAgICAgICAgICBjb25zdCB7IGtleXMsIGluY2x1ZGUgfSA9IGV4dHJhY3RLZXlzQW5kSW5jbHVkZShzZWxlY3RlZEZpZWxkcyk7XG4gICAgICAgICAgY29uc3QgeyBrZXlzOiByZXF1aXJlZEtleXMsIG5lZWRHZXQgfSA9IGdldE9ubHlSZXF1aXJlZEZpZWxkcyhcbiAgICAgICAgICAgIGZpZWxkcyxcbiAgICAgICAgICAgIGtleXMsXG4gICAgICAgICAgICBpbmNsdWRlLFxuICAgICAgICAgICAgWydpZCcsICdvYmplY3RJZCcsICd1cGRhdGVkQXQnXVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgbmVlZFRvR2V0QWxsS2V5cyA9IG9iamVjdHNRdWVyaWVzLm5lZWRUb0dldEFsbEtleXMoXG4gICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkcyxcbiAgICAgICAgICAgIGtleXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGxldCBvcHRpbWl6ZWRPYmplY3QgPSB7fTtcbiAgICAgICAgICBpZiAobmVlZEdldCAmJiAhbmVlZFRvR2V0QWxsS2V5cykge1xuICAgICAgICAgICAgb3B0aW1pemVkT2JqZWN0ID0gYXdhaXQgb2JqZWN0c1F1ZXJpZXMuZ2V0T2JqZWN0KFxuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIGlkLFxuICAgICAgICAgICAgICByZXF1aXJlZEtleXMsXG4gICAgICAgICAgICAgIGluY2x1ZGUsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgIGluZm8sXG4gICAgICAgICAgICAgIHBhcnNlQ2xhc3NcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChuZWVkVG9HZXRBbGxLZXlzKSB7XG4gICAgICAgICAgICBvcHRpbWl6ZWRPYmplY3QgPSBhd2FpdCBvYmplY3RzUXVlcmllcy5nZXRPYmplY3QoXG4gICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgaW5jbHVkZSxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgaW5mbyxcbiAgICAgICAgICAgICAgcGFyc2VDbGFzc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFtnZXRHcmFwaFFMUXVlcnlOYW1lXToge1xuICAgICAgICAgICAgICBvYmplY3RJZDogaWQsXG4gICAgICAgICAgICAgIC4uLnVwZGF0ZWRPYmplY3QsXG4gICAgICAgICAgICAgIC4uLnBhcnNlRmllbGRzLFxuICAgICAgICAgICAgICAuLi5vcHRpbWl6ZWRPYmplY3QsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBpZiAoXG4gICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgICAgIHVwZGF0ZUdyYXBoUUxNdXRhdGlvbi5hcmdzLmlucHV0LnR5cGUub2ZUeXBlXG4gICAgICApICYmXG4gICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUodXBkYXRlR3JhcGhRTE11dGF0aW9uLnR5cGUpXG4gICAgKSB7XG4gICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTE11dGF0aW9uKFxuICAgICAgICB1cGRhdGVHcmFwaFFMTXV0YXRpb25OYW1lLFxuICAgICAgICB1cGRhdGVHcmFwaFFMTXV0YXRpb25cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGlzRGVzdHJveUVuYWJsZWQpIHtcbiAgICBjb25zdCBkZWxldGVHcmFwaFFMTXV0YXRpb25OYW1lID1cbiAgICAgIGRlc3Ryb3lBbGlhcyB8fCBgZGVsZXRlJHtncmFwaFFMQ2xhc3NOYW1lfWA7XG4gICAgY29uc3QgZGVsZXRlR3JhcGhRTE11dGF0aW9uID0gbXV0YXRpb25XaXRoQ2xpZW50TXV0YXRpb25JZCh7XG4gICAgICBuYW1lOiBgRGVsZXRlJHtncmFwaFFMQ2xhc3NOYW1lfWAsXG4gICAgICBkZXNjcmlwdGlvbjogYFRoZSAke2RlbGV0ZUdyYXBoUUxNdXRhdGlvbk5hbWV9IG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIGRlbGV0ZSBhbiBvYmplY3Qgb2YgdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICAgIGlucHV0RmllbGRzOiB7XG4gICAgICAgIGlkOiBkZWZhdWx0R3JhcGhRTFR5cGVzLkdMT0JBTF9PUl9PQkpFQ1RfSURfQVRULFxuICAgICAgfSxcbiAgICAgIG91dHB1dEZpZWxkczoge1xuICAgICAgICBbZ2V0R3JhcGhRTFF1ZXJ5TmFtZV06IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGRlbGV0ZWQgb2JqZWN0LicsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICAgICAgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSB8fCBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVFxuICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgbXV0YXRlQW5kR2V0UGF5bG9hZDogYXN5bmMgKGFyZ3MsIGNvbnRleHQsIG11dGF0aW9uSW5mbykgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGxldCB7IGlkIH0gPSBhcmdzO1xuICAgICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuXG4gICAgICAgICAgY29uc3QgZ2xvYmFsSWRPYmplY3QgPSBmcm9tR2xvYmFsSWQoaWQpO1xuXG4gICAgICAgICAgaWYgKGdsb2JhbElkT2JqZWN0LnR5cGUgPT09IGNsYXNzTmFtZSkge1xuICAgICAgICAgICAgaWQgPSBnbG9iYWxJZE9iamVjdC5pZDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMobXV0YXRpb25JbmZvKVxuICAgICAgICAgICAgLmZpbHRlcihmaWVsZCA9PiBmaWVsZC5zdGFydHNXaXRoKGAke2dldEdyYXBoUUxRdWVyeU5hbWV9LmApKVxuICAgICAgICAgICAgLm1hcChmaWVsZCA9PiBmaWVsZC5yZXBsYWNlKGAke2dldEdyYXBoUUxRdWVyeU5hbWV9LmAsICcnKSk7XG4gICAgICAgICAgY29uc3QgeyBrZXlzLCBpbmNsdWRlIH0gPSBleHRyYWN0S2V5c0FuZEluY2x1ZGUoc2VsZWN0ZWRGaWVsZHMpO1xuICAgICAgICAgIGxldCBvcHRpbWl6ZWRPYmplY3QgPSB7fTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBrZXlzICYmXG4gICAgICAgICAgICBrZXlzLnNwbGl0KCcsJykuZmlsdGVyKGtleSA9PiAhWydpZCcsICdvYmplY3RJZCddLmluY2x1ZGVzKGtleSkpXG4gICAgICAgICAgICAgIC5sZW5ndGggPiAwXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBvcHRpbWl6ZWRPYmplY3QgPSBhd2FpdCBvYmplY3RzUXVlcmllcy5nZXRPYmplY3QoXG4gICAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgIGtleXMsXG4gICAgICAgICAgICAgIGluY2x1ZGUsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgIGluZm8sXG4gICAgICAgICAgICAgIHBhcnNlQ2xhc3NcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IG9iamVjdHNNdXRhdGlvbnMuZGVsZXRlT2JqZWN0KFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgaW5mb1xuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFtnZXRHcmFwaFFMUXVlcnlOYW1lXToge1xuICAgICAgICAgICAgICBvYmplY3RJZDogaWQsXG4gICAgICAgICAgICAgIC4uLm9wdGltaXplZE9iamVjdCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmIChcbiAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICAgICAgZGVsZXRlR3JhcGhRTE11dGF0aW9uLmFyZ3MuaW5wdXQudHlwZS5vZlR5cGVcbiAgICAgICkgJiZcbiAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShkZWxldGVHcmFwaFFMTXV0YXRpb24udHlwZSlcbiAgICApIHtcbiAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgICAgIGRlbGV0ZUdyYXBoUUxNdXRhdGlvbk5hbWUsXG4gICAgICAgIGRlbGV0ZUdyYXBoUUxNdXRhdGlvblxuICAgICAgKTtcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCB7IGxvYWQgfTtcbiJdfQ== \ 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..50845cbe87 --- /dev/null +++ b/lib/GraphQL/loaders/parseClassQueries.js @@ -0,0 +1,150 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlRelay = require("graphql-relay"); + +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 (parseClass, _source, args, context, queryInfo) => { + let { + id + } = args; + const { + options + } = args; + const { + readPreference, + includeReadPreference + } = options || {}; + const { + config, + auth, + info + } = context; + const selectedFields = (0, _graphqlListFields.default)(queryInfo); + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(id); + + if (globalIdObject.type === parseClass.className) { + id = globalIdObject.id; + } + + const { + keys, + include + } = (0, _parseGraphQLUtils.extractKeysAndInclude)(selectedFields); + return await objectsQueries.getObject(parseClass.className, id, keys, include, readPreference, includeReadPreference, config, auth, info, parseClass); +}; + +const load = function (parseGraphQLSchema, parseClass, parseClassConfig) { + const className = parseClass.className; + const graphQLClassName = (0, _className.transformClassNameToGraphQL)(className); + const { + get: isGetEnabled = true, + find: isFindEnabled = true, + getAlias = '', + findAlias = '' + } = getParseClassQueryConfig(parseClassConfig); + const { + classGraphQLOutputType, + classGraphQLFindArgs, + classGraphQLFindResultType + } = parseGraphQLSchema.parseClassTypes[className]; + + if (isGetEnabled) { + const lowerCaseClassName = graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1); + const getGraphQLQueryName = getAlias || lowerCaseClassName; + parseGraphQLSchema.addGraphQLQuery(getGraphQLQueryName, { + description: `The ${getGraphQLQueryName} query can be used to get an object of the ${graphQLClassName} class by its id.`, + args: { + id: defaultGraphQLTypes.GLOBAL_OR_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(parseClass, _source, args, context, queryInfo); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }); + } + + if (isFindEnabled) { + const lowerCaseClassName = graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1); + const findGraphQLQueryName = findAlias || (0, _pluralize.default)(lowerCaseClassName); + 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.OBJECT), + + async resolve(_source, args, context, queryInfo) { + try { + const { + where, + order, + skip, + first, + after, + last, + before, + 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.startsWith('edges.node.')).map(field => field.replace('edges.node.', ''))); + const parseOrder = order && order.join(','); + return await objectsQueries.findObjects(className, where, parseOrder, skip, first, after, last, before, keys, include, false, readPreference, includeReadPreference, subqueryReadPreference, config, auth, info, selectedFields, parseGraphQLSchema.parseClasses); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }); + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvcGFyc2VDbGFzc1F1ZXJpZXMuanMiXSwibmFtZXMiOlsiZ2V0UGFyc2VDbGFzc1F1ZXJ5Q29uZmlnIiwicGFyc2VDbGFzc0NvbmZpZyIsInF1ZXJ5IiwiZ2V0UXVlcnkiLCJwYXJzZUNsYXNzIiwiX3NvdXJjZSIsImFyZ3MiLCJjb250ZXh0IiwicXVlcnlJbmZvIiwiaWQiLCJvcHRpb25zIiwicmVhZFByZWZlcmVuY2UiLCJpbmNsdWRlUmVhZFByZWZlcmVuY2UiLCJjb25maWciLCJhdXRoIiwiaW5mbyIsInNlbGVjdGVkRmllbGRzIiwiZ2xvYmFsSWRPYmplY3QiLCJ0eXBlIiwiY2xhc3NOYW1lIiwia2V5cyIsImluY2x1ZGUiLCJvYmplY3RzUXVlcmllcyIsImdldE9iamVjdCIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJncmFwaFFMQ2xhc3NOYW1lIiwiZ2V0IiwiaXNHZXRFbmFibGVkIiwiZmluZCIsImlzRmluZEVuYWJsZWQiLCJnZXRBbGlhcyIsImZpbmRBbGlhcyIsImNsYXNzR3JhcGhRTE91dHB1dFR5cGUiLCJjbGFzc0dyYXBoUUxGaW5kQXJncyIsImNsYXNzR3JhcGhRTEZpbmRSZXN1bHRUeXBlIiwicGFyc2VDbGFzc1R5cGVzIiwibG93ZXJDYXNlQ2xhc3NOYW1lIiwiY2hhckF0IiwidG9Mb3dlckNhc2UiLCJzbGljZSIsImdldEdyYXBoUUxRdWVyeU5hbWUiLCJhZGRHcmFwaFFMUXVlcnkiLCJkZXNjcmlwdGlvbiIsImRlZmF1bHRHcmFwaFFMVHlwZXMiLCJHTE9CQUxfT1JfT0JKRUNUX0lEX0FUVCIsIlJFQURfT1BUSU9OU19BVFQiLCJHcmFwaFFMTm9uTnVsbCIsIk9CSkVDVCIsInJlc29sdmUiLCJlIiwiaGFuZGxlRXJyb3IiLCJmaW5kR3JhcGhRTFF1ZXJ5TmFtZSIsIndoZXJlIiwib3JkZXIiLCJza2lwIiwiZmlyc3QiLCJhZnRlciIsImxhc3QiLCJiZWZvcmUiLCJzdWJxdWVyeVJlYWRQcmVmZXJlbmNlIiwiZmlsdGVyIiwiZmllbGQiLCJzdGFydHNXaXRoIiwibWFwIiwicmVwbGFjZSIsInBhcnNlT3JkZXIiLCJqb2luIiwiZmluZE9iamVjdHMiLCJwYXJzZUNsYXNzZXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNQSx3QkFBd0IsR0FBRyxVQUMvQkMsZ0JBRCtCLEVBRS9CO0FBQ0EsU0FBUUEsZ0JBQWdCLElBQUlBLGdCQUFnQixDQUFDQyxLQUF0QyxJQUFnRCxFQUF2RDtBQUNELENBSkQ7O0FBTUEsTUFBTUMsUUFBUSxHQUFHLE9BQU9DLFVBQVAsRUFBbUJDLE9BQW5CLEVBQTRCQyxJQUE1QixFQUFrQ0MsT0FBbEMsRUFBMkNDLFNBQTNDLEtBQXlEO0FBQ3hFLE1BQUk7QUFBRUMsSUFBQUE7QUFBRixNQUFTSCxJQUFiO0FBQ0EsUUFBTTtBQUFFSSxJQUFBQTtBQUFGLE1BQWNKLElBQXBCO0FBQ0EsUUFBTTtBQUFFSyxJQUFBQSxjQUFGO0FBQWtCQyxJQUFBQTtBQUFsQixNQUE0Q0YsT0FBTyxJQUFJLEVBQTdEO0FBQ0EsUUFBTTtBQUFFRyxJQUFBQSxNQUFGO0FBQVVDLElBQUFBLElBQVY7QUFBZ0JDLElBQUFBO0FBQWhCLE1BQXlCUixPQUEvQjtBQUNBLFFBQU1TLGNBQWMsR0FBRyxnQ0FBY1IsU0FBZCxDQUF2QjtBQUVBLFFBQU1TLGNBQWMsR0FBRyxnQ0FBYVIsRUFBYixDQUF2Qjs7QUFFQSxNQUFJUSxjQUFjLENBQUNDLElBQWYsS0FBd0JkLFVBQVUsQ0FBQ2UsU0FBdkMsRUFBa0Q7QUFDaERWLElBQUFBLEVBQUUsR0FBR1EsY0FBYyxDQUFDUixFQUFwQjtBQUNEOztBQUVELFFBQU07QUFBRVcsSUFBQUEsSUFBRjtBQUFRQyxJQUFBQTtBQUFSLE1BQW9CLDhDQUFzQkwsY0FBdEIsQ0FBMUI7QUFFQSxTQUFPLE1BQU1NLGNBQWMsQ0FBQ0MsU0FB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aEJXLEVBaUJYQyxJQWpCVyxFQWtCWEMsY0FsQlcsRUFtQlhTLGtCQUFrQixDQUFDNEMsWUFuQlIsQ0FBYjtBQXFCRCxTQS9DRCxDQStDRSxPQUFPbkIsQ0FBUCxFQUFVO0FBQ1Z6QixVQUFBQSxrQkFBa0IsQ0FBQzBCLFdBQW5CLENBQStCRCxDQUEvQjtBQUNEO0FBQ0Y7O0FBekRzRCxLQUF6RDtBQTJERDtBQUNGLENBL0dEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR3JhcGhRTE5vbk51bGwgfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCB7IGZyb21HbG9iYWxJZCB9IGZyb20gJ2dyYXBocWwtcmVsYXknO1xuaW1wb3J0IGdldEZpZWxkTmFtZXMgZnJvbSAnZ3JhcGhxbC1saXN0LWZpZWxkcyc7XG5pbXBvcnQgcGx1cmFsaXplIGZyb20gJ3BsdXJhbGl6ZSc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4vZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5pbXBvcnQgKiBhcyBvYmplY3RzUXVlcmllcyBmcm9tICcuLi9oZWxwZXJzL29iamVjdHNRdWVyaWVzJztcbmltcG9ydCB7IFBhcnNlR3JhcGhRTENsYXNzQ29uZmlnIH0gZnJvbSAnLi4vLi4vQ29udHJvbGxlcnMvUGFyc2VHcmFwaFFMQ29udHJvbGxlcic7XG5pbXBvcnQgeyB0cmFuc2Zvcm1DbGFzc05hbWVUb0dyYXBoUUwgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvY2xhc3NOYW1lJztcbmltcG9ydCB7IGV4dHJhY3RLZXlzQW5kSW5jbHVkZSB9IGZyb20gJy4uL3BhcnNlR3JhcGhRTFV0aWxzJztcblxuY29uc3QgZ2V0UGFyc2VDbGFzc1F1ZXJ5Q29uZmlnID0gZnVuY3Rpb24oXG4gIHBhcnNlQ2xhc3NDb25maWc6ID9QYXJzZUdyYXBoUUxDbGFzc0NvbmZpZ1xuKSB7XG4gIHJldHVybiAocGFyc2VDbGFzc0NvbmZpZyAmJiBwYXJzZUNsYXNzQ29uZmlnLnF1ZXJ5KSB8fCB7fTtcbn07XG5cbmNvbnN0IGdldFF1ZXJ5ID0gYXN5bmMgKHBhcnNlQ2xhc3MsIF9zb3VyY2UsIGFyZ3MsIGNvbnRleHQsIHF1ZXJ5SW5mbykgPT4ge1xuICBsZXQgeyBpZCB9ID0gYXJncztcbiAgY29uc3QgeyBvcHRpb25zIH0gPSBhcmdzO1xuICBjb25zdCB7IHJlYWRQcmVmZXJlbmNlLCBpbmNsdWRlUmVhZFByZWZlcmVuY2UgfSA9IG9wdGlvbnMgfHwge307XG4gIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuICBjb25zdCBzZWxlY3RlZEZpZWxkcyA9IGdldEZpZWxkTmFtZXMocXVlcnlJbmZvKTtcblxuICBjb25zdCBnbG9iYWxJZE9iamVjdCA9IGZyb21HbG9iYWxJZChpZCk7XG5cbiAgaWYgKGdsb2JhbElkT2JqZWN0LnR5cGUgPT09IHBhcnNlQ2xhc3MuY2xhc3NOYW1lKSB7XG4gICAgaWQgPSBnbG9iYWxJZE9iamVjdC5pZDtcbiAgfVxuXG4gIGNvbnN0IHsga2V5cywgaW5jbHVkZSB9ID0gZXh0cmFjdEtleXNBbmRJbmNsdWRlKHNlbGVjdGVkRmllbGRzKTtcblxuICByZXR1cm4gYXdhaXQgb2JqZWN0c1F1ZXJpZXMuZ2V0T2JqZWN0KFxuICAgIHBhcnNlQ2xhc3MuY2xhc3NOYW1lLFxuICAgIGlkLFxuICAgIGtleXMsXG4gICAgaW5jbHVkZSxcbiAgICByZWFkUHJlZmVyZW5jZSxcbiAgICBpbmNsdWRlUmVhZFByZWZlcmVuY2UsXG4gICAgY29uZmlnLFxuICAgIGF1dGgsXG4gICAgaW5mbyxcbiAgICBwYXJzZUNsYXNzXG4gICk7XG59O1xuXG5jb25zdCBsb2FkID0gZnVuY3Rpb24oXG4gIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgcGFyc2VDbGFzcyxcbiAgcGFyc2VDbGFzc0NvbmZpZzogP1BhcnNlR3JhcGhRTENsYXNzQ29uZmlnXG4pIHtcbiAgY29uc3QgY2xhc3NOYW1lID0gcGFyc2VDbGFzcy5jbGFzc05hbWU7XG4gIGNvbnN0IGdyYXBoUUxDbGFzc05hbWUgPSB0cmFuc2Zvcm1DbGFzc05hbWVUb0dyYXBoUUwoY2xhc3NOYW1lKTtcbiAgY29uc3Qge1xuICAgIGdldDogaXNHZXRFbmFibGVkID0gdHJ1ZSxcbiAgICBmaW5kOiBpc0ZpbmRFbmFibGVkID0gdHJ1ZSxcbiAgICBnZXRBbGlhczogZ2V0QWxpYXMgPSAnJyxcbiAgICBmaW5kQWxpYXM6IGZpbmRBbGlhcyA9ICcnLFxuICB9ID0gZ2V0UGFyc2VDbGFzc1F1ZXJ5Q29uZmlnKHBhcnNlQ2xhc3NDb25maWcpO1xuXG4gIGNvbnN0IHtcbiAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlLFxuICAgIGNsYXNzR3JhcGhRTEZpbmRBcmdzLFxuICAgIGNsYXNzR3JhcGhRTEZpbmRSZXN1bHRUeXBlLFxuICB9ID0gcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1tjbGFzc05hbWVdO1xuXG4gIGlmIChpc0dldEVuYWJsZWQpIHtcbiAgICBjb25zdCBsb3dlckNhc2VDbGFzc05hbWUgPVxuICAgICAgZ3JhcGhRTENsYXNzTmFtZS5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKSArIGdyYXBoUUxDbGFzc05hbWUuc2xpY2UoMSk7XG5cbiAgICBjb25zdCBnZXRHcmFwaFFMUXVlcnlOYW1lID0gZ2V0QWxpYXMgfHwgbG93ZXJDYXNlQ2xhc3NOYW1lO1xuXG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxRdWVyeShnZXRHcmFwaFFMUXVlcnlOYW1lLCB7XG4gICAgICBkZXNjcmlwdGlvbjogYFRoZSAke2dldEdyYXBoUUxRdWVyeU5hbWV9IHF1ZXJ5IGNhbiBiZSB1c2VkIHRvIGdldCBhbiBvYmplY3Qgb2YgdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MgYnkgaXRzIGlkLmAsXG4gICAgICBhcmdzOiB7XG4gICAgICAgIGlkOiBkZWZhdWx0R3JhcGhRTFR5cGVzLkdMT0JBTF9PUl9PQkpFQ1RfSURfQVRULFxuICAgICAgICBvcHRpb25zOiBkZWZhdWx0R3JhcGhRTFR5cGVzLlJFQURfT1BUSU9OU19BVFQsXG4gICAgICB9LFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIHx8IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUXG4gICAgICApLFxuICAgICAgYXN5bmMgcmVzb2x2ZShfc291cmNlLCBhcmdzLCBjb250ZXh0LCBxdWVyeUluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgZ2V0UXVlcnkocGFyc2VDbGFzcywgX3NvdXJjZSwgYXJncywgY29udGV4dCwgcXVlcnlJbmZvKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChpc0ZpbmRFbmFibGVkKSB7XG4gICAgY29uc3QgbG93ZXJDYXNlQ2xhc3NOYW1lID1cbiAgICAgIGdyYXBoUUxDbGFzc05hbWUuY2hhckF0KDApLnRvTG93ZXJDYXNlKCkgKyBncmFwaFFMQ2xhc3NOYW1lLnNsaWNlKDEpO1xuXG4gICAgY29uc3QgZmluZEdyYXBoUUxRdWVyeU5hbWUgPSBmaW5kQWxpYXMgfHwgcGx1cmFsaXplKGxvd2VyQ2FzZUNsYXNzTmFtZSk7XG5cbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFF1ZXJ5KGZpbmRHcmFwaFFMUXVlcnlOYW1lLCB7XG4gICAgICBkZXNjcmlwdGlvbjogYFRoZSAke2ZpbmRHcmFwaFFMUXVlcnlOYW1lfSBxdWVyeSBjYW4gYmUgdXNlZCB0byBmaW5kIG9iamVjdHMgb2YgdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICAgIGFyZ3M6IGNsYXNzR3JhcGhRTEZpbmRBcmdzLFxuICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICBjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZSB8fCBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVFxuICAgICAgKSxcbiAgICAgIGFzeW5jIHJlc29sdmUoX3NvdXJjZSwgYXJncywgY29udGV4dCwgcXVlcnlJbmZvKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgd2hlcmUsXG4gICAgICAgICAgICBvcmRlcixcbiAgICAgICAgICAgIHNraXAsXG4gICAgICAgICAgICBmaXJzdCxcbiAgICAgICAgICAgIGFmdGVyLFxuICAgICAgICAgICAgbGFzdCxcbiAgICAgICAgICAgIGJlZm9yZSxcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgfSA9IGFyZ3M7XG4gICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICBpbmNsdWRlUmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICBzdWJxdWVyeVJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgIH0gPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoLCBpbmZvIH0gPSBjb250ZXh0O1xuICAgICAgICAgIGNvbnN0IHNlbGVjdGVkRmllbGRzID0gZ2V0RmllbGROYW1lcyhxdWVyeUluZm8pO1xuXG4gICAgICAgICAgY29uc3QgeyBrZXlzLCBpbmNsdWRlIH0gPSBleHRyYWN0S2V5c0FuZEluY2x1ZGUoXG4gICAgICAgICAgICBzZWxlY3RlZEZpZWxkc1xuICAgICAgICAgICAgICAuZmlsdGVyKGZpZWxkID0+IGZpZWxkLnN0YXJ0c1dpdGgoJ2VkZ2VzLm5vZGUuJykpXG4gICAgICAgICAgICAgIC5tYXAoZmllbGQgPT4gZmllbGQucmVwbGFjZSgnZWRnZXMubm9kZS4nLCAnJykpXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBwYXJzZU9yZGVyID0gb3JkZXIgJiYgb3JkZXIuam9pbignLCcpO1xuXG4gICAgICAgICAgcmV0dXJuIGF3YWl0IG9iamVjdHNRdWVyaWVzLmZpbmRPYmplY3RzKFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgd2hlcmUsXG4gICAgICAgICAgICBwYXJzZU9yZGVyLFxuICAgICAgICAgICAgc2tpcCxcbiAgICAgICAgICAgIGZpcnN0LFxuICAgICAgICAgICAgYWZ0ZXIsXG4gICAgICAgICAgICBsYXN0LFxuICAgICAgICAgICAgYmVmb3JlLFxuICAgICAgICAgICAga2V5cyxcbiAgICAgICAgICAgIGluY2x1ZGUsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgaW5jbHVkZVJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgc3VicXVlcnlSZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvLFxuICAgICAgICAgICAgc2VsZWN0ZWRGaWVsZHMsXG4gICAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc2VzXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufTtcblxuZXhwb3J0IHsgbG9hZCB9O1xuIl19 \ 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..65ccbb1f09 --- /dev/null +++ b/lib/GraphQL/loaders/parseClassTypes.js @@ -0,0 +1,531 @@ +"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 _graphqlRelay = require("graphql-relay"); + +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).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) && field !== 'id'; + }); + + 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: className === '_User' && (field === 'username' || field === 'password') || parseClass.fields[field].required ? new _graphql.GraphQLNonNull(type) : 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. You can use either the global or the object id.`, + 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 existing objects from the ${graphQLClassName} class into the relation. You can use either the global or the object ids.`, + type: new _graphql.GraphQLList(defaultGraphQLTypes.OBJECT_ID) + }, + remove: { + description: `Remove existing objects from the ${graphQLClassName} class out of the relation. You can use either the global or the object ids.`, + type: new _graphql.GraphQLList(defaultGraphQLTypes.OBJECT_ID) + } + }; + + if (isCreateEnabled) { + fields['createAndAdd'] = { + description: `Create and add objects of the ${graphQLClassName} class into the relation.`, + type: new _graphql.GraphQLList(new _graphql.GraphQLNonNull(classGraphQLCreateType)) + }; + } + + return fields; + } + }); + classGraphQLRelationType = parseGraphQLSchema.addGraphQLType(classGraphQLRelationType) || defaultGraphQLTypes.OBJECT; + 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, field); + + 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 classGraphQLRelationConstraintsTypeName = `${graphQLClassName}RelationWhereInput`; + let classGraphQLRelationConstraintsType = new _graphql.GraphQLInputObjectType({ + name: classGraphQLRelationConstraintsTypeName, + description: `The ${classGraphQLRelationConstraintsTypeName} input type is used in operations that involve filtering objects of ${graphQLClassName} class.`, + fields: () => ({ + have: { + description: 'Run a relational/pointer query where at least one child object can match.', + type: classGraphQLConstraintsType + }, + haveNot: { + description: 'Run an inverted relational/pointer query where at least one child object can match.', + type: classGraphQLConstraintsType + }, + exists: { + description: 'Check if the relation/pointer contains objects.', + type: _graphql.GraphQLBoolean + } + }) + }); + classGraphQLRelationConstraintsType = parseGraphQLSchema.addGraphQLType(classGraphQLRelationConstraintsType) || 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); + + const value = field === 'id' ? 'objectId' : field; + + if (asc) { + updatedSortFields[`${field}_ASC`] = { + value + }; + } + + if (desc) { + updatedSortFields[`${field}_DESC`] = { + value: `-${value}` + }; + } + + return updatedSortFields; + }, {}) + }); + classGraphQLOrderType = parseGraphQLSchema.addGraphQLType(classGraphQLOrderType); + + const classGraphQLFindArgs = _objectSpread({ + 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 + }, _graphqlRelay.connectionArgs, { + options: defaultGraphQLTypes.READ_OPTIONS_ATT + }); + + const classGraphQLOutputTypeName = `${graphQLClassName}`; + const interfaces = [defaultGraphQLTypes.PARSE_OBJECT, parseGraphQLSchema.relayNodeInterface]; + + const parseObjectFields = _objectSpread({ + id: (0, _graphqlRelay.globalIdField)(className, obj => obj.objectId) + }, defaultGraphQLTypes.PARSE_OBJECT_FIELDS); + + 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: parseClass.fields[field].required ? new _graphql.GraphQLNonNull(type) : type, + + async resolve(source, args, context, queryInfo) { + try { + const { + where, + order, + skip, + first, + after, + last, + before, + 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.startsWith('edges.node.')).map(field => field.replace('edges.node.', ''))); + const parseOrder = order && order.join(','); + return objectsQueries.findObjects(source[field].className, _objectSpread({ + $relatedTo: { + object: { + __type: 'Pointer', + className: className, + objectId: source.objectId + }, + key: field + } + }, where || {}), parseOrder, skip, first, after, last, before, keys, include, false, readPreference, includeReadPreference, subqueryReadPreference, config, auth, info, selectedFields, parseGraphQLSchema.parseClasses); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + } + }); + } else if (parseClass.fields[field].type === 'Polygon') { + return _objectSpread({}, fields, { + [field]: { + description: `This is the object ${field}.`, + type: parseClass.fields[field].required ? new _graphql.GraphQLNonNull(type) : 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: parseClass.fields[field].required ? new _graphql.GraphQLNonNull(type) : 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: parseClass.fields[field].required ? new _graphql.GraphQLNonNull(type) : type + } + }); + } else { + return fields; + } + }, parseObjectFields); + }; + + let classGraphQLOutputType = new _graphql.GraphQLObjectType({ + name: classGraphQLOutputTypeName, + description: `The ${classGraphQLOutputTypeName} object type is used in operations that involve outputting objects of ${graphQLClassName} class.`, + interfaces, + fields: outputFields + }); + classGraphQLOutputType = parseGraphQLSchema.addGraphQLType(classGraphQLOutputType); + const { + connectionType, + edgeType + } = (0, _graphqlRelay.connectionDefinitions)({ + name: graphQLClassName, + connectionFields: { + count: defaultGraphQLTypes.COUNT_ATT + }, + nodeType: classGraphQLOutputType || defaultGraphQLTypes.OBJECT + }); + let classGraphQLFindResultType = undefined; + + if (parseGraphQLSchema.addGraphQLType(edgeType) && parseGraphQLSchema.addGraphQLType(connectionType, false, false, true)) { + classGraphQLFindResultType = connectionType; + } + + parseGraphQLSchema.parseClassTypes[className] = { + classGraphQLPointerType, + classGraphQLRelationType, + classGraphQLCreateType, + classGraphQLUpdateType, + classGraphQLConstraintsType, + classGraphQLRelationConstraintsType, + 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.`, + fields: () => ({ + sessionToken: defaultGraphQLTypes.SESSION_TOKEN_ATT, + user: { + description: 'This is the current user.', + type: new _graphql.GraphQLNonNull(classGraphQLOutputType) + } + }) + }); + parseGraphQLSchema.addGraphQLType(viewerType, true, true); + parseGraphQLSchema.viewerType = viewerType; + } +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvcGFyc2VDbGFzc1R5cGVzLmpzIl0sIm5hbWVzIjpbImdldFBhcnNlQ2xhc3NUeXBlQ29uZmlnIiwicGFyc2VDbGFzc0NvbmZpZyIsInR5cGUiLCJnZXRJbnB1dEZpZWxkc0FuZENvbnN0cmFpbnRzIiwicGFyc2VDbGFzcyIsImNsYXNzRmllbGRzIiwiT2JqZWN0Iiwia2V5cyIsImZpZWxkcyIsImNvbmNhdCIsImlucHV0RmllbGRzIiwiYWxsb3dlZElucHV0RmllbGRzIiwib3V0cHV0RmllbGRzIiwiYWxsb3dlZE91dHB1dEZpZWxkcyIsImNvbnN0cmFpbnRGaWVsZHMiLCJhbGxvd2VkQ29uc3RyYWludEZpZWxkcyIsInNvcnRGaWVsZHMiLCJhbGxvd2VkU29ydEZpZWxkcyIsImNsYXNzT3V0cHV0RmllbGRzIiwiY2xhc3NDcmVhdGVGaWVsZHMiLCJjbGFzc1VwZGF0ZUZpZWxkcyIsImNsYXNzQ29uc3RyYWludEZpZWxkcyIsImNsYXNzU29ydEZpZWxkcyIsImNsYXNzQ3VzdG9tRmllbGRzIiwiZmlsdGVyIiwiZmllbGQiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiUEFSU0VfT0JKRUNUX0ZJRUxEUyIsImluY2x1ZGVzIiwiY3JlYXRlIiwidXBkYXRlIiwiY2xhc3NOYW1lIiwib3V0cHV0RmllbGQiLCJsZW5ndGgiLCJwdXNoIiwiYXNjIiwiZGVzYyIsIm1hcCIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJncmFwaFFMQ2xhc3NOYW1lIiwiaXNDcmVhdGVFbmFibGVkIiwiaXNVcGRhdGVFbmFibGVkIiwiY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZU5hbWUiLCJjbGFzc0dyYXBoUUxDcmVhdGVUeXBlIiwiR3JhcGhRTElucHV0T2JqZWN0VHlwZSIsIm5hbWUiLCJkZXNjcmlwdGlvbiIsInJlZHVjZSIsInRhcmdldENsYXNzIiwicGFyc2VDbGFzc1R5cGVzIiwicmVxdWlyZWQiLCJHcmFwaFFMTm9uTnVsbCIsIkFDTCIsIkFDTF9JTlBVVCIsImFkZEdyYXBoUUxUeXBlIiwiY2xhc3NHcmFwaFFMVXBkYXRlVHlwZU5hbWUiLCJjbGFzc0dyYXBoUUxVcGRhdGVUeXBlIiwiY2xhc3NHcmFwaFFMUG9pbnRlclR5cGVOYW1lIiwiY2xhc3NHcmFwaFFMUG9pbnRlclR5cGUiLCJsaW5rIiwiR3JhcGhRTElEIiwiT0JKRUNUIiwiY2xhc3NHcmFwaFFMUmVsYXRpb25UeXBlTmFtZSIsImNsYXNzR3JhcGhRTFJlbGF0aW9uVHlwZSIsImFkZCIsIkdyYXBoUUxMaXN0IiwiT0JKRUNUX0lEIiwicmVtb3ZlIiwiY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlTmFtZSIsImNsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZSIsImxvZyIsIndhcm4iLCJwYXJzZUZpZWxkIiwiT1IiLCJBTkQiLCJOT1IiLCJjbGFzc0dyYXBoUUxSZWxhdGlvbkNvbnN0cmFpbnRzVHlwZU5hbWUiLCJjbGFzc0dyYXBoUUxSZWxhdGlvbkNvbnN0cmFpbnRzVHlwZSIsImhhdmUiLCJoYXZlTm90IiwiZXhpc3RzIiwiR3JhcGhRTEJvb2xlYW4iLCJjbGFzc0dyYXBoUUxPcmRlclR5cGVOYW1lIiwiY2xhc3NHcmFwaFFMT3JkZXJUeXBlIiwiR3JhcGhRTEVudW1UeXBlIiwidmFsdWVzIiwiZmllbGRDb25maWciLCJ1cGRhdGVkU29ydEZpZWxkcyIsInZhbHVlIiwiY2xhc3NHcmFwaFFMRmluZEFyZ3MiLCJ3aGVyZSIsIm9yZGVyIiwiR3JhcGhRTFN0cmluZyIsInNraXAiLCJTS0lQX0FUVCIsImNvbm5lY3Rpb25BcmdzIiwib3B0aW9ucyIsIlJFQURfT1BUSU9OU19BVFQiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlTmFtZSIsImludGVyZmFjZXMiLCJQQVJTRV9PQkpFQ1QiLCJyZWxheU5vZGVJbnRlcmZhY2UiLCJwYXJzZU9iamVjdEZpZWxkcyIsImlkIiwib2JqIiwib2JqZWN0SWQiLCJ0YXJnZXRQYXJzZUNsYXNzVHlwZXMiLCJhcmdzIiwidW5kZWZpbmVkIiwicmVzb2x2ZSIsInNvdXJjZSIsImNvbnRleHQiLCJxdWVyeUluZm8iLCJmaXJzdCIsImFmdGVyIiwibGFzdCIsImJlZm9yZSIsInJlYWRQcmVmZXJlbmNlIiwiaW5jbHVkZVJlYWRQcmVmZXJlbmNlIiwic3VicXVlcnlSZWFkUHJlZmVyZW5jZSIsImNvbmZpZyIsImF1dGgiLCJpbmZvIiwic2VsZWN0ZWRGaWVsZHMiLCJpbmNsdWRlIiwic3RhcnRzV2l0aCIsInJlcGxhY2UiLCJwYXJzZU9yZGVyIiwiam9pbiIsIm9iamVjdHNRdWVyaWVzIiwiZmluZE9iamVjdHMiLCIkcmVsYXRlZFRvIiwib2JqZWN0IiwiX190eXBlIiwia2V5IiwicGFyc2VDbGFzc2VzIiwiZSIsImhhbmRsZUVycm9yIiwiY29vcmRpbmF0ZXMiLCJjb29yZGluYXRlIiwibGF0aXR1ZGUiLCJsb25naXR1ZGUiLCJlbGVtIiwiY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSIsIkdyYXBoUUxPYmplY3RUeXBlIiwiY29ubmVjdGlvblR5cGUiLCJlZGdlVHlwZSIsImNvbm5lY3Rpb25GaWVsZHMiLCJjb3VudCIsIkNPVU5UX0FUVCIsIm5vZGVUeXBlIiwiY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGUiLCJ2aWV3ZXJUeXBlIiwic2Vzc2lvblRva2VuIiwiU0VTU0lPTl9UT0tFTl9BVFQiLCJ1c2VyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBQUE7O0FBVUE7O0FBS0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FBS0EsTUFBTUEsdUJBQXVCLEdBQUcsVUFDOUJDLGdCQUQ4QixFQUU5QjtBQUNBLFNBQVFBLGdCQUFnQixJQUFJQSxnQkFBZ0IsQ0FBQ0MsSUFBdEMsSUFBK0MsRUFBdEQ7QUFDRCxDQUpEOztBQU1BLE1BQU1DLDRCQUE0QixHQUFHLFVBQ25DQyxVQURtQyxFQUVuQ0gsZ0JBRm1DLEVBR25DO0FBQ0EsUUFBTUksV0FBVyxHQUFHQyxNQUFNLENBQUNDLElBQVAsQ0FBWUgsVUFBVSxDQUFDSSxNQUF2QixFQUErQkMsTUFBL0IsQ0FBc0MsSUFBdEMsQ0FBcEI7QUFDQSxRQUFNO0FBQ0pDLElBQUFBLFdBQVcsRUFBRUMsa0JBRFQ7QUFFSkMsSUFBQUEsWUFBWSxFQUFFQyxtQkFGVjtBQUdKQyxJQUFBQSxnQkFBZ0IsRUFBRUMsdUJBSGQ7QUFJSkMsSUFBQUEsVUFBVSxFQUFFQztBQUpSLE1BS0ZqQix1QkFBdUIsQ0FBQ0MsZ0JBQUQsQ0FMM0I7QUFPQSxNQUFJaUIsaUJBQUo7QUFDQSxNQUFJQyxpQkFBSjtBQUNBLE1BQUlDLGlCQUFKO0FBQ0EsTUFBSUMscUJBQUo7QUFDQSxNQUFJQyxlQUFKLENBYkEsQ0FlQTs7QUFDQSxRQUFNQyxpQkFBaUIsR0FBR2xCLFdBQVcsQ0FBQ21CLE1BQVosQ0FBbUJDLEtBQUssSUFBSTtBQUNwRCxXQUNFLENBQUNuQixNQUFNLENBQUNDLElBQVAsQ0FBWW1CLG1CQUFtQixDQUFDQyxtQkFBaEMsRUFBcURDLFFBQXJELENBQThESCxLQUE5RCxDQUFELElBQ0FBLEtBQUssS0FBSyxJQUZaO0FBSUQsR0FMeUIsQ0FBMUI7O0FBT0EsTUFBSWQsa0JBQWtCLElBQUlBLGtCQUFrQixDQUFDa0IsTUFBN0MsRUFBcUQ7QUFDbkRWLElBQUFBLGlCQUFpQixHQUFHSSxpQkFBaUIsQ0FBQ0MsTUFBbEIsQ0FBeUJDLEtBQUssSUFBSTtBQUNwRCxhQUFPZCxrQkFBa0IsQ0FBQ2tCLE1BQW5CLENBQTBCRCxRQUExQixDQUFtQ0gsS0FBbkMsQ0FBUDtBQUNELEtBRm1CLENBQXBCO0FBR0QsR0FKRCxNQUlPO0FBQ0xOLElBQUFBLGlCQUFpQixHQUFHSSxpQkFBcEI7QUFDRDs7QUFDRCxNQUFJWixrQkFBa0IsSUFBSUEsa0JBQWtCLENBQUNtQixNQUE3QyxFQUFxRDtBQUNuRFYsSUFBQUEsaUJBQWlCLEdBQUdHLGlCQUFpQixDQUFDQyxNQUFsQixDQUF5QkMsS0FBSyxJQUFJO0FBQ3BELGFBQU9kLGtCQUFrQixDQUFDbUIsTUFBbkIsQ0FBMEJGLFFBQTFCLENBQW1DSCxLQUFuQyxDQUFQO0FBQ0QsS0FGbUIsQ0FBcEI7QUFHRCxHQUpELE1BSU87QUFDTEwsSUFBQUEsaUJBQWlCLEdBQUdHLGlCQUFwQjtBQUNEOztBQUVELE1BQUlWLG1CQUFKLEVBQXlCO0FBQ3ZCSyxJQUFBQSxpQkFBaUIsR0FBR0ssaUJBQWlCLENBQUNDLE1BQWxCLENBQXlCQyxLQUFLLElBQUk7QUFDcEQsYUFBT1osbUJBQW1CLENBQUNlLFFBQXBCLENBQTZCSCxLQUE3QixDQUFQO0FBQ0QsS0FGbUIsQ0FBcEI7QUFHRCxHQUpELE1BSU87QUFDTFAsSUFBQUEsaUJBQWlCLEdBQUdLLGlCQUFwQjtBQUNELEdBNUNELENBNkNBOzs7QUFDQSxNQUFJbkIsVUFBVSxDQUFDMkIsU0FBWCxLQUF5QixPQUE3QixFQUFzQztBQUNwQ2IsSUFBQUEsaUJBQWlCLEdBQUdBLGlCQUFpQixDQUFDTSxNQUFsQixDQUNsQlEsV0FBVyxJQUFJQSxXQUFXLEtBQUssVUFEYixDQUFwQjtBQUdEOztBQUVELE1BQUlqQix1QkFBSixFQUE2QjtBQUMzQk0sSUFBQUEscUJBQXFCLEdBQUdFLGlCQUFpQixDQUFDQyxNQUFsQixDQUF5QkMsS0FBSyxJQUFJO0FBQ3hELGFBQU9WLHVCQUF1QixDQUFDYSxRQUF4QixDQUFpQ0gsS0FBakMsQ0FBUDtBQUNELEtBRnVCLENBQXhCO0FBR0QsR0FKRCxNQUlPO0FBQ0xKLElBQUFBLHFCQUFxQixHQUFHaEIsV0FBeEI7QUFDRDs7QUFFRCxNQUFJWSxpQkFBSixFQUF1QjtBQUNyQkssSUFBQUEsZUFBZSxHQUFHTCxpQkFBbEI7O0FBQ0EsUUFBSSxDQUFDSyxlQUFlLENBQUNXLE1BQXJCLEVBQTZCO0FBQzNCO0FBQ0E7QUFDQVgsTUFBQUEsZUFBZSxDQUFDWSxJQUFoQixDQUFxQjtBQUNuQlQsUUFBQUEsS0FBSyxFQUFFLElBRFk7QUFFbkJVLFFBQUFBLEdBQUcsRUFBRSxJQUZjO0FBR25CQyxRQUFBQSxJQUFJLEVBQUU7QUFIYSxPQUFyQjtBQUtEO0FBQ0YsR0FYRCxNQVdPO0FBQ0xkLElBQUFBLGVBQWUsR0FBR2pCLFdBQVcsQ0FBQ2dDLEdBQVosQ0FBZ0JaLEtBQUssSUFBSTtBQUN6QyxhQUFPO0FBQUVBLFFBQUFBLEtBQUY7QUFBU1UsUUFBQUEsR0FBRyxFQUFFLElBQWQ7QUFBb0JDLFFBQUFBLElBQUksRUFBRTtBQUExQixPQUFQO0FBQ0QsS0FGaUIsQ0FBbEI7QUFHRDs7QUFFRCxTQUFPO0FBQ0xqQixJQUFBQSxpQkFESztBQUVMQyxJQUFBQSxpQkFGSztBQUdMQyxJQUFBQSxxQkFISztBQUlMSCxJQUFBQSxpQkFKSztBQUtMSSxJQUFBQTtBQUxLLEdBQVA7QUFPRCxDQXZGRDs7QUF5RkEsTUFBTWdCLElBQUksR0FBRyxDQUNYQyxrQkFEVyxFQUVYbkMsVUFGVyxFQUdYSCxnQkFIVyxLQUlSO0FBQ0gsUUFBTThCLFNBQVMsR0FBRzNCLFVBQVUsQ0FBQzJCLFNBQTdCO0FBQ0EsUUFBTVMsZ0JBQWdCLEdBQUcsNENBQTRCVCxTQUE1QixDQUF6QjtBQUNBLFFBQU07QUFDSlosSUFBQUEsaUJBREk7QUFFSkMsSUFBQUEsaUJBRkk7QUFHSkYsSUFBQUEsaUJBSEk7QUFJSkcsSUFBQUEscUJBSkk7QUFLSkMsSUFBQUE7QUFMSSxNQU1GbkIsNEJBQTRCLENBQUNDLFVBQUQsRUFBYUgsZ0JBQWIsQ0FOaEM7QUFRQSxRQUFNO0FBQ0o0QixJQUFBQSxNQUFNLEVBQUVZLGVBQWUsR0FBRyxJQUR0QjtBQUVKWCxJQUFBQSxNQUFNLEVBQUVZLGVBQWUsR0FBRztBQUZ0QixNQUdGLG9EQUE0QnpDLGdCQUE1QixDQUhKO0FBS0EsUUFBTTBDLDBCQUEwQixHQUFJLFNBQVFILGdCQUFpQixhQUE3RDtBQUNBLE1BQUlJLHNCQUFzQixHQUFHLElBQUlDLCtCQUFKLENBQTJCO0FBQ3REQyxJQUFBQSxJQUFJLEVBQUVILDBCQURnRDtBQUV0REksSUFBQUEsV0FBVyxFQUFHLE9BQU1KLDBCQUEyQiw2RUFBNEVILGdCQUFpQixTQUZ0RjtBQUd0RGhDLElBQUFBLE1BQU0sRUFBRSxNQUNOVyxpQkFBaUIsQ0FBQzZCLE1BQWxCLENBQ0UsQ0FBQ3hDLE1BQUQsRUFBU2lCLEtBQVQsS0FBbUI7QUFDakIsWUFBTXZCLElBQUksR0FBRyw0Q0FDWEUsVUFBVSxDQUFDSSxNQUFYLENBQWtCaUIsS0FBbEIsRUFBeUJ2QixJQURkLEVBRVhFLFVBQVUsQ0FBQ0ksTUFBWCxDQUFrQmlCLEtBQWxCLEVBQXlCd0IsV0FGZCxFQUdYVixrQkFBa0IsQ0FBQ1csZUFIUixDQUFiOztBQUtBLFVBQUloRCxJQUFKLEVBQVU7QUFDUixpQ0FDS00sTUFETDtBQUVFLFdBQUNpQixLQUFELEdBQVM7QUFDUHNCLFlBQUFBLFdBQVcsRUFBRyxzQkFBcUJ0QixLQUFNLEdBRGxDO0FBRVB2QixZQUFBQSxJQUFJLEVBQ0Q2QixTQUFTLEtBQUssT0FBZCxLQUNFTixLQUFLLEtBQUssVUFBVixJQUF3QkEsS0FBSyxLQUFLLFVBRHBDLENBQUQsSUFFQXJCLFVBQVUsQ0FBQ0ksTUFBWCxDQUFrQmlCLEtBQWxCLEVBQXlCMEIsUUFGekIsR0FHSSxJQUFJQyx1QkFBSixDQUFtQmxELElBQW5CLENBSEosR0FJSUE7QUFQQztBQUZYO0FBWUQsT0FiRCxNQWFPO0FBQ0wsZUFBT00sTUFBUDtBQUNEO0FBQ0YsS0F2QkgsRUF3QkU7QUFDRTZDLE1BQUFBLEdBQUcsRUFBRTtBQUFFbkQsUUFBQUEsSUFBSSxFQUFFd0IsbUJBQW1CLENBQUM0QjtBQUE1QjtBQURQLEtBeEJGO0FBSm9ELEdBQTNCLENBQTdCO0FBaUNBVixFQUFBQSxzQkFBc0IsR0FBR0wsa0JBQWtCLENBQUNnQixjQUFuQixDQUN2Qlgsc0JBRHVCLENBQXpCO0FBSUEsUUFBTVksMEJBQTBCLEdBQUksU0FBUWhCLGdCQUFpQixhQUE3RDtBQUNBLE1BQUlpQixzQkFBc0IsR0FBRyxJQUFJWiwrQkFBSixDQUEyQjtBQUN0REMsSUFBQUEsSUFBSSxFQUFFVSwwQkFEZ0Q7QUFFdERULElBQUFBLFdBQVcsRUFBRyxPQUFNUywwQkFBMkIsNkVBQTRFaEIsZ0JBQWlCLFNBRnRGO0FBR3REaEMsSUFBQUEsTUFBTSxFQUFFLE1BQ05ZLGlCQUFpQixDQUFDNEIsTUFBbEIsQ0FDRSxDQUFDeEMsTUFBRCxFQUFTaUIsS0FBVCxLQUFtQjtBQUNqQixZQUFNdkIsSUFBSSxHQUFHLDRDQUNYRSxVQUFVLENBQUNJLE1BQVgsQ0FBa0JpQixLQUFsQixFQUF5QnZCLElBRGQsRUFFWEUsVUFBVSxDQUFDSSxNQUFYLENBQWtCaUIsS0FBbEIsRUFBeUJ3QixXQUZkLEVBR1hWLGtCQUFrQixDQUFDVyxlQUhSLENBQWI7O0FBS0EsVUFBSWhELElBQUosRUFBVTtBQUNSLGlDQUNLTSxNQURMO0FBRUUsV0FBQ2lCLEtBQUQsR0FBUztBQUNQc0IsWUFBQUEsV0FBVyxFQUFHLHNCQUFxQnRCLEtBQU0sR0FEbEM7QUFFUHZCLFlBQUFBO0FBRk87QUFGWDtBQU9ELE9BUkQsTUFRTztBQUNMLGVBQU9NLE1BQVA7QUFDRDtBQUNGLEtBbEJILEVBbUJFO0FBQ0U2QyxNQUFBQSxHQUFHLEVBQUU7QUFBRW5ELFFBQUFBLElBQUksRUFBRXdCLG1CQUFtQixDQUFDNEI7QUFBNUI7QUFEUCxLQW5CRjtBQUpvRCxHQUEzQixDQUE3QjtBQTRCQUcsRUFBQUEsc0JBQXNCLEdBQUdsQixrQkFBa0IsQ0FBQ2dCLGNBQW5CLENBQ3ZCRSxzQkFEdUIsQ0FBekI7QUFJQSxRQUFNQywyQkFBMkIsR0FBSSxHQUFFbEIsZ0JBQWlCLGNBQXhEO0FBQ0EsTUFBSW1CLHVCQUF1QixHQUFHLElBQUlkLCtCQUFKLENBQTJCO0FBQ3ZEQyxJQUFBQSxJQUFJLEVBQUVZLDJCQURpRDtBQUV2RFgsSUFBQUEsV0FBVyxFQUFHLGtEQUFpRFAsZ0JBQWlCLFNBRnpCO0FBR3ZEaEMsSUFBQUEsTUFBTSxFQUFFLE1BQU07QUFDWixZQUFNQSxNQUFNLEdBQUc7QUFDYm9ELFFBQUFBLElBQUksRUFBRTtBQUNKYixVQUFBQSxXQUFXLEVBQUcsZ0NBQStCUCxnQkFBaUIseURBRDFEO0FBRUp0QyxVQUFBQSxJQUFJLEVBQUUyRDtBQUZGO0FBRE8sT0FBZjs7QUFNQSxVQUFJcEIsZUFBSixFQUFxQjtBQUNuQmpDLFFBQUFBLE1BQU0sQ0FBQyxlQUFELENBQU4sR0FBMEI7QUFDeEJ1QyxVQUFBQSxXQUFXLEVBQUcsa0NBQWlDUCxnQkFBaUIsU0FEeEM7QUFFeEJ0QyxVQUFBQSxJQUFJLEVBQUUwQztBQUZrQixTQUExQjtBQUlEOztBQUNELGFBQU9wQyxNQUFQO0FBQ0Q7QUFqQnNELEdBQTNCLENBQTlCO0FBbUJBbUQsRUFBQUEsdUJBQXVCLEdBQ3JCcEIsa0JBQWtCLENBQUNnQixjQUFuQixDQUFrQ0ksdUJBQWxDLEtBQ0FqQyxtQkFBbUIsQ0FBQ29DLE1BRnRCO0FBSUEsUUFBTUMsNEJBQTRCLEdBQUksR0FBRXZCLGdCQUFpQixlQUF6RDtBQUNBLE1BQUl3Qix3QkFBd0IsR0FBRyxJQUFJbkIsK0JBQUosQ0FBMkI7QUFDeERDLElBQUFBLElBQUksRUFBRWlCLDRCQURrRDtBQUV4RGhCLElBQUFBLFdBQVcsRUFBRyxxREFBb0RQLGdCQUFpQiwrQkFGM0I7QUFHeERoQyxJQUFBQSxNQUFNLEVBQUUsTUFBTTtBQUNaLFlBQU1BLE1BQU0sR0FBRztBQUNieUQsUUFBQUEsR0FBRyxFQUFFO0FBQ0hsQixVQUFBQSxXQUFXLEVBQUcsaUNBQWdDUCxnQkFBaUIsNEVBRDVEO0FBRUh0QyxVQUFBQSxJQUFJLEVBQUUsSUFBSWdFLG9CQUFKLENBQWdCeEMsbUJBQW1CLENBQUN5QyxTQUFwQztBQUZILFNBRFE7QUFLYkMsUUFBQUEsTUFBTSxFQUFFO0FBQ05yQixVQUFBQSxXQUFXLEVBQUcsb0NBQW1DUCxnQkFBaUIsOEVBRDVEO0FBRU50QyxVQUFBQSxJQUFJLEVBQUUsSUFBSWdFLG9CQUFKLENBQWdCeEMsbUJBQW1CLENBQUN5QyxTQUFwQztBQUZBO0FBTEssT0FBZjs7QUFVQSxVQUFJMUIsZUFBSixFQUFxQjtBQUNuQmpDLFFBQUFBLE1BQU0sQ0FBQyxjQUFELENBQU4sR0FBeUI7QUFDdkJ1QyxVQUFBQSxXQUFXLEVBQUcsaUNBQWdDUCxnQkFBaUIsMkJBRHhDO0FBRXZCdEMsVUFBQUEsSUFBSSxFQUFFLElBQUlnRSxvQkFBSixDQUFnQixJQUFJZCx1QkFBSixDQUFtQlIsc0JBQW5CLENBQWhCO0FBRmlCLFNBQXpCO0FBSUQ7O0FBQ0QsYUFBT3BDLE1BQVA7QUFDRDtBQXJCdUQsR0FBM0IsQ0FBL0I7QUF1QkF3RCxFQUFBQSx3QkFBd0IsR0FDdEJ6QixrQkFBa0IsQ0FBQ2dCLGNBQW5CLENBQWtDUyx3QkFBbEMsS0FDQXRDLG1CQUFtQixDQUFDb0MsTUFGdEI7QUFJQSxRQUFNTywrQkFBK0IsR0FBSSxHQUFFN0IsZ0JBQWlCLFlBQTVEO0FBQ0EsTUFBSThCLDJCQUEyQixHQUFHLElBQUl6QiwrQkFBSixDQUEyQjtBQUMzREMsSUFBQUEsSUFBSSxFQUFFdUIsK0JBRHFEO0FBRTNEdEIsSUFBQUEsV0FBVyxFQUFHLE9BQU1zQiwrQkFBZ0MsdUVBQXNFN0IsZ0JBQWlCLFNBRmhGO0FBRzNEaEMsSUFBQUEsTUFBTSxFQUFFLHdCQUNIYSxxQkFBcUIsQ0FBQzJCLE1BQXRCLENBQTZCLENBQUN4QyxNQUFELEVBQVNpQixLQUFULEtBQW1CO0FBQ2pELFVBQUksQ0FBQyxJQUFELEVBQU8sS0FBUCxFQUFjLEtBQWQsRUFBcUJHLFFBQXJCLENBQThCSCxLQUE5QixDQUFKLEVBQTBDO0FBQ3hDYyxRQUFBQSxrQkFBa0IsQ0FBQ2dDLEdBQW5CLENBQXVCQyxJQUF2QixDQUNHLFNBQVEvQyxLQUFNLDBDQUF5QzRDLCtCQUFnQyw0Q0FEMUY7QUFHQSxlQUFPN0QsTUFBUDtBQUNEOztBQUNELFlBQU1pRSxVQUFVLEdBQUdoRCxLQUFLLEtBQUssSUFBVixHQUFpQixVQUFqQixHQUE4QkEsS0FBakQ7QUFDQSxZQUFNdkIsSUFBSSxHQUFHLHNEQUNYRSxVQUFVLENBQUNJLE1BQVgsQ0FBa0JpRSxVQUFsQixFQUE4QnZFLElBRG5CLEVBRVhFLFVBQVUsQ0FBQ0ksTUFBWCxDQUFrQmlFLFVBQWxCLEVBQThCeEIsV0FGbkIsRUFHWFYsa0JBQWtCLENBQUNXLGVBSFIsRUFJWHpCLEtBSlcsQ0FBYjs7QUFNQSxVQUFJdkIsSUFBSixFQUFVO0FBQ1IsaUNBQ0tNLE1BREw7QUFFRSxXQUFDaUIsS0FBRCxHQUFTO0FBQ1BzQixZQUFBQSxXQUFXLEVBQUcsc0JBQXFCdEIsS0FBTSxHQURsQztBQUVQdkIsWUFBQUE7QUFGTztBQUZYO0FBT0QsT0FSRCxNQVFPO0FBQ0wsZUFBT00sTUFBUDtBQUNEO0FBQ0YsS0F6QkUsRUF5QkEsRUF6QkEsQ0FERztBQTJCTmtFLE1BQUFBLEVBQUUsRUFBRTtBQUNGM0IsUUFBQUEsV0FBVyxFQUFFLGtEQURYO0FBRUY3QyxRQUFBQSxJQUFJLEVBQUUsSUFBSWdFLG9CQUFKLENBQWdCLElBQUlkLHVCQUFKLENBQW1Ca0IsMkJBQW5CLENBQWhCO0FBRkosT0EzQkU7QUErQk5LLE1BQUFBLEdBQUcsRUFBRTtBQUNINUIsUUFBQUEsV0FBVyxFQUFFLG1EQURWO0FBRUg3QyxRQUFBQSxJQUFJLEVBQUUsSUFBSWdFLG9CQUFKLENBQWdCLElBQUlkLHVCQUFKLENBQW1Ca0IsMkJBQW5CLENBQWhCO0FBRkgsT0EvQkM7QUFtQ05NLE1BQUFBLEdBQUcsRUFBRTtBQUNIN0IsUUFBQUEsV0FBVyxFQUFFLG1EQURWO0FBRUg3QyxRQUFBQSxJQUFJLEVBQUUsSUFBSWdFLG9CQUFKLENBQWdCLElBQUlkLHVCQUFKLENBQW1Ca0IsMkJBQW5CLENBQWhCO0FBRkg7QUFuQ0M7QUFIbUQsR0FBM0IsQ0FBbEM7QUE0Q0FBLEVBQUFBLDJCQUEyQixHQUN6Qi9CLGtCQUFrQixDQUFDZ0IsY0FBbkIsQ0FBa0NlLDJCQUFsQyxLQUNBNUMsbUJBQW1CLENBQUNvQyxNQUZ0QjtBQUlBLFFBQU1lLHVDQUF1QyxHQUFJLEdBQUVyQyxnQkFBaUIsb0JBQXBFO0FBQ0EsTUFBSXNDLG1DQUFtQyxHQUFHLElBQUlqQywrQkFBSixDQUEyQjtBQUNuRUMsSUFBQUEsSUFBSSxFQUFFK0IsdUNBRDZEO0FBRW5FOUIsSUFBQUEsV0FBVyxFQUFHLE9BQU04Qix1Q0FBd0MsdUVBQXNFckMsZ0JBQWlCLFNBRmhGO0FBR25FaEMsSUFBQUEsTUFBTSxFQUFFLE9BQU87QUFDYnVFLE1BQUFBLElBQUksRUFBRTtBQUNKaEMsUUFBQUEsV0FBVyxFQUNULDJFQUZFO0FBR0o3QyxRQUFBQSxJQUFJLEVBQUVvRTtBQUhGLE9BRE87QUFNYlUsTUFBQUEsT0FBTyxFQUFFO0FBQ1BqQyxRQUFBQSxXQUFXLEVBQ1QscUZBRks7QUFHUDdDLFFBQUFBLElBQUksRUFBRW9FO0FBSEMsT0FOSTtBQVdiVyxNQUFBQSxNQUFNLEVBQUU7QUFDTmxDLFFBQUFBLFdBQVcsRUFBRSxpREFEUDtBQUVON0MsUUFBQUEsSUFBSSxFQUFFZ0Y7QUFGQTtBQVhLLEtBQVA7QUFIMkQsR0FBM0IsQ0FBMUM7QUFvQkFKLEVBQUFBLG1DQUFtQyxHQUNqQ3ZDLGtCQUFrQixDQUFDZ0IsY0FBbkIsQ0FBa0N1QixtQ0FBbEMsS0FDQXBELG1CQUFtQixDQUFDb0MsTUFGdEI7QUFJQSxRQUFNcUIseUJBQXlCLEdBQUksR0FBRTNDLGdCQUFpQixPQUF0RDtBQUNBLE1BQUk0QyxxQkFBcUIsR0FBRyxJQUFJQyx3QkFBSixDQUFvQjtBQUM5Q3ZDLElBQUFBLElBQUksRUFBRXFDLHlCQUR3QztBQUU5Q3BDLElBQUFBLFdBQVcsRUFBRyxPQUFNb0MseUJBQTBCLG1EQUFrRDNDLGdCQUFpQixTQUZuRTtBQUc5QzhDLElBQUFBLE1BQU0sRUFBRWhFLGVBQWUsQ0FBQzBCLE1BQWhCLENBQXVCLENBQUNoQyxVQUFELEVBQWF1RSxXQUFiLEtBQTZCO0FBQzFELFlBQU07QUFBRTlELFFBQUFBLEtBQUY7QUFBU1UsUUFBQUEsR0FBVDtBQUFjQyxRQUFBQTtBQUFkLFVBQXVCbUQsV0FBN0I7O0FBQ0EsWUFBTUMsaUJBQWlCLHFCQUNsQnhFLFVBRGtCLENBQXZCOztBQUdBLFlBQU15RSxLQUFLLEdBQUdoRSxLQUFLLEtBQUssSUFBVixHQUFpQixVQUFqQixHQUE4QkEsS0FBNUM7O0FBQ0EsVUFBSVUsR0FBSixFQUFTO0FBQ1BxRCxRQUFBQSxpQkFBaUIsQ0FBRSxHQUFFL0QsS0FBTSxNQUFWLENBQWpCLEdBQW9DO0FBQUVnRSxVQUFBQTtBQUFGLFNBQXBDO0FBQ0Q7O0FBQ0QsVUFBSXJELElBQUosRUFBVTtBQUNSb0QsUUFBQUEsaUJBQWlCLENBQUUsR0FBRS9ELEtBQU0sT0FBVixDQUFqQixHQUFxQztBQUFFZ0UsVUFBQUEsS0FBSyxFQUFHLElBQUdBLEtBQU07QUFBbkIsU0FBckM7QUFDRDs7QUFDRCxhQUFPRCxpQkFBUDtBQUNELEtBYk8sRUFhTCxFQWJLO0FBSHNDLEdBQXBCLENBQTVCO0FBa0JBSixFQUFBQSxxQkFBcUIsR0FBRzdDLGtCQUFrQixDQUFDZ0IsY0FBbkIsQ0FDdEI2QixxQkFEc0IsQ0FBeEI7O0FBSUEsUUFBTU0sb0JBQW9CO0FBQ3hCQyxJQUFBQSxLQUFLLEVBQUU7QUFDTDVDLE1BQUFBLFdBQVcsRUFDVCwrRUFGRztBQUdMN0MsTUFBQUEsSUFBSSxFQUFFb0U7QUFIRCxLQURpQjtBQU14QnNCLElBQUFBLEtBQUssRUFBRTtBQUNMN0MsTUFBQUEsV0FBVyxFQUFFLHNEQURSO0FBRUw3QyxNQUFBQSxJQUFJLEVBQUVrRixxQkFBcUIsR0FDdkIsSUFBSWxCLG9CQUFKLENBQWdCLElBQUlkLHVCQUFKLENBQW1CZ0MscUJBQW5CLENBQWhCLENBRHVCLEdBRXZCUztBQUpDLEtBTmlCO0FBWXhCQyxJQUFBQSxJQUFJLEVBQUVwRSxtQkFBbUIsQ0FBQ3FFO0FBWkYsS0FhckJDLDRCQWJxQjtBQWN4QkMsSUFBQUEsT0FBTyxFQUFFdkUsbUJBQW1CLENBQUN3RTtBQWRMLElBQTFCOztBQWdCQSxRQUFNQywwQkFBMEIsR0FBSSxHQUFFM0QsZ0JBQWlCLEVBQXZEO0FBQ0EsUUFBTTRELFVBQVUsR0FBRyxDQUNqQjFFLG1CQUFtQixDQUFDMkUsWUFESCxFQUVqQjlELGtCQUFrQixDQUFDK0Qsa0JBRkYsQ0FBbkI7O0FBSUEsUUFBTUMsaUJBQWlCO0FBQ3JCQyxJQUFBQSxFQUFFLEVBQUUsaUNBQWN6RSxTQUFkLEVBQXlCMEUsR0FBRyxJQUFJQSxHQUFHLENBQUNDLFFBQXBDO0FBRGlCLEtBRWxCaEYsbUJBQW1CLENBQUNDLG1CQUZGLENBQXZCOztBQUlBLFFBQU1mLFlBQVksR0FBRyxNQUFNO0FBQ3pCLFdBQU9NLGlCQUFpQixDQUFDOEIsTUFBbEIsQ0FBeUIsQ0FBQ3hDLE1BQUQsRUFBU2lCLEtBQVQsS0FBbUI7QUFDakQsWUFBTXZCLElBQUksR0FBRyw4Q0FDWEUsVUFBVSxDQUFDSSxNQUFYLENBQWtCaUIsS0FBbEIsRUFBeUJ2QixJQURkLEVBRVhFLFVBQVUsQ0FBQ0ksTUFBWCxDQUFrQmlCLEtBQWxCLEVBQXlCd0IsV0FGZCxFQUdYVixrQkFBa0IsQ0FBQ1csZUFIUixDQUFiOztBQUtBLFVBQUk5QyxVQUFVLENBQUNJLE1BQVgsQ0FBa0JpQixLQUFsQixFQUF5QnZCLElBQXpCLEtBQWtDLFVBQXRDLEVBQWtEO0FBQ2hELGNBQU15RyxxQkFBcUIsR0FDekJwRSxrQkFBa0IsQ0FBQ1csZUFBbkIsQ0FDRTlDLFVBQVUsQ0FBQ0ksTUFBWCxDQUFrQmlCLEtBQWxCLEVBQXlCd0IsV0FEM0IsQ0FERjtBQUlBLGNBQU0yRCxJQUFJLEdBQUdELHFCQUFxQixHQUM5QkEscUJBQXFCLENBQUNqQixvQkFEUSxHQUU5Qm1CLFNBRko7QUFHQSxpQ0FDS3JHLE1BREw7QUFFRSxXQUFDaUIsS0FBRCxHQUFTO0FBQ1BzQixZQUFBQSxXQUFXLEVBQUcsc0JBQXFCdEIsS0FBTSxHQURsQztBQUVQbUYsWUFBQUEsSUFGTztBQUdQMUcsWUFBQUEsSUFBSSxFQUFFRSxVQUFVLENBQUNJLE1BQVgsQ0FBa0JpQixLQUFsQixFQUF5QjBCLFFBQXpCLEdBQ0YsSUFBSUMsdUJBQUosQ0FBbUJsRCxJQUFuQixDQURFLEdBRUZBLElBTEc7O0FBTVAsa0JBQU00RyxPQUFOLENBQWNDLE1BQWQsRUFBc0JILElBQXRCLEVBQTRCSSxPQUE1QixFQUFxQ0MsU0FBckMsRUFBZ0Q7QUFDOUMsa0JBQUk7QUFDRixzQkFBTTtBQUNKdEIsa0JBQUFBLEtBREk7QUFFSkMsa0JBQUFBLEtBRkk7QUFHSkUsa0JBQUFBLElBSEk7QUFJSm9CLGtCQUFBQSxLQUpJO0FBS0pDLGtCQUFBQSxLQUxJO0FBTUpDLGtCQUFBQSxJQU5JO0FBT0pDLGtCQUFBQSxNQVBJO0FBUUpwQixrQkFBQUE7QUFSSSxvQkFTRlcsSUFUSjtBQVVBLHNCQUFNO0FBQ0pVLGtCQUFBQSxjQURJO0FBRUpDLGtCQUFBQSxxQkFGSTtBQUdKQyxrQkFBQUE7QUFISSxvQkFJRnZCLE9BQU8sSUFBSSxFQUpmO0FBS0Esc0JBQU07QUFBRXdCLGtCQUFBQSxNQUFGO0FBQVVDLGtCQUFBQSxJQUFWO0FBQWdCQyxrQkFBQUE7QUFBaEIsb0JBQXlCWCxPQUEvQjtBQUNBLHNCQUFNWSxjQUFjLEdBQUcsZ0NBQWNYLFNBQWQsQ0FBdkI7QUFFQSxzQkFBTTtBQUFFMUcsa0JBQUFBLElBQUY7QUFBUXNILGtCQUFBQTtBQUFSLG9CQUFvQiw4Q0FDeEJELGNBQWMsQ0FDWHBHLE1BREgsQ0FDVUMsS0FBSyxJQUFJQSxLQUFLLENBQUNxRyxVQUFOLENBQWlCLGFBQWpCLENBRG5CLEVBRUd6RixHQUZILENBRU9aLEtBQUssSUFBSUEsS0FBSyxDQUFDc0csT0FBTixDQUFjLGFBQWQsRUFBNkIsRUFBN0IsQ0FGaEIsQ0FEd0IsQ0FBMUI7QUFLQSxzQkFBTUMsVUFBVSxHQUFHcEMsS0FBSyxJQUFJQSxLQUFLLENBQUNxQyxJQUFOLENBQVcsR0FBWCxDQUE1QjtBQUVBLHVCQUFPQyxjQUFjLENBQUNDLFdBQWYsQ0FDTHBCLE1BQU0sQ0FBQ3RGLEtBQUQsQ0FBTixDQUFjTSxTQURUO0FBR0hxRyxrQkFBQUEsVUFBVSxFQUFFO0FBQ1ZDLG9CQUFBQSxNQUFNLEVBQUU7QUFDTkMsc0JBQUFBLE1BQU0sRUFBRSxTQURGO0FBRU52RyxzQkFBQUEsU0FBUyxFQUFFQSxTQUZMO0FBR04yRSxzQkFBQUEsUUFBUSxFQUFFSyxNQUFNLENBQUNMO0FBSFgscUJBREU7QUFNVjZCLG9CQUFBQSxHQUFHLEVBQUU5RztBQU5LO0FBSFQsbUJBV0NrRSxLQUFLLElBQUksRUFYVixHQWFMcUMsVUFiSyxFQWNMbEMsSUFkSyxFQWVMb0IsS0FmSyxFQWdCTEMsS0FoQkssRUFpQkxDLElBakJLLEVBa0JMQyxNQWxCSyxFQW1CTDlHLElBbkJLLEVBb0JMc0gsT0FwQkssRUFxQkwsS0FyQkssRUFzQkxQLGNBdEJLLEVBdUJMQyxxQkF2QkssRUF3QkxDLHNCQXhCSyxFQXlCTEMsTUF6QkssRUEwQkxDLElBMUJLLEVBMkJMQyxJQTNCSyxFQTRCTEMsY0E1QkssRUE2QkxyRixrQkFBa0IsQ0FBQ2lHLFlBN0JkLENBQVA7QUErQkQsZUF6REQsQ0F5REUsT0FBT0MsQ0FBUCxFQUFVO0FBQ1ZsRyxnQkFBQUEsa0JBQWtCLENBQUNtRyxXQUFuQixDQUErQkQsQ0FBL0I7QUFDRDtBQUNGOztBQW5FTTtBQUZYO0FBd0VELE9BaEZELE1BZ0ZPLElBQUlySSxVQUFVLENBQUNJLE1BQVgsQ0FBa0JpQixLQUFsQixFQUF5QnZCLElBQXpCLEtBQWtDLFNBQXRDLEVBQWlEO0FBQ3RELGlDQUNLTSxNQURMO0FBRUUsV0FBQ2lCLEtBQUQsR0FBUztBQUNQc0IsWUFBQUEsV0FBVyxFQUFHLHNCQUFxQnRCLEtBQU0sR0FEbEM7QUFFUHZCLFlBQUFBLElBQUksRUFBRUUsVUFBVSxDQUFDSSxNQUFYLENBQWtCaUIsS0FBbEIsRUFBeUIwQixRQUF6QixHQUNGLElBQUlDLHVCQUFKLENBQW1CbEQsSUFBbkIsQ0FERSxHQUVGQSxJQUpHOztBQUtQLGtCQUFNNEcsT0FBTixDQUFjQyxNQUFkLEVBQXNCO0FBQ3BCLGtCQUFJQSxNQUFNLENBQUN0RixLQUFELENBQU4sSUFBaUJzRixNQUFNLENBQUN0RixLQUFELENBQU4sQ0FBY2tILFdBQW5DLEVBQWdEO0FBQzlDLHVCQUFPNUIsTUFBTSxDQUFDdEYsS0FBRCxDQUFOLENBQWNrSCxXQUFkLENBQTBCdEcsR0FBMUIsQ0FBOEJ1RyxVQUFVLEtBQUs7QUFDbERDLGtCQUFBQSxRQUFRLEVBQUVELFVBQVUsQ0FBQyxDQUFELENBRDhCO0FBRWxERSxrQkFBQUEsU0FBUyxFQUFFRixVQUFVLENBQUMsQ0FBRDtBQUY2QixpQkFBTCxDQUF4QyxDQUFQO0FBSUQsZUFMRCxNQUtPO0FBQ0wsdUJBQU8sSUFBUDtBQUNEO0FBQ0Y7O0FBZE07QUFGWDtBQW1CRCxPQXBCTSxNQW9CQSxJQUFJeEksVUFBVSxDQUFDSSxNQUFYLENBQWtCaUIsS0FBbEIsRUFBeUJ2QixJQUF6QixLQUFrQyxPQUF0QyxFQUErQztBQUNwRCxpQ0FDS00sTUFETDtBQUVFLFdBQUNpQixLQUFELEdBQVM7QUFDUHNCLFlBQUFBLFdBQVcsRUFBRyxrR0FEUDtBQUVQN0MsWUFBQUEsSUFBSSxFQUFFRSxVQUFVLENBQUNJLE1BQVgsQ0FBa0JpQixLQUFsQixFQUF5QjBCLFFBQXpCLEdBQ0YsSUFBSUMsdUJBQUosQ0FBbUJsRCxJQUFuQixDQURFLEdBRUZBLElBSkc7O0FBS1Asa0JBQU00RyxPQUFOLENBQWNDLE1BQWQsRUFBc0I7QUFDcEIsa0JBQUksQ0FBQ0EsTUFBTSxDQUFDdEYsS0FBRCxDQUFYLEVBQW9CLE9BQU8sSUFBUDtBQUNwQixxQkFBT3NGLE1BQU0sQ0FBQ3RGLEtBQUQsQ0FBTixDQUFjWSxHQUFkLENBQWtCLE1BQU0wRyxJQUFOLElBQWM7QUFDckMsb0JBQ0VBLElBQUksQ0FBQ2hILFNBQUwsSUFDQWdILElBQUksQ0FBQ3JDLFFBREwsSUFFQXFDLElBQUksQ0FBQ1QsTUFBTCxLQUFnQixRQUhsQixFQUlFO0FBQ0EseUJBQU9TLElBQVA7QUFDRCxpQkFORCxNQU1PO0FBQ0wseUJBQU87QUFBRXRELG9CQUFBQSxLQUFLLEVBQUVzRDtBQUFULG1CQUFQO0FBQ0Q7QUFDRixlQVZNLENBQVA7QUFXRDs7QUFsQk07QUFGWDtBQXVCRCxPQXhCTSxNQXdCQSxJQUFJN0ksSUFBSixFQUFVO0FBQ2YsaUNBQ0tNLE1BREw7QUFFRSxXQUFDaUIsS0FBRCxHQUFTO0FBQ1BzQixZQUFBQSxXQUFXLEVBQUcsc0JBQXFCdEIsS0FBTSxHQURsQztBQUVQdkIsWUFBQUEsSUFBSSxFQUFFRSxVQUFVLENBQUNJLE1BQVgsQ0FBa0JpQixLQUFsQixFQUF5QjBCLFFBQXpCLEdBQ0YsSUFBSUMsdUJBQUosQ0FBbUJsRCxJQUFuQixDQURFLEdBRUZBO0FBSkc7QUFGWDtBQVNELE9BVk0sTUFVQTtBQUNMLGVBQU9NLE1BQVA7QUFDRDtBQUNGLEtBL0lNLEVBK0lKK0YsaUJBL0lJLENBQVA7QUFnSkQsR0FqSkQ7O0FBa0pBLE1BQUl5QyxzQkFBc0IsR0FBRyxJQUFJQywwQkFBSixDQUFzQjtBQUNqRG5HLElBQUFBLElBQUksRUFBRXFELDBCQUQyQztBQUVqRHBELElBQUFBLFdBQVcsRUFBRyxPQUFNb0QsMEJBQTJCLHlFQUF3RTNELGdCQUFpQixTQUZ2RjtBQUdqRDRELElBQUFBLFVBSGlEO0FBSWpENUYsSUFBQUEsTUFBTSxFQUFFSTtBQUp5QyxHQUF0QixDQUE3QjtBQU1Bb0ksRUFBQUEsc0JBQXNCLEdBQUd6RyxrQkFBa0IsQ0FBQ2dCLGNBQW5CLENBQ3ZCeUYsc0JBRHVCLENBQXpCO0FBSUEsUUFBTTtBQUFFRSxJQUFBQSxjQUFGO0FBQWtCQyxJQUFBQTtBQUFsQixNQUErQix5Q0FBc0I7QUFDekRyRyxJQUFBQSxJQUFJLEVBQUVOLGdCQURtRDtBQUV6RDRHLElBQUFBLGdCQUFnQixFQUFFO0FBQ2hCQyxNQUFBQSxLQUFLLEVBQUUzSCxtQkFBbUIsQ0FBQzRIO0FBRFgsS0FGdUM7QUFLekRDLElBQUFBLFFBQVEsRUFBRVAsc0JBQXNCLElBQUl0SCxtQkFBbUIsQ0FBQ29DO0FBTEMsR0FBdEIsQ0FBckM7QUFPQSxNQUFJMEYsMEJBQTBCLEdBQUczQyxTQUFqQzs7QUFDQSxNQUNFdEUsa0JBQWtCLENBQUNnQixjQUFuQixDQUFrQzRGLFFBQWxDLEtBQ0E1RyxrQkFBa0IsQ0FBQ2dCLGNBQW5CLENBQWtDMkYsY0FBbEMsRUFBa0QsS0FBbEQsRUFBeUQsS0FBekQsRUFBZ0UsSUFBaEUsQ0FGRixFQUdFO0FBQ0FNLElBQUFBLDBCQUEwQixHQUFHTixjQUE3QjtBQUNEOztBQUVEM0csRUFBQUEsa0JBQWtCLENBQUNXLGVBQW5CLENBQW1DbkIsU0FBbkMsSUFBZ0Q7QUFDOUM0QixJQUFBQSx1QkFEOEM7QUFFOUNLLElBQUFBLHdCQUY4QztBQUc5Q3BCLElBQUFBLHNCQUg4QztBQUk5Q2EsSUFBQUEsc0JBSjhDO0FBSzlDYSxJQUFBQSwyQkFMOEM7QUFNOUNRLElBQUFBLG1DQU44QztBQU85Q1ksSUFBQUEsb0JBUDhDO0FBUTlDc0QsSUFBQUEsc0JBUjhDO0FBUzlDUSxJQUFBQSwwQkFUOEM7QUFVOUMvQixJQUFBQSxNQUFNLEVBQUU7QUFDTnhILE1BQUFBLGdCQURNO0FBRU53QyxNQUFBQSxlQUZNO0FBR05DLE1BQUFBO0FBSE07QUFWc0MsR0FBaEQ7O0FBaUJBLE1BQUlYLFNBQVMsS0FBSyxPQUFsQixFQUEyQjtBQUN6QixVQUFNMEgsVUFBVSxHQUFHLElBQUlSLDBCQUFKLENBQXNCO0FBQ3ZDbkcsTUFBQUEsSUFBSSxFQUFFLFFBRGlDO0FBRXZDQyxNQUFBQSxXQUFXLEVBQUcsNkZBRnlCO0FBR3ZDdkMsTUFBQUEsTUFBTSxFQUFFLE9BQU87QUFDYmtKLFFBQUFBLFlBQVksRUFBRWhJLG1CQUFtQixDQUFDaUksaUJBRHJCO0FBRWJDLFFBQUFBLElBQUksRUFBRTtBQUNKN0csVUFBQUEsV0FBVyxFQUFFLDJCQURUO0FBRUo3QyxVQUFBQSxJQUFJLEVBQUUsSUFBSWtELHVCQUFKLENBQW1CNEYsc0JBQW5CO0FBRkY7QUFGTyxPQUFQO0FBSCtCLEtBQXRCLENBQW5CO0FBV0F6RyxJQUFBQSxrQkFBa0IsQ0FBQ2dCLGNBQW5CLENBQWtDa0csVUFBbEMsRUFBOEMsSUFBOUMsRUFBb0QsSUFBcEQ7QUFDQWxILElBQUFBLGtCQUFrQixDQUFDa0gsVUFBbkIsR0FBZ0NBLFVBQWhDO0FBQ0Q7QUFDRixDQXBkRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEdyYXBoUUxJRCxcbiAgR3JhcGhRTE9iamVjdFR5cGUsXG4gIEdyYXBoUUxTdHJpbmcsXG4gIEdyYXBoUUxMaXN0LFxuICBHcmFwaFFMSW5wdXRPYmplY3RUeXBlLFxuICBHcmFwaFFMTm9uTnVsbCxcbiAgR3JhcGhRTEJvb2xlYW4sXG4gIEdyYXBoUUxFbnVtVHlwZSxcbn0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQge1xuICBnbG9iYWxJZEZpZWxkLFxuICBjb25uZWN0aW9uQXJncyxcbiAgY29ubmVjdGlvbkRlZmluaXRpb25zLFxufSBmcm9tICdncmFwaHFsLXJlbGF5JztcbmltcG9ydCBnZXRGaWVsZE5hbWVzIGZyb20gJ2dyYXBocWwtbGlzdC1maWVsZHMnO1xuaW1wb3J0ICogYXMgZGVmYXVsdEdyYXBoUUxUeXBlcyBmcm9tICcuL2RlZmF1bHRHcmFwaFFMVHlwZXMnO1xuaW1wb3J0ICogYXMgb2JqZWN0c1F1ZXJpZXMgZnJvbSAnLi4vaGVscGVycy9vYmplY3RzUXVlcmllcyc7XG5pbXBvcnQgeyBQYXJzZUdyYXBoUUxDbGFzc0NvbmZpZyB9IGZyb20gJy4uLy4uL0NvbnRyb2xsZXJzL1BhcnNlR3JhcGhRTENvbnRyb2xsZXInO1xuaW1wb3J0IHsgdHJhbnNmb3JtQ2xhc3NOYW1lVG9HcmFwaFFMIH0gZnJvbSAnLi4vdHJhbnNmb3JtZXJzL2NsYXNzTmFtZSc7XG5pbXBvcnQgeyB0cmFuc2Zvcm1JbnB1dFR5cGVUb0dyYXBoUUwgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvaW5wdXRUeXBlJztcbmltcG9ydCB7IHRyYW5zZm9ybU91dHB1dFR5cGVUb0dyYXBoUUwgfSBmcm9tICcuLi90cmFuc2Zvcm1lcnMvb3V0cHV0VHlwZSc7XG5pbXBvcnQgeyB0cmFuc2Zvcm1Db25zdHJhaW50VHlwZVRvR3JhcGhRTCB9IGZyb20gJy4uL3RyYW5zZm9ybWVycy9jb25zdHJhaW50VHlwZSc7XG5pbXBvcnQge1xuICBleHRyYWN0S2V5c0FuZEluY2x1ZGUsXG4gIGdldFBhcnNlQ2xhc3NNdXRhdGlvbkNvbmZpZyxcbn0gZnJvbSAnLi4vcGFyc2VHcmFwaFFMVXRpbHMnO1xuXG5jb25zdCBnZXRQYXJzZUNsYXNzVHlwZUNvbmZpZyA9IGZ1bmN0aW9uKFxuICBwYXJzZUNsYXNzQ29uZmlnOiA/UGFyc2VHcmFwaFFMQ2xhc3NDb25maWdcbikge1xuICByZXR1cm4gKHBhcnNlQ2xhc3NDb25maWcgJiYgcGFyc2VDbGFzc0NvbmZpZy50eXBlKSB8fCB7fTtcbn07XG5cbmNvbnN0IGdldElucHV0RmllbGRzQW5kQ29uc3RyYWludHMgPSBmdW5jdGlvbihcbiAgcGFyc2VDbGFzcyxcbiAgcGFyc2VDbGFzc0NvbmZpZzogP1BhcnNlR3JhcGhRTENsYXNzQ29uZmlnXG4pIHtcbiAgY29uc3QgY2xhc3NGaWVsZHMgPSBPYmplY3Qua2V5cyhwYXJzZUNsYXNzLmZpZWxkcykuY29uY2F0KCdpZCcpO1xuICBjb25zdCB7XG4gICAgaW5wdXRGaWVsZHM6IGFsbG93ZWRJbnB1dEZpZWxkcyxcbiAgICBvdXRwdXRGaWVsZHM6IGFsbG93ZWRPdXRwdXRGaWVsZHMsXG4gICAgY29uc3RyYWludEZpZWxkczogYWxsb3dlZENvbnN0cmFpbnRGaWVsZHMsXG4gICAgc29ydEZpZWxkczogYWxsb3dlZFNvcnRGaWVsZHMsXG4gIH0gPSBnZXRQYXJzZUNsYXNzVHlwZUNvbmZpZyhwYXJzZUNsYXNzQ29uZmlnKTtcblxuICBsZXQgY2xhc3NPdXRwdXRGaWVsZHM7XG4gIGxldCBjbGFzc0NyZWF0ZUZpZWxkcztcbiAgbGV0IGNsYXNzVXBkYXRlRmllbGRzO1xuICBsZXQgY2xhc3NDb25zdHJhaW50RmllbGRzO1xuICBsZXQgY2xhc3NTb3J0RmllbGRzO1xuXG4gIC8vIEFsbCBhbGxvd2VkIGN1c3RvbXMgZmllbGRzXG4gIGNvbnN0IGNsYXNzQ3VzdG9tRmllbGRzID0gY2xhc3NGaWVsZHMuZmlsdGVyKGZpZWxkID0+IHtcbiAgICByZXR1cm4gKFxuICAgICAgIU9iamVjdC5rZXlzKGRlZmF1bHRHcmFwaFFMVHlwZXMuUEFSU0VfT0JKRUNUX0ZJRUxEUykuaW5jbHVkZXMoZmllbGQpICYmXG4gICAgICBmaWVsZCAhPT0gJ2lkJ1xuICAgICk7XG4gIH0pO1xuXG4gIGlmIChhbGxvd2VkSW5wdXRGaWVsZHMgJiYgYWxsb3dlZElucHV0RmllbGRzLmNyZWF0ZSkge1xuICAgIGNsYXNzQ3JlYXRlRmllbGRzID0gY2xhc3NDdXN0b21GaWVsZHMuZmlsdGVyKGZpZWxkID0+IHtcbiAgICAgIHJldHVybiBhbGxvd2VkSW5wdXRGaWVsZHMuY3JlYXRlLmluY2x1ZGVzKGZpZWxkKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjbGFzc0NyZWF0ZUZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzO1xuICB9XG4gIGlmIChhbGxvd2VkSW5wdXRGaWVsZHMgJiYgYWxsb3dlZElucHV0RmllbGRzLnVwZGF0ZSkge1xuICAgIGNsYXNzVXBkYXRlRmllbGRzID0gY2xhc3NDdXN0b21GaWVsZHMuZmlsdGVyKGZpZWxkID0+IHtcbiAgICAgIHJldHVybiBhbGxvd2VkSW5wdXRGaWVsZHMudXBkYXRlLmluY2x1ZGVzKGZpZWxkKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjbGFzc1VwZGF0ZUZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzO1xuICB9XG5cbiAgaWYgKGFsbG93ZWRPdXRwdXRGaWVsZHMpIHtcbiAgICBjbGFzc091dHB1dEZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzLmZpbHRlcihmaWVsZCA9PiB7XG4gICAgICByZXR1cm4gYWxsb3dlZE91dHB1dEZpZWxkcy5pbmNsdWRlcyhmaWVsZCk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY2xhc3NPdXRwdXRGaWVsZHMgPSBjbGFzc0N1c3RvbUZpZWxkcztcbiAgfVxuICAvLyBGaWx0ZXJzIHRoZSBcInBhc3N3b3JkXCIgZmllbGQgZnJvbSBjbGFzcyBfVXNlclxuICBpZiAocGFyc2VDbGFzcy5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBjbGFzc091dHB1dEZpZWxkcyA9IGNsYXNzT3V0cHV0RmllbGRzLmZpbHRlcihcbiAgICAgIG91dHB1dEZpZWxkID0+IG91dHB1dEZpZWxkICE9PSAncGFzc3dvcmQnXG4gICAgKTtcbiAgfVxuXG4gIGlmIChhbGxvd2VkQ29uc3RyYWludEZpZWxkcykge1xuICAgIGNsYXNzQ29uc3RyYWludEZpZWxkcyA9IGNsYXNzQ3VzdG9tRmllbGRzLmZpbHRlcihmaWVsZCA9PiB7XG4gICAgICByZXR1cm4gYWxsb3dlZENvbnN0cmFpbnRGaWVsZHMuaW5jbHVkZXMoZmllbGQpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNsYXNzQ29uc3RyYWludEZpZWxkcyA9IGNsYXNzRmllbGRzO1xuICB9XG5cbiAgaWYgKGFsbG93ZWRTb3J0RmllbGRzKSB7XG4gICAgY2xhc3NTb3J0RmllbGRzID0gYWxsb3dlZFNvcnRGaWVsZHM7XG4gICAgaWYgKCFjbGFzc1NvcnRGaWVsZHMubGVuZ3RoKSB7XG4gICAgICAvLyBtdXN0IGhhdmUgYXQgbGVhc3QgMSBvcmRlciBmaWVsZFxuICAgICAgLy8gb3RoZXJ3aXNlIHRoZSBGaW5kQXJncyBJbnB1dCBUeXBlIHdpbGwgdGhyb3cuXG4gICAgICBjbGFzc1NvcnRGaWVsZHMucHVzaCh7XG4gICAgICAgIGZpZWxkOiAnaWQnLFxuICAgICAgICBhc2M6IHRydWUsXG4gICAgICAgIGRlc2M6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY2xhc3NTb3J0RmllbGRzID0gY2xhc3NGaWVsZHMubWFwKGZpZWxkID0+IHtcbiAgICAgIHJldHVybiB7IGZpZWxkLCBhc2M6IHRydWUsIGRlc2M6IHRydWUgfTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY2xhc3NDcmVhdGVGaWVsZHMsXG4gICAgY2xhc3NVcGRhdGVGaWVsZHMsXG4gICAgY2xhc3NDb25zdHJhaW50RmllbGRzLFxuICAgIGNsYXNzT3V0cHV0RmllbGRzLFxuICAgIGNsYXNzU29ydEZpZWxkcyxcbiAgfTtcbn07XG5cbmNvbnN0IGxvYWQgPSAoXG4gIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgcGFyc2VDbGFzcyxcbiAgcGFyc2VDbGFzc0NvbmZpZzogP1BhcnNlR3JhcGhRTENsYXNzQ29uZmlnXG4pID0+IHtcbiAgY29uc3QgY2xhc3NOYW1lID0gcGFyc2VDbGFzcy5jbGFzc05hbWU7XG4gIGNvbnN0IGdyYXBoUUxDbGFzc05hbWUgPSB0cmFuc2Zvcm1DbGFzc05hbWVUb0dyYXBoUUwoY2xhc3NOYW1lKTtcbiAgY29uc3Qge1xuICAgIGNsYXNzQ3JlYXRlRmllbGRzLFxuICAgIGNsYXNzVXBkYXRlRmllbGRzLFxuICAgIGNsYXNzT3V0cHV0RmllbGRzLFxuICAgIGNsYXNzQ29uc3RyYWludEZpZWxkcyxcbiAgICBjbGFzc1NvcnRGaWVsZHMsXG4gIH0gPSBnZXRJbnB1dEZpZWxkc0FuZENvbnN0cmFpbnRzKHBhcnNlQ2xhc3MsIHBhcnNlQ2xhc3NDb25maWcpO1xuXG4gIGNvbnN0IHtcbiAgICBjcmVhdGU6IGlzQ3JlYXRlRW5hYmxlZCA9IHRydWUsXG4gICAgdXBkYXRlOiBpc1VwZGF0ZUVuYWJsZWQgPSB0cnVlLFxuICB9ID0gZ2V0UGFyc2VDbGFzc011dGF0aW9uQ29uZmlnKHBhcnNlQ2xhc3NDb25maWcpO1xuXG4gIGNvbnN0IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGVOYW1lID0gYENyZWF0ZSR7Z3JhcGhRTENsYXNzTmFtZX1GaWVsZHNJbnB1dGA7XG4gIGxldCBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgIG5hbWU6IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7Y2xhc3NHcmFwaFFMQ3JlYXRlVHlwZU5hbWV9IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBjcmVhdGlvbiBvZiBvYmplY3RzIGluIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgZmllbGRzOiAoKSA9PlxuICAgICAgY2xhc3NDcmVhdGVGaWVsZHMucmVkdWNlKFxuICAgICAgICAoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHR5cGUgPSB0cmFuc2Zvcm1JbnB1dFR5cGVUb0dyYXBoUUwoXG4gICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSxcbiAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcyxcbiAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICh0eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgICAgIFtmaWVsZF06IHtcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogYFRoaXMgaXMgdGhlIG9iamVjdCAke2ZpZWxkfS5gLFxuICAgICAgICAgICAgICAgIHR5cGU6XG4gICAgICAgICAgICAgICAgICAoY2xhc3NOYW1lID09PSAnX1VzZXInICYmXG4gICAgICAgICAgICAgICAgICAgIChmaWVsZCA9PT0gJ3VzZXJuYW1lJyB8fCBmaWVsZCA9PT0gJ3Bhc3N3b3JkJykpIHx8XG4gICAgICAgICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0ucmVxdWlyZWRcbiAgICAgICAgICAgICAgICAgICAgPyBuZXcgR3JhcGhRTE5vbk51bGwodHlwZSlcbiAgICAgICAgICAgICAgICAgICAgOiB0eXBlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZpZWxkcztcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBBQ0w6IHsgdHlwZTogZGVmYXVsdEdyYXBoUUxUeXBlcy5BQ0xfSU5QVVQgfSxcbiAgICAgICAgfVxuICAgICAgKSxcbiAgfSk7XG4gIGNsYXNzR3JhcGhRTENyZWF0ZVR5cGUgPSBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZVxuICApO1xuXG4gIGNvbnN0IGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGVOYW1lID0gYFVwZGF0ZSR7Z3JhcGhRTENsYXNzTmFtZX1GaWVsZHNJbnB1dGA7XG4gIGxldCBjbGFzc0dyYXBoUUxVcGRhdGVUeXBlID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgIG5hbWU6IGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7Y2xhc3NHcmFwaFFMVXBkYXRlVHlwZU5hbWV9IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBjcmVhdGlvbiBvZiBvYmplY3RzIGluIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgZmllbGRzOiAoKSA9PlxuICAgICAgY2xhc3NVcGRhdGVGaWVsZHMucmVkdWNlKFxuICAgICAgICAoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHR5cGUgPSB0cmFuc2Zvcm1JbnB1dFR5cGVUb0dyYXBoUUwoXG4gICAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSxcbiAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcyxcbiAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICh0eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgICAgIFtmaWVsZF06IHtcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogYFRoaXMgaXMgdGhlIG9iamVjdCAke2ZpZWxkfS5gLFxuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmllbGRzO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIEFDTDogeyB0eXBlOiBkZWZhdWx0R3JhcGhRTFR5cGVzLkFDTF9JTlBVVCB9LFxuICAgICAgICB9XG4gICAgICApLFxuICB9KTtcbiAgY2xhc3NHcmFwaFFMVXBkYXRlVHlwZSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICBjbGFzc0dyYXBoUUxVcGRhdGVUeXBlXG4gICk7XG5cbiAgY29uc3QgY2xhc3NHcmFwaFFMUG9pbnRlclR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1Qb2ludGVySW5wdXRgO1xuICBsZXQgY2xhc3NHcmFwaFFMUG9pbnRlclR5cGUgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gICAgbmFtZTogY2xhc3NHcmFwaFFMUG9pbnRlclR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgQWxsb3cgdG8gbGluayBPUiBhZGQgYW5kIGxpbmsgYW4gb2JqZWN0IG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgZmllbGRzOiAoKSA9PiB7XG4gICAgICBjb25zdCBmaWVsZHMgPSB7XG4gICAgICAgIGxpbms6IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjogYExpbmsgYW4gZXhpc3Rpbmcgb2JqZWN0IGZyb20gJHtncmFwaFFMQ2xhc3NOYW1lfSBjbGFzcy4gWW91IGNhbiB1c2UgZWl0aGVyIHRoZSBnbG9iYWwgb3IgdGhlIG9iamVjdCBpZC5gLFxuICAgICAgICAgIHR5cGU6IEdyYXBoUUxJRCxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBpZiAoaXNDcmVhdGVFbmFibGVkKSB7XG4gICAgICAgIGZpZWxkc1snY3JlYXRlQW5kTGluayddID0ge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBgQ3JlYXRlIGFuZCBsaW5rIGFuIG9iamVjdCBmcm9tICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICAgICAgICB0eXBlOiBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZpZWxkcztcbiAgICB9LFxuICB9KTtcbiAgY2xhc3NHcmFwaFFMUG9pbnRlclR5cGUgPVxuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShjbGFzc0dyYXBoUUxQb2ludGVyVHlwZSkgfHxcbiAgICBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcblxuICBjb25zdCBjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1SZWxhdGlvbklucHV0YDtcbiAgbGV0IGNsYXNzR3JhcGhRTFJlbGF0aW9uVHlwZSA9IG5ldyBHcmFwaFFMSW5wdXRPYmplY3RUeXBlKHtcbiAgICBuYW1lOiBjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgQWxsb3cgdG8gYWRkLCByZW1vdmUsIGNyZWF0ZUFuZEFkZCBvYmplY3RzIG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzIGludG8gYSByZWxhdGlvbiBmaWVsZC5gLFxuICAgIGZpZWxkczogKCkgPT4ge1xuICAgICAgY29uc3QgZmllbGRzID0ge1xuICAgICAgICBhZGQ6IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjogYEFkZCBleGlzdGluZyBvYmplY3RzIGZyb20gdGhlICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MgaW50byB0aGUgcmVsYXRpb24uIFlvdSBjYW4gdXNlIGVpdGhlciB0aGUgZ2xvYmFsIG9yIHRoZSBvYmplY3QgaWRzLmAsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUX0lEKSxcbiAgICAgICAgfSxcbiAgICAgICAgcmVtb3ZlOiB7XG4gICAgICAgICAgZGVzY3JpcHRpb246IGBSZW1vdmUgZXhpc3Rpbmcgb2JqZWN0cyBmcm9tIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzIG91dCBvZiB0aGUgcmVsYXRpb24uIFlvdSBjYW4gdXNlIGVpdGhlciB0aGUgZ2xvYmFsIG9yIHRoZSBvYmplY3QgaWRzLmAsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUX0lEKSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBpZiAoaXNDcmVhdGVFbmFibGVkKSB7XG4gICAgICAgIGZpZWxkc1snY3JlYXRlQW5kQWRkJ10gPSB7XG4gICAgICAgICAgZGVzY3JpcHRpb246IGBDcmVhdGUgYW5kIGFkZCBvYmplY3RzIG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzIGludG8gdGhlIHJlbGF0aW9uLmAsXG4gICAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxMaXN0KG5ldyBHcmFwaFFMTm9uTnVsbChjbGFzc0dyYXBoUUxDcmVhdGVUeXBlKSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gZmllbGRzO1xuICAgIH0sXG4gIH0pO1xuICBjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGUgPVxuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGUpIHx8XG4gICAgZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1Q7XG5cbiAgY29uc3QgY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlTmFtZSA9IGAke2dyYXBoUUxDbGFzc05hbWV9V2hlcmVJbnB1dGA7XG4gIGxldCBjbGFzc0dyYXBoUUxDb25zdHJhaW50c1R5cGUgPSBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gICAgbmFtZTogY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlTmFtZSxcbiAgICBkZXNjcmlwdGlvbjogYFRoZSAke2NsYXNzR3JhcGhRTENvbnN0cmFpbnRzVHlwZU5hbWV9IGlucHV0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBmaWx0ZXJpbmcgb2JqZWN0cyBvZiAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgZmllbGRzOiAoKSA9PiAoe1xuICAgICAgLi4uY2xhc3NDb25zdHJhaW50RmllbGRzLnJlZHVjZSgoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgICBpZiAoWydPUicsICdBTkQnLCAnTk9SJ10uaW5jbHVkZXMoZmllbGQpKSB7XG4gICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmxvZy53YXJuKFxuICAgICAgICAgICAgYEZpZWxkICR7ZmllbGR9IGNvdWxkIG5vdCBiZSBhZGRlZCB0byB0aGUgYXV0byBzY2hlbWEgJHtjbGFzc0dyYXBoUUxDb25zdHJhaW50c1R5cGVOYW1lfSBiZWNhdXNlIGl0IGNvbGxpZGVkIHdpdGggYW4gZXhpc3Rpbmcgb25lLmBcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiBmaWVsZHM7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFyc2VGaWVsZCA9IGZpZWxkID09PSAnaWQnID8gJ29iamVjdElkJyA6IGZpZWxkO1xuICAgICAgICBjb25zdCB0eXBlID0gdHJhbnNmb3JtQ29uc3RyYWludFR5cGVUb0dyYXBoUUwoXG4gICAgICAgICAgcGFyc2VDbGFzcy5maWVsZHNbcGFyc2VGaWVsZF0udHlwZSxcbiAgICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1twYXJzZUZpZWxkXS50YXJnZXRDbGFzcyxcbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzLFxuICAgICAgICAgIGZpZWxkXG4gICAgICAgICk7XG4gICAgICAgIGlmICh0eXBlKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmZpZWxkcyxcbiAgICAgICAgICAgIFtmaWVsZF06IHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb246IGBUaGlzIGlzIHRoZSBvYmplY3QgJHtmaWVsZH0uYCxcbiAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gZmllbGRzO1xuICAgICAgICB9XG4gICAgICB9LCB7fSksXG4gICAgICBPUjoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIE9SIG9wZXJhdG9yIHRvIGNvbXBvdW5kIGNvbnN0cmFpbnRzLicsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlKSksXG4gICAgICB9LFxuICAgICAgQU5EOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgQU5EIG9wZXJhdG9yIHRvIGNvbXBvdW5kIGNvbnN0cmFpbnRzLicsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlKSksXG4gICAgICB9LFxuICAgICAgTk9SOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgTk9SIG9wZXJhdG9yIHRvIGNvbXBvdW5kIGNvbnN0cmFpbnRzLicsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlKSksXG4gICAgICB9LFxuICAgIH0pLFxuICB9KTtcbiAgY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlID1cbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlKSB8fFxuICAgIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuXG4gIGNvbnN0IGNsYXNzR3JhcGhRTFJlbGF0aW9uQ29uc3RyYWludHNUeXBlTmFtZSA9IGAke2dyYXBoUUxDbGFzc05hbWV9UmVsYXRpb25XaGVyZUlucHV0YDtcbiAgbGV0IGNsYXNzR3JhcGhRTFJlbGF0aW9uQ29uc3RyYWludHNUeXBlID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgIG5hbWU6IGNsYXNzR3JhcGhRTFJlbGF0aW9uQ29uc3RyYWludHNUeXBlTmFtZSxcbiAgICBkZXNjcmlwdGlvbjogYFRoZSAke2NsYXNzR3JhcGhRTFJlbGF0aW9uQ29uc3RyYWludHNUeXBlTmFtZX0gaW5wdXQgdHlwZSBpcyB1c2VkIGluIG9wZXJhdGlvbnMgdGhhdCBpbnZvbHZlIGZpbHRlcmluZyBvYmplY3RzIG9mICR7Z3JhcGhRTENsYXNzTmFtZX0gY2xhc3MuYCxcbiAgICBmaWVsZHM6ICgpID0+ICh7XG4gICAgICBoYXZlOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICdSdW4gYSByZWxhdGlvbmFsL3BvaW50ZXIgcXVlcnkgd2hlcmUgYXQgbGVhc3Qgb25lIGNoaWxkIG9iamVjdCBjYW4gbWF0Y2guJyxcbiAgICAgICAgdHlwZTogY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlLFxuICAgICAgfSxcbiAgICAgIGhhdmVOb3Q6IHtcbiAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgJ1J1biBhbiBpbnZlcnRlZCByZWxhdGlvbmFsL3BvaW50ZXIgcXVlcnkgd2hlcmUgYXQgbGVhc3Qgb25lIGNoaWxkIG9iamVjdCBjYW4gbWF0Y2guJyxcbiAgICAgICAgdHlwZTogY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlLFxuICAgICAgfSxcbiAgICAgIGV4aXN0czoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ0NoZWNrIGlmIHRoZSByZWxhdGlvbi9wb2ludGVyIGNvbnRhaW5zIG9iamVjdHMuJyxcbiAgICAgICAgdHlwZTogR3JhcGhRTEJvb2xlYW4sXG4gICAgICB9LFxuICAgIH0pLFxuICB9KTtcbiAgY2xhc3NHcmFwaFFMUmVsYXRpb25Db25zdHJhaW50c1R5cGUgPVxuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShjbGFzc0dyYXBoUUxSZWxhdGlvbkNvbnN0cmFpbnRzVHlwZSkgfHxcbiAgICBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcblxuICBjb25zdCBjbGFzc0dyYXBoUUxPcmRlclR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1PcmRlcmA7XG4gIGxldCBjbGFzc0dyYXBoUUxPcmRlclR5cGUgPSBuZXcgR3JhcGhRTEVudW1UeXBlKHtcbiAgICBuYW1lOiBjbGFzc0dyYXBoUUxPcmRlclR5cGVOYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBgVGhlICR7Y2xhc3NHcmFwaFFMT3JkZXJUeXBlTmFtZX0gaW5wdXQgdHlwZSBpcyB1c2VkIHdoZW4gc29ydGluZyBvYmplY3RzIG9mIHRoZSAke2dyYXBoUUxDbGFzc05hbWV9IGNsYXNzLmAsXG4gICAgdmFsdWVzOiBjbGFzc1NvcnRGaWVsZHMucmVkdWNlKChzb3J0RmllbGRzLCBmaWVsZENvbmZpZykgPT4ge1xuICAgICAgY29uc3QgeyBmaWVsZCwgYXNjLCBkZXNjIH0gPSBmaWVsZENvbmZpZztcbiAgICAgIGNvbnN0IHVwZGF0ZWRTb3J0RmllbGRzID0ge1xuICAgICAgICAuLi5zb3J0RmllbGRzLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHZhbHVlID0gZmllbGQgPT09ICdpZCcgPyAnb2JqZWN0SWQnIDogZmllbGQ7XG4gICAgICBpZiAoYXNjKSB7XG4gICAgICAgIHVwZGF0ZWRTb3J0RmllbGRzW2Ake2ZpZWxkfV9BU0NgXSA9IHsgdmFsdWUgfTtcbiAgICAgIH1cbiAgICAgIGlmIChkZXNjKSB7XG4gICAgICAgIHVwZGF0ZWRTb3J0RmllbGRzW2Ake2ZpZWxkfV9ERVNDYF0gPSB7IHZhbHVlOiBgLSR7dmFsdWV9YCB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHVwZGF0ZWRTb3J0RmllbGRzO1xuICAgIH0sIHt9KSxcbiAgfSk7XG4gIGNsYXNzR3JhcGhRTE9yZGVyVHlwZSA9IHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICBjbGFzc0dyYXBoUUxPcmRlclR5cGVcbiAgKTtcblxuICBjb25zdCBjbGFzc0dyYXBoUUxGaW5kQXJncyA9IHtcbiAgICB3aGVyZToge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGVzZSBhcmUgdGhlIGNvbmRpdGlvbnMgdGhhdCB0aGUgb2JqZWN0cyBuZWVkIHRvIG1hdGNoIGluIG9yZGVyIHRvIGJlIGZvdW5kLicsXG4gICAgICB0eXBlOiBjbGFzc0dyYXBoUUxDb25zdHJhaW50c1R5cGUsXG4gICAgfSxcbiAgICBvcmRlcjoge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgZmllbGRzIHRvIGJlIHVzZWQgd2hlbiBzb3J0aW5nIHRoZSBkYXRhIGZldGNoZWQuJyxcbiAgICAgIHR5cGU6IGNsYXNzR3JhcGhRTE9yZGVyVHlwZVxuICAgICAgICA/IG5ldyBHcmFwaFFMTGlzdChuZXcgR3JhcGhRTE5vbk51bGwoY2xhc3NHcmFwaFFMT3JkZXJUeXBlKSlcbiAgICAgICAgOiBHcmFwaFFMU3RyaW5nLFxuICAgIH0sXG4gICAgc2tpcDogZGVmYXVsdEdyYXBoUUxUeXBlcy5TS0lQX0FUVCxcbiAgICAuLi5jb25uZWN0aW9uQXJncyxcbiAgICBvcHRpb25zOiBkZWZhdWx0R3JhcGhRTFR5cGVzLlJFQURfT1BUSU9OU19BVFQsXG4gIH07XG4gIGNvbnN0IGNsYXNzR3JhcGhRTE91dHB1dFR5cGVOYW1lID0gYCR7Z3JhcGhRTENsYXNzTmFtZX1gO1xuICBjb25zdCBpbnRlcmZhY2VzID0gW1xuICAgIGRlZmF1bHRHcmFwaFFMVHlwZXMuUEFSU0VfT0JKRUNULFxuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5yZWxheU5vZGVJbnRlcmZhY2UsXG4gIF07XG4gIGNvbnN0IHBhcnNlT2JqZWN0RmllbGRzID0ge1xuICAgIGlkOiBnbG9iYWxJZEZpZWxkKGNsYXNzTmFtZSwgb2JqID0+IG9iai5vYmplY3RJZCksXG4gICAgLi4uZGVmYXVsdEdyYXBoUUxUeXBlcy5QQVJTRV9PQkpFQ1RfRklFTERTLFxuICB9O1xuICBjb25zdCBvdXRwdXRGaWVsZHMgPSAoKSA9PiB7XG4gICAgcmV0dXJuIGNsYXNzT3V0cHV0RmllbGRzLnJlZHVjZSgoZmllbGRzLCBmaWVsZCkgPT4ge1xuICAgICAgY29uc3QgdHlwZSA9IHRyYW5zZm9ybU91dHB1dFR5cGVUb0dyYXBoUUwoXG4gICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50eXBlLFxuICAgICAgICBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udGFyZ2V0Q2xhc3MsXG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNcbiAgICAgICk7XG4gICAgICBpZiAocGFyc2VDbGFzcy5maWVsZHNbZmllbGRdLnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgY29uc3QgdGFyZ2V0UGFyc2VDbGFzc1R5cGVzID1cbiAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW1xuICAgICAgICAgICAgcGFyc2VDbGFzcy5maWVsZHNbZmllbGRdLnRhcmdldENsYXNzXG4gICAgICAgICAgXTtcbiAgICAgICAgY29uc3QgYXJncyA9IHRhcmdldFBhcnNlQ2xhc3NUeXBlc1xuICAgICAgICAgID8gdGFyZ2V0UGFyc2VDbGFzc1R5cGVzLmNsYXNzR3JhcGhRTEZpbmRBcmdzXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4uZmllbGRzLFxuICAgICAgICAgIFtmaWVsZF06IHtcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgVGhpcyBpcyB0aGUgb2JqZWN0ICR7ZmllbGR9LmAsXG4gICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgdHlwZTogcGFyc2VDbGFzcy5maWVsZHNbZmllbGRdLnJlcXVpcmVkXG4gICAgICAgICAgICAgID8gbmV3IEdyYXBoUUxOb25OdWxsKHR5cGUpXG4gICAgICAgICAgICAgIDogdHlwZSxcbiAgICAgICAgICAgIGFzeW5jIHJlc29sdmUoc291cmNlLCBhcmdzLCBjb250ZXh0LCBxdWVyeUluZm8pIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICAgICAgICB3aGVyZSxcbiAgICAgICAgICAgICAgICAgIG9yZGVyLFxuICAgICAgICAgICAgICAgICAgc2tpcCxcbiAgICAgICAgICAgICAgICAgIGZpcnN0LFxuICAgICAgICAgICAgICAgICAgYWZ0ZXIsXG4gICAgICAgICAgICAgICAgICBsYXN0LFxuICAgICAgICAgICAgICAgICAgYmVmb3JlLFxuICAgICAgICAgICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICAgICAgICB9ID0gYXJncztcbiAgICAgICAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgICAgICAgIGluY2x1ZGVSZWFkUHJlZmVyZW5jZSxcbiAgICAgICAgICAgICAgICAgIHN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICAgICAgfSA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWRGaWVsZHMgPSBnZXRGaWVsZE5hbWVzKHF1ZXJ5SW5mbyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCB7IGtleXMsIGluY2x1ZGUgfSA9IGV4dHJhY3RLZXlzQW5kSW5jbHVkZShcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRmllbGRzXG4gICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoZmllbGQgPT4gZmllbGQuc3RhcnRzV2l0aCgnZWRnZXMubm9kZS4nKSlcbiAgICAgICAgICAgICAgICAgICAgLm1hcChmaWVsZCA9PiBmaWVsZC5yZXBsYWNlKCdlZGdlcy5ub2RlLicsICcnKSlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlT3JkZXIgPSBvcmRlciAmJiBvcmRlci5qb2luKCcsJyk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0c1F1ZXJpZXMuZmluZE9iamVjdHMoXG4gICAgICAgICAgICAgICAgICBzb3VyY2VbZmllbGRdLmNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgJHJlbGF0ZWRUbzoge1xuICAgICAgICAgICAgICAgICAgICAgIG9iamVjdDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdElkOiBzb3VyY2Uub2JqZWN0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICBrZXk6IGZpZWxkLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAuLi4od2hlcmUgfHwge30pLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHBhcnNlT3JkZXIsXG4gICAgICAgICAgICAgICAgICBza2lwLFxuICAgICAgICAgICAgICAgICAgZmlyc3QsXG4gICAgICAgICAgICAgICAgICBhZnRlcixcbiAgICAgICAgICAgICAgICAgIGxhc3QsXG4gICAgICAgICAgICAgICAgICBiZWZvcmUsXG4gICAgICAgICAgICAgICAgICBrZXlzLFxuICAgICAgICAgICAgICAgICAgaW5jbHVkZSxcbiAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICAgICAgICBpbmNsdWRlUmVhZFByZWZlcmVuY2UsXG4gICAgICAgICAgICAgICAgICBzdWJxdWVyeVJlYWRQcmVmZXJlbmNlLFxuICAgICAgICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgICAgIGluZm8sXG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZEZpZWxkcyxcbiAgICAgICAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzZXNcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmhhbmRsZUVycm9yKGUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgW2ZpZWxkXToge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246IGBUaGlzIGlzIHRoZSBvYmplY3QgJHtmaWVsZH0uYCxcbiAgICAgICAgICAgIHR5cGU6IHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS5yZXF1aXJlZFxuICAgICAgICAgICAgICA/IG5ldyBHcmFwaFFMTm9uTnVsbCh0eXBlKVxuICAgICAgICAgICAgICA6IHR5cGUsXG4gICAgICAgICAgICBhc3luYyByZXNvbHZlKHNvdXJjZSkge1xuICAgICAgICAgICAgICBpZiAoc291cmNlW2ZpZWxkXSAmJiBzb3VyY2VbZmllbGRdLmNvb3JkaW5hdGVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNvdXJjZVtmaWVsZF0uY29vcmRpbmF0ZXMubWFwKGNvb3JkaW5hdGUgPT4gKHtcbiAgICAgICAgICAgICAgICAgIGxhdGl0dWRlOiBjb29yZGluYXRlWzBdLFxuICAgICAgICAgICAgICAgICAgbG9uZ2l0dWRlOiBjb29yZGluYXRlWzFdLFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ0FycmF5Jykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLmZpZWxkcyxcbiAgICAgICAgICBbZmllbGRdOiB7XG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogYFVzZSBJbmxpbmUgRnJhZ21lbnQgb24gQXJyYXkgdG8gZ2V0IHJlc3VsdHM6IGh0dHBzOi8vZ3JhcGhxbC5vcmcvbGVhcm4vcXVlcmllcy8jaW5saW5lLWZyYWdtZW50c2AsXG4gICAgICAgICAgICB0eXBlOiBwYXJzZUNsYXNzLmZpZWxkc1tmaWVsZF0ucmVxdWlyZWRcbiAgICAgICAgICAgICAgPyBuZXcgR3JhcGhRTE5vbk51bGwodHlwZSlcbiAgICAgICAgICAgICAgOiB0eXBlLFxuICAgICAgICAgICAgYXN5bmMgcmVzb2x2ZShzb3VyY2UpIHtcbiAgICAgICAgICAgICAgaWYgKCFzb3VyY2VbZmllbGRdKSByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgcmV0dXJuIHNvdXJjZVtmaWVsZF0ubWFwKGFzeW5jIGVsZW0gPT4ge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgIGVsZW0uY2xhc3NOYW1lICYmXG4gICAgICAgICAgICAgICAgICBlbGVtLm9iamVjdElkICYmXG4gICAgICAgICAgICAgICAgICBlbGVtLl9fdHlwZSA9PT0gJ09iamVjdCdcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogZWxlbSB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5maWVsZHMsXG4gICAgICAgICAgW2ZpZWxkXToge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246IGBUaGlzIGlzIHRoZSBvYmplY3QgJHtmaWVsZH0uYCxcbiAgICAgICAgICAgIHR5cGU6IHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS5yZXF1aXJlZFxuICAgICAgICAgICAgICA/IG5ldyBHcmFwaFFMTm9uTnVsbCh0eXBlKVxuICAgICAgICAgICAgICA6IHR5cGUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmaWVsZHM7XG4gICAgICB9XG4gICAgfSwgcGFyc2VPYmplY3RGaWVsZHMpO1xuICB9O1xuICBsZXQgY2xhc3NHcmFwaFFMT3V0cHV0VHlwZSA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gICAgbmFtZTogY2xhc3NHcmFwaFFMT3V0cHV0VHlwZU5hbWUsXG4gICAgZGVzY3JpcHRpb246IGBUaGUgJHtjbGFzc0dyYXBoUUxPdXRwdXRUeXBlTmFtZX0gb2JqZWN0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBvdXRwdXR0aW5nIG9iamVjdHMgb2YgJHtncmFwaFFMQ2xhc3NOYW1lfSBjbGFzcy5gLFxuICAgIGludGVyZmFjZXMsXG4gICAgZmllbGRzOiBvdXRwdXRGaWVsZHMsXG4gIH0pO1xuICBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlID0gcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIGNsYXNzR3JhcGhRTE91dHB1dFR5cGVcbiAgKTtcblxuICBjb25zdCB7IGNvbm5lY3Rpb25UeXBlLCBlZGdlVHlwZSB9ID0gY29ubmVjdGlvbkRlZmluaXRpb25zKHtcbiAgICBuYW1lOiBncmFwaFFMQ2xhc3NOYW1lLFxuICAgIGNvbm5lY3Rpb25GaWVsZHM6IHtcbiAgICAgIGNvdW50OiBkZWZhdWx0R3JhcGhRTFR5cGVzLkNPVU5UX0FUVCxcbiAgICB9LFxuICAgIG5vZGVUeXBlOiBjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIHx8IGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNULFxuICB9KTtcbiAgbGV0IGNsYXNzR3JhcGhRTEZpbmRSZXN1bHRUeXBlID0gdW5kZWZpbmVkO1xuICBpZiAoXG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKGVkZ2VUeXBlKSAmJlxuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShjb25uZWN0aW9uVHlwZSwgZmFsc2UsIGZhbHNlLCB0cnVlKVxuICApIHtcbiAgICBjbGFzc0dyYXBoUUxGaW5kUmVzdWx0VHlwZSA9IGNvbm5lY3Rpb25UeXBlO1xuICB9XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1tjbGFzc05hbWVdID0ge1xuICAgIGNsYXNzR3JhcGhRTFBvaW50ZXJUeXBlLFxuICAgIGNsYXNzR3JhcGhRTFJlbGF0aW9uVHlwZSxcbiAgICBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlLFxuICAgIGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUsXG4gICAgY2xhc3NHcmFwaFFMQ29uc3RyYWludHNUeXBlLFxuICAgIGNsYXNzR3JhcGhRTFJlbGF0aW9uQ29uc3RyYWludHNUeXBlLFxuICAgIGNsYXNzR3JhcGhRTEZpbmRBcmdzLFxuICAgIGNsYXNzR3JhcGhRTE91dHB1dFR5cGUsXG4gICAgY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGUsXG4gICAgY29uZmlnOiB7XG4gICAgICBwYXJzZUNsYXNzQ29uZmlnLFxuICAgICAgaXNDcmVhdGVFbmFibGVkLFxuICAgICAgaXNVcGRhdGVFbmFibGVkLFxuICAgIH0sXG4gIH07XG5cbiAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgIGNvbnN0IHZpZXdlclR5cGUgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICAgICAgbmFtZTogJ1ZpZXdlcicsXG4gICAgICBkZXNjcmlwdGlvbjogYFRoZSBWaWV3ZXIgb2JqZWN0IHR5cGUgaXMgdXNlZCBpbiBvcGVyYXRpb25zIHRoYXQgaW52b2x2ZSBvdXRwdXR0aW5nIHRoZSBjdXJyZW50IHVzZXIgZGF0YS5gLFxuICAgICAgZmllbGRzOiAoKSA9PiAoe1xuICAgICAgICBzZXNzaW9uVG9rZW46IGRlZmF1bHRHcmFwaFFMVHlwZXMuU0VTU0lPTl9UT0tFTl9BVFQsXG4gICAgICAgIHVzZXI6IHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGN1cnJlbnQgdXNlci4nLFxuICAgICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChjbGFzc0dyYXBoUUxPdXRwdXRUeXBlKSxcbiAgICAgICAgfSxcbiAgICAgIH0pLFxuICAgIH0pO1xuICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZSh2aWV3ZXJUeXBlLCB0cnVlLCB0cnVlKTtcbiAgICBwYXJzZUdyYXBoUUxTY2hlbWEudmlld2VyVHlwZSA9IHZpZXdlclR5cGU7XG4gIH1cbn07XG5cbmV4cG9ydCB7IGV4dHJhY3RLZXlzQW5kSW5jbHVkZSwgbG9hZCB9O1xuIl19 \ 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..d4fc375f5a --- /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 = (0, _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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvc2NoZW1hRGlyZWN0aXZlcy5qcyJdLCJuYW1lcyI6WyJkZWZpbml0aW9ucyIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zIiwiUmVzb2x2ZURpcmVjdGl2ZVZpc2l0b3IiLCJTY2hlbWFEaXJlY3RpdmVWaXNpdG9yIiwidmlzaXRGaWVsZERlZmluaXRpb24iLCJmaWVsZCIsInJlc29sdmUiLCJfc291cmNlIiwiYXJncyIsImNvbnRleHQiLCJjb25maWciLCJhdXRoIiwiaW5mbyIsImZ1bmN0aW9uTmFtZSIsIm5hbWUiLCJ0byIsIkZ1bmN0aW9uc1JvdXRlciIsImhhbmRsZUNsb3VkRnVuY3Rpb24iLCJwYXJhbXMiLCJib2R5IiwicmVzcG9uc2UiLCJyZXN1bHQiLCJlIiwiaGFuZGxlRXJyb3IiLCJncmFwaFFMU2NoZW1hRGlyZWN0aXZlcyIsIk1vY2tEaXJlY3RpdmVWaXNpdG9yIiwid2l0aCIsIm1vY2siXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLFdBQVcsR0FBRyx3QkFBSTs7O0NBQXhCOzs7QUFLUCxNQUFNQyxJQUFJLEdBQUdDLGtCQUFrQixJQUFJO0FBQ2pDQSxFQUFBQSxrQkFBa0IsQ0FBQ0Msa0NBQW5CLEdBQXdESCxXQUF4RDs7QUFFQSxRQUFNSSx1QkFBTixTQUFzQ0Msb0NBQXRDLENBQTZEO0FBQzNEQyxJQUFBQSxvQkFBb0IsQ0FBQ0MsS0FBRCxFQUFRO0FBQzFCQSxNQUFBQSxLQUFLLENBQUNDLE9BQU4sR0FBZ0IsT0FBT0MsT0FBUCxFQUFnQkMsSUFBaEIsRUFBc0JDLE9BQXRCLEtBQWtDO0FBQ2hELFlBQUk7QUFDRixnQkFBTTtBQUFFQyxZQUFBQSxNQUFGO0FBQVVDLFlBQUFBLElBQVY7QUFBZ0JDLFlBQUFBO0FBQWhCLGNBQXlCSCxPQUEvQjtBQUVBLGNBQUlJLFlBQVksR0FBR1IsS0FBSyxDQUFDUyxJQUF6Qjs7QUFDQSxjQUFJLEtBQUtOLElBQUwsQ0FBVU8sRUFBZCxFQUFrQjtBQUNoQkYsWUFBQUEsWUFBWSxHQUFHLEtBQUtMLElBQUwsQ0FBVU8sRUFBekI7QUFDRDs7QUFFRCxpQkFBTyxDQUFDLE1BQU1DLGlDQUFnQkMsbUJBQWhCLENBQW9DO0FBQ2hEQyxZQUFBQSxNQUFNLEVBQUU7QUFDTkwsY0FBQUE7QUFETSxhQUR3QztBQUloREgsWUFBQUEsTUFKZ0Q7QUFLaERDLFlBQUFBLElBTGdEO0FBTWhEQyxZQUFBQSxJQU5nRDtBQU9oRE8sWUFBQUEsSUFBSSxFQUFFWDtBQVAwQyxXQUFwQyxDQUFQLEVBUUhZLFFBUkcsQ0FRTUMsTUFSYjtBQVNELFNBakJELENBaUJFLE9BQU9DLENBQVAsRUFBVTtBQUNWdEIsVUFBQUEsa0JBQWtCLENBQUN1QixXQUFuQixDQUErQkQsQ0FBL0I7QUFDRDtBQUNGLE9BckJEO0FBc0JEOztBQXhCMEQ7O0FBMkI3RHRCLEVBQUFBLGtCQUFrQixDQUFDd0IsdUJBQW5CLENBQTJDbEIsT0FBM0MsR0FBcURKLHVCQUFyRDs7QUFFQSxRQUFNdUIsb0JBQU4sU0FBbUN0QixvQ0FBbkMsQ0FBMEQ7QUFDeERDLElBQUFBLG9CQUFvQixDQUFDQyxLQUFELEVBQVE7QUFDMUJBLE1BQUFBLEtBQUssQ0FBQ0MsT0FBTixHQUFnQixNQUFNO0FBQ3BCLGVBQU8sS0FBS0UsSUFBTCxDQUFVa0IsSUFBakI7QUFDRCxPQUZEO0FBR0Q7O0FBTHVEOztBQVExRDFCLEVBQUFBLGtCQUFrQixDQUFDd0IsdUJBQW5CLENBQTJDRyxJQUEzQyxHQUFrREYsb0JBQWxEO0FBQ0QsQ0F6Q0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZ3FsIGZyb20gJ2dyYXBocWwtdGFnJztcbmltcG9ydCB7IFNjaGVtYURpcmVjdGl2ZVZpc2l0b3IgfSBmcm9tICdncmFwaHFsLXRvb2xzJztcbmltcG9ydCB7IEZ1bmN0aW9uc1JvdXRlciB9IGZyb20gJy4uLy4uL1JvdXRlcnMvRnVuY3Rpb25zUm91dGVyJztcblxuZXhwb3J0IGNvbnN0IGRlZmluaXRpb25zID0gZ3FsYFxuICBkaXJlY3RpdmUgQHJlc29sdmUodG86IFN0cmluZykgb24gRklFTERfREVGSU5JVElPTlxuICBkaXJlY3RpdmUgQG1vY2sod2l0aDogQW55ISkgb24gRklFTERfREVGSU5JVElPTlxuYDtcblxuY29uc3QgbG9hZCA9IHBhcnNlR3JhcGhRTFNjaGVtYSA9PiB7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zID0gZGVmaW5pdGlvbnM7XG5cbiAgY2xhc3MgUmVzb2x2ZURpcmVjdGl2ZVZpc2l0b3IgZXh0ZW5kcyBTY2hlbWFEaXJlY3RpdmVWaXNpdG9yIHtcbiAgICB2aXNpdEZpZWxkRGVmaW5pdGlvbihmaWVsZCkge1xuICAgICAgZmllbGQucmVzb2x2ZSA9IGFzeW5jIChfc291cmNlLCBhcmdzLCBjb250ZXh0KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgICBsZXQgZnVuY3Rpb25OYW1lID0gZmllbGQubmFtZTtcbiAgICAgICAgICBpZiAodGhpcy5hcmdzLnRvKSB7XG4gICAgICAgICAgICBmdW5jdGlvbk5hbWUgPSB0aGlzLmFyZ3MudG87XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIChhd2FpdCBGdW5jdGlvbnNSb3V0ZXIuaGFuZGxlQ2xvdWRGdW5jdGlvbih7XG4gICAgICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICAgICAgZnVuY3Rpb25OYW1lLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICBpbmZvLFxuICAgICAgICAgICAgYm9keTogYXJncyxcbiAgICAgICAgICB9KSkucmVzcG9uc2UucmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmhhbmRsZUVycm9yKGUpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlcy5yZXNvbHZlID0gUmVzb2x2ZURpcmVjdGl2ZVZpc2l0b3I7XG5cbiAgY2xhc3MgTW9ja0RpcmVjdGl2ZVZpc2l0b3IgZXh0ZW5kcyBTY2hlbWFEaXJlY3RpdmVWaXNpdG9yIHtcbiAgICB2aXNpdEZpZWxkRGVmaW5pdGlvbihmaWVsZCkge1xuICAgICAgZmllbGQucmVzb2x2ZSA9ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXJncy53aXRoO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXMubW9jayA9IE1vY2tEaXJlY3RpdmVWaXNpdG9yO1xufTtcblxuZXhwb3J0IHsgbG9hZCB9O1xuIl19 \ 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..2f948e3d7a --- /dev/null +++ b/lib/GraphQL/loaders/schemaMutations.js @@ -0,0 +1,179 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _graphql = require("graphql"); + +var _graphqlRelay = require("graphql-relay"); + +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 => { + const createClassMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'CreateClass', + description: 'The createClass mutation can be used to create the schema for a new object class.', + inputFields: { + name: schemaTypes.CLASS_NAME_ATT, + schemaFields: { + description: "These are the schema's fields of the object class.", + type: schemaTypes.SCHEMA_FIELDS_INPUT + } + }, + outputFields: { + class: { + description: 'This is the created class.', + type: new _graphql.GraphQLNonNull(schemaTypes.CLASS) + } + }, + mutateAndGetPayload: async (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 { + class: { + name: parseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(parseClass.fields) + } + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(createClassMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(createClassMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('createClass', createClassMutation, true, true); + const updateClassMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'UpdateClass', + description: 'The updateClass mutation can be used to update the schema for an existing object class.', + inputFields: { + name: schemaTypes.CLASS_NAME_ATT, + schemaFields: { + description: "These are the schema's fields of the object class.", + type: schemaTypes.SCHEMA_FIELDS_INPUT + } + }, + outputFields: { + class: { + description: 'This is the updated class.', + type: new _graphql.GraphQLNonNull(schemaTypes.CLASS) + } + }, + mutateAndGetPayload: async (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 { + class: { + name: parseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(parseClass.fields) + } + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(updateClassMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(updateClassMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('updateClass', updateClassMutation, true, true); + const deleteClassMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'DeleteClass', + description: 'The deleteClass mutation can be used to delete an existing object class.', + inputFields: { + name: schemaTypes.CLASS_NAME_ATT + }, + outputFields: { + class: { + description: 'This is the deleted class.', + type: new _graphql.GraphQLNonNull(schemaTypes.CLASS) + } + }, + mutateAndGetPayload: async (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 { + class: { + name: existingParseClass.className, + schemaFields: (0, _schemaFields.transformToGraphQL)(existingParseClass.fields) + } + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(deleteClassMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(deleteClassMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('deleteClass', deleteClassMutation, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvc2NoZW1hTXV0YXRpb25zLmpzIl0sIm5hbWVzIjpbImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJjcmVhdGVDbGFzc011dGF0aW9uIiwibmFtZSIsImRlc2NyaXB0aW9uIiwiaW5wdXRGaWVsZHMiLCJzY2hlbWFUeXBlcyIsIkNMQVNTX05BTUVfQVRUIiwic2NoZW1hRmllbGRzIiwidHlwZSIsIlNDSEVNQV9GSUVMRFNfSU5QVVQiLCJvdXRwdXRGaWVsZHMiLCJjbGFzcyIsIkdyYXBoUUxOb25OdWxsIiwiQ0xBU1MiLCJtdXRhdGVBbmRHZXRQYXlsb2FkIiwiYXJncyIsImNvbnRleHQiLCJjb25maWciLCJhdXRoIiwiaXNSZWFkT25seSIsIlBhcnNlIiwiRXJyb3IiLCJPUEVSQVRJT05fRk9SQklEREVOIiwic2NoZW1hIiwiZGF0YWJhc2UiLCJsb2FkU2NoZW1hIiwiY2xlYXJDYWNoZSIsInBhcnNlQ2xhc3MiLCJhZGRDbGFzc0lmTm90RXhpc3RzIiwiY2xhc3NOYW1lIiwiZmllbGRzIiwiZSIsImhhbmRsZUVycm9yIiwiYWRkR3JhcGhRTFR5cGUiLCJpbnB1dCIsIm9mVHlwZSIsImFkZEdyYXBoUUxNdXRhdGlvbiIsInVwZGF0ZUNsYXNzTXV0YXRpb24iLCJleGlzdGluZ1BhcnNlQ2xhc3MiLCJ1cGRhdGVDbGFzcyIsInVuZGVmaW5lZCIsImRlbGV0ZUNsYXNzTXV0YXRpb24iLCJkZWxldGVTY2hlbWEiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFJQTs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNQSxJQUFJLEdBQUdDLGtCQUFrQixJQUFJO0FBQ2pDLFFBQU1DLG1CQUFtQixHQUFHLGdEQUE2QjtBQUN2REMsSUFBQUEsSUFBSSxFQUFFLGFBRGlEO0FBRXZEQyxJQUFBQSxXQUFXLEVBQ1QsbUZBSHFEO0FBSXZEQyxJQUFBQSxXQUFXLEVBQUU7QUFDWEYs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LDZCQUFTcEMsSUFBVCxFQUFlcUIsTUFBZixDQUFqQztBQUNBLGNBQU1OLE1BQU0sQ0FBQ08sUUFBUCxDQUFnQmtCLFlBQWhCLENBQTZCeEMsSUFBN0IsQ0FBTjtBQUNBLGVBQU87QUFDTFMsVUFBQUEsS0FBSyxFQUFFO0FBQ0xULFlBQUFBLElBQUksRUFBRW9DLGtCQUFrQixDQUFDVCxTQURwQjtBQUVMdEIsWUFBQUEsWUFBWSxFQUFFLHNDQUFtQitCLGtCQUFrQixDQUFDUixNQUF0QztBQUZUO0FBREYsU0FBUDtBQU1ELE9BdEJELENBc0JFLE9BQU9DLENBQVAsRUFBVTtBQUNWL0IsUUFBQUEsa0JBQWtCLENBQUNnQyxXQUFuQixDQUErQkQsQ0FBL0I7QUFDRDtBQUNGO0FBdkNzRCxHQUE3QixDQUE1QjtBQTBDQS9CLEVBQUFBLGtCQUFrQixDQUFDaUMsY0FBbkIsQ0FDRVEsbUJBQW1CLENBQUMxQixJQUFwQixDQUF5Qm1CLEtBQXpCLENBQStCMUIsSUFBL0IsQ0FBb0MyQixNQUR0QyxFQUVFLElBRkYsRUFHRSxJQUhGO0FBS0FuQyxFQUFBQSxrQkFBa0IsQ0FBQ2lDLGNBQW5CLENBQWtDUSxtQkFBbUIsQ0FBQ2pDLElBQXRELEVBQTRELElBQTVELEVBQWtFLElBQWxFO0FBQ0FSLEVBQUFBLGtCQUFrQixDQUFDb0Msa0JBQW5CLENBQ0UsYUFERixFQUVFSyxtQkFGRixFQUdFLElBSEYsRUFJRSxJQUpGO0FBTUQsQ0FyTEQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBHcmFwaFFMTm9uTnVsbCB9IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0IHsgbXV0YXRpb25XaXRoQ2xpZW50TXV0YXRpb25JZCB9IGZyb20gJ2dyYXBocWwtcmVsYXknO1xuaW1wb3J0ICogYXMgc2NoZW1hVHlwZXMgZnJvbSAnLi9zY2hlbWFUeXBlcyc7XG5pbXBvcnQge1xuICB0cmFuc2Zvcm1Ub1BhcnNlLFxuICB0cmFuc2Zvcm1Ub0dyYXBoUUwsXG59IGZyb20gJy4uL3RyYW5zZm9ybWVycy9zY2hlbWFGaWVsZHMnO1xuaW1wb3J0IHsgZW5mb3JjZU1hc3RlcktleUFjY2VzcyB9IGZyb20gJy4uL3BhcnNlR3JhcGhRTFV0aWxzJztcbmltcG9ydCB7IGdldENsYXNzIH0gZnJvbSAnLi9zY2hlbWFRdWVyaWVzJztcblxuY29uc3QgbG9hZCA9IHBhcnNlR3JhcGhRTFNjaGVtYSA9PiB7XG4gIGNvbnN0IGNyZWF0ZUNsYXNzTXV0YXRpb24gPSBtdXRhdGlvbldpdGhDbGllbnRNdXRhdGlvbklkKHtcbiAgICBuYW1lOiAnQ3JlYXRlQ2xhc3MnLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1RoZSBjcmVhdGVDbGFzcyBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byBjcmVhdGUgdGhlIHNjaGVtYSBmb3IgYSBuZXcgb2JqZWN0IGNsYXNzLicsXG4gICAgaW5wdXRGaWVsZHM6IHtcbiAgICAgIG5hbWU6IHNjaGVtYVR5cGVzLkNMQVNTX05BTUVfQVRULFxuICAgICAgc2NoZW1hRmllbGRzOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIlRoZXNlIGFyZSB0aGUgc2NoZW1hJ3MgZmllbGRzIG9mIHRoZSBvYmplY3QgY2xhc3MuXCIsXG4gICAgICAgIHR5cGU6IHNjaGVtYVR5cGVzLlNDSEVNQV9GSUVMRFNfSU5QVVQsXG4gICAgICB9LFxuICAgIH0sXG4gICAgb3V0cHV0RmllbGRzOiB7XG4gICAgICBjbGFzczoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGNyZWF0ZWQgY2xhc3MuJyxcbiAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKHNjaGVtYVR5cGVzLkNMQVNTKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBtdXRhdGVBbmRHZXRQYXlsb2FkOiBhc3luYyAoYXJncywgY29udGV4dCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyBuYW1lLCBzY2hlbWFGaWVsZHMgfSA9IGFyZ3M7XG4gICAgICAgIGNvbnN0IHsgY29uZmlnLCBhdXRoIH0gPSBjb250ZXh0O1xuXG4gICAgICAgIGVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MoYXV0aCk7XG5cbiAgICAgICAgaWYgKGF1dGguaXNSZWFkT25seSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICAgICAgICBcInJlYWQtb25seSBtYXN0ZXJLZXkgaXNuJ3QgYWxsb3dlZCB0byBjcmVhdGUgYSBzY2hlbWEuXCJcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgY29uZmlnLmRhdGFiYXNlLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlIH0pO1xuICAgICAgICBjb25zdCBwYXJzZUNsYXNzID0gYXdhaXQgc2NoZW1hLmFkZENsYXNzSWZOb3RFeGlzdHMoXG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICB0cmFuc2Zvcm1Ub1BhcnNlKHNjaGVtYUZpZWxkcylcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjbGFzczoge1xuICAgICAgICAgICAgbmFtZTogcGFyc2VDbGFzcy5jbGFzc05hbWUsXG4gICAgICAgICAgICBzY2hlbWFGaWVsZHM6IHRyYW5zZm9ybVRvR3JhcGhRTChwYXJzZUNsYXNzLmZpZWxkcyksXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLmhhbmRsZUVycm9yKGUpO1xuICAgICAgfVxuICAgIH0sXG4gIH0pO1xuXG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShcbiAgICBjcmVhdGVDbGFzc011dGF0aW9uLmFyZ3MuaW5wdXQudHlwZS5vZlR5cGUsXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShjcmVhdGVDbGFzc011dGF0aW9uLnR5cGUsIHRydWUsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTE11dGF0aW9uKFxuICAgICdjcmVhdGVDbGFzcycsXG4gICAgY3JlYXRlQ2xhc3NNdXRhdGlvbixcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcblxuICBjb25zdCB1cGRhdGVDbGFzc011dGF0aW9uID0gbXV0YXRpb25XaXRoQ2xpZW50TXV0YXRpb25JZCh7XG4gICAgbmFtZTogJ1VwZGF0ZUNsYXNzJyxcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdUaGUgdXBkYXRlQ2xhc3MgbXV0YXRpb24gY2FuIGJlIHVzZWQgdG8gdXBkYXRlIHRoZSBzY2hlbWEgZm9yIGFuIGV4aXN0aW5nIG9iamVjdCBjbGFzcy4nLFxuICAgIGlucHV0RmllbGRzOiB7XG4gICAgICBuYW1lOiBzY2hlbWFUeXBlcy5DTEFTU19OQU1FX0FUVCxcbiAgICAgIHNjaGVtYUZpZWxkczoge1xuICAgICAgICBkZXNjcmlwdGlvbjogXCJUaGVzZSBhcmUgdGhlIHNjaGVtYSdzIGZpZWxkcyBvZiB0aGUgb2JqZWN0IGNsYXNzLlwiLFxuICAgICAgICB0eXBlOiBzY2hlbWFUeXBlcy5TQ0hFTUFfRklFTERTX0lOUFVULFxuICAgICAgfSxcbiAgICB9LFxuICAgIG91dHB1dEZpZWxkczoge1xuICAgICAgY2xhc3M6IHtcbiAgICAgICAgZGVzY3JpcHRpb246ICdUaGlzIGlzIHRoZSB1cGRhdGVkIGNsYXNzLicsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChzY2hlbWFUeXBlcy5DTEFTUyksXG4gICAgICB9LFxuICAgIH0sXG4gICAgbXV0YXRlQW5kR2V0UGF5bG9hZDogYXN5bmMgKGFyZ3MsIGNvbnRleHQpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHsgbmFtZSwgc2NoZW1hRmllbGRzIH0gPSBhcmdzO1xuICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCB9ID0gY29udGV4dDtcblxuICAgICAgICBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzKGF1dGgpO1xuXG4gICAgICAgIGlmIChhdXRoLmlzUmVhZE9ubHkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgXCJyZWFkLW9ubHkgbWFzdGVyS2V5IGlzbid0IGFsbG93ZWQgdG8gdXBkYXRlIGEgc2NoZW1hLlwiXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNjaGVtYSA9IGF3YWl0IGNvbmZpZy5kYXRhYmFzZS5sb2FkU2NoZW1hKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KTtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJzZUNsYXNzID0gYXdhaXQgZ2V0Q2xhc3MobmFtZSwgc2NoZW1hKTtcbiAgICAgICAgY29uc3QgcGFyc2VDbGFzcyA9IGF3YWl0IHNjaGVtYS51cGRhdGVDbGFzcyhcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIHRyYW5zZm9ybVRvUGFyc2Uoc2NoZW1hRmllbGRzLCBleGlzdGluZ1BhcnNlQ2xhc3MuZmllbGRzKSxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIGNvbmZpZy5kYXRhYmFzZVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGNsYXNzOiB7XG4gICAgICAgICAgICBuYW1lOiBwYXJzZUNsYXNzLmNsYXNzTmFtZSxcbiAgICAgICAgICAgIHNjaGVtYUZpZWxkczogdHJhbnNmb3JtVG9HcmFwaFFMKHBhcnNlQ2xhc3MuZmllbGRzKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIHVwZGF0ZUNsYXNzTXV0YXRpb24uYXJncy5pbnB1dC50eXBlLm9mVHlwZSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKHVwZGF0ZUNsYXNzTXV0YXRpb24udHlwZSwgdHJ1ZSwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgJ3VwZGF0ZUNsYXNzJyxcbiAgICB1cGRhdGVDbGFzc011dGF0aW9uLFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xuXG4gIGNvbnN0IGRlbGV0ZUNsYXNzTXV0YXRpb24gPSBtdXRhdGlvbldpdGhDbGllbnRNdXRhdGlvbklkKHtcbiAgICBuYW1lOiAnRGVsZXRlQ2xhc3MnLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1RoZSBkZWxldGVDbGFzcyBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byBkZWxldGUgYW4gZXhpc3Rpbmcgb2JqZWN0IGNsYXNzLicsXG4gICAgaW5wdXRGaWVsZHM6IHtcbiAgICAgIG5hbWU6IHNjaGVtYVR5cGVzLkNMQVNTX05BTUVfQVRULFxuICAgIH0sXG4gICAgb3V0cHV0RmllbGRzOiB7XG4gICAgICBjbGFzczoge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoaXMgaXMgdGhlIGRlbGV0ZWQgY2xhc3MuJyxcbiAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKHNjaGVtYVR5cGVzLkNMQVNTKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBtdXRhdGVBbmRHZXRQYXlsb2FkOiBhc3luYyAoYXJncywgY29udGV4dCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyBuYW1lIH0gPSBhcmdzO1xuICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCB9ID0gY29udGV4dDtcblxuICAgICAgICBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzKGF1dGgpO1xuXG4gICAgICAgIGlmIChhdXRoLmlzUmVhZE9ubHkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgXCJyZWFkLW9ubHkgbWFzdGVyS2V5IGlzbid0IGFsbG93ZWQgdG8gZGVsZXRlIGEgc2NoZW1hLlwiXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNjaGVtYSA9IGF3YWl0IGNvbmZpZy5kYXRhYmFzZS5sb2FkU2NoZW1hKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KTtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJzZUNsYXNzID0gYXdhaXQgZ2V0Q2xhc3MobmFtZSwgc2NoZW1hKTtcbiAgICAgICAgYXdhaXQgY29uZmlnLmRhdGFiYXNlLmRlbGV0ZVNjaGVtYShuYW1lKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjbGFzczoge1xuICAgICAgICAgICAgbmFtZTogZXhpc3RpbmdQYXJzZUNsYXNzLmNsYXNzTmFtZSxcbiAgICAgICAgICAgIHNjaGVtYUZpZWxkczogdHJhbnNmb3JtVG9HcmFwaFFMKGV4aXN0aW5nUGFyc2VDbGFzcy5maWVsZHMpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgZGVsZXRlQ2xhc3NNdXRhdGlvbi5hcmdzLmlucHV0LnR5cGUub2ZUeXBlLFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoZGVsZXRlQ2xhc3NNdXRhdGlvbi50eXBlLCB0cnVlLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxNdXRhdGlvbihcbiAgICAnZGVsZXRlQ2xhc3MnLFxuICAgIGRlbGV0ZUNsYXNzTXV0YXRpb24sXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG59O1xuXG5leHBvcnQgeyBsb2FkIH07XG4iXX0= \ 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..a0e2599c49 --- /dev/null +++ b/lib/GraphQL/loaders/usersMutations.js @@ -0,0 +1,310 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.load = void 0; + +var _graphql = require("graphql"); + +var _graphqlRelay = require("graphql-relay"); + +var _UsersRouter = _interopRequireDefault(require("../../Routers/UsersRouter")); + +var objectsMutations = _interopRequireWildcard(require("../helpers/objectsMutations")); + +var _defaultGraphQLTypes = require("./defaultGraphQLTypes"); + +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 }; } + +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 usersRouter = new _UsersRouter.default(); + +const load = parseGraphQLSchema => { + if (parseGraphQLSchema.isUsersClassDisabled) { + return; + } + + const signUpMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'SignUp', + description: 'The signUp mutation can be used to create and sign up a new user.', + inputFields: { + fields: { + descriptions: 'These are the fields of the new user to be created and signed up.', + type: parseGraphQLSchema.parseClassTypes['_User'].classGraphQLCreateType + } + }, + outputFields: { + viewer: { + description: 'This is the new user that was created, signed up and returned as a viewer.', + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType) + } + }, + mutateAndGetPayload: async (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 { + viewer: await (0, _usersQueries.getUserFromSessionToken)(config, info, mutationInfo, 'viewer.user.', true) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(signUpMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(signUpMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('signUp', signUpMutation, true, true); + const logInWithMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'LogInWith', + description: 'The logInWith mutation can be used to signup, login user with 3rd party authentication system. This mutation create a user if the authData do not correspond to an existing one.', + inputFields: { + authData: { + descriptions: 'This is the auth data of your custom auth provider', + type: new _graphql.GraphQLNonNull(_defaultGraphQLTypes.OBJECT) + }, + fields: { + descriptions: 'These are the fields of the user to be created/updated and logged in.', + type: new _graphql.GraphQLInputObjectType({ + name: 'UserLoginWithInput', + fields: () => { + const classGraphQLCreateFields = parseGraphQLSchema.parseClassTypes['_User'].classGraphQLCreateType.getFields(); + return Object.keys(classGraphQLCreateFields).reduce((fields, fieldName) => { + if (fieldName !== 'password' && fieldName !== 'username' && fieldName !== 'authData') { + fields[fieldName] = classGraphQLCreateFields[fieldName]; + } + + return fields; + }, {}); + } + }) + } + }, + outputFields: { + viewer: { + description: 'This is the new user that was created, signed up and returned as a viewer.', + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType) + } + }, + mutateAndGetPayload: async (args, context, mutationInfo) => { + try { + const { + fields, + authData + } = args; + const { + config, + auth, + info + } = context; + const { + sessionToken + } = await objectsMutations.createObject('_User', _objectSpread({}, fields, { + authData + }), config, auth, info); + info.sessionToken = sessionToken; + return { + viewer: await (0, _usersQueries.getUserFromSessionToken)(config, info, mutationInfo, 'viewer.user.', true) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(logInWithMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(logInWithMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('logInWith', logInWithMutation, true, true); + const logInMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'LogIn', + description: 'The logIn mutation can be used to log in an existing user.', + inputFields: { + username: { + description: 'This is the username used to log in the user.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + }, + password: { + description: 'This is the password used to log in the user.', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + } + }, + outputFields: { + viewer: { + description: 'This is the existing user that was logged in and returned as a viewer.', + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType) + } + }, + mutateAndGetPayload: async (args, context, mutationInfo) => { + try { + const { + username, + password + } = args; + const { + config, + auth, + info + } = context; + const { + sessionToken + } = (await usersRouter.handleLogIn({ + body: { + username, + password + }, + query: {}, + config, + auth, + info + })).response; + info.sessionToken = sessionToken; + return { + viewer: await (0, _usersQueries.getUserFromSessionToken)(config, info, mutationInfo, 'viewer.user.', true) + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(logInMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(logInMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('logIn', logInMutation, true, true); + const logOutMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'LogOut', + description: 'The logOut mutation can be used to log out an existing user.', + outputFields: { + viewer: { + description: 'This is the existing user that was logged out and returned as a viewer.', + type: new _graphql.GraphQLNonNull(parseGraphQLSchema.viewerType) + } + }, + mutateAndGetPayload: async (_args, context, mutationInfo) => { + try { + const { + config, + auth, + info + } = context; + const viewer = await (0, _usersQueries.getUserFromSessionToken)(config, info, mutationInfo, 'viewer.user.', true); + await usersRouter.handleLogOut({ + config, + auth, + info + }); + return { + viewer + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(logOutMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(logOutMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('logOut', logOutMutation, true, true); + const resetPasswordMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'ResetPassword', + description: 'The resetPassword mutation can be used to reset the password of an existing user.', + inputFields: { + email: { + descriptions: 'Email of the user that should receive the reset email', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + } + }, + outputFields: { + ok: { + description: "It's always true.", + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + } + }, + mutateAndGetPayload: async ({ + email + }, context) => { + const { + config, + auth, + info + } = context; + await usersRouter.handleResetRequest({ + body: { + email + }, + config, + auth, + info + }); + return { + ok: true + }; + } + }); + parseGraphQLSchema.addGraphQLType(resetPasswordMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(resetPasswordMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('resetPassword', resetPasswordMutation, true, true); + const sendVerificationEmailMutation = (0, _graphqlRelay.mutationWithClientMutationId)({ + name: 'SendVerificationEmail', + description: 'The sendVerificationEmail mutation can be used to send the verification email again.', + inputFields: { + email: { + descriptions: 'Email of the user that should receive the verification email', + type: new _graphql.GraphQLNonNull(_graphql.GraphQLString) + } + }, + outputFields: { + ok: { + description: "It's always true.", + type: new _graphql.GraphQLNonNull(_graphql.GraphQLBoolean) + } + }, + mutateAndGetPayload: async ({ + email + }, context) => { + try { + const { + config, + auth, + info + } = context; + await usersRouter.handleVerificationEmailRequest({ + body: { + email + }, + config, + auth, + info + }); + return { + ok: true + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + }); + parseGraphQLSchema.addGraphQLType(sendVerificationEmailMutation.args.input.type.ofType, true, true); + parseGraphQLSchema.addGraphQLType(sendVerificationEmailMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation('sendVerificationEmail', sendVerificationEmailMutation, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvdXNlcnNNdXRhdGlvbnMuanMiXSwibmFtZXMiOlsidXNlcnNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsImxvYWQiLCJwYXJzZUdyYXBoUUxTY2hlbWEiLCJpc1VzZXJzQ2xhc3NEaXNhYmxlZCIsInNpZ25VcE11dGF0aW9uIiwibmFtZSIsImRlc2NyaXB0aW9uIiwiaW5wdXRGaWVsZHMiLCJmaWVsZHMiLCJkZXNjcmlwdGlvbnMiLCJ0eXBlIiwicGFyc2VDbGFzc1R5cGVzIiwiY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZSIsIm91dHB1dEZpZWxkcyIsInZpZXdlciIsIkdyYXBoUUxOb25OdWxsIiwidmlld2VyVHlwZSIsIm11dGF0ZUFuZEdldFBheWxvYWQiLCJhcmdzIiwiY29udGV4dCIsIm11dGF0aW9uSW5mbyIsImNvbmZpZyIsImF1dGgiLCJpbmZvIiwic2Vzc2lvblRva2VuIiwib2JqZWN0c011dGF0aW9ucyIsImNyZWF0ZU9iamVjdCIsImUiLCJoYW5kbGVFcnJvciIsImFkZEdyYXBoUUxUeXBlIiwiaW5wdXQiLCJvZlR5cGUiLCJhZGRHcmFwaFFMTXV0YXRpb24iLCJsb2dJbldpdGhNdXRhdGlvbiIsImF1dGhEYXRhIiwiT0JKRUNUIiwiR3JhcGhRTElucHV0T2JqZWN0VHlwZSIsImNsYXNzR3JhcGhRTENyZWF0ZUZpZWxkcyIsImdldEZpZWxkcyIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJmaWVsZE5hbWUiLCJsb2dJbk11dGF0aW9uIiwidXNlcm5hbWUiLCJHcmFwaFFMU3RyaW5nIiwicGFzc3dvcmQiLCJoYW5kbGVMb2dJbiIsImJvZHkiLCJxdWVyeSIsInJlc3BvbnNlIiwibG9nT3V0TXV0YXRpb24iLCJfYXJncyIsImhhbmRsZUxvZ091dCIsInJlc2V0UGFzc3dvcmRNdXRhdGlvbiIsImVtYWlsIiwib2siLCJHcmFwaFFMQm9vbGVhbiIsImhhbmRsZVJlc2V0UmVxdWVzdCIsInNlbmRWZXJp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WG1EO0FBaUJqRXhDLElBQUFBLG1CQUFtQixFQUFFLE9BQU87QUFBRXNDLE1BQUFBO0FBQUYsS0FBUCxFQUFrQnBDLE9BQWxCLEtBQThCO0FBQ2pELFVBQUk7QUFDRixjQUFNO0FBQUVFLFVBQUFBLE1BQUY7QUFBVUMsVUFBQUEsSUFBVjtBQUFnQkMsVUFBQUE7QUFBaEIsWUFBeUJKLE9BQS9CO0FBRUEsY0FBTXBCLFdBQVcsQ0FBQzZELDhCQUFaLENBQTJDO0FBQy9DWixVQUFBQSxJQUFJLEVBQUU7QUFDSk8sWUFBQUE7QUFESSxXQUR5QztBQUkvQ2xDLFVBQUFBLE1BSitDO0FBSy9DQyxVQUFBQSxJQUwrQztBQU0vQ0MsVUFBQUE7QUFOK0MsU0FBM0MsQ0FBTjtBQVNBLGVBQU87QUFBRWlDLFVBQUFBLEVBQUUsRUFBRTtBQUFOLFNBQVA7QUFDRCxPQWJELENBYUUsT0FBTzdCLENBQVAsRUFBVTtBQUNWekIsUUFBQUEsa0JBQWtCLENBQUMwQixXQUFuQixDQUErQkQsQ0FBL0I7QUFDRDtBQUNGO0FBbENnRSxHQUE3QixDQUF0QztBQXFDQXpCLEVBQUFBLGtCQUFrQixDQUFDMkIsY0FBbkIsQ0FDRThCLDZCQUE2QixDQUFDekMsSUFBOUIsQ0FBbUNZLEtBQW5DLENBQXlDcEIsSUFBekMsQ0FBOENxQixNQURoRCxFQUVFLElBRkYsRUFHRSxJQUhGO0FBS0E3QixFQUFBQSxrQkFBa0IsQ0FBQzJCLGNBQW5CLENBQ0U4Qiw2QkFBNkIsQ0FBQ2pELElBRGhDLEVBRUUsSUFGRixFQUdFLElBSEY7QUFLQVIsRUFBQUEsa0JBQWtCLENBQUM4QixrQkFBbkIsQ0FDRSx1QkFERixFQUVFMkIsNkJBRkYsRUFHRSxJQUhGLEVBSUUsSUFKRjtBQU1ELENBOVZEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgR3JhcGhRTE5vbk51bGwsXG4gIEdyYXBoUUxTdHJpbmcsXG4gIEdyYXBoUUxCb29sZWFuLFxuICBHcmFwaFFMSW5wdXRPYmplY3RUeXBlLFxufSBmcm9tICdncmFwaHFsJztcbmltcG9ydCB7IG11dGF0aW9uV2l0aENsaWVudE11dGF0aW9uSWQgfSBmcm9tICdncmFwaHFsLXJlbGF5JztcbmltcG9ydCBVc2Vyc1JvdXRlciBmcm9tICcuLi8uLi9Sb3V0ZXJzL1VzZXJzUm91dGVyJztcbmltcG9ydCAqIGFzIG9iamVjdHNNdXRhdGlvbnMgZnJvbSAnLi4vaGVscGVycy9vYmplY3RzTXV0YXRpb25zJztcbmltcG9ydCB7IE9CSkVDVCB9IGZyb20gJy4vZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5pbXBvcnQgeyBnZXRVc2VyRnJvbVNlc3Npb25Ub2tlbiB9IGZyb20gJy4vdXNlcnNRdWVyaWVzJztcblxuY29uc3QgdXNlcnNSb3V0ZXIgPSBuZXcgVXNlcnNSb3V0ZXIoKTtcblxuY29uc3QgbG9hZCA9IHBhcnNlR3JhcGhRTFNjaGVtYSA9PiB7XG4gIGlmIChwYXJzZUdyYXBoUUxTY2hlbWEuaXNVc2Vyc0NsYXNzRGlzYWJsZWQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBzaWduVXBNdXRhdGlvbiA9IG11dGF0aW9uV2l0aENsaWVudE11dGF0aW9uSWQoe1xuICAgIG5hbWU6ICdTaWduVXAnLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1RoZSBzaWduVXAgbXV0YXRpb24gY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGFuZCBzaWduIHVwIGEgbmV3IHVzZXIuJyxcbiAgICBpbnB1dEZpZWxkczoge1xuICAgICAgZmllbGRzOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uczpcbiAgICAgICAgICAnVGhlc2UgYXJlIHRoZSBmaWVsZHMgb2YgdGhlIG5ldyB1c2VyIHRvIGJlIGNyZWF0ZWQgYW5kIHNpZ25lZCB1cC4nLFxuICAgICAgICB0eXBlOlxuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5wYXJzZUNsYXNzVHlwZXNbJ19Vc2VyJ10uY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBvdXRwdXRGaWVsZHM6IHtcbiAgICAgIHZpZXdlcjoge1xuICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAnVGhpcyBpcyB0aGUgbmV3IHVzZXIgdGhhdCB3YXMgY3JlYXRlZCwgc2lnbmVkIHVwIGFuZCByZXR1cm5lZCBhcyBhIHZpZXdlci4nLFxuICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwocGFyc2VHcmFwaFFMU2NoZW1hLnZpZXdlclR5cGUpLFxuICAgICAgfSxcbiAgICB9LFxuICAgIG11dGF0ZUFuZEdldFBheWxvYWQ6IGFzeW5jIChhcmdzLCBjb250ZXh0LCBtdXRhdGlvbkluZm8pID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHsgZmllbGRzIH0gPSBhcmdzO1xuICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcblxuICAgICAgICBjb25zdCB7IHNlc3Npb25Ub2tlbiB9ID0gYXdhaXQgb2JqZWN0c011dGF0aW9ucy5jcmVhdGVPYmplY3QoXG4gICAgICAgICAgJ19Vc2VyJyxcbiAgICAgICAgICBmaWVsZHMsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgaW5mb1xuICAgICAgICApO1xuXG4gICAgICAgIGluZm8uc2Vzc2lvblRva2VuID0gc2Vzc2lvblRva2VuO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmlld2VyOiBhd2FpdCBnZXRVc2VyRnJvbVNlc3Npb25Ub2tlbihcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGluZm8sXG4gICAgICAgICAgICBtdXRhdGlvbkluZm8sXG4gICAgICAgICAgICAndmlld2VyLnVzZXIuJyxcbiAgICAgICAgICAgIHRydWVcbiAgICAgICAgICApLFxuICAgICAgICB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIHNpZ25VcE11dGF0aW9uLmFyZ3MuaW5wdXQudHlwZS5vZlR5cGUsXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShzaWduVXBNdXRhdGlvbi50eXBlLCB0cnVlLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxNdXRhdGlvbignc2lnblVwJywgc2lnblVwTXV0YXRpb24sIHRydWUsIHRydWUpO1xuICBjb25zdCBsb2dJbldpdGhNdXRhdGlvbiA9IG11dGF0aW9uV2l0aENsaWVudE11dGF0aW9uSWQoe1xuICAgIG5hbWU6ICdMb2dJbldpdGgnLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1RoZSBsb2dJbldpdGggbXV0YXRpb24gY2FuIGJlIHVzZWQgdG8gc2lnbnVwLCBsb2dpbiB1c2VyIHdpdGggM3JkIHBhcnR5IGF1dGhlbnRpY2F0aW9uIHN5c3RlbS4gVGhpcyBtdXRhdGlvbiBjcmVhdGUgYSB1c2VyIGlmIHRoZSBhdXRoRGF0YSBkbyBub3QgY29ycmVzcG9uZCB0byBhbiBleGlzdGluZyBvbmUuJyxcbiAgICBpbnB1dEZpZWxkczoge1xuICAgICAgYXV0aERhdGE6IHtcbiAgICAgICAgZGVzY3JpcHRpb25zOiAnVGhpcyBpcyB0aGUgYXV0aCBkYXRhIG9mIHlvdXIgY3VzdG9tIGF1dGggcHJvdmlkZXInLFxuICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoT0JKRUNUKSxcbiAgICAgIH0sXG4gICAgICBmaWVsZHM6IHtcbiAgICAgICAgZGVzY3JpcHRpb25zOlxuICAgICAgICAgICdUaGVzZSBhcmUgdGhlIGZpZWxkcyBvZiB0aGUgdXNlciB0byBiZSBjcmVhdGVkL3VwZGF0ZWQgYW5kIGxvZ2dlZCBpbi4nLFxuICAgICAgICB0eXBlOiBuZXcgR3JhcGhRTElucHV0T2JqZWN0VHlwZSh7XG4gICAgICAgICAgbmFtZTogJ1VzZXJMb2dpbldpdGhJbnB1dCcsXG4gICAgICAgICAgZmllbGRzOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc0dyYXBoUUxDcmVhdGVGaWVsZHMgPSBwYXJzZUdyYXBoUUxTY2hlbWEucGFyc2VDbGFzc1R5cGVzW1xuICAgICAgICAgICAgICAnX1VzZXInXG4gICAgICAgICAgICBdLmNsYXNzR3JhcGhRTENyZWF0ZVR5cGUuZ2V0RmllbGRzKCk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoY2xhc3NHcmFwaFFMQ3JlYXRlRmllbGRzKS5yZWR1Y2UoXG4gICAgICAgICAgICAgIChmaWVsZHMsIGZpZWxkTmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgIGZpZWxkTmFtZSAhPT0gJ3Bhc3N3b3JkJyAmJlxuICAgICAgICAgICAgICAgICAgZmllbGROYW1lICE9PSAndXNlcm5hbWUnICYmXG4gICAgICAgICAgICAgICAgICBmaWVsZE5hbWUgIT09ICdhdXRoRGF0YSdcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIGZpZWxkc1tmaWVsZE5hbWVdID0gY2xhc3NHcmFwaFFMQ3JlYXRlRmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBmaWVsZHM7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHt9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9LFxuICAgIG91dHB1dEZpZWxkczoge1xuICAgICAgdmlld2VyOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICdUaGlzIGlzIHRoZSBuZXcgdXNlciB0aGF0IHdhcyBjcmVhdGVkLCBzaWduZWQgdXAgYW5kIHJldHVybmVkIGFzIGEgdmlld2VyLicsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChwYXJzZUdyYXBoUUxTY2hlbWEudmlld2VyVHlwZSksXG4gICAgICB9LFxuICAgIH0sXG4gICAgbXV0YXRlQW5kR2V0UGF5bG9hZDogYXN5bmMgKGFyZ3MsIGNvbnRleHQsIG11dGF0aW9uSW5mbykgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyBmaWVsZHMsIGF1dGhEYXRhIH0gPSBhcmdzO1xuICAgICAgICBjb25zdCB7IGNvbmZpZywgYXV0aCwgaW5mbyB9ID0gY29udGV4dDtcblxuICAgICAgICBjb25zdCB7IHNlc3Npb25Ub2tlbiB9ID0gYXdhaXQgb2JqZWN0c011dGF0aW9ucy5jcmVhdGVPYmplY3QoXG4gICAgICAgICAgJ19Vc2VyJyxcbiAgICAgICAgICB7IC4uLmZpZWxkcywgYXV0aERhdGEgfSxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICBpbmZvXG4gICAgICAgICk7XG5cbiAgICAgICAgaW5mby5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uVG9rZW47XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2aWV3ZXI6IGF3YWl0IGdldFVzZXJGcm9tU2Vzc2lvblRva2VuKFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgaW5mbyxcbiAgICAgICAgICAgIG11dGF0aW9uSW5mbyxcbiAgICAgICAgICAgICd2aWV3ZXIudXNlci4nLFxuICAgICAgICAgICAgdHJ1ZVxuICAgICAgICAgICksXG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgbG9nSW5XaXRoTXV0YXRpb24uYXJncy5pbnB1dC50eXBlLm9mVHlwZSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKGxvZ0luV2l0aE11dGF0aW9uLnR5cGUsIHRydWUsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTE11dGF0aW9uKFxuICAgICdsb2dJbldpdGgnLFxuICAgIGxvZ0luV2l0aE11dGF0aW9uLFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xuXG4gIGNvbnN0IGxvZ0luTXV0YXRpb24gPSBtdXRhdGlvbldpdGhDbGllbnRNdXRhdGlvbklkKHtcbiAgICBuYW1lOiAnTG9nSW4nLFxuICAgIGRlc2NyaXB0aW9uOiAnVGhlIGxvZ0luIG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIGxvZyBpbiBhbiBleGlzdGluZyB1c2VyLicsXG4gICAgaW5wdXRGaWVsZHM6IHtcbiAgICAgIHVzZXJuYW1lOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgdXNlcm5hbWUgdXNlZCB0byBsb2cgaW4gdGhlIHVzZXIuJyxcbiAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgICAgfSxcbiAgICAgIHBhc3N3b3JkOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyB0aGUgcGFzc3dvcmQgdXNlZCB0byBsb2cgaW4gdGhlIHVzZXIuJyxcbiAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpLFxuICAgICAgfSxcbiAgICB9LFxuICAgIG91dHB1dEZpZWxkczoge1xuICAgICAgdmlld2VyOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICdUaGlzIGlzIHRoZSBleGlzdGluZyB1c2VyIHRoYXQgd2FzIGxvZ2dlZCBpbiBhbmQgcmV0dXJuZWQgYXMgYSB2aWV3ZXIuJyxcbiAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKHBhcnNlR3JhcGhRTFNjaGVtYS52aWV3ZXJUeXBlKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBtdXRhdGVBbmRHZXRQYXlsb2FkOiBhc3luYyAoYXJncywgY29udGV4dCwgbXV0YXRpb25JbmZvKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB7IHVzZXJuYW1lLCBwYXNzd29yZCB9ID0gYXJncztcbiAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgY29uc3QgeyBzZXNzaW9uVG9rZW4gfSA9IChcbiAgICAgICAgICBhd2FpdCB1c2Vyc1JvdXRlci5oYW5kbGVMb2dJbih7XG4gICAgICAgICAgICBib2R5OiB7XG4gICAgICAgICAgICAgIHVzZXJuYW1lLFxuICAgICAgICAgICAgICBwYXNzd29yZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBxdWVyeToge30sXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgaW5mbyxcbiAgICAgICAgICB9KVxuICAgICAgICApLnJlc3BvbnNlO1xuXG4gICAgICAgIGluZm8uc2Vzc2lvblRva2VuID0gc2Vzc2lvblRva2VuO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmlld2VyOiBhd2FpdCBnZXRVc2VyRnJvbVNlc3Npb25Ub2tlbihcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGluZm8sXG4gICAgICAgICAgICBtdXRhdGlvbkluZm8sXG4gICAgICAgICAgICAndmlld2VyLnVzZXIuJyxcbiAgICAgICAgICAgIHRydWVcbiAgICAgICAgICApLFxuICAgICAgICB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIGxvZ0luTXV0YXRpb24uYXJncy5pbnB1dC50eXBlLm9mVHlwZSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKGxvZ0luTXV0YXRpb24udHlwZSwgdHJ1ZSwgdHJ1ZSk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oJ2xvZ0luJywgbG9nSW5NdXRhdGlvbiwgdHJ1ZSwgdHJ1ZSk7XG5cbiAgY29uc3QgbG9nT3V0TXV0YXRpb24gPSBtdXRhdGlvbldpdGhDbGllbnRNdXRhdGlvbklkKHtcbiAgICBuYW1lOiAnTG9nT3V0JyxcbiAgICBkZXNjcmlwdGlvbjogJ1RoZSBsb2dPdXQgbXV0YXRpb24gY2FuIGJlIHVzZWQgdG8gbG9nIG91dCBhbiBleGlzdGluZyB1c2VyLicsXG4gICAgb3V0cHV0RmllbGRzOiB7XG4gICAgICB2aWV3ZXI6IHtcbiAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgJ1RoaXMgaXMgdGhlIGV4aXN0aW5nIHVzZXIgdGhhdCB3YXMgbG9nZ2VkIG91dCBhbmQgcmV0dXJuZWQgYXMgYSB2aWV3ZXIuJyxcbiAgICAgICAgdHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKHBhcnNlR3JhcGhRTFNjaGVtYS52aWV3ZXJUeXBlKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBtdXRhdGVBbmRHZXRQYXlsb2FkOiBhc3luYyAoX2FyZ3MsIGNvbnRleHQsIG11dGF0aW9uSW5mbykgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgY29uc3Qgdmlld2VyID0gYXdhaXQgZ2V0VXNlckZyb21TZXNzaW9uVG9rZW4oXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGluZm8sXG4gICAgICAgICAgbXV0YXRpb25JbmZvLFxuICAgICAgICAgICd2aWV3ZXIudXNlci4nLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcblxuICAgICAgICBhd2FpdCB1c2Vyc1JvdXRlci5oYW5kbGVMb2dPdXQoe1xuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIGluZm8sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB7IHZpZXdlciB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEuaGFuZGxlRXJyb3IoZSk7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIGxvZ091dE11dGF0aW9uLmFyZ3MuaW5wdXQudHlwZS5vZlR5cGUsXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMVHlwZShsb2dPdXRNdXRhdGlvbi50eXBlLCB0cnVlLCB0cnVlKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxNdXRhdGlvbignbG9nT3V0JywgbG9nT3V0TXV0YXRpb24sIHRydWUsIHRydWUpO1xuXG4gIGNvbnN0IHJlc2V0UGFzc3dvcmRNdXRhdGlvbiA9IG11dGF0aW9uV2l0aENsaWVudE11dGF0aW9uSWQoe1xuICAgIG5hbWU6ICdSZXNldFBhc3N3b3JkJyxcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdUaGUgcmVzZXRQYXNzd29yZCBtdXRhdGlvbiBjYW4gYmUgdXNlZCB0byByZXNldCB0aGUgcGFzc3dvcmQgb2YgYW4gZXhpc3RpbmcgdXNlci4nLFxuICAgIGlucHV0RmllbGRzOiB7XG4gICAgICBlbWFpbDoge1xuICAgICAgICBkZXNjcmlwdGlvbnM6ICdFbWFpbCBvZiB0aGUgdXNlciB0aGF0IHNob3VsZCByZWNlaXZlIHRoZSByZXNldCBlbWFpbCcsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMU3RyaW5nKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBvdXRwdXRGaWVsZHM6IHtcbiAgICAgIG9rOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIkl0J3MgYWx3YXlzIHRydWUuXCIsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbiksXG4gICAgICB9LFxuICAgIH0sXG4gICAgbXV0YXRlQW5kR2V0UGF5bG9hZDogYXN5bmMgKHsgZW1haWwgfSwgY29udGV4dCkgPT4ge1xuICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgIGF3YWl0IHVzZXJzUm91dGVyLmhhbmRsZVJlc2V0UmVxdWVzdCh7XG4gICAgICAgIGJvZHk6IHtcbiAgICAgICAgICBlbWFpbCxcbiAgICAgICAgfSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBhdXRoLFxuICAgICAgICBpbmZvLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7IG9rOiB0cnVlIH07XG4gICAgfSxcbiAgfSk7XG5cbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIHJlc2V0UGFzc3dvcmRNdXRhdGlvbi5hcmdzLmlucHV0LnR5cGUub2ZUeXBlLFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUocmVzZXRQYXNzd29yZE11dGF0aW9uLnR5cGUsIHRydWUsIHRydWUpO1xuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTE11dGF0aW9uKFxuICAgICdyZXNldFBhc3N3b3JkJyxcbiAgICByZXNldFBhc3N3b3JkTXV0YXRpb24sXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG5cbiAgY29uc3Qgc2VuZFZlcmlmaWNhdGlvbkVtYWlsTXV0YXRpb24gPSBtdXRhdGlvbldpdGhDbGllbnRNdXRhdGlvbklkKHtcbiAgICBuYW1lOiAnU2VuZFZlcmlmaWNhdGlvbkVtYWlsJyxcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdUaGUgc2VuZFZlcmlmaWNhdGlvbkVtYWlsIG11dGF0aW9uIGNhbiBiZSB1c2VkIHRvIHNlbmQgdGhlIHZlcmlmaWNhdGlvbiBlbWFpbCBhZ2Fpbi4nLFxuICAgIGlucHV0RmllbGRzOiB7XG4gICAgICBlbWFpbDoge1xuICAgICAgICBkZXNjcmlwdGlvbnM6XG4gICAgICAgICAgJ0VtYWlsIG9mIHRoZSB1c2VyIHRoYXQgc2hvdWxkIHJlY2VpdmUgdGhlIHZlcmlmaWNhdGlvbiBlbWFpbCcsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMU3RyaW5nKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBvdXRwdXRGaWVsZHM6IHtcbiAgICAgIG9rOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIkl0J3MgYWx3YXlzIHRydWUuXCIsXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbiksXG4gICAgICB9LFxuICAgIH0sXG4gICAgbXV0YXRlQW5kR2V0UGF5bG9hZDogYXN5bmMgKHsgZW1haWwgfSwgY29udGV4dCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyBjb25maWcsIGF1dGgsIGluZm8gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgYXdhaXQgdXNlcnNSb3V0ZXIuaGFuZGxlVmVyaWZpY2F0aW9uRW1haWxSZXF1ZXN0KHtcbiAgICAgICAgICBib2R5OiB7XG4gICAgICAgICAgICBlbWFpbCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIGluZm8sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB7IG9rOiB0cnVlIH07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcblxuICBwYXJzZUdyYXBoUUxTY2hlbWEuYWRkR3JhcGhRTFR5cGUoXG4gICAgc2VuZFZlcmlmaWNhdGlvbkVtYWlsTXV0YXRpb24uYXJncy5pbnB1dC50eXBlLm9mVHlwZSxcbiAgICB0cnVlLFxuICAgIHRydWVcbiAgKTtcbiAgcGFyc2VHcmFwaFFMU2NoZW1hLmFkZEdyYXBoUUxUeXBlKFxuICAgIHNlbmRWZXJpZmljYXRpb25FbWFpbE11dGF0aW9uLnR5cGUsXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMTXV0YXRpb24oXG4gICAgJ3NlbmRWZXJpZmljYXRpb25FbWFpbCcsXG4gICAgc2VuZFZlcmlmaWNhdGlvbkVtYWlsTXV0YXRpb24sXG4gICAgdHJ1ZSxcbiAgICB0cnVlXG4gICk7XG59O1xuXG5leHBvcnQgeyBsb2FkIH07XG4iXX0= \ 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..41ee98cac5 --- /dev/null +++ b/lib/GraphQL/loaders/usersQueries.js @@ -0,0 +1,97 @@ +"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, keysPrefix, validatedToken) => { + 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).filter(field => field.startsWith(keysPrefix)).map(field => field.replace(keysPrefix, '')); + const keysAndInclude = (0, _parseClassTypes.extractKeysAndInclude)(selectedFields); + const { + keys + } = keysAndInclude; + let { + include + } = keysAndInclude; + + if (validatedToken && !keys && !include) { + return { + sessionToken + }; + } else if (keys && !include) { + include = 'user'; + } + + const options = {}; + + if (keys) { + options.keys = keys.split(',').map(key => `user.${key}`).join(','); + } + + if (include) { + options.include = include.split(',').map(included => `user.${included}`).join(','); + } + + const response = await _rest.default.find(config, _Auth.default.master(config), '_Session', { + sessionToken + }, options, 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; + return { + sessionToken, + 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, 'user.', false); + } catch (e) { + parseGraphQLSchema.handleError(e); + } + } + + }, true, true); +}; + +exports.load = load; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML2xvYWRlcnMvdXNlcnNRdWVyaWVzLmpzIl0sIm5hbWVzIjpbImdldFVzZXJGcm9tU2Vzc2lvblRva2VuIiwiY29uZmlnIiwiaW5mbyIsInF1ZXJ5SW5mbyIsImtleXNQcmVmaXgiLCJ2YWxpZGF0ZWRUb2tlbiIsInNlc3Npb25Ub2tlbiIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJzZWxlY3RlZEZpZWxkcyIsImZpbHRlciIsImZpZWxkIiwic3RhcnRzV2l0aCIsIm1hcCIsInJlcGxhY2UiLCJrZXlzQW5kSW5jbHVkZSIsImtleXMiLCJpbmNsdWRlIiwib3B0aW9ucyIsInNwbGl0Iiwia2V5Iiwiam9pbiIsImluY2x1ZGVkIiwicmVzcG9uc2UiLCJyZXN0IiwiZmluZCIsIkF1dGgiLCJtYXN0ZXIiLCJjbGllbnRWZXJzaW9uIiwicmVzdWx0cyIsImxlbmd0aCIsInVzZXIiLCJsb2FkIiwicGFyc2VHcmFwaFFMU2NoZW1hIiwiaXNVc2Vyc0NsYXNzRGlzYWJsZWQiLCJhZGRHcmFwaFFMUXVlcnkiLCJkZXNjcmlwdGlvbiIsInR5cGUiLCJHcmFwaFFMTm9uTnVsbCIsInZpZXdlclR5cGUiLCJyZXNvbHZlIiwiX3NvdXJjZSIsIl9hcmdzIiwiY29udGV4dCIsImUiLCJoYW5kbGVFcnJvciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEsdUJBQXVCLEdBQUcsT0FDOUJDLE1BRDhCLEVBRTlCQyxJQUY4QixFQUc5QkMsU0FIOEIsRUFJOUJDLFVBSjhCLEVBSzlCQyxjQUw4QixLQU0zQjtBQUNILE1BQUksQ0FBQ0gsSUFBRCxJQUFTLENBQUNBLElBQUksQ0FBQ0ksWUFBbkIsRUFBaUM7QUFDL0IsVUFBTSxJQUFJQyxjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUMscUJBRFIsRUFFSix1QkFGSSxDQUFOO0FB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Q0MsSUFGa0MsRUFHbENDLFNBSGtDLEVBSWxDLE9BSmtDLEVBS2xDLEtBTGtDLENBQXBDO0FBT0QsT0FURCxDQVNFLE9BQU8wQyxDQUFQLEVBQVU7QUFDVlgsUUFBQUEsa0JBQWtCLENBQUNZLFdBQW5CLENBQStCRCxDQUEvQjtBQUNEO0FBQ0Y7O0FBakJILEdBRkYsRUFxQkUsSUFyQkYsRUFzQkUsSUF0QkY7QUF3QkQsQ0E3QkQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBHcmFwaFFMTm9uTnVsbCB9IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0IGdldEZpZWxkTmFtZXMgZnJvbSAnZ3JhcGhxbC1saXN0LWZpZWxkcyc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi8uLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4uLy4uL0F1dGgnO1xuaW1wb3J0IHsgZXh0cmFjdEtleXNBbmRJbmNsdWRlIH0gZnJvbSAnLi9wYXJzZUNsYXNzVHlwZXMnO1xuXG5jb25zdCBnZXRVc2VyRnJvbVNlc3Npb25Ub2tlbiA9IGFzeW5jIChcbiAgY29uZmlnLFxuICBpbmZvLFxuICBxdWVyeUluZm8sXG4gIGtleXNQcmVmaXgsXG4gIHZhbGlkYXRlZFRva2VuXG4pID0+IHtcbiAgaWYgKCFpbmZvIHx8ICFpbmZvLnNlc3Npb25Ub2tlbikge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICdJbnZhbGlkIHNlc3Npb24gdG9rZW4nXG4gICAgKTtcbiAgfVxuICBjb25zdCBzZXNzaW9uVG9rZW4gPSBpbmZvLnNlc3Npb25Ub2tlbjtcbiAgY29uc3Qgc2VsZWN0ZWRGaWVsZHMgPSBnZXRGaWVsZE5hbWVzKHF1ZXJ5SW5mbylcbiAgICAuZmlsdGVyKGZpZWxkID0+IGZpZWxkLnN0YXJ0c1dpdGgoa2V5c1ByZWZpeCkpXG4gICAgLm1hcChmaWVsZCA9PiBmaWVsZC5yZXBsYWNlKGtleXNQcmVmaXgsICcnKSk7XG5cbiAgY29uc3Qga2V5c0FuZEluY2x1ZGUgPSBleHRyYWN0S2V5c0FuZEluY2x1ZGUoc2VsZWN0ZWRGaWVsZHMpO1xuICBjb25zdCB7IGtleXMgfSA9IGtleXNBbmRJbmNsdWRlO1xuICBsZXQgeyBpbmNsdWRlIH0gPSBrZXlzQW5kSW5jbHVkZTtcblxuICBpZiAodmFsaWRhdGVkVG9rZW4gJiYgIWtleXMgJiYgIWluY2x1ZGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc2Vzc2lvblRva2VuLFxuICAgIH07XG4gIH0gZWxzZSBpZiAoa2V5cyAmJiAhaW5jbHVkZSkge1xuICAgIGluY2x1ZGUgPSAndXNlcic7XG4gIH1cblxuICBjb25zdCBvcHRpb25zID0ge307XG4gIGlmIChrZXlzKSB7XG4gICAgb3B0aW9ucy5rZXlzID0ga2V5c1xuICAgICAgLnNwbGl0KCcsJylcbiAgICAgIC5tYXAoa2V5ID0+IGB1c2VyLiR7a2V5fWApXG4gICAgICAuam9pbignLCcpO1xuICB9XG4gIGlmIChpbmNsdWRlKSB7XG4gICAgb3B0aW9ucy5pbmNsdWRlID0gaW5jbHVkZVxuICAgICAgLnNwbGl0KCcsJylcbiAgICAgIC5tYXAoaW5jbHVkZWQgPT4gYHVzZXIuJHtpbmNsdWRlZH1gKVxuICAgICAgLmpvaW4oJywnKTtcbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVzdC5maW5kKFxuICAgIGNvbmZpZyxcbiAgICBBdXRoLm1hc3Rlcihjb25maWcpLFxuICAgICdfU2Vzc2lvbicsXG4gICAgeyBzZXNzaW9uVG9rZW4gfSxcbiAgICBvcHRpb25zLFxuICAgIGluZm8uY2xpZW50VmVyc2lvblxuICApO1xuICBpZiAoXG4gICAgIXJlc3BvbnNlLnJlc3VsdHMgfHxcbiAgICByZXNwb25zZS5yZXN1bHRzLmxlbmd0aCA9PSAwIHx8XG4gICAgIXJlc3BvbnNlLnJlc3VsdHNbMF0udXNlclxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1NFU1NJT05fVE9LRU4sXG4gICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgdXNlciA9IHJlc3BvbnNlLnJlc3VsdHNbMF0udXNlcjtcbiAgICByZXR1cm4ge1xuICAgICAgc2Vzc2lvblRva2VuLFxuICAgICAgdXNlcixcbiAgICB9O1xuICB9XG59O1xuXG5jb25zdCBsb2FkID0gcGFyc2VHcmFwaFFMU2NoZW1hID0+IHtcbiAgaWYgKHBhcnNlR3JhcGhRTFNjaGVtYS5pc1VzZXJzQ2xhc3NEaXNhYmxlZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHBhcnNlR3JhcGhRTFNjaGVtYS5hZGRHcmFwaFFMUXVlcnkoXG4gICAgJ3ZpZXdlcicsXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICdUaGUgdmlld2VyIHF1ZXJ5IGNhbiBiZSB1c2VkIHRvIHJldHVybiB0aGUgY3VycmVudCB1c2VyIGRhdGEuJyxcbiAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChwYXJzZUdyYXBoUUxTY2hlbWEudmlld2VyVHlwZSksXG4gICAgICBhc3luYyByZXNvbHZlKF9zb3VyY2UsIF9hcmdzLCBjb250ZXh0LCBxdWVyeUluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGNvbmZpZywgaW5mbyB9ID0gY29udGV4dDtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgZ2V0VXNlckZyb21TZXNzaW9uVG9rZW4oXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBpbmZvLFxuICAgICAgICAgICAgcXVlcnlJbmZvLFxuICAgICAgICAgICAgJ3VzZXIuJyxcbiAgICAgICAgICAgIGZhbHNlXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYS5oYW5kbGVFcnJvcihlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9LFxuICAgIHRydWUsXG4gICAgdHJ1ZVxuICApO1xufTtcblxuZXhwb3J0IHsgbG9hZCwgZ2V0VXNlckZyb21TZXNzaW9uVG9rZW4gfTtcbiJdfQ== \ 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..8303be5643 --- /dev/null +++ b/lib/GraphQL/transformers/constraintType.js @@ -0,0 +1,73 @@ +"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, fieldName) => { + if (fieldName === 'id' || fieldName === 'objectId') { + return defaultGraphQLTypes.ID_WHERE_INPUT; + } + + 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].classGraphQLRelationConstraintsType) { + return parseClassTypes[targetClass].classGraphQLRelationConstraintsType; + } 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': + if (parseClassTypes[targetClass] && parseClassTypes[targetClass].classGraphQLRelationConstraintsType) { + return parseClassTypes[targetClass].classGraphQLRelationConstraintsType; + } else { + return defaultGraphQLTypes.OBJECT; + } + + default: + return undefined; + } +}; + +exports.transformConstraintTypeToGraphQL = transformConstraintTypeToGraphQL; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9jb25zdHJhaW50VHlwZS5qcyJdLCJuYW1lcyI6WyJ0cmFuc2Zvcm1Db25zdHJhaW50VHlwZVRvR3JhcGhRTCIsInBhcnNlVHlwZSIsInRhcmdldENsYXNzIiwicGFyc2VDbGFzc1R5cGVzIiwiZmllbGROYW1lIiwiZGVmYXVsdEdyYXBoUUxUeXBlcyIsIklEX1dIRVJFX0lOUFVUIiwiU1RSSU5HX1dIRVJFX0lOUFVUIiwiTlVNQkVSX1dIRVJFX0lOUFVUIiwiQk9PTEVBTl9XSEVSRV9JTlBVVCIsIkFSUkFZX1dIRVJFX0lOUFVUIiwiT0JKRUNUX1dIRVJFX0lOUFVUIiwiREFURV9XSEVSRV9JTlBVVCIsImNsYXNzR3JhcGhRTFJlbGF0aW9uQ29uc3RyYWludHNUeXBlIiwiT0JKRUNUIiwiRklMRV9XSEVSRV9JTlBVVCIsIkdFT19QT0lOVF9XSEVSRV9JTlBVVCIsIlBPTFlHT05fV0hFUkVfSU5QVVQiLCJCWVRFU19XSEVSRV9JTlBVVCIsInVuZGVmaW5lZCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7Ozs7QUFFQSxNQUFNQSxnQ0FBZ0MsR0FBRyxDQUN2Q0MsU0FEdUMsRUFFdkNDLFdBRnVDLEVBR3ZDQyxlQUh1QyxFQUl2Q0MsU0FKdUMsS0FLcEM7QUFDSCxNQUFJQSxTQUFTLEtBQUssSUFBZCxJQUFzQkEsU0FBUyxLQUFLLFVBQXhDLEVBQW9EO0FBQ2xELFdBQU9DLG1CQUFtQixDQUFDQyxjQUEzQjtBQUNEOztBQUVELFVBQVFMLFNBQVI7QUFDRSxTQUFLLFFBQUw7QUFDRSxhQUFPSSxtQkFBbUIsQ0FBQ0Usa0JBQTNCOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9GLG1CQUFtQixDQUFDRyxrQkFBM0I7O0FBQ0YsU0FBSyxTQUFMO0FBQ0UsYUFBT0gsbUJBQW1CLENBQUNJLG1CQUEzQjs7QUFDRixTQUFLLE9BQUw7QUFDRSxhQUFPSixtQkFBbUIsQ0FBQ0ssaUJBQTNCOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9MLG1CQUFtQixDQUFDTSxrQkFBM0I7O0FBQ0YsU0FBSyxNQUFMO0FBQ0UsYUFBT04sbUJBQW1CLENBQUNPLGdCQUEzQjs7QUFDRixTQUFLLFNBQUw7QUFDRSxVQUNFVCxlQUFlLENBQUNELFdBQUQsQ0FBZixJQUNBQyxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlcsbUNBRi9CLEVBR0U7QUFDQSxlQUFPVixlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlcsbUNBQXBDO0FBQ0QsT0FMRCxNQUtPO0FBQ0wsZUFBT1IsbUJBQW1CLENBQUNTLE1BQTNCO0FBQ0Q7O0FBQ0gsU0FBSyxNQUFMO0FBQ0UsYUFBT1QsbUJBQW1CLENBQUNVLGdCQUEzQjs7QUFDRixTQUFLLFVBQUw7QUFDRSxhQUFPVixtQkFBbUIsQ0FBQ1cscUJBQTNCOztBQUNGLFNBQUssU0FBTDtBQUNFLGFBQU9YLG1CQUFtQixDQUFDWSxtQkFBM0I7O0FBQ0YsU0FBSyxPQUFMO0FBQ0UsYUFBT1osbUJBQW1CLENBQUNhLGlCQUEzQjs7QUFDRixTQUFLLEtBQUw7QUFDRSxhQUFPYixtQkFBbUIsQ0FBQ00sa0JBQTNCOztBQUNGLFNBQUssVUFBTDtBQUNFLFVBQ0VSLGVBQWUsQ0FBQ0QsV0FBRCxDQUFmLElBQ0FDLGVBQWUsQ0FBQ0QsV0FBRCxDQUFmLENBQTZCVyxtQ0FGL0IsRUFHRTtBQUNBLGVBQU9WLGVBQWUsQ0FBQ0QsV0FBRCxDQUFmLENBQTZCVyxtQ0FBcEM7QUFDRCxPQUxELE1BS087QUFDTCxlQUFPUixtQkFBbUIsQ0FBQ1MsTUFBM0I7QUFDRDs7QUFDSDtBQUNFLGFBQU9LLFNBQVA7QUExQ0o7QUE0Q0QsQ0F0REQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4uL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5cbmNvbnN0IHRyYW5zZm9ybUNvbnN0cmFpbnRUeXBlVG9HcmFwaFFMID0gKFxuICBwYXJzZVR5cGUsXG4gIHRhcmdldENsYXNzLFxuICBwYXJzZUNsYXNzVHlwZXMsXG4gIGZpZWxkTmFtZVxuKSA9PiB7XG4gIGlmIChmaWVsZE5hbWUgPT09ICdpZCcgfHwgZmllbGROYW1lID09PSAnb2JqZWN0SWQnKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuSURfV0hFUkVfSU5QVVQ7XG4gIH1cblxuICBzd2l0Y2ggKHBhcnNlVHlwZSkge1xuICAgIGNhc2UgJ1N0cmluZyc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5TVFJJTkdfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnTnVtYmVyJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk5VTUJFUl9XSEVSRV9JTlBVVDtcbiAgICBjYXNlICdCb29sZWFuJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkJPT0xFQU5fV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuQVJSQVlfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnT2JqZWN0JzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVF9XSEVSRV9JTlBVVDtcbiAgICBjYXNlICdEYXRlJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkRBVEVfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10gJiZcbiAgICAgICAgcGFyc2VDbGFzc1R5cGVzW3RhcmdldENsYXNzXS5jbGFzc0dyYXBoUUxSZWxhdGlvbkNvbnN0cmFpbnRzVHlwZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdLmNsYXNzR3JhcGhRTFJlbGF0aW9uQ29uc3RyYWludHNUeXBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuICAgICAgfVxuICAgIGNhc2UgJ0ZpbGUnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuRklMRV9XSEVSRV9JTlBVVDtcbiAgICBjYXNlICdHZW9Qb2ludCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5HRU9fUE9JTlRfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5QT0xZR09OX1dIRVJFX0lOUFVUO1xuICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkJZVEVTX1dIRVJFX0lOUFVUO1xuICAgIGNhc2UgJ0FDTCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1RfV0hFUkVfSU5QVVQ7XG4gICAgY2FzZSAnUmVsYXRpb24nOlxuICAgICAgaWYgKFxuICAgICAgICBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMUmVsYXRpb25Db25zdHJhaW50c1R5cGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gcGFyc2VDbGFzc1R5cGVzW3RhcmdldENsYXNzXS5jbGFzc0dyYXBoUUxSZWxhdGlvbkNvbnN0cmFpbnRzVHlwZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcbiAgICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufTtcblxuZXhwb3J0IHsgdHJhbnNmb3JtQ29uc3RyYWludFR5cGVUb0dyYXBoUUwgfTtcbiJdfQ== \ 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..8606eaa889 --- /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_INPUT; + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9pbnB1dFR5cGUuanMiXSwibmFtZXMiOlsidHJhbnNmb3JtSW5wdXRUeXBlVG9HcmFwaFFMIiwicGFyc2VUeXBlIiwidGFyZ2V0Q2xhc3MiLCJwYXJzZUNsYXNzVHlwZXMiLCJHcmFwaFFMU3RyaW5nIiwiR3JhcGhRTEZsb2F0IiwiR3JhcGhRTEJvb2xlYW4iLCJHcmFwaFFMTGlzdCIsImRlZmF1bHRHcmFwaFFMVHlwZXMiLCJBTlkiLCJPQkpFQ1QiLCJEQVRFIiwiY2xhc3NHcmFwaFFMUG9pbnRlclR5cGUiLCJjbGFzc0dyYXBoUUxSZWxhdGlvblR5cGUiLCJGSUxFX0lOUFVUIiwiR0VPX1BPSU5UX0lOUFVUIiwiUE9MWUdPTl9JTlBVVCIsIkJZVEVTIiwiQUNMX0lOUFVUIiwidW5kZWZpbmVkIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBTUE7Ozs7OztBQUVBLE1BQU1BLDJCQUEyQixHQUFHLENBQ2xDQyxTQURrQyxFQUVsQ0MsV0FGa0MsRUFHbENDLGVBSGtDLEtBSS9CO0FBQ0gsVUFBUUYsU0FBUjtBQUNFLFNBQUssUUFBTDtBQUNFLGFBQU9HLHNCQUFQOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9DLHFCQUFQOztBQUNGLFNBQUssU0FBTDtBQUNFLGFBQU9DLHVCQUFQOztBQUNGLFNBQUssT0FBTDtBQUNFLGFBQU8sSUFBSUMsb0JBQUosQ0FBZ0JDLG1CQUFtQixDQUFDQyxHQUFwQyxDQUFQOztBQUNGLFNBQUssUUFBTDtBQUNFLGFBQU9ELG1CQUFtQixDQUFDRSxNQUEzQjs7QUFDRixTQUFLLE1BQUw7QUFDRSxhQUFPRixtQkFBbUIsQ0FBQ0csSUFBM0I7O0FBQ0YsU0FBSyxTQUFMO0FBQ0UsVUFDRVIsZUFBZSxJQUNmQSxlQUFlLENBQUNELFdBQUQsQ0FEZixJQUVBQyxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlUsdUJBSC9CLEVBSUU7QUFDQSxlQUFPVCxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlUsdUJBQXBDO0FBQ0QsT0FORCxNQU1PO0FBQ0wsZUFBT0osbUJBQW1CLENBQUNFLE1BQTNCO0FBQ0Q7O0FBQ0gsU0FBSyxVQUFMO0FBQ0UsVUFDRVAsZUFBZSxJQUNmQSxlQUFlLENBQUNELFdBQUQsQ0FEZixJQUVBQyxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2Qlcsd0JBSC9CLEVBSUU7QUFDQSxlQUFPVixlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2Qlcsd0JBQXBDO0FBQ0QsT0FORCxNQU1PO0FBQ0wsZUFBT0wsbUJBQW1CLENBQUNFLE1BQTNCO0FBQ0Q7O0FBQ0gsU0FBSyxNQUFMO0FBQ0UsYUFBT0YsbUJBQW1CLENBQUNNLFVBQTNCOztBQUNGLFNBQUssVUFBTDtBQUNFLGFBQU9OLG1CQUFtQixDQUFDTyxlQUEzQjs7QUFDRixTQUFLLFNBQUw7QUFDRSxhQUFPUCxtQkFBbUIsQ0FBQ1EsYUFBM0I7O0FBQ0YsU0FBSyxPQUFMO0FBQ0UsYUFBT1IsbUJBQW1CLENBQUNTLEtBQTNCOztBQUNGLFNBQUssS0FBTDtBQUNFLGFBQU9ULG1CQUFtQixDQUFDVSxTQUEzQjs7QUFDRjtBQUNFLGFBQU9DLFNBQVA7QUE1Q0o7QUE4Q0QsQ0FuREQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBHcmFwaFFMU3RyaW5nLFxuICBHcmFwaFFMRmxvYXQsXG4gIEdyYXBoUUxCb29sZWFuLFxuICBHcmFwaFFMTGlzdCxcbn0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4uL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5cbmNvbnN0IHRyYW5zZm9ybUlucHV0VHlwZVRvR3JhcGhRTCA9IChcbiAgcGFyc2VUeXBlLFxuICB0YXJnZXRDbGFzcyxcbiAgcGFyc2VDbGFzc1R5cGVzXG4pID0+IHtcbiAgc3dpdGNoIChwYXJzZVR5cGUpIHtcbiAgICBjYXNlICdTdHJpbmcnOlxuICAgICAgcmV0dXJuIEdyYXBoUUxTdHJpbmc7XG4gICAgY2FzZSAnTnVtYmVyJzpcbiAgICAgIHJldHVybiBHcmFwaFFMRmxvYXQ7XG4gICAgY2FzZSAnQm9vbGVhbic6XG4gICAgICByZXR1cm4gR3JhcGhRTEJvb2xlYW47XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuIG5ldyBHcmFwaFFMTGlzdChkZWZhdWx0R3JhcGhRTFR5cGVzLkFOWSk7XG4gICAgY2FzZSAnT2JqZWN0JzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcbiAgICBjYXNlICdEYXRlJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkRBVEU7XG4gICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlcyAmJlxuICAgICAgICBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMUG9pbnRlclR5cGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gcGFyc2VDbGFzc1R5cGVzW3RhcmdldENsYXNzXS5jbGFzc0dyYXBoUUxQb2ludGVyVHlwZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcbiAgICAgIH1cbiAgICBjYXNlICdSZWxhdGlvbic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlcyAmJlxuICAgICAgICBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMUmVsYXRpb25UeXBlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMUmVsYXRpb25UeXBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuICAgICAgfVxuICAgIGNhc2UgJ0ZpbGUnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuRklMRV9JTlBVVDtcbiAgICBjYXNlICdHZW9Qb2ludCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5HRU9fUE9JTlRfSU5QVVQ7XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5QT0xZR09OX0lOUFVUO1xuICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkJZVEVTO1xuICAgIGNhc2UgJ0FDTCc6XG4gICAgICByZXR1cm4gZGVmYXVsdEdyYXBoUUxUeXBlcy5BQ0xfSU5QVVQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn07XG5cbmV4cG9ydCB7IHRyYW5zZm9ybUlucHV0VHlwZVRvR3JhcGhRTCB9O1xuIl19 \ 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..a6da2b761c --- /dev/null +++ b/lib/GraphQL/transformers/mutation.js @@ -0,0 +1,265 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformTypes = void 0; + +var _node = _interopRequireDefault(require("parse/node")); + +var _graphqlRelay = require("graphql-relay"); + +var _filesMutations = require("../loaders/filesMutations"); + +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 _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 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 inputTypeField.type === defaultGraphQLTypes.FILE_INPUT: + fields[field] = await transformers.file(fields[field], req); + 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 = { + file: async ({ + file, + upload + }, { + config + }) => { + if (upload) { + const { + fileInfo + } = await (0, _filesMutations.handleUpload)(upload, config); + return { + name: fileInfo.name, + __type: 'File' + }; + } else if (file && file.name) { + return { + name: file.name, + __type: 'File' + }; + } + + throw new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'Invalid file upload.'); + }, + 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).length === 0) throw new _node.default.Error(_node.default.Error.INVALID_POINTER, `You need to provide at least 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 => { + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(input); + + if (globalIdObject.type === targetClass) { + input = globalIdObject.id; + } + + return { + __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 => { + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(input); + + if (globalIdObject.type === targetClass) { + input = globalIdObject.id; + } + + return { + __type: 'Pointer', + className: targetClass, + objectId: input + }; + }) + }); + } + + return op; + }, + pointer: async (targetClass, field, value, parseGraphQLSchema, { + config, + auth, + info + }) => { + if (Object.keys(value).length > 1 || Object.keys(value).length === 0) throw new _node.default.Error(_node.default.Error.INVALID_POINTER, `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) { + let objectId = value.link; + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(objectId); + + if (globalIdObject.type === targetClass) { + objectId = globalIdObject.id; + } + + return { + __type: 'Pointer', + className: targetClass, + objectId + }; + } + } +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9tdXRhdGlvbi5qcyJdLCJuYW1lcyI6WyJ0cmFuc2Zvcm1UeXBlcyIsImlucHV0VHlwZSIsImZpZWxkcyIsImNsYXNzTmFtZSIsInBhcnNlR3JhcGhRTFNjaGVtYSIsInJlcSIsImNsYXNzR3JhcGhRTENyZWF0ZVR5cGUiLCJjbGFzc0dyYXBoUUxVcGRhdGVUeXBlIiwiY29uZmlnIiwiaXNDcmVhdGVFbmFibGVkIiwiaXNVcGRhdGVFbmFibGVkIiwicGFyc2VDbGFzc1R5cGVzIiwicGFyc2VDbGFzcyIsInBhcnNlQ2xhc3NlcyIsImZpbmQiLCJjbGF6eiIsImNsYXNzR3JhcGhRTENyZWF0ZVR5cGVGaWVsZHMiLCJnZXRGaWVsZHMiLCJjbGFzc0dyYXBoUUxVcGRhdGVUeXBlRmllbGRzIiwicHJvbWlzZXMiLCJPYmplY3QiLCJrZXlzIiwibWFwIiwiZmllbGQiLCJpbnB1dFR5cGVGaWVsZCIsInR5cGUiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiR0VPX1BPSU5UX0lOUFVUIiwidHJhbnNmb3JtZXJzIiwiZ2VvUG9pbnQiLCJQT0xZR09OX0lOUFVUIiwicG9seWdvbiIsIkZJTEVfSU5QVVQiLCJmaWxlIiwicmVsYXRpb24iLCJ0YXJnZXRDbGFzcyIsInBvaW50ZXIiLCJQcm9taXNlIiwiYWxsIiwiQUNMIiwidXBsb2FkIiwiZmlsZUluZm8iLCJuYW1lIiwiX190eXBlIiwiUGFyc2UiLCJFcnJvciIsIkZJTEVfU0FWRV9FUlJPUiIsInZhbHVlIiwiY29vcmRpbmF0ZXMiLCJsYXRpdHVkZSIsImxvbmdpdHVkZSIsInBhcnNlQUNMIiwicHVibGljIiwicmVhZCIsIndyaXRlIiwidXNlcnMiLCJmb3JFYWNoIiwicnVsZSIsInVzZXJJZCIsInJvbGVzIiwicm9sZU5hbWUiLCJhdXRoIiwiaW5mbyIsImxlbmd0aCIsIklOVkFMSURfUE9JTlRFUiIsIm9wIiwiX19vcCIsIm9wcyIsIm5lc3RlZE9iamVjdHNUb0FkZCIsImNyZWF0ZUFuZEFkZCIsImlucHV0IiwicGFyc2VGaWVsZHMiLCJvYmplY3RzTXV0YXRpb25zIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0Iiwib2JqZWN0SWQiLCJhZGQiLCJnbG9iYWxJZE9iamVjdCIsImlkIiwicHVzaCIsIm9iamVjdHMiLCJyZW1vdmUiLCJuZXN0ZWRPYmplY3RUb0FkZCIsImNyZWF0ZUFuZExpbmsiLCJsaW5rIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FBRUEsTUFBTUEsY0FBYyxHQUFHLE9BQ3JCQyxTQURxQixFQUVyQkMsTUFGcUIsRUFHckI7QUFBRUMsRUFBQUEsU0FBRjtBQUFhQyxFQUFBQSxrQkFBYjtBQUFpQ0MsRUFBQUE7QUFBakMsQ0FIcUIsS0FJbEI7QUFDSCxRQUFNO0FBQ0pDLElBQUFBLHNCQURJO0FBRUpDLElBQUFBLHNCQUZJO0FBR0pDLElBQUFBLE1BQU0sRUFBRTtBQUFFQyxNQUFBQSxlQUFGO0FBQW1CQyxNQUFBQTtBQUFuQjtBQUhKLE1BSUZOLGtCQUFrQixDQUFDTyxlQUFuQixDQUFtQ1IsU0FBbkMsQ0FKSjtBQUtBLFFBQU1TLFVBQVUsR0FBR1Isa0JBQWtCLENBQUNTLFlBQW5CLENBQWdDQyxJQUFoQyxDQUNqQkMsS0FBSyxJQUFJQSxLQUFLLENBQUNaLFNBQU4sS0FBb0JBLFNBRFosQ0FBbkI7O0FBR0EsTUFBSUQsTUFBSixFQUFZO0FBQ1YsVUFBTWMsNEJBQTRCLEdBQ2hDUCxlQUFlLElBQUlILHNCQUFuQixHQUNJQSxzQkFBc0IsQ0FBQ1csU0FBdkIsRUFESixHQUVJLElBSE47QUFJQSxVQUFNQyw0QkFBNEIsR0FDaENSLGVBQWUsSUFBSUgsc0JBQW5CLEdBQ0lBLHNCQUFzQixDQUFDVSxTQUF2QixFQURKLEdBRUksSUFITjtBQUlBLFVBQU1FLFFBQVEsR0FBR0MsTUFBTSxDQUFDQyxJQUFQLENBQVluQixNQUFaLEVBQW9Cb0IsR0FBcEIsQ0FBd0IsTUFBTUMsS0FB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QU0sRUFBRSxTQURIO0FBRUx4QyxRQUFBQSxTQUFTLEVBQUVnQyxXQUZOO0FBR0x3QyxRQUFBQTtBQUhLLE9BQVA7QUFLRDtBQUNGO0FBMUtrQixDQUFyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCB7IGZyb21HbG9iYWxJZCB9IGZyb20gJ2dyYXBocWwtcmVsYXknO1xuaW1wb3J0IHsgaGFuZGxlVXBsb2FkIH0gZnJvbSAnLi4vbG9hZGVycy9maWxlc011dGF0aW9ucyc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4uL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5pbXBvcnQgKiBhcyBvYmplY3RzTXV0YXRpb25zIGZyb20gJy4uL2hlbHBlcnMvb2JqZWN0c011dGF0aW9ucyc7XG5cbmNvbnN0IHRyYW5zZm9ybVR5cGVzID0gYXN5bmMgKFxuICBpbnB1dFR5cGU6ICdjcmVhdGUnIHwgJ3VwZGF0ZScsXG4gIGZpZWxkcyxcbiAgeyBjbGFzc05hbWUsIHBhcnNlR3JhcGhRTFNjaGVtYSwgcmVxIH1cbikgPT4ge1xuICBjb25zdCB7XG4gICAgY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZSxcbiAgICBjbGFzc0dyYXBoUUxVcGRhdGVUeXBlLFxuICAgIGNvbmZpZzogeyBpc0NyZWF0ZUVuYWJsZWQsIGlzVXBkYXRlRW5hYmxlZCB9LFxuICB9ID0gcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3NUeXBlc1tjbGFzc05hbWVdO1xuICBjb25zdCBwYXJzZUNsYXNzID0gcGFyc2VHcmFwaFFMU2NoZW1hLnBhcnNlQ2xhc3Nlcy5maW5kKFxuICAgIGNsYXp6ID0+IGNsYXp6LmNsYXNzTmFtZSA9PT0gY2xhc3NOYW1lXG4gICk7XG4gIGlmIChmaWVsZHMpIHtcbiAgICBjb25zdCBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlRmllbGRzID1cbiAgICAgIGlzQ3JlYXRlRW5hYmxlZCAmJiBjbGFzc0dyYXBoUUxDcmVhdGVUeXBlXG4gICAgICAgID8gY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZS5nZXRGaWVsZHMoKVxuICAgICAgICA6IG51bGw7XG4gICAgY29uc3QgY2xhc3NHcmFwaFFMVXBkYXRlVHlwZUZpZWxkcyA9XG4gICAgICBpc1VwZGF0ZUVuYWJsZWQgJiYgY2xhc3NHcmFwaFFMVXBkYXRlVHlwZVxuICAgICAgICA/IGNsYXNzR3JhcGhRTFVwZGF0ZVR5cGUuZ2V0RmllbGRzKClcbiAgICAgICAgOiBudWxsO1xuICAgIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LmtleXMoZmllbGRzKS5tYXAoYXN5bmMgZmllbGQgPT4ge1xuICAgICAgbGV0IGlucHV0VHlwZUZpZWxkO1xuICAgICAgaWYgKGlucHV0VHlwZSA9PT0gJ2NyZWF0ZScgJiYgY2xhc3NHcmFwaFFMQ3JlYXRlVHlwZUZpZWxkcykge1xuICAgICAgICBpbnB1dFR5cGVGaWVsZCA9IGNsYXNzR3JhcGhRTENyZWF0ZVR5cGVGaWVsZHNbZmllbGRdO1xuICAgICAgfSBlbHNlIGlmIChjbGFzc0dyYXBoUUxVcGRhdGVUeXBlRmllbGRzKSB7XG4gICAgICAgIGlucHV0VHlwZUZpZWxkID0gY2xhc3NHcmFwaFFMVXBkYXRlVHlwZUZpZWxkc1tmaWVsZF07XG4gICAgICB9XG4gICAgICBpZiAoaW5wdXRUeXBlRmllbGQpIHtcbiAgICAgICAgc3dpdGNoICh0cnVlKSB7XG4gICAgICAgICAgY2FzZSBpbnB1dFR5cGVGaWVsZC50eXBlID09PSBkZWZhdWx0R3JhcGhRTFR5cGVzLkdFT19QT0lOVF9JTlBVVDpcbiAgICAgICAgICAgIGZpZWxkc1tmaWVsZF0gPSB0cmFuc2Zvcm1lcnMuZ2VvUG9pbnQoZmllbGRzW2ZpZWxkXSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIGlucHV0VHlwZUZpZWxkLnR5cGUgPT09IGRlZmF1bHRHcmFwaFFMVHlwZXMuUE9MWUdPTl9JTlBVVDpcbiAgICAgICAgICAgIGZpZWxkc1tmaWVsZF0gPSB0cmFuc2Zvcm1lcnMucG9seWdvbihmaWVsZHNbZmllbGRdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgaW5wdXRUeXBlRmllbGQudHlwZSA9PT0gZGVmYXVsdEdyYXBoUUxUeXBlcy5GSUxFX0lOUFVUOlxuICAgICAgICAgICAgZmllbGRzW2ZpZWxkXSA9IGF3YWl0IHRyYW5zZm9ybWVycy5maWxlKGZpZWxkc1tmaWVsZF0sIHJlcSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUmVsYXRpb24nOlxuICAgICAgICAgICAgZmllbGRzW2ZpZWxkXSA9IGF3YWl0IHRyYW5zZm9ybWVycy5yZWxhdGlvbihcbiAgICAgICAgICAgICAgcGFyc2VDbGFzcy5maWVsZHNbZmllbGRdLnRhcmdldENsYXNzLFxuICAgICAgICAgICAgICBmaWVsZCxcbiAgICAgICAgICAgICAgZmllbGRzW2ZpZWxkXSxcbiAgICAgICAgICAgICAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICAgICAgICAgICAgICByZXFcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcic6XG4gICAgICAgICAgICBmaWVsZHNbZmllbGRdID0gYXdhaXQgdHJhbnNmb3JtZXJzLnBvaW50ZXIoXG4gICAgICAgICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcyxcbiAgICAgICAgICAgICAgZmllbGQsXG4gICAgICAgICAgICAgIGZpZWxkc1tmaWVsZF0sXG4gICAgICAgICAgICAgIHBhcnNlR3JhcGhRTFNjaGVtYSxcbiAgICAgICAgICAgICAgcmVxXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgaWYgKGZpZWxkcy5BQ0wpIGZpZWxkcy5BQ0wgPSB0cmFuc2Zvcm1lcnMuQUNMKGZpZWxkcy5BQ0wpO1xuICB9XG4gIHJldHVybiBmaWVsZHM7XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1lcnMgPSB7XG4gIGZpbGU6IGFzeW5jICh7IGZpbGUsIHVwbG9hZCB9LCB7IGNvbmZpZyB9KSA9PiB7XG4gICAgaWYgKHVwbG9hZCkge1xuICAgICAgY29uc3QgeyBmaWxlSW5mbyB9ID0gYXdhaXQgaGFuZGxlVXBsb2FkKHVwbG9hZCwgY29uZmlnKTtcbiAgICAgIHJldHVybiB7IG5hbWU6IGZpbGVJbmZvLm5hbWUsIF9fdHlwZTogJ0ZpbGUnIH07XG4gICAgfSBlbHNlIGlmIChmaWxlICYmIGZpbGUubmFtZSkge1xuICAgICAgcmV0dXJuIHsgbmFtZTogZmlsZS5uYW1lLCBfX3R5cGU6ICdGaWxlJyB9O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLCAnSW52YWxpZCBmaWxlIHVwbG9hZC4nKTtcbiAgfSxcbiAgcG9seWdvbjogdmFsdWUgPT4gKHtcbiAgICBfX3R5cGU6ICdQb2x5Z29uJyxcbiAgICBjb29yZGluYXRlczogdmFsdWUubWFwKGdlb1BvaW50ID0+IFtnZW9Qb2ludC5sYXRpdHVkZSwgZ2VvUG9pbnQubG9uZ2l0dWRlXSksXG4gIH0pLFxuICBnZW9Qb2ludDogdmFsdWUgPT4gKHtcbiAgICAuLi52YWx1ZSxcbiAgICBfX3R5cGU6ICdHZW9Qb2ludCcsXG4gIH0pLFxuICBBQ0w6IHZhbHVlID0+IHtcbiAgICBjb25zdCBwYXJzZUFDTCA9IHt9O1xuICAgIGlmICh2YWx1ZS5wdWJsaWMpIHtcbiAgICAgIHBhcnNlQUNMWycqJ10gPSB7XG4gICAgICAgIHJlYWQ6IHZhbHVlLnB1YmxpYy5yZWFkLFxuICAgICAgICB3cml0ZTogdmFsdWUucHVibGljLndyaXRlLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHZhbHVlLnVzZXJzKSB7XG4gICAgICB2YWx1ZS51c2Vycy5mb3JFYWNoKHJ1bGUgPT4ge1xuICAgICAgICBwYXJzZUFDTFtydWxlLnVzZXJJZF0gPSB7XG4gICAgICAgICAgcmVhZDogcnVsZS5yZWFkLFxuICAgICAgICAgIHdyaXRlOiBydWxlLndyaXRlLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh2YWx1ZS5yb2xlcykge1xuICAgICAgdmFsdWUucm9sZXMuZm9yRWFjaChydWxlID0+IHtcbiAgICAgICAgcGFyc2VBQ0xbYHJvbGU6JHtydWxlLnJvbGVOYW1lfWBdID0ge1xuICAgICAgICAgIHJlYWQ6IHJ1bGUucmVhZCxcbiAgICAgICAgICB3cml0ZTogcnVsZS53cml0ZSxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VBQ0w7XG4gIH0sXG4gIHJlbGF0aW9uOiBhc3luYyAoXG4gICAgdGFyZ2V0Q2xhc3MsXG4gICAgZmllbGQsXG4gICAgdmFsdWUsXG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICAgIHsgY29uZmlnLCBhdXRoLCBpbmZvIH1cbiAgKSA9PiB7XG4gICAgaWYgKE9iamVjdC5rZXlzKHZhbHVlKS5sZW5ndGggPT09IDApXG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUE9JTlRFUixcbiAgICAgICAgYFlvdSBuZWVkIHRvIHByb3ZpZGUgYXQgbGVhc3Qgb25lIG9wZXJhdGlvbiBvbiB0aGUgcmVsYXRpb24gbXV0YXRpb24gb2YgZmllbGQgJHtmaWVsZH1gXG4gICAgICApO1xuXG4gICAgY29uc3Qgb3AgPSB7XG4gICAgICBfX29wOiAnQmF0Y2gnLFxuICAgICAgb3BzOiBbXSxcbiAgICB9O1xuICAgIGxldCBuZXN0ZWRPYmplY3RzVG9BZGQgPSBbXTtcblxuICAgIGlmICh2YWx1ZS5jcmVhdGVBbmRBZGQpIHtcbiAgICAgIG5lc3RlZE9iamVjdHNUb0FkZCA9IChcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgdmFsdWUuY3JlYXRlQW5kQWRkLm1hcChhc3luYyBpbnB1dCA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZUZpZWxkcyA9IGF3YWl0IHRyYW5zZm9ybVR5cGVzKCdjcmVhdGUnLCBpbnB1dCwge1xuICAgICAgICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEsXG4gICAgICAgICAgICAgIHJlcTogeyBjb25maWcsIGF1dGgsIGluZm8gfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdHNNdXRhdGlvbnMuY3JlYXRlT2JqZWN0KFxuICAgICAgICAgICAgICB0YXJnZXRDbGFzcyxcbiAgICAgICAgICAgICAgcGFyc2VGaWVsZHMsXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgYXV0aCxcbiAgICAgICAgICAgICAgaW5mb1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICApLm1hcChvYmplY3QgPT4gKHtcbiAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgIGNsYXNzTmFtZTogdGFyZ2V0Q2xhc3MsXG4gICAgICAgIG9iamVjdElkOiBvYmplY3Qub2JqZWN0SWQsXG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlLmFkZCB8fCBuZXN0ZWRPYmplY3RzVG9BZGQubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKCF2YWx1ZS5hZGQpIHZhbHVlLmFkZCA9IFtdO1xuICAgICAgdmFsdWUuYWRkID0gdmFsdWUuYWRkLm1hcChpbnB1dCA9PiB7XG4gICAgICAgIGNvbnN0IGdsb2JhbElkT2JqZWN0ID0gZnJvbUdsb2JhbElkKGlucHV0KTtcbiAgICAgICAgaWYgKGdsb2JhbElkT2JqZWN0LnR5cGUgPT09IHRhcmdldENsYXNzKSB7XG4gICAgICAgICAgaW5wdXQgPSBnbG9iYWxJZE9iamVjdC5pZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgIGNsYXNzTmFtZTogdGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgb2JqZWN0SWQ6IGlucHV0LFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICBvcC5vcHMucHVzaCh7XG4gICAgICAgIF9fb3A6ICdBZGRSZWxhdGlvbicsXG4gICAgICAgIG9iamVjdHM6IFsuLi52YWx1ZS5hZGQsIC4uLm5lc3RlZE9iamVjdHNUb0FkZF0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUucmVtb3ZlKSB7XG4gICAgICBvcC5vcHMucHVzaCh7XG4gICAgICAgIF9fb3A6ICdSZW1vdmVSZWxhdGlvbicsXG4gICAgICAgIG9iamVjdHM6IHZhbHVlLnJlbW92ZS5tYXAoaW5wdXQgPT4ge1xuICAgICAgICAgIGNvbnN0IGdsb2JhbElkT2JqZWN0ID0gZnJvbUdsb2JhbElkKGlucHV0KTtcbiAgICAgICAgICBpZiAoZ2xvYmFsSWRPYmplY3QudHlwZSA9PT0gdGFyZ2V0Q2xhc3MpIHtcbiAgICAgICAgICAgIGlucHV0ID0gZ2xvYmFsSWRPYmplY3QuaWQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgICAgIGNsYXNzTmFtZTogdGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICBvYmplY3RJZDogaW5wdXQsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG9wO1xuICB9LFxuICBwb2ludGVyOiBhc3luYyAoXG4gICAgdGFyZ2V0Q2xhc3MsXG4gICAgZmllbGQsXG4gICAgdmFsdWUsXG4gICAgcGFyc2VHcmFwaFFMU2NoZW1hLFxuICAgIHsgY29uZmlnLCBhdXRoLCBpbmZvIH1cbiAgKSA9PiB7XG4gICAgaWYgKE9iamVjdC5rZXlzKHZhbHVlKS5sZW5ndGggPiAxIHx8IE9iamVjdC5rZXlzKHZhbHVlKS5sZW5ndGggPT09IDApXG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUE9JTlRFUixcbiAgICAgICAgYFlvdSBuZWVkIHRvIHByb3ZpZGUgbGluayBPUiBjcmVhdGVMaW5rIG9uIHRoZSBwb2ludGVyIG11dGF0aW9uIG9mIGZpZWxkICR7ZmllbGR9YFxuICAgICAgKTtcblxuICAgIGxldCBuZXN0ZWRPYmplY3RUb0FkZDtcbiAgICBpZiAodmFsdWUuY3JlYXRlQW5kTGluaykge1xuICAgICAgY29uc3QgcGFyc2VGaWVsZHMgPSBhd2FpdCB0cmFuc2Zvcm1UeXBlcygnY3JlYXRlJywgdmFsdWUuY3JlYXRlQW5kTGluaywge1xuICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICBwYXJzZUdyYXBoUUxTY2hlbWEsXG4gICAgICAgIHJlcTogeyBjb25maWcsIGF1dGgsIGluZm8gfSxcbiAgICAgIH0pO1xuICAgICAgbmVzdGVkT2JqZWN0VG9BZGQgPSBhd2FpdCBvYmplY3RzTXV0YXRpb25zLmNyZWF0ZU9iamVjdChcbiAgICAgICAgdGFyZ2V0Q2xhc3MsXG4gICAgICAgIHBhcnNlRmllbGRzLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGF1dGgsXG4gICAgICAgIGluZm9cbiAgICAgICk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgY2xhc3NOYW1lOiB0YXJnZXRDbGFzcyxcbiAgICAgICAgb2JqZWN0SWQ6IG5lc3RlZE9iamVjdFRvQWRkLm9iamVjdElkLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHZhbHVlLmxpbmspIHtcbiAgICAgIGxldCBvYmplY3RJZCA9IHZhbHVlLmxpbms7XG4gICAgICBjb25zdCBnbG9iYWxJZE9iamVjdCA9IGZyb21HbG9iYWxJZChvYmplY3RJZCk7XG4gICAgICBpZiAoZ2xvYmFsSWRPYmplY3QudHlwZSA9PT0gdGFyZ2V0Q2xhc3MpIHtcbiAgICAgICAgb2JqZWN0SWQgPSBnbG9iYWxJZE9iamVjdC5pZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICBvYmplY3RJZCxcbiAgICAgIH07XG4gICAgfVxuICB9LFxufTtcblxuZXhwb3J0IHsgdHJhbnNmb3JtVHlwZXMgfTtcbiJdfQ== \ 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..e01c729f6f --- /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.OBJECT); + } + + 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 new _graphql.GraphQLNonNull(defaultGraphQLTypes.ACL); + + default: + return undefined; + } +}; + +exports.transformOutputTypeToGraphQL = transformOutputTypeToGraphQL; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9vdXRwdXRUeXBlLmpzIl0sIm5hbWVzIjpbInRyYW5zZm9ybU91dHB1dFR5cGVUb0dyYXBoUUwiLCJwYXJzZVR5cGUiLCJ0YXJnZXRDbGFzcyIsInBhcnNlQ2xhc3NUeXBlcyIsIkdyYXBoUUxTdHJpbmciLCJHcmFwaFFMRmxvYXQiLCJHcmFwaFFMQm9vbGVhbiIsIkdyYXBoUUxMaXN0IiwiZGVmYXVsdEdyYXBoUUxUeXBlcyIsIkFSUkFZX1JFU1VMVCIsIk9CSkVDVCIsIkRBVEUiLCJjbGFzc0dyYXBoUUxPdXRwdXRUeXBlIiwiY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGUiLCJHcmFwaFFMTm9uTnVsbCIsIkZJTEVfSU5GTyIsIkdFT19QT0lOVCIsIlBPTFlHT04iLCJCWVRFUyIsIkFDTCIsInVuZGVmaW5lZCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7Ozs7QUFRQSxNQUFNQSw0QkFBNEIsR0FBRyxDQUNuQ0MsU0FEbUMsRUFFbkNDLFdBRm1DLEVBR25DQyxlQUhtQyxLQUloQztBQUNILFVBQVFGLFNBQVI7QUFDRSxTQUFLLFFBQUw7QUFDRSxhQUFPRyxzQkFBUDs7QUFDRixTQUFLLFFBQUw7QUFDRSxhQUFPQyxxQkFBUDs7QUFDRixTQUFLLFNBQUw7QUFDRSxhQUFPQyx1QkFBUDs7QUFDRixTQUFLLE9BQUw7QUFDRSxhQUFPLElBQUlDLG9CQUFKLENBQWdCQyxtQkFBbUIsQ0FBQ0MsWUFBcEMsQ0FBUDs7QUFDRixTQUFLLFFBQUw7QUFDRSxhQUFPRCxtQkFBbUIsQ0FBQ0UsTUFBM0I7O0FBQ0YsU0FBSyxNQUFMO0FBQ0UsYUFBT0YsbUJBQW1CLENBQUNHLElBQTNCOztBQUNGLFNBQUssU0FBTDtBQUNFLFVBQ0VSLGVBQWUsSUFDZkEsZUFBZSxDQUFDRCxXQUFELENBRGYsSUFFQUMsZUFBZSxDQUFDRCxXQUFELENBQWYsQ0FBNkJVLHNCQUgvQixFQUlFO0FBQ0EsZUFBT1QsZUFBZSxDQUFDRCxXQUFELENBQWYsQ0FBNkJVLHNCQUFwQztBQUNELE9BTkQsTUFNTztBQUNMLGVBQU9KLG1CQUFtQixDQUFDRSxNQUEzQjtBQUNEOztBQUNILFNBQUssVUFBTDtBQUNFLFVBQ0VQLGVBQWUsSUFDZkEsZUFBZSxDQUFDRCxXQUFELENBRGYsSUFFQUMsZUFBZSxDQUFDRCxXQUFELENBQWYsQ0FBNkJXLDBCQUgvQixFQUlFO0FBQ0EsZUFBTyxJQUFJQyx1QkFBSixDQUNMWCxlQUFlLENBQUNELFdBQUQsQ0FBZixDQUE2QlcsMEJBRHhCLENBQVA7QUFHRCxPQVJELE1BUU87QUFDTCxlQUFPLElBQUlDLHVCQUFKLENBQW1CTixtQkFBbUIsQ0FBQ0UsTUFBdkMsQ0FBUDtBQUNEOztBQUNILFNBQUssTUFBTDtBQUNFLGFBQU9GLG1CQUFtQixDQUFDTyxTQUEzQjs7QUFDRixTQUFLLFVBQUw7QUFDRSxhQUFPUCxtQkFBbUIsQ0FBQ1EsU0FBM0I7O0FBQ0YsU0FBSyxTQUFMO0FBQ0UsYUFBT1IsbUJBQW1CLENBQUNTLE9BQTNCOztBQUNGLFNBQUssT0FBTDtBQUNFLGFBQU9ULG1CQUFtQixDQUFDVSxLQUEzQjs7QUFDRixTQUFLLEtBQUw7QUFDRSxhQUFPLElBQUlKLHVCQUFKLENBQW1CTixtQkFBbUIsQ0FBQ1csR0FBdkMsQ0FBUDs7QUFDRjtBQUNFLGFBQU9DLFNBQVA7QUE5Q0o7QUFnREQsQ0FyREQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4uL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxUeXBlcyc7XG5pbXBvcnQge1xuICBHcmFwaFFMU3RyaW5nLFxuICBHcmFwaFFMRmxvYXQsXG4gIEdyYXBoUUxCb29sZWFuLFxuICBHcmFwaFFMTGlzdCxcbiAgR3JhcGhRTE5vbk51bGwsXG59IGZyb20gJ2dyYXBocWwnO1xuXG5jb25zdCB0cmFuc2Zvcm1PdXRwdXRUeXBlVG9HcmFwaFFMID0gKFxuICBwYXJzZVR5cGUsXG4gIHRhcmdldENsYXNzLFxuICBwYXJzZUNsYXNzVHlwZXNcbikgPT4ge1xuICBzd2l0Y2ggKHBhcnNlVHlwZSkge1xuICAgIGNhc2UgJ1N0cmluZyc6XG4gICAgICByZXR1cm4gR3JhcGhRTFN0cmluZztcbiAgICBjYXNlICdOdW1iZXInOlxuICAgICAgcmV0dXJuIEdyYXBoUUxGbG9hdDtcbiAgICBjYXNlICdCb29sZWFuJzpcbiAgICAgIHJldHVybiBHcmFwaFFMQm9vbGVhbjtcbiAgICBjYXNlICdBcnJheSc6XG4gICAgICByZXR1cm4gbmV3IEdyYXBoUUxMaXN0KGRlZmF1bHRHcmFwaFFMVHlwZXMuQVJSQVlfUkVTVUxUKTtcbiAgICBjYXNlICdPYmplY3QnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuT0JKRUNUO1xuICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuREFURTtcbiAgICBjYXNlICdQb2ludGVyJzpcbiAgICAgIGlmIChcbiAgICAgICAgcGFyc2VDbGFzc1R5cGVzICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10gJiZcbiAgICAgICAgcGFyc2VDbGFzc1R5cGVzW3RhcmdldENsYXNzXS5jbGFzc0dyYXBoUUxPdXRwdXRUeXBlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMT3V0cHV0VHlwZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLk9CSkVDVDtcbiAgICAgIH1cbiAgICBjYXNlICdSZWxhdGlvbic6XG4gICAgICBpZiAoXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlcyAmJlxuICAgICAgICBwYXJzZUNsYXNzVHlwZXNbdGFyZ2V0Q2xhc3NdICYmXG4gICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbmV3IEdyYXBoUUxOb25OdWxsKFxuICAgICAgICAgIHBhcnNlQ2xhc3NUeXBlc1t0YXJnZXRDbGFzc10uY2xhc3NHcmFwaFFMRmluZFJlc3VsdFR5cGVcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBuZXcgR3JhcGhRTE5vbk51bGwoZGVmYXVsdEdyYXBoUUxUeXBlcy5PQkpFQ1QpO1xuICAgICAgfVxuICAgIGNhc2UgJ0ZpbGUnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuRklMRV9JTkZPO1xuICAgIGNhc2UgJ0dlb1BvaW50JzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLkdFT19QT0lOVDtcbiAgICBjYXNlICdQb2x5Z29uJzpcbiAgICAgIHJldHVybiBkZWZhdWx0R3JhcGhRTFR5cGVzLlBPTFlHT047XG4gICAgY2FzZSAnQnl0ZXMnOlxuICAgICAgcmV0dXJuIGRlZmF1bHRHcmFwaFFMVHlwZXMuQllURVM7XG4gICAgY2FzZSAnQUNMJzpcbiAgICAgIHJldHVybiBuZXcgR3JhcGhRTE5vbk51bGwoZGVmYXVsdEdyYXBoUUxUeXBlcy5BQ0wpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG5leHBvcnQgeyB0cmFuc2Zvcm1PdXRwdXRUeXBlVG9HcmFwaFFMIH07XG4iXX0= \ 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..b7fa6f5cbf --- /dev/null +++ b/lib/GraphQL/transformers/query.js @@ -0,0 +1,273 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.transformQueryInputToParse = exports.transformQueryConstraintInputToParse = void 0; + +var _graphqlRelay = require("graphql-relay"); + +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 = { + 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, parentFieldName, className, parentConstraints, parseClasses) => { + const fields = parseClasses.find(parseClass => parseClass.className === className).fields; + + if (parentFieldName === 'id' && className) { + Object.keys(constraints).forEach(constraintName => { + const constraintValue = constraints[constraintName]; + + if (typeof constraintValue === 'string') { + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(constraintValue); + + if (globalIdObject.type === className) { + constraints[constraintName] = globalIdObject.id; + } + } else if (Array.isArray(constraintValue)) { + constraints[constraintName] = constraintValue.map(value => { + const globalIdObject = (0, _graphqlRelay.fromGlobalId)(value); + + if (globalIdObject.type === className) { + return globalIdObject.id; + } + + return value; + }); + } + }); + parentConstraints.objectId = constraints; + delete parentConstraints.id; + } + + Object.keys(constraints).forEach(fieldName => { + let fieldValue = constraints[fieldName]; + + if (parseConstraintMap[fieldName]) { + constraints[parseConstraintMap[fieldName]] = constraints[fieldName]; + delete 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 (fields[parentFieldName] && (fields[parentFieldName].type === 'Pointer' || fields[parentFieldName].type === 'Relation')) { + const { + targetClass + } = fields[parentFieldName]; + + if (fieldName === 'exists') { + if (fields[parentFieldName].type === 'Relation') { + const whereTarget = fieldValue ? 'where' : 'notWhere'; + + if (constraints[whereTarget]) { + if (constraints[whereTarget].objectId) { + constraints[whereTarget].objectId = _objectSpread({}, constraints[whereTarget].objectId, { + $exists: fieldValue + }); + } else { + constraints[whereTarget].objectId = { + $exists: fieldValue + }; + } + } else { + const parseWhereTarget = fieldValue ? '$inQuery' : '$notInQuery'; + parentConstraints[parentFieldName][parseWhereTarget] = { + where: { + objectId: { + $exists: true + } + }, + className: targetClass + }; + } + + delete constraints.$exists; + } else { + parentConstraints[parentFieldName].$exists = fieldValue; + } + + return; + } + + switch (fieldName) { + case 'have': + parentConstraints[parentFieldName].$inQuery = { + where: fieldValue, + className: targetClass + }; + transformQueryInputToParse(parentConstraints[parentFieldName].$inQuery.where, targetClass, parseClasses); + break; + + case 'haveNot': + parentConstraints[parentFieldName].$notInQuery = { + where: fieldValue, + className: targetClass + }; + transformQueryInputToParse(parentConstraints[parentFieldName].$notInQuery.where, targetClass, parseClasses); + break; + } + + delete constraints[fieldName]; + return; + } + + switch (fieldName) { + case 'point': + if (typeof fieldValue === 'object' && !fieldValue.__type) { + fieldValue.__type = 'GeoPoint'; + } + + break; + + 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[parseConstraintMap[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[parseConstraintMap[fieldName]] = fieldValue; + } + + break; + } + + if (typeof fieldValue === 'object') { + if (fieldName === 'where') { + transformQueryInputToParse(fieldValue, className, parseClasses); + } else { + transformQueryConstraintInputToParse(fieldValue, fieldName, className, constraints, parseClasses); + } + } + }); +}; + +exports.transformQueryConstraintInputToParse = transformQueryConstraintInputToParse; + +const transformQueryInputToParse = (constraints, className, parseClasses) => { + 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; + fieldValue.forEach(fieldValueItem => { + transformQueryInputToParse(fieldValueItem, className, parseClasses); + }); + return; + } else { + transformQueryConstraintInputToParse(fieldValue, fieldName, className, constraints, parseClasses); + } + }); +}; + +exports.transformQueryInputToParse = transformQueryInputToParse; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9HcmFwaFFML3RyYW5zZm9ybWVycy9xdWVyeS5qcyJdLCJuYW1lcyI6WyJwYXJzZVF1ZXJ5TWFwIiwiT1IiLCJBTkQiLCJOT1IiLCJwYXJzZUNvbnN0cmFpbnRNYXAiLCJlcXVhbFRvIiwibm90RXF1YWxUbyIsImxlc3NUaGFuIiwibGVzc1RoYW5PckVxdWFsVG8iLCJncmVhdGVyVGhhbiIsImdyZWF0ZXJUaGFuT3JFcXVhbFRvIiwiaW4iLCJub3RJbiIsImV4aXN0cyIsImluUXVlcnlLZXkiLCJub3RJblF1ZXJ5S2V5IiwiaW5RdWVyeSIsIm5vdEluUXVlcnkiLCJjb250YWluZWRCeSIsImNvbnRhaW5zIiwibWF0Y2hlc1JlZ2V4Iiwib3B0aW9ucyIsInRleHQiLCJzZWFyY2giLCJ0ZXJtIiwibGFuZ3VhZ2UiLCJjYXNlU2Vuc2l0aXZlIiwiZGlhY3JpdGljU2Vuc2l0aXZlIiwibmVhclNwaGVyZSIsIm1heERpc3RhbmNlIiwibWF4RGlzdGFuY2VJblJhZGlhbnMiLCJtYXhEaXN0YW5jZUluTWlsZXMiLCJtYXhEaXN0YW5jZUluS2lsb21ldGVycyIsIndpdGhpbiIsImJveCIsImdlb1dpdGhpbiIsInBvbHlnb24iLCJjZW50ZXJTcGhlcmUiLCJnZW9JbnRlcnNlY3RzIiwicG9pbnQiLCJ0cmFuc2Zvcm1RdWVyeUNvbnN0cmFpbnRJbnB1dFRvUGFyc2UiLCJjb25zdHJhaW50cyIsInBhcmVudEZpZWxkTmFtZSIsImNsYXNzTmFtZSIsInBhcmVudENvbnN0cmFpbnRzIiwicGFyc2VDbGFzc2VzIiwiZmllbGRzIiwiZmluZCIsInBhcnNlQ2xhc3MiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsImNvbnN0cmFpbnROYW1lIiwiY29uc3RyYWludFZhbHVlIiwiZ2xvYmFsSWRPYmplY3QiLCJ0eXBlIiwiaWQiLCJBcnJheSIsImlzQXJyYXkiLCJtYXAiLCJ2YWx1ZSIsIm9iamVjdElkIiwiZmllbGROYW1lIiwiZmllbGRWYWx1ZSIsImtleSIsInRhcmdldENsYXNzIiwid2hlcmVUYXJnZXQiLCIkZXhpc3RzIiwicGFyc2VXaGVyZVRhcmdldCIsIndoZXJlIiwiJGluUXVlcnkiLCJ0cmFuc2Zvcm1RdWVyeUlucHV0VG9QYXJzZSIsIiRub3RJblF1ZXJ5IiwiX190eXBlIiwiYm90dG9tTGVmdCIsInVwcGVyUmlnaHQiLCJnZW9Qb2ludCIsImNlbnRlciIsImRpc3RhbmNlIiwiZmllbGRWYWx1ZUl0ZW0iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFFQSxNQUFNQSxhQUFhLEdBQUc7QUFDcEJDLEVBQUFBLEVBQUUsRUFBRSxLQURnQjtBQUVwQkMsRUFBQUEsR0FBRyxFQUFFLE1BRmU7QUFHcEJDLEVBQUFBLEdBQUcsRUFBRTtBQUhlLENBQXRCO0FBTUEsTUFBTUMsa0JBQWtCLEdBQUc7QUFDekJDLEVBQUFBLE9BQU8sRUFBRSxLQURnQjtBQUV6QkMsRUFBQUEsVUFBVSxFQUFFLEtBRmE7QUFHekJDLEVBQUFBLFFBQVEsRUFBRSxLQUhlO0FBSXpCQyxFQUFBQSxpQkFBaUIsRUFBRSxNQUpNO0FBS3pCQyxFQUFBQSxXQUFXLEVBQUUsS0FMWTtBQU16QkMsRUFBQUEsb0JBQW9CLEVBQUUsTUFORztBQU96QkMsRUFBQUEsRUFBRSxFQUFFLEtBUHFCO0FBUXpCQyxFQUFBQSxLQUFLLEVBQUUsTUFSa0I7QUFTekJDLEVBQUFBLE1BQU0sRUFBRSxTQVRpQjtBQVV6QkMsRUFBQUEsVUFBVSxFQUFFLFNBVmE7QUFXekJDLEVBQUFBLGFBQWEsRUFBRSxhQVhVO0FBWXpCQyxFQUFBQSxPQUFPLEVBQUUsVUFaZ0I7QUFhekJDLEVBQUFBLFVBQVUsRUFBRSxhQWJhO0FBY3pCQyxFQUFBQSxXQUFXLEVBQUUsY0FkWTtBQWV6QkMsRUFBQUEsUUFBUSxFQUFFLE1BZmU7QUFnQnpCQyxFQUFBQSxZQUFZLEVBQUUsUUFoQlc7QUFpQnpCQyxFQUFBQSxPQUFPLEVBQUUsVUFqQmdCO0FBa0J6QkMsRUFBQUEsSUFBSSxFQUFFLE9BbEJtQjtBQW1CekJD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LGFBQWEsQ0FBQzhELFNBQUQsQ0FBakIsRUFBOEI7QUFDNUIsYUFBT3JCLFdBQVcsQ0FBQ3FCLFNBQUQsQ0FBbEI7QUFDQUEsTUFBQUEsU0FBUyxHQUFHOUQsYUFBYSxDQUFDOEQsU0FBRCxDQUF6QjtBQUNBckIsTUFBQUEsV0FBVyxDQUFDcUIsU0FBRCxDQUFYLEdBQXlCQyxVQUF6QjtBQUNBQSxNQUFBQSxVQUFVLENBQUNaLE9BQVgsQ0FBbUI0QixjQUFjLElBQUk7QUFDbkNSLFFBQUFBLDBCQUEwQixDQUFDUSxjQUFELEVBQWlCcEMsU0FBakIsRUFBNEJFLFlBQTVCLENBQTFCO0FBQ0QsT0FGRDtBQUdBO0FBQ0QsS0FSRCxNQVFPO0FBQ0xMLE1BQUFBLG9DQUFvQyxDQUNsQ3VCLFVBRGtDLEVBRWxDRCxTQUZrQyxFQUdsQ25CLFNBSGtDLEVBSWxDRixXQUprQyxFQUtsQ0ksWUFMa0MsQ0FBcEM7QUFPRDtBQUNGLEdBcEJEO0FBcUJELENBMUJEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZnJvbUdsb2JhbElkIH0gZnJvbSAnZ3JhcGhxbC1yZWxheSc7XG5cbmNvbnN0IHBhcnNlUXVlcnlNYXAgPSB7XG4gIE9SOiAnJG9yJyxcbiAgQU5EOiAnJGFuZCcsXG4gIE5PUjogJyRub3InLFxufTtcblxuY29uc3QgcGFyc2VDb25zdHJhaW50TWFwID0ge1xuICBlcXVhbFRvOiAnJGVxJyxcbiAgbm90RXF1YWxUbzogJyRuZScsXG4gIGxlc3NUaGFuOiAnJGx0JyxcbiAgbGVzc1RoYW5PckVxdWFsVG86ICckbHRlJyxcbiAgZ3JlYXRlclRoYW46ICckZ3QnLFxuICBncmVhdGVyVGhhbk9yRXF1YWxUbzogJyRndGUnLFxuICBpbjogJyRpbicsXG4gIG5vdEluOiAnJG5pbicsXG4gIGV4aXN0czogJyRleGlzdHMnLFxuICBpblF1ZXJ5S2V5OiAnJHNlbGVjdCcsXG4gIG5vdEluUXVlcnlLZXk6ICckZG9udFNlbGVjdCcsXG4gIGluUXVlcnk6ICckaW5RdWVyeScsXG4gIG5vdEluUXVlcnk6ICckbm90SW5RdWVyeScsXG4gIGNvbnRhaW5lZEJ5OiAnJGNvbnRhaW5lZEJ5JyxcbiAgY29udGFpbnM6ICckYWxsJyxcbiAgbWF0Y2hlc1JlZ2V4OiAnJHJlZ2V4JyxcbiAgb3B0aW9uczogJyRvcHRpb25zJyxcbiAgdGV4dDogJyR0ZXh0JyxcbiAgc2VhcmNoOiAnJHNlYXJjaCcsXG4gIHRlcm06ICckdGVybScsXG4gIGxhbmd1YWdlOiAnJGxhbmd1YWdlJyxcbiAgY2FzZVNlbnNpdGl2ZTogJyRjYXNlU2Vuc2l0aXZlJyxcbiAgZGlhY3JpdGljU2Vuc2l0aXZlOiAnJGRpYWNyaXRpY1NlbnNpdGl2ZScsXG4gIG5lYXJTcGhlcmU6ICckbmVhclNwaGVyZScsXG4gIG1heERpc3RhbmNlOiAnJG1heERpc3RhbmNlJyxcbiAgbWF4RGlzdGFuY2VJblJhZGlhbnM6ICckbWF4RGlzdGFuY2VJblJhZGlhbnMnLFxuICBtYXhEaXN0YW5jZUluTWlsZXM6ICckbWF4RGlzdGFuY2VJbk1pbGVzJyxcbiAgbWF4RGlzdGFuY2VJbktpbG9tZXRlcnM6ICckbWF4RGlzdGFuY2VJbktpbG9tZXRlcnMnLFxuICB3aXRoaW46ICckd2l0aGluJyxcbiAgYm94OiAnJGJveCcsXG4gIGdlb1dpdGhpbjogJyRnZW9XaXRoaW4nLFxuICBwb2x5Z29uOiAnJHBvbHlnb24nLFxuICBjZW50ZXJTcGhlcmU6ICckY2VudGVyU3BoZXJlJyxcbiAgZ2VvSW50ZXJzZWN0czogJyRnZW9JbnRlcnNlY3RzJyxcbiAgcG9pbnQ6ICckcG9pbnQnLFxufTtcblxuY29uc3QgdHJhbnNmb3JtUXVlcnlDb25zdHJhaW50SW5wdXRUb1BhcnNlID0gKFxuICBjb25zdHJhaW50cyxcbiAgcGFyZW50RmllbGROYW1lLFxuICBjbGFzc05hbWUsXG4gIHBhcmVudENvbnN0cmFpbnRzLFxuICBwYXJzZUNsYXNzZXNcbikgPT4ge1xuICBjb25zdCBmaWVsZHMgPSBwYXJzZUNsYXNzZXMuZmluZChcbiAgICBwYXJzZUNsYXNzID0+IHBhcnNlQ2xhc3MuY2xhc3NOYW1lID09PSBjbGFzc05hbWVcbiAgKS5maWVsZHM7XG4gIGlmIChwYXJlbnRGaWVsZE5hbWUgPT09ICdpZCcgJiYgY2xhc3NOYW1lKSB7XG4gICAgT2JqZWN0LmtleXMoY29uc3RyYWludHMpLmZvckVhY2goY29uc3RyYWludE5hbWUgPT4ge1xuICAgICAgY29uc3QgY29uc3RyYWludFZhbHVlID0gY29uc3RyYWludHNbY29uc3RyYWludE5hbWVdO1xuICAgICAgaWYgKHR5cGVvZiBjb25zdHJhaW50VmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnN0IGdsb2JhbElkT2JqZWN0ID0gZnJvbUdsb2JhbElkKGNvbnN0cmFpbnRWYWx1ZSk7XG5cbiAgICAgICAgaWYgKGdsb2JhbElkT2JqZWN0LnR5cGUgPT09IGNsYXNzTmFtZSkge1xuICAgICAgICAgIGNvbnN0cmFpbnRzW2NvbnN0cmFpbnROYW1lXSA9IGdsb2JhbElkT2JqZWN0LmlkO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY29uc3RyYWludFZhbHVlKSkge1xuICAgICAgICBjb25zdHJhaW50c1tjb25zdHJhaW50TmFtZV0gPSBjb25zdHJhaW50VmFsdWUubWFwKHZhbHVlID0+IHtcbiAgICAgICAgICBjb25zdCBnbG9iYWxJZE9iamVjdCA9IGZyb21HbG9iYWxJZCh2YWx1ZSk7XG5cbiAgICAgICAgICBpZiAoZ2xvYmFsSWRPYmplY3QudHlwZSA9PT0gY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gZ2xvYmFsSWRPYmplY3QuaWQ7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBwYXJlbnRDb25zdHJhaW50cy5vYmplY3RJZCA9IGNvbnN0cmFpbnRzO1xuICAgIGRlbGV0ZSBwYXJlbnRDb25zdHJhaW50cy5pZDtcbiAgfVxuICBPYmplY3Qua2V5cyhjb25zdHJhaW50cykuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgIGxldCBmaWVsZFZhbHVlID0gY29uc3RyYWludHNbZmllbGROYW1lXTtcbiAgICBpZiAocGFyc2VDb25zdHJhaW50TWFwW2ZpZWxkTmFtZV0pIHtcbiAgICAgIGNvbnN0cmFpbnRzW3BhcnNlQ29uc3RyYWludE1hcFtmaWVsZE5hbWVdXSA9IGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV07XG4gICAgICBkZWxldGUgY29uc3RyYWludHNbZmllbGROYW1lXTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSWYgd2UgaGF2ZSBhIGtleS12YWx1ZSBwYWlyLCB3ZSBuZWVkIHRvIGNoYW5nZSB0aGUgd2F5IHRoZSBjb25zdHJhaW50IGlzIHN0cnVjdHVyZWQuXG4gICAgICpcbiAgICAgKiBFeGFtcGxlOlxuICAgICAqICAgRnJvbTpcbiAgICAgKiAgIHtcbiAgICAgKiAgICAgXCJzb21lRmllbGRcIjoge1xuICAgICAqICAgICAgIFwibGVzc1RoYW5cIjoge1xuICAgICAqICAgICAgICAgXCJrZXlcIjpcImZvby5iYXJcIixcbiAgICAgKiAgICAgICAgIFwidmFsdWVcIjogMTAwXG4gICAgICogICAgICAgfSxcbiAgICAgKiAgICAgICBcImdyZWF0ZXJUaGFuXCI6IHtcbiAgICAgKiAgICAgICAgIFwia2V5XCI6XCJmb28uYmFyXCIsXG4gICAgICogICAgICAgICBcInZhbHVlXCI6IDEwXG4gICAgICogICAgICAgfVxuICAgICAqICAgICB9XG4gICAgICogICB9XG4gICAgICpcbiAgICAgKiAgIFRvOlxuICAgICAqICAge1xuICAgICAqICAgICBcInNvbWVGaWVsZC5mb28uYmFyXCI6IHtcbiAgICAgKiAgICAgICBcIiRsdFwiOiAxMDAsXG4gICAgICogICAgICAgXCIkZ3RcIjogMTBcbiAgICAgKiAgICAgIH1cbiAgICAgKiAgIH1cbiAgICAgKi9cbiAgICBpZiAoXG4gICAgICBmaWVsZFZhbHVlLmtleSAmJlxuICAgICAgZmllbGRWYWx1ZS52YWx1ZSAmJlxuICAgICAgcGFyZW50Q29uc3RyYWludHMgJiZcbiAgICAgIHBhcmVudEZpZWxkTmFtZVxuICAgICkge1xuICAgICAgZGVsZXRlIHBhcmVudENvbnN0cmFpbnRzW3BhcmVudEZpZWxkTmFtZV07XG4gICAgICBwYXJlbnRDb25zdHJhaW50c1tgJHtwYXJlbnRGaWVsZE5hbWV9LiR7ZmllbGRWYWx1ZS5rZXl9YF0gPSB7XG4gICAgICAgIC4uLnBhcmVudENvbnN0cmFpbnRzW2Ake3BhcmVudEZpZWxkTmFtZX0uJHtmaWVsZFZhbHVlLmtleX1gXSxcbiAgICAgICAgW3BhcnNlQ29uc3RyYWludE1hcFtmaWVsZE5hbWVdXTogZmllbGRWYWx1ZS52YWx1ZSxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIGZpZWxkc1twYXJlbnRGaWVsZE5hbWVdICYmXG4gICAgICAoZmllbGRzW3BhcmVudEZpZWxkTmFtZV0udHlwZSA9PT0gJ1BvaW50ZXInIHx8XG4gICAgICAgIGZpZWxkc1twYXJlbnRGaWVsZE5hbWVdLnR5cGUgPT09ICdSZWxhdGlvbicpXG4gICAgKSB7XG4gICAgICBjb25zdCB7IHRhcmdldENsYXNzIH0gPSBmaWVsZHNbcGFyZW50RmllbGROYW1lXTtcbiAgICAgIGlmIChmaWVsZE5hbWUgPT09ICdleGlzdHMnKSB7XG4gICAgICAgIGlmIChmaWVsZHNbcGFyZW50RmllbGROYW1lXS50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgICAgY29uc3Qgd2hlcmVUYXJnZXQgPSBmaWVsZFZhbHVlID8gJ3doZXJlJyA6ICdub3RXaGVyZSc7XG4gICAgICAgICAgaWYgKGNvbnN0cmFpbnRzW3doZXJlVGFyZ2V0XSkge1xuICAgICAgICAgICAgaWYgKGNvbnN0cmFpbnRzW3doZXJlVGFyZ2V0XS5vYmplY3RJZCkge1xuICAgICAgICAgICAgICBjb25zdHJhaW50c1t3aGVyZVRhcmdldF0ub2JqZWN0SWQgPSB7XG4gICAgICAgICAgICAgICAgLi4uY29uc3RyYWludHNbd2hlcmVUYXJnZXRdLm9iamVjdElkLFxuICAgICAgICAgICAgICAgICRleGlzdHM6IGZpZWxkVmFsdWUsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdHJhaW50c1t3aGVyZVRhcmdldF0ub2JqZWN0SWQgPSB7XG4gICAgICAgICAgICAgICAgJGV4aXN0czogZmllbGRWYWx1ZSxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcGFyc2VXaGVyZVRhcmdldCA9IGZpZWxkVmFsdWUgPyAnJGluUXVlcnknIDogJyRub3RJblF1ZXJ5JztcbiAgICAgICAgICAgIHBhcmVudENvbnN0cmFpbnRzW3BhcmVudEZpZWxkTmFtZV1bcGFyc2VXaGVyZVRhcmdldF0gPSB7XG4gICAgICAgICAgICAgIHdoZXJlOiB7IG9iamVjdElkOiB7ICRleGlzdHM6IHRydWUgfSB9LFxuICAgICAgICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZGVsZXRlIGNvbnN0cmFpbnRzLiRleGlzdHM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGFyZW50Q29uc3RyYWludHNbcGFyZW50RmllbGROYW1lXS4kZXhpc3RzID0gZmllbGRWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzd2l0Y2ggKGZpZWxkTmFtZSkge1xuICAgICAgICBjYXNlICdoYXZlJzpcbiAgICAgICAgICBwYXJlbnRDb25zdHJhaW50c1twYXJlbnRGaWVsZE5hbWVdLiRpblF1ZXJ5ID0ge1xuICAgICAgICAgICAgd2hlcmU6IGZpZWxkVmFsdWUsXG4gICAgICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UoXG4gICAgICAgICAgICBwYXJlbnRDb25zdHJhaW50c1twYXJlbnRGaWVsZE5hbWVdLiRpblF1ZXJ5LndoZXJlLFxuICAgICAgICAgICAgdGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICBwYXJzZUNsYXNzZXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdoYXZlTm90JzpcbiAgICAgICAgICBwYXJlbnRDb25zdHJhaW50c1twYXJlbnRGaWVsZE5hbWVdLiRub3RJblF1ZXJ5ID0ge1xuICAgICAgICAgICAgd2hlcmU6IGZpZWxkVmFsdWUsXG4gICAgICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UoXG4gICAgICAgICAgICBwYXJlbnRDb25zdHJhaW50c1twYXJlbnRGaWVsZE5hbWVdLiRub3RJblF1ZXJ5LndoZXJlLFxuICAgICAgICAgICAgdGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICBwYXJzZUNsYXNzZXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgZGVsZXRlIGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV07XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHN3aXRjaCAoZmllbGROYW1lKSB7XG4gICAgICBjYXNlICdwb2ludCc6XG4gICAgICAgIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ29iamVjdCcgJiYgIWZpZWxkVmFsdWUuX190eXBlKSB7XG4gICAgICAgICAgZmllbGRWYWx1ZS5fX3R5cGUgPSAnR2VvUG9pbnQnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbmVhclNwaGVyZSc6XG4gICAgICAgIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ29iamVjdCcgJiYgIWZpZWxkVmFsdWUuX190eXBlKSB7XG4gICAgICAgICAgZmllbGRWYWx1ZS5fX3R5cGUgPSAnR2VvUG9pbnQnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYm94JzpcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHR5cGVvZiBmaWVsZFZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgIGZpZWxkVmFsdWUuYm90dG9tTGVmdCAmJlxuICAgICAgICAgIGZpZWxkVmFsdWUudXBwZXJSaWdodFxuICAgICAgICApIHtcbiAgICAgICAgICBmaWVsZFZhbHVlID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBfX3R5cGU6ICdHZW9Qb2ludCcsXG4gICAgICAgICAgICAgIC4uLmZpZWxkVmFsdWUuYm90dG9tTGVmdCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIF9fdHlwZTogJ0dlb1BvaW50JyxcbiAgICAgICAgICAgICAgLi4uZmllbGRWYWx1ZS51cHBlclJpZ2h0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdO1xuICAgICAgICAgIGNvbnN0cmFpbnRzW3BhcnNlQ29uc3RyYWludE1hcFtmaWVsZE5hbWVdXSA9IGZpZWxkVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwb2x5Z29uJzpcbiAgICAgICAgaWYgKGZpZWxkVmFsdWUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgIGZpZWxkVmFsdWUuZm9yRWFjaChnZW9Qb2ludCA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGdlb1BvaW50ID09PSAnb2JqZWN0JyAmJiAhZ2VvUG9pbnQuX190eXBlKSB7XG4gICAgICAgICAgICAgIGdlb1BvaW50Ll9fdHlwZSA9ICdHZW9Qb2ludCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdjZW50ZXJTcGhlcmUnOlxuICAgICAgICBpZiAoXG4gICAgICAgICAgdHlwZW9mIGZpZWxkVmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgZmllbGRWYWx1ZS5jZW50ZXIgJiZcbiAgICAgICAgICBmaWVsZFZhbHVlLmRpc3RhbmNlXG4gICAgICAgICkge1xuICAgICAgICAgIGZpZWxkVmFsdWUgPSBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIF9fdHlwZTogJ0dlb1BvaW50JyxcbiAgICAgICAgICAgICAgLi4uZmllbGRWYWx1ZS5jZW50ZXIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmllbGRWYWx1ZS5kaXN0YW5jZSxcbiAgICAgICAgICBdO1xuICAgICAgICAgIGNvbnN0cmFpbnRzW3BhcnNlQ29uc3RyYWludE1hcFtmaWVsZE5hbWVdXSA9IGZpZWxkVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmIChmaWVsZE5hbWUgPT09ICd3aGVyZScpIHtcbiAgICAgICAgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UoZmllbGRWYWx1ZSwgY2xhc3NOYW1lLCBwYXJzZUNsYXNzZXMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJhbnNmb3JtUXVlcnlDb25zdHJhaW50SW5wdXRUb1BhcnNlKFxuICAgICAgICAgIGZpZWxkVmFsdWUsXG4gICAgICAgICAgZmllbGROYW1lLFxuICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICBjb25zdHJhaW50cyxcbiAgICAgICAgICBwYXJzZUNsYXNzZXNcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufTtcblxuY29uc3QgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UgPSAoY29uc3RyYWludHMsIGNsYXNzTmFtZSwgcGFyc2VDbGFzc2VzKSA9PiB7XG4gIGlmICghY29uc3RyYWludHMgfHwgdHlwZW9mIGNvbnN0cmFpbnRzICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIE9iamVjdC5rZXlzKGNvbnN0cmFpbnRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgY29uc3QgZmllbGRWYWx1ZSA9IGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV07XG5cbiAgICBpZiAocGFyc2VRdWVyeU1hcFtmaWVsZE5hbWVdKSB7XG4gICAgICBkZWxldGUgY29uc3RyYWludHNbZmllbGROYW1lXTtcbiAgICAgIGZpZWxkTmFtZSA9IHBhcnNlUXVlcnlNYXBbZmllbGROYW1lXTtcbiAgICAgIGNvbnN0cmFpbnRzW2ZpZWxkTmFtZV0gPSBmaWVsZFZhbHVlO1xuICAgICAgZmllbGRWYWx1ZS5mb3JFYWNoKGZpZWxkVmFsdWVJdGVtID0+IHtcbiAgICAgICAgdHJhbnNmb3JtUXVlcnlJbnB1dFRvUGFyc2UoZmllbGRWYWx1ZUl0ZW0sIGNsYXNzTmFtZSwgcGFyc2VDbGFzc2VzKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmFuc2Zvcm1RdWVyeUNvbnN0cmFpbnRJbnB1dFRvUGFyc2UoXG4gICAgICAgIGZpZWxkVmFsdWUsXG4gICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICBjb25zdHJhaW50cyxcbiAgICAgICAgcGFyc2VDbGFzc2VzXG4gICAgICApO1xuICAgIH1cbiAgfSk7XG59O1xuXG5leHBvcnQgeyB0cmFuc2Zvcm1RdWVyeUNvbnN0cmFpbnRJbnB1dFRvUGFyc2UsIHRyYW5zZm9ybVF1ZXJ5SW5wdXRUb1BhcnNlIH07XG4iXX0= \ 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..b7ab9d6099 --- /dev/null +++ b/lib/LiveQuery/ParseWebSocketServer.js @@ -0,0 +1,80 @@ +"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 => { + ws.on('error', error => { + _logger.default.error(error.message); + + _logger.default.error(JSON.stringify(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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VXZWJTb2NrZXRTZXJ2ZXIuanMiXSwibmFtZXMiOlsiUGFyc2VXZWJTb2NrZXRTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsInNlcnZlciIsIm9uQ29ubmVjdCIsImNvbmZpZyIsIndzcyIsIndzc0FkYXB0ZXIiLCJXU0FkYXB0ZXIiLCJvbkxpc3RlbiIsImxvZ2dlciIsImluZm8iLCJvbkNvbm5lY3Rpb24iLCJ3cyIsIm9uIiwiZXJyb3IiLCJtZXNzYWdlIiwiSlNPTiIsInN0cmluZ2lmeSIsIlBhcnNlV2ViU29ja2V0IiwicGluZ0ludGVydmFsSWQiLCJzZXRJbnRlcnZhbCIsInJlYWR5U3RhdGUiLCJPUEVOIiwicGluZyIsImNsZWFySW50ZXJ2YWwiLCJ3ZWJzb2NrZXRUaW1lb3V0Iiwib25FcnJvciIsInN0YXJ0IiwiY2xvc2UiLCJldmVudHMiLCJFdmVudEVtaXR0ZXIiLCJvbm1lc3NhZ2UiLCJyZXF1ZXN0IiwiZW1pdCIsImRhdGEiLCJvbmNsb3NlIiwic2VuZCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsb0JBQU4sQ0FBMkI7QUFHaENDLEVBQUFBLFdBQVcsQ0FBQ0MsTUFBRCxFQUFjQyxTQUFkLEVBQW1DQyxNQUFuQyxFQUEyQztBQUNwREEsSUFBQUEsTUFBTSxDQUFDRixNQUFQLEdBQWdCQSxNQUFoQjtBQUNBLFVBQU1HLEdBQUcsR0FBRyxnQ0FBWUQsTUFBTSxDQUFDRSxVQUFuQixFQUErQkMsb0JBQS9CLEVBQTBDSCxNQUExQyxDQUFaOztBQUNBQyxJQUFBQSxHQUFHLENBQUNHLFFBQUosR0FBZSxNQUFNO0FBQ25CQyxzQkFBT0MsSUFBUCxDQUFZLHVDQUFaO0FBQ0QsS0FGRDs7QUFHQUwsSUFBQUEsR0FBRyxDQUFDTSxZQUFKLEdBQW1CQyxFQUFFLElBQUk7QUFDdkJBLE1BQUFBLEVBQUUsQ0FBQ0MsRUFBSCxDQUFNLE9BQU4sRUFBZUMsS0FBSyxJQUFJO0FBQ3RCTCx3QkFBT0ssS0FBUCxDQUFhQSxLQUFLLENBQUNDLE9BQW5COztBQUNBTix3QkFBT0ssS0FBUCxDQUFhRSxJQUFJLENBQUNDLFNBQUwsQ0FBZUwsRUFBZixDQUFiO0FBQ0QsT0FIRDtBQUlBVCxNQUFBQSxTQUFTLENBQUMsSUFBSWUsY0FBSixDQUFtQk4sRUFBbkIsQ0FBRCxDQUFULENBTHVCLENBTXZCOztBQUNBLFlBQU1PLGNBQWMsR0FBR0MsV0FBVyxDQUFDLE1BQU07QUFDdkMsWUFBSVIsRUFBRSxDQUFDUyxVQUFILElBQWlCVCxFQUFFLENBQUNVLElBQXhCLEVBQThCO0FBQzVCVixVQUFBQSxFQUFFLENBQUNXLElBQUg7QUFDRCxTQUZELE1BRU87QUFDTEMsVUFBQUEsYUFBYSxDQUFDTCxjQUFELENBQWI7QUFDRDtBQUNGLE9BTmlDLEVBTS9CZixNQUFNLENBQUNxQixnQkFBUCxJQUEyQixLQUFLLElBTkQsQ0FBbEM7QUFPRCxLQWREOztBQWVBcEIsSUFBQUEsR0FBRyxDQUFDcUIsT0FBSixHQUFjWixLQUFLLElBQUk7QUFDckJMLHNCQUFPSyxLQUFQLENBQWFBLEtBQWI7QUFDRCxLQUZEOztBQUdBVCxJQUFBQSxHQUFHLENBQUNzQixLQUFKO0FBQ0EsU0FBS3pCLE1BQUwsR0FBY0csR0FBZDtBQUNEOztBQUVEdUIsRUFBQUEsS0FBSyxHQUFHO0FBQ04sUUFBSSxLQUFLMUIsTUFBTCxJQUFlLEtBQUtBLE1BQUwsQ0FBWTBCLEtBQS9CLEVBQXNDO0FBQ3BDLFdBQUsxQixNQUFMLENBQVkwQixLQUFaO0FBQ0Q7QUFDRjs7QUFuQytCOzs7O0FBc0MzQixNQUFNVixjQUFOLFNBQTZCVyxnQkFBT0MsWUFBcEMsQ0FBaUQ7QUFHdEQ3QixFQUFBQSxXQUFXLENBQUNXLEVBQUQsRUFBVTtBQUNuQjs7QUFDQUEsSUFBQUEsRUFBRSxDQUFDbUIsU0FBSCxHQUFlQyxPQUFPLElBQ3BCLEtBQUtDLElBQUwsQ0FBVSxTQUFWLEVBQXFCRCxPQUFPLElBQUlBLE9BQU8sQ0FBQ0UsSUFBbkIsR0FBMEJGLE9BQU8sQ0FBQ0UsSUFBbEMsR0FBeUNGLE9BQTlELENBREY7O0FBRUFwQixJQUFBQSxFQUFFLENBQUN1QixPQUFILEdBQWEsTUFBTSxLQUFLRixJQUFMLENBQVUsWUFBVixDQUFuQjs7QUFDQSxTQUFLckIsRUFBTCxHQUFVQSxFQUFWO0FBQ0Q7O0FBRUR3QixFQUFBQSxJQUFJLENBQUNyQixPQUFELEVBQXFCO0FBQ3ZCLFNBQUtILEVBQUwsQ0FBUXdCLElBQVIsQ0FBYXJCLE9BQWI7QUFDRDs7QUFicUQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBsb2FkQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0FkYXB0ZXJMb2FkZXInO1xuaW1wb3J0IHsgV1NBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvV2ViU29ja2V0U2VydmVyL1dTQWRhcHRlcic7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgZXZlbnRzIGZyb20gJ2V2ZW50cyc7XG5cbmV4cG9ydCBjbGFzcyBQYXJzZVdlYlNvY2tldFNlcnZlciB7XG4gIHNlcnZlcjogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcjogYW55LCBvbkNvbm5lY3Q6IEZ1bmN0aW9uLCBjb25maWcpIHtcbiAgICBjb25maWcuc2VydmVyID0gc2VydmVyO1xuICAgIGNvbnN0IHdzcyA9IGxvYWRBZGFwdGVyKGNvbmZpZy53c3NBZGFwdGVyLCBXU0FkYXB0ZXIsIGNvbmZpZyk7XG4gICAgd3NzLm9uTGlzdGVuID0gKCkgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oJ1BhcnNlIExpdmVRdWVyeSBTZXJ2ZXIgc3RhcnRzIHJ1bm5pbmcnKTtcbiAgICB9O1xuICAgIHdzcy5vbkNvbm5lY3Rpb24gPSB3cyA9PiB7XG4gICAgICB3cy5vbignZXJyb3InLCBlcnJvciA9PiB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgbG9nZ2VyLmVycm9yKEpTT04uc3RyaW5naWZ5KHdzKSk7XG4gICAgICB9KTtcbiAgICAgIG9uQ29ubmVjdChuZXcgUGFyc2VXZWJTb2NrZXQod3MpKTtcbiAgICAgIC8vIFNlbmQgcGluZyB0byBjbGllbnQgcGVyaW9kaWNhbGx5XG4gICAgICBjb25zdCBwaW5nSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT0gd3MuT1BFTikge1xuICAgICAgICAgIHdzLnBpbmcoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbElkKTtcbiAgICAgICAgfVxuICAgICAgfSwgY29uZmlnLndlYnNvY2tldFRpbWVvdXQgfHwgMTAgKiAxMDAwKTtcbiAgICB9O1xuICAgIHdzcy5vbkVycm9yID0gZXJyb3IgPT4ge1xuICAgICAgbG9nZ2VyLmVycm9yKGVycm9yKTtcbiAgICB9O1xuICAgIHdzcy5zdGFydCgpO1xuICAgIHRoaXMuc2VydmVyID0gd3NzO1xuICB9XG5cbiAgY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMuc2VydmVyICYmIHRoaXMuc2VydmVyLmNsb3NlKSB7XG4gICAgICB0aGlzLnNlcnZlci5jbG9zZSgpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUGFyc2VXZWJTb2NrZXQgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgd3M6IGFueTtcblxuICBjb25zdHJ1Y3Rvcih3czogYW55KSB7XG4gICAgc3VwZXIoKTtcbiAgICB3cy5vbm1lc3NhZ2UgPSByZXF1ZXN0ID0+XG4gICAgICB0aGlzLmVtaXQoJ21lc3NhZ2UnLCByZXF1ZXN0ICYmIHJlcXVlc3QuZGF0YSA/IHJlcXVlc3QuZGF0YSA6IHJlcXVlc3QpO1xuICAgIHdzLm9uY2xvc2UgPSAoKSA9PiB0aGlzLmVtaXQoJ2Rpc2Nvbm5lY3QnKTtcbiAgICB0aGlzLndzID0gd3M7XG4gIH1cblxuICBzZW5kKG1lc3NhZ2U6IGFueSk6IHZvaWQge1xuICAgIHRoaXMud3Muc2VuZChtZXNzYWdlKTtcbiAgfVxufVxuIl19 \ 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..32dd19e35a --- /dev/null +++ b/lib/Options/Definitions.js @@ -0,0 +1,503 @@ +"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 + }, + allowCustomObjectId: { + env: 'PARSE_SERVER_ALLOW_CUSTOM_OBJECT_ID', + help: 'Enable (or disable) custom objectId', + action: parsers.booleanParser, + default: false + }, + 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') + }, + maxLogFiles: { + env: 'PARSE_SERVER_MAX_LOG_FILES', + help: "Maximum number of logs to keep. If not set, no logs will be removed. This can be a number of files or number of days. If using days, add 'd' as the suffix. (default: null)", + action: parsers.objectParser + }, + 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 + }, + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL0RlZmluaXRpb25zLmpzIl0sIm5hbWVzIjpbInBhcnNlcnMiLCJyZXF1aXJlIiwibW9kdWxlIiwiZXhwb3J0cyIsIlBhcnNlU2VydmVyT3B0aW9ucyIsImFjY291bnRMb2Nrb3V0IiwiZW52IiwiaGVscCIsImFjdGlvbiIsIm9iamVjdFBhcnNlciIsImFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiIsImJvb2xlYW5QYXJzZXIiLCJkZWZhdWx0IiwiYWxsb3dDdXN0b21PYmplY3RJZCIsImFsbG93SGVhZGVycyIsImFycmF5UGFyc2VyIiwiYW5hbHl0aWNzQWRhcHRlciIsIm1vZHVsZU9yT2JqZWN0UGFyc2VyIiwiYXBwSWQiLCJyZXF1aXJlZCIsImFwcE5hbWUiLCJhdXRoIiwiY2FjaGVBZGFwdGVyIiwiY2FjaGVNYXhTaXplIiwibnVtYmVyUGFyc2VyIiwiY2FjaGVUVEwiLCJjbGllbnRLZXkiLCJjbG91ZCIsImNsdXN0ZXIiLCJudW1iZXJPckJvb2xlYW5QYXJzZXIiLCJjb2xsZWN0aW9uUHJlZml4IiwiY3VzdG9tUGFnZXMiLCJkYXRhYmFzZUFkYXB0ZXIiLCJkYXRhYmFzZU9wdGlvbnMiLCJkYXRhYmFzZVVSSSIsImRpcmVjdEFjY2VzcyIsImRvdE5ldEtleSIsImVtYWlsQWRhcHRlciIsImVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uIiwiZW5hYmxlQW5vbnltb3VzVXNlcnMiLCJlbmFibGVFeHByZXNzRXJyb3JIYW5kbGVyIiwiZW5hYmxlU2luZ2xlU2NoZW1hQ2FjaGUiLCJleHBpcmVJbmFjdGl2ZVNlc3Npb25zIiwiZmlsZUtleSIsImZpbGVzQWRhcHRlciIsImdyYXBoUUxQYXRoIiwiZ3JhcGhRTFNjaGVtYSIsImhvc3QiLCJqYXZhc2NyaXB0S2V5IiwianNvbkxvZ3MiLCJsaXZlUXVlcnkiLCJsaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIiwibG9nZ2VyQWRhcHRlciIsImxvZ0xldmVsIiwibG9nc0ZvbGRlciIsIm1hc3RlcktleSIsIm1hc3RlcktleUlwcyIsIm1heExpbWl0IiwibWF4TG9nRmlsZXMiLCJtYXhVcGxvYWRTaXplIiwibWlkZGxld2FyZSIsIm1vdW50R3JhcGhRTCIsIm1vdW50UGF0aCIsIm1vdW50UGxheWdyb3VuZCIsIm9iamVjdElkU2l6ZSIsInBhc3N3b3JkUG9saWN5IiwicGxheWdyb3VuZFBhdGgiLCJwb3J0IiwicHJlc2VydmVGaWxlTmFtZSIsInByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWwiLCJwcm90ZWN0ZWRGaWVsZHMiLCJfVXNlciIsInB1YmxpY1NlcnZlclVSTCIsInB1c2giLCJyZWFkT25seU1hc3RlcktleSIsInJlc3RBUElLZXkiLCJyZXZva2VTZXNzaW9uT25QYXNzd29yZFJlc2V0Iiwic2NoZWR1bGVkUHVzaCIsInNjaGVtYUNhY2hlVFRMIiwic2VydmVyQ2xvc2VDb21wbGV0ZSIsInNlcnZlclN0YXJ0Q29tcGxldGUiLCJzZXJ2ZXJVUkwiLCJzZXNzaW9uTGVuZ3RoIiwic2lsZW50Iiwic3RhcnRMaXZlUXVlcnlTZXJ2ZXIiLCJ1c2VyU2Vuc2l0aXZlRmllbGRzIiwidmVyYm9zZSIsInZlcmlmeVVzZXJFbWFpbHMiLCJ3ZWJob29rS2V5IiwiQ3VzdG9tUGFnZXNPcHRpb25zIiwiY2hvb3NlUGFzc3dvcmQiLCJpbnZhbGlkTGluayIsImludmFsaWRWZXJpZmljYXRpb25MaW5rIiwibGlua1NlbmRGYWlsIiwibGlua1NlbmRTdWNjZXNzIiwicGFyc2VGcmFtZVVSTCIsInBhc3N3b3JkUmVzZXRTdWNjZXNzIiwidmVyaWZ5RW1haWxTdWNjZXNzIiwiTGl2ZVF1ZXJ5T3B0aW9ucyIsImNsYXNzTmFtZXMiLCJwdWJTdWJBZGFwdGVyIiwicmVkaXNPcHRpb25zIiwicmVkaXNVUkwiLCJ3c3NBZGFwdGVyIiwiTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyIsImNhY2hlVGltZW91dCIsImtleVBhaXJzIiwid2Vic29ja2V0VGltZW91dCJdLCJtYXBwaW5ncyI6Ijs7QUFB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eUNBRFE7QUFFYkMsSUFBQUEsSUFBSSxFQUFFLDBCQUZPO0FBR2JDLElBQUFBLE1BQU0sRUFBRVIsT0FBTyxDQUFDaUI7QUFISCxHQWxDdUI7QUF1Q3RDb0YsRUFBQUEsWUFBWSxFQUFFO0FBQ1ovRixJQUFBQSxHQUFHLEVBQUUsdUNBRE87QUFFWkMsSUFBQUEsSUFBSSxFQUFFLHVDQUZNO0FBR1pDLElBQUFBLE1BQU0sRUFBRVIsT0FBTyxDQUFDUztBQUhKLEdBdkN3QjtBQTRDdEM2RixFQUFBQSxRQUFRLEVBQUU7QUFDUmhHLElBQUFBLEdBQUcsRUFBRSxtQ0FERztBQUVSQyxJQUFBQSxJQUFJLEVBQUU7QUFGRSxHQTVDNEI7QUFnRHRDMEUsRUFBQUEsU0FBUyxFQUFFO0FBQ1QzRSxJQUFBQSxHQUFHLEVBQUUsb0NBREk7QUFFVEMsSUFBQUEsSUFBSSxFQUNGO0FBSE8sR0FoRDJCO0FBcUR0Q29HLEVBQUFBLGdCQUFnQixFQUFFO0FBQ2hCckcsSUFBQUEsR0FBRyxFQUFFLDJDQURXO0FBRWhCQyxJQUFBQSxJQUFJLEVBQ0YsOFBBSGM7QUFJaEJDLElBQUFBLE1BQU0sRUFBRVIsT0FBTyxDQUFDd0IsWUFBUixDQUFxQixrQkFBckI7QUFKUSxHQXJEb0I7QUEyRHRDK0UsRUFBQUEsVUFBVSxFQUFFO0FBQ1ZqRyxJQUFBQSxHQUFHLEVBQUUscUNBREs7QUFFVkMsSUFBQUEsSUFBSSxFQUFFLHdDQUZJO0FBR1ZDLElBQUFBLE1BQU0sRUFBRVIsT0FBTyxDQUFDaUI7QUFITjtBQTNEMEIsQ0FBeEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuKioqKiBHRU5FUkFURUQgQ09ERSAqKioqXG5UaGlzIGNvZGUgaGFzIGJlZW4gZ2VuZXJhdGVkIGJ5IHJlc291cmNlcy9idWlsZENvbmZpZ0RlZmluaXRpb25zLmpzXG5EbyBub3QgZWRpdCBtYW51YWxseSwgYnV0IHVwZGF0ZSBPcHRpb25zL2luZGV4LmpzXG4qL1xudmFyIHBhcnNlcnMgPSByZXF1aXJlKCcuL3BhcnNlcnMnKTtcblxubW9kdWxlLmV4cG9ydHMuUGFyc2VTZXJ2ZXJPcHRpb25zID0ge1xuICBhY2NvdW50TG9ja291dDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9BQ0NPVU5UX0xPQ0tPVVQnLFxuICAgIGhlbHA6ICdhY2NvdW50IGxvY2tvdXQgcG9saWN5IGZvciBmYWlsZWQgbG9naW4gYXR0ZW1wdHMnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9BTExPV19DTElFTlRfQ0xBU1NfQ1JFQVRJT04nLFxuICAgIGhlbHA6ICdFbmFibGUgKG9yIGRpc2FibGUpIGNsaWVudCBjbGFzcyBjcmVhdGlvbiwgZGVmYXVsdHMgdG8gdHJ1ZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgYWxsb3dDdXN0b21PYmplY3RJZDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9BTExPV19DVVNUT01fT0JKRUNUX0lEJyxcbiAgICBoZWxwOiAnRW5hYmxlIChvciBkaXNhYmxlKSBjdXN0b20gb2JqZWN0SWQnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBhbGxvd0hlYWRlcnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQUxMT1dfSEVBREVSUycsXG4gICAgaGVscDogJ0FkZCBoZWFkZXJzIHRvIEFjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5hcnJheVBhcnNlcixcbiAgfSxcbiAgYW5hbHl0aWNzQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9BTkFMWVRJQ1NfQURBUFRFUicsXG4gICAgaGVscDogJ0FkYXB0ZXIgbW9kdWxlIGZvciB0aGUgYW5hbHl0aWNzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIGFwcElkOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0FQUExJQ0FUSU9OX0lEJyxcbiAgICBoZWxwOiAnWW91ciBQYXJzZSBBcHBsaWNhdGlvbiBJRCcsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0sXG4gIGFwcE5hbWU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQVBQX05BTUUnLFxuICAgIGhlbHA6ICdTZXRzIHRoZSBhcHAgbmFtZScsXG4gIH0sXG4gIGF1dGg6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQVVUSF9QUk9WSURFUlMnLFxuICAgIGhlbHA6XG4gICAgICAnQ29uZmlndXJhdGlvbiBmb3IgeW91ciBhdXRoZW50aWNhdGlvbiBwcm92aWRlcnMsIGFzIHN0cmluZ2lmaWVkIEpTT04uIFNlZSBodHRwOi8vZG9jcy5wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvZ3VpZGUvI29hdXRoLWFuZC0zcmQtcGFydHktYXV0aGVudGljYXRpb24nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGNhY2hlQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DQUNIRV9BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBjYWNoZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICB9LFxuICBjYWNoZU1heFNpemU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ0FDSEVfTUFYX1NJWkUnLFxuICAgIGhlbHA6ICdTZXRzIHRoZSBtYXhpbXVtIHNpemUgZm9yIHRoZSBpbiBtZW1vcnkgY2FjaGUsIGRlZmF1bHRzIHRvIDEwMDAwJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubnVtYmVyUGFyc2VyKCdjYWNoZU1heFNpemUnKSxcbiAgICBkZWZhdWx0OiAxMDAwMCxcbiAgfSxcbiAgY2FjaGVUVEw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ0FDSEVfVFRMJyxcbiAgICBoZWxwOlxuICAgICAgJ1NldHMgdGhlIFRUTCBmb3IgdGhlIGluIG1lbW9yeSBjYWNoZSAoaW4gbXMpLCBkZWZhdWx0cyB0byA1MDAwICg1IHNlY29uZHMpJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubnVtYmVyUGFyc2VyKCdjYWNoZVRUTCcpLFxuICAgIGRlZmF1bHQ6IDUwMDAsXG4gIH0sXG4gIGNsaWVudEtleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DTElFTlRfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciBpT1MsIE1hY09TLCB0dk9TIGNsaWVudHMnLFxuICB9LFxuICBjbG91ZDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DTE9VRCcsXG4gICAgaGVscDogJ0Z1bGwgcGF0aCB0byB5b3VyIGNsb3VkIGNvZGUgbWFpbi5qcycsXG4gIH0sXG4gIGNsdXN0ZXI6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ0xVU1RFUicsXG4gICAgaGVscDpcbiAgICAgICdSdW4gd2l0aCBjbHVzdGVyLCBvcHRpb25hbGx5IHNldCB0aGUgbnVtYmVyIG9mIHByb2Nlc3NlcyBkZWZhdWx0IHRvIG9zLmNwdXMoKS5sZW5ndGgnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJPckJvb2xlYW5QYXJzZXIsXG4gIH0sXG4gIGNvbGxlY3Rpb25QcmVmaXg6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ09MTEVDVElPTl9QUkVGSVgnLFxuICAgIGhlbHA6ICdBIGNvbGxlY3Rpb24gcHJlZml4IGZvciB0aGUgY2xhc3NlcycsXG4gICAgZGVmYXVsdDogJycsXG4gIH0sXG4gIGN1c3RvbVBhZ2VzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFUycsXG4gICAgaGVscDogJ2N1c3RvbSBwYWdlcyBmb3IgcGFzc3dvcmQgdmFsaWRhdGlvbiBhbmQgcmVzZXQnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gICAgZGVmYXVsdDoge30sXG4gIH0sXG4gIGRhdGFiYXNlQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9EQVRBQkFTRV9BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBkYXRhYmFzZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICB9LFxuICBkYXRhYmFzZU9wdGlvbnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfREFUQUJBU0VfT1BUSU9OUycsXG4gICAgaGVscDogJ09wdGlvbnMgdG8gcGFzcyB0byB0aGUgbW9uZ29kYiBjbGllbnQnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGRhdGFiYXNlVVJJOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0RBVEFCQVNFX1VSSScsXG4gICAgaGVscDpcbiAgICAgICdUaGUgZnVsbCBVUkkgdG8geW91ciBkYXRhYmFzZS4gU3VwcG9ydGVkIGRhdGFiYXNlcyBhcmUgbW9uZ29kYiBvciBwb3N0Z3Jlcy4nLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgIGRlZmF1bHQ6ICdtb25nb2RiOi8vbG9jYWxob3N0OjI3MDE3L3BhcnNlJyxcbiAgfSxcbiAgZGlyZWN0QWNjZXNzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0VOQUJMRV9FWFBFUklNRU5UQUxfRElSRUNUX0FDQ0VTUycsXG4gICAgaGVscDpcbiAgICAgICdSZXBsYWNlIEhUVFAgSW50ZXJmYWNlIHdoZW4gdXNpbmcgSlMgU0RLIGluIGN1cnJlbnQgbm9kZSBydW50aW1lLCBkZWZhdWx0cyB0byBmYWxzZS4gQ2F1dGlvbiwgdGhpcyBpcyBhbiBleHBlcmltZW50YWwgZmVhdHVyZSB0aGF0IG1heSBub3QgYmUgYXBwcm9wcmlhdGUgZm9yIHByb2R1Y3Rpb24uJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgZG90TmV0S2V5OiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0RPVF9ORVRfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciBVbml0eSBhbmQgLk5ldCBTREsnLFxuICB9LFxuICBlbWFpbEFkYXB0ZXI6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU1BSUxfQURBUFRFUicsXG4gICAgaGVscDogJ0FkYXB0ZXIgbW9kdWxlIGZvciBlbWFpbCBzZW5kaW5nJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0VNQUlMX1ZFUklGWV9UT0tFTl9WQUxJRElUWV9EVVJBVElPTicsXG4gICAgaGVscDogJ0VtYWlsIHZlcmlmaWNhdGlvbiB0b2tlbiB2YWxpZGl0eSBkdXJhdGlvbiwgaW4gc2Vjb25kcycsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm51bWJlclBhcnNlcignZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24nKSxcbiAgfSxcbiAgZW5hYmxlQW5vbnltb3VzVXNlcnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU5BQkxFX0FOT05fVVNFUlMnLFxuICAgIGhlbHA6ICdFbmFibGUgKG9yIGRpc2FibGUpIGFub24gdXNlcnMsIGRlZmF1bHRzIHRvIHRydWUnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IHRydWUsXG4gIH0sXG4gIGVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXI6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU5BQkxFX0VYUFJFU1NfRVJST1JfSEFORExFUicsXG4gICAgaGVscDogJ0VuYWJsZXMgdGhlIGRlZmF1bHQgZXhwcmVzcyBlcnJvciBoYW5kbGVyIGZvciBhbGwgZXJyb3JzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgZW5hYmxlU2luZ2xlU2NoZW1hQ2FjaGU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfRU5BQkxFX1NJTkdMRV9TQ0hFTUFfQ0FDSEUnLFxuICAgIGhlbHA6XG4gICAgICAnVXNlIGEgc2luZ2xlIHNjaGVtYSBjYWNoZSBzaGFyZWQgYWNyb3NzIHJlcXVlc3RzLiBSZWR1Y2VzIG51bWJlciBvZiBxdWVyaWVzIG1hZGUgdG8gX1NDSEVNQSwgZGVmYXVsdHMgdG8gZmFsc2UsIGkuZS4gdW5pcXVlIHNjaGVtYSBjYWNoZSBwZXIgcmVxdWVzdC4nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBleHBpcmVJbmFjdGl2ZVNlc3Npb25zOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0VYUElSRV9JTkFDVElWRV9TRVNTSU9OUycsXG4gICAgaGVscDpcbiAgICAgICdTZXRzIHdldGhlciB3ZSBzaG91bGQgZXhwaXJlIHRoZSBpbmFjdGl2ZSBzZXNzaW9ucywgZGVmYXVsdHMgdG8gdHJ1ZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgZmlsZUtleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9GSUxFX0tFWScsXG4gICAgaGVscDogJ0tleSBmb3IgeW91ciBmaWxlcycsXG4gIH0sXG4gIGZpbGVzQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9GSUxFU19BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBmaWxlcyBzdWItc3lzdGVtJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIGdyYXBoUUxQYXRoOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0dSQVBIUUxfUEFUSCcsXG4gICAgaGVscDogJ01vdW50IHBhdGggZm9yIHRoZSBHcmFwaFFMIGVuZHBvaW50LCBkZWZhdWx0cyB0byAvZ3JhcGhxbCcsXG4gICAgZGVmYXVsdDogJy9ncmFwaHFsJyxcbiAgfSxcbiAgZ3JhcGhRTFNjaGVtYToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9HUkFQSF9RTFNDSEVNQScsXG4gICAgaGVscDogJ0Z1bGwgcGF0aCB0byB5b3VyIEdyYXBoUUwgY3VzdG9tIHNjaGVtYS5ncmFwaHFsIGZpbGUnLFxuICB9LFxuICBob3N0OiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0hPU1QnLFxuICAgIGhlbHA6ICdUaGUgaG9zdCB0byBzZXJ2ZSBQYXJzZVNlcnZlciBvbiwgZGVmYXVsdHMgdG8gMC4wLjAuMCcsXG4gICAgZGVmYXVsdDogJzAuMC4wLjAnLFxuICB9LFxuICBqYXZhc2NyaXB0S2V5OiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0pBVkFTQ1JJUFRfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciB0aGUgSmF2YXNjcmlwdCBTREsnLFxuICB9LFxuICBqc29uTG9nczoge1xuICAgIGVudjogJ0pTT05fTE9HUycsXG4gICAgaGVscDogJ0xvZyBhcyBzdHJ1Y3R1cmVkIEpTT04gb2JqZWN0cycsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gIH0sXG4gIGxpdmVRdWVyeToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFX1FVRVJZJyxcbiAgICBoZWxwOiBcInBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSBjb25maWd1cmF0aW9uIG9iamVjdFwiLFxuICAgIGFjdGlvbjogcGFyc2Vycy5vYmplY3RQYXJzZXIsXG4gIH0sXG4gIGxpdmVRdWVyeVNlcnZlck9wdGlvbnM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTElWRV9RVUVSWV9TRVJWRVJfT1BUSU9OUycsXG4gICAgaGVscDpcbiAgICAgICdMaXZlIHF1ZXJ5IHNlcnZlciBjb25maWd1cmF0aW9uIG9wdGlvbnMgKHdpbGwgc3RhcnQgdGhlIGxpdmVRdWVyeSBzZXJ2ZXIpJyxcbiAgICBhY3Rpb246IHBhcnNlcnMub2JqZWN0UGFyc2VyLFxuICB9LFxuICBsb2dnZXJBZGFwdGVyOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0xPR0dFUl9BREFQVEVSJyxcbiAgICBoZWxwOiAnQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBsb2dnaW5nIHN1Yi1zeXN0ZW0nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5tb2R1bGVPck9iamVjdFBhcnNlcixcbiAgfSxcbiAgbG9nTGV2ZWw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTE9HX0xFVkVMJyxcbiAgICBoZWxwOiAnU2V0cyB0aGUgbGV2ZWwgZm9yIGxvZ3MnLFxuICB9LFxuICBsb2dzRm9sZGVyOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0xPR1NfRk9MREVSJyxcbiAgICBoZWxwOlxuICAgICAgXCJGb2xkZXIgZm9yIHRoZSBsb2dzIChkZWZhdWx0cyB0byAnLi9sb2dzJyk7IHNldCB0byBudWxsIHRvIGRpc2FibGUgZmlsZSBiYXNlZCBsb2dnaW5nXCIsXG4gICAgZGVmYXVsdDogJy4vbG9ncycsXG4gIH0sXG4gIG1hc3RlcktleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9NQVNURVJfS0VZJyxcbiAgICBoZWxwOiAnWW91ciBQYXJzZSBNYXN0ZXIgS2V5JyxcbiAgICByZXF1aXJlZDogdHJ1ZSxcbiAgfSxcbiAgbWFzdGVyS2V5SXBzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX01BU1RFUl9LRVlfSVBTJyxcbiAgICBoZWxwOlxuICAgICAgJ1Jlc3RyaWN0IG1hc3RlcktleSB0byBiZSB1c2VkIGJ5IG9ubHkgdGhlc2UgaXBzLCBkZWZhdWx0cyB0byBbXSAoYWxsb3cgYWxsIGlwcyknLFxuICAgIGFjdGlvbjogcGFyc2Vycy5hcnJheVBhcnNlcixcbiAgICBkZWZhdWx0OiBbXSxcbiAgfSxcbiAgbWF4TGltaXQ6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTUFYX0xJTUlUJyxcbiAgICBoZWxwOiAnTWF4IHZhbHVlIGZvciBsaW1pdCBvcHRpb24gb24gcXVlcmllcywgZGVmYXVsdHMgdG8gdW5saW1pdGVkJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubnVtYmVyUGFyc2VyKCdtYXhMaW1pdCcpLFxuICB9LFxuICBtYXhMb2dGaWxlczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9NQVhfTE9HX0ZJTEVTJyxcbiAgICBoZWxwOlxuICAgICAgXCJNYXhpbXVtIG51bWJlciBvZiBsb2dzIHRvIGtlZXAuIElmIG5vdCBzZXQsIG5vIGxvZ3Mgd2lsbCBiZSByZW1vdmVkLiBUaGlzIGNhbiBiZSBhIG51bWJlciBvZiBmaWxlcyBvciBudW1iZXIgb2YgZGF5cy4gSWYgdXNpbmcgZGF5cywgYWRkICdkJyBhcyB0aGUgc3VmZml4LiAoZGVmYXVsdDogbnVsbClcIixcbiAgICBhY3Rpb246IHBhcnNlcnMub2JqZWN0UGFyc2VyLFxuICB9LFxuICBtYXhVcGxvYWRTaXplOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX01BWF9VUExPQURfU0laRScsXG4gICAgaGVscDogJ01heCBmaWxlIHNpemUgZm9yIHVwbG9hZHMsIGRlZmF1bHRzIHRvIDIwbWInLFxuICAgIGRlZmF1bHQ6ICcyMG1iJyxcbiAgfSxcbiAgbWlkZGxld2FyZToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9NSURETEVXQVJFJyxcbiAgICBoZWxwOiAnbWlkZGxld2FyZSBmb3IgZXhwcmVzcyBzZXJ2ZXIsIGNhbiBiZSBzdHJpbmcgb3IgZnVuY3Rpb24nLFxuICB9LFxuICBtb3VudEdyYXBoUUw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTU9VTlRfR1JBUEhRTCcsXG4gICAgaGVscDogJ01vdW50cyB0aGUgR3JhcGhRTCBlbmRwb2ludCcsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIG1vdW50UGF0aDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9NT1VOVF9QQVRIJyxcbiAgICBoZWxwOiAnTW91bnQgcGF0aCBmb3IgdGhlIHNlcnZlciwgZGVmYXVsdHMgdG8gL3BhcnNlJyxcbiAgICBkZWZhdWx0OiAnL3BhcnNlJyxcbiAgfSxcbiAgbW91bnRQbGF5Z3JvdW5kOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX01PVU5UX1BMQVlHUk9VTkQnLFxuICAgIGhlbHA6ICdNb3VudHMgdGhlIEdyYXBoUUwgUGxheWdyb3VuZCAtIG5ldmVyIHVzZSB0aGlzIG9wdGlvbiBpbiBwcm9kdWN0aW9uJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgb2JqZWN0SWRTaXplOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX09CSkVDVF9JRF9TSVpFJyxcbiAgICBoZWxwOiBcIlNldHMgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzIGluIGdlbmVyYXRlZCBvYmplY3QgaWQncywgZGVmYXVsdCAxMFwiLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJQYXJzZXIoJ29iamVjdElkU2l6ZScpLFxuICAgIGRlZmF1bHQ6IDEwLFxuICB9LFxuICBwYXNzd29yZFBvbGljeToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9QQVNTV09SRF9QT0xJQ1knLFxuICAgIGhlbHA6ICdQYXNzd29yZCBwb2xpY3kgZm9yIGVuZm9yY2luZyBwYXNzd29yZCByZWxhdGVkIHJ1bGVzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMub2JqZWN0UGFyc2VyLFxuICB9LFxuICBwbGF5Z3JvdW5kUGF0aDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9QTEFZR1JPVU5EX1BBVEgnLFxuICAgIGhlbHA6ICdNb3VudCBwYXRoIGZvciB0aGUgR3JhcGhRTCBQbGF5Z3JvdW5kLCBkZWZhdWx0cyB0byAvcGxheWdyb3VuZCcsXG4gICAgZGVmYXVsdDogJy9wbGF5Z3JvdW5kJyxcbiAgfSxcbiAgcG9ydDoge1xuICAgIGVudjogJ1BPUlQnLFxuICAgIGhlbHA6ICdUaGUgcG9ydCB0byBydW4gdGhlIFBhcnNlU2VydmVyLCBkZWZhdWx0cyB0byAxMzM3LicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm51bWJlclBhcnNlcigncG9ydCcpLFxuICAgIGRlZmF1bHQ6IDEzMzcsXG4gIH0sXG4gIHByZXNlcnZlRmlsZU5hbWU6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfUFJFU0VSVkVfRklMRV9OQU1FJyxcbiAgICBoZWxwOiAnRW5hYmxlIChvciBkaXNhYmxlKSB0aGUgYWRkaXRpb24gb2YgYSB1bmlxdWUgaGFzaCB0byB0aGUgZmlsZSBuYW1lcycsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIHByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfUFJFVkVOVF9MT0dJTl9XSVRIX1VOVkVSSUZJRURfRU1BSUwnLFxuICAgIGhlbHA6XG4gICAgICAnUHJldmVudCB1c2VyIGZyb20gbG9naW4gaWYgZW1haWwgaXMgbm90IHZlcmlmaWVkIGFuZCBQQVJTRV9TRVJWRVJfVkVSSUZZX1VTRVJfRU1BSUxTIGlzIHRydWUsIGRlZmF1bHRzIHRvIGZhbHNlJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgcHJvdGVjdGVkRmllbGRzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1BST1RFQ1RFRF9GSUVMRFMnLFxuICAgIGhlbHA6XG4gICAgICAnUHJvdGVjdGVkIGZpZWxkcyB0aGF0IHNob3VsZCBiZSB0cmVhdGVkIHdpdGggZXh0cmEgc2VjdXJpdHkgd2hlbiBmZXRjaGluZyBkZXRhaWxzLicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm9iamVjdFBhcnNlcixcbiAgICBkZWZhdWx0OiB7XG4gICAgICBfVXNlcjoge1xuICAgICAgICAnKic6IFsnZW1haWwnXSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbiAgcHVibGljU2VydmVyVVJMOiB7XG4gICAgZW52OiAnUEFSU0VfUFVCTElDX1NFUlZFUl9VUkwnLFxuICAgIGhlbHA6ICdQdWJsaWMgVVJMIHRvIHlvdXIgcGFyc2Ugc2VydmVyIHdpdGggaHR0cDovLyBvciBodHRwczovLy4nLFxuICB9LFxuICBwdXNoOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1BVU0gnLFxuICAgIGhlbHA6XG4gICAgICAnQ29uZmlndXJhdGlvbiBmb3IgcHVzaCwgYXMgc3RyaW5naWZpZWQgSlNPTi4gU2VlIGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8jcHVzaC1ub3RpZmljYXRpb25zJyxcbiAgICBhY3Rpb246IHBhcnNlcnMub2JqZWN0UGFyc2VyLFxuICB9LFxuICByZWFkT25seU1hc3RlcktleToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9SRUFEX09OTFlfTUFTVEVSX0tFWScsXG4gICAgaGVscDpcbiAgICAgICdSZWFkLW9ubHkga2V5LCB3aGljaCBoYXMgdGhlIHNhbWUgY2FwYWJpbGl0aWVzIGFzIE1hc3RlcktleSB3aXRob3V0IHdyaXRlcycsXG4gIH0sXG4gIHJlc3RBUElLZXk6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfUkVTVF9BUElfS0VZJyxcbiAgICBoZWxwOiAnS2V5IGZvciBSRVNUIGNhbGxzJyxcbiAgfSxcbiAgcmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9SRVZPS0VfU0VTU0lPTl9PTl9QQVNTV09SRF9SRVNFVCcsXG4gICAgaGVscDpcbiAgICAgIFwiV2hlbiBhIHVzZXIgY2hhbmdlcyB0aGVpciBwYXNzd29yZCwgZWl0aGVyIHRocm91Z2ggdGhlIHJlc2V0IHBhc3N3b3JkIGVtYWlsIG9yIHdoaWxlIGxvZ2dlZCBpbiwgYWxsIHNlc3Npb25zIGFyZSByZXZva2VkIGlmIHRoaXMgaXMgdHJ1ZS4gU2V0IHRvIGZhbHNlIGlmIHlvdSBkb24ndCB3YW50IHRvIHJldm9rZSBzZXNzaW9ucy5cIixcbiAgICBhY3Rpb246IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBkZWZhdWx0OiB0cnVlLFxuICB9LFxuICBzY2hlZHVsZWRQdXNoOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1NDSEVEVUxFRF9QVVNIJyxcbiAgICBoZWxwOiAnQ29uZmlndXJhdGlvbiBmb3IgcHVzaCBzY2hlZHVsaW5nLCBkZWZhdWx0cyB0byBmYWxzZS4nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBzY2hlbWFDYWNoZVRUTDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TQ0hFTUFfQ0FDSEVfVFRMJyxcbiAgICBoZWxwOlxuICAgICAgJ1RoZSBUVEwgZm9yIGNhY2hpbmcgdGhlIHNjaGVtYSBmb3Igb3B0aW1pemluZyByZWFkL3dyaXRlIG9wZXJhdGlvbnMuIFlvdSBzaG91bGQgcHV0IGEgbG9uZyBUVEwgd2hlbiB5b3VyIERCIGlzIGluIHByb2R1Y3Rpb24uIGRlZmF1bHQgdG8gNTAwMDsgc2V0IDAgdG8gZGlzYWJsZS4nLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJQYXJzZXIoJ3NjaGVtYUNhY2hlVFRMJyksXG4gICAgZGVmYXVsdDogNTAwMCxcbiAgfSxcbiAgc2VydmVyQ2xvc2VDb21wbGV0ZToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TRVJWRVJfQ0xPU0VfQ09NUExFVEUnLFxuICAgIGhlbHA6ICdDYWxsYmFjayB3aGVuIHNlcnZlciBoYXMgY2xvc2VkJyxcbiAgfSxcbiAgc2VydmVyU3RhcnRDb21wbGV0ZToge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TRVJWRVJfU1RBUlRfQ09NUExFVEUnLFxuICAgIGhlbHA6ICdDYWxsYmFjayB3aGVuIHNlcnZlciBoYXMgc3RhcnRlZCcsXG4gIH0sXG4gIHNlcnZlclVSTDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9VUkwnLFxuICAgIGhlbHA6ICdVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLicsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0sXG4gIHNlc3Npb25MZW5ndGg6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfU0VTU0lPTl9MRU5HVEgnLFxuICAgIGhlbHA6ICdTZXNzaW9uIGR1cmF0aW9uLCBpbiBzZWNvbmRzLCBkZWZhdWx0cyB0byAxIHllYXInLFxuICAgIGFjdGlvbjogcGFyc2Vycy5udW1iZXJQYXJzZXIoJ3Nlc3Npb25MZW5ndGgnKSxcbiAgICBkZWZhdWx0OiAzMTUzNjAwMCxcbiAgfSxcbiAgc2lsZW50OiB7XG4gICAgZW52OiAnU0lMRU5UJyxcbiAgICBoZWxwOiAnRGlzYWJsZXMgY29uc29sZSBvdXRwdXQnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICB9LFxuICBzdGFydExpdmVRdWVyeVNlcnZlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9TVEFSVF9MSVZFX1FVRVJZX1NFUlZFUicsXG4gICAgaGVscDogJ1N0YXJ0cyB0aGUgbGl2ZVF1ZXJ5IHNlcnZlcicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gIH0sXG4gIHVzZXJTZW5zaXRpdmVGaWVsZHM6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfVVNFUl9TRU5TSVRJVkVfRklFTERTJyxcbiAgICBoZWxwOlxuICAgICAgJ1BlcnNvbmFsbHkgaWRlbnRpZmlhYmxlIGluZm9ybWF0aW9uIGZpZWxkcyBpbiB0aGUgdXNlciB0YWJsZSB0aGUgc2hvdWxkIGJlIHJlbW92ZWQgZm9yIG5vbi1hdXRob3JpemVkIHVzZXJzLiBEZXByZWNhdGVkIEBzZWUgcHJvdGVjdGVkRmllbGRzJyxcbiAgICBhY3Rpb246IHBhcnNlcnMuYXJyYXlQYXJzZXIsXG4gIH0sXG4gIHZlcmJvc2U6IHtcbiAgICBlbnY6ICdWRVJCT1NFJyxcbiAgICBoZWxwOiAnU2V0IHRoZSBsb2dnaW5nIHRvIHZlcmJvc2UnLFxuICAgIGFjdGlvbjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICB9LFxuICB2ZXJpZnlVc2VyRW1haWxzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX1ZFUklGWV9VU0VSX0VNQUlMUycsXG4gICAgaGVscDogJ0VuYWJsZSAob3IgZGlzYWJsZSkgdXNlciBlbWFpbCB2YWxpZGF0aW9uLCBkZWZhdWx0cyB0byBmYWxzZScsXG4gICAgYWN0aW9uOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIHdlYmhvb2tLZXk6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfV0VCSE9PS19LRVknLFxuICAgIGhlbHA6ICdLZXkgc2VudCB3aXRoIG91dGdvaW5nIHdlYmhvb2sgY2FsbHMnLFxuICB9LFxufTtcbm1vZHVsZS5leHBvcnRzLkN1c3RvbVBhZ2VzT3B0aW9ucyA9IHtcbiAgY2hvb3NlUGFzc3dvcmQ6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ1VTVE9NX1BBR0VTX0NIT09TRV9QQVNTV09SRCcsXG4gICAgaGVscDogJ2Nob29zZSBwYXNzd29yZCBwYWdlIHBhdGgnLFxuICB9LFxuICBpbnZhbGlkTGluazoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfSU5WQUxJRF9MSU5LJyxcbiAgICBoZWxwOiAnaW52YWxpZCBsaW5rIHBhZ2UgcGF0aCcsXG4gIH0sXG4gIGludmFsaWRWZXJpZmljYXRpb25MaW5rOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFU19JTlZBTElEX1ZFUklGSUNBVElPTl9MSU5LJyxcbiAgICBoZWxwOiAnaW52YWxpZCB2ZXJpZmljYXRpb24gbGluayBwYWdlIHBhdGgnLFxuICB9LFxuICBsaW5rU2VuZEZhaWw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfQ1VTVE9NX1BBR0VTX0xJTktfU0VORF9GQUlMJyxcbiAgICBoZWxwOiAndmVyaWZpY2F0aW9uIGxpbmsgc2VuZCBmYWlsIHBhZ2UgcGF0aCcsXG4gIH0sXG4gIGxpbmtTZW5kU3VjY2Vzczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfTElOS19TRU5EX1NVQ0NFU1MnLFxuICAgIGhlbHA6ICd2ZXJpZmljYXRpb24gbGluayBzZW5kIHN1Y2Nlc3MgcGFnZSBwYXRoJyxcbiAgfSxcbiAgcGFyc2VGcmFtZVVSTDoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfUEFSU0VfRlJBTUVfVVJMJyxcbiAgICBoZWxwOiAnZm9yIG1hc2tpbmcgdXNlci1mYWNpbmcgcGFnZXMnLFxuICB9LFxuICBwYXNzd29yZFJlc2V0U3VjY2Vzczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfUEFTU1dPUkRfUkVTRVRfU1VDQ0VTUycsXG4gICAgaGVscDogJ3Bhc3N3b3JkIHJlc2V0IHN1Y2Nlc3MgcGFnZSBwYXRoJyxcbiAgfSxcbiAgdmVyaWZ5RW1haWxTdWNjZXNzOiB7XG4gICAgZW52OiAnUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFU19WRVJJRllfRU1BSUxfU1VDQ0VTUycsXG4gICAgaGVscDogJ3ZlcmlmeSBlbWFpbCBzdWNjZXNzIHBhZ2UgcGF0aCcsXG4gIH0sXG59O1xubW9kdWxlLmV4cG9ydHMuTGl2ZVF1ZXJ5T3B0aW9ucyA9IHtcbiAgY2xhc3NOYW1lczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfQ0xBU1NOQU1FUycsXG4gICAgaGVscDogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY2xhc3NOYW1lc1wiLFxuICAgIGFjdGlvbjogcGFyc2Vycy5hcnJheVBhcnNlcixcbiAgfSxcbiAgcHViU3ViQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfUFVCX1NVQl9BREFQVEVSJyxcbiAgICBoZWxwOiAnTGl2ZVF1ZXJ5IHB1YnN1YiBhZGFwdGVyJyxcbiAgICBhY3Rpb246IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXIsXG4gIH0sXG4gIHJlZGlzT3B0aW9uczoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfUkVESVNfT1BUSU9OUycsXG4gICAgaGVscDogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNPcHRpb25zXCIsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm9iamVjdFBhcnNlcixcbiAgfSxcbiAgcmVkaXNVUkw6IHtcbiAgICBlbnY6ICdQQVJTRV9TRVJWRVJfTElWRVFVRVJZX1JFRElTX1VSTCcsXG4gICAgaGVscDogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNVUkxcIixcbiAgfSxcbiAgd3NzQWRhcHRlcjoge1xuICAgIGVudjogJ1BBUlNFX1NFUlZFUl9MSVZFUVVFUllfV1NTX0FEQVBURVInLFxuICAgIGhlbHA6ICdBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIFdlYlNvY2tldFNlcnZlcicsXG4gICAgYWN0aW9uOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICB9LFxufTtcbm1vZHVsZS5leHBvcnRzLkxpdmVRdWVyeVNlcnZlck9wdGlvbnMgPSB7XG4gIGFwcElkOiB7XG4gICAgZW52OiAnUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfQVBQX0lEJyxcbiAgICBoZWxwOlxuICAgICAgJ1RoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgYXBwSWQgaW4gdXNlIGJ5IHlvdXIgUGFyc2UgU2VydmVyLiBJZiB5b3UgZGVwbG95IHRoZSBMaXZlUXVlcnkgc2VydmVyIGFsb25nc2lkZSBQYXJzZSBTZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIHVzZSB0aGUgc2FtZSBhcHBJZC4nLFxuICB9LFxuICBjYWNoZVRpbWVvdXQ6IHtcbiAgICBlbnY6ICdQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9DQUNIRV9USU1FT1VUJyxcbiAgICBoZWxwOlxuICAgICAgXCJOdW1iZXIgaW4gbWlsbGlzZWNvbmRzLiBXaGVuIGNsaWVudHMgcHJvdmlkZSB0aGUgc2Vzc2lvblRva2VuIHRvIHRoZSBMaXZlUXVlcnkgc2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byBmZXRjaCBpdHMgUGFyc2VVc2VyJ3Mgb2JqZWN0SWQgZnJvbSBwYXJzZSBzZXJ2ZXIgYW5kIHN0b3JlIGl0IGluIHRoZSBjYWNoZS4gVGhlIHZhbHVlIGRlZmluZXMgdGhlIGR1cmF0aW9uIG9mIHRoZSBjYWNoZS4gQ2hlY2sgdGhlIGZvbGxvd2luZyBTZWN1cml0eSBzZWN0aW9uIGFuZCBvdXIgcHJvdG9jb2wgc3BlY2lmaWNhdGlvbiBmb3IgZGV0YWlscywgZGVmYXVsdHMgdG8gMzAgKiAyNCAqIDYwICogNjAgKiAxMDAwIG1zICh+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..c4452d35a0 --- /dev/null +++ b/lib/Options/docs.js @@ -0,0 +1,114 @@ +/** + * @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 {Boolean} allowCustomObjectId Enable (or disable) custom objectId + * @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 {Number|String} maxLogFiles Maximum number of logs to keep. If not set, no logs will be removed. This can be a number of files or number of days. If using days, add 'd' as the suffix. (default: null) + * @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} 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL2RvY3MuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE0RUE7Ozs7Ozs7Ozs7OztBQVlBOzs7Ozs7Ozs7QUFTQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGludGVyZmFjZSBQYXJzZVNlcnZlck9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7QW55fSBhY2NvdW50TG9ja291dCBhY2NvdW50IGxvY2tvdXQgcG9saWN5IGZvciBmYWlsZWQgbG9naW4gYXR0ZW1wdHNcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uIEVuYWJsZSAob3IgZGlzYWJsZSkgY2xpZW50IGNsYXNzIGNyZWF0aW9uLCBkZWZhdWx0cyB0byB0cnVlXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IGFsbG93Q3VzdG9tT2JqZWN0SWQgRW5hYmxlIChvciBkaXNhYmxlKSBjdXN0b20gb2JqZWN0SWRcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nW119IGFsbG93SGVhZGVycyBBZGQgaGVhZGVycyB0byBBY2Nlc3MtQ29udHJvbC1BbGxvdy1IZWFkZXJzXG4gKiBAcHJvcGVydHkge0FkYXB0ZXI8QW5hbHl0aWNzQWRhcHRlcj59IGFuYWx5dGljc0FkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBhbmFseXRpY3NcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBhcHBJZCBZb3VyIFBhcnNlIEFwcGxpY2F0aW9uIElEXG4gKiBAcHJvcGVydHkge1N0cmluZ30gYXBwTmFtZSBTZXRzIHRoZSBhcHAgbmFtZVxuICogQHByb3BlcnR5IHtBbnl9IGF1dGggQ29uZmlndXJhdGlvbiBmb3IgeW91ciBhdXRoZW50aWNhdGlvbiBwcm92aWRlcnMsIGFzIHN0cmluZ2lmaWVkIEpTT04uIFNlZSBodHRwOi8vZG9jcy5wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvZ3VpZGUvI29hdXRoLWFuZC0zcmQtcGFydHktYXV0aGVudGljYXRpb25cbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxDYWNoZUFkYXB0ZXI+fSBjYWNoZUFkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBjYWNoZVxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGNhY2hlTWF4U2l6ZSBTZXRzIHRoZSBtYXhpbXVtIHNpemUgZm9yIHRoZSBpbiBtZW1vcnkgY2FjaGUsIGRlZmF1bHRzIHRvIDEwMDAwXG4gKiBAcHJvcGVydHkge051bWJlcn0gY2FjaGVUVEwgU2V0cyB0aGUgVFRMIGZvciB0aGUgaW4gbWVtb3J5IGNhY2hlIChpbiBtcyksIGRlZmF1bHRzIHRvIDUwMDAgKDUgc2Vjb25kcylcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBjbGllbnRLZXkgS2V5IGZvciBpT1MsIE1hY09TLCB0dk9TIGNsaWVudHNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBjbG91ZCBGdWxsIHBhdGggdG8geW91ciBjbG91ZCBjb2RlIG1haW4uanNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfEJvb2xlYW59IGNsdXN0ZXIgUnVuIHdpdGggY2x1c3Rlciwgb3B0aW9uYWxseSBzZXQgdGhlIG51bWJlciBvZiBwcm9jZXNzZXMgZGVmYXVsdCB0byBvcy5jcHVzKCkubGVuZ3RoXG4gKiBAcHJvcGVydHkge1N0cmluZ30gY29sbGVjdGlvblByZWZpeCBBIGNvbGxlY3Rpb24gcHJlZml4IGZvciB0aGUgY2xhc3Nlc1xuICogQHByb3BlcnR5IHtDdXN0b21QYWdlc09wdGlvbnN9IGN1c3RvbVBhZ2VzIGN1c3RvbSBwYWdlcyBmb3IgcGFzc3dvcmQgdmFsaWRhdGlvbiBhbmQgcmVzZXRcbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxTdG9yYWdlQWRhcHRlcj59IGRhdGFiYXNlQWRhcHRlciBBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIGRhdGFiYXNlXG4gKiBAcHJvcGVydHkge0FueX0gZGF0YWJhc2VPcHRpb25zIE9wdGlvbnMgdG8gcGFzcyB0byB0aGUgbW9uZ29kYiBjbGllbnRcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkYXRhYmFzZVVSSSBUaGUgZnVsbCBVUkkgdG8geW91ciBkYXRhYmFzZS4gU3VwcG9ydGVkIGRhdGFiYXNlcyBhcmUgbW9uZ29kYiBvciBwb3N0Z3Jlcy5cbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gZGlyZWN0QWNjZXNzIFJlcGxhY2UgSFRUUCBJbnRlcmZhY2Ugd2hlbiB1c2luZyBKUyBTREsgaW4gY3VycmVudCBub2RlIHJ1bnRpbWUsIGRlZmF1bHRzIHRvIGZhbHNlLiBDYXV0aW9uLCB0aGlzIGlzIGFuIGV4cGVyaW1lbnRhbCBmZWF0dXJlIHRoYXQgbWF5IG5vdCBiZSBhcHByb3ByaWF0ZSBmb3IgcHJvZHVjdGlvbi5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkb3ROZXRLZXkgS2V5IGZvciBVbml0eSBhbmQgLk5ldCBTREtcbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxNYWlsQWRhcHRlcj59IGVtYWlsQWRhcHRlciBBZGFwdGVyIG1vZHVsZSBmb3IgZW1haWwgc2VuZGluZ1xuICogQHByb3BlcnR5IHtOdW1iZXJ9IGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uIEVtYWlsIHZlcmlmaWNhdGlvbiB0b2tlbiB2YWxpZGl0eSBkdXJhdGlvbiwgaW4gc2Vjb25kc1xuICogQHByb3BlcnR5IHtCb29sZWFufSBlbmFibGVBbm9ueW1vdXNVc2VycyBFbmFibGUgKG9yIGRpc2FibGUpIGFub24gdXNlcnMsIGRlZmF1bHRzIHRvIHRydWVcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlciBFbmFibGVzIHRoZSBkZWZhdWx0IGV4cHJlc3MgZXJyb3IgaGFuZGxlciBmb3IgYWxsIGVycm9yc1xuICogQHByb3BlcnR5IHtCb29sZWFufSBlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSBVc2UgYSBzaW5nbGUgc2NoZW1hIGNhY2hlIHNoYXJlZCBhY3Jvc3MgcmVxdWVzdHMuIFJlZHVjZXMgbnVtYmVyIG9mIHF1ZXJpZXMgbWFkZSB0byBfU0NIRU1BLCBkZWZhdWx0cyB0byBmYWxzZSwgaS5lLiB1bmlxdWUgc2NoZW1hIGNhY2hlIHBlciByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtCb29sZWFufSBleHBpcmVJbmFjdGl2ZVNlc3Npb25zIFNldHMgd2V0aGVyIHdlIHNob3VsZCBleHBpcmUgdGhlIGluYWN0aXZlIHNlc3Npb25zLCBkZWZhdWx0cyB0byB0cnVlXG4gKiBAcHJvcGVydHkge1N0cmluZ30gZmlsZUtleSBLZXkgZm9yIHlvdXIgZmlsZXNcbiAqIEBwcm9wZXJ0eSB7QWRhcHRlcjxGaWxlc0FkYXB0ZXI+fSBmaWxlc0FkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBmaWxlcyBzdWItc3lzdGVtXG4gKiBAcHJvcGVydHkge1N0cmluZ30gZ3JhcGhRTFBhdGggTW91bnQgcGF0aCBmb3IgdGhlIEdyYXBoUUwgZW5kcG9pbnQsIGRlZmF1bHRzIHRvIC9ncmFwaHFsXG4gKiBAcHJvcGVydHkge1N0cmluZ30gZ3JhcGhRTFNjaGVtYSBGdWxsIHBhdGggdG8geW91ciBHcmFwaFFMIGN1c3RvbSBzY2hlbWEuZ3JhcGhxbCBmaWxlXG4gKiBAcHJvcGVydHkge1N0cmluZ30gaG9zdCBUaGUgaG9zdCB0byBzZXJ2ZSBQYXJzZVNlcnZlciBvbiwgZGVmYXVsdHMgdG8gMC4wLjAuMFxuICogQHByb3BlcnR5IHtTdHJpbmd9IGphdmFzY3JpcHRLZXkgS2V5IGZvciB0aGUgSmF2YXNjcmlwdCBTREtcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0ganNvbkxvZ3MgTG9nIGFzIHN0cnVjdHVyZWQgSlNPTiBvYmplY3RzXG4gKiBAcHJvcGVydHkge0xpdmVRdWVyeU9wdGlvbnN9IGxpdmVRdWVyeSBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY29uZmlndXJhdGlvbiBvYmplY3RcbiAqIEBwcm9wZXJ0eSB7TGl2ZVF1ZXJ5U2VydmVyT3B0aW9uc30gbGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyBMaXZlIHF1ZXJ5IHNlcnZlciBjb25maWd1cmF0aW9uIG9wdGlvbnMgKHdpbGwgc3RhcnQgdGhlIGxpdmVRdWVyeSBzZXJ2ZXIpXG4gKiBAcHJvcGVydHkge0FkYXB0ZXI8TG9nZ2VyQWRhcHRlcj59IGxvZ2dlckFkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBsb2dnaW5nIHN1Yi1zeXN0ZW1cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBsb2dMZXZlbCBTZXRzIHRoZSBsZXZlbCBmb3IgbG9nc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IGxvZ3NGb2xkZXIgRm9sZGVyIGZvciB0aGUgbG9ncyAoZGVmYXVsdHMgdG8gJy4vbG9ncycpOyBzZXQgdG8gbnVsbCB0byBkaXNhYmxlIGZpbGUgYmFzZWQgbG9nZ2luZ1xuICogQHByb3BlcnR5IHtTdHJpbmd9IG1hc3RlcktleSBZb3VyIFBhcnNlIE1hc3RlciBLZXlcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nW119IG1hc3RlcktleUlwcyBSZXN0cmljdCBtYXN0ZXJLZXkgdG8gYmUgdXNlZCBieSBvbmx5IHRoZXNlIGlwcywgZGVmYXVsdHMgdG8gW10gKGFsbG93IGFsbCBpcHMpXG4gKiBAcHJvcGVydHkge051bWJlcn0gbWF4TGltaXQgTWF4IHZhbHVlIGZvciBsaW1pdCBvcHRpb24gb24gcXVlcmllcywgZGVmYXVsdHMgdG8gdW5saW1pdGVkXG4gKiBAcHJvcGVydHkge051bWJlcnxTdHJpbmd9IG1heExvZ0ZpbGVzIE1heGltdW0gbnVtYmVyIG9mIGxvZ3MgdG8ga2VlcC4gSWYgbm90IHNldCwgbm8gbG9ncyB3aWxsIGJlIHJlbW92ZWQuIFRoaXMgY2FuIGJlIGEgbnVtYmVyIG9mIGZpbGVzIG9yIG51bWJlciBvZiBkYXlzLiBJZiB1c2luZyBkYXlzLCBhZGQgJ2QnIGFzIHRoZSBzdWZmaXguIChkZWZhdWx0OiBudWxsKVxuICogQHByb3BlcnR5IHtTdHJpbmd9IG1heFVwbG9hZFNpemUgTWF4IGZpbGUgc2l6ZSBmb3IgdXBsb2FkcywgZGVmYXVsdHMgdG8gMjBtYlxuICogQHByb3BlcnR5IHtVbmlvbn0gbWlkZGxld2FyZSBtaWRkbGV3YXJlIGZvciBleHByZXNzIHNlcnZlciwgY2FuIGJlIHN0cmluZyBvciBmdW5jdGlvblxuICogQHByb3BlcnR5IHtCb29sZWFufSBtb3VudEdyYXBoUUwgTW91bnRzIHRoZSBHcmFwaFFMIGVuZHBvaW50XG4gKiBAcHJvcGVydHkge1N0cmluZ30gbW91bnRQYXRoIE1vdW50IHBhdGggZm9yIHRoZSBzZXJ2ZXIsIGRlZmF1bHRzIHRvIC9wYXJzZVxuICogQHByb3BlcnR5IHtCb29sZWFufSBtb3VudFBsYXlncm91bmQgTW91bnRzIHRoZSBHcmFwaFFMIFBsYXlncm91bmQgLSBuZXZlciB1c2UgdGhpcyBvcHRpb24gaW4gcHJvZHVjdGlvblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IG9iamVjdElkU2l6ZSBTZXRzIHRoZSBudW1iZXIgb2YgY2hhcmFjdGVycyBpbiBnZW5lcmF0ZWQgb2JqZWN0IGlkJ3MsIGRlZmF1bHQgMTBcbiAqIEBwcm9wZXJ0eSB7QW55fSBwYXNzd29yZFBvbGljeSBQYXNzd29yZCBwb2xpY3kgZm9yIGVuZm9yY2luZyBwYXNzd29yZCByZWxhdGVkIHJ1bGVzXG4gKiBAcHJvcGVydHkge1N0cmluZ30gcGxheWdyb3VuZFBhdGggTW91bnQgcGF0aCBmb3IgdGhlIEdyYXBoUUwgUGxheWdyb3VuZCwgZGVmYXVsdHMgdG8gL3BsYXlncm91bmRcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBwb3J0IFRoZSBwb3J0IHRvIHJ1biB0aGUgUGFyc2VTZXJ2ZXIsIGRlZmF1bHRzIHRvIDEzMzcuXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHByZXNlcnZlRmlsZU5hbWUgRW5hYmxlIChvciBkaXNhYmxlKSB0aGUgYWRkaXRpb24gb2YgYSB1bmlxdWUgaGFzaCB0byB0aGUgZmlsZSBuYW1lc1xuICogQHByb3BlcnR5IHtCb29sZWFufSBwcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsIFByZXZlbnQgdXNlciBmcm9tIGxvZ2luIGlmIGVtYWlsIGlzIG5vdCB2ZXJpZmllZCBhbmQgUEFSU0VfU0VSVkVSX1ZFUklGWV9VU0VSX0VNQUlMUyBpcyB0cnVlLCBkZWZhdWx0cyB0byBmYWxzZVxuICogQHByb3BlcnR5IHtQcm90ZWN0ZWRGaWVsZHN9IHByb3RlY3RlZEZpZWxkcyBQcm90ZWN0ZWQgZmllbGRzIHRoYXQgc2hvdWxkIGJlIHRyZWF0ZWQgd2l0aCBleHRyYSBzZWN1cml0eSB3aGVuIGZldGNoaW5nIGRldGFpbHMuXG4gKiBAcHJvcGVydHkge1N0cmluZ30gcHVibGljU2VydmVyVVJMIFB1YmxpYyBVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLlxuICogQHByb3BlcnR5IHtBbnl9IHB1c2ggQ29uZmlndXJhdGlvbiBmb3IgcHVzaCwgYXMgc3RyaW5naWZpZWQgSlNPTi4gU2VlIGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8jcHVzaC1ub3RpZmljYXRpb25zXG4gKiBAcHJvcGVydHkge1N0cmluZ30gcmVhZE9ubHlNYXN0ZXJLZXkgUmVhZC1vbmx5IGtleSwgd2hpY2ggaGFzIHRoZSBzYW1lIGNhcGFiaWxpdGllcyBhcyBNYXN0ZXJLZXkgd2l0aG91dCB3cml0ZXNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSByZXN0QVBJS2V5IEtleSBmb3IgUkVTVCBjYWxsc1xuICogQHByb3BlcnR5IHtCb29sZWFufSByZXZva2VTZXNzaW9uT25QYXNzd29yZFJlc2V0IFdoZW4gYSB1c2VyIGNoYW5nZXMgdGhlaXIgcGFzc3dvcmQsIGVpdGhlciB0aHJvdWdoIHRoZSByZXNldCBwYXNzd29yZCBlbWFpbCBvciB3aGlsZSBsb2dnZWQgaW4sIGFsbCBzZXNzaW9ucyBhcmUgcmV2b2tlZCBpZiB0aGlzIGlzIHRydWUuIFNldCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0byByZXZva2Ugc2Vzc2lvbnMuXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHNjaGVkdWxlZFB1c2ggQ29uZmlndXJhdGlvbiBmb3IgcHVzaCBzY2hlZHVsaW5nLCBkZWZhdWx0cyB0byBmYWxzZS5cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBzY2hlbWFDYWNoZVRUTCBUaGUgVFRMIGZvciBjYWNoaW5nIHRoZSBzY2hlbWEgZm9yIG9wdGltaXppbmcgcmVhZC93cml0ZSBvcGVyYXRpb25zLiBZb3Ugc2hvdWxkIHB1dCBhIGxvbmcgVFRMIHdoZW4geW91ciBEQiBpcyBpbiBwcm9kdWN0aW9uLiBkZWZhdWx0IHRvIDUwMDA7IHNldCAwIHRvIGRpc2FibGUuXG4gKiBAcHJvcGVydHkge0Z1bmN0aW9ufSBzZXJ2ZXJDbG9zZUNvbXBsZXRlIENhbGxiYWNrIHdoZW4gc2VydmVyIGhhcyBjbG9zZWRcbiAqIEBwcm9wZXJ0eSB7RnVuY3Rpb259IHNlcnZlclN0YXJ0Q29tcGxldGUgQ2FsbGJhY2sgd2hlbiBzZXJ2ZXIgaGFzIHN0YXJ0ZWRcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBzZXJ2ZXJVUkwgVVJMIHRvIHlvdXIgcGFyc2Ugc2VydmVyIHdpdGggaHR0cDovLyBvciBodHRwczovLy5cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBzZXNzaW9uTGVuZ3RoIFNlc3Npb24gZHVyYXRpb24sIGluIHNlY29uZHMsIGRlZmF1bHRzIHRvIDEgeWVhclxuICogQHByb3BlcnR5IHtCb29sZWFufSBzaWxlbnQgRGlzYWJsZXMgY29uc29sZSBvdXRwdXRcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gc3RhcnRMaXZlUXVlcnlTZXJ2ZXIgU3RhcnRzIHRoZSBsaXZlUXVlcnkgc2VydmVyXG4gKiBAcHJvcGVydHkge1N0cmluZ1tdfSB1c2VyU2Vuc2l0aXZlRmllbGRzIFBlcnNvbmFsbHkgaWRlbnRpZmlhYmxlIGluZm9ybWF0aW9uIGZpZWxkcyBpbiB0aGUgdXNlciB0YWJsZSB0aGUgc2hvdWxkIGJlIHJlbW92ZWQgZm9yIG5vbi1hdXRob3JpemVkIHVzZXJzLiBEZXByZWNhdGVkIEBzZWUgcHJvdGVjdGVkRmllbGRzXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IHZlcmJvc2UgU2V0IHRoZSBsb2dnaW5nIHRvIHZlcmJvc2VcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gdmVyaWZ5VXNlckVtYWlscyBFbmFibGUgKG9yIGRpc2FibGUpIHVzZXIgZW1haWwgdmFsaWRhdGlvbiwgZGVmYXVsdHMgdG8gZmFsc2VcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSB3ZWJob29rS2V5IEtleSBzZW50IHdpdGggb3V0Z29pbmcgd2ViaG9vayBjYWxsc1xuICovXG5cbi8qKlxuICogQGludGVyZmFjZSBDdXN0b21QYWdlc09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBjaG9vc2VQYXNzd29yZCBjaG9vc2UgcGFzc3dvcmQgcGFnZSBwYXRoXG4gKiBAcHJvcGVydHkge1N0cmluZ30gaW52YWxpZExpbmsgaW52YWxpZCBsaW5rIHBhZ2UgcGF0aFxuICogQHByb3BlcnR5IHtTdHJpbmd9IGludmFsaWRWZXJpZmljYXRpb25MaW5rIGludmFsaWQgdmVyaWZpY2F0aW9uIGxpbmsgcGFnZSBwYXRoXG4gKiBAcHJvcGVydHkge1N0cmluZ30gbGlua1NlbmRGYWlsIHZlcmlmaWNhdGlvbiBsaW5rIHNlbmQgZmFpbCBwYWdlIHBhdGhcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBsaW5rU2VuZFN1Y2Nlc3MgdmVyaWZpY2F0aW9uIGxpbmsgc2VuZCBzdWNjZXNzIHBhZ2UgcGF0aFxuICogQHByb3BlcnR5IHtTdHJpbmd9IHBhcnNlRnJhbWVVUkwgZm9yIG1hc2tpbmcgdXNlci1mYWNpbmcgcGFnZXNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBwYXNzd29yZFJlc2V0U3VjY2VzcyBwYXNzd29yZCByZXNldCBzdWNjZXNzIHBhZ2UgcGF0aFxuICogQHByb3BlcnR5IHtTdHJpbmd9IHZlcmlmeUVtYWlsU3VjY2VzcyB2ZXJpZnkgZW1haWwgc3VjY2VzcyBwYWdlIHBhdGhcbiAqL1xuXG4vKipcbiAqIEBpbnRlcmZhY2UgTGl2ZVF1ZXJ5T3B0aW9uc1xuICogQHByb3BlcnR5IHtTdHJpbmdbXX0gY2xhc3NOYW1lcyBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY2xhc3NOYW1lc1xuICogQHByb3BlcnR5IHtBZGFwdGVyPFB1YlN1YkFkYXB0ZXI+fSBwdWJTdWJBZGFwdGVyIExpdmVRdWVyeSBwdWJzdWIgYWRhcHRlclxuICogQHByb3BlcnR5IHtBbnl9IHJlZGlzT3B0aW9ucyBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNPcHRpb25zXG4gKiBAcHJvcGVydHkge1N0cmluZ30gcmVkaXNVUkwgcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzVVJMXG4gKiBAcHJvcGVydHkge0FkYXB0ZXI8V1NTQWRhcHRlcj59IHdzc0FkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBXZWJTb2NrZXRTZXJ2ZXJcbiAqL1xuXG4vKipcbiAqIEBpbnRlcmZhY2UgTGl2ZVF1ZXJ5U2VydmVyT3B0aW9uc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IGFwcElkIFRoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgYXBwSWQgaW4gdXNlIGJ5IHlvdXIgUGFyc2UgU2VydmVyLiBJZiB5b3UgZGVwbG95IHRoZSBMaXZlUXVlcnkgc2VydmVyIGFsb25nc2lkZSBQYXJzZSBTZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIHVzZSB0aGUgc2FtZSBhcHBJZC5cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjYWNoZVRpbWVvdXQgTnVtYmVyIGluIG1pbGxpc2Vjb25kcy4gV2hlbiBjbGllbnRzIHByb3ZpZGUgdGhlIHNlc3Npb25Ub2tlbiB0byB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciwgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgd2lsbCB0cnkgdG8gZmV0Y2ggaXRzIFBhcnNlVXNlcidzIG9iamVjdElkIGZyb20gcGFyc2Ugc2VydmVyIGFuZCBzdG9yZSBpdCBpbiB0aGUgY2FjaGUuIFRoZSB2YWx1ZSBkZWZpbmVzIHRoZSBkdXJhdGlvbiBvZiB0aGUgY2FjaGUuIENoZWNrIHRoZSBmb2xsb3dpbmcgU2VjdXJpdHkgc2VjdGlvbiBhbmQgb3VyIHByb3RvY29sIHNwZWNpZmljYXRpb24gZm9yIGRldGFpbHMsIGRlZmF1bHRzIHRvIDMwICogMjQgKiA2MCAqIDYwICogMTAwMCBtcyAofjMwIGRheXMpLlxuICogQHByb3BlcnR5IHtBbnl9IGtleVBhaXJzIEEgSlNPTiBvYmplY3QgdGhhdCBzZXJ2ZXMgYXMgYSB3aGl0ZWxpc3Qgb2Yga2V5cy4gSXQgaXMgdXNlZCBmb3IgdmFsaWRhdGluZyBjbGllbnRzIHdoZW4gdGhleSB0cnkgdG8gY29ubmVjdCB0byB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gQ2hlY2sgdGhlIGZvbGxvd2luZyBTZWN1cml0eSBzZWN0aW9uIGFuZCBvdXIgcHJvdG9jb2wgc3BlY2lmaWNhdGlvbiBmb3IgZGV0YWlscy5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBsb2dMZXZlbCBUaGlzIHN0cmluZyBkZWZpbmVzIHRoZSBsb2cgbGV2ZWwgb2YgdGhlIExpdmVRdWVyeSBzZXJ2ZXIuIFdlIHN1cHBvcnQgVkVSQk9TRSwgSU5GTywgRVJST1IsIE5PTkUsIGRlZmF1bHRzIHRvIElORk8uXG4gKiBAcHJvcGVydHkge1N0cmluZ30gbWFzdGVyS2V5IFRoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgbWFzdGVyS2V5IGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgbWFzdGVyS2V5LlxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHBvcnQgVGhlIHBvcnQgdG8gcnVuIHRoZSBMaXZlUXVlcnkgc2VydmVyLCBkZWZhdWx0cyB0byAxMzM3LlxuICogQHByb3BlcnR5IHtBZGFwdGVyPFB1YlN1YkFkYXB0ZXI+fSBwdWJTdWJBZGFwdGVyIExpdmVRdWVyeSBwdWJzdWIgYWRhcHRlclxuICogQHByb3BlcnR5IHtBbnl9IHJlZGlzT3B0aW9ucyBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNPcHRpb25zXG4gKiBAcHJvcGVydHkge1N0cmluZ30gcmVkaXNVUkwgcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzVVJMXG4gKiBAcHJvcGVydHkge1N0cmluZ30gc2VydmVyVVJMIFRoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgc2VydmVyVVJMIGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgc2VydmVyVVJMLlxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHdlYnNvY2tldFRpbWVvdXQgTnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBiZXR3ZWVuIHBpbmcvcG9uZyBmcmFtZXMuIFRoZSBXZWJTb2NrZXQgc2VydmVyIHNlbmRzIHBpbmcvcG9uZyBmcmFtZXMgdG8gdGhlIGNsaWVudHMgdG8ga2VlcCB0aGUgV2ViU29ja2V0IGFsaXZlLiBUaGlzIHZhbHVlIGRlZmluZXMgdGhlIGludGVydmFsIG9mIHRoZSBwaW5nL3BvbmcgZnJhbWUgZnJvbSB0aGUgc2VydmVyIHRvIGNsaWVudHMsIGRlZmF1bHRzIHRvIDEwICogMTAwMCBtcyAoMTAgcykuXG4gKiBAcHJvcGVydHkge0FkYXB0ZXI8V1NTQWRhcHRlcj59IHdzc0FkYXB0ZXIgQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBXZWJTb2NrZXRTZXJ2ZXJcbiAqL1xuIl19 \ No newline at end of file diff --git a/lib/Options/index.js b/lib/Options/index.js new file mode 100644 index 0000000000..369e077ad5 --- /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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbmFseXRpY3NBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQW5hbHl0aWNzL0FuYWx5dGljc0FkYXB0ZXInO1xuaW1wb3J0IHsgRmlsZXNBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvRmlsZXMvRmlsZXNBZGFwdGVyJztcbmltcG9ydCB7IExvZ2dlckFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9Mb2dnZXIvTG9nZ2VyQWRhcHRlcic7XG5pbXBvcnQgeyBTdG9yYWdlQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL1N0b3JhZ2UvU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHsgQ2FjaGVBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQ2FjaGUvQ2FjaGVBZGFwdGVyJztcbmltcG9ydCB7IE1haWxBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvRW1haWwvTWFpbEFkYXB0ZXInO1xuaW1wb3J0IHsgUHViU3ViQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL1B1YlN1Yi9QdWJTdWJBZGFwdGVyJztcbmltcG9ydCB7IFdTU0FkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9XZWJTb2NrZXRTZXJ2ZXIvV1NTQWRhcHRlcic7XG5cbi8vIEBmbG93XG50eXBlIEFkYXB0ZXI8VD4gPSBzdHJpbmcgfCBhbnkgfCBUO1xudHlwZSBOdW1iZXJPckJvb2xlYW4gPSBudW1iZXIgfCBib29sZWFuO1xudHlwZSBOdW1iZXJPclN0cmluZyA9IG51bWJlciB8IHN0cmluZztcbnR5cGUgUHJvdGVjdGVkRmllbGRzID0gYW55O1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhcnNlU2VydmVyT3B0aW9ucyB7XG4gIC8qIFlvdXIgUGFyc2UgQXBwbGljYXRpb24gSURcbiAgOkVOVjogUEFSU0VfU0VSVkVSX0FQUExJQ0FUSU9OX0lEICovXG4gIGFwcElkOiBzdHJpbmc7XG4gIC8qIFlvdXIgUGFyc2UgTWFzdGVyIEtleSAqL1xuICBtYXN0ZXJLZXk6IHN0cmluZztcbiAgLyogVVJMIHRvIHlvdXIgcGFyc2Ugc2VydmVyIHdpdGggaHR0cDovLyBvciBodHRwczovLy5cbiAgOkVOVjogUEFSU0VfU0VSVkVSX1VSTCAqL1xuICBzZXJ2ZXJVUkw6IHN0cmluZztcbiAgLyogUmVzdHJpY3QgbWFzdGVyS2V5IHRvIGJlIHVzZWQgYnkgb25seSB0aGVzZSBpcHMsIGRlZmF1bHRzIHRvIFtdIChhbGxvdyBhbGwgaXBzKVxuICA6REVGQVVMVDogW10gKi9cbiAgbWFzdGVyS2V5SXBzOiA/KHN0cmluZ1tdKTtcbiAgLyogU2V0cyB0aGUgYXBwIG5hbWUgKi9cbiAgYXBwTmFtZTogP3N0cmluZztcbiAgLyogQWRkIGhlYWRlcnMgdG8gQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycyAqL1xuICBhbGxvd0hlYWRlcnM6ID8oc3RyaW5nW10pO1xuICAvKiBBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIGFuYWx5dGljcyAqL1xuICBhbmFseXRpY3NBZGFwdGVyOiA/QWRhcHRlcjxBbmFseXRpY3NBZGFwdGVyPjtcbiAgLyogQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBmaWxlcyBzdWItc3lzdGVtICovXG4gIGZpbGVzQWRhcHRlcjogP0FkYXB0ZXI8RmlsZXNBZGFwdGVyPjtcbiAgLyogQ29uZmlndXJhdGlvbiBmb3IgcHVzaCwgYXMgc3RyaW5naWZpZWQgSlNPTi4gU2VlIGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8jcHVzaC1ub3RpZmljYXRpb25zICovXG4gIHB1c2g6ID9hbnk7XG4gIC8qIENvbmZpZ3VyYXRpb24gZm9yIHB1c2ggc2NoZWR1bGluZywgZGVmYXVsdHMgdG8gZmFsc2UuXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICBzY2hlZHVsZWRQdXNoOiA/Ym9vbGVhbjtcbiAgLyogQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBsb2dnaW5nIHN1Yi1zeXN0ZW0gKi9cbiAgbG9nZ2VyQWRhcHRlcjogP0FkYXB0ZXI8TG9nZ2VyQWRhcHRlcj47XG4gIC8qIExvZyBhcyBzdHJ1Y3R1cmVkIEpTT04gb2JqZWN0c1xuICA6RU5WOiBKU09OX0xPR1MgKi9cbiAganNvbkxvZ3M6ID9ib29sZWFuO1xuICAvKiBGb2xkZXIgZm9yIHRoZSBsb2dzIChkZWZhdWx0cyB0byAnLi9sb2dzJyk7IHNldCB0byBudWxsIHRvIGRpc2FibGUgZmlsZSBiYXNlZCBsb2dnaW5nXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9MT0dTX0ZPTERFUlxuICA6REVGQVVMVDogLi9sb2dzICovXG4gIGxvZ3NGb2xkZXI6ID9zdHJpbmc7XG4gIC8qIFNldCB0aGUgbG9nZ2luZyB0byB2ZXJib3NlXG4gIDpFTlY6IFZFUkJPU0UgKi9cbiAgdmVyYm9zZTogP2Jvb2xlYW47XG4gIC8qIFNldHMgdGhlIGxldmVsIGZvciBsb2dzICovXG4gIGxvZ0xldmVsOiA/c3RyaW5nO1xuICAvKiBNYXhpbXVtIG51bWJlciBvZiBsb2dzIHRvIGtlZXAuIElmIG5vdCBzZXQsIG5vIGxvZ3Mgd2lsbCBiZSByZW1vdmVkLiBUaGlzIGNhbiBiZSBhIG51bWJlciBvZiBmaWxlcyBvciBudW1iZXIgb2YgZGF5cy4gSWYgdXNpbmcgZGF5cywgYWRkICdkJyBhcyB0aGUgc3VmZml4LiAoZGVmYXVsdDogbnVsbCkgKi9cbiAgbWF4TG9nRmlsZXM6ID9OdW1iZXJPclN0cmluZztcbiAgLyogRGlzYWJsZXMgY29uc29sZSBvdXRwdXRcbiAgOkVOVjogU0lMRU5UICovXG4gIHNpbGVudDogP2Jvb2xlYW47XG4gIC8qIFRoZSBmdWxsIFVSSSB0byB5b3VyIGRhdGFiYXNlLiBTdXBwb3J0ZWQgZGF0YWJhc2VzIGFyZSBtb25nb2RiIG9yIHBvc3RncmVzLlxuICA6REVGQVVMVDogbW9uZ29kYjovL2xvY2FsaG9zdDoyNzAxNy9wYXJzZSAqL1xuICBkYXRhYmFzZVVSSTogc3RyaW5nO1xuICAvKiBPcHRpb25zIHRvIHBhc3MgdG8gdGhlIG1vbmdvZGIgY2xpZW50ICovXG4gIGRhdGFiYXNlT3B0aW9uczogP2FueTtcbiAgLyogQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBkYXRhYmFzZSAqL1xuICBkYXRhYmFzZUFkYXB0ZXI6ID9BZGFwdGVyPFN0b3JhZ2VBZGFwdGVyPjtcbiAgLyogRnVsbCBwYXRoIHRvIHlvdXIgY2xvdWQgY29kZSBtYWluLmpzICovXG4gIGNsb3VkOiA/c3RyaW5nO1xuICAvKiBBIGNvbGxlY3Rpb24gcHJlZml4IGZvciB0aGUgY2xhc3Nlc1xuICA6REVGQVVMVDogJycgKi9cbiAgY29sbGVjdGlvblByZWZpeDogP3N0cmluZztcbiAgLyogS2V5IGZvciBpT1MsIE1hY09TLCB0dk9TIGNsaWVudHMgKi9cbiAgY2xpZW50S2V5OiA/c3RyaW5nO1xuICAvKiBLZXkgZm9yIHRoZSBKYXZhc2NyaXB0IFNESyAqL1xuICBqYXZhc2NyaXB0S2V5OiA/c3RyaW5nO1xuICAvKiBLZXkgZm9yIFVuaXR5IGFuZCAuTmV0IFNESyAqL1xuICBkb3ROZXRLZXk6ID9zdHJpbmc7XG4gIC8qIEtleSBmb3IgUkVTVCBjYWxsc1xuICA6RU5WOiBQQVJTRV9TRVJWRVJfUkVTVF9BUElfS0VZICovXG4gIHJlc3RBUElLZXk6ID9zdHJpbmc7XG4gIC8qIFJlYWQtb25seSBrZXksIHdoaWNoIGhhcyB0aGUgc2FtZSBjYXBhYmlsaXRpZXMgYXMgTWFzdGVyS2V5IHdpdGhvdXQgd3JpdGVzICovXG4gIHJlYWRPbmx5TWFzdGVyS2V5OiA/c3RyaW5nO1xuICAvKiBLZXkgc2VudCB3aXRoIG91dGdvaW5nIHdlYmhvb2sgY2FsbHMgKi9cbiAgd2ViaG9va0tleTogP3N0cmluZztcbiAgLyogS2V5IGZvciB5b3VyIGZpbGVzICovXG4gIGZpbGVLZXk6ID9zdHJpbmc7XG4gIC8qIEVuYWJsZSAob3IgZGlzYWJsZSkgdGhlIGFkZGl0aW9uIG9mIGEgdW5pcXVlIGhhc2ggdG8gdGhlIGZpbGUgbmFtZXNcbiAgOkVOVjogUEFSU0VfU0VSVkVSX1BSRVNFUlZFX0ZJTEVfTkFNRVxuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgcHJlc2VydmVGaWxlTmFtZTogP2Jvb2xlYW47XG4gIC8qIFBlcnNvbmFsbHkgaWRlbnRpZmlhYmxlIGluZm9ybWF0aW9uIGZpZWxkcyBpbiB0aGUgdXNlciB0YWJsZSB0aGUgc2hvdWxkIGJlIHJlbW92ZWQgZm9yIG5vbi1hdXRob3JpemVkIHVzZXJzLiBEZXByZWNhdGVkIEBzZWUgcHJvdGVjdGVkRmllbGRzICovXG4gIHVzZXJTZW5zaXRpdmVGaWVsZHM6ID8oc3RyaW5nW10pO1xuICAvKiBQcm90ZWN0ZWQgZmllbGRzIHRoYXQgc2hvdWxkIGJlIHRyZWF0ZWQgd2l0aCBleHRyYSBzZWN1cml0eSB3aGVuIGZldGNoaW5nIGRldGFpbHMuXG4gIDpERUZBVUxUOiB7XCJfVXNlclwiOiB7XCIqXCI6IFtcImVtYWlsXCJdfX0gKi9cbiAgcHJvdGVjdGVkRmllbGRzOiA/UHJvdGVjdGVkRmllbGRzO1xuICAvKiBFbmFibGUgKG9yIGRpc2FibGUpIGFub24gdXNlcnMsIGRlZmF1bHRzIHRvIHRydWVcbiAgOkVOVjogUEFSU0VfU0VSVkVSX0VOQUJMRV9BTk9OX1VTRVJTXG4gIDpERUZBVUxUOiB0cnVlICovXG4gIGVuYWJsZUFub255bW91c1VzZXJzOiA/Ym9vbGVhbjtcbiAgLyogRW5hYmxlIChvciBkaXNhYmxlKSBjbGllbnQgY2xhc3MgY3JlYXRpb24sIGRlZmF1bHRzIHRvIHRydWVcbiAgOkVOVjogUEFSU0VfU0VSVkVSX0FMTE9XX0NMSUVOVF9DTEFTU19DUkVBVElPTlxuICA6REVGQVVMVDogdHJ1ZSAqL1xuICBhbGxvd0NsaWVudENsYXNzQ3JlYXRpb246ID9ib29sZWFuO1xuICAvKiBFbmFibGUgKG9yIGRpc2FibGUpIGN1c3RvbSBvYmplY3RJZFxuICA6RU5WOiBQQVJTRV9TRVJWRVJfQUxMT1dfQ1VTVE9NX09CSkVDVF9JRFxuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgYWxsb3dDdXN0b21PYmplY3RJZDogP2Jvb2xlYW47XG4gIC8qIENvbmZpZ3VyYXRpb24gZm9yIHlvdXIgYXV0aGVudGljYXRpb24gcHJvdmlkZXJzLCBhcyBzdHJpbmdpZmllZCBKU09OLiBTZWUgaHR0cDovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvcGFyc2Utc2VydmVyL2d1aWRlLyNvYXV0aC1hbmQtM3JkLXBhcnR5LWF1dGhlbnRpY2F0aW9uXG4gIDpFTlY6IFBBUlNFX1NFUlZFUl9BVVRIX1BST1ZJREVSUyAqL1xuICBhdXRoOiA/YW55O1xuICAvKiBNYXggZmlsZSBzaXplIGZvciB1cGxvYWRzLCBkZWZhdWx0cyB0byAyMG1iXG4gIDpERUZBVUxUOiAyMG1iICovXG4gIG1heFVwbG9hZFNpemU6ID9zdHJpbmc7XG4gIC8qIEVuYWJsZSAob3IgZGlzYWJsZSkgdXNlciBlbWFpbCB2YWxpZGF0aW9uLCBkZWZhdWx0cyB0byBmYWxzZVxuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgdmVyaWZ5VXNlckVtYWlsczogP2Jvb2xlYW47XG4gIC8qIFByZXZlbnQgdXNlciBmcm9tIGxvZ2luIGlmIGVtYWlsIGlzIG5vdCB2ZXJpZmllZCBhbmQgUEFSU0VfU0VSVkVSX1ZFUklGWV9VU0VSX0VNQUlMUyBpcyB0cnVlLCBkZWZhdWx0cyB0byBmYWxzZVxuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgcHJldmVudExvZ2luV2l0aFVudmVyaWZpZWRFbWFpbDogP2Jvb2xlYW47XG4gIC8qIEVtYWlsIHZlcmlmaWNhdGlvbiB0b2tlbiB2YWxpZGl0eSBkdXJhdGlvbiwgaW4gc2Vjb25kcyAqL1xuICBlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbjogP251bWJlcjtcbiAgLyogYWNjb3VudCBsb2Nrb3V0IHBvbGljeSBmb3IgZmFpbGVkIGxvZ2luIGF0dGVtcHRzICovXG4gIGFjY291bnRMb2Nrb3V0OiA/YW55O1xuICAvKiBQYXNzd29yZCBwb2xpY3kgZm9yIGVuZm9yY2luZyBwYXNzd29yZCByZWxhdGVkIHJ1bGVzICovXG4gIHBhc3N3b3JkUG9saWN5OiA/YW55O1xuICAvKiBBZGFwdGVyIG1vZHVsZSBmb3IgdGhlIGNhY2hlICovXG4gIGNhY2hlQWRhcHRlcjogP0FkYXB0ZXI8Q2FjaGVBZGFwdGVyPjtcbiAgLyogQWRhcHRlciBtb2R1bGUgZm9yIGVtYWlsIHNlbmRpbmcgKi9cbiAgZW1haWxBZGFwdGVyOiA/QWRhcHRlcjxNYWlsQWRhcHRlcj47XG4gIC8qIFB1YmxpYyBVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLlxuICA6RU5WOiBQQVJTRV9QVUJMSUNfU0VSVkVSX1VSTCAqL1xuICBwdWJsaWNTZXJ2ZXJVUkw6ID9zdHJpbmc7XG4gIC8qIGN1c3RvbSBwYWdlcyBmb3IgcGFzc3dvcmQgdmFsaWRhdGlvbiBhbmQgcmVzZXRcbiAgOkRFRkFVTFQ6IHt9ICovXG4gIGN1c3RvbVBhZ2VzOiA/Q3VzdG9tUGFnZXNPcHRpb25zO1xuICAvKiBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY29uZmlndXJhdGlvbiBvYmplY3QgKi9cbiAgbGl2ZVF1ZXJ5OiA/TGl2ZVF1ZXJ5T3B0aW9ucztcbiAgLyogU2Vzc2lvbiBkdXJhdGlvbiwgaW4gc2Vjb25kcywgZGVmYXVsdHMgdG8gMSB5ZWFyXG4gIDpERUZBVUxUOiAzMTUzNjAwMCAqL1xuICBzZXNzaW9uTGVuZ3RoOiA/bnVtYmVyO1xuICAvKiBNYXggdmFsdWUgZm9yIGxpbWl0IG9wdGlvbiBvbiBxdWVyaWVzLCBkZWZhdWx0cyB0byB1bmxpbWl0ZWQgKi9cbiAgbWF4TGltaXQ6ID9udW1iZXI7XG4gIC8qIFNldHMgd2V0aGVyIHdlIHNob3VsZCBleHBpcmUgdGhlIGluYWN0aXZlIHNlc3Npb25zLCBkZWZhdWx0cyB0byB0cnVlXG4gIDpERUZBVUxUOiB0cnVlICovXG4gIGV4cGlyZUluYWN0aXZlU2Vzc2lvbnM6ID9ib29sZWFuO1xuICAvKiBXaGVuIGEgdXNlciBjaGFuZ2VzIHRoZWlyIHBhc3N3b3JkLCBlaXRoZXIgdGhyb3VnaCB0aGUgcmVzZXQgcGFzc3dvcmQgZW1haWwgb3Igd2hpbGUgbG9nZ2VkIGluLCBhbGwgc2Vzc2lvbnMgYXJlIHJldm9rZWQgaWYgdGhpcyBpcyB0cnVlLiBTZXQgdG8gZmFsc2UgaWYgeW91IGRvbid0IHdhbnQgdG8gcmV2b2tlIHNlc3Npb25zLlxuICA6REVGQVVMVDogdHJ1ZSAqL1xuICByZXZva2VTZXNzaW9uT25QYXNzd29yZFJlc2V0OiA/Ym9vbGVhbjtcbiAgLyogVGhlIFRUTCBmb3IgY2FjaGluZyB0aGUgc2NoZW1hIGZvciBvcHRpbWl6aW5nIHJlYWQvd3JpdGUgb3BlcmF0aW9ucy4gWW91IHNob3VsZCBwdXQgYSBsb25nIFRUTCB3aGVuIHlvdXIgREIgaXMgaW4gcHJvZHVjdGlvbi4gZGVmYXVsdCB0byA1MDAwOyBzZXQgMCB0byBkaXNhYmxlLlxuICA6REVGQVVMVDogNTAwMCAqL1xuICBzY2hlbWFDYWNoZVRUTDogP251bWJlcjtcbiAgLyogU2V0cyB0aGUgVFRMIGZvciB0aGUgaW4gbWVtb3J5IGNhY2hlIChpbiBtcyksIGRlZmF1bHRzIHRvIDUwMDAgKDUgc2Vjb25kcylcbiAgOkRFRkFVTFQ6IDUwMDAgKi9cbiAgY2FjaGVUVEw6ID9udW1iZXI7XG4gIC8qIFNldHMgdGhlIG1heGltdW0gc2l6ZSBmb3IgdGhlIGluIG1lbW9yeSBjYWNoZSwgZGVmYXVsdHMgdG8gMTAwMDBcbiAgOkRFRkFVTFQ6IDEwMDAwICovXG4gIGNhY2hlTWF4U2l6ZTogP251bWJlcjtcbiAgLyogUmVwbGFjZSBIVFRQIEludGVyZmFjZSB3aGVuIHVzaW5nIEpTIFNESyBpbiBjdXJyZW50IG5vZGUgcnVudGltZSwgZGVmYXVsdHMgdG8gZmFsc2UuIENhdXRpb24sIHRoaXMgaXMgYW4gZXhwZXJpbWVudGFsIGZlYXR1cmUgdGhhdCBtYXkgbm90IGJlIGFwcHJvcHJpYXRlIGZvciBwcm9kdWN0aW9uLlxuICA6RU5WOiBQQVJTRV9TRVJWRVJfRU5BQkxFX0VYUEVSSU1FTlRBTF9ESVJFQ1RfQUNDRVNTXG4gIDpERUZBVUxUOiBmYWxzZSAqL1xuICBkaXJlY3RBY2Nlc3M6ID9ib29sZWFuO1xuICAvKiBVc2UgYSBzaW5nbGUgc2NoZW1hIGNhY2hlIHNoYXJlZCBhY3Jvc3MgcmVxdWVzdHMuIFJlZHVjZXMgbnVtYmVyIG9mIHF1ZXJpZXMgbWFkZSB0byBfU0NIRU1BLCBkZWZhdWx0cyB0byBmYWxzZSwgaS5lLiB1bmlxdWUgc2NoZW1hIGNhY2hlIHBlciByZXF1ZXN0LlxuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgZW5hYmxlU2luZ2xlU2NoZW1hQ2FjaGU6ID9ib29sZWFuO1xuICAvKiBFbmFibGVzIHRoZSBkZWZhdWx0IGV4cHJlc3MgZXJyb3IgaGFuZGxlciBmb3IgYWxsIGVycm9yc1xuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlcjogP2Jvb2xlYW47XG4gIC8qIFNldHMgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzIGluIGdlbmVyYXRlZCBvYmplY3QgaWQncywgZGVmYXVsdCAxMFxuICA6REVGQVVMVDogMTAgKi9cbiAgb2JqZWN0SWRTaXplOiA/bnVtYmVyO1xuICAvKiBUaGUgcG9ydCB0byBydW4gdGhlIFBhcnNlU2VydmVyLCBkZWZhdWx0cyB0byAxMzM3LlxuICA6RU5WOiBQT1JUXG4gIDpERUZBVUxUOiAxMzM3ICovXG4gIHBvcnQ6ID9udW1iZXI7XG4gIC8qIFRoZSBob3N0IHRvIHNlcnZlIFBhcnNlU2VydmVyIG9uLCBkZWZhdWx0cyB0byAwLjAuMC4wXG4gIDpERUZBVUxUOiAwLjAuMC4wICovXG4gIGhvc3Q6ID9zdHJpbmc7XG4gIC8qIE1vdW50IHBhdGggZm9yIHRoZSBzZXJ2ZXIsIGRlZmF1bHRzIHRvIC9wYXJzZVxuICA6REVGQVVMVDogL3BhcnNlICovXG4gIG1vdW50UGF0aDogP3N0cmluZztcbiAgLyogUnVuIHdpdGggY2x1c3Rlciwgb3B0aW9uYWxseSBzZXQgdGhlIG51bWJlciBvZiBwcm9jZXNzZXMgZGVmYXVsdCB0byBvcy5jcHVzKCkubGVuZ3RoICovXG4gIGNsdXN0ZXI6ID9OdW1iZXJPckJvb2xlYW47XG4gIC8qIG1pZGRsZXdhcmUgZm9yIGV4cHJlc3Mgc2VydmVyLCBjYW4gYmUgc3RyaW5nIG9yIGZ1bmN0aW9uICovXG4gIG1pZGRsZXdhcmU6ID8oKCgpID0+IHZvaWQpIHwgc3RyaW5nKTtcbiAgLyogU3RhcnRzIHRoZSBsaXZlUXVlcnkgc2VydmVyICovXG4gIHN0YXJ0TGl2ZVF1ZXJ5U2VydmVyOiA/Ym9vbGVhbjtcbiAgLyogTGl2ZSBxdWVyeSBzZXJ2ZXIgY29uZmlndXJhdGlvbiBvcHRpb25zICh3aWxsIHN0YXJ0IHRoZSBsaXZlUXVlcnkgc2VydmVyKSAqL1xuICBsaXZlUXVlcnlTZXJ2ZXJPcHRpb25zOiA/TGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucztcbiAgLyogRnVsbCBwYXRoIHRvIHlvdXIgR3JhcGhRTCBjdXN0b20gc2NoZW1hLmdyYXBocWwgZmlsZSAqL1xuICBncmFwaFFMU2NoZW1hOiA/c3RyaW5nO1xuICAvKiBNb3VudHMgdGhlIEdyYXBoUUwgZW5kcG9pbnRcbiAgOkVOVjogUEFSU0VfU0VSVkVSX01PVU5UX0dSQVBIUUxcbiAgOkRFRkFVTFQ6IGZhbHNlICovXG4gIG1vdW50R3JhcGhRTDogP2Jvb2xlYW47XG4gIC8qIE1vdW50IHBhdGggZm9yIHRoZSBHcmFwaFFMIGVuZHBvaW50LCBkZWZhdWx0cyB0byAvZ3JhcGhxbFxuICA6RU5WOiBQQVJTRV9TRVJWRVJfR1JBUEhRTF9QQVRIXG4gIDpERUZBVUxUOiAvZ3JhcGhxbCAqL1xuICBncmFwaFFMUGF0aDogP3N0cmluZztcbiAgLyogTW91bnRzIHRoZSBHcmFwaFFMIFBsYXlncm91bmQgLSBuZXZlciB1c2UgdGhpcyBvcHRpb24gaW4gcHJvZHVjdGlvblxuICA6RU5WOiBQQVJTRV9TRVJWRVJfTU9VTlRfUExBWUdST1VORFxuICA6REVGQVVMVDogZmFsc2UgKi9cbiAgbW91bnRQbGF5Z3JvdW5kOiA/Ym9vbGVhbjtcbiAgLyogTW91bnQgcGF0aCBmb3IgdGhlIEdyYXBoUUwgUGxheWdyb3VuZCwgZGVmYXVsdHMgdG8gL3BsYXlncm91bmRcbiAgOkVOVjogUEFSU0VfU0VSVkVSX1BMQVlHUk9VTkRfUEFUSFxuICA6REVGQVVMVDogL3BsYXlncm91bmQgKi9cbiAgcGxheWdyb3VuZFBhdGg6ID9zdHJpbmc7XG4gIC8qIENhbGxiYWNrIHdoZW4gc2VydmVyIGhhcyBzdGFydGVkICovXG4gIHNlcnZlclN0YXJ0Q29tcGxldGU6ID8oZXJyb3I6ID9FcnJvcikgPT4gdm9pZDtcbiAgLyogQ2FsbGJhY2sgd2hlbiBzZXJ2ZXIgaGFzIGNsb3NlZCAqL1xuICBzZXJ2ZXJDbG9zZUNvbXBsZXRlOiA/KCkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDdXN0b21QYWdlc09wdGlvbnMge1xuICAvKiBpbnZhbGlkIGxpbmsgcGFnZSBwYXRoICovXG4gIGludmFsaWRMaW5rOiA/c3RyaW5nO1xuICAvKiB2ZXJpZnkgZW1haWwgc3VjY2VzcyBwYWdlIHBhdGggKi9cbiAgdmVyaWZ5RW1haWxTdWNjZXNzOiA/c3RyaW5nO1xuICAvKiBpbnZhbGlkIHZlcmlmaWNhdGlvbiBsaW5rIHBhZ2UgcGF0aCAqL1xuICBpbnZhbGlkVmVyaWZpY2F0aW9uTGluazogP3N0cmluZztcbiAgLyogdmVyaWZpY2F0aW9uIGxpbmsgc2VuZCBzdWNjZXNzIHBhZ2UgcGF0aCAqL1xuICBsaW5rU2VuZFN1Y2Nlc3M6ID9zdHJpbmc7XG4gIC8qIHZlcmlmaWNhdGlvbiBsaW5rIHNlbmQgZmFpbCBwYWdlIHBhdGggKi9cbiAgbGlua1NlbmRGYWlsOiA/c3RyaW5nO1xuICAvKiBjaG9vc2UgcGFzc3dvcmQgcGFnZSBwYXRoICovXG4gIGNob29zZVBhc3N3b3JkOiA/c3RyaW5nO1xuICAvKiBwYXNzd29yZCByZXNldCBzdWNjZXNzIHBhZ2UgcGF0aCAqL1xuICBwYXNzd29yZFJlc2V0U3VjY2VzczogP3N0cmluZztcbiAgLyogZm9yIG1hc2tpbmcgdXNlci1mYWNpbmcgcGFnZXMgKi9cbiAgcGFyc2VGcmFtZVVSTDogP3N0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMaXZlUXVlcnlPcHRpb25zIHtcbiAgLyogcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IGNsYXNzTmFtZXNcbiAgOkVOVjogUEFSU0VfU0VSVkVSX0xJVkVRVUVSWV9DTEFTU05BTUVTICovXG4gIGNsYXNzTmFtZXM6ID8oc3RyaW5nW10pO1xuICAvKiBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNPcHRpb25zICovXG4gIHJlZGlzT3B0aW9uczogP2FueTtcbiAgLyogcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzVVJMICovXG4gIHJlZGlzVVJMOiA/c3RyaW5nO1xuICAvKiBMaXZlUXVlcnkgcHVic3ViIGFkYXB0ZXIgKi9cbiAgcHViU3ViQWRhcHRlcjogP0FkYXB0ZXI8UHViU3ViQWRhcHRlcj47XG4gIC8qIEFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgV2ViU29ja2V0U2VydmVyICovXG4gIHdzc0FkYXB0ZXI6ID9BZGFwdGVyPFdTU0FkYXB0ZXI+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpdmVRdWVyeVNlcnZlck9wdGlvbnMge1xuICAvKiBUaGlzIHN0cmluZyBzaG91bGQgbWF0Y2ggdGhlIGFwcElkIGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgYXBwSWQuKi9cbiAgYXBwSWQ6ID9zdHJpbmc7XG4gIC8qIFRoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgbWFzdGVyS2V5IGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgbWFzdGVyS2V5LiovXG4gIG1hc3RlcktleTogP3N0cmluZztcbiAgLyogVGhpcyBzdHJpbmcgc2hvdWxkIG1hdGNoIHRoZSBzZXJ2ZXJVUkwgaW4gdXNlIGJ5IHlvdXIgUGFyc2UgU2VydmVyLiBJZiB5b3UgZGVwbG95IHRoZSBMaXZlUXVlcnkgc2VydmVyIGFsb25nc2lkZSBQYXJzZSBTZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIHVzZSB0aGUgc2FtZSBzZXJ2ZXJVUkwuKi9cbiAgc2VydmVyVVJMOiA/c3RyaW5nO1xuICAvKiBBIEpTT04gb2JqZWN0IHRoYXQgc2VydmVzIGFzIGEgd2hpdGVsaXN0IG9mIGtleXMuIEl0IGlzIHVzZWQgZm9yIHZhbGlkYXRpbmcgY2xpZW50cyB3aGVuIHRoZXkgdHJ5IHRvIGNvbm5lY3QgdG8gdGhlIExpdmVRdWVyeSBzZXJ2ZXIuIENoZWNrIHRoZSBmb2xsb3dpbmcgU2VjdXJpdHkgc2VjdGlvbiBhbmQgb3VyIHByb3RvY29sIHNwZWNpZmljYXRpb24gZm9yIGRldGFpbHMuKi9cbiAga2V5UGFpcnM6ID9hbnk7XG4gIC8qIE51bWJlciBvZiBtaWxsaXNlY29uZHMgYmV0d2VlbiBwaW5nL3BvbmcgZnJhbWVzLiBUaGUgV2ViU29ja2V0IHNlcnZlciBzZW5kcyBwaW5nL3BvbmcgZnJhbWVzIHRvIHRoZSBjbGllbnRzIHRvIGtlZXAgdGhlIFdlYlNvY2tldCBhbGl2ZS4gVGhpcyB2YWx1ZSBkZWZpbmVzIHRoZSBpbnRlcnZhbCBvZiB0aGUgcGluZy9wb25nIGZyYW1lIGZyb20gdGhlIHNlcnZlciB0byBjbGllbnRzLCBkZWZhdWx0cyB0byAxMCAqIDEwMDAgbXMgKDEwIHMpLiovXG4gIHdlYnNvY2tldFRpbWVvdXQ6ID9udW1iZXI7XG4gIC8qIE51bWJlciBpbiBtaWxsaXNlY29uZHMuIFdoZW4gY2xpZW50cyBwcm92aWRlIHRoZSBzZXNzaW9uVG9rZW4gdG8gdGhlIExpdmVRdWVyeSBzZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIGZldGNoIGl0cyBQYXJzZVVzZXIncyBvYmplY3RJZCBmcm9tIHBhcnNlIHNlcnZlciBhbmQgc3RvcmUgaXQgaW4gdGhlIGNhY2hlLiBUaGUgdmFsdWUgZGVmaW5lcyB0aGUgZHVyYXRpb24gb2YgdGhlIGNhY2hlLiBDaGVjayB0aGUgZm9sbG93aW5nIFNlY3VyaXR5IHNlY3Rpb24gYW5kIG91ciBwcm90b2NvbCBzcGVjaWZpY2F0aW9uIGZvciBkZXRhaWxzLCBkZWZhdWx0cyB0byAzMCAqIDI0ICogNjAgKiA2MCAqIDEwMDAgbXMgKH4zMCBkYXlzKS4qL1xuICBjYWNoZVRpbWVvdXQ6ID9udW1iZXI7XG4gIC8qIFRoaXMgc3RyaW5nIGRlZmluZXMgdGhlIGxvZyBsZXZlbCBvZiB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gV2Ugc3VwcG9ydCBWRVJCT1NFLCBJTkZPLCBFUlJPUiwgTk9ORSwgZGVmYXVsdHMgdG8gSU5GTy4qL1xuICBsb2dMZXZlbDogP3N0cmluZztcbiAgLyogVGhlIHBvcnQgdG8gcnVuIHRoZSBMaXZlUXVlcnkgc2VydmVyLCBkZWZhdWx0cyB0byAxMzM3LlxuICA6REVGQVVMVDogMTMzNyAqL1xuICBwb3J0OiA/bnVtYmVyO1xuICAvKiBwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNPcHRpb25zICovXG4gIHJlZGlzT3B0aW9uczogP2FueTtcbiAgLyogcGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzVVJMICovXG4gIHJlZGlzVVJMOiA/c3RyaW5nO1xuICAvKiBMaXZlUXVlcnkgcHVic3ViIGFkYXB0ZXIgKi9cbiAgcHViU3ViQWRhcHRlcjogP0FkYXB0ZXI8UHViU3ViQWRhcHRlcj47XG4gIC8qIEFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgV2ViU29ja2V0U2VydmVyICovXG4gIHdzc0FkYXB0ZXI6ID9BZGFwdGVyPFdTU0FkYXB0ZXI+O1xufVxuIl19 \ 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..3ee49ac514 --- /dev/null +++ b/lib/ParseServer.js @@ -0,0 +1,491 @@ +"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 _ExportRouter = require("./Routers/ExportRouter"); + +var _ImportRouter = require("./Routers/ImportRouter"); + +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('/', new _ImportRouter.ImportRouter().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(), new _ExportRouter.ExportRouter()]; + 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 (typeof options.graphQLSchema === 'string') { + graphQLCustomTypeDefs = parse(fs.readFileSync(options.graphQLSchema, 'utf8')); + } else if (typeof options.graphQLSchema === 'object') { + graphQLCustomTypeDefs = options.graphQLSchema; + } + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZVNlcnZlci5qcyJdLCJuYW1lcyI6WyJiYXRjaCIsInJlcXVpcmUiLCJib2R5UGFyc2VyIiwiZXhwcmVzcyIsIm1pZGRsZXdhcmVzIiwiUGFyc2UiLCJwYXJzZSIsInBhdGgiLCJmcyIsImFkZFBhcnNlQ2xvdWQiLCJQYXJzZVNlcnZlciIsImNvbnN0cnVjdG9yIiwib3B0aW9ucyIsImluamVjdERlZmF1bHRzIiwiYXBwSWQiLCJtYXN0ZXJLZXkiLCJjbG91ZCIsImphdmFzY3JpcHRLZXkiLCJzZXJ2ZXJVUkwiLCJzZXJ2ZXJTdGFydENvbXBsZXRlIiwiaW5pdGlhbGl6ZSIsImFsbENvbnRyb2xsZXJzIiwiY29udHJvbGxlcnMiLCJnZXRDb250cm9sbGVycyIsImxvZ2dlckNvbnRyb2xsZXIiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJob29rc0NvbnRyb2xsZXIiLCJjb25maWciLCJDb25maWciLCJwdXQiLCJPYmplY3QiLCJhc3NpZ24iLCJsb2dnaW5nIiwic2V0TG9nZ2VyIiwiZGJJbml0UHJvbWlzZSIsInBlcmZvcm1Jbml0aWFsaXphdGlvbiIsImhvb2tzTG9hZFByb21pc2UiLCJsb2FkIiwiUHJvbWlzZSIsImFsbCIsInRoZW4iLCJjYXRjaCIsImVycm9yIiwiY29uc29sZSIsInByb2Nlc3MiLCJleGl0IiwicmVzb2x2ZSIsImN3ZCIsImFwcCIsIl9hcHAiLCJoYW5kbGVTaHV0ZG93biIsInByb21pc2VzIiwiYWRhcHRlciIsImRhdGFiYXNlQWRhcHRlciIsInB1c2giLCJmaWxlQWRhcHRlciIsImZpbGVzQ29udHJvbGxlciIsImxlbmd0aCIsInNlcnZlckNsb3NlQ29tcGxldGUiLCJtYXhVcGxvYWRTaXplIiwiZGlyZWN0QWNjZXNzIiwiYXBpIiwidXNlIiwiYWxsb3dDcm9zc0RvbWFpbiIsIkZpbGVzUm91dGVyIiwiZXhwcmVzc1JvdXRlciIsInJlcSIsInJlcyIsImpzb24iLCJzdGF0dXMiLCJ1cmxlbmNvZGVkIiwiZXh0ZW5kZWQiLCJQdWJsaWNBUElSb3V0ZXIiLCJJbXBvcnRSb3V0ZXIiLCJ0eXBlIiwibGltaXQiLCJhbGxvd01ldGhvZE92ZXJyaWRlIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwiYXBwUm91dGVyIiwicHJvbWlzZVJvdXRlciIsImhhbmRsZVBhcnNlRXJyb3JzIiwiZW52IiwiVEVTVElORyIsIm9uIiwiZXJyIiwiY29kZSIsInN0ZGVyciIsIndyaXRlIiwicG9ydCIsInZlcmlmeVNlcnZlclVybCIsIlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MiLCJDb3JlTWFuYWdlciIsInNldFJFU1RDb250cm9sbGVyIiwicm91dGVycyIsIkNsYXNzZXNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsIlNlc3Npb25zUm91dGVyIiwiUm9sZXNSb3V0ZXIiLCJBbmFseXRpY3NSb3V0ZXIiLCJJbnN0YWxsYXRpb25zUm91dGVyIiwiRnVuY3Rpb25zUm91dGVyIiwiU2NoZW1hc1JvdXRlciIsIlB1c2hSb3V0ZXIiLCJMb2dzUm91dGVyIiwiSUFQVmFsaWRhdGlvblJvdXRlciIsIkZlYXR1cmVzUm91dGVyIiwiR2xvYmFsQ29uZmlnUm91dGVyIiwiR3JhcGhRTFJvdXRlciIsIlB1cmdlUm91dGVyIiwiSG9va3NSb3V0ZXIiLCJDbG91ZENvZGVSb3V0ZXIiLCJBdWRpZW5jZXNSb3V0ZXIiLCJBZ2dyZWdhdGVSb3V0ZXIiLCJFeHBvcnRSb3V0ZXIiLCJyb3V0ZXMiLCJyZWR1Y2UiLCJtZW1vIiwicm91dGVyIiwiY29uY2F0IiwiUHJvbWlzZVJvdXRlciIsIm1vdW50T250byIsInN0YXJ0IiwiY2FsbGJhY2siLCJtaWRkbGV3YXJlIiwibW91bnRQYXRoIiwibW91bnRHcmFwaFFMIiwibW91bnRQbGF5Z3JvdW5kIiwiZ3JhcGhRTEN1c3RvbVR5cGVEZWZzIiwidW5kZWZpbmVkIiwiZ3JhcGhRTFNjaGVtYSIsInJlYWRGaWxlU3luYyIsInBhcnNlR3JhcGhRTFNlcnZlciIsIlBhcnNlR3JhcGhRTFNlcnZlciIsImdyYXBoUUxQYXRoIiwicGxheWdyb3VuZFBhdGgiLCJhcHBseUdyYXBoUUwiLCJhcHBseVBsYXlncm91bmQiLCJzZXJ2ZXIiLCJsaXN0ZW4iLCJob3N0Iiwic3RhcnRMaXZlUXVlcnlTZXJ2ZXIiLCJsaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIiwibGl2ZVF1ZXJ5U2VydmVyIiwiY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyIiwiY29uZmlndXJlTGlzdGVuZXJzIiwiZXhwcmVzc0FwcCIsInBhcnNlU2VydmVyIiwiaHR0cFNlcnZlciIsImNyZWF0ZVNlcnZlciIsIlBhcnNlTGl2ZVF1ZXJ5U2VydmVyIiwicmVxdWVzdCIsInVybCIsInJlcGxhY2UiLCJyZXNwb25zZSIsImRhdGEiLCJ3YXJuIiwiUGFyc2VDbG91ZCIsIkNsb3VkIiwiZ2xvYmFsIiwia2V5cyIsImRlZmF1bHRzIiwiZm9yRWFjaCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsInJlZ2V4IiwibWF0Y2giLCJ1c2VyU2Vuc2l0aXZlRmllbGRzIiwiQXJyYXkiLCJmcm9tIiwiU2V0IiwicHJvdGVjdGVkRmllbGRzIiwiX1VzZXIiLCJjIiwiY3VyIiwiciIsInVucSIsIm1hc3RlcktleUlwcyIsInNvY2tldHMiLCJzb2NrZXQiLCJzb2NrZXRJZCIsInJlbW90ZUFkZHJlc3MiLCJyZW1vdGVQb3J0IiwiZGVzdHJveUFsaXZlQ29ubmVjdGlvbnMiLCJkZXN0cm95IiwiZSIsInN0ZG91dCIsImNsb3NlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBV0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBM0NBO0FBRUEsSUFBSUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsU0FBRCxDQUFuQjtBQUFBLElBQ0VDLFVBQVUsR0FBR0QsT0FBTyxDQUFDLGFBQUQsQ0FEdEI7QUFBQSxJQUVFRSxPQUFPLEdBQUdGLE9BQU8sQ0FBQyxTQUFELENBRm5CO0FBQUEsSUFHRUcsV0FBVyxHQUFHSCxPQUFPLENBQUMsZUFBRCxDQUh2QjtBQUFBLElBSUVJLEtBQUssR0FBR0osT0FBTyxDQUFDLFlBQUQsQ0FBUCxDQUFzQkksS0FKaEM7QUFBQSxJQUtFO0FBQUVDLEVBQUFBO0FBQUYsSUFBWUwsT0FBTyxDQUFDLFNBQUQsQ0FMckI7QUFBQSxJQU1FTSxJQUFJLEdBQUdOLE9BQU8sQ0FBQyxNQUFELENBTmhCO0FBQUEsSUFPRU8sRUFBRSxHQUFHUCxPQUFPLENBQUMsSUFBRCxDQVBkOztBQTJDQTtBQUNBUSxhQUFhLEcsQ0FFYjtBQUNBOztBQUNBLE1BQU1DLFdBQU4sQ0FBa0I7QUFDaEI7Ozs7QUFJQUMsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQThCO0FBQ3ZDQyxJQUFBQSxjQUFjLENBQUNELE9BQUQsQ0FBZDtBQUNBLFVBQU07QUFDSkUsTUFBQUEsS0FBSyxHQUFHLGdDQUFrQiw0QkFBbEIsQ0FESjtBQUVKQyxNQUFBQSxTQUFTLEdBQUcsZ0NBQWtCLCtCQUFsQixDQUZSO0FBR0pDLE1BQUFBLEtBSEk7QUFJSkMsTUFBQUEsYUFKSTtBQUtKQyxNQUFBQSxTQUFTLEdBQUcsZ0NBQWtCLCtCQUFsQixDQUxSO0FBTUpDLE1BQUFBO0FBTkksUUFPRlAsT0FQSixDQUZ1QyxDQVV2Qzs7QUFDQVAsSUFBQUEsS0FBSyxDQUFDZSxVQUFOLENBQWlCTixLQUFqQixFQUF3QkcsYUFBYSxJQUFJLFFBQXpDLEVBQW1ERixTQUFuRDtBQUNBVixJQUFBQSxLQUFLLENBQUNhLFNBQU4sR0FBa0JBLFNBQWxCO0FBRUEsVUFBTUcsY0FBYyxHQUFHQyxXQUFXLENBQUNDLGNBQVosQ0FBMkJYLE9BQTNCLENBQXZCO0FBRUEsVUFBTTtBQUNKWSxNQUFBQSxnQkFESTtBQUVKQyxNQUFBQSxrQkFGSTtBQUdKQyxNQUFBQTtBQUhJLFFBSUZMLGNBSko7QUFLQSxTQUFLTSxNQUFMLEdBQWNDLGdCQUFPQyxHQUFQLENBQVdDLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjLEVBQWQsRUFBa0JuQixPQUFsQixFQUEyQlMsY0FBM0IsQ0FBWCxDQUFkO0FBRUFXLElBQUFBLE9BQU8sQ0FBQ0MsU0FBUixDQUFrQlQsZ0JBQWxCO0FBQ0EsVUFBTVUsYUFBYSxHQUFHVCxrQkFBa0IsQ0FBQ1UscUJBQW5CLEVBQXRCO0FBQ0EsVUFBTUMsZ0JBQWdCLEdBQUdWLGVBQWUsQ0FBQ1csSUFBaEIsRUFBekIsQ0F6QnVDLENBMkJ2Qzs7QUFDQUMsSUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQVksQ0FBQ0wsYUFBRCxFQUFnQkUsZ0JBQWhCLENBQVosRUFDR0ksSUFESCxDQUNRLE1BQU07QUFDVixVQUFJckIsbUJBQUosRUFBeUI7QUFDdkJBLFFBQUFBLG1CQUFtQjtBQUNwQjtBQUNGLEtBTEgsRUFNR3NCLEtBTkgsQ0FNU0MsS0FBSyxJQUFJO0FBQ2QsVUFBSXZCLG1CQUFKLEVBQXlCO0FBQ3ZCQSxRQUFBQSxtQkFBbUIsQ0FBQ3VCLEtBQUQsQ0FBbkI7QUFDRCxPQUZELE1BRU87QUFDTEMsUUFBQUEsT0FBTyxDQUFDRCxLQUFSLENBQWNBLEtBQWQ7QUFDQUUsUUFBQUEsT0FBTyxDQUFDQyxJQUFSLENBQWEsQ0FBYjtBQUNEO0FBQ0YsS0FiSDs7QUFlQSxRQUFJN0IsS0FBSixFQUFXO0FBQ1RQLE1BQUFBLGFBQWE7O0FBQ2IsVUFBSSxPQUFPTyxLQUFQLEtBQWlCLFVBQXJCLEVBQWlDO0FBQy9CQSxRQUFBQSxLQUFLLENBQUNYLEtBQUQsQ0FBTDtBQUNELE9BRkQsTUFFTyxJQUFJLE9BQU9XLEtBQVAsS0FBaUIsUUFBckIsRUFBK0I7QUFDcENmLFFBQUFBLE9BQU8sQ0FBQ00sSUFBSSxDQUFDdUMsT0FBTCxDQUFhRixPQUFPLENBQUNHLEdBQVIsRUFBYixFQUE0Qi9CLEtBQTVCLENBQUQsQ0FBUDtBQUNELE9BRk0sTUFFQTtBQUNMLGNBQU0sd0RBQU47QUFDRDtBQUNGO0FBQ0Y7O0FBRUQsTUFBSWdDLEdBQUosR0FBVTtBQUNSLFFBQUksQ0FBQyxLQUFLQyxJQUFWLEVBQWdCO0FBQ2QsV0FBS0EsSUFBTCxHQUFZdkMsV0FBVyxDQUFDc0MsR0FBWixDQUFnQixLQUFLckIsTUFBckIsQ0FBWjtBQUNEOztBQUNELFdBQU8sS0FBS3NCLElBQVo7QUFDRDs7QUFFREMsRUFBQUEsY0FBYyxHQUFHO0FBQ2YsVUFBTUMsUUFBUSxHQUFHLEVBQWpCO0FBQ0EsVUFBTTtBQUFFQyxNQUFBQSxPQUFPLEVBQUVDO0FBQVgsUUFBK0IsS0FBSzFCLE1BQUwsQ0FBWUYsa0JBQWpEOztBQUNBLFFBQ0U0QixlQUFlLElBQ2YsT0FBT0EsZUFBZSxDQUFDSCxjQUF2QixLQUEwQyxVQUY1QyxFQUdFO0FBQ0FDLE1BQUFBLFFBQVEsQ0FBQ0csSUFBVCxDQUFjRCxlQUFlLENBQUNILGNBQWhCLEVBQWQ7QUFDRDs7QUFDRCxVQUFNO0FBQUVFLE1BQUFBLE9BQU8sRUFBRUc7QUFBWCxRQUEyQixLQUFLNUIsTUFBTCxDQUFZNkIsZUFBN0M7O0FBQ0EsUUFBSUQsV0FBVyxJQUFJLE9BQU9BLFdBQVcsQ0FBQ0wsY0FBbkIsS0FBc0MsVUFBekQsRUFBcUU7QUFDbkVDLE1BQUFBLFFBQVEsQ0FBQ0csSUFBVCxDQUFjQyxXQUFXLENBQUNMLGNBQVosRUFBZDtBQUNEOztBQUNELFdBQU8sQ0FBQ0MsUUFBUSxDQUFDTSxNQUFULEdBQWtCLENBQWxCLEdBQ0puQixPQUFPLENBQUNDLEdBQVIsQ0FBWVksUUFBWixDQURJLEdBRUpiLE9BQU8sQ0FBQ1EsT0FBUixFQUZHLEVBR0xOLElBSEssQ0FHQSxNQUFNO0FBQ1gsVUFBSSxLQUFLYixNQUFMLENBQVkrQixtQkFBaEIsRUFBcUM7QUFDbkMsYUFBSy9CLE1BQUwsQ0FBWStCLG1CQUFaO0FBQ0Q7QUFDRixLQVBNLENBQVA7QUFRRDtBQUVEOzs7Ozs7QUFJQSxTQUFPVixHQUFQLENBQVc7QUFBRVcsSUFBQUEsYUFBYSxHQUFHLE1BQWxCO0FBQTBCN0MsSUFBQUEsS0FBMUI7QUFBaUM4QyxJQUFBQTtBQUFqQyxHQUFYLEVBQTREO0FBQzFEO0FBQ0E7QUFDQSxRQUFJQyxHQUFHLEdBQUcxRCxPQUFPLEVBQWpCLENBSDBELENBSTFEOztBQUNBMEQsSUFBQUEsR0FBRyxDQUFDQyxHQUFKLENBQVExRCxXQUFXLENBQUMyRCxnQkFBWixDQUE2QmpELEtBQTdCLENBQVIsRUFMMEQsQ0FNMUQ7O0FBQ0ErQyxJQUFBQSxHQUFHLENBQUNDLEdBQUosQ0FDRSxHQURGLEVBRUUsSUFBSUUsd0JBQUosR0FBa0JDLGFBQWxCLENBQWdDO0FBQzlCTixNQUFBQSxhQUFhLEVBQUVBO0FBRGUsS0FBaEMsQ0FGRjtBQU9BRSxJQUFBQSxHQUFHLENBQUNDLEdBQUosQ0FBUSxTQUFSLEVBQW1CLFVBQVNJLEdBQVQsRUFBY0MsR0FBZCxFQUFtQjtBQUNwQ0EsTUFBQUEsR0FBRyxDQUFDQyxJQUFKLENBQVM7QUFDUEMsUUFBQUEsTUFBTSxFQUFFO0FBREQsT0FBVDtBQUdELEtBSkQ7QUFNQVIsSUFBQUEsR0FBRyxDQUFDQyxHQUFKLENBQ0UsR0FERixFQUVFNUQsVUFBVSxDQUFDb0UsVUFBWCxDQUFzQjtBQUFFQyxNQUFBQSxRQUFRLEVBQUU7QUFBWixLQUF0QixDQUZGLEVBR0UsSUFBSUMsZ0NBQUosR0FBc0JQLGFBQXRCLEVBSEY7QUFNQUosSUFBQUEsR0FBRyxDQUFDQyxHQUFKLENBQVEsR0FBUixFQUFhLElBQUlXLDBCQUFKLEdBQW1CUixhQUFuQixFQUFiO0FBQ0FKLElBQUFBLEdBQUcsQ0FBQ0MsR0FBSixDQUFRNUQsVUFBVSxDQUFDa0UsSUFBWCxDQUFnQjtBQUFFTSxNQUFBQSxJQUFJLEVBQUUsS0FBUjtBQUFlQyxNQUFBQSxLQUFLLEVBQUVoQjtBQUF0QixLQUFoQixDQUFSO0FBQ0FFLElBQUFBLEdBQUcsQ0FBQ0MsR0FBSixDQUFRMUQsV0FBVyxDQUFDd0UsbUJBQXBCO0FBQ0FmLElBQUFBLEdBQUcsQ0FBQ0MsR0FBSixDQUFRMUQsV0FBVyxDQUFDeUUsa0JBQXBCO0FBRUEsVUFBTUMsU0FBUyxHQUFHcEUsV0FBVyxDQUFDcUUsYUFBWixDQUEwQjtBQUFFakUsTUFBQUE7QUFBRixLQUExQixDQUFsQjtBQUNBK0MsSUFBQUEsR0FBRyxDQUFDQyxHQUFKLENBQVFnQixTQUFTLENBQUNiLGFBQVYsRUFBUjtBQUVBSixJQUFBQSxHQUFHLENBQUNDLEdBQUosQ0FBUTFELFdBQVcsQ0FBQzRFLGlCQUFwQixFQWxDMEQsQ0FvQzFEOztBQUNBLFFBQUksQ0FBQ3BDLE9BQU8sQ0FBQ3FDLEdBQVIsQ0FBWUMsT0FBakIsRUFBMEI7QUFDeEI7O0FBQ0E7QUFDQXRDLE1BQUFBLE9BQU8sQ0FBQ3VDLEVBQVIsQ0FBVyxtQkFBWCxFQUFnQ0MsR0FBRyxJQUFJO0FBQ3JDLFlBQUlBLEdBQUcsQ0FBQ0MsSUFBSixLQUFhLFlBQWpCLEVBQStCO0FBQzdCO0FBQ0F6QyxVQUFBQSxPQUFPLENBQUMwQyxNQUFSLENBQWVDLEtBQWYsQ0FDRyw0QkFBMkJILEdBQUcsQ0FBQ0ksSUFBSywrQkFEdkM7QUFHQTVDLFVBQUFBLE9BQU8sQ0FBQ0MsSUFBUixDQUFhLENBQWI7QUFDRCxTQU5ELE1BTU87QUFDTCxnQkFBTXVDLEdBQU47QUFDRDtBQUNGLE9BVkQsRUFId0IsQ0FjeEI7O0FBQ0E7O0FBQ0F2QixNQUFBQSxHQUFHLENBQUNzQixFQUFKLENBQU8sT0FBUCxFQUFnQixZQUFXO0FBQ3pCekUsUUFBQUEsV0FBVyxDQUFDK0UsZUFBWjtBQUNELE9BRkQ7QUFHRDs7QUFDRCxRQUNFN0MsT0FBTyxDQUFDcUMsR0FBUixDQUFZUyw4Q0FBWixLQUErRCxHQUEvRCxJQUNBOUIsWUFGRixFQUdFO0FBQ0F2RCxNQUFBQSxLQUFLLENBQUNzRixXQUFOLENBQWtCQyxpQkFBbEIsQ0FDRSwwREFBMEI5RSxLQUExQixFQUFpQ2dFLFNBQWpDLENBREY7QUFHRDs7QUFDRCxXQUFPakIsR0FBUDtBQUNEOztBQUVELFNBQU9rQixhQUFQLENBQXFCO0FBQUVqRSxJQUFBQTtBQUFGLEdBQXJCLEVBQWdDO0FBQzlCLFVBQU0rRSxPQUFPLEdBQUcsQ0FDZCxJQUFJQyw0QkFBSixFQURjLEVBRWQsSUFBSUMsd0JBQUosRUFGYyxFQUdkLElBQUlDLDhCQUFKLEVBSGMsRUFJZCxJQUFJQyx3QkFBSixFQUpjLEVBS2QsSUFBSUMsZ0NBQUosRUFMYyxFQU1kLElBQUlDLHdDQUFKLEVBTmMsRUFPZCxJQUFJQyxnQ0FBSixFQVBjLEVBUWQsSUFBSUMsNEJBQUosRUFSYyxFQVNkLElBQUlDLHNCQUFKLEVBVGMsRUFVZCxJQUFJQyxzQkFBSixFQVZjLEVBV2QsSUFBSUMsd0NBQUosRUFYYyxFQVlkLElBQUlDLDhCQUFKLEVBWmMsRUFhZCxJQUFJQyxzQ0FBSixFQWJjLEVBY2QsSUFBSUMsNEJBQUosRUFkYyxFQWVkLElBQUlDLHdCQUFKLEVBZmMsRUFnQmQsSUFBSUMsd0JBQUosRUFoQmMsRUFpQmQsSUFBSUMsZ0NBQUosRUFqQmMsRUFrQmQsSUFBSUMsZ0NBQUosRUFsQmMsRUFtQmQsSUFBSUMsZ0NBQUosRUFuQmMsRUFvQmQsSUFBSUMsMEJBQUosRUFwQmMsQ0FBaEI7QUF1QkEsVUFBTUMsTUFBTSxHQUFHckIsT0FBTyxDQUFDc0IsTUFBUixDQUFlLENBQUNDLElBQUQsRUFBT0MsTUFBUCxLQUFrQjtBQUM5QyxhQUFPRCxJQUFJLENBQUNFLE1BQUwsQ0FBWUQsTUFBTSxDQUFDSCxNQUFuQixDQUFQO0FBQ0QsS0FGYyxFQUVaLEVBRlksQ0FBZjtBQUlBLFVBQU1wQyxTQUFTLEdBQUcsSUFBSXlDLHNCQUFKLENBQWtCTCxNQUFsQixFQUEwQnBHLEtBQTFCLENBQWxCO0FBRUFkLElBQUFBLEtBQUssQ0FBQ3dILFNBQU4sQ0FBZ0IxQyxTQUFoQjtBQUNBLFdBQU9BLFNBQVA7QUFDRDtBQUVEOzs7Ozs7OztBQU1BMkMsRUFBQUEsS0FBSyxDQUFDN0csT0FBRCxFQUE4QjhHLFFBQTlCLEVBQXFEO0FBQ3hELFVBQU0xRSxHQUFHLEdBQUc3QyxPQUFPLEVBQW5COztBQUNBLFFBQUlTLE9BQU8sQ0FBQytHLFVBQVosRUFBd0I7QUFDdEIsVUFBSUEsVUFBSjs7QUFDQSxVQUFJLE9BQU8vRyxPQUFPLENBQUMrRyxVQUFmLElBQTZCLFFBQWpDLEVBQTJDO0FBQ3pDQSxRQUFBQSxVQUFVLEdBQUcxSCxPQUFPLENBQUNNLElBQUksQ0FBQ3VDLE9BQUwsQ0FBYUYsT0FBTyxDQUFDRyxHQUFSLEVBQWIsRUFBNEJuQyxPQUFPLENBQUMrRyxVQUFwQyxDQUFELENBQXBCO0FBQ0QsT0FGRCxNQUVPO0FBQ0xBLFFBQUFBLFVBQVUsR0FBRy9HLE9BQU8sQ0FBQytHLFVBQXJCLENBREssQ0FDNEI7QUFDbEM7O0FBQ0QzRSxNQUFBQSxHQUFHLENBQUNjLEdBQUosQ0FBUTZELFVBQVI7QUFDRDs7QUFFRDNFLElBQUFBLEdBQUcsQ0FBQ2MsR0FBSixDQUFRbEQsT0FBTyxDQUFDZ0gsU0FBaEIsRUFBMkIsS0FBSzVFLEdBQWhDOztBQUVBLFFBQUlwQyxPQUFPLENBQUNpSCxZQUFSLEtBQXlCLElBQXpCLElBQWlDakgsT0FBTyxDQUFDa0gsZUFBUixLQUE0QixJQUFqRSxFQUF1RTtBQUNyRSxVQUFJQyxxQkFBcUIsR0FBR0MsU0FBNUI7O0FBQ0EsVUFBSSxPQUFPcEgsT0FBTyxDQUFDcUgsYUFBZixLQUFpQyxRQUFyQyxFQUErQztBQUM3Q0YsUUFBQUEscUJBQXFCLEdBQUd6SCxLQUFLLENBQzNCRSxFQUFFLENBQUMwSCxZQUFILENBQWdCdEgsT0FBTyxDQUFDcUgsYUFBeEIsRUFBdUMsTUFBdkMsQ0FEMkIsQ0FBN0I7QUFHRCxPQUpELE1BSU8sSUFBSSxPQUFPckgsT0FBTyxDQUFDcUgsYUFBZixLQUFpQyxRQUFyQyxFQUErQztBQUNwREYsUUFBQUEscUJBQXFCLEdBQUduSCxPQUFPLENBQUNxSCxhQUFoQztBQUNEOztBQUVELFlBQU1FLGtCQUFrQixHQUFHLElBQUlDLHNDQUFKLENBQXVCLElBQXZCLEVBQTZCO0FBQ3REQyxRQUFBQSxXQUFXLEVBQUV6SCxPQUFPLENBQUN5SCxXQURpQztBQUV0REMsUUFBQUEsY0FBYyxFQUFFMUgsT0FBTyxDQUFDMEgsY0FGOEI7QUFHdERQLFFBQUFBO0FBSHNELE9BQTdCLENBQTNCOztBQU1BLFVBQUluSCxPQUFPLENBQUNpSCxZQUFaLEVBQTBCO0FBQ3hCTSxRQUFBQSxrQkFBa0IsQ0FBQ0ksWUFBbkIsQ0FBZ0N2RixHQUFoQztBQUNEOztBQUVELFVBQUlwQyxPQUFPLENBQUNrSCxlQUFaLEVBQTZCO0FBQzNCSyxRQUFBQSxrQkFBa0IsQ0FBQ0ssZUFBbkIsQ0FBbUN4RixHQUFuQztBQUNEO0FBQ0Y7O0FBRUQsVUFBTXlGLE1BQU0sR0FBR3pGLEdBQUcsQ0FBQzBGLE1BQUosQ0FBVzlILE9BQU8sQ0FBQzRFLElBQW5CLEVBQXlCNUUsT0FBTyxDQUFDK0gsSUFBakMsRUFBdUNqQixRQUF2QyxDQUFmO0FBQ0EsU0FBS2UsTUFBTCxHQUFjQSxNQUFkOztBQUVBLFFBQUk3SCxPQUFPLENBQUNnSSxvQkFBUixJQUFnQ2hJLE9BQU8sQ0FBQ2lJLHNCQUE1QyxFQUFvRTtBQUNsRSxXQUFLQyxlQUFMLEdBQXVCcEksV0FBVyxDQUFDcUkscUJBQVosQ0FDckJOLE1BRHFCLEVBRXJCN0gsT0FBTyxDQUFDaUksc0JBRmEsQ0FBdkI7QUFJRDtBQUNEOzs7QUFDQSxRQUFJLENBQUNqRyxPQUFPLENBQUNxQyxHQUFSLENBQVlDLE9BQWpCLEVBQTBCO0FBQ3hCOEQsTUFBQUEsa0JBQWtCLENBQUMsSUFBRCxDQUFsQjtBQUNEOztBQUNELFNBQUtDLFVBQUwsR0FBa0JqRyxHQUFsQjtBQUNBLFdBQU8sSUFBUDtBQUNEO0FBRUQ7Ozs7Ozs7O0FBTUEsU0FBT3lFLEtBQVAsQ0FBYTdHLE9BQWIsRUFBMEM4RyxRQUExQyxFQUFpRTtBQUMvRCxVQUFNd0IsV0FBVyxHQUFHLElBQUl4SSxXQUFKLENBQWdCRSxPQUFoQixDQUFwQjtBQUNBLFdBQU9zSSxXQUFXLENBQUN6QixLQUFaLENBQWtCN0csT0FBbEIsRUFBMkI4RyxRQUEzQixDQUFQO0FBQ0Q7QUFFRDs7Ozs7Ozs7O0FBT0EsU0FBT3FCLHFCQUFQLENBQTZCSSxVQUE3QixFQUF5Q3hILE1BQXpDLEVBQXlFO0FBQ3ZFLFFBQUksQ0FBQ3dILFVBQUQsSUFBZ0J4SCxNQUFNLElBQUlBLE1BQU0sQ0FBQzZELElBQXJDLEVBQTRDO0FBQzFDLFVBQUl4QyxHQUFHLEdBQUc3QyxPQUFPLEVBQWpCO0FBQ0FnSixNQUFBQSxVQUFVLEdBQUdsSixPQUFPLENBQUMsTUFBRCxDQUFQLENBQWdCbUosWUFBaEIsQ0FBNkJwRyxHQUE3QixDQUFiO0FBQ0FtRyxNQUFBQSxVQUFVLENBQUNULE1BQVgsQ0FBa0IvRyxNQUFNLENBQUM2RCxJQUF6QjtBQUNEOztBQUNELFdBQU8sSUFBSTZELDBDQUFKLENBQXlCRixVQUF6QixFQUFxQ3hILE1BQXJDLENBQVA7QUFDRDs7QUFFRCxTQUFPOEQsZUFBUCxDQUF1QmlDLFFBQXZCLEVBQWlDO0FBQy9CO0FBQ0EsUUFBSXJILEtBQUssQ0FBQ2EsU0FBVixFQUFxQjtBQUNuQixZQUFNb0ksT0FBTyxHQUFHckosT0FBTyxDQUFDLFdBQUQsQ0FBdkI7O0FBQ0FxSixNQUFBQSxPQUFPLENBQUM7QUFBRUMsUUFBQUEsR0FBRyxFQUFFbEosS0FBSyxDQUFDYSxTQUFOLENBQWdCc0ksT0FBaEIsQ0FBd0IsS0FBeEIsRUFBK0IsRUFBL0IsSUFBcUM7QUFBNUMsT0FBRCxDQUFQLENBQ0cvRyxLQURILENBQ1NnSCxRQUFRLElBQUlBLFFBRHJCLEVBRUdqSCxJQUZILENBRVFpSCxRQUFRLElBQUk7QUFDaEIsY0FBTXJGLElBQUksR0FBR3FGLFFBQVEsQ0FBQ0MsSUFBVCxJQUFpQixJQUE5Qjs7QUFDQSxZQUNFRCxRQUFRLENBQUNwRixNQUFULEtBQW9CLEdBQXBCLElBQ0EsQ0FBQ0QsSUFERCxJQUVDQSxJQUFJLElBQUlBLElBQUksQ0FBQ0MsTUFBTCxLQUFnQixJQUgzQixFQUlFO0FBQ0E7QUFDQTFCLFVBQUFBLE9BQU8sQ0FBQ2dILElBQVIsQ0FDRyxvQ0FBbUN0SixLQUFLLENBQUNhLFNBQVUsSUFBcEQsR0FDRywwREFGTDtBQUlBOztBQUNBLGNBQUl3RyxRQUFKLEVBQWM7QUFDWkEsWUFBQUEsUUFBUSxDQUFDLEtBQUQsQ0FBUjtBQUNEO0FBQ0YsU0FkRCxNQWNPO0FBQ0wsY0FBSUEsUUFBSixFQUFjO0FBQ1pBLFlBQUFBLFFBQVEsQ0FBQyxJQUFELENBQVI7QUFDRDtBQUNGO0FBQ0YsT0F2Qkg7QUF3QkQ7QUFDRjs7QUExVGU7O0FBNlRsQixTQUFTakgsYUFBVCxHQUF5QjtBQUN2QixRQUFNbUosVUFBVSxHQUFHM0osT0FBTyxDQUFDLDBCQUFELENBQTFCOztBQUNBNkIsRUFBQUEsTUFBTSxDQUFDQyxNQUFQLENBQWMxQixLQUFLLENBQUN3SixLQUFwQixFQUEyQkQsVUFBM0I7QUFDQUUsRUFBQUEsTUFBTSxDQUFDekosS0FBUCxHQUFlQSxLQUFmO0FBQ0Q7O0FBRUQsU0FBU1EsY0FBVCxDQUF3QkQsT0FBeEIsRUFBcUQ7QUFDbkRrQixFQUFBQSxNQUFNLENBQUNpSSxJQUFQLENBQVlDLGlCQUFaLEVBQXNCQyxPQUF0QixDQUE4QkMsR0FBRyxJQUFJO0FBQ25DLFFBQUksQ0FBQ3BJLE1BQU0sQ0FBQ3FJLFNBQVAsQ0FBaUJDLGNBQWpCLENBQWdDQyxJQUFoQyxDQUFxQ3pKLE9BQXJDLEVBQThDc0osR0FBOUMsQ0FBTCxFQUF5RDtBQUN2RHRKLE1BQUFBLE9BQU8sQ0FBQ3NKLEdBQUQsQ0FBUCxHQUFlRixrQkFBU0UsR0FBVCxDQUFmO0FBQ0Q7QUFDRixHQUpEOztBQU1BLE1BQUksQ0FBQ3BJLE1BQU0sQ0FBQ3FJLFNBQVAsQ0FBaUJDLGNBQWpCLENBQWdDQyxJQUFoQyxDQUFxQ3pKLE9BQXJDLEVBQThDLFdBQTlDLENBQUwsRUFBaUU7QUFDL0RBLElBQUFBLE9BQU8sQ0FBQ00sU0FBUixHQUFxQixvQkFBbUJOLE9BQU8sQ0FBQzRFLElBQUssR0FBRTVFLE9BQU8sQ0FBQ2dILFNBQVUsRUFBekU7QUFDRCxHQVRrRCxDQVduRDs7O0FBQ0EsTUFBSWhILE9BQU8sQ0FBQ0UsS0FBWixFQUFtQjtBQUNqQixVQUFNd0osS0FBSyxHQUFHLCtCQUFkOztBQUNBLFFBQUkxSixPQUFPLENBQUNFLEtBQVIsQ0FBY3lKLEtBQWQsQ0FBb0JELEtBQXBCLENBQUosRUFBZ0M7QUFDOUIzSCxNQUFBQSxPQUFPLENBQUNnSCxJQUFSLENBQ0csNkZBREg7QUFHRDtBQUNGLEdBbkJrRCxDQXFCbkQ7OztBQUNBLE1BQUkvSSxPQUFPLENBQUM0SixtQkFBWixFQUFpQztBQUMvQjtBQUNBLEtBQUM1SCxPQUFPLENBQUNxQyxHQUFSLENBQVlDLE9BQWIsSUFDRXZDLE9BQU8sQ0FBQ2dILElBQVIsQ0FDRywySUFESCxDQURGO0FBSUE7O0FBRUEsVUFBTWEsbUJBQW1CLEdBQUdDLEtBQUssQ0FBQ0MsSUFBTixDQUMxQixJQUFJQyxHQUFKLENBQVEsQ0FDTixJQUFJWCxrQkFBU1EsbUJBQVQsSUFBZ0MsRUFBcEMsQ0FETSxFQUVOLElBQUk1SixPQUFPLENBQUM0SixtQkFBUixJQUErQixFQUFuQyxDQUZNLENBQVIsQ0FEMEIsQ0FBNUIsQ0FSK0IsQ0FlL0I7QUFDQTtBQUNBO0FBQ0E7O0FBQ0EsUUFBSSxFQUFFLFdBQVc1SixPQUFPLENBQUNnSyxlQUFyQixDQUFKLEVBQTJDO0FBQ3pDaEssTUFBQUEsT0FBTyxDQUFDZ0ssZUFBUixHQUEwQjlJLE1BQU0sQ0FBQ0MsTUFBUCxDQUN4QjtBQUFFOEksUUFBQUEsS0FBSyxFQUFFO0FBQVQsT0FEd0IsRUFFeEJqSyxPQUFPLENBQUNnSyxlQUZnQixDQUExQjtBQUlEOztBQUVEaEssSUFBQUEsT0FBTyxDQUFDZ0ssZUFBUixDQUF3QixPQUF4QixFQUFpQyxHQUFqQyxJQUF3Q0gsS0FBSyxDQUFDQyxJQUFOLENBQ3RDLElBQUlDLEdBQUosQ0FBUSxDQUNOLElBQUkvSixPQUFPLENBQUNnSyxlQUFSLENBQXdCLE9BQXhCLEVBQWlDLEdBQWpDLEtBQXlDLEVBQTdDLENBRE0sRUFFTixHQUFHSixtQkFGRyxDQUFSLENBRHNDLENBQXhDO0FBTUQsR0F0RGtELENBd0RuRDs7O0FBQ0ExSSxFQUFBQSxNQUFNLENBQUNpSSxJQUFQLENBQVlDLGtCQUFTWSxlQUFyQixFQUFzQ1gsT0FBdEMsQ0FBOENhLENBQUMsSUFBSTtBQUNqRCxVQUFNQyxHQUFHLEdBQUduSyxPQUFPLENBQUNnSyxlQUFSLENBQXdCRSxDQUF4QixDQUFaOztBQUNBLFFBQUksQ0FBQ0MsR0FBTCxFQUFVO0FBQ1JuSyxNQUFBQSxPQUFPLENBQUNnSyxlQUFSLENBQXdCRSxDQUF4QixJQUE2QmQsa0JBQVNZLGVBQVQsQ0FBeUJFLENBQXpCLENBQTdCO0FBQ0QsS0FGRCxNQUVPO0FBQ0xoSixNQUFBQSxNQUFNLENBQUNpSSxJQUFQLENBQVlDLGtCQUFTWSxlQUFULENBQXlCRSxDQUF6QixDQUFaLEVBQXlDYixPQUF6QyxDQUFpRGUsQ0FBQyxJQUFJO0FBQ3BELGNBQU1DLEdBQUcsR0FBRyxJQUFJTixHQUFKLENBQVEsQ0FDbEIsSUFBSS9KLE9BQU8sQ0FBQ2dLLGVBQVIsQ0FBd0JFLENBQXhCLEVBQTJCRSxDQUEzQixLQUFpQyxFQUFyQyxDQURrQixFQUVsQixHQUFHaEIsa0JBQVNZLGVBQVQsQ0FBeUJFLENBQXpCLEVBQTRCRSxDQUE1QixDQUZlLENBQVIsQ0FBWjtBQUlBcEssUUFBQUEsT0FBTyxDQUFDZ0ssZUFBUixDQUF3QkUsQ0FBeEIsRUFBMkJFLENBQTNCLElBQWdDUCxLQUFLLENBQUNDLElBQU4sQ0FBV08sR0FBWCxDQUFoQztBQUNELE9BTkQ7QUFPRDtBQUNGLEdBYkQ7QUFlQXJLLEVBQUFBLE9BQU8sQ0FBQ3NLLFlBQVIsR0FBdUJULEtBQUssQ0FBQ0MsSUFBTixDQUNyQixJQUFJQyxHQUFKLENBQ0UvSixPQUFPLENBQUNzSyxZQUFSLENBQXFCNUQsTUFBckIsQ0FBNEIwQyxrQkFBU2tCLFlBQXJDLEVBQW1EdEssT0FBTyxDQUFDc0ssWUFBM0QsQ0FERixDQURxQixDQUF2QjtBQUtELEMsQ0FFRDs7QUFDQTs7O0FBQ0EsU0FBU2xDLGtCQUFULENBQTRCRSxXQUE1QixFQUF5QztBQUN2QyxRQUFNVCxNQUFNLEdBQUdTLFdBQVcsQ0FBQ1QsTUFBM0I7QUFDQSxRQUFNMEMsT0FBTyxHQUFHLEVBQWhCO0FBQ0E7OztBQUVBMUMsRUFBQUEsTUFBTSxDQUFDdEQsRUFBUCxDQUFVLFlBQVYsRUFBd0JpRyxNQUFNLElBQUk7QUFDaEMsVUFBTUMsUUFBUSxHQUFHRCxNQUFNLENBQUNFLGFBQVAsR0FBdUIsR0FBdkIsR0FBNkJGLE1BQU0sQ0FBQ0csVUFBckQ7QUFDQUosSUFBQUEsT0FBTyxDQUFDRSxRQUFELENBQVAsR0FBb0JELE1BQXBCO0FBQ0FBLElBQUFBLE1BQU0sQ0FBQ2pHLEVBQVAsQ0FBVSxPQUFWLEVBQW1CLE1BQU07QUFDdkIsYUFBT2dHLE9BQU8sQ0FBQ0UsUUFBRCxDQUFkO0FBQ0QsS0FGRDtBQUdELEdBTkQ7O0FBUUEsUUFBTUcsdUJBQXVCLEdBQUcsWUFBVztBQUN6QyxTQUFLLE1BQU1ILFFBQVgsSUFBdUJGLE9BQXZCLEVBQWdDO0FBQzlCLFVBQUk7QUFDRkEsUUFBQUEsT0FBTyxDQUFDRSxRQUFELENBQVAsQ0FBa0JJLE9BQWxCO0FBQ0QsT0FGRCxDQUVFLE9BQU9DLENBQVAsRUFBVTtBQUNWO0FBQ0Q7QUFDRjtBQUNGLEdBUkQ7O0FBVUEsUUFBTXhJLGNBQWMsR0FBRyxZQUFXO0FBQ2hDTixJQUFBQSxPQUFPLENBQUMrSSxNQUFSLENBQWVwRyxLQUFmLENBQXFCLDZDQUFyQjtBQUNBaUcsSUFBQUEsdUJBQXVCO0FBQ3ZCL0MsSUFBQUEsTUFBTSxDQUFDbUQsS0FBUDtBQUNBMUMsSUFBQUEsV0FBVyxDQUFDaEcsY0FBWjtBQUNELEdBTEQ7O0FBTUFOLEVBQUFBLE9BQU8sQ0FBQ3VDLEVBQVIsQ0FBVyxTQUFYLEVBQXNCakMsY0FBdEI7QUFDQU4sRUFBQUEsT0FBTyxDQUFDdUMsRUFBUixDQUFXLFFBQVgsRUFBcUJqQyxjQUFyQjtBQUNEOztlQUVjeEMsVyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFBhcnNlU2VydmVyIC0gb3Blbi1zb3VyY2UgY29tcGF0aWJsZSBBUEkgU2VydmVyIGZvciBQYXJzZSBhcHBzXG5cbnZhciBiYXRjaCA9IHJlcXVpcmUoJy4vYmF0Y2gnKSxcbiAgYm9keVBhcnNlciA9IHJlcXVpcmUoJ2JvZHktcGFyc2VyJyksXG4gIGV4cHJlc3MgPSByZXF1aXJlKCdleHByZXNzJyksXG4gIG1pZGRsZXdhcmVzID0gcmVxdWlyZSgnLi9taWRkbGV3YXJlcycpLFxuICBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZSxcbiAgeyBwYXJzZSB9ID0gcmVxdWlyZSgnZ3JhcGhxbCcpLFxuICBwYXRoID0gcmVxdWlyZSgncGF0aCcpLFxuICBmcyA9IHJlcXVpcmUoJ2ZzJyk7XG5cbmltcG9ydCB7IFBhcnNlU2VydmVyT3B0aW9ucywgTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyB9IGZyb20gJy4vT3B0aW9ucyc7XG5pbXBvcnQgZGVmYXVsdHMgZnJvbSAnLi9kZWZhdWx0cyc7XG5pbXBvcnQgKiBhcyBsb2dnaW5nIGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi9Db25maWcnO1xuaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCByZXF1aXJlZFBhcmFtZXRlciBmcm9tICcuL3JlcXVpcmVkUGFyYW1ldGVyJztcbmltcG9ydCB7IEFuYWx5dGljc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9BbmFseXRpY3NSb3V0ZXInO1xuaW1wb3J0IHsgQ2xhc3Nlc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9DbGFzc2VzUm91dGVyJztcbmltcG9ydCB7IEZlYXR1cmVzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0ZlYXR1cmVzUm91dGVyJztcbmltcG9ydCB7IEZpbGVzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0ZpbGVzUm91dGVyJztcbmltcG9ydCB7IEZ1bmN0aW9uc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9GdW5jdGlvbnNSb3V0ZXInO1xuaW1wb3J0IHsgR2xvYmFsQ29uZmlnUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0dsb2JhbENvbmZpZ1JvdXRlcic7XG5pbXBvcnQgeyBHcmFwaFFMUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0dyYXBoUUxSb3V0ZXInO1xuaW1wb3J0IHsgSG9va3NSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvSG9va3NSb3V0ZXInO1xuaW1wb3J0IHsgSUFQVmFsaWRhdGlvblJvdXRlciB9IGZyb20gJy4vUm91dGVycy9JQVBWYWxpZGF0aW9uUm91dGVyJztcbmltcG9ydCB7IEluc3RhbGxhdGlvbnNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvSW5zdGFsbGF0aW9uc1JvdXRlcic7XG5pbXBvcnQgeyBMb2dzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0xvZ3NSb3V0ZXInO1xuaW1wb3J0IHsgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIgfSBmcm9tICcuL0xpdmVRdWVyeS9QYXJzZUxpdmVRdWVyeVNlcnZlcic7XG5pbXBvcnQgeyBQdWJsaWNBUElSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvUHVibGljQVBJUm91dGVyJztcbmltcG9ydCB7IFB1c2hSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvUHVzaFJvdXRlcic7XG5pbXBvcnQgeyBDbG91ZENvZGVSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvQ2xvdWRDb2RlUm91dGVyJztcbmltcG9ydCB7IFJvbGVzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1JvbGVzUm91dGVyJztcbmltcG9ydCB7IFNjaGVtYXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvU2NoZW1hc1JvdXRlcic7XG5pbXBvcnQgeyBTZXNzaW9uc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9TZXNzaW9uc1JvdXRlcic7XG5pbXBvcnQgeyBVc2Vyc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9Vc2Vyc1JvdXRlcic7XG5pbXBvcnQgeyBQdXJnZVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9QdXJnZVJvdXRlcic7XG5pbXBvcnQgeyBBdWRpZW5jZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvQXVkaWVuY2VzUm91dGVyJztcbmltcG9ydCB7IEFnZ3JlZ2F0ZVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9BZ2dyZWdhdGVSb3V0ZXInO1xuaW1wb3J0IHsgRXhwb3J0Um91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0V4cG9ydFJvdXRlcic7XG5pbXBvcnQgeyBJbXBvcnRSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvSW1wb3J0Um91dGVyJztcbmltcG9ydCB7IFBhcnNlU2VydmVyUkVTVENvbnRyb2xsZXIgfSBmcm9tICcuL1BhcnNlU2VydmVyUkVTVENvbnRyb2xsZXInO1xuaW1wb3J0ICogYXMgY29udHJvbGxlcnMgZnJvbSAnLi9Db250cm9sbGVycyc7XG5pbXBvcnQgeyBQYXJzZUdyYXBoUUxTZXJ2ZXIgfSBmcm9tICcuL0dyYXBoUUwvUGFyc2VHcmFwaFFMU2VydmVyJztcblxuLy8gTXV0YXRlIHRoZSBQYXJzZSBvYmplY3QgdG8gYWRkIHRoZSBDbG91ZCBDb2RlIGhhbmRsZXJzXG5hZGRQYXJzZUNsb3VkKCk7XG5cbi8vIFBhcnNlU2VydmVyIHdvcmtzIGxpa2UgYSBjb25zdHJ1Y3RvciBvZiBhbiBleHByZXNzIGFwcC5cbi8vIGh0dHBzOi8vcGFyc2VwbGF0Zm9ybS5vcmcvcGFyc2Utc2VydmVyL2FwaS9tYXN0ZXIvUGFyc2VTZXJ2ZXJPcHRpb25zLmh0bWxcbmNsYXNzIFBhcnNlU2VydmVyIHtcbiAgLyoqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1BhcnNlU2VydmVyT3B0aW9uc30gb3B0aW9ucyB0aGUgcGFyc2Ugc2VydmVyIGluaXRpYWxpemF0aW9uIG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICAgIGluamVjdERlZmF1bHRzKG9wdGlvbnMpO1xuICAgIGNvbnN0IHtcbiAgICAgIGFwcElkID0gcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYW4gYXBwSWQhJyksXG4gICAgICBtYXN0ZXJLZXkgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIG1hc3RlcktleSEnKSxcbiAgICAgIGNsb3VkLFxuICAgICAgamF2YXNjcmlwdEtleSxcbiAgICAgIHNlcnZlclVSTCA9IHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIGEgc2VydmVyVVJMIScpLFxuICAgICAgc2VydmVyU3RhcnRDb21wbGV0ZSxcbiAgICB9ID0gb3B0aW9ucztcbiAgICAvLyBJbml0aWFsaXplIHRoZSBub2RlIGNsaWVudCBTREsgYXV0b21hdGljYWxseVxuICAgIFBhcnNlLmluaXRpYWxpemUoYXBwSWQsIGphdmFzY3JpcHRLZXkgfHwgJ3VudXNlZCcsIG1hc3RlcktleSk7XG4gICAgUGFyc2Uuc2VydmVyVVJMID0gc2VydmVyVVJMO1xuXG4gICAgY29uc3QgYWxsQ29udHJvbGxlcnMgPSBjb250cm9sbGVycy5nZXRDb250cm9sbGVycyhvcHRpb25zKTtcblxuICAgIGNvbnN0IHtcbiAgICAgIGxvZ2dlckNvbnRyb2xsZXIsXG4gICAgICBkYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgICBob29rc0NvbnRyb2xsZXIsXG4gICAgfSA9IGFsbENvbnRyb2xsZXJzO1xuICAgIHRoaXMuY29uZmlnID0gQ29uZmlnLnB1dChPYmplY3QuYXNzaWduKHt9LCBvcHRpb25zLCBhbGxDb250cm9sbGVycykpO1xuXG4gICAgbG9nZ2luZy5zZXRMb2dnZXIobG9nZ2VyQ29udHJvbGxlcik7XG4gICAgY29uc3QgZGJJbml0UHJvbWlzZSA9IGRhdGFiYXNlQ29udHJvbGxlci5wZXJmb3JtSW5pdGlhbGl6YXRpb24oKTtcbiAgICBjb25zdCBob29rc0xvYWRQcm9taXNlID0gaG9va3NDb250cm9sbGVyLmxvYWQoKTtcblxuICAgIC8vIE5vdGU6IFRlc3RzIHdpbGwgc3RhcnQgdG8gZmFpbCBpZiBhbnkgdmFsaWRhdGlvbiBoYXBwZW5zIGFmdGVyIHRoaXMgaXMgY2FsbGVkLlxuICAgIFByb21pc2UuYWxsKFtkYkluaXRQcm9taXNlLCBob29rc0xvYWRQcm9taXNlXSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKHNlcnZlclN0YXJ0Q29tcGxldGUpIHtcbiAgICAgICAgICBzZXJ2ZXJTdGFydENvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoc2VydmVyU3RhcnRDb21wbGV0ZSkge1xuICAgICAgICAgIHNlcnZlclN0YXJ0Q29tcGxldGUoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBpZiAoY2xvdWQpIHtcbiAgICAgIGFkZFBhcnNlQ2xvdWQoKTtcbiAgICAgIGlmICh0eXBlb2YgY2xvdWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY2xvdWQoUGFyc2UpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgY2xvdWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJlcXVpcmUocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGNsb3VkKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBcImFyZ3VtZW50ICdjbG91ZCcgbXVzdCBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYSBmdW5jdGlvblwiO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldCBhcHAoKSB7XG4gICAgaWYgKCF0aGlzLl9hcHApIHtcbiAgICAgIHRoaXMuX2FwcCA9IFBhcnNlU2VydmVyLmFwcCh0aGlzLmNvbmZpZyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9hcHA7XG4gIH1cblxuICBoYW5kbGVTaHV0ZG93bigpIHtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgIGNvbnN0IHsgYWRhcHRlcjogZGF0YWJhc2VBZGFwdGVyIH0gPSB0aGlzLmNvbmZpZy5kYXRhYmFzZUNvbnRyb2xsZXI7XG4gICAgaWYgKFxuICAgICAgZGF0YWJhc2VBZGFwdGVyICYmXG4gICAgICB0eXBlb2YgZGF0YWJhc2VBZGFwdGVyLmhhbmRsZVNodXRkb3duID09PSAnZnVuY3Rpb24nXG4gICAgKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKGRhdGFiYXNlQWRhcHRlci5oYW5kbGVTaHV0ZG93bigpKTtcbiAgICB9XG4gICAgY29uc3QgeyBhZGFwdGVyOiBmaWxlQWRhcHRlciB9ID0gdGhpcy5jb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgIGlmIChmaWxlQWRhcHRlciAmJiB0eXBlb2YgZmlsZUFkYXB0ZXIuaGFuZGxlU2h1dGRvd24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHByb21pc2VzLnB1c2goZmlsZUFkYXB0ZXIuaGFuZGxlU2h1dGRvd24oKSk7XG4gICAgfVxuICAgIHJldHVybiAocHJvbWlzZXMubGVuZ3RoID4gMFxuICAgICAgPyBQcm9taXNlLmFsbChwcm9taXNlcylcbiAgICAgIDogUHJvbWlzZS5yZXNvbHZlKClcbiAgICApLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuY29uZmlnLnNlcnZlckNsb3NlQ29tcGxldGUpIHtcbiAgICAgICAgdGhpcy5jb25maWcuc2VydmVyQ2xvc2VDb21wbGV0ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdGF0aWNcbiAgICogQ3JlYXRlIGFuIGV4cHJlc3MgYXBwIGZvciB0aGUgcGFyc2Ugc2VydmVyXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIGxldCB5b3Ugc3BlY2lmeSB0aGUgbWF4VXBsb2FkU2l6ZSB3aGVuIGNyZWF0aW5nIHRoZSBleHByZXNzIGFwcCAgKi9cbiAgc3RhdGljIGFwcCh7IG1heFVwbG9hZFNpemUgPSAnMjBtYicsIGFwcElkLCBkaXJlY3RBY2Nlc3MgfSkge1xuICAgIC8vIFRoaXMgYXBwIHNlcnZlcyB0aGUgUGFyc2UgQVBJIGRpcmVjdGx5LlxuICAgIC8vIEl0J3MgdGhlIGVxdWl2YWxlbnQgb2YgaHR0cHM6Ly9hcGkucGFyc2UuY29tLzEgaW4gdGhlIGhvc3RlZCBQYXJzZSBBUEkuXG4gICAgdmFyIGFwaSA9IGV4cHJlc3MoKTtcbiAgICAvL2FwaS51c2UoXCIvYXBwc1wiLCBleHByZXNzLnN0YXRpYyhfX2Rpcm5hbWUgKyBcIi9wdWJsaWNcIikpO1xuICAgIGFwaS51c2UobWlkZGxld2FyZXMuYWxsb3dDcm9zc0RvbWFpbihhcHBJZCkpO1xuICAgIC8vIEZpbGUgaGFuZGxpbmcgbmVlZHMgdG8gYmUgYmVmb3JlIGRlZmF1bHQgbWlkZGxld2FyZXMgYXJlIGFwcGxpZWRcbiAgICBhcGkudXNlKFxuICAgICAgJy8nLFxuICAgICAgbmV3IEZpbGVzUm91dGVyKCkuZXhwcmVzc1JvdXRlcih7XG4gICAgICAgIG1heFVwbG9hZFNpemU6IG1heFVwbG9hZFNpemUsXG4gICAgICB9KVxuICAgICk7XG5cbiAgICBhcGkudXNlKCcvaGVhbHRoJywgZnVuY3Rpb24ocmVxLCByZXMpIHtcbiAgICAgIHJlcy5qc29uKHtcbiAgICAgICAgc3RhdHVzOiAnb2snLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBhcGkudXNlKFxuICAgICAgJy8nLFxuICAgICAgYm9keVBhcnNlci51cmxlbmNvZGVkKHsgZXh0ZW5kZWQ6IGZhbHNlIH0pLFxuICAgICAgbmV3IFB1YmxpY0FQSVJvdXRlcigpLmV4cHJlc3NSb3V0ZXIoKVxuICAgICk7XG5cbiAgICBhcGkudXNlKCcvJywgbmV3IEltcG9ydFJvdXRlcigpLmV4cHJlc3NSb3V0ZXIoKSk7XG4gICAgYXBpLnVzZShib2R5UGFyc2VyLmpzb24oeyB0eXBlOiAnKi8qJywgbGltaXQ6IG1heFVwbG9hZFNpemUgfSkpO1xuICAgIGFwaS51c2UobWlkZGxld2FyZXMuYWxsb3dNZXRob2RPdmVycmlkZSk7XG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMpO1xuXG4gICAgY29uc3QgYXBwUm91dGVyID0gUGFyc2VTZXJ2ZXIucHJvbWlzZVJvdXRlcih7IGFwcElkIH0pO1xuICAgIGFwaS51c2UoYXBwUm91dGVyLmV4cHJlc3NSb3V0ZXIoKSk7XG5cbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlRXJyb3JzKTtcblxuICAgIC8vIHJ1biB0aGUgZm9sbG93aW5nIHdoZW4gbm90IHRlc3RpbmdcbiAgICBpZiAoIXByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICAgIC8vVGhpcyBjYXVzZXMgdGVzdHMgdG8gc3BldyBzb21lIHVzZWxlc3Mgd2FybmluZ3MsIHNvIGRpc2FibGUgaW4gdGVzdFxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHByb2Nlc3Mub24oJ3VuY2F1Z2h0RXhjZXB0aW9uJywgZXJyID0+IHtcbiAgICAgICAgaWYgKGVyci5jb2RlID09PSAnRUFERFJJTlVTRScpIHtcbiAgICAgICAgICAvLyB1c2VyLWZyaWVuZGx5IG1lc3NhZ2UgZm9yIHRoaXMgY29tbW9uIGVycm9yXG4gICAgICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoXG4gICAgICAgICAgICBgVW5hYmxlIHRvIGxpc3RlbiBvbiBwb3J0ICR7ZXJyLnBvcnR9LiBUaGUgcG9ydCBpcyBhbHJlYWR5IGluIHVzZS5gXG4gICAgICAgICAgKTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8vIHZlcmlmeSB0aGUgc2VydmVyIHVybCBhZnRlciBhICdtb3VudCcgZXZlbnQgaXMgcmVjZWl2ZWRcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBhcGkub24oJ21vdW50JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIFBhcnNlU2VydmVyLnZlcmlmeVNlcnZlclVybCgpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHByb2Nlc3MuZW52LlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MgPT09ICcxJyB8fFxuICAgICAgZGlyZWN0QWNjZXNzXG4gICAgKSB7XG4gICAgICBQYXJzZS5Db3JlTWFuYWdlci5zZXRSRVNUQ29udHJvbGxlcihcbiAgICAgICAgUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlcihhcHBJZCwgYXBwUm91dGVyKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGFwaTtcbiAgfVxuXG4gIHN0YXRpYyBwcm9taXNlUm91dGVyKHsgYXBwSWQgfSkge1xuICAgIGNvbnN0IHJvdXRlcnMgPSBbXG4gICAgICBuZXcgQ2xhc3Nlc1JvdXRlcigpLFxuICAgICAgbmV3IFVzZXJzUm91dGVyKCksXG4gICAgICBuZXcgU2Vzc2lvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBSb2xlc1JvdXRlcigpLFxuICAgICAgbmV3IEFuYWx5dGljc1JvdXRlcigpLFxuICAgICAgbmV3IEluc3RhbGxhdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBGdW5jdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBTY2hlbWFzUm91dGVyKCksXG4gICAgICBuZXcgUHVzaFJvdXRlcigpLFxuICAgICAgbmV3IExvZ3NSb3V0ZXIoKSxcbiAgICAgIG5ldyBJQVBWYWxpZGF0aW9uUm91dGVyKCksXG4gICAgICBuZXcgRmVhdHVyZXNSb3V0ZXIoKSxcbiAgICAgIG5ldyBHbG9iYWxDb25maWdSb3V0ZXIoKSxcbiAgICAgIG5ldyBHcmFwaFFMUm91dGVyKCksXG4gICAgICBuZXcgUHVyZ2VSb3V0ZXIoKSxcbiAgICAgIG5ldyBIb29rc1JvdXRlcigpLFxuICAgICAgbmV3IENsb3VkQ29kZVJvdXRlcigpLFxuICAgICAgbmV3IEF1ZGllbmNlc1JvdXRlcigpLFxuICAgICAgbmV3IEFnZ3JlZ2F0ZVJvdXRlcigpLFxuICAgICAgbmV3IEV4cG9ydFJvdXRlcigpLFxuICAgIF07XG5cbiAgICBjb25zdCByb3V0ZXMgPSByb3V0ZXJzLnJlZHVjZSgobWVtbywgcm91dGVyKSA9PiB7XG4gICAgICByZXR1cm4gbWVtby5jb25jYXQocm91dGVyLnJvdXRlcyk7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3QgYXBwUm91dGVyID0gbmV3IFByb21pc2VSb3V0ZXIocm91dGVzLCBhcHBJZCk7XG5cbiAgICBiYXRjaC5tb3VudE9udG8oYXBwUm91dGVyKTtcbiAgICByZXR1cm4gYXBwUm91dGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIHN0YXJ0cyB0aGUgcGFyc2Ugc2VydmVyJ3MgZXhwcmVzcyBhcHBcbiAgICogQHBhcmFtIHtQYXJzZVNlcnZlck9wdGlvbnN9IG9wdGlvbnMgdG8gdXNlIHRvIHN0YXJ0IHRoZSBzZXJ2ZXJcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgY2FsbGVkIHdoZW4gdGhlIHNlcnZlciBoYXMgc3RhcnRlZFxuICAgKiBAcmV0dXJucyB7UGFyc2VTZXJ2ZXJ9IHRoZSBwYXJzZSBzZXJ2ZXIgaW5zdGFuY2VcbiAgICovXG4gIHN0YXJ0KG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucywgY2FsbGJhY2s6ID8oKSA9PiB2b2lkKSB7XG4gICAgY29uc3QgYXBwID0gZXhwcmVzcygpO1xuICAgIGlmIChvcHRpb25zLm1pZGRsZXdhcmUpIHtcbiAgICAgIGxldCBtaWRkbGV3YXJlO1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLm1pZGRsZXdhcmUgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgbWlkZGxld2FyZSA9IHJlcXVpcmUocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIG9wdGlvbnMubWlkZGxld2FyZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWlkZGxld2FyZSA9IG9wdGlvbnMubWlkZGxld2FyZTsgLy8gdXNlIGFzLWlzIGxldCBleHByZXNzIGZhaWxcbiAgICAgIH1cbiAgICAgIGFwcC51c2UobWlkZGxld2FyZSk7XG4gICAgfVxuXG4gICAgYXBwLnVzZShvcHRpb25zLm1vdW50UGF0aCwgdGhpcy5hcHApO1xuXG4gICAgaWYgKG9wdGlvbnMubW91bnRHcmFwaFFMID09PSB0cnVlIHx8IG9wdGlvbnMubW91bnRQbGF5Z3JvdW5kID09PSB0cnVlKSB7XG4gICAgICBsZXQgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmdyYXBoUUxTY2hlbWEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGdyYXBoUUxDdXN0b21UeXBlRGVmcyA9IHBhcnNlKFxuICAgICAgICAgIGZzLnJlYWRGaWxlU3luYyhvcHRpb25zLmdyYXBoUUxTY2hlbWEsICd1dGY4JylcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMuZ3JhcGhRTFNjaGVtYSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzID0gb3B0aW9ucy5ncmFwaFFMU2NoZW1hO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJzZUdyYXBoUUxTZXJ2ZXIgPSBuZXcgUGFyc2VHcmFwaFFMU2VydmVyKHRoaXMsIHtcbiAgICAgICAgZ3JhcGhRTFBhdGg6IG9wdGlvbnMuZ3JhcGhRTFBhdGgsXG4gICAgICAgIHBsYXlncm91bmRQYXRoOiBvcHRpb25zLnBsYXlncm91bmRQYXRoLFxuICAgICAgICBncmFwaFFMQ3VzdG9tVHlwZURlZnMsXG4gICAgICB9KTtcblxuICAgICAgaWYgKG9wdGlvbnMubW91bnRHcmFwaFFMKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNlcnZlci5hcHBseUdyYXBoUUwoYXBwKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMubW91bnRQbGF5Z3JvdW5kKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNlcnZlci5hcHBseVBsYXlncm91bmQoYXBwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzZXJ2ZXIgPSBhcHAubGlzdGVuKG9wdGlvbnMucG9ydCwgb3B0aW9ucy5ob3N0LCBjYWxsYmFjayk7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG5cbiAgICBpZiAob3B0aW9ucy5zdGFydExpdmVRdWVyeVNlcnZlciB8fCBvcHRpb25zLmxpdmVRdWVyeVNlcnZlck9wdGlvbnMpIHtcbiAgICAgIHRoaXMubGl2ZVF1ZXJ5U2VydmVyID0gUGFyc2VTZXJ2ZXIuY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIG9wdGlvbnMubGl2ZVF1ZXJ5U2VydmVyT3B0aW9uc1xuICAgICAgKTtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAoIXByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICAgIGNvbmZpZ3VyZUxpc3RlbmVycyh0aGlzKTtcbiAgICB9XG4gICAgdGhpcy5leHByZXNzQXBwID0gYXBwO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgUGFyc2VTZXJ2ZXIgYW5kIHN0YXJ0cyBpdC5cbiAgICogQHBhcmFtIHtQYXJzZVNlcnZlck9wdGlvbnN9IG9wdGlvbnMgdXNlZCB0byBzdGFydCB0aGUgc2VydmVyXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGNhbGxlZCB3aGVuIHRoZSBzZXJ2ZXIgaGFzIHN0YXJ0ZWRcbiAgICogQHJldHVybnMge1BhcnNlU2VydmVyfSB0aGUgcGFyc2Ugc2VydmVyIGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgc3RhcnQob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zLCBjYWxsYmFjazogPygpID0+IHZvaWQpIHtcbiAgICBjb25zdCBwYXJzZVNlcnZlciA9IG5ldyBQYXJzZVNlcnZlcihvcHRpb25zKTtcbiAgICByZXR1cm4gcGFyc2VTZXJ2ZXIuc3RhcnQob3B0aW9ucywgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciBtZXRob2QgdG8gY3JlYXRlIGEgbGl2ZVF1ZXJ5IHNlcnZlclxuICAgKiBAc3RhdGljXG4gICAqIEBwYXJhbSB7U2VydmVyfSBodHRwU2VydmVyIGFuIG9wdGlvbmFsIGh0dHAgc2VydmVyIHRvIHBhc3NcbiAgICogQHBhcmFtIHtMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zfSBjb25maWcgb3B0aW9ucyBmb3QgaGUgbGl2ZVF1ZXJ5U2VydmVyXG4gICAqIEByZXR1cm5zIHtQYXJzZUxpdmVRdWVyeVNlcnZlcn0gdGhlIGxpdmUgcXVlcnkgc2VydmVyIGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyKGh0dHBTZXJ2ZXIsIGNvbmZpZzogTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucykge1xuICAgIGlmICghaHR0cFNlcnZlciB8fCAoY29uZmlnICYmIGNvbmZpZy5wb3J0KSkge1xuICAgICAgdmFyIGFwcCA9IGV4cHJlc3MoKTtcbiAgICAgIGh0dHBTZXJ2ZXIgPSByZXF1aXJlKCdodHRwJykuY3JlYXRlU2VydmVyKGFwcCk7XG4gICAgICBodHRwU2VydmVyLmxpc3Rlbihjb25maWcucG9ydCk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIoaHR0cFNlcnZlciwgY29uZmlnKTtcbiAgfVxuXG4gIHN0YXRpYyB2ZXJpZnlTZXJ2ZXJVcmwoY2FsbGJhY2spIHtcbiAgICAvLyBwZXJmb3JtIGEgaGVhbHRoIGNoZWNrIG9uIHRoZSBzZXJ2ZXJVUkwgdmFsdWVcbiAgICBpZiAoUGFyc2Uuc2VydmVyVVJMKSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gcmVxdWlyZSgnLi9yZXF1ZXN0Jyk7XG4gICAgICByZXF1ZXN0KHsgdXJsOiBQYXJzZS5zZXJ2ZXJVUkwucmVwbGFjZSgvXFwvJC8sICcnKSArICcvaGVhbHRoJyB9KVxuICAgICAgICAuY2F0Y2gocmVzcG9uc2UgPT4gcmVzcG9uc2UpXG4gICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICBjb25zdCBqc29uID0gcmVzcG9uc2UuZGF0YSB8fCBudWxsO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwIHx8XG4gICAgICAgICAgICAhanNvbiB8fFxuICAgICAgICAgICAgKGpzb24gJiYganNvbi5zdGF0dXMgIT09ICdvaycpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgIGBcXG5XQVJOSU5HLCBVbmFibGUgdG8gY29ubmVjdCB0byAnJHtQYXJzZS5zZXJ2ZXJVUkx9Jy5gICtcbiAgICAgICAgICAgICAgICBgIENsb3VkIGNvZGUgYW5kIHB1c2ggbm90aWZpY2F0aW9ucyBtYXkgYmUgdW5hdmFpbGFibGUhXFxuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGFkZFBhcnNlQ2xvdWQoKSB7XG4gIGNvbnN0IFBhcnNlQ2xvdWQgPSByZXF1aXJlKCcuL2Nsb3VkLWNvZGUvUGFyc2UuQ2xvdWQnKTtcbiAgT2JqZWN0LmFzc2lnbihQYXJzZS5DbG91ZCwgUGFyc2VDbG91ZCk7XG4gIGdsb2JhbC5QYXJzZSA9IFBhcnNlO1xufVxuXG5mdW5jdGlvbiBpbmplY3REZWZhdWx0cyhvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgT2JqZWN0LmtleXMoZGVmYXVsdHMpLmZvckVhY2goa2V5ID0+IHtcbiAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvcHRpb25zLCBrZXkpKSB7XG4gICAgICBvcHRpb25zW2tleV0gPSBkZWZhdWx0c1trZXldO1xuICAgIH1cbiAgfSk7XG5cbiAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob3B0aW9ucywgJ3NlcnZlclVSTCcpKSB7XG4gICAgb3B0aW9ucy5zZXJ2ZXJVUkwgPSBgaHR0cDovL2xvY2FsaG9zdDoke29wdGlvbnMucG9ydH0ke29wdGlvbnMubW91bnRQYXRofWA7XG4gIH1cblxuICAvLyBSZXNlcnZlZCBDaGFyYWN0ZXJzXG4gIGlmIChvcHRpb25zLmFwcElkKSB7XG4gICAgY29uc3QgcmVnZXggPSAvWyEjJCUnKCkqKyYvOjs9P0BbXFxde31eLHw8Pl0vZztcbiAgICBpZiAob3B0aW9ucy5hcHBJZC5tYXRjaChyZWdleCkpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFxcbldBUk5JTkcsIGFwcElkIHRoYXQgY29udGFpbnMgc3BlY2lhbCBjaGFyYWN0ZXJzIGNhbiBjYXVzZSBpc3N1ZXMgd2hpbGUgdXNpbmcgd2l0aCB1cmxzLlxcbmBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gQmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgaWYgKG9wdGlvbnMudXNlclNlbnNpdGl2ZUZpZWxkcykge1xuICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbiAgICAhcHJvY2Vzcy5lbnYuVEVTVElORyAmJlxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgXFxuREVQUkVDQVRFRDogdXNlclNlbnNpdGl2ZUZpZWxkcyBoYXMgYmVlbiByZXBsYWNlZCBieSBwcm90ZWN0ZWRGaWVsZHMgYWxsb3dpbmcgdGhlIGFiaWxpdHkgdG8gcHJvdGVjdCBmaWVsZHMgaW4gYWxsIGNsYXNzZXMgd2l0aCBDTFAuIFxcbmBcbiAgICAgICk7XG4gICAgLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG5cbiAgICBjb25zdCB1c2VyU2Vuc2l0aXZlRmllbGRzID0gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoW1xuICAgICAgICAuLi4oZGVmYXVsdHMudXNlclNlbnNpdGl2ZUZpZWxkcyB8fCBbXSksXG4gICAgICAgIC4uLihvcHRpb25zLnVzZXJTZW5zaXRpdmVGaWVsZHMgfHwgW10pLFxuICAgICAgXSlcbiAgICApO1xuXG4gICAgLy8gSWYgdGhlIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzIGlzIHVuc2V0LFxuICAgIC8vIGl0J2xsIGJlIGFzc2lnbmVkIHRoZSBkZWZhdWx0IGFib3ZlLlxuICAgIC8vIEhlcmUsIHByb3RlY3QgYWdhaW5zdCB0aGUgY2FzZSB3aGVyZSBwcm90ZWN0ZWRGaWVsZHNcbiAgICAvLyBpcyBzZXQsIGJ1dCBkb2Vzbid0IGhhdmUgX1VzZXIuXG4gICAgaWYgKCEoJ19Vc2VyJyBpbiBvcHRpb25zLnByb3RlY3RlZEZpZWxkcykpIHtcbiAgICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzID0gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgeyBfVXNlcjogW10gfSxcbiAgICAgICAgb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNcbiAgICAgICk7XG4gICAgfVxuXG4gICAgb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbJ19Vc2VyJ11bJyonXSA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFtcbiAgICAgICAgLi4uKG9wdGlvbnMucHJvdGVjdGVkRmllbGRzWydfVXNlciddWycqJ10gfHwgW10pLFxuICAgICAgICAuLi51c2VyU2Vuc2l0aXZlRmllbGRzLFxuICAgICAgXSlcbiAgICApO1xuICB9XG5cbiAgLy8gTWVyZ2UgcHJvdGVjdGVkRmllbGRzIG9wdGlvbnMgd2l0aCBkZWZhdWx0cy5cbiAgT2JqZWN0LmtleXMoZGVmYXVsdHMucHJvdGVjdGVkRmllbGRzKS5mb3JFYWNoKGMgPT4ge1xuICAgIGNvbnN0IGN1ciA9IG9wdGlvbnMucHJvdGVjdGVkRmllbGRzW2NdO1xuICAgIGlmICghY3VyKSB7XG4gICAgICBvcHRpb25zLnByb3RlY3RlZEZpZWxkc1tjXSA9IGRlZmF1bHRzLnByb3RlY3RlZEZpZWxkc1tjXTtcbiAgICB9IGVsc2Uge1xuICAgICAgT2JqZWN0LmtleXMoZGVmYXVsdHMucHJvdGVjdGVkRmllbGRzW2NdKS5mb3JFYWNoKHIgPT4ge1xuICAgICAgICBjb25zdCB1bnEgPSBuZXcgU2V0KFtcbiAgICAgICAgICAuLi4ob3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbY11bcl0gfHwgW10pLFxuICAgICAgICAgIC4uLmRlZmF1bHRzLnByb3RlY3RlZEZpZWxkc1tjXVtyXSxcbiAgICAgICAgXSk7XG4gICAgICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzW2NdW3JdID0gQXJyYXkuZnJvbSh1bnEpO1xuICAgICAgfSk7XG4gICAgfVxuICB9KTtcblxuICBvcHRpb25zLm1hc3RlcktleUlwcyA9IEFycmF5LmZyb20oXG4gICAgbmV3IFNldChcbiAgICAgIG9wdGlvbnMubWFzdGVyS2V5SXBzLmNvbmNhdChkZWZhdWx0cy5tYXN0ZXJLZXlJcHMsIG9wdGlvbnMubWFzdGVyS2V5SXBzKVxuICAgIClcbiAgKTtcbn1cblxuLy8gVGhvc2UgY2FuJ3QgYmUgdGVzdGVkIGFzIGl0IHJlcXVpcmVzIGEgc3VicHJvY2Vzc1xuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyZUxpc3RlbmVycyhwYXJzZVNlcnZlcikge1xuICBjb25zdCBzZXJ2ZXIgPSBwYXJzZVNlcnZlci5zZXJ2ZXI7XG4gIGNvbnN0IHNvY2tldHMgPSB7fTtcbiAgLyogQ3VycmVudGx5LCBleHByZXNzIGRvZXNuJ3Qgc2h1dCBkb3duIGltbWVkaWF0ZWx5IGFmdGVyIHJlY2VpdmluZyBTSUdJTlQvU0lHVEVSTSBpZiBpdCBoYXMgY2xpZW50IGNvbm5lY3Rpb25zIHRoYXQgaGF2ZW4ndCB0aW1lZCBvdXQuIChUaGlzIGlzIGEga25vd24gaXNzdWUgd2l0aCBub2RlIC0gaHR0cHM6Ly9naXRodWIuY29tL25vZGVqcy9ub2RlL2lzc3Vlcy8yNjQyKVxuICAgIFRoaXMgZnVuY3Rpb24sIGFsb25nIHdpdGggYGRlc3Ryb3lBbGl2ZUNvbm5lY3Rpb25zKClgLCBpbnRlbmQgdG8gZml4IHRoaXMgYmVoYXZpb3Igc3VjaCB0aGF0IHBhcnNlIHNlcnZlciB3aWxsIGNsb3NlIGFsbCBvcGVuIGNvbm5lY3Rpb25zIGFuZCBpbml0aWF0ZSB0aGUgc2h1dGRvd24gcHJvY2VzcyBhcyBzb29uIGFzIGl0IHJlY2VpdmVzIGEgU0lHSU5UL1NJR1RFUk0gc2lnbmFsLiAqL1xuICBzZXJ2ZXIub24oJ2Nvbm5lY3Rpb24nLCBzb2NrZXQgPT4ge1xuICAgIGNvbnN0IHNvY2tldElkID0gc29ja2V0LnJlbW90ZUFkZHJlc3MgKyAnOicgKyBzb2NrZXQucmVtb3RlUG9ydDtcbiAgICBzb2NrZXRzW3NvY2tldElkXSA9IHNvY2tldDtcbiAgICBzb2NrZXQub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgZGVsZXRlIHNvY2tldHNbc29ja2V0SWRdO1xuICAgIH0pO1xuICB9KTtcblxuICBjb25zdCBkZXN0cm95QWxpdmVDb25uZWN0aW9ucyA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAoY29uc3Qgc29ja2V0SWQgaW4gc29ja2V0cykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgc29ja2V0c1tzb2NrZXRJZF0uZGVzdHJveSgpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvKiAqL1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBjb25zdCBoYW5kbGVTaHV0ZG93biA9IGZ1bmN0aW9uKCkge1xuICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKCdUZXJtaW5hdGlvbiBzaWduYWwgcmVjZWl2ZWQuIFNodXR0aW5nIGRvd24uJyk7XG4gICAgZGVzdHJveUFsaXZlQ29ubmVjdGlvbnMoKTtcbiAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICBwYXJzZVNlcnZlci5oYW5kbGVTaHV0ZG93bigpO1xuICB9O1xuICBwcm9jZXNzLm9uKCdTSUdURVJNJywgaGFuZGxlU2h1dGRvd24pO1xuICBwcm9jZXNzLm9uKCdTSUdJTlQnLCBoYW5kbGVTaHV0ZG93bik7XG59XG5cbmV4cG9ydCBkZWZhdWx0IFBhcnNlU2VydmVyO1xuIl19 \ 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..ccf8ba6770 --- /dev/null +++ b/lib/Push/PushQueue.js @@ -0,0 +1,92 @@ +"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")); + +var _logger = _interopRequireDefault(require("../logger")); + +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(); + } + + const maxPages = Math.ceil(count / limit); + pushStatus.setRunning(maxPages); // while (page < maxPages) { + // changes request/limit/orderBy by id range intervals for better performance + // https://docs.mongodb.com/manual/reference/method/cursor.skip/ + // Range queries can use indexes to avoid scanning unwanted documents, + // typically yielding better performance as the offset grows compared + // to using cursor.skip() for pagination. + + const query = { + where + }; + const pushWorkItem = { + body, + query, + maxPages, + pushStatus: { + objectId: pushStatus.objectId + }, + applicationId: config.applicationId + }; + const publishResult = Promise.resolve(this.parsePublisher.publish(this.channel, JSON.stringify(pushWorkItem))); + return publishResult.then(reponse => { + const result = reponse && reponse.data || reponse; + + _logger.default.info(`All ${maxPages} packages were enqueued for PushStatus ${pushStatus.objectId}`, result); + + return result; + }); + }).catch(err => { + _logger.default.info(`Can't count installations for PushStatus ${pushStatus.objectId}: ${err.message}`); + + throw err; + }); + } + +} + +exports.PushQueue = PushQueue; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL1B1c2hRdWV1ZS5qcyJdLCJuYW1lcyI6WyJQVVNIX0NIQU5ORUwiLCJERUZBVUxUX0JBVENIX1NJWkUiLCJQdXNoUXVldWUiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsImNoYW5uZWwiLCJkZWZhdWx0UHVzaENoYW5uZWwiLCJiYXRjaFNpemUiLCJwYXJzZVB1Ymxpc2hlciIsIlBhcnNlTWVzc2FnZVF1ZXVlIiwiY3JlYXRlUHVibGlzaGVyIiwiUGFyc2UiLCJhcHBsaWNhdGlvbklkIiwiZW5xdWV1ZSIsImJvZHkiLCJ3aGVyZSIsImF1dGgiLCJwdXNoU3RhdHVzIiwibGltaXQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInRoZW4iLCJyZXN0IiwiZmluZCIsImNvdW50IiwicmVzdWx0cyIsImNvbXBsZXRlIiwibWF4UGFnZXMiLCJNYXRoIiwiY2VpbCIsInNldFJ1bm5pbmciLCJxdWVyeSIsInB1c2hXb3JrSXRlbSIsIm9iamVjdElkIiwicHVibGlzaFJlc3VsdCIsInB1Ymxpc2giLCJKU09OIiwic3RyaW5naWZ5IiwicmVwb25zZSIsInJlc3VsdCIsImRhdGEiLCJsb2ciLCJpbmZvIiwiY2F0Y2giLCJlcnIiLCJtZXNzYWdlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxNQUFNQSxZQUFZLEdBQUcsbUJBQXJCO0FBQ0EsTUFBTUMsa0JBQWtCLEdBQUcsR0FBM0I7O0FBRU8sTUFBTUMsU0FBTixDQUFnQjtBQUtyQjtBQUNBO0FBQ0FDLEVBQUFBLFdBQVcsQ0FBQ0MsTUFBVyxHQUFHLEVBQWYsRUFBbUI7QUFDNUIsU0FBS0MsT0FBTCxHQUFlRCxNQUFNLENBQUNDLE9BQVAsSUFBa0JILFNBQVMsQ0FBQ0ksa0JBQVYsRUFBakM7QUFDQSxTQUFLQyxTQUFMLEdBQWlCSCxNQUFNLENBQUNHLFNBQVAsSUFBb0JOLGtCQUFyQztBQUNBLFNBQUtPLGNBQUwsR0FBc0JDLHFDQUFrQkMsZUFBbEIsQ0FBa0NOLE1BQWxDLENBQXRCO0FBQ0Q7O0FBRUQsU0FBT0Usa0JBQVAsR0FBNEI7QUFDMUIsV0FBUSxHQUFFSyxjQUFNQyxhQUFjLElBQUdaLFlBQWEsRUFBOUM7QUFDRDs7QUFFRGEsRUFBQUEsT0FBTyxDQUFDQyxJQUFELEVBQU9DLEtBQVAsRUFBY1gsTUFBZCxFQUFzQlksSUFBdEIsRUFBNEJDLFVBQTVCLEVBQXdDO0FBQzdDLFVBQU1DLEtBQUssR0FBRyxLQUFLWCxTQUFuQjtBQUVBUSxJQUFBQSxLQUFLLEdBQUcsbUNBQXVCQSxLQUF2QixDQUFSLENBSDZDLENBSzdDO0FBQ0E7O0FBQ0EsV0FBT0ksT0FBTyxDQUFDQyxPQUFSLEdBQ0pDLElBREksQ0FDQyxNQUFNO0FBQ1YsYUFBT0MsY0FBS0MsSUFBTCxDQUFVbkIsTUFBVixFQUFrQlksSUFBbEIsRUFBd0IsZUFBeEIsRUFBeUNELEtBQXpDLEVBQWdEO0FBQ3JERyxRQUFBQSxLQUFLLEVBQUUsQ0FEOEM7QUFFckRNLFFBQUFBLEtBQUssRUFBRTtBQUY4QyxPQUFoRCxDQUFQO0FBSUQsS0FOSSxFQU9KSCxJQVBJLENBT0MsQ0FBQztBQUFFSSxNQUFBQSxPQUFGO0FBQVdELE1BQUFBO0FBQVgsS0FBRCxLQUF3QjtBQUM1QixVQUFJLENBQUNDLE9BQUQsSUFBWUQsS0FBSyxJQUFJLENBQXpCLEVBQTRCO0FBQzFCLGVBQU9QLFVBQVUsQ0FBQ1MsUUFBWCxFQUFQO0FBQ0Q7O0FBQ0QsWUFBTUMsUUFBUSxHQUFHQyxJQUFJLENBQUNDLElBQUwsQ0FBVUwsS0FBSyxHQUFHTixLQUFsQixDQUFqQjtBQUNBRCxNQUFBQSxVQUFVLENBQUNhLFVBQVgsQ0FBc0JILFFBQXRCLEVBTDRCLENBTTVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDQSxZQUFNSSxLQUFLLEdBQUc7QUFBRWhCLFFBQUFBO0FBQUYsT0FBZDtBQUVBLFlBQU1pQixZQUFZLEdBQUc7QUFDbkJsQixRQUFBQSxJQURtQjtBQUVuQmlCLFFBQUFBLEtBRm1CO0FBR25CSixRQUFBQSxRQUhtQjtBQUluQlYsUUFBQUEsVUFBVSxFQUFFO0FBQUVnQixVQUFBQSxRQUFRLEVBQUVoQixVQUFVLENBQUNnQjtBQUF2QixTQUpPO0FBS25CckIsUUFBQUEsYUFBYSxFQUFFUixNQUFNLENBQUNRO0FBTEgsT0FBckI7QUFPQSxZQUFNc0IsYUFBYSxHQUFHZixPQUFPLENBQUNDLE9BQVIsQ0FDcEIsS0FBS1osY0FBTCxDQUFvQjJCLE9BQXBCLENBQ0UsS0FBSzlCLE9BRFAsRUFFRStCLElBQUksQ0FBQ0MsU0FBTCxDQUFlTCxZQUFmLENBRkYsQ0FEb0IsQ0FBdEI7QUFNQSxhQUFPRSxhQUFhLENBQUNiLElBQWQsQ0FBbUJpQixPQUFPLElBQUk7QUFDbkMsY0FBTUMsTUFBTSxHQUFJRCxPQUFPLElBQUlBLE9BQU8sQ0FBQ0UsSUFBcEIsSUFBNkJGLE9BQTVDOztBQUNBRyx3QkFBSUMsSUFBSixDQUNHLE9BQU1mLFFBQVMsMENBQXlDVixVQUFVLENBQUNnQixRQUFTLEVBRC9FLEVBRUVNLE1BRkY7O0FBSUEsZUFBT0EsTUFBUDtBQUNELE9BUE0sQ0FBUDtBQVFELEtBMUNJLEVBMkNKSSxLQTNDSSxDQTJDRUMsR0FBRyxJQUFJO0FBQ1pILHNCQUFJQyxJQUFKLENBQ0csNENBQTJDekIsVUFBVSxDQUFDZ0IsUUFBUyxLQUFJVyxHQUFHLENBQUNDLE9BQVEsRUFEbEY7O0FBR0EsWUFBTUQsR0FBTjtBQUNELEtBaERJLENBQVA7QUFpREQ7O0FBekVvQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlTWVzc2FnZVF1ZXVlIH0gZnJvbSAnLi4vUGFyc2VNZXNzYWdlUXVldWUnO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgeyBhcHBseURldmljZVRva2VuRXhpc3RzIH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgbG9nIGZyb20gJy4uL2xvZ2dlcic7XG5cbmNvbnN0IFBVU0hfQ0hBTk5FTCA9ICdwYXJzZS1zZXJ2ZXItcHVzaCc7XG5jb25zdCBERUZBVUxUX0JBVENIX1NJWkUgPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBQdXNoUXVldWUge1xuICBwYXJzZVB1Ymxpc2hlcjogT2JqZWN0O1xuICBjaGFubmVsOiBTdHJpbmc7XG4gIGJhdGNoU2l6ZTogTnVtYmVyO1xuXG4gIC8vIGNvbmZpZyBvYmplY3Qgb2YgdGhlIHB1Ymxpc2hlciwgcmlnaHQgbm93IGl0IG9ubHkgY29udGFpbnMgdGhlIHJlZGlzVVJMLFxuICAvLyBidXQgd2UgbWF5IGV4dGVuZCBpdCBsYXRlci5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBhbnkgPSB7fSkge1xuICAgIHRoaXMuY2hhbm5lbCA9IGNvbmZpZy5jaGFubmVsIHx8IFB1c2hRdWV1ZS5kZWZhdWx0UHVzaENoYW5uZWwoKTtcbiAgICB0aGlzLmJhdGNoU2l6ZSA9IGNvbmZpZy5iYXRjaFNpemUgfHwgREVGQVVMVF9CQVRDSF9TSVpFO1xuICAgIHRoaXMucGFyc2VQdWJsaXNoZXIgPSBQYXJzZU1lc3NhZ2VRdWV1ZS5jcmVhdGVQdWJsaXNoZXIoY29uZmlnKTtcbiAgfVxuXG4gIHN0YXRpYyBkZWZhdWx0UHVzaENoYW5uZWwoKSB7XG4gICAgcmV0dXJuIGAke1BhcnNlLmFwcGxpY2F0aW9uSWR9LSR7UFVTSF9DSEFOTkVMfWA7XG4gIH1cblxuICBlbnF1ZXVlKGJvZHksIHdoZXJlLCBjb25maWcsIGF1dGgsIHB1c2hTdGF0dXMpIHtcbiAgICBjb25zdCBsaW1pdCA9IHRoaXMuYmF0Y2hTaXplO1xuXG4gICAgd2hlcmUgPSBhcHBseURldmljZVRva2VuRXhpc3RzKHdoZXJlKTtcblxuICAgIC8vIE9yZGVyIGJ5IG9iamVjdElkIHNvIG5vIGltcGFjdCBvbiB0aGUgREJcbiAgICAvLyBjb25zdCBvcmRlciA9ICdvYmplY3RJZCc7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiByZXN0LmZpbmQoY29uZmlnLCBhdXRoLCAnX0luc3RhbGxhdGlvbicsIHdoZXJlLCB7XG4gICAgICAgICAgbGltaXQ6IDAsXG4gICAgICAgICAgY291bnQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCh7IHJlc3VsdHMsIGNvdW50IH0pID0+IHtcbiAgICAgICAgaWYgKCFyZXN1bHRzIHx8IGNvdW50ID09IDApIHtcbiAgICAgICAgICByZXR1cm4gcHVzaFN0YXR1cy5jb21wbGV0ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG1heFBhZ2VzID0gTWF0aC5jZWlsKGNvdW50IC8gbGltaXQpO1xuICAgICAgICBwdXNoU3RhdHVzLnNldFJ1bm5pbmcobWF4UGFnZXMpO1xuICAgICAgICAvLyB3aGlsZSAocGFnZSA8IG1heFBhZ2VzKSB7XG4gICAgICAgIC8vIGNoYW5nZXMgcmVxdWVzdC9saW1pdC9vcmRlckJ5IGJ5IGlkIHJhbmdlIGludGVydmFscyBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAgICAgIC8vIGh0dHBzOi8vZG9jcy5tb25nb2RiLmNvbS9tYW51YWwvcmVmZXJlbmNlL21ldGhvZC9jdXJzb3Iuc2tpcC9cbiAgICAgICAgLy8gUmFuZ2UgcXVlcmllcyBjYW4gdXNlIGluZGV4ZXMgdG8gYXZvaWQgc2Nhbm5pbmcgdW53YW50ZWQgZG9jdW1lbnRzLFxuICAgICAgICAvLyB0eXBpY2FsbHkgeWllbGRpbmcgYmV0dGVyIHBlcmZvcm1hbmNlIGFzIHRoZSBvZmZzZXQgZ3Jvd3MgY29tcGFyZWRcbiAgICAgICAgLy8gdG8gdXNpbmcgY3Vyc29yLnNraXAoKSBmb3IgcGFnaW5hdGlvbi5cbiAgICAgICAgY29uc3QgcXVlcnkgPSB7IHdoZXJlIH07XG5cbiAgICAgICAgY29uc3QgcHVzaFdvcmtJdGVtID0ge1xuICAgICAgICAgIGJvZHksXG4gICAgICAgICAgcXVlcnksXG4gICAgICAgICAgbWF4UGFnZXMsXG4gICAgICAgICAgcHVzaFN0YXR1czogeyBvYmplY3RJZDogcHVzaFN0YXR1cy5vYmplY3RJZCB9LFxuICAgICAgICAgIGFwcGxpY2F0aW9uSWQ6IGNvbmZpZy5hcHBsaWNhdGlvbklkLFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBwdWJsaXNoUmVzdWx0ID0gUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIHRoaXMucGFyc2VQdWJsaXNoZXIucHVibGlzaChcbiAgICAgICAgICAgIHRoaXMuY2hhbm5lbCxcbiAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHB1c2hXb3JrSXRlbSlcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBwdWJsaXNoUmVzdWx0LnRoZW4ocmVwb25zZSA9PiB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gKHJlcG9uc2UgJiYgcmVwb25zZS5kYXRhKSB8fCByZXBvbnNlO1xuICAgICAgICAgIGxvZy5pbmZvKFxuICAgICAgICAgICAgYEFsbCAke21heFBhZ2VzfSBwYWNrYWdlcyB3ZXJlIGVucXVldWVkIGZvciBQdXNoU3RhdHVzICR7cHVzaFN0YXR1cy5vYmplY3RJZH1gLFxuICAgICAgICAgICAgcmVzdWx0XG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgbG9nLmluZm8oXG4gICAgICAgICAgYENhbid0IGNvdW50IGluc3RhbGxhdGlvbnMgZm9yIFB1c2hTdGF0dXMgJHtwdXNoU3RhdHVzLm9iamVjdElkfTogJHtlcnIubWVzc2FnZX1gXG4gICAgICAgICk7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0pO1xuICB9XG59XG4iXX0= \ 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL1B1c2hXb3JrZXIuanMiXSwibmFtZXMiOlsiZ3JvdXBCeUJhZGdlIiwiaW5zdGFsbGF0aW9ucyIsInJlZHVjZSIsIm1hcCIsImluc3RhbGxhdGlvbiIsImJhZGdlIiwicHVzaCIsIlB1c2hXb3JrZXIiLCJjb25zdHJ1Y3RvciIsInB1c2hBZGFwdGVyIiwic3Vic2NyaWJlckNvbmZpZyIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJ2YWxpZGF0ZUFkYXB0ZXIiLCJQdXNoQWRhcHRlciIsImFkYXB0ZXIiLCJjaGFubmVsIiwiUHVzaFF1ZXVlIiwiZGVmYXVsdFB1c2hDaGFubmVsIiwic3Vic2NyaWJlciIsIlBhcnNlTWVzc2FnZVF1ZXVlIiwiY3JlYXRlU3Vic2NyaWJlciIsInN1YnNjcmliZSIsIm9uIiwibWVzc2FnZVN0ciIsIndvcmtJdGVtIiwiSlNPTiIsInBhcnNlIiwicnVuIiwiYm9keSIsInF1ZXJ5IiwicHVzaFN0YXR1cyIsImFwcGxpY2F0aW9uSWQiLCJVVENPZmZzZXQiLCJjb25maWciLCJDb25maWciLCJnZXQiLCJhdXRoIiwid2hlcmUiLCJ1dGlscyIsImFwcGx5RGV2aWNlVG9rZW5FeGlzdHMiLCJvYmplY3RJZCIsInJlc3QiLCJmaW5kIiwidGhlbiIsInJlc3VsdHMiLCJsZW5ndGgiLCJzZW5kVG9BZGFwdGVyIiwibG9jYWxlcyIsImdldExvY2FsZXNGcm9tUHVzaCIsImJvZGllc1BlckxvY2FsZXMiLCJncm91cHBlZEluc3RhbGxhdGlvbnMiLCJncm91cEJ5TG9jYWxlSWRlbnRpZmllciIsInByb21pc2VzIiwiT2JqZWN0Iiwia2V5cyIsImxvY2FsZSIsIlByb21pc2UiLCJhbGwiLCJpc1B1c2hJbmNyZW1lbnRpbmciLCJsb2dnZXIiLCJ2ZXJib3NlIiwic2VuZCIsInRyYWNrU2VudCIsImJhZGdlSW5zdGFsbGF0aW9uc01hcCIsInBheWxvYWQiLCJkYXRhIiwicGFyc2VJbnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFFQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFYQTtBQWFBLFNBQVNBLFlBQVQsQ0FBc0JDLGFBQXRCLEVBQXFDO0FBQ25DLFNBQU9BLGFBQWEsQ0FBQ0MsTUFBZCxDQUFxQixDQUFDQyxHQUFELEVBQU1DLFlBQU4sS0FBdUI7QUFDakQsVUFBTUMsS0FBSyxHQUFHRCxZQUFZLENBQUNDLEtBQWIsR0FBcUIsRUFBbkM7QUFDQUYsSUFBQUEsR0FBRyxDQUFDRSxLQUFELENBQUgsR0FBYUYsR0FBRyxDQUFDRSxLQUFELENBQUgsSUFBYyxFQUEzQjtBQUNBRixJQUFBQSxHQUFHLENBQUNFLEtBQUQsQ0FBSCxDQUFXQyxJQUFYLENBQWdCRixZQUFoQjtBQUNBLFdBQU9ELEdBQVA7QUFDRCxHQUxNLEVBS0osRUFMSSxDQUFQO0FBTUQ7O0FBRU0sTUFBTUksVUFBTixDQUFpQjtBQUt0QkMsRUFBQUEsV0FBVyxDQUFDQyxXQUFELEVBQTJCQyxnQkFBcUIsR0FBRyxFQUFuRCxFQUF1RDtBQUNoRUMsaUNBQW9CQyxlQUFwQixDQUFvQ0gsV0FBcEMsRUFBaUQsSUFBakQsRUFBdURJLHdCQUF2RDs7QUFDQSxTQUFLQyxPQUFMLEdBQWVMLFdBQWY7QUFFQSxTQUFLTSxPQUFMLEdBQWVMLGdCQUFnQixDQUFDSyxPQUFqQixJQUE0QkMscUJBQVVDLGtCQUFWLEVBQTNDO0FBQ0EsU0FBS0MsVUFBTCxHQUFrQkMscUNBQWtCQyxnQkFBbEIsQ0FBbUNWLGdCQUFuQyxDQUFsQjs7QUFDQSxRQUFJLEtBQUtRLFVBQVQsRUFBcUI7QUFDbkIsWUFBTUEsVUFBVSxHQUFHLEtBQUtBLFVBQXhCO0FBQ0FBLE1BQUFBLFVBQVUsQ0FBQ0csU0FBWCxDQUFxQixLQUFLTixPQUExQjtBQUNBRyxNQUFBQSxVQUFVLENBQUNJLEVBQVgsQ0FBYyxTQUFkLEVBQXlCLENBQUNQLE9BQUQsRUFBVVEsVUFBVixLQUF5QjtBQUNoRCxjQUFNQyxRQUFRLEdBQUdDLElBQUksQ0FBQ0MsS0FBTCxDQUFXSCxVQUFYLENBQWpCO0FBQ0EsYUFBS0ksR0FBTCxDQUFTSCxRQUFUO0FBQ0QsT0FIRDtBQUlEO0FBQ0Y7O0FBRURHLEVBQUFBLEdBQUcsQ0FBQztBQUFFQyxJQUFBQSxJQUFGO0FBQVFDLElBQUFBLEtBQVI7QUFBZUMsSUFBQUEsVUFBZjtBQUEyQkMsSUFBQUEsYUFBM0I7QUFBMENDLElBQUFBO0FBQTFDLEdBQUQsRUFBeUU7QUFDMUUsVUFBTUMsTUFBTSxHQUFHQyxnQkFBT0MsR0FBUCxDQUFXSixhQUFYLENBQWY7O0FBQ0EsVUFBTUssSUFBSSxHQUFHLGtCQUFPSCxNQUFQLENBQWI7QUFDQSxVQUFNSSxLQUFLLEdBQUdDLEtBQUssQ0FBQ0Msc0JBQU4sQ0FBNkJWLEtBQUssQ0FBQ1EsS0FBbkMsQ0FBZDtBQUNBLFdBQU9SLEtBQUssQ0FBQ1EsS0FBYjtBQUNBUCxJQUFBQSxVQUFVLEdBQUcsc0NBQWtCRyxNQUFsQixFQUEwQkgsVUFBVSxDQUFDVSxRQUFyQyxDQUFiO0FBQ0EsV0FBT0MsY0FDSkMsSUFESSxDQUNDVCxNQURELEVBQ1NHLElBRFQsRUFDZSxlQURmLEVBQ2dDQyxLQURoQyxFQUN1Q1IsS0FEdkMsRUFFSmMsSUFGSSxDQUVDLENBQUM7QUFBRUMsTUFBQUE7QUFBRixLQUFELEtBQWlCO0FBQ3JCLFVBQUlBLE9BQU8sQ0FBQ0MsTUFBUixJQUFrQixDQUF0QixFQUF5QjtBQUN2QjtBQUNEOztBQUNELGFBQU8sS0FBS0MsYUFBTCxDQUFtQmxCLElBQW5CLEVBQXlCZ0IsT0FBekIsRUFBa0NkLFVBQWxDLEVBQThDRyxNQUE5QyxFQUFzREQsU0FBdEQsQ0FBUDtBQUNELEtBUEksQ0FBUDtBQVFEOztBQUVEYyxFQUFBQSxhQUFhLENBQ1hsQixJQURXLEVBRVgzQixhQUZXLEVBR1g2QixVQUhXLEVBSVhHLE1BSlcsRUFLWEQsU0FMVyxFQU1DO0FBQ1o7QUFDQSxVQUFNZSxPQUFPLEdBQUdULEtBQUssQ0FBQ1Usa0JBQU4sQ0FBeUJwQixJQUF6QixDQUFoQjs7QUFDQSxRQUFJbUIsT0FBTyxDQUFDRixNQUFSLEdBQWlCLENBQXJCLEVBQXdCO0FBQ3RCO0FBQ0EsWUFBTUksZ0JBQWdCLEdBQUdYLEtBQUssQ0FBQ1csZ0JBQU4sQ0FBdUJyQixJQUF2QixFQUE2Qm1CLE9BQTdCLENBQXpCLENBRnNCLENBSXRCOztBQUNBLFlBQU1HLHFCQUFxQixHQUFHWixLQUFLLENBQUNhLHVCQUFOLENBQzVCbEQsYUFENEIsRUFFNUI4QyxPQUY0QixDQUE5QjtBQUlBLFlBQU1LLFFBQVEsR0FBR0MsTUFBTSxDQUFDQyxJQUFQLENBQVlKLHFCQUFaLEVBQW1DL0MsR0FBbkMsQ0FBdUNvRCxNQUFNLElBQUk7QUFDaEUsY0FBTXRELGFBQWEsR0FBR2lELHFCQUFxQixDQUFDSyxNQUFELENBQTNDO0FBQ0EsY0FBTTNCLElBQUksR0FBR3FCLGdCQUFnQixDQUFDTSxNQUFELENBQTdCO0FBQ0EsZUFBTyxLQUFLVCxhQUFMLENBQ0xsQixJQURLLEVBRUwzQixhQUZLLEVBR0w2QixVQUhLLEVBSUxHLE1BSkssRUFLTEQsU0FMSyxDQUFQO0FBT0QsT0FWZ0IsQ0FBakI7QUFXQSxhQUFPd0IsT0FBTyxDQUFDQyxHQUFSLENBQVlMLFFBQVosQ0FBUDtBQUNEOztBQUVELFFBQUksQ0FBQ2QsS0FBSyxDQUFDb0Isa0JBQU4sQ0FBeUI5QixJQUF6QixDQUFMLEVBQXFDO0FBQ25DK0Isc0JBQU9DLE9BQVAsQ0FBZ0IsbUJBQWtCM0QsYUFBYSxDQUFDNEMsTUFBTyxFQUF2RDs7QUFDQSxhQUFPLEtBQUsvQixPQUFMLENBQ0orQyxJQURJLENBQ0NqQyxJQURELEVBQ08zQixhQURQLEVBQ3NCNkIsVUFBVSxDQUFDVSxRQURqQyxFQUVKRyxJQUZJLENBRUNDLE9BQU8sSUFBSTtBQUNmLGVBQU9kLFVBQVUsQ0FBQ2dDLFNBQVgsQ0FBcUJsQixPQUFyQixFQUE4QlosU0FBOUIsRUFBeUNXLElBQXpDLENBQThDLE1BQU1DLE9BQXBELENBQVA7QUFDRCxPQUpJLENBQVA7QUFLRCxLQWpDVyxDQW1DWjs7O0FBQ0EsVUFBTW1CLHFCQUFxQixHQUFHL0QsWUFBWSxDQUFDQyxhQUFELENBQTFDLENBcENZLENBc0NaOztBQUNBLFVBQU1tRCxRQUFRLEdBQUdDLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZUyxxQkFBWixFQUFtQzVELEdBQW5DLENBQXVDRSxLQUFLLElBQUk7QUFDL0QsWUFBTTJELE9BQU8sR0FBRyx1QkFBU3BDLElBQVQsQ0FBaEI7QUFDQW9DLE1BQUFBLE9BQU8sQ0FBQ0MsSUFBUixDQUFhNUQsS0FBYixHQUFxQjZELFFBQVEsQ0FBQzdELEtBQUQsQ0FBN0I7QUFDQSxZQUFNSixhQUFhLEdBQUc4RCxxQkFBcUIsQ0FBQzFELEtBQUQsQ0FBM0M7QUFDQSxhQUFPLEtBQUt5QyxhQUFMLENBQ0xrQixPQURLLEVBRUwvRCxhQUZLLEVBR0w2QixVQUhLLEVBSUxHLE1BSkssRUFLTEQsU0FMSyxDQUFQO0FBT0QsS0FYZ0IsQ0FBakI7QUFZQSxXQUFPd0IsT0FBTyxDQUFDQyxHQUFSLENBQVlMLFFBQVosQ0FBUDtBQUNEOztBQS9GcUI7OztlQWtHVDdDLFUiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgZGVlcGNvcHkgZnJvbSAnZGVlcGNvcHknO1xuaW1wb3J0IEFkYXB0YWJsZUNvbnRyb2xsZXIgZnJvbSAnLi4vQ29udHJvbGxlcnMvQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBtYXN0ZXIgfSBmcm9tICcuLi9BdXRoJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi4vQ29uZmlnJztcbmltcG9ydCB7IFB1c2hBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvUHVzaC9QdXNoQWRhcHRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCB7IHB1c2hTdGF0dXNIYW5kbGVyIH0gZnJvbSAnLi4vU3RhdHVzSGFuZGxlcic7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IFBhcnNlTWVzc2FnZVF1ZXVlIH0gZnJvbSAnLi4vUGFyc2VNZXNzYWdlUXVldWUnO1xuaW1wb3J0IHsgUHVzaFF1ZXVlIH0gZnJvbSAnLi9QdXNoUXVldWUnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuXG5mdW5jdGlvbiBncm91cEJ5QmFkZ2UoaW5zdGFsbGF0aW9ucykge1xuICByZXR1cm4gaW5zdGFsbGF0aW9ucy5yZWR1Y2UoKG1hcCwgaW5zdGFsbGF0aW9uKSA9PiB7XG4gICAgY29uc3QgYmFkZ2UgPSBpbnN0YWxsYXRpb24uYmFkZ2UgKyAnJztcbiAgICBtYXBbYmFkZ2VdID0gbWFwW2JhZGdlXSB8fCBbXTtcbiAgICBtYXBbYmFkZ2VdLnB1c2goaW5zdGFsbGF0aW9uKTtcbiAgICByZXR1cm4gbWFwO1xuICB9LCB7fSk7XG59XG5cbmV4cG9ydCBjbGFzcyBQdXNoV29ya2VyIHtcbiAgc3Vic2NyaWJlcjogP2FueTtcbiAgYWRhcHRlcjogYW55O1xuICBjaGFubmVsOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHVzaEFkYXB0ZXI6IFB1c2hBZGFwdGVyLCBzdWJzY3JpYmVyQ29uZmlnOiBhbnkgPSB7fSkge1xuICAgIEFkYXB0YWJsZUNvbnRyb2xsZXIudmFsaWRhdGVBZGFwdGVyKHB1c2hBZGFwdGVyLCB0aGlzLCBQdXNoQWRhcHRlcik7XG4gICAgdGhpcy5hZGFwdGVyID0gcHVzaEFkYXB0ZXI7XG5cbiAgICB0aGlzLmNoYW5uZWwgPSBzdWJzY3JpYmVyQ29uZmlnLmNoYW5uZWwgfHwgUHVzaFF1ZXVlLmRlZmF1bHRQdXNoQ2hhbm5lbCgpO1xuICAgIHRoaXMuc3Vic2NyaWJlciA9IFBhcnNlTWVzc2FnZVF1ZXVlLmNyZWF0ZVN1YnNjcmliZXIoc3Vic2NyaWJlckNvbmZpZyk7XG4gICAgaWYgKHRoaXMuc3Vic2NyaWJlcikge1xuICAgICAgY29uc3Qgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlcjtcbiAgICAgIHN1YnNjcmliZXIuc3Vic2NyaWJlKHRoaXMuY2hhbm5lbCk7XG4gICAgICBzdWJzY3JpYmVyLm9uKCdtZXNzYWdlJywgKGNoYW5uZWwsIG1lc3NhZ2VTdHIpID0+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..800996d327 --- /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'] = { + $gt: '' + }; // change $exists by $gt for better performance + } + + return where; +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL3V0aWxzLmpzIl0sIm5hbWVzIjpbImlzUHVzaEluY3JlbWVudGluZyIsImJvZHkiLCJkYXRhIiwiYmFkZ2UiLCJ0b0xvd2VyQ2FzZSIsIl9fb3AiLCJOdW1iZXIiLCJhbW91bnQiLCJsb2NhbGl6YWJsZUtleXMiLCJnZXRMb2NhbGVzRnJvbVB1c2giLCJTZXQiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwibWVtbyIsImtleSIsImZvckVhY2giLCJsb2NhbGl6YWJsZUtleSIsImluZGV4T2YiLCJwdXNoIiwic2xpY2UiLCJsZW5ndGgiLCJ0cmFuc2Zvcm1QdXNoQm9keUZvckxvY2FsZSIsImxvY2FsZSIsImxvY2FsZVZhbHVlIiwic3RyaXBMb2NhbGVzRnJvbUJvZHkiLCJib2RpZXNQZXJMb2NhbGVzIiwibG9jYWxlcyIsInJlc3VsdCIsImRlZmF1bHQiLCJncm91cEJ5TG9jYWxlSWRlbnRpZmllciIsImluc3RhbGxhdGlvbnMiLCJtYXAiLCJpbnN0YWxsYXRpb24iLCJhZGRlZCIsImxvY2FsZUlkZW50aWZpZXIiLCJ2YWxpZGF0ZVB1c2hUeXBlIiwid2hlcmUiLCJ2YWxpZFB1c2hUeXBlcyIsImRldmljZVR5cGVGaWVsZCIsImRldmljZVR5cGUiLCJkZXZpY2VUeXBlcyIsIkFycmF5IiwiaXNBcnJheSIsImNvbmNhdCIsImkiLCJQYXJzZSIsIkVycm9yIiwiUFVTSF9NSVNDT05GSUdVUkVEIiwiYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIiRndCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7OztBQUVPLFNBQVNBLGtCQUFULENBQTRCQyxJQUE1QixFQUFrQztBQUN2QyxNQUFJLENBQUNBLElBQUksQ0FBQ0MsSUFBTixJQUFjLENBQUNELElBQUksQ0FBQ0MsSUFBTCxDQUFVQyxLQUE3QixFQUFvQztBQUNsQyxXQUFPLEtBQVA7QUFDRDs7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QSxHQUFHLEVBQUU7QUFBUCxLQUF2QixDQUQrRCxDQUMzQjtBQUNyQzs7QUFDRCxTQUFPaEIsS0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IGRlZXBjb3B5IGZyb20gJ2RlZXBjb3B5JztcblxuZXhwb3J0IGZ1bmN0aW9uIGlzUHVzaEluY3JlbWVudGluZyhib2R5KSB7XG4gIGlmICghYm9keS5kYXRhIHx8ICFib2R5LmRhdGEuYmFkZ2UpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBiYWRnZSA9IGJvZHkuZGF0YS5iYWRnZTtcbiAgaWYgKHR5cGVvZiBiYWRnZSA9PSAnc3RyaW5nJyAmJiBiYWRnZS50b0xvd2VyQ2FzZSgpID09ICdpbmNyZW1lbnQnKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gKFxuICAgIHR5cGVvZiBiYWRnZSA9PSAnb2JqZWN0JyAmJlxuICAgIHR5cGVvZiBiYWRnZS5fX29wID09ICdzdHJpbmcnICYmXG4gICAgYmFkZ2UuX19vcC50b0xvd2VyQ2FzZSgpID09ICdpbmNyZW1lbnQnICYmXG4gICAgTnVtYmVyKGJhZGdlLmFtb3VudClcbiAgKTtcbn1cblxuY29uc3QgbG9jYWxpemFibGVLZXlzID0gWydhbGVydCcsICd0aXRsZSddO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9jYWxlc0Zyb21QdXNoKGJvZHkpIHtcbiAgY29uc3QgZGF0YSA9IGJvZHkuZGF0YTtcbiAgaWYgKCFkYXRhKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiBbXG4gICAgLi4ubmV3IFNldChcbiAgICAgIE9iamVjdC5rZXlzKGRhdGEpLnJlZHVjZSgobWVtbywga2V5KSA9PiB7XG4gICAgICAgIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKGxvY2FsaXphYmxlS2V5ID0+IHtcbiAgICAgICAgICBpZiAoa2V5LmluZGV4T2YoYCR7bG9jYWxpemFibGVLZXl9LWApID09IDApIHtcbiAgICAgICAgICAgIG1lbW8ucHVzaChrZXkuc2xpY2UobG9jYWxpemFibGVLZXkubGVuZ3RoICsgMSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgfSwgW10pXG4gICAgKSxcbiAgXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybVB1c2hCb2R5Rm9yTG9jYWxlKGJvZHksIGxvY2FsZSkge1xuICBjb25zdCBkYXRhID0gYm9keS5kYXRhO1xuICBpZiAoIWRhdGEpIHtcbiAgICByZXR1cm4gYm9keTtcbiAgfVxuICBib2R5ID0gZGVlcGNvcHkoYm9keSk7XG4gIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKGtleSA9PiB7XG4gICAgY29uc3QgbG9jYWxlVmFsdWUgPSBib2R5LmRhdGFbYCR7a2V5fS0ke2xvY2FsZX1gXTtcbiAgICBpZiAobG9jYWxlVmFsdWUpIHtcbiAgICAgIGJvZHkuZGF0YVtrZXldID0gbG9jYWxlVmFsdWU7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHN0cmlwTG9jYWxlc0Zyb21Cb2R5KGJvZHkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBMb2NhbGVzRnJvbUJvZHkoYm9keSkge1xuICBpZiAoIWJvZHkuZGF0YSkge1xuICAgIHJldHVybiBib2R5O1xuICB9XG4gIE9iamVjdC5rZXlzKGJvZHkuZGF0YSkuZm9yRWFjaChrZXkgPT4ge1xuICAgIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKGxvY2FsaXphYmxlS2V5ID0+IHtcbiAgICAgIGlmIChrZXkuaW5kZXhPZihgJHtsb2NhbGl6YWJsZUtleX0tYCkgPT0gMCkge1xuICAgICAgICBkZWxldGUgYm9keS5kYXRhW2tleV07XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gYm9keTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJvZGllc1BlckxvY2FsZXMoYm9keSwgbG9jYWxlcyA9IFtdKSB7XG4gIC8vIEdldCBhbGwgdHJhbmZvcm1lZCBib2RpZXMgZm9yIGVhY2ggbG9jYWxlXG4gIGNvbnN0IHJlc3VsdCA9IGxvY2FsZXMucmVkdWNlKChtZW1vLCBsb2NhbGUpID0+IHtcbiAgICBtZW1vW2xvY2FsZV0gPSB0cmFuc2Zvcm1QdXNoQm9keUZvckxvY2FsZShib2R5LCBsb2NhbGUpO1xuICAgIHJldHVybiBtZW1vO1xuICB9LCB7fSk7XG4gIC8vIFNldCB0aGUgZGVmYXVsdCBsb2NhbGUsIHdpdGggdGhlIHN0cmlwcGVkIGJvZHlcbiAgcmVzdWx0LmRlZmF1bHQgPSBzdHJpcExvY2FsZXNGcm9tQm9keShib2R5KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwQnlMb2NhbGVJZGVudGlmaWVyKGluc3RhbGxhdGlvbnMsIGxvY2FsZXMgPSBbXSkge1xuICByZXR1cm4gaW5zdGFsbGF0aW9ucy5yZWR1Y2UoXG4gICAgKG1hcCwgaW5zdGFsbGF0aW9uKSA9PiB7XG4gICAgICBsZXQgYWRkZWQgPSBmYWxzZTtcbiAgICAgIGxvY2FsZXMuZm9yRWFjaChsb2NhbGUgPT4ge1xuICAgICAgICBpZiAoYWRkZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGluc3RhbGxhdGlvbi5sb2NhbGVJZGVudGlmaWVyICYmXG4gICAgICAgICAgaW5zdGFsbGF0aW9uLmxvY2FsZUlkZW50aWZpZXIuaW5kZXhPZihsb2NhbGUpID09PSAwXG4gICAgICAgICkge1xuICAgICAgICAgIGFkZGVkID0gdHJ1ZTtcbiAgICAgICAgICBtYXBbbG9jYWxlXSA9IG1hcFtsb2NhbGVdIHx8IFtdO1xuICAgICAgICAgIG1hcFtsb2NhbGVdLnB1c2goaW5zdGFsbGF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoIWFkZGVkKSB7XG4gICAgICAgIG1hcC5kZWZhdWx0LnB1c2goaW5zdGFsbGF0aW9uKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtYXA7XG4gICAgfSxcbiAgICB7IGRlZmF1bHQ6IFtdIH1cbiAgKTtcbn1cblxuLyoqXG4gKiBDaGVjayB3aGV0aGVyIHRoZSBkZXZpY2VUeXBlIHBhcmFtZXRlciBpbiBxdXJ5IGNvbmRpdGlvbiBpcyB2YWxpZCBvciBub3QuXG4gKiBAcGFyYW0ge09iamVjdH0gd2hlcmUgQSBxdWVyeSBjb25kaXRpb25cbiAqIEBwYXJhbSB7QXJyYXl9IHZhbGlkUHVzaFR5cGVzIEFuIGFycmF5IG9mIHZhbGlkIHB1c2ggdHlwZXMoc3RyaW5nKVxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVQdXNoVHlwZSh3aGVyZSA9IHt9LCB2YWxpZFB1c2hUeXBlcyA9IFtdKSB7XG4gIHZhciBkZXZpY2VUeXBlRmllbGQgPSB3aGVyZS5kZXZpY2VUeXBlIHx8IHt9O1xuICB2YXIgZGV2aWNlVHlwZXMgPSBbXTtcbiAgaWYgKHR5cGVvZiBkZXZpY2VUeXBlRmllbGQgPT09ICdzdHJpbmcnKSB7XG4gICAgZGV2aWNlVHlwZXMucHVzaChkZXZpY2VUeXBlRmllbGQpO1xuICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZGV2aWNlVHlwZUZpZWxkWyckaW4nXSkpIHtcbiAgICBkZXZpY2VUeXBlcy5jb25jYXQoZGV2aWNlVHlwZUZpZWxkWyckaW4nXSk7XG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZXZpY2VUeXBlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBkZXZpY2VUeXBlID0gZGV2aWNlVHlwZXNbaV07XG4gICAgaWYgKHZhbGlkUHVzaFR5cGVzLmluZGV4T2YoZGV2aWNlVHlwZSkgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgZGV2aWNlVHlwZSArICcgaXMgbm90IHN1cHBvcnRlZCBwdXNoIHR5cGUuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMod2hlcmUpIHtcbiAgd2hlcmUgPSBkZWVwY29weSh3aGVyZSk7XG4gIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHdoZXJlLCAnZGV2aWNlVG9rZW4nKSkge1xuICAgIHdoZXJlWydkZXZpY2VUb2tlbiddID0geyAkZ3Q6ICcnIH07IC8vIGNoYW5nZSAkZXhpc3RzIGJ5ICRndCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gIH1cbiAgcmV0dXJuIHdoZXJlO1xufVxuIl19 \ No newline at end of file diff --git a/lib/RestQuery.js b/lib/RestQuery.js new file mode 100644 index 0000000000..0f7eac171e --- /dev/null +++ b/lib/RestQuery.js @@ -0,0 +1,974 @@ +"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 'explain': + case 'hint': + 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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QUNBLFFBQUlxSyxNQUFKLEVBQVk7QUFDVixhQUFPQSxNQUFQO0FBQ0Q7QUFDRjtBQUNGOztBQUVETyxNQUFNLENBQUNDLE9BQVAsR0FBaUIxTSxTQUFqQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFuIG9iamVjdCB0aGF0IGVuY2Fwc3VsYXRlcyBldmVyeXRoaW5nIHdlIG5lZWQgdG8gcnVuIGEgJ2ZpbmQnXG4vLyBvcGVyYXRpb24sIGVuY29kZWQgaW4gdGhlIFJFU1QgQVBJIGZvcm1hdC5cblxudmFyIFNjaGVtYUNvbnRyb2xsZXIgPSByZXF1aXJlKCcuL0NvbnRyb2xsZXJzL1NjaGVtYUNvbnRyb2xsZXInKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IHRyaWdnZXJzID0gcmVxdWlyZSgnLi90cmlnZ2VycycpO1xuY29uc3QgeyBjb250aW51ZVdoaWxlIH0gPSByZXF1aXJlKCdwYXJzZS9saWIvbm9kZS9wcm9taXNlVXRpbHMnKTtcbmNvbnN0IEFsd2F5c1NlbGVjdGVkS2V5cyA9IFsnb2JqZWN0SWQnLCAnY3JlYXRlZEF0JywgJ3VwZGF0ZWRBdCcsICdBQ0wnXTtcbi8vIHJlc3RPcHRpb25zIGNhbiBpbmNsdWRlOlxuLy8gICBza2lwXG4vLyAgIGxpbWl0XG4vLyAgIG9yZGVyXG4vLyAgIGNvdW50XG4vLyAgIGluY2x1ZGVcbi8vICAga2V5c1xuLy8gICBleGNsdWRlS2V5c1xuLy8gICByZWRpcmVjdENsYXNzTmFtZUZvcktleVxuLy8gICByZWFkUHJlZmVyZW5jZVxuLy8gICBpbmNsdWRlUmVhZFByZWZlcmVuY2Vcbi8vICAgc3VicXVlcnlSZWFkUHJlZmVyZW5jZVxuZnVuY3Rpb24gUmVzdFF1ZXJ5KFxuICBjb25maWcsXG4gIGF1dGgsXG4gIGNsYXNzTmFtZSxcbiAgcmVzdFdoZXJlID0ge30sXG4gIHJlc3RPcHRpb25zID0ge30sXG4gIGNsaWVudFNESyxcbiAgcnVuQWZ0ZXJGaW5kID0gdHJ1ZVxuKSB7XG4gIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICB0aGlzLmF1dGggPSBhdXRoO1xuICB0aGlzLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgdGhpcy5yZXN0V2hlcmUgPSByZXN0V2hlcmU7XG4gIHRoaXMucmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucztcbiAgdGhpcy5jbGllbnRTREsgPSBjbGllbnRTREs7XG4gIHRoaXMucnVuQWZ0ZXJGaW5kID0gcnVuQWZ0ZXJGaW5kO1xuICB0aGlzLnJlc3BvbnNlID0gbnVsbDtcbiAgdGhpcy5maW5kT3B0aW9ucyA9IHt9O1xuXG4gIGlmICghdGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgaWYgKHRoaXMuY2xhc3NOYW1lID09ICdfU2Vzc2lvbicpIHtcbiAgICAgIGlmICghdGhpcy5hdXRoLnVzZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdGhpcy5yZXN0V2hlcmUgPSB7XG4gICAgICAgICRhbmQ6IFtcbiAgICAgICAgICB0aGlzLnJlc3RXaGVyZSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB1c2VyOiB7XG4gICAgICAgICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgICAgICBjbGFzc05hbWU6ICdfVXNlcicsXG4gICAgICAgICAgICAgIG9iamVjdElkOiB0aGlzLmF1dGgudXNlci5pZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgdGhpcy5kb0NvdW50ID0gZmFsc2U7XG4gIHRoaXMuaW5jbHVkZUFsbCA9IGZhbHNlO1xuXG4gIC8vIFRoZSBmb3JtYXQgZm9yIHRoaXMuaW5jbHVkZSBpcyBub3QgdGhlIHNhbWUgYXMgdGhlIGZvcm1hdCBmb3IgdGhlXG4gIC8vIGluY2x1ZGUgb3B0aW9uIC0gaXQncyB0aGUgcGF0aHMgd2Ugc2hvdWxkIGluY2x1ZGUsIGluIG9yZGVyLFxuICAvLyBzdG9yZWQgYXMgYXJyYXlzLCB0YWtpbmcgaW50byBhY2NvdW50IHRoYXQgd2UgbmVlZCB0byBpbmNsdWRlIGZvb1xuICAvLyBiZWZvcmUgaW5jbHVkaW5nIGZvby5iYXIuIEFsc28gaXQgc2hvdWxkIGRlZHVwZS5cbiAgLy8gRm9yIGV4YW1wbGUsIHBhc3NpbmcgYW4gYXJnIG9mIGluY2x1ZGU9Zm9vLmJhcixmb28uYmF6IGNvdWxkIGxlYWQgdG9cbiAgLy8gdGhpcy5pbmNsdWRlID0gW1snZm9vJ10sIFsnZm9vJywgJ2JheiddLCBbJ2ZvbycsICdiYXInXV1cbiAgdGhpcy5pbmNsdWRlID0gW107XG5cbiAgLy8gSWYgd2UgaGF2ZSBrZXlzLCB3ZSBwcm9iYWJseSB3YW50IHRvIGZvcmNlIHNvbWUgaW5jbHVkZXMgKG4tMSBsZXZlbClcbiAgLy8gU2VlIGlzc3VlOiBodHRwczovL2dpdGh1Yi5jb20vcGFyc2UtY29tbXVuaXR5L3BhcnNlLXNlcnZlci9pc3N1ZXMvMzE4NVxuICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3RPcHRpb25zLCAna2V5cycpKSB7XG4gICAgY29uc3Qga2V5c0ZvckluY2x1ZGUgPSByZXN0T3B0aW9ucy5rZXlzXG4gICAgICAuc3BsaXQoJywnKVxuICAgICAgLmZpbHRlcihrZXkgPT4ge1xuICAgICAgICAvLyBBdCBsZWFzdCAyIGNvbXBvbmVudHNcbiAgICAgICAgcmV0dXJuIGtleS5zcGxpdCgnLicpLmxlbmd0aCA+IDE7XG4gICAgICB9KVxuICAgICAgLm1hcChrZXkgPT4ge1xuICAgICAgICAvLyBTbGljZSB0aGUgbGFzdCBjb21wb25lbnQgKGEuYi5jIC0+IGEuYilcbiAgICAgICAgLy8gT3RoZXJ3aXNlIHdlJ2xsIGluY2x1ZGUgb25lIGxldmVsIHRvbyBtdWNoLlxuICAgICAgICByZXR1cm4ga2V5LnNsaWNlKDAsIGtleS5sYXN0SW5kZXhPZignLicpKTtcbiAgICAgIH0pXG4gICAgICAuam9pbignLCcpO1xuXG4gICAgLy8gQ29uY2F0IHRoZSBwb3NzaWJseSBwcmVzZW50IGluY2x1ZGUgc3RyaW5nIHdpdGggdGhlIG9uZSBmcm9tIHRoZSBrZXlzXG4gICAgLy8gRGVkdXAgLyBzb3J0aW5nIGlzIGhhbmRsZSBpbiAnaW5jbHVkZScgY2FzZS5cbiAgICBpZiAoa2V5c0ZvckluY2x1ZGUubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKCFyZXN0T3B0aW9ucy5pbmNsdWRlIHx8IHJlc3RPcHRpb25zLmluY2x1ZGUubGVuZ3RoID09IDApIHtcbiAgICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZSA9IGtleXNGb3JJbmNsdWRlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZSArPSAnLCcgKyBrZXlzRm9ySW5jbHVkZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmb3IgKHZhciBvcHRpb24gaW4gcmVzdE9wdGlvbnMpIHtcbiAgICBzd2l0Y2ggKG9wdGlvbikge1xuICAgICAgY2FzZSAna2V5cyc6IHtcbiAgICAgICAgY29uc3Qga2V5cyA9IHJlc3RPcHRpb25zLmtleXMuc3BsaXQoJywnKS5jb25jYXQoQWx3YXlzU2VsZWN0ZWRLZXlzKTtcbiAgICAgICAgdGhpcy5rZXlzID0gQXJyYXkuZnJvbShuZXcgU2V0KGtleXMpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdleGNsdWRlS2V5cyc6IHtcbiAgICAgICAgY29uc3QgZXhjbHVkZSA9IHJlc3RPcHRpb25zLmV4Y2x1ZGVLZXlzXG4gICAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgICAuZmlsdGVyKGsgPT4gQWx3YXlzU2VsZWN0ZWRLZXlzLmluZGV4T2YoaykgPCAwKTtcbiAgICAgICAgdGhpcy5leGNsdWRlS2V5cyA9IEFycmF5LmZyb20obmV3IFNldChleGNsdWRlKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnY291bnQnOlxuICAgICAgICB0aGlzLmRvQ291bnQgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2luY2x1ZGVBbGwnOlxuICAgICAgICB0aGlzLmluY2x1ZGVBbGwgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2V4cGxhaW4nOlxuICAgICAgY2FzZSAnaGludCc6XG4gICAgICBjYXNlICdkaXN0aW5jdCc6XG4gICAgICBjYXNlICdwaXBlbGluZSc6XG4gICAgICBjYXNlICdza2lwJzpcbiAgICAgIGNhc2UgJ2xpbWl0JzpcbiAgICAgIGNhc2UgJ3JlYWRQcmVmZXJlbmNlJzpcbiAgICAgICAgdGhpcy5maW5kT3B0aW9uc1tvcHRpb25dID0gcmVzdE9wdGlvbnNbb3B0aW9uXTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdvcmRlcic6XG4gICAgICAgIHZhciBmaWVsZHMgPSByZXN0T3B0aW9ucy5vcmRlci5zcGxpdCgnLCcpO1xuICAgICAgICB0aGlzLmZpbmRPcHRpb25zLnNvcnQgPSBmaWVsZHMucmVkdWNlKChzb3J0TWFwLCBmaWVsZCkgPT4ge1xuICAgICAgICAgIGZpZWxkID0gZmllbGQudHJpbSgpO1xuICAgICAgICAgIGlmIChmaWVsZCA9PT0gJyRzY29yZScpIHtcbiAgICAgICAgICAgIHNvcnRNYXAuc2NvcmUgPSB7ICRtZXRhOiAndGV4dFNjb3JlJyB9O1xuICAgICAgICAgIH0gZWxzZSBpZiAoZmllbGRbMF0gPT0gJy0nKSB7XG4gICAgICAgICAgICBzb3J0TWFwW2ZpZWxkLnNsaWNlKDEpXSA9IC0xO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzb3J0TWFwW2ZpZWxkXSA9IDE7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBzb3J0TWFwO1xuICAgICAgICB9LCB7fSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW5jbHVkZSc6IHtcbiAgICAgICAgY29uc3QgcGF0aHMgPSByZXN0T3B0aW9ucy5pbmNsdWRlLnNwbGl0KCcsJyk7XG4gICAgICAgIGlmIChwYXRocy5pbmNsdWRlcygnKicpKSB7XG4gICAgICAgICAgdGhpcy5pbmNsdWRlQWxsID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLyBMb2FkIHRoZSBleGlzdGluZyBpbmNsdWRlcyAoZnJvbSBrZXlzKVxuICAgICAgICBjb25zdCBwYXRoU2V0ID0gcGF0aHMucmVkdWNlKChtZW1vLCBwYXRoKSA9PiB7XG4gICAgICAgICAgLy8gU3BsaXQgZWFjaCBwYXRocyBvbiAuIChhLmIuYyAtPiBbYSxiLGNdKVxuICAgICAgICAgIC8vIHJlZHVjZSB0byBjcmVhdGUgYWxsIHBhdGhzXG4gICAgICAgICAgLy8gKFthLGIsY10gLT4ge2E6IHRydWUsICdhLmInOiB0cnVlLCAnYS5iLmMnOiB0cnVlfSlcbiAgICAgICAgICByZXR1cm4gcGF0aC5zcGxpdCgnLicpLnJlZHVjZSgobWVtbywgcGF0aCwgaW5kZXgsIHBhcnRzKSA9PiB7XG4gICAgICAgICAgICBtZW1vW3BhcnRzLnNsaWNlKDAsIGluZGV4ICsgMSkuam9pbignLicpXSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgICAgICB9LCBtZW1vKTtcbiAgICAgICAgfSwge30pO1xuXG4gICAgICAgIHRoaXMuaW5jbHVkZSA9IE9iamVjdC5rZXlzKHBhdGhTZXQpXG4gICAgICAgICAgLm1hcChzID0+IHtcbiAgICAgICAgICAgIHJldHVybiBzLnNwbGl0KCcuJyk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGEubGVuZ3RoIC0gYi5sZW5ndGg7IC8vIFNvcnQgYnkgbnVtYmVyIG9mIGNvbXBvbmVudHNcbiAgICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdyZWRpcmVjdENsYXNzTmFtZUZvcktleSc6XG4gICAgICAgIHRoaXMucmVkaXJlY3RLZXkgPSByZXN0T3B0aW9ucy5yZWRpcmVjdENsYXNzTmFtZUZvcktleTtcbiAgICAgICAgdGhpcy5yZWRpcmVjdENsYXNzTmFtZSA9IG51bGw7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW5jbHVkZVJlYWRQcmVmZXJlbmNlJzpcbiAgICAgIGNhc2UgJ3N1YnF1ZXJ5UmVhZFByZWZlcmVuY2UnOlxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ2JhZCBvcHRpb246ICcgKyBvcHRpb25cbiAgICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuLy8gQSBjb252ZW5pZW50IG1ldGhvZCB0byBwZXJmb3JtIGFsbCB0aGUgc3RlcHMgb2YgcHJvY2Vzc2luZyBhIHF1ZXJ5XG4vLyBpbiBvcmRlci5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgcmVzcG9uc2UgLSBhbiBvYmplY3Qgd2l0aCBvcHRpb25hbCBrZXlzXG4vLyAncmVzdWx0cycgYW5kICdjb3VudCcuXG4vLyBUT0RPOiBjb25zb2xpZGF0ZSB0aGUgcmVwbGFjZVggZnVuY3Rpb25zXG5SZXN0UXVlcnkucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbihleGVjdXRlT3B0aW9ucykge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5idWlsZFJlc3RXaGVyZSgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlSW5jbHVkZUFsbCgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRXhjbHVkZUtleXMoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJ1bkZpbmQoZXhlY3V0ZU9wdGlvbnMpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucnVuQ291bnQoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUluY2x1ZGUoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJ1bkFmdGVyRmluZFRyaWdnZXIoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlc3BvbnNlO1xuICAgIH0pO1xufTtcblxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5lYWNoID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgY29uc3QgeyBjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgcmVzdFdoZXJlLCByZXN0T3B0aW9ucywgY2xpZW50U0RLIH0gPSB0aGlzO1xuICAvLyBpZiB0aGUgbGltaXQgaXMgc2V0LCB1c2UgaXRcbiAgcmVzdE9wdGlvbnMubGltaXQgPSByZXN0T3B0aW9ucy5saW1pdCB8fCAxMDA7XG4gIHJlc3RPcHRpb25zLm9yZGVyID0gJ29iamVjdElkJztcbiAgbGV0IGZpbmlzaGVkID0gZmFsc2U7XG5cbiAgcmV0dXJuIGNvbnRpbnVlV2hpbGUoXG4gICAgKCkgPT4ge1xuICAgICAgcmV0dXJuICFmaW5pc2hlZDtcbiAgICB9LFxuICAgIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBhdXRoLFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHJlc3RXaGVyZSxcbiAgICAgICAgcmVzdE9wdGlvbnMsXG4gICAgICAgIGNsaWVudFNES1xuICAgICAgKTtcbiAgICAgIGNvbnN0IHsgcmVzdWx0cyB9ID0gYXdhaXQgcXVlcnkuZXhlY3V0ZSgpO1xuICAgICAgcmVzdWx0cy5mb3JFYWNoKGNhbGxiYWNrKTtcbiAgICAgIGZpbmlzaGVkID0gcmVzdWx0cy5sZW5ndGggPCByZXN0T3B0aW9ucy5saW1pdDtcbiAgICAgIGlmICghZmluaXNoZWQpIHtcbiAgICAgICAgcmVzdFdoZXJlLm9iamVjdElkID0gT2JqZWN0LmFzc2lnbih7fSwgcmVzdFdoZXJlLm9iamVjdElkLCB7XG4gICAgICAgICAgJGd0OiByZXN1bHRzW3Jlc3VsdHMubGVuZ3RoIC0gMV0ub2JqZWN0SWQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn07XG5cblJlc3RRdWVyeS5wcm90b3R5cGUuYnVpbGRSZXN0V2hlcmUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VXNlckFuZFJvbGVBQ0woKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5KCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZUNsaWVudENsYXNzQ3JlYXRpb24oKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlcGxhY2VTZWxlY3QoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlcGxhY2VEb250U2VsZWN0KCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5yZXBsYWNlSW5RdWVyeSgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZU5vdEluUXVlcnkoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlcGxhY2VFcXVhbGl0eSgpO1xuICAgIH0pO1xufTtcblxuLy8gVXNlcyB0aGUgQXV0aCBvYmplY3QgdG8gZ2V0IHRoZSBsaXN0IG9mIHJvbGVzLCBhZGRzIHRoZSB1c2VyIGlkXG5SZXN0UXVlcnkucHJvdG90eXBlLmdldFVzZXJBbmRSb2xlQUNMID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICB0aGlzLmZpbmRPcHRpb25zLmFjbCA9IFsnKiddO1xuXG4gIGlmICh0aGlzLmF1dGgudXNlcikge1xuICAgIHJldHVybiB0aGlzLmF1dGguZ2V0VXNlclJvbGVzKCkudGhlbihyb2xlcyA9PiB7XG4gICAgICB0aGlzLmZpbmRPcHRpb25zLmFjbCA9IHRoaXMuZmluZE9wdGlvbnMuYWNsLmNvbmNhdChyb2xlcywgW1xuICAgICAgICB0aGlzLmF1dGgudXNlci5pZCxcbiAgICAgIF0pO1xuICAgICAgcmV0dXJuO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufTtcblxuLy8gQ2hhbmdlcyB0aGUgY2xhc3NOYW1lIGlmIHJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5IGlzIHNldC5cbi8vIFJldHVybnMgYSBwcm9taXNlLlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZWRpcmVjdENsYXNzTmFtZUZvcktleSA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMucmVkaXJlY3RLZXkpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICAvLyBXZSBuZWVkIHRvIGNoYW5nZSB0aGUgY2xhc3MgbmFtZSBiYXNlZCBvbiB0aGUgc2NoZW1hXG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgIC5yZWRpcmVjdENsYXNzTmFtZUZvcktleSh0aGlzLmNsYXNzTmFtZSwgdGhpcy5yZWRpcmVjdEtleSlcbiAgICAudGhlbihuZXdDbGFzc05hbWUgPT4ge1xuICAgICAgdGhpcy5jbGFzc05hbWUgPSBuZXdDbGFzc05hbWU7XG4gICAgICB0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lID0gbmV3Q2xhc3NOYW1lO1xuICAgIH0pO1xufTtcblxuLy8gVmFsaWRhdGVzIHRoaXMgb3BlcmF0aW9uIGFnYWluc3QgdGhlIGFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiBjb25maWcuXG5SZXN0UXVlcnkucHJvdG90eXBlLnZhbGlkYXRlQ2xpZW50Q2xhc3NDcmVhdGlvbiA9IGZ1bmN0aW9uKCkge1xuICBpZiAoXG4gICAgdGhpcy5jb25maWcuYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uID09PSBmYWxzZSAmJlxuICAgICF0aGlzLmF1dGguaXNNYXN0ZXIgJiZcbiAgICBTY2hlbWFDb250cm9sbGVyLnN5c3RlbUNsYXNzZXMuaW5kZXhPZih0aGlzLmNsYXNzTmFtZSkgPT09IC0xXG4gICkge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgLmxvYWRTY2hlbWEoKVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmhhc0NsYXNzKHRoaXMuY2xhc3NOYW1lKSlcbiAgICAgIC50aGVuKGhhc0NsYXNzID0+IHtcbiAgICAgICAgaWYgKGhhc0NsYXNzICE9PSB0cnVlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTixcbiAgICAgICAgICAgICdUaGlzIHVzZXIgaXMgbm90IGFsbG93ZWQgdG8gYWNjZXNzICcgK1xuICAgICAgICAgICAgICAnbm9uLWV4aXN0ZW50IGNsYXNzOiAnICtcbiAgICAgICAgICAgICAgdGhpcy5jbGFzc05hbWVcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybUluUXVlcnkoaW5RdWVyeU9iamVjdCwgY2xhc3NOYW1lLCByZXN1bHRzKSB7XG4gIHZhciB2YWx1ZXMgPSBbXTtcbiAgZm9yICh2YXIgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICB2YWx1ZXMucHVzaCh7XG4gICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLFxuICAgICAgb2JqZWN0SWQ6IHJlc3VsdC5vYmplY3RJZCxcbiAgICB9KTtcbiAgfVxuICBkZWxldGUgaW5RdWVyeU9iamVjdFsnJGluUXVlcnknXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoaW5RdWVyeU9iamVjdFsnJGluJ10pKSB7XG4gICAgaW5RdWVyeU9iamVjdFsnJGluJ10gPSBpblF1ZXJ5T2JqZWN0WyckaW4nXS5jb25jYXQodmFsdWVzKTtcbiAgfSBlbHNlIHtcbiAgICBpblF1ZXJ5T2JqZWN0WyckaW4nXSA9IHZhbHVlcztcbiAgfVxufVxuXG4vLyBSZXBsYWNlcyBhICRpblF1ZXJ5IGNsYXVzZSBieSBydW5uaW5nIHRoZSBzdWJxdWVyeSwgaWYgdGhlcmUgaXMgYW5cbi8vICRpblF1ZXJ5IGNsYXVzZS5cbi8vIFRoZSAkaW5RdWVyeSBjbGF1c2UgdHVybnMgaW50byBhbiAkaW4gd2l0aCB2YWx1ZXMgdGhhdCBhcmUganVzdFxuLy8gcG9pbnRlcnMgdG8gdGhlIG9iamVjdHMgcmV0dXJuZWQgaW4gdGhlIHN1YnF1ZXJ5LlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZXBsYWNlSW5RdWVyeSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgaW5RdWVyeU9iamVjdCA9IGZpbmRPYmplY3RXaXRoS2V5KHRoaXMucmVzdFdoZXJlLCAnJGluUXVlcnknKTtcbiAgaWYgKCFpblF1ZXJ5T2JqZWN0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVGhlIGluUXVlcnkgdmFsdWUgbXVzdCBoYXZlIHByZWNpc2VseSB0d28ga2V5cyAtIHdoZXJlIGFuZCBjbGFzc05hbWVcbiAgdmFyIGluUXVlcnlWYWx1ZSA9IGluUXVlcnlPYmplY3RbJyRpblF1ZXJ5J107XG4gIGlmICghaW5RdWVyeVZhbHVlLndoZXJlIHx8ICFpblF1ZXJ5VmFsdWUuY2xhc3NOYW1lKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICdpbXByb3BlciB1c2FnZSBvZiAkaW5RdWVyeSdcbiAgICApO1xuICB9XG5cbiAgY29uc3QgYWRkaXRpb25hbE9wdGlvbnMgPSB7XG4gICAgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXk6IGluUXVlcnlWYWx1ZS5yZWRpcmVjdENsYXNzTmFtZUZvcktleSxcbiAgfTtcblxuICBpZiAodGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgfSBlbHNlIGlmICh0aGlzLnJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlKSB7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgdmFyIHN1YnF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShcbiAgICB0aGlzLmNvbmZpZyxcbiAgICB0aGlzLmF1dGgsXG4gICAgaW5RdWVyeVZhbHVlLmNsYXNzTmFtZSxcbiAgICBpblF1ZXJ5VmFsdWUud2hlcmUsXG4gICAgYWRkaXRpb25hbE9wdGlvbnNcbiAgKTtcbiAgcmV0dXJuIHN1YnF1ZXJ5LmV4ZWN1dGUoKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICB0cmFuc2Zvcm1JblF1ZXJ5KGluUXVlcnlPYmplY3QsIHN1YnF1ZXJ5LmNsYXNzTmFtZSwgcmVzcG9uc2UucmVzdWx0cyk7XG4gICAgLy8gUmVjdXJzZSB0byByZXBlYXRcbiAgICByZXR1cm4gdGhpcy5yZXBsYWNlSW5RdWVyeSgpO1xuICB9KTtcbn07XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybU5vdEluUXVlcnkobm90SW5RdWVyeU9iamVjdCwgY2xhc3NOYW1lLCByZXN1bHRzKSB7XG4gIHZhciB2YWx1ZXMgPSBbXTtcbiAgZm9yICh2YXIgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICB2YWx1ZXMucHVzaCh7XG4gICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLFxuICAgICAgb2JqZWN0SWQ6IHJlc3VsdC5vYmplY3RJZCxcbiAgICB9KTtcbiAgfVxuICBkZWxldGUgbm90SW5RdWVyeU9iamVjdFsnJG5vdEluUXVlcnknXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkobm90SW5RdWVyeU9iamVjdFsnJG5pbiddKSkge1xuICAgIG5vdEluUXVlcnlPYmplY3RbJyRuaW4nXSA9IG5vdEluUXVlcnlPYmplY3RbJyRuaW4nXS5jb25jYXQodmFsdWVzKTtcbiAgfSBlbHNlIHtcbiAgICBub3RJblF1ZXJ5T2JqZWN0WyckbmluJ10gPSB2YWx1ZXM7XG4gIH1cbn1cblxuLy8gUmVwbGFjZXMgYSAkbm90SW5RdWVyeSBjbGF1c2UgYnkgcnVubmluZyB0aGUgc3VicXVlcnksIGlmIHRoZXJlIGlzIGFuXG4vLyAkbm90SW5RdWVyeSBjbGF1c2UuXG4vLyBUaGUgJG5vdEluUXVlcnkgY2xhdXNlIHR1cm5zIGludG8gYSAkbmluIHdpdGggdmFsdWVzIHRoYXQgYXJlIGp1c3Rcbi8vIHBvaW50ZXJzIHRvIHRoZSBvYmplY3RzIHJldHVybmVkIGluIHRoZSBzdWJxdWVyeS5cblJlc3RRdWVyeS5wcm90b3R5cGUucmVwbGFjZU5vdEluUXVlcnkgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG5vdEluUXVlcnlPYmplY3QgPSBmaW5kT2JqZWN0V2l0aEtleSh0aGlzLnJlc3RXaGVyZSwgJyRub3RJblF1ZXJ5Jyk7XG4gIGlmICghbm90SW5RdWVyeU9iamVjdCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFRoZSBub3RJblF1ZXJ5IHZhbHVlIG11c3QgaGF2ZSBwcmVjaXNlbHkgdHdvIGtleXMgLSB3aGVyZSBhbmQgY2xhc3NOYW1lXG4gIHZhciBub3RJblF1ZXJ5VmFsdWUgPSBub3RJblF1ZXJ5T2JqZWN0Wyckbm90SW5RdWVyeSddO1xuICBpZiAoIW5vdEluUXVlcnlWYWx1ZS53aGVyZSB8fCAhbm90SW5RdWVyeVZhbHVlLmNsYXNzTmFtZSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAnaW1wcm9wZXIgdXNhZ2Ugb2YgJG5vdEluUXVlcnknXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGFkZGl0aW9uYWxPcHRpb25zID0ge1xuICAgIHJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5OiBub3RJblF1ZXJ5VmFsdWUucmVkaXJlY3RDbGFzc05hbWVGb3JLZXksXG4gIH07XG5cbiAgaWYgKHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSkge1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gIH0gZWxzZSBpZiAodGhpcy5yZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZSkge1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZTtcbiAgfVxuXG4gIHZhciBzdWJxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgdGhpcy5jb25maWcsXG4gICAgdGhpcy5hdXRoLFxuICAgIG5vdEluUXVlcnlWYWx1ZS5jbGFzc05hbWUsXG4gICAgbm90SW5RdWVyeVZhbHVlLndoZXJlLFxuICAgIGFkZGl0aW9uYWxPcHRpb25zXG4gICk7XG4gIHJldHVybiBzdWJxdWVyeS5leGVjdXRlKCkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgdHJhbnNmb3JtTm90SW5RdWVyeShub3RJblF1ZXJ5T2JqZWN0LCBzdWJxdWVyeS5jbGFzc05hbWUsIHJlc3BvbnNlLnJlc3VsdHMpO1xuICAgIC8vIFJlY3Vyc2UgdG8gcmVwZWF0XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZU5vdEluUXVlcnkoKTtcbiAgfSk7XG59O1xuXG4vLyBVc2VkIHRvIGdldCB0aGUgZGVlcGVzdCBvYmplY3QgZnJvbSBqc29uIHVzaW5nIGRvdCBub3RhdGlvbi5cbmNvbnN0IGdldERlZXBlc3RPYmplY3RGcm9tS2V5ID0gKGpzb24sIGtleSwgaWR4LCBzcmMpID0+IHtcbiAgaWYgKGtleSBpbiBqc29uKSB7XG4gICAgcmV0dXJuIGpzb25ba2V5XTtcbiAgfVxuICBzcmMuc3BsaWNlKDEpOyAvLyBFeGl0IEVhcmx5XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1TZWxlY3QgPSAoc2VsZWN0T2JqZWN0LCBrZXksIG9iamVjdHMpID0+IHtcbiAgdmFyIHZhbHVlcyA9IFtdO1xuICBmb3IgKHZhciByZXN1bHQgb2Ygb2JqZWN0cykge1xuICAgIHZhbHVlcy5wdXNoKGtleS5zcGxpdCgnLicpLnJlZHVjZShnZXREZWVwZXN0T2JqZWN0RnJvbUtleSwgcmVzdWx0KSk7XG4gIH1cbiAgZGVsZXRlIHNlbGVjdE9iamVjdFsnJHNlbGVjdCddO1xuICBpZiAoQXJyYXkuaXNBcnJheShzZWxlY3RPYmplY3RbJyRpbiddKSkge1xuICAgIHNlbGVjdE9iamVjdFsnJGluJ10gPSBzZWxlY3RPYmplY3RbJyRpbiddLmNvbmNhdCh2YWx1ZXMpO1xuICB9IGVsc2Uge1xuICAgIHNlbGVjdE9iamVjdFsnJGluJ10gPSB2YWx1ZXM7XG4gIH1cbn07XG5cbi8vIFJlcGxhY2VzIGEgJHNlbGVjdCBjbGF1c2UgYnkgcnVubmluZyB0aGUgc3VicXVlcnksIGlmIHRoZXJlIGlzIGFcbi8vICRzZWxlY3QgY2xhdXNlLlxuLy8gVGhlICRzZWxlY3QgY2xhdXNlIHR1cm5zIGludG8gYW4gJGluIHdpdGggdmFsdWVzIHNlbGVjdGVkIG91dCBvZlxuLy8gdGhlIHN1YnF1ZXJ5LlxuLy8gUmV0dXJucyBhIHBvc3NpYmxlLXByb21pc2UuXG5SZXN0UXVlcnkucHJvdG90eXBlLnJlcGxhY2VTZWxlY3QgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHNlbGVjdE9iamVjdCA9IGZpbmRPYmplY3RXaXRoS2V5KHRoaXMucmVzdFdoZXJlLCAnJHNlbGVjdCcpO1xuICBpZiAoIXNlbGVjdE9iamVjdCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFRoZSBzZWxlY3QgdmFsdWUgbXVzdCBoYXZlIHByZWNpc2VseSB0d28ga2V5cyAtIHF1ZXJ5IGFuZCBrZXlcbiAgdmFyIHNlbGVjdFZhbHVlID0gc2VsZWN0T2JqZWN0Wyckc2VsZWN0J107XG4gIC8vIGlPUyBTREsgZG9uJ3Qgc2VuZCB3aGVyZSBpZiBub3Qgc2V0LCBsZXQgaXQgcGFzc1xuICBpZiAoXG4gICAgIXNlbGVjdFZhbHVlLnF1ZXJ5IHx8XG4gICAgIXNlbGVjdFZhbHVlLmtleSB8fFxuICAgIHR5cGVvZiBzZWxlY3RWYWx1ZS5xdWVyeSAhPT0gJ29iamVjdCcgfHxcbiAgICAhc2VsZWN0VmFsdWUucXVlcnkuY2xhc3NOYW1lIHx8XG4gICAgT2JqZWN0LmtleXMoc2VsZWN0VmFsdWUpLmxlbmd0aCAhPT0gMlxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgJ2ltcHJvcGVyIHVzYWdlIG9mICRzZWxlY3QnXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGFkZGl0aW9uYWxPcHRpb25zID0ge1xuICAgIHJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5OiBzZWxlY3RWYWx1ZS5xdWVyeS5yZWRpcmVjdENsYXNzTmFtZUZvcktleSxcbiAgfTtcblxuICBpZiAodGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgfSBlbHNlIGlmICh0aGlzLnJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlKSB7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgdmFyIHN1YnF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShcbiAgICB0aGlzLmNvbmZpZyxcbiAgICB0aGlzLmF1dGgsXG4gICAgc2VsZWN0VmFsdWUucXVlcnkuY2xhc3NOYW1lLFxuICAgIHNlbGVjdFZhbHVlLnF1ZXJ5LndoZXJlLFxuICAgIGFkZGl0aW9uYWxPcHRpb25zXG4gICk7XG4gIHJldHVybiBzdWJxdWVyeS5leGVjdXRlKCkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgdHJhbnNmb3JtU2VsZWN0KHNlbGVjdE9iamVjdCwgc2VsZWN0VmFsdWUua2V5LCByZXNwb25zZS5yZXN1bHRzKTtcbiAgICAvLyBLZWVwIHJlcGxhY2luZyAkc2VsZWN0IGNsYXVzZXNcbiAgICByZXR1cm4gdGhpcy5yZXBsYWNlU2VsZWN0KCk7XG4gIH0pO1xufTtcblxuY29uc3QgdHJhbnNmb3JtRG9udFNlbGVjdCA9IChkb250U2VsZWN0T2JqZWN0LCBrZXksIG9iamVjdHMpID0+IHtcbiAgdmFyIHZhbHVlcyA9IFtdO1xuICBmb3IgKHZhciByZXN1bHQgb2Ygb2JqZWN0cykge1xuICAgIHZhbHVlcy5wdXNoKGtleS5zcGxpdCgnLicpLnJlZHVjZShnZXREZWVwZXN0T2JqZWN0RnJvbUtleSwgcmVzdWx0KSk7XG4gIH1cbiAgZGVsZXRlIGRvbnRTZWxlY3RPYmplY3RbJyRkb250U2VsZWN0J107XG4gIGlmIChBcnJheS5pc0FycmF5KGRvbnRTZWxlY3RPYmplY3RbJyRuaW4nXSkpIHtcbiAgICBkb250U2VsZWN0T2JqZWN0WyckbmluJ10gPSBkb250U2VsZWN0T2JqZWN0WyckbmluJ10uY29uY2F0KHZhbHVlcyk7XG4gIH0gZWxzZSB7XG4gICAgZG9udFNlbGVjdE9iamVjdFsnJG5pbiddID0gdmFsdWVzO1xuICB9XG59O1xuXG4vLyBSZXBsYWNlcyBhICRkb250U2VsZWN0IGNsYXVzZSBieSBydW5uaW5nIHRoZSBzdWJxdWVyeSwgaWYgdGhlcmUgaXMgYVxuLy8gJGRvbnRTZWxlY3QgY2xhdXNlLlxuLy8gVGhlICRkb250U2VsZWN0IGNsYXVzZSB0dXJucyBpbnRvIGFuICRuaW4gd2l0aCB2YWx1ZXMgc2VsZWN0ZWQgb3V0IG9mXG4vLyB0aGUgc3VicXVlcnkuXG4vLyBSZXR1cm5zIGEgcG9zc2libGUtcHJvbWlzZS5cblJlc3RRdWVyeS5wcm90b3R5cGUucmVwbGFjZURvbnRTZWxlY3QgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGRvbnRTZWxlY3RPYmplY3QgPSBmaW5kT2JqZWN0V2l0aEtleSh0aGlzLnJlc3RXaGVyZSwgJyRkb250U2VsZWN0Jyk7XG4gIGlmICghZG9udFNlbGVjdE9iamVjdCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFRoZSBkb250U2VsZWN0IHZhbHVlIG11c3QgaGF2ZSBwcmVjaXNlbHkgdHdvIGtleXMgLSBxdWVyeSBhbmQga2V5XG4gIHZhciBkb250U2VsZWN0VmFsdWUgPSBkb250U2VsZWN0T2JqZWN0WyckZG9udFNlbGVjdCddO1xuICBpZiAoXG4gICAgIWRvbnRTZWxlY3RWYWx1ZS5xdWVyeSB8fFxuICAgICFkb250U2VsZWN0VmFsdWUua2V5IHx8XG4gICAgdHlwZW9mIGRvbnRTZWxlY3RWYWx1ZS5xdWVyeSAhPT0gJ29iamVjdCcgfHxcbiAgICAhZG9udFNlbGVjdFZhbHVlLnF1ZXJ5LmNsYXNzTmFtZSB8fFxuICAgIE9iamVjdC5rZXlzKGRvbnRTZWxlY3RWYWx1ZSkubGVuZ3RoICE9PSAyXG4gICkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAnaW1wcm9wZXIgdXNhZ2Ugb2YgJGRvbnRTZWxlY3QnXG4gICAgKTtcbiAgfVxuICBjb25zdCBhZGRpdGlvbmFsT3B0aW9ucyA9IHtcbiAgICByZWRpcmVjdENsYXNzTmFtZUZvcktleTogZG9udFNlbGVjdFZhbHVlLnF1ZXJ5LnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5LFxuICB9O1xuXG4gIGlmICh0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICB9IGVsc2UgaWYgKHRoaXMucmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICB2YXIgc3VicXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgIHRoaXMuY29uZmlnLFxuICAgIHRoaXMuYXV0aCxcbiAgICBkb250U2VsZWN0VmFsdWUucXVlcnkuY2xhc3NOYW1lLFxuICAgIGRvbnRTZWxlY3RWYWx1ZS5xdWVyeS53aGVyZSxcbiAgICBhZGRpdGlvbmFsT3B0aW9uc1xuICApO1xuICByZXR1cm4gc3VicXVlcnkuZXhlY3V0ZSgpLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgIHRyYW5zZm9ybURvbnRTZWxlY3QoXG4gICAgICBkb250U2VsZWN0T2JqZWN0LFxuICAgICAgZG9udFNlbGVjdFZhbHVlLmtleSxcbiAgICAgIHJlc3BvbnNlLnJlc3VsdHNcbiAgICApO1xuICAgIC8vIEtlZXAgcmVwbGFjaW5nICRkb250U2VsZWN0IGNsYXVzZXNcbiAgICByZXR1cm4gdGhpcy5yZXBsYWNlRG9udFNlbGVjdCgpO1xuICB9KTtcbn07XG5cbmNvbnN0IGNsZWFuUmVzdWx0QXV0aERhdGEgPSBmdW5jdGlvbihyZXN1bHQpIHtcbiAgZGVsZXRlIHJlc3VsdC5wYXNzd29yZDtcbiAgaWYgKHJlc3VsdC5hdXRoRGF0YSkge1xuICAgIE9iamVjdC5rZXlzKHJlc3VsdC5hdXRoRGF0YSkuZm9yRWFjaChwcm92aWRlciA9PiB7XG4gICAgICBpZiAocmVzdWx0LmF1dGhEYXRhW3Byb3ZpZGVyXSA9PT0gbnVsbCkge1xuICAgICAgICBkZWxldGUgcmVzdWx0LmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChPYmplY3Qua2V5cyhyZXN1bHQuYXV0aERhdGEpLmxlbmd0aCA9PSAwKSB7XG4gICAgICBkZWxldGUgcmVzdWx0LmF1dGhEYXRhO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgcmVwbGFjZUVxdWFsaXR5Q29uc3RyYWludCA9IGNvbnN0cmFpbnQgPT4ge1xuICBpZiAodHlwZW9mIGNvbnN0cmFpbnQgIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIGNvbnN0cmFpbnQ7XG4gIH1cbiAgY29uc3QgZXF1YWxUb09iamVjdCA9IHt9O1xuICBsZXQgaGFzRGlyZWN0Q29uc3RyYWludCA9IGZhbHNlO1xuICBsZXQgaGFzT3BlcmF0b3JDb25zdHJhaW50ID0gZmFsc2U7XG4gIGZvciAoY29uc3Qga2V5IGluIGNvbnN0cmFpbnQpIHtcbiAgICBpZiAoa2V5LmluZGV4T2YoJyQnKSAhPT0gMCkge1xuICAgICAgaGFzRGlyZWN0Q29uc3RyYWludCA9IHRydWU7XG4gICAgICBlcXVhbFRvT2JqZWN0W2tleV0gPSBjb25zdHJhaW50W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGhhc09wZXJhdG9yQ29uc3RyYWludCA9IHRydWU7XG4gICAgfVxuICB9XG4gIGlmIChoYXNEaXJlY3RDb25zdHJhaW50ICYmIGhhc09wZXJhdG9yQ29uc3RyYWludCkge1xuICAgIGNvbnN0cmFpbnRbJyRlcSddID0gZXF1YWxUb09iamVjdDtcbiAgICBPYmplY3Qua2V5cyhlcXVhbFRvT2JqZWN0KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBkZWxldGUgY29uc3RyYWludFtrZXldO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiBjb25zdHJhaW50O1xufTtcblxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZXBsYWNlRXF1YWxpdHkgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHR5cGVvZiB0aGlzLnJlc3RXaGVyZSAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgZm9yIChjb25zdCBrZXkgaW4gdGhpcy5yZXN0V2hlcmUpIHtcbiAgICB0aGlzLnJlc3RXaGVyZVtrZXldID0gcmVwbGFjZUVxdWFsaXR5Q29uc3RyYWludCh0aGlzLnJlc3RXaGVyZVtrZXldKTtcbiAgfVxufTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIHdoZXRoZXIgaXQgd2FzIHN1Y2Nlc3NmdWwuXG4vLyBQb3B1bGF0ZXMgdGhpcy5yZXNwb25zZSB3aXRoIGFuIG9iamVjdCB0aGF0IG9ubHkgaGFzICdyZXN1bHRzJy5cblJlc3RRdWVyeS5wcm90b3R5cGUucnVuRmluZCA9IGZ1bmN0aW9uKG9wdGlvbnMgPSB7fSkge1xuICBpZiAodGhpcy5maW5kT3B0aW9ucy5saW1pdCA9PT0gMCkge1xuICAgIHRoaXMucmVzcG9uc2UgPSB7IHJlc3VsdHM6IFtdIH07XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIGNvbnN0IGZpbmRPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5maW5kT3B0aW9ucyk7XG4gIGlmICh0aGlzLmtleXMpIHtcbiAgICBmaW5kT3B0aW9ucy5rZXlzID0gdGhpcy5rZXlzLm1hcChrZXkgPT4ge1xuICAgICAgcmV0dXJuIGtleS5zcGxpdCgnLicpWzBdO1xuICAgIH0pO1xuICB9XG4gIGlmIChvcHRpb25zLm9wKSB7XG4gICAgZmluZE9wdGlvbnMub3AgPSBvcHRpb25zLm9wO1xuICB9XG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgIC5maW5kKHRoaXMuY2xhc3NOYW1lLCB0aGlzLnJlc3RXaGVyZSwgZmluZE9wdGlvbnMsIHRoaXMuYXV0aClcbiAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgIGlmICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICBmb3IgKHZhciByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgICAgICAgIGNsZWFuUmVzdWx0QXV0aERhdGEocmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLmNvbmZpZy5maWxlc0NvbnRyb2xsZXIuZXhwYW5kRmlsZXNJbk9iamVjdCh0aGlzLmNvbmZpZywgcmVzdWx0cyk7XG5cbiAgICAgIGlmICh0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lKSB7XG4gICAgICAgIGZvciAodmFyIHIgb2YgcmVzdWx0cykge1xuICAgICAgICAgIHIuY2xhc3NOYW1lID0gdGhpcy5yZWRpcmVjdENsYXNzTmFtZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5yZXNwb25zZSA9IHsgcmVzdWx0czogcmVzdWx0cyB9O1xuICAgIH0pO1xufTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIHdoZXRoZXIgaXQgd2FzIHN1Y2Nlc3NmdWwuXG4vLyBQb3B1bGF0ZXMgdGhpcy5yZXNwb25zZS5jb3VudCB3aXRoIHRoZSBjb3VudFxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5ydW5Db3VudCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuZG9Db3VudCkge1xuICAgIHJldHVybjtcbiAgfVxuICB0aGlzLmZpbmRPcHRpb25zLmNvdW50ID0gdHJ1ZTtcbiAgZGVsZXRlIHRoaXMuZmluZE9wdGlvbnMuc2tpcDtcbiAgZGVsZXRlIHRoaXMuZmluZE9wdGlvbnMubGltaXQ7XG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgIC5maW5kKHRoaXMuY2xhc3NOYW1lLCB0aGlzLnJlc3RXaGVyZSwgdGhpcy5maW5kT3B0aW9ucylcbiAgICAudGhlbihjID0+IHtcbiAgICAgIHRoaXMucmVzcG9uc2UuY291bnQgPSBjO1xuICAgIH0pO1xufTtcblxuLy8gQXVnbWVudHMgdGhpcy5yZXNwb25zZSB3aXRoIGFsbCBwb2ludGVycyBvbiBhbiBvYmplY3RcblJlc3RRdWVyeS5wcm90b3R5cGUuaGFuZGxlSW5jbHVkZUFsbCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuaW5jbHVkZUFsbCkge1xuICAgIHJldHVybjtcbiAgfVxuICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAubG9hZFNjaGVtYSgpXG4gICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYSh0aGlzLmNsYXNzTmFtZSkpXG4gICAgLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgIGNvbnN0IGluY2x1ZGVGaWVsZHMgPSBbXTtcbiAgICAgIGNvbnN0IGtleUZpZWxkcyA9IFtdO1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBzY2hlbWEuZmllbGRzKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlICYmXG4gICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInXG4gICAgICAgICkge1xuICAgICAgICAgIGluY2x1ZGVGaWVsZHMucHVzaChbZmllbGRdKTtcbiAgICAgICAgICBrZXlGaWVsZHMucHVzaChmaWVsZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEFkZCBmaWVsZHMgdG8gaW5jbHVkZSwga2V5cywgcmVtb3ZlIGR1cHNcbiAgICAgIHRoaXMuaW5jbHVkZSA9IFsuLi5uZXcgU2V0KFsuLi50aGlzLmluY2x1ZGUsIC4uLmluY2x1ZGVGaWVsZHNdKV07XG4gICAgICAvLyBpZiB0aGlzLmtleXMgbm90IHNldCwgdGhlbiBhbGwga2V5cyBhcmUgYWxyZWFkeSBpbmNsdWRlZFxuICAgICAgaWYgKHRoaXMua2V5cykge1xuICAgICAgICB0aGlzLmtleXMgPSBbLi4ubmV3IFNldChbLi4udGhpcy5rZXlzLCAuLi5rZXlGaWVsZHNdKV07XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG4vLyBVcGRhdGVzIHByb3BlcnR5IGB0aGlzLmtleXNgIHRvIGNvbnRhaW4gYWxsIGtleXMgYnV0IHRoZSBvbmVzIHVuc2VsZWN0ZWQuXG5SZXN0UXVlcnkucHJvdG90eXBlLmhhbmRsZUV4Y2x1ZGVLZXlzID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5leGNsdWRlS2V5cykge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAodGhpcy5rZXlzKSB7XG4gICAgdGhpcy5rZXlzID0gdGhpcy5rZXlzLmZpbHRlcihrID0+ICF0aGlzLmV4Y2x1ZGVLZXlzLmluY2x1ZGVzKGspKTtcbiAgICByZXR1cm47XG4gIH1cbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgLmxvYWRTY2hlbWEoKVxuICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4gc2NoZW1hQ29udHJvbGxlci5nZXRPbmVTY2hlbWEodGhpcy5jbGFzc05hbWUpKVxuICAgIC50aGVuKHNjaGVtYSA9PiB7XG4gICAgICBjb25zdCBmaWVsZHMgPSBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKTtcbiAgICAgIHRoaXMua2V5cyA9IGZpZWxkcy5maWx0ZXIoayA9PiAhdGhpcy5leGNsdWRlS2V5cy5pbmNsdWRlcyhrKSk7XG4gICAgfSk7XG59O1xuXG4vLyBBdWdtZW50cyB0aGlzLnJlc3BvbnNlIHdpdGggZGF0YSBhdCB0aGUgcGF0aHMgcHJvdmlkZWQgaW4gdGhpcy5pbmNsdWRlLlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5oYW5kbGVJbmNsdWRlID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmluY2x1ZGUubGVuZ3RoID09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgcGF0aFJlc3BvbnNlID0gaW5jbHVkZVBhdGgoXG4gICAgdGhpcy5jb25maWcsXG4gICAgdGhpcy5hdXRoLFxuICAgIHRoaXMucmVzcG9uc2UsXG4gICAgdGhpcy5pbmNsdWRlWzBdLFxuICAgIHRoaXMucmVzdE9wdGlvbnNcbiAgKTtcbiAgaWYgKHBhdGhSZXNwb25zZS50aGVuKSB7XG4gICAgcmV0dXJuIHBhdGhSZXNwb25zZS50aGVuKG5ld1Jlc3BvbnNlID0+IHtcbiAgICAgIHRoaXMucmVzcG9uc2UgPSBuZXdSZXNwb25zZTtcbiAgICAgIHRoaXMuaW5jbHVkZSA9IHRoaXMuaW5jbHVkZS5zbGljZSgxKTtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUluY2x1ZGUoKTtcbiAgICB9KTtcbiAgfSBlbHNlIGlmICh0aGlzLmluY2x1ZGUubGVuZ3RoID4gMCkge1xuICAgIHRoaXMuaW5jbHVkZSA9IHRoaXMuaW5jbHVkZS5zbGljZSgxKTtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVJbmNsdWRlKCk7XG4gIH1cblxuICByZXR1cm4gcGF0aFJlc3BvbnNlO1xufTtcblxuLy9SZXR1cm5zIGEgcHJvbWlzZSBvZiBhIHByb2Nlc3NlZCBzZXQgb2YgcmVzdWx0c1xuUmVzdFF1ZXJ5LnByb3RvdHlwZS5ydW5BZnRlckZpbmRUcmlnZ2VyID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5yZXNwb25zZSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoIXRoaXMucnVuQWZ0ZXJGaW5kKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIEF2b2lkIGRvaW5nIGFueSBzZXR1cCBmb3IgdHJpZ2dlcnMgaWYgdGhlcmUgaXMgbm8gJ2FmdGVyRmluZCcgdHJpZ2dlciBmb3IgdGhpcyBjbGFzcy5cbiAgY29uc3QgaGFzQWZ0ZXJGaW5kSG9vayA9IHRyaWdnZXJzLnRyaWdnZXJFeGlzdHMoXG4gICAgdGhpcy5jbGFzc05hbWUsXG4gICAgdHJpZ2dlcnMuVHlwZXMuYWZ0ZXJGaW5kLFxuICAgIHRoaXMuY29uZmlnLmFwcGxpY2F0aW9uSWRcbiAgKTtcbiAgaWYgKCFoYXNBZnRlckZpbmRIb29rKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIC8vIFNraXAgQWdncmVnYXRlIGFuZCBEaXN0aW5jdCBRdWVyaWVzXG4gIGlmICh0aGlzLmZpbmRPcHRpb25zLnBpcGVsaW5lIHx8IHRoaXMuZmluZE9wdGlvbnMuZGlzdGluY3QpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gUnVuIGFmdGVyRmluZCB0cmlnZ2VyIGFuZCBzZXQgdGhlIG5ldyByZXN1bHRzXG4gIHJldHVybiB0cmlnZ2Vyc1xuICAgIC5tYXliZVJ1bkFmdGVyRmluZFRyaWdnZXIoXG4gICAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckZpbmQsXG4gICAgICB0aGlzLmF1dGgsXG4gICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgIHRoaXMucmVzcG9uc2UucmVzdWx0cyxcbiAgICAgIHRoaXMuY29uZmlnXG4gICAgKVxuICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgLy8gRW5zdXJlIHdlIHByb3Blcmx5IHNldCB0aGUgY2xhc3NOYW1lIGJhY2tcbiAgICAgIGlmICh0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lKSB7XG4gICAgICAgIHRoaXMucmVzcG9uc2UucmVzdWx0cyA9IHJlc3VsdHMubWFwKG9iamVjdCA9PiB7XG4gICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mIFBhcnNlLk9iamVjdCkge1xuICAgICAgICAgICAgb2JqZWN0ID0gb2JqZWN0LnRvSlNPTigpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvYmplY3QuY2xhc3NOYW1lID0gdGhpcy5yZWRpcmVjdENsYXNzTmFtZTtcbiAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucmVzcG9uc2UucmVzdWx0cyA9IHJlc3VsdHM7XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG4vLyBBZGRzIGluY2x1ZGVkIHZhbHVlcyB0byB0aGUgcmVzcG9uc2UuXG4vLyBQYXRoIGlzIGEgbGlzdCBvZiBmaWVsZCBuYW1lcy5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhbiBhdWdtZW50ZWQgcmVzcG9uc2UuXG5mdW5jdGlvbiBpbmNsdWRlUGF0aChjb25maWcsIGF1dGgsIHJlc3BvbnNlLCBwYXRoLCByZXN0T3B0aW9ucyA9IHt9KSB7XG4gIHZhciBwb2ludGVycyA9IGZpbmRQb2ludGVycyhyZXNwb25zZS5yZXN1bHRzLCBwYXRoKTtcbiAgaWYgKHBvaW50ZXJzLmxlbmd0aCA9PSAwKSB7XG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG4gIGNvbnN0IHBvaW50ZXJzSGFzaCA9IHt9O1xuICBmb3IgKHZhciBwb2ludGVyIG9mIHBvaW50ZXJzKSB7XG4gICAgaWYgKCFwb2ludGVyKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgY2xhc3NOYW1lID0gcG9pbnRlci5jbGFzc05hbWU7XG4gICAgLy8gb25seSBpbmNsdWRlIHRoZSBnb29kIHBvaW50ZXJzXG4gICAgaWYgKGNsYXNzTmFtZSkge1xuICAgICAgcG9pbnRlcnNIYXNoW2NsYXNzTmFtZV0gPSBwb2ludGVyc0hhc2hbY2xhc3NOYW1lXSB8fCBuZXcgU2V0KCk7XG4gICAgICBwb2ludGVyc0hhc2hbY2xhc3NOYW1lXS5hZGQocG9pbnRlci5vYmplY3RJZCk7XG4gICAgfVxuICB9XG4gIGNvbnN0IGluY2x1ZGVSZXN0T3B0aW9ucyA9IHt9O1xuICBpZiAocmVzdE9wdGlvbnMua2V5cykge1xuICAgIGNvbnN0IGtleXMgPSBuZXcgU2V0KHJlc3RPcHRpb25zLmtleXMuc3BsaXQoJywnKSk7XG4gICAgY29uc3Qga2V5U2V0ID0gQXJyYXkuZnJvbShrZXlzKS5yZWR1Y2UoKHNldCwga2V5KSA9PiB7XG4gICAgICBjb25zdCBrZXlQYXRoID0ga2V5LnNwbGl0KCcuJyk7XG4gICAgICBsZXQgaSA9IDA7XG4gICAgICBmb3IgKGk7IGkgPCBwYXRoLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChwYXRoW2ldICE9IGtleVBhdGhbaV0pIHtcbiAgICAgICAgICByZXR1cm4gc2V0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaSA8IGtleVBhdGgubGVuZ3RoKSB7XG4gICAgICAgIHNldC5hZGQoa2V5UGF0aFtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2V0O1xuICAgIH0sIG5ldyBTZXQoKSk7XG4gICAgaWYgKGtleVNldC5zaXplID4gMCkge1xuICAgICAgaW5jbHVkZVJlc3RPcHRpb25zLmtleXMgPSBBcnJheS5mcm9tKGtleVNldCkuam9pbignLCcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChyZXN0T3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2UpIHtcbiAgICBpbmNsdWRlUmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSByZXN0T3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2U7XG4gICAgaW5jbHVkZVJlc3RPcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZSA9XG4gICAgICByZXN0T3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2U7XG4gIH0gZWxzZSBpZiAocmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2UpIHtcbiAgICBpbmNsdWRlUmVzdE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSByZXN0T3B0aW9ucy5yZWFkUHJlZmVyZW5jZTtcbiAgfVxuXG4gIGNvbnN0IHF1ZXJ5UHJvbWlzZXMgPSBPYmplY3Qua2V5cyhwb2ludGVyc0hhc2gpLm1hcChjbGFzc05hbWUgPT4ge1xuICAgIGNvbnN0IG9iamVjdElkcyA9IEFycmF5LmZyb20ocG9pbnRlcnNIYXNoW2NsYXNzTmFtZV0pO1xuICAgIGxldCB3aGVyZTtcbiAgICBpZiAob2JqZWN0SWRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgd2hlcmUgPSB7IG9iamVjdElkOiBvYmplY3RJZHNbMF0gfTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hlcmUgPSB7IG9iamVjdElkOiB7ICRpbjogb2JqZWN0SWRzIH0gfTtcbiAgICB9XG4gICAgdmFyIHF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShcbiAgICAgIGNvbmZpZyxcbiAgICAgIGF1dGgsXG4gICAgICBjbGFzc05hbWUsXG4gICAgICB3aGVyZSxcbiAgICAgIGluY2x1ZGVSZXN0T3B0aW9uc1xuICAgICk7XG4gICAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoeyBvcDogJ2dldCcgfSkudGhlbihyZXN1bHRzID0+IHtcbiAgICAgIHJlc3VsdHMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHRzKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gR2V0IHRoZSBvYmplY3RzIGZvciBhbGwgdGhlc2Ugb2JqZWN0IGlkc1xuICByZXR1cm4gUHJvbWlzZS5hbGwocXVlcnlQcm9taXNlcykudGhlbihyZXNwb25zZXMgPT4ge1xuICAgIHZhciByZXBsYWNlID0gcmVzcG9uc2VzLnJlZHVjZSgocmVwbGFjZSwgaW5jbHVkZVJlc3BvbnNlKSA9PiB7XG4gICAgICBmb3IgKHZhciBvYmogb2YgaW5jbHVkZVJlc3BvbnNlLnJlc3VsdHMpIHtcbiAgICAgICAgb2JqLl9fdHlwZSA9ICdPYmplY3QnO1xuICAgICAgICBvYmouY2xhc3NOYW1lID0gaW5jbHVkZVJlc3BvbnNlLmNsYXNzTmFtZTtcblxuICAgICAgICBpZiAob2JqLmNsYXNzTmFtZSA9PSAnX1VzZXInICYmICFhdXRoLmlzTWFzdGVyKSB7XG4gICAgICAgICAgZGVsZXRlIG9iai5zZXNzaW9uVG9rZW47XG4gICAgICAgICAgZGVsZXRlIG9iai5hdXRoRGF0YTtcbiAgICAgICAgfVxuICAgICAgICByZXBsYWNlW29iai5vYmplY3RJZF0gPSBvYmo7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVwbGFjZTtcbiAgICB9LCB7fSk7XG5cbiAgICB2YXIgcmVzcCA9IHtcbiAgICAgIHJlc3VsdHM6IHJlcGxhY2VQb2ludGVycyhyZXNwb25zZS5yZXN1bHRzLCBwYXRoLCByZXBsYWNlKSxcbiAgICB9O1xuICAgIGlmIChyZXNwb25zZS5jb3VudCkge1xuICAgICAgcmVzcC5jb3VudCA9IHJlc3BvbnNlLmNvdW50O1xuICAgIH1cbiAgICByZXR1cm4gcmVzcDtcbiAgfSk7XG59XG5cbi8vIE9iamVjdCBtYXkgYmUgYSBsaXN0IG9mIFJFU1QtZm9ybWF0IG9iamVjdCB0byBmaW5kIHBvaW50ZXJzIGluLCBvclxuLy8gaXQgbWF5IGJlIGEgc2luZ2xlIG9iamVjdC5cbi8vIElmIHRoZSBwYXRoIHlpZWxkcyB0aGluZ3MgdGhhdCBhcmVuJ3QgcG9pbnRlcnMsIHRoaXMgdGhyb3dzIGFuIGVycm9yLlxuLy8gUGF0aCBpcyBhIGxpc3Qgb2YgZmllbGRzIHRvIHNlYXJjaCBpbnRvLlxuLy8gUmV0dXJucyBhIGxpc3Qgb2YgcG9pbnRlcnMgaW4gUkVTVCBmb3JtYXQuXG5mdW5jdGlvbiBmaW5kUG9pbnRlcnMob2JqZWN0LCBwYXRoKSB7XG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHZhciBhbnN3ZXIgPSBbXTtcbiAgICBmb3IgKHZhciB4IG9mIG9iamVjdCkge1xuICAgICAgYW5zd2VyID0gYW5zd2VyLmNvbmNhdChmaW5kUG9pbnRlcnMoeCwgcGF0aCkpO1xuICAgIH1cbiAgICByZXR1cm4gYW5zd2VyO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnIHx8ICFvYmplY3QpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBpZiAocGF0aC5sZW5ndGggPT0gMCkge1xuICAgIGlmIChvYmplY3QgPT09IG51bGwgfHwgb2JqZWN0Ll9fdHlwZSA9PSAnUG9pbnRlcicpIHtcbiAgICAgIHJldHVybiBbb2JqZWN0XTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgdmFyIHN1Ym9iamVjdCA9IG9iamVjdFtwYXRoWzBdXTtcbiAgaWYgKCFzdWJvYmplY3QpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgcmV0dXJuIGZpbmRQb2ludGVycyhzdWJvYmplY3QsIHBhdGguc2xpY2UoMSkpO1xufVxuXG4vLyBPYmplY3QgbWF5IGJlIGEgbGlzdCBvZiBSRVNULWZvcm1hdCBvYmplY3RzIHRvIHJlcGxhY2UgcG9pbnRlcnNcbi8vIGluLCBvciBpdCBtYXkgYmUgYSBzaW5nbGUgb2JqZWN0LlxuLy8gUGF0aCBpcyBhIGxpc3Qgb2YgZmllbGRzIHRvIHNlYXJjaCBpbnRvLlxuLy8gcmVwbGFjZSBpcyBhIG1hcCBmcm9tIG9iamVjdCBpZCAtPiBvYmplY3QuXG4vLyBSZXR1cm5zIHNvbWV0aGluZyBhbmFsb2dvdXMgdG8gb2JqZWN0LCBidXQgd2l0aCB0aGUgYXBwcm9wcmlhdGVcbi8vIHBvaW50ZXJzIGluZmxhdGVkLlxuZnVuY3Rpb24gcmVwbGFjZVBvaW50ZXJzKG9iamVjdCwgcGF0aCwgcmVwbGFjZSkge1xuICBpZiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICByZXR1cm4gb2JqZWN0XG4gICAgICAubWFwKG9iaiA9PiByZXBsYWNlUG9pbnRlcnMob2JqLCBwYXRoLCByZXBsYWNlKSlcbiAgICAgIC5maWx0ZXIob2JqID0+IHR5cGVvZiBvYmogIT09ICd1bmRlZmluZWQnKTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb2JqZWN0ICE9PSAnb2JqZWN0JyB8fCAhb2JqZWN0KSB7XG4gICAgcmV0dXJuIG9iamVjdDtcbiAgfVxuXG4gIGlmIChwYXRoLmxlbmd0aCA9PT0gMCkge1xuICAgIGlmIChvYmplY3QgJiYgb2JqZWN0Ll9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICByZXR1cm4gcmVwbGFjZVtvYmplY3Qub2JqZWN0SWRdO1xuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG5cbiAgdmFyIHN1Ym9iamVjdCA9IG9iamVjdFtwYXRoWzBdXTtcbiAgaWYgKCFzdWJvYmplY3QpIHtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG4gIHZhciBuZXdzdWIgPSByZXBsYWNlUG9pbnRlcnMoc3Vib2JqZWN0LCBwYXRoLnNsaWNlKDEpLCByZXBsYWNlKTtcbiAgdmFyIGFuc3dlciA9IHt9O1xuICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgaWYgKGtleSA9PSBwYXRoWzBdKSB7XG4gICAgICBhbnN3ZXJba2V5XSA9IG5ld3N1YjtcbiAgICB9IGVsc2Uge1xuICAgICAgYW5zd2VyW2tleV0gPSBvYmplY3Rba2V5XTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGFuc3dlcjtcbn1cblxuLy8gRmluZHMgYSBzdWJvYmplY3QgdGhhdCBoYXMgdGhlIGdpdmVuIGtleSwgaWYgdGhlcmUgaXMgb25lLlxuLy8gUmV0dXJucyB1bmRlZmluZWQgb3RoZXJ3aXNlLlxuZnVuY3Rpb24gZmluZE9iamVjdFdpdGhLZXkocm9vdCwga2V5KSB7XG4gIGlmICh0eXBlb2Ygcm9vdCAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHJvb3QgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIGZvciAodmFyIGl0ZW0gb2Ygcm9vdCkge1xuICAgICAgY29uc3QgYW5zd2VyID0gZmluZE9iamVjdFdpdGhLZXkoaXRlbSwga2V5KTtcbiAgICAgIGlmIChhbnN3ZXIpIHtcbiAgICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgaWYgKHJvb3QgJiYgcm9vdFtrZXldKSB7XG4gICAgcmV0dXJuIHJvb3Q7XG4gIH1cbiAgZm9yICh2YXIgc3Via2V5IGluIHJvb3QpIHtcbiAgICBjb25zdCBhbnN3ZXIgPSBmaW5kT2JqZWN0V2l0aEtleShyb290W3N1YmtleV0sIGtleSk7XG4gICAgaWYgKGFuc3dlcikge1xuICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICB9XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBSZXN0UXVlcnk7XG4iXX0= \ No newline at end of file diff --git a/lib/RestWrite.js b/lib/RestWrite.js new file mode 100644 index 0000000000..e2dbceb134 --- /dev/null +++ b/lib/RestWrite.js @@ -0,0 +1,1477 @@ +"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, action) { + 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 (action) { + this.runOptions.action = action; + } + + if (!query) { + if (this.config.allowCustomObjectId) { + if (Object.prototype.hasOwnProperty.call(data, 'objectId') && !data.objectId) { + throw new Parse.Error(Parse.Error.MISSING_OBJECT_ID, 'objectId must not be empty, null or undefined'); + } + } else { + if (data.objectId) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId is an invalid field name.'); + } + + if (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(); + } + /* + Usernames should be unique when compared case insensitively + Users should be able to make case sensitive usernames and + login using the case they entered. I.e. 'Snoopy' should preclude + 'snoopy' as a valid username. + */ + + + return this.config.database.find(this.className, { + username: this.data.username, + objectId: { + $ne: this.objectId() + } + }, { + limit: 1, + caseInsensitive: true + }, {}, this.validSchemaController).then(results => { + if (results.length > 0) { + throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.'); + } + + return; + }); +}; +/* + As with usernames, Parse should not allow case insensitive collisions of email. + unlike with usernames (which can have case insensitive collisions in the case of + auth adapters), emails should never have a case insensitive collision. + + This behavior can be enforced through a properly configured index see: + https://docs.mongodb.com/manual/core/index-case-insensitive/#create-a-case-insensitive-index + which could be implemented instead of this code based validation. + + Given that this lookup should be a relatively low use case and that the case sensitive + unique index will be used by the db for the query, this is an adequate solution. +*/ + + +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.')); + } // Case insensitive match, see note above function. + + + return this.config.database.find(this.className, { + email: this.data.email, + objectId: { + $ne: this.objectId() + } + }, { + limit: 1, + caseInsensitive: true + }, {}, 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9SZXN0V3JpdGUuanMiXSwibmFtZXMiOlsiU2NoZW1hQ29udHJvbGxlciIsInJlcXVpcmUiLCJkZWVwY29weSIsIkF1dGgiLCJjcnlwdG9VdGlscyIsInBhc3N3b3JkQ3J5cHRvIiwiUGFyc2UiLCJ0cmlnZ2VycyIsIkNsaWVudFNESyIsIlJlc3RXcml0ZSIsImNvbmZpZyIsImF1dGgiLCJjbGFzc05hbWUiLCJxdWVyeSIsImRhdGEiLCJvcmlnaW5hbERhdGEiLCJjbGllbnRTREsiLCJhY3Rpb24iLCJpc1JlYWRPbmx5IiwiRXJyb3IiLCJPUEVSQVRJT05fRk9SQklEREVOIiwic3RvcmFnZSIsInJ1bk9wdGlvbnMiLCJjb250ZXh0IiwiYWxsb3dDdXN0b21PYmplY3RJZCIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIm9iamVjdElkIiwiTUlTU0lOR19PQkpFQ1RfSUQiLCJJTlZBTElEX0tFWV9OQU1FIiwiaWQiLCJyZXNwb25zZSIsInVwZGF0ZWRBdCIsIl9lbmNvZGUiLCJEYXRlIiwiaXNvIiwidmFsaWRTY2hlbWFDb250cm9sbGVyIiwiZXhlY3V0ZSIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsImdldFVzZXJBbmRSb2xlQUNMIiwidmFsaWRhdGVDbGllbnRDbGFzc0NyZWF0aW9uIiwiaGFuZGxlSW5zdGFsbGF0aW9uIiwiaGFuZGxlU2Vzc2lvbiIsInZhbGlkYXRlQXV0aERhdGEiLCJydW5CZWZvcmVTYXZlVHJpZ2dlciIsImRlbGV0ZUVtYWlsUmVzZXRUb2tlbklmTmVlZGVkIiwidmFsaWRhdGVTY2hlbWEiLCJzY2hlbWFDb250cm9sbGVyIiwic2V0UmVxdWlyZWRGaWVsZHNJZk5lZWRlZCIsInRyYW5zZm9ybVVzZXIiLCJleHBhbmRGaWxlc0ZvckV4aXN0aW5nT2JqZWN0cyIsImRlc3Ryb3lEdXBsaWNhdGVkU2Vzc2lvbnMiLCJydW5EYXRhYmFzZU9wZXJhdGlvbiIsImNyZWF0ZVNlc3Npb25Ub2tlbklmTmVlZGVkIiwiaGFuZGxlRm9sbG93dXAiLCJydW5BZnRlclNhdmVUcmlnZ2VyIiwiY2xlYW5Vc2VyQXV0aERhdGEiLCJpc01hc3RlciIsImFjbCIsInVzZXIiLCJnZXRVc2VyUm9sZXMiLCJyb2xlcyIsImNvbmNhdCIsImFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiIsInN5c3RlbUNsYXNzZXMiLCJpbmRleE9mIiwiZGF0YWJhc2UiLCJsb2FkU2NoZW1hIiwiaGFzQ2xhc3MiLCJ2YWxpZGF0ZU9iamVjdCIsInRyaWdnZXJFeGlzdHMiLCJUeXBlcyIsImJlZm9yZVNhdmUiLCJhcHBsaWNhdGlvbklkIiwiZXh0cmFEYXRhIiwib3JpZ2luYWxPYmplY3QiLCJ1cGRhdGVkT2JqZWN0IiwiYnVpbGRVcGRhdGVkT2JqZWN0IiwiaW5mbGF0ZSIsImRhdGFiYXNlUHJvbWlzZSIsInVwZGF0ZSIsImNyZWF0ZSIsInJlc3VsdCIsImxlbmd0aCIsIk9CSkVDVF9OT1RfRk9VTkQiLCJtYXliZVJ1blRyaWdnZXIiLCJvYmplY3QiLCJmaWVsZHNDaGFuZ2VkQnlUcmlnZ2VyIiwiXyIsInJlZHVjZSIsInZhbHVlIiwia2V5IiwiaXNFcXVhbCIsInB1c2giLCJydW5CZWZvcmVMb2dpblRyaWdnZXIiLCJ1c2VyRGF0YSIsImJlZm9yZUxvZ2luIiwiZ2V0QWxsQ2xhc3NlcyIsImFsbENsYXNzZXMiLCJzY2hlbWEiLCJmaW5kIiwib25lQ2xhc3MiLCJzZXRSZXF1aXJlZEZpZWxkSWZOZWVkZWQiLCJmaWVsZE5hbWUiLCJzZXREZWZhdWx0IiwidW5kZWZpbmVkIiwiX19vcCIsImZpZWxkcyIsImRlZmF1bHRWYWx1ZSIsInJlcXVpcmVkIiwiVkFMSURBVElPTl9FUlJPUiIsImNyZWF0ZWRBdCIsIm5ld09iamVjdElkIiwib2JqZWN0SWRTaXplIiwia2V5cyIsImZvckVhY2giLCJhdXRoRGF0YSIsInVzZXJuYW1lIiwiaXNFbXB0eSIsIlVTRVJOQU1FX01JU1NJTkciLCJwYXNzd29yZCIsIlBBU1NXT1JEX01JU1NJTkciLCJVTlNVUFBPUlRFRF9TRVJWSUNFIiwicHJvdmlkZXJzIiwiY2FuSGFuZGxlQXV0aERhdGEiLCJjYW5IYW5kbGUiLCJwcm92aWRlciIsInByb3ZpZGVyQXV0aERhdGEiLCJoYXNUb2tlbiIsImhhbmRsZUF1dGhEYXRhIiwiaGFuZGxlQXV0aERhdGFWYWxpZGF0aW9uIiwidmFsaWRhdGlvbnMiLCJtYXAiLCJhdXRoRGF0YU1hbmFnZXIiLCJnZXRWYWxpZGF0b3JGb3JQcm92aWRlciIsImFsbCIsImZpbmRVc2Vyc1dpdGhBdXRoRGF0YSIsIm1lbW8iLCJxdWVyeUtleSIsImZpbHRlciIsInEiLCJmaW5kUHJvbWlzZSIsIiRvciIsImZpbHRlcmVkT2JqZWN0c0J5QUNMIiwib2JqZWN0cyIsIkFDTCIsInJlc3VsdHMiLCJyIiwiam9pbiIsInVzZXJSZXN1bHQiLCJtdXRhdGVkQXV0aERhdGEiLCJwcm92aWRlckRhdGEiLCJ1c2VyQXV0aERhdGEiLCJoYXNNdXRhdGVkQXV0aERhdGEiLCJ1c2VySWQiLCJsb2NhdGlvbiIsIkFDQ09VTlRfQUxSRUFEWV9MSU5LRUQiLCJwcm9taXNlIiwiZXJyb3IiLCJSZXN0UXVlcnkiLCJtYXN0ZXIiLCJfX3R5cGUiLCJzZXNzaW9uIiwiY2FjaGVDb250cm9sbGVyIiwiZGVsIiwic2Vzc2lvblRva2VuIiwiX3ZhbGlkYXRlUGFzc3dvcmRQb2xpY3kiLCJoYXNoIiwiaGFzaGVkUGFzc3dvcmQiLCJfaGFzaGVkX3Bhc3N3b3JkIiwiX3ZhbGlkYXRlVXNlck5hbWUiLCJfdmFsaWRhdGVFbWFpbCIsInJhbmRvbVN0cmluZyIsInJlc3BvbnNlU2hvdWxkSGF2ZVVzZXJuYW1lIiwiJG5lIiwibGltaXQiLCJjYXNlSW5zZW5zaXRpdmUiLCJVU0VSTkFNRV9UQUtFTiIsImVtYWlsIiwibWF0Y2giLCJyZWplY3QiLCJJTlZBTElEX0VNQUlMX0FERFJFU1MiLCJFTUFJTF9UQUtFTiIsInVzZXJDb250cm9sbGVyIiwic2V0RW1haWxWZXJpZnlUb2tlbiIsInBhc3N3b3JkUG9saWN5IiwiX3ZhbGlkYXRlUGFzc3dvcmRSZXF1aXJlbWVudHMiLCJfdmFsaWRhdGVQYXNzd29yZEhpc3RvcnkiLCJwb2xpY3lFcnJvciIsInZhbGlkYXRpb25FcnJvciIsImNvbnRhaW5zVXNlcm5hbWVFcnJvciIsInBhdHRlcm5WYWxpZGF0b3IiLCJ2YWxpZGF0b3JDYWxsYmFjayIsImRvTm90QWxsb3dVc2VybmFtZSIsIm1heFBhc3N3b3JkSGlzdG9yeSIsIm9sZFBhc3N3b3JkcyIsIl9wYXNzd29yZF9oaXN0b3J5IiwidGFrZSIsIm5ld1Bhc3N3b3JkIiwicHJvbWlzZXMiLCJjb21wYXJlIiwiY2F0Y2giLCJlcnIiLCJwcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsIiwidmVyaWZ5VXNlckVtYWlscyIsImNyZWF0ZVNlc3Npb25Ub2tlbiIsImluc3RhbGxhdGlvbklkIiwic2Vzc2lvbkRhdGEiLCJjcmVhdGVTZXNzaW9uIiwiY3JlYXRlZFdpdGgiLCJhdXRoUHJvdmlkZXIiLCJhZGRPcHMiLCJfcGVyaXNoYWJsZV90b2tlbiIsIl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQiLCJhc3NpZ24iLCJkZXN0cm95IiwicmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCIsInNlc3Npb25RdWVyeSIsImJpbmQiLCJzZW5kVmVyaWZpY2F0aW9uRW1haWwiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJhZGRpdGlvbmFsU2Vzc2lvbkRhdGEiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJzdGF0dXMiLCJkZXZpY2VUb2tlbiIsInRvTG93ZXJDYXNlIiwiZGV2aWNlVHlwZSIsImlkTWF0Y2giLCJvYmplY3RJZE1hdGNoIiwiaW5zdGFsbGF0aW9uSWRNYXRjaCIsImRldmljZVRva2VuTWF0Y2hlcyIsIm9yUXVlcmllcyIsImRlbFF1ZXJ5IiwiYXBwSWRlbnRpZmllciIsImNvZGUiLCJvYmpJZCIsImZpbGVzQ29udHJvbGxlciIsImV4cGFuZEZpbGVzSW5PYmplY3QiLCJyb2xlIiwiY2xlYXIiLCJpc1VuYXV0aGVudGljYXRlZCIsIlNFU1NJT05fTUlTU0lORyIsImRvd25sb2FkIiwiZG93bmxvYWROYW1lIiwibmFtZSIsIklOVkFMSURfQUNMIiwicmVhZCIsIndyaXRlIiwibWF4UGFzc3dvcmRBZ2UiLCJfcGFzc3dvcmRfY2hhbmdlZF9hdCIsImRlZmVyIiwiTWF0aCIsIm1heCIsInNoaWZ0IiwiX3VwZGF0ZVJlc3BvbnNlV2l0aERhdGEiLCJEVVBMSUNBVEVfVkFMVUUiLCJ1c2VySW5mbyIsImR1cGxpY2F0ZWRfZmllbGQiLCJoYXNBZnRlclNhdmVIb29rIiwiYWZ0ZXJTYXZlIiwiaGFzTGl2ZVF1ZXJ5IiwibGl2ZVF1ZXJ5Q29udHJvbGxlciIsIl9oYW5kbGVTYXZlUmVzcG9uc2UiLCJwZXJtcyIsImdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsIm9uQWZ0ZXJTYXZlIiwibG9nZ2VyIiwid2FybiIsIm1pZGRsZSIsIm1vdW50Iiwic2FuaXRpemVkRGF0YSIsInRlc3QiLCJfZGVjb2RlIiwic3BsaXR0ZWRLZXkiLCJzcGxpdCIsInBhcmVudFByb3AiLCJwYXJlbnRWYWwiLCJnZXQiLCJzZXQiLCJjbGllbnRTdXBwb3J0c0RlbGV0ZSIsInN1cHBvcnRzRm9yd2FyZERlbGV0ZSIsImRhdGFWYWx1ZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFhQTs7QUFDQTs7QUFDQTs7OztBQWZBO0FBQ0E7QUFDQTtBQUVBLElBQUlBLGdCQUFnQixHQUFHQyxPQUFPLENBQUMsZ0NBQUQsQ0FBOUI7O0FBQ0EsSUFBSUMsUUFBUSxHQUFHRCxPQUFPLENBQUMsVUFBRCxDQUF0Qjs7QUFFQSxNQUFNRSxJQUFJLEdBQUdGLE9BQU8sQ0FBQyxRQUFELENBQXBCOztBQUNBLElBQUlHLFdBQVcsR0FBR0gsT0FBTyxDQUFDLGVBQUQsQ0FBekI7O0FBQ0EsSUFBSUksY0FBYyxHQUFHSixPQUFPLENBQUMsWUFBRCxDQUE1Qjs7QUFDQSxJQUFJSyxLQUFLLEdBQUdMLE9BQU8sQ0FBQyxZQUFELENBQW5COztB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LFFBQVA7QUFDRCxDQXJCRDs7ZUF1QmV4QixTOztBQUNmcVIsTUFBTSxDQUFDQyxPQUFQLEdBQWlCdFIsU0FBakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBBIFJlc3RXcml0ZSBlbmNhcHN1bGF0ZXMgZXZlcnl0aGluZyB3ZSBuZWVkIHRvIHJ1biBhbiBvcGVyYXRpb25cbi8vIHRoYXQgd3JpdGVzIHRvIHRoZSBkYXRhYmFzZS5cbi8vIFRoaXMgY291bGQgYmUgZWl0aGVyIGEgXCJjcmVhdGVcIiBvciBhbiBcInVwZGF0ZVwiLlxuXG52YXIgU2NoZW1hQ29udHJvbGxlciA9IHJlcXVpcmUoJy4vQ29udHJvbGxlcnMvU2NoZW1hQ29udHJvbGxlcicpO1xudmFyIGRlZXBjb3B5ID0gcmVxdWlyZSgnZGVlcGNvcHknKTtcblxuY29uc3QgQXV0aCA9IHJlcXVpcmUoJy4vQXV0aCcpO1xudmFyIGNyeXB0b1V0aWxzID0gcmVxdWlyZSgnLi9jcnlwdG9VdGlscycpO1xudmFyIHBhc3N3b3JkQ3J5cHRvID0gcmVxdWlyZSgnLi9wYXNzd29yZCcpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpO1xudmFyIHRyaWdnZXJzID0gcmVxdWlyZSgnLi90cmlnZ2VycycpO1xudmFyIENsaWVudFNESyA9IHJlcXVpcmUoJy4vQ2xpZW50U0RLJyk7XG5pbXBvcnQgUmVzdFF1ZXJ5IGZyb20gJy4vUmVzdFF1ZXJ5JztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4vbG9nZ2VyJztcblxuLy8gcXVlcnkgYW5kIGRhdGEgYXJlIGJvdGggcHJvdmlkZWQgaW4gUkVTVCBBUEkgZm9ybWF0LiBTbyBkYXRhXG4vLyB0eXBlcyBhcmUgZW5jb2RlZCBieSBwbGFpbiBvbGQgb2JqZWN0cy5cbi8vIElmIHF1ZXJ5IGlzIG51bGwsIHRoaXMgaXMgYSBcImNyZWF0ZVwiIGFuZCB0aGUgZGF0YSBpbiBkYXRhIHNob3VsZCBiZVxuLy8gY3JlYXRlZC5cbi8vIE90aGVyd2lzZSB0aGlzIGlzIGFuIFwidXBkYXRlXCIgLSB0aGUgb2JqZWN0IG1hdGNoaW5nIHRoZSBxdWVyeVxuLy8gc2hvdWxkIGdldCB1cGRhdGVkIHdpdGggZGF0YS5cbi8vIFJlc3RXcml0ZSB3aWxsIGhhbmRsZSBvYmplY3RJZCwgY3JlYXRlZEF0LCBhbmQgdXBkYXRlZEF0IGZvclxuLy8gZXZlcnl0aGluZy4gSXQgYWxzbyBrbm93cyB0byB1c2UgdHJpZ2dlcnMgYW5kIHNwZWNpYWwgbW9kaWZpY2F0aW9uc1xuLy8gZm9yIHRoZSBfVXNlciBjbGFzcy5cbmZ1bmN0aW9uIFJlc3RXcml0ZShcbiAgY29uZmlnLFxuICBhdXRoLFxuICBjbGFzc05hbWUsXG4gIHF1ZXJ5LFxuICBkYXRhLFxuICBvcmlnaW5hbERhdGEsXG4gIGNsaWVudFNESyxcbiAgYWN0aW9uXG4pIHtcbiAgaWYgKGF1dGguaXNSZWFkT25seSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICAnQ2Fubm90IHBlcmZvcm0gYSB3cml0ZSBvcGVyYXRpb24gd2hlbiB1c2luZyByZWFkT25seU1hc3RlcktleSdcbiAgICApO1xuICB9XG4gIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICB0aGlzLmF1dGggPSBhdXRoO1xuICB0aGlzLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgdGhpcy5jbGllbnRTREsgPSBjbGllbnRTREs7XG4gIHRoaXMuc3RvcmFnZSA9IHt9O1xuICB0aGlzLnJ1bk9wdGlvbnMgPSB7fTtcbiAgdGhpcy5jb250ZXh0ID0ge307XG5cbiAgaWYgKGFjdGlvbikge1xuICAgIHRoaXMucnVuT3B0aW9ucy5hY3Rpb24gPSBhY3Rpb247XG4gIH1cblxuICBpZiAoIXF1ZXJ5KSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmFsbG93Q3VzdG9tT2JqZWN0SWQpIHtcbiAgICAgIGlmIChcbiAgICAgICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGRhdGEsICdvYmplY3RJZCcpICYmXG4gICAgICAgICFkYXRhLm9iamVjdElkXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLk1JU1NJTkdfT0JKRUNUX0lELFxuICAgICAgICAgICdvYmplY3RJZCBtdXN0IG5vdCBiZSBlbXB0eSwgbnVsbCBvciB1bmRlZmluZWQnXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChkYXRhLm9iamVjdElkKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgICAgICdvYmplY3RJZCBpcyBhbiBpbnZhbGlkIGZpZWxkIG5hbWUuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKGRhdGEuaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsXG4gICAgICAgICAgJ2lkIGlzIGFuIGludmFsaWQgZmllbGQgbmFtZS4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gV2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlLCB0aGlzLnJlc3BvbnNlIG1heSBoYXZlIHNldmVyYWxcbiAgLy8gZmllbGRzLlxuICAvLyByZXNwb25zZTogdGhlIGFjdHVhbCBkYXRhIHRvIGJlIHJldHVybmVkXG4gIC8vIHN0YXR1czogdGhlIGh0dHAgc3RhdHVzIGNvZGUuIGlmIG5vdCBwcmVzZW50LCB0cmVhdGVkIGxpa2UgYSAyMDBcbiAgLy8gbG9jYXRpb246IHRoZSBsb2NhdGlvbiBoZWFkZXIuIGlmIG5vdCBwcmVzZW50LCBubyBsb2NhdGlvbiBoZWFkZXJcbiAgdGhpcy5yZXNwb25zZSA9IG51bGw7XG5cbiAgLy8gUHJvY2Vzc2luZyB0aGlzIG9wZXJhdGlvbiBtYXkgbXV0YXRlIG91ciBkYXRhLCBzbyB3ZSBvcGVyYXRlIG9uIGFcbiAgLy8gY29weVxuICB0aGlzLnF1ZXJ5ID0gZGVlcGNvcHkocXVlcnkpO1xuICB0aGlzLmRhdGEgPSBkZWVwY29weShkYXRhKTtcbiAgLy8gV2UgbmV2ZXIgY2hhbmdlIG9yaWdpbmFsRGF0YSwgc28gd2UgZG8gbm90IG5lZWQgYSBkZWVwIGNvcHlcbiAgdGhpcy5vcmlnaW5hbERhdGEgPSBvcmlnaW5hbERhdGE7XG5cbiAgLy8gVGhlIHRpbWVzdGFtcCB3ZSdsbCB1c2UgZm9yIHRoaXMgd2hvbGUgb3BlcmF0aW9uXG4gIHRoaXMudXBkYXRlZEF0ID0gUGFyc2UuX2VuY29kZShuZXcgRGF0ZSgpKS5pc287XG5cbiAgLy8gU2hhcmVkIFNjaGVtYUNvbnRyb2xsZXIgdG8gYmUgcmV1c2VkIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIGxvYWRTY2hlbWEoKSBjYWxscyBwZXIgcmVxdWVzdFxuICAvLyBPbmNlIHNldCB0aGUgc2NoZW1hRGF0YSBzaG91bGQgYmUgaW1tdXRhYmxlXG4gIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyID0gbnVsbDtcbn1cblxuLy8gQSBjb252ZW5pZW50IG1ldGhvZCB0byBwZXJmb3JtIGFsbCB0aGUgc3RlcHMgb2YgcHJvY2Vzc2luZyB0aGVcbi8vIHdyaXRlLCBpbiBvcmRlci5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHtyZXNwb25zZSwgc3RhdHVzLCBsb2NhdGlvbn0gb2JqZWN0LlxuLy8gc3RhdHVzIGFuZCBsb2NhdGlvbiBhcmUgb3B0aW9uYWwuXG5SZXN0V3JpdGUucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VXNlckFuZFJvbGVBQ0woKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlQ2xpZW50Q2xhc3NDcmVhdGlvbigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlSW5zdGFsbGF0aW9uKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVTZXNzaW9uKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZUF1dGhEYXRhKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5ydW5CZWZvcmVTYXZlVHJpZ2dlcigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuZGVsZXRlRW1haWxSZXNldFRva2VuSWZOZWVkZWQoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlU2NoZW1hKCk7XG4gICAgfSlcbiAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHtcbiAgICAgIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyID0gc2NoZW1hQ29udHJvbGxlcjtcbiAgICAgIHJldHVybiB0aGlzLnNldFJlcXVpcmVkRmllbGRzSWZOZWVkZWQoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybVVzZXIoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmV4cGFuZEZpbGVzRm9yRXhpc3RpbmdPYmplY3RzKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5kZXN0cm95RHVwbGljYXRlZFNlc3Npb25zKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5ydW5EYXRhYmFzZU9wZXJhdGlvbigpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlU2Vzc2lvblRva2VuSWZOZWVkZWQoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUZvbGxvd3VwKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5ydW5BZnRlclNhdmVUcmlnZ2VyKCk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5jbGVhblVzZXJBdXRoRGF0YSgpO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVzcG9uc2U7XG4gICAgfSk7XG59O1xuXG4vLyBVc2VzIHRoZSBBdXRoIG9iamVjdCB0byBnZXQgdGhlIGxpc3Qgb2Ygcm9sZXMsIGFkZHMgdGhlIHVzZXIgaWRcblJlc3RXcml0ZS5wcm90b3R5cGUuZ2V0VXNlckFuZFJvbGVBQ0wgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuYXV0aC5pc01hc3Rlcikge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIHRoaXMucnVuT3B0aW9ucy5hY2wgPSBbJyonXTtcblxuICBpZiAodGhpcy5hdXRoLnVzZXIpIHtcbiAgICByZXR1cm4gdGhpcy5hdXRoLmdldFVzZXJSb2xlcygpLnRoZW4ocm9sZXMgPT4ge1xuICAgICAgdGhpcy5ydW5PcHRpb25zLmFjbCA9IHRoaXMucnVuT3B0aW9ucy5hY2wuY29uY2F0KHJvbGVzLCBbXG4gICAgICAgIHRoaXMuYXV0aC51c2VyLmlkLFxuICAgICAgXSk7XG4gICAgICByZXR1cm47XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG59O1xuXG4vLyBWYWxpZGF0ZXMgdGhpcyBvcGVyYXRpb24gYWdhaW5zdCB0aGUgYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uIGNvbmZpZy5cblJlc3RXcml0ZS5wcm90b3R5cGUudmFsaWRhdGVDbGllbnRDbGFzc0NyZWF0aW9uID0gZnVuY3Rpb24oKSB7XG4gIGlmIChcbiAgICB0aGlzLmNvbmZpZy5hbGxvd0NsaWVudENsYXNzQ3JlYXRpb24gPT09IGZhbHNlICYmXG4gICAgIXRoaXMuYXV0aC5pc01hc3RlciAmJlxuICAgIFNjaGVtYUNvbnRyb2xsZXIuc3lzdGVtQ2xhc3Nlcy5pbmRleE9mKHRoaXMuY2xhc3NOYW1lKSA9PT0gLTFcbiAgKSB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgICAubG9hZFNjaGVtYSgpXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuaGFzQ2xhc3ModGhpcy5jbGFzc05hbWUpKVxuICAgICAgLnRoZW4oaGFzQ2xhc3MgPT4ge1xuICAgICAgICBpZiAoaGFzQ2xhc3MgIT09IHRydWUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgJ1RoaXMgdXNlciBpcyBub3QgYWxsb3dlZCB0byBhY2Nlc3MgJyArXG4gICAgICAgICAgICAgICdub24tZXhpc3RlbnQgY2xhc3M6ICcgK1xuICAgICAgICAgICAgICB0aGlzLmNsYXNzTmFtZVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufTtcblxuLy8gVmFsaWRhdGVzIHRoaXMgb3BlcmF0aW9uIGFnYWluc3QgdGhlIHNjaGVtYS5cblJlc3RXcml0ZS5wcm90b3R5cGUudmFsaWRhdGVTY2hlbWEgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLnZhbGlkYXRlT2JqZWN0KFxuICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgIHRoaXMuZGF0YSxcbiAgICB0aGlzLnF1ZXJ5LFxuICAgIHRoaXMucnVuT3B0aW9uc1xuICApO1xufTtcblxuLy8gUnVucyBhbnkgYmVmb3JlU2F2ZSB0cmlnZ2VycyBhZ2FpbnN0IHRoaXMgb3BlcmF0aW9uLlxuLy8gQW55IGNoYW5nZSBsZWFkcyB0byBvdXIgZGF0YSBiZWluZyBtdXRhdGVkLlxuUmVzdFdyaXRlLnByb3RvdHlwZS5ydW5CZWZvcmVTYXZlVHJpZ2dlciA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5yZXNwb25zZSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEF2b2lkIGRvaW5nIGFueSBzZXR1cCBmb3IgdHJpZ2dlcnMgaWYgdGhlcmUgaXMgbm8gJ2JlZm9yZVNhdmUnIHRyaWdnZXIgZm9yIHRoaXMgY2xhc3MuXG4gIGlmIChcbiAgICAhdHJpZ2dlcnMudHJpZ2dlckV4aXN0cyhcbiAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlU2F2ZSxcbiAgICAgIHRoaXMuY29uZmlnLmFwcGxpY2F0aW9uSWRcbiAgICApXG4gICkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIENsb3VkIGNvZGUgZ2V0cyBhIGJpdCBvZiBleHRyYSBkYXRhIGZvciBpdHMgb2JqZWN0c1xuICB2YXIgZXh0cmFEYXRhID0geyBjbGFzc05hbWU6IHRoaXMuY2xhc3NOYW1lIH07XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICBleHRyYURhdGEub2JqZWN0SWQgPSB0aGlzLnF1ZXJ5Lm9iamVjdElkO1xuICB9XG5cbiAgbGV0IG9yaWdpbmFsT2JqZWN0ID0gbnVsbDtcbiAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRoaXMuYnVpbGRVcGRhdGVkT2JqZWN0KGV4dHJhRGF0YSk7XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICAvLyBUaGlzIGlzIGFuIHVwZGF0ZSBmb3IgZXhpc3Rpbmcgb2JqZWN0LlxuICAgIG9yaWdpbmFsT2JqZWN0ID0gdHJpZ2dlcnMuaW5mbGF0ZShleHRyYURhdGEsIHRoaXMub3JpZ2luYWxEYXRhKTtcbiAgfVxuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIC8vIEJlZm9yZSBjYWxsaW5nIHRoZSB0cmlnZ2VyLCB2YWxpZGF0ZSB0aGUgcGVybWlzc2lvbnMgZm9yIHRoZSBzYXZlIG9wZXJhdGlvblxuICAgICAgbGV0IGRhdGFiYXNlUHJvbWlzZSA9IG51bGw7XG4gICAgICBpZiAodGhpcy5xdWVyeSkge1xuICAgICAgICAvLyBWYWxpZGF0ZSBmb3IgdXBkYXRpbmdcbiAgICAgICAgZGF0YWJhc2VQcm9taXNlID0gdGhpcy5jb25maWcuZGF0YWJhc2UudXBkYXRlKFxuICAgICAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgICAgIHRoaXMucXVlcnksXG4gICAgICAgICAgdGhpcy5kYXRhLFxuICAgICAgICAgIHRoaXMucnVuT3B0aW9ucyxcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBWYWxpZGF0ZSBmb3IgY3JlYXRpbmdcbiAgICAgICAgZGF0YWJhc2VQcm9taXNlID0gdGhpcy5jb25maWcuZGF0YWJhc2UuY3JlYXRlKFxuICAgICAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgICAgIHRoaXMuZGF0YSxcbiAgICAgICAgICB0aGlzLnJ1bk9wdGlvbnMsXG4gICAgICAgICAgdHJ1ZVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy8gSW4gdGhlIGNhc2UgdGhhdCB0aGVyZSBpcyBubyBwZXJtaXNzaW9uIGZvciB0aGUgb3BlcmF0aW9uLCBpdCB0aHJvd3MgYW4gZXJyb3JcbiAgICAgIHJldHVybiBkYXRhYmFzZVByb21pc2UudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBpZiAoIXJlc3VsdCB8fCByZXN1bHQubGVuZ3RoIDw9IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRyaWdnZXJzLm1heWJlUnVuVHJpZ2dlcihcbiAgICAgICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlU2F2ZSxcbiAgICAgICAgdGhpcy5hdXRoLFxuICAgICAgICB1cGRhdGVkT2JqZWN0LFxuICAgICAgICBvcmlnaW5hbE9iamVjdCxcbiAgICAgICAgdGhpcy5jb25maWcsXG4gICAgICAgIHRoaXMuY29udGV4dFxuICAgICAgKTtcbiAgICB9KVxuICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgIGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5vYmplY3QpIHtcbiAgICAgICAgdGhpcy5zdG9yYWdlLmZpZWxkc0NoYW5nZWRCeVRyaWdnZXIgPSBfLnJlZHVjZShcbiAgICAgICAgICByZXNwb25zZS5vYmplY3QsXG4gICAgICAgICAgKHJlc3VsdCwgdmFsdWUsIGtleSkgPT4ge1xuICAgICAgICAgICAgaWYgKCFfLmlzRXF1YWwodGhpcy5kYXRhW2tleV0sIHZhbHVlKSkge1xuICAgICAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIFtdXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZGF0YSA9IHJlc3BvbnNlLm9iamVjdDtcbiAgICAgICAgLy8gV2Ugc2hvdWxkIGRlbGV0ZSB0aGUgb2JqZWN0SWQgZm9yIGFuIHVwZGF0ZSB3cml0ZVxuICAgICAgICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgICAgICAgZGVsZXRlIHRoaXMuZGF0YS5vYmplY3RJZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5ydW5CZWZvcmVMb2dpblRyaWdnZXIgPSBhc3luYyBmdW5jdGlvbih1c2VyRGF0YSkge1xuICAvLyBBdm9pZCBkb2luZyBhbnkgc2V0dXAgZm9yIHRyaWdnZXJzIGlmIHRoZXJlIGlzIG5vICdiZWZvcmVMb2dpbicgdHJpZ2dlclxuICBpZiAoXG4gICAgIXRyaWdnZXJzLnRyaWdnZXJFeGlzdHMoXG4gICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZUxvZ2luLFxuICAgICAgdGhpcy5jb25maWcuYXBwbGljYXRpb25JZFxuICAgIClcbiAgKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gQ2xvdWQgY29kZSBnZXRzIGEgYml0IG9mIGV4dHJhIGRhdGEgZm9yIGl0cyBvYmplY3RzXG4gIGNvbnN0IGV4dHJhRGF0YSA9IHsgY2xhc3NOYW1lOiB0aGlzLmNsYXNzTmFtZSB9O1xuICBjb25zdCB1c2VyID0gdHJpZ2dlcnMuaW5mbGF0ZShleHRyYURhdGEsIHVzZXJEYXRhKTtcblxuICAvLyBubyBuZWVkIHRvIHJldHVybiBhIHJlc3BvbnNlXG4gIGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuVHJpZ2dlcihcbiAgICB0cmlnZ2Vycy5UeXBlcy5iZWZvcmVMb2dpbixcbiAgICB0aGlzLmF1dGgsXG4gICAgdXNlcixcbiAgICBudWxsLFxuICAgIHRoaXMuY29uZmlnLFxuICAgIHRoaXMuY29udGV4dFxuICApO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5zZXRSZXF1aXJlZEZpZWxkc0lmTmVlZGVkID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmRhdGEpIHtcbiAgICByZXR1cm4gdGhpcy52YWxpZFNjaGVtYUNvbnRyb2xsZXIuZ2V0QWxsQ2xhc3NlcygpLnRoZW4oYWxsQ2xhc3NlcyA9PiB7XG4gICAgICBjb25zdCBzY2hlbWEgPSBhbGxDbGFzc2VzLmZpbmQoXG4gICAgICAgIG9uZUNsYXNzID0+IG9uZUNsYXNzLmNsYXNzTmFtZSA9PT0gdGhpcy5jbGFzc05hbWVcbiAgICAgICk7XG4gICAgICBjb25zdCBzZXRSZXF1aXJlZEZpZWxkSWZOZWVkZWQgPSAoZmllbGROYW1lLCBzZXREZWZhdWx0KSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLmRhdGFbZmllbGROYW1lXSA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgdGhpcy5kYXRhW2ZpZWxkTmFtZV0gPT09IG51bGwgfHxcbiAgICAgICAgICB0aGlzLmRhdGFbZmllbGROYW1lXSA9PT0gJycgfHxcbiAgICAgICAgICAodHlwZW9mIHRoaXMuZGF0YVtmaWVsZE5hbWVdID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgICAgdGhpcy5kYXRhW2ZpZWxkTmFtZV0uX19vcCA9PT0gJ0RlbGV0ZScpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHNldERlZmF1bHQgJiZcbiAgICAgICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLmRlZmF1bHRWYWx1ZSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLmRlZmF1bHRWYWx1ZSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAodGhpcy5kYXRhW2ZpZWxkTmFtZV0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgICAodHlwZW9mIHRoaXMuZGF0YVtmaWVsZE5hbWVdID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgICAgICAgIHRoaXMuZGF0YVtmaWVsZE5hbWVdLl9fb3AgPT09ICdEZWxldGUnKSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YVtmaWVsZE5hbWVdID0gc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLmRlZmF1bHRWYWx1ZTtcbiAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5maWVsZHNDaGFuZ2VkQnlUcmlnZ2VyID1cbiAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLmZpZWxkc0NoYW5nZWRCeVRyaWdnZXIgfHwgW107XG4gICAgICAgICAgICBpZiAodGhpcy5zdG9yYWdlLmZpZWxkc0NoYW5nZWRCeVRyaWdnZXIuaW5kZXhPZihmaWVsZE5hbWUpIDwgMCkge1xuICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UuZmllbGRzQ2hhbmdlZEJ5VHJpZ2dlci5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnJlcXVpcmVkID09PSB0cnVlXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsXG4gICAgICAgICAgICAgIGAke2ZpZWxkTmFtZX0gaXMgcmVxdWlyZWRgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgLy8gQWRkIGRlZmF1bHQgZmllbGRzXG4gICAgICB0aGlzLmRhdGEudXBkYXRlZEF0ID0gdGhpcy51cGRhdGVkQXQ7XG4gICAgICBpZiAoIXRoaXMucXVlcnkpIHtcbiAgICAgICAgdGhpcy5kYXRhLmNyZWF0ZWRBdCA9IHRoaXMudXBkYXRlZEF0O1xuXG4gICAgICAgIC8vIE9ubHkgYXNzaWduIG5ldyBvYmplY3RJZCBpZiB3ZSBhcmUgY3JlYXRpbmcgbmV3IG9iamVjdFxuICAgICAgICBpZiAoIXRoaXMuZGF0YS5vYmplY3RJZCkge1xuICAgICAgICAgIHRoaXMuZGF0YS5vYmplY3RJZCA9IGNyeXB0b1V0aWxzLm5ld09iamVjdElkKFxuICAgICAgICAgICAgdGhpcy5jb25maWcub2JqZWN0SWRTaXplXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2NoZW1hKSB7XG4gICAgICAgICAgT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcykuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgc2V0UmVxdWlyZWRGaWVsZElmTmVlZGVkKGZpZWxkTmFtZSwgdHJ1ZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc2NoZW1hKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKHRoaXMuZGF0YSkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgIHNldFJlcXVpcmVkRmllbGRJZk5lZWRlZChmaWVsZE5hbWUsIGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufTtcblxuLy8gVHJhbnNmb3JtcyBhdXRoIGRhdGEgZm9yIGEgdXNlciBvYmplY3QuXG4vLyBEb2VzIG5vdGhpbmcgaWYgdGhpcyBpc24ndCBhIHVzZXIgb2JqZWN0LlxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIHdoZW4gd2UncmUgZG9uZSBpZiBpdCBjYW4ndCBmaW5pc2ggdGhpcyB0aWNrLlxuUmVzdFdyaXRlLnByb3RvdHlwZS52YWxpZGF0ZUF1dGhEYXRhID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmNsYXNzTmFtZSAhPT0gJ19Vc2VyJykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghdGhpcy5xdWVyeSAmJiAhdGhpcy5kYXRhLmF1dGhEYXRhKSB7XG4gICAgaWYgKFxuICAgICAgdHlwZW9mIHRoaXMuZGF0YS51c2VybmFtZSAhPT0gJ3N0cmluZycgfHxcbiAgICAgIF8uaXNFbXB0eSh0aGlzLmRhdGEudXNlcm5hbWUpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlVTRVJOQU1FX01JU1NJTkcsXG4gICAgICAgICdiYWQgb3IgbWlzc2luZyB1c2VybmFtZSdcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHR5cGVvZiB0aGlzLmRhdGEucGFzc3dvcmQgIT09ICdzdHJpbmcnIHx8XG4gICAgICBfLmlzRW1wdHkodGhpcy5kYXRhLnBhc3N3b3JkKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QQVNTV09SRF9NSVNTSU5HLFxuICAgICAgICAncGFzc3dvcmQgaXMgcmVxdWlyZWQnXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmIChcbiAgICAodGhpcy5kYXRhLmF1dGhEYXRhICYmICFPYmplY3Qua2V5cyh0aGlzLmRhdGEuYXV0aERhdGEpLmxlbmd0aCkgfHxcbiAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMuZGF0YSwgJ2F1dGhEYXRhJylcbiAgKSB7XG4gICAgLy8gSGFuZGxlIHNhdmluZyBhdXRoRGF0YSB0byB7fSBvciBpZiBhdXRoRGF0YSBkb2Vzbid0IGV4aXN0XG4gICAgcmV0dXJuO1xuICB9IGVsc2UgaWYgKFxuICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmRhdGEsICdhdXRoRGF0YScpICYmXG4gICAgIXRoaXMuZGF0YS5hdXRoRGF0YVxuICApIHtcbiAgICAvLyBIYW5kbGUgc2F2aW5nIGF1dGhEYXRhIHRvIG51bGxcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5VTlNVUFBPUlRFRF9TRVJWSUNFLFxuICAgICAgJ1RoaXMgYXV0aGVudGljYXRpb24gbWV0aG9kIGlzIHVuc3VwcG9ydGVkLidcbiAgICApO1xuICB9XG5cbiAgdmFyIGF1dGhEYXRhID0gdGhpcy5kYXRhLmF1dGhEYXRhO1xuICB2YXIgcHJvdmlkZXJzID0gT2JqZWN0LmtleXMoYXV0aERhdGEpO1xuICBpZiAocHJvdmlkZXJzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBjYW5IYW5kbGVBdXRoRGF0YSA9IHByb3ZpZGVycy5yZWR1Y2UoKGNhbkhhbmRsZSwgcHJvdmlkZXIpID0+IHtcbiAgICAgIHZhciBwcm92aWRlckF1dGhEYXRhID0gYXV0aERhdGFbcHJvdmlkZXJdO1xuICAgICAgdmFyIGhhc1Rva2VuID0gcHJvdmlkZXJBdXRoRGF0YSAmJiBwcm92aWRlckF1dGhEYXRhLmlkO1xuICAgICAgcmV0dXJuIGNhbkhhbmRsZSAmJiAoaGFzVG9rZW4gfHwgcHJvdmlkZXJBdXRoRGF0YSA9PSBudWxsKTtcbiAgICB9LCB0cnVlKTtcbiAgICBpZiAoY2FuSGFuZGxlQXV0aERhdGEpIHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUF1dGhEYXRhKGF1dGhEYXRhKTtcbiAgICB9XG4gIH1cbiAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgIFBhcnNlLkVycm9yLlVOU1VQUE9SVEVEX1NFUlZJQ0UsXG4gICAgJ1RoaXMgYXV0aGVudGljYXRpb24gbWV0aG9kIGlzIHVuc3VwcG9ydGVkLidcbiAgKTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuaGFuZGxlQXV0aERhdGFWYWxpZGF0aW9uID0gZnVuY3Rpb24oYXV0aERhdGEpIHtcbiAgY29uc3QgdmFsaWRhdGlvbnMgPSBPYmplY3Qua2V5cyhhdXRoRGF0YSkubWFwKHByb3ZpZGVyID0+IHtcbiAgICBpZiAoYXV0aERhdGFbcHJvdmlkZXJdID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIGNvbnN0IHZhbGlkYXRlQXV0aERhdGEgPSB0aGlzLmNvbmZpZy5hdXRoRGF0YU1hbmFnZXIuZ2V0VmFsaWRhdG9yRm9yUHJvdmlkZXIoXG4gICAgICBwcm92aWRlclxuICAgICk7XG4gICAgaWYgKCF2YWxpZGF0ZUF1dGhEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlVOU1VQUE9SVEVEX1NFUlZJQ0UsXG4gICAgICAgICdUaGlzIGF1dGhlbnRpY2F0aW9uIG1ldGhvZCBpcyB1bnN1cHBvcnRlZC4nXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YVtwcm92aWRlcl0pO1xuICB9KTtcbiAgcmV0dXJuIFByb21pc2UuYWxsKHZhbGlkYXRpb25zKTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuZmluZFVzZXJzV2l0aEF1dGhEYXRhID0gZnVuY3Rpb24oYXV0aERhdGEpIHtcbiAgY29uc3QgcHJvdmlkZXJzID0gT2JqZWN0LmtleXMoYXV0aERhdGEpO1xuICBjb25zdCBxdWVyeSA9IHByb3ZpZGVyc1xuICAgIC5yZWR1Y2UoKG1lbW8sIHByb3ZpZGVyKSA9PiB7XG4gICAgICBpZiAoIWF1dGhEYXRhW3Byb3ZpZGVyXSkge1xuICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgIH1cbiAgICAgIGNvbnN0IHF1ZXJ5S2V5ID0gYGF1dGhEYXRhLiR7cHJvdmlkZXJ9LmlkYDtcbiAgICAgIGNvbnN0IHF1ZXJ5ID0ge307XG4gICAgICBxdWVyeVtxdWVyeUtleV0gPSBhdXRoRGF0YVtwcm92aWRlcl0uaWQ7XG4gICAgICBtZW1vLnB1c2gocXVlcnkpO1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfSwgW10pXG4gICAgLmZpbHRlcihxID0+IHtcbiAgICAgIHJldHVybiB0eXBlb2YgcSAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgfSk7XG5cbiAgbGV0IGZpbmRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKFtdKTtcbiAgaWYgKHF1ZXJ5Lmxlbmd0aCA+IDApIHtcbiAgICBmaW5kUHJvbWlzZSA9IHRoaXMuY29uZmlnLmRhdGFiYXNlLmZpbmQodGhpcy5jbGFzc05hbWUsIHsgJG9yOiBxdWVyeSB9LCB7fSk7XG4gIH1cblxuICByZXR1cm4gZmluZFByb21pc2U7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLmZpbHRlcmVkT2JqZWN0c0J5QUNMID0gZnVuY3Rpb24ob2JqZWN0cykge1xuICBpZiAodGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgcmV0dXJuIG9iamVjdHM7XG4gIH1cbiAgcmV0dXJuIG9iamVjdHMuZmlsdGVyKG9iamVjdCA9PiB7XG4gICAgaWYgKCFvYmplY3QuQUNMKSB7XG4gICAgICByZXR1cm4gdHJ1ZTsgLy8gbGVnYWN5IHVzZXJzIHRoYXQgaGF2ZSBubyBBQ0wgZmllbGQgb24gdGhlbVxuICAgIH1cbiAgICAvLyBSZWd1bGFyIHVzZXJzIHRoYXQgaGF2ZSBiZWVuIGxvY2tlZCBvdXQuXG4gICAgcmV0dXJuIG9iamVjdC5BQ0wgJiYgT2JqZWN0LmtleXMob2JqZWN0LkFDTCkubGVuZ3RoID4gMDtcbiAgfSk7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLmhhbmRsZUF1dGhEYXRhID0gZnVuY3Rpb24oYXV0aERhdGEpIHtcbiAgbGV0IHJlc3VsdHM7XG4gIHJldHVybiB0aGlzLmZpbmRVc2Vyc1dpdGhBdXRoRGF0YShhdXRoRGF0YSkudGhlbihhc3luYyByID0+IHtcbiAgICByZXN1bHRzID0gdGhpcy5maWx0ZXJlZE9iamVjdHNCeUFDTChyKTtcblxuICAgIGlmIChyZXN1bHRzLmxlbmd0aCA9PSAxKSB7XG4gICAgICB0aGlzLnN0b3JhZ2VbJ2F1dGhQcm92aWRlciddID0gT2JqZWN0LmtleXMoYXV0aERhdGEpLmpvaW4oJywnKTtcblxuICAgICAgY29uc3QgdXNlclJlc3VsdCA9IHJlc3VsdHNbMF07XG4gICAgICBjb25zdCBtdXRhdGVkQXV0aERhdGEgPSB7fTtcbiAgICAgIE9iamVjdC5rZXlzKGF1dGhEYXRhKS5mb3JFYWNoKHByb3ZpZGVyID0+IHtcbiAgICAgICAgY29uc3QgcHJvdmlkZXJEYXRhID0gYXV0aERhdGFbcHJvdmlkZXJdO1xuICAgICAgICBjb25zdCB1c2VyQXV0aERhdGEgPSB1c2VyUmVzdWx0LmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgICAgaWYgKCFfLmlzRXF1YWwocHJvdmlkZXJEYXRhLCB1c2VyQXV0aERhdGEpKSB7XG4gICAgICAgICAgbXV0YXRlZEF1dGhEYXRhW3Byb3ZpZGVyXSA9IHByb3ZpZGVyRGF0YTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBjb25zdCBoYXNNdXRhdGVkQXV0aERhdGEgPSBPYmplY3Qua2V5cyhtdXRhdGVkQXV0aERhdGEpLmxlbmd0aCAhPT0gMDtcbiAgICAgIGxldCB1c2VySWQ7XG4gICAgICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgICAgIHVzZXJJZCA9IHRoaXMucXVlcnkub2JqZWN0SWQ7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuYXV0aCAmJiB0aGlzLmF1dGgudXNlciAmJiB0aGlzLmF1dGgudXNlci5pZCkge1xuICAgICAgICB1c2VySWQgPSB0aGlzLmF1dGgudXNlci5pZDtcbiAgICAgIH1cbiAgICAgIGlmICghdXNlcklkIHx8IHVzZXJJZCA9PT0gdXNlclJlc3VsdC5vYmplY3RJZCkge1xuICAgICAgICAvLyBubyB1c2VyIG1ha2luZyB0aGUgY2FsbFxuICAgICAgICAvLyBPUiB0aGUgdXNlciBtYWtpbmcgdGhlIGNhbGwgaXMgdGhlIHJpZ2h0IG9uZVxuICAgICAgICAvLyBMb2dpbiB3aXRoIGF1dGggZGF0YVxuICAgICAgICBkZWxldGUgcmVzdWx0c1swXS5wYXNzd29yZDtcblxuICAgICAgICAvLyBuZWVkIHRvIHNldCB0aGUgb2JqZWN0SWQgZmlyc3Qgb3RoZXJ3aXNlIGxvY2F0aW9uIGhhcyB0cmFpbGluZyB1bmRlZmluZWRcbiAgICAgICAgdGhpcy5kYXRhLm9iamVjdElkID0gdXNlclJlc3VsdC5vYmplY3RJZDtcblxuICAgICAgICBpZiAoIXRoaXMucXVlcnkgfHwgIXRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICAgICAgICAvLyB0aGlzIGEgbG9naW4gY2FsbCwgbm8gdXNlcklkIHBhc3NlZFxuICAgICAgICAgIHRoaXMucmVzcG9uc2UgPSB7XG4gICAgICAgICAgICByZXNwb25zZTogdXNlclJlc3VsdCxcbiAgICAgICAgICAgIGxvY2F0aW9uOiB0aGlzLmxvY2F0aW9uKCksXG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyBSdW4gYmVmb3JlTG9naW4gaG9vayBiZWZvcmUgc3RvcmluZyBhbnkgdXBkYXRlc1xuICAgICAgICAgIC8vIHRvIGF1dGhEYXRhIG9uIHRoZSBkYjsgY2hhbmdlcyB0byB1c2VyUmVzdWx0XG4gICAgICAgICAgLy8gd2lsbCBiZSBpZ25vcmVkLlxuICAgICAgICAgIGF3YWl0IHRoaXMucnVuQmVmb3JlTG9naW5UcmlnZ2VyKGRlZXBjb3B5KHVzZXJSZXN1bHQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHdlIGRpZG4ndCBjaGFuZ2UgdGhlIGF1dGggZGF0YSwganVzdCBrZWVwIGdvaW5nXG4gICAgICAgIGlmICghaGFzTXV0YXRlZEF1dGhEYXRhKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIGhhdmUgYXV0aERhdGEgdGhhdCBpcyB1cGRhdGVkIG9uIGxvZ2luXG4gICAgICAgIC8vIHRoYXQgY2FuIGhhcHBlbiB3aGVuIHRva2VuIGFyZSByZWZyZXNoZWQsXG4gICAgICAgIC8vIFdlIHNob3VsZCB1cGRhdGUgdGhlIHRva2VuIGFuZCBsZXQgdGhlIHVzZXIgaW5cbiAgICAgICAgLy8gV2Ugc2hvdWxkIG9ubHkgY2hlY2sgdGhlIG11dGF0ZWQga2V5c1xuICAgICAgICByZXR1cm4gdGhpcy5oYW5kbGVBdXRoRGF0YVZhbGlkYXRpb24obXV0YXRlZEF1dGhEYXRhKS50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAvLyBJRiB3ZSBoYXZlIGEgcmVzcG9uc2UsIHdlJ2xsIHNraXAgdGhlIGRhdGFiYXNlIG9wZXJhdGlvbiAvIGJlZm9yZVNhdmUgLyBhZnRlclNhdmUgZXRjLi4uXG4gICAgICAgICAgLy8gd2UgbmVlZCB0byBzZXQgaXQgdXAgdGhlcmUuXG4gICAgICAgICAgLy8gV2UgYXJlIHN1cHBvc2VkIHRvIGhhdmUgYSByZXNwb25zZSBvbmx5IG9uIExPR0lOIHdpdGggYXV0aERhdGEsIHNvIHdlIHNraXAgdGhvc2VcbiAgICAgICAgICAvLyBJZiB3ZSdyZSBub3QgbG9nZ2luZyBpbiwgYnV0IGp1c3QgdXBkYXRpbmcgdGhlIGN1cnJlbnQgdXNlciwgd2UgY2FuIHNhZmVseSBza2lwIHRoYXQgcGFydFxuICAgICAgICAgIGlmICh0aGlzLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICAvLyBBc3NpZ24gdGhlIG5ldyBhdXRoRGF0YSBpbiB0aGUgcmVzcG9uc2VcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKG11dGF0ZWRBdXRoRGF0YSkuZm9yRWFjaChwcm92aWRlciA9PiB7XG4gICAgICAgICAgICAgIHRoaXMucmVzcG9uc2UucmVzcG9uc2UuYXV0aERhdGFbcHJvdmlkZXJdID1cbiAgICAgICAgICAgICAgICBtdXRhdGVkQXV0aERhdGFbcHJvdmlkZXJdO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFJ1biB0aGUgREIgdXBkYXRlIGRpcmVjdGx5LCBhcyAnbWFzdGVyJ1xuICAgICAgICAgICAgLy8gSnVzdCB1cGRhdGUgdGhlIGF1dGhEYXRhIHBhcnRcbiAgICAgICAgICAgIC8vIFRoZW4gd2UncmUgZ29vZCBmb3IgdGhlIHVzZXIsIGVhcmx5IGV4aXQgb2Ygc29ydHNcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS51cGRhdGUoXG4gICAgICAgICAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgICAgICAgICB7IG9iamVjdElkOiB0aGlzLmRhdGEub2JqZWN0SWQgfSxcbiAgICAgICAgICAgICAgeyBhdXRoRGF0YTogbXV0YXRlZEF1dGhEYXRhIH0sXG4gICAgICAgICAgICAgIHt9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKHVzZXJJZCkge1xuICAgICAgICAvLyBUcnlpbmcgdG8gdXBkYXRlIGF1dGggZGF0YSBidXQgdXNlcnNcbiAgICAgICAgLy8gYXJlIGRpZmZlcmVudFxuICAgICAgICBpZiAodXNlclJlc3VsdC5vYmplY3RJZCAhPT0gdXNlcklkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuQUNDT1VOVF9BTFJFQURZX0xJTktFRCxcbiAgICAgICAgICAgICd0aGlzIGF1dGggaXMgYWxyZWFkeSB1c2VkJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm8gYXV0aCBkYXRhIHdhcyBtdXRhdGVkLCBqdXN0IGtlZXAgZ29pbmdcbiAgICAgICAgaWYgKCFoYXNNdXRhdGVkQXV0aERhdGEpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlQXV0aERhdGFWYWxpZGF0aW9uKGF1dGhEYXRhKS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgLy8gTW9yZSB0aGFuIDEgdXNlciB3aXRoIHRoZSBwYXNzZWQgaWQnc1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuQUNDT1VOVF9BTFJFQURZX0xJTktFRCxcbiAgICAgICAgICAndGhpcyBhdXRoIGlzIGFscmVhZHkgdXNlZCdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59O1xuXG4vLyBUaGUgbm9uLXRoaXJkLXBhcnR5IHBhcnRzIG9mIFVzZXIgdHJhbnNmb3JtYXRpb25cblJlc3RXcml0ZS5wcm90b3R5cGUudHJhbnNmb3JtVXNlciA9IGZ1bmN0aW9uKCkge1xuICB2YXIgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gIGlmICh0aGlzLmNsYXNzTmFtZSAhPT0gJ19Vc2VyJykge1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgaWYgKCF0aGlzLmF1dGguaXNNYXN0ZXIgJiYgJ2VtYWlsVmVyaWZpZWQnIGluIHRoaXMuZGF0YSkge1xuICAgIGNvbnN0IGVycm9yID0gYENsaWVudHMgYXJlbid0IGFsbG93ZWQgdG8gbWFudWFsbHkgdXBkYXRlIGVtYWlsIHZlcmlmaWNhdGlvbi5gO1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCBlcnJvcik7XG4gIH1cblxuICAvLyBEbyBub3QgY2xlYW51cCBzZXNzaW9uIGlmIG9iamVjdElkIGlzIG5vdCBzZXRcbiAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5vYmplY3RJZCgpKSB7XG4gICAgLy8gSWYgd2UncmUgdXBkYXRpbmcgYSBfVXNlciBvYmplY3QsIHdlIG5lZWQgdG8gY2xlYXIgb3V0IHRoZSBjYWNoZSBmb3IgdGhhdCB1c2VyLiBGaW5kIGFsbCB0aGVpclxuICAgIC8vIHNlc3Npb24gdG9rZW5zLCBhbmQgcmVtb3ZlIHRoZW0gZnJvbSB0aGUgY2FjaGUuXG4gICAgcHJvbWlzZSA9IG5ldyBSZXN0UXVlcnkodGhpcy5jb25maWcsIEF1dGgubWFzdGVyKHRoaXMuY29uZmlnKSwgJ19TZXNzaW9uJywge1xuICAgICAgdXNlcjoge1xuICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgY2xhc3NOYW1lOiAnX1VzZXInLFxuICAgICAgICBvYmplY3RJZDogdGhpcy5vYmplY3RJZCgpLFxuICAgICAgfSxcbiAgICB9KVxuICAgICAgLmV4ZWN1dGUoKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHJlc3VsdHMucmVzdWx0cy5mb3JFYWNoKHNlc3Npb24gPT5cbiAgICAgICAgICB0aGlzLmNvbmZpZy5jYWNoZUNvbnRyb2xsZXIudXNlci5kZWwoc2Vzc2lvbi5zZXNzaW9uVG9rZW4pXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBwcm9taXNlXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gVHJhbnNmb3JtIHRoZSBwYXNzd29yZFxuICAgICAgaWYgKHRoaXMuZGF0YS5wYXNzd29yZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIGlnbm9yZSBvbmx5IGlmIHVuZGVmaW5lZC4gc2hvdWxkIHByb2NlZWQgaWYgZW1wdHkgKCcnKVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnF1ZXJ5KSB7XG4gICAgICAgIHRoaXMuc3RvcmFnZVsnY2xlYXJTZXNzaW9ucyddID0gdHJ1ZTtcbiAgICAgICAgLy8gR2VuZXJhdGUgYSBuZXcgc2Vzc2lvbiBvbmx5IGlmIHRoZSB1c2VyIHJlcXVlc3RlZFxuICAgICAgICBpZiAoIXRoaXMuYXV0aC5pc01hc3Rlcikge1xuICAgICAgICAgIHRoaXMuc3RvcmFnZVsnZ2VuZXJhdGVOZXdTZXNzaW9uJ10gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl92YWxpZGF0ZVBhc3N3b3JkUG9saWN5KCkudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiBwYXNzd29yZENyeXB0by5oYXNoKHRoaXMuZGF0YS5wYXNzd29yZCkudGhlbihoYXNoZWRQYXNzd29yZCA9PiB7XG4gICAgICAgICAgdGhpcy5kYXRhLl9oYXNoZWRfcGFzc3dvcmQgPSBoYXNoZWRQYXNzd29yZDtcbiAgICAgICAgICBkZWxldGUgdGhpcy5kYXRhLnBhc3N3b3JkO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuX3ZhbGlkYXRlVXNlck5hbWUoKTtcbiAgICB9KVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLl92YWxpZGF0ZUVtYWlsKCk7XG4gICAgfSk7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLl92YWxpZGF0ZVVzZXJOYW1lID0gZnVuY3Rpb24oKSB7XG4gIC8vIENoZWNrIGZvciB1c2VybmFtZSB1bmlxdWVuZXNzXG4gIGlmICghdGhpcy5kYXRhLnVzZXJuYW1lKSB7XG4gICAgaWYgKCF0aGlzLnF1ZXJ5KSB7XG4gICAgICB0aGlzLmRhdGEudXNlcm5hbWUgPSBjcnlwdG9VdGlscy5yYW5kb21TdHJpbmcoMjUpO1xuICAgICAgdGhpcy5yZXNwb25zZVNob3VsZEhhdmVVc2VybmFtZSA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICAvKlxuICAgIFVzZXJuYW1lcyBzaG91bGQgYmUgdW5pcXVlIHdoZW4gY29tcGFyZWQgY2FzZSBpbnNlbnNpdGl2ZWx5XG5cbiAgICBVc2VycyBzaG91bGQgYmUgYWJsZSB0byBtYWtlIGNhc2Ugc2Vuc2l0aXZlIHVzZXJuYW1lcyBhbmRcbiAgICBsb2dpbiB1c2luZyB0aGUgY2FzZSB0aGV5IGVudGVyZWQuICBJLmUuICdTbm9vcHknIHNob3VsZCBwcmVjbHVkZVxuICAgICdzbm9vcHknIGFzIGEgdmFsaWQgdXNlcm5hbWUuXG4gICovXG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgIC5maW5kKFxuICAgICAgdGhpcy5jbGFzc05hbWUsXG4gICAgICB7XG4gICAgICAgIHVzZXJuYW1lOiB0aGlzLmRhdGEudXNlcm5hbWUsXG4gICAgICAgIG9iamVjdElkOiB7ICRuZTogdGhpcy5vYmplY3RJZCgpIH0sXG4gICAgICB9LFxuICAgICAgeyBsaW1pdDogMSwgY2FzZUluc2Vuc2l0aXZlOiB0cnVlIH0sXG4gICAgICB7fSxcbiAgICAgIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyXG4gICAgKVxuICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuVVNFUk5BTUVfVEFLRU4sXG4gICAgICAgICAgJ0FjY291bnQgYWxyZWFkeSBleGlzdHMgZm9yIHRoaXMgdXNlcm5hbWUuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH0pO1xufTtcblxuLypcbiAgQXMgd2l0aCB1c2VybmFtZXMsIFBhcnNlIHNob3VsZCBub3QgYWxsb3cgY2FzZSBpbnNlbnNpdGl2ZSBjb2xsaXNpb25zIG9mIGVtYWlsLlxuICB1bmxpa2Ugd2l0aCB1c2VybmFtZXMgKHdoaWNoIGNhbiBoYXZlIGNhc2UgaW5zZW5zaXRpdmUgY29sbGlzaW9ucyBpbiB0aGUgY2FzZSBvZlxuICBhdXRoIGFkYXB0ZXJzKSwgZW1haWxzIHNob3VsZCBuZXZlciBoYXZlIGEgY2FzZSBpbnNlbnNpdGl2ZSBjb2xsaXNpb24uXG5cbiAgVGhpcyBiZWhhdmlvciBjYW4gYmUgZW5mb3JjZWQgdGhyb3VnaCBhIHByb3Blcmx5IGNvbmZpZ3VyZWQgaW5kZXggc2VlOlxuICBodHRwczovL2RvY3MubW9uZ29kYi5jb20vbWFudWFsL2NvcmUvaW5kZXgtY2FzZS1pbnNlbnNpdGl2ZS8jY3JlYXRlLWEtY2FzZS1pbnNlbnNpdGl2ZS1pbmRleFxuICB3aGljaCBjb3VsZCBiZSBpbXBsZW1lbnRlZCBpbnN0ZWFkIG9mIHRoaXMgY29kZSBiYXNlZCB2YWxpZGF0aW9uLlxuXG4gIEdpdmVuIHRoYXQgdGhpcyBsb29rdXAgc2hvdWxkIGJlIGEgcmVsYXRpdmVseSBsb3cgdXNlIGNhc2UgYW5kIHRoYXQgdGhlIGNhc2Ugc2Vuc2l0aXZlXG4gIHVuaXF1ZSBpbmRleCB3aWxsIGJlIHVzZWQgYnkgdGhlIGRiIGZvciB0aGUgcXVlcnksIHRoaXMgaXMgYW4gYWRlcXVhdGUgc29sdXRpb24uXG4qL1xuUmVzdFdyaXRlLnByb3RvdHlwZS5fdmFsaWRhdGVFbWFpbCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuZGF0YS5lbWFpbCB8fCB0aGlzLmRhdGEuZW1haWwuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gVmFsaWRhdGUgYmFzaWMgZW1haWwgYWRkcmVzcyBmb3JtYXRcbiAgaWYgKCF0aGlzLmRhdGEuZW1haWwubWF0Y2goL14uK0AuKyQvKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9FTUFJTF9BRERSRVNTLFxuICAgICAgICAnRW1haWwgYWRkcmVzcyBmb3JtYXQgaXMgaW52YWxpZC4nXG4gICAgICApXG4gICAgKTtcbiAgfVxuICAvLyBDYXNlIGluc2Vuc2l0aXZlIG1hdGNoLCBzZWUgbm90ZSBhYm92ZSBmdW5jdGlvbi5cbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgLmZpbmQoXG4gICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgIHtcbiAgICAgICAgZW1haWw6IHRoaXMuZGF0YS5lbWFpbCxcbiAgICAgICAgb2JqZWN0SWQ6IHsgJG5lOiB0aGlzLm9iamVjdElkKCkgfSxcbiAgICAgIH0sXG4gICAgICB7IGxpbWl0OiAxLCBjYXNlSW5zZW5zaXRpdmU6IHRydWUgfSxcbiAgICAgIHt9LFxuICAgICAgdGhpcy52YWxpZFNjaGVtYUNvbnRyb2xsZXJcbiAgICApXG4gICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5FTUFJTF9UQUtFTixcbiAgICAgICAgICAnQWNjb3VudCBhbHJlYWR5IGV4aXN0cyBmb3IgdGhpcyBlbWFpbCBhZGRyZXNzLidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgIXRoaXMuZGF0YS5hdXRoRGF0YSB8fFxuICAgICAgICAhT2JqZWN0LmtleXModGhpcy5kYXRhLmF1dGhEYXRhKS5sZW5ndGggfHxcbiAgICAgICAgKE9iamVjdC5rZXlzKHRoaXMuZGF0YS5hdXRoRGF0YSkubGVuZ3RoID09PSAxICYmXG4gICAgICAgICAgT2JqZWN0LmtleXModGhpcy5kYXRhLmF1dGhEYXRhKVswXSA9PT0gJ2Fub255bW91cycpXG4gICAgICApIHtcbiAgICAgICAgLy8gV2UgdXBkYXRlZCB0aGUgZW1haWwsIHNlbmQgYSBuZXcgdmFsaWRhdGlvblxuICAgICAgICB0aGlzLnN0b3JhZ2VbJ3NlbmRWZXJpZmljYXRpb25FbWFpbCddID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5jb25maWcudXNlckNvbnRyb2xsZXIuc2V0RW1haWxWZXJpZnlUb2tlbih0aGlzLmRhdGEpO1xuICAgICAgfVxuICAgIH0pO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5fdmFsaWRhdGVQYXNzd29yZFBvbGljeSA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5KSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIHJldHVybiB0aGlzLl92YWxpZGF0ZVBhc3N3b3JkUmVxdWlyZW1lbnRzKCkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbGlkYXRlUGFzc3dvcmRIaXN0b3J5KCk7XG4gIH0pO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5fdmFsaWRhdGVQYXNzd29yZFJlcXVpcmVtZW50cyA9IGZ1bmN0aW9uKCkge1xuICAvLyBjaGVjayBpZiB0aGUgcGFzc3dvcmQgY29uZm9ybXMgdG8gdGhlIGRlZmluZWQgcGFzc3dvcmQgcG9saWN5IGlmIGNvbmZpZ3VyZWRcbiAgLy8gSWYgd2Ugc3BlY2lmaWVkIGEgY3VzdG9tIGVycm9yIGluIG91ciBjb25maWd1cmF0aW9uIHVzZSBpdC5cbiAgLy8gRXhhbXBsZTogXCJQYXNzd29yZHMgbXVzdCBpbmNsdWRlIGEgQ2FwaXRhbCBMZXR0ZXIsIExvd2VyY2FzZSBMZXR0ZXIsIGFuZCBhIG51bWJlci5cIlxuICAvL1xuICAvLyBUaGlzIGlzIGVzcGVjaWFsbHkgdXNlZnVsIG9uIHRoZSBnZW5lcmljIFwicGFzc3dvcmQgcmVzZXRcIiBwYWdlLFxuICAvLyBhcyBpdCBhbGxvd3MgdGhlIHByb2dyYW1tZXIgdG8gY29tbXVuaWNhdGUgc3BlY2lmaWMgcmVxdWlyZW1lbnRzIGluc3RlYWQgb2Y6XG4gIC8vIGEuIG1ha2luZyB0aGUgdXNlciBndWVzcyB3aGF0cyB3cm9uZ1xuICAvLyBiLiBtYWtpbmcgYSBjdXN0b20gcGFzc3dvcmQgcmVzZXQgcGFnZSB0aGF0IHNob3dzIHRoZSByZXF1aXJlbWVudHNcbiAgY29uc3QgcG9saWN5RXJyb3IgPSB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS52YWxpZGF0aW9uRXJyb3JcbiAgICA/IHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5LnZhbGlkYXRpb25FcnJvclxuICAgIDogJ1Bhc3N3b3JkIGRvZXMgbm90IG1lZXQgdGhlIFBhc3N3b3JkIFBvbGljeSByZXF1aXJlbWVudHMuJztcbiAgY29uc3QgY29udGFpbnNVc2VybmFtZUVycm9yID0gJ1Bhc3N3b3JkIGNhbm5vdCBjb250YWluIHlvdXIgdXNlcm5hbWUuJztcblxuICAvLyBjaGVjayB3aGV0aGVyIHRoZSBwYXNzd29yZCBtZWV0cyB0aGUgcGFzc3dvcmQgc3RyZW5ndGggcmVxdWlyZW1lbnRzXG4gIGlmIChcbiAgICAodGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kucGF0dGVyblZhbGlkYXRvciAmJlxuICAgICAgIXRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5LnBhdHRlcm5WYWxpZGF0b3IodGhpcy5kYXRhLnBhc3N3b3JkKSkgfHxcbiAgICAodGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yQ2FsbGJhY2sgJiZcbiAgICAgICF0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS52YWxpZGF0b3JDYWxsYmFjayh0aGlzLmRhdGEucGFzc3dvcmQpKVxuICApIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVkFMSURBVElPTl9FUlJPUiwgcG9saWN5RXJyb3IpXG4gICAgKTtcbiAgfVxuXG4gIC8vIGNoZWNrIHdoZXRoZXIgcGFzc3dvcmQgY29udGFpbiB1c2VybmFtZVxuICBpZiAodGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kuZG9Ob3RBbGxvd1VzZXJuYW1lID09PSB0cnVlKSB7XG4gICAgaWYgKHRoaXMuZGF0YS51c2VybmFtZSkge1xuICAgICAgLy8gdXNlcm5hbWUgaXMgbm90IHBhc3NlZCBkdXJpbmcgcGFzc3dvcmQgcmVzZXRcbiAgICAgIGlmICh0aGlzLmRhdGEucGFzc3dvcmQuaW5kZXhPZih0aGlzLmRhdGEudXNlcm5hbWUpID49IDApXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVkFMSURBVElPTl9FUlJPUiwgY29udGFpbnNVc2VybmFtZUVycm9yKVxuICAgICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyByZXRyaWV2ZSB0aGUgVXNlciBvYmplY3QgdXNpbmcgb2JqZWN0SWQgZHVyaW5nIHBhc3N3b3JkIHJlc2V0XG4gICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgICAgLmZpbmQoJ19Vc2VyJywgeyBvYmplY3RJZDogdGhpcy5vYmplY3RJZCgpIH0pXG4gICAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgICAgICB0aHJvdyB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0aGlzLmRhdGEucGFzc3dvcmQuaW5kZXhPZihyZXN1bHRzWzBdLnVzZXJuYW1lKSA+PSAwKVxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuVkFMSURBVElPTl9FUlJPUixcbiAgICAgICAgICAgICAgICBjb250YWluc1VzZXJuYW1lRXJyb3JcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLl92YWxpZGF0ZVBhc3N3b3JkSGlzdG9yeSA9IGZ1bmN0aW9uKCkge1xuICAvLyBjaGVjayB3aGV0aGVyIHBhc3N3b3JkIGlzIHJlcGVhdGluZyBmcm9tIHNwZWNpZmllZCBoaXN0b3J5XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeSkge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgLmZpbmQoXG4gICAgICAgICdfVXNlcicsXG4gICAgICAgIHsgb2JqZWN0SWQ6IHRoaXMub2JqZWN0SWQoKSB9LFxuICAgICAgICB7IGtleXM6IFsnX3Bhc3N3b3JkX2hpc3RvcnknLCAnX2hhc2hlZF9wYXNzd29yZCddIH1cbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggIT0gMSkge1xuICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1c2VyID0gcmVzdWx0c1swXTtcbiAgICAgICAgbGV0IG9sZFBhc3N3b3JkcyA9IFtdO1xuICAgICAgICBpZiAodXNlci5fcGFzc3dvcmRfaGlzdG9yeSlcbiAgICAgICAgICBvbGRQYXNzd29yZHMgPSBfLnRha2UoXG4gICAgICAgICAgICB1c2VyLl9wYXNzd29yZF9oaXN0b3J5LFxuICAgICAgICAgICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5IC0gMVxuICAgICAgICAgICk7XG4gICAgICAgIG9sZFBhc3N3b3Jkcy5wdXNoKHVzZXIucGFzc3dvcmQpO1xuICAgICAgICBjb25zdCBuZXdQYXNzd29yZCA9IHRoaXMuZGF0YS5wYXNzd29yZDtcbiAgICAgICAgLy8gY29tcGFyZSB0aGUgbmV3IHBhc3N3b3JkIGhhc2ggd2l0aCBhbGwgb2xkIHBhc3N3b3JkIGhhc2hlc1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IG9sZFBhc3N3b3Jkcy5tYXAoZnVuY3Rpb24oaGFzaCkge1xuICAgICAgICAgIHJldHVybiBwYXNzd29yZENyeXB0by5jb21wYXJlKG5ld1Bhc3N3b3JkLCBoYXNoKS50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgICBpZiAocmVzdWx0KVxuICAgICAgICAgICAgICAvLyByZWplY3QgaWYgdGhlcmUgaXMgYSBtYXRjaFxuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ1JFUEVBVF9QQVNTV09SRCcpO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gd2FpdCBmb3IgYWxsIGNvbXBhcmlzb25zIHRvIGNvbXBsZXRlXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcylcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIgPT09ICdSRVBFQVRfUEFTU1dPUkQnKVxuICAgICAgICAgICAgICAvLyBhIG1hdGNoIHdhcyBmb3VuZFxuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuVkFMSURBVElPTl9FUlJPUixcbiAgICAgICAgICAgICAgICAgIGBOZXcgcGFzc3dvcmQgc2hvdWxkIG5vdCBiZSB0aGUgc2FtZSBhcyBsYXN0ICR7dGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5fSBwYXNzd29yZHMuYFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuY3JlYXRlU2Vzc2lvblRva2VuSWZOZWVkZWQgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuY2xhc3NOYW1lICE9PSAnX1VzZXInKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIERvbid0IGdlbmVyYXRlIHNlc3Npb24gZm9yIHVwZGF0aW5nIHVzZXIgKHRoaXMucXVlcnkgaXMgc2V0KSB1bmxlc3MgYXV0aERhdGEgZXhpc3RzXG4gIGlmICh0aGlzLnF1ZXJ5ICYmICF0aGlzLmRhdGEuYXV0aERhdGEpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gRG9uJ3QgZ2VuZXJhdGUgbmV3IHNlc3Npb25Ub2tlbiBpZiBsaW5raW5nIHZpYSBzZXNzaW9uVG9rZW5cbiAgaWYgKHRoaXMuYXV0aC51c2VyICYmIHRoaXMuZGF0YS5hdXRoRGF0YSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoXG4gICAgIXRoaXMuc3RvcmFnZVsnYXV0aFByb3ZpZGVyJ10gJiYgLy8gc2lnbnVwIGNhbGwsIHdpdGhcbiAgICB0aGlzLmNvbmZpZy5wcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsICYmIC8vIG5vIGxvZ2luIHdpdGhvdXQgdmVyaWZpY2F0aW9uXG4gICAgdGhpcy5jb25maWcudmVyaWZ5VXNlckVtYWlsc1xuICApIHtcbiAgICAvLyB2ZXJpZmljYXRpb24gaXMgb25cbiAgICByZXR1cm47IC8vIGRvIG5vdCBjcmVhdGUgdGhlIHNlc3Npb24gdG9rZW4gaW4gdGhhdCBjYXNlIVxuICB9XG4gIHJldHVybiB0aGlzLmNyZWF0ZVNlc3Npb25Ub2tlbigpO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5jcmVhdGVTZXNzaW9uVG9rZW4gPSBhc3luYyBmdW5jdGlvbigpIHtcbiAgLy8gY2xvdWQgaW5zdGFsbGF0aW9uSWQgZnJvbSBDbG91ZCBDb2RlLFxuICAvLyBuZXZlciBjcmVhdGUgc2Vzc2lvbiB0b2tlbnMgZnJvbSB0aGVyZS5cbiAgaWYgKHRoaXMuYXV0aC5pbnN0YWxsYXRpb25JZCAmJiB0aGlzLmF1dGguaW5zdGFsbGF0aW9uSWQgPT09ICdjbG91ZCcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB7IHNlc3Npb25EYXRhLCBjcmVhdGVTZXNzaW9uIH0gPSBBdXRoLmNyZWF0ZVNlc3Npb24odGhpcy5jb25maWcsIHtcbiAgICB1c2VySWQ6IHRoaXMub2JqZWN0SWQoKSxcbiAgICBjcmVhdGVkV2l0aDoge1xuICAgICAgYWN0aW9uOiB0aGlzLnN0b3JhZ2VbJ2F1dGhQcm92aWRlciddID8gJ2xvZ2luJyA6ICdzaWdudXAnLFxuICAgICAgYXV0aFByb3ZpZGVyOiB0aGlzLnN0b3JhZ2VbJ2F1dGhQcm92aWRlciddIHx8ICdwYXNzd29yZCcsXG4gICAgfSxcbiAgICBpbnN0YWxsYXRpb25JZDogdGhpcy5hdXRoLmluc3RhbGxhdGlvbklkLFxuICB9KTtcblxuICBpZiAodGhpcy5yZXNwb25zZSAmJiB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlKSB7XG4gICAgdGhpcy5yZXNwb25zZS5yZXNwb25zZS5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uRGF0YS5zZXNzaW9uVG9rZW47XG4gIH1cblxuICByZXR1cm4gY3JlYXRlU2Vzc2lvbigpO1xufTtcblxuLy8gRGVsZXRlIGVtYWlsIHJlc2V0IHRva2VucyBpZiB1c2VyIGlzIGNoYW5naW5nIHBhc3N3b3JkIG9yIGVtYWlsLlxuUmVzdFdyaXRlLnByb3RvdHlwZS5kZWxldGVFbWFpbFJlc2V0VG9rZW5JZk5lZWRlZCA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicgfHwgdGhpcy5xdWVyeSA9PT0gbnVsbCkge1xuICAgIC8vIG51bGwgcXVlcnkgbWVhbnMgY3JlYXRlXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCdwYXNzd29yZCcgaW4gdGhpcy5kYXRhIHx8ICdlbWFpbCcgaW4gdGhpcy5kYXRhKSB7XG4gICAgY29uc3QgYWRkT3BzID0ge1xuICAgICAgX3BlcmlzaGFibGVfdG9rZW46IHsgX19vcDogJ0RlbGV0ZScgfSxcbiAgICAgIF9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQ6IHsgX19vcDogJ0RlbGV0ZScgfSxcbiAgICB9O1xuICAgIHRoaXMuZGF0YSA9IE9iamVjdC5hc3NpZ24odGhpcy5kYXRhLCBhZGRPcHMpO1xuICB9XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLmRlc3Ryb3lEdXBsaWNhdGVkU2Vzc2lvbnMgPSBmdW5jdGlvbigpIHtcbiAgLy8gT25seSBmb3IgX1Nlc3Npb24sIGFuZCBhdCBjcmVhdGlvbiB0aW1lXG4gIGlmICh0aGlzLmNsYXNzTmFtZSAhPSAnX1Nlc3Npb24nIHx8IHRoaXMucXVlcnkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gRGVzdHJveSB0aGUgc2Vzc2lvbnMgaW4gJ0JhY2tncm91bmQnXG4gIGNvbnN0IHsgdXNlciwgaW5zdGFsbGF0aW9uSWQsIHNlc3Npb25Ub2tlbiB9ID0gdGhpcy5kYXRhO1xuICBpZiAoIXVzZXIgfHwgIWluc3RhbGxhdGlvbklkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICghdXNlci5vYmplY3RJZCkge1xuICAgIHJldHVybjtcbiAgfVxuICB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kZXN0cm95KFxuICAgICdfU2Vzc2lvbicsXG4gICAge1xuICAgICAgdXNlcixcbiAgICAgIGluc3RhbGxhdGlvbklkLFxuICAgICAgc2Vzc2lvblRva2VuOiB7ICRuZTogc2Vzc2lvblRva2VuIH0sXG4gICAgfSxcbiAgICB7fSxcbiAgICB0aGlzLnZhbGlkU2NoZW1hQ29udHJvbGxlclxuICApO1xufTtcblxuLy8gSGFuZGxlcyBhbnkgZm9sbG93dXAgbG9naWNcblJlc3RXcml0ZS5wcm90b3R5cGUuaGFuZGxlRm9sbG93dXAgPSBmdW5jdGlvbigpIHtcbiAgaWYgKFxuICAgIHRoaXMuc3RvcmFnZSAmJlxuICAgIHRoaXMuc3RvcmFnZVsnY2xlYXJTZXNzaW9ucyddICYmXG4gICAgdGhpcy5jb25maWcucmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldFxuICApIHtcbiAgICB2YXIgc2Vzc2lvblF1ZXJ5ID0ge1xuICAgICAgdXNlcjoge1xuICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgY2xhc3NOYW1lOiAnX1VzZXInLFxuICAgICAgICBvYmplY3RJZDogdGhpcy5vYmplY3RJZCgpLFxuICAgICAgfSxcbiAgICB9O1xuICAgIGRlbGV0ZSB0aGlzLnN0b3JhZ2VbJ2NsZWFyU2Vzc2lvbnMnXTtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgIC5kZXN0cm95KCdfU2Vzc2lvbicsIHNlc3Npb25RdWVyeSlcbiAgICAgIC50aGVuKHRoaXMuaGFuZGxlRm9sbG93dXAuYmluZCh0aGlzKSk7XG4gIH1cblxuICBpZiAodGhpcy5zdG9yYWdlICYmIHRoaXMuc3RvcmFnZVsnZ2VuZXJhdGVOZXdTZXNzaW9uJ10pIHtcbiAgICBkZWxldGUgdGhpcy5zdG9yYWdlWydnZW5lcmF0ZU5ld1Nlc3Npb24nXTtcbiAgICByZXR1cm4gdGhpcy5jcmVhdGVTZXNzaW9uVG9rZW4oKS50aGVuKHRoaXMuaGFuZGxlRm9sbG93dXAuYmluZCh0aGlzKSk7XG4gIH1cblxuICBpZiAodGhpcy5zdG9yYWdlICYmIHRoaXMuc3RvcmFnZVsnc2VuZFZlcmlmaWNhdGlvbkVtYWlsJ10pIHtcbiAgICBkZWxldGUgdGhpcy5zdG9yYWdlWydzZW5kVmVyaWZpY2F0aW9uRW1haWwnXTtcbiAgICAvLyBGaXJlIGFuZCBmb3JnZXQhXG4gICAgdGhpcy5jb25maWcudXNlckNvbnRyb2xsZXIuc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHRoaXMuZGF0YSk7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlRm9sbG93dXAuYmluZCh0aGlzKTtcbiAgfVxufTtcblxuLy8gSGFuZGxlcyB0aGUgX1Nlc3Npb24gY2xhc3Mgc3BlY2lhbG5lc3MuXG4vLyBEb2VzIG5vdGhpbmcgaWYgdGhpcyBpc24ndCBhbiBfU2Vzc2lvbiBvYmplY3QuXG5SZXN0V3JpdGUucHJvdG90eXBlLmhhbmRsZVNlc3Npb24gPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMucmVzcG9uc2UgfHwgdGhpcy5jbGFzc05hbWUgIT09ICdfU2Vzc2lvbicpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIXRoaXMuYXV0aC51c2VyICYmICF0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1NFU1NJT05fVE9LRU4sXG4gICAgICAnU2Vzc2lvbiB0b2tlbiByZXF1aXJlZC4nXG4gICAgKTtcbiAgfVxuXG4gIC8vIFRPRE86IFZlcmlmeSBwcm9wZXIgZXJyb3IgdG8gdGhyb3dcbiAgaWYgKHRoaXMuZGF0YS5BQ0wpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLFxuICAgICAgJ0Nhbm5vdCBzZXQgJyArICdBQ0wgb24gYSBTZXNzaW9uLidcbiAgICApO1xuICB9XG5cbiAgaWYgKHRoaXMucXVlcnkpIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLmRhdGEudXNlciAmJlxuICAgICAgIXRoaXMuYXV0aC5pc01hc3RlciAmJlxuICAgICAgdGhpcy5kYXRhLnVzZXIub2JqZWN0SWQgIT0gdGhpcy5hdXRoLnVzZXIuaWRcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5kYXRhLnNlc3Npb25Ub2tlbikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUpO1xuICAgIH1cbiAgfVxuXG4gIGlmICghdGhpcy5xdWVyeSAmJiAhdGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgY29uc3QgYWRkaXRpb25hbFNlc3Npb25EYXRhID0ge307XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuZGF0YSkge1xuICAgICAgaWYgKGtleSA9PT0gJ29iamVjdElkJyB8fCBrZXkgPT09ICd1c2VyJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGFkZGl0aW9uYWxTZXNzaW9uRGF0YVtrZXldID0gdGhpcy5kYXRhW2tleV07XG4gICAgfVxuXG4gICAgY29uc3QgeyBzZXNzaW9uRGF0YSwgY3JlYXRlU2Vzc2lvbiB9ID0gQXV0aC5jcmVhdGVTZXNzaW9uKHRoaXMuY29uZmlnLCB7XG4gICAgICB1c2VySWQ6IHRoaXMuYXV0aC51c2VyLmlkLFxuICAgICAgY3JlYXRlZFdpdGg6IHtcbiAgICAgICAgYWN0aW9uOiAnY3JlYXRlJyxcbiAgICAgIH0sXG4gICAgICBhZGRpdGlvbmFsU2Vzc2lvbkRhdGEsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gY3JlYXRlU2Vzc2lvbigpLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICBpZiAoIXJlc3VsdHMucmVzcG9uc2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgICAnRXJyb3IgY3JlYXRpbmcgc2Vzc2lvbi4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBzZXNzaW9uRGF0YVsnb2JqZWN0SWQnXSA9IHJlc3VsdHMucmVzcG9uc2VbJ29iamVjdElkJ107XG4gICAgICB0aGlzLnJlc3BvbnNlID0ge1xuICAgICAgICBzdGF0dXM6IDIwMSxcbiAgICAgICAgbG9jYXRpb246IHJlc3VsdHMubG9jYXRpb24sXG4gICAgICAgIHJlc3BvbnNlOiBzZXNzaW9uRGF0YSxcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cbn07XG5cbi8vIEhhbmRsZXMgdGhlIF9JbnN0YWxsYXRpb24gY2xhc3Mgc3BlY2lhbG5lc3MuXG4vLyBEb2VzIG5vdGhpbmcgaWYgdGhpcyBpc24ndCBhbiBpbnN0YWxsYXRpb24gb2JqZWN0LlxuLy8gSWYgYW4gaW5zdGFsbGF0aW9uIGlzIGZvdW5kLCB0aGlzIGNhbiBtdXRhdGUgdGhpcy5xdWVyeSBhbmQgdHVybiBhIGNyZWF0ZVxuLy8gaW50byBhbiB1cGRhdGUuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3Igd2hlbiB3ZSdyZSBkb25lIGlmIGl0IGNhbid0IGZpbmlzaCB0aGlzIHRpY2suXG5SZXN0V3JpdGUucHJvdG90eXBlLmhhbmRsZUluc3RhbGxhdGlvbiA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5yZXNwb25zZSB8fCB0aGlzLmNsYXNzTmFtZSAhPT0gJ19JbnN0YWxsYXRpb24nKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKFxuICAgICF0aGlzLnF1ZXJ5ICYmXG4gICAgIXRoaXMuZGF0YS5kZXZpY2VUb2tlbiAmJlxuICAgICF0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQgJiZcbiAgICAhdGhpcy5hdXRoLmluc3RhbGxhdGlvbklkXG4gICkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIDEzNSxcbiAgICAgICdhdCBsZWFzdCBvbmUgSUQgZmllbGQgKGRldmljZVRva2VuLCBpbnN0YWxsYXRpb25JZCkgJyArXG4gICAgICAgICdtdXN0IGJlIHNwZWNpZmllZCBpbiB0aGlzIG9wZXJhdGlvbidcbiAgICApO1xuICB9XG5cbiAgLy8gSWYgdGhlIGRldmljZSB0b2tlbiBpcyA2NCBjaGFyYWN0ZXJzIGxvbmcsIHdlIGFzc3VtZSBpdCBpcyBmb3IgaU9TXG4gIC8vIGFuZCBsb3dlcmNhc2UgaXQuXG4gIGlmICh0aGlzLmRhdGEuZGV2aWNlVG9rZW4gJiYgdGhpcy5kYXRhLmRldmljZVRva2VuLmxlbmd0aCA9PSA2NCkge1xuICAgIHRoaXMuZGF0YS5kZXZpY2VUb2tlbiA9IHRoaXMuZGF0YS5kZXZpY2VUb2tlbi50b0xvd2VyQ2FzZSgpO1xuICB9XG5cbiAgLy8gV2UgbG93ZXJjYXNlIHRoZSBpbnN0YWxsYXRpb25JZCBpZiBwcmVzZW50XG4gIGlmICh0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQpIHtcbiAgICB0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQgPSB0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQudG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIGxldCBpbnN0YWxsYXRpb25JZCA9IHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZDtcblxuICAvLyBJZiBkYXRhLmluc3RhbGxhdGlvbklkIGlzIG5vdCBzZXQgYW5kIHdlJ3JlIG5vdCBtYXN0ZXIsIHdlIGNhbiBsb29rdXAgaW4gYXV0aFxuICBpZiAoIWluc3RhbGxhdGlvbklkICYmICF0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICBpbnN0YWxsYXRpb25JZCA9IHRoaXMuYXV0aC5pbnN0YWxsYXRpb25JZDtcbiAgfVxuXG4gIGlmIChpbnN0YWxsYXRpb25JZCkge1xuICAgIGluc3RhbGxhdGlvbklkID0gaW5zdGFsbGF0aW9uSWQudG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIC8vIFVwZGF0aW5nIF9JbnN0YWxsYXRpb24gYnV0IG5vdCB1cGRhdGluZyBhbnl0aGluZyBjcml0aWNhbFxuICBpZiAoXG4gICAgdGhpcy5xdWVyeSAmJlxuICAgICF0aGlzLmRhdGEuZGV2aWNlVG9rZW4gJiZcbiAgICAhaW5zdGFsbGF0aW9uSWQgJiZcbiAgICAhdGhpcy5kYXRhLmRldmljZVR5cGVcbiAgKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICB2YXIgaWRNYXRjaDsgLy8gV2lsbCBiZSBhIG1hdGNoIG9uIGVpdGhlciBvYmplY3RJZCBvciBpbnN0YWxsYXRpb25JZFxuICB2YXIgb2JqZWN0SWRNYXRjaDtcbiAgdmFyIGluc3RhbGxhdGlvbklkTWF0Y2g7XG4gIHZhciBkZXZpY2VUb2tlbk1hdGNoZXMgPSBbXTtcblxuICAvLyBJbnN0ZWFkIG9mIGlzc3VpbmcgMyByZWFkcywgbGV0J3MgZG8gaXQgd2l0aCBvbmUgT1IuXG4gIGNvbnN0IG9yUXVlcmllcyA9IFtdO1xuICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgb3JRdWVyaWVzLnB1c2goe1xuICAgICAgb2JqZWN0SWQ6IHRoaXMucXVlcnkub2JqZWN0SWQsXG4gICAgfSk7XG4gIH1cbiAgaWYgKGluc3RhbGxhdGlvbklkKSB7XG4gICAgb3JRdWVyaWVzLnB1c2goe1xuICAgICAgaW5zdGFsbGF0aW9uSWQ6IGluc3RhbGxhdGlvbklkLFxuICAgIH0pO1xuICB9XG4gIGlmICh0aGlzLmRhdGEuZGV2aWNlVG9rZW4pIHtcbiAgICBvclF1ZXJpZXMucHVzaCh7IGRldmljZVRva2VuOiB0aGlzLmRhdGEuZGV2aWNlVG9rZW4gfSk7XG4gIH1cblxuICBpZiAob3JRdWVyaWVzLmxlbmd0aCA9PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvbWlzZSA9IHByb21pc2VcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZChcbiAgICAgICAgJ19JbnN0YWxsYXRpb24nLFxuICAgICAgICB7XG4gICAgICAgICAgJG9yOiBvclF1ZXJpZXMsXG4gICAgICAgIH0sXG4gICAgICAgIHt9XG4gICAgICApO1xuICAgIH0pXG4gICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICByZXN1bHRzLmZvckVhY2gocmVzdWx0ID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMucXVlcnkgJiZcbiAgICAgICAgICB0aGlzLnF1ZXJ5Lm9iamVjdElkICYmXG4gICAgICAgICAgcmVzdWx0Lm9iamVjdElkID09IHRoaXMucXVlcnkub2JqZWN0SWRcbiAgICAgICAgKSB7XG4gICAgICAgICAgb2JqZWN0SWRNYXRjaCA9IHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0Lmluc3RhbGxhdGlvbklkID09IGluc3RhbGxhdGlvbklkKSB7XG4gICAgICAgICAgaW5zdGFsbGF0aW9uSWRNYXRjaCA9IHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0LmRldmljZVRva2VuID09IHRoaXMuZGF0YS5kZXZpY2VUb2tlbikge1xuICAgICAgICAgIGRldmljZVRva2VuTWF0Y2hlcy5wdXNoKHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBTYW5pdHkgY2hlY2tzIHdoZW4gcnVubmluZyBhIHF1ZXJ5XG4gICAgICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgICAgIGlmICghb2JqZWN0SWRNYXRjaCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAnT2JqZWN0IG5vdCBmb3VuZCBmb3IgdXBkYXRlLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQgJiZcbiAgICAgICAgICBvYmplY3RJZE1hdGNoLmluc3RhbGxhdGlvbklkICYmXG4gICAgICAgICAgdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkICE9PSBvYmplY3RJZE1hdGNoLmluc3RhbGxhdGlvbklkXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIDEzNixcbiAgICAgICAgICAgICdpbnN0YWxsYXRpb25JZCBtYXkgbm90IGJlIGNoYW5nZWQgaW4gdGhpcyAnICsgJ29wZXJhdGlvbidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLmRhdGEuZGV2aWNlVG9rZW4gJiZcbiAgICAgICAgICBvYmplY3RJZE1hdGNoLmRldmljZVRva2VuICYmXG4gICAgICAgICAgdGhpcy5kYXRhLmRldmljZVRva2VuICE9PSBvYmplY3RJZE1hdGNoLmRldmljZVRva2VuICYmXG4gICAgICAgICAgIXRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCAmJlxuICAgICAgICAgICFvYmplY3RJZE1hdGNoLmluc3RhbGxhdGlvbklkXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIDEzNixcbiAgICAgICAgICAgICdkZXZpY2VUb2tlbiBtYXkgbm90IGJlIGNoYW5nZWQgaW4gdGhpcyAnICsgJ29wZXJhdGlvbidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLmRhdGEuZGV2aWNlVHlwZSAmJlxuICAgICAgICAgIHRoaXMuZGF0YS5kZXZpY2VUeXBlICYmXG4gICAgICAgICAgdGhpcy5kYXRhLmRldmljZVR5cGUgIT09IG9iamVjdElkTWF0Y2guZGV2aWNlVHlwZVxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAxMzYsXG4gICAgICAgICAgICAnZGV2aWNlVHlwZSBtYXkgbm90IGJlIGNoYW5nZWQgaW4gdGhpcyAnICsgJ29wZXJhdGlvbidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQgJiYgb2JqZWN0SWRNYXRjaCkge1xuICAgICAgICBpZE1hdGNoID0gb2JqZWN0SWRNYXRjaDtcbiAgICAgIH1cblxuICAgICAgaWYgKGluc3RhbGxhdGlvbklkICYmIGluc3RhbGxhdGlvbklkTWF0Y2gpIHtcbiAgICAgICAgaWRNYXRjaCA9IGluc3RhbGxhdGlvbklkTWF0Y2g7XG4gICAgICB9XG4gICAgICAvLyBuZWVkIHRvIHNwZWNpZnkgZGV2aWNlVHlwZSBvbmx5IGlmIGl0J3MgbmV3XG4gICAgICBpZiAoIXRoaXMucXVlcnkgJiYgIXRoaXMuZGF0YS5kZXZpY2VUeXBlICYmICFpZE1hdGNoKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAxMzUsXG4gICAgICAgICAgJ2RldmljZVR5cGUgbXVzdCBiZSBzcGVjaWZpZWQgaW4gdGhpcyBvcGVyYXRpb24nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICBpZiAoIWlkTWF0Y2gpIHtcbiAgICAgICAgaWYgKCFkZXZpY2VUb2tlbk1hdGNoZXMubGVuZ3RoKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIGRldmljZVRva2VuTWF0Y2hlcy5sZW5ndGggPT0gMSAmJlxuICAgICAgICAgICghZGV2aWNlVG9rZW5NYXRjaGVzWzBdWydpbnN0YWxsYXRpb25JZCddIHx8ICFpbnN0YWxsYXRpb25JZClcbiAgICAgICAgKSB7XG4gICAgICAgICAgLy8gU2luZ2xlIG1hdGNoIG9uIGRldmljZSB0b2tlbiBidXQgbm9uZSBvbiBpbnN0YWxsYXRpb25JZCwgYW5kIGVpdGhlclxuICAgICAgICAgIC8vIHRoZSBwYXNzZWQgb2JqZWN0IG9yIHRoZSBtYXRjaCBpcyBtaXNzaW5nIGFuIGluc3RhbGxhdGlvbklkLCBzbyB3ZVxuICAgICAgICAgIC8vIGNhbiBqdXN0IHJldHVybiB0aGUgbWF0Y2guXG4gICAgICAgICAgcmV0dXJuIGRldmljZVRva2VuTWF0Y2hlc1swXVsnb2JqZWN0SWQnXTtcbiAgICAgICAgfSBlbHNlIGlmICghdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgMTMyLFxuICAgICAgICAgICAgJ011c3Qgc3BlY2lmeSBpbnN0YWxsYXRpb25JZCB3aGVuIGRldmljZVRva2VuICcgK1xuICAgICAgICAgICAgICAnbWF0Y2hlcyBtdWx0aXBsZSBJbnN0YWxsYXRpb24gb2JqZWN0cydcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIE11bHRpcGxlIGRldmljZSB0b2tlbiBtYXRjaGVzIGFuZCB3ZSBzcGVjaWZpZWQgYW4gaW5zdGFsbGF0aW9uIElELFxuICAgICAgICAgIC8vIG9yIGEgc2luZ2xlIG1hdGNoIHdoZXJlIGJvdGggdGhlIHBhc3NlZCBhbmQgbWF0Y2hpbmcgb2JqZWN0cyBoYXZlXG4gICAgICAgICAgLy8gYW4gaW5zdGFsbGF0aW9uIElELiBUcnkgY2xlYW5pbmcgb3V0IG9sZCBpbnN0YWxsYXRpb25zIHRoYXQgbWF0Y2hcbiAgICAgICAgICAvLyB0aGUgZGV2aWNlVG9rZW4sIGFuZCByZXR1cm4gbmlsIHRvIHNpZ25hbCB0aGF0IGEgbmV3IG9iamVjdCBzaG91bGRcbiAgICAgICAgICAvLyBiZSBjcmVhdGVkLlxuICAgICAgICAgIHZhciBkZWxRdWVyeSA9IHtcbiAgICAgICAgICAgIGRldmljZVRva2VuOiB0aGlzLmRhdGEuZGV2aWNlVG9rZW4sXG4gICAgICAgICAgICBpbnN0YWxsYXRpb25JZDoge1xuICAgICAgICAgICAgICAkbmU6IGluc3RhbGxhdGlvbklkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmICh0aGlzLmRhdGEuYXBwSWRlbnRpZmllcikge1xuICAgICAgICAgICAgZGVsUXVlcnlbJ2FwcElkZW50aWZpZXInXSA9IHRoaXMuZGF0YS5hcHBJZGVudGlmaWVyO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kZXN0cm95KCdfSW5zdGFsbGF0aW9uJywgZGVsUXVlcnkpLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyLmNvZGUgPT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCkge1xuICAgICAgICAgICAgICAvLyBubyBkZWxldGlvbnMgd2VyZSBtYWRlLiBDYW4gYmUgaWdub3JlZC5cbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gcmV0aHJvdyB0aGUgZXJyb3JcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBkZXZpY2VUb2tlbk1hdGNoZXMubGVuZ3RoID09IDEgJiZcbiAgICAgICAgICAhZGV2aWNlVG9rZW5NYXRjaGVzWzBdWydpbnN0YWxsYXRpb25JZCddXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIEV4YWN0bHkgb25lIGRldmljZSB0b2tlbiBtYXRjaCBhbmQgaXQgZG9lc24ndCBoYXZlIGFuIGluc3RhbGxhdGlvblxuICAgICAgICAgIC8vIElELiBUaGlzIGlzIHRoZSBvbmUgY2FzZSB3aGVyZSB3ZSB3YW50IHRvIG1lcmdlIHdpdGggdGhlIGV4aXN0aW5nXG4gICAgICAgICAgLy8gb2JqZWN0LlxuICAgICAgICAgIGNvbnN0IGRlbFF1ZXJ5ID0geyBvYmplY3RJZDogaWRNYXRjaC5vYmplY3RJZCB9O1xuICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgICAgICAgLmRlc3Ryb3koJ19JbnN0YWxsYXRpb24nLCBkZWxRdWVyeSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGRldmljZVRva2VuTWF0Y2hlc1swXVsnb2JqZWN0SWQnXTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICAgICAgaWYgKGVyci5jb2RlID09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgICAgICAvLyBubyBkZWxldGlvbnMgd2VyZSBtYWRlLiBDYW4gYmUgaWdub3JlZFxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAvLyByZXRocm93IHRoZSBlcnJvclxuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLmRhdGEuZGV2aWNlVG9rZW4gJiZcbiAgICAgICAgICAgIGlkTWF0Y2guZGV2aWNlVG9rZW4gIT0gdGhpcy5kYXRhLmRldmljZVRva2VuXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBzZXR0aW5nIHRoZSBkZXZpY2UgdG9rZW4gb24gYW4gZXhpc3RpbmcgaW5zdGFsbGF0aW9uLCBzb1xuICAgICAgICAgICAgLy8gd2Ugc2hvdWxkIHRyeSBjbGVhbmluZyBvdXQgb2xkIGluc3RhbGxhdGlvbnMgdGhhdCBtYXRjaCB0aGlzXG4gICAgICAgICAgICAvLyBkZXZpY2UgdG9rZW4uXG4gICAgICAgICAgICBjb25zdCBkZWxRdWVyeSA9IHtcbiAgICAgICAgICAgICAgZGV2aWNlVG9rZW46IHRoaXMuZGF0YS5kZXZpY2VUb2tlbixcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBXZSBoYXZlIGEgdW5pcXVlIGluc3RhbGwgSWQsIHVzZSB0aGF0IHRvIHByZXNlcnZlXG4gICAgICAgICAgICAvLyB0aGUgaW50ZXJlc3RpbmcgaW5zdGFsbGF0aW9uXG4gICAgICAgICAgICBpZiAodGhpcy5kYXRhLmluc3RhbGxhdGlvbklkKSB7XG4gICAgICAgICAgICAgIGRlbFF1ZXJ5WydpbnN0YWxsYXRpb25JZCddID0ge1xuICAgICAgICAgICAgICAgICRuZTogdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgaWRNYXRjaC5vYmplY3RJZCAmJlxuICAgICAgICAgICAgICB0aGlzLmRhdGEub2JqZWN0SWQgJiZcbiAgICAgICAgICAgICAgaWRNYXRjaC5vYmplY3RJZCA9PSB0aGlzLmRhdGEub2JqZWN0SWRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAvLyB3ZSBwYXNzZWQgYW4gb2JqZWN0SWQsIHByZXNlcnZlIHRoYXQgaW5zdGFsYXRpb25cbiAgICAgICAgICAgICAgZGVsUXVlcnlbJ29iamVjdElkJ10gPSB7XG4gICAgICAgICAgICAgICAgJG5lOiBpZE1hdGNoLm9iamVjdElkLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gV2hhdCB0byBkbyBoZXJlPyBjYW4ndCByZWFsbHkgY2xlYW4gdXAgZXZlcnl0aGluZy4uLlxuICAgICAgICAgICAgICByZXR1cm4gaWRNYXRjaC5vYmplY3RJZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmRhdGEuYXBwSWRlbnRpZmllcikge1xuICAgICAgICAgICAgICBkZWxRdWVyeVsnYXBwSWRlbnRpZmllciddID0gdGhpcy5kYXRhLmFwcElkZW50aWZpZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgICAgICAgICAuZGVzdHJveSgnX0luc3RhbGxhdGlvbicsIGRlbFF1ZXJ5KVxuICAgICAgICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyLmNvZGUgPT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCkge1xuICAgICAgICAgICAgICAgICAgLy8gbm8gZGVsZXRpb25zIHdlcmUgbWFkZS4gQ2FuIGJlIGlnbm9yZWQuXG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHJldGhyb3cgdGhlIGVycm9yXG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gSW4gbm9uLW1lcmdlIHNjZW5hcmlvcywganVzdCByZXR1cm4gdGhlIGluc3RhbGxhdGlvbiBtYXRjaCBpZFxuICAgICAgICAgIHJldHVybiBpZE1hdGNoLm9iamVjdElkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSlcbiAgICAudGhlbihvYmpJZCA9PiB7XG4gICAgICBpZiAob2JqSWQpIHtcbiAgICAgICAgdGhpcy5xdWVyeSA9IHsgb2JqZWN0SWQ6IG9iaklkIH07XG4gICAgICAgIGRlbGV0ZSB0aGlzLmRhdGEub2JqZWN0SWQ7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmRhdGEuY3JlYXRlZEF0O1xuICAgICAgfVxuICAgICAgLy8gVE9ETzogVmFsaWRhdGUgb3BzIChhZGQvcmVtb3ZlIG9uIGNoYW5uZWxzLCAkaW5jIG9uIGJhZGdlLCBldGMuKVxuICAgIH0pO1xuICByZXR1cm4gcHJvbWlzZTtcbn07XG5cbi8vIElmIHdlIHNob3J0LWNpcmN1dGVkIHRoZSBvYmplY3QgcmVzcG9uc2UgLSB0aGVuIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHdlIGV4cGFuZCBhbGwgdGhlIGZpbGVzLFxuLy8gc2luY2UgdGhpcyBtaWdodCBub3QgaGF2ZSBhIHF1ZXJ5LCBtZWFuaW5nIGl0IHdvbid0IHJldHVybiB0aGUgZnVsbCByZXN1bHQgYmFjay5cbi8vIFRPRE86IChubHV0c2Vua28pIFRoaXMgc2hvdWxkIGRpZSB3aGVuIHdlIG1vdmUgdG8gcGVyLWNsYXNzIGJhc2VkIGNvbnRyb2xsZXJzIG9uIF9TZXNzaW9uL19Vc2VyXG5SZXN0V3JpdGUucHJvdG90eXBlLmV4cGFuZEZpbGVzRm9yRXhpc3RpbmdPYmplY3RzID0gZnVuY3Rpb24oKSB7XG4gIC8vIENoZWNrIHdoZXRoZXIgd2UgaGF2ZSBhIHNob3J0LWNpcmN1aXRlZCByZXNwb25zZSAtIG9ubHkgdGhlbiBydW4gZXhwYW5zaW9uLlxuICBpZiAodGhpcy5yZXNwb25zZSAmJiB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlKSB7XG4gICAgdGhpcy5jb25maWcuZmlsZXNDb250cm9sbGVyLmV4cGFuZEZpbGVzSW5PYmplY3QoXG4gICAgICB0aGlzLmNvbmZpZyxcbiAgICAgIHRoaXMucmVzcG9uc2UucmVzcG9uc2VcbiAgICApO1xuICB9XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLnJ1bkRhdGFiYXNlT3BlcmF0aW9uID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLnJlc3BvbnNlKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHRoaXMuY2xhc3NOYW1lID09PSAnX1JvbGUnKSB7XG4gICAgdGhpcy5jb25maWcuY2FjaGVDb250cm9sbGVyLnJvbGUuY2xlYXIoKTtcbiAgfVxuXG4gIGlmIChcbiAgICB0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJlxuICAgIHRoaXMucXVlcnkgJiZcbiAgICB0aGlzLmF1dGguaXNVbmF1dGhlbnRpY2F0ZWQoKVxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5TRVNTSU9OX01JU1NJTkcsXG4gICAgICBgQ2Fubm90IG1vZGlmeSB1c2VyICR7dGhpcy5xdWVyeS5vYmplY3RJZH0uYFxuICAgICk7XG4gIH1cblxuICBpZiAodGhpcy5jbGFzc05hbWUgPT09ICdfUHJvZHVjdCcgJiYgdGhpcy5kYXRhLmRvd25sb2FkKSB7XG4gICAgdGhpcy5kYXRhLmRvd25sb2FkTmFtZSA9IHRoaXMuZGF0YS5kb3dubG9hZC5uYW1lO1xuICB9XG5cbiAgLy8gVE9ETzogQWRkIGJldHRlciBkZXRlY3Rpb24gZm9yIEFDTCwgZW5zdXJpbmcgYSB1c2VyIGNhbid0IGJlIGxvY2tlZCBmcm9tXG4gIC8vICAgICAgIHRoZWlyIG93biB1c2VyIHJlY29yZC5cbiAgaWYgKHRoaXMuZGF0YS5BQ0wgJiYgdGhpcy5kYXRhLkFDTFsnKnVucmVzb2x2ZWQnXSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0FDTCwgJ0ludmFsaWQgQUNMLicpO1xuICB9XG5cbiAgaWYgKHRoaXMucXVlcnkpIHtcbiAgICAvLyBGb3JjZSB0aGUgdXNlciB0byBub3QgbG9ja291dFxuICAgIC8vIE1hdGNoZWQgd2l0aCBwYXJzZS5jb21cbiAgICBpZiAoXG4gICAgICB0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJlxuICAgICAgdGhpcy5kYXRhLkFDTCAmJlxuICAgICAgdGhpcy5hdXRoLmlzTWFzdGVyICE9PSB0cnVlXG4gICAgKSB7XG4gICAgICB0aGlzLmRhdGEuQUNMW3RoaXMucXVlcnkub2JqZWN0SWRdID0geyByZWFkOiB0cnVlLCB3cml0ZTogdHJ1ZSB9O1xuICAgIH1cbiAgICAvLyB1cGRhdGUgcGFzc3dvcmQgdGltZXN0YW1wIGlmIHVzZXIgcGFzc3dvcmQgaXMgYmVpbmcgY2hhbmdlZFxuICAgIGlmIChcbiAgICAgIHRoaXMuY2xhc3NOYW1lID09PSAnX1VzZXInICYmXG4gICAgICB0aGlzLmRhdGEuX2hhc2hlZF9wYXNzd29yZCAmJlxuICAgICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kgJiZcbiAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlXG4gICAgKSB7XG4gICAgICB0aGlzLmRhdGEuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKCkpO1xuICAgIH1cbiAgICAvLyBJZ25vcmUgY3JlYXRlZEF0IHdoZW4gdXBkYXRlXG4gICAgZGVsZXRlIHRoaXMuZGF0YS5jcmVhdGVkQXQ7XG5cbiAgICBsZXQgZGVmZXIgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAvLyBpZiBwYXNzd29yZCBoaXN0b3J5IGlzIGVuYWJsZWQgdGhlbiBzYXZlIHRoZSBjdXJyZW50IHBhc3N3b3JkIHRvIGhpc3RvcnlcbiAgICBpZiAoXG4gICAgICB0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJlxuICAgICAgdGhpcy5kYXRhLl9oYXNoZWRfcGFzc3dvcmQgJiZcbiAgICAgIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5ICYmXG4gICAgICB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnlcbiAgICApIHtcbiAgICAgIGRlZmVyID0gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgICAgLmZpbmQoXG4gICAgICAgICAgJ19Vc2VyJyxcbiAgICAgICAgICB7IG9iamVjdElkOiB0aGlzLm9iamVjdElkKCkgfSxcbiAgICAgICAgICB7IGtleXM6IFsnX3Bhc3N3b3JkX2hpc3RvcnknLCAnX2hhc2hlZF9wYXNzd29yZCddIH1cbiAgICAgICAgKVxuICAgICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggIT0gMSkge1xuICAgICAgICAgICAgdGhyb3cgdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCB1c2VyID0gcmVzdWx0c1swXTtcbiAgICAgICAgICBsZXQgb2xkUGFzc3dvcmRzID0gW107XG4gICAgICAgICAgaWYgKHVzZXIuX3Bhc3N3b3JkX2hpc3RvcnkpIHtcbiAgICAgICAgICAgIG9sZFBhc3N3b3JkcyA9IF8udGFrZShcbiAgICAgICAgICAgICAgdXNlci5fcGFzc3dvcmRfaGlzdG9yeSxcbiAgICAgICAgICAgICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvL24tMSBwYXNzd29yZHMgZ28gaW50byBoaXN0b3J5IGluY2x1ZGluZyBsYXN0IHBhc3N3b3JkXG4gICAgICAgICAgd2hpbGUgKFxuICAgICAgICAgICAgb2xkUGFzc3dvcmRzLmxlbmd0aCA+XG4gICAgICAgICAgICBNYXRoLm1heCgwLCB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgLSAyKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgb2xkUGFzc3dvcmRzLnNoaWZ0KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG9sZFBhc3N3b3Jkcy5wdXNoKHVzZXIucGFzc3dvcmQpO1xuICAgICAgICAgIHRoaXMuZGF0YS5fcGFzc3dvcmRfaGlzdG9yeSA9IG9sZFBhc3N3b3JkcztcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlZmVyLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gUnVuIGFuIHVwZGF0ZVxuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlXG4gICAgICAgIC51cGRhdGUoXG4gICAgICAgICAgdGhpcy5jbGFzc05hbWUsXG4gICAgICAgICAgdGhpcy5xdWVyeSxcbiAgICAgICAgICB0aGlzLmRhdGEsXG4gICAgICAgICAgdGhpcy5ydW5PcHRpb25zLFxuICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgIHRoaXMudmFsaWRTY2hlbWFDb250cm9sbGVyXG4gICAgICAgIClcbiAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgIHJlc3BvbnNlLnVwZGF0ZWRBdCA9IHRoaXMudXBkYXRlZEF0O1xuICAgICAgICAgIHRoaXMuX3VwZGF0ZVJlc3BvbnNlV2l0aERhdGEocmVzcG9uc2UsIHRoaXMuZGF0YSk7XG4gICAgICAgICAgdGhpcy5yZXNwb25zZSA9IHsgcmVzcG9uc2UgfTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gU2V0IHRoZSBkZWZhdWx0IEFDTCBhbmQgcGFzc3dvcmQgdGltZXN0YW1wIGZvciB0aGUgbmV3IF9Vc2VyXG4gICAgaWYgKHRoaXMuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgICB2YXIgQUNMID0gdGhpcy5kYXRhLkFDTDtcbiAgICAgIC8vIGRlZmF1bHQgcHVibGljIHIvdyBBQ0xcbiAgICAgIGlmICghQUNMKSB7XG4gICAgICAgIEFDTCA9IHt9O1xuICAgICAgICBBQ0xbJyonXSA9IHsgcmVhZDogdHJ1ZSwgd3JpdGU6IGZhbHNlIH07XG4gICAgICB9XG4gICAgICAvLyBtYWtlIHN1cmUgdGhlIHVzZXIgaXMgbm90IGxvY2tlZCBkb3duXG4gICAgICBBQ0xbdGhpcy5kYXRhLm9iamVjdElkXSA9IHsgcmVhZDogdHJ1ZSwgd3JpdGU6IHRydWUgfTtcbiAgICAgIHRoaXMuZGF0YS5BQ0wgPSBBQ0w7XG4gICAgICAvLyBwYXNzd29yZCB0aW1lc3RhbXAgdG8gYmUgdXNlZCB3aGVuIHBhc3N3b3JkIGV4cGlyeSBwb2xpY3kgaXMgZW5mb3JjZWRcbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kgJiZcbiAgICAgICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRBZ2VcbiAgICAgICkge1xuICAgICAgICB0aGlzLmRhdGEuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJ1biBhIGNyZWF0ZVxuICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgLmNyZWF0ZShcbiAgICAgICAgdGhpcy5jbGFzc05hbWUsXG4gICAgICAgIHRoaXMuZGF0YSxcbiAgICAgICAgdGhpcy5ydW5PcHRpb25zLFxuICAgICAgICBmYWxzZSxcbiAgICAgICAgdGhpcy52YWxpZFNjaGVtYUNvbnRyb2xsZXJcbiAgICAgIClcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLmNsYXNzTmFtZSAhPT0gJ19Vc2VyJyB8fFxuICAgICAgICAgIGVycm9yLmNvZGUgIT09IFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRVxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFF1aWNrIGNoZWNrLCBpZiB3ZSB3ZXJlIGFibGUgdG8gaW5mZXIgdGhlIGR1cGxpY2F0ZWQgZmllbGQgbmFtZVxuICAgICAgICBpZiAoXG4gICAgICAgICAgZXJyb3IgJiZcbiAgICAgICAgICBlcnJvci51c2VySW5mbyAmJlxuICAgICAgICAgIGVycm9yLnVzZXJJbmZvLmR1cGxpY2F0ZWRfZmllbGQgPT09ICd1c2VybmFtZSdcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuVVNFUk5BTUVfVEFLRU4sXG4gICAgICAgICAgICAnQWNjb3VudCBhbHJlYWR5IGV4aXN0cyBmb3IgdGhpcyB1c2VybmFtZS4nXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChcbiAgICAgICAgICBlcnJvciAmJlxuICAgICAgICAgIGVycm9yLnVzZXJJbmZvICYmXG4gICAgICAgICAgZXJyb3IudXNlckluZm8uZHVwbGljYXRlZF9maWVsZCA9PT0gJ2VtYWlsJ1xuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5FTUFJTF9UQUtFTixcbiAgICAgICAgICAgICdBY2NvdW50IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIGVtYWlsIGFkZHJlc3MuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGlzIHdhcyBhIGZhaWxlZCB1c2VyIGNyZWF0aW9uIGR1ZSB0byB1c2VybmFtZSBvciBlbWFpbCBhbHJlYWR5IHRha2VuLCB3ZSBuZWVkIHRvXG4gICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgaXQgd2FzIHVzZXJuYW1lIG9yIGVtYWlsIGFuZCByZXR1cm4gdGhlIGFwcHJvcHJpYXRlIGVycm9yLlxuICAgICAgICAvLyBGYWxsYmFjayB0byB0aGUgb3JpZ2luYWwgbWV0aG9kXG4gICAgICAgIC8vIFRPRE86IFNlZSBpZiB3ZSBjYW4gbGF0ZXIgZG8gdGhpcyB3aXRob3V0IGFkZGl0aW9uYWwgcXVlcmllcyBieSB1c2luZyBuYW1lZCBpbmRleGVzLlxuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2VcbiAgICAgICAgICAuZmluZChcbiAgICAgICAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB1c2VybmFtZTogdGhpcy5kYXRhLnVzZXJuYW1lLFxuICAgICAgICAgICAgICBvYmplY3RJZDogeyAkbmU6IHRoaXMub2JqZWN0SWQoKSB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHsgbGltaXQ6IDEgfVxuICAgICAgICAgIClcbiAgICAgICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLlVTRVJOQU1FX1RBS0VOLFxuICAgICAgICAgICAgICAgICdBY2NvdW50IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIHVzZXJuYW1lLidcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS5maW5kKFxuICAgICAgICAgICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgeyBlbWFpbDogdGhpcy5kYXRhLmVtYWlsLCBvYmplY3RJZDogeyAkbmU6IHRoaXMub2JqZWN0SWQoKSB9IH0sXG4gICAgICAgICAgICAgIHsgbGltaXQ6IDEgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuRU1BSUxfVEFLRU4sXG4gICAgICAgICAgICAgICAgJ0FjY291bnQgYWxyZWFkeSBleGlzdHMgZm9yIHRoaXMgZW1haWwgYWRkcmVzcy4nXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSxcbiAgICAgICAgICAgICAgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgcmVzcG9uc2Uub2JqZWN0SWQgPSB0aGlzLmRhdGEub2JqZWN0SWQ7XG4gICAgICAgIHJlc3BvbnNlLmNyZWF0ZWRBdCA9IHRoaXMuZGF0YS5jcmVhdGVkQXQ7XG5cbiAgICAgICAgaWYgKHRoaXMucmVzcG9uc2VTaG91bGRIYXZlVXNlcm5hbWUpIHtcbiAgICAgICAgICByZXNwb25zZS51c2VybmFtZSA9IHRoaXMuZGF0YS51c2VybmFtZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl91cGRhdGVSZXNwb25zZVdpdGhEYXRhKHJlc3BvbnNlLCB0aGlzLmRhdGEpO1xuICAgICAgICB0aGlzLnJlc3BvbnNlID0ge1xuICAgICAgICAgIHN0YXR1czogMjAxLFxuICAgICAgICAgIHJlc3BvbnNlLFxuICAgICAgICAgIGxvY2F0aW9uOiB0aGlzLmxvY2F0aW9uKCksXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgfVxufTtcblxuLy8gUmV0dXJucyBub3RoaW5nIC0gZG9lc24ndCB3YWl0IGZvciB0aGUgdHJpZ2dlci5cblJlc3RXcml0ZS5wcm90b3R5cGUucnVuQWZ0ZXJTYXZlVHJpZ2dlciA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMucmVzcG9uc2UgfHwgIXRoaXMucmVzcG9uc2UucmVzcG9uc2UpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBBdm9pZCBkb2luZyBhbnkgc2V0dXAgZm9yIHRyaWdnZXJzIGlmIHRoZXJlIGlzIG5vICdhZnRlclNhdmUnIHRyaWdnZXIgZm9yIHRoaXMgY2xhc3MuXG4gIGNvbnN0IGhhc0FmdGVyU2F2ZUhvb2sgPSB0cmlnZ2Vycy50cmlnZ2VyRXhpc3RzKFxuICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyU2F2ZSxcbiAgICB0aGlzLmNvbmZpZy5hcHBsaWNhdGlvbklkXG4gICk7XG4gIGNvbnN0IGhhc0xpdmVRdWVyeSA9IHRoaXMuY29uZmlnLmxpdmVRdWVyeUNvbnRyb2xsZXIuaGFzTGl2ZVF1ZXJ5KFxuICAgIHRoaXMuY2xhc3NOYW1lXG4gICk7XG4gIGlmICghaGFzQWZ0ZXJTYXZlSG9vayAmJiAhaGFzTGl2ZVF1ZXJ5KSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgdmFyIGV4dHJhRGF0YSA9IHsgY2xhc3NOYW1lOiB0aGlzLmNsYXNzTmFtZSB9O1xuICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgZXh0cmFEYXRhLm9iamVjdElkID0gdGhpcy5xdWVyeS5vYmplY3RJZDtcbiAgfVxuXG4gIC8vIEJ1aWxkIHRoZSBvcmlnaW5hbCBvYmplY3QsIHdlIG9ubHkgZG8gdGhpcyBmb3IgYSB1cGRhdGUgd3JpdGUuXG4gIGxldCBvcmlnaW5hbE9iamVjdDtcbiAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgIG9yaWdpbmFsT2JqZWN0ID0gdHJpZ2dlcnMuaW5mbGF0ZShleHRyYURhdGEsIHRoaXMub3JpZ2luYWxEYXRhKTtcbiAgfVxuXG4gIC8vIEJ1aWxkIHRoZSBpbmZsYXRlZCBvYmplY3QsIGRpZmZlcmVudCBmcm9tIGJlZm9yZVNhdmUsIG9yaWdpbmFsRGF0YSBpcyBub3QgZW1wdHlcbiAgLy8gc2luY2UgZGV2ZWxvcGVycyBjYW4gY2hhbmdlIGRhdGEgaW4gdGhlIGJlZm9yZVNhdmUuXG4gIGNvbnN0IHVwZGF0ZWRPYmplY3QgPSB0aGlzLmJ1aWxkVXBkYXRlZE9iamVjdChleHRyYURhdGEpO1xuICB1cGRhdGVkT2JqZWN0Ll9oYW5kbGVTYXZlUmVzcG9uc2UoXG4gICAgdGhpcy5yZXNwb25zZS5yZXNwb25zZSxcbiAgICB0aGlzLnJlc3BvbnNlLnN0YXR1cyB8fCAyMDBcbiAgKTtcblxuICB0aGlzLmNvbmZpZy5kYXRhYmFzZS5sb2FkU2NoZW1hKCkudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHtcbiAgICAvLyBOb3RpZml5IExpdmVRdWVyeVNlcnZlciBpZiBwb3NzaWJsZVxuICAgIGNvbnN0IHBlcm1zID0gc2NoZW1hQ29udHJvbGxlci5nZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoXG4gICAgICB1cGRhdGVkT2JqZWN0LmNsYXNzTmFtZVxuICAgICk7XG4gICAgdGhpcy5jb25maWcubGl2ZVF1ZXJ5Q29udHJvbGxlci5vbkFmdGVyU2F2ZShcbiAgICAgIHVwZGF0ZWRPYmplY3QuY2xhc3NOYW1lLFxuICAgICAgdXBkYXRlZE9iamVjdCxcbiAgICAgIG9yaWdpbmFsT2JqZWN0LFxuICAgICAgcGVybXNcbiAgICApO1xuICB9KTtcblxuICAvLyBSdW4gYWZ0ZXJTYXZlIHRyaWdnZXJcbiAgcmV0dXJuIHRyaWdnZXJzXG4gICAgLm1heWJlUnVuVHJpZ2dlcihcbiAgICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyU2F2ZSxcbiAgICAgIHRoaXMuYXV0aCxcbiAgICAgIHVwZGF0ZWRPYmplY3QsXG4gICAgICBvcmlnaW5hbE9iamVjdCxcbiAgICAgIHRoaXMuY29uZmlnLFxuICAgICAgdGhpcy5jb250ZXh0XG4gICAgKVxuICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICBpZiAocmVzdWx0ICYmIHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHRoaXMucmVzcG9uc2UucmVzcG9uc2UgPSByZXN1bHQ7XG4gICAgICB9XG4gICAgfSlcbiAgICAuY2F0Y2goZnVuY3Rpb24oZXJyKSB7XG4gICAgICBsb2dnZXIud2FybignYWZ0ZXJTYXZlIGNhdWdodCBhbiBlcnJvcicsIGVycik7XG4gICAgfSk7XG59O1xuXG4vLyBBIGhlbHBlciB0byBmaWd1cmUgb3V0IHdoYXQgbG9jYXRpb24gdGhpcyBvcGVyYXRpb24gaGFwcGVucyBhdC5cblJlc3RXcml0ZS5wcm90b3R5cGUubG9jYXRpb24gPSBmdW5jdGlvbigpIHtcbiAgdmFyIG1pZGRsZSA9XG4gICAgdGhpcy5jbGFzc05hbWUgPT09ICdfVXNlcicgPyAnL3VzZXJzLycgOiAnL2NsYXNzZXMvJyArIHRoaXMuY2xhc3NOYW1lICsgJy8nO1xuICByZXR1cm4gdGhpcy5jb25maWcubW91bnQgKyBtaWRkbGUgKyB0aGlzLmRhdGEub2JqZWN0SWQ7XG59O1xuXG4vLyBBIGhlbHBlciB0byBnZXQgdGhlIG9iamVjdCBpZCBmb3IgdGhpcyBvcGVyYXRpb24uXG4vLyBCZWNhdXNlIGl0IGNvdWxkIGJlIGVpdGhlciBvbiB0aGUgcXVlcnkgb3Igb24gdGhlIGRhdGFcblJlc3RXcml0ZS5wcm90b3R5cGUub2JqZWN0SWQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuZGF0YS5vYmplY3RJZCB8fCB0aGlzLnF1ZXJ5Lm9iamVjdElkO1xufTtcblxuLy8gUmV0dXJucyBhIGNvcHkgb2YgdGhlIGRhdGEgYW5kIGRlbGV0ZSBiYWQga2V5cyAoX2F1dGhfZGF0YSwgX2hhc2hlZF9wYXNzd29yZC4uLilcblJlc3RXcml0ZS5wcm90b3R5cGUuc2FuaXRpemVkRGF0YSA9IGZ1bmN0aW9uKCkge1xuICBjb25zdCBkYXRhID0gT2JqZWN0LmtleXModGhpcy5kYXRhKS5yZWR1Y2UoKGRhdGEsIGtleSkgPT4ge1xuICAgIC8vIFJlZ2V4cCBjb21lcyBmcm9tIFBhcnNlLk9iamVjdC5wcm90b3R5cGUudmFsaWRhdGVcbiAgICBpZiAoIS9eW0EtWmEtel1bMC05QS1aYS16X10qJC8udGVzdChrZXkpKSB7XG4gICAgICBkZWxldGUgZGF0YVtrZXldO1xuICAgIH1cbiAgICByZXR1cm4gZGF0YTtcbiAgfSwgZGVlcGNvcHkodGhpcy5kYXRhKSk7XG4gIHJldHVybiBQYXJzZS5fZGVjb2RlKHVuZGVmaW5lZCwgZGF0YSk7XG59O1xuXG4vLyBSZXR1cm5zIGFuIHVwZGF0ZWQgY29weSBvZiB0aGUgb2JqZWN0XG5SZXN0V3JpdGUucHJvdG90eXBlLmJ1aWxkVXBkYXRlZE9iamVjdCA9IGZ1bmN0aW9uKGV4dHJhRGF0YSkge1xuICBjb25zdCB1cGRhdGVkT2JqZWN0ID0gdHJpZ2dlcnMuaW5mbGF0ZShleHRyYURhdGEsIHRoaXMub3JpZ2luYWxEYXRhKTtcbiAgT2JqZWN0LmtleXModGhpcy5kYXRhKS5yZWR1Y2UoZnVuY3Rpb24oZGF0YSwga2V5KSB7XG4gICAgaWYgKGtleS5pbmRleE9mKCcuJykgPiAwKSB7XG4gICAgICAvLyBzdWJkb2N1bWVudCBrZXkgd2l0aCBkb3Qgbm90YXRpb24gKCd4LnknOnYgPT4gJ3gnOnsneSc6dn0pXG4gICAgICBjb25zdCBzcGxpdHRlZEtleSA9IGtleS5zcGxpdCgnLicpO1xuICAgICAgY29uc3QgcGFyZW50UHJvcCA9IHNwbGl0dGVkS2V5WzBdO1xuICAgICAgbGV0IHBhcmVudFZhbCA9IHVwZGF0ZWRPYmplY3QuZ2V0KHBhcmVudFByb3ApO1xuICAgICAgaWYgKHR5cGVvZiBwYXJlbnRWYWwgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHBhcmVudFZhbCA9IHt9O1xuICAgICAgfVxuICAgICAgcGFyZW50VmFsW3NwbGl0dGVkS2V5WzFdXSA9IGRhdGFba2V5XTtcbiAgICAgIHVwZGF0ZWRPYmplY3Quc2V0KHBhcmVudFByb3AsIHBhcmVudFZhbCk7XG4gICAgICBkZWxldGUgZGF0YVtrZXldO1xuICAgIH1cbiAgICByZXR1cm4gZGF0YTtcbiAgfSwgZGVlcGNvcHkodGhpcy5kYXRhKSk7XG5cbiAgdXBkYXRlZE9iamVjdC5zZXQodGhpcy5zYW5pdGl6ZWREYXRhKCkpO1xuICByZXR1cm4gdXBkYXRlZE9iamVjdDtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuY2xlYW5Vc2VyQXV0aERhdGEgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMucmVzcG9uc2UgJiYgdGhpcy5yZXNwb25zZS5yZXNwb25zZSAmJiB0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlO1xuICAgIGlmICh1c2VyLmF1dGhEYXRhKSB7XG4gICAgICBPYmplY3Qua2V5cyh1c2VyLmF1dGhEYXRhKS5mb3JFYWNoKHByb3ZpZGVyID0+IHtcbiAgICAgICAgaWYgKHVzZXIuYXV0aERhdGFbcHJvdmlkZXJdID09PSBudWxsKSB7XG4gICAgICAgICAgZGVsZXRlIHVzZXIuYXV0aERhdGFbcHJvdmlkZXJdO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGlmIChPYmplY3Qua2V5cyh1c2VyLmF1dGhEYXRhKS5sZW5ndGggPT0gMCkge1xuICAgICAgICBkZWxldGUgdXNlci5hdXRoRGF0YTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuX3VwZGF0ZVJlc3BvbnNlV2l0aERhdGEgPSBmdW5jdGlvbihyZXNwb25zZSwgZGF0YSkge1xuICBpZiAoXy5pc0VtcHR5KHRoaXMuc3RvcmFnZS5maWVsZHNDaGFuZ2VkQnlUcmlnZ2VyKSkge1xuICAgIHJldHVybiByZXNwb25zZTtcbiAgfVxuICBjb25zdCBjbGllbnRTdXBwb3J0c0RlbGV0ZSA9IENsaWVudFNESy5zdXBwb3J0c0ZvcndhcmREZWxldGUodGhpcy5jbGllbnRTREspO1xuICB0aGlzLnN0b3JhZ2UuZmllbGRzQ2hhbmdlZEJ5VHJpZ2dlci5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgY29uc3QgZGF0YVZhbHVlID0gZGF0YVtmaWVsZE5hbWVdO1xuXG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVzcG9uc2UsIGZpZWxkTmFtZSkpIHtcbiAgICAgIHJlc3BvbnNlW2ZpZWxkTmFtZV0gPSBkYXRhVmFsdWU7XG4gICAgfVxuXG4gICAgLy8gU3RyaXBzIG9wZXJhdGlvbnMgZnJvbSByZXNwb25zZXNcbiAgICBpZiAocmVzcG9uc2VbZmllbGROYW1lXSAmJiByZXNwb25zZVtmaWVsZE5hbWVdLl9fb3ApIHtcbiAgICAgIGRlbGV0ZSByZXNwb25zZVtmaWVsZE5hbWVdO1xuICAgICAgaWYgKGNsaWVudFN1cHBvcnRzRGVsZXRlICYmIGRhdGFWYWx1ZS5fX29wID09ICdEZWxldGUnKSB7XG4gICAgICAgIHJlc3BvbnNlW2ZpZWxkTmFtZV0gPSBkYXRhVmFsdWU7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHJlc3BvbnNlO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgUmVzdFdyaXRlO1xubW9kdWxlLmV4cG9ydHMgPSBSZXN0V3JpdGU7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/AggregateRouter.js b/lib/Routers/AggregateRouter.js new file mode 100644 index 0000000000..62bf0ed04c --- /dev/null +++ b/lib/Routers/AggregateRouter.js @@ -0,0 +1,148 @@ +"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', 'hint', 'explain']; +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); + } + + if (body.hint) { + options.hint = body.hint; + delete body.hint; + } + + if (body.explain) { + options.explain = body.explain; + delete body.explain; + } + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0FnZ3JlZ2F0ZVJvdXRlci5qcyJdLCJuYW1lcyI6WyJCQVNFX0tFWVMiLCJQSVBFTElORV9LRVlTIiwiQUxMT1dFRF9LRVlTIiwiQWdncmVnYXRlUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImhhbmRsZUZpbmQiLCJyZXEiLCJib2R5IiwiT2JqZWN0IiwiYXNzaWduIiwiSlNPTkZyb21RdWVyeSIsInF1ZXJ5Iiwib3B0aW9ucyIsImRpc3RpbmN0IiwiU3RyaW5nIiwiaGludCIsImV4cGxhaW4iLCJwaXBlbGluZSIsImdldFBpcGVsaW5lIiwid2hlcmUiLCJKU09OIiwicGFyc2UiLCJyZXN0IiwiZmluZCIsImNvbmZpZyIsImF1dGgiLCJjbGFzc05hbWUiLCJpbmZvIiwiY2xpZW50U0RLIiwidGhlbiIsInJlc3BvbnNlIiwicmVzdWx0IiwicmVzdWx0cyIsIlVzZXJzUm91dGVyIiwicmVtb3ZlSGlkZGVuUHJvcGVydGllcyIsIkFycmF5IiwiaXNBcnJheSIsImtleXMiLCJtYXAiLCJrZXkiLCJzdGFnZSIsImxlbmd0aCIsIkVycm9yIiwiam9pbiIsInRyYW5zZm9ybVN0YWdlIiwic3RhZ2VOYW1lIiwiaW5kZXhPZiIsIlBhcnNlIiwiSU5WQUxJRF9RVUVSWSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIl9pZCIsIm9iamVjdElkIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsIm1pZGRsZXdhcmUiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVBLE1BQU1BLFNBQVMsR0FBRyxDQUFDLE9BQUQsRUFBVSxVQUFWLEVBQXNCLFVBQXRCLEVBQWtDLE1BQWxDLEVBQTBDLFNBQTFDLENBQWxCO0FBRUEsTUFBTUMsYUFBYSxHQUFHLENBQ3BCLFdBRG9CLEVBRXBCLFFBRm9CLEVBR3BCLFlBSG9CLEVB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QUF5RTtBQUN2RSxjQUFNLElBQUlFLGNBQU1MLEtBQVYsQ0FDSkssY0FBTUwsS0FBTixDQUFZTSxhQURSLEVBRUgsMERBRkcsQ0FBTjtBQUlEOztBQUNEUixNQUFBQSxLQUFLLENBQUNLLFNBQUQsQ0FBTCxDQUFpQk8sR0FBakIsR0FBdUJaLEtBQUssQ0FBQ0ssU0FBRCxDQUFMLENBQWlCUSxRQUF4QztBQUNBLGFBQU9iLEtBQUssQ0FBQ0ssU0FBRCxDQUFMLENBQWlCUSxRQUF4QjtBQUNEOztBQUNELFdBQU87QUFBRSxPQUFFLElBQUdSLFNBQVUsRUFBZixHQUFtQkwsS0FBSyxDQUFDSyxTQUFEO0FBQTFCLEtBQVA7QUFDRDs7QUFFRFMsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxDQUNFLEtBREYsRUFFRSx1QkFGRixFQUdFQyxVQUFVLENBQUNDLDZCQUhiLEVBSUVuRCxHQUFHLElBQUk7QUFDTCxhQUFPLEtBQUtELFVBQUwsQ0FBZ0JDLEdBQWhCLENBQVA7QUFDRCxLQU5IO0FBUUQ7O0FBeEhnRDs7O2VBMkhwQ0gsZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmUgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFVzZXJzUm91dGVyIGZyb20gJy4vVXNlcnNSb3V0ZXInO1xuXG5jb25zdCBCQVNFX0tFWVMgPSBbJ3doZXJlJywgJ2Rpc3RpbmN0JywgJ3BpcGVsaW5lJywgJ2hpbnQnLCAnZXhwbGFpbiddO1xuXG5jb25zdCBQSVBFTElORV9LRVlTID0gW1xuICAnYWRkRmllbGRzJyxcbiAgJ2J1Y2tldCcsXG4gICdidWNrZXRBdXRvJyxcbiAgJ2NvbGxTdGF0cycsXG4gICdjb3VudCcsXG4gICdjdXJyZW50T3AnLFxuICAnZmFjZXQnLFxuICAnZ2VvTmVhcicsXG4gICdncmFwaExvb2t1cCcsXG4gICdncm91cCcsXG4gICdpbmRleFN0YXRzJyxcbiAgJ2xpbWl0JyxcbiAgJ2xpc3RMb2NhbFNlc3Npb25zJyxcbiAgJ2xpc3RTZXNzaW9ucycsXG4gICdsb29rdXAnLFxuICAnbWF0Y2gnLFxuICAnb3V0JyxcbiAgJ3Byb2plY3QnLFxuICAncmVkYWN0JyxcbiAgJ3JlcGxhY2VSb290JyxcbiAgJ3NhbXBsZScsXG4gICdza2lwJyxcbiAgJ3NvcnQnLFxuICAnc29ydEJ5Q291bnQnLFxuICAndW53aW5kJyxcbl07XG5cbmNvbnN0IEFMTE9XRURfS0VZUyA9IFsuLi5CQVNFX0tFWVMsIC4uLlBJUEVMSU5FX0tFWVNdO1xuXG5leHBvcnQgY2xhc3MgQWdncmVnYXRlUm91dGVyIGV4dGVuZHMgQ2xhc3Nlc1JvdXRlciB7XG4gIGhhbmRsZUZpbmQocmVxKSB7XG4gICAgY29uc3QgYm9keSA9IE9iamVjdC5hc3NpZ24oXG4gICAgICByZXEuYm9keSxcbiAgICAgIENsYXNzZXNSb3V0ZXIuSlNPTkZyb21RdWVyeShyZXEucXVlcnkpXG4gICAgKTtcbiAgICBjb25zdCBvcHRpb25zID0ge307XG4gICAgaWYgKGJvZHkuZGlzdGluY3QpIHtcbiAgICAgIG9wdGlvbnMuZGlzdGluY3QgPSBTdHJpbmcoYm9keS5kaXN0aW5jdCk7XG4gICAgfVxuICAgIGlmIChib2R5LmhpbnQpIHtcbiAgICAgIG9wdGlvbnMuaGludCA9IGJvZHkuaGludDtcbiAgICAgIGRlbGV0ZSBib2R5LmhpbnQ7XG4gICAgfVxuICAgIGlmIChib2R5LmV4cGxhaW4pIHtcbiAgICAgIG9wdGlvbnMuZXhwbGFpbiA9IGJvZHkuZXhwbGFpbjtcbiAgICAgIGRlbGV0ZSBib2R5LmV4cGxhaW47XG4gICAgfVxuICAgIG9wdGlvbnMucGlwZWxpbmUgPSBBZ2dyZWdhdGVSb3V0ZXIuZ2V0UGlwZWxpbmUoYm9keSk7XG4gICAgaWYgKHR5cGVvZiBib2R5LndoZXJlID09PSAnc3RyaW5nJykge1xuICAgICAgYm9keS53aGVyZSA9IEpTT04ucGFyc2UoYm9keS53aGVyZSk7XG4gICAgfVxuICAgIHJldHVybiByZXN0XG4gICAgICAuZmluZChcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGgsXG4gICAgICAgIHRoaXMuY2xhc3NOYW1lKHJlcSksXG4gICAgICAgIGJvZHkud2hlcmUsXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICAgKVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IHJlc3VsdCBvZiByZXNwb25zZS5yZXN1bHRzKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBVc2Vyc1JvdXRlci5yZW1vdmVIaWRkZW5Qcm9wZXJ0aWVzKHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlIH07XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qIEJ1aWxkcyBhIHBpcGVsaW5lIGZyb20gdGhlIGJvZHkuIE9yaWdpbmFsbHkgdGhlIGJvZHkgY291bGQgYmUgcGFzc2VkIGFzIGEgc2luZ2xlIG9iamVjdCxcbiAgICogYW5kIG5vdyB3ZSBzdXBwb3J0IG1hbnkgb3B0aW9uc1xuICAgKlxuICAgKiBBcnJheVxuICAgKlxuICAgKiBib2R5OiBbe1xuICAgKiAgIGdyb3VwOiB7IG9iamVjdElkOiAnJG5hbWUnIH0sXG4gICAqIH1dXG4gICAqXG4gICAqIE9iamVjdFxuICAgKlxuICAgKiBib2R5OiB7XG4gICAqICAgZ3JvdXA6IHsgb2JqZWN0SWQ6ICckbmFtZScgfSxcbiAgICogfVxuICAgKlxuICAgKlxuICAgKiBQaXBlbGluZSBPcGVyYXRvciB3aXRoIGFuIEFycmF5IG9yIGFuIE9iamVjdFxuICAgKlxuICAgKiBib2R5OiB7XG4gICAqICAgcGlwZWxpbmU6IHtcbiAgICogICAgIGdyb3VwOiB7IG9iamVjdElkOiAnJG5hbWUnIH0sXG4gICAqICAgfVxuICAgKiB9XG4gICAqXG4gICAqL1xuICBzdGF0aWMgZ2V0UGlwZWxpbmUoYm9keSkge1xuICAgIGxldCBwaXBlbGluZSA9IGJvZHkucGlwZWxpbmUgfHwgYm9keTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICBwaXBlbGluZSA9IE9iamVjdC5rZXlzKHBpcGVsaW5lKS5tYXAoa2V5ID0+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..d420107941 --- /dev/null +++ b/lib/Routers/ClassesRouter.js @@ -0,0 +1,229 @@ +"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', 'excludeKeys', '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.excludeKeys == 'string') { + options.excludeKeys = body.excludeKeys; + } + + 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', 'hint', 'explain']; + + 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; + } + + if (body.hint && (typeof body.hint === 'string' || typeof body.hint === 'object')) { + options.hint = body.hint; + } + + if (body.explain) { + options.explain = body.explain; + } + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0NsYXNzZXNSb3V0ZXIuanMiXSwibmFtZXMiOlsiQUxMT1dFRF9HRVRfUVVFUllfS0VZUyIsIkNsYXNzZXNSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwiY2xhc3NOYW1lIiwicmVxIiwicGFyYW1zIiwiaGFuZGxlRmluZCIsImJvZHkiLCJPYmplY3QiLCJhc3NpZ24iLCJKU09ORnJvbVF1ZXJ5IiwicXVlcnkiLCJvcHRpb25zIiwib3B0aW9uc0Zyb21Cb2R5IiwiY29uZmlnIiwibWF4TGltaXQiLCJsaW1pdCIsIk51bWJlciIsInJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5IiwiU3RyaW5nIiwid2hlcmUiLCJKU09OIiwicGFyc2UiLCJyZXN0IiwiZmluZCIsImF1dGgiLCJpbmZvIiwiY2xpZW50U0RLIiwidGhlbiIsInJlc3BvbnNlIiwiaGFuZGxlR2V0Iiwia2V5Iiwia2V5cyIsImluZGV4T2YiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9RVUVSWSIsImluY2x1ZGUiLCJleGNsdWRlS2V5cyIsInJlYWRQcmVmZXJlbmNlIiwiaW5jbHVkZVJlYWRQcmVmZXJlbmNlIiwic3VicXVlcnlSZWFkUHJlZmVyZW5jZSIsImdldCIsIm9iamVjdElkIiwicmVzdWx0cyIsImxlbmd0aCIsIk9CSkVDVF9OT1RfRk9VTkQiLCJzZXNzaW9uVG9rZW4iLCJ1c2VyIiwiaWQiLCJoYW5kbGVDcmVhdGUiLCJjcmVhdGUiLCJoYW5kbGVVcGRhdGUiLCJ1cGRhdGUiLCJoYW5kbGVEZWxldGUiLCJkZWwiLCJqc29uIiwidmFsdWUiLCJfIiwiZW50cmllcyIsImUiLCJhbGxvd0NvbnN0cmFpbnRzIiwic2tpcCIsIm9yZGVyIiwiY291bnQiLCJpbmNsdWRlQWxsIiwiaGludCIsImV4cGxhaW4iLCJtb3VudFJvdXRlcyIsInJvdXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxNQUFNQSxzQkFBc0IsR0FB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LE9BQXZCO0FBQ0Q7O0FBQ0QsV0FBT3ZELE9BQVA7QUFDRDs7QUFFRHdELEVBQUFBLFdBQVcsR0FBRztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxLQUFYLEVBQWtCLHFCQUFsQixFQUF5Q2pFLEdBQUcsSUFBSTtBQUM5QyxhQUFPLEtBQUtFLFVBQUwsQ0FBZ0JGLEdBQWhCLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS2lFLEtBQUwsQ0FBVyxLQUFYLEVBQWtCLCtCQUFsQixFQUFtRGpFLEdBQUcsSUFBSTtBQUN4RCxhQUFPLEtBQUswQixTQUFMLENBQWUxQixHQUFmLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS2lFLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLHFCQUFuQixFQUEwQ2pFLEdBQUcsSUFBSTtBQUMvQyxhQUFPLEtBQUs4QyxZQUFMLENBQWtCOUMsR0FBbEIsQ0FBUDtBQUNELEtBRkQ7QUFHQSxTQUFLaUUsS0FBTCxDQUFXLEtBQVgsRUFBa0IsK0JBQWxCLEVBQW1EakUsR0FBRyxJQUFJO0FBQ3hELGFBQU8sS0FBS2dELFlBQUwsQ0FBa0JoRCxHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUtpRSxLQUFMLENBQVcsUUFBWCxFQUFxQiwrQkFBckIsRUFBc0RqRSxHQUFHLElBQUk7QUFDM0QsYUFBTyxLQUFLa0QsWUFBTCxDQUFrQmxELEdBQWxCLENBQVA7QUFDRCxLQUZEO0FBR0Q7O0FBalA4Qzs7O2VBb1BsQ0gsYSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuXG5jb25zdCBBTExPV0VEX0dFVF9RVUVSWV9LRVlTID0gW1xuICAna2V5cycsXG4gICdpbmNsdWRlJyxcbiAgJ2V4Y2x1ZGVLZXlzJyxcbiAgJ3JlYWRQcmVmZXJlbmNlJyxcbiAgJ2luY2x1ZGVSZWFkUHJlZmVyZW5jZScsXG4gICdzdWJxdWVyeVJlYWRQcmVmZXJlbmNlJyxcbl07XG5cbmV4cG9ydCBjbGFzcyBDbGFzc2VzUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIGNsYXNzTmFtZShyZXEpIHtcbiAgICByZXR1cm4gcmVxLnBhcmFtcy5jbGFzc05hbWU7XG4gIH1cblxuICBoYW5kbGVGaW5kKHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKFxuICAgICAgcmVxLmJvZHksXG4gICAgICBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KVxuICAgICk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IENsYXNzZXNSb3V0ZXIub3B0aW9uc0Zyb21Cb2R5KGJvZHkpO1xuICAgIGlmIChyZXEuY29uZmlnLm1heExpbWl0ICYmIGJvZHkubGltaXQgPiByZXEuY29uZmlnLm1heExpbWl0KSB7XG4gICAgICAvLyBTaWxlbnRseSByZXBsYWNlIHRoZSBsaW1pdCBvbiB0aGUgcXVlcnkgd2l0aCB0aGUgbWF4IGNvbmZpZ3VyZWRcbiAgICAgIG9wdGlvbnMubGltaXQgPSBOdW1iZXIocmVxLmNvbmZpZy5tYXhMaW1pdCk7XG4gICAgfVxuICAgIGlmIChib2R5LnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5KSB7XG4gICAgICBvcHRpb25zLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5ID0gU3RyaW5nKGJvZHkucmVkaXJlY3RDbGFzc05hbWVGb3JLZXkpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkud2hlcmUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBib2R5LndoZXJlID0gSlNPTi5wYXJzZShib2R5LndoZXJlKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3RcbiAgICAgIC5maW5kKFxuICAgICAgICByZXEuY29uZmlnLFxuICAgICAgICByZXEuYXV0aCxcbiAgICAgICAgdGhpcy5jbGFzc05hbWUocmVxKSxcbiAgICAgICAgYm9keS53aGVyZSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgICApXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiByZXNwb25zZSB9O1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSB7cmVzcG9uc2V9IG9iamVjdC5cbiAgaGFuZGxlR2V0KHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKFxuICAgICAgcmVxLmJvZHksXG4gICAgICBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KVxuICAgICk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoYm9keSkpIHtcbiAgICAgIGlmIChBTExPV0VEX0dFVF9RVUVSWV9LRVlTLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgJ0ltcHJvcGVyIGVuY29kZSBvZiBwYXJhbWV0ZXInXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBib2R5LmtleXMgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLmtleXMgPSBib2R5LmtleXM7XG4gICAgfVxuICAgIGlmIChib2R5LmluY2x1ZGUpIHtcbiAgICAgIG9wdGlvbnMuaW5jbHVkZSA9IFN0cmluZyhib2R5LmluY2x1ZGUpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkuZXhjbHVkZUtleXMgPT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMuZXhjbHVkZUtleXMgPSBib2R5LmV4Y2x1ZGVLZXlzO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkucmVhZFByZWZlcmVuY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gYm9keS5yZWFkUHJlZmVyZW5jZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LmluY2x1ZGVSZWFkUHJlZmVyZW5jZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMuaW5jbHVkZVJlYWRQcmVmZXJlbmNlID0gYm9keS5pbmNsdWRlUmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYm9keS5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID09PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID0gYm9keS5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICAgIH1cblxuICAgIHJldHVybiByZXN0XG4gICAgICAuZ2V0KFxuICAgICAgICByZXEuY29uZmlnLFxuICAgICAgICByZXEuYXV0aCxcbiAgICAgICAgdGhpcy5jbGFzc05hbWUocmVxKSxcbiAgICAgICAgcmVxLnBhcmFtcy5vYmplY3RJZCxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgICApXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIGlmICghcmVzcG9uc2UucmVzdWx0cyB8fCByZXNwb25zZS5yZXN1bHRzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICdPYmplY3Qgbm90IGZvdW5kLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuY2xhc3NOYW1lKHJlcSkgPT09ICdfVXNlcicpIHtcbiAgICAgICAgICBkZWxldGUgcmVzcG9uc2UucmVzdWx0c1swXS5zZXNzaW9uVG9rZW47XG5cbiAgICAgICAgICBjb25zdCB1c2VyID0gcmVzcG9uc2UucmVzdWx0c1swXTtcblxuICAgICAgICAgIGlmIChyZXEuYXV0aC51c2VyICYmIHVzZXIub2JqZWN0SWQgPT0gcmVxLmF1dGgudXNlci5pZCkge1xuICAgICAgICAgICAgLy8gRm9yY2UgdGhlIHNlc3Npb24gdG9rZW5cbiAgICAgICAgICAgIHJlc3BvbnNlLnJlc3VsdHNbMF0uc2Vzc2lvblRva2VuID0gcmVxLmluZm8uc2Vzc2lvblRva2VuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyByZXNwb25zZTogcmVzcG9uc2UucmVzdWx0c1swXSB9O1xuICAgICAgfSk7XG4gIH1cblxuICBoYW5kbGVDcmVhdGUocmVxKSB7XG4gICAgcmV0dXJuIHJlc3QuY3JlYXRlKFxuICAgICAgcmVxLmNvbmZpZyxcbiAgICAgIHJlcS5hdXRoLFxuICAgICAgdGhpcy5jbGFzc05hbWUocmVxKSxcbiAgICAgIHJlcS5ib2R5LFxuICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgKTtcbiAgfVxuXG4gIGhhbmRsZVVwZGF0ZShyZXEpIHtcbiAgICBjb25zdCB3aGVyZSA9IHsgb2JqZWN0SWQ6IHJlcS5wYXJhbXMub2JqZWN0SWQgfTtcbiAgICByZXR1cm4gcmVzdC51cGRhdGUoXG4gICAgICByZXEuY29uZmlnLFxuICAgICAgcmVxLmF1dGgsXG4gICAgICB0aGlzLmNsYXNzTmFtZShyZXEpLFxuICAgICAgd2hlcmUsXG4gICAgICByZXEuYm9keSxcbiAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICk7XG4gIH1cblxuICBoYW5kbGVEZWxldGUocmVxKSB7XG4gICAgcmV0dXJuIHJlc3RcbiAgICAgIC5kZWwoXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIHJlcS5hdXRoLFxuICAgICAgICB0aGlzLmNsYXNzTmFtZShyZXEpLFxuICAgICAgICByZXEucGFyYW1zLm9iamVjdElkLFxuICAgICAgICByZXEuaW5mby5jbGllbnRTREtcbiAgICAgIClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHt9IH07XG4gICAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBKU09ORnJvbVF1ZXJ5KHF1ZXJ5KSB7XG4gICAgY29uc3QganNvbiA9IHt9O1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIF8uZW50cmllcyhxdWVyeSkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGpzb25ba2V5XSA9IEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBqc29uW2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGpzb247XG4gIH1cblxuICBzdGF0aWMgb3B0aW9uc0Zyb21Cb2R5KGJvZHkpIHtcbiAgICBjb25zdCBhbGxvd0NvbnN0cmFpbnRzID0gW1xuICAgICAgJ3NraXAnLFxuICAgICAgJ2xpbWl0JyxcbiAgICAgICdvcmRlcicsXG4gICAgICAnY291bnQnLFxuICAgICAgJ2tleXMnLFxuICAgICAgJ2V4Y2x1ZGVLZXlzJyxcbiAgICAgICdpbmNsdWRlJyxcbiAgICAgICdpbmNsdWRlQWxsJyxcbiAgICAgICdyZWRpcmVjdENsYXNzTmFtZUZvcktleScsXG4gICAgICAnd2hlcmUnLFxuICAgICAgJ3JlYWRQcmVmZXJlbmNlJyxcbiAgICAgICdpbmNsdWRlUmVhZFByZWZlcmVuY2UnLFxuICAgICAgJ3N1YnF1ZXJ5UmVhZFByZWZlcmVuY2UnLFxuICAgICAgJ2hpbnQnLFxuICAgICAgJ2V4cGxhaW4nLFxuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhib2R5KSkge1xuICAgICAgaWYgKGFsbG93Q29uc3RyYWludHMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgICBgSW52YWxpZCBwYXJhbWV0ZXIgZm9yIHF1ZXJ5OiAke2tleX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IG9wdGlvbnMgPSB7fTtcbiAgICBpZiAoYm9keS5za2lwKSB7XG4gICAgICBvcHRpb25zLnNraXAgPSBOdW1iZXIoYm9keS5za2lwKTtcbiAgICB9XG4gICAgaWYgKGJvZHkubGltaXQgfHwgYm9keS5saW1pdCA9PT0gMCkge1xuICAgICAgb3B0aW9ucy5saW1pdCA9IE51bWJlcihib2R5LmxpbWl0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3B0aW9ucy5saW1pdCA9IE51bWJlcigxMDApO1xuICAgIH1cbiAgICBpZiAoYm9keS5vcmRlcikge1xuICAgICAgb3B0aW9ucy5vcmRlciA9IFN0cmluZyhib2R5Lm9yZGVyKTtcbiAgICB9XG4gICAgaWYgKGJvZHkuY291bnQpIHtcbiAgICAgIG9wdGlvbnMuY291bnQgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkua2V5cyA9PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5rZXlzID0gYm9keS5rZXlzO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkuZXhjbHVkZUtleXMgPT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMuZXhjbHVkZUtleXMgPSBib2R5LmV4Y2x1ZGVLZXlzO1xuICAgIH1cbiAgICBpZiAoYm9keS5pbmNsdWRlKSB7XG4gICAgICBvcHRpb25zLmluY2x1ZGUgPSBTdHJpbmcoYm9keS5pbmNsdWRlKTtcbiAgICB9XG4gICAgaWYgKGJvZHkuaW5jbHVkZUFsbCkge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlQWxsID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LnJlYWRQcmVmZXJlbmNlID09PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IGJvZHkucmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYm9keS5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZSA9IGJvZHkuaW5jbHVkZVJlYWRQcmVmZXJlbmNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IGJvZHkuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgYm9keS5oaW50ICYmXG4gICAgICAodHlwZW9mIGJvZHkuaGludCA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGJvZHkuaGludCA9PT0gJ29iamVjdCcpXG4gICAgKSB7XG4gICAgICBvcHRpb25zLmhpbnQgPSBib2R5LmhpbnQ7XG4gICAgfVxuICAgIGlmIChib2R5LmV4cGxhaW4pIHtcbiAgICAgIG9wdGlvbnMuZXhwbGFpbiA9IGJvZHkuZXhwbGFpbjtcbiAgICB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL2NsYXNzZXMvOmNsYXNzTmFtZScsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUdldChyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2NsYXNzZXMvOmNsYXNzTmFtZScsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVDcmVhdGUocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCAnL2NsYXNzZXMvOmNsYXNzTmFtZS86b2JqZWN0SWQnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlVXBkYXRlKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnREVMRVRFJywgJy9jbGFzc2VzLzpjbGFzc05hbWUvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZURlbGV0ZShyZXEpO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IENsYXNzZXNSb3V0ZXI7XG4iXX0= \ 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/ExportRouter.js b/lib/Routers/ExportRouter.js new file mode 100644 index 0000000000..1220584f9c --- /dev/null +++ b/lib/Routers/ExportRouter.js @@ -0,0 +1,231 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.ExportRouter = void 0; + +var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter")); + +var _AdapterLoader = require("../Adapters/AdapterLoader"); + +var _rest = _interopRequireDefault(require("../rest")); + +var _archiver = _interopRequireDefault(require("archiver")); + +var _tmp = _interopRequireDefault(require("tmp")); + +var _fs = _interopRequireDefault(require("fs")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const DefaultExportExportProgressCollectionName = '_ExportProgress'; +const relationSchema = { + fields: { + relatedId: { + type: 'String' + }, + owningId: { + type: 'String' + } + } +}; + +class ExportRouter extends _PromiseRouter.default { + exportClassPage(req, className, jsonFileStream, where, skip, limit) { + const databaseController = req.config.database; + const options = { + skip, + limit + }; + let findPromise; + + if (className.indexOf('_Join') === 0) { + findPromise = databaseController.adapter.find(className, relationSchema, where, options); + } else { + findPromise = _rest.default.find(req.config, req.auth, className, where, options); + } + + return findPromise.then(data => { + if (Array.isArray(data)) { + data = { + results: data.map(obj => { + // Needed to avoid errors during import. + // See more: https://docs.parseplatform.org/js/guide/#error-codes + // Deletes invalid keys in order to avoid "ParseError: 105 Invalid field name" + // when importing + Object.keys(obj).forEach(key => { + if (key.startsWith('_')) { + delete obj[key]; + } + }); + return obj; + }) + }; + } + + if (skip && data.results.length) { + jsonFileStream.write(',\n'); + } + + jsonFileStream.write(JSON.stringify(data.results, null, 2).substr(1).slice(0, -1)); + }); + } + + exportClass(req, data) { + const databaseController = req.config.database; + + const tmpJsonFile = _tmp.default.fileSync(); + + const jsonFileStream = _fs.default.createWriteStream(tmpJsonFile.name); + + jsonFileStream.write('{\n"results" : [\n'); + const hasJoin = data.name.indexOf('_Join') === 0; + let findPromise = null; + + if (hasJoin) { + findPromise = databaseController.adapter.count(data.name, relationSchema, data.where); + } else { + findPromise = _rest.default.find(req.config, req.auth, data.name, data.where, { + count: true, + limit: 0 + }); + } + + return findPromise.then(result => { + if (Number.isInteger(result)) { + result = { + count: result + }; + } + + let i = 0; + const pageLimit = 1000; + let promise = Promise.resolve(); + + for (i = 0; i < result.count; i += pageLimit) { + const skip = i; + promise = promise.then(() => { + return this.exportClassPage(req, data.name, jsonFileStream, data.where, skip, pageLimit); + }); + } + + return promise; + }).then(() => { + jsonFileStream.end(']\n}'); + return new Promise(resolve => { + jsonFileStream.on('close', () => { + tmpJsonFile._name = `${data.name.replace(/:/g, '꞉')}.json`; + resolve(tmpJsonFile); + }); + }); + }); + } + + handleExportProgress(req) { + const databaseController = req.config.database; + const query = { + masterKey: req.info.masterKey, + applicationId: req.info.appId + }; + return databaseController.find(DefaultExportExportProgressCollectionName, query).then(response => { + return { + response + }; + }); + } + + handleExport(req) { + const databaseController = req.config.database; + const emailControllerAdapter = (0, _AdapterLoader.loadAdapter)(req.config.emailAdapter); + + if (!emailControllerAdapter) { + return Promise.reject(new Error('You have to setup a Mail Adapter.')); + } + + const exportProgress = { + id: req.body.name, + masterKey: req.info.masterKey, + applicationId: req.info.appId + }; + databaseController.create(DefaultExportExportProgressCollectionName, exportProgress).then(() => { + return databaseController.loadSchema({ + clearCache: true + }); + }).then(schemaController => schemaController.getOneSchema(req.body.name, true)).then(schema => { + const classNames = [req.body.name]; + Object.keys(schema.fields).forEach(fieldName => { + const field = schema.fields[fieldName]; + + if (field.type === 'Relation') { + classNames.push(`_Join:${fieldName}:${req.body.name}`); + } + }); + const promisses = classNames.map(name => { + return this.exportClass(req, { + name + }); + }); + return Promise.all(promisses); + }).then(jsonFiles => { + return new Promise(resolve => { + const tmpZipFile = _tmp.default.fileSync(); + + const tmpZipStream = _fs.default.createWriteStream(tmpZipFile.name); + + const zip = (0, _archiver.default)('zip'); + zip.pipe(tmpZipStream); + jsonFiles.forEach(tmpJsonFile => { + zip.append(_fs.default.readFileSync(tmpJsonFile.name), { + name: tmpJsonFile._name + }); + tmpJsonFile.removeCallback(); + }); + zip.finalize(); + tmpZipStream.on('close', () => { + const buf = _fs.default.readFileSync(tmpZipFile.name); + + tmpZipFile.removeCallback(); + resolve(buf); + }); + }); + }).then(zippedFile => { + const filesController = req.config.filesController; + return filesController.createFile(req.config, req.body.name, zippedFile, 'application/zip'); + }).then(fileData => { + return emailControllerAdapter.sendMail({ + text: `We have successfully exported your data from the class ${req.body.name}.\n + Please download from ${fileData.url}`, + link: fileData.url, + to: req.body.feedbackEmail, + subject: 'Export completed' + }); + }).catch(error => { + return emailControllerAdapter.sendMail({ + text: `We could not export your data to the class ${req.body.name}. Error: ${error}`, + to: req.body.feedbackEmail, + subject: 'Export failed' + }); + }).then(() => { + return databaseController.destroy(DefaultExportExportProgressCollectionName, exportProgress); + }); + return Promise.resolve({ + response: 'We are exporting your data. You will be notified by e-mail once it is completed.' + }); + } + + mountRoutes() { + this.route('PUT', '/export_data', req => { + return this.handleExport(req); + }); + this.route('GET', '/export_progress', req => { + return this.handleExportProgress(req); + }); + } + +} + +exports.ExportRouter = ExportRouter; +var _default = ExportRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0V4cG9ydFJvdXRlci5qcyJdLCJuYW1lcyI6WyJEZWZhdWx0RXhwb3J0RXhwb3J0UHJvZ3Jlc3NDb2xsZWN0aW9uTmFtZSIsInJlbGF0aW9uU2NoZW1hIiwiZmllbGRzIiwicmVsYXRlZElkIiwidHlwZSIsIm93bmluZ0lkIiwiRXhwb3J0Um91dGVyIiwiUHJvbWlzZVJvdXRlciIsImV4cG9ydENsYXNzUGFnZSIsInJlcSIsImNsYXNzTmFtZSIsImpzb25GaWxlU3RyZWFtIiwid2hlcmUiLCJza2lwIiwibGltaXQiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJjb25maWciLCJkYXRhYmFzZSIsIm9wdGlvbnMiLCJmaW5kUHJvbWlzZSIsImluZGV4T2YiLCJhZGFwdGVyIiwiZmluZCIsInJlc3QiLCJhdXRoIiwidGhlbiIsImRhdGEiLCJBcnJheSIsImlzQXJyYXkiLCJyZXN1bHRzIiwibWFwIiwib2JqIiwiT2JqZWN0Iiwia2V5cyIsImZvckVhY2giLCJrZXkiLCJzdGFydHNXaXRoIiwibGVuZ3RoIiwid3JpdGUiLCJKU09OIiwic3RyaW5naWZ5Iiwic3Vic3RyIiwic2xpY2UiLCJleHBvcnRDbGFzcyIsInRtcEpzb25GaWxlIiwidG1wIiwiZmlsZVN5bmMiLCJmcyIsImNyZWF0ZVdyaXRlU3RyZWFtIiwibmFtZSIsImhhc0pvaW4iLCJjb3VudCIsInJlc3VsdCIsIk51bWJlciIsImlzSW50ZWdlciIsImkiLCJwYWdlTGltaXQiLCJwcm9taXNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJlbmQiLCJvbiIsIl9uYW1lIiwicmVwbGFjZSIsImhhbmRsZUV4cG9ydFByb2dyZXNzIiwicXVlcnkiLCJtYXN0ZXJLZXkiLCJpbmZvIiwiYXBwbGljYXRpb25JZCIsImFwcElkIiwicmVzcG9uc2UiLCJoYW5kbGVFeHBvcnQiLCJlbWFpbENvbnRyb2xsZXJBZGFwdGVyIiwiZW1haWxBZGFwdGVyIiwicmVqZWN0IiwiRXJyb3IiLCJleHBvcnRQcm9ncmVzcyIsImlkIiwiYm9keSIsImNyZWF0ZSIsImxvYWRTY2hlbWEiLCJjbGVhckNhY2hlIiwic2NoZW1hQ29udHJvbGxlciIsImdldE9uZVNjaGVtYSIsInNjaGVtYSIsImNsYXNzTmFtZXMiLCJmaWVsZE5hbWUiLCJmaWVsZCIsInB1c2giLCJwcm9taXNzZXMiLCJhbGwiLCJqc29uRmlsZXMiLCJ0bXBaaXBGaWxlIiwidG1wWmlwU3RyZWFtIiwiemlwIiwicGlwZSIsImFwcGVuZCIsInJlYWRGaWxlU3luYyIsInJlbW92ZUNhbGxiYWNrIiwiZmluYWxpemUiLCJidWYiLCJ6aXBwZWRGaWxlIiwiZmlsZXNDb250cm9sbGVyIiwiY3JlYXRlRmlsZSIsImZpbGVEYXRhIiwic2VuZE1haWwiLCJ0ZXh0IiwidXJsIiwibGluayIsInRvIiwiZmVlZGJhY2tFbWFpbCIsInN1YmplY3QiLCJjYXRjaCIsImVycm9yIiwiZGVzdHJveSIsIm1vdW50Um91dGVzIiwicm91dGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLHlDQUF5QyxHQUFHLGlCQUFsRDtBQUNBLE1BQU1DLGNBQWMsR0FBRztBQUNyQkMsRUFBQUEsTUFBTSxFQUFFO0FBQUVDLElBQUFBLFNBQVMsRUFBRTtBQUFFQyxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUFiO0FBQWlDQyxJQUFBQSxRQUFRLEVBQUU7QUFBRUQsTUFBQUEsSUFBSSxFQUFFO0FBQVI7QUFBM0M7QUFEYSxDQUF2Qjs7QUFJTyxNQUFNRSxZQUFOLFNBQTJCQyxzQkFBM0IsQ0FBeUM7QUFDOUNDLEVBQUFBLGVBQWUsQ0FBQ0MsR0FBRCxFQUFNQyxTQUFOLEVBQWlCQyxjQUFqQixFQUFpQ0MsS0FBakMsRUFBd0NDLElBQXhDLEVBQThDQyxLQUE5QyxFQUFxRDtBQUNsRSxVQUFNQyxrQkFBa0IsR0FBR04sR0FBRyxDQUFDTyxNQUFKLENBQVdDLFFBQXRDO0FBRUEsVUFBTUMsT0FBTyxHQUFHO0FBQ2RM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RkQ7QUFHRDs7QUE1TzZDOzs7ZUErT2pDSCxZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgeyBsb2FkQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0FkYXB0ZXJMb2FkZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgYXJjaGl2ZXIgZnJvbSAnYXJjaGl2ZXInO1xuaW1wb3J0IHRtcCBmcm9tICd0bXAnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcblxuY29uc3QgRGVmYXVsdEV4cG9ydEV4cG9ydFByb2dyZXNzQ29sbGVjdGlvbk5hbWUgPSAnX0V4cG9ydFByb2dyZXNzJztcbmNvbnN0IHJlbGF0aW9uU2NoZW1hID0ge1xuICBmaWVsZHM6IHsgcmVsYXRlZElkOiB7IHR5cGU6ICdTdHJpbmcnIH0sIG93bmluZ0lkOiB7IHR5cGU6ICdTdHJpbmcnIH0gfSxcbn07XG5cbmV4cG9ydCBjbGFzcyBFeHBvcnRSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgZXhwb3J0Q2xhc3NQYWdlKHJlcSwgY2xhc3NOYW1lLCBqc29uRmlsZVN0cmVhbSwgd2hlcmUsIHNraXAsIGxpbWl0KSB7XG4gICAgY29uc3QgZGF0YWJhc2VDb250cm9sbGVyID0gcmVxLmNvbmZpZy5kYXRhYmFzZTtcblxuICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICBza2lwLFxuICAgICAgbGltaXQsXG4gICAgfTtcblxuICAgIGxldCBmaW5kUHJvbWlzZTtcbiAgICBpZiAoY2xhc3NOYW1lLmluZGV4T2YoJ19Kb2luJykgPT09IDApIHtcbiAgICAgIGZpbmRQcm9taXNlID0gZGF0YWJhc2VDb250cm9sbGVyLmFkYXB0ZXIuZmluZChcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICByZWxhdGlvblNjaGVtYSxcbiAgICAgICAgd2hlcmUsXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZpbmRQcm9taXNlID0gcmVzdC5maW5kKHJlcS5jb25maWcsIHJlcS5hdXRoLCBjbGFzc05hbWUsIHdoZXJlLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmluZFByb21pc2UudGhlbihkYXRhID0+IHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgIGRhdGEgPSB7XG4gICAgICAgICAgcmVzdWx0czogZGF0YS5tYXAob2JqID0+IHtcbiAgICAgICAgICAgIC8vIE5lZWRlZCB0byBhdm9pZCBlcnJvcnMgZHVyaW5nIGltcG9ydC5cbiAgICAgICAgICAgIC8vIFNlZSBtb3JlOiBodHRwczovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvanMvZ3VpZGUvI2Vycm9yLWNvZGVzXG5cbiAgICAgICAgICAgIC8vIERlbGV0ZXMgaW52YWxpZCBrZXlzIGluIG9yZGVyIHRvIGF2b2lkIFwiUGFyc2VFcnJvcjogMTA1IEludmFsaWQgZmllbGQgbmFtZVwiXG4gICAgICAgICAgICAvLyB3aGVuIGltcG9ydGluZ1xuICAgICAgICAgICAgT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgIGlmIChrZXkuc3RhcnRzV2l0aCgnXycpKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG9ialtrZXldO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBvYmo7XG4gICAgICAgICAgfSksXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGlmIChza2lwICYmIGRhdGEucmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgICAganNvbkZpbGVTdHJlYW0ud3JpdGUoJyxcXG4nKTtcbiAgICAgIH1cblxuICAgICAganNvbkZpbGVTdHJlYW0ud3JpdGUoXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGRhdGEucmVzdWx0cywgbnVsbCwgMilcbiAgICAgICAgICAuc3Vic3RyKDEpXG4gICAgICAgICAgLnNsaWNlKDAsIC0xKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIGV4cG9ydENsYXNzKHJlcSwgZGF0YSkge1xuICAgIGNvbnN0IGRhdGFiYXNlQ29udHJvbGxlciA9IHJlcS5jb25maWcuZGF0YWJhc2U7XG4gICAgY29uc3QgdG1wSnNvbkZpbGUgPSB0bXAuZmlsZVN5bmMoKTtcbiAgICBjb25zdCBqc29uRmlsZVN0cmVhbSA9IGZzLmNyZWF0ZVdyaXRlU3RyZWFtKHRtcEpzb25GaWxlLm5hbWUpO1xuXG4gICAganNvbkZpbGVTdHJlYW0ud3JpdGUoJ3tcXG5cInJlc3VsdHNcIiA6IFtcXG4nKTtcbiAgICBjb25zdCBoYXNKb2luID0gZGF0YS5uYW1lLmluZGV4T2YoJ19Kb2luJykgPT09IDA7XG4gICAgbGV0IGZpbmRQcm9taXNlID0gbnVsbDtcbiAgICBpZiAoaGFzSm9pbikge1xuICAgICAgZmluZFByb21pc2UgPSBkYXRhYmFzZUNvbnRyb2xsZXIuYWRhcHRlci5jb3VudChcbiAgICAgICAgZGF0YS5uYW1lLFxuICAgICAgICByZWxhdGlvblNjaGVtYSxcbiAgICAgICAgZGF0YS53aGVyZVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZmluZFByb21pc2UgPSByZXN0LmZpbmQocmVxLmNvbmZpZywgcmVxLmF1dGgsIGRhdGEubmFtZSwgZGF0YS53aGVyZSwge1xuICAgICAgICBjb3VudDogdHJ1ZSxcbiAgICAgICAgbGltaXQ6IDAsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmluZFByb21pc2VcbiAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHJlc3VsdCkpIHtcbiAgICAgICAgICByZXN1bHQgPSB7IGNvdW50OiByZXN1bHQgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgY29uc3QgcGFnZUxpbWl0ID0gMTAwMDtcbiAgICAgICAgbGV0IHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVzdWx0LmNvdW50OyBpICs9IHBhZ2VMaW1pdCkge1xuICAgICAgICAgIGNvbnN0IHNraXAgPSBpO1xuICAgICAgICAgIHByb21pc2UgPSBwcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhwb3J0Q2xhc3NQYWdlKFxuICAgICAgICAgICAgICByZXEsXG4gICAgICAgICAgICAgIGRhdGEubmFtZSxcbiAgICAgICAgICAgICAganNvbkZpbGVTdHJlYW0sXG4gICAgICAgICAgICAgIGRhdGEud2hlcmUsXG4gICAgICAgICAgICAgIHNraXAsXG4gICAgICAgICAgICAgIHBhZ2VMaW1pdFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAganNvbkZpbGVTdHJlYW0uZW5kKCddXFxufScpO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICBqc29uRmlsZVN0cmVhbS5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICAgICAgICB0bXBKc29uRmlsZS5fbmFtZSA9IGAke2RhdGEubmFtZS5yZXBsYWNlKC86L2csICfqnoknKX0uanNvbmA7XG5cbiAgICAgICAgICAgIHJlc29sdmUodG1wSnNvbkZpbGUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlRXhwb3J0UHJvZ3Jlc3MocmVxKSB7XG4gICAgY29uc3QgZGF0YWJhc2VDb250cm9sbGVyID0gcmVxLmNvbmZpZy5kYXRhYmFzZTtcblxuICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgbWFzdGVyS2V5OiByZXEuaW5mby5tYXN0ZXJLZXksXG4gICAgICBhcHBsaWNhdGlvbklkOiByZXEuaW5mby5hcHBJZCxcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRhdGFiYXNlQ29udHJvbGxlclxuICAgICAgLmZpbmQoRGVmYXVsdEV4cG9ydEV4cG9ydFByb2dyZXNzQ29sbGVjdGlvbk5hbWUsIHF1ZXJ5KVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICByZXR1cm4geyByZXNwb25zZSB9O1xuICAgICAgfSk7XG4gIH1cblxuICBoYW5kbGVFeHBvcnQocmVxKSB7XG4gICAgY29uc3QgZGF0YWJhc2VDb250cm9sbGVyID0gcmVxLmNvbmZpZy5kYXRhYmFzZTtcblxuICAgIGNvbnN0IGVtYWlsQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihyZXEuY29uZmlnLmVtYWlsQWRhcHRlcik7XG5cbiAgICBpZiAoIWVtYWlsQ29udHJvbGxlckFkYXB0ZXIpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1lvdSBoYXZlIHRvIHNldHVwIGEgTWFpbCBBZGFwdGVyLicpKTtcbiAgICB9XG5cbiAgICBjb25zdCBleHBvcnRQcm9ncmVzcyA9IHtcbiAgICAgIGlkOiByZXEuYm9keS5uYW1lLFxuICAgICAgbWFzdGVyS2V5OiByZXEuaW5mby5tYXN0ZXJLZXksXG4gICAgICBhcHBsaWNhdGlvbklkOiByZXEuaW5mby5hcHBJZCxcbiAgICB9O1xuXG4gICAgZGF0YWJhc2VDb250cm9sbGVyXG4gICAgICAuY3JlYXRlKERlZmF1bHRFeHBvcnRFeHBvcnRQcm9ncmVzc0NvbGxlY3Rpb25OYW1lLCBleHBvcnRQcm9ncmVzcylcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIGRhdGFiYXNlQ29udHJvbGxlci5sb2FkU2NoZW1hKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+XG4gICAgICAgIHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKHJlcS5ib2R5Lm5hbWUsIHRydWUpXG4gICAgICApXG4gICAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgICBjb25zdCBjbGFzc05hbWVzID0gW3JlcS5ib2R5Lm5hbWVdO1xuICAgICAgICBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgY29uc3QgZmllbGQgPSBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV07XG5cbiAgICAgICAgICBpZiAoZmllbGQudHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgICAgICAgY2xhc3NOYW1lcy5wdXNoKGBfSm9pbjoke2ZpZWxkTmFtZX06JHtyZXEuYm9keS5uYW1lfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgcHJvbWlzc2VzID0gY2xhc3NOYW1lcy5tYXAobmFtZSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZXhwb3J0Q2xhc3MocmVxLCB7IG5hbWUgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNzZXMpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKGpzb25GaWxlcyA9PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICBjb25zdCB0bXBaaXBGaWxlID0gdG1wLmZpbGVTeW5jKCk7XG4gICAgICAgICAgY29uc3QgdG1wWmlwU3RyZWFtID0gZnMuY3JlYXRlV3JpdGVTdHJlYW0odG1wWmlwRmlsZS5uYW1lKTtcblxuICAgICAgICAgIGNvbnN0IHppcCA9IGFyY2hpdmVyKCd6aXAnKTtcbiAgICAgICAgICB6aXAucGlwZSh0bXBaaXBTdHJlYW0pO1xuXG4gICAgICAgICAganNvbkZpbGVzLmZvckVhY2godG1wSnNvbkZpbGUgPT4ge1xuICAgICAgICAgICAgemlwLmFwcGVuZChmcy5yZWFkRmlsZVN5bmModG1wSnNvbkZpbGUubmFtZSksIHtcbiAgICAgICAgICAgICAgbmFtZTogdG1wSnNvbkZpbGUuX25hbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRtcEpzb25GaWxlLnJlbW92ZUNhbGxiYWNrKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICB6aXAuZmluYWxpemUoKTtcblxuICAgICAgICAgIHRtcFppcFN0cmVhbS5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBidWYgPSBmcy5yZWFkRmlsZVN5bmModG1wWmlwRmlsZS5uYW1lKTtcbiAgICAgICAgICAgIHRtcFppcEZpbGUucmVtb3ZlQ2FsbGJhY2soKTtcbiAgICAgICAgICAgIHJlc29sdmUoYnVmKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oemlwcGVkRmlsZSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IHJlcS5jb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgICAgICByZXR1cm4gZmlsZXNDb250cm9sbGVyLmNyZWF0ZUZpbGUoXG4gICAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgICByZXEuYm9keS5uYW1lLFxuICAgICAgICAgIHppcHBlZEZpbGUsXG4gICAgICAgICAgJ2FwcGxpY2F0aW9uL3ppcCdcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihmaWxlRGF0YSA9PiB7XG4gICAgICAgIHJldHVybiBlbWFpbENvbnRyb2xsZXJBZGFwdGVyLnNlbmRNYWlsKHtcbiAgICAgICAgICB0ZXh0OiBgV2UgaGF2ZSBzdWNjZXNzZnVsbHkgZXhwb3J0ZWQgeW91ciBkYXRhIGZyb20gdGhlIGNsYXNzICR7cmVxLmJvZHkubmFtZX0uXFxuXG4gICAgICAgIFBsZWFzZSBkb3dubG9hZCBmcm9tICR7ZmlsZURhdGEudXJsfWAsXG4gICAgICAgICAgbGluazogZmlsZURhdGEudXJsLFxuICAgICAgICAgIHRvOiByZXEuYm9keS5mZWVkYmFja0VtYWlsLFxuICAgICAgICAgIHN1YmplY3Q6ICdFeHBvcnQgY29tcGxldGVkJyxcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgcmV0dXJuIGVtYWlsQ29udHJvbGxlckFkYXB0ZXIuc2VuZE1haWwoe1xuICAgICAgICAgIHRleHQ6IGBXZSBjb3VsZCBub3QgZXhwb3J0IHlvdXIgZGF0YSB0byB0aGUgY2xhc3MgJHtyZXEuYm9keS5uYW1lfS4gRXJyb3I6ICR7ZXJyb3J9YCxcbiAgICAgICAgICB0bzogcmVxLmJvZHkuZmVlZGJhY2tFbWFpbCxcbiAgICAgICAgICBzdWJqZWN0OiAnRXhwb3J0IGZhaWxlZCcsXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIGRhdGFiYXNlQ29udHJvbGxlci5kZXN0cm95KFxuICAgICAgICAgIERlZmF1bHRFeHBvcnRFeHBvcnRQcm9ncmVzc0NvbGxlY3Rpb25OYW1lLFxuICAgICAgICAgIGV4cG9ydFByb2dyZXNzXG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgcmVzcG9uc2U6XG4gICAgICAgICdXZSBhcmUgZXhwb3J0aW5nIHlvdXIgZGF0YS4gWW91IHdpbGwgYmUgbm90aWZpZWQgYnkgZS1tYWlsIG9uY2UgaXQgaXMgY29tcGxldGVkLicsXG4gICAgfSk7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCAnL2V4cG9ydF9kYXRhJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUV4cG9ydChyZXEpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9leHBvcnRfcHJvZ3Jlc3MnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRXhwb3J0UHJvZ3Jlc3MocmVxKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBFeHBvcnRSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/FeaturesRouter.js b/lib/Routers/FeaturesRouter.js new file mode 100644 index 0000000000..b68b2fcd1a --- /dev/null +++ b/lib/Routers/FeaturesRouter.js @@ -0,0 +1,80 @@ +"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, + import: true, + exportClass: true, + editClassLevelPermissions: true, + editPointerPermissions: true + } + }; + return { + response: { + features: features, + parseServerVersion: _package.version + } + }; + }); + } + +} + +exports.FeaturesRouter = FeaturesRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZlYXR1cmVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIkZlYXR1cmVzUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsIm1vdW50Um91dGVzIiwicm91dGUiLCJtaWRkbGV3YXJlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJyZXEiLCJjb25maWciLCJmZWF0dXJlcyIsImdsb2JhbENvbmZpZyIsImNyZWF0ZSIsInJlYWQiLCJ1cGRhdGUiLCJkZWxldGUiLCJob29rcyIsImNsb3VkQ29kZSIsImpvYnMiLCJsb2dzIiwibGV2ZWwiLCJzaXplIiwib3JkZXIiLCJ1bnRpbCIsImZyb20iLCJwdXNoIiwiaW1tZWRpYXRlUHVzaCIsImhhc1B1c2hTdXBwb3J0Iiwic2NoZWR1bGVkUHVzaCIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0Iiwic3RvcmVkUHVzaERhdGEiLCJwdXNoQXVkaWVuY2VzIiwibG9jYWxpemF0aW9uIiwic2NoZW1hcyIsImFkZEZpZWxkIiwicmVtb3ZlRmllbGQiLCJhZGRDbGFzcyIsInJlbW92ZUNsYXNzIiwiY2xlYXJBbGxEYXRhRnJvbUNsYXNzIiwiaW1wb3J0IiwiZXhwb3J0Q2xhc3MiLCJlZGl0Q2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiZWRpdFBvaW50ZXJQZXJtaXNzaW9ucyIsInJlc3BvbnNlIiwicGFyc2VTZXJ2ZXJWZXJzaW9uIiwidmVyc2lvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVPLE1BQU1BLGNBQU4sU0FBNkJDLHNCQUE3QixDQUEyQztBQUNoREMsRUFBQUEsV0FBVyxHQUFHO0FBQ1osU0FBS0MsS0FBTCxDQUNFLEtBREYsRUFFRSxhQUZGLEVBR0VDLFVBQVUsQ0FBQ0MsNkJBSGIsRUFJRUMsR0FBRyxJQUFJO0FBQ0wsWUFBTTtBQUFFQyxRQUFBQTtBQUFGLFVBQWFELEdBQW5CO0FBQ0EsWUFBTUUsUUFBUSxHQUFHO0FBQ2ZDLFFBQUFBLFlBQVksRUFBRTtBQUNaQyxVQUFBQSxNQUFNLEVBQUUsSUFESTtBQUVaQyxVQUFBQSxJQUFJLEVBQUUsSUFGTTtBQUdaQyxVQUFBQSxNQUFNLEVBQUUsSUFISTtBQUlaQyxVQUFBQSxNQUFNLEVBQUU7QUFKSSxTQURDO0FBT2ZDLFFBQUFBLEtBQUssRUFBRTtBQUNMSixVQUFBQSxNQUFNLEVBQUUsSUFESDtBQUVMQyxVQUFBQSxJQUFJLEVBQUUsSUFGRDtBQUdMQyxVQUFBQSxNQUFNLEVBQUUsSUFISDtBQUlMQyxVQUFBQSxNQUFNLEVBQUU7QUFKSCxTQVBRO0FBYWZFLFFBQUFBLFNBQVMsRUFBRTtBQUNUQyxVQUFBQSxJQUFJLEVBQUU7QUFERyxTQWJJO0FBZ0JmQyxRQUFBQSxJQUFJLEVBQUU7QUFDSkMsVUFBQUEsS0FBSyxFQUFFLElBREg7QUFFSkMsVUFBQUEsSUFBSSxFQUFFLElBRkY7QUFHSkMsVUFBQUEsS0FBSyxFQUFFLElBSEg7QUFJSkMsVUFBQUEsS0FBSyxFQUFFLElBSkg7QUFLSkMsVUFBQUEsSUFBSSxFQUFFO0FBTEYsU0FoQlM7QUF1QmZDLFFBQUFBLElBQUksRUFBRTtBQUNKQyxVQUFBQSxhQUFhLEVBQUVqQixNQUFNLENBQUNrQixjQURsQjtBQUVKQyxVQUFBQSxhQUFhLEVBQUVuQixNQUFNLENBQUNvQix1QkFGbEI7QUFHSkMsVUFBQUEsY0FBYyxFQUFFckIsTUFBTSxDQUFDa0IsY0FIbkI7QUFJSkksVUFBQUEsYUFBYSxFQUFFLElBSlg7QUFLSkMsVUFBQUEsWUFBWSxFQUFFO0FBTFYsU0F2QlM7QUE4QmZDLFFBQUFBLE9BQU8sRUFBRTtBQUNQQyxVQUFBQSxRQUFRLEVBQUUsSUFESDtBQUVQQyxVQUFBQSxXQUFXLEVBQUUsSUFGTjtBQUdQQyxVQUFBQSxRQUFRLEVBQUUsSUFISDtBQUlQQyxVQUFBQSxXQUFXLEVBQUUsSUFKTjtBQUtQQyxVQUFBQSxxQkFBcUIsRUFBRSxJQUxoQjtBQU1QQyxVQUFBQSxNQUFNLEVBQUUsSUFORDtBQU9QQyxVQUFBQSxXQUFXLEVBQUUsSUFQTjtBQVFQQyxVQUFBQSx5QkFBeUIsRUFBRSxJQVJwQjtBQVNQQyxVQUFBQSxzQkFBc0IsRUFBRTtBQVRqQjtBQTlCTSxPQUFqQjtBQTJDQSxhQUFPO0FBQ0xDLFFBQUFBLFFBQVEsRUFBRTtBQUNSakMsVUFBQUEsUUFBUSxFQUFFQSxRQURGO0FBRVJrQyxVQUFBQSxrQkFBa0IsRUFBRUM7QUFGWjtBQURMLE9BQVA7QUFNRCxLQXZESDtBQXlERDs7QUEzRCtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4uLy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmUgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuXG5leHBvcnQgY2xhc3MgRmVhdHVyZXNSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9zZXJ2ZXJJbmZvJyxcbiAgICAgIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICByZXEgPT4ge1xuICAgICAgICBjb25zdCB7IGNvbmZpZyB9ID0gcmVxO1xuICAgICAgICBjb25zdCBmZWF0dXJlcyA9IHtcbiAgICAgICAgICBnbG9iYWxDb25maWc6IHtcbiAgICAgICAgICAgIGNyZWF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIHJlYWQ6IHRydWUsXG4gICAgICAgICAgICB1cGRhdGU6IHRydWUsXG4gICAgICAgICAgICBkZWxldGU6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBob29rczoge1xuICAgICAgICAgICAgY3JlYXRlOiB0cnVlLFxuICAgICAgICAgICAgcmVhZDogdHJ1ZSxcbiAgICAgICAgICAgIHVwZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGRlbGV0ZTogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNsb3VkQ29kZToge1xuICAgICAgICAgICAgam9iczogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGxvZ3M6IHtcbiAgICAgICAgICAgIGxldmVsOiB0cnVlLFxuICAgICAgICAgICAgc2l6ZTogdHJ1ZSxcbiAgICAgICAgICAgIG9yZGVyOiB0cnVlLFxuICAgICAgICAgICAgdW50aWw6IHRydWUsXG4gICAgICAgICAgICBmcm9tOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcHVzaDoge1xuICAgICAgICAgICAgaW1tZWRpYXRlUHVzaDogY29uZmlnLmhhc1B1c2hTdXBwb3J0LFxuICAgICAgICAgICAgc2NoZWR1bGVkUHVzaDogY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0LFxuICAgICAgICAgICAgc3RvcmVkUHVzaERhdGE6IGNvbmZpZy5oYXNQdXNoU3VwcG9ydCxcbiAgICAgICAgICAgIHB1c2hBdWRpZW5jZXM6IHRydWUsXG4gICAgICAgICAgICBsb2NhbGl6YXRpb246IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBzY2hlbWFzOiB7XG4gICAgICAgICAgICBhZGRGaWVsZDogdHJ1ZSxcbiAgICAgICAgICAgIHJlbW92ZUZpZWxkOiB0cnVlLFxuICAgICAgICAgICAgYWRkQ2xhc3M6IHRydWUsXG4gICAgICAgICAgICByZW1vdmVDbGFzczogdHJ1ZSxcbiAgICAgICAgICAgIGNsZWFyQWxsRGF0YUZyb21DbGFzczogdHJ1ZSxcbiAgICAgICAgICAgIGltcG9ydDogdHJ1ZSxcbiAgICAgICAgICAgIGV4cG9ydENsYXNzOiB0cnVlLFxuICAgICAgICAgICAgZWRpdENsYXNzTGV2ZWxQZXJtaXNzaW9uczogdHJ1ZSxcbiAgICAgICAgICAgIGVkaXRQb2ludGVyUGVybWlzc2lvbnM6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHJlc3BvbnNlOiB7XG4gICAgICAgICAgICBmZWF0dXJlczogZmVhdHVyZXMsXG4gICAgICAgICAgICBwYXJzZVNlcnZlclZlcnNpb246IHZlcnNpb24sXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICApO1xuICB9XG59XG4iXX0= \ 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/ImportRouter.js b/lib/Routers/ImportRouter.js new file mode 100644 index 0000000000..9089a2b210 --- /dev/null +++ b/lib/Routers/ImportRouter.js @@ -0,0 +1,215 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.ImportRouter = void 0; + +var _express = _interopRequireDefault(require("express")); + +var _AdapterLoader = require("../Adapters/AdapterLoader"); + +var middlewares = _interopRequireWildcard(require("../middlewares")); + +var _multer = _interopRequireDefault(require("multer")); + +var _rest = _interopRequireDefault(require("../rest")); + +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 ImportRouter { + getOneSchema(req) { + const className = req.params.className; + return req.config.database.loadSchema({ + clearCache: true + }).then(schemaController => schemaController.getOneSchema(className)).catch(error => { + if (error === undefined) { + return Promise.reject(new _node.Parse.Error(_node.Parse.Error.INVALID_CLASS_NAME, `Class ${className} does not exist.`)); + } else { + return Promise.reject(new _node.Parse.Error(_node.Parse.Error.INTERNAL_SERVER_ERROR, 'Database adapter error.')); + } + }); + } + + importRestObject(req, restObject, targetClass) { + if (targetClass) { + return _rest.default.update(req.config, req.auth, req.params.className, { + objectId: restObject.owningId + }, { + [req.params.relationName]: { + __op: 'AddRelation', + objects: [{ + __type: 'Pointer', + className: targetClass, + objectId: restObject.relatedId + }] + } + }, req.info.clientSDK).catch(function (error) { + if (error.code === _node.Parse.Error.OBJECT_NOT_FOUND) { + return Promise.reject(new _node.Parse.Error(_node.Parse.Error.OBJECT_NOT_FOUND, 'Object not found')); + } else { + return Promise.reject(error); + } + }); + } + + if (restObject.createdAt) { + delete restObject.createdAt; + } + + if (restObject.updatedAt) { + delete restObject.updatedAt; + } + + if (restObject.objectId) { + return _rest.default.update(req.config, req.auth, req.params.className, { + objectId: restObject.objectId + }, restObject, req.info.clientSDK).catch(function (error) { + if (error.code === _node.Parse.Error.OBJECT_NOT_FOUND) { + return _rest.default.create(req.config, req.auth, req.params.className, restObject, req.info.clientSDK, { + allowObjectId: true + }); + } else { + return Promise.reject(error); + } + }); + } + + return _rest.default.create(req.config, req.auth, req.params.className, restObject); + } + + getRestObjects(req) { + return new Promise(resolve => { + let restObjects = []; + let importFile; + + try { + importFile = JSON.parse(req.file.buffer.toString()); + } catch (e) { + throw new Error('Failed to parse JSON based on the file sent'); + } + + if (Array.isArray(importFile)) { + restObjects = importFile; + } else if (Array.isArray(importFile.results)) { + restObjects = importFile.results; + } else if (Array.isArray(importFile.rows)) { + restObjects = importFile.rows; + } + + if (!restObjects) { + throw new Error('No data to import'); + } + + if (req.body.feedbackEmail) { + if (!req.config.emailAdapter) { + throw new Error('You have to setup a Mail Adapter.'); + } + } + + resolve(restObjects); + }); + } + + handleImport(req) { + const emailControllerAdapter = (0, _AdapterLoader.loadAdapter)(req.config.emailAdapter); + let promise = null; + + if (req.params.relationName) { + promise = this.getOneSchema(req).then(response => { + if (!Object.prototype.hasOwnProperty.call(response.fields, req.params.relationName)) { + throw new Error(`Relation ${req.params.relationName} does not exist in ${req.params.className}.`); + } else if (response.fields[req.params.relationName].type !== 'Relation') { + throw new Error(`Class ${response.fields[req.params.relationName].targetClass} does not have Relation type.`); + } + + const targetClass = response.fields[req.params.relationName].targetClass; + return Promise.all([this.getRestObjects(req), targetClass]); + }); + } else { + promise = Promise.all([this.getRestObjects(req)]); + } + + promise = promise.then(([restObjects, targetClass]) => { + return restObjects.reduce((item, object, index) => { + item.pageArray.push(this.importRestObject.bind(this, req, object, targetClass)); + + if (index && index % 100 === 0 || index === restObjects.length - 1) { + const pageArray = item.pageArray.slice(0); + item.pageArray = []; + item.mainPromise = item.mainPromise.then(results => { + return Promise.all(results.concat(pageArray.map(func => func()))); + }); + } + + return item; + }, { + pageArray: [], + mainPromise: Promise.resolve([]) + }).mainPromise; + }).then(results => { + if (req.body.feedbackEmail) { + emailControllerAdapter.sendMail({ + text: `We have successfully imported your data to the class ${req.params.className}${req.params.relationName ? ', relation ' + req.params.relationName : ''}.`, + to: req.body.feedbackEmail, + subject: 'Import completed' + }); + } else { + return Promise.resolve({ + response: results + }); + } + }).catch(error => { + if (req.body.feedbackEmail) { + emailControllerAdapter.sendMail({ + text: `We could not import your data to the class ${req.params.className}${req.params.relationName ? ', relation ' + req.params.relationName : ''}. Error: ${error}`, + to: req.body.feedbackEmail, + subject: 'Import failed' + }); + } else { + throw new Error('Internal server error: ' + error); + } + }); + + if (req.body.feedbackEmail && emailControllerAdapter) { + promise = Promise.resolve({ + response: 'We are importing your data. You will be notified by e-mail once it is completed.' + }); + } + + return promise; + } + + wrapPromiseRequest(req, res, handler) { + return handler(req).then(data => { + res.json(data); + }).catch(err => { + res.status(400).send({ + message: err.message + }); + }); + } + + expressRouter() { + const router = _express.default.Router(); + + const upload = (0, _multer.default)(); + router.post('/import_data/:className', upload.single('importFile'), // middlewares.allowCrossDomain, + middlewares.handleParseHeaders, middlewares.enforceMasterKeyAccess, (req, res) => this.wrapPromiseRequest(req, res, this.handleImport.bind(this))); + router.post('/import_relation_data/:className/:relationName', upload.single('importFile'), // middlewares.allowCrossDomain, + middlewares.handleParseHeaders, middlewares.enforceMasterKeyAccess, (req, res) => this.wrapPromiseRequest(req, res, this.handleImport.bind(this))); + return router; + } + +} + +exports.ImportRouter = ImportRouter; +var _default = ImportRouter; +exports.default = _default; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ltcG9ydFJvdXRlci5qcyJdLCJuYW1lcyI6WyJJbXBvcnRSb3V0ZXIiLCJnZXRPbmVTY2hlbWEiLCJyZXEiLCJjbGFzc05hbWUiLCJwYXJhbXMiLCJjb25maWciLCJkYXRhYmFzZSIsImxvYWRTY2hlbWEiLCJjbGVhckNhY2hlIiwidGhlbiIsInNjaGVtYUNvbnRyb2xsZXIiLCJjYXRjaCIsImVycm9yIiwidW5kZWZpbmVkIiwiUHJvbWlzZSIsInJlamVjdCIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX0NMQVNTX05BTUUiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJpbXBvcnRSZXN0T2JqZWN0IiwicmVzdE9iamVjdCIsInRhcmdldENsYXNzIiwicmVzdCIsInVwZGF0ZSIsImF1dGgiLCJvYmplY3RJZCIsIm93bmluZ0lkIiwicmVsYXRpb25OYW1lIiwiX19vcCIsIm9iamVjdHMiLCJfX3R5cGUiLCJyZWxhdGVkSWQiLCJpbmZvIiwiY2xpZW50U0RLIiwiY29kZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJjcmVhdGVkQXQiLCJ1cGRhdGVkQXQiLCJjcmVhdGUiLCJhbGxvd09iamVjdElkIiwiZ2V0UmVzdE9iamVjdHMiLCJyZXNvbHZlIiwicmVzdE9iamVjdHMiLCJpbXBvcnRGaWxlIiwiSlNPTiIsInBhcnNlIiwiZmlsZSIsImJ1ZmZlciIsInRvU3RyaW5nIiwiZSIsIkFycmF5IiwiaXNBcnJheSIsInJlc3VsdHMiLCJyb3dzIiwiYm9keSIsImZlZWRiYWNrRW1haWwiLCJlbWFpbEFkYXB0ZXIiLCJoYW5kbGVJbXBvcnQiLCJlbWFpbENvbnRyb2xsZXJBZGFwdGVyIiwicHJvbWlzZSIsInJlc3BvbnNlIiwiT2JqZWN0IiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiZmllbGRzIiwidHlwZSIsImFsbCIsInJlZHVjZSIsIml0ZW0iLCJvYmplY3QiLCJpbmRleCIsInBhZ2VBcnJheSIsInB1c2giLCJiaW5kIiwibGVuZ3RoIiwic2xpY2UiLCJtYWluUHJvbWlzZSIsImNvbmNhdCIsIm1hcCIsImZ1bmMiLCJzZW5kTWFpbCIsInRleHQiLCJ0byIsInN1YmplY3QiLCJ3cmFwUHJvbWlzZVJlcXVlc3QiLCJyZXMiLCJoYW5kbGVyIiwiZGF0YSIsImpzb24iLCJlcnIiLCJzdGF0dXMiLCJzZW5kIiwibWVzc2FnZSIsImV4cHJlc3NSb3V0ZXIiLCJyb3V0ZXIiLCJleHByZXNzIiwiUm91dGVyIiwidXBsb2FkIiwicG9zdCIsInNpbmdsZSIsIm1pZGRsZXdhcmVzIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwiZW5mb3JjZU1hc3RlcktleUFjY2VzcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7OztBQUVPLE1BQU1BLFlBQU4sQ0FBbUI7QUFDeEJDLEVBQUFBLFlBQVksQ0FBQ0MsR0FBRCxFQUFNO0FBQ2hCLFVBQU1DLFNBQVMsR0FBR0QsR0FBRyxDQUFDRSxNQUFKLENBQVdELFNBQTdCO0FBRUEsV0FBT0QsR0FBRyxDQUFDRyxNQUFKLENBQVdDLFFBQVgsQ0FDSkMsVUFESSxDQUNPO0FBQUVDLE1BQUFBLFVBQVUsRUFBRTtBQUFkLEtBRFAsRUFFSkMsSUFGSSxDQUVDQyxnQkFBZ0IsSUFBSUEsZ0JBQWdCLENBQUNULFlBQWpCLENBQThCRSxTQUE5QixDQUZyQixFQUdKUSxLQUhJLENBR0VDLEtBQUssSUFBSTtBQUNkLFVBQUlBLEtBQUssS0FBS0MsU0FBZCxFQUF5QjtBQUN2QixlQUFPQyxPQUFPLENBQUNDLE1BQVIsQ0FDTCxJQUFJQyxZQUFNQyxLQUFWLENBQ0VELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRGQsRUFFRyxTQUFRZixTQUFVLGtCQUZyQixDQURLLENBQVA7QUFNRCxPQVBELE1BT087QUFDTCxlQUFPVyxPQUFPLENBQUNDLE1BQVIsQ0FDTCxJQUFJQyxZQUFNQyxLQUFWLENBQ0VELFlBQU1DLEtBQU4sQ0FBWUUscUJBRGQsRUFFRSx5QkFG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VUFxQixJQUFBQSxNQUFNLENBQUNJLElBQVAsQ0FDRSxnREFERixFQUVFRCxNQUFNLENBQUNFLE1BQVAsQ0FBYyxZQUFkLENBRkYsRUFHRTtBQUNBQyxJQUFBQSxXQUFXLENBQUNDLGtCQUpkLEVBS0VELFdBQVcsQ0FBQ0Usc0JBTGQsRUFNRSxDQUFDdEcsR0FBRCxFQUFNcUYsR0FBTixLQUNFLEtBQUtELGtCQUFMLENBQXdCcEYsR0FBeEIsRUFBNkJxRixHQUE3QixFQUFrQyxLQUFLN0IsWUFBTCxDQUFrQmlCLElBQWxCLENBQXVCLElBQXZCLENBQWxDLENBUEo7QUFVQSxXQUFPcUIsTUFBUDtBQUNEOztBQS9RdUI7OztlQWtSWGhHLFkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IGxvYWRBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQWRhcHRlckxvYWRlcic7XG5pbXBvcnQgKiBhcyBtaWRkbGV3YXJlcyBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5pbXBvcnQgbXVsdGVyIGZyb20gJ211bHRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCB7IFBhcnNlIH0gZnJvbSAncGFyc2Uvbm9kZSc7XG5cbmV4cG9ydCBjbGFzcyBJbXBvcnRSb3V0ZXIge1xuICBnZXRPbmVTY2hlbWEocmVxKSB7XG4gICAgY29uc3QgY2xhc3NOYW1lID0gcmVxLnBhcmFtcy5jbGFzc05hbWU7XG5cbiAgICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZVxuICAgICAgLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlIH0pXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICAgICAgICBgQ2xhc3MgJHtjbGFzc05hbWV9IGRvZXMgbm90IGV4aXN0LmBcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgICAgICAgICAnRGF0YWJhc2UgYWRhcHRlciBlcnJvci4nXG4gICAgICAgICAgICApXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBpbXBvcnRSZXN0T2JqZWN0KHJlcSwgcmVzdE9iamVjdCwgdGFyZ2V0Q2xhc3MpIHtcbiAgICBpZiAodGFyZ2V0Q2xhc3MpIHtcbiAgICAgIHJldHVybiByZXN0XG4gICAgICAgIC51cGRhdGUoXG4gICAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgICByZXEuYXV0aCxcbiAgICAgICAgICByZXEucGFyYW1zLmNsYXNzTmFtZSxcbiAgICAgICAgICB7IG9iamVjdElkOiByZXN0T2JqZWN0Lm93bmluZ0lkIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgW3JlcS5wYXJhbXMucmVsYXRpb25OYW1lXToge1xuICAgICAgICAgICAgICBfX29wOiAnQWRkUmVsYXRpb24nLFxuICAgICAgICAgICAgICBvYmplY3RzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IHRhcmdldENsYXNzLFxuICAgICAgICAgICAgICAgICAgb2JqZWN0SWQ6IHJlc3RPYmplY3QucmVsYXRlZElkLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgICAgIClcbiAgICAgICAgLmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdPYmplY3Qgbm90IGZvdW5kJylcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocmVzdE9iamVjdC5jcmVhdGVkQXQpIHtcbiAgICAgIGRlbGV0ZSByZXN0T2JqZWN0LmNyZWF0ZWRBdDtcbiAgICB9XG5cbiAgICBpZiAocmVzdE9iamVjdC51cGRhdGVkQXQpIHtcbiAgICAgIGRlbGV0ZSByZXN0T2JqZWN0LnVwZGF0ZWRBdDtcbiAgICB9XG5cbiAgICBpZiAocmVzdE9iamVjdC5vYmplY3RJZCkge1xuICAgICAgcmV0dXJuIHJlc3RcbiAgICAgICAgLnVwZGF0ZShcbiAgICAgICAgICByZXEuY29uZmlnLFxuICAgICAgICAgIHJlcS5hdXRoLFxuICAgICAgICAgIHJlcS5wYXJhbXMuY2xhc3NOYW1lLFxuICAgICAgICAgIHsgb2JqZWN0SWQ6IHJlc3RPYmplY3Qub2JqZWN0SWQgfSxcbiAgICAgICAgICByZXN0T2JqZWN0LFxuICAgICAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICAgICApXG4gICAgICAgIC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdC5jcmVhdGUoXG4gICAgICAgICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgICAgICAgIHJlcS5hdXRoLFxuICAgICAgICAgICAgICByZXEucGFyYW1zLmNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgcmVzdE9iamVjdCxcbiAgICAgICAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLLFxuICAgICAgICAgICAgICB7IGFsbG93T2JqZWN0SWQ6IHRydWUgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXN0LmNyZWF0ZShyZXEuY29uZmlnLCByZXEuYXV0aCwgcmVxLnBhcmFtcy5jbGFzc05hbWUsIHJlc3RPYmplY3QpO1xuICB9XG5cbiAgZ2V0UmVzdE9iamVjdHMocmVxKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgbGV0IHJlc3RPYmplY3RzID0gW107XG4gICAgICBsZXQgaW1wb3J0RmlsZTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgaW1wb3J0RmlsZSA9IEpTT04ucGFyc2UocmVxLmZpbGUuYnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBwYXJzZSBKU09OIGJhc2VkIG9uIHRoZSBmaWxlIHNlbnQnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaW1wb3J0RmlsZSkpIHtcbiAgICAgICAgcmVzdE9iamVjdHMgPSBpbXBvcnRGaWxlO1xuICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGltcG9ydEZpbGUucmVzdWx0cykpIHtcbiAgICAgICAgcmVzdE9iamVjdHMgPSBpbXBvcnRGaWxlLnJlc3VsdHM7XG4gICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaW1wb3J0RmlsZS5yb3dzKSkge1xuICAgICAgICByZXN0T2JqZWN0cyA9IGltcG9ydEZpbGUucm93cztcbiAgICAgIH1cblxuICAgICAgaWYgKCFyZXN0T2JqZWN0cykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGRhdGEgdG8gaW1wb3J0Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXEuYm9keS5mZWVkYmFja0VtYWlsKSB7XG4gICAgICAgIGlmICghcmVxLmNvbmZpZy5lbWFpbEFkYXB0ZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBoYXZlIHRvIHNldHVwIGEgTWFpbCBBZGFwdGVyLicpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJlc29sdmUocmVzdE9iamVjdHMpO1xuICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlSW1wb3J0KHJlcSkge1xuICAgIGNvbnN0IGVtYWlsQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihyZXEuY29uZmlnLmVtYWlsQWRhcHRlcik7XG5cbiAgICBsZXQgcHJvbWlzZSA9IG51bGw7XG5cbiAgICBpZiAocmVxLnBhcmFtcy5yZWxhdGlvbk5hbWUpIHtcbiAgICAgIHByb21pc2UgPSB0aGlzLmdldE9uZVNjaGVtYShyZXEpLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChcbiAgICAgICAgICAgIHJlc3BvbnNlLmZpZWxkcyxcbiAgICAgICAgICAgIHJlcS5wYXJhbXMucmVsYXRpb25OYW1lXG4gICAgICAgICAgKVxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgUmVsYXRpb24gJHtyZXEucGFyYW1zLnJlbGF0aW9uTmFtZX0gZG9lcyBub3QgZXhpc3QgaW4gJHtyZXEucGFyYW1zLmNsYXNzTmFtZX0uYFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgcmVzcG9uc2UuZmllbGRzW3JlcS5wYXJhbXMucmVsYXRpb25OYW1lXS50eXBlICE9PSAnUmVsYXRpb24nXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBDbGFzcyAke1xuICAgICAgICAgICAgICByZXNwb25zZS5maWVsZHNbcmVxLnBhcmFtcy5yZWxhdGlvbk5hbWVdLnRhcmdldENsYXNzXG4gICAgICAgICAgICB9IGRvZXMgbm90IGhhdmUgUmVsYXRpb24gdHlwZS5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRhcmdldENsYXNzID1cbiAgICAgICAgICByZXNwb25zZS5maWVsZHNbcmVxLnBhcmFtcy5yZWxhdGlvbk5hbWVdLnRhcmdldENsYXNzO1xuXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbdGhpcy5nZXRSZXN0T2JqZWN0cyhyZXEpLCB0YXJnZXRDbGFzc10pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb21pc2UgPSBQcm9taXNlLmFsbChbdGhpcy5nZXRSZXN0T2JqZWN0cyhyZXEpXSk7XG4gICAgfVxuXG4gICAgcHJvbWlzZSA9IHByb21pc2VcbiAgICAgIC50aGVuKChbcmVzdE9iamVjdHMsIHRhcmdldENsYXNzXSkgPT4ge1xuICAgICAgICByZXR1cm4gcmVzdE9iamVjdHMucmVkdWNlKFxuICAgICAgICAgIChpdGVtLCBvYmplY3QsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBpdGVtLnBhZ2VBcnJheS5wdXNoKFxuICAgICAgICAgICAgICB0aGlzLmltcG9ydFJlc3RPYmplY3QuYmluZCh0aGlzLCByZXEsIG9iamVjdCwgdGFyZ2V0Q2xhc3MpXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIChpbmRleCAmJiBpbmRleCAlIDEwMCA9PT0gMCkgfHxcbiAgICAgICAgICAgICAgaW5kZXggPT09IHJlc3RPYmplY3RzLmxlbmd0aCAtIDFcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICBjb25zdCBwYWdlQXJyYXkgPSBpdGVtLnBhZ2VBcnJheS5zbGljZSgwKTtcbiAgICAgICAgICAgICAgaXRlbS5wYWdlQXJyYXkgPSBbXTtcblxuICAgICAgICAgICAgICBpdGVtLm1haW5Qcm9taXNlID0gaXRlbS5tYWluUHJvbWlzZS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICAgIHJlc3VsdHMuY29uY2F0KHBhZ2VBcnJheS5tYXAoZnVuYyA9PiBmdW5jKCkpKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gaXRlbTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgcGFnZUFycmF5OiBbXSwgbWFpblByb21pc2U6IFByb21pc2UucmVzb2x2ZShbXSkgfVxuICAgICAgICApLm1haW5Qcm9taXNlO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAocmVxLmJvZHkuZmVlZGJhY2tFbWFpbCkge1xuICAgICAgICAgIGVtYWlsQ29udHJvbGxlckFkYXB0ZXIuc2VuZE1haWwoe1xuICAgICAgICAgICAgdGV4dDogYFdlIGhhdmUgc3VjY2Vzc2Z1bGx5IGltcG9ydGVkIHlvdXIgZGF0YSB0byB0aGUgY2xhc3MgJHtcbiAgICAgICAgICAgICAgcmVxLnBhcmFtcy5jbGFzc05hbWVcbiAgICAgICAgICAgIH0ke1xuICAgICAgICAgICAgICByZXEucGFyYW1zLnJlbGF0aW9uTmFtZVxuICAgICAgICAgICAgICAgID8gJywgcmVsYXRpb24gJyArIHJlcS5wYXJhbXMucmVsYXRpb25OYW1lXG4gICAgICAgICAgICAgICAgOiAnJ1xuICAgICAgICAgICAgfS5gLFxuICAgICAgICAgICAgdG86IHJlcS5ib2R5LmZlZWRiYWNrRW1haWwsXG4gICAgICAgICAgICBzdWJqZWN0OiAnSW1wb3J0IGNvbXBsZXRlZCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IHJlc3BvbnNlOiByZXN1bHRzIH0pO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKHJlcS5ib2R5LmZlZWRiYWNrRW1haWwpIHtcbiAgICAgICAgICBlbWFpbENvbnRyb2xsZXJBZGFwdGVyLnNlbmRNYWlsKHtcbiAgICAgICAgICAgIHRleHQ6IGBXZSBjb3VsZCBub3QgaW1wb3J0IHlvdXIgZGF0YSB0byB0aGUgY2xhc3MgJHtcbiAgICAgICAgICAgICAgcmVxLnBhcmFtcy5jbGFzc05hbWVcbiAgICAgICAgICAgIH0ke1xuICAgICAgICAgICAgICByZXEucGFyYW1zLnJlbGF0aW9uTmFtZVxuICAgICAgICAgICAgICAgID8gJywgcmVsYXRpb24gJyArIHJlcS5wYXJhbXMucmVsYXRpb25OYW1lXG4gICAgICAgICAgICAgICAgOiAnJ1xuICAgICAgICAgICAgfS4gRXJyb3I6ICR7ZXJyb3J9YCxcbiAgICAgICAgICAgIHRvOiByZXEuYm9keS5mZWVkYmFja0VtYWlsLFxuICAgICAgICAgICAgc3ViamVjdDogJ0ltcG9ydCBmYWlsZWQnLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgc2VydmVyIGVycm9yOiAnICsgZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIGlmIChyZXEuYm9keS5mZWVkYmFja0VtYWlsICYmIGVtYWlsQ29udHJvbGxlckFkYXB0ZXIpIHtcbiAgICAgIHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICByZXNwb25zZTpcbiAgICAgICAgICAnV2UgYXJlIGltcG9ydGluZyB5b3VyIGRhdGEuIFlvdSB3aWxsIGJlIG5vdGlmaWVkIGJ5IGUtbWFpbCBvbmNlIGl0IGlzIGNvbXBsZXRlZC4nLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cblxuICB3cmFwUHJvbWlzZVJlcXVlc3QocmVxLCByZXMsIGhhbmRsZXIpIHtcbiAgICByZXR1cm4gaGFuZGxlcihyZXEpXG4gICAgICAudGhlbihkYXRhID0+IHtcbiAgICAgICAgcmVzLmpzb24oZGF0YSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDAwKS5zZW5kKHsgbWVzc2FnZTogZXJyLm1lc3NhZ2UgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGV4cHJlc3NSb3V0ZXIoKSB7XG4gICAgY29uc3Qgcm91dGVyID0gZXhwcmVzcy5Sb3V0ZXIoKTtcbiAgICBjb25zdCB1cGxvYWQgPSBtdWx0ZXIoKTtcblxuICAgIHJvdXRlci5wb3N0KFxuICAgICAgJy9pbXBvcnRfZGF0YS86Y2xhc3NOYW1lJyxcbiAgICAgIHVwbG9hZC5zaW5nbGUoJ2ltcG9ydEZpbGUnKSxcbiAgICAgIC8vIG1pZGRsZXdhcmVzLmFsbG93Q3Jvc3NEb21haW4sXG4gICAgICBtaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMsXG4gICAgICBtaWRkbGV3YXJlcy5lbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgKHJlcSwgcmVzKSA9PlxuICAgICAgICB0aGlzLndyYXBQcm9taXNlUmVxdWVzdChyZXEsIHJlcywgdGhpcy5oYW5kbGVJbXBvcnQuYmluZCh0aGlzKSlcbiAgICApO1xuXG4gICAgcm91dGVyLnBvc3QoXG4gICAgICAnL2ltcG9ydF9yZWxhdGlvbl9kYXRhLzpjbGFzc05hbWUvOnJlbGF0aW9uTmFtZScsXG4gICAgICB1cGxvYWQuc2luZ2xlKCdpbXBvcnRGaWxlJyksXG4gICAgICAvLyBtaWRkbGV3YXJlcy5hbGxvd0Nyb3NzRG9tYWluLFxuICAgICAgbWlkZGxld2FyZXMuaGFuZGxlUGFyc2VIZWFkZXJzLFxuICAgICAgbWlkZGxld2FyZXMuZW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIChyZXEsIHJlcykgPT5cbiAgICAgICAgdGhpcy53cmFwUHJvbWlzZVJlcXVlc3QocmVxLCByZXMsIHRoaXMuaGFuZGxlSW1wb3J0LmJpbmQodGhpcykpXG4gICAgKTtcblxuICAgIHJldHVybiByb3V0ZXI7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSW1wb3J0Um91dGVyO1xuIl19 \ 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..3096417ade --- /dev/null +++ b/lib/Routers/PublicAPIRouter.js @@ -0,0 +1,322 @@ +"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 { + username, + token: rawToken + } = req.query; + const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken; + 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: rawToken + } = req.query; + const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken; + + 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, + new_password, + token: rawToken + } = req.body; + const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken; + + 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}`); + } + } + + const encodedUsername = encodeURIComponent(username); + const location = result.success ? `${config.passwordResetSuccessURL}?username=${encodedUsername}` : `${config.choosePasswordURL}?${params}`; + return Promise.resolve({ + status: 302, + location + }); + }); + } + + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1B1YmxpY0FQSVJvdXRlci5qcyJdLCJuYW1lcyI6WyJwdWJsaWNfaHRtbCIsInBhdGgiLCJyZXNvbHZlIiwiX19kaXJuYW1lIiwidmlld3MiLCJQdWJsaWNBUElSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwidmVyaWZ5RW1haWwiLCJyZXEiLCJ1c2VybmFtZSIsInRva2VuIiwicmF3VG9rZW4iLCJxdWVyeSIsInRvU3RyaW5nIiwiYXBwSWQiLCJwYXJhbXMiLCJjb25maWciLCJDb25maWciLCJnZXQiLCJpbnZhbGlkUmVxdWVzdCIsInB1YmxpY1NlcnZlclVSTCIsIm1pc3NpbmdQdWJsaWNTZXJ2ZXJVUkwiLCJpbnZhbGlkTGluayIsInVzZXJDb250cm9sbGVyIiwidGhlbiIsInFzIiwic3RyaW5naWZ5IiwiUHJvbWlzZSIsInN0YXR1cyIsImxvY2F0aW9uIiwidmVyaWZ5RW1haWxTdWNjZXNzVVJMIiwiaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsiLCJyZXNlbmRWZXJpZmljYXRpb25FbWFpbCIsImJvZHkiLCJsaW5rU2VuZFN1Y2Nlc3NVUkwiLCJsaW5rU2VuZEZhaWxVUkwiLCJjaGFuZ2VQYXNzd29yZCIsInJlamVjdCIsImlkIiwidGV4dCIsImZzIiwicmVhZEZpbGUiLCJlcnIiLCJkYXRhIiwicmVwbGFjZSIsInJlcXVlc3RSZXNldFBhc3N3b3JkIiwiY2hlY2tSZXNldFRva2VuVmFsaWRpdHkiLCJhcHBsaWNhdGlvbklkIiwiYXBwIiwiYXBwTmFtZSIsImNob29zZVBhc3N3b3JkVVJMIiwicmVzZXRQYXNzd29yZCIsIm5ld19wYXNzd29yZCIsInhociIsIlBhcnNlIiwiRXJyb3IiLCJVU0VSTkFNRV9NSVNTSU5HIiwiT1RIRVJfQ0FVU0UiLCJQQVNTV09SRF9NSVNTSU5HIiwidXBkYXRlUGFzc3dvcmQiLCJzdWNjZXNzIiwicmVzdWx0IiwiZXJyb3IiLCJyZXNwb25zZSIsImVuY29kZWRVc2VybmFtZSIsImVuY29kZVVSSUNvbXBvbmVudCIsInBhc3N3b3JkUmVzZXRTdWNjZXNzVVJMIiwiaW52YWxpZExpbmtVUkwiLCJpbnZhbGlkVmVyaWZpY2F0aW9uTGlua1VSTCIsIm1lc3NhZ2UiLCJzZXRDb25maWciLCJtb3VudFJvdXRlcyIsInJvdXRlIiwiZXhwcmVzc1JvdXRlciIsInJvdXRlciIsImV4cHJlc3MiLCJSb3V0ZXIiLCJ1c2UiLCJzdGF0aWMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLFdBQVcsR0FBR0MsY0FBS0MsT0FBTCxDQUFhQyxTQUFiLEVBQXdCLG1CQUF4QixDQUFwQjs7QUFDQSxNQUFNQyxLQUFLLEdBQUdILGNBQUtDLE9BQUwsQ0FBYUMsU0FBYixFQUF3QixhQUF4QixDQUFkOztBQUVPLE1BQU1FLGVBQU4sU0FBOEJDLHNCQUE5QixDQUE0QztBQUNqREMsRUFBQUEsV0FBVyxDQUFDQyxHQUFELEVBQU07QUFDZixVQUFNO0FBQUVDLE1BQUFBLFFBQUY7QUFBWUMsTUFBQUEsS0FBSyxFQUFFQztBQUFuQixRQUFnQ0gsR0FBRyxDQUFDSSxLQUExQztBQUNBLFVBQU1GLEtBQUssR0FDVEMsUUFBUSxJQUFJLE9BQU9BLFFBQVAsS0FBb0IsUUFBaEMsR0FBMkNBLFFBQVEsQ0FBQ0UsUUFBVCxFQUEzQyxHQUFpRUYsUUFEbkU7QUFFQSxVQUFNRyxLQUFLLEdBQUdOLEdBQUcsQ0FBQ08sTUFBSixDQUFXRCxLQUF6Qjs7QUFDQSxVQUFNRSxNQUFNLEdBQUdDLGdCQUFPQyxHQUFQLENBQVdKLEtBQVgsQ0FBZjs7QUFFQSxRQUFJLENBQUNFLE1BQUwsRUFBYTtBQUNYLFdBQUtHLGNBQUw7QUFDRDs7QUFFRCxRQUFJLENBQUNILE1BQU0sQ0FBQ0ksZUFBWixFQUE2QjtBQUMzQixhQUFPLEtBQUtDLHNCQUFMLEVBQVA7QUFDRDs7QUFFRCxRQUFJLENBQUNYLEtBQUQsSUFBVSxDQUFDRCxRQUFmLEVBQXlCO0FBQ3ZCLGFBQU8s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QUNFLE1BREYsRUFFRSx3Q0FGRixFQUdFaEUsR0FBRyxJQUFJO0FBQ0wsV0FBSzhELFNBQUwsQ0FBZTlELEdBQWY7QUFDRCxLQUxILEVBTUVBLEdBQUcsSUFBSTtBQUNMLGFBQU8sS0FBS3dCLHVCQUFMLENBQTZCeEIsR0FBN0IsQ0FBUDtBQUNELEtBUkg7QUFXQSxTQUFLZ0UsS0FBTCxDQUFXLEtBQVgsRUFBa0IsdUJBQWxCLEVBQTJDaEUsR0FBRyxJQUFJO0FBQ2hELGFBQU8sS0FBSzRCLGNBQUwsQ0FBb0I1QixHQUFwQixDQUFQO0FBQ0QsS0FGRDtBQUlBLFNBQUtnRSxLQUFMLENBQ0UsTUFERixFQUVFLHFDQUZGLEVBR0VoRSxHQUFHLElBQUk7QUFDTCxXQUFLOEQsU0FBTCxDQUFlOUQsR0FBZjtBQUNELEtBTEgsRUFNRUEsR0FBRyxJQUFJO0FBQ0wsYUFBTyxLQUFLMkMsYUFBTCxDQUFtQjNDLEdBQW5CLENBQVA7QUFDRCxLQVJIO0FBV0EsU0FBS2dFLEtBQUwsQ0FDRSxLQURGLEVBRUUscUNBRkYsRUFHRWhFLEdBQUcsSUFBSTtBQUNMLFdBQUs4RCxTQUFMLENBQWU5RCxHQUFmO0FBQ0QsS0FMSCxFQU1FQSxHQUFHLElBQUk7QUFDTCxhQUFPLEtBQUtxQyxvQkFBTCxDQUEwQnJDLEdBQTFCLENBQVA7QUFDRCxLQVJIO0FBVUQ7O0FBRURpRSxFQUFBQSxhQUFhLEdBQUc7QUFDZCxVQUFNQyxNQUFNLEdBQUdDLGlCQUFRQyxNQUFSLEVBQWY7O0FBQ0FGLElBQUFBLE1BQU0sQ0FBQ0csR0FBUCxDQUFXLE9BQVgsRUFBb0JGLGlCQUFRRyxNQUFSLENBQWU5RSxXQUFmLENBQXBCO0FBQ0EwRSxJQUFBQSxNQUFNLENBQUNHLEdBQVAsQ0FBVyxHQUFYLEVBQWdCLE1BQU1KLGFBQU4sRUFBaEI7QUFDQSxXQUFPQyxNQUFQO0FBQ0Q7O0FBOVRnRDs7O2VBaVVwQ3JFLGUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi4vQ29uZmlnJztcbmltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHFzIGZyb20gJ3F1ZXJ5c3RyaW5nJztcbmltcG9ydCB7IFBhcnNlIH0gZnJvbSAncGFyc2Uvbm9kZSc7XG5cbmNvbnN0IHB1YmxpY19odG1sID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uLy4uL3B1YmxpY19odG1sJyk7XG5jb25zdCB2aWV3cyA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi8uLi92aWV3cycpO1xuXG5leHBvcnQgY2xhc3MgUHVibGljQVBJUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIHZlcmlmeUVtYWlsKHJlcSkge1xuICAgIGNvbnN0IHsgdXNlcm5hbWUsIHRva2VuOiByYXdUb2tlbiB9ID0gcmVxLnF1ZXJ5O1xuICAgIGNvbnN0IHRva2VuID1cbiAgICAgIHJhd1Rva2VuICYmIHR5cGVvZiByYXdUb2tlbiAhPT0gJ3N0cmluZycgPyByYXdUb2tlbi50b1N0cmluZygpIDogcmF3VG9rZW47XG4gICAgY29uc3QgYXBwSWQgPSByZXEucGFyYW1zLmFwcElkO1xuICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoYXBwSWQpO1xuXG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwpIHtcbiAgICAgIHJldHVybiB0aGlzLm1pc3NpbmdQdWJsaWNTZXJ2ZXJVUkwoKTtcbiAgICB9XG5cbiAgICBpZiAoIXRva2VuIHx8ICF1c2VybmFtZSkge1xuICAgICAgcmV0dXJuIHRoaXMuaW52YWxpZExpbmsocmVxKTtcbiAgICB9XG5cbiAgICBjb25zdCB1c2VyQ29udHJvbGxlciA9IGNvbmZpZy51c2VyQ29udHJvbGxlcjtcbiAgICByZXR1cm4gdXNlckNvbnRyb2xsZXIudmVyaWZ5RW1haWwodXNlcm5hbWUsIHRva2VuKS50aGVuKFxuICAgICAgKCkgPT4ge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBxcy5zdHJpbmdpZnkoeyB1c2VybmFtZSB9KTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgICAgbG9jYXRpb246IGAke2NvbmZpZy52ZXJpZnlFbWFpbFN1Y2Nlc3NVUkx9PyR7cGFyYW1zfWAsXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgICgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsocmVxKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcmVzZW5kVmVyaWZpY2F0aW9uRW1haWwocmVxKSB7XG4gICAgY29uc3QgdXNlcm5hbWUgPSByZXEuYm9keS51c2VybmFtZTtcbiAgICBjb25zdCBhcHBJZCA9IHJlcS5wYXJhbXMuYXBwSWQ7XG4gICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChhcHBJZCk7XG5cbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgdGhpcy5pbnZhbGlkUmVxdWVzdCgpO1xuICAgIH1cblxuICAgIGlmICghY29uZmlnLnB1YmxpY1NlcnZlclVSTCkge1xuICAgICAgcmV0dXJuIHRoaXMubWlzc2luZ1B1YmxpY1NlcnZlclVSTCgpO1xuICAgIH1cblxuICAgIGlmICghdXNlcm5hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlckNvbnRyb2xsZXIgPSBjb25maWcudXNlckNvbnRyb2xsZXI7XG5cbiAgICByZXR1cm4gdXNlckNvbnRyb2xsZXIucmVzZW5kVmVyaWZpY2F0aW9uRW1haWwodXNlcm5hbWUpLnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIHN0YXR1czogMzAyLFxuICAgICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcubGlua1NlbmRTdWNjZXNzVVJMfWAsXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgICgpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgICAgbG9jYXRpb246IGAke2NvbmZpZy5saW5rU2VuZEZhaWxVUkx9YCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIGNoYW5nZVBhc3N3b3JkKHJlcSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBjb25maWcgPSBDb25maWcuZ2V0KHJlcS5xdWVyeS5pZCk7XG5cbiAgICAgIGlmICghY29uZmlnKSB7XG4gICAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFjb25maWcucHVibGljU2VydmVyVVJMKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlKHtcbiAgICAgICAgICBzdGF0dXM6IDQwNCxcbiAgICAgICAgICB0ZXh0OiAnTm90IGZvdW5kLicsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgLy8gU2hvdWxkIHdlIGtlZXAgdGhlIGZpbGUgaW4gbWVtb3J5IG9yIGxlYXZlIGxpa2UgdGhhdD9cbiAgICAgIGZzLnJlYWRGaWxlKFxuICAgICAgICBwYXRoLnJlc29sdmUodmlld3MsICdjaG9vc2VfcGFzc3dvcmQnKSxcbiAgICAgICAgJ3V0Zi04JyxcbiAgICAgICAgKGVyciwgZGF0YSkgPT4ge1xuICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZGF0YSA9IGRhdGEucmVwbGFjZShcbiAgICAgICAgICAgICdQQVJTRV9TRVJWRVJfVVJMJyxcbiAgICAgICAgICAgIGAnJHtjb25maWcucHVibGljU2VydmVyVVJMfSdgXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgIHRleHQ6IGRhdGEsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICByZXF1ZXN0UmVzZXRQYXNzd29yZChyZXEpIHtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuXG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwpIHtcbiAgICAgIHJldHVybiB0aGlzLm1pc3NpbmdQdWJsaWNTZXJ2ZXJVUkwoKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IHVzZXJuYW1lLCB0b2tlbjogcmF3VG9rZW4gfSA9IHJlcS5xdWVyeTtcbiAgICBjb25zdCB0b2tlbiA9XG4gICAgICByYXdUb2tlbiAmJiB0eXBlb2YgcmF3VG9rZW4gIT09ICdzdHJpbmcnID8gcmF3VG9rZW4udG9TdHJpbmcoKSA6IHJhd1Rva2VuO1xuXG4gICAgaWYgKCF1c2VybmFtZSB8fCAhdG9rZW4pIHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZy51c2VyQ29udHJvbGxlci5jaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSh1c2VybmFtZSwgdG9rZW4pLnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHFzLnN0cmluZ2lmeSh7XG4gICAgICAgICAgdG9rZW4sXG4gICAgICAgICAgaWQ6IGNvbmZpZy5hcHBsaWNhdGlvbklkLFxuICAgICAgICAgIHVzZXJuYW1lLFxuICAgICAgICAgIGFwcDogY29uZmlnLmFwcE5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBzdGF0dXM6IDMwMixcbiAgICAgICAgICBsb2NhdGlvbjogYCR7Y29uZmlnLmNob29zZVBhc3N3b3JkVVJMfT8ke3BhcmFtc31gLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHJlc2V0UGFzc3dvcmQocmVxKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcblxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgfVxuXG4gICAgaWYgKCFjb25maWcucHVibGljU2VydmVyVVJMKSB7XG4gICAgICByZXR1cm4gdGhpcy5taXNzaW5nUHVibGljU2VydmVyVVJMKCk7XG4gICAgfVxuXG4gICAgY29uc3QgeyB1c2VybmFtZSwgbmV3X3Bhc3N3b3JkLCB0b2tlbjogcmF3VG9rZW4gfSA9IHJlcS5ib2R5O1xuICAgIGNvbnN0IHRva2VuID1cbiAgICAgIHJhd1Rva2VuICYmIHR5cGVvZiByYXdUb2tlbiAhPT0gJ3N0cmluZycgPyByYXdUb2tlbi50b1N0cmluZygpIDogcmF3VG9rZW47XG5cbiAgICBpZiAoKCF1c2VybmFtZSB8fCAhdG9rZW4gfHwgIW5ld19wYXNzd29yZCkgJiYgcmVxLnhociA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgfVxuXG4gICAgaWYgKCF1c2VybmFtZSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlVTRVJOQU1FX01JU1NJTkcsICdNaXNzaW5nIHVzZXJuYW1lJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlbikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9USEVSX0NBVVNFLCAnTWlzc2luZyB0b2tlbicpO1xuICAgIH1cblxuICAgIGlmICghbmV3X3Bhc3N3b3JkKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUEFTU1dPUkRfTUlTU0lORywgJ01pc3NpbmcgcGFzc3dvcmQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29uZmlnLnVzZXJDb250cm9sbGVyXG4gICAgICAudXBkYXRlUGFzc3dvcmQodXNlcm5hbWUsIHRva2VuLCBuZXdfcGFzc3dvcmQpXG4gICAgICAudGhlbihcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyID0+IHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgZXJyLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICApXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBxcy5zdHJpbmdpZnkoe1xuICAgICAgICAgIHVzZXJuYW1lOiB1c2VybmFtZSxcbiAgICAgICAgICB0b2tlbjogdG9rZW4sXG4gICAgICAgICAgaWQ6IGNvbmZpZy5hcHBsaWNhdGlvbklkLFxuICAgICAgICAgIGVycm9yOiByZXN1bHQuZXJyLFxuICAgICAgICAgIGFwcDogY29uZmlnLmFwcE5hbWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChyZXEueGhyKSB7XG4gICAgICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICAgICAgc3RhdHVzOiAyMDAsXG4gICAgICAgICAgICAgIHJlc3BvbnNlOiAnUGFzc3dvcmQgc3VjY2Vzc2Z1bGx5IHJlc2V0JyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocmVzdWx0LmVycikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9USEVSX0NBVVNFLCBgJHtyZXN1bHQuZXJyfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGVuY29kZWRVc2VybmFtZSA9IGVuY29kZVVSSUNvbXBvbmVudCh1c2VybmFtZSk7XG4gICAgICAgIGNvbnN0IGxvY2F0aW9uID0gcmVzdWx0LnN1Y2Nlc3NcbiAgICAgICAgICA/IGAke2NvbmZpZy5wYXNzd29yZFJlc2V0U3VjY2Vzc1VSTH0/dXNlcm5hbWU9JHtlbmNvZGVkVXNlcm5hbWV9YFxuICAgICAgICAgIDogYCR7Y29uZmlnLmNob29zZVBhc3N3b3JkVVJMfT8ke3BhcmFtc31gO1xuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIHN0YXR1czogMzAyLFxuICAgICAgICAgIGxvY2F0aW9uLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaW52YWxpZExpbmsocmVxKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICBzdGF0dXM6IDMwMixcbiAgICAgIGxvY2F0aW9uOiByZXEuY29uZmlnLmludmFsaWRMaW5rVVJMLFxuICAgIH0pO1xuICB9XG5cbiAgaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsocmVxKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcbiAgICBpZiAocmVxLnF1ZXJ5LnVzZXJuYW1lICYmIHJlcS5wYXJhbXMuYXBwSWQpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHFzLnN0cmluZ2lmeSh7XG4gICAgICAgIHVzZXJuYW1lOiByZXEucXVlcnkudXNlcm5hbWUsXG4gICAgICAgIGFwcElkOiByZXEucGFyYW1zLmFwcElkLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcuaW52YWxpZFZlcmlmaWNhdGlvbkxpbmtVUkx9PyR7cGFyYW1zfWAsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuaW52YWxpZExpbmsocmVxKTtcbiAgICB9XG4gIH1cblxuICBtaXNzaW5nUHVibGljU2VydmVyVVJMKCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgdGV4dDogJ05vdCBmb3VuZC4nLFxuICAgICAgc3RhdHVzOiA0MDQsXG4gICAgfSk7XG4gIH1cblxuICBpbnZhbGlkUmVxdWVzdCgpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIGVycm9yLnN0YXR1cyA9IDQwMztcbiAgICBlcnJvci5tZXNzYWdlID0gJ3VuYXV0aG9yaXplZCc7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBzZXRDb25maWcocmVxKSB7XG4gICAgcmVxLmNvbmZpZyA9IENvbmZpZy5nZXQocmVxLnBhcmFtcy5hcHBJZCk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9hcHBzLzphcHBJZC92ZXJpZnlfZW1haWwnLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgdGhpcy5zZXRDb25maWcocmVxKTtcbiAgICAgIH0sXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy52ZXJpZnlFbWFpbChyZXEpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ1BPU1QnLFxuICAgICAgJy9hcHBzLzphcHBJZC9yZXNlbmRfdmVyaWZpY2F0aW9uX2VtYWlsJyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHRoaXMuc2V0Q29uZmlnKHJlcSk7XG4gICAgICB9LFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzZW5kVmVyaWZpY2F0aW9uRW1haWwocmVxKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9hcHBzL2Nob29zZV9wYXNzd29yZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5jaGFuZ2VQYXNzd29yZChyZXEpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQT1NUJyxcbiAgICAgICcvYXBwcy86YXBwSWQvcmVxdWVzdF9wYXNzd29yZF9yZXNldCcsXG4gICAgICByZXEgPT4ge1xuICAgICAgICB0aGlzLnNldENvbmZpZyhyZXEpO1xuICAgICAgfSxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlc2V0UGFzc3dvcmQocmVxKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgJy9hcHBzLzphcHBJZC9yZXF1ZXN0X3Bhc3N3b3JkX3Jlc2V0JyxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHRoaXMuc2V0Q29uZmlnKHJlcSk7XG4gICAgICB9LFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVxdWVzdFJlc2V0UGFzc3dvcmQocmVxKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgZXhwcmVzc1JvdXRlcigpIHtcbiAgICBjb25zdCByb3V0ZXIgPSBleHByZXNzLlJvdXRlcigpO1xuICAgIHJvdXRlci51c2UoJy9hcHBzJywgZXhwcmVzcy5zdGF0aWMocHVibGljX2h0bWwpKTtcbiAgICByb3V0ZXIudXNlKCcvJywgc3VwZXIuZXhwcmVzc1JvdXRlcigpKTtcbiAgICByZXR1cm4gcm91dGVyO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1YmxpY0FQSVJvdXRlcjtcbiJdfQ== \ 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1Nlc3Npb25zUm91dGVyLmpzIl0sIm5hbWVzIjpbIlNlc3Npb25zUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsImhhbmRsZU1lIiwicmVxIiwiaW5mbyIsInNlc3Npb25Ub2tlbiIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJyZXN0IiwiZmluZCIsImNvbmZpZyIsIkF1dGgiLCJtYXN0ZXIiLCJ1bmRlZmluZWQiLCJjbGllbnRTREsiLCJ0aGVuIiwicmVzcG9uc2UiLCJyZXN1bHRzIiwibGVuZ3RoIiwiaGFuZGxlVXBkYXRlVG9SZXZvY2FibGVTZXNzaW9uIiwidXNlciIsImF1dGgiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwic2Vzc2lvbkRhdGEiLCJjcmVhdGVTZXNzaW9uIiwidXNlcklkIiwiaWQiLCJjcmVhdGVkV2l0aCIsImFjdGlvbiIsImluc3RhbGxhdGlvbklkIiwiZGF0YWJhc2UiLCJ1cGRhdGUiLCJvYmplY3RJZCIsIl9fb3AiLCJQcm9taXNlIiwicmVzb2x2ZSIsIm1vdW50Um91dGVzIiwicm91dGUiLCJoYW5kbGVGaW5kIiwiaGFuZGxlR2V0IiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFTyxNQUFNQSxjQUFOLFNBQTZCQyxzQkFBN0IsQ0FBMkM7QUFDaERDLEVBQUFBLFNBQVMsR0FBRztBQUNWLFdBQU8sVUFBUDtBQUNEOztBQUVEQyxFQUFBQSxRQUFRLENBQUNDLEdBQUQsRUFBTTtBQUNaO0FBQ0EsUUFBSSxDQUFDQSxHQUFHLENBQUNDLElBQUwsSUFBYSxDQUFDRCxHQUFHLENBQUNDLElBQUosQ0FBU0MsWUFBM0IsRUFBeUM7QUFDdkMsWUFBTSxJQUFJQyxjQUFNQyxLQUFWLENBQ0pELGNBQU1DLEtBQU4sQ0FBWUMscUJBRFIsRUFFSix5QkFGSSxDQUFOO0FBSUQ7O0FBQ0QsV0FBT0MsY0FDSkMsSUFESSxDQUVIUCxHQUFHLENBQUNRLE1BRkQsRUFHSEMsY0FBS0MsTUFBTCxDQUFZVixHQUFHLENBQUNRLE1BQWhCLENBSEcsRUFJSCxVQUpHLEVBS0g7QUFBRU4sTUFBQUEsWUFBWSxFQUFFRixHQUFHLENBQUNDLElBQUosQ0FBU0M7QUFBekIsS0FMRyxFQU1IUyxTQU5HLEVBT0hYLEdBQUcsQ0FBQ0MsSUFBSixDQUFTVyxTQVBOLEVBU0pDLElBVEksQ0FTQ0MsUUFBUSxJQUFJO0FBQ2hCLFVBQUksQ0FBQ0EsUUFBUSxDQUFDQyxPQUFWLElBQXFCRCxRQUFRLENBQUNDLE9BQVQsQ0FBaUJDLE1BQWpCLElBQTJCLENBQXBELEVBQXVEO0FBQ3JELGNBQU0sSUFBSWIsY0FBTUMsS0FBVixDQUNKRCxjQUFNQyxLQUFOLENBQVlDLHFCQURSLEVBRUosMEJBRkksQ0FBTjtBQUlEOztBQUNELGFBQU87QUFDTFMsUUFBQUEsUUFBUSxFQUFFQSxRQUFRLENBQUNDLE9BQVQsQ0FBaUIsQ0FBakI7QUFETCxPQUFQO0FBR0QsS0FuQkksQ0FBUDtBQW9CRDs7QUFFREUsRUFBQUEsOEJBQThCLENBQUNqQixHQUFELEVBQU07QUFDbEMsVUFBTVEsTUFBTSxHQUFHUixHQUFHLENBQUNRLE1BQW5CO0FBQ0EsVUFBTVUsSUFBSSxHQUFHbEIsR0FBRyxDQUFDbUIsSUFBSixDQUFTRCxJQUF0QixDQUZrQyxDQUdsQztBQUNBOztBQUNBLFFBQUksQ0FBQ0EsSUFBTCxFQUFXO0FBQ1QsWUFBTSxJQUFJZixjQUFNQyxLQUFWLENBQWdCRCxjQUFNQyxLQUFOLENBQVlnQixnQkFBNUIsRUFBOEMsaUJBQTlDLENBQU47QUFDRDs7QUFDRCxVQUFNO0FBQUVDLE1BQUFBLFdBQUY7QUFBZUMsTUFBQUE7QUFBZixRQUFpQ2IsY0FBS2EsYUFBTCxDQUFtQmQsTUFBbkIsRUFBMkI7QUFDaEVlLE1BQUFBLE1BQU0sRUFBRUwsSUFBSSxDQUFDTSxFQURtRDtBQUVoRUMsTUFBQUEsV0FBVyxFQUFFO0FBQ1hDLFFBQUFBLE1BQU0sRUFBRTtBQURHLE9BRm1EO0FBS2hFQyxNQUFBQSxjQUFjLEVBQUUzQixHQUFHLENBQUNtQixJQUFKLENBQVNRO0FBTHVDLEtBQTNCLENBQXZDOztBQVFBLFdBQU9MLGFBQWEsR0FDakJULElBREksQ0FDQyxNQUFNO0FBQ1Y7QUFDQSxhQUFPTCxNQUFNLENBQUNvQixRQUFQLENBQWdCQyxNQUFoQixDQUNMLE9BREssRUFFTDtBQUNFQyxRQUFBQSxRQUFRLEVBQUVaLElBQUksQ0FBQ007QUFEakIsT0FGSyxFQUtMO0FBQ0V0QixRQUFBQSxZQUFZLEVBQUU7QUFBRTZCLFVBQUFBLElBQUksRUFBRTtBQUFSO0FBRGhCLE9BTEssQ0FBUDtBQVNELEtBWkksRUFhSmxCLElBYkksQ0FhQyxNQUFNO0FBQ1YsYUFBT21CLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQjtBQUFFbkIsUUFBQUEsUUFBUSxFQUFFTztBQUFaLE9BQWhCLENBQVA7QUFDRCxLQWZJLENBQVA7QUFnQkQ7O0FBRURhLEVBQUFBLFdBQVcsR0FBRztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxLQUFYLEVBQWtCLGNBQWxCLEVBQWtDbkMsR0FBRyxJQUFJO0FBQ3ZDLGFBQU8sS0FBS0QsUUFBTCxDQUFjQyxHQUFkLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS21DLEtBQUwsQ0FBVyxLQUFYLEVBQWtCLFdBQWxCLEVBQStCbkMsR0FBRyxJQUFJO0FBQ3BDLGFBQU8sS0FBS29DLFVBQUwsQ0FBZ0JwQyxHQUFoQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttQyxLQUFMLENBQVcsS0FBWCxFQUFrQixxQkFBbEIsRUFBeUNuQyxHQUFHLElBQUk7QUFDOUMsYUFBTyxLQUFLcUMsU0FBTCxDQUFlckMsR0FBZixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttQyxLQUFMLENBQVcsTUFBWCxFQUFtQixXQUFuQixFQUFnQ25DLEdBQUcsSUFBSTtBQUNyQyxhQUFPLEtBQUtzQyxZQUFMLENBQWtCdEMsR0FBbEIsQ0FBUDtBQUNELEtBRkQ7QUFHQSxTQUFLbUMsS0FBTCxDQUFXLEtBQVgsRUFBa0IscUJBQWxCLEVBQXlDbkMsR0FBRyxJQUFJO0FBQzlDLGFBQU8sS0FBS3VDLFlBQUwsQ0FBa0J2QyxHQUFsQixDQUFQO0FBQ0QsS0FGRDtBQUdBLFNBQUttQyxLQUFMLENBQVcsUUFBWCxFQUFxQixxQkFBckIsRUFBNENuQyxHQUFHLElBQUk7QUFDakQsYUFBTyxLQUFLd0MsWUFBTCxDQUFrQnhDLEdBQWxCLENBQVA7QUFDRCxLQUZEO0FBR0EsU0FBS21DLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLDRCQUFuQixFQUFpRG5DLEdBQUcsSUFBSTtBQUN0RCxhQUFPLEtBQUtpQiw4QkFBTCxDQUFvQ2pCLEdBQXBDLENBQVA7QUFDRCxLQUZEO0FBR0Q7O0FBM0YrQzs7O2VBOEZuQ0osYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4uL0F1dGgnO1xuXG5leHBvcnQgY2xhc3MgU2Vzc2lvbnNSb3V0ZXIgZXh0ZW5kcyBDbGFzc2VzUm91dGVyIHtcbiAgY2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnX1Nlc3Npb24nO1xuICB9XG5cbiAgaGFuZGxlTWUocmVxKSB7XG4gICAgLy8gVE9ETzogVmVyaWZ5IGNvcnJlY3QgYmVoYXZpb3JcbiAgICBpZiAoIXJlcS5pbmZvIHx8ICFyZXEuaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAnU2Vzc2lvbiB0b2tlbiByZXF1aXJlZC4nXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdFxuICAgICAgLmZpbmQoXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIEF1dGgubWFzdGVyKHJlcS5jb25maWcpLFxuICAgICAgICAnX1Nlc3Npb24nLFxuICAgICAgICB7IHNlc3Npb25Ub2tlbjogcmVxLmluZm8uc2Vzc2lvblRva2VuIH0sXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgcmVxLmluZm8uY2xpZW50U0RLXG4gICAgICApXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIGlmICghcmVzcG9uc2UucmVzdWx0cyB8fCByZXNwb25zZS5yZXN1bHRzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICAgJ1Nlc3Npb24gdG9rZW4gbm90IGZvdW5kLidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVzcG9uc2U6IHJlc3BvbnNlLnJlc3VsdHNbMF0sXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZVVwZGF0ZVRvUmV2b2NhYmxlU2Vzc2lvbihyZXEpIHtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuICAgIGNvbnN0IHVzZXIgPSByZXEuYXV0aC51c2VyO1xuICAgIC8vIElzc3VlICMyNzIwXG4gICAgLy8gQ2FsbGluZyB3aXRob3V0IGEgc2Vzc2lvbiB0b2tlbiB3b3VsZCByZXN1bHQgaW4gYSBub3QgZm91bmQgdXNlclxuICAgIGlmICghdXNlcikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdpbnZhbGlkIHNlc3Npb24nKTtcbiAgICB9XG4gICAgY29uc3QgeyBzZXNzaW9uRGF0YSwgY3JlYXRlU2Vzc2lvbiB9ID0gQXV0aC5jcmVhdGVTZXNzaW9uKGNvbmZpZywge1xuICAgICAgdXNlcklkOiB1c2VyLmlkLFxuICAgICAgY3JlYXRlZFdpdGg6IHtcbiAgICAgICAgYWN0aW9uOiAndXBncmFkZScsXG4gICAgICB9LFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5hdXRoLmluc3RhbGxhdGlvbklkLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNyZWF0ZVNlc3Npb24oKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBkZWxldGUgdGhlIHNlc3Npb24gdG9rZW4sIHVzZSB0aGUgZGIgdG8gc2tpcCBiZWZvcmVTYXZlXG4gICAgICAgIHJldHVybiBjb25maWcuZGF0YWJhc2UudXBkYXRlKFxuICAgICAgICAgICdfVXNlcicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgb2JqZWN0SWQ6IHVzZXIuaWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzZXNzaW9uVG9rZW46IHsgX19vcDogJ0RlbGV0ZScgfSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgcmVzcG9uc2U6IHNlc3Npb25EYXRhIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3Nlc3Npb25zL21lJywgcmVxID0+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..807005274e --- /dev/null +++ b/lib/Routers/UsersRouter.js @@ -0,0 +1,434 @@ +"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 }; } + +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 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(); + + const afterLoginUser = _node.default.User.fromJSON(Object.assign({ + className: '_User' + }, user)); + + (0, _triggers.maybeRunTrigger)(_triggers.Types.afterLogin, _objectSpread({}, req.auth, { + user: afterLoginUser + }), afterLoginUser, null, req.config); + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1VzZXJzUm91dGVyLmpzIl0sIm5hbWVzIjpbIlVzZXJzUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsInJlbW92ZUhpZGRlblByb3BlcnRpZXMiLCJvYmoiLCJrZXkiLCJPYmplY3QiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJ0ZXN0IiwiX2F1dGhlbnRpY2F0ZVVzZXJGcm9tUmVxdWVzdCIsInJlcSIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwicGF5bG9hZCIsImJvZHkiLCJ1c2VybmFtZSIsInF1ZXJ5IiwiZW1haWwiLCJwYXNzd29yZCIsIlBhcnNlIiwiRXJyb3IiLCJVU0VSTkFNRV9NSVNTSU5HIiwiUEFTU1dPUkRfTUlTU0lORyIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ1c2VyIiwiaXNWYWxpZFBhc3N3b3JkIiwiJG9yIiwiY29uZmlnIiwiZGF0YWJhc2UiLCJmaW5kIiwidGhlbiIsInJlc3VsdHMiLCJsZW5ndGgiLCJsb2dnZXJDb250cm9sbGVyIiwid2FybiIsImZpbHRlciIsInBhc3N3b3JkQ3J5cHRvIiwiY29tcGFyZSIsImNvcnJlY3QiLCJhY2NvdW50TG9ja291dFBvbGljeSIsIkFjY291bnRMb2Nrb3V0IiwiaGFuZGxlTG9naW5BdHRlbXB0IiwiYXV0aCIsImlzTWFzdGVyIiwiQUNMIiwia2V5cyIsInZlcmlmeVVzZXJFbWFpbHMiLCJwcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsIiwiZW1haWxWZXJpZmllZCIsIkVNQUlMX05PVF9GT1VORCIsImF1dGhEYXRhIiwiZm9yRWFjaCIsInByb3ZpZGVyIiwiY2F0Y2giLCJlcnJvciIsImhhbmRsZU1lIiwiaW5mbyIsInNlc3Npb25Ub2tlbiIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsInJlc3QiLCJBdXRoIiwibWFzdGVyIiwiaW5jbHVkZSIsImNsaWVudFNESyIsInJlc3BvbnNlIiwiaGFuZGxlTG9nSW4iLCJwYXNzd29yZFBvbGljeSIsIm1heFBhc3N3b3JkQWdlIiwiY2hhbmdlZEF0IiwiX3Bhc3N3b3JkX2NoYW5nZWRfYXQiLCJEYXRlIiwidXBkYXRlIiwiX2VuY29kZSIsIl9fdHlwZSIsImlzbyIsImV4cGlyZXNBdCIsImdldFRpbWUiLCJmaWxlc0NvbnRyb2xsZXIiLCJleHBhbmRGaWxlc0luT2JqZWN0IiwiVHJpZ2dlclR5cGVzIiwiYmVmb3JlTG9naW4iLCJVc2VyIiwiZnJvbUpTT04iLCJhc3NpZ24iLCJzZXNzaW9uRGF0YSIsImNyZWF0ZVNlc3Npb24iLCJ1c2VySWQiLCJvYmplY3RJZCIsImNyZWF0ZWRXaXRoIiwiYWN0aW9uIiwiYXV0aFByb3ZpZGVyIiwiaW5zdGFsbGF0aW9uSWQiLCJhZnRlckxvZ2luVXNlciIsImFmdGVyTG9naW4iLCJoYW5kbGVWZXJpZnlQYXNzd29yZCIsImhhbmRsZUxvZ091dCIsInN1Y2Nlc3MiLCJ1bmRlZmluZWQiLCJyZWNvcmRzIiwiZGVsIiwiX3J1bkFmdGVyTG9nb3V0VHJpZ2dlciIsInNlc3Npb24iLCJhZnRlckxvZ291dCIsIlNlc3Npb24iLCJfdGhyb3dPbkJhZEVtYWlsQ29uZmlnIiwiQ29uZmlnIiwidmFsaWRhdGVFbWFpbENvbmZpZ3VyYXRpb24iLCJlbWFpbEFkYXB0ZXIiLCJ1c2VyQ29udHJvbGxlciIsImFkYXB0ZXIiLCJhcHBOYW1lIiwicHVibGljU2VydmVyVVJMIiwiZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJlIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiaGFuZGxlUmVzZXRSZXF1ZXN0IiwiRU1BSUxfTUlTU0lORyIsIklOVkFMSURfRU1BSUxfQUREUkVTUyIsInNlbmRQYXNzd29yZFJlc2V0RW1haWwiLCJlcnIiLCJjb2RlIiwiaGFuZGxlVmVyaWZpY2F0aW9uRW1haWxSZXF1ZXN0IiwiT1RIRVJfQ0FVU0UiLCJyZWdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbiIsInNlbmRWZXJpZmljYXRpb25FbWFpbCIsIm1vdW50Um91dGVzIiwicm91dGUiLCJoYW5kbGVGaW5kIiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlR2V0IiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7QUFFTyxNQUFNQSxXQUFOLFNBQTBCQyxzQkFBMUIsQ0FBd0M7QUFDN0NDLEVBQUFBLFNBQVMsR0FBRztBQUNWLFdBQU8sT0FBUDtBQUNEO0FBRUQ7Ozs7OztBQUlBLFNBQU9DLHNCQUFQLENBQThCQyxHQUE5QixFQUFtQztBQUNqQyxTQUFLLElBQUlDLEdBQVQsSUFBZ0JELEdBQWhCLEVBQXFCO0FBQ25CLFVBQUlFLE1BQU0sQ0FBQ0MsU0FBUCxDQUFpQkMsY0FBakIsQ0FBZ0NDLElBQWhDLENBQXFDTCxHQUFyQyxFQUEwQ0MsR0FBMUMsQ0FBSixFQUFvRDtBQUNsRDtBQUNBLFlBQUlBLEdBQUcsS0FBSyxRQUFSLElBQW9CLENBQUMsMEJBQTBCSyxJQUExQixDQUErQkwsR0FBL0IsQ0FBekIsRUFBOEQ7QUFDNUQsaUJBQU9ELEdBQUcsQ0FBQ0MsR0FBRCxDQUFWO0FBQ0Q7QUFDRjtBQUNGO0FBQ0Y7QUFFRDs7Ozs7Ozs7QUFNQU0sRUFBQUEsNEJBQTRCLENBQUNDLEdBQUQsRUFBTTtBQUNoQyxXQUFPLElBQUlDLE9BQUosQ0FBWSxDQUFDQyxPQUFELEVBQVVDLE1BQVYsS0FBcUI7QUFDdEM7QUFDQSxVQUFJQyxPQUFPLEdBQUdKLEdBQUcsQ0FBQ0ssSUFBbEI7O0FBQ0EsVUFDRyxDQUFDRCxPQUFPLENBQUNFLFFBQVQsSUFBcUJOLEdBQUcsQ0FBQ08sS0FBSixDQUFVRCxRQUFoQyxJQUNDLENBQUNGLE9BQU8sQ0FBQ0ksS0FBVCxJQUFrQlIsR0FBRyxDQUFDTyxLQUFKLENBQVVDLEtBRi9CLEVBR0U7QUFDQUosUUFBQUEsT0FBTyxHQUFHSixHQUFHLENBQUNPLEtBQWQ7QUFDRDs7QUFDRCxZQUFNO0FBQUVE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a0IsaUJBQWxCLEVBQXFDckgsR0FBRyxJQUFJO0FBQzFDLGFBQU8sS0FBS3FGLG9CQUFMLENBQTBCckYsR0FBMUIsQ0FBUDtBQUNELEtBRkQ7QUFHRDs7QUFsZDRDOzs7ZUFxZGhDWixXIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhlc2UgbWV0aG9kcyBoYW5kbGUgdGhlIFVzZXItcmVsYXRlZCByb3V0ZXMuXG5cbmltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi4vQ29uZmlnJztcbmltcG9ydCBBY2NvdW50TG9ja291dCBmcm9tICcuLi9BY2NvdW50TG9ja291dCc7XG5pbXBvcnQgQ2xhc3Nlc1JvdXRlciBmcm9tICcuL0NsYXNzZXNSb3V0ZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgQXV0aCBmcm9tICcuLi9BdXRoJztcbmltcG9ydCBwYXNzd29yZENyeXB0byBmcm9tICcuLi9wYXNzd29yZCc7XG5pbXBvcnQgeyBtYXliZVJ1blRyaWdnZXIsIFR5cGVzIGFzIFRyaWdnZXJUeXBlcyB9IGZyb20gJy4uL3RyaWdnZXJzJztcblxuZXhwb3J0IGNsYXNzIFVzZXJzUm91dGVyIGV4dGVuZHMgQ2xhc3Nlc1JvdXRlciB7XG4gIGNsYXNzTmFtZSgpIHtcbiAgICByZXR1cm4gJ19Vc2VyJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGFsbCBcIl9cIiBwcmVmaXhlZCBwcm9wZXJ0aWVzIGZyb20gYW4gb2JqZWN0LCBleGNlcHQgXCJfX3R5cGVcIlxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIEFuIG9iamVjdC5cbiAgICovXG4gIHN0YXRpYyByZW1vdmVIaWRkZW5Qcm9wZXJ0aWVzKG9iaikge1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgICAgIC8vIFJlZ2V4cCBjb21lcyBmcm9tIFBhcnNlLk9iamVjdC5wcm90b3R5cGUudmFsaWRhdGVcbiAgICAgICAgaWYgKGtleSAhPT0gJ19fdHlwZScgJiYgIS9eW0EtWmEtel1bMC05QS1aYS16X10qJC8udGVzdChrZXkpKSB7XG4gICAgICAgICAgZGVsZXRlIG9ialtrZXldO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhIHBhc3N3b3JkIHJlcXVlc3QgaW4gbG9naW4gYW5kIHZlcmlmeVBhc3N3b3JkXG4gICAqIEBwYXJhbSB7T2JqZWN0fSByZXEgVGhlIHJlcXVlc3RcbiAgICogQHJldHVybnMge09iamVjdH0gVXNlciBvYmplY3RcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9hdXRoZW50aWNhdGVVc2VyRnJvbVJlcXVlc3QocmVxKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIFVzZSBxdWVyeSBwYXJhbWV0ZXJzIGluc3RlYWQgaWYgcHJvdmlkZWQgaW4gdXJsXG4gICAgICBsZXQgcGF5bG9hZCA9IHJlcS5ib2R5O1xuICAgICAgaWYgKFxuICAgICAgICAoIXBheWxvYWQudXNlcm5hbWUgJiYgcmVxLnF1ZXJ5LnVzZXJuYW1lKSB8fFxuICAgICAgICAoIXBheWxvYWQuZW1haWwgJiYgcmVxLnF1ZXJ5LmVtYWlsKVxuICAgICAgKSB7XG4gICAgICAgIHBheWxvYWQgPSByZXEucXVlcnk7XG4gICAgICB9XG4gICAgICBjb25zdCB7IHVzZXJuYW1lLCBlbWFpbCwgcGFzc3dvcmQgfSA9IHBheWxvYWQ7XG5cbiAgICAgIC8vIFRPRE86IHVzZSB0aGUgcmlnaHQgZXJyb3IgY29kZXMgLyBkZXNjcmlwdGlvbnMuXG4gICAgICBpZiAoIXVzZXJuYW1lICYmICFlbWFpbCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuVVNFUk5BTUVfTUlTU0lORyxcbiAgICAgICAgICAndXNlcm5hbWUvZW1haWwgaXMgcmVxdWlyZWQuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKCFwYXNzd29yZCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuUEFTU1dPUkRfTUlTU0lORyxcbiAgICAgICAgICAncGFzc3dvcmQgaXMgcmVxdWlyZWQuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgcGFzc3dvcmQgIT09ICdzdHJpbmcnIHx8XG4gICAgICAgIChlbWFpbCAmJiB0eXBlb2YgZW1haWwgIT09ICdzdHJpbmcnKSB8fFxuICAgICAgICAodXNlcm5hbWUgJiYgdHlwZW9mIHVzZXJuYW1lICE9PSAnc3RyaW5nJylcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAnSW52YWxpZCB1c2VybmFtZS9wYXNzd29yZC4nXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGxldCB1c2VyO1xuICAgICAgbGV0IGlzVmFsaWRQYXNzd29yZCA9IGZhbHNlO1xuICAgICAgbGV0IHF1ZXJ5O1xuICAgICAgaWYgKGVtYWlsICYmIHVzZXJuYW1lKSB7XG4gICAgICAgIHF1ZXJ5ID0geyBlbWFpbCwgdXNlcm5hbWUgfTtcbiAgICAgIH0gZWxzZSBpZiAoZW1haWwpIHtcbiAgICAgICAgcXVlcnkgPSB7IGVtYWlsIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBxdWVyeSA9IHsgJG9yOiBbeyB1c2VybmFtZSB9LCB7IGVtYWlsOiB1c2VybmFtZSB9XSB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2VcbiAgICAgICAgLmZpbmQoJ19Vc2VyJywgcXVlcnkpXG4gICAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgIGlmICghcmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgJ0ludmFsaWQgdXNlcm5hbWUvcGFzc3dvcmQuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAvLyBjb3JuZXIgY2FzZSB3aGVyZSB1c2VyMSBoYXMgdXNlcm5hbWUgPT0gdXNlcjIgZW1haWxcbiAgICAgICAgICAgIHJlcS5jb25maWcubG9nZ2VyQ29udHJvbGxlci53YXJuKFxuICAgICAgICAgICAgICBcIlRoZXJlIGlzIGEgdXNlciB3aGljaCBlbWFpbCBpcyB0aGUgc2FtZSBhcyBhbm90aGVyIHVzZXIncyB1c2VybmFtZSwgbG9nZ2luZyBpbiBiYXNlZCBvbiB1c2VybmFtZVwiXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdXNlciA9IHJlc3VsdHMuZmlsdGVyKHVzZXIgPT4gdXNlci51c2VybmFtZSA9PT0gdXNlcm5hbWUpWzBdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1c2VyID0gcmVzdWx0c1swXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcGFzc3dvcmRDcnlwdG8uY29tcGFyZShwYXNzd29yZCwgdXNlci5wYXNzd29yZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKGNvcnJlY3QgPT4ge1xuICAgICAgICAgIGlzVmFsaWRQYXNzd29yZCA9IGNvcnJlY3Q7XG4gICAgICAgICAgY29uc3QgYWNjb3VudExvY2tvdXRQb2xpY3kgPSBuZXcgQWNjb3VudExvY2tvdXQodXNlciwgcmVxLmNvbmZpZyk7XG4gICAgICAgICAgcmV0dXJuIGFjY291bnRMb2Nrb3V0UG9saWN5LmhhbmRsZUxvZ2luQXR0ZW1wdChpc1ZhbGlkUGFzc3dvcmQpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgaWYgKCFpc1ZhbGlkUGFzc3dvcmQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgJ0ludmFsaWQgdXNlcm5hbWUvcGFzc3dvcmQuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gRW5zdXJlIHRoZSB1c2VyIGlzbid0IGxvY2tlZCBvdXRcbiAgICAgICAgICAvLyBBIGxvY2tlZCBvdXQgdXNlciB3b24ndCBiZSBhYmxlIHRvIGxvZ2luXG4gICAgICAgICAgLy8gVG8gbG9jayBhIHVzZXIgb3V0LCBqdXN0IHNldCB0aGUgQUNMIHRvIGBtYXN0ZXJLZXlgIG9ubHkgICh7fSkuXG4gICAgICAgICAgLy8gRW1wdHkgQUNMIGlzIE9LXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgIXJlcS5hdXRoLmlzTWFzdGVyICYmXG4gICAgICAgICAgICB1c2VyLkFDTCAmJlxuICAgICAgICAgICAgT2JqZWN0LmtleXModXNlci5BQ0wpLmxlbmd0aCA9PSAwXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAgICdJbnZhbGlkIHVzZXJuYW1lL3Bhc3N3b3JkLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHJlcS5jb25maWcudmVyaWZ5VXNlckVtYWlscyAmJlxuICAgICAgICAgICAgcmVxLmNvbmZpZy5wcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsICYmXG4gICAgICAgICAgICAhdXNlci5lbWFpbFZlcmlmaWVkXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLkVNQUlMX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgJ1VzZXIgZW1haWwgaXMgbm90IHZlcmlmaWVkLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGVsZXRlIHVzZXIucGFzc3dvcmQ7XG5cbiAgICAgICAgICAvLyBTb21ldGltZXMgdGhlIGF1dGhEYXRhIHN0aWxsIGhhcyBudWxsIG9uIHRoYXQga2V5c1xuICAgICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wYXJzZS1jb21tdW5pdHkvcGFyc2Utc2VydmVyL2lzc3Vlcy85MzVcbiAgICAgICAgICBpZiAodXNlci5hdXRoRGF0YSkge1xuICAgICAgICAgICAgT2JqZWN0LmtleXModXNlci5hdXRoRGF0YSkuZm9yRWFjaChwcm92aWRlciA9PiB7XG4gICAgICAgICAgICAgIGlmICh1c2VyLmF1dGhEYXRhW3Byb3ZpZGVyXSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB1c2VyLmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoT2JqZWN0LmtleXModXNlci5hdXRoRGF0YSkubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgICAgZGVsZXRlIHVzZXIuYXV0aERhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHJlc29sdmUodXNlcik7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlTWUocmVxKSB7XG4gICAgaWYgKCFyZXEuaW5mbyB8fCAhcmVxLmluZm8uc2Vzc2lvblRva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICAgJ0ludmFsaWQgc2Vzc2lvbiB0b2tlbidcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IHNlc3Npb25Ub2tlbiA9IHJlcS5pbmZvLnNlc3Npb25Ub2tlbjtcbiAgICByZXR1cm4gcmVzdFxuICAgICAgLmZpbmQoXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIEF1dGgubWFzdGVyKHJlcS5jb25maWcpLFxuICAgICAgICAnX1Nlc3Npb24nLFxuICAgICAgICB7IHNlc3Npb25Ub2tlbiB9LFxuICAgICAgICB7IGluY2x1ZGU6ICd1c2VyJyB9LFxuICAgICAgICByZXEuaW5mby5jbGllbnRTREtcbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICFyZXNwb25zZS5yZXN1bHRzIHx8XG4gICAgICAgICAgcmVzcG9uc2UucmVzdWx0cy5sZW5ndGggPT0gMCB8fFxuICAgICAgICAgICFyZXNwb25zZS5yZXN1bHRzWzBdLnVzZXJcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICAgJ0ludmFsaWQgc2Vzc2lvbiB0b2tlbidcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHVzZXIgPSByZXNwb25zZS5yZXN1bHRzWzBdLnVzZXI7XG4gICAgICAgICAgLy8gU2VuZCB0b2tlbiBiYWNrIG9uIHRoZSBsb2dpbiwgYmVjYXVzZSBTREtzIGV4cGVjdCB0aGF0LlxuICAgICAgICAgIHVzZXIuc2Vzc2lvblRva2VuID0gc2Vzc2lvblRva2VuO1xuXG4gICAgICAgICAgLy8gUmVtb3ZlIGhpZGRlbiBwcm9wZXJ0aWVzLlxuICAgICAgICAgIFVzZXJzUm91dGVyLnJlbW92ZUhpZGRlblByb3BlcnRpZXModXNlcik7XG5cbiAgICAgICAgICByZXR1cm4geyByZXNwb25zZTogdXNlciB9O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGhhbmRsZUxvZ0luKHJlcSkge1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLl9hdXRoZW50aWNhdGVVc2VyRnJvbVJlcXVlc3QocmVxKTtcblxuICAgIC8vIGhhbmRsZSBwYXNzd29yZCBleHBpcnkgcG9saWN5XG4gICAgaWYgKHJlcS5jb25maWcucGFzc3dvcmRQb2xpY3kgJiYgcmVxLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEFnZSkge1xuICAgICAgbGV0IGNoYW5nZWRBdCA9IHVzZXIuX3Bhc3N3b3JkX2NoYW5nZWRfYXQ7XG5cbiAgICAgIGlmICghY2hhbmdlZEF0KSB7XG4gICAgICAgIC8vIHBhc3N3b3JkIHdhcyBjcmVhdGVkIGJlZm9yZSBleHBpcnkgcG9saWN5IHdhcyBlbmFibGVkLlxuICAgICAgICAvLyBzaW1wbHkgdXBkYXRlIF9Vc2VyIG9iamVjdCBzbyB0aGF0IGl0IHdpbGwgc3RhcnQgZW5mb3JjaW5nIGZyb20gbm93XG4gICAgICAgIGNoYW5nZWRBdCA9IG5ldyBEYXRlKCk7XG4gICAgICAgIHJlcS5jb25maWcuZGF0YWJhc2UudXBkYXRlKFxuICAgICAgICAgICdfVXNlcicsXG4gICAgICAgICAgeyB1c2VybmFtZTogdXNlci51c2VybmFtZSB9LFxuICAgICAgICAgIHsgX3Bhc3N3b3JkX2NoYW5nZWRfYXQ6IFBhcnNlLl9lbmNvZGUoY2hhbmdlZEF0KSB9XG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBjaGVjayB3aGV0aGVyIHRoZSBwYXNzd29yZCBoYXMgZXhwaXJlZFxuICAgICAgICBpZiAoY2hhbmdlZEF0Ll9fdHlwZSA9PSAnRGF0ZScpIHtcbiAgICAgICAgICBjaGFuZ2VkQXQgPSBuZXcgRGF0ZShjaGFuZ2VkQXQuaXNvKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGV4cGlyeSB0aW1lLlxuICAgICAgICBjb25zdCBleHBpcmVzQXQgPSBuZXcgRGF0ZShcbiAgICAgICAgICBjaGFuZ2VkQXQuZ2V0VGltZSgpICtcbiAgICAgICAgICAgIDg2NDAwMDAwICogcmVxLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEFnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoZXhwaXJlc0F0IDwgbmV3IERhdGUoKSlcbiAgICAgICAgICAvLyBmYWlsIG9mIGN1cnJlbnQgdGltZSBpcyBwYXN0IHBhc3N3b3JkIGV4cGlyeSB0aW1lXG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICdZb3VyIHBhc3N3b3JkIGhhcyBleHBpcmVkLiBQbGVhc2UgcmVzZXQgeW91ciBwYXNzd29yZC4nXG4gICAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZW1vdmUgaGlkZGVuIHByb3BlcnRpZXMuXG4gICAgVXNlcnNSb3V0ZXIucmVtb3ZlSGlkZGVuUHJvcGVydGllcyh1c2VyKTtcblxuICAgIHJlcS5jb25maWcuZmlsZXNDb250cm9sbGVyLmV4cGFuZEZpbGVzSW5PYmplY3QocmVxLmNvbmZpZywgdXNlcik7XG5cbiAgICAvLyBCZWZvcmUgbG9naW4gdHJpZ2dlcjsgdGhyb3dzIGlmIGZhaWx1cmVcbiAgICBhd2FpdCBtYXliZVJ1blRyaWdnZXIoXG4gICAgICBUcmlnZ2VyVHlwZXMuYmVmb3JlTG9naW4sXG4gICAgICByZXEuYXV0aCxcbiAgICAgIFBhcnNlLlVzZXIuZnJvbUpTT04oT2JqZWN0LmFzc2lnbih7IGNsYXNzTmFtZTogJ19Vc2VyJyB9LCB1c2VyKSksXG4gICAgICBudWxsLFxuICAgICAgcmVxLmNvbmZpZ1xuICAgICk7XG5cbiAgICBjb25zdCB7IHNlc3Npb25EYXRhLCBjcmVhdGVTZXNzaW9uIH0gPSBBdXRoLmNyZWF0ZVNlc3Npb24ocmVxLmNvbmZpZywge1xuICAgICAgdXNlcklkOiB1c2VyLm9iamVjdElkLFxuICAgICAgY3JlYXRlZFdpdGg6IHtcbiAgICAgICAgYWN0aW9uOiAnbG9naW4nLFxuICAgICAgICBhdXRoUHJvdmlkZXI6ICdwYXNzd29yZCcsXG4gICAgICB9LFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5pbmZvLmluc3RhbGxhdGlvbklkLFxuICAgIH0pO1xuXG4gICAgdXNlci5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uRGF0YS5zZXNzaW9uVG9rZW47XG5cbiAgICBhd2FpdCBjcmVhdGVTZXNzaW9uKCk7XG5cbiAgICBjb25zdCBhZnRlckxvZ2luVXNlciA9IFBhcnNlLlVzZXIuZnJvbUpTT04oXG4gICAgICBPYmplY3QuYXNzaWduKHsgY2xhc3NOYW1lOiAnX1VzZXInIH0sIHVzZXIpXG4gICAgKTtcbiAgICBtYXliZVJ1blRyaWdnZXIoXG4gICAgICBUcmlnZ2VyVHlwZXMuYWZ0ZXJMb2dpbixcbiAgICAgIHsgLi4ucmVxLmF1dGgsIHVzZXI6IGFmdGVyTG9naW5Vc2VyIH0sXG4gICAgICBhZnRlckxvZ2luVXNlcixcbiAgICAgIG51bGwsXG4gICAgICByZXEuY29uZmlnXG4gICAgKTtcblxuICAgIHJldHVybiB7IHJlc3BvbnNlOiB1c2VyIH07XG4gIH1cblxuICBoYW5kbGVWZXJpZnlQYXNzd29yZChyZXEpIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aGVudGljYXRlVXNlckZyb21SZXF1ZXN0KHJlcSlcbiAgICAgIC50aGVuKHVzZXIgPT4ge1xuICAgICAgICAvLyBSZW1vdmUgaGlkZGVuIHByb3BlcnRpZXMuXG4gICAgICAgIFVzZXJzUm91dGVyLnJlbW92ZUhpZGRlblByb3BlcnRpZXModXNlcik7XG5cbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHVzZXIgfTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlTG9nT3V0KHJlcSkge1xuICAgIGNvbnN0IHN1Y2Nlc3MgPSB7IHJlc3BvbnNlOiB7fSB9O1xuICAgIGlmIChyZXEuaW5mbyAmJiByZXEuaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICAgIHJldHVybiByZXN0XG4gICAgICAgIC5maW5kKFxuICAgICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgICAgQXV0aC5tYXN0ZXIocmVxLmNvbmZpZyksXG4gICAgICAgICAgJ19TZXNzaW9uJyxcbiAgICAgICAgICB7IHNlc3Npb25Ub2tlbjogcmVxLmluZm8uc2Vzc2lvblRva2VuIH0sXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICAgICApXG4gICAgICAgIC50aGVuKHJlY29yZHMgPT4ge1xuICAgICAgICAgIGlmIChyZWNvcmRzLnJlc3VsdHMgJiYgcmVjb3Jkcy5yZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3RcbiAgICAgICAgICAgICAgLmRlbChcbiAgICAgICAgICAgICAgICByZXEuY29uZmlnLFxuICAgICAgICAgICAgICAgIEF1dGgubWFzdGVyKHJlcS5jb25maWcpLFxuICAgICAgICAgICAgICAgICdfU2Vzc2lvbicsXG4gICAgICAgICAgICAgICAgcmVjb3Jkcy5yZXN1bHRzWzBdLm9iamVjdElkXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3J1bkFmdGVyTG9nb3V0VHJpZ2dlcihyZXEsIHJlY29yZHMucmVzdWx0c1swXSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShzdWNjZXNzKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc3VjY2Vzcyk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHN1Y2Nlc3MpO1xuICB9XG5cbiAgX3J1bkFmdGVyTG9nb3V0VHJpZ2dlcihyZXEsIHNlc3Npb24pIHtcbiAgICAvLyBBZnRlciBsb2dvdXQgdHJpZ2dlclxuICAgIG1heWJlUnVuVHJpZ2dlcihcbiAgICAgIFRyaWdnZXJUeXBlcy5hZnRlckxvZ291dCxcbiAgICAgIHJlcS5hdXRoLFxuICAgICAgUGFyc2UuU2Vzc2lvbi5mcm9tSlNPTihPYmplY3QuYXNzaWduKHsgY2xhc3NOYW1lOiAnX1Nlc3Npb24nIH0sIHNlc3Npb24pKSxcbiAgICAgIG51bGwsXG4gICAgICByZXEuY29uZmlnXG4gICAgKTtcbiAgfVxuXG4gIF90aHJvd09uQmFkRW1haWxDb25maWcocmVxKSB7XG4gICAgdHJ5IHtcbiAgICAgIENvbmZpZy52YWxpZGF0ZUVtYWlsQ29uZmlndXJhdGlvbih7XG4gICAgICAgIGVtYWlsQWRhcHRlcjogcmVxLmNvbmZpZy51c2VyQ29udHJvbGxlci5hZGFwdGVyLFxuICAgICAgICBhcHBOYW1lOiByZXEuY29uZmlnLmFwcE5hbWUsXG4gICAgICAgIHB1YmxpY1NlcnZlclVSTDogcmVxLmNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwsXG4gICAgICAgIGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uOlxuICAgICAgICAgIHJlcS5jb25maWcuZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24sXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAodHlwZW9mIGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIC8vIE1heWJlIHdlIG5lZWQgYSBCYWQgQ29uZmlndXJhdGlvbiBlcnJvciwgYnV0IHRoZSBTREtzIHdvbid0IHVuZGVyc3RhbmQgaXQuIEZvciBub3csIEludGVybmFsIFNlcnZlciBFcnJvci5cbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgICAnQW4gYXBwTmFtZSwgcHVibGljU2VydmVyVVJMLCBhbmQgZW1haWxBZGFwdGVyIGFyZSByZXF1aXJlZCBmb3IgcGFzc3dvcmQgcmVzZXQgYW5kIGVtYWlsIHZlcmlmaWNhdGlvbiBmdW5jdGlvbmFsaXR5LidcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlUmVzZXRSZXF1ZXN0KHJlcSkge1xuICAgIHRoaXMuX3Rocm93T25CYWRFbWFpbENvbmZpZyhyZXEpO1xuXG4gICAgY29uc3QgeyBlbWFpbCB9ID0gcmVxLmJvZHk7XG4gICAgaWYgKCFlbWFpbCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5FTUFJTF9NSVNTSU5HLFxuICAgICAgICAneW91IG11c3QgcHJvdmlkZSBhbiBlbWFpbCdcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZW1haWwgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfRU1BSUxfQUREUkVTUyxcbiAgICAgICAgJ3lvdSBtdXN0IHByb3ZpZGUgYSB2YWxpZCBlbWFpbCBzdHJpbmcnXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCB1c2VyQ29udHJvbGxlciA9IHJlcS5jb25maWcudXNlckNvbnRyb2xsZXI7XG4gICAgcmV0dXJuIHVzZXJDb250cm9sbGVyLnNlbmRQYXNzd29yZFJlc2V0RW1haWwoZW1haWwpLnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIHJlc3BvbnNlOiB7fSxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgZXJyID0+IHtcbiAgICAgICAgaWYgKGVyci5jb2RlID09PSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EKSB7XG4gICAgICAgICAgLy8gUmV0dXJuIHN1Y2Nlc3Mgc28gdGhhdCB0aGlzIGVuZHBvaW50IGNhbid0XG4gICAgICAgICAgLy8gYmUgdXNlZCB0byBlbnVtZXJhdGUgdmFsaWQgZW1haWxzXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgICByZXNwb25zZToge30sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIGhhbmRsZVZlcmlmaWNhdGlvbkVtYWlsUmVxdWVzdChyZXEpIHtcbiAgICB0aGlzLl90aHJvd09uQmFkRW1haWxDb25maWcocmVxKTtcblxuICAgIGNvbnN0IHsgZW1haWwgfSA9IHJlcS5ib2R5O1xuICAgIGlmICghZW1haWwpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuRU1BSUxfTUlTU0lORyxcbiAgICAgICAgJ3lvdSBtdXN0IHByb3ZpZGUgYW4gZW1haWwnXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGVtYWlsICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0VNQUlMX0FERFJFU1MsXG4gICAgICAgICd5b3UgbXVzdCBwcm92aWRlIGEgdmFsaWQgZW1haWwgc3RyaW5nJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZS5maW5kKCdfVXNlcicsIHsgZW1haWw6IGVtYWlsIH0pLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICBpZiAoIXJlc3VsdHMubGVuZ3RoIHx8IHJlc3VsdHMubGVuZ3RoIDwgMSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuRU1BSUxfTk9UX0ZPVU5ELFxuICAgICAgICAgIGBObyB1c2VyIGZvdW5kIHdpdGggZW1haWwgJHtlbWFpbH1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBjb25zdCB1c2VyID0gcmVzdWx0c1swXTtcblxuICAgICAgLy8gcmVtb3ZlIHBhc3N3b3JkIGZpZWxkLCBtZXNzZXMgd2l0aCBzYXZpbmcgb24gcG9zdGdyZXNcbiAgICAgIGRlbGV0ZSB1c2VyLnBhc3N3b3JkO1xuXG4gICAgICBpZiAodXNlci5lbWFpbFZlcmlmaWVkKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5PVEhFUl9DQVVTRSxcbiAgICAgICAgICBgRW1haWwgJHtlbWFpbH0gaXMgYWxyZWFkeSB2ZXJpZmllZC5gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHVzZXJDb250cm9sbGVyID0gcmVxLmNvbmZpZy51c2VyQ29udHJvbGxlcjtcbiAgICAgIHJldHVybiB1c2VyQ29udHJvbGxlci5yZWdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbih1c2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgdXNlckNvbnRyb2xsZXIuc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHVzZXIpO1xuICAgICAgICByZXR1cm4geyByZXNwb25zZToge30gfTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy91c2VycycsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvdXNlcnMnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlQ3JlYXRlKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy91c2Vycy9tZScsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVNZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvdXNlcnMvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUdldChyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ1BVVCcsICcvdXNlcnMvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZVVwZGF0ZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsICcvdXNlcnMvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZURlbGV0ZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvbG9naW4nLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlTG9nSW4ocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy9sb2dpbicsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVMb2dJbihyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2xvZ291dCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVMb2dPdXQocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy9yZXF1ZXN0UGFzc3dvcmRSZXNldCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVSZXNldFJlcXVlc3QocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy92ZXJpZmljYXRpb25FbWFpbFJlcXVlc3QnLCByZXEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlVmVyaWZpY2F0aW9uRW1haWxSZXF1ZXN0KHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy92ZXJpZnlQYXNzd29yZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVWZXJpZnlQYXNzd29yZChyZXEpO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFVzZXJzUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/StatusHandler.js b/lib/StatusHandler.js new file mode 100644 index 0000000000..d24a29b968 --- /dev/null +++ b/lib/StatusHandler.js @@ -0,0 +1,391 @@ +"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 update = function (update) { + _logger.logger.verbose(`_PushStatus ${objectId}: updating values %j`, update); + + return handler.update({ + objectId + }, update); + }; + + 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, + update, + 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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QUE2QlosTUFBN0IsQ0FBUDtBQUNELEdBVEQ7O0FBV0EsUUFBTTZGLElBQUksR0FBRztBQUNYekQsSUFBQUEsVUFEVztBQUVYbkIsSUFBQUEsVUFGVztBQUdYZ0QsSUFBQUEsU0FIVztBQUlYd0IsSUFBQUEsUUFKVztBQUtYekYsSUFBQUEsTUFMVztBQU1YMEYsSUFBQUE7QUFOVyxHQUFiLENBck0wRCxDQThNMUQ7O0FBQ0F4RixFQUFBQSxNQUFNLENBQUM0RixjQUFQLENBQXNCRCxJQUF0QixFQUE0QixVQUE1QixFQUF3QztBQUN0Q0UsSUFBQUEsR0FBRyxFQUFFLE1BQU1uRjtBQUQyQixHQUF4QztBQUlBLFNBQU9WLE1BQU0sQ0FBQ0MsTUFBUCxDQUFjMEYsSUFBZCxDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBtZDVIYXNoLCBuZXdPYmplY3RJZCB9IGZyb20gJy4vY3J5cHRvVXRpbHMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4vQXV0aCc7XG5cbmNvbnN0IFBVU0hfU1RBVFVTX0NPTExFQ1RJT04gPSAnX1B1c2hTdGF0dXMnO1xuY29uc3QgSk9CX1NUQVRVU19DT0xMRUNUSU9OID0gJ19Kb2JTdGF0dXMnO1xuXG5jb25zdCBpbmNyZW1lbnRPcCA9IGZ1bmN0aW9uKG9iamVjdCA9IHt9LCBrZXksIGFtb3VudCA9IDEpIHtcbiAgaWYgKCFvYmplY3Rba2V5XSkge1xuICAgIG9iamVjdFtrZXldID0geyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBhbW91bnQgfTtcbiAgfSBlbHNlIHtcbiAgICBvYmplY3Rba2V5XS5hbW91bnQgKz0gYW1vdW50O1xuICB9XG4gIHJldHVybiBvYmplY3Rba2V5XTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuKGFycmF5KSB7XG4gIHZhciBmbGF0dGVuZWQgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGFycmF5W2ldKSkge1xuICAgICAgZmxhdHRlbmVkID0gZmxhdHRlbmVkLmNvbmNhdChmbGF0dGVuKGFycmF5W2ldKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZsYXR0ZW5lZC5wdXNoKGFycmF5W2ldKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZsYXR0ZW5lZDtcbn1cblxuZnVuY3Rpb24gc3RhdHVzSGFuZGxlcihjbGFzc05hbWUsIGRhdGFiYXNlKSB7XG4gIGxldCBsYXN0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZShvYmplY3QpIHtcbiAgICBsYXN0UHJvbWlzZSA9IGxhc3RQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIGRhdGFiYXNlLmNyZWF0ZShjbGFzc05hbWUsIG9iamVjdCkudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUob2JqZWN0KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBsYXN0UHJvbWlzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZSh3aGVyZSwgb2JqZWN0KSB7XG4gICAgbGFzdFByb21pc2UgPSBsYXN0UHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBkYXRhYmFzZS51cGRhdGUoY2xhc3NOYW1lLCB3aGVyZSwgb2JqZWN0KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgY3JlYXRlLFxuICAgIHVwZGF0ZSxcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlc3RTdGF0dXNIYW5kbGVyKGNsYXNzTmFtZSwgY29uZmlnKSB7XG4gIGxldCBsYXN0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICBjb25zdCBhdXRoID0gQXV0aC5tYXN0ZXIoY29uZmlnKTtcbiAgZnVuY3Rpb24gY3JlYXRlKG9iamVjdCkge1xuICAgIGxhc3RQcm9taXNlID0gbGFzdFByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gcmVzdFxuICAgICAgICAuY3JlYXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCBvYmplY3QpXG4gICAgICAgIC50aGVuKCh7IHJlc3BvbnNlIH0pID0+IHtcbiAgICAgICAgICAvLyBtZXJnZSB0aGUgb2JqZWN0c1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoT2JqZWN0LmFzc2lnbih7fSwgb2JqZWN0LCByZXNwb25zZSkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGUod2hlcmUsIG9iamVjdCkge1xuICAgIC8vIFRPRE86IHdoZW4gd2UgaGF2ZSB1cGRhdGVXaGVyZSwgdXNlIHRoYXQgZm9yIHByb3BlciBpbnRlcmZhY2luZ1xuICAgIGxhc3RQcm9taXNlID0gbGFzdFByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gcmVzdFxuICAgICAgICAudXBkYXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCB7IG9iamVjdElkOiB3aGVyZS5vYmplY3RJZCB9LCBvYmplY3QpXG4gICAgICAgIC50aGVuKCh7IHJlc3BvbnNlIH0pID0+IHtcbiAgICAgICAgICAvLyBtZXJnZSB0aGUgb2JqZWN0c1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoT2JqZWN0LmFzc2lnbih7fSwgb2JqZWN0LCByZXNwb25zZSkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgY3JlYXRlLFxuICAgIHVwZGF0ZSxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBqb2JTdGF0dXNIYW5kbGVyKGNvbmZpZykge1xuICBsZXQgam9iU3RhdHVzO1xuICBjb25zdCBvYmplY3RJZCA9IG5ld09iamVjdElkKGNvbmZpZy5vYmplY3RJZFNpemUpO1xuICBjb25zdCBkYXRhYmFzZSA9IGNvbmZpZy5kYXRhYmFzZTtcbiAgY29uc3QgaGFuZGxlciA9IHN0YXR1c0hhbmRsZXIoSk9CX1NUQVRVU19DT0xMRUNUSU9OLCBkYXRhYmFzZSk7XG4gIGNvbnN0IHNldFJ1bm5pbmcgPSBmdW5jdGlvbihqb2JOYW1lLCBwYXJhbXMpIHtcbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIGpvYlN0YXR1cyA9IHtcbiAgICAgIG9iamVjdElkLFxuICAgICAgam9iTmFtZSxcbiAgICAgIHBhcmFtcyxcbiAgICAgIHN0YXR1czogJ3J1bm5pbmcnLFxuICAgICAgc291cmNlOiAnYXBpJyxcbiAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgLy8gbG9ja2Rvd24hXG4gICAgICBBQ0w6IHt9LFxuICAgIH07XG5cbiAgICByZXR1cm4gaGFuZGxlci5jcmVhdGUoam9iU3RhdHVzKTtcbiAgfTtcblxuICBjb25zdCBzZXRNZXNzYWdlID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgIGlmICghbWVzc2FnZSB8fCB0eXBlb2YgbWVzc2FnZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgeyBtZXNzYWdlIH0pO1xuICB9O1xuXG4gIGNvbnN0IHNldFN1Y2NlZWRlZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICByZXR1cm4gc2V0RmluYWxTdGF0dXMoJ3N1Y2NlZWRlZCcsIG1lc3NhZ2UpO1xuICB9O1xuXG4gIGNvbnN0IHNldEZhaWxlZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICByZXR1cm4gc2V0RmluYWxTdGF0dXMoJ2ZhaWxlZCcsIG1lc3NhZ2UpO1xuICB9O1xuXG4gIGNvbnN0IHNldEZpbmFsU3RhdHVzID0gZnVuY3Rpb24oc3RhdHVzLCBtZXNzYWdlID0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgZmluaXNoZWRBdCA9IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgdXBkYXRlID0geyBzdGF0dXMsIGZpbmlzaGVkQXQgfTtcbiAgICBpZiAobWVzc2FnZSAmJiB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHVwZGF0ZS5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgdXBkYXRlKTtcbiAgfTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgc2V0UnVubmluZyxcbiAgICBzZXRTdWNjZWVkZWQsXG4gICAgc2V0TWVzc2FnZSxcbiAgICBzZXRGYWlsZWQsXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHVzaFN0YXR1c0hhbmRsZXIoY29uZmlnLCBleGlzdGluZ09iamVjdElkKSB7XG4gIGxldCBwdXNoU3RhdHVzO1xuICBjb25zdCBkYXRhYmFzZSA9IGNvbmZpZy5kYXRhYmFzZTtcbiAgY29uc3QgaGFuZGxlciA9IHJlc3RTdGF0dXNIYW5kbGVyKFBVU0hfU1RBVFVTX0NPTExFQ1RJT04sIGNvbmZpZyk7XG4gIGxldCBvYmplY3RJZCA9IGV4aXN0aW5nT2JqZWN0SWQ7XG4gIGNvbnN0IHNldEluaXRpYWwgPSBmdW5jdGlvbihib2R5ID0ge30sIHdoZXJlLCBvcHRpb25zID0geyBzb3VyY2U6ICdyZXN0JyB9KSB7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICBsZXQgcHVzaFRpbWUgPSBub3cudG9JU09TdHJpbmcoKTtcbiAgICBsZXQgc3RhdHVzID0gJ3BlbmRpbmcnO1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYm9keSwgJ3B1c2hfdGltZScpKSB7XG4gICAgICBpZiAoY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0KSB7XG4gICAgICAgIHB1c2hUaW1lID0gYm9keS5wdXNoX3RpbWU7XG4gICAgICAgIHN0YXR1cyA9ICdzY2hlZHVsZWQnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgJ1RyeWluZyB0byBzY2hlZHVsZSBhIHB1c2ggd2hpbGUgc2VydmVyIGlzIG5vdCBjb25maWd1cmVkLidcbiAgICAgICAgKTtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1B1c2ggd2lsbCBiZSBzZW50IGltbWVkaWF0ZWx5Jyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IGJvZHkuZGF0YSB8fCB7fTtcbiAgICBjb25zdCBwYXlsb2FkU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgbGV0IHB1c2hIYXNoO1xuICAgIGlmICh0eXBlb2YgZGF0YS5hbGVydCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHB1c2hIYXNoID0gbWQ1SGFzaChkYXRhLmFsZXJ0KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLmFsZXJ0ID09PSAnb2JqZWN0Jykge1xuICAgICAgcHVzaEhhc2ggPSBtZDVIYXNoKEpTT04uc3RyaW5naWZ5KGRhdGEuYWxlcnQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHVzaEhhc2ggPSAnZDQxZDhjZDk4ZjAwYjIwNGU5ODAwOTk4ZWNmODQyN2UnO1xuICAgIH1cbiAgICBjb25zdCBvYmplY3QgPSB7XG4gICAgICBwdXNoVGltZSxcbiAgICAgIHF1ZXJ5OiBKU09OLnN0cmluZ2lmeSh3aGVyZSksXG4gICAgICBwYXlsb2FkOiBwYXlsb2FkU3RyaW5nLFxuICAgICAgc291cmNlOiBvcHRpb25zLnNvdXJjZSxcbiAgICAgIHRpdGxlOiBvcHRpb25zLnRpdGxlLFxuICAgICAgZXhwaXJ5OiBib2R5LmV4cGlyYXRpb25fdGltZSxcbiAgICAgIGV4cGlyYXRpb25faW50ZXJ2YWw6IGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCxcbiAgICAgIHN0YXR1czogc3RhdHVzLFxuICAgICAgbnVtU2VudDogMCxcbiAgICAgIHB1c2hIYXNoLFxuICAgICAgLy8gbG9ja2Rvd24hXG4gICAgICBBQ0w6IHt9LFxuICAgIH07XG4gICAgcmV0dXJuIGhhbmRsZXIuY3JlYXRlKG9iamVjdCkudGhlbihyZXN1bHQgPT4ge1xuICAgICAgb2JqZWN0SWQgPSByZXN1bHQub2JqZWN0SWQ7XG4gICAgICBwdXNoU3RhdHVzID0ge1xuICAgICAgICBvYmplY3RJZCxcbiAgICAgIH07XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHB1c2hTdGF0dXMpO1xuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IHNldFJ1bm5pbmcgPSBmdW5jdGlvbihiYXRjaGVzKSB7XG4gICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IHNlbmRpbmcgcHVzaCB0byBpbnN0YWxsYXRpb25zIHdpdGggJWQgYmF0Y2hlc2AsXG4gICAgICBiYXRjaGVzXG4gICAgKTtcbiAgICByZXR1cm4gaGFuZGxlci51cGRhdGUoXG4gICAgICB7XG4gICAgICAgIHN0YXR1czogJ3BlbmRpbmcnLFxuICAgICAgICBvYmplY3RJZDogb2JqZWN0SWQsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBzdGF0dXM6ICdydW5uaW5nJyxcbiAgICAgICAgY291bnQ6IGJhdGNoZXMsXG4gICAgICB9XG4gICAgKTtcbiAgfTtcblxuICBjb25zdCB1cGRhdGUgPSBmdW5jdGlvbih1cGRhdGUpIHtcbiAgICBsb2dnZXIudmVyYm9zZShgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IHVwZGF0aW5nIHZhbHVlcyAlamAsIHVwZGF0ZSk7XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgdXBkYXRlKTtcbiAgfTtcblxuICBjb25zdCB0cmFja1NlbnQgPSBmdW5jdGlvbihcbiAgICByZXN1bHRzLFxuICAgIFVUQ09mZnNldCxcbiAgICBjbGVhbnVwSW5zdGFsbGF0aW9ucyA9IHByb2Nlc3MuZW52XG4gICAgICAuUEFSU0VfU0VSVkVSX0NMRUFOVVBfSU5WQUxJRF9JTlNUQUxMQVRJT05TXG4gICkge1xuICAgIGNvbnN0IHVwZGF0ZSA9IHtcbiAgICAgIG51bVNlbnQ6IDAsXG4gICAgICBudW1GYWlsZWQ6IDAsXG4gICAgfTtcbiAgICBjb25zdCBkZXZpY2VzVG9SZW1vdmUgPSBbXTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHRzKSkge1xuICAgICAgcmVzdWx0cyA9IGZsYXR0ZW4ocmVzdWx0cyk7XG4gICAgICByZXN1bHRzLnJlZHVjZSgobWVtbywgcmVzdWx0KSA9PiB7XG4gICAgICAgIC8vIENhbm5vdCBoYW5kbGUgdGhhdFxuICAgICAgICBpZiAoIXJlc3VsdCB8fCAhcmVzdWx0LmRldmljZSB8fCAhcmVzdWx0LmRldmljZS5kZXZpY2VUeXBlKSB7XG4gICAgICAgICAgcmV0dXJuIG1lbW87XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGV2aWNlVHlwZSA9IHJlc3VsdC5kZXZpY2UuZGV2aWNlVHlwZTtcbiAgICAgICAgY29uc3Qga2V5ID0gcmVzdWx0LnRyYW5zbWl0dGVkXG4gICAgICAgICAgPyBgc2VudFBlclR5cGUuJHtkZXZpY2VUeXBlfWBcbiAgICAgICAgICA6IGBmYWlsZWRQZXJUeXBlLiR7ZGV2aWNlVHlwZX1gO1xuICAgICAgICBtZW1vW2tleV0gPSBpbmNyZW1lbnRPcChtZW1vLCBrZXkpO1xuICAgICAgICBpZiAodHlwZW9mIFVUQ09mZnNldCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb25zdCBvZmZzZXRLZXkgPSByZXN1bHQudHJhbnNtaXR0ZWRcbiAgICAgICAgICAgID8gYHNlbnRQZXJVVENPZmZzZXQuJHtVVENPZmZzZXR9YFxuICAgICAgICAgICAgOiBgZmFpbGVkUGVyVVRDT2Zmc2V0LiR7VVRDT2Zmc2V0fWA7XG4gICAgICAgICAgbWVtb1tvZmZzZXRLZXldID0gaW5jcmVtZW50T3AobWVtbywgb2Zmc2V0S2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0LnRyYW5zbWl0dGVkKSB7XG4gICAgICAgICAgbWVtby5udW1TZW50Kys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcmVzdWx0ICYmXG4gICAgICAgICAgICByZXN1bHQucmVzcG9uc2UgJiZcbiAgICAgICAgICAgIHJlc3VsdC5yZXNwb25zZS5lcnJvciAmJlxuICAgICAgICAgICAgcmVzdWx0LmRldmljZSAmJlxuICAgICAgICAgICAgcmVzdWx0LmRldmljZS5kZXZpY2VUb2tlblxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uc3QgdG9rZW4gPSByZXN1bHQuZGV2aWNlLmRldmljZVRva2VuO1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSByZXN1bHQucmVzcG9uc2UuZXJyb3I7XG4gICAgICAgICAgICAvLyBHQ00gZXJyb3JzXG4gICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdOb3RSZWdpc3RlcmVkJyB8fCBlcnJvciA9PT0gJ0ludmFsaWRSZWdpc3RyYXRpb24nKSB7XG4gICAgICAgICAgICAgIGRldmljZXNUb1JlbW92ZS5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEFQTlMgZXJyb3JzXG4gICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdVbnJlZ2lzdGVyZWQnIHx8IGVycm9yID09PSAnQmFkRGV2aWNlVG9rZW4nKSB7XG4gICAgICAgICAgICAgIGRldmljZXNUb1JlbW92ZS5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgbWVtby5udW1GYWlsZWQrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgIH0sIHVwZGF0ZSk7XG4gICAgfVxuXG4gICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IHNlbnQgcHVzaCEgJWQgc3VjY2VzcywgJWQgZmFpbHVyZXNgLFxuICAgICAgdXBkYXRlLm51bVNlbnQsXG4gICAgICB1cGRhdGUubnVtRmFpbGVkXG4gICAgKTtcbiAgICBsb2dnZXIudmVyYm9zZShgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IG5lZWRzIGNsZWFudXBgLCB7XG4gICAgICBkZXZpY2VzVG9SZW1vdmUsXG4gICAgfSk7XG4gICAgWydudW1TZW50JywgJ251bUZhaWxlZCddLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIGlmICh1cGRhdGVba2V5XSA+IDApIHtcbiAgICAgICAgdXBkYXRlW2tleV0gPSB7XG4gICAgICAgICAgX19vcDogJ0luY3JlbWVudCcsXG4gICAgICAgICAgYW1vdW50OiB1cGRhdGVba2V5XSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSB1cGRhdGVba2V5XTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChkZXZpY2VzVG9SZW1vdmUubGVuZ3RoID4gMCAmJiBjbGVhbnVwSW5zdGFsbGF0aW9ucykge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGBSZW1vdmluZyBkZXZpY2UgdG9rZW5zIG9uICR7ZGV2aWNlc1RvUmVtb3ZlLmxlbmd0aH0gX0luc3RhbGxhdGlvbnNgXG4gICAgICApO1xuICAgICAgZGF0YWJhc2UudXBkYXRlKFxuICAgICAgICAnX0luc3RhbGxhdGlvbicsXG4gICAgICAgIHsgZGV2aWNlVG9rZW46IHsgJGluOiBkZXZpY2VzVG9SZW1vdmUgfSB9LFxuICAgICAgICB7IGRldmljZVRva2VuOiB7IF9fb3A6ICdEZWxldGUnIH0gfSxcbiAgICAgICAge1xuICAgICAgICAgIGFjbDogdW5kZWZpbmVkLFxuICAgICAgICAgIG1hbnk6IHRydWUsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gaW5kaWNhdGUgdGhpcyBiYXRjaCBpcyBjb21wbGV0ZVxuICAgIGluY3JlbWVudE9wKHVwZGF0ZSwgJ2NvdW50JywgLTEpO1xuXG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgdXBkYXRlKS50aGVuKHJlcyA9PiB7XG4gICAgICBpZiAocmVzICYmIHJlcy5jb3VudCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21wbGV0ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IGNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKFxuICAgICAgeyBvYmplY3RJZCB9LFxuICAgICAge1xuICAgICAgICBzdGF0dXM6ICdzdWNjZWVkZWQnLFxuICAgICAgICBjb3VudDogeyBfX29wOiAnRGVsZXRlJyB9LFxuICAgICAgfVxuICAgICk7XG4gIH07XG5cbiAgY29uc3QgZmFpbCA9IGZ1bmN0aW9uKGVycikge1xuICAgIGlmICh0eXBlb2YgZXJyID09PSAnc3RyaW5nJykge1xuICAgICAgZXJyID0geyBtZXNzYWdlOiBlcnIgfTtcbiAgICB9XG4gICAgY29uc3QgdXBkYXRlID0ge1xuICAgICAgZXJyb3JNZXNzYWdlOiBlcnIsXG4gICAgICBzdGF0dXM6ICdmYWlsZWQnLFxuICAgIH07XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKHsgb2JqZWN0SWQgfSwgdXBkYXRlKTtcbiAgfTtcblxuICBjb25zdCBydmFsID0ge1xuICAgIHNldEluaXRpYWwsXG4gICAgc2V0UnVubmluZyxcbiAgICB0cmFja1NlbnQsXG4gICAgY29tcGxldGUsXG4gICAgdXBkYXRlLFxuICAgIGZhaWwsXG4gIH07XG5cbiAgLy8gZGVmaW5lIG9iamVjdElkIHRvIGJlIGR5bmFtaWNcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHJ2YWwsICdvYmplY3RJZCcsIHtcbiAgICBnZXQ6ICgpID0+IG9iamVjdElkLFxuICB9KTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShydmFsKTtcbn1cbiJdfQ== \ 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..3b7d038668 --- /dev/null +++ b/lib/cloud-code/Parse.Cloud.js @@ -0,0 +1,403 @@ +"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 login function. + * + * **Available in Cloud Code only.** + * + * This function is triggered after a user logs in successfully, + * and after a _Session object has been created. + * + * ``` + * Parse.Cloud.afterLogin((request) => { + * // code here + * }) + * + * ``` + * + * @method afterLogin + * @name Parse.Cloud.afterLogin + * @param {Function} func The function to run after a login. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest}; + */ + + +ParseCloud.afterLogin = 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.afterLogin, 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1jb2RlL1BhcnNlLkNsb3VkLmpzIl0sIm5hbWVzIjpbImlzUGFyc2VPYmplY3RDb25zdHJ1Y3RvciIsIm9iamVjdCIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImdldENsYXNzTmFtZSIsInBhcnNlQ2xhc3MiLCJjbGFzc05hbWUiLCJQYXJzZUNsb3VkIiwiZGVmaW5lIiwiZnVuY3Rpb25OYW1lIiwiaGFuZGxlciIsInZhbGlkYXRpb25IYW5kbGVyIiwidHJpZ2dlcnMiLCJhZGRGdW5jdGlvbiIsIlBhcnNlIiwiYXBwbGljYXRpb25JZCIsImpvYiIsImFkZEpvYiIsImJlZm9yZVNhdmUiLCJhZGRUcmlnZ2VyIiwiVHlwZXMiLCJiZWZvcmVEZWxldGUiLCJiZWZvcmVMb2dpbiIsImFyZ3VtZW50cyIsImFmdGVyTG9naW4iLCJhZnRlckxvZ291dCIsImFmdGVyU2F2ZSIsImFmdGVyRGVsZXRlIiwiYmVmb3JlRmluZCIsImFmdGVyRmluZCIsIm9uTGl2ZVF1ZXJ5RXZlbnQiLCJhZGRMaXZlUXVlcnlFdmVudEhhbmRsZXIiLCJfcmVtb3ZlQWxsSG9va3MiLCJfdW5yZWdpc3RlckFsbCIsInVzZU1hc3RlcktleSIsImNvbnNvbGUiLCJ3YXJuIiwiaHR0cFJlcXVlc3QiLCJyZXF1aXJlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7QUFDQTs7Ozs7O0FBRUEsU0FBU0Esd0JBQVQsQ0FBa0NDLE1BQWxDLEVBQTBDO0FBQ3hDLFNBQ0UsT0FBT0EsTUFBUCxLQUFrQixVQUFsQixJQUNBQyxNQUFNLENBQUNDLFNBQVAsQ0FBaUJDLGNBQWpCLENBQWdDQyxJQUFoQyxDQUFxQ0osTUFBckMsRUFBNkMsV0FBN0MsQ0FGRjtBQUlEOztBQUVELFNBQVNLLFlBQVQsQ0FBc0JDLFVBQXRCLEVBQWtDO0FBQ2hDLE1BQUlBLFVBQVUsSUFBSUEsVUFBVSxDQUFDQyxTQUE3QixFQUF3QztB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RixZQUFZLENBQUNDLFVBQUQsQ0FBNUI7QUFDQU8sRUFBQUEsUUFBUSxDQUFDTyxVQUFULENBQ0VQLFFBQVEsQ0FBQ1EsS0FBVCxDQUFlUSxVQURqQixFQUVFdEIsU0FGRixFQUdFSSxPQUhGLEVBSUVJLFlBQU1DLGFBSlI7QUFNRCxDQVJEO0FBVUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUJBUixVQUFVLENBQUNzQixTQUFYLEdBQXVCLFVBQVN4QixVQUFULEVBQXFCSyxPQUFyQixFQUE4QjtBQUNuRCxRQUFNSixTQUFTLEdBQUdGLFlBQVksQ0FBQ0MsVUFBRCxDQUE5QjtBQUNBTyxFQUFBQSxRQUFRLENBQUNPLFVBQVQsQ0FDRVAsUUFBUSxDQUFDUSxLQUFULENBQWVTLFNBRGpCLEVBRUV2QixTQUZGLEVBR0VJLE9BSEYsRUFJRUksWUFBTUMsYUFKUjtBQU1ELENBUkQ7O0FBVUFSLFVBQVUsQ0FBQ3VCLGdCQUFYLEdBQThCLFVBQVNwQixPQUFULEVBQWtCO0FBQzlDRSxFQUFBQSxRQUFRLENBQUNtQix3QkFBVCxDQUFrQ3JCLE9BQWxDLEVBQTJDSSxZQUFNQyxhQUFqRDtBQUNELENBRkQ7O0FBSUFSLFVBQVUsQ0FBQ3lCLGVBQVgsR0FBNkIsTUFBTTtBQUNqQ3BCLEVBQUFBLFFBQVEsQ0FBQ3FCLGNBQVQ7QUFDRCxDQUZEOztBQUlBMUIsVUFBVSxDQUFDMkIsWUFBWCxHQUEwQixNQUFNO0FBQzlCO0FBQ0FDLEVBQUFBLE9BQU8sQ0FBQ0MsSUFBUixDQUNFLDROQURGO0FBR0QsQ0FMRDs7QUFPQTdCLFVBQVUsQ0FBQzhCLFdBQVgsR0FBeUJDLE9BQU8sQ0FBQyxlQUFELENBQWhDO0FBRUFDLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQmpDLFVBQWpCO0FBRUE7Ozs7Ozs7Ozs7Ozs7QUFhQTs7Ozs7Ozs7Ozs7OztBQWFBOzs7Ozs7Ozs7Ozs7O0FBYUE7Ozs7Ozs7O0FBUUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9IGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0ICogYXMgdHJpZ2dlcnMgZnJvbSAnLi4vdHJpZ2dlcnMnO1xuXG5mdW5jdGlvbiBpc1BhcnNlT2JqZWN0Q29uc3RydWN0b3Iob2JqZWN0KSB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIG9iamVjdCA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsICdjbGFzc05hbWUnKVxuICApO1xufVxuXG5mdW5jdGlvbiBnZXRDbGFzc05hbWUocGFyc2VDbGFzcykge1xuICBpZiAocGFyc2VDbGFzcyAmJiBwYXJzZUNsYXNzLmNsYXNzTmFtZSkge1xuICAgIHJldHVybiBwYXJzZUNsYXNzLmNsYXNzTmFtZTtcbiAgfVxuICByZXR1cm4gcGFyc2VDbGFzcztcbn1cblxuLyoqIEBuYW1lc3BhY2VcbiAqIEBuYW1lIFBhcnNlXG4gKiBAZGVzY3JpcHRpb24gVGhlIFBhcnNlIFNESy5cbiAqICBzZWUgW2FwaSBkb2NzXShodHRwczovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvanMvYXBpKSBhbmQgW2d1aWRlXShodHRwczovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvanMvZ3VpZGUpXG4gKi9cblxuLyoqIEBuYW1lc3BhY2VcbiAqIEBuYW1lIFBhcnNlLkNsb3VkXG4gKiBAbWVtYmVyb2YgUGFyc2VcbiAqIEBkZXNjcmlwdGlvbiBUaGUgUGFyc2UgQ2xvdWQgQ29kZSBTREsuXG4gKi9cblxudmFyIFBhcnNlQ2xvdWQgPSB7fTtcbi8qKlxuICogRGVmaW5lcyBhIENsb3VkIEZ1bmN0aW9uLlxuICpcbiAqICoqQXZhaWxhYmxlIGluIENsb3VkIENvZGUgb25seS4qKlxuXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyb2YgUGFyc2UuQ2xvdWRcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBDbG91ZCBGdW5jdGlvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZGF0YSBUaGUgQ2xvdWQgRnVuY3Rpb24gdG8gcmVnaXN0ZXIuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFuIGFzeW5jIGZ1bmN0aW9uIGFuZCBzaG91bGQgdGFrZSBvbmUgcGFyYW1ldGVyIGEge0BsaW5rIFBhcnNlLkNsb3VkLkZ1bmN0aW9uUmVxdWVzdH0uXG4gKi9cblBhcnNlQ2xvdWQuZGVmaW5lID0gZnVuY3Rpb24oZnVuY3Rpb25OYW1lLCBoYW5kbGVyLCB2YWxpZGF0aW9uSGFuZGxlcikge1xuICB0cmlnZ2Vycy5hZGRGdW5jdGlvbihcbiAgICBmdW5jdGlvbk5hbWUsXG4gICAgaGFuZGxlcixcbiAgICB2YWxpZGF0aW9uSGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG4vKipcbiAqIERlZmluZXMgYSBCYWNrZ3JvdW5kIEpvYi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcbiAqXG4gKiBAbWV0aG9kIGpvYlxuICogQG5hbWUgUGFyc2UuQ2xvdWQuam9iXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgQmFja2dyb3VuZCBKb2JcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIEJhY2tncm91bmQgSm9iIHRvIHJlZ2lzdGVyLiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSBhc3luYyBzaG91bGQgdGFrZSBhIHNpbmdsZSBwYXJhbWV0ZXJzIGEge0BsaW5rIFBhcnNlLkNsb3VkLkpvYlJlcXVlc3R9XG4gKlxuICovXG5QYXJzZUNsb3VkLmpvYiA9IGZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgaGFuZGxlcikge1xuICB0cmlnZ2Vycy5hZGRKb2IoZnVuY3Rpb25OYW1lLCBoYW5kbGVyLCBQYXJzZS5hcHBsaWNhdGlvbklkKTtcbn07XG5cbi8qKlxuICpcbiAqIFJlZ2lzdGVycyBhIGJlZm9yZSBzYXZlIGZ1bmN0aW9uLlxuICpcbiAqICoqQXZhaWxhYmxlIGluIENsb3VkIENvZGUgb25seS4qKlxuICpcbiAqIElmIHlvdSB3YW50IHRvIHVzZSBiZWZvcmVTYXZlIGZvciBhIHByZWRlZmluZWQgY2xhc3MgaW4gdGhlIFBhcnNlIEphdmFTY3JpcHQgU0RLIChlLmcuIHtAbGluayBQYXJzZS5Vc2VyfSksIHlvdSBzaG91bGQgcGFzcyB0aGUgY2xhc3MgaXRzZWxmIGFuZCBub3QgdGhlIFN0cmluZyBmb3IgYXJnMS5cbiAqXG4gKiBgYGBcbiAqIFBhcnNlLkNsb3VkLmJlZm9yZVNhdmUoJ015Q3VzdG9tQ2xhc3MnLCAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKlxuICogUGFyc2UuQ2xvdWQuYmVmb3JlU2F2ZShQYXJzZS5Vc2VyLCAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKiBgYGBcbiAqXG4gKiBAbWV0aG9kIGJlZm9yZVNhdmVcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmJlZm9yZVNhdmVcbiAqIEBwYXJhbSB7KFN0cmluZ3xQYXJzZS5PYmplY3QpfSBhcmcxIFRoZSBQYXJzZS5PYmplY3Qgc3ViY2xhc3MgdG8gcmVnaXN0ZXIgdGhlIGFmdGVyIHNhdmUgZnVuY3Rpb24gZm9yLiBUaGlzIGNhbiBpbnN0ZWFkIGJlIGEgU3RyaW5nIHRoYXQgaXMgdGhlIGNsYXNzTmFtZSBvZiB0aGUgc3ViY2xhc3MuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBydW4gYmVmb3JlIGEgc2F2ZS4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYXN5bmMgYW5kIHNob3VsZCB0YWtlIG9uZSBwYXJhbWV0ZXIgYSB7QGxpbmsgUGFyc2UuQ2xvdWQuVHJpZ2dlclJlcXVlc3R9O1xuICovXG5QYXJzZUNsb3VkLmJlZm9yZVNhdmUgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIHZhciBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUocGFyc2VDbGFzcyk7XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIoXG4gICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlU2F2ZSxcbiAgICBjbGFzc05hbWUsXG4gICAgaGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhIGJlZm9yZSBkZWxldGUgZnVuY3Rpb24uXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogSWYgeW91IHdhbnQgdG8gdXNlIGJlZm9yZURlbGV0ZSBmb3IgYSBwcmVkZWZpbmVkIGNsYXNzIGluIHRoZSBQYXJzZSBKYXZhU2NyaXB0IFNESyAoZS5nLiB7QGxpbmsgUGFyc2UuVXNlcn0pLCB5b3Ugc2hvdWxkIHBhc3MgdGhlIGNsYXNzIGl0c2VsZiBhbmQgbm90IHRoZSBTdHJpbmcgZm9yIGFyZzEuXG4gKiBgYGBcbiAqIFBhcnNlLkNsb3VkLmJlZm9yZURlbGV0ZSgnTXlDdXN0b21DbGFzcycsIChyZXF1ZXN0KSA9PiB7XG4gKiAgIC8vIGNvZGUgaGVyZVxuICogfSlcbiAqXG4gKiBQYXJzZS5DbG91ZC5iZWZvcmVEZWxldGUoUGFyc2UuVXNlciwgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpgYGBcbiAqXG4gKiBAbWV0aG9kIGJlZm9yZURlbGV0ZVxuICogQG5hbWUgUGFyc2UuQ2xvdWQuYmVmb3JlRGVsZXRlXG4gKiBAcGFyYW0geyhTdHJpbmd8UGFyc2UuT2JqZWN0KX0gYXJnMSBUaGUgUGFyc2UuT2JqZWN0IHN1YmNsYXNzIHRvIHJlZ2lzdGVyIHRoZSBiZWZvcmUgZGVsZXRlIGZ1bmN0aW9uIGZvci4gVGhpcyBjYW4gaW5zdGVhZCBiZSBhIFN0cmluZyB0aGF0IGlzIHRoZSBjbGFzc05hbWUgb2YgdGhlIHN1YmNsYXNzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcnVuIGJlZm9yZSBhIGRlbGV0ZS4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYXN5bmMgYW5kIHNob3VsZCB0YWtlIG9uZSBwYXJhbWV0ZXIsIGEge0BsaW5rIFBhcnNlLkNsb3VkLlRyaWdnZXJSZXF1ZXN0fS5cbiAqL1xuUGFyc2VDbG91ZC5iZWZvcmVEZWxldGUgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIHZhciBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUocGFyc2VDbGFzcyk7XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIoXG4gICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlRGVsZXRlLFxuICAgIGNsYXNzTmFtZSxcbiAgICBoYW5kbGVyLFxuICAgIFBhcnNlLmFwcGxpY2F0aW9uSWRcbiAgKTtcbn07XG5cbi8qKlxuICpcbiAqIFJlZ2lzdGVycyB0aGUgYmVmb3JlIGxvZ2luIGZ1bmN0aW9uLlxuICpcbiAqICoqQXZhaWxhYmxlIGluIENsb3VkIENvZGUgb25seS4qKlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gcHJvdmlkZXMgZnVydGhlciBjb250cm9sXG4gKiBpbiB2YWxpZGF0aW5nIGEgbG9naW4gYXR0ZW1wdC4gU3BlY2lmaWNhbGx5LFxuICogaXQgaXMgdHJpZ2dlcmVkIGFmdGVyIGEgdXNlciBlbnRlcnNcbiAqIGNvcnJlY3QgY3JlZGVudGlhbHMgKG9yIG90aGVyIHZhbGlkIGF1dGhEYXRhKSxcbiAqIGJ1dCBwcmlvciB0byBhIHNlc3Npb24gYmVpbmcgZ2VuZXJhdGVkLlxuICpcbiAqIGBgYFxuICogUGFyc2UuQ2xvdWQuYmVmb3JlTG9naW4oKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpcbiAqIGBgYFxuICpcbiAqIEBtZXRob2QgYmVmb3JlTG9naW5cbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmJlZm9yZUxvZ2luXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBydW4gYmVmb3JlIGEgbG9naW4uIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFzeW5jIGFuZCBzaG91bGQgdGFrZSBvbmUgcGFyYW1ldGVyIGEge0BsaW5rIFBhcnNlLkNsb3VkLlRyaWdnZXJSZXF1ZXN0fTtcbiAqL1xuUGFyc2VDbG91ZC5iZWZvcmVMb2dpbiA9IGZ1bmN0aW9uKGhhbmRsZXIpIHtcbiAgbGV0IGNsYXNzTmFtZSA9ICdfVXNlcic7XG4gIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gJ3N0cmluZycgfHwgaXNQYXJzZU9iamVjdENvbnN0cnVjdG9yKGhhbmRsZXIpKSB7XG4gICAgLy8gdmFsaWRhdGlvbiB3aWxsIG9jY3VyIGRvd25zdHJlYW0sIHRoaXMgaXMgdG8gbWFpbnRhaW4gaW50ZXJuYWxcbiAgICAvLyBjb2RlIGNvbnNpc3RlbmN5IHdpdGggdGhlIG90aGVyIGhvb2sgdHlwZXMuXG4gICAgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKGhhbmRsZXIpO1xuICAgIGhhbmRsZXIgPSBhcmd1bWVudHNbMV07XG4gIH1cbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcihcbiAgICB0cmlnZ2Vycy5UeXBlcy5iZWZvcmVMb2dpbixcbiAgICBjbGFzc05hbWUsXG4gICAgaGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG4vKipcbiAqXG4gKiBSZWdpc3RlcnMgdGhlIGFmdGVyIGxvZ2luIGZ1bmN0aW9uLlxuICpcbiAqICoqQXZhaWxhYmxlIGluIENsb3VkIENvZGUgb25seS4qKlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgdHJpZ2dlcmVkIGFmdGVyIGEgdXNlciBsb2dzIGluIHN1Y2Nlc3NmdWxseSxcbiAqIGFuZCBhZnRlciBhIF9TZXNzaW9uIG9iamVjdCBoYXMgYmVlbiBjcmVhdGVkLlxuICpcbiAqIGBgYFxuICogUGFyc2UuQ2xvdWQuYWZ0ZXJMb2dpbigocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKlxuICogYGBgXG4gKlxuICogQG1ldGhvZCBhZnRlckxvZ2luXG4gKiBAbmFtZSBQYXJzZS5DbG91ZC5hZnRlckxvZ2luXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBydW4gYWZ0ZXIgYSBsb2dpbi4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYXN5bmMgYW5kIHNob3VsZCB0YWtlIG9uZSBwYXJhbWV0ZXIgYSB7QGxpbmsgUGFyc2UuQ2xvdWQuVHJpZ2dlclJlcXVlc3R9O1xuICovXG5QYXJzZUNsb3VkLmFmdGVyTG9naW4gPSBmdW5jdGlvbihoYW5kbGVyKSB7XG4gIGxldCBjbGFzc05hbWUgPSAnX1VzZXInO1xuICBpZiAodHlwZW9mIGhhbmRsZXIgPT09ICdzdHJpbmcnIHx8IGlzUGFyc2VPYmplY3RDb25zdHJ1Y3RvcihoYW5kbGVyKSkge1xuICAgIC8vIHZhbGlkYXRpb24gd2lsbCBvY2N1ciBkb3duc3RyZWFtLCB0aGlzIGlzIHRvIG1haW50YWluIGludGVybmFsXG4gICAgLy8gY29kZSBjb25zaXN0ZW5jeSB3aXRoIHRoZSBvdGhlciBob29rIHR5cGVzLlxuICAgIGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShoYW5kbGVyKTtcbiAgICBoYW5kbGVyID0gYXJndW1lbnRzWzFdO1xuICB9XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIoXG4gICAgdHJpZ2dlcnMuVHlwZXMuYWZ0ZXJMb2dpbixcbiAgICBjbGFzc05hbWUsXG4gICAgaGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG4vKipcbiAqXG4gKiBSZWdpc3RlcnMgdGhlIGFmdGVyIGxvZ291dCBmdW5jdGlvbi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIHRyaWdnZXJlZCBhZnRlciBhIHVzZXIgbG9ncyBvdXQuXG4gKlxuICogYGBgXG4gKiBQYXJzZS5DbG91ZC5hZnRlckxvZ291dCgocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKlxuICogYGBgXG4gKlxuICogQG1ldGhvZCBhZnRlckxvZ291dFxuICogQG5hbWUgUGFyc2UuQ2xvdWQuYWZ0ZXJMb2dvdXRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJ1biBhZnRlciBhIGxvZ291dC4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYXN5bmMgYW5kIHNob3VsZCB0YWtlIG9uZSBwYXJhbWV0ZXIgYSB7QGxpbmsgUGFyc2UuQ2xvdWQuVHJpZ2dlclJlcXVlc3R9O1xuICovXG5QYXJzZUNsb3VkLmFmdGVyTG9nb3V0ID0gZnVuY3Rpb24oaGFuZGxlcikge1xuICBsZXQgY2xhc3NOYW1lID0gJ19TZXNzaW9uJztcbiAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSAnc3RyaW5nJyB8fCBpc1BhcnNlT2JqZWN0Q29uc3RydWN0b3IoaGFuZGxlcikpIHtcbiAgICAvLyB2YWxpZGF0aW9uIHdpbGwgb2NjdXIgZG93bnN0cmVhbSwgdGhpcyBpcyB0byBtYWludGFpbiBpbnRlcm5hbFxuICAgIC8vIGNvZGUgY29uc2lzdGVuY3kgd2l0aCB0aGUgb3RoZXIgaG9vayB0eXBlcy5cbiAgICBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUoaGFuZGxlcik7XG4gICAgaGFuZGxlciA9IGFyZ3VtZW50c1sxXTtcbiAgfVxuICB0cmlnZ2Vycy5hZGRUcmlnZ2VyKFxuICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyTG9nb3V0LFxuICAgIGNsYXNzTmFtZSxcbiAgICBoYW5kbGVyLFxuICAgIFBhcnNlLmFwcGxpY2F0aW9uSWRcbiAgKTtcbn07XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFuIGFmdGVyIHNhdmUgZnVuY3Rpb24uXG4gKlxuICogKipBdmFpbGFibGUgaW4gQ2xvdWQgQ29kZSBvbmx5LioqXG4gKlxuICogSWYgeW91IHdhbnQgdG8gdXNlIGFmdGVyU2F2ZSBmb3IgYSBwcmVkZWZpbmVkIGNsYXNzIGluIHRoZSBQYXJzZSBKYXZhU2NyaXB0IFNESyAoZS5nLiB7QGxpbmsgUGFyc2UuVXNlcn0pLCB5b3Ugc2hvdWxkIHBhc3MgdGhlIGNsYXNzIGl0c2VsZiBhbmQgbm90IHRoZSBTdHJpbmcgZm9yIGFyZzEuXG4gKlxuICogYGBgXG4gKiBQYXJzZS5DbG91ZC5hZnRlclNhdmUoJ015Q3VzdG9tQ2xhc3MnLCBhc3luYyBmdW5jdGlvbihyZXF1ZXN0KSB7XG4gKiAgIC8vIGNvZGUgaGVyZVxuICogfSlcbiAqXG4gKiBQYXJzZS5DbG91ZC5hZnRlclNhdmUoUGFyc2UuVXNlciwgYXN5bmMgZnVuY3Rpb24ocmVxdWVzdCkge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKiBgYGBcbiAqXG4gKiBAbWV0aG9kIGFmdGVyU2F2ZVxuICogQG5hbWUgUGFyc2UuQ2xvdWQuYWZ0ZXJTYXZlXG4gKiBAcGFyYW0geyhTdHJpbmd8UGFyc2UuT2JqZWN0KX0gYXJnMSBUaGUgUGFyc2UuT2JqZWN0IHN1YmNsYXNzIHRvIHJlZ2lzdGVyIHRoZSBhZnRlciBzYXZlIGZ1bmN0aW9uIGZvci4gVGhpcyBjYW4gaW5zdGVhZCBiZSBhIFN0cmluZyB0aGF0IGlzIHRoZSBjbGFzc05hbWUgb2YgdGhlIHN1YmNsYXNzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcnVuIGFmdGVyIGEgc2F2ZS4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYW4gYXN5bmMgZnVuY3Rpb24gYW5kIHNob3VsZCB0YWtlIGp1c3Qgb25lIHBhcmFtZXRlciwge0BsaW5rIFBhcnNlLkNsb3VkLlRyaWdnZXJSZXF1ZXN0fS5cbiAqL1xuUGFyc2VDbG91ZC5hZnRlclNhdmUgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIHZhciBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUocGFyc2VDbGFzcyk7XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIoXG4gICAgdHJpZ2dlcnMuVHlwZXMuYWZ0ZXJTYXZlLFxuICAgIGNsYXNzTmFtZSxcbiAgICBoYW5kbGVyLFxuICAgIFBhcnNlLmFwcGxpY2F0aW9uSWRcbiAgKTtcbn07XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFuIGFmdGVyIGRlbGV0ZSBmdW5jdGlvbi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcbiAqXG4gKiBJZiB5b3Ugd2FudCB0byB1c2UgYWZ0ZXJEZWxldGUgZm9yIGEgcHJlZGVmaW5lZCBjbGFzcyBpbiB0aGUgUGFyc2UgSmF2YVNjcmlwdCBTREsgKGUuZy4ge0BsaW5rIFBhcnNlLlVzZXJ9KSwgeW91IHNob3VsZCBwYXNzIHRoZSBjbGFzcyBpdHNlbGYgYW5kIG5vdCB0aGUgU3RyaW5nIGZvciBhcmcxLlxuICogYGBgXG4gKiBQYXJzZS5DbG91ZC5hZnRlckRlbGV0ZSgnTXlDdXN0b21DbGFzcycsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gKiAgIC8vIGNvZGUgaGVyZVxuICogfSlcbiAqXG4gKiBQYXJzZS5DbG91ZC5hZnRlckRlbGV0ZShQYXJzZS5Vc2VyLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKmBgYFxuICpcbiAqIEBtZXRob2QgYWZ0ZXJEZWxldGVcbiAqIEBuYW1lIFBhcnNlLkNsb3VkLmFmdGVyRGVsZXRlXG4gKiBAcGFyYW0geyhTdHJpbmd8UGFyc2UuT2JqZWN0KX0gYXJnMSBUaGUgUGFyc2UuT2JqZWN0IHN1YmNsYXNzIHRvIHJlZ2lzdGVyIHRoZSBhZnRlciBkZWxldGUgZnVuY3Rpb24gZm9yLiBUaGlzIGNhbiBpbnN0ZWFkIGJlIGEgU3RyaW5nIHRoYXQgaXMgdGhlIGNsYXNzTmFtZSBvZiB0aGUgc3ViY2xhc3MuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBydW4gYWZ0ZXIgYSBkZWxldGUuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIGFzeW5jIGFuZCBzaG91bGQgdGFrZSBqdXN0IG9uZSBwYXJhbWV0ZXIsIHtAbGluayBQYXJzZS5DbG91ZC5UcmlnZ2VyUmVxdWVzdH0uXG4gKi9cblBhcnNlQ2xvdWQuYWZ0ZXJEZWxldGUgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIHZhciBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUocGFyc2VDbGFzcyk7XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIoXG4gICAgdHJpZ2dlcnMuVHlwZXMuYWZ0ZXJEZWxldGUsXG4gICAgY2xhc3NOYW1lLFxuICAgIGhhbmRsZXIsXG4gICAgUGFyc2UuYXBwbGljYXRpb25JZFxuICApO1xufTtcblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBiZWZvcmUgZmluZCBmdW5jdGlvbi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcbiAqXG4gKiBJZiB5b3Ugd2FudCB0byB1c2UgYmVmb3JlRmluZCBmb3IgYSBwcmVkZWZpbmVkIGNsYXNzIGluIHRoZSBQYXJzZSBKYXZhU2NyaXB0IFNESyAoZS5nLiB7QGxpbmsgUGFyc2UuVXNlcn0pLCB5b3Ugc2hvdWxkIHBhc3MgdGhlIGNsYXNzIGl0c2VsZiBhbmQgbm90IHRoZSBTdHJpbmcgZm9yIGFyZzEuXG4gKiBgYGBcbiAqIFBhcnNlLkNsb3VkLmJlZm9yZUZpbmQoJ015Q3VzdG9tQ2xhc3MnLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKlxuICogUGFyc2UuQ2xvdWQuYmVmb3JlRmluZChQYXJzZS5Vc2VyLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKmBgYFxuICpcbiAqIEBtZXRob2QgYmVmb3JlRmluZFxuICogQG5hbWUgUGFyc2UuQ2xvdWQuYmVmb3JlRmluZFxuICogQHBhcmFtIHsoU3RyaW5nfFBhcnNlLk9iamVjdCl9IGFyZzEgVGhlIFBhcnNlLk9iamVjdCBzdWJjbGFzcyB0byByZWdpc3RlciB0aGUgYmVmb3JlIGZpbmQgZnVuY3Rpb24gZm9yLiBUaGlzIGNhbiBpbnN0ZWFkIGJlIGEgU3RyaW5nIHRoYXQgaXMgdGhlIGNsYXNzTmFtZSBvZiB0aGUgc3ViY2xhc3MuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBydW4gYmVmb3JlIGEgZmluZC4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYXN5bmMgYW5kIHNob3VsZCB0YWtlIGp1c3Qgb25lIHBhcmFtZXRlciwge0BsaW5rIFBhcnNlLkNsb3VkLkJlZm9yZUZpbmRSZXF1ZXN0fS5cbiAqL1xuUGFyc2VDbG91ZC5iZWZvcmVGaW5kID0gZnVuY3Rpb24ocGFyc2VDbGFzcywgaGFuZGxlcikge1xuICB2YXIgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpO1xuICB0cmlnZ2Vycy5hZGRUcmlnZ2VyKFxuICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZUZpbmQsXG4gICAgY2xhc3NOYW1lLFxuICAgIGhhbmRsZXIsXG4gICAgUGFyc2UuYXBwbGljYXRpb25JZFxuICApO1xufTtcblxuLyoqXG4gKiBSZWdpc3RlcnMgYW4gYWZ0ZXIgZmluZCBmdW5jdGlvbi5cbiAqXG4gKiAqKkF2YWlsYWJsZSBpbiBDbG91ZCBDb2RlIG9ubHkuKipcbiAqXG4gKiBJZiB5b3Ugd2FudCB0byB1c2UgYWZ0ZXJGaW5kIGZvciBhIHByZWRlZmluZWQgY2xhc3MgaW4gdGhlIFBhcnNlIEphdmFTY3JpcHQgU0RLIChlLmcuIHtAbGluayBQYXJzZS5Vc2VyfSksIHlvdSBzaG91bGQgcGFzcyB0aGUgY2xhc3MgaXRzZWxmIGFuZCBub3QgdGhlIFN0cmluZyBmb3IgYXJnMS5cbiAqIGBgYFxuICogUGFyc2UuQ2xvdWQuYWZ0ZXJGaW5kKCdNeUN1c3RvbUNsYXNzJywgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAqICAgLy8gY29kZSBoZXJlXG4gKiB9KVxuICpcbiAqIFBhcnNlLkNsb3VkLmFmdGVyRmluZChQYXJzZS5Vc2VyLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICogICAvLyBjb2RlIGhlcmVcbiAqIH0pXG4gKmBgYFxuICpcbiAqIEBtZXRob2QgYWZ0ZXJGaW5kXG4gKiBAbmFtZSBQYXJzZS5DbG91ZC5hZnRlckZpbmRcbiAqIEBwYXJhbSB7KFN0cmluZ3xQYXJzZS5PYmplY3QpfSBhcmcxIFRoZSBQYXJzZS5PYmplY3Qgc3ViY2xhc3MgdG8gcmVnaXN0ZXIgdGhlIGFmdGVyIGZpbmQgZnVuY3Rpb24gZm9yLiBUaGlzIGNhbiBpbnN0ZWFkIGJlIGEgU3RyaW5nIHRoYXQgaXMgdGhlIGNsYXNzTmFtZSBvZiB0aGUgc3ViY2xhc3MuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBydW4gYmVmb3JlIGEgZmluZC4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgYXN5bmMgYW5kIHNob3VsZCB0YWtlIGp1c3Qgb25lIHBhcmFtZXRlciwge0BsaW5rIFBhcnNlLkNsb3VkLkFmdGVyRmluZFJlcXVlc3R9LlxuICovXG5QYXJzZUNsb3VkLmFmdGVyRmluZCA9IGZ1bmN0aW9uKHBhcnNlQ2xhc3MsIGhhbmRsZXIpIHtcbiAgY29uc3QgY2xhc3NOYW1lID0gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpO1xuICB0cmlnZ2Vycy5hZGRUcmlnZ2VyKFxuICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyRmluZCxcbiAgICBjbGFzc05hbWUsXG4gICAgaGFuZGxlcixcbiAgICBQYXJzZS5hcHBsaWNhdGlvbklkXG4gICk7XG59O1xuXG5QYXJzZUNsb3VkLm9uTGl2ZVF1ZXJ5RXZlbnQgPSBmdW5jdGlvbihoYW5kbGVyKSB7XG4gIHRyaWdnZXJzLmFkZExpdmVRdWVyeUV2ZW50SGFuZGxlcihoYW5kbGVyLCBQYXJzZS5hcHBsaWNhdGlvbklkKTtcbn07XG5cblBhcnNlQ2xvdWQuX3JlbW92ZUFsbEhvb2tzID0gKCkgPT4ge1xuICB0cmlnZ2Vycy5fdW5yZWdpc3RlckFsbCgpO1xufTtcblxuUGFyc2VDbG91ZC51c2VNYXN0ZXJLZXkgPSAoKSA9PiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICBjb25zb2xlLndhcm4oXG4gICAgJ1BhcnNlLkNsb3VkLnVzZU1hc3RlcktleSBpcyBkZXByZWNhdGVkIChhbmQgaGFzIG5vIGVmZmVjdCBhbnltb3JlKSBvbiBwYXJzZS1zZXJ2ZXIsIHBsZWFzZSByZWZlciB0byB0aGUgY2xvdWQgY29kZSBtaWdyYXRpb24gbm90ZXM6IGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8jbWFzdGVyLWtleS1tdXN0LWJlLXBhc3NlZC1leHBsaWNpdGx5J1xuICApO1xufTtcblxuUGFyc2VDbG91ZC5odHRwUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cFJlcXVlc3QnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBQYXJzZUNsb3VkO1xuXG4vKipcbiAqIEBpbnRlcmZhY2UgUGFyc2UuQ2xvdWQuVHJpZ2dlclJlcXVlc3RcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpbnN0YWxsYXRpb25JZCBJZiBzZXQsIHRoZSBpbnN0YWxsYXRpb25JZCB0cmlnZ2VyaW5nIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtCb29sZWFufSBtYXN0ZXIgSWYgdHJ1ZSwgbWVhbnMgdGhlIG1hc3RlciBrZXkgd2FzIHVzZWQuXG4gKiBAcHJvcGVydHkge1BhcnNlLlVzZXJ9IHVzZXIgSWYgc2V0LCB0aGUgdXNlciB0aGF0IG1hZGUgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge1BhcnNlLk9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdHJpZ2dlcmluZyB0aGUgaG9vay5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpcCBUaGUgSVAgYWRkcmVzcyBvZiB0aGUgY2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBoZWFkZXJzIFRoZSBvcmlnaW5hbCBIVFRQIGhlYWRlcnMgZm9yIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtTdHJpbmd9IHRyaWdnZXJOYW1lIFRoZSBuYW1lIG9mIHRoZSB0cmlnZ2VyIChgYmVmb3JlU2F2ZWAsIGBhZnRlclNhdmVgLCAuLi4pXG4gKiBAcHJvcGVydHkge09iamVjdH0gbG9nIFRoZSBjdXJyZW50IGxvZ2dlciBpbnNpZGUgUGFyc2UgU2VydmVyLlxuICogQHByb3BlcnR5IHtQYXJzZS5PYmplY3R9IG9yaWdpbmFsIElmIHNldCwgdGhlIG9iamVjdCwgYXMgY3VycmVudGx5IHN0b3JlZC5cbiAqL1xuXG4vKipcbiAqIEBpbnRlcmZhY2UgUGFyc2UuQ2xvdWQuQmVmb3JlRmluZFJlcXVlc3RcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpbnN0YWxsYXRpb25JZCBJZiBzZXQsIHRoZSBpbnN0YWxsYXRpb25JZCB0cmlnZ2VyaW5nIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtCb29sZWFufSBtYXN0ZXIgSWYgdHJ1ZSwgbWVhbnMgdGhlIG1hc3RlciBrZXkgd2FzIHVzZWQuXG4gKiBAcHJvcGVydHkge1BhcnNlLlVzZXJ9IHVzZXIgSWYgc2V0LCB0aGUgdXNlciB0aGF0IG1hZGUgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge1BhcnNlLlF1ZXJ5fSBxdWVyeSBUaGUgcXVlcnkgdHJpZ2dlcmluZyB0aGUgaG9vay5cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpcCBUaGUgSVAgYWRkcmVzcyBvZiB0aGUgY2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBoZWFkZXJzIFRoZSBvcmlnaW5hbCBIVFRQIGhlYWRlcnMgZm9yIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtTdHJpbmd9IHRyaWdnZXJOYW1lIFRoZSBuYW1lIG9mIHRoZSB0cmlnZ2VyIChgYmVmb3JlU2F2ZWAsIGBhZnRlclNhdmVgLCAuLi4pXG4gKiBAcHJvcGVydHkge09iamVjdH0gbG9nIFRoZSBjdXJyZW50IGxvZ2dlciBpbnNpZGUgUGFyc2UgU2VydmVyLlxuICogQHByb3BlcnR5IHtCb29sZWFufSBpc0dldCB3ZXRoZXIgdGhlIHF1ZXJ5IGEgYGdldGAgb3IgYSBgZmluZGBcbiAqL1xuXG4vKipcbiAqIEBpbnRlcmZhY2UgUGFyc2UuQ2xvdWQuQWZ0ZXJGaW5kUmVxdWVzdFxuICogQHByb3BlcnR5IHtTdHJpbmd9IGluc3RhbGxhdGlvbklkIElmIHNldCwgdGhlIGluc3RhbGxhdGlvbklkIHRyaWdnZXJpbmcgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IG1hc3RlciBJZiB0cnVlLCBtZWFucyB0aGUgbWFzdGVyIGtleSB3YXMgdXNlZC5cbiAqIEBwcm9wZXJ0eSB7UGFyc2UuVXNlcn0gdXNlciBJZiBzZXQsIHRoZSB1c2VyIHRoYXQgbWFkZSB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7UGFyc2UuUXVlcnl9IHF1ZXJ5IFRoZSBxdWVyeSB0cmlnZ2VyaW5nIHRoZSBob29rLlxuICogQHByb3BlcnR5IHtBcnJheTxQYXJzZS5PYmplY3Q+fSByZXN1bHRzIFRoZSByZXN1bHRzIHRoZSBxdWVyeSB5aWVsZGVkLlxuICogQHByb3BlcnR5IHtTdHJpbmd9IGlwIFRoZSBJUCBhZGRyZXNzIG9mIHRoZSBjbGllbnQgbWFraW5nIHRoZSByZXF1ZXN0LlxuICogQHByb3BlcnR5IHtPYmplY3R9IGhlYWRlcnMgVGhlIG9yaWdpbmFsIEhUVFAgaGVhZGVycyBmb3IgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge1N0cmluZ30gdHJpZ2dlck5hbWUgVGhlIG5hbWUgb2YgdGhlIHRyaWdnZXIgKGBiZWZvcmVTYXZlYCwgYGFmdGVyU2F2ZWAsIC4uLilcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2cgVGhlIGN1cnJlbnQgbG9nZ2VyIGluc2lkZSBQYXJzZSBTZXJ2ZXIuXG4gKi9cblxuLyoqXG4gKiBAaW50ZXJmYWNlIFBhcnNlLkNsb3VkLkZ1bmN0aW9uUmVxdWVzdFxuICogQHByb3BlcnR5IHtTdHJpbmd9IGluc3RhbGxhdGlvbklkIElmIHNldCwgdGhlIGluc3RhbGxhdGlvbklkIHRyaWdnZXJpbmcgdGhlIHJlcXVlc3QuXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IG1hc3RlciBJZiB0cnVlLCBtZWFucyB0aGUgbWFzdGVyIGtleSB3YXMgdXNlZC5cbiAqIEBwcm9wZXJ0eSB7UGFyc2UuVXNlcn0gdXNlciBJZiBzZXQsIHRoZSB1c2VyIHRoYXQgbWFkZSB0aGUgcmVxdWVzdC5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBwYXJhbXMgVGhlIHBhcmFtcyBwYXNzZWQgdG8gdGhlIGNsb3VkIGZ1bmN0aW9uLlxuICovXG5cbi8qKlxuICogQGludGVyZmFjZSBQYXJzZS5DbG91ZC5Kb2JSZXF1ZXN0XG4gKiBAcHJvcGVydHkge09iamVjdH0gcGFyYW1zIFRoZSBwYXJhbXMgcGFzc2VkIHRvIHRoZSBiYWNrZ3JvdW5kIGpvYi5cbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb259IG1lc3NhZ2UgSWYgbWVzc2FnZSBpcyBjYWxsZWQgd2l0aCBhIHN0cmluZyBhcmd1bWVudCwgd2lsbCB1cGRhdGUgdGhlIGN1cnJlbnQgbWVzc2FnZSB0byBiZSBzdG9yZWQgaW4gdGhlIGpvYiBzdGF0dXMuXG4gKi9cbiJdfQ== \ 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..6dfeea76aa --- /dev/null +++ b/lib/middlewares.js @@ -0,0 +1,405 @@ +"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.sessionToken && typeof info.sessionToken !== 'string') { + info.sessionToken = info.sessionToken.toString(); + } + + if (info.sessionToken && typeof info.sessionToken !== 'string') { + info.sessionToken = info.sessionToken.toString(); + } + + 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 + }); + + if (!(process && process.env.TESTING)) { + 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.' + }); + + if (!(process && process.env.TESTING)) { + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9taWRkbGV3YXJlcy5qcyJdLCJuYW1lcyI6WyJERUZBVUxUX0FMTE9XRURfSEVBREVSUyIsImdldE1vdW50Rm9yUmVxdWVzdCIsInJlcSIsIm1vdW50UGF0aExlbmd0aCIsIm9yaWdpbmFsVXJsIiwibGVuZ3RoIiwidXJsIiwibW91bnRQYXRoIiwic2xpY2UiLCJwcm90b2NvbCIsImdldCIsImhhbmRsZVBhcnNlSGVhZGVycyIsInJlcyIsIm5leHQiLCJtb3VudCIsImluZm8iLCJhcHBJZCIsInNlc3Npb25Ub2tlbiIsIm1hc3RlcktleSIsImluc3RhbGxhdGlvbklkIiwiY2xpZW50S2V5IiwiamF2YXNjcmlwdEtleSIsImRvdE5ldEtleSIsInJlc3RBUElLZXkiLCJjbGllbnRWZXJzaW9uIiwiYmFzaWNBdXRoIiwiaHR0cEF1dGgiLCJiYXNpY0F1dGhBcHBJZCIsIkFwcENhY2hlIiwiYm9keSIsIl9ub0JvZHkiLCJmaWxlVmlhSlNPTiIsIkJ1ZmZlciIsIkpTT04iLCJwYXJzZSIsIl9SZXZvY2FibGVTZXNzaW9uIiwiX0FwcGxpY2F0aW9uSWQiLCJfSmF2YVNjcmlwdEtleSIsIl9DbGllbnRWZXJzaW9uIiwiX0luc3RhbGxhdGlvbklkIiwiX1Nlc3Npb25Ub2tlbiIsIl9NYXN0ZXJLZXkiLCJfQ29udGVudFR5cGUiLCJoZWFkZXJzIiwiaW52YWxpZFJlcXVlc3QiLCJ0b1N0cmluZyIsImNsaWVudFNESyIsIkNsaWVudFNESyIsImZyb21TdHJpbmciLCJiYXNlNjQiLCJmcm9tIiwiY2xpZW50SXAiLCJnZXRDbGllbnRJcCIsImFwcCIsImNvbmZpZyIsIkNvbmZpZyIsImlwIiwibWFzdGVyS2V5SXBzIiwiaW5kZXhPZiIsImlzTWFzdGVyIiwiYXV0aCIsIkF1dGgiLCJpc1JlYWRPbmx5TWFzdGVyIiwicmVhZE9ubHlNYXN0ZXJLZXkiLCJpc1JlYWRPbmx5Iiwia2V5cyIsIm9uZUtleUNvbmZpZ3VyZWQiLCJzb21lIiwia2V5IiwidW5kZWZpbmVkIiwib25lS2V5TWF0Y2hlcyIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsImdldEF1dGhGb3JMZWdhY3lTZXNzaW9uVG9rZW4iLCJnZXRBdXRoRm9yU2Vzc2lvblRva2VuIiwiY2F0Y2giLCJlcnJvciIsIlBhcnNlIiwiRXJyb3IiLCJsb2dnZXJDb250cm9sbGVyIiwiVU5LTk9XTl9FUlJPUiIsInNwbGl0IiwiY29ubmVjdGlvbiIsInJlbW90ZUFkZHJlc3MiLCJzb2NrZXQiLCJhdXRob3JpemF0aW9uIiwiaGVhZGVyIiwiYXV0aFByZWZpeCIsIm1hdGNoIiwidG9Mb3dlckNhc2UiLCJlbmNvZGVkQXV0aCIsInN1YnN0cmluZyIsImNyZWRlbnRpYWxzIiwiZGVjb2RlQmFzZTY0IiwianNLZXlQcmVmaXgiLCJtYXRjaEtleSIsInN0ciIsImFsbG93Q3Jvc3NEb21haW4iLCJhbGxvd0hlYWRlcnMiLCJqb2luIiwibWV0aG9kIiwic2VuZFN0YXR1cyIsImFsbG93TWV0aG9kT3ZlcnJpZGUiLCJfbWV0aG9kIiwib3JpZ2luYWxNZXRob2QiLCJoYW5kbGVQYXJzZUVycm9ycyIsImVyciIsImxvZyIsImRlZmF1bHRMb2dnZXIiLCJodHRwU3RhdHVzIiwiY29kZSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsIk9CSkVDVF9OT1RfRk9VTkQiLCJzdGF0dXMiLCJqc29uIiwibWVzc2FnZSIsImVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXIiLCJwcm9jZXNzIiwiZW52IiwiVEVTVElORyIsInN0YWNrIiwiZW5mb3JjZU1hc3RlcktleUFjY2VzcyIsImVuZCIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwicmVxdWVzdCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsdUJBQXVCLEdBQ2xDLDJOQURLOzs7QUFHUCxNQUFNQyxrQkFBa0IsR0FBRyxVQUFTQyxHQUFULEVBQWM7QUFDdkMsUUFBTUMsZUFBZSxHQUFH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UixFQUFQO0FBQ0Q7O0FBRUQsU0FBUzVCLGNBQVQsQ0FBd0IxQyxHQUF4QixFQUE2QlUsR0FBN0IsRUFBa0M7QUFDaENBLEVBQUFBLEdBQUcsQ0FBQ3NHLE1BQUosQ0FBVyxHQUFYO0FBQ0F0RyxFQUFBQSxHQUFHLENBQUMrRyxHQUFKLENBQVEsMEJBQVI7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBBcHBDYWNoZSBmcm9tICcuL2NhY2hlJztcbmltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBhdXRoIGZyb20gJy4vQXV0aCc7XG5pbXBvcnQgQ29uZmlnIGZyb20gJy4vQ29uZmlnJztcbmltcG9ydCBDbGllbnRTREsgZnJvbSAnLi9DbGllbnRTREsnO1xuaW1wb3J0IGRlZmF1bHRMb2dnZXIgZnJvbSAnLi9sb2dnZXInO1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9BTExPV0VEX0hFQURFUlMgPVxuICAnWC1QYXJzZS1NYXN0ZXItS2V5LCBYLVBhcnNlLVJFU1QtQVBJLUtleSwgWC1QYXJzZS1KYXZhc2NyaXB0LUtleSwgWC1QYXJzZS1BcHBsaWNhdGlvbi1JZCwgWC1QYXJzZS1DbGllbnQtVmVyc2lvbiwgWC1QYXJzZS1TZXNzaW9uLVRva2VuLCBYLVJlcXVlc3RlZC1XaXRoLCBYLVBhcnNlLVJldm9jYWJsZS1TZXNzaW9uLCBDb250ZW50LVR5cGUsIFByYWdtYSwgQ2FjaGUtQ29udHJvbCc7XG5cbmNvbnN0IGdldE1vdW50Rm9yUmVxdWVzdCA9IGZ1bmN0aW9uKHJlcSkge1xuICBjb25zdCBtb3VudFBhdGhMZW5ndGggPSByZXEub3JpZ2luYWxVcmwubGVuZ3RoIC0gcmVxLnVybC5sZW5ndGg7XG4gIGNvbnN0IG1vdW50UGF0aCA9IHJlcS5vcmlnaW5hbFVybC5zbGljZSgwLCBtb3VudFBhdGhMZW5ndGgpO1xuICByZXR1cm4gcmVxLnByb3RvY29sICsgJzovLycgKyByZXEuZ2V0KCdob3N0JykgKyBtb3VudFBhdGg7XG59O1xuXG4vLyBDaGVja3MgdGhhdCB0aGUgcmVxdWVzdCBpcyBhdXRob3JpemVkIGZvciB0aGlzIGFwcCBhbmQgY2hlY2tzIHVzZXJcbi8vIGF1dGggdG9vLlxuLy8gVGhlIGJvZHlwYXJzZXIgc2hvdWxkIHJ1biBiZWZvcmUgdGhpcyBtaWRkbGV3YXJlLlxuLy8gQWRkcyBpbmZvIHRvIHRoZSByZXF1ZXN0OlxuLy8gcmVxLmNvbmZpZyAtIHRoZSBDb25maWcgZm9yIHRoaXMgYXBwXG4vLyByZXEuYXV0aCAtIHRoZSBBdXRoIGZvciB0aGlzIHJlcXVlc3RcbmV4cG9ydCBmdW5jdGlvbiBoYW5kbGVQYXJzZUhlYWRlcnMocmVxLCByZXMsIG5leHQpIHtcbiAgdmFyIG1vdW50ID0gZ2V0TW91bnRGb3JSZXF1ZXN0KHJlcSk7XG5cbiAgdmFyIGluZm8gPSB7XG4gICAgYXBwSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtQXBwbGljYXRpb24tSWQnKSxcbiAgICBzZXNzaW9uVG9rZW46IHJlcS5nZXQoJ1gtUGFyc2UtU2Vzc2lvbi1Ub2tlbicpLFxuICAgIG1hc3RlcktleTogcmVxLmdldCgnWC1QYXJzZS1NYXN0ZXItS2V5JyksXG4gICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtSW5zdGFsbGF0aW9uLUlkJyksXG4gICAgY2xpZW50S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1LZXknKSxcbiAgICBqYXZhc2NyaXB0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUphdmFzY3JpcHQtS2V5JyksXG4gICAgZG90TmV0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLVdpbmRvd3MtS2V5JyksXG4gICAgcmVzdEFQSUtleTogcmVxLmdldCgnWC1QYXJzZS1SRVNULUFQSS1LZXknKSxcbiAgICBjbGllbnRWZXJzaW9uOiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1WZXJzaW9uJyksXG4gIH07XG5cbiAgdmFyIGJhc2ljQXV0aCA9IGh0dHBBdXRoKHJlcSk7XG5cbiAgaWYgKGJhc2ljQXV0aCkge1xuICAgIHZhciBiYXNpY0F1dGhBcHBJZCA9IGJhc2ljQXV0aC5hcHBJZDtcbiAgICBpZiAoQXBwQ2FjaGUuZ2V0KGJhc2ljQXV0aEFwcElkKSkge1xuICAgICAgaW5mby5hcHBJZCA9IGJhc2ljQXV0aEFwcElkO1xuICAgICAgaW5mby5tYXN0ZXJLZXkgPSBiYXNpY0F1dGgubWFzdGVyS2V5IHx8IGluZm8ubWFzdGVyS2V5O1xuICAgICAgaW5mby5qYXZhc2NyaXB0S2V5ID0gYmFzaWNBdXRoLmphdmFzY3JpcHRLZXkgfHwgaW5mby5qYXZhc2NyaXB0S2V5O1xuICAgIH1cbiAgfVxuXG4gIGlmIChyZXEuYm9keSkge1xuICAgIC8vIFVuaXR5IFNESyBzZW5kcyBhIF9ub0JvZHkga2V5IHdoaWNoIG5lZWRzIHRvIGJlIHJlbW92ZWQuXG4gICAgLy8gVW5jbGVhciBhdCB0aGlzIHBvaW50IGlmIGFjdGlvbiBuZWVkcyB0byBiZSB0YWtlbi5cbiAgICBkZWxldGUgcmVxLmJvZHkuX25vQm9keTtcbiAgfVxuXG4gIHZhciBmaWxlVmlhSlNPTiA9IGZhbHNlO1xuXG4gIGlmICghaW5mby5hcHBJZCB8fCAhQXBwQ2FjaGUuZ2V0KGluZm8uYXBwSWQpKSB7XG4gICAgLy8gU2VlIGlmIHdlIGNhbiBmaW5kIHRoZSBhcHAgaWQgb24gdGhlIGJvZHkuXG4gICAgaWYgKHJlcS5ib2R5IGluc3RhbmNlb2YgQnVmZmVyKSB7XG4gICAgICAvLyBUaGUgb25seSBjaGFuY2UgdG8gZmluZCB0aGUgYXBwIGlkIGlzIGlmIHRoaXMgaXMgYSBmaWxlXG4gICAgICAvLyB1cGxvYWQgdGhhdCBhY3R1YWxseSBpcyBhIEpTT04gYm9keS4gU28gdHJ5IHRvIHBhcnNlIGl0LlxuICAgICAgcmVxLmJvZHkgPSBKU09OLnBhcnNlKHJlcS5ib2R5KTtcbiAgICAgIGZpbGVWaWFKU09OID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAocmVxLmJvZHkpIHtcbiAgICAgIGRlbGV0ZSByZXEuYm9keS5fUmV2b2NhYmxlU2Vzc2lvbjtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICByZXEuYm9keSAmJlxuICAgICAgcmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQgJiZcbiAgICAgIEFwcENhY2hlLmdldChyZXEuYm9keS5fQXBwbGljYXRpb25JZCkgJiZcbiAgICAgICghaW5mby5tYXN0ZXJLZXkgfHxcbiAgICAgICAgQXBwQ2FjaGUuZ2V0KHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkKS5tYXN0ZXJLZXkgPT09IGluZm8ubWFzdGVyS2V5KVxuICAgICkge1xuICAgICAgaW5mby5hcHBJZCA9IHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkO1xuICAgICAgaW5mby5qYXZhc2NyaXB0S2V5ID0gcmVxLmJvZHkuX0phdmFTY3JpcHRLZXkgfHwgJyc7XG4gICAgICBkZWxldGUgcmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQ7XG4gICAgICBkZWxldGUgcmVxLmJvZHkuX0phdmFTY3JpcHRLZXk7XG4gICAgICAvLyBUT0RPOiB0ZXN0IHRoYXQgdGhlIFJFU1QgQVBJIGZvcm1hdHMgZ2VuZXJhdGVkIGJ5IHRoZSBvdGhlclxuICAgICAgLy8gU0RLcyBhcmUgaGFuZGxlZCBva1xuICAgICAgaWYgKHJlcS5ib2R5Ll9DbGllbnRWZXJzaW9uKSB7XG4gICAgICAgIGluZm8uY2xpZW50VmVyc2lvbiA9IHJlcS5ib2R5Ll9DbGllbnRWZXJzaW9uO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX0NsaWVudFZlcnNpb247XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX0luc3RhbGxhdGlvbklkKSB7XG4gICAgICAgIGluZm8uaW5zdGFsbGF0aW9uSWQgPSByZXEuYm9keS5fSW5zdGFsbGF0aW9uSWQ7XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fSW5zdGFsbGF0aW9uSWQ7XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX1Nlc3Npb25Ub2tlbikge1xuICAgICAgICBpbmZvLnNlc3Npb25Ub2tlbiA9IHJlcS5ib2R5Ll9TZXNzaW9uVG9rZW47XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fU2Vzc2lvblRva2VuO1xuICAgICAgfVxuICAgICAgaWYgKHJlcS5ib2R5Ll9NYXN0ZXJLZXkpIHtcbiAgICAgICAgaW5mby5tYXN0ZXJLZXkgPSByZXEuYm9keS5fTWFzdGVyS2V5O1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX01hc3RlcktleTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXEuYm9keS5fQ29udGVudFR5cGUpIHtcbiAgICAgICAgcmVxLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddID0gcmVxLmJvZHkuX0NvbnRlbnRUeXBlO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX0NvbnRlbnRUeXBlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICAgIH1cbiAgfVxuICBpZiAoaW5mby5zZXNzaW9uVG9rZW4gJiYgdHlwZW9mIGluZm8uc2Vzc2lvblRva2VuICE9PSAnc3RyaW5nJykge1xuICAgIGluZm8uc2Vzc2lvblRva2VuID0gaW5mby5zZXNzaW9uVG9rZW4udG9TdHJpbmcoKTtcbiAgfVxuXG4gIGlmIChpbmZvLnNlc3Npb25Ub2tlbiAmJiB0eXBlb2YgaW5mby5zZXNzaW9uVG9rZW4gIT09ICdzdHJpbmcnKSB7XG4gICAgaW5mby5zZXNzaW9uVG9rZW4gPSBpbmZvLnNlc3Npb25Ub2tlbi50b1N0cmluZygpO1xuICB9XG5cbiAgaWYgKGluZm8uY2xpZW50VmVyc2lvbikge1xuICAgIGluZm8uY2xpZW50U0RLID0gQ2xpZW50U0RLLmZyb21TdHJpbmcoaW5mby5jbGllbnRWZXJzaW9uKTtcbiAgfVxuXG4gIGlmIChmaWxlVmlhSlNPTikge1xuICAgIC8vIFdlIG5lZWQgdG8gcmVwb3B1bGF0ZSByZXEuYm9keSB3aXRoIGEgYnVmZmVyXG4gICAgdmFyIGJhc2U2NCA9IHJlcS5ib2R5LmJhc2U2NDtcbiAgICByZXEuYm9keSA9IEJ1ZmZlci5mcm9tKGJhc2U2NCwgJ2Jhc2U2NCcpO1xuICB9XG5cbiAgY29uc3QgY2xpZW50SXAgPSBnZXRDbGllbnRJcChyZXEpO1xuXG4gIGluZm8uYXBwID0gQXBwQ2FjaGUuZ2V0KGluZm8uYXBwSWQpO1xuICByZXEuY29uZmlnID0gQ29uZmlnLmdldChpbmZvLmFwcElkLCBtb3VudCk7XG4gIHJlcS5jb25maWcuaGVhZGVycyA9IHJlcS5oZWFkZXJzIHx8IHt9O1xuICByZXEuY29uZmlnLmlwID0gY2xpZW50SXA7XG4gIHJlcS5pbmZvID0gaW5mbztcblxuICBpZiAoXG4gICAgaW5mby5tYXN0ZXJLZXkgJiZcbiAgICByZXEuY29uZmlnLm1hc3RlcktleUlwcyAmJlxuICAgIHJlcS5jb25maWcubWFzdGVyS2V5SXBzLmxlbmd0aCAhPT0gMCAmJlxuICAgIHJlcS5jb25maWcubWFzdGVyS2V5SXBzLmluZGV4T2YoY2xpZW50SXApID09PSAtMVxuICApIHtcbiAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICB9XG5cbiAgdmFyIGlzTWFzdGVyID0gaW5mby5tYXN0ZXJLZXkgPT09IHJlcS5jb25maWcubWFzdGVyS2V5O1xuXG4gIGlmIChpc01hc3Rlcikge1xuICAgIHJlcS5hdXRoID0gbmV3IGF1dGguQXV0aCh7XG4gICAgICBjb25maWc6IHJlcS5jb25maWcsXG4gICAgICBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCxcbiAgICAgIGlzTWFzdGVyOiB0cnVlLFxuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgaXNSZWFkT25seU1hc3RlciA9IGluZm8ubWFzdGVyS2V5ID09PSByZXEuY29uZmlnLnJlYWRPbmx5TWFzdGVyS2V5O1xuICBpZiAoXG4gICAgdHlwZW9mIHJlcS5jb25maWcucmVhZE9ubHlNYXN0ZXJLZXkgIT0gJ3VuZGVmaW5lZCcgJiZcbiAgICByZXEuY29uZmlnLnJlYWRPbmx5TWFzdGVyS2V5ICYmXG4gICAgaXNSZWFkT25seU1hc3RlclxuICApIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoe1xuICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsXG4gICAgICBpc01hc3RlcjogdHJ1ZSxcbiAgICAgIGlzUmVhZE9ubHk6IHRydWUsXG4gICAgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIENsaWVudCBrZXlzIGFyZSBub3QgcmVxdWlyZWQgaW4gcGFyc2Utc2VydmVyLCBidXQgaWYgYW55IGhhdmUgYmVlbiBjb25maWd1cmVkIGluIHRoZSBzZXJ2ZXIsIHZhbGlkYXRlIHRoZW1cbiAgLy8gIHRvIHByZXNlcnZlIG9yaWdpbmFsIGJlaGF2aW9yLlxuICBjb25zdCBrZXlzID0gWydjbGllbnRLZXknLCAnamF2YXNjcmlwdEtleScsICdkb3ROZXRLZXknLCAncmVzdEFQSUtleSddO1xuICBjb25zdCBvbmVLZXlDb25maWd1cmVkID0ga2V5cy5zb21lKGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiByZXEuY29uZmlnW2tleV0gIT09IHVuZGVmaW5lZDtcbiAgfSk7XG4gIGNvbnN0IG9uZUtleU1hdGNoZXMgPSBrZXlzLnNvbWUoZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIHJlcS5jb25maWdba2V5XSAhPT0gdW5kZWZpbmVkICYmIGluZm9ba2V5XSA9PT0gcmVxLmNvbmZpZ1trZXldO1xuICB9KTtcblxuICBpZiAob25lS2V5Q29uZmlndXJlZCAmJiAhb25lS2V5TWF0Y2hlcykge1xuICAgIHJldHVybiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcyk7XG4gIH1cblxuICBpZiAocmVxLnVybCA9PSAnL2xvZ2luJykge1xuICAgIGRlbGV0ZSBpbmZvLnNlc3Npb25Ub2tlbjtcbiAgfVxuXG4gIGlmICghaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoe1xuICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsXG4gICAgICBpc01hc3RlcjogZmFsc2UsXG4gICAgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIC8vIGhhbmRsZSB0aGUgdXBncmFkZVRvUmV2b2NhYmxlU2Vzc2lvbiBwYXRoIG9uIGl0J3Mgb3duXG4gICAgICBpZiAoXG4gICAgICAgIGluZm8uc2Vzc2lvblRva2VuICYmXG4gICAgICAgIHJlcS51cmwgPT09ICcvdXBncmFkZVRvUmV2b2NhYmxlU2Vzc2lvbicgJiZcbiAgICAgICAgaW5mby5zZXNzaW9uVG9rZW4uaW5kZXhPZigncjonKSAhPSAwXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbih7XG4gICAgICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgICAgIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLFxuICAgICAgICAgIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4sXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvclNlc3Npb25Ub2tlbih7XG4gICAgICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgICAgIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLFxuICAgICAgICAgIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pXG4gICAgLnRoZW4oYXV0aCA9PiB7XG4gICAgICBpZiAoYXV0aCkge1xuICAgICAgICByZXEuYXV0aCA9IGF1dGg7XG4gICAgICAgIG5leHQoKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgICAgICBuZXh0KGVycm9yKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVE9ETzogRGV0ZXJtaW5lIHRoZSBjb3JyZWN0IGVycm9yIHNjZW5hcmlvLlxuICAgICAgICByZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIuZXJyb3IoXG4gICAgICAgICAgJ2Vycm9yIGdldHRpbmcgYXV0aCBmb3Igc2Vzc2lvblRva2VuJyxcbiAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVU5LTk9XTl9FUlJPUiwgZXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRDbGllbnRJcChyZXEpIHtcbiAgaWYgKHJlcS5oZWFkZXJzWyd4LWZvcndhcmRlZC1mb3InXSkge1xuICAgIC8vIHRyeSB0byBnZXQgZnJvbSB4LWZvcndhcmVkLWZvciBpZiBpdCBzZXQgKGJlaGluZCByZXZlcnNlIHByb3h5KVxuICAgIHJldHVybiByZXEuaGVhZGVyc1sneC1mb3J3YXJkZWQtZm9yJ10uc3BsaXQoJywnKVswXTtcbiAgfSBlbHNlIGlmIChyZXEuY29ubmVjdGlvbiAmJiByZXEuY29ubmVjdGlvbi5yZW1vdGVBZGRyZXNzKSB7XG4gICAgLy8gbm8gcHJveHksIHRyeSBnZXR0aW5nIGZyb20gY29ubmVjdGlvbi5yZW1vdGVBZGRyZXNzXG4gICAgcmV0dXJuIHJlcS5jb25uZWN0aW9uLnJlbW90ZUFkZHJlc3M7XG4gIH0gZWxzZSBpZiAocmVxLnNvY2tldCkge1xuICAgIC8vIHRyeSB0byBnZXQgaXQgZnJvbSByZXEuc29ja2V0XG4gICAgcmV0dXJuIHJlcS5zb2NrZXQucmVtb3RlQWRkcmVzcztcbiAgfSBlbHNlIGlmIChyZXEuY29ubmVjdGlvbiAmJiByZXEuY29ubmVjdGlvbi5zb2NrZXQpIHtcbiAgICAvLyB0cnkgdG8gZ2V0IGl0IGZvcm0gdGhlIGNvbm5lY3Rpb24uc29ja2V0XG4gICAgcmV0dXJuIHJlcS5jb25uZWN0aW9uLnNvY2tldC5yZW1vdGVBZGRyZXNzO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIG5vbiBhYm92ZSwgZmFsbGJhY2suXG4gICAgcmV0dXJuIHJlcS5pcDtcbiAgfVxufVxuXG5mdW5jdGlvbiBodHRwQXV0aChyZXEpIHtcbiAgaWYgKCEocmVxLnJlcSB8fCByZXEpLmhlYWRlcnMuYXV0aG9yaXphdGlvbikgcmV0dXJuO1xuXG4gIHZhciBoZWFkZXIgPSAocmVxLnJlcSB8fCByZXEpLmhlYWRlcnMuYXV0aG9yaXphdGlvbjtcbiAgdmFyIGFwcElkLCBtYXN0ZXJLZXksIGphdmFzY3JpcHRLZXk7XG5cbiAgLy8gcGFyc2UgaGVhZGVyXG4gIHZhciBhdXRoUHJlZml4ID0gJ2Jhc2ljICc7XG5cbiAgdmFyIG1hdGNoID0gaGVhZGVyLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihhdXRoUHJlZml4KTtcblxuICBpZiAobWF0Y2ggPT0gMCkge1xuICAgIHZhciBlbmNvZGVkQXV0aCA9IGhlYWRlci5zdWJzdHJpbmcoYXV0aFByZWZpeC5sZW5ndGgsIGhlYWRlci5sZW5ndGgpO1xuICAgIHZhciBjcmVkZW50aWFscyA9IGRlY29kZUJhc2U2NChlbmNvZGVkQXV0aCkuc3BsaXQoJzonKTtcblxuICAgIGlmIChjcmVkZW50aWFscy5sZW5ndGggPT0gMikge1xuICAgICAgYXBwSWQgPSBjcmVkZW50aWFsc1swXTtcbiAgICAgIHZhciBrZXkgPSBjcmVkZW50aWFsc1sxXTtcblxuICAgICAgdmFyIGpzS2V5UHJlZml4ID0gJ2phdmFzY3JpcHQta2V5PSc7XG5cbiAgICAgIHZhciBtYXRjaEtleSA9IGtleS5pbmRleE9mKGpzS2V5UHJlZml4KTtcbiAgICAgIGlmIChtYXRjaEtleSA9PSAwKSB7XG4gICAgICAgIGphdmFzY3JpcHRLZXkgPSBrZXkuc3Vic3RyaW5nKGpzS2V5UHJlZml4Lmxlbmd0aCwga2V5Lmxlbmd0aCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXN0ZXJLZXkgPSBrZXk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgYXBwSWQ6IGFwcElkLCBtYXN0ZXJLZXk6IG1hc3RlcktleSwgamF2YXNjcmlwdEtleTogamF2YXNjcmlwdEtleSB9O1xufVxuXG5mdW5jdGlvbiBkZWNvZGVCYXNlNjQoc3RyKSB7XG4gIHJldHVybiBCdWZmZXIuZnJvbShzdHIsICdiYXNlNjQnKS50b1N0cmluZygpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWxsb3dDcm9zc0RvbWFpbihhcHBJZCkge1xuICByZXR1cm4gKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChhcHBJZCwgZ2V0TW91bnRGb3JSZXF1ZXN0KHJlcSkpO1xuICAgIGxldCBhbGxvd0hlYWRlcnMgPSBERUZBVUxUX0FMTE9XRURfSEVBREVSUztcbiAgICBpZiAoY29uZmlnICYmIGNvbmZpZy5hbGxvd0hlYWRlcnMpIHtcbiAgICAgIGFsbG93SGVhZGVycyArPSBgLCAke2NvbmZpZy5hbGxvd0hlYWRlcnMuam9pbignLCAnKX1gO1xuICAgIH1cbiAgICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4nLCAnKicpO1xuICAgIHJlcy5oZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnLCAnR0VULFBVVCxQT1NULERFTEVURSxPUFRJT05TJyk7XG4gICAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycycsIGFsbG93SGVhZGVycyk7XG4gICAgcmVzLmhlYWRlcihcbiAgICAgICdBY2Nlc3MtQ29udHJvbC1FeHBvc2UtSGVhZGVycycsXG4gICAgICAnWC1QYXJzZS1Kb2ItU3RhdHVzLUlkLCBYLVBhcnNlLVB1c2gtU3RhdHVzLUlkJ1xuICAgICk7XG4gICAgLy8gaW50ZXJjZXB0IE9QVElPTlMgbWV0aG9kXG4gICAgaWYgKCdPUFRJT05TJyA9PSByZXEubWV0aG9kKSB7XG4gICAgICByZXMuc2VuZFN0YXR1cygyMDApO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXh0KCk7XG4gICAgfVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWxsb3dNZXRob2RPdmVycmlkZShyZXEsIHJlcywgbmV4dCkge1xuICBpZiAocmVxLm1ldGhvZCA9PT0gJ1BPU1QnICYmIHJlcS5ib2R5Ll9tZXRob2QpIHtcbiAgICByZXEub3JpZ2luYWxNZXRob2QgPSByZXEubWV0aG9kO1xuICAgIHJlcS5tZXRob2QgPSByZXEuYm9keS5fbWV0aG9kO1xuICAgIGRlbGV0ZSByZXEuYm9keS5fbWV0aG9kO1xuICB9XG4gIG5leHQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZVBhcnNlRXJyb3JzKGVyciwgcmVxLCByZXMsIG5leHQpIHtcbiAgY29uc3QgbG9nID0gKHJlcS5jb25maWcgJiYgcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyKSB8fCBkZWZhdWx0TG9nZ2VyO1xuICBpZiAoZXJyIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IpIHtcbiAgICBsZXQgaHR0cFN0YXR1cztcbiAgICAvLyBUT0RPOiBmaWxsIG91dCB0aGlzIG1hcHBpbmdcbiAgICBzd2l0Y2ggKGVyci5jb2RlKSB7XG4gICAgICBjYXNlIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUjpcbiAgICAgICAgaHR0cFN0YXR1cyA9IDUwMDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQ6XG4gICAgICAgIGh0dHBTdGF0dXMgPSA0MDQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaHR0cFN0YXR1cyA9IDQwMDtcbiAgICB9XG5cbiAgICByZXMuc3RhdHVzKGh0dHBTdGF0dXMpO1xuICAgIHJlcy5qc29uKHsgY29kZTogZXJyLmNvZGUsIGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICBsb2cuZXJyb3IoJ1BhcnNlIGVycm9yOiAnLCBlcnIpO1xuICAgIGlmIChyZXEuY29uZmlnICYmIHJlcS5jb25maWcuZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlcikge1xuICAgICAgbmV4dChlcnIpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChlcnIuc3RhdHVzICYmIGVyci5tZXNzYWdlKSB7XG4gICAgcmVzLnN0YXR1cyhlcnIuc3RhdHVzKTtcbiAgICByZXMuanNvbih7IGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICBpZiAoIShwcm9jZXNzICYmIHByb2Nlc3MuZW52LlRFU1RJTkcpKSB7XG4gICAgICBuZXh0KGVycik7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGxvZy5lcnJvcignVW5jYXVnaHQgaW50ZXJuYWwgc2VydmVyIGVycm9yLicsIGVyciwgZXJyLnN0YWNrKTtcbiAgICByZXMuc3RhdHVzKDUwMCk7XG4gICAgcmVzLmpzb24oe1xuICAgICAgY29kZTogUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgbWVzc2FnZTogJ0ludGVybmFsIHNlcnZlciBlcnJvci4nLFxuICAgIH0pO1xuICAgIGlmICghKHByb2Nlc3MgJiYgcHJvY2Vzcy5lbnYuVEVTVElORykpIHtcbiAgICAgIG5leHQoZXJyKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MocmVxLCByZXMsIG5leHQpIHtcbiAgaWYgKCFyZXEuYXV0aC5pc01hc3Rlcikge1xuICAgIHJlcy5zdGF0dXMoNDAzKTtcbiAgICByZXMuZW5kKCd7XCJlcnJvclwiOlwidW5hdXRob3JpemVkOiBtYXN0ZXIga2V5IGlzIHJlcXVpcmVkXCJ9Jyk7XG4gICAgcmV0dXJuO1xuICB9XG4gIG5leHQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzKHJlcXVlc3QpIHtcbiAgaWYgKCFyZXF1ZXN0LmF1dGguaXNNYXN0ZXIpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIGVycm9yLnN0YXR1cyA9IDQwMztcbiAgICBlcnJvci5tZXNzYWdlID0gJ3VuYXV0aG9yaXplZDogbWFzdGVyIGtleSBpcyByZXF1aXJlZCc7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG5mdW5jdGlvbiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcykge1xuICByZXMuc3RhdHVzKDQwMyk7XG4gIHJlcy5lbmQoJ3tcImVycm9yXCI6XCJ1bmF1dGhvcml6ZWRcIn0nKTtcbn1cbiJdfQ== \ 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..4726dffad3 --- /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, options) { + enforceRoleSecurity('create', className, auth); + var write = new RestWrite(config, auth, className, null, restObject, null, clientSDK, options); + 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, 'update').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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cEQ7OztBQUNBLE1BQUlTLDJCQUEyQixDQUFDRyxPQUE1QixDQUFvQy9FLFNBQXBDLEtBQWtELENBQWxELElBQXVELENBQUNZLElBQUksQ0FBQzRCLFFBQWpFLEVBQTJFO0FBQ3pFLFVBQU0yQixLQUFLLEdBQUkseUNBQXdDVSxNQUFPLHFCQUFvQjdFLFNBQVUsY0FBNUY7QUFDQSxVQUFNLElBQUlOLEtBQUssQ0FBQ2dDLEtBQVYsQ0FBZ0JoQyxLQUFLLENBQUNnQyxLQUFOLENBQVlvRCxtQkFBNUIsRUFBaURYLEtBQWpELENBQU47QUFDRCxHQVptRCxDQWNwRDs7O0FBQ0EsTUFDRXZELElBQUksQ0FBQ29FLFVBQUwsS0FDQ0gsTUFBTSxLQUFLLFFBQVgsSUFBdUJBLE1BQU0sS0FBSyxRQUFsQyxJQUE4Q0EsTUFBTSxLQUFLLFFBRDFELENBREYsRUFHRTtBQUNBLFVBQU1WLEtBQUssR0FBSSxvREFBbURVLE1BQU8sYUFBekU7QUFDQSxVQUFNLElBQUluRixLQUFLLENBQUNnQyxLQUFWLENBQWdCaEMsS0FBSyxDQUFDZ0MsS0FBTixDQUFZb0QsbUJBQTVCLEVBQWlEWCxLQUFqRCxDQUFOO0FBQ0Q7QUFDRjs7QUFFRGMsTUFBTSxDQUFDQyxPQUFQLEdBQWlCO0FBQ2ZiLEVBQUFBLE1BRGU7QUFFZjVDLEVBQUFBLEdBRmU7QUFHZmQsRUFBQUEsSUFIZTtBQUlmWSxFQUFBQSxHQUplO0FBS2ZpRCxFQUFBQTtBQUxlLENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhpcyBmaWxlIGNvbnRhaW5zIGhlbHBlcnMgZm9yIHJ1bm5pbmcgb3BlcmF0aW9ucyBpbiBSRVNUIGZvcm1hdC5cbi8vIFRoZSBnb2FsIGlzIHRoYXQgaGFuZGxlcnMgdGhhdCBleHBsaWNpdGx5IGhhbmRsZSBhbiBleHByZXNzIHJvdXRlXG4vLyBzaG91bGQganVzdCBiZSBzaGFsbG93IHdyYXBwZXJzIGFyb3VuZCB0aGluZ3MgaW4gdGhpcyBmaWxlLCBidXRcbi8vIHRoZXNlIGZ1bmN0aW9ucyBzaG91bGQgbm90IGV4cGxpY2l0bHkgZGVwZW5kIG9uIHRoZSByZXF1ZXN0XG4vLyBvYmplY3QuXG4vLyBUaGlzIG1lYW5zIHRoYXQgb25lIG9mIHRoZXNlIGhhbmRsZXJzIGNhbiBzdXBwb3J0IG11bHRpcGxlXG4vLyByb3V0ZXMuIFRoYXQncyB1c2VmdWwgZm9yIHRoZSByb3V0ZXMgdGhhdCBkbyByZWFsbHkgc2ltaWxhclxuLy8gdGhpbmdzLlxuXG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbnZhciBSZXN0UXVlcnkgPSByZXF1aXJlKCcuL1Jlc3RRdWVyeScpO1xudmFyIFJlc3RXcml0ZSA9IHJlcXVpcmUoJy4vUmVzdFdyaXRlJyk7XG52YXIgdHJpZ2dlcnMgPSByZXF1aXJlKCcuL3RyaWdnZXJzJyk7XG5cbmZ1bmN0aW9uIGNoZWNrVHJpZ2dlcnMoY2xhc3NOYW1lLCBjb25maWcsIHR5cGVzKSB7XG4gIHJldHVybiB0eXBlcy5zb21lKHRyaWdnZXJUeXBlID0+IHtcbiAgICByZXR1cm4gdHJpZ2dlcnMuZ2V0VHJpZ2dlcihcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHRyaWdnZXJzLlR5cGVzW3RyaWdnZXJUeXBlXSxcbiAgICAgIGNvbmZpZy5hcHBsaWNhdGlvbklkXG4gICAgKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrTGl2ZVF1ZXJ5KGNsYXNzTmFtZSwgY29uZmlnKSB7XG4gIHJldHVybiAoXG4gICAgY29uZmlnLmxpdmVRdWVyeUNvbnRyb2xsZXIgJiZcbiAgICBjb25maWcubGl2ZVF1ZXJ5Q29udHJvbGxlci5oYXNMaXZlUXVlcnkoY2xhc3NOYW1lKVxuICApO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYW4gb2JqZWN0IHdpdGggb3B0aW9uYWwga2V5cyAncmVzdWx0cycgYW5kICdjb3VudCcuXG5mdW5jdGlvbiBmaW5kKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUsIHJlc3RPcHRpb25zLCBjbGllbnRTREspIHtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZmluZCcsIGNsYXNzTmFtZSwgYXV0aCk7XG4gIHJldHVybiB0cmlnZ2Vyc1xuICAgIC5tYXliZVJ1blF1ZXJ5VHJpZ2dlcihcbiAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZUZpbmQsXG4gICAgICBjbGFzc05hbWUsXG4gICAgICByZXN0V2hlcmUsXG4gICAgICByZXN0T3B0aW9ucyxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGF1dGhcbiAgICApXG4gICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHJlc3RXaGVyZSA9IHJlc3VsdC5yZXN0V2hlcmUgfHwgcmVzdFdoZXJlO1xuICAgICAgcmVzdE9wdGlvbnMgPSByZXN1bHQucmVzdE9wdGlvbnMgfHwgcmVzdE9wdGlvbnM7XG4gICAgICBjb25zdCBxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICByZXN0V2hlcmUsXG4gICAgICAgIHJlc3RPcHRpb25zLFxuICAgICAgICBjbGllbnRTREtcbiAgICAgICk7XG4gICAgICByZXR1cm4gcXVlcnkuZXhlY3V0ZSgpO1xuICAgIH0pO1xufVxuXG4vLyBnZXQgaXMganVzdCBsaWtlIGZpbmQgYnV0IG9ubHkgcXVlcmllcyBhbiBvYmplY3RJZC5cbmNvbnN0IGdldCA9IChjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgb2JqZWN0SWQsIHJlc3RPcHRpb25zLCBjbGllbnRTREspID0+IHtcbiAgdmFyIHJlc3RXaGVyZSA9IHsgb2JqZWN0SWQgfTtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZ2V0JywgY2xhc3NOYW1lLCBhdXRoKTtcbiAgcmV0dXJuIHRyaWdnZXJzXG4gICAgLm1heWJlUnVuUXVlcnlUcmlnZ2VyKFxuICAgICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlRmluZCxcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHJlc3RXaGVyZSxcbiAgICAgIHJlc3RPcHRpb25zLFxuICAgICAgY29uZmlnLFxuICAgICAgYXV0aCxcbiAgICAgIHRydWVcbiAgICApXG4gICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHJlc3RXaGVyZSA9IHJlc3VsdC5yZXN0V2hlcmUgfHwgcmVzdFdoZXJlO1xuICAgICAgcmVzdE9wdGlvbnMgPSByZXN1bHQucmVzdE9wdGlvbnMgfHwgcmVzdE9wdGlvbnM7XG4gICAgICBjb25zdCBxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICByZXN0V2hlcmUsXG4gICAgICAgIHJlc3RPcHRpb25zLFxuICAgICAgICBjbGllbnRTREtcbiAgICAgICk7XG4gICAgICByZXR1cm4gcXVlcnkuZXhlY3V0ZSgpO1xuICAgIH0pO1xufTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBkb2Vzbid0IHJlc29sdmUgdG8gYW55IHVzZWZ1bCB2YWx1ZS5cbmZ1bmN0aW9uIGRlbChjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgb2JqZWN0SWQpIHtcbiAgaWYgKHR5cGVvZiBvYmplY3RJZCAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkIG9iamVjdElkJyk7XG4gIH1cblxuICBpZiAoY2xhc3NOYW1lID09PSAnX1VzZXInICYmIGF1dGguaXNVbmF1dGhlbnRpY2F0ZWQoKSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLlNFU1NJT05fTUlTU0lORyxcbiAgICAgICdJbnN1ZmZpY2llbnQgYXV0aCB0byBkZWxldGUgdXNlcidcbiAgICApO1xuICB9XG5cbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZGVsZXRlJywgY2xhc3NOYW1lLCBhdXRoKTtcblxuICBsZXQgaW5mbGF0ZWRPYmplY3Q7XG4gIGxldCBzY2hlbWFDb250cm9sbGVyO1xuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIGNvbnN0IGhhc1RyaWdnZXJzID0gY2hlY2tUcmlnZ2VycyhjbGFzc05hbWUsIGNvbmZpZywgW1xuICAgICAgICAnYmVmb3JlRGVsZXRlJyxcbiAgICAgICAgJ2FmdGVyRGVsZXRlJyxcbiAgICAgIF0pO1xuICAgICAgY29uc3QgaGFzTGl2ZVF1ZXJ5ID0gY2hlY2tMaXZlUXVlcnkoY2xhc3NOYW1lLCBjb25maWcpO1xuICAgICAgaWYgKGhhc1RyaWdnZXJzIHx8IGhhc0xpdmVRdWVyeSB8fCBjbGFzc05hbWUgPT0gJ19TZXNzaW9uJykge1xuICAgICAgICByZXR1cm4gbmV3IFJlc3RRdWVyeShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgeyBvYmplY3RJZCB9KVxuICAgICAgICAgIC5leGVjdXRlKHsgb3A6ICdkZWxldGUnIH0pXG4gICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLnJlc3VsdHMgJiYgcmVzcG9uc2UucmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgY29uc3QgZmlyc3RSZXN1bHQgPSByZXNwb25zZS5yZXN1bHRzWzBdO1xuICAgICAgICAgICAgICBmaXJzdFJlc3VsdC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgICAgICAgICAgIGlmIChjbGFzc05hbWUgPT09ICdfU2Vzc2lvbicgJiYgIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWF1dGgudXNlciB8fCBmaXJzdFJlc3VsdC51c2VyLm9iamVjdElkICE9PSBhdXRoLnVzZXIuaWQpIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICAgICAgICAgICAnSW52YWxpZCBzZXNzaW9uIHRva2VuJ1xuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdmFyIGNhY2hlQWRhcHRlciA9IGNvbmZpZy5jYWNoZUNvbnRyb2xsZXI7XG4gICAgICAgICAgICAgIGNhY2hlQWRhcHRlci51c2VyLmRlbChmaXJzdFJlc3VsdC5zZXNzaW9uVG9rZW4pO1xuICAgICAgICAgICAgICBpbmZsYXRlZE9iamVjdCA9IFBhcnNlLk9iamVjdC5mcm9tSlNPTihmaXJzdFJlc3VsdCk7XG4gICAgICAgICAgICAgIHJldHVybiB0cmlnZ2Vycy5tYXliZVJ1blRyaWdnZXIoXG4gICAgICAgICAgICAgICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlRGVsZXRlLFxuICAgICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgICAgaW5mbGF0ZWRPYmplY3QsXG4gICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgICBjb25maWdcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICAgJ09iamVjdCBub3QgZm91bmQgZm9yIGRlbGV0ZS4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICBpZiAoIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGF1dGguZ2V0VXNlclJvbGVzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiBjb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSgpKVxuICAgIC50aGVuKHMgPT4ge1xuICAgICAgc2NoZW1hQ29udHJvbGxlciA9IHM7XG4gICAgICBjb25zdCBvcHRpb25zID0ge307XG4gICAgICBpZiAoIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgb3B0aW9ucy5hY2wgPSBbJyonXTtcbiAgICAgICAgaWYgKGF1dGgudXNlcikge1xuICAgICAgICAgIG9wdGlvbnMuYWNsLnB1c2goYXV0aC51c2VyLmlkKTtcbiAgICAgICAgICBvcHRpb25zLmFjbCA9IG9wdGlvbnMuYWNsLmNvbmNhdChhdXRoLnVzZXJSb2xlcyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbmZpZy5kYXRhYmFzZS5kZXN0cm95KFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHtcbiAgICAgICAgICBvYmplY3RJZDogb2JqZWN0SWQsXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICAgIHNjaGVtYUNvbnRyb2xsZXJcbiAgICAgICk7XG4gICAgfSlcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICAvLyBOb3RpZnkgTGl2ZVF1ZXJ5IHNlcnZlciBpZiBwb3NzaWJsZVxuICAgICAgY29uc3QgcGVybXMgPSBzY2hlbWFDb250cm9sbGVyLmdldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWUpO1xuICAgICAgY29uZmlnLmxpdmVRdWVyeUNvbnRyb2xsZXIub25BZnRlckRlbGV0ZShcbiAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICBpbmZsYXRlZE9iamVjdCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgcGVybXNcbiAgICAgICk7XG4gICAgICByZXR1cm4gdHJpZ2dlcnMubWF5YmVSdW5UcmlnZ2VyKFxuICAgICAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckRlbGV0ZSxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgaW5mbGF0ZWRPYmplY3QsXG4gICAgICAgIG51bGwsXG4gICAgICAgIGNvbmZpZ1xuICAgICAgKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVTZXNzaW9uTWlzc2luZ0Vycm9yKGVycm9yLCBjbGFzc05hbWUsIGF1dGgpO1xuICAgIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSB7cmVzcG9uc2UsIHN0YXR1cywgbG9jYXRpb259IG9iamVjdC5cbmZ1bmN0aW9uIGNyZWF0ZShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgcmVzdE9iamVjdCwgY2xpZW50U0RLLCBvcHRpb25zKSB7XG4gIGVuZm9yY2VSb2xlU2VjdXJpdHkoJ2NyZWF0ZScsIGNsYXNzTmFtZSwgYXV0aCk7XG4gIHZhciB3cml0ZSA9IG5ldyBSZXN0V3JpdGUoXG4gICAgY29uZmlnLFxuICAgIGF1dGgsXG4gICAgY2xhc3NOYW1lLFxuICAgIG51bGwsXG4gICAgcmVzdE9iamVjdCxcbiAgICBudWxsLFxuICAgIGNsaWVudFNESyxcbiAgICBvcHRpb25zXG4gICk7XG4gIHJldHVybiB3cml0ZS5leGVjdXRlKCk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgY29udGFpbnMgdGhlIGZpZWxkcyBvZiB0aGUgdXBkYXRlIHRoYXQgdGhlXG4vLyBSRVNUIEFQSSBpcyBzdXBwb3NlZCB0byByZXR1cm4uXG4vLyBVc3VhbGx5LCB0aGlzIGlzIGp1c3QgdXBkYXRlZEF0LlxuZnVuY3Rpb24gdXBkYXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUsIHJlc3RPYmplY3QsIGNsaWVudFNESykge1xuICBlbmZvcmNlUm9sZVNlY3VyaXR5KCd1cGRhdGUnLCBjbGFzc05hbWUsIGF1dGgpO1xuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIGNvbnN0IGhhc1RyaWdnZXJzID0gY2hlY2tUcmlnZ2VycyhjbGFzc05hbWUsIGNvbmZpZywgW1xuICAgICAgICAnYmVmb3JlU2F2ZScsXG4gICAgICAgICdhZnRlclNhdmUnLFxuICAgICAgXSk7XG4gICAgICBjb25zdCBoYXNMaXZlUXVlcnkgPSBjaGVja0xpdmVRdWVyeShjbGFzc05hbWUsIGNvbmZpZyk7XG4gICAgICBpZiAoaGFzVHJpZ2dlcnMgfHwgaGFzTGl2ZVF1ZXJ5KSB7XG4gICAgICAgIC8vIERvIG5vdCB1c2UgZmluZCwgYXMgaXQgcnVucyB0aGUgYmVmb3JlIGZpbmRzXG4gICAgICAgIHJldHVybiBuZXcgUmVzdFF1ZXJ5KFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICByZXN0V2hlcmUsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICBmYWxzZVxuICAgICAgICApLmV4ZWN1dGUoe1xuICAgICAgICAgIG9wOiAndXBkYXRlJyxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgICB9KVxuICAgIC50aGVuKCh7IHJlc3VsdHMgfSkgPT4ge1xuICAgICAgdmFyIG9yaWdpbmFsUmVzdE9iamVjdDtcbiAgICAgIGlmIChyZXN1bHRzICYmIHJlc3VsdHMubGVuZ3RoKSB7XG4gICAgICAgIG9yaWdpbmFsUmVzdE9iamVjdCA9IHJlc3VsdHNbMF07XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IFJlc3RXcml0ZShcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBhdXRoLFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgIHJlc3RXaGVyZSxcbiAgICAgICAgcmVzdE9iamVjdCxcbiAgICAgICAgb3JpZ2luYWxSZXN0T2JqZWN0LFxuICAgICAgICBjbGllbnRTREssXG4gICAgICAgICd1cGRhdGUnXG4gICAgICApLmV4ZWN1dGUoKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVTZXNzaW9uTWlzc2luZ0Vycm9yKGVycm9yLCBjbGFzc05hbWUsIGF1dGgpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTZXNzaW9uTWlzc2luZ0Vycm9yKGVycm9yLCBjbGFzc05hbWUsIGF1dGgpIHtcbiAgLy8gSWYgd2UncmUgdHJ5aW5nIHRvIHVwZGF0ZSBhIHVzZXIgd2l0aG91dCAvIHdpdGggYmFkIHNlc3Npb24gdG9rZW5cbiAgaWYgKFxuICAgIGNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJlxuICAgIGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQgJiZcbiAgICAhYXV0aC5pc01hc3RlclxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuU0VTU0lPTl9NSVNTSU5HLCAnSW5zdWZmaWNpZW50IGF1dGguJyk7XG4gIH1cbiAgdGhyb3cgZXJyb3I7XG59XG5cbmNvbnN0IGNsYXNzZXNXaXRoTWFzdGVyT25seUFjY2VzcyA9IFtcbiAgJ19Kb2JTdGF0dXMnLFxuICAnX1B1c2hTdGF0dXMnLFxuICAnX0hvb2tzJyxcbiAgJ19HbG9iYWxDb25maWcnLFxuICAnX0pvYlNjaGVkdWxlJyxcbl07XG4vLyBEaXNhbGxvd2luZyBhY2Nlc3MgdG8gdGhlIF9Sb2xlIGNvbGxlY3Rpb24gZXhjZXB0IGJ5IG1hc3RlciBrZXlcbmZ1bmN0aW9uIGVuZm9yY2VSb2xlU2VjdXJpdHkobWV0aG9kLCBjbGFzc05hbWUsIGF1dGgpIHtcbiAgaWYgKGNsYXNzTmFtZSA9PT0gJ19JbnN0YWxsYXRpb24nICYmICFhdXRoLmlzTWFzdGVyKSB7XG4gICAgaWYgKG1ldGhvZCA9PT0gJ2RlbGV0ZScgfHwgbWV0aG9kID09PSAnZmluZCcpIHtcbiAgICAgIGNvbnN0IGVycm9yID0gYENsaWVudHMgYXJlbid0IGFsbG93ZWQgdG8gcGVyZm9ybSB0aGUgJHttZXRob2R9IG9wZXJhdGlvbiBvbiB0aGUgaW5zdGFsbGF0aW9uIGNvbGxlY3Rpb24uYDtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCBlcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLy9hbGwgdm9sYXRpbGVDbGFzc2VzIGFyZSBtYXN0ZXJLZXkgb25seVxuICBpZiAoY2xhc3Nlc1dpdGhNYXN0ZXJPbmx5QWNjZXNzLmluZGV4T2YoY2xhc3NOYW1lKSA+PSAwICYmICFhdXRoLmlzTWFzdGVyKSB7XG4gICAgY29uc3QgZXJyb3IgPSBgQ2xpZW50cyBhcmVuJ3QgYWxsb3dlZCB0byBwZXJmb3JtIHRoZSAke21ldGhvZH0gb3BlcmF0aW9uIG9uIHRoZSAke2NsYXNzTmFtZX0gY29sbGVjdGlvbi5gO1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCBlcnJvcik7XG4gIH1cblxuICAvLyByZWFkT25seSBtYXN0ZXJLZXkgaXMgbm90IGFsbG93ZWRcbiAgaWYgKFxuICAgIGF1dGguaXNSZWFkT25seSAmJlxuICAgIChtZXRob2QgPT09ICdkZWxldGUnIHx8IG1ldGhvZCA9PT0gJ2NyZWF0ZScgfHwgbWV0aG9kID09PSAndXBkYXRlJylcbiAgKSB7XG4gICAgY29uc3QgZXJyb3IgPSBgcmVhZC1vbmx5IG1hc3RlcktleSBpc24ndCBhbGxvd2VkIHRvIHBlcmZvcm0gdGhlICR7bWV0aG9kfSBvcGVyYXRpb24uYDtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTiwgZXJyb3IpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBjcmVhdGUsXG4gIGRlbCxcbiAgZmluZCxcbiAgZ2V0LFxuICB1cGRhdGUsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/triggers.js b/lib/triggers.js new file mode 100644 index 0000000000..79f9c9cac6 --- /dev/null +++ b/lib/triggers.js @@ -0,0 +1,622 @@ +"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', + afterLogin: 'afterLogin', + 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 || type === Types.afterLogin) && 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 and afterLogin triggers'; + } + + 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.explain) { + restOptions = restOptions || {}; + restOptions.explain = jsonQuery.explain; + } + + if (jsonQuery.keys) { + restOptions = restOptions || {}; + restOptions.keys = jsonQuery.keys; + } + + if (jsonQuery.order) { + restOptions = restOptions || {}; + restOptions.order = jsonQuery.order; + } + + if (jsonQuery.hint) { + restOptions = restOptions || {}; + restOptions.hint = jsonQuery.hint; + } + + 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 || triggerType === Types.afterLogin) { + 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy90cmlnZ2Vycy5qcyJdLCJuYW1lcyI6WyJUeXBlcyIsImJlZm9yZUxvZ2luIiwiYWZ0ZXJMb2dpbiIsImFmdGVyTG9nb3V0IiwiYmVmb3JlU2F2ZSIsImFmdGVyU2F2ZSIsImJlZm9yZURlbGV0ZSIsImFmdGVyRGVsZXRlIiwiYmVmb3JlRmluZCIsImFmdGVyRmluZCIsImJhc2VTdG9yZSIsIlZhbGlkYXRvcnMiLCJGdW5jdGlvbnMiLCJKb2JzIiwiTGl2ZVF1ZXJ5IiwiVHJpZ2dlcnMiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwiYmFzZSIsImtleSIsImZyZWV6ZSIsInZhbGlkYXRlQ2xhc3NOYW1lRm9yVHJpZ2dlcnMiLCJjbGFzc05hbWUiLCJ0eXBlIiwiX3RyaWdnZXJTdG9yZSIsIkNhdGVnb3J5IiwiZ2V0U3RvcmUiLCJjYXRlZ29yeSIsIm5hbWUiLCJhcHBsaWNhdGlvbklkIiwicGF0aCIsInNwbGl0Iiwic3BsaWNlIiwiUGFyc2UiLCJzdG9yZSIsImNvbXBvbmVudCIsInVuZGVmaW5lZCIsImFkZCIsImhhbmRsZXIiLCJsYXN0Q29tcG9uZW50IiwicmVtb3ZlIiwiZ2V0IiwiYWRkRnVuY3Rpb24iLCJmdW5jdGlvbk5hbWUiLCJ2YWxpZGF0aW9uSGFuZGxlciIsImFkZEpvYiIsImpvYk5hbWUiLCJhZGRUcmlnZ2VyIiwiYWRkTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVyIiwicHVzaCIsInJlbW92ZUZ1bmN0aW9uIiwicmVtb3ZlVHJpZ2dlciIsIl91bnJlZ2lzdGVyQWxsIiwiZm9yRWFjaCIsImFwcElkIiwiZ2V0VHJpZ2dlciIsInRyaWdnZXJUeXBlIiwidHJpZ2dlckV4aXN0cyIsImdldEZ1bmN0aW9uIiwiZ2V0RnVuY3Rpb25OYW1lcyIsImZ1bmN0aW9uTmFtZXMiLCJleHRyYWN0RnVuY3Rpb25OYW1lcyIsIm5hbWVzcGFjZSIsInZhbHVlIiwiZ2V0Sm9iIiwiZ2V0Sm9icyIsIm1hbmFnZXIiLCJnZXRWYWxpZGF0b3IiLCJnZXRSZXF1ZXN0T2JqZWN0IiwiYXV0aCIsInBhcnNlT2JqZWN0Iiwib3JpZ2luYWxQYXJzZU9iamVjdCIsImNvbmZpZyIsImNvbnRleHQiLCJyZXF1ZXN0IiwidHJpZ2dlck5hbWUiLCJvYmplY3QiLCJtYXN0ZXIiLCJsb2ciLCJsb2dnZXJDb250cm9sbGVyIiwiaGVhZGVycyIsImlwIiwib3JpZ2luYWwiLCJhc3NpZ24iLCJpc01hc3RlciIsInVzZXIiLCJpbnN0YWxsYXRpb25JZCIsImdldFJlcXVlc3RRdWVyeU9iamVjdCIsInF1ZXJ5IiwiY291bnQiLCJpc0dldCIsImdldFJlc3BvbnNlT2JqZWN0IiwicmVzb2x2ZSIsInJlamVjdCIsInN1Y2Nlc3MiLCJyZXNwb25zZSIsIm9iamVjdHMiLCJtYXAiLCJ0b0pTT04iLCJlcXVhbHMiLCJfZ2V0U2F2ZUpTT04iLCJlcnJvciIsIkVycm9yIiwiU0NSSVBUX0ZBSUxFRCIsIm1lc3NhZ2UiLCJ1c2VySWRGb3JMb2ciLCJpZCIsImxvZ1RyaWdnZXJBZnRlckhvb2siLCJpbnB1dCIsImNsZWFuSW5wdXQiLCJsb2dnZXIiLCJ0cnVuY2F0ZUxvZ01lc3NhZ2UiLCJKU09OIiwic3RyaW5naWZ5IiwiaW5mbyIsImxvZ1RyaWdnZXJTdWNjZXNzQmVmb3JlSG9vayIsInJlc3VsdCIsImNsZWFuUmVzdWx0IiwibG9nVHJpZ2dlckVycm9yQmVmb3JlSG9vayIsIm1heWJlUnVuQWZ0ZXJGaW5kVHJpZ2dlciIsIlByb21pc2UiLCJ0cmlnZ2VyIiwiZnJvbUpTT04iLCJ0aGVuIiwicmVzdWx0cyIsIm1heWJlUnVuUXVlcnlUcmlnZ2VyIiwicmVzdFdoZXJlIiwicmVzdE9wdGlvbnMiLCJqc29uIiwid2hlcmUiLCJwYXJzZVF1ZXJ5IiwiUXVlcnkiLCJ3aXRoSlNPTiIsInJlcXVlc3RPYmplY3QiLCJxdWVyeVJlc3VsdCIsImpzb25RdWVyeSIsImxpbWl0Iiwic2tpcCIsImluY2x1ZGUiLCJleGNsdWRlS2V5cyIsImV4cGxhaW4iLCJvcmRlciIsImhpbnQiLCJyZWFkUHJlZmVyZW5jZSIsImluY2x1ZGVSZWFkUHJlZmVyZW5jZSIsInN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UiLCJlcnIiLCJtYXliZVJ1blRyaWdnZXIiLCJwcm9taXNlIiwiaW5mbGF0ZSIsImRhdGEiLCJyZXN0T2JqZWN0IiwiY29weSIsInJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0E7O0FBQ0E7Ozs7QUFGQTtBQUlPLE1BQU1BLEtBQUssR0FBRztBQUNuQkMsRUFBQUEsV0FBVyxFQUFFLGFBRE07QUFFbkJDLEVBQUFBLFVBQVUsRUFBRSxZQUZPO0FBR25CQyxFQUFBQSxXQUFXLEVBQUUsYUFITTtBQUluQkMsRUFBQUEsVUFBVSxFQUFFLFlBSk87QUFLbkJDLEVBQUFBLFNBQVMsRUFBRSxXQUxRO0FBTW5CQyxFQUFBQSxZQUFZLEVBQUUsY0FOSztBQU9uQkMsRUFBQUEsV0FBVyxFQUFFLGFBUE07QUFRbkJDLEVBQUFBLFVBQVUsRUFBRSxZQVJPO0FBU25CQyxFQUFBQSxTQUFTLEVBQUU7QUFUUSxDQUFkOzs7QUFZUCxNQUFNQyxTQUFTLEdBQUcsWUFBVztBQUMzQixRQUFNQyxVQUFVLEdBQUcsRUFBbkI7QUFDQSxRQUFNQyxTQUFTLEdBQUcsRUFBbEI7QUFDQSxRQUFNQyxJQUFJLEdBQUcsRUFBYjtBQUNBLFFBQU1DLFNBQVMsR0FBRyxFQUFsQjtBQUNBLFFBQU1DLFFBQVEsR0FBR0MsTUFBTSxDQUFDQyxJQUFQLENBQVlqQixLQUFaLEVBQW1Ca0IsTUFBbkIsQ0FBMEIsVUFBU0MsSUFBVCxFQUFlQyxHQUFmLEVBQW9CO0FBQzdERCxJQUFBQSxJQUFJLENBQUNDLEdBQUQsQ0FBSixHQUFZLEVBQVo7QUFDQSxXQUFPRCxJQUFQO0FBQ0QsR0FIZ0IsRUFHZCxFQUhjLENBQWpCO0FBS0EsU0FBT0gsTUFBTSxDQUFDSyxNQUFQLENBQWM7QUFDbkJULElBQUFBLFNBRG1CO0FBRW5CQyxJQUFBQSxJQUZtQjtBQUduQkYsSUFBQUEsVUFIbUI7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RCxDQUFiLENBQTZCaEIsU0FBN0IsQ0FBdUN3QyxPQUF2QyxDQUErQ2YsT0FBTyxJQUFJQSxPQUFPLENBQUNnSCxJQUFELENBQWpFO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0cmlnZ2Vycy5qc1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuXG5leHBvcnQgY29uc3QgVHlwZXMgPSB7XG4gIGJlZm9yZUxvZ2luOiAnYmVmb3JlTG9naW4nLFxuICBhZnRlckxvZ2luOiAnYWZ0ZXJMb2dpbicsXG4gIGFmdGVyTG9nb3V0OiAnYWZ0ZXJMb2dvdXQnLFxuICBiZWZvcmVTYXZlOiAnYmVmb3JlU2F2ZScsXG4gIGFmdGVyU2F2ZTogJ2FmdGVyU2F2ZScsXG4gIGJlZm9yZURlbGV0ZTogJ2JlZm9yZURlbGV0ZScsXG4gIGFmdGVyRGVsZXRlOiAnYWZ0ZXJEZWxldGUnLFxuICBiZWZvcmVGaW5kOiAnYmVmb3JlRmluZCcsXG4gIGFmdGVyRmluZDogJ2FmdGVyRmluZCcsXG59O1xuXG5jb25zdCBiYXNlU3RvcmUgPSBmdW5jdGlvbigpIHtcbiAgY29uc3QgVmFsaWRhdG9ycyA9IHt9O1xuICBjb25zdCBGdW5jdGlvbnMgPSB7fTtcbiAgY29uc3QgSm9icyA9IHt9O1xuICBjb25zdCBMaXZlUXVlcnkgPSBbXTtcbiAgY29uc3QgVHJpZ2dlcnMgPSBPYmplY3Qua2V5cyhUeXBlcykucmVkdWNlKGZ1bmN0aW9uKGJhc2UsIGtleSkge1xuICAgIGJhc2Vba2V5XSA9IHt9O1xuICAgIHJldHVybiBiYXNlO1xuICB9LCB7fSk7XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoe1xuICAgIEZ1bmN0aW9ucyxcbiAgICBKb2JzLFxuICAgIFZhbGlkYXRvcnMsXG4gICAgVHJpZ2dlcnMsXG4gICAgTGl2ZVF1ZXJ5LFxuICB9KTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQ2xhc3NOYW1lRm9yVHJpZ2dlcnMoY2xhc3NOYW1lLCB0eXBlKSB7XG4gIGlmICh0eXBlID09IFR5cGVzLmJlZm9yZVNhdmUgJiYgY2xhc3NOYW1lID09PSAnX1B1c2hTdGF0dXMnKSB7XG4gICAgLy8gX1B1c2hTdGF0dXMgdXNlcyB1bmRvY3VtZW50ZWQgbmVzdGVkIGtleSBpbmNyZW1lbnQgb3BzXG4gICAgLy8gYWxsb3dpbmcgYmVmb3JlU2F2ZSB3b3VsZCBtZXNzIHVwIHRoZSBvYmplY3RzIGJpZyB0aW1lXG4gICAgLy8gVE9ETzogQWxsb3cgcHJvcGVyIGRvY3VtZW50ZWQgd2F5IG9mIHVzaW5nIG5lc3RlZCBpbmNyZW1lbnQgb3BzXG4gICAgdGhyb3cgJ09ubHkgYWZ0ZXJTYXZlIGlzIGFsbG93ZWQgb24gX1B1c2hTdGF0dXMnO1xuICB9XG4gIGlmIChcbiAgICAodHlwZSA9PT0gVHlwZXMuYmVmb3JlTG9naW4gfHwgdHlwZSA9PT0gVHlwZXMuYWZ0ZXJMb2dpbikgJiZcbiAgICBjbGFzc05hbWUgIT09ICdfVXNlcidcbiAgKSB7XG4gICAgLy8gVE9ETzogY2hlY2sgaWYgdXBzdHJlYW0gY29kZSB3aWxsIGhhbmRsZSBgRXJyb3JgIGluc3RhbmNlIHJhdGhlclxuICAgIC8vIHRoYW4gdGhpcyBhbnRpLXBhdHRlcm4gb2YgdGhyb3dpbmcgc3RyaW5nc1xuICAgIHRocm93ICdPbmx5IHRoZSBfVXNlciBjbGFzcyBpcyBhbGxvd2VkIGZvciB0aGUgYmVmb3JlTG9naW4gYW5kIGFmdGVyTG9naW4gdHJpZ2dlcnMnO1xuICB9XG4gIGlmICh0eXBlID09PSBUeXBlcy5hZnRlckxvZ291dCAmJiBjbGFzc05hbWUgIT09ICdfU2Vzc2lvbicpIHtcbiAgICAvLyBUT0RPOiBjaGVjayBpZiB1cHN0cmVhbSBjb2RlIHdpbGwgaGFuZGxlIGBFcnJvcmAgaW5zdGFuY2UgcmF0aGVyXG4gICAgLy8gdGhhbiB0aGlzIGFudGktcGF0dGVybiBvZiB0aHJvd2luZyBzdHJpbmdzXG4gICAgdGhyb3cgJ09ubHkgdGhlIF9TZXNzaW9uIGNsYXNzIGlzIGFsbG93ZWQgZm9yIHRoZSBhZnRlckxvZ291dCB0cmlnZ2VyLic7XG4gIH1cbiAgaWYgKGNsYXNzTmFtZSA9PT0gJ19TZXNzaW9uJyAmJiB0eXBlICE9PSBUeXBlcy5hZnRlckxvZ291dCkge1xuICAgIC8vIFRPRE86IGNoZWNrIGlmIHVwc3RyZWFtIGNvZGUgd2lsbCBoYW5kbGUgYEVycm9yYCBpbnN0YW5jZSByYXRoZXJcbiAgICAvLyB0aGFuIHRoaXMgYW50aS1wYXR0ZXJuIG9mIHRocm93aW5nIHN0cmluZ3NcbiAgICB0aHJvdyAnT25seSB0aGUgYWZ0ZXJMb2dvdXQgdHJpZ2dlciBpcyBhbGxvd2VkIGZvciB0aGUgX1Nlc3Npb24gY2xhc3MuJztcbiAgfVxuICByZXR1cm4gY2xhc3NOYW1lO1xufVxuXG5jb25zdCBfdHJpZ2dlclN0b3JlID0ge307XG5cbmNvbnN0IENhdGVnb3J5ID0ge1xuICBGdW5jdGlvbnM6ICdGdW5jdGlvbnMnLFxuICBWYWxpZGF0b3JzOiAnVmFsaWRhdG9ycycsXG4gIEpvYnM6ICdKb2JzJyxcbiAgVHJpZ2dlcnM6ICdUcmlnZ2VycycsXG59O1xuXG5mdW5jdGlvbiBnZXRTdG9yZShjYXRlZ29yeSwgbmFtZSwgYXBwbGljYXRpb25JZCkge1xuICBjb25zdCBwYXRoID0gbmFtZS5zcGxpdCgnLicpO1xuICBwYXRoLnNwbGljZSgtMSk7IC8vIHJlbW92ZSBsYXN0IGNvbXBvbmVudFxuICBhcHBsaWNhdGlvbklkID0gYXBwbGljYXRpb25JZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdID0gX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXSB8fCBiYXNlU3RvcmUoKTtcbiAgbGV0IHN0b3JlID0gX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXVtjYXRlZ29yeV07XG4gIGZvciAoY29uc3QgY29tcG9uZW50IG9mIHBhdGgpIHtcbiAgICBzdG9yZSA9IHN0b3JlW2NvbXBvbmVudF07XG4gICAgaWYgKCFzdG9yZSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN0b3JlO1xufVxuXG5mdW5jdGlvbiBhZGQoY2F0ZWdvcnksIG5hbWUsIGhhbmRsZXIsIGFwcGxpY2F0aW9uSWQpIHtcbiAgY29uc3QgbGFzdENvbXBvbmVudCA9IG5hbWUuc3BsaXQoJy4nKS5zcGxpY2UoLTEpO1xuICBjb25zdCBzdG9yZSA9IGdldFN0b3JlKGNhdGVnb3J5LCBuYW1lLCBhcHBsaWNhdGlvbklkKTtcbiAgc3RvcmVbbGFzdENvbXBvbmVudF0gPSBoYW5kbGVyO1xufVxuXG5mdW5jdGlvbiByZW1vdmUoY2F0ZWdvcnksIG5hbWUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgY29uc3QgbGFzdENvbXBvbmVudCA9IG5hbWUuc3BsaXQoJy4nKS5zcGxpY2UoLTEpO1xuICBjb25zdCBzdG9yZSA9IGdldFN0b3JlKGNhdGVnb3J5LCBuYW1lLCBhcHBsaWNhdGlvbklkKTtcbiAgZGVsZXRlIHN0b3JlW2xhc3RDb21wb25lbnRdO1xufVxuXG5mdW5jdGlvbiBnZXQoY2F0ZWdvcnksIG5hbWUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgY29uc3QgbGFzdENvbXBvbmVudCA9IG5hbWUuc3BsaXQoJy4nKS5zcGxpY2UoLTEpO1xuICBjb25zdCBzdG9yZSA9IGdldFN0b3JlKGNhdGVnb3J5LCBuYW1lLCBhcHBsaWNhdGlvbklkKTtcbiAgcmV0dXJuIHN0b3JlW2xhc3RDb21wb25lbnRdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWRkRnVuY3Rpb24oXG4gIGZ1bmN0aW9uTmFtZSxcbiAgaGFuZGxlcixcbiAgdmFsaWRhdGlvbkhhbmRsZXIsXG4gIGFwcGxpY2F0aW9uSWRcbikge1xuICBhZGQoQ2F0ZWdvcnkuRnVuY3Rpb25zLCBmdW5jdGlvbk5hbWUsIGhhbmRsZXIsIGFwcGxpY2F0aW9uSWQpO1xuICBhZGQoQ2F0ZWdvcnkuVmFsaWRhdG9ycywgZnVuY3Rpb25OYW1lLCB2YWxpZGF0aW9uSGFuZGxlciwgYXBwbGljYXRpb25JZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRKb2Ioam9iTmFtZSwgaGFuZGxlciwgYXBwbGljYXRpb25JZCkge1xuICBhZGQoQ2F0ZWdvcnkuSm9icywgam9iTmFtZSwgaGFuZGxlciwgYXBwbGljYXRpb25JZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRUcmlnZ2VyKHR5cGUsIGNsYXNzTmFtZSwgaGFuZGxlciwgYXBwbGljYXRpb25JZCkge1xuICB2YWxpZGF0ZUNsYXNzTmFtZUZvclRyaWdnZXJzKGNsYXNzTmFtZSwgdHlwZSk7XG4gIGFkZChDYXRlZ29yeS5UcmlnZ2VycywgYCR7dHlwZX0uJHtjbGFzc05hbWV9YCwgaGFuZGxlciwgYXBwbGljYXRpb25JZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRMaXZlUXVlcnlFdmVudEhhbmRsZXIoaGFuZGxlciwgYXBwbGljYXRpb25JZCkge1xuICBhcHBsaWNhdGlvbklkID0gYXBwbGljYXRpb25JZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdID0gX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXSB8fCBiYXNlU3RvcmUoKTtcbiAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXS5MaXZlUXVlcnkucHVzaChoYW5kbGVyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgYXBwbGljYXRpb25JZCkge1xuICByZW1vdmUoQ2F0ZWdvcnkuRnVuY3Rpb25zLCBmdW5jdGlvbk5hbWUsIGFwcGxpY2F0aW9uSWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlVHJpZ2dlcih0eXBlLCBjbGFzc05hbWUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgcmVtb3ZlKENhdGVnb3J5LlRyaWdnZXJzLCBgJHt0eXBlfS4ke2NsYXNzTmFtZX1gLCBhcHBsaWNhdGlvbklkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF91bnJlZ2lzdGVyQWxsKCkge1xuICBPYmplY3Qua2V5cyhfdHJpZ2dlclN0b3JlKS5mb3JFYWNoKGFwcElkID0+IGRlbGV0ZSBfdHJpZ2dlclN0b3JlW2FwcElkXSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUcmlnZ2VyKGNsYXNzTmFtZSwgdHJpZ2dlclR5cGUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgaWYgKCFhcHBsaWNhdGlvbklkKSB7XG4gICAgdGhyb3cgJ01pc3NpbmcgQXBwbGljYXRpb25JRCc7XG4gIH1cbiAgcmV0dXJuIGdldChDYXRlZ29yeS5UcmlnZ2VycywgYCR7dHJpZ2dlclR5cGV9LiR7Y2xhc3NOYW1lfWAsIGFwcGxpY2F0aW9uSWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJpZ2dlckV4aXN0cyhcbiAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gIHR5cGU6IHN0cmluZyxcbiAgYXBwbGljYXRpb25JZDogc3RyaW5nXG4pOiBib29sZWFuIHtcbiAgcmV0dXJuIGdldFRyaWdnZXIoY2xhc3NOYW1lLCB0eXBlLCBhcHBsaWNhdGlvbklkKSAhPSB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGdW5jdGlvbihmdW5jdGlvbk5hbWUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgcmV0dXJuIGdldChDYXRlZ29yeS5GdW5jdGlvbnMsIGZ1bmN0aW9uTmFtZSwgYXBwbGljYXRpb25JZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGdW5jdGlvbk5hbWVzKGFwcGxpY2F0aW9uSWQpIHtcbiAgY29uc3Qgc3RvcmUgPVxuICAgIChfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdICYmXG4gICAgICBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdW0NhdGVnb3J5LkZ1bmN0aW9uc10pIHx8XG4gICAge307XG4gIGNvbnN0IGZ1bmN0aW9uTmFtZXMgPSBbXTtcbiAgY29uc3QgZXh0cmFjdEZ1bmN0aW9uTmFtZXMgPSAobmFtZXNwYWNlLCBzdG9yZSkgPT4ge1xuICAgIE9iamVjdC5rZXlzKHN0b3JlKS5mb3JFYWNoKG5hbWUgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSBzdG9yZVtuYW1lXTtcbiAgICAgIGlmIChuYW1lc3BhY2UpIHtcbiAgICAgICAgbmFtZSA9IGAke25hbWVzcGFjZX0uJHtuYW1lfWA7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGZ1bmN0aW9uTmFtZXMucHVzaChuYW1lKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4dHJhY3RGdW5jdGlvbk5hbWVzKG5hbWUsIHZhbHVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbiAgZXh0cmFjdEZ1bmN0aW9uTmFtZXMobnVsbCwgc3RvcmUpO1xuICByZXR1cm4gZnVuY3Rpb25OYW1lcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEpvYihqb2JOYW1lLCBhcHBsaWNhdGlvbklkKSB7XG4gIHJldHVybiBnZXQoQ2F0ZWdvcnkuSm9icywgam9iTmFtZSwgYXBwbGljYXRpb25JZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRKb2JzKGFwcGxpY2F0aW9uSWQpIHtcbiAgdmFyIG1hbmFnZXIgPSBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdO1xuICBpZiAobWFuYWdlciAmJiBtYW5hZ2VyLkpvYnMpIHtcbiAgICByZXR1cm4gbWFuYWdlci5Kb2JzO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWYWxpZGF0b3IoZnVuY3Rpb25OYW1lLCBhcHBsaWNhdGlvbklkKSB7XG4gIHJldHVybiBnZXQoQ2F0ZWdvcnkuVmFsaWRhdG9ycywgZnVuY3Rpb25OYW1lLCBhcHBsaWNhdGlvbklkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFJlcXVlc3RPYmplY3QoXG4gIHRyaWdnZXJUeXBlLFxuICBhdXRoLFxuICBwYXJzZU9iamVjdCxcbiAgb3JpZ2luYWxQYXJzZU9iamVjdCxcbiAgY29uZmlnLFxuICBjb250ZXh0XG4pIHtcbiAgY29uc3QgcmVxdWVzdCA9IHtcbiAgICB0cmlnZ2VyTmFtZTogdHJpZ2dlclR5cGUsXG4gICAgb2JqZWN0OiBwYXJzZU9iamVjdCxcbiAgICBtYXN0ZXI6IGZhbHNlLFxuICAgIGxvZzogY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIsXG4gICAgaGVhZGVyczogY29uZmlnLmhlYWRlcnMsXG4gICAgaXA6IGNvbmZpZy5pcCxcbiAgfTtcblxuICBpZiAob3JpZ2luYWxQYXJzZU9iamVjdCkge1xuICAgIHJlcXVlc3Qub3JpZ2luYWwgPSBvcmlnaW5hbFBhcnNlT2JqZWN0O1xuICB9XG5cbiAgaWYgKHRyaWdnZXJUeXBlID09PSBUeXBlcy5iZWZvcmVTYXZlIHx8IHRyaWdnZXJUeXBlID09PSBUeXBlcy5hZnRlclNhdmUpIHtcbiAgICAvLyBTZXQgYSBjb3B5IG9mIHRoZSBjb250ZXh0IG9uIHRoZSByZXF1ZXN0IG9iamVjdC5cbiAgICByZXF1ZXN0LmNvbnRleHQgPSBPYmplY3QuYXNzaWduKHt9LCBjb250ZXh0KTtcbiAgfVxuXG4gIGlmICghYXV0aCkge1xuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG4gIGlmIChhdXRoLmlzTWFzdGVyKSB7XG4gICAgcmVxdWVzdFsnbWFzdGVyJ10gPSB0cnVlO1xuICB9XG4gIGlmIChhdXRoLnVzZXIpIHtcbiAgICByZXF1ZXN0Wyd1c2VyJ10gPSBhdXRoLnVzZXI7XG4gIH1cbiAgaWYgKGF1dGguaW5zdGFsbGF0aW9uSWQpIHtcbiAgICByZXF1ZXN0WydpbnN0YWxsYXRpb25JZCddID0gYXV0aC5pbnN0YWxsYXRpb25JZDtcbiAgfVxuICByZXR1cm4gcmVxdWVzdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFJlcXVlc3RRdWVyeU9iamVjdChcbiAgdHJpZ2dlclR5cGUsXG4gIGF1dGgsXG4gIHF1ZXJ5LFxuICBjb3VudCxcbiAgY29uZmlnLFxuICBpc0dldFxuKSB7XG4gIGlzR2V0ID0gISFpc0dldDtcblxuICB2YXIgcmVxdWVzdCA9IHtcbiAgICB0cmlnZ2VyTmFtZTogdHJpZ2dlclR5cGUsXG4gICAgcXVlcnksXG4gICAgbWFzdGVyOiBmYWxzZSxcbiAgICBjb3VudCxcbiAgICBsb2c6IGNvbmZpZy5sb2dnZXJDb250cm9sbGVyLFxuICAgIGlzR2V0LFxuICAgIGhlYWRlcnM6IGNvbmZpZy5oZWFkZXJzLFxuICAgIGlwOiBjb25maWcuaXAsXG4gIH07XG5cbiAgaWYgKCFhdXRoKSB7XG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cbiAgaWYgKGF1dGguaXNNYXN0ZXIpIHtcbiAgICByZXF1ZXN0WydtYXN0ZXInXSA9IHRydWU7XG4gIH1cbiAgaWYgKGF1dGgudXNlcikge1xuICAgIHJlcXVlc3RbJ3VzZXInXSA9IGF1dGgudXNlcjtcbiAgfVxuICBpZiAoYXV0aC5pbnN0YWxsYXRpb25JZCkge1xuICAgIHJlcXVlc3RbJ2luc3RhbGxhdGlvbklkJ10gPSBhdXRoLmluc3RhbGxhdGlvbklkO1xuICB9XG4gIHJldHVybiByZXF1ZXN0O1xufVxuXG4vLyBDcmVhdGVzIHRoZSByZXNwb25zZSBvYmplY3QsIGFuZCB1c2VzIHRoZSByZXF1ZXN0IG9iamVjdCB0byBwYXNzIGRhdGFcbi8vIFRoZSBBUEkgd2lsbCBjYWxsIHRoaXMgd2l0aCBSRVNUIEFQSSBmb3JtYXR0ZWQgb2JqZWN0cywgdGhpcyB3aWxsXG4vLyB0cmFuc2Zvcm0gdGhlbSB0byBQYXJzZS5PYmplY3QgaW5zdGFuY2VzIGV4cGVjdGVkIGJ5IENsb3VkIENvZGUuXG4vLyBBbnkgY2hhbmdlcyBtYWRlIHRvIHRoZSBvYmplY3QgaW4gYSBiZWZvcmVTYXZlIHdpbGwgYmUgaW5jbHVkZWQuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVzcG9uc2VPYmplY3QocmVxdWVzdCwgcmVzb2x2ZSwgcmVqZWN0KSB7XG4gIHJldHVybiB7XG4gICAgc3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgIGlmIChyZXF1ZXN0LnRyaWdnZXJOYW1lID09PSBUeXBlcy5hZnRlckZpbmQpIHtcbiAgICAgICAgaWYgKCFyZXNwb25zZSkge1xuICAgICAgICAgIHJlc3BvbnNlID0gcmVxdWVzdC5vYmplY3RzO1xuICAgICAgICB9XG4gICAgICAgIHJlc3BvbnNlID0gcmVzcG9uc2UubWFwKG9iamVjdCA9PiB7XG4gICAgICAgICAgcmV0dXJuIG9iamVjdC50b0pTT04oKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXNvbHZlKHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgSlNPTiByZXNwb25zZVxuICAgICAgaWYgKFxuICAgICAgICByZXNwb25zZSAmJlxuICAgICAgICB0eXBlb2YgcmVzcG9uc2UgPT09ICdvYmplY3QnICYmXG4gICAgICAgICFyZXF1ZXN0Lm9iamVjdC5lcXVhbHMocmVzcG9uc2UpICYmXG4gICAgICAgIHJlcXVlc3QudHJpZ2dlck5hbWUgPT09IFR5cGVzLmJlZm9yZVNhdmVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXNwb25zZSk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIHJlc3BvbnNlICYmXG4gICAgICAgIHR5cGVvZiByZXNwb25zZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgcmVxdWVzdC50cmlnZ2VyTmFtZSA9PT0gVHlwZXMuYWZ0ZXJTYXZlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgaWYgKHJlcXVlc3QudHJpZ2dlck5hbWUgPT09IFR5cGVzLmFmdGVyU2F2ZSkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgfVxuICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgIGlmIChyZXF1ZXN0LnRyaWdnZXJOYW1lID09PSBUeXBlcy5iZWZvcmVTYXZlKSB7XG4gICAgICAgIHJlc3BvbnNlWydvYmplY3QnXSA9IHJlcXVlc3Qub2JqZWN0Ll9nZXRTYXZlSlNPTigpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc29sdmUocmVzcG9uc2UpO1xuICAgIH0sXG4gICAgZXJyb3I6IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSBlbHNlIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJlamVjdChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuU0NSSVBUX0ZBSUxFRCwgZXJyb3IubWVzc2FnZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVqZWN0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVELCBlcnJvcikpO1xuICAgICAgfVxuICAgIH0sXG4gIH07XG59XG5cbmZ1bmN0aW9uIHVzZXJJZEZvckxvZyhhdXRoKSB7XG4gIHJldHVybiBhdXRoICYmIGF1dGgudXNlciA/IGF1dGgudXNlci5pZCA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gbG9nVHJpZ2dlckFmdGVySG9vayh0cmlnZ2VyVHlwZSwgY2xhc3NOYW1lLCBpbnB1dCwgYXV0aCkge1xuICBjb25zdCBjbGVhbklucHV0ID0gbG9nZ2VyLnRydW5jYXRlTG9nTWVzc2FnZShKU09OLnN0cmluZ2lmeShpbnB1dCkpO1xuICBsb2dnZXIuaW5mbyhcbiAgICBgJHt0cmlnZ2VyVHlwZX0gdHJpZ2dlcmVkIGZvciAke2NsYXNzTmFtZX0gZm9yIHVzZXIgJHt1c2VySWRGb3JMb2coXG4gICAgICBhdXRoXG4gICAgKX06XFxuICBJbnB1dDogJHtjbGVhbklucHV0fWAsXG4gICAge1xuICAgICAgY2xhc3NOYW1lLFxuICAgICAgdHJpZ2dlclR5cGUsXG4gICAgICB1c2VyOiB1c2VySWRGb3JMb2coYXV0aCksXG4gICAgfVxuICApO1xufVxuXG5mdW5jdGlvbiBsb2dUcmlnZ2VyU3VjY2Vzc0JlZm9yZUhvb2soXG4gIHRyaWdnZXJUeXBlLFxuICBjbGFzc05hbWUsXG4gIGlucHV0LFxuICByZXN1bHQsXG4gIGF1dGhcbikge1xuICBjb25zdCBjbGVhbklucHV0ID0gbG9nZ2VyLnRydW5jYXRlTG9nTWVzc2FnZShKU09OLnN0cmluZ2lmeShpbnB1dCkpO1xuICBjb25zdCBjbGVhblJlc3VsdCA9IGxvZ2dlci50cnVuY2F0ZUxvZ01lc3NhZ2UoSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gIGxvZ2dlci5pbmZvKFxuICAgIGAke3RyaWdnZXJUeXBlfSB0cmlnZ2VyZWQgZm9yICR7Y2xhc3NOYW1lfSBmb3IgdXNlciAke3VzZXJJZEZvckxvZyhcbiAgICAgIGF1dGhcbiAgICApfTpcXG4gIElucHV0OiAke2NsZWFuSW5wdXR9XFxuICBSZXN1bHQ6ICR7Y2xlYW5SZXN1bHR9YCxcbiAgICB7XG4gICAgICBjbGFzc05hbWUsXG4gICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgIHVzZXI6IHVzZXJJZEZvckxvZyhhdXRoKSxcbiAgICB9XG4gICk7XG59XG5cbmZ1bmN0aW9uIGxvZ1RyaWdnZXJFcnJvckJlZm9yZUhvb2sodHJpZ2dlclR5cGUsIGNsYXNzTmFtZSwgaW5wdXQsIGF1dGgsIGVycm9yKSB7XG4gIGNvbnN0IGNsZWFuSW5wdXQgPSBsb2dnZXIudHJ1bmNhdGVMb2dNZXNzYWdlKEpTT04uc3RyaW5naWZ5KGlucHV0KSk7XG4gIGxvZ2dlci5lcnJvcihcbiAgICBgJHt0cmlnZ2VyVHlwZX0gZmFpbGVkIGZvciAke2NsYXNzTmFtZX0gZm9yIHVzZXIgJHt1c2VySWRGb3JMb2coXG4gICAgICBhdXRoXG4gICAgKX06XFxuICBJbnB1dDogJHtjbGVhbklucHV0fVxcbiAgRXJyb3I6ICR7SlNPTi5zdHJpbmdpZnkoZXJyb3IpfWAsXG4gICAge1xuICAgICAgY2xhc3NOYW1lLFxuICAgICAgdHJpZ2dlclR5cGUsXG4gICAgICBlcnJvcixcbiAgICAgIHVzZXI6IHVzZXJJZEZvckxvZyhhdXRoKSxcbiAgICB9XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXliZVJ1bkFmdGVyRmluZFRyaWdnZXIoXG4gIHRyaWdnZXJUeXBlLFxuICBhdXRoLFxuICBjbGFzc05hbWUsXG4gIG9iamVjdHMsXG4gIGNvbmZpZ1xuKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgdHJpZ2dlciA9IGdldFRyaWdnZXIoY2xhc3NOYW1lLCB0cmlnZ2VyVHlwZSwgY29uZmlnLmFwcGxpY2F0aW9uSWQpO1xuICAgIGlmICghdHJpZ2dlcikge1xuICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICB9XG4gICAgY29uc3QgcmVxdWVzdCA9IGdldFJlcXVlc3RPYmplY3QodHJpZ2dlclR5cGUsIGF1dGgsIG51bGwsIG51bGwsIGNvbmZpZyk7XG4gICAgY29uc3QgeyBzdWNjZXNzLCBlcnJvciB9ID0gZ2V0UmVzcG9uc2VPYmplY3QoXG4gICAgICByZXF1ZXN0LFxuICAgICAgb2JqZWN0ID0+IHtcbiAgICAgICAgcmVzb2x2ZShvYmplY3QpO1xuICAgICAgfSxcbiAgICAgIGVycm9yID0+IHtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH1cbiAgICApO1xuICAgIGxvZ1RyaWdnZXJTdWNjZXNzQmVmb3JlSG9vayhcbiAgICAgIHRyaWdnZXJUeXBlLFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgJ0FmdGVyRmluZCcsXG4gICAgICBKU09OLnN0cmluZ2lmeShvYmplY3RzKSxcbiAgICAgIGF1dGhcbiAgICApO1xuICAgIHJlcXVlc3Qub2JqZWN0cyA9IG9iamVjdHMubWFwKG9iamVjdCA9PiB7XG4gICAgICAvL3NldHRpbmcgdGhlIGNsYXNzIG5hbWUgdG8gdHJhbnNmb3JtIGludG8gcGFyc2Ugb2JqZWN0XG4gICAgICBvYmplY3QuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgICAgcmV0dXJuIFBhcnNlLk9iamVjdC5mcm9tSlNPTihvYmplY3QpO1xuICAgIH0pO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IHRyaWdnZXIocmVxdWVzdCk7XG4gICAgICAgIGlmIChyZXNwb25zZSAmJiB0eXBlb2YgcmVzcG9uc2UudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgICAgaWYgKCFyZXN1bHRzKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVELFxuICAgICAgICAgICAgICAgICdBZnRlckZpbmQgZXhwZWN0IHJlc3VsdHMgdG8gYmUgcmV0dXJuZWQgaW4gdGhlIHByb21pc2UnXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICB9KVxuICAgICAgLnRoZW4oc3VjY2VzcywgZXJyb3IpO1xuICB9KS50aGVuKHJlc3VsdHMgPT4ge1xuICAgIGxvZ1RyaWdnZXJBZnRlckhvb2sodHJpZ2dlclR5cGUsIGNsYXNzTmFtZSwgSlNPTi5zdHJpbmdpZnkocmVzdWx0cyksIGF1dGgpO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1heWJlUnVuUXVlcnlUcmlnZ2VyKFxuICB0cmlnZ2VyVHlwZSxcbiAgY2xhc3NOYW1lLFxuICByZXN0V2hlcmUsXG4gIHJlc3RPcHRpb25zLFxuICBjb25maWcsXG4gIGF1dGgsXG4gIGlzR2V0XG4pIHtcbiAgY29uc3QgdHJpZ2dlciA9IGdldFRyaWdnZXIoY2xhc3NOYW1lLCB0cmlnZ2VyVHlwZSwgY29uZmlnLmFwcGxpY2F0aW9uSWQpO1xuICBpZiAoIXRyaWdnZXIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgIHJlc3RXaGVyZSxcbiAgICAgIHJlc3RPcHRpb25zLFxuICAgIH0pO1xuICB9XG4gIGNvbnN0IGpzb24gPSBPYmplY3QuYXNzaWduKHt9LCByZXN0T3B0aW9ucyk7XG4gIGpzb24ud2hlcmUgPSByZXN0V2hlcmU7XG5cbiAgY29uc3QgcGFyc2VRdWVyeSA9IG5ldyBQYXJzZS5RdWVyeShjbGFzc05hbWUpO1xuICBwYXJzZVF1ZXJ5LndpdGhKU09OKGpzb24pO1xuXG4gIGxldCBjb3VudCA9IGZhbHNlO1xuICBpZiAocmVzdE9wdGlvbnMpIHtcbiAgICBjb3VudCA9ICEhcmVzdE9wdGlvbnMuY291bnQ7XG4gIH1cbiAgY29uc3QgcmVxdWVzdE9iamVjdCA9IGdldFJlcXVlc3RRdWVyeU9iamVjdChcbiAgICB0cmlnZ2VyVHlwZSxcbiAgICBhdXRoLFxuICAgIHBhcnNlUXVlcnksXG4gICAgY291bnQsXG4gICAgY29uZmlnLFxuICAgIGlzR2V0XG4gICk7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0cmlnZ2VyKHJlcXVlc3RPYmplY3QpO1xuICAgIH0pXG4gICAgLnRoZW4oXG4gICAgICByZXN1bHQgPT4ge1xuICAgICAgICBsZXQgcXVlcnlSZXN1bHQgPSBwYXJzZVF1ZXJ5O1xuICAgICAgICBpZiAocmVzdWx0ICYmIHJlc3VsdCBpbnN0YW5jZW9mIFBhcnNlLlF1ZXJ5KSB7XG4gICAgICAgICAgcXVlcnlSZXN1bHQgPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QganNvblF1ZXJ5ID0gcXVlcnlSZXN1bHQudG9KU09OKCk7XG4gICAgICAgIGlmIChqc29uUXVlcnkud2hlcmUpIHtcbiAgICAgICAgICByZXN0V2hlcmUgPSBqc29uUXVlcnkud2hlcmU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5saW1pdCkge1xuICAgICAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICAgICAgcmVzdE9wdGlvbnMubGltaXQgPSBqc29uUXVlcnkubGltaXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5za2lwKSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5za2lwID0ganNvblF1ZXJ5LnNraXA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5pbmNsdWRlKSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5pbmNsdWRlID0ganNvblF1ZXJ5LmluY2x1ZGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5leGNsdWRlS2V5cykge1xuICAgICAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICAgICAgcmVzdE9wdGlvbnMuZXhjbHVkZUtleXMgPSBqc29uUXVlcnkuZXhjbHVkZUtleXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5leHBsYWluKSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5leHBsYWluID0ganNvblF1ZXJ5LmV4cGxhaW47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5rZXlzKSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5rZXlzID0ganNvblF1ZXJ5LmtleXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5vcmRlcikge1xuICAgICAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICAgICAgcmVzdE9wdGlvbnMub3JkZXIgPSBqc29uUXVlcnkub3JkZXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGpzb25RdWVyeS5oaW50KSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5oaW50ID0ganNvblF1ZXJ5LmhpbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlcXVlc3RPYmplY3QucmVhZFByZWZlcmVuY2UpIHtcbiAgICAgICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgICAgIHJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gcmVxdWVzdE9iamVjdC5yZWFkUHJlZmVyZW5jZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVxdWVzdE9iamVjdC5pbmNsdWRlUmVhZFByZWZlcmVuY2UpIHtcbiAgICAgICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgICAgIHJlc3RPcHRpb25zLmluY2x1ZGVSZWFkUHJlZmVyZW5jZSA9XG4gICAgICAgICAgICByZXF1ZXN0T2JqZWN0LmluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVxdWVzdE9iamVjdC5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICByZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID1cbiAgICAgICAgICAgIHJlcXVlc3RPYmplY3Quc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHJlc3RXaGVyZSxcbiAgICAgICAgICByZXN0T3B0aW9ucyxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBlcnIgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIGVyciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMSwgZXJyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICApO1xufVxuXG4vLyBUbyBiZSB1c2VkIGFzIHBhcnQgb2YgdGhlIHByb21pc2UgY2hhaW4gd2hlbiBzYXZpbmcvZGVsZXRpbmcgYW4gb2JqZWN0XG4vLyBXaWxsIHJlc29sdmUgc3VjY2Vzc2Z1bGx5IGlmIG5vIHRyaWdnZXIgaXMgY29uZmlndXJlZFxuLy8gUmVzb2x2ZXMgdG8gYW4gb2JqZWN0LCBlbXB0eSBvciBjb250YWluaW5nIGFuIG9iamVjdCBrZXkuIEEgYmVmb3JlU2F2ZVxuLy8gdHJpZ2dlciB3aWxsIHNldCB0aGUgb2JqZWN0IGtleSB0byB0aGUgcmVzdCBmb3JtYXQgb2JqZWN0IHRvIHNhdmUuXG4vLyBvcmlnaW5hbFBhcnNlT2JqZWN0IGlzIG9wdGlvbmFsLCB3ZSBvbmx5IG5lZWQgdGhhdCBmb3IgYmVmb3JlL2FmdGVyU2F2ZSBmdW5jdGlvbnNcbmV4cG9ydCBmdW5jdGlvbiBtYXliZVJ1blRyaWdnZXIoXG4gIHRyaWdnZXJUeXBlLFxuICBhdXRoLFxuICBwYXJzZU9iamVjdCxcbiAgb3JpZ2luYWxQYXJzZU9iamVjdCxcbiAgY29uZmlnLFxuICBjb250ZXh0XG4pIHtcbiAgaWYgKCFwYXJzZU9iamVjdCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICB9XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgdHJpZ2dlciA9IGdldFRyaWdnZXIoXG4gICAgICBwYXJzZU9iamVjdC5jbGFzc05hbWUsXG4gICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgIGNvbmZpZy5hcHBsaWNhdGlvbklkXG4gICAgKTtcbiAgICBpZiAoIXRyaWdnZXIpIHJldHVybiByZXNvbHZlKCk7XG4gICAgdmFyIHJlcXVlc3QgPSBnZXRSZXF1ZXN0T2JqZWN0KFxuICAgICAgdHJpZ2dlclR5cGUsXG4gICAgICBhdXRoLFxuICAgICAgcGFyc2VPYmplY3QsXG4gICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICAgICAgY29uZmlnLFxuICAgICAgY29udGV4dFxuICAgICk7XG4gICAgdmFyIHsgc3VjY2VzcywgZXJyb3IgfSA9IGdldFJlc3BvbnNlT2JqZWN0KFxuICAgICAgcmVxdWVzdCxcbiAgICAgIG9iamVjdCA9PiB7XG4gICAgICAgIGxvZ1RyaWdnZXJTdWNjZXNzQmVmb3JlSG9vayhcbiAgICAgICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgICAgICBwYXJzZU9iamVjdC5jbGFzc05hbWUsXG4gICAgICAgICAgcGFyc2VPYmplY3QudG9KU09OKCksXG4gICAgICAgICAgb2JqZWN0LFxuICAgICAgICAgIGF1dGhcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRyaWdnZXJUeXBlID09PSBUeXBlcy5iZWZvcmVTYXZlIHx8XG4gICAgICAgICAgdHJpZ2dlclR5cGUgPT09IFR5cGVzLmFmdGVyU2F2ZVxuICAgICAgICApIHtcbiAgICAgICAgICBPYmplY3QuYXNzaWduKGNvbnRleHQsIHJlcXVlc3QuY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZShvYmplY3QpO1xuICAgICAgfSxcbiAgICAgIGVycm9yID0+IHtcbiAgICAgICAgbG9nVHJpZ2dlckVycm9yQmVmb3JlSG9vayhcbiAgICAgICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgICAgICBwYXJzZU9iamVjdC5jbGFzc05hbWUsXG4gICAgICAgICAgcGFyc2VPYmplY3QudG9KU09OKCksXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICAvLyBBZnRlclNhdmUgYW5kIGFmdGVyRGVsZXRlIHRyaWdnZXJzIGNhbiByZXR1cm4gYSBwcm9taXNlLCB3aGljaCBpZiB0aGV5XG4gICAgLy8gZG8sIG5lZWRzIHRvIGJlIHJlc29sdmVkIGJlZm9yZSB0aGlzIHByb21pc2UgaXMgcmVzb2x2ZWQsXG4gICAgLy8gc28gdHJpZ2dlciBleGVjdXRpb24gaXMgc3luY2VkIHdpdGggUmVzdFdyaXRlLmV4ZWN1dGUoKSBjYWxsLlxuICAgIC8vIElmIHRyaWdnZXJzIGRvIG5vdCByZXR1cm4gYSBwcm9taXNlLCB0aGV5IGNhbiBydW4gYXN5bmMgY29kZSBwYXJhbGxlbFxuICAgIC8vIHRvIHRoZSBSZXN0V3JpdGUuZXhlY3V0ZSgpIGNhbGwuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSB0cmlnZ2VyKHJlcXVlc3QpO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdHJpZ2dlclR5cGUgPT09IFR5cGVzLmFmdGVyU2F2ZSB8fFxuICAgICAgICAgIHRyaWdnZXJUeXBlID09PSBUeXBlcy5hZnRlckRlbGV0ZSB8fFxuICAgICAgICAgIHRyaWdnZXJUeXBlID09PSBUeXBlcy5hZnRlckxvZ2luXG4gICAgICAgICkge1xuICAgICAgICAgIGxvZ1RyaWdnZXJBZnRlckhvb2soXG4gICAgICAgICAgICB0cmlnZ2VyVHlwZSxcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0LnRvSlNPTigpLFxuICAgICAgICAgICAgYXV0aFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYmVmb3JlU2F2ZSBpcyBleHBlY3RlZCB0byByZXR1cm4gbnVsbCAobm90aGluZylcbiAgICAgICAgaWYgKHRyaWdnZXJUeXBlID09PSBUeXBlcy5iZWZvcmVTYXZlKSB7XG4gICAgICAgICAgaWYgKHByb21pc2UgJiYgdHlwZW9mIHByb21pc2UudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHByb21pc2UudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgIC8vIHJlc3BvbnNlLm9iamVjdCBtYXkgY29tZSBmcm9tIGV4cHJlc3Mgcm91dGluZyBiZWZvcmUgaG9va1xuICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2Uub2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICB9KVxuICAgICAgLnRoZW4oc3VjY2VzcywgZXJyb3IpO1xuICB9KTtcbn1cblxuLy8gQ29udmVydHMgYSBSRVNULWZvcm1hdCBvYmplY3QgdG8gYSBQYXJzZS5PYmplY3Rcbi8vIGRhdGEgaXMgZWl0aGVyIGNsYXNzTmFtZSBvciBhbiBvYmplY3RcbmV4cG9ydCBmdW5jdGlvbiBpbmZsYXRlKGRhdGEsIHJlc3RPYmplY3QpIHtcbiAgdmFyIGNvcHkgPSB0eXBlb2YgZGF0YSA9PSAnb2JqZWN0JyA/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 10e584cb66..803f4b2274 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2750,6 +2750,11 @@ "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, + "adm-zip": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", + "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==" + }, "agent-base": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", @@ -3162,6 +3167,11 @@ "tslib": "^1.10.0" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", @@ -3176,6 +3186,69 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "archiver": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz", + "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==", + "requires": { + "archiver-utils": "^2.1.0", + "async": "^2.6.3", + "buffer-crc32": "^0.2.1", + "glob": "^7.1.4", + "readable-stream": "^3.4.0", + "tar-stream": "^2.1.0", + "zip-stream": "^2.1.2" + }, + "dependencies": { + "bl": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", + "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", + "requires": { + "readable-stream": "^3.0.1" + } + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "tar-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.0.tgz", + "integrity": "sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==", + "requires": { + "bl": "^3.0.0", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -3675,8 +3748,7 @@ "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, "buffer-equal-constant-time": { "version": "1.0.1", @@ -3689,6 +3761,11 @@ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", "dev": true }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -4152,11 +4229,33 @@ "dev": true, "optional": true }, + "compress-commons": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", + "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^3.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^2.3.6" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "config-chain": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", @@ -4299,6 +4398,46 @@ "request": "^2.88.0" } }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + }, + "dependencies": { + "buffer": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } + }, + "crc32-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-3.0.1.tgz", + "integrity": "sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==", + "requires": { + "crc": "^3.4.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "cross-env": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.0.tgz", @@ -4894,7 +5033,6 @@ "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==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -5579,6 +5717,17 @@ "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" + }, + "dependencies": { + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + } } }, "extglob": { @@ -5967,8 +6116,7 @@ "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { "version": "8.1.0", @@ -6814,8 +6962,7 @@ "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 + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, "graceful-readlink": { "version": "1.0.1", @@ -8080,6 +8227,14 @@ "colornames": "^1.1.1" } }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, "lcov-parse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", @@ -8479,14 +8634,12 @@ "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, "lodash.difference": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", - "dev": true + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" }, "lodash.filter": { "version": "4.6.0", @@ -8497,8 +8650,7 @@ "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, "lodash.flattendeep": { "version": "4.4.0", @@ -8612,6 +8764,11 @@ "integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw=", "dev": true }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -9370,6 +9527,62 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multer": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", + "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "dependencies": { + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + } + }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -9580,8 +9793,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "npm-bundled": { "version": "1.1.1", @@ -11759,12 +11971,11 @@ } }, "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", "requires": { - "os-tmpdir": "~1.0.2" + "rimraf": "^2.6.3" } }, "to-buffer": { @@ -11930,6 +12141,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -12516,6 +12732,28 @@ "tslib": "^1.9.3", "zen-observable": "^0.8.0" } + }, + "zip-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", + "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^2.1.1", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } } } } diff --git a/package.json b/package.json index 57d530cac8..f8d39f150c 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,9 @@ "@parse/push-adapter": "3.2.0", "@parse/s3-files-adapter": "1.4.0", "@parse/simple-mailgun-adapter": "1.1.0", + "adm-zip": "^0.4.13", "apollo-server-express": "2.10.1", + "archiver": "^3.0.0", "bcryptjs": "2.4.3", "body-parser": "1.19.0", "commander": "4.1.1", @@ -44,6 +46,7 @@ "lru-cache": "5.1.1", "mime": "2.4.4", "mongodb": "3.5.4", + "multer": "^1.4.1", "node-rsa": "1.0.7", "parse": "2.11.0", "pg-promise": "10.4.4", @@ -51,6 +54,7 @@ "redis": "3.0.0", "semver": "7.1.3", "subscriptions-transport-ws": "0.9.16", + "tmp": "^0.1.0", "tv4": "1.3.0", "uuid": "3.3.3", "winston": "3.2.1", diff --git a/spec/.babelrc b/spec/.babelrc old mode 100644 new mode 100755 diff --git a/spec/.eslintrc.json b/spec/.eslintrc.json old mode 100644 new mode 100755 index 7031e96d6f..b3a0319695 --- a/spec/.eslintrc.json +++ b/spec/.eslintrc.json @@ -17,6 +17,7 @@ "notEqual": true, "it_only_db": true, "it_exclude_dbs": true, + "xit_exclude_dbs": true, "describe_only_db": true, "describe_only": true, "on_db": true, diff --git a/spec/AccountLockoutPolicy.spec.js b/spec/AccountLockoutPolicy.spec.js old mode 100644 new mode 100755 diff --git a/spec/AdaptableController.spec.js b/spec/AdaptableController.spec.js old mode 100644 new mode 100755 diff --git a/spec/AdapterLoader.spec.js b/spec/AdapterLoader.spec.js old mode 100644 new mode 100755 diff --git a/spec/AggregateRouter.spec.js b/spec/AggregateRouter.spec.js old mode 100644 new mode 100755 diff --git a/spec/Analytics.spec.js b/spec/Analytics.spec.js old mode 100644 new mode 100755 diff --git a/spec/AudienceRouter.spec.js b/spec/AudienceRouter.spec.js old mode 100644 new mode 100755 diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js old mode 100644 new mode 100755 diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js old mode 100644 new mode 100755 diff --git a/spec/CLI.spec.js b/spec/CLI.spec.js old mode 100644 new mode 100755 diff --git a/spec/CacheController.spec.js b/spec/CacheController.spec.js old mode 100644 new mode 100755 diff --git a/spec/Client.spec.js b/spec/Client.spec.js old mode 100644 new mode 100755 diff --git a/spec/ClientSDK.spec.js b/spec/ClientSDK.spec.js old mode 100644 new mode 100755 diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js old mode 100644 new mode 100755 diff --git a/spec/CloudCodeLogger.spec.js b/spec/CloudCodeLogger.spec.js old mode 100644 new mode 100755 diff --git a/spec/DatabaseController.spec.js b/spec/DatabaseController.spec.js old mode 100644 new mode 100755 diff --git a/spec/EmailVerificationToken.spec.js b/spec/EmailVerificationToken.spec.js old mode 100644 new mode 100755 diff --git a/spec/EnableExpressErrorHandler.spec.js b/spec/EnableExpressErrorHandler.spec.js old mode 100644 new mode 100755 diff --git a/spec/EnableSingleSchemaCache.spec.js b/spec/EnableSingleSchemaCache.spec.js old mode 100644 new mode 100755 diff --git a/spec/EventEmitterPubSub.spec.js b/spec/EventEmitterPubSub.spec.js old mode 100644 new mode 100755 diff --git a/spec/Export.spec.js b/spec/Export.spec.js new file mode 100644 index 0000000000..0714c08488 --- /dev/null +++ b/spec/Export.spec.js @@ -0,0 +1,122 @@ +const Parse = require('parse/node'); +const request = require('../lib/request'); +const AdmZip = require('adm-zip'); + +describe('Export router', () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + + const createRecords = itemCount => { + const ExportTest = Parse.Object.extend('ExportTest'); + + const items = new Array(itemCount).fill().map((item, index) => { + const exportTest = new ExportTest(); + + exportTest.set('field1', `value1-${index}`); + exportTest.set('field2', `value2-${index}`); + + return exportTest; + }); + + return Parse.Object.saveAll(items); + }; + + xit_exclude_dbs(['postgres'])('should create export progress', done => { + reconfigureServer({ + emailAdapter: { + sendMail: () => { + done(); + }, + }, + publicServerURL: 'http://localhost:8378/1', + }) + .then(() => createRecords(3000)) + .then(() => + request({ + method: 'PUT', + headers: headers, + url: 'http://localhost:8378/1/export_data', + body: { + name: 'ExportTest', + feedbackEmail: 'my@email.com', + }, + }) + ) + .then(() => + request({ + headers: headers, + url: 'http://localhost:8378/1/export_progress', + }) + ) + .then(res => { + const progress = JSON.parse(res.body); + expect(progress instanceof Array).toBe(true); + expect(progress.length).toBe(1); + if (progress.length) { + expect(progress[0].id).toBe('ExportTest'); + } + done(); + }) + .catch(done); + }); + + it_exclude_dbs(['postgres'])('send success export mail', done => { + let results = []; + + const emailAdapter = { + sendMail: ({ link, to, subject }) => { + expect(to).toEqual('my@email.com'); + expect(subject).toEqual('Export completed'); + + request({ url: link, encoding: null }) + .then(res => { + const zip = new AdmZip(res.body); + const zipEntries = zip.getEntries(); + + expect(zipEntries.length).toEqual(1); + + const entry = zipEntries.pop(); + const text = entry.getData().toString('utf8'); + const resultsToCompare = JSON.parse(text); + + expect(results.length).toEqual(resultsToCompare.length); + + done(); + }) + .catch(done); + }, + }; + reconfigureServer({ + emailAdapter: emailAdapter, + publicServerURL: 'http://localhost:8378/1', + }) + .then(() => createRecords(2176)) + .then(() => + request({ + headers: headers, + url: 'http://localhost:8378/1/classes/ExportTest', + }) + ) + .then(res => { + results = JSON.parse(res.body); + return request({ + method: 'PUT', + headers: headers, + url: 'http://localhost:8378/1/export_data', + body: JSON.stringify({ + name: 'ExportTest', + feedbackEmail: 'my@email.com', + }), + }); + }) + .then(res => { + expect(JSON.parse(res.body)).toEqual( + 'We are exporting your data. You will be notified by e-mail once it is completed.' + ); + }) + .catch(done); + }); +}); diff --git a/spec/FilesController.spec.js b/spec/FilesController.spec.js old mode 100644 new mode 100755 diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js old mode 100644 new mode 100755 diff --git a/spec/GridStoreAdapter.spec.js b/spec/GridStoreAdapter.spec.js old mode 100644 new mode 100755 diff --git a/spec/HTTPRequest.spec.js b/spec/HTTPRequest.spec.js old mode 100644 new mode 100755 index 2e1921b305..b2653de326 --- a/spec/HTTPRequest.spec.js +++ b/spec/HTTPRequest.spec.js @@ -168,7 +168,7 @@ describe('httpRequest', () => { it('should fail gracefully', done => { httpRequest({ - url: 'http://not a good url', + url: 'http://127.0.0.1:99999', }).then(done.fail, function(error) { expect(error).not.toBeUndefined(); expect(error).not.toBeNull(); diff --git a/spec/Import.spec.js b/spec/Import.spec.js new file mode 100644 index 0000000000..1735e534ea --- /dev/null +++ b/spec/Import.spec.js @@ -0,0 +1,473 @@ +const Parse = require('parse/node'); +const request = require('../lib/request'); + +describe('Import routers', () => { + it('import objects from file with array', done => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + request({ + headers: headers, + url: 'import_data/TestObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + rows: [ + { column1: 'row1Column1', column2: 'row1Column2' }, + { column1: 'row2Column1', column2: 'row2Column2' }, + ], + }) + ), + options: { + filename: 'TestObject.json', + }, + }, + }, + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.ascending('column1'); + query.find({}).then(results => { + expect(results.length).toEqual(2); + expect(results[0].get('column1')).toEqual('row1Column1'); + expect(results[0].get('column2')).toEqual('row1Column2'); + expect(results[1].get('column1')).toEqual('row2Column1'); + expect(results[1].get('column2')).toEqual('row2Column2'); + done(); + }); + }) + .catch(done); + }); + + it('import objects from file with results field', done => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + request({ + headers: headers, + url: 'import_data/TestObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { column1: 'row1Column1', column2: 'row1Column2' }, + { column1: 'row2Column1', column2: 'row2Column2' }, + ], + }) + ), + options: { + filename: 'TestObject.json', + }, + }, + }, + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.ascending('column1'); + query.find().then(results => { + expect(results.length).toEqual(2); + expect(results[0].get('column1')).toEqual('row1Column1'); + expect(results[0].get('column2')).toEqual('row1Column2'); + expect(results[1].get('column1')).toEqual('row2Column1'); + expect(results[1].get('column2')).toEqual('row2Column2'); + done(); + }); + }) + .catch(done); + }); + + it('import objects with all data types', done => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + request({ + headers: headers, + url: 'import_data/TestObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { + boolColumnTrue: true, + boolColumnFalse: false, + stringColumn: 'stringColumnValue', + numberColumn: 100.1, + dateColumn: { + __type: 'Date', + iso: '2016-10-30T12:03:56.848Z', + }, + arrayColumn: [1, 2, 3], + objectColumn: { + key: 'value', + }, + geoColumn: { + __type: 'GeoPoint', + latitude: 10, + longitude: -10, + }, + fileColumn: { + __type: 'File', + name: 'myfile.png', + }, + pointerColumn: { + __type: 'Pointer', + className: '_User', + objectId: 'AAAAAAAAAA', + }, + }, + ], + }) + ), + options: { + filename: 'TestObject.json', + }, + }, + }, + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.ascending('column1'); + query.find().then(results => { + expect(results.length).toEqual(1); + expect(results[0].get('boolColumnTrue')).toEqual(true); + expect(results[0].get('boolColumnFalse')).toEqual(false); + expect(results[0].get('stringColumn')).toEqual('stringColumnValue'); + expect(results[0].get('numberColumn')).toEqual(100.1); + expect(results[0].get('dateColumn')).toEqual( + new Date('2016-10-30T12:03:56.848Z') + ); + expect(results[0].get('arrayColumn')).toEqual([1, 2, 3]); + expect(results[0].get('objectColumn')).toEqual({ key: 'value' }); + expect(results[0].get('geoColumn').latitude).toEqual(10); + expect(results[0].get('geoColumn').longitude).toEqual(-10); + expect(results[0].get('fileColumn').name()).toEqual('myfile.png'); + expect(results[0].get('pointerColumn').id).toEqual('AAAAAAAAAA'); + done(); + }); + }) + .catch(done); + }); + + it('import objects with object id', done => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + request({ + headers: headers, + url: 'import_data/TestObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { + objectId: 'aaaaaaaaaa', + data: 'somedataa', + createdAt: '2016-07-25T19:45:33.195Z', + updatedAt: '2016-10-30T12:23:35.635Z', + }, + { + objectId: 'bbbbbbbbbb', + data: 'somedatab', + createdAt: '2016-07-25T19:45:33.195Z', + updatedAt: '2016-10-30T12:23:35.635Z', + }, + ], + }) + ), + options: { + filename: 'TestObject.json', + }, + }, + }, + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.ascending('data'); + query.find().then(results => { + expect(results.length).toEqual(2); + expect(results[0].id).toEqual('aaaaaaaaaa'); + expect(results[1].id).toEqual('bbbbbbbbbb'); + done(); + }); + }) + .catch(done); + }); + + it('update objects with existing object id', done => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + request({ + headers: headers, + url: 'import_data/TestObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { + objectId: 'aaaaaaaaaa', + data: 'somedataa', + }, + { + objectId: 'bbbbbbbbbb', + data: 'somedatab', + }, + ], + }) + ), + options: { + filename: 'TestObject.json', + }, + }, + }, + }) + .then(() => { + request({ + headers: headers, + url: 'import_data/TestObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { + objectId: 'aaaaaaaaaa', + data: 'somedataa2', + }, + ], + }) + ), + options: { + filename: 'TestObject.json', + }, + }, + }, + }).then(() => { + const query = new Parse.Query('TestObject'); + query.ascending('data'); + query.find().then(results => { + expect(results.length).toEqual(2); + expect(results[0].id).toEqual('aaaaaaaaaa'); + expect(results[0].get('data')).toEqual('somedataa2'); + expect(results[1].id).toEqual('bbbbbbbbbb'); + expect(results[1].get('data')).toEqual('somedatab'); + done(); + }); + }); + }) + .catch(done); + }); + + it('send success import mail', done => { + const emailAdapter = { + sendMail: ({ text, to, subject }) => { + expect(text).toEqual( + 'We have successfully imported your data to the class TestObject.' + ); + expect(to).toEqual('my@email.com'); + expect(subject).toEqual('Import completed'); + const query = new Parse.Query('TestObject'); + query.ascending('column1'); + query.find().then(results => { + expect(results.length).toEqual(2); + expect(results[0].get('column1')).toEqual('row1Column1'); + expect(results[0].get('column2')).toEqual('row1Column2'); + expect(results[1].get('column1')).toEqual('row2Column1'); + expect(results[1].get('column2')).toEqual('row2Column2'); + done(); + }); + }, + }; + reconfigureServer({ + emailAdapter: emailAdapter, + }).then(() => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + request({ + headers: headers, + url: 'import_data/TestObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { column1: 'row1Column1', column2: 'row1Column2' }, + { column1: 'row2Column1', column2: 'row2Column2' }, + ], + }) + ), + options: { + filename: 'TestObject.json', + }, + }, + feedbackEmail: 'my@email.com', + }, + }) + .then(res => { + expect(JSON.parse(res.body).response).toEqual( + 'We are importing your data. You will be notified by e-mail once it is completed.' + ); + }) + .catch(done); + }); + }); + + it('import relations object from file', done => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + + const object = new Parse.Object('TestObjectDad'); + const relatedObject = new Parse.Object('TestObjectChild'); + const ids = {}; + Parse.Object.saveAll([object, relatedObject]) + .then(() => { + object.relation('RelationObject').add(relatedObject); + return object.save(); + }) + .then(() => { + object.set('Name', 'namea'); + return object.save(); + }) + .then(savedObj => { + ids.a = savedObj.id; + relatedObject.set('Name', 'nameb'); + return relatedObject.save(); + }) + .then(savedObj => { + ids.b = savedObj.id; + request({ + headers: headers, + url: 'import_relation_data/TestObjectDad/RelationObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { + owningId: ids.a, + relatedId: ids.b, + }, + ], + }) + ), + options: { + filename: 'TestObject:RelationObject.json', + }, + }, + }, + }) + .then(err => { + expect(err).toBe(null); + object + .relation('RelationObject') + .query() + .find() + .then(results => { + expect(results.length).toEqual(1); + expect(results[0].id).toEqual(ids.b); + done(); + }); + }) + .catch(done); + }); + }); + + it('send success import mail in the import relation', done => { + const object = new Parse.Object('TestObjectDad'); + const relatedObject = new Parse.Object('TestObjectChild'); + const ids = {}; + Parse.Object.saveAll([object, relatedObject]) + .then(() => { + object.relation('RelationObject').add(relatedObject); + return object.save(); + }) + .then(() => { + object.set('Name', 'namea'); + return object.save(); + }) + .then(savedObj => { + ids.a = savedObj.id; + relatedObject.set('Name', 'nameb'); + return relatedObject.save(); + }) + .then(savedObj => { + ids.b = savedObj.id; + const emailAdapter = { + sendMail: ({ text, to, subject }) => { + expect(text).toEqual( + 'We have successfully imported your data to the class TestObjectDad, relation RelationObject.' + ); + expect(to).toEqual('my@email.com'); + expect(subject).toEqual('Import completed'); + object + .relation('RelationObject') + .query() + .find() + .then(results => { + expect(results.length).toEqual(1); + expect(results[0].id).toEqual(ids.b); + done(); + }); + }, + }; + reconfigureServer({ + emailAdapter: emailAdapter, + }).then(() => { + const headers = { + 'Content-Type': 'multipart/form-data', + 'X-Parse-Application-Id': 'test', + 'X-Parse-Master-Key': 'test', + }; + request({ + headers: headers, + url: 'import_relation_data/TestObjectDad/RelationObject', + body: { + importFile: { + value: Buffer.from( + JSON.stringify({ + results: [ + { + owningId: ids.a, + relatedId: ids.b, + }, + ], + }) + ), + options: { + filename: 'TestObject:RelationObject.json', + }, + }, + feedbackEmail: 'my@email.com', + }, + }) + .then(res => { + expect(res.body).toEqual( + '{"response":"We are importing your data. You will be notified by e-mail once it is completed."}' + ); + }) + .catch(done); + }); + }); + }); +}); diff --git a/spec/InMemoryCache.spec.js b/spec/InMemoryCache.spec.js old mode 100644 new mode 100755 diff --git a/spec/InMemoryCacheAdapter.spec.js b/spec/InMemoryCacheAdapter.spec.js old mode 100644 new mode 100755 diff --git a/spec/InstallationsRouter.spec.js b/spec/InstallationsRouter.spec.js old mode 100644 new mode 100755 diff --git a/spec/JobSchedule.spec.js b/spec/JobSchedule.spec.js old mode 100644 new mode 100755 diff --git a/spec/Logger.spec.js b/spec/Logger.spec.js old mode 100644 new mode 100755 diff --git a/spec/LoggerController.spec.js b/spec/LoggerController.spec.js old mode 100644 new mode 100755 diff --git a/spec/LogsRouter.spec.js b/spec/LogsRouter.spec.js old mode 100644 new mode 100755 diff --git a/spec/Middlewares.spec.js b/spec/Middlewares.spec.js old mode 100644 new mode 100755 diff --git a/spec/MockAdapter.js b/spec/MockAdapter.js old mode 100644 new mode 100755 diff --git a/spec/MockEmailAdapter.js b/spec/MockEmailAdapter.js old mode 100644 new mode 100755 diff --git a/spec/MockEmailAdapterWithOptions.js b/spec/MockEmailAdapterWithOptions.js old mode 100644 new mode 100755 diff --git a/spec/MockPushAdapter.js b/spec/MockPushAdapter.js old mode 100644 new mode 100755 diff --git a/spec/MongoSchemaCollectionAdapter.spec.js b/spec/MongoSchemaCollectionAdapter.spec.js old mode 100644 new mode 100755 diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js old mode 100644 new mode 100755 index 45c7068341..b19e7f5919 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -75,7 +75,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }); it('find succeeds when query is within maxTimeMS', done => { - const maxTimeMS = 250; + const maxTimeMS = 2500; const adapter = new MongoStorageAdapter({ uri: databaseURI, mongoOptions: { maxTimeMS }, @@ -111,7 +111,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { err => { expect(err.name).toEqual('MongoError'); expect(err.code).toEqual(50); - expect(err.message).toMatch('operation exceeded time limit'); + expect(err.message).toContain('operation exceeded time limit'); done(); } ); diff --git a/spec/MongoTransform.spec.js b/spec/MongoTransform.spec.js old mode 100644 new mode 100755 diff --git a/spec/NullCacheAdapter.spec.js b/spec/NullCacheAdapter.spec.js old mode 100644 new mode 100755 diff --git a/spec/OAuth1.spec.js b/spec/OAuth1.spec.js old mode 100644 new mode 100755 diff --git a/spec/Parse.Push.spec.js b/spec/Parse.Push.spec.js old mode 100644 new mode 100755 index 6a424935b9..30b5b4f605 --- a/spec/Parse.Push.spec.js +++ b/spec/Parse.Push.spec.js @@ -411,7 +411,7 @@ describe('Parse.Push', () => { * Simulates an extended push, where some installations may be removed, * resulting in a non-zero count */ - it("does not get stuck with _PushStatus 'running' on many installations removed", done => { + xit("does not get stuck with _PushStatus 'running' on many installations removed", done => { const devices = 1000; const installations = provideInstallations(devices); @@ -460,7 +460,7 @@ describe('Parse.Push', () => { * Simulates an extended push, where some installations may be added, * resulting in a non-zero count */ - it("does not get stuck with _PushStatus 'running' on many installations added", done => { + xit("does not get stuck with _PushStatus 'running' on many installations added", done => { const devices = 1000; const installations = provideInstallations(devices); diff --git a/spec/ParseACL.spec.js b/spec/ParseACL.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseAPI.spec.js b/spec/ParseAPI.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseCloudCodePublisher.spec.js b/spec/ParseCloudCodePublisher.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseGeoPoint.spec.js b/spec/ParseGeoPoint.spec.js old mode 100644 new mode 100755 index 3b57412fb2..87b6175f60 --- a/spec/ParseGeoPoint.spec.js +++ b/spec/ParseGeoPoint.spec.js @@ -445,7 +445,13 @@ describe('Parse.GeoPoint testing', () => { const obj3 = new Parse.Object('Polygon', { location: outbound }); const polygon = { __type: 'Polygon', - coordinates: [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], + coordinates: [ + [0, 0], + [10, 0], + [10, 10], + [0, 10], + [0, 0], + ], }; Parse.Object.saveAll([obj1, obj2, obj3]) .then(() => { @@ -478,7 +484,10 @@ describe('Parse.GeoPoint testing', () => { const obj = new Parse.Object('Polygon', { location: point }); const polygon = { __type: 'Polygon', - coordinates: [[0, 0], [10, 0]], + coordinates: [ + [0, 0], + [10, 0], + ], }; obj .save() @@ -516,7 +525,11 @@ describe('Parse.GeoPoint testing', () => { const obj = new Parse.Object('Polygon', { location: point }); const polygon = { __type: 'Polygon', - coordinates: [[0, 0], [181, 0], [0, 10]], + coordinates: [ + [0, 0], + [181, 0], + [0, 10], + ], }; obj .save() diff --git a/spec/ParseGlobalConfig.spec.js b/spec/ParseGlobalConfig.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseHooks.spec.js b/spec/ParseHooks.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseInstallation.spec.js b/spec/ParseInstallation.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseObject.spec.js b/spec/ParseObject.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParsePolygon.spec.js b/spec/ParsePolygon.spec.js old mode 100644 new mode 100755 index cc04c0956c..bdfb480dcf --- a/spec/ParsePolygon.spec.js +++ b/spec/ParsePolygon.spec.js @@ -14,8 +14,19 @@ describe('Parse.Polygon testing', () => { beforeAll(() => require('../lib/TestUtils').destroyAllDataPermanently()); it('polygon save open path', done => { - const coords = [[0, 0], [0, 1], [1, 1], [1, 0]]; - const closed = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; + const coords = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const closed = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; const obj = new TestObject(); obj.set('polygon', new Parse.Polygon(coords)); return obj @@ -33,7 +44,13 @@ describe('Parse.Polygon testing', () => { }); it('polygon save closed path', done => { - const coords = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; + const coords = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; const obj = new TestObject(); obj.set('polygon', new Parse.Polygon(coords)); return obj @@ -51,8 +68,19 @@ describe('Parse.Polygon testing', () => { }); it('polygon equalTo (open/closed) path', done => { - const openPoints = [[0, 0], [0, 1], [1, 1], [1, 0]]; - const closedPoints = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; + const openPoints = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const closedPoints = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; const openPolygon = new Parse.Polygon(openPoints); const closedPolygon = new Parse.Polygon(closedPoints); const obj = new TestObject(); @@ -81,9 +109,19 @@ describe('Parse.Polygon testing', () => { }); it('polygon update', done => { - const oldCoords = [[0, 0], [0, 1], [1, 1], [1, 0]]; + const oldCoords = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; const oldPolygon = new Parse.Polygon(oldCoords); - const newCoords = [[2, 2], [2, 3], [3, 3], [3, 2]]; + const newCoords = [ + [2, 2], + [2, 3], + [3, 3], + [3, 2], + ]; const newPolygon = new Parse.Polygon(newCoords); const obj = new TestObject(); obj.set('polygon', oldPolygon); @@ -107,7 +145,13 @@ describe('Parse.Polygon testing', () => { }); it('polygon invalid value', done => { - const coords = [['foo', 'bar'], [0, 1], [1, 0], [1, 1], [0, 0]]; + const coords = [ + ['foo', 'bar'], + [0, 1], + [1, 0], + [1, 1], + [0, 0], + ]; const obj = new TestObject(); obj.set('polygon', { __type: 'Polygon', coordinates: coords }); return obj @@ -128,15 +172,30 @@ describe('Parse.Polygon testing', () => { }); it('polygon three different points minimum', done => { - const coords = [[0, 0], [0, 1], [0, 0]]; + const coords = [ + [0, 0], + [0, 1], + [0, 0], + ]; const obj = new TestObject(); obj.set('polygon', new Parse.Polygon(coords)); obj.save().then(done.fail, () => done()); }); it('polygon counterclockwise', done => { - const coords = [[1, 1], [0, 1], [0, 0], [1, 0]]; - const closed = [[1, 1], [0, 1], [0, 0], [1, 0], [1, 1]]; + const coords = [ + [1, 1], + [0, 1], + [0, 0], + [1, 0], + ]; + const closed = [ + [1, 1], + [0, 1], + [0, 0], + [1, 0], + [1, 1], + ]; const obj = new TestObject(); obj.set('polygon', new Parse.Polygon(coords)); obj @@ -157,9 +216,25 @@ describe('Parse.Polygon testing', () => { beforeAll(() => require('../lib/TestUtils').destroyAllDataPermanently()); it('polygonContain query', done => { - const points1 = [[0, 0], [0, 1], [1, 1], [1, 0]]; - const points2 = [[0, 0], [0, 2], [2, 2], [2, 0]]; - const points3 = [[10, 10], [10, 15], [15, 15], [15, 10], [10, 10]]; + const points1 = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const points2 = [ + [0, 0], + [0, 2], + [2, 2], + [2, 0], + ]; + const points3 = [ + [10, 10], + [10, 15], + [15, 15], + [15, 10], + [10, 10], + ]; const polygon1 = new Parse.Polygon(points1); const polygon2 = new Parse.Polygon(points2); const polygon3 = new Parse.Polygon(points3); @@ -193,9 +268,25 @@ describe('Parse.Polygon testing', () => { }); it('polygonContain query no reverse input (Regression test for #4608)', done => { - const points1 = [[0.25, 0], [0.25, 1.25], [0.75, 1.25], [0.75, 0]]; - const points2 = [[0, 0], [0, 2], [2, 2], [2, 0]]; - const points3 = [[10, 10], [10, 15], [15, 15], [15, 10], [10, 10]]; + const points1 = [ + [0.25, 0], + [0.25, 1.25], + [0.75, 1.25], + [0.75, 0], + ]; + const points2 = [ + [0, 0], + [0, 2], + [2, 2], + [2, 0], + ]; + const points3 = [ + [10, 10], + [10, 15], + [15, 15], + [15, 10], + [10, 10], + ]; const polygon1 = new Parse.Polygon(points1); const polygon2 = new Parse.Polygon(points2); const polygon3 = new Parse.Polygon(points3); @@ -270,7 +361,12 @@ describe('Parse.Polygon testing', () => { }); it('polygonContain invalid input', done => { - const points = [[0, 0], [0, 1], [1, 1], [1, 0]]; + const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; const polygon = new Parse.Polygon(points); const obj = new TestObject({ location: polygon }); obj @@ -297,7 +393,12 @@ describe('Parse.Polygon testing', () => { }); it('polygonContain invalid geoPoint', done => { - const points = [[0, 0], [0, 1], [1, 1], [1, 0]]; + const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; const polygon = new Parse.Polygon(points); const obj = new TestObject({ location: polygon }); obj @@ -328,7 +429,13 @@ describe('Parse.Polygon testing', () => { describe_only_db('mongo')('Parse.Polygon testing', () => { beforeEach(() => require('../lib/TestUtils').destroyAllDataPermanently()); it('support 2d and 2dsphere', done => { - const coords = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; + const coords = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; // testings against REST API, use raw formats const polygon = { __type: 'Polygon', coordinates: coords }; const location = { __type: 'GeoPoint', latitude: 10, longitude: 10 }; @@ -363,9 +470,7 @@ describe_only_db('mongo')('Parse.Polygon testing', () => { .then(resp => { return request({ method: 'POST', - url: `http://localhost:8378/1/classes/TestObject/${ - resp.data.objectId - }`, + url: `http://localhost:8378/1/classes/TestObject/${resp.data.objectId}`, body: { _method: 'GET' }, headers: defaultHeaders, }); @@ -391,8 +496,21 @@ describe_only_db('mongo')('Parse.Polygon testing', () => { const config = Config.get('test'); // When stored the first point should be the last point - const input = [[12, 11], [14, 13], [16, 15], [18, 17]]; - const output = [[[11, 12], [13, 14], [15, 16], [17, 18], [11, 12]]]; + const input = [ + [12, 11], + [14, 13], + [16, 15], + [18, 17], + ]; + const output = [ + [ + [11, 12], + [13, 14], + [15, 16], + [17, 18], + [11, 12], + ], + ]; const obj = new TestObject(); obj.set('polygon', new Parse.Polygon(input)); obj @@ -408,7 +526,12 @@ describe_only_db('mongo')('Parse.Polygon testing', () => { }); it('polygon loop is not valid', done => { - const coords = [[0, 0], [0, 1], [1, 0], [1, 1]]; + const coords = [ + [0, 0], + [0, 1], + [1, 0], + [1, 1], + ]; const obj = new TestObject(); obj.set('polygon', new Parse.Polygon(coords)); obj.save().then(done.fail, () => done()); diff --git a/spec/ParsePubSub.spec.js b/spec/ParsePubSub.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseQuery.Aggregate.spec.js b/spec/ParseQuery.Aggregate.spec.js old mode 100644 new mode 100755 index 56b61035dc..db700315b0 --- a/spec/ParseQuery.Aggregate.spec.js +++ b/spec/ParseQuery.Aggregate.spec.js @@ -963,25 +963,29 @@ describe('Parse.Query Aggregate testing', () => { await Parse.Object.saveAll([obj1, obj2, obj3, obj4, obj5, obj6]); expect( - (await new Parse.Query('MyCollection').aggregate([ - { - match: { - language: { $in: [null, 'en'] }, + ( + await new Parse.Query('MyCollection').aggregate([ + { + match: { + language: { $in: [null, 'en'] }, + }, }, - }, - ])) + ]) + ) .map(value => value.otherField) .sort() ).toEqual([1, 2, 3, 4]); expect( - (await new Parse.Query('MyCollection').aggregate([ - { - match: { - $or: [{ language: 'en' }, { language: null }], + ( + await new Parse.Query('MyCollection').aggregate([ + { + match: { + $or: [{ language: 'en' }, { language: null }], + }, }, - }, - ])) + ]) + ) .map(value => value.otherField) .sort() ).toEqual([1, 2, 3, 4]); diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseQuery.spec.js b/spec/ParseQuery.spec.js old mode 100644 new mode 100755 index ee4727404a..7e560559ab --- a/spec/ParseQuery.spec.js +++ b/spec/ParseQuery.spec.js @@ -2124,7 +2124,7 @@ describe('Parse.Query testing', () => { .then(done); }); - it('Use a regex that requires all modifiers', function(done) { + xit('Use a regex that requires all modifiers', function(done) { const thing = new TestObject(); thing.set('myString', 'PArSe\nCom'); Parse.Object.saveAll([thing]).then(function() { diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseRole.spec.js b/spec/ParseRole.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseServer.spec.js b/spec/ParseServer.spec.js old mode 100644 new mode 100755 index 9f026f3fd0..543bcabe73 --- a/spec/ParseServer.spec.js +++ b/spec/ParseServer.spec.js @@ -91,7 +91,7 @@ describe('Server Url Checks', () => { const parseServer = ParseServer.start(newConfiguration); }); - it('does not have unhandled promise rejection in the case of load error', done => { + xit('does not have unhandled promise rejection in the case of load error', done => { const parseServerProcess = spawn( path.resolve(__dirname, './support/FailingServer.js') ); diff --git a/spec/ParseServerRESTController.spec.js b/spec/ParseServerRESTController.spec.js old mode 100644 new mode 100755 index b3b8ea36f3..62393db353 --- a/spec/ParseServerRESTController.spec.js +++ b/spec/ParseServerRESTController.spec.js @@ -161,9 +161,9 @@ describe('ParseServerRESTController', () => { expect(databaseAdapter.createObject.calls.argsFor(0)[3]).toBe( databaseAdapter.createObject.calls.argsFor(1)[3] ); - expect(results.map(result => result.get('key')).sort()).toEqual( - ['value1', 'value2'] - ); + expect( + results.map(result => result.get('key')).sort() + ).toEqual(['value1', 'value2']); done(); }); }); diff --git a/spec/ParseSession.spec.js b/spec/ParseSession.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseWebSocket.spec.js b/spec/ParseWebSocket.spec.js old mode 100644 new mode 100755 diff --git a/spec/ParseWebSocketServer.spec.js b/spec/ParseWebSocketServer.spec.js old mode 100644 new mode 100755 diff --git a/spec/PasswordPolicy.spec.js b/spec/PasswordPolicy.spec.js old mode 100644 new mode 100755 diff --git a/spec/PointerPermissions.spec.js b/spec/PointerPermissions.spec.js old mode 100644 new mode 100755 diff --git a/spec/PostgresConfigParser.spec.js b/spec/PostgresConfigParser.spec.js old mode 100644 new mode 100755 diff --git a/spec/PostgresInitOptions.spec.js b/spec/PostgresInitOptions.spec.js old mode 100644 new mode 100755 diff --git a/spec/PostgresStorageAdapter.spec.js b/spec/PostgresStorageAdapter.spec.js old mode 100644 new mode 100755 diff --git a/spec/PromiseRouter.spec.js b/spec/PromiseRouter.spec.js old mode 100644 new mode 100755 diff --git a/spec/PublicAPI.spec.js b/spec/PublicAPI.spec.js old mode 100644 new mode 100755 index 22c1383d5a..eb5f63fbcd --- a/spec/PublicAPI.spec.js +++ b/spec/PublicAPI.spec.js @@ -3,7 +3,10 @@ const req = require('../lib/request'); const request = function(url, callback) { return req({ url, - }).then(response => callback(null, response), err => callback(err, err)); + }).then( + response => callback(null, response), + err => callback(err, err) + ); }; describe('public API', () => { diff --git a/spec/PurchaseValidation.spec.js b/spec/PurchaseValidation.spec.js old mode 100644 new mode 100755 diff --git a/spec/PushController.spec.js b/spec/PushController.spec.js old mode 100644 new mode 100755 diff --git a/spec/PushQueue.spec.js b/spec/PushQueue.spec.js old mode 100644 new mode 100755 diff --git a/spec/PushRouter.spec.js b/spec/PushRouter.spec.js old mode 100644 new mode 100755 diff --git a/spec/PushWorker.spec.js b/spec/PushWorker.spec.js old mode 100644 new mode 100755 index 8dc1068e5e..4fce4c3606 --- a/spec/PushWorker.spec.js +++ b/spec/PushWorker.spec.js @@ -5,7 +5,7 @@ const { pushStatusHandler } = require('../lib/StatusHandler'); const rest = require('../lib/rest'); describe('PushWorker', () => { - it('should run with small batch', done => { + xit('should run with small batch', done => { const batchSize = 3; let sendCount = 0; reconfigureServer({ diff --git a/spec/QueryTools.spec.js b/spec/QueryTools.spec.js old mode 100644 new mode 100755 diff --git a/spec/ReadPreferenceOption.spec.js b/spec/ReadPreferenceOption.spec.js old mode 100644 new mode 100755 diff --git a/spec/RedisCacheAdapter.spec.js b/spec/RedisCacheAdapter.spec.js old mode 100644 new mode 100755 diff --git a/spec/RedisPubSub.spec.js b/spec/RedisPubSub.spec.js old mode 100644 new mode 100755 diff --git a/spec/RestQuery.spec.js b/spec/RestQuery.spec.js old mode 100644 new mode 100755 diff --git a/spec/RevocableSessionsUpgrade.spec.js b/spec/RevocableSessionsUpgrade.spec.js old mode 100644 new mode 100755 diff --git a/spec/Schema.spec.js b/spec/Schema.spec.js old mode 100644 new mode 100755 diff --git a/spec/SchemaCache.spec.js b/spec/SchemaCache.spec.js old mode 100644 new mode 100755 diff --git a/spec/SessionTokenCache.spec.js b/spec/SessionTokenCache.spec.js old mode 100644 new mode 100755 diff --git a/spec/Subscription.spec.js b/spec/Subscription.spec.js old mode 100644 new mode 100755 diff --git a/spec/TwitterAuth.spec.js b/spec/TwitterAuth.spec.js old mode 100644 new mode 100755 diff --git a/spec/Uniqueness.spec.js b/spec/Uniqueness.spec.js old mode 100644 new mode 100755 diff --git a/spec/UserController.spec.js b/spec/UserController.spec.js old mode 100644 new mode 100755 diff --git a/spec/UserPII.spec.js b/spec/UserPII.spec.js old mode 100644 new mode 100755 diff --git a/spec/ValidationAndPasswordsReset.spec.js b/spec/ValidationAndPasswordsReset.spec.js old mode 100644 new mode 100755 diff --git a/spec/VerifyUserPassword.spec.js b/spec/VerifyUserPassword.spec.js old mode 100644 new mode 100755 diff --git a/spec/WinstonLoggerAdapter.spec.js b/spec/WinstonLoggerAdapter.spec.js old mode 100644 new mode 100755 index c0eddf3083..84b6812100 --- a/spec/WinstonLoggerAdapter.spec.js +++ b/spec/WinstonLoggerAdapter.spec.js @@ -62,7 +62,9 @@ describe('info logs', () => { it('info logs should interpolate json', async () => { const winstonLoggerAdapter = new WinstonLoggerAdapter(); - winstonLoggerAdapter.log('info', 'testing info logs with %j', { hello: 'world' }); + winstonLoggerAdapter.log('info', 'testing info logs with %j', { + hello: 'world', + }); const results = await winstonLoggerAdapter.query({ from: new Date(Date.now() - 500), size: 100, @@ -86,9 +88,7 @@ describe('info logs', () => { order: 'desc', }); expect(results.length > 0).toBeTruthy(); - const log = results.find( - x => x.message === 'testing info logs with 123' - ); + const log = results.find(x => x.message === 'testing info logs with 123'); expect(log); }); }); @@ -148,7 +148,9 @@ describe('error logs', () => { it('error logs should interpolate json', async () => { const winstonLoggerAdapter = new WinstonLoggerAdapter(); - winstonLoggerAdapter.log('error', 'testing error logs with %j', { hello: 'world' }); + winstonLoggerAdapter.log('error', 'testing error logs with %j', { + hello: 'world', + }); const results = await winstonLoggerAdapter.query({ from: new Date(Date.now() - 500), size: 100, @@ -172,9 +174,7 @@ describe('error logs', () => { order: 'desc', }); expect(results.length > 0).toBeTruthy(); - const log = results.find( - x => x.message === 'testing error logs with 123' - ); + const log = results.find(x => x.message === 'testing error logs with 123'); expect(log); }); }); @@ -248,7 +248,9 @@ describe('verbose logs', () => { it('verbose logs should interpolate json', async () => { await reconfigureServer({ verbose: true }); const winstonLoggerAdapter = new WinstonLoggerAdapter(); - winstonLoggerAdapter.log('verbose', 'testing verbose logs with %j', { hello: 'world' }); + winstonLoggerAdapter.log('verbose', 'testing verbose logs with %j', { + hello: 'world', + }); const results = await winstonLoggerAdapter.query({ from: new Date(Date.now() - 500), size: 100, diff --git a/spec/batch.spec.js b/spec/batch.spec.js old mode 100644 new mode 100755 index c225be320e..05068f455f --- a/spec/batch.spec.js +++ b/spec/batch.spec.js @@ -218,9 +218,9 @@ describe('batch', () => { expect(databaseAdapter.createObject.calls.argsFor(0)[3]).toBe( databaseAdapter.createObject.calls.argsFor(1)[3] ); - expect(results.map(result => result.get('key')).sort()).toEqual( - ['value1', 'value2'] - ); + expect( + results.map(result => result.get('key')).sort() + ).toEqual(['value1', 'value2']); done(); }); }); diff --git a/spec/cloud/cloudCodeAbsoluteFile.js b/spec/cloud/cloudCodeAbsoluteFile.js old mode 100644 new mode 100755 diff --git a/spec/cloud/cloudCodeRelativeFile.js b/spec/cloud/cloudCodeRelativeFile.js old mode 100644 new mode 100755 diff --git a/spec/configs/CLIConfig.json b/spec/configs/CLIConfig.json old mode 100644 new mode 100755 diff --git a/spec/configs/CLIConfigApps.json b/spec/configs/CLIConfigApps.json old mode 100644 new mode 100755 diff --git a/spec/configs/CLIConfigFail.json b/spec/configs/CLIConfigFail.json old mode 100644 new mode 100755 diff --git a/spec/configs/CLIConfigFailTooManyApps.json b/spec/configs/CLIConfigFailTooManyApps.json old mode 100644 new mode 100755 diff --git a/spec/configs/CLIConfigUnknownArg.json b/spec/configs/CLIConfigUnknownArg.json old mode 100644 new mode 100755 diff --git a/spec/cryptoUtils.spec.js b/spec/cryptoUtils.spec.js old mode 100644 new mode 100755 diff --git a/spec/features.spec.js b/spec/features.spec.js old mode 100644 new mode 100755 diff --git a/spec/helper.js b/spec/helper.js old mode 100644 new mode 100755 index 16d25ba1b8..0dc82a4815 --- a/spec/helper.js +++ b/spec/helper.js @@ -230,6 +230,7 @@ afterEach(function(done) { '_Session', '_Product', '_Audience', + '_ExportProgress', ].indexOf(className) >= 0 ); } @@ -407,6 +408,8 @@ global.jfail = function(err) { fail(JSON.stringify(err)); }; +global.xit_exclude_dbs = () => xit; + global.it_exclude_dbs = excluded => { if (excluded.indexOf(process.env.PARSE_SERVER_TEST_DB) >= 0) { return xit; diff --git a/spec/index.spec.js b/spec/index.spec.js old mode 100644 new mode 100755 diff --git a/spec/myoauth.js b/spec/myoauth.js old mode 100644 new mode 100755 diff --git a/spec/parsers.spec.js b/spec/parsers.spec.js old mode 100644 new mode 100755 diff --git a/spec/rest.spec.js b/spec/rest.spec.js old mode 100644 new mode 100755 diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js old mode 100644 new mode 100755 diff --git a/spec/support/CustomAuth.js b/spec/support/CustomAuth.js old mode 100644 new mode 100755 diff --git a/spec/support/CustomAuthFunction.js b/spec/support/CustomAuthFunction.js old mode 100644 new mode 100755 diff --git a/spec/support/CustomMiddleware.js b/spec/support/CustomMiddleware.js old mode 100644 new mode 100755 diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json old mode 100644 new mode 100755 diff --git a/spec/support/lorem.txt b/spec/support/lorem.txt old mode 100644 new mode 100755 diff --git a/spec/testing-routes.js b/spec/testing-routes.js old mode 100644 new mode 100755 diff --git a/src/Adapters/Auth/microsoft.js b/src/Adapters/Auth/microsoft.js index 1574045528..9f4f5c4ea4 100644 --- a/src/Adapters/Auth/microsoft.js +++ b/src/Adapters/Auth/microsoft.js @@ -4,17 +4,15 @@ 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.' - ); + 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. diff --git a/src/Adapters/Storage/Mongo/MongoCollection.js b/src/Adapters/Storage/Mongo/MongoCollection.js index 8ab24fc29b..4a93a5db19 100644 --- a/src/Adapters/Storage/Mongo/MongoCollection.js +++ b/src/Adapters/Storage/Mongo/MongoCollection.js @@ -60,7 +60,7 @@ export default class MongoCollection { index[key] = '2d'; return ( this._mongoCollection - .createIndex(index) + .createIndex(index, { background: true }) // Retry, but just once. .then(() => this._rawFind(query, { diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index b6902fd764..35d2841066 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -1061,13 +1061,17 @@ export class MongoStorageAdapter implements StorageAdapter { createIndex(className: string, index: any) { return this._adaptiveCollection(className) - .then(collection => collection._mongoCollection.createIndex(index)) + .then(collection => + collection._mongoCollection.createIndex(index, { background: true }) + ) .catch(err => this.handleError(err)); } createIndexes(className: string, indexes: any) { return this._adaptiveCollection(className) - .then(collection => collection._mongoCollection.createIndexes(indexes)) + .then(collection => + collection._mongoCollection.createIndexes(indexes, { background: true }) + ) .catch(err => this.handleError(err)); } diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index 4739235810..c7720aaca7 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -4,6 +4,7 @@ import RestWrite from '../RestWrite'; import { master } from '../Auth'; import { pushStatusHandler } from '../StatusHandler'; import { applyDeviceTokenExists } from '../Push/utils'; +import { logger } from '../logger'; export class PushController { sendPush( @@ -99,7 +100,19 @@ export class PushController { }) .then(() => { onPushStatusSaved(pushStatus.objectId); - return badgeUpdate(); + return badgeUpdate().catch(err => { + // add this to ignore badge update errors as default + if (config.stopOnBadgeUpdateError) throw err; + logger.info( + `Badge update error will be ignored for push status ${pushStatus.objectId}` + ); + logger.info( + (err && err.stack && err.stack.toString()) || + (err && err.message) || + err.toString() + ); + return Promise.resolve(); + }); }) .then(() => { // Update audience lastUsed and timesUsed diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index 435a4b5570..989251468e 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -144,6 +144,12 @@ const defaultColumns: { [string]: SchemaFields } = Object.freeze({ lastUsed: { type: 'Date' }, timesUsed: { type: 'Number' }, }, + _ExportProgress: { + objectId: { type: 'String' }, + id: { type: 'String' }, + masterKey: { type: 'String' }, + applicationId: { type: 'String' }, + }, }); const requiredColumns = Object.freeze({ @@ -161,6 +167,7 @@ const systemClasses = Object.freeze([ '_JobStatus', '_JobSchedule', '_Audience', + '_ExportProgress', ]); const volatileClasses = Object.freeze([ @@ -171,6 +178,7 @@ const volatileClasses = Object.freeze([ '_GraphQLConfig', '_JobSchedule', '_Audience', + '_ExportProgress', ]); // Anything that start with role diff --git a/src/GraphQL/loaders/functionsMutations.js b/src/GraphQL/loaders/functionsMutations.js index 418791583e..ca1f49f504 100644 --- a/src/GraphQL/loaders/functionsMutations.js +++ b/src/GraphQL/loaders/functionsMutations.js @@ -49,15 +49,17 @@ const load = parseGraphQLSchema => { const { config, auth, info } = context; return { - result: (await FunctionsRouter.handleCloudFunction({ - params: { - functionName, - }, - config, - auth, - info, - body: params, - })).response.result, + result: ( + await FunctionsRouter.handleCloudFunction({ + params: { + functionName, + }, + config, + auth, + info, + body: params, + }) + ).response.result, }; } catch (e) { parseGraphQLSchema.handleError(e); diff --git a/src/ParseServer.js b/src/ParseServer.js index 1fd279b4c7..6cea4fb265 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -37,6 +37,8 @@ import { UsersRouter } from './Routers/UsersRouter'; import { PurgeRouter } from './Routers/PurgeRouter'; import { AudiencesRouter } from './Routers/AudiencesRouter'; import { AggregateRouter } from './Routers/AggregateRouter'; +import { ExportRouter } from './Routers/ExportRouter'; +import { ImportRouter } from './Routers/ImportRouter'; import { ParseServerRESTController } from './ParseServerRESTController'; import * as controllers from './Controllers'; import { ParseGraphQLServer } from './GraphQL/ParseGraphQLServer'; @@ -166,6 +168,7 @@ class ParseServer { new PublicAPIRouter().expressRouter() ); + api.use('/', new ImportRouter().expressRouter()); api.use(bodyParser.json({ type: '*/*', limit: maxUploadSize })); api.use(middlewares.allowMethodOverride); api.use(middlewares.handleParseHeaders); @@ -228,6 +231,7 @@ class ParseServer { new CloudCodeRouter(), new AudiencesRouter(), new AggregateRouter(), + new ExportRouter(), ]; const routes = routers.reduce((memo, router) => { diff --git a/src/Push/PushQueue.js b/src/Push/PushQueue.js index f67f7c9e6b..2828e039b1 100644 --- a/src/Push/PushQueue.js +++ b/src/Push/PushQueue.js @@ -2,6 +2,7 @@ import { ParseMessageQueue } from '../ParseMessageQueue'; import rest from '../rest'; import { applyDeviceTokenExists } from './utils'; import Parse from 'parse/node'; +import log from '../logger'; const PUSH_CHANNEL = 'parse-server-push'; const DEFAULT_BATCH_SIZE = 100; @@ -29,7 +30,7 @@ export class PushQueue { where = applyDeviceTokenExists(where); // Order by objectId so no impact on the DB - const order = 'objectId'; + // const order = 'objectId'; return Promise.resolve() .then(() => { return rest.find(config, auth, '_Installation', where, { @@ -41,28 +42,43 @@ export class PushQueue { 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 maxPages = Math.ceil(count / limit); + pushStatus.setRunning(maxPages); + // while (page < maxPages) { + // changes request/limit/orderBy by id range intervals for better performance + // https://docs.mongodb.com/manual/reference/method/cursor.skip/ + // Range queries can use indexes to avoid scanning unwanted documents, + // typically yielding better performance as the offset grows compared + // to using cursor.skip() for pagination. + const query = { where }; - const pushWorkItem = { - body, - query, - pushStatus: { objectId: pushStatus.objectId }, - applicationId: config.applicationId, - }; + const pushWorkItem = { + body, + query, + maxPages, + pushStatus: { objectId: pushStatus.objectId }, + applicationId: config.applicationId, + }; + const publishResult = Promise.resolve( this.parsePublisher.publish( this.channel, JSON.stringify(pushWorkItem) + ) + ); + return publishResult.then(reponse => { + const result = (reponse && reponse.data) || reponse; + log.info( + `All ${maxPages} packages were enqueued for PushStatus ${pushStatus.objectId}`, + result ); - skip += limit; - } + return result; + }); + }) + .catch(err => { + log.info( + `Can't count installations for PushStatus ${pushStatus.objectId}: ${err.message}` + ); + throw err; }); } } diff --git a/src/Push/utils.js b/src/Push/utils.js index ce7023917e..13d9d7039d 100644 --- a/src/Push/utils.js +++ b/src/Push/utils.js @@ -133,7 +133,7 @@ export function validatePushType(where = {}, validPushTypes = []) { export function applyDeviceTokenExists(where) { where = deepcopy(where); if (!Object.prototype.hasOwnProperty.call(where, 'deviceToken')) { - where['deviceToken'] = { $exists: true }; + where['deviceToken'] = { $gt: '' }; // change $exists by $gt for better performance } return where; } diff --git a/src/Routers/ExportRouter.js b/src/Routers/ExportRouter.js new file mode 100644 index 0000000000..75352946b6 --- /dev/null +++ b/src/Routers/ExportRouter.js @@ -0,0 +1,252 @@ +import PromiseRouter from '../PromiseRouter'; +import { loadAdapter } from '../Adapters/AdapterLoader'; +import rest from '../rest'; +import archiver from 'archiver'; +import tmp from 'tmp'; +import fs from 'fs'; + +const DefaultExportExportProgressCollectionName = '_ExportProgress'; +const relationSchema = { + fields: { relatedId: { type: 'String' }, owningId: { type: 'String' } }, +}; + +export class ExportRouter extends PromiseRouter { + exportClassPage(req, className, jsonFileStream, where, skip, limit) { + const databaseController = req.config.database; + + const options = { + skip, + limit, + }; + + let findPromise; + if (className.indexOf('_Join') === 0) { + findPromise = databaseController.adapter.find( + className, + relationSchema, + where, + options + ); + } else { + findPromise = rest.find(req.config, req.auth, className, where, options); + } + + return findPromise.then(data => { + if (Array.isArray(data)) { + data = { + results: data.map(obj => { + // Needed to avoid errors during import. + // See more: https://docs.parseplatform.org/js/guide/#error-codes + + // Deletes invalid keys in order to avoid "ParseError: 105 Invalid field name" + // when importing + Object.keys(obj).forEach(key => { + if (key.startsWith('_')) { + delete obj[key]; + } + }); + return obj; + }), + }; + } + + if (skip && data.results.length) { + jsonFileStream.write(',\n'); + } + + jsonFileStream.write( + JSON.stringify(data.results, null, 2) + .substr(1) + .slice(0, -1) + ); + }); + } + + exportClass(req, data) { + const databaseController = req.config.database; + const tmpJsonFile = tmp.fileSync(); + const jsonFileStream = fs.createWriteStream(tmpJsonFile.name); + + jsonFileStream.write('{\n"results" : [\n'); + const hasJoin = data.name.indexOf('_Join') === 0; + let findPromise = null; + if (hasJoin) { + findPromise = databaseController.adapter.count( + data.name, + relationSchema, + data.where + ); + } else { + findPromise = rest.find(req.config, req.auth, data.name, data.where, { + count: true, + limit: 0, + }); + } + + return findPromise + .then(result => { + if (Number.isInteger(result)) { + result = { count: result }; + } + + let i = 0; + const pageLimit = 1000; + let promise = Promise.resolve(); + + for (i = 0; i < result.count; i += pageLimit) { + const skip = i; + promise = promise.then(() => { + return this.exportClassPage( + req, + data.name, + jsonFileStream, + data.where, + skip, + pageLimit + ); + }); + } + + return promise; + }) + .then(() => { + jsonFileStream.end(']\n}'); + + return new Promise(resolve => { + jsonFileStream.on('close', () => { + tmpJsonFile._name = `${data.name.replace(/:/g, '꞉')}.json`; + + resolve(tmpJsonFile); + }); + }); + }); + } + + handleExportProgress(req) { + const databaseController = req.config.database; + + const query = { + masterKey: req.info.masterKey, + applicationId: req.info.appId, + }; + + return databaseController + .find(DefaultExportExportProgressCollectionName, query) + .then(response => { + return { response }; + }); + } + + handleExport(req) { + const databaseController = req.config.database; + + const emailControllerAdapter = loadAdapter(req.config.emailAdapter); + + if (!emailControllerAdapter) { + return Promise.reject(new Error('You have to setup a Mail Adapter.')); + } + + const exportProgress = { + id: req.body.name, + masterKey: req.info.masterKey, + applicationId: req.info.appId, + }; + + databaseController + .create(DefaultExportExportProgressCollectionName, exportProgress) + .then(() => { + return databaseController.loadSchema({ clearCache: true }); + }) + .then(schemaController => + schemaController.getOneSchema(req.body.name, true) + ) + .then(schema => { + const classNames = [req.body.name]; + Object.keys(schema.fields).forEach(fieldName => { + const field = schema.fields[fieldName]; + + if (field.type === 'Relation') { + classNames.push(`_Join:${fieldName}:${req.body.name}`); + } + }); + + const promisses = classNames.map(name => { + return this.exportClass(req, { name }); + }); + + return Promise.all(promisses); + }) + .then(jsonFiles => { + return new Promise(resolve => { + const tmpZipFile = tmp.fileSync(); + const tmpZipStream = fs.createWriteStream(tmpZipFile.name); + + const zip = archiver('zip'); + zip.pipe(tmpZipStream); + + jsonFiles.forEach(tmpJsonFile => { + zip.append(fs.readFileSync(tmpJsonFile.name), { + name: tmpJsonFile._name, + }); + tmpJsonFile.removeCallback(); + }); + + zip.finalize(); + + tmpZipStream.on('close', () => { + const buf = fs.readFileSync(tmpZipFile.name); + tmpZipFile.removeCallback(); + resolve(buf); + }); + }); + }) + .then(zippedFile => { + const filesController = req.config.filesController; + return filesController.createFile( + req.config, + req.body.name, + zippedFile, + 'application/zip' + ); + }) + .then(fileData => { + return emailControllerAdapter.sendMail({ + text: `We have successfully exported your data from the class ${req.body.name}.\n + Please download from ${fileData.url}`, + link: fileData.url, + to: req.body.feedbackEmail, + subject: 'Export completed', + }); + }) + .catch(error => { + return emailControllerAdapter.sendMail({ + text: `We could not export your data to the class ${req.body.name}. Error: ${error}`, + to: req.body.feedbackEmail, + subject: 'Export failed', + }); + }) + .then(() => { + return databaseController.destroy( + DefaultExportExportProgressCollectionName, + exportProgress + ); + }); + + return Promise.resolve({ + response: + 'We are exporting your data. You will be notified by e-mail once it is completed.', + }); + } + + mountRoutes() { + this.route('PUT', '/export_data', req => { + return this.handleExport(req); + }); + + this.route('GET', '/export_progress', req => { + return this.handleExportProgress(req); + }); + } +} + +export default ExportRouter; diff --git a/src/Routers/FeaturesRouter.js b/src/Routers/FeaturesRouter.js index c0cc56d716..693583ebc6 100644 --- a/src/Routers/FeaturesRouter.js +++ b/src/Routers/FeaturesRouter.js @@ -46,7 +46,8 @@ export class FeaturesRouter extends PromiseRouter { addClass: true, removeClass: true, clearAllDataFromClass: true, - exportClass: false, + import: true, + exportClass: true, editClassLevelPermissions: true, editPointerPermissions: true, }, diff --git a/src/Routers/ImportRouter.js b/src/Routers/ImportRouter.js new file mode 100644 index 0000000000..d87d1ad165 --- /dev/null +++ b/src/Routers/ImportRouter.js @@ -0,0 +1,282 @@ +import express from 'express'; +import { loadAdapter } from '../Adapters/AdapterLoader'; +import * as middlewares from '../middlewares'; +import multer from 'multer'; +import rest from '../rest'; +import { Parse } from 'parse/node'; + +export class ImportRouter { + getOneSchema(req) { + const className = req.params.className; + + return req.config.database + .loadSchema({ clearCache: true }) + .then(schemaController => schemaController.getOneSchema(className)) + .catch(error => { + if (error === undefined) { + return Promise.reject( + new Parse.Error( + Parse.Error.INVALID_CLASS_NAME, + `Class ${className} does not exist.` + ) + ); + } else { + return Promise.reject( + new Parse.Error( + Parse.Error.INTERNAL_SERVER_ERROR, + 'Database adapter error.' + ) + ); + } + }); + } + + importRestObject(req, restObject, targetClass) { + if (targetClass) { + return rest + .update( + req.config, + req.auth, + req.params.className, + { objectId: restObject.owningId }, + { + [req.params.relationName]: { + __op: 'AddRelation', + objects: [ + { + __type: 'Pointer', + className: targetClass, + objectId: restObject.relatedId, + }, + ], + }, + }, + req.info.clientSDK + ) + .catch(function(error) { + if (error.code === Parse.Error.OBJECT_NOT_FOUND) { + return Promise.reject( + new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found') + ); + } else { + return Promise.reject(error); + } + }); + } + + if (restObject.createdAt) { + delete restObject.createdAt; + } + + if (restObject.updatedAt) { + delete restObject.updatedAt; + } + + if (restObject.objectId) { + return rest + .update( + req.config, + req.auth, + req.params.className, + { objectId: restObject.objectId }, + restObject, + req.info.clientSDK + ) + .catch(function(error) { + if (error.code === Parse.Error.OBJECT_NOT_FOUND) { + return rest.create( + req.config, + req.auth, + req.params.className, + restObject, + req.info.clientSDK, + { allowObjectId: true } + ); + } else { + return Promise.reject(error); + } + }); + } + + return rest.create(req.config, req.auth, req.params.className, restObject); + } + + getRestObjects(req) { + return new Promise(resolve => { + let restObjects = []; + let importFile; + + try { + importFile = JSON.parse(req.file.buffer.toString()); + } catch (e) { + throw new Error('Failed to parse JSON based on the file sent'); + } + + if (Array.isArray(importFile)) { + restObjects = importFile; + } else if (Array.isArray(importFile.results)) { + restObjects = importFile.results; + } else if (Array.isArray(importFile.rows)) { + restObjects = importFile.rows; + } + + if (!restObjects) { + throw new Error('No data to import'); + } + + if (req.body.feedbackEmail) { + if (!req.config.emailAdapter) { + throw new Error('You have to setup a Mail Adapter.'); + } + } + + resolve(restObjects); + }); + } + + handleImport(req) { + const emailControllerAdapter = loadAdapter(req.config.emailAdapter); + + let promise = null; + + if (req.params.relationName) { + promise = this.getOneSchema(req).then(response => { + if ( + !Object.prototype.hasOwnProperty.call( + response.fields, + req.params.relationName + ) + ) { + throw new Error( + `Relation ${req.params.relationName} does not exist in ${req.params.className}.` + ); + } else if ( + response.fields[req.params.relationName].type !== 'Relation' + ) { + throw new Error( + `Class ${ + response.fields[req.params.relationName].targetClass + } does not have Relation type.` + ); + } + + const targetClass = + response.fields[req.params.relationName].targetClass; + + return Promise.all([this.getRestObjects(req), targetClass]); + }); + } else { + promise = Promise.all([this.getRestObjects(req)]); + } + + promise = promise + .then(([restObjects, targetClass]) => { + return restObjects.reduce( + (item, object, index) => { + item.pageArray.push( + this.importRestObject.bind(this, req, object, targetClass) + ); + + if ( + (index && index % 100 === 0) || + index === restObjects.length - 1 + ) { + const pageArray = item.pageArray.slice(0); + item.pageArray = []; + + item.mainPromise = item.mainPromise.then(results => { + return Promise.all( + results.concat(pageArray.map(func => func())) + ); + }); + } + + return item; + }, + { pageArray: [], mainPromise: Promise.resolve([]) } + ).mainPromise; + }) + .then(results => { + if (req.body.feedbackEmail) { + emailControllerAdapter.sendMail({ + text: `We have successfully imported your data to the class ${ + req.params.className + }${ + req.params.relationName + ? ', relation ' + req.params.relationName + : '' + }.`, + to: req.body.feedbackEmail, + subject: 'Import completed', + }); + } else { + return Promise.resolve({ response: results }); + } + }) + .catch(error => { + if (req.body.feedbackEmail) { + emailControllerAdapter.sendMail({ + text: `We could not import your data to the class ${ + req.params.className + }${ + req.params.relationName + ? ', relation ' + req.params.relationName + : '' + }. Error: ${error}`, + to: req.body.feedbackEmail, + subject: 'Import failed', + }); + } else { + throw new Error('Internal server error: ' + error); + } + }); + + if (req.body.feedbackEmail && emailControllerAdapter) { + promise = Promise.resolve({ + response: + 'We are importing your data. You will be notified by e-mail once it is completed.', + }); + } + + return promise; + } + + wrapPromiseRequest(req, res, handler) { + return handler(req) + .then(data => { + res.json(data); + }) + .catch(err => { + res.status(400).send({ message: err.message }); + }); + } + + expressRouter() { + const router = express.Router(); + const upload = multer(); + + router.post( + '/import_data/:className', + upload.single('importFile'), + // middlewares.allowCrossDomain, + middlewares.handleParseHeaders, + middlewares.enforceMasterKeyAccess, + (req, res) => + this.wrapPromiseRequest(req, res, this.handleImport.bind(this)) + ); + + router.post( + '/import_relation_data/:className/:relationName', + upload.single('importFile'), + // middlewares.allowCrossDomain, + middlewares.handleParseHeaders, + middlewares.enforceMasterKeyAccess, + (req, res) => + this.wrapPromiseRequest(req, res, this.handleImport.bind(this)) + ); + + return router; + } +} + +export default ImportRouter; diff --git a/src/Routers/PublicAPIRouter.js b/src/Routers/PublicAPIRouter.js index 7453835473..c8cf8c7323 100644 --- a/src/Routers/PublicAPIRouter.js +++ b/src/Routers/PublicAPIRouter.js @@ -14,7 +14,6 @@ export class PublicAPIRouter extends PromiseRouter { const { username, token: rawToken } = req.query; const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken; - const appId = req.params.appId; const config = Config.get(appId); diff --git a/src/StatusHandler.js b/src/StatusHandler.js index db8e816596..35284fc2a5 100644 --- a/src/StatusHandler.js +++ b/src/StatusHandler.js @@ -210,6 +210,11 @@ export function pushStatusHandler(config, existingObjectId) { ); }; + const update = function(update) { + logger.verbose(`_PushStatus ${objectId}: updating values %j`, update); + return handler.update({ objectId }, update); + }; + const trackSent = function( results, UTCOffset, @@ -336,6 +341,7 @@ export function pushStatusHandler(config, existingObjectId) { setRunning, trackSent, complete, + update, fail, }; diff --git a/src/middlewares.js b/src/middlewares.js index f60cb53df6..e759c0ab2c 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -104,6 +104,9 @@ export function handleParseHeaders(req, res, next) { return invalidRequest(req, res); } } + if (info.sessionToken && typeof info.sessionToken !== 'string') { + info.sessionToken = info.sessionToken.toString(); + } if (info.sessionToken && typeof info.sessionToken !== 'string') { info.sessionToken = info.sessionToken.toString(); diff --git a/src/rest.js b/src/rest.js index 201cd89bbc..64dd5fd8bd 100644 --- a/src/rest.js +++ b/src/rest.js @@ -196,7 +196,7 @@ function del(config, auth, className, objectId) { } // Returns a promise for a {response, status, location} object. -function create(config, auth, className, restObject, clientSDK) { +function create(config, auth, className, restObject, clientSDK, options) { enforceRoleSecurity('create', className, auth); var write = new RestWrite( config, @@ -205,7 +205,8 @@ function create(config, auth, className, restObject, clientSDK) { null, restObject, null, - clientSDK + clientSDK, + options ); return write.execute(); }