From a2127f720891d3f23dbfb08fd8927bb88f015ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B4nio=20Davi=20Mac=C3=AAdo=20Co=C3=AAlho=20de=20Cas?= =?UTF-8?q?tro?= Date: Wed, 24 May 2017 15:52:46 -0300 Subject: [PATCH 01/73] To merge --- .gitignore | 2 +- lib/AccountLockout.js | 159 ++ lib/Adapters/AdapterLoader.js | 44 + lib/Adapters/Analytics/AnalyticsAdapter.js | 28 + lib/Adapters/Auth/AuthAdapter.js | 28 + lib/Adapters/Auth/OAuth1Client.js | 222 +++ lib/Adapters/Auth/facebook.js | 56 + lib/Adapters/Auth/github.js | 54 + lib/Adapters/Auth/google.js | 70 + lib/Adapters/Auth/index.js | 121 ++ lib/Adapters/Auth/instagram.js | 43 + lib/Adapters/Auth/janraincapture.js | 55 + lib/Adapters/Auth/janrainengage.js | 73 + lib/Adapters/Auth/linkedin.js | 60 + lib/Adapters/Auth/meetup.js | 53 + lib/Adapters/Auth/qq.js | 53 + lib/Adapters/Auth/spotify.js | 62 + lib/Adapters/Auth/twitter.js | 56 + lib/Adapters/Auth/vkontakte.js | 67 + lib/Adapters/Auth/wechat.js | 47 + lib/Adapters/Auth/weibo.js | 66 + lib/Adapters/Cache/CacheAdapter.js | 34 + lib/Adapters/Cache/InMemoryCache.js | 70 + lib/Adapters/Cache/InMemoryCacheAdapter.js | 41 + lib/Adapters/Cache/LRUCache.js | 48 + lib/Adapters/Cache/NullCacheAdapter.js | 30 + lib/Adapters/Cache/RedisCacheAdapter.js | 99 + lib/Adapters/Email/MailAdapter.js | 29 + lib/Adapters/Files/FilesAdapter.js | 60 + lib/Adapters/Files/GridStoreAdapter.js | 89 + lib/Adapters/Logger/LoggerAdapter.js | 22 + lib/Adapters/Logger/WinstonLogger.js | 125 ++ lib/Adapters/Logger/WinstonLoggerAdapter.js | 71 + lib/Adapters/MessageQueue/EventEmitterMQ.js | 72 + lib/Adapters/PubSub/EventEmitterPubSub.js | 65 + lib/Adapters/PubSub/RedisPubSub.js | 68 + lib/Adapters/Push/PushAdapter.js | 32 + lib/Adapters/Storage/Mongo/MongoCollection.js | 112 ++ .../Storage/Mongo/MongoSchemaCollection.js | 227 +++ .../Storage/Mongo/MongoStorageAdapter.js | 578 ++++++ lib/Adapters/Storage/Mongo/MongoTransform.js | 1314 +++++++++++++ .../Storage/Postgres/PostgresClient.js | 33 + .../Storage/Postgres/PostgresConfigParser.js | 46 + .../Postgres/PostgresStorageAdapter.js | 1660 +++++++++++++++++ .../Storage/Postgres/sql/array/add-unique.sql | 11 + .../Storage/Postgres/sql/array/add.sql | 11 + .../Postgres/sql/array/contains-all.sql | 11 + .../Storage/Postgres/sql/array/contains.sql | 11 + .../Storage/Postgres/sql/array/remove.sql | 11 + lib/Adapters/Storage/Postgres/sql/index.js | 32 + .../sql/misc/json-object-set-keys.sql | 19 + lib/Auth.js | 221 +++ lib/ClientSDK.js | 42 + lib/Config.js | 292 +++ lib/Controllers/AdaptableController.js | 86 + lib/Controllers/AnalyticsController.js | 43 + lib/Controllers/CacheController.js | 91 + lib/Controllers/DatabaseController.js | 1016 ++++++++++ lib/Controllers/FilesController.js | 108 ++ lib/Controllers/HooksController.js | 237 +++ lib/Controllers/LiveQueryController.js | 58 + lib/Controllers/LoggerController.js | 243 +++ lib/Controllers/PushController.js | 212 +++ lib/Controllers/SchemaCache.js | 96 + lib/Controllers/SchemaController.js | 1048 +++++++++++ lib/Controllers/UserController.js | 259 +++ lib/Controllers/index.js | 282 +++ lib/LiveQuery/Client.js | 97 + lib/LiveQuery/Id.js | 22 + lib/LiveQuery/ParseCloudCodePublisher.js | 50 + lib/LiveQuery/ParseLiveQueryServer.js | 580 ++++++ lib/LiveQuery/ParsePubSub.js | 45 + lib/LiveQuery/ParseWebSocketServer.js | 62 + lib/LiveQuery/QueryTools.js | 320 ++++ lib/LiveQuery/RequestSchema.js | 145 ++ lib/LiveQuery/SessionTokenCache.js | 63 + lib/LiveQuery/Subscription.js | 55 + lib/LiveQuery/equalObjects.js | 50 + lib/Options/Definitions.js | 388 ++++ lib/Options/index.js | 1 + lib/Options/parsers.js | 77 + lib/ParseMessageQueue.js | 30 + lib/ParseServer.js | 375 ++++ lib/ParseServerRESTController.js | 103 + lib/PromiseRouter.js | 218 +++ lib/Push/PushQueue.js | 72 + lib/Push/PushWorker.js | 149 ++ lib/Push/utils.js | 133 ++ lib/RestQuery.js | 752 ++++++++ lib/RestWrite.js | 1178 ++++++++++++ lib/Routers/AggregateRouter.js | 82 + lib/Routers/AnalyticsRouter.js | 31 + lib/Routers/AudiencesRouter.js | 72 + lib/Routers/ClassesRouter.js | 169 ++ lib/Routers/CloudCodeRouter.js | 95 + lib/Routers/ExportRouter.js | 212 +++ lib/Routers/FeaturesRouter.js | 75 + lib/Routers/FilesRouter.js | 205 ++ lib/Routers/FunctionsRouter.js | 183 ++ lib/Routers/GlobalConfigRouter.js | 61 + lib/Routers/HooksRouter.js | 117 ++ lib/Routers/IAPValidationRouter.js | 125 ++ lib/Routers/ImportRouter.js | 208 +++ lib/Routers/InstallationsRouter.js | 53 + lib/Routers/LogsRouter.js | 71 + lib/Routers/PublicAPIRouter.js | 271 +++ lib/Routers/PurgeRouter.js | 42 + lib/Routers/PushRouter.js | 88 + lib/Routers/RolesRouter.js | 39 + lib/Routers/SchemasRouter.js | 96 + lib/Routers/SessionsRouter.js | 116 ++ lib/Routers/UsersRouter.js | 325 ++++ lib/StatusHandler.js | 324 ++++ lib/TestUtils.js | 27 + lib/batch.js | 98 + lib/cache.js | 11 + .../definitions/parse-live-query-server.js | 7 + lib/cli/definitions/parse-server.js | 7 + lib/cli/parse-live-query-server.js | 21 + lib/cli/parse-server.js | 98 + lib/cli/utils/commander.js | 140 ++ lib/cli/utils/runner.js | 53 + lib/cloud-code/HTTPResponse.js | 56 + lib/cloud-code/Parse.Cloud.js | 72 + lib/cloud-code/httpRequest.js | 101 + lib/cryptoUtils.js | 58 + lib/defaults.js | 43 + lib/deprecated.js | 11 + lib/index.js | 77 + lib/logger.js | 47 + lib/middlewares.js | 344 ++++ lib/password.js | 29 + lib/requiredParameter.js | 9 + lib/rest.js | 180 ++ lib/triggers.js | 467 +++++ lib/vendor/README.md | 8 + lib/vendor/mongodbUrl.js | 924 +++++++++ package.json | 3 + spec/Export.spec.js | 139 ++ spec/Import.spec.js | 460 +++++ src/Adapters/PubSub/RedisPubSub.js | 52 +- src/Controllers/SchemaController.js | 10 +- src/ParseServer.js | 4 + src/Push/PushWorker.js | 30 +- src/RestQuery.js | 12 +- src/RestWrite.js | 5 +- src/Routers/ExportRouter.js | 212 +++ src/Routers/FeaturesRouter.js | 3 +- src/Routers/ImportRouter.js | 219 +++ src/middlewares.js | 2 +- src/rest.js | 4 +- 151 files changed, 22829 insertions(+), 23 deletions(-) create mode 100644 lib/AccountLockout.js create mode 100644 lib/Adapters/AdapterLoader.js create mode 100644 lib/Adapters/Analytics/AnalyticsAdapter.js create mode 100644 lib/Adapters/Auth/AuthAdapter.js create mode 100644 lib/Adapters/Auth/OAuth1Client.js create mode 100644 lib/Adapters/Auth/facebook.js create mode 100644 lib/Adapters/Auth/github.js create mode 100644 lib/Adapters/Auth/google.js create mode 100755 lib/Adapters/Auth/index.js create mode 100644 lib/Adapters/Auth/instagram.js create mode 100644 lib/Adapters/Auth/janraincapture.js create mode 100644 lib/Adapters/Auth/janrainengage.js create mode 100644 lib/Adapters/Auth/linkedin.js create mode 100644 lib/Adapters/Auth/meetup.js create mode 100644 lib/Adapters/Auth/qq.js create mode 100644 lib/Adapters/Auth/spotify.js create mode 100644 lib/Adapters/Auth/twitter.js create mode 100644 lib/Adapters/Auth/vkontakte.js create mode 100644 lib/Adapters/Auth/wechat.js create mode 100644 lib/Adapters/Auth/weibo.js create mode 100644 lib/Adapters/Cache/CacheAdapter.js create mode 100644 lib/Adapters/Cache/InMemoryCache.js create mode 100644 lib/Adapters/Cache/InMemoryCacheAdapter.js create mode 100644 lib/Adapters/Cache/LRUCache.js create mode 100644 lib/Adapters/Cache/NullCacheAdapter.js create mode 100644 lib/Adapters/Cache/RedisCacheAdapter.js create mode 100644 lib/Adapters/Email/MailAdapter.js create mode 100644 lib/Adapters/Files/FilesAdapter.js create mode 100644 lib/Adapters/Files/GridStoreAdapter.js create mode 100644 lib/Adapters/Logger/LoggerAdapter.js create mode 100644 lib/Adapters/Logger/WinstonLogger.js create mode 100644 lib/Adapters/Logger/WinstonLoggerAdapter.js create mode 100644 lib/Adapters/MessageQueue/EventEmitterMQ.js create mode 100644 lib/Adapters/PubSub/EventEmitterPubSub.js create mode 100644 lib/Adapters/PubSub/RedisPubSub.js create mode 100644 lib/Adapters/Push/PushAdapter.js create mode 100644 lib/Adapters/Storage/Mongo/MongoCollection.js create mode 100644 lib/Adapters/Storage/Mongo/MongoSchemaCollection.js create mode 100644 lib/Adapters/Storage/Mongo/MongoStorageAdapter.js create mode 100644 lib/Adapters/Storage/Mongo/MongoTransform.js create mode 100644 lib/Adapters/Storage/Postgres/PostgresClient.js create mode 100644 lib/Adapters/Storage/Postgres/PostgresConfigParser.js create mode 100644 lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js create mode 100644 lib/Adapters/Storage/Postgres/sql/array/add-unique.sql create mode 100644 lib/Adapters/Storage/Postgres/sql/array/add.sql create mode 100644 lib/Adapters/Storage/Postgres/sql/array/contains-all.sql create mode 100644 lib/Adapters/Storage/Postgres/sql/array/contains.sql create mode 100644 lib/Adapters/Storage/Postgres/sql/array/remove.sql create mode 100644 lib/Adapters/Storage/Postgres/sql/index.js create mode 100644 lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql create mode 100644 lib/Auth.js create mode 100644 lib/ClientSDK.js create mode 100644 lib/Config.js create mode 100644 lib/Controllers/AdaptableController.js create mode 100644 lib/Controllers/AnalyticsController.js create mode 100644 lib/Controllers/CacheController.js create mode 100644 lib/Controllers/DatabaseController.js create mode 100644 lib/Controllers/FilesController.js create mode 100644 lib/Controllers/HooksController.js create mode 100644 lib/Controllers/LiveQueryController.js create mode 100644 lib/Controllers/LoggerController.js create mode 100644 lib/Controllers/PushController.js create mode 100644 lib/Controllers/SchemaCache.js create mode 100644 lib/Controllers/SchemaController.js create mode 100644 lib/Controllers/UserController.js create mode 100644 lib/Controllers/index.js create mode 100644 lib/LiveQuery/Client.js create mode 100644 lib/LiveQuery/Id.js create mode 100644 lib/LiveQuery/ParseCloudCodePublisher.js create mode 100644 lib/LiveQuery/ParseLiveQueryServer.js create mode 100644 lib/LiveQuery/ParsePubSub.js create mode 100644 lib/LiveQuery/ParseWebSocketServer.js create mode 100644 lib/LiveQuery/QueryTools.js create mode 100644 lib/LiveQuery/RequestSchema.js create mode 100644 lib/LiveQuery/SessionTokenCache.js create mode 100644 lib/LiveQuery/Subscription.js create mode 100644 lib/LiveQuery/equalObjects.js create mode 100644 lib/Options/Definitions.js create mode 100644 lib/Options/index.js create mode 100644 lib/Options/parsers.js create mode 100644 lib/ParseMessageQueue.js create mode 100644 lib/ParseServer.js create mode 100644 lib/ParseServerRESTController.js create mode 100644 lib/PromiseRouter.js create mode 100644 lib/Push/PushQueue.js create mode 100644 lib/Push/PushWorker.js create mode 100644 lib/Push/utils.js create mode 100644 lib/RestQuery.js create mode 100644 lib/RestWrite.js create mode 100644 lib/Routers/AggregateRouter.js create mode 100644 lib/Routers/AnalyticsRouter.js create mode 100644 lib/Routers/AudiencesRouter.js create mode 100644 lib/Routers/ClassesRouter.js create mode 100644 lib/Routers/CloudCodeRouter.js create mode 100644 lib/Routers/ExportRouter.js create mode 100644 lib/Routers/FeaturesRouter.js create mode 100644 lib/Routers/FilesRouter.js create mode 100644 lib/Routers/FunctionsRouter.js create mode 100644 lib/Routers/GlobalConfigRouter.js create mode 100644 lib/Routers/HooksRouter.js create mode 100644 lib/Routers/IAPValidationRouter.js create mode 100644 lib/Routers/ImportRouter.js create mode 100644 lib/Routers/InstallationsRouter.js create mode 100644 lib/Routers/LogsRouter.js create mode 100644 lib/Routers/PublicAPIRouter.js create mode 100644 lib/Routers/PurgeRouter.js create mode 100644 lib/Routers/PushRouter.js create mode 100644 lib/Routers/RolesRouter.js create mode 100644 lib/Routers/SchemasRouter.js create mode 100644 lib/Routers/SessionsRouter.js create mode 100644 lib/Routers/UsersRouter.js create mode 100644 lib/StatusHandler.js create mode 100644 lib/TestUtils.js create mode 100644 lib/batch.js create mode 100644 lib/cache.js create mode 100644 lib/cli/definitions/parse-live-query-server.js create mode 100644 lib/cli/definitions/parse-server.js create mode 100644 lib/cli/parse-live-query-server.js create mode 100755 lib/cli/parse-server.js create mode 100644 lib/cli/utils/commander.js create mode 100644 lib/cli/utils/runner.js create mode 100644 lib/cloud-code/HTTPResponse.js create mode 100644 lib/cloud-code/Parse.Cloud.js create mode 100644 lib/cloud-code/httpRequest.js create mode 100644 lib/cryptoUtils.js create mode 100644 lib/defaults.js create mode 100644 lib/deprecated.js create mode 100644 lib/index.js create mode 100644 lib/logger.js create mode 100644 lib/middlewares.js create mode 100644 lib/password.js create mode 100644 lib/requiredParameter.js create mode 100644 lib/rest.js create mode 100644 lib/triggers.js create mode 100644 lib/vendor/README.md create mode 100644 lib/vendor/mongodbUrl.js create mode 100644 spec/Export.spec.js create mode 100644 spec/Import.spec.js create mode 100644 src/Routers/ExportRouter.js create mode 100644 src/Routers/ImportRouter.js diff --git a/.gitignore b/.gitignore index 4e4ee21cae..8f1edaabbf 100644 --- a/.gitignore +++ b/.gitignore @@ -41,7 +41,7 @@ node_modules .vscode # Babel.js -lib/ +#lib/ # cache folder .cache diff --git a/lib/AccountLockout.js b/lib/AccountLockout.js new file mode 100644 index 0000000000..dd1522e9c7 --- /dev/null +++ b/lib/AccountLockout.js @@ -0,0 +1,159 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AccountLockout = undefined; + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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: _node2.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: _node2.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 _node2.default.Error(_node2.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; // This class handles the Account Lockout Policy settings. + +exports.default = AccountLockout; \ No newline at end of file diff --git a/lib/Adapters/AdapterLoader.js b/lib/Adapters/AdapterLoader.js new file mode 100644 index 0000000000..ffdf98fd95 --- /dev/null +++ b/lib/Adapters/AdapterLoader.js @@ -0,0 +1,44 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.loadAdapter = loadAdapter; +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; +} + +exports.default = loadAdapter; \ 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..d4af892ac0 --- /dev/null +++ b/lib/Adapters/Analytics/AnalyticsAdapter.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/*eslint no-unused-vars: "off"*/ +class AnalyticsAdapter { + + /* + @param parameters: the analytics request body, analytics info will be in the dimensions property + @param req: the original http request + */ + appOpened(parameters, req) { + return Promise.resolve({}); + } + + /* + @param eventName: the name of the custom eventName + @param parameters: the analytics request body, analytics info will be in the dimensions property + @param req: the original http request + */ + trackEvent(eventName, parameters, req) { + return Promise.resolve({}); + } +} + +exports.AnalyticsAdapter = AnalyticsAdapter; +exports.default = AnalyticsAdapter; \ 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..b3dec519db --- /dev/null +++ b/lib/Adapters/Auth/AuthAdapter.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/*eslint no-unused-vars: "off"*/ +class AuthAdapter { + + /* + @param appIds: the specified app ids in the configuration + @param authData: the client provided authData + @returns a promise that resolves if the applicationId is valid + */ + validateAppId(appIds, authData) { + return Promise.resolve({}); + } + + /* + @param authData: the client provided authData + @param options: additional options + */ + validateAuthData(authData, options) { + return Promise.resolve({}); + } +} + +exports.AuthAdapter = AuthAdapter; +exports.default = AuthAdapter; \ 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..68da0c6f99 --- /dev/null +++ b/lib/Adapters/Auth/OAuth1Client.js @@ -0,0 +1,222 @@ +'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; \ 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..2e422926f8 --- /dev/null +++ b/lib/Adapters/Auth/facebook.js @@ -0,0 +1,56 @@ +'use strict'; + +// Helper functions for accessing the Facebook Graph API. +var https = require('https'); +var Parse = require('parse/node').Parse; + +// Returns a promise that fulfills iff this user id is valid. +function validateAuthData(authData) { + return graphRequest('me?fields=id&access_token=' + authData.access_token).then(data => { + if (data && data.id == authData.id) { + 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) { + var access_token = authData.access_token; + if (!appIds.length) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Facebook auth is not configured.'); + } + return graphRequest('app?access_token=' + access_token).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 new Promise(function (resolve, reject) { + https.get('https://graph.facebook.com/v2.5/' + path, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with Facebook.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..e727313fc7 --- /dev/null +++ b/lib/Adapters/Auth/github.js @@ -0,0 +1,54 @@ +'use strict'; + +// Helper functions for accessing the github API. +var https = require('https'); +var Parse = require('parse/node').Parse; + +// 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 new Promise(function (resolve, reject) { + https.get({ + host: 'api.github.com', + path: '/' + path, + headers: { + 'Authorization': 'bearer ' + access_token, + 'User-Agent': 'parse-server' + } + }, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with Github.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..898eeeffdb --- /dev/null +++ b/lib/Adapters/Auth/google.js @@ -0,0 +1,70 @@ +'use strict'; + +// Helper functions for accessing the google API. +var https = require('https'); +var Parse = require('parse/node').Parse; + +function validateIdToken(id, token) { + return request("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 request("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 request(path) { + return new Promise(function (resolve, reject) { + https.get("https://www.googleapis.com/oauth2/v3/" + path, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with Google.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..1fd4073170 --- /dev/null +++ b/lib/Adapters/Auth/index.js @@ -0,0 +1,121 @@ +'use strict'; + +var _AdapterLoader = require('../AdapterLoader'); + +var _AdapterLoader2 = _interopRequireDefault(_AdapterLoader); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const facebook = require('./facebook'); +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 vkontakte = require("./vkontakte"); +const qq = require("./qq"); +const wechat = require("./wechat"); +const weibo = require("./weibo"); + +const anonymous = { + validateAuthData: () => { + return Promise.resolve(); + }, + validateAppId: () => { + return Promise.resolve(); + } +}; + +const providers = { + facebook, + instagram, + linkedin, + meetup, + google, + github, + twitter, + spotify, + anonymous, + digits, + janrainengage, + janraincapture, + vkontakte, + qq, + wechat, + weibo +}; + +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) { + const defaultAdapter = providers[provider]; + const adapter = Object.assign({}, defaultAdapter); + const providerOptions = authOptions[provider]; + + if (!defaultAdapter && !providerOptions) { + return; + } + + const appIds = providerOptions ? providerOptions.appIds : undefined; + + // Try the configuration methods + if (providerOptions) { + const optionalAdapter = (0, _AdapterLoader2.default)(providerOptions, undefined, providerOptions); + if (optionalAdapter) { + ['validateAuthData', 'validateAppId'].forEach(key => { + if (optionalAdapter[key]) { + adapter[key] = optionalAdapter[key]; + } + }); + } + } + + 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; \ 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..090bc168d9 --- /dev/null +++ b/lib/Adapters/Auth/instagram.js @@ -0,0 +1,43 @@ +'use strict'; + +// Helper functions for accessing the instagram API. +var https = require('https'); +var Parse = require('parse/node').Parse; + +// 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 new Promise(function (resolve, reject) { + https.get("https://api.instagram.com/v1/" + path, 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 validate this access token with Instagram.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..bfab1a995c --- /dev/null +++ b/lib/Adapters/Auth/janraincapture.js @@ -0,0 +1,55 @@ +'use strict'; + +// Helper functions for accessing the Janrain Capture API. +var https = require('https'); +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 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 new Promise(function (resolve, reject) { + https.get({ + host: host, + path: '/entity?' + query_string_data + }, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + resolve(JSON.parse(data)); + }); + }).on('error', function () { + reject('Failed to validate this access token with Janrain capture.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..c3936dfd63 --- /dev/null +++ b/lib/Adapters/Auth/janrainengage.js @@ -0,0 +1,73 @@ +'use strict'; + +// Helper functions for accessing the Janrain Engage API. +var https = require('https'); +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 request(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 request(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 new Promise(function (resolve, reject) { + // Create the post request. + var post_req = https.request(post_options, function (res) { + var data = ''; + res.setEncoding('utf8'); + // Append data as we receive it from the Janrain engage server. + res.on('data', function (d) { + data += d; + }); + // Once we have all the data, we can parse it and return the data we want. + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }); + + post_req.write(post_data); + post_req.end(); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..702de7081b --- /dev/null +++ b/lib/Adapters/Auth/linkedin.js @@ -0,0 +1,60 @@ +'use strict'; + +// Helper functions for accessing the linkedin API. +var https = require('https'); +var Parse = require('parse/node').Parse; + +// Returns a promise that fulfills iff this user id is valid. +function validateAuthData(authData) { + return request('people/~:(id)', 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 new Promise(function (resolve, reject) { + https.get({ + host: 'api.linkedin.com', + path: '/v1/' + path, + headers: headers + }, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with Linkedin.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..7a996510b5 --- /dev/null +++ b/lib/Adapters/Auth/meetup.js @@ -0,0 +1,53 @@ +'use strict'; + +// Helper functions for accessing the meetup API. +var https = require('https'); +var Parse = require('parse/node').Parse; + +// 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 new Promise(function (resolve, reject) { + https.get({ + host: 'api.meetup.com', + path: '/2/' + path, + headers: { + 'Authorization': 'bearer ' + access_token + } + }, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with Meetup.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..aa82ca6b62 --- /dev/null +++ b/lib/Adapters/Auth/qq.js @@ -0,0 +1,53 @@ +'use strict'; + +// Helper functions for accessing the qq Graph API. +var https = require('https'); +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 new Promise(function (resolve, reject) { + https.get('https://graph.qq.com/oauth2.0/' + path, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + var starPos = data.indexOf("("); + var 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); + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with qq.'); + }); + }); +} + +module.exports = { + validateAppId, + validateAuthData +}; \ 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..f1d8f6da21 --- /dev/null +++ b/lib/Adapters/Auth/spotify.js @@ -0,0 +1,62 @@ +'use strict'; + +// Helper functions for accessing the Spotify API. +var https = require('https'); +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 new Promise(function (resolve, reject) { + https.get({ + host: 'api.spotify.com', + path: '/v1/' + path, + headers: { + 'Authorization': 'Bearer ' + access_token + } + }, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with Spotify.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..4f4560fedc --- /dev/null +++ b/lib/Adapters/Auth/twitter.js @@ -0,0 +1,56 @@ +'use strict'; + +// Helper functions for accessing the twitter API. +var OAuth = require('./OAuth1Client'); +var Parse = require('parse/node').Parse; +var logger = require('../../logger').default; + +// 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) { + logger.error('Twitter Auth', 'Multiple twitter configurations are available, by no consumer_key was sent by the client.'); + 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) { + logger.error('Twitter Auth', 'Cannot find a configuration for the provided consumer_key'); + 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 +}; \ 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..195a33f93b --- /dev/null +++ b/lib/Adapters/Auth/vkontakte.js @@ -0,0 +1,67 @@ +'use strict'; + +// Helper functions for accessing the vkontakte API. + +var https = require('https'); +var Parse = require('parse/node').Parse; +var logger = require('../../logger').default; + +// 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/secure.checkToken?token=" + authData.access_token + "&client_secret=" + params.appSecret + "&access_token=" + response.access_token).then(function (response) { + if (response && response.response && response.response.user_id == authData.id) { + return; + } + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Vk auth is invalid for this user.'); + }); + } + logger.error('Vk Auth', 'Vk appIds or appSecret is incorrect.'); + 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) { + logger.error('Vk Auth', 'Vk auth is not configured. Missing appIds or appSecret.'); + 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 new Promise(function (resolve, reject) { + https.get("https://" + host + "/" + path, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with Vk.'); + }); + }); +} + +module.exports = { + validateAppId: validateAppId, + validateAuthData: validateAuthData +}; \ 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..1f0aebaa50 --- /dev/null +++ b/lib/Adapters/Auth/wechat.js @@ -0,0 +1,47 @@ +'use strict'; + +// Helper functions for accessing the WeChat Graph API. +var https = require('https'); +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 new Promise(function (resolve, reject) { + https.get('https://api.weixin.qq.com/sns/' + path, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + }).on('error', function () { + reject('Failed to validate this access token with wechat.'); + }); + }); +} + +module.exports = { + validateAppId, + validateAuthData +}; \ 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..b6a0d0f46d --- /dev/null +++ b/lib/Adapters/Auth/weibo.js @@ -0,0 +1,66 @@ +'use strict'; + +// Helper functions for accessing the weibo Graph API. +var https = require('https'); +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) { + return new Promise(function (resolve, reject) { + 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) + } + }; + var req = https.request(options, function (res) { + var data = ''; + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function () { + try { + data = JSON.parse(data); + } catch (e) { + return reject(e); + } + resolve(data); + }); + res.on('error', function () { + reject('Failed to validate this access token with weibo.'); + }); + }); + req.on('error', function () { + reject('Failed to validate this access token with weibo.'); + }); + req.write(postData); + req.end(); + }); +} + +module.exports = { + validateAppId, + validateAuthData +}; \ 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..bbb17ef749 --- /dev/null +++ b/lib/Adapters/Cache/CacheAdapter.js @@ -0,0 +1,34 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/*eslint no-unused-vars: "off"*/ +class CacheAdapter { + /** + * Get a value in the cache + * @param 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 key Cache key to set + * @param value Value to set the key + * @param ttl Optional TTL + */ + put(key, value, ttl) {} + + /** + * Remove a value from the cache. + * @param key Cache key to remove + */ + del(key) {} + + /** + * Empty a cache + */ + clear() {} +} +exports.CacheAdapter = CacheAdapter; \ 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..c76bbc729d --- /dev/null +++ b/lib/Adapters/Cache/InMemoryCache.js @@ -0,0 +1,70 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +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; +exports.default = InMemoryCache; \ 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..e3705c920c --- /dev/null +++ b/lib/Adapters/Cache/InMemoryCacheAdapter.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.InMemoryCacheAdapter = undefined; + +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; +exports.default = InMemoryCacheAdapter; \ 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..a4476aa154 --- /dev/null +++ b/lib/Adapters/Cache/LRUCache.js @@ -0,0 +1,48 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.LRUCache = undefined; + +var _lruCache = require('lru-cache'); + +var _lruCache2 = _interopRequireDefault(_lruCache); + +var _defaults = require('../../defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class LRUCache { + constructor({ + ttl = _defaults2.default.cacheTTL, + maxSize = _defaults2.default.cacheMaxSize + }) { + this.cache = new _lruCache2.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; +exports.default = LRUCache; \ 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..55d536878c --- /dev/null +++ b/lib/Adapters/Cache/NullCacheAdapter.js @@ -0,0 +1,30 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +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; +exports.default = NullCacheAdapter; \ No newline at end of file diff --git a/lib/Adapters/Cache/RedisCacheAdapter.js b/lib/Adapters/Cache/RedisCacheAdapter.js new file mode 100644 index 0000000000..615a4c8250 --- /dev/null +++ b/lib/Adapters/Cache/RedisCacheAdapter.js @@ -0,0 +1,99 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RedisCacheAdapter = undefined; + +var _redis = require('redis'); + +var _redis2 = _interopRequireDefault(_redis); + +var _logger = require('../../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const DEFAULT_REDIS_TTL = 30 * 1000; // 30 seconds in milliseconds + +function debug() { + _logger2.default.debug.apply(_logger2.default, ['RedisCacheAdapter', ...arguments]); +} + +class RedisCacheAdapter { + + constructor(redisCtx, ttl = DEFAULT_REDIS_TTL) { + this.client = _redis2.default.createClient(redisCtx); + this.p = Promise.resolve(); + this.ttl = ttl; + } + + get(key) { + debug('get', key); + this.p = this.p.then(() => { + return new Promise(resolve => { + this.client.get(key, function (err, res) { + debug('-> get', key, res); + if (!res) { + return resolve(null); + } + resolve(JSON.parse(res)); + }); + }); + }); + return this.p; + } + + put(key, value, ttl = this.ttl) { + value = JSON.stringify(value); + debug('put', key, value, ttl); + if (ttl === 0) { + return this.p; // ttl of zero is a logical no-op, but redis cannot set expire time of zero + } + if (ttl < 0 || isNaN(ttl)) { + ttl = DEFAULT_REDIS_TTL; + } + this.p = this.p.then(() => { + return new Promise(resolve => { + if (ttl === Infinity) { + this.client.set(key, value, function () { + resolve(); + }); + } else { + this.client.psetex(key, ttl, value, function () { + resolve(); + }); + } + }); + }); + return this.p; + } + + del(key) { + debug('del', key); + this.p = this.p.then(() => { + return new Promise(resolve => { + this.client.del(key, function () { + resolve(); + }); + }); + }); + return this.p; + } + + clear() { + debug('clear'); + this.p = this.p.then(() => { + return new Promise(resolve => { + this.client.flushdb(function () { + resolve(); + }); + }); + }); + return this.p; + } +} + +exports.RedisCacheAdapter = RedisCacheAdapter; +exports.default = RedisCacheAdapter; \ 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..b2fe018c92 --- /dev/null +++ b/lib/Adapters/Email/MailAdapter.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/*eslint no-unused-vars: "off"*/ +/* + 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; +exports.default = MailAdapter; \ 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..128cb2cd94 --- /dev/null +++ b/lib/Adapters/Files/FilesAdapter.js @@ -0,0 +1,60 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +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) {} +} + +exports.FilesAdapter = FilesAdapter; /*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) +// +// Default is GridStoreAdapter, which requires mongo +// and for the API server to be using the DatabaseController with Mongo +// database adapter. + +exports.default = FilesAdapter; \ 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..d5e944344f --- /dev/null +++ b/lib/Adapters/Files/GridStoreAdapter.js @@ -0,0 +1,89 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.GridStoreAdapter = undefined; + +var _mongodb = require('mongodb'); + +var _FilesAdapter = require('./FilesAdapter'); + +var _defaults = require('../../defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GridStoreAdapter extends _FilesAdapter.FilesAdapter { + + constructor(mongoDatabaseURI = _defaults2.default.DefaultMongoURI) { + super(); + this._databaseURI = mongoDatabaseURI; + } + + _connect() { + if (!this._connectionPromise) { + this._connectionPromise = _mongodb.MongoClient.connect(this._databaseURI); + } + 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); + } + + getFileStream(filename) { + return this._connect().then(database => { + return _mongodb.GridStore.exist(database, filename).then(() => { + const gridStore = new _mongodb.GridStore(database, filename, 'r'); + return gridStore.open(); + }); + }); + } +} + +exports.GridStoreAdapter = GridStoreAdapter; /** + GridStoreAdapter + Stores files in Mongo using GridStore + Requires the database adapter to be based on mongoclient + + weak + */ + +exports.default = GridStoreAdapter; \ 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..097955b9d4 --- /dev/null +++ b/lib/Adapters/Logger/LoggerAdapter.js @@ -0,0 +1,22 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/*eslint no-unused-vars: "off"*/ +// Logger Adapter +// +// Allows you to change the logger mechanism +// +// Adapter classes must implement the following functions: +// * log() {} +// * query(options, callback) /* optional */ +// Default is WinstonLoggerAdapter.js + +class LoggerAdapter { + constructor(options) {} + log(level, message) /* meta */{} +} + +exports.LoggerAdapter = LoggerAdapter; +exports.default = LoggerAdapter; \ 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..bda6f18ea8 --- /dev/null +++ b/lib/Adapters/Logger/WinstonLogger.js @@ -0,0 +1,125 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.logger = undefined; +exports.configureLogger = configureLogger; +exports.addTransport = addTransport; +exports.removeTransport = removeTransport; + +var _winston = require('winston'); + +var _winston2 = _interopRequireDefault(_winston); + +var _fs = require('fs'); + +var _fs2 = _interopRequireDefault(_fs); + +var _path = require('path'); + +var _path2 = _interopRequireDefault(_path); + +var _winstonDailyRotateFile = require('winston-daily-rotate-file'); + +var _winstonDailyRotateFile2 = _interopRequireDefault(_winstonDailyRotateFile); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _defaults = require('../../defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const logger = new _winston2.default.Logger(); +const additionalTransports = []; + +function updateTransports(options) { + const transports = Object.assign({}, logger.transports); + if (options) { + const silent = options.silent; + delete options.silent; + if (_lodash2.default.isNull(options.dirname)) { + delete transports['parse-server']; + delete transports['parse-server-error']; + } else if (!_lodash2.default.isUndefined(options.dirname)) { + transports['parse-server'] = new _winstonDailyRotateFile2.default(Object.assign({}, { + filename: 'parse-server.info', + name: 'parse-server' + }, options, { timestamp: true })); + transports['parse-server-error'] = new _winstonDailyRotateFile2.default(Object.assign({}, { + filename: 'parse-server.err', + name: 'parse-server-error' + }, options, { level: 'error', timestamp: true })); + } + + transports.console = new _winston2.default.transports.Console(Object.assign({ + colorize: true, + name: 'console', + silent + }, options)); + } + // Mount the additional transports + additionalTransports.forEach(transport => { + transports[transport.name] = transport; + }); + logger.configure({ + transports: _lodash2.default.values(transports) + }); +} + +function configureLogger({ + logsFolder = _defaults2.default.logsFolder, + jsonLogs = _defaults2.default.jsonLogs, + logLevel = _winston2.default.level, + verbose = _defaults2.default.verbose, + silent = _defaults2.default.silent } = {}) { + + if (verbose) { + logLevel = 'verbose'; + } + + _winston2.default.level = logLevel; + const options = {}; + + if (logsFolder) { + if (!_path2.default.isAbsolute(logsFolder)) { + logsFolder = _path2.default.resolve(process.cwd(), logsFolder); + } + try { + _fs2.default.mkdirSync(logsFolder); + } catch (e) {/* */} + } + options.dirname = logsFolder; + options.level = logLevel; + options.silent = silent; + + if (jsonLogs) { + options.json = true; + options.stringify = true; + } + updateTransports(options); +} + +function addTransport(transport) { + additionalTransports.push(transport); + updateTransports(); +} + +function removeTransport(transport) { + const transportName = typeof transport == 'string' ? transport : transport.name; + const transports = Object.assign({}, logger.transports); + delete transports[transportName]; + logger.configure({ + transports: _lodash2.default.values(transports) + }); + _lodash2.default.remove(additionalTransports, transport => { + return transport.name === transportName; + }); +} + +exports.logger = logger; +exports.default = logger; \ 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..0ea0a02cf7 --- /dev/null +++ b/lib/Adapters/Logger/WinstonLoggerAdapter.js @@ -0,0 +1,71 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WinstonLoggerAdapter = undefined; + +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; +exports.default = WinstonLoggerAdapter; \ 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..c25e1c2076 --- /dev/null +++ b/lib/Adapters/MessageQueue/EventEmitterMQ.js @@ -0,0 +1,72 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.EventEmitterMQ = undefined; + +var _events = require('events'); + +var _events2 = _interopRequireDefault(_events); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const emitter = new _events2.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 _events2.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; \ 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..b878353d74 --- /dev/null +++ b/lib/Adapters/PubSub/EventEmitterPubSub.js @@ -0,0 +1,65 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.EventEmitterPubSub = undefined; + +var _events = require('events'); + +var _events2 = _interopRequireDefault(_events); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const emitter = new _events2.default.EventEmitter(); + +class Publisher { + + constructor(emitter) { + this.emitter = emitter; + } + + publish(channel, message) { + this.emitter.emit(channel, message); + } +} + +class Subscriber extends _events2.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; \ 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..bb84311735 --- /dev/null +++ b/lib/Adapters/PubSub/RedisPubSub.js @@ -0,0 +1,68 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createSubscriber = exports.createPublisher = exports.RedisPubSub = undefined; + +var _redis = require('redis'); + +var _redis2 = _interopRequireDefault(_redis); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createPublisher({ redisURL }) { + var redisCli = _redis2.default.createClient(redisURL, { no_ready_check: true }); + + if (redisCli) { + redisCli.publish2 = redisCli.publish; + + redisCli.publish = function (channel, body) { + var bodyObject; + try { + bodyObject = JSON.parse(body); + } catch (e) { + bodyObject = {}; + } + if (bodyObject && bodyObject.pushStatus) { + redisCli.multi([['sadd', bodyObject.applicationId + ':push', body]]).exec(); + } + return redisCli.publish2(channel, body); + }; + } + + return redisCli; +} + +function createSubscriber({ redisURL }) { + var redisCli = _redis2.default.createClient(redisURL, { no_ready_check: true }); + var secondaryClient = _redis2.default.createClient(redisURL, { no_ready_check: true }); + if (redisCli) { + redisCli.run = function (workItem) { + return new _node2.default.Promise(function (resolve) { + secondaryClient.multi([['spop', workItem.applicationId + ':push']]).exec(function (err, rep) { + if (!err && rep && rep[0]) { + resolve(JSON.parse(rep[0])); + } else { + resolve(); + } + }); + }); + }; + } + + return redisCli; +} + +const RedisPubSub = { + createPublisher, + createSubscriber +}; + +exports.RedisPubSub = RedisPubSub; +exports.createPublisher = createPublisher; +exports.createSubscriber = createSubscriber; \ 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..d8080c5328 --- /dev/null +++ b/lib/Adapters/Push/PushAdapter.js @@ -0,0 +1,32 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +/*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. + +class PushAdapter { + send(body, installations, pushStatus) {} + + /** + * Get an array of valid push types. + * @returns {Array} An array of valid push types + */ + getValidPushTypes() { + return []; + } +} + +exports.PushAdapter = PushAdapter; +exports.default = PushAdapter; \ 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..7e9c22c2b6 --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoCollection.js @@ -0,0 +1,112 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +const mongodb = require('mongodb'); +const Collection = mongodb.Collection; + +class MongoCollection { + + constructor(mongoCollection) { + this._mongoCollection = mongoCollection; + } + + // Does a find with "smart indexing". + // Currently this just means, if it needs a geoindex and there is + // none, then build the geoindex. + // This could be improved a lot but it's not clear if that's a good + // idea. Or even if this behavior is a good idea. + find(query, { skip, limit, sort, keys, maxTimeMS, readPreference } = {}) { + // Support for Full Text Search - $text + if (keys && keys.$score) { + delete keys.$score; + keys.score = { $meta: 'textScore' }; + } + return this._rawFind(query, { skip, limit, sort, keys, maxTimeMS, readPreference }).catch(error => { + // Check for "no geoindex" error + if (error.code != 17007 && !error.message.match(/unable to find index for .geoNear/)) { + throw error; + } + // Figure out what key needs an index + const key = error.message.match(/field=([A-Za-z_0-9]+) /)[1]; + if (!key) { + throw error; + } + + var index = {}; + index[key] = '2d'; + return this._mongoCollection.createIndex(index) + // Retry, but just once. + .then(() => this._rawFind(query, { skip, limit, sort, keys, maxTimeMS, readPreference })); + }); + } + + _rawFind(query, { skip, limit, sort, keys, maxTimeMS, readPreference } = {}) { + let findOperation = this._mongoCollection.find(query, { skip, limit, sort, readPreference }); + + if (keys) { + findOperation = findOperation.project(keys); + } + + if (maxTimeMS) { + findOperation = findOperation.maxTimeMS(maxTimeMS); + } + + return findOperation.toArray(); + } + + count(query, { skip, limit, sort, maxTimeMS, readPreference } = {}) { + const countOperation = this._mongoCollection.count(query, { skip, limit, sort, maxTimeMS, readPreference }); + + return countOperation; + } + + distinct(field, query) { + return this._mongoCollection.distinct(field, query); + } + + aggregate(pipeline, { maxTimeMS, readPreference } = {}) { + return this._mongoCollection.aggregate(pipeline, { maxTimeMS, readPreference }).toArray(); + } + + insertOne(object) { + return this._mongoCollection.insertOne(object); + } + + // 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) { + return this._mongoCollection.update(query, update, { upsert: true }); + } + + updateOne(query, update) { + return this._mongoCollection.updateOne(query, update); + } + + updateMany(query, update) { + return this._mongoCollection.updateMany(query, update); + } + + deleteMany(query) { + return this._mongoCollection.deleteMany(query); + } + + _ensureSparseUniqueIndexInBackground(indexRequest) { + return new Promise((resolve, reject) => { + this._mongoCollection.ensureIndex(indexRequest, { unique: true, background: true, sparse: true }, error => { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); + } + + drop() { + return this._mongoCollection.drop(); + } +} +exports.default = MongoCollection; \ 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..c987723ccc --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js @@ -0,0 +1,227 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _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; }; + +var _MongoCollection = require('./MongoCollection'); + +var _MongoCollection2 = _interopRequireDefault(_MongoCollection); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: 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]); + 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: {}, + get: {}, + create: {}, + update: {}, + delete: {}, + addField: {} +}); + +const defaultCLPS = Object.freeze({ + find: { '*': true }, + get: { '*': true }, + create: { '*': true }, + update: { '*': true }, + delete: { '*': true }, + addField: { '*': true } +}); + +function mongoSchemaToParseSchema(mongoSchema) { + let clps = defaultCLPS; + let indexes = {}; + if (mongoSchema._metadata) { + if (mongoSchema._metadata.class_permissions) { + clps = _extends({}, emptyCLPS, mongoSchema._metadata.class_permissions); + } + if (mongoSchema._metadata.indexes) { + indexes = _extends({}, 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), []); + } + + 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, type) { + 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 (type.type === 'GeoPoint') { + // Make sure there are not other geopoint fields + if (Object.keys(schema.fields).some(existingField => schema.fields[existingField].type === 'GeoPoint')) { + throw new _node2.default.Error(_node2.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(() => { + // 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) + return this.upsertSchema(className, { [fieldName]: { '$exists': false } }, { '$set': { [fieldName]: parseFieldTypeToMongoFieldType(type) } }); + }); + } +} + +// 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; + +exports.default = MongoSchemaCollection; \ 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..fbde2bed67 --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -0,0 +1,578 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MongoStorageAdapter = undefined; + +var _MongoCollection = require('./MongoCollection'); + +var _MongoCollection2 = _interopRequireDefault(_MongoCollection); + +var _MongoSchemaCollection = require('./MongoSchemaCollection'); + +var _MongoSchemaCollection2 = _interopRequireDefault(_MongoSchemaCollection); + +var _mongodbUrl = require('../../../vendor/mongodbUrl'); + +var _MongoTransform = require('./MongoTransform'); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _defaults = require('../../../defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +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 = _objectWithoutProperties(_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' + }; + + for (const fieldName in fields) { + mongoObject[fieldName] = _MongoSchemaCollection2.default.parseFieldTypeToMongoFieldType(fields[fieldName]); + } + + 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; + } + + return mongoObject; +}; + +class MongoStorageAdapter { + // Private + constructor({ + uri = _defaults2.default.DefaultMongoURI, + collectionPrefix = '', + mongoOptions = {} + }) { + this._uri = uri; + this._collectionPrefix = collectionPrefix; + this._mongoOptions = mongoOptions; + + // MaxTimeMS is not a global MongoDB client option, it is applied per operation. + this._maxTimeMS = mongoOptions.maxTimeMS; + this.canSortOnJoinTables = true; + delete mongoOptions.maxTimeMS; + } + // Public + + + 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(database => { + if (!database) { + delete this.connectionPromise; + return; + } + database.on('error', () => { + delete this.connectionPromise; + }); + database.on('close', () => { + delete this.connectionPromise; + }); + this.database = database; + }).catch(err => { + delete this.connectionPromise; + return Promise.reject(err); + }); + + return this.connectionPromise; + } + + handleShutdown() { + if (!this.database) { + return; + } + this.database.close(false); + } + + _adaptiveCollection(name) { + return this.connect().then(() => this.database.collection(this._collectionPrefix + name)).then(rawCollection => new _MongoCollection2.default(rawCollection)); + } + + _schemaCollection() { + return this.connect().then(() => this._adaptiveCollection(MongoSchemaCollectionName)).then(collection => new _MongoSchemaCollection2.default(collection)); + } + + classExists(name) { + return this.connect().then(() => { + return this.database.listCollections({ name: this._collectionPrefix + name }).toArray(); + }).then(collections => { + return collections.length > 0; + }); + } + + setClassLevelPermissions(className, CLPs) { + return this._schemaCollection().then(schemaCollection => schemaCollection.updateSchema(className, { + $set: { '_metadata.class_permissions': CLPs } + })); + } + + 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 _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`); + } + if (!existingIndexes[name] && field.__op === 'Delete') { + throw new _node2.default.Error(_node2.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 (!fields.hasOwnProperty(key)) { + throw new _node2.default.Error(_node2.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 } + })); + } + + 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(() => { + // 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._collection.insertOne(mongoObject)).then(result => _MongoSchemaCollection2.default._TESTmongoSchemaToParseSchema(result.ops[0])).catch(error => { + if (error.code === 11000) { + //Mongo's duplicate key error + throw new _node2.default.Error(_node2.default.Error.DUPLICATE_VALUE, 'Class already exists.'); + } else { + throw error; + } + }); + } + + addFieldIfNotExists(className, fieldName, type) { + return this._schemaCollection().then(schemaCollection => schemaCollection.addFieldIfNotExists(className, fieldName, type)).then(() => this.createIndexesIfNeeded(className, fieldName, type)); + } + + // 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)); + } + + // Delete all data known to this adapter. Used for testing. + deleteAllClasses() { + return storageAdapterAllCollections(this).then(collections => Promise.all(collections.map(collection => 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; + }); + + return this._adaptiveCollection(className).then(collection => collection.updateMany({}, collectionUpdate)).then(() => this._schemaCollection()).then(schemaCollection => schemaCollection.updateSchema(className, schemaUpdate)); + } + + // 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()); + } + + // 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)); + } + + // 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) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoObject = (0, _MongoTransform.parseObjectToMongoObjectForCreate)(className, object, schema); + return this._adaptiveCollection(className).then(collection => collection.insertOne(mongoObject)).catch(error => { + if (error.code === 11000) { + // Duplicate value + const err = new _node2.default.Error(_node2.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; + }); + } + + // 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) { + schema = convertParseSchemaToMongoSchema(schema); + return this._adaptiveCollection(className).then(collection => { + const mongoWhere = (0, _MongoTransform.transformWhere)(className, query, schema); + return collection.deleteMany(mongoWhere); + }).then(({ result }) => { + if (result.n === 0) { + throw new _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + return Promise.resolve(); + }, () => { + throw new _node2.default.Error(_node2.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) { + 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)); + } + + // Atomically finds and updates an object based on query. + // Return value not currently well specified. + findOneAndUpdate(className, schema, query, update) { + 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.findAndModify(mongoWhere, [], mongoUpdate, { new: true })).then(result => (0, _MongoTransform.mongoObjectToParseObject)(className, result.value, schema)); + } + + // Hopefully we can get rid of this. It's only used for config and hooks. + upsertOneObject(className, schema, query, update) { + 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)); + } + + // Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }. + find(className, schema, query, { skip, limit, sort, keys, readPreference }) { + schema = convertParseSchemaToMongoSchema(schema); + const mongoWhere = (0, _MongoTransform.transformWhere)(className, query, schema); + const mongoSort = _lodash2.default.mapKeys(sort, (value, fieldName) => (0, _MongoTransform.transformKey)(className, fieldName, schema)); + const mongoKeys = _lodash2.default.reduce(keys, (memo, key) => { + memo[(0, _MongoTransform.transformKey)(className, key, schema)] = 1; + return memo; + }, {}); + + readPreference = this._parseReadPreference(readPreference); + return this.createTextIndexesIfNeeded(className, query, schema).then(() => this._adaptiveCollection(className)).then(collection => collection.find(mongoWhere, { + skip, + limit, + sort: mongoSort, + keys: mongoKeys, + maxTimeMS: this._maxTimeMS, + readPreference + })).then(objects => objects.map(object => (0, _MongoTransform.mongoObjectToParseObject)(className, object, schema))); + } + + // 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 _node2.default.Error(_node2.default.Error.DUPLICATE_VALUE, 'Tried to ensure field uniqueness for a class that already has duplicates.'); + } + throw error; + }); + } + + // Used in tests + _rawFind(className, query) { + return this._adaptiveCollection(className).then(collection => collection.find(query, { + maxTimeMS: this._maxTimeMS + })); + } + + // Executes a count. + count(className, schema, query, readPreference) { + schema = convertParseSchemaToMongoSchema(schema); + readPreference = this._parseReadPreference(readPreference); + return this._adaptiveCollection(className).then(collection => collection.count((0, _MongoTransform.transformWhere)(className, query, schema), { + maxTimeMS: this._maxTimeMS, + readPreference + })); + } + + distinct(className, schema, query, fieldName) { + schema = convertParseSchemaToMongoSchema(schema); + return this._adaptiveCollection(className).then(collection => collection.distinct(fieldName, (0, _MongoTransform.transformWhere)(className, query, schema))).then(objects => objects.map(object => (0, _MongoTransform.mongoObjectToParseObject)(className, object, schema))); + } + + aggregate(className, schema, pipeline, readPreference) { + readPreference = this._parseReadPreference(readPreference); + return this._adaptiveCollection(className).then(collection => collection.aggregate(pipeline, { readPreference, maxTimeMS: this._maxTimeMS })).then(results => { + results.forEach(result => { + if (result.hasOwnProperty('_id')) { + result.objectId = result._id; + delete result._id; + } + }); + return results; + }).then(objects => objects.map(object => (0, _MongoTransform.mongoObjectToParseObject)(className, object, schema))); + } + + _parseReadPreference(readPreference) { + if (readPreference) { + 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; + default: + throw new _node2.default.Error(_node2.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)); + } + + createIndexes(className, indexes) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.createIndexes(indexes)); + } + + 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 (index.hasOwnProperty(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()); + } + + dropIndex(className, index) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.dropIndex(index)); + } + + dropAllIndexes(className) { + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.dropIndexes()); + } + + updateSchemaWithIndexes() { + return this.getAllClasses().then(classes => { + const promises = classes.map(schema => { + return this.setIndexesFromMongo(schema.className); + }); + return Promise.all(promises); + }); + } +} + +exports.MongoStorageAdapter = MongoStorageAdapter; +exports.default = MongoStorageAdapter; + +module.exports = MongoStorageAdapter; // Required for tests \ 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..5a39ba79c9 --- /dev/null +++ b/lib/Adapters/Storage/Mongo/MongoTransform.js @@ -0,0 +1,1314 @@ +'use strict'; + +var _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; }; + +var _logger = require('../../../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: 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 (className === '_GlobalConfig') { + 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 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) { + 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 (className === '_GlobalConfig') { + 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': + return { key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema)) }; + case '$and': + return { key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, schema)) }; + 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); + if (transformedConstraint !== CannotTransform) { + if (transformedConstraint.$text) { + return { key: '$text', value: transformedConstraint.$text }; + } + 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) { + const mongoWhere = {}; + for (const restKey in restWhere) { + const out = transformQueryKeyValue(className, restKey, restWhere[restKey], schema); + 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 = _extends({}, 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 { + 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) { + 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; + } + + _logger2.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] = _lodash2.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); + 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 '$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': + var point = constraint[key]; + answer[key] = [point.longitude, point.latitude]; + break; + + case '$maxDistance': + 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']; + if (!(polygon instanceof Array)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + } + if (polygon.length < 3) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + } + const points = polygon.map(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 + }; + 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': + return mongoObject; + case 'undefined': + 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); + } + + if (mongoObject.hasOwnProperty('__type') && mongoObject.__type == 'Date' && mongoObject.iso instanceof Date) { + mongoObject.iso = mongoObject.iso.toJSON(); + return mongoObject; + } + + return mapValues(mongoObject, nestedMongoObjectToNestedParseObject); + default: + throw 'unknown js type'; + } +}; + +// 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': + return mongoObject; + case 'undefined': + 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; + default: + // Check other auth data keys + var authDataMatch = key.match(/^_auth_data_([a-zA-Z0-9_]+)$/); + if (authDataMatch) { + 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]) { + _logger2.default.info('transform.js', 'Found a pointer column not in the schema, dropping it.', className, newKey); + break; + } + if (schema.fields[newKey].type !== 'Pointer') { + _logger2.default.info('transform.js', 'Found a pointer in a non-pointer column, dropping it.', className, key); + break; + } + if (mongoObject[key] === null) { + break; + } + var objData = mongoObject[key].split('$'); + if (objData[0] !== schema.fields[newKey].targetClass) { + throw 'pointer to incorrect className'; + } + restObject[newKey] = { + __type: 'Pointer', + className: objData[0], + objectId: objData[1] + }; + 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 _extends({}, 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(new Buffer(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) { + return { + __type: 'Polygon', + coordinates: object['coordinates'][0] + }; + }, + + 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) { + const coords = json.coordinates; + 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'); + } + 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 +}; \ 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..85429dfa81 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresClient.js @@ -0,0 +1,33 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createClient = createClient; + +const parser = require('./PostgresConfigParser'); + +function createClient(uri, databaseOptions) { + let dbOptions = {}; + databaseOptions = databaseOptions || {}; + + if (uri) { + dbOptions = parser.getDatabaseOptionsFromURI(uri); + } + + for (const key in databaseOptions) { + dbOptions[key] = databaseOptions[key]; + } + + const initOptions = dbOptions.initOptions || {}; + const pgp = require('pg-promise')(initOptions); + const client = pgp(dbOptions); + + if (dbOptions.pgOptions) { + for (const key in dbOptions.pgOptions) { + pgp.pg.defaults[key] = dbOptions.pgOptions[key]; + } + } + + return { client, pgp }; +} \ 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..19a5112a8b --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresConfigParser.js @@ -0,0 +1,46 @@ +'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 +}; \ 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..29dfa4f670 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -0,0 +1,1660 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PostgresStorageAdapter = undefined; + +var _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; }; + +var _PostgresClient = require('./PostgresClient'); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _sql = require('./sql'); + +var _sql2 = _interopRequireDefault(_sql); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const PostgresRelationDoesNotExistError = '42P01'; +const PostgresDuplicateRelationError = '42P07'; +const PostgresDuplicateColumnError = '42701'; +const PostgresDuplicateObjectError = '42710'; +const PostgresUniqueIndexViolationError = '23505'; +const PostgresTransactionAbortedError = '25P02'; +const logger = require('../../../logger'); + +const debug = function () { + let args = [...arguments]; + 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 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: {}, + create: {}, + update: {}, + delete: {}, + addField: {} +}); + +const defaultCLPS = Object.freeze({ + find: { '*': true }, + get: { '*': true }, + create: { '*': true }, + update: { '*': true }, + delete: { '*': true }, + addField: { '*': true } +}); + +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 = _extends({}, emptyCLPS, schema.classLevelPermissions); + } + let indexes = {}; + if (schema.indexes) { + indexes = _extends({}, 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 => { + 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 _node2.default.Error(_node2.default.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); + } + } + } +}; + +// Returns the list of join tables on a schema +const joinTablesForSchema = schema => { + const list = []; + if (schema) { + Object.keys(schema.fields).forEach(field => { + if (schema.fields[field].type === 'Relation') { + list.push(`_Join:${field}:${schema.className}`); + } + }); + } + return list; +}; + +const buildWhereClause = ({ schema, query, index }) => { + const patterns = []; + let values = []; + const sorts = []; + + schema = toPostgresSchema(schema); + for (const fieldName in query) { + const isArrayField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array'; + const initialPatternsLength = patterns.length; + const fieldValue = query[fieldName]; + + // nothingin the schema, it's gonna blow up + if (!schema.fields[fieldName]) { + // as it won't exist + if (fieldValue && fieldValue.$exists === false) { + continue; + } + } + + if (fieldName.indexOf('.') >= 0) { + let name = transformDotField(fieldName); + if (fieldValue === null) { + patterns.push(`${name} IS NULL`); + } else { + if (fieldValue.$in) { + const inPatterns = []; + name = transformDotFieldToComponents(fieldName).join('->'); + fieldValue.$in.forEach(listElem => { + if (typeof listElem === 'string') { + inPatterns.push(`"${listElem}"`); + } else { + inPatterns.push(`${listElem}`); + } + }); + patterns.push(`(${name})::jsonb @> '[${inPatterns.join(',')}]'::jsonb`); + } else if (fieldValue.$regex) { + // Handle later + } else { + patterns.push(`${name} = '${fieldValue}'`); + } + } + } 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}`); + 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 (fieldName === '$or' || fieldName === '$and') { + const clauses = []; + const clauseValues = []; + fieldValue.forEach(subQuery => { + const clause = buildWhereClause({ schema, query: subQuery, index }); + if (clause.pattern.length > 0) { + clauses.push(clause.pattern); + clauseValues.push(...clause.values); + index += clause.values.length; + } + }); + const orOrAnd = fieldName === '$or' ? ' OR ' : ' AND '; + patterns.push(`(${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 + patterns.push(`($${index}:name <> $${index + 1} OR $${index}:name IS NULL)`); + } + } + + // TODO: support arrays + values.push(fieldName, fieldValue.$ne); + index += 2; + } + + if (fieldValue.$eq) { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.$eq); + 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) => { + if (baseArray.length > 0) { + const not = notIn ? ' NOT ' : ''; + 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; + } + }; + if (fieldValue.$in) { + createConstraint(_lodash2.default.flatMap(fieldValue.$in, elt => elt), false); + } + if (fieldValue.$nin) { + createConstraint(_lodash2.default.flatMap(fieldValue.$nin, elt => elt), true); + } + } + + if (Array.isArray(fieldValue.$all) && isArrayField) { + patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`); + values.push(fieldName, JSON.stringify(fieldValue.$all)); + 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.$text) { + const search = fieldValue.$text.$search; + let language = 'english'; + if (typeof search !== 'object') { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, `bad $text: $search, should be object`); + } + if (!search.$term || typeof search.$term !== 'string') { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, `bad $text: $term, should be string`); + } + if (search.$language && typeof search.$language !== 'string') { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.INVALID_JSON, `bad $text: $caseSensitive, should be boolean`); + } else if (search.$caseSensitive) { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.INVALID_JSON, `bad $text: $diacriticSensitive, should be boolean`); + } else if (search.$diacriticSensitive === false) { + throw new _node2.default.Error(_node2.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.$polygon) { + const polygon = fieldValue.$geoWithin.$polygon; + if (!(polygon instanceof Array)) { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + } + if (polygon.length < 3) { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + } + const points = polygon.map(point => { + if (typeof point !== 'object' || point.__type !== 'GeoPoint') { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value'); + } else { + _node2.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 _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoIntersect value; $point should be GeoPoint'); + } else { + _node2.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]) { + const pgComparator = ParseToPosgresComparator[cmp]; + patterns.push(`$${index}:name ${pgComparator} $${index + 1}`); + values.push(fieldName, toPostgresValue(fieldValue[cmp])); + index += 2; + } + }); + + if (initialPatternsLength === patterns.length) { + throw new _node2.default.Error(_node2.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 { + + constructor({ + uri, + collectionPrefix = '', + databaseOptions + }) { + this._collectionPrefix = collectionPrefix; + const { client, pgp } = (0, _PostgresClient.createClient)(uri, databaseOptions); + this._client = client; + this._pgp = pgp; + } + // Private + + + handleShutdown() { + if (!this._client) { + return; + } + this._client.$pool.end(); + } + + _ensureSchemaCollectionExists(conn) { + conn = conn || this._client; + return conn.none('CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )').catch(error => { + if (error.code === PostgresDuplicateRelationError || error.code === PostgresUniqueIndexViolationError || error.code === PostgresDuplicateObjectError) { + // Table already exists, must have been created by a different request. Ignore error. + } else { + throw error; + } + }); + } + + classExists(name) { + return this._client.one('SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)', [name], a => a.exists); + } + + setClassLevelPermissions(className, CLPs) { + return this._ensureSchemaCollectionExists().then(() => { + const values = [className, 'schema', 'classLevelPermissions', JSON.stringify(CLPs)]; + return this._client.none(`UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className"=$1 `, values); + }); + } + + setIndexesWithSchemaFormat(className, submittedIndexes, existingIndexes = {}, fields, conn) { + conn = conn || this._client; + 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 _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`); + } + if (!existingIndexes[name] && field.__op === 'Delete') { + throw new _node2.default.Error(_node2.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 (!fields.hasOwnProperty(key)) { + throw new _node2.default.Error(_node2.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, conn); + } + let deletePromise = Promise.resolve(); + if (deletedIndexes.length > 0) { + deletePromise = this.dropIndexes(className, deletedIndexes, conn); + } + return conn.task(t => { + const values = [className, 'schema', 'indexes', JSON.stringify(existingIndexes)]; + return t.batch([deletePromise, insertPromise, this._ensureSchemaCollectionExists(t), t.none('UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className"=$1', values)]); + }); + } + + createClass(className, schema) { + return this._client.tx('create-class', t => { + const q1 = this.createTable(className, schema, t); + const q2 = t.none('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($, $, true)', { className, schema }); + const q3 = this.setIndexesWithSchemaFormat(className, schema.indexes, {}, schema.fields, t); + + return t.batch([q1, q2, q3]); + }).then(() => { + return toParseSchema(schema); + }).catch(err => { + if (Array.isArray(err.data) && err.data.length > 1 && err.data[0].result.code === PostgresTransactionAbortedError) { + err = err.data[1].result; + } + + if (err.code === PostgresUniqueIndexViolationError && err.detail.includes(className)) { + throw new _node2.default.Error(_node2.default.Error.DUPLICATE_VALUE, `Class ${className} already exists.`); + } + throw err; + }); + } + + // Just create a table, do not insert in schema + createTable(className, schema, conn) { + conn = conn || this._client; + 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]; + return conn.task(t => { + return this._ensureSchemaCollectionExists(t).then(() => conn.none(qs, values)).catch(error => { + if (error.code === PostgresDuplicateRelationError) { + // Table already exists, must have been created by a different request. Ignore error. + } else { + throw error; + } + }); + }).then(() => { + return conn.tx('create-relation-tables', t => { + const queries = relations.map(fieldName => { + return t.none('CREATE TABLE IF NOT EXISTS $ ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', { joinTable: `_Join:${fieldName}:${className}` }); + }); + return t.batch(queries); + }); + }); + } + + addFieldIfNotExists(className, fieldName, type) { + // TODO: Must be revised for invalid logic... + debug('addFieldIfNotExists', { className, fieldName, type }); + return this._client.tx('add-field-if-not-exists', t => { + let promise = Promise.resolve(); + if (type.type !== 'Relation') { + promise = t.none('ALTER TABLE $ ADD COLUMN $ $', { + className, + fieldName, + postgresType: parseTypeToPostgresType(type) + }).catch(error => { + if (error.code === PostgresRelationDoesNotExistError) { + return this.createClass(className, { fields: { [fieldName]: type } }); + } else if (error.code === PostgresDuplicateColumnError) { + // Column already exists, created by other request. Carry on to + // See if it's the right type. + } else { + throw error; + } + }); + } else { + promise = t.none('CREATE TABLE IF NOT EXISTS $ ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', { joinTable: `_Join:${fieldName}:${className}` }); + } + return promise.then(() => { + return t.any('SELECT "schema" FROM "_SCHEMA" WHERE "className" = $ and ("schema"::json->\'fields\'->$) is not null', { className, fieldName }); + }).then(result => { + if (result[0]) { + throw "Attempted to add a field that already exists"; + } else { + const path = `{fields,${fieldName}}`; + return t.none('UPDATE "_SCHEMA" SET "schema"=jsonb_set("schema", $, $) WHERE "className"=$', { path, type, className }); + } + }); + }); + } + + // Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.) + // and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible. + deleteClass(className) { + const operations = [{ query: `DROP TABLE IF EXISTS $1:name`, values: [className] }, { query: `DELETE FROM "_SCHEMA" WHERE "className" = $1`, values: [className] }]; + return this._client.tx(t => t.none(this._pgp.helpers.concat(operations))).then(() => className.indexOf('_Join:') != 0); // resolves with false when _Join table + } + + // Delete all data known to this adapter. Used for testing. + deleteAllClasses() { + const now = new Date().getTime(); + debug('deleteAllClasses'); + return this._client.any('SELECT * FROM "_SCHEMA"').then(results => { + const joins = results.reduce((list, schema) => { + return list.concat(joinTablesForSchema(schema.schema)); + }, []); + const classes = ['_SCHEMA', '_PushStatus', '_JobStatus', '_JobSchedule', '_Hooks', '_GlobalConfig', '_Audience', ...results.map(result => result.className), ...joins]; + return this._client.tx(t => t.batch(classes.map(className => t.none('DROP TABLE IF EXISTS $', { className })))); + }, error => { + if (error.code === PostgresRelationDoesNotExistError) { + // No _SCHEMA collection. Don't delete anything. + return; + } else { + throw error; + } + }).then(() => { + debug(`deleteAllClasses done in ${new Date().getTime() - now}`); + }); + } + + // Remove the column and all the data. For Relations, the _Join collection is handled + // specially, this function does not delete _Join columns. It should, however, indicate + // that the relation fields does not exist anymore. In mongo, this means removing it from + // the _SCHEMA collection. There should be no actual data in the collection under the same name + // as the relation column, so it's fine to attempt to delete it. If the fields listed to be + // deleted do not exist, this function should return successfully anyways. Checking for + // attempts to delete non-existent fields is the responsibility of Parse Server. + + // This function is not obligated to delete fields atomically. It is given the field + // names in a list so that databases that are capable of deleting fields atomically + // may do so. + + // Returns a Promise. + deleteFields(className, schema, fieldNames) { + debug('deleteFields', className, fieldNames); + return Promise.resolve().then(() => { + 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'); + + const doBatch = t => { + const batch = [t.none('UPDATE "_SCHEMA" SET "schema"=$ WHERE "className"=$', { schema, className })]; + if (values.length > 1) { + batch.push(t.none(`ALTER TABLE $1:name DROP COLUMN ${columns}`, values)); + } + return batch; + }; + return this._client.tx(t => { + return t.batch(doBatch(t)); + }); + }); + } + + // 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._ensureSchemaCollectionExists().then(() => this._client.map('SELECT * FROM "_SCHEMA"', null, row => _extends({ className: row.className }, row.schema))).then(res => res.map(toParseSchema)); + } + + // Return a promise for the schema with the given name, in Parse format. If + // this adapter doesn't know about the schema, return a promise that rejects with + // undefined as the reason. + getClass(className) { + debug('getClass', className); + return this._client.any('SELECT * FROM "_SCHEMA" WHERE "className"=$', { className }).then(result => { + if (result.length === 1) { + return result[0].schema; + } else { + throw undefined; + } + }).then(toParseSchema); + } + + // TODO: remove the mongo format dependency in the return value + createObject(className, schema, object) { + 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); + return this._client.none(qs, values).then(() => ({ ops: [object] })).catch(error => { + if (error.code === PostgresUniqueIndexViolationError) { + const err = new _node2.default.Error(_node2.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] }; + } + } + throw err; + } else { + throw error; + } + }); + } + + // 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) { + debug('deleteObjectsByQuery', className, query); + const values = [className]; + const index = 2; + const where = buildWhereClause({ schema, index, query }); + values.push(...where.values); + if (Object.keys(query).length === 0) { + where.pattern = 'TRUE'; + } + const qs = `WITH deleted AS (DELETE FROM $1:name WHERE ${where.pattern} RETURNING *) SELECT count(*) FROM deleted`; + debug(qs, values); + return this._client.one(qs, values, a => +a.count).then(count => { + if (count === 0) { + throw new _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } else { + return count; + } + }).catch(error => { + if (error.code === PostgresRelationDoesNotExistError) { + // Don't delete anything if doesn't exist + } else { + throw error; + } + }); + } + // Return value not currently well specified. + findOneAndUpdate(className, schema, query, update) { + debug('findOneAndUpdate', className, query, update); + return this.updateObjectsByQuery(className, schema, query, update).then(val => val[0]); + } + + // Apply the update to all objects that match the given Parse Query. + updateObjectsByQuery(className, schema, query, update) { + debug('updateObjectsByQuery', className, query, update); + const updatePatterns = []; + const values = [className]; + let index = 2; + schema = toPostgresSchema(schema); + + const originalUpdate = _extends({}, update); + 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]; + 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 + return originalUpdate[k].__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 + return originalUpdate[k].__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'`; + }, ''); + + updatePatterns.push(`$${index}:name = ( COALESCE($${index}:name, '{}'::jsonb) ${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[]`); + } else { + let type = 'text'; + for (const elt of fieldValue) { + if (typeof elt == 'object') { + type = 'json'; + break; + } + } + updatePatterns.push(`$${index}:name = array_to_json($${index + 1}::${type}[])::jsonb`); + } + values.push(fieldName, fieldValue); + index += 2; + } else { + debug('Not supported update', fieldName, fieldValue); + return Promise.reject(new _node2.default.Error(_node2.default.Error.OPERATION_FORBIDDEN, `Postgres doesn't support update ${JSON.stringify(fieldValue)} yet`)); + } + } + + const where = buildWhereClause({ schema, index, query }); + values.push(...where.values); + + const whereClause = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const qs = `UPDATE $1:name SET ${updatePatterns.join(',')} ${whereClause} RETURNING *`; + debug('update: ', qs, values); + return this._client.any(qs, values); + } + + // Hopefully, we can get rid of this. It's only used for config and hooks. + upsertOneObject(className, schema, query, update) { + debug('upsertOneObject', { className, query, update }); + const createValue = Object.assign({}, query, update); + return this.createObject(className, schema, createValue).catch(err => { + // ignore duplicate value errors as it's upsert + if (err.code === _node2.default.Error.DUPLICATE_VALUE) { + return this.findOneAndUpdate(className, schema, query, update); + } + throw err; + }); + } + + find(className, schema, query, { skip, limit, sort, keys }) { + debug('find', className, query, { skip, limit, sort, keys }); + const hasLimit = limit !== undefined; + const hasSkip = skip !== undefined; + let values = [className]; + const where = buildWhereClause({ schema, query, index: 2 }); + values.push(...where.values); + + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const limitPattern = hasLimit ? `LIMIT $${values.length + 1}` : ''; + if (hasLimit) { + values.push(limit); + } + const skipPattern = hasSkip ? `OFFSET $${values.length + 1}` : ''; + if (hasSkip) { + values.push(skip); + } + + let sortPattern = ''; + if (sort) { + const sorting = Object.keys(sort).map(key => { + // Using $idx pattern gives: non-integer constant in ORDER BY + if (sort[key] === 1) { + return `"${key}" ASC`; + } + return `"${key}" 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 + keys = keys.filter(key => { + return key.length > 0; + }); + 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(err => { + // Query on non existing table, don't crash + if (err.code === PostgresRelationDoesNotExistError) { + return []; + } + return Promise.reject(err); + }).then(results => results.map(object => this.postgresObjectToParseObject(className, object, schema))); + } + + // Converts from a postgres-format object to a REST-format object. + // Does not strip out anything based on a lack of authentication. + postgresObjectToParseObject(className, object, schema) { + Object.keys(schema.fields).forEach(fieldName => { + if (schema.fields[fieldName].type === 'Pointer' && object[fieldName]) { + object[fieldName] = { objectId: object[fieldName], __type: 'Pointer', className: schema.fields[fieldName].targetClass }; + } + if (schema.fields[fieldName].type === 'Relation') { + object[fieldName] = { + __type: "Relation", + className: schema.fields[fieldName].targetClass + }; + } + if (object[fieldName] && schema.fields[fieldName].type === 'GeoPoint') { + object[fieldName] = { + __type: "GeoPoint", + latitude: object[fieldName].y, + longitude: object[fieldName].x + }; + } + if (object[fieldName] && schema.fields[fieldName].type === 'Polygon') { + let coords = object[fieldName]; + coords = coords.substr(2, coords.length - 4).split('),('); + coords = coords.map(point => { + return [parseFloat(point.split(',')[1]), parseFloat(point.split(',')[0])]; + }); + object[fieldName] = { + __type: "Polygon", + coordinates: coords + }; + } + if (object[fieldName] && schema.fields[fieldName].type === 'File') { + object[fieldName] = { + __type: 'File', + name: object[fieldName] + }; + } + }); + //TODO: remove this reliance on the mongo format. DB adapter shouldn't know there is a difference between created at and any other date field. + if (object.createdAt) { + object.createdAt = object.createdAt.toISOString(); + } + if (object.updatedAt) { + object.updatedAt = object.updatedAt.toISOString(); + } + if (object.expiresAt) { + object.expiresAt = { __type: 'Date', iso: object.expiresAt.toISOString() }; + } + if (object._email_verify_token_expires_at) { + object._email_verify_token_expires_at = { __type: 'Date', iso: object._email_verify_token_expires_at.toISOString() }; + } + if (object._account_lockout_expires_at) { + object._account_lockout_expires_at = { __type: 'Date', iso: object._account_lockout_expires_at.toISOString() }; + } + if (object._perishable_token_expires_at) { + object._perishable_token_expires_at = { __type: 'Date', iso: object._perishable_token_expires_at.toISOString() }; + } + if (object._password_changed_at) { + object._password_changed_at = { __type: 'Date', iso: object._password_changed_at.toISOString() }; + } + + for (const fieldName in object) { + if (object[fieldName] === null) { + delete object[fieldName]; + } + if (object[fieldName] instanceof Date) { + object[fieldName] = { __type: 'Date', iso: object[fieldName].toISOString() }; + } + } + + return object; + } + + // Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't + // currently know which fields are nullable and which aren't, we ignore that criteria. + // As such, we shouldn't expose this function to users of parse until we have an out-of-band + // Way of determining if a field is nullable. Undefined doesn't count against uniqueness, + // which is why we use sparse indexes. + ensureUniqueness(className, schema, fieldNames) { + // Use the same name for every ensureUniqueness attempt, because postgres + // Will happily create the same index with multiple names. + const constraintName = `unique_${fieldNames.sort().join('_')}`; + const constraintPatterns = fieldNames.map((fieldName, index) => `$${index + 3}:name`); + const qs = `ALTER TABLE $1:name ADD CONSTRAINT $2:name UNIQUE (${constraintPatterns.join(',')})`; + return this._client.none(qs, [className, constraintName, ...fieldNames]).catch(error => { + if (error.code === PostgresDuplicateRelationError && error.message.includes(constraintName)) { + // Index already exists. Ignore error. + } else if (error.code === PostgresUniqueIndexViolationError && error.message.includes(constraintName)) { + // Cast the error into the proper parse error + throw new _node2.default.Error(_node2.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided'); + } else { + throw error; + } + }); + } + + // Executes a count. + count(className, schema, query) { + debug('count', className, query); + const values = [className]; + const where = buildWhereClause({ schema, query, index: 2 }); + values.push(...where.values); + + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const qs = `SELECT count(*) FROM $1:name ${wherePattern}`; + return this._client.one(qs, values, a => +a.count).catch(err => { + if (err.code === PostgresRelationDoesNotExistError) { + return 0; + } + throw err; + }); + } + + distinct(className, schema, query, fieldName) { + debug('distinct', className, query); + let field = fieldName; + let column = fieldName; + if (fieldName.indexOf('.') >= 0) { + field = transformDotFieldToComponents(fieldName).join('->'); + column = fieldName.split('.')[0]; + } + const isArrayField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array'; + const values = [field, column, className]; + const where = buildWhereClause({ schema, query, index: 4 }); + values.push(...where.values); + + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + let qs = `SELECT DISTINCT ON ($1:raw) $2:raw FROM $3:name ${wherePattern}`; + if (isArrayField) { + qs = `SELECT distinct jsonb_array_elements($1:raw) as $2:raw FROM $3:name ${wherePattern}`; + } + debug(qs, values); + return this._client.any(qs, values).catch(() => []).then(results => { + if (fieldName.indexOf('.') === -1) { + return results.map(object => object[field]); + } + const child = fieldName.split('.')[1]; + return results.map(object => object[column][child]); + }).then(results => results.map(object => this.postgresObjectToParseObject(className, object, schema))); + } + + aggregate(className, schema, pipeline) { + debug('aggregate', className, pipeline); + const values = [className]; + let columns = []; + let countField = 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') { + columns.push(`${transformAggregateField(value)} AS "objectId"`); + groupPattern = `GROUP BY ${transformAggregateField(value)}`; + continue; + } + if (value.$sum) { + if (typeof value.$sum === 'string') { + columns.push(`SUM(${transformAggregateField(value.$sum)}) AS "${field}"`); + } else { + countField = field; + columns.push(`COUNT(*) AS "${field}"`); + } + } + if (value.$max) { + columns.push(`MAX(${transformAggregateField(value.$max)}) AS "${field}"`); + } + if (value.$min) { + columns.push(`MIN(${transformAggregateField(value.$min)}) AS "${field}"`); + } + if (value.$avg) { + columns.push(`AVG(${transformAggregateField(value.$avg)}) AS "${field}"`); + } + } + columns.join(','); + } 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(field); + } + } + } + if (stage.$match) { + const patterns = []; + for (const field in stage.$match) { + const value = stage.$match[field]; + Object.keys(ParseToPosgresComparator).forEach(cmp => { + if (value[cmp]) { + const pgComparator = ParseToPosgresComparator[cmp]; + patterns.push(`${field} ${pgComparator} ${value[cmp]}`); + } + }); + } + wherePattern = patterns.length > 0 ? `WHERE ${patterns.join(' ')}` : ''; + } + if (stage.$limit) { + limitPattern = `LIMIT ${stage.$limit}`; + } + if (stage.$skip) { + skipPattern = `OFFSET ${stage.$skip}`; + } + if (stage.$sort) { + const sort = stage.$sort; + const sorting = Object.keys(sort).map(key => { + if (sort[key] === 1) { + return `"${key}" ASC`; + } + return `"${key}" DESC`; + }).join(','); + sortPattern = sort !== undefined && Object.keys(sort).length > 0 ? `ORDER BY ${sorting}` : ''; + } + } + + const qs = `SELECT ${columns} FROM $1:name ${wherePattern} ${sortPattern} ${limitPattern} ${skipPattern} ${groupPattern}`; + debug(qs, values); + return this._client.any(qs, values).then(results => results.map(object => this.postgresObjectToParseObject(className, object, schema))).then(results => { + if (countField) { + results[0][countField] = parseInt(results[0][countField], 10); + } + results.forEach(result => { + if (!result.hasOwnProperty('objectId')) { + result.objectId = null; + } + }); + return results; + }); + } + + performInitialization({ VolatileClassesSchemas }) { + debug('performInitialization'); + const promises = VolatileClassesSchemas.map(schema => { + return this.createTable(schema.className, schema).catch(err => { + if (err.code === PostgresDuplicateRelationError || err.code === _node2.default.Error.INVALID_CLASS_NAME) { + return Promise.resolve(); + } + throw err; + }); + }); + return Promise.all(promises).then(() => { + return this._client.tx(t => { + return t.batch([t.none(_sql2.default.misc.jsonObjectSetKeys), t.none(_sql2.default.array.add), t.none(_sql2.default.array.addUnique), t.none(_sql2.default.array.remove), t.none(_sql2.default.array.containsAll), t.none(_sql2.default.array.contains)]); + }); + }).then(data => { + debug(`initializationDone in ${data.duration}`); + }).catch(error => { + /* eslint-disable no-console */ + console.error(error); + }); + } + + createIndexes(className, indexes, conn) { + return (conn || this._client).tx(t => t.batch(indexes.map(i => { + return t.none('CREATE INDEX $1:name ON $2:name ($3:name)', [i.name, className, i.key]); + }))); + } + + dropIndexes(className, indexes, conn) { + return (conn || this._client).tx(t => t.batch(indexes.map(i => t.none('DROP INDEX $1:name', i)))); + } + + getIndexes(className) { + const qs = 'SELECT * FROM pg_indexes WHERE tablename = ${className}'; + return this._client.any(qs, { className }); + } + + updateSchemaWithIndexes() { + return Promise.resolve(); + } +} + +exports.PostgresStorageAdapter = PostgresStorageAdapter; +function convertPolygonToSQL(polygon) { + if (polygon.length < 3) { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.INTERNAL_SERVER_ERROR, 'GeoJSON: Loop must have at least 3 different vertices'); + } + const points = polygon.map(point => { + _node2.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/gmi, '$1') + // remove lines starting with a comment + .replace(/^#.*\n/gmi, '') + // remove non escaped whitespace + .replace(/([^\\])\s+/gmi, '$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 createLiteralRegex(remaining) { + return remaining.split('').map(c => { + if (c.match(/[0-9a-zA-Z]/) !== 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`); +} + +exports.default = PostgresStorageAdapter; + +module.exports = PostgresStorageAdapter; // Required for tests \ 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.sql b/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql new file mode 100644 index 0000000000..24355bc732 --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql @@ -0,0 +1,11 @@ +CREATE OR REPLACE FUNCTION array_contains_all( + "array" jsonb, + "values" jsonb +) + RETURNS boolean + LANGUAGE sql + IMMUTABLE + STRICT +AS $function$ + SELECT RES.CNT = jsonb_array_length("values") 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/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..c1b31b93ac --- /dev/null +++ b/lib/Adapters/Storage/Postgres/sql/index.js @@ -0,0 +1,32 @@ +'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'), + 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; +} \ 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/Auth.js b/lib/Auth.js new file mode 100644 index 0000000000..2520d1dba1 --- /dev/null +++ b/lib/Auth.js @@ -0,0 +1,221 @@ +'use strict'; + +var Parse = require('parse/node').Parse; +var RestQuery = require('./RestQuery'); + +// 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, isMaster = false, isReadOnly = false, user, installationId } = {}) { + this.config = config; + 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.couldUpdateUserId = function (userId) { + if (this.isMaster) { + return true; + } + if (this.user && this.user.id === userId) { + return true; + } + return false; +}; + +// 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 +var getAuthForSessionToken = function ({ config, sessionToken, installationId } = {}) { + return config.cacheController.user.get(sessionToken).then(userJSON => { + if (userJSON) { + const cachedUser = Parse.Object.fromJSON(userJSON); + return Promise.resolve(new Auth({ config, isMaster: false, installationId, user: cachedUser })); + } + + var restOptions = { + limit: 1, + include: 'user' + }; + + var query = new RestQuery(config, master(config), '_Session', { sessionToken }, restOptions); + return query.execute().then(response => { + var results = response.results; + if (results.length !== 1 || !results[0]['user']) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + } + + var 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.'); + } + var obj = results[0]['user']; + delete obj.password; + obj['className'] = '_User'; + obj['sessionToken'] = sessionToken; + config.cacheController.user.put(sessionToken, obj); + const userObject = Parse.Object.fromJSON(obj); + return new Auth({ config, isMaster: false, installationId, user: userObject }); + }); + }); +}; + +var getAuthForLegacySessionToken = function ({ config, sessionToken, installationId } = {}) { + var restOptions = { + limit: 1 + }; + var query = new RestQuery(config, master(config), '_User', { sessionToken: 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; +}; + +// Iterates through the role tree and compiles a users roles +Auth.prototype._loadRoles = function () { + var cacheAdapter = this.config.cacheController; + return cacheAdapter.role.get(this.user.id).then(cachedRoles => { + if (cachedRoles != null) { + this.fetchedRoles = true; + this.userRoles = cachedRoles; + return Promise.resolve(cachedRoles); + } + + var restWhere = { + 'users': { + __type: 'Pointer', + className: '_User', + objectId: this.user.id + } + }; + // First get the role ids this user is directly a member of + var query = new RestQuery(this.config, master(this.config), '_Role', restWhere, {}); + return query.execute().then(response => { + var results = response.results; + if (!results.length) { + this.userRoles = []; + this.fetchedRoles = true; + this.rolePromise = null; + + cacheAdapter.role.put(this.user.id, Array(...this.userRoles)); + return Promise.resolve(this.userRoles); + } + var rolesMap = results.reduce((m, r) => { + m.names.push(r.name); + m.ids.push(r.objectId); + return m; + }, { ids: [], names: [] }); + + // run the recursive finding + return this._getAllRolesNamesForRoleIds(rolesMap.ids, rolesMap.names).then(roleNames => { + this.userRoles = roleNames.map(r => { + return 'role:' + r; + }); + this.fetchedRoles = true; + this.rolePromise = null; + cacheAdapter.role.put(this.user.id, Array(...this.userRoles)); + return Promise.resolve(this.userRoles); + }); + }); + }); +}; + +// 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 => { + return queriedRoles[roleID] !== true; + }).map(roleID => { + // mark as queried + queriedRoles[roleID] = true; + return { + __type: 'Pointer', + className: '_Role', + objectId: roleID + }; + }); + + // all roles are accounted for, return the names + if (ins.length == 0) { + return Promise.resolve([...new Set(names)]); + } + // Build an OR query across all parentRoles + let restWhere; + if (ins.length == 1) { + restWhere = { 'roles': ins[0] }; + } else { + restWhere = { 'roles': { '$in': ins } }; + } + const query = new RestQuery(this.config, master(this.config), '_Role', restWhere, {}); + return query.execute().then(response => { + var results = response.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)]); + }); +}; + +module.exports = { + Auth, + master, + nobody, + readOnly, + getAuthForSessionToken, + getAuthForLegacySessionToken +}; \ No newline at end of file diff --git a/lib/ClientSDK.js b/lib/ClientSDK.js new file mode 100644 index 0000000000..6e029ceb07 --- /dev/null +++ b/lib/ClientSDK.js @@ -0,0 +1,42 @@ +'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 +}; \ No newline at end of file diff --git a/lib/Config.js b/lib/Config.js new file mode 100644 index 0000000000..71c74906e1 --- /dev/null +++ b/lib/Config.js @@ -0,0 +1,292 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Config = undefined; + +var _cache = require('./cache'); + +var _cache2 = _interopRequireDefault(_cache); + +var _SchemaCache = require('./Controllers/SchemaCache'); + +var _SchemaCache2 = _interopRequireDefault(_SchemaCache); + +var _DatabaseController = require('./Controllers/DatabaseController'); + +var _DatabaseController2 = _interopRequireDefault(_DatabaseController); + +var _net = require('net'); + +var _net2 = _interopRequireDefault(_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 = _cache2.default.get(applicationId); + if (!cacheInfo) { + return; + } + const config = new Config(); + config.applicationId = applicationId; + Object.keys(cacheInfo).forEach(key => { + if (key == 'databaseController') { + const schemaCache = new _SchemaCache2.default(cacheInfo.cacheController, cacheInfo.schemaCacheTTL, cacheInfo.enableSingleSchemaCache); + config.database = new _DatabaseController2.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); + _cache2.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 + }) { + + 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); + } + + 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 (!_net2.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.'; + } + } + + 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; +exports.default = Config; + +module.exports = Config; \ No newline at end of file diff --git a/lib/Controllers/AdaptableController.js b/lib/Controllers/AdaptableController.js new file mode 100644 index 0000000000..c782269d77 --- /dev/null +++ b/lib/Controllers/AdaptableController.js @@ -0,0 +1,86 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AdaptableController = undefined; + +var _Config = require("../Config"); + +var _Config2 = _interopRequireDefault(_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 _Config2.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; +exports.default = AdaptableController; \ No newline at end of file diff --git a/lib/Controllers/AnalyticsController.js b/lib/Controllers/AnalyticsController.js new file mode 100644 index 0000000000..a54cf91666 --- /dev/null +++ b/lib/Controllers/AnalyticsController.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AnalyticsController = undefined; + +var _AdaptableController = require('./AdaptableController'); + +var _AdaptableController2 = _interopRequireDefault(_AdaptableController); + +var _AnalyticsAdapter = require('../Adapters/Analytics/AnalyticsAdapter'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AnalyticsController extends _AdaptableController2.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; +exports.default = AnalyticsController; \ No newline at end of file diff --git a/lib/Controllers/CacheController.js b/lib/Controllers/CacheController.js new file mode 100644 index 0000000000..5b0466cbb0 --- /dev/null +++ b/lib/Controllers/CacheController.js @@ -0,0 +1,91 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CacheController = exports.SubCache = undefined; + +var _AdaptableController = require('./AdaptableController'); + +var _AdaptableController2 = _interopRequireDefault(_AdaptableController); + +var _CacheAdapter = require('../Adapters/Cache/CacheAdapter'); + +var _CacheAdapter2 = _interopRequireDefault(_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 _AdaptableController2.default { + + constructor(adapter, appId, options = {}) { + super(adapter, appId, options); + + this.role = new SubCache('role', this); + this.user = new SubCache('user', 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 _CacheAdapter2.default; + } +} + +exports.CacheController = CacheController; +exports.default = CacheController; \ No newline at end of file diff --git a/lib/Controllers/DatabaseController.js b/lib/Controllers/DatabaseController.js new file mode 100644 index 0000000000..30c9d24fde --- /dev/null +++ b/lib/Controllers/DatabaseController.js @@ -0,0 +1,1016 @@ +'use strict'; + +var _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; }; + +var _node = require('parse/node'); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _intersect = require('intersect'); + +var _intersect2 = _interopRequireDefault(_intersect); + +var _deepcopy = require('deepcopy'); + +var _deepcopy2 = _interopRequireDefault(_deepcopy); + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +var _SchemaController = require('./SchemaController'); + +var SchemaController = _interopRequireWildcard(_SchemaController); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } // A database adapter that works with data exported from the hosted +// Parse database. + +function addWriteACL(query, acl) { + const newQuery = _lodash2.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 = _lodash2.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', '_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); + + /* In MongoDB, $or queries which are not alone at the top level of the + * query can not make efficient use of indexes due to a long standing + * bug known as SERVER-13732. + * + * This block restructures queries in which $or is not the sole top + * level element by moving all other top-level predicates inside every + * subdocument of the $or predicate, allowing MongoDB's query planner + * to make full use of the most relevant indexes. + * + * EG: {$or: [{a: 1}, {a: 2}], b: 2} + * Becomes: {$or: [{a: 1, b: 2}, {a: 2, b: 2}]} + * + * The only exceptions are $near and $nearSphere operators, which are + * constrained to only 1 operator per query. As a result, these ops + * remain at the top level + * + * https://jira.mongodb.org/browse/SERVER-13732 + * https://github.com/parse-community/parse-server/issues/3767 + */ + Object.keys(query).forEach(key => { + const noCollisions = !query.$or.some(subq => subq.hasOwnProperty(key)); + let hasNears = false; + if (query[key] != null && typeof query[key] == 'object') { + hasNears = '$near' in query[key] || '$nearSphere' in query[key]; + } + if (key != '$or' && noCollisions && !hasNears) { + query.$or.forEach(subquery => { + subquery[key] = query[key]; + }); + delete query[key]; + } + }); + query.$or.forEach(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.'); + } + } + + 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}`); + } + }); +}; + +function DatabaseController(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; +} + +DatabaseController.prototype.collectionExists = function (className) { + return this.adapter.classExists(className); +}; + +DatabaseController.prototype.purgeCollection = function (className) { + return this.loadSchema().then(schemaController => schemaController.getOneSchema(className)).then(schema => this.adapter.deleteObjectsByQuery(className, schema, {})); +}; + +DatabaseController.prototype.validateClassName = function (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. +DatabaseController.prototype.loadSchema = function (options = { clearCache: false }) { + if (!this.schemaPromise) { + this.schemaPromise = SchemaController.load(this.adapter, this.schemaCache, options); + this.schemaPromise.then(() => delete this.schemaPromise, () => delete this.schemaPromise); + } + return this.schemaPromise; +}; + +// Returns a promise for the classname that is related to the given +// classname through the key. +// TODO: make this not in the DatabaseController interface +DatabaseController.prototype.redirectClassNameForKey = function (className, key) { + return this.loadSchema().then(schema => { + var t = schema.getExpectedType(className, key); + if (t && t.type == 'Relation') { + return t.targetClass; + } else { + 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. +DatabaseController.prototype.validateObject = function (className, object, query, { acl }) { + let schema; + const isMaster = acl === undefined; + var aclGroup = acl || []; + return this.loadSchema().then(s => { + schema = s; + if (isMaster) { + return Promise.resolve(); + } + return this.canAddField(schema, className, object, aclGroup); + }).then(() => { + return schema.validateObject(className, object, query); + }); +}; + +// Filters out any data that shouldn't be on this REST-formatted object. +const filterSensitiveData = (isMaster, aclGroup, className, object) => { + if (className !== '_User') { + 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; + + 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; +}; + +DatabaseController.prototype.update = function (className, query, update, { + acl, + many, + upsert +} = {}, skipSanitization = false) { + const originalQuery = query; + const originalUpdate = update; + // Make a copy of the object, so we don't mutate the incoming data. + update = (0, _deepcopy2.default)(update); + var relationUpdates = []; + var isMaster = acl === undefined; + var aclGroup = acl || []; + return this.loadSchema().then(schemaController => { + return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'update')).then(() => { + relationUpdates = this.collectRelationUpdates(className, originalQuery.objectId, update); + if (!isMaster) { + query = this.addPointerPermissions(schemaController, className, 'update', query, aclGroup); + } + if (!query) { + return Promise.resolve(); + } + if (acl) { + query = addWriteACL(query, acl); + } + validateQuery(query); + 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}`); + } + fieldName = fieldName.split('.')[0]; + if (!SchemaController.fieldNameIsValid(fieldName) && !isSpecialUpdateKey(fieldName)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Invalid field name for update: ${fieldName}`); + } + }); + for (const updateOperation in update) { + if (Object.keys(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 (many) { + return this.adapter.updateObjectsByQuery(className, schema, query, update); + } else if (upsert) { + return this.adapter.upsertOneObject(className, schema, query, update); + } else { + return this.adapter.findOneAndUpdate(className, schema, query, update); + } + }); + }).then(result => { + if (!result) { + return Promise.reject(new _node.Parse.Error(_node.Parse.Error.OBJECT_NOT_FOUND, 'Object not found.')); + } + return this.handleRelationUpdates(className, originalQuery.objectId, update, relationUpdates).then(() => { + return result; + }); + }).then(result => { + if (skipSanitization) { + return Promise.resolve(result); + } + return sanitizeDatabaseResult(originalUpdate, result); + }); + }); +}; + +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); +} + +// Collect all relation-updating operations from a REST-format update. +// Returns a list of all relation updates to perform +// This mutates update. +DatabaseController.prototype.collectRelationUpdates = function (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 +DatabaseController.prototype.handleRelationUpdates = function (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. +const relationSchema = { fields: { relatedId: { type: 'String' }, owningId: { type: 'String' } } }; +DatabaseController.prototype.addRelation = function (key, fromClassName, fromId, toId) { + const doc = { + relatedId: toId, + owningId: fromId + }; + return this.adapter.upsertOneObject(`_Join:${key}:${fromClassName}`, relationSchema, doc, doc); +}; + +// Removes a relation. +// Returns a promise that resolves successfully iff the remove was +// successful. +DatabaseController.prototype.removeRelation = function (key, fromClassName, fromId, toId) { + var doc = { + relatedId: toId, + owningId: fromId + }; + return this.adapter.deleteObjectsByQuery(`_Join:${key}:${fromClassName}`, relationSchema, doc).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. +DatabaseController.prototype.destroy = function (className, query, { acl } = {}) { + const isMaster = acl === undefined; + const aclGroup = acl || []; + + return this.loadSchema().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)).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; + }); + }); + }); +}; + +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; + } +}; + +// Inserts an object into the database. +// Returns a promise that resolves successfully iff the object saved. +DatabaseController.prototype.create = function (className, object, { acl } = {}) { + // 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.loadSchema()).then(schemaController => { + return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'create')).then(() => schemaController.enforceClassExists(className)).then(() => schemaController.reloadData()).then(() => schemaController.getOneSchema(className, true)).then(schema => { + transformAuthData(className, object, schema); + flattenUpdateOperatorsForCreate(object); + return this.adapter.createObject(className, SchemaController.convertSchemaToAdapterSchema(schema), object); + }).then(result => { + return this.handleRelationUpdates(className, null, object, relationUpdates).then(() => { + return sanitizeDatabaseResult(originalObject, result.ops[0]); + }); + }); + }); +}; + +DatabaseController.prototype.canAddField = function (schema, className, object, aclGroup) { + const classSchema = schema.data[className]; + if (!classSchema) { + return Promise.resolve(); + } + const fields = Object.keys(object); + const schemaFields = Object.keys(classSchema); + const newKeys = fields.filter(field => { + return schemaFields.indexOf(field) < 0; + }); + if (newKeys.length > 0) { + return schema.validatePermission(className, aclGroup, 'addField'); + } + return Promise.resolve(); +}; + +// Won't delete collections in the system namespace +// Returns a promise. +DatabaseController.prototype.deleteEverything = function () { + this.schemaPromise = null; + return Promise.all([this.adapter.deleteAllClasses(), this.schemaCache.clear()]); +}; + +// Returns a promise for a list of related ids given an owning id. +// className here is the owning className. +DatabaseController.prototype.relatedIds = function (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. +DatabaseController.prototype.owningIds = function (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 +DatabaseController.prototype.reduceInRelation = function (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 +DatabaseController.prototype.reduceRelationKeys = function (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); + }); + } +}; + +DatabaseController.prototype.addInObjectIdsIds = function (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; + + 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 = _intersect2.default.big(allIds); + } else { + idsIntersection = (0, _intersect2.default)(allIds); + } + + // Need to make sure we don't clobber existing shorthand $eq constraints on objectId. + if (!('objectId' in query)) { + query.objectId = {}; + } else if (typeof query.objectId === 'string') { + query.objectId = { + $eq: query.objectId + }; + } + query.objectId['$in'] = idsIntersection; + + return query; +}; + +DatabaseController.prototype.addNotInObjectIdsIds = function (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 = {}; + } else if (typeof query.objectId === 'string') { + query.objectId = { + $eq: query.objectId + }; + } + + query.objectId['$nin'] = allIds; + return query; +}; + +// Runs a query on the database. +// Returns a promise that resolves to a list of items. +// Options: +// skip number of results to skip. +// limit limit to this number of results. +// sort an object where keys are the fields to sort by. +// the value is +1 for ascending, -1 for descending. +// count run a count instead of returning results. +// acl restrict this operation with an ACL for the provided array +// of user objectIds and roles. acl: null means no user. +// when this field is not present, don't do anything regarding ACLs. +// TODO: make userIds not needed here. The db adapter shouldn't know +// anything about users, ideally. Then, improve the format of the ACL +// arg to work like the others. +DatabaseController.prototype.find = function (className, query, { + skip, + limit, + acl, + sort = {}, + count, + keys, + op, + distinct, + pipeline, + readPreference +} = {}) { + 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.loadSchema().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; + } + 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}`); + } + if (!SchemaController.fieldNameIsValid(fieldName)) { + throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}.`); + } + }); + const queryOptions = { skip, limit, sort, keys, readPreference }; + return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, op)).then(() => this.reduceRelationKeys(className, query, queryOptions)).then(() => this.reduceInRelation(className, query, schemaController)).then(() => { + if (!isMaster) { + query = this.addPointerPermissions(schemaController, className, op, query, aclGroup); + } + if (!query) { + if (op == 'get') { + throw new _node.Parse.Error(_node.Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } else { + return []; + } + } + if (!isMaster) { + query = addReadACL(query, aclGroup); + } + validateQuery(query); + if (count) { + if (!classExists) { + return 0; + } else { + return this.adapter.count(className, schema, query, readPreference); + } + } else if (distinct) { + if (!classExists) { + return []; + } else { + return this.adapter.distinct(className, schema, query, distinct); + } + } else if (pipeline) { + if (!classExists) { + return []; + } else { + return this.adapter.aggregate(className, schema, pipeline, readPreference); + } + } else { + if (!classExists) { + return []; + } else { + return this.adapter.find(className, schema, query, queryOptions).then(objects => objects.map(object => { + object = untransformObjectACL(object); + return filterSensitiveData(isMaster, aclGroup, className, object); + })).catch(error => { + throw new _node.Parse.Error(_node.Parse.Error.INTERNAL_SERVER_ERROR, error); + }); + } + } + }); + }); + }); +}; + +// 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; +}; + +DatabaseController.prototype.deleteSchema = function (className) { + return this.loadSchema(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: {} })).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)))); + } else { + return Promise.resolve(); + } + }); + }); +}; + +DatabaseController.prototype.addPointerPermissions = function (schema, className, operation, query, aclGroup = []) { + // Check if class has public permission for operation + // If the BaseCLP pass, let go through + if (schema.testBaseCLP(className, aclGroup, operation)) { + return query; + } + const perms = schema.perms[className]; + const field = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields'; + const userACL = aclGroup.filter(acl => { + return acl.indexOf('role:') != 0 && acl != '*'; + }); + // the ACL should have exactly 1 user + if (perms && perms[field] && perms[field].length > 0) { + // No user set return undefined + // If the length is > 1, that means we didn't de-dupe users correctly + if (userACL.length != 1) { + return; + } + const userId = userACL[0]; + const userPointer = { + "__type": "Pointer", + "className": "_User", + "objectId": userId + }; + + const permFields = perms[field]; + const ors = permFields.map(key => { + const q = { + [key]: userPointer + }; + // if we already have a constraint on the key, use the $and + if (query.hasOwnProperty(key)) { + return { '$and': [q, query] }; + } + // otherwise just add the constaint + return Object.assign({}, query, { + [`${key}`]: userPointer + }); + }); + if (ors.length > 1) { + return { '$or': ors }; + } + return ors[0]; + } else { + return query; + } +}; + +// 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. +DatabaseController.prototype.performInitialization = function () { + const requiredUserFields = { fields: _extends({}, SchemaController.defaultColumns._Default, SchemaController.defaultColumns._User) }; + const requiredRoleFields = { fields: _extends({}, 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 => { + _logger2.default.warn('Unable to ensure uniqueness for usernames: ', error); + throw error; + }); + + const emailUniqueness = userClassPromise.then(() => this.adapter.ensureUniqueness('_User', requiredUserFields, ['email'])).catch(error => { + _logger2.default.warn('Unable to ensure uniqueness for user email addresses: ', error); + throw error; + }); + + const roleUniqueness = roleClassPromise.then(() => this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name'])).catch(error => { + _logger2.default.warn('Unable to ensure uniqueness for role name: ', error); + throw error; + }); + + const indexPromise = this.adapter.updateSchemaWithIndexes(); + + // Create tables for volatile classes + const adapterInit = this.adapter.performInitialization({ VolatileClassesSchemas: SchemaController.VolatileClassesSchemas }); + return Promise.all([usernameUniqueness, emailUniqueness, roleUniqueness, adapterInit, indexPromise]); +}; + +function joinTableName(className, key) { + return `_Join:${key}:${className}`; +} + +// Expose validateQuery for tests +DatabaseController._validateQuery = validateQuery; +module.exports = DatabaseController; \ No newline at end of file diff --git a/lib/Controllers/FilesController.js b/lib/Controllers/FilesController.js new file mode 100644 index 0000000000..8cbfc6596f --- /dev/null +++ b/lib/Controllers/FilesController.js @@ -0,0 +1,108 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FilesController = undefined; + +var _cryptoUtils = require('../cryptoUtils'); + +var _AdaptableController = require('./AdaptableController'); + +var _AdaptableController2 = _interopRequireDefault(_AdaptableController); + +var _FilesAdapter = require('../Adapters/Files/FilesAdapter'); + +var _path = require('path'); + +var _path2 = _interopRequireDefault(_path); + +var _mime = require('mime'); + +var _mime2 = _interopRequireDefault(_mime); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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}-.*"); // FilesController.js +class FilesController extends _AdaptableController2.default { + + getFileData(config, filename) { + return this.adapter.getFileData(filename); + } + + createFile(config, filename, data, contentType) { + + const extname = _path2.default.extname(filename); + + const hasExtension = extname.length > 0; + + if (!hasExtension && contentType && _mime2.default.getExtension(contentType)) { + filename = filename + '.' + _mime2.default.getExtension(contentType); + } else if (hasExtension && !contentType) { + contentType = _mime2.default.getType(filename); + } + + filename = (0, _cryptoUtils.randomHexString)(32) + '_' + filename; + + var 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; + } + + getFileStream(config, filename) { + return this.adapter.getFileStream(filename); + } +} + +exports.FilesController = FilesController; +exports.default = FilesController; \ No newline at end of file diff --git a/lib/Controllers/HooksController.js b/lib/Controllers/HooksController.js new file mode 100644 index 0000000000..94a9fa8054 --- /dev/null +++ b/lib/Controllers/HooksController.js @@ -0,0 +1,237 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.HooksController = undefined; + +var _triggers = require("../triggers"); + +var triggers = _interopRequireWildcard(_triggers); + +var _node = require("parse/node"); + +var Parse = _interopRequireWildcard(_node); + +var _request = require("request"); + +var request = _interopRequireWildcard(_request); + +var _logger = require("../logger"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +/** weak */ + +const DefaultHooksCollectionName = "_Hooks"; + +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 }, 1).then(results => results[0]); + } + + getFunctions() { + return this._getHooks({ functionName: { $exists: true } }); + } + + getTrigger(className, triggerName) { + return this._getHooks({ className: className, triggerName: triggerName }, 1).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, res) => { + 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 = { + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(jsonBody) + }; + + if (key) { + jsonRequest.headers['X-Parse-Webhook-Key'] = key; + } else { + _logger.logger.warn('Making outgoing webhook request without webhookKey being set!'); + } + + request.post(hook.url, jsonRequest, function (err, httpResponse, body) { + var result; + 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) { + return res.error(err); + } else if (hook.triggerName === 'beforeSave') { + if (typeof result === 'object') { + delete result.createdAt; + delete result.updatedAt; + } + return res.success({ object: result }); + } else { + return res.success(result); + } + }); + }; +} + +exports.default = HooksController; \ No newline at end of file diff --git a/lib/Controllers/LiveQueryController.js b/lib/Controllers/LiveQueryController.js new file mode 100644 index 0000000000..7ccd287d5e --- /dev/null +++ b/lib/Controllers/LiveQueryController.js @@ -0,0 +1,58 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.LiveQueryController = undefined; + +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) { + if (!this.hasLiveQuery(className)) { + return; + } + const req = this._makePublisherRequest(currentObject, originalObject); + this.liveQueryPublisher.onCloudCodeAfterSave(req); + } + + onAfterDelete(className, currentObject, originalObject) { + if (!this.hasLiveQuery(className)) { + return; + } + const req = this._makePublisherRequest(currentObject, originalObject); + this.liveQueryPublisher.onCloudCodeAfterDelete(req); + } + + hasLiveQuery(className) { + return this.classNames.has(className); + } + + _makePublisherRequest(currentObject, originalObject) { + const req = { + object: currentObject + }; + if (currentObject) { + req.original = originalObject; + } + return req; + } +} + +exports.LiveQueryController = LiveQueryController; +exports.default = LiveQueryController; \ No newline at end of file diff --git a/lib/Controllers/LoggerController.js b/lib/Controllers/LoggerController.js new file mode 100644 index 0000000000..cafd1825ae --- /dev/null +++ b/lib/Controllers/LoggerController.js @@ -0,0 +1,243 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.LoggerController = exports.LogOrder = exports.LogLevel = undefined; + +var _node = require('parse/node'); + +var _AdaptableController = require('./AdaptableController'); + +var _AdaptableController2 = _interopRequireDefault(_AdaptableController); + +var _LoggerAdapter = require('../Adapters/Logger/LoggerAdapter'); + +var _url = require('url'); + +var _url2 = _interopRequireDefault(_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 = exports.LogLevel = { + INFO: 'info', + ERROR: 'error' +}; + +const LogOrder = exports.LogOrder = { + DESCENDING: 'desc', + ASCENDING: 'asc' +}; + +const logLevels = ['error', 'warn', 'info', 'debug', 'verbose', 'silly']; + +class LoggerController extends _AdaptableController2.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 password = _url2.default.parse(urlString, true).query.password; + + if (password) { + urlString = urlString.replace('password=' + password, 'password=********'); + } + return urlString; + } + + 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; +exports.default = LoggerController; \ No newline at end of file diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js new file mode 100644 index 0000000000..89599094ba --- /dev/null +++ b/lib/Controllers/PushController.js @@ -0,0 +1,212 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PushController = undefined; + +var _node = require('parse/node'); + +var _RestQuery = require('../RestQuery'); + +var _RestQuery2 = _interopRequireDefault(_RestQuery); + +var _RestWrite = require('../RestWrite'); + +var _RestWrite2 = _interopRequireDefault(_RestWrite); + +var _Auth = require('../Auth'); + +var _StatusHandler = require('../StatusHandler'); + +var _utils = require('../Push/utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class PushController { + + sendPush(body = {}, where = {}, config, auth, onPushStatusSaved = () => {}, now = new Date()) { + if (!config.hasPushSupport) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Missing push configuration'); + } + + // Replace the expiration_time and push_time with a valid Unix epoch milliseconds time + body.expiration_time = PushController.getExpirationTime(body); + body.expiration_interval = PushController.getExpirationInterval(body); + if (body.expiration_time && body.expiration_interval) { + throw new _node.Parse.Error(_node.Parse.Error.PUSH_MISCONFIGURED, 'Both expiration_time and expiration_interval cannot be set'); + } + + // Immediate push + if (body.expiration_interval && !body.hasOwnProperty('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 (Number(badge)) { + restUpdate = { badge: badge }; + } else { + throw "Invalid value for badge, expected number or 'Increment'"; + } + + // 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 _RestQuery2.default(config, (0, _Auth.master)(config), '_Installation', updateWhere); + return restQuery.buildRestWhere().then(() => { + const write = new _RestWrite2.default(config, (0, _Auth.master)(config), '_Installation', restQuery.restWhere, restUpdate); + write.runOptions.many = true; + return write.execute(); + }); + }; + } + const pushStatus = (0, _StatusHandler.pushStatusHandler)(config); + return Promise.resolve().then(() => { + return pushStatus.setInitial(body, where); + }).then(() => { + onPushStatusSaved(pushStatus.objectId); + return badgeUpdate(); + }).then(() => { + // Update audience lastUsed and timesUsed + if (body.audience_id) { + const audienceId = body.audience_id; + + var updateAudience = { + lastUsed: { __type: "Date", iso: new Date().toISOString() }, + timesUsed: { __op: "Increment", "amount": 1 } + }; + const write = new _RestWrite2.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 (body.hasOwnProperty('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 = body.hasOwnProperty('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 = body.hasOwnProperty('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 = body.hasOwnProperty('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; +exports.default = PushController; \ No newline at end of file diff --git a/lib/Controllers/SchemaCache.js b/lib/Controllers/SchemaCache.js new file mode 100644 index 0000000000..67982c4287 --- /dev/null +++ b/lib/Controllers/SchemaCache.js @@ -0,0 +1,96 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _cryptoUtils = require("../cryptoUtils"); + +var _defaults = require("../defaults"); + +var _defaults2 = _interopRequireDefault(_defaults); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const MAIN_SCHEMA = "__MAIN_SCHEMA"; +const SCHEMA_CACHE_PREFIX = "__SCHEMA"; +const ALL_KEYS = "__ALL_KEYS"; + +class SchemaCache { + + constructor(cacheController, ttl = _defaults2.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); + } + } + + put(key, value) { + return this.cache.get(this.prefix + ALL_KEYS).then(allKeys => { + allKeys = allKeys || {}; + allKeys[key] = true; + return Promise.all([this.cache.put(this.prefix + ALL_KEYS, allKeys, this.ttl), this.cache.put(key, value, this.ttl)]); + }); + } + + 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.put(this.prefix + MAIN_SCHEMA, schema); + } + + setOneSchema(className, schema) { + if (!this.ttl) { + return Promise.resolve(null); + } + return this.put(this.prefix + className, schema); + } + + getOneSchema(className) { + if (!this.ttl) { + return Promise.resolve(null); + } + return this.cache.get(this.prefix + className).then(schema => { + if (schema) { + return Promise.resolve(schema); + } + return this.cache.get(this.prefix + MAIN_SCHEMA).then(cachedSchemas => { + cachedSchemas = cachedSchemas || []; + schema = cachedSchemas.find(cachedSchema => { + return cachedSchema.className === className; + }); + if (schema) { + return Promise.resolve(schema); + } + return Promise.resolve(null); + }); + }); + } + + clear() { + // That clears all caches... + return this.cache.get(this.prefix + ALL_KEYS).then(allKeys => { + if (!allKeys) { + return; + } + const promises = Object.keys(allKeys).map(key => { + return this.cache.del(key); + }); + return Promise.all(promises); + }); + } +} +exports.default = SchemaCache; \ No newline at end of file diff --git a/lib/Controllers/SchemaController.js b/lib/Controllers/SchemaController.js new file mode 100644 index 0000000000..643956669f --- /dev/null +++ b/lib/Controllers/SchemaController.js @@ -0,0 +1,1048 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _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; }; + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +// 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. +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' } + }, + _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' } + } +}); + +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']); + +const volatileClasses = Object.freeze(['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig', '_JobSchedule', '_Audience', '_ExportProgress']); + +// 10 alpha numberic chars + uppercase +const userIdRegex = /^[a-zA-Z0-9]{10}$/; +// Anything that start with role +const roleRegex = /^role:.*/; +// * permission +const publicRegex = /^\*$/; + +const requireAuthenticationRegex = /^requiresAuthentication$/; + +const permissionKeyRegex = Object.freeze([userIdRegex, roleRegex, publicRegex, requireAuthenticationRegex]); + +function verifyPermissionKey(key) { + const result = permissionKeyRegex.reduce((isGood, regEx) => { + isGood = isGood || key.match(regEx) != null; + return isGood; + }, false); + if (!result) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid key for class level permissions`); + } +} + +const CLPValidKeys = Object.freeze(['find', 'count', 'get', 'create', 'update', 'delete', 'addField', 'readUserFields', 'writeUserFields']); +function validateCLP(perms, fields) { + if (!perms) { + return; + } + Object.keys(perms).forEach(operation => { + if (CLPValidKeys.indexOf(operation) == -1) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `${operation} is not a valid operation for class level permissions`); + } + + if (operation === 'readUserFields' || operation === 'writeUserFields') { + if (!Array.isArray(perms[operation])) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${perms[operation]}' is not a valid value for class level permissions ${operation}`); + } else { + perms[operation].forEach(key => { + if (!fields[key] || fields[key].type != 'Pointer' || fields[key].targetClass != '_User') { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid column for class level pointer permissions ${operation}`); + } + }); + } + return; + } + + Object.keys(perms[operation]).forEach(key => { + verifyPermissionKey(key); + const perm = perms[operation][key]; + if (perm !== true) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${perm}' is not a valid value for class level permissions ${operation}:${key}:${perm}`); + } + }); + }); +} +const joinClassRegex = /^_Join:[A-Za-z0-9_]+:[A-Za-z0-9_]+/; +const classAndFieldRegex = /^[A-Za-z][A-Za-z0-9_]*$/; +function classNameIsValid(className) { + // Valid classes must: + return ( + // Be one of _User, _Installation, _Role, _Session OR + systemClasses.indexOf(className) > -1 || + // Be a join table OR + joinClassRegex.test(className) || + // Include only alpha-numeric and underscores, and not start with an underscore or number + fieldNameIsValid(className) + ); +} + +// Valid fields must be alpha-numeric, and not start with an underscore or number +function fieldNameIsValid(fieldName) { + return classAndFieldRegex.test(fieldName); +} + +// Checks that it's not trying to clobber one of the default fields of the class. +function fieldNameIsValidForClass(fieldName, className) { + if (!fieldNameIsValid(fieldName)) { + return false; + } + if (defaultColumns._Default[fieldName]) { + return false; + } + if (defaultColumns[className] && defaultColumns[className][fieldName]) { + return false; + } + return true; +} + +function invalidClassNameMessage(className) { + return 'Invalid classname: ' + className + ', classnames can only have alphanumeric characters and _, and must start with an alpha character '; +} + +const invalidJsonError = new Parse.Error(Parse.Error.INVALID_JSON, "invalid JSON"); +const validNonRelationOrPointerTypes = ['Number', 'String', 'Boolean', 'Date', 'Object', 'Array', 'GeoPoint', 'File', 'Bytes', 'Polygon']; +// Returns an error suitable for throwing if the type is invalid +const fieldTypeIsInvalid = ({ type, targetClass }) => { + if (['Pointer', 'Relation'].indexOf(type) >= 0) { + if (!targetClass) { + return new Parse.Error(135, `type ${type} needs a class name`); + } else if (typeof targetClass !== 'string') { + return invalidJsonError; + } else if (!classNameIsValid(targetClass)) { + return new Parse.Error(Parse.Error.INVALID_CLASS_NAME, invalidClassNameMessage(targetClass)); + } else { + return undefined; + } + } + if (typeof type !== 'string') { + return invalidJsonError; + } + if (validNonRelationOrPointerTypes.indexOf(type) < 0) { + return new Parse.Error(Parse.Error.INCORRECT_TYPE, `invalid field type: ${type}`); + } + return undefined; +}; + +const convertSchemaToAdapterSchema = schema => { + schema = injectDefaultSchema(schema); + delete schema.fields.ACL; + schema.fields._rperm = { type: 'Array' }; + schema.fields._wperm = { type: 'Array' }; + + if (schema.className === '_User') { + delete schema.fields.password; + schema.fields._hashed_password = { type: 'String' }; + } + + return schema; +}; + +const convertAdapterSchemaToParseSchema = (_ref) => { + let schema = _objectWithoutProperties(_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; +}; + +const injectDefaultSchema = ({ className, fields, classLevelPermissions, indexes }) => { + const defaultSchema = { + className, + fields: _extends({}, 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 _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 +})); +const VolatileClassesSchemas = [_HooksSchema, _JobStatusSchema, _JobScheduleSchema, _PushStatusSchema, _GlobalConfigSchema, _AudienceSchema]; + +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 (type.targetClass) { + return `${type.type}<${type.targetClass}>`; + } + return `${type.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.data[className][fieldName] tells you the type of that field, in mongo format + this.data = {}; + // this.perms[className][operation] tells you the acl-style permissions + this.perms = {}; + // this.indexes[className][operation] tells you the indexes + this.indexes = {}; + } + + reloadData(options = { clearCache: false }) { + let promise = Promise.resolve(); + if (options.clearCache) { + promise = promise.then(() => { + return this._cache.clear(); + }); + } + if (this.reloadDataPromise && !options.clearCache) { + return this.reloadDataPromise; + } + this.reloadDataPromise = promise.then(() => { + return this.getAllClasses(options); + }).then(allSchemas => { + const data = {}; + const perms = {}; + const indexes = {}; + allSchemas.forEach(schema => { + data[schema.className] = injectDefaultSchema(schema).fields; + perms[schema.className] = schema.classLevelPermissions; + indexes[schema.className] = schema.indexes; + }); + + // Inject the in-memory classes + volatileClasses.forEach(className => { + const schema = injectDefaultSchema({ className }); + data[className] = schema.fields; + perms[className] = schema.classLevelPermissions; + indexes[className] = schema.indexes; + }); + this.data = data; + this.perms = perms; + this.indexes = indexes; + delete this.reloadDataPromise; + }, err => { + this.data = {}; + this.perms = {}; + this.indexes = {}; + delete this.reloadDataPromise; + throw err; + }); + return this.reloadDataPromise; + } + + getAllClasses(options = { clearCache: false }) { + let promise = Promise.resolve(); + if (options.clearCache) { + promise = this._cache.clear(); + } + return promise.then(() => { + return this._cache.getAllClasses(); + }).then(allClasses => { + if (allClasses && allClasses.length && !options.clearCache) { + return Promise.resolve(allClasses); + } + return this._dbAdapter.getAllClasses().then(allSchemas => allSchemas.map(injectDefaultSchema)).then(allSchemas => { + return this._cache.setAllClasses(allSchemas).then(() => { + 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) { + return Promise.resolve({ + className, + fields: this.data[className], + classLevelPermissions: this.perms[className], + indexes: this.indexes[className] + }); + } + return this._cache.getOneSchema(className).then(cached => { + if (cached && !options.clearCache) { + return Promise.resolve(cached); + } + return this._dbAdapter.getClass(className).then(injectDefaultSchema).then(result => { + return this._cache.setOneSchema(className, result).then(() => { + return result; + }); + }); + }); + }); + } + + // 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) { + return Promise.reject(validationError); + } + + return this._dbAdapter.createClass(className, convertSchemaToAdapterSchema({ fields, classLevelPermissions, indexes, className })).then(convertAdapterSchemaToParseSchema).then(res => { + return this._cache.clear().then(() => { + return Promise.resolve(res); + }); + }).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 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); + } + 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(() => this.setPermissions(className, classLevelPermissions, newSchema)).then(() => this._dbAdapter.setIndexesWithSchemaFormat(className, indexes, schema.indexes, newSchema)).then(() => this.reloadData({ clearCache: true })) + //TODO: Move this logic into the database adapter + .then(() => { + const reloadedSchema = { + className: className, + fields: this.data[className], + classLevelPermissions: this.perms[className] + }; + if (this.indexes[className] && Object.keys(this.indexes[className]).length !== 0) { + reloadedSchema.indexes = this.indexes[className]; + } + 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.data[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.data[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.data[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 error = fieldTypeIsInvalid(fields[fieldName]); + if (error) return { code: error.code, error: error.message }; + } + } + + for (const fieldName in defaultColumns[className]) { + fields[fieldName] = defaultColumns[className][fieldName]; + } + + const geoPoints = Object.keys(fields).filter(key => fields[key] && fields[key].type === 'GeoPoint'); + if (geoPoints.length > 1) { + return { + code: Parse.Error.INCORRECT_TYPE, + error: 'currently, only one GeoPoint field may exist in an object. Adding ' + geoPoints[1] + ' when ' + geoPoints[0] + ' already exists.' + }; + } + validateCLP(classLevelPermissions, fields); + } + + // Sets the Class-level permissions for a given className, which must exist. + setPermissions(className, perms, newSchema) { + if (typeof perms === 'undefined') { + return Promise.resolve(); + } + validateCLP(perms, newSchema); + return this._dbAdapter.setClassLevelPermissions(className, perms); + } + + // Returns a promise that resolves successfully to the new schema + // object if the provided className-fieldName-type tuple is valid. + // The className must already be validated. + // If 'freeze' is true, refuse to update the schema for this field. + enforceFieldExists(className, fieldName, type) { + if (fieldName.indexOf(".") > 0) { + // subdocument key (x.y) => ok if x is of type 'object' + fieldName = fieldName.split(".")[0]; + type = 'Object'; + } + if (!fieldNameIsValid(fieldName)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}.`); + } + + // If someone tries to create a new field with null/undefined as the value, return; + if (!type) { + return Promise.resolve(this); + } + + return this.reloadData().then(() => { + const expectedType = this.getExpectedType(className, fieldName); + if (typeof type === 'string') { + type = { type }; + } + + 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 this; + } + + return this._dbAdapter.addFieldIfNotExists(className, fieldName, type).then(() => { + // The update succeeded. Reload the schema + return this.reloadData({ clearCache: true }); + }, 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 this.reloadData({ clearCache: true }); + }).then(() => { + // Ensure that the schema now validates + if (!dbTypeMatchesObjectType(this.getExpectedType(className, fieldName), type)) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `Could not add field ${fieldName}`); + } + // Remove the cached schema + this._cache.clear(); + return this; + }); + }); + } + + // 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 = _extends({}, 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. + validateObject(className, object, query) { + let geocount = 0; + let promise = this.enforceClassExists(className); + 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.then(() => { + 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; + } + + promise = promise.then(schema => schema.enforceFieldExists(className, fieldName, expected)); + } + promise = thenValidateRequiredColumns(promise, className, object, query); + return promise; + } + + // 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); + } + + // Validates the base CLP for an operation + testBaseCLP(className, aclGroup, operation) { + if (!this.perms[className] || !this.perms[className][operation]) { + return true; + } + const classPerms = this.perms[className]; + const perms = classPerms[operation]; + // Handle the public scenario quickly + 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 + validatePermission(className, aclGroup, operation) { + + if (this.testBaseCLP(className, aclGroup, operation)) { + return Promise.resolve(); + } + + if (!this.perms[className] || !this.perms[className][operation]) { + return true; + } + const classPerms = this.perms[className]; + const perms = classPerms[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(classPerms[permissionField]) && classPerms[permissionField].length > 0) { + return Promise.resolve(); + } + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, `Permission denied for action ${operation} on class ${className}.`); + } + + // Returns the expected type for a className+key combination + // or undefined if the schema is not set + getExpectedType(className, fieldName) { + if (this.data && this.data[className]) { + const expectedType = this.data[className][fieldName]; + return expectedType === 'map' ? 'Object' : expectedType; + } + return undefined; + } + + // Checks if a given class is in the schema. + hasClass(className) { + return this.reloadData().then(() => !!this.data[className]); + } +} + +exports.default = SchemaController; // Returns a promise for a new Schema. + +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. +function buildMergedSchemaObject(existingFields, putRequest) { + const newSchema = {}; + 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'; +} + +exports.load = load; +exports.classNameIsValid = classNameIsValid; +exports.fieldNameIsValid = fieldNameIsValid; +exports.invalidClassNameMessage = invalidClassNameMessage; +exports.buildMergedSchemaObject = buildMergedSchemaObject; +exports.systemClasses = systemClasses; +exports.defaultColumns = defaultColumns; +exports.convertSchemaToAdapterSchema = convertSchemaToAdapterSchema; +exports.VolatileClassesSchemas = VolatileClassesSchemas; \ No newline at end of file diff --git a/lib/Controllers/UserController.js b/lib/Controllers/UserController.js new file mode 100644 index 0000000000..898ebaa770 --- /dev/null +++ b/lib/Controllers/UserController.js @@ -0,0 +1,259 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.UserController = undefined; + +var _cryptoUtils = require('../cryptoUtils'); + +var _triggers = require('../triggers'); + +var _AdaptableController = require('./AdaptableController'); + +var _AdaptableController2 = _interopRequireDefault(_AdaptableController); + +var _MailAdapter = require('../Adapters/Email/MailAdapter'); + +var _MailAdapter2 = _interopRequireDefault(_MailAdapter); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var RestQuery = require('../RestQuery'); +var Auth = require('../Auth'); + +class UserController extends _AdaptableController2.default { + + constructor(adapter, appId, options = {}) { + super(adapter, appId, options); + } + + validateAdapter(adapter) { + // Allow no adapter + if (!adapter && !this.shouldVerifyEmails) { + return; + } + super.validateAdapter(adapter); + } + + expectedAdapterType() { + return _MailAdapter2.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 = _node2.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: _node2.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 _rest2.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 undefined; + } + + 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)); + } + }); + } + + resendVerificationEmail(username) { + return this.getUserIfNeeded({ username: username }).then(aUser => { + if (!aUser || aUser.emailVerified) { + throw undefined; + } + this.setEmailVerifyToken(aUser); + return this.config.database.update('_User', { username }, 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 = _node2.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)) + // clear reset password token + .then(() => this.config.database.update('_User', { username }, { + _perishable_token: { __op: 'Delete' }, + _perishable_token_expires_at: { __op: 'Delete' } + })).catch(error => { + if (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 }; + } +} + +exports.UserController = UserController; // Mark this private + +function updateUserPassword(userId, password, config) { + return _rest2.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}`; + } +} + +exports.default = UserController; \ No newline at end of file diff --git a/lib/Controllers/index.js b/lib/Controllers/index.js new file mode 100644 index 0000000000..2d2a6dfb88 --- /dev/null +++ b/lib/Controllers/index.js @@ -0,0 +1,282 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getControllers = getControllers; +exports.getLoggerController = getLoggerController; +exports.getFilesController = getFilesController; +exports.getUserController = getUserController; +exports.getCacheController = getCacheController; +exports.getAnalyticsController = getAnalyticsController; +exports.getLiveQueryController = getLiveQueryController; +exports.getDatabaseController = getDatabaseController; +exports.getHooksController = getHooksController; +exports.getPushController = getPushController; +exports.getAuthDataManager = getAuthDataManager; +exports.getDatabaseAdapter = getDatabaseAdapter; + +var _Auth = require('../Adapters/Auth'); + +var _Auth2 = _interopRequireDefault(_Auth); + +var _Options = require('../Options'); + +var _AdapterLoader = require('../Adapters/AdapterLoader'); + +var _defaults = require('../defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +var _url = require('url'); + +var _url2 = _interopRequireDefault(_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 = require('./DatabaseController'); + +var _DatabaseController2 = _interopRequireDefault(_DatabaseController); + +var _SchemaCache = require('./SchemaCache'); + +var _SchemaCache2 = _interopRequireDefault(_SchemaCache); + +var _GridStoreAdapter = require('../Adapters/Files/GridStoreAdapter'); + +var _WinstonLoggerAdapter = require('../Adapters/Logger/WinstonLoggerAdapter'); + +var _InMemoryCacheAdapter = require('../Adapters/Cache/InMemoryCacheAdapter'); + +var _AnalyticsAdapter = require('../Adapters/Analytics/AnalyticsAdapter'); + +var _MongoStorageAdapter = require('../Adapters/Storage/Mongo/MongoStorageAdapter'); + +var _MongoStorageAdapter2 = _interopRequireDefault(_MongoStorageAdapter); + +var _PostgresStorageAdapter = require('../Adapters/Storage/Postgres/PostgresStorageAdapter'); + +var _PostgresStorageAdapter2 = _interopRequireDefault(_PostgresStorageAdapter); + +var _pushAdapter = require('@parse/push-adapter'); + +var _pushAdapter2 = _interopRequireDefault(_pushAdapter); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: 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); + return { + loggerController, + filesController, + userController, + pushController, + hasPushScheduledSupport, + hasPushSupport, + pushWorker, + pushControllerQueue, + analyticsController, + cacheController, + liveQueryController, + databaseController, + hooksController, + authDataManager + }; +} + +// Adapters + +// Controllers +function getLoggerController(options) { + const { + appId, + jsonLogs, + logsFolder, + verbose, + logLevel, + silent, + loggerAdapter + } = options; + const loggerOptions = { jsonLogs, logsFolder, verbose, logLevel, silent }; + const loggerControllerAdapter = (0, _AdapterLoader.loadAdapter)(loggerAdapter, _WinstonLoggerAdapter.WinstonLoggerAdapter, loggerOptions); + return new _LoggerController.LoggerController(loggerControllerAdapter, appId, loggerOptions); +} + +function getFilesController(options) { + const { + appId, + databaseURI, + filesAdapter, + databaseAdapter + } = 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 _GridStoreAdapter.GridStoreAdapter(databaseURI); + }); + return new _FilesController.FilesController(filesControllerAdapter, appId); +} + +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 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 !== _defaults2.default.databaseURI || collectionPrefix !== _defaults2.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 _DatabaseController2.default(databaseAdapter, new _SchemaCache2.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, _pushAdapter2.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, _Auth2.default)(auth, enableAnonymousUsers); +} + +function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions) { + let protocol; + try { + const parsedURI = _url2.default.parse(databaseURI); + protocol = parsedURI.protocol ? parsedURI.protocol.toLowerCase() : null; + } catch (e) {/* */} + switch (protocol) { + case 'postgres:': + return new _PostgresStorageAdapter2.default({ + uri: databaseURI, + collectionPrefix, + databaseOptions + }); + default: + return new _MongoStorageAdapter2.default({ + uri: databaseURI, + collectionPrefix, + mongoOptions: databaseOptions + }); + } +} \ No newline at end of file diff --git a/lib/LiveQuery/Client.js b/lib/LiveQuery/Client.js new file mode 100644 index 0000000000..dc97207772 --- /dev/null +++ b/lib/LiveQuery/Client.js @@ -0,0 +1,97 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Client = undefined; + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const dafaultFields = ['className', 'objectId', 'updatedAt', 'createdAt', 'ACL']; + +class Client { + + constructor(id, parseWebSocket, hasMasterKey) { + this.id = id; + this.parseWebSocket = parseWebSocket; + this.hasMasterKey = hasMasterKey; + 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) { + _logger2.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) { + const response = { + 'op': type, + 'clientId': this.id + }; + 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); + } + 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; \ No newline at end of file diff --git a/lib/LiveQuery/Id.js b/lib/LiveQuery/Id.js new file mode 100644 index 0000000000..72fb66d6a6 --- /dev/null +++ b/lib/LiveQuery/Id.js @@ -0,0 +1,22 @@ +'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; \ No newline at end of file diff --git a/lib/LiveQuery/ParseCloudCodePublisher.js b/lib/LiveQuery/ParseCloudCodePublisher.js new file mode 100644 index 0000000000..cbc1c691bf --- /dev/null +++ b/lib/LiveQuery/ParseCloudCodePublisher.js @@ -0,0 +1,50 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseCloudCodePublisher = undefined; + +var _ParsePubSub = require('./ParsePubSub'); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_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(_node2.default.applicationId + 'afterSave', request); + } + + onCloudCodeAfterDelete(request) { + this._onCloudCodeMessage(_node2.default.applicationId + 'afterDelete', request); + } + + // Request is the request object from cloud code functions. request.object is a ParseObject. + _onCloudCodeMessage(type, request) { + _logger2.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; \ No newline at end of file diff --git a/lib/LiveQuery/ParseLiveQueryServer.js b/lib/LiveQuery/ParseLiveQueryServer.js new file mode 100644 index 0000000000..30188195ee --- /dev/null +++ b/lib/LiveQuery/ParseLiveQueryServer.js @@ -0,0 +1,580 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseLiveQueryServer = undefined; + +var _tv = require('tv4'); + +var _tv2 = _interopRequireDefault(_tv); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _Subscription = require('./Subscription'); + +var _Client = require('./Client'); + +var _ParseWebSocketServer = require('./ParseWebSocketServer'); + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +var _RequestSchema = require('./RequestSchema'); + +var _RequestSchema2 = _interopRequireDefault(_RequestSchema); + +var _QueryTools = require('./QueryTools'); + +var _ParsePubSub = require('./ParsePubSub'); + +var _SessionTokenCache = require('./SessionTokenCache'); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _uuid = require('uuid'); + +var _uuid2 = _interopRequireDefault(_uuid); + +var _triggers = require('../triggers'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class ParseLiveQueryServer { + // className -> (queryHash -> subscription) + constructor(server, config) { + this.server = server; + this.clients = new Map(); + this.subscriptions = new Map(); + + config = config || {}; + + // 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]); + } + _logger2.default.verbose('Support key pairs', this.keyPairs); + + // Initialize Parse + _node2.default.Object.disableSingleInstance(); + + const serverURL = config.serverURL || _node2.default.serverURL; + _node2.default.serverURL = serverURL; + const appId = config.appId || _node2.default.applicationId; + const javascriptKey = _node2.default.javaScriptKey; + const masterKey = config.masterKey || _node2.default.masterKey; + _node2.default.initialize(appId, javascriptKey, masterKey); + + // Initialize websocket server + this.parseWebSocketServer = new _ParseWebSocketServer.ParseWebSocketServer(server, parseWebsocket => this._onConnect(parseWebsocket), config.websocketTimeout); + + // Initialize subscriber + this.subscriber = _ParsePubSub.ParsePubSub.createSubscriber(config); + this.subscriber.subscribe(_node2.default.applicationId + 'afterSave'); + this.subscriber.subscribe(_node2.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) => { + _logger2.default.verbose('Subscribe messsage %j', messageStr); + let message; + try { + message = JSON.parse(messageStr); + } catch (e) { + _logger2.default.error('unable to parse message', messageStr, e); + return; + } + this._inflateParseObject(message); + if (channel === _node2.default.applicationId + 'afterSave') { + this._onAfterSave(message); + } else if (channel === _node2.default.applicationId + 'afterDelete') { + this._onAfterDelete(message); + } else { + _logger2.default.error('Get message %s from unknown channel %j', message, channel); + } + }); + + // Initialize sessionToken cache + this.sessionTokenCache = new _SessionTokenCache.SessionTokenCache(config.cacheTimeout); + } + + // Message is the JSON object from publisher. Message.currentParseObject is the ParseObject JSON after changes. + // Message.originalParseObject is the original ParseObject JSON. + + // The subscriber we use to get object update from publisher + _inflateParseObject(message) { + // Inflate merged object + const currentParseObject = message.currentParseObject; + let className = currentParseObject.className; + let parseObject = new _node2.default.Object(className); + parseObject._finishFetch(currentParseObject); + message.currentParseObject = parseObject; + // Inflate original object + const originalParseObject = message.originalParseObject; + if (originalParseObject) { + className = originalParseObject.className; + parseObject = new _node2.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) { + _logger2.default.verbose(_node2.default.applicationId + 'afterDelete is triggered'); + + const deletedParseObject = message.currentParseObject.toJSON(); + const className = deletedParseObject.className; + _logger2.default.verbose('ClassName: %j | ObjectId: %s', className, deletedParseObject.id); + _logger2.default.verbose('Current client number : %d', this.clients.size); + + const classSubscriptions = this.subscriptions.get(className); + if (typeof classSubscriptions === 'undefined') { + _logger2.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 _lodash2.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 ACL + this._matchesACL(acl, client, requestId).then(isMatched => { + if (!isMatched) { + return null; + } + client.pushDelete(requestId, deletedParseObject); + }, error => { + _logger2.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) { + _logger2.default.verbose(_node2.default.applicationId + 'afterSave is triggered'); + + let originalParseObject = null; + if (message.originalParseObject) { + originalParseObject = message.originalParseObject.toJSON(); + } + const currentParseObject = message.currentParseObject.toJSON(); + const className = currentParseObject.className; + _logger2.default.verbose('ClassName: %s | ObjectId: %s', className, currentParseObject.id); + _logger2.default.verbose('Current client number : %d', this.clients.size); + + const classSubscriptions = this.subscriptions.get(className); + if (typeof classSubscriptions === 'undefined') { + _logger2.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 _lodash2.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 = _node2.default.Promise.as(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 = _node2.default.Promise.as(false); + } else { + const currentACL = message.currentParseObject.getACL(); + currentACLCheckingPromise = this._matchesACL(currentACL, client, requestId); + } + + _node2.default.Promise.when(originalACLCheckingPromise, currentACLCheckingPromise).then((isOriginalMatched, isCurrentMatched) => { + _logger2.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); + }, error => { + _logger2.default.error('Matching ACL error : ', error); + }); + } + } + } + } + + _onConnect(parseWebsocket) { + parseWebsocket.on('message', request => { + if (typeof request === 'string') { + try { + request = JSON.parse(request); + } catch (e) { + _logger2.default.error('unable to parse request', request, e); + return; + } + } + _logger2.default.verbose('Request: %j', request); + + // Check whether this request is a valid request, return error directly if not + if (!_tv2.default.validate(request, _RequestSchema2.default['general']) || !_tv2.default.validate(request, _RequestSchema2.default[request.op])) { + _Client.Client.pushError(parseWebsocket, 1, _tv2.default.error.message); + _logger2.default.error('Connect message error %s', _tv2.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'); + _logger2.default.error('Get unknown operation', request.op); + } + }); + + parseWebsocket.on('disconnect', () => { + _logger2.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}` + }); + _logger2.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 _lodash2.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); + } + } + + _logger2.default.verbose('Current clients %d', this.clients.size); + _logger2.default.verbose('Current subscriptions %d', this.subscriptions.size); + (0, _triggers.runLiveQueryEventHandlers)({ + event: 'ws_disconnect', + clients: this.clients.size, + subscriptions: this.subscriptions.size + }); + }); + + (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); + } + + _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 _node2.default.Promise.as(true); + } + // Check subscription sessionToken matches ACL first + const subscriptionInfo = client.getSubscriptionInfo(requestId); + if (typeof subscriptionInfo === 'undefined') { + return _node2.default.Promise.as(false); + } + + const subscriptionSessionToken = subscriptionInfo.sessionToken; + return this.sessionTokenCache.getUserId(subscriptionSessionToken).then(userId => { + return acl.getReadAccess(userId); + }).then(isSubscriptionSessionTokenMatched => { + if (isSubscriptionSessionTokenMatched) { + return _node2.default.Promise.as(true); + } + + // Check if the user has any roles that match the ACL + return new _node2.default.Promise((resolve, reject) => { + + // 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 resolve(false); + } + + this.sessionTokenCache.getUserId(subscriptionSessionToken).then(userId => { + + // Pass along a null if there is no user id + if (!userId) { + return _node2.default.Promise.as(null); + } + + // Prepare a user object to query for roles + // To eliminate a query for the user, create one locally with the id + var user = new _node2.default.User(); + user.id = userId; + return user; + }).then(user => { + + // Pass along an empty array (of roles) if no user + if (!user) { + return _node2.default.Promise.as([]); + } + + // Then get the user's roles + var rolesQuery = new _node2.default.Query(_node2.default.Role); + rolesQuery.equalTo("users", user); + return rolesQuery.find({ useMasterKey: true }); + }).then(roles => { + + // Finally, see if any of the user's roles allow them read access + for (const role of roles) { + if (acl.getRoleReadAccess(role)) { + return resolve(true); + } + } + resolve(false); + }).catch(error => { + reject(error); + }); + }); + }).then(isRoleMatched => { + + if (isRoleMatched) { + return _node2.default.Promise.as(true); + } + + // Check client sessionToken matches ACL + const clientSessionToken = client.sessionToken; + return this.sessionTokenCache.getUserId(clientSessionToken).then(userId => { + return acl.getReadAccess(userId); + }); + }).then(isMatched => { + return _node2.default.Promise.as(isMatched); + }, () => { + return _node2.default.Promise.as(false); + }); + } + + _handleConnect(parseWebsocket, request) { + if (!this._validateKeys(request, this.keyPairs)) { + _Client.Client.pushError(parseWebsocket, 4, 'Key in request is not valid'); + _logger2.default.error('Key in request is not valid'); + return; + } + const hasMasterKey = this._hasMasterKey(request, this.keyPairs); + const clientId = (0, _uuid2.default)(); + const client = new _Client.Client(clientId, parseWebsocket, hasMasterKey); + parseWebsocket.clientId = clientId; + this.clients.set(parseWebsocket.clientId, client); + _logger2.default.info(`Create new client: ${parseWebsocket.clientId}`); + client.pushConnect(); + (0, _triggers.runLiveQueryEventHandlers)({ + event: 'connect', + clients: this.clients.size, + subscriptions: this.subscriptions.size + }); + } + + _hasMasterKey(request, validKeyPairs) { + if (!validKeyPairs || validKeyPairs.size == 0 || !validKeyPairs.has("masterKey")) { + return false; + } + if (!request || !request.hasOwnProperty("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 (!parseWebsocket.hasOwnProperty('clientId')) { + _Client.Client.pushError(parseWebsocket, 2, 'Can not find this client, make sure you connect to server before subscribing'); + _logger2.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 and sessionToken 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); + + _logger2.default.verbose(`Create client ${parseWebsocket.clientId} new subscription: ${request.requestId}`); + _logger2.default.verbose('Current client number: %d', this.clients.size); + (0, _triggers.runLiveQueryEventHandlers)({ + event: 'subscribe', + clients: this.clients.size, + subscriptions: this.subscriptions.size + }); + } + + _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 (!parseWebsocket.hasOwnProperty('clientId')) { + _Client.Client.pushError(parseWebsocket, 2, 'Can not find this client, make sure you connect to server before unsubscribing'); + _logger2.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.'); + _logger2.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.'); + _logger2.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)({ + event: 'unsubscribe', + clients: this.clients.size, + subscriptions: this.subscriptions.size + }); + + if (!notifyClient) { + return; + } + + client.pushUnsubscribe(request.requestId); + + _logger2.default.verbose(`Delete client: ${parseWebsocket.clientId} | subscription: ${request.requestId}`); + } +} + +exports.ParseLiveQueryServer = ParseLiveQueryServer; \ No newline at end of file diff --git a/lib/LiveQuery/ParsePubSub.js b/lib/LiveQuery/ParsePubSub.js new file mode 100644 index 0000000000..6686db2607 --- /dev/null +++ b/lib/LiveQuery/ParsePubSub.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParsePubSub = undefined; + +var _AdapterLoader = require('../Adapters/AdapterLoader'); + +var _EventEmitterPubSub = require('../Adapters/PubSub/EventEmitterPubSub'); + +var _RedisPubSub = require('../Adapters/PubSub/RedisPubSub'); + +const 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); + } +}; + +exports.ParsePubSub = ParsePubSub; \ No newline at end of file diff --git a/lib/LiveQuery/ParseWebSocketServer.js b/lib/LiveQuery/ParseWebSocketServer.js new file mode 100644 index 0000000000..f59723886c --- /dev/null +++ b/lib/LiveQuery/ParseWebSocketServer.js @@ -0,0 +1,62 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseWebSocket = exports.ParseWebSocketServer = undefined; + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const typeMap = new Map([['disconnect', 'close']]); +const getWS = function () { + try { + return require('uws'); + } catch (e) { + return require('ws'); + } +}; + +class ParseWebSocketServer { + + constructor(server, onConnect, websocketTimeout = 10 * 1000) { + const WebSocketServer = getWS().Server; + const wss = new WebSocketServer({ server: server }); + wss.on('listening', () => { + _logger2.default.info('Parse LiveQuery Server starts running'); + }); + wss.on('connection', ws => { + onConnect(new ParseWebSocket(ws)); + // Send ping to client periodically + const pingIntervalId = setInterval(() => { + if (ws.readyState == ws.OPEN) { + ws.ping(); + } else { + clearInterval(pingIntervalId); + } + }, websocketTimeout); + }); + this.server = wss; + } +} + +exports.ParseWebSocketServer = ParseWebSocketServer; +class ParseWebSocket { + + constructor(ws) { + this.ws = ws; + } + + on(type, callback) { + const wsType = typeMap.has(type) ? typeMap.get(type) : type; + this.ws.on(wsType, callback); + } + + send(message) { + this.ws.send(message); + } +} +exports.ParseWebSocket = ParseWebSocket; \ No newline at end of file diff --git a/lib/LiveQuery/QueryTools.js b/lib/LiveQuery/QueryTools.js new file mode 100644 index 0000000000..74d528c8f8 --- /dev/null +++ b/lib/LiveQuery/QueryTools.js @@ -0,0 +1,320 @@ +'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 (!where.hasOwnProperty('$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; + } + // 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; \ No newline at end of file diff --git a/lib/LiveQuery/RequestSchema.js b/lib/LiveQuery/RequestSchema.js new file mode 100644 index 0000000000..a0a7e511c7 --- /dev/null +++ b/lib/LiveQuery/RequestSchema.js @@ -0,0 +1,145 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +const general = { + 'title': 'General request schema', + 'type': 'object', + 'properties': { + 'op': { + 'type': 'string', + 'enum': ['connect', 'subscribe', 'unsubscribe', 'update'] + } + } +}; + +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' + } + }, + '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 +}; + +exports.default = RequestSchema; \ No newline at end of file diff --git a/lib/LiveQuery/SessionTokenCache.js b/lib/LiveQuery/SessionTokenCache.js new file mode 100644 index 0000000000..82056f7439 --- /dev/null +++ b/lib/LiveQuery/SessionTokenCache.js @@ -0,0 +1,63 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SessionTokenCache = undefined; + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _lruCache = require('lru-cache'); + +var _lruCache2 = _interopRequireDefault(_lruCache); + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function userForSessionToken(sessionToken) { + var q = new _node2.default.Query("_Session"); + q.equalTo("sessionToken", sessionToken); + return q.first({ useMasterKey: true }).then(function (session) { + if (!session) { + return _node2.default.Promise.error("No session found for session token"); + } + return session.get("user"); + }); +} + +class SessionTokenCache { + + constructor(timeout = 30 * 24 * 60 * 60 * 1000, maxSize = 10000) { + this.cache = new _lruCache2.default({ + max: maxSize, + maxAge: timeout + }); + } + + getUserId(sessionToken) { + if (!sessionToken) { + return _node2.default.Promise.error('Empty sessionToken'); + } + const userId = this.cache.get(sessionToken); + if (userId) { + _logger2.default.verbose('Fetch userId %s of sessionToken %s from Cache', userId, sessionToken); + return _node2.default.Promise.as(userId); + } + return userForSessionToken(sessionToken).then(user => { + _logger2.default.verbose('Fetch userId %s of sessionToken %s from Parse', user.id, sessionToken); + const userId = user.id; + this.cache.set(sessionToken, userId); + return _node2.default.Promise.as(userId); + }, error => { + _logger2.default.error('Can not fetch userId for sessionToken %j, error %j', sessionToken, error); + return _node2.default.Promise.error(error); + }); + } +} + +exports.SessionTokenCache = SessionTokenCache; \ No newline at end of file diff --git a/lib/LiveQuery/Subscription.js b/lib/LiveQuery/Subscription.js new file mode 100644 index 0000000000..8d0019fda0 --- /dev/null +++ b/lib/LiveQuery/Subscription.js @@ -0,0 +1,55 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Subscription = undefined; + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_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') { + _logger2.default.error('Can not find client %d to delete', clientId); + return; + } + + const index = requestIds.indexOf(requestId); + if (index < 0) { + _logger2.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; \ No newline at end of file diff --git a/lib/LiveQuery/equalObjects.js b/lib/LiveQuery/equalObjects.js new file mode 100644 index 0000000000..bb3890a748 --- /dev/null +++ b/lib/LiveQuery/equalObjects.js @@ -0,0 +1,50 @@ +'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; \ No newline at end of file diff --git a/lib/Options/Definitions.js b/lib/Options/Definitions.js new file mode 100644 index 0000000000..7cd842f3c3 --- /dev/null +++ b/lib/Options/Definitions.js @@ -0,0 +1,388 @@ +/* +**** GENERATED CODE **** +This code has been generated by resources/buildConfigDefinitions.js +Do not edit manually, but update Options/index.js +*/"use strict"; + +var parsers = require("./parsers"); + +module.exports.ParseServerOptions = { + "appId": { + "env": "PARSE_SERVER_APPLICATION_ID", + "help": "Your Parse Application ID", + "required": true + }, + "masterKey": { + "env": "PARSE_SERVER_MASTER_KEY", + "help": "Your Parse Master Key", + "required": true + }, + "serverURL": { + "env": "PARSE_SERVER_URL", + "help": "URL to your parse server with http:// or https://.", + "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": [] + }, + "appName": { + "env": "PARSE_SERVER_APP_NAME", + "help": "Sets the app name" + }, + "analyticsAdapter": { + "env": "PARSE_SERVER_ANALYTICS_ADAPTER", + "help": "Adapter module for the analytics", + "action": parsers.moduleOrObjectParser + }, + "filesAdapter": { + "env": "PARSE_SERVER_FILES_ADAPTER", + "help": "Adapter module for the files sub-system", + "action": parsers.moduleOrObjectParser + }, + "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 + }, + "scheduledPush": { + "env": "PARSE_SERVER_SCHEDULED_PUSH", + "help": "Configuration for push scheduling. Defaults to false.", + "action": parsers.booleanParser, + "default": false + }, + "loggerAdapter": { + "env": "PARSE_SERVER_LOGGER_ADAPTER", + "help": "Adapter module for the logging sub-system", + "action": parsers.moduleOrObjectParser + }, + "jsonLogs": { + "env": "JSON_LOGS", + "help": "Log as structured JSON objects", + "action": parsers.booleanParser + }, + "logsFolder": { + "env": "PARSE_SERVER_LOGS_FOLDER", + "help": "Folder for the logs (defaults to './logs'); set to null to disable file based logging", + "default": "./logs" + }, + "verbose": { + "env": "VERBOSE", + "help": "Set the logging to verbose", + "action": parsers.booleanParser + }, + "logLevel": { + "env": "PARSE_SERVER_LOG_LEVEL", + "help": "Sets the level for logs" + }, + "silent": { + "env": "SILENT", + "help": "Disables console output", + "action": parsers.booleanParser + }, + "databaseURI": { + "env": "PARSE_SERVER_DATABASE_URI", + "help": "The full URI to your mongodb database", + "required": true, + "default": "mongodb://localhost:27017/parse" + }, + "databaseOptions": { + "env": "PARSE_SERVER_DATABASE_OPTIONS", + "help": "Options to pass to the mongodb client", + "action": parsers.objectParser + }, + "databaseAdapter": { + "env": "PARSE_SERVER_DATABASE_ADAPTER", + "help": "Adapter module for the database", + "action": parsers.moduleOrObjectParser + }, + "cloud": { + "env": "PARSE_SERVER_CLOUD", + "help": "Full path to your cloud code main.js" + }, + "collectionPrefix": { + "env": "PARSE_SERVER_COLLECTION_PREFIX", + "help": "A collection prefix for the classes", + "default": "" + }, + "clientKey": { + "env": "PARSE_SERVER_CLIENT_KEY", + "help": "Key for iOS, MacOS, tvOS clients" + }, + "javascriptKey": { + "env": "PARSE_SERVER_JAVASCRIPT_KEY", + "help": "Key for the Javascript SDK" + }, + "dotNetKey": { + "env": "PARSE_SERVER_DOT_NET_KEY", + "help": "Key for Unity and .Net SDK" + }, + "restAPIKey": { + "env": "PARSE_SERVER_REST_API_KEY", + "help": "Key for REST calls" + }, + "readOnlyMasterKey": { + "env": "PARSE_SERVER_READ_ONLY_MASTER_KEY", + "help": "Read-only key, which has the same capabilities as MasterKey without writes" + }, + "webhookKey": { + "env": "PARSE_SERVER_WEBHOOK_KEY", + "help": "Key sent with outgoing webhook calls" + }, + "fileKey": { + "env": "PARSE_SERVER_FILE_KEY", + "help": "Key for your files" + }, + "userSensitiveFields": { + "env": "PARSE_SERVER_USER_SENSITIVE_FIELDS", + "help": "Personally identifiable information fields in the user table the should be removed for non-authorized users.", + "action": parsers.arrayParser, + "default": ["email"] + }, + "enableAnonymousUsers": { + "env": "PARSE_SERVER_ENABLE_ANON_USERS", + "help": "Enable (or disable) anon users, defaults to true", + "action": parsers.booleanParser, + "default": true + }, + "allowClientClassCreation": { + "env": "PARSE_SERVER_ALLOW_CLIENT_CLASS_CREATION", + "help": "Enable (or disable) client class creation, defaults to true", + "action": parsers.booleanParser, + "default": true + }, + "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 + }, + "maxUploadSize": { + "env": "PARSE_SERVER_MAX_UPLOAD_SIZE", + "help": "Max file size for uploads. defaults to 20mb", + "default": "20mb" + }, + "verifyUserEmails": { + "env": "PARSE_SERVER_VERIFY_USER_EMAILS", + "help": "Enable (or disable) user email validation, defaults to false", + "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 + }, + "emailVerifyTokenValidityDuration": { + "env": "PARSE_SERVER_EMAIL_VERIFY_TOKEN_VALIDITY_DURATION", + "help": "Email verification token validity duration", + "action": parsers.numberParser("emailVerifyTokenValidityDuration") + }, + "accountLockout": { + "env": "PARSE_SERVER_ACCOUNT_LOCKOUT", + "help": "account lockout policy for failed login attempts", + "action": parsers.objectParser + }, + "passwordPolicy": { + "env": "PARSE_SERVER_PASSWORD_POLICY", + "help": "Password policy for enforcing password related rules", + "action": parsers.objectParser + }, + "cacheAdapter": { + "env": "PARSE_SERVER_CACHE_ADAPTER", + "help": "Adapter module for the cache", + "action": parsers.moduleOrObjectParser + }, + "emailAdapter": { + "env": "PARSE_SERVER_EMAIL_ADAPTER", + "help": "Adapter module for the email sending", + "action": parsers.moduleOrObjectParser + }, + "publicServerURL": { + "env": "PARSE_PUBLIC_SERVER_URL", + "help": "Public URL to your parse server with http:// or https://." + }, + "customPages": { + "env": "PARSE_SERVER_CUSTOM_PAGES", + "help": "custom pages for password validation and reset", + "action": parsers.objectParser, + "default": {} + }, + "liveQuery": { + "env": "PARSE_SERVER_LIVE_QUERY", + "help": "parse-server's LiveQuery configuration object", + "action": parsers.objectParser + }, + "sessionLength": { + "env": "PARSE_SERVER_SESSION_LENGTH", + "help": "Session duration, in seconds, defaults to 1 year", + "action": parsers.numberParser("sessionLength"), + "default": 31536000 + }, + "maxLimit": { + "env": "PARSE_SERVER_MAX_LIMIT", + "help": "Max value for limit option on queries, defaults to unlimited", + "action": parsers.numberParser("maxLimit") + }, + "expireInactiveSessions": { + "env": "PARSE_SERVER_EXPIRE_INACTIVE_SESSIONS", + "help": "Sets wether we should expire the inactive sessions, defaults to true", + "action": parsers.booleanParser, + "default": true + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "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 + }, + "port": { + "env": "PORT", + "help": "The port to run the ParseServer. defaults to 1337.", + "action": parsers.numberParser("port"), + "default": 1337 + }, + "host": { + "env": "PARSE_SERVER_HOST", + "help": "The host to serve ParseServer on. defaults to 0.0.0.0", + "default": "0.0.0.0" + }, + "mountPath": { + "env": "PARSE_SERVER_MOUNT_PATH", + "help": "Mount path for the server, defaults to /parse", + "default": "/parse" + }, + "cluster": { + "env": "PARSE_SERVER_CLUSTER", + "help": "Run with cluster, optionally set the number of processes default to os.cpus().length", + "action": parsers.numberOrBooleanParser + }, + "middleware": { + "env": "PARSE_SERVER_MIDDLEWARE", + "help": "middleware for express server, can be string or function" + }, + "startLiveQueryServer": { + "env": "PARSE_SERVER_START_LIVE_QUERY_SERVER", + "help": "Starts the liveQuery server", + "action": parsers.booleanParser + }, + "liveQueryServerOptions": { + "env": "PARSE_SERVER_LIVE_QUERY_SERVER_OPTIONS", + "help": "Live query server configuration options (will start the liveQuery server)", + "action": parsers.objectParser + } +}; +module.exports.CustomPagesOptions = { + "invalidLink": { + "env": "PARSE_SERVER_CUSTOM_PAGES_INVALID_LINK", + "help": "invalid link page path" + }, + "verifyEmailSuccess": { + "env": "PARSE_SERVER_CUSTOM_PAGES_VERIFY_EMAIL_SUCCESS", + "help": "verify email success page path" + }, + "choosePassword": { + "env": "PARSE_SERVER_CUSTOM_PAGES_CHOOSE_PASSWORD", + "help": "choose password page path" + }, + "passwordResetSuccess": { + "env": "PARSE_SERVER_CUSTOM_PAGES_PASSWORD_RESET_SUCCESS", + "help": "password reset success page path" + } +}; +module.exports.LiveQueryOptions = { + "classNames": { + "env": "PARSE_SERVER_LIVEQUERY_CLASSNAMES", + "help": "parse-server's LiveQuery classNames", + "action": parsers.arrayParser + }, + "redisURL": { + "env": "PARSE_SERVER_LIVEQUERY_REDIS_URL", + "help": "parse-server's LiveQuery redisURL" + }, + "pubSubAdapter": { + "env": "PARSE_SERVER_LIVEQUERY_PUB_SUB_ADAPTER", + "help": "LiveQuery pubsub adapter", + "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." + }, + "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." + }, + "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." + }, + "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 + }, + "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") + }, + "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") + }, + "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." + }, + "port": { + "env": "PARSE_LIVE_QUERY_SERVER_PORT", + "help": "The port to run the ParseServer. defaults to 1337.", + "action": parsers.numberParser("port"), + "default": 1337 + }, + "redisURL": { + "env": "PARSE_LIVE_QUERY_SERVER_REDIS_URL", + "help": "parse-server's LiveQuery redisURL" + }, + "pubSubAdapter": { + "env": "PARSE_LIVE_QUERY_SERVER_PUB_SUB_ADAPTER", + "help": "LiveQuery pubsub adapter", + "action": parsers.moduleOrObjectParser + } +}; \ No newline at end of file diff --git a/lib/Options/index.js b/lib/Options/index.js new file mode 100644 index 0000000000..9a390c31f7 --- /dev/null +++ b/lib/Options/index.js @@ -0,0 +1 @@ +"use strict"; \ No newline at end of file diff --git a/lib/Options/parsers.js b/lib/Options/parsers.js new file mode 100644 index 0000000000..4b93c680e9 --- /dev/null +++ b/lib/Options/parsers.js @@ -0,0 +1,77 @@ +'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 +}; \ No newline at end of file diff --git a/lib/ParseMessageQueue.js b/lib/ParseMessageQueue.js new file mode 100644 index 0000000000..617324204d --- /dev/null +++ b/lib/ParseMessageQueue.js @@ -0,0 +1,30 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseMessageQueue = undefined; + +var _AdapterLoader = require('./Adapters/AdapterLoader'); + +var _EventEmitterMQ = require('./Adapters/MessageQueue/EventEmitterMQ'); + +const 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); +}; + +exports.ParseMessageQueue = ParseMessageQueue; \ No newline at end of file diff --git a/lib/ParseServer.js b/lib/ParseServer.js new file mode 100644 index 0000000000..218a37f29c --- /dev/null +++ b/lib/ParseServer.js @@ -0,0 +1,375 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _Options = require('./Options'); + +var _defaults = require('./defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +var _logger = require('./logger'); + +var logging = _interopRequireWildcard(_logger); + +var _Config = require('./Config'); + +var _Config2 = _interopRequireDefault(_Config); + +var _PromiseRouter = require('./PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _requiredParameter = require('./requiredParameter'); + +var _requiredParameter2 = _interopRequireDefault(_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 _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 _ImportRouter = require('./Routers/ImportRouter'); + +var _ExportRouter = require('./Routers/ExportRouter'); + +var _ParseServerRESTController = require('./ParseServerRESTController'); + +var _Controllers = require('./Controllers'); + +var controllers = _interopRequireWildcard(_Controllers); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _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, + path = require('path'); + +// Mutate the Parse object to add the Cloud Code handlers +addParseCloud(); + +// ParseServer works like a constructor of an express app. +// The args that we understand are: +// "analyticsAdapter": an adapter class for analytics +// "filesAdapter": a class like GridStoreAdapter providing create, get, +// and delete +// "loggerAdapter": a class like WinstonLoggerAdapter providing info, error, +// and query +// "jsonLogs": log as structured JSON objects +// "databaseURI": a uri like mongodb://localhost:27017/dbname to tell us +// what database this Parse API connects to. +// "cloud": relative location to cloud code to require, or a function +// that is given an instance of Parse as a parameter. Use this instance of Parse +// to register your cloud code hooks and functions. +// "appId": the application id to host +// "masterKey": the master key for requests to this app +// "collectionPrefix": optional prefix for database collection names +// "fileKey": optional key from Parse dashboard for supporting older files +// hosted by Parse +// "clientKey": optional key from Parse dashboard +// "dotNetKey": optional key from Parse dashboard +// "restAPIKey": optional key from Parse dashboard +// "webhookKey": optional key from Parse dashboard +// "javascriptKey": optional key from Parse dashboard +// "push": optional key from configure push +// "sessionLength": optional length in seconds for how long Sessions should be valid for +// "maxLimit": optional upper bound for what can be specified for the 'limit' parameter on queries + +class ParseServer { + + constructor(options) { + injectDefaults(options); + const { + appId = (0, _requiredParameter2.default)('You must provide an appId!'), + masterKey = (0, _requiredParameter2.default)('You must provide a masterKey!'), + cloud, + javascriptKey, + serverURL = (0, _requiredParameter2.default)('You must provide a serverURL!'), + __indexBuildCompletionCallbackForTests = () => {} + } = 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 = _Config2.default.put(Object.assign({}, options, allControllers)); + + logging.setLogger(loggerController); + const dbInitPromise = databaseController.performInitialization(); + hooksController.load(); + + // Note: Tests will start to fail if any validation happens after this is called. + if (process.env.TESTING) { + __indexBuildCompletionCallbackForTests(dbInitPromise); + } + + 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 { adapter } = this.config.databaseController; + if (adapter && typeof adapter.handleShutdown === 'function') { + adapter.handleShutdown(); + } + } + + static app({ maxUploadSize = '20mb', appId }) { + // 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")); + // File handling needs to be before default middlewares are applied + api.use('/', middlewares.allowCrossDomain, 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('/', middlewares.allowCrossDomain, new _ImportRouter.ImportRouter().expressRouter()); + api.use(bodyParser.json({ 'type': '*/*', limit: maxUploadSize })); + api.use(middlewares.allowCrossDomain); + 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') { + 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 _PurgeRouter.PurgeRouter(), new _ExportRouter.ExportRouter(), new _HooksRouter.HooksRouter(), new _CloudCodeRouter.CloudCodeRouter(), new _AudiencesRouter.AudiencesRouter(), new _AggregateRouter.AggregateRouter()]; + + const routes = routers.reduce((memo, router) => { + return memo.concat(router.routes); + }, []); + + const appRouter = new _PromiseRouter2.default(routes, appId); + + batch.mountOnto(appRouter); + return appRouter; + } + + 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); + 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; + } + + static start(options, callback) { + const parseServer = new ParseServer(options); + return parseServer.start(options, callback); + } + + 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(Parse.serverURL.replace(/\/$/, "") + "/health", function (error, response, body) { + let json; + try { + json = JSON.parse(body); + } catch (e) { + json = null; + } + if (error || response.statusCode !== 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(_defaults2.default).forEach(key => { + if (!options.hasOwnProperty(key)) { + options[key] = _defaults2.default[key]; + } + }); + + if (!options.hasOwnProperty('serverURL')) { + options.serverURL = `http://localhost:${options.port}${options.mountPath}`; + } + + options.userSensitiveFields = Array.from(new Set(options.userSensitiveFields.concat(_defaults2.default.userSensitiveFields, options.userSensitiveFields))); + + options.masterKeyIps = Array.from(new Set(options.masterKeyIps.concat(_defaults2.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); +} + +exports.default = ParseServer; \ No newline at end of file diff --git a/lib/ParseServerRESTController.js b/lib/ParseServerRESTController.js new file mode 100644 index 0000000000..2ae687a32a --- /dev/null +++ b/lib/ParseServerRESTController.js @@ -0,0 +1,103 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +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 Parse.Promise.as(options.sessionToken); + } + return Parse.Promise.as(null); +} + +function getAuth(options = {}, config) { + const installationId = options.installationId || 'cloud'; + if (options.useMasterKey) { + return Parse.Promise.as(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 Parse.Promise.as(new Auth.Auth({ config, installationId })); + } + }); +} + +function ParseServerRESTController(applicationId, router) { + function handleRequest(method, path, data = {}, options = {}) { + // Store the arguments, for later use if internal fails + const args = arguments; + + const 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') { + const promises = data.requests.map(request => { + return handleRequest(request.method, request.path, request.body, options).then(response => { + return Parse.Promise.as({ success: response }); + }, error => { + return Parse.Promise.as({ error: { code: error.code, error: error.message } }); + }); + }); + return Parse.Promise.all(promises); + } + + let query; + if (method === 'GET') { + query = data; + } + + return new Parse.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 + }; +} + +exports.default = ParseServerRESTController; +exports.ParseServerRESTController = ParseServerRESTController; \ No newline at end of file diff --git a/lib/PromiseRouter.js b/lib/PromiseRouter.js new file mode 100644 index 0000000000..120ec91d54 --- /dev/null +++ b/lib/PromiseRouter.js @@ -0,0 +1,218 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _express = require('express'); + +var _express2 = _interopRequireDefault(_express); + +var _logger = require('./logger'); + +var _logger2 = _interopRequireDefault(_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(_express2.default.Router()); + } + + tryRouteRequest(method, path, request) { + var match = this.match(method, path); + if (!match) { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'cannot route ' + method + ' ' + path); + } + request.params = match.params; + return new Promise((resolve, reject) => { + match.handler(request).then(resolve, reject); + }); + } +} + +exports.default = PromiseRouter; // 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. + +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; + _logger2.default.logRequest({ + method, + url, + headers, + body + }); + promiseHandler(req).then(result => { + if (!result.response && !result.location && !result.text) { + _logger2.default.error('the handler did not include a "response" or a "location" field'); + throw 'control should not get here'; + } + + _logger2.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); + }, e => { + _logger2.default.error(`Error generating response. ${(0, _util.inspect)(e)}`, { error: e }); + next(e); + }); + } catch (e) { + _logger2.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 = _logger2.default.maskSensitiveUrl(maskUrl); + } + return maskUrl; +} \ No newline at end of file diff --git a/lib/Push/PushQueue.js b/lib/Push/PushQueue.js new file mode 100644 index 0000000000..9566a939b4 --- /dev/null +++ b/lib/Push/PushQueue.js @@ -0,0 +1,72 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PushQueue = undefined; + +var _ParseMessageQueue = require('../ParseMessageQueue'); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _utils = require('./utils'); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const PUSH_CHANNEL = 'parse-server-push'; +const DEFAULT_BATCH_SIZE = 100; + +class PushQueue { + + // config object of the publisher, right now it only contains the redisURL, + // but we may extend it later. + constructor(config = {}) { + this.channel = config.channel || PushQueue.defaultPushChannel(); + this.batchSize = config.batchSize || DEFAULT_BATCH_SIZE; + this.parsePublisher = _ParseMessageQueue.ParseMessageQueue.createPublisher(config); + } + + static defaultPushChannel() { + return `${_node2.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 _rest2.default.find(config, auth, '_Installation', where, { limit: 0, count: true }); + }).then(({ results, count }) => { + if (!results || count == 0) { + return Promise.reject({ error: 'PushController: no results in query' }); + } + pushStatus.setRunning(Math.ceil(count / limit)); + let skip = 0; + while (skip < count) { + const query = { where, + limit, + skip, + order }; + + const pushWorkItem = { + body, + query, + pushStatus: { objectId: pushStatus.objectId }, + applicationId: config.applicationId + }; + this.parsePublisher.publish(this.channel, JSON.stringify(pushWorkItem)); + skip += limit; + } + }); + } +} +exports.PushQueue = PushQueue; \ No newline at end of file diff --git a/lib/Push/PushWorker.js b/lib/Push/PushWorker.js new file mode 100644 index 0000000000..14060e558c --- /dev/null +++ b/lib/Push/PushWorker.js @@ -0,0 +1,149 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PushWorker = undefined; + +var _deepcopy = require('deepcopy'); + +var _deepcopy2 = _interopRequireDefault(_deepcopy); + +var _AdaptableController = require('../Controllers/AdaptableController'); + +var _AdaptableController2 = _interopRequireDefault(_AdaptableController); + +var _Auth = require('../Auth'); + +var _Config = require('../Config'); + +var _Config2 = _interopRequireDefault(_Config); + +var _PushAdapter = require('../Adapters/Push/PushAdapter'); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _StatusHandler = require('../StatusHandler'); + +var _utils = require('./utils'); + +var utils = _interopRequireWildcard(_utils); + +var _ParseMessageQueue = require('../ParseMessageQueue'); + +var _PushQueue = require('./PushQueue'); + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 = {}) { + _AdaptableController2.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.getAndRun(workItem); + }); + } + } + + unsubscribe() { + if (this.subscriber) { + this.subscriber.unsubscribe(this.channel); + } + } + + run({ body, query, pushStatus, applicationId, UTCOffset }) { + const config = _Config2.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 _rest2.default.find(config, auth, '_Installation', where, query).then(({ results }) => { + if (results.length == 0) { + return pushStatus.trackSent(results); + } + return this.sendToAdapter(body, results, pushStatus, config, UTCOffset); + }, err => { + throw err; + }); + } + + 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)) { + _logger2.default.verbose(`Sending push to ${installations.length}`); + return this.adapter.send(body, installations, pushStatus.objectId).then(results => { + return pushStatus.trackSent(results, UTCOffset, undefined, installations.length - results.length).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, _deepcopy2.default)(body); + payload.data.badge = parseInt(badge); + const installations = badgeInstallationsMap[badge]; + return this.sendToAdapter(payload, installations, pushStatus, config, UTCOffset); + }); + return Promise.all(promises); + } + + getAndRun(workItem) { + var _this = this; + if (!_this.subscriber.run) { + return _this.run(workItem); + } + return _this.subscriber.run(workItem).then(function (gotItem) { + if (gotItem) { + return _this.run(gotItem).then(function () { + return _this.getAndRun(gotItem); + }); + } else { + return Promise.resolve(); + } + }); + } +} + +exports.PushWorker = PushWorker; +exports.default = PushWorker; \ No newline at end of file diff --git a/lib/Push/utils.js b/lib/Push/utils.js new file mode 100644 index 0000000000..a526977766 --- /dev/null +++ b/lib/Push/utils.js @@ -0,0 +1,133 @@ +'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 = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _deepcopy = require('deepcopy'); + +var _deepcopy2 = _interopRequireDefault(_deepcopy); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function isPushIncrementing(body) { + return body.data && body.data.badge && typeof body.data.badge == 'string' && body.data.badge.toLowerCase() == "increment"; +} + +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, _deepcopy2.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 _node2.default.Error(_node2.default.Error.PUSH_MISCONFIGURED, deviceType + ' is not supported push type.'); + } + } +} + +function applyDeviceTokenExists(where) { + where = (0, _deepcopy2.default)(where); + if (!where.hasOwnProperty('deviceToken')) { + where['deviceToken'] = { '$exists': true }; + } + return where; +} \ No newline at end of file diff --git a/lib/RestQuery.js b/lib/RestQuery.js new file mode 100644 index 0000000000..7478200467 --- /dev/null +++ b/lib/RestQuery.js @@ -0,0 +1,752 @@ +'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 AlwaysSelectedKeys = ['objectId', 'createdAt', 'updatedAt']; +// restOptions can include: +// skip +// limit +// order +// count +// include +// keys +// redirectClassNameForKey +function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, clientSDK) { + + this.config = config; + this.auth = auth; + this.className = className; + this.restWhere = restWhere; + this.restOptions = restOptions; + this.clientSDK = clientSDK; + this.response = null; + this.findOptions = {}; + if (!this.auth.isMaster) { + this.findOptions.acl = this.auth.user ? [this.auth.user.id] : null; + if (this.className == '_Session') { + if (!this.findOptions.acl) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'This session token is invalid.'); + } + this.restWhere = { + '$and': [this.restWhere, { + 'user': { + __type: 'Pointer', + className: '_User', + objectId: this.auth.user.id + } + }] + }; + } + } + + this.doCount = 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 (restOptions.hasOwnProperty('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 'count': + this.doCount = true; + break; + case 'distinct': + case 'pipeline': + case 'skip': + case 'limit': + case 'readPreference': + this.findOptions[option] = restOptions[option]; + break; + case 'order': + var fields = restOptions.order.split(','); + this.findOptions.sort = fields.reduce((sortMap, field) => { + field = field.trim(); + if (field === '$score') { + sortMap.score = { $meta: 'textScore' }; + } else if (field[0] == '-') { + sortMap[field.slice(1)] = -1; + } else { + sortMap[field] = 1; + } + return sortMap; + }, {}); + break; + case 'include': + { + const paths = restOptions.include.split(','); + // 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.runFind(executeOptions); + }).then(() => { + return this.runCount(); + }).then(() => { + return this.handleInclude(); + }).then(() => { + return this.runAfterFindTrigger(); + }).then(() => { + return this.response; + }); +}; + +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 || !this.auth.user) { + return Promise.resolve(); + } + return this.auth.getUserRoles().then(roles => { + // Concat with the roles to prevent duplications on multiple calls + const aclSet = new Set([].concat(this.findOptions.acl, roles)); + this.findOptions.acl = Array.from(aclSet); + 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, + keys: 'objectId' + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } + + 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, + keys: 'objectId' + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } + + 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(); + }); +}; + +const transformSelect = (selectObject, key, objects) => { + var values = []; + for (var result of objects) { + values.push(key.split('.').reduce((o, i) => o[i], 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, + keys: selectValue.key + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } + + 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((o, i) => o[i], 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, + keys: dontSelectValue.key + }; + + if (this.restOptions.subqueryReadPreference) { + additionalOptions.readPreference = this.restOptions.subqueryReadPreference; + additionalOptions.subqueryReadPreference = this.restOptions.subqueryReadPreference; + } + + 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 cleanResultOfSensitiveUserInfo = function (result, auth, config) { + delete result.password; + + if (auth.isMaster || auth.user && auth.user.id === result.objectId) { + return; + } + + for (const field of config.userSensitiveFields) { + delete result[field]; + } +}; + +const cleanResultAuthData = function (result) { + 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).then(results => { + if (this.className === '_User') { + for (var result of results) { + cleanResultOfSensitiveUserInfo(result, this.auth, this.config); + 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 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; + } + // 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(); + } + // 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 => { + 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; + } + + 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; \ No newline at end of file diff --git a/lib/RestWrite.js b/lib/RestWrite.js new file mode 100644 index 0000000000..b763f7d00d --- /dev/null +++ b/lib/RestWrite.js @@ -0,0 +1,1178 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _RestQuery = require('./RestQuery'); + +var _RestQuery2 = _interopRequireDefault(_RestQuery); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _logger = require('./logger'); + +var _logger2 = _interopRequireDefault(_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'); + +var 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, options) { + 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 = {}; + const allowObjectId = options && options.allowObjectId === true; + if (!query && data.objectId && !allowObjectId) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId 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; +} + +// 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.runBeforeTrigger(); + }).then(() => { + return this.validateSchema(); + }).then(() => { + 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.runAfterTrigger(); + }).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.runBeforeTrigger = 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(() => { + return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config); + }).then(response => { + if (response && response.object) { + this.storage.fieldsChangedByTrigger = _lodash2.default.reduce(response.object, (result, value, key) => { + if (!_lodash2.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.setRequiredFieldsIfNeeded = function () { + if (this.data) { + // 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); + } + } + } + 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' || _lodash2.default.isEmpty(this.data.username)) { + throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'bad or missing username'); + } + if (typeof this.data.password !== 'string' || _lodash2.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) { + return; + } + + 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.handleAuthData = function (authData) { + let results; + return this.findUsersWithAuthData(authData).then(r => { + results = r; + 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'); + } + + this.storage['authProvider'] = Object.keys(authData).join(','); + + if (results.length > 0) { + const userResult = results[0]; + const mutatedAuthData = {}; + Object.keys(authData).forEach(provider => { + const providerData = authData[provider]; + const userAuthData = userResult.authData[provider]; + if (!_lodash2.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() + }; + } + // 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(() => { + // 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); + }); +}; + +// 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 _RestQuery2.default(this.config, Auth.master(this.config), '_Session', { + user: { + __type: "Pointer", + className: "_User", + objectId: this.objectId() + } + }).execute().then(results => { + results.results.forEach(session => this.config.cacheController.user.del(session.sessionToken)); + }); + } + + return promise.then(() => { + // Transform the password + if (this.data.password === undefined) { + // ignore only if undefined. should proceed if empty ('') + return Promise.resolve(); + } + + if (this.query) { + this.storage['clearSessions'] = true; + // Generate a new session only if the user requested + if (!this.auth.isMaster) { + this.storage['generateNewSession'] = true; + } + } + + return this._validatePasswordPolicy().then(() => { + return passwordCrypto.hash(this.data.password).then(hashedPassword => { + this.data._hashed_password = hashedPassword; + delete this.data.password; + }); + }); + }).then(() => { + return this._validateUserName(); + }).then(() => { + return this._validateEmail(); + }); +}; + +RestWrite.prototype._validateUserName = function () { + // Check for username uniqueness + if (!this.data.username) { + if (!this.query) { + this.data.username = cryptoUtils.randomString(25); + this.responseShouldHaveUsername = true; + } + return Promise.resolve(); + } + // We need to a find to check for duplicate username in case they are missing the unique index on usernames + // TODO: Check if there is a unique index, and if so, skip this query. + return this.config.database.find(this.className, { username: this.data.username, objectId: { '$ne': this.objectId() } }, { limit: 1 }).then(results => { + if (results.length > 0) { + throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.'); + } + return; + }); +}; + +RestWrite.prototype._validateEmail = function () { + if (!this.data.email || this.data.email.__op === 'Delete') { + return Promise.resolve(); + } + // Validate basic email address format + if (!this.data.email.match(/^.+@.+$/)) { + return Promise.reject(new Parse.Error(Parse.Error.INVALID_EMAIL_ADDRESS, 'Email address format is invalid.')); + } + // Same problem for email as above for username + return this.config.database.find(this.className, { email: this.data.email, objectId: { '$ne': this.objectId() } }, { limit: 1 }).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 + const policyError = 'Password does not meet the Password Policy requirements.'; + + // 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, policyError)); + } 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, policyError)); + 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 = _lodash2.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; + } + if (this.query) { + 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 = function () { + // cloud installationId from Cloud Code, + // never create session tokens from there. + if (this.auth.installationId && this.auth.installationId === 'cloud') { + return; + } + var token = 'r:' + cryptoUtils.newToken(); + + var expiresAt = this.config.generateSessionExpiresAt(); + var sessionData = { + sessionToken: token, + user: { + __type: 'Pointer', + className: '_User', + objectId: this.objectId() + }, + createdWith: { + 'action': this.storage['authProvider'] ? 'login' : 'signup', + 'authProvider': this.storage['authProvider'] || 'password' + }, + restricted: false, + installationId: this.auth.installationId, + expiresAt: Parse._encode(expiresAt) + }; + if (this.response && this.response.response) { + this.response.response.sessionToken = token; + } + + return new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData).execute(); +}; + +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 } + }); +}; + +// 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) { + var token = 'r:' + cryptoUtils.newToken(); + var expiresAt = this.config.generateSessionExpiresAt(); + var sessionData = { + sessionToken: token, + user: { + __type: 'Pointer', + className: '_User', + objectId: this.auth.user.id + }, + createdWith: { + 'action': 'create' + }, + restricted: true, + expiresAt: Parse._encode(expiresAt) + }; + for (var key in this.data) { + if (key === 'objectId' || key === 'user') { + continue; + } + sessionData[key] = this.data[key]; + } + var create = new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData); + return create.execute().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.couldUpdateUserId(this.query.objectId)) { + 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.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 = _lodash2.default.take(user._password_history, this.config.passwordPolicy.maxPasswordHistory); + } + //n-1 passwords go into history including last password + while (oldPasswords.length > 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).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).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.runAfterTrigger = 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); + + // Notifiy LiveQueryServer if possible + this.config.liveQueryController.onAfterSave(updatedObject.className, updatedObject, originalObject); + + // Run afterSave trigger + return triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config).catch(function (err) { + _logger2.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 (_lodash2.default.isEmpty(this.storage.fieldsChangedByTrigger)) { + return response; + } + const clientSupportsDelete = ClientSDK.supportsForwardDelete(this.clientSDK); + this.storage.fieldsChangedByTrigger.forEach(fieldName => { + const dataValue = data[fieldName]; + + if (!response.hasOwnProperty(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; +}; + +exports.default = RestWrite; + +module.exports = RestWrite; \ No newline at end of file diff --git a/lib/Routers/AggregateRouter.js b/lib/Routers/AggregateRouter.js new file mode 100644 index 0000000000..2a0519915e --- /dev/null +++ b/lib/Routers/AggregateRouter.js @@ -0,0 +1,82 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AggregateRouter = undefined; + +var _ClassesRouter = require('./ClassesRouter'); + +var _ClassesRouter2 = _interopRequireDefault(_ClassesRouter); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _UsersRouter = require('./UsersRouter'); + +var _UsersRouter2 = _interopRequireDefault(_UsersRouter); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const ALLOWED_KEYS = ['where', 'distinct', 'project', 'match', 'redact', 'limit', 'skip', 'unwind', 'group', 'sample', 'sort', 'geoNear', 'lookup', 'out', 'indexStats', 'facet', 'bucket', 'bucketAuto', 'sortByCount', 'addFields', 'replaceRoot', 'count', 'graphLookup']; + +class AggregateRouter extends _ClassesRouter2.default { + + handleFind(req) { + const body = Object.assign(req.body, _ClassesRouter2.default.JSONFromQuery(req.query)); + const options = {}; + const pipeline = []; + + for (const key in body) { + if (ALLOWED_KEYS.indexOf(key) === -1) { + throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: ${key}`); + } + if (key === 'group') { + if (body[key].hasOwnProperty('_id')) { + throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: group. Please use objectId instead of _id`); + } + if (!body[key].hasOwnProperty('objectId')) { + throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: group. objectId is required`); + } + body[key]._id = body[key].objectId; + delete body[key].objectId; + } + pipeline.push({ [`$${key}`]: body[key] }); + } + if (body.distinct) { + options.distinct = String(body.distinct); + } + options.pipeline = pipeline; + if (typeof body.where === 'string') { + body.where = JSON.parse(body.where); + } + return _rest2.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') { + _UsersRouter2.default.removeHiddenProperties(result); + } + } + return { response }; + }); + } + + mountRoutes() { + this.route('GET', '/aggregate/:className', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handleFind(req); + }); + } +} + +exports.AggregateRouter = AggregateRouter; +exports.default = AggregateRouter; \ No newline at end of file diff --git a/lib/Routers/AnalyticsRouter.js b/lib/Routers/AnalyticsRouter.js new file mode 100644 index 0000000000..4cd6885171 --- /dev/null +++ b/lib/Routers/AnalyticsRouter.js @@ -0,0 +1,31 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AnalyticsRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function appOpened(req) { + const analyticsController = req.config.analyticsController; + return analyticsController.appOpened(req); +} // AnalyticsRouter.js + + +function trackEvent(req) { + const analyticsController = req.config.analyticsController; + return analyticsController.trackEvent(req); +} + +class AnalyticsRouter extends _PromiseRouter2.default { + mountRoutes() { + this.route('POST', '/events/AppOpened', appOpened); + this.route('POST', '/events/:eventName', trackEvent); + } +} +exports.AnalyticsRouter = AnalyticsRouter; \ No newline at end of file diff --git a/lib/Routers/AudiencesRouter.js b/lib/Routers/AudiencesRouter.js new file mode 100644 index 0000000000..ce31014ea5 --- /dev/null +++ b/lib/Routers/AudiencesRouter.js @@ -0,0 +1,72 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AudiencesRouter = undefined; + +var _ClassesRouter = require('./ClassesRouter'); + +var _ClassesRouter2 = _interopRequireDefault(_ClassesRouter); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AudiencesRouter extends _ClassesRouter2.default { + + className() { + return '_Audience'; + } + + handleFind(req) { + const body = Object.assign(req.body, _ClassesRouter2.default.JSONFromQuery(req.query)); + const options = _ClassesRouter2.default.optionsFromBody(body); + + return _rest2.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; +exports.default = AudiencesRouter; \ No newline at end of file diff --git a/lib/Routers/ClassesRouter.js b/lib/Routers/ClassesRouter.js new file mode 100644 index 0000000000..d038344e8b --- /dev/null +++ b/lib/Routers/ClassesRouter.js @@ -0,0 +1,169 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ClassesRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const ALLOWED_GET_QUERY_KEYS = ['keys', 'include']; + +class ClassesRouter extends _PromiseRouter2.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 _rest2.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 _node2.default.Error(_node2.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); + } + + return _rest2.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 _node2.default.Error(_node2.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 _rest2.default.create(req.config, req.auth, this.className(req), req.body, req.info.clientSDK); + } + + handleUpdate(req) { + const where = { objectId: req.params.objectId }; + return _rest2.default.update(req.config, req.auth, this.className(req), where, req.body, req.info.clientSDK); + } + + handleDelete(req) { + return _rest2.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 _lodash2.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', 'include', 'redirectClassNameForKey', 'where']; + + for (const key of Object.keys(body)) { + if (allowConstraints.indexOf(key) === -1) { + throw new _node2.default.Error(_node2.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 (body.include) { + options.include = String(body.include); + } + 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; +exports.default = ClassesRouter; \ No newline at end of file diff --git a/lib/Routers/CloudCodeRouter.js b/lib/Routers/CloudCodeRouter.js new file mode 100644 index 0000000000..69ff4066e4 --- /dev/null +++ b/lib/Routers/CloudCodeRouter.js @@ -0,0 +1,95 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CloudCodeRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_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 _node2.default.Error(_node2.default.Error.INTERNAL_SERVER_ERROR, 'Cannot Schedule a job that is not deployed'); + } +} + +class CloudCodeRouter extends _PromiseRouter2.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 _rest2.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 _rest2.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 _rest2.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 _rest2.default.update(req.config, req.auth, '_JobSchedule', { objectId }, formatJobSchedule(job_schedule)).then(response => { + return { + response + }; + }); + } + + static deleteJob(req) { + const { objectId } = req.params; + return _rest2.default.del(req.config, req.auth, '_JobSchedule', objectId).then(response => { + return { + response + }; + }); + } +} +exports.CloudCodeRouter = CloudCodeRouter; \ No newline at end of file diff --git a/lib/Routers/ExportRouter.js b/lib/Routers/ExportRouter.js new file mode 100644 index 0000000000..0e834ae1e4 --- /dev/null +++ b/lib/Routers/ExportRouter.js @@ -0,0 +1,212 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ExportRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _AdapterLoader = require('../Adapters/AdapterLoader'); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _archiver = require('archiver'); + +var _archiver2 = _interopRequireDefault(_archiver); + +var _tmp = require('tmp'); + +var _tmp2 = _interopRequireDefault(_tmp); + +var _fs = require('fs'); + +var _fs2 = _interopRequireDefault(_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 _PromiseRouter2.default { + + exportClassPage(req, name, jsonFileStream, where, skip, limit) { + + const databaseController = req.config.database; + + const options = { + skip, + limit + }; + + const findPromise = name.indexOf('_Join') === 0 ? databaseController.adapter.find(name, relationSchema, where, options) : _rest2.default.find(req.config, req.auth, name, where, options); + + return findPromise.then(data => { + if (Array.isArray(data)) { + data = { results: data }; + } + + 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 = _tmp2.default.fileSync(); + const jsonFileStream = _fs2.default.createWriteStream(tmpJsonFile.name); + + jsonFileStream.write('{\n"results" : [\n'); + + const findPromise = data.name.indexOf('_Join') === 0 ? databaseController.adapter.count(data.name, relationSchema, data.where) : _rest2.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 = _tmp2.default.fileSync(); + const tmpZipStream = _fs2.default.createWriteStream(tmpZipFile.name); + + const zip = (0, _archiver2.default)('zip'); + zip.pipe(tmpZipStream); + + jsonFiles.forEach(tmpJsonFile => { + zip.append(_fs2.default.readFileSync(tmpJsonFile.name), { name: tmpJsonFile._name }); + tmpJsonFile.removeCallback(); + }); + + zip.finalize(); + + tmpZipStream.on('close', () => { + + const buf = _fs2.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; +exports.default = ExportRouter; \ No newline at end of file diff --git a/lib/Routers/FeaturesRouter.js b/lib/Routers/FeaturesRouter.js new file mode 100644 index 0000000000..df7fe673b4 --- /dev/null +++ b/lib/Routers/FeaturesRouter.js @@ -0,0 +1,75 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FeaturesRouter = undefined; + +var _package = require('../../package.json'); + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class FeaturesRouter extends _PromiseRouter2.default { + mountRoutes() { + this.route('GET', '/serverInfo', middleware.promiseEnforceMasterKeyAccess, 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: req.config.hasPushSupport, + scheduledPush: req.config.hasPushScheduledSupport, + storedPushData: req.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; \ No newline at end of file diff --git a/lib/Routers/FilesRouter.js b/lib/Routers/FilesRouter.js new file mode 100644 index 0000000000..8ab5e94388 --- /dev/null +++ b/lib/Routers/FilesRouter.js @@ -0,0 +1,205 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FilesRouter = undefined; + +var _express = require('express'); + +var _express2 = _interopRequireDefault(_express); + +var _bodyParser = require('body-parser'); + +var _bodyParser2 = _interopRequireDefault(_bodyParser); + +var _middlewares = require('../middlewares'); + +var Middlewares = _interopRequireWildcard(_middlewares); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _Config = require('../Config'); + +var _Config2 = _interopRequireDefault(_Config); + +var _mime = require('mime'); + +var _mime2 = _interopRequireDefault(_mime); + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class FilesRouter { + + expressRouter({ maxUploadSize = '20Mb' } = {}) { + var router = _express2.default.Router(); + router.get('/files/:appId/:filename', this.getHandler); + + router.post('/files', function (req, res, next) { + next(new _node2.default.Error(_node2.default.Error.INVALID_FILE_NAME, 'Filename not provided.')); + }); + + router.post('/files/:filename', Middlewares.allowCrossDomain, _bodyParser2.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.allowCrossDomain, Middlewares.handleParseHeaders, Middlewares.enforceMasterKeyAccess, this.deleteHandler); + return router; + } + + getHandler(req, res) { + const config = _Config2.default.get(req.params.appId); + const filesController = config.filesController; + const filename = req.params.filename; + const contentType = _mime2.default.getType(filename); + if (isFileStreamable(req, filesController)) { + filesController.getFileStream(config, filename).then(stream => { + handleFileStream(stream, 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) { + if (!req.body || !req.body.length) { + next(new _node2.default.Error(_node2.default.Error.FILE_SAVE_ERROR, 'Invalid file upload.')); + return; + } + + if (req.params.filename.length > 128) { + next(new _node2.default.Error(_node2.default.Error.INVALID_FILE_NAME, 'Filename too long.')); + return; + } + + if (!req.params.filename.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) { + next(new _node2.default.Error(_node2.default.Error.INVALID_FILE_NAME, 'Filename contains invalid characters.')); + return; + } + + const filename = req.params.filename; + const contentType = req.get('Content-type'); + const config = req.config; + const filesController = config.filesController; + + filesController.createFile(config, filename, req.body, contentType).then(result => { + res.status(201); + res.set('Location', result.url); + res.json(result); + }).catch(e => { + _logger2.default.error(e.message, e); + next(new _node2.default.Error(_node2.default.Error.FILE_SAVE_ERROR, 'Could not store file.')); + }); + } + + 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 _node2.default.Error(_node2.default.Error.FILE_DELETE_ERROR, 'Could not delete file.')); + }); + } +} + +exports.FilesRouter = FilesRouter; +function isFileStreamable(req, filesController) { + return req.get('Range') && typeof filesController.adapter.getFileStream === 'function'; +} + +function getRange(req) { + const parts = req.get('Range').replace(/bytes=/, "").split("-"); + return { start: parseInt(parts[0], 10), end: parseInt(parts[1], 10) }; +} + +// handleFileStream is licenced 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/). +function handleFileStream(stream, req, res, contentType) { + const buffer_size = 1024 * 1024; //1024Kb + // Range request, partiall stream the file + let { + start, end + } = getRange(req); + + 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 avaialbe 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(); + } + }); + }); +} \ No newline at end of file diff --git a/lib/Routers/FunctionsRouter.js b/lib/Routers/FunctionsRouter.js new file mode 100644 index 0000000000..ef871f47bd --- /dev/null +++ b/lib/Routers/FunctionsRouter.js @@ -0,0 +1,183 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FunctionsRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require('../middlewares'); + +var _StatusHandler = require('../StatusHandler'); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_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 _lodash2.default.mapValues(params, parseObject); +} + +class FunctionsRouter extends _PromiseRouter2.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 + }; + const status = { + success: jobHandler.setSucceeded.bind(jobHandler), + error: jobHandler.setFailed.bind(jobHandler), + message: jobHandler.setMessage.bind(jobHandler) + }; + return jobHandler.setRunning(jobName, params).then(jobStatus => { + request.jobId = jobStatus.objectId; + // run the function async + process.nextTick(() => { + jobFunction(request, status); + }); + 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 (code, message) { + if (!message) { + message = code; + code = Parse.Error.SCRIPT_FAILED; + } + 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) { + let params = Object.assign({}, req.body, req.query); + params = parseParams(params); + var 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)); + var response = 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); + } + }); + // Force the keys before the function calls. + Parse.applicationId = req.config.applicationId; + Parse.javascriptKey = req.config.javascriptKey; + Parse.masterKey = req.config.masterKey; + theFunction(request, response); + }); + } else { + throw new Parse.Error(Parse.Error.SCRIPT_FAILED, `Invalid function: "${functionName}"`); + } + } +} +exports.FunctionsRouter = FunctionsRouter; \ No newline at end of file diff --git a/lib/Routers/GlobalConfigRouter.js b/lib/Routers/GlobalConfigRouter.js new file mode 100644 index 0000000000..140960dfe8 --- /dev/null +++ b/lib/Routers/GlobalConfigRouter.js @@ -0,0 +1,61 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.GlobalConfigRouter = undefined; + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalConfigRouter extends _PromiseRouter2.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]; + return { response: { params: globalConfig.params } }; + }); + } + + updateGlobalConfig(req) { + if (req.auth.isReadOnly) { + throw new _node2.default.Error(_node2.default.Error.OPERATION_FORBIDDEN, 'read-only masterKey isn\'t allowed to update the config.'); + } + const params = req.body.params; + // Transform in dot notation to make sure it works + const update = Object.keys(params).reduce((acc, key) => { + acc[`params.${key}`] = params[key]; + 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; // global_config.js + +exports.default = GlobalConfigRouter; \ No newline at end of file diff --git a/lib/Routers/HooksRouter.js b/lib/Routers/HooksRouter.js new file mode 100644 index 0000000000..07a6933ea2 --- /dev/null +++ b/lib/Routers/HooksRouter.js @@ -0,0 +1,117 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.HooksRouter = undefined; + +var _node = require('parse/node'); + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class HooksRouter extends _PromiseRouter2.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; +exports.default = HooksRouter; \ No newline at end of file diff --git a/lib/Routers/IAPValidationRouter.js b/lib/Routers/IAPValidationRouter.js new file mode 100644 index 0000000000..0d03e91f41 --- /dev/null +++ b/lib/Routers/IAPValidationRouter.js @@ -0,0 +1,125 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.IAPValidationRouter = undefined; + +var _PromiseRouter = require("../PromiseRouter"); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _node = require("parse/node"); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var request = require("request"); +var 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 new Promise(function (fulfill, reject) { + request.post({ + url: url, + body: { "receipt-data": receipt }, + json: true + }, function (err, res, body) { + var status = body.status; + if (status == 0) { + // No need to pass anything, status is OK + return fulfill(); + } + // receipt is from test and should go to test + return reject(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 _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Object not found.'); + } + + var download = products[0].download; + return Promise.resolve({ response: download }); + }); +} + +class IAPValidationRouter extends _PromiseRouter2.default { + + handleRequest(req) { + let receipt = req.body.receipt; + const productIdentifier = req.body.productIdentifier; + + if (!receipt || !productIdentifier) { + // TODO: Error, malformed request + throw new _node2.default.Error(_node2.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; \ No newline at end of file diff --git a/lib/Routers/ImportRouter.js b/lib/Routers/ImportRouter.js new file mode 100644 index 0000000000..726bda099b --- /dev/null +++ b/lib/Routers/ImportRouter.js @@ -0,0 +1,208 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ImportRouter = undefined; + +var _express = require('express'); + +var _express2 = _interopRequireDefault(_express); + +var _AdapterLoader = require('../Adapters/AdapterLoader'); + +var _middlewares = require('../middlewares'); + +var middlewares = _interopRequireWildcard(_middlewares); + +var _multer = require('multer'); + +var _multer2 = _interopRequireDefault(_multer); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _node = require('parse/node'); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _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 _rest2.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 _rest2.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 _rest2.default.create(req.config, req.auth, req.params.className, restObject, req.info.clientSDK, { allowObjectId: true }); + } else { + return Promise.reject(error); + } + }); + } + + return _rest2.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 (!response.fields.hasOwnProperty(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 = _express2.default.Router(); + const upload = (0, _multer2.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; +exports.default = ImportRouter; \ No newline at end of file diff --git a/lib/Routers/InstallationsRouter.js b/lib/Routers/InstallationsRouter.js new file mode 100644 index 0000000000..becd25b183 --- /dev/null +++ b/lib/Routers/InstallationsRouter.js @@ -0,0 +1,53 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.InstallationsRouter = undefined; + +var _ClassesRouter = require('./ClassesRouter'); + +var _ClassesRouter2 = _interopRequireDefault(_ClassesRouter); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// InstallationsRouter.js + +class InstallationsRouter extends _ClassesRouter2.default { + className() { + return '_Installation'; + } + + handleFind(req) { + const body = Object.assign(req.body, _ClassesRouter2.default.JSONFromQuery(req.query)); + const options = _ClassesRouter2.default.optionsFromBody(body); + return _rest2.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; +exports.default = InstallationsRouter; \ No newline at end of file diff --git a/lib/Routers/LogsRouter.js b/lib/Routers/LogsRouter.js new file mode 100644 index 0000000000..99ed475a83 --- /dev/null +++ b/lib/Routers/LogsRouter.js @@ -0,0 +1,71 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.LogsRouter = undefined; + +var _node = require('parse/node'); + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class LogsRouter extends _PromiseRouter2.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; +exports.default = LogsRouter; \ No newline at end of file diff --git a/lib/Routers/PublicAPIRouter.js b/lib/Routers/PublicAPIRouter.js new file mode 100644 index 0000000000..ef29364807 --- /dev/null +++ b/lib/Routers/PublicAPIRouter.js @@ -0,0 +1,271 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PublicAPIRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _Config = require('../Config'); + +var _Config2 = _interopRequireDefault(_Config); + +var _express = require('express'); + +var _express2 = _interopRequireDefault(_express); + +var _path = require('path'); + +var _path2 = _interopRequireDefault(_path); + +var _fs = require('fs'); + +var _fs2 = _interopRequireDefault(_fs); + +var _querystring = require('querystring'); + +var _querystring2 = _interopRequireDefault(_querystring); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const public_html = _path2.default.resolve(__dirname, "../../public_html"); +const views = _path2.default.resolve(__dirname, '../../views'); + +class PublicAPIRouter extends _PromiseRouter2.default { + + verifyEmail(req) { + const { token, username } = req.query; + const appId = req.params.appId; + const config = _Config2.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 = _querystring2.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 = _Config2.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 = _Config2.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? + _fs2.default.readFile(_path2.default.resolve(views, "choose_password"), 'utf-8', (err, data) => { + if (err) { + return reject(err); + } + data = data.replace("PARSE_SERVER_URL", `'${config.publicServerURL}'`); + resolve({ + text: data + }); + }); + }); + } + + requestResetPassword(req) { + + const config = req.config; + + if (!config) { + this.invalidRequest(); + } + + if (!config.publicServerURL) { + return this.missingPublicServerURL(); + } + + const { username, token } = req.query; + + if (!username || !token) { + return this.invalidLink(req); + } + + return config.userController.checkResetTokenValidity(username, token).then(() => { + const params = _querystring2.default.stringify({ token, id: config.applicationId, username, app: config.appName }); + return Promise.resolve({ + status: 302, + location: `${config.choosePasswordURL}?${params}` + }); + }, () => { + return this.invalidLink(req); + }); + } + + resetPassword(req) { + + const config = req.config; + + if (!config) { + this.invalidRequest(); + } + + if (!config.publicServerURL) { + return this.missingPublicServerURL(); + } + + const { + username, + token, + new_password + } = req.body; + + if (!username || !token || !new_password) { + return this.invalidLink(req); + } + + return config.userController.updatePassword(username, token, new_password).then(() => { + const params = _querystring2.default.stringify({ username: username }); + return Promise.resolve({ + status: 302, + location: `${config.passwordResetSuccessURL}?${params}` + }); + }, err => { + const params = _querystring2.default.stringify({ username: username, token: token, id: config.applicationId, error: err, app: config.appName }); + return Promise.resolve({ + status: 302, + location: `${config.choosePasswordURL}?${params}` + }); + }); + } + + invalidLink(req) { + return Promise.resolve({ + status: 302, + location: req.config.invalidLinkURL + }); + } + + invalidVerificationLink(req) { + const config = req.config; + if (req.query.username && req.params.appId) { + const params = _querystring2.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 = _Config2.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 = _express2.default.Router(); + router.use("/apps", _express2.default.static(public_html)); + router.use("/", super.expressRouter()); + return router; + } +} + +exports.PublicAPIRouter = PublicAPIRouter; +exports.default = PublicAPIRouter; \ No newline at end of file diff --git a/lib/Routers/PurgeRouter.js b/lib/Routers/PurgeRouter.js new file mode 100644 index 0000000000..7f55981c42 --- /dev/null +++ b/lib/Routers/PurgeRouter.js @@ -0,0 +1,42 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PurgeRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class PurgeRouter extends _PromiseRouter2.default { + + handlePurge(req) { + 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: {} }; + }); + } + + mountRoutes() { + this.route('DELETE', '/purge/:className', middleware.promiseEnforceMasterKeyAccess, req => { + return this.handlePurge(req); + }); + } +} + +exports.PurgeRouter = PurgeRouter; +exports.default = PurgeRouter; \ No newline at end of file diff --git a/lib/Routers/PushRouter.js b/lib/Routers/PushRouter.js new file mode 100644 index 0000000000..a0cb95c9cf --- /dev/null +++ b/lib/Routers/PushRouter.js @@ -0,0 +1,88 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PushRouter = undefined; + +var _PromiseRouter = require("../PromiseRouter"); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require("../middlewares"); + +var middleware = _interopRequireWildcard(_middlewares); + +var _node = require("parse/node"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class PushRouter extends _PromiseRouter2.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; +exports.default = PushRouter; \ No newline at end of file diff --git a/lib/Routers/RolesRouter.js b/lib/Routers/RolesRouter.js new file mode 100644 index 0000000000..05ae6cccf6 --- /dev/null +++ b/lib/Routers/RolesRouter.js @@ -0,0 +1,39 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RolesRouter = undefined; + +var _ClassesRouter = require('./ClassesRouter'); + +var _ClassesRouter2 = _interopRequireDefault(_ClassesRouter); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class RolesRouter extends _ClassesRouter2.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; +exports.default = RolesRouter; \ No newline at end of file diff --git a/lib/Routers/SchemasRouter.js b/lib/Routers/SchemasRouter.js new file mode 100644 index 0000000000..01f909fcd6 --- /dev/null +++ b/lib/Routers/SchemasRouter.js @@ -0,0 +1,96 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SchemasRouter = undefined; + +var _PromiseRouter = require('../PromiseRouter'); + +var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter); + +var _middlewares = require('../middlewares'); + +var middleware = _interopRequireWildcard(_middlewares); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _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 _PromiseRouter2.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; \ No newline at end of file diff --git a/lib/Routers/SessionsRouter.js b/lib/Routers/SessionsRouter.js new file mode 100644 index 0000000000..dc614896ee --- /dev/null +++ b/lib/Routers/SessionsRouter.js @@ -0,0 +1,116 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SessionsRouter = undefined; + +var _ClassesRouter = require('./ClassesRouter'); + +var _ClassesRouter2 = _interopRequireDefault(_ClassesRouter); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _Auth = require('../Auth'); + +var _Auth2 = _interopRequireDefault(_Auth); + +var _RestWrite = require('../RestWrite'); + +var _RestWrite2 = _interopRequireDefault(_RestWrite); + +var _cryptoUtils = require('../cryptoUtils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SessionsRouter extends _ClassesRouter2.default { + + className() { + return '_Session'; + } + + handleMe(req) { + // TODO: Verify correct behavior + if (!req.info || !req.info.sessionToken) { + throw new _node2.default.Error(_node2.default.Error.INVALID_SESSION_TOKEN, 'Session token required.'); + } + return _rest2.default.find(req.config, _Auth2.default.master(req.config), '_Session', { sessionToken: req.info.sessionToken }, undefined, req.info.clientSDK).then(response => { + if (!response.results || response.results.length == 0) { + throw new _node2.default.Error(_node2.default.Error.INVALID_SESSION_TOKEN, 'Session token not found.'); + } + return { + response: response.results[0] + }; + }); + } + + handleUpdateToRevocableSession(req) { + const config = req.config; + const masterAuth = _Auth2.default.master(config); + const user = req.auth.user; + // Issue #2720 + // Calling without a session token would result in a not found user + if (!user) { + throw new _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'invalid session'); + } + const expiresAt = config.generateSessionExpiresAt(); + const sessionData = { + sessionToken: 'r:' + (0, _cryptoUtils.newToken)(), + user: { + __type: 'Pointer', + className: '_User', + objectId: user.id + }, + createdWith: { + 'action': 'upgrade' + }, + restricted: false, + installationId: req.auth.installationId, + expiresAt: _node2.default._encode(expiresAt) + }; + const create = new _RestWrite2.default(config, masterAuth, '_Session', null, sessionData); + return create.execute().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; +exports.default = SessionsRouter; \ No newline at end of file diff --git a/lib/Routers/UsersRouter.js b/lib/Routers/UsersRouter.js new file mode 100644 index 0000000000..472c5e4efb --- /dev/null +++ b/lib/Routers/UsersRouter.js @@ -0,0 +1,325 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.UsersRouter = undefined; + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _Config = require('../Config'); + +var _Config2 = _interopRequireDefault(_Config); + +var _AccountLockout = require('../AccountLockout'); + +var _AccountLockout2 = _interopRequireDefault(_AccountLockout); + +var _ClassesRouter = require('./ClassesRouter'); + +var _ClassesRouter2 = _interopRequireDefault(_ClassesRouter); + +var _rest = require('../rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _Auth = require('../Auth'); + +var _Auth2 = _interopRequireDefault(_Auth); + +var _password = require('../password'); + +var _password2 = _interopRequireDefault(_password); + +var _RestWrite = require('../RestWrite'); + +var _RestWrite2 = _interopRequireDefault(_RestWrite); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// These methods handle the User-related routes. + +const cryptoUtils = require('../cryptoUtils'); + +class UsersRouter extends _ClassesRouter2.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 (obj.hasOwnProperty(key)) { + // Regexp comes from Parse.Object.prototype.validate + if (key !== "__type" && !/^[A-Za-z][0-9A-Za-z_]*$/.test(key)) { + delete obj[key]; + } + } + } + } + + handleMe(req) { + if (!req.info || !req.info.sessionToken) { + throw new _node2.default.Error(_node2.default.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + } + const sessionToken = req.info.sessionToken; + return _rest2.default.find(req.config, _Auth2.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 _node2.default.Error(_node2.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 }; + } + }); + } + + handleLogIn(req) { + // 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 _node2.default.Error(_node2.default.Error.USERNAME_MISSING, 'username/email is required.'); + } + if (!password) { + throw new _node2.default.Error(_node2.default.Error.PASSWORD_MISSING, 'password is required.'); + } + if (typeof password !== 'string' || email && typeof email !== 'string' || username && typeof username !== 'string') { + throw new _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + + let user; + let isValidPassword = false; + const query = Object.assign({}, username ? { username } : {}, email ? { email } : {}); + return req.config.database.find('_User', query).then(results => { + if (!results.length) { + throw new _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + user = results[0]; + + if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) { + throw new _node2.default.Error(_node2.default.Error.EMAIL_NOT_FOUND, 'User email is not verified.'); + } + return _password2.default.compare(password, user.password); + }).then(correct => { + isValidPassword = correct; + const accountLockoutPolicy = new _AccountLockout2.default(user, req.config); + return accountLockoutPolicy.handleLoginAttempt(isValidPassword); + }).then(() => { + if (!isValidPassword) { + throw new _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + + // 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: _node2.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 _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Your password has expired. Please reset your password.'); + } + } + + const token = 'r:' + cryptoUtils.newToken(); + user.sessionToken = token; + delete user.password; + + // Remove hidden properties. + UsersRouter.removeHiddenProperties(user); + + // 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; + } + } + + req.config.filesController.expandFilesInObject(req.config, user); + + const expiresAt = req.config.generateSessionExpiresAt(); + const sessionData = { + sessionToken: token, + user: { + __type: 'Pointer', + className: '_User', + objectId: user.objectId + }, + createdWith: { + 'action': 'login', + 'authProvider': 'password' + }, + restricted: false, + expiresAt: _node2.default._encode(expiresAt) + }; + + if (req.info.installationId) { + sessionData.installationId = req.info.installationId; + } + + const create = new _RestWrite2.default(req.config, _Auth2.default.master(req.config), '_Session', null, sessionData); + return create.execute(); + }).then(() => { + return { response: user }; + }); + } + + handleLogOut(req) { + const success = { response: {} }; + if (req.info && req.info.sessionToken) { + return _rest2.default.find(req.config, _Auth2.default.master(req.config), '_Session', { sessionToken: req.info.sessionToken }, undefined, req.info.clientSDK).then(records => { + if (records.results && records.results.length) { + return _rest2.default.del(req.config, _Auth2.default.master(req.config), '_Session', records.results[0].objectId).then(() => { + return Promise.resolve(success); + }); + } + return Promise.resolve(success); + }); + } + return Promise.resolve(success); + } + + _throwOnBadEmailConfig(req) { + try { + _Config2.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 _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.EMAIL_MISSING, "you must provide an email"); + } + if (typeof email !== 'string') { + throw new _node2.default.Error(_node2.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 === _node2.default.Error.OBJECT_NOT_FOUND) { + throw new _node2.default.Error(_node2.default.Error.EMAIL_NOT_FOUND, `No user found with email ${email}.`); + } else { + throw err; + } + }); + } + + handleVerificationEmailRequest(req) { + this._throwOnBadEmailConfig(req); + + const { email } = req.body; + if (!email) { + throw new _node2.default.Error(_node2.default.Error.EMAIL_MISSING, 'you must provide an email'); + } + if (typeof email !== 'string') { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.EMAIL_NOT_FOUND, `No user found with email ${email}`); + } + const user = results[0]; + + if (user.emailVerified) { + throw new _node2.default.Error(_node2.default.Error.OTHER_CAUSE, `Email ${email} is already verified.`); + } + + const userController = req.config.userController; + 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); + }); + } +} + +exports.UsersRouter = UsersRouter; +exports.default = UsersRouter; \ No newline at end of file diff --git a/lib/StatusHandler.js b/lib/StatusHandler.js new file mode 100644 index 0000000000..1abf9778a2 --- /dev/null +++ b/lib/StatusHandler.js @@ -0,0 +1,324 @@ +'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 = require('./rest'); + +var _rest2 = _interopRequireDefault(_rest); + +var _Auth = require('./Auth'); + +var _Auth2 = _interopRequireDefault(_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 = _Auth2.default.master(config); + function create(object) { + lastPromise = lastPromise.then(() => { + return _rest2.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 _rest2.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 (body.hasOwnProperty('push_time')) { + if (config.hasPushScheduledSupport) { + pushTime = body.push_time; + status = 'scheduled'; + } else { + _logger.logger.warn('Trying to schedule a push while server is not configured.'); + _logger.logger.warn('Push will be sent immediately'); + } + } + + const data = body.data || {}; + const payloadString = JSON.stringify(data); + let pushHash; + if (typeof data.alert === 'string') { + pushHash = (0, _cryptoUtils.md5Hash)(data.alert); + } else if (typeof data.alert === 'object') { + pushHash = (0, _cryptoUtils.md5Hash)(JSON.stringify(data.alert)); + } else { + pushHash = 'd41d8cd98f00b204e9800998ecf8427e'; + } + const object = { + pushTime, + query: JSON.stringify(where), + payload: payloadString, + source: options.source, + title: options.title, + expiry: body.expiration_time, + expiration_interval: body.expiration_interval, + status: status, + numSent: 0, + pushHash, + // lockdown! + ACL: {} + }; + return handler.create(object).then(result => { + objectId = result.objectId; + pushStatus = { + objectId + }; + return Promise.resolve(pushStatus); + }); + }; + + const setRunning = function (batches) { + _logger.logger.verbose(`_PushStatus ${objectId}: sending push to installations with %d batches`, batches); + return handler.update({ + status: "pending", + objectId: objectId + }, { + status: "running", + count: batches + }); + }; + + const trackSent = function (results, UTCOffset, cleanupInstallations = process.env.PARSE_SERVER_CLEANUP_INVALID_INSTALLATIONS) { + const update = { + numSent: 0, + numFailed: 0 + }; + const devicesToRemove = []; + if (Array.isArray(results)) { + results = flatten(results); + results.reduce((memo, result) => { + // Cannot handle that + if (!result || !result.device || !result.device.deviceType) { + return memo; + } + const deviceType = result.device.deviceType; + const key = result.transmitted ? `sentPerType.${deviceType}` : `failedPerType.${deviceType}`; + memo[key] = incrementOp(memo, key); + if (typeof UTCOffset !== 'undefined') { + const offsetKey = result.transmitted ? `sentPerUTCOffset.${UTCOffset}` : `failedPerUTCOffset.${UTCOffset}`; + memo[offsetKey] = incrementOp(memo, offsetKey); + } + if (result.transmitted) { + memo.numSent++; + } else { + if (result && result.response && result.response.error && result.device && result.device.deviceToken) { + const token = result.device.deviceToken; + const error = result.response.error; + // GCM errors + if (error === 'NotRegistered' || error === 'InvalidRegistration') { + devicesToRemove.push(token); + } + // APNS errors + if (error === 'Unregistered' || error === 'BadDeviceToken') { + devicesToRemove.push(token); + } + } + memo.numFailed++; + } + return memo; + }, update); + } + + _logger.logger.verbose(`_PushStatus ${objectId}: sent push! %d success, %d failures`, update.numSent, update.numFailed); + _logger.logger.verbose(`_PushStatus ${objectId}: needs cleanup`, { devicesToRemove }); + ['numSent', 'numFailed'].forEach(key => { + if (update[key] > 0) { + update[key] = { + __op: 'Increment', + amount: update[key] + }; + } else { + delete update[key]; + } + }); + + if (devicesToRemove.length > 0 && cleanupInstallations) { + _logger.logger.info(`Removing device tokens on ${devicesToRemove.length} _Installations`); + database.update('_Installation', { deviceToken: { '$in': devicesToRemove } }, { deviceToken: { "__op": "Delete" } }, { + acl: undefined, + many: true + }); + } + + // indicate this batch is complete + incrementOp(update, 'count', -1); + + return handler.update({ objectId }, update).then(res => { + if (res && res.count === 0) { + return this.complete(); + } + }); + }; + + const complete = function () { + return handler.update({ objectId }, { + status: 'succeeded', + count: { __op: 'Delete' } + }); + }; + + const fail = function (err) { + if (typeof err === 'string') { + err = { message: err }; + } + const update = { + errorMessage: err, + status: 'failed' + }; + return handler.update({ objectId }, update); + }; + + const rval = { + setInitial, + setRunning, + trackSent, + complete, + fail + }; + + // define objectId to be dynamic + Object.defineProperty(rval, "objectId", { + get: () => objectId + }); + + return Object.freeze(rval); +} \ No newline at end of file diff --git a/lib/TestUtils.js b/lib/TestUtils.js new file mode 100644 index 0000000000..df58b7ceca --- /dev/null +++ b/lib/TestUtils.js @@ -0,0 +1,27 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.destroyAllDataPermanently = destroyAllDataPermanently; + +var _cache = require('./cache'); + +var _cache2 = _interopRequireDefault(_cache); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +//Used by tests +function destroyAllDataPermanently() { + if (!process.env.TESTING) { + throw 'Only supported in test environment'; + } + return Promise.all(Object.keys(_cache2.default.cache).map(appId => { + const app = _cache2.default.get(appId); + if (app.databaseController) { + return app.databaseController.deleteEverything(); + } else { + return Promise.resolve(); + } + })); +} \ No newline at end of file diff --git a/lib/batch.js b/lib/batch.js new file mode 100644 index 0000000000..1d95e529c0 --- /dev/null +++ b/lib/batch.js @@ -0,0 +1,98 @@ +'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); + + 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 => { + return { response: results }; + }); +} + +module.exports = { + mountOnto, + makeBatchRoutingPathFunction +}; \ No newline at end of file diff --git a/lib/cache.js b/lib/cache.js new file mode 100644 index 0000000000..51641150c3 --- /dev/null +++ b/lib/cache.js @@ -0,0 +1,11 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AppCache = undefined; + +var _InMemoryCache = require('./Adapters/Cache/InMemoryCache'); + +var AppCache = exports.AppCache = new _InMemoryCache.InMemoryCache({ ttl: NaN }); +exports.default = AppCache; \ 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..094e37ca72 --- /dev/null +++ b/lib/cli/definitions/parse-live-query-server.js @@ -0,0 +1,7 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +const LiveQueryServerOptions = require('../../Options/Definitions').LiveQueryServerOptions; +exports.default = LiveQueryServerOptions; \ 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..f9dbfe85ac --- /dev/null +++ b/lib/cli/definitions/parse-server.js @@ -0,0 +1,7 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +const ParseServerDefinitions = require('../../Options/Definitions').ParseServerOptions; +exports.default = ParseServerDefinitions; \ 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..4adcd0ea43 --- /dev/null +++ b/lib/cli/parse-live-query-server.js @@ -0,0 +1,21 @@ +'use strict'; + +var _parseLiveQueryServer = require('./definitions/parse-live-query-server'); + +var _parseLiveQueryServer2 = _interopRequireDefault(_parseLiveQueryServer); + +var _runner = require('./utils/runner'); + +var _runner2 = _interopRequireDefault(_runner); + +var _index = require('../index'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +(0, _runner2.default)({ + definitions: _parseLiveQueryServer2.default, + start: function (program, options, logOptions) { + logOptions(); + _index.ParseServer.createLiveQueryServer(undefined, options); + } +}); \ 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..125396c70c --- /dev/null +++ b/lib/cli/parse-server.js @@ -0,0 +1,98 @@ +'use strict'; + +var _index = require('../index'); + +var _index2 = _interopRequireDefault(_index); + +var _parseServer = require('./definitions/parse-server'); + +var _parseServer2 = _interopRequireDefault(_parseServer); + +var _cluster = require('cluster'); + +var _cluster2 = _interopRequireDefault(_cluster); + +var _os = require('os'); + +var _os2 = _interopRequireDefault(_os); + +var _runner = require('./utils/runner'); + +var _runner2 = _interopRequireDefault(_runner); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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(''); +}; /* eslint-disable no-console */ + + +(0, _runner2.default)({ + definitions: _parseServer2.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.cluster) { + const numCPUs = typeof options.cluster === 'number' ? options.cluster : _os2.default.cpus().length; + if (_cluster2.default.isMaster) { + logOptions(); + for (let i = 0; i < numCPUs; i++) { + _cluster2.default.fork(); + } + _cluster2.default.on('exit', (worker, code) => { + console.log(`worker ${worker.process.pid} died (${code})... Restarting`); + _cluster2.default.fork(); + }); + } else { + _index2.default.start(options, () => { + console.log('[' + process.pid + '] parse-server running on ' + options.serverURL); + }); + } + } else { + _index2.default.start(options, () => { + logOptions(); + console.log(''); + console.log('[' + process.pid + '] parse-server running on ' + options.serverURL); + }); + } + } +}); + +/* eslint-enable no-console */ \ 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..3059e45614 --- /dev/null +++ b/lib/cli/utils/commander.js @@ -0,0 +1,140 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _commander = require('commander'); + +var _path = require('path'); + +var _path2 = _interopRequireDefault(_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 = _path2.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 (!this.hasOwnProperty(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; + }, {}); +}; + +exports.default = new _commander.Command(); +/* eslint-enable no-console */ \ 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..0f38ab9e2e --- /dev/null +++ b/lib/cli/utils/runner.js @@ -0,0 +1,53 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function ({ + definitions, + help, + usage, + start +}) { + _commander2.default.loadDefinitions(definitions); + if (usage) { + _commander2.default.usage(usage); + } + if (help) { + _commander2.default.on('--help', help); + } + _commander2.default.parse(process.argv, process.env); + + const options = _commander2.default.getOptions(); + start(_commander2.default, options, function () { + logStartupOptions(options); + }); +}; + +var _commander = require("./commander"); + +var _commander2 = _interopRequireDefault(_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 (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 */ + } +} \ 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..47fd6e9d44 --- /dev/null +++ b/lib/cloud-code/HTTPResponse.js @@ -0,0 +1,56 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +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; \ 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..f33baa9116 --- /dev/null +++ b/lib/cloud-code/Parse.Cloud.js @@ -0,0 +1,72 @@ +'use strict'; + +var _node = require('parse/node'); + +var _triggers = require('../triggers'); + +var triggers = _interopRequireWildcard(_triggers); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function getClassName(parseClass) { + if (parseClass && parseClass.className) { + return parseClass.className; + } + return parseClass; +} + +var ParseCloud = {}; +ParseCloud.define = function (functionName, handler, validationHandler) { + triggers.addFunction(functionName, handler, validationHandler, _node.Parse.applicationId); +}; + +ParseCloud.job = function (functionName, handler) { + triggers.addJob(functionName, handler, _node.Parse.applicationId); +}; + +ParseCloud.beforeSave = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.beforeSave, className, handler, _node.Parse.applicationId); +}; + +ParseCloud.beforeDelete = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.beforeDelete, className, handler, _node.Parse.applicationId); +}; + +ParseCloud.afterSave = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.afterSave, className, handler, _node.Parse.applicationId); +}; + +ParseCloud.afterDelete = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.afterDelete, className, handler, _node.Parse.applicationId); +}; + +ParseCloud.beforeFind = function (parseClass, handler) { + var className = getClassName(parseClass); + triggers.addTrigger(triggers.Types.beforeFind, className, handler, _node.Parse.applicationId); +}; + +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; \ 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..64188f20dc --- /dev/null +++ b/lib/cloud-code/httpRequest.js @@ -0,0 +1,101 @@ +'use strict'; + +var _request = require('request'); + +var _request2 = _interopRequireDefault(_request); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _HTTPResponse = require('./HTTPResponse'); + +var _HTTPResponse2 = _interopRequireDefault(_HTTPResponse); + +var _querystring = require('querystring'); + +var _querystring2 = _interopRequireDefault(_querystring); + +var _logger = require('../logger'); + +var _logger2 = _interopRequireDefault(_logger); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var 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 = _querystring2.default.stringify(body); + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } else { + /* istanbul ignore next */ + if (contentTypeKeys.length > 1) { + _logger2.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 = _querystring2.default.stringify(body); + } + } + return { body, headers }; +}; + +module.exports = function (options) { + var promise = new _node2.default.Promise(); + var callbacks = { + success: options.success, + error: options.error + }; + delete options.success; + delete options.error; + delete options.uri; // not supported + options = Object.assign(options, encodeBody(options)); + // set follow redirects to false by default + options.followRedirect = options.followRedirects == true; + // support params options + if (typeof options.params === 'object') { + options.qs = options.params; + } else if (typeof options.params === 'string') { + options.qs = _querystring2.default.parse(options.params); + } + // force the response as a buffer + options.encoding = null; + + (0, _request2.default)(options, (error, response, body) => { + if (error) { + if (callbacks.error) { + callbacks.error(error); + } + return promise.reject(error); + } + const httpResponse = new _HTTPResponse2.default(response, body); + + // Consider <200 && >= 400 as errors + if (httpResponse.status < 200 || httpResponse.status >= 400) { + if (callbacks.error) { + callbacks.error(httpResponse); + } + return promise.reject(httpResponse); + } else { + if (callbacks.success) { + callbacks.success(httpResponse); + } + return promise.resolve(httpResponse); + } + }); + return promise; +}; + +module.exports.encodeBody = encodeBody; \ No newline at end of file diff --git a/lib/cryptoUtils.js b/lib/cryptoUtils.js new file mode 100644 index 0000000000..1eae0aab4c --- /dev/null +++ b/lib/cryptoUtils.js @@ -0,0 +1,58 @@ +'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'); +} \ No newline at end of file diff --git a/lib/defaults.js b/lib/defaults.js new file mode 100644 index 0000000000..2fadaeaee0 --- /dev/null +++ b/lib/defaults.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DefaultMongoURI = undefined; + +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 (def.hasOwnProperty('default')) { + memo[key] = def.default; + } + return memo; +}, {}); + +const computedDefaults = { + jsonLogs: process.env.JSON_LOGS || false, + logsFolder, + verbose, + level +}; + +exports.default = Object.assign({}, DefinitionDefaults, computedDefaults); +const DefaultMongoURI = exports.DefaultMongoURI = DefinitionDefaults.databaseURI; \ No newline at end of file diff --git a/lib/deprecated.js b/lib/deprecated.js new file mode 100644 index 0000000000..f808c611c6 --- /dev/null +++ b/lib/deprecated.js @@ -0,0 +1,11 @@ +"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}`; + }; +} \ No newline at end of file diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000000..b3ba2ad882 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,77 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ParseServer = exports.PushWorker = exports.TestUtils = exports.LRUCacheAdapter = exports.RedisCacheAdapter = exports.NullCacheAdapter = exports.InMemoryCacheAdapter = exports.FileSystemAdapter = exports.GCSAdapter = exports.S3Adapter = undefined; + +var _ParseServer2 = require('./ParseServer'); + +var _ParseServer3 = _interopRequireDefault(_ParseServer2); + +var _s3FilesAdapter = require('@parse/s3-files-adapter'); + +var _s3FilesAdapter2 = _interopRequireDefault(_s3FilesAdapter); + +var _fsFilesAdapter = require('@parse/fs-files-adapter'); + +var _fsFilesAdapter2 = _interopRequireDefault(_fsFilesAdapter); + +var _InMemoryCacheAdapter = require('./Adapters/Cache/InMemoryCacheAdapter'); + +var _InMemoryCacheAdapter2 = _interopRequireDefault(_InMemoryCacheAdapter); + +var _NullCacheAdapter = require('./Adapters/Cache/NullCacheAdapter'); + +var _NullCacheAdapter2 = _interopRequireDefault(_NullCacheAdapter); + +var _RedisCacheAdapter = require('./Adapters/Cache/RedisCacheAdapter'); + +var _RedisCacheAdapter2 = _interopRequireDefault(_RedisCacheAdapter); + +var _LRUCache = require('./Adapters/Cache/LRUCache.js'); + +var _LRUCache2 = _interopRequireDefault(_LRUCache); + +var _TestUtils = require('./TestUtils'); + +var TestUtils = _interopRequireWildcard(_TestUtils); + +var _deprecated = require('./deprecated'); + +var _logger = require('./logger'); + +var _PushWorker = require('./Push/PushWorker'); + +var _Options = require('./Options'); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Factory function +const _ParseServer = function (options) { + const server = new _ParseServer3.default(options); + return server.app; +}; +// Mount the create liveQueryServer +_ParseServer.createLiveQueryServer = _ParseServer3.default.createLiveQueryServer; +_ParseServer.start = _ParseServer3.default.start; + +const GCSAdapter = (0, _deprecated.useExternal)('GCSAdapter', '@parse/gcs-files-adapter'); + +Object.defineProperty(module.exports, 'logger', { + get: _logger.getLogger +}); + +exports.default = _ParseServer3.default; +exports.S3Adapter = _s3FilesAdapter2.default; +exports.GCSAdapter = GCSAdapter; +exports.FileSystemAdapter = _fsFilesAdapter2.default; +exports.InMemoryCacheAdapter = _InMemoryCacheAdapter2.default; +exports.NullCacheAdapter = _NullCacheAdapter2.default; +exports.RedisCacheAdapter = _RedisCacheAdapter2.default; +exports.LRUCacheAdapter = _LRUCache2.default; +exports.TestUtils = TestUtils; +exports.PushWorker = _PushWorker.PushWorker; +exports.ParseServer = _ParseServer; \ No newline at end of file diff --git a/lib/logger.js b/lib/logger.js new file mode 100644 index 0000000000..1f9e6dea5e --- /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 = require('./defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +var _WinstonLoggerAdapter = require('./Adapters/Logger/WinstonLoggerAdapter'); + +var _LoggerController = require('./Controllers/LoggerController'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function defaultLogger() { + const options = { + logsFolder: _defaults2.default.logsFolder, + jsonLogs: _defaults2.default.jsonLogs, + verbose: _defaults2.default.verbose, + silent: _defaults2.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 +}); \ No newline at end of file diff --git a/lib/middlewares.js b/lib/middlewares.js new file mode 100644 index 0000000000..4b336419f7 --- /dev/null +++ b/lib/middlewares.js @@ -0,0 +1,344 @@ +'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; + +var _cache = require('./cache'); + +var _cache2 = _interopRequireDefault(_cache); + +var _logger = require('./logger'); + +var _logger2 = _interopRequireDefault(_logger); + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _Auth = require('./Auth'); + +var _Auth2 = _interopRequireDefault(_Auth); + +var _Config = require('./Config'); + +var _Config2 = _interopRequireDefault(_Config); + +var _ClientSDK = require('./ClientSDK'); + +var _ClientSDK2 = _interopRequireDefault(_ClientSDK); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// 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 mountPathLength = req.originalUrl.length - req.url.length; + var mountPath = req.originalUrl.slice(0, mountPathLength); + var mount = req.protocol + '://' + req.get('host') + mountPath; + + 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 (_cache2.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 || !_cache2.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 && _cache2.default.get(req.body._ApplicationId) && (!info.masterKey || _cache2.default.get(req.body._ApplicationId).masterKey === info.masterKey)) { + info.appId = req.body._ApplicationId; + info.javascriptKey = req.body._JavaScriptKey || ''; + delete req.body._ApplicationId; + delete req.body._JavaScriptKey; + // TODO: test that the REST API formats generated by the other + // SDKs are handled ok + if (req.body._ClientVersion) { + info.clientVersion = req.body._ClientVersion; + delete req.body._ClientVersion; + } + if (req.body._InstallationId) { + info.installationId = req.body._InstallationId; + delete req.body._InstallationId; + } + if (req.body._SessionToken) { + info.sessionToken = req.body._SessionToken; + delete req.body._SessionToken; + } + if (req.body._MasterKey) { + info.masterKey = req.body._MasterKey; + delete req.body._MasterKey; + } + if (req.body._ContentType) { + req.headers['content-type'] = req.body._ContentType; + delete req.body._ContentType; + } + } else { + return invalidRequest(req, res); + } + } + + if (info.clientVersion) { + info.clientSDK = _ClientSDK2.default.fromString(info.clientVersion); + } + + if (fileViaJSON) { + // We need to repopulate req.body with a buffer + var base64 = req.body.base64; + req.body = new Buffer(base64, 'base64'); + } + + const clientIp = getClientIp(req); + + info.app = _cache2.default.get(info.appId); + req.config = _Config2.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 _Auth2.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 _Auth2.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 _Auth2.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 _Auth2.default.getAuthForLegacySessionToken({ config: req.config, installationId: info.installationId, sessionToken: info.sessionToken }); + } else { + return _Auth2.default.getAuthForSessionToken({ config: req.config, installationId: info.installationId, sessionToken: info.sessionToken }); + } + }).then(auth => { + if (auth) { + req.auth = auth; + next(); + } + }).catch(error => { + if (error instanceof _node2.default.Error) { + next(error); + return; + } else { + // TODO: Determine the correct error scenario. + _logger2.default.error('error getting auth for sessionToken', error); + throw new _node2.default.Error(_node2.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 new Buffer(str, 'base64').toString(); +} + +function allowCrossDomain(req, res, next) { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); + res.header('Access-Control-Allow-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, X-CSRF-Token'); + + // 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) { + if (err instanceof _node2.default.Error) { + let httpStatus; + // TODO: fill out this mapping + switch (err.code) { + case _node2.default.Error.INTERNAL_SERVER_ERROR: + httpStatus = 500; + break; + case _node2.default.Error.OBJECT_NOT_FOUND: + httpStatus = 404; + break; + default: + httpStatus = 400; + } + + res.status(httpStatus); + res.json({ code: err.code, error: err.message }); + _logger2.default.error(err.message, err); + } else if (err.status && err.message) { + res.status(err.status); + res.json({ error: err.message }); + next(err); + } else { + _logger2.default.error('Uncaught internal server error.', err, err.stack); + res.status(500); + res.json({ + code: _node2.default.Error.INTERNAL_SERVER_ERROR, + message: 'Internal server error.' + }); + next(err); + } +} + +function enforceMasterKeyAccess(req, res, next) { + if (!req.auth.isMaster) { + res.status(403); + res.end('{"error":"unauthorized: master key is required"}'); + return; + } + next(); +} + +function promiseEnforceMasterKeyAccess(request) { + if (!request.auth.isMaster) { + const error = new Error(); + error.status = 403; + error.message = "unauthorized: master key is required"; + throw error; + } + return Promise.resolve(); +} + +function invalidRequest(req, res) { + res.status(403); + res.end('{"error":"unauthorized"}'); +} \ No newline at end of file diff --git a/lib/password.js b/lib/password.js new file mode 100644 index 0000000000..729a07b272 --- /dev/null +++ b/lib/password.js @@ -0,0 +1,29 @@ +'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 +}; \ No newline at end of file diff --git a/lib/requiredParameter.js b/lib/requiredParameter.js new file mode 100644 index 0000000000..844b5a0749 --- /dev/null +++ b/lib/requiredParameter.js @@ -0,0 +1,9 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = errorMessage => { + throw errorMessage; +}; \ No newline at end of file diff --git a/lib/rest.js b/lib/rest.js new file mode 100644 index 0000000000..ffe0e0326a --- /dev/null +++ b/lib/rest.js @@ -0,0 +1,180 @@ +'use strict'; + +var _Auth = require('./Auth'); + +var _Auth2 = _interopRequireDefault(_Auth); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// 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.couldUpdateUserId(objectId)) { + throw new Parse.Error(Parse.Error.SESSION_MISSING, 'insufficient auth to delete user'); + } + + enforceRoleSecurity('delete', className, auth); + + var inflatedObject; + + return Promise.resolve().then(() => { + const hasTriggers = checkTriggers(className, config, ['beforeDelete', 'afterDelete']); + const hasLiveQuery = checkLiveQuery(className, config); + if (hasTriggers || hasLiveQuery || className == '_Session') { + return find(config, _Auth2.default.master(config), className, { objectId: objectId }).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); + // Notify LiveQuery server if possible + config.liveQueryController.onAfterDelete(inflatedObject.className, inflatedObject); + 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(() => { + var 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); + }).then(() => { + return triggers.maybeRunTrigger(triggers.Types.afterDelete, auth, inflatedObject, null, config); + }); +} + +// 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) { + return find(config, _Auth2.default.master(config), className, restWhere); + } + return Promise.resolve({}); + }).then(response => { + var originalRestObject; + if (response && response.results && response.results.length) { + originalRestObject = response.results[0]; + } + + var write = new RestWrite(config, auth, className, restWhere, restObject, originalRestObject, clientSDK); + return write.execute(); + }); +} + +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 +}; \ No newline at end of file diff --git a/lib/triggers.js b/lib/triggers.js new file mode 100644 index 0000000000..8c3ca80db8 --- /dev/null +++ b/lib/triggers.js @@ -0,0 +1,467 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Types = undefined; +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.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; + +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + +var _logger = require('./logger'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// triggers.js +const Types = exports.Types = { + beforeSave: 'beforeSave', + afterSave: 'afterSave', + beforeDelete: 'beforeDelete', + afterDelete: 'afterDelete', + beforeFind: 'beforeFind', + afterFind: 'afterFind' +}; + +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) { + const restrictedClassNames = ['_Session']; + if (restrictedClassNames.indexOf(className) != -1) { + throw `Triggers are not supported for ${className} class.`; + } + 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'; + } + return className; +} + +const _triggerStore = {}; + +function addFunction(functionName, handler, validationHandler, applicationId) { + applicationId = applicationId || _node2.default.applicationId; + _triggerStore[applicationId] = _triggerStore[applicationId] || baseStore(); + _triggerStore[applicationId].Functions[functionName] = handler; + _triggerStore[applicationId].Validators[functionName] = validationHandler; +} + +function addJob(jobName, handler, applicationId) { + applicationId = applicationId || _node2.default.applicationId; + _triggerStore[applicationId] = _triggerStore[applicationId] || baseStore(); + _triggerStore[applicationId].Jobs[jobName] = handler; +} + +function addTrigger(type, className, handler, applicationId) { + validateClassNameForTriggers(className, type); + applicationId = applicationId || _node2.default.applicationId; + _triggerStore[applicationId] = _triggerStore[applicationId] || baseStore(); + _triggerStore[applicationId].Triggers[type][className] = handler; +} + +function addLiveQueryEventHandler(handler, applicationId) { + applicationId = applicationId || _node2.default.applicationId; + _triggerStore[applicationId] = _triggerStore[applicationId] || baseStore(); + _triggerStore[applicationId].LiveQuery.push(handler); +} + +function removeFunction(functionName, applicationId) { + applicationId = applicationId || _node2.default.applicationId; + delete _triggerStore[applicationId].Functions[functionName]; +} + +function removeTrigger(type, className, applicationId) { + applicationId = applicationId || _node2.default.applicationId; + delete _triggerStore[applicationId].Triggers[type][className]; +} + +function _unregisterAll() { + Object.keys(_triggerStore).forEach(appId => delete _triggerStore[appId]); +} + +function getTrigger(className, triggerType, applicationId) { + if (!applicationId) { + throw "Missing ApplicationID"; + } + var manager = _triggerStore[applicationId]; + if (manager && manager.Triggers && manager.Triggers[triggerType] && manager.Triggers[triggerType][className]) { + return manager.Triggers[triggerType][className]; + } + return undefined; +} + +function triggerExists(className, type, applicationId) { + return getTrigger(className, type, applicationId) != undefined; +} + +function getFunction(functionName, applicationId) { + var manager = _triggerStore[applicationId]; + if (manager && manager.Functions) { + return manager.Functions[functionName]; + } + return undefined; +} + +function getJob(jobName, applicationId) { + var manager = _triggerStore[applicationId]; + if (manager && manager.Jobs) { + return manager.Jobs[jobName]; + } + return undefined; +} + +function getJobs(applicationId) { + var manager = _triggerStore[applicationId]; + if (manager && manager.Jobs) { + return manager.Jobs; + } + return undefined; +} + +function getValidator(functionName, applicationId) { + var manager = _triggerStore[applicationId]; + if (manager && manager.Validators) { + return manager.Validators[functionName]; + } + return undefined; +} + +function getRequestObject(triggerType, auth, parseObject, originalParseObject, config) { + var request = { + triggerName: triggerType, + object: parseObject, + master: false, + log: config.loggerController, + headers: config.headers, + ip: config.ip + }; + + if (originalParseObject) { + request.original = originalParseObject; + } + + 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 && !request.object.equals(response) && request.triggerName === Types.beforeSave) { + return resolve(response); + } + response = {}; + if (request.triggerName === Types.beforeSave) { + response['object'] = request.object._getSaveJSON(); + } + return resolve(response); + }, + error: function (code, message) { + if (!message) { + message = code; + code = _node2.default.Error.SCRIPT_FAILED; + } + var scriptError = new _node2.default.Error(code, message); + return reject(scriptError); + } + }; +} + +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 response = 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 _node2.default.Object.fromJSON(object); + }); + const triggerPromise = trigger(request, response); + if (triggerPromise && typeof triggerPromise.then === "function") { + return triggerPromise.then(promiseResults => { + if (promiseResults) { + resolve(promiseResults); + } else { + return reject(new _node2.default.Error(_node2.default.Error.SCRIPT_FAILED, "AfterFind expect results to be returned in the promise")); + } + }); + } + }).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 parseQuery = new _node2.default.Query(className); + if (restWhere) { + parseQuery._where = restWhere; + } + let count = false; + if (restOptions) { + if (restOptions.include && restOptions.include.length > 0) { + parseQuery._include = restOptions.include.split(','); + } + if (restOptions.skip) { + parseQuery._skip = restOptions.skip; + } + if (restOptions.limit) { + parseQuery._limit = restOptions.limit; + } + 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 _node2.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.keys) { + restOptions = restOptions || {}; + restOptions.keys = jsonQuery.keys; + } + 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 _node2.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) { + 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); + var response = getResponseObject(request, object => { + logTriggerSuccessBeforeHook(triggerType, parseObject.className, parseObject.toJSON(), object, auth); + resolve(object); + }, error => { + logTriggerErrorBeforeHook(triggerType, parseObject.className, parseObject.toJSON(), auth, error); + reject(error); + }); + // Force the current Parse app before the trigger + _node2.default.applicationId = config.applicationId; + _node2.default.javascriptKey = config.javascriptKey || ''; + _node2.default.masterKey = config.masterKey; + + // 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. + var triggerPromise = trigger(request, response); + if (triggerType === Types.afterSave || triggerType === Types.afterDelete) { + logTriggerAfterHook(triggerType, parseObject.className, parseObject.toJSON(), auth); + if (triggerPromise && typeof triggerPromise.then === "function") { + return triggerPromise.then(resolve, resolve); + } else { + return resolve(); + } + } + }); +} + +// 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 _node2.default.Object.fromJSON(copy); +} + +function runLiveQueryEventHandlers(data, applicationId = _node2.default.applicationId) { + if (!_triggerStore || !_triggerStore[applicationId] || !_triggerStore[applicationId].LiveQuery) { + return; + } + _triggerStore[applicationId].LiveQuery.forEach(handler => handler(data)); +} \ No newline at end of file diff --git a/lib/vendor/README.md b/lib/vendor/README.md new file mode 100644 index 0000000000..6bcf5df262 --- /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..091ed8e742 --- /dev/null +++ b/lib/vendor/mongodbUrl.js @@ -0,0 +1,924 @@ +// 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) { + result.hostname = result.host = isAbsolute ? '' : 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; +} \ No newline at end of file diff --git a/package.json b/package.json index 0a6ce60975..529f9c17f8 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,8 @@ "@parse/push-adapter": "2.0.2", "@parse/s3-files-adapter": "1.2.1", "@parse/simple-mailgun-adapter": "1.0.1", + "adm-zip": "0.4.7", + "archiver": "1.3.0", "bcryptjs": "2.4.3", "body-parser": "1.18.2", "commander": "2.12.1", @@ -38,6 +40,7 @@ "redis": "2.8.0", "request": "2.83.0", "semver": "5.4.1", + "tmp": "0.0.33", "tv4": "1.3.0", "uuid": "^3.1.0", "winston": "2.4.0", diff --git a/spec/Export.spec.js b/spec/Export.spec.js new file mode 100644 index 0000000000..961c99cb0b --- /dev/null +++ b/spec/Export.spec.js @@ -0,0 +1,139 @@ +const Parse = require("parse/node"); +const request = require('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); + }; + + it_exclude_dbs(['postgres'])('should create export progress', (done) => { + + reconfigureServer({ + emailAdapter : { + sendMail : () => { + done(); + } + } + }) + .then(() => { + return createRecords(3000); + }) + .then(() => { + request.put( + { + headers: headers, + url: 'http://localhost:8378/1/export_data', + body: JSON.stringify({ + name: 'ExportTest', + feedbackEmail: 'my@email.com' + }) + }, + () => { + + request.get( + { + headers: headers, + url: 'http://localhost:8378/1/export_progress' + }, + (err, response, body) => { + + const progress = JSON.parse(body); + + expect(progress instanceof Array).toBe(true); + expect(progress.length).toBe(1); + + if (progress.length) { + expect(progress[0].id).toBe('ExportTest'); + } + }); + } + ); + } + ).catch(fail); + }); + + 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.get({ url: link, encoding: null }, function(err, res, zipFile) { + + if(err) throw err; + + const zip = new AdmZip(zipFile); + 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(); + }); + } + } + reconfigureServer({ + emailAdapter: emailAdapter, + publicServerURL: "http://localhost:8378/1" + }) + .then(() => { + return createRecords(2176); + }) + .then(() => { + request.get( + { + headers: headers, + url: 'http://localhost:8378/1/classes/ExportTest', + }, + (err, response, body) => { + results = JSON.parse(body); + + request.put( + { + headers: headers, + url: 'http://localhost:8378/1/export_data', + body: JSON.stringify({ + name: 'ExportTest', + feedbackEmail: 'my@email.com' + }) + }, + (err, response, body) => { + expect(err).toBe(null); + expect(body).toEqual('"We are exporting your data. You will be notified by e-mail once it is completed."'); + } + ); + } + ); + }); + }); +}); diff --git a/spec/Import.spec.js b/spec/Import.spec.js new file mode 100644 index 0000000000..06b932ad87 --- /dev/null +++ b/spec/Import.spec.js @@ -0,0 +1,460 @@ +const Parse = require("parse/node"); +const request = require('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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_data/TestObject', + formData: { + importFile: { + value: Buffer.from(JSON.stringify({ + rows:[ + { column1: 'row1Column1', column2: 'row1Column2' }, + { column1: 'row2Column1', column2: 'row2Column2' } + ] + })), + options: { + filename: 'TestObject.json' + } + } + } + }, + (err) => { + + expect(err).toBe(null); + + 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(); + }); + } + ); + }); + + 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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_data/TestObject', + formData: { + importFile: { + value: Buffer.from(JSON.stringify({ + results: [ + {column1: 'row1Column1', column2: 'row1Column2'}, + {column1: 'row2Column1', column2: 'row2Column2'} + ] + })), + options: { + filename: 'TestObject.json' + } + } + } + }, + (err) => { + expect(err).toBe(null); + 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(); + }); + } + ); + }); + + 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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_data/TestObject', + formData: { + 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' + } + } + } + }, + (err) => { + expect(err).toBe(null); + 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(); + }); + } + ); + }); + + 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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_data/TestObject', + formData: { + 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' + } + } + } + }, + (err) => { + expect(err).toBe(null); + 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(); + }); + } + ); + }); + + 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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_data/TestObject', + formData: { + importFile: { + value: Buffer.from(JSON.stringify({ + results: [ + { + 'objectId': 'aaaaaaaaaa', + 'data': 'somedataa' + }, + { + 'objectId': 'bbbbbbbbbb', + 'data': 'somedatab' + } + ] + })), + options: { + filename: 'TestObject.json' + } + } + } + }, + (err) => { + expect(err).toBe(null); + request.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_data/TestObject', + formData: { + importFile: { + value: Buffer.from(JSON.stringify({ + results: [ + { + 'objectId': 'aaaaaaaaaa', + 'data': 'somedataa2' + } + ] + })), + options: { + filename: 'TestObject.json' + } + } + } + }, + (err) => { + expect(err).toBe(null); + 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(); + }); + } + ); + } + ); + }); + + 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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_data/TestObject', + formData: { + importFile: { + value: Buffer.from(JSON.stringify({ + results: [ + {column1: 'row1Column1', column2: 'row1Column2'}, + {column1: 'row2Column1', column2: 'row2Column2'} + ], + })), + options: { + filename: 'TestObject.json' + } + }, + feedbackEmail: 'my@email.com' + } + }, + (err, response, body) => { + expect(err).toBe(null); + expect(JSON.parse(body).response).toEqual('We are importing your data. You will be notified by e-mail once it is completed.'); + } + ); + }); + }); + + 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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_relation_data/TestObjectDad/RelationObject', + formData: { + importFile: { + value: Buffer.from(JSON.stringify({ + results: [ + { + 'owningId': ids.a, + 'relatedId': ids.b + } + ] + })), + options: { + filename: 'TestObject:RelationObject.json' + } + } + } + }, + (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(); + }); + } + ) + }); + }); + + 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.post( + { + headers: headers, + url: 'http://localhost:8378/1/import_relation_data/TestObjectDad/RelationObject', + formData: { + importFile: { + value: Buffer.from(JSON.stringify({ + results: [ + { + 'owningId': ids.a, + 'relatedId': ids.b + } + ] + })), + options: { + filename: 'TestObject:RelationObject.json' + } + }, + feedbackEmail: 'my@email.com' + } + }, + (err, response, body) => { + expect(err).toBe(null); + expect(body).toEqual('{"response":"We are importing your data. You will be notified by e-mail once it is completed."}'); + } + ); + }); + }); + }); +}); diff --git a/src/Adapters/PubSub/RedisPubSub.js b/src/Adapters/PubSub/RedisPubSub.js index 7fb62dfca2..29f4dcf512 100644 --- a/src/Adapters/PubSub/RedisPubSub.js +++ b/src/Adapters/PubSub/RedisPubSub.js @@ -1,18 +1,62 @@ import redis from 'redis'; +import Parse from 'parse/node'; function createPublisher({redisURL}): any { - return redis.createClient(redisURL, { no_ready_check: true }); + var redisCli = redis.createClient(redisURL, { no_ready_check: true }); + + if (redisCli) { + redisCli.publish2 = redisCli.publish; + + redisCli.publish = function (channel, body) { + var bodyObject; + try { + bodyObject = JSON.parse(body); + } catch (e) { + bodyObject = {}; + } + if (bodyObject && bodyObject.pushStatus) { + redisCli.multi([ + ['sadd', bodyObject.applicationId + ':push', body] + ]).exec(); + } + return redisCli.publish2(channel, body); + }; + } + + return redisCli; } function createSubscriber({redisURL}): any { - return redis.createClient(redisURL, { no_ready_check: true }); + var redisCli = redis.createClient(redisURL, { no_ready_check: true }); + var secondaryClient = redis.createClient(redisURL, { no_ready_check: true }); + if (redisCli) { + redisCli.run = function (workItem) { + return new Parse.Promise(function (resolve) { + secondaryClient + .multi([ + ['spop', workItem.applicationId + ':push'] + ]) + .exec(function (err, rep) { + if (!err && rep && rep[0]) { + resolve(JSON.parse(rep[0])); + } else { + resolve(); + } + }) + }); + }; + } + + return redisCli; } const RedisPubSub = { createPublisher, createSubscriber -} +}; export { - RedisPubSub + RedisPubSub, + createPublisher, + createSubscriber } diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index ab579b6aa2..14a9847d78 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -124,6 +124,12 @@ const defaultColumns = Object.freeze({ "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'} } }); @@ -132,9 +138,9 @@ const requiredColumns = Object.freeze({ _Role: ["name", "ACL"] }); -const systemClasses = Object.freeze(['_User', '_Installation', '_Role', '_Session', '_Product', '_PushStatus', '_JobStatus', '_JobSchedule', '_Audience']); +const systemClasses = Object.freeze(['_User', '_Installation', '_Role', '_Session', '_Product', '_PushStatus', '_JobStatus', '_JobSchedule', '_Audience', '_ExportProgress' ]); -const volatileClasses = Object.freeze(['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig', '_JobSchedule', '_Audience']); +const volatileClasses = Object.freeze(['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig', '_JobSchedule', '_Audience', '_ExportProgress']); // 10 alpha numberic chars + uppercase const userIdRegex = /^[a-zA-Z0-9]{10}$/; diff --git a/src/ParseServer.js b/src/ParseServer.js index 76631ea3d9..ced6577620 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -35,6 +35,8 @@ import { UsersRouter } from './Routers/UsersRouter'; import { PurgeRouter } from './Routers/PurgeRouter'; import { AudiencesRouter } from './Routers/AudiencesRouter'; import { AggregateRouter } from './Routers/AggregateRouter'; +import { ImportRouter } from './Routers/ImportRouter'; +import { ExportRouter } from './Routers/ExportRouter'; import { ParseServerRESTController } from './ParseServerRESTController'; import * as controllers from './Controllers'; @@ -146,6 +148,7 @@ class ParseServer { api.use('/', bodyParser.urlencoded({extended: false}), new PublicAPIRouter().expressRouter()); + api.use('/', middlewares.allowCrossDomain, new ImportRouter().expressRouter()); api.use(bodyParser.json({ 'type': '*/*' , limit: maxUploadSize })); api.use(middlewares.allowCrossDomain); api.use(middlewares.allowMethodOverride); @@ -196,6 +199,7 @@ class ParseServer { new FeaturesRouter(), new GlobalConfigRouter(), new PurgeRouter(), + new ExportRouter(), new HooksRouter(), new CloudCodeRouter(), new AudiencesRouter(), diff --git a/src/Push/PushWorker.js b/src/Push/PushWorker.js index afd4416dc9..f96a281040 100644 --- a/src/Push/PushWorker.js +++ b/src/Push/PushWorker.js @@ -21,7 +21,7 @@ function groupByBadge(installations) { } export class PushWorker { - subscriber: ?any; + subscriber: any; adapter: any; channel: string; @@ -36,7 +36,7 @@ export class PushWorker { subscriber.subscribe(this.channel); subscriber.on('message', (channel, messageStr) => { const workItem = JSON.parse(messageStr); - this.run(workItem); + this.getAndRun(workItem); }); } } @@ -47,7 +47,7 @@ export class PushWorker { } } - run({ body, query, pushStatus, applicationId, UTCOffset }: any): Promise<*> { + run({ body, query, pushStatus, applicationId, UTCOffset }: any): Promise { const config = Config.get(applicationId); const auth = master(config); const where = utils.applyDeviceTokenExists(query.where); @@ -55,7 +55,7 @@ export class PushWorker { pushStatus = pushStatusHandler(config, pushStatus.objectId); return rest.find(config, auth, '_Installation', where, query).then(({results}) => { if (results.length == 0) { - return; + return pushStatus.trackSent(results); } return this.sendToAdapter(body, results, pushStatus, config, UTCOffset); }, err => { @@ -63,7 +63,7 @@ export class PushWorker { }); } - sendToAdapter(body: any, installations: any[], pushStatus: any, config: Config, UTCOffset: ?any): Promise<*> { + sendToAdapter(body: any, installations: any, pushStatus: any, config: Config, UTCOffset: any): Promise { // Check if we have locales in the push body const locales = utils.getLocalesFromPush(body); if (locales.length > 0) { @@ -83,7 +83,8 @@ export class PushWorker { if (!utils.isPushIncrementing(body)) { logger.verbose(`Sending push to ${installations.length}`); return this.adapter.send(body, installations, pushStatus.objectId).then((results) => { - return pushStatus.trackSent(results, UTCOffset).then(() => results); + return pushStatus.trackSent(results, UTCOffset, undefined, installations.length - results.length) + .then(() => results); }); } @@ -99,6 +100,23 @@ export class PushWorker { }); return Promise.all(promises); } + + getAndRun(workItem: any): Promise { + var _this = this; + if (!_this.subscriber.run) { + return _this.run(workItem); + } + return _this.subscriber.run(workItem).then(function (gotItem) { + if (gotItem) { + return _this.run(gotItem) + .then(function () { + return _this.getAndRun(gotItem) + }) + } else { + return Promise.resolve(); + } + }); + } } export default PushWorker; diff --git a/src/RestQuery.js b/src/RestQuery.js index 0af910522b..c7f6a9f29e 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -263,7 +263,8 @@ RestQuery.prototype.replaceInQuery = function() { } const additionalOptions = { - redirectClassNameForKey: inQueryValue.redirectClassNameForKey + redirectClassNameForKey: inQueryValue.redirectClassNameForKey, + keys: 'objectId' }; if (this.restOptions.subqueryReadPreference) { @@ -316,7 +317,8 @@ RestQuery.prototype.replaceNotInQuery = function() { } const additionalOptions = { - redirectClassNameForKey: notInQueryValue.redirectClassNameForKey + redirectClassNameForKey: notInQueryValue.redirectClassNameForKey, + keys: 'objectId' }; if (this.restOptions.subqueryReadPreference) { @@ -371,7 +373,8 @@ RestQuery.prototype.replaceSelect = function() { } const additionalOptions = { - redirectClassNameForKey: selectValue.query.redirectClassNameForKey + redirectClassNameForKey: selectValue.query.redirectClassNameForKey, + keys: selectValue.key }; if (this.restOptions.subqueryReadPreference) { @@ -424,7 +427,8 @@ RestQuery.prototype.replaceDontSelect = function() { 'improper usage of $dontSelect'); } const additionalOptions = { - redirectClassNameForKey: dontSelectValue.query.redirectClassNameForKey + redirectClassNameForKey: dontSelectValue.query.redirectClassNameForKey, + keys: dontSelectValue.key }; if (this.restOptions.subqueryReadPreference) { diff --git a/src/RestWrite.js b/src/RestWrite.js index 424284d5ba..439c55bed0 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -24,7 +24,7 @@ import logger from './logger'; // 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) { +function RestWrite(config, auth, className, query, data, originalData, clientSDK, options) { if (auth.isReadOnly) { throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Cannot perform a write operation when using readOnlyMasterKey'); } @@ -34,7 +34,8 @@ function RestWrite(config, auth, className, query, data, originalData, clientSDK this.clientSDK = clientSDK; this.storage = {}; this.runOptions = {}; - if (!query && data.objectId) { + const allowObjectId = options && options.allowObjectId === true; + if (!query && data.objectId && !allowObjectId) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId is an invalid field name.'); } diff --git a/src/Routers/ExportRouter.js b/src/Routers/ExportRouter.js new file mode 100644 index 0000000000..386ce6fcc1 --- /dev/null +++ b/src/Routers/ExportRouter.js @@ -0,0 +1,212 @@ +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, name, jsonFileStream, where, skip, limit) { + + const databaseController = req.config.database; + + const options = { + skip, + limit + }; + + const findPromise = name.indexOf('_Join') === 0 ? + databaseController.adapter.find(name, relationSchema, where, options) + : rest.find(req.config, req.auth, name, where, options); + + return findPromise + .then((data) => { + if (Array.isArray(data)) { + data = { results : data }; + } + + 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 findPromise = data.name.indexOf('_Join') === 0 ? + databaseController.adapter.count(data.name, relationSchema, data.where) + : 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 47d1a0980c..e74b534c9d 100644 --- a/src/Routers/FeaturesRouter.js +++ b/src/Routers/FeaturesRouter.js @@ -41,7 +41,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..c1cdd68e02 --- /dev/null +++ b/src/Routers/ImportRouter.js @@ -0,0 +1,219 @@ +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 (!response.fields.hasOwnProperty(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/middlewares.js b/src/middlewares.js index 0606ab8f38..18bcaa11a3 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -246,7 +246,7 @@ function decodeBase64(str) { export function allowCrossDomain(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); - res.header('Access-Control-Allow-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'); + res.header('Access-Control-Allow-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, X-CSRF-Token'); // intercept OPTIONS method if ('OPTIONS' == req.method) { diff --git a/src/rest.js b/src/rest.js index b428f43cb8..cbfacbcca6 100644 --- a/src/rest.js +++ b/src/rest.js @@ -114,9 +114,9 @@ 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, auth, className, null, restObject, null, clientSDK); + var write = new RestWrite(config, auth, className, null, restObject, null, clientSDK, options); return write.execute(); } From a420fd70485080462432d5ea2c18dc799a44657f Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Wed, 22 Aug 2018 14:27:49 -0300 Subject: [PATCH 02/73] Add background true --- lib/Adapters/Storage/Mongo/MongoStorageAdapter.js | 4 ++-- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js index a3b25cfdc8..b93ae9facd 100644 --- a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -589,11 +589,11 @@ class MongoStorageAdapter { } createIndex(className, index) { - return this._adaptiveCollection(className).then(collection => collection._mongoCollection.createIndex(index)).catch(err => this.handleError(err)); + 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)).catch(err => this.handleError(err)); + return this._adaptiveCollection(className).then(collection => collection._mongoCollection.createIndexes(indexes, { background: true })).catch(err => this.handleError(err)); } createIndexesIfNeeded(className, fieldName, type) { diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 29614942a0..e1db8b93b2 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -641,13 +641,13 @@ 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)); } From 408d5539548497b55625df19424a160148f20744 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Mon, 3 Sep 2018 10:54:05 -0300 Subject: [PATCH 03/73] Merge from 2.8.4 to master --- .babelrc | 5 +- .github/ISSUE_TEMPLATE/---feature-request.md | 17 + .../ISSUE_TEMPLATE/---push-notifications.md | 7 + .github/ISSUE_TEMPLATE/---report-an-issue.md | 53 + .github/ISSUE_TEMPLATE/Bug_report.md | 51 + .gitignore | 3 + .nvmrc | 1 + .nycrc | 2 +- .travis.yml | 26 +- CHANGELOG.md | 114 +- CONTRIBUTING.md | 51 +- Dockerfile | 2 +- README.md | 17 +- lib/AccountLockout.js | 3 +- lib/Adapters/AdapterLoader.js | 3 +- lib/Adapters/Analytics/AnalyticsAdapter.js | 3 +- lib/Adapters/Auth/AuthAdapter.js | 3 +- lib/Adapters/Auth/OAuth1Client.js | 3 +- lib/Adapters/Auth/facebook.js | 5 +- lib/Adapters/Auth/facebookaccountkit.js | 3 +- lib/Adapters/Auth/github.js | 3 +- lib/Adapters/Auth/google.js | 3 +- lib/Adapters/Auth/index.js | 3 +- lib/Adapters/Auth/instagram.js | 3 +- lib/Adapters/Auth/janraincapture.js | 3 +- lib/Adapters/Auth/janrainengage.js | 3 +- lib/Adapters/Auth/linkedin.js | 3 +- lib/Adapters/Auth/meetup.js | 3 +- lib/Adapters/Auth/qq.js | 3 +- lib/Adapters/Auth/spotify.js | 3 +- lib/Adapters/Auth/twitter.js | 3 +- lib/Adapters/Auth/vkontakte.js | 5 +- lib/Adapters/Auth/wechat.js | 3 +- lib/Adapters/Auth/weibo.js | 3 +- lib/Adapters/Cache/CacheAdapter.js | 3 +- lib/Adapters/Cache/InMemoryCache.js | 3 +- lib/Adapters/Cache/InMemoryCacheAdapter.js | 3 +- lib/Adapters/Cache/LRUCache.js | 3 +- lib/Adapters/Cache/NullCacheAdapter.js | 3 +- lib/Adapters/Cache/RedisCacheAdapter.js | 3 +- lib/Adapters/Email/MailAdapter.js | 3 +- lib/Adapters/Files/FilesAdapter.js | 3 +- lib/Adapters/Files/GridStoreAdapter.js | 3 +- lib/Adapters/Logger/LoggerAdapter.js | 3 +- lib/Adapters/Logger/WinstonLogger.js | 3 +- lib/Adapters/Logger/WinstonLoggerAdapter.js | 3 +- lib/Adapters/MessageQueue/EventEmitterMQ.js | 3 +- lib/Adapters/PubSub/EventEmitterPubSub.js | 3 +- lib/Adapters/PubSub/RedisPubSub.js | 3 +- lib/Adapters/Push/PushAdapter.js | 3 +- lib/Adapters/Storage/Mongo/MongoCollection.js | 3 +- .../Storage/Mongo/MongoSchemaCollection.js | 3 +- .../Storage/Mongo/MongoStorageAdapter.js | 157 +- lib/Adapters/Storage/Mongo/MongoTransform.js | 132 +- .../Storage/Postgres/PostgresClient.js | 3 +- .../Storage/Postgres/PostgresConfigParser.js | 3 +- .../Postgres/PostgresStorageAdapter.js | 166 +- .../Postgres/sql/array/contains-all-regex.sql | 14 + .../Postgres/sql/array/contains-all.sql | 5 +- lib/Adapters/Storage/Postgres/sql/index.js | 4 +- lib/Adapters/Storage/StorageAdapter.js | 3 +- lib/Auth.js | 15 +- lib/ClientSDK.js | 3 +- lib/Config.js | 3 +- lib/Controllers/AdaptableController.js | 3 +- lib/Controllers/AnalyticsController.js | 3 +- lib/Controllers/CacheController.js | 3 +- lib/Controllers/DatabaseController.js | 53 +- lib/Controllers/FilesController.js | 9 +- lib/Controllers/HooksController.js | 22 +- lib/Controllers/LiveQueryController.js | 3 +- lib/Controllers/LoggerController.js | 3 +- lib/Controllers/PushController.js | 7 +- lib/Controllers/SchemaCache.js | 3 +- lib/Controllers/SchemaController.js | 7 +- lib/Controllers/UserController.js | 3 +- lib/Controllers/index.js | 8 +- lib/Controllers/types.js | 3 +- lib/LiveQuery/Client.js | 3 +- lib/LiveQuery/Id.js | 3 +- lib/LiveQuery/ParseCloudCodePublisher.js | 3 +- lib/LiveQuery/ParseLiveQueryServer.js | 3 +- lib/LiveQuery/ParsePubSub.js | 3 +- lib/LiveQuery/ParseWebSocketServer.js | 3 +- lib/LiveQuery/QueryTools.js | 3 +- lib/LiveQuery/RequestSchema.js | 3 +- lib/LiveQuery/SessionTokenCache.js | 3 +- lib/LiveQuery/Subscription.js | 3 +- lib/LiveQuery/equalObjects.js | 3 +- lib/Options/Definitions.js | 15 +- lib/Options/index.js | 3 +- lib/Options/parsers.js | 3 +- lib/ParseMessageQueue.js | 3 +- lib/ParseServer.js | 3 +- lib/ParseServerRESTController.js | 3 +- lib/PromiseRouter.js | 3 +- lib/Push/PushQueue.js | 3 +- lib/Push/PushWorker.js | 11 +- lib/Push/utils.js | 14 +- lib/RestQuery.js | 78 +- lib/RestWrite.js | 22 +- lib/Routers/AggregateRouter.js | 54 +- lib/Routers/AnalyticsRouter.js | 3 +- lib/Routers/AudiencesRouter.js | 3 +- lib/Routers/ClassesRouter.js | 8 +- lib/Routers/CloudCodeRouter.js | 3 +- lib/Routers/ExportRouter.js | 3 +- lib/Routers/FeaturesRouter.js | 3 +- lib/Routers/FilesRouter.js | 3 +- lib/Routers/FunctionsRouter.js | 6 +- lib/Routers/GlobalConfigRouter.js | 3 +- lib/Routers/HooksRouter.js | 3 +- lib/Routers/IAPValidationRouter.js | 3 +- lib/Routers/ImportRouter.js | 3 +- lib/Routers/InstallationsRouter.js | 3 +- lib/Routers/LogsRouter.js | 3 +- lib/Routers/PublicAPIRouter.js | 3 +- lib/Routers/PurgeRouter.js | 14 +- lib/Routers/PushRouter.js | 3 +- lib/Routers/RolesRouter.js | 3 +- lib/Routers/SchemasRouter.js | 3 +- lib/Routers/SessionsRouter.js | 3 +- lib/Routers/UsersRouter.js | 194 +- lib/StatusHandler.js | 3 +- lib/TestUtils.js | 12 +- lib/batch.js | 3 +- lib/cache.js | 3 +- .../definitions/parse-live-query-server.js | 3 +- lib/cli/definitions/parse-server.js | 3 +- lib/cli/parse-live-query-server.js | 3 +- lib/cli/parse-server.js | 3 +- lib/cli/utils/commander.js | 3 +- lib/cli/utils/runner.js | 3 +- lib/cloud-code/HTTPResponse.js | 3 +- lib/cloud-code/Parse.Cloud.js | 3 +- lib/cloud-code/httpRequest.js | 3 +- lib/cryptoUtils.js | 3 +- lib/defaults.js | 3 +- lib/deprecated.js | 3 +- lib/index.js | 3 +- lib/logger.js | 3 +- lib/middlewares.js | 8 +- lib/password.js | 3 +- lib/requiredParameter.js | 3 +- lib/rest.js | 43 +- lib/triggers.js | 6 +- lib/vendor/mongodbUrl.js | 3 +- package-lock.json | 12280 ++++++++++++++++ package.json | 56 +- postinstall.js | 50 + resources/npm-git.sh | 39 - spec/.babelrc | 14 + spec/AccountLockoutPolicy.spec.js | 2 +- spec/AdaptableController.spec.js | 8 +- spec/AdapterLoader.spec.js | 6 +- spec/AudienceRouter.spec.js | 8 +- spec/Auth.spec.js | 2 +- spec/AuthenticationAdapters.spec.js | 10 +- spec/CLI.spec.js | 8 +- spec/CacheController.spec.js | 2 +- spec/Client.spec.js | 4 +- spec/ClientSDK.spec.js | 2 +- spec/CloudCode.spec.js | 4 +- spec/CloudCodeLogger.spec.js | 4 +- spec/DatabaseController.spec.js | 2 +- spec/EmailVerificationToken.spec.js | 2 +- spec/EnableExpressErrorHandler.spec.js | 66 + spec/EnableSingleSchemaCache.spec.js | 6 +- spec/EventEmitterPubSub.spec.js | 2 +- spec/FilesController.spec.js | 52 +- spec/GridStoreAdapter.js | 6 +- spec/HTTPRequest.spec.js | 74 +- spec/InMemoryCache.spec.js | 4 +- spec/InMemoryCacheAdapter.spec.js | 2 +- spec/InstallationsRouter.spec.js | 8 +- spec/JobSchedule.spec.js | 4 +- spec/Logger.spec.js | 2 +- spec/LoggerController.spec.js | 10 +- spec/LogsRouter.spec.js | 6 +- spec/Middlewares.spec.js | 16 +- spec/MongoSchemaCollectionAdapter.spec.js | 2 +- spec/MongoStorageAdapter.spec.js | 8 +- spec/MongoTransform.spec.js | 39 +- spec/NullCacheAdapter.spec.js | 2 +- spec/OAuth1.spec.js | 2 +- spec/ParseACL.spec.js | 6 +- spec/ParseAPI.spec.js | 30 +- spec/ParseCloudCodePublisher.spec.js | 8 +- spec/ParseFile.spec.js | 18 - spec/ParseGeoPoint.spec.js | 110 + spec/ParseGlobalConfig.spec.js | 2 +- spec/ParseHooks.spec.js | 24 +- spec/ParseInstallation.spec.js | 8 +- spec/ParseLiveQueryServer.spec.js | 117 +- spec/ParseObject.spec.js | 27 + spec/ParsePolygon.spec.js | 263 +- spec/ParsePubSub.spec.js | 34 +- spec/ParseQuery.Aggregate.spec.js | 306 +- spec/ParseQuery.FullTextSearch.spec.js | 8 +- spec/ParseQuery.spec.js | 867 +- spec/ParseRelation.spec.js | 33 + spec/ParseRole.spec.js | 6 +- spec/ParseServer.spec.js | 23 +- spec/ParseServerRESTController.spec.js | 4 +- spec/ParseUser.spec.js | 238 +- spec/ParseWebSocket.spec.js | 2 +- spec/ParseWebSocketServer.spec.js | 2 +- spec/PointerPermissions.spec.js | 2 +- spec/PostgresConfigParser.spec.js | 2 +- spec/PostgresInitOptions.spec.js | 16 +- spec/PostgresStorageAdapter.spec.js | 2 +- spec/PromiseRouter.spec.js | 2 +- spec/PushController.spec.js | 86 +- spec/PushQueue.spec.js | 4 +- spec/PushRouter.spec.js | 2 +- spec/PushWorker.spec.js | 14 +- spec/QueryTools.spec.js | 4 +- spec/ReadPreferenceOption.spec.js | 65 +- spec/RedisCacheAdapter.spec.js | 2 +- spec/RedisPubSub.spec.js | 2 +- spec/RestQuery.spec.js | 6 +- spec/RevocableSessionsUpgrade.spec.js | 2 +- spec/Schema.spec.js | 4 +- spec/SchemaCache.spec.js | 6 +- spec/SessionTokenCache.spec.js | 2 +- spec/Subscription.spec.js | 4 +- spec/TwitterAuth.spec.js | 2 +- spec/Uniqueness.spec.js | 2 +- spec/UserController.spec.js | 4 +- spec/UserPII.spec.js | 2 +- spec/ValidationAndPasswordsReset.spec.js | 2 +- spec/VerifyUserPassword.spec.js | 494 + spec/WinstonLoggerAdapter.spec.js | 2 +- spec/batch.spec.js | 2 +- spec/cryptoUtils.spec.js | 2 +- spec/helper.js | 46 +- spec/index.spec.js | 6 +- spec/parsers.spec.js | 4 +- spec/rest.spec.js | 8 +- spec/schemas.spec.js | 925 +- spec/support/jasmine.json | 1 - spec/testing-routes.js | 10 +- src/Adapters/Auth/facebook.js | 2 +- src/Adapters/Auth/vkontakte.js | 2 +- .../Storage/Mongo/MongoStorageAdapter.js | 157 +- src/Adapters/Storage/Mongo/MongoTransform.js | 150 +- .../Postgres/PostgresStorageAdapter.js | 202 +- .../Postgres/sql/array/contains-all-regex.sql | 14 + .../Postgres/sql/array/contains-all.sql | 5 +- src/Adapters/Storage/Postgres/sql/index.js | 1 + src/Adapters/Storage/StorageAdapter.js | 4 +- src/Auth.js | 12 +- src/Controllers/DatabaseController.js | 52 +- src/Controllers/FilesController.js | 8 +- src/Controllers/HooksController.js | 11 +- src/Controllers/PushController.js | 5 +- src/Controllers/SchemaController.js | 4 +- src/Controllers/index.js | 6 +- src/Options/Definitions.js | 12 + src/Options/index.js | 5 + src/Push/PushWorker.js | 14 +- src/Push/utils.js | 15 +- src/RestQuery.js | 77 +- src/RestWrite.js | 18 +- src/Routers/AggregateRouter.js | 102 +- src/Routers/ClassesRouter.js | 5 +- src/Routers/FunctionsRouter.js | 3 + src/Routers/PurgeRouter.js | 6 + src/Routers/UsersRouter.js | 224 +- src/TestUtils.js | 9 +- src/middlewares.js | 5 +- src/rest.js | 40 +- src/triggers.js | 3 + 273 files changed, 17936 insertions(+), 1684 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/---feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/---push-notifications.md create mode 100644 .github/ISSUE_TEMPLATE/---report-an-issue.md create mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md create mode 100644 .nvmrc create mode 100644 lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql create mode 100644 package-lock.json create mode 100644 postinstall.js delete mode 100755 resources/npm-git.sh create mode 100644 spec/.babelrc create mode 100644 spec/EnableExpressErrorHandler.spec.js create mode 100644 spec/VerifyUserPassword.spec.js create mode 100644 src/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql diff --git a/.babelrc b/.babelrc index 509c3decfe..c8c8069f1d 100644 --- a/.babelrc +++ b/.babelrc @@ -6,8 +6,9 @@ "presets": [ ["env", { "targets": { - "node": "6.11.4" + "node": "8" } }] - ] + ], + "sourceMaps": "inline" } diff --git a/.github/ISSUE_TEMPLATE/---feature-request.md b/.github/ISSUE_TEMPLATE/---feature-request.md new file mode 100644 index 0000000000..a19d228731 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---feature-request.md @@ -0,0 +1,17 @@ +--- +name: "\U0001F4A1 Feature request" +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/---push-notifications.md b/.github/ISSUE_TEMPLATE/---push-notifications.md new file mode 100644 index 0000000000..3466cb9c1d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---push-notifications.md @@ -0,0 +1,7 @@ +--- +name: "\U0001F4F2 Push Notifications" +about: Issues with setting up or delivering push notifications + +--- + + diff --git a/.github/ISSUE_TEMPLATE/---report-an-issue.md b/.github/ISSUE_TEMPLATE/---report-an-issue.md new file mode 100644 index 0000000000..b5bdc244a4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---report-an-issue.md @@ -0,0 +1,53 @@ +--- +name: "\U0001F41B Report an issue" +about: Report an issue on parse-server + +--- + + +### Issue Description + + + +### Steps to reproduce + + + +### Expected Results + + + +### Actual Outcome + + + +### 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 + + 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 8f1edaabbf..fa194e2576 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ node_modules # Folder created by FileSystemAdapter /files + +# Merge files +*.orig diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..22ec1e6494 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +8.10 diff --git a/.nycrc b/.nycrc index 60afab1c96..4233221321 100644 --- a/.nycrc +++ b/.nycrc @@ -5,7 +5,7 @@ ], "exclude": [ "**/spec/**", - "lib/" + "src/" ] } diff --git a/.travis.yml b/.travis.yml index 156719debc..3c6cb081ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,9 @@ services: - docker addons: postgresql: '9.5' - apt_packages: - - postgresql-9.5-postgis-2.3 + apt: + packages: + - postgresql-9.5-postgis-2.3 branches: only: - master @@ -25,44 +26,43 @@ stage: test env: global: - COVERAGE_OPTION='./node_modules/.bin/nyc' - - NODE_VERSION=6.11.4 + - NODE_VERSION=8.11.2 matrix: - MONGODB_VERSION=3.2.13 - MONGODB_VERSION=3.4.4 - PARSE_SERVER_TEST_DB=postgres - PARSE_SERVER_TEST_CACHE=redis - - NODE_VERSION=8.7 + - NODE_VERSION=stable +matrix: + allow_failures: + - env: NODE_VERSION=stable before_install: - nvm install $NODE_VERSION - nvm use $NODE_VERSION +- npm install -g greenkeeper-lockfile@1 before_script: - node -e 'require("./lib/index.js")' - psql -c 'create database parse_server_postgres_adapter_test_database;' -U postgres - psql -c 'CREATE EXTENSION postgis;' -U postgres -d parse_server_postgres_adapter_test_database - psql -c 'CREATE EXTENSION postgis_topology;' -U postgres -d parse_server_postgres_adapter_test_database - silent=1 mongodb-runner --start +- greenkeeper-lockfile-update script: - npm run coverage after_script: +- greenkeeper-lockfile-upload - bash <(curl -s https://codecov.io/bash) jobs: include: - # release on github latest branch + # release on npm on tags - stage: release - node_js: '6.11.4' + node_js: '8.10' env: before_script: skip after_script: skip script: skip deploy: - - provider: script - skip_cleanup: true - script: ./resources/npm-git.sh - on: - branch: - - master - - 3.x - provider: npm skip_cleanup: true email: diff --git a/CHANGELOG.md b/CHANGELOG.md index dedd655d06..f311531762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,117 @@ ## Parse Server Changelog ### master -[Full Changelog](https://github.com/parse-community/parse-server/compare/2.7.4...master) +[Full Changelog](https://github.com/parse-community/parse-server/compare/2.8.4...master) + +### 2.8.4 +[Full Changelog](https://github.com/parse-community/parse-server/compare/2.8.3...2.8.4) + +#### Improvements +* Adds ability to forward errors to express handler (#4697) +* Adds ability to increment the push badge with an arbitrary value (#4889) +* Adds ability to preserve the file names when uploading (#4915) +* `_User` now follow regular ACL policy. Letting administrator lock user out. (#4860) and (#4898) +* Ensure dates are properly handled in aggregates (#4743) +* Aggregates: Improved support for stages sharing the same name +* Add includeAll option +* Added verify password to users router and tests. (#4747) +* Ensure read preference is never overriden, so DB config prevails (#4833) +* add support for geoWithin.centerSphere queries via withJSON (#4825) +* Allow sorting an object field (#4806) +* Postgres: Don't merge JSON fields after save() to keep same behaviour as MongoDB (#4808) (#4815) + +#### Dependency updates +* [commander@2.16.0](https://www.npmjs.com/package/commander) +* [mongodb@3.1.1](https://www.npmjs.com/package/mongodb) +* [pg-promise@8.4.5](https://www.npmjs.com/package/pg-promise) +* [ws@6.0.0](https://www.npmjs.com/package/ws) +* [bcrypt@3.0.0](https://www.npmjs.com/package/bcrypt) +* [uws@10.148.1](https://www.npmjs.com/package/uws) + +##### Devevelopment Dependencies Updates: +* [cross-env@5.2.0](https://www.npmjs.com/package/cross-env) +* [eslint@5.0.0](https://www.npmjs.com/package/eslint) +* [flow-bin@0.76.0](https://www.npmjs.com/package/flow-bin) +* [mongodb-runner@4.0.0](https://www.npmjs.com/package/mongodb-runner) +* [nodemon@1.18.1](https://www.npmjs.com/package/nodemon) +* [nyc@12.0.2](https://www.npmjs.com/package/nyc) +* [request-promise@4.2.2](https://www.npmjs.com/package/request-promise) +* [supports-color@5.4.0](https://www.npmjs.com/package/supports-color) + +### 2.8.3 +[Full Changelog](https://github.com/parse-community/parse-server/compare/2.8.2...2.8.3) + +* Adds support for JS SDK 2.0 job status header + +### 2.8.2 +[Full Changelog](https://github.com/parse-community/parse-server/compare/2.8.1...2.8.2) + +##### Bug Fixes: +* Ensure legacy users without ACL's are not locked out, thanks to [Florent Vilmart](https://github.com/flovilmart) + +#### Improvements: +* Use common HTTP agent to increase webhooks performance, thanks to [Tyler Brock](https://github.com/TylerBrock) +* Adds withinPolygon support for Polygon objects, thanks to [Mads Bjerre](https://github.com/madsb) + +#### Dependency Updates: +* [ws@5.2.0](https://www.npmjs.com/package/ws) +* [commander@2.15.1](https://www.npmjs.com/package/commander) +* [nodemon@1.17.5](https://www.npmjs.com/package/nodemon) + +##### Devevelopment Dependencies Updates: +* [flow-bin@0.73.0](https://www.npmjs.com/package/flow-bin) +* [cross-env@5.1.6](https://www.npmjs.com/package/cross-env) +* [gaze@1.1.3](https://www.npmjs.com/package/gaze) +* [deepcopy@1.0.0](https://www.npmjs.com/package/deepcopy) +* [deep-diff@1.0.1](https://www.npmjs.com/package/deep-diff) + + +### 2.8.1 +[Full Changelog](https://github.com/parse-community/parse-server/compare/2.8.1...2.8.0) + +Ensure all the files are properly exported to the final package. + +### 2.8.0 +[Full Changelog](https://github.com/parse-community/parse-server/compare/2.8.0...2.7.4) + +#### New Features +* Adding Mongodb element to add `arrayMatches` the #4762 (#4766), thanks to [Jérémy Piednoel](https://github.com/jeremypiednoel) +* Adds ability to Lockout users (#4749), thanks to [Florent Vilmart](https://github.com/flovilmart) + +#### Bug fixes: +* Fixes issue when using afterFind with relations (#4752), thanks to [Florent Vilmart](https://github.com/flovilmart) +* New query condition support to match all strings that starts with some other given strings (#3864), thanks to [Eduard Bosch Bertran](https://github.com/eduardbosch) +* Allow creation of indices on default fields (#4738), thanks to [Claire Neveu](https://github.com/ClaireNeveu) +* Purging empty class (#4676), thanks to [Diamond Lewis](https://github.com/dplewis) +* Postgres: Fixes issues comparing to zero or false (#4667), thanks to [Diamond Lewis](https://github.com/dplewis) +* Fix Aggregate Match Pointer (#4643), thanks to [Diamond Lewis](https://github.com/dplewis) + +#### Improvements: +* Allow Parse.Error when returning from Cloud Code (#4695), thanks to [Saulo Tauil](https://github.com/saulogt) +* Fix typo: "requrest" -> "request" (#4761), thanks to [Joseph Frazier](https://github.com/josephfrazier) +* Send version for Vkontakte API (#4725), thanks to [oleg](https://github.com/alekoleg) +* Ensure we respond with invalid password even if email is unverified (#4708), thanks to [dblythy](https://github.com/dblythy) +* Add _password_history to default sensitive data (#4699), thanks to [Jong Eun Lee](https://github.com/yomybaby) +* Check for node version in postinstall script (#4657), thanks to [Diamond Lewis](https://github.com/dplewis) +* Remove FB Graph API version from URL to use the oldest non deprecated version, thanks to [SebC](https://github.com/SebC99) + +#### Dependency Updates: +* [@parse/push-adapter@2.0.3](https://www.npmjs.com/package/@parse/push-adapter) +* [@parse/simple-mailgun-adapter@1.0.2](https://www.npmjs.com/package/@parse/simple-mailgun-adapter) +* [uws@10.148.0](https://www.npmjs.com/package/uws) +* [body-parser@1.18.3](https://www.npmjs.com/package/body-parser) +* [mime@2.3.1](https://www.npmjs.com/package/mime) +* [request@2.85.0](https://www.npmjs.com/package/request) +* [mongodb@3.0.7](https://www.npmjs.com/package/mongodb) +* [bcrypt@2.0.1](https://www.npmjs.com/package/bcrypt) +* [ws@5.1.1](https://www.npmjs.com/package/ws) + +##### Devevelopment Dependencies Updates: +* [cross-env@5.1.5](https://www.npmjs.com/package/cross-env) +* [flow-bin@0.71.0](https://www.npmjs.com/package/flow-bin) +* [deep-diff@1.0.0](https://www.npmjs.com/package/deep-diff) +* [nodemon@1.17.3](https://www.npmjs.com/package/nodemon) + ### 2.7.4 [Full Changelog](https://github.com/parse-community/parse-server/compare/2.7.4...2.7.3) @@ -1079,7 +1189,7 @@ Other fixes by [Mathias Rangel Wulff](https://github.com/mathiasrw) * Fix: Improve compatability of cloud code beforeSave hook for newly created object * Fix: ACL creation for master key only objects * Fix: Allow uploading files without Content-Type -* Fix: Add features to http requrest to match Parse.com +* Fix: Add features to http request to match Parse.com * Fix: Bugs in development script when running from locations other than project root * Fix: Can pass query constraints in URL * Fix: Objects with legacy "_tombstone" key now don't cause issues. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f6a907f832..6f822ae0ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,49 @@ -### Contributing to Parse Server +# Contributing to Parse Server -#### Pull Requests Welcome! +We really want Parse to be yours, to see it grow and thrive in the open source community. -We really want Parse to be yours, to see it grow and thrive in the open source community. +If you are not familiar with Pull Requests and want to know more about them, you can visit the [Creating a pull request](https://help.github.com/articles/creating-a-pull-request/) article. It contains detailed informations about the process. -##### Please Do's +## Setting up the project for debugging and contributing: + +### Recommended setup: + +* [vscode](https://code.visualstudio.com), the popular IDE. +* [Jasmine Test Explorer](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-test-explorer), a very practical test exploration plugin which let you run, debug and see the test results inline. + +### Setting up you local machine: + +* [Fork](https://github.com/parse-community/parse-server) this project and clone the fork on your local machine: + +```sh +$ git clone https://github.com/parse-community/parse-server +$ cd parse-server # go into the clone directory +$ npm install # install all the node dependencies +$ code . # launch vscode +$ npm run watch # run babel watching for local file changes +``` + +Once you have babel running in watch mode, you can start making changes to parse-server. + +### Good to know: + +* The lib/ folder is not commited, so never make changes in there. +* Always make changes to files in the `src/` folder. +* All the tests should point to sources in the `lib/` folder. + +### Troubleshooting: + +*Question*: I modify the code in the src folder but it doesn't seem to have any effect.
+*Answer*: Check that `npm run watch` is running + +*Question*: How do I use breakpoints and debug step by step?
+*Answer*: The easiest way is to install [Jasmine Test Explorer](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-test-explorer), it will let you run selectively tests and debug them. + +*Question*: How do I deploy my forked version on my servers?
+*Answer*: In your `package.json`, update the `parse-server` dependency to `https://github.com/MY_USERNAME/parse-server#MY_FEATURE`. Run `npm install`, commit the changes and deploy to your servers. + + +### Please Do's * Begin by reading the [Development Guide](http://docs.parseplatform.org/parse-server/guide/#development-guide) to learn how to get started running the parse-server. * Take testing seriously! Aim to increase the test coverage with every pull request. To obtain the test coverage of the project, run: @@ -17,7 +56,7 @@ We really want Parse to be yours, to see it grow and thrive in the open source c * Lint your code by running `npm run lint` to make sure the code is not going to be rejected by the CI. * **Do not** publish the *lib* folder. -##### Run your tests against Postgres (optional) +### Run your tests against Postgres (optional) If your pull request introduces a change that may affect the storage or retrieval of objects, you may want to make sure it plays nice with Postgres. @@ -28,6 +67,6 @@ If your pull request introduces a change that may affect the storage or retrieva - `it_only_db('mongo')` // will make a test that only runs on mongo - `it_exclude_dbs(['postgres'])` // will make a test that runs against all DB's but postgres -##### Code of Conduct +### Code of Conduct This project adheres to the [Contributor Covenant Code of Conduct](https://github.com/parse-community/parse-server/blob/master/CODE_OF_CONDUCT.md). By participating, you are expected to honor this code. diff --git a/Dockerfile b/Dockerfile index bf30a303d1..b4ac513b58 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:boron +FROM node:carbon RUN mkdir -p /parse-server COPY ./ /parse-server/ diff --git a/README.md b/README.md index 0b6a2ea132..3c5a81bea3 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,7 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo #### Advanced options * `fileKey` - For migrated apps, this is necessary to provide access to files already hosted on Parse. +* `preserveFileName` - Set to true to remove the unique hash added to the file names. Defaults to false. * `allowClientClassCreation` - Set to false to disable client class creation. Defaults to true. * `enableAnonymousUsers` - Set to false to disable anonymous users. Defaults to true. * `auth` - Used to configure support for [3rd party authentication](http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication). @@ -393,16 +394,24 @@ If you believe you've found an issue with Parse Server, make sure these boxes ar # Want to ride the bleeding edge? -The `latest` branch in this repository is automatically maintained to be the last -commit to `master` to pass all tests, in the same form found on npm. It is -recommend to use builds deployed npm for many reasons, but if you want to use +It is recommend to use builds deployed npm for many reasons, but if you want to use the latest not-yet-released version of parse-server, you can do so by depending directly on this branch: ``` -npm install parseplatform/parse-server.git#latest +npm install parse-community/parse-server.git#master ``` +## Experimenting + +You can also use your own forks, and work in progress branches by specifying them: + +``` +npm install github:myUsername/parse-server#my-awesome-feature +``` + +And don't forget, if you plan to deploy it remotely, you should run `npm install` with the `--save` option. + # Contributing We really want Parse to be yours, to see it grow and thrive in the open source community. Please see the [Contributing to Parse Server guide](CONTRIBUTING.md). diff --git a/lib/AccountLockout.js b/lib/AccountLockout.js index dd1522e9c7..3c16140231 100644 --- a/lib/AccountLockout.js +++ b/lib/AccountLockout.js @@ -156,4 +156,5 @@ class AccountLockout { exports.AccountLockout = AccountLockout; // This class handles the Account Lockout Policy settings. -exports.default = AccountLockout; \ No newline at end of file +exports.default = AccountLockout; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9BY2NvdW50TG9ja291dC5qcyJdLCJuYW1lcyI6WyJBY2NvdW50TG9ja291dCIsImNvbnN0cnVjdG9yIiwidXNlciIsImNvbmZpZyIsIl91c2VyIiwiX2NvbmZpZyIsIl9zZXRGYWlsZWRMb2dpbkNvdW50IiwidmFsdWUiLCJxdWVyeSIsInVzZXJuYW1lIiwidXBkYXRlRmllbGRzIiwiX2ZhaWxlZF9sb2dpbl9jb3VudCIsImRhdGFiYXNlIiwidXBkYXRlIiwiX2lzRmFpbGVkTG9naW5Db3VudFNldCIsIiRleGlzdHMiLCJmaW5kIiwidGhlbiIsInVzZXJzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiX2luaXRGYWlsZWRMb2dpbkNvdW50IiwiZmFpbGVkTG9naW5Db3VudElzU2V0IiwiX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQiLCJfX29wIiwiYW1vdW50IiwiX3NldExvY2tvdXRFeHBpcmF0aW9uIiwiJGd0ZSIsImFjY291bnRMb2Nrb3V0IiwidGhyZXNob2xkIiwibm93IiwiRGF0ZSIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIlBhcnNlIiwiX2VuY29kZSIsImdldFRpbWUiLCJkdXJhdGlvbiIsImNhdGNoIiwiZXJyIiwiY29kZSIsIm1lc3NhZ2UiLCJfbm90TG9ja2VkIiwiJGd0IiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiX2hhbmRsZUZhaWxlZExvZ2luQXR0ZW1wdCIsImhhbmRsZUxvZ2luQXR0ZW1wdCIsImxvZ2luU3VjY2Vzc2Z1bCIsIlByb21pc2UiLCJyZXNvbHZlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7Ozs7OztBQUVPLE1BQU1BLGNBQU4sQ0FBcUI7QUFDMUJDLGNBQVlDLElBQVosRUFBa0JDLE1BQWxCLEVBQTBCO0FBQ3hCLFNBQUtDLEtBQUwsR0FBYUYsSUFBYjtBQUNBLFNBQUtHLE9BQUwsR0FBZUYsTUFBZjtBQUNEOztBQUVEOzs7QUFHQUcsdUJBQXFCQyxLQUFyQixFQUE0QjtB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IHRoZSBBY2NvdW50IExvY2tvdXQgUG9saWN5IHNldHRpbmdzLlxuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuXG5leHBvcnQgY2xhc3MgQWNjb3VudExvY2tvdXQge1xuICBjb25zdHJ1Y3Rvcih1c2VyLCBjb25maWcpIHtcbiAgICB0aGlzLl91c2VyID0gdXNlcjtcbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gIH1cblxuICAvKipcbiAgICogc2V0IF9mYWlsZWRfbG9naW5fY291bnQgdG8gdmFsdWVcbiAgICovXG4gIF9zZXRGYWlsZWRMb2dpbkNvdW50KHZhbHVlKSB7XG4gICAgY29uc3QgcXVlcnkgPSB7XG4gICAgICB1c2VybmFtZTogdGhpcy5fdXNlci51c2VybmFtZVxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVGaWVsZHMgPSB7XG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB2YWx1ZVxuICAgIH07XG5cbiAgICByZXR1cm4gdGhpcy5fY29uZmlnLmRhdGFiYXNlLnVwZGF0ZSgnX1VzZXInLCBxdWVyeSwgdXBkYXRlRmllbGRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjaGVjayBpZiB0aGUgX2ZhaWxlZF9sb2dpbl9jb3VudCBmaWVsZCBoYXMgYmVlbiBzZXRcbiAgICovXG4gIF9pc0ZhaWxlZExvZ2luQ291bnRTZXQoKSB7XG4gICAgY29uc3QgcXVlcnkgPSB7XG4gICAgICB1c2VybmFtZTogdGhpcy5fdXNlci51c2VybmFtZSxcbiAgICAgIF9mYWlsZWRfbG9naW5fY291bnQ6IHsgJGV4aXN0czogdHJ1ZSB9XG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCBxdWVyeSlcbiAgICAgIC50aGVuKHVzZXJzID0+IHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodXNlcnMpICYmIHVzZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIF9mYWlsZWRfbG9naW5fY291bnQgaXMgTk9UIHNldCB0aGVuIHNldCBpdCB0byAwXG4gICAqIGVsc2UgZG8gbm90aGluZ1xuICAgKi9cbiAgX2luaXRGYWlsZWRMb2dpbkNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9pc0ZhaWxlZExvZ2luQ291bnRTZXQoKVxuICAgICAgLnRoZW4oZmFpbGVkTG9naW5Db3VudElzU2V0ID0+IHtcbiAgICAgICAgaWYgKCFmYWlsZWRMb2dpbkNvdW50SXNTZXQpIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5fc2V0RmFpbGVkTG9naW5Db3VudCgwKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogaW5jcmVtZW50IF9mYWlsZWRfbG9naW5fY291bnQgYnkgMVxuICAgKi9cbiAgX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQoKSB7XG4gICAgY29uc3QgcXVlcnkgPSB7XG4gICAgICB1c2VybmFtZTogdGhpcy5fdXNlci51c2VybmFtZVxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVGaWVsZHMgPSB7X2ZhaWxlZF9sb2dpbl9jb3VudDoge19fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IDF9fTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UudXBkYXRlKCdfVXNlcicsIHF1ZXJ5LCB1cGRhdGVGaWVsZHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIHRoZSBmYWlsZWQgbG9naW4gY291bnQgaXMgZ3JlYXRlciB0aGFuIHRoZSB0aHJlc2hvbGRcbiAgICogdGhlbiBzZXRzIGxvY2tvdXQgZXhwaXJhdGlvbiB0byAnY3VycmVudHRpbWUgKyBhY2NvdW50UG9saWN5LmR1cmF0aW9uJywgaS5lLiwgYWNjb3VudCBpcyBsb2NrZWQgb3V0IGZvciB0aGUgbmV4dCAnYWNjb3VudFBvbGljeS5kdXJhdGlvbicgbWludXRlc1xuICAgKiBlbHNlIGRvIG5vdGhpbmdcbiAgICovXG4gIF9zZXRMb2Nrb3V0RXhwaXJhdGlvbigpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogeyAkZ3RlOiB0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQudGhyZXNob2xkIH1cbiAgICB9O1xuXG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcblxuICAgIGNvbnN0IHVwZGF0ZUZpZWxkcyA9IHtcbiAgICAgIF9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdDogUGFyc2UuX2VuY29kZShuZXcgRGF0ZShub3cuZ2V0VGltZSgpICsgdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0LmR1cmF0aW9uICogNjAgKiAxMDAwKSlcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywgcXVlcnksIHVwZGF0ZUZpZWxkcylcbiAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICBpZiAoZXJyICYmIGVyci5jb2RlICYmIGVyci5tZXNzYWdlICYmIGVyci5jb2RlID09PSAxMDEgJiYgZXJyLm1lc3NhZ2UgPT09ICdPYmplY3Qgbm90IGZvdW5kLicpIHtcbiAgICAgICAgICByZXR1cm47IC8vIG5vdGhpbmcgdG8gdXBkYXRlIHNvIHdlIGFyZSBnb29kXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyOyAvLyB1bmtub3duIGVycm9yXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIF9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCA+IGN1cnJlbnRfdGltZSBhbmQgX2ZhaWxlZF9sb2dpbl9jb3VudCA+IHRocmVzaG9sZFxuICAgKiAgIHJlamVjdCB3aXRoIGFjY291bnQgbG9ja2VkIGVycm9yXG4gICAqIGVsc2VcbiAgICogICByZXNvbHZlXG4gICAqL1xuICBfbm90TG9ja2VkKCkge1xuICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgdXNlcm5hbWU6IHRoaXMuX3VzZXIudXNlcm5hbWUsXG4gICAgICBfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQ6IHsgJGd0OiBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKCkpIH0sXG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7JGd0ZTogdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0LnRocmVzaG9sZH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS5maW5kKCdfVXNlcicsIHF1ZXJ5KVxuICAgICAgLnRoZW4odXNlcnMgPT4ge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh1c2VycykgJiYgdXNlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnWW91ciBhY2NvdW50IGlzIGxvY2tlZCBkdWUgdG8gbXVsdGlwbGUgZmFpbGVkIGxvZ2luIGF0dGVtcHRzLiBQbGVhc2UgdHJ5IGFnYWluIGFmdGVyICcgKyB0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQuZHVyYXRpb24gKyAnIG1pbnV0ZShzKScpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzZXQgYW5kL29yIGluY3JlbWVudCBfZmFpbGVkX2xvZ2luX2NvdW50XG4gICAqIGlmIF9mYWlsZWRfbG9naW5fY291bnQgPiB0aHJlc2hvbGRcbiAgICogICBzZXQgdGhlIF9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCB0byBjdXJyZW50X3RpbWUgKyBhY2NvdW50UG9saWN5LmR1cmF0aW9uXG4gICAqIGVsc2VcbiAgICogICBkbyBub3RoaW5nXG4gICAqL1xuICBfaGFuZGxlRmFpbGVkTG9naW5BdHRlbXB0KCkge1xuICAgIHJldHVybiB0aGlzLl9pbml0RmFpbGVkTG9naW5Db3VudCgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pbmNyZW1lbnRGYWlsZWRMb2dpbkNvdW50KCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2V0TG9ja291dEV4cGlyYXRpb24oKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGhhbmRsZSBsb2dpbiBhdHRlbXB0IGlmIHRoZSBBY2NvdW50IExvY2tvdXQgUG9saWN5IGlzIGVuYWJsZWRcbiAgICovXG4gIGhhbmRsZUxvZ2luQXR0ZW1wdChsb2dpblN1Y2Nlc3NmdWwpIHtcbiAgICBpZiAoIXRoaXMuX2NvbmZpZy5hY2NvdW50TG9ja291dCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fbm90TG9ja2VkKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGxvZ2luU3VjY2Vzc2Z1bCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLl9zZXRGYWlsZWRMb2dpbkNvdW50KDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVGYWlsZWRMb2dpbkF0dGVtcHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBBY2NvdW50TG9ja291dDtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/AdapterLoader.js b/lib/Adapters/AdapterLoader.js index ffdf98fd95..9dd1852e55 100644 --- a/lib/Adapters/AdapterLoader.js +++ b/lib/Adapters/AdapterLoader.js @@ -41,4 +41,5 @@ function loadAdapter(adapter, defaultAdapter, options) { return adapter; } -exports.default = loadAdapter; \ No newline at end of file +exports.default = loadAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9BZGFwdGVycy9BZGFwdGVyTG9hZGVyLmpzIl0sIm5hbWVzIjpbImxvYWRBZGFwdGVyIiwiYWRhcHRlciIsImRlZmF1bHRBZGFwdGVyIiwib3B0aW9ucyIsInVuZGVmaW5lZCIsImUiLCJuYW1lIiwiQWRhcHRlciIsInJlcXVpcmUiLCJkZWZhdWx0IiwibW9kdWxlIiwiY2xhc3MiXSwibWFwcGluZ3MiOiI7Ozs7O1FBQWdCQSxXLEdBQUFBLFc7QUFBVCxTQUFTQSxXQUFULENBQXFCQyxPQUFyQixFQUE4QkMsY0FBOUIsRUFBOENDLE9BQTlDLEVBQXVEO0FBQzVELE1BQUksQ0FBQ0YsT0FBTCxFQUFjO0FBQ1osUUFBSSxDQUFDQyxjQUFMLEVBQXFCO0FBQ25CLGFBQU9DLE9BQVA7QUFDRDtBQUNEO0FBQ0EsV0FBT0gsWUFBWUUsY0FBWixFQUE0QkUsU0FBNUIsRUFBdUNELE9BQXZDLENBQVA7QUFDRCxHQU5ELE1BTU8sSUFBSSxPQUFPRixPQUFQLEtBQW1CLFVBQXZCLEVBQW1DO0FBQ3hDLFFBQUk7QUFDRixhQUFPQSxRQUFRRSxPQUFSLENBQVA7QUFDRCxLQUZELENBRUUsT0FBTUUsQ0FBTixFQUFTO0FBQ1QsVUFBSUEsRUFBRUMsSUFBRixLQUFXLFdBQWYsRUFBNEI7QUFDMUIsWUFBSUMsVUFBVU4sT0FBZDtBQUNBLGVBQU8sSUFBSU0sT0FBSixDQUFZSixPQUFaLENBQVA7QUFDRCxPQUhELE1BR087QUFDTCxjQUFNRSxDQUFOO0FBQ0Q7QUFDRjtBQUNGLEdBWE0sTUFXQSxJQUFJLE9BQU9KLE9BQVAsS0FBbUIsUUFBdkIsRUFBaUM7QUFDdEM7QUFDQUEsY0FBVU8sUUFBUVAsT0FBUixDQUFWO0FBQ0E7QUFDQSxRQUFJQSxRQUFRUSxPQUFaLEVBQXFCO0FBQ25CUixnQkFBVUEsUUFBUVEsT0FBbEI7QUFDRDtBQUNELFdBQU9ULFlBQVlDLE9BQVosRUFBcUJHLFNBQXJCLEVBQWdDRCxPQUFoQyxDQUFQO0FBQ0QsR0FSTSxNQVFBLElBQUlGLFFBQVFTLE1BQVosRUFBb0I7QUFDekIsV0FBT1YsWUFBWUMsUUFBUVMsTUFBcEIsRUFBNEJOLFNBQTVCLEVBQXVDSCxRQUFRRSxPQUEvQyxDQUFQO0FBQ0QsR0FGTSxNQUVBLElBQUlGLFFBQVFVLEtBQVosRUFBbUI7QUFDeEIsV0FBT1gsWUFBWUMsUUFBUVUsS0FBcEIsRUFBMkJQLFNBQTNCLEVBQXNDSCxRQUFRRSxPQUE5QyxDQUFQO0FBQ0QsR0FGTSxNQUVBLElBQUlGLFFBQVFBLE9BQVosRUFBcUI7QUFDMUIsV0FBT0QsWUFBWUMsUUFBUUEsT0FBcEIsRUFBNkJHLFNBQTdCLEVBQXdDSCxRQUFRRSxPQUFoRCxDQUFQO0FBQ0Q7QUFDRDtBQUNBLFNBQU9GLE9BQVA7QUFDRDs7a0JBRWNELFciLCJmaWxlIjoiQWRhcHRlckxvYWRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiBsb2FkQWRhcHRlcihhZGFwdGVyLCBkZWZhdWx0QWRhcHRlciwgb3B0aW9ucykge1xuICBpZiAoIWFkYXB0ZXIpIHtcbiAgICBpZiAoIWRlZmF1bHRBZGFwdGVyKSB7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9XG4gICAgLy8gTG9hZCBmcm9tIHRoZSBkZWZhdWx0IGFkYXB0ZXIgd2hlbiBubyBhZGFwdGVyIGlzIHNldFxuICAgIHJldHVybiBsb2FkQWRhcHRlcihkZWZhdWx0QWRhcHRlciwgdW5kZWZpbmVkLCBvcHRpb25zKTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgYWRhcHRlciA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhZGFwdGVyKG9wdGlvbnMpO1xuICAgIH0gY2F0Y2goZSkge1xuICAgICAgaWYgKGUubmFtZSA9PT0gJ1R5cGVFcnJvcicpIHtcbiAgICAgICAgdmFyIEFkYXB0ZXIgPSBhZGFwdGVyO1xuICAgICAgICByZXR1cm4gbmV3IEFkYXB0ZXIob3B0aW9ucyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlb2YgYWRhcHRlciA9PT0gXCJzdHJpbmdcIikge1xuICAgIC8qIGVzbGludC1kaXNhYmxlICovXG4gICAgYWRhcHRlciA9IHJlcXVpcmUoYWRhcHRlcik7XG4gICAgLy8gSWYgaXQncyBkZWZpbmUgYXMgYSBtb2R1bGUsIGdldCB0aGUgZGVmYXVsdFxuICAgIGlmIChhZGFwdGVyLmRlZmF1bHQpIHtcbiAgICAgIGFkYXB0ZXIgPSBhZGFwdGVyLmRlZmF1bHQ7XG4gICAgfVxuICAgIHJldHVybiBsb2FkQWRhcHRlcihhZGFwdGVyLCB1bmRlZmluZWQsIG9wdGlvbnMpO1xuICB9IGVsc2UgaWYgKGFkYXB0ZXIubW9kdWxlKSB7XG4gICAgcmV0dXJuIGxvYWRBZGFwdGVyKGFkYXB0ZXIubW9kdWxlLCB1bmRlZmluZWQsIGFkYXB0ZXIub3B0aW9ucyk7XG4gIH0gZWxzZSBpZiAoYWRhcHRlci5jbGFzcykge1xuICAgIHJldHVybiBsb2FkQWRhcHRlcihhZGFwdGVyLmNsYXNzLCB1bmRlZmluZWQsIGFkYXB0ZXIub3B0aW9ucyk7XG4gIH0gZWxzZSBpZiAoYWRhcHRlci5hZGFwdGVyKSB7XG4gICAgcmV0dXJuIGxvYWRBZGFwdGVyKGFkYXB0ZXIuYWRhcHRlciwgdW5kZWZpbmVkLCBhZGFwdGVyLm9wdGlvbnMpO1xuICB9XG4gIC8vIHJldHVybiB0aGUgYWRhcHRlciBhcyBwcm92aWRlZFxuICByZXR1cm4gYWRhcHRlcjtcbn1cblxuZXhwb3J0IGRlZmF1bHQgbG9hZEFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Analytics/AnalyticsAdapter.js b/lib/Adapters/Analytics/AnalyticsAdapter.js index d4af892ac0..ba26cf0606 100644 --- a/lib/Adapters/Analytics/AnalyticsAdapter.js +++ b/lib/Adapters/Analytics/AnalyticsAdapter.js @@ -25,4 +25,5 @@ class AnalyticsAdapter { } exports.AnalyticsAdapter = AnalyticsAdapter; -exports.default = AnalyticsAdapter; \ No newline at end of file +exports.default = AnalyticsAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BbmFseXRpY3MvQW5hbHl0aWNzQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJBbmFseXRpY3NBZGFwdGVyIiwiYXBwT3BlbmVkIiwicGFyYW1ldGVycyIsInJlcSIsIlByb21pc2UiLCJyZXNvbHZlIiwidHJhY2tFdmVudCIsImV2ZW50TmFtZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNPLE1BQU1BLGdCQUFOLENBQXVCOztBQUU1Qjs7OztBQUlBQyxZQUFVQyxVQUFWLEVBQXNCQyxHQUF0QixFQUEyQjtBQUN6QixXQUFPQyxRQUFRQyxPQUFSLENBQWdCLEVBQWhCLENBQVA7QUFDRDs7QUFFRDs7Ozs7QUFLQUMsYUFBV0MsU0FBWCxFQUFzQkwsVUFBdEIsRUFBa0NDLEdBQWxDLEVBQXVDO0FBQ3JDLFdBQU9DLFFBQVFDLE9BQVIsQ0FBZ0IsRUFBaEIsQ0FBUDtBQUNEO0FBakIyQjs7UUFBakJMLGdCLEdBQUFBLGdCO2tCQW9CRUEsZ0IiLCJmaWxlIjoiQW5hbHl0aWNzQWRhcHRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qZXNsaW50IG5vLXVudXNlZC12YXJzOiBcIm9mZlwiKi9cbmV4cG9ydCBjbGFzcyBBbmFseXRpY3NBZGFwdGVyIHtcblxuICAvKlxuICBAcGFyYW0gcGFyYW1ldGVyczogdGhlIGFuYWx5dGljcyByZXF1ZXN0IGJvZHksIGFuYWx5dGljcyBpbmZvIHdpbGwgYmUgaW4gdGhlIGRpbWVuc2lvbnMgcHJvcGVydHlcbiAgQHBhcmFtIHJlcTogdGhlIG9yaWdpbmFsIGh0dHAgcmVxdWVzdFxuICAgKi9cbiAgYXBwT3BlbmVkKHBhcmFtZXRlcnMsIHJlcSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICB9XG5cbiAgLypcbiAgQHBhcmFtIGV2ZW50TmFtZTogdGhlIG5hbWUgb2YgdGhlIGN1c3RvbSBldmVudE5hbWVcbiAgQHBhcmFtIHBhcmFtZXRlcnM6IHRoZSBhbmFseXRpY3MgcmVxdWVzdCBib2R5LCBhbmFseXRpY3MgaW5mbyB3aWxsIGJlIGluIHRoZSBkaW1lbnNpb25zIHByb3BlcnR5XG4gIEBwYXJhbSByZXE6IHRoZSBvcmlnaW5hbCBodHRwIHJlcXVlc3RcbiAgICovXG4gIHRyYWNrRXZlbnQoZXZlbnROYW1lLCBwYXJhbWV0ZXJzLCByZXEpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBBbmFseXRpY3NBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/AuthAdapter.js b/lib/Adapters/Auth/AuthAdapter.js index b3dec519db..6c4ea0972a 100644 --- a/lib/Adapters/Auth/AuthAdapter.js +++ b/lib/Adapters/Auth/AuthAdapter.js @@ -25,4 +25,5 @@ class AuthAdapter { } exports.AuthAdapter = AuthAdapter; -exports.default = AuthAdapter; \ No newline at end of file +exports.default = AuthAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL0F1dGhBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIkF1dGhBZGFwdGVyIiwidmFsaWRhdGVBcHBJZCIsImFwcElkcyIsImF1dGhEYXRhIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwib3B0aW9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNPLE1BQU1BLFdBQU4sQ0FBa0I7O0FBRXZCOzs7OztBQUtBQyxnQkFBY0MsTUFBZCxFQUFzQkMsUUFBdEIsRUFBZ0M7QUFDOUIsV0FBT0MsUUFBUUMsT0FBUixDQUFnQixFQUFoQixDQUFQO0FBQ0Q7O0FBRUQ7Ozs7QUFJQUMsbUJBQWlCSCxRQUFqQixFQUEyQkksT0FBM0IsRUFBb0M7QUFDbEMsV0FBT0gsUUFBUUMsT0FBUixDQUFnQixFQUFoQixDQUFQO0FBQ0Q7QUFqQnNCOztRQUFaTCxXLEdBQUFBLFc7a0JBb0JFQSxXIiwiZmlsZSI6IkF1dGhBZGFwdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyplc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIqL1xuZXhwb3J0IGNsYXNzIEF1dGhBZGFwdGVyIHtcblxuICAvKlxuICBAcGFyYW0gYXBwSWRzOiB0aGUgc3BlY2lmaWVkIGFwcCBpZHMgaW4gdGhlIGNvbmZpZ3VyYXRpb25cbiAgQHBhcmFtIGF1dGhEYXRhOiB0aGUgY2xpZW50IHByb3ZpZGVkIGF1dGhEYXRhXG4gIEByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGlmIHRoZSBhcHBsaWNhdGlvbklkIGlzIHZhbGlkXG4gICAqL1xuICB2YWxpZGF0ZUFwcElkKGFwcElkcywgYXV0aERhdGEpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgfVxuXG4gIC8qXG4gIEBwYXJhbSBhdXRoRGF0YTogdGhlIGNsaWVudCBwcm92aWRlZCBhdXRoRGF0YVxuICBAcGFyYW0gb3B0aW9uczogYWRkaXRpb25hbCBvcHRpb25zXG4gICAqL1xuICB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQXV0aEFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/OAuth1Client.js b/lib/Adapters/Auth/OAuth1Client.js index 68da0c6f99..5d719f7c1d 100644 --- a/lib/Adapters/Auth/OAuth1Client.js +++ b/lib/Adapters/Auth/OAuth1Client.js @@ -219,4 +219,5 @@ OAuth.signRequest = function (request, oauth_parameters, consumer_secret, auth_t return request; }; -module.exports = OAuth; \ No newline at end of file +module.exports = OAuth; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL09BdXRoMUNsaWVudC5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJjcnlwdG8iLCJQYXJzZSIsIk9BdXRoIiwib3B0aW9ucyIsIkVycm9yIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiY29uc3VtZXJfa2V5IiwiY29uc3VtZXJfc2VjcmV0IiwiYXV0aF90b2tlbiIsImF1dGhfdG9rZW5fc2VjcmV0IiwiaG9zdCIsIm9hdXRoX3BhcmFtcyIsInByb3RvdHlwZSIsInNlbmQiLCJtZXRob2QiLCJwYXRoIiwicGFyYW1zIiwiYm9keSIsInJlcXVlc3QiLCJidWlsZFJlcXVlc3QiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsImh0dHBSZXF1ZXN0IiwicmVzIiwiZGF0YSIsIm9uIiwiY2h1bmsiLCJKU09OIiwicGFyc2UiLCJ3cml0ZSIsImVuZCIsImluZGV4T2YiLCJPYmplY3QiLCJrZXlzIiwibGVuZ3RoIiwiYnVpbGRQYXJhbWV0ZXJTdHJpbmciLCJ0b1VwcGVyQ2FzZSIsIm9hdXRoX2NvbnN1bWVyX2tleSIsInNpZ25SZXF1ZXN0IiwiZ2V0IiwicG9zdCIsImVuY29kZSIsInN0ciIsInRvU3RyaW5nIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwicmVwbGFjZSIsInNpZ25hdHVyZU1ldGhvZCIsInZlcnNpb24iLCJub25jZSIsInRleHQiLCJwb3NzaWJsZSIsImkiLCJjaGFyQXQiLCJNYXRoIiwiZmxvb3IiLCJyYW5kb20iLCJvYmoiLCJzb3J0IiwibWFwIiwia2V5Iiwiam9pbiIsImJ1aWxkU2lnbmF0dXJlU3RyaW5nIiwidXJsIiwicGFyYW1ldGVycyIsInNpZ25hdHVyZSIsImNyZWF0ZUhtYWMiLCJ1cGRhdGUiLCJkaWdlc3QiLCJvYXV0aF9wYXJhbWV0ZXJzIiwib2F1dGhfbm9uY2UiLCJvYXV0aF90aW1lc3RhbXAiLCJEYXRlIiwiZ2V0VGltZSIsIm9hdXRoX3NpZ25hdHVyZV9tZXRob2QiLCJvYXV0aF92ZXJzaW9uIiwic2lnbmF0dXJlUGFyYW1zIiwicGFyYW1ldGVyc1RvTWVyZ2UiLCJrIiwicGFyYW1ldGVyU3RyaW5nIiwic2lnbmF0dXJlU3RyaW5nIiwic2lnbmF0dXJlS2V5Iiwib2F1dGhfc2lnbmF0dXJlIiwiaGVhZGVycyIsImF1dGhIZWFkZXIiLCJ2YWx1ZSIsIkF1dGhvcml6YXRpb24iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLElBQUlBLFFBQVFDLFFBQVEsT0FBUixDQUFaO0FBQUEsSUFDRUMsU0FBU0QsUUFBUSxRQUFSLENBRFg7QUFFQSxJQUFJRSxRQUFRRixRQUFRLFlBQVIsRUFBc0JFLEtBQWxDOztBQUVBLElBQUlDLFFBQVEsVUFBU0MsT0FBVCxFQUFrQjtBQUM1QixNQUFHLENBQUNBLE9BQUosRUFBYTtBQUNYLFVBQU0sSUFBSUYsTUFBTUcsS0FBVixDQUFnQkgsTUFBTUcsS0FBTixDQUFZQyxxQkFBNUIsRUFBbUQsNEJBQW5ELENBQU47QUFDRDtBQUNELE9BQUtDLFlBQUwsR0FBb0JILFFBQVFHLFlBQTVCO0FBQ0EsT0FBS0MsZUFBTCxHQUF1QkosUUFBUUksZUFBL0I7QUFDQSxPQUFLQyxVQUFMLEdBQWtCTCxRQUFRSyxVQUExQjtBQUNBLE9BQUtDLGlCQUFMLEdBQXlCTixRQUFRTSxpQkFBakM7QUFDQSxPQUFLQyxJQUFMLEdBQVlQLFFBQVFPLElBQXBCO0FBQ0EsT0FBS0MsWUFBTCxHQUFvQlIsUUFBUVEsWUFBUixJQUF3QixFQUE1QztBQUNELENBVkQ7O0FBWUFULE1BQU1VLFNBQU4sQ0FBZ0JDLElBQWhCLEdBQXVCLFVBQVNDLE1BQVQsRUFBaUJDLElBQWpCLEVBQXVCQyxNQUF2QixFQUErQkMsSUFBL0IsRUFBb0M7O0FBRXpELE1BQUlDLFVBQVUsS0FBS0MsWUFBTCxDQUFrQkwsTUFBbEIsRUFBMEJDLElBQTFCLEVBQWdDQyxNQUFoQyxFQUF3Q0MsSUFBeEMsQ0FBZDtBQUNBO0FBQ0EsU0FBTyxJQUFJRyxPQUFKLENBQVks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bEJqRSxZQUFRaUUsT0FBUixHQUFrQixFQUFsQjtBQUNEOztBQUVEO0FBQ0EsTUFBSUMsYUFBYW5ELE9BQU9DLElBQVAsQ0FBWW1DLGdCQUFaLEVBQThCWCxJQUE5QixHQUFxQ0MsR0FBckMsQ0FBeUMsVUFBU0MsR0FBVCxFQUFhO0FBQ3JFLFFBQUl5QixRQUFRaEIsaUJBQWlCVCxHQUFqQixDQUFaO0FBQ0EsV0FBT0EsTUFBTSxJQUFOLEdBQWF5QixLQUFiLEdBQXFCLEdBQTVCO0FBQ0QsR0FIZ0IsRUFHZHhCLElBSGMsQ0FHVCxJQUhTLENBQWpCOztBQUtBM0MsVUFBUWlFLE9BQVIsQ0FBZ0JHLGFBQWhCLEdBQWdDLFdBQVdGLFVBQTNDOztBQUVBO0FBQ0FsRSxVQUFRaUUsT0FBUixDQUFnQixjQUFoQixJQUFrQyxtQ0FBbEM7QUFDQSxTQUFPakUsT0FBUDtBQUVELENBakVEOztBQW1FQXFFLE9BQU9DLE9BQVAsR0FBaUJ0RixLQUFqQiIsImZpbGUiOiJPQXV0aDFDbGllbnQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpLFxuICBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxudmFyIE9BdXRoID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICBpZighb3B0aW9ucykge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsICdObyBvcHRpb25zIHBhc3NlZCB0byBPQXV0aCcpO1xuICB9XG4gIHRoaXMuY29uc3VtZXJfa2V5ID0gb3B0aW9ucy5jb25zdW1lcl9rZXk7XG4gIHRoaXMuY29uc3VtZXJfc2VjcmV0ID0gb3B0aW9ucy5jb25zdW1lcl9zZWNyZXQ7XG4gIHRoaXMuYXV0aF90b2tlbiA9IG9wdGlvbnMuYXV0aF90b2tlbjtcbiAgdGhpcy5hdXRoX3Rva2VuX3NlY3JldCA9IG9wdGlvbnMuYXV0aF90b2tlbl9zZWNyZXQ7XG4gIHRoaXMuaG9zdCA9IG9wdGlvbnMuaG9zdDtcbiAgdGhpcy5vYXV0aF9wYXJhbXMgPSBvcHRpb25zLm9hdXRoX3BhcmFtcyB8fCB7fTtcbn07XG5cbk9BdXRoLnByb3RvdHlwZS5zZW5kID0gZnVuY3Rpb24obWV0aG9kLCBwYXRoLCBwYXJhbXMsIGJvZHkpe1xuXG4gIHZhciByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QobWV0aG9kLCBwYXRoLCBwYXJhbXMsIGJvZHkpO1xuICAvLyBFbmNvZGUgdGhlIGJvZHkgcHJvcGVybHksIHRoZSBjdXJyZW50IFBhcnNlIEltcGxlbWVudGF0aW9uIGRvbid0IGRvIGl0IHByb3Blcmx5XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgaHR0cFJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KHJlcXVlc3QsIGZ1bmN0aW9uKHJlcykge1xuICAgICAgdmFyIGRhdGEgPSAnJztcbiAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uKGNodW5rKSB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgfSk7XG4gICAgfSkub24oJ2Vycm9yJywgZnVuY3Rpb24oKSB7XG4gICAgICByZWplY3QoJ0ZhaWxlZCB0byBtYWtlIGFuIE9BdXRoIHJlcXVlc3QnKTtcbiAgICB9KTtcbiAgICBpZiAocmVxdWVzdC5ib2R5KSB7XG4gICAgICBodHRwUmVxdWVzdC53cml0ZShyZXF1ZXN0LmJvZHkpO1xuICAgIH1cbiAgICBodHRwUmVxdWVzdC5lbmQoKTtcbiAgfSk7XG59O1xuXG5PQXV0aC5wcm90b3R5cGUuYnVpbGRSZXF1ZXN0ID0gZnVuY3Rpb24obWV0aG9kLCBwYXRoLCBwYXJhbXMsIGJvZHkpIHtcbiAgaWYgKHBhdGguaW5kZXhPZihcIi9cIikgIT0gMCkge1xuICAgIHBhdGggPSBcIi9cIiArIHBhdGg7XG4gIH1cbiAgaWYgKHBhcmFtcyAmJiBPYmplY3Qua2V5cyhwYXJhbXMpLmxlbmd0aCA+IDApIHtcbiAgICBwYXRoICs9IFwiP1wiICsgT0F1dGguYnVpbGRQYXJhbWV0ZXJTdHJpbmcocGFyYW1zKTtcbiAgfVxuXG4gIHZhciByZXF1ZXN0ID0ge1xuICAgIGhvc3Q6ICAgdGhpcy5ob3N0LFxuICAgIHBhdGg6IFx0cGF0aCxcbiAgICBtZXRob2Q6IG1ldGhvZC50b1VwcGVyQ2FzZSgpXG4gIH07XG5cbiAgdmFyIG9hdXRoX3BhcmFtcyA9IHRoaXMub2F1dGhfcGFyYW1zIHx8IHt9O1xuICBvYXV0aF9wYXJhbXMub2F1dGhfY29uc3VtZXJfa2V5ID0gdGhpcy5jb25zdW1lcl9rZXk7XG4gIGlmKHRoaXMuYXV0aF90b2tlbil7XG4gICAgb2F1dGhfcGFyYW1zW1wib2F1dGhfdG9rZW5cIl0gPSB0aGlzLmF1dGhfdG9rZW47XG4gIH1cblxuICByZXF1ZXN0ID0gT0F1dGguc2lnblJlcXVlc3QocmVxdWVzdCwgb2F1dGhfcGFyYW1zLCB0aGlzLmNvbnN1bWVyX3NlY3JldCwgIHRoaXMuYXV0aF90b2tlbl9zZWNyZXQpO1xuXG4gIGlmIChib2R5ICYmIE9iamVjdC5rZXlzKGJvZHkpLmxlbmd0aCA+IDApIHtcbiAgICByZXF1ZXN0LmJvZHkgPSBPQXV0aC5idWlsZFBhcmFtZXRlclN0cmluZyhib2R5KTtcbiAgfVxuICByZXR1cm4gcmVxdWVzdDtcbn1cblxuT0F1dGgucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uKHBhdGgsIHBhcmFtcykge1xuICByZXR1cm4gdGhpcy5zZW5kKFwiR0VUXCIsIHBhdGgsIHBhcmFtcyk7XG59XG5cbk9BdXRoLnByb3RvdHlwZS5wb3N0ID0gZnVuY3Rpb24ocGF0aCwgcGFyYW1zLCBib2R5KSB7XG4gIHJldHVybiB0aGlzLnNlbmQoXCJQT1NUXCIsIHBhdGgsIHBhcmFtcywgYm9keSk7XG59XG5cbi8qXG5cdFByb3BlciBzdHJpbmcgJWVzY2FwZSBlbmNvZGluZ1xuKi9cbk9BdXRoLmVuY29kZSA9IGZ1bmN0aW9uKHN0cikge1xuICAvLyAgICAgICBkaXNjdXNzIGF0OiBodHRwOi8vcGhwanMub3JnL2Z1bmN0aW9ucy9yYXd1cmxlbmNvZGUvXG4gIC8vICAgICAgb3JpZ2luYWwgYnk6IEJyZXR0IFphbWlyIChodHRwOi8vYnJldHQtemFtaXIubWUpXG4gIC8vICAgICAgICAgaW5wdXQgYnk6IHRyYXZjXG4gIC8vICAgICAgICAgaW5wdXQgYnk6IEJyZXR0IFphbWlyIChodHRwOi8vYnJldHQtemFtaXIubWUpXG4gIC8vICAgICAgICAgaW5wdXQgYnk6IE1pY2hhZWwgR3JpZXJcbiAgLy8gICAgICAgICBpbnB1dCBieTogUmF0aGVvdXNcbiAgLy8gICAgICBidWdmaXhlZCBieTogS2V2aW4gdmFuIFpvbm5ldmVsZCAoaHR0cDovL2tldmluLnZhbnpvbm5ldmVsZC5uZXQpXG4gIC8vICAgICAgYnVnZml4ZWQgYnk6IEJyZXR0IFphbWlyIChodHRwOi8vYnJldHQtemFtaXIubWUpXG4gIC8vICAgICAgYnVnZml4ZWQgYnk6IEpvcmlzXG4gIC8vIHJlaW1wbGVtZW50ZWQgYnk6IEJyZXR0IFphbWlyIChodHRwOi8vYnJldHQtemFtaXIubWUpXG4gIC8vIHJlaW1wbGVtZW50ZWQgYnk6IEJyZXR0IFphbWlyIChodHRwOi8vYnJldHQtemFtaXIubWUpXG4gIC8vICAgICAgICAgICAgIG5vdGU6IFRoaXMgcmVmbGVjdHMgUEhQIDUuMy82LjArIGJlaGF2aW9yXG4gIC8vICAgICAgICAgICAgIG5vdGU6IFBsZWFzZSBiZSBhd2FyZSB0aGF0IHRoaXMgZnVuY3Rpb24gZXhwZWN0cyB0byBlbmNvZGUgaW50byBVVEYtOCBlbmNvZGVkIHN0cmluZ3MsIGFzIGZvdW5kIG9uXG4gIC8vICAgICAgICAgICAgIG5vdGU6IHBhZ2VzIHNlcnZlZCBhcyBVVEYtOFxuICAvLyAgICAgICAgZXhhbXBsZSAxOiByYXd1cmxlbmNvZGUoJ0tldmluIHZhbiBab25uZXZlbGQhJyk7XG4gIC8vICAgICAgICByZXR1cm5zIDE6ICdLZXZpbiUyMHZhbiUyMFpvbm5ldmVsZCUyMSdcbiAgLy8gICAgICAgIGV4YW1wbGUgMjogcmF3dXJsZW5jb2RlKCdodHRwOi8va2V2aW4udmFuem9ubmV2ZWxkLm5ldC8nKTtcbiAgLy8gICAgICAgIHJldHVybnMgMjogJ2h0dHAlM0ElMkYlMkZrZXZpbi52YW56b25uZXZlbGQubmV0JTJGJ1xuICAvLyAgICAgICAgZXhhbXBsZSAzOiByYXd1cmxlbmNvZGUoJ2h0dHA6Ly93d3cuZ29vZ2xlLm5sL3NlYXJjaD9xPXBocC5qcyZpZT11dGYtOCZvZT11dGYtOCZhcT10JnJscz1jb20udWJ1bnR1OmVuLVVTOnVub2ZmaWNpYWwmY2xpZW50PWZpcmVmb3gtYScpO1xuICAvLyAgICAgICAgcmV0dXJucyAzOiAnaHR0cCUzQSUyRiUyRnd3dy5nb29nbGUubmwlMkZzZWFyY2glM0ZxJTNEcGhwLmpzJTI2aWUlM0R1dGYtOCUyNm9lJTNEdXRmLTglMjZhcSUzRHQlMjZybHMlM0Rjb20udWJ1bnR1JTNBZW4tVVMlM0F1bm9mZmljaWFsJTI2Y2xpZW50JTNEZmlyZWZveC1hJ1xuXG4gIHN0ciA9IChzdHIgKyAnJylcbiAgICAudG9TdHJpbmcoKTtcblxuICAvLyBUaWxkZSBzaG91bGQgYmUgYWxsb3dlZCB1bmVzY2FwZWQgaW4gZnV0dXJlIHZlcnNpb25zIG9mIFBIUCAoYXMgcmVmbGVjdGVkIGJlbG93KSwgYnV0IGlmIHlvdSB3YW50IHRvIHJlZmxlY3QgY3VycmVudFxuICAvLyBQSFAgYmVoYXZpb3IsIHlvdSB3b3VsZCBuZWVkIHRvIGFkZCBcIi5yZXBsYWNlKC9+L2csICclN0UnKTtcIiB0byB0aGUgZm9sbG93aW5nLlxuICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHN0cilcbiAgICAucmVwbGFjZSgvIS9nLCAnJTIxJylcbiAgICAucmVwbGFjZSgvJy9nLCAnJTI3JylcbiAgICAucmVwbGFjZSgvXFwoL2csICclMjgnKVxuICAgIC5yZXBsYWNlKC9cXCkvZywgJyUyOScpXG4gICAgLnJlcGxhY2UoL1xcKi9nLCAnJTJBJyk7XG59XG5cbk9BdXRoLnNpZ25hdHVyZU1ldGhvZCA9IFwiSE1BQy1TSEExXCI7XG5PQXV0aC52ZXJzaW9uID0gXCIxLjBcIjtcblxuLypcblx0R2VuZXJhdGUgYSBub25jZVxuKi9cbk9BdXRoLm5vbmNlID0gZnVuY3Rpb24oKXtcbiAgdmFyIHRleHQgPSBcIlwiO1xuICB2YXIgcG9zc2libGUgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5XCI7XG5cbiAgZm9yKHZhciBpID0gMDsgaSA8IDMwOyBpKyspXG4gICAgdGV4dCArPSBwb3NzaWJsZS5jaGFyQXQoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogcG9zc2libGUubGVuZ3RoKSk7XG5cbiAgcmV0dXJuIHRleHQ7XG59XG5cbk9BdXRoLmJ1aWxkUGFyYW1ldGVyU3RyaW5nID0gZnVuY3Rpb24ob2JqKXtcbiAgLy8gU29ydCBrZXlzIGFuZCBlbmNvZGUgdmFsdWVzXG4gIGlmIChvYmopIHtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaikuc29ydCgpO1xuXG4gICAgLy8gTWFwIGtleT12YWx1ZSwgam9pbiB0aGVtIGJ5ICZcbiAgICByZXR1cm4ga2V5cy5tYXAoZnVuY3Rpb24oa2V5KXtcbiAgICAgIHJldHVybiBrZXkgKyBcIj1cIiArIE9BdXRoLmVuY29kZShvYmpba2V5XSk7XG4gICAgfSkuam9pbihcIiZcIik7XG4gIH1cblxuICByZXR1cm4gXCJcIjtcbn1cblxuLypcblx0QnVpbGQgdGhlIHNpZ25hdHVyZSBzdHJpbmcgZnJvbSB0aGUgb2JqZWN0XG4qL1xuXG5PQXV0aC5idWlsZFNpZ25hdHVyZVN0cmluZyA9IGZ1bmN0aW9uKG1ldGhvZCwgdXJsLCBwYXJhbWV0ZXJzKXtcbiAgcmV0dXJuIFttZXRob2QudG9VcHBlckNhc2UoKSwgT0F1dGguZW5jb2RlKHVybCksIE9BdXRoLmVuY29kZShwYXJhbWV0ZXJzKV0uam9pbihcIiZcIik7XG59XG5cbi8qXG5cdFJldHVucyBlbmNvZGVkIEhNQUMtU0hBMSBmcm9tIGtleSBhbmQgdGV4dFxuKi9cbk9BdXRoLnNpZ25hdHVyZSA9IGZ1bmN0aW9uKHRleHQsIGtleSl7XG4gIGNyeXB0byA9IHJlcXVpcmUoXCJjcnlwdG9cIik7XG4gIHJldHVybiBPQXV0aC5lbmNvZGUoY3J5cHRvLmNyZWF0ZUhtYWMoJ3NoYTEnLCBrZXkpLnVwZGF0ZSh0ZXh0KS5kaWdlc3QoJ2Jhc2U2NCcpKTtcbn1cblxuT0F1dGguc2lnblJlcXVlc3QgPSBmdW5jdGlvbihyZXF1ZXN0LCBvYXV0aF9wYXJhbWV0ZXJzLCBjb25zdW1lcl9zZWNyZXQsIGF1dGhfdG9rZW5fc2VjcmV0KXtcbiAgb2F1dGhfcGFyYW1ldGVycyA9IG9hdXRoX3BhcmFtZXRlcnMgfHwge307XG5cbiAgLy8gU2V0IGRlZmF1bHQgdmFsdWVzXG4gIGlmICghb2F1dGhfcGFyYW1ldGVycy5vYXV0aF9ub25jZSkge1xuICAgIG9hdXRoX3BhcmFtZXRlcnMub2F1dGhfbm9uY2UgPSBPQXV0aC5ub25jZSgpO1xuICB9XG4gIGlmICghb2F1dGhfcGFyYW1ldGVycy5vYXV0aF90aW1lc3RhbXApIHtcbiAgICBvYXV0aF9wYXJhbWV0ZXJzLm9hdXRoX3RpbWVzdGFtcCA9IE1hdGguZmxvb3IobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKTtcbiAgfVxuICBpZiAoIW9hdXRoX3BhcmFtZXRlcnMub2F1dGhfc2lnbmF0dXJlX21ldGhvZCkge1xuICAgIG9hdXRoX3BhcmFtZXRlcnMub2F1dGhfc2lnbmF0dXJlX21ldGhvZCA9IE9BdXRoLnNpZ25hdHVyZU1ldGhvZDtcbiAgfVxuICBpZiAoIW9hdXRoX3BhcmFtZXRlcnMub2F1dGhfdmVyc2lvbikge1xuICAgIG9hdXRoX3BhcmFtZXRlcnMub2F1dGhfdmVyc2lvbiA9IE9BdXRoLnZlcnNpb247XG4gIH1cblxuICBpZighYXV0aF90b2tlbl9zZWNyZXQpe1xuICAgIGF1dGhfdG9rZW5fc2VjcmV0ID0gXCJcIjtcbiAgfVxuICAvLyBGb3JjZSBHRVQgbWV0aG9kIGlmIHVuc2V0XG4gIGlmICghcmVxdWVzdC5tZXRob2QpIHtcbiAgICByZXF1ZXN0Lm1ldGhvZCA9IFwiR0VUXCJcbiAgfVxuXG4gIC8vIENvbGxlY3QgIGFsbCB0aGUgcGFyYW1ldGVycyBpbiBvbmUgc2lnbmF0dXJlUGFyYW1ldGVycyBvYmplY3RcbiAgdmFyIHNpZ25hdHVyZVBhcmFtcyA9IHt9O1xuICB2YXIgcGFyYW1ldGVyc1RvTWVyZ2UgPSBbcmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QuYm9keSwgb2F1dGhfcGFyYW1ldGVyc107XG4gIGZvcih2YXIgaSBpbiBwYXJhbWV0ZXJzVG9NZXJnZSkge1xuICAgIHZhciBwYXJhbWV0ZXJzID0gcGFyYW1ldGVyc1RvTWVyZ2VbaV07XG4gICAgZm9yKHZhciBrIGluIHBhcmFtZXRlcnMpIHtcbiAgICAgIHNpZ25hdHVyZVBhcmFtc1trXSA9IHBhcmFtZXRlcnNba107XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIGEgc3RyaW5nIGJhc2VkIG9uIHRoZSBwYXJhbWV0ZXJzXG4gIHZhciBwYXJhbWV0ZXJTdHJpbmcgPSBPQXV0aC5idWlsZFBhcmFtZXRlclN0cmluZyhzaWduYXR1cmVQYXJhbXMpO1xuXG4gIC8vIEJ1aWxkIHRoZSBzaWduYXR1cmUgc3RyaW5nXG4gIHZhciB1cmwgPSBcImh0dHBzOi8vXCIgKyByZXF1ZXN0Lmhvc3QgKyBcIlwiICsgcmVxdWVzdC5wYXRoO1xuXG4gIHZhciBzaWduYXR1cmVTdHJpbmcgPSBPQXV0aC5idWlsZFNpZ25hdHVyZVN0cmluZyhyZXF1ZXN0Lm1ldGhvZCwgdXJsLCBwYXJhbWV0ZXJTdHJpbmcpO1xuICAvLyBIYXNoIHRoZSBzaWduYXR1cmUgc3RyaW5nXG4gIHZhciBzaWduYXR1cmVLZXkgPSBbT0F1dGguZW5jb2RlKGNvbnN1bWVyX3NlY3JldCksIE9BdXRoLmVuY29kZShhdXRoX3Rva2VuX3NlY3JldCldLmpvaW4oXCImXCIpO1xuXG4gIHZhciBzaWduYXR1cmUgPSBPQXV0aC5zaWduYXR1cmUoc2lnbmF0dXJlU3RyaW5nLCBzaWduYXR1cmVLZXkpO1xuXG4gIC8vIFNldCB0aGUgc2lnbmF0dXJlIGluIHRoZSBwYXJhbXNcbiAgb2F1dGhfcGFyYW1ldGVycy5vYXV0aF9zaWduYXR1cmUgPSBzaWduYXR1cmU7XG4gIGlmKCFyZXF1ZXN0LmhlYWRlcnMpe1xuICAgIHJlcXVlc3QuaGVhZGVycyA9IHt9O1xuICB9XG5cbiAgLy8gU2V0IHRoZSBhdXRob3JpemF0aW9uIGhlYWRlclxuICB2YXIgYXV0aEhlYWRlciA9IE9iamVjdC5rZXlzKG9hdXRoX3BhcmFtZXRlcnMpLnNvcnQoKS5tYXAoZnVuY3Rpb24oa2V5KXtcbiAgICB2YXIgdmFsdWUgPSBvYXV0aF9wYXJhbWV0ZXJzW2tleV07XG4gICAgcmV0dXJuIGtleSArICc9XCInICsgdmFsdWUgKyAnXCInO1xuICB9KS5qb2luKFwiLCBcIilcblxuICByZXF1ZXN0LmhlYWRlcnMuQXV0aG9yaXphdGlvbiA9ICdPQXV0aCAnICsgYXV0aEhlYWRlcjtcblxuICAvLyBTZXQgdGhlIGNvbnRlbnQgdHlwZSBoZWFkZXJcbiAgcmVxdWVzdC5oZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdID0gXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIjtcbiAgcmV0dXJuIHJlcXVlc3Q7XG5cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBPQXV0aDtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/facebook.js b/lib/Adapters/Auth/facebook.js index 2e422926f8..825e6fe932 100644 --- a/lib/Adapters/Auth/facebook.js +++ b/lib/Adapters/Auth/facebook.js @@ -31,7 +31,7 @@ function validateAppId(appIds, authData) { // A promisey wrapper for FB graph requests. function graphRequest(path) { return new Promise(function (resolve, reject) { - https.get('https://graph.facebook.com/v2.5/' + path, function (res) { + https.get('https://graph.facebook.com/' + path, function (res) { var data = ''; res.on('data', function (chunk) { data += chunk; @@ -53,4 +53,5 @@ function graphRequest(path) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2ZhY2Vib29rLmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsIlBhcnNlIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwiZ3JhcGhSZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJhcHBJZHMiLCJsZW5ndGgiLCJpbmRleE9mIiwicGF0aCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZ2V0IiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsImUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsUUFBUUMsUUFBUSxPQUFSLENBQVo7QUFDQSxJQUFJQyxRQUFRRCxRQUFRLFlBQVIsRUFBc0JDLEtBQWxDOztBQUVBO0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DO0FBQ2xDLFNBQU9DLGFBQWEsK0JBQStCRCxTQUFTRSxZQUFyRCxFQUNKQyxJQURJLENBQ0VDLElBQUQsSUFBVTtBQUNkLFFBQUlBLFFBQVFBLEtBQUtDLEVBQUwsSUFBV0wsU0FBU0ssRUFBaEMsRUFBb0M7QUFDbEM7QUFDRDtBQUNELFVBQU0sSUFBSVAsTUFBTVEsS0FBVixDQUNKUixNQUFNUSxLQUFOLENBQVlDLGdCQURSLEVBRUoseUNBRkksQ0FBTjtBQUdELEdBUkksQ0FBUDtBQVNEOztBQUVEO0FBQ0EsU0FBU0MsYUFBVCxDQUF1QkMsTUFBdkIsRUFBK0JULFFBQS9CLEVBQXlDO0FBQ3ZDLE1BQUlFLGVBQWVGLFNBQVNFLFlBQTVCO0FBQ0EsTUFBSSxDQUFDTyxPQUFPQyxNQUFaLEVBQW9CO0FBQ2xCLFVBQU0sSUFBSVosTUFBTVEsS0FBVixDQUNKUixNQUFNUSxLQUFOLENBQVlDLGdCQURSLEVBRUosa0NBRkksQ0FBTjtBQUdEO0FBQ0QsU0FBT04sYUFBYSxzQkFBc0JDLFlBQW5DLEVBQ0pDLElBREksQ0FDRUMsSUFBRCxJQUFVO0FBQ2QsUUFBSUEsUUFBUUssT0FBT0UsT0FBUCxDQUFlUCxLQUFLQyxFQUFwQixLQUEyQixDQUFDLENBQXhDLEVBQTJDO0FBQ3pDO0FBQ0Q7QUFDRCxVQUFNLElBQUlQLE1BQU1RLEtBQVYsQ0FDSlIsTUFBTVEsS0FBTixDQUFZQyxnQkFEUixFQUVKLHlDQUZJLENBQU47QUFHRCxHQVJJLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNOLFlBQVQsQ0FBc0JXLElBQXRCLEVBQTRCO0FBQzFCLFNBQU8sSUFBSUMsT0FBSixDQUFZLFVBQVNDLE9BQVQsRUFBa0JDLE1BQWxCLEVBQTBCO0FBQzNDbkIsVUFBTW9CLEdBQU4sQ0FBVSxnQ0FBZ0NKLElBQTFDLEVBQWdELFVBQVNLLEdBQVQsRUFBYztBQUM1RCxVQUFJYixPQUFPLEVBQVg7QUFDQWEsVUFBSUMsRUFBSixDQUFPLE1BQVAsRUFBZSxVQUFTQyxLQUFULEVBQWdCO0FBQzdCZixnQkFBUWUsS0FBUjtBQUNELE9BRkQ7QUFHQUYsVUFBSUMsRUFBSixDQUFPLEtBQVAsRUFBYyxZQUFXO0FBQ3ZCLFlBQUk7QUFDRmQsaUJBQU9nQixLQUFLQyxLQUFMLENBQVdqQixJQUFYLENBQVA7QUFDRCxTQUZELENBRUUsT0FBTWtCLENBQU4sRUFBUztBQUNULGlCQUFPUCxPQUFPTyxDQUFQLENBQVA7QUFDRDtBQUNEUixnQkFBUVYsSUFBUjtBQUNELE9BUEQ7QUFRRCxLQWJELEVBYUdjLEVBYkgsQ0FhTSxPQWJOLEVBYWUsWUFBVztBQUN4QkgsYUFBTyxxREFBUDtBQUNELEtBZkQ7QUFnQkQsR0FqQk0sQ0FBUDtBQWtCRDs7QUFFRFEsT0FBT0MsT0FBUCxHQUFpQjtBQUNmaEIsaUJBQWVBLGFBREE7QUFFZlQsb0JBQWtCQTtBQUZILENBQWpCIiwiZmlsZSI6ImZhY2Vib29rLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBGYWNlYm9vayBHcmFwaCBBUEkuXG52YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIHJldHVybiBncmFwaFJlcXVlc3QoJ21lP2ZpZWxkcz1pZCZhY2Nlc3NfdG9rZW49JyArIGF1dGhEYXRhLmFjY2Vzc190b2tlbilcbiAgICAudGhlbigoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEgJiYgZGF0YS5pZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICdGYWNlYm9vayBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKGFwcElkcywgYXV0aERhdGEpIHtcbiAgdmFyIGFjY2Vzc190b2tlbiA9IGF1dGhEYXRhLmFjY2Vzc190b2tlbjtcbiAgaWYgKCFhcHBJZHMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdGYWNlYm9vayBhdXRoIGlzIG5vdCBjb25maWd1cmVkLicpO1xuICB9XG4gIHJldHVybiBncmFwaFJlcXVlc3QoJ2FwcD9hY2Nlc3NfdG9rZW49JyArIGFjY2Vzc190b2tlbilcbiAgICAudGhlbigoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEgJiYgYXBwSWRzLmluZGV4T2YoZGF0YS5pZCkgIT0gLTEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnRmFjZWJvb2sgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJyk7XG4gICAgfSk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgRkIgZ3JhcGggcmVxdWVzdHMuXG5mdW5jdGlvbiBncmFwaFJlcXVlc3QocGF0aCkge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgaHR0cHMuZ2V0KCdodHRwczovL2dyYXBoLmZhY2Vib29rLmNvbS8nICsgcGF0aCwgZnVuY3Rpb24ocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgIH0pO1xuICAgICAgcmVzLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgfSk7XG4gICAgfSkub24oJ2Vycm9yJywgZnVuY3Rpb24oKSB7XG4gICAgICByZWplY3QoJ0ZhaWxlZCB0byB2YWxpZGF0ZSB0aGlzIGFjY2VzcyB0b2tlbiB3aXRoIEZhY2Vib29rLicpO1xuICAgIH0pO1xuICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGFcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/facebookaccountkit.js b/lib/Adapters/Auth/facebookaccountkit.js index 1e975a08c5..2272362589 100644 --- a/lib/Adapters/Auth/facebookaccountkit.js +++ b/lib/Adapters/Auth/facebookaccountkit.js @@ -65,4 +65,5 @@ function validateAuthData(authData, options) { module.exports = { validateAppId, validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2ZhY2Vib29rYWNjb3VudGtpdC5qcyJdLCJuYW1lcyI6WyJjcnlwdG8iLCJyZXF1aXJlIiwiaHR0cHMiLCJQYXJzZSIsImdyYXBoUmVxdWVzdCIsInBhdGgiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsImdldCIsInJlcyIsImRhdGEiLCJvbiIsImNodW5rIiwiSlNPTiIsInBhcnNlIiwiZXJyb3IiLCJlIiwiZ2V0UmVxdWVzdFBhdGgiLCJhdXRoRGF0YSIsIm9wdGlvbnMiLCJhY2Nlc3NfdG9rZW4iLCJhcHBTZWNyZXQiLCJhcHBzZWNyZXRfcHJvb2YiLCJjcmVhdGVIbWFjIiwidXBkYXRlIiwiZGlnZXN0IiwidmFsaWRhdGVBcHBJZCIsImFwcElkcyIsImxlbmd0aCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInRoZW4iLCJhcHBsaWNhdGlvbiIsImluZGV4T2YiLCJpZCIsInZhbGlkYXRlQXV0aERhdGEiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLE1BQU1BLFNBQVNDLFFBQVEsUUFBUixDQUFmO0FBQ0EsTUFBTUMsUUFBUUQsUUFBUSxPQUFSLENBQWQ7QUFDQSxNQUFNRSxRQUFTRixRQUFRLFlBQVIsRUFBc0JFLEtBQXJDOztBQUVBLE1BQU1DLGVBQWdCQyxJQUFELElBQVU7QUFDN0IsU0FBTyxJQUFJQyxPQUFKLENBQVksQ0FBQ0MsT0FBRCxFQUFVQyxNQUFWLEtBQXFCO0FBQ3RDTixVQUFNTyxHQUFOLENBQVcscUNBQW9DSixJQUFLLEVBQXBELEVBQXdESyxHQUFELElBQVM7QUFDOUQsVUFBSUMsT0FBTyxFQUFYO0FBQ0FELFVBQUlFLEVBQUosQ0FBTyxNQUFQLEVBQWdCQyxLQUFELElBQVc7QUFDeEJGLGdCQUFRRSxLQUFSO0FBQ0QsT0FGRDtBQUdBSCxVQUFJRSxFQUFKLENBQU8sS0FBUCxFQUFjLE1BQU07QUFDbEIsWUFBSTtBQUNGRCxpQkFBT0csS0FBS0MsS0FBTCxDQUFXSixJQUFYLENBQVA7QUFDQSxjQUFJQSxLQUFLSyxLQUFULEVBQWdCO0FBQ2Q7QUFDQTtBQUNBUixtQkFBT0csS0FBS0ssS0FBWjtBQUNELFdBSkQsTUFJTztBQUNMVCxvQkFBUUksSUFBUjtBQUNEO0FBQ0YsU0FURCxDQVNFLE9BQU9NLENBQVAsRUFBVTtBQUNWVCxpQkFBT1MsQ0FBUDtBQUNEO0FBQ0YsT0FiRDtBQWNELEtBbkJELEVBbUJHTCxFQW5CSCxDQW1CTSxPQW5CTixFQW1CZSxZQUFZO0FBQ3pCSixhQUFPLGlFQUFQO0FBQ0QsS0FyQkQ7QUFzQkQsR0F2Qk0sQ0FBUDtBQXdCRCxDQXpCRDs7QUEyQkEsU0FBU1UsY0FBVCxDQUF3QkMsUUFBeEIsRUFBa0NDLE9BQWxDLEVBQTJDO0FBQ3pDLFFBQU1DLGVBQWVGLFNBQVNFLFlBQTlCO0FBQUEsUUFBNENDLFlBQVlGLFdBQVdBLFFBQVFFLFNBQTNFO0FBQ0EsTUFBSUEsU0FBSixFQUFlO0FBQ2IsVUFBTUMsa0JBQWtCdkIsT0FBT3dCLFVBQVAsQ0FBa0IsUUFBbEIsRUFBNEJGLFNBQTVCLEVBQXVDRyxNQUF2QyxDQUE4Q0osWUFBOUMsRUFBNERLLE1BQTVELENBQW1FLEtBQW5FLENBQXhCO0FBQ0EsV0FBUSxtQkFBa0JMLFlBQWEsb0JBQW1CRSxlQUFnQixFQUExRTtBQUNEO0FBQ0QsU0FBUSxtQkFBa0JGLFlBQWEsRUFBdkM7QUFDRDs7QUFFRCxTQUFTTSxhQUFULENBQXVCQyxNQUF2QixFQUErQlQsUUFBL0IsRUFBeUNDLE9BQXpDLEVBQWtEO0FBQ2hELE1BQUksQ0FBQ1EsT0FBT0MsTUFBWixFQUFvQjtBQUNsQixXQUFPdkIsUUFBUUUsTUFBUixDQUNMLElBQUlMLE1BQU0yQixLQUFWLENBQ0UzQixNQUFNMkIsS0FBTixDQUFZQyxnQkFEZCxFQUVFLG9EQUZGLENBREssQ0FBUDtBQUtEO0FBQ0QsU0FBTzNCLGFBQWFjLGVBQWVDLFFBQWYsRUFBeUJDLE9BQXpCLENBQWIsRUFDSlksSUFESSxDQUNDckIsUUFBUTtBQUNaLFFBQUlBLFFBQVFBLEtBQUtzQixXQUFiLElBQTRCTCxPQUFPTSxPQUFQLENBQWV2QixLQUFLc0IsV0FBTCxDQUFpQkUsRUFBaEMsS0FBdUMsQ0FBQyxDQUF4RSxFQUEyRTtBQUN6RTtBQUNEO0FBQ0QsVUFBTSxJQUFJaEMsTUFBTTJCLEtBQVYsQ0FDSjNCLE1BQU0yQixLQUFOLENBQVlDLGdCQURSLEVBRUosMkRBRkksQ0FBTjtBQUdELEdBUkksQ0FBUDtBQVNEOztBQUVELFNBQVNLLGdCQUFULENBQTBCakIsUUFBMUIsRUFBb0NDLE9BQXBDLEVBQTZDO0FBQzNDLFNBQU9oQixhQUFhYyxlQUFlQyxRQUFmLEVBQXlCQyxPQUF6QixDQUFiLEVBQ0pZLElBREksQ0FDQ3JCLFFBQVE7QUFDWixRQUFJQSxRQUFRQSxLQUFLd0IsRUFBTCxJQUFXaEIsU0FBU2dCLEVBQWhDLEVBQW9DO0FBQ2xDO0FBQ0Q7QUFDRCxVQUFNLElBQUloQyxNQUFNMkIsS0FBVixDQUNKM0IsTUFBTTJCLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSixxREFGSSxDQUFOO0FBR0QsR0FSSSxDQUFQO0FBU0Q7O0FBRURNLE9BQU9DLE9BQVAsR0FBaUI7QUFDZlgsZUFEZTtBQUVmUztBQUZlLENBQWpCIiwiZmlsZSI6ImZhY2Vib29rYWNjb3VudGtpdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGNyeXB0byA9IHJlcXVpcmUoJ2NyeXB0bycpO1xuY29uc3QgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xuY29uc3QgUGFyc2UgID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG5jb25zdCBncmFwaFJlcXVlc3QgPSAocGF0aCkgPT4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGh0dHBzLmdldChgaHR0cHM6Ly9ncmFwaC5hY2NvdW50a2l0LmNvbS92MS4xLyR7cGF0aH1gLCAocmVzKSA9PiB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgKGNodW5rKSA9PiB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICAgIGlmIChkYXRhLmVycm9yKSB7XG4gICAgICAgICAgICAvLyB3aGVuIHNvbWV0aGluZyB3cm9uZyB3aXRoIGZiIGdyYXBoIHJlcXVlc3QgKHRva2VuIGNvcnJ1cHRlZCBldGMuKVxuICAgICAgICAgICAgLy8gaW5zdGVhZCBvZiBuZXR3b3JrIGlzc3VlXG4gICAgICAgICAgICByZWplY3QoZGF0YS5lcnJvcik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KS5vbignZXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICByZWplY3QoJ0ZhaWxlZCB0byB2YWxpZGF0ZSB0aGlzIGFjY2VzcyB0b2tlbiB3aXRoIEZhY2Vib29rIEFjY291bnQgS2l0LicpO1xuICAgIH0pO1xuICB9KTtcbn07XG5cbmZ1bmN0aW9uIGdldFJlcXVlc3RQYXRoKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gIGNvbnN0IGFjY2Vzc190b2tlbiA9IGF1dGhEYXRhLmFjY2Vzc190b2tlbiwgYXBwU2VjcmV0ID0gb3B0aW9ucyAmJiBvcHRpb25zLmFwcFNlY3JldDtcbiAgaWYgKGFwcFNlY3JldCkge1xuICAgIGNvbnN0IGFwcHNlY3JldF9wcm9vZiA9IGNyeXB0by5jcmVhdGVIbWFjKFwic2hhMjU2XCIsIGFwcFNlY3JldCkudXBkYXRlKGFjY2Vzc190b2tlbikuZGlnZXN0KCdoZXgnKTtcbiAgICByZXR1cm4gYG1lP2FjY2Vzc190b2tlbj0ke2FjY2Vzc190b2tlbn0mYXBwc2VjcmV0X3Byb29mPSR7YXBwc2VjcmV0X3Byb29mfWBcbiAgfVxuICByZXR1cm4gYG1lP2FjY2Vzc190b2tlbj0ke2FjY2Vzc190b2tlbn1gO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKGFwcElkcywgYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgaWYgKCFhcHBJZHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnRmFjZWJvb2sgYXBwIGlkIGZvciBBY2NvdW50IEtpdCBpcyBub3QgY29uZmlndXJlZC4nKVxuICAgIClcbiAgfVxuICByZXR1cm4gZ3JhcGhSZXF1ZXN0KGdldFJlcXVlc3RQYXRoKGF1dGhEYXRhLCBvcHRpb25zKSlcbiAgICAudGhlbihkYXRhID0+IHtcbiAgICAgIGlmIChkYXRhICYmIGRhdGEuYXBwbGljYXRpb24gJiYgYXBwSWRzLmluZGV4T2YoZGF0YS5hcHBsaWNhdGlvbi5pZCkgIT0gLTEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnRmFjZWJvb2sgYXBwIGlkIGZvciBBY2NvdW50IEtpdCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJyk7XG4gICAgfSlcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSwgb3B0aW9ucykge1xuICByZXR1cm4gZ3JhcGhSZXF1ZXN0KGdldFJlcXVlc3RQYXRoKGF1dGhEYXRhLCBvcHRpb25zKSlcbiAgICAudGhlbihkYXRhID0+IHtcbiAgICAgIGlmIChkYXRhICYmIGRhdGEuaWQgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnRmFjZWJvb2sgQWNjb3VudCBLaXQgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJyk7XG4gICAgfSlcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGFcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/github.js b/lib/Adapters/Auth/github.js index e727313fc7..ecfd8ceef9 100644 --- a/lib/Adapters/Auth/github.js +++ b/lib/Adapters/Auth/github.js @@ -51,4 +51,5 @@ function request(path, access_token) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dpdGh1Yi5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJQYXJzZSIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsInJlcXVlc3QiLCJhY2Nlc3NfdG9rZW4iLCJ0aGVuIiwiZGF0YSIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsInJlamVjdCIsImdldCIsImhvc3QiLCJoZWFkZXJzIiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsImUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsUUFBUUMsUUFBUSxPQUFSLENBQVo7QUFDQSxJQUFJQyxRQUFRRCxRQUFRLFlBQVIsRUFBc0JDLEtBQWxDOztBQUVBO0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DO0FBQ2xDLFNBQU9DLFFBQVEsTUFBUixFQUFnQkQsU0FBU0UsWUFBekIsRUFDSkMsSUFESSxDQUNFQyxJQUFELElBQVU7QUFDZCxRQUFJQSxRQUFRQSxLQUFLQyxFQUFMLElBQVdMLFNBQVNLLEVBQWhDLEVBQW9DO0FBQ2xDO0FBQ0Q7QUFDRCxVQUFNLElBQUlQLE1BQU1RLEtBQVYsQ0FDSlIsTUFBTVEsS0FBTixDQUFZQyxnQkFEUixFQUVKLHVDQUZJLENBQU47QUFHRCxHQVJJLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTVCxPQUFULENBQWlCVSxJQUFqQixFQUF1QlQsWUFBdkIsRUFBcUM7QUFDbkMsU0FBTyxJQUFJTyxPQUFKLENBQVksVUFBU0MsT0FBVCxFQUFrQkUsTUFBbEIsRUFBMEI7QUFDM0NoQixVQUFNaUIsR0FBTixDQUFVO0FBQ1JDLFlBQU0sZ0JBREU7QUFFUkgsWUFBTSxNQUFNQSxJQUZKO0FBR1JJLGVBQVM7QUFDUCx5QkFBaUIsWUFBWWIsWUFEdEI7QUFFUCxzQkFBYztBQUZQO0FBSEQsS0FBVixFQU9HLFVBQVNjLEdBQVQsRUFBYztBQUNmLFVBQUlaLE9BQU8sRUFBWDtBQUNBWSxVQUFJQyxFQUFKLENBQU8sTUFBUCxFQUFlLFVBQVNDLEtBQVQsRUFBZ0I7QUFDN0JkLGdCQUFRYyxLQUFSO0FBQ0QsT0FGRDtBQUdBRixVQUFJQyxFQUFKLENBQU8sS0FBUCxFQUFjLFlBQVc7QUFDdkIsWUFBSTtBQUNGYixpQkFBT2UsS0FBS0MsS0FBTCxDQUFXaEIsSUFBWCxDQUFQO0FBQ0QsU0FGRCxDQUVFLE9BQU1pQixDQUFOLEVBQVM7QUFDVCxpQkFBT1QsT0FBT1MsQ0FBUCxDQUFQO0FBQ0Q7QUFDRFgsZ0JBQVFOLElBQVI7QUFDRCxPQVBEO0FBUUQsS0FwQkQsRUFvQkdhLEVBcEJILENBb0JNLE9BcEJOLEVBb0JlLFlBQVc7QUFDeEJMLGFBQU8sbURBQVA7QUFDRCxLQXRCRDtBQXVCRCxHQXhCTSxDQUFQO0FBeUJEOztBQUVEVSxPQUFPQyxPQUFQLEdBQWlCO0FBQ2ZmLGlCQUFlQSxhQURBO0FBRWZULG9CQUFrQkE7QUFGSCxDQUFqQiIsImZpbGUiOiJnaXRodWIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIGdpdGh1YiBBUEkuXG52YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIHJldHVybiByZXF1ZXN0KCd1c2VyJywgYXV0aERhdGEuYWNjZXNzX3Rva2VuKVxuICAgIC50aGVuKChkYXRhKSA9PiB7XG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLmlkID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ0dpdGh1YiBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgYXBpIHJlcXVlc3RzXG5mdW5jdGlvbiByZXF1ZXN0KHBhdGgsIGFjY2Vzc190b2tlbikge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgaHR0cHMuZ2V0KHtcbiAgICAgIGhvc3Q6ICdhcGkuZ2l0aHViLmNvbScsXG4gICAgICBwYXRoOiAnLycgKyBwYXRoLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6ICdiZWFyZXIgJyArIGFjY2Vzc190b2tlbixcbiAgICAgICAgJ1VzZXItQWdlbnQnOiAncGFyc2Utc2VydmVyJ1xuICAgICAgfVxuICAgIH0sIGZ1bmN0aW9uKHJlcykge1xuICAgICAgdmFyIGRhdGEgPSAnJztcbiAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uKGNodW5rKSB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgIH0pO1xuICAgIH0pLm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgcmVqZWN0KCdGYWlsZWQgdG8gdmFsaWRhdGUgdGhpcyBhY2Nlc3MgdG9rZW4gd2l0aCBHaXRodWIuJyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YVxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/google.js b/lib/Adapters/Auth/google.js index 898eeeffdb..32ace595e5 100644 --- a/lib/Adapters/Auth/google.js +++ b/lib/Adapters/Auth/google.js @@ -67,4 +67,5 @@ function request(path) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dvb2dsZS5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJQYXJzZSIsInZhbGlkYXRlSWRUb2tlbiIsImlkIiwidG9rZW4iLCJyZXF1ZXN0IiwidGhlbiIsInJlc3BvbnNlIiwic3ViIiwidXNlcl9pZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXV0aFRva2VuIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwiaWRfdG9rZW4iLCJhY2Nlc3NfdG9rZW4iLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJwYXRoIiwicmVqZWN0IiwiZ2V0IiwicmVzIiwiZGF0YSIsIm9uIiwiY2h1bmsiLCJKU09OIiwicGFyc2UiLCJlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLFFBQVFDLFFBQVEsT0FBUixDQUFaO0FBQ0EsSUFBSUMsUUFBUUQsUUFBUSxZQUFSLEVBQXNCQyxLQUFsQzs7QUFFQSxTQUFTQyxlQUFULENBQXlCQyxFQUF6QixFQUE2QkMsS0FBN0IsRUFBb0M7QUFDbEMsU0FBT0MsUUFBUSx3QkFBd0JELEtBQWhDLEVBQ0pFLElBREksQ0FDRUMsUUFBRCxJQUFjO0FBQ2xCLFFBQUlBLGFBQWFBLFNBQVNDLEdBQVQsSUFBZ0JMLEVBQWhCLElBQXNCSSxTQUFTRSxPQUFULElBQW9CTixFQUF2RCxDQUFKLEVBQWdFO0FBQzlEO0FBQ0Q7QUFDRCxVQUFNLElBQUlGLE1BQU1TLEtBQVYsQ0FDSlQsTUFBTVMsS0FBTixDQUFZQyxnQkFEUixFQUVKLHVDQUZJLENBQU47QUFHRCxHQVJJLENBQVA7QUFTRDs7QUFFRCxTQUFTQyxpQkFBVCxDQUEyQlQsRUFBM0IsRUFBK0JDLEtBQS9CLEVBQXNDO0FBQ3BDLFNBQU9DLFFBQVEsNEJBQTRCRCxLQUFwQyxFQUNKRSxJQURJLENBQ0VDLFFBQUQsSUFBYztBQUNsQixRQUFJQSxhQUFjQSxTQUFTQyxHQUFULElBQWdCTCxFQUFoQixJQUFzQkksU0FBU0UsT0FBVCxJQUFvQk4sRUFBeEQsQ0FBSixFQUFpRTtBQUMvRDtBQUNEO0FBQ0QsVUFBTSxJQUFJRixNQUFNUyxLQUFWLENBQ0pULE1BQU1TLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix1Q0FGSSxDQUFOO0FBR0QsR0FSSSxDQUFQO0FBU0Q7O0FBRUQ7QUFDQSxTQUFTRSxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsTUFBSUEsU0FBU0MsUUFBYixFQUF1QjtBQUNyQixXQUFPYixnQkFBZ0JZLFNBQVNYLEVBQXpCLEVBQTZCVyxTQUFTQyxRQUF0QyxDQUFQO0FBQ0QsR0FGRCxNQUVPO0FBQ0wsV0FBT0gsa0JBQWtCRSxTQUFTWCxFQUEzQixFQUErQlcsU0FBU0UsWUFBeEMsRUFBc0RWLElBQXRELENBQTJELE1BQU07QUFDdEU7QUFDQTtBQUNELEtBSE0sRUFHSixNQUFNO0FBQ1A7QUFDQSxhQUFPSixnQkFBZ0JZLFNBQVNYLEVBQXpCLEVBQTZCVyxTQUFTRSxZQUF0QyxDQUFQO0FBQ0QsS0FOTSxDQUFQO0FBT0Q7QUFDRjs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTZCxPQUFULENBQWlCZSxJQUFqQixFQUF1QjtBQUNyQixTQUFPLElBQUlGLE9BQUosQ0FBWSxVQUFTQyxPQUFULEVBQWtCRSxNQUFsQixFQUEwQjtBQUMzQ3RCLFVBQU11QixHQUFOLENBQVUsMENBQTBDRixJQUFwRCxFQUEwRCxVQUFTRyxHQUFULEVBQWM7QUFDdEUsVUFBSUMsT0FBTyxFQUFYO0FBQ0FELFVBQUlFLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBU0MsS0FBVCxFQUFnQjtBQUM3QkYsZ0JBQVFFLEtBQVI7QUFDRCxPQUZEO0FBR0FILFVBQUlFLEVBQUosQ0FBTyxLQUFQLEVBQWMsWUFBVztBQUN2QixZQUFJO0FBQ0ZELGlCQUFPRyxLQUFLQyxLQUFMLENBQVdKLElBQVgsQ0FBUDtBQUNELFNBRkQsQ0FFRSxPQUFNSyxDQUFOLEVBQVM7QUFDVCxpQkFBT1IsT0FBT1EsQ0FBUCxDQUFQO0FBQ0Q7QUFDRFYsZ0JBQVFLLElBQVI7QUFDRCxPQVBEO0FBUUQsS0FiRCxFQWFHQyxFQWJILENBYU0sT0FiTixFQWFlLFlBQVc7QUFDeEJKLGFBQU8sbURBQVA7QUFDRCxLQWZEO0FBZ0JELEdBakJNLENBQVA7QUFrQkQ7O0FBRURTLE9BQU9DLE9BQVAsR0FBaUI7QUFDZmQsaUJBQWVBLGFBREE7QUFFZkosb0JBQWtCQTtBQUZILENBQWpCIiwiZmlsZSI6Imdvb2dsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgZ29vZ2xlIEFQSS5cbnZhciBodHRwcyA9IHJlcXVpcmUoJ2h0dHBzJyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbmZ1bmN0aW9uIHZhbGlkYXRlSWRUb2tlbihpZCwgdG9rZW4pIHtcbiAgcmV0dXJuIHJlcXVlc3QoXCJ0b2tlbmluZm8/aWRfdG9rZW49XCIgKyB0b2tlbilcbiAgICAudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgIGlmIChyZXNwb25zZSAmJiAocmVzcG9uc2Uuc3ViID09IGlkIHx8IHJlc3BvbnNlLnVzZXJfaWQgPT0gaWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ0dvb2dsZSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoVG9rZW4oaWQsIHRva2VuKSB7XG4gIHJldHVybiByZXF1ZXN0KFwidG9rZW5pbmZvP2FjY2Vzc190b2tlbj1cIiArIHRva2VuKVxuICAgIC50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgaWYgKHJlc3BvbnNlICYmICAocmVzcG9uc2Uuc3ViID09IGlkIHx8IHJlc3BvbnNlLnVzZXJfaWQgPT0gaWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ0dvb2dsZSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIGlmIChhdXRoRGF0YS5pZF90b2tlbikge1xuICAgIHJldHVybiB2YWxpZGF0ZUlkVG9rZW4oYXV0aERhdGEuaWQsIGF1dGhEYXRhLmlkX3Rva2VuKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdmFsaWRhdGVBdXRoVG9rZW4oYXV0aERhdGEuaWQsIGF1dGhEYXRhLmFjY2Vzc190b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAvLyBWYWxpZGF0aW9uIHdpdGggYXV0aCB0b2tlbiB3b3JrZWRcbiAgICAgIHJldHVybjtcbiAgICB9LCAoKSA9PiB7XG4gICAgICAvLyBUcnkgd2l0aCB0aGUgaWRfdG9rZW4gcGFyYW1cbiAgICAgIHJldHVybiB2YWxpZGF0ZUlkVG9rZW4oYXV0aERhdGEuaWQsIGF1dGhEYXRhLmFjY2Vzc190b2tlbik7XG4gICAgfSk7XG4gIH1cbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIHJlcXVlc3QocGF0aCkge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgaHR0cHMuZ2V0KFwiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL1wiICsgcGF0aCwgZnVuY3Rpb24ocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgIH0pO1xuICAgICAgcmVzLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgfSk7XG4gICAgfSkub24oJ2Vycm9yJywgZnVuY3Rpb24oKSB7XG4gICAgICByZWplY3QoJ0ZhaWxlZCB0byB2YWxpZGF0ZSB0aGlzIGFjY2VzcyB0b2tlbiB3aXRoIEdvb2dsZS4nKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/index.js b/lib/Adapters/Auth/index.js index 59b1392463..1935d38a9f 100755 --- a/lib/Adapters/Auth/index.js +++ b/lib/Adapters/Auth/index.js @@ -119,4 +119,5 @@ module.exports = function (authOptions = {}, enableAnonymousUsers = true) { }); }; -module.exports.loadAuthAdapter = loadAuthAdapter; \ No newline at end of file +module.exports.loadAuthAdapter = loadAuthAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2luZGV4LmpzIl0sIm5hbWVzIjpbImZhY2Vib29rIiwicmVxdWlyZSIsImZhY2Vib29rYWNjb3VudGtpdCIsImluc3RhZ3JhbSIsImxpbmtlZGluIiwibWVldHVwIiwiZ29vZ2xlIiwiZ2l0aHViIiwidHdpdHRlciIsInNwb3RpZnkiLCJkaWdpdHMiLCJqYW5yYWluZW5nYWdlIiwiamFucmFpbmNhcHR1cmUiLCJ2a29udGFrdGUiLCJxcSIsIndlY2hhdCIsIndlaWJvIiwiYW5vbnltb3VzIiwidmFsaWRhdGVBdXRoRGF0YSIsIlByb21pc2UiLCJyZXNvbHZlIiwidmFsaWRhdGVBcHBJZCIsInByb3ZpZGVycyIsImF1dGhEYXRhVmFsaWRhdG9yIiwiYWRhcHRlciIsImFwcElkcyIsIm9wdGlvbnMiLCJhdXRoRGF0YSIsInRoZW4iLCJsb2FkQXV0aEFkYXB0ZXIiLCJwcm92aWRlciIsImF1dGhPcHRpb25zIiwiZGVmYXVsdEFkYXB0ZXIiLCJPYmplY3QiLCJhc3NpZ24iLCJwcm92aWRlck9wdGlvbnMiLCJ1bmRlZmluZWQiLCJvcHRpb25hbEFkYXB0ZXIiLCJmb3JFYWNoIiwia2V5IiwibW9kdWxlIiwiZXhwb3J0cyIsImVuYWJsZUFub255bW91c1VzZXJzIiwiX2VuYWJsZUFub255bW91c1VzZXJzIiwic2V0RW5hYmxlQW5vbnltb3VzVXNlcnMiLCJlbmFibGUiLCJnZXRWYWxpZGF0b3JGb3JQcm92aWRlciIsImZyZWV6ZSJdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7O0FBRUEsTUFBTUEsV0FBV0MsUUFBUSxZQUFSLENBQWpCO0FBQ0EsTUFBTUMscUJBQXFCRCxRQUFRLHNCQUFSLENBQTNCO0FBQ0EsTUFBTUUsWUFBWUYsUUFBUSxhQUFSLENBQWxCO0FBQ0EsTUFBTUcsV0FBV0gsUUFBUSxZQUFSLENBQWpCO0FBQ0EsTUFBTUksU0FBU0osUUFBUSxVQUFSLENBQWY7QUFDQSxNQUFNSyxTQUFTTCxRQUFRLFVB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QUFsRCxFQUF3RDtBQUN2RSxNQUFJQyx3QkFBd0JELG9CQUE1QjtBQUNBLFFBQU1FLDBCQUEwQixVQUFTQyxNQUFULEVBQWlCO0FBQy9DRiw0QkFBd0JFLE1BQXhCO0FBQ0QsR0FGRDtBQUdBO0FBQ0EsUUFBTUMsMEJBQTBCLFVBQVNoQixRQUFULEVBQW1COztBQUVqRCxRQUFJQSxhQUFhLFdBQWIsSUFBNEIsQ0FBQ2EscUJBQWpDLEVBQXdEO0FBQ3REO0FBQ0Q7O0FBRUQsVUFBTTtBQUNKbkIsYUFESTtBQUVKQyxZQUZJO0FBR0pVO0FBSEksUUFJRk4sZ0JBQWdCQyxRQUFoQixFQUEwQkMsV0FBMUIsQ0FKSjs7QUFNQSxXQUFPUixrQkFBa0JDLE9BQWxCLEVBQTJCQyxNQUEzQixFQUFtQ1UsZUFBbkMsQ0FBUDtBQUNELEdBYkQ7O0FBZUEsU0FBT0YsT0FBT2MsTUFBUCxDQUFjO0FBQ25CRCwyQkFEbUI7QUFFbkJGO0FBRm1CLEdBQWQsQ0FBUDtBQUlELENBekJEOztBQTJCQUosT0FBT0MsT0FBUCxDQUFlWixlQUFmLEdBQWlDQSxlQUFqQyIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBsb2FkQWRhcHRlciBmcm9tICcuLi9BZGFwdGVyTG9hZGVyJztcblxuY29uc3QgZmFjZWJvb2sgPSByZXF1aXJlKCcuL2ZhY2Vib29rJyk7XG5jb25zdCBmYWNlYm9va2FjY291bnRraXQgPSByZXF1aXJlKCcuL2ZhY2Vib29rYWNjb3VudGtpdCcpO1xuY29uc3QgaW5zdGFncmFtID0gcmVxdWlyZShcIi4vaW5zdGFncmFtXCIpO1xuY29uc3QgbGlua2VkaW4gPSByZXF1aXJlKFwiLi9saW5rZWRpblwiKTtcbmNvbnN0IG1lZXR1cCA9IHJlcXVpcmUoXCIuL21lZXR1cFwiKTtcbmNvbnN0IGdvb2dsZSA9IHJlcXVpcmUoXCIuL2dvb2dsZVwiKTtcbmNvbnN0IGdpdGh1YiA9IHJlcXVpcmUoXCIuL2dpdGh1YlwiKTtcbmNvbnN0IHR3aXR0ZXIgPSByZXF1aXJlKFwiLi90d2l0dGVyXCIpO1xuY29uc3Qgc3BvdGlmeSA9IHJlcXVpcmUoXCIuL3Nwb3RpZnlcIik7XG5jb25zdCBkaWdpdHMgPSByZXF1aXJlKFwiLi90d2l0dGVyXCIpOyAvLyBkaWdpdHMgdG9rZW5zIGFyZSB2YWxpZGF0ZWQgYnkgdHdpdHRlclxuY29uc3QgamFucmFpbmVuZ2FnZSA9IHJlcXVpcmUoXCIuL2phbnJhaW5lbmdhZ2VcIik7XG5jb25zdCBqYW5yYWluY2FwdHVyZSA9IHJlcXVpcmUoXCIuL2phbnJhaW5jYXB0dXJlXCIpO1xuY29uc3QgdmtvbnRha3RlID0gcmVxdWlyZShcIi4vdmtvbnRha3RlXCIpO1xuY29uc3QgcXEgPSByZXF1aXJlKFwiLi9xcVwiKTtcbmNvbnN0IHdlY2hhdCA9IHJlcXVpcmUoXCIuL3dlY2hhdFwiKTtcbmNvbnN0IHdlaWJvID0gcmVxdWlyZShcIi4vd2VpYm9cIik7XG5cbmNvbnN0IGFub255bW91cyA9IHtcbiAgdmFsaWRhdGVBdXRoRGF0YTogKCkgPT4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfSxcbiAgdmFsaWRhdGVBcHBJZDogKCkgPT4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufVxuXG5jb25zdCBwcm92aWRlcnMgPSB7XG4gIGZhY2Vib29rLFxuICBmYWNlYm9va2FjY291bnRraXQsXG4gIGluc3RhZ3JhbSxcbiAgbGlua2VkaW4sXG4gIG1lZXR1cCxcbiAgZ29vZ2xlLFxuICBnaXRodWIsXG4gIHR3aXR0ZXIsXG4gIHNwb3RpZnksXG4gIGFub255bW91cyxcbiAgZGlnaXRzLFxuICBqYW5yYWluZW5nYWdlLFxuICBqYW5yYWluY2FwdHVyZSxcbiAgdmtvbnRha3RlLFxuICBxcSxcbiAgd2VjaGF0LFxuICB3ZWlib1xufVxuZnVuY3Rpb24gYXV0aERhdGFWYWxpZGF0b3IoYWRhcHRlciwgYXBwSWRzLCBvcHRpb25zKSB7XG4gIHJldHVybiBmdW5jdGlvbihhdXRoRGF0YSkge1xuICAgIHJldHVybiBhZGFwdGVyLnZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMpLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGFwcElkcykge1xuICAgICAgICByZXR1cm4gYWRhcHRlci52YWxpZGF0ZUFwcElkKGFwcElkcywgYXV0aERhdGEsIG9wdGlvbnMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGxvYWRBdXRoQWRhcHRlcihwcm92aWRlciwgYXV0aE9wdGlvbnMpIHtcbiAgY29uc3QgZGVmYXVsdEFkYXB0ZXIgPSBwcm92aWRlcnNbcHJvdmlkZXJdO1xuICBjb25zdCBhZGFwdGVyID0gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdEFkYXB0ZXIpO1xuICBjb25zdCBwcm92aWRlck9wdGlvbnMgPSBhdXRoT3B0aW9uc1twcm92aWRlcl07XG5cbiAgaWYgKCFkZWZhdWx0QWRhcHRlciAmJiAhcHJvdmlkZXJPcHRpb25zKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgYXBwSWRzID0gcHJvdmlkZXJPcHRpb25zID8gcHJvdmlkZXJPcHRpb25zLmFwcElkcyA6IHVuZGVmaW5lZDtcblxuICAvLyBUcnkgdGhlIGNvbmZpZ3VyYXRpb24gbWV0aG9kc1xuICBpZiAocHJvdmlkZXJPcHRpb25zKSB7XG4gICAgY29uc3Qgb3B0aW9uYWxBZGFwdGVyID0gbG9hZEFkYXB0ZXIocHJvdmlkZXJPcHRpb25zLCB1bmRlZmluZWQsIHByb3ZpZGVyT3B0aW9ucyk7XG4gICAgaWYgKG9wdGlvbmFsQWRhcHRlcikge1xuICAgICAgWyd2YWxpZGF0ZUF1dGhEYXRhJywgJ3ZhbGlkYXRlQXBwSWQnXS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgaWYgKG9wdGlvbmFsQWRhcHRlcltrZXldKSB7XG4gICAgICAgICAgYWRhcHRlcltrZXldID0gb3B0aW9uYWxBZGFwdGVyW2tleV07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGlmICghYWRhcHRlci52YWxpZGF0ZUF1dGhEYXRhIHx8ICFhZGFwdGVyLnZhbGlkYXRlQXBwSWQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICByZXR1cm4ge2FkYXB0ZXIsIGFwcElkcywgcHJvdmlkZXJPcHRpb25zfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihhdXRoT3B0aW9ucyA9IHt9LCBlbmFibGVBbm9ueW1vdXNVc2VycyA9IHRydWUpIHtcbiAgbGV0IF9lbmFibGVBbm9ueW1vdXNVc2VycyA9IGVuYWJsZUFub255bW91c1VzZXJzO1xuICBjb25zdCBzZXRFbmFibGVBbm9ueW1vdXNVc2VycyA9IGZ1bmN0aW9uKGVuYWJsZSkge1xuICAgIF9lbmFibGVBbm9ueW1vdXNVc2VycyA9IGVuYWJsZTtcbiAgfVxuICAvLyBUbyBoYW5kbGUgdGhlIHRlc3QgY2FzZXMgb24gY29uZmlndXJhdGlvblxuICBjb25zdCBnZXRWYWxpZGF0b3JGb3JQcm92aWRlciA9IGZ1bmN0aW9uKHByb3ZpZGVyKSB7XG5cbiAgICBpZiAocHJvdmlkZXIgPT09ICdhbm9ueW1vdXMnICYmICFfZW5hYmxlQW5vbnltb3VzVXNlcnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7XG4gICAgICBhZGFwdGVyLFxuICAgICAgYXBwSWRzLFxuICAgICAgcHJvdmlkZXJPcHRpb25zXG4gICAgfSA9IGxvYWRBdXRoQWRhcHRlcihwcm92aWRlciwgYXV0aE9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIGF1dGhEYXRhVmFsaWRhdG9yKGFkYXB0ZXIsIGFwcElkcywgcHJvdmlkZXJPcHRpb25zKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKHtcbiAgICBnZXRWYWxpZGF0b3JGb3JQcm92aWRlcixcbiAgICBzZXRFbmFibGVBbm9ueW1vdXNVc2Vyc1xuICB9KVxufVxuXG5tb2R1bGUuZXhwb3J0cy5sb2FkQXV0aEFkYXB0ZXIgPSBsb2FkQXV0aEFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/instagram.js b/lib/Adapters/Auth/instagram.js index 090bc168d9..266519da97 100644 --- a/lib/Adapters/Auth/instagram.js +++ b/lib/Adapters/Auth/instagram.js @@ -40,4 +40,5 @@ function request(path) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2luc3RhZ3JhbS5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJQYXJzZSIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsInJlcXVlc3QiLCJhY2Nlc3NfdG9rZW4iLCJ0aGVuIiwicmVzcG9uc2UiLCJkYXRhIiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJwYXRoIiwicmVqZWN0IiwiZ2V0IiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxRQUFRQyxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7O0FBRUE7QUFDQSxTQUFTQyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsU0FBT0MsUUFBUSw4QkFBOEJELFNBQVNFLFlBQS9DLEVBQ0pDLElBREksQ0FDRUMsUUFBRCxJQUFjO0FBQ2xCLFFBQUlBLFlBQVlBLFNBQVNDLElBQXJCLElBQTZCRCxTQUFTQyxJQUFULENBQWNDLEVBQWQsSUFBb0JOLFNBQVNNLEVBQTlELEVBQWtFO0FBQ2hFO0FBQ0Q7QUFDRCxVQUFNLElBQUlSLE1BQU1TLEtBQVYsQ0FDSlQsTUFBTVMsS0FBTixDQUFZQyxnQkFEUixFQUVKLDBDQUZJLENBQU47QUFHRCxHQVJJLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTVixPQUFULENBQWlCVyxJQUFqQixFQUF1QjtBQUNyQixTQUFPLElBQUlGLE9BQUosQ0FBWSxVQUFTQyxPQUFULEVBQWtCRSxNQUFsQixFQUEwQjtBQUMzQ2pCLFVBQU1rQixHQUFOLENBQVUsa0NBQWtDRixJQUE1QyxFQUFrRCxVQUFTRyxHQUFULEVBQWM7QUFDOUQsVUFBSVYsT0FBTyxFQUFYO0FBQ0FVLFVBQUlDLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBU0MsS0FBVCxFQUFnQjtBQUM3QlosZ0JBQVFZLEtBQVI7QUFDRCxPQUZEO0FBR0FGLFVBQUlDLEVBQUosQ0FBTyxLQUFQLEVBQWMsWUFBVztBQUN2QlgsZUFBT2EsS0FBS0MsS0FBTCxDQUFXZCxJQUFYLENBQVA7QUFDQU0sZ0JBQVFOLElBQVI7QUFDRCxPQUhEO0FBSUQsS0FURCxFQVNHVyxFQVRILENBU00sT0FUTixFQVNlLFlBQVc7QUFDeEJILGFBQU8sc0RBQVA7QUFDRCxLQVhEO0FBWUQsR0FiTSxDQUFQO0FBY0Q7O0FBRURPLE9BQU9DLE9BQVAsR0FBaUI7QUFDZlosaUJBQWVBLGFBREE7QUFFZlYsb0JBQWtCQTtBQUZILENBQWpCIiwiZmlsZSI6Imluc3RhZ3JhbS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgaW5zdGFncmFtIEFQSS5cbnZhciBodHRwcyA9IHJlcXVpcmUoJ2h0dHBzJyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoXCJ1c2Vycy9zZWxmLz9hY2Nlc3NfdG9rZW49XCIgKyBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pXG4gICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UuZGF0YSAmJiByZXNwb25zZS5kYXRhLmlkID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ0luc3RhZ3JhbSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgYXBpIHJlcXVlc3RzXG5mdW5jdGlvbiByZXF1ZXN0KHBhdGgpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGh0dHBzLmdldChcImh0dHBzOi8vYXBpLmluc3RhZ3JhbS5jb20vdjEvXCIgKyBwYXRoLCBmdW5jdGlvbihyZXMpIHtcbiAgICAgIHZhciBkYXRhID0gJyc7XG4gICAgICByZXMub24oJ2RhdGEnLCBmdW5jdGlvbihjaHVuaykge1xuICAgICAgICBkYXRhICs9IGNodW5rO1xuICAgICAgfSk7XG4gICAgICByZXMub24oJ2VuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgIH0pO1xuICAgIH0pLm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgcmVqZWN0KCdGYWlsZWQgdG8gdmFsaWRhdGUgdGhpcyBhY2Nlc3MgdG9rZW4gd2l0aCBJbnN0YWdyYW0uJyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YVxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/janraincapture.js b/lib/Adapters/Auth/janraincapture.js index bfab1a995c..5d897af342 100644 --- a/lib/Adapters/Auth/janraincapture.js +++ b/lib/Adapters/Auth/janraincapture.js @@ -52,4 +52,5 @@ function request(host, access_token) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2phbnJhaW5jYXB0dXJlLmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsIlBhcnNlIiwicXVlcnlzdHJpbmciLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJvcHRpb25zIiwicmVxdWVzdCIsImphbnJhaW5fY2FwdHVyZV9ob3N0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJzdGF0IiwicmVzdWx0IiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJob3N0IiwicXVlcnlfc3RyaW5nX2RhdGEiLCJzdHJpbmdpZnkiLCJyZWplY3QiLCJnZXQiLCJwYXRoIiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxRQUFRQyxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7QUFDQSxJQUFJQyxjQUFjRixRQUFRLGFBQVIsQ0FBbEI7O0FBRUE7QUFDQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQXBDLEVBQTZDO0FBQzNDLFNBQU9DLFFBQVFELFFBQVFFLG9CQUFoQixFQUFzQ0gsU0FBU0ksWUFBL0MsRUFDSkMsSUFESSxDQUNFQyxJQUFELElBQVU7QUFDZDtBQUNBO0FBQ0EsUUFBSUEsUUFBUUEsS0FBS0MsSUFBTCxJQUFhLElBQXJCLElBQTZCRCxLQUFLRSxNQUFMLElBQWVSLFNBQVNTLEVBQXpELEVBQTZEO0FBQzNEO0FBQ0Q7QUFDRCxVQUFNLElBQUlaLE1BQU1hLEtBQVYsQ0FBZ0JiLE1BQU1hLEtBQU4sQ0FBWUMsZ0JBQTVCLEVBQThDLGdEQUE5QyxDQUFOO0FBQ0QsR0FSSSxDQUFQO0FBU0Q7O0FBRUQ7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCO0FBQ0EsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTWixPQUFULENBQWlCYSxJQUFqQixFQUF1QlgsWUFBdkIsRUFBcUM7O0FBRW5DLE1BQUlZLG9CQUFvQmxCLFlBQVltQixTQUFaLENBQXNCO0FBQzVDLG9CQUFnQmIsWUFENEI7QUFFNUMsc0JBQWtCLE1BRjBCLENBRW5CO0FBRm1CLEdBQXRCLENBQXhCOztBQUtBLFNBQU8sSUFBSVMsT0FBSixDQUFZLFVBQVNDLE9BQVQsRUFBa0JJLE1BQWxCLEVBQTBCO0FBQzNDdkIsVUFBTXdCLEdBQU4sQ0FBVTtBQUNSSixZQUFNQSxJQURFO0FBRVJLLFlBQU0sYUFBYUo7QUFGWCxLQUFWLEVBR0csVUFBU0ssR0FBVCxFQUFjO0FBQ2YsVUFBSWYsT0FBTyxFQUFYO0FBQ0FlLFVBQUlDLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBU0MsS0FBVCxFQUFnQjtBQUM3QmpCLGdCQUFRaUIsS0FBUjtBQUNELE9BRkQ7QUFHQUYsVUFBSUMsRUFBSixDQUFPLEtBQVAsRUFBYyxZQUFZO0FBQ3hCUixnQkFBUVUsS0FBS0MsS0FBTCxDQUFXbkIsSUFBWCxDQUFSO0FBQ0QsT0FGRDtBQUdELEtBWEQsRUFXR2dCLEVBWEgsQ0FXTSxPQVhOLEVBV2UsWUFBVztBQUN4QkosYUFBTyw0REFBUDtBQUNELEtBYkQ7QUFjRCxHQWZNLENBQVA7QUFnQkQ7O0FBRURRLE9BQU9DLE9BQVAsR0FBaUI7QUFDZmYsaUJBQWVBLGFBREE7QUFFZmIsb0JBQWtCQTtBQUZILENBQWpCIiwiZmlsZSI6ImphbnJhaW5jYXB0dXJlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBKYW5yYWluIENhcHR1cmUgQVBJLlxudmFyIGh0dHBzID0gcmVxdWlyZSgnaHR0cHMnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbnZhciBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHJlcXVlc3Qob3B0aW9ucy5qYW5yYWluX2NhcHR1cmVfaG9zdCwgYXV0aERhdGEuYWNjZXNzX3Rva2VuKVxuICAgIC50aGVuKChkYXRhKSA9PiB7XG4gICAgICAvL3N1Y2Nlc3NmdWwgcmVzcG9uc2Ugd2lsbCBoYXZlIGEgXCJzdGF0XCIgKHN0YXR1cykgb2YgJ29rJyBhbmQgYSByZXN1bHQgbm9kZSB0aGF0IHN0b3JlcyB0aGUgdXVpZCwgYmVjYXVzZSB0aGF0J3MgYWxsIHdlIGFza2VkIGZvclxuICAgICAgLy9zZWU6IGh0dHBzOi8vZG9jcy5qYW5yYWluLmNvbS9hcGkvcmVnaXN0cmF0aW9uL2VudGl0eS8jZW50aXR5XG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLnN0YXQgPT0gJ29rJyAmJiBkYXRhLnJlc3VsdCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ0phbnJhaW4gY2FwdHVyZSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICAvL25vLW9wXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIHJlcXVlc3QoaG9zdCwgYWNjZXNzX3Rva2VuKSB7XG5cbiAgdmFyIHF1ZXJ5X3N0cmluZ19kYXRhID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHtcbiAgICAnYWNjZXNzX3Rva2VuJzogYWNjZXNzX3Rva2VuLFxuICAgICdhdHRyaWJ1dGVfbmFtZSc6ICd1dWlkJyAvLyB3ZSBvbmx5IG5lZWQgdG8gcHVsbCB0aGUgdXVpZCBmb3IgdGhpcyBhY2Nlc3MgdG9rZW4gdG8gbWFrZSBzdXJlIGl0IG1hdGNoZXNcbiAgfSk7XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGh0dHBzLmdldCh7XG4gICAgICBob3N0OiBob3N0LFxuICAgICAgcGF0aDogJy9lbnRpdHk/JyArIHF1ZXJ5X3N0cmluZ19kYXRhXG4gICAgfSwgZnVuY3Rpb24ocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgIH0pO1xuICAgICAgcmVzLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlc29sdmUoSlNPTi5wYXJzZShkYXRhKSk7XG4gICAgICB9KTtcbiAgICB9KS5vbignZXJyb3InLCBmdW5jdGlvbigpIHtcbiAgICAgIHJlamVjdCgnRmFpbGVkIHRvIHZhbGlkYXRlIHRoaXMgYWNjZXNzIHRva2VuIHdpdGggSmFucmFpbiBjYXB0dXJlLicpO1xuICAgIH0pO1xuICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGFcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/janrainengage.js b/lib/Adapters/Auth/janrainengage.js index c3936dfd63..8582e83699 100644 --- a/lib/Adapters/Auth/janrainengage.js +++ b/lib/Adapters/Auth/janrainengage.js @@ -70,4 +70,5 @@ function request(api_key, auth_token) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2phbnJhaW5lbmdhZ2UuanMiXSwibmFtZXMiOlsiaHR0cHMiLCJyZXF1aXJlIiwiUGFyc2UiLCJxdWVyeXN0cmluZyIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsIm9wdGlvbnMiLCJyZXF1ZXN0IiwiYXBpX2tleSIsImF1dGhfdG9rZW4iLCJ0aGVuIiwiZGF0YSIsInN0YXQiLCJwcm9maWxlIiwiaWRlbnRpZmllciIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicG9zdF9kYXRhIiwic3RyaW5naWZ5IiwicG9zdF9vcHRpb25zIiwiaG9zdCIsInBhdGgiLCJtZXRob2QiLCJoZWFkZXJzIiwibGVuZ3RoIiwicmVqZWN0IiwicG9zdF9yZXEiLCJyZXMiLCJzZXRFbmNvZGluZyIsIm9uIiwiZCIsIkpTT04iLCJwYXJzZSIsImUiLCJ3cml0ZSIsImVuZCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxRQUFRQyxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7QUFDQSxJQUFJQyxjQUFjRixRQUFRLGFBQVIsQ0FBbEI7O0FBRUE7QUFDQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQXBDLEVBQTZDO0FBQzNDLFNBQU9DLFFBQVFELFFBQVFFLE9BQWhCLEVBQXlCSCxTQUFTSSxVQUFsQyxFQUNKQyxJQURJLENBQ0VDLElBQUQsSUFBVTtBQUNkO0FBQ0E7QUFDQSxRQUFJQSxRQUFRQSxLQUFLQyxJQUFMLElBQWEsSUFBckIsSUFBNkJELEtBQUtFLE9BQUwsQ0FBYUMsVUFBYixJQUEyQlQsU0FBU1UsRUFBckUsRUFBeUU7QUFDdkU7QUFDRDtBQUNELFVBQU0sSUFBSWIsTUFBTWMsS0FBVixDQUFnQmQsTUFBTWMsS0FBTixDQUFZQyxnQkFBNUIsRUFBOEMsK0NBQTlDLENBQU47QUFDRCxHQVJJLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkI7QUFDQSxTQUFPQyxRQUFRQyxPQUFSLEVBQVA7QUFDRDs7QUFFRDtBQUNBLFNBQVNiLE9BQVQsQ0FBaUJDLE9BQWpCLEVBQTBCQyxVQUExQixFQUFzQzs7QUFFcEMsTUFBSVksWUFBWWxCLFlBQVltQixTQUFaLENBQXNCO0FBQ3BDLGFBQVNiLFVBRDJCO0FBRXBDLGNBQVVELE9BRjBCO0FBR3BDLGNBQVU7QUFIMEIsR0FBdEIsQ0FBaEI7O0FBTUEsTUFBSWUsZUFBZTtBQUNqQkMsVUFBTSxZQURXO0FBRWpCQyxVQUFNLG1CQUZXO0FBR2pCQyxZQUFRLE1BSFM7QUFJakJDLGFBQVM7QUFDUCxzQkFBZ0IsbUNBRFQ7QUFFUCx3QkFBa0JOLFVBQVVPO0FBRnJCO0FBSlEsR0FBbkI7O0FBVUEsU0FBTyxJQUFJVCxPQUFKLENBQVksVUFBVUMsT0FBVixFQUFtQlMsTUFBbkIsRUFBMkI7QUFDNUM7QUFDQSxRQUFJQyxXQUFXOUIsTUFBTU8sT0FBTixDQUFjZ0IsWUFBZCxFQUE0QixVQUFVUSxHQUFWLEVBQWU7QUFDeEQsVUFBSXBCLE9BQU8sRUFBWDtBQUNBb0IsVUFBSUMsV0FBSixDQUFnQixNQUFoQjtBQUNBO0FBQ0FELFVBQUlFLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBVUMsQ0FBVixFQUFhO0FBQzFCdkIsZ0JBQVF1QixDQUFSO0FBQ0QsT0FGRDtBQUdBO0FBQ0FILFVBQUlFLEVBQUosQ0FBTyxLQUFQLEVBQWMsWUFBWTtBQUN4QixZQUFJO0FBQ0Z0QixpQkFBT3dCLEtBQUtDLEtBQUwsQ0FBV3pCLElBQVgsQ0FBUDtBQUNELFNBRkQsQ0FFRSxPQUFNMEIsQ0FBTixFQUFTO0FBQ1QsaUJBQU9SLE9BQU9RLENBQVAsQ0FBUDtBQUNEO0FBQ0RqQixnQkFBUVQsSUFBUjtBQUNELE9BUEQ7QUFRRCxLQWhCYyxDQUFmOztBQWtCQW1CLGFBQVNRLEtBQVQsQ0FBZWpCLFNBQWY7QUFDQVMsYUFBU1MsR0FBVDtBQUNELEdBdEJNLENBQVA7QUF1QkQ7O0FBRURDLE9BQU9DLE9BQVAsR0FBaUI7QUFDZnZCLGlCQUFlQSxhQURBO0FBRWZkLG9CQUFrQkE7QUFGSCxDQUFqQiIsImZpbGUiOiJqYW5yYWluZW5nYWdlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBKYW5yYWluIEVuZ2FnZSBBUEkuXG52YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xudmFyIHF1ZXJ5c3RyaW5nID0gcmVxdWlyZSgncXVlcnlzdHJpbmcnKTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyB1c2VyIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSwgb3B0aW9ucykge1xuICByZXR1cm4gcmVxdWVzdChvcHRpb25zLmFwaV9rZXksIGF1dGhEYXRhLmF1dGhfdG9rZW4pXG4gICAgLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgIC8vc3VjY2Vzc2Z1bCByZXNwb25zZSB3aWxsIGhhdmUgYSBcInN0YXRcIiAoc3RhdHVzKSBvZiAnb2snIGFuZCBhIHByb2ZpbGUgbm9kZSB3aXRoIGFuIGlkZW50aWZpZXJcbiAgICAgIC8vc2VlOiBodHRwOi8vZGV2ZWxvcGVycy5qYW5yYWluLmNvbS9vdmVydmlldy9zb2NpYWwtbG9naW4vaWRlbnRpdHktcHJvdmlkZXJzL3VzZXItcHJvZmlsZS1kYXRhLyNub3JtYWxpemVkLXVzZXItcHJvZmlsZS1kYXRhXG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLnN0YXQgPT0gJ29rJyAmJiBkYXRhLnByb2ZpbGUuaWRlbnRpZmllciA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ0phbnJhaW4gZW5nYWdlIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLicpO1xuICAgIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIC8vbm8tb3BcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChhcGlfa2V5LCBhdXRoX3Rva2VuKSB7XG5cbiAgdmFyIHBvc3RfZGF0YSA9IHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeSh7XG4gICAgJ3Rva2VuJzogYXV0aF90b2tlbixcbiAgICAnYXBpS2V5JzogYXBpX2tleSxcbiAgICAnZm9ybWF0JzogJ2pzb24nXG4gIH0pO1xuXG4gIHZhciBwb3N0X29wdGlvbnMgPSB7XG4gICAgaG9zdDogJ3JweG5vdy5jb20nLFxuICAgIHBhdGg6ICcvYXBpL3YyL2F1dGhfaW5mbycsXG4gICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAgICAgJ0NvbnRlbnQtTGVuZ3RoJzogcG9zdF9kYXRhLmxlbmd0aFxuICAgIH1cbiAgfTtcblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIC8vIENyZWF0ZSB0aGUgcG9zdCByZXF1ZXN0LlxuICAgIHZhciBwb3N0X3JlcSA9IGh0dHBzLnJlcXVlc3QocG9zdF9vcHRpb25zLCBmdW5jdGlvbiAocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLnNldEVuY29kaW5nKCd1dGY4Jyk7XG4gICAgICAvLyBBcHBlbmQgZGF0YSBhcyB3ZSByZWNlaXZlIGl0IGZyb20gdGhlIEphbnJhaW4gZW5nYWdlIHNlcnZlci5cbiAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uIChkKSB7XG4gICAgICAgIGRhdGEgKz0gZDtcbiAgICAgIH0pO1xuICAgICAgLy8gT25jZSB3ZSBoYXZlIGFsbCB0aGUgZGF0YSwgd2UgY2FuIHBhcnNlIGl0IGFuZCByZXR1cm4gdGhlIGRhdGEgd2Ugd2FudC5cbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHBvc3RfcmVxLndyaXRlKHBvc3RfZGF0YSk7XG4gICAgcG9zdF9yZXEuZW5kKCk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YVxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/linkedin.js b/lib/Adapters/Auth/linkedin.js index 702de7081b..943a6a659e 100644 --- a/lib/Adapters/Auth/linkedin.js +++ b/lib/Adapters/Auth/linkedin.js @@ -57,4 +57,5 @@ function request(path, access_token, is_mobile_sdk) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2xpbmtlZGluLmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsIlBhcnNlIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwicmVxdWVzdCIsImFjY2Vzc190b2tlbiIsImlzX21vYmlsZV9zZGsiLCJ0aGVuIiwiZGF0YSIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsImhlYWRlcnMiLCJyZWplY3QiLCJnZXQiLCJob3N0IiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsImUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsUUFBUUMsUUFBUSxPQUFSLENBQVo7QUFDQSxJQUFJQyxRQUFRRCxRQUFRLFlBQVIsRUFBc0JDLEtBQWxDOztBQUVBO0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DO0FBQ2xDLFNBQU9DLFFBQVEsZUFBUixFQUF5QkQsU0FBU0UsWUFBbEMsRUFBZ0RGLFNBQVNHLGFBQXpELEVBQ0pDLElBREksQ0FDRUMsSUFBRCxJQUFVO0FBQ2QsUUFBSUEsUUFBUUEsS0FBS0MsRUFBTCxJQUFXTixTQUFTTSxFQUFoQyxFQUFvQztBQUNsQztBQUNEO0FBQ0QsVUFBTSxJQUFJUixNQUFNUyxLQUFWLENBQ0pULE1BQU1TLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix5Q0FGSSxDQUFOO0FBR0QsR0FSSSxDQUFQO0FBU0Q7O0FBRUQ7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLFFBQVFDLE9BQVIsRUFBUDtBQUNEOztBQUVEO0FBQ0EsU0FBU1YsT0FBVCxDQUFpQlcsSUFBakIsRUFBdUJWLFlBQXZCLEVBQXFDQyxhQUFyQyxFQUFvRDtBQUNsRCxNQUFJVSxVQUFVO0FBQ1oscUJBQWlCLFlBQVlYLFlBRGpCO0FBRVosbUJBQWU7QUFGSCxHQUFkOztBQUtBLE1BQUdDLGFBQUgsRUFBa0I7QUFDaEJVLFlBQVEsVUFBUixJQUFzQixNQUF0QjtBQUNEOztBQUVELFNBQU8sSUFBSUgsT0FBSixDQUFZLFVBQVNDLE9BQVQsRUFBa0JHLE1BQWxCLEVBQTBCO0FBQzNDbEIsVUFBTW1CLEdBQU4sQ0FBVTtBQUNSQyxZQUFNLGtCQURFO0FBRVJKLFlBQU0sU0FBU0EsSUFGUDtBQUdSQyxlQUFTQTtBQUhELEtBQVYsRUFJRyxVQUFTSSxHQUFULEVBQWM7QUFDZixVQUFJWixPQUFPLEVBQVg7QUFDQVksVUFBSUMsRUFBSixDQUFPLE1BQVAsRUFBZSxVQUFTQyxLQUFULEVBQWdCO0FBQzdCZCxnQkFBUWMsS0FBUjtBQUNELE9BRkQ7QUFHQUYsVUFBSUMsRUFBSixDQUFPLEtBQVAsRUFBYyxZQUFXO0FBQ3ZCLFlBQUk7QUFDRmIsaUJBQU9lLEtBQUtDLEtBQUwsQ0FBV2hCLElBQVgsQ0FBUDtBQUNELFNBRkQsQ0FFRSxPQUFNaUIsQ0FBTixFQUFTO0FBQ1QsaUJBQU9SLE9BQU9RLENBQVAsQ0FBUDtBQUNEO0FBQ0RYLGdCQUFRTixJQUFSO0FBQ0QsT0FQRDtBQVFELEtBakJELEVBaUJHYSxFQWpCSCxDQWlCTSxPQWpCTixFQWlCZSxZQUFXO0FBQ3hCSixhQUFPLHFEQUFQO0FBQ0QsS0FuQkQ7QUFvQkQsR0FyQk0sQ0FBUDtBQXNCRDs7QUFFRFMsT0FBT0MsT0FBUCxHQUFpQjtBQUNmZixpQkFBZUEsYUFEQTtBQUVmVixvQkFBa0JBO0FBRkgsQ0FBakIiLCJmaWxlIjoibGlua2VkaW4uanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIGxpbmtlZGluIEFQSS5cbnZhciBodHRwcyA9IHJlcXVpcmUoJ2h0dHBzJyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoJ3Blb3BsZS9+OihpZCknLCBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4sIGF1dGhEYXRhLmlzX21vYmlsZV9zZGspXG4gICAgLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgIGlmIChkYXRhICYmIGRhdGEuaWQgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnTGlua2VkaW4gYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJyk7XG4gICAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChwYXRoLCBhY2Nlc3NfdG9rZW4sIGlzX21vYmlsZV9zZGspIHtcbiAgdmFyIGhlYWRlcnMgPSB7XG4gICAgJ0F1dGhvcml6YXRpb24nOiAnQmVhcmVyICcgKyBhY2Nlc3NfdG9rZW4sXG4gICAgJ3gtbGktZm9ybWF0JzogJ2pzb24nLFxuICB9XG5cbiAgaWYoaXNfbW9iaWxlX3Nkaykge1xuICAgIGhlYWRlcnNbJ3gtbGktc3JjJ10gPSAnbXNkayc7XG4gIH1cblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgaHR0cHMuZ2V0KHtcbiAgICAgIGhvc3Q6ICdhcGkubGlua2VkaW4uY29tJyxcbiAgICAgIHBhdGg6ICcvdjEvJyArIHBhdGgsXG4gICAgICBoZWFkZXJzOiBoZWFkZXJzXG4gICAgfSwgZnVuY3Rpb24ocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgIH0pO1xuICAgICAgcmVzLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgfSk7XG4gICAgfSkub24oJ2Vycm9yJywgZnVuY3Rpb24oKSB7XG4gICAgICByZWplY3QoJ0ZhaWxlZCB0byB2YWxpZGF0ZSB0aGlzIGFjY2VzcyB0b2tlbiB3aXRoIExpbmtlZGluLicpO1xuICAgIH0pO1xuICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGFcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/meetup.js b/lib/Adapters/Auth/meetup.js index 7a996510b5..33fd7f34e6 100644 --- a/lib/Adapters/Auth/meetup.js +++ b/lib/Adapters/Auth/meetup.js @@ -50,4 +50,5 @@ function request(path, access_token) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL21lZXR1cC5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJQYXJzZSIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsInJlcXVlc3QiLCJhY2Nlc3NfdG9rZW4iLCJ0aGVuIiwiZGF0YSIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsInJlamVjdCIsImdldCIsImhvc3QiLCJoZWFkZXJzIiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsImUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsUUFBUUMsUUFBUSxPQUFSLENBQVo7QUFDQSxJQUFJQyxRQUFRRCxRQUFRLFlBQVIsRUFBc0JDLEtBQWxDOztBQUVBO0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DO0FBQ2xDLFNBQU9DLFFBQVEsYUFBUixFQUF1QkQsU0FBU0UsWUFBaEMsRUFDSkMsSUFESSxDQUNFQyxJQUFELElBQVU7QUFDZCxRQUFJQSxRQUFRQSxLQUFLQyxFQUFMLElBQVdMLFNBQVNLLEVBQWhDLEVBQW9DO0FBQ2xDO0FBQ0Q7QUFDRCxVQUFNLElBQUlQLE1BQU1RLEtBQVYsQ0FDSlIsTUFBTVEsS0FBTixDQUFZQyxnQkFEUixFQUVKLHVDQUZJLENBQU47QUFHRCxHQVJJLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTVCxPQUFULENBQWlCVSxJQUFqQixFQUF1QlQsWUFBdkIsRUFBcUM7QUFDbkMsU0FBTyxJQUFJTyxPQUFKLENBQVksVUFBU0MsT0FBVCxFQUFrQkUsTUFBbEIsRUFBMEI7QUFDM0NoQixVQUFNaUIsR0FBTixDQUFVO0FBQ1JDLFlBQU0sZ0JBREU7QUFFUkgsWUFBTSxRQUFRQSxJQUZOO0FBR1JJLGVBQVM7QUFDUCx5QkFBaUIsWUFBWWI7QUFEdEI7QUFIRCxLQUFWLEVBTUcsVUFBU2MsR0FBVCxFQUFjO0FBQ2YsVUFBSVosT0FBTyxFQUFYO0FBQ0FZLFVBQUlDLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBU0MsS0FBVCxFQUFnQjtBQUM3QmQsZ0JBQVFjLEtBQVI7QUFDRCxPQUZEO0FBR0FGLFVBQUlDLEVBQUosQ0FBTyxLQUFQLEVBQWMsWUFBVztBQUN2QixZQUFJO0FBQ0ZiLGlCQUFPZSxLQUFLQyxLQUFMLENBQVdoQixJQUFYLENBQVA7QUFDRCxTQUZELENBRUUsT0FBTWlCLENBQU4sRUFBUztBQUNULGlCQUFPVCxPQUFPUyxDQUFQLENBQVA7QUFDRDtBQUNEWCxnQkFBUU4sSUFBUjtBQUNELE9BUEQ7QUFRRCxLQW5CRCxFQW1CR2EsRUFuQkgsQ0FtQk0sT0FuQk4sRUFtQmUsWUFBVztBQUN4QkwsYUFBTyxtREFBUDtBQUNELEtBckJEO0FBc0JELEdBdkJNLENBQVA7QUF3QkQ7O0FBRURVLE9BQU9DLE9BQVAsR0FBaUI7QUFDZmYsaUJBQWVBLGFBREE7QUFFZlQsb0JBQWtCQTtBQUZILENBQWpCIiwiZmlsZSI6Im1lZXR1cC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgbWVldHVwIEFQSS5cbnZhciBodHRwcyA9IHJlcXVpcmUoJ2h0dHBzJyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIHJlcXVlc3QoJ21lbWJlci9zZWxmJywgYXV0aERhdGEuYWNjZXNzX3Rva2VuKVxuICAgIC50aGVuKChkYXRhKSA9PiB7XG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLmlkID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ01lZXR1cCBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgYXBpIHJlcXVlc3RzXG5mdW5jdGlvbiByZXF1ZXN0KHBhdGgsIGFjY2Vzc190b2tlbikge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgaHR0cHMuZ2V0KHtcbiAgICAgIGhvc3Q6ICdhcGkubWVldHVwLmNvbScsXG4gICAgICBwYXRoOiAnLzIvJyArIHBhdGgsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdBdXRob3JpemF0aW9uJzogJ2JlYXJlciAnICsgYWNjZXNzX3Rva2VuXG4gICAgICB9XG4gICAgfSwgZnVuY3Rpb24ocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgIH0pO1xuICAgICAgcmVzLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgfSk7XG4gICAgfSkub24oJ2Vycm9yJywgZnVuY3Rpb24oKSB7XG4gICAgICByZWplY3QoJ0ZhaWxlZCB0byB2YWxpZGF0ZSB0aGlzIGFjY2VzcyB0b2tlbiB3aXRoIE1lZXR1cC4nKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/qq.js b/lib/Adapters/Auth/qq.js index aa82ca6b62..a5de7424aa 100644 --- a/lib/Adapters/Auth/qq.js +++ b/lib/Adapters/Auth/qq.js @@ -50,4 +50,5 @@ function graphRequest(path) { module.exports = { validateAppId, validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3FxLmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsIlBhcnNlIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwiZ3JhcGhSZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJvcGVuaWQiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInBhdGgiLCJyZWplY3QiLCJnZXQiLCJyZXMiLCJvbiIsImNodW5rIiwic3RhclBvcyIsImluZGV4T2YiLCJlbmRQb3MiLCJzdWJzdHJpbmciLCJKU09OIiwicGFyc2UiLCJlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLFFBQVFDLFFBQVEsT0FBUixDQUFaO0FBQ0EsSUFBSUMsUUFBUUQsUUFBUSxZQUFSLEVBQXNCQyxLQUFsQzs7QUFFQTtBQUNBLFNBQVNDLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxhQUFhLHFCQUFxQkQsU0FBU0UsWUFBM0MsRUFBeURDLElBQXpELENBQThELFVBQVVDLElBQVYsRUFBZ0I7QUFDbkYsUUFBSUEsUUFBUUEsS0FBS0MsTUFBTCxJQUFlTCxTQUFTTSxFQUFwQyxFQUF3QztBQUN0QztBQUNEO0FBQ0QsVUFBTSxJQUFJUixNQUFNUyxLQUFWLENBQWdCVCxNQUFNUyxLQUFOLENBQVlDLGdCQUE1QixFQUE4QyxtQ0FBOUMsQ0FBTjtBQUNELEdBTE0sQ0FBUDtBQU1EOztBQUVEO0FBQ0EsU0FBU0MsYUFBVCxHQUF5QjtBQUN2QixTQUFPQyxRQUFRQyxPQUFSLEVBQVA7QUFDRDs7QUFFRDtBQUNBLFNBQVNWLFlBQVQsQ0FBc0JXLElBQXRCLEVBQTRCO0FBQzFCLFNBQU8sSUFBSUYsT0FBSixDQUFZLFVBQVVDLE9BQVYsRUFBbUJFLE1BQW5CLEVBQTJCO0FBQzVDakIsVUFBTWtCLEdBQU4sQ0FBVSxtQ0FBbUNGLElBQTdDLEVBQW1ELFVBQVVHLEdBQVYsRUFBZTtBQUNoRSxVQUFJWCxPQUFPLEVBQVg7QUFDQVcsVUFBSUMsRUFBSixDQUFPLE1BQVAsRUFBZSxVQUFVQyxLQUFWLEVBQWlCO0FBQzlCYixnQkFBUWEsS0FBUjtBQUNELE9BRkQ7QUFHQUYsVUFBSUMsRUFBSixDQUFPLEtBQVAsRUFBYyxZQUFZO0FBQ3hCLFlBQUlFLFVBQVVkLEtBQUtlLE9BQUwsQ0FBYSxHQUFiLENBQWQ7QUFDQSxZQUFJQyxTQUFTaEIsS0FBS2UsT0FBTCxDQUFhLEdBQWIsQ0FBYjtBQUNBLFlBQUdELFdBQVcsQ0FBQyxDQUFaLElBQWlCRSxVQUFVLENBQUMsQ0FBL0IsRUFBaUM7QUFDL0IsZ0JBQU0sSUFBSXRCLE1BQU1TLEtBQVYsQ0FBZ0JULE1BQU1TLEtBQU4sQ0FBWUMsZ0JBQTVCLEVBQThDLG1DQUE5QyxDQUFOO0FBQ0Q7QUFDREosZUFBT0EsS0FBS2lCLFNBQUwsQ0FBZUgsVUFBVSxDQUF6QixFQUEyQkUsU0FBUyxDQUFwQyxDQUFQO0FBQ0EsWUFBSTtBQUNGaEIsaUJBQU9rQixLQUFLQyxLQUFMLENBQVduQixJQUFYLENBQVA7QUFDRCxTQUZELENBRUUsT0FBTW9CLENBQU4sRUFBUztBQUNULGlCQUFPWCxPQUFPVyxDQUFQLENBQVA7QUFDRDtBQUNEYixnQkFBUVAsSUFBUjtBQUNELE9BYkQ7QUFjRCxLQW5CRCxFQW1CR1ksRUFuQkgsQ0FtQk0sT0FuQk4sRUFtQmUsWUFBWTtBQUN6QkgsYUFBTywrQ0FBUDtBQUNELEtBckJEO0FBc0JELEdBdkJNLENBQVA7QUF3QkQ7O0FBRURZLE9BQU9DLE9BQVAsR0FBaUI7QUFDZmpCLGVBRGU7QUFFZlY7QUFGZSxDQUFqQiIsImZpbGUiOiJxcS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgcXEgR3JhcGggQVBJLlxudmFyIGh0dHBzID0gcmVxdWlyZSgnaHR0cHMnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyB1c2VyIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSkge1xuICByZXR1cm4gZ3JhcGhSZXF1ZXN0KCdtZT9hY2Nlc3NfdG9rZW49JyArIGF1dGhEYXRhLmFjY2Vzc190b2tlbikudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuICAgIGlmIChkYXRhICYmIGRhdGEub3BlbmlkID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAncXEgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJyk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZCgpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIHFxIGdyYXBoIHJlcXVlc3RzLlxuZnVuY3Rpb24gZ3JhcGhSZXF1ZXN0KHBhdGgpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBodHRwcy5nZXQoJ2h0dHBzOi8vZ3JhcGgucXEuY29tL29hdXRoMi4wLycgKyBwYXRoLCBmdW5jdGlvbiAocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc3RhclBvcyA9IGRhdGEuaW5kZXhPZihcIihcIik7XG4gICAgICAgIHZhciBlbmRQb3MgPSBkYXRhLmluZGV4T2YoXCIpXCIpO1xuICAgICAgICBpZihzdGFyUG9zID09IC0xIHx8IGVuZFBvcyA9PSAtMSl7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdxcSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gZGF0YS5zdWJzdHJpbmcoc3RhclBvcyArIDEsZW5kUG9zIC0gMSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgIH0pO1xuICAgIH0pLm9uKCdlcnJvcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJlamVjdCgnRmFpbGVkIHRvIHZhbGlkYXRlIHRoaXMgYWNjZXNzIHRva2VuIHdpdGggcXEuJyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YVxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Auth/spotify.js b/lib/Adapters/Auth/spotify.js index f1d8f6da21..b102c58b84 100644 --- a/lib/Adapters/Auth/spotify.js +++ b/lib/Adapters/Auth/spotify.js @@ -59,4 +59,5 @@ function request(path, access_token) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3Nwb3RpZnkuanMiXSwibmFtZXMiOlsiaHR0cHMiLCJyZXF1aXJlIiwiUGFyc2UiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJyZXF1ZXN0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJhcHBJZHMiLCJsZW5ndGgiLCJpbmRleE9mIiwicGF0aCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZ2V0IiwiaG9zdCIsImhlYWRlcnMiLCJyZXMiLCJvbiIsImNodW5rIiwiSlNPTiIsInBhcnNlIiwiZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxRQUFRQyxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7O0FBRUE7QUFDQSxTQUFTQyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsU0FBT0MsUUFBUSxJQUFSLEVBQWNELFNBQVNFLFlBQXZCLEVBQ0pDLElBREksQ0FDRUMsSUFBRCxJQUFVO0FBQ2QsUUFBSUEsUUFBUUEsS0FBS0MsRUFBTCxJQUFXTCxTQUFTSyxFQUFoQyxFQUFvQztBQUNsQztBQUNEO0FBQ0QsVUFBTSxJQUFJUCxNQUFNUSxLQUFWLENBQ0pSLE1BQU1RLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix3Q0FGSSxDQUFOO0FBR0QsR0FSSSxDQUFQO0FBU0Q7O0FBRUQ7QUFDQSxTQUFTQyxhQUFULENBQXVCQyxNQUF2QixFQUErQlQsUUFBL0IsRUFBeUM7QUFDdkMsTUFBSUUsZUFBZUYsU0FBU0UsWUFBNUI7QUFDQSxNQUFJLENBQUNPLE9BQU9DLE1BQVosRUFBb0I7QUFDbEIsVUFBTSxJQUFJWixNQUFNUSxLQUFWLENBQ0pSLE1BQU1RLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSixpQ0FGSSxDQUFOO0FBR0Q7QUFDRCxTQUFPTixRQUFRLElBQVIsRUFBY0MsWUFBZCxFQUNKQyxJQURJLENBQ0VDLElBQUQsSUFBVTtBQUNkLFFBQUlBLFFBQVFLLE9BQU9FLE9BQVAsQ0FBZVAsS0FBS0MsRUFBcEIsS0FBMkIsQ0FBQyxDQUF4QyxFQUEyQztBQUN6QztBQUNEO0FBQ0QsVUFBTSxJQUFJUCxNQUFNUSxLQUFWLENBQ0pSLE1BQU1RLEtBQU4sQ0FBWUMsZ0JBRFIsRUFFSix3Q0FGSSxDQUFOO0FBR0QsR0FSSSxDQUFQO0FBU0Q7O0FBRUQ7QUFDQSxTQUFTTixPQUFULENBQWlCVyxJQUFqQixFQUF1QlYsWUFBdkIsRUFBcUM7QUFDbkMsU0FBTyxJQUFJVyxPQUFKLENBQVksVUFBU0MsT0FBVCxFQUFrQkMsTUFBbEIsRUFBMEI7QUFDM0NuQixVQUFNb0IsR0FBTixDQUFVO0FBQ1JDLFlBQU0saUJBREU7QUFFUkwsWUFBTSxTQUFTQSxJQUZQO0FBR1JNLGVBQVM7QUFDUCx5QkFBaUIsWUFBWWhCO0FBRHRCO0FBSEQsS0FBVixFQU1HLFVBQVNpQixHQUFULEVBQWM7QUFDZixVQUFJZixPQUFPLEVBQVg7QUFDQWUsVUFBSUMsRUFBSixDQUFPLE1BQVAsRUFBZSxVQUFTQyxLQUFULEVBQWdCO0FBQzdCakIsZ0JBQVFpQixLQUFSO0FBQ0QsT0FGRDtBQUdBRixVQUFJQyxFQUFKLENBQU8sS0FBUCxFQUFjLFlBQVc7QUFDdkIsWUFBSTtBQUNGaEIsaUJBQU9rQixLQUFLQyxLQUFMLENBQVduQixJQUFYLENBQVA7QUFDRCxTQUZELENBRUUsT0FBTW9CLENBQU4sRUFBUztBQUNULGlCQUFPVCxPQUFPUyxDQUFQLENBQVA7QUFDRDtBQUNEVixnQkFBUVYsSUFBUjtBQUNELE9BUEQ7QUFRRCxLQW5CRCxFQW1CR2dCLEVBbkJILENBbUJNLE9BbkJOLEVBbUJlLFlBQVc7QUFDeEJMLGFBQU8sb0RBQVA7QUFDRCxLQXJCRDtBQXNCRCxHQXZCTSxDQUFQO0FBd0JEOztBQUVEVSxPQUFPQyxPQUFQLEdBQWlCO0FBQ2ZsQixpQkFBZUEsYUFEQTtBQUVmVCxvQkFBa0JBO0FBRkgsQ0FBakIiLCJmaWxlIjoic3BvdGlmeS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgU3BvdGlmeSBBUEkuXG52YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIHJldHVybiByZXF1ZXN0KCdtZScsIGF1dGhEYXRhLmFjY2Vzc190b2tlbilcbiAgICAudGhlbigoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEgJiYgZGF0YS5pZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICdTcG90aWZ5IGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLicpO1xuICAgIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgYXBwIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBcHBJZChhcHBJZHMsIGF1dGhEYXRhKSB7XG4gIHZhciBhY2Nlc3NfdG9rZW4gPSBhdXRoRGF0YS5hY2Nlc3NfdG9rZW47XG4gIGlmICghYXBwSWRzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnU3BvdGlmeSBhdXRoIGlzIG5vdCBjb25maWd1cmVkLicpO1xuICB9XG4gIHJldHVybiByZXF1ZXN0KCdtZScsIGFjY2Vzc190b2tlbilcbiAgICAudGhlbigoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEgJiYgYXBwSWRzLmluZGV4T2YoZGF0YS5pZCkgIT0gLTEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAnU3BvdGlmeSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBTcG90aWZ5IEFQSSByZXF1ZXN0cy5cbmZ1bmN0aW9uIHJlcXVlc3QocGF0aCwgYWNjZXNzX3Rva2VuKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICBodHRwcy5nZXQoe1xuICAgICAgaG9zdDogJ2FwaS5zcG90aWZ5LmNvbScsXG4gICAgICBwYXRoOiAnL3YxLycgKyBwYXRoLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6ICdCZWFyZXIgJyArIGFjY2Vzc190b2tlblxuICAgICAgfVxuICAgIH0sIGZ1bmN0aW9uKHJlcykge1xuICAgICAgdmFyIGRhdGEgPSAnJztcbiAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uKGNodW5rKSB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgIH0pO1xuICAgIH0pLm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgcmVqZWN0KCdGYWlsZWQgdG8gdmFsaWRhdGUgdGhpcyBhY2Nlc3MgdG9rZW4gd2l0aCBTcG90aWZ5LicpO1xuICAgIH0pO1xuICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGFcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Auth/twitter.js b/lib/Adapters/Auth/twitter.js index 4f4560fedc..456fd342e1 100644 --- a/lib/Adapters/Auth/twitter.js +++ b/lib/Adapters/Auth/twitter.js @@ -53,4 +53,5 @@ module.exports = { validateAppId, validateAuthData, handleMultipleConfigurations -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3R3aXR0ZXIuanMiXSwibmFtZXMiOlsiT0F1dGgiLCJyZXF1aXJlIiwiUGFyc2UiLCJsb2dnZXIiLCJkZWZhdWx0IiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwib3B0aW9ucyIsIkVycm9yIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiaGFuZGxlTXVsdGlwbGVDb25maWd1cmF0aW9ucyIsImNsaWVudCIsImhvc3QiLCJhdXRoX3Rva2VuIiwiYXV0aF90b2tlbl9zZWNyZXQiLCJnZXQiLCJ0aGVuIiwiZGF0YSIsImlkX3N0ciIsImlkIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsIkFycmF5IiwiaXNBcnJheSIsImNvbnN1bWVyX2tleSIsImVycm9yIiwiZmlsdGVyIiwib3B0aW9uIiwibGVuZ3RoIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLFFBQVFDLFFBQVEsZ0JBQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7QUFDQSxJQUFJQyxTQUFTRixRQUFRLGNBQVIsRUFBd0JHLE9BQXJDOztBQUVBO0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DQyxPQUFwQyxFQUE2QztBQUMzQyxNQUFHLENBQUNBLE9BQUosRUFBYTtBQUNYLFVBQU0sSUFBSUwsTUFBTU0sS0FBVixDQUFnQk4sTUFBTU0sS0FBTixDQUFZQyxxQkFBNUIsRUFBbUQsb0NBQW5ELENBQU47QUFDRDtBQUNERixZQUFVRyw2QkFBNkJKLFFBQTdCLEVBQXVDQyxPQUF2QyxDQUFWO0FBQ0EsTUFBSUksU0FBUyxJQUFJWCxLQUFKLENBQVVPLE9BQVYsQ0FBYjtBQUNBSSxTQUFPQyxJQUFQLEdBQWMsaUJBQWQ7QUFDQUQsU0FBT0UsVUFBUCxHQUFvQlAsU0FBU08sVUFBN0I7QUFDQUYsU0FBT0csaUJBQVAsR0FBMkJSLFNBQVNRLGlCQUFwQzs7QUFFQSxTQUFPSCxPQUFPSSxHQUFQLENBQVcsc0NBQVgsRUFBbURDLElBQW5ELENBQXlEQyxJQUFELElBQVU7QUFDdkUsUUFBSUEsUUFBUUEsS0FBS0MsTUFBTCxJQUFlLEtBQUtaLFNBQVNhLEVBQXpDLEVBQTZDO0FBQzNDO0FBQ0Q7QUFDRCxVQUFNLElBQUlqQixNQUFNTSxLQUFWLENBQ0pOLE1BQU1NLEtBQU4sQ0FBWVksZ0JBRFIsRUFFSix3Q0FGSSxDQUFOO0FBR0QsR0FQTSxDQUFQO0FBUUQ7O0FBRUQ7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFNBQU9DLFFBQVFDLE9BQVIsRUFBUDtBQUNEOztBQUVELFNBQVNiLDRCQUFULENBQXNDSixRQUF0QyxFQUFnREMsT0FBaEQsRUFBeUQ7QUFDdkQsTUFBSWlCLE1BQU1DLE9BQU4sQ0FBY2xCLE9BQWQsQ0FBSixFQUE0QjtBQUMxQixVQUFNbUIsZUFBZXBCLFNBQVNvQixZQUE5QjtBQUNBLFFBQUksQ0FBQ0EsWUFBTCxFQUFtQjtBQUNqQnZCLGFBQU93QixLQUFQLENBQWEsY0FBYixFQUE2QiwyRkFBN0I7QUFDQSxZQUFNLElBQUl6QixNQUFNTSxLQUFWLENBQWdCTixNQUFNTSxLQUFOLENBQVlZLGdCQUE1QixFQUE4Qyx3Q0FBOUMsQ0FBTjtBQUNEO0FBQ0RiLGNBQVVBLFFBQVFxQixNQUFSLENBQWdCQyxNQUFELElBQVk7QUFDbkMsYUFBT0EsT0FBT0gsWUFBUCxJQUF1QkEsWUFBOUI7QUFDRCxLQUZTLENBQVY7O0FBSUEsUUFBSW5CLFFBQVF1QixNQUFSLElBQWtCLENBQXRCLEVBQXlCO0FBQ3ZCM0IsYUFBT3dCLEtBQVAsQ0FBYSxjQUFiLEVBQTRCLDJEQUE1QjtBQUNBLFlBQU0sSUFBSXpCLE1BQU1NLEtBQVYsQ0FBZ0JOLE1BQU1NLEtBQU4sQ0FBWVksZ0JBQTVCLEVBQThDLHdDQUE5QyxDQUFOO0FBQ0Q7QUFDRGIsY0FBVUEsUUFBUSxDQUFSLENBQVY7QUFDRDtBQUNELFNBQU9BLE9BQVA7QUFDRDs7QUFFRHdCLE9BQU9DLE9BQVAsR0FBaUI7QUFDZlgsZUFEZTtBQUVmaEIsa0JBRmU7QUFHZks7QUFIZSxDQUFqQiIsImZpbGUiOiJ0d2l0dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSB0d2l0dGVyIEFQSS5cbnZhciBPQXV0aCA9IHJlcXVpcmUoJy4vT0F1dGgxQ2xpZW50Jyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG52YXIgbG9nZ2VyID0gcmVxdWlyZSgnLi4vLi4vbG9nZ2VyJykuZGVmYXVsdDtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyB1c2VyIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSwgb3B0aW9ucykge1xuICBpZighb3B0aW9ucykge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsICdUd2l0dGVyIGF1dGggY29uZmlndXJhdGlvbiBtaXNzaW5nJyk7XG4gIH1cbiAgb3B0aW9ucyA9IGhhbmRsZU11bHRpcGxlQ29uZmlndXJhdGlvbnMoYXV0aERhdGEsIG9wdGlvbnMpO1xuICB2YXIgY2xpZW50ID0gbmV3IE9BdXRoKG9wdGlvbnMpO1xuICBjbGllbnQuaG9zdCA9IFwiYXBpLnR3aXR0ZXIuY29tXCI7XG4gIGNsaWVudC5hdXRoX3Rva2VuID0gYXV0aERhdGEuYXV0aF90b2tlbjtcbiAgY2xpZW50LmF1dGhfdG9rZW5fc2VjcmV0ID0gYXV0aERhdGEuYXV0aF90b2tlbl9zZWNyZXQ7XG5cbiAgcmV0dXJuIGNsaWVudC5nZXQoXCIvMS4xL2FjY291bnQvdmVyaWZ5X2NyZWRlbnRpYWxzLmpzb25cIikudGhlbigoZGF0YSkgPT4ge1xuICAgIGlmIChkYXRhICYmIGRhdGEuaWRfc3RyID09ICcnICsgYXV0aERhdGEuaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdUd2l0dGVyIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLicpO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU11bHRpcGxlQ29uZmlndXJhdGlvbnMoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHtcbiAgICBjb25zdCBjb25zdW1lcl9rZXkgPSBhdXRoRGF0YS5jb25zdW1lcl9rZXk7XG4gICAgaWYgKCFjb25zdW1lcl9rZXkpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignVHdpdHRlciBBdXRoJywgJ011bHRpcGxlIHR3aXR0ZXIgY29uZmlndXJhdGlvbnMgYXJlIGF2YWlsYWJsZSwgYnkgbm8gY29uc3VtZXJfa2V5IHdhcyBzZW50IGJ5IHRoZSBjbGllbnQuJyk7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ1R3aXR0ZXIgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJyk7XG4gICAgfVxuICAgIG9wdGlvbnMgPSBvcHRpb25zLmZpbHRlcigob3B0aW9uKSA9PiB7XG4gICAgICByZXR1cm4gb3B0aW9uLmNvbnN1bWVyX2tleSA9PSBjb25zdW1lcl9rZXk7XG4gICAgfSk7XG5cbiAgICBpZiAob3B0aW9ucy5sZW5ndGggPT0gMCkge1xuICAgICAgbG9nZ2VyLmVycm9yKCdUd2l0dGVyIEF1dGgnLCdDYW5ub3QgZmluZCBhIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBwcm92aWRlZCBjb25zdW1lcl9rZXknKTtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnVHdpdHRlciBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9XG4gICAgb3B0aW9ucyA9IG9wdGlvbnNbMF07XG4gIH1cbiAgcmV0dXJuIG9wdGlvbnM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhLFxuICBoYW5kbGVNdWx0aXBsZUNvbmZpZ3VyYXRpb25zXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/vkontakte.js b/lib/Adapters/Auth/vkontakte.js index 195a33f93b..9ef0fa1d5e 100644 --- a/lib/Adapters/Auth/vkontakte.js +++ b/lib/Adapters/Auth/vkontakte.js @@ -10,7 +10,7 @@ var logger = require('../../logger').default; function validateAuthData(authData, params) { return vkOAuth2Request(params).then(function (response) { if (response && response.access_token) { - return request("api.vk.com", "method/secure.checkToken?token=" + authData.access_token + "&client_secret=" + params.appSecret + "&access_token=" + response.access_token).then(function (response) { + return request("api.vk.com", "method/secure.checkToken?token=" + authData.access_token + "&client_secret=" + params.appSecret + "&access_token=" + response.access_token + "&v=5.59").then(function (response) { if (response && response.response && response.response.user_id == authData.id) { return; } @@ -64,4 +64,5 @@ function request(host, path) { module.exports = { validateAppId: validateAppId, validateAuthData: validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3Zrb250YWt0ZS5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJQYXJzZSIsImxvZ2dlciIsImRlZmF1bHQiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJwYXJhbXMiLCJ2a09BdXRoMlJlcXVlc3QiLCJ0aGVuIiwicmVzcG9uc2UiLCJhY2Nlc3NfdG9rZW4iLCJyZXF1ZXN0IiwiYXBwU2VjcmV0IiwidXNlcl9pZCIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiZXJyb3IiLCJQcm9taXNlIiwicmVzb2x2ZSIsImFwcElkcyIsImxlbmd0aCIsInZhbGlkYXRlQXBwSWQiLCJob3N0IiwicGF0aCIsInJlamVjdCIsImdldCIsInJlcyIsImRhdGEiLCJvbiIsImNodW5rIiwiSlNPTiIsInBhcnNlIiwiZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBOztBQUVBLElBQUlBLFFBQVFDLFFBQVEsT0FBUixDQUFaO0FBQ0EsSUFBSUMsUUFBUUQsUUFBUSxZQUFSLEVBQXNCQyxLQUFsQztBQUNBLElBQUlDLFNBQVNGLFFBQVEsY0FBUixFQUF3QkcsT0FBckM7O0FBRUE7QUFDQSxTQUFTQyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE1BQXBDLEVBQTRDO0FBQzFDLFNBQU9DLGdCQUFnQkQsTUFBaEIsRUFBd0JFLElBQXhCLENBQTZCLFVBQVVDLFFBQVYsRUFBb0I7QUFDdEQsUUFBSUEsWUFBWUEsU0FBU0MsWUFBekIsRUFBdUM7QUFDckMsYUFBT0MsUUFBUSxZQUFSLEVBQXNCLG9DQUFvQ04sU0FBU0ssWUFBN0MsR0FBNEQsaUJBQTVELEdBQWdGSixPQUFPTSxTQUF2RixHQUFtRyxnQkFBbkcsR0FBc0hILFNBQVNDLFlBQS9ILEdBQThJLFNBQXBLLEVBQStLRixJQUEvSyxDQUFvTCxVQUFVQyxRQUFWLEVBQW9CO0FBQzdNLFlBQUlBLFlBQVlBLFNBQVNBLFFBQXJCLElBQWlDQSxTQUFTQSxRQUFULENBQWtCSSxPQUFsQixJQUE2QlIsU0FBU1MsRUFBM0UsRUFBK0U7QUFDN0U7QUFDRDtBQUNELGNBQU0sSUFBSWIsTUFBTWMsS0FBVixDQUFnQmQsTUFBTWMsS0FBTixDQUFZQyxnQkFBNUIsRUFBOEMsbUNBQTlDLENBQU47QUFDRCxPQUxNLENBQVA7QUFNRDtBQUNEZCxXQUFPZSxLQUFQLENBQWEsU0FBYixFQUF3QixzQ0FBeEI7QUFDQSxVQUFNLElBQUloQixNQUFNYyxLQUFWLENBQWdCZCxNQUFNYyxLQUFOLENBQVlDLGdCQUE1QixFQUE4QyxzQ0FBOUMsQ0FBTjtBQUNELEdBWE0sQ0FBUDtBQVlEOztBQUVELFNBQVNULGVBQVQsQ0FBeUJELE1BQXpCLEVBQWlDO0FBQy9CLFNBQU8sSUFBSVksT0FBSixDQUFZLFVBQVVDLE9BQVYsRUFBbUI7QUFDcEMsUUFBSSxDQUFDYixNQUFELElBQVcsQ0FBQ0EsT0FBT2MsTUFBbkIsSUFBNkIsQ0FBQ2QsT0FBT2MsTUFBUCxDQUFjQyxNQUE1QyxJQUFzRCxDQUFDZixPQUFPTSxTQUE5RCxJQUEyRSxDQUFDTixPQUFPTSxTQUFQLENBQWlCUyxNQUFqRyxFQUF5RztBQUN2R25CLGFBQU9lLEtBQVAsQ0FBYSxTQUFiLEVBQXdCLHlEQUF4QjtBQUNBLFlBQU0sSUFBSWhCLE1BQU1jLEtBQVYsQ0FBZ0JkLE1BQU1jLEtBQU4sQ0FBWUMsZ0JBQTVCLEVBQThDLHlEQUE5QyxDQUFOO0FBQ0Q7QUFDREc7QUFDRCxHQU5NLEVBTUpYLElBTkksQ0FNQyxZQUFZO0FBQ2xCLFdBQU9HLFFBQVEsY0FBUixFQUF3Qiw0QkFBNEJMLE9BQU9jLE1BQW5DLEdBQTRDLGlCQUE1QyxHQUFnRWQsT0FBT00sU0FBdkUsR0FBbUYsdUNBQTNHLENBQVA7QUFDRCxHQVJNLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNVLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0osUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTUixPQUFULENBQWlCWSxJQUFqQixFQUF1QkMsSUFBdkIsRUFBNkI7QUFDM0IsU0FBTyxJQUFJTixPQUFKLENBQVksVUFBVUMsT0FBVixFQUFtQk0sTUFBbkIsRUFBMkI7QUFDNUMxQixVQUFNMkIsR0FBTixDQUFVLGFBQWFILElBQWIsR0FBb0IsR0FBcEIsR0FBMEJDLElBQXBDLEVBQTBDLFVBQVVHLEdBQVYsRUFBZTtBQUN2RCxVQUFJQyxPQUFPLEVBQVg7QUFDQUQsVUFBSUUsRUFBSixDQUFPLE1BQVAsRUFBZSxVQUFVQyxLQUFWLEVBQWlCO0FBQzlCRixnQkFBUUUsS0FBUjtBQUNELE9BRkQ7QUFHQUgsVUFBSUUsRUFBSixDQUFPLEtBQVAsRUFBYyxZQUFZO0FBQ3hCLFlBQUk7QUFDRkQsaUJBQU9HLEtBQUtDLEtBQUwsQ0FBV0osSUFBWCxDQUFQO0FBQ0QsU0FGRCxDQUVFLE9BQU1LLENBQU4sRUFBUztBQUNULGlCQUFPUixPQUFPUSxDQUFQLENBQVA7QUFDRDtBQUNEZCxnQkFBUVMsSUFBUjtBQUNELE9BUEQ7QUFRRCxLQWJELEVBYUdDLEVBYkgsQ0FhTSxPQWJOLEVBYWUsWUFBWTtBQUN6QkosYUFBTywrQ0FBUDtBQUNELEtBZkQ7QUFnQkQsR0FqQk0sQ0FBUDtBQWtCRDs7QUFFRFMsT0FBT0MsT0FBUCxHQUFpQjtBQUNmYixpQkFBZUEsYUFEQTtBQUVmbEIsb0JBQWtCQTtBQUZILENBQWpCIiwiZmlsZSI6InZrb250YWt0ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSB2a29udGFrdGUgQVBJLlxuXG52YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xudmFyIGxvZ2dlciA9IHJlcXVpcmUoJy4uLy4uL2xvZ2dlcicpLmRlZmF1bHQ7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIHBhcmFtcykge1xuICByZXR1cm4gdmtPQXV0aDJSZXF1ZXN0KHBhcmFtcykudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UuYWNjZXNzX3Rva2VuKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdChcImFwaS52ay5jb21cIiwgXCJtZXRob2Qvc2VjdXJlLmNoZWNrVG9rZW4/dG9rZW49XCIgKyBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4gKyBcIiZjbGllbnRfc2VjcmV0PVwiICsgcGFyYW1zLmFwcFNlY3JldCArIFwiJmFjY2Vzc190b2tlbj1cIiArIHJlc3BvbnNlLmFjY2Vzc190b2tlbiArIFwiJnY9NS41OVwiKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UucmVzcG9uc2UgJiYgcmVzcG9uc2UucmVzcG9uc2UudXNlcl9pZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ1ZrIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLicpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGxvZ2dlci5lcnJvcignVmsgQXV0aCcsICdWayBhcHBJZHMgb3IgYXBwU2VjcmV0IGlzIGluY29ycmVjdC4nKTtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ1ZrIGFwcElkcyBvciBhcHBTZWNyZXQgaXMgaW5jb3JyZWN0LicpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdmtPQXV0aDJSZXF1ZXN0KHBhcmFtcykge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHtcbiAgICBpZiAoIXBhcmFtcyB8fCAhcGFyYW1zLmFwcElkcyB8fCAhcGFyYW1zLmFwcElkcy5sZW5ndGggfHwgIXBhcmFtcy5hcHBTZWNyZXQgfHwgIXBhcmFtcy5hcHBTZWNyZXQubGVuZ3RoKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1ZrIEF1dGgnLCAnVmsgYXV0aCBpcyBub3QgY29uZmlndXJlZC4gTWlzc2luZyBhcHBJZHMgb3IgYXBwU2VjcmV0LicpO1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdWayBhdXRoIGlzIG5vdCBjb25maWd1cmVkLiBNaXNzaW5nIGFwcElkcyBvciBhcHBTZWNyZXQuJyk7XG4gICAgfVxuICAgIHJlc29sdmUoKTtcbiAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHJlcXVlc3QoXCJvYXV0aC52ay5jb21cIiwgXCJhY2Nlc3NfdG9rZW4/Y2xpZW50X2lkPVwiICsgcGFyYW1zLmFwcElkcyArIFwiJmNsaWVudF9zZWNyZXQ9XCIgKyBwYXJhbXMuYXBwU2VjcmV0ICsgXCImdj01LjU5JmdyYW50X3R5cGU9Y2xpZW50X2NyZWRlbnRpYWxzXCIpO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgYXBpIHJlcXVlc3RzXG5mdW5jdGlvbiByZXF1ZXN0KGhvc3QsIHBhdGgpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBodHRwcy5nZXQoXCJodHRwczovL1wiICsgaG9zdCArIFwiL1wiICsgcGF0aCwgZnVuY3Rpb24gKHJlcykge1xuICAgICAgdmFyIGRhdGEgPSAnJztcbiAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uIChjaHVuaykge1xuICAgICAgICBkYXRhICs9IGNodW5rO1xuICAgICAgfSk7XG4gICAgICByZXMub24oJ2VuZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgfSk7XG4gICAgfSkub24oJ2Vycm9yJywgZnVuY3Rpb24gKCkge1xuICAgICAgcmVqZWN0KCdGYWlsZWQgdG8gdmFsaWRhdGUgdGhpcyBhY2Nlc3MgdG9rZW4gd2l0aCBWay4nKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/wechat.js b/lib/Adapters/Auth/wechat.js index 1f0aebaa50..62062b210b 100644 --- a/lib/Adapters/Auth/wechat.js +++ b/lib/Adapters/Auth/wechat.js @@ -44,4 +44,5 @@ function graphRequest(path) { module.exports = { validateAppId, validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3dlY2hhdC5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJQYXJzZSIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsImdyYXBoUmVxdWVzdCIsImFjY2Vzc190b2tlbiIsImlkIiwidGhlbiIsImRhdGEiLCJlcnJjb2RlIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsInJlamVjdCIsImdldCIsInJlcyIsIm9uIiwiY2h1bmsiLCJKU09OIiwicGFyc2UiLCJlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLElBQUlBLFFBQVFDLFFBQVEsT0FBUixDQUFaO0FBQ0EsSUFBSUMsUUFBUUQsUUFBUSxZQUFSLEVBQXNCQyxLQUFsQzs7QUFFQTtBQUNBLFNBQVNDLGdCQUFULENBQTBCQyxRQUExQixFQUFvQztBQUNsQyxTQUFPQyxhQUFhLHVCQUF1QkQsU0FBU0UsWUFBaEMsR0FBK0MsVUFBL0MsR0FBNERGLFNBQVNHLEVBQWxGLEVBQXNGQyxJQUF0RixDQUEyRixVQUFVQyxJQUFWLEVBQWdCO0FBQ2hILFFBQUlBLEtBQUtDLE9BQUwsSUFBZ0IsQ0FBcEIsRUFBdUI7QUFDckI7QUFDRDtBQUNELFVBQU0sSUFBSVIsTUFBTVMsS0FBVixDQUFnQlQsTUFBTVMsS0FBTixDQUFZQyxnQkFBNUIsRUFBOEMsdUNBQTlDLENBQU47QUFDRCxHQUxNLENBQVA7QUFNRDs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTVixZQUFULENBQXNCVyxJQUF0QixFQUE0QjtBQUMxQixTQUFPLElBQUlGLE9BQUosQ0FBWSxVQUFVQyxPQUFWLEVBQW1CRSxNQUFuQixFQUEyQjtBQUM1Q2pCLFVBQU1rQixHQUFOLENBQVUsbUNBQW1DRixJQUE3QyxFQUFtRCxVQUFVRyxHQUFWLEVBQWU7QUFDaEUsVUFBSVYsT0FBTyxFQUFYO0FBQ0FVLFVBQUlDLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBVUMsS0FBVixFQUFpQjtBQUM5QlosZ0JBQVFZLEtBQVI7QUFDRCxPQUZEO0FBR0FGLFVBQUlDLEVBQUosQ0FBTyxLQUFQLEVBQWMsWUFBWTtBQUN4QixZQUFJO0FBQ0ZYLGlCQUFPYSxLQUFLQyxLQUFMLENBQVdkLElBQVgsQ0FBUDtBQUNELFNBRkQsQ0FFRSxPQUFNZSxDQUFOLEVBQVM7QUFDVCxpQkFBT1AsT0FBT08sQ0FBUCxDQUFQO0FBQ0Q7QUFDRFQsZ0JBQVFOLElBQVI7QUFDRCxPQVBEO0FBUUQsS0FiRCxFQWFHVyxFQWJILENBYU0sT0FiTixFQWFlLFlBQVk7QUFDekJILGFBQU8sbURBQVA7QUFDRCxLQWZEO0FBZ0JELEdBakJNLENBQVA7QUFrQkQ7O0FBRURRLE9BQU9DLE9BQVAsR0FBaUI7QUFDZmIsZUFEZTtBQUVmVjtBQUZlLENBQWpCIiwiZmlsZSI6IndlY2hhdC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgV2VDaGF0IEdyYXBoIEFQSS5cbnZhciBodHRwcyA9IHJlcXVpcmUoJ2h0dHBzJyk7XG52YXIgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIGdyYXBoUmVxdWVzdCgnYXV0aD9hY2Nlc3NfdG9rZW49JyArIGF1dGhEYXRhLmFjY2Vzc190b2tlbiArICcmb3BlbmlkPScgKyBhdXRoRGF0YS5pZCkudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuICAgIGlmIChkYXRhLmVycmNvZGUgPT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ3dlY2hhdCBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgV2VDaGF0IGdyYXBoIHJlcXVlc3RzLlxuZnVuY3Rpb24gZ3JhcGhSZXF1ZXN0KHBhdGgpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBodHRwcy5nZXQoJ2h0dHBzOi8vYXBpLndlaXhpbi5xcS5jb20vc25zLycgKyBwYXRoLCBmdW5jdGlvbiAocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICB9KTtcbiAgICB9KS5vbignZXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICByZWplY3QoJ0ZhaWxlZCB0byB2YWxpZGF0ZSB0aGlzIGFjY2VzcyB0b2tlbiB3aXRoIHdlY2hhdC4nKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Auth/weibo.js b/lib/Adapters/Auth/weibo.js index b6a0d0f46d..db29576bf0 100644 --- a/lib/Adapters/Auth/weibo.js +++ b/lib/Adapters/Auth/weibo.js @@ -63,4 +63,5 @@ function graphRequest(access_token) { module.exports = { validateAppId, validateAuthData -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL3dlaWJvLmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsIlBhcnNlIiwicXVlcnlzdHJpbmciLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJncmFwaFJlcXVlc3QiLCJhY2Nlc3NfdG9rZW4iLCJ0aGVuIiwiZGF0YSIsInVpZCIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwicG9zdERhdGEiLCJzdHJpbmdpZnkiLCJvcHRpb25zIiwiaG9zdG5hbWUiLCJwYXRoIiwibWV0aG9kIiwiaGVhZGVycyIsIkJ1ZmZlciIsImJ5dGVMZW5ndGgiLCJyZXEiLCJyZXF1ZXN0IiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsImUiLCJ3cml0ZSIsImVuZCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxRQUFRQyxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7QUFDQSxJQUFJQyxjQUFjRixRQUFRLGFBQVIsQ0FBbEI7O0FBRUE7QUFDQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0M7QUFDbEMsU0FBT0MsYUFBYUQsU0FBU0UsWUFBdEIsRUFBb0NDLElBQXBDLENBQXlDLFVBQVVDLElBQVYsRUFBZ0I7QUFDOUQsUUFBSUEsUUFBUUEsS0FBS0MsR0FBTCxJQUFZTCxTQUFTTSxFQUFqQyxFQUFxQztBQUNuQztBQUNEO0FBQ0QsVUFBTSxJQUFJVCxNQUFNVSxLQUFWLENBQWdCVixNQUFNVSxLQUFOLENBQVlDLGdCQUE1QixFQUE4QyxzQ0FBOUMsQ0FBTjtBQUNELEdBTE0sQ0FBUDtBQU1EOztBQUVEO0FBQ0EsU0FBU0MsYUFBVCxHQUF5QjtBQUN2QixTQUFPQyxRQUFRQyxPQUFSLEVBQVA7QUFDRDs7QUFFRDtBQUNBLFNBQVNWLFlBQVQsQ0FBc0JDLFlBQXRCLEVBQW9DO0FBQ2xDLFNBQU8sSUFBSVEsT0FBSixDQUFZLFVBQVVDLE9BQVYsRUFBbUJDLE1BQW5CLEVBQTJCO0FBQzVDLFFBQUlDLFdBQVdmLFlBQVlnQixTQUFaLENBQXNCO0FBQ25DLHNCQUFlWjtBQURvQixLQUF0QixDQUFmO0FBR0EsUUFBSWEsVUFBVTtBQUNaQyxnQkFBVSxlQURFO0FBRVpDLFlBQU0sd0JBRk07QUFHWkMsY0FBUSxNQUhJO0FBSVpDLGVBQVM7QUFDUCx3QkFBZ0IsbUNBRFQ7QUFFUCwwQkFBa0JDLE9BQU9DLFVBQVAsQ0FBa0JSLFFBQWxCO0FBRlg7QUFKRyxLQUFkO0FBU0EsUUFBSVMsTUFBTTNCLE1BQU00QixPQUFOLENBQWNSLE9BQWQsRUFBdUIsVUFBU1MsR0FBVCxFQUFhO0FBQzVDLFVBQUlwQixPQUFPLEVBQVg7QUFDQW9CLFVBQUlDLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBVUMsS0FBVixFQUFpQjtBQUM5QnRCLGdCQUFRc0IsS0FBUjtBQUNELE9BRkQ7QUFHQUYsVUFBSUMsRUFBSixDQUFPLEtBQVAsRUFBYyxZQUFZO0FBQ3hCLFlBQUk7QUFDRnJCLGlCQUFPdUIsS0FBS0MsS0FBTCxDQUFXeEIsSUFBWCxDQUFQO0FBQ0QsU0FGRCxDQUVFLE9BQU15QixDQUFOLEVBQVM7QUFDVCxpQkFBT2pCLE9BQU9pQixDQUFQLENBQVA7QUFDRDtBQUNEbEIsZ0JBQVFQLElBQVI7QUFDRCxPQVBEO0FBUUFvQixVQUFJQyxFQUFKLENBQU8sT0FBUCxFQUFnQixZQUFZO0FBQzFCYixlQUFPLGtEQUFQO0FBQ0QsT0FGRDtBQUdELEtBaEJTLENBQVY7QUFpQkFVLFFBQUlHLEVBQUosQ0FBTyxPQUFQLEVBQWdCLFlBQVk7QUFDMUJiLGFBQU8sa0RBQVA7QUFDRCxLQUZEO0FBR0FVLFFBQUlRLEtBQUosQ0FBVWpCLFFBQVY7QUFDQVMsUUFBSVMsR0FBSjtBQUNELEdBbkNNLENBQVA7QUFvQ0Q7O0FBRURDLE9BQU9DLE9BQVAsR0FBaUI7QUFDZnhCLGVBRGU7QUFFZlY7QUFGZSxDQUFqQiIsImZpbGUiOiJ3ZWliby5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEhlbHBlciBmdW5jdGlvbnMgZm9yIGFjY2Vzc2luZyB0aGUgd2VpYm8gR3JhcGggQVBJLlxudmFyIGh0dHBzID0gcmVxdWlyZSgnaHR0cHMnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbnZhciBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEpIHtcbiAgcmV0dXJuIGdyYXBoUmVxdWVzdChhdXRoRGF0YS5hY2Nlc3NfdG9rZW4pLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHtcbiAgICBpZiAoZGF0YSAmJiBkYXRhLnVpZCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ3dlaWJvIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLicpO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciB3ZWlibyBncmFwaCByZXF1ZXN0cy5cbmZ1bmN0aW9uIGdyYXBoUmVxdWVzdChhY2Nlc3NfdG9rZW4pIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgcG9zdERhdGEgPSBxdWVyeXN0cmluZy5zdHJpbmdpZnkoe1xuICAgICAgXCJhY2Nlc3NfdG9rZW5cIjphY2Nlc3NfdG9rZW5cbiAgICB9KTtcbiAgICB2YXIgb3B0aW9ucyA9IHtcbiAgICAgIGhvc3RuYW1lOiAnYXBpLndlaWJvLmNvbScsXG4gICAgICBwYXRoOiAnL29hdXRoMi9nZXRfdG9rZW5faW5mbycsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAgICAgICAnQ29udGVudC1MZW5ndGgnOiBCdWZmZXIuYnl0ZUxlbmd0aChwb3N0RGF0YSlcbiAgICAgIH1cbiAgICB9O1xuICAgIHZhciByZXEgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIGZ1bmN0aW9uKHJlcyl7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlamVjdCgnRmFpbGVkIHRvIHZhbGlkYXRlIHRoaXMgYWNjZXNzIHRva2VuIHdpdGggd2VpYm8uJyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXEub24oJ2Vycm9yJywgZnVuY3Rpb24gKCkge1xuICAgICAgcmVqZWN0KCdGYWlsZWQgdG8gdmFsaWRhdGUgdGhpcyBhY2Nlc3MgdG9rZW4gd2l0aCB3ZWliby4nKTtcbiAgICB9KTtcbiAgICByZXEud3JpdGUocG9zdERhdGEpO1xuICAgIHJlcS5lbmQoKTtcbiAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Cache/CacheAdapter.js b/lib/Adapters/Cache/CacheAdapter.js index bbb17ef749..402a231ebb 100644 --- a/lib/Adapters/Cache/CacheAdapter.js +++ b/lib/Adapters/Cache/CacheAdapter.js @@ -31,4 +31,5 @@ class CacheAdapter { */ clear() {} } -exports.CacheAdapter = CacheAdapter; \ No newline at end of file +exports.CacheAdapter = CacheAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9DYWNoZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsiQ2FjaGVBZGFwdGVyIiwiZ2V0Iiwia2V5IiwicHV0IiwidmFsdWUiLCJ0dGwiLCJkZWwiLCJjbGVhciJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNPLE1BQU1BLFlBQU4sQ0FBbUI7QUFDeEI7Ozs7O0FBS0FDLE1BQUlDLEdBQUosRUFBUyxDQUFFOztBQUVYOzs7Ozs7QUFNQUMsTUFBSUQsR0FBSixFQUFTRSxLQUFULEVBQWdCQyxHQUFoQixFQUFxQixDQUFFOztBQUV2Qjs7OztBQUlBQyxNQUFJSixHQUFKLEVBQVMsQ0FBRTs7QUFFWDs7O0FBR0FLLFVBQVEsQ0FBRTtBQXpCYztRQUFiUCxZLEdBQUFBLFkiLCJmaWxlIjoiQ2FjaGVBZGFwdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyplc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIqL1xuZXhwb3J0IGNsYXNzIENhY2hlQWRhcHRlciB7XG4gIC8qKlxuICAgKiBHZXQgYSB2YWx1ZSBpbiB0aGUgY2FjaGVcbiAgICogQHBhcmFtIGtleSBDYWNoZSBrZXkgdG8gZ2V0XG4gICAqIEByZXR1cm4gUHJvbWlzZSB0aGF0IHdpbGwgZXZlbnR1YWxseSByZXNvbHZlIHRvIHRoZSB2YWx1ZSBpbiB0aGUgY2FjaGUuXG4gICAqL1xuICBnZXQoa2V5KSB7fVxuXG4gIC8qKlxuICAgKiBTZXQgYSB2YWx1ZSBpbiB0aGUgY2FjaGVcbiAgICogQHBhcmFtIGtleSBDYWNoZSBrZXkgdG8gc2V0XG4gICAqIEBwYXJhbSB2YWx1ZSBWYWx1ZSB0byBzZXQgdGhlIGtleVxuICAgKiBAcGFyYW0gdHRsIE9wdGlvbmFsIFRUTFxuICAgKi9cbiAgcHV0KGtleSwgdmFsdWUsIHR0bCkge31cblxuICAvKipcbiAgICogUmVtb3ZlIGEgdmFsdWUgZnJvbSB0aGUgY2FjaGUuXG4gICAqIEBwYXJhbSBrZXkgQ2FjaGUga2V5IHRvIHJlbW92ZVxuICAgKi9cbiAgZGVsKGtleSkge31cblxuICAvKipcbiAgICogRW1wdHkgYSBjYWNoZVxuICAgKi9cbiAgY2xlYXIoKSB7fVxufVxuIl19 \ No newline at end of file diff --git a/lib/Adapters/Cache/InMemoryCache.js b/lib/Adapters/Cache/InMemoryCache.js index c76bbc729d..3fef58804e 100644 --- a/lib/Adapters/Cache/InMemoryCache.js +++ b/lib/Adapters/Cache/InMemoryCache.js @@ -67,4 +67,5 @@ class InMemoryCache { } exports.InMemoryCache = InMemoryCache; -exports.default = InMemoryCache; \ No newline at end of file +exports.default = InMemoryCache; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9Jbk1lbW9yeUNhY2hlLmpzIl0sIm5hbWVzIjpbIkRFRkFVTFRfQ0FDSEVfVFRMIiwiSW5NZW1vcnlDYWNoZSIsImNvbnN0cnVjdG9yIiwidHRsIiwiY2FjaGUiLCJPYmplY3QiLCJjcmVhdGUiLCJnZXQiLCJrZXkiLCJyZWNvcmQiLCJpc05hTiIsImV4cGlyZSIsIkRhdGUiLCJub3ciLCJ2YWx1ZSIsInB1dCIsIk5hTiIsInRpbWVvdXQiLCJzZXRUaW1lb3V0IiwiZGVsIiwiY2xlYXJUaW1lb3V0IiwiY2xlYXIiXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsTUFBTUEsb0JBQW9CLElBQUksSUFBOUI7O0FBR08sTUFBTUMsYUFBTixDQUFvQjtBQUN6QkMsY0FBWTtBQUNWQyxVQUFNSDtBQURJLEdBQVosRUFFRztBQUNELFNBQUtHLEdBQUwsR0FBV0EsR0FBWDtBQUNBLFNBQUtDLEtBQUwsR0FBYUMsT0FBT0MsTUFBUCxDQUFjLElBQWQsQ0FBYjtBQUNEOztBQUVEQyxNQUFJQyxHQUFKLEVBQVM7QUFDUCxVQUFNQyxTQUFTLEtBQUtMLEtBQUwsQ0FBV0ksR0FBWCxDQUFmO0FBQ0EsUUFBSUMsVUFBVSxJQUFkLEVBQW9CO0FBQ2xCLGFBQU8sSUFBUDtBQUNEOztBQUVEO0FBQ0EsUUFBSUMsTUFBTUQsT0FBT0UsTUFBYixLQUF3QkYsT0FBT0UsTUFBUCxJQUFpQkMsS0FBS0MsR0FBTCxFQUE3QyxFQUF5RDtBQUN2RCxhQUFPSixPQUFPSyxLQUFkO0FBQ0Q7O0FBRUQ7QUFDQSxXQUFPLEtBQUtWLEtBQUwsQ0FBV0ksR0FBWCxDQUFQO0FBQ0EsV0FBTyxJQUFQO0FBQ0Q7O0FBRURPLE1BQUlQLEdBQUosRUFBU00sS0FBVCxFQUFnQlgsTUFBTSxLQUFLQSxHQUEzQixFQUFnQztBQUM5QixRQUFJQSxNQUFNLENBQU4sSUFBV08sTUFBTVAsR0FBTixDQUFmLEVBQTJCO0FBQ3pCQSxZQUFNYSxHQUFOO0FBQ0Q7O0FBRUQsUUFBSVAsU0FBUztBQUNYSyxhQUFPQSxLQURJO0FBRVhILGNBQVFSLE1BQU1TLEtBQUtDLEdBQUw7QUFGSCxLQUFiOztBQUtBLFFBQUksQ0FBQ0gsTUFBTUQsT0FBT0UsTUFBYixDQUFMLEVBQTJCO0FBQ3pCRixhQUFPUSxPQUFQLEdBQWlCQyxXQUFXLE1BQU07QUFDaEMsYUFBS0MsR0FBTCxDQUFTWCxHQUFUO0FBQ0QsT0FGZ0IsRUFFZEwsR0FGYyxDQUFqQjtBQUdEOztBQUVELFNBQUtDLEtBQUwsQ0FBV0ksR0FBWCxJQUFrQkMsTUFBbEI7QUFDRDs7QUFFRFUsTUFBSVgsR0FBSixFQUFTO0FBQ1AsUUFBSUMsU0FBUyxLQUFLTCxLQUFMLENBQVdJLEdBQVgsQ0FBYjtBQUNBLFFBQUlDLFVBQVUsSUFBZCxFQUFvQjtBQUNsQjtBQUNEOztBQUVELFFBQUlBLE9BQU9RLE9BQVgsRUFBb0I7QUFDbEJHLG1CQUFhWCxPQUFPUSxPQUFwQjtBQUNEO0FBQ0QsV0FBTyxLQUFLYixLQUFMLENBQVdJLEdBQVgsQ0FBUDtBQUNEOztBQUVEYSxVQUFRO0FBQ04sU0FBS2pCLEtBQUwsR0FBYUMsT0FBT0MsTUFBUCxDQUFjLElBQWQsQ0FBYjtBQUNEOztBQXpEd0I7O1FBQWRMLGEsR0FBQUEsYTtrQkE2REVBLGEiLCJmaWxlIjoiSW5NZW1vcnlDYWNoZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IERFRkFVTFRfQ0FDSEVfVFRMID0gNSAqIDEwMDA7XG5cblxuZXhwb3J0IGNsYXNzIEluTWVtb3J5Q2FjaGUge1xuICBjb25zdHJ1Y3Rvcih7XG4gICAgdHRsID0gREVGQVVMVF9DQUNIRV9UVExcbiAgfSkge1xuICAgIHRoaXMudHRsID0gdHRsO1xuICAgIHRoaXMuY2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB9XG5cbiAgZ2V0KGtleSkge1xuICAgIGNvbnN0IHJlY29yZCA9IHRoaXMuY2FjaGVba2V5XTtcbiAgICBpZiAocmVjb3JkID09IG51bGwpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIEhhcyBSZWNvcmQgYW5kIGlzbnQgZXhwaXJlZFxuICAgIGlmIChpc05hTihyZWNvcmQuZXhwaXJlKSB8fCByZWNvcmQuZXhwaXJlID49IERhdGUubm93KCkpIHtcbiAgICAgIHJldHVybiByZWNvcmQudmFsdWU7XG4gICAgfVxuXG4gICAgLy8gUmVjb3JkIGhhcyBleHBpcmVkXG4gICAgZGVsZXRlIHRoaXMuY2FjaGVba2V5XTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHB1dChrZXksIHZhbHVlLCB0dGwgPSB0aGlzLnR0bCkge1xuICAgIGlmICh0dGwgPCAwIHx8IGlzTmFOKHR0bCkpIHtcbiAgICAgIHR0bCA9IE5hTjtcbiAgICB9XG5cbiAgICB2YXIgcmVjb3JkID0ge1xuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgZXhwaXJlOiB0dGwgKyBEYXRlLm5vdygpXG4gICAgfVxuXG4gICAgaWYgKCFpc05hTihyZWNvcmQuZXhwaXJlKSkge1xuICAgICAgcmVjb3JkLnRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5kZWwoa2V5KTtcbiAgICAgIH0sIHR0bCk7XG4gICAgfVxuXG4gICAgdGhpcy5jYWNoZVtrZXldID0gcmVjb3JkO1xuICB9XG5cbiAgZGVsKGtleSkge1xuICAgIHZhciByZWNvcmQgPSB0aGlzLmNhY2hlW2tleV07XG4gICAgaWYgKHJlY29yZCA9PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHJlY29yZC50aW1lb3V0KSB7XG4gICAgICBjbGVhclRpbWVvdXQocmVjb3JkLnRpbWVvdXQpO1xuICAgIH1cbiAgICBkZWxldGUgdGhpcy5jYWNoZVtrZXldO1xuICB9XG5cbiAgY2xlYXIoKSB7XG4gICAgdGhpcy5jYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBJbk1lbW9yeUNhY2hlO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Cache/InMemoryCacheAdapter.js b/lib/Adapters/Cache/InMemoryCacheAdapter.js index e3705c920c..5abd33a629 100644 --- a/lib/Adapters/Cache/InMemoryCacheAdapter.js +++ b/lib/Adapters/Cache/InMemoryCacheAdapter.js @@ -38,4 +38,5 @@ class InMemoryCacheAdapter { } exports.InMemoryCacheAdapter = InMemoryCacheAdapter; -exports.default = InMemoryCacheAdapter; \ No newline at end of file +exports.default = InMemoryCacheAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9Jbk1lbW9yeUNhY2hlQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJJbk1lbW9yeUNhY2hlQWRhcHRlciIsImNvbnN0cnVjdG9yIiwiY3R4IiwiY2FjaGUiLCJMUlVDYWNoZSIsImdldCIsImtleSIsInJlY29yZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicHV0IiwidmFsdWUiLCJ0dGwiLCJkZWwiLCJjbGVhciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUVPLE1BQU1BLG9CQUFOLENBQTJCOztBQUVoQ0MsY0FBWUMsR0FBWixFQUFpQjtBQUNmLFNBQUtDLEtBQUwsR0FBYSxJQUFJQyxrQkFBSixDQUFhRixHQUFiLENBQWI7QUFDRDs7QUFFREcsTUFBSUMsR0FBSixFQUFTO0FBQ1AsVUFBTUMsU0FBUyxLQUFLSixLQUFMLENBQVdFLEdBQVgsQ0FBZUMsR0FBZixDQUFmO0FBQ0EsUUFBSUMsV0FBVyxJQUFmLEVBQXFCO0FBQ25CLGFBQU9DLFFBQVFDLE9BQVIsQ0FBZ0IsSUFBaEIsQ0FBUDtBQUNEO0FBQ0QsV0FBT0QsUUFBUUMsT0FBUixDQUFnQkYsTUFBaEIsQ0FBUDtBQUNEOztBQUVERyxNQUFJSixHQUFKLEVBQVNLLEtBQVQsRUFBZ0JDLEdBQWhCLEVBQXFCO0FBQ25CLFNBQUtULEtBQUwsQ0FBV08sR0FBWCxDQUFlSixHQUFmLEVBQW9CSyxLQUFwQixFQUEyQkMsR0FBM0I7QUFDQSxXQUFPSixRQUFRQyxPQUFSLEVBQVA7QUFDRDs7QUFFREksTUFBSVAsR0FBSixFQUFTO0FBQ1AsU0FBS0gsS0FBTCxDQUFXVSxHQUFYLENBQWVQLEdBQWY7QUFDQSxXQUFPRSxRQUFRQyxPQUFSLEVBQVA7QUFDRDs7QUFFREssVUFBUTtBQUNOLFNBQUtYLEtBQUwsQ0FBV1csS0FBWDtBQUNBLFdBQU9OLFFBQVFDLE9BQVIsRUFBUDtBQUNEO0FBM0IrQjs7UUFBckJULG9CLEdBQUFBLG9CO2tCQThCRUEsb0IiLCJmaWxlIjoiSW5NZW1vcnlDYWNoZUFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0xSVUNhY2hlfSBmcm9tICcuL0xSVUNhY2hlJztcblxuZXhwb3J0IGNsYXNzIEluTWVtb3J5Q2FjaGVBZGFwdGVyIHtcblxuICBjb25zdHJ1Y3RvcihjdHgpIHtcbiAgICB0aGlzLmNhY2hlID0gbmV3IExSVUNhY2hlKGN0eClcbiAgfVxuXG4gIGdldChrZXkpIHtcbiAgICBjb25zdCByZWNvcmQgPSB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgIGlmIChyZWNvcmQgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVjb3JkKTtcbiAgfVxuXG4gIHB1dChrZXksIHZhbHVlLCB0dGwpIHtcbiAgICB0aGlzLmNhY2hlLnB1dChrZXksIHZhbHVlLCB0dGwpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGRlbChrZXkpIHtcbiAgICB0aGlzLmNhY2hlLmRlbChrZXkpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHRoaXMuY2FjaGUuY2xlYXIoKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSW5NZW1vcnlDYWNoZUFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Cache/LRUCache.js b/lib/Adapters/Cache/LRUCache.js index a4476aa154..e3b0acc5db 100644 --- a/lib/Adapters/Cache/LRUCache.js +++ b/lib/Adapters/Cache/LRUCache.js @@ -45,4 +45,5 @@ class LRUCache { } exports.LRUCache = LRUCache; -exports.default = LRUCache; \ No newline at end of file +exports.default = LRUCache; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9MUlVDYWNoZS5qcyJdLCJuYW1lcyI6WyJMUlVDYWNoZSIsImNvbnN0cnVjdG9yIiwidHRsIiwiZGVmYXVsdHMiLCJjYWNoZVRUTCIsIm1heFNpemUiLCJjYWNoZU1heFNpemUiLCJjYWNoZSIsIkxSVSIsIm1heCIsIm1heEFnZSIsImdldCIsImtleSIsInB1dCIsInZhbHVlIiwic2V0IiwiZGVsIiwiY2xlYXIiLCJyZXNldCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBQ0E7Ozs7OztBQUVPLE1BQU1BLFFBQU4sQ0FBZTtBQUNwQkMsY0FBWTtBQUNWQyxVQUFNQyxtQkFBU0MsUUFETDtBQUVWQyxjQUFVRixtQkFBU0c7QUFGVCxHQUFaLEVBR0c7QUFDRCxTQUFLQyxLQUFMLEdBQWEsSUFBSUMsa0JBQUosQ0FBUTtBQUNuQkMsV0FBS0osT0FEYztBQUVuQkssY0FBUVI7QUFGVyxLQUFSLENBQWI7QUFJRDs7QUFFRFMsTUFBSUMsR0FBSixFQUFTO0FBQ1AsV0FBTyxLQUFLTCxLQUFMLENBQVdJLEdBQVgsQ0FBZUMsR0FBZixLQUF1QixJQUE5QjtBQUNEOztBQUVEQyxNQUFJRCxHQUFKLEVBQVNFLEtBQVQsRUFBZ0JaLE1BQU0sS0FBS0EsR0FBM0IsRUFBZ0M7QUFDOUIsU0FBS0ssS0FBTCxDQUFXUSxHQUFYLENBQWVILEdBQWYsRUFBb0JFLEtBQXBCLEVBQTJCWixHQUEzQjtBQUNEOztBQUVEYyxNQUFJSixHQUFKLEVBQVM7QUFDUCxTQUFLTCxLQUFMLENBQVdTLEdBQVgsQ0FBZUosR0FBZjtBQUNEOztBQUVESyxVQUFRO0FBQ04sU0FBS1YsS0FBTCxDQUFXVyxLQUFYO0FBQ0Q7O0FBekJtQjs7UUFBVGxCLFEsR0FBQUEsUTtrQkE2QkVBLFEiLCJmaWxlIjoiTFJVQ2FjaGUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgTFJVIGZyb20gJ2xydS1jYWNoZSc7XG5pbXBvcnQgZGVmYXVsdHMgIGZyb20gJy4uLy4uL2RlZmF1bHRzJztcblxuZXhwb3J0IGNsYXNzIExSVUNhY2hlIHtcbiAgY29uc3RydWN0b3Ioe1xuICAgIHR0bCA9IGRlZmF1bHRzLmNhY2hlVFRMLFxuICAgIG1heFNpemUgPSBkZWZhdWx0cy5jYWNoZU1heFNpemUsXG4gIH0pIHtcbiAgICB0aGlzLmNhY2hlID0gbmV3IExSVSh7XG4gICAgICBtYXg6IG1heFNpemUsXG4gICAgICBtYXhBZ2U6IHR0bFxuICAgIH0pO1xuICB9XG5cbiAgZ2V0KGtleSkge1xuICAgIHJldHVybiB0aGlzLmNhY2hlLmdldChrZXkpIHx8IG51bGw7XG4gIH1cblxuICBwdXQoa2V5LCB2YWx1ZSwgdHRsID0gdGhpcy50dGwpIHtcbiAgICB0aGlzLmNhY2hlLnNldChrZXksIHZhbHVlLCB0dGwpO1xuICB9XG5cbiAgZGVsKGtleSkge1xuICAgIHRoaXMuY2FjaGUuZGVsKGtleSk7XG4gIH1cblxuICBjbGVhcigpIHtcbiAgICB0aGlzLmNhY2hlLnJlc2V0KCk7XG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBMUlVDYWNoZTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Cache/NullCacheAdapter.js b/lib/Adapters/Cache/NullCacheAdapter.js index 55d536878c..cdb02b4e8a 100644 --- a/lib/Adapters/Cache/NullCacheAdapter.js +++ b/lib/Adapters/Cache/NullCacheAdapter.js @@ -27,4 +27,5 @@ class NullCacheAdapter { } exports.NullCacheAdapter = NullCacheAdapter; -exports.default = NullCacheAdapter; \ No newline at end of file +exports.default = NullCacheAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9OdWxsQ2FjaGVBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIk51bGxDYWNoZUFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsImdldCIsIlByb21pc2UiLCJyZXNvbHZlIiwicHV0IiwiZGVsIiwiY2xlYXIiXSwibWFwcGluZ3MiOiI7Ozs7O0FBQU8sTUFBTUEsZ0JBQU4sQ0FBdUI7O0FBRTVCQyxnQkFBYyxDQUFFOztBQUVoQkMsUUFBTTtBQUNKLFdBQU8sSUFBSUMsT0FBSixDQUFhQyxPQUFELElBQWE7QUFDOUIsYUFBT0EsUUFBUSxJQUFSLENBQVA7QUFDRCxLQUZNLENBQVA7QUFHRDs7QUFFREMsUUFBTTtBQUNKLFdBQU9GLFFBQVFDLE9BQVIsRUFBUDtBQUNEOztBQUVERSxRQUFNO0FBQ0osV0FBT0gsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRURHLFVBQVE7QUFDTixXQUFPSixRQUFRQyxPQUFSLEVBQVA7QUFDRDtBQXBCMkI7O1FBQWpCSixnQixHQUFBQSxnQjtrQkF1QkVBLGdCIiwiZmlsZSI6Ik51bGxDYWNoZUFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY2xhc3MgTnVsbENhY2hlQWRhcHRlciB7XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgIH0pXG4gIH1cblxuICBwdXQoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgZGVsKCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBOdWxsQ2FjaGVBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Cache/RedisCacheAdapter.js b/lib/Adapters/Cache/RedisCacheAdapter.js index 615a4c8250..028a069ec0 100644 --- a/lib/Adapters/Cache/RedisCacheAdapter.js +++ b/lib/Adapters/Cache/RedisCacheAdapter.js @@ -96,4 +96,5 @@ class RedisCacheAdapter { } exports.RedisCacheAdapter = RedisCacheAdapter; -exports.default = RedisCacheAdapter; \ No newline at end of file +exports.default = RedisCacheAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9DYWNoZS9SZWRpc0NhY2hlQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJERUZBVUxUX1JFRElTX1RUTCIsImRlYnVnIiwibG9nZ2VyIiwiYXBwbHkiLCJhcmd1bWVudHMiLCJSZWRpc0NhY2hlQWRhcHRlciIsImNvbnN0cnVjdG9yIiwicmVkaXNDdHgiLCJ0dGwiLCJjbGllbnQiLCJyZWRpcyIsImNyZWF0ZUNsaWVudCIsInAiLCJQcm9taXNlIiwicmVzb2x2ZSIsImdldCIsImtleSIsInRoZW4iLCJlcnIiLCJyZXMiLCJKU09OIiwicGFyc2UiLCJwdXQiLCJ2YWx1ZSIsInN0cmluZ2lmeSIsImlzTmFOIiwiSW5maW5pdHkiLCJzZXQiLCJwc2V0ZXgiLCJkZWwiLCJjbGVhciIsImZsdXNoZGIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7Ozs7QUFFQSxNQUFNQSxvQkFBb0IsS0FBSyxJQUEvQixDLENBQXFDOztBQUVyQyxTQUFTQyxLQUFULEdBQWlCO0FBQ2ZDLG1CQUFPRCxLQUFQLENBQWFFLEtBQWIsQ0FBbUJELGdCQUFuQixFQUEyQixDQUFDLG1CQUFELEVBQXNCLEdBQUdFLFNBQXpCLENBQTNCO0FBQ0Q7O0FBRU0sTUFBTUMsaUJBQU4sQ0FBd0I7O0FBRTdCQyxjQUFZQyxRQUFaLEVBQXNCQyxNQUFNUixpQkFBNUIsRUFBK0M7QUFDN0MsU0FBS1MsTUFBTCxHQUFjQyxnQkFBTUMsWUFBTixDQUFtQkosUUFBbkIsQ0FBZDtBQUNBLFNBQUtLLENBQUwsR0FBU0MsUUFBUUMsT0FBUixFQUFUO0FBQ0EsU0FBS04sR0FBTCxHQUFXQSxHQUFYO0FBQ0Q7O0FBRURPLE1BQUlDLEdBQUosRUFBUztBQUNQZixVQUFNLEtBQU4sRUFBYWUsR0FBYjtBQUNBLFNBQUtKLENBQUwsR0FBUyxLQUFLQSxDQUFMLENBQU9LLElBQVAsQ0FBWSxNQUFNO0FBQ3pCLGFBQU8sSUFBSUosT0FBSixDQUFhQyxPQUFELElBQWE7QUFDOUIsYUFBS0wsTUFBTCxDQUFZTSxHQUFaLENBQWdCQyxHQUFoQixFQUFxQixVQUFTRSxHQUFULEVBQWNDLEdBQWQsRUFBbUI7QUFDdENsQixnQkFBTSxRQUFOLEVBQWdCZSxHQUFoQixFQUFxQkcsR0FBckI7QUFDQSxjQUFHLENBQUNBLEdBQUosRUFBUztBQUNQLG1CQUFPTCxRQUFRLElBQVIsQ0FBUDtBQUNEO0FBQ0RBLGtCQUFRTSxLQUFLQyxLQUFMLENBQVdGLEdBQVgsQ0FBUjtBQUNELFNBTkQ7QUFPRCxPQVJNLENBQVA7QUFTRCxLQVZRLENBQVQ7QUFXQSxXQUFPLEtBQUtQLENBQVo7QUFDRDs7QUFFRFUsTUFBSU4sR0FBSixFQUFTTyxLQUFULEVBQWdCZixNQUFNLEtBQUtBLEdBQTNCLEVBQWdDO0FBQzlCZSxZQUFRSCxLQUFLSSxTQUFMLENBQWVELEtBQWYsQ0FBUjtBQUNBdEIsVUFBTSxLQUFOLEVBQWFlLEdBQWIsRUFBa0JPLEtBQWxCLEVBQXlCZixHQUF6QjtBQUNBLFFBQUlBLFFBQVEsQ0FBWixFQUFlO0FBQ2IsYUFBTyxLQUFLSSxDQUFaLENBRGEsQ0FDRTtBQUNoQjtBQUNELFFBQUlKLE1BQU0sQ0FBTixJQUFXaUIsTUFBTWpCLEdBQU4sQ0FBZixFQUEyQjtBQUN6QkEsWUFBTVIsaUJBQU47QUFDRDtBQUNELFNBQUtZLENBQUwsR0FBUyxLQUFLQSxDQUFMLENBQU9LLElBQVAsQ0FBWSxNQUFNO0FBQ3pCLGFBQU8sSUFBSUosT0FBSixDQUFhQyxPQUFELElBQWE7QUFDOUIsWUFBSU4sUUFBUWtCLFFBQVosRUFBc0I7QUFDcEIsZUFBS2pCLE1BQUwsQ0FBWWtCLEdBQVosQ0FBZ0JYLEdBQWhCLEVBQXFCTyxLQUFyQixFQUE0QixZQUFXO0FBQ3JDVDtBQUNELFdBRkQ7QUFHRCxTQUpELE1BSU87QUFDTCxlQUFLTCxNQUFMLENBQVltQixNQUFaLENBQW1CWixHQUFuQixFQUF3QlIsR0FBeEIsRUFBNkJlLEtBQTdCLEVBQW9DLFlBQVc7QUFDN0NUO0FBQ0QsV0FGRDtBQUdEO0FBQ0YsT0FWTSxDQUFQO0FBV0QsS0FaUSxDQUFUO0FBYUEsV0FBTyxLQUFLRixDQUFaO0FBQ0Q7O0FBRURpQixNQUFJYixHQUFKLEVBQVM7QUFDUGYsVUFBTSxLQUFOLEVBQWFlLEdBQWI7QUFDQSxTQUFLSixDQUFMLEdBQVMsS0FBS0EsQ0FBTCxDQUFPSyxJQUFQLENBQVksTUFBTTtBQUN6QixhQUFPLElBQUlKLE9BQUosQ0FBYUMsT0FBRCxJQUFhO0FBQzlCLGFBQUtMLE1BQUwsQ0FBWW9CLEdBQVosQ0FBZ0JiLEdBQWhCLEVBQXFCLFlBQVc7QUFDOUJGO0FBQ0QsU0FGRDtBQUdELE9BSk0sQ0FBUDtBQUtELEtBTlEsQ0FBVDtBQU9BLFdBQU8sS0FBS0YsQ0FBWjtBQUNEOztBQUVEa0IsVUFBUTtBQUNON0IsVUFBTSxPQUFOO0FBQ0EsU0FBS1csQ0FBTCxHQUFTLEtBQUtBLENBQUwsQ0FBT0ssSUFBUCxDQUFZLE1BQU07QUFDekIsYUFBTyxJQUFJSixPQUFKLENBQWFDLE9BQUQsSUFBYTtBQUM5QixhQUFLTCxNQUFMLENBQVlzQixPQUFaLENBQW9CLFlBQVc7QUFDN0JqQjtBQUNELFNBRkQ7QUFHRCxPQUpNLENBQVA7QUFLRCxLQU5RLENBQVQ7QUFPQSxXQUFPLEtBQUtGLENBQVo7QUFDRDtBQXZFNEI7O1FBQWxCUCxpQixHQUFBQSxpQjtrQkEwRUVBLGlCIiwiZmlsZSI6IlJlZGlzQ2FjaGVBZGFwdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlZGlzIGZyb20gJ3JlZGlzJztcbmltcG9ydCBsb2dnZXIgZnJvbSAnLi4vLi4vbG9nZ2VyJztcblxuY29uc3QgREVGQVVMVF9SRURJU19UVEwgPSAzMCAqIDEwMDA7IC8vIDMwIHNlY29uZHMgaW4gbWlsbGlzZWNvbmRzXG5cbmZ1bmN0aW9uIGRlYnVnKCkge1xuICBsb2dnZXIuZGVidWcuYXBwbHkobG9nZ2VyLCBbJ1JlZGlzQ2FjaGVBZGFwdGVyJywgLi4uYXJndW1lbnRzXSk7XG59XG5cbmV4cG9ydCBjbGFzcyBSZWRpc0NhY2hlQWRhcHRlciB7XG5cbiAgY29uc3RydWN0b3IocmVkaXNDdHgsIHR0bCA9IERFRkFVTFRfUkVESVNfVFRMKSB7XG4gICAgdGhpcy5jbGllbnQgPSByZWRpcy5jcmVhdGVDbGllbnQocmVkaXNDdHgpO1xuICAgIHRoaXMucCA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIHRoaXMudHRsID0gdHRsO1xuICB9XG5cbiAgZ2V0KGtleSkge1xuICAgIGRlYnVnKCdnZXQnLCBrZXkpO1xuICAgIHRoaXMucCA9IHRoaXMucC50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICB0aGlzLmNsaWVudC5nZXQoa2V5LCBmdW5jdGlvbihlcnIsIHJlcykge1xuICAgICAgICAgIGRlYnVnKCctPiBnZXQnLCBrZXksIHJlcyk7XG4gICAgICAgICAgaWYoIXJlcykge1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUoSlNPTi5wYXJzZShyZXMpKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5wO1xuICB9XG5cbiAgcHV0KGtleSwgdmFsdWUsIHR0bCA9IHRoaXMudHRsKSB7XG4gICAgdmFsdWUgPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgZGVidWcoJ3B1dCcsIGtleSwgdmFsdWUsIHR0bCk7XG4gICAgaWYgKHR0bCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMucDsgLy8gdHRsIG9mIHplcm8gaXMgYSBsb2dpY2FsIG5vLW9wLCBidXQgcmVkaXMgY2Fubm90IHNldCBleHBpcmUgdGltZSBvZiB6ZXJvXG4gICAgfVxuICAgIGlmICh0dGwgPCAwIHx8IGlzTmFOKHR0bCkpIHtcbiAgICAgIHR0bCA9IERFRkFVTFRfUkVESVNfVFRMO1xuICAgIH1cbiAgICB0aGlzLnAgPSB0aGlzLnAudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgaWYgKHR0bCA9PT0gSW5maW5pdHkpIHtcbiAgICAgICAgICB0aGlzLmNsaWVudC5zZXQoa2V5LCB2YWx1ZSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5jbGllbnQucHNldGV4KGtleSwgdHRsLCB2YWx1ZSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLnA7XG4gIH1cblxuICBkZWwoa2V5KSB7XG4gICAgZGVidWcoJ2RlbCcsIGtleSk7XG4gICAgdGhpcy5wID0gdGhpcy5wLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHRoaXMuY2xpZW50LmRlbChrZXksIGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5wO1xuICB9XG5cbiAgY2xlYXIoKSB7XG4gICAgZGVidWcoJ2NsZWFyJyk7XG4gICAgdGhpcy5wID0gdGhpcy5wLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHRoaXMuY2xpZW50LmZsdXNoZGIoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLnA7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUmVkaXNDYWNoZUFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Email/MailAdapter.js b/lib/Adapters/Email/MailAdapter.js index b2fe018c92..24e6230d0b 100644 --- a/lib/Adapters/Email/MailAdapter.js +++ b/lib/Adapters/Email/MailAdapter.js @@ -26,4 +26,5 @@ class MailAdapter { } exports.MailAdapter = MailAdapter; -exports.default = MailAdapter; \ No newline at end of file +exports.default = MailAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9FbWFpbC9NYWlsQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJNYWlsQWRhcHRlciIsInNlbmRNYWlsIiwib3B0aW9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNBOzs7O0FBSU8sTUFBTUEsV0FBTixDQUFrQjtBQUN2Qjs7Ozs7OztBQU9BQyxXQUFTQyxPQUFULEVBQWtCLENBQUU7O0FBRXBCOzs7QUFHQTtBQUNBO0FBZHVCOztRQUFaRixXLEdBQUFBLFc7a0JBaUJFQSxXIiwiZmlsZSI6Ik1haWxBZGFwdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyplc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIqL1xuLypcbiAgTWFpbCBBZGFwdGVyIHByb3RvdHlwZVxuICBBIE1haWxBZGFwdGVyIHNob3VsZCBpbXBsZW1lbnQgYXQgbGVhc3Qgc2VuZE1haWwoKVxuICovXG5leHBvcnQgY2xhc3MgTWFpbEFkYXB0ZXIge1xuICAvKlxuICAgKiBBIG1ldGhvZCBmb3Igc2VuZGluZyBtYWlsXG4gICAqIEBwYXJhbSBvcHRpb25zIHdvdWxkIGhhdmUgdGhlIHBhcmFtZXRlcnNcbiAgICogLSB0bzogdGhlIHJlY2lwaWVudFxuICAgKiAtIHRleHQ6IHRoZSByYXcgdGV4dCBvZiB0aGUgbWVzc2FnZVxuICAgKiAtIHN1YmplY3Q6IHRoZSBzdWJqZWN0IG9mIHRoZSBlbWFpbFxuICAgKi9cbiAgc2VuZE1haWwob3B0aW9ucykge31cblxuICAvKiBZb3UgY2FuIGltcGxlbWVudCB0aG9zZSBtZXRob2RzIGlmIHlvdSB3YW50XG4gICAqIHRvIHByb3ZpZGUgSFRNTCB0ZW1wbGF0ZXMgZXRjLi4uXG4gICAqL1xuICAvLyBzZW5kVmVyaWZpY2F0aW9uRW1haWwoeyBsaW5rLCBhcHBOYW1lLCB1c2VyIH0pIHt9XG4gIC8vIHNlbmRQYXNzd29yZFJlc2V0RW1haWwoeyBsaW5rLCBhcHBOYW1lLCB1c2VyIH0pIHt9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1haWxBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Files/FilesAdapter.js b/lib/Adapters/Files/FilesAdapter.js index 128cb2cd94..eb8230f6e6 100644 --- a/lib/Adapters/Files/FilesAdapter.js +++ b/lib/Adapters/Files/FilesAdapter.js @@ -57,4 +57,5 @@ exports.FilesAdapter = FilesAdapter; /*eslint no-unused-vars: "off"*/ // and for the API server to be using the DatabaseController with Mongo // database adapter. -exports.default = FilesAdapter; \ No newline at end of file +exports.default = FilesAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9GaWxlcy9GaWxlc0FkYXB0ZXIuanMiXSwibmFtZXMiOlsiRmlsZXNBZGFwdGVyIiwiY3JlYXRlRmlsZSIsImZpbGVuYW1lIiwiZGF0YSIsImNvbnRlbnRUeXBlIiwiZGVsZXRlRmlsZSIsImdldEZpbGVEYXRhIiwiZ2V0RmlsZUxvY2F0aW9uIiwiY29uZmlnIl0sIm1hcHBpbmdzIjoiOzs7OztBQWlCTyxNQUFNQSxZQUFOLENBQW1COztBQUV4Qjs7Ozs7Ozs7O0FBU0FDLGFBQVdDLFFBQVgsRUFBNkJDLElBQTdCLEVBQW1DQyxXQUFuQyxFQUFpRSxDQUFHOztBQUVwRTs7Ozs7O0FBTUFDLGFBQVdILFFBQVgsRUFBc0MsQ0FBRzs7QUFFekM7Ozs7OztBQU1BSSxjQUFZSixRQUFaLEVBQTRDLENBQUc7O0FBRS9DOzs7Ozs7O0FBT0FLLGtCQUFnQkMsTUFBaEIsRUFBZ0NOLFFBQWhDLEVBQTBELENBQUc7QUFwQ3JDOztRQUFiRixZLEdBQUFBLFksRUFqQmI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7a0JBMkNlQSxZIiwiZmlsZSI6IkZpbGVzQWRhcHRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qZXNsaW50IG5vLXVudXNlZC12YXJzOiBcIm9mZlwiKi9cbi8vIEZpbGVzIEFkYXB0ZXJcbi8vXG4vLyBBbGxvd3MgeW91IHRvIGNoYW5nZSB0aGUgZmlsZSBzdG9yYWdlIG1lY2hhbmlzbS5cbi8vXG4vLyBBZGFwdGVyIGNsYXNzZXMgbXVzdCBpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBmdW5jdGlvbnM6XG4vLyAqIGNyZWF0ZUZpbGUoZmlsZW5hbWUsIGRhdGEsIGNvbnRlbnRUeXBlKVxuLy8gKiBkZWxldGVGaWxlKGZpbGVuYW1lKVxuLy8gKiBnZXRGaWxlRGF0YShmaWxlbmFtZSlcbi8vICogZ2V0RmlsZUxvY2F0aW9uKGNvbmZpZywgZmlsZW5hbWUpXG4vL1xuLy8gRGVmYXVsdCBpcyBHcmlkU3RvcmVBZGFwdGVyLCB3aGljaCByZXF1aXJlcyBtb25nb1xuLy8gYW5kIGZvciB0aGUgQVBJIHNlcnZlciB0byBiZSB1c2luZyB0aGUgRGF0YWJhc2VDb250cm9sbGVyIHdpdGggTW9uZ29cbi8vIGRhdGFiYXNlIGFkYXB0ZXIuXG5cbmltcG9ydCB0eXBlIHsgQ29uZmlnIH0gZnJvbSAnLi4vLi4vQ29uZmlnJ1xuXG5leHBvcnQgY2xhc3MgRmlsZXNBZGFwdGVyIHtcblxuICAvKiBSZXNwb25zaWJsZSBmb3Igc3RvcmluZyB0aGUgZmlsZSBpbiBvcmRlciB0byBiZSByZXRyaWV2ZWQgbGF0ZXIgYnkgaXRzIGZpbGVuYW1lXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIHRoZSBmaWxlbmFtZSB0byBzYXZlXG4gICAqIEBwYXJhbSB7Kn0gZGF0YSAtIHRoZSBidWZmZXIgb2YgZGF0YSBmcm9tIHRoZSBmaWxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZW50VHlwZSAtIHRoZSBzdXBwb3NlZCBjb250ZW50VHlwZVxuICAgKiBAZGlzY3Vzc2lvbiB0aGUgY29udGVudFR5cGUgY2FuIGJlIHVuZGVmaW5lZCBpZiB0aGUgY29udHJvbGxlciB3YXMgbm90IGFibGUgdG8gZGV0ZXJtaW5lIGl0XG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHNob3VsZCBmYWlsIGlmIHRoZSBzdG9yYWdlIGRpZG4ndCBzdWNjZWVkXG4gICAqL1xuICBjcmVhdGVGaWxlKGZpbGVuYW1lOiBzdHJpbmcsIGRhdGEsIGNvbnRlbnRUeXBlOiBzdHJpbmcpOiBQcm9taXNlIHsgfVxuXG4gIC8qIFJlc3BvbnNpYmxlIGZvciBkZWxldGluZyB0aGUgc3BlY2lmaWVkIGZpbGVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gdGhlIGZpbGVuYW1lIHRvIGRlbGV0ZVxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCBzaG91bGQgZmFpbCBpZiB0aGUgZGVsZXRpb24gZGlkbid0IHN1Y2NlZWRcbiAgICovXG4gIGRlbGV0ZUZpbGUoZmlsZW5hbWU6IHN0cmluZyk6IFByb21pc2UgeyB9XG5cbiAgLyogUmVzcG9uc2libGUgZm9yIHJldHJpZXZpbmcgdGhlIGRhdGEgb2YgdGhlIHNwZWNpZmllZCBmaWxlXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIHRoZSBuYW1lIG9mIGZpbGUgdG8gcmV0cmlldmVcbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgc2hvdWxkIHBhc3Mgd2l0aCB0aGUgZmlsZSBkYXRhIG9yIGZhaWwgb24gZXJyb3JcbiAgICovXG4gIGdldEZpbGVEYXRhKGZpbGVuYW1lOiBzdHJpbmcpOiBQcm9taXNlPGFueT4geyB9XG5cbiAgLyogUmV0dXJucyBhbiBhYnNvbHV0ZSBVUkwgd2hlcmUgdGhlIGZpbGUgY2FuIGJlIGFjY2Vzc2VkXG4gICAqXG4gICAqIEBwYXJhbSB7Q29uZmlnfSBjb25maWcgLSBzZXJ2ZXIgY29uZmlndXJhdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWVcbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nfSBBYnNvbHV0ZSBVUkxcbiAgICovXG4gIGdldEZpbGVMb2NhdGlvbihjb25maWc6IENvbmZpZywgZmlsZW5hbWU6IHN0cmluZyk6IHN0cmluZyB7IH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRmlsZXNBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Files/GridStoreAdapter.js b/lib/Adapters/Files/GridStoreAdapter.js index 355f2779dc..c872fff25b 100644 --- a/lib/Adapters/Files/GridStoreAdapter.js +++ b/lib/Adapters/Files/GridStoreAdapter.js @@ -88,4 +88,5 @@ exports.GridStoreAdapter = GridStoreAdapter; /** // -disable-next -exports.default = GridStoreAdapter; \ No newline at end of file +exports.default = GridStoreAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9GaWxlcy9HcmlkU3RvcmVBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIkdyaWRTdG9yZUFkYXB0ZXIiLCJGaWxlc0FkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsIm1vbmdvRGF0YWJhc2VVUkkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsIl9kYXRhYmFzZVVSSSIsIl9jb25uZWN0IiwiX2Nvbm5lY3Rpb25Qcm9taXNlIiwiTW9uZ29DbGllbnQiLCJjb25uZWN0IiwidGhlbiIsImNsaWVudCIsImRiIiwicyIsIm9wdGlvbnMiLCJkYk5hbWUiLCJjcmVhdGVGaWxlIiwiZmlsZW5hbWUiLCJkYXRhIiwiZGF0YWJhc2UiLCJncmlkU3RvcmUiLCJHcmlkU3RvcmUiLCJvcGVuIiwid3JpdGUiLCJjbG9zZSIsImRlbGV0ZUZpbGUiLCJ1bmxpbmsiLCJnZXRGaWxlRGF0YSIsImV4aXN0IiwicmVhZCIsImdldEZpbGVMb2NhdGlvbiIsImNvbmZpZyIsIm1vdW50IiwiYXBwbGljYXRpb25JZCIsImVuY29kZVVSSUNvbXBvbmVudCIsImdldEZpbGVTdHJlYW0iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7Ozs7O0FBRU8sTUFBTUEsZ0JBQU4sU0FBK0JDLDBCQUEvQixDQUE0Qzs7QUFJakRDLGNBQVlDLG1CQUFtQkMsbUJBQVNDLGVBQXhDLEVBQXlEO0FBQ3ZEO0FBQ0EsU0FBS0MsWUFBTCxHQUFvQkgsZ0JBQXBCO0FBQ0Q7O0FBRURJLGFBQVc7QUFDVCxRQUFJLENBQUMsS0FBS0Msa0JBQVYsRUFBOEI7QUFDNUIsV0FBS0Esa0JBQUwsR0FBMEJDLHFCQUFZQyxPQUFaLENBQW9CLEtBQUtKLFlBQXpCLEVBQ3ZCSyxJQUR1QixDQUNqQkMsTUFBRCxJQUFZQSxPQUFPQyxFQUFQLENBQVVELE9BQU9FLENBQVAsQ0FBU0MsT0FBVCxDQUFpQkMsTUFBM0IsQ0FETSxDQUExQjtBQUVEO0FBQ0QsV0FBTyxLQUFLUixrQkFBWjtBQUNEOztBQUVEO0FBQ0E7QUFDQVMsYUFBV0MsUUFBWCxFQUE2QkMsSUFBN0IsRUFBbUM7QUFDakMsV0FBTyxLQUFLWixRQUFMLEdBQWdCSSxJQUFoQixDQUFzQlMsUUFBRCxJQUFjO0FBQ3hDLFlBQU1DLFlBQVksSUFBSUMsa0JBQUosQ0FBY0YsUUFBZCxFQUF3QkYsUUFBeEIsRUFBa0MsR0FBbEMsQ0FBbEI7QUFDQSxhQUFPRyxVQUFVRSxJQUFWLEVBQVA7QUFDRCxLQUhNLEVBR0paLElBSEksQ0FHQ1UsYUFBYTtBQUNuQixhQUFPQSxVQUFVRyxLQUFWLENBQWdCTCxJQUFoQixDQUFQO0FBQ0QsS0FMTSxFQUtKUixJQUxJLENBS0NVLGFBQWE7QUFDbkIsYUFBT0EsVUFBVUksS0FBVixFQUFQO0FBQ0QsS0FQTSxDQUFQO0FBUUQ7O0FBRURDLGFBQVdSLFFBQVgsRUFBNkI7QUFDM0IsV0FBTyxLQUFLWCxRQUFMLEdBQWdCSSxJQUFoQixDQUFxQlMsWUFBWTtBQUN0QyxZQUFNQyxZQUFZLElBQUlDLGtCQUFKLENBQWNGLFFBQWQsRUFBd0JGLFFBQXhCLEVBQWtDLEdBQWxDLENBQWxCO0FBQ0EsYUFBT0csVUFBVUUsSUFBVixFQUFQO0FBQ0QsS0FITSxFQUdKWixJQUhJLENBR0VVLFNBQUQsSUFBZTtBQUNyQixhQUFPQSxVQUFVTSxNQUFWLEVBQVA7QUFDRCxLQUxNLEVBS0poQixJQUxJLENBS0VVLFNBQUQsSUFBZTtBQUNyQixhQUFPQSxVQUFVSSxLQUFWLEVBQVA7QUFDRCxLQVBNLENBQVA7QUFRRDs7QUFFREcsY0FBWVYsUUFBWixFQUE4QjtBQUM1QixXQUFPLEtBQUtYLFFBQUwsR0FBZ0JJLElBQWhCLENBQXFCUyxZQUFZO0FBQ3RDLGFBQU9FLG1CQUFVTyxLQUFWLENBQWdCVCxRQUFoQixFQUEwQkYsUUFBMUIsRUFDSlAsSUFESSxDQUNDLE1BQU07QUFDVixjQUFNVSxZQUFZLElBQUlDLGtCQUFKLENBQWNGLFFBQWQsRUFBd0JGLFFBQXhCLEVBQWtDLEdBQWxDLENBQWxCO0FBQ0EsZUFBT0csVUFBVUUsSUFBVixFQUFQO0FBQ0QsT0FKSSxDQUFQO0FBS0QsS0FOTSxFQU1KWixJQU5JLENBTUNVLGFBQWE7QUFDbkIsYUFBT0EsVUFBVVMsSUFBVixFQUFQO0FBQ0QsS0FSTSxDQUFQO0FBU0Q7O0FBRURDLGtCQUFnQkMsTUFBaEIsRUFBd0JkLFFBQXhCLEVBQWtDO0FBQ2hDLFdBQVFjLE9BQU9DLEtBQVAsR0FBZSxTQUFmLEdBQTJCRCxPQUFPRSxhQUFsQyxHQUFrRCxHQUFsRCxHQUF3REMsbUJBQW1CakIsUUFBbkIsQ0FBaEU7QUFDRDs7QUFFRGtCLGdCQUFjbEIsUUFBZCxFQUFnQztBQUM5QixXQUFPLEtBQUtYLFFBQUwsR0FBZ0JJLElBQWhCLENBQXFCUyxZQUFZO0FBQ3RDLGFBQU9FLG1CQUFVTyxLQUFWLENBQWdCVCxRQUFoQixFQUEwQkYsUUFBMUIsRUFBb0NQLElBQXBDLENBQXlDLE1BQU07QUFDcEQsY0FBTVUsWUFBWSxJQUFJQyxrQkFBSixDQUFjRixRQUFkLEVBQXdCRixRQUF4QixFQUFrQyxHQUFsQyxDQUFsQjtBQUNBLGVBQU9HLFVBQVVFLElBQVYsRUFBUDtBQUNELE9BSE0sQ0FBUDtBQUlELEtBTE0sQ0FBUDtBQU1EO0FBaEVnRDs7UUFBdEN2QixnQixHQUFBQSxnQixFQWJiOzs7Ozs7OztBQVFBOztrQkF3RWVBLGdCIiwiZmlsZSI6IkdyaWRTdG9yZUFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiBHcmlkU3RvcmVBZGFwdGVyXG4gU3RvcmVzIGZpbGVzIGluIE1vbmdvIHVzaW5nIEdyaWRTdG9yZVxuIFJlcXVpcmVzIHRoZSBkYXRhYmFzZSBhZGFwdGVyIHRvIGJlIGJhc2VkIG9uIG1vbmdvY2xpZW50XG5cbiBAZmxvdyB3ZWFrXG4gKi9cblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgeyBNb25nb0NsaWVudCwgR3JpZFN0b3JlLCBEYn0gZnJvbSAnbW9uZ29kYic7XG5pbXBvcnQgeyBGaWxlc0FkYXB0ZXIgfSAgICAgICAgICAgICAgZnJvbSAnLi9GaWxlc0FkYXB0ZXInO1xuaW1wb3J0IGRlZmF1bHRzICAgICAgICAgICAgICAgICAgICAgIGZyb20gJy4uLy4uL2RlZmF1bHRzJztcblxuZXhwb3J0IGNsYXNzIEdyaWRTdG9yZUFkYXB0ZXIgZXh0ZW5kcyBGaWxlc0FkYXB0ZXIge1xuICBfZGF0YWJhc2VVUkk6IHN0cmluZztcbiAgX2Nvbm5lY3Rpb25Qcm9taXNlOiBQcm9taXNlPERiPjtcblxuICBjb25zdHJ1Y3Rvcihtb25nb0RhdGFiYXNlVVJJID0gZGVmYXVsdHMuRGVmYXVsdE1vbmdvVVJJKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLl9kYXRhYmFzZVVSSSA9IG1vbmdvRGF0YWJhc2VVUkk7XG4gIH1cblxuICBfY29ubmVjdCgpIHtcbiAgICBpZiAoIXRoaXMuX2Nvbm5lY3Rpb25Qcm9taXNlKSB7XG4gICAgICB0aGlzLl9jb25uZWN0aW9uUHJvbWlzZSA9IE1vbmdvQ2xpZW50LmNvbm5lY3QodGhpcy5fZGF0YWJhc2VVUkkpXG4gICAgICAgIC50aGVuKChjbGllbnQpID0+IGNsaWVudC5kYihjbGllbnQucy5vcHRpb25zLmRiTmFtZSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY29ubmVjdGlvblByb21pc2U7XG4gIH1cblxuICAvLyBGb3IgYSBnaXZlbiBjb25maWcgb2JqZWN0LCBmaWxlbmFtZSwgYW5kIGRhdGEsIHN0b3JlIGEgZmlsZVxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZVxuICBjcmVhdGVGaWxlKGZpbGVuYW1lOiBzdHJpbmcsIGRhdGEpIHtcbiAgICByZXR1cm4gdGhpcy5fY29ubmVjdCgpLnRoZW4oKGRhdGFiYXNlKSA9PiB7XG4gICAgICBjb25zdCBncmlkU3RvcmUgPSBuZXcgR3JpZFN0b3JlKGRhdGFiYXNlLCBmaWxlbmFtZSwgJ3cnKTtcbiAgICAgIHJldHVybiBncmlkU3RvcmUub3BlbigpO1xuICAgIH0pLnRoZW4oZ3JpZFN0b3JlID0+IHtcbiAgICAgIHJldHVybiBncmlkU3RvcmUud3JpdGUoZGF0YSk7XG4gICAgfSkudGhlbihncmlkU3RvcmUgPT4ge1xuICAgICAgcmV0dXJuIGdyaWRTdG9yZS5jbG9zZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgZGVsZXRlRmlsZShmaWxlbmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2Nvbm5lY3QoKS50aGVuKGRhdGFiYXNlID0+IHtcbiAgICAgIGNvbnN0IGdyaWRTdG9yZSA9IG5ldyBHcmlkU3RvcmUoZGF0YWJhc2UsIGZpbGVuYW1lLCAncicpO1xuICAgICAgcmV0dXJuIGdyaWRTdG9yZS5vcGVuKCk7XG4gICAgfSkudGhlbigoZ3JpZFN0b3JlKSA9PiB7XG4gICAgICByZXR1cm4gZ3JpZFN0b3JlLnVubGluaygpO1xuICAgIH0pLnRoZW4oKGdyaWRTdG9yZSkgPT4ge1xuICAgICAgcmV0dXJuIGdyaWRTdG9yZS5jbG9zZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0RmlsZURhdGEoZmlsZW5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9jb25uZWN0KCkudGhlbihkYXRhYmFzZSA9PiB7XG4gICAgICByZXR1cm4gR3JpZFN0b3JlLmV4aXN0KGRhdGFiYXNlLCBmaWxlbmFtZSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGdyaWRTdG9yZSA9IG5ldyBHcmlkU3RvcmUoZGF0YWJhc2UsIGZpbGVuYW1lLCAncicpO1xuICAgICAgICAgIHJldHVybiBncmlkU3RvcmUub3BlbigpO1xuICAgICAgICB9KTtcbiAgICB9KS50aGVuKGdyaWRTdG9yZSA9PiB7XG4gICAgICByZXR1cm4gZ3JpZFN0b3JlLnJlYWQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldEZpbGVMb2NhdGlvbihjb25maWcsIGZpbGVuYW1lKSB7XG4gICAgcmV0dXJuIChjb25maWcubW91bnQgKyAnL2ZpbGVzLycgKyBjb25maWcuYXBwbGljYXRpb25JZCArICcvJyArIGVuY29kZVVSSUNvbXBvbmVudChmaWxlbmFtZSkpO1xuICB9XG5cbiAgZ2V0RmlsZVN0cmVhbShmaWxlbmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2Nvbm5lY3QoKS50aGVuKGRhdGFiYXNlID0+IHtcbiAgICAgIHJldHVybiBHcmlkU3RvcmUuZXhpc3QoZGF0YWJhc2UsIGZpbGVuYW1lKS50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgZ3JpZFN0b3JlID0gbmV3IEdyaWRTdG9yZShkYXRhYmFzZSwgZmlsZW5hbWUsICdyJyk7XG4gICAgICAgIHJldHVybiBncmlkU3RvcmUub3BlbigpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgR3JpZFN0b3JlQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Logger/LoggerAdapter.js b/lib/Adapters/Logger/LoggerAdapter.js index 097955b9d4..d9504544ec 100644 --- a/lib/Adapters/Logger/LoggerAdapter.js +++ b/lib/Adapters/Logger/LoggerAdapter.js @@ -19,4 +19,5 @@ class LoggerAdapter { } exports.LoggerAdapter = LoggerAdapter; -exports.default = LoggerAdapter; \ No newline at end of file +exports.default = LoggerAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9Mb2dnZXIvTG9nZ2VyQWRhcHRlci5qcyJdLCJuYW1lcyI6WyJMb2dnZXJBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwibG9nIiwibGV2ZWwiLCJtZXNzYWdlIl0sIm1hcHBpbmdzIjoiOzs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFTyxNQUFNQSxhQUFOLENBQW9CO0FBQ3pCQyxjQUFZQyxPQUFaLEVBQXFCLENBQUU7QUFDdkJDLE1BQUlDLEtBQUosRUFBV0MsT0FBWCxFQUFvQixVQUFZLENBQUU7QUFGVDs7UUFBZEwsYSxHQUFBQSxhO2tCQUtFQSxhIiwiZmlsZSI6IkxvZ2dlckFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKmVzbGludCBuby11bnVzZWQtdmFyczogXCJvZmZcIiovXG4vLyBMb2dnZXIgQWRhcHRlclxuLy9cbi8vIEFsbG93cyB5b3UgdG8gY2hhbmdlIHRoZSBsb2dnZXIgbWVjaGFuaXNtXG4vL1xuLy8gQWRhcHRlciBjbGFzc2VzIG11c3QgaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgZnVuY3Rpb25zOlxuLy8gKiBsb2coKSB7fVxuLy8gKiBxdWVyeShvcHRpb25zLCBjYWxsYmFjaykgLyogb3B0aW9uYWwgKi9cbi8vIERlZmF1bHQgaXMgV2luc3RvbkxvZ2dlckFkYXB0ZXIuanNcblxuZXhwb3J0IGNsYXNzIExvZ2dlckFkYXB0ZXIge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7fVxuICBsb2cobGV2ZWwsIG1lc3NhZ2UsIC8qIG1ldGEgKi8pIHt9XG59XG5cbmV4cG9ydCBkZWZhdWx0IExvZ2dlckFkYXB0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Logger/WinstonLogger.js b/lib/Adapters/Logger/WinstonLogger.js index bda6f18ea8..25baf58959 100644 --- a/lib/Adapters/Logger/WinstonLogger.js +++ b/lib/Adapters/Logger/WinstonLogger.js @@ -122,4 +122,5 @@ function removeTransport(transport) { } exports.logger = logger; -exports.default = logger; \ No newline at end of file +exports.default = logger; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlci5qcyJdLCJuYW1lcyI6WyJjb25maWd1cmVMb2dnZXIiLCJhZGRUcmFuc3BvcnQiLCJyZW1vdmVUcmFuc3BvcnQiLCJsb2dnZXIiLCJ3aW5zdG9uIiwiTG9nZ2VyIiwiYWRkaXRpb25hbFRyYW5zcG9ydHMiLCJ1cGRhdGVUcmFuc3BvcnRzIiwib3B0aW9ucyIsInRyYW5zcG9ydHMiLCJPYmplY3QiLCJhc3NpZ24iLCJzaWxlbnQiLCJfIiwiaXNOdWxsIiwiZGlybmFtZSIsImlzVW5kZWZpbmVkIiwiRGFpbHlSb3RhdGVGaWxlIiwiZmlsZW5hbWUiLCJuYW1lIiwidGltZXN0YW1wIiwibGV2ZWwiLCJjb25zb2xlIiwiQ29uc29sZSIsImNvbG9yaXplIiwiZm9yRWFjaCIsInRyYW5zcG9ydCIsImNvbmZpZ3VyZSIsInZhbHVlcyIsImxvZ3NGb2xkZXIiLCJkZWZhdWx0cyIsImpzb25Mb2dzIiwibG9nTGV2ZWwiLCJ2ZXJib3NlIiwicGF0aCIsImlzQWJzb2x1dGUiLCJyZXNvbHZlIiwicHJvY2VzcyIsImN3ZCIsImZzIiwibWtkaXJTeW5jIiwiZSIsImpzb24iLCJzdHJpbmdpZnkiLCJwdXNoIiwidHJhbnNwb3J0TmFtZSIsInJlbW92ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7O1FBK0NnQkEsZSxHQUFBQSxlO1FBaUNBQyxZLEdBQUFBLFk7UUFLQUMsZSxHQUFBQSxlOztBQXJGaEI7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFQSxNQUFNQyxTQUFTLElBQUlDLGtCQUFRQyxNQUFaLEVBQWY7QUFDQSxNQUFNQyx1QkFBdUIsRUFBN0I7O0FBRUEsU0FBU0MsZ0JBQVQsQ0FBMEJDLE9BQTFCLEVBQW1DO0FBQ2pDLFFBQU1DLGFBQWFDLE9BQU9DLE1BQVAsQ0FBYyxFQUFkLEVBQWtCUixPQUFPTSxVQUF6QixDQUFuQjtBQUNBLE1BQUlELE9BQUosRUFB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VVAsSUFBM0U7QUFDQSxRQUFNVixhQUFhQyxPQUFPQyxNQUFQLENBQWMsRUFBZCxFQUFrQlIsT0FBT00sVUFBekIsQ0FBbkI7QUFDQSxTQUFPQSxXQUFXb0MsYUFBWCxDQUFQO0FBQ0ExQyxTQUFPd0IsU0FBUCxDQUFpQjtBQUNmbEIsZ0JBQVlJLGlCQUFFZSxNQUFGLENBQVNuQixVQUFUO0FBREcsR0FBakI7QUFHQUksbUJBQUVpQyxNQUFGLENBQVN4QyxvQkFBVCxFQUFnQ29CLFNBQUQsSUFBZTtBQUM1QyxXQUFPQSxVQUFVUCxJQUFWLEtBQW1CMEIsYUFBMUI7QUFDRCxHQUZEO0FBR0Q7O1FBRVExQyxNLEdBQUFBLE07a0JBQ01BLE0iLCJmaWxlIjoiV2luc3RvbkxvZ2dlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB3aW5zdG9uIGZyb20gJ3dpbnN0b24nO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IERhaWx5Um90YXRlRmlsZSBmcm9tICd3aW5zdG9uLWRhaWx5LXJvdGF0ZS1maWxlJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgZGVmYXVsdHMgIGZyb20gJy4uLy4uL2RlZmF1bHRzJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IHdpbnN0b24uTG9nZ2VyKCk7XG5jb25zdCBhZGRpdGlvbmFsVHJhbnNwb3J0cyA9IFtdO1xuXG5mdW5jdGlvbiB1cGRhdGVUcmFuc3BvcnRzKG9wdGlvbnMpIHtcbiAgY29uc3QgdHJhbnNwb3J0cyA9IE9iamVjdC5hc3NpZ24oe30sIGxvZ2dlci50cmFuc3BvcnRzKTtcbiAgaWYgKG9wdGlvbnMpIHtcbiAgICBjb25zdCBzaWxlbnQgPSBvcHRpb25zLnNpbGVudDtcbiAgICBkZWxldGUgb3B0aW9ucy5zaWxlbnQ7XG4gICAgaWYgKF8uaXNOdWxsKG9wdGlvbnMuZGlybmFtZSkpIHtcbiAgICAgIGRlbGV0ZSB0cmFuc3BvcnRzWydwYXJzZS1zZXJ2ZXInXTtcbiAgICAgIGRlbGV0ZSB0cmFuc3BvcnRzWydwYXJzZS1zZXJ2ZXItZXJyb3InXTtcbiAgICB9IGVsc2UgaWYgKCFfLmlzVW5kZWZpbmVkKG9wdGlvbnMuZGlybmFtZSkpIHtcbiAgICAgIHRyYW5zcG9ydHNbJ3BhcnNlLXNlcnZlciddID0gbmV3IChEYWlseVJvdGF0ZUZpbGUpKFxuICAgICAgICBPYmplY3QuYXNzaWduKHt9LCB7XG4gICAgICAgICAgZmlsZW5hbWU6ICdwYXJzZS1zZXJ2ZXIuaW5mbycsXG4gICAgICAgICAgbmFtZTogJ3BhcnNlLXNlcnZlcicsXG4gICAgICAgIH0sIG9wdGlvbnMsIHsgdGltZXN0YW1wOiB0cnVlIH0pKTtcbiAgICAgIHRyYW5zcG9ydHNbJ3BhcnNlLXNlcnZlci1lcnJvciddID0gbmV3IChEYWlseVJvdGF0ZUZpbGUpKFxuICAgICAgICBPYmplY3QuYXNzaWduKHt9LCB7XG4gICAgICAgICAgZmlsZW5hbWU6ICdwYXJzZS1zZXJ2ZXIuZXJyJyxcbiAgICAgICAgICBuYW1lOiAncGFyc2Utc2VydmVyLWVycm9yJyxcbiAgICAgICAgfSwgb3B0aW9ucywgeyBsZXZlbDogJ2Vycm9yJywgdGltZXN0YW1wOiB0cnVlICB9KSk7XG4gICAgfVxuXG4gICAgdHJhbnNwb3J0cy5jb25zb2xlID0gbmV3ICh3aW5zdG9uLnRyYW5zcG9ydHMuQ29uc29sZSkoXG4gICAgICBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgY29sb3JpemU6IHRydWUsXG4gICAgICAgIG5hbWU6ICdjb25zb2xlJyxcbiAgICAgICAgc2lsZW50XG4gICAgICB9LCBvcHRpb25zKSk7XG4gIH1cbiAgLy8gTW91bnQgdGhlIGFkZGl0aW9uYWwgdHJhbnNwb3J0c1xuICBhZGRpdGlvbmFsVHJhbnNwb3J0cy5mb3JFYWNoKCh0cmFuc3BvcnQpID0+IHtcbiAgICB0cmFuc3BvcnRzW3RyYW5zcG9ydC5uYW1lXSA9IHRyYW5zcG9ydDtcbiAgfSk7XG4gIGxvZ2dlci5jb25maWd1cmUoe1xuICAgIHRyYW5zcG9ydHM6IF8udmFsdWVzKHRyYW5zcG9ydHMpXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29uZmlndXJlTG9nZ2VyKHtcbiAgbG9nc0ZvbGRlciA9IGRlZmF1bHRzLmxvZ3NGb2xkZXIsXG4gIGpzb25Mb2dzID0gZGVmYXVsdHMuanNvbkxvZ3MsXG4gIGxvZ0xldmVsID0gd2luc3Rvbi5sZXZlbCxcbiAgdmVyYm9zZSA9IGRlZmF1bHRzLnZlcmJvc2UsXG4gIHNpbGVudCA9IGRlZmF1bHRzLnNpbGVudCB9ID0ge30pIHtcblxuICBpZiAodmVyYm9zZSkge1xuICAgIGxvZ0xldmVsID0gJ3ZlcmJvc2UnO1xuICB9XG5cbiAgd2luc3Rvbi5sZXZlbCA9IGxvZ0xldmVsO1xuICBjb25zdCBvcHRpb25zID0ge307XG5cbiAgaWYgKGxvZ3NGb2xkZXIpIHtcbiAgICBpZiAoIXBhdGguaXNBYnNvbHV0ZShsb2dzRm9sZGVyKSkge1xuICAgICAgbG9nc0ZvbGRlciA9IHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCBsb2dzRm9sZGVyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGZzLm1rZGlyU3luYyhsb2dzRm9sZGVyKTtcbiAgICB9IGNhdGNoIChlKSB7IC8qICovIH1cbiAgfVxuICBvcHRpb25zLmRpcm5hbWUgPSBsb2dzRm9sZGVyO1xuICBvcHRpb25zLmxldmVsID0gbG9nTGV2ZWw7XG4gIG9wdGlvbnMuc2lsZW50ID0gc2lsZW50O1xuXG4gIGlmIChqc29uTG9ncykge1xuICAgIG9wdGlvbnMuanNvbiA9IHRydWU7XG4gICAgb3B0aW9ucy5zdHJpbmdpZnkgPSB0cnVlO1xuICB9XG4gIHVwZGF0ZVRyYW5zcG9ydHMob3B0aW9ucyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRUcmFuc3BvcnQodHJhbnNwb3J0KSB7XG4gIGFkZGl0aW9uYWxUcmFuc3BvcnRzLnB1c2godHJhbnNwb3J0KTtcbiAgdXBkYXRlVHJhbnNwb3J0cygpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlVHJhbnNwb3J0KHRyYW5zcG9ydCkge1xuICBjb25zdCB0cmFuc3BvcnROYW1lID0gdHlwZW9mIHRyYW5zcG9ydCA9PSAnc3RyaW5nJyA/IHRyYW5zcG9ydCA6IHRyYW5zcG9ydC5uYW1lO1xuICBjb25zdCB0cmFuc3BvcnRzID0gT2JqZWN0LmFzc2lnbih7fSwgbG9nZ2VyLnRyYW5zcG9ydHMpO1xuICBkZWxldGUgdHJhbnNwb3J0c1t0cmFuc3BvcnROYW1lXTtcbiAgbG9nZ2VyLmNvbmZpZ3VyZSh7XG4gICAgdHJhbnNwb3J0czogXy52YWx1ZXModHJhbnNwb3J0cylcbiAgfSk7XG4gIF8ucmVtb3ZlKGFkZGl0aW9uYWxUcmFuc3BvcnRzLCAodHJhbnNwb3J0KSA9PiB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydC5uYW1lID09PSB0cmFuc3BvcnROYW1lO1xuICB9KTtcbn1cblxuZXhwb3J0IHsgbG9nZ2VyIH07XG5leHBvcnQgZGVmYXVsdCBsb2dnZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Logger/WinstonLoggerAdapter.js b/lib/Adapters/Logger/WinstonLoggerAdapter.js index 0ea0a02cf7..13b1e7dff2 100644 --- a/lib/Adapters/Logger/WinstonLoggerAdapter.js +++ b/lib/Adapters/Logger/WinstonLoggerAdapter.js @@ -68,4 +68,5 @@ class WinstonLoggerAdapter extends _LoggerAdapter.LoggerAdapter { } exports.WinstonLoggerAdapter = WinstonLoggerAdapter; -exports.default = WinstonLoggerAdapter; \ No newline at end of file +exports.default = WinstonLoggerAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlckFkYXB0ZXIuanMiXSwibmFtZXMiOlsiTUlMTElTRUNPTkRTX0lOX0FfREFZIiwiV2luc3RvbkxvZ2dlckFkYXB0ZXIiLCJMb2dnZXJBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwibG9nIiwibG9nZ2VyIiwiYXBwbHkiLCJhcmd1bWVudHMiLCJhZGRUcmFuc3BvcnQiLCJ0cmFuc3BvcnQiLCJxdWVyeSIsImNhbGxiYWNrIiwiZnJvbSIsIkRhdGUiLCJub3ciLCJ1bnRpbCIsImxpbWl0Iiwic2l6ZSIsIm9yZGVyIiwibGV2ZWwiLCJxdWVyeU9wdGlvbnMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsImVyciIsInJlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUVBLE1BQU1BLHdCQUF3QixLQUFLLEVBQUwsR0FBVSxFQUFWLEdBQWUsSUFBN0M7O0FBRU8sTUFBTUMsb0JBQU4sU0FBbUNDLDRCQUFuQyxDQUFpRDtBQUN0REMsY0FBWUMsT0FBWixFQUFxQjtBQUNuQjtBQUNBLFFBQUlBLE9BQUosRUFBYTtBQUNYLDBDQUFnQkEsT0FBaEI7QUFDRDtBQUNGOztBQUVEQyxRQUFNO0FBQ0osV0FBT0Msc0JBQU9ELEdBQVAsQ0FBV0UsS0FBWCxDQUFpQkQscUJBQWpCLEVBQXlCRSxTQUF6QixDQUFQO0FBQ0Q7O0FBRURDLGVBQWFDLFNBQWIsRUFBd0I7QUFDdEI7QUFDQTtBQUNBO0FBQ0EscUNBQWFBLFNBQWI7QUFDRDs7QUFFRDtBQUNBQyxRQUFNUCxPQUFOLEVBQWVRLFdBQVcsTUFBTSxDQUFFLENBQWxDLEVBQW9DO0FBQ2xDLFFBQUksQ0FBQ1IsT0FBTCxFQUFjO0FBQ1pBLGdCQUFVLEVBQVY7QUFDRDtBQUNEO0FBQ0EsVUFBTVMsT0FBT1QsUUFBUVMsSUFBUixJQUFnQixJQUFJQyxJQUFKLENBQVNBLEtBQUtDLEdBQUwsS0FBYyxJQUFJZixxQkFBM0IsQ0FBN0I7QUFDQSxVQUFNZ0IsUUFBUVosUUFBUVksS0FBUixJQUFpQixJQUFJRixJQUFKLEVBQS9CO0FBQ0EsVUFBTUcsUUFBUWIsUUFBUWMsSUFBUixJQUFnQixFQUE5QjtBQUNBLFVBQU1DLFFBQVFmLFFBQVFlLEtBQVIsSUFBaUIsTUFBL0I7QUFDQSxVQUFNQyxRQUFRaEIsUUFBUWdCLEtBQVIsSUFBaUIsTUFBL0I7O0FBRUEsVUFBTUMsZUFBZTtBQUNuQlIsVUFEbUI7QUFFbkJHLFdBRm1CO0FBR25CQyxXQUhtQjtBQUluQkU7QUFKbUIsS0FBckI7O0FBT0EsV0FBTyxJQUFJRyxPQUFKLENBQVksQ0FBQ0MsT0FBRCxFQUFVQyxNQUFWLEtBQXFCO0FBQ3RDbEIsNEJBQU9LLEtBQVAsQ0FBYVUsWUFBYixFQUEyQixDQUFDSSxHQUFELEVBQU1DLEdBQU4sS0FBYztBQUN2QyxZQUFJRCxHQUFKLEVBQVM7QUFDUGIsbUJBQVNhLEdBQVQ7QUFDQSxpQkFBT0QsT0FBT0MsR0FBUCxDQUFQO0FBQ0Q7QUFDRCxZQUFJTCxTQUFTLE9BQWIsRUFBc0I7QUFDcEJSLG1CQUFTYyxJQUFJLG9CQUFKLENBQVQ7QUFDQUgsa0JBQVFHLElBQUksb0JBQUosQ0FBUjtBQUNELFNBSEQsTUFHTztBQUNMZCxtQkFBU2MsSUFBSSxjQUFKLENBQVQ7QUFDQUgsa0JBQVFHLElBQUksY0FBSixDQUFSO0FBQ0Q7QUFDRixPQVpEO0FBYUQsS0FkTSxDQUFQO0FBZUQ7QUFyRHFEOztRQUEzQ3pCLG9CLEdBQUFBLG9CO2tCQXdERUEsb0IiLCJmaWxlIjoiV2luc3RvbkxvZ2dlckFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMb2dnZXJBZGFwdGVyIH0gZnJvbSAnLi9Mb2dnZXJBZGFwdGVyJztcbmltcG9ydCB7IGxvZ2dlciwgYWRkVHJhbnNwb3J0LCBjb25maWd1cmVMb2dnZXIgfSBmcm9tICcuL1dpbnN0b25Mb2dnZXInO1xuXG5jb25zdCBNSUxMSVNFQ09ORFNfSU5fQV9EQVkgPSAyNCAqIDYwICogNjAgKiAxMDAwO1xuXG5leHBvcnQgY2xhc3MgV2luc3RvbkxvZ2dlckFkYXB0ZXIgZXh0ZW5kcyBMb2dnZXJBZGFwdGVyIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIHN1cGVyKCk7XG4gICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgIGNvbmZpZ3VyZUxvZ2dlcihvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBsb2coKSB7XG4gICAgcmV0dXJuIGxvZ2dlci5sb2cuYXBwbHkobG9nZ2VyLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgYWRkVHJhbnNwb3J0KHRyYW5zcG9ydCkge1xuICAgIC8vIE5vdGUgdGhhdCB0aGlzIGlzIGNhbGxpbmcgYWRkVHJhbnNwb3J0XG4gICAgLy8gZnJvbSBsb2dnZXIuICBTZWUgaW1wb3J0IC0gY29uZnVzaW5nLlxuICAgIC8vIGJ1dCB0aGlzIGlzIG5vdCByZWN1cnNpdmUuXG4gICAgYWRkVHJhbnNwb3J0KHRyYW5zcG9ydCk7XG4gIH1cblxuICAvLyBjdXN0b20gcXVlcnkgYXMgd2luc3RvbiBpcyBjdXJyZW50bHkgbGltaXRlZFxuICBxdWVyeShvcHRpb25zLCBjYWxsYmFjayA9ICgpID0+IHt9KSB7XG4gICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICBvcHRpb25zID0ge307XG4gICAgfVxuICAgIC8vIGRlZmF1bHRzIHRvIDcgZGF5cyBwcmlvclxuICAgIGNvbnN0IGZyb20gPSBvcHRpb25zLmZyb20gfHwgbmV3IERhdGUoRGF0ZS5ub3coKSAtICg3ICogTUlMTElTRUNPTkRTX0lOX0FfREFZKSk7XG4gICAgY29uc3QgdW50aWwgPSBvcHRpb25zLnVudGlsIHx8IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgbGltaXQgPSBvcHRpb25zLnNpemUgfHwgMTA7XG4gICAgY29uc3Qgb3JkZXIgPSBvcHRpb25zLm9yZGVyIHx8ICdkZXNjJztcbiAgICBjb25zdCBsZXZlbCA9IG9wdGlvbnMubGV2ZWwgfHwgJ2luZm8nO1xuXG4gICAgY29uc3QgcXVlcnlPcHRpb25zID0ge1xuICAgICAgZnJvbSxcbiAgICAgIHVudGlsLFxuICAgICAgbGltaXQsXG4gICAgICBvcmRlclxuICAgIH07XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbG9nZ2VyLnF1ZXJ5KHF1ZXJ5T3B0aW9ucywgKGVyciwgcmVzKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGV2ZWwgPT0gJ2Vycm9yJykge1xuICAgICAgICAgIGNhbGxiYWNrKHJlc1sncGFyc2Utc2VydmVyLWVycm9yJ10pO1xuICAgICAgICAgIHJlc29sdmUocmVzWydwYXJzZS1zZXJ2ZXItZXJyb3InXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2FsbGJhY2socmVzWydwYXJzZS1zZXJ2ZXInXSk7XG4gICAgICAgICAgcmVzb2x2ZShyZXNbJ3BhcnNlLXNlcnZlciddKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBXaW5zdG9uTG9nZ2VyQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/MessageQueue/EventEmitterMQ.js b/lib/Adapters/MessageQueue/EventEmitterMQ.js index c25e1c2076..8213076ae7 100644 --- a/lib/Adapters/MessageQueue/EventEmitterMQ.js +++ b/lib/Adapters/MessageQueue/EventEmitterMQ.js @@ -69,4 +69,5 @@ const EventEmitterMQ = { createSubscriber }; -exports.EventEmitterMQ = EventEmitterMQ; \ No newline at end of file +exports.EventEmitterMQ = EventEmitterMQ; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9NZXNzYWdlUXVldWUvRXZlbnRFbWl0dGVyTVEuanMiXSwibmFtZXMiOlsiZW1pdHRlciIsImV2ZW50cyIsIkV2ZW50RW1pdHRlciIsInN1YnNjcmlwdGlvbnMiLCJNYXAiLCJ1bnN1YnNjcmliZSIsImNoYW5uZWwiLCJoYXMiLCJyZW1vdmVMaXN0ZW5lciIsImdldCIsImRlbGV0ZSIsIlB1Ymxpc2hlciIsImNvbnN0cnVjdG9yIiwicHVibGlzaCIsIm1lc3NhZ2UiLCJlbWl0IiwiQ29uc3VtZXIiLCJzdWJzY3JpYmUiLCJoYW5kbGVyIiwic2V0Iiwib24iLCJjcmVhdGVQdWJsaXNoZXIiLCJjcmVhdGVTdWJzY3JpYmVyIiwiRXZlbnRFbWl0dGVyTVEiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7O0FBRUEsTUFBTUEsVUFBVSxJQUFJQyxpQkFBT0MsWUFBWCxFQUFoQjtBQUNBLE1BQU1DLGdCQUFnQixJQUFJQyxHQUFKLEVBQXRCOztBQUVBLFNBQVNDLFdBQVQsQ0FBcUJDLE9BQXJCLEVBQXNDO0FBQ3BDLE1BQUksQ0FBQ0gsY0FBY0ksR0FBZCxDQUFrQkQsT0FBbEIsQ0FBTCxFQUFpQztBQUMvQjtBQUNBO0FBQ0Q7QUFDRDtBQUNBTixVQUFRUSxjQUFSLENBQXVCRixPQUF2QixFQUFnQ0gsY0FBY00sR0FBZCxDQUFrQkgsT0FBbEIsQ0FBaEM7QUFDQUgsZ0JBQWNPLE1BQWQsQ0FBcUJKLE9BQXJCO0FBQ0Q7O0FBRUQsTUFBTUssU0FBTixDQUFnQjs7QUFHZEMsY0FBWVosT0FBWixFQUEwQjtBQUN4QixTQUFLQSxPQUFMLEdBQWVBLE9BQWY7QUFDRDs7QUFFRGEsVUFBUVAsT0FBUixFQUF5QlEsT0FBekIsRUFBZ0Q7QUFDOUMsU0FBS2QsT0FBTCxDQUFhZSxJQUFiLENBQWtCVCxPQUFsQixFQUEyQlEsT0FBM0I7QUFDRDtBQVRhOztBQVloQixNQUFNRSxRQUFOLFNBQXVCZixpQkFBT0MsWUFBOUIsQ0FBMkM7O0FBR3pDVSxjQUFZWixPQUFaLEVBQTBCO0FBQ3hCO0FBQ0EsU0FBS0EsT0FBTCxHQUFlQSxPQUFmO0FBQ0Q7O0FBRURpQixZQUFVWCxPQUFWLEVBQWlDO0FBQy9CRCxnQkFBWUMsT0FBWjtBQUNBLFVBQU1ZLFVBQVdKLE9BQUQsSUFBYTtBQUMzQixXQUFLQyxJQUFMLENBQVUsU0FBVixFQUFxQlQsT0FBckIsRUFBOEJRLE9BQTlCO0FBQ0QsS0FGRDtBQUdBWCxrQkFBY2dCLEdBQWQsQ0FBa0JiLE9BQWxCLEVBQTJCWSxPQUEzQjtBQUNBLFNBQUtsQixPQUFMLENBQWFvQixFQUFiLENBQWdCZCxPQUFoQixFQUF5QlksT0FBekI7QUFDRDs7QUFFRGIsY0FBWUMsT0FBWixFQUFtQztBQUNqQ0QsZ0JBQVlDLE9BQVo7QUFDRDtBQW5Cd0M7O0FBc0IzQyxTQUFTZSxlQUFULEdBQWdDO0FBQzlCLFNBQU8sSUFBSVYsU0FBSixDQUFjWCxPQUFkLENBQVA7QUFDRDs7QUFFRCxTQUFTc0IsZ0JBQVQsR0FBaUM7QUFDL0IsU0FBTyxJQUFJTixRQUFKLENBQWFoQixPQUFiLENBQVA7QUFDRDs7QUFFRCxNQUFNdUIsaUJBQWlCO0FBQ3JCRixpQkFEcUI7QUFFckJDO0FBRnFCLENBQXZCOztRQU1FQyxjLEdBQUFBLGMiLCJmaWxlIjoiRXZlbnRFbWl0dGVyTVEuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZXZlbnRzIGZyb20gJ2V2ZW50cyc7XG5cbmNvbnN0IGVtaXR0ZXIgPSBuZXcgZXZlbnRzLkV2ZW50RW1pdHRlcigpO1xuY29uc3Qgc3Vic2NyaXB0aW9ucyA9IG5ldyBNYXAoKTtcblxuZnVuY3Rpb24gdW5zdWJzY3JpYmUoY2hhbm5lbDogc3RyaW5nKSB7XG4gIGlmICghc3Vic2NyaXB0aW9ucy5oYXMoY2hhbm5lbCkpIHtcbiAgICAvL2NvbnNvbGUubG9nKCdObyBjaGFubmVsIHRvIHVuc3ViIGZyb20nKTtcbiAgICByZXR1cm47XG4gIH1cbiAgLy9jb25zb2xlLmxvZygndW5zdWIgJywgY2hhbm5lbCk7XG4gIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoY2hhbm5lbCwgc3Vic2NyaXB0aW9ucy5nZXQoY2hhbm5lbCkpO1xuICBzdWJzY3JpcHRpb25zLmRlbGV0ZShjaGFubmVsKTtcbn1cblxuY2xhc3MgUHVibGlzaGVyIHtcbiAgZW1pdHRlcjogYW55O1xuXG4gIGNvbnN0cnVjdG9yKGVtaXR0ZXI6IGFueSkge1xuICAgIHRoaXMuZW1pdHRlciA9IGVtaXR0ZXI7XG4gIH1cblxuICBwdWJsaXNoKGNoYW5uZWw6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5lbWl0dGVyLmVtaXQoY2hhbm5lbCwgbWVzc2FnZSk7XG4gIH1cbn1cblxuY2xhc3MgQ29uc3VtZXIgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgZW1pdHRlcjogYW55O1xuXG4gIGNvbnN0cnVjdG9yKGVtaXR0ZXI6IGFueSkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5lbWl0dGVyID0gZW1pdHRlcjtcbiAgfVxuXG4gIHN1YnNjcmliZShjaGFubmVsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB1bnN1YnNjcmliZShjaGFubmVsKTtcbiAgICBjb25zdCBoYW5kbGVyID0gKG1lc3NhZ2UpID0+IHtcbiAgICAgIHRoaXMuZW1pdCgnbWVzc2FnZScsIGNoYW5uZWwsIG1lc3NhZ2UpO1xuICAgIH1cbiAgICBzdWJzY3JpcHRpb25zLnNldChjaGFubmVsLCBoYW5kbGVyKTtcbiAgICB0aGlzLmVtaXR0ZXIub24oY2hhbm5lbCwgaGFuZGxlcik7XG4gIH1cblxuICB1bnN1YnNjcmliZShjaGFubmVsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB1bnN1YnNjcmliZShjaGFubmVsKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVQdWJsaXNoZXIoKTogYW55IHtcbiAgcmV0dXJuIG5ldyBQdWJsaXNoZXIoZW1pdHRlcik7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVN1YnNjcmliZXIoKTogYW55IHtcbiAgcmV0dXJuIG5ldyBDb25zdW1lcihlbWl0dGVyKTtcbn1cblxuY29uc3QgRXZlbnRFbWl0dGVyTVEgPSB7XG4gIGNyZWF0ZVB1Ymxpc2hlcixcbiAgY3JlYXRlU3Vic2NyaWJlclxufVxuXG5leHBvcnQge1xuICBFdmVudEVtaXR0ZXJNUVxufVxuIl19 \ No newline at end of file diff --git a/lib/Adapters/PubSub/EventEmitterPubSub.js b/lib/Adapters/PubSub/EventEmitterPubSub.js index b878353d74..57e2e8a915 100644 --- a/lib/Adapters/PubSub/EventEmitterPubSub.js +++ b/lib/Adapters/PubSub/EventEmitterPubSub.js @@ -62,4 +62,5 @@ const EventEmitterPubSub = { createSubscriber }; -exports.EventEmitterPubSub = EventEmitterPubSub; \ No newline at end of file +exports.EventEmitterPubSub = EventEmitterPubSub; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9QdWJTdWIvRXZlbnRFbWl0dGVyUHViU3ViLmpzIl0sIm5hbWVzIjpbImVtaXR0ZXIiLCJldmVudHMiLCJFdmVudEVtaXR0ZXIiLCJQdWJsaXNoZXIiLCJjb25zdHJ1Y3RvciIsInB1Ymxpc2giLCJjaGFubmVsIiwibWVzc2FnZSIsImVtaXQiLCJTdWJzY3JpYmVyIiwic3Vic2NyaXB0aW9ucyIsIk1hcCIsInN1YnNjcmliZSIsImhhbmRsZXIiLCJzZXQiLCJvbiIsInVuc3Vic2NyaWJlIiwiaGFzIiwicmVtb3ZlTGlzdGVuZXIiLCJnZXQiLCJkZWxldGUiLCJjcmVhdGVQdWJsaXNoZXIiLCJjcmVhdGVTdWJzY3JpYmVyIiwiRXZlbnRFbWl0dGVyUHViU3ViIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7OztBQUVBLE1BQU1BLFVBQVUsSUFBSUMsaUJBQU9DLFlBQVgsRUFBaEI7O0FBRUEsTUFBTUMsU0FBTixDQUFnQjs7QUFHZEMsY0FBWUosT0FBWixFQUEwQjtBQUN4QixTQUFLQSxPQUFMLEdBQWVBLE9BQWY7QUFDRDs7QUFFREssVUFBUUMsT0FBUixFQUF5QkMsT0FBekIsRUFBZ0Q7QUFDOUMsU0FBS1AsT0FBTCxDQUFhUSxJQUFiLENBQWtCRixPQUFsQixFQUEyQkMsT0FBM0I7QUFDRDtBQVRhOztBQVloQixNQUFNRSxVQUFOLFNBQXlCUixpQkFBT0MsWUFBaEMsQ0FBNkM7O0FBSTNDRSxjQUFZSixPQUFaLEVBQTBCO0FBQ3hCO0FBQ0EsU0FBS0EsT0FBTCxHQUFlQSxPQUFmO0FBQ0EsU0FBS1UsYUFBTCxHQUFxQixJQUFJQyxHQUFKLEVBQXJCO0FBQ0Q7O0FBRURDLFlBQVVOLE9BQVYsRUFBaUM7QUFDL0IsVUFBTU8sVUFBV04sT0FBRCxJQUFhO0FBQzNCLFdBQUtDLElBQUwsQ0FBVSxTQUFWLEVBQXFCRixPQUFyQixFQUE4QkMsT0FBOUI7QUFDRCxLQUZEO0FBR0EsU0FBS0csYUFBTCxDQUFtQkksR0FBbkIsQ0FBdUJSLE9BQXZCLEVBQWdDTyxPQUFoQztBQUNBLFNBQUtiLE9BQUwsQ0FBYWUsRUFBYixDQUFnQlQsT0FBaEIsRUFBeUJPLE9BQXpCO0FBQ0Q7O0FBRURHLGNBQVlWLE9BQVosRUFBbUM7QUFDakMsUUFBSSxDQUFDLEtBQUtJLGFBQUwsQ0FBbUJPLEdBQW5CLENBQXVCWCxPQUF2QixDQUFMLEVBQXNDO0FBQ3BDO0FBQ0Q7QUFDRCxTQUFLTixPQUFMLENBQWFrQixjQUFiLENBQTRCWixPQUE1QixFQUFxQyxLQUFLSSxhQUFMLENBQW1CUyxHQUFuQixDQUF1QmIsT0FBdkIsQ0FBckM7QUFDQSxTQUFLSSxhQUFMLENBQW1CVSxNQUFuQixDQUEwQmQsT0FBMUI7QUFDRDtBQXhCMEM7O0FBMkI3QyxTQUFTZSxlQUFULEdBQWdDO0FBQzlCLFNBQU8sSUFBSWxCLFNBQUosQ0FBY0gsT0FBZCxDQUFQO0FBQ0Q7O0FBRUQsU0FBU3NCLGdCQUFULEdBQWlDO0FBQy9CLFNBQU8sSUFBSWIsVUFBSixDQUFlVCxPQUFmLENBQVA7QUFDRDs7QUFFRCxNQUFNdUIscUJBQXFCO0FBQ3pCRixpQkFEeUI7QUFFekJDO0FBRnlCLENBQTNCOztRQU1FQyxrQixHQUFBQSxrQiIsImZpbGUiOiJFdmVudEVtaXR0ZXJQdWJTdWIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZXZlbnRzIGZyb20gJ2V2ZW50cyc7XG5cbmNvbnN0IGVtaXR0ZXIgPSBuZXcgZXZlbnRzLkV2ZW50RW1pdHRlcigpO1xuXG5jbGFzcyBQdWJsaXNoZXIge1xuICBlbWl0dGVyOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoZW1pdHRlcjogYW55KSB7XG4gICAgdGhpcy5lbWl0dGVyID0gZW1pdHRlcjtcbiAgfVxuXG4gIHB1Ymxpc2goY2hhbm5lbDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmVtaXR0ZXIuZW1pdChjaGFubmVsLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5jbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgZXZlbnRzLkV2ZW50RW1pdHRlciB7XG4gIGVtaXR0ZXI6IGFueTtcbiAgc3Vic2NyaXB0aW9uczogYW55O1xuXG4gIGNvbnN0cnVjdG9yKGVtaXR0ZXI6IGFueSkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5lbWl0dGVyID0gZW1pdHRlcjtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBzdWJzY3JpYmUoY2hhbm5lbDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgaGFuZGxlciA9IChtZXNzYWdlKSA9PiB7XG4gICAgICB0aGlzLmVtaXQoJ21lc3NhZ2UnLCBjaGFubmVsLCBtZXNzYWdlKTtcbiAgICB9XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnNldChjaGFubmVsLCBoYW5kbGVyKTtcbiAgICB0aGlzLmVtaXR0ZXIub24oY2hhbm5lbCwgaGFuZGxlcik7XG4gIH1cblxuICB1bnN1YnNjcmliZShjaGFubmVsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc3Vic2NyaXB0aW9ucy5oYXMoY2hhbm5lbCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5lbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGNoYW5uZWwsIHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoY2hhbm5lbCkpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5kZWxldGUoY2hhbm5lbCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlUHVibGlzaGVyKCk6IGFueSB7XG4gIHJldHVybiBuZXcgUHVibGlzaGVyKGVtaXR0ZXIpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVTdWJzY3JpYmVyKCk6IGFueSB7XG4gIHJldHVybiBuZXcgU3Vic2NyaWJlcihlbWl0dGVyKTtcbn1cblxuY29uc3QgRXZlbnRFbWl0dGVyUHViU3ViID0ge1xuICBjcmVhdGVQdWJsaXNoZXIsXG4gIGNyZWF0ZVN1YnNjcmliZXJcbn1cblxuZXhwb3J0IHtcbiAgRXZlbnRFbWl0dGVyUHViU3ViXG59XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/PubSub/RedisPubSub.js b/lib/Adapters/PubSub/RedisPubSub.js index bb84311735..450baf503f 100644 --- a/lib/Adapters/PubSub/RedisPubSub.js +++ b/lib/Adapters/PubSub/RedisPubSub.js @@ -65,4 +65,5 @@ const RedisPubSub = { exports.RedisPubSub = RedisPubSub; exports.createPublisher = createPublisher; -exports.createSubscriber = createSubscriber; \ No newline at end of file +exports.createSubscriber = createSubscriber; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9QdWJTdWIvUmVkaXNQdWJTdWIuanMiXSwibmFtZXMiOlsiY3JlYXRlUHVibGlzaGVyIiwicmVkaXNVUkwiLCJyZWRpc0NsaSIsInJlZGlzIiwiY3JlYXRlQ2xpZW50Iiwibm9fcmVhZHlfY2hlY2siLCJwdWJsaXNoMiIsInB1Ymxpc2giLCJjaGFubmVsIiwiYm9keSIsImJvZHlPYmplY3QiLCJKU09OIiwicGFyc2UiLCJlIiwicHVzaFN0YXR1cyIsIm11bHRpIiwiYXBwbGljYXRpb25JZCIsImV4ZWMiLCJjcmVhdGVTdWJzY3JpYmVyIiwic2Vjb25kYXJ5Q2xpZW50IiwicnVuIiwid29ya0l0ZW0iLCJQYXJzZSIsIlByb21pc2UiLCJyZXNvbHZlIiwiZXJyIiwicmVwIiwiUmVkaXNQdWJTdWIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7Ozs7QUFFQSxTQUFTQSxlQUFULENBQXlCLEVBQUNDLFFBQUQsRUFBekIsRUFBMEM7QUFDeEMsTUFBSUMsV0FBV0MsZ0JBQU1DLFlBQU4sQ0FBbUJILFFBQW5CLEVBQTZCLEVBQUVJLGdCQUFnQixJQUFsQixFQUE3QixDQUFmOztBQUVBLE1BQUlILFFBQUosRUFBYztBQUNaQSxhQUFTSSxRQUFULEdBQW9CSixTQUFTSyxPQUE3Qjs7QUFFQUwsYUFBU0ssT0FBVCxHQUFtQixVQUFVQyxPQUFWLEVBQW1CQyxJQUFuQixFQUF5QjtBQUMxQyxVQUFJQyxVQUFKO0FBQ0EsVUFBSTtBQUNGQSxxQkFBYUMsS0FBS0MsS0FBTCxDQUFXSCxJQUFYLENBQWI7QUFDRCxPQUZELENBRUUsT0FBT0ksQ0FBUCxFQUFVO0FBQ1ZILHFCQUFhLEVBQWI7QUFDRDtBQUNELFVBQUlBLGNBQWNBLFdBQVdJLFVBQTdCLEVBQXlDO0FBQ3ZDWixpQkFBU2EsS0FBVCxDQUFlLENBQ2IsQ0FBQyxNQUFELEVBQVNMLFdBQVdNLGFBQVgsR0FBMkIsT0FBcEMsRUFBNkNQLElBQTdDLENBRGEsQ0FBZixFQUVHUSxJQUZIO0FBR0Q7QUFDRCxhQUFPZixTQUFTSSxRQUFULENBQWtCRSxPQUFsQixFQUEyQkMsSUFBM0IsQ0FBUDtBQUNELEtBYkQ7QUFjRDs7QUFFRCxTQUFPUCxRQUFQO0FBQ0Q7O0FBRUQsU0FBU2dCLGdCQUFULENBQTBCLEVBQUNqQixRQUFELEVBQTFCLEVBQTJDO0FBQ3pDLE1BQUlDLFdBQVdDLGdCQUFNQyxZQUFOLENBQW1CSCxRQUFuQixFQUE2QixFQUFFSSxnQkFBZ0IsSUFBbEIsRUFBN0IsQ0FBZjtBQUNBLE1BQUljLGtCQUFrQmhCLGdCQUFNQyxZQUFOLENBQW1CSCxRQUFuQixFQUE2QixFQUFFSSxnQkFBZ0IsSUFBbEIsRUFBN0IsQ0FBdEI7QUFDQSxNQUFJSCxRQUFKLEVBQWM7QUFDWkEsYUFBU2tCLEdBQVQsR0FBZSxVQUFVQyxRQUFWLEVBQW9CO0FBQ2pDLGFBQU8sSUFBSUMsZUFBTUMsT0FBVixDQUFrQixVQUFVQyxPQUFWLEVBQW1CO0FBQzFDTCx3QkFDR0osS0FESCxDQUNTLENBQ0wsQ0FBQyxNQUFELEVBQVNNLFNBQVNMLGFBQVQsR0FBeUIsT0FBbEMsQ0FESyxDQURULEVBSUdDLElBSkgsQ0FJUSxVQUFVUSxHQUFWLEVBQWVDLEdBQWYsRUFBb0I7QUFDeEIsY0FBSSxDQUFDRCxHQUFELElBQVFDLEdBQVIsSUFBZUEsSUFBSSxDQUFKLENBQW5CLEVBQTJCO0FBQ3pCRixvQkFBUWIsS0FBS0MsS0FBTCxDQUFXYyxJQUFJLENBQUosQ0FBWCxDQUFSO0FBQ0QsV0FGRCxNQUVPO0FBQ0xGO0FBQ0Q7QUFDRixTQVZIO0FBV0QsT0FaTSxDQUFQO0FBYUQsS0FkRDtBQWVEOztBQUVELFNBQU90QixRQUFQO0FBQ0Q7O0FBRUQsTUFBTXlCLGNBQWM7QUFDbEIzQixpQkFEa0I7QUFFbEJrQjtBQUZrQixDQUFwQjs7UUFNRVMsVyxHQUFBQSxXO1FBQ0EzQixlLEdBQUFBLGU7UUFDQWtCLGdCLEdBQUFBLGdCIiwiZmlsZSI6IlJlZGlzUHViU3ViLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlZGlzIGZyb20gJ3JlZGlzJztcbmltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcblxuZnVuY3Rpb24gY3JlYXRlUHVibGlzaGVyKHtyZWRpc1VSTH0pOiBhbnkge1xuICB2YXIgcmVkaXNDbGkgPSByZWRpcy5jcmVhdGVDbGllbnQocmVkaXNVUkwsIHsgbm9fcmVhZHlfY2hlY2s6IHRydWUgfSk7XG5cbiAgaWYgKHJlZGlzQ2xpKSB7XG4gICAgcmVkaXNDbGkucHVibGlzaDIgPSByZWRpc0NsaS5wdWJsaXNoO1xuXG4gICAgcmVkaXNDbGkucHVibGlzaCA9IGZ1bmN0aW9uIChjaGFubmVsLCBib2R5KSB7XG4gICAgICB2YXIgYm9keU9iamVjdDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGJvZHlPYmplY3QgPSBKU09OLnBhcnNlKGJvZHkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBib2R5T2JqZWN0ID0ge307XG4gICAgICB9XG4gICAgICBpZiAoYm9keU9iamVjdCAmJiBib2R5T2JqZWN0LnB1c2hTdGF0dXMpIHtcbiAgICAgICAgcmVkaXNDbGkubXVsdGkoW1xuICAgICAgICAgIFsnc2FkZCcsIGJvZHlPYmplY3QuYXBwbGljYXRpb25JZCArICc6cHVzaCcsIGJvZHldXG4gICAgICAgIF0pLmV4ZWMoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZWRpc0NsaS5wdWJsaXNoMihjaGFubmVsLCBib2R5KTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHJlZGlzQ2xpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVTdWJzY3JpYmVyKHtyZWRpc1VSTH0pOiBhbnkge1xuICB2YXIgcmVkaXNDbGkgPSByZWRpcy5jcmVhdGVDbGllbnQocmVkaXNVUkwsIHsgbm9fcmVhZHlfY2hlY2s6IHRydWUgfSk7XG4gIHZhciBzZWNvbmRhcnlDbGllbnQgPSByZWRpcy5jcmVhdGVDbGllbnQocmVkaXNVUkwsIHsgbm9fcmVhZHlfY2hlY2s6IHRydWUgfSk7XG4gIGlmIChyZWRpc0NsaSkge1xuICAgIHJlZGlzQ2xpLnJ1biA9IGZ1bmN0aW9uICh3b3JrSXRlbSkge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5Qcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgIHNlY29uZGFyeUNsaWVudFxuICAgICAgICAgIC5tdWx0aShbXG4gICAgICAgICAgICBbJ3Nwb3AnLCB3b3JrSXRlbS5hcHBsaWNhdGlvbklkICsgJzpwdXNoJ11cbiAgICAgICAgICBdKVxuICAgICAgICAgIC5leGVjKGZ1bmN0aW9uIChlcnIsIHJlcCkge1xuICAgICAgICAgICAgaWYgKCFlcnIgJiYgcmVwICYmIHJlcFswXSkge1xuICAgICAgICAgICAgICByZXNvbHZlKEpTT04ucGFyc2UocmVwWzBdKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSlcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cblxuICByZXR1cm4gcmVkaXNDbGk7XG59XG5cbmNvbnN0IFJlZGlzUHViU3ViID0ge1xuICBjcmVhdGVQdWJsaXNoZXIsXG4gIGNyZWF0ZVN1YnNjcmliZXJcbn07XG5cbmV4cG9ydCB7XG4gIFJlZGlzUHViU3ViLFxuICBjcmVhdGVQdWJsaXNoZXIsXG4gIGNyZWF0ZVN1YnNjcmliZXJcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Push/PushAdapter.js b/lib/Adapters/Push/PushAdapter.js index d8080c5328..39bcf60093 100644 --- a/lib/Adapters/Push/PushAdapter.js +++ b/lib/Adapters/Push/PushAdapter.js @@ -29,4 +29,5 @@ class PushAdapter { } exports.PushAdapter = PushAdapter; -exports.default = PushAdapter; \ No newline at end of file +exports.default = PushAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9QdXNoL1B1c2hBZGFwdGVyLmpzIl0sIm5hbWVzIjpbIlB1c2hBZGFwdGVyIiwic2VuZCIsImJvZHkiLCJpbnN0YWxsYXRpb25zIiwicHVzaFN0YXR1cyIsImdldFZhbGlkUHVzaFR5cGVzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVPLE1BQU1BLFdBQU4sQ0FBa0I7QUFDdkJDLE9BQUtDLElBQUwsRUFBZ0JDLGFBQWhCLEVBQXNDQyxVQUF0QyxFQUFvRSxDQUFFOztBQUV0RTs7OztBQUlBQyxzQkFBOEI7QUFDNUIsV0FBTyxFQUFQO0FBQ0Q7QUFUc0I7O1FBQVpMLFcsR0FBQUEsVztrQkFZRUEsVyIsImZpbGUiOiJQdXNoQWRhcHRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG4vKmVzbGludCBuby11bnVzZWQtdmFyczogXCJvZmZcIiovXG4vLyBQdXNoIEFkYXB0ZXJcbi8vXG4vLyBBbGxvd3MgeW91IHRvIGNoYW5nZSB0aGUgcHVzaCBub3RpZmljYXRpb24gbWVjaGFuaXNtLlxuLy9cbi8vIEFkYXB0ZXIgY2xhc3NlcyBtdXN0IGltcGxlbWVudCB0aGUgZm9sbG93aW5nIGZ1bmN0aW9uczpcbi8vICogZ2V0VmFsaWRQdXNoVHlwZXMoKVxuLy8gKiBzZW5kKGRldmljZXMsIGluc3RhbGxhdGlvbnMsIHB1c2hTdGF0dXMpXG4vL1xuLy8gRGVmYXVsdCBpcyBQYXJzZVB1c2hBZGFwdGVyLCB3aGljaCB1c2VzIEdDTSBmb3Jcbi8vIGFuZHJvaWQgcHVzaCBhbmQgQVBOUyBmb3IgaW9zIHB1c2guXG5cbmV4cG9ydCBjbGFzcyBQdXNoQWRhcHRlciB7XG4gIHNlbmQoYm9keTogYW55LCBpbnN0YWxsYXRpb25zOiBhbnlbXSwgcHVzaFN0YXR1czogYW55KTogP1Byb21pc2U8Kj4ge31cblxuICAvKipcbiAgICogR2V0IGFuIGFycmF5IG9mIHZhbGlkIHB1c2ggdHlwZXMuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gQW4gYXJyYXkgb2YgdmFsaWQgcHVzaCB0eXBlc1xuICAgKi9cbiAgZ2V0VmFsaWRQdXNoVHlwZXMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbXVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoCollection.js b/lib/Adapters/Storage/Mongo/MongoCollection.js index 7e9c22c2b6..e24eb7354a 100644 --- a/lib/Adapters/Storage/Mongo/MongoCollection.js +++ b/lib/Adapters/Storage/Mongo/MongoCollection.js @@ -109,4 +109,5 @@ class MongoCollection { return this._mongoCollection.drop(); } } -exports.default = MongoCollection; \ No newline at end of file +exports.default = MongoCollection; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJtb25nb2RiIiwicmVxdWlyZSIsIkNvbGxlY3Rpb24iLCJNb25nb0NvbGxlY3Rpb24iLCJjb25zdHJ1Y3RvciIsIm1vbmdvQ29sbGVjdGlvbiIsIl9tb25nb0NvbGxlY3Rpb24iLCJmaW5kIiwicXVlcnkiLCJza2lwIiwibGltaXQiLCJzb3J0Iiwia2V5cyIsIm1heFRpbWVNUyIsInJlYWRQcmVmZXJlbmNlIiwiJHNjb3JlIiwic2NvcmUiLCIkbWV0YSIsIl9yYXdGaW5kIiwiY2F0Y2giLCJlcnJvciIsImNvZGUiLCJtZXNzYWdlIiwibWF0Y2giLCJrZXkiLCJpbmRleCIsImNyZWF0ZUluZGV4IiwidGhlbiIsImZpbmRPcGVyYXRpb24iLCJwcm9qZWN0IiwidG9BcnJheSIsImNvdW50IiwiY291bnRPcGVyYXRpb24iLCJkaXN0aW5jdCIsImZpZWxkIiwiYWdncmVnYXRlIiwicGlwZWxpbmUiLCJpbnNlcnRPbmUiLCJvYmplY3QiLCJ1cHNlcnRPbmUiLCJ1cGRhdGUiLCJ1cHNlcnQiLCJ1cGRhdGVPbmUiLCJ1cGRhdGVNYW55IiwiZGVsZXRlTWFueSIsIl9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZCIsImluZGV4UmVxdWVzdCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZW5zdXJlSW5kZXgiLCJ1bmlxdWUiLCJiYWNrZ3JvdW5kIiwic3BhcnNlIiwiZHJvcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxNQUFNQSxVQUFVQyxRQUFRLFNBQVIsQ0FBaEI7QUFDQSxNQUFNQyxhQUFhRixRQUFRRSxVQUEzQjs7QUFFZSxNQUFNQyxlQUFOLENBQXNCOztBQUduQ0MsY0FBWUMsZUFBWixFQUF3QztBQUN0QyxTQUFLQyxnQkFBTCxHQUF3QkQsZUFBeEI7QUFDRDs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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LFNBQU87QUFDTCxXQUFPLEtBQUtoRCxnQkFBTCxDQUFzQmdELElBQXRCLEVBQVA7QUFDRDtBQXhHa0M7a0JBQWhCbkQsZSIsImZpbGUiOiJNb25nb0NvbGxlY3Rpb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgQ29sbGVjdGlvbiA9IG1vbmdvZGIuQ29sbGVjdGlvbjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTW9uZ29Db2xsZWN0aW9uIHtcbiAgX21vbmdvQ29sbGVjdGlvbjpDb2xsZWN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKG1vbmdvQ29sbGVjdGlvbjpDb2xsZWN0aW9uKSB7XG4gICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uID0gbW9uZ29Db2xsZWN0aW9uO1xuICB9XG5cbiAgLy8gRG9lcyBhIGZpbmQgd2l0aCBcInNtYXJ0IGluZGV4aW5nXCIuXG4gIC8vIEN1cnJlbnRseSB0aGlzIGp1c3QgbWVhbnMsIGlmIGl0IG5lZWRzIGEgZ2VvaW5kZXggYW5kIHRoZXJlIGlzXG4gIC8vIG5vbmUsIHRoZW4gYnVpbGQgdGhlIGdlb2luZGV4LlxuICAvLyBUaGlzIGNvdWxkIGJlIGltcHJvdmVkIGEgbG90IGJ1dCBpdCdzIG5vdCBjbGVhciBpZiB0aGF0J3MgYSBnb29kXG4gIC8vIGlkZWEuIE9yIGV2ZW4gaWYgdGhpcyBiZWhhdmlvciBpcyBhIGdvb2QgaWRlYS5cbiAgZmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICAvLyBTdXBwb3J0IGZvciBGdWxsIFRleHQgU2VhcmNoIC0gJHRleHRcbiAgICBpZihrZXlzICYmIGtleXMuJHNjb3JlKSB7XG4gICAgICBkZWxldGUga2V5cy4kc2NvcmU7XG4gICAgICBrZXlzLnNjb3JlID0geyRtZXRhOiAndGV4dFNjb3JlJ307XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9yYXdGaW5kKHF1ZXJ5LCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvLyBDaGVjayBmb3IgXCJubyBnZW9pbmRleFwiIGVycm9yXG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9IDE3MDA3ICYmICFlcnJvci5tZXNzYWdlLm1hdGNoKC91bmFibGUgdG8gZmluZCBpbmRleCBmb3IgLmdlb05lYXIvKSkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZpZ3VyZSBvdXQgd2hhdCBrZXkgbmVlZHMgYW4gaW5kZXhcbiAgICAgICAgY29uc3Qga2V5ID0gZXJyb3IubWVzc2FnZS5tYXRjaCgvZmllbGQ9KFtBLVphLXpfMC05XSspIC8pWzFdO1xuICAgICAgICBpZiAoIWtleSkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluZGV4ID0ge307XG4gICAgICAgIGluZGV4W2tleV0gPSAnMmQnO1xuICAgICAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4KGluZGV4KVxuICAgICAgICAgIC8vIFJldHJ5LCBidXQganVzdCBvbmNlLlxuICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuX3Jhd0ZpbmQocXVlcnksIHsgc2tpcCwgbGltaXQsIHNvcnQsIGtleXMsIG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSkpO1xuICAgICAgfSk7XG4gIH1cblxuICBfcmF3RmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICBsZXQgZmluZE9wZXJhdGlvbiA9IHRoaXMuX21vbmdvQ29sbGVjdGlvblxuICAgICAgLmZpbmQocXVlcnksIHsgc2tpcCwgbGltaXQsIHNvcnQsIHJlYWRQcmVmZXJlbmNlIH0pXG5cbiAgICBpZiAoa2V5cykge1xuICAgICAgZmluZE9wZXJhdGlvbiA9IGZpbmRPcGVyYXRpb24ucHJvamVjdChrZXlzKTtcbiAgICB9XG5cbiAgICBpZiAobWF4VGltZU1TKSB7XG4gICAgICBmaW5kT3BlcmF0aW9uID0gZmluZE9wZXJhdGlvbi5tYXhUaW1lTVMobWF4VGltZU1TKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmluZE9wZXJhdGlvbi50b0FycmF5KCk7XG4gIH1cblxuICBjb3VudChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICBjb25zdCBjb3VudE9wZXJhdGlvbiA9IHRoaXMuX21vbmdvQ29sbGVjdGlvbi5jb3VudChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9KTtcblxuICAgIHJldHVybiBjb3VudE9wZXJhdGlvbjtcbiAgfVxuXG4gIGRpc3RpbmN0KGZpZWxkLCBxdWVyeSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uZGlzdGluY3QoZmllbGQsIHF1ZXJ5KTtcbiAgfVxuXG4gIGFnZ3JlZ2F0ZShwaXBlbGluZSwgeyBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0gPSB7fSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uYWdncmVnYXRlKHBpcGVsaW5lLCB7IG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSkudG9BcnJheSgpO1xuICB9XG5cbiAgaW5zZXJ0T25lKG9iamVjdCkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uaW5zZXJ0T25lKG9iamVjdCk7XG4gIH1cblxuICAvLyBBdG9taWNhbGx5IHVwZGF0ZXMgZGF0YSBpbiB0aGUgZGF0YWJhc2UgZm9yIGEgc2luZ2xlIChmaXJzdCkgb2JqZWN0IHRoYXQgbWF0Y2hlZCB0aGUgcXVlcnlcbiAgLy8gSWYgdGhlcmUgaXMgbm90aGluZyB0aGF0IG1hdGNoZXMgdGhlIHF1ZXJ5IC0gZG9lcyBpbnNlcnRcbiAgLy8gUG9zdGdyZXMgTm90ZTogYElOU0VSVCAuLi4gT04gQ09ORkxJQ1QgVVBEQVRFYCB0aGF0IGlzIGF2YWlsYWJsZSBzaW5jZSA5LjUuXG4gIHVwc2VydE9uZShxdWVyeSwgdXBkYXRlKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi51cGRhdGUocXVlcnksIHVwZGF0ZSwgeyB1cHNlcnQ6IHRydWUgfSlcbiAgfVxuXG4gIHVwZGF0ZU9uZShxdWVyeSwgdXBkYXRlKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi51cGRhdGVPbmUocXVlcnksIHVwZGF0ZSk7XG4gIH1cblxuICB1cGRhdGVNYW55KHF1ZXJ5LCB1cGRhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLnVwZGF0ZU1hbnkocXVlcnksIHVwZGF0ZSk7XG4gIH1cblxuICBkZWxldGVNYW55KHF1ZXJ5KSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5kZWxldGVNYW55KHF1ZXJ5KTtcbiAgfVxuXG4gIF9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZChpbmRleFJlcXVlc3QpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmVuc3VyZUluZGV4KGluZGV4UmVxdWVzdCwgeyB1bmlxdWU6IHRydWUsIGJhY2tncm91bmQ6IHRydWUsIHNwYXJzZTogdHJ1ZSB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZHJvcCgpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmRyb3AoKTtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js b/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js index c8b35c71ef..1335b2b1a2 100644 --- a/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +++ b/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js @@ -235,4 +235,5 @@ class MongoSchemaCollection { MongoSchemaCollection._TESTmongoSchemaToParseSchema = mongoSchemaToParseSchema; MongoSchemaCollection.parseFieldTypeToMongoFieldType = parseFieldTypeToMongoFieldType; -exports.default = MongoSchemaCollection; \ No newline at end of file +exports.default = MongoSchemaCollection; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU2NoZW1hQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJtb25nb0ZpZWxkVG9QYXJzZVNjaGVtYUZpZWxkIiwidHlwZSIsInRhcmdldENsYXNzIiwic2xpY2UiLCJzdGFydHNXaXRoIiwibGVuZ3RoIiwibm9uRmllbGRTY2hlbWFLZXlzIiwibW9uZ29TY2hlbWFGaWVsZHNUb1BhcnNlU2NoZW1hRmllbGRzIiwic2NoZW1hIiwiZmllbGROYW1lcyIsIk9iamVjdCIsImtleXMiLCJmaWx0ZXIiLCJrZXkiLCJpbmRleE9mIiwicmVzcG9uc2UiLCJyZWR1Y2UiLCJvYmoiLCJmaWVsZE5hbWUiLCJBQ0wiLCJjcmVhdGVkQXQiLCJ1cGRhdGVkQXQiLCJvYmplY3RJZCIsImVtcHR5Q0xQUyIsImZyZWV6ZSIsImZpbmQiLCJnZXQiLCJjcmVhdGUiLCJ1cGRhdGUiLCJkZWxldGUiLCJhZGRGaWVsZCIsImRlZmF1bHRDTFBTIiwibW9uZ29TY2hlbWFUb1BhcnNlU2NoZW1hIiwibW9uZ29TY2hlbWEiLCJjbHBzIiwiaW5kZXhlcyIsIl9tZXRhZGF0YSIsImNsYXNzX3Blcm1pc3Npb25zIiwiY2xhc3NOYW1lIiwiX2lkIiwiZmllbGRzIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiX21vbmdvU2NoZW1hUXVlcnlGcm9tTmFtZVF1ZXJ5IiwibmFtZSIsInF1ZXJ5Iiwib2JqZWN0IiwiZm9yRWFjaCIsInBhcnNlRmllbGRUeXBlVG9Nb25nb0ZpZWxkVHlwZSIsIk1vbmdvU2NoZW1hQ29sbGVjdGlvbiIsImNvbnN0cnVjdG9yIiwiY29sbGVjdGlvbiIsIl9jb2xsZWN0aW9uIiwiX2ZldGNoQWxsU2NoZW1hc0Zyb21fU0NIRU1BIiwiX3Jhd0ZpbmQiLCJ0aGVuIiwic2NoZW1hcyIsIm1hcCIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwibGltaXQiLCJyZXN1bHRzIiwidW5kZWZpbmVkIiwiZmluZEFuZERlbGV0ZVNjaGVtYSIsIl9tb25nb0NvbGxlY3Rpb24iLCJmaW5kQW5kUmVtb3ZlIiwiaW5zZXJ0U2NoZW1hIiwiaW5zZXJ0T25lIiwicmVzdWx0Iiwib3BzIiwiY2F0Y2giLCJlcnJvciIsImNvZGUiLCJQYXJzZSIsIkVycm9yIiwiRFVQTElDQVRFX1ZBTFVFIiwidXBkYXRlU2NoZW1hIiwidXBkYXRlT25lIiwidXBzZXJ0U2NoZW1hIiwidXBzZXJ0T25lIiwiYWRkRmllbGRJZk5vdEV4aXN0cyIsInNvbWUiLCJleGlzdGluZ0ZpZWxkIiwiSU5DT1JSRUNUX1RZUEUiLCJfVEVTVG1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7Ozs7QUFFQSxTQUFTQSw0QkFBVCxDQUFzQ0MsSUFBdEMsRUFBNEM7QUFDMUMsTUFBSUEsS0FBSyxDQUFMLE1BQVksR0FBaEIsRUFBcUI7QUFDbkIsV0FBTztBQUNMQSxZQUFNLFNBREQ7QUFFTEMsbUJBQWFELEtBQUtFLEtBQUwsQ0FBVyxDQUFYO0FBRlIsS0FBUDtBQUlEO0FBQ0QsTUFBSUYsS0FBS0csVUFBTCxDQUFnQixXQUFoQixDQUFKLEVBQWtDO0FBQ2hDLFdBQU87QUFDTEgsWUFBTSxVQUREO0FBRUxDLG1CQUFhRCxLQUFLRSxLQUFMLENBQVcsWUFBWUUsTUFBdkIsRUFBK0JKLEtBQUtJLE1BQUwsR0FBYyxDQUE3QztBQUZSLEtBQVA7QUFJRDtBQUNELFVBQVFKLElBQVI7QUFDQSxTQUFLLFFBQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLFFBQVAsRUFBUDtBQUNqQixTQUFLLFFBQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLFFBQVAsRUFBUDtBQUNqQixTQUFLLFNBQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLFNBQVAsRUFBUDtBQUNqQixTQUFLLE1BQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLE1BQVAsRUFBUDtBQUNqQixTQUFLLEtBQUw7QUFDQSxTQUFLLFFBQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLFFBQVAsRUFBUDtBQUNqQixTQUFLLE9BQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLE9BQVAsRUFBUDtBQUNqQixTQUFLLFVBQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLFVBQVAsRUFBUDtBQUNqQixTQUFLLE1BQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLE1BQVAsRUFBUDtBQUNqQixTQUFLLE9BQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLE9BQVAsRUFBUDtBQUNqQixTQUFLLFNBQUw7QUFBaUIsYUFBTyxFQUFDQSxNQUFNLFNBQVAsRUFBUDtBQVhqQjtBQWFEOztBQUVELE1BQU1LLHFCQUFxQixDQUFDLEtBQUQsRUFBUSxXQUFSLEVBQXFCLHFCQUFyQixDQUEzQjtBQUNBLFNBQVNDLG9DQUFULENBQThDQyxNQUE5QyxFQUFzRDtBQUNwRCxNQUFJQyxhQUFhQyxPQUFPQyxJQUFQLENBQVlILE1BQVosRUFBb0JJLE1BQXBCLENBQTJCQyxPQUFPUCxtQkFBbUJRLE9BQW5CLENBQTJCRCxHQUEzQixNQUFvQyxDQUFDLENBQXZFLENBQWpCO0FBQ0EsTUFBSUUsV0FBV04sV0FBV08sTUFBWCxDQUFrQixDQUFDQyxHQUFELEVBQU1DLFNBQU4sS0FBb0I7QUFDbkRELFFBQUlDLFNBQUosSUFBaUJsQiw2QkFBNkJRLE9BQU9VLFNBQVAsQ0FBN0IsQ0FBakI7QUFDQSxXQUFPRCxHQUFQO0FBQ0QsR0FIYyxFQUdaLEVBSFksQ0FBZjtBQUlBRixXQUFTSSxHQUFULEdBQWUsRUFBQ2xCLE1BQU0sS0FBUCxFQUFmO0FBQ0FjLFdBQVNLLFNBQVQsR0FBcUIsRUFBQ25CLE1BQU0sTUFBUCxFQUFyQjtBQUNBYyxXQUFTTSxTQUFULEdBQXFCLEVBQUNwQixNQUFNLE1BQVAsRUFBckI7QUFDQWMsV0FBU08sUUFBVCxHQUFvQixFQUFDckIsTUFBTSxRQUFQLEVBQXBCO0FBQ0EsU0FBT2MsUUFBUDtBQUNEOztBQUVELE1BQU1RLFlBQVliLE9BQU9jLE1BQVAsQ0FBYztBQUM5QkMsUUFBTSxFQUR3QjtBQUU5QkMsT0FBSyxFQUZ5QjtBQUc5QkMsVUFBUSxFQUhzQjtBQUk5QkMsVUFBUSxFQUpzQjtBQUs5QkMsVUFBUSxFQUxzQjtBQU05QkMsWUFBVTtBQU5vQixDQUFkLENBQWxCOztBQVNBLE1BQU1DLGNBQWNyQixPQUFPYyxNQUFQLENBQWM7QUFDaENDLFFBQU0sRUFBQyxLQUFLLElBQU4sRUFEMEI7QUFFaENDLE9BQUssRUFBQyxLQUFLLElBQU4sRUFGMkI7QUFHaENDLFVBQVEsRUFBQyxLQUFLLElBQU4sRUFId0I7QUFJaENDLFVBQVEsRUFBQyxLQUFLLElBQU4sRUFKd0I7QUFLaENDLFVBQVEsRUFBQyxLQUFLLElBQU4sRUFMd0I7QUFNaENDLFlBQVUsRUFBQyxLQUFLLElBQU47QUFOc0IsQ0FBZCxDQUFwQjs7QUFTQSxTQUFTRSx3QkFBVCxDQUFrQ0MsV0FBbEMsRUFBK0M7QUFDN0MsTUFBSUMsT0FBT0gsV0FBWDtBQUNBLE1BQUlJLFVBQVUsRUFBZDtBQUNBLE1BQUlGLFlBQVlHLFNBQWhCLEVBQTJCO0FBQ3pCLFFBQUlILFlBQVlHLFNBQVosQ0FBc0JDLGlCQUExQixFQUE2QztBQUMzQ0gsMEJBQVdYLFNBQVgsRUFBeUJVLFlBQVlHLFNBQVosQ0FBc0JDLGlCQUEvQztBQUNEO0FBQ0QsUUFBSUosWUFBWUcsU0FBWixDQUFzQkQsT0FBMUIsRUFBbUM7QUFDakNBLDZCQUFjRixZQUFZRyxTQUFaLENBQXNCRCxPQUFwQztBQUNEO0FBQ0Y7QUFDRCxTQUFPO0FBQ0xHLGVBQVdMLFlBQVlNLEdBRGxCO0FBRUxDLFlBQVFqQyxxQ0FBcUMwQixXQUFyQyxDQUZIO0FBR0xRLDJCQUF1QlAsSUFIbEI7QUFJTEMsYUFBU0E7QUFKSixHQUFQO0FBTUQ7O0FBRUQsU0FBU08sOEJBQVQsQ0FBd0NDLElBQXhDLEVBQXNEQyxLQUF0RCxFQUE2RDtBQUMzRCxRQUFNQyxTQUFTLEVBQUVOLEtBQUtJLElBQVAsRUFBZjtBQUNBLE1BQUlDLEtBQUosRUFBVztBQUNUbEMsV0FBT0MsSUFBUCxDQUFZaUMsS0FBWixFQUFtQkUsT0FBbkIsQ0FBMkJqQyxPQUFPO0FBQ2hDZ0MsYUFBT2hDLEdBQVAsSUFBYytCLE1BQU0vQixHQUFOLENBQWQ7QUFDRCxLQUZEO0FBR0Q7QUFDRCxTQUFPZ0MsTUFBUDtBQUNEOztBQUdEO0FBQ0E7QUFDQSxTQUFTRSw4QkFBVCxDQUF3QyxFQUFFOUMsSUFBRixFQUFRQyxXQUFSLEVBQXhDLEVBQStEO0FBQzdELFVBQVFELElBQVI7QUFDQSxTQUFLLFNBQUw7QUFBaUIsYUFBUSxJQUFHQyxXQUFZLEVBQXZCO0FBQ2pCLFNBQUssVUFBTDtBQUFpQixhQUFRLFlBQVdBLFdBQVksR0FBL0I7QUFDakIsU0FBSyxRQUFMO0FBQWlCLGFBQU8sUUFBUDtBQUNqQixTQUFLLFFBQUw7QUFBaUIsYUFBTyxRQUFQO0FBQ2pCLFNBQUssU0FBTDtBQUFpQixhQUFPLFNBQVA7QUFDakIsU0FBSyxNQUFMO0FBQWlCLGFBQU8sTUFBUDtBQUNqQixTQUFLLFFBQUw7QUFBaUIsYUFBTyxRQUFQO0FBQ2pCLFNBQUssT0FBTDtBQUFpQixhQUFPLE9BQVA7QUFDakIsU0FBSyxVQUFMO0FBQWlCLGFBQU8sVUFBUDtBQUNqQixTQUFLLE1BQUw7QUFBaUIsYUFBTyxNQUFQO0FBQ2pCLFNBQUssT0FBTDtBQUFpQixhQUFPLE9BQVA7QUFDakIsU0FBSyxTQUFMO0FBQWlCLGFBQU8sU0FBUDtBQVpqQjtBQWNEOztBQUVELE1BQU04QyxxQkFBTixDQUE0Qjs7QUFHMUJDLGNBQVlDLFVBQVosRUFBeUM7QUFDdkMsU0FBS0MsV0FBTCxHQUFtQkQsVUFBbkI7QUFDRDs7QUFFREUsZ0NBQThCO0FBQzVCLFdBQU8sS0FBS0QsV0FBTCxDQUFpQkUsUUFBakIsQ0FBMEIsRUFBMUIsRUFDSkMsSUFESSxDQUNDQyxXQUFXQSxRQUFRQyxHQUFSLENBQVl4Qix3QkFBWixDQURaLENBQVA7QUFFRDs7QUFFRHlCLDZCQUEyQmQsSUFBM0IsRUFBeUM7QUFDdkMsV0FBTyxLQUFLUSxXQUFMLENBQWlCRSxRQUFqQixDQUEwQlgsK0JBQStCQyxJQUEvQixDQUExQixFQUFnRSxFQUFFZSxPQUFPLENBQVQsRUFBaEUsRUFBOEVKLElBQTlFLENBQW1GSyxXQUFXO0FBQ25HLFVBQUlBLFFBQVF0RCxNQUFSLEtBQW1CLENBQXZCLEVBQTBCO0FBQ3hCLGVBQU8yQix5QkFBeUIyQixRQUFRLENBQVIsQ0FBekIsQ0FBUDtBQUNELE9BRkQsTUFFTztBQUNMLGNBQU1DLFNBQU47QUFDRDtBQUNGLEtBTk0sQ0FBUDtBQU9EOztBQUVEO0FBQ0FDLHNCQUFvQmxCLElBQXBCLEVBQWtDO0FBQ2hDLFdBQU8sS0FBS1EsV0FBTCxDQUFpQlcsZ0JBQWpCLENBQWtDQyxhQUFsQyxDQUFnRHJCLCtCQUErQkMsSUFBL0IsQ0FBaEQsRUFBc0YsRUFBdEYsQ0FBUDtBQUNEOztBQUVEcUIsZUFBYXhELE1BQWIsRUFBMEI7QUFDeEIsV0FBTyxLQUFLMkMsV0FBTCxDQUFpQmMsU0FBakIsQ0FBMkJ6RCxNQUEzQixFQUNKOEMsSUFESSxDQUNDWSxVQUFVbEMseUJBQXlCa0MsT0FBT0MsR0FBUCxDQUFXLENBQVgsQ0FBekIsQ0FEWCxFQUVKQyxLQUZJLENBRUVDLFNBQVM7QUFDZCxVQUFJQSxNQUFNQyxJQUFOLEtBQWUsS0FBbkIsRUFBMEI7QUFBRTtBQUMxQixjQUFNLElBQUlDLGVBQU1DLEtBQVYsQ0FBZ0JELGVBQU1DLEtBQU4sQ0FBWUMsZUFBNUIsRUFBNkMsdUJBQTdDLENBQU47QUFDRCxPQUZELE1BRU87QUFDTCxjQUFNSixLQUFOO0FBQ0Q7QUFDRixLQVJJLENBQVA7QUFTRDs7QUFFREssZUFBYS9CLElBQWIsRUFBMkJmLE1BQTNCLEVBQW1DO0FBQ2pDLFdBQU8sS0FBS3VCLFdBQUwsQ0FBaUJ3QixTQUFqQixDQUEyQmpDLCtCQUErQkMsSUFBL0IsQ0FBM0IsRUFBaUVmLE1BQWpFLENBQVA7QUFDRDs7QUFFRGdELGVBQWFqQyxJQUFiLEVBQTJCQyxLQUEzQixFQUEwQ2hCLE1BQTFDLEVBQWtEO0FBQ2hELFdBQU8sS0FBS3VCLFdBQUwsQ0FBaUIwQixTQUFqQixDQUEyQm5DLCtCQUErQkMsSUFBL0IsRUFBcUNDLEtBQXJDLENBQTNCLEVBQXdFaEIsTUFBeEUsQ0FBUDtBQUNEOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0FrRCxzQkFBb0J4QyxTQUFwQixFQUF1Q3BCLFNBQXZDLEVBQTBEakIsSUFBMUQsRUFBd0U7QUFDdEUsV0FBTyxLQUFLd0QsMEJBQUwsQ0FBZ0NuQixTQUFoQyxFQUNKZ0IsSUFESSxDQUNDOUMsVUFBVTtBQUNkO0FBQ0EsVUFBSUEsT0FBT2dDLE1BQVAsQ0FBY3RCLFNBQWQsS0FBNEIwQyxTQUFoQyxFQUEyQztBQUN6QztBQUNEO0FBQ0Q7QUFDQSxVQUFJM0QsS0FBS0EsSUFBTCxLQUFjLFVBQWxCLEVBQThCO0FBQzlCO0FBQ0UsWUFBSVMsT0FBT0MsSUFBUCxDQUFZSCxPQUFPZ0MsTUFBbkIsRUFBMkJ1QyxJQUEzQixDQUFnQ0MsaUJBQWlCeEUsT0FBT2dDLE1BQVAsQ0FBY3dDLGFBQWQsRUFBNkIvRSxJQUE3QixLQUFzQyxVQUF2RixDQUFKLEVBQXdHO0FBQ3RHLGdCQUFNLElBQUlzRSxlQUFNQyxLQUFWLENBQWdCRCxlQUFNQyxLQUFOLENBQVlTLGNBQTVCLEVBQTRDLHNEQUE1QyxDQUFOO0FBQ0Q7QUFDRjtBQUNEO0FBQ0QsS0FkSSxFQWNGWixTQUFTO0FBQ1o7QUFDQTtBQUNFLFVBQUlBLFVBQVVULFNBQWQsRUFBeUI7QUFDdkI7QUFDRDtBQUNELFlBQU1TLEtBQU47QUFDRCxLQXJCSSxFQXNCSmYsSUF0QkksQ0FzQkMsTUFBTTtBQUNaO0FBQ0E7QUFDRSxhQUFPLEtBQUtzQixZQUFMLENBQ0x0QyxTQURLLEVBRUwsRUFBRSxDQUFDcEIsU0FBRCxHQUFhLEVBQUUsV0FBVyxLQUFiLEVBQWYsRUFGSyxFQUdMLEVBQUUsUUFBUyxFQUFFLENBQUNBLFNBQUQsR0FBYTZCLCtCQUErQjlDLElBQS9CLENBQWYsRUFBWCxFQUhLLENBQVA7QUFLRCxLQTlCSSxDQUFQO0FBK0JEO0FBMUZ5Qjs7QUE2RjVCO0FBQ0E7QUFDQStDLHNCQUFzQmtDLDZCQUF0QixHQUFzRGxELHdCQUF0RDtBQUNBZ0Isc0JBQXNCRCw4QkFBdEIsR0FBdURBLDhCQUF2RDs7a0JBRWVDLHFCIiwiZmlsZSI6Ik1vbmdvU2NoZW1hQ29sbGVjdGlvbi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBNb25nb0NvbGxlY3Rpb24gZnJvbSAnLi9Nb25nb0NvbGxlY3Rpb24nO1xuaW1wb3J0IFBhcnNlICAgICAgICAgICBmcm9tICdwYXJzZS9ub2RlJztcblxuZnVuY3Rpb24gbW9uZ29GaWVsZFRvUGFyc2VTY2hlbWFGaWVsZCh0eXBlKSB7XG4gIGlmICh0eXBlWzBdID09PSAnKicpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ1BvaW50ZXInLFxuICAgICAgdGFyZ2V0Q2xhc3M6IHR5cGUuc2xpY2UoMSksXG4gICAgfTtcbiAgfVxuICBpZiAodHlwZS5zdGFydHNXaXRoKCdyZWxhdGlvbjwnKSkge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAnUmVsYXRpb24nLFxuICAgICAgdGFyZ2V0Q2xhc3M6IHR5cGUuc2xpY2UoJ3JlbGF0aW9uPCcubGVuZ3RoLCB0eXBlLmxlbmd0aCAtIDEpLFxuICAgIH07XG4gIH1cbiAgc3dpdGNoICh0eXBlKSB7XG4gIGNhc2UgJ251bWJlcic6ICAgcmV0dXJuIHt0eXBlOiAnTnVtYmVyJ307XG4gIGNhc2UgJ3N0cmluZyc6ICAgcmV0dXJuIHt0eXBlOiAnU3RyaW5nJ307XG4gIGNhc2UgJ2Jvb2xlYW4nOiAgcmV0dXJuIHt0eXBlOiAnQm9vbGVhbid9O1xuICBjYXNlICdkYXRlJzogICAgIHJldHVybiB7dHlwZTogJ0RhdGUnfTtcbiAgY2FzZSAnbWFwJzpcbiAgY2FzZSAnb2JqZWN0JzogICByZXR1cm4ge3R5cGU6ICdPYmplY3QnfTtcbiAgY2FzZSAnYXJyYXknOiAgICByZXR1cm4ge3R5cGU6ICdBcnJheSd9O1xuICBjYXNlICdnZW9wb2ludCc6IHJldHVybiB7dHlwZTogJ0dlb1BvaW50J307XG4gIGNhc2UgJ2ZpbGUnOiAgICAgcmV0dXJuIHt0eXBlOiAnRmlsZSd9O1xuICBjYXNlICdieXRlcyc6ICAgIHJldHVybiB7dHlwZTogJ0J5dGVzJ307XG4gIGNhc2UgJ3BvbHlnb24nOiAgcmV0dXJuIHt0eXBlOiAnUG9seWdvbid9O1xuICB9XG59XG5cbmNvbnN0IG5vbkZpZWxkU2NoZW1hS2V5cyA9IFsnX2lkJywgJ19tZXRhZGF0YScsICdfY2xpZW50X3Blcm1pc3Npb25zJ107XG5mdW5jdGlvbiBtb25nb1NjaGVtYUZpZWxkc1RvUGFyc2VTY2hlbWFGaWVsZHMoc2NoZW1hKSB7XG4gIHZhciBmaWVsZE5hbWVzID0gT2JqZWN0LmtleXMoc2NoZW1hKS5maWx0ZXIoa2V5ID0+IG5vbkZpZWxkU2NoZW1hS2V5cy5pbmRleE9mKGtleSkgPT09IC0xKTtcbiAgdmFyIHJlc3BvbnNlID0gZmllbGROYW1lcy5yZWR1Y2UoKG9iaiwgZmllbGROYW1lKSA9PiB7XG4gICAgb2JqW2ZpZWxkTmFtZV0gPSBtb25nb0ZpZWxkVG9QYXJzZVNjaGVtYUZpZWxkKHNjaGVtYVtmaWVsZE5hbWVdKVxuICAgIHJldHVybiBvYmo7XG4gIH0sIHt9KTtcbiAgcmVzcG9uc2UuQUNMID0ge3R5cGU6ICdBQ0wnfTtcbiAgcmVzcG9uc2UuY3JlYXRlZEF0ID0ge3R5cGU6ICdEYXRlJ307XG4gIHJlc3BvbnNlLnVwZGF0ZWRBdCA9IHt0eXBlOiAnRGF0ZSd9O1xuICByZXNwb25zZS5vYmplY3RJZCA9IHt0eXBlOiAnU3RyaW5nJ307XG4gIHJldHVybiByZXNwb25zZTtcbn1cblxuY29uc3QgZW1wdHlDTFBTID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGZpbmQ6IHt9LFxuICBnZXQ6IHt9LFxuICBjcmVhdGU6IHt9LFxuICB1cGRhdGU6IHt9LFxuICBkZWxldGU6IHt9LFxuICBhZGRGaWVsZDoge30sXG59KTtcblxuY29uc3QgZGVmYXVsdENMUFMgPSBPYmplY3QuZnJlZXplKHtcbiAgZmluZDogeycqJzogdHJ1ZX0sXG4gIGdldDogeycqJzogdHJ1ZX0sXG4gIGNyZWF0ZTogeycqJzogdHJ1ZX0sXG4gIHVwZGF0ZTogeycqJzogdHJ1ZX0sXG4gIGRlbGV0ZTogeycqJzogdHJ1ZX0sXG4gIGFkZEZpZWxkOiB7JyonOiB0cnVlfSxcbn0pO1xuXG5mdW5jdGlvbiBtb25nb1NjaGVtYVRvUGFyc2VTY2hlbWEobW9uZ29TY2hlbWEpIHtcbiAgbGV0IGNscHMgPSBkZWZhdWx0Q0xQUztcbiAgbGV0IGluZGV4ZXMgPSB7fVxuICBpZiAobW9uZ29TY2hlbWEuX21ldGFkYXRhKSB7XG4gICAgaWYgKG1vbmdvU2NoZW1hLl9tZXRhZGF0YS5jbGFzc19wZXJtaXNzaW9ucykge1xuICAgICAgY2xwcyA9IHsuLi5lbXB0eUNMUFMsIC4uLm1vbmdvU2NoZW1hLl9tZXRhZGF0YS5jbGFzc19wZXJtaXNzaW9uc307XG4gICAgfVxuICAgIGlmIChtb25nb1NjaGVtYS5fbWV0YWRhdGEuaW5kZXhlcykge1xuICAgICAgaW5kZXhlcyA9IHsuLi5tb25nb1NjaGVtYS5fbWV0YWRhdGEuaW5kZXhlc307XG4gICAgfVxuICB9XG4gIHJldHVybiB7XG4gICAgY2xhc3NOYW1lOiBtb25nb1NjaGVtYS5faWQsXG4gICAgZmllbGRzOiBtb25nb1NjaGVtYUZpZWxkc1RvUGFyc2VTY2hlbWFGaWVsZHMobW9uZ29TY2hlbWEpLFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogY2xwcyxcbiAgICBpbmRleGVzOiBpbmRleGVzLFxuICB9O1xufVxuXG5mdW5jdGlvbiBfbW9uZ29TY2hlbWFRdWVyeUZyb21OYW1lUXVlcnkobmFtZTogc3RyaW5nLCBxdWVyeSkge1xuICBjb25zdCBvYmplY3QgPSB7IF9pZDogbmFtZSB9O1xuICBpZiAocXVlcnkpIHtcbiAgICBPYmplY3Qua2V5cyhxdWVyeSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgb2JqZWN0W2tleV0gPSBxdWVyeVtrZXldO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiBvYmplY3Q7XG59XG5cblxuLy8gUmV0dXJucyBhIHR5cGUgc3VpdGFibGUgZm9yIGluc2VydGluZyBpbnRvIG1vbmdvIF9TQ0hFTUEgY29sbGVjdGlvbi5cbi8vIERvZXMgbm8gdmFsaWRhdGlvbi4gVGhhdCBpcyBleHBlY3RlZCB0byBiZSBkb25lIGluIFBhcnNlIFNlcnZlci5cbmZ1bmN0aW9uIHBhcnNlRmllbGRUeXBlVG9Nb25nb0ZpZWxkVHlwZSh7IHR5cGUsIHRhcmdldENsYXNzIH0pIHtcbiAgc3dpdGNoICh0eXBlKSB7XG4gIGNhc2UgJ1BvaW50ZXInOiAgcmV0dXJuIGAqJHt0YXJnZXRDbGFzc31gO1xuICBjYXNlICdSZWxhdGlvbic6IHJldHVybiBgcmVsYXRpb248JHt0YXJnZXRDbGFzc30+YDtcbiAgY2FzZSAnTnVtYmVyJzogICByZXR1cm4gJ251bWJlcic7XG4gIGNhc2UgJ1N0cmluZyc6ICAgcmV0dXJuICdzdHJpbmcnO1xuICBjYXNlICdCb29sZWFuJzogIHJldHVybiAnYm9vbGVhbic7XG4gIGNhc2UgJ0RhdGUnOiAgICAgcmV0dXJuICdkYXRlJztcbiAgY2FzZSAnT2JqZWN0JzogICByZXR1cm4gJ29iamVjdCc7XG4gIGNhc2UgJ0FycmF5JzogICAgcmV0dXJuICdhcnJheSc7XG4gIGNhc2UgJ0dlb1BvaW50JzogcmV0dXJuICdnZW9wb2ludCc7XG4gIGNhc2UgJ0ZpbGUnOiAgICAgcmV0dXJuICdmaWxlJztcbiAgY2FzZSAnQnl0ZXMnOiAgICByZXR1cm4gJ2J5dGVzJztcbiAgY2FzZSAnUG9seWdvbic6ICByZXR1cm4gJ3BvbHlnb24nO1xuICB9XG59XG5cbmNsYXNzIE1vbmdvU2NoZW1hQ29sbGVjdGlvbiB7XG4gIF9jb2xsZWN0aW9uOiBNb25nb0NvbGxlY3Rpb247XG5cbiAgY29uc3RydWN0b3IoY29sbGVjdGlvbjogTW9uZ29Db2xsZWN0aW9uKSB7XG4gICAgdGhpcy5fY29sbGVjdGlvbiA9IGNvbGxlY3Rpb247XG4gIH1cblxuICBfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbGxlY3Rpb24uX3Jhd0ZpbmQoe30pXG4gICAgICAudGhlbihzY2hlbWFzID0+IHNjaGVtYXMubWFwKG1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYSkpO1xuICB9XG5cbiAgX2ZldGNoT25lU2NoZW1hRnJvbV9TQ0hFTUEobmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbGxlY3Rpb24uX3Jhd0ZpbmQoX21vbmdvU2NoZW1hUXVlcnlGcm9tTmFtZVF1ZXJ5KG5hbWUpLCB7IGxpbWl0OiAxIH0pLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICBpZiAocmVzdWx0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIG1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYShyZXN1bHRzWzBdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIEF0b21pY2FsbHkgZmluZCBhbmQgZGVsZXRlIGFuIG9iamVjdCBiYXNlZCBvbiBxdWVyeS5cbiAgZmluZEFuZERlbGV0ZVNjaGVtYShuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmZpbmRBbmRSZW1vdmUoX21vbmdvU2NoZW1hUXVlcnlGcm9tTmFtZVF1ZXJ5KG5hbWUpLCBbXSk7XG4gIH1cblxuICBpbnNlcnRTY2hlbWEoc2NoZW1hOiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fY29sbGVjdGlvbi5pbnNlcnRPbmUoc2NoZW1hKVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IG1vbmdvU2NoZW1hVG9QYXJzZVNjaGVtYShyZXN1bHQub3BzWzBdKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkgeyAvL01vbmdvJ3MgZHVwbGljYXRlIGtleSBlcnJvclxuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsICdDbGFzcyBhbHJlYWR5IGV4aXN0cy4nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgfVxuXG4gIHVwZGF0ZVNjaGVtYShuYW1lOiBzdHJpbmcsIHVwZGF0ZSkge1xuICAgIHJldHVybiB0aGlzLl9jb2xsZWN0aW9uLnVwZGF0ZU9uZShfbW9uZ29TY2hlbWFRdWVyeUZyb21OYW1lUXVlcnkobmFtZSksIHVwZGF0ZSk7XG4gIH1cblxuICB1cHNlcnRTY2hlbWEobmFtZTogc3RyaW5nLCBxdWVyeTogc3RyaW5nLCB1cGRhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5fY29sbGVjdGlvbi51cHNlcnRPbmUoX21vbmdvU2NoZW1hUXVlcnlGcm9tTmFtZVF1ZXJ5KG5hbWUsIHF1ZXJ5KSwgdXBkYXRlKTtcbiAgfVxuXG4gIC8vIEFkZCBhIGZpZWxkIHRvIHRoZSBzY2hlbWEuIElmIGRhdGFiYXNlIGRvZXMgbm90IHN1cHBvcnQgdGhlIGZpZWxkXG4gIC8vIHR5cGUgKGUuZy4gbW9uZ28gZG9lc24ndCBzdXBwb3J0IG1vcmUgdGhhbiBvbmUgR2VvUG9pbnQgaW4gYSBjbGFzcykgcmVqZWN0IHdpdGggYW4gXCJJbmNvcnJlY3QgVHlwZVwiXG4gIC8vIFBhcnNlIGVycm9yIHdpdGggYSBkZXNjaXB0aXZlIG1lc3NhZ2UuIElmIHRoZSBmaWVsZCBhbHJlYWR5IGV4aXN0cywgdGhpcyBmdW5jdGlvbiBtdXN0XG4gIC8vIG5vdCBtb2RpZnkgdGhlIHNjaGVtYSwgYW5kIG11c3QgcmVqZWN0IHdpdGggRFVQTElDQVRFX1ZBTFVFIGVycm9yLlxuICAvLyBJZiB0aGlzIGlzIGNhbGxlZCBmb3IgYSBjbGFzcyB0aGF0IGRvZXNuJ3QgZXhpc3QsIHRoaXMgZnVuY3Rpb24gbXVzdCBjcmVhdGUgdGhhdCBjbGFzcy5cblxuICAvLyBUT0RPOiB0aHJvdyBhbiBlcnJvciBpZiBhbiB1bnN1cHBvcnRlZCBmaWVsZCB0eXBlIGlzIHBhc3NlZC4gRGVjaWRpbmcgd2hldGhlciBhIHR5cGUgaXMgc3VwcG9ydGVkXG4gIC8vIHNob3VsZCBiZSB0aGUgam9iIG9mIHRoZSBhZGFwdGVyLiBTb21lIGFkYXB0ZXJzIG1heSBub3Qgc3VwcG9ydCBHZW9Qb2ludCBhdCBhbGwuIE90aGVycyBtYXlcbiAgLy8gU3VwcG9ydCBhZGRpdGlvbmFsIHR5cGVzIHRoYXQgTW9uZ28gZG9lc24ndCwgbGlrZSBNb25leSwgb3Igc29tZXRoaW5nLlxuXG4gIC8vIFRPRE86IGRvbid0IHNwZW5kIGFuIGV4dHJhIHF1ZXJ5IG9uIGZpbmRpbmcgdGhlIHNjaGVtYSBpZiB0aGUgdHlwZSB3ZSBhcmUgdHJ5aW5nIHRvIGFkZCBpc24ndCBhIEdlb1BvaW50LlxuICBhZGRGaWVsZElmTm90RXhpc3RzKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2ZldGNoT25lU2NoZW1hRnJvbV9TQ0hFTUEoY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgICAgLy8gSWYgYSBmaWVsZCB3aXRoIHRoaXMgbmFtZSBhbHJlYWR5IGV4aXN0cywgaXQgd2lsbCBiZSBoYW5kbGVkIGVsc2V3aGVyZS5cbiAgICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlIHNjaGVtYSBleGlzdHMuIENoZWNrIGZvciBleGlzdGluZyBHZW9Qb2ludHMuXG4gICAgICAgIGlmICh0eXBlLnR5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgLy8gTWFrZSBzdXJlIHRoZXJlIGFyZSBub3Qgb3RoZXIgZ2VvcG9pbnQgZmllbGRzXG4gICAgICAgICAgaWYgKE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLnNvbWUoZXhpc3RpbmdGaWVsZCA9PiBzY2hlbWEuZmllbGRzW2V4aXN0aW5nRmllbGRdLnR5cGUgPT09ICdHZW9Qb2ludCcpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsICdNb25nb0RCIG9ubHkgc3VwcG9ydHMgb25lIEdlb1BvaW50IGZpZWxkIGluIGEgY2xhc3MuJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0sIGVycm9yID0+IHtcbiAgICAgIC8vIElmIGVycm9yIGlzIHVuZGVmaW5lZCwgdGhlIHNjaGVtYSBkb2Vzbid0IGV4aXN0LCBhbmQgd2UgY2FuIGNyZWF0ZSB0aGUgc2NoZW1hIHdpdGggdGhlIGZpZWxkLlxuICAgICAgLy8gSWYgc29tZSBvdGhlciBlcnJvciwgcmVqZWN0IHdpdGggaXQuXG4gICAgICAgIGlmIChlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgIC8vIFdlIHVzZSAkZXhpc3RzIGFuZCAkc2V0IHRvIGF2b2lkIG92ZXJ3cml0aW5nIHRoZSBmaWVsZCB0eXBlIGlmIGl0XG4gICAgICAvLyBhbHJlYWR5IGV4aXN0cy4gKGl0IGNvdWxkIGhhdmUgYWRkZWQgaW5iZXR3ZWVuIHRoZSBsYXN0IHF1ZXJ5IGFuZCB0aGUgdXBkYXRlKVxuICAgICAgICByZXR1cm4gdGhpcy51cHNlcnRTY2hlbWEoXG4gICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgIHsgW2ZpZWxkTmFtZV06IHsgJyRleGlzdHMnOiBmYWxzZSB9IH0sXG4gICAgICAgICAgeyAnJHNldCcgOiB7IFtmaWVsZE5hbWVdOiBwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUodHlwZSkgfSB9XG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgfVxufVxuXG4vLyBFeHBvcnRlZCBmb3IgdGVzdGluZyByZWFzb25zIGFuZCBiZWNhdXNlIHdlIGhhdmVuJ3QgbW92ZWQgYWxsIG1vbmdvIHNjaGVtYSBmb3JtYXRcbi8vIHJlbGF0ZWQgbG9naWMgaW50byB0aGUgZGF0YWJhc2UgYWRhcHRlciB5ZXQuXG5Nb25nb1NjaGVtYUNvbGxlY3Rpb24uX1RFU1Rtb25nb1NjaGVtYVRvUGFyc2VTY2hlbWEgPSBtb25nb1NjaGVtYVRvUGFyc2VTY2hlbWFcbk1vbmdvU2NoZW1hQ29sbGVjdGlvbi5wYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUgPSBwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGVcblxuZXhwb3J0IGRlZmF1bHQgTW9uZ29TY2hlbWFDb2xsZWN0aW9uXG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js index b93ae9facd..dbd8421b3c 100644 --- a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -301,9 +301,8 @@ class MongoStorageAdapter { .then(() => this._schemaCollection()).then(schemaCollection => schemaCollection.findAndDeleteSchema(className)).catch(err => this.handleError(err)); } - // Delete all data known to this adapter. Used for testing. - deleteAllClasses() { - return storageAdapterAllCollections(this).then(collections => Promise.all(collections.map(collection => collection.drop()))).catch(err => this.handleError(err)); + deleteAllClasses(fast) { + return storageAdapterAllCollections(this).then(collections => Promise.all(collections.map(collection => fast ? collection.remove({}) : collection.drop()))); } // Remove the column and all the data. For Relations, the _Join collection is handled @@ -511,26 +510,17 @@ class MongoStorageAdapter { aggregate(className, schema, pipeline, readPreference) { let isPointerField = false; pipeline = pipeline.map(stage => { - if (stage.$group && stage.$group._id && typeof stage.$group._id === 'string') { - const field = stage.$group._id.substring(1); - if (schema.fields[field] && schema.fields[field].type === 'Pointer') { + 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; - stage.$group._id = `$_p_${field}`; } } if (stage.$match) { - for (const field in stage.$match) { - if (schema.fields[field] && schema.fields[field].type === 'Pointer') { - const transformMatch = { [`_p_${field}`]: `${className}$${stage.$match[field]}` }; - stage.$match = transformMatch; - } - if (field === 'objectId') { - const transformMatch = Object.assign({}, stage.$match); - transformMatch._id = stage.$match[field]; - delete transformMatch.objectId; - stage.$match = transformMatch; - } - } + stage.$match = this._parseAggregateArgs(schema, stage.$match); + } + if (stage.$project) { + stage.$project = this._parseAggregateProjectArgs(schema, stage.$project); } return stage; }); @@ -557,6 +547,130 @@ class MongoStorageAdapter { }).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 (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) { switch (readPreference) { case 'PRIMARY': @@ -575,8 +689,6 @@ class MongoStorageAdapter { readPreference = ReadPreference.NEAREST; break; case undefined: - // this is to match existing tests, which were failing as mongodb@3.0 don't report readPreference anymore - readPreference = ReadPreference.PRIMARY; break; default: throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, 'Not supported read preference.'); @@ -656,4 +768,5 @@ class MongoStorageAdapter { } exports.MongoStorageAdapter = MongoStorageAdapter; -exports.default = MongoStorageAdapter; \ No newline at end of file +exports.default = MongoStorageAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsibW9uZ29kYiIsInJlcXVpcmUiLCJNb25nb0NsaWVudCIsIlJlYWRQcmVmZXJlbmNlIiwiTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSIsInN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMiLCJtb25nb0FkYXB0ZXIiLCJjb25uZWN0IiwidGhlbiIsImRhdGFiYXNlIiwiY29sbGVjdGlvbnMiLCJmaWx0ZXIiLCJjb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwibWF0Y2giLCJjb2xsZWN0aW9uTmFtZSIsImluZGV4T2YiLCJfY29sbGVjdGlvblByZWZpeCIsImNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEiLCJzY2hlbWEiLCJmaWVsZHMiLCJfcnBlcm0iLCJfd3Blcm0iLCJjbGFzc05hbWUiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vbmdvT2JqZWN0IiwiX2lkIiwib2JqZWN0SWQiLCJ1cGRhdGVkQXQiLCJjcmVhdGVkQXQiLCJfbWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJmaWVsZE5hbWUiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJjbGFzc19wZXJtaXNzaW9ucyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJNb25nb1N0b3JhZ2VBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJ1cmkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsImNvbGxlY3Rpb25QcmVmaXgiLCJtb25nb09wdGlvbnMiLCJfdXJpIiwiX21vbmdvT3B0aW9ucyIsIl9tYXhUaW1lTVMiLCJtYXhUaW1lTVMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiY29ubmVjdGlvblByb21pc2UiLCJlbmNvZGVkVXJpIiwiY2xpZW50Iiwib3B0aW9ucyIsInMiLCJkYiIsImRiTmFtZSIsIm9uIiwiY2F0Y2giLCJlcnIiLCJQcm9taXNlIiwicmVqZWN0IiwiaGFuZGxlRXJyb3IiLCJlcnJvciIsImNvZGUiLCJsb2dnZXIiLCJoYW5kbGVTaHV0ZG93biIsImNsb3NlIiwiX2FkYXB0aXZlQ29sbGVjdGlvbiIsIm5hbWUiLCJyYXdDb2xsZWN0aW9uIiwiTW9uZ29Db2xsZWN0aW9uIiwiX3NjaGVtYUNvbGxlY3Rpb24iLCJjbGFzc0V4aXN0cyIsImxpc3RDb2xsZWN0aW9ucyIsInRvQXJyYXkiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2NoZW1hQ29sbGVjdGlvbiIsInVwZGF0ZVNjaGVtYSIsIiRzZXQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJyZXNvbHZlIiwiX2lkXyIsImRlbGV0ZVByb21pc2VzIiwiaW5zZXJ0ZWRJbmRleGVzIiwiZm9yRWFjaCIsImZpZWxkIiwiX19vcCIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1FVRVJZIiwicHJvbWlzZSIsImRyb3BJbmRleCIsInB1c2giLCJrZXkiLCJoYXNPd25Qcm9wZXJ0eSIsImluc2VydFByb21pc2UiLCJjcmVhdGVJbmRleGVzIiwiYWxsIiwic2V0SW5kZXhlc0Zyb21Nb25nbyIsImdldEluZGV4ZXMiLCJyZWR1Y2UiLCJvYmoiLCJpbmRleCIsIl9mdHMiLCJfZnRzeCIsIndlaWdodHMiLCJjcmVhdGVDbGFzcyIsImluc2VydFNjaGVtYSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJ0eXBlIiwiY3JlYXRlSW5kZXhlc0lmTmVlZGVkIiwiZGVsZXRlQ2xhc3MiLCJkcm9wIiwibWVzc2FnZSIsImZpbmRBbmREZWxldGVTY2hlbWEiLCJkZWxldGVBbGxDbGFzc2VzIiwiZmFzdCIsIm1hcCIsInJlbW92ZSIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJtb25nb0Zvcm1hdE5hbWVzIiwiY29sbGVjdGlvblVwZGF0ZSIsInNjaGVtYVVwZGF0ZSIsInVwZGF0ZU1hbnkiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hc0NvbGxlY3Rpb24iLCJfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEiLCJnZXRDbGFzcyIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0IiwiaW5zZXJ0T25lIiwiRFVQTElDQVRFX1ZBTFVFIiwidW5kZXJseWluZ0Vycm9yIiwibWF0Y2hlcyIsIkFycmF5IiwiaXNBcnJheSIsInVzZXJJbmZvIiwiZHVwbGljYXRlZF9maWVsZCIsImRlbGV0ZU9iamVjdHNCeVF1ZXJ5IiwicXVlcnkiLCJtb25nb1doZXJlIiwiZGVsZXRlTWFueSIsInJlc3VsdCIsIm4iLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cGRhdGUiLCJtb25nb1VwZGF0ZSIsImZpbmRPbmVBbmRVcGRhdGUiLCJfbW9uZ29Db2xsZWN0aW9uIiwiZmluZEFuZE1vZGlmeSIsIm5ldyIsInZhbHVlIiwidXBzZXJ0T25lT2JqZWN0IiwidXBzZXJ0T25lIiwiZmluZCIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJyZWFkUHJlZmVyZW5jZSIsIm1vbmdvU29ydCIsIl8iLCJtYXBLZXlzIiwibW9uZ29LZXlzIiwibWVtbyIsIl9wYXJzZVJlYWRQcmVmZXJlbmNlIiwiY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZCIsIm9iamVjdHMiLCJlbnN1cmVVbmlxdWVuZXNzIiwiaW5kZXhDcmVhdGlvblJlcXVlc3QiLCJtb25nb0ZpZWxkTmFtZXMiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJfcmF3RmluZCIsImNvdW50IiwiZGlzdGluY3QiLCJpc1BvaW50ZXJGaWVsZCIsInN1YnN0cmluZyIsImFnZ3JlZ2F0ZSIsInBpcGVsaW5lIiwic3RhZ2UiLCIkZ3JvdXAiLCJfcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3MiLCIkbWF0Y2giLCJfcGFyc2VBZ2dyZWdhdGVBcmdzIiwiJHByb2plY3QiLCJfcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyIsInJlc3VsdHMiLCJzcGxpdCIsImlzRW1wdHkiLCJyZXR1cm5WYWx1ZSIsInRhcmdldENsYXNzIiwiX2NvbnZlcnRUb0RhdGUiLCJEYXRlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJjcmVhdGVJbmRleCIsImJhY2tncm91bmQiLCIkdGV4dCIsImluZGV4TmFtZSIsInRleHRJbmRleCIsImRyb3BBbGxJbmRleGVzIiwiZHJvcEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsImNsYXNzZXMiLCJwcm9taXNlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFLQTs7QUFJQTs7QUFTQTs7OztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7OztBQUxBOztBQUVBOzs7QUFLQTtBQUNBLE1BQU1BLFVBQVVDLFFBQVEsU0FBUixDQUFoQjtBQUNBLE1BQU1DLGNBQWNGLFFBQVFFLFdBQTVCO0FBQ0EsTUFBTUMsaUJBQWlCSCxRQUFRRyxjQUEvQjs7QUFFQSxNQUFNQyw0QkFBNEIsU0FBbEM7O0FBRUEsTUFBTUMsK0JBQStCQyxnQkFBZ0I7QUFDbkQsU0FBT0EsYUFBYUMsT0FBYixHQUNKQyxJQURJLENBQ0MsTUFBTUYsYUFBYUcsUUFBYixDQUFzQkMsV0FBdEIsRUFEUCxFQUVKRixJQUZJLENBRUNFLGVBQWU7QUFDbkIsV0FBT0EsWUFBWUMsTUFBWixDQUFtQkMsY0FBYztBQUN0QyxVQUFJQSxXQUFXQyxTQUFYLENBQXFCQyxLQUFyQixDQUEyQixZQUEzQixDQUFKLEVBQThDO0FBQzVDLGVBQU8sS0FB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TCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRURvQyxZQUFVNUUsU0FBVixFQUE2QnVGLEtBQTdCLEVBQXlDO0FBQ3ZDLFdBQU8sS0FBS3RDLG1CQUFMLENBQXlCakQsU0FBekIsRUFDSmYsSUFESSxDQUNDSSxjQUFjQSxXQUFXb0osZ0JBQVgsQ0FBNEI3RCxTQUE1QixDQUFzQ1csS0FBdEMsQ0FEZixFQUVKaEQsS0FGSSxDQUVFQyxPQUFPLEtBQUtHLFdBQUwsQ0FBaUJILEdBQWpCLENBRlQsQ0FBUDtBQUdEOztBQUVEd0osaUJBQWVoTSxTQUFmLEVBQWtDO0FBQ2hDLFdBQU8sS0FBS2lELG1CQUFMLENBQXlCakQsU0FBekIsRUFDSmYsSUFESSxDQUNDSSxjQUFjQSxXQUFXb0osZ0JBQVgsQ0FBNEJ3RCxXQUE1QixFQURmLEVBRUoxSixLQUZJLENBRUVDLE9BQU8sS0FBS0csV0FBTCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRUQwSiw0QkFBd0M7QUFDdEMsV0FBTyxLQUFLcEYsYUFBTCxHQUNKN0gsSUFESSxDQUNFa04sT0FBRCxJQUFhO0FBQ2pCLFlBQU1DLFdBQVdELFFBQVE3RixHQUFSLENBQWExRyxNQUFELElBQVk7QUFDdkMsZUFBTyxLQUFLdUYsbUJBQUwsQ0FBeUJ2RixPQUFPSSxTQUFoQyxDQUFQO0FBQ0QsT0FGZ0IsQ0FBakI7QUFHQSxhQUFPeUMsUUFBUXlDLEdBQVIsQ0FBWWtILFFBQVosQ0FBUDtBQUNELEtBTkksRUFPSjdKLEtBUEksQ0FPRUMsT0FBTyxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQVBULENBQVA7QUFRRDtBQXZ0QndEOztRQUE5Q3JCLG1CLEdBQUFBLG1CO2tCQTB0QkVBLG1CIiwiZmlsZSI6Ik1vbmdvU3RvcmFnZUFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuaW1wb3J0IE1vbmdvQ29sbGVjdGlvbiAgICAgICBmcm9tICcuL01vbmdvQ29sbGVjdGlvbic7XG5pbXBvcnQgTW9uZ29TY2hlbWFDb2xsZWN0aW9uIGZyb20gJy4vTW9uZ29TY2hlbWFDb2xsZWN0aW9uJztcbmltcG9ydCB7IFN0b3JhZ2VBZGFwdGVyIH0gICAgZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHR5cGUgeyBTY2hlbWFUeXBlLFxuICBRdWVyeVR5cGUsXG4gIFN0b3JhZ2VDbGFzcyxcbiAgUXVlcnlPcHRpb25zIH0gZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHtcbiAgcGFyc2UgYXMgcGFyc2VVcmwsXG4gIGZvcm1hdCBhcyBmb3JtYXRVcmwsXG59IGZyb20gJy4uLy4uLy4uL3ZlbmRvci9tb25nb2RiVXJsJztcbmltcG9ydCB7XG4gIHBhcnNlT2JqZWN0VG9Nb25nb09iamVjdEZvckNyZWF0ZSxcbiAgbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0LFxuICB0cmFuc2Zvcm1LZXksXG4gIHRyYW5zZm9ybVdoZXJlLFxuICB0cmFuc2Zvcm1VcGRhdGUsXG4gIHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcsXG59IGZyb20gJy4vTW9uZ29UcmFuc2Zvcm0nO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgUGFyc2UgICAgICAgICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgXyAgICAgICAgICAgICAgICAgICAgIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgZGVmYXVsdHMgICAgICAgICAgICAgIGZyb20gJy4uLy4uLy4uL2RlZmF1bHRzJztcbmltcG9ydCBsb2dnZXIgICAgICAgICAgICAgICAgZnJvbSAnLi4vLi4vLi4vbG9nZ2VyJztcblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5jb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgTW9uZ29DbGllbnQgPSBtb25nb2RiLk1vbmdvQ2xpZW50O1xuY29uc3QgUmVhZFByZWZlcmVuY2UgPSBtb25nb2RiLlJlYWRQcmVmZXJlbmNlO1xuXG5jb25zdCBNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lID0gJ19TQ0hFTUEnO1xuXG5jb25zdCBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zID0gbW9uZ29BZGFwdGVyID0+IHtcbiAgcmV0dXJuIG1vbmdvQWRhcHRlci5jb25uZWN0KClcbiAgICAudGhlbigoKSA9PiBtb25nb0FkYXB0ZXIuZGF0YWJhc2UuY29sbGVjdGlvbnMoKSlcbiAgICAudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbnMuZmlsdGVyKGNvbGxlY3Rpb24gPT4ge1xuICAgICAgICBpZiAoY29sbGVjdGlvbi5uYW1lc3BhY2UubWF0Y2goL1xcLnN5c3RlbVxcLi8pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IElmIHlvdSBoYXZlIG9uZSBhcHAgd2l0aCBhIGNvbGxlY3Rpb24gcHJlZml4IHRoYXQgaGFwcGVucyB0byBiZSBhIHByZWZpeCBvZiBhbm90aGVyXG4gICAgICAgIC8vIGFwcHMgcHJlZml4LCB0aGlzIHdpbGwgZ28gdmVyeSB2ZXJ5IGJhZGx5LiBXZSBzaG91bGQgZml4IHRoYXQgc29tZWhvdy5cbiAgICAgICAgcmV0dXJuIChjb2xsZWN0aW9uLmNvbGxlY3Rpb25OYW1lLmluZGV4T2YobW9uZ29BZGFwdGVyLl9jb2xsZWN0aW9uUHJlZml4KSA9PSAwKTtcbiAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5jb25zdCBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hID0gKHsuLi5zY2hlbWF9KSA9PiB7XG4gIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9ycGVybTtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3dwZXJtO1xuXG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgLy8gTGVnYWN5IG1vbmdvIGFkYXB0ZXIga25vd3MgYWJvdXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBwYXNzd29yZCBhbmQgX2hhc2hlZF9wYXNzd29yZC5cbiAgICAvLyBGdXR1cmUgZGF0YWJhc2UgYWRhcHRlcnMgd2lsbCBvbmx5IGtub3cgYWJvdXQgX2hhc2hlZF9wYXNzd29yZC5cbiAgICAvLyBOb3RlOiBQYXJzZSBTZXJ2ZXIgd2lsbCBicmluZyBiYWNrIHBhc3N3b3JkIHdpdGggaW5qZWN0RGVmYXVsdFNjaGVtYSwgc28gd2UgZG9uJ3QgbmVlZFxuICAgIC8vIHRvIGFkZCBfaGFzaGVkX3Bhc3N3b3JkIGJhY2sgZXZlci5cbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkO1xuICB9XG5cbiAgcmV0dXJuIHNjaGVtYTtcbn1cblxuLy8gUmV0dXJucyB7IGNvZGUsIGVycm9yIH0gaWYgaW52YWxpZCwgb3IgeyByZXN1bHQgfSwgYW4gb2JqZWN0XG4vLyBzdWl0YWJsZSBmb3IgaW5zZXJ0aW5nIGludG8gX1NDSEVNQSBjb2xsZWN0aW9uLCBvdGhlcndpc2UuXG5jb25zdCBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWVBbmRDTFAgPSAoZmllbGRzLCBjbGFzc05hbWUsIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucywgaW5kZXhlcykgPT4ge1xuICBjb25zdCBtb25nb09iamVjdCA9IHtcbiAgICBfaWQ6IGNsYXNzTmFtZSxcbiAgICBvYmplY3RJZDogJ3N0cmluZycsXG4gICAgdXBkYXRlZEF0OiAnc3RyaW5nJyxcbiAgICBjcmVhdGVkQXQ6ICdzdHJpbmcnLFxuICAgIF9tZXRhZGF0YTogdW5kZWZpbmVkLFxuICB9O1xuXG4gIGZvciAoY29uc3QgZmllbGROYW1lIGluIGZpZWxkcykge1xuICAgIG1vbmdvT2JqZWN0W2ZpZWxkTmFtZV0gPSBNb25nb1NjaGVtYUNvbGxlY3Rpb24ucGFyc2VGaWVsZFR5cGVUb01vbmdvRmllbGRUeXBlKGZpZWxkc1tmaWVsZE5hbWVdKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgY2xhc3NMZXZlbFBlcm1pc3Npb25zICE9PSAndW5kZWZpbmVkJykge1xuICAgIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSA9IG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSB8fCB7fTtcbiAgICBpZiAoIWNsYXNzTGV2ZWxQZXJtaXNzaW9ucykge1xuICAgICAgZGVsZXRlIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YS5jbGFzc19wZXJtaXNzaW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zID0gY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgIH1cbiAgfVxuXG4gIGlmIChpbmRleGVzICYmIHR5cGVvZiBpbmRleGVzID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyhpbmRleGVzKS5sZW5ndGggPiAwKSB7XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhID0gbW9uZ29PYmplY3QuX21ldGFkYXRhIHx8IHt9O1xuICAgIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YS5pbmRleGVzID0gaW5kZXhlcztcbiAgfVxuXG4gIGlmICghbW9uZ29PYmplY3QuX21ldGFkYXRhKSB7IC8vIGNsZWFudXAgdGhlIHVudXNlZCBfbWV0YWRhdGFcbiAgICBkZWxldGUgbW9uZ29PYmplY3QuX21ldGFkYXRhO1xuICB9XG5cbiAgcmV0dXJuIG1vbmdvT2JqZWN0O1xufVxuXG5cbmV4cG9ydCBjbGFzcyBNb25nb1N0b3JhZ2VBZGFwdGVyIGltcGxlbWVudHMgU3RvcmFnZUFkYXB0ZXIge1xuICAvLyBQcml2YXRlXG4gIF91cmk6IHN0cmluZztcbiAgX2NvbGxlY3Rpb25QcmVmaXg6IHN0cmluZztcbiAgX21vbmdvT3B0aW9uczogT2JqZWN0O1xuICAvLyBQdWJsaWNcbiAgY29ubmVjdGlvblByb21pc2U6IFByb21pc2U8YW55PjtcbiAgZGF0YWJhc2U6IGFueTtcbiAgY2xpZW50OiBNb25nb0NsaWVudDtcbiAgX21heFRpbWVNUzogP251bWJlcjtcbiAgY2FuU29ydE9uSm9pblRhYmxlczogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcih7XG4gICAgdXJpID0gZGVmYXVsdHMuRGVmYXVsdE1vbmdvVVJJLFxuICAgIGNvbGxlY3Rpb25QcmVmaXggPSAnJyxcbiAgICBtb25nb09wdGlvbnMgPSB7fSxcbiAgfTogYW55KSB7XG4gICAgdGhpcy5fdXJpID0gdXJpO1xuICAgIHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggPSBjb2xsZWN0aW9uUHJlZml4O1xuICAgIHRoaXMuX21vbmdvT3B0aW9ucyA9IG1vbmdvT3B0aW9ucztcblxuICAgIC8vIE1heFRpbWVNUyBpcyBub3QgYSBnbG9iYWwgTW9uZ29EQiBjbGllbnQgb3B0aW9uLCBpdCBpcyBhcHBsaWVkIHBlciBvcGVyYXRpb24uXG4gICAgdGhpcy5fbWF4VGltZU1TID0gbW9uZ29PcHRpb25zLm1heFRpbWVNUztcbiAgICB0aGlzLmNhblNvcnRPbkpvaW5UYWJsZXMgPSB0cnVlO1xuICAgIGRlbGV0ZSBtb25nb09wdGlvbnMubWF4VGltZU1TO1xuICB9XG5cbiAgY29ubmVjdCgpIHtcbiAgICBpZiAodGhpcy5jb25uZWN0aW9uUHJvbWlzZSkge1xuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgfVxuXG4gICAgLy8gcGFyc2luZyBhbmQgcmUtZm9ybWF0dGluZyBjYXVzZXMgdGhlIGF1dGggdmFsdWUgKGlmIHRoZXJlKSB0byBnZXQgVVJJXG4gICAgLy8gZW5jb2RlZFxuICAgIGNvbnN0IGVuY29kZWRVcmkgPSBmb3JtYXRVcmwocGFyc2VVcmwodGhpcy5fdXJpKSk7XG5cbiAgICB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlID0gTW9uZ29DbGllbnQuY29ubmVjdChlbmNvZGVkVXJpLCB0aGlzLl9tb25nb09wdGlvbnMpLnRoZW4oY2xpZW50ID0+IHtcbiAgICAgIC8vIFN0YXJ0aW5nIG1vbmdvREIgMy4wLCB0aGUgTW9uZ29DbGllbnQuY29ubmVjdCBkb24ndCByZXR1cm4gYSBEQiBhbnltb3JlIGJ1dCBhIGNsaWVudFxuICAgICAgLy8gRm9ydHVuYXRlbHksIHdlIGNhbiBnZXQgYmFjayB0aGUgb3B0aW9ucyBhbmQgdXNlIHRoZW0gdG8gc2VsZWN0IHRoZSBwcm9wZXIgREIuXG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbW9uZ29kYi9ub2RlLW1vbmdvZGItbmF0aXZlL2Jsb2IvMmMzNWQ3NmYwODU3NDIyNWI4ZGIwMmQ3YmVmNjg3MTIzZTZiYjAxOC9saWIvbW9uZ29fY2xpZW50LmpzI0w4ODVcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSBjbGllbnQucy5vcHRpb25zO1xuICAgICAgY29uc3QgZGF0YWJhc2UgPSBjbGllbnQuZGIob3B0aW9ucy5kYk5hbWUpO1xuICAgICAgaWYgKCFkYXRhYmFzZSkge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZGF0YWJhc2Uub24oJ2Vycm9yJywgKCkgPT4ge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIH0pO1xuICAgICAgZGF0YWJhc2Uub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jbGllbnQgPSBjbGllbnQ7XG4gICAgICB0aGlzLmRhdGFiYXNlID0gZGF0YWJhc2U7XG4gICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgZGVsZXRlIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICB9XG5cbiAgaGFuZGxlRXJyb3I8VD4oZXJyb3I6ID8oRXJyb3IgfCBQYXJzZS5FcnJvcikpOiBQcm9taXNlPFQ+IHtcbiAgICBpZiAoZXJyb3IgJiYgZXJyb3IuY29kZSA9PT0gMTMpIHsgLy8gVW5hdXRob3JpemVkIGVycm9yXG4gICAgICBkZWxldGUgdGhpcy5jbGllbnQ7XG4gICAgICBkZWxldGUgdGhpcy5kYXRhYmFzZTtcbiAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgbG9nZ2VyLmVycm9yKCdSZWNlaXZlZCB1bmF1dGhvcml6ZWQgZXJyb3InLCB7IGVycm9yOiBlcnJvciB9KTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBoYW5kbGVTaHV0ZG93bigpIHtcbiAgICBpZiAoIXRoaXMuY2xpZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2xpZW50LmNsb3NlKGZhbHNlKTtcbiAgfVxuXG4gIF9hZGFwdGl2ZUNvbGxlY3Rpb24obmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdCgpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmRhdGFiYXNlLmNvbGxlY3Rpb24odGhpcy5fY29sbGVjdGlvblByZWZpeCArIG5hbWUpKVxuICAgICAgLnRoZW4ocmF3Q29sbGVjdGlvbiA9PiBuZXcgTW9uZ29Db2xsZWN0aW9uKHJhd0NvbGxlY3Rpb24pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgX3NjaGVtYUNvbGxlY3Rpb24oKTogUHJvbWlzZTxNb25nb1NjaGVtYUNvbGxlY3Rpb24+IHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KClcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lKSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gbmV3IE1vbmdvU2NoZW1hQ29sbGVjdGlvbihjb2xsZWN0aW9uKSk7XG4gIH1cblxuICBjbGFzc0V4aXN0cyhuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5kYXRhYmFzZS5saXN0Q29sbGVjdGlvbnMoeyBuYW1lOiB0aGlzLl9jb2xsZWN0aW9uUHJlZml4ICsgbmFtZSB9KS50b0FycmF5KCk7XG4gICAgfSkudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbnMubGVuZ3RoID4gMDtcbiAgICB9KS5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWU6IHN0cmluZywgQ0xQczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgJHNldDogeyAnX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zJzogQ0xQcyB9XG4gICAgICB9KSkuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWU6IHN0cmluZywgc3VibWl0dGVkSW5kZXhlczogYW55LCBleGlzdGluZ0luZGV4ZXM6IGFueSA9IHt9LCBmaWVsZHM6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChzdWJtaXR0ZWRJbmRleGVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKGV4aXN0aW5nSW5kZXhlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICBleGlzdGluZ0luZGV4ZXMgPSB7IF9pZF86IHsgX2lkOiAxfSB9O1xuICAgIH1cbiAgICBjb25zdCBkZWxldGVQcm9taXNlcyA9IFtdO1xuICAgIGNvbnN0IGluc2VydGVkSW5kZXhlcyA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEluZGV4ZXMpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb25zdCBmaWVsZCA9IHN1Ym1pdHRlZEluZGV4ZXNbbmFtZV07XG4gICAgICBpZiAoZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW5kZXggJHtuYW1lfSBleGlzdHMsIGNhbm5vdCB1cGRhdGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4aXN0aW5nSW5kZXhlc1tuYW1lXSAmJiBmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgYEluZGV4ICR7bmFtZX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBkZWxldGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuZHJvcEluZGV4KGNsYXNzTmFtZSwgbmFtZSk7XG4gICAgICAgIGRlbGV0ZVByb21pc2VzLnB1c2gocHJvbWlzZSk7XG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0luZGV4ZXNbbmFtZV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBPYmplY3Qua2V5cyhmaWVsZCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgIGlmICghZmllbGRzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgRmllbGQgJHtrZXl9IGRvZXMgbm90IGV4aXN0LCBjYW5ub3QgYWRkIGluZGV4LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGV4aXN0aW5nSW5kZXhlc1tuYW1lXSA9IGZpZWxkO1xuICAgICAgICBpbnNlcnRlZEluZGV4ZXMucHVzaCh7XG4gICAgICAgICAga2V5OiBmaWVsZCxcbiAgICAgICAgICBuYW1lLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBsZXQgaW5zZXJ0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIGlmIChpbnNlcnRlZEluZGV4ZXMubGVuZ3RoID4gMCkge1xuICAgICAgaW5zZXJ0UHJvbWlzZSA9IHRoaXMuY3JlYXRlSW5kZXhlcyhjbGFzc05hbWUsIGluc2VydGVkSW5kZXhlcyk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLmFsbChkZWxldGVQcm9taXNlcylcbiAgICAgIC50aGVuKCgpID0+IGluc2VydFByb21pc2UpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuaW5kZXhlcyc6ICBleGlzdGluZ0luZGV4ZXMgfVxuICAgICAgfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBzZXRJbmRleGVzRnJvbU1vbmdvKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0SW5kZXhlcyhjbGFzc05hbWUpLnRoZW4oKGluZGV4ZXMpID0+IHtcbiAgICAgIGluZGV4ZXMgPSBpbmRleGVzLnJlZHVjZSgob2JqLCBpbmRleCkgPT4ge1xuICAgICAgICBpZiAoaW5kZXgua2V5Ll9mdHMpIHtcbiAgICAgICAgICBkZWxldGUgaW5kZXgua2V5Ll9mdHM7XG4gICAgICAgICAgZGVsZXRlIGluZGV4LmtleS5fZnRzeDtcbiAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIGluZGV4LndlaWdodHMpIHtcbiAgICAgICAgICAgIGluZGV4LmtleVtmaWVsZF0gPSAndGV4dCc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG9ialtpbmRleC5uYW1lXSA9IGluZGV4LmtleTtcbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgIH0sIHt9KTtcbiAgICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuaW5kZXhlcyc6IGluZGV4ZXMgfVxuICAgICAgICB9KSk7XG4gICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKVxuICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgLy8gSWdub3JlIGlmIGNvbGxlY3Rpb24gbm90IGZvdW5kXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb09iamVjdCA9IG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZUFuZENMUChzY2hlbWEuZmllbGRzLCBjbGFzc05hbWUsIHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMsIHNjaGVtYS5pbmRleGVzKTtcbiAgICBtb25nb09iamVjdC5faWQgPSBjbGFzc05hbWU7XG4gICAgcmV0dXJuIHRoaXMuc2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQoY2xhc3NOYW1lLCBzY2hlbWEuaW5kZXhlcywge30sIHNjaGVtYS5maWVsZHMpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uaW5zZXJ0U2NoZW1hKG1vbmdvT2JqZWN0KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGFkZEZpZWxkSWZOb3RFeGlzdHMoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uYWRkRmllbGRJZk5vdEV4aXN0cyhjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSkpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmNyZWF0ZUluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBEcm9wcyBhIGNvbGxlY3Rpb24uIFJlc29sdmVzIHdpdGggdHJ1ZSBpZiBpdCB3YXMgYSBQYXJzZSBTY2hlbWEgKGVnLiBfVXNlciwgQ3VzdG9tLCBldGMuKVxuICAvLyBhbmQgcmVzb2x2ZXMgd2l0aCBmYWxzZSBpZiBpdCB3YXNuJ3QgKGVnLiBhIGpvaW4gdGFibGUpLiBSZWplY3RzIGlmIGRlbGV0aW9uIHdhcyBpbXBvc3NpYmxlLlxuICBkZWxldGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmRyb3AoKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAvLyAnbnMgbm90IGZvdW5kJyBtZWFucyBjb2xsZWN0aW9uIHdhcyBhbHJlYWR5IGdvbmUuIElnbm9yZSBkZWxldGlvbiBhdHRlbXB0LlxuICAgICAgICBpZiAoZXJyb3IubWVzc2FnZSA9PSAnbnMgbm90IGZvdW5kJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgLy8gV2UndmUgZHJvcHBlZCB0aGUgY29sbGVjdGlvbiwgbm93IHJlbW92ZSB0aGUgX1NDSEVNQSBkb2N1bWVudFxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLmZpbmRBbmREZWxldGVTY2hlbWEoY2xhc3NOYW1lKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRlbGV0ZUFsbENsYXNzZXMoZmFzdDogYm9vbGVhbikge1xuICAgIHJldHVybiBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zKHRoaXMpXG4gICAgICAudGhlbihjb2xsZWN0aW9ucyA9PiBQcm9taXNlLmFsbChjb2xsZWN0aW9ucy5tYXAoY29sbGVjdGlvbiA9PiBmYXN0ID8gY29sbGVjdGlvbi5yZW1vdmUoe30pIDogY29sbGVjdGlvbi5kcm9wKCkpKSk7XG4gIH1cblxuICAvLyBSZW1vdmUgdGhlIGNvbHVtbiBhbmQgYWxsIHRoZSBkYXRhLiBGb3IgUmVsYXRpb25zLCB0aGUgX0pvaW4gY29sbGVjdGlvbiBpcyBoYW5kbGVkXG4gIC8vIHNwZWNpYWxseSwgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBkZWxldGUgX0pvaW4gY29sdW1ucy4gSXQgc2hvdWxkLCBob3dldmVyLCBpbmRpY2F0ZVxuICAvLyB0aGF0IHRoZSByZWxhdGlvbiBmaWVsZHMgZG9lcyBub3QgZXhpc3QgYW55bW9yZS4gSW4gbW9uZ28sIHRoaXMgbWVhbnMgcmVtb3ZpbmcgaXQgZnJvbVxuICAvLyB0aGUgX1NDSEVNQSBjb2xsZWN0aW9uLiAgVGhlcmUgc2hvdWxkIGJlIG5vIGFjdHVhbCBkYXRhIGluIHRoZSBjb2xsZWN0aW9uIHVuZGVyIHRoZSBzYW1lIG5hbWVcbiAgLy8gYXMgdGhlIHJlbGF0aW9uIGNvbHVtbiwgc28gaXQncyBmaW5lIHRvIGF0dGVtcHQgdG8gZGVsZXRlIGl0LiBJZiB0aGUgZmllbGRzIGxpc3RlZCB0byBiZVxuICAvLyBkZWxldGVkIGRvIG5vdCBleGlzdCwgdGhpcyBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIHN1Y2Nlc3NmdWxseSBhbnl3YXlzLiBDaGVja2luZyBmb3JcbiAgLy8gYXR0ZW1wdHMgdG8gZGVsZXRlIG5vbi1leGlzdGVudCBmaWVsZHMgaXMgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIFBhcnNlIFNlcnZlci5cblxuICAvLyBQb2ludGVyIGZpZWxkIG5hbWVzIGFyZSBwYXNzZWQgZm9yIGxlZ2FjeSByZWFzb25zOiB0aGUgb3JpZ2luYWwgbW9uZ29cbiAgLy8gZm9ybWF0IHN0b3JlZCBwb2ludGVyIGZpZWxkIG5hbWVzIGRpZmZlcmVudGx5IGluIHRoZSBkYXRhYmFzZSwgYW5kIHRoZXJlZm9yZVxuICAvLyBuZWVkZWQgdG8ga25vdyB0aGUgdHlwZSBvZiB0aGUgZmllbGQgYmVmb3JlIGl0IGNvdWxkIGRlbGV0ZSBpdC4gRnV0dXJlIGRhdGFiYXNlXG4gIC8vIGFkYXB0ZXJzIHNob3VsZCBpZ25vcmUgdGhlIHBvaW50ZXJGaWVsZE5hbWVzIGFyZ3VtZW50LiBBbGwgdGhlIGZpZWxkIG5hbWVzIGFyZSBpblxuICAvLyBmaWVsZE5hbWVzLCB0aGV5IHNob3cgdXAgYWRkaXRpb25hbGx5IGluIHRoZSBwb2ludGVyRmllbGROYW1lcyBkYXRhYmFzZSBmb3IgdXNlXG4gIC8vIGJ5IHRoZSBtb25nbyBhZGFwdGVyLCB3aGljaCBkZWFscyB3aXRoIHRoZSBsZWdhY3kgbW9uZ28gZm9ybWF0LlxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gaXMgbm90IG9ibGlnYXRlZCB0byBkZWxldGUgZmllbGRzIGF0b21pY2FsbHkuIEl0IGlzIGdpdmVuIHRoZSBmaWVsZFxuICAvLyBuYW1lcyBpbiBhIGxpc3Qgc28gdGhhdCBkYXRhYmFzZXMgdGhhdCBhcmUgY2FwYWJsZSBvZiBkZWxldGluZyBmaWVsZHMgYXRvbWljYWxseVxuICAvLyBtYXkgZG8gc28uXG5cbiAgLy8gUmV0dXJucyBhIFByb21pc2UuXG4gIGRlbGV0ZUZpZWxkcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBmaWVsZE5hbWVzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IG1vbmdvRm9ybWF0TmFtZXMgPSBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuIGBfcF8ke2ZpZWxkTmFtZX1gXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZmllbGROYW1lO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGNvbnN0IGNvbGxlY3Rpb25VcGRhdGUgPSB7ICckdW5zZXQnIDoge30gfTtcbiAgICBtb25nb0Zvcm1hdE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb2xsZWN0aW9uVXBkYXRlWyckdW5zZXQnXVtuYW1lXSA9IG51bGw7XG4gICAgfSk7XG5cbiAgICBjb25zdCBzY2hlbWFVcGRhdGUgPSB7ICckdW5zZXQnIDoge30gfTtcbiAgICBmaWVsZE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBzY2hlbWFVcGRhdGVbJyR1bnNldCddW25hbWVdID0gbnVsbDtcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLnVwZGF0ZU1hbnkoe30sIGNvbGxlY3Rpb25VcGRhdGUpKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHNjaGVtYVVwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBSZXR1cm4gYSBwcm9taXNlIGZvciBhbGwgc2NoZW1hcyBrbm93biB0byB0aGlzIGFkYXB0ZXIsIGluIFBhcnNlIGZvcm1hdC4gSW4gY2FzZSB0aGVcbiAgLy8gc2NoZW1hcyBjYW5ub3QgYmUgcmV0cmlldmVkLCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMuIFJlcXVpcmVtZW50cyBmb3IgdGhlXG4gIC8vIHJlamVjdGlvbiByZWFzb24gYXJlIFRCRC5cbiAgZ2V0QWxsQ2xhc3NlcygpOiBQcm9taXNlPFN0b3JhZ2VDbGFzc1tdPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKS50aGVuKHNjaGVtYXNDb2xsZWN0aW9uID0+IHNjaGVtYXNDb2xsZWN0aW9uLl9mZXRjaEFsbFNjaGVtYXNGcm9tX1NDSEVNQSgpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgdGhlIHNjaGVtYSB3aXRoIHRoZSBnaXZlbiBuYW1lLCBpbiBQYXJzZSBmb3JtYXQuIElmXG4gIC8vIHRoaXMgYWRhcHRlciBkb2Vzbid0IGtub3cgYWJvdXQgdGhlIHNjaGVtYSwgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMgd2l0aFxuICAvLyB1bmRlZmluZWQgYXMgdGhlIHJlYXNvbi5cbiAgZ2V0Q2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFN0b3JhZ2VDbGFzcz4ge1xuICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgIC50aGVuKHNjaGVtYXNDb2xsZWN0aW9uID0+IHNjaGVtYXNDb2xsZWN0aW9uLl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BKGNsYXNzTmFtZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBUT0RPOiBBcyB5ZXQgbm90IHBhcnRpY3VsYXJseSB3ZWxsIHNwZWNpZmllZC4gQ3JlYXRlcyBhbiBvYmplY3QuIE1heWJlIHNob3VsZG4ndCBldmVuIG5lZWQgdGhlIHNjaGVtYSxcbiAgLy8gYW5kIHNob3VsZCBpbmZlciBmcm9tIHRoZSB0eXBlLiBPciBtYXliZSBkb2VzIG5lZWQgdGhlIHNjaGVtYSBmb3IgdmFsaWRhdGlvbnMuIE9yIG1heWJlIG5lZWRzXG4gIC8vIHRoZSBzY2hlbWEgb25seSBmb3IgdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQuIFdlJ2xsIGZpZ3VyZSB0aGF0IG91dCBsYXRlci5cbiAgY3JlYXRlT2JqZWN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIG9iamVjdDogYW55KSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvT2JqZWN0ID0gcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlKGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmluc2VydE9uZShtb25nb09iamVjdCkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTEwMDApIHsgLy8gRHVwbGljYXRlIHZhbHVlXG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnKTtcbiAgICAgICAgICBlcnIudW5kZXJseWluZ0Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgaWYgKGVycm9yLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBlcnJvci5tZXNzYWdlLm1hdGNoKC9pbmRleDpbXFxzYS16QS1aMC05X1xcLVxcLl0rXFwkPyhbYS16QS1aXy1dKylfMS8pO1xuICAgICAgICAgICAgaWYgKG1hdGNoZXMgJiYgQXJyYXkuaXNBcnJheShtYXRjaGVzKSkge1xuICAgICAgICAgICAgICBlcnIudXNlckluZm8gPSB7IGR1cGxpY2F0ZWRfZmllbGQ6IG1hdGNoZXNbMV0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgLy8gSWYgbm8gb2JqZWN0cyBtYXRjaCwgcmVqZWN0IHdpdGggT0JKRUNUX05PVF9GT1VORC4gSWYgb2JqZWN0cyBhcmUgZm91bmQgYW5kIGRlbGV0ZWQsIHJlc29sdmUgd2l0aCB1bmRlZmluZWQuXG4gIC8vIElmIHRoZXJlIGlzIHNvbWUgb3RoZXIgZXJyb3IsIHJlamVjdCB3aXRoIElOVEVSTkFMX1NFUlZFUl9FUlJPUi5cbiAgZGVsZXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4ge1xuICAgICAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZGVsZXRlTWFueShtb25nb1doZXJlKVxuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKVxuICAgICAgLnRoZW4oKHsgcmVzdWx0IH0pID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdC5uID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdPYmplY3Qgbm90IGZvdW5kLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0sICgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0RhdGFiYXNlIGFkYXB0ZXIgZXJyb3InKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgdXBkYXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29VcGRhdGUgPSB0cmFuc2Zvcm1VcGRhdGUoY2xhc3NOYW1lLCB1cGRhdGUsIHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29XaGVyZSA9IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24udXBkYXRlTWFueShtb25nb1doZXJlLCBtb25nb1VwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBBdG9taWNhbGx5IGZpbmRzIGFuZCB1cGRhdGVzIGFuIG9iamVjdCBiYXNlZCBvbiBxdWVyeS5cbiAgLy8gUmV0dXJuIHZhbHVlIG5vdCBjdXJyZW50bHkgd2VsbCBzcGVjaWZpZWQuXG4gIGZpbmRPbmVBbmRVcGRhdGUoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29VcGRhdGUgPSB0cmFuc2Zvcm1VcGRhdGUoY2xhc3NOYW1lLCB1cGRhdGUsIHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29XaGVyZSA9IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5maW5kQW5kTW9kaWZ5KG1vbmdvV2hlcmUsIFtdLCBtb25nb1VwZGF0ZSwgeyBuZXc6IHRydWUgfSkpXG4gICAgICAudGhlbihyZXN1bHQgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgcmVzdWx0LnZhbHVlLCBzY2hlbWEpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDExMDAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBIb3BlZnVsbHkgd2UgY2FuIGdldCByaWQgb2YgdGhpcy4gSXQncyBvbmx5IHVzZWQgZm9yIGNvbmZpZyBhbmQgaG9va3MuXG4gIHVwc2VydE9uZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB1cGRhdGU6IGFueSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi51cHNlcnRPbmUobW9uZ29XaGVyZSwgbW9uZ29VcGRhdGUpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gRXhlY3V0ZXMgYSBmaW5kLiBBY2NlcHRzOiBjbGFzc05hbWUsIHF1ZXJ5IGluIFBhcnNlIGZvcm1hdCwgYW5kIHsgc2tpcCwgbGltaXQsIHNvcnQgfS5cbiAgZmluZChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCByZWFkUHJlZmVyZW5jZSB9OiBRdWVyeU9wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1NvcnQgPSBfLm1hcEtleXMoc29ydCwgKHZhbHVlLCBmaWVsZE5hbWUpID0+IHRyYW5zZm9ybUtleShjbGFzc05hbWUsIGZpZWxkTmFtZSwgc2NoZW1hKSk7XG4gICAgY29uc3QgbW9uZ29LZXlzID0gXy5yZWR1Y2Uoa2V5cywgKG1lbW8sIGtleSkgPT4ge1xuICAgICAgbWVtb1t0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBrZXksIHNjaGVtYSldID0gMTtcbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH0sIHt9KTtcblxuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5maW5kKG1vbmdvV2hlcmUsIHtcbiAgICAgICAgc2tpcCxcbiAgICAgICAgbGltaXQsXG4gICAgICAgIHNvcnQ6IG1vbmdvU29ydCxcbiAgICAgICAga2V5czogbW9uZ29LZXlzLFxuICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICB9KSlcbiAgICAgIC50aGVuKG9iamVjdHMgPT4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSB1bmlxdWUgaW5kZXguIFVuaXF1ZSBpbmRleGVzIG9uIG51bGxhYmxlIGZpZWxkcyBhcmUgbm90IGFsbG93ZWQuIFNpbmNlIHdlIGRvbid0XG4gIC8vIGN1cnJlbnRseSBrbm93IHdoaWNoIGZpZWxkcyBhcmUgbnVsbGFibGUgYW5kIHdoaWNoIGFyZW4ndCwgd2UgaWdub3JlIHRoYXQgY3JpdGVyaWEuXG4gIC8vIEFzIHN1Y2gsIHdlIHNob3VsZG4ndCBleHBvc2UgdGhpcyBmdW5jdGlvbiB0byB1c2VycyBvZiBwYXJzZSB1bnRpbCB3ZSBoYXZlIGFuIG91dC1vZi1iYW5kXG4gIC8vIFdheSBvZiBkZXRlcm1pbmluZyBpZiBhIGZpZWxkIGlzIG51bGxhYmxlLiBVbmRlZmluZWQgZG9lc24ndCBjb3VudCBhZ2FpbnN0IHVuaXF1ZW5lc3MsXG4gIC8vIHdoaWNoIGlzIHdoeSB3ZSB1c2Ugc3BhcnNlIGluZGV4ZXMuXG4gIGVuc3VyZVVuaXF1ZW5lc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgZmllbGROYW1lczogc3RyaW5nW10pIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgaW5kZXhDcmVhdGlvblJlcXVlc3QgPSB7fTtcbiAgICBjb25zdCBtb25nb0ZpZWxkTmFtZXMgPSBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT4gdHJhbnNmb3JtS2V5KGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpKTtcbiAgICBtb25nb0ZpZWxkTmFtZXMuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaW5kZXhDcmVhdGlvblJlcXVlc3RbZmllbGROYW1lXSA9IDE7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX2Vuc3VyZVNwYXJzZVVuaXF1ZUluZGV4SW5CYWNrZ3JvdW5kKGluZGV4Q3JlYXRpb25SZXF1ZXN0KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsICdUcmllZCB0byBlbnN1cmUgZmllbGQgdW5pcXVlbmVzcyBmb3IgYSBjbGFzcyB0aGF0IGFscmVhZHkgaGFzIGR1cGxpY2F0ZXMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVXNlZCBpbiB0ZXN0c1xuICBfcmF3RmluZChjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IFF1ZXJ5VHlwZSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKS50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5maW5kKHF1ZXJ5LCB7XG4gICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICB9KSkuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGNvdW50LlxuICBjb3VudChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCByZWFkUHJlZmVyZW5jZTogP3N0cmluZykge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICByZWFkUHJlZmVyZW5jZSA9IHRoaXMuX3BhcnNlUmVhZFByZWZlcmVuY2UocmVhZFByZWZlcmVuY2UpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmNvdW50KHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSksIHtcbiAgICAgICAgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMsXG4gICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkaXN0aW5jdChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCBmaWVsZE5hbWU6IHN0cmluZykge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBpc1BvaW50ZXJGaWVsZCA9IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1BvaW50ZXInO1xuICAgIGlmIChpc1BvaW50ZXJGaWVsZCkge1xuICAgICAgZmllbGROYW1lID0gYF9wXyR7ZmllbGROYW1lfWBcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uZGlzdGluY3QoZmllbGROYW1lLCB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpKSlcbiAgICAgIC50aGVuKG9iamVjdHMgPT4ge1xuICAgICAgICBvYmplY3RzID0gb2JqZWN0cy5maWx0ZXIoKG9iaikgPT4gb2JqICE9IG51bGwpO1xuICAgICAgICByZXR1cm4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZmllbGROYW1lLnN1YnN0cmluZygzKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nKHNjaGVtYSwgZmllbGQsIG9iamVjdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGFnZ3JlZ2F0ZShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnksIHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKSB7XG4gICAgbGV0IGlzUG9pbnRlckZpZWxkID0gZmFsc2U7XG4gICAgcGlwZWxpbmUgPSBwaXBlbGluZS5tYXAoKHN0YWdlKSA9PiB7XG4gICAgICBpZiAoc3RhZ2UuJGdyb3VwKSB7XG4gICAgICAgIHN0YWdlLiRncm91cCA9IHRoaXMuX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzKHNjaGVtYSwgc3RhZ2UuJGdyb3VwKTtcbiAgICAgICAgaWYgKHN0YWdlLiRncm91cC5faWQgJiYgKHR5cGVvZiBzdGFnZS4kZ3JvdXAuX2lkID09PSAnc3RyaW5nJykgJiYgc3RhZ2UuJGdyb3VwLl9pZC5pbmRleE9mKCckX3BfJykgPj0gMCkge1xuICAgICAgICAgIGlzUG9pbnRlckZpZWxkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRtYXRjaCkge1xuICAgICAgICBzdGFnZS4kbWF0Y2ggPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hLCBzdGFnZS4kbWF0Y2gpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRwcm9qZWN0KSB7XG4gICAgICAgIHN0YWdlLiRwcm9qZWN0ID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyhzY2hlbWEsIHN0YWdlLiRwcm9qZWN0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdGFnZTtcbiAgICB9KTtcbiAgICByZWFkUHJlZmVyZW5jZSA9IHRoaXMuX3BhcnNlUmVhZFByZWZlcmVuY2UocmVhZFByZWZlcmVuY2UpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmFnZ3JlZ2F0ZShwaXBlbGluZSwgeyByZWFkUHJlZmVyZW5jZSwgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMgfSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTYwMDYpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHJlc3VsdHMuZm9yRWFjaChyZXN1bHQgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQuaGFzT3duUHJvcGVydHkoJ19pZCcpKSB7XG4gICAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQgJiYgcmVzdWx0Ll9pZCkge1xuICAgICAgICAgICAgICByZXN1bHQuX2lkID0gcmVzdWx0Ll9pZC5zcGxpdCgnJCcpWzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdC5faWQgPT0gbnVsbCB8fCBfLmlzRW1wdHkocmVzdWx0Ll9pZCkpIHtcbiAgICAgICAgICAgICAgcmVzdWx0Ll9pZCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQub2JqZWN0SWQgPSByZXN1bHQuX2lkO1xuICAgICAgICAgICAgZGVsZXRlIHJlc3VsdC5faWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiBvYmplY3RzLm1hcChvYmplY3QgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCByZWN1cnNpdmVseSB0cmF2ZXJzZSB0aGUgcGlwZWxpbmUgYW5kIGNvbnZlcnQgYW55IFBvaW50ZXIgb3IgRGF0ZSBjb2x1bW5zLlxuICAvLyBJZiB3ZSBkZXRlY3QgYSBwb2ludGVyIGNvbHVtbiB3ZSB3aWxsIHJlbmFtZSB0aGUgY29sdW1uIGJlaW5nIHF1ZXJpZWQgZm9yIHRvIG1hdGNoIHRoZSBjb2x1bW5cbiAgLy8gaW4gdGhlIGRhdGFiYXNlLiBXZSBhbHNvIG1vZGlmeSB0aGUgdmFsdWUgdG8gd2hhdCB3ZSBleHBlY3QgdGhlIHZhbHVlIHRvIGJlIGluIHRoZSBkYXRhYmFzZVxuICAvLyBhcyB3ZWxsLlxuICAvLyBGb3IgZGF0ZXMsIHRoZSBkcml2ZXIgZXhwZWN0cyBhIERhdGUgb2JqZWN0LCBidXQgd2UgaGF2ZSBhIHN0cmluZyBjb21pbmcgaW4uIFNvIHdlJ2xsIGNvbnZlcnRcbiAgLy8gdGhlIHN0cmluZyB0byBhIERhdGUgc28gdGhlIGRyaXZlciBjYW4gcGVyZm9ybSB0aGUgbmVjZXNzYXJ5IGNvbXBhcmlzb24uXG4gIC8vXG4gIC8vIFRoZSBnb2FsIG9mIHRoaXMgbWV0aG9kIGlzIHRvIGxvb2sgZm9yIHRoZSBcImxlYXZlc1wiIG9mIHRoZSBwaXBlbGluZSBhbmQgZGV0ZXJtaW5lIGlmIGl0IG5lZWRzXG4gIC8vIHRvIGJlIGNvbnZlcnRlZC4gVGhlIHBpcGVsaW5lIGNhbiBoYXZlIGEgZmV3IGRpZmZlcmVudCBmb3Jtcy4gRm9yIG1vcmUgZGV0YWlscywgc2VlOlxuICAvLyAgICAgaHR0cHM6Ly9kb2NzLm1vbmdvZGIuY29tL21hbnVhbC9yZWZlcmVuY2Uvb3BlcmF0b3IvYWdncmVnYXRpb24vXG4gIC8vXG4gIC8vIElmIHRoZSBwaXBlbGluZSBpcyBhbiBhcnJheSwgaXQgbWVhbnMgd2UgYXJlIHByb2JhYmx5IHBhcnNpbmcgYW4gJyRhbmQnIG9yICckb3InIG9wZXJhdG9yLiBJblxuICAvLyB0aGF0IGNhc2Ugd2UgbmVlZCB0byBsb29wIHRocm91Z2ggYWxsIG9mIGl0J3MgY2hpbGRyZW4gdG8gZmluZCB0aGUgY29sdW1ucyBiZWluZyBvcGVyYXRlZCBvbi5cbiAgLy8gSWYgdGhlIHBpcGVsaW5lIGlzIGFuIG9iamVjdCwgdGhlbiB3ZSdsbCBsb29wIHRocm91Z2ggdGhlIGtleXMgY2hlY2tpbmcgdG8gc2VlIGlmIHRoZSBrZXkgbmFtZVxuICAvLyBtYXRjaGVzIG9uZSBvZiB0aGUgc2NoZW1hIGNvbHVtbnMuIElmIGl0IGRvZXMgbWF0Y2ggYSBjb2x1bW4gYW5kIHRoZSBjb2x1bW4gaXMgYSBQb2ludGVyIG9yXG4gIC8vIGEgRGF0ZSwgdGhlbiB3ZSdsbCBjb252ZXJ0IHRoZSB2YWx1ZSBhcyBkZXNjcmliZWQgYWJvdmUuXG4gIC8vXG4gIC8vIEFzIG11Y2ggYXMgSSBoYXRlIHJlY3Vyc2lvbi4uLnRoaXMgc2VlbWVkIGxpa2UgYSBnb29kIGZpdCBmb3IgaXQuIFdlJ3JlIGVzc2VudGlhbGx5IHRyYXZlcnNpbmdcbiAgLy8gZG93biBhIHRyZWUgdG8gZmluZCBhIFwibGVhZiBub2RlXCIgYW5kIGNoZWNraW5nIHRvIHNlZSBpZiBpdCBuZWVkcyB0byBiZSBjb252ZXJ0ZWQuXG4gIF9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnkpOiBhbnkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHBpcGVsaW5lKSkge1xuICAgICAgcmV0dXJuIHBpcGVsaW5lLm1hcCgodmFsdWUpID0+IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHZhbHVlKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBwaXBlbGluZVtmaWVsZF0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBQYXNzIG9iamVjdHMgZG93biB0byBNb25nb0RCLi4udGhpcyBpcyBtb3JlIHRoYW4gbGlrZWx5IGFuICRleGlzdHMgb3BlcmF0b3IuXG4gICAgICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IHBpcGVsaW5lW2ZpZWxkXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWVbYF9wXyR7ZmllbGR9YF0gPSBgJHtzY2hlbWEuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzc30kJHtwaXBlbGluZVtmaWVsZF19YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ0RhdGUnKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fY29udmVydFRvRGF0ZShwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2lkJ10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2NyZWF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfdXBkYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHBpcGVsaW5lO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgb25lIGFib3ZlLiBSYXRoZXIgdGhhbiB0cnlpbmcgdG8gY29tYmluZSB0aGVzZVxuICAvLyB0d28gZnVuY3Rpb25zIGFuZCBtYWtpbmcgdGhlIGNvZGUgZXZlbiBoYXJkZXIgdG8gdW5kZXJzdGFuZCwgSSBkZWNpZGVkIHRvIHNwbGl0IGl0IHVwLiBUaGVcbiAgLy8gZGlmZmVyZW5jZSB3aXRoIHRoaXMgZnVuY3Rpb24gaXMgd2UgYXJlIG5vdCB0cmFuc2Zvcm1pbmcgdGhlIHZhbHVlcywgb25seSB0aGUga2V5cyBvZiB0aGVcbiAgLy8gcGlwZWxpbmUuXG4gIF9wYXJzZUFnZ3JlZ2F0ZVByb2plY3RBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbYF9wXyR7ZmllbGR9YF0gPSBwaXBlbGluZVtmaWVsZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hLCBwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19pZCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19jcmVhdGVkX2F0J10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX3VwZGF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgdHdvIGFib3ZlLiBNb25nb0RCICRncm91cCBhZ2dyZWdhdGUgbG9va3MgbGlrZTpcbiAgLy8gICAgIHsgJGdyb3VwOiB7IF9pZDogPGV4cHJlc3Npb24+LCA8ZmllbGQxPjogeyA8YWNjdW11bGF0b3IxPiA6IDxleHByZXNzaW9uMT4gfSwgLi4uIH0gfVxuICAvLyBUaGUgPGV4cHJlc3Npb24+IGNvdWxkIGJlIGEgY29sdW1uIG5hbWUsIHByZWZpeGVkIHdpdGggdGhlICckJyBjaGFyYWN0ZXIuIFdlJ2xsIGxvb2sgZm9yXG4gIC8vIHRoZXNlIDxleHByZXNzaW9uPiBhbmQgY2hlY2sgdG8gc2VlIGlmIGl0IGlzIGEgJ1BvaW50ZXInIG9yIGlmIGl0J3Mgb25lIG9mIGNyZWF0ZWRBdCxcbiAgLy8gdXBkYXRlZEF0IG9yIG9iamVjdElkIGFuZCBjaGFuZ2UgaXQgYWNjb3JkaW5nbHkuXG4gIF9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSk6IGFueSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICByZXR1cm4gcGlwZWxpbmUubWFwKCh2YWx1ZSkgPT4gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCB2YWx1ZSkpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTtcbiAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCBwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgZmllbGQgPSBwaXBlbGluZS5zdWJzdHJpbmcoMSk7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgIHJldHVybiBgJF9wXyR7ZmllbGR9YDtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuICckX2NyZWF0ZWRfYXQnO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm4gJyRfdXBkYXRlZF9hdCc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwaXBlbGluZTtcbiAgfVxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBhdHRlbXB0IHRvIGNvbnZlcnQgdGhlIHByb3ZpZGVkIHZhbHVlIHRvIGEgRGF0ZSBvYmplY3QuIFNpbmNlIHRoaXMgaXMgcGFydFxuICAvLyBvZiBhbiBhZ2dyZWdhdGlvbiBwaXBlbGluZSwgdGhlIHZhbHVlIGNhbiBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgaXQgY2FuIGJlIGFub3RoZXIgb2JqZWN0IHdpdGhcbiAgLy8gYW4gb3BlcmF0b3IgaW4gaXQgKGxpa2UgJGd0LCAkbHQsIGV0YykuIEJlY2F1c2Ugb2YgdGhpcyBJIGZlbHQgaXQgd2FzIGVhc2llciB0byBtYWtlIHRoaXMgYVxuICAvLyByZWN1cnNpdmUgbWV0aG9kIHRvIHRyYXZlcnNlIGRvd24gdG8gdGhlIFwibGVhZiBub2RlXCIgd2hpY2ggaXMgZ29pbmcgdG8gYmUgdGhlIHN0cmluZy5cbiAgX2NvbnZlcnRUb0RhdGUodmFsdWU6IGFueSk6IGFueSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fVxuICAgIGZvciAoY29uc3QgZmllbGQgaW4gdmFsdWUpIHtcbiAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX2NvbnZlcnRUb0RhdGUodmFsdWVbZmllbGRdKVxuICAgIH1cbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cblxuICBfcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZTogP3N0cmluZyk6ID9zdHJpbmcge1xuICAgIHN3aXRjaCAocmVhZFByZWZlcmVuY2UpIHtcbiAgICBjYXNlICdQUklNQVJZJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1BSSU1BUllfUFJFRkVSUkVEJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWV9QUkVGRVJSRUQ7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdTRUNPTkRBUlknOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5TRUNPTkRBUlk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdTRUNPTkRBUllfUFJFRkVSUkVEJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuU0VDT05EQVJZX1BSRUZFUlJFRDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ05FQVJFU1QnOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5ORUFSRVNUO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSB1bmRlZmluZWQ6XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksICdOb3Qgc3VwcG9ydGVkIHJlYWQgcHJlZmVyZW5jZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgcGVyZm9ybUluaXRpYWxpemF0aW9uKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4KGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleDogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5jcmVhdGVJbmRleChpbmRleCwge2JhY2tncm91bmQ6IHRydWV9KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4ZXMoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4ZXM6IGFueSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uY3JlYXRlSW5kZXhlcyhpbmRleGVzLCB7YmFja2dyb3VuZDogdHJ1ZX0pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZywgdHlwZTogYW55KSB7XG4gICAgaWYgKHR5cGUgJiYgdHlwZS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgIGNvbnN0IGluZGV4ID0ge1xuICAgICAgICBbZmllbGROYW1lXTogJzJkc3BoZXJlJ1xuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUluZGV4KGNsYXNzTmFtZSwgaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBjcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogUXVlcnlUeXBlLCBzY2hlbWE6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvcihjb25zdCBmaWVsZE5hbWUgaW4gcXVlcnkpIHtcbiAgICAgIGlmICghcXVlcnlbZmllbGROYW1lXSB8fCAhcXVlcnlbZmllbGROYW1lXS4kdGV4dCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4aXN0aW5nSW5kZXhlcyA9IHNjaGVtYS5pbmRleGVzO1xuICAgICAgZm9yIChjb25zdCBrZXkgaW4gZXhpc3RpbmdJbmRleGVzKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gZXhpc3RpbmdJbmRleGVzW2tleV07XG4gICAgICAgIGlmIChpbmRleC5oYXNPd25Qcm9wZXJ0eShmaWVsZE5hbWUpKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBpbmRleE5hbWUgPSBgJHtmaWVsZE5hbWV9X3RleHRgO1xuICAgICAgY29uc3QgdGV4dEluZGV4ID0ge1xuICAgICAgICBbaW5kZXhOYW1lXTogeyBbZmllbGROYW1lXTogJ3RleHQnIH1cbiAgICAgIH07XG4gICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWUsIHRleHRJbmRleCwgZXhpc3RpbmdJbmRleGVzLCBzY2hlbWEuZmllbGRzKVxuICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDg1KSB7IC8vIEluZGV4IGV4aXN0IHdpdGggZGlmZmVyZW50IG9wdGlvbnNcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNGcm9tTW9uZ28oY2xhc3NOYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBnZXRJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5pbmRleGVzKCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wSW5kZXgoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmRyb3BJbmRleChpbmRleCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wQWxsSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uZHJvcEluZGV4ZXMoKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzKCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QWxsQ2xhc3NlcygpXG4gICAgICAudGhlbigoY2xhc3NlcykgPT4ge1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IGNsYXNzZXMubWFwKChzY2hlbWEpID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzRnJvbU1vbmdvKHNjaGVtYS5jbGFzc05hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTW9uZ29TdG9yYWdlQWRhcHRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoTransform.js b/lib/Adapters/Storage/Mongo/MongoTransform.js index 0931dd48d8..f3e4261c03 100644 --- a/lib/Adapters/Storage/Mongo/MongoTransform.js +++ b/lib/Adapters/Storage/Mongo/MongoTransform.js @@ -141,6 +141,44 @@ const transformKeyValueForUpdate = (className, restKey, restValue, parseFormatSc 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"); @@ -230,9 +268,9 @@ function transformQueryKeyValue(className, key, value, schema) { case '_email_verify_token': return { key, value }; case '$or': - return { key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema)) }; case '$and': - return { key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, schema)) }; + case '$nor': + return { key: key, value: value.map(subQuery => transformWhere(className, subQuery, schema)) }; case 'lastUsed': if (valueAsDate(value)) { return { key: '_last_used', value: valueAsDate(value) }; @@ -268,6 +306,9 @@ function transformQueryKeyValue(className, key, value, schema) { if (transformedConstraint.$text) { return { key: '$text', value: transformedConstraint.$text }; } + if (transformedConstraint.$elemMatch) { + return { key: '$nor', value: [{ [key]: transformedConstraint }] }; + } return { key, value: transformedConstraint }; } @@ -483,6 +524,8 @@ const transformInteriorAtom = 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; } @@ -757,6 +800,12 @@ function transformConstraint(constraint, field) { 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': @@ -767,6 +816,17 @@ function transformConstraint(constraint, field) { 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; @@ -839,23 +899,58 @@ function transformConstraint(constraint, field) { case '$geoWithin': { const polygon = constraint[key]['$polygon']; - if (!(polygon instanceof Array)) { - throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); - } - if (polygon.length < 3) { - throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); - } - const points = polygon.map(point => { - if (!GeoPointCoder.isValidJSON(point)) { - throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value'); + 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 { - Parse.GeoPoint._validate(point.latitude, point.longitude); + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint\'s'); } - return [point.longitude, point.latitude]; - }); - answer[key] = { - '$polygon': points - }; + 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': @@ -1325,4 +1420,5 @@ module.exports = { relativeTimeToDate, transformConstraint, transformPointerString -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvVHJhbnNmb3JtLmpzIl0sIm5hbWVzIjpbIm1vbmdvZGIiLCJyZXF1aXJlIiwiUGFyc2UiLCJ0cmFuc2Zvcm1LZXkiLCJjbGFzc05hbWUiLCJmaWVsZE5hbWUiLCJzY2hlbWEiLCJmaWVsZHMiLCJfX3R5cGUiLCJ0eXBlIiwidHJhbnNmb3JtS2V5VmFsdWVGb3JVcGRhdGUiLCJyZXN0S2V5IiwicmVzdFZhbHVlIiwicGFyc2VGb3JtYXRTY2hlbWEiLCJrZXkiLCJ0aW1lRmllbGQiLCJ2YWx1ZSIsInBhcnNlSW50IiwidHJhbnNmb3JtVG9wTGV2ZWxBdG9tIiwiQ2Fubm90VHJhbnNmb3JtIiwiRGF0ZSIsImluZGV4T2YiLCJBcnJheSIsIm1hcCIsInRyYW5zZm9ybUludGVyaW9yVmFsdWUiLCJ0cmFuc2Zvcm1VcGRhdGVPcGVyYXRvciIsIm1hcFZhbHVlcyIsImlzUmVnZXgiLCJSZWdFeHAiLCJpc1N0YXJ0c1dpdGhSZWdleCIsIm1hdGNoZXMiLCJ0b1N0cmluZyIsIm1hdGNoIiwiaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSIsInZhbHVlcyIsImlzQXJyYXkiLCJsZW5ndGgiLCJmaXJzdFZhbHVlc0lzUmVnZXgiLCJpIiwiaXNBbnlWYWx1ZVJlZ2V4Iiwic29tZSIsIk9iamVjdCIsImtleXMiLCJpbmNsdWRlcyIsIkVycm9yIiwiSU5WQUxJRF9ORVNURURfS0VZIiwidHJhbnNmb3JtSW50ZXJpb3JBdG9tIiwidmFsdWVBc0RhdGUiLCJ0cmFuc2Zvcm1RdWVyeUtleVZhbHVlIiwic3ViUXVlcnkiLCJ0cmFuc2Zvcm1XaGVyZSIsImF1dGhEYXRhTWF0Y2giLCJwcm92aWRlciIsImV4cGVjdGVkVHlwZUlzQXJyYXkiLCJleHBlY3RlZFR5cGVJc1BvaW50ZXIiLCJmaWVsZCIsInRyYW5zZm9ybWVkQ29uc3RyYWludCIsInRyYW5zZm9ybUNvbnN0cmFpbnQiLCIkdGV4dCIsIiRlbGVtTWF0Y2giLCJJTlZBTElEX0pTT04iLCJyZXN0V2hlcmUiLCJtb25nb1doZXJlIiwib3V0IiwicGFyc2VPYmplY3RLZXlWYWx1ZVRvTW9uZ29PYmplY3RLZXlWYWx1ZSIsInRyYW5zZm9ybWVkVmFsdWUiLCJjb2VyY2VkVG9EYXRlIiwiSU5WQUxJRF9LRVlfTkFNRSIsInBhcnNlT2JqZWN0VG9Nb25nb09iamVjdEZvckNyZWF0ZSIsInJlc3RDcmVhdGUiLCJhZGRMZWdhY3lBQ0wiLCJtb25nb0NyZWF0ZSIsInVuZGVmaW5lZCIsImNyZWF0ZWRBdCIsIl9jcmVhdGVkX2F0IiwiaXNvIiwidXBkYXRlZEF0IiwiX3VwZGF0ZWRfYXQiLCJ0cmFuc2Zvcm1VcGRhdGUiLCJyZXN0VXBkYXRlIiwibW9uZ29VcGRhdGUiLCJhY2wiLCJfcnBlcm0iLCJfd3Blcm0iLCJfYWNsIiwiJHNldCIsIl9fb3AiLCJhcmciLCJyZXN0T2JqZWN0IiwicmVzdE9iamVjdENvcHkiLCJmb3JFYWNoIiwiZW50cnkiLCJ3IiwiciIsImF0b20iLCJvYmplY3RJZCIsIkRhdGVDb2RlciIsImlzVmFsaWRKU09OIiwiSlNPTlRvRGF0YWJhc2UiLCJCeXRlc0NvZGVyIiwiJHJlZ2V4IiwidGFyZ2V0Q2xhc3MiLCJHZW9Qb2ludENvZGVyIiwiUG9seWdvbkNvZGVyIiwiRmlsZUNvZGVyIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwicmVsYXRpdmVUaW1lVG9EYXRlIiwidGV4dCIsIm5vdyIsInRvTG93ZXJDYXNlIiwicGFydHMiLCJzcGxpdCIsImZpbHRlciIsInBhcnQiLCJmdXR1cmUiLCJwYXN0Iiwic3RhdHVzIiwiaW5mbyIsInNsaWNlIiwicGFpcnMiLCJwdXNoIiwic2hpZnQiLCJzZWNvbmRzIiwibnVtIiwiaW50ZXJ2YWwiLCJ2YWwiLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJtaWxsaXNlY29uZHMiLCJyZXN1bHQiLCJ2YWx1ZU9mIiwiY29uc3RyYWludCIsImluQXJyYXkiLCJ0cmFuc2Zvcm1GdW5jdGlvbiIsInRyYW5zZm9ybWVyIiwiSlNPTiIsInN0cmluZ2lmeSIsInNvcnQiLCJyZXZlcnNlIiwiYW5zd2VyIiwiJHJlbGF0aXZlVGltZSIsInBhcnNlclJlc3VsdCIsImxvZyIsImFyciIsIl8iLCJmbGF0TWFwIiwicyIsIiRuaW4iLCJzZWFyY2giLCIkc2VhcmNoIiwiJHRlcm0iLCIkbGFuZ3VhZ2UiLCIkY2FzZVNlbnNpdGl2ZSIsIiRkaWFjcml0aWNTZW5zaXRpdmUiLCJwb2ludCIsImxvbmdpdHVkZSIsImxhdGl0dWRlIiwiQ09NTUFORF9VTkFWQUlMQUJMRSIsImJveCIsInBvbHlnb24iLCJjZW50ZXJTcGhlcmUiLCJwb2ludHMiLCJjb29yZGluYXRlcyIsIkdlb1BvaW50IiwiX3ZhbGlkYXRlIiwiZGlzdGFuY2UiLCJpc05hTiIsIiRnZW9tZXRyeSIsImFtb3VudCIsIm9iamVjdHMiLCJmbGF0dGVuIiwidG9BZGQiLCJtb25nb09wIiwiQWRkIiwiQWRkVW5pcXVlIiwidG9SZW1vdmUiLCJvYmplY3QiLCJpdGVyYXRvciIsIm5lc3RlZE1vbmdvT2JqZWN0VG9OZXN0ZWRQYXJzZU9iamVjdCIsIm1vbmdvT2JqZWN0IiwiX2VuY29kZSIsIkxvbmciLCJ0b051bWJlciIsIkRvdWJsZSIsImlzVmFsaWREYXRhYmFzZU9iamVjdCIsImRhdGFiYXNlVG9KU09OIiwiaGFzT3duUHJvcGVydHkiLCJ0b0pTT04iLCJ0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nIiwicG9pbnRlclN0cmluZyIsIm9iakRhdGEiLCJtb25nb09iamVjdFRvUGFyc2VPYmplY3QiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibmV3S2V5Iiwic3Vic3RyaW5nIiwicmVsYXRpb25GaWVsZE5hbWVzIiwicmVsYXRpb25GaWVsZHMiLCJyZWxhdGlvbkZpZWxkTmFtZSIsImpzb24iLCJiYXNlNjRQYXR0ZXJuIiwiaXNCYXNlNjRWYWx1ZSIsInRlc3QiLCJidWZmZXIiLCJiYXNlNjQiLCJCaW5hcnkiLCJCdWZmZXIiLCJjb29yZHMiLCJjb29yZCIsInBhcnNlRmxvYXQiLCJ1bmlxdWUi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SixJQUVOQSxNQUFNUixNQUFOLEtBQWlCLFNBRm5CO0FBSUQ7QUFoRWdCLENBQW5COztBQW1FQSxJQUFJZ0csWUFBWTtBQUNkaUYsaUJBQWVULE1BQWYsRUFBdUI7QUFDckIsV0FBTztBQUNMeEssY0FBUSxNQURIO0FBRUwrTSxZQUFNdkM7QUFGRCxLQUFQO0FBSUQsR0FOYTs7QUFRZFEsd0JBQXNCUixNQUF0QixFQUE4QjtBQUM1QixXQUFRLE9BQU9BLE1BQVAsS0FBa0IsUUFBMUI7QUFDRCxHQVZhOztBQVlkOUUsaUJBQWVvRyxJQUFmLEVBQXFCO0FBQ25CLFdBQU9BLEtBQUtpQixJQUFaO0FBQ0QsR0FkYTs7QUFnQmR0SCxjQUFZakYsS0FBWixFQUFtQjtBQUNqQixXQUFRLE9BQU9BLEtBQVAsS0FBaUIsUUFBakIsSUFDTkEsVUFBVSxJQURKLElBRU5BLE1BQU1SLE1BQU4sS0FBaUIsTUFGbkI7QUFJRDtBQXJCYSxDQUFoQjs7QUF3QkFnTixPQUFPQyxPQUFQLEdBQWlCO0FBQ2Z0TixjQURlO0FBRWZpRSxtQ0FGZTtBQUdmVSxpQkFIZTtBQUlmNUIsZ0JBSmU7QUFLZjZJLDBCQUxlO0FBTWZyRixvQkFOZTtBQU9makQscUJBUGU7QUFRZm1JO0FBUmUsQ0FBakIiLCJmaWxlIjoiTW9uZ29UcmFuc2Zvcm0uanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbG9nIGZyb20gJy4uLy4uLy4uL2xvZ2dlcic7XG5pbXBvcnQgXyAgIGZyb20gJ2xvZGFzaCc7XG52YXIgbW9uZ29kYiA9IHJlcXVpcmUoJ21vbmdvZGInKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxuY29uc3QgdHJhbnNmb3JtS2V5ID0gKGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpID0+IHtcbiAgLy8gQ2hlY2sgaWYgdGhlIHNjaGVtYSBpcyBrbm93biBzaW5jZSBpdCdzIGEgYnVpbHQtaW4gZmllbGQuXG4gIHN3aXRjaChmaWVsZE5hbWUpIHtcbiAgY2FzZSAnb2JqZWN0SWQnOiByZXR1cm4gJ19pZCc7XG4gIGNhc2UgJ2NyZWF0ZWRBdCc6IHJldHVybiAnX2NyZWF0ZWRfYXQnO1xuICBjYXNlICd1cGRhdGVkQXQnOiByZXR1cm4gJ191cGRhdGVkX2F0JztcbiAgY2FzZSAnc2Vzc2lvblRva2VuJzogcmV0dXJuICdfc2Vzc2lvbl90b2tlbic7XG4gIGNhc2UgJ2xhc3RVc2VkJzogcmV0dXJuICdfbGFzdF91c2VkJztcbiAgY2FzZSAndGltZXNVc2VkJzogcmV0dXJuICd0aW1lc191c2VkJztcbiAgfVxuXG4gIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLl9fdHlwZSA9PSAnUG9pbnRlcicpIHtcbiAgICBmaWVsZE5hbWUgPSAnX3BfJyArIGZpZWxkTmFtZTtcbiAgfSBlbHNlIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT0gJ1BvaW50ZXInKSB7XG4gICAgZmllbGROYW1lID0gJ19wXycgKyBmaWVsZE5hbWU7XG4gIH1cblxuICByZXR1cm4gZmllbGROYW1lO1xufVxuXG5jb25zdCB0cmFuc2Zvcm1LZXlWYWx1ZUZvclVwZGF0ZSA9IChjbGFzc05hbWUsIHJlc3RLZXksIHJlc3RWYWx1ZSwgcGFyc2VGb3JtYXRTY2hlbWEpID0+IHtcbiAgLy8gQ2hlY2sgaWYgdGhlIHNjaGVtYSBpcyBrbm93biBzaW5jZSBpdCdzIGEgYnVpbHQtaW4gZmllbGQuXG4gIHZhciBrZXkgPSByZXN0S2V5O1xuICB2YXIgdGltZUZpZWxkID0gZmFsc2U7XG4gIHN3aXRjaChrZXkpIHtcbiAgY2FzZSAnb2JqZWN0SWQnOlxuICBjYXNlICdfaWQnOlxuICAgIGlmIChjbGFzc05hbWUgPT09ICdfR2xvYmFsQ29uZmlnJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAga2V5OiBrZXksXG4gICAgICAgIHZhbHVlOiBwYXJzZUludChyZXN0VmFsdWUpXG4gICAgICB9XG4gICAgfVxuICAgIGtleSA9ICdfaWQnO1xuICAgIGJyZWFrO1xuICBjYXNlICdjcmVhdGVkQXQnOlxuICBjYXNlICdfY3JlYXRlZF9hdCc6XG4gICAga2V5ID0gJ19jcmVhdGVkX2F0JztcbiAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgIGJyZWFrO1xuICBjYXNlICd1cGRhdGVkQXQnOlxuICBjYXNlICdfdXBkYXRlZF9hdCc6XG4gICAga2V5ID0gJ191cGRhdGVkX2F0JztcbiAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgIGJyZWFrO1xuICBjYXNlICdzZXNzaW9uVG9rZW4nOlxuICBjYXNlICdfc2Vzc2lvbl90b2tlbic6XG4gICAga2V5ID0gJ19zZXNzaW9uX3Rva2VuJztcbiAgICBicmVhaztcbiAgY2FzZSAnZXhwaXJlc0F0JzpcbiAgY2FzZSAnX2V4cGlyZXNBdCc6XG4gICAga2V5ID0gJ2V4cGlyZXNBdCc7XG4gICAgdGltZUZpZWxkID0gdHJ1ZTtcbiAgICBicmVhaztcbiAgY2FzZSAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0JzpcbiAgICBrZXkgPSAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0JztcbiAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgIGJyZWFrO1xuICBjYXNlICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnOlxuICAgIGtleSA9ICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnO1xuICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgJ19mYWlsZWRfbG9naW5fY291bnQnOlxuICAgIGtleSA9ICdfZmFpbGVkX2xvZ2luX2NvdW50JztcbiAgICBicmVhaztcbiAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAga2V5ID0gJ19wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQnO1xuICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgJ19wYXNzd29yZF9jaGFuZ2VkX2F0JzpcbiAgICBrZXkgPSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnO1xuICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgJ19ycGVybSc6XG4gIGNhc2UgJ193cGVybSc6XG4gICAgcmV0dXJuIHtrZXk6IGtleSwgdmFsdWU6IHJlc3RWYWx1ZX07XG4gIGNhc2UgJ2xhc3RVc2VkJzpcbiAgY2FzZSAnX2xhc3RfdXNlZCc6XG4gICAga2V5ID0gJ19sYXN0X3VzZWQnO1xuICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgJ3RpbWVzVXNlZCc6XG4gIGNhc2UgJ3RpbWVzX3VzZWQnOlxuICAgIGtleSA9ICd0aW1lc191c2VkJztcbiAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgIGJyZWFrO1xuICB9XG5cbiAgaWYgKChwYXJzZUZvcm1hdFNjaGVtYS5maWVsZHNba2V5XSAmJiBwYXJzZUZvcm1hdFNjaGVtYS5maWVsZHNba2V5XS50eXBlID09PSAnUG9pbnRlcicpIHx8ICghcGFyc2VGb3JtYXRTY2hlbWEuZmllbGRzW2tleV0gJiYgcmVzdFZhbHVlICYmIHJlc3RWYWx1ZS5fX3R5cGUgPT0gJ1BvaW50ZXInKSkge1xuICAgIGtleSA9ICdfcF8nICsga2V5O1xuICB9XG5cbiAgLy8gSGFuZGxlIGF0b21pYyB2YWx1ZXNcbiAgdmFyIHZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gIGlmICh2YWx1ZSAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgaWYgKHRpbWVGaWVsZCAmJiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykpIHtcbiAgICAgIHZhbHVlID0gbmV3IERhdGUodmFsdWUpO1xuICAgIH1cbiAgICBpZiAocmVzdEtleS5pbmRleE9mKCcuJykgPiAwKSB7XG4gICAgICByZXR1cm4ge2tleSwgdmFsdWU6IHJlc3RWYWx1ZX1cbiAgICB9XG4gICAgcmV0dXJuIHtrZXksIHZhbHVlfTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBhcnJheXNcbiAgaWYgKHJlc3RWYWx1ZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgdmFsdWUgPSByZXN0VmFsdWUubWFwKHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xuICAgIHJldHVybiB7a2V5LCB2YWx1ZX07XG4gIH1cblxuICAvLyBIYW5kbGUgdXBkYXRlIG9wZXJhdG9yc1xuICBpZiAodHlwZW9mIHJlc3RWYWx1ZSA9PT0gJ29iamVjdCcgJiYgJ19fb3AnIGluIHJlc3RWYWx1ZSkge1xuICAgIHJldHVybiB7a2V5LCB2YWx1ZTogdHJhbnNmb3JtVXBkYXRlT3BlcmF0b3IocmVzdFZhbHVlLCBmYWxzZSl9O1xuICB9XG5cbiAgLy8gSGFuZGxlIG5vcm1hbCBvYmplY3RzIGJ5IHJlY3Vyc2luZ1xuICB2YWx1ZSA9IG1hcFZhbHVlcyhyZXN0VmFsdWUsIHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xuICByZXR1cm4ge2tleSwgdmFsdWV9O1xufVxuXG5jb25zdCBpc1JlZ2V4ID0gdmFsdWUgPT4ge1xuICByZXR1cm4gdmFsdWUgJiYgKHZhbHVlIGluc3RhbmNlb2YgUmVnRXhwKVxufVxuXG5jb25zdCBpc1N0YXJ0c1dpdGhSZWdleCA9IHZhbHVlID0+IHtcbiAgaWYgKCFpc1JlZ2V4KHZhbHVlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IG1hdGNoZXMgPSB2YWx1ZS50b1N0cmluZygpLm1hdGNoKC9cXC9cXF5cXFxcUS4qXFxcXEVcXC8vKTtcbiAgcmV0dXJuICEhbWF0Y2hlcztcbn1cblxuY29uc3QgaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSA9IHZhbHVlcyA9PiB7XG4gIGlmICghdmFsdWVzIHx8ICFBcnJheS5pc0FycmF5KHZhbHVlcykgfHwgdmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgZmlyc3RWYWx1ZXNJc1JlZ2V4ID0gaXNTdGFydHNXaXRoUmVnZXgodmFsdWVzWzBdKTtcbiAgaWYgKHZhbHVlcy5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZXNJc1JlZ2V4O1xuICB9XG5cbiAgZm9yIChsZXQgaSA9IDEsIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGg7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGlmIChmaXJzdFZhbHVlc0lzUmVnZXggIT09IGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlc1tpXSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuY29uc3QgaXNBbnlWYWx1ZVJlZ2V4ID0gdmFsdWVzID0+IHtcbiAgcmV0dXJuIHZhbHVlcy5zb21lKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBpc1JlZ2V4KHZhbHVlKTtcbiAgfSk7XG59XG5cbmNvbnN0IHRyYW5zZm9ybUludGVyaW9yVmFsdWUgPSByZXN0VmFsdWUgPT4ge1xuICBpZiAocmVzdFZhbHVlICE9PSBudWxsICYmIHR5cGVvZiByZXN0VmFsdWUgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKHJlc3RWYWx1ZSkuc29tZShrZXkgPT4ga2V5LmluY2x1ZGVzKCckJykgfHwga2V5LmluY2x1ZGVzKCcuJykpKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfTkVTVEVEX0tFWSwgXCJOZXN0ZWQga2V5cyBzaG91bGQgbm90IGNvbnRhaW4gdGhlICckJyBvciAnLicgY2hhcmFjdGVyc1wiKTtcbiAgfVxuICAvLyBIYW5kbGUgYXRvbWljIHZhbHVlc1xuICB2YXIgdmFsdWUgPSB0cmFuc2Zvcm1JbnRlcmlvckF0b20ocmVzdFZhbHVlKTtcbiAgaWYgKHZhbHVlICE9PSBDYW5ub3RUcmFuc2Zvcm0pIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICAvLyBIYW5kbGUgYXJyYXlzXG4gIGlmIChyZXN0VmFsdWUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHJldHVybiByZXN0VmFsdWUubWFwKHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xuICB9XG5cbiAgLy8gSGFuZGxlIHVwZGF0ZSBvcGVyYXRvcnNcbiAgaWYgKHR5cGVvZiByZXN0VmFsdWUgPT09ICdvYmplY3QnICYmICdfX29wJyBpbiByZXN0VmFsdWUpIHtcbiAgICByZXR1cm4gdHJhbnNmb3JtVXBkYXRlT3BlcmF0b3IocmVzdFZhbHVlLCB0cnVlKTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBub3JtYWwgb2JqZWN0cyBieSByZWN1cnNpbmdcbiAgcmV0dXJuIG1hcFZhbHVlcyhyZXN0VmFsdWUsIHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xufVxuXG5jb25zdCB2YWx1ZUFzRGF0ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gbmV3IERhdGUodmFsdWUpO1xuICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybVF1ZXJ5S2V5VmFsdWUoY2xhc3NOYW1lLCBrZXksIHZhbHVlLCBzY2hlbWEpIHtcbiAgc3dpdGNoKGtleSkge1xuICBjYXNlICdjcmVhdGVkQXQnOlxuICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB7a2V5OiAnX2NyZWF0ZWRfYXQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpfVxuICAgIH1cbiAgICBrZXkgPSAnX2NyZWF0ZWRfYXQnO1xuICAgIGJyZWFrO1xuICBjYXNlICd1cGRhdGVkQXQnOlxuICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB7a2V5OiAnX3VwZGF0ZWRfYXQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpfVxuICAgIH1cbiAgICBrZXkgPSAnX3VwZGF0ZWRfYXQnO1xuICAgIGJyZWFrO1xuICBjYXNlICdleHBpcmVzQXQnOlxuICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB7a2V5OiAnZXhwaXJlc0F0JywgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKX1cbiAgICB9XG4gICAgYnJlYWs7XG4gIGNhc2UgJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHtrZXk6ICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpfVxuICAgIH1cbiAgICBicmVhaztcbiAgY2FzZSAnb2JqZWN0SWQnOiB7XG4gICAgaWYgKGNsYXNzTmFtZSA9PT0gJ19HbG9iYWxDb25maWcnKSB7XG4gICAgICB2YWx1ZSA9IHBhcnNlSW50KHZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIHtrZXk6ICdfaWQnLCB2YWx1ZX1cbiAgfVxuICBjYXNlICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnOlxuICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB7a2V5OiAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JywgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKX1cbiAgICB9XG4gICAgYnJlYWs7XG4gIGNhc2UgJ19mYWlsZWRfbG9naW5fY291bnQnOlxuICAgIHJldHVybiB7a2V5LCB2YWx1ZX07XG4gIGNhc2UgJ3Nlc3Npb25Ub2tlbic6IHJldHVybiB7a2V5OiAnX3Nlc3Npb25fdG9rZW4nLCB2YWx1ZX1cbiAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHsga2V5OiAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCcsIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSkgfVxuICAgIH1cbiAgICBicmVhaztcbiAgY2FzZSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnOlxuICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB7IGtleTogJ19wYXNzd29yZF9jaGFuZ2VkX2F0JywgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKSB9XG4gICAgfVxuICAgIGJyZWFrO1xuICBjYXNlICdfcnBlcm0nOlxuICBjYXNlICdfd3Blcm0nOlxuICBjYXNlICdfcGVyaXNoYWJsZV90b2tlbic6XG4gIGNhc2UgJ19lbWFpbF92ZXJpZnlfdG9rZW4nOiByZXR1cm4ge2tleSwgdmFsdWV9XG4gIGNhc2UgJyRvcic6XG4gIGNhc2UgJyRhbmQnOlxuICBjYXNlICckbm9yJzpcbiAgICByZXR1cm4ge2tleToga2V5LCB2YWx1ZTogdmFsdWUubWFwKHN1YlF1ZXJ5ID0+IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgc3ViUXVlcnksIHNjaGVtYSkpfTtcbiAgY2FzZSAnbGFzdFVzZWQnOlxuICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB7a2V5OiAnX2xhc3RfdXNlZCcsIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSl9XG4gICAgfVxuICAgIGtleSA9ICdfbGFzdF91c2VkJztcbiAgICBicmVhaztcbiAgY2FzZSAndGltZXNVc2VkJzpcbiAgICByZXR1cm4ge2tleTogJ3RpbWVzX3VzZWQnLCB2YWx1ZTogdmFsdWV9O1xuICBkZWZhdWx0OiB7XG4gICAgLy8gT3RoZXIgYXV0aCBkYXRhXG4gICAgY29uc3QgYXV0aERhdGFNYXRjaCA9IGtleS5tYXRjaCgvXmF1dGhEYXRhXFwuKFthLXpBLVowLTlfXSspXFwuaWQkLyk7XG4gICAgaWYgKGF1dGhEYXRhTWF0Y2gpIHtcbiAgICAgIGNvbnN0IHByb3ZpZGVyID0gYXV0aERhdGFNYXRjaFsxXTtcbiAgICAgIC8vIFNwZWNpYWwtY2FzZSBhdXRoIGRhdGEuXG4gICAgICByZXR1cm4ge2tleTogYF9hdXRoX2RhdGFfJHtwcm92aWRlcn0uaWRgLCB2YWx1ZX07XG4gICAgfVxuICB9XG4gIH1cblxuICBjb25zdCBleHBlY3RlZFR5cGVJc0FycmF5ID1cbiAgICBzY2hlbWEgJiZcbiAgICBzY2hlbWEuZmllbGRzW2tleV0gJiZcbiAgICBzY2hlbWEuZmllbGRzW2tleV0udHlwZSA9PT0gJ0FycmF5JztcblxuICBjb25zdCBleHBlY3RlZFR5cGVJc1BvaW50ZXIgPVxuICAgIHNjaGVtYSAmJlxuICAgIHNjaGVtYS5maWVsZHNba2V5XSAmJlxuICAgIHNjaGVtYS5maWVsZHNba2V5XS50eXBlID09PSAnUG9pbnRlcic7XG5cbiAgY29uc3QgZmllbGQgPSBzY2hlbWEgJiYgc2NoZW1hLmZpZWxkc1trZXldO1xuICBpZiAoZXhwZWN0ZWRUeXBlSXNQb2ludGVyIHx8ICFzY2hlbWEgJiYgdmFsdWUgJiYgdmFsdWUuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICBrZXkgPSAnX3BfJyArIGtleTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBxdWVyeSBjb25zdHJhaW50c1xuICBjb25zdCB0cmFuc2Zvcm1lZENvbnN0cmFpbnQgPSB0cmFuc2Zvcm1Db25zdHJhaW50KHZhbHVlLCBmaWVsZCk7XG4gIGlmICh0cmFuc2Zvcm1lZENvbnN0cmFpbnQgIT09IENhbm5vdFRyYW5zZm9ybSkge1xuICAgIGlmICh0cmFuc2Zvcm1lZENvbnN0cmFpbnQuJHRleHQpIHtcbiAgICAgIHJldHVybiB7a2V5OiAnJHRleHQnLCB2YWx1ZTogdHJhbnNmb3JtZWRDb25zdHJhaW50LiR0ZXh0fTtcbiAgICB9XG4gICAgaWYgKHRyYW5zZm9ybWVkQ29uc3RyYWludC4kZWxlbU1hdGNoKSB7XG4gICAgICByZXR1cm4geyBrZXk6ICckbm9yJywgdmFsdWU6IFt7IFtrZXldOiB0cmFuc2Zvcm1lZENvbnN0cmFpbnQgfV0gfTtcbiAgICB9XG4gICAgcmV0dXJuIHtrZXksIHZhbHVlOiB0cmFuc2Zvcm1lZENvbnN0cmFpbnR9O1xuICB9XG5cbiAgaWYgKGV4cGVjdGVkVHlwZUlzQXJyYXkgJiYgISh2YWx1ZSBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgIHJldHVybiB7a2V5LCB2YWx1ZTogeyAnJGFsbCcgOiBbdHJhbnNmb3JtSW50ZXJpb3JBdG9tKHZhbHVlKV0gfX07XG4gIH1cblxuICAvLyBIYW5kbGUgYXRvbWljIHZhbHVlc1xuICBpZiAodHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHZhbHVlKSAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgcmV0dXJuIHtrZXksIHZhbHVlOiB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20odmFsdWUpfTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgWW91IGNhbm5vdCB1c2UgJHt2YWx1ZX0gYXMgYSBxdWVyeSBwYXJhbWV0ZXIuYCk7XG4gIH1cbn1cblxuLy8gTWFpbiBleHBvc2VkIG1ldGhvZCB0byBoZWxwIHJ1biBxdWVyaWVzLlxuLy8gcmVzdFdoZXJlIGlzIHRoZSBcIndoZXJlXCIgY2xhdXNlIGluIFJFU1QgQVBJIGZvcm0uXG4vLyBSZXR1cm5zIHRoZSBtb25nbyBmb3JtIG9mIHRoZSBxdWVyeS5cbmZ1bmN0aW9uIHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcmVzdFdoZXJlLCBzY2hlbWEpIHtcbiAgY29uc3QgbW9uZ29XaGVyZSA9IHt9O1xuICBmb3IgKGNvbnN0IHJlc3RLZXkgaW4gcmVzdFdoZXJlKSB7XG4gICAgY29uc3Qgb3V0ID0gdHJhbnNmb3JtUXVlcnlLZXlWYWx1ZShjbGFzc05hbWUsIHJlc3RLZXksIHJlc3RXaGVyZVtyZXN0S2V5XSwgc2NoZW1hKTtcbiAgICBtb25nb1doZXJlW291dC5rZXldID0gb3V0LnZhbHVlO1xuICB9XG4gIHJldHVybiBtb25nb1doZXJlO1xufVxuXG5jb25zdCBwYXJzZU9iamVjdEtleVZhbHVlVG9Nb25nb09iamVjdEtleVZhbHVlID0gKHJlc3RLZXksIHJlc3RWYWx1ZSwgc2NoZW1hKSA9PiB7XG4gIC8vIENoZWNrIGlmIHRoZSBzY2hlbWEgaXMga25vd24gc2luY2UgaXQncyBhIGJ1aWx0LWluIGZpZWxkLlxuICBsZXQgdHJhbnNmb3JtZWRWYWx1ZTtcbiAgbGV0IGNvZXJjZWRUb0RhdGU7XG4gIHN3aXRjaChyZXN0S2V5KSB7XG4gIGNhc2UgJ29iamVjdElkJzogcmV0dXJuIHtrZXk6ICdfaWQnLCB2YWx1ZTogcmVzdFZhbHVlfTtcbiAgY2FzZSAnZXhwaXJlc0F0JzpcbiAgICB0cmFuc2Zvcm1lZFZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gICAgY29lcmNlZFRvRGF0ZSA9IHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlID09PSAnc3RyaW5nJyA/IG5ldyBEYXRlKHRyYW5zZm9ybWVkVmFsdWUpIDogdHJhbnNmb3JtZWRWYWx1ZVxuICAgIHJldHVybiB7a2V5OiAnZXhwaXJlc0F0JywgdmFsdWU6IGNvZXJjZWRUb0RhdGV9O1xuICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgIHRyYW5zZm9ybWVkVmFsdWUgPSB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20ocmVzdFZhbHVlKTtcbiAgICBjb2VyY2VkVG9EYXRlID0gdHlwZW9mIHRyYW5zZm9ybWVkVmFsdWUgPT09ICdzdHJpbmcnID8gbmV3IERhdGUodHJhbnNmb3JtZWRWYWx1ZSkgOiB0cmFuc2Zvcm1lZFZhbHVlXG4gICAgcmV0dXJuIHtrZXk6ICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnLCB2YWx1ZTogY29lcmNlZFRvRGF0ZX07XG4gIGNhc2UgJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCc6XG4gICAgdHJhbnNmb3JtZWRWYWx1ZSA9IHRyYW5zZm9ybVRvcExldmVsQXRvbShyZXN0VmFsdWUpO1xuICAgIGNvZXJjZWRUb0RhdGUgPSB0eXBlb2YgdHJhbnNmb3JtZWRWYWx1ZSA9PT0gJ3N0cmluZycgPyBuZXcgRGF0ZSh0cmFuc2Zvcm1lZFZhbHVlKSA6IHRyYW5zZm9ybWVkVmFsdWVcbiAgICByZXR1cm4ge2tleTogJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCcsIHZhbHVlOiBjb2VyY2VkVG9EYXRlfTtcbiAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAgdHJhbnNmb3JtZWRWYWx1ZSA9IHRyYW5zZm9ybVRvcExldmVsQXRvbShyZXN0VmFsdWUpO1xuICAgIGNvZXJjZWRUb0RhdGUgPSB0eXBlb2YgdHJhbnNmb3JtZWRWYWx1ZSA9PT0gJ3N0cmluZycgPyBuZXcgRGF0ZSh0cmFuc2Zvcm1lZFZhbHVlKSA6IHRyYW5zZm9ybWVkVmFsdWVcbiAgICByZXR1cm4geyBrZXk6ICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JywgdmFsdWU6IGNvZXJjZWRUb0RhdGUgfTtcbiAgY2FzZSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnOlxuICAgIHRyYW5zZm9ybWVkVmFsdWUgPSB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20ocmVzdFZhbHVlKTtcbiAgICBjb2VyY2VkVG9EYXRlID0gdHlwZW9mIHRyYW5zZm9ybWVkVmFsdWUgPT09ICdzdHJpbmcnID8gbmV3IERhdGUodHJhbnNmb3JtZWRWYWx1ZSkgOiB0cmFuc2Zvcm1lZFZhbHVlXG4gICAgcmV0dXJuIHsga2V5OiAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnLCB2YWx1ZTogY29lcmNlZFRvRGF0ZSB9O1xuICBjYXNlICdfZmFpbGVkX2xvZ2luX2NvdW50JzpcbiAgY2FzZSAnX3JwZXJtJzpcbiAgY2FzZSAnX3dwZXJtJzpcbiAgY2FzZSAnX2VtYWlsX3ZlcmlmeV90b2tlbic6XG4gIGNhc2UgJ19oYXNoZWRfcGFzc3dvcmQnOlxuICBjYXNlICdfcGVyaXNoYWJsZV90b2tlbic6IHJldHVybiB7a2V5OiByZXN0S2V5LCB2YWx1ZTogcmVzdFZhbHVlfTtcbiAgY2FzZSAnc2Vzc2lvblRva2VuJzogcmV0dXJuIHtrZXk6ICdfc2Vzc2lvbl90b2tlbicsIHZhbHVlOiByZXN0VmFsdWV9O1xuICBkZWZhdWx0OlxuICAgIC8vIEF1dGggZGF0YSBzaG91bGQgaGF2ZSBiZWVuIHRyYW5zZm9ybWVkIGFscmVhZHlcbiAgICBpZiAocmVzdEtleS5tYXRjaCgvXmF1dGhEYXRhXFwuKFthLXpBLVowLTlfXSspXFwuaWQkLykpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLCAnY2FuIG9ubHkgcXVlcnkgb24gJyArIHJlc3RLZXkpO1xuICAgIH1cbiAgICAvLyBUcnVzdCB0aGF0IHRoZSBhdXRoIGRhdGEgaGFzIGJlZW4gdHJhbnNmb3JtZWQgYW5kIHNhdmUgaXQgZGlyZWN0bHlcbiAgICBpZiAocmVzdEtleS5tYXRjaCgvXl9hdXRoX2RhdGFfW2EtekEtWjAtOV9dKyQvKSkge1xuICAgICAgcmV0dXJuIHtrZXk6IHJlc3RLZXksIHZhbHVlOiByZXN0VmFsdWV9O1xuICAgIH1cbiAgfVxuICAvL3NraXAgc3RyYWlnaHQgdG8gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tIGZvciBCeXRlcywgdGhleSBkb24ndCBzaG93IHVwIGluIHRoZSBzY2hlbWEgZm9yIHNvbWUgcmVhc29uXG4gIGlmIChyZXN0VmFsdWUgJiYgcmVzdFZhbHVlLl9fdHlwZSAhPT0gJ0J5dGVzJykge1xuICAgIC8vTm90ZTogV2UgbWF5IG5vdCBrbm93IHRoZSB0eXBlIG9mIGEgZmllbGQgaGVyZSwgYXMgdGhlIHVzZXIgY291bGQgYmUgc2F2aW5nIChudWxsKSB0byBhIGZpZWxkXG4gICAgLy9UaGF0IG5ldmVyIGV4aXN0ZWQgYmVmb3JlLCBtZWFuaW5nIHdlIGNhbid0IGluZmVyIHRoZSB0eXBlLlxuICAgIGlmIChzY2hlbWEuZmllbGRzW3Jlc3RLZXldICYmIHNjaGVtYS5maWVsZHNbcmVzdEtleV0udHlwZSA9PSAnUG9pbnRlcicgfHwgcmVzdFZhbHVlLl9fdHlwZSA9PSAnUG9pbnRlcicpIHtcbiAgICAgIHJlc3RLZXkgPSAnX3BfJyArIHJlc3RLZXk7XG4gICAgfVxuICB9XG5cbiAgLy8gSGFuZGxlIGF0b21pYyB2YWx1ZXNcbiAgdmFyIHZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gIGlmICh2YWx1ZSAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgcmV0dXJuIHtrZXk6IHJlc3RLZXksIHZhbHVlOiB2YWx1ZX07XG4gIH1cblxuICAvLyBBQ0xzIGFyZSBoYW5kbGVkIGJlZm9yZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWRcbiAgLy8gSWYgYW4gQUNMIGtleSBzdGlsbCBleGlzdHMgaGVyZSwgc29tZXRoaW5nIGlzIHdyb25nLlxuICBpZiAocmVzdEtleSA9PT0gJ0FDTCcpIHtcbiAgICB0aHJvdyAnVGhlcmUgd2FzIGEgcHJvYmxlbSB0cmFuc2Zvcm1pbmcgYW4gQUNMLic7XG4gIH1cblxuICAvLyBIYW5kbGUgYXJyYXlzXG4gIGlmIChyZXN0VmFsdWUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHZhbHVlID0gcmVzdFZhbHVlLm1hcCh0cmFuc2Zvcm1JbnRlcmlvclZhbHVlKTtcbiAgICByZXR1cm4ge2tleTogcmVzdEtleSwgdmFsdWU6IHZhbHVlfTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBub3JtYWwgb2JqZWN0cyBieSByZWN1cnNpbmdcbiAgaWYgKE9iamVjdC5rZXlzKHJlc3RWYWx1ZSkuc29tZShrZXkgPT4ga2V5LmluY2x1ZGVzKCckJykgfHwga2V5LmluY2x1ZGVzKCcuJykpKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfTkVTVEVEX0tFWSwgXCJOZXN0ZWQga2V5cyBzaG91bGQgbm90IGNvbnRhaW4gdGhlICckJyBvciAnLicgY2hhcmFjdGVyc1wiKTtcbiAgfVxuICB2YWx1ZSA9IG1hcFZhbHVlcyhyZXN0VmFsdWUsIHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xuICByZXR1cm4ge2tleTogcmVzdEtleSwgdmFsdWV9O1xufVxuXG5jb25zdCBwYXJzZU9iamVjdFRvTW9uZ29PYmplY3RGb3JDcmVhdGUgPSAoY2xhc3NOYW1lLCByZXN0Q3JlYXRlLCBzY2hlbWEpID0+IHtcbiAgcmVzdENyZWF0ZSA9IGFkZExlZ2FjeUFDTChyZXN0Q3JlYXRlKTtcbiAgY29uc3QgbW9uZ29DcmVhdGUgPSB7fVxuICBmb3IgKGNvbnN0IHJlc3RLZXkgaW4gcmVzdENyZWF0ZSkge1xuICAgIGlmIChyZXN0Q3JlYXRlW3Jlc3RLZXldICYmIHJlc3RDcmVhdGVbcmVzdEtleV0uX190eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgeyBrZXksIHZhbHVlIH0gPSBwYXJzZU9iamVjdEtleVZhbHVlVG9Nb25nb09iamVjdEtleVZhbHVlKFxuICAgICAgcmVzdEtleSxcbiAgICAgIHJlc3RDcmVhdGVbcmVzdEtleV0sXG4gICAgICBzY2hlbWFcbiAgICApO1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBtb25nb0NyZWF0ZVtrZXldID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgLy8gVXNlIHRoZSBsZWdhY3kgbW9uZ28gZm9ybWF0IGZvciBjcmVhdGVkQXQgYW5kIHVwZGF0ZWRBdFxuICBpZiAobW9uZ29DcmVhdGUuY3JlYXRlZEF0KSB7XG4gICAgbW9uZ29DcmVhdGUuX2NyZWF0ZWRfYXQgPSBuZXcgRGF0ZShtb25nb0NyZWF0ZS5jcmVhdGVkQXQuaXNvIHx8IG1vbmdvQ3JlYXRlLmNyZWF0ZWRBdCk7XG4gICAgZGVsZXRlIG1vbmdvQ3JlYXRlLmNyZWF0ZWRBdDtcbiAgfVxuICBpZiAobW9uZ29DcmVhdGUudXBkYXRlZEF0KSB7XG4gICAgbW9uZ29DcmVhdGUuX3VwZGF0ZWRfYXQgPSBuZXcgRGF0ZShtb25nb0NyZWF0ZS51cGRhdGVkQXQuaXNvIHx8IG1vbmdvQ3JlYXRlLnVwZGF0ZWRBdCk7XG4gICAgZGVsZXRlIG1vbmdvQ3JlYXRlLnVwZGF0ZWRBdDtcbiAgfVxuXG4gIHJldHVybiBtb25nb0NyZWF0ZTtcbn1cblxuLy8gTWFpbiBleHBvc2VkIG1ldGhvZCB0byBoZWxwIHVwZGF0ZSBvbGQgb2JqZWN0cy5cbmNvbnN0IHRyYW5zZm9ybVVwZGF0ZSA9IChjbGFzc05hbWUsIHJlc3RVcGRhdGUsIHBhcnNlRm9ybWF0U2NoZW1hKSA9PiB7XG4gIGNvbnN0IG1vbmdvVXBkYXRlID0ge307XG4gIGNvbnN0IGFjbCA9IGFkZExlZ2FjeUFDTChyZXN0VXBkYXRlKTtcbiAgaWYgKGFjbC5fcnBlcm0gfHwgYWNsLl93cGVybSB8fCBhY2wuX2FjbCkge1xuICAgIG1vbmdvVXBkYXRlLiRzZXQgPSB7fTtcbiAgICBpZiAoYWNsLl9ycGVybSkge1xuICAgICAgbW9uZ29VcGRhdGUuJHNldC5fcnBlcm0gPSBhY2wuX3JwZXJtO1xuICAgIH1cbiAgICBpZiAoYWNsLl93cGVybSkge1xuICAgICAgbW9uZ29VcGRhdGUuJHNldC5fd3Blcm0gPSBhY2wuX3dwZXJtO1xuICAgIH1cbiAgICBpZiAoYWNsLl9hY2wpIHtcbiAgICAgIG1vbmdvVXBkYXRlLiRzZXQuX2FjbCA9IGFjbC5fYWNsO1xuICAgIH1cbiAgfVxuICBmb3IgKHZhciByZXN0S2V5IGluIHJlc3RVcGRhdGUpIHtcbiAgICBpZiAocmVzdFVwZGF0ZVtyZXN0S2V5XSAmJiByZXN0VXBkYXRlW3Jlc3RLZXldLl9fdHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHZhciBvdXQgPSB0cmFuc2Zvcm1LZXlWYWx1ZUZvclVwZGF0ZShjbGFzc05hbWUsIHJlc3RLZXksIHJlc3RVcGRhdGVbcmVzdEtleV0sIHBhcnNlRm9ybWF0U2NoZW1hKTtcblxuICAgIC8vIElmIHRoZSBvdXRwdXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW55ICQga2V5cywgaXQncyBhblxuICAgIC8vIG9wZXJhdG9yIHRoYXQgbmVlZHMgdG8gYmUgbGlmdGVkIG9udG8gdGhlIHRvcCBsZXZlbCB1cGRhdGVcbiAgICAvLyBvYmplY3QuXG4gICAgaWYgKHR5cGVvZiBvdXQudmFsdWUgPT09ICdvYmplY3QnICYmIG91dC52YWx1ZSAhPT0gbnVsbCAmJiBvdXQudmFsdWUuX19vcCkge1xuICAgICAgbW9uZ29VcGRhdGVbb3V0LnZhbHVlLl9fb3BdID0gbW9uZ29VcGRhdGVbb3V0LnZhbHVlLl9fb3BdIHx8IHt9O1xuICAgICAgbW9uZ29VcGRhdGVbb3V0LnZhbHVlLl9fb3BdW291dC5rZXldID0gb3V0LnZhbHVlLmFyZztcbiAgICB9IGVsc2Uge1xuICAgICAgbW9uZ29VcGRhdGVbJyRzZXQnXSA9IG1vbmdvVXBkYXRlWyckc2V0J10gfHwge307XG4gICAgICBtb25nb1VwZGF0ZVsnJHNldCddW291dC5rZXldID0gb3V0LnZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtb25nb1VwZGF0ZTtcbn1cblxuLy8gQWRkIHRoZSBsZWdhY3kgX2FjbCBmb3JtYXQuXG5jb25zdCBhZGRMZWdhY3lBQ0wgPSByZXN0T2JqZWN0ID0+IHtcbiAgY29uc3QgcmVzdE9iamVjdENvcHkgPSB7Li4ucmVzdE9iamVjdH07XG4gIGNvbnN0IF9hY2wgPSB7fTtcblxuICBpZiAocmVzdE9iamVjdC5fd3Blcm0pIHtcbiAgICByZXN0T2JqZWN0Ll93cGVybS5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIF9hY2xbZW50cnldID0geyB3OiB0cnVlIH07XG4gICAgfSk7XG4gICAgcmVzdE9iamVjdENvcHkuX2FjbCA9IF9hY2w7XG4gIH1cblxuICBpZiAocmVzdE9iamVjdC5fcnBlcm0pIHtcbiAgICByZXN0T2JqZWN0Ll9ycGVybS5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIGlmICghKGVudHJ5IGluIF9hY2wpKSB7XG4gICAgICAgIF9hY2xbZW50cnldID0geyByOiB0cnVlIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfYWNsW2VudHJ5XS5yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXN0T2JqZWN0Q29weS5fYWNsID0gX2FjbDtcbiAgfVxuXG4gIHJldHVybiByZXN0T2JqZWN0Q29weTtcbn1cblxuXG4vLyBBIHNlbnRpbmVsIHZhbHVlIHRoYXQgaGVscGVyIHRyYW5zZm9ybWF0aW9ucyByZXR1cm4gd2hlbiB0aGV5XG4vLyBjYW5ub3QgcGVyZm9ybSBhIHRyYW5zZm9ybWF0aW9uXG5mdW5jdGlvbiBDYW5ub3RUcmFuc2Zvcm0oKSB7fVxuXG5jb25zdCB0cmFuc2Zvcm1JbnRlcmlvckF0b20gPSAoYXRvbSkgPT4ge1xuICAvLyBUT0RPOiBjaGVjayB2YWxpZGl0eSBoYXJkZXIgZm9yIHRoZSBfX3R5cGUtZGVmaW5lZCB0eXBlc1xuICBpZiAodHlwZW9mIGF0b20gPT09ICdvYmplY3QnICYmIGF0b20gJiYgIShhdG9tIGluc3RhbmNlb2YgRGF0ZSkgJiYgYXRvbS5fX3R5cGUgPT09ICdQb2ludGVyJykge1xuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgIGNsYXNzTmFtZTogYXRvbS5jbGFzc05hbWUsXG4gICAgICBvYmplY3RJZDogYXRvbS5vYmplY3RJZFxuICAgIH07XG4gIH0gZWxzZSBpZiAodHlwZW9mIGF0b20gPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGF0b20gPT09ICdzeW1ib2wnKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgYGNhbm5vdCB0cmFuc2Zvcm0gdmFsdWU6ICR7YXRvbX1gKTtcbiAgfSBlbHNlIGlmIChEYXRlQ29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICByZXR1cm4gRGF0ZUNvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICB9IGVsc2UgaWYgKEJ5dGVzQ29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICByZXR1cm4gQnl0ZXNDb2Rlci5KU09OVG9EYXRhYmFzZShhdG9tKTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgYXRvbSA9PT0gJ29iamVjdCcgJiYgYXRvbSAmJiBhdG9tLiRyZWdleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoYXRvbS4kcmVnZXgpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBhdG9tO1xuICB9XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byB0cmFuc2Zvcm0gYW4gYXRvbSBmcm9tIFJFU1QgZm9ybWF0IHRvIE1vbmdvIGZvcm1hdC5cbi8vIEFuIGF0b20gaXMgYW55dGhpbmcgdGhhdCBjYW4ndCBjb250YWluIG90aGVyIGV4cHJlc3Npb25zLiBTbyBpdFxuLy8gaW5jbHVkZXMgdGhpbmdzIHdoZXJlIG9iamVjdHMgYXJlIHVzZWQgdG8gcmVwcmVzZW50IG90aGVyXG4vLyBkYXRhdHlwZXMsIGxpa2UgcG9pbnRlcnMgYW5kIGRhdGVzLCBidXQgaXQgZG9lcyBub3QgaW5jbHVkZSBvYmplY3RzXG4vLyBvciBhcnJheXMgd2l0aCBnZW5lcmljIHN0dWZmIGluc2lkZS5cbi8vIFJhaXNlcyBhbiBlcnJvciBpZiB0aGlzIGNhbm5vdCBwb3NzaWJseSBiZSB2YWxpZCBSRVNUIGZvcm1hdC5cbi8vIFJldHVybnMgQ2Fubm90VHJhbnNmb3JtIGlmIGl0J3MganVzdCBub3QgYW4gYXRvbVxuZnVuY3Rpb24gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKGF0b20sIGZpZWxkKSB7XG4gIHN3aXRjaCh0eXBlb2YgYXRvbSkge1xuICBjYXNlICdudW1iZXInOlxuICBjYXNlICdib29sZWFuJzpcbiAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICByZXR1cm4gYXRvbTtcbiAgY2FzZSAnc3RyaW5nJzpcbiAgICBpZiAoZmllbGQgJiYgZmllbGQudHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICByZXR1cm4gYCR7ZmllbGQudGFyZ2V0Q2xhc3N9JCR7YXRvbX1gO1xuICAgIH1cbiAgICByZXR1cm4gYXRvbTtcbiAgY2FzZSAnc3ltYm9sJzpcbiAgY2FzZSAnZnVuY3Rpb24nOlxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sIGBjYW5ub3QgdHJhbnNmb3JtIHZhbHVlOiAke2F0b219YCk7XG4gIGNhc2UgJ29iamVjdCc6XG4gICAgaWYgKGF0b20gaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAvLyBUZWNobmljYWxseSBkYXRlcyBhcmUgbm90IHJlc3QgZm9ybWF0LCBidXQsIGl0IHNlZW1zIHByZXR0eVxuICAgICAgLy8gY2xlYXIgd2hhdCB0aGV5IHNob3VsZCBiZSB0cmFuc2Zvcm1lZCB0bywgc28gbGV0J3MganVzdCBkbyBpdC5cbiAgICAgIHJldHVybiBhdG9tO1xuICAgIH1cblxuICAgIGlmIChhdG9tID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gYXRvbTtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBjaGVjayB2YWxpZGl0eSBoYXJkZXIgZm9yIHRoZSBfX3R5cGUtZGVmaW5lZCB0eXBlc1xuICAgIGlmIChhdG9tLl9fdHlwZSA9PSAnUG9pbnRlcicpIHtcbiAgICAgIHJldHVybiBgJHthdG9tLmNsYXNzTmFtZX0kJHthdG9tLm9iamVjdElkfWA7XG4gICAgfVxuICAgIGlmIChEYXRlQ29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICAgIHJldHVybiBEYXRlQ29kZXIuSlNPTlRvRGF0YWJhc2UoYXRvbSk7XG4gICAgfVxuICAgIGlmIChCeXRlc0NvZGVyLmlzVmFsaWRKU09OKGF0b20pKSB7XG4gICAgICByZXR1cm4gQnl0ZXNDb2Rlci5KU09OVG9EYXRhYmFzZShhdG9tKTtcbiAgICB9XG4gICAgaWYgKEdlb1BvaW50Q29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICAgIHJldHVybiBHZW9Qb2ludENvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICAgIH1cbiAgICBpZiAoUG9seWdvbkNvZGVyLmlzVmFsaWRKU09OKGF0b20pKSB7XG4gICAgICByZXR1cm4gUG9seWdvbkNvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICAgIH1cbiAgICBpZiAoRmlsZUNvZGVyLmlzVmFsaWRKU09OKGF0b20pKSB7XG4gICAgICByZXR1cm4gRmlsZUNvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICAgIH1cbiAgICByZXR1cm4gQ2Fubm90VHJhbnNmb3JtO1xuXG4gIGRlZmF1bHQ6XG4gICAgLy8gSSBkb24ndCB0aGluayB0eXBlb2YgY2FuIGV2ZXIgbGV0IHVzIGdldCBoZXJlXG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgYHJlYWxseSBkaWQgbm90IGV4cGVjdCB2YWx1ZTogJHthdG9tfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbGF0aXZlVGltZVRvRGF0ZSh0ZXh0LCBub3cgPSBuZXcgRGF0ZSgpKSB7XG4gIHRleHQgPSB0ZXh0LnRvTG93ZXJDYXNlKCk7XG5cbiAgbGV0IHBhcnRzID0gdGV4dC5zcGxpdCgnICcpO1xuXG4gIC8vIEZpbHRlciBvdXQgd2hpdGVzcGFjZVxuICBwYXJ0cyA9IHBhcnRzLmZpbHRlcigocGFydCkgPT4gcGFydCAhPT0gJycpO1xuXG4gIGNvbnN0IGZ1dHVyZSA9IHBhcnRzWzBdID09PSAnaW4nO1xuICBjb25zdCBwYXN0ID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gPT09ICdhZ28nO1xuXG4gIGlmICghZnV0dXJlICYmICFwYXN0ICYmIHRleHQgIT09ICdub3cnKSB7XG4gICAgcmV0dXJuIHsgc3RhdHVzOiAnZXJyb3InLCBpbmZvOiBcIlRpbWUgc2hvdWxkIGVpdGhlciBzdGFydCB3aXRoICdpbicgb3IgZW5kIHdpdGggJ2FnbydcIiB9O1xuICB9XG5cbiAgaWYgKGZ1dHVyZSAmJiBwYXN0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogJ2Vycm9yJyxcbiAgICAgIGluZm86IFwiVGltZSBjYW5ub3QgaGF2ZSBib3RoICdpbicgYW5kICdhZ28nXCIsXG4gICAgfTtcbiAgfVxuXG4gIC8vIHN0cmlwIHRoZSAnYWdvJyBvciAnaW4nXG4gIGlmIChmdXR1cmUpIHtcbiAgICBwYXJ0cyA9IHBhcnRzLnNsaWNlKDEpO1xuICB9IGVsc2UgeyAvLyBwYXN0XG4gICAgcGFydHMgPSBwYXJ0cy5zbGljZSgwLCBwYXJ0cy5sZW5ndGggLSAxKTtcbiAgfVxuXG4gIGlmIChwYXJ0cy5sZW5ndGggJSAyICE9PSAwICYmIHRleHQgIT09ICdub3cnKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogJ2Vycm9yJyxcbiAgICAgIGluZm86ICdJbnZhbGlkIHRpbWUgc3RyaW5nLiBEYW5nbGluZyB1bml0IG9yIG51bWJlci4nLFxuICAgIH07XG4gIH1cblxuICBjb25zdCBwYWlycyA9IFtdO1xuICB3aGlsZShwYXJ0cy5sZW5ndGgpIHtcbiAgICBwYWlycy5wdXNoKFsgcGFydHMuc2hpZnQoKSwgcGFydHMuc2hpZnQoKSBdKTtcbiAgfVxuXG4gIGxldCBzZWNvbmRzID0gMDtcbiAgZm9yIChjb25zdCBbbnVtLCBpbnRlcnZhbF0gb2YgcGFpcnMpIHtcbiAgICBjb25zdCB2YWwgPSBOdW1iZXIobnVtKTtcbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIodmFsKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhdHVzOiAnZXJyb3InLFxuICAgICAgICBpbmZvOiBgJyR7bnVtfScgaXMgbm90IGFuIGludGVnZXIuYCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgc3dpdGNoKGludGVydmFsKSB7XG4gICAgY2FzZSAneXInOlxuICAgIGNhc2UgJ3lycyc6XG4gICAgY2FzZSAneWVhcic6XG4gICAgY2FzZSAneWVhcnMnOlxuICAgICAgc2Vjb25kcyArPSB2YWwgKiAzMTUzNjAwMDsgLy8gMzY1ICogMjQgKiA2MCAqIDYwXG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3drJzpcbiAgICBjYXNlICd3a3MnOlxuICAgIGNhc2UgJ3dlZWsnOlxuICAgIGNhc2UgJ3dlZWtzJzpcbiAgICAgIHNlY29uZHMgKz0gdmFsICogNjA0ODAwOyAvLyA3ICogMjQgKiA2MCAqIDYwXG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2QnOlxuICAgIGNhc2UgJ2RheSc6XG4gICAgY2FzZSAnZGF5cyc6XG4gICAgICBzZWNvbmRzICs9IHZhbCAqIDg2NDAwOyAvLyAyNCAqIDYwICogNjBcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnaHInOlxuICAgIGNhc2UgJ2hycyc6XG4gICAgY2FzZSAnaG91cic6XG4gICAgY2FzZSAnaG91cnMnOlxuICAgICAgc2Vjb25kcyArPSB2YWwgKiAzNjAwOyAvLyA2MCAqIDYwXG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ21pbic6XG4gICAgY2FzZSAnbWlucyc6XG4gICAgY2FzZSAnbWludXRlJzpcbiAgICBjYXNlICdtaW51dGVzJzpcbiAgICAgIHNlY29uZHMgKz0gdmFsICogNjA7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3NlYyc6XG4gICAgY2FzZSAnc2Vjcyc6XG4gICAgY2FzZSAnc2Vjb25kJzpcbiAgICBjYXNlICdzZWNvbmRzJzpcbiAgICAgIHNlY29uZHMgKz0gdmFsO1xuICAgICAgYnJlYWs7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhdHVzOiAnZXJyb3InLFxuICAgICAgICBpbmZvOiBgSW52YWxpZCBpbnRlcnZhbDogJyR7aW50ZXJ2YWx9J2AsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG1pbGxpc2Vjb25kcyA9IHNlY29uZHMgKiAxMDAwO1xuICBpZiAoZnV0dXJlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnLFxuICAgICAgaW5mbzogJ2Z1dHVyZScsXG4gICAgICByZXN1bHQ6IG5ldyBEYXRlKG5vdy52YWx1ZU9mKCkgKyBtaWxsaXNlY29uZHMpXG4gICAgfTtcbiAgfSBlbHNlIGlmIChwYXN0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnLFxuICAgICAgaW5mbzogJ3Bhc3QnLFxuICAgICAgcmVzdWx0OiBuZXcgRGF0ZShub3cudmFsdWVPZigpIC0gbWlsbGlzZWNvbmRzKVxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnLFxuICAgICAgaW5mbzogJ3ByZXNlbnQnLFxuICAgICAgcmVzdWx0OiBuZXcgRGF0ZShub3cudmFsdWVPZigpKVxuICAgIH1cbiAgfVxufVxuXG4vLyBUcmFuc2Zvcm1zIGEgcXVlcnkgY29uc3RyYWludCBmcm9tIFJFU1QgQVBJIGZvcm1hdCB0byBNb25nbyBmb3JtYXQuXG4vLyBBIGNvbnN0cmFpbnQgaXMgc29tZXRoaW5nIHdpdGggZmllbGRzIGxpa2UgJGx0LlxuLy8gSWYgaXQgaXMgbm90IGEgdmFsaWQgY29uc3RyYWludCBidXQgaXQgY291bGQgYmUgYSB2YWxpZCBzb21ldGhpbmdcbi8vIGVsc2UsIHJldHVybiBDYW5ub3RUcmFuc2Zvcm0uXG4vLyBpbkFycmF5IGlzIHdoZXRoZXIgdGhpcyBpcyBhbiBhcnJheSBmaWVsZC5cbmZ1bmN0aW9uIHRyYW5zZm9ybUNvbnN0cmFpbnQoY29uc3RyYWludCwgZmllbGQpIHtcbiAgY29uc3QgaW5BcnJheSA9IGZpZWxkICYmIGZpZWxkLnR5cGUgJiYgZmllbGQudHlwZSA9PT0gJ0FycmF5JztcbiAgaWYgKHR5cGVvZiBjb25zdHJhaW50ICE9PSAnb2JqZWN0JyB8fCAhY29uc3RyYWludCkge1xuICAgIHJldHVybiBDYW5ub3RUcmFuc2Zvcm07XG4gIH1cbiAgY29uc3QgdHJhbnNmb3JtRnVuY3Rpb24gPSBpbkFycmF5ID8gdHJhbnNmb3JtSW50ZXJpb3JBdG9tIDogdHJhbnNmb3JtVG9wTGV2ZWxBdG9tO1xuICBjb25zdCB0cmFuc2Zvcm1lciA9IChhdG9tKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtRnVuY3Rpb24oYXRvbSwgZmllbGQpO1xuICAgIGlmIChyZXN1bHQgPT09IENhbm5vdFRyYW5zZm9ybSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgYGJhZCBhdG9tOiAke0pTT04uc3RyaW5naWZ5KGF0b20pfWApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIC8vIGtleXMgaXMgdGhlIGNvbnN0cmFpbnRzIGluIHJldmVyc2UgYWxwaGFiZXRpY2FsIG9yZGVyLlxuICAvLyBUaGlzIGlzIGEgaGFjayBzbyB0aGF0OlxuICAvLyAgICRyZWdleCBpcyBoYW5kbGVkIGJlZm9yZSAkb3B0aW9uc1xuICAvLyAgICRuZWFyU3BoZXJlIGlzIGhhbmRsZWQgYmVmb3JlICRtYXhEaXN0YW5jZVxuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNvbnN0cmFpbnQpLnNvcnQoKS5yZXZlcnNlKCk7XG4gIHZhciBhbnN3ZXIgPSB7fTtcbiAgZm9yICh2YXIga2V5IG9mIGtleXMpIHtcbiAgICBzd2l0Y2goa2V5KSB7XG4gICAgY2FzZSAnJGx0JzpcbiAgICBjYXNlICckbHRlJzpcbiAgICBjYXNlICckZ3QnOlxuICAgIGNhc2UgJyRndGUnOlxuICAgIGNhc2UgJyRleGlzdHMnOlxuICAgIGNhc2UgJyRuZSc6XG4gICAgY2FzZSAnJGVxJzoge1xuICAgICAgY29uc3QgdmFsID0gY29uc3RyYWludFtrZXldO1xuICAgICAgaWYgKHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwuJHJlbGF0aXZlVGltZSkge1xuICAgICAgICBpZiAoZmllbGQgJiYgZmllbGQudHlwZSAhPT0gJ0RhdGUnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJyRyZWxhdGl2ZVRpbWUgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIERhdGUgZmllbGQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgJyRleGlzdHMnOlxuICAgICAgICBjYXNlICckbmUnOlxuICAgICAgICBjYXNlICckZXEnOlxuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICckcmVsYXRpdmVUaW1lIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCB0aGUgJGx0LCAkbHRlLCAkZ3QsIGFuZCAkZ3RlIG9wZXJhdG9ycycpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFyc2VyUmVzdWx0ID0gcmVsYXRpdmVUaW1lVG9EYXRlKHZhbC4kcmVsYXRpdmVUaW1lKTtcbiAgICAgICAgaWYgKHBhcnNlclJlc3VsdC5zdGF0dXMgPT09ICdzdWNjZXNzJykge1xuICAgICAgICAgIGFuc3dlcltrZXldID0gcGFyc2VyUmVzdWx0LnJlc3VsdDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGxvZy5pbmZvKCdFcnJvciB3aGlsZSBwYXJzaW5nIHJlbGF0aXZlIGRhdGUnLCBwYXJzZXJSZXN1bHQpO1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgYmFkICRyZWxhdGl2ZVRpbWUgKCR7a2V5fSkgdmFsdWUuICR7cGFyc2VyUmVzdWx0LmluZm99YCk7XG4gICAgICB9XG5cbiAgICAgIGFuc3dlcltrZXldID0gdHJhbnNmb3JtZXIodmFsKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGNhc2UgJyRpbic6XG4gICAgY2FzZSAnJG5pbic6IHtcbiAgICAgIGNvbnN0IGFyciA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICAgIGlmICghKGFyciBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICcgKyBrZXkgKyAnIHZhbHVlJyk7XG4gICAgICB9XG4gICAgICBhbnN3ZXJba2V5XSA9IF8uZmxhdE1hcChhcnIsIHZhbHVlID0+IHtcbiAgICAgICAgcmV0dXJuICgoYXRvbSkgPT4ge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGF0b20pKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUubWFwKHRyYW5zZm9ybWVyKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybWVyKGF0b20pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkodmFsdWUpO1xuICAgICAgfSk7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY2FzZSAnJGFsbCc6IHtcbiAgICAgIGNvbnN0IGFyciA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICAgIGlmICghKGFyciBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICdiYWQgJyArIGtleSArICcgdmFsdWUnKTtcbiAgICAgIH1cbiAgICAgIGFuc3dlcltrZXldID0gYXJyLm1hcCh0cmFuc2Zvcm1JbnRlcmlvckF0b20pO1xuXG4gICAgICBjb25zdCB2YWx1ZXMgPSBhbnN3ZXJba2V5XTtcbiAgICAgIGlmIChpc0FueVZhbHVlUmVnZXgodmFsdWVzKSAmJiAhaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSh2YWx1ZXMpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdBbGwgJGFsbCB2YWx1ZXMgbXVzdCBiZSBvZiByZWdleCB0eXBlIG9yIG5vbmU6ICdcbiAgICAgICAgICArIHZhbHVlcyk7XG4gICAgICB9XG5cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjYXNlICckcmVnZXgnOlxuICAgICAgdmFyIHMgPSBjb25zdHJhaW50W2tleV07XG4gICAgICBpZiAodHlwZW9mIHMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdiYWQgcmVnZXg6ICcgKyBzKTtcbiAgICAgIH1cbiAgICAgIGFuc3dlcltrZXldID0gcztcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnJGNvbnRhaW5lZEJ5Jzoge1xuICAgICAgY29uc3QgYXJyID0gY29uc3RyYWludFtrZXldO1xuICAgICAgaWYgKCEoYXJyIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkY29udGFpbmVkQnk6IHNob3VsZCBiZSBhbiBhcnJheWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGFuc3dlci4kZWxlbU1hdGNoID0ge1xuICAgICAgICAkbmluOiBhcnIubWFwKHRyYW5zZm9ybWVyKVxuICAgICAgfTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjYXNlICckb3B0aW9ucyc6XG4gICAgICBhbnN3ZXJba2V5XSA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnJHRleHQnOiB7XG4gICAgICBjb25zdCBzZWFyY2ggPSBjb25zdHJhaW50W2tleV0uJHNlYXJjaDtcbiAgICAgIGlmICh0eXBlb2Ygc2VhcmNoICE9PSAnb2JqZWN0Jykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRzZWFyY2gsIHNob3VsZCBiZSBvYmplY3RgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIXNlYXJjaC4kdGVybSB8fCB0eXBlb2Ygc2VhcmNoLiR0ZXJtICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICR0ZXJtLCBzaG91bGQgYmUgc3RyaW5nYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICAgJyRzZWFyY2gnOiBzZWFyY2guJHRlcm1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHNlYXJjaC4kbGFuZ3VhZ2UgJiYgdHlwZW9mIHNlYXJjaC4kbGFuZ3VhZ2UgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGxhbmd1YWdlLCBzaG91bGQgYmUgc3RyaW5nYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGxhbmd1YWdlKSB7XG4gICAgICAgIGFuc3dlcltrZXldLiRsYW5ndWFnZSA9IHNlYXJjaC4kbGFuZ3VhZ2U7XG4gICAgICB9XG4gICAgICBpZiAoc2VhcmNoLiRjYXNlU2Vuc2l0aXZlICYmIHR5cGVvZiBzZWFyY2guJGNhc2VTZW5zaXRpdmUgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRjYXNlU2Vuc2l0aXZlLCBzaG91bGQgYmUgYm9vbGVhbmBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VhcmNoLiRjYXNlU2Vuc2l0aXZlKSB7XG4gICAgICAgIGFuc3dlcltrZXldLiRjYXNlU2Vuc2l0aXZlID0gc2VhcmNoLiRjYXNlU2Vuc2l0aXZlO1xuICAgICAgfVxuICAgICAgaWYgKHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlICYmIHR5cGVvZiBzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGRpYWNyaXRpY1NlbnNpdGl2ZSwgc2hvdWxkIGJlIGJvb2xlYW5gXG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlKSB7XG4gICAgICAgIGFuc3dlcltrZXldLiRkaWFjcml0aWNTZW5zaXRpdmUgPSBzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjYXNlICckbmVhclNwaGVyZSc6XG4gICAgICB2YXIgcG9pbnQgPSBjb25zdHJhaW50W2tleV07XG4gICAgICBhbnN3ZXJba2V5XSA9IFtwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlXTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnJG1heERpc3RhbmNlJzpcbiAgICAgIGFuc3dlcltrZXldID0gY29uc3RyYWludFtrZXldO1xuICAgICAgYnJlYWs7XG5cbiAgICAvLyBUaGUgU0RLcyBkb24ndCBzZWVtIHRvIHVzZSB0aGVzZSBidXQgdGhleSBhcmUgZG9jdW1lbnRlZCBpbiB0aGVcbiAgICAvLyBSRVNUIEFQSSBkb2NzLlxuICAgIGNhc2UgJyRtYXhEaXN0YW5jZUluUmFkaWFucyc6XG4gICAgICBhbnN3ZXJbJyRtYXhEaXN0YW5jZSddID0gY29uc3RyYWludFtrZXldO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnJG1heERpc3RhbmNlSW5NaWxlcyc6XG4gICAgICBhbnN3ZXJbJyRtYXhEaXN0YW5jZSddID0gY29uc3RyYWludFtrZXldIC8gMzk1OTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJyRtYXhEaXN0YW5jZUluS2lsb21ldGVycyc6XG4gICAgICBhbnN3ZXJbJyRtYXhEaXN0YW5jZSddID0gY29uc3RyYWludFtrZXldIC8gNjM3MTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnJHNlbGVjdCc6XG4gICAgY2FzZSAnJGRvbnRTZWxlY3QnOlxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5DT01NQU5EX1VOQVZBSUxBQkxFLFxuICAgICAgICAndGhlICcgKyBrZXkgKyAnIGNvbnN0cmFpbnQgaXMgbm90IHN1cHBvcnRlZCB5ZXQnKTtcblxuICAgIGNhc2UgJyR3aXRoaW4nOlxuICAgICAgdmFyIGJveCA9IGNvbnN0cmFpbnRba2V5XVsnJGJveCddO1xuICAgICAgaWYgKCFib3ggfHwgYm94Lmxlbmd0aCAhPSAyKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ21hbGZvcm1hdHRlZCAkd2l0aGluIGFyZycpO1xuICAgICAgfVxuICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICckYm94JzogW1xuICAgICAgICAgIFtib3hbMF0ubG9uZ2l0dWRlLCBib3hbMF0ubGF0aXR1ZGVdLFxuICAgICAgICAgIFtib3hbMV0ubG9uZ2l0dWRlLCBib3hbMV0ubGF0aXR1ZGVdXG4gICAgICAgIF1cbiAgICAgIH07XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJyRnZW9XaXRoaW4nOiB7XG4gICAgICBjb25zdCBwb2x5Z29uID0gY29uc3RyYWludFtrZXldWyckcG9seWdvbiddO1xuICAgICAgY29uc3QgY2VudGVyU3BoZXJlID0gY29uc3RyYWludFtrZXldWyckY2VudGVyU3BoZXJlJ107XG4gICAgICBpZiAocG9seWdvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxldCBwb2ludHM7XG4gICAgICAgIGlmICh0eXBlb2YgcG9seWdvbiA9PT0gJ29iamVjdCcgJiYgcG9seWdvbi5fX3R5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgICAgIGlmICghcG9seWdvbi5jb29yZGluYXRlcyB8fCBwb2x5Z29uLmNvb3JkaW5hdGVzLmxlbmd0aCA8IDMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7IFBvbHlnb24uY29vcmRpbmF0ZXMgc2hvdWxkIGNvbnRhaW4gYXQgbGVhc3QgMyBsb24vbGF0IHBhaXJzJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcG9pbnRzID0gcG9seWdvbi5jb29yZGluYXRlcztcbiAgICAgICAgfSBlbHNlIGlmIChwb2x5Z29uIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICBpZiAocG9seWdvbi5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkcG9seWdvbiBzaG91bGQgY29udGFpbiBhdCBsZWFzdCAzIEdlb1BvaW50cydcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHBvaW50cyA9IHBvbHlnb247XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkcG9seWdvbiBzaG91bGQgYmUgUG9seWdvbiBvYmplY3Qgb3IgQXJyYXkgb2YgUGFyc2UuR2VvUG9pbnRcXCdzJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcG9pbnRzID0gcG9pbnRzLm1hcCgocG9pbnQpID0+IHtcbiAgICAgICAgICBpZiAocG9pbnQgaW5zdGFuY2VvZiBBcnJheSAmJiBwb2ludC5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwb2ludFsxXSwgcG9pbnRbMF0pO1xuICAgICAgICAgICAgcmV0dXJuIHBvaW50O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIUdlb1BvaW50Q29kZXIuaXNWYWxpZEpTT04ocG9pbnQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICRnZW9XaXRoaW4gdmFsdWUnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50LmxhdGl0dWRlLCBwb2ludC5sb25naXR1ZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gW3BvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGVdO1xuICAgICAgICB9KTtcbiAgICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICAgJyRwb2x5Z29uJzogcG9pbnRzXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKGNlbnRlclNwaGVyZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmICghKGNlbnRlclNwaGVyZSBpbnN0YW5jZW9mIEFycmF5KSB8fCBjZW50ZXJTcGhlcmUubGVuZ3RoIDwgMikge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJGNlbnRlclNwaGVyZSBzaG91bGQgYmUgYW4gYXJyYXkgb2YgUGFyc2UuR2VvUG9pbnQgYW5kIGRpc3RhbmNlJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gR2V0IHBvaW50LCBjb252ZXJ0IHRvIGdlbyBwb2ludCBpZiBuZWNlc3NhcnkgYW5kIHZhbGlkYXRlXG4gICAgICAgIGxldCBwb2ludCA9IGNlbnRlclNwaGVyZVswXTtcbiAgICAgICAgaWYgKHBvaW50IGluc3RhbmNlb2YgQXJyYXkgJiYgcG9pbnQubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgcG9pbnQgPSBuZXcgUGFyc2UuR2VvUG9pbnQocG9pbnRbMV0sIHBvaW50WzBdKTtcbiAgICAgICAgfSBlbHNlIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihwb2ludCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRjZW50ZXJTcGhlcmUgZ2VvIHBvaW50IGludmFsaWQnKTtcbiAgICAgICAgfVxuICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAgIC8vIEdldCBkaXN0YW5jZSBhbmQgdmFsaWRhdGVcbiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBjZW50ZXJTcGhlcmVbMV07XG4gICAgICAgIGlmKGlzTmFOKGRpc3RhbmNlKSB8fCBkaXN0YW5jZSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRjZW50ZXJTcGhlcmUgZGlzdGFuY2UgaW52YWxpZCcpO1xuICAgICAgICB9XG4gICAgICAgIGFuc3dlcltrZXldID0ge1xuICAgICAgICAgICckY2VudGVyU3BoZXJlJzogW1xuICAgICAgICAgICAgW3BvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGVdLFxuICAgICAgICAgICAgZGlzdGFuY2VcbiAgICAgICAgICBdXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY2FzZSAnJGdlb0ludGVyc2VjdHMnOiB7XG4gICAgICBjb25zdCBwb2ludCA9IGNvbnN0cmFpbnRba2V5XVsnJHBvaW50J107XG4gICAgICBpZiAoIUdlb1BvaW50Q29kZXIuaXNWYWxpZEpTT04ocG9pbnQpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ2JhZCAkZ2VvSW50ZXJzZWN0IHZhbHVlOyAkcG9pbnQgc2hvdWxkIGJlIEdlb1BvaW50J1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50LmxhdGl0dWRlLCBwb2ludC5sb25naXR1ZGUpO1xuICAgICAgfVxuICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICRnZW9tZXRyeToge1xuICAgICAgICAgIHR5cGU6ICdQb2ludCcsXG4gICAgICAgICAgY29vcmRpbmF0ZXM6IFtwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlXVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICBpZiAoa2V5Lm1hdGNoKC9eXFwkKy8pKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ2JhZCBjb25zdHJhaW50OiAnICsga2V5KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBDYW5ub3RUcmFuc2Zvcm07XG4gICAgfVxuICB9XG4gIHJldHVybiBhbnN3ZXI7XG59XG5cbi8vIFRyYW5zZm9ybXMgYW4gdXBkYXRlIG9wZXJhdG9yIGZyb20gUkVTVCBmb3JtYXQgdG8gbW9uZ28gZm9ybWF0LlxuLy8gVG8gYmUgdHJhbnNmb3JtZWQsIHRoZSBpbnB1dCBzaG91bGQgaGF2ZSBhbiBfX29wIGZpZWxkLlxuLy8gSWYgZmxhdHRlbiBpcyB0cnVlLCB0aGlzIHdpbGwgZmxhdHRlbiBvcGVyYXRvcnMgdG8gdGhlaXIgc3RhdGljXG4vLyBkYXRhIGZvcm1hdC4gRm9yIGV4YW1wbGUsIGFuIGluY3JlbWVudCBvZiAyIHdvdWxkIHNpbXBseSBiZWNvbWUgYVxuLy8gMi5cbi8vIFRoZSBvdXRwdXQgZm9yIGEgbm9uLWZsYXR0ZW5lZCBvcGVyYXRvciBpcyBhIGhhc2ggd2l0aCBfX29wIGJlaW5nXG4vLyB0aGUgbW9uZ28gb3AsIGFuZCBhcmcgYmVpbmcgdGhlIGFyZ3VtZW50LlxuLy8gVGhlIG91dHB1dCBmb3IgYSBmbGF0dGVuZWQgb3BlcmF0b3IgaXMganVzdCBhIHZhbHVlLlxuLy8gUmV0dXJucyB1bmRlZmluZWQgaWYgdGhpcyBzaG91bGQgYmUgYSBuby1vcC5cblxuZnVuY3Rpb24gdHJhbnNmb3JtVXBkYXRlT3BlcmF0b3Ioe1xuICBfX29wLFxuICBhbW91bnQsXG4gIG9iamVjdHMsXG59LCBmbGF0dGVuKSB7XG4gIHN3aXRjaChfX29wKSB7XG4gIGNhc2UgJ0RlbGV0ZSc6XG4gICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB7X19vcDogJyR1bnNldCcsIGFyZzogJyd9O1xuICAgIH1cblxuICBjYXNlICdJbmNyZW1lbnQnOlxuICAgIGlmICh0eXBlb2YgYW1vdW50ICE9PSAnbnVtYmVyJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2luY3JlbWVudGluZyBtdXN0IHByb3ZpZGUgYSBudW1iZXInKTtcbiAgICB9XG4gICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgIHJldHVybiBhbW91bnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB7X19vcDogJyRpbmMnLCBhcmc6IGFtb3VudH07XG4gICAgfVxuXG4gIGNhc2UgJ0FkZCc6XG4gIGNhc2UgJ0FkZFVuaXF1ZSc6XG4gICAgaWYgKCEob2JqZWN0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ29iamVjdHMgdG8gYWRkIG11c3QgYmUgYW4gYXJyYXknKTtcbiAgICB9XG4gICAgdmFyIHRvQWRkID0gb2JqZWN0cy5tYXAodHJhbnNmb3JtSW50ZXJpb3JBdG9tKTtcbiAgICBpZiAoZmxhdHRlbikge1xuICAgICAgcmV0dXJuIHRvQWRkO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgbW9uZ29PcCA9IHtcbiAgICAgICAgQWRkOiAnJHB1c2gnLFxuICAgICAgICBBZGRVbmlxdWU6ICckYWRkVG9TZXQnXG4gICAgICB9W19fb3BdO1xuICAgICAgcmV0dXJuIHtfX29wOiBtb25nb09wLCBhcmc6IHsnJGVhY2gnOiB0b0FkZH19O1xuICAgIH1cblxuICBjYXNlICdSZW1vdmUnOlxuICAgIGlmICghKG9iamVjdHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdvYmplY3RzIHRvIHJlbW92ZSBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgfVxuICAgIHZhciB0b1JlbW92ZSA9IG9iamVjdHMubWFwKHRyYW5zZm9ybUludGVyaW9yQXRvbSk7XG4gICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtfX29wOiAnJHB1bGxBbGwnLCBhcmc6IHRvUmVtb3ZlfTtcbiAgICB9XG5cbiAgZGVmYXVsdDpcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuQ09NTUFORF9VTkFWQUlMQUJMRSwgYFRoZSAke19fb3B9IG9wZXJhdG9yIGlzIG5vdCBzdXBwb3J0ZWQgeWV0LmApO1xuICB9XG59XG5mdW5jdGlvbiBtYXBWYWx1ZXMob2JqZWN0LCBpdGVyYXRvcikge1xuICBjb25zdCByZXN1bHQgPSB7fTtcbiAgT2JqZWN0LmtleXMob2JqZWN0KS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICByZXN1bHRba2V5XSA9IGl0ZXJhdG9yKG9iamVjdFtrZXldKTtcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmNvbnN0IG5lc3RlZE1vbmdvT2JqZWN0VG9OZXN0ZWRQYXJzZU9iamVjdCA9IG1vbmdvT2JqZWN0ID0+IHtcbiAgc3dpdGNoKHR5cGVvZiBtb25nb09iamVjdCkge1xuICBjYXNlICdzdHJpbmcnOlxuICBjYXNlICdudW1iZXInOlxuICBjYXNlICdib29sZWFuJzpcbiAgICByZXR1cm4gbW9uZ29PYmplY3Q7XG4gIGNhc2UgJ3VuZGVmaW5lZCc6XG4gIGNhc2UgJ3N5bWJvbCc6XG4gIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICB0aHJvdyAnYmFkIHZhbHVlIGluIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdCc7XG4gIGNhc2UgJ29iamVjdCc6XG4gICAgaWYgKG1vbmdvT2JqZWN0ID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgIHJldHVybiBtb25nb09iamVjdC5tYXAobmVzdGVkTW9uZ29PYmplY3RUb05lc3RlZFBhcnNlT2JqZWN0KTtcbiAgICB9XG5cbiAgICBpZiAobW9uZ29PYmplY3QgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICByZXR1cm4gUGFyc2UuX2VuY29kZShtb25nb09iamVjdCk7XG4gICAgfVxuXG4gICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgbW9uZ29kYi5Mb25nKSB7XG4gICAgICByZXR1cm4gbW9uZ29PYmplY3QudG9OdW1iZXIoKTtcbiAgICB9XG5cbiAgICBpZiAobW9uZ29PYmplY3QgaW5zdGFuY2VvZiBtb25nb2RiLkRvdWJsZSkge1xuICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0LnZhbHVlO1xuICAgIH1cblxuICAgIGlmIChCeXRlc0NvZGVyLmlzVmFsaWREYXRhYmFzZU9iamVjdChtb25nb09iamVjdCkpIHtcbiAgICAgIHJldHVybiBCeXRlc0NvZGVyLmRhdGFiYXNlVG9KU09OKG1vbmdvT2JqZWN0KTtcbiAgICB9XG5cbiAgICBpZiAobW9uZ29PYmplY3QuaGFzT3duUHJvcGVydHkoJ19fdHlwZScpICYmIG1vbmdvT2JqZWN0Ll9fdHlwZSA9PSAnRGF0ZScgJiYgbW9uZ29PYmplY3QuaXNvIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgbW9uZ29PYmplY3QuaXNvID0gbW9uZ29PYmplY3QuaXNvLnRvSlNPTigpO1xuICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0O1xuICAgIH1cblxuICAgIHJldHVybiBtYXBWYWx1ZXMobW9uZ29PYmplY3QsIG5lc3RlZE1vbmdvT2JqZWN0VG9OZXN0ZWRQYXJzZU9iamVjdCk7XG4gIGRlZmF1bHQ6XG4gICAgdGhyb3cgJ3Vua25vd24ganMgdHlwZSc7XG4gIH1cbn1cblxuY29uc3QgdHJhbnNmb3JtUG9pbnRlclN0cmluZyA9IChzY2hlbWEsIGZpZWxkLCBwb2ludGVyU3RyaW5nKSA9PiB7XG4gIGNvbnN0IG9iakRhdGEgPSBwb2ludGVyU3RyaW5nLnNwbGl0KCckJyk7XG4gIGlmIChvYmpEYXRhWzBdICE9PSBzY2hlbWEuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzcykge1xuICAgIHRocm93ICdwb2ludGVyIHRvIGluY29ycmVjdCBjbGFzc05hbWUnO1xuICB9XG4gIHJldHVybiB7XG4gICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgY2xhc3NOYW1lOiBvYmpEYXRhWzBdLFxuICAgIG9iamVjdElkOiBvYmpEYXRhWzFdXG4gIH07XG59XG5cbi8vIENvbnZlcnRzIGZyb20gYSBtb25nby1mb3JtYXQgb2JqZWN0IHRvIGEgUkVTVC1mb3JtYXQgb2JqZWN0LlxuLy8gRG9lcyBub3Qgc3RyaXAgb3V0IGFueXRoaW5nIGJhc2VkIG9uIGEgbGFjayBvZiBhdXRoZW50aWNhdGlvbi5cbmNvbnN0IG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdCA9IChjbGFzc05hbWUsIG1vbmdvT2JqZWN0LCBzY2hlbWEpID0+IHtcbiAgc3dpdGNoKHR5cGVvZiBtb25nb09iamVjdCkge1xuICBjYXNlICdzdHJpbmcnOlxuICBjYXNlICdudW1iZXInOlxuICBjYXNlICdib29sZWFuJzpcbiAgICByZXR1cm4gbW9uZ29PYmplY3Q7XG4gIGNhc2UgJ3VuZGVmaW5lZCc6XG4gIGNhc2UgJ3N5bWJvbCc6XG4gIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICB0aHJvdyAnYmFkIHZhbHVlIGluIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdCc7XG4gIGNhc2UgJ29iamVjdCc6IHtcbiAgICBpZiAobW9uZ29PYmplY3QgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAobW9uZ29PYmplY3QgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0Lm1hcChuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QpO1xuICAgIH1cblxuICAgIGlmIChtb25nb09iamVjdCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgIHJldHVybiBQYXJzZS5fZW5jb2RlKG1vbmdvT2JqZWN0KTtcbiAgICB9XG5cbiAgICBpZiAobW9uZ29PYmplY3QgaW5zdGFuY2VvZiBtb25nb2RiLkxvbmcpIHtcbiAgICAgIHJldHVybiBtb25nb09iamVjdC50b051bWJlcigpO1xuICAgIH1cblxuICAgIGlmIChtb25nb09iamVjdCBpbnN0YW5jZW9mIG1vbmdvZGIuRG91YmxlKSB7XG4gICAgICByZXR1cm4gbW9uZ29PYmplY3QudmFsdWU7XG4gICAgfVxuXG4gICAgaWYgKEJ5dGVzQ29kZXIuaXNWYWxpZERhdGFiYXNlT2JqZWN0KG1vbmdvT2JqZWN0KSkge1xuICAgICAgcmV0dXJuIEJ5dGVzQ29kZXIuZGF0YWJhc2VUb0pTT04obW9uZ29PYmplY3QpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3RPYmplY3QgPSB7fTtcbiAgICBpZiAobW9uZ29PYmplY3QuX3JwZXJtIHx8IG1vbmdvT2JqZWN0Ll93cGVybSkge1xuICAgICAgcmVzdE9iamVjdC5fcnBlcm0gPSBtb25nb09iamVjdC5fcnBlcm0gfHwgW107XG4gICAgICByZXN0T2JqZWN0Ll93cGVybSA9IG1vbmdvT2JqZWN0Ll93cGVybSB8fCBbXTtcbiAgICAgIGRlbGV0ZSBtb25nb09iamVjdC5fcnBlcm07XG4gICAgICBkZWxldGUgbW9uZ29PYmplY3QuX3dwZXJtO1xuICAgIH1cblxuICAgIGZvciAodmFyIGtleSBpbiBtb25nb09iamVjdCkge1xuICAgICAgc3dpdGNoKGtleSkge1xuICAgICAgY2FzZSAnX2lkJzpcbiAgICAgICAgcmVzdE9iamVjdFsnb2JqZWN0SWQnXSA9ICcnICsgbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdfaGFzaGVkX3Bhc3N3b3JkJzpcbiAgICAgICAgcmVzdE9iamVjdC5faGFzaGVkX3Bhc3N3b3JkID0gbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdfYWNsJzpcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuJzpcbiAgICAgIGNhc2UgJ19wZXJpc2hhYmxlX3Rva2VuJzpcbiAgICAgIGNhc2UgJ19wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgY2FzZSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnOlxuICAgICAgY2FzZSAnX3RvbWJzdG9uZSc6XG4gICAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgY2FzZSAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JzpcbiAgICAgIGNhc2UgJ19mYWlsZWRfbG9naW5fY291bnQnOlxuICAgICAgY2FzZSAnX3Bhc3N3b3JkX2hpc3RvcnknOlxuICAgICAgICAvLyBUaG9zZSBrZXlzIHdpbGwgYmUgZGVsZXRlZCBpZiBuZWVkZWQgaW4gdGhlIERCIENvbnRyb2xsZXJcbiAgICAgICAgcmVzdE9iamVjdFtrZXldID0gbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdfc2Vzc2lvbl90b2tlbic6XG4gICAgICAgIHJlc3RPYmplY3RbJ3Nlc3Npb25Ub2tlbiddID0gbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd1cGRhdGVkQXQnOlxuICAgICAgY2FzZSAnX3VwZGF0ZWRfYXQnOlxuICAgICAgICByZXN0T2JqZWN0Wyd1cGRhdGVkQXQnXSA9IFBhcnNlLl9lbmNvZGUobmV3IERhdGUobW9uZ29PYmplY3Rba2V5XSkpLmlzbztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdjcmVhdGVkQXQnOlxuICAgICAgY2FzZSAnX2NyZWF0ZWRfYXQnOlxuICAgICAgICByZXN0T2JqZWN0WydjcmVhdGVkQXQnXSA9IFBhcnNlLl9lbmNvZGUobmV3IERhdGUobW9uZ29PYmplY3Rba2V5XSkpLmlzbztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdleHBpcmVzQXQnOlxuICAgICAgY2FzZSAnX2V4cGlyZXNBdCc6XG4gICAgICAgIHJlc3RPYmplY3RbJ2V4cGlyZXNBdCddID0gUGFyc2UuX2VuY29kZShuZXcgRGF0ZShtb25nb09iamVjdFtrZXldKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbGFzdFVzZWQnOlxuICAgICAgY2FzZSAnX2xhc3RfdXNlZCc6XG4gICAgICAgIHJlc3RPYmplY3RbJ2xhc3RVc2VkJ10gPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKG1vbmdvT2JqZWN0W2tleV0pKS5pc287XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndGltZXNVc2VkJzpcbiAgICAgIGNhc2UgJ3RpbWVzX3VzZWQnOlxuICAgICAgICByZXN0T2JqZWN0Wyd0aW1lc1VzZWQnXSA9IG1vbmdvT2JqZWN0W2tleV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gQ2hlY2sgb3RoZXIgYXV0aCBkYXRhIGtleXNcbiAgICAgICAgdmFyIGF1dGhEYXRhTWF0Y2ggPSBrZXkubWF0Y2goL15fYXV0aF9kYXRhXyhbYS16QS1aMC05X10rKSQvKTtcbiAgICAgICAgaWYgKGF1dGhEYXRhTWF0Y2gpIHtcbiAgICAgICAgICB2YXIgcHJvdmlkZXIgPSBhdXRoRGF0YU1hdGNoWzFdO1xuICAgICAgICAgIHJlc3RPYmplY3RbJ2F1dGhEYXRhJ10gPSByZXN0T2JqZWN0WydhdXRoRGF0YSddIHx8IHt9O1xuICAgICAgICAgIHJlc3RPYmplY3RbJ2F1dGhEYXRhJ11bcHJvdmlkZXJdID0gbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChrZXkuaW5kZXhPZignX3BfJykgPT0gMCkge1xuICAgICAgICAgIHZhciBuZXdLZXkgPSBrZXkuc3Vic3RyaW5nKDMpO1xuICAgICAgICAgIGlmICghc2NoZW1hLmZpZWxkc1tuZXdLZXldKSB7XG4gICAgICAgICAgICBsb2cuaW5mbygndHJhbnNmb3JtLmpzJywgJ0ZvdW5kIGEgcG9pbnRlciBjb2x1bW4gbm90IGluIHRoZSBzY2hlbWEsIGRyb3BwaW5nIGl0LicsIGNsYXNzTmFtZSwgbmV3S2V5KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tuZXdLZXldLnR5cGUgIT09ICdQb2ludGVyJykge1xuICAgICAgICAgICAgbG9nLmluZm8oJ3RyYW5zZm9ybS5qcycsICdGb3VuZCBhIHBvaW50ZXIgaW4gYSBub24tcG9pbnRlciBjb2x1bW4sIGRyb3BwaW5nIGl0LicsIGNsYXNzTmFtZSwga2V5KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobW9uZ29PYmplY3Rba2V5XSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3RPYmplY3RbbmV3S2V5XSA9IHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcoc2NoZW1hLCBuZXdLZXksIG1vbmdvT2JqZWN0W2tleV0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9IGVsc2UgaWYgKGtleVswXSA9PSAnXycgJiYga2V5ICE9ICdfX3R5cGUnKSB7XG4gICAgICAgICAgdGhyb3cgKCdiYWQga2V5IGluIHVudHJhbnNmb3JtOiAnICsga2V5KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2tleV0gJiYgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdGaWxlJyAmJiBGaWxlQ29kZXIuaXNWYWxpZERhdGFiYXNlT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICAgICAgcmVzdE9iamVjdFtrZXldID0gRmlsZUNvZGVyLmRhdGFiYXNlVG9KU09OKHZhbHVlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1trZXldICYmIHNjaGVtYS5maWVsZHNba2V5XS50eXBlID09PSAnR2VvUG9pbnQnICYmIEdlb1BvaW50Q29kZXIuaXNWYWxpZERhdGFiYXNlT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICAgICAgcmVzdE9iamVjdFtrZXldID0gR2VvUG9pbnRDb2Rlci5kYXRhYmFzZVRvSlNPTih2YWx1ZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHNjaGVtYS5maWVsZHNba2V5XSAmJiBzY2hlbWEuZmllbGRzW2tleV0udHlwZSA9PT0gJ1BvbHlnb24nICYmIFBvbHlnb25Db2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QodmFsdWUpKSB7XG4gICAgICAgICAgICByZXN0T2JqZWN0W2tleV0gPSBQb2x5Z29uQ29kZXIuZGF0YWJhc2VUb0pTT04odmFsdWUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2tleV0gJiYgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdCeXRlcycgJiYgQnl0ZXNDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QodmFsdWUpKSB7XG4gICAgICAgICAgICByZXN0T2JqZWN0W2tleV0gPSBCeXRlc0NvZGVyLmRhdGFiYXNlVG9KU09OKHZhbHVlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXN0T2JqZWN0W2tleV0gPSBuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QobW9uZ29PYmplY3Rba2V5XSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmVsYXRpb25GaWVsZE5hbWVzID0gT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcykuZmlsdGVyKGZpZWxkTmFtZSA9PiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1JlbGF0aW9uJyk7XG4gICAgY29uc3QgcmVsYXRpb25GaWVsZHMgPSB7fTtcbiAgICByZWxhdGlvbkZpZWxkTmFtZXMuZm9yRWFjaChyZWxhdGlvbkZpZWxkTmFtZSA9PiB7XG4gICAgICByZWxhdGlvbkZpZWxkc1tyZWxhdGlvbkZpZWxkTmFtZV0gPSB7XG4gICAgICAgIF9fdHlwZTogJ1JlbGF0aW9uJyxcbiAgICAgICAgY2xhc3NOYW1lOiBzY2hlbWEuZmllbGRzW3JlbGF0aW9uRmllbGROYW1lXS50YXJnZXRDbGFzcyxcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7IC4uLnJlc3RPYmplY3QsIC4uLnJlbGF0aW9uRmllbGRzIH07XG4gIH1cbiAgZGVmYXVsdDpcbiAgICB0aHJvdyAndW5rbm93biBqcyB0eXBlJztcbiAgfVxufVxuXG52YXIgRGF0ZUNvZGVyID0ge1xuICBKU09OVG9EYXRhYmFzZShqc29uKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKGpzb24uaXNvKTtcbiAgfSxcblxuICBpc1ZhbGlkSlNPTih2YWx1ZSkge1xuICAgIHJldHVybiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgdmFsdWUgIT09IG51bGwgJiZcbiAgICAgIHZhbHVlLl9fdHlwZSA9PT0gJ0RhdGUnXG4gICAgKTtcbiAgfVxufTtcblxudmFyIEJ5dGVzQ29kZXIgPSB7XG4gIGJhc2U2NFBhdHRlcm46IG5ldyBSZWdFeHAoXCJeKD86W0EtWmEtejAtOSsvXXs0fSkqKD86W0EtWmEtejAtOSsvXXsyfT09fFtBLVphLXowLTkrL117M309KT8kXCIpLFxuICBpc0Jhc2U2NFZhbHVlKG9iamVjdCkge1xuICAgIGlmICh0eXBlb2Ygb2JqZWN0ICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5iYXNlNjRQYXR0ZXJuLnRlc3Qob2JqZWN0KTtcbiAgfSxcblxuICBkYXRhYmFzZVRvSlNPTihvYmplY3QpIHtcbiAgICBsZXQgdmFsdWU7XG4gICAgaWYgKHRoaXMuaXNCYXNlNjRWYWx1ZShvYmplY3QpKSB7XG4gICAgICB2YWx1ZSA9IG9iamVjdDtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgPSBvYmplY3QuYnVmZmVyLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIF9fdHlwZTogJ0J5dGVzJyxcbiAgICAgIGJhc2U2NDogdmFsdWVcbiAgICB9O1xuICB9LFxuXG4gIGlzVmFsaWREYXRhYmFzZU9iamVjdChvYmplY3QpIHtcbiAgICByZXR1cm4gKG9iamVjdCBpbnN0YW5jZW9mIG1vbmdvZGIuQmluYXJ5KSB8fCB0aGlzLmlzQmFzZTY0VmFsdWUob2JqZWN0KTtcbiAgfSxcblxuICBKU09OVG9EYXRhYmFzZShqc29uKSB7XG4gICAgcmV0dXJuIG5ldyBtb25nb2RiLkJpbmFyeShuZXcgQnVmZmVyKGpzb24uYmFzZTY0LCAnYmFzZTY0JykpO1xuICB9LFxuXG4gIGlzVmFsaWRKU09OKHZhbHVlKSB7XG4gICAgcmV0dXJuICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICB2YWx1ZSAhPT0gbnVsbCAmJlxuICAgICAgdmFsdWUuX190eXBlID09PSAnQnl0ZXMnXG4gICAgKTtcbiAgfVxufTtcblxudmFyIEdlb1BvaW50Q29kZXIgPSB7XG4gIGRhdGFiYXNlVG9KU09OKG9iamVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdHZW9Qb2ludCcsXG4gICAgICBsYXRpdHVkZTogb2JqZWN0WzFdLFxuICAgICAgbG9uZ2l0dWRlOiBvYmplY3RbMF1cbiAgICB9XG4gIH0sXG5cbiAgaXNWYWxpZERhdGFiYXNlT2JqZWN0KG9iamVjdCkge1xuICAgIHJldHVybiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXkgJiZcbiAgICAgIG9iamVjdC5sZW5ndGggPT0gMlxuICAgICk7XG4gIH0sXG5cbiAgSlNPTlRvRGF0YWJhc2UoanNvbikge1xuICAgIHJldHVybiBbIGpzb24ubG9uZ2l0dWRlLCBqc29uLmxhdGl0dWRlIF07XG4gIH0sXG5cbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgICB2YWx1ZS5fX3R5cGUgPT09ICdHZW9Qb2ludCdcbiAgICApO1xuICB9XG59O1xuXG52YXIgUG9seWdvbkNvZGVyID0ge1xuICBkYXRhYmFzZVRvSlNPTihvYmplY3QpIHtcbiAgICAvLyBDb252ZXJ0IGxuZy9sYXQgLT4gbGF0L2xuZ1xuICAgIGNvbnN0IGNvb3JkcyA9IG9iamVjdC5jb29yZGluYXRlc1swXS5tYXAoKGNvb3JkKSA9PiB7XG4gICAgICByZXR1cm4gW2Nvb3JkWzFdLCBjb29yZFswXV07XG4gICAgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIF9fdHlwZTogJ1BvbHlnb24nLFxuICAgICAgY29vcmRpbmF0ZXM6IGNvb3Jkc1xuICAgIH1cbiAgfSxcblxuICBpc1ZhbGlkRGF0YWJhc2VPYmplY3Qob2JqZWN0KSB7XG4gICAgY29uc3QgY29vcmRzID0gb2JqZWN0LmNvb3JkaW5hdGVzWzBdO1xuICAgIGlmIChvYmplY3QudHlwZSAhPT0gJ1BvbHlnb24nIHx8ICEoY29vcmRzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBwb2ludCA9IGNvb3Jkc1tpXTtcbiAgICAgIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QocG9pbnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwYXJzZUZsb2F0KHBvaW50WzFdKSwgcGFyc2VGbG9hdChwb2ludFswXSkpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBKU09OVG9EYXRhYmFzZShqc29uKSB7XG4gICAgbGV0IGNvb3JkcyA9IGpzb24uY29vcmRpbmF0ZXM7XG4gICAgLy8gQWRkIGZpcnN0IHBvaW50IHRvIHRoZSBlbmQgdG8gY2xvc2UgcG9seWdvblxuICAgIGlmIChjb29yZHNbMF1bMF0gIT09IGNvb3Jkc1tjb29yZHMubGVuZ3RoIC0gMV1bMF0gfHxcbiAgICAgICAgY29vcmRzWzBdWzFdICE9PSBjb29yZHNbY29vcmRzLmxlbmd0aCAtIDFdWzFdKSB7XG4gICAgICBjb29yZHMucHVzaChjb29yZHNbMF0pO1xuICAgIH1cbiAgICBjb25zdCB1bmlxdWUgPSBjb29yZHMuZmlsdGVyKChpdGVtLCBpbmRleCwgYXIpID0+IHtcbiAgICAgIGxldCBmb3VuZEluZGV4ID0gLTE7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IHB0ID0gYXJbaV07XG4gICAgICAgIGlmIChwdFswXSA9PT0gaXRlbVswXSAmJlxuICAgICAgICAgICAgcHRbMV0gPT09IGl0ZW1bMV0pIHtcbiAgICAgICAgICBmb3VuZEluZGV4ID0gaTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZvdW5kSW5kZXggPT09IGluZGV4O1xuICAgIH0pO1xuICAgIGlmICh1bmlxdWUubGVuZ3RoIDwgMykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgICdHZW9KU09OOiBMb29wIG11c3QgaGF2ZSBhdCBsZWFzdCAzIGRpZmZlcmVudCB2ZXJ0aWNlcydcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIENvbnZlcnQgbGF0L2xvbmcgLT4gbG9uZy9sYXRcbiAgICBjb29yZHMgPSBjb29yZHMubWFwKChjb29yZCkgPT4ge1xuICAgICAgcmV0dXJuIFtjb29yZFsxXSwgY29vcmRbMF1dO1xuICAgIH0pO1xuICAgIHJldHVybiB7IHR5cGU6ICdQb2x5Z29uJywgY29vcmRpbmF0ZXM6IFtjb29yZHNdIH07XG4gIH0sXG5cbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgICB2YWx1ZS5fX3R5cGUgPT09ICdQb2x5Z29uJ1xuICAgICk7XG4gIH1cbn07XG5cbnZhciBGaWxlQ29kZXIgPSB7XG4gIGRhdGFiYXNlVG9KU09OKG9iamVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdGaWxlJyxcbiAgICAgIG5hbWU6IG9iamVjdFxuICAgIH1cbiAgfSxcblxuICBpc1ZhbGlkRGF0YWJhc2VPYmplY3Qob2JqZWN0KSB7XG4gICAgcmV0dXJuICh0eXBlb2Ygb2JqZWN0ID09PSAnc3RyaW5nJyk7XG4gIH0sXG5cbiAgSlNPTlRvRGF0YWJhc2UoanNvbikge1xuICAgIHJldHVybiBqc29uLm5hbWU7XG4gIH0sXG5cbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgICB2YWx1ZS5fX3R5cGUgPT09ICdGaWxlJ1xuICAgICk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB0cmFuc2Zvcm1LZXksXG4gIHBhcnNlT2JqZWN0VG9Nb25nb09iamVjdEZvckNyZWF0ZSxcbiAgdHJhbnNmb3JtVXBkYXRlLFxuICB0cmFuc2Zvcm1XaGVyZSxcbiAgbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0LFxuICByZWxhdGl2ZVRpbWVUb0RhdGUsXG4gIHRyYW5zZm9ybUNvbnN0cmFpbnQsXG4gIHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/PostgresClient.js b/lib/Adapters/Storage/Postgres/PostgresClient.js index 85429dfa81..debb0584fc 100644 --- a/lib/Adapters/Storage/Postgres/PostgresClient.js +++ b/lib/Adapters/Storage/Postgres/PostgresClient.js @@ -30,4 +30,5 @@ function createClient(uri, databaseOptions) { } return { client, pgp }; -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzQ2xpZW50LmpzIl0sIm5hbWVzIjpbImNyZWF0ZUNsaWVudCIsInBhcnNlciIsInJlcXVpcmUiLCJ1cmkiLCJkYXRhYmFzZU9wdGlvbnMiLCJkYk9wdGlvbnMiLCJnZXREYXRhYmFzZU9wdGlvbnNGcm9tVVJJIiwia2V5IiwiaW5pdE9wdGlvbnMiLCJwZ3AiLCJjbGllbnQiLCJwZ09wdGlvbnMiLCJwZyIsImRlZmF1bHRzIl0sIm1hcHBpbmdzIjoiOzs7OztRQUdnQkEsWSxHQUFBQSxZOztBQUZoQixNQUFNQyxTQUFTQyxRQUFRLHdCQUFSLENBQWY7O0FBRU8sU0FBU0YsWUFBVCxDQUFzQkcsR0FBdEIsRUFBMkJDLGVBQTNCLEVBQTRDO0FBQ2pELE1BQUlDLFlBQVksRUFBaEI7QUFDQUQsb0JBQWtCQSxtQkFBbUIsRUFBckM7O0FBRUEsTUFBSUQsR0FBSixFQUFTO0FBQ1BFLGdCQUFZSixPQUFPSyx5QkFBUCxDQUFpQ0gsR0FBakMsQ0FBWjtBQUNEOztBQUVELE9BQUssTUFBTUksR0FBWCxJQUFrQkgsZUFBbEIsRUFBbUM7QUFDakNDLGNBQVVFLEdBQVYsSUFBaUJILGdCQUFnQkcsR0FBaEIsQ0FBakI7QUFDRDs7QUFFRCxRQUFNQyxjQUFjSCxVQUFVRyxXQUFWLElBQXlCLEVBQTdDO0FBQ0EsUUFBTUMsTUFBTVAsUUFBUSxZQUFSLEVBQXNCTSxXQUF0QixDQUFaO0FBQ0EsUUFBTUUsU0FBU0QsSUFBSUosU0FBSixDQUFmOztBQUVBLE1BQUlBLFVBQVVNLFNBQWQsRUFBeUI7QUFDdkIsU0FBSyxNQUFNSixHQUFYLElBQWtCRixVQUFVTSxTQUE1QixFQUF1QztBQUNyQ0YsVUFBSUcsRUFBSixDQUFPQyxRQUFQLENBQWdCTixHQUFoQixJQUF1QkYsVUFBVU0sU0FBVixDQUFvQkosR0FBcEIsQ0FBdkI7QUFDRDtBQUNGOztBQUVELFNBQU8sRUFBRUcsTUFBRixFQUFVRCxHQUFWLEVBQVA7QUFDRCIsImZpbGUiOiJQb3N0Z3Jlc0NsaWVudC5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc3QgcGFyc2VyID0gcmVxdWlyZSgnLi9Qb3N0Z3Jlc0NvbmZpZ1BhcnNlcicpO1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ2xpZW50KHVyaSwgZGF0YWJhc2VPcHRpb25zKSB7XG4gIGxldCBkYk9wdGlvbnMgPSB7fTtcbiAgZGF0YWJhc2VPcHRpb25zID0gZGF0YWJhc2VPcHRpb25zIHx8IHt9O1xuXG4gIGlmICh1cmkpIHtcbiAgICBkYk9wdGlvbnMgPSBwYXJzZXIuZ2V0RGF0YWJhc2VPcHRpb25zRnJvbVVSSSh1cmkpO1xuICB9XG5cbiAgZm9yIChjb25zdCBrZXkgaW4gZGF0YWJhc2VPcHRpb25zKSB7XG4gICAgZGJPcHRpb25zW2tleV0gPSBkYXRhYmFzZU9wdGlvbnNba2V5XTtcbiAgfVxuXG4gIGNvbnN0IGluaXRPcHRpb25zID0gZGJPcHRpb25zLmluaXRPcHRpb25zIHx8IHt9O1xuICBjb25zdCBwZ3AgPSByZXF1aXJlKCdwZy1wcm9taXNlJykoaW5pdE9wdGlvbnMpO1xuICBjb25zdCBjbGllbnQgPSBwZ3AoZGJPcHRpb25zKTtcblxuICBpZiAoZGJPcHRpb25zLnBnT3B0aW9ucykge1xuICAgIGZvciAoY29uc3Qga2V5IGluIGRiT3B0aW9ucy5wZ09wdGlvbnMpIHtcbiAgICAgIHBncC5wZy5kZWZhdWx0c1trZXldID0gZGJPcHRpb25zLnBnT3B0aW9uc1trZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IGNsaWVudCwgcGdwIH07XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/PostgresConfigParser.js b/lib/Adapters/Storage/Postgres/PostgresConfigParser.js index 19a5112a8b..a43631ed90 100644 --- a/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +++ b/lib/Adapters/Storage/Postgres/PostgresConfigParser.js @@ -43,4 +43,5 @@ function parseQueryParams(queryString) { module.exports = { parseQueryParams: parseQueryParams, getDatabaseOptionsFromURI: getDatabaseOptionsFromURI -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzQ29uZmlnUGFyc2VyLmpzIl0sIm5hbWVzIjpbInVybCIsInJlcXVpcmUiLCJnZXREYXRhYmFzZU9wdGlvbnNGcm9tVVJJIiwidXJpIiwiZGF0YWJhc2VPcHRpb25zIiwicGFyc2VkVVJJIiwicGFyc2UiLCJxdWVyeVBhcmFtcyIsInBhcnNlUXVlcnlQYXJhbXMiLCJxdWVyeSIsImF1dGhQYXJ0cyIsImF1dGgiLCJzcGxpdCIsImhvc3QiLCJob3N0bmFtZSIsInBvcnQiLCJwYXJzZUludCIsImRhdGFiYXNlIiwicGF0aG5hbWUiLCJzdWJzdHIiLCJ1bmRlZmluZWQiLCJ1c2VyIiwibGVuZ3RoIiwicGFzc3dvcmQiLCJzc2wiLCJ0b0xvd2VyQ2FzZSIsImJpbmFyeSIsImNsaWVudF9lbmNvZGluZyIsImFwcGxpY2F0aW9uX25hbWUiLCJmYWxsYmFja19hcHBsaWNhdGlvbl9uYW1lIiwicG9vbFNpemUiLCJxdWVyeVN0cmluZyIsInJlZHVjZSIsInAiLCJjIiwicGFydHMiLCJkZWNvZGVVUklDb21wb25lbnQiLCJzbGljZSIsImpvaW4iLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLE1BQU1BLE1BQU1DLFFBQVEsS0FBUixDQUFaOztBQUVBLFNBQVNDLHlCQUFULENBQW1DQyxHQUFuQyxFQUF3QztBQUN0QyxRQUFNQyxrQkFBa0IsRUFBeEI7O0FBRUEsUUFBTUMsWUFBWUwsSUFBSU0sS0FBSixDQUFVSCxHQUFWLENBQWxCO0FBQ0EsUUFBTUksY0FBY0MsaUJBQWlCSCxVQUFVSSxLQUEzQixDQUFwQjtBQUNBLFFBQU1DLFlBQVlMLFVBQVVNLElBQVYsR0FBaUJOLFVBQVVNLElBQVYsQ0FBZUMsS0FBZixDQUFxQixHQUFyQixDQUFqQixHQUE2QyxFQUEvRDs7QUFFQVIsa0JBQWdCUyxJQUFoQixHQUF1QlIsVUFBVVMsUUFBVixJQUFzQixXQUE3QztBQUNBVixrQkFBZ0JXLElBQWhCLEdBQXVCVixVQUFVVSxJQUFWLEdBQWlCQyxTQUFTWCxVQUFVVSxJQUFuQixDQUFqQixHQUE0QyxJQUFuRTtBQUNBWCxrQkFBZ0JhLFFBQWhCLEdBQTJCWixVQUFVYSxRQUFWLEdBQ3ZCYixVQUFVYSxRQUFWLENBQW1CQyxNQUFuQixDQUEwQixDQUExQixDQUR1QixHQUV2QkMsU0FGSjs7QUFJQWhCLGtCQUFnQmlCLElBQWhCLEdBQXVCWCxVQUFVWSxNQUFWLEdBQW1CLENBQW5CLEdBQXVCWixVQUFVLENBQVYsQ0FBdkIsR0FBc0MsRUFBN0Q7QUFDQU4sa0JBQWdCbUIsUUFBaEIsR0FBMkJiLFVBQVVZLE1BQVYsR0FBbUIsQ0FBbkIsR0FBdUJaLFVBQVUsQ0FBVixDQUF2QixHQUFzQyxFQUFqRTs7QUFFQU4sa0JBQWdCb0IsR0FBaEIsR0FDRWpCLFlBQVlpQixHQUFaLElBQW1CakIsWUFBWWlCLEdBQVosQ0FBZ0JDLFdBQWhCLE9BQWtDLE1BQXJELEdBQThELElBQTlELEdBQXFFLEtBRHZFO0FBRUFyQixrQkFBZ0JzQixNQUFoQixHQUNFbkIsWUFBWW1CLE1BQVosSUFBc0JuQixZQUFZbUIsTUFBWixDQUFtQkQsV0FBbkIsT0FBcUMsTUFBM0QsR0FBb0UsSUFBcEUsR0FBMkUsS0FEN0U7O0FBR0FyQixrQkFBZ0J1QixlQUFoQixHQUFrQ3BCLFlBQVlvQixlQUE5QztBQUNBdkIsa0JBQWdCd0IsZ0JBQWhCLEdBQW1DckIsWUFBWXFCLGdCQUEvQztBQUNBeEIsa0JBQWdCeUIseUJBQWhCLEdBQTRDdEIsWUFBWXNCLHlCQUF4RDs7QUFFQSxNQUFJdEIsWUFBWXVCLFFBQWhCLEVBQTBCO0FBQ3hCMUIsb0JBQWdCMEIsUUFBaEIsR0FBMkJkLFNBQVNULFlBQVl1QixRQUFyQixLQUFrQyxFQUE3RDtBQUNEOztBQUVELFNBQU8xQixlQUFQO0FBQ0Q7O0FBRUQsU0FBU0ksZ0JBQVQsQ0FBMEJ1QixXQUExQixFQUF1QztBQUNyQ0EsZ0JBQWNBLGVBQWUsRUFBN0I7O0FBRUEsU0FBT0EsWUFDSm5CLEtBREksQ0FDRSxHQURGLEVBRUpvQixNQUZJLENBRUcsQ0FBQ0MsQ0FBRCxFQUFJQyxDQUFKLEtBQVU7QUFDaEIsVUFBTUMsUUFBUUQsRUFBRXRCLEtBQUYsQ0FBUSxHQUFSLENBQWQ7QUFDQXFCLE1BQUVHLG1CQUFtQkQsTUFBTSxDQUFOLENBQW5CLENBQUYsSUFDRUEsTUFBTWIsTUFBTixHQUFlLENBQWYsR0FDSWMsbUJBQW1CRCxNQUFNRSxLQUFOLENBQVksQ0FBWixFQUFlQyxJQUFmLENBQW9CLEdBQXBCLENBQW5CLENBREosR0FFSSxFQUhOO0FBSUEsV0FBT0wsQ0FBUDtBQUNELEdBVEksRUFTRixFQVRFLENBQVA7QUFVRDs7QUFFRE0sT0FBT0MsT0FBUCxHQUFpQjtBQUNmaEMsb0JBQWtCQSxnQkFESDtBQUVmTiw2QkFBMkJBO0FBRlosQ0FBakIiLCJmaWxlIjoiUG9zdGdyZXNDb25maWdQYXJzZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCB1cmwgPSByZXF1aXJlKCd1cmwnKTtcblxuZnVuY3Rpb24gZ2V0RGF0YWJhc2VPcHRpb25zRnJvbVVSSSh1cmkpIHtcbiAgY29uc3QgZGF0YWJhc2VPcHRpb25zID0ge307XG5cbiAgY29uc3QgcGFyc2VkVVJJID0gdXJsLnBhcnNlKHVyaSk7XG4gIGNvbnN0IHF1ZXJ5UGFyYW1zID0gcGFyc2VRdWVyeVBhcmFtcyhwYXJzZWRVUkkucXVlcnkpO1xuICBjb25zdCBhdXRoUGFydHMgPSBwYXJzZWRVUkkuYXV0aCA/IHBhcnNlZFVSSS5hdXRoLnNwbGl0KCc6JykgOiBbXTtcblxuICBkYXRhYmFzZU9wdGlvbnMuaG9zdCA9IHBhcnNlZFVSSS5ob3N0bmFtZSB8fCAnbG9jYWxob3N0JztcbiAgZGF0YWJhc2VPcHRpb25zLnBvcnQgPSBwYXJzZWRVUkkucG9ydCA/IHBhcnNlSW50KHBhcnNlZFVSSS5wb3J0KSA6IDU0MzI7XG4gIGRhdGFiYXNlT3B0aW9ucy5kYXRhYmFzZSA9IHBhcnNlZFVSSS5wYXRobmFtZVxuICAgID8gcGFyc2VkVVJJLnBhdGhuYW1lLnN1YnN0cigxKVxuICAgIDogdW5kZWZpbmVkO1xuXG4gIGRhdGFiYXNlT3B0aW9ucy51c2VyID0gYXV0aFBhcnRzLmxlbmd0aCA+IDAgPyBhdXRoUGFydHNbMF0gOiAnJztcbiAgZGF0YWJhc2VPcHRpb25zLnBhc3N3b3JkID0gYXV0aFBhcnRzLmxlbmd0aCA+IDEgPyBhdXRoUGFydHNbMV0gOiAnJztcblxuICBkYXRhYmFzZU9wdGlvbnMuc3NsID1cbiAgICBxdWVyeVBhcmFtcy5zc2wgJiYgcXVlcnlQYXJhbXMuc3NsLnRvTG93ZXJDYXNlKCkgPT09ICd0cnVlJyA/IHRydWUgOiBmYWxzZTtcbiAgZGF0YWJhc2VPcHRpb25zLmJpbmFyeSA9XG4gICAgcXVlcnlQYXJhbXMuYmluYXJ5ICYmIHF1ZXJ5UGFyYW1zLmJpbmFyeS50b0xvd2VyQ2FzZSgpID09PSAndHJ1ZScgPyB0cnVlIDogZmFsc2U7XG5cbiAgZGF0YWJhc2VPcHRpb25zLmNsaWVudF9lbmNvZGluZyA9IHF1ZXJ5UGFyYW1zLmNsaWVudF9lbmNvZGluZztcbiAgZGF0YWJhc2VPcHRpb25zLmFwcGxpY2F0aW9uX25hbWUgPSBxdWVyeVBhcmFtcy5hcHBsaWNhdGlvbl9uYW1lO1xuICBkYXRhYmFzZU9wdGlvbnMuZmFsbGJhY2tfYXBwbGljYXRpb25fbmFtZSA9IHF1ZXJ5UGFyYW1zLmZhbGxiYWNrX2FwcGxpY2F0aW9uX25hbWU7XG5cbiAgaWYgKHF1ZXJ5UGFyYW1zLnBvb2xTaXplKSB7XG4gICAgZGF0YWJhc2VPcHRpb25zLnBvb2xTaXplID0gcGFyc2VJbnQocXVlcnlQYXJhbXMucG9vbFNpemUpIHx8IDEwO1xuICB9XG5cbiAgcmV0dXJuIGRhdGFiYXNlT3B0aW9ucztcbn1cblxuZnVuY3Rpb24gcGFyc2VRdWVyeVBhcmFtcyhxdWVyeVN0cmluZykge1xuICBxdWVyeVN0cmluZyA9IHF1ZXJ5U3RyaW5nIHx8ICcnO1xuXG4gIHJldHVybiBxdWVyeVN0cmluZ1xuICAgIC5zcGxpdCgnJicpXG4gICAgLnJlZHVjZSgocCwgYykgPT4ge1xuICAgICAgY29uc3QgcGFydHMgPSBjLnNwbGl0KCc9Jyk7XG4gICAgICBwW2RlY29kZVVSSUNvbXBvbmVudChwYXJ0c1swXSldID1cbiAgICAgICAgcGFydHMubGVuZ3RoID4gMVxuICAgICAgICAgID8gZGVjb2RlVVJJQ29tcG9uZW50KHBhcnRzLnNsaWNlKDEpLmpvaW4oJz0nKSlcbiAgICAgICAgICA6ICcnO1xuICAgICAgcmV0dXJuIHA7XG4gICAgfSwge30pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgcGFyc2VRdWVyeVBhcmFtczogcGFyc2VRdWVyeVBhcmFtcyxcbiAgZ2V0RGF0YWJhc2VPcHRpb25zRnJvbVVSSTogZ2V0RGF0YWJhc2VPcHRpb25zRnJvbVVSSVxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js index e238f40ada..5e499c41df 100644 --- a/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -313,13 +313,20 @@ const buildWhereClause = ({ schema, query, index }) => { index += 2; } else if (typeof fieldValue === 'boolean') { patterns.push(`$${index}:name = $${index + 1}`); - values.push(fieldName, fieldValue); + // 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 (fieldName === '$or' || fieldName === '$and') { + } else if (['$or', '$nor', '$and'].includes(fieldName)) { const clauses = []; const clauseValues = []; fieldValue.forEach(subQuery => { @@ -330,8 +337,11 @@ const buildWhereClause = ({ schema, query, index }) => { index += clause.values.length; } }); - const orOrAnd = fieldName === '$or' ? ' OR ' : ' AND '; - patterns.push(`(${clauses.join(orOrAnd)})`); + + const orOrAnd = fieldName === '$and' ? ' AND ' : ' OR '; + const not = fieldName === '$nor' ? ' NOT ' : ''; + + patterns.push(`${not}(${clauses.join(orOrAnd)})`); values.push(...clauseValues); } @@ -355,11 +365,16 @@ const buildWhereClause = ({ schema, query, index }) => { values.push(fieldName, fieldValue.$ne); index += 2; } - - if (fieldValue.$eq) { - patterns.push(`$${index}:name = $${index + 1}`); - values.push(fieldName, fieldValue.$eq); - index += 2; + if (fieldValue.$eq !== undefined) { + if (fieldValue.$eq === null) { + patterns.push(`$${index}:name IS NULL`); + values.push(fieldName); + index += 1; + } else { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.$eq); + 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') { @@ -416,10 +431,26 @@ const buildWhereClause = ({ schema, query, index }) => { if (fieldValue.$nin) { createConstraint(_lodash2.default.flatMap(fieldValue.$nin, elt => elt), true); } + } else if (typeof fieldValue.$in !== 'undefined') { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $in value'); + } else if (typeof fieldValue.$nin !== 'undefined') { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $nin value'); } if (Array.isArray(fieldValue.$all) && isArrayField) { - patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`); + if (isAnyValueRegexStartsWith(fieldValue.$all)) { + if (!isAllValuesRegexOrNone(fieldValue.$all)) { + throw new _node2.default.Error(_node2.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; } @@ -434,6 +465,17 @@ const buildWhereClause = ({ schema, query, index }) => { index += 1; } + if (fieldValue.$containedBy) { + const arr = fieldValue.$containedBy; + if (!(arr instanceof Array)) { + throw new _node2.default.Error(_node2.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'; @@ -485,15 +527,51 @@ const buildWhereClause = ({ schema, query, index }) => { index += 2; } + if (fieldValue.$geoWithin && fieldValue.$geoWithin.$centerSphere) { + const centerSphere = fieldValue.$geoWithin.$centerSphere; + if (!(centerSphere instanceof Array) || centerSphere.length < 2) { + throw new _node2.default.Error(_node2.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 _node2.default.GeoPoint(point[1], point[0]); + } else if (!GeoPointCoder.isValidJSON(point)) { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere geo point invalid'); + } + _node2.default.GeoPoint._validate(point.latitude, point.longitude); + // Get distance and validate + const distance = centerSphere[1]; + if (isNaN(distance) || distance < 0) { + throw new _node2.default.Error(_node2.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; - if (!(polygon instanceof Array)) { - throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); - } - if (polygon.length < 3) { - throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + let points; + if (typeof polygon === 'object' && polygon.__type === 'Polygon') { + if (!polygon.coordinates || polygon.coordinates.length < 3) { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'); + } + points = polygon; + } else { + throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint\'s'); } - const points = polygon.map(point => { + points = points.map(point => { + if (point instanceof Array && point.length === 2) { + _node2.default.GeoPoint._validate(point[1], point[0]); + return `(${point[0]}, ${point[1]})`; + } if (typeof point !== 'object' || point.__type !== 'GeoPoint') { throw new _node2.default.Error(_node2.default.Error.INVALID_JSON, 'bad $geoWithin value'); } else { @@ -571,7 +649,7 @@ const buildWhereClause = ({ schema, query, index }) => { } Object.keys(ParseToPosgresComparator).forEach(cmp => { - if (fieldValue[cmp]) { + if (fieldValue[cmp] || fieldValue[cmp] === 0) { const pgComparator = ParseToPosgresComparator[cmp]; patterns.push(`$${index}:name ${pgComparator} $${index + 1}`); values.push(fieldName, toPostgresValue(fieldValue[cmp])); @@ -598,7 +676,9 @@ class PostgresStorageAdapter { const { client, pgp } = (0, _PostgresClient.createClient)(uri, databaseOptions); this._client = client; this._pgp = pgp; + this.canSortOnJoinTables = false; } + // Private @@ -1220,7 +1300,7 @@ class PostgresStorageAdapter { return p + ` - '$${index + 1 + i}:value'`; }, ''); - updatePatterns.push(`$${index}:name = ( COALESCE($${index}:name, '{}'::jsonb) ${deletePatterns} ${incrementPatterns} || $${index + 1 + keysToDelete.length}::jsonb )`); + updatePatterns.push(`$${index}:name = ('{}'::jsonb ${deletePatterns} ${incrementPatterns} || $${index + 1 + keysToDelete.length}::jsonb )`); values.push(fieldName, ...keysToDelete, JSON.stringify(fieldValue)); index += 2 + keysToDelete.length; @@ -1290,11 +1370,12 @@ class PostgresStorageAdapter { 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 `"${key}" ASC`; + return `${transformKey} ASC`; } - return `"${key}" DESC`; + return `${transformKey} DESC`; }).join(); sortPattern = sort !== undefined && Object.keys(sort).length > 0 ? `ORDER BY ${sorting}` : ''; } @@ -1672,7 +1753,7 @@ class PostgresStorageAdapter { }); return Promise.all(promises).then(() => { return this._client.tx('perform-initialization', t => { - return t.batch([t.none(_sql2.default.misc.jsonObjectSetKeys), t.none(_sql2.default.array.add), t.none(_sql2.default.array.addUnique), t.none(_sql2.default.array.remove), t.none(_sql2.default.array.containsAll), t.none(_sql2.default.array.contains)]); + return t.batch([t.none(_sql2.default.misc.jsonObjectSetKeys), t.none(_sql2.default.array.add), t.none(_sql2.default.array.addUnique), t.none(_sql2.default.array.remove), t.none(_sql2.default.array.containsAll), t.none(_sql2.default.array.containsAllRegex), t.none(_sql2.default.array.contains)]); }); }).then(data => { debug(`initializationDone in ${data.duration}`); @@ -1764,6 +1845,40 @@ function processRegexPattern(s) { 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 => { if (c.match(/[0-9a-zA-Z]/) !== null) { @@ -1800,4 +1915,11 @@ function literalizeRegexPart(s) { return s.replace(/([^\\])(\\E)/, '$1').replace(/([^\\])(\\Q)/, '$1').replace(/^\\E/, '').replace(/^\\Q/, '').replace(/([^'])'/, `$1''`).replace(/^'([^'])/, `''$1`); } -exports.default = PostgresStorageAdapter; \ No newline at end of file +var GeoPointCoder = { + isValidJSON(value) { + return typeof value === 'object' && value !== null && value.__type === 'GeoPoint'; + } +}; + +exports.default = PostgresStorageAdapter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsiUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVDb2x1bW5FcnJvciIsIlBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yIiwiUG9zdGdyZXNEdXBsaWNhdGVPYmplY3RFcnJvciIsIlBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciIsIlBvc3RncmVzVHJhbnNhY3Rpb25BYm9ydGVkRXJyb3IiLCJsb2dnZXIiLCJyZXF1aXJlIiwiZGVidWciLCJhcmdzIiwiYXJndW1lbnRzIiwiY29uY2F0Iiwic2xpY2UiLCJsZW5ndGgiLCJsb2ciLCJnZXRMb2dnZXIiLCJhcHBseSIsInBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlIiwidHlwZSIsImNvbnRlbnRzIiwiSlNPTiIsInN0cmluZ2lmeSIsIlBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvciIsIm1vbmdvQWdncmVnYXRlVG9Qb3N0Z3JlcyIsIiRkYXlPZk1vbnRoIiwiJGRheU9mV2VlayIsIiRkYXlPZlllYXIiLCIkaXNvRGF5T2ZXZWVrIiwiJGlzb1dlZWtZZWFyIiwiJGhvdXIiLCIkbWludXRlIiwiJHNlY29uZCIsIiRtaWxsaXNlY29uZCIsIiRtb250aCIsIiR3ZWVrIiwiJHllYXIiLCJ0b1Bvc3RncmVzVmFsdWUiLCJ2YWx1ZSIsIl9fdHlwZSIsImlzbyIsIm5hbWUiLCJ0cmFuc2Zvcm1WYWx1ZSIsIm9iamVjdElkIiwiZW1wdHlDTFBTIiwiT2JqZWN0IiwiZnJlZXplIiwiZmluZCIsImdldCIsImNyZWF0ZSIsInVwZGF0ZSIsImRlbGV0ZSIsImFkZEZpZWxkIiwiZGVmYXVsdENMUFMiLCJ0b1BhcnNlU2NoZW1hIiwic2NoZW1hIiwiY2xhc3NOYW1lIiwiZmllbGRzIiwiX2hhc2hlZF9wYXNzd29yZCIsIl93cGVybSIsIl9ycGVybSIsImNscHMiLCJjbGFzc0xldmVsUGVybWlzc2lvbnMiLCJpbmRleGVzIiwidG9Qb3N0Z3Jlc1NjaGVtYSIsIl9wYXNzd29yZF9oaXN0b3J5IiwiaGFuZGxlRG90RmllbGRzIiwib2JqZWN0Iiwia2V5cyIsImZvckVhY2giLCJmaWVsZE5hbWUiLCJpbmRleE9mIiwiY29tcG9uZW50cyIsInNwbGl0IiwiZmlyc3QiLCJzaGlmdCIsImN1cnJlbnRPYmoiLCJuZXh0IiwiX19vcCIsInVuZGVmaW5lZCIsInRyYW5zZm9ybURvdEZpZWxkVG9Db21wb25lbnRzIiwibWFwIiwiY21wdCIsImluZGV4IiwidHJhbnNmb3JtRG90RmllbGQiLCJqb2luIiwidHJhbnNmb3JtQWdncmVnYXRlRmllbGQiLCJzdWJzdHIiLCJ2YWxpZGF0ZUtleXMiLCJrZXkiLCJpbmNsdWRlcyIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX05FU1RFRF9LRVkiLCJqb2luVGFibGVzRm9yU2NoZW1hIiwibGlzdCIsImZpZWxkIiwicHVzaCIsImJ1aWxkV2hlcmVDbGF1c2UiLCJxdWVyeSIsInBhdHRlcm5zIiwidmFsdWVzIiwic29ydHMiLCJpc0FycmF5RmllbGQiLCJpbml0aWFsUGF0dGVybnNMZW5ndGgiLCJmaWVsZFZhbHVlIiwiJGV4aXN0cyIsIiRpbiIsImluUGF0dGVybnMiLCJsaXN0RWxlbSIsIiRyZWdleCIsIk1BWF9JTlRfUExVU19PTkUiLCJjbGF1c2VzIiwiY2xhdXNlVmFsdWVzIiwic3ViUXVlcnkiLCJjbGF1c2UiLCJwYXR0ZXJuIiwib3JPckFuZCIsIm5vdCIsIiRuZSIsIiRlcSIsImlzSW5Pck5pbiIsIkFycmF5IiwiaXNBcnJheSIsIiRuaW4iLCJhbGxvd051bGwiLCJsaXN0SW5kZXgiLCJjcmVhdGVDb25zdHJhaW50IiwiYmFzZUFycmF5Iiwibm90SW4iLCJfIiwiZmxhdE1hcCIsImVsdCIsIklOVkFMSURfSlNPTiIsIiRhbGwiLCJpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoIiwiaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSIsImkiLCJwcm9jZXNzUmVnZXhQYXR0ZXJuIiwic3Vic3RyaW5nIiwiJGNvbnRhaW5lZEJ5IiwiYXJyIiwiJHRleHQiLCJzZWFyY2giLCIkc2VhcmNoIiwibGFuZ3VhZ2UiLCIkdGVybSIsIiRsYW5ndWFnZSIsIiRjYXNlU2Vuc2l0aXZlIiwiJGRpYWNyaXRpY1NlbnNpdGl2ZSIsIiRuZWFyU3BoZXJlIiwicG9pbnQiLCJkaXN0YW5jZSIsIiRtYXhEaXN0YW5jZSIsImRpc3RhbmNlSW5LTSIsImxvbmdpdHVkZSIsImxhdGl0dWRlIiwiJHdpdGhpbiIsIiRib3giLCJib3giLCJsZWZ0IiwiYm90dG9tIiwicmlnaHQiLCJ0b3AiLCIkZ2VvV2l0aGluIiwiJGNlbnRlclNwaGVyZSIsImNlbnRlclNwaGVyZSIsIkdlb1BvaW50IiwiR2VvUG9pbnRDb2RlciIsImlzVmFsaWRKU09OIiwiX3ZhbGlkYXRlIiwiaXNOYU4iLCIkcG9seWdvbiIsInBvbHlnb24iLCJwb2ludHMiLCJjb29yZGluYXRlcyIsIiRnZW9JbnRlcnNlY3RzIiwiJHBvaW50IiwicmVnZXgiLCJvcGVyYXRvciIsIm9wdHMiLCIkb3B0aW9ucyIsInJlbW92ZVdoaXRlU3BhY2UiLCJjb252ZXJ0UG9seWdvblRvU1FMIiwiY21wIiwicGdDb21wYXJhdG9yIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsIlBvc3RncmVzU3RvcmFnZUFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsInVyaSIsImNvbGxlY3Rpb25QcmVmaXgiLCJkYXRhYmFzZU9wdGlvbnMiLCJfY29sbGVjdGlvblByZWZpeCIsImNsaWVudCIsInBncCIsIl9jbGllbnQiLCJfcGdwIiwiY2FuU29ydE9uSm9pblRhYmxlcyIsImhhbmRsZVNodXRkb3duIiwiJHBvb2wiLCJlbmQiLCJfZW5zdXJlU2NoZW1hQ29sbGVjdGlvbkV4aXN0cyIsImNvbm4iLCJub25lIiwiY2F0Y2giLCJlcnJvciIsImNvZGUiLCJjbGFzc0V4aXN0cyIsIm9uZSIsImEiLCJleGlzdHMiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2VsZiIsInRhc2siLCJ0Iiwic2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQiLCJzdWJtaXR0ZWRJbmRleGVzIiwiZXhpc3RpbmdJbmRleGVzIiwiUHJvbWlzZSIsInJlc29sdmUiLCJfaWRfIiwiX2lkIiwiZGVsZXRlZEluZGV4ZXMiLCJpbnNlcnRlZEluZGV4ZXMiLCJJTlZBTElEX1FVRVJZIiwiaGFzT3duUHJvcGVydHkiLCJ0eCIsImNyZWF0ZUluZGV4ZXMiLCJkcm9wSW5kZXhlcyIsImNyZWF0ZUNsYXNzIiwicTEiLCJjcmVhdGVUYWJsZSIsInEyIiwicTMiLCJiYXRjaCIsInRoZW4iLCJlcnIiLCJkYXRhIiwicmVzdWx0IiwiZGV0YWlsIiwiRFVQTElDQVRFX1ZBTFVFIiwidmFsdWVzQXJyYXkiLCJwYXR0ZXJuc0FycmF5IiwiYXNzaWduIiwiX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0IiwiX2VtYWlsX3ZlcmlmeV90b2tlbiIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIl9mYWlsZWRfbG9naW5fY291bnQiLCJfcGVyaXNoYWJsZV90b2tlbiIsIl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQiLCJfcGFzc3dvcmRfY2hhbmdlZF9hdCIsInJlbGF0aW9ucyIsInBhcnNlVHlwZSIsInFzIiwiam9pblRhYmxlIiwic2NoZW1hVXBncmFkZSIsImNvbHVtbnMiLCJjb2x1bW5fbmFtZSIsIm5ld0NvbHVtbnMiLCJmaWx0ZXIiLCJpdGVtIiwiYWRkRmllbGRJZk5vdEV4aXN0cyIsInBvc3RncmVzVHlwZSIsImFueSIsInBhdGgiLCJkZWxldGVDbGFzcyIsIm9wZXJhdGlvbnMiLCJoZWxwZXJzIiwiZGVsZXRlQWxsQ2xhc3NlcyIsIm5vdyIsIkRhdGUiLCJnZXRUaW1lIiwicmVzdWx0cyIsImpvaW5zIiwicmVkdWNlIiwiY2xhc3NlcyIsInF1ZXJpZXMiLCJkZWxldGVGaWVsZHMiLCJmaWVsZE5hbWVzIiwiaWR4IiwiZ2V0QWxsQ2xhc3NlcyIsInJvdyIsImdldENsYXNzIiwiY3JlYXRlT2JqZWN0IiwiY29sdW1uc0FycmF5IiwiZ2VvUG9pbnRzIiwiYXV0aERhdGFNYXRjaCIsIm1hdGNoIiwicHJvdmlkZXIiLCJwb3AiLCJpbml0aWFsVmFsdWVzIiwidmFsIiwidGVybWluYXRpb24iLCJnZW9Qb2ludHNJbmplY3RzIiwibCIsImNvbHVtbnNQYXR0ZXJuIiwiY29sIiwidmFsdWVzUGF0dGVybiIsIm9wcyIsInVuZGVybHlpbmdFcnJvciIsImNvbnN0cmFpbnQiLCJtYXRjaGVzIiwidXNlckluZm8iLCJkdXBsaWNhdGVkX2ZpZWxkIiwiZGVsZXRlT2JqZWN0c0J5UXVlcnkiLCJ3aGVyZSIsImNvdW50IiwiT0JKRUNUX05PVF9GT1VORCIsImZpbmRPbmVBbmRVcGRhdGUiLCJ1cGRhdGVPYmplY3RzQnlRdWVyeSIsInVwZGF0ZVBhdHRlcm5zIiwib3JpZ2luYWxVcGRhdGUiLCJnZW5lcmF0ZSIsImpzb25iIiwibGFzdEtleSIsImZpZWxkTmFtZUluZGV4Iiwic3RyIiwiYW1vdW50Iiwib2JqZWN0cyIsImtleXNUb0luY3JlbWVudCIsImsiLCJpbmNyZW1lbnRQYXR0ZXJucyIsImMiLCJrZXlzVG9EZWxldGUiLCJkZWxldGVQYXR0ZXJucyIsInAiLCJleHBlY3RlZFR5cGUiLCJyZWplY3QiLCJ3aGVyZUNsYXVzZSIsInVwc2VydE9uZU9iamVjdCIsImNyZWF0ZVZhbHVlIiwic2tpcCIsImxpbWl0Iiwic29ydCIsImhhc0xpbWl0IiwiaGFzU2tpcCIsIndoZXJlUGF0dGVybiIsImxpbWl0UGF0dGVybiIsInNraXBQYXR0ZXJuIiwic29ydFBhdHRlcm4iLCJzb3J0Q29weSIsInNvcnRpbmciLCJ0cmFuc2Zvcm1LZXkiLCJwb3N0Z3Jlc09iamVjdFRvUGFyc2VPYmplY3QiLCJ0YXJnZXRDbGFzcyIsInkiLCJ4IiwiY29vcmRzIiwicGFyc2VGbG9hdCIsImNyZWF0ZWRBdCIsInRvSVNPU3RyaW5nIiwidXBkYXRlZEF0IiwiZXhwaXJlc0F0IiwiZW5zdXJlVW5pcXVlbmVzcyIsImNvbnN0cmFpbnROYW1lIiwiY29uc3RyYWludFBhdHRlcm5zIiwibWVzc2FnZSIsImRpc3RpbmN0IiwiY29sdW1uIiwiaXNOZXN0ZWQiLCJpc1BvaW50ZXJGaWVsZCIsInRyYW5zZm9ybWVyIiwiY2hpbGQiLCJhZ2dyZWdhdGUiLCJwaXBlbGluZSIsImNvdW50RmllbGQiLCJncm91cFZhbHVlcyIsImdyb3VwUGF0dGVybiIsInN0YWdlIiwiJGdyb3VwIiwiZ3JvdXBCeUZpZWxkcyIsImFsaWFzIiwib3BlcmF0aW9uIiwic291cmNlIiwiJHN1bSIsIiRtYXgiLCIkbWluIiwiJGF2ZyIsIiRwcm9qZWN0IiwiJG1hdGNoIiwiJG9yIiwiY29sbGFwc2UiLCJlbGVtZW50IiwibWF0Y2hQYXR0ZXJucyIsIiRsaW1pdCIsIiRza2lwIiwiJHNvcnQiLCJvcmRlciIsInBhcnNlSW50IiwicGVyZm9ybUluaXRpYWxpemF0aW9uIiwiVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyIsInByb21pc2VzIiwiSU5WQUxJRF9DTEFTU19OQU1FIiwiYWxsIiwic3FsIiwibWlzYyIsImpzb25PYmplY3RTZXRLZXlzIiwiYXJyYXkiLCJhZGQiLCJhZGRVbmlxdWUiLCJyZW1vdmUiLCJjb250YWluc0FsbCIsImNvbnRhaW5zQWxsUmVnZXgiLCJjb250YWlucyIsImR1cmF0aW9uIiwiY29uc29sZSIsImNyZWF0ZUluZGV4ZXNJZk5lZWRlZCIsImdldEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsInVuaXF1ZSIsImFyIiwiZm91bmRJbmRleCIsInB0IiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiZW5kc1dpdGgiLCJyZXBsYWNlIiwidHJpbSIsInMiLCJzdGFydHNXaXRoIiwibGl0ZXJhbGl6ZVJlZ2V4UGFydCIsImlzU3RhcnRzV2l0aFJlZ2V4IiwiZmlyc3RWYWx1ZXNJc1JlZ2V4Iiwic29tZSIsImNyZWF0ZUxpdGVyYWxSZWdleCIsInJlbWFpbmluZyIsIm1hdGNoZXIxIiwicmVzdWx0MSIsInByZWZpeCIsIm1hdGNoZXIyIiwicmVzdWx0MiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFFQTs7QUFFQTs7O0FBSEE7O0FBRUE7Ozs7QUFFQTs7OztBQUNBOzs7O0FBaUJBOzs7O0FBZkEsTUFBTUEsb0NBQW9DLE9BQTFDO0FBQ0EsTUFBTUMsaUNBQWlDLE9BQXZDO0FBQ0EsTUFBTUMsK0JBQStCLE9BQXJDO0FBQ0EsTUFBTUMsNkJBQTZCLE9BQW5DO0FBQ0EsTUFBTUMsK0JBQStCLE9BQXJDO0FBQ0EsTUFBTUMsb0NBQW9DLE9BQTFDO0FBQ0EsTUFBTUMsa0NBQWtDLE9BQXhDO0FBQ0EsTUFBTUMsU0FBU0MsUUFBUSxpQkFBUixDQUFmOztBQUVBLE1BQU1DLFFBQVEsVUFBUyxHQUFHQyxJQUFaLEVBQXVCO0FBQ25DQSxTQUFPLENBQUMsU0FBU0MsVUFBVSxDQUFWLENBQVYsRUFBd0JDLE1BQXhCLENBQStCRixLQUFLRyxLQUFMLENBQVcsQ0FBWCxFQUFjSCxLQUFLSSxNQUFuQixDQUEvQixDQUFQO0FBQ0EsUUFBTUMsTUFBTVIsT0FBT1MsU0FBUCxFQUFaO0FBQ0FELE1BQUlOLEtBQUosQ0FBVVEsS0FBVixDQUFnQkYsR0FBaEIsRUFBcUJMLElBQXJCO0FBQ0QsQ0FKRDs7QUFXQSxNQUFNUSwwQkFBMEJDLFFBQVE7QUFDdEMsVUFBUUEsS0FBS0EsSUFBYjtBQUNBLFNBQUssUUFBTDtBQUFlLGFBQU8sTUFBUDtBQUNmLFNBQUssTUFBTDtBQUFhLGFBQU8sMEJBQVA7QUFDYixTQUFLLFFBQUw7QUFBZSxhQUFPLE9BQVA7QUFDZixTQUFLLE1BQUw7QUFBYSxhQUFPLE1BQVA7QUFDYixTQUFLLFNBQUw7QUFBZ0IsYUFBTyxTQUFQO0FBQ2hCLFNBQUssU0FBTDtBQUFnQixhQUFPLFVBQVA7QUFDaEIsU0FBSyxRQUFMO0FBQWUsYUFBTyxrQkFBUDtBQUNmLFNBQUssVUFBTDtBQUFpQixhQUFPLE9BQVA7QUFDakIsU0FBSyxPQUFM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QURGO0FBUUQ7O0FBRUQsSUFBSXhQLGdCQUFnQjtBQUNsQkMsY0FBWW5JLEtBQVosRUFBbUI7QUFDakIsV0FBUSxPQUFPQSxLQUFQLEtBQWlCLFFBQWpCLElBQ05BLFVBQVUsSUFESixJQUVOQSxNQUFNQyxNQUFOLEtBQWlCLFVBRm5CO0FBSUQ7QUFOaUIsQ0FBcEI7O2tCQVNlb0osc0IiLCJmaWxlIjoiUG9zdGdyZXNTdG9yYWdlQWRhcHRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG5pbXBvcnQgeyBjcmVhdGVDbGllbnQgfSBmcm9tICcuL1Bvc3RncmVzQ2xpZW50Jztcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IFBhcnNlICAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBfICAgICAgICAgICAgICAgIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgc3FsICAgICAgICAgICAgICBmcm9tICcuL3NxbCc7XG5cbmNvbnN0IFBvc3RncmVzUmVsYXRpb25Eb2VzTm90RXhpc3RFcnJvciA9ICc0MlAwMSc7XG5jb25zdCBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IgPSAnNDJQMDcnO1xuY29uc3QgUG9zdGdyZXNEdXBsaWNhdGVDb2x1bW5FcnJvciA9ICc0MjcwMSc7XG5jb25zdCBQb3N0Z3Jlc01pc3NpbmdDb2x1bW5FcnJvciA9ICc0MjcwMyc7XG5jb25zdCBQb3N0Z3Jlc0R1cGxpY2F0ZU9iamVjdEVycm9yID0gJzQyNzEwJztcbmNvbnN0IFBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciA9ICcyMzUwNSc7XG5jb25zdCBQb3N0Z3Jlc1RyYW5zYWN0aW9uQWJvcnRlZEVycm9yID0gJzI1UDAyJztcbmNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJy4uLy4uLy4uL2xvZ2dlcicpO1xuXG5jb25zdCBkZWJ1ZyA9IGZ1bmN0aW9uKC4uLmFyZ3M6IGFueSkge1xuICBhcmdzID0gWydQRzogJyArIGFyZ3VtZW50c1swXV0uY29uY2F0KGFyZ3Muc2xpY2UoMSwgYXJncy5sZW5ndGgpKTtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmdldExvZ2dlcigpO1xuICBsb2cuZGVidWcuYXBwbHkobG9nLCBhcmdzKTtcbn1cblxuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSAgICBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgdHlwZSB7IFNjaGVtYVR5cGUsXG4gIFF1ZXJ5VHlwZSxcbiAgUXVlcnlPcHRpb25zIH0gZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuXG5jb25zdCBwYXJzZVR5cGVUb1Bvc3RncmVzVHlwZSA9IHR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGUudHlwZSkge1xuICBjYXNlICdTdHJpbmcnOiByZXR1cm4gJ3RleHQnO1xuICBjYXNlICdEYXRlJzogcmV0dXJuICd0aW1lc3RhbXAgd2l0aCB0aW1lIHpvbmUnO1xuICBjYXNlICdPYmplY3QnOiByZXR1cm4gJ2pzb25iJztcbiAgY2FzZSAnRmlsZSc6IHJldHVybiAndGV4dCc7XG4gIGNhc2UgJ0Jvb2xlYW4nOiByZXR1cm4gJ2Jvb2xlYW4nO1xuICBjYXNlICdQb2ludGVyJzogcmV0dXJuICdjaGFyKDEwKSc7XG4gIGNhc2UgJ051bWJlcic6IHJldHVybiAnZG91YmxlIHByZWNpc2lvbic7XG4gIGNhc2UgJ0dlb1BvaW50JzogcmV0dXJuICdwb2ludCc7XG4gIGNhc2UgJ0J5dGVzJzogcmV0dXJuICdqc29uYic7XG4gIGNhc2UgJ1BvbHlnb24nOiByZXR1cm4gJ3BvbHlnb24nO1xuICBjYXNlICdBcnJheSc6XG4gICAgaWYgKHR5cGUuY29udGVudHMgJiYgdHlwZS5jb250ZW50cy50eXBlID09PSAnU3RyaW5nJykge1xuICAgICAgcmV0dXJuICd0ZXh0W10nO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gJ2pzb25iJztcbiAgICB9XG4gIGRlZmF1bHQ6IHRocm93IGBubyB0eXBlIGZvciAke0pTT04uc3RyaW5naWZ5KHR5cGUpfSB5ZXRgO1xuICB9XG59O1xuXG5jb25zdCBQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3IgPSB7XG4gICckZ3QnOiAnPicsXG4gICckbHQnOiAnPCcsXG4gICckZ3RlJzogJz49JyxcbiAgJyRsdGUnOiAnPD0nXG59XG5cbmNvbnN0IG1vbmdvQWdncmVnYXRlVG9Qb3N0Z3JlcyA9IHtcbiAgJGRheU9mTW9udGg6ICdEQVknLFxuICAkZGF5T2ZXZWVrOiAnRE9XJyxcbiAgJGRheU9mWWVhcjogJ0RPWScsXG4gICRpc29EYXlPZldlZWs6ICdJU09ET1cnLFxuICAkaXNvV2Vla1llYXI6J0lTT1lFQVInLFxuICAkaG91cjogJ0hPVVInLFxuICAkbWludXRlOiAnTUlOVVRFJyxcbiAgJHNlY29uZDogJ1NFQ09ORCcsXG4gICRtaWxsaXNlY29uZDogJ01JTExJU0VDT05EUycsXG4gICRtb250aDogJ01PTlRIJyxcbiAgJHdlZWs6ICdXRUVLJyxcbiAgJHllYXI6ICdZRUFSJyxcbn07XG5cbmNvbnN0IHRvUG9zdGdyZXNWYWx1ZSA9IHZhbHVlID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICBpZiAodmFsdWUuX190eXBlID09PSAnRGF0ZScpIHtcbiAgICAgIHJldHVybiB2YWx1ZS5pc287XG4gICAgfVxuICAgIGlmICh2YWx1ZS5fX3R5cGUgPT09ICdGaWxlJykge1xuICAgICAgcmV0dXJuIHZhbHVlLm5hbWU7XG4gICAgfVxuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuY29uc3QgdHJhbnNmb3JtVmFsdWUgPSB2YWx1ZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgIHZhbHVlLl9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgcmV0dXJuIHZhbHVlLm9iamVjdElkO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLy8gRHVwbGljYXRlIGZyb20gdGhlbiBtb25nbyBhZGFwdGVyLi4uXG5jb25zdCBlbXB0eUNMUFMgPSBPYmplY3QuZnJlZXplKHtcbiAgZmluZDoge30sXG4gIGdldDoge30sXG4gIGNyZWF0ZToge30sXG4gIHVwZGF0ZToge30sXG4gIGRlbGV0ZToge30sXG4gIGFkZEZpZWxkOiB7fSxcbn0pO1xuXG5jb25zdCBkZWZhdWx0Q0xQUyA9IE9iamVjdC5mcmVlemUoe1xuICBmaW5kOiB7JyonOiB0cnVlfSxcbiAgZ2V0OiB7JyonOiB0cnVlfSxcbiAgY3JlYXRlOiB7JyonOiB0cnVlfSxcbiAgdXBkYXRlOiB7JyonOiB0cnVlfSxcbiAgZGVsZXRlOiB7JyonOiB0cnVlfSxcbiAgYWRkRmllbGQ6IHsnKic6IHRydWV9LFxufSk7XG5cbmNvbnN0IHRvUGFyc2VTY2hlbWEgPSAoc2NoZW1hKSA9PiB7XG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX2hhc2hlZF9wYXNzd29yZDtcbiAgfVxuICBpZiAoc2NoZW1hLmZpZWxkcykge1xuICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl93cGVybTtcbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5fcnBlcm07XG4gIH1cbiAgbGV0IGNscHMgPSBkZWZhdWx0Q0xQUztcbiAgaWYgKHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMpIHtcbiAgICBjbHBzID0gey4uLmVtcHR5Q0xQUywgLi4uc2NoZW1hLmNsYXNzTGV2ZWxQZXJtaXNzaW9uc307XG4gIH1cbiAgbGV0IGluZGV4ZXMgPSB7fTtcbiAgaWYgKHNjaGVtYS5pbmRleGVzKSB7XG4gICAgaW5kZXhlcyA9IHsuLi5zY2hlbWEuaW5kZXhlc307XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBjbGFzc05hbWU6IHNjaGVtYS5jbGFzc05hbWUsXG4gICAgZmllbGRzOiBzY2hlbWEuZmllbGRzLFxuICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogY2xwcyxcbiAgICBpbmRleGVzLFxuICB9O1xufVxuXG5jb25zdCB0b1Bvc3RncmVzU2NoZW1hID0gKHNjaGVtYSkgPT4ge1xuICBpZiAoIXNjaGVtYSkge1xuICAgIHJldHVybiBzY2hlbWE7XG4gIH1cbiAgc2NoZW1hLmZpZWxkcyA9IHNjaGVtYS5maWVsZHMgfHwge307XG4gIHNjaGVtYS5maWVsZHMuX3dwZXJtID0ge3R5cGU6ICdBcnJheScsIGNvbnRlbnRzOiB7dHlwZTogJ1N0cmluZyd9fVxuICBzY2hlbWEuZmllbGRzLl9ycGVybSA9IHt0eXBlOiAnQXJyYXknLCBjb250ZW50czoge3R5cGU6ICdTdHJpbmcnfX1cbiAgaWYgKHNjaGVtYS5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBzY2hlbWEuZmllbGRzLl9oYXNoZWRfcGFzc3dvcmQgPSB7dHlwZTogJ1N0cmluZyd9O1xuICAgIHNjaGVtYS5maWVsZHMuX3Bhc3N3b3JkX2hpc3RvcnkgPSB7dHlwZTogJ0FycmF5J307XG4gIH1cbiAgcmV0dXJuIHNjaGVtYTtcbn1cblxuY29uc3QgaGFuZGxlRG90RmllbGRzID0gKG9iamVjdCkgPT4ge1xuICBPYmplY3Qua2V5cyhvYmplY3QpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+IC0xKSB7XG4gICAgICBjb25zdCBjb21wb25lbnRzID0gZmllbGROYW1lLnNwbGl0KCcuJyk7XG4gICAgICBjb25zdCBmaXJzdCA9IGNvbXBvbmVudHMuc2hpZnQoKTtcbiAgICAgIG9iamVjdFtmaXJzdF0gPSBvYmplY3RbZmlyc3RdIHx8IHt9O1xuICAgICAgbGV0IGN1cnJlbnRPYmogPSBvYmplY3RbZmlyc3RdO1xuICAgICAgbGV0IG5leHQ7XG4gICAgICBsZXQgdmFsdWUgPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgIGlmICh2YWx1ZSAmJiB2YWx1ZS5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB2YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbmQtYXNzaWduICovXG4gICAgICB3aGlsZShuZXh0ID0gY29tcG9uZW50cy5zaGlmdCgpKSB7XG4gICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbmQtYXNzaWduICovXG4gICAgICAgIGN1cnJlbnRPYmpbbmV4dF0gPSBjdXJyZW50T2JqW25leHRdIHx8IHt9O1xuICAgICAgICBpZiAoY29tcG9uZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICBjdXJyZW50T2JqW25leHRdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudE9iaiA9IGN1cnJlbnRPYmpbbmV4dF07XG4gICAgICB9XG4gICAgICBkZWxldGUgb2JqZWN0W2ZpZWxkTmFtZV07XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIG9iamVjdDtcbn1cblxuY29uc3QgdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMgPSAoZmllbGROYW1lKSA9PiB7XG4gIHJldHVybiBmaWVsZE5hbWUuc3BsaXQoJy4nKS5tYXAoKGNtcHQsIGluZGV4KSA9PiB7XG4gICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICByZXR1cm4gYFwiJHtjbXB0fVwiYDtcbiAgICB9XG4gICAgcmV0dXJuIGAnJHtjbXB0fSdgO1xuICB9KTtcbn1cblxuY29uc3QgdHJhbnNmb3JtRG90RmllbGQgPSAoZmllbGROYW1lKSA9PiB7XG4gIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID09PSAtMSkge1xuICAgIHJldHVybiBgXCIke2ZpZWxkTmFtZX1cImA7XG4gIH1cbiAgY29uc3QgY29tcG9uZW50cyA9IHRyYW5zZm9ybURvdEZpZWxkVG9Db21wb25lbnRzKGZpZWxkTmFtZSk7XG4gIGxldCBuYW1lID0gY29tcG9uZW50cy5zbGljZSgwLCBjb21wb25lbnRzLmxlbmd0aCAtIDEpLmpvaW4oJy0+Jyk7XG4gIG5hbWUgKz0gJy0+PicgKyBjb21wb25lbnRzW2NvbXBvbmVudHMubGVuZ3RoIC0gMV07XG4gIHJldHVybiBuYW1lO1xufVxuXG5jb25zdCB0cmFuc2Zvcm1BZ2dyZWdhdGVGaWVsZCA9IChmaWVsZE5hbWUpID0+IHtcbiAgaWYgKHR5cGVvZiBmaWVsZE5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGZpZWxkTmFtZTtcbiAgfVxuICBpZiAoZmllbGROYW1lID09PSAnJF9jcmVhdGVkX2F0Jykge1xuICAgIHJldHVybiAnY3JlYXRlZEF0JztcbiAgfVxuICBpZiAoZmllbGROYW1lID09PSAnJF91cGRhdGVkX2F0Jykge1xuICAgIHJldHVybiAndXBkYXRlZEF0JztcbiAgfVxuICByZXR1cm4gZmllbGROYW1lLnN1YnN0cigxKTtcbn1cblxuY29uc3QgdmFsaWRhdGVLZXlzID0gKG9iamVjdCkgPT4ge1xuICBpZiAodHlwZW9mIG9iamVjdCA9PSAnb2JqZWN0Jykge1xuICAgIGZvciAoY29uc3Qga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKHR5cGVvZiBvYmplY3Rba2V5XSA9PSAnb2JqZWN0Jykge1xuICAgICAgICB2YWxpZGF0ZUtleXMob2JqZWN0W2tleV0pO1xuICAgICAgfVxuXG4gICAgICBpZihrZXkuaW5jbHVkZXMoJyQnKSB8fCBrZXkuaW5jbHVkZXMoJy4nKSl7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX05FU1RFRF9LRVksIFwiTmVzdGVkIGtleXMgc2hvdWxkIG5vdCBjb250YWluIHRoZSAnJCcgb3IgJy4nIGNoYXJhY3RlcnNcIik7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vIFJldHVybnMgdGhlIGxpc3Qgb2Ygam9pbiB0YWJsZXMgb24gYSBzY2hlbWFcbmNvbnN0IGpvaW5UYWJsZXNGb3JTY2hlbWEgPSAoc2NoZW1hKSA9PiB7XG4gIGNvbnN0IGxpc3QgPSBbXTtcbiAgaWYgKHNjaGVtYSkge1xuICAgIE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLmZvckVhY2goKGZpZWxkKSA9PiB7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgICBsaXN0LnB1c2goYF9Kb2luOiR7ZmllbGR9OiR7c2NoZW1hLmNsYXNzTmFtZX1gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gbGlzdDtcbn1cblxuaW50ZXJmYWNlIFdoZXJlQ2xhdXNlIHtcbiAgcGF0dGVybjogc3RyaW5nO1xuICB2YWx1ZXM6IEFycmF5PGFueT47XG4gIHNvcnRzOiBBcnJheTxhbnk+O1xufVxuXG5jb25zdCBidWlsZFdoZXJlQ2xhdXNlID0gKHsgc2NoZW1hLCBxdWVyeSwgaW5kZXggfSk6IFdoZXJlQ2xhdXNlID0+IHtcbiAgY29uc3QgcGF0dGVybnMgPSBbXTtcbiAgbGV0IHZhbHVlcyA9IFtdO1xuICBjb25zdCBzb3J0cyA9IFtdO1xuXG4gIHNjaGVtYSA9IHRvUG9zdGdyZXNTY2hlbWEoc2NoZW1hKTtcbiAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gcXVlcnkpIHtcbiAgICBjb25zdCBpc0FycmF5RmllbGQgPSBzY2hlbWEuZmllbGRzXG4gICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdXG4gICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdBcnJheSc7XG4gICAgY29uc3QgaW5pdGlhbFBhdHRlcm5zTGVuZ3RoID0gcGF0dGVybnMubGVuZ3RoO1xuICAgIGNvbnN0IGZpZWxkVmFsdWUgPSBxdWVyeVtmaWVsZE5hbWVdO1xuXG4gICAgLy8gbm90aGluZ2luIHRoZSBzY2hlbWEsIGl0J3MgZ29ubmEgYmxvdyB1cFxuICAgIGlmICghc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdKSB7XG4gICAgICAvLyBhcyBpdCB3b24ndCBleGlzdFxuICAgICAgaWYgKGZpZWxkVmFsdWUgJiYgZmllbGRWYWx1ZS4kZXhpc3RzID09PSBmYWxzZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+PSAwKSB7XG4gICAgICBsZXQgbmFtZSA9IHRyYW5zZm9ybURvdEZpZWxkKGZpZWxkTmFtZSk7XG4gICAgICBpZiAoZmllbGRWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAke25hbWV9IElTIE5VTExgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmaWVsZFZhbHVlLiRpbikge1xuICAgICAgICAgIGNvbnN0IGluUGF0dGVybnMgPSBbXTtcbiAgICAgICAgICBuYW1lID0gdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMoZmllbGROYW1lKS5qb2luKCctPicpO1xuICAgICAgICAgIGZpZWxkVmFsdWUuJGluLmZvckVhY2goKGxpc3RFbGVtKSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGxpc3RFbGVtID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBpblBhdHRlcm5zLnB1c2goYFwiJHtsaXN0RWxlbX1cImApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaW5QYXR0ZXJucy5wdXNoKGAke2xpc3RFbGVtfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCgke25hbWV9KTo6anNvbmIgQD4gJ1ske2luUGF0dGVybnMuam9pbigpfV0nOjpqc29uYmApO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuJHJlZ2V4KSB7XG4gICAgICAgICAgLy8gSGFuZGxlIGxhdGVyXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgJHtuYW1lfSA9ICcke2ZpZWxkVmFsdWV9J2ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlID09PSBudWxsIHx8IGZpZWxkVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgSVMgTlVMTGApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgIGluZGV4ICs9IDE7XG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgLy8gQ2FuJ3QgY2FzdCBib29sZWFuIHRvIGRvdWJsZSBwcmVjaXNpb25cbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdOdW1iZXInKSB7XG4gICAgICAgIC8vIFNob3VsZCBhbHdheXMgcmV0dXJuIHplcm8gcmVzdWx0c1xuICAgICAgICBjb25zdCBNQVhfSU5UX1BMVVNfT05FID0gOTIyMzM3MjAzNjg1NDc3NTgwODtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBNQVhfSU5UX1BMVVNfT05FKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICB9XG4gICAgICBpbmRleCArPSAyO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH0gZWxzZSBpZiAoWyckb3InLCAnJG5vcicsICckYW5kJ10uaW5jbHVkZXMoZmllbGROYW1lKSkge1xuICAgICAgY29uc3QgY2xhdXNlcyA9IFtdO1xuICAgICAgY29uc3QgY2xhdXNlVmFsdWVzID0gW107XG4gICAgICBmaWVsZFZhbHVlLmZvckVhY2goKHN1YlF1ZXJ5KSA9PiAge1xuICAgICAgICBjb25zdCBjbGF1c2UgPSBidWlsZFdoZXJlQ2xhdXNlKHsgc2NoZW1hLCBxdWVyeTogc3ViUXVlcnksIGluZGV4IH0pO1xuICAgICAgICBpZiAoY2xhdXNlLnBhdHRlcm4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNsYXVzZXMucHVzaChjbGF1c2UucGF0dGVybik7XG4gICAgICAgICAgY2xhdXNlVmFsdWVzLnB1c2goLi4uY2xhdXNlLnZhbHVlcyk7XG4gICAgICAgICAgaW5kZXggKz0gY2xhdXNlLnZhbHVlcy5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBvck9yQW5kID0gZmllbGROYW1lID09PSAnJGFuZCcgPyAnIEFORCAnIDogJyBPUiAnO1xuICAgICAgY29uc3Qgbm90ID0gZmllbGROYW1lID09PSAnJG5vcicgPyAnIE5PVCAnIDogJyc7XG5cbiAgICAgIHBhdHRlcm5zLnB1c2goYCR7bm90fSgke2NsYXVzZXMuam9pbihvck9yQW5kKX0pYCk7XG4gICAgICB2YWx1ZXMucHVzaCguLi5jbGF1c2VWYWx1ZXMpO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRuZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgIGZpZWxkVmFsdWUuJG5lID0gSlNPTi5zdHJpbmdpZnkoW2ZpZWxkVmFsdWUuJG5lXSk7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYE5PVCBhcnJheV9jb250YWlucygkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfSlgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmaWVsZFZhbHVlLiRuZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5PVCBOVUxMYCk7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGlmIG5vdCBudWxsLCB3ZSBuZWVkIHRvIG1hbnVhbGx5IGV4Y2x1ZGUgbnVsbFxuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCgkJHtpbmRleH06bmFtZSA8PiAkJHtpbmRleCArIDF9IE9SICQke2luZGV4fTpuYW1lIElTIE5VTEwpYCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVE9ETzogc3VwcG9ydCBhcnJheXNcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS4kbmUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG4gICAgaWYgKGZpZWxkVmFsdWUuJGVxICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChmaWVsZFZhbHVlLiRlcSA9PT0gbnVsbCkge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSBJUyBOVUxMYCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLiRlcSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGlzSW5Pck5pbiA9IEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kaW4pIHx8IEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kbmluKTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlLiRpbikgJiZcbiAgICAgICAgaXNBcnJheUZpZWxkICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5jb250ZW50cyAmJlxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0uY29udGVudHMudHlwZSA9PT0gJ1N0cmluZycpIHtcbiAgICAgIGNvbnN0IGluUGF0dGVybnMgPSBbXTtcbiAgICAgIGxldCBhbGxvd051bGwgPSBmYWxzZTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBmaWVsZFZhbHVlLiRpbi5mb3JFYWNoKChsaXN0RWxlbSwgbGlzdEluZGV4KSA9PiB7XG4gICAgICAgIGlmIChsaXN0RWxlbSA9PT0gbnVsbCkge1xuICAgICAgICAgIGFsbG93TnVsbCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2gobGlzdEVsZW0pO1xuICAgICAgICAgIGluUGF0dGVybnMucHVzaChgJCR7aW5kZXggKyAxICsgbGlzdEluZGV4IC0gKGFsbG93TnVsbCA/IDEgOiAwKX1gKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoYWxsb3dOdWxsKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCgkJHtpbmRleH06bmFtZSBJUyBOVUxMIE9SICQke2luZGV4fTpuYW1lICYmIEFSUkFZWyR7aW5QYXR0ZXJucy5qb2luKCl9XSlgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lICYmIEFSUkFZWyR7aW5QYXR0ZXJucy5qb2luKCl9XWApO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDEgKyBpblBhdHRlcm5zLmxlbmd0aDtcbiAgICB9IGVsc2UgaWYgKGlzSW5Pck5pbikge1xuICAgICAgdmFyIGNyZWF0ZUNvbnN0cmFpbnQgPSAoYmFzZUFycmF5LCBub3RJbikgPT4ge1xuICAgICAgICBpZiAoYmFzZUFycmF5Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zdCBub3QgPSBub3RJbiA/ICcgTk9UICcgOiAnJztcbiAgICAgICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAke25vdH0gYXJyYXlfY29udGFpbnMoJCR7aW5kZXh9Om5hbWUsICQke2luZGV4ICsgMX0pYCk7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGJhc2VBcnJheSkpO1xuICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSGFuZGxlIE5lc3RlZCBEb3QgTm90YXRpb24gQWJvdmVcbiAgICAgICAgICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDApIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaW5QYXR0ZXJucyA9IFtdO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICAgIGJhc2VBcnJheS5mb3JFYWNoKChsaXN0RWxlbSwgbGlzdEluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIGlmIChsaXN0RWxlbSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGxpc3RFbGVtKTtcbiAgICAgICAgICAgICAgICBpblBhdHRlcm5zLnB1c2goYCQke2luZGV4ICsgMSArIGxpc3RJbmRleH1gKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSAke25vdH0gSU4gKCR7aW5QYXR0ZXJucy5qb2luKCl9KWApO1xuICAgICAgICAgICAgaW5kZXggPSBpbmRleCArIDEgKyBpblBhdHRlcm5zLmxlbmd0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIW5vdEluKSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSBJUyBOVUxMYCk7XG4gICAgICAgICAgaW5kZXggPSBpbmRleCArIDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChmaWVsZFZhbHVlLiRpbikge1xuICAgICAgICBjcmVhdGVDb25zdHJhaW50KF8uZmxhdE1hcChmaWVsZFZhbHVlLiRpbiwgZWx0ID0+IGVsdCksIGZhbHNlKTtcbiAgICAgIH1cbiAgICAgIGlmIChmaWVsZFZhbHVlLiRuaW4pIHtcbiAgICAgICAgY3JlYXRlQ29uc3RyYWludChfLmZsYXRNYXAoZmllbGRWYWx1ZS4kbmluLCBlbHQgPT4gZWx0KSwgdHJ1ZSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKHR5cGVvZiBmaWVsZFZhbHVlLiRpbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdiYWQgJGluIHZhbHVlJyk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZS4kbmluICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAkbmluIHZhbHVlJyk7XG4gICAgfVxuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kYWxsKSAmJiBpc0FycmF5RmllbGQpIHtcbiAgICAgIGlmIChpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoKGZpZWxkVmFsdWUuJGFsbCkpIHtcbiAgICAgICAgaWYgKCFpc0FsbFZhbHVlc1JlZ2V4T3JOb25lKGZpZWxkVmFsdWUuJGFsbCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnQWxsICRhbGwgdmFsdWVzIG11c3QgYmUgb2YgcmVnZXggdHlwZSBvciBub25lOiAnXG4gICAgICAgICAgICArIGZpZWxkVmFsdWUuJGFsbCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpZWxkVmFsdWUuJGFsbC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gcHJvY2Vzc1JlZ2V4UGF0dGVybihmaWVsZFZhbHVlLiRhbGxbaV0uJHJlZ2V4KTtcbiAgICAgICAgICBmaWVsZFZhbHVlLiRhbGxbaV0gPSB2YWx1ZS5zdWJzdHJpbmcoMSkgKyAnJSc7XG4gICAgICAgIH1cbiAgICAgICAgcGF0dGVybnMucHVzaChgYXJyYXlfY29udGFpbnNfYWxsX3JlZ2V4KCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9Ojpqc29uYilgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYGFycmF5X2NvbnRhaW5zX2FsbCgkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfTo6anNvbmIpYCk7XG4gICAgICB9XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUuJGFsbCkpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGZpZWxkVmFsdWUuJGV4aXN0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmIChmaWVsZFZhbHVlLiRleGlzdHMpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgSVMgTk9UIE5VTExgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5VTExgKTtcbiAgICAgIH1cbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBpbmRleCArPSAxO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRjb250YWluZWRCeSkge1xuICAgICAgY29uc3QgYXJyID0gZmllbGRWYWx1ZS4kY29udGFpbmVkQnk7XG4gICAgICBpZiAoIShhcnIgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICRjb250YWluZWRCeTogc2hvdWxkIGJlIGFuIGFycmF5YFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA8QCAkJHtpbmRleCArIDF9Ojpqc29uYmApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShhcnIpKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJHRleHQpIHtcbiAgICAgIGNvbnN0IHNlYXJjaCA9IGZpZWxkVmFsdWUuJHRleHQuJHNlYXJjaDtcbiAgICAgIGxldCBsYW5ndWFnZSA9ICdlbmdsaXNoJztcbiAgICAgIGlmICh0eXBlb2Ygc2VhcmNoICE9PSAnb2JqZWN0Jykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRzZWFyY2gsIHNob3VsZCBiZSBvYmplY3RgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIXNlYXJjaC4kdGVybSB8fCB0eXBlb2Ygc2VhcmNoLiR0ZXJtICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICR0ZXJtLCBzaG91bGQgYmUgc3RyaW5nYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKHNlYXJjaC4kbGFuZ3VhZ2UgJiYgdHlwZW9mIHNlYXJjaC4kbGFuZ3VhZ2UgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGxhbmd1YWdlLCBzaG91bGQgYmUgc3RyaW5nYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGxhbmd1YWdlKSB7XG4gICAgICAgIGxhbmd1YWdlID0gc2VhcmNoLiRsYW5ndWFnZTtcbiAgICAgIH1cbiAgICAgIGlmIChzZWFyY2guJGNhc2VTZW5zaXRpdmUgJiYgdHlwZW9mIHNlYXJjaC4kY2FzZVNlbnNpdGl2ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGNhc2VTZW5zaXRpdmUsIHNob3VsZCBiZSBib29sZWFuYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGNhc2VTZW5zaXRpdmUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkY2FzZVNlbnNpdGl2ZSBub3Qgc3VwcG9ydGVkLCBwbGVhc2UgdXNlICRyZWdleCBvciBjcmVhdGUgYSBzZXBhcmF0ZSBsb3dlciBjYXNlIGNvbHVtbi5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoc2VhcmNoLiRkaWFjcml0aWNTZW5zaXRpdmUgJiYgdHlwZW9mIHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkZGlhY3JpdGljU2Vuc2l0aXZlLCBzaG91bGQgYmUgYm9vbGVhbmBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VhcmNoLiRkaWFjcml0aWNTZW5zaXRpdmUgPT09IGZhbHNlKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgYGJhZCAkdGV4dDogJGRpYWNyaXRpY1NlbnNpdGl2ZSAtIGZhbHNlIG5vdCBzdXBwb3J0ZWQsIGluc3RhbGwgUG9zdGdyZXMgVW5hY2NlbnQgRXh0ZW5zaW9uYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcGF0dGVybnMucHVzaChgdG9fdHN2ZWN0b3IoJCR7aW5kZXh9LCAkJHtpbmRleCArIDF9Om5hbWUpIEBAIHRvX3RzcXVlcnkoJCR7aW5kZXggKyAyfSwgJCR7aW5kZXggKyAzfSlgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGxhbmd1YWdlLCBmaWVsZE5hbWUsIGxhbmd1YWdlLCBzZWFyY2guJHRlcm0pO1xuICAgICAgaW5kZXggKz0gNDtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kbmVhclNwaGVyZSkge1xuICAgICAgY29uc3QgcG9pbnQgPSBmaWVsZFZhbHVlLiRuZWFyU3BoZXJlO1xuICAgICAgY29uc3QgZGlzdGFuY2UgPSBmaWVsZFZhbHVlLiRtYXhEaXN0YW5jZTtcbiAgICAgIGNvbnN0IGRpc3RhbmNlSW5LTSA9IGRpc3RhbmNlICogNjM3MSAqIDEwMDA7XG4gICAgICBwYXR0ZXJucy5wdXNoKGBTVF9kaXN0YW5jZV9zcGhlcmUoJCR7aW5kZXh9Om5hbWU6Omdlb21ldHJ5LCBQT0lOVCgkJHtpbmRleCArIDF9LCAkJHtpbmRleCArIDJ9KTo6Z2VvbWV0cnkpIDw9ICQke2luZGV4ICsgM31gKTtcbiAgICAgIHNvcnRzLnB1c2goYFNUX2Rpc3RhbmNlX3NwaGVyZSgkJHtpbmRleH06bmFtZTo6Z2VvbWV0cnksIFBPSU5UKCQke2luZGV4ICsgMX0sICQke2luZGV4ICsgMn0pOjpnZW9tZXRyeSkgQVNDYClcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgcG9pbnQubG9uZ2l0dWRlLCBwb2ludC5sYXRpdHVkZSwgZGlzdGFuY2VJbktNKTtcbiAgICAgIGluZGV4ICs9IDQ7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJHdpdGhpbiAmJiBmaWVsZFZhbHVlLiR3aXRoaW4uJGJveCkge1xuICAgICAgY29uc3QgYm94ID0gZmllbGRWYWx1ZS4kd2l0aGluLiRib3g7XG4gICAgICBjb25zdCBsZWZ0ID0gYm94WzBdLmxvbmdpdHVkZTtcbiAgICAgIGNvbnN0IGJvdHRvbSA9IGJveFswXS5sYXRpdHVkZTtcbiAgICAgIGNvbnN0IHJpZ2h0ID0gYm94WzFdLmxvbmdpdHVkZTtcbiAgICAgIGNvbnN0IHRvcCA9IGJveFsxXS5sYXRpdHVkZTtcblxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWU6OnBvaW50IDxAICQke2luZGV4ICsgMX06OmJveGApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBgKCgke2xlZnR9LCAke2JvdHRvbX0pLCAoJHtyaWdodH0sICR7dG9wfSkpYCk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRnZW9XaXRoaW4gJiYgZmllbGRWYWx1ZS4kZ2VvV2l0aGluLiRjZW50ZXJTcGhlcmUpIHtcbiAgICAgIGNvbnN0IGNlbnRlclNwaGVyZSA9IGZpZWxkVmFsdWUuJGdlb1dpdGhpbi4kY2VudGVyU3BoZXJlO1xuICAgICAgaWYgKCEoY2VudGVyU3BoZXJlIGluc3RhbmNlb2YgQXJyYXkpIHx8IGNlbnRlclNwaGVyZS5sZW5ndGggPCAyKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJGNlbnRlclNwaGVyZSBzaG91bGQgYmUgYW4gYXJyYXkgb2YgUGFyc2UuR2VvUG9pbnQgYW5kIGRpc3RhbmNlJyk7XG4gICAgICB9XG4gICAgICAvLyBHZXQgcG9pbnQsIGNvbnZlcnQgdG8gZ2VvIHBvaW50IGlmIG5lY2Vzc2FyeSBhbmQgdmFsaWRhdGVcbiAgICAgIGxldCBwb2ludCA9IGNlbnRlclNwaGVyZVswXTtcbiAgICAgIGlmIChwb2ludCBpbnN0YW5jZW9mIEFycmF5ICYmIHBvaW50Lmxlbmd0aCA9PT0gMikge1xuICAgICAgICBwb2ludCA9IG5ldyBQYXJzZS5HZW9Qb2ludChwb2ludFsxXSwgcG9pbnRbMF0pO1xuICAgICAgfSBlbHNlIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihwb2ludCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkY2VudGVyU3BoZXJlIGdlbyBwb2ludCBpbnZhbGlkJyk7XG4gICAgICB9XG4gICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAvLyBHZXQgZGlzdGFuY2UgYW5kIHZhbGlkYXRlXG4gICAgICBjb25zdCBkaXN0YW5jZSA9IGNlbnRlclNwaGVyZVsxXTtcbiAgICAgIGlmKGlzTmFOKGRpc3RhbmNlKSB8fCBkaXN0YW5jZSA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkY2VudGVyU3BoZXJlIGRpc3RhbmNlIGludmFsaWQnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRpc3RhbmNlSW5LTSA9IGRpc3RhbmNlICogNjM3MSAqIDEwMDA7XG4gICAgICBwYXR0ZXJucy5wdXNoKGBTVF9kaXN0YW5jZV9zcGhlcmUoJCR7aW5kZXh9Om5hbWU6Omdlb21ldHJ5LCBQT0lOVCgkJHtpbmRleCArIDF9LCAkJHtpbmRleCArIDJ9KTo6Z2VvbWV0cnkpIDw9ICQke2luZGV4ICsgM31gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgcG9pbnQubG9uZ2l0dWRlLCBwb2ludC5sYXRpdHVkZSwgZGlzdGFuY2VJbktNKTtcbiAgICAgIGluZGV4ICs9IDQ7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJGdlb1dpdGhpbiAmJiBmaWVsZFZhbHVlLiRnZW9XaXRoaW4uJHBvbHlnb24pIHtcbiAgICAgIGNvbnN0IHBvbHlnb24gPSBmaWVsZFZhbHVlLiRnZW9XaXRoaW4uJHBvbHlnb247XG4gICAgICBsZXQgcG9pbnRzO1xuICAgICAgaWYgKHR5cGVvZiBwb2x5Z29uID09PSAnb2JqZWN0JyAmJiBwb2x5Z29uLl9fdHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgIGlmICghcG9seWdvbi5jb29yZGluYXRlcyB8fCBwb2x5Z29uLmNvb3JkaW5hdGVzLmxlbmd0aCA8IDMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7IFBvbHlnb24uY29vcmRpbmF0ZXMgc2hvdWxkIGNvbnRhaW4gYXQgbGVhc3QgMyBsb24vbGF0IHBhaXJzJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcG9pbnRzID0gcG9seWdvbi5jb29yZGluYXRlcztcbiAgICAgIH0gZWxzZSBpZiAoKHBvbHlnb24gaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgaWYgKHBvbHlnb24ubGVuZ3RoIDwgMykge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJHBvbHlnb24gc2hvdWxkIGNvbnRhaW4gYXQgbGVhc3QgMyBHZW9Qb2ludHMnXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBwb2ludHMgPSBwb2x5Z29uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRwb2x5Z29uIHNob3VsZCBiZSBQb2x5Z29uIG9iamVjdCBvciBBcnJheSBvZiBQYXJzZS5HZW9Qb2ludFxcJ3MnXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBwb2ludHMgPSBwb2ludHMubWFwKChwb2ludCkgPT4ge1xuICAgICAgICBpZiAocG9pbnQgaW5zdGFuY2VvZiBBcnJheSAmJiBwb2ludC5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnRbMV0sIHBvaW50WzBdKTtcbiAgICAgICAgICByZXR1cm4gYCgke3BvaW50WzBdfSwgJHtwb2ludFsxXX0pYDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHBvaW50ICE9PSAnb2JqZWN0JyB8fCBwb2ludC5fX3R5cGUgIT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICRnZW9XaXRoaW4gdmFsdWUnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGAoJHtwb2ludC5sb25naXR1ZGV9LCAke3BvaW50LmxhdGl0dWRlfSlgO1xuICAgICAgfSkuam9pbignLCAnKTtcblxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWU6OnBvaW50IDxAICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgYCgke3BvaW50c30pYCk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cbiAgICBpZiAoZmllbGRWYWx1ZS4kZ2VvSW50ZXJzZWN0cyAmJiBmaWVsZFZhbHVlLiRnZW9JbnRlcnNlY3RzLiRwb2ludCkge1xuICAgICAgY29uc3QgcG9pbnQgPSBmaWVsZFZhbHVlLiRnZW9JbnRlcnNlY3RzLiRwb2ludDtcbiAgICAgIGlmICh0eXBlb2YgcG9pbnQgIT09ICdvYmplY3QnIHx8IHBvaW50Ll9fdHlwZSAhPT0gJ0dlb1BvaW50Jykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICdiYWQgJGdlb0ludGVyc2VjdCB2YWx1ZTsgJHBvaW50IHNob3VsZCBiZSBHZW9Qb2ludCdcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwb2ludC5sYXRpdHVkZSwgcG9pbnQubG9uZ2l0dWRlKTtcbiAgICAgIH1cbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lOjpwb2x5Z29uIEA+ICQke2luZGV4ICsgMX06OnBvaW50YCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGAoJHtwb2ludC5sb25naXR1ZGV9LCAke3BvaW50LmxhdGl0dWRlfSlgKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJHJlZ2V4KSB7XG4gICAgICBsZXQgcmVnZXggPSBmaWVsZFZhbHVlLiRyZWdleDtcbiAgICAgIGxldCBvcGVyYXRvciA9ICd+JztcbiAgICAgIGNvbnN0IG9wdHMgPSBmaWVsZFZhbHVlLiRvcHRpb25zO1xuICAgICAgaWYgKG9wdHMpIHtcbiAgICAgICAgaWYgKG9wdHMuaW5kZXhPZignaScpID49IDApIHtcbiAgICAgICAgICBvcGVyYXRvciA9ICd+Kic7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdHMuaW5kZXhPZigneCcpID49IDApIHtcbiAgICAgICAgICByZWdleCA9IHJlbW92ZVdoaXRlU3BhY2UocmVnZXgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5hbWUgPSB0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpO1xuICAgICAgcmVnZXggPSBwcm9jZXNzUmVnZXhQYXR0ZXJuKHJlZ2V4KTtcblxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9OnJhdyAke29wZXJhdG9yfSAnJCR7aW5kZXggKyAxfTpyYXcnYCk7XG4gICAgICB2YWx1ZXMucHVzaChuYW1lLCByZWdleCk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYGFycmF5X2NvbnRhaW5zKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9KWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KFtmaWVsZFZhbHVlXSkpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5vYmplY3RJZCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRGF0ZScpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmlzbyk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgcGF0dGVybnMucHVzaCgnJCcgKyBpbmRleCArICc6bmFtZSB+PSBQT0lOVCgkJyArIChpbmRleCArIDEpICsgJywgJCcgKyAoaW5kZXggKyAyKSArICcpJyk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUubG9uZ2l0dWRlLCBmaWVsZFZhbHVlLmxhdGl0dWRlKTtcbiAgICAgIGluZGV4ICs9IDM7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFBvbHlnb25Ub1NRTChmaWVsZFZhbHVlLmNvb3JkaW5hdGVzKTtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIH49ICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgdmFsdWUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBPYmplY3Qua2V5cyhQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3IpLmZvckVhY2goY21wID0+IHtcbiAgICAgIGlmIChmaWVsZFZhbHVlW2NtcF0gfHwgZmllbGRWYWx1ZVtjbXBdID09PSAwKSB7XG4gICAgICAgIGNvbnN0IHBnQ29tcGFyYXRvciA9IFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcltjbXBdO1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSAke3BnQ29tcGFyYXRvcn0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHRvUG9zdGdyZXNWYWx1ZShmaWVsZFZhbHVlW2NtcF0pKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChpbml0aWFsUGF0dGVybnNMZW5ndGggPT09IHBhdHRlcm5zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sIGBQb3N0Z3JlcyBkb2Vzbid0IHN1cHBvcnQgdGhpcyBxdWVyeSB0eXBlIHlldCAke0pTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUpfWApO1xuICAgIH1cbiAgfVxuICB2YWx1ZXMgPSB2YWx1ZXMubWFwKHRyYW5zZm9ybVZhbHVlKTtcbiAgcmV0dXJuIHsgcGF0dGVybjogcGF0dGVybnMuam9pbignIEFORCAnKSwgdmFsdWVzLCBzb3J0cyB9O1xufVxuXG5leHBvcnQgY2xhc3MgUG9zdGdyZXNTdG9yYWdlQWRhcHRlciBpbXBsZW1lbnRzIFN0b3JhZ2VBZGFwdGVyIHtcblxuICBjYW5Tb3J0T25Kb2luVGFibGVzOiBib29sZWFuO1xuXG4gIC8vIFByaXZhdGVcbiAgX2NvbGxlY3Rpb25QcmVmaXg6IHN0cmluZztcbiAgX2NsaWVudDogYW55O1xuICBfcGdwOiBhbnk7XG5cbiAgY29uc3RydWN0b3Ioe1xuICAgIHVyaSxcbiAgICBjb2xsZWN0aW9uUHJlZml4ID0gJycsXG4gICAgZGF0YWJhc2VPcHRpb25zXG4gIH06IGFueSkge1xuICAgIHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggPSBjb2xsZWN0aW9uUHJlZml4O1xuICAgIGNvbnN0IHsgY2xpZW50LCBwZ3AgfSA9IGNyZWF0ZUNsaWVudCh1cmksIGRhdGFiYXNlT3B0aW9ucyk7XG4gICAgdGhpcy5fY2xpZW50ID0gY2xpZW50O1xuICAgIHRoaXMuX3BncCA9IHBncDtcbiAgICB0aGlzLmNhblNvcnRPbkpvaW5UYWJsZXMgPSBmYWxzZTtcbiAgfVxuXG4gIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGlmICghdGhpcy5fY2xpZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX2NsaWVudC4kcG9vbC5lbmQoKTtcbiAgfVxuXG4gIF9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzKGNvbm46IGFueSkge1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICByZXR1cm4gY29ubi5ub25lKCdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyBcIl9TQ0hFTUFcIiAoIFwiY2xhc3NOYW1lXCIgdmFyQ2hhcigxMjApLCBcInNjaGVtYVwiIGpzb25iLCBcImlzUGFyc2VDbGFzc1wiIGJvb2wsIFBSSU1BUlkgS0VZIChcImNsYXNzTmFtZVwiKSApJylcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3JcbiAgICAgICAgICB8fCBlcnJvci5jb2RlID09PSBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3JcbiAgICAgICAgICB8fCBlcnJvci5jb2RlID09PSBQb3N0Z3Jlc0R1cGxpY2F0ZU9iamVjdEVycm9yKSB7XG4gICAgICAgIC8vIFRhYmxlIGFscmVhZHkgZXhpc3RzLCBtdXN0IGhhdmUgYmVlbiBjcmVhdGVkIGJ5IGEgZGlmZmVyZW50IHJlcXVlc3QuIElnbm9yZSBlcnJvci5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBjbGFzc0V4aXN0cyhuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50Lm9uZSgnU0VMRUNUIEVYSVNUUyAoU0VMRUNUIDEgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIFdIRVJFIHRhYmxlX25hbWUgPSAkMSknLCBbbmFtZV0sIGEgPT4gYS5leGlzdHMpO1xuICB9XG5cbiAgc2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKGNsYXNzTmFtZTogc3RyaW5nLCBDTFBzOiBhbnkpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50LnRhc2soJ3NldC1jbGFzcy1sZXZlbC1wZXJtaXNzaW9ucycsIGZ1bmN0aW9uICogKHQpIHtcbiAgICAgIHlpZWxkIHNlbGYuX2Vuc3VyZVNjaGVtYUNvbGxlY3Rpb25FeGlzdHModCk7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAnc2NoZW1hJywgJ2NsYXNzTGV2ZWxQZXJtaXNzaW9ucycsIEpTT04uc3RyaW5naWZ5KENMUHMpXTtcbiAgICAgIHlpZWxkIHQubm9uZShgVVBEQVRFIFwiX1NDSEVNQVwiIFNFVCAkMjpuYW1lID0ganNvbl9vYmplY3Rfc2V0X2tleSgkMjpuYW1lLCAkMzo6dGV4dCwgJDQ6Ompzb25iKSBXSEVSRSBcImNsYXNzTmFtZVwiPSQxYCwgdmFsdWVzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KGNsYXNzTmFtZTogc3RyaW5nLCBzdWJtaXR0ZWRJbmRleGVzOiBhbnksIGV4aXN0aW5nSW5kZXhlczogYW55ID0ge30sIGZpZWxkczogYW55LCBjb25uOiA/YW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29ubiA9IGNvbm4gfHwgdGhpcy5fY2xpZW50O1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGlmIChzdWJtaXR0ZWRJbmRleGVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKGV4aXN0aW5nSW5kZXhlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICBleGlzdGluZ0luZGV4ZXMgPSB7IF9pZF86IHsgX2lkOiAxfSB9O1xuICAgIH1cbiAgICBjb25zdCBkZWxldGVkSW5kZXhlcyA9IFtdO1xuICAgIGNvbnN0IGluc2VydGVkSW5kZXhlcyA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEluZGV4ZXMpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb25zdCBmaWVsZCA9IHN1Ym1pdHRlZEluZGV4ZXNbbmFtZV07XG4gICAgICBpZiAoZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW5kZXggJHtuYW1lfSBleGlzdHMsIGNhbm5vdCB1cGRhdGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4aXN0aW5nSW5kZXhlc1tuYW1lXSAmJiBmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgYEluZGV4ICR7bmFtZX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBkZWxldGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgZGVsZXRlZEluZGV4ZXMucHVzaChuYW1lKTtcbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nSW5kZXhlc1tuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGZpZWxkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKCFmaWVsZHMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksIGBGaWVsZCAke2tleX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBhZGQgaW5kZXguYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZXhpc3RpbmdJbmRleGVzW25hbWVdID0gZmllbGQ7XG4gICAgICAgIGluc2VydGVkSW5kZXhlcy5wdXNoKHtcbiAgICAgICAgICBrZXk6IGZpZWxkLFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBjb25uLnR4KCdzZXQtaW5kZXhlcy13aXRoLXNjaGVtYS1mb3JtYXQnLCBmdW5jdGlvbiAqICh0KSB7XG4gICAgICBpZiAoaW5zZXJ0ZWRJbmRleGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgeWllbGQgc2VsZi5jcmVhdGVJbmRleGVzKGNsYXNzTmFtZSwgaW5zZXJ0ZWRJbmRleGVzLCB0KTtcbiAgICAgIH1cbiAgICAgIGlmIChkZWxldGVkSW5kZXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHlpZWxkIHNlbGYuZHJvcEluZGV4ZXMoY2xhc3NOYW1lLCBkZWxldGVkSW5kZXhlcywgdCk7XG4gICAgICB9XG4gICAgICB5aWVsZCBzZWxmLl9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzKHQpO1xuICAgICAgeWllbGQgdC5ub25lKCdVUERBVEUgXCJfU0NIRU1BXCIgU0VUICQyOm5hbWUgPSBqc29uX29iamVjdF9zZXRfa2V5KCQyOm5hbWUsICQzOjp0ZXh0LCAkNDo6anNvbmIpIFdIRVJFIFwiY2xhc3NOYW1lXCI9JDEnLCBbY2xhc3NOYW1lLCAnc2NoZW1hJywgJ2luZGV4ZXMnLCBKU09OLnN0cmluZ2lmeShleGlzdGluZ0luZGV4ZXMpXSk7XG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBjb25uOiA/YW55KSB7XG4gICAgY29ubiA9IGNvbm4gfHwgdGhpcy5fY2xpZW50O1xuICAgIHJldHVybiBjb25uLnR4KCdjcmVhdGUtY2xhc3MnLCB0ID0+IHtcbiAgICAgIGNvbnN0IHExID0gdGhpcy5jcmVhdGVUYWJsZShjbGFzc05hbWUsIHNjaGVtYSwgdCk7XG4gICAgICBjb25zdCBxMiA9IHQubm9uZSgnSU5TRVJUIElOVE8gXCJfU0NIRU1BXCIgKFwiY2xhc3NOYW1lXCIsIFwic2NoZW1hXCIsIFwiaXNQYXJzZUNsYXNzXCIpIFZBTFVFUyAoJDxjbGFzc05hbWU+LCAkPHNjaGVtYT4sIHRydWUpJywgeyBjbGFzc05hbWUsIHNjaGVtYSB9KTtcbiAgICAgIGNvbnN0IHEzID0gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWUsIHNjaGVtYS5pbmRleGVzLCB7fSwgc2NoZW1hLmZpZWxkcywgdCk7XG4gICAgICByZXR1cm4gdC5iYXRjaChbcTEsIHEyLCBxM10pO1xuICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0b1BhcnNlU2NoZW1hKHNjaGVtYSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIGlmIChlcnIuZGF0YVswXS5yZXN1bHQuY29kZSA9PT0gUG9zdGdyZXNUcmFuc2FjdGlvbkFib3J0ZWRFcnJvcikge1xuICAgICAgICAgIGVyciA9IGVyci5kYXRhWzFdLnJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXJyLmNvZGUgPT09IFBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciAmJiBlcnIuZGV0YWlsLmluY2x1ZGVzKGNsYXNzTmFtZSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLCBgQ2xhc3MgJHtjbGFzc05hbWV9IGFscmVhZHkgZXhpc3RzLmApXG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfSlcbiAgfVxuXG4gIC8vIEp1c3QgY3JlYXRlIGEgdGFibGUsIGRvIG5vdCBpbnNlcnQgaW4gc2NoZW1hXG4gIGNyZWF0ZVRhYmxlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGNvbm46IGFueSkge1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBkZWJ1ZygnY3JlYXRlVGFibGUnLCBjbGFzc05hbWUsIHNjaGVtYSk7XG4gICAgY29uc3QgdmFsdWVzQXJyYXkgPSBbXTtcbiAgICBjb25zdCBwYXR0ZXJuc0FycmF5ID0gW107XG4gICAgY29uc3QgZmllbGRzID0gT2JqZWN0LmFzc2lnbih7fSwgc2NoZW1hLmZpZWxkcyk7XG4gICAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgZmllbGRzLl9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCA9IHt0eXBlOiAnRGF0ZSd9O1xuICAgICAgZmllbGRzLl9lbWFpbF92ZXJpZnlfdG9rZW4gPSB7dHlwZTogJ1N0cmluZyd9O1xuICAgICAgZmllbGRzLl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCA9IHt0eXBlOiAnRGF0ZSd9O1xuICAgICAgZmllbGRzLl9mYWlsZWRfbG9naW5fY291bnQgPSB7dHlwZTogJ051bWJlcid9O1xuICAgICAgZmllbGRzLl9wZXJpc2hhYmxlX3Rva2VuID0ge3R5cGU6ICdTdHJpbmcnfTtcbiAgICAgIGZpZWxkcy5fcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0ID0ge3R5cGU6ICdEYXRlJ307XG4gICAgICBmaWVsZHMuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSB7dHlwZTogJ0RhdGUnfTtcbiAgICAgIGZpZWxkcy5fcGFzc3dvcmRfaGlzdG9yeSA9IHsgdHlwZTogJ0FycmF5J307XG4gICAgfVxuICAgIGxldCBpbmRleCA9IDI7XG4gICAgY29uc3QgcmVsYXRpb25zID0gW107XG4gICAgT2JqZWN0LmtleXMoZmllbGRzKS5mb3JFYWNoKChmaWVsZE5hbWUpID0+IHtcbiAgICAgIGNvbnN0IHBhcnNlVHlwZSA9IGZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgLy8gU2tpcCB3aGVuIGl0J3MgYSByZWxhdGlvblxuICAgICAgLy8gV2UnbGwgY3JlYXRlIHRoZSB0YWJsZXMgbGF0ZXJcbiAgICAgIGlmIChwYXJzZVR5cGUudHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgICByZWxhdGlvbnMucHVzaChmaWVsZE5hbWUpXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChbJ19ycGVybScsICdfd3Blcm0nXS5pbmRleE9mKGZpZWxkTmFtZSkgPj0gMCkge1xuICAgICAgICBwYXJzZVR5cGUuY29udGVudHMgPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gICAgICB9XG4gICAgICB2YWx1ZXNBcnJheS5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICB2YWx1ZXNBcnJheS5wdXNoKHBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlKHBhcnNlVHlwZSkpO1xuICAgICAgcGF0dGVybnNBcnJheS5wdXNoKGAkJHtpbmRleH06bmFtZSAkJHtpbmRleCArIDF9OnJhd2ApO1xuICAgICAgaWYgKGZpZWxkTmFtZSA9PT0gJ29iamVjdElkJykge1xuICAgICAgICBwYXR0ZXJuc0FycmF5LnB1c2goYFBSSU1BUlkgS0VZICgkJHtpbmRleH06bmFtZSlgKVxuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDI7XG4gICAgfSk7XG4gICAgY29uc3QgcXMgPSBgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJDE6bmFtZSAoJHtwYXR0ZXJuc0FycmF5LmpvaW4oKX0pYDtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAuLi52YWx1ZXNBcnJheV07XG5cbiAgICByZXR1cm4gY29ubi50YXNrKCdjcmVhdGUtdGFibGUnLCBmdW5jdGlvbiAqICh0KSB7XG4gICAgICB0cnkge1xuICAgICAgICB5aWVsZCBzZWxmLl9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzKHQpO1xuICAgICAgICB5aWVsZCB0Lm5vbmUocXMsIHZhbHVlcyk7XG4gICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBFTFNFOiBUYWJsZSBhbHJlYWR5IGV4aXN0cywgbXVzdCBoYXZlIGJlZW4gY3JlYXRlZCBieSBhIGRpZmZlcmVudCByZXF1ZXN0LiBJZ25vcmUgdGhlIGVycm9yLlxuICAgICAgfVxuICAgICAgeWllbGQgdC50eCgnY3JlYXRlLXRhYmxlLXR4JywgdHggPT4ge1xuICAgICAgICByZXR1cm4gdHguYmF0Y2gocmVsYXRpb25zLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgIHJldHVybiB0eC5ub25lKCdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAkPGpvaW5UYWJsZTpuYW1lPiAoXCJyZWxhdGVkSWRcIiB2YXJDaGFyKDEyMCksIFwib3duaW5nSWRcIiB2YXJDaGFyKDEyMCksIFBSSU1BUlkgS0VZKFwicmVsYXRlZElkXCIsIFwib3duaW5nSWRcIikgKScsIHtqb2luVGFibGU6IGBfSm9pbjoke2ZpZWxkTmFtZX06JHtjbGFzc05hbWV9YH0pO1xuICAgICAgICB9KSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHNjaGVtYVVwZ3JhZGUoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgY29ubjogYW55KSB7XG4gICAgZGVidWcoJ3NjaGVtYVVwZ3JhZGUnLCB7IGNsYXNzTmFtZSwgc2NoZW1hIH0pO1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgIHJldHVybiBjb25uLnR4KCdzY2hlbWEtdXBncmFkZScsIGZ1bmN0aW9uICogKHQpIHtcbiAgICAgIGNvbnN0IGNvbHVtbnMgPSB5aWVsZCB0Lm1hcCgnU0VMRUNUIGNvbHVtbl9uYW1lIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLmNvbHVtbnMgV0hFUkUgdGFibGVfbmFtZSA9ICQ8Y2xhc3NOYW1lPicsIHsgY2xhc3NOYW1lIH0sIGEgPT4gYS5jb2x1bW5fbmFtZSk7XG4gICAgICBjb25zdCBuZXdDb2x1bW5zID0gT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcylcbiAgICAgICAgLmZpbHRlcihpdGVtID0+IGNvbHVtbnMuaW5kZXhPZihpdGVtKSA9PT0gLTEpXG4gICAgICAgIC5tYXAoZmllbGROYW1lID0+IHNlbGYuYWRkRmllbGRJZk5vdEV4aXN0cyhjbGFzc05hbWUsIGZpZWxkTmFtZSwgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLCB0KSk7XG5cbiAgICAgIHlpZWxkIHQuYmF0Y2gobmV3Q29sdW1ucyk7XG4gICAgfSk7XG4gIH1cblxuICBhZGRGaWVsZElmTm90RXhpc3RzKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZywgdHlwZTogYW55LCBjb25uOiBhbnkpIHtcbiAgICAvLyBUT0RPOiBNdXN0IGJlIHJldmlzZWQgZm9yIGludmFsaWQgbG9naWMuLi5cbiAgICBkZWJ1ZygnYWRkRmllbGRJZk5vdEV4aXN0cycsIHtjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZX0pO1xuICAgIGNvbm4gPSBjb25uIHx8IHRoaXMuX2NsaWVudDtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICByZXR1cm4gY29ubi50eCgnYWRkLWZpZWxkLWlmLW5vdC1leGlzdHMnLCBmdW5jdGlvbiAqICh0KSB7XG4gICAgICBpZiAodHlwZS50eXBlICE9PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgeWllbGQgdC5ub25lKCdBTFRFUiBUQUJMRSAkPGNsYXNzTmFtZTpuYW1lPiBBREQgQ09MVU1OICQ8ZmllbGROYW1lOm5hbWU+ICQ8cG9zdGdyZXNUeXBlOnJhdz4nLCB7XG4gICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICBmaWVsZE5hbWUsXG4gICAgICAgICAgICBwb3N0Z3Jlc1R5cGU6IHBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlKHR5cGUpXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4geWllbGQgc2VsZi5jcmVhdGVDbGFzcyhjbGFzc05hbWUsIHtmaWVsZHM6IHtbZmllbGROYW1lXTogdHlwZX19LCB0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgIT09IFBvc3RncmVzRHVwbGljYXRlQ29sdW1uRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb2x1bW4gYWxyZWFkeSBleGlzdHMsIGNyZWF0ZWQgYnkgb3RoZXIgcmVxdWVzdC4gQ2Fycnkgb24gdG8gc2VlIGlmIGl0J3MgdGhlIHJpZ2h0IHR5cGUuXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHlpZWxkIHQubm9uZSgnQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJDxqb2luVGFibGU6bmFtZT4gKFwicmVsYXRlZElkXCIgdmFyQ2hhcigxMjApLCBcIm93bmluZ0lkXCIgdmFyQ2hhcigxMjApLCBQUklNQVJZIEtFWShcInJlbGF0ZWRJZFwiLCBcIm93bmluZ0lkXCIpICknLCB7am9pblRhYmxlOiBgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWB9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0ID0geWllbGQgdC5hbnkoJ1NFTEVDVCBcInNjaGVtYVwiIEZST00gXCJfU0NIRU1BXCIgV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQ8Y2xhc3NOYW1lPiBhbmQgKFwic2NoZW1hXCI6Ompzb24tPlxcJ2ZpZWxkc1xcJy0+JDxmaWVsZE5hbWU+KSBpcyBub3QgbnVsbCcsIHtjbGFzc05hbWUsIGZpZWxkTmFtZX0pO1xuXG4gICAgICBpZiAocmVzdWx0WzBdKSB7XG4gICAgICAgIHRocm93ICdBdHRlbXB0ZWQgdG8gYWRkIGEgZmllbGQgdGhhdCBhbHJlYWR5IGV4aXN0cyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBwYXRoID0gYHtmaWVsZHMsJHtmaWVsZE5hbWV9fWA7XG4gICAgICAgIHlpZWxkIHQubm9uZSgnVVBEQVRFIFwiX1NDSEVNQVwiIFNFVCBcInNjaGVtYVwiPWpzb25iX3NldChcInNjaGVtYVwiLCAkPHBhdGg+LCAkPHR5cGU+KSAgV0hFUkUgXCJjbGFzc05hbWVcIj0kPGNsYXNzTmFtZT4nLCB7cGF0aCwgdHlwZSwgY2xhc3NOYW1lfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBEcm9wcyBhIGNvbGxlY3Rpb24uIFJlc29sdmVzIHdpdGggdHJ1ZSBpZiBpdCB3YXMgYSBQYXJzZSBTY2hlbWEgKGVnLiBfVXNlciwgQ3VzdG9tLCBldGMuKVxuICAvLyBhbmQgcmVzb2x2ZXMgd2l0aCBmYWxzZSBpZiBpdCB3YXNuJ3QgKGVnLiBhIGpvaW4gdGFibGUpLiBSZWplY3RzIGlmIGRlbGV0aW9uIHdhcyBpbXBvc3NpYmxlLlxuICBkZWxldGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBbXG4gICAgICB7cXVlcnk6IGBEUk9QIFRBQkxFIElGIEVYSVNUUyAkMTpuYW1lYCwgdmFsdWVzOiBbY2xhc3NOYW1lXX0sXG4gICAgICB7cXVlcnk6IGBERUxFVEUgRlJPTSBcIl9TQ0hFTUFcIiBXSEVSRSBcImNsYXNzTmFtZVwiID0gJDFgLCB2YWx1ZXM6IFtjbGFzc05hbWVdfVxuICAgIF07XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC50eCh0ID0+IHQubm9uZSh0aGlzLl9wZ3AuaGVscGVycy5jb25jYXQob3BlcmF0aW9ucykpKVxuICAgICAgLnRoZW4oKCkgPT4gY2xhc3NOYW1lLmluZGV4T2YoJ19Kb2luOicpICE9IDApOyAvLyByZXNvbHZlcyB3aXRoIGZhbHNlIHdoZW4gX0pvaW4gdGFibGVcbiAgfVxuXG4gIC8vIERlbGV0ZSBhbGwgZGF0YSBrbm93biB0byB0aGlzIGFkYXB0ZXIuIFVzZWQgZm9yIHRlc3RpbmcuXG4gIGRlbGV0ZUFsbENsYXNzZXMoKSB7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgaGVscGVycyA9IHRoaXMuX3BncC5oZWxwZXJzO1xuICAgIGRlYnVnKCdkZWxldGVBbGxDbGFzc2VzJyk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2xpZW50LnRhc2soJ2RlbGV0ZS1hbGwtY2xhc3NlcycsIGZ1bmN0aW9uICogKHQpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSB5aWVsZCB0LmFueSgnU0VMRUNUICogRlJPTSBcIl9TQ0hFTUFcIicpO1xuICAgICAgICBjb25zdCBqb2lucyA9IHJlc3VsdHMucmVkdWNlKChsaXN0OiBBcnJheTxzdHJpbmc+LCBzY2hlbWE6IGFueSkgPT4ge1xuICAgICAgICAgIHJldHVybiBsaXN0LmNvbmNhdChqb2luVGFibGVzRm9yU2NoZW1hKHNjaGVtYS5zY2hlbWEpKTtcbiAgICAgICAgfSwgW10pO1xuICAgICAgICBjb25zdCBjbGFzc2VzID0gWydfU0NIRU1BJywgJ19QdXNoU3RhdHVzJywgJ19Kb2JTdGF0dXMnLCAnX0pvYlNjaGVkdWxlJywgJ19Ib29rcycsICdfR2xvYmFsQ29uZmlnJywgJ19BdWRpZW5jZScsIC4uLnJlc3VsdHMubWFwKHJlc3VsdCA9PiByZXN1bHQuY2xhc3NOYW1lKSwgLi4uam9pbnNdO1xuICAgICAgICBjb25zdCBxdWVyaWVzID0gY2xhc3Nlcy5tYXAoY2xhc3NOYW1lID0+ICh7cXVlcnk6ICdEUk9QIFRBQkxFIElGIEVYSVNUUyAkPGNsYXNzTmFtZTpuYW1lPicsIHZhbHVlczoge2NsYXNzTmFtZX19KSk7XG4gICAgICAgIHlpZWxkIHQudHgodHggPT4gdHgubm9uZShoZWxwZXJzLmNvbmNhdChxdWVyaWVzKSkpO1xuICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm8gX1NDSEVNQSBjb2xsZWN0aW9uLiBEb24ndCBkZWxldGUgYW55dGhpbmcuXG4gICAgICB9XG4gICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgZGVidWcoYGRlbGV0ZUFsbENsYXNzZXMgZG9uZSBpbiAke25ldyBEYXRlKCkuZ2V0VGltZSgpIC0gbm93fWApO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBSZW1vdmUgdGhlIGNvbHVtbiBhbmQgYWxsIHRoZSBkYXRhLiBGb3IgUmVsYXRpb25zLCB0aGUgX0pvaW4gY29sbGVjdGlvbiBpcyBoYW5kbGVkXG4gIC8vIHNwZWNpYWxseSwgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBkZWxldGUgX0pvaW4gY29sdW1ucy4gSXQgc2hvdWxkLCBob3dldmVyLCBpbmRpY2F0ZVxuICAvLyB0aGF0IHRoZSByZWxhdGlvbiBmaWVsZHMgZG9lcyBub3QgZXhpc3QgYW55bW9yZS4gSW4gbW9uZ28sIHRoaXMgbWVhbnMgcmVtb3ZpbmcgaXQgZnJvbVxuICAvLyB0aGUgX1NDSEVNQSBjb2xsZWN0aW9uLiAgVGhlcmUgc2hvdWxkIGJlIG5vIGFjdHVhbCBkYXRhIGluIHRoZSBjb2xsZWN0aW9uIHVuZGVyIHRoZSBzYW1lIG5hbWVcbiAgLy8gYXMgdGhlIHJlbGF0aW9uIGNvbHVtbiwgc28gaXQncyBmaW5lIHRvIGF0dGVtcHQgdG8gZGVsZXRlIGl0LiBJZiB0aGUgZmllbGRzIGxpc3RlZCB0byBiZVxuICAvLyBkZWxldGVkIGRvIG5vdCBleGlzdCwgdGhpcyBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIHN1Y2Nlc3NmdWxseSBhbnl3YXlzLiBDaGVja2luZyBmb3JcbiAgLy8gYXR0ZW1wdHMgdG8gZGVsZXRlIG5vbi1leGlzdGVudCBmaWVsZHMgaXMgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIFBhcnNlIFNlcnZlci5cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBvYmxpZ2F0ZWQgdG8gZGVsZXRlIGZpZWxkcyBhdG9taWNhbGx5LiBJdCBpcyBnaXZlbiB0aGUgZmllbGRcbiAgLy8gbmFtZXMgaW4gYSBsaXN0IHNvIHRoYXQgZGF0YWJhc2VzIHRoYXQgYXJlIGNhcGFibGUgb2YgZGVsZXRpbmcgZmllbGRzIGF0b21pY2FsbHlcbiAgLy8gbWF5IGRvIHNvLlxuXG4gIC8vIFJldHVybnMgYSBQcm9taXNlLlxuICBkZWxldGVGaWVsZHMoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgZmllbGROYW1lczogc3RyaW5nW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBkZWJ1ZygnZGVsZXRlRmllbGRzJywgY2xhc3NOYW1lLCBmaWVsZE5hbWVzKTtcbiAgICBmaWVsZE5hbWVzID0gZmllbGROYW1lcy5yZWR1Y2UoKGxpc3Q6IEFycmF5PHN0cmluZz4sIGZpZWxkTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBmaWVsZCA9IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXVxuICAgICAgaWYgKGZpZWxkLnR5cGUgIT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgbGlzdC5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICB9XG4gICAgICBkZWxldGUgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3QgdmFsdWVzID0gW2NsYXNzTmFtZSwgLi4uZmllbGROYW1lc107XG4gICAgY29uc3QgY29sdW1ucyA9IGZpZWxkTmFtZXMubWFwKChuYW1lLCBpZHgpID0+IHtcbiAgICAgIHJldHVybiBgJCR7aWR4ICsgMn06bmFtZWA7XG4gICAgfSkuam9pbignLCBEUk9QIENPTFVNTicpO1xuXG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC50eCgnZGVsZXRlLWZpZWxkcycsIGZ1bmN0aW9uICogKHQpIHtcbiAgICAgIHlpZWxkIHQubm9uZSgnVVBEQVRFIFwiX1NDSEVNQVwiIFNFVCBcInNjaGVtYVwiPSQ8c2NoZW1hPiBXSEVSRSBcImNsYXNzTmFtZVwiPSQ8Y2xhc3NOYW1lPicsIHtzY2hlbWEsIGNsYXNzTmFtZX0pO1xuICAgICAgaWYgKHZhbHVlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgIHlpZWxkIHQubm9uZShgQUxURVIgVEFCTEUgJDE6bmFtZSBEUk9QIENPTFVNTiAke2NvbHVtbnN9YCwgdmFsdWVzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybiBhIHByb21pc2UgZm9yIGFsbCBzY2hlbWFzIGtub3duIHRvIHRoaXMgYWRhcHRlciwgaW4gUGFyc2UgZm9ybWF0LiBJbiBjYXNlIHRoZVxuICAvLyBzY2hlbWFzIGNhbm5vdCBiZSByZXRyaWV2ZWQsIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVqZWN0cy4gUmVxdWlyZW1lbnRzIGZvciB0aGVcbiAgLy8gcmVqZWN0aW9uIHJlYXNvbiBhcmUgVEJELlxuICBnZXRBbGxDbGFzc2VzKCkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQudGFzaygnZ2V0LWFsbC1jbGFzc2VzJywgZnVuY3Rpb24gKiAodCkge1xuICAgICAgeWllbGQgc2VsZi5fZW5zdXJlU2NoZW1hQ29sbGVjdGlvbkV4aXN0cyh0KTtcbiAgICAgIHJldHVybiB5aWVsZCB0Lm1hcCgnU0VMRUNUICogRlJPTSBcIl9TQ0hFTUFcIicsIG51bGwsIHJvdyA9PiB0b1BhcnNlU2NoZW1hKHsgY2xhc3NOYW1lOiByb3cuY2xhc3NOYW1lLCAuLi5yb3cuc2NoZW1hIH0pKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybiBhIHByb21pc2UgZm9yIHRoZSBzY2hlbWEgd2l0aCB0aGUgZ2l2ZW4gbmFtZSwgaW4gUGFyc2UgZm9ybWF0LiBJZlxuICAvLyB0aGlzIGFkYXB0ZXIgZG9lc24ndCBrbm93IGFib3V0IHRoZSBzY2hlbWEsIHJldHVybiBhIHByb21pc2UgdGhhdCByZWplY3RzIHdpdGhcbiAgLy8gdW5kZWZpbmVkIGFzIHRoZSByZWFzb24uXG4gIGdldENsYXNzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgZGVidWcoJ2dldENsYXNzJywgY2xhc3NOYW1lKTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50LmFueSgnU0VMRUNUICogRlJPTSBcIl9TQ0hFTUFcIiBXSEVSRSBcImNsYXNzTmFtZVwiPSQ8Y2xhc3NOYW1lPicsIHsgY2xhc3NOYW1lIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0WzBdLnNjaGVtYTtcbiAgICAgIH0pXG4gICAgICAudGhlbih0b1BhcnNlU2NoZW1hKTtcbiAgfVxuXG4gIC8vIFRPRE86IHJlbW92ZSB0aGUgbW9uZ28gZm9ybWF0IGRlcGVuZGVuY3kgaW4gdGhlIHJldHVybiB2YWx1ZVxuICBjcmVhdGVPYmplY3QoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgb2JqZWN0OiBhbnkpIHtcbiAgICBkZWJ1ZygnY3JlYXRlT2JqZWN0JywgY2xhc3NOYW1lLCBvYmplY3QpO1xuICAgIGxldCBjb2x1bW5zQXJyYXkgPSBbXTtcbiAgICBjb25zdCB2YWx1ZXNBcnJheSA9IFtdO1xuICAgIHNjaGVtYSA9IHRvUG9zdGdyZXNTY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBnZW9Qb2ludHMgPSB7fTtcblxuICAgIG9iamVjdCA9IGhhbmRsZURvdEZpZWxkcyhvYmplY3QpO1xuXG4gICAgdmFsaWRhdGVLZXlzKG9iamVjdCk7XG5cbiAgICBPYmplY3Qua2V5cyhvYmplY3QpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgYXV0aERhdGFNYXRjaCA9IGZpZWxkTmFtZS5tYXRjaCgvXl9hdXRoX2RhdGFfKFthLXpBLVowLTlfXSspJC8pO1xuICAgICAgaWYgKGF1dGhEYXRhTWF0Y2gpIHtcbiAgICAgICAgdmFyIHByb3ZpZGVyID0gYXV0aERhdGFNYXRjaFsxXTtcbiAgICAgICAgb2JqZWN0WydhdXRoRGF0YSddID0gb2JqZWN0WydhdXRoRGF0YSddIHx8IHt9O1xuICAgICAgICBvYmplY3RbJ2F1dGhEYXRhJ11bcHJvdmlkZXJdID0gb2JqZWN0W2ZpZWxkTmFtZV07XG4gICAgICAgIGRlbGV0ZSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgZmllbGROYW1lID0gJ2F1dGhEYXRhJztcbiAgICAgIH1cblxuICAgICAgY29sdW1uc0FycmF5LnB1c2goZmllbGROYW1lKTtcbiAgICAgIGlmICghc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICBpZiAoZmllbGROYW1lID09PSAnX2VtYWlsX3ZlcmlmeV90b2tlbicgfHxcbiAgICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19mYWlsZWRfbG9naW5fY291bnQnIHx8XG4gICAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfcGVyaXNoYWJsZV90b2tlbicgfHxcbiAgICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19wYXNzd29yZF9oaXN0b3J5Jyl7XG4gICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmllbGROYW1lID09PSAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0Jykge1xuICAgICAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSkge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXS5pc28pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG51bGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWVsZE5hbWUgPT09ICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnIHx8XG4gICAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JyB8fFxuICAgICAgICAgICAgZmllbGROYW1lID09PSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnKSB7XG4gICAgICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdKSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLmlzbyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gobnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHN3aXRjaCAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUpIHtcbiAgICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLmlzbyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChudWxsKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1BvaW50ZXInOlxuICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLm9iamVjdElkKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdBcnJheSc6XG4gICAgICAgIGlmIChbJ19ycGVybScsICdfd3Blcm0nXS5pbmRleE9mKGZpZWxkTmFtZSkgPj0gMCkge1xuICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2goSlNPTi5zdHJpbmdpZnkob2JqZWN0W2ZpZWxkTmFtZV0pKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ09iamVjdCc6XG4gICAgICBjYXNlICdCeXRlcyc6XG4gICAgICBjYXNlICdTdHJpbmcnOlxuICAgICAgY2FzZSAnTnVtYmVyJzpcbiAgICAgIGNhc2UgJ0Jvb2xlYW4nOlxuICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdGaWxlJzpcbiAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXS5uYW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdQb2x5Z29uJzoge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbnZlcnRQb2x5Z29uVG9TUUwob2JqZWN0W2ZpZWxkTmFtZV0uY29vcmRpbmF0ZXMpO1xuICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdHZW9Qb2ludCc6XG4gICAgICAgIC8vIHBvcCB0aGUgcG9pbnQgYW5kIHByb2Nlc3MgbGF0ZXJcbiAgICAgICAgZ2VvUG9pbnRzW2ZpZWxkTmFtZV0gPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgY29sdW1uc0FycmF5LnBvcCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IGBUeXBlICR7c2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGV9IG5vdCBzdXBwb3J0ZWQgeWV0YDtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbHVtbnNBcnJheSA9IGNvbHVtbnNBcnJheS5jb25jYXQoT2JqZWN0LmtleXMoZ2VvUG9pbnRzKSk7XG4gICAgY29uc3QgaW5pdGlhbFZhbHVlcyA9IHZhbHVlc0FycmF5Lm1hcCgodmFsLCBpbmRleCkgPT4ge1xuICAgICAgbGV0IHRlcm1pbmF0aW9uID0gJyc7XG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSBjb2x1bW5zQXJyYXlbaW5kZXhdO1xuICAgICAgaWYgKFsnX3JwZXJtJywnX3dwZXJtJ10uaW5kZXhPZihmaWVsZE5hbWUpID49IDApIHtcbiAgICAgICAgdGVybWluYXRpb24gPSAnOjp0ZXh0W10nO1xuICAgICAgfSBlbHNlIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdBcnJheScpIHtcbiAgICAgICAgdGVybWluYXRpb24gPSAnOjpqc29uYic7XG4gICAgICB9XG4gICAgICByZXR1cm4gYCQke2luZGV4ICsgMiArIGNvbHVtbnNBcnJheS5sZW5ndGh9JHt0ZXJtaW5hdGlvbn1gO1xuICAgIH0pO1xuICAgIGNvbnN0IGdlb1BvaW50c0luamVjdHMgPSBPYmplY3Qua2V5cyhnZW9Qb2ludHMpLm1hcCgoa2V5KSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGdlb1BvaW50c1trZXldO1xuICAgICAgdmFsdWVzQXJyYXkucHVzaCh2YWx1ZS5sb25naXR1ZGUsIHZhbHVlLmxhdGl0dWRlKTtcbiAgICAgIGNvbnN0IGwgPSB2YWx1ZXNBcnJheS5sZW5ndGggKyBjb2x1bW5zQXJyYXkubGVuZ3RoO1xuICAgICAgcmV0dXJuIGBQT0lOVCgkJHtsfSwgJCR7bCArIDF9KWA7XG4gICAgfSk7XG5cbiAgICBjb25zdCBjb2x1bW5zUGF0dGVybiA9IGNvbHVtbnNBcnJheS5tYXAoKGNvbCwgaW5kZXgpID0+IGAkJHtpbmRleCArIDJ9Om5hbWVgKS5qb2luKCk7XG4gICAgY29uc3QgdmFsdWVzUGF0dGVybiA9IGluaXRpYWxWYWx1ZXMuY29uY2F0KGdlb1BvaW50c0luamVjdHMpLmpvaW4oKVxuXG4gICAgY29uc3QgcXMgPSBgSU5TRVJUIElOVE8gJDE6bmFtZSAoJHtjb2x1bW5zUGF0dGVybn0pIFZBTFVFUyAoJHt2YWx1ZXNQYXR0ZXJufSlgXG4gICAgY29uc3QgdmFsdWVzID0gW2NsYXNzTmFtZSwgLi4uY29sdW1uc0FycmF5LCAuLi52YWx1ZXNBcnJheV1cbiAgICBkZWJ1ZyhxcywgdmFsdWVzKTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50Lm5vbmUocXMsIHZhbHVlcylcbiAgICAgIC50aGVuKCgpID0+ICh7IG9wczogW29iamVjdF0gfSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnKTtcbiAgICAgICAgICBlcnIudW5kZXJseWluZ0Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBlcnJvci5jb25zdHJhaW50Lm1hdGNoKC91bmlxdWVfKFthLXpBLVpdKykvKTtcbiAgICAgICAgICAgIGlmIChtYXRjaGVzICYmIEFycmF5LmlzQXJyYXkobWF0Y2hlcykpIHtcbiAgICAgICAgICAgICAgZXJyLnVzZXJJbmZvID0geyBkdXBsaWNhdGVkX2ZpZWxkOiBtYXRjaGVzWzFdIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGVycm9yID0gZXJyO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBSZW1vdmUgYWxsIG9iamVjdHMgdGhhdCBtYXRjaCB0aGUgZ2l2ZW4gUGFyc2UgUXVlcnkuXG4gIC8vIElmIG5vIG9iamVjdHMgbWF0Y2gsIHJlamVjdCB3aXRoIE9CSkVDVF9OT1RfRk9VTkQuIElmIG9iamVjdHMgYXJlIGZvdW5kIGFuZCBkZWxldGVkLCByZXNvbHZlIHdpdGggdW5kZWZpbmVkLlxuICAvLyBJZiB0aGVyZSBpcyBzb21lIG90aGVyIGVycm9yLCByZWplY3Qgd2l0aCBJTlRFUk5BTF9TRVJWRVJfRVJST1IuXG4gIGRlbGV0ZU9iamVjdHNCeVF1ZXJ5KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUpIHtcbiAgICBkZWJ1ZygnZGVsZXRlT2JqZWN0c0J5UXVlcnknLCBjbGFzc05hbWUsIHF1ZXJ5KTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBjb25zdCBpbmRleCA9IDI7XG4gICAgY29uc3Qgd2hlcmUgPSBidWlsZFdoZXJlQ2xhdXNlKHsgc2NoZW1hLCBpbmRleCwgcXVlcnkgfSlcbiAgICB2YWx1ZXMucHVzaCguLi53aGVyZS52YWx1ZXMpO1xuICAgIGlmIChPYmplY3Qua2V5cyhxdWVyeSkubGVuZ3RoID09PSAwKSB7XG4gICAgICB3aGVyZS5wYXR0ZXJuID0gJ1RSVUUnO1xuICAgIH1cbiAgICBjb25zdCBxcyA9IGBXSVRIIGRlbGV0ZWQgQVMgKERFTEVURSBGUk9NICQxOm5hbWUgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufSBSRVRVUk5JTkcgKikgU0VMRUNUIGNvdW50KCopIEZST00gZGVsZXRlZGA7XG4gICAgZGVidWcocXMsIHZhbHVlcyk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5vbmUocXMsIHZhbHVlcyAsIGEgPT4gK2EuY291bnQpXG4gICAgICAudGhlbihjb3VudCA9PiB7XG4gICAgICAgIGlmIChjb3VudCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnT2JqZWN0IG5vdCBmb3VuZC4nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gY291bnQ7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRUxTRTogRG9uJ3QgZGVsZXRlIGFueXRoaW5nIGlmIGRvZXNuJ3QgZXhpc3RcbiAgICAgIH0pO1xuICB9XG4gIC8vIFJldHVybiB2YWx1ZSBub3QgY3VycmVudGx5IHdlbGwgc3BlY2lmaWVkLlxuICBmaW5kT25lQW5kVXBkYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIHVwZGF0ZTogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICBkZWJ1ZygnZmluZE9uZUFuZFVwZGF0ZScsIGNsYXNzTmFtZSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lLCBzY2hlbWEsIHF1ZXJ5LCB1cGRhdGUpXG4gICAgICAudGhlbigodmFsKSA9PiB2YWxbMF0pO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgdXBkYXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpOiBQcm9taXNlPFthbnldPiB7XG4gICAgZGVidWcoJ3VwZGF0ZU9iamVjdHNCeVF1ZXJ5JywgY2xhc3NOYW1lLCBxdWVyeSwgdXBkYXRlKTtcbiAgICBjb25zdCB1cGRhdGVQYXR0ZXJucyA9IFtdO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtjbGFzc05hbWVdXG4gICAgbGV0IGluZGV4ID0gMjtcbiAgICBzY2hlbWEgPSB0b1Bvc3RncmVzU2NoZW1hKHNjaGVtYSk7XG5cbiAgICBjb25zdCBvcmlnaW5hbFVwZGF0ZSA9IHsuLi51cGRhdGV9O1xuICAgIHVwZGF0ZSA9IGhhbmRsZURvdEZpZWxkcyh1cGRhdGUpO1xuICAgIC8vIFJlc29sdmUgYXV0aERhdGEgZmlyc3QsXG4gICAgLy8gU28gd2UgZG9uJ3QgZW5kIHVwIHdpdGggbXVsdGlwbGUga2V5IHVwZGF0ZXNcbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiB1cGRhdGUpIHtcbiAgICAgIGNvbnN0IGF1dGhEYXRhTWF0Y2ggPSBmaWVsZE5hbWUubWF0Y2goL15fYXV0aF9kYXRhXyhbYS16QS1aMC05X10rKSQvKTtcbiAgICAgIGlmIChhdXRoRGF0YU1hdGNoKSB7XG4gICAgICAgIHZhciBwcm92aWRlciA9IGF1dGhEYXRhTWF0Y2hbMV07XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdXBkYXRlW2ZpZWxkTmFtZV07XG4gICAgICAgIGRlbGV0ZSB1cGRhdGVbZmllbGROYW1lXTtcbiAgICAgICAgdXBkYXRlWydhdXRoRGF0YSddID0gdXBkYXRlWydhdXRoRGF0YSddIHx8IHt9O1xuICAgICAgICB1cGRhdGVbJ2F1dGhEYXRhJ11bcHJvdmlkZXJdID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gdXBkYXRlKSB7XG4gICAgICBjb25zdCBmaWVsZFZhbHVlID0gdXBkYXRlW2ZpZWxkTmFtZV07XG4gICAgICBpZiAoZmllbGRWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9IE5VTExgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGROYW1lID09ICdhdXRoRGF0YScpIHtcbiAgICAgICAgLy8gVGhpcyByZWN1cnNpdmVseSBzZXRzIHRoZSBqc29uX29iamVjdFxuICAgICAgICAvLyBPbmx5IDEgbGV2ZWwgZGVlcFxuICAgICAgICBjb25zdCBnZW5lcmF0ZSA9IChqc29uYjogc3RyaW5nLCBrZXk6IHN0cmluZywgdmFsdWU6IGFueSkgPT4ge1xuICAgICAgICAgIHJldHVybiBganNvbl9vYmplY3Rfc2V0X2tleShDT0FMRVNDRSgke2pzb25ifSwgJ3t9Jzo6anNvbmIpLCAke2tleX0sICR7dmFsdWV9KTo6anNvbmJgO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxhc3RLZXkgPSBgJCR7aW5kZXh9Om5hbWVgO1xuICAgICAgICBjb25zdCBmaWVsZE5hbWVJbmRleCA9IGluZGV4O1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICBjb25zdCB1cGRhdGUgPSBPYmplY3Qua2V5cyhmaWVsZFZhbHVlKS5yZWR1Y2UoKGxhc3RLZXk6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICBjb25zdCBzdHIgPSBnZW5lcmF0ZShsYXN0S2V5LCBgJCR7aW5kZXh9Ojp0ZXh0YCwgYCQke2luZGV4ICsgMX06Ompzb25iYClcbiAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgIGxldCB2YWx1ZSA9IGZpZWxkVmFsdWVba2V5XTtcbiAgICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICAgICAgICB2YWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2YWx1ZSA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICB2YWx1ZXMucHVzaChrZXksIHZhbHVlKTtcbiAgICAgICAgICByZXR1cm4gc3RyO1xuICAgICAgICB9LCBsYXN0S2V5KTtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7ZmllbGROYW1lSW5kZXh9Om5hbWUgPSAke3VwZGF0ZX1gKTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS5fX29wID09PSAnSW5jcmVtZW50Jykge1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9IENPQUxFU0NFKCQke2luZGV4fTpuYW1lLCAwKSArICQke2luZGV4ICsgMX1gKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmFtb3VudCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ0FkZCcpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSBhcnJheV9hZGQoQ09BTEVTQ0UoJCR7aW5kZXh9Om5hbWUsICdbXSc6Ompzb25iKSwgJCR7aW5kZXggKyAxfTo6anNvbmIpYCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS5vYmplY3RzKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YClcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBudWxsKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS5fX29wID09PSAnUmVtb3ZlJykge1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9IGFycmF5X3JlbW92ZShDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ1tdJzo6anNvbmIpLCAkJHtpbmRleCArIDF9Ojpqc29uYilgKVxuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUub2JqZWN0cykpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fb3AgPT09ICdBZGRVbmlxdWUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gYXJyYXlfYWRkX3VuaXF1ZShDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ1tdJzo6anNvbmIpLCAkJHtpbmRleCArIDF9Ojpqc29uYilgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlLm9iamVjdHMpKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGROYW1lID09PSAndXBkYXRlZEF0JykgeyAvL1RPRE86IHN0b3Agc3BlY2lhbCBjYXNpbmcgdGhpcy4gSXQgc2hvdWxkIGNoZWNrIGZvciBfX3R5cGUgPT09ICdEYXRlJyBhbmQgdXNlIC5pc29cbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YClcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUub2JqZWN0SWQpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ0RhdGUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHRvUG9zdGdyZXNWYWx1ZShmaWVsZFZhbHVlKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ0ZpbGUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHRvUG9zdGdyZXNWYWx1ZShmaWVsZFZhbHVlKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnR2VvUG9pbnQnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggKyAyfSlgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmxvbmdpdHVkZSwgZmllbGRWYWx1ZS5sYXRpdHVkZSk7XG4gICAgICAgIGluZGV4ICs9IDM7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0UG9seWdvblRvU1FMKGZpZWxkVmFsdWUuY29vcmRpbmF0ZXMpO1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCB2YWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ29iamVjdCdcbiAgICAgICAgICAgICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdXG4gICAgICAgICAgICAgICAgICAgICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnT2JqZWN0Jykge1xuICAgICAgICAvLyBHYXRoZXIga2V5cyB0byBpbmNyZW1lbnRcbiAgICAgICAgY29uc3Qga2V5c1RvSW5jcmVtZW50ID0gT2JqZWN0LmtleXMob3JpZ2luYWxVcGRhdGUpLmZpbHRlcihrID0+IHtcbiAgICAgICAgICAvLyBjaG9vc2UgdG9wIGxldmVsIGZpZWxkcyB0aGF0IGhhdmUgYSBkZWxldGUgb3BlcmF0aW9uIHNldFxuICAgICAgICAgIC8vIE5vdGUgdGhhdCBPYmplY3Qua2V5cyBpcyBpdGVyYXRpbmcgb3ZlciB0aGUgKipvcmlnaW5hbCoqIHVwZGF0ZSBvYmplY3RcbiAgICAgICAgICAvLyBhbmQgdGhhdCBzb21lIG9mIHRoZSBrZXlzIG9mIHRoZSBvcmlnaW5hbCB1cGRhdGUgY291bGQgYmUgbnVsbCBvciB1bmRlZmluZWQ6XG4gICAgICAgICAgLy8gKFNlZSB0aGUgYWJvdmUgY2hlY2sgYGlmIChmaWVsZFZhbHVlID09PSBudWxsIHx8IHR5cGVvZiBmaWVsZFZhbHVlID09IFwidW5kZWZpbmVkXCIpYClcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IG9yaWdpbmFsVXBkYXRlW2tdO1xuICAgICAgICAgIHJldHVybiB2YWx1ZSAmJiB2YWx1ZS5fX29wID09PSAnSW5jcmVtZW50JyAmJiBrLnNwbGl0KCcuJykubGVuZ3RoID09PSAyICYmIGsuc3BsaXQoXCIuXCIpWzBdID09PSBmaWVsZE5hbWU7XG4gICAgICAgIH0pLm1hcChrID0+IGsuc3BsaXQoJy4nKVsxXSk7XG5cbiAgICAgICAgbGV0IGluY3JlbWVudFBhdHRlcm5zID0gJyc7XG4gICAgICAgIGlmIChrZXlzVG9JbmNyZW1lbnQubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGluY3JlbWVudFBhdHRlcm5zID0gJyB8fCAnICsga2V5c1RvSW5jcmVtZW50Lm1hcCgoYykgPT4ge1xuICAgICAgICAgICAgY29uc3QgYW1vdW50ID0gZmllbGRWYWx1ZVtjXS5hbW91bnQ7XG4gICAgICAgICAgICByZXR1cm4gYENPTkNBVCgne1wiJHtjfVwiOicsIENPQUxFU0NFKCQke2luZGV4fTpuYW1lLT4+JyR7Y30nLCcwJyk6OmludCArICR7YW1vdW50fSwgJ30nKTo6anNvbmJgO1xuICAgICAgICAgIH0pLmpvaW4oJyB8fCAnKTtcbiAgICAgICAgICAvLyBTdHJpcCB0aGUga2V5c1xuICAgICAgICAgIGtleXNUb0luY3JlbWVudC5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgICAgIGRlbGV0ZSBmaWVsZFZhbHVlW2tleV07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBrZXlzVG9EZWxldGU6IEFycmF5PHN0cmluZz4gPSBPYmplY3Qua2V5cyhvcmlnaW5hbFVwZGF0ZSkuZmlsdGVyKGsgPT4ge1xuICAgICAgICAgIC8vIGNob29zZSB0b3AgbGV2ZWwgZmllbGRzIHRoYXQgaGF2ZSBhIGRlbGV0ZSBvcGVyYXRpb24gc2V0LlxuICAgICAgICAgIGNvbnN0IHZhbHVlID0gb3JpZ2luYWxVcGRhdGVba107XG4gICAgICAgICAgcmV0dXJuIHZhbHVlICYmIHZhbHVlLl9fb3AgPT09ICdEZWxldGUnICYmIGsuc3BsaXQoJy4nKS5sZW5ndGggPT09IDIgJiYgay5zcGxpdChcIi5cIilbMF0gPT09IGZpZWxkTmFtZTtcbiAgICAgICAgfSkubWFwKGsgPT4gay5zcGxpdCgnLicpWzFdKTtcblxuICAgICAgICBjb25zdCBkZWxldGVQYXR0ZXJucyA9IGtleXNUb0RlbGV0ZS5yZWR1Y2UoKHA6IHN0cmluZywgYzogc3RyaW5nLCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgICByZXR1cm4gcCArIGAgLSAnJCR7aW5kZXggKyAxICsgaX06dmFsdWUnYDtcbiAgICAgICAgfSwgJycpO1xuXG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gKCd7fSc6Ompzb25iICR7ZGVsZXRlUGF0dGVybnN9ICR7aW5jcmVtZW50UGF0dGVybnN9IHx8ICQke2luZGV4ICsgMSArIGtleXNUb0RlbGV0ZS5sZW5ndGh9Ojpqc29uYiApYCk7XG5cbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCAuLi5rZXlzVG9EZWxldGUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMiArIGtleXNUb0RlbGV0ZS5sZW5ndGg7XG4gICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdXG4gICAgICAgICAgICAgICAgICAgICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnQXJyYXknKSB7XG4gICAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZSA9IHBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSk7XG4gICAgICAgIGlmIChleHBlY3RlZFR5cGUgPT09ICd0ZXh0W10nKSB7XG4gICAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9Ojp0ZXh0W11gKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsZXQgdHlwZSA9ICd0ZXh0JztcbiAgICAgICAgICBmb3IgKGNvbnN0IGVsdCBvZiBmaWVsZFZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsdCA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICB0eXBlID0gJ2pzb24nO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSBhcnJheV90b19qc29uKCQke2luZGV4ICsgMX06OiR7dHlwZX1bXSk6Ompzb25iYCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlYnVnKCdOb3Qgc3VwcG9ydGVkIHVwZGF0ZScsIGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTiwgYFBvc3RncmVzIGRvZXNuJ3Qgc3VwcG9ydCB1cGRhdGUgJHtKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKX0geWV0YCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHdoZXJlID0gYnVpbGRXaGVyZUNsYXVzZSh7IHNjaGVtYSwgaW5kZXgsIHF1ZXJ5IH0pXG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcblxuICAgIGNvbnN0IHdoZXJlQ2xhdXNlID0gd2hlcmUucGF0dGVybi5sZW5ndGggPiAwID8gYFdIRVJFICR7d2hlcmUucGF0dGVybn1gIDogJyc7XG4gICAgY29uc3QgcXMgPSBgVVBEQVRFICQxOm5hbWUgU0VUICR7dXBkYXRlUGF0dGVybnMuam9pbigpfSAke3doZXJlQ2xhdXNlfSBSRVRVUk5JTkcgKmA7XG4gICAgZGVidWcoJ3VwZGF0ZTogJywgcXMsIHZhbHVlcyk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5hbnkocXMsIHZhbHVlcyk7XG4gIH1cblxuICAvLyBIb3BlZnVsbHksIHdlIGNhbiBnZXQgcmlkIG9mIHRoaXMuIEl0J3Mgb25seSB1c2VkIGZvciBjb25maWcgYW5kIGhvb2tzLlxuICB1cHNlcnRPbmVPYmplY3QoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpIHtcbiAgICBkZWJ1ZygndXBzZXJ0T25lT2JqZWN0Jywge2NsYXNzTmFtZSwgcXVlcnksIHVwZGF0ZX0pO1xuICAgIGNvbnN0IGNyZWF0ZVZhbHVlID0gT2JqZWN0LmFzc2lnbih7fSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlT2JqZWN0KGNsYXNzTmFtZSwgc2NoZW1hLCBjcmVhdGVWYWx1ZSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIC8vIGlnbm9yZSBkdXBsaWNhdGUgdmFsdWUgZXJyb3JzIGFzIGl0J3MgdXBzZXJ0XG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5maW5kT25lQW5kVXBkYXRlKGNsYXNzTmFtZSwgc2NoZW1hLCBxdWVyeSwgdXBkYXRlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgZmluZChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzIH06IFF1ZXJ5T3B0aW9ucykge1xuICAgIGRlYnVnKCdmaW5kJywgY2xhc3NOYW1lLCBxdWVyeSwge3NraXAsIGxpbWl0LCBzb3J0LCBrZXlzIH0pO1xuICAgIGNvbnN0IGhhc0xpbWl0ID0gbGltaXQgIT09IHVuZGVmaW5lZDtcbiAgICBjb25zdCBoYXNTa2lwID0gc2tpcCAhPT0gdW5kZWZpbmVkO1xuICAgIGxldCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2UoeyBzY2hlbWEsIHF1ZXJ5LCBpbmRleDogMiB9KVxuICAgIHZhbHVlcy5wdXNoKC4uLndoZXJlLnZhbHVlcyk7XG5cbiAgICBjb25zdCB3aGVyZVBhdHRlcm4gPSB3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgPyBgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufWAgOiAnJztcbiAgICBjb25zdCBsaW1pdFBhdHRlcm4gPSBoYXNMaW1pdCA/IGBMSU1JVCAkJHt2YWx1ZXMubGVuZ3RoICsgMX1gIDogJyc7XG4gICAgaWYgKGhhc0xpbWl0KSB7XG4gICAgICB2YWx1ZXMucHVzaChsaW1pdCk7XG4gICAgfVxuICAgIGNvbnN0IHNraXBQYXR0ZXJuID0gaGFzU2tpcCA/IGBPRkZTRVQgJCR7dmFsdWVzLmxlbmd0aCArIDF9YCA6ICcnO1xuICAgIGlmIChoYXNTa2lwKSB7XG4gICAgICB2YWx1ZXMucHVzaChza2lwKTtcbiAgICB9XG5cbiAgICBsZXQgc29ydFBhdHRlcm4gPSAnJztcbiAgICBpZiAoc29ydCkge1xuICAgICAgY29uc3Qgc29ydENvcHk6IGFueSA9IHNvcnQ7XG4gICAgICBjb25zdCBzb3J0aW5nID0gT2JqZWN0LmtleXMoc29ydCkubWFwKChrZXkpID0+IHtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtS2V5ID0gdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMoa2V5KS5qb2luKCctPicpO1xuICAgICAgICAvLyBVc2luZyAkaWR4IHBhdHRlcm4gZ2l2ZXM6ICBub24taW50ZWdlciBjb25zdGFudCBpbiBPUkRFUiBCWVxuICAgICAgICBpZiAoc29ydENvcHlba2V5XSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBgJHt0cmFuc2Zvcm1LZXl9IEFTQ2A7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGAke3RyYW5zZm9ybUtleX0gREVTQ2A7XG4gICAgICB9KS5qb2luKCk7XG4gICAgICBzb3J0UGF0dGVybiA9IHNvcnQgIT09IHVuZGVmaW5lZCAmJiBPYmplY3Qua2V5cyhzb3J0KS5sZW5ndGggPiAwID8gYE9SREVSIEJZICR7c29ydGluZ31gIDogJyc7XG4gICAgfVxuICAgIGlmICh3aGVyZS5zb3J0cyAmJiBPYmplY3Qua2V5cygod2hlcmUuc29ydHM6IGFueSkpLmxlbmd0aCA+IDApIHtcbiAgICAgIHNvcnRQYXR0ZXJuID0gYE9SREVSIEJZICR7d2hlcmUuc29ydHMuam9pbigpfWA7XG4gICAgfVxuXG4gICAgbGV0IGNvbHVtbnMgPSAnKic7XG4gICAgaWYgKGtleXMpIHtcbiAgICAgIC8vIEV4Y2x1ZGUgZW1wdHkga2V5c1xuICAgICAga2V5cyA9IGtleXMuZmlsdGVyKChrZXkpID0+IHtcbiAgICAgICAgcmV0dXJuIGtleS5sZW5ndGggPiAwO1xuICAgICAgfSk7XG4gICAgICBjb2x1bW5zID0ga2V5cy5tYXAoKGtleSwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKGtleSA9PT0gJyRzY29yZScpIHtcbiAgICAgICAgICByZXR1cm4gYHRzX3JhbmtfY2QodG9fdHN2ZWN0b3IoJCR7Mn0sICQkezN9Om5hbWUpLCB0b190c3F1ZXJ5KCQkezR9LCAkJHs1fSksIDMyKSBhcyBzY29yZWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGAkJHtpbmRleCArIHZhbHVlcy5sZW5ndGggKyAxfTpuYW1lYDtcbiAgICAgIH0pLmpvaW4oKTtcbiAgICAgIHZhbHVlcyA9IHZhbHVlcy5jb25jYXQoa2V5cyk7XG4gICAgfVxuXG4gICAgY29uc3QgcXMgPSBgU0VMRUNUICR7Y29sdW1uc30gRlJPTSAkMTpuYW1lICR7d2hlcmVQYXR0ZXJufSAke3NvcnRQYXR0ZXJufSAke2xpbWl0UGF0dGVybn0gJHtza2lwUGF0dGVybn1gO1xuICAgIGRlYnVnKHFzLCB2YWx1ZXMpO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQuYW55KHFzLCB2YWx1ZXMpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvLyBRdWVyeSBvbiBub24gZXhpc3RpbmcgdGFibGUsIGRvbid0IGNyYXNoXG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc1JlbGF0aW9uRG9lc05vdEV4aXN0RXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW107XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiByZXN1bHRzLm1hcChvYmplY3QgPT4gdGhpcy5wb3N0Z3Jlc09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSkpKTtcbiAgfVxuXG4gIC8vIENvbnZlcnRzIGZyb20gYSBwb3N0Z3Jlcy1mb3JtYXQgb2JqZWN0IHRvIGEgUkVTVC1mb3JtYXQgb2JqZWN0LlxuICAvLyBEb2VzIG5vdCBzdHJpcCBvdXQgYW55dGhpbmcgYmFzZWQgb24gYSBsYWNrIG9mIGF1dGhlbnRpY2F0aW9uLlxuICBwb3N0Z3Jlc09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lOiBzdHJpbmcsIG9iamVjdDogYW55LCBzY2hlbWE6IGFueSkge1xuICAgIE9iamVjdC5rZXlzKHNjaGVtYS5maWVsZHMpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1BvaW50ZXInICYmIG9iamVjdFtmaWVsZE5hbWVdKSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0geyBvYmplY3RJZDogb2JqZWN0W2ZpZWxkTmFtZV0sIF9fdHlwZTogJ1BvaW50ZXInLCBjbGFzc05hbWU6IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50YXJnZXRDbGFzcyB9O1xuICAgICAgfVxuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogXCJSZWxhdGlvblwiLFxuICAgICAgICAgIGNsYXNzTmFtZTogc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnRhcmdldENsYXNzXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6IFwiR2VvUG9pbnRcIixcbiAgICAgICAgICBsYXRpdHVkZTogb2JqZWN0W2ZpZWxkTmFtZV0ueSxcbiAgICAgICAgICBsb25naXR1ZGU6IG9iamVjdFtmaWVsZE5hbWVdLnhcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgbGV0IGNvb3JkcyA9IG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgICBjb29yZHMgPSBjb29yZHMuc3Vic3RyKDIsIGNvb3Jkcy5sZW5ndGggLSA0KS5zcGxpdCgnKSwoJyk7XG4gICAgICAgIGNvb3JkcyA9IGNvb3Jkcy5tYXAoKHBvaW50KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHBhcnNlRmxvYXQocG9pbnQuc3BsaXQoJywnKVsxXSksXG4gICAgICAgICAgICBwYXJzZUZsb2F0KHBvaW50LnNwbGl0KCcsJylbMF0pXG4gICAgICAgICAgXTtcbiAgICAgICAgfSk7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogXCJQb2x5Z29uXCIsXG4gICAgICAgICAgY29vcmRpbmF0ZXM6IGNvb3Jkc1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdGaWxlJykge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdGaWxlJyxcbiAgICAgICAgICBuYW1lOiBvYmplY3RbZmllbGROYW1lXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgLy9UT0RPOiByZW1vdmUgdGhpcyByZWxpYW5jZSBvbiB0aGUgbW9uZ28gZm9ybWF0LiBEQiBhZGFwdGVyIHNob3VsZG4ndCBrbm93IHRoZXJlIGlzIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIGNyZWF0ZWQgYXQgYW5kIGFueSBvdGhlciBkYXRlIGZpZWxkLlxuICAgIGlmIChvYmplY3QuY3JlYXRlZEF0KSB7XG4gICAgICBvYmplY3QuY3JlYXRlZEF0ID0gb2JqZWN0LmNyZWF0ZWRBdC50b0lTT1N0cmluZygpO1xuICAgIH1cbiAgICBpZiAob2JqZWN0LnVwZGF0ZWRBdCkge1xuICAgICAgb2JqZWN0LnVwZGF0ZWRBdCA9IG9iamVjdC51cGRhdGVkQXQudG9JU09TdHJpbmcoKTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC5leHBpcmVzQXQpIHtcbiAgICAgIG9iamVjdC5leHBpcmVzQXQgPSB7IF9fdHlwZTogJ0RhdGUnLCBpc286IG9iamVjdC5leHBpcmVzQXQudG9JU09TdHJpbmcoKSB9O1xuICAgIH1cbiAgICBpZiAob2JqZWN0Ll9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCkge1xuICAgICAgb2JqZWN0Ll9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCA9IHsgX190eXBlOiAnRGF0ZScsIGlzbzogb2JqZWN0Ll9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdC50b0lTT1N0cmluZygpIH07XG4gICAgfVxuICAgIGlmIChvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0KSB7XG4gICAgICBvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0ID0geyBfX3R5cGU6ICdEYXRlJywgaXNvOiBvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0LnRvSVNPU3RyaW5nKCkgfTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC5fcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0KSB7XG4gICAgICBvYmplY3QuX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCA9IHsgX190eXBlOiAnRGF0ZScsIGlzbzogb2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQudG9JU09TdHJpbmcoKSB9O1xuICAgIH1cbiAgICBpZiAob2JqZWN0Ll9wYXNzd29yZF9jaGFuZ2VkX2F0KSB7XG4gICAgICBvYmplY3QuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSB7IF9fdHlwZTogJ0RhdGUnLCBpc286IG9iamVjdC5fcGFzc3dvcmRfY2hhbmdlZF9hdC50b0lTT1N0cmluZygpIH07XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gPT09IG51bGwpIHtcbiAgICAgICAgZGVsZXRlIG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgfVxuICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHsgX190eXBlOiAnRGF0ZScsIGlzbzogb2JqZWN0W2ZpZWxkTmFtZV0udG9JU09TdHJpbmcoKSB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICAvLyBDcmVhdGUgYSB1bmlxdWUgaW5kZXguIFVuaXF1ZSBpbmRleGVzIG9uIG51bGxhYmxlIGZpZWxkcyBhcmUgbm90IGFsbG93ZWQuIFNpbmNlIHdlIGRvbid0XG4gIC8vIGN1cnJlbnRseSBrbm93IHdoaWNoIGZpZWxkcyBhcmUgbnVsbGFibGUgYW5kIHdoaWNoIGFyZW4ndCwgd2UgaWdub3JlIHRoYXQgY3JpdGVyaWEuXG4gIC8vIEFzIHN1Y2gsIHdlIHNob3VsZG4ndCBleHBvc2UgdGhpcyBmdW5jdGlvbiB0byB1c2VycyBvZiBwYXJzZSB1bnRpbCB3ZSBoYXZlIGFuIG91dC1vZi1iYW5kXG4gIC8vIFdheSBvZiBkZXRlcm1pbmluZyBpZiBhIGZpZWxkIGlzIG51bGxhYmxlLiBVbmRlZmluZWQgZG9lc24ndCBjb3VudCBhZ2FpbnN0IHVuaXF1ZW5lc3MsXG4gIC8vIHdoaWNoIGlzIHdoeSB3ZSB1c2Ugc3BhcnNlIGluZGV4ZXMuXG4gIGVuc3VyZVVuaXF1ZW5lc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgZmllbGROYW1lczogc3RyaW5nW10pIHtcbiAgICAvLyBVc2UgdGhlIHNhbWUgbmFtZSBmb3IgZXZlcnkgZW5zdXJlVW5pcXVlbmVzcyBhdHRlbXB0LCBiZWNhdXNlIHBvc3RncmVzXG4gICAgLy8gV2lsbCBoYXBwaWx5IGNyZWF0ZSB0aGUgc2FtZSBpbmRleCB3aXRoIG11bHRpcGxlIG5hbWVzLlxuICAgIGNvbnN0IGNvbnN0cmFpbnROYW1lID0gYHVuaXF1ZV8ke2ZpZWxkTmFtZXMuc29ydCgpLmpvaW4oJ18nKX1gO1xuICAgIGNvbnN0IGNvbnN0cmFpbnRQYXR0ZXJucyA9IGZpZWxkTmFtZXMubWFwKChmaWVsZE5hbWUsIGluZGV4KSA9PiBgJCR7aW5kZXggKyAzfTpuYW1lYCk7XG4gICAgY29uc3QgcXMgPSBgQUxURVIgVEFCTEUgJDE6bmFtZSBBREQgQ09OU1RSQUlOVCAkMjpuYW1lIFVOSVFVRSAoJHtjb25zdHJhaW50UGF0dGVybnMuam9pbigpfSlgO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQubm9uZShxcywgW2NsYXNzTmFtZSwgY29uc3RyYWludE5hbWUsIC4uLmZpZWxkTmFtZXNdKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBvc3RncmVzRHVwbGljYXRlUmVsYXRpb25FcnJvciAmJiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKGNvbnN0cmFpbnROYW1lKSkge1xuICAgICAgICAvLyBJbmRleCBhbHJlYWR5IGV4aXN0cy4gSWdub3JlIGVycm9yLlxuICAgICAgICB9IGVsc2UgaWYgKGVycm9yLmNvZGUgPT09IFBvc3RncmVzVW5pcXVlSW5kZXhWaW9sYXRpb25FcnJvciAmJiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKGNvbnN0cmFpbnROYW1lKSkge1xuICAgICAgICAvLyBDYXN0IHRoZSBlcnJvciBpbnRvIHRoZSBwcm9wZXIgcGFyc2UgZXJyb3JcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLCAnQSBkdXBsaWNhdGUgdmFsdWUgZm9yIGEgZmllbGQgd2l0aCB1bmlxdWUgdmFsdWVzIHdhcyBwcm92aWRlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIEV4ZWN1dGVzIGEgY291bnQuXG4gIGNvdW50KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUpIHtcbiAgICBkZWJ1ZygnY291bnQnLCBjbGFzc05hbWUsIHF1ZXJ5KTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2UoeyBzY2hlbWEsIHF1ZXJ5LCBpbmRleDogMiB9KTtcbiAgICB2YWx1ZXMucHVzaCguLi53aGVyZS52YWx1ZXMpO1xuXG4gICAgY29uc3Qgd2hlcmVQYXR0ZXJuID0gd2hlcmUucGF0dGVybi5sZW5ndGggPiAwID8gYFdIRVJFICR7d2hlcmUucGF0dGVybn1gIDogJyc7XG4gICAgY29uc3QgcXMgPSBgU0VMRUNUIGNvdW50KCopIEZST00gJDE6bmFtZSAke3doZXJlUGF0dGVybn1gO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQub25lKHFzLCB2YWx1ZXMsIGEgPT4gK2EuY291bnQpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9KTtcbiAgfVxuXG4gIGRpc3RpbmN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIGZpZWxkTmFtZTogc3RyaW5nKSB7XG4gICAgZGVidWcoJ2Rpc3RpbmN0JywgY2xhc3NOYW1lLCBxdWVyeSk7XG4gICAgbGV0IGZpZWxkID0gZmllbGROYW1lO1xuICAgIGxldCBjb2x1bW4gPSBmaWVsZE5hbWU7XG4gICAgY29uc3QgaXNOZXN0ZWQgPSBmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDA7XG4gICAgaWYgKGlzTmVzdGVkKSB7XG4gICAgICBmaWVsZCA9IHRyYW5zZm9ybURvdEZpZWxkVG9Db21wb25lbnRzKGZpZWxkTmFtZSkuam9pbignLT4nKTtcbiAgICAgIGNvbHVtbiA9IGZpZWxkTmFtZS5zcGxpdCgnLicpWzBdO1xuICAgIH1cbiAgICBjb25zdCBpc0FycmF5RmllbGQgPSBzY2hlbWEuZmllbGRzXG4gICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdXG4gICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdBcnJheSc7XG4gICAgY29uc3QgaXNQb2ludGVyRmllbGQgPSBzY2hlbWEuZmllbGRzXG4gICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdXG4gICAgICAgICAgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdQb2ludGVyJztcbiAgICBjb25zdCB2YWx1ZXMgPSBbZmllbGQsIGNvbHVtbiwgY2xhc3NOYW1lXTtcbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2UoeyBzY2hlbWEsIHF1ZXJ5LCBpbmRleDogNCB9KTtcbiAgICB2YWx1ZXMucHVzaCguLi53aGVyZS52YWx1ZXMpO1xuXG4gICAgY29uc3Qgd2hlcmVQYXR0ZXJuID0gd2hlcmUucGF0dGVybi5sZW5ndGggPiAwID8gYFdIRVJFICR7d2hlcmUucGF0dGVybn1gIDogJyc7XG4gICAgY29uc3QgdHJhbnNmb3JtZXIgPSBpc0FycmF5RmllbGQgPyAnanNvbmJfYXJyYXlfZWxlbWVudHMnIDogJ09OJztcbiAgICBsZXQgcXMgPSBgU0VMRUNUIERJU1RJTkNUICR7dHJhbnNmb3JtZXJ9KCQxOm5hbWUpICQyOm5hbWUgRlJPTSAkMzpuYW1lICR7d2hlcmVQYXR0ZXJufWA7XG4gICAgaWYgKGlzTmVzdGVkKSB7XG4gICAgICBxcyA9IGBTRUxFQ1QgRElTVElOQ1QgJHt0cmFuc2Zvcm1lcn0oJDE6cmF3KSAkMjpyYXcgRlJPTSAkMzpuYW1lICR7d2hlcmVQYXR0ZXJufWA7XG4gICAgfVxuICAgIGRlYnVnKHFzLCB2YWx1ZXMpO1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQuYW55KHFzLCB2YWx1ZXMpXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSBQb3N0Z3Jlc01pc3NpbmdDb2x1bW5FcnJvcikge1xuICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgICBpZiAoIWlzTmVzdGVkKSB7XG4gICAgICAgICAgcmVzdWx0cyA9IHJlc3VsdHMuZmlsdGVyKChvYmplY3QpID0+IG9iamVjdFtmaWVsZF0gIT09IG51bGwpO1xuICAgICAgICAgIHJldHVybiByZXN1bHRzLm1hcChvYmplY3QgPT4ge1xuICAgICAgICAgICAgaWYgKCFpc1BvaW50ZXJGaWVsZCkge1xuICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0W2ZpZWxkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgICAgICBjbGFzc05hbWU6ICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICAgIG9iamVjdElkOiBvYmplY3RbZmllbGRdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoaWxkID0gZmllbGROYW1lLnNwbGl0KCcuJylbMV07XG4gICAgICAgIHJldHVybiByZXN1bHRzLm1hcChvYmplY3QgPT4gb2JqZWN0W2NvbHVtbl1bY2hpbGRdKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHRzID0+IHJlc3VsdHMubWFwKG9iamVjdCA9PiB0aGlzLnBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKSkpO1xuICB9XG5cbiAgYWdncmVnYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSkge1xuICAgIGRlYnVnKCdhZ2dyZWdhdGUnLCBjbGFzc05hbWUsIHBpcGVsaW5lKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBsZXQgaW5kZXg6IG51bWJlciA9IDI7XG4gICAgbGV0IGNvbHVtbnM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IGNvdW50RmllbGQgPSBudWxsO1xuICAgIGxldCBncm91cFZhbHVlcyA9IG51bGw7XG4gICAgbGV0IHdoZXJlUGF0dGVybiA9ICcnO1xuICAgIGxldCBsaW1pdFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc2tpcFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc29ydFBhdHRlcm4gPSAnJztcbiAgICBsZXQgZ3JvdXBQYXR0ZXJuID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwaXBlbGluZS5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY29uc3Qgc3RhZ2UgPSBwaXBlbGluZVtpXTtcbiAgICAgIGlmIChzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRncm91cFtmaWVsZF07XG4gICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZmllbGQgPT09ICdfaWQnICYmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSAmJiB2YWx1ZSAhPT0gJycpIHtcbiAgICAgICAgICAgIGNvbHVtbnMucHVzaChgJCR7aW5kZXh9Om5hbWUgQVMgXCJvYmplY3RJZFwiYCk7XG4gICAgICAgICAgICBncm91cFBhdHRlcm4gPSBgR1JPVVAgQlkgJCR7aW5kZXh9Om5hbWVgO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2godHJhbnNmb3JtQWdncmVnYXRlRmllbGQodmFsdWUpKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGZpZWxkID09PSAnX2lkJyAmJiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JykgJiYgT2JqZWN0LmtleXModmFsdWUpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgZ3JvdXBWYWx1ZXMgPSB2YWx1ZTtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwQnlGaWVsZHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYWxpYXMgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gT2JqZWN0LmtleXModmFsdWVbYWxpYXNdKVswXTtcbiAgICAgICAgICAgICAgY29uc3Qgc291cmNlID0gdHJhbnNmb3JtQWdncmVnYXRlRmllbGQodmFsdWVbYWxpYXNdW29wZXJhdGlvbl0pO1xuICAgICAgICAgICAgICBpZiAobW9uZ29BZ2dyZWdhdGVUb1Bvc3RncmVzW29wZXJhdGlvbl0pIHtcbiAgICAgICAgICAgICAgICBpZiAoIWdyb3VwQnlGaWVsZHMuaW5jbHVkZXMoYFwiJHtzb3VyY2V9XCJgKSkge1xuICAgICAgICAgICAgICAgICAgZ3JvdXBCeUZpZWxkcy5wdXNoKGBcIiR7c291cmNlfVwiYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbHVtbnMucHVzaChgRVhUUkFDVCgke21vbmdvQWdncmVnYXRlVG9Qb3N0Z3Jlc1tvcGVyYXRpb25dfSBGUk9NICQke2luZGV4fTpuYW1lIEFUIFRJTUUgWk9ORSAnVVRDJykgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgICAgdmFsdWVzLnB1c2goc291cmNlLCBhbGlhcyk7XG4gICAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ3JvdXBQYXR0ZXJuID0gYEdST1VQIEJZICQke2luZGV4fTpyYXdgO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goZ3JvdXBCeUZpZWxkcy5qb2luKCkpO1xuICAgICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodmFsdWUuJHN1bSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZS4kc3VtID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYFNVTSgkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRzdW0pLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb3VudEZpZWxkID0gZmllbGQ7XG4gICAgICAgICAgICAgIGNvbHVtbnMucHVzaChgQ09VTlQoKikgQVMgJCR7aW5kZXh9Om5hbWVgKTtcbiAgICAgICAgICAgICAgdmFsdWVzLnB1c2goZmllbGQpO1xuICAgICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodmFsdWUuJG1heCkge1xuICAgICAgICAgICAgY29sdW1ucy5wdXNoKGBNQVgoJCR7aW5kZXh9Om5hbWUpIEFTICQke2luZGV4ICsgMX06bmFtZWApO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2godHJhbnNmb3JtQWdncmVnYXRlRmllbGQodmFsdWUuJG1heCksIGZpZWxkKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh2YWx1ZS4kbWluKSB7XG4gICAgICAgICAgICBjb2x1bW5zLnB1c2goYE1JTigkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaCh0cmFuc2Zvcm1BZ2dyZWdhdGVGaWVsZCh2YWx1ZS4kbWluKSwgZmllbGQpO1xuICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHZhbHVlLiRhdmcpIHtcbiAgICAgICAgICAgIGNvbHVtbnMucHVzaChgQVZHKCQke2luZGV4fTpuYW1lKSBBUyAkJHtpbmRleCArIDF9Om5hbWVgKTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRhdmcpLCBmaWVsZCk7XG4gICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29sdW1ucy5wdXNoKCcqJyk7XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJHByb2plY3QpIHtcbiAgICAgICAgaWYgKGNvbHVtbnMuaW5jbHVkZXMoJyonKSkge1xuICAgICAgICAgIGNvbHVtbnMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIHN0YWdlLiRwcm9qZWN0KSB7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBzdGFnZS4kcHJvamVjdFtmaWVsZF07XG4gICAgICAgICAgaWYgKCh2YWx1ZSA9PT0gMSB8fCB2YWx1ZSA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgIGNvbHVtbnMucHVzaChgJCR7aW5kZXh9Om5hbWVgKTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gW107XG4gICAgICAgIGNvbnN0IG9yT3JBbmQgPSBzdGFnZS4kbWF0Y2guaGFzT3duUHJvcGVydHkoJyRvcicpID8gJyBPUiAnIDogJyBBTkQgJztcblxuICAgICAgICBpZiAoc3RhZ2UuJG1hdGNoLiRvcikge1xuICAgICAgICAgIGNvbnN0IGNvbGxhcHNlID0ge307XG4gICAgICAgICAgc3RhZ2UuJG1hdGNoLiRvci5mb3JFYWNoKChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBlbGVtZW50KSB7XG4gICAgICAgICAgICAgIGNvbGxhcHNlW2tleV0gPSBlbGVtZW50W2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgc3RhZ2UuJG1hdGNoID0gY29sbGFwc2U7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBzdGFnZS4kbWF0Y2gpIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRtYXRjaFtmaWVsZF07XG4gICAgICAgICAgY29uc3QgbWF0Y2hQYXR0ZXJucyA9IFtdO1xuICAgICAgICAgIE9iamVjdC5rZXlzKFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcikuZm9yRWFjaCgoY21wKSA9PiB7XG4gICAgICAgICAgICBpZiAodmFsdWVbY21wXSkge1xuICAgICAgICAgICAgICBjb25zdCBwZ0NvbXBhcmF0b3IgPSBQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3JbY21wXTtcbiAgICAgICAgICAgICAgbWF0Y2hQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSAke3BnQ29tcGFyYXRvcn0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZCwgdG9Qb3N0Z3Jlc1ZhbHVlKHZhbHVlW2NtcF0pKTtcbiAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAobWF0Y2hQYXR0ZXJucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAoJHttYXRjaFBhdHRlcm5zLmpvaW4oJyBBTkQgJyl9KWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSAmJiBtYXRjaFBhdHRlcm5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZCwgdmFsdWUpO1xuICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgd2hlcmVQYXR0ZXJuID0gcGF0dGVybnMubGVuZ3RoID4gMCA/IGBXSEVSRSAke3BhdHRlcm5zLmpvaW4oYCAke29yT3JBbmR9IGApfWAgOiAnJztcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kbGltaXQpIHtcbiAgICAgICAgbGltaXRQYXR0ZXJuID0gYExJTUlUICQke2luZGV4fWA7XG4gICAgICAgIHZhbHVlcy5wdXNoKHN0YWdlLiRsaW1pdCk7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJHNraXApIHtcbiAgICAgICAgc2tpcFBhdHRlcm4gPSBgT0ZGU0VUICQke2luZGV4fWA7XG4gICAgICAgIHZhbHVlcy5wdXNoKHN0YWdlLiRza2lwKTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kc29ydCkge1xuICAgICAgICBjb25zdCBzb3J0ID0gc3RhZ2UuJHNvcnQ7XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhzb3J0KTtcbiAgICAgICAgY29uc3Qgc29ydGluZyA9IGtleXMubWFwKChrZXkpID0+IHtcbiAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1lciA9IHNvcnRba2V5XSA9PT0gMSA/ICdBU0MnIDogJ0RFU0MnO1xuICAgICAgICAgIGNvbnN0IG9yZGVyID0gYCQke2luZGV4fTpuYW1lICR7dHJhbnNmb3JtZXJ9YDtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIHJldHVybiBvcmRlcjtcbiAgICAgICAgfSkuam9pbigpO1xuICAgICAgICB2YWx1ZXMucHVzaCguLi5rZXlzKTtcbiAgICAgICAgc29ydFBhdHRlcm4gPSBzb3J0ICE9PSB1bmRlZmluZWQgJiYgc29ydGluZy5sZW5ndGggPiAwID8gYE9SREVSIEJZICR7c29ydGluZ31gIDogJyc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcXMgPSBgU0VMRUNUICR7Y29sdW1ucy5qb2luKCl9IEZST00gJDE6bmFtZSAke3doZXJlUGF0dGVybn0gJHtzb3J0UGF0dGVybn0gJHtsaW1pdFBhdHRlcm59ICR7c2tpcFBhdHRlcm59ICR7Z3JvdXBQYXR0ZXJufWA7XG4gICAgZGVidWcocXMsIHZhbHVlcyk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5tYXAocXMsIHZhbHVlcywgYSA9PiB0aGlzLnBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIGEsIHNjaGVtYSkpXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgcmVzdWx0cy5mb3JFYWNoKHJlc3VsdCA9PiB7XG4gICAgICAgICAgaWYgKCFyZXN1bHQuaGFzT3duUHJvcGVydHkoJ29iamVjdElkJykpIHtcbiAgICAgICAgICAgIHJlc3VsdC5vYmplY3RJZCA9IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChncm91cFZhbHVlcykge1xuICAgICAgICAgICAgcmVzdWx0Lm9iamVjdElkID0ge307XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBncm91cFZhbHVlcykge1xuICAgICAgICAgICAgICByZXN1bHQub2JqZWN0SWRba2V5XSA9IHJlc3VsdFtrZXldO1xuICAgICAgICAgICAgICBkZWxldGUgcmVzdWx0W2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChjb3VudEZpZWxkKSB7XG4gICAgICAgICAgICByZXN1bHRbY291bnRGaWVsZF0gPSBwYXJzZUludChyZXN1bHRbY291bnRGaWVsZF0sIDEwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybUluaXRpYWxpemF0aW9uKHsgVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyB9OiBhbnkpIHtcbiAgICAvLyBUT0RPOiBUaGlzIG1ldGhvZCBuZWVkcyB0byBiZSByZXdyaXR0ZW4gdG8gbWFrZSBwcm9wZXIgdXNlIG9mIGNvbm5lY3Rpb25zIChAdml0YWx5LXQpXG4gICAgZGVidWcoJ3BlcmZvcm1Jbml0aWFsaXphdGlvbicpO1xuICAgIGNvbnN0IHByb21pc2VzID0gVm9sYXRpbGVDbGFzc2VzU2NoZW1hcy5tYXAoKHNjaGVtYSkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlVGFibGUoc2NoZW1hLmNsYXNzTmFtZSwgc2NoZW1hKVxuICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIGlmIChlcnIuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yIHx8IGVyci5jb2RlID09PSBQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB0aGlzLnNjaGVtYVVwZ3JhZGUoc2NoZW1hLmNsYXNzTmFtZSwgc2NoZW1hKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xpZW50LnR4KCdwZXJmb3JtLWluaXRpYWxpemF0aW9uJywgdCA9PiB7XG4gICAgICAgICAgcmV0dXJuIHQuYmF0Y2goW1xuICAgICAgICAgICAgdC5ub25lKHNxbC5taXNjLmpzb25PYmplY3RTZXRLZXlzKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuYWRkKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuYWRkVW5pcXVlKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkucmVtb3ZlKSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuY29udGFpbnNBbGwpLFxuICAgICAgICAgICAgdC5ub25lKHNxbC5hcnJheS5jb250YWluc0FsbFJlZ2V4KSxcbiAgICAgICAgICAgIHQubm9uZShzcWwuYXJyYXkuY29udGFpbnMpXG4gICAgICAgICAgXSk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC50aGVuKGRhdGEgPT4ge1xuICAgICAgICBkZWJ1ZyhgaW5pdGlhbGl6YXRpb25Eb25lIGluICR7ZGF0YS5kdXJhdGlvbn1gKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgfSk7XG4gIH1cblxuICBjcmVhdGVJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleGVzOiBhbnksIGNvbm46ID9hbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gKGNvbm4gfHwgdGhpcy5fY2xpZW50KS50eCh0ID0+IHQuYmF0Y2goaW5kZXhlcy5tYXAoaSA9PiB7XG4gICAgICByZXR1cm4gdC5ub25lKCdDUkVBVEUgSU5ERVggJDE6bmFtZSBPTiAkMjpuYW1lICgkMzpuYW1lKScsIFtpLm5hbWUsIGNsYXNzTmFtZSwgaS5rZXldKTtcbiAgICB9KSkpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZywgdHlwZTogYW55LCBjb25uOiA/YW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIChjb25uIHx8IHRoaXMuX2NsaWVudCkubm9uZSgnQ1JFQVRFIElOREVYICQxOm5hbWUgT04gJDI6bmFtZSAoJDM6bmFtZSknLCBbZmllbGROYW1lLCBjbGFzc05hbWUsIHR5cGVdKTtcbiAgfVxuXG4gIGRyb3BJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleGVzOiBhbnksIGNvbm46IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHF1ZXJpZXMgPSBpbmRleGVzLm1hcChpID0+ICh7cXVlcnk6ICdEUk9QIElOREVYICQxOm5hbWUnLCB2YWx1ZXM6IGl9KSk7XG4gICAgcmV0dXJuIChjb25uIHx8IHRoaXMuX2NsaWVudCkudHgodCA9PiB0Lm5vbmUodGhpcy5fcGdwLmhlbHBlcnMuY29uY2F0KHF1ZXJpZXMpKSk7XG4gIH1cblxuICBnZXRJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcXMgPSAnU0VMRUNUICogRlJPTSBwZ19pbmRleGVzIFdIRVJFIHRhYmxlbmFtZSA9ICR7Y2xhc3NOYW1lfSc7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5hbnkocXMsIHtjbGFzc05hbWV9KTtcbiAgfVxuXG4gIHVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb252ZXJ0UG9seWdvblRvU1FMKHBvbHlnb24pIHtcbiAgaWYgKHBvbHlnb24ubGVuZ3RoIDwgMykge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgIGBQb2x5Z29uIG11c3QgaGF2ZSBhdCBsZWFzdCAzIHZhbHVlc2BcbiAgICApO1xuICB9XG4gIGlmIChwb2x5Z29uWzBdWzBdICE9PSBwb2x5Z29uW3BvbHlnb24ubGVuZ3RoIC0gMV1bMF0gfHxcbiAgICBwb2x5Z29uWzBdWzFdICE9PSBwb2x5Z29uW3BvbHlnb24ubGVuZ3RoIC0gMV1bMV0pIHtcbiAgICBwb2x5Z29uLnB1c2gocG9seWdvblswXSk7XG4gIH1cbiAgY29uc3QgdW5pcXVlID0gcG9seWdvbi5maWx0ZXIoKGl0ZW0sIGluZGV4LCBhcikgPT4ge1xuICAgIGxldCBmb3VuZEluZGV4ID0gLTE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhci5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY29uc3QgcHQgPSBhcltpXTtcbiAgICAgIGlmIChwdFswXSA9PT0gaXRlbVswXSAmJlxuICAgICAgICAgIHB0WzFdID09PSBpdGVtWzFdKSB7XG4gICAgICAgIGZvdW5kSW5kZXggPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kSW5kZXggPT09IGluZGV4O1xuICB9KTtcbiAgaWYgKHVuaXF1ZS5sZW5ndGggPCAzKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgJ0dlb0pTT046IExvb3AgbXVzdCBoYXZlIGF0IGxlYXN0IDMgZGlmZmVyZW50IHZlcnRpY2VzJ1xuICAgICk7XG4gIH1cbiAgY29uc3QgcG9pbnRzID0gcG9seWdvbi5tYXAoKHBvaW50KSA9PiB7XG4gICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBhcnNlRmxvYXQocG9pbnRbMV0pLCBwYXJzZUZsb2F0KHBvaW50WzBdKSk7XG4gICAgcmV0dXJuIGAoJHtwb2ludFsxXX0sICR7cG9pbnRbMF19KWA7XG4gIH0pLmpvaW4oJywgJyk7XG4gIHJldHVybiBgKCR7cG9pbnRzfSlgO1xufVxuXG5mdW5jdGlvbiByZW1vdmVXaGl0ZVNwYWNlKHJlZ2V4KSB7XG4gIGlmICghcmVnZXguZW5kc1dpdGgoJ1xcbicpKXtcbiAgICByZWdleCArPSAnXFxuJztcbiAgfVxuXG4gIC8vIHJlbW92ZSBub24gZXNjYXBlZCBjb21tZW50c1xuICByZXR1cm4gcmVnZXgucmVwbGFjZSgvKFteXFxcXF0pIy4qXFxuL2dtaSwgJyQxJylcbiAgICAvLyByZW1vdmUgbGluZXMgc3RhcnRpbmcgd2l0aCBhIGNvbW1lbnRcbiAgICAucmVwbGFjZSgvXiMuKlxcbi9nbWksICcnKVxuICAgIC8vIHJlbW92ZSBub24gZXNjYXBlZCB3aGl0ZXNwYWNlXG4gICAgLnJlcGxhY2UoLyhbXlxcXFxdKVxccysvZ21pLCAnJDEnKVxuICAgIC8vIHJlbW92ZSB3aGl0ZXNwYWNlIGF0IHRoZSBiZWdpbm5pbmcgb2YgYSBsaW5lXG4gICAgLnJlcGxhY2UoL15cXHMrLywgJycpXG4gICAgLnRyaW0oKTtcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1JlZ2V4UGF0dGVybihzKSB7XG4gIGlmIChzICYmIHMuc3RhcnRzV2l0aCgnXicpKXtcbiAgICAvLyByZWdleCBmb3Igc3RhcnRzV2l0aFxuICAgIHJldHVybiAnXicgKyBsaXRlcmFsaXplUmVnZXhQYXJ0KHMuc2xpY2UoMSkpO1xuXG4gIH0gZWxzZSBpZiAocyAmJiBzLmVuZHNXaXRoKCckJykpIHtcbiAgICAvLyByZWdleCBmb3IgZW5kc1dpdGhcbiAgICByZXR1cm4gbGl0ZXJhbGl6ZVJlZ2V4UGFydChzLnNsaWNlKDAsIHMubGVuZ3RoIC0gMSkpICsgJyQnO1xuICB9XG5cbiAgLy8gcmVnZXggZm9yIGNvbnRhaW5zXG4gIHJldHVybiBsaXRlcmFsaXplUmVnZXhQYXJ0KHMpO1xufVxuXG5mdW5jdGlvbiBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZSkge1xuICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycgfHwgIXZhbHVlLnN0YXJ0c1dpdGgoJ14nKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IG1hdGNoZXMgPSB2YWx1ZS5tYXRjaCgvXFxeXFxcXFEuKlxcXFxFLyk7XG4gIHJldHVybiAhIW1hdGNoZXM7XG59XG5cbmZ1bmN0aW9uIGlzQWxsVmFsdWVzUmVnZXhPck5vbmUodmFsdWVzKSB7XG4gIGlmICghdmFsdWVzIHx8ICFBcnJheS5pc0FycmF5KHZhbHVlcykgfHwgdmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgZmlyc3RWYWx1ZXNJc1JlZ2V4ID0gaXNTdGFydHNXaXRoUmVnZXgodmFsdWVzWzBdLiRyZWdleCk7XG4gIGlmICh2YWx1ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGZpcnN0VmFsdWVzSXNSZWdleDtcbiAgfVxuXG4gIGZvciAobGV0IGkgPSAxLCBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoZmlyc3RWYWx1ZXNJc1JlZ2V4ICE9PSBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZXNbaV0uJHJlZ2V4KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoKHZhbHVlcykge1xuICByZXR1cm4gdmFsdWVzLnNvbWUoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlLiRyZWdleCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVMaXRlcmFsUmVnZXgocmVtYWluaW5nKSB7XG4gIHJldHVybiByZW1haW5pbmcuc3BsaXQoJycpLm1hcChjID0+IHtcbiAgICBpZiAoYy5tYXRjaCgvWzAtOWEtekEtWl0vKSAhPT0gbnVsbCkge1xuICAgICAgLy8gZG9uJ3QgZXNjYXBlIGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzXG4gICAgICByZXR1cm4gYztcbiAgICB9XG4gICAgLy8gZXNjYXBlIGV2ZXJ5dGhpbmcgZWxzZSAoc2luZ2xlIHF1b3RlcyB3aXRoIHNpbmdsZSBxdW90ZXMsIGV2ZXJ5dGhpbmcgZWxzZSB3aXRoIGEgYmFja3NsYXNoKVxuICAgIHJldHVybiBjID09PSBgJ2AgPyBgJydgIDogYFxcXFwke2N9YDtcbiAgfSkuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIGxpdGVyYWxpemVSZWdleFBhcnQoczogc3RyaW5nKSB7XG4gIGNvbnN0IG1hdGNoZXIxID0gL1xcXFxRKCg/IVxcXFxFKS4qKVxcXFxFJC9cbiAgY29uc3QgcmVzdWx0MTogYW55ID0gcy5tYXRjaChtYXRjaGVyMSk7XG4gIGlmKHJlc3VsdDEgJiYgcmVzdWx0MS5sZW5ndGggPiAxICYmIHJlc3VsdDEuaW5kZXggPiAtMSkge1xuICAgIC8vIHByb2Nlc3MgcmVnZXggdGhhdCBoYXMgYSBiZWdpbm5pbmcgYW5kIGFuIGVuZCBzcGVjaWZpZWQgZm9yIHRoZSBsaXRlcmFsIHRleHRcbiAgICBjb25zdCBwcmVmaXggPSBzLnN1YnN0cigwLCByZXN1bHQxLmluZGV4KTtcbiAgICBjb25zdCByZW1haW5pbmcgPSByZXN1bHQxWzFdO1xuXG4gICAgcmV0dXJuIGxpdGVyYWxpemVSZWdleFBhcnQocHJlZml4KSArIGNyZWF0ZUxpdGVyYWxSZWdleChyZW1haW5pbmcpO1xuICB9XG5cbiAgLy8gcHJvY2VzcyByZWdleCB0aGF0IGhhcyBhIGJlZ2lubmluZyBzcGVjaWZpZWQgZm9yIHRoZSBsaXRlcmFsIHRleHRcbiAgY29uc3QgbWF0Y2hlcjIgPSAvXFxcXFEoKD8hXFxcXEUpLiopJC9cbiAgY29uc3QgcmVzdWx0MjogYW55ID0gcy5tYXRjaChtYXRjaGVyMik7XG4gIGlmKHJlc3VsdDIgJiYgcmVzdWx0Mi5sZW5ndGggPiAxICYmIHJlc3VsdDIuaW5kZXggPiAtMSl7XG4gICAgY29uc3QgcHJlZml4ID0gcy5zdWJzdHIoMCwgcmVzdWx0Mi5pbmRleCk7XG4gICAgY29uc3QgcmVtYWluaW5nID0gcmVzdWx0MlsxXTtcblxuICAgIHJldHVybiBsaXRlcmFsaXplUmVnZXhQYXJ0KHByZWZpeCkgKyBjcmVhdGVMaXRlcmFsUmVnZXgocmVtYWluaW5nKTtcbiAgfVxuXG4gIC8vIHJlbW92ZSBhbGwgaW5zdGFuY2VzIG9mIFxcUSBhbmQgXFxFIGZyb20gdGhlIHJlbWFpbmluZyB0ZXh0ICYgZXNjYXBlIHNpbmdsZSBxdW90ZXNcbiAgcmV0dXJuIChcbiAgICBzLnJlcGxhY2UoLyhbXlxcXFxdKShcXFxcRSkvLCAnJDEnKVxuICAgICAgLnJlcGxhY2UoLyhbXlxcXFxdKShcXFxcUSkvLCAnJDEnKVxuICAgICAgLnJlcGxhY2UoL15cXFxcRS8sICcnKVxuICAgICAgLnJlcGxhY2UoL15cXFxcUS8sICcnKVxuICAgICAgLnJlcGxhY2UoLyhbXiddKScvLCBgJDEnJ2ApXG4gICAgICAucmVwbGFjZSgvXicoW14nXSkvLCBgJyckMWApXG4gICk7XG59XG5cbnZhciBHZW9Qb2ludENvZGVyID0ge1xuICBpc1ZhbGlkSlNPTih2YWx1ZSkge1xuICAgIHJldHVybiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgdmFsdWUgIT09IG51bGwgJiZcbiAgICAgIHZhbHVlLl9fdHlwZSA9PT0gJ0dlb1BvaW50J1xuICAgICk7XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IFBvc3RncmVzU3RvcmFnZUFkYXB0ZXI7XG4iXX0= \ No newline at end of file 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 index 24355bc732..8db1ca0e7b 100644 --- a/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql +++ b/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql @@ -7,5 +7,8 @@ CREATE OR REPLACE FUNCTION array_contains_all( IMMUTABLE STRICT AS $function$ - SELECT RES.CNT = jsonb_array_length("values") FROM (SELECT COUNT(*) as CNT FROM jsonb_array_elements("array") as elt WHERE elt IN (SELECT jsonb_array_elements("values"))) as RES; + 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/index.js b/lib/Adapters/Storage/Postgres/sql/index.js index c1b31b93ac..8774d5fbff 100644 --- a/lib/Adapters/Storage/Postgres/sql/index.js +++ b/lib/Adapters/Storage/Postgres/sql/index.js @@ -9,6 +9,7 @@ module.exports = { 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: { @@ -29,4 +30,5 @@ function sql(file) { } return qf; -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL3NxbC9pbmRleC5qcyJdLCJuYW1lcyI6WyJRdWVyeUZpbGUiLCJyZXF1aXJlIiwicGF0aCIsIm1vZHVsZSIsImV4cG9ydHMiLCJhcnJheSIsImFkZCIsInNxbCIsImFkZFVuaXF1ZSIsImNvbnRhaW5zIiwiY29udGFpbnNBbGwiLCJjb250YWluc0FsbFJlZ2V4IiwicmVtb3ZlIiwibWlzYyIsImpzb25PYmplY3RTZXRLZXlzIiwiZmlsZSIsImZ1bGxQYXRoIiwiam9pbiIsIl9fZGlybmFtZSIsInFmIiwibWluaWZ5IiwiZXJyb3IiXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBLElBQUlBLFlBQVlDLFFBQVEsWUFBUixFQUFzQkQsU0FBdEM7QUFDQSxJQUFJRSxPQUFPRCxRQUFRLE1BQVIsQ0FBWDs7QUFFQUUsT0FBT0MsT0FBUCxHQUFpQjtBQUNmQyxTQUFPO0FBQ0xDLFNBQUtDLElBQUksZUFBSixDQURBO0FBRUxDLGVBQVdELElBQUksc0JBQUosQ0FGTjtBQUdMRSxjQUFVRixJQUFJLG9CQUFKLENBSEw7QUFJTEcsaUJBQWFILElBQUksd0JBQUosQ0FKUjtBQUtMSSxzQkFBa0JKLElBQUksOEJBQUosQ0FMYjtBQU1MSyxZQUFRTCxJQUFJLGtCQUFKO0FBTkgsR0FEUTtBQVNmTSxRQUFNO0FBQ0pDLHVCQUFtQlAsSUFBSSwrQkFBSjtBQURmO0FBVFMsQ0FBakI7O0FBY0E7QUFDQTtBQUNBLFNBQVNBLEdBQVQsQ0FBYVEsSUFBYixFQUFtQjs7QUFFakIsTUFBSUMsV0FBV2QsS0FBS2UsSUFBTCxDQUFVQyxTQUFWLEVBQXFCSCxJQUFyQixDQUFmLENBRmlCLENBRTBCOztBQUUzQyxNQUFJSSxLQUFLLElBQUluQixTQUFKLENBQWNnQixRQUFkLEVBQXdCLEVBQUNJLFFBQVEsSUFBVCxFQUF4QixDQUFUOztBQUVBLE1BQUlELEdBQUdFLEtBQVAsRUFBYztBQUNaLFVBQU1GLEdBQUdFLEtBQVQ7QUFDRDs7QUFFRCxTQUFPRixFQUFQO0FBQ0QiLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBRdWVyeUZpbGUgPSByZXF1aXJlKCdwZy1wcm9taXNlJykuUXVlcnlGaWxlO1xudmFyIHBhdGggPSByZXF1aXJlKCdwYXRoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBhcnJheToge1xuICAgIGFkZDogc3FsKCdhcnJheS9hZGQuc3FsJyksXG4gICAgYWRkVW5pcXVlOiBzcWwoJ2FycmF5L2FkZC11bmlxdWUuc3FsJyksXG4gICAgY29udGFpbnM6IHNxbCgnYXJyYXkvY29udGFpbnMuc3FsJyksXG4gICAgY29udGFpbnNBbGw6IHNxbCgnYXJyYXkvY29udGFpbnMtYWxsLnNxbCcpLFxuICAgIGNvbnRhaW5zQWxsUmVnZXg6IHNxbCgnYXJyYXkvY29udGFpbnMtYWxsLXJlZ2V4LnNxbCcpLFxuICAgIHJlbW92ZTogc3FsKCdhcnJheS9yZW1vdmUuc3FsJylcbiAgfSxcbiAgbWlzYzoge1xuICAgIGpzb25PYmplY3RTZXRLZXlzOiBzcWwoJ21pc2MvanNvbi1vYmplY3Qtc2V0LWtleXMuc3FsJylcbiAgfVxufTtcblxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIEhlbHBlciBmb3IgbGlua2luZyB0byBleHRlcm5hbCBxdWVyeSBmaWxlcztcbmZ1bmN0aW9uIHNxbChmaWxlKSB7XG5cbiAgdmFyIGZ1bGxQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgZmlsZSk7IC8vIGdlbmVyYXRpbmcgZnVsbCBwYXRoO1xuXG4gIHZhciBxZiA9IG5ldyBRdWVyeUZpbGUoZnVsbFBhdGgsIHttaW5pZnk6IHRydWV9KTtcblxuICBpZiAocWYuZXJyb3IpIHtcbiAgICB0aHJvdyBxZi5lcnJvcjtcbiAgfVxuXG4gIHJldHVybiBxZjtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Adapters/Storage/StorageAdapter.js b/lib/Adapters/Storage/StorageAdapter.js index 9a390c31f7..97297a65bc 100644 --- a/lib/Adapters/Storage/StorageAdapter.js +++ b/lib/Adapters/Storage/StorageAdapter.js @@ -1 +1,2 @@ -"use strict"; \ No newline at end of file +"use strict"; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJTdG9yYWdlQWRhcHRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbXX0= \ No newline at end of file diff --git a/lib/Auth.js b/lib/Auth.js index 77d21f59dc..1905aac26b 100644 --- a/lib/Auth.js +++ b/lib/Auth.js @@ -23,14 +23,14 @@ function Auth({ config, isMaster = false, isReadOnly = false, user, installation // Whether this auth could possibly modify the given user id. // It still could be forbidden via ACLs even if this returns true. -Auth.prototype.couldUpdateUserId = function (userId) { +Auth.prototype.isUnauthenticated = function () { if (this.isMaster) { - return true; + return false; } - if (this.user && this.user.id === userId) { - return true; + if (this.user) { + return false; } - return false; + return true; }; // A helper to get a master-level Auth object @@ -65,7 +65,7 @@ var getAuthForSessionToken = function ({ config, sessionToken, installationId } return query.execute().then(response => { var results = response.results; if (results.length !== 1 || !results[0]['user']) { - throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } var now = new Date(), @@ -254,4 +254,5 @@ module.exports = { getAuthForSessionToken, getAuthForLegacySessionToken, createSession -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9BdXRoLmpzIl0sIm5hbWVzIjpbImNyeXB0b1V0aWxzIiwicmVxdWlyZSIsIlJlc3RRdWVyeSIsIlBhcnNlIiwiQXV0aCIsImNvbmZpZyIsImlzTWFzdGVyIiwiaXNSZWFkT25seSIsInVzZXIiLCJpbnN0YWxsYXRpb25JZCIsInVzZXJSb2xlcyIsImZldGNoZWRSb2xlcyIsInJvbGVQcm9taXNlIiwicHJvdG90eXBlIiwiaXNVbmF1dGhlbnRpY2F0ZWQiLCJtYXN0ZXIiLCJyZWFkT25seSIsIm5vYm9keSIsImdldEF1dGhGb3JTZXNzaW9uVG9rZW4iLCJzZXNzaW9uVG9rZW4iLCJjYWNoZUNvbnRyb2xsZXIiLCJnZXQiLCJ0aGVuIiwidXNlckpTT04iLCJjYWNoZWRVc2VyIiwiT2JqZWN0IiwiZnJvbUpTT04iLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlc3RPcHRpb25zIiwibGltaXQiLCJpbmNsdWRlIiwicXVlcnkiLCJleGVjdXRlIiwicmVzcG9uc2UiLCJyZXN1bHRzIiwibGVuZ3RoIiwiRXJyb3IiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJub3ciLCJEYXRlIiwiZXhwaXJlc0F0IiwiaXNvIiwidW5kZWZpbmVkIiwib2JqIiwicGFzc3dvcmQiLCJwdXQiLCJ1c2VyT2JqZWN0IiwiZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbiIsImNsYXNzTmFtZSIsImdldFVzZXJSb2xlcyIsIl9sb2FkUm9sZXMiLCJjYWNoZUFkYXB0ZXIiLCJyb2xlIiwiaWQiLCJjYWNoZWRSb2xlcyIsInJlc3RXaGVyZSIsIl9fdHlwZSIsIm9iamVjdElkIiwiQXJyYXkiLCJyb2xlc01hcCIsInJlZHVjZSIsIm0iLCJyIiwibmFtZXMiLCJwdXNoIiwibmFtZSIsImlkcyIsIl9nZXRBbGxSb2xlc05hbWVzRm9yUm9sZUlkcyIsInJvbGVOYW1lcyIsIm1hcCIsInJvbGVJRHMiLCJxdWVyaWVkUm9sZXMiLCJpbnMiLCJmaWx0ZXIiLCJyb2xlSUQiLCJTZXQiLCJyZXN1bHRNYXAiLCJtZW1vIiwiY29uY2F0IiwiY3JlYXRlU2Vzc2lvbiIsInVzZXJJZCIsImNyZWF0ZWRXaXRoIiwiYWRkaXRpb25hbFNlc3Npb25EYXRhIiwidG9rZW4iLCJuZXdUb2tlbiIsImdlbmVyYXRlU2Vzc2lvbkV4cGlyZXNBdCIsInNlc3Npb25EYXRhIiwicmVzdHJpY3RlZCIsIl9lbmNvZGUiLCJhc3NpZ24iLCJSZXN0V3JpdGUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLE1BQU1BLGNBQWNDLFFBQVEsZUFBUixDQUFwQjtBQUNBLE1BQU1DLFlBQVlELFFBQVEsYUFBUixDQUFsQjtBQUNBLE1BQU1FLFFBQVFGLFFBQVEsWUFBUixDQUFkOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVNHLElBQVQsQ0FBYyxFQUFFQyxNQUFGLEVBQVVDLFdBQVcsS0FBckIsRUFBNEJDLGFBQWEsS0FBekMsRUFBZ0RDLElBQWhELEVBQXNEQyxjQUF0RCxLQUF5RSxFQUF2RixFQUEyRjtBQUN6RixPQUFLSixNQUFMLEdBQWNBLE1BQWQ7QUFDQSxPQUFLSSxjQUFMLEdBQXNCQSxjQUF0QjtBQUNBLE9BQUtILFFBQUwsR0FBZ0JBLFFBQWhCO0FBQ0EsT0FBS0UsSUFBTCxHQUFZQSxJQUFaO0FBQ0EsT0FBS0QsVUFBTCxHQUFrQkEsVUFBbEI7O0FBRUE7QUFDQTtBQUNBLE9BQUtHLFNBQUwsR0FBaUIsRUFBakI7QUFDQSxPQUFLQyxZQUFMLEdBQW9CLEtBQXBCO0FBQ0EsT0FBS0MsV0FBTCxHQUFtQixJQUFuQjtBQUNEOztBQUVEO0FBQ0E7QUFDQVIsS0FBS1MsU0FBTCxDQUFlQyxpQkFBZixHQUFtQyxZQUFXO0FBQzVDLE1BQUksS0FBS1IsUUFBVCxFQUFtQjtBQUNqQixXQUFPLEtBQVA7QUFDRDtBQUNELE1BQUksS0FBS0UsSUFBVCxFQUFlO0FBQ2IsV0FBTyxLQUFQO0FBQ0Q7QUFDRCxTQUFPLElBQVA7QUFDRCxDQVJEOztBQVVBO0FBQ0EsU0FBU08sTUFBVCxDQUFnQlYsTUFBaEIs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RGdCLFNBQU9pRSxNQUFQLENBQWNILFdBQWQsRUFBMkJKLHFCQUEzQjtBQUNBO0FBQ0EsUUFBTVEsWUFBWTFGLFFBQVEsYUFBUixDQUFsQjs7QUFFQSxTQUFPO0FBQ0xzRixlQURLO0FBRUxQLG1CQUFlLE1BQU0sSUFBSVcsU0FBSixDQUFjdEYsTUFBZCxFQUFzQlUsT0FBT1YsTUFBUCxDQUF0QixFQUFzQyxVQUF0QyxFQUFrRCxJQUFsRCxFQUF3RGtGLFdBQXhELEVBQXFFdEQsT0FBckU7QUFGaEIsR0FBUDtBQUlELENBaENEOztBQWtDQTJELE9BQU9DLE9BQVAsR0FBaUI7QUFDZnpGLE1BRGU7QUFFZlcsUUFGZTtBQUdmRSxRQUhlO0FBSWZELFVBSmU7QUFLZkUsd0JBTGU7QUFNZjhCLDhCQU5lO0FBT2ZnQztBQVBlLENBQWpCIiwiZmlsZSI6IkF1dGguanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBjcnlwdG9VdGlscyA9IHJlcXVpcmUoJy4vY3J5cHRvVXRpbHMnKTtcbmNvbnN0IFJlc3RRdWVyeSA9IHJlcXVpcmUoJy4vUmVzdFF1ZXJ5Jyk7XG5jb25zdCBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKTtcblxuLy8gQW4gQXV0aCBvYmplY3QgdGVsbHMgeW91IHdobyBpcyByZXF1ZXN0aW5nIHNvbWV0aGluZyBhbmQgd2hldGhlclxuLy8gdGhlIG1hc3RlciBrZXkgd2FzIHVzZWQuXG4vLyB1c2VyT2JqZWN0IGlzIGEgUGFyc2UuVXNlciBhbmQgY2FuIGJlIG51bGwgaWYgdGhlcmUncyBubyB1c2VyLlxuZnVuY3Rpb24gQXV0aCh7IGNvbmZpZywgaXNNYXN0ZXIgPSBmYWxzZSwgaXNSZWFkT25seSA9IGZhbHNlLCB1c2VyLCBpbnN0YWxsYXRpb25JZCB9ID0ge30pIHtcbiAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gIHRoaXMuaW5zdGFsbGF0aW9uSWQgPSBpbnN0YWxsYXRpb25JZDtcbiAgdGhpcy5pc01hc3RlciA9IGlzTWFzdGVyO1xuICB0aGlzLnVzZXIgPSB1c2VyO1xuICB0aGlzLmlzUmVhZE9ubHkgPSBpc1JlYWRPbmx5O1xuXG4gIC8vIEFzc3VtaW5nIGEgdXNlcnMgcm9sZXMgd29uJ3QgY2hhbmdlIGR1cmluZyBhIHNpbmdsZSByZXF1ZXN0LCB3ZSdsbFxuICAvLyBvbmx5IGxvYWQgdGhlbSBvbmNlLlxuICB0aGlzLnVzZXJSb2xlcyA9IFtdO1xuICB0aGlzLmZldGNoZWRSb2xlcyA9IGZhbHNlO1xuICB0aGlzLnJvbGVQcm9taXNlID0gbnVsbDtcbn1cblxuLy8gV2hldGhlciB0aGlzIGF1dGggY291bGQgcG9zc2libHkgbW9kaWZ5IHRoZSBnaXZlbiB1c2VyIGlkLlxuLy8gSXQgc3RpbGwgY291bGQgYmUgZm9yYmlkZGVuIHZpYSBBQ0xzIGV2ZW4gaWYgdGhpcyByZXR1cm5zIHRydWUuXG5BdXRoLnByb3RvdHlwZS5pc1VuYXV0aGVudGljYXRlZCA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5pc01hc3Rlcikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAodGhpcy51c2VyKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufTtcblxuLy8gQSBoZWxwZXIgdG8gZ2V0IGEgbWFzdGVyLWxldmVsIEF1dGggb2JqZWN0XG5mdW5jdGlvbiBtYXN0ZXIoY29uZmlnKSB7XG4gIHJldHVybiBuZXcgQXV0aCh7IGNvbmZpZywgaXNNYXN0ZXI6IHRydWUgfSk7XG59XG5cbi8vIEEgaGVscGVyIHRvIGdldCBhIG1hc3Rlci1sZXZlbCBBdXRoIG9iamVjdFxuZnVuY3Rpb24gcmVhZE9ubHkoY29uZmlnKSB7XG4gIHJldHVybiBuZXcgQXV0aCh7IGNvbmZpZywgaXNNYXN0ZXI6IHRydWUsIGlzUmVhZE9ubHk6IHRydWUgfSk7XG59XG5cbi8vIEEgaGVscGVyIHRvIGdldCBhIG5vYm9keS1sZXZlbCBBdXRoIG9iamVjdFxuZnVuY3Rpb24gbm9ib2R5KGNvbmZpZykge1xuICByZXR1cm4gbmV3IEF1dGgoeyBjb25maWcsIGlzTWFzdGVyOiBmYWxzZSB9KTtcbn1cblxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIEF1dGggb2JqZWN0XG52YXIgZ2V0QXV0aEZvclNlc3Npb25Ub2tlbiA9IGZ1bmN0aW9uKHsgY29uZmlnLCBzZXNzaW9uVG9rZW4sIGluc3RhbGxhdGlvbklkIH0gPSB7fSkge1xuICByZXR1cm4gY29uZmlnLmNhY2hlQ29udHJvbGxlci51c2VyLmdldChzZXNzaW9uVG9rZW4pLnRoZW4oKHVzZXJKU09OKSA9PiB7XG4gICAgaWYgKHVzZXJKU09OKSB7XG4gICAgICBjb25zdCBjYWNoZWRVc2VyID0gUGFyc2UuT2JqZWN0LmZyb21KU09OKHVzZXJKU09OKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEF1dGgoe2NvbmZpZywgaXNNYXN0ZXI6IGZhbHNlLCBpbnN0YWxsYXRpb25JZCwgdXNlcjogY2FjaGVkVXNlcn0pKTtcbiAgICB9XG5cbiAgICB2YXIgcmVzdE9wdGlvbnMgPSB7XG4gICAgICBsaW1pdDogMSxcbiAgICAgIGluY2x1ZGU6ICd1c2VyJ1xuICAgIH07XG5cbiAgICB2YXIgcXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfU2Vzc2lvbicsIHtzZXNzaW9uVG9rZW59LCByZXN0T3B0aW9ucyk7XG4gICAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgdmFyIHJlc3VsdHMgPSByZXNwb25zZS5yZXN1bHRzO1xuICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9PSAxIHx8ICFyZXN1bHRzWzBdWyd1c2VyJ10pIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTiwgJ0ludmFsaWQgc2Vzc2lvbiB0b2tlbicpO1xuICAgICAgfVxuXG4gICAgICB2YXIgbm93ID0gbmV3IERhdGUoKSxcbiAgICAgICAgZXhwaXJlc0F0ID0gcmVzdWx0c1swXS5leHBpcmVzQXQgPyBuZXcgRGF0ZShyZXN1bHRzWzBdLmV4cGlyZXNBdC5pc28pIDogdW5kZWZpbmVkO1xuICAgICAgaWYgKGV4cGlyZXNBdCA8IG5vdykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICdTZXNzaW9uIHRva2VuIGlzIGV4cGlyZWQuJyk7XG4gICAgICB9XG4gICAgICB2YXIgb2JqID0gcmVzdWx0c1swXVsndXNlciddO1xuICAgICAgZGVsZXRlIG9iai5wYXNzd29yZDtcbiAgICAgIG9ialsnY2xhc3NOYW1lJ10gPSAnX1VzZXInO1xuICAgICAgb2JqWydzZXNzaW9uVG9rZW4nXSA9IHNlc3Npb25Ub2tlbjtcbiAgICAgIGNvbmZpZy5jYWNoZUNvbnRyb2xsZXIudXNlci5wdXQoc2Vzc2lvblRva2VuLCBvYmopO1xuICAgICAgY29uc3QgdXNlck9iamVjdCA9IFBhcnNlLk9iamVjdC5mcm9tSlNPTihvYmopO1xuICAgICAgcmV0dXJuIG5ldyBBdXRoKHtjb25maWcsIGlzTWFzdGVyOiBmYWxzZSwgaW5zdGFsbGF0aW9uSWQsIHVzZXI6IHVzZXJPYmplY3R9KTtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG52YXIgZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbiA9IGZ1bmN0aW9uKHtjb25maWcsIHNlc3Npb25Ub2tlbiwgaW5zdGFsbGF0aW9uSWQgfSA9IHt9KSB7XG4gIHZhciByZXN0T3B0aW9ucyA9IHtcbiAgICBsaW1pdDogMVxuICB9O1xuICB2YXIgcXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfVXNlcicsIHsgc2Vzc2lvblRva2VuOiBzZXNzaW9uVG9rZW59LCByZXN0T3B0aW9ucyk7XG4gIHJldHVybiBxdWVyeS5leGVjdXRlKCkudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICB2YXIgcmVzdWx0cyA9IHJlc3BvbnNlLnJlc3VsdHM7XG4gICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLCAnaW52YWxpZCBsZWdhY3kgc2Vzc2lvbiB0b2tlbicpO1xuICAgIH1cbiAgICBjb25zdCBvYmogPSByZXN1bHRzWzBdO1xuICAgIG9iai5jbGFzc05hbWUgPSAnX1VzZXInO1xuICAgIGNvbnN0IHVzZXJPYmplY3QgPSBQYXJzZS5PYmplY3QuZnJvbUpTT04ob2JqKTtcbiAgICByZXR1cm4gbmV3IEF1dGgoe2NvbmZpZywgaXNNYXN0ZXI6IGZhbHNlLCBpbnN0YWxsYXRpb25JZCwgdXNlcjogdXNlck9iamVjdH0pO1xuICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiByb2xlIG5hbWVzXG5BdXRoLnByb3RvdHlwZS5nZXRVc2VyUm9sZXMgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuaXNNYXN0ZXIgfHwgIXRoaXMudXNlcikge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoW10pO1xuICB9XG4gIGlmICh0aGlzLmZldGNoZWRSb2xlcykge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy51c2VyUm9sZXMpO1xuICB9XG4gIGlmICh0aGlzLnJvbGVQcm9taXNlKSB7XG4gICAgcmV0dXJuIHRoaXMucm9sZVByb21pc2U7XG4gIH1cbiAgdGhpcy5yb2xlUHJvbWlzZSA9IHRoaXMuX2xvYWRSb2xlcygpO1xuICByZXR1cm4gdGhpcy5yb2xlUHJvbWlzZTtcbn07XG5cbi8vIEl0ZXJhdGVzIHRocm91Z2ggdGhlIHJvbGUgdHJlZSBhbmQgY29tcGlsZXMgYSB1c2VycyByb2xlc1xuQXV0aC5wcm90b3R5cGUuX2xvYWRSb2xlcyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgY2FjaGVBZGFwdGVyID0gdGhpcy5jb25maWcuY2FjaGVDb250cm9sbGVyO1xuICByZXR1cm4gY2FjaGVBZGFwdGVyLnJvbGUuZ2V0KHRoaXMudXNlci5pZCkudGhlbigoY2FjaGVkUm9sZXMpID0+IHtcbiAgICBpZiAoY2FjaGVkUm9sZXMgIT0gbnVsbCkge1xuICAgICAgdGhpcy5mZXRjaGVkUm9sZXMgPSB0cnVlO1xuICAgICAgdGhpcy51c2VyUm9sZXMgPSBjYWNoZWRSb2xlcztcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoY2FjaGVkUm9sZXMpO1xuICAgIH1cblxuICAgIHZhciByZXN0V2hlcmUgPSB7XG4gICAgICAndXNlcnMnOiB7XG4gICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICBjbGFzc05hbWU6ICdfVXNlcicsXG4gICAgICAgIG9iamVjdElkOiB0aGlzLnVzZXIuaWRcbiAgICAgIH1cbiAgICB9O1xuICAgIC8vIEZpcnN0IGdldCB0aGUgcm9sZSBpZHMgdGhpcyB1c2VyIGlzIGRpcmVjdGx5IGEgbWVtYmVyIG9mXG4gICAgdmFyIHF1ZXJ5ID0gbmV3IFJlc3RRdWVyeSh0aGlzLmNvbmZpZywgbWFzdGVyKHRoaXMuY29uZmlnKSwgJ19Sb2xlJywgcmVzdFdoZXJlLCB7fSk7XG4gICAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgdmFyIHJlc3VsdHMgPSByZXNwb25zZS5yZXN1bHRzO1xuICAgICAgaWYgKCFyZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLnVzZXJSb2xlcyA9IFtdO1xuICAgICAgICB0aGlzLmZldGNoZWRSb2xlcyA9IHRydWU7XG4gICAgICAgIHRoaXMucm9sZVByb21pc2UgPSBudWxsO1xuXG4gICAgICAgIGNhY2hlQWRhcHRlci5yb2xlLnB1dCh0aGlzLnVzZXIuaWQsIEFycmF5KC4uLnRoaXMudXNlclJvbGVzKSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy51c2VyUm9sZXMpO1xuICAgICAgfVxuICAgICAgdmFyIHJvbGVzTWFwID0gcmVzdWx0cy5yZWR1Y2UoKG0sIHIpID0+IHtcbiAgICAgICAgbS5uYW1lcy5wdXNoKHIubmFtZSk7XG4gICAgICAgIG0uaWRzLnB1c2goci5vYmplY3RJZCk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfSwge2lkczogW10sIG5hbWVzOiBbXX0pO1xuXG4gICAgICAvLyBydW4gdGhlIHJlY3Vyc2l2ZSBmaW5kaW5nXG4gICAgICByZXR1cm4gdGhpcy5fZ2V0QWxsUm9sZXNOYW1lc0ZvclJvbGVJZHMocm9sZXNNYXAuaWRzLCByb2xlc01hcC5uYW1lcylcbiAgICAgICAgLnRoZW4oKHJvbGVOYW1lcykgPT4ge1xuICAgICAgICAgIHRoaXMudXNlclJvbGVzID0gcm9sZU5hbWVzLm1hcCgocikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICdyb2xlOicgKyByO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMuZmV0Y2hlZFJvbGVzID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLnJvbGVQcm9taXNlID0gbnVsbDtcbiAgICAgICAgICBjYWNoZUFkYXB0ZXIucm9sZS5wdXQodGhpcy51c2VyLmlkLCBBcnJheSguLi50aGlzLnVzZXJSb2xlcykpO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy51c2VyUm9sZXMpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG4vLyBHaXZlbiBhIGxpc3Qgb2Ygcm9sZUlkcywgZmluZCBhbGwgdGhlIHBhcmVudCByb2xlcywgcmV0dXJucyBhIHByb21pc2Ugd2l0aCBhbGwgbmFtZXNcbkF1dGgucHJvdG90eXBlLl9nZXRBbGxSb2xlc05hbWVzRm9yUm9sZUlkcyA9IGZ1bmN0aW9uKHJvbGVJRHMsIG5hbWVzID0gW10sIHF1ZXJpZWRSb2xlcyA9IHt9KSB7XG4gIGNvbnN0IGlucyA9IHJvbGVJRHMuZmlsdGVyKChyb2xlSUQpID0+IHtcbiAgICByZXR1cm4gcXVlcmllZFJvbGVzW3JvbGVJRF0gIT09IHRydWU7XG4gIH0pLm1hcCgocm9sZUlEKSA9PiB7XG4gICAgLy8gbWFyayBhcyBxdWVyaWVkXG4gICAgcXVlcmllZFJvbGVzW3JvbGVJRF0gPSB0cnVlO1xuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgIGNsYXNzTmFtZTogJ19Sb2xlJyxcbiAgICAgIG9iamVjdElkOiByb2xlSURcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGFsbCByb2xlcyBhcmUgYWNjb3VudGVkIGZvciwgcmV0dXJuIHRoZSBuYW1lc1xuICBpZiAoaW5zLmxlbmd0aCA9PSAwKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShbLi4ubmV3IFNldChuYW1lcyldKTtcbiAgfVxuICAvLyBCdWlsZCBhbiBPUiBxdWVyeSBhY3Jvc3MgYWxsIHBhcmVudFJvbGVzXG4gIGxldCByZXN0V2hlcmU7XG4gIGlmIChpbnMubGVuZ3RoID09IDEpIHtcbiAgICByZXN0V2hlcmUgPSB7ICdyb2xlcyc6IGluc1swXSB9O1xuICB9IGVsc2Uge1xuICAgIHJlc3RXaGVyZSA9IHsgJ3JvbGVzJzogeyAnJGluJzogaW5zIH19XG4gIH1cbiAgY29uc3QgcXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KHRoaXMuY29uZmlnLCBtYXN0ZXIodGhpcy5jb25maWcpLCAnX1JvbGUnLCByZXN0V2hlcmUsIHt9KTtcbiAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgIHZhciByZXN1bHRzID0gcmVzcG9uc2UucmVzdWx0cztcbiAgICAvLyBOb3RoaW5nIGZvdW5kXG4gICAgaWYgKCFyZXN1bHRzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuYW1lcyk7XG4gICAgfVxuICAgIC8vIE1hcCB0aGUgcmVzdWx0cyB3aXRoIGFsbCBJZHMgYW5kIG5hbWVzXG4gICAgY29uc3QgcmVzdWx0TWFwID0gcmVzdWx0cy5yZWR1Y2UoKG1lbW8sIHJvbGUpID0+IHtcbiAgICAgIG1lbW8ubmFtZXMucHVzaChyb2xlLm5hbWUpO1xuICAgICAgbWVtby5pZHMucHVzaChyb2xlLm9iamVjdElkKTtcbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH0sIHtpZHM6IFtdLCBuYW1lczogW119KTtcbiAgICAvLyBzdG9yZSB0aGUgbmV3IGZvdW5kIG5hbWVzXG4gICAgbmFtZXMgPSBuYW1lcy5jb25jYXQocmVzdWx0TWFwLm5hbWVzKTtcbiAgICAvLyBmaW5kIHRoZSBuZXh0IG9uZXMsIGNpcmN1bGFyIHJvbGVzIHdpbGwgYmUgY3V0XG4gICAgcmV0dXJuIHRoaXMuX2dldEFsbFJvbGVzTmFtZXNGb3JSb2xlSWRzKHJlc3VsdE1hcC5pZHMsIG5hbWVzLCBxdWVyaWVkUm9sZXMpXG4gIH0pLnRoZW4oKG5hbWVzKSA9PiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShbLi4ubmV3IFNldChuYW1lcyldKVxuICB9KVxufVxuXG5jb25zdCBjcmVhdGVTZXNzaW9uID0gZnVuY3Rpb24oY29uZmlnLCB7XG4gIHVzZXJJZCxcbiAgY3JlYXRlZFdpdGgsXG4gIGluc3RhbGxhdGlvbklkLFxuICBhZGRpdGlvbmFsU2Vzc2lvbkRhdGEsXG59KSB7XG4gIGNvbnN0IHRva2VuID0gJ3I6JyArIGNyeXB0b1V0aWxzLm5ld1Rva2VuKCk7XG4gIGNvbnN0IGV4cGlyZXNBdCA9IGNvbmZpZy5nZW5lcmF0ZVNlc3Npb25FeHBpcmVzQXQoKTtcbiAgY29uc3Qgc2Vzc2lvbkRhdGEgPSB7XG4gICAgc2Vzc2lvblRva2VuOiB0b2tlbixcbiAgICB1c2VyOiB7XG4gICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgIGNsYXNzTmFtZTogJ19Vc2VyJyxcbiAgICAgIG9iamVjdElkOiB1c2VySWRcbiAgICB9LFxuICAgIGNyZWF0ZWRXaXRoLFxuICAgIHJlc3RyaWN0ZWQ6IGZhbHNlLFxuICAgIGV4cGlyZXNBdDogUGFyc2UuX2VuY29kZShleHBpcmVzQXQpXG4gIH07XG5cbiAgaWYgKGluc3RhbGxhdGlvbklkKSB7XG4gICAgc2Vzc2lvbkRhdGEuaW5zdGFsbGF0aW9uSWQgPSBpbnN0YWxsYXRpb25JZFxuICB9XG5cbiAgT2JqZWN0LmFzc2lnbihzZXNzaW9uRGF0YSwgYWRkaXRpb25hbFNlc3Npb25EYXRhKTtcbiAgLy8gV2UgbmVlZCB0byBpbXBvcnQgUmVzdFdyaXRlIGF0IHRoaXMgcG9pbnQgZm9yIHRoZSBjeWNsaWMgZGVwZW5kZW5jeSBpdCBoYXMgdG8gaXRcbiAgY29uc3QgUmVzdFdyaXRlID0gcmVxdWlyZSgnLi9SZXN0V3JpdGUnKTtcblxuICByZXR1cm4ge1xuICAgIHNlc3Npb25EYXRhLFxuICAgIGNyZWF0ZVNlc3Npb246ICgpID0+IG5ldyBSZXN0V3JpdGUoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19TZXNzaW9uJywgbnVsbCwgc2Vzc2lvbkRhdGEpLmV4ZWN1dGUoKVxuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBBdXRoLFxuICBtYXN0ZXIsXG4gIG5vYm9keSxcbiAgcmVhZE9ubHksXG4gIGdldEF1dGhGb3JTZXNzaW9uVG9rZW4sXG4gIGdldEF1dGhGb3JMZWdhY3lTZXNzaW9uVG9rZW4sXG4gIGNyZWF0ZVNlc3Npb24sXG59O1xuIl19 \ No newline at end of file diff --git a/lib/ClientSDK.js b/lib/ClientSDK.js index 6e029ceb07..a89dd54ddd 100644 --- a/lib/ClientSDK.js +++ b/lib/ClientSDK.js @@ -39,4 +39,5 @@ module.exports = { compatible, supportsForwardDelete, fromString -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9DbGllbnRTREsuanMiXSwibmFtZXMiOlsic2VtdmVyIiwicmVxdWlyZSIsImNvbXBhdGlibGUiLCJjb21wYXRpYmxlU0RLIiwiY2xpZW50U0RLIiwiZnJvbVN0cmluZyIsImNsaWVudFZlcnNpb24iLCJ2ZXJzaW9uIiwiY29tcGF0aWJsaXR5VmVyc2lvbiIsInNkayIsInNhdGlzZmllcyIsInN1cHBvcnRzRm9yd2FyZERlbGV0ZSIsImpzIiwidmVyc2lvblJFIiwibWF0Y2giLCJ0b0xvd2VyQ2FzZSIsImxlbmd0aCIsInVuZGVmaW5lZCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUEsSUFBSUEsU0FBU0MsUUFBUSxRQUFSLENBQWI7O0FBRUEsU0FBU0MsVUFBVCxDQUFvQkMsYUFBcEIsRUFBbUM7QUFDakMsU0FBTyxVQUFTQyxTQUFULEVBQW9CO0FBQ3pCLFFBQUksT0FBT0EsU0FBUCxLQUFxQixRQUF6QixFQUFtQztBQUNqQ0Esa0JBQVlDLFdBQVdELFNBQVgsQ0FBWjtBQUNEO0FBQ0Q7QUFDQSxRQUFJLENBQUNBLFNBQUwsRUFBZ0I7QUFDZCxhQUFPLElBQVA7QUFDRDtBQUNELFVBQU1FLGdCQUFnQkYsVUFBVUcsT0FBaEM7QUFDQSxVQUFNQyxzQkFBc0JMLGNBQWNDLFVBQVVLLEdBQXhCLENBQTVCO0FBQ0EsV0FBT1QsT0FBT1UsU0FBUCxDQUFpQkosYUFBakIsRUFBZ0NFLG1CQUFoQyxDQUFQO0FBQ0QsR0FYRDtBQVlEOztBQUVELFNBQVNHLHFCQUFULENBQStCUCxTQUEvQixFQUEwQztBQUN4QyxTQUFPRixXQUFXO0FBQ2hCVSxRQUFJO0FBRFksR0FBWCxFQUVKUixTQUZJLENBQVA7QUFHRDs7QUFFRCxTQUFTQyxVQUFULENBQW9CRSxPQUFwQixFQUE2QjtBQUMzQixRQUFNTSxZQUFZLHdCQUFsQjtBQUNBLFFBQU1DLFFBQVFQLFFBQVFRLFdBQVIsR0FBc0JELEtBQXRCLENBQTRCRCxTQUE1QixDQUFkO0FBQ0EsTUFBSUMsU0FBU0EsTUFBTUUsTUFBTixLQUFpQixDQUE5QixFQUFpQztBQUMvQixXQUFPO0FBQ0xQLFdBQUtLLE1BQU0sQ0FBTixDQURBO0FBRUxQLGVBQVNPLE1BQU0sQ0FBTjtBQUZKLEtBQVA7QUFJRDtBQUNELFNBQU9HLFNBQVA7QUFDRDs7QUFFREMsT0FBT0MsT0FBUCxHQUFpQjtBQUNmakIsWUFEZTtBQUVmUyx1QkFGZTtBQUdmTjtBQUhlLENBQWpCIiwiZmlsZSI6IkNsaWVudFNESy5qcyIsInNvdXJjZXNDb250ZW50IjpbInZhciBzZW12ZXIgPSByZXF1aXJlKCdzZW12ZXInKTtcblxuZnVuY3Rpb24gY29tcGF0aWJsZShjb21wYXRpYmxlU0RLKSB7XG4gIHJldHVybiBmdW5jdGlvbihjbGllbnRTREspIHtcbiAgICBpZiAodHlwZW9mIGNsaWVudFNESyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNsaWVudFNESyA9IGZyb21TdHJpbmcoY2xpZW50U0RLKTtcbiAgICB9XG4gICAgLy8gUkVTVCBBUEksIG9yIGN1c3RvbSBTREtcbiAgICBpZiAoIWNsaWVudFNESykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IGNsaWVudFZlcnNpb24gPSBjbGllbnRTREsudmVyc2lvbjtcbiAgICBjb25zdCBjb21wYXRpYmxpdHlWZXJzaW9uID0gY29tcGF0aWJsZVNES1tjbGllbnRTREsuc2RrXTtcbiAgICByZXR1cm4gc2VtdmVyLnNhdGlzZmllcyhjbGllbnRWZXJzaW9uLCBjb21wYXRpYmxpdHlWZXJzaW9uKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzdXBwb3J0c0ZvcndhcmREZWxldGUoY2xpZW50U0RLKSB7XG4gIHJldHVybiBjb21wYXRpYmxlKHtcbiAgICBqczogJz49MS45LjAnXG4gIH0pKGNsaWVudFNESyk7XG59XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmcodmVyc2lvbikge1xuICBjb25zdCB2ZXJzaW9uUkUgPSAvKFstYS16QS1aXSspKFswLTlcXC5dKykvO1xuICBjb25zdCBtYXRjaCA9IHZlcnNpb24udG9Mb3dlckNhc2UoKS5tYXRjaCh2ZXJzaW9uUkUpO1xuICBpZiAobWF0Y2ggJiYgbWF0Y2gubGVuZ3RoID09PSAzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNkazogbWF0Y2hbMV0sXG4gICAgICB2ZXJzaW9uOiBtYXRjaFsyXVxuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgY29tcGF0aWJsZSxcbiAgc3VwcG9ydHNGb3J3YXJkRGVsZXRlLFxuICBmcm9tU3RyaW5nXG59XG4iXX0= \ No newline at end of file diff --git a/lib/Config.js b/lib/Config.js index 71c74906e1..83218c8b9a 100644 --- a/lib/Config.js +++ b/lib/Config.js @@ -289,4 +289,5 @@ class Config { exports.Config = Config; exports.default = Config; -module.exports = Config; \ No newline at end of file +module.exports = Config; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Db25maWcuanMiXSwibmFtZXMiOlsicmVtb3ZlVHJhaWxpbmdTbGFzaCIsInN0ciIsImVuZHNXaXRoIiwic3Vic3RyIiwibGVuZ3RoIiwiQ29uZmlnIiwiZ2V0IiwiYXBwbGljYXRpb25JZCIsIm1vdW50IiwiY2FjaGVJbmZvIiwiQXBwQ2FjaGUiLCJjb25maWciLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsImtleSIsInNjaGVtYUNhY2hlIiwiU2NoZW1hQ2FjaGUiLCJjYWNoZUNvbnRyb2xsZXIiLCJzY2hlbWFDYWNoZVRUTCIsImVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlIiwiZGF0YWJhc2UiLCJEYXRhYmFzZUNvbnRyb2xsZXIiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJhZGFwdGVyIiwiZ2VuZXJhdGVTZXNzaW9uRXhwaXJlc0F0IiwiYmluZCIsImdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbkV4cGlyZXNBdCIsInB1dCIsInNlcnZlckNvbmZpZ3VyYXRpb24iLCJ2YWxpZGF0ZSIsImFwcElkIiwic2V0dXBQYXNzd29yZFZhbGlkYXRvciIsInBhc3N3b3JkUG9saWN5IiwidmVyaWZ5VXNlckVtYWlscyIsInVzZXJDb250cm9sbGVyIiwiYXBwTmFtZSIsInB1YmxpY1NlcnZlclVSTCIsInJldm9rZVNlc3Npb25PblBhc3N3b3JkUmVzZXQiLCJleHBpcmVJbmFjdGl2ZVNlc3Npb25zIiwic2Vzc2lvbkxlbmd0aCIsIm1heExpbWl0IiwiZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJhY2NvdW50TG9ja291dCIsIm1hc3RlcktleUlwcyIsIm1hc3RlcktleSIsInJlYWRPbmx5TWFzdGVyS2V5IiwiRXJyb3IiLCJlbWFpbEFkYXB0ZXIiLCJ2YWxpZGF0ZUVtYWlsQ29uZmlndXJhdGlvbiIsInZhbGlkYXRlQWNjb3VudExvY2tvdXRQb2xpY3kiLCJ2YWxpZGF0ZVBhc3N3b3JkUG9saWN5Iiwic3RhcnRzV2l0aCIsInZhbGlkYXRlU2Vzc2lvbkNvbmZpZ3VyYXRpb24iLCJ2YWxpZGF0ZU1hc3RlcktleUlwcyIsInZhbGlkYXRlTWF4TGltaXQiLCJkdXJhdGlvbiIsIk51bWJlciIsImlzSW50ZWdlciIsInRocmVzaG9sZCIsIm1heFBhc3N3b3JkQWdlIiwidW5kZWZpbmVkIiwicmVzZXRUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJ2YWxpZGF0b3JQYXR0ZXJuIiwiUmVnRXhwIiwidmFsaWRhdG9yQ2FsbGJhY2siLCJkb05vdEFsbG93VXNlcm5hbWUiLCJtYXhQYXNzd29yZEhpc3RvcnkiLCJwYXR0ZXJuVmFsaWRhdG9yIiwidmFsdWUiLCJ0ZXN0IiwiaXNOYU4iLCJpcCIsIm5ldCIsImlzSVAiLCJfbW91bnQiLCJuZXdWYWx1ZSIsIm5vdyIsIkRhdGUiLCJnZXRUaW1lIiwiZ2VuZXJhdGVQYXNzd29yZFJlc2V0VG9rZW5FeHBpcmVzQXQiLCJpbnZhbGlkTGlua1VSTCIsImN1c3RvbVBhZ2VzIiwiaW52YWxpZExpbmsiLCJpbnZhbGlkVmVyaWZpY2F0aW9uTGlua1VSTCIsImludmFsaWRWZXJpZmljYXRpb25MaW5rIiwibGlua1NlbmRTdWNjZXNzVVJMIiwibGlua1NlbmRTdWNjZXNzIiwibGlua1NlbmRGYWlsVVJMIiwibGlua1NlbmRGYWlsIiwidmVyaWZ5RW1haWxTdWNjZXNzVVJMIiwidmVyaWZ5RW1haWxTdWNjZXNzIiwiY2hvb3NlUGFzc3dvcmRVUkwiLCJjaG9vc2VQYXNzd29yZCIsInJlcXVlc3RSZXNldFBhc3N3b3JkVVJMIiwicGFzc3dvcmRSZXNldFN1Y2Nlc3NVUkwiLCJwYXNzd29yZFJlc2V0U3VjY2VzcyIsInBhcnNlRnJhbWVVUkwiLCJ2ZXJpZnlFbWFpbFVSTCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFJQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBUEE7QUFDQTtBQUNBOztBQU9BLFNBQVNBLG1CQUFULENBQTZCQyxHQUE3QixFQUFrQztBQUNoQyxNQUFJLENBQUNB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bUQsZUFBSixHQUFzQjtBQUNwQixXQUFPLEtBQUtOLFdBQUwsQ0FBaUJPLFlBQWpCLElBQWtDLEdBQUUsS0FBS3BELGVBQWdCLDJCQUFoRTtBQUNEOztBQUVELE1BQUlxRCxxQkFBSixHQUE0QjtBQUMxQixXQUFPLEtBQUtSLFdBQUwsQ0FBaUJTLGtCQUFqQixJQUF3QyxHQUFFLEtBQUt0RCxlQUFnQixpQ0FBdEU7QUFDRDs7QUFFRCxNQUFJdUQsaUJBQUosR0FBd0I7QUFDdEIsV0FBTyxLQUFLVixXQUFMLENBQWlCVyxjQUFqQixJQUFvQyxHQUFFLEtBQUt4RCxlQUFnQix1QkFBbEU7QUFDRDs7QUFFRCxNQUFJeUQsdUJBQUosR0FBOEI7QUFDNUIsV0FBUSxHQUFFLEtBQUt6RCxlQUFnQixTQUFRLEtBQUs5QixhQUFjLHlCQUExRDtBQUNEOztBQUVELE1BQUl3Rix1QkFBSixHQUE4QjtBQUM1QixXQUFPLEtBQUtiLFdBQUwsQ0FBaUJjLG9CQUFqQixJQUEwQyxHQUFFLEtBQUszRCxlQUFnQixtQ0FBeEU7QUFDRDs7QUFFRCxNQUFJNEQsYUFBSixHQUFvQjtBQUNsQixXQUFPLEtBQUtmLFdBQUwsQ0FBaUJlLGFBQXhCO0FBQ0Q7O0FBRUQsTUFBSUMsY0FBSixHQUFxQjtBQUNuQixXQUFRLEdBQUUsS0FBSzdELGVBQWdCLFNBQVEsS0FBSzlCLGFBQWMsZUFBMUQ7QUFDRDtBQTNQaUI7O1FBQVBGLE0sR0FBQUEsTTtrQkE4UEVBLE07O0FBQ2Y4RixPQUFPQyxPQUFQLEdBQWlCL0YsTUFBakIiLCJmaWxlIjoiQ29uZmlnLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQSBDb25maWcgb2JqZWN0IHByb3ZpZGVzIGluZm9ybWF0aW9uIGFib3V0IGhvdyBhIHNwZWNpZmljIGFwcCBpc1xuLy8gY29uZmlndXJlZC5cbi8vIG1vdW50IGlzIHRoZSBVUkwgZm9yIHRoZSByb290IG9mIHRoZSBBUEk7IGluY2x1ZGVzIGh0dHAsIGRvbWFpbiwgZXRjLlxuXG5pbXBvcnQgQXBwQ2FjaGUgZnJvbSAnLi9jYWNoZSc7XG5pbXBvcnQgU2NoZW1hQ2FjaGUgZnJvbSAnLi9Db250cm9sbGVycy9TY2hlbWFDYWNoZSc7XG5pbXBvcnQgRGF0YWJhc2VDb250cm9sbGVyIGZyb20gJy4vQ29udHJvbGxlcnMvRGF0YWJhc2VDb250cm9sbGVyJztcbmltcG9ydCBuZXQgZnJvbSAnbmV0JztcblxuZnVuY3Rpb24gcmVtb3ZlVHJhaWxpbmdTbGFzaChzdHIpIHtcbiAgaWYgKCFzdHIpIHtcbiAgICByZXR1cm4gc3RyO1xuICB9XG4gIGlmIChzdHIuZW5kc1dpdGgoXCIvXCIpKSB7XG4gICAgc3RyID0gc3RyLnN1YnN0cigwLCBzdHIubGVuZ3RoIC0gMSk7XG4gIH1cbiAgcmV0dXJuIHN0cjtcbn1cblxuZXhwb3J0IGNsYXNzIENvbmZpZyB7XG4gIHN0YXRpYyBnZXQoYXBwbGljYXRpb25JZDogc3RyaW5nLCBtb3VudDogc3RyaW5nKSB7XG4gICAgY29uc3QgY2FjaGVJbmZvID0gQXBwQ2FjaGUuZ2V0KGFwcGxpY2F0aW9uSWQpO1xuICAgIGlmICghY2FjaGVJbmZvKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZyA9IG5ldyBDb25maWcoKTtcbiAgICBjb25maWcuYXBwbGljYXRpb25JZCA9IGFwcGxpY2F0aW9uSWQ7XG4gICAgT2JqZWN0LmtleXMoY2FjaGVJbmZvKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgIGlmIChrZXkgPT0gJ2RhdGFiYXNlQ29udHJvbGxlcicpIHtcbiAgICAgICAgY29uc3Qgc2NoZW1hQ2FjaGUgPSBuZXcgU2NoZW1hQ2FjaGUoY2FjaGVJbmZvLmNhY2hlQ29udHJvbGxlcixcbiAgICAgICAgICBjYWNoZUluZm8uc2NoZW1hQ2FjaGVUVEwsXG4gICAgICAgICAgY2FjaGVJbmZvLmVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlKTtcbiAgICAgICAgY29uZmlnLmRhdGFiYXNlID0gbmV3IERhdGFiYXNlQ29udHJvbGxlcihjYWNoZUluZm8uZGF0YWJhc2VDb250cm9sbGVyLmFkYXB0ZXIsIHNjaGVtYUNhY2hlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbmZpZ1trZXldID0gY2FjaGVJbmZvW2tleV07XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29uZmlnLm1vdW50ID0gcmVtb3ZlVHJhaWxpbmdTbGFzaChtb3VudCk7XG4gICAgY29uZmlnLmdlbmVyYXRlU2Vzc2lvbkV4cGlyZXNBdCA9IGNvbmZpZy5nZW5lcmF0ZVNlc3Npb25FeHBpcmVzQXQuYmluZChjb25maWcpO1xuICAgIGNvbmZpZy5nZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW5FeHBpcmVzQXQgPSBjb25maWcuZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuRXhwaXJlc0F0LmJpbmQoY29uZmlnKTtcbiAgICByZXR1cm4gY29uZmlnO1xuICB9XG5cbiAgc3RhdGljIHB1dChzZXJ2ZXJDb25maWd1cmF0aW9uKSB7XG4gICAgQ29uZmlnLnZhbGlkYXRlKHNlcnZlckNvbmZpZ3VyYXRpb24pO1xuICAgIEFwcENhY2hlLnB1dChzZXJ2ZXJDb25maWd1cmF0aW9uLmFwcElkLCBzZXJ2ZXJDb25maWd1cmF0aW9uKTtcbiAgICBDb25maWcuc2V0dXBQYXNzd29yZFZhbGlkYXRvcihzZXJ2ZXJDb25maWd1cmF0aW9uLnBhc3N3b3JkUG9saWN5KTtcbiAgICByZXR1cm4gc2VydmVyQ29uZmlndXJhdGlvbjtcbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZSh7XG4gICAgdmVyaWZ5VXNlckVtYWlscyxcbiAgICB1c2VyQ29udHJvbGxlcixcbiAgICBhcHBOYW1lLFxuICAgIHB1YmxpY1NlcnZlclVSTCxcbiAgICByZXZva2VTZXNzaW9uT25QYXNzd29yZFJlc2V0LFxuICAgIGV4cGlyZUluYWN0aXZlU2Vzc2lvbnMsXG4gICAgc2Vzc2lvbkxlbmd0aCxcbiAgICBtYXhMaW1pdCxcbiAgICBlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbixcbiAgICBhY2NvdW50TG9ja291dCxcbiAgICBwYXNzd29yZFBvbGljeSxcbiAgICBtYXN0ZXJLZXlJcHMsXG4gICAgbWFzdGVyS2V5LFxuICAgIHJlYWRPbmx5TWFzdGVyS2V5LFxuICB9KSB7XG5cbiAgICBpZiAobWFzdGVyS2V5ID09PSByZWFkT25seU1hc3RlcktleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtYXN0ZXJLZXkgYW5kIHJlYWRPbmx5TWFzdGVyS2V5IHNob3VsZCBiZSBkaWZmZXJlbnQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBlbWFpbEFkYXB0ZXIgPSB1c2VyQ29udHJvbGxlci5hZGFwdGVyO1xuICAgIGlmICh2ZXJpZnlVc2VyRW1haWxzKSB7XG4gICAgICB0aGlzLnZhbGlkYXRlRW1haWxDb25maWd1cmF0aW9uKHtlbWFpbEFkYXB0ZXIsIGFwcE5hbWUsIHB1YmxpY1NlcnZlclVSTCwgZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb259KTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlQWNjb3VudExvY2tvdXRQb2xpY3koYWNjb3VudExvY2tvdXQpO1xuXG4gICAgdGhpcy52YWxpZGF0ZVBhc3N3b3JkUG9saWN5KHBhc3N3b3JkUG9saWN5KTtcblxuICAgIGlmICh0eXBlb2YgcmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICB0aHJvdyAncmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCBtdXN0IGJlIGEgYm9vbGVhbiB2YWx1ZSc7XG4gICAgfVxuXG4gICAgaWYgKHB1YmxpY1NlcnZlclVSTCkge1xuICAgICAgaWYgKCFwdWJsaWNTZXJ2ZXJVUkwuc3RhcnRzV2l0aChcImh0dHA6Ly9cIikgJiYgIXB1YmxpY1NlcnZlclVSTC5zdGFydHNXaXRoKFwiaHR0cHM6Ly9cIikpIHtcbiAgICAgICAgdGhyb3cgXCJwdWJsaWNTZXJ2ZXJVUkwgc2hvdWxkIGJlIGEgdmFsaWQgSFRUUFMgVVJMIHN0YXJ0aW5nIHdpdGggaHR0cHM6Ly9cIlxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudmFsaWRhdGVTZXNzaW9uQ29uZmlndXJhdGlvbihzZXNzaW9uTGVuZ3RoLCBleHBpcmVJbmFjdGl2ZVNlc3Npb25zKTtcblxuICAgIHRoaXMudmFsaWRhdGVNYXN0ZXJLZXlJcHMobWFzdGVyS2V5SXBzKTtcblxuICAgIHRoaXMudmFsaWRhdGVNYXhMaW1pdChtYXhMaW1pdCk7XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVBY2NvdW50TG9ja291dFBvbGljeShhY2NvdW50TG9ja291dCkge1xuICAgIGlmIChhY2NvdW50TG9ja291dCkge1xuICAgICAgaWYgKHR5cGVvZiBhY2NvdW50TG9ja291dC5kdXJhdGlvbiAhPT0gJ251bWJlcicgfHwgYWNjb3VudExvY2tvdXQuZHVyYXRpb24gPD0gMCB8fCBhY2NvdW50TG9ja291dC5kdXJhdGlvbiA+IDk5OTk5KSB7XG4gICAgICAgIHRocm93ICdBY2NvdW50IGxvY2tvdXQgZHVyYXRpb24gc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiAwIGFuZCBsZXNzIHRoYW4gMTAwMDAwJztcbiAgICAgIH1cblxuICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGFjY291bnRMb2Nrb3V0LnRocmVzaG9sZCkgfHwgYWNjb3VudExvY2tvdXQudGhyZXNob2xkIDwgMSB8fCBhY2NvdW50TG9ja291dC50aHJlc2hvbGQgPiA5OTkpIHtcbiAgICAgICAgdGhyb3cgJ0FjY291bnQgbG9ja291dCB0aHJlc2hvbGQgc2hvdWxkIGJlIGFuIGludGVnZXIgZ3JlYXRlciB0aGFuIDAgYW5kIGxlc3MgdGhhbiAxMDAwJztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVQYXNzd29yZFBvbGljeShwYXNzd29yZFBvbGljeSkge1xuICAgIGlmIChwYXNzd29yZFBvbGljeSkge1xuICAgICAgaWYgKHBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlICE9PSB1bmRlZmluZWQgJiYgKHR5cGVvZiBwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEFnZSAhPT0gJ251bWJlcicgfHwgcGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRBZ2UgPCAwKSkge1xuICAgICAgICB0aHJvdyAncGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRBZ2UgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcic7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbiAhPT0gdW5kZWZpbmVkICYmICh0eXBlb2YgcGFzc3dvcmRQb2xpY3kucmVzZXRUb2tlblZhbGlkaXR5RHVyYXRpb24gIT09ICdudW1iZXInIHx8IHBhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uIDw9IDApKSB7XG4gICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJztcbiAgICAgIH1cblxuICAgICAgaWYocGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVybil7XG4gICAgICAgIGlmKHR5cGVvZihwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuKSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuID0gbmV3IFJlZ0V4cChwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKCEocGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVybiBpbnN0YW5jZW9mIFJlZ0V4cCkpe1xuICAgICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS52YWxpZGF0b3JQYXR0ZXJuIG11c3QgYmUgYSByZWdleCBzdHJpbmcgb3IgUmVnRXhwIG9iamVjdC4nO1xuICAgICAgICB9XG4gICAgICB9XG5cblxuICAgICAgaWYocGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yQ2FsbGJhY2sgJiYgdHlwZW9mIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvckNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS52YWxpZGF0b3JDYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24uJztcbiAgICAgIH1cblxuICAgICAgaWYocGFzc3dvcmRQb2xpY3kuZG9Ob3RBbGxvd1VzZXJuYW1lICYmIHR5cGVvZiBwYXNzd29yZFBvbGljeS5kb05vdEFsbG93VXNlcm5hbWUgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyAncGFzc3dvcmRQb2xpY3kuZG9Ob3RBbGxvd1VzZXJuYW1lIG11c3QgYmUgYSBib29sZWFuIHZhbHVlLic7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKHBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeSkgfHwgcGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5IDw9IDAgfHwgcGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5ID4gMjApKSB7XG4gICAgICAgIHRocm93ICdwYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgbXVzdCBiZSBhbiBpbnRlZ2VyIHJhbmdpbmcgMCAtIDIwJztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBpZiB0aGUgcGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yUGF0dGVybiBpcyBjb25maWd1cmVkIHRoZW4gc2V0dXAgYSBjYWxsYmFjayB0byBwcm9jZXNzIHRoZSBwYXR0ZXJuXG4gIHN0YXRpYyBzZXR1cFBhc3N3b3JkVmFsaWRhdG9yKHBhc3N3b3JkUG9saWN5KSB7XG4gICAgaWYgKHBhc3N3b3JkUG9saWN5ICYmIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4pIHtcbiAgICAgIHBhc3N3b3JkUG9saWN5LnBhdHRlcm5WYWxpZGF0b3IgPSAodmFsdWUpID0+IHtcbiAgICAgICAgcmV0dXJuIHBhc3N3b3JkUG9saWN5LnZhbGlkYXRvclBhdHRlcm4udGVzdCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlRW1haWxDb25maWd1cmF0aW9uKHtlbWFpbEFkYXB0ZXIsIGFwcE5hbWUsIHB1YmxpY1NlcnZlclVSTCwgZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb259KSB7XG4gICAgaWYgKCFlbWFpbEFkYXB0ZXIpIHtcbiAgICAgIHRocm93ICdBbiBlbWFpbEFkYXB0ZXIgaXMgcmVxdWlyZWQgZm9yIGUtbWFpbCB2ZXJpZmljYXRpb24gYW5kIHBhc3N3b3JkIHJlc2V0cy4nO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGFwcE5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyAnQW4gYXBwIG5hbWUgaXMgcmVxdWlyZWQgZm9yIGUtbWFpbCB2ZXJpZmljYXRpb24gYW5kIHBhc3N3b3JkIHJlc2V0cy4nO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHB1YmxpY1NlcnZlclVSTCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93ICdBIHB1YmxpYyBzZXJ2ZXIgdXJsIGlzIHJlcXVpcmVkIGZvciBlLW1haWwgdmVyaWZpY2F0aW9uIGFuZCBwYXNzd29yZCByZXNldHMuJztcbiAgICB9XG4gICAgaWYgKGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uKSB7XG4gICAgICBpZiAoaXNOYU4oZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24pKSB7XG4gICAgICAgIHRocm93ICdFbWFpbCB2ZXJpZnkgdG9rZW4gdmFsaWRpdHkgZHVyYXRpb24gbXVzdCBiZSBhIHZhbGlkIG51bWJlci4nO1xuICAgICAgfSBlbHNlIGlmIChlbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbiA8PSAwKSB7XG4gICAgICAgIHRocm93ICdFbWFpbCB2ZXJpZnkgdG9rZW4gdmFsaWRpdHkgZHVyYXRpb24gbXVzdCBiZSBhIHZhbHVlIGdyZWF0ZXIgdGhhbiAwLidcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVNYXN0ZXJLZXlJcHMobWFzdGVyS2V5SXBzKSB7XG4gICAgZm9yIChjb25zdCBpcCBvZiBtYXN0ZXJLZXlJcHMpIHtcbiAgICAgIGlmKCFuZXQuaXNJUChpcCkpe1xuICAgICAgICB0aHJvdyBgSW52YWxpZCBpcCBpbiBtYXN0ZXJLZXlJcHM6ICR7aXB9YDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXQgbW91bnQoKSB7XG4gICAgdmFyIG1vdW50ID0gdGhpcy5fbW91bnQ7XG4gICAgaWYgKHRoaXMucHVibGljU2VydmVyVVJMKSB7XG4gICAgICBtb3VudCA9IHRoaXMucHVibGljU2VydmVyVVJMO1xuICAgIH1cbiAgICByZXR1cm4gbW91bnQ7XG4gIH1cblxuICBzZXQgbW91bnQobmV3VmFsdWUpIHtcbiAgICB0aGlzLl9tb3VudCA9IG5ld1ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlU2Vzc2lvbkNvbmZpZ3VyYXRpb24oc2Vzc2lvbkxlbmd0aCwgZXhwaXJlSW5hY3RpdmVTZXNzaW9ucykge1xuICAgIGlmIChleHBpcmVJbmFjdGl2ZVNlc3Npb25zKSB7XG4gICAgICBpZiAoaXNOYU4oc2Vzc2lvbkxlbmd0aCkpIHtcbiAgICAgICAgdGhyb3cgJ1Nlc3Npb24gbGVuZ3RoIG11c3QgYmUgYSB2YWxpZCBudW1iZXIuJztcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKHNlc3Npb25MZW5ndGggPD0gMCkge1xuICAgICAgICB0aHJvdyAnU2Vzc2lvbiBsZW5ndGggbXVzdCBiZSBhIHZhbHVlIGdyZWF0ZXIgdGhhbiAwLidcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdmFsaWRhdGVNYXhMaW1pdChtYXhMaW1pdCkge1xuICAgIGlmIChtYXhMaW1pdCA8PSAwKSB7XG4gICAgICB0aHJvdyAnTWF4IGxpbWl0IG11c3QgYmUgYSB2YWx1ZSBncmVhdGVyIHRoYW4gMC4nXG4gICAgfVxuICB9XG5cbiAgZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuRXhwaXJlc0F0KCkge1xuICAgIGlmICghdGhpcy52ZXJpZnlVc2VyRW1haWxzIHx8ICF0aGlzLmVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB2YXIgbm93ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gbmV3IERhdGUobm93LmdldFRpbWUoKSArICh0aGlzLmVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uICogMTAwMCkpO1xuICB9XG5cbiAgZ2VuZXJhdGVQYXNzd29yZFJlc2V0VG9rZW5FeHBpcmVzQXQoKSB7XG4gICAgaWYgKCF0aGlzLnBhc3N3b3JkUG9saWN5IHx8ICF0aGlzLnBhc3N3b3JkUG9saWN5LnJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIHJldHVybiBuZXcgRGF0ZShub3cuZ2V0VGltZSgpICsgKHRoaXMucGFzc3dvcmRQb2xpY3kucmVzZXRUb2tlblZhbGlkaXR5RHVyYXRpb24gKiAxMDAwKSk7XG4gIH1cblxuICBnZW5lcmF0ZVNlc3Npb25FeHBpcmVzQXQoKSB7XG4gICAgaWYgKCF0aGlzLmV4cGlyZUluYWN0aXZlU2Vzc2lvbnMpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIHJldHVybiBuZXcgRGF0ZShub3cuZ2V0VGltZSgpICsgKHRoaXMuc2Vzc2lvbkxlbmd0aCAqIDEwMDApKTtcbiAgfVxuXG4gIGdldCBpbnZhbGlkTGlua1VSTCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXN0b21QYWdlcy5pbnZhbGlkTGluayB8fCBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9pbnZhbGlkX2xpbmsuaHRtbGA7XG4gIH1cblxuICBnZXQgaW52YWxpZFZlcmlmaWNhdGlvbkxpbmtVUkwoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tUGFnZXMuaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsgfHwgYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvaW52YWxpZF92ZXJpZmljYXRpb25fbGluay5odG1sYDtcbiAgfVxuXG4gIGdldCBsaW5rU2VuZFN1Y2Nlc3NVUkwoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tUGFnZXMubGlua1NlbmRTdWNjZXNzIHx8IGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzL2xpbmtfc2VuZF9zdWNjZXNzLmh0bWxgXG4gIH1cblxuICBnZXQgbGlua1NlbmRGYWlsVVJMKCkge1xuICAgIHJldHVybiB0aGlzLmN1c3RvbVBhZ2VzLmxpbmtTZW5kRmFpbCB8fCBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy9saW5rX3NlbmRfZmFpbC5odG1sYFxuICB9XG5cbiAgZ2V0IHZlcmlmeUVtYWlsU3VjY2Vzc1VSTCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXN0b21QYWdlcy52ZXJpZnlFbWFpbFN1Y2Nlc3MgfHwgYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvdmVyaWZ5X2VtYWlsX3N1Y2Nlc3MuaHRtbGA7XG4gIH1cblxuICBnZXQgY2hvb3NlUGFzc3dvcmRVUkwoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tUGFnZXMuY2hvb3NlUGFzc3dvcmQgfHwgYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvY2hvb3NlX3Bhc3N3b3JkYDtcbiAgfVxuXG4gIGdldCByZXF1ZXN0UmVzZXRQYXNzd29yZFVSTCgpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5wdWJsaWNTZXJ2ZXJVUkx9L2FwcHMvJHt0aGlzLmFwcGxpY2F0aW9uSWR9L3JlcXVlc3RfcGFzc3dvcmRfcmVzZXRgO1xuICB9XG5cbiAgZ2V0IHBhc3N3b3JkUmVzZXRTdWNjZXNzVVJMKCkge1xuICAgIHJldHVybiB0aGlzLmN1c3RvbVBhZ2VzLnBhc3N3b3JkUmVzZXRTdWNjZXNzIHx8IGAke3RoaXMucHVibGljU2VydmVyVVJMfS9hcHBzL3Bhc3N3b3JkX3Jlc2V0X3N1Y2Nlc3MuaHRtbGA7XG4gIH1cblxuICBnZXQgcGFyc2VGcmFtZVVSTCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXN0b21QYWdlcy5wYXJzZUZyYW1lVVJMO1xuICB9XG5cbiAgZ2V0IHZlcmlmeUVtYWlsVVJMKCkge1xuICAgIHJldHVybiBgJHt0aGlzLnB1YmxpY1NlcnZlclVSTH0vYXBwcy8ke3RoaXMuYXBwbGljYXRpb25JZH0vdmVyaWZ5X2VtYWlsYDtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDb25maWc7XG5tb2R1bGUuZXhwb3J0cyA9IENvbmZpZztcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/AdaptableController.js b/lib/Controllers/AdaptableController.js index c782269d77..8405e53e57 100644 --- a/lib/Controllers/AdaptableController.js +++ b/lib/Controllers/AdaptableController.js @@ -83,4 +83,5 @@ class AdaptableController { } exports.AdaptableController = AdaptableController; -exports.default = AdaptableController; \ No newline at end of file +exports.default = AdaptableController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9BZGFwdGFibGVDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIl9hZGFwdGVyIiwiU3ltYm9sIiwiQWRhcHRhYmxlQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwiYWRhcHRlciIsImFwcElkIiwib3B0aW9ucyIsInZhbGlkYXRlQWRhcHRlciIsImNvbmZpZyIsIkNvbmZpZyIsImdldCIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJFcnJvciIsInNlbGYiLCJFeHBlY3RlZFR5cGUiLCJuYW1lIiwiVHlwZSIsIm1pc21hdGNoZXMiLCJPYmplY3QiLCJnZXRPd25Qcm9wZXJ0eU5hbWVzIiwicHJvdG90eXBlIiwicmVkdWNlIiwib2JqIiwia2V5IiwiYWRhcHRlclR5cGUiLCJleHBlY3RlZFR5cGUiLCJleHBlY3RlZCIsImFjdHVhbCIsImtleXMiLCJsZW5ndGgiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFZQTs7Ozs7O0FBWkE7Ozs7Ozs7Ozs7QUFVQTtBQUNBLElBQUlBLFdBQVdDLFFBQWY7QUFHTyxNQUFNQyxtQkFBTixDQUEwQjs7QUFFL0JDLGNBQVlDLE9BQVosRUFBcUJDLEtBQXJCLEVBQTRCQyxPQUE1QixFQUFxQztBQUNuQyxTQUFLQSxPQUFMLEdBQWVBLE9BQWY7QUFDQSxTQUFLRCxLQUFMLEdBQWFBLEtBQWI7QUFDQSxTQUFLRCxPQUFMLEdBQWVBLE9BQWY7QUFDRDs7QUFFRCxNQUFJQSxPQUFKLENBQVlBLE9BQVosRUFBcUI7QUFDbkIsU0FBS0csZUFBTCxDQUFxQkgsT0FBckI7QUFDQSxTQUFLSixRQUFMLElBQWlCSSxPQUFqQjtBQUNEOztBQUVELE1BQUlBLE9BQUosR0FBYztBQUNaLFdBQU8sS0FBS0osUUFBTCxDQUFQO0FBQ0Q7O0FBRUQsTUFBSVEsTUFBSixHQUFhO0FBQ1gsV0FBT0MsaUJBQU9DLEdBQVAsQ0FBVyxLQUFLTCxLQUFoQixDQUFQO0FBQ0Q7O0FBRURNLHdCQUFzQjtBQUNwQixVQUFNLElBQUlDLEtBQUosQ0FBVSxtREFBVixDQUFOO0FBQ0Q7O0FBRURMLGtCQUFnQkgsT0FBaEIsRUFBeUI7QUFDdkJGLHdCQUFvQkssZUFBcEIsQ0FBb0NILE9BQXBDLEVBQTZDLElBQTdDO0FBQ0Q7O0FBRUQsU0FBT0csZUFBUCxDQUF1QkgsT0FBdkIsRUFBZ0NTLElBQWhDLEVBQXNDQyxZQUF0QyxFQUFvRDtBQUNsRCxRQUFJLENBQUNWLE9BQUwsRUFBYztBQUNaLFlBQU0sSUFBSVEsS0FBSixDQUFVLEtBQUtULFdBQUwsQ0FBaUJZLElBQWpCLEdBQXdCLHNCQUFsQyxDQUFOO0FBQ0Q7O0FBRUQsVUFBTUMsT0FBT0YsZ0JBQWdCRCxLQUFLRixtQkFBTCxFQUE3QjtBQUNBO0FBQ0EsUUFBSSxDQUFDSyxJQUFMLEVBQVc7QUFDVDtBQUNEOztBQUVEO0FBQ0EsVUFBTUMsYUFBYUMsT0FBT0MsbUJBQVAsQ0FBMkJILEtBQUtJLFNBQWhDLEVBQTJDQyxNQUEzQyxDQUFrRCxDQUFDQyxHQUFELEVBQU1DLEdBQU4sS0FBYztBQUNqRixZQUFNQyxjQUFjLE9BQU9wQixRQUFRbUIsR0FBUixDQUEzQjtBQUNBLFlBQU1FLGVBQWUsT0FBT1QsS0FBS0ksU0FBTCxDQUFlRyxHQUFmLENBQTVCO0FBQ0EsVUFBSUMsZ0JBQWdCQyxZQUFwQixFQUFrQztBQUNoQ0gsWUFBSUMsR0FBSixJQUFXO0FBQ1RHLG9CQUFVRCxZQUREO0FBRVRFLGtCQUFRSDtBQUZDLFNBQVg7QUFJRDtBQUNELGFBQU9GLEdBQVA7QUFDRCxLQVZrQixFQVVoQixFQVZnQixDQUFuQjs7QUFZQSxRQUFJSixPQUFPVSxJQUFQLENBQVlYLFVBQVosRUFBd0JZLE1BQXhCLEdBQWlDLENBQXJDLEVBQXdDO0FBQ3RDLFlBQU0sSUFBSWpCLEtBQUosQ0FBVSxrREFBVixFQUE4RFIsT0FBOUQsRUFBdUVhLFVBQXZFLENBQU47QUFDRDtBQUNGO0FBeEQ4Qjs7UUFBcEJmLG1CLEdBQUFBLG1CO2tCQTJERUEsbUIiLCJmaWxlIjoiQWRhcHRhYmxlQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5BZGFwdGFibGVDb250cm9sbGVyLmpzXG5cbkFkYXB0YWJsZUNvbnRyb2xsZXIgaXMgdGhlIGJhc2UgY2xhc3MgZm9yIGFsbCBjb250cm9sbGVyc1xudGhhdCBzdXBwb3J0IGFkYXB0ZXIsXG5UaGUgc3VwZXIgY2xhc3MgdGFrZXMgY2FyZSBvZiBjcmVhdGluZyB0aGUgcmlnaHQgaW5zdGFuY2UgZm9yIHRoZSBhZGFwdGVyXG5iYXNlZCBvbiB0aGUgcGFyYW1ldGVycyBwYXNzZWRcblxuICovXG5cbi8vIF9hZGFwdGVyIGlzIHByaXZhdGUsIHVzZSBTeW1ib2xcbnZhciBfYWRhcHRlciA9IFN5bWJvbCgpO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuXG5leHBvcnQgY2xhc3MgQWRhcHRhYmxlQ29udHJvbGxlciB7XG5cbiAgY29uc3RydWN0b3IoYWRhcHRlciwgYXBwSWQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMuYXBwSWQgPSBhcHBJZDtcbiAgICB0aGlzLmFkYXB0ZXIgPSBhZGFwdGVyO1xuICB9XG5cbiAgc2V0IGFkYXB0ZXIoYWRhcHRlcikge1xuICAgIHRoaXMudmFsaWRhdGVBZGFwdGVyKGFkYXB0ZXIpO1xuICAgIHRoaXNbX2FkYXB0ZXJdID0gYWRhcHRlcjtcbiAgfVxuXG4gIGdldCBhZGFwdGVyKCkge1xuICAgIHJldHVybiB0aGlzW19hZGFwdGVyXTtcbiAgfVxuXG4gIGdldCBjb25maWcoKSB7XG4gICAgcmV0dXJuIENvbmZpZy5nZXQodGhpcy5hcHBJZCk7XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN1YmNsYXNzZXMgc2hvdWxkIGltcGxlbWVudCBleHBlY3RlZEFkYXB0ZXJUeXBlKClcIik7XG4gIH1cblxuICB2YWxpZGF0ZUFkYXB0ZXIoYWRhcHRlcikge1xuICAgIEFkYXB0YWJsZUNvbnRyb2xsZXIudmFsaWRhdGVBZGFwdGVyKGFkYXB0ZXIsIHRoaXMpO1xuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlQWRhcHRlcihhZGFwdGVyLCBzZWxmLCBFeHBlY3RlZFR5cGUpIHtcbiAgICBpZiAoIWFkYXB0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmNvbnN0cnVjdG9yLm5hbWUgKyBcIiByZXF1aXJlcyBhbiBhZGFwdGVyXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IFR5cGUgPSBFeHBlY3RlZFR5cGUgfHwgc2VsZi5leHBlY3RlZEFkYXB0ZXJUeXBlKCk7XG4gICAgLy8gQWxsb3cgc2tpcHBpbmcgZm9yIHRlc3RpbmdcbiAgICBpZiAoIVR5cGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBNYWtlcyBzdXJlIHRoZSBwcm90b3R5cGUgbWF0Y2hlc1xuICAgIGNvbnN0IG1pc21hdGNoZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhUeXBlLnByb3RvdHlwZSkucmVkdWNlKChvYmosIGtleSkgPT4ge1xuICAgICAgY29uc3QgYWRhcHRlclR5cGUgPSB0eXBlb2YgYWRhcHRlcltrZXldO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gdHlwZW9mIFR5cGUucHJvdG90eXBlW2tleV07XG4gICAgICBpZiAoYWRhcHRlclR5cGUgIT09IGV4cGVjdGVkVHlwZSkge1xuICAgICAgICBvYmpba2V5XSA9IHtcbiAgICAgICAgICBleHBlY3RlZDogZXhwZWN0ZWRUeXBlLFxuICAgICAgICAgIGFjdHVhbDogYWRhcHRlclR5cGVcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9iajtcbiAgICB9LCB7fSk7XG5cbiAgICBpZiAoT2JqZWN0LmtleXMobWlzbWF0Y2hlcykubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQWRhcHRlciBwcm90b3R5cGUgZG9uJ3QgbWF0Y2ggZXhwZWN0ZWQgcHJvdG90eXBlXCIsIGFkYXB0ZXIsIG1pc21hdGNoZXMpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBBZGFwdGFibGVDb250cm9sbGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Controllers/AnalyticsController.js b/lib/Controllers/AnalyticsController.js index a54cf91666..1d2f826ef1 100644 --- a/lib/Controllers/AnalyticsController.js +++ b/lib/Controllers/AnalyticsController.js @@ -40,4 +40,5 @@ class AnalyticsController extends _AdaptableController2.default { } exports.AnalyticsController = AnalyticsController; -exports.default = AnalyticsController; \ No newline at end of file +exports.default = AnalyticsController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9BbmFseXRpY3NDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkFuYWx5dGljc0NvbnRyb2xsZXIiLCJBZGFwdGFibGVDb250cm9sbGVyIiwiYXBwT3BlbmVkIiwicmVxIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aGVuIiwiYWRhcHRlciIsImJvZHkiLCJyZXNwb25zZSIsImNhdGNoIiwidHJhY2tFdmVudCIsInBhcmFtcyIsImV2ZW50TmFtZSIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJBbmFseXRpY3NBZGFwdGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFDQTs7OztBQUVPLE1BQU1BLG1CQUFOLFNBQWtDQyw2QkFBbEMsQ0FBc0Q7QUFDM0RDLFlBQVVDLEdBQVYsRUFBZTtBQUNiLFdBQU9DLFFBQVFDLE9BQVIsR0FBa0JDLElBQWxCLENBQXVCLE1BQU07QUFDbEMsYUFBTyxLQUFLQyxPQUFMLENBQWFMLFNBQWIsQ0FBdUJDLElBQUlLLElBQTNCLEVBQWlDTCxHQUFqQyxDQUFQO0FBQ0QsS0FGTSxFQUVKRyxJQUZJLENBRUVHLFFBQUQsSUFBYztBQUNwQixhQUFPLEVBQUVBLFVBQVVBLFlBQVksRUFBeEIsRUFBUDtBQUNELEtBSk0sRUFJSkMsS0FKSSxDQUlFLE1BQU07QUFDYixhQUFPLEVBQUVELFVBQVUsRUFBWixFQUFQO0FBQ0QsS0FOTSxDQUFQO0FBT0Q7O0FBRURFLGFBQVdSLEdBQVgsRUFBZ0I7QUFDZCxXQUFPQyxRQUFRQyxPQUFSLEdBQWtCQyxJQUFsQixDQUF1QixNQUFNO0FBQ2xDLGFBQU8sS0FBS0MsT0FBTCxDQUFhSSxVQUFiLENBQXdCUixJQUFJUyxNQUFKLENBQVdDLFNBQW5DLEVBQThDVixJQUFJSyxJQUFsRCxFQUF3REwsR0FBeEQsQ0FBUDtBQUNELEtBRk0sRUFFSkcsSUFGSSxDQUVFRyxRQUFELElBQWM7QUFDcEIsYUFBTyxFQUFFQSxVQUFVQSxZQUFZLEVBQXhCLEVBQVA7QUFDRCxLQUpNLEVBSUpDLEtBSkksQ0FJRSxNQUFNO0FBQ2IsYUFBTyxFQUFFRCxVQUFVLEVBQVosRUFBUDtBQUNELEtBTk0sQ0FBUDtBQU9EOztBQUVESyx3QkFBc0I7QUFDcEIsV0FBT0Msa0NBQVA7QUFDRDtBQXZCMEQ7O1FBQWhEZixtQixHQUFBQSxtQjtrQkEwQkVBLG1CIiwiZmlsZSI6IkFuYWx5dGljc0NvbnRyb2xsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQWRhcHRhYmxlQ29udHJvbGxlciBmcm9tICcuL0FkYXB0YWJsZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgQW5hbHl0aWNzQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0FuYWx5dGljcy9BbmFseXRpY3NBZGFwdGVyJztcblxuZXhwb3J0IGNsYXNzIEFuYWx5dGljc0NvbnRyb2xsZXIgZXh0ZW5kcyBBZGFwdGFibGVDb250cm9sbGVyIHtcbiAgYXBwT3BlbmVkKHJlcSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuYXBwT3BlbmVkKHJlcS5ib2R5LCByZXEpO1xuICAgIH0pLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICByZXR1cm4geyByZXNwb25zZTogcmVzcG9uc2UgfHwge30gfTtcbiAgICB9KS5jYXRjaCgoKSA9PiB7XG4gICAgICByZXR1cm4geyByZXNwb25zZToge30gfTtcbiAgICB9KTtcbiAgfVxuXG4gIHRyYWNrRXZlbnQocmVxKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci50cmFja0V2ZW50KHJlcS5wYXJhbXMuZXZlbnROYW1lLCByZXEuYm9keSwgcmVxKTtcbiAgICB9KS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHJlc3BvbnNlIHx8IHt9IH07XG4gICAgfSkuY2F0Y2goKCkgPT4ge1xuICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHt9IH07XG4gICAgfSk7XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHJldHVybiBBbmFseXRpY3NBZGFwdGVyO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEFuYWx5dGljc0NvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/CacheController.js b/lib/Controllers/CacheController.js index 5b0466cbb0..15aefc8298 100644 --- a/lib/Controllers/CacheController.js +++ b/lib/Controllers/CacheController.js @@ -88,4 +88,5 @@ class CacheController extends _AdaptableController2.default { } exports.CacheController = CacheController; -exports.default = CacheController; \ No newline at end of file +exports.default = CacheController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9DYWNoZUNvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiS0VZX1NFUEFSQVRPUl9DSEFSIiwiam9pbktleXMiLCJrZXlzIiwiam9pbiIsIlN1YkNhY2hlIiwiY29uc3RydWN0b3IiLCJwcmVmaXgiLCJjYWNoZUNvbnRyb2xsZXIiLCJ0dGwiLCJjYWNoZSIsImdldCIsImtleSIsImNhY2hlS2V5IiwicHV0IiwidmFsdWUiLCJkZWwiLCJjbGVhciIsIkNhY2hlQ29udHJvbGxlciIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJhZGFwdGVyIiwiYXBwSWQiLCJvcHRpb25zIiwicm9sZSIsInVzZXIiLCJ0aGVuIiwiUHJvbWlzZSIsInJlc29sdmUiLCJleHBlY3RlZEFkYXB0ZXJUeXBlIiwiQ2FjaGVBZGFwdGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEscUJBQXFCLEdBQTNCOztBQUVBLFNBQVNDLFFBQVQsQ0FBa0IsR0FBR0MsSUFBckIsRUFBMkI7QUFDekIsU0FBT0EsS0FBS0MsSUFBTCxDQUFVSCxrQkFBVixDQUFQO0FBQ0Q7O0FBRUQ7Ozs7O0FBS08sTUFBTUksUUFBTixDQUFlO0FBQ3BCQyxjQUFZQyxNQUFaLEVBQW9CQyxlQUFwQixFQUFxQ0MsR0FBckMsRUFBMEM7QUFDeEMsU0FBS0YsTUFBTCxHQUFjQSxNQUFkO0FBQ0EsU0FBS0csS0FBTCxHQUFhRixlQUFiO0FBQ0EsU0FBS0MsR0FBTCxHQUFXQSxHQUFYO0FBQ0Q7O0FBRURFLE1BQUlDLEdBQUosRUFBUztBQUNQLFVBQU1DLFdBQVdYLFNBQVMsS0FBS0ssTUFBZCxFQUFzQkssR0FBdEIsQ0FBakI7QUFDQSxXQUFPLEtBQUtGLEtBQUwsQ0FBV0MsR0FBWCxDQUFlRSxRQUFmLENBQVA7QUFDRDs7QUFFREMsTUFBSUYsR0FBSixFQUFTRyxLQUFULEVBQWdCTixHQUFoQixFQUFxQjtBQUNuQixVQUFNSSxXQUFXWCxTQUFTLEtBQUtLLE1BQWQsRUFBc0JLLEdBQXRCLENBQWpCO0FBQ0EsV0FBTyxLQUFLRixLQUFMLENBQVdJLEdBQVgsQ0FBZUQsUUFBZixFQUF5QkUsS0FBekIsRUFBZ0NOLEdBQWhDLENBQVA7QUFDRDs7QUFFRE8sTUFBSUosR0FBSixFQUFTO0FBQ1AsVUFBTUMsV0FBV1gsU0FBUyxLQUFLSyxNQUFkLEVBQXNCSyxHQUF0QixDQUFqQjtBQUNBLFdBQU8sS0FBS0YsS0FBTCxDQUFXTSxHQUFYLENBQWVILFFBQWYsQ0FBUDtBQUNEOztBQUVESSxVQUFRO0FBQ04sV0FBTyxLQUFLUCxLQUFMLENBQVdPLEtBQVgsRUFBUDtBQUNEO0FBeEJtQjs7UUFBVFosUSxHQUFBQSxRO0FBNEJOLE1BQU1hLGVBQU4sU0FBOEJDLDZCQUE5QixDQUFrRDs7QUFFdkRiLGNBQVljLE9BQVosRUFBcUJDLEtBQXJCLEVBQTRCQyxVQUFVLEVBQXRDLEVBQTBDO0FBQ3hDLFVBQU1GLE9BQU4sRUFBZUMsS0FBZixFQUFzQkMsT0FBdEI7O0FBRUEsU0FBS0MsSUFBTCxHQUFZLElBQUlsQixRQUFKLENBQWEsTUFBYixFQUFxQixJQUFyQixDQUFaO0FBQ0EsU0FBS21CLElBQUwsR0FBWSxJQUFJbkIsUUFBSixDQUFhLE1BQWIsRUFBcUIsSUFBckIsQ0FBWjtBQUNEOztBQUVETSxNQUFJQyxHQUFKLEVBQVM7QUFDUCxVQUFNQyxXQUFXWCxTQUFTLEtBQUttQixLQUFkLEVBQXFCVCxHQUFyQixDQUFqQjtBQUNBLFdBQU8sS0FBS1EsT0FBTCxDQUFhVCxHQUFiLENBQWlCRSxRQUFqQixFQUEyQlksSUFBM0IsQ0FBZ0MsSUFBaEMsRUFBc0MsTUFBTUMsUUFBUUMsT0FBUixDQUFnQixJQUFoQixDQUE1QyxDQUFQO0FBQ0Q7O0FBRURiLE1BQUlGLEdBQUosRUFBU0csS0FBVCxFQUFnQk4sR0FBaEIsRUFBcUI7QUFDbkIsVUFBTUksV0FBV1gsU0FBUyxLQUFLbUIsS0FBZCxFQUFxQlQsR0FBckIsQ0FBakI7QUFDQSxXQUFPLEtBQUtRLE9BQUwsQ0FBYU4sR0FBYixDQUFpQkQsUUFBakIsRUFBMkJFLEtBQTNCLEVBQWtDTixHQUFsQyxDQUFQO0FBQ0Q7O0FBRURPLE1BQUlKLEdBQUosRUFBUztBQUNQLFVBQU1DLFdBQVdYLFNBQVMsS0FBS21CLEtBQWQsRUFBcUJULEdBQXJCLENBQWpCO0FBQ0EsV0FBTyxLQUFLUSxPQUFMLENBQWFKLEdBQWIsQ0FBaUJILFFBQWpCLENBQVA7QUFDRDs7QUFFREksVUFBUTtBQUNOLFdBQU8sS0FBS0csT0FBTCxDQUFhSCxLQUFiLEVBQVA7QUFDRDs7QUFFRFcsd0JBQXNCO0FBQ3BCLFdBQU9DLHNCQUFQO0FBQ0Q7QUE5QnNEOztRQUE1Q1gsZSxHQUFBQSxlO2tCQWlDRUEsZSIsImZpbGUiOiJDYWNoZUNvbnRyb2xsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQWRhcHRhYmxlQ29udHJvbGxlciBmcm9tICcuL0FkYXB0YWJsZUNvbnRyb2xsZXInO1xuaW1wb3J0IENhY2hlQWRhcHRlciAgICAgICAgZnJvbSAnLi4vQWRhcHRlcnMvQ2FjaGUvQ2FjaGVBZGFwdGVyJztcblxuY29uc3QgS0VZX1NFUEFSQVRPUl9DSEFSID0gJzonO1xuXG5mdW5jdGlvbiBqb2luS2V5cyguLi5rZXlzKSB7XG4gIHJldHVybiBrZXlzLmpvaW4oS0VZX1NFUEFSQVRPUl9DSEFSKTtcbn1cblxuLyoqXG4gKiBQcmVmaXggYWxsIGNhbGxzIHRvIHRoZSBjYWNoZSB2aWEgYSBwcmVmaXggc3RyaW5nLCB1c2VmdWwgd2hlbiBncm91cGluZyBDYWNoZSBieSBvYmplY3QgdHlwZS5cbiAqXG4gKiBlZyBcIlJvbGVcIiBvciBcIlNlc3Npb25cIlxuICovXG5leHBvcnQgY2xhc3MgU3ViQ2FjaGUge1xuICBjb25zdHJ1Y3RvcihwcmVmaXgsIGNhY2hlQ29udHJvbGxlciwgdHRsKSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gICAgdGhpcy5jYWNoZSA9IGNhY2hlQ29udHJvbGxlcjtcbiAgICB0aGlzLnR0bCA9IHR0bDtcbiAgfVxuXG4gIGdldChrZXkpIHtcbiAgICBjb25zdCBjYWNoZUtleSA9IGpvaW5LZXlzKHRoaXMucHJlZml4LCBrZXkpO1xuICAgIHJldHVybiB0aGlzLmNhY2hlLmdldChjYWNoZUtleSk7XG4gIH1cblxuICBwdXQoa2V5LCB2YWx1ZSwgdHRsKSB7XG4gICAgY29uc3QgY2FjaGVLZXkgPSBqb2luS2V5cyh0aGlzLnByZWZpeCwga2V5KTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZS5wdXQoY2FjaGVLZXksIHZhbHVlLCB0dGwpO1xuICB9XG5cbiAgZGVsKGtleSkge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gam9pbktleXModGhpcy5wcmVmaXgsIGtleSk7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuZGVsKGNhY2hlS2V5KTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHJldHVybiB0aGlzLmNhY2hlLmNsZWFyKCk7XG4gIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgQ2FjaGVDb250cm9sbGVyIGV4dGVuZHMgQWRhcHRhYmxlQ29udHJvbGxlciB7XG5cbiAgY29uc3RydWN0b3IoYWRhcHRlciwgYXBwSWQsIG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIGFwcElkLCBvcHRpb25zKTtcblxuICAgIHRoaXMucm9sZSA9IG5ldyBTdWJDYWNoZSgncm9sZScsIHRoaXMpO1xuICAgIHRoaXMudXNlciA9IG5ldyBTdWJDYWNoZSgndXNlcicsIHRoaXMpO1xuICB9XG5cbiAgZ2V0KGtleSkge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gam9pbktleXModGhpcy5hcHBJZCwga2V5KTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmdldChjYWNoZUtleSkudGhlbihudWxsLCAoKSA9PiBQcm9taXNlLnJlc29sdmUobnVsbCkpO1xuICB9XG5cbiAgcHV0KGtleSwgdmFsdWUsIHR0bCkge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gam9pbktleXModGhpcy5hcHBJZCwga2V5KTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnB1dChjYWNoZUtleSwgdmFsdWUsIHR0bCk7XG4gIH1cblxuICBkZWwoa2V5KSB7XG4gICAgY29uc3QgY2FjaGVLZXkgPSBqb2luS2V5cyh0aGlzLmFwcElkLCBrZXkpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuZGVsKGNhY2hlS2V5KTtcbiAgfVxuXG4gIGNsZWFyKCkge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuY2xlYXIoKTtcbiAgfVxuXG4gIGV4cGVjdGVkQWRhcHRlclR5cGUoKSB7XG4gICAgcmV0dXJuIENhY2hlQWRhcHRlcjtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDYWNoZUNvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/DatabaseController.js b/lib/Controllers/DatabaseController.js index daf78ed9ae..afb8274205 100644 --- a/lib/Controllers/DatabaseController.js +++ b/lib/Controllers/DatabaseController.js @@ -80,7 +80,7 @@ const transformObjectACL = (_ref) => { return result; }; -const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count']; +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; @@ -141,6 +141,14 @@ const validateQuery = query => { } } + 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') { @@ -177,6 +185,7 @@ const filterSensitiveData = (isMaster, aclGroup, className, object) => { 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; @@ -315,6 +324,16 @@ const untransformObjectACL = (_ref2) => { 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 { @@ -422,13 +441,13 @@ class DatabaseController { 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}`); } - fieldName = fieldName.split('.')[0]; - if (!SchemaController.fieldNameIsValid(fieldName) && !isSpecialUpdateKey(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 (Object.keys(updateOperation).some(innerKey => innerKey.includes('$') || innerKey.includes('.'))) { + 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"); } } @@ -637,10 +656,15 @@ class DatabaseController { } // Won't delete collections in the system namespace - // Returns a promise. - deleteEverything() { + /** + * 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(), this.schemaCache.clear()]); + return Promise.all([this.adapter.deleteAllClasses(fast), this.schemaCache.clear()]); } // Returns a promise for a list of related ids given an owning id. @@ -840,7 +864,8 @@ class DatabaseController { op, distinct, pipeline, - readPreference + readPreference, + isWrite } = {}) { const isMaster = acl === undefined; const aclGroup = acl || []; @@ -878,7 +903,8 @@ class DatabaseController { if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) { throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Cannot sort by ${fieldName}`); } - if (!SchemaController.fieldNameIsValid(fieldName)) { + const rootFieldName = getRootFieldName(fieldName); + if (!SchemaController.fieldNameIsValid(rootFieldName)) { throw new _node.Parse.Error(_node.Parse.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}.`); } }); @@ -894,7 +920,11 @@ class DatabaseController { } } if (!isMaster) { - query = addReadACL(query, aclGroup); + if (isWrite) { + query = addWriteACL(query, aclGroup); + } else { + query = addReadACL(query, aclGroup); + } } validateQuery(query); if (count) { @@ -1037,4 +1067,5 @@ class DatabaseController { module.exports = DatabaseController; // Expose validateQuery for tests -module.exports._validateQuery = validateQuery; \ No newline at end of file +module.exports._validateQuery = validateQuery; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsiU2NoZW1hQ29udHJvbGxlciIsImFkZFdyaXRlQUNMIiwicXVlcnkiLCJhY2wiLCJuZXdRdWVyeSIsIl8iLCJjbG9uZURlZXAiLCJfd3Blcm0iLCJhZGRSZWFkQUNMIiwiX3JwZXJtIiwidHJhbnNmb3JtT2JqZWN0QUNMIiwiQUNMIiwicmVzdWx0IiwiZW50cnkiLCJyZWFkIiwicHVzaCIsIndyaXRlIiwic3BlY2lhbFF1ZXJ5a2V5cyIsImlzU3BlY2lhbFF1ZXJ5S2V5Iiwia2V5IiwiaW5kZXhPZiIsInZhbGlkYXRlUXVlcnkiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9RVUVSWSIsIiRvciIsIkFycmF5IiwiZm9yRWFjaCIsIk9iamVjdCIsImtleXMiLCJub0NvbGxpc2lvbnMiLCJzb21lIiwic3VicSIsImhhc093blByb3BlcnR5IiwiaGFzTmVhcnMiLCJzdWJxdWVyeSIsIiRhbmQiLCIkbm9yIiwibGVuZ3RoIiwiJHJlZ2V4IiwiJG9wdGlvbnMiLCJtYXRjaCIsIklOVkFMSURfS0VZX05BTUUiLCJmaWx0ZXJTZW5zaXRpdmVEYXRhIiwiaXNNYXN0ZXIiLCJhY2xHcm91cCIsImNsYXNzTmFtZSIsIm9iamVjdCIsInBhc3N3b3JkIiwiX2hhc2hlZF9wYXNzd29yZCIsInNlc3Npb25Ub2tlbiIsIl9lbWFpbF92ZXJpZnlfdG9rZW4iLCJfcGVyaXNoYWJsZV90b2tlbiIsIl9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQiLCJfdG9tYnN0b25lIiwiX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0IiwiX2ZhaWxlZF9sb2dpbl9jb3VudCIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIl9wYXNzd29yZF9jaGFuZ2VkX2F0IiwiX3Bhc3N3b3JkX2hpc3RvcnkiLCJvYmplY3RJZCIsImF1dGhEYXRhIiwic3BlY2lhbEtleXNGb3JVcGRhdGUiLCJpc1NwZWNpYWxVcGRhdGVLZXkiLCJleHBhbmRSZXN1bHRPbktleVBhdGgiLCJ2YWx1ZSIsInBhdGgiLCJzcGxpdCIsImZpcnN0S2V5IiwibmV4dFBhdGgiLCJzbGljZSIsImpvaW4iLCJzYW5pdGl6ZURhdGFiYXNlUmVzdWx0Iiwib3JpZ2luYWxPYmplY3QiLCJyZXNwb25zZSIsIlByb21pc2UiLCJyZXNvbHZlIiwia2V5VXBkYXRlIiwiX19vcCIsImpvaW5UYWJsZU5hbWUiLCJmbGF0dGVuVXBkYXRlT3BlcmF0b3JzRm9yQ3JlYXRlIiwiYW1vdW50IiwiSU5WQUxJRF9KU09OIiwib2JqZWN0cyIsIkNPTU1BTkRfVU5BVkFJTEFCTEUiLCJ0cmFuc2Zvcm1BdXRoRGF0YSIsInNjaGVtYSIsInByb3ZpZGVyIiwicHJvdmlkZXJEYXRhIiwiZmllbGROYW1lIiwiZmllbGRzIiwidHlwZSIsInVudHJhbnNmb3JtT2JqZWN0QUNMIiwib3V0cHV0IiwiZ2V0Um9vdEZpZWxkTmFtZSIsInJlbGF0aW9uU2NoZW1hIiwicmVsYXRlZElkIiwib3duaW5nSWQiLCJEYXRhYmFzZUNvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImFkYXB0ZXIiLCJzY2hlbWFDYWNoZSIsInNjaGVtYVByb21pc2UiLCJjb2xsZWN0aW9uRXhpc3RzIiwiY2xhc3NFeGlzdHMiLCJwdXJnZUNvbGxlY3Rpb24iLCJsb2FkU2NoZW1hIiwidGhlbiIsInNjaGVtYUNvbnRyb2xsZXIiLCJnZXRPbmVTY2hlbWEiLCJkZWxldGVPYmplY3RzQnlRdWVyeSIsInZhbGlkYXRlQ2xhc3NOYW1lIiwiY2xhc3NOYW1lSXNWYWxpZCIsInJlamVjdCIsIklOVkFMSURfQ0xBU1NfTkFNRSIsIm9wdGlvbnMiLCJjbGVhckNhY2hlIiwibG9hZCIsInJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5IiwidCIsImdldEV4cGVjdGVkVHlwZSIsInRhcmdldENsYXNzIiwidmFsaWRhdGVPYmplY3QiLCJ1bmRlZmluZWQiLCJzIiwiY2FuQWRkRmllbGQiLCJ1cGRhdGUiLCJtYW55IiwidXBzZXJ0Iiwic2tpcFNhbml0aXphdGlvbiIsIm9yaWdpbmFsUXVlcnkiLCJvcmlnaW5hbFVwZGF0ZSIsInJlbGF0aW9uVXBkYXRlcyIsInZhbGlkYXRlUGVybWlzc2lvbiIsImNvbGxlY3RSZWxhdGlvblVwZGF0ZXMiLCJhZGRQb2ludGVyUGVybWlzc2lvbnMiLCJjYXRjaCIsImVycm9yIiwicm9vdEZpZWxkTmFtZSIsImZpZWxkTmFtZUlzVmFsaWQiLCJ1cGRhdGVPcGVyYXRpb24iLCJpbm5lcktleSIsImluY2x1ZGVzIiwiSU5WQUxJRF9ORVNURURfS0VZIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cHNlcnRPbmVPYmplY3QiLCJmaW5kT25lQW5kVXBkYXRlIiwiT0JKRUNUX05PVF9GT1VORCIsImhhbmRsZVJlbGF0aW9uVXBkYXRlcyIsIm9wcyIsImRlbGV0ZU1lIiwicHJvY2VzcyIsIm9wIiwieCIsInBlbmRpbmciLCJhZGRSZWxhdGlvbiIsInJlbW92ZVJlbGF0aW9uIiwiYWxsIiwiZnJvbUNsYXNzTmFtZSIsImZyb21JZCIsInRvSWQiLCJkb2MiLCJjb2RlIiwiZGVzdHJveSIsInBhcnNlRm9ybWF0U2NoZW1hIiwiY3JlYXRlIiwiY3JlYXRlZEF0IiwiaXNvIiwiX190eXBlIiwidXBkYXRlZEF0IiwiZW5mb3JjZUNsYXNzRXhpc3RzIiwicmVsb2FkRGF0YSIsImNyZWF0ZU9iamVjdCIsImNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEiLCJjbGFzc1NjaGVtYSIsImRhdGEiLCJzY2hlbWFGaWVsZHMiLCJuZXdLZXlzIiwiZmlsdGVyIiwiZmllbGQiLCJkZWxldGVFdmVyeXRoaW5nIiwiZmFzdCIsImRlbGV0ZUFsbENsYXNzZXMiLCJjbGVhciIsInJlbGF0ZWRJZHMiLCJxdWVyeU9wdGlvbnMiLCJza2lwIiwibGltaXQiLCJzb3J0IiwiZmluZE9wdGlvbnMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiZmluZCIsInJlc3VsdHMiLCJtYXAiLCJvd25pbmdJZHMiLCJyZWR1Y2VJblJlbGF0aW9uIiwib3JzIiwiYVF1ZXJ5IiwiaW5kZXgiLCJwcm9taXNlcyIsInF1ZXJpZXMiLCJjb25zdHJhaW50S2V5IiwiaXNOZWdhdGlvbiIsInIiLCJxIiwiaWRzIiwiYWRkTm90SW5PYmplY3RJZHNJZHMiLCJhZGRJbk9iamVjdElkc0lkcyIsInJlZHVjZVJlbGF0aW9uS2V5cyIsInJlbGF0ZWRUbyIsImlkc0Zyb21TdHJpbmciLCJpZHNGcm9tRXEiLCJpZHNGcm9tSW4iLCJhbGxJZHMiLCJsaXN0IiwidG90YWxMZW5ndGgiLCJyZWR1Y2UiLCJtZW1vIiwiaWRzSW50ZXJzZWN0aW9uIiwiaW50ZXJzZWN0IiwiYmlnIiwiJGluIiwiJGVxIiwiaWRzRnJvbU5pbiIsIlNldCIsIiRuaW4iLCJjb3VudCIsImRpc3RpbmN0IiwicGlwZWxpbmUiLCJyZWFkUHJlZmVyZW5jZSIsImlzV3JpdGUiLCJfY3JlYXRlZF9hdCIsIl91cGRhdGVkX2F0IiwiYWdncmVnYXRlIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiZGVsZXRlU2NoZW1hIiwiZGVsZXRlQ2xhc3MiLCJ3YXNQYXJzZUNvbGxlY3Rpb24iLCJyZWxhdGlvbkZpZWxkTmFtZXMiLCJuYW1lIiwib3BlcmF0aW9uIiwidGVzdEJhc2VDTFAiLCJwZXJtcyIsInVzZXJBQ0wiLCJ1c2VySWQiLCJ1c2VyUG9pbnRlciIsInBlcm1GaWVsZHMiLCJhc3NpZ24iLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJyZXF1aXJlZFVzZXJGaWVsZHMiLCJkZWZhdWx0Q29sdW1ucyIsIl9EZWZhdWx0IiwiX1VzZXIiLCJyZXF1aXJlZFJvbGVGaWVsZHMiLCJfUm9sZSIsInVzZXJDbGFzc1Byb21pc2UiLCJyb2xlQ2xhc3NQcm9taXNlIiwidXNlcm5hbWVVbmlxdWVuZXNzIiwiZW5zdXJlVW5pcXVlbmVzcyIsImxvZ2dlciIsIndhcm4iLCJlbWFpbFVuaXF1ZW5lc3MiLCJyb2xlVW5pcXVlbmVzcyIsImluZGV4UHJvbWlzZSIsInVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzIiwiYWRhcHRlckluaXQiLCJWb2xhdGlsZUNsYXNzZXNTY2hlbWFzIiwibW9kdWxlIiwiZXhwb3J0cyIsIl92YWxpZGF0ZVF1ZXJ5Il0sIm1hcHBpbmdzIjoiOzs7O0FBS0E7O0FBRUE7Ozs7QUFFQTs7OztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7SUFBWUEsZ0I7O0FBQ1o7Ozs7Ozs7QUFiQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOzs7QUFRQSxTQUFTQyxXQUFULENBQXFCQyxLQUFyQixFQUE0QkMsR0FBNUIsRUFBaUM7QUFDL0IsUUFBTUMsV0FBV0MsaUJBQUVDLFNBQUYsQ0FBWUosS0FBWixDQUFqQjtBQUNBO0FBQ0FFLFdBQVNHLE1BQVQsR0FBa0IsRUFBRSxPQUFRLENBQUMsSUFBRCxFQUFPLEdBQUdKLEdBQVYsQ0FBVixFQUFsQjtBQUNBLFNBQU9DLFFBQVA7QUFDRDs7QUFFRCxTQUFTSSxVQUFULENBQW9CTixLQUFwQixFQUEyQkMsR0FBM0IsRUFBZ0M7QUFDOUIsUUFBTUMsV0FBV0MsaUJBQUVDLFNBQUYsQ0FBWUosS0FBWixDQUFqQjtBQUNBO0FBQ0FFLFdBQVNLLE1BQVQsR0FBa0IsRUFBQyxPQUFPLENBQUMsSUFBRCxFQUFPLEdBQVAsRUFBWSxHQUFHTixHQUFmLENBQVIsRUFBbEI7QUFDQSxTQUFPQyxRQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxNQUFNTSxxQkFBcUIsVUFBd0I7QUFBQSxNQUF2QixFQUFFQyxHQUFGLEVBQXVCO0FBQUEsTUFBYkMsTUFBYTs7QUFDakQsTUFBSSxDQUFDRCxHQUFMLEVBQVU7QUFDUixXQUFPQyxNQUFQO0FBQ0Q7O0FBRURBLFNBQU9MLE1BQVAsR0FBZ0IsRUFBaEI7QUFDQUssU0FBT0gsTUFBUCxHQUFnQixFQUFoQjs7QUFFQSxPQUFLLE1BQU1JLEtBQVgsSUFBb0JGLEdBQXBCLEVBQXlCO0FBQ3ZCLFFBQUlBLElBQUlFLEtBQUosRUFBV0MsSUFBZixFQUFxQjtBQUNuQkYsYUFBT0gsTUFBUCxDQUFjTSxJQUFkLENBQW1CRixLQUFuQjtBQUNEO0FB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QTNDLEVBQW5DLENBQXBCO0FBQ0EsV0FBTy9MLFFBQVFrRixHQUFSLENBQVksQ0FBQ29HLGtCQUFELEVBQXFCSSxlQUFyQixFQUFzQ0MsY0FBdEMsRUFBc0RHLFdBQXRELEVBQW1FRixZQUFuRSxDQUFaLENBQVA7QUFDRDs7QUFseEJzQjs7QUF1eEJ6QkksT0FBT0MsT0FBUCxHQUFpQjFLLGtCQUFqQjtBQUNBO0FBQ0F5SyxPQUFPQyxPQUFQLENBQWVDLGNBQWYsR0FBZ0N4UCxhQUFoQyIsImZpbGUiOiJEYXRhYmFzZUNvbnRyb2xsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyLvu78vLyBAZmxvd1xuLy8gQSBkYXRhYmFzZSBhZGFwdGVyIHRoYXQgd29ya3Mgd2l0aCBkYXRhIGV4cG9ydGVkIGZyb20gdGhlIGhvc3RlZFxuLy8gUGFyc2UgZGF0YWJhc2UuXG5cbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0IHsgUGFyc2UgfSAgICAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBfICAgICAgICAgICAgICAgICAgICAgIGZyb20gJ2xvZGFzaCc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBpbnRlcnNlY3QgICAgICAgICAgICAgIGZyb20gJ2ludGVyc2VjdCc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBkZWVwY29weSAgICAgICAgICAgICAgIGZyb20gJ2RlZXBjb3B5JztcbmltcG9ydCBsb2dnZXIgICAgICAgICAgICAgICAgIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgKiBhcyBTY2hlbWFDb250cm9sbGVyICAgICAgIGZyb20gJy4vU2NoZW1hQ29udHJvbGxlcic7XG5pbXBvcnQgeyBTdG9yYWdlQWRhcHRlciB9ICAgICBmcm9tICcuLi9BZGFwdGVycy9TdG9yYWdlL1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCB0eXBlIHsgUXVlcnlPcHRpb25zLFxuICBGdWxsUXVlcnlPcHRpb25zIH0gICAgICAgICAgZnJvbSAnLi4vQWRhcHRlcnMvU3RvcmFnZS9TdG9yYWdlQWRhcHRlcic7XG5cbmZ1bmN0aW9uIGFkZFdyaXRlQUNMKHF1ZXJ5LCBhY2wpIHtcbiAgY29uc3QgbmV3UXVlcnkgPSBfLmNsb25lRGVlcChxdWVyeSk7XG4gIC8vQ2FuJ3QgYmUgYW55IGV4aXN0aW5nICdfd3Blcm0nIHF1ZXJ5LCB3ZSBkb24ndCBhbGxvdyBjbGllbnQgcXVlcmllcyBvbiB0aGF0LCBubyBuZWVkIHRvICRhbmRcbiAgbmV3UXVlcnkuX3dwZXJtID0geyBcIiRpblwiIDogW251bGwsIC4uLmFjbF19O1xuICByZXR1cm4gbmV3UXVlcnk7XG59XG5cbmZ1bmN0aW9uIGFkZFJlYWRBQ0wocXVlcnksIGFjbCkge1xuICBjb25zdCBuZXdRdWVyeSA9IF8uY2xvbmVEZWVwKHF1ZXJ5KTtcbiAgLy9DYW4ndCBiZSBhbnkgZXhpc3RpbmcgJ19ycGVybScgcXVlcnksIHdlIGRvbid0IGFsbG93IGNsaWVudCBxdWVyaWVzIG9uIHRoYXQsIG5vIG5lZWQgdG8gJGFuZFxuICBuZXdRdWVyeS5fcnBlcm0gPSB7XCIkaW5cIjogW251bGwsIFwiKlwiLCAuLi5hY2xdfTtcbiAgcmV0dXJuIG5ld1F1ZXJ5O1xufVxuXG4vLyBUcmFuc2Zvcm1zIGEgUkVTVCBBUEkgZm9ybWF0dGVkIEFDTCBvYmplY3QgdG8gb3VyIHR3by1maWVsZCBtb25nbyBmb3JtYXQuXG5jb25zdCB0cmFuc2Zvcm1PYmplY3RBQ0wgPSAoeyBBQ0wsIC4uLnJlc3VsdCB9KSA9PiB7XG4gIGlmICghQUNMKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHJlc3VsdC5fd3Blcm0gPSBbXTtcbiAgcmVzdWx0Ll9ycGVybSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZW50cnkgaW4gQUNMKSB7XG4gICAgaWYgKEFDTFtlbnRyeV0ucmVhZCkge1xuICAgICAgcmVzdWx0Ll9ycGVybS5wdXNoKGVudHJ5KTtcbiAgICB9XG4gICAgaWYgKEFDTFtlbnRyeV0ud3JpdGUpIHtcbiAgICAgIHJlc3VsdC5fd3Blcm0ucHVzaChlbnRyeSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmNvbnN0IHNwZWNpYWxRdWVyeWtleXMgPSBbJyRhbmQnLCAnJG9yJywgJyRub3InLCAnX3JwZXJtJywgJ193cGVybScsICdfcGVyaXNoYWJsZV90b2tlbicsICdfZW1haWxfdmVyaWZ5X3Rva2VuJywgJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCcsICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnLCAnX2ZhaWxlZF9sb2dpbl9jb3VudCddO1xuXG5jb25zdCBpc1NwZWNpYWxRdWVyeUtleSA9IGtleSA9PiB7XG4gIHJldHVybiBzcGVjaWFsUXVlcnlrZXlzLmluZGV4T2Yoa2V5KSA+PSAwO1xufVxuXG5jb25zdCB2YWxpZGF0ZVF1ZXJ5ID0gKHF1ZXJ5OiBhbnkpOiB2b2lkID0+IHtcbiAgaWYgKHF1ZXJ5LkFDTCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCAnQ2Fubm90IHF1ZXJ5IG9uIEFDTC4nKTtcbiAgfVxuXG4gIGlmIChxdWVyeS4kb3IpIHtcbiAgICBpZiAocXVlcnkuJG9yIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgIHF1ZXJ5LiRvci5mb3JFYWNoKHZhbGlkYXRlUXVlcnkpO1xuXG4gICAgICAvKiBJbiBNb25nb0RCLCAkb3IgcXVlcmllcyB3aGljaCBhcmUgbm90IGFsb25lIGF0IHRoZSB0b3AgbGV2ZWwgb2YgdGhlXG4gICAgICAgKiBxdWVyeSBjYW4gbm90IG1ha2UgZWZmaWNpZW50IHVzZSBvZiBpbmRleGVzIGR1ZSB0byBhIGxvbmcgc3RhbmRpbmdcbiAgICAgICAqIGJ1ZyBrbm93biBhcyBTRVJWRVItMTM3MzIuXG4gICAgICAgKlxuICAgICAgICogVGhpcyBibG9jayByZXN0cnVjdHVyZXMgcXVlcmllcyBpbiB3aGljaCAkb3IgaXMgbm90IHRoZSBzb2xlIHRvcFxuICAgICAgICogbGV2ZWwgZWxlbWVudCBieSBtb3ZpbmcgYWxsIG90aGVyIHRvcC1sZXZlbCBwcmVkaWNhdGVzIGluc2lkZSBldmVyeVxuICAgICAgICogc3ViZG9jdW1lbnQgb2YgdGhlICRvciBwcmVkaWNhdGUsIGFsbG93aW5nIE1vbmdvREIncyBxdWVyeSBwbGFubmVyXG4gICAgICAgKiB0byBtYWtlIGZ1bGwgdXNlIG9mIHRoZSBtb3N0IHJlbGV2YW50IGluZGV4ZXMuXG4gICAgICAgKlxuICAgICAgICogRUc6ICAgICAgeyRvcjogW3thOiAxfSwge2E6IDJ9XSwgYjogMn1cbiAgICAgICAqIEJlY29tZXM6IHskb3I6IFt7YTogMSwgYjogMn0sIHthOiAyLCBiOiAyfV19XG4gICAgICAgKlxuICAgICAgICogVGhlIG9ubHkgZXhjZXB0aW9ucyBhcmUgJG5lYXIgYW5kICRuZWFyU3BoZXJlIG9wZXJhdG9ycywgd2hpY2ggYXJlXG4gICAgICAgKiBjb25zdHJhaW5lZCB0byBvbmx5IDEgb3BlcmF0b3IgcGVyIHF1ZXJ5LiBBcyBhIHJlc3VsdCwgdGhlc2Ugb3BzXG4gICAgICAgKiByZW1haW4gYXQgdGhlIHRvcCBsZXZlbFxuICAgICAgICpcbiAgICAgICAqIGh0dHBzOi8vamlyYS5tb25nb2RiLm9yZy9icm93c2UvU0VSVkVSLTEzNzMyXG4gICAgICAgKiBodHRwczovL2dpdGh1Yi5jb20vcGFyc2UtY29tbXVuaXR5L3BhcnNlLXNlcnZlci9pc3N1ZXMvMzc2N1xuICAgICAgICovXG4gICAgICBPYmplY3Qua2V5cyhxdWVyeSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICBjb25zdCBub0NvbGxpc2lvbnMgPSAhcXVlcnkuJG9yLnNvbWUoc3VicSA9PiBzdWJxLmhhc093blByb3BlcnR5KGtleSkpXG4gICAgICAgIGxldCBoYXNOZWFycyA9IGZhbHNlXG4gICAgICAgIGlmIChxdWVyeVtrZXldICE9IG51bGwgJiYgdHlwZW9mIHF1ZXJ5W2tleV0gPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBoYXNOZWFycyA9ICgnJG5lYXInIGluIHF1ZXJ5W2tleV0gfHwgJyRuZWFyU3BoZXJlJyBpbiBxdWVyeVtrZXldKVxuICAgICAgICB9XG4gICAgICAgIGlmIChrZXkgIT0gJyRvcicgJiYgbm9Db2xsaXNpb25zICYmICFoYXNOZWFycykge1xuICAgICAgICAgIHF1ZXJ5LiRvci5mb3JFYWNoKHN1YnF1ZXJ5ID0+IHtcbiAgICAgICAgICAgIHN1YnF1ZXJ5W2tleV0gPSBxdWVyeVtrZXldO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGRlbGV0ZSBxdWVyeVtrZXldO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHF1ZXJ5LiRvci5mb3JFYWNoKHZhbGlkYXRlUXVlcnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgJ0JhZCAkb3IgZm9ybWF0IC0gdXNlIGFuIGFycmF5IHZhbHVlLicpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChxdWVyeS4kYW5kKSB7XG4gICAgaWYgKHF1ZXJ5LiRhbmQgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgcXVlcnkuJGFuZC5mb3JFYWNoKHZhbGlkYXRlUXVlcnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgJ0JhZCAkYW5kIGZvcm1hdCAtIHVzZSBhbiBhcnJheSB2YWx1ZS4nKTtcbiAgICB9XG4gIH1cblxuICBpZiAocXVlcnkuJG5vcikge1xuICAgIGlmIChxdWVyeS4kbm9yIGluc3RhbmNlb2YgQXJyYXkgJiYgcXVlcnkuJG5vci5sZW5ndGggPiAwKSB7XG4gICAgICBxdWVyeS4kbm9yLmZvckVhY2godmFsaWRhdGVRdWVyeSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCAnQmFkICRub3IgZm9ybWF0IC0gdXNlIGFuIGFycmF5IG9mIGF0IGxlYXN0IDEgdmFsdWUuJyk7XG4gICAgfVxuICB9XG5cbiAgT2JqZWN0LmtleXMocXVlcnkpLmZvckVhY2goa2V5ID0+IHtcbiAgICBpZiAocXVlcnkgJiYgcXVlcnlba2V5XSAmJiBxdWVyeVtrZXldLiRyZWdleCkge1xuICAgICAgaWYgKHR5cGVvZiBxdWVyeVtrZXldLiRvcHRpb25zID09PSAnc3RyaW5nJykge1xuICAgICAgICBpZiAoIXF1ZXJ5W2tleV0uJG9wdGlvbnMubWF0Y2goL15baW14c10rJC8pKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksIGBCYWQgJG9wdGlvbnMgdmFsdWUgZm9yIHF1ZXJ5OiAke3F1ZXJ5W2tleV0uJG9wdGlvbnN9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFpc1NwZWNpYWxRdWVyeUtleShrZXkpICYmICFrZXkubWF0Y2goL15bYS16QS1aXVthLXpBLVowLTlfXFwuXSokLykpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLCBgSW52YWxpZCBrZXkgbmFtZTogJHtrZXl9YCk7XG4gICAgfVxuICB9KTtcbn1cblxuLy8gRmlsdGVycyBvdXQgYW55IGRhdGEgdGhhdCBzaG91bGRuJ3QgYmUgb24gdGhpcyBSRVNULWZvcm1hdHRlZCBvYmplY3QuXG5jb25zdCBmaWx0ZXJTZW5zaXRpdmVEYXRhID0gKGlzTWFzdGVyLCBhY2xHcm91cCwgY2xhc3NOYW1lLCBvYmplY3QpID0+IHtcbiAgaWYgKGNsYXNzTmFtZSAhPT0gJ19Vc2VyJykge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICBvYmplY3QucGFzc3dvcmQgPSBvYmplY3QuX2hhc2hlZF9wYXNzd29yZDtcbiAgZGVsZXRlIG9iamVjdC5faGFzaGVkX3Bhc3N3b3JkO1xuXG4gIGRlbGV0ZSBvYmplY3Quc2Vzc2lvblRva2VuO1xuXG4gIGlmIChpc01hc3Rlcikge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgZGVsZXRlIG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuO1xuICBkZWxldGUgb2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuO1xuICBkZWxldGUgb2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX3RvbWJzdG9uZTtcbiAgZGVsZXRlIG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX2ZhaWxlZF9sb2dpbl9jb3VudDtcbiAgZGVsZXRlIG9iamVjdC5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX3Bhc3N3b3JkX2NoYW5nZWRfYXQ7XG4gIGRlbGV0ZSBvYmplY3QuX3Bhc3N3b3JkX2hpc3Rvcnk7XG5cbiAgaWYgKChhY2xHcm91cC5pbmRleE9mKG9iamVjdC5vYmplY3RJZCkgPiAtMSkpIHtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG4gIGRlbGV0ZSBvYmplY3QuYXV0aERhdGE7XG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5pbXBvcnQgdHlwZSB7IExvYWRTY2hlbWFPcHRpb25zIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8vIFJ1bnMgYW4gdXBkYXRlIG9uIHRoZSBkYXRhYmFzZS5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhbiBvYmplY3Qgd2l0aCB0aGUgbmV3IHZhbHVlcyBmb3IgZmllbGRcbi8vIG1vZGlmaWNhdGlvbnMgdGhhdCBkb24ndCBrbm93IHRoZWlyIHJlc3VsdHMgYWhlYWQgb2YgdGltZSwgbGlrZVxuLy8gJ2luY3JlbWVudCcuXG4vLyBPcHRpb25zOlxuLy8gICBhY2w6ICBhIGxpc3Qgb2Ygc3RyaW5ncy4gSWYgdGhlIG9iamVjdCB0byBiZSB1cGRhdGVkIGhhcyBhbiBBQ0wsXG4vLyAgICAgICAgIG9uZSBvZiB0aGUgcHJvdmlkZWQgc3RyaW5ncyBtdXN0IHByb3ZpZGUgdGhlIGNhbGxlciB3aXRoXG4vLyAgICAgICAgIHdyaXRlIHBlcm1pc3Npb25zLlxuY29uc3Qgc3BlY2lhbEtleXNGb3JVcGRhdGUgPSBbJ19oYXNoZWRfcGFzc3dvcmQnLCAnX3BlcmlzaGFibGVfdG9rZW4nLCAnX2VtYWlsX3ZlcmlmeV90b2tlbicsICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnLCAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JywgJ19mYWlsZWRfbG9naW5fY291bnQnLCAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCcsICdfcGFzc3dvcmRfY2hhbmdlZF9hdCcsICdfcGFzc3dvcmRfaGlzdG9yeSddO1xuXG5jb25zdCBpc1NwZWNpYWxVcGRhdGVLZXkgPSBrZXkgPT4ge1xuICByZXR1cm4gc3BlY2lhbEtleXNGb3JVcGRhdGUuaW5kZXhPZihrZXkpID49IDA7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZFJlc3VsdE9uS2V5UGF0aChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleS5pbmRleE9mKCcuJykgPCAwKSB7XG4gICAgb2JqZWN0W2tleV0gPSB2YWx1ZVtrZXldO1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgY29uc3QgcGF0aCA9IGtleS5zcGxpdCgnLicpO1xuICBjb25zdCBmaXJzdEtleSA9IHBhdGhbMF07XG4gIGNvbnN0IG5leHRQYXRoID0gcGF0aC5zbGljZSgxKS5qb2luKCcuJyk7XG4gIG9iamVjdFtmaXJzdEtleV0gPSBleHBhbmRSZXN1bHRPbktleVBhdGgob2JqZWN0W2ZpcnN0S2V5XSB8fCB7fSwgbmV4dFBhdGgsIHZhbHVlW2ZpcnN0S2V5XSk7XG4gIGRlbGV0ZSBvYmplY3Rba2V5XTtcbiAgcmV0dXJuIG9iamVjdDtcbn1cblxuZnVuY3Rpb24gc2FuaXRpemVEYXRhYmFzZVJlc3VsdChvcmlnaW5hbE9iamVjdCwgcmVzdWx0KTogUHJvbWlzZTxhbnk+IHtcbiAgY29uc3QgcmVzcG9uc2UgPSB7fTtcbiAgaWYgKCFyZXN1bHQpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3BvbnNlKTtcbiAgfVxuICBPYmplY3Qua2V5cyhvcmlnaW5hbE9iamVjdCkuZm9yRWFjaChrZXkgPT4ge1xuICAgIGNvbnN0IGtleVVwZGF0ZSA9IG9yaWdpbmFsT2JqZWN0W2tleV07XG4gICAgLy8gZGV0ZXJtaW5lIGlmIHRoYXQgd2FzIGFuIG9wXG4gICAgaWYgKGtleVVwZGF0ZSAmJiB0eXBlb2Yga2V5VXBkYXRlID09PSAnb2JqZWN0JyAmJiBrZXlVcGRhdGUuX19vcFxuICAgICAgJiYgWydBZGQnLCAnQWRkVW5pcXVlJywgJ1JlbW92ZScsICdJbmNyZW1lbnQnXS5pbmRleE9mKGtleVVwZGF0ZS5fX29wKSA+IC0xKSB7XG4gICAgICAvLyBvbmx5IHZhbGlkIG9wcyB0aGF0IHByb2R1Y2UgYW4gYWN0aW9uYWJsZSByZXN1bHRcbiAgICAgIC8vIHRoZSBvcCBtYXkgaGF2ZSBoYXBwZW5kIG9uIGEga2V5cGF0aFxuICAgICAgZXhwYW5kUmVzdWx0T25LZXlQYXRoKHJlc3BvbnNlLCBrZXksIHJlc3VsdCk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXNwb25zZSk7XG59XG5cbmZ1bmN0aW9uIGpvaW5UYWJsZU5hbWUoY2xhc3NOYW1lLCBrZXkpIHtcbiAgcmV0dXJuIGBfSm9pbjoke2tleX06JHtjbGFzc05hbWV9YDtcbn1cblxuY29uc3QgZmxhdHRlblVwZGF0ZU9wZXJhdG9yc0ZvckNyZWF0ZSA9IG9iamVjdCA9PiB7XG4gIGZvciAoY29uc3Qga2V5IGluIG9iamVjdCkge1xuICAgIGlmIChvYmplY3Rba2V5XSAmJiBvYmplY3Rba2V5XS5fX29wKSB7XG4gICAgICBzd2l0Y2ggKG9iamVjdFtrZXldLl9fb3ApIHtcbiAgICAgIGNhc2UgJ0luY3JlbWVudCc6XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0W2tleV0uYW1vdW50ICE9PSAnbnVtYmVyJykge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdvYmplY3RzIHRvIGFkZCBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0W2tleV0gPSBvYmplY3Rba2V5XS5hbW91bnQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnQWRkJzpcbiAgICAgICAgaWYgKCEob2JqZWN0W2tleV0ub2JqZWN0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdvYmplY3RzIHRvIGFkZCBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0W2tleV0gPSBvYmplY3Rba2V5XS5vYmplY3RzO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0FkZFVuaXF1ZSc6XG4gICAgICAgIGlmICghKG9iamVjdFtrZXldLm9iamVjdHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnb2JqZWN0cyB0byBhZGQgbXVzdCBiZSBhbiBhcnJheScpO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdFtrZXldID0gb2JqZWN0W2tleV0ub2JqZWN0cztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdSZW1vdmUnOlxuICAgICAgICBpZiAoIShvYmplY3Rba2V5XS5vYmplY3RzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ29iamVjdHMgdG8gYWRkIG11c3QgYmUgYW4gYXJyYXknKTtcbiAgICAgICAgfVxuICAgICAgICBvYmplY3Rba2V5XSA9IFtdXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnRGVsZXRlJzpcbiAgICAgICAgZGVsZXRlIG9iamVjdFtrZXldO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5DT01NQU5EX1VOQVZBSUxBQkxFLCBgVGhlICR7b2JqZWN0W2tleV0uX19vcH0gb3BlcmF0b3IgaXMgbm90IHN1cHBvcnRlZCB5ZXQuYCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IHRyYW5zZm9ybUF1dGhEYXRhID0gKGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpID0+IHtcbiAgaWYgKG9iamVjdC5hdXRoRGF0YSAmJiBjbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBPYmplY3Qua2V5cyhvYmplY3QuYXV0aERhdGEpLmZvckVhY2gocHJvdmlkZXIgPT4ge1xuICAgICAgY29uc3QgcHJvdmlkZXJEYXRhID0gb2JqZWN0LmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGBfYXV0aF9kYXRhXyR7cHJvdmlkZXJ9YDtcbiAgICAgIGlmIChwcm92aWRlckRhdGEgPT0gbnVsbCkge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX29wOiAnRGVsZXRlJ1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHByb3ZpZGVyRGF0YTtcbiAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdID0geyB0eXBlOiAnT2JqZWN0JyB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgZGVsZXRlIG9iamVjdC5hdXRoRGF0YTtcbiAgfVxufVxuLy8gVHJhbnNmb3JtcyBhIERhdGFiYXNlIGZvcm1hdCBBQ0wgdG8gYSBSRVNUIEFQSSBmb3JtYXQgQUNMXG5jb25zdCB1bnRyYW5zZm9ybU9iamVjdEFDTCA9ICh7X3JwZXJtLCBfd3Blcm0sIC4uLm91dHB1dH0pID0+IHtcbiAgaWYgKF9ycGVybSB8fCBfd3Blcm0pIHtcbiAgICBvdXRwdXQuQUNMID0ge307XG5cbiAgICAoX3JwZXJtIHx8IFtdKS5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIGlmICghb3V0cHV0LkFDTFtlbnRyeV0pIHtcbiAgICAgICAgb3V0cHV0LkFDTFtlbnRyeV0gPSB7IHJlYWQ6IHRydWUgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dC5BQ0xbZW50cnldWydyZWFkJ10gPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgKF93cGVybSB8fCBbXSkuZm9yRWFjaChlbnRyeSA9PiB7XG4gICAgICBpZiAoIW91dHB1dC5BQ0xbZW50cnldKSB7XG4gICAgICAgIG91dHB1dC5BQ0xbZW50cnldID0geyB3cml0ZTogdHJ1ZSB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0LkFDTFtlbnRyeV1bJ3dyaXRlJ10gPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cbi8qKlxuICogV2hlbiBxdWVyeWluZywgdGhlIGZpZWxkTmFtZSBtYXkgYmUgY29tcG91bmQsIGV4dHJhY3QgdGhlIHJvb3QgZmllbGROYW1lXG4gKiAgICAgYHRlbXBlcmF0dXJlLmNlbHNpdXNgIGJlY29tZXMgYHRlbXBlcmF0dXJlYFxuICogQHBhcmFtIHtzdHJpbmd9IGZpZWxkTmFtZSB0aGF0IG1heSBiZSBhIGNvbXBvdW5kIGZpZWxkIG5hbWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSByb290IG5hbWUgb2YgdGhlIGZpZWxkXG4gKi9cbmNvbnN0IGdldFJvb3RGaWVsZE5hbWUgPSAoZmllbGROYW1lOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICByZXR1cm4gZmllbGROYW1lLnNwbGl0KCcuJylbMF1cbn1cblxuY29uc3QgcmVsYXRpb25TY2hlbWEgPSB7IGZpZWxkczogeyByZWxhdGVkSWQ6IHsgdHlwZTogJ1N0cmluZycgfSwgb3duaW5nSWQ6IHsgdHlwZTogJ1N0cmluZycgfSB9IH07XG5cbmNsYXNzIERhdGFiYXNlQ29udHJvbGxlciB7XG4gIGFkYXB0ZXI6IFN0b3JhZ2VBZGFwdGVyO1xuICBzY2hlbWFDYWNoZTogYW55O1xuICBzY2hlbWFQcm9taXNlOiA/UHJvbWlzZTxTY2hlbWFDb250cm9sbGVyLlNjaGVtYUNvbnRyb2xsZXI+O1xuXG4gIGNvbnN0cnVjdG9yKGFkYXB0ZXI6IFN0b3JhZ2VBZGFwdGVyLCBzY2hlbWFDYWNoZTogYW55KSB7XG4gICAgdGhpcy5hZGFwdGVyID0gYWRhcHRlcjtcbiAgICB0aGlzLnNjaGVtYUNhY2hlID0gc2NoZW1hQ2FjaGU7XG4gICAgLy8gV2UgZG9uJ3Qgd2FudCBhIG11dGFibGUgdGhpcy5zY2hlbWEsIGJlY2F1c2UgdGhlbiB5b3UgY291bGQgaGF2ZVxuICAgIC8vIG9uZSByZXF1ZXN0IHRoYXQgdXNlcyBkaWZmZXJlbnQgc2NoZW1hcyBmb3IgZGlmZmVyZW50IHBhcnRzIG9mXG4gICAgLy8gaXQuIEluc3RlYWQsIHVzZSBsb2FkU2NoZW1hIHRvIGdldCBhIHNjaGVtYS5cbiAgICB0aGlzLnNjaGVtYVByb21pc2UgPSBudWxsO1xuICB9XG5cbiAgY29sbGVjdGlvbkV4aXN0cyhjbGFzc05hbWU6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuY2xhc3NFeGlzdHMoY2xhc3NOYW1lKTtcbiAgfVxuXG4gIHB1cmdlQ29sbGVjdGlvbihjbGFzc05hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmxvYWRTY2hlbWEoKVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYShjbGFzc05hbWUpKVxuICAgICAgLnRoZW4oc2NoZW1hID0+IHRoaXMuYWRhcHRlci5kZWxldGVPYmplY3RzQnlRdWVyeShjbGFzc05hbWUsIHNjaGVtYSwge30pKTtcbiAgfVxuXG4gIHZhbGlkYXRlQ2xhc3NOYW1lKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFTY2hlbWFDb250cm9sbGVyLmNsYXNzTmFtZUlzVmFsaWQoY2xhc3NOYW1lKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsICdpbnZhbGlkIGNsYXNzTmFtZTogJyArIGNsYXNzTmFtZSkpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSBzY2hlbWFDb250cm9sbGVyLlxuICBsb2FkU2NoZW1hKG9wdGlvbnM6IExvYWRTY2hlbWFPcHRpb25zID0ge2NsZWFyQ2FjaGU6IGZhbHNlfSk6IFByb21pc2U8U2NoZW1hQ29udHJvbGxlci5TY2hlbWFDb250cm9sbGVyPiB7XG4gICAgaWYgKHRoaXMuc2NoZW1hUHJvbWlzZSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdGhpcy5zY2hlbWFQcm9taXNlO1xuICAgIH1cbiAgICB0aGlzLnNjaGVtYVByb21pc2UgPSBTY2hlbWFDb250cm9sbGVyLmxvYWQodGhpcy5hZGFwdGVyLCB0aGlzLnNjaGVtYUNhY2hlLCBvcHRpb25zKTtcbiAgICB0aGlzLnNjaGVtYVByb21pc2UudGhlbigoKSA9PiBkZWxldGUgdGhpcy5zY2hlbWFQcm9taXNlLFxuICAgICAgKCkgPT4gZGVsZXRlIHRoaXMuc2NoZW1hUHJvbWlzZSk7XG4gICAgcmV0dXJuIHRoaXMubG9hZFNjaGVtYShvcHRpb25zKTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgY2xhc3NuYW1lIHRoYXQgaXMgcmVsYXRlZCB0byB0aGUgZ2l2ZW5cbiAgLy8gY2xhc3NuYW1lIHRocm91Z2ggdGhlIGtleS5cbiAgLy8gVE9ETzogbWFrZSB0aGlzIG5vdCBpbiB0aGUgRGF0YWJhc2VDb250cm9sbGVyIGludGVyZmFjZVxuICByZWRpcmVjdENsYXNzTmFtZUZvcktleShjbGFzc05hbWU6IHN0cmluZywga2V5OiBzdHJpbmcpOiBQcm9taXNlPD9zdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hKCkudGhlbigoc2NoZW1hKSA9PiB7XG4gICAgICB2YXIgdCAgPSBzY2hlbWEuZ2V0RXhwZWN0ZWRUeXBlKGNsYXNzTmFtZSwga2V5KTtcbiAgICAgIGlmICh0ICE9IG51bGwgJiYgdHlwZW9mIHQgIT09ICdzdHJpbmcnICYmIHQudHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgICByZXR1cm4gdC50YXJnZXRDbGFzcztcbiAgICAgIH1cbiAgICAgIHJldHVybiBjbGFzc05hbWU7XG4gICAgfSk7XG4gIH1cblxuICAvLyBVc2VzIHRoZSBzY2hlbWEgdG8gdmFsaWRhdGUgdGhlIG9iamVjdCAoUkVTVCBBUEkgZm9ybWF0KS5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbmV3IHNjaGVtYS5cbiAgLy8gVGhpcyBkb2VzIG5vdCB1cGRhdGUgdGhpcy5zY2hlbWEsIGJlY2F1c2UgaW4gYSBzaXR1YXRpb24gbGlrZSBhXG4gIC8vIGJhdGNoIHJlcXVlc3QsIHRoYXQgY291bGQgY29uZnVzZSBvdGhlciB1c2VycyBvZiB0aGUgc2NoZW1hLlxuICB2YWxpZGF0ZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0OiBhbnksIHF1ZXJ5OiBhbnksIHsgYWNsIH06IFF1ZXJ5T3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGxldCBzY2hlbWE7XG4gICAgY29uc3QgaXNNYXN0ZXIgPSBhY2wgPT09IHVuZGVmaW5lZDtcbiAgICB2YXIgYWNsR3JvdXA6IHN0cmluZ1tdICA9IGFjbCB8fCBbXTtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hKCkudGhlbihzID0+IHtcbiAgICAgIHNjaGVtYSA9IHM7XG4gICAgICBpZiAoaXNNYXN0ZXIpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuY2FuQWRkRmllbGQoc2NoZW1hLCBjbGFzc05hbWUsIG9iamVjdCwgYWNsR3JvdXApO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHNjaGVtYS52YWxpZGF0ZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgcXVlcnkpO1xuICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogYW55LCB1cGRhdGU6IGFueSwge1xuICAgIGFjbCxcbiAgICBtYW55LFxuICAgIHVwc2VydCxcbiAgfTogRnVsbFF1ZXJ5T3B0aW9ucyA9IHt9LCBza2lwU2FuaXRpemF0aW9uOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IG9yaWdpbmFsUXVlcnkgPSBxdWVyeTtcbiAgICBjb25zdCBvcmlnaW5hbFVwZGF0ZSA9IHVwZGF0ZTtcbiAgICAvLyBNYWtlIGEgY29weSBvZiB0aGUgb2JqZWN0LCBzbyB3ZSBkb24ndCBtdXRhdGUgdGhlIGluY29taW5nIGRhdGEuXG4gICAgdXBkYXRlID0gZGVlcGNvcHkodXBkYXRlKTtcbiAgICB2YXIgcmVsYXRpb25VcGRhdGVzID0gW107XG4gICAgdmFyIGlzTWFzdGVyID0gYWNsID09PSB1bmRlZmluZWQ7XG4gICAgdmFyIGFjbEdyb3VwID0gYWNsIHx8IFtdO1xuICAgIHJldHVybiB0aGlzLmxvYWRTY2hlbWEoKVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiB7XG4gICAgICAgIHJldHVybiAoaXNNYXN0ZXIgPyBQcm9taXNlLnJlc29sdmUoKSA6IHNjaGVtYUNvbnRyb2xsZXIudmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZSwgYWNsR3JvdXAsICd1cGRhdGUnKSlcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZWxhdGlvblVwZGF0ZXMgPSB0aGlzLmNvbGxlY3RSZWxhdGlvblVwZGF0ZXMoY2xhc3NOYW1lLCBvcmlnaW5hbFF1ZXJ5Lm9iamVjdElkLCB1cGRhdGUpO1xuICAgICAgICAgICAgaWYgKCFpc01hc3Rlcikge1xuICAgICAgICAgICAgICBxdWVyeSA9IHRoaXMuYWRkUG9pbnRlclBlcm1pc3Npb25zKHNjaGVtYUNvbnRyb2xsZXIsIGNsYXNzTmFtZSwgJ3VwZGF0ZScsIHF1ZXJ5LCBhY2xHcm91cCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXF1ZXJ5KSB7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChhY2wpIHtcbiAgICAgICAgICAgICAgcXVlcnkgPSBhZGRXcml0ZUFDTChxdWVyeSwgYWNsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhbGlkYXRlUXVlcnkocXVlcnkpO1xuICAgICAgICAgICAgcmV0dXJuIHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSwgdHJ1ZSlcbiAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgc2NoZW1hIGRvZXNuJ3QgZXhpc3QsIHByZXRlbmQgaXQgZXhpc3RzIHdpdGggbm8gZmllbGRzLiBUaGlzIGJlaGF2aW9yXG4gICAgICAgICAgICAgICAgLy8gd2lsbCBsaWtlbHkgbmVlZCByZXZpc2l0aW5nLlxuICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4geyBmaWVsZHM6IHt9IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKHVwZGF0ZSkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKGZpZWxkTmFtZS5tYXRjaCgvXmF1dGhEYXRhXFwuKFthLXpBLVowLTlfXSspXFwuaWQkLykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsIGBJbnZhbGlkIGZpZWxkIG5hbWUgZm9yIHVwZGF0ZTogJHtmaWVsZE5hbWV9YCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBjb25zdCByb290RmllbGROYW1lID0gZ2V0Um9vdEZpZWxkTmFtZShmaWVsZE5hbWUpO1xuICAgICAgICAgICAgICAgICAgaWYgKCFTY2hlbWFDb250cm9sbGVyLmZpZWxkTmFtZUlzVmFsaWQocm9vdEZpZWxkTmFtZSkgJiYgIWlzU3BlY2lhbFVwZGF0ZUtleShyb290RmllbGROYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSwgYEludmFsaWQgZmllbGQgbmFtZSBmb3IgdXBkYXRlOiAke2ZpZWxkTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHVwZGF0ZU9wZXJhdGlvbiBpbiB1cGRhdGUpIHtcbiAgICAgICAgICAgICAgICAgIGlmICh1cGRhdGVbdXBkYXRlT3BlcmF0aW9uXSAmJiB0eXBlb2YgdXBkYXRlW3VwZGF0ZU9wZXJhdGlvbl0gPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKHVwZGF0ZVt1cGRhdGVPcGVyYXRpb25dKS5zb21lKGlubmVyS2V5ID0+IGlubmVyS2V5LmluY2x1ZGVzKCckJykgfHwgaW5uZXJLZXkuaW5jbHVkZXMoJy4nKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfTkVTVEVEX0tFWSwgXCJOZXN0ZWQga2V5cyBzaG91bGQgbm90IGNvbnRhaW4gdGhlICckJyBvciAnLicgY2hhcmFjdGVyc1wiKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdXBkYXRlID0gdHJhbnNmb3JtT2JqZWN0QUNMKHVwZGF0ZSk7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtQXV0aERhdGEoY2xhc3NOYW1lLCB1cGRhdGUsIHNjaGVtYSk7XG4gICAgICAgICAgICAgICAgaWYgKG1hbnkpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIudXBkYXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lLCBzY2hlbWEsIHF1ZXJ5LCB1cGRhdGUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodXBzZXJ0KSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnVwc2VydE9uZU9iamVjdChjbGFzc05hbWUsIHNjaGVtYSwgcXVlcnksIHVwZGF0ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuZmluZE9uZUFuZFVwZGF0ZShjbGFzc05hbWUsIHNjaGVtYSwgcXVlcnksIHVwZGF0ZSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnRoZW4oKHJlc3VsdDogYW55KSA9PiB7XG4gICAgICAgICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ09iamVjdCBub3QgZm91bmQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oYW5kbGVSZWxhdGlvblVwZGF0ZXMoY2xhc3NOYW1lLCBvcmlnaW5hbFF1ZXJ5Lm9iamVjdElkLCB1cGRhdGUsIHJlbGF0aW9uVXBkYXRlcykudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgIGlmIChza2lwU2FuaXRpemF0aW9uKSB7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzYW5pdGl6ZURhdGFiYXNlUmVzdWx0KG9yaWdpbmFsVXBkYXRlLCByZXN1bHQpO1xuICAgICAgICAgIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBDb2xsZWN0IGFsbCByZWxhdGlvbi11cGRhdGluZyBvcGVyYXRpb25zIGZyb20gYSBSRVNULWZvcm1hdCB1cGRhdGUuXG4gIC8vIFJldHVybnMgYSBsaXN0IG9mIGFsbCByZWxhdGlvbiB1cGRhdGVzIHRvIHBlcmZvcm1cbiAgLy8gVGhpcyBtdXRhdGVzIHVwZGF0ZS5cbiAgY29sbGVjdFJlbGF0aW9uVXBkYXRlcyhjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0SWQ6ID9zdHJpbmcsIHVwZGF0ZTogYW55KSB7XG4gICAgdmFyIG9wcyA9IFtdO1xuICAgIHZhciBkZWxldGVNZSA9IFtdO1xuICAgIG9iamVjdElkID0gdXBkYXRlLm9iamVjdElkIHx8IG9iamVjdElkO1xuXG4gICAgdmFyIHByb2Nlc3MgPSAob3AsIGtleSkgPT4ge1xuICAgICAgaWYgKCFvcCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAob3AuX19vcCA9PSAnQWRkUmVsYXRpb24nKSB7XG4gICAgICAgIG9wcy5wdXNoKHtrZXksIG9wfSk7XG4gICAgICAgIGRlbGV0ZU1lLnB1c2goa2V5KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wLl9fb3AgPT0gJ1JlbW92ZVJlbGF0aW9uJykge1xuICAgICAgICBvcHMucHVzaCh7a2V5LCBvcH0pO1xuICAgICAgICBkZWxldGVNZS5wdXNoKGtleSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcC5fX29wID09ICdCYXRjaCcpIHtcbiAgICAgICAgZm9yICh2YXIgeCBvZiBvcC5vcHMpIHtcbiAgICAgICAgICBwcm9jZXNzKHgsIGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9yIChjb25zdCBrZXkgaW4gdXBkYXRlKSB7XG4gICAgICBwcm9jZXNzKHVwZGF0ZVtrZXldLCBrZXkpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGtleSBvZiBkZWxldGVNZSkge1xuICAgICAgZGVsZXRlIHVwZGF0ZVtrZXldO1xuICAgIH1cbiAgICByZXR1cm4gb3BzO1xuICB9XG5cbiAgLy8gUHJvY2Vzc2VzIHJlbGF0aW9uLXVwZGF0aW5nIG9wZXJhdGlvbnMgZnJvbSBhIFJFU1QtZm9ybWF0IHVwZGF0ZS5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCB1cGRhdGVzIGhhdmUgYmVlbiBwZXJmb3JtZWRcbiAgaGFuZGxlUmVsYXRpb25VcGRhdGVzKGNsYXNzTmFtZTogc3RyaW5nLCBvYmplY3RJZDogc3RyaW5nLCB1cGRhdGU6IGFueSwgb3BzOiBhbnkpIHtcbiAgICB2YXIgcGVuZGluZyA9IFtdO1xuICAgIG9iamVjdElkID0gdXBkYXRlLm9iamVjdElkIHx8IG9iamVjdElkO1xuICAgIG9wcy5mb3JFYWNoKCh7a2V5LCBvcH0pID0+IHtcbiAgICAgIGlmICghb3ApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKG9wLl9fb3AgPT0gJ0FkZFJlbGF0aW9uJykge1xuICAgICAgICBmb3IgKGNvbnN0IG9iamVjdCBvZiBvcC5vYmplY3RzKSB7XG4gICAgICAgICAgcGVuZGluZy5wdXNoKHRoaXMuYWRkUmVsYXRpb24oa2V5LCBjbGFzc05hbWUsXG4gICAgICAgICAgICBvYmplY3RJZCxcbiAgICAgICAgICAgIG9iamVjdC5vYmplY3RJZCkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChvcC5fX29wID09ICdSZW1vdmVSZWxhdGlvbicpIHtcbiAgICAgICAgZm9yIChjb25zdCBvYmplY3Qgb2Ygb3Aub2JqZWN0cykge1xuICAgICAgICAgIHBlbmRpbmcucHVzaCh0aGlzLnJlbW92ZVJlbGF0aW9uKGtleSwgY2xhc3NOYW1lLFxuICAgICAgICAgICAgb2JqZWN0SWQsXG4gICAgICAgICAgICBvYmplY3Qub2JqZWN0SWQpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHBlbmRpbmcpO1xuICB9XG5cbiAgLy8gQWRkcyBhIHJlbGF0aW9uLlxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSBpZmYgdGhlIGFkZCB3YXMgc3VjY2Vzc2Z1bC5cbiAgYWRkUmVsYXRpb24oa2V5OiBzdHJpbmcsIGZyb21DbGFzc05hbWU6IHN0cmluZywgZnJvbUlkOiBzdHJpbmcsIHRvSWQ6IHN0cmluZykge1xuICAgIGNvbnN0IGRvYyA9IHtcbiAgICAgIHJlbGF0ZWRJZDogdG9JZCxcbiAgICAgIG93bmluZ0lkOiBmcm9tSWRcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIudXBzZXJ0T25lT2JqZWN0KGBfSm9pbjoke2tleX06JHtmcm9tQ2xhc3NOYW1lfWAsIHJlbGF0aW9uU2NoZW1hLCBkb2MsIGRvYyk7XG4gIH1cblxuICAvLyBSZW1vdmVzIGEgcmVsYXRpb24uXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgc3VjY2Vzc2Z1bGx5IGlmZiB0aGUgcmVtb3ZlIHdhc1xuICAvLyBzdWNjZXNzZnVsLlxuICByZW1vdmVSZWxhdGlvbihrZXk6IHN0cmluZywgZnJvbUNsYXNzTmFtZTogc3RyaW5nLCBmcm9tSWQ6IHN0cmluZywgdG9JZDogc3RyaW5nKSB7XG4gICAgdmFyIGRvYyA9IHtcbiAgICAgIHJlbGF0ZWRJZDogdG9JZCxcbiAgICAgIG93bmluZ0lkOiBmcm9tSWRcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuZGVsZXRlT2JqZWN0c0J5UXVlcnkoYF9Kb2luOiR7a2V5fToke2Zyb21DbGFzc05hbWV9YCwgcmVsYXRpb25TY2hlbWEsIGRvYylcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIC8vIFdlIGRvbid0IGNhcmUgaWYgdGhleSB0cnkgdG8gZGVsZXRlIGEgbm9uLWV4aXN0ZW50IHJlbGF0aW9uLlxuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBSZW1vdmVzIG9iamVjdHMgbWF0Y2hlcyB0aGlzIHF1ZXJ5IGZyb20gdGhlIGRhdGFiYXNlLlxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSBpZmYgdGhlIG9iamVjdCB3YXNcbiAgLy8gZGVsZXRlZC5cbiAgLy8gT3B0aW9uczpcbiAgLy8gICBhY2w6ICBhIGxpc3Qgb2Ygc3RyaW5ncy4gSWYgdGhlIG9iamVjdCB0byBiZSB1cGRhdGVkIGhhcyBhbiBBQ0wsXG4gIC8vICAgICAgICAgb25lIG9mIHRoZSBwcm92aWRlZCBzdHJpbmdzIG11c3QgcHJvdmlkZSB0aGUgY2FsbGVyIHdpdGhcbiAgLy8gICAgICAgICB3cml0ZSBwZXJtaXNzaW9ucy5cbiAgZGVzdHJveShjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IGFueSwgeyBhY2wgfTogUXVlcnlPcHRpb25zID0ge30pOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IGlzTWFzdGVyID0gYWNsID09PSB1bmRlZmluZWQ7XG4gICAgY29uc3QgYWNsR3JvdXAgPSBhY2wgfHwgW107XG5cbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hKClcbiAgICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4ge1xuICAgICAgICByZXR1cm4gKGlzTWFzdGVyID8gUHJvbWlzZS5yZXNvbHZlKCkgOiBzY2hlbWFDb250cm9sbGVyLnZhbGlkYXRlUGVybWlzc2lvbihjbGFzc05hbWUsIGFjbEdyb3VwLCAnZGVsZXRlJykpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFpc01hc3Rlcikge1xuICAgICAgICAgICAgICBxdWVyeSA9IHRoaXMuYWRkUG9pbnRlclBlcm1pc3Npb25zKHNjaGVtYUNvbnRyb2xsZXIsIGNsYXNzTmFtZSwgJ2RlbGV0ZScsIHF1ZXJ5LCBhY2xHcm91cCk7XG4gICAgICAgICAgICAgIGlmICghcXVlcnkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ09iamVjdCBub3QgZm91bmQuJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGRlbGV0ZSBieSBxdWVyeVxuICAgICAgICAgICAgaWYgKGFjbCkge1xuICAgICAgICAgICAgICBxdWVyeSA9IGFkZFdyaXRlQUNMKHF1ZXJ5LCBhY2wpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsaWRhdGVRdWVyeShxdWVyeSk7XG4gICAgICAgICAgICByZXR1cm4gc2NoZW1hQ29udHJvbGxlci5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lKVxuICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAvLyBJZiB0aGUgc2NoZW1hIGRvZXNuJ3QgZXhpc3QsIHByZXRlbmQgaXQgZXhpc3RzIHdpdGggbm8gZmllbGRzLiBUaGlzIGJlaGF2aW9yXG4gICAgICAgICAgICAgIC8vIHdpbGwgbGlrZWx5IG5lZWQgcmV2aXNpdGluZy5cbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZmllbGRzOiB7fSB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLnRoZW4ocGFyc2VGb3JtYXRTY2hlbWEgPT4gdGhpcy5hZGFwdGVyLmRlbGV0ZU9iamVjdHNCeVF1ZXJ5KGNsYXNzTmFtZSwgcGFyc2VGb3JtYXRTY2hlbWEsIHF1ZXJ5KSlcbiAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgLy8gV2hlbiBkZWxldGluZyBzZXNzaW9ucyB3aGlsZSBjaGFuZ2luZyBwYXNzd29yZHMsIGRvbid0IHRocm93IGFuIGVycm9yIGlmIHRoZXkgZG9uJ3QgaGF2ZSBhbnkgc2Vzc2lvbnMuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzTmFtZSA9PT0gXCJfU2Vzc2lvblwiICYmIGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIEluc2VydHMgYW4gb2JqZWN0IGludG8gdGhlIGRhdGFiYXNlLlxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSBpZmYgdGhlIG9iamVjdCBzYXZlZC5cbiAgY3JlYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBvYmplY3Q6IGFueSwgeyBhY2wgfTogUXVlcnlPcHRpb25zID0ge30pOiBQcm9taXNlPGFueT4ge1xuICAvLyBNYWtlIGEgY29weSBvZiB0aGUgb2JqZWN0LCBzbyB3ZSBkb24ndCBtdXRhdGUgdGhlIGluY29taW5nIGRhdGEuXG4gICAgY29uc3Qgb3JpZ2luYWxPYmplY3QgPSBvYmplY3Q7XG4gICAgb2JqZWN0ID0gdHJhbnNmb3JtT2JqZWN0QUNMKG9iamVjdCk7XG5cbiAgICBvYmplY3QuY3JlYXRlZEF0ID0geyBpc286IG9iamVjdC5jcmVhdGVkQXQsIF9fdHlwZTogJ0RhdGUnIH07XG4gICAgb2JqZWN0LnVwZGF0ZWRBdCA9IHsgaXNvOiBvYmplY3QudXBkYXRlZEF0LCBfX3R5cGU6ICdEYXRlJyB9O1xuXG4gICAgdmFyIGlzTWFzdGVyID0gYWNsID09PSB1bmRlZmluZWQ7XG4gICAgdmFyIGFjbEdyb3VwID0gYWNsIHx8IFtdO1xuICAgIGNvbnN0IHJlbGF0aW9uVXBkYXRlcyA9IHRoaXMuY29sbGVjdFJlbGF0aW9uVXBkYXRlcyhjbGFzc05hbWUsIG51bGwsIG9iamVjdCk7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGVDbGFzc05hbWUoY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5sb2FkU2NoZW1hKCkpXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHtcbiAgICAgICAgcmV0dXJuIChpc01hc3RlciA/IFByb21pc2UucmVzb2x2ZSgpIDogc2NoZW1hQ29udHJvbGxlci52YWxpZGF0ZVBlcm1pc3Npb24oY2xhc3NOYW1lLCBhY2xHcm91cCwgJ2NyZWF0ZScpKVxuICAgICAgICAgIC50aGVuKCgpID0+IHNjaGVtYUNvbnRyb2xsZXIuZW5mb3JjZUNsYXNzRXhpc3RzKGNsYXNzTmFtZSkpXG4gICAgICAgICAgLnRoZW4oKCkgPT4gc2NoZW1hQ29udHJvbGxlci5yZWxvYWREYXRhKCkpXG4gICAgICAgICAgLnRoZW4oKCkgPT4gc2NoZW1hQ29udHJvbGxlci5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCB0cnVlKSlcbiAgICAgICAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgICAgICAgdHJhbnNmb3JtQXV0aERhdGEoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSk7XG4gICAgICAgICAgICBmbGF0dGVuVXBkYXRlT3BlcmF0b3JzRm9yQ3JlYXRlKG9iamVjdCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmNyZWF0ZU9iamVjdChjbGFzc05hbWUsIFNjaGVtYUNvbnRyb2xsZXIuY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShzY2hlbWEpLCBvYmplY3QpO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmhhbmRsZVJlbGF0aW9uVXBkYXRlcyhjbGFzc05hbWUsIG9iamVjdC5vYmplY3RJZCwgb2JqZWN0LCByZWxhdGlvblVwZGF0ZXMpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gc2FuaXRpemVEYXRhYmFzZVJlc3VsdChvcmlnaW5hbE9iamVjdCwgcmVzdWx0Lm9wc1swXSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgfSlcbiAgfVxuXG4gIGNhbkFkZEZpZWxkKHNjaGVtYTogU2NoZW1hQ29udHJvbGxlci5TY2hlbWFDb250cm9sbGVyLCBjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0OiBhbnksIGFjbEdyb3VwOiBzdHJpbmdbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNsYXNzU2NoZW1hID0gc2NoZW1hLmRhdGFbY2xhc3NOYW1lXTtcbiAgICBpZiAoIWNsYXNzU2NoZW1hKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIGNvbnN0IGZpZWxkcyA9IE9iamVjdC5rZXlzKG9iamVjdCk7XG4gICAgY29uc3Qgc2NoZW1hRmllbGRzID0gT2JqZWN0LmtleXMoY2xhc3NTY2hlbWEpO1xuICAgIGNvbnN0IG5ld0tleXMgPSBmaWVsZHMuZmlsdGVyKChmaWVsZCkgPT4ge1xuICAgICAgLy8gU2tpcCBmaWVsZHMgdGhhdCBhcmUgdW5zZXRcbiAgICAgIGlmIChvYmplY3RbZmllbGRdICYmIG9iamVjdFtmaWVsZF0uX19vcCAmJiBvYmplY3RbZmllbGRdLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzY2hlbWFGaWVsZHMuaW5kZXhPZihmaWVsZCkgPCAwO1xuICAgIH0pO1xuICAgIGlmIChuZXdLZXlzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBzY2hlbWEudmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZSwgYWNsR3JvdXAsICdhZGRGaWVsZCcpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICAvLyBXb24ndCBkZWxldGUgY29sbGVjdGlvbnMgaW4gdGhlIHN5c3RlbSBuYW1lc3BhY2VcbiAgLyoqXG4gICAqIERlbGV0ZSBhbGwgY2xhc3NlcyBhbmQgY2xlYXJzIHRoZSBzY2hlbWEgY2FjaGVcbiAgICpcbiAgICogQHBhcmFtIHtib29sZWFufSBmYXN0IHNldCB0byB0cnVlIGlmIGl0J3Mgb2sgdG8ganVzdCBkZWxldGUgcm93cyBhbmQgbm90IGluZGV4ZXNcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IHdoZW4gdGhlIGRlbGV0aW9ucyBjb21wbGV0ZXNcbiAgICovXG4gIGRlbGV0ZUV2ZXJ5dGhpbmcoZmFzdDogYm9vbGVhbiA9IGZhbHNlKTogUHJvbWlzZTxhbnk+IHtcbiAgICB0aGlzLnNjaGVtYVByb21pc2UgPSBudWxsO1xuICAgIHJldHVybiBQcm9taXNlLmFsbChbXG4gICAgICB0aGlzLmFkYXB0ZXIuZGVsZXRlQWxsQ2xhc3NlcyhmYXN0KSxcbiAgICAgIHRoaXMuc2NoZW1hQ2FjaGUuY2xlYXIoKVxuICAgIF0pO1xuICB9XG5cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSBsaXN0IG9mIHJlbGF0ZWQgaWRzIGdpdmVuIGFuIG93bmluZyBpZC5cbiAgLy8gY2xhc3NOYW1lIGhlcmUgaXMgdGhlIG93bmluZyBjbGFzc05hbWUuXG4gIHJlbGF0ZWRJZHMoY2xhc3NOYW1lOiBzdHJpbmcsIGtleTogc3RyaW5nLCBvd25pbmdJZDogc3RyaW5nLCBxdWVyeU9wdGlvbnM6IFF1ZXJ5T3B0aW9ucyk6IFByb21pc2U8QXJyYXk8c3RyaW5nPj4ge1xuICAgIGNvbnN0IHsgc2tpcCwgbGltaXQsIHNvcnQgfSA9IHF1ZXJ5T3B0aW9ucztcbiAgICBjb25zdCBmaW5kT3B0aW9ucyA9IHt9O1xuICAgIGlmIChzb3J0ICYmIHNvcnQuY3JlYXRlZEF0ICYmIHRoaXMuYWRhcHRlci5jYW5Tb3J0T25Kb2luVGFibGVzKSB7XG4gICAgICBmaW5kT3B0aW9ucy5zb3J0ID0geyAnX2lkJyA6IHNvcnQuY3JlYXRlZEF0IH07XG4gICAgICBmaW5kT3B0aW9ucy5saW1pdCA9IGxpbWl0O1xuICAgICAgZmluZE9wdGlvbnMuc2tpcCA9IHNraXA7XG4gICAgICBxdWVyeU9wdGlvbnMuc2tpcCA9IDA7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuZmluZChqb2luVGFibGVOYW1lKGNsYXNzTmFtZSwga2V5KSwgcmVsYXRpb25TY2hlbWEsIHsgb3duaW5nSWQgfSwgZmluZE9wdGlvbnMpXG4gICAgICAudGhlbihyZXN1bHRzID0+IHJlc3VsdHMubWFwKHJlc3VsdCA9PiByZXN1bHQucmVsYXRlZElkKSk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSBsaXN0IG9mIG93bmluZyBpZHMgZ2l2ZW4gc29tZSByZWxhdGVkIGlkcy5cbiAgLy8gY2xhc3NOYW1lIGhlcmUgaXMgdGhlIG93bmluZyBjbGFzc05hbWUuXG4gIG93bmluZ0lkcyhjbGFzc05hbWU6IHN0cmluZywga2V5OiBzdHJpbmcsIHJlbGF0ZWRJZHM6IHN0cmluZ1tdKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuZmluZChqb2luVGFibGVOYW1lKGNsYXNzTmFtZSwga2V5KSwgcmVsYXRpb25TY2hlbWEsIHsgcmVsYXRlZElkOiB7ICckaW4nOiByZWxhdGVkSWRzIH0gfSwge30pXG4gICAgICAudGhlbihyZXN1bHRzID0+IHJlc3VsdHMubWFwKHJlc3VsdCA9PiByZXN1bHQub3duaW5nSWQpKTtcbiAgfVxuXG4gIC8vIE1vZGlmaWVzIHF1ZXJ5IHNvIHRoYXQgaXQgbm8gbG9uZ2VyIGhhcyAkaW4gb24gcmVsYXRpb24gZmllbGRzLCBvclxuICAvLyBlcXVhbC10by1wb2ludGVyIGNvbnN0cmFpbnRzIG9uIHJlbGF0aW9uIGZpZWxkcy5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHF1ZXJ5IGlzIG11dGF0ZWRcbiAgcmVkdWNlSW5SZWxhdGlvbihjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IGFueSwgc2NoZW1hOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAvLyBTZWFyY2ggZm9yIGFuIGluLXJlbGF0aW9uIG9yIGVxdWFsLXRvLXJlbGF0aW9uXG4gIC8vIE1ha2UgaXQgc2VxdWVudGlhbCBmb3Igbm93LCBub3Qgc3VyZSBvZiBwYXJhbGxlaXphdGlvbiBzaWRlIGVmZmVjdHNcbiAgICBpZiAocXVlcnlbJyRvciddKSB7XG4gICAgICBjb25zdCBvcnMgPSBxdWVyeVsnJG9yJ107XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwob3JzLm1hcCgoYVF1ZXJ5LCBpbmRleCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWR1Y2VJblJlbGF0aW9uKGNsYXNzTmFtZSwgYVF1ZXJ5LCBzY2hlbWEpLnRoZW4oKGFRdWVyeSkgPT4ge1xuICAgICAgICAgIHF1ZXJ5Wyckb3InXVtpbmRleF0gPSBhUXVlcnk7XG4gICAgICAgIH0pO1xuICAgICAgfSkpLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHF1ZXJ5KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LmtleXMocXVlcnkpLm1hcCgoa2V5KSA9PiB7XG4gICAgICBjb25zdCB0ID0gc2NoZW1hLmdldEV4cGVjdGVkVHlwZShjbGFzc05hbWUsIGtleSk7XG4gICAgICBpZiAoIXQgfHwgdC50eXBlICE9PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocXVlcnkpO1xuICAgICAgfVxuICAgICAgbGV0IHF1ZXJpZXM6ID9hbnlbXSA9IG51bGw7XG4gICAgICBpZiAocXVlcnlba2V5XSAmJiAocXVlcnlba2V5XVsnJGluJ10gfHwgcXVlcnlba2V5XVsnJG5lJ10gfHwgcXVlcnlba2V5XVsnJG5pbiddIHx8IHF1ZXJ5W2tleV0uX190eXBlID09ICdQb2ludGVyJykpIHtcbiAgICAgIC8vIEJ1aWxkIHRoZSBsaXN0IG9mIHF1ZXJpZXNcbiAgICAgICAgcXVlcmllcyA9IE9iamVjdC5rZXlzKHF1ZXJ5W2tleV0pLm1hcCgoY29uc3RyYWludEtleSkgPT4ge1xuICAgICAgICAgIGxldCByZWxhdGVkSWRzO1xuICAgICAgICAgIGxldCBpc05lZ2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgaWYgKGNvbnN0cmFpbnRLZXkgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgICAgIHJlbGF0ZWRJZHMgPSBbcXVlcnlba2V5XS5vYmplY3RJZF07XG4gICAgICAgICAgfSBlbHNlIGlmIChjb25zdHJhaW50S2V5ID09ICckaW4nKSB7XG4gICAgICAgICAgICByZWxhdGVkSWRzID0gcXVlcnlba2V5XVsnJGluJ10ubWFwKHIgPT4gci5vYmplY3RJZCk7XG4gICAgICAgICAgfSBlbHNlIGlmIChjb25zdHJhaW50S2V5ID09ICckbmluJykge1xuICAgICAgICAgICAgaXNOZWdhdGlvbiA9IHRydWU7XG4gICAgICAgICAgICByZWxhdGVkSWRzID0gcXVlcnlba2V5XVsnJG5pbiddLm1hcChyID0+IHIub2JqZWN0SWQpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY29uc3RyYWludEtleSA9PSAnJG5lJykge1xuICAgICAgICAgICAgaXNOZWdhdGlvbiA9IHRydWU7XG4gICAgICAgICAgICByZWxhdGVkSWRzID0gW3F1ZXJ5W2tleV1bJyRuZSddLm9iamVjdElkXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaXNOZWdhdGlvbixcbiAgICAgICAgICAgIHJlbGF0ZWRJZHNcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcXVlcmllcyA9IFt7aXNOZWdhdGlvbjogZmFsc2UsIHJlbGF0ZWRJZHM6IFtdfV07XG4gICAgICB9XG5cbiAgICAgIC8vIHJlbW92ZSB0aGUgY3VycmVudCBxdWVyeUtleSBhcyB3ZSBkb24sdCBuZWVkIGl0IGFueW1vcmVcbiAgICAgIGRlbGV0ZSBxdWVyeVtrZXldO1xuICAgICAgLy8gZXhlY3V0ZSBlYWNoIHF1ZXJ5IGluZGVwZW5kZW50bHkgdG8gYnVpbGQgdGhlIGxpc3Qgb2ZcbiAgICAgIC8vICRpbiAvICRuaW5cbiAgICAgIGNvbnN0IHByb21pc2VzID0gcXVlcmllcy5tYXAoKHEpID0+IHtcbiAgICAgICAgaWYgKCFxKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm93bmluZ0lkcyhjbGFzc05hbWUsIGtleSwgcS5yZWxhdGVkSWRzKS50aGVuKChpZHMpID0+IHtcbiAgICAgICAgICBpZiAocS5pc05lZ2F0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmFkZE5vdEluT2JqZWN0SWRzSWRzKGlkcywgcXVlcnkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmFkZEluT2JqZWN0SWRzSWRzKGlkcywgcXVlcnkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0pXG5cbiAgICB9KVxuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocXVlcnkpO1xuICAgIH0pXG4gIH1cblxuICAvLyBNb2RpZmllcyBxdWVyeSBzbyB0aGF0IGl0IG5vIGxvbmdlciBoYXMgJHJlbGF0ZWRUb1xuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gcXVlcnkgaXMgbXV0YXRlZFxuICByZWR1Y2VSZWxhdGlvbktleXMoY2xhc3NOYW1lOiBzdHJpbmcsIHF1ZXJ5OiBhbnksIHF1ZXJ5T3B0aW9uczogYW55KTogP1Byb21pc2U8dm9pZD4ge1xuXG4gICAgaWYgKHF1ZXJ5Wyckb3InXSkge1xuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHF1ZXJ5Wyckb3InXS5tYXAoKGFRdWVyeSkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWR1Y2VSZWxhdGlvbktleXMoY2xhc3NOYW1lLCBhUXVlcnksIHF1ZXJ5T3B0aW9ucyk7XG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgdmFyIHJlbGF0ZWRUbyA9IHF1ZXJ5WyckcmVsYXRlZFRvJ107XG4gICAgaWYgKHJlbGF0ZWRUbykge1xuICAgICAgcmV0dXJuIHRoaXMucmVsYXRlZElkcyhcbiAgICAgICAgcmVsYXRlZFRvLm9iamVjdC5jbGFzc05hbWUsXG4gICAgICAgIHJlbGF0ZWRUby5rZXksXG4gICAgICAgIHJlbGF0ZWRUby5vYmplY3Qub2JqZWN0SWQsXG4gICAgICAgIHF1ZXJ5T3B0aW9ucylcbiAgICAgICAgLnRoZW4oKGlkcykgPT4ge1xuICAgICAgICAgIGRlbGV0ZSBxdWVyeVsnJHJlbGF0ZWRUbyddO1xuICAgICAgICAgIHRoaXMuYWRkSW5PYmplY3RJZHNJZHMoaWRzLCBxdWVyeSk7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucmVkdWNlUmVsYXRpb25LZXlzKGNsYXNzTmFtZSwgcXVlcnksIHF1ZXJ5T3B0aW9ucyk7XG4gICAgICAgIH0pLnRoZW4oKCkgPT4ge30pO1xuICAgIH1cbiAgfVxuXG4gIGFkZEluT2JqZWN0SWRzSWRzKGlkczogP0FycmF5PHN0cmluZz4gPSBudWxsLCBxdWVyeTogYW55KSB7XG4gICAgY29uc3QgaWRzRnJvbVN0cmluZzogP0FycmF5PHN0cmluZz4gPSB0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT09ICdzdHJpbmcnID8gW3F1ZXJ5Lm9iamVjdElkXSA6IG51bGw7XG4gICAgY29uc3QgaWRzRnJvbUVxOiA/QXJyYXk8c3RyaW5nPiA9IHF1ZXJ5Lm9iamVjdElkICYmIHF1ZXJ5Lm9iamVjdElkWyckZXEnXSA/IFtxdWVyeS5vYmplY3RJZFsnJGVxJ11dIDogbnVsbDtcbiAgICBjb25zdCBpZHNGcm9tSW46ID9BcnJheTxzdHJpbmc+ID0gcXVlcnkub2JqZWN0SWQgJiYgcXVlcnkub2JqZWN0SWRbJyRpbiddID8gcXVlcnkub2JqZWN0SWRbJyRpbiddIDogbnVsbDtcblxuICAgIC8vIEBmbG93LWRpc2FibGUtbmV4dFxuICAgIGNvbnN0IGFsbElkczogQXJyYXk8QXJyYXk8c3RyaW5nPj4gPSBbaWRzRnJvbVN0cmluZywgaWRzRnJvbUVxLCBpZHNGcm9tSW4sIGlkc10uZmlsdGVyKGxpc3QgPT4gbGlzdCAhPT0gbnVsbCk7XG4gICAgY29uc3QgdG90YWxMZW5ndGggPSBhbGxJZHMucmVkdWNlKChtZW1vLCBsaXN0KSA9PiBtZW1vICsgbGlzdC5sZW5ndGgsIDApO1xuXG4gICAgbGV0IGlkc0ludGVyc2VjdGlvbiA9IFtdO1xuICAgIGlmICh0b3RhbExlbmd0aCA+IDEyNSkge1xuICAgICAgaWRzSW50ZXJzZWN0aW9uID0gaW50ZXJzZWN0LmJpZyhhbGxJZHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZHNJbnRlcnNlY3Rpb24gPSBpbnRlcnNlY3QoYWxsSWRzKTtcbiAgICB9XG5cbiAgICAvLyBOZWVkIHRvIG1ha2Ugc3VyZSB3ZSBkb24ndCBjbG9iYmVyIGV4aXN0aW5nIHNob3J0aGFuZCAkZXEgY29uc3RyYWludHMgb24gb2JqZWN0SWQuXG4gICAgaWYgKCEoJ29iamVjdElkJyBpbiBxdWVyeSkpIHtcbiAgICAgIHF1ZXJ5Lm9iamVjdElkID0ge1xuICAgICAgICAkaW46IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcXVlcnkub2JqZWN0SWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBxdWVyeS5vYmplY3RJZCA9IHtcbiAgICAgICAgJGluOiB1bmRlZmluZWQsXG4gICAgICAgICRlcTogcXVlcnkub2JqZWN0SWRcbiAgICAgIH07XG4gICAgfVxuICAgIHF1ZXJ5Lm9iamVjdElkWyckaW4nXSA9IGlkc0ludGVyc2VjdGlvbjtcblxuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIGFkZE5vdEluT2JqZWN0SWRzSWRzKGlkczogc3RyaW5nW10gPSBbXSwgcXVlcnk6IGFueSkge1xuICAgIGNvbnN0IGlkc0Zyb21OaW4gPSBxdWVyeS5vYmplY3RJZCAmJiBxdWVyeS5vYmplY3RJZFsnJG5pbiddID8gcXVlcnkub2JqZWN0SWRbJyRuaW4nXSA6IFtdO1xuICAgIGxldCBhbGxJZHMgPSBbLi4uaWRzRnJvbU5pbiwuLi5pZHNdLmZpbHRlcihsaXN0ID0+IGxpc3QgIT09IG51bGwpO1xuXG4gICAgLy8gbWFrZSBhIHNldCBhbmQgc3ByZWFkIHRvIHJlbW92ZSBkdXBsaWNhdGVzXG4gICAgYWxsSWRzID0gWy4uLm5ldyBTZXQoYWxsSWRzKV07XG5cbiAgICAvLyBOZWVkIHRvIG1ha2Ugc3VyZSB3ZSBkb24ndCBjbG9iYmVyIGV4aXN0aW5nIHNob3J0aGFuZCAkZXEgY29uc3RyYWludHMgb24gb2JqZWN0SWQuXG4gICAgaWYgKCEoJ29iamVjdElkJyBpbiBxdWVyeSkpIHtcbiAgICAgIHF1ZXJ5Lm9iamVjdElkID0ge1xuICAgICAgICAkbmluOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHF1ZXJ5Lm9iamVjdElkID09PSAnc3RyaW5nJykge1xuICAgICAgcXVlcnkub2JqZWN0SWQgPSB7XG4gICAgICAgICRuaW46IHVuZGVmaW5lZCxcbiAgICAgICAgJGVxOiBxdWVyeS5vYmplY3RJZFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBxdWVyeS5vYmplY3RJZFsnJG5pbiddID0gYWxsSWRzO1xuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIC8vIFJ1bnMgYSBxdWVyeSBvbiB0aGUgZGF0YWJhc2UuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBsaXN0IG9mIGl0ZW1zLlxuICAvLyBPcHRpb25zOlxuICAvLyAgIHNraXAgICAgbnVtYmVyIG9mIHJlc3VsdHMgdG8gc2tpcC5cbiAgLy8gICBsaW1pdCAgIGxpbWl0IHRvIHRoaXMgbnVtYmVyIG9mIHJlc3VsdHMuXG4gIC8vICAgc29ydCAgICBhbiBvYmplY3Qgd2hlcmUga2V5cyBhcmUgdGhlIGZpZWxkcyB0byBzb3J0IGJ5LlxuICAvLyAgICAgICAgICAgdGhlIHZhbHVlIGlzICsxIGZvciBhc2NlbmRpbmcsIC0xIGZvciBkZXNjZW5kaW5nLlxuICAvLyAgIGNvdW50ICAgcnVuIGEgY291bnQgaW5zdGVhZCBvZiByZXR1cm5pbmcgcmVzdWx0cy5cbiAgLy8gICBhY2wgICAgIHJlc3RyaWN0IHRoaXMgb3BlcmF0aW9uIHdpdGggYW4gQUNMIGZvciB0aGUgcHJvdmlkZWQgYXJyYXlcbiAgLy8gICAgICAgICAgIG9mIHVzZXIgb2JqZWN0SWRzIGFuZCByb2xlcy4gYWNsOiBudWxsIG1lYW5zIG5vIHVzZXIuXG4gIC8vICAgICAgICAgICB3aGVuIHRoaXMgZmllbGQgaXMgbm90IHByZXNlbnQsIGRvbid0IGRvIGFueXRoaW5nIHJlZ2FyZGluZyBBQ0xzLlxuICAvLyBUT0RPOiBtYWtlIHVzZXJJZHMgbm90IG5lZWRlZCBoZXJlLiBUaGUgZGIgYWRhcHRlciBzaG91bGRuJ3Qga25vd1xuICAvLyBhbnl0aGluZyBhYm91dCB1c2VycywgaWRlYWxseS4gVGhlbiwgaW1wcm92ZSB0aGUgZm9ybWF0IG9mIHRoZSBBQ0xcbiAgLy8gYXJnIHRvIHdvcmsgbGlrZSB0aGUgb3RoZXJzLlxuICBmaW5kKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogYW55LCB7XG4gICAgc2tpcCxcbiAgICBsaW1pdCxcbiAgICBhY2wsXG4gICAgc29ydCA9IHt9LFxuICAgIGNvdW50LFxuICAgIGtleXMsXG4gICAgb3AsXG4gICAgZGlzdGluY3QsXG4gICAgcGlwZWxpbmUsXG4gICAgcmVhZFByZWZlcmVuY2UsXG4gICAgaXNXcml0ZSxcbiAgfTogYW55ID0ge30pOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IGlzTWFzdGVyID0gYWNsID09PSB1bmRlZmluZWQ7XG4gICAgY29uc3QgYWNsR3JvdXAgPSBhY2wgfHwgW107XG4gICAgb3AgPSBvcCB8fCAodHlwZW9mIHF1ZXJ5Lm9iamVjdElkID09ICdzdHJpbmcnICYmIE9iamVjdC5rZXlzKHF1ZXJ5KS5sZW5ndGggPT09IDEgPyAnZ2V0JyA6ICdmaW5kJyk7XG4gICAgLy8gQ291bnQgb3BlcmF0aW9uIGlmIGNvdW50aW5nXG4gICAgb3AgPSAoY291bnQgPT09IHRydWUgPyAnY291bnQnIDogb3ApO1xuXG4gICAgbGV0IGNsYXNzRXhpc3RzID0gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcy5sb2FkU2NoZW1hKClcbiAgICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4ge1xuICAgICAgICAvL0FsbG93IHZvbGF0aWxlIGNsYXNzZXMgaWYgcXVlcnlpbmcgd2l0aCBNYXN0ZXIgKGZvciBfUHVzaFN0YXR1cylcbiAgICAgICAgLy9UT0RPOiBNb3ZlIHZvbGF0aWxlIGNsYXNzZXMgY29uY2VwdCBpbnRvIG1vbmdvIGFkYXB0ZXIsIHBvc3RncmVzIGFkYXB0ZXIgc2hvdWxkbid0IGNhcmVcbiAgICAgICAgLy90aGF0IGFwaS5wYXJzZS5jb20gYnJlYWtzIHdoZW4gX1B1c2hTdGF0dXMgZXhpc3RzIGluIG1vbmdvLlxuICAgICAgICByZXR1cm4gc2NoZW1hQ29udHJvbGxlci5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCBpc01hc3RlcilcbiAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIC8vIEJlaGF2aW9yIGZvciBub24tZXhpc3RlbnQgY2xhc3NlcyBpcyBraW5kYSB3ZWlyZCBvbiBQYXJzZS5jb20uIFByb2JhYmx5IGRvZXNuJ3QgbWF0dGVyIHRvbyBtdWNoLlxuICAgICAgICAgIC8vIEZvciBub3csIHByZXRlbmQgdGhlIGNsYXNzIGV4aXN0cyBidXQgaGFzIG5vIG9iamVjdHMsXG4gICAgICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjbGFzc0V4aXN0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXR1cm4geyBmaWVsZHM6IHt9IH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKHNjaGVtYSA9PiB7XG4gICAgICAgICAgLy8gUGFyc2UuY29tIHRyZWF0cyBxdWVyaWVzIG9uIF9jcmVhdGVkX2F0IGFuZCBfdXBkYXRlZF9hdCBhcyBpZiB0aGV5IHdlcmUgcXVlcmllcyBvbiBjcmVhdGVkQXQgYW5kIHVwZGF0ZWRBdCxcbiAgICAgICAgICAvLyBzbyBkdXBsaWNhdGUgdGhhdCBiZWhhdmlvciBoZXJlLiBJZiBib3RoIGFyZSBzcGVjaWZpZWQsIHRoZSBjb3JyZWN0IGJlaGF2aW9yIHRvIG1hdGNoIFBhcnNlLmNvbSBpcyB0b1xuICAgICAgICAgIC8vIHVzZSB0aGUgb25lIHRoYXQgYXBwZWFycyBmaXJzdCBpbiB0aGUgc29ydCBsaXN0LlxuICAgICAgICAgICAgaWYgKHNvcnQuX2NyZWF0ZWRfYXQpIHtcbiAgICAgICAgICAgICAgc29ydC5jcmVhdGVkQXQgPSBzb3J0Ll9jcmVhdGVkX2F0O1xuICAgICAgICAgICAgICBkZWxldGUgc29ydC5fY3JlYXRlZF9hdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzb3J0Ll91cGRhdGVkX2F0KSB7XG4gICAgICAgICAgICAgIHNvcnQudXBkYXRlZEF0ID0gc29ydC5fdXBkYXRlZF9hdDtcbiAgICAgICAgICAgICAgZGVsZXRlIHNvcnQuX3VwZGF0ZWRfYXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBxdWVyeU9wdGlvbnMgPSB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCByZWFkUHJlZmVyZW5jZSB9O1xuICAgICAgICAgICAgT2JqZWN0LmtleXMoc29ydCkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICBpZiAoZmllbGROYW1lLm1hdGNoKC9eYXV0aERhdGFcXC4oW2EtekEtWjAtOV9dKylcXC5pZCQvKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLCBgQ2Fubm90IHNvcnQgYnkgJHtmaWVsZE5hbWV9YCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3Qgcm9vdEZpZWxkTmFtZSA9IGdldFJvb3RGaWVsZE5hbWUoZmllbGROYW1lKTtcbiAgICAgICAgICAgICAgaWYgKCFTY2hlbWFDb250cm9sbGVyLmZpZWxkTmFtZUlzVmFsaWQocm9vdEZpZWxkTmFtZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSwgYEludmFsaWQgZmllbGQgbmFtZTogJHtmaWVsZE5hbWV9LmApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiAoaXNNYXN0ZXIgPyBQcm9taXNlLnJlc29sdmUoKSA6IHNjaGVtYUNvbnRyb2xsZXIudmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZSwgYWNsR3JvdXAsIG9wKSlcbiAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5yZWR1Y2VSZWxhdGlvbktleXMoY2xhc3NOYW1lLCBxdWVyeSwgcXVlcnlPcHRpb25zKSlcbiAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5yZWR1Y2VJblJlbGF0aW9uKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYUNvbnRyb2xsZXIpKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc01hc3Rlcikge1xuICAgICAgICAgICAgICAgICAgcXVlcnkgPSB0aGlzLmFkZFBvaW50ZXJQZXJtaXNzaW9ucyhzY2hlbWFDb250cm9sbGVyLCBjbGFzc05hbWUsIG9wLCBxdWVyeSwgYWNsR3JvdXApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgICBpZiAob3AgPT0gJ2dldCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdPYmplY3Qgbm90IGZvdW5kLicpO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWlzTWFzdGVyKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoaXNXcml0ZSkge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IGFkZFdyaXRlQUNMKHF1ZXJ5LCBhY2xHcm91cCk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IGFkZFJlYWRBQ0wocXVlcnksIGFjbEdyb3VwKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFsaWRhdGVRdWVyeShxdWVyeSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50KSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXNzRXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5jb3VudChjbGFzc05hbWUsIHNjaGVtYSwgcXVlcnksIHJlYWRQcmVmZXJlbmNlKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9ICBlbHNlIGlmIChkaXN0aW5jdCkge1xuICAgICAgICAgICAgICAgICAgaWYgKCFjbGFzc0V4aXN0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmRpc3RpbmN0KGNsYXNzTmFtZSwgc2NoZW1hLCBxdWVyeSwgZGlzdGluY3QpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gIGVsc2UgaWYgKHBpcGVsaW5lKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXNzRXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIuYWdncmVnYXRlKGNsYXNzTmFtZSwgc2NoZW1hLCBwaXBlbGluZSwgcmVhZFByZWZlcmVuY2UpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmZpbmQoY2xhc3NOYW1lLCBzY2hlbWEsIHF1ZXJ5LCBxdWVyeU9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKG9iamVjdHMgPT4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBvYmplY3QgPSB1bnRyYW5zZm9ybU9iamVjdEFDTChvYmplY3QpO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmaWx0ZXJTZW5zaXRpdmVEYXRhKGlzTWFzdGVyLCBhY2xHcm91cCwgY2xhc3NOYW1lLCBvYmplY3QpXG4gICAgICAgICAgICAgICAgICAgIH0pKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGRlbGV0ZVNjaGVtYShjbGFzc05hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlIH0pXG4gICAgICAudGhlbihzY2hlbWFDb250cm9sbGVyID0+IHNjaGVtYUNvbnRyb2xsZXIuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSwgdHJ1ZSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJldHVybiB7IGZpZWxkczoge30gfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC50aGVuKChzY2hlbWE6IGFueSkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xsZWN0aW9uRXhpc3RzKGNsYXNzTmFtZSlcbiAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLmFkYXB0ZXIuY291bnQoY2xhc3NOYW1lLCB7IGZpZWxkczoge30gfSkpXG4gICAgICAgICAgLnRoZW4oY291bnQgPT4ge1xuICAgICAgICAgICAgaWYgKGNvdW50ID4gMCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMjU1LCBgQ2xhc3MgJHtjbGFzc05hbWV9IGlzIG5vdCBlbXB0eSwgY29udGFpbnMgJHtjb3VudH0gb2JqZWN0cywgY2Fubm90IGRyb3Agc2NoZW1hLmApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5kZWxldGVDbGFzcyhjbGFzc05hbWUpO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnRoZW4od2FzUGFyc2VDb2xsZWN0aW9uID0+IHtcbiAgICAgICAgICAgIGlmICh3YXNQYXJzZUNvbGxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgY29uc3QgcmVsYXRpb25GaWVsZE5hbWVzID0gT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcykuZmlsdGVyKGZpZWxkTmFtZSA9PiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1JlbGF0aW9uJyk7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChyZWxhdGlvbkZpZWxkTmFtZXMubWFwKG5hbWUgPT4gdGhpcy5hZGFwdGVyLmRlbGV0ZUNsYXNzKGpvaW5UYWJsZU5hbWUoY2xhc3NOYW1lLCBuYW1lKSkpKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgfSlcbiAgfVxuXG4gIGFkZFBvaW50ZXJQZXJtaXNzaW9ucyhzY2hlbWE6IGFueSwgY2xhc3NOYW1lOiBzdHJpbmcsIG9wZXJhdGlvbjogc3RyaW5nLCBxdWVyeTogYW55LCBhY2xHcm91cDogYW55W10gPSBbXSkge1xuICAvLyBDaGVjayBpZiBjbGFzcyBoYXMgcHVibGljIHBlcm1pc3Npb24gZm9yIG9wZXJhdGlvblxuICAvLyBJZiB0aGUgQmFzZUNMUCBwYXNzLCBsZXQgZ28gdGhyb3VnaFxuICAgIGlmIChzY2hlbWEudGVzdEJhc2VDTFAoY2xhc3NOYW1lLCBhY2xHcm91cCwgb3BlcmF0aW9uKSkge1xuICAgICAgcmV0dXJuIHF1ZXJ5O1xuICAgIH1cbiAgICBjb25zdCBwZXJtcyA9IHNjaGVtYS5wZXJtc1tjbGFzc05hbWVdO1xuICAgIGNvbnN0IGZpZWxkID0gWydnZXQnLCAnZmluZCddLmluZGV4T2Yob3BlcmF0aW9uKSA+IC0xID8gJ3JlYWRVc2VyRmllbGRzJyA6ICd3cml0ZVVzZXJGaWVsZHMnO1xuICAgIGNvbnN0IHVzZXJBQ0wgPSBhY2xHcm91cC5maWx0ZXIoKGFjbCkgPT4ge1xuICAgICAgcmV0dXJuIGFjbC5pbmRleE9mKCdyb2xlOicpICE9IDAgJiYgYWNsICE9ICcqJztcbiAgICB9KTtcbiAgICAvLyB0aGUgQUNMIHNob3VsZCBoYXZlIGV4YWN0bHkgMSB1c2VyXG4gICAgaWYgKHBlcm1zICYmIHBlcm1zW2ZpZWxkXSAmJiBwZXJtc1tmaWVsZF0ubGVuZ3RoID4gMCkge1xuICAgIC8vIE5vIHVzZXIgc2V0IHJldHVybiB1bmRlZmluZWRcbiAgICAvLyBJZiB0aGUgbGVuZ3RoIGlzID4gMSwgdGhhdCBtZWFucyB3ZSBkaWRuJ3QgZGUtZHVwZSB1c2VycyBjb3JyZWN0bHlcbiAgICAgIGlmICh1c2VyQUNMLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVzZXJJZCA9IHVzZXJBQ0xbMF07XG4gICAgICBjb25zdCB1c2VyUG9pbnRlciA9ICB7XG4gICAgICAgIFwiX190eXBlXCI6IFwiUG9pbnRlclwiLFxuICAgICAgICBcImNsYXNzTmFtZVwiOiBcIl9Vc2VyXCIsXG4gICAgICAgIFwib2JqZWN0SWRcIjogdXNlcklkXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwZXJtRmllbGRzID0gcGVybXNbZmllbGRdO1xuICAgICAgY29uc3Qgb3JzID0gcGVybUZpZWxkcy5tYXAoKGtleSkgPT4ge1xuICAgICAgICBjb25zdCBxID0ge1xuICAgICAgICAgIFtrZXldOiB1c2VyUG9pbnRlclxuICAgICAgICB9O1xuICAgICAgICAvLyBpZiB3ZSBhbHJlYWR5IGhhdmUgYSBjb25zdHJhaW50IG9uIHRoZSBrZXksIHVzZSB0aGUgJGFuZFxuICAgICAgICBpZiAocXVlcnkuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgIHJldHVybiB7JyRhbmQnOiBbcSwgcXVlcnldfTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UganVzdCBhZGQgdGhlIGNvbnN0YWludFxuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgcXVlcnksIHtcbiAgICAgICAgICBbYCR7a2V5fWBdOiB1c2VyUG9pbnRlcixcbiAgICAgICAgfSlcbiAgICAgIH0pO1xuICAgICAgaWYgKG9ycy5sZW5ndGggPiAxKSB7XG4gICAgICAgIHJldHVybiB7JyRvcic6IG9yc307XG4gICAgICB9XG4gICAgICByZXR1cm4gb3JzWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcXVlcnk7XG4gICAgfVxuICB9XG5cbiAgLy8gVE9ETzogY3JlYXRlIGluZGV4ZXMgb24gZmlyc3QgY3JlYXRpb24gb2YgYSBfVXNlciBvYmplY3QuIE90aGVyd2lzZSBpdCdzIGltcG9zc2libGUgdG9cbiAgLy8gaGF2ZSBhIFBhcnNlIGFwcCB3aXRob3V0IGl0IGhhdmluZyBhIF9Vc2VyIGNvbGxlY3Rpb24uXG4gIHBlcmZvcm1Jbml0aWFsaXphdGlvbigpIHtcbiAgICBjb25zdCByZXF1aXJlZFVzZXJGaWVsZHMgPSB7IGZpZWxkczogeyAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0LCAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9Vc2VyIH0gfTtcbiAgICBjb25zdCByZXF1aXJlZFJvbGVGaWVsZHMgPSB7IGZpZWxkczogeyAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0LCAuLi5TY2hlbWFDb250cm9sbGVyLmRlZmF1bHRDb2x1bW5zLl9Sb2xlIH0gfTtcblxuICAgIGNvbnN0IHVzZXJDbGFzc1Byb21pc2UgPSB0aGlzLmxvYWRTY2hlbWEoKVxuICAgICAgLnRoZW4oc2NoZW1hID0+IHNjaGVtYS5lbmZvcmNlQ2xhc3NFeGlzdHMoJ19Vc2VyJykpXG4gICAgY29uc3Qgcm9sZUNsYXNzUHJvbWlzZSA9IHRoaXMubG9hZFNjaGVtYSgpXG4gICAgICAudGhlbihzY2hlbWEgPT4gc2NoZW1hLmVuZm9yY2VDbGFzc0V4aXN0cygnX1JvbGUnKSlcblxuICAgIGNvbnN0IHVzZXJuYW1lVW5pcXVlbmVzcyA9IHVzZXJDbGFzc1Byb21pc2VcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuYWRhcHRlci5lbnN1cmVVbmlxdWVuZXNzKCdfVXNlcicsIHJlcXVpcmVkVXNlckZpZWxkcywgWyd1c2VybmFtZSddKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdVbmFibGUgdG8gZW5zdXJlIHVuaXF1ZW5lc3MgZm9yIHVzZXJuYW1lczogJywgZXJyb3IpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgZW1haWxVbmlxdWVuZXNzID0gdXNlckNsYXNzUHJvbWlzZVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5hZGFwdGVyLmVuc3VyZVVuaXF1ZW5lc3MoJ19Vc2VyJywgcmVxdWlyZWRVc2VyRmllbGRzLCBbJ2VtYWlsJ10pKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1VuYWJsZSB0byBlbnN1cmUgdW5pcXVlbmVzcyBmb3IgdXNlciBlbWFpbCBhZGRyZXNzZXM6ICcsIGVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IHJvbGVVbmlxdWVuZXNzID0gcm9sZUNsYXNzUHJvbWlzZVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5hZGFwdGVyLmVuc3VyZVVuaXF1ZW5lc3MoJ19Sb2xlJywgcmVxdWlyZWRSb2xlRmllbGRzLCBbJ25hbWUnXSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBsb2dnZXIud2FybignVW5hYmxlIHRvIGVuc3VyZSB1bmlxdWVuZXNzIGZvciByb2xlIG5hbWU6ICcsIGVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IGluZGV4UHJvbWlzZSA9IHRoaXMuYWRhcHRlci51cGRhdGVTY2hlbWFXaXRoSW5kZXhlcygpO1xuXG4gICAgLy8gQ3JlYXRlIHRhYmxlcyBmb3Igdm9sYXRpbGUgY2xhc3Nlc1xuICAgIGNvbnN0IGFkYXB0ZXJJbml0ID0gdGhpcy5hZGFwdGVyLnBlcmZvcm1Jbml0aWFsaXphdGlvbih7IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXM6IFNjaGVtYUNvbnRyb2xsZXIuVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyB9KTtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoW3VzZXJuYW1lVW5pcXVlbmVzcywgZW1haWxVbmlxdWVuZXNzLCByb2xlVW5pcXVlbmVzcywgYWRhcHRlckluaXQsIGluZGV4UHJvbWlzZV0pO1xuICB9XG5cbiAgc3RhdGljIF92YWxpZGF0ZVF1ZXJ5OiAoKGFueSkgPT4gdm9pZClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBEYXRhYmFzZUNvbnRyb2xsZXI7XG4vLyBFeHBvc2UgdmFsaWRhdGVRdWVyeSBmb3IgdGVzdHNcbm1vZHVsZS5leHBvcnRzLl92YWxpZGF0ZVF1ZXJ5ID0gdmFsaWRhdGVRdWVyeTtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/FilesController.js b/lib/Controllers/FilesController.js index 8cbfc6596f..eecc598bd6 100644 --- a/lib/Controllers/FilesController.js +++ b/lib/Controllers/FilesController.js @@ -42,9 +42,11 @@ class FilesController extends _AdaptableController2.default { contentType = _mime2.default.getType(filename); } - filename = (0, _cryptoUtils.randomHexString)(32) + '_' + filename; + if (!this.options.preserveFileName) { + filename = (0, _cryptoUtils.randomHexString)(32) + '_' + filename; + } - var location = this.adapter.getFileLocation(config, filename); + const location = this.adapter.getFileLocation(config, filename); return this.adapter.createFile(filename, data, contentType).then(() => { return Promise.resolve({ url: location, @@ -105,4 +107,5 @@ class FilesController extends _AdaptableController2.default { } exports.FilesController = FilesController; -exports.default = FilesController; \ No newline at end of file +exports.default = FilesController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9GaWxlc0NvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsibGVnYWN5RmlsZXNSZWdleCIsIlJlZ0V4cCIsIkZpbGVzQ29udHJvbGxlciIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJnZXRGaWxlRGF0YSIsImNvbmZpZyIsImZpbGVuYW1lIiwiYWRhcHRlciIsImNyZWF0ZUZpbGUiLCJkYXRhIiwiY29udGVudFR5cGUiLCJleHRuYW1lIiwicGF0aCIsImhhc0V4dGVuc2lvbiIsImxlbmd0aCIsIm1pbWUiLCJnZXRFeHRlbnNpb24iLCJnZXRUeXBlIiwib3B0aW9ucyIsInByZXNlcnZlRmlsZU5hbWUiLCJsb2NhdGlvbiIsImdldEZpbGVMb2NhdGlvbiIsInRoZW4iLCJQcm9taXNlIiwicmVzb2x2ZSIsInVybCIsIm5hbWUiLCJkZWxldGVGaWxlIiwiZXhwYW5kRmlsZXNJbk9iamVjdCIsIm9iamVjdCIsIkFycmF5IiwibWFwIiwib2JqIiwia2V5IiwiZmlsZU9iamVjdCIsImZpbGVLZXkiLCJ1bmRlZmluZWQiLCJpbmRleE9mIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwidGVzdCIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJGaWxlc0FkYXB0ZXIiLCJnZXRGaWxlU3RyZWFtIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFQSxNQUFNQSxtQkFBbUIsSUFBSUMsTUFBSixDQUFXLGlGQUFYLENBQXpCLEMsQ0FQQTtBQVNPLE1BQU1DLGVBQU4sU0FBOEJDLDZCQUE5QixDQUFrRDs7QUFFdkRDLGNBQVlDLE1BQVosRUFBb0JDLFFBQXBCLEVBQThCO0FBQzVCLFdBQU8sS0FBS0MsT0FBTCxDQUFhSCxXQUFiLENBQXlCRSxRQUF6QixDQUFQO0FBQ0Q7O0FBRURFLGFBQVdILE1BQVgsRUFBbUJDLFFBQW5CLEVBQTZCRyxJQUE3QixFQUFtQ0MsV0FBbkMsRUFBZ0Q7O0FBRTlD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QUVEQyxnQkFBY3JDLE1BQWQsRUFBc0JDLFFBQXRCLEVBQWdDO0FBQzlCLFdBQU8sS0FBS0MsT0FBTCxDQUFhbUMsYUFBYixDQUEyQnBDLFFBQTNCLENBQVA7QUFDRDtBQS9Fc0Q7O1FBQTVDSixlLEdBQUFBLGU7a0JBa0ZFQSxlIiwiZmlsZSI6IkZpbGVzQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEZpbGVzQ29udHJvbGxlci5qc1xuaW1wb3J0IHsgcmFuZG9tSGV4U3RyaW5nIH0gZnJvbSAnLi4vY3J5cHRvVXRpbHMnO1xuaW1wb3J0IEFkYXB0YWJsZUNvbnRyb2xsZXIgZnJvbSAnLi9BZGFwdGFibGVDb250cm9sbGVyJztcbmltcG9ydCB7IEZpbGVzQWRhcHRlciB9IGZyb20gJy4uL0FkYXB0ZXJzL0ZpbGVzL0ZpbGVzQWRhcHRlcic7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBtaW1lIGZyb20gJ21pbWUnO1xuXG5jb25zdCBsZWdhY3lGaWxlc1JlZ2V4ID0gbmV3IFJlZ0V4cChcIl5bMC05YS1mQS1GXXs4fS1bMC05YS1mQS1GXXs0fS1bMC05YS1mQS1GXXs0fS1bMC05YS1mQS1GXXs0fS1bMC05YS1mQS1GXXsxMn0tLipcIik7XG5cbmV4cG9ydCBjbGFzcyBGaWxlc0NvbnRyb2xsZXIgZXh0ZW5kcyBBZGFwdGFibGVDb250cm9sbGVyIHtcblxuICBnZXRGaWxlRGF0YShjb25maWcsIGZpbGVuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5nZXRGaWxlRGF0YShmaWxlbmFtZSk7XG4gIH1cblxuICBjcmVhdGVGaWxlKGNvbmZpZywgZmlsZW5hbWUsIGRhdGEsIGNvbnRlbnRUeXBlKSB7XG5cbiAgICBjb25zdCBleHRuYW1lID0gcGF0aC5leHRuYW1lKGZpbGVuYW1lKTtcblxuICAgIGNvbnN0IGhhc0V4dGVuc2lvbiA9IGV4dG5hbWUubGVuZ3RoID4gMDtcblxuICAgIGlmICghaGFzRXh0ZW5zaW9uICYmIGNvbnRlbnRUeXBlICYmIG1pbWUuZ2V0RXh0ZW5zaW9uKGNvbnRlbnRUeXBlKSkge1xuICAgICAgZmlsZW5hbWUgPSBmaWxlbmFtZSArICcuJyArIG1pbWUuZ2V0RXh0ZW5zaW9uKGNvbnRlbnRUeXBlKTtcbiAgICB9IGVsc2UgaWYgKGhhc0V4dGVuc2lvbiAmJiAhY29udGVudFR5cGUpIHtcbiAgICAgIGNvbnRlbnRUeXBlID0gbWltZS5nZXRUeXBlKGZpbGVuYW1lKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMub3B0aW9ucy5wcmVzZXJ2ZUZpbGVOYW1lKSB7XG4gICAgICBmaWxlbmFtZSA9IHJhbmRvbUhleFN0cmluZygzMikgKyAnXycgKyBmaWxlbmFtZTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuYWRhcHRlci5nZXRGaWxlTG9jYXRpb24oY29uZmlnLCBmaWxlbmFtZSk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5jcmVhdGVGaWxlKGZpbGVuYW1lLCBkYXRhLCBjb250ZW50VHlwZSkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgdXJsOiBsb2NhdGlvbixcbiAgICAgICAgbmFtZTogZmlsZW5hbWVcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZGVsZXRlRmlsZShjb25maWcsIGZpbGVuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5kZWxldGVGaWxlKGZpbGVuYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kIGZpbGUgcmVmZXJlbmNlcyBpbiBSRVNULWZvcm1hdCBvYmplY3QgYW5kIGFkZHMgdGhlIHVybCBrZXlcbiAgICogd2l0aCB0aGUgY3VycmVudCBtb3VudCBwb2ludCBhbmQgYXBwIGlkLlxuICAgKiBPYmplY3QgbWF5IGJlIGEgc2luZ2xlIG9iamVjdCBvciBsaXN0IG9mIFJFU1QtZm9ybWF0IG9iamVjdHMuXG4gICAqL1xuICBleHBhbmRGaWxlc0luT2JqZWN0KGNvbmZpZywgb2JqZWN0KSB7XG4gICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBvYmplY3QubWFwKChvYmopID0+IHRoaXMuZXhwYW5kRmlsZXNJbk9iamVjdChjb25maWcsIG9iaikpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBjb25zdCBmaWxlT2JqZWN0ID0gb2JqZWN0W2tleV07XG4gICAgICBpZiAoZmlsZU9iamVjdCAmJiBmaWxlT2JqZWN0WydfX3R5cGUnXSA9PT0gJ0ZpbGUnKSB7XG4gICAgICAgIGlmIChmaWxlT2JqZWN0Wyd1cmwnXSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZpbGVuYW1lID0gZmlsZU9iamVjdFsnbmFtZSddO1xuICAgICAgICAvLyBhbGwgZmlsZW5hbWVzIHN0YXJ0aW5nIHdpdGggXCJ0ZnNzLVwiIHNob3VsZCBiZSBmcm9tIGZpbGVzLnBhcnNldGZzcy5jb21cbiAgICAgICAgLy8gYWxsIGZpbGVuYW1lcyBzdGFydGluZyB3aXRoIGEgXCItXCIgc2VwZXJhdGVkIFVVSUQgc2hvdWxkIGJlIGZyb20gZmlsZXMucGFyc2UuY29tXG4gICAgICAgIC8vIGFsbCBvdGhlciBmaWxlbmFtZXMgaGF2ZSBiZWVuIG1pZ3JhdGVkIG9yIGNyZWF0ZWQgZnJvbSBQYXJzZSBTZXJ2ZXJcbiAgICAgICAgaWYgKGNvbmZpZy5maWxlS2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBmaWxlT2JqZWN0Wyd1cmwnXSA9IHRoaXMuYWRhcHRlci5nZXRGaWxlTG9jYXRpb24oY29uZmlnLCBmaWxlbmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGZpbGVuYW1lLmluZGV4T2YoJ3Rmc3MtJykgPT09IDApIHtcbiAgICAgICAgICAgIGZpbGVPYmplY3RbJ3VybCddID0gJ2h0dHA6Ly9maWxlcy5wYXJzZXRmc3MuY29tLycgKyBjb25maWcuZmlsZUtleSArICcvJyArIGVuY29kZVVSSUNvbXBvbmVudChmaWxlbmFtZSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChsZWdhY3lGaWxlc1JlZ2V4LnRlc3QoZmlsZW5hbWUpKSB7XG4gICAgICAgICAgICBmaWxlT2JqZWN0Wyd1cmwnXSA9ICdodHRwOi8vZmlsZXMucGFyc2UuY29tLycgKyBjb25maWcuZmlsZUtleSArICcvJyArIGVuY29kZVVSSUNvbXBvbmVudChmaWxlbmFtZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVPYmplY3RbJ3VybCddID0gdGhpcy5hZGFwdGVyLmdldEZpbGVMb2NhdGlvbihjb25maWcsIGZpbGVuYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHJldHVybiBGaWxlc0FkYXB0ZXI7XG4gIH1cblxuICBnZXRGaWxlU3RyZWFtKGNvbmZpZywgZmlsZW5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmdldEZpbGVTdHJlYW0oZmlsZW5hbWUpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEZpbGVzQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/HooksController.js b/lib/Controllers/HooksController.js index 438db85a7d..ae0ce6a26c 100644 --- a/lib/Controllers/HooksController.js +++ b/lib/Controllers/HooksController.js @@ -19,6 +19,16 @@ var request = _interopRequireWildcard(_request); var _logger = require("../logger"); +var _http = require("http"); + +var _http2 = _interopRequireDefault(_http); + +var _https = require("https"); + +var _https2 = _interopRequireDefault(_https); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } // -disable-next @@ -26,6 +36,12 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; const DefaultHooksCollectionName = "_Hooks"; // -disable-next + +const HTTPAgents = { + http: new _http2.default.Agent({ keepAlive: true }), + https: new _https2.default.Agent({ keepAlive: true }) +}; + class HooksController { constructor(applicationId, databaseController, webhookKey) { @@ -194,6 +210,9 @@ function wrapToHTTPRequest(hook, key) { body: JSON.stringify(jsonBody) }; + const agent = hook.url.startsWith('https') ? HTTPAgents['https'] : HTTPAgents['http']; + jsonRequest.agent = agent; + if (key) { jsonRequest.headers['X-Parse-Webhook-Key'] = key; } else { @@ -235,4 +254,5 @@ function wrapToHTTPRequest(hook, key) { }; } -exports.default = HooksController; \ No newline at end of file +exports.default = HooksController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9Ib29rc0NvbnRyb2xsZXIuanMiXSwibmFtZXMiOlsidHJpZ2dlcnMiLCJQYXJzZSIsInJlcXVlc3QiLCJEZWZhdWx0SG9va3NDb2xsZWN0aW9uTmFtZSIsIkhUVFBBZ2VudHMiLCJodHRwIiwiQWdlbnQiLCJrZWVwQWxpdmUiLCJodHRwcyIsIkhvb2tzQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwiYXBwbGljYXRpb25JZCIsImRhdGFiYXNlQ29udHJvbGxlciIsIndlYmhvb2tLZXkiLCJfYXBwbGljYXRpb25JZCIsIl93ZWJob29rS2V5IiwiZGF0YWJhc2UiLCJsb2FkIiwiX2dldEhvb2tzIiwidGhlbiIsImhvb2tzIiwiZm9yRWFjaCIsImhvb2siLCJhZGRIb29rVG9UcmlnZ2VycyIsImdldEZ1bmN0aW9uIiwiZnVuY3Rpb25OYW1lIiwicmVzdWx0cyIsImdldEZ1bmN0aW9ucyIsIiRleGlzdHMiLCJnZXRUcmlnZ2VyIiwiY2xhc3NOYW1lIiwidHJpZ2dlck5hbWUiLCJnZXRUcmlnZ2VycyIsImRlbGV0ZUZ1bmN0aW9uIiwicmVtb3ZlRnVuY3Rpb24iLCJfcmVtb3ZlSG9va3MiLCJkZWxldGVUcmlnZ2VyIiwicmVtb3ZlVHJpZ2dlciIsInF1ZXJ5IiwiZmluZCIsIm1hcCIsInJlc3VsdCIsIm9iamVjdElkIiwiZGVzdHJveSIsIlByb21pc2UiLCJyZXNvbHZlIiwic2F2ZUhvb2siLCJ1cmwiLCJFcnJvciIsInVwZGF0ZSIsInVwc2VydCIsIndyYXBwZWRGdW5jdGlvbiIsIndyYXBUb0hUVFBSZXF1ZXN0IiwiYWRkVHJpZ2dlciIsImFkZEZ1bmN0aW9uIiwiYWRkSG9vayIsImNyZWF0ZU9yVXBkYXRlSG9vayIsImFIb29rIiwiVHlwZXMiLCJjcmVhdGVIb29rIiwidXBkYXRlSG9vayIsImtleSIsInJlcSIsInJlcyIsImpzb25Cb2R5IiwiaSIsIm9iamVjdCIsInRvSlNPTiIsIm9yaWdpbmFsIiwianNvblJlcXVlc3QiLCJoZWFkZXJzIiwiYm9keSIsIkpTT04iLCJzdHJpbmdpZnkiLCJhZ2VudCIsInN0YXJ0c1dpdGgiLCJsb2dnZXIiLCJ3YXJuIiwicG9zdCIsImVyciIsImh0dHBSZXNwb25zZSIsInBhcnNlIiwiZSIsImVycm9yIiwiY29kZSIsInBhcnRpYWxSZXNwb25zZSIsInN1YnN0cmluZyIsInN1Y2Nlc3MiLCJjcmVhdGVkQXQiLCJ1cGRhdGVkQXQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFFQTs7SUFBWUEsUTs7QUFFWjs7SUFBWUMsSzs7QUFFWjs7SUFBWUMsTzs7QUFDWjs7QUFDQTs7OztBQUNBOzs7Ozs7OztBQUpBO0FBTEE7O0FBV0EsTUFBTUMsNkJBQTZCLFFBQW5DO0FBUkE7O0FBU0EsTUFBTUMsYUFBYTtBQUNqQkMsUUFBTSxJQUFJQSxlQUFLQyxLQUFULENBQWUsRUFBRUMsV0FBVyxJQUFiLEVBQWYsQ0FEVztBQUVqQkMsU0FBTyxJQUFJQSxnQkFBTUYsS0FBVixDQUFnQixFQUFFQyxXQUFXLElBQWIsRUFBaEI7QUFGVSxDQUFuQjs7QUFLTyxNQUFNRSxlQUFOLENBQXNCOztBQUszQkMsY0FBWUMsYUFBWixFQUFrQ0Msa0JBQWxDLEVBQXNEQyxVQUF0RCxFQUFrRTtBQUNoRSxTQUFLQyxjQUFMLEdBQXNCSCxhQUF0QjtBQUNBLFNBQUtJLFdBQUwsR0FBbUJGLFVBQW5CO0FBQ0EsU0FBS0csUUFBTCxHQUFnQkosa0JBQWhCO0FBQ0Q7O0FBRURLLFNBQU87QUFDTCxXQUFPLEtBQUtDLFNBQUwsR0FBaUJDLElBQWpCLENBQXNCQyxTQUFTO0FBQ3BDQSxjQUFRQSxTQUFTLEVBQWpCO0FBQ0FBLFlBQU1DLE9BQU4sQ0FBZUMsSUFBRCxJQUFVO0FBQ3RCLGFBQUtDLGlCQUFMLENBQXVCRCxJQUF2QjtBQUNELE9BRkQ7QUFHRCxLQUxNLENBQVA7QUFNRDs7QUFFREUsY0FBWUMsWUFBWixFQUEwQjtBQUN4QixXQUFPLEtBQUtQLFNBQUwsQ0FBZSxFQUFFTyxjQUFjQSxZQUFoQixFQUFmLEVBQStDTixJ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QixLQUFLZ0IsT0FBZDtBQUNBUixnQkFBTVIsS0FBS1ksS0FBWDtBQUNEO0FBQ0Y7O0FBRUQsVUFBSUosR0FBSixFQUFTO0FBQ1AsZUFBT2hCLElBQUlvQixLQUFKLENBQVVKLEdBQVYsQ0FBUDtBQUNELE9BRkQsTUFFTyxJQUFJekQsS0FBS1MsV0FBTCxLQUFxQixZQUF6QixFQUF1QztBQUM1QyxZQUFJLE9BQU9VLE1BQVAsS0FBa0IsUUFBdEIsRUFBZ0M7QUFDOUIsaUJBQU9BLE9BQU8rQyxTQUFkO0FBQ0EsaUJBQU8vQyxPQUFPZ0QsU0FBZDtBQUNEO0FBQ0QsZUFBTzFCLElBQUl3QixPQUFKLENBQVksRUFBQ3JCLFFBQVF6QixNQUFULEVBQVosQ0FBUDtBQUNELE9BTk0sTUFNQTtBQUNMLGVBQU9zQixJQUFJd0IsT0FBSixDQUFZOUMsTUFBWixDQUFQO0FBQ0Q7QUFDRixLQS9CRDtBQWdDRCxHQTdERDtBQThERDs7a0JBRWNoQyxlIiwiZmlsZSI6Ikhvb2tzQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBAZmxvdyB3ZWFrICovXG5cbmltcG9ydCAqIGFzIHRyaWdnZXJzICAgICAgICBmcm9tIFwiLi4vdHJpZ2dlcnNcIjtcbi8vIEBmbG93LWRpc2FibGUtbmV4dFxuaW1wb3J0ICogYXMgUGFyc2UgICAgICAgICAgIGZyb20gXCJwYXJzZS9ub2RlXCI7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCAqIGFzIHJlcXVlc3QgICAgICAgICBmcm9tIFwicmVxdWVzdFwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gICAgICAgICAgIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgaHR0cCAgICAgICAgICAgICAgICAgZnJvbSAnaHR0cCc7XG5pbXBvcnQgaHR0cHMgICAgICAgICAgICAgICAgZnJvbSAnaHR0cHMnO1xuXG5jb25zdCBEZWZhdWx0SG9va3NDb2xsZWN0aW9uTmFtZSA9IFwiX0hvb2tzXCI7XG5jb25zdCBIVFRQQWdlbnRzID0ge1xuICBodHRwOiBuZXcgaHR0cC5BZ2VudCh7IGtlZXBBbGl2ZTogdHJ1ZSB9KSxcbiAgaHR0cHM6IG5ldyBodHRwcy5BZ2VudCh7IGtlZXBBbGl2ZTogdHJ1ZSB9KSxcbn1cblxuZXhwb3J0IGNsYXNzIEhvb2tzQ29udHJvbGxlciB7XG4gIF9hcHBsaWNhdGlvbklkOnN0cmluZztcbiAgX3dlYmhvb2tLZXk6c3RyaW5nO1xuICBkYXRhYmFzZTogYW55O1xuXG4gIGNvbnN0cnVjdG9yKGFwcGxpY2F0aW9uSWQ6c3RyaW5nLCBkYXRhYmFzZUNvbnRyb2xsZXIsIHdlYmhvb2tLZXkpIHtcbiAgICB0aGlzLl9hcHBsaWNhdGlvbklkID0gYXBwbGljYXRpb25JZDtcbiAgICB0aGlzLl93ZWJob29rS2V5ID0gd2ViaG9va0tleTtcbiAgICB0aGlzLmRhdGFiYXNlID0gZGF0YWJhc2VDb250cm9sbGVyO1xuICB9XG5cbiAgbG9hZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0SG9va3MoKS50aGVuKGhvb2tzID0+IHtcbiAgICAgIGhvb2tzID0gaG9va3MgfHwgW107XG4gICAgICBob29rcy5mb3JFYWNoKChob29rKSA9PiB7XG4gICAgICAgIHRoaXMuYWRkSG9va1RvVHJpZ2dlcnMoaG9vayk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldEZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSkge1xuICAgIHJldHVybiB0aGlzLl9nZXRIb29rcyh7IGZ1bmN0aW9uTmFtZTogZnVuY3Rpb25OYW1lIH0pLnRoZW4ocmVzdWx0cyA9PiByZXN1bHRzWzBdKTtcbiAgfVxuXG4gIGdldEZ1bmN0aW9ucygpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0SG9va3MoeyBmdW5jdGlvbk5hbWU6IHsgJGV4aXN0czogdHJ1ZSB9IH0pO1xuICB9XG5cbiAgZ2V0VHJpZ2dlcihjbGFzc05hbWUsIHRyaWdnZXJOYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldEhvb2tzKHsgY2xhc3NOYW1lOiBjbGFzc05hbWUsIHRyaWdnZXJOYW1lOiB0cmlnZ2VyTmFtZSB9KS50aGVuKHJlc3VsdHMgPT4gcmVzdWx0c1swXSk7XG4gIH1cblxuICBnZXRUcmlnZ2VycygpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0SG9va3MoeyBjbGFzc05hbWU6IHsgJGV4aXN0czogdHJ1ZSB9LCB0cmlnZ2VyTmFtZTogeyAkZXhpc3RzOiB0cnVlIH0gfSk7XG4gIH1cblxuICBkZWxldGVGdW5jdGlvbihmdW5jdGlvbk5hbWUpIHtcbiAgICB0cmlnZ2Vycy5yZW1vdmVGdW5jdGlvbihmdW5jdGlvbk5hbWUsIHRoaXMuX2FwcGxpY2F0aW9uSWQpO1xuICAgIHJldHVybiB0aGlzLl9yZW1vdmVIb29rcyh7IGZ1bmN0aW9uTmFtZTogZnVuY3Rpb25OYW1lIH0pO1xuICB9XG5cbiAgZGVsZXRlVHJpZ2dlcihjbGFzc05hbWUsIHRyaWdnZXJOYW1lKSB7XG4gICAgdHJpZ2dlcnMucmVtb3ZlVHJpZ2dlcih0cmlnZ2VyTmFtZSwgY2xhc3NOYW1lLCB0aGlzLl9hcHBsaWNhdGlvbklkKTtcbiAgICByZXR1cm4gdGhpcy5fcmVtb3ZlSG9va3MoeyBjbGFzc05hbWU6IGNsYXNzTmFtZSwgdHJpZ2dlck5hbWU6IHRyaWdnZXJOYW1lIH0pO1xuICB9XG5cbiAgX2dldEhvb2tzKHF1ZXJ5ID0ge30pIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhYmFzZS5maW5kKERlZmF1bHRIb29rc0NvbGxlY3Rpb25OYW1lLCBxdWVyeSkudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgcmV0dXJuIHJlc3VsdHMubWFwKChyZXN1bHQpID0+IHtcbiAgICAgICAgZGVsZXRlIHJlc3VsdC5vYmplY3RJZDtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgX3JlbW92ZUhvb2tzKHF1ZXJ5KSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YWJhc2UuZGVzdHJveShEZWZhdWx0SG9va3NDb2xsZWN0aW9uTmFtZSwgcXVlcnkpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gICAgfSk7XG4gIH1cblxuICBzYXZlSG9vayhob29rKSB7XG4gICAgdmFyIHF1ZXJ5O1xuICAgIGlmIChob29rLmZ1bmN0aW9uTmFtZSAmJiBob29rLnVybCkge1xuICAgICAgcXVlcnkgPSB7IGZ1bmN0aW9uTmFtZTogaG9vay5mdW5jdGlvbk5hbWUgfVxuICAgIH0gZWxzZSBpZiAoaG9vay50cmlnZ2VyTmFtZSAmJiBob29rLmNsYXNzTmFtZSAmJiBob29rLnVybCkge1xuICAgICAgcXVlcnkgPSB7IGNsYXNzTmFtZTogaG9vay5jbGFzc05hbWUsIHRyaWdnZXJOYW1lOiBob29rLnRyaWdnZXJOYW1lIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDE0MywgXCJpbnZhbGlkIGhvb2sgZGVjbGFyYXRpb25cIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmRhdGFiYXNlLnVwZGF0ZShEZWZhdWx0SG9va3NDb2xsZWN0aW9uTmFtZSwgcXVlcnksIGhvb2ssIHt1cHNlcnQ6IHRydWV9KS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoaG9vayk7XG4gICAgfSlcbiAgfVxuXG4gIGFkZEhvb2tUb1RyaWdnZXJzKGhvb2spIHtcbiAgICB2YXIgd3JhcHBlZEZ1bmN0aW9uID0gd3JhcFRvSFRUUFJlcXVlc3QoaG9vaywgdGhpcy5fd2ViaG9va0tleSk7XG4gICAgd3JhcHBlZEZ1bmN0aW9uLnVybCA9IGhvb2sudXJsO1xuICAgIGlmIChob29rLmNsYXNzTmFtZSkge1xuICAgICAgdHJpZ2dlcnMuYWRkVHJpZ2dlcihob29rLnRyaWdnZXJOYW1lLCBob29rLmNsYXNzTmFtZSwgd3JhcHBlZEZ1bmN0aW9uLCB0aGlzLl9hcHBsaWNhdGlvbklkKVxuICAgIH0gZWxzZSB7XG4gICAgICB0cmlnZ2Vycy5hZGRGdW5jdGlvbihob29rLmZ1bmN0aW9uTmFtZSwgd3JhcHBlZEZ1bmN0aW9uLCBudWxsLCB0aGlzLl9hcHBsaWNhdGlvbklkKTtcbiAgICB9XG4gIH1cblxuICBhZGRIb29rKGhvb2spIHtcbiAgICB0aGlzLmFkZEhvb2tUb1RyaWdnZXJzKGhvb2spO1xuICAgIHJldHVybiB0aGlzLnNhdmVIb29rKGhvb2spO1xuICB9XG5cbiAgY3JlYXRlT3JVcGRhdGVIb29rKGFIb29rKSB7XG4gICAgdmFyIGhvb2s7XG4gICAgaWYgKGFIb29rICYmIGFIb29rLmZ1bmN0aW9uTmFtZSAmJiBhSG9vay51cmwpIHtcbiAgICAgIGhvb2sgPSB7fTtcbiAgICAgIGhvb2suZnVuY3Rpb25OYW1lID0gYUhvb2suZnVuY3Rpb25OYW1lO1xuICAgICAgaG9vay51cmwgPSBhSG9vay51cmw7XG4gICAgfSBlbHNlIGlmIChhSG9vayAmJiBhSG9vay5jbGFzc05hbWUgJiYgYUhvb2sudXJsICYmIGFIb29rLnRyaWdnZXJOYW1lICYmIHRyaWdnZXJzLlR5cGVzW2FIb29rLnRyaWdnZXJOYW1lXSkge1xuICAgICAgaG9vayA9IHt9O1xuICAgICAgaG9vay5jbGFzc05hbWUgPSBhSG9vay5jbGFzc05hbWU7XG4gICAgICBob29rLnVybCA9IGFIb29rLnVybDtcbiAgICAgIGhvb2sudHJpZ2dlck5hbWUgPSBhSG9vay50cmlnZ2VyTmFtZTtcblxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTQzLCBcImludmFsaWQgaG9vayBkZWNsYXJhdGlvblwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5hZGRIb29rKGhvb2spO1xuICB9XG5cbiAgY3JlYXRlSG9vayhhSG9vaykge1xuICAgIGlmIChhSG9vay5mdW5jdGlvbk5hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEZ1bmN0aW9uKGFIb29rLmZ1bmN0aW9uTmFtZSkudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTQzLCBgZnVuY3Rpb24gbmFtZTogJHthSG9vay5mdW5jdGlvbk5hbWV9IGFscmVhZHkgZXhpdHNgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVPclVwZGF0ZUhvb2soYUhvb2spO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGFIb29rLmNsYXNzTmFtZSAmJiBhSG9vay50cmlnZ2VyTmFtZSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VHJpZ2dlcihhSG9vay5jbGFzc05hbWUsIGFIb29rLnRyaWdnZXJOYW1lKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxNDMsIGBjbGFzcyAke2FIb29rLmNsYXNzTmFtZX0gYWxyZWFkeSBoYXMgdHJpZ2dlciAke2FIb29rLnRyaWdnZXJOYW1lfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU9yVXBkYXRlSG9vayhhSG9vayk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTQzLCBcImludmFsaWQgaG9vayBkZWNsYXJhdGlvblwiKTtcbiAgfVxuXG4gIHVwZGF0ZUhvb2soYUhvb2spIHtcbiAgICBpZiAoYUhvb2suZnVuY3Rpb25OYW1lKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRGdW5jdGlvbihhSG9vay5mdW5jdGlvbk5hbWUpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlT3JVcGRhdGVIb29rKGFIb29rKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTQzLCBgbm8gZnVuY3Rpb24gbmFtZWQ6ICR7YUhvb2suZnVuY3Rpb25OYW1lfSBpcyBkZWZpbmVkYCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGFIb29rLmNsYXNzTmFtZSAmJiBhSG9vay50cmlnZ2VyTmFtZSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VHJpZ2dlcihhSG9vay5jbGFzc05hbWUsIGFIb29rLnRyaWdnZXJOYW1lKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU9yVXBkYXRlSG9vayhhSG9vayk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDE0MywgYGNsYXNzICR7YUhvb2suY2xhc3NOYW1lfSBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxNDMsIFwiaW52YWxpZCBob29rIGRlY2xhcmF0aW9uXCIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHdyYXBUb0hUVFBSZXF1ZXN0KGhvb2ssIGtleSkge1xuICByZXR1cm4gKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QganNvbkJvZHkgPSB7fTtcbiAgICBmb3IgKHZhciBpIGluIHJlcSkge1xuICAgICAganNvbkJvZHlbaV0gPSByZXFbaV07XG4gICAgfVxuICAgIGlmIChyZXEub2JqZWN0KSB7XG4gICAgICBqc29uQm9keS5vYmplY3QgPSByZXEub2JqZWN0LnRvSlNPTigpO1xuICAgICAganNvbkJvZHkub2JqZWN0LmNsYXNzTmFtZSA9IHJlcS5vYmplY3QuY2xhc3NOYW1lO1xuICAgIH1cbiAgICBpZiAocmVxLm9yaWdpbmFsKSB7XG4gICAgICBqc29uQm9keS5vcmlnaW5hbCA9IHJlcS5vcmlnaW5hbC50b0pTT04oKTtcbiAgICAgIGpzb25Cb2R5Lm9yaWdpbmFsLmNsYXNzTmFtZSA9IHJlcS5vcmlnaW5hbC5jbGFzc05hbWU7XG4gICAgfVxuICAgIGNvbnN0IGpzb25SZXF1ZXN0OiBhbnkgPSB7XG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICAgIH0sXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShqc29uQm9keSksXG4gICAgfTtcblxuICAgIGNvbnN0IGFnZW50ID0gaG9vay51cmwuc3RhcnRzV2l0aCgnaHR0cHMnKSA/IEhUVFBBZ2VudHNbJ2h0dHBzJ10gOiBIVFRQQWdlbnRzWydodHRwJ107XG4gICAganNvblJlcXVlc3QuYWdlbnQgPSBhZ2VudDtcblxuICAgIGlmIChrZXkpIHtcbiAgICAgIGpzb25SZXF1ZXN0LmhlYWRlcnNbJ1gtUGFyc2UtV2ViaG9vay1LZXknXSA9IGtleTtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nZ2VyLndhcm4oJ01ha2luZyBvdXRnb2luZyB3ZWJob29rIHJlcXVlc3Qgd2l0aG91dCB3ZWJob29rS2V5IGJlaW5nIHNldCEnKTtcbiAgICB9XG5cbiAgICByZXF1ZXN0LnBvc3QoaG9vay51cmwsIGpzb25SZXF1ZXN0LCBmdW5jdGlvbiAoZXJyLCBodHRwUmVzcG9uc2UsIGJvZHkpIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICBpZiAoYm9keSkge1xuICAgICAgICBpZiAodHlwZW9mIGJvZHkgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYm9keSA9IEpTT04ucGFyc2UoYm9keSk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgZXJyID0ge1xuICAgICAgICAgICAgICBlcnJvcjogXCJNYWxmb3JtZWQgcmVzcG9uc2VcIixcbiAgICAgICAgICAgICAgY29kZTogLTEsXG4gICAgICAgICAgICAgIHBhcnRpYWxSZXNwb25zZTogYm9keS5zdWJzdHJpbmcoMCwgMTAwKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFlcnIpIHtcbiAgICAgICAgICByZXN1bHQgPSBib2R5LnN1Y2Nlc3M7XG4gICAgICAgICAgZXJyID0gYm9keS5lcnJvcjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJldHVybiByZXMuZXJyb3IoZXJyKTtcbiAgICAgIH0gZWxzZSBpZiAoaG9vay50cmlnZ2VyTmFtZSA9PT0gJ2JlZm9yZVNhdmUnKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGRlbGV0ZSByZXN1bHQuY3JlYXRlZEF0O1xuICAgICAgICAgIGRlbGV0ZSByZXN1bHQudXBkYXRlZEF0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXMuc3VjY2Vzcyh7b2JqZWN0OiByZXN1bHR9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiByZXMuc3VjY2VzcyhyZXN1bHQpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEhvb2tzQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/LiveQueryController.js b/lib/Controllers/LiveQueryController.js index 7ccd287d5e..e61a8cf1e4 100644 --- a/lib/Controllers/LiveQueryController.js +++ b/lib/Controllers/LiveQueryController.js @@ -55,4 +55,5 @@ class LiveQueryController { } exports.LiveQueryController = LiveQueryController; -exports.default = LiveQueryController; \ No newline at end of file +exports.default = LiveQueryController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9MaXZlUXVlcnlDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkxpdmVRdWVyeUNvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsImNsYXNzTmFtZXMiLCJTZXQiLCJBcnJheSIsImxpdmVRdWVyeVB1Ymxpc2hlciIsIlBhcnNlQ2xvdWRDb2RlUHVibGlzaGVyIiwib25BZnRlclNhdmUiLCJjbGFzc05hbWUiLCJjdXJyZW50T2JqZWN0Iiwib3JpZ2luYWxPYmplY3QiLCJoYXNMaXZlUXVlcnkiLCJyZXEiLCJfbWFrZVB1Ymxpc2hlclJlcXVlc3QiLCJvbkNsb3VkQ29kZUFmdGVyU2F2ZSIsIm9uQWZ0ZXJEZWxldGUiLCJvbkNsb3VkQ29kZUFmdGVyRGVsZXRlIiwiaGFzIiwib2JqZWN0Iiwib3JpZ2luYWwiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDTyxNQUFNQSxtQkFBTixDQUEwQjs7QUFJL0JDLGNBQVlDLE1BQVosRUFBdUM7QUFDckM7QUFDQSxRQUFJLENBQUNBLE1BQUQsSUFBVyxDQUFDQSxPQUFPQyxVQUF2QixFQUFtQztBQUNqQyxXQUFLQSxVQUFMLEdBQWtCLElBQUlDLEdBQUosRUFBbEI7QUFDRCxLQUZELE1BRU8sSUFBSUYsT0FBT0MsVUFBUCxZQUE2QkUsS0FBakMsRUFBd0M7QUFDN0MsV0FBS0YsVUFBTCxHQUFrQixJQUFJQyxHQUFKLENBQVFGLE9BQU9DLFVBQWYsQ0FBbEI7QUFDRCxLQUZNLE1BRUE7QUFDTCxZQUFNLGdEQUFOO0FBQ0Q7QUFDRCxTQUFLRyxrQkFBTCxHQUEwQixJQUFJQyxnREFBSixDQUE0QkwsTUFBNUIsQ0FBMUI7QUFDRDs7QUFFRE0sY0FBWUMsU0FBWixFQUErQkMsYUFBL0IsRUFBbURDLGNBQW5ELEVBQXdFO0FBQ3RFLFFBQUksQ0FBQyxLQUFLQyxZQUFMLENBQWtCSCxTQUFsQixDQUFMLEVBQW1DO0FBQ2pDO0FBQ0Q7QUFDRCxVQUFNSSxNQUFNLEtBQUtDLHFCQUFMLENBQTJCSixhQUEzQixFQUEwQ0MsY0FBMUMsQ0FBWjtBQUNBLFNBQUtMLGtCQUFMLENBQXdCUyxvQkFBeEIsQ0FBNkNGLEdBQTdDO0FBQ0Q7O0FBRURHLGdCQUFjUCxTQUFkLEVBQWlDQyxhQUFqQyxFQUFxREMsY0FBckQsRUFBMEU7QUFDeEUsUUFBSSxDQUFDLEtBQUtDLFlBQUwsQ0FBa0JILFNBQWxCLENBQUwsRUFBbUM7QUFDakM7QUFDRDtBQUNELFVBQU1JLE1BQU0sS0FBS0MscUJBQUwsQ0FBMkJKLGFBQTNCLEVBQTBDQyxjQUExQyxDQUFaO0FBQ0EsU0FBS0wsa0JBQUwsQ0FBd0JXLHNCQUF4QixDQUErQ0osR0FBL0M7QUFDRDs7QUFFREQsZUFBYUgsU0FBYixFQUF5QztBQUN2QyxXQUFPLEtBQUtOLFVBQUwsQ0FBZ0JlLEdBQWhCLENBQW9CVCxTQUFwQixDQUFQO0FBQ0Q7O0FBRURLLHdCQUFzQkosYUFBdEIsRUFBMENDLGNBQTFDLEVBQW9FO0FBQ2xFLFVBQU1FLE1BQU07QUFDVk0sY0FBUVQ7QUFERSxLQUFaO0FBR0EsUUFBSUEsYUFBSixFQUFtQjtBQUNqQkcsVUFBSU8sUUFBSixHQUFlVCxjQUFmO0FBQ0Q7QUFDRCxXQUFPRSxHQUFQO0FBQ0Q7QUE1QzhCOztRQUFwQmIsbUIsR0FBQUEsbUI7a0JBK0NFQSxtQiIsImZpbGUiOiJMaXZlUXVlcnlDb250cm9sbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIgfSBmcm9tICcuLi9MaXZlUXVlcnkvUGFyc2VDbG91ZENvZGVQdWJsaXNoZXInO1xuaW1wb3J0IHsgTGl2ZVF1ZXJ5T3B0aW9ucyB9IGZyb20gJy4uL09wdGlvbnMnO1xuZXhwb3J0IGNsYXNzIExpdmVRdWVyeUNvbnRyb2xsZXIge1xuICBjbGFzc05hbWVzOiBhbnk7XG4gIGxpdmVRdWVyeVB1Ymxpc2hlcjogYW55O1xuXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogP0xpdmVRdWVyeU9wdGlvbnMpIHtcbiAgICAvLyBJZiBjb25maWcgaXMgZW1wdHksIHdlIGp1c3QgYXNzdW1lIG5vIGNsYXNzcyBuZWVkcyB0byBiZSByZWdpc3RlcmVkIGFzIExpdmVRdWVyeVxuICAgIGlmICghY29uZmlnIHx8ICFjb25maWcuY2xhc3NOYW1lcykge1xuICAgICAgdGhpcy5jbGFzc05hbWVzID0gbmV3IFNldCgpO1xuICAgIH0gZWxzZSBpZiAoY29uZmlnLmNsYXNzTmFtZXMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgdGhpcy5jbGFzc05hbWVzID0gbmV3IFNldChjb25maWcuY2xhc3NOYW1lcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93ICdsaXZlUXVlcnkuY2xhc3NlcyBzaG91bGQgYmUgYW4gYXJyYXkgb2Ygc3RyaW5nJ1xuICAgIH1cbiAgICB0aGlzLmxpdmVRdWVyeVB1Ymxpc2hlciA9IG5ldyBQYXJzZUNsb3VkQ29kZVB1Ymxpc2hlcihjb25maWcpO1xuICB9XG5cbiAgb25BZnRlclNhdmUoY2xhc3NOYW1lOiBzdHJpbmcsIGN1cnJlbnRPYmplY3Q6IGFueSwgb3JpZ2luYWxPYmplY3Q6IGFueSkge1xuICAgIGlmICghdGhpcy5oYXNMaXZlUXVlcnkoY2xhc3NOYW1lKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByZXEgPSB0aGlzLl9tYWtlUHVibGlzaGVyUmVxdWVzdChjdXJyZW50T2JqZWN0LCBvcmlnaW5hbE9iamVjdCk7XG4gICAgdGhpcy5saXZlUXVlcnlQdWJsaXNoZXIub25DbG91ZENvZGVBZnRlclNhdmUocmVxKTtcbiAgfVxuXG4gIG9uQWZ0ZXJEZWxldGUoY2xhc3NOYW1lOiBzdHJpbmcsIGN1cnJlbnRPYmplY3Q6IGFueSwgb3JpZ2luYWxPYmplY3Q6IGFueSkge1xuICAgIGlmICghdGhpcy5oYXNMaXZlUXVlcnkoY2xhc3NOYW1lKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByZXEgPSB0aGlzLl9tYWtlUHVibGlzaGVyUmVxdWVzdChjdXJyZW50T2JqZWN0LCBvcmlnaW5hbE9iamVjdCk7XG4gICAgdGhpcy5saXZlUXVlcnlQdWJsaXNoZXIub25DbG91ZENvZGVBZnRlckRlbGV0ZShyZXEpO1xuICB9XG5cbiAgaGFzTGl2ZVF1ZXJ5KGNsYXNzTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY2xhc3NOYW1lcy5oYXMoY2xhc3NOYW1lKTtcbiAgfVxuXG4gIF9tYWtlUHVibGlzaGVyUmVxdWVzdChjdXJyZW50T2JqZWN0OiBhbnksIG9yaWdpbmFsT2JqZWN0OiBhbnkpOiBhbnkge1xuICAgIGNvbnN0IHJlcSA9IHtcbiAgICAgIG9iamVjdDogY3VycmVudE9iamVjdFxuICAgIH07XG4gICAgaWYgKGN1cnJlbnRPYmplY3QpIHtcbiAgICAgIHJlcS5vcmlnaW5hbCA9IG9yaWdpbmFsT2JqZWN0O1xuICAgIH1cbiAgICByZXR1cm4gcmVxO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IExpdmVRdWVyeUNvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/LoggerController.js b/lib/Controllers/LoggerController.js index 8c78f99fad..4ce29ddc96 100644 --- a/lib/Controllers/LoggerController.js +++ b/lib/Controllers/LoggerController.js @@ -253,4 +253,5 @@ class LoggerController extends _AdaptableController2.default { } exports.LoggerController = LoggerController; -exports.default = LoggerController; \ No newline at end of file +exports.default = LoggerController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9Mb2dnZXJDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIk1JTExJU0VDT05EU19JTl9BX0RBWSIsIkxPR19TVFJJTkdfVFJVTkNBVEVfTEVOR1RIIiwidHJ1bmNhdGlvbk1hcmtlciIsIkxvZ0xldmVsIiwiSU5GTyIsIkVSUk9SIiwiTG9nT3JkZXIiLCJERVNDRU5ESU5HIiwiQVNDRU5ESU5HIiwibG9nTGV2ZWxzIiwiTG9nZ2VyQ29udHJvbGxlciIsIkFkYXB0YWJsZUNvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImFkYXB0ZXIiLCJhcHBJZCIsIm9wdGlvbnMiLCJsb2dMZXZlbCIsImxldmVsIiwidmVyYm9zZSIsImluZGV4IiwiaW5kZXhPZiIsImZvckVhY2giLCJsZXZlbEluZGV4IiwibWFza1NlbnNpdGl2ZVVybCIsInVybFN0cmluZyIsInVybE9iaiIsInVybCIsInBhcnNlIiwicXVlcnkiLCJzYW5pdGl6ZWRRdWVyeSIsImtleSIsInNsaWNlIiwicGF0aG5hbWUiLCJtYXNrU2Vuc2l0aXZlIiwiYXJnQXJyYXkiLCJtYXAiLCJlIiwicmVwbGFjZSIsIkFycmF5IiwiaXNBcnJheSIsIml0ZW0iLCJib2R5IiwiT2JqZWN0Iiwia2V5cyIsInBhcmFtcyIsImxvZyIsImFyZ3MiLCJjb25jYXQiLCJhcmciLCJhcHBseSIsImluZm8iLCJhcmd1bWVudHMiLCJlcnJvciIsIndhcm4iLCJkZWJ1ZyIsInNpbGx5IiwibG9nUmVxdWVzdCIsIm1ldGhvZCIsImhlYWRlcnMiLCJzdHJpbmdpZmllZEJvZHkiLCJKU09OIiwic3RyaW5naWZ5IiwibG9nUmVzcG9uc2UiLCJyZXN1bHQiLCJzdHJpbmdpZmllZFJlc3BvbnNlIiwidmFsaWREYXRlVGltZSIsImRhdGUiLCJEYXRlIiwiaXNOYU4iLCJnZXRUaW1lIiwidHJ1bmNhdGVMb2dNZXNzYWdlIiwic3RyaW5nIiwibGVuZ3RoIiwidHJ1bmNhdGVkIiwic3Vic3RyaW5nIiwicGFyc2VPcHRpb25zIiwiZnJvbSIsIm5vdyIsInVudGlsIiwic2l6ZSIsIk51bWJlciIsIm9yZGVyIiwiZ2V0TG9ncyIsIlBhcnNlIiwiRXJyb3IiLCJQVVNIX01JU0NPTkZJR1VSRUQiLCJleHBlY3RlZEFkYXB0ZXJUeXBlIiwiTG9nZ2VyQWRhcHRlciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBQ0E7O0FBQ0E7Ozs7OztBQUVBLE1BQU1BLHdCQUF3QixLQUFLLEVBQUwsR0FBVSxFQUFWLEdBQWUsSUFBN0M7QUFDQSxNQUFNQyw2QkFBNkIsSUFBbkM7QUFDQSxNQUFNQyxtQkFBbUIsaUJBQXpCOztBQUVPLE1BQU1DLDhCQUFXO0FBQ3RCQyxRQUFNLE1BRGdCO0FBRXRCQyxTQUFPO0FBRmUsQ0FBakI7O0FBS0EsTUFBTUMsOEJBQVc7QUFDdEJDLGNBQVksTUFEVTtBQUV0QkMsYUFBVztBQUZXLENBQWpCOztBQUtQLE1BQU1DLFlBQVksQ0FDaEIsT0FEZ0IsRUFFaEIsTUFGZ0IsRUFHaEIsTUFIZ0IsRUFJaEIsT0FKZ0IsRUFLaEIsU0FMZ0IsRUFNaEIsT0FOZ0IsQ0FBbEI7O0FBU08sTUFBTUMsZ0JBQU4sU0FBK0JDLDZCQUEvQixDQUFtRDs7QUFFeERDLGNBQVlDLE9BQVosRUFBcUJDLEtBQXJCLEVBQTRCQyxVQUFVLEVBQUNDLFVBQVUsTUFBWCxFQUF0QyxFQUEwRDtBQUN4RCxVQUFNSCxPQUFOLEVBQWVDLEtBQWYsRUFBc0JDLE9BQXRCO0FBQ0EsUUFBSUUsUUFBUSxNQUFaO0FBQ0EsUUFBSUYsUUFBUUcsT0FBWixFQUFxQjtBQUNuQkQsY0FBUSxTQUFSO0FBQ0Q7QUFDRCxRQUFJRixRQUFRQyxRQUFaLEVBQXNCO0FBQ3BCQyxjQUFRRixRQUFRQyxRQUFoQjtBQUNEO0FBQ0QsVUFBTUcsUUFBUVYsVUFBVVcsT0FBVixDQUFrQkgsS0FBbEIsQ0FBZCxDQVR3RCxDQVNoQjtBQUN4Q1IsY0FBVVksT0FBVixDQUFrQixDQUFDSixLQUFELEVBQVFLLFVBQVIsS0FBdUI7QUFDdkMsVUFB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QUFRRixRQUFRRSxLQUFSLElBQWlCZCxTQUFTQyxJQUF4Qzs7QUFFQSxXQUFPO0FBQ0x3RSxVQURLO0FBRUxFLFdBRks7QUFHTEMsVUFISztBQUlMRSxXQUpLO0FBS0xoRTtBQUxLLEtBQVA7QUFPRDs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBaUUsVUFBUW5FLFVBQVUsRUFBbEIsRUFBc0I7QUFDcEIsUUFBSSxDQUFDLEtBQUtGLE9BQVYsRUFBbUI7QUFDakIsWUFBTSxJQUFJc0UsWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZQyxrQkFBNUIsRUFDSixpQ0FESSxDQUFOO0FBRUQ7QUFDRCxRQUFJLE9BQU8sS0FBS3hFLE9BQUwsQ0FBYWUsS0FBcEIsS0FBOEIsVUFBbEMsRUFBOEM7QUFDNUMsWUFBTSxJQUFJdUQsWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZQyxrQkFBNUIsRUFDSixrREFESSxDQUFOO0FBRUQ7QUFDRHRFLGNBQVVMLGlCQUFpQmlFLFlBQWpCLENBQThCNUQsT0FBOUIsQ0FBVjtBQUNBLFdBQU8sS0FBS0YsT0FBTCxDQUFhZSxLQUFiLENBQW1CYixPQUFuQixDQUFQO0FBQ0Q7O0FBRUR1RSx3QkFBc0I7QUFDcEIsV0FBT0MsNEJBQVA7QUFDRDtBQXZOdUQ7O1FBQTdDN0UsZ0IsR0FBQUEsZ0I7a0JBME5FQSxnQiIsImZpbGUiOiJMb2dnZXJDb250cm9sbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2UgfSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBBZGFwdGFibGVDb250cm9sbGVyIGZyb20gJy4vQWRhcHRhYmxlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBMb2dnZXJBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvTG9nZ2VyL0xvZ2dlckFkYXB0ZXInO1xuaW1wb3J0IHVybCBmcm9tICd1cmwnO1xuXG5jb25zdCBNSUxMSVNFQ09ORFNfSU5fQV9EQVkgPSAyNCAqIDYwICogNjAgKiAxMDAwO1xuY29uc3QgTE9HX1NUUklOR19UUlVOQ0FURV9MRU5HVEggPSAxMDAwO1xuY29uc3QgdHJ1bmNhdGlvbk1hcmtlciA9ICcuLi4gKHRydW5jYXRlZCknO1xuXG5leHBvcnQgY29uc3QgTG9nTGV2ZWwgPSB7XG4gIElORk86ICdpbmZvJyxcbiAgRVJST1I6ICdlcnJvcidcbn1cblxuZXhwb3J0IGNvbnN0IExvZ09yZGVyID0ge1xuICBERVNDRU5ESU5HOiAnZGVzYycsXG4gIEFTQ0VORElORzogJ2FzYydcbn1cblxuY29uc3QgbG9nTGV2ZWxzID0gW1xuICAnZXJyb3InLFxuICAnd2FybicsXG4gICdpbmZvJyxcbiAgJ2RlYnVnJyxcbiAgJ3ZlcmJvc2UnLFxuICAnc2lsbHknLFxuXVxuXG5leHBvcnQgY2xhc3MgTG9nZ2VyQ29udHJvbGxlciBleHRlbmRzIEFkYXB0YWJsZUNvbnRyb2xsZXIge1xuXG4gIGNvbnN0cnVjdG9yKGFkYXB0ZXIsIGFwcElkLCBvcHRpb25zID0ge2xvZ0xldmVsOiAnaW5mbyd9KSB7XG4gICAgc3VwZXIoYWRhcHRlciwgYXBwSWQsIG9wdGlvbnMpO1xuICAgIGxldCBsZXZlbCA9ICdpbmZvJztcbiAgICBpZiAob3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICBsZXZlbCA9ICd2ZXJib3NlJztcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMubG9nTGV2ZWwpIHtcbiAgICAgIGxldmVsID0gb3B0aW9ucy5sb2dMZXZlbDtcbiAgICB9XG4gICAgY29uc3QgaW5kZXggPSBsb2dMZXZlbHMuaW5kZXhPZihsZXZlbCk7IC8vIGluZm8gYnkgZGVmYXVsdFxuICAgIGxvZ0xldmVscy5mb3JFYWNoKChsZXZlbCwgbGV2ZWxJbmRleCkgPT4ge1xuICAgICAgaWYgKGxldmVsSW5kZXggPiBpbmRleCkgeyAvLyBzaWxlbmNlIHRoZSBsZXZlbHMgdGhhdCBhcmUgPiBtYXhJbmRleFxuICAgICAgICB0aGlzW2xldmVsXSA9ICgpID0+IHt9O1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgbWFza1NlbnNpdGl2ZVVybCh1cmxTdHJpbmcpIHtcbiAgICBjb25zdCB1cmxPYmogPSB1cmwucGFyc2UodXJsU3RyaW5nLCB0cnVlKTtcbiAgICBjb25zdCBxdWVyeSA9IHVybE9iai5xdWVyeTtcbiAgICBsZXQgc2FuaXRpemVkUXVlcnkgPSAnPyc7XG5cbiAgICBmb3IoY29uc3Qga2V5IGluIHF1ZXJ5KSB7XG4gICAgICBpZihrZXkgIT09ICdwYXNzd29yZCcpIHtcbiAgICAgICAgLy8gbm9ybWFsIHZhbHVlXG4gICAgICAgIHNhbml0aXplZFF1ZXJ5ICs9IGtleSArICc9JyArIHF1ZXJ5W2tleV0gKyAnJic7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBwYXNzd29yZCB2YWx1ZSwgcmVkYWN0IGl0XG4gICAgICAgIHNhbml0aXplZFF1ZXJ5ICs9IGtleSArICc9JyArICcqKioqKioqKicgKyAnJic7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdHJpbSBsYXN0IGNoYXJhY3RlciwgPyBvciAmXG4gICAgc2FuaXRpemVkUXVlcnkgPSBzYW5pdGl6ZWRRdWVyeS5zbGljZSgwLCAtMSk7XG5cbiAgICAvLyByZXR1cm4gb3JpZ2luYWwgcGF0aCBuYW1lIHdpdGggc2FuaXRpemVkIHBhcmFtcyBhdHRhY2hlZFxuICAgIHJldHVybiB1cmxPYmoucGF0aG5hbWUgKyBzYW5pdGl6ZWRRdWVyeTtcbiAgfVxuXG4gIG1hc2tTZW5zaXRpdmUoYXJnQXJyYXkpIHtcbiAgICByZXR1cm4gYXJnQXJyYXkubWFwKGUgPT4ge1xuICAgICAgaWYgKCFlKSB7XG4gICAgICAgIHJldHVybiBlO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBlLnJlcGxhY2UoLyhwYXNzd29yZFwiLj86Lj9cIilbXlwiXSpcIi9nLCAnJDEqKioqKioqKlwiJyk7XG4gICAgICB9XG4gICAgICAvLyBlbHNlIGl0IGlzIGFuIG9iamVjdC4uLlxuXG4gICAgICAvLyBjaGVjayB0aGUgdXJsXG4gICAgICBpZiAoZS51cmwpIHtcbiAgICAgICAgLy8gZm9yIHN0cmluZ3NcbiAgICAgICAgaWYgKHR5cGVvZiBlLnVybCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBlLnVybCA9IHRoaXMubWFza1NlbnNpdGl2ZVVybChlLnVybCk7XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShlLnVybCkpIHsgLy8gZm9yIHN0cmluZ3MgaW4gYXJyYXlcbiAgICAgICAgICBlLnVybCA9IGUudXJsLm1hcChpdGVtID0+IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaXRlbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWFza1NlbnNpdGl2ZVVybChpdGVtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGUuYm9keSkge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhlLmJvZHkpKSB7XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3Bhc3N3b3JkJykge1xuICAgICAgICAgICAgZS5ib2R5W2tleV0gPSAnKioqKioqKionO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChlLnBhcmFtcykge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhlLnBhcmFtcykpIHtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncGFzc3dvcmQnKSB7XG4gICAgICAgICAgICBlLnBhcmFtc1trZXldID0gJyoqKioqKioqJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZTtcbiAgICB9KTtcbiAgfVxuXG4gIGxvZyhsZXZlbCwgYXJncykge1xuICAgIC8vIG1ha2UgdGhlIHBhc3NlZCBpbiBhcmd1bWVudHMgb2JqZWN0IGFuIGFycmF5IHdpdGggdGhlIHNwcmVhZCBvcGVyYXRvclxuICAgIGFyZ3MgPSB0aGlzLm1hc2tTZW5zaXRpdmUoWy4uLmFyZ3NdKTtcbiAgICBhcmdzID0gW10uY29uY2F0KGxldmVsLCBhcmdzLm1hcCgoYXJnKSA9PiB7XG4gICAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJykgeyByZXR1cm4gYXJnKCk7IH1cbiAgICAgIHJldHVybiBhcmc7XG4gICAgfSkpO1xuICAgIHRoaXMuYWRhcHRlci5sb2cuYXBwbHkodGhpcy5hZGFwdGVyLCBhcmdzKTtcbiAgfVxuXG4gIGluZm8oKSB7XG4gICAgcmV0dXJuIHRoaXMubG9nKCdpbmZvJywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIGVycm9yKCkge1xuICAgIHJldHVybiB0aGlzLmxvZygnZXJyb3InLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgd2FybigpIHtcbiAgICByZXR1cm4gdGhpcy5sb2coJ3dhcm4nLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgdmVyYm9zZSgpIHtcbiAgICByZXR1cm4gdGhpcy5sb2coJ3ZlcmJvc2UnLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgZGVidWcoKSB7XG4gICAgcmV0dXJuIHRoaXMubG9nKCdkZWJ1ZycsIGFyZ3VtZW50cyk7XG4gIH1cblxuICBzaWxseSgpIHtcbiAgICByZXR1cm4gdGhpcy5sb2coJ3NpbGx5JywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIGxvZ1JlcXVlc3Qoe1xuICAgIG1ldGhvZCxcbiAgICB1cmwsXG4gICAgaGVhZGVycyxcbiAgICBib2R5XG4gIH0pIHtcbiAgICB0aGlzLnZlcmJvc2UoKCkgPT4ge1xuICAgICAgY29uc3Qgc3RyaW5naWZpZWRCb2R5ID0gSlNPTi5zdHJpbmdpZnkoYm9keSwgbnVsbCwgMik7XG4gICAgICByZXR1cm4gYFJFUVVFU1QgZm9yIFske21ldGhvZH1dICR7dXJsfTogJHtzdHJpbmdpZmllZEJvZHl9YDtcbiAgICB9LCB7XG4gICAgICBtZXRob2QsXG4gICAgICB1cmwsXG4gICAgICBoZWFkZXJzLFxuICAgICAgYm9keVxuICAgIH0pO1xuICB9XG5cbiAgbG9nUmVzcG9uc2Uoe1xuICAgIG1ldGhvZCxcbiAgICB1cmwsXG4gICAgcmVzdWx0XG4gIH0pIHtcbiAgICB0aGlzLnZlcmJvc2UoXG4gICAgICAoKSA9PiB7IGNvbnN0IHN0cmluZ2lmaWVkUmVzcG9uc2UgPSBKU09OLnN0cmluZ2lmeShyZXN1bHQsIG51bGwsIDIpO1xuICAgICAgICByZXR1cm4gYFJFU1BPTlNFIGZyb20gWyR7bWV0aG9kfV0gJHt1cmx9OiAke3N0cmluZ2lmaWVkUmVzcG9uc2V9YDtcbiAgICAgIH0sXG4gICAgICB7cmVzdWx0OiByZXN1bHR9XG4gICAgKTtcbiAgfVxuICAvLyBjaGVjayB0aGF0IGRhdGUgaW5wdXQgaXMgdmFsaWRcbiAgc3RhdGljIHZhbGlkRGF0ZVRpbWUoZGF0ZSkge1xuICAgIGlmICghZGF0ZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGRhdGUgPSBuZXcgRGF0ZShkYXRlKTtcblxuICAgIGlmICghaXNOYU4oZGF0ZS5nZXRUaW1lKCkpKSB7XG4gICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHRydW5jYXRlTG9nTWVzc2FnZShzdHJpbmcpIHtcbiAgICBpZiAoc3RyaW5nICYmIHN0cmluZy5sZW5ndGggPiBMT0dfU1RSSU5HX1RSVU5DQVRFX0xFTkdUSCkge1xuICAgICAgY29uc3QgdHJ1bmNhdGVkID0gc3RyaW5nLnN1YnN0cmluZygwLCBMT0dfU1RSSU5HX1RSVU5DQVRFX0xFTkdUSCkgKyB0cnVuY2F0aW9uTWFya2VyO1xuICAgICAgcmV0dXJuIHRydW5jYXRlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc3RyaW5nO1xuICB9XG5cbiAgc3RhdGljIHBhcnNlT3B0aW9ucyhvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBmcm9tID0gTG9nZ2VyQ29udHJvbGxlci52YWxpZERhdGVUaW1lKG9wdGlvbnMuZnJvbSkgfHxcbiAgICAgIG5ldyBEYXRlKERhdGUubm93KCkgLSA3ICogTUlMTElTRUNPTkRTX0lOX0FfREFZKTtcbiAgICBjb25zdCB1bnRpbCA9IExvZ2dlckNvbnRyb2xsZXIudmFsaWREYXRlVGltZShvcHRpb25zLnVudGlsKSB8fCBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IHNpemUgPSBOdW1iZXIob3B0aW9ucy5zaXplKSB8fCAxMDtcbiAgICBjb25zdCBvcmRlciA9IG9wdGlvbnMub3JkZXIgfHwgTG9nT3JkZXIuREVTQ0VORElORztcbiAgICBjb25zdCBsZXZlbCA9IG9wdGlvbnMubGV2ZWwgfHwgTG9nTGV2ZWwuSU5GTztcblxuICAgIHJldHVybiB7XG4gICAgICBmcm9tLFxuICAgICAgdW50aWwsXG4gICAgICBzaXplLFxuICAgICAgb3JkZXIsXG4gICAgICBsZXZlbCxcbiAgICB9O1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEge3Jlc3BvbnNlfSBvYmplY3QuXG4gIC8vIHF1ZXJ5IHBhcmFtczpcbiAgLy8gbGV2ZWwgKG9wdGlvbmFsKSBMZXZlbCBvZiBsb2dnaW5nIHlvdSB3YW50IHRvIHF1ZXJ5IGZvciAoaW5mbyB8fCBlcnJvcilcbiAgLy8gZnJvbSAob3B0aW9uYWwpIFN0YXJ0IHRpbWUgZm9yIHRoZSBzZWFyY2guIERlZmF1bHRzIHRvIDEgd2VlayBhZ28uXG4gIC8vIHVudGlsIChvcHRpb25hbCkgRW5kIHRpbWUgZm9yIHRoZSBzZWFyY2guIERlZmF1bHRzIHRvIGN1cnJlbnQgdGltZS5cbiAgLy8gb3JkZXIgKG9wdGlvbmFsKSBEaXJlY3Rpb24gb2YgcmVzdWx0cyByZXR1cm5lZCwgZWl0aGVyIOKAnGFzY+KAnSBvciDigJxkZXNj4oCdLiBEZWZhdWx0cyB0byDigJxkZXNj4oCdLlxuICAvLyBzaXplIChvcHRpb25hbCkgTnVtYmVyIG9mIHJvd3MgcmV0dXJuZWQgYnkgc2VhcmNoLiBEZWZhdWx0cyB0byAxMFxuICBnZXRMb2dzKG9wdGlvbnMgPSB7fSkge1xuICAgIGlmICghdGhpcy5hZGFwdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnTG9nZ2VyIGFkYXB0ZXIgaXMgbm90IGF2YWlsYWJsZScpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHRoaXMuYWRhcHRlci5xdWVyeSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgJ1F1ZXJ5aW5nIGxvZ3MgaXMgbm90IHN1cHBvcnRlZCB3aXRoIHRoaXMgYWRhcHRlcicpO1xuICAgIH1cbiAgICBvcHRpb25zID0gTG9nZ2VyQ29udHJvbGxlci5wYXJzZU9wdGlvbnMob3B0aW9ucyk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5xdWVyeShvcHRpb25zKTtcbiAgfVxuXG4gIGV4cGVjdGVkQWRhcHRlclR5cGUoKSB7XG4gICAgcmV0dXJuIExvZ2dlckFkYXB0ZXI7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTG9nZ2VyQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js index 89599094ba..9c783a58fd 100644 --- a/lib/Controllers/PushController.js +++ b/lib/Controllers/PushController.js @@ -59,10 +59,12 @@ class PushController { 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'"; + throw "Invalid value for badge, expected number or 'Increment' or {increment: number}"; } // Force filtering on only valid device tokens @@ -209,4 +211,5 @@ class PushController { } exports.PushController = PushController; -exports.default = PushController; \ No newline at end of file +exports.default = PushController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJidWlsZFJlc3RXaGVyZSIsInRoZW4iLCJ3cml0ZSIsIlJlc3RXcml0ZSIsInJlc3RXaGVyZSIsInJ1bk9wdGlvbnMiLCJtYW55IiwiZXhlY3V0ZSIsInB1c2hTdGF0dXMiLCJzZXRJbml0aWFsIiwib2JqZWN0SWQiLCJhdWRpZW5jZV9pZCIsImF1ZGllbmNlSWQiLCJ1cGRhdGVBdWRpZW5jZSIsImxhc3RVc2VkIiwiX190eXBlIiwiaXNvIiwidG9JU09TdHJpbmciLCJ0aW1lc1VzZWQiLCJoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCIsInB1c2hDb250cm9sbGVyUXVldWUiLCJlbnF1ZXVlIiwiY2F0Y2giLCJlcnIiLCJmYWlsIiwiaGFzRXhwaXJhdGlvblRpbWUiLCJleHBpcmF0aW9uVGltZVBhcmFtIiwiZXhwaXJhdGlvblRpbWUiLCJpc0Zpbml0ZSIsImhhc0V4cGlyYXRpb25JbnRlcnZhbCIsImV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIiwiaGFzUHVzaFRpbWUiLCJwdXNoVGltZVBhcmFtIiwiaXNMb2NhbFRpbWUiLCJwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50Iiwib2Zmc2V0UGF0dGVybiIsImluZGV4T2YiLCJsZW5ndGgiLCJ0ZXN0IiwiaXNvU3RyaW5nIiwic3Vic3RyaW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsY0FBTixDQUFxQjs7QUFFMUJDLFdBQVNDLE9BQU8sRUFBaEIsRUFBb0JDLFFBQVEsRUFBNUIsRUFBZ0NDLE1BQWhDLEVBQXdDQyxJQUF4QyxFQUE4Q0Msb0JBQW9CLE1BQU0sQ0FBRSxDQUExRSxFQUE0RUMsTUFBTSxJQUFJQyxJQUFKLEVBQWxGLEVBQThGO0FBQzVGLFFBQUksQ0FBQ0osT0FBT0ssY0FBWixFQUE0QjtBQUMxQixZQUFNLElBQUlDLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0osNEJBREksQ0FBTjtBQUVEOztBQUVEO0FBQ0FWLFNBQUtXLGVBQUwsR0FBdUJiLGVBQWVjLGlCQUFmLENBQWlDWixJQUFqQyxDQUF2QjtBQUNBQSxTQUFLYSxtQkFBTCxHQUEyQmYsZUFBZWdCLHFCQUFmLENBQXFDZCxJQUFyQyxDQUEzQjtBQUNBLFFBQUlBLEtBQUtXLGVBQUwsSUFBd0JYLEtBQUthLG1CQUFqQyxFQUFzRDtBQUNwRCxZQUFNLElBQUlMLFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKLDREQUZJLENBQU47QUFHRDs7QUFFRDtBQUNBLFFBQUlWLEtBQUthLG1CQUFMLElBQTRCLENBQUNiLEtBQUtlLGNBQUwsQ0FBb0IsV0FBcEIsQ0FBakMsRUFBbUU7QUFDakUsWUFBTUMsUUFBUWhCLEtBQUthLG1CQUFMLEdBQTJCLElBQXpDO0FBQ0FiLFdBQUtXLGVBQUwsR0FBd0IsSUFBSUwsSUFBSixDQUFTRCxJQUFJWSxPQUFKLEtBQWdCRCxLQUF6QixDQUFELENBQWtDQyxPQUFsQyxFQUF2QjtBQUNEOztBQUVELFVBQU1DLFdBQVdwQixlQUFlcUIsV0FBZixDQUEyQm5CLElBQTNCLENBQWpCO0FBQ0EsUUFBSWtCLFlBQVlBLFNBQVNFLElBQVQsS0FBa0IsV0FBbEMsRUFBK0M7QUFDN0NwQixXQUFLLFdBQUwsSUFBb0JGLGVBQWV1QixjQUFmLENBQThCSCxRQUE5QixDQUFwQjtBQUNEOztBQUVEO0FBQ0E7QUFDQSxRQUFJSSxjQUFjLE1BQU07QUFDdEIsYUFBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0QsS0FGRDs7QUFJQSxRQUFJeEIsS0FBS3lCLElBQUwsSUFBYXpCLEtBQUt5QixJQUFMLENBQVVDLEtBQTNCLEVBQWtDO0FBQ2hDLFlBQU1BLFFBQVExQixLQUFLeUIsSUFBTCxDQUFVQyxLQUF4QjtBQUNBLFVBQUlDLGFBQWEsRUFBakI7QUFDQSxVQUFJLE9BQU9ELEtBQVAsSUFBZ0IsUUFBaEIsSUFBNEJBLE1BQU1FLFdBQU4sT0FBd0IsV0FBeEQsRUFBcUU7QUFDbkVELHFCQUFhLEVBQUVELE9BQU8sRUFBRUcsTUFBTSxXQUFSLEVBQXFCQyxRQUFRLENBQTdCLEVBQVQsRUFBYjtBQUNELE9BRkQsTUFFTyxJQUFJLE9BQU9KLEtBQVAsSUFBZ0IsUUFBaEIsSUFBNEIsT0FBT0EsTUFBTUcsSUFBYixJQUFxQixRQUFqRCxJQUNBSCxNQUFNRyxJQUFOLENBQVdELFdBQVgsTUFBNEIsV0FENUIsSUFDMkNHLE9BQU9MLE1BQU1JLE1BQWIsQ0FEL0MsRUFDcUU7QUFDMUVILHFCQUFhLEVBQUVELE9BQU8sRUFBRUcsTUFBTSxXQUFSLEVBQXFCQyxRQUFRSixNQUFNSSxNQUFuQyxFQUFULEVBQWI7QUFDRCxPQUhNLE1BR0EsSUFBSUMsT0FBT0wsS0FBUCxDQUFKLEVBQW1CO0FBQ3hCQyxxQkFBYSxFQUFFRCxPQUFPQSxLQUFULEVBQWI7QUFDRCxPQUZNLE1BRUE7QUFDTCxjQUFNLGdGQUFOO0FBQ0Q7O0FBRUQ7QUFDQSxZQUFNTSxjQUFjLG1DQUF1Qi9CLEtBQXZCLENBQXBCO0FBQ0FxQixvQkFBYyxNQUFNO0FBQ2xCO0FBQ0EsY0FBTVcsWUFBWSxJQUFJQyxtQkFBSixDQUFjaEMsTUFBZCxFQUFzQixrQkFBT0EsTUFBUCxDQUF0QixFQUFzQyxlQUF0QyxFQUF1RDhCLFdBQXZELENBQWxCO0FBQ0EsZUFBT0MsVUFBVUUsY0FBVixHQUEyQkMsSUFBM0IsQ0FBZ0MsTUFBTTtBQUMzQyxnQkFBTUMsUUFBUSxJQUFJQyxtQkFBSixDQUFjcEMsTUFBZCxFQUFzQixrQkFBT0EsTUFBUCxDQUF0QixFQUFzQyxlQUF0QyxFQUF1RCtCLFVBQVVNLFNBQWpFLEVBQTRFWixVQUE1RSxDQUFkO0FBQ0FVLGdCQUFNRyxVQUFOLENBQWlCQyxJQUFqQixHQUF3QixJQUF4QjtBQUNBLGlCQUFPSixNQUFNSyxPQUFOLEVBQVA7QUFDRCxTQUpNLENBQVA7QUFLRCxPQVJEO0FBU0Q7QUFDRCxVQUFNQyxhQUFhLHNDQUFrQnpDLE1BQWxCLENBQW5CO0FBQ0EsV0FBT3FCLFFBQVFDLE9BQVIsR0FBa0JZLElBQWxCLENBQXVCLE1BQU07QUFDbEMsYUFBT08sV0FBV0MsVUFBWCxDQUFzQjVDLElBQXRCLEVBQTRCQyxLQUE1QixDQUFQO0FBQ0QsS0FGTSxFQUVKbUMsSUFGSSxDQUVDLE1BQU07QUFDWmhDLHdCQUFrQnVDLFdBQVdFLFFBQTdCO0FBQ0EsYUFBT3ZCLGFBQVA7QUFDRCxLQUxNLEVBS0pjLElBTEksQ0FLQyxNQUFNO0FBQ1o7QUFDQSxVQUFJcEMsS0FBSzhDLFdBQVQsRUFBc0I7QUFDcEIsY0FBTUMsYUFBYS9DLEtBQUs4QyxXQUF4Qjs7QUFFQSxZQUFJRSxpQkFBaUI7QUFDbkJDLG9CQUFVLEVBQUVDLFFBQVEsTUFBVixFQUFrQkMsS0FBSyxJQUFJN0MsSUFBSixHQUFXOEMsV0FBWCxFQUF2QixFQURTO0FBRW5CQyxxQkFBVyxFQUFFeEIsTUFBTSxXQUFSLEVBQXFCLFVBQVUsQ0FBL0I7QUFGUSxTQUFyQjtBQUlBLGNBQU1RLFFBQVEsSUFBSUMsbUJBQUosQ0FBY3BDLE1BQWQsRUFBc0Isa0JBQU9BLE1BQVAsQ0FBdEIsRUFBc0MsV0FBdEMsRUFBbUQsRUFBQzJDLFVBQVVFLFVBQVgsRUFBbkQsRUFBMkVDLGNBQTNFLENBQWQ7QUFDQVgsY0FBTUssT0FBTjtBQUNEO0FBQ0Q7QUFDQSxhQUFPbkIsUUFBUUMsT0FBUixFQUFQO0FBQ0QsS0FuQk0sRUFtQkpZLElBbkJJLENBbUJDLE1BQU07QUFDWixVQUFJcEMsS0FBS2UsY0FBTCxDQUFvQixXQUFwQixLQUFvQ2IsT0FBT29ELHVCQUEvQyxFQUF3RTtBQUN0RSxlQUFPL0IsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7QUFDRCxhQUFPdEIsT0FBT3FELG1CQUFQLENBQTJCQyxPQUEzQixDQUFtQ3hELElBQW5DLEVBQXlDQyxLQUF6QyxFQUFnREMsTUFBaEQsRUFBd0RDLElBQXhELEVBQThEd0MsVUFBOUQsQ0FBUDtBQUNELEtBeEJNLEVBd0JKYyxLQXhCSSxDQXdCR0MsR0FBRCxJQUFTO0FBQ2hCLGFBQU9mLFdBQVdnQixJQUFYLENBQWdCRCxHQUFoQixFQUFxQnRCLElBQXJCLENBQTBCLE1BQU07QUFDckMsY0FBTXNCLEdBQU47QUFDRCxPQUZNLENBQVA7QUFHRCxLQTVCTSxDQUFQO0FBNkJEOztBQUVEOzs7OztBQUtBLFNBQU85QyxpQkFBUCxDQUF5QlosT0FBTyxFQUFoQyxFQUFvQztBQUNsQyxRQUFJNEQsb0JBQW9CNUQsS0FBS2UsY0FBTCxDQUFvQixpQkFBcEIsQ0FBeEI7QUFDQSxRQUFJLENBQUM2QyxpQkFBTCxFQUF3QjtBQUN0QjtBQUNEO0FBQ0QsUUFBSUMsc0JBQXNCN0QsS0FBSyxpQkFBTCxDQUExQjtBQUNBLFFBQUk4RCxjQUFKO0FBQ0EsUUFBSSxPQUFPRCxtQkFBUCxLQUErQixRQUFuQyxFQUE2QztBQUMzQ0MsdUJBQWlCLElBQUl4RCxJQUFKLENBQVN1RCxzQkFBc0IsSUFBL0IsQ0FBakI7QUFDRCxLQUZELE1BRU8sSUFBSSxPQUFPQSxtQkFBUCxLQUErQixRQUFuQyxFQUE2QztBQUNsREMsdUJBQWlCLElBQUl4RCxJQUFKLENBQVN1RCxtQkFBVCxDQUFqQjtBQUNELEtBRk0sTUFFQTtBQUNMLFlBQU0sSUFBSXJELFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0pWLEtBQUssaUJBQUwsSUFBMEIscUJBRHRCLENBQU47QUFFRDtBQUNEO0FBQ0EsUUFBSSxDQUFDK0QsU0FBU0QsY0FBVCxDQUFMLEVBQStCO0FBQzdCLFlBQU0sSUFBSXRELFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0pWLEtBQUssaUJBQUwsSUFBMEIscUJBRHRCLENBQU47QUFFRDtBQUNELFdBQU84RCxlQUFlN0MsT0FBZixFQUFQO0FBQ0Q7O0FBRUQsU0FBT0gscUJBQVAsQ0FBNkJkLE9BQU8sRUFBcEMsRUFBd0M7QUFDdEMsVUFBTWdFLHdCQUF3QmhFLEtBQUtlLGNBQUwsQ0FBb0IscUJBQXBCLENBQTlCO0FBQ0EsUUFBSSxDQUFDaUQscUJBQUwsRUFBNEI7QUFDMUI7QUFDRDs7QUFFRCxRQUFJQywwQkFBMEJqRSxLQUFLLHFCQUFMLENBQTlCO0FBQ0EsUUFBSSxPQUFPaUUsdUJBQVAsS0FBbUMsUUFBbkMsSUFBK0NBLDJCQUEyQixDQUE5RSxFQUFpRjtBQUMvRSxZQUFNLElBQUl6RCxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNILHFEQURHLENBQU47QUFFRDtBQUNELFdBQU91RCx1QkFBUDtBQUNEOztBQUVEOzs7OztBQUtBLFNBQU85QyxXQUFQLENBQW1CbkIsT0FBTyxFQUExQixFQUE4QjtBQUM1QixRQUFJa0UsY0FBY2xFLEtBQUtlLGNBQUwsQ0FBb0IsV0FBcEIsQ0FBbEI7QUFDQSxRQUFJLENBQUNtRCxXQUFMLEVBQWtCO0FBQ2hCO0FBQ0Q7QUFDRCxRQUFJQyxnQkFBZ0JuRSxLQUFLLFdBQUwsQ0FBcEI7QUFDQSxRQUFJb0IsSUFBSjtBQUNBLFFBQUlnRCxjQUFjLElBQWxCOztBQUVBLFFBQUksT0FBT0QsYUFBUCxLQUF5QixRQUE3QixFQUF1QztBQUNyQy9DLGFBQU8sSUFBSWQsSUFBSixDQUFTNkQsZ0JBQWdCLElBQXpCLENBQVA7QUFDRCxLQUZELE1BRU8sSUFBSSxPQUFPQSxhQUFQLEtBQXlCLFFBQTdCLEVBQXVDO0FBQzVDQyxvQkFBYyxDQUFDdEUsZUFBZXVFLDRCQUFmLENBQTRDRixhQUE1QyxDQUFmO0FBQ0EvQyxhQUFPLElBQUlkLElBQUosQ0FBUzZELGFBQVQsQ0FBUDtBQUNELEtBSE0sTUFHQTtBQUNMLFlBQU0sSUFBSTNELFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0pWLEtBQUssV0FBTCxJQUFvQixxQkFEaEIsQ0FBTjtBQUVEO0FBQ0Q7QUFDQSxRQUFJLENBQUMrRCxTQUFTM0MsSUFBVCxDQUFMLEVBQXFCO0FBQ25CLFlBQU0sSUFBSVosWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZQyxrQkFBNUIsRUFDSlYsS0FBSyxXQUFMLElBQW9CLHFCQURoQixDQUFOO0FBRUQ7O0FBRUQsV0FBTztBQUNMb0IsVUFESztBQUVMZ0Q7QUFGSyxLQUFQO0FBSUQ7O0FBRUQ7Ozs7O0FBS0EsU0FBT0MsNEJBQVAsQ0FBb0NGLGFBQXBDLEVBQW9FO0FBQ2xFLFVBQU1HLGdCQUFnQixzQkFBdEI7QUFDQSxXQUFPSCxjQUFjSSxPQUFkLENBQXNCLEdBQXRCLE1BQStCSixjQUFjSyxNQUFkLEdBQXVCLENBQXRELENBQXdEO0FBQXhELE9BQ0ZGLGNBQWNHLElBQWQsQ0FBbUJOLGFBQW5CLENBREwsQ0FGa0UsQ0FHMUI7QUFDekM7O0FBRUQ7Ozs7OztBQU1BLFNBQU85QyxjQUFQLENBQXNCLEVBQUVELElBQUYsRUFBUWdELFdBQVIsRUFBdEIsRUFBbUY7QUFDakYsUUFBSUEsV0FBSixFQUFpQjtBQUFFO0FBQ2pCLFlBQU1NLFlBQVl0RCxLQUFLZ0MsV0FBTCxFQUFsQjtBQUNBLGFBQU9zQixVQUFVQyxTQUFWLENBQW9CLENBQXBCLEVBQXVCRCxVQUFVSCxPQUFWLENBQWtCLEdBQWxCLENBQXZCLENBQVA7QUFDRDtBQUNELFdBQU9uRCxLQUFLZ0MsV0FBTCxFQUFQO0FBQ0Q7QUFoTXlCOztRQUFmdEQsYyxHQUFBQSxjO2tCQW1NRUEsYyIsImZpbGUiOiJQdXNoQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlIH0gICAgICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFJlc3RRdWVyeSAgICAgICAgICAgICAgZnJvbSAnLi4vUmVzdFF1ZXJ5JztcbmltcG9ydCBSZXN0V3JpdGUgICAgICAgICAgICAgIGZyb20gJy4uL1Jlc3RXcml0ZSc7XG5pbXBvcnQgeyBtYXN0ZXIgfSAgICAgICAgICAgICBmcm9tICcuLi9BdXRoJztcbmltcG9ydCB7IHB1c2hTdGF0dXNIYW5kbGVyIH0gIGZyb20gJy4uL1N0YXR1c0hhbmRsZXInO1xuaW1wb3J0IHsgYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyB9IGZyb20gJy4uL1B1c2gvdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgUHVzaENvbnRyb2xsZXIge1xuXG4gIHNlbmRQdXNoKGJvZHkgPSB7fSwgd2hlcmUgPSB7fSwgY29uZmlnLCBhdXRoLCBvblB1c2hTdGF0dXNTYXZlZCA9ICgpID0+IHt9LCBub3cgPSBuZXcgRGF0ZSgpKSB7XG4gICAgaWYgKCFjb25maWcuaGFzUHVzaFN1cHBvcnQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdNaXNzaW5nIHB1c2ggY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIFJlcGxhY2UgdGhlIGV4cGlyYXRpb25fdGltZSBhbmQgcHVzaF90aW1lIHdpdGggYSB2YWxpZCBVbml4IGVwb2NoIG1pbGxpc2Vjb25kcyB0aW1lXG4gICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uVGltZShib2R5KTtcbiAgICBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSk7XG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl90aW1lICYmIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdCb3RoIGV4cGlyYXRpb25fdGltZSBhbmQgZXhwaXJhdGlvbl9pbnRlcnZhbCBjYW5ub3QgYmUgc2V0Jyk7XG4gICAgfVxuXG4gICAgLy8gSW1tZWRpYXRlIHB1c2hcbiAgICBpZiAoYm9keS5leHBpcmF0aW9uX2ludGVydmFsICYmICFib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKSkge1xuICAgICAgY29uc3QgdHRsTXMgPSBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgKiAxMDAwO1xuICAgICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSAobmV3IERhdGUobm93LnZhbHVlT2YoKSArIHR0bE1zKSkudmFsdWVPZigpO1xuICAgIH1cblxuICAgIGNvbnN0IHB1c2hUaW1lID0gUHVzaENvbnRyb2xsZXIuZ2V0UHVzaFRpbWUoYm9keSk7XG4gICAgaWYgKHB1c2hUaW1lICYmIHB1c2hUaW1lLmRhdGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBib2R5WydwdXNoX3RpbWUnXSA9IFB1c2hDb250cm9sbGVyLmZvcm1hdFB1c2hUaW1lKHB1c2hUaW1lKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBJZiB0aGUgcmVxIGNhbiBwYXNzIHRoZSBjaGVja2luZywgd2UgcmV0dXJuIGltbWVkaWF0ZWx5IGluc3RlYWQgb2Ygd2FpdGluZ1xuICAgIC8vIHB1c2hlcyB0byBiZSBzZW50LiBXZSBwcm9iYWJseSBjaGFuZ2UgdGhpcyBiZWhhdmlvdXIgaW4gdGhlIGZ1dHVyZS5cbiAgICBsZXQgYmFkZ2VVcGRhdGUgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYgKGJvZHkuZGF0YSAmJiBib2R5LmRhdGEuYmFkZ2UpIHtcbiAgICAgIGNvbnN0IGJhZGdlID0gYm9keS5kYXRhLmJhZGdlO1xuICAgICAgbGV0IHJlc3RVcGRhdGUgPSB7fTtcbiAgICAgIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ3N0cmluZycgJiYgYmFkZ2UudG9Mb3dlckNhc2UoKSA9PT0gJ2luY3JlbWVudCcpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogMSB9IH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGJhZGdlID09ICdvYmplY3QnICYmIHR5cGVvZiBiYWRnZS5fX29wID09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICAgICAgIGJhZGdlLl9fb3AudG9Mb3dlckNhc2UoKSA9PSAnaW5jcmVtZW50JyAmJiBOdW1iZXIoYmFkZ2UuYW1vdW50KSkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBiYWRnZS5hbW91bnQgfSB9XG4gICAgICB9IGVsc2UgaWYgKE51bWJlcihiYWRnZSkpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IGJhZGdlIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IFwiSW52YWxpZCB2YWx1ZSBmb3IgYmFkZ2UsIGV4cGVjdGVkIG51bWJlciBvciAnSW5jcmVtZW50JyBvciB7aW5jcmVtZW50OiBudW1iZXJ9XCI7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvcmNlIGZpbHRlcmluZyBvbiBvbmx5IHZhbGlkIGRldmljZSB0b2tlbnNcbiAgICAgIGNvbnN0IHVwZGF0ZVdoZXJlID0gYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyh3aGVyZSk7XG4gICAgICBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgICAgLy8gQnVpbGQgYSByZWFsIFJlc3RRdWVyeSBzbyB3ZSBjYW4gdXNlIGl0IGluIFJlc3RXcml0ZVxuICAgICAgICBjb25zdCByZXN0UXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgdXBkYXRlV2hlcmUpO1xuICAgICAgICByZXR1cm4gcmVzdFF1ZXJ5LmJ1aWxkUmVzdFdoZXJlKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgcmVzdFF1ZXJ5LnJlc3RXaGVyZSwgcmVzdFVwZGF0ZSk7XG4gICAgICAgICAgd3JpdGUucnVuT3B0aW9ucy5tYW55ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcHVzaFN0YXR1cyA9IHB1c2hTdGF0dXNIYW5kbGVyKGNvbmZpZyk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHB1c2hTdGF0dXMuc2V0SW5pdGlhbChib2R5LCB3aGVyZSk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBvblB1c2hTdGF0dXNTYXZlZChwdXNoU3RhdHVzLm9iamVjdElkKTtcbiAgICAgIHJldHVybiBiYWRnZVVwZGF0ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gVXBkYXRlIGF1ZGllbmNlIGxhc3RVc2VkIGFuZCB0aW1lc1VzZWRcbiAgICAgIGlmIChib2R5LmF1ZGllbmNlX2lkKSB7XG4gICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgIHZhciB1cGRhdGVBdWRpZW5jZSA9IHtcbiAgICAgICAgICBsYXN0VXNlZDogeyBfX3R5cGU6IFwiRGF0ZVwiLCBpc286IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSB9LFxuICAgICAgICAgIHRpbWVzVXNlZDogeyBfX29wOiBcIkluY3JlbWVudFwiLCBcImFtb3VudFwiOiAxIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfQXVkaWVuY2UnLCB7b2JqZWN0SWQ6IGF1ZGllbmNlSWR9LCB1cGRhdGVBdWRpZW5jZSk7XG4gICAgICAgIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgIH1cbiAgICAgIC8vIERvbid0IHdhaXQgZm9yIHRoZSBhdWRpZW5jZSB1cGRhdGUgcHJvbWlzZSB0byByZXNvbHZlLlxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpICYmIGNvbmZpZy5oYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShib2R5LCB3aGVyZSwgY29uZmlnLCBhdXRoLCBwdXNoU3RhdHVzKTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5mYWlsKGVycikudGhlbigoKSA9PiB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBleHBpcmF0aW9uIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgZXhwaXJhdGlvbiB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldEV4cGlyYXRpb25UaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNFeHBpcmF0aW9uVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25fdGltZScpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvblRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV4cGlyYXRpb25UaW1lUGFyYW0gPSBib2R5WydleHBpcmF0aW9uX3RpbWUnXTtcbiAgICB2YXIgZXhwaXJhdGlvblRpbWU7XG4gICAgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwaXJhdGlvblRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGV4cGlyYXRpb25UaW1lID0gbmV3IERhdGUoZXhwaXJhdGlvblRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZXhwaXJhdGlvblRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIGV4cGlyYXRpb25UaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZXhwaXJhdGlvblRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBib2R5WydleHBpcmF0aW9uX3RpbWUnXSArICcgaXMgbm90IHZhbGlkIHRpbWUuJyk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uVGltZS52YWx1ZU9mKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkgPSB7fSkge1xuICAgIGNvbnN0IGhhc0V4cGlyYXRpb25JbnRlcnZhbCA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25faW50ZXJ2YWwnKTtcbiAgICBpZiAoIWhhc0V4cGlyYXRpb25JbnRlcnZhbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25faW50ZXJ2YWwnXTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtICE9PSAnbnVtYmVyJyB8fCBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBgZXhwaXJhdGlvbl9pbnRlcnZhbCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAwYCk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcHVzaCB0aW1lIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcXVlc3QgQSByZXF1ZXN0IG9iamVjdFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfHVuZGVmaW5lZH0gVGhlIHB1c2ggdGltZSBpZiBpdCBleGlzdHMgaW4gdGhlIHJlcXVlc3RcbiAgICovXG4gIHN0YXRpYyBnZXRQdXNoVGltZShib2R5ID0ge30pIHtcbiAgICB2YXIgaGFzUHVzaFRpbWUgPSBib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKTtcbiAgICBpZiAoIWhhc1B1c2hUaW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBwdXNoVGltZVBhcmFtID0gYm9keVsncHVzaF90aW1lJ107XG4gICAgdmFyIGRhdGU7XG4gICAgdmFyIGlzTG9jYWxUaW1lID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlzTG9jYWxUaW1lID0gIVB1c2hDb250cm9sbGVyLnB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbSk7XG4gICAgICBkYXRlID0gbmV3IERhdGUocHVzaFRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgcHVzaFRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIHB1c2hUaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZGF0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0ZSxcbiAgICAgIGlzTG9jYWxUaW1lLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgSVNPODYwMSBmb3JtYXR0ZWQgZGF0ZSBjb250YWlucyBhIHRpbWV6b25lIGNvbXBvbmVudFxuICAgKiBAcGFyYW0gcHVzaFRpbWVQYXJhbSB7c3RyaW5nfVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50KHB1c2hUaW1lUGFyYW06IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG9mZnNldFBhdHRlcm4gPSAvKC4rKShbKy1dKVxcZFxcZDpcXGRcXGQkLztcbiAgICByZXR1cm4gcHVzaFRpbWVQYXJhbS5pbmRleE9mKCdaJykgPT09IHB1c2hUaW1lUGFyYW0ubGVuZ3RoIC0gMSAvLyAyMDA3LTA0LTA1VDEyOjMwWlxuICAgICAgfHwgb2Zmc2V0UGF0dGVybi50ZXN0KHB1c2hUaW1lUGFyYW0pOyAvLyAyMDA3LTA0LTA1VDEyOjMwLjAwMCswMjowMCwgMjAwNy0wNC0wNVQxMjozMC4wMDAtMDI6MDBcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGRhdGUgdG8gSVNPIGZvcm1hdCBpbiBVVEMgdGltZSBhbmQgc3RyaXBzIHRoZSB0aW1lem9uZSBpZiBgaXNMb2NhbFRpbWVgIGlzIHRydWVcbiAgICogQHBhcmFtIGRhdGUge0RhdGV9XG4gICAqIEBwYXJhbSBpc0xvY2FsVGltZSB7Ym9vbGVhbn1cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBmb3JtYXRQdXNoVGltZSh7IGRhdGUsIGlzTG9jYWxUaW1lIH06IHsgZGF0ZTogRGF0ZSwgaXNMb2NhbFRpbWU6IGJvb2xlYW4gfSkge1xuICAgIGlmIChpc0xvY2FsVGltZSkgeyAvLyBTdHJpcCAnWidcbiAgICAgIGNvbnN0IGlzb1N0cmluZyA9IGRhdGUudG9JU09TdHJpbmcoKTtcbiAgICAgIHJldHVybiBpc29TdHJpbmcuc3Vic3RyaW5nKDAsIGlzb1N0cmluZy5pbmRleE9mKCdaJykpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hDb250cm9sbGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Controllers/SchemaCache.js b/lib/Controllers/SchemaCache.js index 67982c4287..3e9fede799 100644 --- a/lib/Controllers/SchemaCache.js +++ b/lib/Controllers/SchemaCache.js @@ -93,4 +93,5 @@ class SchemaCache { }); } } -exports.default = SchemaCache; \ No newline at end of file +exports.default = SchemaCache; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9TY2hlbWFDYWNoZS5qcyJdLCJuYW1lcyI6WyJNQUlOX1NDSEVNQSIsIlNDSEVNQV9DQUNIRV9QUkVGSVgiLCJBTExfS0VZUyIsIlNjaGVtYUNhY2hlIiwiY29uc3RydWN0b3IiLCJjYWNoZUNvbnRyb2xsZXIiLCJ0dGwiLCJkZWZhdWx0cyIsInNjaGVtYUNhY2hlVFRMIiwic2luZ2xlQ2FjaGUiLCJwYXJzZUludCIsImNhY2hlIiwicHJlZml4IiwicHV0Iiwia2V5IiwidmFsdWUiLCJnZXQiLCJ0aGVuIiwiYWxsS2V5cyIsIlByb21pc2UiLCJhbGwiLCJnZXRBbGxDbGFzc2VzIiwicmVzb2x2ZSIsInNldEFsbENsYXNzZXMiLCJzY2hlbWEiLCJzZXRPbmVTY2hlbWEiLCJjbGFzc05hbWUiLCJnZXRPbmVTY2hlbWEiLCJjYWNoZWRTY2hlbWFzIiwiZmluZCIsImNhY2hlZFNjaGVtYSIsImNsZWFyIiwicHJvbWlzZXMiLCJPYmplY3QiLCJrZXlzIiwibWFwIiwiZGVsIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFJQTs7QUFDQTs7Ozs7O0FBTEEsTUFBTUEsY0FBYyxlQUFwQjtBQUNBLE1BQU1DLHNCQUFzQixVQUE1QjtBQUNBLE1BQU1DLFdBQVcsWUFBakI7O0FBS2UsTUFBTUMsV0FBTixDQUFrQjs7QUFHL0JDLGNBQVlDLGVBQVosRUFBNkJDLE1BQU1DLG1CQUFTQyxjQUE1QyxFQUE0REMsY0FBYyxLQUExRSxFQUFpRjtBQUMvRSxTQUFLSCxHQUFMLEdBQVdBLEdBQVg7QUFDQSxRQUFJLE9BQU9BLEdBQVAsSUFBYyxRQUFsQixFQUE0QjtBQUMxQixXQUFLQSxHQUFMLEdBQVdJLFNBQVNKLEdBQVQsQ0FBWDtBQUNEO0FBQ0QsU0FBS0ssS0FBTCxHQUFhTixlQUFiO0FBQ0EsU0FBS08sTUFBTCxHQUFjWCxtQkFBZDtBQUNBLFFBQUksQ0FBQ1EsV0FBTCxFQUFrQjtBQUNoQixXQUFLRyxNQUFMLElBQWUsK0JBQWEsRUFBYixD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LENBQWV0QixHQUFmLENBQVA7QUFDRCxPQUZnQixDQUFqQjtBQUdBLGFBQU9LLFFBQVFDLEdBQVIsQ0FBWVksUUFBWixDQUFQO0FBQ0QsS0FSTSxDQUFQO0FBU0Q7QUE1RThCO2tCQUFaN0IsVyIsImZpbGUiOiJTY2hlbWFDYWNoZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IE1BSU5fU0NIRU1BID0gXCJfX01BSU5fU0NIRU1BXCI7XG5jb25zdCBTQ0hFTUFfQ0FDSEVfUFJFRklYID0gXCJfX1NDSEVNQVwiO1xuY29uc3QgQUxMX0tFWVMgPSBcIl9fQUxMX0tFWVNcIjtcblxuaW1wb3J0IHsgcmFuZG9tU3RyaW5nIH0gZnJvbSAnLi4vY3J5cHRvVXRpbHMnO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4uL2RlZmF1bHRzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2NoZW1hQ2FjaGUge1xuICBjYWNoZTogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKGNhY2hlQ29udHJvbGxlciwgdHRsID0gZGVmYXVsdHMuc2NoZW1hQ2FjaGVUVEwsIHNpbmdsZUNhY2hlID0gZmFsc2UpIHtcbiAgICB0aGlzLnR0bCA9IHR0bDtcbiAgICBpZiAodHlwZW9mIHR0bCA9PSAnc3RyaW5nJykge1xuICAgICAgdGhpcy50dGwgPSBwYXJzZUludCh0dGwpO1xuICAgIH1cbiAgICB0aGlzLmNhY2hlID0gY2FjaGVDb250cm9sbGVyO1xuICAgIHRoaXMucHJlZml4ID0gU0NIRU1BX0NBQ0hFX1BSRUZJWDtcbiAgICBpZiAoIXNpbmdsZUNhY2hlKSB7XG4gICAgICB0aGlzLnByZWZpeCArPSByYW5kb21TdHJpbmcoMjApO1xuICAgIH1cbiAgfVxuXG4gIHB1dChrZXksIHZhbHVlKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0KHRoaXMucHJlZml4ICsgQUxMX0tFWVMpLnRoZW4oKGFsbEtleXMpID0+IHtcbiAgICAgIGFsbEtleXMgPSBhbGxLZXlzIHx8IHt9O1xuICAgICAgYWxsS2V5c1trZXldID0gdHJ1ZTtcbiAgICAgIHJldHVybiBQcm9taXNlLmFsbChbdGhpcy5jYWNoZS5wdXQodGhpcy5wcmVmaXggKyBBTExfS0VZUywgYWxsS2V5cywgdGhpcy50dGwpLCB0aGlzLmNhY2hlLnB1dChrZXksIHZhbHVlLCB0aGlzLnR0bCldKTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldEFsbENsYXNzZXMoKSB7XG4gICAgaWYgKCF0aGlzLnR0bCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0KHRoaXMucHJlZml4ICsgTUFJTl9TQ0hFTUEpO1xuICB9XG5cbiAgc2V0QWxsQ2xhc3NlcyhzY2hlbWEpIHtcbiAgICBpZiAoIXRoaXMudHRsKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wdXQodGhpcy5wcmVmaXggKyBNQUlOX1NDSEVNQSwgc2NoZW1hKTtcbiAgfVxuXG4gIHNldE9uZVNjaGVtYShjbGFzc05hbWUsIHNjaGVtYSkge1xuICAgIGlmICghdGhpcy50dGwpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnB1dCh0aGlzLnByZWZpeCArIGNsYXNzTmFtZSwgc2NoZW1hKTtcbiAgfVxuXG4gIGdldE9uZVNjaGVtYShjbGFzc05hbWUpIHtcbiAgICBpZiAoIXRoaXMudHRsKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQodGhpcy5wcmVmaXggKyBjbGFzc05hbWUpLnRoZW4oKHNjaGVtYSkgPT4ge1xuICAgICAgaWYgKHNjaGVtYSkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHNjaGVtYSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQodGhpcy5wcmVmaXggKyBNQUlOX1NDSEVNQSkudGhlbigoY2FjaGVkU2NoZW1hcykgPT4ge1xuICAgICAgICBjYWNoZWRTY2hlbWFzID0gY2FjaGVkU2NoZW1hcyB8fCBbXTtcbiAgICAgICAgc2NoZW1hID0gY2FjaGVkU2NoZW1hcy5maW5kKChjYWNoZWRTY2hlbWEpID0+IHtcbiAgICAgICAgICByZXR1cm4gY2FjaGVkU2NoZW1hLmNsYXNzTmFtZSA9PT0gY2xhc3NOYW1lO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHNjaGVtYSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc2NoZW1hKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBjbGVhcigpIHtcbiAgICAvLyBUaGF0IGNsZWFycyBhbGwgY2FjaGVzLi4uXG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0KHRoaXMucHJlZml4ICsgQUxMX0tFWVMpLnRoZW4oKGFsbEtleXMpID0+IHtcbiAgICAgIGlmICghYWxsS2V5cykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBwcm9taXNlcyA9IE9iamVjdC5rZXlzKGFsbEtleXMpLm1hcCgoa2V5KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhY2hlLmRlbChrZXkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgIH0pO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/SchemaController.js b/lib/Controllers/SchemaController.js index ec89d50464..8375695153 100644 --- a/lib/Controllers/SchemaController.js +++ b/lib/Controllers/SchemaController.js @@ -519,6 +519,8 @@ class SchemaController { 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); @@ -548,7 +550,7 @@ class SchemaController { return this.enforceFieldExists(className, fieldName, type); }); return Promise.all(promises); - }).then(() => this.setPermissions(className, classLevelPermissions, newSchema)).then(() => this._dbAdapter.setIndexesWithSchemaFormat(className, indexes, schema.indexes, newSchema)).then(() => this.reloadData({ clearCache: true })) + }).then(() => 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(() => { const reloadedSchema = { @@ -1073,4 +1075,5 @@ exports.systemClasses = systemClasses; exports.defaultColumns = defaultColumns; exports.convertSchemaToAdapterSchema = convertSchemaToAdapterSchema; exports.VolatileClassesSchemas = VolatileClassesSchemas; -exports.SchemaController = SchemaController; \ No newline at end of file +exports.SchemaController = SchemaController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9TY2hlbWFDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsImRlZmF1bHRDb2x1bW5zIiwiT2JqZWN0IiwiZnJlZXplIiwiX0RlZmF1bHQiLCJ0eXBlIiwiX1VzZXIiLCJfSW5zdGFsbGF0aW9uIiwiX1JvbGUiLCJ0YXJnZXRDbGFzcyIsIl9TZXNzaW9uIiwiX1Byb2R1Y3QiLCJfUHVzaFN0YXR1cyIsIl9Kb2JTdGF0dXMiLCJfSm9iU2NoZWR1bGUiLCJfSG9va3MiLCJfR2xvYmFsQ29uZmlnIiwiX0F1ZGllbmNlIiwiX0V4cG9ydFByb2dyZXNzIiwicmVxdWlyZWRDb2x1bW5zIiwic3lzdGVtQ2xhc3NlcyIsInZvbGF0aWxlQ2xhc3NlcyIsInVzZXJJZFJlZ2V4Iiwicm9sZVJlZ2V4IiwicHVibGljUmVnZXgiLCJyZXF1aXJlQXV0aGVudGljYXRpb25SZWdleCIsInBlcm1pc3Npb25LZXlSZWdleCIsInZlcmlmeVBlcm1pc3Npb25LZXkiLCJrZXkiLCJyZXN1bHQiLCJyZWR1Y2UiLCJpc0dvb2QiLCJyZWdFeCIsIm1hdGNoIiwiRXJyb3IiLCJJTlZBTElEX0pTT04iLCJDTFBWYWxpZEtleXMiLCJ2YWxpZGF0ZUNMUCIsInBlcm1zIiwiZmllbGRzIiwia2V5cyIsImZvckVhY2giLCJvcGVyYXRpb24iLCJpbmRleE9mIiwiQXJyYXkiLCJpc0FycmF5IiwicGVybSIsImpvaW5DbGFzc1JlZ2V4IiwiY2xhc3NBbmRGaWVsZFJlZ2V4IiwiY2xhc3NOYW1lSXNWYWxpZCIsImNsYXNzTmFtZSIsInRlc3QiLCJmaWVsZE5hbWVJc1ZhbGlkIiwiZmllbGROYW1lIiwiZmllbGROYW1lSXNWYWxpZEZvckNsYXNzIiwiaW52YWxpZENsYXNzTmFtZU1lc3NhZ2UiLCJpbnZhbGlkSnNvbkVycm9yIiwidmFsaWROb25SZWxhdGlvbk9yUG9pbnRlclR5cGVzIiwiZmllbGRUeXBlSXNJbnZhbGlkIiwiSU5WQUxJRF9DTEFTU19OQU1FIiwidW5kZWZpbmVkIiwiSU5DT1JSRUNUX1RZUEUiLCJjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hIiwic2NoZW1hIiwiaW5qZWN0RGVmYXVsdFNjaGVtYSIsIkFDTCIsIl9ycGVybSIsIl93cGVybSIsInBhc3N3b3JkIiwiX2hhc2hlZF9wYXNzd29yZCIsImNvbnZlcnRBZGFwdGVyU2NoZW1hVG9QYXJzZVNjaGVtYSIsImF1dGhEYXRhIiwiaW5kZXhlcyIsImxlbmd0aCIsImNsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsImRlZmF1bHRTY2hlbWEiLCJfSG9va3NTY2hlbWEiLCJfR2xvYmFsQ29uZmlnU2NoZW1hIiwiX1B1c2hTdGF0dXNTY2hlbWEiLCJfSm9iU3RhdHVzU2NoZW1hIiwiX0pvYlNjaGVkdWxlU2NoZW1hIiwiX0F1ZGllbmNlU2NoZW1hIiwiVm9sYXRpbGVDbGFzc2VzU2NoZW1hcyIsImRiVHlwZU1hdGNoZXNPYmplY3RUeXBlIiwiZGJUeXBlIiwib2JqZWN0VHlwZSIsInR5cGVUb1N0cmluZyIsIlNjaGVtYUNvbnRyb2xsZXIiLCJjb25zdHJ1Y3RvciIsImRhdGFiYXNlQWRhcHRlciIsInNjaGVtYUNhY2hlIiwiX2RiQWRhcHRlciIsIl9jYWNoZSIsImRhdGEiLCJyZWxvYWREYXRhIiwib3B0aW9ucyIsImNsZWFyQ2FjaGUiLCJwcm9taXNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aGVuIiwiY2xlYXIiLCJyZWxvYWREYXRhUHJvbWlzZSIsImdldEFsbENsYXNzZXMiLCJhbGxTY2hlbWFzIiwiZXJyIiwiYWxsQ2xhc3NlcyIsIm1hcCIsInNldEFsbENsYXNzZXMiLCJnZXRPbmVTY2hlbWEiLCJhbGxvd1ZvbGF0aWxlQ2xhc3NlcyIsImNhY2hlZCIsImdldENsYXNzIiwic2V0T25lU2NoZW1hIiwiYWRkQ2xhc3NJZk5vdEV4aXN0cyIsInZhbGlkYXRpb25FcnJvciIsInZhbGlkYXRlTmV3Q2xhc3MiLCJyZWplY3QiLCJjcmVhdGVDbGFzcyIsInJlcyIsImNhdGNoIiwiZXJyb3IiLCJjb2RlIiwiRFVQTElDQVRFX1ZBTFVFIiwidXBkYXRlQ2xhc3MiLCJzdWJtaXR0ZWRGaWVsZHMiLCJkYXRhYmFzZSIsImV4aXN0aW5nRmllbGRzIiwibmFtZSIsImZpZWxkIiwiX19vcCIsIm5ld1NjaGVtYSIsImJ1aWxkTWVyZ2VkU2NoZW1hT2JqZWN0IiwiZGVmYXVsdEZpZWxkcyIsImZ1bGxOZXdTY2hlbWEiLCJhc3NpZ24iLCJ2YWxpZGF0ZVNjaGVtYURhdGEiLCJkZWxldGVkRmllbGRzIiwiaW5zZXJ0ZWRGaWVsZHMiLCJwdXNoIiwiZGVsZXRlUHJvbWlzZSIsImRlbGV0ZUZpZWxkcyIsInByb21pc2VzIiwiZW5mb3JjZUZpZWxkRXhpc3RzIiwiYWxsIiwic2V0UGVybWlzc2lvbnMiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInJlbG9hZGVkU2NoZW1hIiwiZW5mb3JjZUNsYXNzRXhpc3RzIiwiZXhpc3RpbmdGaWVsZE5hbWVzIiwiSU5WQUxJRF9LRVlfTkFNRSIsIm1lc3NhZ2UiLCJnZW9Qb2ludHMiLCJmaWx0ZXIiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJzcGxpdCIsImV4cGVjdGVkVHlwZSIsImdldEV4cGVjdGVkVHlwZSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJkZWxldGVGaWVsZCIsImZpZWxkTmFtZXMiLCJzY2hlbWFGaWVsZHMiLCJhZGFwdGVyIiwiZGVsZXRlQ2xhc3MiLCJ2YWxpZGF0ZU9iamVjdCIsIm9iamVjdCIsInF1ZXJ5IiwiZ2VvY291bnQiLCJleHBlY3RlZCIsImdldFR5cGUiLCJ0aGVuVmFsaWRhdGVSZXF1aXJlZENvbHVtbnMiLCJ2YWxpZGF0ZVJlcXVpcmVkQ29sdW1ucyIsImNvbHVtbnMiLCJtaXNzaW5nQ29sdW1ucyIsImNvbHVtbiIsIm9iamVjdElkIiwidGVzdEJhc2VDTFAiLCJhY2xHcm91cCIsImNsYXNzUGVybXMiLCJzb21lIiwiYWNsIiwidmFsaWRhdGVQZXJtaXNzaW9uIiwiT0JKRUNUX05PVF9GT1VORCIsInBlcm1pc3Npb25GaWVsZCIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJoYXNDbGFzcyIsImxvYWQiLCJkYkFkYXB0ZXIiLCJwdXRSZXF1ZXN0Iiwic3lzU2NoZW1hRmllbGQiLCJfaWQiLCJvbGRGaWVsZCIsImZpZWxkSXNEZWxldGVkIiwibmV3RmllbGQiLCJzY2hlbWFQcm9taXNlIiwib2JqIiwiZ2V0T2JqZWN0VHlwZSIsIl9fdHlwZSIsImlzbyIsImxhdGl0dWRlIiwibG9uZ2l0dWRlIiwiYmFzZTY0IiwiY29vcmRpbmF0ZXMiLCJvYmplY3RzIiwib3BzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFrQkE7O0FBQ0E7Ozs7Ozs7O0FBbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTUEsUUFBUUMsUUFBUSxZQUFSLEVBQXNCRCxLQUFwQzs7O0FBV0EsTUFBTUUsaUJBQTJDQyxPQUFPQyxNQUFQLENBQWM7QUFDN0Q7QUFDQUMsWUFBVTtBQUNSLGdCQUFhLEVBQUNDLE1BQUssUUFBTixFQURMO0FBRVIsaUJBQWEsRUFBQ0EsTUFBSyxNQUFOLEVBRkw7QUFHUixpQkFBYSxFQUFDQSxNQUFLLE1BQU4sRUFITDtBQUlSLFdBQWEsRUFBQ0EsTUFBSyxLQUFOO0FBSkwsR0FGbUQ7QUFRN0Q7QUFDQUMsU0FBTztBQUNMLGdCQUFpQixFQUFDRCxNQUFLLFFBQU4sRUFEWjtBQUVMLGdCQUFpQixFQUFDQSxNQUFLLFFBQU4sRUFGWjtBQUdMLGFBQWlCLEVBQUNBLE1BQUssUUFBTixFQUhaO0FBSUwscUJBQWlCLEVBQUNBLE1BQUssU0FBTixFQUpaO0FBS0wsZ0JBQWlCLEVBQUNBLE1BQUssUUFBTjtBQUxaLEdBVHNEO0FBZ0I3RDtBQUNBRSxpQkFBZTtBQUNiLHNCQUFvQixFQUFDRixNQUFLLFFBQU4sRUFEUDtBQUViLG1CQUFvQixFQUFDQSxNQUFLLFFBQU4sRUFGUDtBQUdiLGdCQUFvQixFQUFDQSxNQUFL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QUFSLEVBQWM7QUFDWixZQUFPaUUsSUFBSWpFLElBQVg7QUFDQSxXQUFLLFdBQUw7QUFDRSxlQUFPLFFBQVA7QUFDRixXQUFLLFFBQUw7QUFDRSxlQUFPLElBQVA7QUFDRixXQUFLLEtBQUw7QUFDQSxXQUFLLFdBQUw7QUFDQSxXQUFLLFFBQUw7QUFDRSxlQUFPLE9BQVA7QUFDRixXQUFLLGFBQUw7QUFDQSxXQUFLLGdCQUFMO0FBQ0UsZUFBTztBQUNMN0gsZ0JBQU0sVUFERDtBQUVMSSx1QkFBYTBMLElBQUlRLE9BQUosQ0FBWSxDQUFaLEVBQWV6SjtBQUZ2QixTQUFQO0FBSUYsV0FBSyxPQUFMO0FBQ0UsZUFBT2tKLGNBQWNELElBQUlTLEdBQUosQ0FBUSxDQUFSLENBQWQsQ0FBUDtBQUNGO0FBQ0UsY0FBTSxvQkFBb0JULElBQUlqRSxJQUE5QjtBQWxCRjtBQW9CRDtBQUNELFNBQU8sUUFBUDtBQUNEOztRQUdDd0QsSSxHQUFBQSxJO1FBQ0F6SSxnQixHQUFBQSxnQjtRQUNBRyxnQixHQUFBQSxnQjtRQUNBRyx1QixHQUFBQSx1QjtRQUNBNkUsdUIsR0FBQUEsdUI7UUFDQWhILGEsR0FBQUEsYTtRQUNBbkIsYyxHQUFBQSxjO1FBQ0E2RCw0QixHQUFBQSw0QjtRQUNBb0Isc0IsR0FBQUEsc0I7UUFDQUssZ0IsR0FBQUEsZ0IiLCJmaWxlIjoiU2NoZW1hQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG4vLyBUaGlzIGNsYXNzIGhhbmRsZXMgc2NoZW1hIHZhbGlkYXRpb24sIHBlcnNpc3RlbmNlLCBhbmQgbW9kaWZpY2F0aW9uLlxuLy9cbi8vIEVhY2ggaW5kaXZpZHVhbCBTY2hlbWEgb2JqZWN0IHNob3VsZCBiZSBpbW11dGFibGUuIFRoZSBoZWxwZXJzIHRvXG4vLyBkbyB0aGluZ3Mgd2l0aCB0aGUgU2NoZW1hIGp1c3QgcmV0dXJuIGEgbmV3IHNjaGVtYSB3aGVuIHRoZSBzY2hlbWFcbi8vIGlzIGNoYW5nZWQuXG4vL1xuLy8gVGhlIGNhbm9uaWNhbCBwbGFjZSB0byBzdG9yZSB0aGlzIFNjaGVtYSBpcyBpbiB0aGUgZGF0YWJhc2UgaXRzZWxmLFxuLy8gaW4gYSBfU0NIRU1BIGNvbGxlY3Rpb24uIFRoaXMgaXMgbm90IHRoZSByaWdodCB3YXkgdG8gZG8gaXQgZm9yIGFuXG4vLyBvcGVuIHNvdXJjZSBmcmFtZXdvcmssIGJ1dCBpdCdzIGJhY2t3YXJkIGNvbXBhdGlibGUsIHNvIHdlJ3JlXG4vLyBrZWVwaW5nIGl0IHRoaXMgd2F5IGZvciBub3cuXG4vL1xuLy8gSW4gQVBJLWhhbmRsaW5nIGNvZGUsIHlvdSBzaG91bGQgb25seSB1c2UgdGhlIFNjaGVtYSBjbGFzcyB2aWEgdGhlXG4vLyBEYXRhYmFzZUNvbnRyb2xsZXIuIFRoaXMgd2lsbCBsZXQgdXMgcmVwbGFjZSB0aGUgc2NoZW1hIGxvZ2ljIGZvclxuLy8gZGlmZmVyZW50IGRhdGFiYXNlcy5cbi8vIFRPRE86IGhpZGUgYWxsIHNjaGVtYSBsb2dpYyBpbnNpZGUgdGhlIGRhdGFiYXNlIGFkYXB0ZXIuXG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSAgICAgZnJvbSAnLi4vQWRhcHRlcnMvU3RvcmFnZS9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgRGF0YWJhc2VDb250cm9sbGVyICAgICBmcm9tICcuL0RhdGFiYXNlQ29udHJvbGxlcic7XG5pbXBvcnQgdHlwZSB7XG4gIFNjaGVtYSxcbiAgU2NoZW1hRmllbGRzLFxuICBDbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gIFNjaGVtYUZpZWxkLFxuICBMb2FkU2NoZW1hT3B0aW9ucyxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbmNvbnN0IGRlZmF1bHRDb2x1bW5zOiB7W3N0cmluZ106IFNjaGVtYUZpZWxkc30gPSBPYmplY3QuZnJlZXplKHtcbiAgLy8gQ29udGFpbiB0aGUgZGVmYXVsdCBjb2x1bW5zIGZvciBldmVyeSBwYXJzZSBvYmplY3QgdHlwZSAoZXhjZXB0IF9Kb2luIGNvbGxlY3Rpb24pXG4gIF9EZWZhdWx0OiB7XG4gICAgXCJvYmplY3RJZFwiOiAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiY3JlYXRlZEF0XCI6IHt0eXBlOidEYXRlJ30sXG4gICAgXCJ1cGRhdGVkQXRcIjoge3R5cGU6J0RhdGUnfSxcbiAgICBcIkFDTFwiOiAgICAgICB7dHlwZTonQUNMJ30sXG4gIH0sXG4gIC8vIFRoZSBhZGRpdGlvbmFsIGRlZmF1bHQgY29sdW1ucyBmb3IgdGhlIF9Vc2VyIGNvbGxlY3Rpb24gKGluIGFkZGl0aW9uIHRvIERlZmF1bHRDb2xzKVxuICBfVXNlcjoge1xuICAgIFwidXNlcm5hbWVcIjogICAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJwYXNzd29yZFwiOiAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcImVtYWlsXCI6ICAgICAgICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiZW1haWxWZXJpZmllZFwiOiB7dHlwZTonQm9vbGVhbid9LFxuICAgIFwiYXV0aERhdGFcIjogICAgICB7dHlwZTonT2JqZWN0J31cbiAgfSxcbiAgLy8gVGhlIGFkZGl0aW9uYWwgZGVmYXVsdCBjb2x1bW5zIGZvciB0aGUgX0luc3RhbGxhdGlvbiBjb2xsZWN0aW9uIChpbiBhZGRpdGlvbiB0byBEZWZhdWx0Q29scylcbiAgX0luc3RhbGxhdGlvbjoge1xuICAgIFwiaW5zdGFsbGF0aW9uSWRcIjogICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJkZXZpY2VUb2tlblwiOiAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcImNoYW5uZWxzXCI6ICAgICAgICAge3R5cGU6J0FycmF5J30sXG4gICAgXCJkZXZpY2VUeXBlXCI6ICAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcInB1c2hUeXBlXCI6ICAgICAgICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiR0NNU2VuZGVySWRcIjogICAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJ0aW1lWm9uZVwiOiAgICAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcImxvY2FsZUlkZW50aWZpZXJcIjoge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiYmFkZ2VcIjogICAgICAgICAgICB7dHlwZTonTnVtYmVyJ30sXG4gICAgXCJhcHBWZXJzaW9uXCI6ICAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcImFwcE5hbWVcIjogICAgICAgICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiYXBwSWRlbnRpZmllclwiOiAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJwYXJzZVZlcnNpb25cIjogICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgfSxcbiAgLy8gVGhlIGFkZGl0aW9uYWwgZGVmYXVsdCBjb2x1bW5zIGZvciB0aGUgX1JvbGUgY29sbGVjdGlvbiAoaW4gYWRkaXRpb24gdG8gRGVmYXVsdENvbHMpXG4gIF9Sb2xlOiB7XG4gICAgXCJuYW1lXCI6ICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJ1c2Vyc1wiOiB7dHlwZTonUmVsYXRpb24nLCB0YXJnZXRDbGFzczonX1VzZXInfSxcbiAgICBcInJvbGVzXCI6IHt0eXBlOidSZWxhdGlvbicsIHRhcmdldENsYXNzOidfUm9sZSd9XG4gIH0sXG4gIC8vIFRoZSBhZGRpdGlvbmFsIGRlZmF1bHQgY29sdW1ucyBmb3IgdGhlIF9TZXNzaW9uIGNvbGxlY3Rpb24gKGluIGFkZGl0aW9uIHRvIERlZmF1bHRDb2xzKVxuICBfU2Vzc2lvbjoge1xuICAgIFwicmVzdHJpY3RlZFwiOiAgICAge3R5cGU6J0Jvb2xlYW4nfSxcbiAgICBcInVzZXJcIjogICAgICAgICAgIHt0eXBlOidQb2ludGVyJywgdGFyZ2V0Q2xhc3M6J19Vc2VyJ30sXG4gICAgXCJpbnN0YWxsYXRpb25JZFwiOiB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJzZXNzaW9uVG9rZW5cIjogICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJleHBpcmVzQXRcIjogICAgICB7dHlwZTonRGF0ZSd9LFxuICAgIFwiY3JlYXRlZFdpdGhcIjogICAge3R5cGU6J09iamVjdCd9XG4gIH0sXG4gIF9Qcm9kdWN0OiB7XG4gICAgXCJwcm9kdWN0SWRlbnRpZmllclwiOiAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiZG93bmxvYWRcIjogICAgICAgICAgIHt0eXBlOidGaWxlJ30sXG4gICAgXCJkb3dubG9hZE5hbWVcIjogICAgICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiaWNvblwiOiAgICAgICAgICAgICAgIHt0eXBlOidGaWxlJ30sXG4gICAgXCJvcmRlclwiOiAgICAgICAgICAgICAge3R5cGU6J051bWJlcid9LFxuICAgIFwidGl0bGVcIjogICAgICAgICAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcInN1YnRpdGxlXCI6ICAgICAgICAgICB7dHlwZTonU3RyaW5nJ30sXG4gIH0sXG4gIF9QdXNoU3RhdHVzOiB7XG4gICAgXCJwdXNoVGltZVwiOiAgICAgICAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcInNvdXJjZVwiOiAgICAgICAgICAgICAge3R5cGU6J1N0cmluZyd9LCAvLyByZXN0IG9yIHdlYnVpXG4gICAgXCJxdWVyeVwiOiAgICAgICAgICAgICAgIHt0eXBlOidTdHJpbmcnfSwgLy8gdGhlIHN0cmluZ2lmaWVkIEpTT04gcXVlcnlcbiAgICBcInBheWxvYWRcIjogICAgICAgICAgICAge3R5cGU6J1N0cmluZyd9LCAvLyB0aGUgc3RyaW5naWZpZWQgSlNPTiBwYXlsb2FkLFxuICAgIFwidGl0bGVcIjogICAgICAgICAgICAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJleHBpcnlcIjogICAgICAgICAgICAgIHt0eXBlOidOdW1iZXInfSxcbiAgICBcImV4cGlyYXRpb25faW50ZXJ2YWxcIjoge3R5cGU6J051bWJlcid9LFxuICAgIFwic3RhdHVzXCI6ICAgICAgICAgICAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJudW1TZW50XCI6ICAgICAgICAgICAgIHt0eXBlOidOdW1iZXInfSxcbiAgICBcIm51bUZhaWxlZFwiOiAgICAgICAgICAge3R5cGU6J051bWJlcid9LFxuICAgIFwicHVzaEhhc2hcIjogICAgICAgICAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJlcnJvck1lc3NhZ2VcIjogICAgICAgIHt0eXBlOidPYmplY3QnfSxcbiAgICBcInNlbnRQZXJUeXBlXCI6ICAgICAgICAge3R5cGU6J09iamVjdCd9LFxuICAgIFwiZmFpbGVkUGVyVHlwZVwiOiAgICAgICB7dHlwZTonT2JqZWN0J30sXG4gICAgXCJzZW50UGVyVVRDT2Zmc2V0XCI6ICAgIHt0eXBlOidPYmplY3QnfSxcbiAgICBcImZhaWxlZFBlclVUQ09mZnNldFwiOiAge3R5cGU6J09iamVjdCd9LFxuICAgIFwiY291bnRcIjogICAgICAgICAgICAgICB7dHlwZTonTnVtYmVyJ30gLy8gdHJhY2tzICMgb2YgYmF0Y2hlcyBxdWV1ZWQgYW5kIHBlbmRpbmdcbiAgfSxcbiAgX0pvYlN0YXR1czoge1xuICAgIFwiam9iTmFtZVwiOiAgICB7dHlwZTogJ1N0cmluZyd9LFxuICAgIFwic291cmNlXCI6ICAgICB7dHlwZTogJ1N0cmluZyd9LFxuICAgIFwic3RhdHVzXCI6ICAgICB7dHlwZTogJ1N0cmluZyd9LFxuICAgIFwibWVzc2FnZVwiOiAgICB7dHlwZTogJ1N0cmluZyd9LFxuICAgIFwicGFyYW1zXCI6ICAgICB7dHlwZTogJ09iamVjdCd9LCAvLyBwYXJhbXMgcmVjZWl2ZWQgd2hlbiBjYWxsaW5nIHRoZSBqb2JcbiAgICBcImZpbmlzaGVkQXRcIjoge3R5cGU6ICdEYXRlJ31cbiAgfSxcbiAgX0pvYlNjaGVkdWxlOiB7XG4gICAgXCJqb2JOYW1lXCI6ICAgICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiZGVzY3JpcHRpb25cIjogIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcInBhcmFtc1wiOiAgICAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJzdGFydEFmdGVyXCI6ICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwiZGF5c09mV2Vla1wiOiAgIHt0eXBlOidBcnJheSd9LFxuICAgIFwidGltZU9mRGF5XCI6ICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcImxhc3RSdW5cIjogICAgICB7dHlwZTonTnVtYmVyJ30sXG4gICAgXCJyZXBlYXRNaW51dGVzXCI6e3R5cGU6J051bWJlcid9XG4gIH0sXG4gIF9Ib29rczoge1xuICAgIFwiZnVuY3Rpb25OYW1lXCI6IHt0eXBlOidTdHJpbmcnfSxcbiAgICBcImNsYXNzTmFtZVwiOiAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJ0cmlnZ2VyTmFtZVwiOiAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwidXJsXCI6ICAgICAgICAgIHt0eXBlOidTdHJpbmcnfVxuICB9LFxuICBfR2xvYmFsQ29uZmlnOiB7XG4gICAgXCJvYmplY3RJZFwiOiB7dHlwZTogJ1N0cmluZyd9LFxuICAgIFwicGFyYW1zXCI6ICAge3R5cGU6ICdPYmplY3QnfVxuICB9LFxuICBfQXVkaWVuY2U6IHtcbiAgICBcIm9iamVjdElkXCI6ICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJuYW1lXCI6ICAgICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwicXVlcnlcIjogICAgIHt0eXBlOidTdHJpbmcnfSwgLy9zdG9yaW5nIHF1ZXJ5IGFzIEpTT04gc3RyaW5nIHRvIHByZXZlbnQgXCJOZXN0ZWQga2V5cyBzaG91bGQgbm90IGNvbnRhaW4gdGhlICckJyBvciAnLicgY2hhcmFjdGVyc1wiIGVycm9yXG4gICAgXCJsYXN0VXNlZFwiOiAge3R5cGU6J0RhdGUnfSxcbiAgICBcInRpbWVzVXNlZFwiOiB7dHlwZTonTnVtYmVyJ31cbiAgfSxcbiAgX0V4cG9ydFByb2dyZXNzOiB7XG4gICAgXCJvYmplY3RJZFwiOiAgICAgIHt0eXBlOidTdHJpbmcnfSxcbiAgICBcImlkXCI6ICAgICAgICAgICAge3R5cGU6J1N0cmluZyd9LFxuICAgIFwibWFzdGVyS2V5XCI6ICAgICB7dHlwZTonU3RyaW5nJ30sXG4gICAgXCJhcHBsaWNhdGlvbklkXCI6IHt0eXBlOidTdHJpbmcnfVxuICB9XG59KTtcblxuY29uc3QgcmVxdWlyZWRDb2x1bW5zID0gT2JqZWN0LmZyZWV6ZSh7XG4gIF9Qcm9kdWN0OiBbXCJwcm9kdWN0SWRlbnRpZmllclwiLCBcImljb25cIiwgXCJvcmRlclwiLCBcInRpdGxlXCIsIFwic3VidGl0bGVcIl0sXG4gIF9Sb2xlOiBbXCJuYW1lXCIsIFwiQUNMXCJdXG59KTtcblxuY29uc3Qgc3lzdGVtQ2xhc3NlcyA9IE9iamVjdC5mcmVlemUoWydfVXNlcicsICdfSW5zdGFsbGF0aW9uJywgJ19Sb2xlJywgJ19TZXNzaW9uJywgJ19Qcm9kdWN0JywgJ19QdXNoU3RhdHVzJywgJ19Kb2JTdGF0dXMnLCAnX0pvYlNjaGVkdWxlJywgJ19BdWRpZW5jZScsICAnX0V4cG9ydFByb2dyZXNzJyBdKTtcblxuY29uc3Qgdm9sYXRpbGVDbGFzc2VzID0gT2JqZWN0LmZyZWV6ZShbJ19Kb2JTdGF0dXMnLCAnX1B1c2hTdGF0dXMnLCAnX0hvb2tzJywgJ19HbG9iYWxDb25maWcnLCAnX0pvYlNjaGVkdWxlJywgJ19BdWRpZW5jZScsICdfRXhwb3J0UHJvZ3Jlc3MnXSk7XG5cbi8vIDEwIGFscGhhIG51bWJlcmljIGNoYXJzICsgdXBwZXJjYXNlXG5jb25zdCB1c2VySWRSZWdleCA9IC9eW2EtekEtWjAtOV17MTB9JC87XG4vLyBBbnl0aGluZyB0aGF0IHN0YXJ0IHdpdGggcm9sZVxuY29uc3Qgcm9sZVJlZ2V4ID0gL15yb2xlOi4qLztcbi8vICogcGVybWlzc2lvblxuY29uc3QgcHVibGljUmVnZXggPSAvXlxcKiQvXG5cbmNvbnN0IHJlcXVpcmVBdXRoZW50aWNhdGlvblJlZ2V4ID0gL15yZXF1aXJlc0F1dGhlbnRpY2F0aW9uJC9cblxuY29uc3QgcGVybWlzc2lvbktleVJlZ2V4ID0gT2JqZWN0LmZyZWV6ZShbdXNlcklkUmVnZXgsIHJvbGVSZWdleCwgcHVibGljUmVnZXgsIHJlcXVpcmVBdXRoZW50aWNhdGlvblJlZ2V4XSk7XG5cbmZ1bmN0aW9uIHZlcmlmeVBlcm1pc3Npb25LZXkoa2V5KSB7XG4gIGNvbnN0IHJlc3VsdCA9IHBlcm1pc3Npb25LZXlSZWdleC5yZWR1Y2UoKGlzR29vZCwgcmVnRXgpID0+IHtcbiAgICBpc0dvb2QgPSBpc0dvb2QgfHwga2V5Lm1hdGNoKHJlZ0V4KSAhPSBudWxsO1xuICAgIHJldHVybiBpc0dvb2Q7XG4gIH0sIGZhbHNlKTtcbiAgaWYgKCFyZXN1bHQpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgJyR7a2V5fScgaXMgbm90IGEgdmFsaWQga2V5IGZvciBjbGFzcyBsZXZlbCBwZXJtaXNzaW9uc2ApO1xuICB9XG59XG5cbmNvbnN0IENMUFZhbGlkS2V5cyA9IE9iamVjdC5mcmVlemUoWydmaW5kJywgJ2NvdW50JywgJ2dldCcsICdjcmVhdGUnLCAndXBkYXRlJywgJ2RlbGV0ZScsICdhZGRGaWVsZCcsICdyZWFkVXNlckZpZWxkcycsICd3cml0ZVVzZXJGaWVsZHMnXSk7XG5mdW5jdGlvbiB2YWxpZGF0ZUNMUChwZXJtczogQ2xhc3NMZXZlbFBlcm1pc3Npb25zLCBmaWVsZHM6IFNjaGVtYUZpZWxkcykge1xuICBpZiAoIXBlcm1zKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIE9iamVjdC5rZXlzKHBlcm1zKS5mb3JFYWNoKChvcGVyYXRpb24pID0+IHtcbiAgICBpZiAoQ0xQVmFsaWRLZXlzLmluZGV4T2Yob3BlcmF0aW9uKSA9PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgYCR7b3BlcmF0aW9ufSBpcyBub3QgYSB2YWxpZCBvcGVyYXRpb24gZm9yIGNsYXNzIGxldmVsIHBlcm1pc3Npb25zYCk7XG4gICAgfVxuICAgIGlmICghcGVybXNbb3BlcmF0aW9uXSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChvcGVyYXRpb24gPT09ICdyZWFkVXNlckZpZWxkcycgfHwgb3BlcmF0aW9uID09PSAnd3JpdGVVc2VyRmllbGRzJykge1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHBlcm1zW29wZXJhdGlvbl0pKSB7XG4gICAgICAgIC8vIEBmbG93LWRpc2FibGUtbmV4dFxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgJyR7cGVybXNbb3BlcmF0aW9uXX0nIGlzIG5vdCBhIHZhbGlkIHZhbHVlIGZvciBjbGFzcyBsZXZlbCBwZXJtaXNzaW9ucyAke29wZXJhdGlvbn1gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlcm1zW29wZXJhdGlvbl0uZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgICAgaWYgKCFmaWVsZHNba2V5XSB8fCBmaWVsZHNba2V5XS50eXBlICE9ICdQb2ludGVyJyB8fCBmaWVsZHNba2V5XS50YXJnZXRDbGFzcyAhPSAnX1VzZXInKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgJyR7a2V5fScgaXMgbm90IGEgdmFsaWQgY29sdW1uIGZvciBjbGFzcyBsZXZlbCBwb2ludGVyIHBlcm1pc3Npb25zICR7b3BlcmF0aW9ufWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG4gICAgT2JqZWN0LmtleXMocGVybXNbb3BlcmF0aW9uXSkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICB2ZXJpZnlQZXJtaXNzaW9uS2V5KGtleSk7XG4gICAgICAvLyBAZmxvdy1kaXNhYmxlLW5leHRcbiAgICAgIGNvbnN0IHBlcm0gPSBwZXJtc1tvcGVyYXRpb25dW2tleV07XG4gICAgICBpZiAocGVybSAhPT0gdHJ1ZSkge1xuICAgICAgICAvLyBAZmxvdy1kaXNhYmxlLW5leHRcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgYCcke3Blcm19JyBpcyBub3QgYSB2YWxpZCB2YWx1ZSBmb3IgY2xhc3MgbGV2ZWwgcGVybWlzc2lvbnMgJHtvcGVyYXRpb259OiR7a2V5fToke3Blcm19YCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuY29uc3Qgam9pbkNsYXNzUmVnZXggPSAvXl9Kb2luOltBLVphLXowLTlfXSs6W0EtWmEtejAtOV9dKy87XG5jb25zdCBjbGFzc0FuZEZpZWxkUmVnZXggPSAvXltBLVphLXpdW0EtWmEtejAtOV9dKiQvO1xuZnVuY3Rpb24gY2xhc3NOYW1lSXNWYWxpZChjbGFzc05hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAvLyBWYWxpZCBjbGFzc2VzIG11c3Q6XG4gIHJldHVybiAoXG4gICAgLy8gQmUgb25lIG9mIF9Vc2VyLCBfSW5zdGFsbGF0aW9uLCBfUm9sZSwgX1Nlc3Npb24gT1JcbiAgICBzeXN0ZW1DbGFzc2VzLmluZGV4T2YoY2xhc3NOYW1lKSA+IC0xIHx8XG4gICAgLy8gQmUgYSBqb2luIHRhYmxlIE9SXG4gICAgam9pbkNsYXNzUmVnZXgudGVzdChjbGFzc05hbWUpIHx8XG4gICAgLy8gSW5jbHVkZSBvbmx5IGFscGhhLW51bWVyaWMgYW5kIHVuZGVyc2NvcmVzLCBhbmQgbm90IHN0YXJ0IHdpdGggYW4gdW5kZXJzY29yZSBvciBudW1iZXJcbiAgICBmaWVsZE5hbWVJc1ZhbGlkKGNsYXNzTmFtZSlcbiAgKTtcbn1cblxuLy8gVmFsaWQgZmllbGRzIG11c3QgYmUgYWxwaGEtbnVtZXJpYywgYW5kIG5vdCBzdGFydCB3aXRoIGFuIHVuZGVyc2NvcmUgb3IgbnVtYmVyXG5mdW5jdGlvbiBmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBjbGFzc0FuZEZpZWxkUmVnZXgudGVzdChmaWVsZE5hbWUpO1xufVxuXG4vLyBDaGVja3MgdGhhdCBpdCdzIG5vdCB0cnlpbmcgdG8gY2xvYmJlciBvbmUgb2YgdGhlIGRlZmF1bHQgZmllbGRzIG9mIHRoZSBjbGFzcy5cbmZ1bmN0aW9uIGZpZWxkTmFtZUlzVmFsaWRGb3JDbGFzcyhmaWVsZE5hbWU6IHN0cmluZywgY2xhc3NOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0W2ZpZWxkTmFtZV0pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0gJiYgZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXVtmaWVsZE5hbWVdKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZShjbGFzc05hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiAnSW52YWxpZCBjbGFzc25hbWU6ICcgKyBjbGFzc05hbWUgKyAnLCBjbGFzc25hbWVzIGNhbiBvbmx5IGhhdmUgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMgYW5kIF8sIGFuZCBtdXN0IHN0YXJ0IHdpdGggYW4gYWxwaGEgY2hhcmFjdGVyICc7XG59XG5cbmNvbnN0IGludmFsaWRKc29uRXJyb3IgPSBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBcImludmFsaWQgSlNPTlwiKTtcbmNvbnN0IHZhbGlkTm9uUmVsYXRpb25PclBvaW50ZXJUeXBlcyA9IFtcbiAgJ051bWJlcicsXG4gICdTdHJpbmcnLFxuICAnQm9vbGVhbicsXG4gICdEYXRlJyxcbiAgJ09iamVjdCcsXG4gICdBcnJheScsXG4gICdHZW9Qb2ludCcsXG4gICdGaWxlJyxcbiAgJ0J5dGVzJyxcbiAgJ1BvbHlnb24nXG5dO1xuLy8gUmV0dXJucyBhbiBlcnJvciBzdWl0YWJsZSBmb3IgdGhyb3dpbmcgaWYgdGhlIHR5cGUgaXMgaW52YWxpZFxuY29uc3QgZmllbGRUeXBlSXNJbnZhbGlkID0gKHsgdHlwZSwgdGFyZ2V0Q2xhc3MgfSkgPT4ge1xuICBpZiAoWydQb2ludGVyJywgJ1JlbGF0aW9uJ10uaW5kZXhPZih0eXBlKSA+PSAwKSB7XG4gICAgaWYgKCF0YXJnZXRDbGFzcykge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcigxMzUsIGB0eXBlICR7dHlwZX0gbmVlZHMgYSBjbGFzcyBuYW1lYCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdGFyZ2V0Q2xhc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gaW52YWxpZEpzb25FcnJvcjtcbiAgICB9IGVsc2UgaWYgKCFjbGFzc05hbWVJc1ZhbGlkKHRhcmdldENsYXNzKSkge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsIGludmFsaWRDbGFzc05hbWVNZXNzYWdlKHRhcmdldENsYXNzKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG4gIGlmICh0eXBlb2YgdHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gaW52YWxpZEpzb25FcnJvcjtcbiAgfVxuICBpZiAodmFsaWROb25SZWxhdGlvbk9yUG9pbnRlclR5cGVzLmluZGV4T2YodHlwZSkgPCAwKSB7XG4gICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTkNPUlJFQ1RfVFlQRSwgYGludmFsaWQgZmllbGQgdHlwZTogJHt0eXBlfWApO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmNvbnN0IGNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEgPSAoc2NoZW1hOiBhbnkpID0+IHtcbiAgc2NoZW1hID0gaW5qZWN0RGVmYXVsdFNjaGVtYShzY2hlbWEpO1xuICBkZWxldGUgc2NoZW1hLmZpZWxkcy5BQ0w7XG4gIHNjaGVtYS5maWVsZHMuX3JwZXJtID0geyB0eXBlOiAnQXJyYXknIH07XG4gIHNjaGVtYS5maWVsZHMuX3dwZXJtID0geyB0eXBlOiAnQXJyYXknIH07XG5cbiAgaWYgKHNjaGVtYS5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5wYXNzd29yZDtcbiAgICBzY2hlbWEuZmllbGRzLl9oYXNoZWRfcGFzc3dvcmQgPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gIH1cblxuICByZXR1cm4gc2NoZW1hO1xufVxuXG5jb25zdCBjb252ZXJ0QWRhcHRlclNjaGVtYVRvUGFyc2VTY2hlbWEgPSAoey4uLnNjaGVtYX0pID0+IHtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3JwZXJtO1xuICBkZWxldGUgc2NoZW1hLmZpZWxkcy5fd3Blcm07XG5cbiAgc2NoZW1hLmZpZWxkcy5BQ0wgPSB7IHR5cGU6ICdBQ0wnIH07XG5cbiAgaWYgKHNjaGVtYS5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5hdXRoRGF0YTsgLy9BdXRoIGRhdGEgaXMgaW1wbGljaXRcbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkO1xuICAgIHNjaGVtYS5maWVsZHMucGFzc3dvcmQgPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gIH1cblxuICBpZiAoc2NoZW1hLmluZGV4ZXMgJiYgT2JqZWN0LmtleXMoc2NoZW1hLmluZGV4ZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgIGRlbGV0ZSBzY2hlbWEuaW5kZXhlcztcbiAgfVxuXG4gIHJldHVybiBzY2hlbWE7XG59XG5cbmNvbnN0IGluamVjdERlZmF1bHRTY2hlbWEgPSAoe2NsYXNzTmFtZSwgZmllbGRzLCBjbGFzc0xldmVsUGVybWlzc2lvbnMsIGluZGV4ZXN9OiBTY2hlbWEpID0+IHtcbiAgY29uc3QgZGVmYXVsdFNjaGVtYTogU2NoZW1hID0ge1xuICAgIGNsYXNzTmFtZSxcbiAgICBmaWVsZHM6IHtcbiAgICAgIC4uLmRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0LFxuICAgICAgLi4uKGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0gfHwge30pLFxuICAgICAgLi4uZmllbGRzLFxuICAgIH0sXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICB9O1xuICBpZiAoaW5kZXhlcyAmJiBPYmplY3Qua2V5cyhpbmRleGVzKS5sZW5ndGggIT09IDApIHtcbiAgICBkZWZhdWx0U2NoZW1hLmluZGV4ZXMgPSBpbmRleGVzO1xuICB9XG4gIHJldHVybiBkZWZhdWx0U2NoZW1hO1xufTtcblxuY29uc3QgX0hvb2tzU2NoZW1hID0gIHtjbGFzc05hbWU6IFwiX0hvb2tzXCIsIGZpZWxkczogZGVmYXVsdENvbHVtbnMuX0hvb2tzfTtcbmNvbnN0IF9HbG9iYWxDb25maWdTY2hlbWEgPSB7IGNsYXNzTmFtZTogXCJfR2xvYmFsQ29uZmlnXCIsIGZpZWxkczogZGVmYXVsdENvbHVtbnMuX0dsb2JhbENvbmZpZyB9XG5jb25zdCBfUHVzaFN0YXR1c1NjaGVtYSA9IGNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEoaW5qZWN0RGVmYXVsdFNjaGVtYSh7XG4gIGNsYXNzTmFtZTogXCJfUHVzaFN0YXR1c1wiLFxuICBmaWVsZHM6IHt9LFxuICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHt9XG59KSk7XG5jb25zdCBfSm9iU3RhdHVzU2NoZW1hID0gY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShpbmplY3REZWZhdWx0U2NoZW1hKHtcbiAgY2xhc3NOYW1lOiBcIl9Kb2JTdGF0dXNcIixcbiAgZmllbGRzOiB7fSxcbiAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiB7fVxufSkpO1xuY29uc3QgX0pvYlNjaGVkdWxlU2NoZW1hID0gY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYShpbmplY3REZWZhdWx0U2NoZW1hKHtcbiAgY2xhc3NOYW1lOiBcIl9Kb2JTY2hlZHVsZVwiLFxuICBmaWVsZHM6IHt9LFxuICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHt9XG59KSk7XG5jb25zdCBfQXVkaWVuY2VTY2hlbWEgPSBjb252ZXJ0U2NoZW1hVG9BZGFwdGVyU2NoZW1hKGluamVjdERlZmF1bHRTY2hlbWEoe1xuICBjbGFzc05hbWU6IFwiX0F1ZGllbmNlXCIsXG4gIGZpZWxkczogZGVmYXVsdENvbHVtbnMuX0F1ZGllbmNlLFxuICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IHt9XG59KSk7XG5jb25zdCBWb2xhdGlsZUNsYXNzZXNTY2hlbWFzID0gW19Ib29rc1NjaGVtYSwgX0pvYlN0YXR1c1NjaGVtYSwgX0pvYlNjaGVkdWxlU2NoZW1hLCBfUHVzaFN0YXR1c1NjaGVtYSwgX0dsb2JhbENvbmZpZ1NjaGVtYSwgX0F1ZGllbmNlU2NoZW1hXTtcblxuY29uc3QgZGJUeXBlTWF0Y2hlc09iamVjdFR5cGUgPSAoZGJUeXBlOiBTY2hlbWFGaWVsZCB8IHN0cmluZywgb2JqZWN0VHlwZTogU2NoZW1hRmllbGQpID0+IHtcbiAgaWYgKGRiVHlwZS50eXBlICE9PSBvYmplY3RUeXBlLnR5cGUpIHJldHVybiBmYWxzZTtcbiAgaWYgKGRiVHlwZS50YXJnZXRDbGFzcyAhPT0gb2JqZWN0VHlwZS50YXJnZXRDbGFzcykgcmV0dXJuIGZhbHNlO1xuICBpZiAoZGJUeXBlID09PSBvYmplY3RUeXBlLnR5cGUpIHJldHVybiB0cnVlO1xuICBpZiAoZGJUeXBlLnR5cGUgPT09IG9iamVjdFR5cGUudHlwZSkgcmV0dXJuIHRydWU7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuY29uc3QgdHlwZVRvU3RyaW5nID0gKHR5cGU6IFNjaGVtYUZpZWxkIHwgc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiB0eXBlO1xuICB9XG4gIGlmICh0eXBlLnRhcmdldENsYXNzKSB7XG4gICAgcmV0dXJuIGAke3R5cGUudHlwZX08JHt0eXBlLnRhcmdldENsYXNzfT5gO1xuICB9XG4gIHJldHVybiBgJHt0eXBlLnR5cGV9YDtcbn1cblxuLy8gU3RvcmVzIHRoZSBlbnRpcmUgc2NoZW1hIG9mIHRoZSBhcHAgaW4gYSB3ZWlyZCBoeWJyaWQgZm9ybWF0IHNvbWV3aGVyZSBiZXR3ZWVuXG4vLyB0aGUgbW9uZ28gZm9ybWF0IGFuZCB0aGUgUGFyc2UgZm9ybWF0LiBTb29uLCB0aGlzIHdpbGwgYWxsIGJlIFBhcnNlIGZvcm1hdC5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjaGVtYUNvbnRyb2xsZXIge1xuICBfZGJBZGFwdGVyOiBTdG9yYWdlQWRhcHRlcjtcbiAgZGF0YTogYW55O1xuICBwZXJtczogYW55O1xuICBpbmRleGVzOiBhbnk7XG4gIF9jYWNoZTogYW55O1xuICByZWxvYWREYXRhUHJvbWlzZTogUHJvbWlzZTxhbnk+O1xuXG4gIGNvbnN0cnVjdG9yKGRhdGFiYXNlQWRhcHRlcjogU3RvcmFnZUFkYXB0ZXIsIHNjaGVtYUNhY2hlOiBhbnkpIHtcbiAgICB0aGlzLl9kYkFkYXB0ZXIgPSBkYXRhYmFzZUFkYXB0ZXI7XG4gICAgdGhpcy5fY2FjaGUgPSBzY2hlbWFDYWNoZTtcbiAgICAvLyB0aGlzLmRhdGFbY2xhc3NOYW1lXVtmaWVsZE5hbWVdIHRlbGxzIHlvdSB0aGUgdHlwZSBvZiB0aGF0IGZpZWxkLCBpbiBtb25nbyBmb3JtYXRcbiAgICB0aGlzLmRhdGEgPSB7fTtcbiAgICAvLyB0aGlzLnBlcm1zW2NsYXNzTmFtZV1bb3BlcmF0aW9uXSB0ZWxscyB5b3UgdGhlIGFjbC1zdHlsZSBwZXJtaXNzaW9uc1xuICAgIHRoaXMucGVybXMgPSB7fTtcbiAgICAvLyB0aGlzLmluZGV4ZXNbY2xhc3NOYW1lXVtvcGVyYXRpb25dIHRlbGxzIHlvdSB0aGUgaW5kZXhlc1xuICAgIHRoaXMuaW5kZXhlcyA9IHt9O1xuICB9XG5cbiAgcmVsb2FkRGF0YShvcHRpb25zOiBMb2FkU2NoZW1hT3B0aW9ucyA9IHtjbGVhckNhY2hlOiBmYWxzZX0pOiBQcm9taXNlPGFueT4ge1xuICAgIGxldCBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgaWYgKG9wdGlvbnMuY2xlYXJDYWNoZSkge1xuICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5jbGVhcigpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnJlbG9hZERhdGFQcm9taXNlICYmICFvcHRpb25zLmNsZWFyQ2FjaGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlbG9hZERhdGFQcm9taXNlO1xuICAgIH1cbiAgICB0aGlzLnJlbG9hZERhdGFQcm9taXNlID0gcHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmdldEFsbENsYXNzZXMob3B0aW9ucykudGhlbigoYWxsU2NoZW1hcykgPT4ge1xuICAgICAgICBjb25zdCBkYXRhID0ge307XG4gICAgICAgIGNvbnN0IHBlcm1zID0ge307XG4gICAgICAgIGNvbnN0IGluZGV4ZXMgPSB7fTtcbiAgICAgICAgYWxsU2NoZW1hcy5mb3JFYWNoKHNjaGVtYSA9PiB7XG4gICAgICAgICAgZGF0YVtzY2hlbWEuY2xhc3NOYW1lXSA9IGluamVjdERlZmF1bHRTY2hlbWEoc2NoZW1hKS5maWVsZHM7XG4gICAgICAgICAgcGVybXNbc2NoZW1hLmNsYXNzTmFtZV0gPSBzY2hlbWEuY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgICAgICAgIGluZGV4ZXNbc2NoZW1hLmNsYXNzTmFtZV0gPSBzY2hlbWEuaW5kZXhlcztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gSW5qZWN0IHRoZSBpbi1tZW1vcnkgY2xhc3Nlc1xuICAgICAgICB2b2xhdGlsZUNsYXNzZXMuZm9yRWFjaChjbGFzc05hbWUgPT4ge1xuICAgICAgICAgIGNvbnN0IHNjaGVtYSA9IGluamVjdERlZmF1bHRTY2hlbWEoeyBjbGFzc05hbWUsIGZpZWxkczoge30sIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczoge30gfSk7XG4gICAgICAgICAgZGF0YVtjbGFzc05hbWVdID0gc2NoZW1hLmZpZWxkcztcbiAgICAgICAgICBwZXJtc1tjbGFzc05hbWVdID0gc2NoZW1hLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucztcbiAgICAgICAgICBpbmRleGVzW2NsYXNzTmFtZV0gPSBzY2hlbWEuaW5kZXhlcztcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgICAgIHRoaXMucGVybXMgPSBwZXJtcztcbiAgICAgICAgdGhpcy5pbmRleGVzID0gaW5kZXhlcztcbiAgICAgICAgZGVsZXRlIHRoaXMucmVsb2FkRGF0YVByb21pc2U7XG4gICAgICB9LCAoZXJyKSA9PiB7XG4gICAgICAgIHRoaXMuZGF0YSA9IHt9O1xuICAgICAgICB0aGlzLnBlcm1zID0ge307XG4gICAgICAgIHRoaXMuaW5kZXhlcyA9IHt9O1xuICAgICAgICBkZWxldGUgdGhpcy5yZWxvYWREYXRhUHJvbWlzZTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfSlcbiAgICB9KS50aGVuKCgpID0+IHt9KTtcbiAgICByZXR1cm4gdGhpcy5yZWxvYWREYXRhUHJvbWlzZTtcbiAgfVxuXG4gIGdldEFsbENsYXNzZXMob3B0aW9uczogTG9hZFNjaGVtYU9wdGlvbnMgPSB7Y2xlYXJDYWNoZTogZmFsc2V9KTogUHJvbWlzZTxBcnJheTxTY2hlbWE+PiB7XG4gICAgbGV0IHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBpZiAob3B0aW9ucy5jbGVhckNhY2hlKSB7XG4gICAgICBwcm9taXNlID0gdGhpcy5fY2FjaGUuY2xlYXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5fY2FjaGUuZ2V0QWxsQ2xhc3NlcygpXG4gICAgfSkudGhlbigoYWxsQ2xhc3NlcykgPT4ge1xuICAgICAgaWYgKGFsbENsYXNzZXMgJiYgYWxsQ2xhc3Nlcy5sZW5ndGggJiYgIW9wdGlvbnMuY2xlYXJDYWNoZSkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGFsbENsYXNzZXMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuX2RiQWRhcHRlci5nZXRBbGxDbGFzc2VzKClcbiAgICAgICAgLnRoZW4oYWxsU2NoZW1hcyA9PiBhbGxTY2hlbWFzLm1hcChpbmplY3REZWZhdWx0U2NoZW1hKSlcbiAgICAgICAgLnRoZW4oYWxsU2NoZW1hcyA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlLnNldEFsbENsYXNzZXMoYWxsU2NoZW1hcykudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYWxsU2NoZW1hcztcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSlcbiAgICB9KTtcbiAgfVxuXG4gIGdldE9uZVNjaGVtYShjbGFzc05hbWU6IHN0cmluZywgYWxsb3dWb2xhdGlsZUNsYXNzZXM6IGJvb2xlYW4gPSBmYWxzZSwgb3B0aW9uczogTG9hZFNjaGVtYU9wdGlvbnMgPSB7Y2xlYXJDYWNoZTogZmFsc2V9KTogUHJvbWlzZTxTY2hlbWE+IHtcbiAgICBsZXQgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIGlmIChvcHRpb25zLmNsZWFyQ2FjaGUpIHtcbiAgICAgIHByb21pc2UgPSB0aGlzLl9jYWNoZS5jbGVhcigpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChhbGxvd1ZvbGF0aWxlQ2xhc3NlcyAmJiB2b2xhdGlsZUNsYXNzZXMuaW5kZXhPZihjbGFzc05hbWUpID4gLTEpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgIGZpZWxkczogdGhpcy5kYXRhW2NsYXNzTmFtZV0sXG4gICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiB0aGlzLnBlcm1zW2NsYXNzTmFtZV0sXG4gICAgICAgICAgaW5kZXhlczogdGhpcy5pbmRleGVzW2NsYXNzTmFtZV1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fY2FjaGUuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSkudGhlbigoY2FjaGVkKSA9PiB7XG4gICAgICAgIGlmIChjYWNoZWQgJiYgIW9wdGlvbnMuY2xlYXJDYWNoZSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoY2FjaGVkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fZGJBZGFwdGVyLmdldENsYXNzKGNsYXNzTmFtZSlcbiAgICAgICAgICAudGhlbihpbmplY3REZWZhdWx0U2NoZW1hKVxuICAgICAgICAgIC50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5zZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCByZXN1bHQpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gQ3JlYXRlIGEgbmV3IGNsYXNzIHRoYXQgaW5jbHVkZXMgdGhlIHRocmVlIGRlZmF1bHQgZmllbGRzLlxuICAvLyBBQ0wgaXMgYW4gaW1wbGljaXQgY29sdW1uIHRoYXQgZG9lcyBub3QgZ2V0IGFuIGVudHJ5IGluIHRoZVxuICAvLyBfU0NIRU1BUyBkYXRhYmFzZS4gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZVxuICAvLyBjcmVhdGVkIHNjaGVtYSwgaW4gbW9uZ28gZm9ybWF0LlxuICAvLyBvbiBzdWNjZXNzLCBhbmQgcmVqZWN0cyB3aXRoIGFuIGVycm9yIG9uIGZhaWwuIEVuc3VyZSB5b3VcbiAgLy8gaGF2ZSBhdXRob3JpemF0aW9uIChtYXN0ZXIga2V5LCBvciBjbGllbnQgY2xhc3MgY3JlYXRpb25cbiAgLy8gZW5hYmxlZCkgYmVmb3JlIGNhbGxpbmcgdGhpcyBmdW5jdGlvbi5cbiAgYWRkQ2xhc3NJZk5vdEV4aXN0cyhjbGFzc05hbWU6IHN0cmluZywgZmllbGRzOiBTY2hlbWFGaWVsZHMgPSB7fSwgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBhbnksIGluZGV4ZXM6IGFueSA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdmFyIHZhbGlkYXRpb25FcnJvciA9IHRoaXMudmFsaWRhdGVOZXdDbGFzcyhjbGFzc05hbWUsIGZpZWxkcywgY2xhc3NMZXZlbFBlcm1pc3Npb25zKTtcbiAgICBpZiAodmFsaWRhdGlvbkVycm9yKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QodmFsaWRhdGlvbkVycm9yKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fZGJBZGFwdGVyLmNyZWF0ZUNsYXNzKGNsYXNzTmFtZSwgY29udmVydFNjaGVtYVRvQWRhcHRlclNjaGVtYSh7IGZpZWxkcywgY2xhc3NMZXZlbFBlcm1pc3Npb25zLCBpbmRleGVzLCBjbGFzc05hbWUgfSkpXG4gICAgICAudGhlbihjb252ZXJ0QWRhcHRlclNjaGVtYVRvUGFyc2VTY2hlbWEpXG4gICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5jbGVhcigpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzKTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yICYmIGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsIGBDbGFzcyAke2NsYXNzTmFtZX0gYWxyZWFkeSBleGlzdHMuYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHN1Ym1pdHRlZEZpZWxkczogU2NoZW1hRmllbGRzLCBjbGFzc0xldmVsUGVybWlzc2lvbnM6IGFueSwgaW5kZXhlczogYW55LCBkYXRhYmFzZTogRGF0YWJhc2VDb250cm9sbGVyKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0T25lU2NoZW1hKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKHNjaGVtYSA9PiB7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nRmllbGRzID0gc2NoZW1hLmZpZWxkcztcbiAgICAgICAgT2JqZWN0LmtleXMoc3VibWl0dGVkRmllbGRzKS5mb3JFYWNoKG5hbWUgPT4ge1xuICAgICAgICAgIGNvbnN0IGZpZWxkID0gc3VibWl0dGVkRmllbGRzW25hbWVdO1xuICAgICAgICAgIGlmIChleGlzdGluZ0ZpZWxkc1tuYW1lXSAmJiBmaWVsZC5fX29wICE9PSAnRGVsZXRlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDI1NSwgYEZpZWxkICR7bmFtZX0gZXhpc3RzLCBjYW5ub3QgdXBkYXRlLmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIWV4aXN0aW5nRmllbGRzW25hbWVdICYmIGZpZWxkLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMjU1LCBgRmllbGQgJHtuYW1lfSBkb2VzIG5vdCBleGlzdCwgY2Fubm90IGRlbGV0ZS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0ZpZWxkcy5fcnBlcm07XG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0ZpZWxkcy5fd3Blcm07XG4gICAgICAgIGNvbnN0IG5ld1NjaGVtYSA9IGJ1aWxkTWVyZ2VkU2NoZW1hT2JqZWN0KGV4aXN0aW5nRmllbGRzLCBzdWJtaXR0ZWRGaWVsZHMpO1xuICAgICAgICBjb25zdCBkZWZhdWx0RmllbGRzID0gZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXSB8fCBkZWZhdWx0Q29sdW1ucy5fRGVmYXVsdDtcbiAgICAgICAgY29uc3QgZnVsbE5ld1NjaGVtYSA9IE9iamVjdC5hc3NpZ24oe30sIG5ld1NjaGVtYSwgZGVmYXVsdEZpZWxkcyk7XG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25FcnJvciA9IHRoaXMudmFsaWRhdGVTY2hlbWFEYXRhKGNsYXNzTmFtZSwgbmV3U2NoZW1hLCBjbGFzc0xldmVsUGVybWlzc2lvbnMsIE9iamVjdC5rZXlzKGV4aXN0aW5nRmllbGRzKSk7XG4gICAgICAgIGlmICh2YWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IodmFsaWRhdGlvbkVycm9yLmNvZGUsIHZhbGlkYXRpb25FcnJvci5lcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaW5hbGx5IHdlIGhhdmUgY2hlY2tlZCB0byBtYWtlIHN1cmUgdGhlIHJlcXVlc3QgaXMgdmFsaWQgYW5kIHdlIGNhbiBzdGFydCBkZWxldGluZyBmaWVsZHMuXG4gICAgICAgIC8vIERvIGFsbCBkZWxldGlvbnMgZmlyc3QsIHRoZW4gYSBzaW5nbGUgc2F2ZSB0byBfU0NIRU1BIGNvbGxlY3Rpb24gdG8gaGFuZGxlIGFsbCBhZGRpdGlvbnMuXG4gICAgICAgIGNvbnN0IGRlbGV0ZWRGaWVsZHM6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGNvbnN0IGluc2VydGVkRmllbGRzID0gW107XG4gICAgICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEZpZWxkcykuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgIGlmIChzdWJtaXR0ZWRGaWVsZHNbZmllbGROYW1lXS5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICAgICAgZGVsZXRlZEZpZWxkcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGluc2VydGVkRmllbGRzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCBkZWxldGVQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIGlmIChkZWxldGVkRmllbGRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBkZWxldGVQcm9taXNlID0gdGhpcy5kZWxldGVGaWVsZHMoZGVsZXRlZEZpZWxkcywgY2xhc3NOYW1lLCBkYXRhYmFzZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRlbGV0ZVByb21pc2UgLy8gRGVsZXRlIEV2ZXJ5dGhpbmdcbiAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLnJlbG9hZERhdGEoeyBjbGVhckNhY2hlOiB0cnVlIH0pKSAvLyBSZWxvYWQgb3VyIFNjaGVtYSwgc28gd2UgaGF2ZSBhbGwgdGhlIG5ldyB2YWx1ZXNcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IGluc2VydGVkRmllbGRzLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgICBjb25zdCB0eXBlID0gc3VibWl0dGVkRmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLmVuZm9yY2VGaWVsZEV4aXN0cyhjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLnNldFBlcm1pc3Npb25zKGNsYXNzTmFtZSwgY2xhc3NMZXZlbFBlcm1pc3Npb25zLCBuZXdTY2hlbWEpKVxuICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuX2RiQWRhcHRlci5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWUsIGluZGV4ZXMsIHNjaGVtYS5pbmRleGVzLCBmdWxsTmV3U2NoZW1hKSlcbiAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLnJlbG9hZERhdGEoeyBjbGVhckNhY2hlOiB0cnVlIH0pKVxuICAgICAgICAvL1RPRE86IE1vdmUgdGhpcyBsb2dpYyBpbnRvIHRoZSBkYXRhYmFzZSBhZGFwdGVyXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVsb2FkZWRTY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIGZpZWxkczogdGhpcy5kYXRhW2NsYXNzTmFtZV0sXG4gICAgICAgICAgICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9uczogdGhpcy5wZXJtc1tjbGFzc05hbWVdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICh0aGlzLmluZGV4ZXNbY2xhc3NOYW1lXSAmJiBPYmplY3Qua2V5cyh0aGlzLmluZGV4ZXNbY2xhc3NOYW1lXSkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgIHJlbG9hZGVkU2NoZW1hLmluZGV4ZXMgPSB0aGlzLmluZGV4ZXNbY2xhc3NOYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZWxvYWRlZFNjaGVtYTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsIGBDbGFzcyAke2NsYXNzTmFtZX0gZG9lcyBub3QgZXhpc3QuYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSB0byB0aGUgbmV3IHNjaGVtYVxuICAvLyBvYmplY3Qgb3IgZmFpbHMgd2l0aCBhIHJlYXNvbi5cbiAgZW5mb3JjZUNsYXNzRXhpc3RzKGNsYXNzTmFtZTogc3RyaW5nKTogUHJvbWlzZTxTY2hlbWFDb250cm9sbGVyPiB7XG4gICAgaWYgKHRoaXMuZGF0YVtjbGFzc05hbWVdKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuICAgIH1cbiAgICAvLyBXZSBkb24ndCBoYXZlIHRoaXMgY2xhc3MuIFVwZGF0ZSB0aGUgc2NoZW1hXG4gICAgcmV0dXJuIHRoaXMuYWRkQ2xhc3NJZk5vdEV4aXN0cyhjbGFzc05hbWUpXG4gICAgLy8gVGhlIHNjaGVtYSB1cGRhdGUgc3VjY2VlZGVkLiBSZWxvYWQgdGhlIHNjaGVtYVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5yZWxvYWREYXRhKHsgY2xlYXJDYWNoZTogdHJ1ZSB9KSlcbiAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAvLyBUaGUgc2NoZW1hIHVwZGF0ZSBmYWlsZWQuIFRoaXMgY2FuIGJlIG9rYXkgLSBpdCBtaWdodFxuICAgICAgLy8gaGF2ZSBmYWlsZWQgYmVjYXVzZSB0aGVyZSdzIGEgcmFjZSBjb25kaXRpb24gYW5kIGEgZGlmZmVyZW50XG4gICAgICAvLyBjbGllbnQgaXMgbWFraW5nIHRoZSBleGFjdCBzYW1lIHNjaGVtYSB1cGRhdGUgdGhhdCB3ZSB3YW50LlxuICAgICAgLy8gU28ganVzdCByZWxvYWQgdGhlIHNjaGVtYS5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVsb2FkRGF0YSh7IGNsZWFyQ2FjaGU6IHRydWUgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gRW5zdXJlIHRoYXQgdGhlIHNjaGVtYSBub3cgdmFsaWRhdGVzXG4gICAgICAgIGlmICh0aGlzLmRhdGFbY2xhc3NOYW1lXSkge1xuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sIGBGYWlsZWQgdG8gYWRkICR7Y2xhc3NOYW1lfWApO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgIC8vIFRoZSBzY2hlbWEgc3RpbGwgZG9lc24ndCB2YWxpZGF0ZS4gR2l2ZSB1cFxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnc2NoZW1hIGNsYXNzIG5hbWUgZG9lcyBub3QgcmV2YWxpZGF0ZScpO1xuICAgICAgfSk7XG4gIH1cblxuICB2YWxpZGF0ZU5ld0NsYXNzKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZHM6IFNjaGVtYUZpZWxkcyA9IHt9LCBjbGFzc0xldmVsUGVybWlzc2lvbnM6IGFueSk6IGFueSB7XG4gICAgaWYgKHRoaXMuZGF0YVtjbGFzc05hbWVdKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLCBgQ2xhc3MgJHtjbGFzc05hbWV9IGFscmVhZHkgZXhpc3RzLmApO1xuICAgIH1cbiAgICBpZiAoIWNsYXNzTmFtZUlzVmFsaWQoY2xhc3NOYW1lKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29kZTogUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLFxuICAgICAgICBlcnJvcjogaW52YWxpZENsYXNzTmFtZU1lc3NhZ2UoY2xhc3NOYW1lKSxcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnZhbGlkYXRlU2NoZW1hRGF0YShjbGFzc05hbWUsIGZpZWxkcywgY2xhc3NMZXZlbFBlcm1pc3Npb25zLCBbXSk7XG4gIH1cblxuICB2YWxpZGF0ZVNjaGVtYURhdGEoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkczogU2NoZW1hRmllbGRzLCBjbGFzc0xldmVsUGVybWlzc2lvbnM6IENsYXNzTGV2ZWxQZXJtaXNzaW9ucywgZXhpc3RpbmdGaWVsZE5hbWVzOiBBcnJheTxzdHJpbmc+KSB7XG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gZmllbGRzKSB7XG4gICAgICBpZiAoZXhpc3RpbmdGaWVsZE5hbWVzLmluZGV4T2YoZmllbGROYW1lKSA8IDApIHtcbiAgICAgICAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZSkpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29kZTogUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSxcbiAgICAgICAgICAgIGVycm9yOiAnaW52YWxpZCBmaWVsZCBuYW1lOiAnICsgZmllbGROYW1lLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkRm9yQ2xhc3MoZmllbGROYW1lLCBjbGFzc05hbWUpKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvZGU6IDEzNixcbiAgICAgICAgICAgIGVycm9yOiAnZmllbGQgJyArIGZpZWxkTmFtZSArICcgY2Fubm90IGJlIGFkZGVkJyxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGVycm9yID0gZmllbGRUeXBlSXNJbnZhbGlkKGZpZWxkc1tmaWVsZE5hbWVdKTtcbiAgICAgICAgaWYgKGVycm9yKSByZXR1cm4geyBjb2RlOiBlcnJvci5jb2RlLCBlcnJvcjogZXJyb3IubWVzc2FnZSB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZmllbGROYW1lIGluIGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0pIHtcbiAgICAgIGZpZWxkc1tmaWVsZE5hbWVdID0gZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXVtmaWVsZE5hbWVdO1xuICAgIH1cblxuICAgIGNvbnN0IGdlb1BvaW50cyA9IE9iamVjdC5rZXlzKGZpZWxkcykuZmlsdGVyKGtleSA9PiBmaWVsZHNba2V5XSAmJiBmaWVsZHNba2V5XS50eXBlID09PSAnR2VvUG9pbnQnKTtcbiAgICBpZiAoZ2VvUG9pbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLklOQ09SUkVDVF9UWVBFLFxuICAgICAgICBlcnJvcjogJ2N1cnJlbnRseSwgb25seSBvbmUgR2VvUG9pbnQgZmllbGQgbWF5IGV4aXN0IGluIGFuIG9iamVjdC4gQWRkaW5nICcgKyBnZW9Qb2ludHNbMV0gKyAnIHdoZW4gJyArIGdlb1BvaW50c1swXSArICcgYWxyZWFkeSBleGlzdHMuJyxcbiAgICAgIH07XG4gICAgfVxuICAgIHZhbGlkYXRlQ0xQKGNsYXNzTGV2ZWxQZXJtaXNzaW9ucywgZmllbGRzKTtcbiAgfVxuXG4gIC8vIFNldHMgdGhlIENsYXNzLWxldmVsIHBlcm1pc3Npb25zIGZvciBhIGdpdmVuIGNsYXNzTmFtZSwgd2hpY2ggbXVzdCBleGlzdC5cbiAgc2V0UGVybWlzc2lvbnMoY2xhc3NOYW1lOiBzdHJpbmcsIHBlcm1zOiBhbnksIG5ld1NjaGVtYTogU2NoZW1hRmllbGRzKSB7XG4gICAgaWYgKHR5cGVvZiBwZXJtcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgdmFsaWRhdGVDTFAocGVybXMsIG5ld1NjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2RiQWRhcHRlci5zZXRDbGFzc0xldmVsUGVybWlzc2lvbnMoY2xhc3NOYW1lLCBwZXJtcyk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHN1Y2Nlc3NmdWxseSB0byB0aGUgbmV3IHNjaGVtYVxuICAvLyBvYmplY3QgaWYgdGhlIHByb3ZpZGVkIGNsYXNzTmFtZS1maWVsZE5hbWUtdHlwZSB0dXBsZSBpcyB2YWxpZC5cbiAgLy8gVGhlIGNsYXNzTmFtZSBtdXN0IGFscmVhZHkgYmUgdmFsaWRhdGVkLlxuICAvLyBJZiAnZnJlZXplJyBpcyB0cnVlLCByZWZ1c2UgdG8gdXBkYXRlIHRoZSBzY2hlbWEgZm9yIHRoaXMgZmllbGQuXG4gIGVuZm9yY2VGaWVsZEV4aXN0cyhjbGFzc05hbWU6IHN0cmluZywgZmllbGROYW1lOiBzdHJpbmcsIHR5cGU6IHN0cmluZyB8IFNjaGVtYUZpZWxkKSB7XG4gICAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKFwiLlwiKSA+IDApIHtcbiAgICAgIC8vIHN1YmRvY3VtZW50IGtleSAoeC55KSA9PiBvayBpZiB4IGlzIG9mIHR5cGUgJ29iamVjdCdcbiAgICAgIGZpZWxkTmFtZSA9IGZpZWxkTmFtZS5zcGxpdChcIi5cIilbIDAgXTtcbiAgICAgIHR5cGUgPSAnT2JqZWN0JztcbiAgICB9XG4gICAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkKGZpZWxkTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLCBgSW52YWxpZCBmaWVsZCBuYW1lOiAke2ZpZWxkTmFtZX0uYCk7XG4gICAgfVxuXG4gICAgLy8gSWYgc29tZW9uZSB0cmllcyB0byBjcmVhdGUgYSBuZXcgZmllbGQgd2l0aCBudWxsL3VuZGVmaW5lZCBhcyB0aGUgdmFsdWUsIHJldHVybjtcbiAgICBpZiAoIXR5cGUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVsb2FkRGF0YSgpLnRoZW4oKCkgPT4ge1xuICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gdGhpcy5nZXRFeHBlY3RlZFR5cGUoY2xhc3NOYW1lLCBmaWVsZE5hbWUpO1xuICAgICAgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICB0eXBlID0geyB0eXBlIH07XG4gICAgICB9XG5cbiAgICAgIGlmIChleHBlY3RlZFR5cGUpIHtcbiAgICAgICAgaWYgKCFkYlR5cGVNYXRjaGVzT2JqZWN0VHlwZShleHBlY3RlZFR5cGUsIHR5cGUpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgICAgICBgc2NoZW1hIG1pc21hdGNoIGZvciAke2NsYXNzTmFtZX0uJHtmaWVsZE5hbWV9OyBleHBlY3RlZCAke3R5cGVUb1N0cmluZyhleHBlY3RlZFR5cGUpfSBidXQgZ290ICR7dHlwZVRvU3RyaW5nKHR5cGUpfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5fZGJBZGFwdGVyLmFkZEZpZWxkSWZOb3RFeGlzdHMoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHR5cGUpLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBUaGUgdXBkYXRlIHN1Y2NlZWRlZC4gUmVsb2FkIHRoZSBzY2hlbWFcbiAgICAgICAgcmV0dXJuIHRoaXMucmVsb2FkRGF0YSh7IGNsZWFyQ2FjaGU6IHRydWUgfSk7XG4gICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT0gUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUpIHtcbiAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhhdCB3ZSB0aHJvdyBlcnJvcnMgd2hlbiBpdCBpcyBhcHByb3ByaWF0ZSB0byBkbyBzby5cbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgdXBkYXRlIGZhaWxlZC4gVGhpcyBjYW4gYmUgb2theSAtIGl0IG1pZ2h0IGhhdmUgYmVlbiBhIHJhY2VcbiAgICAgICAgLy8gY29uZGl0aW9uIHdoZXJlIGFub3RoZXIgY2xpZW50IHVwZGF0ZWQgdGhlIHNjaGVtYSBpbiB0aGUgc2FtZVxuICAgICAgICAvLyB3YXkgdGhhdCB3ZSB3YW50ZWQgdG8uIFNvLCBqdXN0IHJlbG9hZCB0aGUgc2NoZW1hXG4gICAgICAgIHJldHVybiB0aGlzLnJlbG9hZERhdGEoeyBjbGVhckNhY2hlOiB0cnVlIH0pO1xuICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgIC8vIEVuc3VyZSB0aGF0IHRoZSBzY2hlbWEgbm93IHZhbGlkYXRlc1xuICAgICAgICBjb25zdCBleHBlY3RlZFR5cGUgPSB0aGlzLmdldEV4cGVjdGVkVHlwZShjbGFzc05hbWUsIGZpZWxkTmFtZSk7XG4gICAgICAgIGlmICh0eXBlb2YgdHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0eXBlID0geyB0eXBlIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFleHBlY3RlZFR5cGUgfHwgIWRiVHlwZU1hdGNoZXNPYmplY3RUeXBlKGV4cGVjdGVkVHlwZSwgdHlwZSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgQ291bGQgbm90IGFkZCBmaWVsZCAke2ZpZWxkTmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZW1vdmUgdGhlIGNhY2hlZCBzY2hlbWFcbiAgICAgICAgdGhpcy5fY2FjaGUuY2xlYXIoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIG1haW50YWluIGNvbXBhdGliaWxpdHlcbiAgZGVsZXRlRmllbGQoZmllbGROYW1lOiBzdHJpbmcsIGNsYXNzTmFtZTogc3RyaW5nLCBkYXRhYmFzZTogRGF0YWJhc2VDb250cm9sbGVyKSB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZXRlRmllbGRzKFtmaWVsZE5hbWVdLCBjbGFzc05hbWUsIGRhdGFiYXNlKTtcbiAgfVxuXG4gIC8vIERlbGV0ZSBmaWVsZHMsIGFuZCByZW1vdmUgdGhhdCBkYXRhIGZyb20gYWxsIG9iamVjdHMuIFRoaXMgaXMgaW50ZW5kZWRcbiAgLy8gdG8gcmVtb3ZlIHVudXNlZCBmaWVsZHMsIGlmIG90aGVyIHdyaXRlcnMgYXJlIHdyaXRpbmcgb2JqZWN0cyB0aGF0IGluY2x1ZGVcbiAgLy8gdGhpcyBmaWVsZCwgdGhlIGZpZWxkIG1heSByZWFwcGVhci4gUmV0dXJucyBhIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoXG4gIC8vIG5vIG9iamVjdCBvbiBzdWNjZXNzLCBvciByZWplY3RzIHdpdGggeyBjb2RlLCBlcnJvciB9IG9uIGZhaWx1cmUuXG4gIC8vIFBhc3NpbmcgdGhlIGRhdGFiYXNlIGFuZCBwcmVmaXggaXMgbmVjZXNzYXJ5IGluIG9yZGVyIHRvIGRyb3AgcmVsYXRpb24gY29sbGVjdGlvbnNcbiAgLy8gYW5kIHJlbW92ZSBmaWVsZHMgZnJvbSBvYmplY3RzLiBJZGVhbGx5IHRoZSBkYXRhYmFzZSB3b3VsZCBiZWxvbmcgdG9cbiAgLy8gYSBkYXRhYmFzZSBhZGFwdGVyIGFuZCB0aGlzIGZ1bmN0aW9uIHdvdWxkIGNsb3NlIG92ZXIgaXQgb3IgYWNjZXNzIGl0IHZpYSBtZW1iZXIuXG4gIGRlbGV0ZUZpZWxkcyhmaWVsZE5hbWVzOiBBcnJheTxzdHJpbmc+LCBjbGFzc05hbWU6IHN0cmluZywgZGF0YWJhc2U6IERhdGFiYXNlQ29udHJvbGxlcikge1xuICAgIGlmICghY2xhc3NOYW1lSXNWYWxpZChjbGFzc05hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FLCBpbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZShjbGFzc05hbWUpKTtcbiAgICB9XG5cbiAgICBmaWVsZE5hbWVzLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgIGlmICghZmllbGROYW1lSXNWYWxpZChmaWVsZE5hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLCBgaW52YWxpZCBmaWVsZCBuYW1lOiAke2ZpZWxkTmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIC8vRG9uJ3QgYWxsb3cgZGVsZXRpbmcgdGhlIGRlZmF1bHQgZmllbGRzLlxuICAgICAgaWYgKCFmaWVsZE5hbWVJc1ZhbGlkRm9yQ2xhc3MoZmllbGROYW1lLCBjbGFzc05hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxMzYsIGBmaWVsZCAke2ZpZWxkTmFtZX0gY2Fubm90IGJlIGNoYW5nZWRgKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLmdldE9uZVNjaGVtYShjbGFzc05hbWUsIGZhbHNlLCB7Y2xlYXJDYWNoZTogdHJ1ZX0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0NMQVNTX05BTUUsIGBDbGFzcyAke2NsYXNzTmFtZX0gZG9lcyBub3QgZXhpc3QuYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAudGhlbihzY2hlbWEgPT4ge1xuICAgICAgICBmaWVsZE5hbWVzLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICBpZiAoIXNjaGVtYS5maWVsZHNbZmllbGROYW1lXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKDI1NSwgYEZpZWxkICR7ZmllbGROYW1lfSBkb2VzIG5vdCBleGlzdCwgY2Fubm90IGRlbGV0ZS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHNjaGVtYUZpZWxkcyA9IHsgLi4uc2NoZW1hLmZpZWxkcyB9O1xuICAgICAgICByZXR1cm4gZGF0YWJhc2UuYWRhcHRlci5kZWxldGVGaWVsZHMoY2xhc3NOYW1lLCBzY2hlbWEsIGZpZWxkTmFtZXMpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGZpZWxkTmFtZXMubWFwKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gc2NoZW1hRmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgICAgICAgIGlmIChmaWVsZCAmJiBmaWVsZC50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgICAgICAgIC8vRm9yIHJlbGF0aW9ucywgZHJvcCB0aGUgX0pvaW4gdGFibGVcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0YWJhc2UuYWRhcHRlci5kZWxldGVDbGFzcyhgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLl9jYWNoZS5jbGVhcigpO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBWYWxpZGF0ZXMgYW4gb2JqZWN0IHByb3ZpZGVkIGluIFJFU1QgZm9ybWF0LlxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBuZXcgc2NoZW1hIGlmIHRoaXMgb2JqZWN0IGlzXG4gIC8vIHZhbGlkLlxuICB2YWxpZGF0ZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0OiBhbnksIHF1ZXJ5OiBhbnkpIHtcbiAgICBsZXQgZ2VvY291bnQgPSAwO1xuICAgIGxldCBwcm9taXNlID0gdGhpcy5lbmZvcmNlQ2xhc3NFeGlzdHMoY2xhc3NOYW1lKTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBnZXRUeXBlKG9iamVjdFtmaWVsZE5hbWVdKTtcbiAgICAgIGlmIChleHBlY3RlZCA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICBnZW9jb3VudCsrO1xuICAgICAgfVxuICAgICAgaWYgKGdlb2NvdW50ID4gMSkge1xuICAgICAgICAvLyBNYWtlIHN1cmUgYWxsIGZpZWxkIHZhbGlkYXRpb24gb3BlcmF0aW9ucyBydW4gYmVmb3JlIHdlIHJldHVybi5cbiAgICAgICAgLy8gSWYgbm90IC0gd2UgYXJlIGNvbnRpbnVpbmcgdG8gcnVuIGxvZ2ljLCBidXQgYWxyZWFkeSBwcm92aWRlZCByZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIuXG4gICAgICAgIHJldHVybiBwcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsXG4gICAgICAgICAgICAndGhlcmUgY2FuIG9ubHkgYmUgb25lIGdlb3BvaW50IGZpZWxkIGluIGEgY2xhc3MnKSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKCFleHBlY3RlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChmaWVsZE5hbWUgPT09ICdBQ0wnKSB7XG4gICAgICAgIC8vIEV2ZXJ5IG9iamVjdCBoYXMgQUNMIGltcGxpY2l0bHkuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKHNjaGVtYSA9PiBzY2hlbWEuZW5mb3JjZUZpZWxkRXhpc3RzKGNsYXNzTmFtZSwgZmllbGROYW1lLCBleHBlY3RlZCkpO1xuICAgIH1cbiAgICBwcm9taXNlID0gdGhlblZhbGlkYXRlUmVxdWlyZWRDb2x1bW5zKHByb21pc2UsIGNsYXNzTmFtZSwgb2JqZWN0LCBxdWVyeSk7XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cblxuICAvLyBWYWxpZGF0ZXMgdGhhdCBhbGwgdGhlIHByb3BlcnRpZXMgYXJlIHNldCBmb3IgdGhlIG9iamVjdFxuICB2YWxpZGF0ZVJlcXVpcmVkQ29sdW1ucyhjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0OiBhbnksIHF1ZXJ5OiBhbnkpIHtcbiAgICBjb25zdCBjb2x1bW5zID0gcmVxdWlyZWRDb2x1bW5zW2NsYXNzTmFtZV07XG4gICAgaWYgKCFjb2x1bW5zIHx8IGNvbHVtbnMubGVuZ3RoID09IDApIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcyk7XG4gICAgfVxuXG4gICAgY29uc3QgbWlzc2luZ0NvbHVtbnMgPSBjb2x1bW5zLmZpbHRlcihmdW5jdGlvbihjb2x1bW4pe1xuICAgICAgaWYgKHF1ZXJ5ICYmIHF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgICAgIGlmIChvYmplY3RbY29sdW1uXSAmJiB0eXBlb2Ygb2JqZWN0W2NvbHVtbl0gPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAvLyBUcnlpbmcgdG8gZGVsZXRlIGEgcmVxdWlyZWQgY29sdW1uXG4gICAgICAgICAgcmV0dXJuIG9iamVjdFtjb2x1bW5dLl9fb3AgPT0gJ0RlbGV0ZSc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm90IHRyeWluZyB0byBkbyBhbnl0aGluZyB0aGVyZVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gIW9iamVjdFtjb2x1bW5dXG4gICAgfSk7XG5cbiAgICBpZiAobWlzc2luZ0NvbHVtbnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTkNPUlJFQ1RfVFlQRSxcbiAgICAgICAgbWlzc2luZ0NvbHVtbnNbMF0gKyAnIGlzIHJlcXVpcmVkLicpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuICB9XG5cbiAgLy8gVmFsaWRhdGVzIHRoZSBiYXNlIENMUCBmb3IgYW4gb3BlcmF0aW9uXG4gIHRlc3RCYXNlQ0xQKGNsYXNzTmFtZTogc3RyaW5nLCBhY2xHcm91cDogc3RyaW5nW10sIG9wZXJhdGlvbjogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLnBlcm1zW2NsYXNzTmFtZV0gfHwgIXRoaXMucGVybXNbY2xhc3NOYW1lXVtvcGVyYXRpb25dKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3QgY2xhc3NQZXJtcyA9IHRoaXMucGVybXNbY2xhc3NOYW1lXTtcbiAgICBjb25zdCBwZXJtcyA9IGNsYXNzUGVybXNbb3BlcmF0aW9uXTtcbiAgICAvLyBIYW5kbGUgdGhlIHB1YmxpYyBzY2VuYXJpbyBxdWlja2x5XG4gICAgaWYgKHBlcm1zWycqJ10pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvLyBDaGVjayBwZXJtaXNzaW9ucyBhZ2FpbnN0IHRoZSBhY2xHcm91cCBwcm92aWRlZCAoYXJyYXkgb2YgdXNlcklkL3JvbGVzKVxuICAgIGlmIChhY2xHcm91cC5zb21lKGFjbCA9PiB7IHJldHVybiBwZXJtc1thY2xdID09PSB0cnVlIH0pKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gVmFsaWRhdGVzIGFuIG9wZXJhdGlvbiBwYXNzZXMgY2xhc3MtbGV2ZWwtcGVybWlzc2lvbnMgc2V0IGluIHRoZSBzY2hlbWFcbiAgdmFsaWRhdGVQZXJtaXNzaW9uKGNsYXNzTmFtZTogc3RyaW5nLCBhY2xHcm91cDogc3RyaW5nW10sIG9wZXJhdGlvbjogc3RyaW5nKSB7XG5cbiAgICBpZiAodGhpcy50ZXN0QmFzZUNMUChjbGFzc05hbWUsIGFjbEdyb3VwLCBvcGVyYXRpb24pKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLnBlcm1zW2NsYXNzTmFtZV0gfHwgIXRoaXMucGVybXNbY2xhc3NOYW1lXVtvcGVyYXRpb25dKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3QgY2xhc3NQZXJtcyA9IHRoaXMucGVybXNbY2xhc3NOYW1lXTtcbiAgICBjb25zdCBwZXJtcyA9IGNsYXNzUGVybXNbb3BlcmF0aW9uXTtcblxuICAgIC8vIElmIG9ubHkgZm9yIGF1dGhlbnRpY2F0ZWQgdXNlcnNcbiAgICAvLyBtYWtlIHN1cmUgd2UgaGF2ZSBhbiBhY2xHcm91cFxuICAgIGlmIChwZXJtc1sncmVxdWlyZXNBdXRoZW50aWNhdGlvbiddKSB7XG4gICAgICAvLyBJZiBhY2xHcm91cCBoYXMgKiAocHVibGljKVxuICAgICAgaWYgKCFhY2xHcm91cCB8fCBhY2xHcm91cC5sZW5ndGggPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAnUGVybWlzc2lvbiBkZW5pZWQsIHVzZXIgbmVlZHMgdG8gYmUgYXV0aGVudGljYXRlZC4nKTtcbiAgICAgIH0gZWxzZSBpZiAoYWNsR3JvdXAuaW5kZXhPZignKicpID4gLTEgJiYgYWNsR3JvdXAubGVuZ3RoID09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgJ1Blcm1pc3Npb24gZGVuaWVkLCB1c2VyIG5lZWRzIHRvIGJlIGF1dGhlbnRpY2F0ZWQuJyk7XG4gICAgICB9XG4gICAgICAvLyByZXF1aXJlc0F1dGhlbnRpY2F0aW9uIHBhc3NlZCwganVzdCBtb3ZlIGZvcndhcmRcbiAgICAgIC8vIHByb2JhYmx5IHdvdWxkIGJlIHdpc2UgYXQgc29tZSBwb2ludCB0byByZW5hbWUgdG8gJ2F1dGhlbnRpY2F0ZWRVc2VyJ1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIC8vIE5vIG1hdGNoaW5nIENMUCwgbGV0J3MgY2hlY2sgdGhlIFBvaW50ZXIgcGVybWlzc2lvbnNcbiAgICAvLyBBbmQgaGFuZGxlIHRob3NlIGxhdGVyXG4gICAgY29uc3QgcGVybWlzc2lvbkZpZWxkID0gWydnZXQnLCAnZmluZCcsICdjb3VudCddLmluZGV4T2Yob3BlcmF0aW9uKSA+IC0xID8gJ3JlYWRVc2VyRmllbGRzJyA6ICd3cml0ZVVzZXJGaWVsZHMnO1xuXG4gICAgLy8gUmVqZWN0IGNyZWF0ZSB3aGVuIHdyaXRlIGxvY2tkb3duXG4gICAgaWYgKHBlcm1pc3Npb25GaWVsZCA9PSAnd3JpdGVVc2VyRmllbGRzJyAmJiBvcGVyYXRpb24gPT0gJ2NyZWF0ZScpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICBgUGVybWlzc2lvbiBkZW5pZWQgZm9yIGFjdGlvbiAke29wZXJhdGlvbn0gb24gY2xhc3MgJHtjbGFzc05hbWV9LmApO1xuICAgIH1cblxuICAgIC8vIFByb2Nlc3MgdGhlIHJlYWRVc2VyRmllbGRzIGxhdGVyXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY2xhc3NQZXJtc1twZXJtaXNzaW9uRmllbGRdKSAmJiBjbGFzc1Blcm1zW3Blcm1pc3Npb25GaWVsZF0ubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTixcbiAgICAgIGBQZXJtaXNzaW9uIGRlbmllZCBmb3IgYWN0aW9uICR7b3BlcmF0aW9ufSBvbiBjbGFzcyAke2NsYXNzTmFtZX0uYCk7XG4gIH1cblxuICAvLyBSZXR1cm5zIHRoZSBleHBlY3RlZCB0eXBlIGZvciBhIGNsYXNzTmFtZStrZXkgY29tYmluYXRpb25cbiAgLy8gb3IgdW5kZWZpbmVkIGlmIHRoZSBzY2hlbWEgaXMgbm90IHNldFxuICBnZXRFeHBlY3RlZFR5cGUoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nKTogPyhTY2hlbWFGaWVsZCB8IHN0cmluZykge1xuICAgIGlmICh0aGlzLmRhdGEgJiYgdGhpcy5kYXRhW2NsYXNzTmFtZV0pIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZSA9IHRoaXMuZGF0YVtjbGFzc05hbWVdW2ZpZWxkTmFtZV1cbiAgICAgIHJldHVybiBleHBlY3RlZFR5cGUgPT09ICdtYXAnID8gJ09iamVjdCcgOiBleHBlY3RlZFR5cGU7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBDaGVja3MgaWYgYSBnaXZlbiBjbGFzcyBpcyBpbiB0aGUgc2NoZW1hLlxuICBoYXNDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLnJlbG9hZERhdGEoKS50aGVuKCgpID0+ICEhKHRoaXMuZGF0YVtjbGFzc05hbWVdKSk7XG4gIH1cbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEgbmV3IFNjaGVtYS5cbmNvbnN0IGxvYWQgPSAoZGJBZGFwdGVyOiBTdG9yYWdlQWRhcHRlciwgc2NoZW1hQ2FjaGU6IGFueSwgb3B0aW9uczogYW55KTogUHJvbWlzZTxTY2hlbWFDb250cm9sbGVyPiA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IG5ldyBTY2hlbWFDb250cm9sbGVyKGRiQWRhcHRlciwgc2NoZW1hQ2FjaGUpO1xuICByZXR1cm4gc2NoZW1hLnJlbG9hZERhdGEob3B0aW9ucykudGhlbigoKSA9PiBzY2hlbWEpO1xufVxuXG4vLyBCdWlsZHMgYSBuZXcgc2NoZW1hIChpbiBzY2hlbWEgQVBJIHJlc3BvbnNlIGZvcm1hdCkgb3V0IG9mIGFuXG4vLyBleGlzdGluZyBtb25nbyBzY2hlbWEgKyBhIHNjaGVtYXMgQVBJIHB1dCByZXF1ZXN0LiBUaGlzIHJlc3BvbnNlXG4vLyBkb2VzIG5vdCBpbmNsdWRlIHRoZSBkZWZhdWx0IGZpZWxkcywgYXMgaXQgaXMgaW50ZW5kZWQgdG8gYmUgcGFzc2VkXG4vLyB0byBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWUuIE5vIHZhbGlkYXRpb24gaXMgZG9uZSBoZXJlLCBpdFxuLy8gaXMgZG9uZSBpbiBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWUuXG5mdW5jdGlvbiBidWlsZE1lcmdlZFNjaGVtYU9iamVjdChleGlzdGluZ0ZpZWxkczogU2NoZW1hRmllbGRzLCBwdXRSZXF1ZXN0OiBhbnkpOiBTY2hlbWFGaWVsZHMge1xuICBjb25zdCBuZXdTY2hlbWEgPSB7fTtcbiAgLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG4gIGNvbnN0IHN5c1NjaGVtYUZpZWxkID0gT2JqZWN0LmtleXMoZGVmYXVsdENvbHVtbnMpLmluZGV4T2YoZXhpc3RpbmdGaWVsZHMuX2lkKSA9PT0gLTEgPyBbXSA6IE9iamVjdC5rZXlzKGRlZmF1bHRDb2x1bW5zW2V4aXN0aW5nRmllbGRzLl9pZF0pO1xuICBmb3IgKGNvbnN0IG9sZEZpZWxkIGluIGV4aXN0aW5nRmllbGRzKSB7XG4gICAgaWYgKG9sZEZpZWxkICE9PSAnX2lkJyAmJiBvbGRGaWVsZCAhPT0gJ0FDTCcgJiYgIG9sZEZpZWxkICE9PSAndXBkYXRlZEF0JyAmJiBvbGRGaWVsZCAhPT0gJ2NyZWF0ZWRBdCcgJiYgb2xkRmllbGQgIT09ICdvYmplY3RJZCcpIHtcbiAgICAgIGlmIChzeXNTY2hlbWFGaWVsZC5sZW5ndGggPiAwICYmIHN5c1NjaGVtYUZpZWxkLmluZGV4T2Yob2xkRmllbGQpICE9PSAtMSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZpZWxkSXNEZWxldGVkID0gcHV0UmVxdWVzdFtvbGRGaWVsZF0gJiYgcHV0UmVxdWVzdFtvbGRGaWVsZF0uX19vcCA9PT0gJ0RlbGV0ZSdcbiAgICAgIGlmICghZmllbGRJc0RlbGV0ZWQpIHtcbiAgICAgICAgbmV3U2NoZW1hW29sZEZpZWxkXSA9IGV4aXN0aW5nRmllbGRzW29sZEZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZm9yIChjb25zdCBuZXdGaWVsZCBpbiBwdXRSZXF1ZXN0KSB7XG4gICAgaWYgKG5ld0ZpZWxkICE9PSAnb2JqZWN0SWQnICYmIHB1dFJlcXVlc3RbbmV3RmllbGRdLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICBpZiAoc3lzU2NoZW1hRmllbGQubGVuZ3RoID4gMCAmJiBzeXNTY2hlbWFGaWVsZC5pbmRleE9mKG5ld0ZpZWxkKSAhPT0gLTEpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBuZXdTY2hlbWFbbmV3RmllbGRdID0gcHV0UmVxdWVzdFtuZXdGaWVsZF07XG4gICAgfVxuICB9XG4gIHJldHVybiBuZXdTY2hlbWE7XG59XG5cbi8vIEdpdmVuIGEgc2NoZW1hIHByb21pc2UsIGNvbnN0cnVjdCBhbm90aGVyIHNjaGVtYSBwcm9taXNlIHRoYXRcbi8vIHZhbGlkYXRlcyB0aGlzIGZpZWxkIG9uY2UgdGhlIHNjaGVtYSBsb2Fkcy5cbmZ1bmN0aW9uIHRoZW5WYWxpZGF0ZVJlcXVpcmVkQ29sdW1ucyhzY2hlbWFQcm9taXNlLCBjbGFzc05hbWUsIG9iamVjdCwgcXVlcnkpIHtcbiAgcmV0dXJuIHNjaGVtYVByb21pc2UudGhlbigoc2NoZW1hKSA9PiB7XG4gICAgcmV0dXJuIHNjaGVtYS52YWxpZGF0ZVJlcXVpcmVkQ29sdW1ucyhjbGFzc05hbWUsIG9iamVjdCwgcXVlcnkpO1xuICB9KTtcbn1cblxuLy8gR2V0cyB0aGUgdHlwZSBmcm9tIGEgUkVTVCBBUEkgZm9ybWF0dGVkIG9iamVjdCwgd2hlcmUgJ3R5cGUnIGlzXG4vLyBleHRlbmRlZCBwYXN0IGphdmFzY3JpcHQgdHlwZXMgdG8gaW5jbHVkZSB0aGUgcmVzdCBvZiB0aGUgUGFyc2Vcbi8vIHR5cGUgc3lzdGVtLlxuLy8gVGhlIG91dHB1dCBzaG91bGQgYmUgYSB2YWxpZCBzY2hlbWEgdmFsdWUuXG4vLyBUT0RPOiBlbnN1cmUgdGhhdCB0aGlzIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgZm9ybWF0IHVzZWQgaW4gT3BlbiBEQlxuZnVuY3Rpb24gZ2V0VHlwZShvYmo6IGFueSk6ID8oU2NoZW1hRmllbGQgfCBzdHJpbmcpIHtcbiAgY29uc3QgdHlwZSA9IHR5cGVvZiBvYmo7XG4gIHN3aXRjaCh0eXBlKSB7XG4gIGNhc2UgJ2Jvb2xlYW4nOlxuICAgIHJldHVybiAnQm9vbGVhbic7XG4gIGNhc2UgJ3N0cmluZyc6XG4gICAgcmV0dXJuICdTdHJpbmcnO1xuICBjYXNlICdudW1iZXInOlxuICAgIHJldHVybiAnTnVtYmVyJztcbiAgY2FzZSAnbWFwJzpcbiAgY2FzZSAnb2JqZWN0JzpcbiAgICBpZiAoIW9iaikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIGdldE9iamVjdFR5cGUob2JqKTtcbiAgY2FzZSAnZnVuY3Rpb24nOlxuICBjYXNlICdzeW1ib2wnOlxuICBjYXNlICd1bmRlZmluZWQnOlxuICBkZWZhdWx0OlxuICAgIHRocm93ICdiYWQgb2JqOiAnICsgb2JqO1xuICB9XG59XG5cbi8vIFRoaXMgZ2V0cyB0aGUgdHlwZSBmb3Igbm9uLUpTT04gdHlwZXMgbGlrZSBwb2ludGVycyBhbmQgZmlsZXMsIGJ1dFxuLy8gYWxzbyBnZXRzIHRoZSBhcHByb3ByaWF0ZSB0eXBlIGZvciAkIG9wZXJhdG9ycy5cbi8vIFJldHVybnMgbnVsbCBpZiB0aGUgdHlwZSBpcyB1bmtub3duLlxuZnVuY3Rpb24gZ2V0T2JqZWN0VHlwZShvYmopOiA/KFNjaGVtYUZpZWxkIHwgc3RyaW5nKSB7XG4gIGlmIChvYmogaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHJldHVybiAnQXJyYXknO1xuICB9XG4gIGlmIChvYmouX190eXBlKXtcbiAgICBzd2l0Y2gob2JqLl9fdHlwZSkge1xuICAgIGNhc2UgJ1BvaW50ZXInIDpcbiAgICAgIGlmKG9iai5jbGFzc05hbWUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiAnUG9pbnRlcicsXG4gICAgICAgICAgdGFyZ2V0Q2xhc3M6IG9iai5jbGFzc05hbWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnUmVsYXRpb24nIDpcbiAgICAgIGlmKG9iai5jbGFzc05hbWUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiAnUmVsYXRpb24nLFxuICAgICAgICAgIHRhcmdldENsYXNzOiBvYmouY2xhc3NOYW1lXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ0ZpbGUnIDpcbiAgICAgIGlmKG9iai5uYW1lKSB7XG4gICAgICAgIHJldHVybiAnRmlsZSc7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdEYXRlJyA6XG4gICAgICBpZihvYmouaXNvKSB7XG4gICAgICAgIHJldHVybiAnRGF0ZSc7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdHZW9Qb2ludCcgOlxuICAgICAgaWYob2JqLmxhdGl0dWRlICE9IG51bGwgJiYgb2JqLmxvbmdpdHVkZSAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiAnR2VvUG9pbnQnO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnQnl0ZXMnIDpcbiAgICAgIGlmKG9iai5iYXNlNjQpIHtcbiAgICAgICAgcmV0dXJuICdCeXRlcyc7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdQb2x5Z29uJyA6XG4gICAgICBpZihvYmouY29vcmRpbmF0ZXMpIHtcbiAgICAgICAgcmV0dXJuICdQb2x5Z29uJztcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5DT1JSRUNUX1RZUEUsIFwiVGhpcyBpcyBub3QgYSB2YWxpZCBcIiArIG9iai5fX3R5cGUpO1xuICB9XG4gIGlmIChvYmpbJyRuZSddKSB7XG4gICAgcmV0dXJuIGdldE9iamVjdFR5cGUob2JqWyckbmUnXSk7XG4gIH1cbiAgaWYgKG9iai5fX29wKSB7XG4gICAgc3dpdGNoKG9iai5fX29wKSB7XG4gICAgY2FzZSAnSW5jcmVtZW50JzpcbiAgICAgIHJldHVybiAnTnVtYmVyJztcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgY2FzZSAnQWRkJzpcbiAgICBjYXNlICdBZGRVbmlxdWUnOlxuICAgIGNhc2UgJ1JlbW92ZSc6XG4gICAgICByZXR1cm4gJ0FycmF5JztcbiAgICBjYXNlICdBZGRSZWxhdGlvbic6XG4gICAgY2FzZSAnUmVtb3ZlUmVsYXRpb24nOlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ1JlbGF0aW9uJyxcbiAgICAgICAgdGFyZ2V0Q2xhc3M6IG9iai5vYmplY3RzWzBdLmNsYXNzTmFtZVxuICAgICAgfVxuICAgIGNhc2UgJ0JhdGNoJzpcbiAgICAgIHJldHVybiBnZXRPYmplY3RUeXBlKG9iai5vcHNbMF0pO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyAndW5leHBlY3RlZCBvcDogJyArIG9iai5fX29wO1xuICAgIH1cbiAgfVxuICByZXR1cm4gJ09iamVjdCc7XG59XG5cbmV4cG9ydCB7XG4gIGxvYWQsXG4gIGNsYXNzTmFtZUlzVmFsaWQsXG4gIGZpZWxkTmFtZUlzVmFsaWQsXG4gIGludmFsaWRDbGFzc05hbWVNZXNzYWdlLFxuICBidWlsZE1lcmdlZFNjaGVtYU9iamVjdCxcbiAgc3lzdGVtQ2xhc3NlcyxcbiAgZGVmYXVsdENvbHVtbnMsXG4gIGNvbnZlcnRTY2hlbWFUb0FkYXB0ZXJTY2hlbWEsXG4gIFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMsXG4gIFNjaGVtYUNvbnRyb2xsZXIsXG59O1xuIl19 \ No newline at end of file diff --git a/lib/Controllers/UserController.js b/lib/Controllers/UserController.js index 2ca5f18cf0..60b713fceb 100644 --- a/lib/Controllers/UserController.js +++ b/lib/Controllers/UserController.js @@ -266,4 +266,5 @@ function buildEmailLink(destination, username, token, config) { } } -exports.default = UserController; \ No newline at end of file +exports.default = UserController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9Vc2VyQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJSZXN0UXVlcnkiLCJyZXF1aXJlIiwiQXV0aCIsIlVzZXJDb250cm9sbGVyIiwiQWRhcHRhYmxlQ29udHJvbGxlciIsImNvbnN0cnVjdG9yIiwiYWRhcHRlciIsImFwcElkIiwib3B0aW9ucyIsInZhbGlkYXRlQWRhcHRlciIsInNob3VsZFZlcmlmeUVtYWlscyIsImV4cGVjdGVkQWRhcHRlclR5cGUiLCJNYWlsQWRhcHRlciIsInZlcmlmeVVzZXJFbWFpbHMiLCJzZXRFbWFpbFZlcmlmeVRva2VuIiwidXNlciIsIl9lbWFpbF92ZXJpZnlfdG9rZW4iLCJlbWFpbFZlcmlmaWVkIiwiY29uZmlnIiwiZW1haWxWZXJpZnlUb2tlblZhbGlkaXR5RHVyYXRpb24iLCJfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQiLCJQYXJzZSIsIl9lbmNvZGUiLCJnZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW5FeHBpcmVzQXQiLCJ2ZXJpZnlFbWFpbCIsInVzZXJuYW1lIiwidG9rZW4iLCJ1bmRlZmluZWQiLCJxdWVyeSIsInVwZGF0ZUZpZWxkcyIsIl9fb3AiLCIkZ3QiLCJEYXRlIiwibWFzdGVyQXV0aCIsIm1hc3RlciIsImNoZWNrSWZBbHJlYWR5VmVyaWZpZWQiLCJleGVjdXRlIiwidGhlbiIsInJlc3VsdCIsInJlc3VsdHMiLCJsZW5ndGgiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlc3QiLCJ1cGRhdGUiLCJjaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSIsImRhdGFiYXNlIiwiZmluZCIsIl9wZXJpc2hhYmxlX3Rva2VuIiwibGltaXQiLCJwYXNzd29yZFBvbGljeSIsInJlc2V0VG9rZW5WYWxpZGl0eUR1cmF0aW9uIiwiZXhwaXJlc0RhdGUiLCJfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0IiwiX190eXBlIiwiaXNvIiwiZ2V0VXNlcklmTmVlZGVkIiwiZW1haWwiLCJ3aGVyZSIsInNlbmRWZXJpZmljYXRpb25FbWFpbCIsImVuY29kZVVSSUNvbXBvbmVudCIsImxpbmsiLCJidWlsZEVtYWlsTGluayIsInZlcmlmeUVtYWlsVVJMIiwiYXBwTmFtZSIsInNlbmRNYWlsIiwiZGVmYXVsdFZlcmlmaWNhdGlvbkVtYWlsIiwicmVnZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW4iLCJyZXNlbmRWZXJpZmljYXRpb25FbWFpbCIsImFVc2VyIiwic2V0UGFzc3dvcmRSZXNldFRva2VuIiwiZ2VuZXJhdGVQYXNzd29yZFJlc2V0VG9rZW5FeHBpcmVzQXQiLCIkb3IiLCIkZXhpc3RzIiwic2VuZFBhc3N3b3JkUmVzZXRFbWFpbCIsInJlcXVlc3RSZXNldFBhc3N3b3JkVVJMIiwiZGVmYXVsdFJlc2V0UGFzc3dvcmRFbWFpbCIsInVwZGF0ZVBhc3N3b3JkIiwicGFzc3dvcmQiLCJ1cGRhdGVVc2VyUGFzc3dvcmQiLCJvYmplY3RJZCIsImNhdGNoIiwiZXJyb3IiLCJtZXNzYWdlIiwicmVqZWN0IiwidGV4dCIsImdldCIsInRvIiwic3ViamVjdCIsInVzZXJJZCIsImRlc3RpbmF0aW9uIiwidXNlcm5hbWVBbmRUb2tlbiIsInBhcnNlRnJhbWVVUkwiLCJkZXN0aW5hdGlvbldpdGhvdXRIb3N0IiwicmVwbGFjZSIsInB1YmxpY1NlcnZlclVSTCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFQSxJQUFJQSxZQUFZQyxRQUFRLGNBQVIsQ0FBaEI7QUFDQSxJQUFJQyxPQUFPRCxRQUFRLFNBQVIsQ0FBWDs7QUFFTyxNQUFNRSxjQUFOLFNBQTZCQyw2QkFBN0IsQ0FBaUQ7O0FBRXREQyxjQUFZQyxPQUFaLEVBQXFCQyxLQUFyQixFQUE0QkMsVUFBVSxFQUF0QyxFQUEwQztBQUN4QyxVQUFNRixPQUFOLEVBQWVDLEtBQWYsRUFBc0JDLE9BQXRCO0FBQ0Q7O0FBRURDLGtCQUFnQkgsT0FBaEIsRUFBeUI7QUFDdkI7QUFDQSxRQUFJLENBQUNBLE9BQUQsSUFBWSxDQUFDLEtBQUtJLGtCQUF0QixFQUEwQztBQUN4QztBQUNEO0FBQ0QsVUFBTUQsZUFBTixDQUFzQkgsT0FBdEI7QUFDRDs7QUFFREssd0JBQXNCO0FBQ3BCLFdBQU9DLHFCQUFQO0FBQ0Q7O0FBRUQsTUFBSUYsa0JBQUosR0FBeUI7QUFDdkIsV0FBTyxLQUFLRixPQUFMLENBQWFLLGdCQUFwQjtBQUNEOztBQUVEQyxzQkFBb0JDLElBQXBCLEVBQTBCO0FBQ3hCLFFBQUksS0FBS0wsa0JBQVQsRUFBNkI7QUFDM0JLLFdBQUtDLG1CQUFMLEdBQTJCLCtCQUFhLEVBQWIsQ0FBM0I7QUFDQUQsV0FBS0UsYUFBTCxHQUFxQixLQUFyQjs7QUFFQSxVQUFJLEtBQUtDLE1BQUwsQ0FBWUMsZ0NBQWhCLEVBQWtEO0FBQ2hESixhQUFLSyw4QkFBTCxHQUFzQ0MsZUFBTUMsT0FBTixDQUFjLEtBQUtKLE1BQUwsQ0FBWUssaUNBQVosRUFBZCxDQUF0QztBQUNEO0FBQ0Y7QUFDRjs7QUFFREMsY0FBWUMsUUFBWixFQUFzQkMsS0FBdEIsRUFBNkI7QUFDM0IsUUFBSSxDQUFDLEtBQUtoQixrQkFBVixFQUE4QjtBQUM1QjtBQUNBO0FBQ0EsWUFBTWlCLFNBQU47QUFDRDs7QUFFRCxVQUFNQyxRQUFRLEVBQUNILFVBQVVBLFFBQVgsRUFBcUJULHFCQUFxQlUsS0FBMUMsRUFBZDtBQUNBLFVBQU1HLGVBQWUsRUFBRVosZUFBZSxJQUFqQixFQUF1QkQscUJBQXFCLEVBQUNjLE1BQU0sUUFBUCxFQUE1QyxFQUFyQjs7QUFFQTtBQUNBO0FBQ0EsUUFBSSxLQUFLWixNQUFMLENBQVlDLGdDQUFoQixFQUFrRDtBQUNoRFMsWUFBTVgsYUFBTixHQUFzQixLQUF0QjtBQUNBVyxZQUFNUiw4QkFBTixHQUF1QyxFQUFFVyxLQUFLVixlQUFNQyxPQUFOLENBQWMsSUFBSVUsSUFBSixFQUFkLENBQVAsRUFBdkM7O0FBRUFILG1CQUFhVCw4QkFBYixHQUE4QyxFQUFDVSxNQUFNLFFBQVAsRUFBOUM7QUFDRDtBQUNELFVBQU1HLGFBQWEvQixLQUFLZ0MsTUFBTCxDQUFZLEtBQUtoQixNQUFqQixDQUFuQjtBQUNBLFFBQUlpQix5QkFBeUIsSUFBSW5DLFNBQUosQ0FBYyxLQUFLa0IsTUFBbkIsRUFBMkJoQixLQUFLZ0MsTUFBTCxDQUFZLEtBQUtoQixNQUFqQixDQUEzQixFQUFxRCxPQUFyRCxFQUE4RCxFQUFDTyxVQUFVQSxRQUFYLEVBQXFCUixlQUFlLElBQXBDLEVBQTlELENBQTdCO0FBQ0EsV0FBT2tCLHVCQUF1QkMsT0FBdkIsR0FBaUNDLElBQWpDLENBQXNDQyxVQUFVO0FBQ3JELFVBQUlBLE9BQU9DLE9BQVAsQ0FBZUMsTUFBbkIsRUFBMkI7QUFDekIsZUFBT0MsUUFBUUMsT0FBUixDQUFnQkosT0FBT0MsT0FBUCxDQUFlQyxNQUFmLENBQXNCLENBQXRCLENBQWhCLENBQVA7QUFDRDtBQUNELGFBQU9HLGVBQUtDLE1BQUwsQ0FBWSxLQUFLMUIsTUFBakIsRUFBeUJlLFVBQXpCLEVBQXFDLE9BQXJDLEVBQThDTCxLQUE5QyxFQUFxREMsWUFBckQsQ0FBUDtBQUNELEtBTE0sQ0FBUDtBQU1EOztBQUVEZ0IsMEJBQXdCcEIsUUFBeEIsRUFBa0NDLEtBQWxDLEVBQXlDO0FBQ3ZDLFdBQU8sS0FBS1IsTUFBTCxDQUFZNEIsUUFBWixDQUFxQkMsSUFBckIsQ0FBMEIsT0FBMUIsRUFBbUM7QUFDeEN0QixnQkFBVUEsUUFEOEI7QUFFeEN1Qix5QkFBbUJ0QjtBQUZxQixLQUFuQyxFQUdKLEVBQUN1QixPQUFPLENBQVIsRUFISSxFQUdRWixJQUhSLENBR2FFLFdBQVc7QUFDN0IsVUFBSUEsUUFBUUMsTUFBUixJQUFrQixDQUF0QixFQUF5QjtBQUN2QixjQUFNYixTQUFOO0FBQ0Q7O0FBRUQsVUFBSSxLQUFLVCxNQUFMLENBQVlnQyxjQUFaLElBQThCLEtBQUtoQyxNQUFMLENBQVlnQyxjQUFaLENBQTJCQywwQkFBN0QsRUFBeUY7QUFDdkYsWUFBSUMsY0FBY2IsUUFBUSxDQUFSLEVBQVdjLDRCQUE3QjtBQUNBLFlBQUlELGVBQWVBLFlBQVlFLE1BQVosSUFBc0IsTUFBekMsRUFBaUQ7QUFDL0NGLHdCQUFjLElBQUlwQixJQUFKLENBQVNvQixZQUFZRyxHQUFyQixDQUFkO0FBQ0Q7QUFDRCxZQUFJSCxjQUFjLElBQUlwQixJQUFKLEVBQWxCLEVBQ0UsTUFBTSxxQ0FBTjtBQUNIOztBQUVELGFBQU9PLFFBQVEsQ0FBUixDQUFQO0FBQ0QsS0FsQk0sQ0FBUDtBQW1CRDs7QUFFRGlCLGtCQUFnQnpDLElBQWhCLEVBQXNCO0FBQ3BCLFFBQUlBLEtBQUtVLFFBQUwsSUFBaUJWLEtBQUswQyxLQUExQixFQUFpQztBQUMvQixhQUFPaEIsUUFBUUMsT0FBUixDQUFnQjNCLElBQWhCLENBQVA7QUFDRDtBQUNELFFBQUkyQyxRQUFRLEVBQVo7QUFDQSxRQUFJM0MsS0FBS1UsUUFBVCxFQUFtQjtBQUNqQmlDLFlBQU1qQyxRQUFOLEdBQWlCVixLQUFLVSxRQUF0QjtBQUNEO0FBQ0QsUUFBSVYsS0FBSzBDLEtBQVQsRUFBZ0I7QUFDZEMsWUFBTUQsS0FBTixHQUFjMUMsS0FBSzBDLEtBQW5CO0FBQ0Q7O0FBRUQsUUFBSTdCLFFBQVEsSUFBSTVCLFNBQUosQ0FBYyxLQUFLa0IsTUFBbkIsRUFBMkJoQixLQUFLZ0MsTUFBTCxDQUFZLEtBQUtoQixNQUFqQixDQUEzQixFQUFxRCxPQUFyRCxFQUE4RHdDLEtBQTlELENBQVo7QUFDQSxXQUFPOUIsTUFBTVEsT0FBTixHQUFnQkMsSUFBaEIsQ0FBcUIsVUFBU0MsTUFBVCxFQUFnQjtBQUMxQyxVQUFJQSxPQUFPQyxPQUFQLENBQWVDLE1BQWYsSUFBeUIsQ0FBN0IsRUFBZ0M7QUFDOUIsY0FBTWIsU0FBTjtBQUNEO0FBQ0QsYUFBT1csT0FBT0MsT0FBUCxDQUFlLENBQWYsQ0FBUDtBQUNELEtBTE0sQ0FBUDtBQU1EOztBQUVEb0Isd0JBQXNCNUMsSUFBdEIsRUFBNEI7QUFDMUIsUUFBSSxDQUFDLEtBQUtMLGtCQUFWLEVBQThCO0FBQzVCO0FBQ0Q7QUFDRCxVQUFNZ0IsUUFBUWtDLG1CQUFtQjdDLEtBQUtDLG1CQUF4QixDQUFkO0FBQ0E7QUFDQSxTQUFLd0MsZUFBTCxDQUFxQnpDLElBQXJCLEVBQTJCc0IsSUFBM0IsQ0FBaUN0QixJQUFELElBQVU7QUFDeEMsWUFBTVUsV0FBV21DLG1CQUFtQjdDLEtBQUtVLFFBQXhCLENBQWpCOztBQUVBLFlBQU1vQyxPQUFPQyxlQUFlLEtBQUs1QyxNQUFMLENBQVk2QyxjQUEzQixFQUEyQ3RDLFFBQTNDLEVBQXFEQyxLQUFyRCxFQUE0RCxLQUFLUixNQUFqRSxDQUFiO0FBQ0EsWUFBTVYsVUFBVTtBQUNkd0QsaUJBQVMsS0FBSzlDLE1BQUwsQ0FBWThDLE9BRFA7QUFFZEgsY0FBTUEsSUFGUTtBQUdkOUMsY0FBTSx1QkFBUSxPQUFSLEVBQWlCQSxJQUFqQjtBQUhRLE9BQWhCO0FBS0EsVUFBSSxLQUFLVCxPQUFMLENBQWFxRCxxQkFBakIsRUFBd0M7QUFDdEMsYUFBS3JELE9BQUwsQ0FBYXFELHFCQUFiLENBQW1DbkQsT0FBbkM7QUFDRCxPQUZELE1BRU87QUFDTCxhQUFLRixPQUFMLENBQWEyRCxRQUFiLENBQXNCLEtBQUtDLHdCQUFMLENBQThCMUQsT0FBOUIsQ0FBdEI7QUFDRDtBQUNGLEtBZEQ7QUFlRDs7QUFFRDs7Ozs7O0FBTUEyRCw2QkFBMkJwRCxJQUEzQixFQUFpQztBQUMvQixTQUFLRCxtQkFBTCxDQUF5QkMsSUFBekI7QUFDQSxXQUFPLEtBQUtHLE1BQUwsQ0FBWTRCLFFBQVosQ0FBcUJGLE1BQXJCLENBQTRCLE9BQTVCLEVBQXFDLEVBQUVuQixVQUFVVixLQUFLVSxRQUFqQixFQUFyQyxFQUFrRVYsSUFBbEUsQ0FBUDtBQUNEOztBQUVEcUQsMEJBQXdCM0MsUUFBeEIsRUFBa0M7QUFDaEMsV0FBTyxLQUFLK0IsZUFBTCxDQUFxQixFQUFDL0IsVUFBVUEsUUFBWCxFQUFyQixFQUEyQ1ksSUFBM0MsQ0FBaURnQyxLQUFELElBQVc7QUFDaEUsVUFBSSxDQUFDQSxLQUFELElBQVVBLE1BQU1wRCxhQUFwQixFQUFtQztBQUNqQyxjQUFNVSxTQUFOO0FBQ0Q7QUFDRCxhQUFPLEtBQUt3QywwQkFBTCxDQUFnQ0UsS0FBaEMsRUFBdUNoQyxJQUF2QyxDQUE0QyxNQUFNO0FBQ3ZELGFBQUtzQixxQkFBTCxDQUEyQlUsS0FBM0I7QUFDRCxPQUZNLENBQVA7QUFHRCxLQVBNLENBQVA7QUFRRDs7QUFFREMsd0JBQXNCYixLQUF0QixFQUE2QjtBQUMzQixVQUFNL0IsUUFBUSxFQUFFc0IsbUJBQW1CLCtCQUFhLEVBQWIsQ0FBckIsRUFBZDs7QUFFQSxRQUFJLEtBQUs5QixNQUFMLENBQVlnQyxjQUFaLElBQThCLEtBQUtoQyxNQUFMLENBQVlnQyxjQUFaLENBQTJCQywwQkFBN0QsRUFBeUY7QUFDdkZ6QixZQUFNMkIsNEJBQU4sR0FBcUNoQyxlQUFNQyxPQUFOLENBQWMsS0FBS0osTUFBTCxDQUFZcUQsbUNBQVosRUFBZCxDQUFyQztBQUNEOztBQUVELFdBQU8sS0FBS3JELE1BQUwsQ0FBWTRCLFFBQVosQ0FBcUJGLE1BQXJCLENBQTRCLE9BQTVCLEVBQXFDLEVBQUU0QixLQUFLLENBQUMsRUFBQ2YsS0FBRCxFQUFELEVBQVUsRUFBQ2hDLFVBQVVnQyxLQUFYLEVBQWtCQSxPQUFPLEVBQUNnQixTQUFTLEtBQVYsRUFBekIsRUFBVixDQUFQLEVBQXJDLEVBQXFHL0MsS0FBckcsRUFBNEcsRUFBNUcsRUFBZ0gsSUFBaEgsQ0FBUDtBQUNEOztBQUVEZ0QseUJBQXVCakIsS0FBdkIsRUFBOEI7QUFDNUIsUUFBSSxDQUFDLEtBQUtuRCxPQUFWLEVBQW1CO0FBQ2pCLFlBQU0sdURBQU47QUFDQTtBQUNEOztBQUVELFdBQU8sS0FBS2dFLHFCQUFMLENBQTJCYixLQUEzQixFQUNKcEIsSUFESSxDQUNDdEIsUUFBUTtBQUNaLFlBQU1XLFFBQVFrQyxtQkFBbUI3QyxLQUFLaUMsaUJBQXhCLENBQWQ7QUFDQSxZQUFNdkIsV0FBV21DLG1CQUFtQjdDLEtBQUtVLFFBQXhCLENBQWpCOztBQUVBLFlBQU1vQyxPQUFPQyxlQUFlLEtBQUs1QyxNQUFMLENBQVl5RCx1QkFBM0IsRUFBb0RsRCxRQUFwRCxFQUE4REMsS0FBOUQsRUFBcUUsS0FBS1IsTUFBMUUsQ0FBYjtBQUNBLFlBQU1WLFVBQVU7QUFDZHdELGlCQUFTLEtBQUs5QyxNQUFMLENBQVk4QyxPQURQO0FBRWRILGNBQU1BLElBRlE7QUFHZDlDLGNBQU0sdUJBQVEsT0FBUixFQUFpQkEsSUFBakI7QUFIUSxPQUFoQjs7QUFNQSxVQUFJLEtBQUtULE9BQUwsQ0FBYW9FLHNCQUFqQixFQUF5QztBQUN2QyxhQUFLcEUsT0FBTCxDQUFhb0Usc0JBQWIsQ0FBb0NsRSxPQUFwQztBQUNELE9BRkQsTUFFTztBQUNMLGFBQUtGLE9BQUwsQ0FBYTJELFFBQWIsQ0FBc0IsS0FBS1cseUJBQUwsQ0FBK0JwRSxPQUEvQixDQUF0QjtBQUNEOztBQUVELGFBQU9pQyxRQUFRQyxPQUFSLENBQWdCM0IsSUFBaEIsQ0FBUDtBQUNELEtBbkJJLENBQVA7QUFvQkQ7O0FBRUQ4RCxpQkFBZXBELFFBQWYsRUFBeUJDLEtBQXpCLEVBQWdDb0QsUUFBaEMsRUFBMEM7QUFDeEMsV0FBTyxLQUFLakMsdUJBQUwsQ0FBNkJwQixRQUE3QixFQUF1Q0MsS0FBdkMsRUFDSlcsSUFESSxDQUNDdEIsUUFBUWdFLG1CQUFtQmhFLEtBQUtpRSxRQUF4QixFQUFrQ0YsUUFBbEMsRUFBNEMsS0FBSzVELE1BQWpELENBRFQ7QUFFTDtBQUZLLEtBR0ptQixJQUhJLENBR0MsTUFBTSxLQUFLbkIsTUFBTCxDQUFZNEIsUUFBWixDQUFxQkYsTUFBckIsQ0FBNEIsT0FBNUIsRUFBcUMsRUFBQ25CLFFBQUQsRUFBckMsRUFBaUQ7QUFDM0R1Qix5QkFBbUIsRUFBQ2xCLE1BQU0sUUFBUCxFQUR3QztBQUUzRHVCLG9DQUE4QixFQUFDdkIsTUFBTSxRQUFQO0FBRjZCLEtBQWpELENBSFAsRUFNRG1ELEtBTkMsQ0FNTUMsS0FBRCxJQUFXO0FBQ25CLFVBQUlBLE1BQU1DLE9BQVYsRUFBbUI7QUFBRztBQUNwQixlQUFPMUMsUUFBUTJDLE1BQVIsQ0FBZUYsTUFBTUMsT0FBckIsQ0FBUDtBQUNELE9BRkQsTUFFTztBQUNMLGVBQU8xQyxRQUFRMkMsTUFBUixDQUFlRixLQUFmLENBQVA7QUFDRDtBQUNGLEtBWkksQ0FBUDtBQWFEOztBQUVEaEIsMkJBQXlCLEVBQUNMLElBQUQsRUFBTzlDLElBQVAsRUFBYWlELE9BQWIsRUFBekIsRUFBa0Q7QUFDaEQsVUFBTXFCLE9BQU8sWUFDVCxvREFEUyxHQUM4Q3RFLEtBQUt1RSxHQUFMLENBQVMsT0FBVCxDQUQ5QyxHQUNrRSxRQURsRSxHQUM2RXRCLE9BRDdFLEdBQ3VGLE1BRHZGLEdBRVQsRUFGUyxHQUdULDZCQUhTLEdBR3VCSCxJQUhwQztBQUlBLFVBQU0wQixLQUFLeEUsS0FBS3VFLEdBQUwsQ0FBUyxPQUFULENBQVg7QUFDQSxVQUFNRSxVQUFVLG1DQUFtQ3hCLE9BQW5EO0FBQ0EsV0FBTyxFQUFFcUIsSUFBRixFQUFRRSxFQUFSLEVBQVlDLE9BQVosRUFBUDtBQUNEOztBQUVEWiw0QkFBMEIsRUFBQ2YsSUFBRCxFQUFPOUMsSUFBUCxFQUFhaUQsT0FBYixFQUExQixFQUFtRDtBQUNqRCxVQUFNcUIsT0FBTyxZQUNULDJDQURTLEdBQ3FDckIsT0FEckMsSUFFUmpELEtBQUt1RSxHQUFMLENBQVMsVUFBVCxJQUF3Qix5QkFBeUJ2RSxLQUFLdUUsR0FBTCxDQUFTLFVBQVQsQ0FBekIsR0FBZ0QsSUFBeEUsR0FBZ0YsRUFGeEUsSUFFOEUsT0FGOUUsR0FHVCxFQUhTLEdBSVQsMkJBSlMsR0FJcUJ6QixJQUpsQztBQUtBLFVBQU0wQixLQUFLeEUsS0FBS3VFLEdBQUwsQ0FBUyxPQUFULEtBQXFCdkUsS0FBS3VFLEdBQUwsQ0FBUyxVQUFULENBQWhDO0FBQ0EsVUFBTUUsVUFBVyx3QkFBd0J4QixPQUF6QztBQUNBLFdBQU8sRUFBRXFCLElBQUYsRUFBUUUsRUFBUixFQUFZQyxPQUFaLEVBQVA7QUFDRDtBQTlOcUQ7O1FBQTNDckYsYyxHQUFBQSxjLEVBaU9iOztBQUNBLFNBQVM0RSxrQkFBVCxDQUE0QlUsTUFBNUIsRUFBb0NYLFFBQXBDLEVBQThDNUQsTUFBOUMsRUFBc0Q7QUFDcEQsU0FBT3lCLGVBQUtDLE1BQUwsQ0FBWTFCLE1BQVosRUFBb0JoQixLQUFLZ0MsTUFBTCxDQUFZaEIsTUFBWixDQUFwQixFQUF5QyxPQUF6QyxFQUFrRCxFQUFFOEQsVUFBVVMsTUFBWixFQUFsRCxFQUF3RTtBQUM3RVgsY0FBVUE7QUFEbUUsR0FBeEUsQ0FBUDtBQUdEOztBQUVELFNBQVNoQixjQUFULENBQXdCNEIsV0FBeEIsRUFBcUNqRSxRQUFyQyxFQUErQ0MsS0FBL0MsRUFBc0RSLE1BQXRELEVBQThEO0FBQzVELFFBQU15RSxtQkFBb0IsU0FBUWpFLEtBQU0sYUFBWUQsUUFBUyxFQUE3RDs7QUFFQSxNQUFJUCxPQUFPMEUsYUFBWCxFQUEwQjtBQUN4QixVQUFNQyx5QkFBeUJILFlBQVlJLE9BQVosQ0FBb0I1RSxPQUFPNkUsZUFBM0IsRUFBNEMsRUFBNUMsQ0FBL0I7O0FBRUEsV0FBUSxHQUFFN0UsT0FBTzBFLGFBQWMsU0FBUWhDLG1CQUFtQmlDLHNCQUFuQixDQUEyQyxJQUFHRixnQkFBaUIsRUFBdEc7QUFDRCxHQUpELE1BSU87QUFDTCxXQUFRLEdBQUVELFdBQVksSUFBR0MsZ0JBQWlCLEVBQTFDO0FBQ0Q7QUFDRjs7a0JBRWN4RixjIiwiZmlsZSI6IlVzZXJDb250cm9sbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tU3RyaW5nIH0gICAgZnJvbSAnLi4vY3J5cHRvVXRpbHMnO1xuaW1wb3J0IHsgaW5mbGF0ZSB9ICAgICAgICAgZnJvbSAnLi4vdHJpZ2dlcnMnO1xuaW1wb3J0IEFkYXB0YWJsZUNvbnRyb2xsZXIgZnJvbSAnLi9BZGFwdGFibGVDb250cm9sbGVyJztcbmltcG9ydCBNYWlsQWRhcHRlciAgICAgICAgIGZyb20gJy4uL0FkYXB0ZXJzL0VtYWlsL01haWxBZGFwdGVyJztcbmltcG9ydCByZXN0ICAgICAgICAgICAgICAgIGZyb20gJy4uL3Jlc3QnO1xuaW1wb3J0IFBhcnNlICAgICAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG5cbnZhciBSZXN0UXVlcnkgPSByZXF1aXJlKCcuLi9SZXN0UXVlcnknKTtcbnZhciBBdXRoID0gcmVxdWlyZSgnLi4vQXV0aCcpO1xuXG5leHBvcnQgY2xhc3MgVXNlckNvbnRyb2xsZXIgZXh0ZW5kcyBBZGFwdGFibGVDb250cm9sbGVyIHtcblxuICBjb25zdHJ1Y3RvcihhZGFwdGVyLCBhcHBJZCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoYWRhcHRlciwgYXBwSWQsIG9wdGlvbnMpO1xuICB9XG5cbiAgdmFsaWRhdGVBZGFwdGVyKGFkYXB0ZXIpIHtcbiAgICAvLyBBbGxvdyBubyBhZGFwdGVyXG4gICAgaWYgKCFhZGFwdGVyICYmICF0aGlzLnNob3VsZFZlcmlmeUVtYWlscykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzdXBlci52YWxpZGF0ZUFkYXB0ZXIoYWRhcHRlcik7XG4gIH1cblxuICBleHBlY3RlZEFkYXB0ZXJUeXBlKCkge1xuICAgIHJldHVybiBNYWlsQWRhcHRlcjtcbiAgfVxuXG4gIGdldCBzaG91bGRWZXJpZnlFbWFpbHMoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy52ZXJpZnlVc2VyRW1haWxzO1xuICB9XG5cbiAgc2V0RW1haWxWZXJpZnlUb2tlbih1c2VyKSB7XG4gICAgaWYgKHRoaXMuc2hvdWxkVmVyaWZ5RW1haWxzKSB7XG4gICAgICB1c2VyLl9lbWFpbF92ZXJpZnlfdG9rZW4gPSByYW5kb21TdHJpbmcoMjUpO1xuICAgICAgdXNlci5lbWFpbFZlcmlmaWVkID0gZmFsc2U7XG5cbiAgICAgIGlmICh0aGlzLmNvbmZpZy5lbWFpbFZlcmlmeVRva2VuVmFsaWRpdHlEdXJhdGlvbikge1xuICAgICAgICB1c2VyLl9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCA9IFBhcnNlLl9lbmNvZGUodGhpcy5jb25maWcuZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuRXhwaXJlc0F0KCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZlcmlmeUVtYWlsKHVzZXJuYW1lLCB0b2tlbikge1xuICAgIGlmICghdGhpcy5zaG91bGRWZXJpZnlFbWFpbHMpIHtcbiAgICAgIC8vIFRyeWluZyB0byB2ZXJpZnkgZW1haWwgd2hlbiBub3QgZW5hYmxlZFxuICAgICAgLy8gVE9ETzogQmV0dGVyIGVycm9yIGhlcmUuXG4gICAgICB0aHJvdyB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcXVlcnkgPSB7dXNlcm5hbWU6IHVzZXJuYW1lLCBfZW1haWxfdmVyaWZ5X3Rva2VuOiB0b2tlbn07XG4gICAgY29uc3QgdXBkYXRlRmllbGRzID0geyBlbWFpbFZlcmlmaWVkOiB0cnVlLCBfZW1haWxfdmVyaWZ5X3Rva2VuOiB7X19vcDogJ0RlbGV0ZSd9fTtcblxuICAgIC8vIGlmIHRoZSBlbWFpbCB2ZXJpZnkgdG9rZW4gbmVlZHMgdG8gYmUgdmFsaWRhdGVkIHRoZW5cbiAgICAvLyBhZGQgYWRkaXRpb25hbCBxdWVyeSBwYXJhbXMgYW5kIGFkZGl0aW9uYWwgZmllbGRzIHRoYXQgbmVlZCB0byBiZSB1cGRhdGVkXG4gICAgaWYgKHRoaXMuY29uZmlnLmVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uKSB7XG4gICAgICBxdWVyeS5lbWFpbFZlcmlmaWVkID0gZmFsc2U7XG4gICAgICBxdWVyeS5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQgPSB7ICRndDogUGFyc2UuX2VuY29kZShuZXcgRGF0ZSgpKSB9O1xuXG4gICAgICB1cGRhdGVGaWVsZHMuX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0ID0ge19fb3A6ICdEZWxldGUnfTtcbiAgICB9XG4gICAgY29uc3QgbWFzdGVyQXV0aCA9IEF1dGgubWFzdGVyKHRoaXMuY29uZmlnKTtcbiAgICB2YXIgY2hlY2tJZkFscmVhZHlWZXJpZmllZCA9IG5ldyBSZXN0UXVlcnkodGhpcy5jb25maWcsIEF1dGgubWFzdGVyKHRoaXMuY29uZmlnKSwgJ19Vc2VyJywge3VzZXJuYW1lOiB1c2VybmFtZSwgZW1haWxWZXJpZmllZDogdHJ1ZX0pO1xuICAgIHJldHVybiBjaGVja0lmQWxyZWFkeVZlcmlmaWVkLmV4ZWN1dGUoKS50aGVuKHJlc3VsdCA9PiB7XG4gICAgICBpZiAocmVzdWx0LnJlc3VsdHMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0LnJlc3VsdHMubGVuZ3RoWzBdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN0LnVwZGF0ZSh0aGlzLmNvbmZpZywgbWFzdGVyQXV0aCwgJ19Vc2VyJywgcXVlcnksIHVwZGF0ZUZpZWxkcyk7XG4gICAgfSk7XG4gIH1cblxuICBjaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSh1c2VybmFtZSwgdG9rZW4pIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCB7XG4gICAgICB1c2VybmFtZTogdXNlcm5hbWUsXG4gICAgICBfcGVyaXNoYWJsZV90b2tlbjogdG9rZW5cbiAgICB9LCB7bGltaXQ6IDF9KS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9IDEpIHtcbiAgICAgICAgdGhyb3cgdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kgJiYgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kucmVzZXRUb2tlblZhbGlkaXR5RHVyYXRpb24pIHtcbiAgICAgICAgbGV0IGV4cGlyZXNEYXRlID0gcmVzdWx0c1swXS5fcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0O1xuICAgICAgICBpZiAoZXhwaXJlc0RhdGUgJiYgZXhwaXJlc0RhdGUuX190eXBlID09ICdEYXRlJykge1xuICAgICAgICAgIGV4cGlyZXNEYXRlID0gbmV3IERhdGUoZXhwaXJlc0RhdGUuaXNvKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhwaXJlc0RhdGUgPCBuZXcgRGF0ZSgpKVxuICAgICAgICAgIHRocm93ICdUaGUgcGFzc3dvcmQgcmVzZXQgbGluayBoYXMgZXhwaXJlZCc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHRzWzBdO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0VXNlcklmTmVlZGVkKHVzZXIpIHtcbiAgICBpZiAodXNlci51c2VybmFtZSAmJiB1c2VyLmVtYWlsKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVzZXIpO1xuICAgIH1cbiAgICB2YXIgd2hlcmUgPSB7fTtcbiAgICBpZiAodXNlci51c2VybmFtZSkge1xuICAgICAgd2hlcmUudXNlcm5hbWUgPSB1c2VyLnVzZXJuYW1lO1xuICAgIH1cbiAgICBpZiAodXNlci5lbWFpbCkge1xuICAgICAgd2hlcmUuZW1haWwgPSB1c2VyLmVtYWlsO1xuICAgIH1cblxuICAgIHZhciBxdWVyeSA9IG5ldyBSZXN0UXVlcnkodGhpcy5jb25maWcsIEF1dGgubWFzdGVyKHRoaXMuY29uZmlnKSwgJ19Vc2VyJywgd2hlcmUpO1xuICAgIHJldHVybiBxdWVyeS5leGVjdXRlKCkudGhlbihmdW5jdGlvbihyZXN1bHQpe1xuICAgICAgaWYgKHJlc3VsdC5yZXN1bHRzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQucmVzdWx0c1swXTtcbiAgICB9KVxuICB9XG5cbiAgc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHVzZXIpIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkVmVyaWZ5RW1haWxzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHRva2VuID0gZW5jb2RlVVJJQ29tcG9uZW50KHVzZXIuX2VtYWlsX3ZlcmlmeV90b2tlbik7XG4gICAgLy8gV2UgbWF5IG5lZWQgdG8gZmV0Y2ggdGhlIHVzZXIgaW4gY2FzZSBvZiB1cGRhdGUgZW1haWxcbiAgICB0aGlzLmdldFVzZXJJZk5lZWRlZCh1c2VyKS50aGVuKCh1c2VyKSA9PiB7XG4gICAgICBjb25zdCB1c2VybmFtZSA9IGVuY29kZVVSSUNvbXBvbmVudCh1c2VyLnVzZXJuYW1lKTtcblxuICAgICAgY29uc3QgbGluayA9IGJ1aWxkRW1haWxMaW5rKHRoaXMuY29uZmlnLnZlcmlmeUVtYWlsVVJMLCB1c2VybmFtZSwgdG9rZW4sIHRoaXMuY29uZmlnKTtcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgIGFwcE5hbWU6IHRoaXMuY29uZmlnLmFwcE5hbWUsXG4gICAgICAgIGxpbms6IGxpbmssXG4gICAgICAgIHVzZXI6IGluZmxhdGUoJ19Vc2VyJywgdXNlciksXG4gICAgICB9O1xuICAgICAgaWYgKHRoaXMuYWRhcHRlci5zZW5kVmVyaWZpY2F0aW9uRW1haWwpIHtcbiAgICAgICAgdGhpcy5hZGFwdGVyLnNlbmRWZXJpZmljYXRpb25FbWFpbChvcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWRhcHRlci5zZW5kTWFpbCh0aGlzLmRlZmF1bHRWZXJpZmljYXRpb25FbWFpbChvcHRpb25zKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVnZW5lcmF0ZXMgdGhlIGdpdmVuIHVzZXIncyBlbWFpbCB2ZXJpZmljYXRpb24gdG9rZW5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICByZWdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbih1c2VyKSB7XG4gICAgdGhpcy5zZXRFbWFpbFZlcmlmeVRva2VuKHVzZXIpO1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywgeyB1c2VybmFtZTogdXNlci51c2VybmFtZSB9LCB1c2VyKTtcbiAgfVxuXG4gIHJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHVzZXJuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VXNlcklmTmVlZGVkKHt1c2VybmFtZTogdXNlcm5hbWV9KS50aGVuKChhVXNlcikgPT4ge1xuICAgICAgaWYgKCFhVXNlciB8fCBhVXNlci5lbWFpbFZlcmlmaWVkKSB7XG4gICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnJlZ2VuZXJhdGVFbWFpbFZlcmlmeVRva2VuKGFVc2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zZW5kVmVyaWZpY2F0aW9uRW1haWwoYVVzZXIpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBzZXRQYXNzd29yZFJlc2V0VG9rZW4oZW1haWwpIHtcbiAgICBjb25zdCB0b2tlbiA9IHsgX3BlcmlzaGFibGVfdG9rZW46IHJhbmRvbVN0cmluZygyNSkgfTtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeSAmJiB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5yZXNldFRva2VuVmFsaWRpdHlEdXJhdGlvbikge1xuICAgICAgdG9rZW4uX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCA9IFBhcnNlLl9lbmNvZGUodGhpcy5jb25maWcuZ2VuZXJhdGVQYXNzd29yZFJlc2V0VG9rZW5FeHBpcmVzQXQoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLnVwZGF0ZSgnX1VzZXInLCB7ICRvcjogW3tlbWFpbH0sIHt1c2VybmFtZTogZW1haWwsIGVtYWlsOiB7JGV4aXN0czogZmFsc2V9fV0gfSwgdG9rZW4sIHt9LCB0cnVlKVxuICB9XG5cbiAgc2VuZFBhc3N3b3JkUmVzZXRFbWFpbChlbWFpbCkge1xuICAgIGlmICghdGhpcy5hZGFwdGVyKSB7XG4gICAgICB0aHJvdyBcIlRyeWluZyB0byBzZW5kIGEgcmVzZXQgcGFzc3dvcmQgYnV0IG5vIGFkYXB0ZXIgaXMgc2V0XCI7XG4gICAgICAvLyAgVE9ETzogTm8gYWRhcHRlcj9cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zZXRQYXNzd29yZFJlc2V0VG9rZW4oZW1haWwpXG4gICAgICAudGhlbih1c2VyID0+IHtcbiAgICAgICAgY29uc3QgdG9rZW4gPSBlbmNvZGVVUklDb21wb25lbnQodXNlci5fcGVyaXNoYWJsZV90b2tlbik7XG4gICAgICAgIGNvbnN0IHVzZXJuYW1lID0gZW5jb2RlVVJJQ29tcG9uZW50KHVzZXIudXNlcm5hbWUpO1xuXG4gICAgICAgIGNvbnN0IGxpbmsgPSBidWlsZEVtYWlsTGluayh0aGlzLmNvbmZpZy5yZXF1ZXN0UmVzZXRQYXNzd29yZFVSTCwgdXNlcm5hbWUsIHRva2VuLCB0aGlzLmNvbmZpZyk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgYXBwTmFtZTogdGhpcy5jb25maWcuYXBwTmFtZSxcbiAgICAgICAgICBsaW5rOiBsaW5rLFxuICAgICAgICAgIHVzZXI6IGluZmxhdGUoJ19Vc2VyJywgdXNlciksXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMuYWRhcHRlci5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKSB7XG4gICAgICAgICAgdGhpcy5hZGFwdGVyLnNlbmRQYXNzd29yZFJlc2V0RW1haWwob3B0aW9ucyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5hZGFwdGVyLnNlbmRNYWlsKHRoaXMuZGVmYXVsdFJlc2V0UGFzc3dvcmRFbWFpbChvcHRpb25zKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVzZXIpO1xuICAgICAgfSk7XG4gIH1cblxuICB1cGRhdGVQYXNzd29yZCh1c2VybmFtZSwgdG9rZW4sIHBhc3N3b3JkKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hlY2tSZXNldFRva2VuVmFsaWRpdHkodXNlcm5hbWUsIHRva2VuKVxuICAgICAgLnRoZW4odXNlciA9PiB1cGRhdGVVc2VyUGFzc3dvcmQodXNlci5vYmplY3RJZCwgcGFzc3dvcmQsIHRoaXMuY29uZmlnKSlcbiAgICAgIC8vIGNsZWFyIHJlc2V0IHBhc3N3b3JkIHRva2VuXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmNvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywge3VzZXJuYW1lfSwge1xuICAgICAgICBfcGVyaXNoYWJsZV90b2tlbjoge19fb3A6ICdEZWxldGUnfSxcbiAgICAgICAgX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdDoge19fb3A6ICdEZWxldGUnfVxuICAgICAgfSkpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBpZiAoZXJyb3IubWVzc2FnZSkgeyAgLy8gaW4gY2FzZSBvZiBQYXJzZS5FcnJvciwgZmFpbCB3aXRoIHRoZSBlcnJvciBtZXNzYWdlIG9ubHlcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBkZWZhdWx0VmVyaWZpY2F0aW9uRW1haWwoe2xpbmssIHVzZXIsIGFwcE5hbWUsIH0pIHtcbiAgICBjb25zdCB0ZXh0ID0gXCJIaSxcXG5cXG5cIiArXG4gICAgICAgIFwiWW91IGFyZSBiZWluZyBhc2tlZCB0byBjb25maXJtIHRoZSBlLW1haWwgYWRkcmVzcyBcIiArIHVzZXIuZ2V0KFwiZW1haWxcIikgKyBcIiB3aXRoIFwiICsgYXBwTmFtZSArIFwiXFxuXFxuXCIgK1xuICAgICAgICBcIlwiICtcbiAgICAgICAgXCJDbGljayBoZXJlIHRvIGNvbmZpcm0gaXQ6XFxuXCIgKyBsaW5rO1xuICAgIGNvbnN0IHRvID0gdXNlci5nZXQoXCJlbWFpbFwiKTtcbiAgICBjb25zdCBzdWJqZWN0ID0gJ1BsZWFzZSB2ZXJpZnkgeW91ciBlLW1haWwgZm9yICcgKyBhcHBOYW1lO1xuICAgIHJldHVybiB7IHRleHQsIHRvLCBzdWJqZWN0IH07XG4gIH1cblxuICBkZWZhdWx0UmVzZXRQYXNzd29yZEVtYWlsKHtsaW5rLCB1c2VyLCBhcHBOYW1lLCB9KSB7XG4gICAgY29uc3QgdGV4dCA9IFwiSGksXFxuXFxuXCIgK1xuICAgICAgICBcIllvdSByZXF1ZXN0ZWQgdG8gcmVzZXQgeW91ciBwYXNzd29yZCBmb3IgXCIgKyBhcHBOYW1lICtcbiAgICAgICAgKHVzZXIuZ2V0KCd1c2VybmFtZScpID8gKFwiICh5b3VyIHVzZXJuYW1lIGlzICdcIiArIHVzZXIuZ2V0KCd1c2VybmFtZScpICsgXCInKVwiKSA6IFwiXCIpICsgXCIuXFxuXFxuXCIgK1xuICAgICAgICBcIlwiICtcbiAgICAgICAgXCJDbGljayBoZXJlIHRvIHJlc2V0IGl0OlxcblwiICsgbGluaztcbiAgICBjb25zdCB0byA9IHVzZXIuZ2V0KFwiZW1haWxcIikgfHwgdXNlci5nZXQoJ3VzZXJuYW1lJyk7XG4gICAgY29uc3Qgc3ViamVjdCA9ICAnUGFzc3dvcmQgUmVzZXQgZm9yICcgKyBhcHBOYW1lO1xuICAgIHJldHVybiB7IHRleHQsIHRvLCBzdWJqZWN0IH07XG4gIH1cbn1cblxuLy8gTWFyayB0aGlzIHByaXZhdGVcbmZ1bmN0aW9uIHVwZGF0ZVVzZXJQYXNzd29yZCh1c2VySWQsIHBhc3N3b3JkLCBjb25maWcpIHtcbiAgcmV0dXJuIHJlc3QudXBkYXRlKGNvbmZpZywgQXV0aC5tYXN0ZXIoY29uZmlnKSwgJ19Vc2VyJywgeyBvYmplY3RJZDogdXNlcklkIH0sIHtcbiAgICBwYXNzd29yZDogcGFzc3dvcmRcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkRW1haWxMaW5rKGRlc3RpbmF0aW9uLCB1c2VybmFtZSwgdG9rZW4sIGNvbmZpZykge1xuICBjb25zdCB1c2VybmFtZUFuZFRva2VuID0gYHRva2VuPSR7dG9rZW59JnVzZXJuYW1lPSR7dXNlcm5hbWV9YFxuXG4gIGlmIChjb25maWcucGFyc2VGcmFtZVVSTCkge1xuICAgIGNvbnN0IGRlc3RpbmF0aW9uV2l0aG91dEhvc3QgPSBkZXN0aW5hdGlvbi5yZXBsYWNlKGNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwsICcnKTtcblxuICAgIHJldHVybiBgJHtjb25maWcucGFyc2VGcmFtZVVSTH0/bGluaz0ke2VuY29kZVVSSUNvbXBvbmVudChkZXN0aW5hdGlvbldpdGhvdXRIb3N0KX0mJHt1c2VybmFtZUFuZFRva2VufWA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGAke2Rlc3RpbmF0aW9ufT8ke3VzZXJuYW1lQW5kVG9rZW59YDtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBVc2VyQ29udHJvbGxlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Controllers/index.js b/lib/Controllers/index.js index 2d2a6dfb88..a1996308f7 100644 --- a/lib/Controllers/index.js +++ b/lib/Controllers/index.js @@ -140,7 +140,8 @@ function getFilesController(options) { appId, databaseURI, filesAdapter, - databaseAdapter + databaseAdapter, + preserveFileName } = options; if (!filesAdapter && databaseAdapter) { throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.'; @@ -148,7 +149,7 @@ function getFilesController(options) { const filesControllerAdapter = (0, _AdapterLoader.loadAdapter)(filesAdapter, () => { return new _GridStoreAdapter.GridStoreAdapter(databaseURI); }); - return new _FilesController.FilesController(filesControllerAdapter, appId); + return new _FilesController.FilesController(filesControllerAdapter, appId, { preserveFileName }); } function getUserController(options) { @@ -279,4 +280,5 @@ function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions) { mongoOptions: databaseOptions }); } -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9pbmRleC5qcyJdLCJuYW1lcyI6WyJnZXRDb250cm9sbGVycyIsImdldExvZ2dlckNvbnRyb2xsZXIiLCJnZXRGaWxlc0NvbnRyb2xsZXIiLCJnZXRVc2VyQ29udHJvbGxlciIsImdldENhY2hlQ29udHJvbGxlciIsImdldEFuYWx5dGljc0NvbnRyb2xsZXIiLCJnZXRMaXZlUXVlcnlDb250cm9sbGVyIiwiZ2V0RGF0YWJhc2VDb250cm9sbGVyIiwiZ2V0SG9va3NDb250cm9sbGVyIiwiZ2V0UHVzaENvbnRyb2xsZXIiLCJnZXRBdXRoRGF0YU1hbmFnZXIiLCJnZXREYXRhYmFzZUFkYXB0ZXIiLCJvcHRpb25zIiwibG9nZ2VyQ29udHJvbGxlciIsImZpbGVzQ29udHJvbGxlciIsInVzZXJDb250cm9sbGVyIiwicHVzaENvbnRyb2xsZXIiLCJoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCIsImhhc1B1c2hTdXBwb3J0IiwicHVzaENvbnRyb2xsZXJRdWV1ZSIsInB1c2hXb3JrZXIiLCJjYWNoZUNvbnRyb2xsZXIiLCJhbmFseXRpY3NDb250cm9sbGVyIiwibGl2ZVF1ZXJ5Q29udHJvbGxlciIsImRhdGFiYXNlQ29udHJvbGxlciIsImhvb2tzQ29udHJvbGxlciIsImF1dGhEYXRhTWFuYWdlciIsImFwcElkIiwianNvbkxvZ3MiLCJsb2dzRm9sZGVyIiwidmVyYm9zZSIsImxvZ0xldmVsIiwic2lsZW50IiwibG9nZ2VyQWRhcHRlciIsImxvZ2dlck9wdGlvbnMiLCJsb2dnZXJDb250cm9sbGVyQWRhcHRlciIsIldpbnN0b25Mb2dnZXJBZGFwdGVyIiwiTG9nZ2VyQ29udHJvbGxlciIsImRhdGFiYXNlVVJJIiwiZmlsZXNBZGFwdGVyIiwiZGF0YWJhc2VBZGFwdGVyIiwicHJlc2VydmVGaWxlTmFtZSIsImZpbGVzQ29udHJvbGxlckFkYXB0ZXIiLCJHcmlkU3RvcmVBZGFwdGVyIiwiRmlsZXNDb250cm9sbGVyIiwiZW1haWxBZGFwdGVyIiwidmVyaWZ5VXNlckVtYWlscyIsImVtYWlsQ29udHJvbGxlckFkYXB0ZXIiLCJVc2VyQ29udHJvbGxlciIsImNhY2hlQWRhcHRlciIsImNhY2hlVFRMIiwiY2FjaGVNYXhTaXplIiwiY2FjaGVDb250cm9sbGVyQWRhcHRlciIsIkluTWVtb3J5Q2FjaGVBZGFwdGVyIiwidHRsIiwibWF4U2l6ZSIsIkNhY2hlQ29udHJvbGxlciIsImFuYWx5dGljc0FkYXB0ZXIiLCJhbmFseXRpY3NDb250cm9sbGVyQWRhcHRlciIsIkFuYWx5dGljc0FkYXB0ZXIiLCJBbmFseXRpY3NDb250cm9sbGVyIiwiTGl2ZVF1ZXJ5Q29udHJvbGxlciIsImxpdmVRdWVyeSIsImRhdGFiYXNlT3B0aW9ucyIsImNvbGxlY3Rpb25QcmVmaXgiLCJzY2hlbWFDYWNoZVRUTCIsImVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlIiwiZGVmYXVsdHMiLCJEYXRhYmFzZUNvbnRyb2xsZXIiLCJTY2hlbWFDYWNoZSIsIndlYmhvb2tLZXkiLCJIb29rc0NvbnRyb2xsZXIiLCJzY2hlZHVsZWRQdXNoIiwicHVzaCIsInB1c2hPcHRpb25zIiwiT2JqZWN0IiwiYXNzaWduIiwicHVzaFF1ZXVlT3B0aW9ucyIsInF1ZXVlT3B0aW9ucyIsInB1c2hBZGFwdGVyIiwiYWRhcHRlciIsIlBhcnNlUHVzaEFkYXB0ZXIiLCJQdXNoQ29udHJvbGxlciIsImRpc2FibGVQdXNoV29ya2VyIiwiUHVzaFF1ZXVlIiwiUHVzaFdvcmtlciIsImF1dGgiLCJlbmFibGVBbm9ueW1vdXNVc2VycyIsInByb3RvY29sIiwicGFyc2VkVVJJIiwidXJsIiwicGFyc2UiLCJ0b0xvd2VyQ2FzZSIsImUiLCJQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyIiwidXJpIiwiTW9uZ29TdG9yYWdlQWRhcHRlciIsIm1vbmdvT3B0aW9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7UUE0QmdCQSxjLEdBQUFBLGM7UUFtQ0FDLG1CLEdBQUFBLG1CO1FBZUFDLGtCLEdBQUFBLGtCO1FBaUJBQyxp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QUtGO0FBQ0UsYUFBTyxJQUFJaUMsNkJBQUosQ0FBd0I7QUFDN0JELGFBQUt6RCxXQUR3QjtBQUU3QjBCLHdCQUY2QjtBQUc3QmlDLHNCQUFjbEM7QUFIZSxPQUF4QixDQUFQO0FBUkY7QUFjRCIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhdXRoRGF0YU1hbmFnZXIgICAgICAgICAgZnJvbSAnLi4vQWRhcHRlcnMvQXV0aCc7XG5pbXBvcnQgeyBQYXJzZVNlcnZlck9wdGlvbnMgfSAgIGZyb20gJy4uL09wdGlvbnMnO1xuaW1wb3J0IHsgbG9hZEFkYXB0ZXIgfSAgICAgICAgICBmcm9tICcuLi9BZGFwdGVycy9BZGFwdGVyTG9hZGVyJztcbmltcG9ydCBkZWZhdWx0cyAgICAgICAgICAgICAgICAgZnJvbSAnLi4vZGVmYXVsdHMnO1xuaW1wb3J0IHVybCAgICAgICAgICAgICAgICAgICAgICBmcm9tICd1cmwnO1xuLy8gQ29udHJvbGxlcnNcbmltcG9ydCB7IExvZ2dlckNvbnRyb2xsZXIgfSAgICAgZnJvbSAnLi9Mb2dnZXJDb250cm9sbGVyJztcbmltcG9ydCB7IEZpbGVzQ29udHJvbGxlciB9ICAgICAgZnJvbSAnLi9GaWxlc0NvbnRyb2xsZXInO1xuaW1wb3J0IHsgSG9va3NDb250cm9sbGVyIH0gICAgICBmcm9tICcuL0hvb2tzQ29udHJvbGxlcic7XG5pbXBvcnQgeyBVc2VyQ29udHJvbGxlciB9ICAgICAgIGZyb20gJy4vVXNlckNvbnRyb2xsZXInO1xuaW1wb3J0IHsgQ2FjaGVDb250cm9sbGVyIH0gICAgICBmcm9tICcuL0NhY2hlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBMaXZlUXVlcnlDb250cm9sbGVyIH0gIGZyb20gJy4vTGl2ZVF1ZXJ5Q29udHJvbGxlcic7XG5pbXBvcnQgeyBBbmFseXRpY3NDb250cm9sbGVyIH0gIGZyb20gJy4vQW5hbHl0aWNzQ29udHJvbGxlcic7XG5pbXBvcnQgeyBQdXNoQ29udHJvbGxlciB9ICAgICAgIGZyb20gJy4vUHVzaENvbnRyb2xsZXInO1xuaW1wb3J0IHsgUHVzaFF1ZXVlIH0gICAgICAgICAgICBmcm9tICcuLi9QdXNoL1B1c2hRdWV1ZSc7XG5pbXBvcnQgeyBQdXNoV29ya2VyIH0gICAgICAgICAgIGZyb20gJy4uL1B1c2gvUHVzaFdvcmtlcic7XG5pbXBvcnQgRGF0YWJhc2VDb250cm9sbGVyICAgICAgIGZyb20gJy4vRGF0YWJhc2VDb250cm9sbGVyJztcbmltcG9ydCBTY2hlbWFDYWNoZSAgICAgICAgICAgICAgZnJvbSAnLi9TY2hlbWFDYWNoZSc7XG5cbi8vIEFkYXB0ZXJzXG5pbXBvcnQgeyBHcmlkU3RvcmVBZGFwdGVyIH0gICAgIGZyb20gJy4uL0FkYXB0ZXJzL0ZpbGVzL0dyaWRTdG9yZUFkYXB0ZXInO1xuaW1wb3J0IHsgV2luc3RvbkxvZ2dlckFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9Mb2dnZXIvV2luc3RvbkxvZ2dlckFkYXB0ZXInO1xuaW1wb3J0IHsgSW5NZW1vcnlDYWNoZUFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9DYWNoZS9Jbk1lbW9yeUNhY2hlQWRhcHRlcic7XG5pbXBvcnQgeyBBbmFseXRpY3NBZGFwdGVyIH0gICAgIGZyb20gJy4uL0FkYXB0ZXJzL0FuYWx5dGljcy9BbmFseXRpY3NBZGFwdGVyJztcbmltcG9ydCBNb25nb1N0b3JhZ2VBZGFwdGVyICAgICAgZnJvbSAnLi4vQWRhcHRlcnMvU3RvcmFnZS9Nb25nby9Nb25nb1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCBQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyICAgZnJvbSAnLi4vQWRhcHRlcnMvU3RvcmFnZS9Qb3N0Z3Jlcy9Qb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCBQYXJzZVB1c2hBZGFwdGVyICAgICAgICAgZnJvbSAnQHBhcnNlL3B1c2gtYWRhcHRlcic7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb250cm9sbGVycyhvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgY29uc3QgbG9nZ2VyQ29udHJvbGxlciA9IGdldExvZ2dlckNvbnRyb2xsZXIob3B0aW9ucyk7XG4gIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGdldEZpbGVzQ29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3QgdXNlckNvbnRyb2xsZXIgPSBnZXRVc2VyQ29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3Qge1xuICAgIHB1c2hDb250cm9sbGVyLFxuICAgIGhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0LFxuICAgIGhhc1B1c2hTdXBwb3J0LFxuICAgIHB1c2hDb250cm9sbGVyUXVldWUsXG4gICAgcHVzaFdvcmtlclxuICB9ID0gZ2V0UHVzaENvbnRyb2xsZXIob3B0aW9ucyk7XG4gIGNvbnN0IGNhY2hlQ29udHJvbGxlciA9IGdldENhY2hlQ29udHJvbGxlcihvcHRpb25zKTtcbiAgY29uc3QgYW5hbHl0aWNzQ29udHJvbGxlciA9IGdldEFuYWx5dGljc0NvbnRyb2xsZXIob3B0aW9ucyk7XG4gIGNvbnN0IGxpdmVRdWVyeUNvbnRyb2xsZXIgPSBnZXRMaXZlUXVlcnlDb250cm9sbGVyKG9wdGlvbnMpO1xuICBjb25zdCBkYXRhYmFzZUNvbnRyb2xsZXIgPSBnZXREYXRhYmFzZUNvbnRyb2xsZXIob3B0aW9ucywgY2FjaGVDb250cm9sbGVyKTtcbiAgY29uc3QgaG9va3NDb250cm9sbGVyID0gZ2V0SG9va3NDb250cm9sbGVyKG9wdGlvbnMsIGRhdGFiYXNlQ29udHJvbGxlcik7XG4gIGNvbnN0IGF1dGhEYXRhTWFuYWdlciA9IGdldEF1dGhEYXRhTWFuYWdlcihvcHRpb25zKTtcbiAgcmV0dXJuIHtcbiAgICBsb2dnZXJDb250cm9sbGVyLFxuICAgIGZpbGVzQ29udHJvbGxlcixcbiAgICB1c2VyQ29udHJvbGxlcixcbiAgICBwdXNoQ29udHJvbGxlcixcbiAgICBoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCxcbiAgICBoYXNQdXNoU3VwcG9ydCxcbiAgICBwdXNoV29ya2VyLFxuICAgIHB1c2hDb250cm9sbGVyUXVldWUsXG4gICAgYW5hbHl0aWNzQ29udHJvbGxlcixcbiAgICBjYWNoZUNvbnRyb2xsZXIsXG4gICAgbGl2ZVF1ZXJ5Q29udHJvbGxlcixcbiAgICBkYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgaG9va3NDb250cm9sbGVyLFxuICAgIGF1dGhEYXRhTWFuYWdlcixcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvZ2dlckNvbnRyb2xsZXIob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKTogTG9nZ2VyQ29udHJvbGxlciB7XG4gIGNvbnN0IHtcbiAgICBhcHBJZCxcbiAgICBqc29uTG9ncyxcbiAgICBsb2dzRm9sZGVyLFxuICAgIHZlcmJvc2UsXG4gICAgbG9nTGV2ZWwsXG4gICAgc2lsZW50LFxuICAgIGxvZ2dlckFkYXB0ZXIsXG4gIH0gPSBvcHRpb25zO1xuICBjb25zdCBsb2dnZXJPcHRpb25zID0geyBqc29uTG9ncywgbG9nc0ZvbGRlciwgdmVyYm9zZSwgbG9nTGV2ZWwsIHNpbGVudCB9O1xuICBjb25zdCBsb2dnZXJDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKGxvZ2dlckFkYXB0ZXIsIFdpbnN0b25Mb2dnZXJBZGFwdGVyLCBsb2dnZXJPcHRpb25zKTtcbiAgcmV0dXJuIG5ldyBMb2dnZXJDb250cm9sbGVyKGxvZ2dlckNvbnRyb2xsZXJBZGFwdGVyLCBhcHBJZCwgbG9nZ2VyT3B0aW9ucyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGaWxlc0NvbnRyb2xsZXIob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKTogRmlsZXNDb250cm9sbGVyIHtcbiAgY29uc3Qge1xuICAgIGFwcElkLFxuICAgIGRhdGFiYXNlVVJJLFxuICAgIGZpbGVzQWRhcHRlcixcbiAgICBkYXRhYmFzZUFkYXB0ZXIsXG4gICAgcHJlc2VydmVGaWxlTmFtZSxcbiAgfSA9IG9wdGlvbnM7XG4gIGlmICghZmlsZXNBZGFwdGVyICYmIGRhdGFiYXNlQWRhcHRlcikge1xuICAgIHRocm93ICdXaGVuIHVzaW5nIGFuIGV4cGxpY2l0IGRhdGFiYXNlIGFkYXB0ZXIsIHlvdSBtdXN0IGFsc28gdXNlIGFuIGV4cGxpY2l0IGZpbGVzQWRhcHRlci4nO1xuICB9XG4gIGNvbnN0IGZpbGVzQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihmaWxlc0FkYXB0ZXIsICgpID0+IHtcbiAgICByZXR1cm4gbmV3IEdyaWRTdG9yZUFkYXB0ZXIoZGF0YWJhc2VVUkkpO1xuICB9KTtcbiAgcmV0dXJuIG5ldyBGaWxlc0NvbnRyb2xsZXIoZmlsZXNDb250cm9sbGVyQWRhcHRlciwgYXBwSWQsIHsgcHJlc2VydmVGaWxlTmFtZSB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVzZXJDb250cm9sbGVyKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucyk6IFVzZXJDb250cm9sbGVyIHtcbiAgY29uc3Qge1xuICAgIGFwcElkLFxuICAgIGVtYWlsQWRhcHRlcixcbiAgICB2ZXJpZnlVc2VyRW1haWxzLFxuICB9ID0gb3B0aW9ucztcbiAgY29uc3QgZW1haWxDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKGVtYWlsQWRhcHRlcik7XG4gIHJldHVybiBuZXcgVXNlckNvbnRyb2xsZXIoZW1haWxDb250cm9sbGVyQWRhcHRlciwgYXBwSWQsIHsgdmVyaWZ5VXNlckVtYWlscyB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENhY2hlQ29udHJvbGxlcihvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpOiBDYWNoZUNvbnRyb2xsZXIge1xuICBjb25zdCB7XG4gICAgYXBwSWQsXG4gICAgY2FjaGVBZGFwdGVyLFxuICAgIGNhY2hlVFRMLFxuICAgIGNhY2hlTWF4U2l6ZSxcbiAgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGNhY2hlQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihjYWNoZUFkYXB0ZXIsIEluTWVtb3J5Q2FjaGVBZGFwdGVyLCB7YXBwSWQ6IGFwcElkLCB0dGw6IGNhY2hlVFRMLCBtYXhTaXplOiBjYWNoZU1heFNpemUgfSk7XG4gIHJldHVybiBuZXcgQ2FjaGVDb250cm9sbGVyKGNhY2hlQ29udHJvbGxlckFkYXB0ZXIsIGFwcElkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFuYWx5dGljc0NvbnRyb2xsZXIob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKTogQW5hbHl0aWNzQ29udHJvbGxlciB7XG4gIGNvbnN0IHtcbiAgICBhbmFseXRpY3NBZGFwdGVyLFxuICB9ID0gb3B0aW9ucztcbiAgY29uc3QgYW5hbHl0aWNzQ29udHJvbGxlckFkYXB0ZXIgPSBsb2FkQWRhcHRlcihhbmFseXRpY3NBZGFwdGVyLCBBbmFseXRpY3NBZGFwdGVyKTtcbiAgcmV0dXJuIG5ldyBBbmFseXRpY3NDb250cm9sbGVyKGFuYWx5dGljc0NvbnRyb2xsZXJBZGFwdGVyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExpdmVRdWVyeUNvbnRyb2xsZXIob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKTogTGl2ZVF1ZXJ5Q29udHJvbGxlciB7XG4gIHJldHVybiBuZXcgTGl2ZVF1ZXJ5Q29udHJvbGxlcihvcHRpb25zLmxpdmVRdWVyeSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhYmFzZUNvbnRyb2xsZXIob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zLCBjYWNoZUNvbnRyb2xsZXI6IENhY2hlQ29udHJvbGxlcik6IERhdGFiYXNlQ29udHJvbGxlciB7XG4gIGNvbnN0IHtcbiAgICBkYXRhYmFzZVVSSSxcbiAgICBkYXRhYmFzZU9wdGlvbnMsXG4gICAgY29sbGVjdGlvblByZWZpeCxcbiAgICBzY2hlbWFDYWNoZVRUTCxcbiAgICBlbmFibGVTaW5nbGVTY2hlbWFDYWNoZSxcbiAgfSA9IG9wdGlvbnM7XG4gIGxldCB7XG4gICAgZGF0YWJhc2VBZGFwdGVyXG4gIH0gPSBvcHRpb25zO1xuICBpZiAoKGRhdGFiYXNlT3B0aW9ucyB8fCAoZGF0YWJhc2VVUkkgJiYgZGF0YWJhc2VVUkkgIT09IGRlZmF1bHRzLmRhdGFiYXNlVVJJKSB8fCBjb2xsZWN0aW9uUHJlZml4ICE9PSBkZWZhdWx0cy5jb2xsZWN0aW9uUHJlZml4KSAmJiBkYXRhYmFzZUFkYXB0ZXIpIHtcbiAgICB0aHJvdyAnWW91IGNhbm5vdCBzcGVjaWZ5IGJvdGggYSBkYXRhYmFzZUFkYXB0ZXIgYW5kIGEgZGF0YWJhc2VVUkkvZGF0YWJhc2VPcHRpb25zL2NvbGxlY3Rpb25QcmVmaXguJztcbiAgfSBlbHNlIGlmICghZGF0YWJhc2VBZGFwdGVyKSB7XG4gICAgZGF0YWJhc2VBZGFwdGVyID0gZ2V0RGF0YWJhc2VBZGFwdGVyKGRhdGFiYXNlVVJJLCBjb2xsZWN0aW9uUHJlZml4LCBkYXRhYmFzZU9wdGlvbnMpXG4gIH0gZWxzZSB7XG4gICAgZGF0YWJhc2VBZGFwdGVyID0gbG9hZEFkYXB0ZXIoZGF0YWJhc2VBZGFwdGVyKVxuICB9XG4gIHJldHVybiBuZXcgRGF0YWJhc2VDb250cm9sbGVyKGRhdGFiYXNlQWRhcHRlciwgbmV3IFNjaGVtYUNhY2hlKGNhY2hlQ29udHJvbGxlciwgc2NoZW1hQ2FjaGVUVEwsIGVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRIb29rc0NvbnRyb2xsZXIob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zLCBkYXRhYmFzZUNvbnRyb2xsZXI6IERhdGFiYXNlQ29udHJvbGxlcik6IEhvb2tzQ29udHJvbGxlciB7XG4gIGNvbnN0IHtcbiAgICBhcHBJZCxcbiAgICB3ZWJob29rS2V5LFxuICB9ID0gb3B0aW9ucztcbiAgcmV0dXJuIG5ldyBIb29rc0NvbnRyb2xsZXIoYXBwSWQsIGRhdGFiYXNlQ29udHJvbGxlciwgd2ViaG9va0tleSk7XG59XG5cbmludGVyZmFjZSBQdXNoQ29udHJvbGxpbmcge1xuICBwdXNoQ29udHJvbGxlcjogUHVzaENvbnRyb2xsZXIsXG4gIGhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0OiBib29sZWFuLFxuICBwdXNoQ29udHJvbGxlclF1ZXVlOiBQdXNoUXVldWUsXG4gIHB1c2hXb3JrZXI6IFB1c2hXb3JrZXJcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFB1c2hDb250cm9sbGVyKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucyk6IFB1c2hDb250cm9sbGluZyB7XG4gIGNvbnN0IHtcbiAgICBzY2hlZHVsZWRQdXNoLFxuICAgIHB1c2gsXG4gIH0gPSBvcHRpb25zO1xuXG4gIGNvbnN0IHB1c2hPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgcHVzaCk7XG4gIGNvbnN0IHB1c2hRdWV1ZU9wdGlvbnMgPSBwdXNoT3B0aW9ucy5xdWV1ZU9wdGlvbnMgfHwge307XG4gIGlmIChwdXNoT3B0aW9ucy5xdWV1ZU9wdGlvbnMpIHtcbiAgICBkZWxldGUgcHVzaE9wdGlvbnMucXVldWVPcHRpb25zO1xuICB9XG5cbiAgLy8gUGFzcyB0aGUgcHVzaCBvcHRpb25zIHRvbyBhcyBpdCB3b3JrcyB3aXRoIHRoZSBkZWZhdWx0XG4gIGNvbnN0IHB1c2hBZGFwdGVyID0gbG9hZEFkYXB0ZXIocHVzaE9wdGlvbnMgJiYgcHVzaE9wdGlvbnMuYWRhcHRlciwgUGFyc2VQdXNoQWRhcHRlciwgcHVzaE9wdGlvbnMpO1xuICAvLyBXZSBwYXNzIHRoZSBvcHRpb25zIGFuZCB0aGUgYmFzZSBjbGFzcyBmb3IgdGhlIGFkYXRwZXIsXG4gIC8vIE5vdGUgdGhhdCBwYXNzaW5nIGFuIGluc3RhbmNlIHdvdWxkIHdvcmsgdG9vXG4gIGNvbnN0IHB1c2hDb250cm9sbGVyID0gbmV3IFB1c2hDb250cm9sbGVyKCk7XG4gIGNvbnN0IGhhc1B1c2hTdXBwb3J0ID0gISEocHVzaEFkYXB0ZXIgJiYgcHVzaCk7XG4gIGNvbnN0IGhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0ID0gaGFzUHVzaFN1cHBvcnQgJiYgKHNjaGVkdWxlZFB1c2ggPT09IHRydWUpO1xuXG4gIGNvbnN0IHtcbiAgICBkaXNhYmxlUHVzaFdvcmtlclxuICB9ID0gcHVzaFF1ZXVlT3B0aW9ucztcblxuICBjb25zdCBwdXNoQ29udHJvbGxlclF1ZXVlID0gbmV3IFB1c2hRdWV1ZShwdXNoUXVldWVPcHRpb25zKTtcbiAgbGV0IHB1c2hXb3JrZXI7XG4gIGlmICghZGlzYWJsZVB1c2hXb3JrZXIpIHtcbiAgICBwdXNoV29ya2VyID0gbmV3IFB1c2hXb3JrZXIocHVzaEFkYXB0ZXIsIHB1c2hRdWV1ZU9wdGlvbnMpO1xuICB9XG4gIHJldHVybiB7XG4gICAgcHVzaENvbnRyb2xsZXIsXG4gICAgaGFzUHVzaFN1cHBvcnQsXG4gICAgaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQsXG4gICAgcHVzaENvbnRyb2xsZXJRdWV1ZSxcbiAgICBwdXNoV29ya2VyXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEF1dGhEYXRhTWFuYWdlcihvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgY29uc3Qge1xuICAgIGF1dGgsXG4gICAgZW5hYmxlQW5vbnltb3VzVXNlcnNcbiAgfSA9IG9wdGlvbnM7XG4gIHJldHVybiBhdXRoRGF0YU1hbmFnZXIoYXV0aCwgZW5hYmxlQW5vbnltb3VzVXNlcnMpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhYmFzZUFkYXB0ZXIoZGF0YWJhc2VVUkksIGNvbGxlY3Rpb25QcmVmaXgsIGRhdGFiYXNlT3B0aW9ucykge1xuICBsZXQgcHJvdG9jb2w7XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkVVJJID0gdXJsLnBhcnNlKGRhdGFiYXNlVVJJKTtcbiAgICBwcm90b2NvbCA9IHBhcnNlZFVSSS5wcm90b2NvbCA/IHBhcnNlZFVSSS5wcm90b2NvbC50b0xvd2VyQ2FzZSgpIDogbnVsbDtcbiAgfSBjYXRjaChlKSB7IC8qICovIH1cbiAgc3dpdGNoIChwcm90b2NvbCkge1xuICBjYXNlICdwb3N0Z3JlczonOlxuICAgIHJldHVybiBuZXcgUG9zdGdyZXNTdG9yYWdlQWRhcHRlcih7XG4gICAgICB1cmk6IGRhdGFiYXNlVVJJLFxuICAgICAgY29sbGVjdGlvblByZWZpeCxcbiAgICAgIGRhdGFiYXNlT3B0aW9uc1xuICAgIH0pO1xuICBkZWZhdWx0OlxuICAgIHJldHVybiBuZXcgTW9uZ29TdG9yYWdlQWRhcHRlcih7XG4gICAgICB1cmk6IGRhdGFiYXNlVVJJLFxuICAgICAgY29sbGVjdGlvblByZWZpeCxcbiAgICAgIG1vbmdvT3B0aW9uczogZGF0YWJhc2VPcHRpb25zLFxuICAgIH0pO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Controllers/types.js b/lib/Controllers/types.js index 9a390c31f7..49132b6ab4 100644 --- a/lib/Controllers/types.js +++ b/lib/Controllers/types.js @@ -1 +1,2 @@ -"use strict"; \ No newline at end of file +"use strict"; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJ0eXBlcy5qcyIsInNvdXJjZXNDb250ZW50IjpbXX0= \ No newline at end of file diff --git a/lib/LiveQuery/Client.js b/lib/LiveQuery/Client.js index dc97207772..a993f6d96b 100644 --- a/lib/LiveQuery/Client.js +++ b/lib/LiveQuery/Client.js @@ -94,4 +94,5 @@ class Client { } } -exports.Client = Client; \ No newline at end of file +exports.Client = Client; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvQ2xpZW50LmpzIl0sIm5hbWVzIjpbImRhZmF1bHRGaWVsZHMiLCJDbGllbnQiLCJjb25zdHJ1Y3RvciIsImlkIiwicGFyc2VXZWJTb2NrZXQiLCJoYXNNYXN0ZXJLZXkiLCJyb2xlcyIsInN1YnNjcmlwdGlvbkluZm9zIiwiTWFwIiwicHVzaENvbm5lY3QiLCJfcHVzaEV2ZW50IiwicHVzaFN1YnNjcmliZSIsInB1c2hVbnN1YnNjcmliZSIsInB1c2hDcmVhdGUiLCJwdXNoRW50ZXIiLCJwdXNoVXBkYXRlIiwicHVzaERlbGV0ZSIsInB1c2hMZWF2ZSIsInB1c2hSZXNwb25zZSIsIm1lc3NhZ2UiLCJsb2dnZXIiLCJ2ZXJib3NlIiwic2VuZCIsInB1c2hFcnJvciIsImNvZGUiLCJlcnJvciIsInJlY29ubmVjdCIsIkpTT04iLCJzdHJpbmdpZnkiLCJhZGRTdWJzY3JpcHRpb25JbmZvIiwicmVxdWVzdElkIiwic3Vic2NyaXB0aW9uSW5mbyIsInNldCIsImdldFN1YnNjcmlwdGlvbkluZm8iLCJnZXQiLCJkZWxldGVTdWJzY3JpcHRpb25JbmZvIiwiZGVsZXRlIiwidHlwZSIsInN1YnNjcmlwdGlvbklkIiwicGFyc2VPYmplY3RKU09OIiwicmVzcG9uc2UiLCJmaWVsZHMiLCJoYXMiLCJfdG9KU09OV2l0aEZpZWxkcyIsImxpbWl0ZWRQYXJzZU9iamVjdCIsImZpZWxkIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7OztBQUtBLE1BQU1BLGdCQUFnQixDQUFDLFdBQUQsRUFBYyxVQUFkLEVBQTBCLFdBQTFCLEVBQXVDLFdBQXZDLEVBQW9ELEtBQXBELENBQXRCOztBQUVBLE1BQU1DLE1BQU4sQ0FBYTs7QUFnQlhDLGNBQVlDLEVBQVosRUFBd0JDLGNBQXhCLEVBQTZDQyxZQUE3QyxFQUFvRTtBQUNsRSxTQUFLRixFQUFMLEdBQVVBLEVBQVY7QUFDQSxTQUFLQyxjQUFMLEdBQXNCQSxjQUF0QjtBQUNBLFNBQUtDLFlB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QUEzQjtBQUNBLFNBQUssTUFBTUMsS0FBWCxJQUFvQjdDLGFBQXBCLEVBQW1DO0FBQ2pDNEMseUJBQW1CQyxLQUFuQixJQUE0Qk4sZ0JBQWdCTSxLQUFoQixDQUE1QjtBQUNEO0FBQ0QsU0FBSyxNQUFNQSxLQUFYLElBQW9CSixNQUFwQixFQUE0QjtBQUMxQixVQUFJSSxTQUFTTixlQUFiLEVBQThCO0FBQzVCSywyQkFBbUJDLEtBQW5CLElBQTRCTixnQkFBZ0JNLEtBQWhCLENBQTVCO0FBQ0Q7QUFDRjtBQUNELFdBQU9ELGtCQUFQO0FBQ0Q7QUE1RlU7O1FBZ0dYM0MsTSxHQUFBQSxNIiwiZmlsZSI6IkNsaWVudC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBsb2dnZXIgZnJvbSAnLi4vbG9nZ2VyJztcblxuaW1wb3J0IHR5cGUgeyBGbGF0dGVuZWRPYmplY3REYXRhIH0gZnJvbSAnLi9TdWJzY3JpcHRpb24nO1xuZXhwb3J0IHR5cGUgTWVzc2FnZSA9IHsgW2F0dHI6IHN0cmluZ106IGFueSB9O1xuXG5jb25zdCBkYWZhdWx0RmllbGRzID0gWydjbGFzc05hbWUnLCAnb2JqZWN0SWQnLCAndXBkYXRlZEF0JywgJ2NyZWF0ZWRBdCcsICdBQ0wnXTtcblxuY2xhc3MgQ2xpZW50IHtcbiAgaWQ6IG51bWJlcjtcbiAgcGFyc2VXZWJTb2NrZXQ6IGFueTtcbiAgaGFzTWFzdGVyS2V5OiBib29sZWFuO1xuICB1c2VySWQ6IHN0cmluZztcbiAgcm9sZXM6IEFycmF5PHN0cmluZz47XG4gIHN1YnNjcmlwdGlvbkluZm9zOiBPYmplY3Q7XG4gIHB1c2hDb25uZWN0OiBGdW5jdGlvbjtcbiAgcHVzaFN1YnNjcmliZTogRnVuY3Rpb247XG4gIHB1c2hVbnN1YnNjcmliZTogRnVuY3Rpb247XG4gIHB1c2hDcmVhdGU6IEZ1bmN0aW9uO1xuICBwdXNoRW50ZXI6IEZ1bmN0aW9uO1xuICBwdXNoVXBkYXRlOiBGdW5jdGlvbjtcbiAgcHVzaERlbGV0ZTogRnVuY3Rpb247XG4gIHB1c2hMZWF2ZTogRnVuY3Rpb247XG5cbiAgY29uc3RydWN0b3IoaWQ6IG51bWJlciwgcGFyc2VXZWJTb2NrZXQ6IGFueSwgaGFzTWFzdGVyS2V5OiBib29sZWFuKSB7XG4gICAgdGhpcy5pZCA9IGlkO1xuICAgIHRoaXMucGFyc2VXZWJTb2NrZXQgPSBwYXJzZVdlYlNvY2tldDtcbiAgICB0aGlzLmhhc01hc3RlcktleSA9IGhhc01hc3RlcktleTtcbiAgICB0aGlzLnJvbGVzID0gW107XG4gICAgdGhpcy5zdWJzY3JpcHRpb25JbmZvcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLnB1c2hDb25uZWN0ID0gdGhpcy5fcHVzaEV2ZW50KCdjb25uZWN0ZWQnKTtcbiAgICB0aGlzLnB1c2hTdWJzY3JpYmUgPSB0aGlzLl9wdXNoRXZlbnQoJ3N1YnNjcmliZWQnKTtcbiAgICB0aGlzLnB1c2hVbnN1YnNjcmliZSA9IHRoaXMuX3B1c2hFdmVudCgndW5zdWJzY3JpYmVkJyk7XG4gICAgdGhpcy5wdXNoQ3JlYXRlID0gdGhpcy5fcHVzaEV2ZW50KCdjcmVhdGUnKTtcbiAgICB0aGlzLnB1c2hFbnRlciA9IHRoaXMuX3B1c2hFdmVudCgnZW50ZXInKTtcbiAgICB0aGlzLnB1c2hVcGRhdGUgPSB0aGlzLl9wdXNoRXZlbnQoJ3VwZGF0ZScpO1xuICAgIHRoaXMucHVzaERlbGV0ZSA9IHRoaXMuX3B1c2hFdmVudCgnZGVsZXRlJyk7XG4gICAgdGhpcy5wdXNoTGVhdmUgPSB0aGlzLl9wdXNoRXZlbnQoJ2xlYXZlJyk7XG4gIH1cblxuICBzdGF0aWMgcHVzaFJlc3BvbnNlKHBhcnNlV2ViU29ja2V0OiBhbnksIG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkIHtcbiAgICBsb2dnZXIudmVyYm9zZSgnUHVzaCBSZXNwb25zZSA6ICVqJywgbWVzc2FnZSk7XG4gICAgcGFyc2VXZWJTb2NrZXQuc2VuZChtZXNzYWdlKTtcbiAgfVxuXG4gIHN0YXRpYyBwdXNoRXJyb3IocGFyc2VXZWJTb2NrZXQ6IGFueSwgY29kZTogbnVtYmVyLCBlcnJvcjogc3RyaW5nLCByZWNvbm5lY3Q6IGJvb2xlYW4gPSB0cnVlKTogdm9pZCB7XG4gICAgQ2xpZW50LnB1c2hSZXNwb25zZShwYXJzZVdlYlNvY2tldCwgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgJ29wJzogJ2Vycm9yJyxcbiAgICAgICdlcnJvcic6IGVycm9yLFxuICAgICAgJ2NvZGUnOiBjb2RlLFxuICAgICAgJ3JlY29ubmVjdCc6IHJlY29ubmVjdFxuICAgIH0pKTtcbiAgfVxuXG4gIGFkZFN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdElkOiBudW1iZXIsIHN1YnNjcmlwdGlvbkluZm86IGFueSk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uSW5mb3Muc2V0KHJlcXVlc3RJZCwgc3Vic2NyaXB0aW9uSW5mbyk7XG4gIH1cblxuICBnZXRTdWJzY3JpcHRpb25JbmZvKHJlcXVlc3RJZDogbnVtYmVyKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5zdWJzY3JpcHRpb25JbmZvcy5nZXQocmVxdWVzdElkKTtcbiAgfVxuXG4gIGRlbGV0ZVN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdElkOiBudW1iZXIpOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5zdWJzY3JpcHRpb25JbmZvcy5kZWxldGUocmVxdWVzdElkKTtcbiAgfVxuXG4gIF9wdXNoRXZlbnQodHlwZTogc3RyaW5nKTogRnVuY3Rpb24ge1xuICAgIHJldHVybiBmdW5jdGlvbihzdWJzY3JpcHRpb25JZDogbnVtYmVyLCBwYXJzZU9iamVjdEpTT046IGFueSk6IHZvaWQge1xuICAgICAgY29uc3QgcmVzcG9uc2U6IE1lc3NhZ2UgPSB7XG4gICAgICAgICdvcCcgOiB0eXBlLFxuICAgICAgICAnY2xpZW50SWQnIDogdGhpcy5pZFxuICAgICAgfTtcbiAgICAgIGlmICh0eXBlb2Ygc3Vic2NyaXB0aW9uSWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJlc3BvbnNlWydyZXF1ZXN0SWQnXSA9IHN1YnNjcmlwdGlvbklkO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwYXJzZU9iamVjdEpTT04gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGxldCBmaWVsZHM7XG4gICAgICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbkluZm9zLmhhcyhzdWJzY3JpcHRpb25JZCkpIHtcbiAgICAgICAgICBmaWVsZHMgPSB0aGlzLnN1YnNjcmlwdGlvbkluZm9zLmdldChzdWJzY3JpcHRpb25JZCkuZmllbGRzO1xuICAgICAgICB9XG4gICAgICAgIHJlc3BvbnNlWydvYmplY3QnXSA9IHRoaXMuX3RvSlNPTldpdGhGaWVsZHMocGFyc2VPYmplY3RKU09OLCBmaWVsZHMpO1xuICAgICAgfVxuICAgICAgQ2xpZW50LnB1c2hSZXNwb25zZSh0aGlzLnBhcnNlV2ViU29ja2V0LCBKU09OLnN0cmluZ2lmeShyZXNwb25zZSkpO1xuICAgIH1cbiAgfVxuXG4gIF90b0pTT05XaXRoRmllbGRzKHBhcnNlT2JqZWN0SlNPTjogYW55LCBmaWVsZHM6IGFueSk6IEZsYXR0ZW5lZE9iamVjdERhdGEge1xuICAgIGlmICghZmllbGRzKSB7XG4gICAgICByZXR1cm4gcGFyc2VPYmplY3RKU09OO1xuICAgIH1cbiAgICBjb25zdCBsaW1pdGVkUGFyc2VPYmplY3QgPSB7fTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGRhZmF1bHRGaWVsZHMpIHtcbiAgICAgIGxpbWl0ZWRQYXJzZU9iamVjdFtmaWVsZF0gPSBwYXJzZU9iamVjdEpTT05bZmllbGRdO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGZpZWxkcykge1xuICAgICAgaWYgKGZpZWxkIGluIHBhcnNlT2JqZWN0SlNPTikge1xuICAgICAgICBsaW1pdGVkUGFyc2VPYmplY3RbZmllbGRdID0gcGFyc2VPYmplY3RKU09OW2ZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGxpbWl0ZWRQYXJzZU9iamVjdDtcbiAgfVxufVxuXG5leHBvcnQge1xuICBDbGllbnRcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/LiveQuery/Id.js b/lib/LiveQuery/Id.js index 72fb66d6a6..70e7eaed52 100644 --- a/lib/LiveQuery/Id.js +++ b/lib/LiveQuery/Id.js @@ -19,4 +19,5 @@ class Id { } } -module.exports = Id; \ No newline at end of file +module.exports = Id; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvSWQuanMiXSwibmFtZXMiOlsiSWQiLCJjb25zdHJ1Y3RvciIsImNsYXNzTmFtZSIsIm9iamVjdElkIiwidG9TdHJpbmciLCJmcm9tU3RyaW5nIiwic3RyIiwic3BsaXQiLCJsZW5ndGgiLCJUeXBlRXJyb3IiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLE1BQU1BLEVBQU4sQ0FBUzs7QUFJUEMsY0FBWUMsU0FBWixFQUErQkMsUUFBL0IsRUFBaUQ7QUFDL0MsU0FBS0QsU0FBTCxHQUFpQkEsU0FBakI7QUFDQSxTQUFLQyxRQUFMLEdBQWdCQSxRQUFoQjtBQUNEO0FBQ0RDLGFBQW1CO0FBQ2pCLFdBQU8sS0FBS0YsU0FBTCxHQUFpQixHQUFqQixHQUF1QixLQUFLQyxRQUFuQztBQUNEOztBQUVELFNBQU9FLFVBQVAsQ0FBa0JDLEdBQWxCLEVBQStCO0FBQzdCLFFBQUlDLFFBQVFELElBQUlDLEtBQUosQ0FBVSxHQUFWLENBQVo7QUFDQSxRQUFJQSxNQUFNQyxNQUFOLEtBQWlCLENBQXJCLEVBQXdCO0FBQ3RCLFlBQU0sSUFBSUMsU0FBSixDQUFjLDBDQUFkLENBQU47QUFDRDtBQUNELFdBQU8sSUFBSVQsRUFBSixDQUFPTyxNQUFNLENBQU4sQ0FBUCxFQUFpQkEsTUFBTSxDQUFOLENBQWpCLENBQVA7QUFDRDtBQWxCTTs7QUFxQlRHLE9BQU9DLE9BQVAsR0FBaUJYLEVBQWpCIiwiZmlsZSI6IklkLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgSWQge1xuICBjbGFzc05hbWU6IHN0cmluZztcbiAgb2JqZWN0SWQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0SWQ6IHN0cmluZykge1xuICAgIHRoaXMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgIHRoaXMub2JqZWN0SWQgPSBvYmplY3RJZDtcbiAgfVxuICB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNsYXNzTmFtZSArICc6JyArIHRoaXMub2JqZWN0SWQ7XG4gIH1cblxuICBzdGF0aWMgZnJvbVN0cmluZyhzdHI6IHN0cmluZykge1xuICAgIHZhciBzcGxpdCA9IHN0ci5zcGxpdCgnOicpO1xuICAgIGlmIChzcGxpdC5sZW5ndGggIT09IDIpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjcmVhdGUgSWQgb2JqZWN0IGZyb20gdGhpcyBzdHJpbmcnKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBJZChzcGxpdFswXSwgc3BsaXRbMV0pO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gSWQ7XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/ParseCloudCodePublisher.js b/lib/LiveQuery/ParseCloudCodePublisher.js index cbc1c691bf..7c744c65e8 100644 --- a/lib/LiveQuery/ParseCloudCodePublisher.js +++ b/lib/LiveQuery/ParseCloudCodePublisher.js @@ -47,4 +47,5 @@ class ParseCloudCodePublisher { } } -exports.ParseCloudCodePublisher = ParseCloudCodePublisher; \ No newline at end of file +exports.ParseCloudCodePublisher = ParseCloudCodePublisher; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIuanMiXSwibmFtZXMiOlsiUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsInBhcnNlUHVibGlzaGVyIiwiUGFyc2VQdWJTdWIiLCJjcmVhdGVQdWJsaXNoZXIiLCJvbkNsb3VkQ29kZUFmdGVyU2F2ZSIsInJlcXVlc3QiLCJfb25DbG91ZENvZGVNZXNzYWdlIiwiUGFyc2UiLCJhcHBsaWNhdGlvbklkIiwib25DbG91ZENvZGVBZnRlckRlbGV0ZSIsInR5cGUiLCJsb2dnZXIiLCJ2ZXJib3NlIiwib2JqZWN0Iiwib3JpZ2luYWwiLCJtZXNzYWdlIiwiY3VycmVudFBhcnNlT2JqZWN0IiwiX3RvRnVsbEpTT04iLCJvcmlnaW5hbFBhcnNlT2JqZWN0IiwicHVibGlzaCIsIkpTT04iLCJzdHJpbmdpZnkiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFQSxNQUFNQSx1QkFBTixDQUE4Qjs7QUFHNUI7QUFDQTtBQUNBQyxjQUFZQyxTQUFjLEVBQTFCLEVBQThCO0FBQzVCLFNBQUtDLGNBQUwsR0FBc0JDLHlCQUFZQyxlQUFaLENBQTRCSCxNQUE1QixDQUF0QjtBQUNEOztBQUVESSx1QkFBcUJDLE9BQXJCLEVBQXlDO0FBQ3ZDLFNBQUtDLG1CQUFMLENBQXlCQyxlQUFNQyxhQUFOLEdBQXNCLFdBQS9DLEVBQTRESCxPQUE1RDtBQUNEOztBQUVESSx5QkFBdUJKLE9BQXZCLEVBQTJDO0FBQ3pDLFNBQUtDLG1CQUFMLENBQXlCQyxlQUFNQyxhQUFOLEdBQXNCLGFBQS9DLEVBQThESCxPQUE5RDtBQUNEOztBQUVEO0FBQ0FDLHNCQUFvQkksSUFBcEIsRUFBa0NMLE9BQWxDLEVBQXNEO0FBQ3BETSxxQkFBT0MsT0FBUCxDQUFlLDBEQUFmLEVBQTJFUCxRQUFRUSxNQUFuRixFQUEyRlIsUUFBUVMsUUFBbkc7QUFDQTtBQUNBLFVBQU1DLFVBQVU7QUFDZEMsMEJBQW9CWCxRQUFRUSxNQUFSLENBQWVJLFdBQWY7QUFETixLQUFoQjtBQUdBLFFBQUlaLFFBQVFTLFFBQVosRUFBc0I7QUFDcEJDLGNBQVFHLG1CQUFSLEdBQThCYixRQUFRUyxRQUFSLENBQWlCRyxXQUFqQixFQUE5QjtBQUNEO0FBQ0QsU0FBS2hCLGNBQUwsQ0FBb0JrQixPQUFwQixDQUE0QlQsSUFBNUIsRUFBa0NVLEtBQUtDLFNBQUwsQ0FBZU4sT0FBZixDQUFsQztBQUNEO0FBNUIyQjs7UUFnQzVCakIsdUIsR0FBQUEsdUIiLCJmaWxlIjoiUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZVB1YlN1YiB9IGZyb20gJy4vUGFyc2VQdWJTdWInO1xuaW1wb3J0IFBhcnNlICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBsb2dnZXIgZnJvbSAnLi4vbG9nZ2VyJztcblxuY2xhc3MgUGFyc2VDbG91ZENvZGVQdWJsaXNoZXIge1xuICBwYXJzZVB1Ymxpc2hlcjogT2JqZWN0O1xuXG4gIC8vIGNvbmZpZyBvYmplY3Qgb2YgdGhlIHB1Ymxpc2hlciwgcmlnaHQgbm93IGl0IG9ubHkgY29udGFpbnMgdGhlIHJlZGlzVVJMLFxuICAvLyBidXQgd2UgbWF5IGV4dGVuZCBpdCBsYXRlci5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBhbnkgPSB7fSkge1xuICAgIHRoaXMucGFyc2VQdWJsaXNoZXIgPSBQYXJzZVB1YlN1Yi5jcmVhdGVQdWJsaXNoZXIoY29uZmlnKTtcbiAgfVxuXG4gIG9uQ2xvdWRDb2RlQWZ0ZXJTYXZlKHJlcXVlc3Q6IGFueSk6IHZvaWQge1xuICAgIHRoaXMuX29uQ2xvdWRDb2RlTWVzc2FnZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyU2F2ZScsIHJlcXVlc3QpO1xuICB9XG5cbiAgb25DbG91ZENvZGVBZnRlckRlbGV0ZShyZXF1ZXN0OiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLl9vbkNsb3VkQ29kZU1lc3NhZ2UoUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlckRlbGV0ZScsIHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gUmVxdWVzdCBpcyB0aGUgcmVxdWVzdCBvYmplY3QgZnJvbSBjbG91ZCBjb2RlIGZ1bmN0aW9ucy4gcmVxdWVzdC5vYmplY3QgaXMgYSBQYXJzZU9iamVjdC5cbiAgX29uQ2xvdWRDb2RlTWVzc2FnZSh0eXBlOiBzdHJpbmcsIHJlcXVlc3Q6IGFueSk6IHZvaWQge1xuICAgIGxvZ2dlci52ZXJib3NlKCdSYXcgcmVxdWVzdCBmcm9tIGNsb3VkIGNvZGUgY3VycmVudCA6ICVqIHwgb3JpZ2luYWwgOiAlaicsIHJlcXVlc3Qub2JqZWN0LCByZXF1ZXN0Lm9yaWdpbmFsKTtcbiAgICAvLyBXZSBuZWVkIHRoZSBmdWxsIEpTT04gd2hpY2ggaW5jbHVkZXMgY2xhc3NOYW1lXG4gICAgY29uc3QgbWVzc2FnZSA9IHtcbiAgICAgIGN1cnJlbnRQYXJzZU9iamVjdDogcmVxdWVzdC5vYmplY3QuX3RvRnVsbEpTT04oKVxuICAgIH1cbiAgICBpZiAocmVxdWVzdC5vcmlnaW5hbCkge1xuICAgICAgbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0ID0gcmVxdWVzdC5vcmlnaW5hbC5fdG9GdWxsSlNPTigpO1xuICAgIH1cbiAgICB0aGlzLnBhcnNlUHVibGlzaGVyLnB1Ymxpc2godHlwZSwgSlNPTi5zdHJpbmdpZnkobWVzc2FnZSkpO1xuICB9XG59XG5cbmV4cG9ydCB7XG4gIFBhcnNlQ2xvdWRDb2RlUHVibGlzaGVyXG59XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/ParseLiveQueryServer.js b/lib/LiveQuery/ParseLiveQueryServer.js index 30188195ee..541a7490c9 100644 --- a/lib/LiveQuery/ParseLiveQueryServer.js +++ b/lib/LiveQuery/ParseLiveQueryServer.js @@ -577,4 +577,5 @@ class ParseLiveQueryServer { } } -exports.ParseLiveQueryServer = ParseLiveQueryServer; \ No newline at end of file +exports.ParseLiveQueryServer = ParseLiveQueryServer; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VMaXZlUXVlcnlTZXJ2ZXIuanMiXSwibmFtZXMiOlsiUGFyc2VMaXZlUXVlcnlTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsInNlcnZlciIsImNvbmZpZyIsImNsaWVudHMiLCJNYXAiLCJzdWJzY3JpcHRpb25zIiwia2V5UGFpcnMiLCJrZXkiLCJPYmplY3QiLCJrZXlzIiwic2V0IiwibG9nZ2VyIiwidmVyYm9zZSIsIlBhcnNlIiwiZGlzYWJsZVNpbmdsZUluc3RhbmNlIiwic2VydmVyVVJMIiwiYXBwSWQiLCJhcHBsaWNhdGlvbklkIiwiamF2YXNjcmlwdEtleSIsImphdmFTY3JpcHRLZXkiLCJtYXN0ZXJLZXkiLCJpbml0aWFsaXplIiwicGFyc2VXZWJTb2NrZXRTZXJ2ZXIiLCJQYXJzZVdlYlNvY2tldFNlcnZlciIsInBhcnNlV2Vic29ja2V0IiwiX29uQ29ubmVjdCIsIndlYnNvY2tldFRpbWVvdXQiLCJzdWJzY3JpYmVyIiwiUGFyc2VQdWJTdWIiLCJjcmVhdGVTdWJzY3JpYmVyIiwic3Vic2NyaWJlIiwib24iLCJjaGFubmVsIiwibWVzc2FnZVN0ciIsIm1lc3NhZ2UiLCJKU09OIiwicGFyc2UiLCJlIiwiZXJyb3IiLCJfaW5mbGF0ZVBhcnNlT2JqZWN0IiwiX29uQWZ0ZXJTYXZlIiwiX29uQWZ0ZXJEZWxldGUiLCJzZXNzaW9uVG9rZW5DYWNoZSIsIlNlc3Npb25Ub2tlbkNhY2hlIiwiY2FjaGVUaW1lb3V0IiwiY3VycmVudFBhcnNlT2JqZWN0IiwiY2xhc3NOYW1lIiwicGFyc2VPYmplY3QiLCJfZmluaXNoRmV0Y2giLCJvcmlnaW5hbFBhcnNlT2JqZWN0IiwiZGVsZXRlZFBhcnNlT2JqZWN0IiwidG9KU09OIiwiaWQiLCJzaXplIiwiY2xhc3NTdWJzY3JpcHRpb25zIiwiZ2V0IiwiZGVidWciLCJzdWJzY3JpcHRpb24iLCJ2YWx1ZXMiLCJpc1N1YnNjcmlwdGlvbk1hdGNoZWQiLCJfbWF0Y2hlc1N1YnNjcmlwdGlvbiIsImNsaWVudElkIiwicmVxdWVzdElkcyIsIl8iLCJlbnRyaWVzIiwiY2xpZW50UmVxdWVzdElkcyIsImNsaWVudCIsInJlcXVlc3RJZCIsImFjbCIsImdldEFDTCIsIl9tYXRjaGVzQUNMIiwidGhlbiIsImlzTWF0Y2hlZCIsInB1c2hEZWxldGUiLCJpc09yaWdpbmFsU3Vic2NyaXB0aW9uTWF0Y2hlZCIsImlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQiLCJvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSIsIlByb21pc2UiLCJhcyIsIm9yaWdpbmFsQUNMIiwiY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSIsImN1cnJlbnRBQ0wiLCJ3aGVuIiwiaXNPcmlnaW5hbE1hdGNoZWQiLCJpc0N1cnJlbnRNYXRjaGVkIiwiaGFzaCIsInR5cGUiLCJmdW5jdGlvbk5hbWUiLCJyZXF1ZXN0IiwidHY0IiwidmFsaWRhdGUiLCJSZXF1ZXN0U2NoZW1hIiwib3AiLCJDbGllbnQiLCJwdXNoRXJyb3IiLCJfaGFuZGxlQ29ubmVjdCIsIl9oYW5kbGVTdWJzY3JpYmUiLCJfaGFuZGxlVXBkYXRlU3Vic2NyaXB0aW9uIiwiX2hhbmRsZVVuc3Vic2NyaWJlIiwiaW5mbyIsImhhcyIsImV2ZW50IiwiZGVsZXRlIiwic3Vic2NyaXB0aW9uSW5mbyIsInN1YnNjcmlwdGlvbkluZm9zIiwiZGVsZXRlQ2xpZW50U3Vic2NyaXB0aW9uIiwiaGFzU3Vic2NyaWJpbmdDbGllbnQiLCJxdWVyeSIsImdldFB1YmxpY1JlYWRBY2Nlc3MiLCJoYXNNYXN0ZXJLZXkiLCJnZXRTdWJzY3JpcHRpb25JbmZvIiwic3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuIiwic2Vzc2lvblRva2VuIiwiZ2V0VXNlcklkIiwidXNlcklkIiwiZ2V0UmVhZEFjY2VzcyIsImlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCIsInJlc29sdmUiLCJyZWplY3QiLCJhY2xfaGFzX3JvbGVzIiwicGVybWlzc2lvbnNCeUlkIiwic29tZSIsInN0YXJ0c1dpdGgiLCJ1c2VyIiwiVXNlciIsInJvbGVzUXVlcnkiLCJRdWVyeSIsIlJvbGUiLCJlcXVhbFRvIiwiZmluZCIsInVzZU1hc3RlcktleSIsInJvbGVzIiwicm9sZSIsImdldFJvbGVSZWFkQWNjZXNzIiwiY2F0Y2giLCJpc1JvbGVNYXRjaGVkIiwiY2xpZW50U2Vzc2lvblRva2VuIiwiX3ZhbGlkYXRlS2V5cyIsIl9oYXNNYXN0ZXJLZXkiLCJwdXNoQ29ubmVjdCIsInZhbGlkS2V5UGFpcnMiLCJoYXNPd25Qcm9wZXJ0eSIsImlzVmFsaWQiLCJzZWNyZXQiLCJzdWJzY3JpcHRpb25IYXNoIiwiU3Vic2NyaXB0aW9uIiwid2hlcmUiLCJmaWVsZHMiLCJhZGRTdWJzY3JpcHRpb25JbmZvIiwiYWRkQ2xpZW50U3Vic2NyaXB0aW9uIiwicHVzaFN1YnNjcmliZSIsIm5vdGlmeUNsaWVudCIsImRlbGV0ZVN1YnNjcmlwdGlvbkluZm8iLCJwdXNoVW5zdWJzY3JpYmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUVBLE1BQU1BLG9CQUFOLENBQTJCO0FBRXpCO0FBT0FDLGNBQVlDLE1BQVosRUFBeUJDLE1BQXpCLEVBQXNDO0FBQ3BDLFNBQUtELE1BQUwsR0FBY0EsTUFBZDtBQUNBLFNBQUtFLE9BQUwsR0FBZSxJQUFJQyxHQUFKLEVBQWY7QUFDQSxTQUFLQyxhQUFMLEdBQXFCLElBQUlELEdBQUosRUFBckI7O0FBRUFGLGFBQVNBLFVBQVUsRUFBbkI7O0FBRUE7QUFDQSxVQUFNSSxXQUFXSixPQUFPSSxRQUFQLElBQW1CLEVBQXBDO0FBQ0EsU0FBS0EsUUFBTCxHQUFnQixJQUFJRixHQUFKLEVBQWhCO0FBQ0EsU0FBSyxNQUFNRyxHQUFYLElBQWtCQyxPQUFPQyxJQUFQLENBQVlILFFBQVosQ0FBbEIsRUFBeUM7QUFDdkMsV0FBS0Es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OUY7QUFDRDtBQTlpQndCOztRQWtqQnpCcEUsb0IsR0FBQUEsb0IiLCJmaWxlIjoiUGFyc2VMaXZlUXVlcnlTZXJ2ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHY0IGZyb20gJ3R2NCc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICcuL1N1YnNjcmlwdGlvbic7XG5pbXBvcnQgeyBDbGllbnQgfSBmcm9tICcuL0NsaWVudCc7XG5pbXBvcnQgeyBQYXJzZVdlYlNvY2tldFNlcnZlciB9IGZyb20gJy4vUGFyc2VXZWJTb2NrZXRTZXJ2ZXInO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IFJlcXVlc3RTY2hlbWEgZnJvbSAnLi9SZXF1ZXN0U2NoZW1hJztcbmltcG9ydCB7IG1hdGNoZXNRdWVyeSwgcXVlcnlIYXNoIH0gZnJvbSAnLi9RdWVyeVRvb2xzJztcbmltcG9ydCB7IFBhcnNlUHViU3ViIH0gZnJvbSAnLi9QYXJzZVB1YlN1Yic7XG5pbXBvcnQgeyBTZXNzaW9uVG9rZW5DYWNoZSB9IGZyb20gJy4vU2Vzc2lvblRva2VuQ2FjaGUnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB1dWlkIGZyb20gJ3V1aWQnO1xuaW1wb3J0IHsgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyB9IGZyb20gJy4uL3RyaWdnZXJzJztcblxuY2xhc3MgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIge1xuICBjbGllbnRzOiBNYXA7XG4gIC8vIGNsYXNzTmFtZSAtPiAocXVlcnlIYXNoIC0+IHN1YnNjcmlwdGlvbilcbiAgc3Vic2NyaXB0aW9uczogT2JqZWN0O1xuICBwYXJzZVdlYlNvY2tldFNlcnZlcjogT2JqZWN0O1xuICBrZXlQYWlycyA6IGFueTtcbiAgLy8gVGhlIHN1YnNjcmliZXIgd2UgdXNlIHRvIGdldCBvYmplY3QgdXBkYXRlIGZyb20gcHVibGlzaGVyXG4gIHN1YnNjcmliZXI6IE9iamVjdDtcblxuICBjb25zdHJ1Y3RvcihzZXJ2ZXI6IGFueSwgY29uZmlnOiBhbnkpIHtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICB0aGlzLmNsaWVudHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zID0gbmV3IE1hcCgpO1xuXG4gICAgY29uZmlnID0gY29uZmlnIHx8IHt9O1xuXG4gICAgLy8gU3RvcmUga2V5cywgY29udmVydCBvYmogdG8gbWFwXG4gICAgY29uc3Qga2V5UGFpcnMgPSBjb25maWcua2V5UGFpcnMgfHwge307XG4gICAgdGhpcy5rZXlQYWlycyA9IG5ldyBNYXAoKTtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhrZXlQYWlycykpIHtcbiAgICAgIHRoaXMua2V5UGFpcnMuc2V0KGtleSwga2V5UGFpcnNba2V5XSk7XG4gICAgfVxuICAgIGxvZ2dlci52ZXJib3NlKCdTdXBwb3J0IGtleSBwYWlycycsIHRoaXMua2V5UGFpcnMpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBQYXJzZVxuICAgIFBhcnNlLk9iamVjdC5kaXNhYmxlU2luZ2xlSW5zdGFuY2UoKTtcblxuICAgIGNvbnN0IHNlcnZlclVSTCA9IGNvbmZpZy5zZXJ2ZXJVUkwgfHwgUGFyc2Uuc2VydmVyVVJMO1xuICAgIFBhcnNlLnNlcnZlclVSTCA9IHNlcnZlclVSTDtcbiAgICBjb25zdCBhcHBJZCA9IGNvbmZpZy5hcHBJZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICAgIGNvbnN0IGphdmFzY3JpcHRLZXkgPSBQYXJzZS5qYXZhU2NyaXB0S2V5O1xuICAgIGNvbnN0IG1hc3RlcktleSA9IGNvbmZpZy5tYXN0ZXJLZXkgfHwgUGFyc2UubWFzdGVyS2V5O1xuICAgIFBhcnNlLmluaXRpYWxpemUoYXBwSWQsIGphdmFzY3JpcHRLZXksIG1hc3RlcktleSk7XG5cbiAgICAvLyBJbml0aWFsaXplIHdlYnNvY2tldCBzZXJ2ZXJcbiAgICB0aGlzLnBhcnNlV2ViU29ja2V0U2VydmVyID0gbmV3IFBhcnNlV2ViU29ja2V0U2VydmVyKFxuICAgICAgc2VydmVyLFxuICAgICAgKHBhcnNlV2Vic29ja2V0KSA9PiB0aGlzLl9vbkNvbm5lY3QocGFyc2VXZWJzb2NrZXQpLFxuICAgICAgY29uZmlnLndlYnNvY2tldFRpbWVvdXRcbiAgICApO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzdWJzY3JpYmVyXG4gICAgdGhpcy5zdWJzY3JpYmVyID0gUGFyc2VQdWJTdWIuY3JlYXRlU3Vic2NyaWJlcihjb25maWcpO1xuICAgIHRoaXMuc3Vic2NyaWJlci5zdWJzY3JpYmUoUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlclNhdmUnKTtcbiAgICB0aGlzLnN1YnNjcmliZXIuc3Vic2NyaWJlKFBhcnNlLmFwcGxpY2F0aW9uSWQgKyAnYWZ0ZXJEZWxldGUnKTtcbiAgICAvLyBSZWdpc3RlciBtZXNzYWdlIGhhbmRsZXIgZm9yIHN1YnNjcmliZXIuIFdoZW4gcHVibGlzaGVyIGdldCBtZXNzYWdlcywgaXQgd2lsbCBwdWJsaXNoIG1lc3NhZ2VcbiAgICAvLyB0byB0aGUgc3Vic2NyaWJlcnMgYW5kIHRoZSBoYW5kbGVyIHdpbGwgYmUgY2FsbGVkLlxuICAgIHRoaXMuc3Vic2NyaWJlci5vbignbWVzc2FnZScsIChjaGFubmVsLCBtZXNzYWdlU3RyKSA9PiB7XG4gICAgICBsb2dnZXIudmVyYm9zZSgnU3Vic2NyaWJlIG1lc3NzYWdlICVqJywgbWVzc2FnZVN0cik7XG4gICAgICBsZXQgbWVzc2FnZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG1lc3NhZ2VTdHIpO1xuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcigndW5hYmxlIHRvIHBhcnNlIG1lc3NhZ2UnLCBtZXNzYWdlU3RyLCBlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5faW5mbGF0ZVBhcnNlT2JqZWN0KG1lc3NhZ2UpO1xuICAgICAgaWYgKGNoYW5uZWwgPT09IFBhcnNlLmFwcGxpY2F0aW9uSWQgKyAnYWZ0ZXJTYXZlJykge1xuICAgICAgICB0aGlzLl9vbkFmdGVyU2F2ZShtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhbm5lbCA9PT0gUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlckRlbGV0ZScpIHtcbiAgICAgICAgdGhpcy5fb25BZnRlckRlbGV0ZShtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcignR2V0IG1lc3NhZ2UgJXMgZnJvbSB1bmtub3duIGNoYW5uZWwgJWonLCBtZXNzYWdlLCBjaGFubmVsKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIEluaXRpYWxpemUgc2Vzc2lvblRva2VuIGNhY2hlXG4gICAgdGhpcy5zZXNzaW9uVG9rZW5DYWNoZSA9IG5ldyBTZXNzaW9uVG9rZW5DYWNoZShjb25maWcuY2FjaGVUaW1lb3V0KTtcbiAgfVxuXG4gIC8vIE1lc3NhZ2UgaXMgdGhlIEpTT04gb2JqZWN0IGZyb20gcHVibGlzaGVyLiBNZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdCBpcyB0aGUgUGFyc2VPYmplY3QgSlNPTiBhZnRlciBjaGFuZ2VzLlxuICAvLyBNZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgaXMgdGhlIG9yaWdpbmFsIFBhcnNlT2JqZWN0IEpTT04uXG4gIF9pbmZsYXRlUGFyc2VPYmplY3QobWVzc2FnZTogYW55KTogdm9pZCB7XG4gICAgLy8gSW5mbGF0ZSBtZXJnZWQgb2JqZWN0XG4gICAgY29uc3QgY3VycmVudFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3Q7XG4gICAgbGV0IGNsYXNzTmFtZSA9IGN1cnJlbnRQYXJzZU9iamVjdC5jbGFzc05hbWU7XG4gICAgbGV0IHBhcnNlT2JqZWN0ID0gbmV3IFBhcnNlLk9iamVjdChjbGFzc05hbWUpO1xuICAgIHBhcnNlT2JqZWN0Ll9maW5pc2hGZXRjaChjdXJyZW50UGFyc2VPYmplY3QpO1xuICAgIG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0ID0gcGFyc2VPYmplY3Q7XG4gICAgLy8gSW5mbGF0ZSBvcmlnaW5hbCBvYmplY3RcbiAgICBjb25zdCBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0O1xuICAgIGlmIChvcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICBjbGFzc05hbWUgPSBvcmlnaW5hbFBhcnNlT2JqZWN0LmNsYXNzTmFtZTtcbiAgICAgIHBhcnNlT2JqZWN0ID0gbmV3IFBhcnNlLk9iamVjdChjbGFzc05hbWUpO1xuICAgICAgcGFyc2VPYmplY3QuX2ZpbmlzaEZldGNoKG9yaWdpbmFsUGFyc2VPYmplY3QpO1xuICAgICAgbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0ID0gcGFyc2VPYmplY3Q7XG4gICAgfVxuICB9XG5cbiAgLy8gTWVzc2FnZSBpcyB0aGUgSlNPTiBvYmplY3QgZnJvbSBwdWJsaXNoZXIgYWZ0ZXIgaW5mbGF0ZWQuIE1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0IGlzIHRoZSBQYXJzZU9iamVjdCBhZnRlciBjaGFuZ2VzLlxuICAvLyBNZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgaXMgdGhlIG9yaWdpbmFsIFBhcnNlT2JqZWN0LlxuICBfb25BZnRlckRlbGV0ZShtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICBsb2dnZXIudmVyYm9zZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyRGVsZXRlIGlzIHRyaWdnZXJlZCcpO1xuXG4gICAgY29uc3QgZGVsZXRlZFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QudG9KU09OKCk7XG4gICAgY29uc3QgY2xhc3NOYW1lID0gZGVsZXRlZFBhcnNlT2JqZWN0LmNsYXNzTmFtZTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ2xhc3NOYW1lOiAlaiB8IE9iamVjdElkOiAlcycsIGNsYXNzTmFtZSwgZGVsZXRlZFBhcnNlT2JqZWN0LmlkKTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBjbGllbnQgbnVtYmVyIDogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG5cbiAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgaWYgKHR5cGVvZiBjbGFzc1N1YnNjcmlwdGlvbnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NhbiBub3QgZmluZCBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MgJyArIGNsYXNzTmFtZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc3Vic2NyaXB0aW9uIG9mIGNsYXNzU3Vic2NyaXB0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgY29uc3QgaXNTdWJzY3JpcHRpb25NYXRjaGVkID0gdGhpcy5fbWF0Y2hlc1N1YnNjcmlwdGlvbihkZWxldGVkUGFyc2VPYmplY3QsIHN1YnNjcmlwdGlvbik7XG4gICAgICBpZiAoIWlzU3Vic2NyaXB0aW9uTWF0Y2hlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgW2NsaWVudElkLCByZXF1ZXN0SWRzXSBvZiBfLmVudHJpZXMoc3Vic2NyaXB0aW9uLmNsaWVudFJlcXVlc3RJZHMpKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQoY2xpZW50SWQpO1xuICAgICAgICBpZiAodHlwZW9mIGNsaWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiByZXF1ZXN0SWRzKSB7XG4gICAgICAgICAgY29uc3QgYWNsID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QuZ2V0QUNMKCk7XG4gICAgICAgICAgLy8gQ2hlY2sgQUNMXG4gICAgICAgICAgdGhpcy5fbWF0Y2hlc0FDTChhY2wsIGNsaWVudCwgcmVxdWVzdElkKS50aGVuKChpc01hdGNoZWQpID0+IHtcbiAgICAgICAgICAgIGlmICghaXNNYXRjaGVkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2xpZW50LnB1c2hEZWxldGUocmVxdWVzdElkLCBkZWxldGVkUGFyc2VPYmplY3QpO1xuICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdNYXRjaGluZyBBQ0wgZXJyb3IgOiAnLCBlcnJvcik7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBNZXNzYWdlIGlzIHRoZSBKU09OIG9iamVjdCBmcm9tIHB1Ymxpc2hlciBhZnRlciBpbmZsYXRlZC4gTWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QgaXMgdGhlIFBhcnNlT2JqZWN0IGFmdGVyIGNoYW5nZXMuXG4gIC8vIE1lc3NhZ2Uub3JpZ2luYWxQYXJzZU9iamVjdCBpcyB0aGUgb3JpZ2luYWwgUGFyc2VPYmplY3QuXG4gIF9vbkFmdGVyU2F2ZShtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICBsb2dnZXIudmVyYm9zZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyU2F2ZSBpcyB0cmlnZ2VyZWQnKTtcblxuICAgIGxldCBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbnVsbDtcbiAgICBpZiAobWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0LnRvSlNPTigpO1xuICAgIH1cbiAgICBjb25zdCBjdXJyZW50UGFyc2VPYmplY3QgPSBtZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdC50b0pTT04oKTtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBjdXJyZW50UGFyc2VPYmplY3QuY2xhc3NOYW1lO1xuICAgIGxvZ2dlci52ZXJib3NlKCdDbGFzc05hbWU6ICVzIHwgT2JqZWN0SWQ6ICVzJywgY2xhc3NOYW1lLCBjdXJyZW50UGFyc2VPYmplY3QuaWQpO1xuICAgIGxvZ2dlci52ZXJib3NlKCdDdXJyZW50IGNsaWVudCBudW1iZXIgOiAlZCcsIHRoaXMuY2xpZW50cy5zaXplKTtcblxuICAgIGNvbnN0IGNsYXNzU3Vic2NyaXB0aW9ucyA9IHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoY2xhc3NOYW1lKTtcbiAgICBpZiAodHlwZW9mIGNsYXNzU3Vic2NyaXB0aW9ucyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ2FuIG5vdCBmaW5kIHN1YnNjcmlwdGlvbnMgdW5kZXIgdGhpcyBjbGFzcyAnICsgY2xhc3NOYW1lKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBzdWJzY3JpcHRpb24gb2YgY2xhc3NTdWJzY3JpcHRpb25zLnZhbHVlcygpKSB7XG4gICAgICBjb25zdCBpc09yaWdpbmFsU3Vic2NyaXB0aW9uTWF0Y2hlZCA9IHRoaXMuX21hdGNoZXNTdWJzY3JpcHRpb24ob3JpZ2luYWxQYXJzZU9iamVjdCwgc3Vic2NyaXB0aW9uKTtcbiAgICAgIGNvbnN0IGlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQgPSB0aGlzLl9tYXRjaGVzU3Vic2NyaXB0aW9uKGN1cnJlbnRQYXJzZU9iamVjdCwgc3Vic2NyaXB0aW9uKTtcbiAgICAgIGZvciAoY29uc3QgW2NsaWVudElkLCByZXF1ZXN0SWRzXSBvZiBfLmVudHJpZXMoc3Vic2NyaXB0aW9uLmNsaWVudFJlcXVlc3RJZHMpKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQoY2xpZW50SWQpO1xuICAgICAgICBpZiAodHlwZW9mIGNsaWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiByZXF1ZXN0SWRzKSB7XG4gICAgICAgICAgLy8gU2V0IG9yaWduYWwgUGFyc2VPYmplY3QgQUNMIGNoZWNraW5nIHByb21pc2UsIGlmIHRoZSBvYmplY3QgZG9lcyBub3QgbWF0Y2hcbiAgICAgICAgICAvLyBzdWJzY3JpcHRpb24sIHdlIGRvIG5vdCBuZWVkIHRvIGNoZWNrIEFDTFxuICAgICAgICAgIGxldCBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZTtcbiAgICAgICAgICBpZiAoIWlzT3JpZ2luYWxTdWJzY3JpcHRpb25NYXRjaGVkKSB7XG4gICAgICAgICAgICBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSA9IFBhcnNlLlByb21pc2UuYXMoZmFsc2UpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxBQ0w7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICAgICAgICAgIG9yaWdpbmFsQUNMID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0LmdldEFDTCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3JpZ2luYWxBQ0xDaGVja2luZ1Byb21pc2UgPSB0aGlzLl9tYXRjaGVzQUNMKG9yaWdpbmFsQUNMLCBjbGllbnQsIHJlcXVlc3RJZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFNldCBjdXJyZW50IFBhcnNlT2JqZWN0IEFDTCBjaGVja2luZyBwcm9taXNlLCBpZiB0aGUgb2JqZWN0IGRvZXMgbm90IG1hdGNoXG4gICAgICAgICAgLy8gc3Vic2NyaXB0aW9uLCB3ZSBkbyBub3QgbmVlZCB0byBjaGVjayBBQ0xcbiAgICAgICAgICBsZXQgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZTtcbiAgICAgICAgICBpZiAoIWlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRBQ0xDaGVja2luZ1Byb21pc2UgPSBQYXJzZS5Qcm9taXNlLmFzKGZhbHNlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudEFDTCA9IG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0LmdldEFDTCgpO1xuICAgICAgICAgICAgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSA9IHRoaXMuX21hdGNoZXNBQ0woY3VycmVudEFDTCwgY2xpZW50LCByZXF1ZXN0SWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIFBhcnNlLlByb21pc2Uud2hlbihcbiAgICAgICAgICAgIG9yaWdpbmFsQUNMQ2hlY2tpbmdQcm9taXNlLFxuICAgICAgICAgICAgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZVxuICAgICAgICAgICkudGhlbigoaXNPcmlnaW5hbE1hdGNoZWQsIGlzQ3VycmVudE1hdGNoZWQpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci52ZXJib3NlKCdPcmlnaW5hbCAlaiB8IEN1cnJlbnQgJWogfCBNYXRjaDogJXMsICVzLCAlcywgJXMgfCBRdWVyeTogJXMnLFxuICAgICAgICAgICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICAgICAgICAgICAgICBjdXJyZW50UGFyc2VPYmplY3QsXG4gICAgICAgICAgICAgIGlzT3JpZ2luYWxTdWJzY3JpcHRpb25NYXRjaGVkLFxuICAgICAgICAgICAgICBpc0N1cnJlbnRTdWJzY3JpcHRpb25NYXRjaGVkLFxuICAgICAgICAgICAgICBpc09yaWdpbmFsTWF0Y2hlZCxcbiAgICAgICAgICAgICAgaXNDdXJyZW50TWF0Y2hlZCxcbiAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLmhhc2hcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIERlY2lkZSBldmVudCB0eXBlXG4gICAgICAgICAgICBsZXQgdHlwZTtcbiAgICAgICAgICAgIGlmIChpc09yaWdpbmFsTWF0Y2hlZCAmJiBpc0N1cnJlbnRNYXRjaGVkKSB7XG4gICAgICAgICAgICAgIHR5cGUgPSAnVXBkYXRlJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPcmlnaW5hbE1hdGNoZWQgJiYgIWlzQ3VycmVudE1hdGNoZWQpIHtcbiAgICAgICAgICAgICAgdHlwZSA9ICdMZWF2ZSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFpc09yaWdpbmFsTWF0Y2hlZCAmJiBpc0N1cnJlbnRNYXRjaGVkKSB7XG4gICAgICAgICAgICAgIGlmIChvcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgdHlwZSA9ICdFbnRlcic7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHlwZSA9ICdDcmVhdGUnO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGZ1bmN0aW9uTmFtZSA9ICdwdXNoJyArIHR5cGU7XG4gICAgICAgICAgICBjbGllbnRbZnVuY3Rpb25OYW1lXShyZXF1ZXN0SWQsIGN1cnJlbnRQYXJzZU9iamVjdCk7XG4gICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ01hdGNoaW5nIEFDTCBlcnJvciA6ICcsIGVycm9yKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9vbkNvbm5lY3QocGFyc2VXZWJzb2NrZXQ6IGFueSk6IHZvaWQge1xuICAgIHBhcnNlV2Vic29ja2V0Lm9uKCdtZXNzYWdlJywgKHJlcXVlc3QpID0+IHtcbiAgICAgIGlmICh0eXBlb2YgcmVxdWVzdCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXF1ZXN0ID0gSlNPTi5wYXJzZShyZXF1ZXN0KTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKCd1bmFibGUgdG8gcGFyc2UgcmVxdWVzdCcsIHJlcXVlc3QsIGUpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbG9nZ2VyLnZlcmJvc2UoJ1JlcXVlc3Q6ICVqJywgcmVxdWVzdCk7XG5cbiAgICAgIC8vIENoZWNrIHdoZXRoZXIgdGhpcyByZXF1ZXN0IGlzIGEgdmFsaWQgcmVxdWVzdCwgcmV0dXJuIGVycm9yIGRpcmVjdGx5IGlmIG5vdFxuICAgICAgaWYgKCF0djQudmFsaWRhdGUocmVxdWVzdCwgUmVxdWVzdFNjaGVtYVsnZ2VuZXJhbCddKSB8fCAhdHY0LnZhbGlkYXRlKHJlcXVlc3QsIFJlcXVlc3RTY2hlbWFbcmVxdWVzdC5vcF0pKSB7XG4gICAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIDEsIHR2NC5lcnJvci5tZXNzYWdlKTtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdDb25uZWN0IG1lc3NhZ2UgZXJyb3IgJXMnLCB0djQuZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgc3dpdGNoKHJlcXVlc3Qub3ApIHtcbiAgICAgIGNhc2UgJ2Nvbm5lY3QnOlxuICAgICAgICB0aGlzLl9oYW5kbGVDb25uZWN0KHBhcnNlV2Vic29ja2V0LCByZXF1ZXN0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzdWJzY3JpYmUnOlxuICAgICAgICB0aGlzLl9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3VwZGF0ZSc6XG4gICAgICAgIHRoaXMuX2hhbmRsZVVwZGF0ZVN1YnNjcmlwdGlvbihwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndW5zdWJzY3JpYmUnOlxuICAgICAgICB0aGlzLl9oYW5kbGVVbnN1YnNjcmliZShwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMywgJ0dldCB1bmtub3duIG9wZXJhdGlvbicpO1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ0dldCB1bmtub3duIG9wZXJhdGlvbicsIHJlcXVlc3Qub3ApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcGFyc2VXZWJzb2NrZXQub24oJ2Rpc2Nvbm5lY3QnLCAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgQ2xpZW50IGRpc2Nvbm5lY3Q6ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9YCk7XG4gICAgICBjb25zdCBjbGllbnRJZCA9IHBhcnNlV2Vic29ja2V0LmNsaWVudElkO1xuICAgICAgaWYgKCF0aGlzLmNsaWVudHMuaGFzKGNsaWVudElkKSkge1xuICAgICAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgICAgICBldmVudDogJ3dzX2Rpc2Nvbm5lY3RfZXJyb3InLFxuICAgICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgICAgIGVycm9yOiBgVW5hYmxlIHRvIGZpbmQgY2xpZW50ICR7Y2xpZW50SWR9YFxuICAgICAgICB9KTtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBDYW4gbm90IGZpbmQgY2xpZW50ICR7Y2xpZW50SWR9IG9uIGRpc2Nvbm5lY3RgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBEZWxldGUgY2xpZW50XG4gICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudHMuZ2V0KGNsaWVudElkKTtcbiAgICAgIHRoaXMuY2xpZW50cy5kZWxldGUoY2xpZW50SWQpO1xuXG4gICAgICAvLyBEZWxldGUgY2xpZW50IGZyb20gc3Vic2NyaXB0aW9uc1xuICAgICAgZm9yIChjb25zdCBbcmVxdWVzdElkLCBzdWJzY3JpcHRpb25JbmZvXSBvZiBfLmVudHJpZXMoY2xpZW50LnN1YnNjcmlwdGlvbkluZm9zKSkge1xuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBzdWJzY3JpcHRpb25JbmZvLnN1YnNjcmlwdGlvbjtcbiAgICAgICAgc3Vic2NyaXB0aW9uLmRlbGV0ZUNsaWVudFN1YnNjcmlwdGlvbihjbGllbnRJZCwgcmVxdWVzdElkKTtcblxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBubyBjbGllbnQgd2hpY2ggaXMgc3Vic2NyaWJpbmcgdGhpcyBzdWJzY3JpcHRpb24sIHJlbW92ZSBpdCBmcm9tIHN1YnNjcmlwdGlvbnNcbiAgICAgICAgY29uc3QgY2xhc3NTdWJzY3JpcHRpb25zID0gdGhpcy5zdWJzY3JpcHRpb25zLmdldChzdWJzY3JpcHRpb24uY2xhc3NOYW1lKTtcbiAgICAgICAgaWYgKCFzdWJzY3JpcHRpb24uaGFzU3Vic2NyaWJpbmdDbGllbnQoKSkge1xuICAgICAgICAgIGNsYXNzU3Vic2NyaXB0aW9ucy5kZWxldGUoc3Vic2NyaXB0aW9uLmhhc2gpO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIHRoZXJlIGlzIG5vIHN1YnNjcmlwdGlvbnMgdW5kZXIgdGhpcyBjbGFzcywgcmVtb3ZlIGl0IGZyb20gc3Vic2NyaXB0aW9uc1xuICAgICAgICBpZiAoY2xhc3NTdWJzY3JpcHRpb25zLnNpemUgPT09IDApIHtcbiAgICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZGVsZXRlKHN1YnNjcmlwdGlvbi5jbGFzc05hbWUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxvZ2dlci52ZXJib3NlKCdDdXJyZW50IGNsaWVudHMgJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG4gICAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBzdWJzY3JpcHRpb25zICVkJywgdGhpcy5zdWJzY3JpcHRpb25zLnNpemUpO1xuICAgICAgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyh7XG4gICAgICAgIGV2ZW50OiAnd3NfZGlzY29ubmVjdCcsXG4gICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICBzdWJzY3JpcHRpb25zOiB0aGlzLnN1YnNjcmlwdGlvbnMuc2l6ZVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgIGV2ZW50OiAnd3NfY29ubmVjdCcsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplXG4gICAgfSk7XG4gIH1cblxuICBfbWF0Y2hlc1N1YnNjcmlwdGlvbihwYXJzZU9iamVjdDogYW55LCBzdWJzY3JpcHRpb246IGFueSk6IGJvb2xlYW4ge1xuICAgIC8vIE9iamVjdCBpcyB1bmRlZmluZWQgb3IgbnVsbCwgbm90IG1hdGNoXG4gICAgaWYgKCFwYXJzZU9iamVjdCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gbWF0Y2hlc1F1ZXJ5KHBhcnNlT2JqZWN0LCBzdWJzY3JpcHRpb24ucXVlcnkpO1xuICB9XG5cbiAgX21hdGNoZXNBQ0woYWNsOiBhbnksIGNsaWVudDogYW55LCByZXF1ZXN0SWQ6IG51bWJlcik6IGFueSB7XG4gICAgLy8gUmV0dXJuIHRydWUgZGlyZWN0bHkgaWYgQUNMIGlzbid0IHByZXNlbnQsIEFDTCBpcyBwdWJsaWMgcmVhZCwgb3IgY2xpZW50IGhhcyBtYXN0ZXIga2V5XG4gICAgaWYgKCFhY2wgfHwgYWNsLmdldFB1YmxpY1JlYWRBY2Nlc3MoKSB8fCBjbGllbnQuaGFzTWFzdGVyS2V5KSB7XG4gICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyh0cnVlKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgc3Vic2NyaXB0aW9uIHNlc3Npb25Ub2tlbiBtYXRjaGVzIEFDTCBmaXJzdFxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIGlmICh0eXBlb2Ygc3Vic2NyaXB0aW9uSW5mbyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKGZhbHNlKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb25TZXNzaW9uVG9rZW4gPSBzdWJzY3JpcHRpb25JbmZvLnNlc3Npb25Ub2tlbjtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uVG9rZW5DYWNoZS5nZXRVc2VySWQoc3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuKS50aGVuKCh1c2VySWQpID0+IHtcbiAgICAgIHJldHVybiBhY2wuZ2V0UmVhZEFjY2Vzcyh1c2VySWQpO1xuICAgIH0pLnRoZW4oKGlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCkgPT4ge1xuICAgICAgaWYgKGlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCkge1xuICAgICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyh0cnVlKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhlIHVzZXIgaGFzIGFueSByb2xlcyB0aGF0IG1hdGNoIHRoZSBBQ0xcbiAgICAgIHJldHVybiBuZXcgUGFyc2UuUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBmYWxzZSByaWdodCBhd2F5IGlmIHRoZSBhY2wgZG9lc24ndCBoYXZlIGFueSByb2xlc1xuICAgICAgICBjb25zdCBhY2xfaGFzX3JvbGVzID0gT2JqZWN0LmtleXMoYWNsLnBlcm1pc3Npb25zQnlJZCkuc29tZShrZXkgPT4ga2V5LnN0YXJ0c1dpdGgoXCJyb2xlOlwiKSk7XG4gICAgICAgIGlmICghYWNsX2hhc19yb2xlcykge1xuICAgICAgICAgIHJldHVybiByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2Vzc2lvblRva2VuQ2FjaGUuZ2V0VXNlcklkKHN1YnNjcmlwdGlvblNlc3Npb25Ub2tlbilcbiAgICAgICAgICAudGhlbigodXNlcklkKSA9PiB7XG5cbiAgICAgICAgICAgIC8vIFBhc3MgYWxvbmcgYSBudWxsIGlmIHRoZXJlIGlzIG5vIHVzZXIgaWRcbiAgICAgICAgICAgIGlmICghdXNlcklkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKG51bGwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQcmVwYXJlIGEgdXNlciBvYmplY3QgdG8gcXVlcnkgZm9yIHJvbGVzXG4gICAgICAgICAgICAvLyBUbyBlbGltaW5hdGUgYSBxdWVyeSBmb3IgdGhlIHVzZXIsIGNyZWF0ZSBvbmUgbG9jYWxseSB3aXRoIHRoZSBpZFxuICAgICAgICAgICAgdmFyIHVzZXIgPSBuZXcgUGFyc2UuVXNlcigpO1xuICAgICAgICAgICAgdXNlci5pZCA9IHVzZXJJZDtcbiAgICAgICAgICAgIHJldHVybiB1c2VyO1xuXG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbigodXNlcikgPT4ge1xuXG4gICAgICAgICAgICAvLyBQYXNzIGFsb25nIGFuIGVtcHR5IGFycmF5IChvZiByb2xlcykgaWYgbm8gdXNlclxuICAgICAgICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKFtdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVGhlbiBnZXQgdGhlIHVzZXIncyByb2xlc1xuICAgICAgICAgICAgdmFyIHJvbGVzUXVlcnkgPSBuZXcgUGFyc2UuUXVlcnkoUGFyc2UuUm9sZSk7XG4gICAgICAgICAgICByb2xlc1F1ZXJ5LmVxdWFsVG8oXCJ1c2Vyc1wiLCB1c2VyKTtcbiAgICAgICAgICAgIHJldHVybiByb2xlc1F1ZXJ5LmZpbmQoe3VzZU1hc3RlcktleTp0cnVlfSk7XG4gICAgICAgICAgfSkuXG4gICAgICAgICAgdGhlbigocm9sZXMpID0+IHtcblxuICAgICAgICAgICAgLy8gRmluYWxseSwgc2VlIGlmIGFueSBvZiB0aGUgdXNlcidzIHJvbGVzIGFsbG93IHRoZW0gcmVhZCBhY2Nlc3NcbiAgICAgICAgICAgIGZvciAoY29uc3Qgcm9sZSBvZiByb2xlcykge1xuICAgICAgICAgICAgICBpZiAoYWNsLmdldFJvbGVSZWFkQWNjZXNzKHJvbGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgfSk7XG4gICAgfSkudGhlbigoaXNSb2xlTWF0Y2hlZCkgPT4ge1xuXG4gICAgICBpZihpc1JvbGVNYXRjaGVkKSB7XG4gICAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKHRydWUpO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBjbGllbnQgc2Vzc2lvblRva2VuIG1hdGNoZXMgQUNMXG4gICAgICBjb25zdCBjbGllbnRTZXNzaW9uVG9rZW4gPSBjbGllbnQuc2Vzc2lvblRva2VuO1xuICAgICAgcmV0dXJuIHRoaXMuc2Vzc2lvblRva2VuQ2FjaGUuZ2V0VXNlcklkKGNsaWVudFNlc3Npb25Ub2tlbikudGhlbigodXNlcklkKSA9PiB7XG4gICAgICAgIHJldHVybiBhY2wuZ2V0UmVhZEFjY2Vzcyh1c2VySWQpO1xuICAgICAgfSk7XG4gICAgfSkudGhlbigoaXNNYXRjaGVkKSA9PiB7XG4gICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyhpc01hdGNoZWQpO1xuICAgIH0sICgpID0+IHtcbiAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKGZhbHNlKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9oYW5kbGVDb25uZWN0KHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSk6IGFueSB7XG4gICAgaWYgKCF0aGlzLl92YWxpZGF0ZUtleXMocmVxdWVzdCwgdGhpcy5rZXlQYWlycykpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIDQsICdLZXkgaW4gcmVxdWVzdCBpcyBub3QgdmFsaWQnKTtcbiAgICAgIGxvZ2dlci5lcnJvcignS2V5IGluIHJlcXVlc3QgaXMgbm90IHZhbGlkJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGhhc01hc3RlcktleSA9IHRoaXMuX2hhc01hc3RlcktleShyZXF1ZXN0LCB0aGlzLmtleVBhaXJzKTtcbiAgICBjb25zdCBjbGllbnRJZCA9IHV1aWQoKTtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgQ2xpZW50KGNsaWVudElkLCBwYXJzZVdlYnNvY2tldCwgaGFzTWFzdGVyS2V5KTtcbiAgICBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCA9IGNsaWVudElkO1xuICAgIHRoaXMuY2xpZW50cy5zZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIGNsaWVudCk7XG4gICAgbG9nZ2VyLmluZm8oYENyZWF0ZSBuZXcgY2xpZW50OiAke3BhcnNlV2Vic29ja2V0LmNsaWVudElkfWApO1xuICAgIGNsaWVudC5wdXNoQ29ubmVjdCgpO1xuICAgIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMoe1xuICAgICAgZXZlbnQ6ICdjb25uZWN0JyxcbiAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgc3Vic2NyaXB0aW9uczogdGhpcy5zdWJzY3JpcHRpb25zLnNpemVcbiAgICB9KTtcbiAgfVxuXG4gIF9oYXNNYXN0ZXJLZXkocmVxdWVzdDogYW55LCB2YWxpZEtleVBhaXJzOiBhbnkpOiBib29sZWFuIHtcbiAgICBpZighdmFsaWRLZXlQYWlycyB8fCB2YWxpZEtleVBhaXJzLnNpemUgPT0gMCB8fFxuICAgICAgIXZhbGlkS2V5UGFpcnMuaGFzKFwibWFzdGVyS2V5XCIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmKCFyZXF1ZXN0IHx8ICFyZXF1ZXN0Lmhhc093blByb3BlcnR5KFwibWFzdGVyS2V5XCIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiByZXF1ZXN0Lm1hc3RlcktleSA9PT0gdmFsaWRLZXlQYWlycy5nZXQoXCJtYXN0ZXJLZXlcIik7XG4gIH1cblxuICBfdmFsaWRhdGVLZXlzKHJlcXVlc3Q6IGFueSwgdmFsaWRLZXlQYWlyczogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKCF2YWxpZEtleVBhaXJzIHx8IHZhbGlkS2V5UGFpcnMuc2l6ZSA9PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgbGV0IGlzVmFsaWQgPSBmYWxzZTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHNlY3JldF0gb2YgdmFsaWRLZXlQYWlycykge1xuICAgICAgaWYgKCFyZXF1ZXN0W2tleV0gfHwgcmVxdWVzdFtrZXldICE9PSBzZWNyZXQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpc1ZhbGlkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gaXNWYWxpZDtcbiAgfVxuXG4gIF9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQ6IGFueSwgcmVxdWVzdDogYW55KTogYW55IHtcbiAgICAvLyBJZiB3ZSBjYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIHJldHVybiBlcnJvciB0byBjbGllbnRcbiAgICBpZiAoIXBhcnNlV2Vic29ja2V0Lmhhc093blByb3BlcnR5KCdjbGllbnRJZCcpKSB7XG4gICAgICBDbGllbnQucHVzaEVycm9yKHBhcnNlV2Vic29ja2V0LCAyLCAnQ2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCBtYWtlIHN1cmUgeW91IGNvbm5lY3QgdG8gc2VydmVyIGJlZm9yZSBzdWJzY3JpYmluZycpO1xuICAgICAgbG9nZ2VyLmVycm9yKCdDYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIG1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBzZXJ2ZXIgYmVmb3JlIHN1YnNjcmliaW5nJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQpO1xuXG4gICAgLy8gR2V0IHN1YnNjcmlwdGlvbiBmcm9tIHN1YnNjcmlwdGlvbnMsIGNyZWF0ZSBvbmUgaWYgbmVjZXNzYXJ5XG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uSGFzaCA9IHF1ZXJ5SGFzaChyZXF1ZXN0LnF1ZXJ5KTtcbiAgICAvLyBBZGQgY2xhc3NOYW1lIHRvIHN1YnNjcmlwdGlvbnMgaWYgbmVjZXNzYXJ5XG4gICAgY29uc3QgY2xhc3NOYW1lID0gcmVxdWVzdC5xdWVyeS5jbGFzc05hbWU7XG4gICAgaWYgKCF0aGlzLnN1YnNjcmlwdGlvbnMuaGFzKGNsYXNzTmFtZSkpIHtcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5zZXQoY2xhc3NOYW1lLCBuZXcgTWFwKCkpO1xuICAgIH1cbiAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgbGV0IHN1YnNjcmlwdGlvbjtcbiAgICBpZiAoY2xhc3NTdWJzY3JpcHRpb25zLmhhcyhzdWJzY3JpcHRpb25IYXNoKSkge1xuICAgICAgc3Vic2NyaXB0aW9uID0gY2xhc3NTdWJzY3JpcHRpb25zLmdldChzdWJzY3JpcHRpb25IYXNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbihjbGFzc05hbWUsIHJlcXVlc3QucXVlcnkud2hlcmUsIHN1YnNjcmlwdGlvbkhhc2gpO1xuICAgICAgY2xhc3NTdWJzY3JpcHRpb25zLnNldChzdWJzY3JpcHRpb25IYXNoLCBzdWJzY3JpcHRpb24pO1xuICAgIH1cblxuICAgIC8vIEFkZCBzdWJzY3JpcHRpb25JbmZvIHRvIGNsaWVudFxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSB7XG4gICAgICBzdWJzY3JpcHRpb246IHN1YnNjcmlwdGlvblxuICAgIH07XG4gICAgLy8gQWRkIHNlbGVjdGVkIGZpZWxkcyBhbmQgc2Vzc2lvblRva2VuIGZvciB0aGlzIHN1YnNjcmlwdGlvbiBpZiBuZWNlc3NhcnlcbiAgICBpZiAocmVxdWVzdC5xdWVyeS5maWVsZHMpIHtcbiAgICAgIHN1YnNjcmlwdGlvbkluZm8uZmllbGRzID0gcmVxdWVzdC5xdWVyeS5maWVsZHM7XG4gICAgfVxuICAgIGlmIChyZXF1ZXN0LnNlc3Npb25Ub2tlbikge1xuICAgICAgc3Vic2NyaXB0aW9uSW5mby5zZXNzaW9uVG9rZW4gPSByZXF1ZXN0LnNlc3Npb25Ub2tlbjtcbiAgICB9XG4gICAgY2xpZW50LmFkZFN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdC5yZXF1ZXN0SWQsIHN1YnNjcmlwdGlvbkluZm8pO1xuXG4gICAgLy8gQWRkIGNsaWVudElkIHRvIHN1YnNjcmlwdGlvblxuICAgIHN1YnNjcmlwdGlvbi5hZGRDbGllbnRTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIHJlcXVlc3QucmVxdWVzdElkKTtcblxuICAgIGNsaWVudC5wdXNoU3Vic2NyaWJlKHJlcXVlc3QucmVxdWVzdElkKTtcblxuICAgIGxvZ2dlci52ZXJib3NlKGBDcmVhdGUgY2xpZW50ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9IG5ldyBzdWJzY3JpcHRpb246ICR7cmVxdWVzdC5yZXF1ZXN0SWR9YCk7XG4gICAgbG9nZ2VyLnZlcmJvc2UoJ0N1cnJlbnQgY2xpZW50IG51bWJlcjogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG4gICAgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyh7XG4gICAgICBldmVudDogJ3N1YnNjcmliZScsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplXG4gICAgfSk7XG4gIH1cblxuICBfaGFuZGxlVXBkYXRlU3Vic2NyaXB0aW9uKHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSk6IGFueSB7XG4gICAgdGhpcy5faGFuZGxlVW5zdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QsIGZhbHNlKTtcbiAgICB0aGlzLl9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICB9XG5cbiAgX2hhbmRsZVVuc3Vic2NyaWJlKHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSwgbm90aWZ5Q2xpZW50OiBib29sID0gdHJ1ZSk6IGFueSB7XG4gICAgLy8gSWYgd2UgY2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCByZXR1cm4gZXJyb3IgdG8gY2xpZW50XG4gICAgaWYgKCFwYXJzZVdlYnNvY2tldC5oYXNPd25Qcm9wZXJ0eSgnY2xpZW50SWQnKSkge1xuICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMiwgJ0NhbiBub3QgZmluZCB0aGlzIGNsaWVudCwgbWFrZSBzdXJlIHlvdSBjb25uZWN0IHRvIHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZycpO1xuICAgICAgbG9nZ2VyLmVycm9yKCdDYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIG1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBzZXJ2ZXIgYmVmb3JlIHVuc3Vic2NyaWJpbmcnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcmVxdWVzdElkID0gcmVxdWVzdC5yZXF1ZXN0SWQ7XG4gICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnRzLmdldChwYXJzZVdlYnNvY2tldC5jbGllbnRJZCk7XG4gICAgaWYgKHR5cGVvZiBjbGllbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBDbGllbnQucHVzaEVycm9yKHBhcnNlV2Vic29ja2V0LCAyLCAnQ2Fubm90IGZpbmQgY2xpZW50IHdpdGggY2xpZW50SWQgJyAgKyBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCArXG4gICAgICAgICcuIE1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBsaXZlIHF1ZXJ5IHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZy4nKTtcbiAgICAgIGxvZ2dlci5lcnJvcignQ2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50ICcgKyBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uSW5mbyA9IGNsaWVudC5nZXRTdWJzY3JpcHRpb25JbmZvKHJlcXVlc3RJZCk7XG4gICAgaWYgKHR5cGVvZiBzdWJzY3JpcHRpb25JbmZvID09PSAndW5kZWZpbmVkJykge1xuICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMiwgJ0Nhbm5vdCBmaW5kIHN1YnNjcmlwdGlvbiB3aXRoIGNsaWVudElkICcgICsgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQgK1xuICAgICAgICAnIHN1YnNjcmlwdGlvbklkICcgKyByZXF1ZXN0SWQgKyAnLiBNYWtlIHN1cmUgeW91IHN1YnNjcmliZSB0byBsaXZlIHF1ZXJ5IHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZy4nKTtcbiAgICAgIGxvZ2dlci5lcnJvcignQ2FuIG5vdCBmaW5kIHN1YnNjcmlwdGlvbiB3aXRoIGNsaWVudElkICcgKyBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCArICAnIHN1YnNjcmlwdGlvbklkICcgKyByZXF1ZXN0SWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFJlbW92ZSBzdWJzY3JpcHRpb24gZnJvbSBjbGllbnRcbiAgICBjbGllbnQuZGVsZXRlU3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIC8vIFJlbW92ZSBjbGllbnQgZnJvbSBzdWJzY3JpcHRpb25cbiAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBzdWJzY3JpcHRpb25JbmZvLnN1YnNjcmlwdGlvbjtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBzdWJzY3JpcHRpb24uY2xhc3NOYW1lO1xuICAgIHN1YnNjcmlwdGlvbi5kZWxldGVDbGllbnRTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIHJlcXVlc3RJZCk7XG4gICAgLy8gSWYgdGhlcmUgaXMgbm8gY2xpZW50IHdoaWNoIGlzIHN1YnNjcmliaW5nIHRoaXMgc3Vic2NyaXB0aW9uLCByZW1vdmUgaXQgZnJvbSBzdWJzY3JpcHRpb25zXG4gICAgY29uc3QgY2xhc3NTdWJzY3JpcHRpb25zID0gdGhpcy5zdWJzY3JpcHRpb25zLmdldChjbGFzc05hbWUpO1xuICAgIGlmICghc3Vic2NyaXB0aW9uLmhhc1N1YnNjcmliaW5nQ2xpZW50KCkpIHtcbiAgICAgIGNsYXNzU3Vic2NyaXB0aW9ucy5kZWxldGUoc3Vic2NyaXB0aW9uLmhhc2gpO1xuICAgIH1cbiAgICAvLyBJZiB0aGVyZSBpcyBubyBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MsIHJlbW92ZSBpdCBmcm9tIHN1YnNjcmlwdGlvbnNcbiAgICBpZiAoY2xhc3NTdWJzY3JpcHRpb25zLnNpemUgPT09IDApIHtcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5kZWxldGUoY2xhc3NOYW1lKTtcbiAgICB9XG4gICAgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyh7XG4gICAgICBldmVudDogJ3Vuc3Vic2NyaWJlJyxcbiAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgc3Vic2NyaXB0aW9uczogdGhpcy5zdWJzY3JpcHRpb25zLnNpemVcbiAgICB9KTtcblxuICAgIGlmICghbm90aWZ5Q2xpZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY2xpZW50LnB1c2hVbnN1YnNjcmliZShyZXF1ZXN0LnJlcXVlc3RJZCk7XG5cbiAgICBsb2dnZXIudmVyYm9zZShgRGVsZXRlIGNsaWVudDogJHtwYXJzZVdlYnNvY2tldC5jbGllbnRJZH0gfCBzdWJzY3JpcHRpb246ICR7cmVxdWVzdC5yZXF1ZXN0SWR9YCk7XG4gIH1cbn1cblxuZXhwb3J0IHtcbiAgUGFyc2VMaXZlUXVlcnlTZXJ2ZXJcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/LiveQuery/ParsePubSub.js b/lib/LiveQuery/ParsePubSub.js index 6686db2607..624907f58e 100644 --- a/lib/LiveQuery/ParsePubSub.js +++ b/lib/LiveQuery/ParsePubSub.js @@ -42,4 +42,5 @@ ParsePubSub.createSubscriber = function (config) { } }; -exports.ParsePubSub = ParsePubSub; \ No newline at end of file +exports.ParsePubSub = ParsePubSub; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VQdWJTdWIuanMiXSwibmFtZXMiOlsiUGFyc2VQdWJTdWIiLCJ1c2VSZWRpcyIsImNvbmZpZyIsInJlZGlzVVJMIiwiY3JlYXRlUHVibGlzaGVyIiwiUmVkaXNQdWJTdWIiLCJhZGFwdGVyIiwicHViU3ViQWRhcHRlciIsIkV2ZW50RW1pdHRlclB1YlN1YiIsImNyZWF0ZVN1YnNjcmliZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFJQTs7QUFJQSxNQUFNQSxjQUFjLEVBQXBCOztBQUVBLFNBQVNDLFFBQVQsQ0FBa0JDLE1BQWxCLEVBQXdDO0FBQ3RDLFFBQU1DLFdBQVdELE9BQU9DLFFBQXhCO0FBQ0EsU0FBTyxPQUFPQSxRQUFQLEtBQW9CLFdBQXBCLElBQW1DQSxhQUFhLEVBQXZEO0FBQ0Q7O0FBRURILFlBQVlJLGVBQVosR0FBOEIsVUFBU0YsTUFBVCxFQUEyQjtBQUN2RCxNQUFJRCxTQUFTQyxNQUFULENBQUosRUFBc0I7QUFDcEIsV0FBT0cseUJBQVlELGVBQVosQ0FBNEJGLE1BQTVCLENBQVA7QUFDRCxHQUZELE1BRU87QUFDTCxVQUFNSSxVQUFVLGdDQUFZSixPQUFPSyxhQUFuQixFQUFrQ0Msc0NBQWxDLEVBQXNETixNQUF0RCxDQUFoQjtBQUNBLFFBQUksT0FBT0ksUUFBUUYsZUFBZixLQUFtQyxVQUF2QyxFQUFtRDtBQUNqRCxZQUFNLDZDQUFOO0FBQ0Q7QUFDRCxXQUFPRSxRQUFRRixlQUFSLENBQXdCRixNQUF4QixDQUFQO0FBQ0Q7QUFDRixDQVZEOztBQVlBRixZQUFZUyxnQkFBWixHQUErQixVQUFTUCxNQUFULEVBQTRCO0FBQ3pELE1BQUlELFNBQVNDLE1BQVQsQ0FBSixFQUFzQjtBQUNwQixXQUFPRyx5QkFBWUksZ0JBQVosQ0FBNkJQLE1BQTdCLENBQVA7QUFDRCxHQUZELE1BRU87QUFDTCxVQUFNSSxVQUFVLGdDQUFZSixPQUFPSyxhQUFuQixFQUFrQ0Msc0NBQWxDLEVBQXNETixNQUF0RCxDQUFoQjtBQUNBLFFBQUksT0FBT0ksUUFBUUcsZ0JBQWYsS0FBb0MsVUFBeEMsRUFBb0Q7QUFDbEQsWUFBTSw4Q0FBTjtBQUNEO0FBQ0QsV0FBT0gsUUFBUUcsZ0JBQVIsQ0FBeUJQLE1BQXpCLENBQVA7QUFDRDtBQUNGLENBVkQ7O1FBYUVGLFcsR0FBQUEsVyIsImZpbGUiOiJQYXJzZVB1YlN1Yi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGxvYWRBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQWRhcHRlckxvYWRlcic7XG5pbXBvcnQge1xuICBFdmVudEVtaXR0ZXJQdWJTdWJcbn0gZnJvbSAnLi4vQWRhcHRlcnMvUHViU3ViL0V2ZW50RW1pdHRlclB1YlN1Yic7XG5cbmltcG9ydCB7XG4gIFJlZGlzUHViU3ViXG59IGZyb20gJy4uL0FkYXB0ZXJzL1B1YlN1Yi9SZWRpc1B1YlN1Yic7XG5cbmNvbnN0IFBhcnNlUHViU3ViID0ge307XG5cbmZ1bmN0aW9uIHVzZVJlZGlzKGNvbmZpZzogYW55KTogYm9vbGVhbiB7XG4gIGNvbnN0IHJlZGlzVVJMID0gY29uZmlnLnJlZGlzVVJMO1xuICByZXR1cm4gdHlwZW9mIHJlZGlzVVJMICE9PSAndW5kZWZpbmVkJyAmJiByZWRpc1VSTCAhPT0gJyc7XG59XG5cblBhcnNlUHViU3ViLmNyZWF0ZVB1Ymxpc2hlciA9IGZ1bmN0aW9uKGNvbmZpZzogYW55KTogYW55IHtcbiAgaWYgKHVzZVJlZGlzKGNvbmZpZykpIHtcbiAgICByZXR1cm4gUmVkaXNQdWJTdWIuY3JlYXRlUHVibGlzaGVyKGNvbmZpZyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYWRhcHRlciA9IGxvYWRBZGFwdGVyKGNvbmZpZy5wdWJTdWJBZGFwdGVyLCBFdmVudEVtaXR0ZXJQdWJTdWIsIGNvbmZpZylcbiAgICBpZiAodHlwZW9mIGFkYXB0ZXIuY3JlYXRlUHVibGlzaGVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyAncHViU3ViQWRhcHRlciBzaG91bGQgaGF2ZSBjcmVhdGVQdWJsaXNoZXIoKSc7XG4gICAgfVxuICAgIHJldHVybiBhZGFwdGVyLmNyZWF0ZVB1Ymxpc2hlcihjb25maWcpO1xuICB9XG59XG5cblBhcnNlUHViU3ViLmNyZWF0ZVN1YnNjcmliZXIgPSBmdW5jdGlvbihjb25maWc6IGFueSk6IHZvaWQge1xuICBpZiAodXNlUmVkaXMoY29uZmlnKSkge1xuICAgIHJldHVybiBSZWRpc1B1YlN1Yi5jcmVhdGVTdWJzY3JpYmVyKGNvbmZpZyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYWRhcHRlciA9IGxvYWRBZGFwdGVyKGNvbmZpZy5wdWJTdWJBZGFwdGVyLCBFdmVudEVtaXR0ZXJQdWJTdWIsIGNvbmZpZylcbiAgICBpZiAodHlwZW9mIGFkYXB0ZXIuY3JlYXRlU3Vic2NyaWJlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhyb3cgJ3B1YlN1YkFkYXB0ZXIgc2hvdWxkIGhhdmUgY3JlYXRlU3Vic2NyaWJlcigpJztcbiAgICB9XG4gICAgcmV0dXJuIGFkYXB0ZXIuY3JlYXRlU3Vic2NyaWJlcihjb25maWcpO1xuICB9XG59XG5cbmV4cG9ydCB7XG4gIFBhcnNlUHViU3ViXG59XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/ParseWebSocketServer.js b/lib/LiveQuery/ParseWebSocketServer.js index f59723886c..7c4e8f4e0f 100644 --- a/lib/LiveQuery/ParseWebSocketServer.js +++ b/lib/LiveQuery/ParseWebSocketServer.js @@ -59,4 +59,5 @@ class ParseWebSocket { this.ws.send(message); } } -exports.ParseWebSocket = ParseWebSocket; \ No newline at end of file +exports.ParseWebSocket = ParseWebSocket; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VXZWJTb2NrZXRTZXJ2ZXIuanMiXSwibmFtZXMiOlsidHlwZU1hcCIsIk1hcCIsImdldFdTIiwicmVxdWlyZSIsImUiLCJQYXJzZVdlYlNvY2tldFNlcnZlciIsImNvbnN0cnVjdG9yIiwic2VydmVyIiwib25Db25uZWN0Iiwid2Vic29ja2V0VGltZW91dCIsIldlYlNvY2tldFNlcnZlciIsIlNlcnZlciIsIndzcyIsIm9uIiwibG9nZ2VyIiwiaW5mbyIsIndzIiwiUGFyc2VXZWJTb2NrZXQiLCJwaW5nSW50ZXJ2YWxJZCIsInNldEludGVydmFsIiwicmVhZHlTdGF0ZSIsIk9QRU4iLCJwaW5nIiwiY2xlYXJJbnRlcnZhbCIsInR5cGUiLCJjYWxsYmFjayIsIndzVHlwZSIsImhhcyIsImdldCIsInNlbmQiLCJtZXNzYWdlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7OztBQUVBLE1BQU1BLFVBQVUsSUFBSUMsR0FBSixDQUFRLENBQUMsQ0FBQyxZQUFELEVBQWUsT0FBZixDQUFELENBQVIsQ0FBaEI7QUFDQSxNQUFNQyxRQUFRLFlBQVc7QUFDdkIsTUFBSTtBQUNGLFdBQU9DLFFBQVEsS0FBUixDQUFQO0FBQ0QsR0FGRCxDQUVFLE9BQU1DLENBQU4sRUFBUztBQUNULFdBQU9ELFFBQVEsSUFBUixDQUFQO0FBQ0Q7QUFDRixDQU5EOztBQVFPLE1BQU1FLG9CQUFOLENBQTJCOztBQUdoQ0MsY0FBWUMsTUFBWixFQUF5QkMsU0FBekIsRUFBOENDLG1CQUEyQixLQUFLLElBQTlFLEVBQW9GO0FBQ2xGLFVBQU1DLGtCQUFrQlIsUUFBUVMsTUFBaEM7QUFDQSxVQUFNQyxNQUFNLElBQUlGLGVBQUosQ0FBb0IsRUFBRUgsUUFBUUEsTUFBVixFQUFwQixDQUFaO0FBQ0FLLFFBQUlDLEVBQUosQ0FBTyxXQUFQLEVBQW9CLE1BQU07QUFDeEJDLHVCQUFPQyxJQUFQLENBQVksdUNBQVo7QUFDRCxLQUZEO0FBR0FILFFBQUlDLEVBQUosQ0FBTyxZQUFQLEVBQXNCRyxFQUFELElBQVE7QUFDM0JSLGdCQUFVLElBQUlTLGNBQUosQ0FBbUJELEVBQW5CLENBQVY7QUFDQTtBQUNBLFlBQU1FLGlCQUFpQkMsWUFBWSxNQUFNO0FBQ3ZDLFlBQUlILEdBQUdJLFVBQUgsSUFBaUJKLEdBQUdLLElBQXhCLEVBQThCO0FBQzVCTCxhQUFHTSxJQUFIO0FBQ0QsU0FGRCxNQUVPO0FBQ0xDLHdCQUFjTCxjQUFkO0FBQ0Q7QUFDRixPQU5zQixFQU1wQlQsZ0JBTm9CLENBQXZCO0FBT0QsS0FWRDtBQVdBLFNBQUtGLE1BQUwsR0FBY0ssR0FBZDtBQUNEO0FBckIrQjs7UUFBckJQLG9CLEdBQUFBLG9CO0FBd0JOLE1BQU1ZLGNBQU4sQ0FBcUI7O0FBRzFCWCxjQUFZVSxFQUFaLEVBQXFCO0FBQ25CLFNBQUtBLEVBQUwsR0FBVUEsRUFBVjtBQUNEOztBQUVESCxLQUFHVyxJQUFILEVBQWlCQyxRQUFqQixFQUFpQztBQUMvQixVQUFNQyxTQUFTMUIsUUFBUTJCLEdBQVIsQ0FBWUgsSUFBWixJQUFvQnhCLFFBQVE0QixHQUFSLENBQVlKLElBQVosQ0FBcEIsR0FBd0NBLElBQXZEO0FBQ0EsU0FBS1IsRUFBTCxDQUFRSCxFQUFSLENBQVdhLE1BQVgsRUFBbUJELFFBQW5CO0FBQ0Q7O0FBRURJLE9BQUtDLE9BQUwsRUFBeUI7QUFDdkIsU0FBS2QsRUFBTCxDQUFRYSxJQUFSLENBQWFDLE9BQWI7QUFDRDtBQWR5QjtRQUFmYixjLEdBQUFBLGMiLCJmaWxlIjoiUGFyc2VXZWJTb2NrZXRTZXJ2ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5cbmNvbnN0IHR5cGVNYXAgPSBuZXcgTWFwKFtbJ2Rpc2Nvbm5lY3QnLCAnY2xvc2UnXV0pO1xuY29uc3QgZ2V0V1MgPSBmdW5jdGlvbigpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gcmVxdWlyZSgndXdzJyk7XG4gIH0gY2F0Y2goZSkge1xuICAgIHJldHVybiByZXF1aXJlKCd3cycpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQYXJzZVdlYlNvY2tldFNlcnZlciB7XG4gIHNlcnZlcjogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcjogYW55LCBvbkNvbm5lY3Q6IEZ1bmN0aW9uLCB3ZWJzb2NrZXRUaW1lb3V0OiBudW1iZXIgPSAxMCAqIDEwMDApIHtcbiAgICBjb25zdCBXZWJTb2NrZXRTZXJ2ZXIgPSBnZXRXUygpLlNlcnZlcjtcbiAgICBjb25zdCB3c3MgPSBuZXcgV2ViU29ja2V0U2VydmVyKHsgc2VydmVyOiBzZXJ2ZXIgfSk7XG4gICAgd3NzLm9uKCdsaXN0ZW5pbmcnLCAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbygnUGFyc2UgTGl2ZVF1ZXJ5IFNlcnZlciBzdGFydHMgcnVubmluZycpO1xuICAgIH0pO1xuICAgIHdzcy5vbignY29ubmVjdGlvbicsICh3cykgPT4ge1xuICAgICAgb25Db25uZWN0KG5ldyBQYXJzZVdlYlNvY2tldCh3cykpO1xuICAgICAgLy8gU2VuZCBwaW5nIHRvIGNsaWVudCBwZXJpb2RpY2FsbHlcbiAgICAgIGNvbnN0IHBpbmdJbnRlcnZhbElkID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBpZiAod3MucmVhZHlTdGF0ZSA9PSB3cy5PUEVOKSB7XG4gICAgICAgICAgd3MucGluZygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsSWQpO1xuICAgICAgICB9XG4gICAgICB9LCB3ZWJzb2NrZXRUaW1lb3V0KTtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlciA9IHdzcztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUGFyc2VXZWJTb2NrZXQge1xuICB3czogYW55O1xuXG4gIGNvbnN0cnVjdG9yKHdzOiBhbnkpIHtcbiAgICB0aGlzLndzID0gd3M7XG4gIH1cblxuICBvbih0eXBlOiBzdHJpbmcsIGNhbGxiYWNrKTogdm9pZCB7XG4gICAgY29uc3Qgd3NUeXBlID0gdHlwZU1hcC5oYXModHlwZSkgPyB0eXBlTWFwLmdldCh0eXBlKSA6IHR5cGU7XG4gICAgdGhpcy53cy5vbih3c1R5cGUsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIHNlbmQobWVzc2FnZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy53cy5zZW5kKG1lc3NhZ2UpO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/QueryTools.js b/lib/LiveQuery/QueryTools.js index 74d528c8f8..905c842d00 100644 --- a/lib/LiveQuery/QueryTools.js +++ b/lib/LiveQuery/QueryTools.js @@ -317,4 +317,5 @@ var QueryTools = { matchesQuery: matchesQuery }; -module.exports = QueryTools; \ No newline at end of file +module.exports = QueryTools; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUXVlcnlUb29scy5qcyJdLCJuYW1lcyI6WyJlcXVhbE9iamVjdHMiLCJyZXF1aXJlIiwiSWQiLCJQYXJzZSIsImZsYXR0ZW5PclF1ZXJpZXMiLCJ3aGVyZSIsImhhc093blByb3BlcnR5IiwiYWNjdW0iLCJpIiwiJG9yIiwibGVuZ3RoIiwiY29uY2F0Iiwic3RyaW5naWZ5Iiwib2JqZWN0IiwicmVwbGFjZSIsIkFycmF5IiwiaXNBcnJheSIsImNvcHkiLCJtYXAiLCJzb3J0Iiwiam9pbiIsInNlY3Rpb25zIiwia2V5cyIsIk9iamVjdCIsImsiLCJwdXNoIiwicXVlcnlIYXNoIiwicXVlcnkiLCJRdWVyeSIsImNsYXNzTmFtZSIsIl93aGVyZSIsImNvbHVtbnMiLCJ2YWx1ZXMiLCJ1bmlxdWVDb2x1bW5zIiwic3ViVmFsdWVzIiwiaiIsImNvbnRhaW5zIiwiaGF5c3RhY2siLCJuZWVkbGUiLCJfX3R5cGUiLCJwdHIiLCJvYmplY3RJZCIsImluZGV4T2YiLCJtYXRjaGVzUXVlcnkiLCJpZCIsImZpZWxkIiwibWF0Y2hlc0tleUNvbnN0cmFpbnRzIiwiZXF1YWxPYmplY3RzR2VuZXJpYyIsIm9iaiIsImNvbXBhcmVUbyIsImVxbEZuIiwia2V5IiwiY29uc3RyYWludHMiLCJrZXlDb21wb25lbnRzIiwic3BsaXQiLCJzdWJPYmplY3RLZXkiLCJrZXlSZW1haW5kZXIiLCJzbGljZSIsIl9kZWNvZGUiLCJjb25kaXRpb24iLCJwcm9wZXJ0eUV4aXN0cyIsImV4aXN0ZW5jZUlzUmVxdWlyZWQiLCJ0ZXN0IiwiZXhwU3RyaW5nIiwiZXNjYXBlRW5kIiwiZXNjYXBlU3RhcnQiLCJzdWJzdHJpbmciLCJNYXRoIiwibWF4IiwiZXhwIiwiUmVnRXhwIiwiJG9wdGlvbnMiLCJkaXN0YW5jZSIsInJhZGlhbnNUbyIsIiRtYXhEaXN0YW5jZSIsIkluZmluaXR5Iiwic291dGhXZXN0IiwiJGJveCIsIm5vcnRoRWFzdCIsImxhdGl0dWRlIiwi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Y2VzQ29udGVudCI6WyJ2YXIgZXF1YWxPYmplY3RzID0gcmVxdWlyZSgnLi9lcXVhbE9iamVjdHMnKTtcbnZhciBJZCA9IHJlcXVpcmUoJy4vSWQnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKTtcblxuLyoqXG4gKiBRdWVyeSBIYXNoZXMgYXJlIGRldGVybWluaXN0aWMgaGFzaGVzIGZvciBQYXJzZSBRdWVyaWVzLlxuICogQW55IHR3byBxdWVyaWVzIHRoYXQgaGF2ZSB0aGUgc2FtZSBzZXQgb2YgY29uc3RyYWludHMgd2lsbCBwcm9kdWNlIHRoZSBzYW1lXG4gKiBoYXNoLiBUaGlzIGxldHMgdXMgcmVsaWFibHkgZ3JvdXAgY29tcG9uZW50cyBieSB0aGUgcXVlcmllcyB0aGV5IGRlcGVuZCB1cG9uLFxuICogYW5kIHF1aWNrbHkgZGV0ZXJtaW5lIGlmIGEgcXVlcnkgaGFzIGNoYW5nZWQuXG4gKi9cblxuLyoqXG4gKiBDb252ZXJ0ICRvciBxdWVyaWVzIGludG8gYW4gYXJyYXkgb2Ygd2hlcmUgY29uZGl0aW9uc1xuICovXG5mdW5jdGlvbiBmbGF0dGVuT3JRdWVyaWVzKHdoZXJlKSB7XG4gIGlmICghd2hlcmUuaGFzT3duUHJvcGVydHkoJyRvcicpKSB7XG4gICAgcmV0dXJuIHdoZXJlO1xuICB9XG4gIHZhciBhY2N1bSA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHdoZXJlLiRvci5sZW5ndGg7IGkrKykge1xuICAgIGFjY3VtID0gYWNjdW0uY29uY2F0KHdoZXJlLiRvcltpXSk7XG4gIH1cbiAgcmV0dXJuIGFjY3VtO1xufVxuXG4vKipcbiAqIERldGVybWluaXN0aWNhbGx5IHR1cm5zIGFuIG9iamVjdCBpbnRvIGEgc3RyaW5nLiBEaXNyZWdhcmRzIG9yZGVyaW5nXG4gKi9cbmZ1bmN0aW9uIHN0cmluZ2lmeShvYmplY3QpOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIG9iamVjdCAhPT0gJ29iamVjdCcgfHwgb2JqZWN0ID09PSBudWxsKSB7XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gJ1wiJyArIG9iamVjdC5yZXBsYWNlKC9cXHwvZywgJyV8JykgKyAnXCInO1xuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0ICsgJyc7XG4gIH1cbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqZWN0KSkge1xuICAgIHZhciBjb3B5ID0gb2JqZWN0Lm1hcChzdHJpbmdpZnkpO1xuICAgIGNvcHkuc29ydCgpO1xuICAgIHJldHVybiAnWycgKyBjb3B5LmpvaW4oJywnKSArICddJztcbiAgfVxuICB2YXIgc2VjdGlvbnMgPSBbXTtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmplY3QpO1xuICBrZXlzLnNvcnQoKTtcbiAgZm9yICh2YXIgayA9IDA7IGsgPCBrZXlzLmxlbmd0aDsgaysrKSB7XG4gICAgc2VjdGlvbnMucHVzaChzdHJpbmdpZnkoa2V5c1trXSkgKyAnOicgKyBzdHJpbmdpZnkob2JqZWN0W2tleXNba11dKSk7XG4gIH1cbiAgcmV0dXJuICd7JyArIHNlY3Rpb25zLmpvaW4oJywnKSArICd9Jztcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBhIGhhc2ggZnJvbSBhIHF1ZXJ5LCB3aXRoIHVuaXF1ZSBmaWVsZHMgZm9yIGNvbHVtbnMsIHZhbHVlcywgb3JkZXIsXG4gKiBza2lwLCBhbmQgbGltaXQuXG4gKi9cbmZ1bmN0aW9uIHF1ZXJ5SGFzaChxdWVyeSkge1xuICBpZiAocXVlcnkgaW5zdGFuY2VvZiBQYXJzZS5RdWVyeSkge1xuICAgIHF1ZXJ5ID0ge1xuICAgICAgY2xhc3NOYW1lOiBxdWVyeS5jbGFzc05hbWUsXG4gICAgICB3aGVyZTogcXVlcnkuX3doZXJlXG4gICAgfVxuICB9XG4gIHZhciB3aGVyZSA9IGZsYXR0ZW5PclF1ZXJpZXMocXVlcnkud2hlcmUgfHwge30pO1xuICB2YXIgY29sdW1ucyA9IFtdO1xuICB2YXIgdmFsdWVzID0gW107XG4gIHZhciBpO1xuICBpZiAoQXJyYXkuaXNBcnJheSh3aGVyZSkpIHtcbiAgICB2YXIgdW5pcXVlQ29sdW1ucyA9IHt9O1xuICAgIGZvciAoaSA9IDA7IGkgPCB3aGVyZS5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHN1YlZhbHVlcyA9IHt9O1xuICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh3aGVyZVtpXSk7XG4gICAgICBrZXlzLnNvcnQoKTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICBzdWJWYWx1ZXNba2V5c1tqXV0gPSB3aGVyZVtpXVtrZXlzW2pdXTtcbiAgICAgICAgdW5pcXVlQ29sdW1uc1trZXlzW2pdXSA9IHRydWU7XG4gICAgICB9XG4gICAgICB2YWx1ZXMucHVzaChzdWJWYWx1ZXMpO1xuICAgIH1cbiAgICBjb2x1bW5zID0gT2JqZWN0LmtleXModW5pcXVlQ29sdW1ucyk7XG4gICAgY29sdW1ucy5zb3J0KCk7XG4gIH0gZWxzZSB7XG4gICAgY29sdW1ucyA9IE9iamVjdC5rZXlzKHdoZXJlKTtcbiAgICBjb2x1bW5zLnNvcnQoKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgY29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFsdWVzLnB1c2god2hlcmVbY29sdW1uc1tpXV0pO1xuICAgIH1cbiAgfVxuXG4gIHZhciBzZWN0aW9ucyA9IFtjb2x1bW5zLmpvaW4oJywnKSwgc3RyaW5naWZ5KHZhbHVlcyldO1xuXG4gIHJldHVybiBxdWVyeS5jbGFzc05hbWUgKyAnOicgKyBzZWN0aW9ucy5qb2luKCd8Jyk7XG59XG5cbi8qKlxuICogY29udGFpbnMgLS0gRGV0ZXJtaW5lcyBpZiBhbiBvYmplY3QgaXMgY29udGFpbmVkIGluIGEgbGlzdCB3aXRoIHNwZWNpYWwgaGFuZGxpbmcgZm9yIFBhcnNlIHBvaW50ZXJzLlxuICovXG5mdW5jdGlvbiBjb250YWlucyhoYXlzdGFjazogQXJyYXksIG5lZWRsZTogYW55KTogYm9vbGVhbiB7XG4gIGlmIChuZWVkbGUgJiYgbmVlZGxlLl9fdHlwZSAmJiBuZWVkbGUuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICBmb3IgKGNvbnN0IGkgaW4gaGF5c3RhY2spIHtcbiAgICAgIGNvbnN0IHB0ciA9IGhheXN0YWNrW2ldO1xuICAgICAgaWYgKHR5cGVvZiBwdHIgPT09ICdzdHJpbmcnICYmIHB0ciA9PT0gbmVlZGxlLm9iamVjdElkKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHB0ci5jbGFzc05hbWUgPT09IG5lZWRsZS5jbGFzc05hbWUgJiZcbiAgICAgICAgICBwdHIub2JqZWN0SWQgPT09IG5lZWRsZS5vYmplY3RJZCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiBoYXlzdGFjay5pbmRleE9mKG5lZWRsZSkgPiAtMTtcbn1cbi8qKlxuICogbWF0Y2hlc1F1ZXJ5IC0tIERldGVybWluZXMgaWYgYW4gb2JqZWN0IHdvdWxkIGJlIHJldHVybmVkIGJ5IGEgUGFyc2UgUXVlcnlcbiAqIEl0J3MgYSBsaWdodHdlaWdodCwgd2hlcmUtY2xhdXNlIG9ubHkgaW1wbGVtZW50YXRpb24gb2YgYSBmdWxsIHF1ZXJ5IGVuZ2luZS5cbiAqIFNpbmNlIHdlIGZpbmQgcXVlcmllcyB0aGF0IG1hdGNoIG9iamVjdHMsIHJhdGhlciB0aGFuIG9iamVjdHMgdGhhdCBtYXRjaFxuICogcXVlcmllcywgd2UgY2FuIGF2b2lkIGJ1aWxkaW5nIGEgZnVsbC1ibG93biBxdWVyeSB0b29sLlxuICovXG5mdW5jdGlvbiBtYXRjaGVzUXVlcnkob2JqZWN0OiBhbnksIHF1ZXJ5OiBhbnkpOiBib29sZWFuIHtcbiAgaWYgKHF1ZXJ5IGluc3RhbmNlb2YgUGFyc2UuUXVlcnkpIHtcbiAgICB2YXIgY2xhc3NOYW1lID1cbiAgICAgIChvYmplY3QuaWQgaW5zdGFuY2VvZiBJZCkgPyBvYmplY3QuaWQuY2xhc3NOYW1lIDogb2JqZWN0LmNsYXNzTmFtZTtcbiAgICBpZiAoY2xhc3NOYW1lICE9PSBxdWVyeS5jbGFzc05hbWUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoZXNRdWVyeShvYmplY3QsIHF1ZXJ5Ll93aGVyZSk7XG4gIH1cbiAgZm9yICh2YXIgZmllbGQgaW4gcXVlcnkpIHtcbiAgICBpZiAoIW1hdGNoZXNLZXlDb25zdHJhaW50cyhvYmplY3QsIGZpZWxkLCBxdWVyeVtmaWVsZF0pKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBlcXVhbE9iamVjdHNHZW5lcmljKG9iaiwgY29tcGFyZVRvLCBlcWxGbikge1xuICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChlcWxGbihvYmpbaV0sIGNvbXBhcmVUbykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBlcWxGbihvYmosIGNvbXBhcmVUbyk7XG59XG5cblxuLyoqXG4gKiBEZXRlcm1pbmVzIHdoZXRoZXIgYW4gb2JqZWN0IG1hdGNoZXMgYSBzaW5nbGUga2V5J3MgY29uc3RyYWludHNcbiAqL1xuZnVuY3Rpb24gbWF0Y2hlc0tleUNvbnN0cmFpbnRzKG9iamVjdCwga2V5LCBjb25zdHJhaW50cykge1xuICBpZiAoY29uc3RyYWludHMgPT09IG51bGwpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYoa2V5LmluZGV4T2YoXCIuXCIpID49IDApe1xuICAgIC8vIEtleSByZWZlcmVuY2VzIGEgc3Vib2JqZWN0XG4gICAgdmFyIGtleUNvbXBvbmVudHMgPSBrZXkuc3BsaXQoXCIuXCIpO1xuICAgIHZhciBzdWJPYmplY3RLZXkgPSBrZXlDb21wb25lbnRzWzBdO1xuICAgIHZhciBrZXlSZW1haW5kZXIgPSBrZXlDb21wb25lbnRzLnNsaWNlKDEpLmpvaW4oXCIuXCIpO1xuICAgIHJldHVybiBtYXRjaGVzS2V5Q29uc3RyYWludHMob2JqZWN0W3N1Yk9iamVjdEtleV0gfHwge30sIGtleVJlbWFpbmRlciwgY29uc3RyYWludHMpO1xuICB9XG4gIHZhciBpO1xuICBpZiAoa2V5ID09PSAnJG9yJykge1xuICAgIGZvciAoaSA9IDA7IGkgPCBjb25zdHJhaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG1hdGNoZXNRdWVyeShvYmplY3QsIGNvbnN0cmFpbnRzW2ldKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChrZXkgPT09ICckcmVsYXRlZFRvJykge1xuICAgIC8vIEJhaWwhIFdlIGNhbid0IGhhbmRsZSByZWxhdGlvbmFsIHF1ZXJpZXMgbG9jYWxseVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBFcXVhbGl0eSAob3IgQXJyYXkgY29udGFpbnMpIGNhc2VzXG4gIGlmICh0eXBlb2YgY29uc3RyYWludHMgIT09ICdvYmplY3QnKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob2JqZWN0W2tleV0pKSB7XG4gICAgICByZXR1cm4gb2JqZWN0W2tleV0uaW5kZXhPZihjb25zdHJhaW50cykgPiAtMTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdFtrZXldID09PSBjb25zdHJhaW50cztcbiAgfVxuICB2YXIgY29tcGFyZVRvO1xuICBpZiAoY29uc3RyYWludHMuX190eXBlKSB7XG4gICAgaWYgKGNvbnN0cmFpbnRzLl9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICByZXR1cm4gZXF1YWxPYmplY3RzR2VuZXJpYyhvYmplY3Rba2V5XSwgY29uc3RyYWludHMsIGZ1bmN0aW9uKG9iaiwgcHRyKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgdHlwZW9mIG9iaiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICBwdHIuY2xhc3NOYW1lID09PSBvYmouY2xhc3NOYW1lICYmXG4gICAgICAgICAgcHRyLm9iamVjdElkID09PSBvYmoub2JqZWN0SWRcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBlcXVhbE9iamVjdHNHZW5lcmljKG9iamVjdFtrZXldLCBQYXJzZS5fZGVjb2RlKGtleSwgY29uc3RyYWludHMpLCBlcXVhbE9iamVjdHMpO1xuICB9XG4gIC8vIE1vcmUgY29tcGxleCBjYXNlc1xuICBmb3IgKHZhciBjb25kaXRpb24gaW4gY29uc3RyYWludHMpIHtcbiAgICBjb21wYXJlVG8gPSBjb25zdHJhaW50c1tjb25kaXRpb25dO1xuICAgIGlmIChjb21wYXJlVG8uX190eXBlKSB7XG4gICAgICBjb21wYXJlVG8gPSBQYXJzZS5fZGVjb2RlKGtleSwgY29tcGFyZVRvKTtcbiAgICB9XG4gICAgc3dpdGNoIChjb25kaXRpb24pIHtcbiAgICBjYXNlICckbHQnOlxuICAgICAgaWYgKG9iamVjdFtrZXldID49IGNvbXBhcmVUbykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICckbHRlJzpcbiAgICAgIGlmIChvYmplY3Rba2V5XSA+IGNvbXBhcmVUbykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICckZ3QnOlxuICAgICAgaWYgKG9iamVjdFtrZXldIDw9IGNvbXBhcmVUbykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICckZ3RlJzpcbiAgICAgIGlmIChvYmplY3Rba2V5XSA8IGNvbXBhcmVUbykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICckbmUnOlxuICAgICAgaWYgKGVxdWFsT2JqZWN0cyhvYmplY3Rba2V5XSwgY29tcGFyZVRvKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICckaW4nOlxuICAgICAgaWYgKCFjb250YWlucyhjb21wYXJlVG8sIG9iamVjdFtrZXldKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICckbmluJzpcbiAgICAgIGlmIChjb250YWlucyhjb21wYXJlVG8sIG9iamVjdFtrZXldKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICckYWxsJzpcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb21wYXJlVG8ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKG9iamVjdFtrZXldLmluZGV4T2YoY29tcGFyZVRvW2ldKSA8IDApIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJyRleGlzdHMnOiB7XG4gICAgICBjb25zdCBwcm9wZXJ0eUV4aXN0cyA9IHR5cGVvZiBvYmplY3Rba2V5XSAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgICBjb25zdCBleGlzdGVuY2VJc1JlcXVpcmVkID0gY29uc3RyYWludHNbJyRleGlzdHMnXTtcbiAgICAgIGlmICh0eXBlb2YgY29uc3RyYWludHNbJyRleGlzdHMnXSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIC8vIFRoZSBTREsgd2lsbCBuZXZlciBzdWJtaXQgYSBub24tYm9vbGVhbiBmb3IgJGV4aXN0cywgYnV0IGlmIHNvbWVvbmVcbiAgICAgICAgLy8gdHJpZXMgdG8gc3VibWl0IGEgbm9uLWJvb2xlYW4gZm9yICRleGl0cyBvdXRzaWRlIHRoZSBTREtzLCBqdXN0IGlnbm9yZSBpdC5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoKCFwcm9wZXJ0eUV4aXN0cyAmJiBleGlzdGVuY2VJc1JlcXVpcmVkKSB8fCAocHJvcGVydHlFeGlzdHMgJiYgIWV4aXN0ZW5jZUlzUmVxdWlyZWQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjYXNlICckcmVnZXgnOlxuICAgICAgaWYgKHR5cGVvZiBjb21wYXJlVG8gPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBjb21wYXJlVG8udGVzdChvYmplY3Rba2V5XSk7XG4gICAgICB9XG4gICAgICAvLyBKUyBkb2Vzbid0IHN1cHBvcnQgcGVybC1zdHlsZSBlc2NhcGluZ1xuICAgICAgdmFyIGV4cFN0cmluZyA9ICcnO1xuICAgICAgdmFyIGVzY2FwZUVuZCA9IC0yO1xuICAgICAgdmFyIGVzY2FwZVN0YXJ0ID0gY29tcGFyZVRvLmluZGV4T2YoJ1xcXFxRJyk7XG4gICAgICB3aGlsZSAoZXNjYXBlU3RhcnQgPiAtMSkge1xuICAgICAgICAvLyBBZGQgdGhlIHVuZXNjYXBlZCBwb3J0aW9uXG4gICAgICAgIGV4cFN0cmluZyArPSBjb21wYXJlVG8uc3Vic3RyaW5nKGVzY2FwZUVuZCArIDIsIGVzY2FwZVN0YXJ0KTtcbiAgICAgICAgZXNjYXBlRW5kID0gY29tcGFyZVRvLmluZGV4T2YoJ1xcXFxFJywgZXNjYXBlU3RhcnQpO1xuICAgICAgICBpZiAoZXNjYXBlRW5kID4gLTEpIHtcbiAgICAgICAgICBleHBTdHJpbmcgKz0gY29tcGFyZVRvLnN1YnN0cmluZyhlc2NhcGVTdGFydCArIDIsIGVzY2FwZUVuZClcbiAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXFxcXFxcXFxcXFxcRS9nLCAnXFxcXEUnKS5yZXBsYWNlKC9cXFcvZywgJ1xcXFwkJicpO1xuICAgICAgICB9XG5cbiAgICAgICAgZXNjYXBlU3RhcnQgPSBjb21wYXJlVG8uaW5kZXhPZignXFxcXFEnLCBlc2NhcGVFbmQpO1xuICAgICAgfVxuICAgICAgZXhwU3RyaW5nICs9IGNvbXBhcmVUby5zdWJzdHJpbmcoTWF0aC5tYXgoZXNjYXBlU3RhcnQsIGVzY2FwZUVuZCArIDIpKTtcbiAgICAgIHZhciBleHAgPSBuZXcgUmVnRXhwKGV4cFN0cmluZywgY29uc3RyYWludHMuJG9wdGlvbnMgfHwgJycpO1xuICAgICAgaWYgKCFleHAudGVzdChvYmplY3Rba2V5XSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnJG5lYXJTcGhlcmUnOlxuICAgICAgaWYgKCFjb21wYXJlVG8gfHwgIW9iamVjdFtrZXldKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciBkaXN0YW5jZSA9IGNvbXBhcmVUby5yYWRpYW5zVG8ob2JqZWN0W2tleV0pO1xuICAgICAgdmFyIG1heCA9IGNvbnN0cmFpbnRzLiRtYXhEaXN0YW5jZSB8fCBJbmZpbml0eTtcbiAgICAgIHJldHVybiBkaXN0YW5jZSA8PSBtYXg7XG4gICAgY2FzZSAnJHdpdGhpbic6XG4gICAgICBpZiAoIWNvbXBhcmVUbyB8fCAhb2JqZWN0W2tleV0pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIHNvdXRoV2VzdCA9IGNvbXBhcmVUby4kYm94WzBdO1xuICAgICAgdmFyIG5vcnRoRWFzdCA9IGNvbXBhcmVUby4kYm94WzFdO1xuICAgICAgaWYgKHNvdXRoV2VzdC5sYXRpdHVkZSA+IG5vcnRoRWFzdC5sYXRpdHVkZSB8fFxuICAgICAgICAgICAgc291dGhXZXN0LmxvbmdpdHVkZSA+IG5vcnRoRWFzdC5sb25naXR1ZGUpIHtcbiAgICAgICAgLy8gSW52YWxpZCBib3gsIGNyb3NzZXMgdGhlIGRhdGUgbGluZVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gKFxuICAgICAgICBvYmplY3Rba2V5XS5sYXRpdHVkZSA+IHNvdXRoV2VzdC5sYXRpdHVkZSAmJlxuICAgICAgICAgIG9iamVjdFtrZXldLmxhdGl0dWRlIDwgbm9ydGhFYXN0LmxhdGl0dWRlICYmXG4gICAgICAgICAgb2JqZWN0W2tleV0ubG9uZ2l0dWRlID4gc291dGhXZXN0LmxvbmdpdHVkZSAmJlxuICAgICAgICAgIG9iamVjdFtrZXldLmxvbmdpdHVkZSA8IG5vcnRoRWFzdC5sb25naXR1ZGVcbiAgICAgICk7XG4gICAgY2FzZSAnJG9wdGlvbnMnOlxuICAgICAgLy8gTm90IGEgcXVlcnkgdHlwZSwgYnV0IGEgd2F5IHRvIGFkZCBvcHRpb25zIHRvICRyZWdleC4gSWdub3JlIGFuZFxuICAgICAgLy8gYXZvaWQgdGhlIGRlZmF1bHRcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJyRtYXhEaXN0YW5jZSc6XG4gICAgICAvLyBOb3QgYSBxdWVyeSB0eXBlLCBidXQgYSB3YXkgdG8gYWRkIGEgY2FwIHRvICRuZWFyU3BoZXJlLiBJZ25vcmUgYW5kXG4gICAgICAvLyBhdm9pZCB0aGUgZGVmYXVsdFxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnJHNlbGVjdCc6XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgY2FzZSAnJGRvbnRTZWxlY3QnOlxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgUXVlcnlUb29scyA9IHtcbiAgcXVlcnlIYXNoOiBxdWVyeUhhc2gsXG4gIG1hdGNoZXNRdWVyeTogbWF0Y2hlc1F1ZXJ5XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFF1ZXJ5VG9vbHM7XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/RequestSchema.js b/lib/LiveQuery/RequestSchema.js index c77f974c74..3c10e0706e 100644 --- a/lib/LiveQuery/RequestSchema.js +++ b/lib/LiveQuery/RequestSchema.js @@ -143,4 +143,5 @@ const RequestSchema = { 'unsubscribe': unsubscribe }; -exports.default = RequestSchema; \ No newline at end of file +exports.default = RequestSchema; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUmVxdWVzdFNjaGVtYS5qcyJdLCJuYW1lcyI6WyJnZW5lcmFsIiwiY29ubmVjdCIsInR5cGUiLCJzdWJzY3JpYmUiLCJ1cGRhdGUiLCJ1bnN1YnNjcmliZSIsIlJlcXVlc3RTY2hlbWEiXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsTUFBTUEsVUFBVTtBQUNkLFdBQVMsd0JBREs7QUFFZCxVQUFRLFFBRk07QUFHZCxnQkFBYztBQUNaLFVBQU07QUFDSixjQUFRLFFBREo7QUFFSixjQUFRLENBQUMsU0FBRCxFQUFZLFdBQVosRUFBeUIsYUFBekIsRUFBd0MsUUFBeEM7QUFGSjtBQURNLEdBSEE7QUFTZCxjQUFZLENBQUMsSUFBRDtBQVRFLENBQWhCOztBQVlBLE1BQU1DLFVBQVc7QUFDZixXQUFTLDBCQURNO0FBRWYsVUFBUSxRQUZPO0FBR2YsZ0JBQWM7QUFDWixVQUFNLFNBRE07QUFFWixxQkFBaUI7QUFDZixjQUFRO0FBRE8sS0FGTDtBQUtaLHFCQUFpQjtBQUNmQyxZQUFNO0FBRFMsS0FMTDtBQVFaLGlCQUFhO0FBQ1hBLFlBQU07QUFESyxLQVJEO0FBV1osaUJBQWE7QUFDWEEsWUFBTTtBQURLLEtBWEQ7QUFjWixrQkFBYztBQUNaQSxZQUFNO0FBRE0sS0FkRjtBQWlCWixrQkFBYztBQUNaLGNBQVE7QUFESSxLQWpCRjtBQW9CWixvQkFBZ0I7QUFDZCxjQUFRO0FBRE07QUFwQkosR0FIQztBQTJCZixjQUFZLENBQUMsSUFBRCxFQUFPLGVBQVAsQ0EzQkc7QUE0QmYsMEJBQXdCO0FBNUJULENBQWpCOztBQStCQSxNQUFNQyxZQUFZO0FBQ2hCLFdBQVMsNEJBRE87QUFFaEIsVUFBUSxRQUZRO0FBR2hCLGdCQUFjO0FBQ1osVUFBTSxXQURNO0FBRVosaUJBQWE7QUFDWCxjQUFRO0FBREcsS0FGRDtBQUtaLGFBQVM7QUFDUCxlQUFTLG9CQURGO0FBRVAsY0FBUSxRQUZEO0FBR1Asb0JBQWM7QUFDWixxQkFBYTtBQUNYLGtCQUFRO0FBREcsU0FERDtBQUlaLGlCQUFTO0FBQ1Asa0JBQVE7QUFERCxTQUpHO0FBT1osa0JBQVU7QUFDUixrQkFBUSxPQURBO0FBRVIsbUJBQVM7QUFDUCxvQkFBUTtBQURELFdBRkQ7QUFLUixzQkFBWSxDQUxKO0FBTVIseUJBQWU7QUFOUDtBQVBFLE9BSFA7QUFtQlAsa0JBQVksQ0FBQyxPQUFELEVBQVUsV0FBVixDQW5CTDtBQW9CUCw4QkFBd0I7QUFwQmpCLEtBTEc7QUEyQlosb0JBQWdCO0FBQ2QsY0FBUTtBQURNO0FBM0JKLEdBSEU7QUFrQ2hCLGNBQVksQ0FBQyxJQUFELEVBQU8sV0FBUCxFQUFvQixPQUFwQixDQWxDSTtBQW1DaEIsMEJBQXdCO0FBbkNSLENBQWxCOztBQXNDQSxNQUFNQyxTQUFTO0FBQ2IsV0FBUyx5QkFESTtBQUViLFVBQVEsUUFGSztBQUdiLGdCQUFjO0FBQ1osVUFBTSxRQURNO0FBRVosaUJBQWE7QUFDWCxjQUFRO0FBREcsS0FGRDtBQUtaLGFBQVM7QUFDUCxlQUFTLG9CQURGO0FBRVAsY0FBUSxRQUZEO0FBR1Asb0JBQWM7QUFDWixxQkFBYTtBQUNYLGtCQUFRO0FBREcsU0FERDtBQUlaLGlCQUFTO0FBQ1Asa0JBQVE7QUFERCxTQUpHO0FBT1osa0JBQVU7QUFDUixrQkFBUSxPQURBO0FBRVIsbUJBQVM7QUFDUCxvQkFBUTtBQURELFdBRkQ7QUFLUixzQkFBWSxDQUxKO0FBTVIseUJBQWU7QUFOUDtBQVBFLE9BSFA7QUFtQlAsa0JBQVksQ0FBQyxPQUFELEVBQVUsV0FBVixDQW5CTDtBQW9CUCw4QkFBd0I7QUFwQmpCLEtBTEc7QUEyQlosb0JBQWdCO0FBQ2QsY0FBUTtBQURNO0FBM0JKLEdBSEQ7QUFrQ2IsY0FBWSxDQUFDLElBQUQsRUFBTyxXQUFQLEVBQW9CLE9BQXBCLENBbENDO0FBbUNiLDBCQUF3QjtBQW5DWCxDQUFmOztBQXNDQSxNQUFNQyxjQUFjO0FBQ2xCLFdBQVMsOEJBRFM7QUFFbEIsVUFBUSxRQUZVO0FBR2xCLGdCQUFjO0FBQ1osVUFBTSxhQURNO0FBRVosaUJBQWE7QUFDWCxjQUFRO0FBREc7QUFGRCxHQUhJO0FBU2xCLGNBQVksQ0FBQyxJQUFELEVBQU8sV0FBUCxDQVRNO0FBVWxCLDBCQUF3QjtBQVZOLENBQXBCOztBQWFBLE1BQU1DLGdCQUFnQjtBQUNwQixhQUFXTixPQURTO0FBRXBCLGFBQVdDLE9BRlM7QUFHcEIsZUFBYUUsU0FITztBQUlwQixZQUFVQyxNQUpVO0FBS3BCLGlCQUFlQztBQUxLLENBQXRCOztrQkFRZUMsYSIsImZpbGUiOiJSZXF1ZXN0U2NoZW1hLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgZ2VuZXJhbCA9IHtcbiAgJ3RpdGxlJzogJ0dlbmVyYWwgcmVxdWVzdCBzY2hlbWEnLFxuICAndHlwZSc6ICdvYmplY3QnLFxuICAncHJvcGVydGllcyc6IHtcbiAgICAnb3AnOiB7XG4gICAgICAndHlwZSc6ICdzdHJpbmcnLFxuICAgICAgJ2VudW0nOiBbJ2Nvbm5lY3QnLCAnc3Vic2NyaWJlJywgJ3Vuc3Vic2NyaWJlJywgJ3VwZGF0ZSddXG4gICAgfSxcbiAgfSxcbiAgJ3JlcXVpcmVkJzogWydvcCddXG59O1xuXG5jb25zdCBjb25uZWN0ID0gIHtcbiAgJ3RpdGxlJzogJ0Nvbm5lY3Qgb3BlcmF0aW9uIHNjaGVtYScsXG4gICd0eXBlJzogJ29iamVjdCcsXG4gICdwcm9wZXJ0aWVzJzoge1xuICAgICdvcCc6ICdjb25uZWN0JyxcbiAgICAnYXBwbGljYXRpb25JZCc6IHtcbiAgICAgICd0eXBlJzogJ3N0cmluZydcbiAgICB9LFxuICAgICdqYXZhc2NyaXB0S2V5Jzoge1xuICAgICAgdHlwZTogJ3N0cmluZydcbiAgICB9LFxuICAgICdtYXN0ZXJLZXknOiB7XG4gICAgICB0eXBlOiAnc3RyaW5nJ1xuICAgIH0sXG4gICAgJ2NsaWVudEtleSc6IHtcbiAgICAgIHR5cGU6ICdzdHJpbmcnXG4gICAgfSxcbiAgICAnd2luZG93c0tleSc6IHtcbiAgICAgIHR5cGU6ICdzdHJpbmcnXG4gICAgfSxcbiAgICAncmVzdEFQSUtleSc6IHtcbiAgICAgICd0eXBlJzogJ3N0cmluZydcbiAgICB9LFxuICAgICdzZXNzaW9uVG9rZW4nOiB7XG4gICAgICAndHlwZSc6ICdzdHJpbmcnXG4gICAgfVxuICB9LFxuICAncmVxdWlyZWQnOiBbJ29wJywgJ2FwcGxpY2F0aW9uSWQnXSxcbiAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiBmYWxzZVxufTtcblxuY29uc3Qgc3Vic2NyaWJlID0ge1xuICAndGl0bGUnOiAnU3Vic2NyaWJlIG9wZXJhdGlvbiBzY2hlbWEnLFxuICAndHlwZSc6ICdvYmplY3QnLFxuICAncHJvcGVydGllcyc6IHtcbiAgICAnb3AnOiAnc3Vic2NyaWJlJyxcbiAgICAncmVxdWVzdElkJzoge1xuICAgICAgJ3R5cGUnOiAnbnVtYmVyJ1xuICAgIH0sXG4gICAgJ3F1ZXJ5Jzoge1xuICAgICAgJ3RpdGxlJzogJ1F1ZXJ5IGZpZWxkIHNjaGVtYScsXG4gICAgICAndHlwZSc6ICdvYmplY3QnLFxuICAgICAgJ3Byb3BlcnRpZXMnOiB7XG4gICAgICAgICdjbGFzc05hbWUnOiB7XG4gICAgICAgICAgJ3R5cGUnOiAnc3RyaW5nJ1xuICAgICAgICB9LFxuICAgICAgICAnd2hlcmUnOiB7XG4gICAgICAgICAgJ3R5cGUnOiAnb2JqZWN0J1xuICAgICAgICB9LFxuICAgICAgICAnZmllbGRzJzoge1xuICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtaW5JdGVtc1wiOiAxLFxuICAgICAgICAgIFwidW5pcXVlSXRlbXNcIjogdHJ1ZVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgJ3JlcXVpcmVkJzogWyd3aGVyZScsICdjbGFzc05hbWUnXSxcbiAgICAgICdhZGRpdGlvbmFsUHJvcGVydGllcyc6IGZhbHNlXG4gICAgfSxcbiAgICAnc2Vzc2lvblRva2VuJzoge1xuICAgICAgJ3R5cGUnOiAnc3RyaW5nJ1xuICAgIH1cbiAgfSxcbiAgJ3JlcXVpcmVkJzogWydvcCcsICdyZXF1ZXN0SWQnLCAncXVlcnknXSxcbiAgJ2FkZGl0aW9uYWxQcm9wZXJ0aWVzJzogZmFsc2Vcbn07XG5cbmNvbnN0IHVwZGF0ZSA9IHtcbiAgJ3RpdGxlJzogJ1VwZGF0ZSBvcGVyYXRpb24gc2NoZW1hJyxcbiAgJ3R5cGUnOiAnb2JqZWN0JyxcbiAgJ3Byb3BlcnRpZXMnOiB7XG4gICAgJ29wJzogJ3VwZGF0ZScsXG4gICAgJ3JlcXVlc3RJZCc6IHtcbiAgICAgICd0eXBlJzogJ251bWJlcidcbiAgICB9LFxuICAgICdxdWVyeSc6IHtcbiAgICAgICd0aXRsZSc6ICdRdWVyeSBmaWVsZCBzY2hlbWEnLFxuICAgICAgJ3R5cGUnOiAnb2JqZWN0JyxcbiAgICAgICdwcm9wZXJ0aWVzJzoge1xuICAgICAgICAnY2xhc3NOYW1lJzoge1xuICAgICAgICAgICd0eXBlJzogJ3N0cmluZydcbiAgICAgICAgfSxcbiAgICAgICAgJ3doZXJlJzoge1xuICAgICAgICAgICd0eXBlJzogJ29iamVjdCdcbiAgICAgICAgfSxcbiAgICAgICAgJ2ZpZWxkcyc6IHtcbiAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWluSXRlbXNcIjogMSxcbiAgICAgICAgICBcInVuaXF1ZUl0ZW1zXCI6IHRydWVcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgICdyZXF1aXJlZCc6IFsnd2hlcmUnLCAnY2xhc3NOYW1lJ10sXG4gICAgICAnYWRkaXRpb25hbFByb3BlcnRpZXMnOiBmYWxzZVxuICAgIH0sXG4gICAgJ3Nlc3Npb25Ub2tlbic6IHtcbiAgICAgICd0eXBlJzogJ3N0cmluZydcbiAgICB9XG4gIH0sXG4gICdyZXF1aXJlZCc6IFsnb3AnLCAncmVxdWVzdElkJywgJ3F1ZXJ5J10sXG4gICdhZGRpdGlvbmFsUHJvcGVydGllcyc6IGZhbHNlXG59O1xuXG5jb25zdCB1bnN1YnNjcmliZSA9IHtcbiAgJ3RpdGxlJzogJ1Vuc3Vic2NyaWJlIG9wZXJhdGlvbiBzY2hlbWEnLFxuICAndHlwZSc6ICdvYmplY3QnLFxuICAncHJvcGVydGllcyc6IHtcbiAgICAnb3AnOiAndW5zdWJzY3JpYmUnLFxuICAgICdyZXF1ZXN0SWQnOiB7XG4gICAgICAndHlwZSc6ICdudW1iZXInXG4gICAgfVxuICB9LFxuICAncmVxdWlyZWQnOiBbJ29wJywgJ3JlcXVlc3RJZCddLFxuICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlXG59XG5cbmNvbnN0IFJlcXVlc3RTY2hlbWEgPSB7XG4gICdnZW5lcmFsJzogZ2VuZXJhbCxcbiAgJ2Nvbm5lY3QnOiBjb25uZWN0LFxuICAnc3Vic2NyaWJlJzogc3Vic2NyaWJlLFxuICAndXBkYXRlJzogdXBkYXRlLFxuICAndW5zdWJzY3JpYmUnOiB1bnN1YnNjcmliZVxufVxuXG5leHBvcnQgZGVmYXVsdCBSZXF1ZXN0U2NoZW1hO1xuIl19 \ No newline at end of file diff --git a/lib/LiveQuery/SessionTokenCache.js b/lib/LiveQuery/SessionTokenCache.js index 82056f7439..943eb311f6 100644 --- a/lib/LiveQuery/SessionTokenCache.js +++ b/lib/LiveQuery/SessionTokenCache.js @@ -60,4 +60,5 @@ class SessionTokenCache { } } -exports.SessionTokenCache = SessionTokenCache; \ No newline at end of file +exports.SessionTokenCache = SessionTokenCache; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvU2Vzc2lvblRva2VuQ2FjaGUuanMiXSwibmFtZXMiOlsidXNlckZvclNlc3Npb25Ub2tlbiIsInNlc3Npb25Ub2tlbiIsInEiLCJQYXJzZSIsIlF1ZXJ5IiwiZXF1YWxUbyIsImZpcnN0IiwidXNlTWFzdGVyS2V5IiwidGhlbiIsInNlc3Npb24iLCJQcm9taXNlIiwiZXJyb3IiLCJnZXQiLCJTZXNzaW9uVG9rZW5DYWNoZSIsImNvbnN0cnVjdG9yIiwidGltZW91dCIsIm1heFNpemUiLCJjYWNoZSIsIkxSVSIsIm1heCIsIm1heEFnZSIsImdldFVzZXJJZCIsInVzZXJJZCIsImxvZ2dlciIsInZlcmJvc2UiLCJhcyIsInVzZXIiLCJpZCIsInNldCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBRUEsU0FBU0EsbUJBQVQsQ0FBNkJDLFlBQTdCLEVBQTBDO0FBQ3hDLE1BQUlDLElBQUksSUFBSUMsZUFBTUMsS0FBVixDQUFnQixVQUFoQixDQUFSO0FBQ0FGLElBQUVHLE9BQUYsQ0FBVSxjQUFWLEVBQTBCSixZQUExQjtBQUNBLFNBQU9DLEVBQUVJLEtBQUYsQ0FBUSxFQUFDQyxjQUFhLElBQWQsRUFBUixFQUE2QkMsSUFBN0IsQ0FBa0MsVUFBU0MsT0FBVCxFQUFpQjtBQUN4RCxRQUFHLENBQUNBLE9BQUosRUFBWTtBQUNWLGFBQU9OLGVBQU1PLE9BQU4sQ0FBY0MsS0FBZCxDQUFvQixvQ0FBcEIsQ0FBUDtBQUNEO0FBQ0QsV0FBT0YsUUFBUUcsR0FBUixDQUFZLE1BQVosQ0FBUDtBQUNELEdBTE0sQ0FBUDtBQU1EOztBQUVELE1BQU1DLGlCQUFOLENBQXdCOztBQUd0QkMsY0FBWUMsVUFBa0IsS0FBSyxFQUFMLEdBQVUsRUFBVixHQUFlLEVBQWYsR0FBb0IsSUFBbEQsRUFBd0RDLFVBQWtCLEtBQTFFLEVBQWlGO0FBQy9FLFNBQUtDLEtBQUwsR0FBYSxJQUFJQyxrQkFBSixDQUFRO0FBQ25CQyxXQUFLSCxPQURjO0FBRW5CSSxjQUFRTDtBQUZXLEtBQVIsQ0FBYjtBQUlEOztBQUVETSxZQUFVcEIsWUFBVixFQUFxQztBQUNuQyxRQUFJLENBQUNBLFlBQUwsRUFBbUI7QUFDakIsYUFBT0UsZUFBTU8sT0FBTixDQUFjQyxLQUFkLENBQW9CLG9CQUFwQixDQUFQO0FBQ0Q7QUFDRCxVQUFNVyxTQUFTLEtBQUtMLEtBQUwsQ0FBV0wsR0FBWCxDQUFlWCxZQUFmLENBQWY7QUFDQSxRQUFJcUIsTUFBSixFQUFZO0FBQ1ZDLHVCQUFPQyxPQUFQLENBQWUsK0NBQWYsRUFBZ0VGLE1BQWhFLEVBQXdFckIsWUFBeEU7QUFDQSxhQUFPRSxlQUFNTyxPQUFOLENBQWNlLEVBQWQsQ0FBaUJILE1BQWpCLENBQVA7QUFDRDtBQUNELFdBQU90QixvQkFBb0JDLFlBQXBCLEVBQWtDTyxJQUFsQyxDQUF3Q2tCLElBQUQsSUFBVTtBQUN0REgsdUJBQU9DLE9BQVAsQ0FBZSwrQ0FBZixFQUFnRUUsS0FBS0MsRUFBckUsRUFBeUUxQixZQUF6RTtBQUNBLFlBQU1xQixTQUFTSSxLQUFLQyxFQUFwQjtBQUNBLFdBQUtWLEtBQUwsQ0FBV1csR0FBWCxDQUFlM0IsWUFBZixFQUE2QnFCLE1BQTdCO0FBQ0EsYUFBT25CLGVBQU1PLE9BQU4sQ0FBY2UsRUFBZCxDQUFpQkgsTUFBakIsQ0FBUDtBQUNELEtBTE0sRUFLSFgsS0FBRCxJQUFXO0FBQ1pZLHVCQUFPWixLQUFQLENBQWEsb0RBQWIsRUFBbUVWLFlBQW5FLEVBQWlGVSxLQUFqRjtBQUNBLGFBQU9SLGVBQU1PLE9BQU4sQ0FBY0MsS0FBZCxDQUFvQkEsS0FBcEIsQ0FBUDtBQUNELEtBUk0sQ0FBUDtBQVNEO0FBNUJxQjs7UUFnQ3RCRSxpQixHQUFBQSxpQiIsImZpbGUiOiJTZXNzaW9uVG9rZW5DYWNoZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBMUlUgZnJvbSAnbHJ1LWNhY2hlJztcbmltcG9ydCBsb2dnZXIgZnJvbSAnLi4vbG9nZ2VyJztcblxuZnVuY3Rpb24gdXNlckZvclNlc3Npb25Ub2tlbihzZXNzaW9uVG9rZW4pe1xuICB2YXIgcSA9IG5ldyBQYXJzZS5RdWVyeShcIl9TZXNzaW9uXCIpO1xuICBxLmVxdWFsVG8oXCJzZXNzaW9uVG9rZW5cIiwgc2Vzc2lvblRva2VuKTtcbiAgcmV0dXJuIHEuZmlyc3Qoe3VzZU1hc3RlcktleTp0cnVlfSkudGhlbihmdW5jdGlvbihzZXNzaW9uKXtcbiAgICBpZighc2Vzc2lvbil7XG4gICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5lcnJvcihcIk5vIHNlc3Npb24gZm91bmQgZm9yIHNlc3Npb24gdG9rZW5cIik7XG4gICAgfVxuICAgIHJldHVybiBzZXNzaW9uLmdldChcInVzZXJcIik7XG4gIH0pO1xufVxuXG5jbGFzcyBTZXNzaW9uVG9rZW5DYWNoZSB7XG4gIGNhY2hlOiBPYmplY3Q7XG5cbiAgY29uc3RydWN0b3IodGltZW91dDogbnVtYmVyID0gMzAgKiAyNCAqIDYwICogNjAgKiAxMDAwLCBtYXhTaXplOiBudW1iZXIgPSAxMDAwMCkge1xuICAgIHRoaXMuY2FjaGUgPSBuZXcgTFJVKHtcbiAgICAgIG1heDogbWF4U2l6ZSxcbiAgICAgIG1heEFnZTogdGltZW91dFxuICAgIH0pO1xuICB9XG5cbiAgZ2V0VXNlcklkKHNlc3Npb25Ub2tlbjogc3RyaW5nKTogYW55IHtcbiAgICBpZiAoIXNlc3Npb25Ub2tlbikge1xuICAgICAgcmV0dXJuIFBhcnNlLlByb21pc2UuZXJyb3IoJ0VtcHR5IHNlc3Npb25Ub2tlbicpO1xuICAgIH1cbiAgICBjb25zdCB1c2VySWQgPSB0aGlzLmNhY2hlLmdldChzZXNzaW9uVG9rZW4pO1xuICAgIGlmICh1c2VySWQpIHtcbiAgICAgIGxvZ2dlci52ZXJib3NlKCdGZXRjaCB1c2VySWQgJXMgb2Ygc2Vzc2lvblRva2VuICVzIGZyb20gQ2FjaGUnLCB1c2VySWQsIHNlc3Npb25Ub2tlbik7XG4gICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyh1c2VySWQpO1xuICAgIH1cbiAgICByZXR1cm4gdXNlckZvclNlc3Npb25Ub2tlbihzZXNzaW9uVG9rZW4pLnRoZW4oKHVzZXIpID0+IHtcbiAgICAgIGxvZ2dlci52ZXJib3NlKCdGZXRjaCB1c2VySWQgJXMgb2Ygc2Vzc2lvblRva2VuICVzIGZyb20gUGFyc2UnLCB1c2VyLmlkLCBzZXNzaW9uVG9rZW4pO1xuICAgICAgY29uc3QgdXNlcklkID0gdXNlci5pZDtcbiAgICAgIHRoaXMuY2FjaGUuc2V0KHNlc3Npb25Ub2tlbiwgdXNlcklkKTtcbiAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKHVzZXJJZCk7XG4gICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0NhbiBub3QgZmV0Y2ggdXNlcklkIGZvciBzZXNzaW9uVG9rZW4gJWosIGVycm9yICVqJywgc2Vzc2lvblRva2VuLCBlcnJvcik7XG4gICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5lcnJvcihlcnJvcik7XG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IHtcbiAgU2Vzc2lvblRva2VuQ2FjaGVcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/LiveQuery/Subscription.js b/lib/LiveQuery/Subscription.js index 8d0019fda0..b8dc38ebbd 100644 --- a/lib/LiveQuery/Subscription.js +++ b/lib/LiveQuery/Subscription.js @@ -52,4 +52,5 @@ class Subscription { } } -exports.Subscription = Subscription; \ No newline at end of file +exports.Subscription = Subscription; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvU3Vic2NyaXB0aW9uLmpzIl0sIm5hbWVzIjpbIlN1YnNjcmlwdGlvbiIsImNvbnN0cnVjdG9yIiwiY2xhc3NOYW1lIiwicXVlcnkiLCJxdWVyeUhhc2giLCJoYXNoIiwiY2xpZW50UmVxdWVzdElkcyIsIk1hcCIsImFkZENsaWVudFN1YnNjcmlwdGlvbiIsImNsaWVudElkIiwicmVxdWVzdElkIiwiaGFzIiwic2V0IiwicmVxdWVzdElkcyIsImdldCIsInB1c2giLCJkZWxldGVDbGllbnRTdWJzY3JpcHRpb24iLCJsb2dnZXIiLCJlcnJvciIsImluZGV4IiwiaW5kZXhPZiIsInNwbGljZSIsImxlbmd0aCIsImRlbGV0ZSIsImhhc1N1YnNjcmliaW5nQ2xpZW50Iiwic2l6ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7Ozs7QUFLQSxNQUFNQSxZQUFOLENBQW1CO0FBQ2pCO0FBTUFDLGNBQVlDLFNBQVosRUFBK0JDLEtBQS9CLEVBQWlEQyxTQUFqRCxFQUFvRTtBQUNsRSxTQUFLRixTQUFMLEdBQWlCQSxTQUFqQjtBQUNBLFNBQUtDLEtBQUwsR0FBYUEsS0FBYjtBQUNBLFNBQUtFLElBQUwsR0FBWUQsU0FBWjtBQUNBLFNBQUtFLGdCQUFMLEdBQXdCLElBQUlDLEdBQUosRUFBeEI7QUFDRDs7QUFFREMsd0JBQXNCQyxRQUF0QixFQUF3Q0MsU0FBeEMsRUFBaUU7QUFDL0QsUUFBSSxDQUFDLEtBQUtKLGdCQUFMLENBQXNCSyxHQUF0QixDQUEwQkYsUUFBMUIsQ0FBTCxFQUEwQztBQUN4QyxXQUFLSCxnQkFBTCxDQUFzQk0sR0FBdEIsQ0FBMEJILFFBQTFCLEVBQW9DLEVBQXBDO0FBQ0Q7QUFDRCxVQUFNSSxhQUFhLEtBQUtQLGdCQUFMLENBQXNCUSxHQUF0QixDQUEwQkwsUUFBMUIsQ0FBbkI7QUFDQUksZUFBV0UsSUFBWCxDQUFnQkwsU0FBaEI7QUFDRDs7QUFFRE0sMkJBQXlCUCxRQUF6QixFQUEyQ0MsU0FBM0MsRUFBb0U7QUFDbEUsVUFBTUcsYUFBYSxLQUFLUCxnQkFBTCxDQUFzQlEsR0FBdEIsQ0FBMEJMLFFBQTFCLENBQW5CO0FBQ0EsUUFBSSxPQUFPSSxVQUFQLEtBQXNCLFdBQTFCLEVBQXVDO0FBQ3JDSSx1QkFBT0MsS0FBUCxDQUFhLGtDQUFiLEVBQWlEVCxRQUFqRDtBQUNBO0FBQ0Q7O0FBRUQsVUFBTVUsUUFBUU4sV0FBV08sT0FBWCxDQUFtQlYsU0FBbkIsQ0FBZDtBQUNBLFFBQUlTLFFBQVEsQ0FBWixFQUFlO0FBQ2JGLHVCQUFPQyxLQUFQLENBQWEsa0RBQWIsRUFBaUVULFFBQWpFLEVBQTJFQyxTQUEzRTtBQUNBO0FBQ0Q7QUFDREcsZUFBV1EsTUFBWCxDQUFrQkYsS0FBbEIsRUFBeUIsQ0FBekI7QUFDQTtBQUNBLFFBQUlOLFdBQVdTLE1BQVgsSUFBcUIsQ0FBekIsRUFBNEI7QUFDMUIsV0FBS2hCLGdCQUFMLENBQXNCaUIsTUFBdEIsQ0FBNkJkLFFBQTdCO0FBQ0Q7QUFDRjs7QUFFRGUseUJBQWdDO0FBQzlCLFdBQU8sS0FBS2xCLGdCQUFMLENBQXNCbUIsSUFBdEIsR0FBNkIsQ0FBcEM7QUFDRDtBQTNDZ0I7O1FBK0NqQnpCLFksR0FBQUEsWSIsImZpbGUiOiJTdWJzY3JpcHRpb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCB0eXBlIEZsYXR0ZW5lZE9iamVjdERhdGEgPSB7IFthdHRyOiBzdHJpbmddOiBhbnkgfTtcbmV4cG9ydCB0eXBlIFF1ZXJ5RGF0YSA9IHsgW2F0dHI6IHN0cmluZ106IGFueSB9O1xuXG5jbGFzcyBTdWJzY3JpcHRpb24ge1xuICAvLyBJdCBpcyBxdWVyeSBjb25kaXRpb24gZWcgcXVlcnkud2hlcmVcbiAgcXVlcnk6IFF1ZXJ5RGF0YTtcbiAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gIGhhc2g6IHN0cmluZztcbiAgY2xpZW50UmVxdWVzdElkczogT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogUXVlcnlEYXRhLCBxdWVyeUhhc2g6IHN0cmluZykge1xuICAgIHRoaXMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgIHRoaXMucXVlcnkgPSBxdWVyeTtcbiAgICB0aGlzLmhhc2ggPSBxdWVyeUhhc2g7XG4gICAgdGhpcy5jbGllbnRSZXF1ZXN0SWRzID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgYWRkQ2xpZW50U3Vic2NyaXB0aW9uKGNsaWVudElkOiBudW1iZXIsIHJlcXVlc3RJZDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNsaWVudFJlcXVlc3RJZHMuaGFzKGNsaWVudElkKSkge1xuICAgICAgdGhpcy5jbGllbnRSZXF1ZXN0SWRzLnNldChjbGllbnRJZCwgW10pO1xuICAgIH1cbiAgICBjb25zdCByZXF1ZXN0SWRzID0gdGhpcy5jbGllbnRSZXF1ZXN0SWRzLmdldChjbGllbnRJZCk7XG4gICAgcmVxdWVzdElkcy5wdXNoKHJlcXVlc3RJZCk7XG4gIH1cblxuICBkZWxldGVDbGllbnRTdWJzY3JpcHRpb24oY2xpZW50SWQ6IG51bWJlciwgcmVxdWVzdElkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCByZXF1ZXN0SWRzID0gdGhpcy5jbGllbnRSZXF1ZXN0SWRzLmdldChjbGllbnRJZCk7XG4gICAgaWYgKHR5cGVvZiByZXF1ZXN0SWRzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgbG9nZ2VyLmVycm9yKCdDYW4gbm90IGZpbmQgY2xpZW50ICVkIHRvIGRlbGV0ZScsIGNsaWVudElkKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBpbmRleCA9IHJlcXVlc3RJZHMuaW5kZXhPZihyZXF1ZXN0SWQpO1xuICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgIGxvZ2dlci5lcnJvcignQ2FuIG5vdCBmaW5kIGNsaWVudCAlZCBzdWJzY3JpcHRpb24gJWQgdG8gZGVsZXRlJywgY2xpZW50SWQsIHJlcXVlc3RJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJlcXVlc3RJZHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAvLyBEZWxldGUgY2xpZW50IHJlZmVyZW5jZSBpZiBpdCBoYXMgbm8gc3Vic2NyaXB0aW9uXG4gICAgaWYgKHJlcXVlc3RJZHMubGVuZ3RoID09IDApIHtcbiAgICAgIHRoaXMuY2xpZW50UmVxdWVzdElkcy5kZWxldGUoY2xpZW50SWQpO1xuICAgIH1cbiAgfVxuXG4gIGhhc1N1YnNjcmliaW5nQ2xpZW50KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNsaWVudFJlcXVlc3RJZHMuc2l6ZSA+IDA7XG4gIH1cbn1cblxuZXhwb3J0IHtcbiAgU3Vic2NyaXB0aW9uXG59XG4iXX0= \ No newline at end of file diff --git a/lib/LiveQuery/equalObjects.js b/lib/LiveQuery/equalObjects.js index bb3890a748..3eff04956b 100644 --- a/lib/LiveQuery/equalObjects.js +++ b/lib/LiveQuery/equalObjects.js @@ -47,4 +47,5 @@ function equalObjects(a, b) { return true; } -module.exports = equalObjects; \ No newline at end of file +module.exports = equalObjects; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvZXF1YWxPYmplY3RzLmpzIl0sIm5hbWVzIjpbInRvU3RyaW5nIiwiT2JqZWN0IiwicHJvdG90eXBlIiwiZXF1YWxPYmplY3RzIiwiYSIsImIiLCJjYWxsIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiaSIsImtleXMiLCJrZXkiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBLElBQUlBLFdBQVdDLE9BQU9DLFNBQVAsQ0FBaUJGLFFBQWhDOztBQUVBOzs7O0FBSUEsU0FBU0csWUFBVCxDQUFzQkMsQ0FBdEIsRUFBeUJDLENBQXpCLEVBQTRCO0FBQzFCLE1BQUksT0FBT0QsQ0FBUCxLQUFhLE9BQU9DLENBQXhCLEVBQTJCO0FBQ3pCLFdBQU8sS0FBUDtBQUNEO0FBQ0QsTUFBSSxPQUFPRCxDQUFQLEtBQWEsUUFBakIsRUFBMkI7QUFDekIsV0FBUUEsTUFBTUMsQ0FBZDtBQUNEO0FBQ0QsTUFBSUQsTUFBTUMsQ0FBVixFQUFhO0FBQ1gsV0FBTyxJQUFQO0FBQ0Q7QUFDRCxNQUFJTCxTQUFTTSxJQUFULENBQWNGLENBQWQsTUFBcUIsZUFBekIsRUFBMEM7QUFDeEMsUUFBSUosU0FBU00sSUFBVCxDQUFjRCxDQUFkLE1BQXFCLGVBQXpCLEVBQTBDO0FBQ3hDLGFBQVEsQ0FBQ0QsQ0FBRCxLQUFPLENBQUNDLENBQWhCO0FBQ0Q7QUFDRCxXQUFPLEtBQVA7QUFDRDtBQUNELE1BQUlFLE1BQU1DLE9BQU4sQ0FBY0osQ0FBZCxDQUFKLEVBQXNCO0FBQ3BCLFFBQUlHLE1BQU1DLE9BQU4sQ0FBY0gsQ0FBZCxDQUFKLEVBQXNCO0FBQ3BCLFVBQUlELEVBQUVLLE1BQUYsS0FBYUosRUFBRUksTUFBbkIsRUFBMkI7QUFDekIsZUFBTyxLQUFQO0FBQ0Q7QUFDRCxXQUFLLElBQUlDLElBQUksQ0FBYixFQUFnQkEsSUFBSU4sRUFBRUssTUFBdEIsRUFBOEJDLEdBQTlCLEVBQW1DO0FBQ2pDLFlBQUksQ0FBQ1AsYUFBYUMsRUFBRU0sQ0FBRixDQUFiLEVBQW1CTCxFQUFFSyxDQUFGLENBQW5CLENBQUwsRUFBK0I7QUFDN0IsaUJBQU8sS0FBUDtBQUNEO0FBQ0Y7QUFDRCxhQUFPLElBQVA7QUFDRDtBQUNELFdBQU8sS0FBUDtBQUNEO0FBQ0QsTUFBSVQsT0FBT1UsSUFBUCxDQUFZUCxDQUFaLEVBQWVLLE1BQWYsS0FBMEJSLE9BQU9VLElBQVAsQ0FBWU4sQ0FBWixFQUFlSSxNQUE3QyxFQUFxRDtBQUNuRCxXQUFPLEtBQVA7QUFDRDtBQUNELE9BQUssSUFBSUcsR0FBVCxJQUFnQlIsQ0FBaEIsRUFBbUI7QUFDakIsUUFBSSxDQUFDRCxhQUFhQyxFQUFFUSxHQUFGLENBQWIsRUFBcUJQLEVBQUVPLEdBQUYsQ0FBckIsQ0FBTCxFQUFtQztBQUNqQyxhQUFPLEtBQVA7QUFDRDtBQUNGO0FBQ0QsU0FBTyxJQUFQO0FBQ0Q7O0FBRURDLE9BQU9DLE9BQVAsR0FBaUJYLFlBQWpCIiwiZmlsZSI6ImVxdWFsT2JqZWN0cy5qcyIsInNvdXJjZXNDb250ZW50IjpbInZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIHR3byBvYmplY3RzIHJlcHJlc2VudCB0aGUgc2FtZSBwcmltaXRpdmUsIHNwZWNpYWwgUGFyc2VcbiAqIHR5cGUsIG9yIGZ1bGwgUGFyc2UgT2JqZWN0LlxuICovXG5mdW5jdGlvbiBlcXVhbE9iamVjdHMoYSwgYikge1xuICBpZiAodHlwZW9mIGEgIT09IHR5cGVvZiBiKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICh0eXBlb2YgYSAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gKGEgPT09IGIpO1xuICB9XG4gIGlmIChhID09PSBiKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKHRvU3RyaW5nLmNhbGwoYSkgPT09ICdbb2JqZWN0IERhdGVdJykge1xuICAgIGlmICh0b1N0cmluZy5jYWxsKGIpID09PSAnW29iamVjdCBEYXRlXScpIHtcbiAgICAgIHJldHVybiAoK2EgPT09ICtiKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYikpIHtcbiAgICAgIGlmIChhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICghZXF1YWxPYmplY3RzKGFbaV0sIGJbaV0pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChPYmplY3Qua2V5cyhhKS5sZW5ndGggIT09IE9iamVjdC5rZXlzKGIpLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKHZhciBrZXkgaW4gYSkge1xuICAgIGlmICghZXF1YWxPYmplY3RzKGFba2V5XSwgYltrZXldKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBlcXVhbE9iamVjdHM7XG4iXX0= \ No newline at end of file diff --git a/lib/Options/Definitions.js b/lib/Options/Definitions.js index ae080de808..1b9881ff00 100644 --- a/lib/Options/Definitions.js +++ b/lib/Options/Definitions.js @@ -135,6 +135,12 @@ module.exports.ParseServerOptions = { "env": "PARSE_SERVER_FILE_KEY", "help": "Key for your files" }, + "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 + }, "userSensitiveFields": { "env": "PARSE_SERVER_USER_SENSITIVE_FIELDS", "help": "Personally identifiable information fields in the user table the should be removed for non-authorized users.", @@ -262,6 +268,12 @@ module.exports.ParseServerOptions = { "action": parsers.booleanParser, "default": false }, + "enableExpressErrorHandler": { + "env": "PARSE_SERVER_ENABLE_EXPRESS_ERROR_HANDLER", + "help": "Enables the default express error handler for all errors", + "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", @@ -385,4 +397,5 @@ module.exports.LiveQueryServerOptions = { "help": "LiveQuery pubsub adapter", "action": parsers.moduleOrObjectParser } -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL0RlZmluaXRpb25zLmpzIl0sIm5hbWVzIjpbInBhcnNlcnMiLCJyZXF1aXJlIiwibW9kdWxlIiwiZXhwb3J0cyIsIlBhcnNlU2VydmVyT3B0aW9ucyIsImFycmF5UGFyc2VyIiwibW9kdWxlT3JPYmplY3RQYXJzZXIiLCJvYmplY3RQYXJzZXIiLCJib29sZWFuUGFyc2VyIiwibnVtYmVyUGFyc2VyIiwibnVtYmVyT3JCb29sZWFuUGFyc2VyIiwiQ3VzdG9tUGFnZXNPcHRpb25zIiwiTGl2ZVF1ZXJ5T3B0aW9ucyIsIkxpdmVRdWVyeVNlcnZlck9wdGlvbnMiXSwibWFwcGluZ3MiOiJBQUFBOzs7O0VBSUU7O0FBRUYsSUFBSUEsVUFBVUMsUUFBUSxXQUFSLENBQWQ7O0FBRUFDLE9BQU9DLE9BQVAsQ0FBZUMsa0JBQWYsR0FBb0M7QUFDbEMsV0FBUztBQUNQLFdBQU8sNkJBREE7QUFFUCxZQUFRLDJCQUZEO0FBR1AsZ0JBQVk7QUFITCxHQUR5QjtBQU1sQyxlQUFhO0FBQ1gsV0FBTyx5QkFESTtBQUVYLFlBQVEsdUJBRkc7QUFHWCxnQkFBWTtBQUhELEdBTnFCO0FBV2xDLGVBQWE7QUFDWCxXQUFPLGtCQURJO0FBRVgsWUFBUSxvREFGRztBQUdYLGdCQUFZO0FBSEQsR0FYcUI7QUFnQmxDLGtCQUFnQjtBQUNkLFdBQU8sNkJBRE87QUFFZCxZQUFRLGlGQUZNO0FBR2QsY0FBVUosUUFBUUssV0FISjtBQUlkLGVBQVc7QUFKRyxHQWhCa0I7QUFzQmxDLGFBQVc7QUFDVCxXQUFPLHVCQURFO0FBRVQsWUFBUTtBQUZDLEdBdEJ1QjtBQTBCbEMsc0JBQW9CO0FBQ2xCLFdBQU8sZ0NBRFc7QUFFbEIsWUFBUSxrQ0FGVTtBQUdsQixjQUFVTCxRQUFRTTtBQUhBLEdBMUJjO0FBK0JsQyxrQkFBZ0I7QUFDZCxXQUFPLDRCQURPO0FBRWQsWUFBUSx5Q0FGTTtBQUdkLGNBQVVOLFFBQVFNO0FBSEosR0EvQmtCO0FBb0NsQyxVQUFRO0FBQ04s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Q09ERSAqKioqXG5UaGlzIGNvZGUgaGFzIGJlZW4gZ2VuZXJhdGVkIGJ5IHJlc291cmNlcy9idWlsZENvbmZpZ0RlZmluaXRpb25zLmpzXG5EbyBub3QgZWRpdCBtYW51YWxseSwgYnV0IHVwZGF0ZSBPcHRpb25zL2luZGV4LmpzXG4qL1widXNlIHN0cmljdFwiO1xuXG52YXIgcGFyc2VycyA9IHJlcXVpcmUoXCIuL3BhcnNlcnNcIik7XG5cbm1vZHVsZS5leHBvcnRzLlBhcnNlU2VydmVyT3B0aW9ucyA9IHtcbiAgXCJhcHBJZFwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfQVBQTElDQVRJT05fSURcIixcbiAgICBcImhlbHBcIjogXCJZb3VyIFBhcnNlIEFwcGxpY2F0aW9uIElEXCIsXG4gICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gIH0sXG4gIFwibWFzdGVyS2V5XCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9NQVNURVJfS0VZXCIsXG4gICAgXCJoZWxwXCI6IFwiWW91ciBQYXJzZSBNYXN0ZXIgS2V5XCIsXG4gICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gIH0sXG4gIFwic2VydmVyVVJMXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9VUkxcIixcbiAgICBcImhlbHBcIjogXCJVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLlwiLFxuICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICB9LFxuICBcIm1hc3RlcktleUlwc1wiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfTUFTVEVSX0tFWV9JUFNcIixcbiAgICBcImhlbHBcIjogXCJSZXN0cmljdCBtYXN0ZXJLZXkgdG8gYmUgdXNlZCBieSBvbmx5IHRoZXNlIGlwcy4gZGVmYXVsdHMgdG8gW10gKGFsbG93IGFsbCBpcHMpXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5hcnJheVBhcnNlcixcbiAgICBcImRlZmF1bHRcIjogW11cbiAgfSxcbiAgXCJhcHBOYW1lXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9BUFBfTkFNRVwiLFxuICAgIFwiaGVscFwiOiBcIlNldHMgdGhlIGFwcCBuYW1lXCJcbiAgfSxcbiAgXCJhbmFseXRpY3NBZGFwdGVyXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9BTkFMWVRJQ1NfQURBUFRFUlwiLFxuICAgIFwiaGVscFwiOiBcIkFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgYW5hbHl0aWNzXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5tb2R1bGVPck9iamVjdFBhcnNlclxuICB9LFxuICBcImZpbGVzQWRhcHRlclwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfRklMRVNfQURBUFRFUlwiLFxuICAgIFwiaGVscFwiOiBcIkFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgZmlsZXMgc3ViLXN5c3RlbVwiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXJcbiAgfSxcbiAgXCJwdXNoXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9QVVNIXCIsXG4gICAgXCJoZWxwXCI6IFwiQ29uZmlndXJhdGlvbiBmb3IgcHVzaCwgYXMgc3RyaW5naWZpZWQgSlNPTi4gU2VlIGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8jcHVzaC1ub3RpZmljYXRpb25zXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5vYmplY3RQYXJzZXJcbiAgfSxcbiAgXCJzY2hlZHVsZWRQdXNoXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9TQ0hFRFVMRURfUFVTSFwiLFxuICAgIFwiaGVscFwiOiBcIkNvbmZpZ3VyYXRpb24gZm9yIHB1c2ggc2NoZWR1bGluZy4gRGVmYXVsdHMgdG8gZmFsc2UuXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICB9LFxuICBcImxvZ2dlckFkYXB0ZXJcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0xPR0dFUl9BREFQVEVSXCIsXG4gICAgXCJoZWxwXCI6IFwiQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBsb2dnaW5nIHN1Yi1zeXN0ZW1cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyXG4gIH0sXG4gIFwianNvbkxvZ3NcIjoge1xuICAgIFwiZW52XCI6IFwiSlNPTl9MT0dTXCIsXG4gICAgXCJoZWxwXCI6IFwiTG9nIGFzIHN0cnVjdHVyZWQgSlNPTiBvYmplY3RzXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyXG4gIH0sXG4gIFwibG9nc0ZvbGRlclwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfTE9HU19GT0xERVJcIixcbiAgICBcImhlbHBcIjogXCJGb2xkZXIgZm9yIHRoZSBsb2dzIChkZWZhdWx0cyB0byAnLi9sb2dzJyk7IHNldCB0byBudWxsIHRvIGRpc2FibGUgZmlsZSBiYXNlZCBsb2dnaW5nXCIsXG4gICAgXCJkZWZhdWx0XCI6IFwiLi9sb2dzXCJcbiAgfSxcbiAgXCJ2ZXJib3NlXCI6IHtcbiAgICBcImVudlwiOiBcIlZFUkJPU0VcIixcbiAgICBcImhlbHBcIjogXCJTZXQgdGhlIGxvZ2dpbmcgdG8gdmVyYm9zZVwiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMuYm9vbGVhblBhcnNlclxuICB9LFxuICBcImxvZ0xldmVsXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9MT0dfTEVWRUxcIixcbiAgICBcImhlbHBcIjogXCJTZXRzIHRoZSBsZXZlbCBmb3IgbG9nc1wiXG4gIH0sXG4gIFwic2lsZW50XCI6IHtcbiAgICBcImVudlwiOiBcIlNJTEVOVFwiLFxuICAgIFwiaGVscFwiOiBcIkRpc2FibGVzIGNvbnNvbGUgb3V0cHV0XCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyXG4gIH0sXG4gIFwiZGF0YWJhc2VVUklcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0RBVEFCQVNFX1VSSVwiLFxuICAgIFwiaGVscFwiOiBcIlRoZSBmdWxsIFVSSSB0byB5b3VyIG1vbmdvZGIgZGF0YWJhc2VcIixcbiAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgXCJkZWZhdWx0XCI6IFwibW9uZ29kYjovL2xvY2FsaG9zdDoyNzAxNy9wYXJzZVwiXG4gIH0sXG4gIFwiZGF0YWJhc2VPcHRpb25zXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9EQVRBQkFTRV9PUFRJT05TXCIsXG4gICAgXCJoZWxwXCI6IFwiT3B0aW9ucyB0byBwYXNzIHRvIHRoZSBtb25nb2RiIGNsaWVudFwiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMub2JqZWN0UGFyc2VyXG4gIH0sXG4gIFwiZGF0YWJhc2VBZGFwdGVyXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9EQVRBQkFTRV9BREFQVEVSXCIsXG4gICAgXCJoZWxwXCI6IFwiQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBkYXRhYmFzZVwiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMubW9kdWxlT3JPYmplY3RQYXJzZXJcbiAgfSxcbiAgXCJjbG91ZFwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfQ0xPVURcIixcbiAgICBcImhlbHBcIjogXCJGdWxsIHBhdGggdG8geW91ciBjbG91ZCBjb2RlIG1haW4uanNcIlxuICB9LFxuICBcImNvbGxlY3Rpb25QcmVmaXhcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0NPTExFQ1RJT05fUFJFRklYXCIsXG4gICAgXCJoZWxwXCI6IFwiQSBjb2xsZWN0aW9uIHByZWZpeCBmb3IgdGhlIGNsYXNzZXNcIixcbiAgICBcImRlZmF1bHRcIjogXCJcIlxuICB9LFxuICBcImNsaWVudEtleVwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfQ0xJRU5UX0tFWVwiLFxuICAgIFwiaGVscFwiOiBcIktleSBmb3IgaU9TLCBNYWNPUywgdHZPUyBjbGllbnRzXCJcbiAgfSxcbiAgXCJqYXZhc2NyaXB0S2V5XCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9KQVZBU0NSSVBUX0tFWVwiLFxuICAgIFwiaGVscFwiOiBcIktleSBmb3IgdGhlIEphdmFzY3JpcHQgU0RLXCJcbiAgfSxcbiAgXCJkb3ROZXRLZXlcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0RPVF9ORVRfS0VZXCIsXG4gICAgXCJoZWxwXCI6IFwiS2V5IGZvciBVbml0eSBhbmQgLk5ldCBTREtcIlxuICB9LFxuICBcInJlc3RBUElLZXlcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1JFU1RfQVBJX0tFWVwiLFxuICAgIFwiaGVscFwiOiBcIktleSBmb3IgUkVTVCBjYWxsc1wiXG4gIH0sXG4gIFwicmVhZE9ubHlNYXN0ZXJLZXlcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1JFQURfT05MWV9NQVNURVJfS0VZXCIsXG4gICAgXCJoZWxwXCI6IFwiUmVhZC1vbmx5IGtleSwgd2hpY2ggaGFzIHRoZSBzYW1lIGNhcGFiaWxpdGllcyBhcyBNYXN0ZXJLZXkgd2l0aG91dCB3cml0ZXNcIlxuICB9LFxuICBcIndlYmhvb2tLZXlcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1dFQkhPT0tfS0VZXCIsXG4gICAgXCJoZWxwXCI6IFwiS2V5IHNlbnQgd2l0aCBvdXRnb2luZyB3ZWJob29rIGNhbGxzXCJcbiAgfSxcbiAgXCJmaWxlS2V5XCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9GSUxFX0tFWVwiLFxuICAgIFwiaGVscFwiOiBcIktleSBmb3IgeW91ciBmaWxlc1wiXG4gIH0sXG4gIFwicHJlc2VydmVGaWxlTmFtZVwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfUFJFU0VSVkVfRklMRV9OQU1FXCIsXG4gICAgXCJoZWxwXCI6IFwiRW5hYmxlIChvciBkaXNhYmxlKSB0aGUgYWRkaXRpb24gb2YgYSB1bmlxdWUgaGFzaCB0byB0aGUgZmlsZSBuYW1lc1wiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBcImRlZmF1bHRcIjogZmFsc2VcbiAgfSxcbiAgXCJ1c2VyU2Vuc2l0aXZlRmllbGRzXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9VU0VSX1NFTlNJVElWRV9GSUVMRFNcIixcbiAgICBcImhlbHBcIjogXCJQZXJzb25hbGx5IGlkZW50aWZpYWJsZSBpbmZvcm1hdGlvbiBmaWVsZHMgaW4gdGhlIHVzZXIgdGFibGUgdGhlIHNob3VsZCBiZSByZW1vdmVkIGZvciBub24tYXV0aG9yaXplZCB1c2Vycy5cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLmFycmF5UGFyc2VyLFxuICAgIFwiZGVmYXVsdFwiOiBbXCJlbWFpbFwiXVxuICB9LFxuICBcImVuYWJsZUFub255bW91c1VzZXJzXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9FTkFCTEVfQU5PTl9VU0VSU1wiLFxuICAgIFwiaGVscFwiOiBcIkVuYWJsZSAob3IgZGlzYWJsZSkgYW5vbiB1c2VycywgZGVmYXVsdHMgdG8gdHJ1ZVwiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBcImRlZmF1bHRcIjogdHJ1ZVxuICB9LFxuICBcImFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvblwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfQUxMT1dfQ0xJRU5UX0NMQVNTX0NSRUFUSU9OXCIsXG4gICAgXCJoZWxwXCI6IFwiRW5hYmxlIChvciBkaXNhYmxlKSBjbGllbnQgY2xhc3MgY3JlYXRpb24sIGRlZmF1bHRzIHRvIHRydWVcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgXCJkZWZhdWx0XCI6IHRydWVcbiAgfSxcbiAgXCJhdXRoXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9BVVRIX1BST1ZJREVSU1wiLFxuICAgIFwiaGVscFwiOiBcIkNvbmZpZ3VyYXRpb24gZm9yIHlvdXIgYXV0aGVudGljYXRpb24gcHJvdmlkZXJzLCBhcyBzdHJpbmdpZmllZCBKU09OLiBTZWUgaHR0cDovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvcGFyc2Utc2VydmVyL2d1aWRlLyNvYXV0aC1hbmQtM3JkLXBhcnR5LWF1dGhlbnRpY2F0aW9uXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5vYmplY3RQYXJzZXJcbiAgfSxcbiAgXCJtYXhVcGxvYWRTaXplXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9NQVhfVVBMT0FEX1NJWkVcIixcbiAgICBcImhlbHBcIjogXCJNYXggZmlsZSBzaXplIGZvciB1cGxvYWRzLiBkZWZhdWx0cyB0byAyMG1iXCIsXG4gICAgXCJkZWZhdWx0XCI6IFwiMjBtYlwiXG4gIH0sXG4gIFwidmVyaWZ5VXNlckVtYWlsc1wiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfVkVSSUZZX1VTRVJfRU1BSUxTXCIsXG4gICAgXCJoZWxwXCI6IFwiRW5hYmxlIChvciBkaXNhYmxlKSB1c2VyIGVtYWlsIHZhbGlkYXRpb24sIGRlZmF1bHRzIHRvIGZhbHNlXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICB9LFxuICBcInByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWxcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1BSRVZFTlRfTE9HSU5fV0lUSF9VTlZFUklGSUVEX0VNQUlMXCIsXG4gICAgXCJoZWxwXCI6IFwiUHJldmVudCB1c2VyIGZyb20gbG9naW4gaWYgZW1haWwgaXMgbm90IHZlcmlmaWVkIGFuZCBQQVJTRV9TRVJWRVJfVkVSSUZZX1VTRVJfRU1BSUxTIGlzIHRydWUsIGRlZmF1bHRzIHRvIGZhbHNlXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICB9LFxuICBcImVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9FTUFJTF9WRVJJRllfVE9LRU5fVkFMSURJVFlfRFVSQVRJT05cIixcbiAgICBcImhlbHBcIjogXCJFbWFpbCB2ZXJpZmljYXRpb24gdG9rZW4gdmFsaWRpdHkgZHVyYXRpb25cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm51bWJlclBhcnNlcihcImVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uXCIpXG4gIH0sXG4gIFwiYWNjb3VudExvY2tvdXRcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0FDQ09VTlRfTE9DS09VVFwiLFxuICAgIFwiaGVscFwiOiBcImFjY291bnQgbG9ja291dCBwb2xpY3kgZm9yIGZhaWxlZCBsb2dpbiBhdHRlbXB0c1wiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMub2JqZWN0UGFyc2VyXG4gIH0sXG4gIFwicGFzc3dvcmRQb2xpY3lcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1BBU1NXT1JEX1BPTElDWVwiLFxuICAgIFwiaGVscFwiOiBcIlBhc3N3b3JkIHBvbGljeSBmb3IgZW5mb3JjaW5nIHBhc3N3b3JkIHJlbGF0ZWQgcnVsZXNcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm9iamVjdFBhcnNlclxuICB9LFxuICBcImNhY2hlQWRhcHRlclwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfQ0FDSEVfQURBUFRFUlwiLFxuICAgIFwiaGVscFwiOiBcIkFkYXB0ZXIgbW9kdWxlIGZvciB0aGUgY2FjaGVcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm1vZHVsZU9yT2JqZWN0UGFyc2VyXG4gIH0sXG4gIFwiZW1haWxBZGFwdGVyXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9FTUFJTF9BREFQVEVSXCIsXG4gICAgXCJoZWxwXCI6IFwiQWRhcHRlciBtb2R1bGUgZm9yIHRoZSBlbWFpbCBzZW5kaW5nXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5tb2R1bGVPck9iamVjdFBhcnNlclxuICB9LFxuICBcInB1YmxpY1NlcnZlclVSTFwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9QVUJMSUNfU0VSVkVSX1VSTFwiLFxuICAgIFwiaGVscFwiOiBcIlB1YmxpYyBVUkwgdG8geW91ciBwYXJzZSBzZXJ2ZXIgd2l0aCBodHRwOi8vIG9yIGh0dHBzOi8vLlwiXG4gIH0sXG4gIFwiY3VzdG9tUGFnZXNcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFU1wiLFxuICAgIFwiaGVscFwiOiBcImN1c3RvbSBwYWdlcyBmb3IgcGFzc3dvcmQgdmFsaWRhdGlvbiBhbmQgcmVzZXRcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm9iamVjdFBhcnNlcixcbiAgICBcImRlZmF1bHRcIjoge31cbiAgfSxcbiAgXCJsaXZlUXVlcnlcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0xJVkVfUVVFUllcIixcbiAgICBcImhlbHBcIjogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgY29uZmlndXJhdGlvbiBvYmplY3RcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm9iamVjdFBhcnNlclxuICB9LFxuICBcInNlc3Npb25MZW5ndGhcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1NFU1NJT05fTEVOR1RIXCIsXG4gICAgXCJoZWxwXCI6IFwiU2Vzc2lvbiBkdXJhdGlvbiwgaW4gc2Vjb25kcywgZGVmYXVsdHMgdG8gMSB5ZWFyXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5udW1iZXJQYXJzZXIoXCJzZXNzaW9uTGVuZ3RoXCIpLFxuICAgIFwiZGVmYXVsdFwiOiAzMTUzNjAwMFxuICB9LFxuICBcIm1heExpbWl0XCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9NQVhfTElNSVRcIixcbiAgICBcImhlbHBcIjogXCJNYXggdmFsdWUgZm9yIGxpbWl0IG9wdGlvbiBvbiBxdWVyaWVzLCBkZWZhdWx0cyB0byB1bmxpbWl0ZWRcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm51bWJlclBhcnNlcihcIm1heExpbWl0XCIpXG4gIH0sXG4gIFwiZXhwaXJlSW5hY3RpdmVTZXNzaW9uc1wiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfRVhQSVJFX0lOQUNUSVZFX1NFU1NJT05TXCIsXG4gICAgXCJoZWxwXCI6IFwiU2V0cyB3ZXRoZXIgd2Ugc2hvdWxkIGV4cGlyZSB0aGUgaW5hY3RpdmUgc2Vzc2lvbnMsIGRlZmF1bHRzIHRvIHRydWVcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLmJvb2xlYW5QYXJzZXIsXG4gICAgXCJkZWZhdWx0XCI6IHRydWVcbiAgfSxcbiAgXCJyZXZva2VTZXNzaW9uT25QYXNzd29yZFJlc2V0XCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9SRVZPS0VfU0VTU0lPTl9PTl9QQVNTV09SRF9SRVNFVFwiLFxuICAgIFwiaGVscFwiOiBcIldoZW4gYSB1c2VyIGNoYW5nZXMgdGhlaXIgcGFzc3dvcmQsIGVpdGhlciB0aHJvdWdoIHRoZSByZXNldCBwYXNzd29yZCBlbWFpbCBvciB3aGlsZSBsb2dnZWQgaW4sIGFsbCBzZXNzaW9ucyBhcmUgcmV2b2tlZCBpZiB0aGlzIGlzIHRydWUuIFNldCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0byByZXZva2Ugc2Vzc2lvbnMuXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIFwiZGVmYXVsdFwiOiB0cnVlXG4gIH0sXG4gIFwic2NoZW1hQ2FjaGVUVExcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1NDSEVNQV9DQUNIRV9UVExcIixcbiAgICBcImhlbHBcIjogXCJUaGUgVFRMIGZvciBjYWNoaW5nIHRoZSBzY2hlbWEgZm9yIG9wdGltaXppbmcgcmVhZC93cml0ZSBvcGVyYXRpb25zLiBZb3Ugc2hvdWxkIHB1dCBhIGxvbmcgVFRMIHdoZW4geW91ciBEQiBpcyBpbiBwcm9kdWN0aW9uLiBkZWZhdWx0IHRvIDUwMDA7IHNldCAwIHRvIGRpc2FibGUuXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5udW1iZXJQYXJzZXIoXCJzY2hlbWFDYWNoZVRUTFwiKSxcbiAgICBcImRlZmF1bHRcIjogNTAwMFxuICB9LFxuICBcImNhY2hlVFRMXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9DQUNIRV9UVExcIixcbiAgICBcImhlbHBcIjogXCJTZXRzIHRoZSBUVEwgZm9yIHRoZSBpbiBtZW1vcnkgY2FjaGUgKGluIG1zKSwgZGVmYXVsdHMgdG8gNTAwMCAoNSBzZWNvbmRzKVwiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMubnVtYmVyUGFyc2VyKFwiY2FjaGVUVExcIiksXG4gICAgXCJkZWZhdWx0XCI6IDUwMDBcbiAgfSxcbiAgXCJjYWNoZU1heFNpemVcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0NBQ0hFX01BWF9TSVpFXCIsXG4gICAgXCJoZWxwXCI6IFwiU2V0cyB0aGUgbWF4aW11bSBzaXplIGZvciB0aGUgaW4gbWVtb3J5IGNhY2hlLCBkZWZhdWx0cyB0byAxMDAwMFwiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMubnVtYmVyUGFyc2VyKFwiY2FjaGVNYXhTaXplXCIpLFxuICAgIFwiZGVmYXVsdFwiOiAxMDAwMFxuICB9LFxuICBcImVuYWJsZVNpbmdsZVNjaGVtYUNhY2hlXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9FTkFCTEVfU0lOR0xFX1NDSEVNQV9DQUNIRVwiLFxuICAgIFwiaGVscFwiOiBcIlVzZSBhIHNpbmdsZSBzY2hlbWEgY2FjaGUgc2hhcmVkIGFjcm9zcyByZXF1ZXN0cy4gUmVkdWNlcyBudW1iZXIgb2YgcXVlcmllcyBtYWRlIHRvIF9TQ0hFTUEuIERlZmF1bHRzIHRvIGZhbHNlLCBpLmUuIHVuaXF1ZSBzY2hlbWEgY2FjaGUgcGVyIHJlcXVlc3QuXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyLFxuICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICB9LFxuICBcImVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXJcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0VOQUJMRV9FWFBSRVNTX0VSUk9SX0hBTkRMRVJcIixcbiAgICBcImhlbHBcIjogXCJFbmFibGVzIHRoZSBkZWZhdWx0IGV4cHJlc3MgZXJyb3IgaGFuZGxlciBmb3IgYWxsIGVycm9yc1wiLFxuICAgIFwiYWN0aW9uXCI6IHBhcnNlcnMuYm9vbGVhblBhcnNlcixcbiAgICBcImRlZmF1bHRcIjogZmFsc2VcbiAgfSxcbiAgXCJvYmplY3RJZFNpemVcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX09CSkVDVF9JRF9TSVpFXCIsXG4gICAgXCJoZWxwXCI6IFwiU2V0cyB0aGUgbnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gZ2VuZXJhdGVkIG9iamVjdCBpZCdzLCBkZWZhdWx0IDEwXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5udW1iZXJQYXJzZXIoXCJvYmplY3RJZFNpemVcIiksXG4gICAgXCJkZWZhdWx0XCI6IDEwXG4gIH0sXG4gIFwicG9ydFwiOiB7XG4gICAgXCJlbnZcIjogXCJQT1JUXCIsXG4gICAgXCJoZWxwXCI6IFwiVGhlIHBvcnQgdG8gcnVuIHRoZSBQYXJzZVNlcnZlci4gZGVmYXVsdHMgdG8gMTMzNy5cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm51bWJlclBhcnNlcihcInBvcnRcIiksXG4gICAgXCJkZWZhdWx0XCI6IDEzMzdcbiAgfSxcbiAgXCJob3N0XCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9IT1NUXCIsXG4gICAgXCJoZWxwXCI6IFwiVGhlIGhvc3QgdG8gc2VydmUgUGFyc2VTZXJ2ZXIgb24uIGRlZmF1bHRzIHRvIDAuMC4wLjBcIixcbiAgICBcImRlZmF1bHRcIjogXCIwLjAuMC4wXCJcbiAgfSxcbiAgXCJtb3VudFBhdGhcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX01PVU5UX1BBVEhcIixcbiAgICBcImhlbHBcIjogXCJNb3VudCBwYXRoIGZvciB0aGUgc2VydmVyLCBkZWZhdWx0cyB0byAvcGFyc2VcIixcbiAgICBcImRlZmF1bHRcIjogXCIvcGFyc2VcIlxuICB9LFxuICBcImNsdXN0ZXJcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0NMVVNURVJcIixcbiAgICBcImhlbHBcIjogXCJSdW4gd2l0aCBjbHVzdGVyLCBvcHRpb25hbGx5IHNldCB0aGUgbnVtYmVyIG9mIHByb2Nlc3NlcyBkZWZhdWx0IHRvIG9zLmNwdXMoKS5sZW5ndGhcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm51bWJlck9yQm9vbGVhblBhcnNlclxuICB9LFxuICBcIm1pZGRsZXdhcmVcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX01JRERMRVdBUkVcIixcbiAgICBcImhlbHBcIjogXCJtaWRkbGV3YXJlIGZvciBleHByZXNzIHNlcnZlciwgY2FuIGJlIHN0cmluZyBvciBmdW5jdGlvblwiXG4gIH0sXG4gIFwic3RhcnRMaXZlUXVlcnlTZXJ2ZXJcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX1NUQVJUX0xJVkVfUVVFUllfU0VSVkVSXCIsXG4gICAgXCJoZWxwXCI6IFwiU3RhcnRzIHRoZSBsaXZlUXVlcnkgc2VydmVyXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5ib29sZWFuUGFyc2VyXG4gIH0sXG4gIFwibGl2ZVF1ZXJ5U2VydmVyT3B0aW9uc1wiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9TRVJWRVJfTElWRV9RVUVSWV9TRVJWRVJfT1BUSU9OU1wiLFxuICAgIFwiaGVscFwiOiBcIkxpdmUgcXVlcnkgc2VydmVyIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyAod2lsbCBzdGFydCB0aGUgbGl2ZVF1ZXJ5IHNlcnZlcilcIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm9iamVjdFBhcnNlclxuICB9XG59O1xubW9kdWxlLmV4cG9ydHMuQ3VzdG9tUGFnZXNPcHRpb25zID0ge1xuICBcImludmFsaWRMaW5rXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfSU5WQUxJRF9MSU5LXCIsXG4gICAgXCJoZWxwXCI6IFwiaW52YWxpZCBsaW5rIHBhZ2UgcGF0aFwiXG4gIH0sXG4gIFwidmVyaWZ5RW1haWxTdWNjZXNzXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfVkVSSUZZX0VNQUlMX1NVQ0NFU1NcIixcbiAgICBcImhlbHBcIjogXCJ2ZXJpZnkgZW1haWwgc3VjY2VzcyBwYWdlIHBhdGhcIlxuICB9LFxuICBcImNob29zZVBhc3N3b3JkXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9DVVNUT01fUEFHRVNfQ0hPT1NFX1BBU1NXT1JEXCIsXG4gICAgXCJoZWxwXCI6IFwiY2hvb3NlIHBhc3N3b3JkIHBhZ2UgcGF0aFwiXG4gIH0sXG4gIFwicGFzc3dvcmRSZXNldFN1Y2Nlc3NcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfU0VSVkVSX0NVU1RPTV9QQUdFU19QQVNTV09SRF9SRVNFVF9TVUNDRVNTXCIsXG4gICAgXCJoZWxwXCI6IFwicGFzc3dvcmQgcmVzZXQgc3VjY2VzcyBwYWdlIHBhdGhcIlxuICB9XG59O1xubW9kdWxlLmV4cG9ydHMuTGl2ZVF1ZXJ5T3B0aW9ucyA9IHtcbiAgXCJjbGFzc05hbWVzXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9MSVZFUVVFUllfQ0xBU1NOQU1FU1wiLFxuICAgIFwiaGVscFwiOiBcInBhcnNlLXNlcnZlcidzIExpdmVRdWVyeSBjbGFzc05hbWVzXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5hcnJheVBhcnNlclxuICB9LFxuICBcInJlZGlzVVJMXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9MSVZFUVVFUllfUkVESVNfVVJMXCIsXG4gICAgXCJoZWxwXCI6IFwicGFyc2Utc2VydmVyJ3MgTGl2ZVF1ZXJ5IHJlZGlzVVJMXCJcbiAgfSxcbiAgXCJwdWJTdWJBZGFwdGVyXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX1NFUlZFUl9MSVZFUVVFUllfUFVCX1NVQl9BREFQVEVSXCIsXG4gICAgXCJoZWxwXCI6IFwiTGl2ZVF1ZXJ5IHB1YnN1YiBhZGFwdGVyXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5tb2R1bGVPck9iamVjdFBhcnNlclxuICB9XG59O1xubW9kdWxlLmV4cG9ydHMuTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyA9IHtcbiAgXCJhcHBJZFwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9BUFBfSURcIixcbiAgICBcImhlbHBcIjogXCJUaGlzIHN0cmluZyBzaG91bGQgbWF0Y2ggdGhlIGFwcElkIGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgYXBwSWQuXCJcbiAgfSxcbiAgXCJtYXN0ZXJLZXlcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfTUFTVEVSX0tFWVwiLFxuICAgIFwiaGVscFwiOiBcIlRoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCB0aGUgbWFzdGVyS2V5IGluIHVzZSBieSB5b3VyIFBhcnNlIFNlcnZlci4gSWYgeW91IGRlcGxveSB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciBhbG9uZ3NpZGUgUGFyc2UgU2VydmVyLCB0aGUgTGl2ZVF1ZXJ5IHNlcnZlciB3aWxsIHRyeSB0byB1c2UgdGhlIHNhbWUgbWFzdGVyS2V5LlwiXG4gIH0sXG4gIFwic2VydmVyVVJMXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX0xJVkVfUVVFUllfU0VSVkVSX1NFUlZFUl9VUkxcIixcbiAgICBcImhlbHBcIjogXCJUaGlzIHN0cmluZyBzaG91bGQgbWF0Y2ggdGhlIHNlcnZlclVSTCBpbiB1c2UgYnkgeW91ciBQYXJzZSBTZXJ2ZXIuIElmIHlvdSBkZXBsb3kgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgYWxvbmdzaWRlIFBhcnNlIFNlcnZlciwgdGhlIExpdmVRdWVyeSBzZXJ2ZXIgd2lsbCB0cnkgdG8gdXNlIHRoZSBzYW1lIHNlcnZlclVSTC5cIlxuICB9LFxuICBcImtleVBhaXJzXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX0xJVkVfUVVFUllfU0VSVkVSX0tFWV9QQUlSU1wiLFxuICAgIFwiaGVscFwiOiBcIkEgSlNPTiBvYmplY3QgdGhhdCBzZXJ2ZXMgYXMgYSB3aGl0ZWxpc3Qgb2Yga2V5cy4gSXQgaXMgdXNlZCBmb3IgdmFsaWRhdGluZyBjbGllbnRzIHdoZW4gdGhleSB0cnkgdG8gY29ubmVjdCB0byB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gQ2hlY2sgdGhlIGZvbGxvd2luZyBTZWN1cml0eSBzZWN0aW9uIGFuZCBvdXIgcHJvdG9jb2wgc3BlY2lmaWNhdGlvbiBmb3IgZGV0YWlscy5cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm9iamVjdFBhcnNlclxuICB9LFxuICBcIndlYnNvY2tldFRpbWVvdXRcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfV0VCU09DS0VUX1RJTUVPVVRcIixcbiAgICBcImhlbHBcIjogXCJOdW1iZXIgb2YgbWlsbGlzZWNvbmRzIGJldHdlZW4gcGluZy9wb25nIGZyYW1lcy4gVGhlIFdlYlNvY2tldCBzZXJ2ZXIgc2VuZHMgcGluZy9wb25nIGZyYW1lcyB0byB0aGUgY2xpZW50cyB0byBrZWVwIHRoZSBXZWJTb2NrZXQgYWxpdmUuIFRoaXMgdmFsdWUgZGVmaW5lcyB0aGUgaW50ZXJ2YWwgb2YgdGhlIHBpbmcvcG9uZyBmcmFtZSBmcm9tIHRoZSBzZXJ2ZXIgdG8gY2xpZW50cy4gRGVmYXVsdHMgdG8gMTAgKiAxMDAwIG1zICgxMCBzKS5cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm51bWJlclBhcnNlcihcIndlYnNvY2tldFRpbWVvdXRcIilcbiAgfSxcbiAgXCJjYWNoZVRpbWVvdXRcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfQ0FDSEVfVElNRU9VVFwiLFxuICAgIFwiaGVscFwiOiBcIk51bWJlciBpbiBtaWxsaXNlY29uZHMuIFdoZW4gY2xpZW50cyBwcm92aWRlIHRoZSBzZXNzaW9uVG9rZW4gdG8gdGhlIExpdmVRdWVyeSBzZXJ2ZXIsIHRoZSBMaXZlUXVlcnkgc2VydmVyIHdpbGwgdHJ5IHRvIGZldGNoIGl0cyBQYXJzZVVzZXIncyBvYmplY3RJZCBmcm9tIHBhcnNlIHNlcnZlciBhbmQgc3RvcmUgaXQgaW4gdGhlIGNhY2hlLiBUaGUgdmFsdWUgZGVmaW5lcyB0aGUgZHVyYXRpb24gb2YgdGhlIGNhY2hlLiBDaGVjayB0aGUgZm9sbG93aW5nIFNlY3VyaXR5IHNlY3Rpb24gYW5kIG91ciBwcm90b2NvbCBzcGVjaWZpY2F0aW9uIGZvciBkZXRhaWxzLiBEZWZhdWx0cyB0byAzMCAqIDI0ICogNjAgKiA2MCAqIDEwMDAgbXMgKH4zMCBkYXlzKS5cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm51bWJlclBhcnNlcihcImNhY2hlVGltZW91dFwiKVxuICB9LFxuICBcImxvZ0xldmVsXCI6IHtcbiAgICBcImVudlwiOiBcIlBBUlNFX0xJVkVfUVVFUllfU0VSVkVSX0xPR19MRVZFTFwiLFxuICAgIFwiaGVscFwiOiBcIlRoaXMgc3RyaW5nIGRlZmluZXMgdGhlIGxvZyBsZXZlbCBvZiB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gV2Ugc3VwcG9ydCBWRVJCT1NFLCBJTkZPLCBFUlJPUiwgTk9ORS4gRGVmYXVsdHMgdG8gSU5GTy5cIlxuICB9LFxuICBcInBvcnRcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfUE9SVFwiLFxuICAgIFwiaGVscFwiOiBcIlRoZSBwb3J0IHRvIHJ1biB0aGUgTGl2ZVF1ZXJ5IHNlcnZlci4gRGVmYXVsdHMgdG8gMTMzNy5cIixcbiAgICBcImFjdGlvblwiOiBwYXJzZXJzLm51bWJlclBhcnNlcihcInBvcnRcIiksXG4gICAgXCJkZWZhdWx0XCI6IDEzMzdcbiAgfSxcbiAgXCJyZWRpc1VSTFwiOiB7XG4gICAgXCJlbnZcIjogXCJQQVJTRV9MSVZFX1FVRVJZX1NFUlZFUl9SRURJU19VUkxcIixcbiAgICBcImhlbHBcIjogXCJwYXJzZS1zZXJ2ZXIncyBMaXZlUXVlcnkgcmVkaXNVUkxcIlxuICB9LFxuICBcInB1YlN1YkFkYXB0ZXJcIjoge1xuICAgIFwiZW52XCI6IFwiUEFSU0VfTElWRV9RVUVSWV9TRVJWRVJfUFVCX1NVQl9BREFQVEVSXCIsXG4gICAgXCJoZWxwXCI6IFwiTGl2ZVF1ZXJ5IHB1YnN1YiBhZGFwdGVyXCIsXG4gICAgXCJhY3Rpb25cIjogcGFyc2Vycy5tb2R1bGVPck9iamVjdFBhcnNlclxuICB9XG59O1xuIl19 \ No newline at end of file diff --git a/lib/Options/index.js b/lib/Options/index.js index 9a390c31f7..30b3ab85bb 100644 --- a/lib/Options/index.js +++ b/lib/Options/index.js @@ -1 +1,2 @@ -"use strict"; \ No newline at end of file +"use strict"; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbXX0= \ No newline at end of file diff --git a/lib/Options/parsers.js b/lib/Options/parsers.js index 4b93c680e9..ce52427c78 100644 --- a/lib/Options/parsers.js +++ b/lib/Options/parsers.js @@ -74,4 +74,5 @@ module.exports = { moduleOrObjectParser, arrayParser, objectParser -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PcHRpb25zL3BhcnNlcnMuanMiXSwibmFtZXMiOlsibnVtYmVyUGFyc2VyIiwia2V5Iiwib3B0IiwiaW50T3B0IiwicGFyc2VJbnQiLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJFcnJvciIsIm51bWJlck9yQm9vbFBhcnNlciIsIm9iamVjdFBhcnNlciIsIkpTT04iLCJwYXJzZSIsImFycmF5UGFyc2VyIiwiQXJyYXkiLCJpc0FycmF5Iiwic3BsaXQiLCJtb2R1bGVPck9iamVjdFBhcnNlciIsImUiLCJib29sZWFuUGFyc2VyIiwibnVsbFBhcnNlciIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUEsU0FBU0EsWUFBVCxDQUFzQkMsR0FBdEIsRUFBMkI7QUFDekIsU0FBTyxVQUFTQyxHQUFULEVBQWM7QUFDbkIsVUFBTUMsU0FBU0MsU0FBU0YsR0FBVCxDQUFmO0FBQ0EsUUFBSSxDQUFDRyxPQUFPQyxTQUFQLENBQWlCSCxNQUFqQixDQUFMLEVBQStCO0FBQzdCLFlBQU0sSUFBSUksS0FBSixDQUFXLE9BQU1OLEdBQUksc0JBQXFCQyxHQUFJLEVBQTlDLENBQU47QUFDRDtBQUNELFdBQU9DLE1BQVA7QUFDRCxHQU5EO0FBT0Q7O0FBRUQsU0FBU0ssa0JBQVQsQ0FBNEJQLEdBQTVCLEVBQWlDO0FBQy9CLFNBQU8sVUFBU0MsR0FBVCxFQUFjO0FBQ25CLFFBQUksT0FBT0EsR0FBUCxLQUFlLFNBQW5CLEVBQThCO0FBQzVCLGFBQU9BLEdBQVA7QUFDRDtBQUNELFFBQUlBLFFBQVEsTUFBWixFQUFvQjtBQUNsQixhQUFPLElBQVA7QUFDRDtBQUNELFFBQUlBLFFBQVEsT0FBWixFQUFxQjtBQUNuQixhQUFPLEtBQVA7QUFDRDtBQUNELFdBQU9GLGFBQWFDLEdBQWIsRUFBa0JDLEdBQWxCLENBQVA7QUFDRCxHQVhEO0FBWUQ7O0FBRUQsU0FBU08sWUFBVCxDQUFzQlAsR0FBdEIsRUFBMkI7QUFDekIsTUFBSSxPQUFPQSxHQUFQLElBQWMsUUFBbEIsRUFBNEI7QUFDMUIsV0FBT0EsR0FBUDtBQUNEO0FBQ0QsU0FBT1EsS0FBS0MsS0FBTCxDQUFXVCxHQUFYLENBQVA7QUFDRDs7QUFFRCxTQUFTVSxXQUFULENBQXFCVixHQUFyQixFQUEwQjtBQUN4QixNQUFJVyxNQUFNQyxPQUFOLENBQWNaLEdBQWQsQ0FBSixFQUF3QjtBQUN0QixXQUFPQSxHQUFQO0FBQ0QsR0FGRCxNQUVPLElBQUksT0FBT0EsR0FBUCxLQUFlLFFBQW5CLEVBQTZCO0FBQ2xDLFdBQU9BLElBQUlhLEtBQUosQ0FBVSxHQUFWLENBQVA7QUFDRCxHQUZNLE1BRUE7QUFDTCxVQUFNLElBQUlSLEtBQUosQ0FBVyxHQUFFTCxHQUFJLGlEQUFqQixDQUFOO0FBQ0Q7QUFDRjs7QUFFRCxTQUFTYyxvQkFBVCxDQUE4QmQsR0FBOUIsRUFBbUM7QUFDakMsTUFBSSxPQUFPQSxHQUFQLElBQWMsUUFBbEIsRUFBNkI7QUFDM0IsV0FBT0EsR0FBUDtBQUNEO0FBQ0QsTUFBSTtBQUNGLFdBQU9RLEtBQUtDLEtBQUwsQ0FBV1QsR0FBWCxDQUFQO0FBQ0QsR0FGRCxDQUVFLE9BQU1lLENBQU4sRUFBUyxDQUFFLEtBQU87QUFDcEIsU0FBT2YsR0FBUDtBQUNEOztBQUVELFNBQVNnQixhQUFULENBQXVCaEIsR0FBdkIsRUFBNEI7QUFDMUIsTUFBSUEsT0FBTyxJQUFQLElBQWVBLE9BQU8sTUFBdEIsSUFBZ0NBLE9BQU8sR0FBM0MsRUFBZ0Q7QUFDOUMsV0FBTyxJQUFQO0FBQ0Q7QUFDRCxTQUFPLEtBQVA7QUFDRDs7QUFFRCxTQUFTaUIsVUFBVCxDQUFvQmpCLEdBQXBCLEVBQXlCO0FBQ3ZCLE1BQUlBLE9BQU8sTUFBWCxFQUFtQjtBQUNqQixXQUFPLElBQVA7QUFDRDtBQUNELFNBQU9BLEdBQVA7QUFDRDs7QUFFRGtCLE9BQU9DLE9BQVAsR0FBaUI7QUFDZnJCLGNBRGU7QUFFZlEsb0JBRmU7QUFHZlcsWUFIZTtBQUlmRCxlQUplO0FBS2ZGLHNCQUxlO0FBTWZKLGFBTmU7QUFPZkg7QUFQZSxDQUFqQiIsImZpbGUiOiJwYXJzZXJzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gbnVtYmVyUGFyc2VyKGtleSkge1xuICByZXR1cm4gZnVuY3Rpb24ob3B0KSB7XG4gICAgY29uc3QgaW50T3B0ID0gcGFyc2VJbnQob3B0KTtcbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoaW50T3B0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBLZXkgJHtrZXl9IGhhcyBpbnZhbGlkIHZhbHVlICR7b3B0fWApO1xuICAgIH1cbiAgICByZXR1cm4gaW50T3B0O1xuICB9XG59XG5cbmZ1bmN0aW9uIG51bWJlck9yQm9vbFBhcnNlcihrZXkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKG9wdCkge1xuICAgIGlmICh0eXBlb2Ygb3B0ID09PSAnYm9vbGVhbicpIHtcbiAgICAgIHJldHVybiBvcHQ7XG4gICAgfVxuICAgIGlmIChvcHQgPT09ICd0cnVlJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChvcHQgPT09ICdmYWxzZScpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIG51bWJlclBhcnNlcihrZXkpKG9wdCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gb2JqZWN0UGFyc2VyKG9wdCkge1xuICBpZiAodHlwZW9mIG9wdCA9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBvcHQ7XG4gIH1cbiAgcmV0dXJuIEpTT04ucGFyc2Uob3B0KVxufVxuXG5mdW5jdGlvbiBhcnJheVBhcnNlcihvcHQpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob3B0KSkge1xuICAgIHJldHVybiBvcHQ7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG9wdCA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gb3B0LnNwbGl0KCcsJyk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke29wdH0gc2hvdWxkIGJlIGEgY29tbWEgc2VwYXJhdGVkIHN0cmluZyBvciBhbiBhcnJheWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1vZHVsZU9yT2JqZWN0UGFyc2VyKG9wdCkge1xuICBpZiAodHlwZW9mIG9wdCA9PSAnb2JqZWN0JykgIHtcbiAgICByZXR1cm4gb3B0O1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2Uob3B0KTtcbiAgfSBjYXRjaChlKSB7IC8qICovIH1cbiAgcmV0dXJuIG9wdDtcbn1cblxuZnVuY3Rpb24gYm9vbGVhblBhcnNlcihvcHQpIHtcbiAgaWYgKG9wdCA9PSB0cnVlIHx8IG9wdCA9PSAndHJ1ZScgfHwgb3B0ID09ICcxJykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gbnVsbFBhcnNlcihvcHQpIHtcbiAgaWYgKG9wdCA9PSAnbnVsbCcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4gb3B0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgbnVtYmVyUGFyc2VyLFxuICBudW1iZXJPckJvb2xQYXJzZXIsXG4gIG51bGxQYXJzZXIsXG4gIGJvb2xlYW5QYXJzZXIsXG4gIG1vZHVsZU9yT2JqZWN0UGFyc2VyLFxuICBhcnJheVBhcnNlcixcbiAgb2JqZWN0UGFyc2VyXG59O1xuIl19 \ No newline at end of file diff --git a/lib/ParseMessageQueue.js b/lib/ParseMessageQueue.js index 617324204d..23ecf7cb60 100644 --- a/lib/ParseMessageQueue.js +++ b/lib/ParseMessageQueue.js @@ -27,4 +27,5 @@ ParseMessageQueue.createSubscriber = function (config) { return adapter.createSubscriber(config); }; -exports.ParseMessageQueue = ParseMessageQueue; \ No newline at end of file +exports.ParseMessageQueue = ParseMessageQueue; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZU1lc3NhZ2VRdWV1ZS5qcyJdLCJuYW1lcyI6WyJQYXJzZU1lc3NhZ2VRdWV1ZSIsImNyZWF0ZVB1Ymxpc2hlciIsImNvbmZpZyIsImFkYXB0ZXIiLCJtZXNzYWdlUXVldWVBZGFwdGVyIiwiRXZlbnRFbWl0dGVyTVEiLCJjcmVhdGVTdWJzY3JpYmVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBSUEsTUFBTUEsb0JBQW9CLEVBQTFCOztBQUVBQSxrQkFBa0JDLGVBQWxCLEdBQW9DLFVBQVNDLE1BQVQsRUFBMkI7QUFDN0QsUUFBTUMsVUFBVSxnQ0FBWUQsT0FBT0UsbUJBQW5CLEVBQXdDQyw4QkFBeEMsRUFBd0RILE1BQXhELENBQWhCO0FBQ0EsTUFBSSxPQUFPQyxRQUFRRixlQUFmLEtBQW1DLFVBQXZDLEVBQW1EO0FBQ2pELFVBQU0sNkNBQU47QUFDRDtBQUNELFNBQU9FLFFBQVFGLGVBQVIsQ0FBd0JDLE1BQXhCLENBQVA7QUFDRCxDQU5EOztBQVFBRixrQkFBa0JNLGdCQUFsQixHQUFxQyxVQUFTSixNQUFULEVBQTRCO0FBQy9ELFFBQU1DLFVBQVUsZ0NBQVlELE9BQU9FLG1CQUFuQixFQUF3Q0MsOEJBQXhDLEVBQXdESCxNQUF4RCxDQUFoQjtBQUNBLE1BQUksT0FBT0MsUUFBUUcsZ0JBQWYsS0FBb0MsVUFBeEMsRUFBb0Q7QUFDbEQsVUFBTSxvREFBTjtBQUNEO0FBQ0QsU0FBT0gsUUFBUUcsZ0JBQVIsQ0FBeUJKLE1BQXpCLENBQVA7QUFDRCxDQU5EOztRQVNFRixpQixHQUFBQSxpQiIsImZpbGUiOiJQYXJzZU1lc3NhZ2VRdWV1ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGxvYWRBZGFwdGVyIH0gZnJvbSAnLi9BZGFwdGVycy9BZGFwdGVyTG9hZGVyJztcbmltcG9ydCB7XG4gIEV2ZW50RW1pdHRlck1RXG59IGZyb20gJy4vQWRhcHRlcnMvTWVzc2FnZVF1ZXVlL0V2ZW50RW1pdHRlck1RJztcblxuY29uc3QgUGFyc2VNZXNzYWdlUXVldWUgPSB7fTtcblxuUGFyc2VNZXNzYWdlUXVldWUuY3JlYXRlUHVibGlzaGVyID0gZnVuY3Rpb24oY29uZmlnOiBhbnkpOiBhbnkge1xuICBjb25zdCBhZGFwdGVyID0gbG9hZEFkYXB0ZXIoY29uZmlnLm1lc3NhZ2VRdWV1ZUFkYXB0ZXIsIEV2ZW50RW1pdHRlck1RLCBjb25maWcpO1xuICBpZiAodHlwZW9mIGFkYXB0ZXIuY3JlYXRlUHVibGlzaGVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgJ3B1YlN1YkFkYXB0ZXIgc2hvdWxkIGhhdmUgY3JlYXRlUHVibGlzaGVyKCknO1xuICB9XG4gIHJldHVybiBhZGFwdGVyLmNyZWF0ZVB1Ymxpc2hlcihjb25maWcpO1xufVxuXG5QYXJzZU1lc3NhZ2VRdWV1ZS5jcmVhdGVTdWJzY3JpYmVyID0gZnVuY3Rpb24oY29uZmlnOiBhbnkpOiB2b2lkIHtcbiAgY29uc3QgYWRhcHRlciA9IGxvYWRBZGFwdGVyKGNvbmZpZy5tZXNzYWdlUXVldWVBZGFwdGVyLCBFdmVudEVtaXR0ZXJNUSwgY29uZmlnKVxuICBpZiAodHlwZW9mIGFkYXB0ZXIuY3JlYXRlU3Vic2NyaWJlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93ICdtZXNzYWdlUXVldWVBZGFwdGVyIHNob3VsZCBoYXZlIGNyZWF0ZVN1YnNjcmliZXIoKSc7XG4gIH1cbiAgcmV0dXJuIGFkYXB0ZXIuY3JlYXRlU3Vic2NyaWJlcihjb25maWcpO1xufVxuXG5leHBvcnQge1xuICBQYXJzZU1lc3NhZ2VRdWV1ZVxufVxuIl19 \ No newline at end of file diff --git a/lib/ParseServer.js b/lib/ParseServer.js index 218a37f29c..0ad293d7c1 100644 --- a/lib/ParseServer.js +++ b/lib/ParseServer.js @@ -372,4 +372,5 @@ function configureListeners(parseServer) { process.on('SIGINT', handleShutdown); } -exports.default = ParseServer; \ No newline at end of file +exports.default = ParseServer; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZVNlcnZlci5qcyJdLCJuYW1lcyI6WyJsb2dnaW5nIiwiY29udHJvbGxlcnMiLCJiYXRjaCIsInJlcXVpcmUiLCJib2R5UGFyc2VyIiwiZXhwcmVzcyIsIm1pZGRsZXdhcmVzIiwiUGFyc2UiLCJwYXRoIiwiYWRkUGFyc2VDbG91ZCIsIlBhcnNlU2VydmVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwiaW5qZWN0RGVmYXVsdHMiLCJhcHBJZCIsIm1hc3RlcktleSIsImNsb3VkIiwiamF2YXNjcmlwdEtleSIsInNlcnZlclVSTCIsIl9faW5kZXhCdWlsZENvbXBsZXRpb25DYWxsYmFja0ZvclRlc3RzIiwiaW5pdGlhbGl6ZSIsImFsbENvbnRyb2xsZXJzIiwiZ2V0Q29udHJvbGxlcnMiLCJsb2dnZXJDb250cm9sbGVyIiwiZGF0YWJhc2VDb250cm9sbGVyIiwiaG9va3NDb250cm9sbGVyIiwiY29uZmlnIiwiQ29uZmlnIiwicHV0IiwiT2JqZWN0IiwiYXNzaWduIiwic2V0TG9nZ2VyIiwiZGJJbml0UHJvbWlzZSIsInBlcmZvcm1Jbml0aWFsaXphdGlvbiIsImxvYWQiLCJwcm9jZXNzIiwiZW52IiwiVEVTVElORyIsInJlc29sdmUiLCJjd2QiLCJhcHAiLCJfYXBwIiwiaGFuZGxlU2h1dGRvd24iLCJhZGFwdGVyIiwibWF4VXBsb2FkU2l6ZSIsImFwaSIsInVzZSIsImFsbG93Q3Jvc3NEb21haW4iLCJGaWxlc1JvdXRlciIsImV4cHJlc3NSb3V0ZXIiLCJyZXEiLCJyZXMiLCJqc29uIiwic3RhdHVzIiwidXJsZW5jb2RlZCIsImV4dGVuZGVkIiwiUHVibGljQVBJUm91dGVyIiwiSW1wb3J0Um91dGVyIiwibGltaXQiLCJhbGxvd01ldGhvZE92ZXJyaWRlIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwiYXBwUm91dGVyIiwicHJvbWlzZVJvdXRlciIsImhhbmRsZVBhcnNlRXJyb3JzIiwib24iLCJlcnIiLCJjb2RlIiwic3RkZXJyIiwid3JpdGUiLCJwb3J0IiwiZXhpdCIsInZlcmlmeVNlcnZlclVybCIsIlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MiLCJDb3JlTWFuYWdlciIsInNldFJFU1RDb250cm9sbGVyIiwicm91dGVycyIsIkNsYXNzZXNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsIlNlc3Npb25zUm91dGVyIiwiUm9sZXNSb3V0ZXIiLCJBbmFseXRpY3NSb3V0ZXIiLCJJbnN0YWxsYXRpb25zUm91dGVyIiwiRnVuY3Rpb25zUm91dGVyIiwiU2NoZW1hc1JvdXRlciIsIlB1c2hSb3V0ZXIiLCJMb2dzUm91dGVyIiwiSUFQVmFsaWRhdGlvblJvdXRlciIsIkZlYXR1cmVzUm91dGVyIiwiR2xvYmFsQ29uZmlnUm91dGVyIiwiUHVyZ2VSb3V0ZXIiLCJFeHBvcnRSb3V0ZXIiLCJIb29rc1JvdXRlciIsIkNsb3VkQ29kZVJvdXRlciIsIkF1ZGllbmNlc1JvdXRlciIsIkFnZ3JlZ2F0ZVJvdXRlciIsInJvdXRlcyIsInJlZHVjZSIsIm1lbW8iLCJyb3V0ZXIiLCJjb25jYXQiLCJQcm9taXNlUm91dGVyIiwibW91bnRPbnRvIiwic3RhcnQiLCJjYWxsYmFjayIsIm1pZGRsZXdhcmUiLCJtb3VudFBhdGgiLCJzZXJ2ZXIiLCJsaXN0ZW4iLCJob3N0Iiwic3RhcnRMaXZlUXVlcnlTZXJ2ZXIiLCJsaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIiwibGl2ZVF1ZXJ5U2VydmVyIiwiY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyIiwiY29uZmlndXJlTGlzdGVuZXJzIiwiZXhwcmVzc0FwcCIsInBhcnNlU2VydmVyIiwiaHR0cFNlcnZlciIsImNyZWF0ZVNlcnZlciIsIlBhcnNlTGl2ZVF1ZXJ5U2VydmVyIiwicmVxdWVzdCIsInJlcGxhY2UiLCJlcnJvciIsInJlc3BvbnNlIiwiYm9keSIsIkpTT04iLCJwYXJzZSIsImUiLCJzdGF0dXNDb2RlIiwiY29uc29sZSIsIndhcm4iLCJQYXJzZUNsb3VkIiwiQ2xvdWQiLCJnbG9iYWwiLCJrZXlzIiwiZGVmYXVsdHMiLCJmb3JFYWNoIiwia2V5IiwiaGFzT3duUHJvcGVydHkiLCJ1c2VyU2Vuc2l0aXZlRmllbGRzIiwiQXJyYXkiLCJmcm9tIiwiU2V0IiwibWFzdGVyS2V5SXBzIiwic29ja2V0cyIsInNvY2tldCIsInNvY2tldElkIiwicmVtb3RlQWRkcmVzcyIsInJlbW90ZVBvcnQiLCJkZXN0cm95QWxpdmVDb25uZWN0aW9ucyIsImRlc3Ryb3kiLCJzdGRvdXQiLCJjbG9zZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBU0E7O0FBRUE7Ozs7QUFDQTs7SUFBWUEsTzs7QUFDWjs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQTs7QUFDQTs7SUFBWUMsVzs7Ozs7O0FBekNaOztBQUVBLElBQUlDLFFBQVFDLFFBQVEsU0FBUixDQUFaO0FBQUEsSUFDRUMsYUFBYUQsUUFBUSxhQUFSLENBRGY7QUFBQSxJQUVFRSxVQUFVRixRQUFRLFNBQVIsQ0FGWjtBQUFBLElBR0VHLGNBQWNILFFBQVEsZUFBUixDQUhoQjtBQUFBLElBSUVJLFFBQVFKLFFBQVEsWUFBUixFQUFzQkksS0FKaEM7QUFBQSxJQUtFQyxPQUFPTCxRQUFRLE1BQVIsQ0FMVDs7QUF3Q0E7QUFDQU07O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxNQUFNQyxXQUFOLENBQWtCOztBQUVoQkMsY0FBWUMsT0FBWixFQUF5QztBQUN2Q0MsbUJBQWVELE9BQWY7QUFDQSxVQUFNO0FBQ0pFLGNBQVEsaUNB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YUFBTytFLFFBQVFFLFFBQVIsQ0FBUDtBQUNELEtBRkQ7QUFHRCxHQU5EOztBQVFBLFFBQU1HLDBCQUEwQixZQUFXO0FBQ3pDLFNBQUssTUFBTUgsUUFBWCxJQUF1QkYsT0FBdkIsRUFBZ0M7QUFDOUIsVUFBSTtBQUNGQSxnQkFBUUUsUUFBUixFQUFrQkksT0FBbEI7QUFDRCxPQUZELENBRUUsT0FBT3ZCLENBQVAsRUFBVSxDQUFFLEtBQU87QUFDdEI7QUFDRixHQU5EOztBQVFBLFFBQU1wRixpQkFBaUIsWUFBVztBQUNoQ1AsWUFBUW1ILE1BQVIsQ0FBZWxGLEtBQWYsQ0FBcUIsNkNBQXJCO0FBQ0FnRjtBQUNBMUMsV0FBTzZDLEtBQVA7QUFDQXBDLGdCQUFZekUsY0FBWjtBQUNELEdBTEQ7QUFNQVAsVUFBUTZCLEVBQVIsQ0FBVyxTQUFYLEVBQXNCdEIsY0FBdEI7QUFDQVAsVUFBUTZCLEVBQVIsQ0FBVyxRQUFYLEVBQXFCdEIsY0FBckI7QUFDRDs7a0JBRWNoQyxXIiwiZmlsZSI6IlBhcnNlU2VydmVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gUGFyc2VTZXJ2ZXIgLSBvcGVuLXNvdXJjZSBjb21wYXRpYmxlIEFQSSBTZXJ2ZXIgZm9yIFBhcnNlIGFwcHNcblxudmFyIGJhdGNoID0gcmVxdWlyZSgnLi9iYXRjaCcpLFxuICBib2R5UGFyc2VyID0gcmVxdWlyZSgnYm9keS1wYXJzZXInKSxcbiAgZXhwcmVzcyA9IHJlcXVpcmUoJ2V4cHJlc3MnKSxcbiAgbWlkZGxld2FyZXMgPSByZXF1aXJlKCcuL21pZGRsZXdhcmVzJyksXG4gIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlLFxuICBwYXRoID0gcmVxdWlyZSgncGF0aCcpO1xuXG5pbXBvcnQgeyBQYXJzZVNlcnZlck9wdGlvbnMsXG4gIExpdmVRdWVyeVNlcnZlck9wdGlvbnMgfSAgICAgIGZyb20gJy4vT3B0aW9ucyc7XG5pbXBvcnQgZGVmYXVsdHMgICAgICAgICAgICAgICAgIGZyb20gJy4vZGVmYXVsdHMnO1xuaW1wb3J0ICogYXMgbG9nZ2luZyAgICAgICAgICAgICBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgQ29uZmlnICAgICAgICAgICAgICAgICAgIGZyb20gJy4vQ29uZmlnJztcbmltcG9ydCBQcm9taXNlUm91dGVyICAgICAgICAgICAgZnJvbSAnLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCByZXF1aXJlZFBhcmFtZXRlciAgICAgICAgZnJvbSAnLi9yZXF1aXJlZFBhcmFtZXRlcic7XG5pbXBvcnQgeyBBbmFseXRpY3NSb3V0ZXIgfSAgICAgIGZyb20gJy4vUm91dGVycy9BbmFseXRpY3NSb3V0ZXInO1xuaW1wb3J0IHsgQ2xhc3Nlc1JvdXRlciB9ICAgICAgICBmcm9tICcuL1JvdXRlcnMvQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgeyBGZWF0dXJlc1JvdXRlciB9ICAgICAgIGZyb20gJy4vUm91dGVycy9GZWF0dXJlc1JvdXRlcic7XG5pbXBvcnQgeyBGaWxlc1JvdXRlciB9ICAgICAgICAgIGZyb20gJy4vUm91dGVycy9GaWxlc1JvdXRlcic7XG5pbXBvcnQgeyBGdW5jdGlvbnNSb3V0ZXIgfSAgICAgIGZyb20gJy4vUm91dGVycy9GdW5jdGlvbnNSb3V0ZXInO1xuaW1wb3J0IHsgR2xvYmFsQ29uZmlnUm91dGVyIH0gICBmcm9tICcuL1JvdXRlcnMvR2xvYmFsQ29uZmlnUm91dGVyJztcbmltcG9ydCB7IEhvb2tzUm91dGVyIH0gICAgICAgICAgZnJvbSAnLi9Sb3V0ZXJzL0hvb2tzUm91dGVyJztcbmltcG9ydCB7IElBUFZhbGlkYXRpb25Sb3V0ZXIgfSAgZnJvbSAnLi9Sb3V0ZXJzL0lBUFZhbGlkYXRpb25Sb3V0ZXInO1xuaW1wb3J0IHsgSW5zdGFsbGF0aW9uc1JvdXRlciB9ICBmcm9tICcuL1JvdXRlcnMvSW5zdGFsbGF0aW9uc1JvdXRlcic7XG5pbXBvcnQgeyBMb2dzUm91dGVyIH0gICAgICAgICAgIGZyb20gJy4vUm91dGVycy9Mb2dzUm91dGVyJztcbmltcG9ydCB7IFBhcnNlTGl2ZVF1ZXJ5U2VydmVyIH0gZnJvbSAnLi9MaXZlUXVlcnkvUGFyc2VMaXZlUXVlcnlTZXJ2ZXInO1xuaW1wb3J0IHsgUHVibGljQVBJUm91dGVyIH0gICAgICBmcm9tICcuL1JvdXRlcnMvUHVibGljQVBJUm91dGVyJztcbmltcG9ydCB7IFB1c2hSb3V0ZXIgfSAgICAgICAgICAgZnJvbSAnLi9Sb3V0ZXJzL1B1c2hSb3V0ZXInO1xuaW1wb3J0IHsgQ2xvdWRDb2RlUm91dGVyIH0gICAgICBmcm9tICcuL1JvdXRlcnMvQ2xvdWRDb2RlUm91dGVyJztcbmltcG9ydCB7IFJvbGVzUm91dGVyIH0gICAgICAgICAgZnJvbSAnLi9Sb3V0ZXJzL1JvbGVzUm91dGVyJztcbmltcG9ydCB7IFNjaGVtYXNSb3V0ZXIgfSAgICAgICAgZnJvbSAnLi9Sb3V0ZXJzL1NjaGVtYXNSb3V0ZXInO1xuaW1wb3J0IHsgU2Vzc2lvbnNSb3V0ZXIgfSAgICAgICBmcm9tICcuL1JvdXRlcnMvU2Vzc2lvbnNSb3V0ZXInO1xuaW1wb3J0IHsgVXNlcnNSb3V0ZXIgfSAgICAgICAgICBmcm9tICcuL1JvdXRlcnMvVXNlcnNSb3V0ZXInO1xuaW1wb3J0IHsgUHVyZ2VSb3V0ZXIgfSAgICAgICAgICBmcm9tICcuL1JvdXRlcnMvUHVyZ2VSb3V0ZXInO1xuaW1wb3J0IHsgQXVkaWVuY2VzUm91dGVyIH0gICAgICBmcm9tICcuL1JvdXRlcnMvQXVkaWVuY2VzUm91dGVyJztcbmltcG9ydCB7IEFnZ3JlZ2F0ZVJvdXRlciB9ICAgICAgZnJvbSAnLi9Sb3V0ZXJzL0FnZ3JlZ2F0ZVJvdXRlcic7XG5pbXBvcnQgeyBJbXBvcnRSb3V0ZXIgfSAgICAgIGZyb20gJy4vUm91dGVycy9JbXBvcnRSb3V0ZXInO1xuaW1wb3J0IHsgRXhwb3J0Um91dGVyIH0gICAgICBmcm9tICcuL1JvdXRlcnMvRXhwb3J0Um91dGVyJztcblxuaW1wb3J0IHsgUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlciB9IGZyb20gJy4vUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlcic7XG5pbXBvcnQgKiBhcyBjb250cm9sbGVycyBmcm9tICcuL0NvbnRyb2xsZXJzJztcbi8vIE11dGF0ZSB0aGUgUGFyc2Ugb2JqZWN0IHRvIGFkZCB0aGUgQ2xvdWQgQ29kZSBoYW5kbGVyc1xuYWRkUGFyc2VDbG91ZCgpO1xuXG4vLyBQYXJzZVNlcnZlciB3b3JrcyBsaWtlIGEgY29uc3RydWN0b3Igb2YgYW4gZXhwcmVzcyBhcHAuXG4vLyBUaGUgYXJncyB0aGF0IHdlIHVuZGVyc3RhbmQgYXJlOlxuLy8gXCJhbmFseXRpY3NBZGFwdGVyXCI6IGFuIGFkYXB0ZXIgY2xhc3MgZm9yIGFuYWx5dGljc1xuLy8gXCJmaWxlc0FkYXB0ZXJcIjogYSBjbGFzcyBsaWtlIEdyaWRTdG9yZUFkYXB0ZXIgcHJvdmlkaW5nIGNyZWF0ZSwgZ2V0LFxuLy8gICAgICAgICAgICAgICAgIGFuZCBkZWxldGVcbi8vIFwibG9nZ2VyQWRhcHRlclwiOiBhIGNsYXNzIGxpa2UgV2luc3RvbkxvZ2dlckFkYXB0ZXIgcHJvdmlkaW5nIGluZm8sIGVycm9yLFxuLy8gICAgICAgICAgICAgICAgIGFuZCBxdWVyeVxuLy8gXCJqc29uTG9nc1wiOiBsb2cgYXMgc3RydWN0dXJlZCBKU09OIG9iamVjdHNcbi8vIFwiZGF0YWJhc2VVUklcIjogYSB1cmkgbGlrZSBtb25nb2RiOi8vbG9jYWxob3N0OjI3MDE3L2RibmFtZSB0byB0ZWxsIHVzXG4vLyAgICAgICAgICB3aGF0IGRhdGFiYXNlIHRoaXMgUGFyc2UgQVBJIGNvbm5lY3RzIHRvLlxuLy8gXCJjbG91ZFwiOiByZWxhdGl2ZSBsb2NhdGlvbiB0byBjbG91ZCBjb2RlIHRvIHJlcXVpcmUsIG9yIGEgZnVuY3Rpb25cbi8vICAgICAgICAgIHRoYXQgaXMgZ2l2ZW4gYW4gaW5zdGFuY2Ugb2YgUGFyc2UgYXMgYSBwYXJhbWV0ZXIuICBVc2UgdGhpcyBpbnN0YW5jZSBvZiBQYXJzZVxuLy8gICAgICAgICAgdG8gcmVnaXN0ZXIgeW91ciBjbG91ZCBjb2RlIGhvb2tzIGFuZCBmdW5jdGlvbnMuXG4vLyBcImFwcElkXCI6IHRoZSBhcHBsaWNhdGlvbiBpZCB0byBob3N0XG4vLyBcIm1hc3RlcktleVwiOiB0aGUgbWFzdGVyIGtleSBmb3IgcmVxdWVzdHMgdG8gdGhpcyBhcHBcbi8vIFwiY29sbGVjdGlvblByZWZpeFwiOiBvcHRpb25hbCBwcmVmaXggZm9yIGRhdGFiYXNlIGNvbGxlY3Rpb24gbmFtZXNcbi8vIFwiZmlsZUtleVwiOiBvcHRpb25hbCBrZXkgZnJvbSBQYXJzZSBkYXNoYm9hcmQgZm9yIHN1cHBvcnRpbmcgb2xkZXIgZmlsZXNcbi8vICAgICAgICAgICAgaG9zdGVkIGJ5IFBhcnNlXG4vLyBcImNsaWVudEtleVwiOiBvcHRpb25hbCBrZXkgZnJvbSBQYXJzZSBkYXNoYm9hcmRcbi8vIFwiZG90TmV0S2V5XCI6IG9wdGlvbmFsIGtleSBmcm9tIFBhcnNlIGRhc2hib2FyZFxuLy8gXCJyZXN0QVBJS2V5XCI6IG9wdGlvbmFsIGtleSBmcm9tIFBhcnNlIGRhc2hib2FyZFxuLy8gXCJ3ZWJob29rS2V5XCI6IG9wdGlvbmFsIGtleSBmcm9tIFBhcnNlIGRhc2hib2FyZFxuLy8gXCJqYXZhc2NyaXB0S2V5XCI6IG9wdGlvbmFsIGtleSBmcm9tIFBhcnNlIGRhc2hib2FyZFxuLy8gXCJwdXNoXCI6IG9wdGlvbmFsIGtleSBmcm9tIGNvbmZpZ3VyZSBwdXNoXG4vLyBcInNlc3Npb25MZW5ndGhcIjogb3B0aW9uYWwgbGVuZ3RoIGluIHNlY29uZHMgZm9yIGhvdyBsb25nIFNlc3Npb25zIHNob3VsZCBiZSB2YWxpZCBmb3Jcbi8vIFwibWF4TGltaXRcIjogb3B0aW9uYWwgdXBwZXIgYm91bmQgZm9yIHdoYXQgY2FuIGJlIHNwZWNpZmllZCBmb3IgdGhlICdsaW1pdCcgcGFyYW1ldGVyIG9uIHF1ZXJpZXNcblxuY2xhc3MgUGFyc2VTZXJ2ZXIge1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICAgIGluamVjdERlZmF1bHRzKG9wdGlvbnMpO1xuICAgIGNvbnN0IHtcbiAgICAgIGFwcElkID0gcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYW4gYXBwSWQhJyksXG4gICAgICBtYXN0ZXJLZXkgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIG1hc3RlcktleSEnKSxcbiAgICAgIGNsb3VkLFxuICAgICAgamF2YXNjcmlwdEtleSxcbiAgICAgIHNlcnZlclVSTCA9IHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIGEgc2VydmVyVVJMIScpLFxuICAgICAgX19pbmRleEJ1aWxkQ29tcGxldGlvbkNhbGxiYWNrRm9yVGVzdHMgPSAoKSA9PiB7fSxcbiAgICB9ID0gb3B0aW9ucztcbiAgICAvLyBJbml0aWFsaXplIHRoZSBub2RlIGNsaWVudCBTREsgYXV0b21hdGljYWxseVxuICAgIFBhcnNlLmluaXRpYWxpemUoYXBwSWQsIGphdmFzY3JpcHRLZXkgfHwgJ3VudXNlZCcsIG1hc3RlcktleSk7XG4gICAgUGFyc2Uuc2VydmVyVVJMID0gc2VydmVyVVJMO1xuXG4gICAgY29uc3QgYWxsQ29udHJvbGxlcnMgPSBjb250cm9sbGVycy5nZXRDb250cm9sbGVycyhvcHRpb25zKTtcblxuICAgIGNvbnN0IHtcbiAgICAgIGxvZ2dlckNvbnRyb2xsZXIsXG4gICAgICBkYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgICBob29rc0NvbnRyb2xsZXIsXG4gICAgfSA9IGFsbENvbnRyb2xsZXJzO1xuICAgIHRoaXMuY29uZmlnID0gQ29uZmlnLnB1dChPYmplY3QuYXNzaWduKHt9LCBvcHRpb25zLCBhbGxDb250cm9sbGVycykpO1xuXG4gICAgbG9nZ2luZy5zZXRMb2dnZXIobG9nZ2VyQ29udHJvbGxlcik7XG4gICAgY29uc3QgZGJJbml0UHJvbWlzZSA9IGRhdGFiYXNlQ29udHJvbGxlci5wZXJmb3JtSW5pdGlhbGl6YXRpb24oKTtcbiAgICBob29rc0NvbnRyb2xsZXIubG9hZCgpO1xuXG4gICAgLy8gTm90ZTogVGVzdHMgd2lsbCBzdGFydCB0byBmYWlsIGlmIGFueSB2YWxpZGF0aW9uIGhhcHBlbnMgYWZ0ZXIgdGhpcyBpcyBjYWxsZWQuXG4gICAgaWYgKHByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICAgIF9faW5kZXhCdWlsZENvbXBsZXRpb25DYWxsYmFja0ZvclRlc3RzKGRiSW5pdFByb21pc2UpO1xuICAgIH1cblxuICAgIGlmIChjbG91ZCkge1xuICAgICAgYWRkUGFyc2VDbG91ZCgpO1xuICAgICAgaWYgKHR5cGVvZiBjbG91ZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjbG91ZChQYXJzZSlcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGNsb3VkID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXF1aXJlKHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCBjbG91ZCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgXCJhcmd1bWVudCAnY2xvdWQnIG11c3QgZWl0aGVyIGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb25cIjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXQgYXBwKCkge1xuICAgIGlmICghdGhpcy5fYXBwKSB7XG4gICAgICB0aGlzLl9hcHAgPSBQYXJzZVNlcnZlci5hcHAodGhpcy5jb25maWcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYXBwO1xuICB9XG5cbiAgaGFuZGxlU2h1dGRvd24oKSB7XG4gICAgY29uc3QgeyBhZGFwdGVyIH0gPSB0aGlzLmNvbmZpZy5kYXRhYmFzZUNvbnRyb2xsZXI7XG4gICAgaWYgKGFkYXB0ZXIgJiYgdHlwZW9mIGFkYXB0ZXIuaGFuZGxlU2h1dGRvd24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGFkYXB0ZXIuaGFuZGxlU2h1dGRvd24oKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgYXBwKHttYXhVcGxvYWRTaXplID0gJzIwbWInLCBhcHBJZH0pIHtcbiAgICAvLyBUaGlzIGFwcCBzZXJ2ZXMgdGhlIFBhcnNlIEFQSSBkaXJlY3RseS5cbiAgICAvLyBJdCdzIHRoZSBlcXVpdmFsZW50IG9mIGh0dHBzOi8vYXBpLnBhcnNlLmNvbS8xIGluIHRoZSBob3N0ZWQgUGFyc2UgQVBJLlxuICAgIHZhciBhcGkgPSBleHByZXNzKCk7XG4gICAgLy9hcGkudXNlKFwiL2FwcHNcIiwgZXhwcmVzcy5zdGF0aWMoX19kaXJuYW1lICsgXCIvcHVibGljXCIpKTtcbiAgICAvLyBGaWxlIGhhbmRsaW5nIG5lZWRzIHRvIGJlIGJlZm9yZSBkZWZhdWx0IG1pZGRsZXdhcmVzIGFyZSBhcHBsaWVkXG4gICAgYXBpLnVzZSgnLycsIG1pZGRsZXdhcmVzLmFsbG93Q3Jvc3NEb21haW4sIG5ldyBGaWxlc1JvdXRlcigpLmV4cHJlc3NSb3V0ZXIoe1xuICAgICAgbWF4VXBsb2FkU2l6ZTogbWF4VXBsb2FkU2l6ZVxuICAgIH0pKTtcblxuICAgIGFwaS51c2UoJy9oZWFsdGgnLCAoZnVuY3Rpb24ocmVxLCByZXMpIHtcbiAgICAgIHJlcy5qc29uKHtcbiAgICAgICAgc3RhdHVzOiAnb2snXG4gICAgICB9KTtcbiAgICB9KSk7XG5cbiAgICBhcGkudXNlKCcvJywgYm9keVBhcnNlci51cmxlbmNvZGVkKHtleHRlbmRlZDogZmFsc2V9KSwgbmV3IFB1YmxpY0FQSVJvdXRlcigpLmV4cHJlc3NSb3V0ZXIoKSk7XG5cbiAgICBhcGkudXNlKCcvJywgbWlkZGxld2FyZXMuYWxsb3dDcm9zc0RvbWFpbiwgbmV3IEltcG9ydFJvdXRlcigpLmV4cHJlc3NSb3V0ZXIoKSk7XG4gICAgYXBpLnVzZShib2R5UGFyc2VyLmpzb24oeyAndHlwZSc6ICcqLyonICwgbGltaXQ6IG1heFVwbG9hZFNpemUgfSkpO1xuICAgIGFwaS51c2UobWlkZGxld2FyZXMuYWxsb3dDcm9zc0RvbWFpbik7XG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5hbGxvd01ldGhvZE92ZXJyaWRlKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlSGVhZGVycyk7XG5cbiAgICBjb25zdCBhcHBSb3V0ZXIgPSBQYXJzZVNlcnZlci5wcm9taXNlUm91dGVyKHsgYXBwSWQgfSk7XG4gICAgYXBpLnVzZShhcHBSb3V0ZXIuZXhwcmVzc1JvdXRlcigpKTtcblxuICAgIGFwaS51c2UobWlkZGxld2FyZXMuaGFuZGxlUGFyc2VFcnJvcnMpO1xuXG4gICAgLy8gcnVuIHRoZSBmb2xsb3dpbmcgd2hlbiBub3QgdGVzdGluZ1xuICAgIGlmICghcHJvY2Vzcy5lbnYuVEVTVElORykge1xuICAgICAgLy9UaGlzIGNhdXNlcyB0ZXN0cyB0byBzcGV3IHNvbWUgdXNlbGVzcyB3YXJuaW5ncywgc28gZGlzYWJsZSBpbiB0ZXN0XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgcHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb24nLCAoZXJyKSA9PiB7XG4gICAgICAgIGlmIChlcnIuY29kZSA9PT0gXCJFQUREUklOVVNFXCIpIHsgLy8gdXNlci1mcmllbmRseSBtZXNzYWdlIGZvciB0aGlzIGNvbW1vbiBlcnJvclxuICAgICAgICAgIHByb2Nlc3Muc3RkZXJyLndyaXRlKGBVbmFibGUgdG8gbGlzdGVuIG9uIHBvcnQgJHtlcnIucG9ydH0uIFRoZSBwb3J0IGlzIGFscmVhZHkgaW4gdXNlLmApO1xuICAgICAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgLy8gdmVyaWZ5IHRoZSBzZXJ2ZXIgdXJsIGFmdGVyIGEgJ21vdW50JyBldmVudCBpcyByZWNlaXZlZFxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIGFwaS5vbignbW91bnQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgUGFyc2VTZXJ2ZXIudmVyaWZ5U2VydmVyVXJsKCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHByb2Nlc3MuZW52LlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MgPT09ICcxJykge1xuICAgICAgUGFyc2UuQ29yZU1hbmFnZXIuc2V0UkVTVENvbnRyb2xsZXIoUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlcihhcHBJZCwgYXBwUm91dGVyKSk7XG4gICAgfVxuICAgIHJldHVybiBhcGk7XG4gIH1cblxuICBzdGF0aWMgcHJvbWlzZVJvdXRlcih7YXBwSWR9KSB7XG4gICAgY29uc3Qgcm91dGVycyA9IFtcbiAgICAgIG5ldyBDbGFzc2VzUm91dGVyKCksXG4gICAgICBuZXcgVXNlcnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBTZXNzaW9uc1JvdXRlcigpLFxuICAgICAgbmV3IFJvbGVzUm91dGVyKCksXG4gICAgICBuZXcgQW5hbHl0aWNzUm91dGVyKCksXG4gICAgICBuZXcgSW5zdGFsbGF0aW9uc1JvdXRlcigpLFxuICAgICAgbmV3IEZ1bmN0aW9uc1JvdXRlcigpLFxuICAgICAgbmV3IFNjaGVtYXNSb3V0ZXIoKSxcbiAgICAgIG5ldyBQdXNoUm91dGVyKCksXG4gICAgICBuZXcgTG9nc1JvdXRlcigpLFxuICAgICAgbmV3IElBUFZhbGlkYXRpb25Sb3V0ZXIoKSxcbiAgICAgIG5ldyBGZWF0dXJlc1JvdXRlcigpLFxuICAgICAgbmV3IEdsb2JhbENvbmZpZ1JvdXRlcigpLFxuICAgICAgbmV3IFB1cmdlUm91dGVyKCksXG4gICAgICBuZXcgRXhwb3J0Um91dGVyKCksXG4gICAgICBuZXcgSG9va3NSb3V0ZXIoKSxcbiAgICAgIG5ldyBDbG91ZENvZGVSb3V0ZXIoKSxcbiAgICAgIG5ldyBBdWRpZW5jZXNSb3V0ZXIoKSxcbiAgICAgIG5ldyBBZ2dyZWdhdGVSb3V0ZXIoKVxuICAgIF07XG5cbiAgICBjb25zdCByb3V0ZXMgPSByb3V0ZXJzLnJlZHVjZSgobWVtbywgcm91dGVyKSA9PiB7XG4gICAgICByZXR1cm4gbWVtby5jb25jYXQocm91dGVyLnJvdXRlcyk7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3QgYXBwUm91dGVyID0gbmV3IFByb21pc2VSb3V0ZXIocm91dGVzLCBhcHBJZCk7XG5cbiAgICBiYXRjaC5tb3VudE9udG8oYXBwUm91dGVyKTtcbiAgICByZXR1cm4gYXBwUm91dGVyO1xuICB9XG5cbiAgc3RhcnQob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zLCBjYWxsYmFjazogPygpPT52b2lkKSB7XG4gICAgY29uc3QgYXBwID0gZXhwcmVzcygpO1xuICAgIGlmIChvcHRpb25zLm1pZGRsZXdhcmUpIHtcbiAgICAgIGxldCBtaWRkbGV3YXJlO1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLm1pZGRsZXdhcmUgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgbWlkZGxld2FyZSA9IHJlcXVpcmUocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIG9wdGlvbnMubWlkZGxld2FyZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWlkZGxld2FyZSA9IG9wdGlvbnMubWlkZGxld2FyZTsgLy8gdXNlIGFzLWlzIGxldCBleHByZXNzIGZhaWxcbiAgICAgIH1cbiAgICAgIGFwcC51c2UobWlkZGxld2FyZSk7XG4gICAgfVxuXG4gICAgYXBwLnVzZShvcHRpb25zLm1vdW50UGF0aCwgdGhpcy5hcHApO1xuICAgIGNvbnN0IHNlcnZlciA9IGFwcC5saXN0ZW4ob3B0aW9ucy5wb3J0LCBvcHRpb25zLmhvc3QsIGNhbGxiYWNrKTtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcblxuICAgIGlmIChvcHRpb25zLnN0YXJ0TGl2ZVF1ZXJ5U2VydmVyIHx8IG9wdGlvbnMubGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucykge1xuICAgICAgdGhpcy5saXZlUXVlcnlTZXJ2ZXIgPSBQYXJzZVNlcnZlci5jcmVhdGVMaXZlUXVlcnlTZXJ2ZXIoc2VydmVyLCBvcHRpb25zLmxpdmVRdWVyeVNlcnZlck9wdGlvbnMpO1xuICAgIH1cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICghcHJvY2Vzcy5lbnYuVEVTVElORykge1xuICAgICAgY29uZmlndXJlTGlzdGVuZXJzKHRoaXMpO1xuICAgIH1cbiAgICB0aGlzLmV4cHJlc3NBcHAgPSBhcHA7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzdGF0aWMgc3RhcnQob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zLCBjYWxsYmFjazogPygpPT52b2lkKSB7XG4gICAgY29uc3QgcGFyc2VTZXJ2ZXIgPSBuZXcgUGFyc2VTZXJ2ZXIob3B0aW9ucyk7XG4gICAgcmV0dXJuIHBhcnNlU2VydmVyLnN0YXJ0KG9wdGlvbnMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVMaXZlUXVlcnlTZXJ2ZXIoaHR0cFNlcnZlciwgY29uZmlnOiBMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zKSB7XG4gICAgaWYgKCFodHRwU2VydmVyIHx8IChjb25maWcgJiYgY29uZmlnLnBvcnQpKSB7XG4gICAgICB2YXIgYXBwID0gZXhwcmVzcygpO1xuICAgICAgaHR0cFNlcnZlciA9IHJlcXVpcmUoJ2h0dHAnKS5jcmVhdGVTZXJ2ZXIoYXBwKTtcbiAgICAgIGh0dHBTZXJ2ZXIubGlzdGVuKGNvbmZpZy5wb3J0KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBQYXJzZUxpdmVRdWVyeVNlcnZlcihodHRwU2VydmVyLCBjb25maWcpO1xuICB9XG5cbiAgc3RhdGljIHZlcmlmeVNlcnZlclVybChjYWxsYmFjaykge1xuICAgIC8vIHBlcmZvcm0gYSBoZWFsdGggY2hlY2sgb24gdGhlIHNlcnZlclVSTCB2YWx1ZVxuICAgIGlmKFBhcnNlLnNlcnZlclVSTCkge1xuICAgICAgY29uc3QgcmVxdWVzdCA9IHJlcXVpcmUoJ3JlcXVlc3QnKTtcbiAgICAgIHJlcXVlc3QoUGFyc2Uuc2VydmVyVVJMLnJlcGxhY2UoL1xcLyQvLCBcIlwiKSArIFwiL2hlYWx0aFwiLCBmdW5jdGlvbiAoZXJyb3IsIHJlc3BvbnNlLCBib2R5KSB7XG4gICAgICAgIGxldCBqc29uO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGpzb24gPSBKU09OLnBhcnNlKGJvZHkpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICBqc29uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXJyb3IgfHwgcmVzcG9uc2Uuc3RhdHVzQ29kZSAhPT0gMjAwIHx8ICFqc29uIHx8IGpzb24gJiYganNvbi5zdGF0dXMgIT09ICdvaycpIHtcbiAgICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgICAgY29uc29sZS53YXJuKGBcXG5XQVJOSU5HLCBVbmFibGUgdG8gY29ubmVjdCB0byAnJHtQYXJzZS5zZXJ2ZXJVUkx9Jy5gICtcbiAgICAgICAgICAgIGAgQ2xvdWQgY29kZSBhbmQgcHVzaCBub3RpZmljYXRpb25zIG1heSBiZSB1bmF2YWlsYWJsZSFcXG5gKTtcbiAgICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi9cbiAgICAgICAgICBpZihjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZihjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJ1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gYWRkUGFyc2VDbG91ZCgpIHtcbiAgY29uc3QgUGFyc2VDbG91ZCA9IHJlcXVpcmUoXCIuL2Nsb3VkLWNvZGUvUGFyc2UuQ2xvdWRcIik7XG4gIE9iamVjdC5hc3NpZ24oUGFyc2UuQ2xvdWQsIFBhcnNlQ2xvdWQpO1xuICBnbG9iYWwuUGFyc2UgPSBQYXJzZTtcbn1cblxuZnVuY3Rpb24gaW5qZWN0RGVmYXVsdHMob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKSB7XG4gIE9iamVjdC5rZXlzKGRlZmF1bHRzKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICBpZiAoIW9wdGlvbnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgb3B0aW9uc1trZXldID0gZGVmYXVsdHNba2V5XTtcbiAgICB9XG4gIH0pO1xuXG4gIGlmICghb3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnc2VydmVyVVJMJykpIHtcbiAgICBvcHRpb25zLnNlcnZlclVSTCA9IGBodHRwOi8vbG9jYWxob3N0OiR7b3B0aW9ucy5wb3J0fSR7b3B0aW9ucy5tb3VudFBhdGh9YDtcbiAgfVxuXG4gIG9wdGlvbnMudXNlclNlbnNpdGl2ZUZpZWxkcyA9IEFycmF5LmZyb20obmV3IFNldChvcHRpb25zLnVzZXJTZW5zaXRpdmVGaWVsZHMuY29uY2F0KFxuICAgIGRlZmF1bHRzLnVzZXJTZW5zaXRpdmVGaWVsZHMsXG4gICAgb3B0aW9ucy51c2VyU2Vuc2l0aXZlRmllbGRzXG4gICkpKTtcblxuICBvcHRpb25zLm1hc3RlcktleUlwcyA9IEFycmF5LmZyb20obmV3IFNldChvcHRpb25zLm1hc3RlcktleUlwcy5jb25jYXQoXG4gICAgZGVmYXVsdHMubWFzdGVyS2V5SXBzLFxuICAgIG9wdGlvbnMubWFzdGVyS2V5SXBzXG4gICkpKTtcbn1cblxuLy8gVGhvc2UgY2FuJ3QgYmUgdGVzdGVkIGFzIGl0IHJlcXVpcmVzIGEgc3VicHJvY2Vzc1xuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyZUxpc3RlbmVycyhwYXJzZVNlcnZlcikge1xuICBjb25zdCBzZXJ2ZXIgPSBwYXJzZVNlcnZlci5zZXJ2ZXI7XG4gIGNvbnN0IHNvY2tldHMgPSB7fTtcbiAgLyogQ3VycmVudGx5LCBleHByZXNzIGRvZXNuJ3Qgc2h1dCBkb3duIGltbWVkaWF0ZWx5IGFmdGVyIHJlY2VpdmluZyBTSUdJTlQvU0lHVEVSTSBpZiBpdCBoYXMgY2xpZW50IGNvbm5lY3Rpb25zIHRoYXQgaGF2ZW4ndCB0aW1lZCBvdXQuIChUaGlzIGlzIGEga25vd24gaXNzdWUgd2l0aCBub2RlIC0gaHR0cHM6Ly9naXRodWIuY29tL25vZGVqcy9ub2RlL2lzc3Vlcy8yNjQyKVxuICAgIFRoaXMgZnVuY3Rpb24sIGFsb25nIHdpdGggYGRlc3Ryb3lBbGl2ZUNvbm5lY3Rpb25zKClgLCBpbnRlbmQgdG8gZml4IHRoaXMgYmVoYXZpb3Igc3VjaCB0aGF0IHBhcnNlIHNlcnZlciB3aWxsIGNsb3NlIGFsbCBvcGVuIGNvbm5lY3Rpb25zIGFuZCBpbml0aWF0ZSB0aGUgc2h1dGRvd24gcHJvY2VzcyBhcyBzb29uIGFzIGl0IHJlY2VpdmVzIGEgU0lHSU5UL1NJR1RFUk0gc2lnbmFsLiAqL1xuICBzZXJ2ZXIub24oJ2Nvbm5lY3Rpb24nLCAoc29ja2V0KSA9PiB7XG4gICAgY29uc3Qgc29ja2V0SWQgPSBzb2NrZXQucmVtb3RlQWRkcmVzcyArICc6JyArIHNvY2tldC5yZW1vdGVQb3J0O1xuICAgIHNvY2tldHNbc29ja2V0SWRdID0gc29ja2V0O1xuICAgIHNvY2tldC5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICBkZWxldGUgc29ja2V0c1tzb2NrZXRJZF07XG4gICAgfSk7XG4gIH0pO1xuXG4gIGNvbnN0IGRlc3Ryb3lBbGl2ZUNvbm5lY3Rpb25zID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yIChjb25zdCBzb2NrZXRJZCBpbiBzb2NrZXRzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBzb2NrZXRzW3NvY2tldElkXS5kZXN0cm95KCk7XG4gICAgICB9IGNhdGNoIChlKSB7IC8qICovIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBoYW5kbGVTaHV0ZG93biA9IGZ1bmN0aW9uKCkge1xuICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKCdUZXJtaW5hdGlvbiBzaWduYWwgcmVjZWl2ZWQuIFNodXR0aW5nIGRvd24uJyk7XG4gICAgZGVzdHJveUFsaXZlQ29ubmVjdGlvbnMoKTtcbiAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICBwYXJzZVNlcnZlci5oYW5kbGVTaHV0ZG93bigpO1xuICB9O1xuICBwcm9jZXNzLm9uKCdTSUdURVJNJywgaGFuZGxlU2h1dGRvd24pO1xuICBwcm9jZXNzLm9uKCdTSUdJTlQnLCBoYW5kbGVTaHV0ZG93bik7XG59XG5cbmV4cG9ydCBkZWZhdWx0IFBhcnNlU2VydmVyO1xuIl19 \ No newline at end of file diff --git a/lib/ParseServerRESTController.js b/lib/ParseServerRESTController.js index 2ae687a32a..227a3d3ff0 100644 --- a/lib/ParseServerRESTController.js +++ b/lib/ParseServerRESTController.js @@ -100,4 +100,5 @@ function ParseServerRESTController(applicationId, router) { } exports.default = ParseServerRESTController; -exports.ParseServerRESTController = ParseServerRESTController; \ No newline at end of file +exports.ParseServerRESTController = ParseServerRESTController; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZVNlcnZlclJFU1RDb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbIkNvbmZpZyIsInJlcXVpcmUiLCJBdXRoIiwiUkVTVENvbnRyb2xsZXIiLCJVUkwiLCJQYXJzZSIsImdldFNlc3Npb25Ub2tlbiIsIm9wdGlvbnMiLCJzZXNzaW9uVG9rZW4iLCJQcm9taXNlIiwiYXMiLCJnZXRBdXRoIiwiY29uZmlnIiwiaW5zdGFsbGF0aW9uSWQiLCJ1c2VNYXN0ZXJLZXkiLCJpc01hc3RlciIsInRoZW4iLCJnZXRBdXRoRm9yU2Vzc2lvblRva2VuIiwiUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlciIsImFwcGxpY2F0aW9uSWQiLCJyb3V0ZXIiLCJoYW5kbGVSZXF1ZXN0IiwibWV0aG9kIiwicGF0aCIsImRhdGEiLCJhcmdzIiwiYXJndW1lbnRzIiwiZ2V0Iiwic2VydmVyVVJMIiwicGFyc2UiLCJpbmRleE9mIiwic2xpY2UiLCJsZW5ndGgiLCJwcm9taXNlcyIsInJlcXVlc3RzIiwibWFwIiwicmVxdWVzdCIsImJvZHkiLCJyZXNwb25zZSIsInN1Y2Nlc3MiLCJlcnJvciIsImNvZGUiLCJtZXNzYWdlIiwiYWxsIiwicXVlcnkiLCJyZXNvbHZlIiwicmVqZWN0IiwiYXV0aCIsImluZm8iLCJ0cnlSb3V0ZVJlcXVlc3QiLCJzdGF0dXMiLCJlcnIiLCJFcnJvciIsIklOVkFMSURfSlNPTiIsImFwcGx5IiwiYWpheCJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxNQUFNQSxTQUFTQyxRQUFRLFVBQVIsQ0FBZjtBQUNBLE1BQU1DLE9BQU9ELFFBQVEsUUFBUixDQUFiO0FBQ0EsTUFBTUUsaUJBQWlCRixRQUFRLCtCQUFSLENBQXZCO0FBQ0EsTUFBTUcsTUFBTUgsUUFBUSxLQUFSLENBQVo7QUFDQSxNQUFNSSxRQUFRSixRQUFRLFlBQVIsQ0FBZDs7QUFFQSxTQUFTSyxlQUFULENBQXlCQyxPQUF6QixFQUFrQztBQUNoQyxNQUFJQSxXQUFXLE9BQU9BLFFBQVFDLFlBQWYsS0FBZ0MsUUFBL0MsRUFBeUQ7QUFDdkQsV0FBT0gsTUFBTUksT0FBTixDQUFjQyxFQUFkLENBQWlCSCxRQUFRQyxZQUF6QixDQUFQO0FBQ0Q7QUFDRCxTQUFPSCxNQUFNSSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsSUFBakIsQ0FBUDtBQUNEOztBQUVELFNBQVNDLE9BQVQsQ0FBaUJKLFVBQVUsRUFBM0IsRUFBK0JLLE1BQS9CLEVBQXVDO0FBQ3JDLFFBQU1DLGlCQUFpQk4sUUFBUU0sY0FBUixJQUEwQixPQUFqRDtBQUNBLE1BQUlOLFFBQVFPLFlBQVosRUFBMEI7QUFDeEIsV0FBT1QsTUFBTUksT0FBTixDQUFjQyxFQUFkLENBQWlCLElBQUlSLEtBQUtBLElBQVQsQ0FBYyxFQUFDVSxNQUFELEVBQVNHLFVBQVUsSUFBbkIsRUFBeUJGLGNBQXpCLEVBQWQsQ0FBakIsQ0FBUDtBQUNEO0FBQ0QsU0FBT1AsZ0JBQWdCQyxPQUFoQixFQUF5QlMsSUFBekIsQ0FBK0JSLFlBQUQsSUFBa0I7QUFDckQsUUFBSUEsWUFBSixFQUFrQjtBQUNoQkQsY0FBUUMsWUFBUixHQUF1QkEsWUFBdkI7QUFDQSxhQUFPTixLQUFLZSxzQkFBTCxDQUE0QjtBQUNqQ0wsY0FEaUM7QUFFakNKLHNCQUFjQSxZQUZtQjtBQUdqQ0s7QUFIaUMsT0FBNUIsQ0FBUDtBQUtELEtBUEQsTUFPTztBQUNMLGFBQU9SLE1BQU1JLE9BQU4sQ0FBY0MsRUFBZCxDQUFpQixJQUFJUixLQUFLQSxJQUFULENBQWMsRUFBRVUsTUFBRixFQUFVQyxjQUFWLEVBQWQsQ0FBakIsQ0FBUDtBQUNEO0FBQ0YsR0FYTSxDQUFQO0FBWUQ7O0FBRUQsU0FBU0sseUJBQVQsQ0FBbUNDLGFBQW5DLEVBQWtEQyxNQUFsRCxFQUEwRDtBQUN4RCxXQUFTQyxhQUFULENBQXVCQyxNQUF2QixFQUErQkMsSUFBL0IsRUFBcUNDLE9BQU8sRUFBNUMsRUFBZ0RqQixVQUFVLEVBQTFELEVBQThEO0FBQzVEO0FBQ0EsVUFBTWtCLE9BQU9DLFNBQWI7O0FBRUEsVUFBTWQsU0FBU1osT0FBTzJCLEdBQVAsQ0FBV1IsYUFBWCxDQUFmO0FBQ0EsVUFBTVMsWUFBWXhCLElBQUl5QixLQUFKLENBQVVqQixPQUFPZ0IsU0FBakIsQ0FBbEI7QUFDQSxRQUFJTCxLQUFLTyxPQUFMLENBQWFGLFVBQVVMLElBQXZCLE1BQWlDLENBQXJDLEVBQXdDO0FBQ3RDQSxhQUFPQSxLQUFLUSxLQUFMLENBQVdILFVBQVVMLElBQVYsQ0FBZVMsTUFBMUIsRUFBa0NULEtBQUtTLE1BQXZDLENBQVA7QUFDRDs7QUFFRCxRQUFJVCxLQUFLLENBQUwsTUFBWSxHQUFoQixFQUFxQjtBQUNuQkEsYUFBTyxNQUFNQSxJQUFiO0FBQ0Q7O0FBRUQsUUFBSUEsU0FBUyxRQUFiLEVBQXVCO0FBQ3JCLFlBQU1VLFdBQVdULEtBQUtVLFFBQUwsQ0FBY0MsR0FBZCxDQUFtQkMsT0FBRCxJQUFhO0FBQzlDLGVBQU9mLGNBQWNlLFFBQVFkLE1BQXRCLEVBQThCYyxRQUFRYixJQUF0QyxFQUE0Q2EsUUFBUUMsSUFBcEQsRUFBMEQ5QixPQUExRCxFQUFtRVMsSUFBbkUsQ0FBeUVzQixRQUFELElBQWM7QUFDM0YsaUJBQU9qQyxNQUFNSSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsRUFBQzZCLFNBQVNELFFBQVYsRUFBakIsQ0FBUDtBQUNELFNBRk0sRUFFSEUsS0FBRCxJQUFXO0FBQ1osaUJBQU9uQyxNQUFNSSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsRUFBQzhCLE9BQU8sRUFBQ0MsTUFBTUQsTUFBTUMsSUFBYixFQUFtQkQsT0FBT0EsTUFBTUUsT0FBaEMsRUFBUixFQUFqQixDQUFQO0FBQ0QsU0FKTSxDQUFQO0FBS0QsT0FOZ0IsQ0FBakI7QUFPQSxhQUFPckMsTUFBTUksT0FBTixDQUFja0MsR0FBZCxDQUFrQlYsUUFBbEIsQ0FBUDtBQUNEOztBQUVELFFBQUlXLEtBQUo7QUFDQSxRQUFJdEIsV0FBVyxLQUFmLEVBQXNCO0FBQ3BCc0IsY0FBUXBCLElBQVI7QUFDRDs7QUFFRCxXQUFPLElBQUluQixNQUFNSSxPQUFWLENBQWtCLENBQUNvQyxPQUFELEVBQVVDLE1BQVYsS0FBcUI7QUFDNUNuQyxjQUFRSixPQUFSLEVBQWlCSyxNQUFqQixFQUF5QkksSUFBekIsQ0FBK0IrQixJQUFELElBQVU7QUFDdEMsY0FBTVgsVUFBVTtBQUNkQyxnQkFBTWIsSUFEUTtBQUVkWixnQkFGYztBQUdkbUMsY0FIYztBQUlkQyxnQkFBTTtBQUNKN0IsMkJBQWVBLGFBRFg7QUFFSlgsMEJBQWNELFFBQVFDO0FBRmxCLFdBSlE7QUFRZG9DO0FBUmMsU0FBaEI7QUFVQSxlQUFPbkMsUUFBUW9DLE9BQVIsR0FBa0I3QixJQUFsQixDQUF1QixNQUFNO0FBQ2xDLGlCQUFPSSxPQUFPNkIsZUFBUCxDQUF1QjNCLE1BQXZCLEVBQStCQyxJQUEvQixFQUFxQ2EsT0FBckMsQ0FBUDtBQUNELFNBRk0sRUFFSnBCLElBRkksQ0FFRXNCLFFBQUQsSUFBYztBQUNwQk8sa0JBQVFQLFNBQVNBLFFBQWpCLEVBQTJCQSxTQUFTWSxNQUFwQyxFQUE0Q1osUUFBNUM7QUFDRCxTQUpNLEVBSUhhLEdBQUQsSUFBUztBQUNWLGNBQUlBLGVBQWU5QyxNQUFNK0MsS0FBckIsSUFDQUQsSUFBSVYsSUFBSixJQUFZcEMsTUFBTStDLEtBQU4sQ0FBWUMsWUFEeEIsSUFFQUYsSUFBSVQsT0FBSixJQUFnQixnQkFBZXBCLE1BQU8sSUFBR0MsSUFBSyxFQUZsRCxFQUVxRDtBQUNuRHBCLDJCQUFlaUMsT0FBZixDQUF1QmtCLEtBQXZCLENBQTZCLElBQTdCLEVBQW1DN0IsSUFBbkMsRUFBeUNULElBQXpDLENBQThDNkIsT0FBOUMsRUFBdURDLE1BQXZEO0FBQ0QsV0FKRCxNQUlPO0FBQ0xBLG1CQUFPSyxHQUFQO0FBQ0Q7QUFDRixTQVpNLENBQVA7QUFhRCxPQXhCRCxFQXdCR0wsTUF4Qkg7QUF5QkQsS0ExQk0sQ0FBUDtBQTJCRDs7QUFFRCxTQUFRO0FBQ05WLGFBQVNmLGFBREg7QUFFTmtDLFVBQU1wRCxlQUFlb0Q7QUFGZixHQUFSO0FBSUQ7O2tCQUVjckMseUI7UUFDTkEseUIsR0FBQUEseUIiLCJmaWxlIjoiUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IENvbmZpZyA9IHJlcXVpcmUoJy4vQ29uZmlnJyk7XG5jb25zdCBBdXRoID0gcmVxdWlyZSgnLi9BdXRoJyk7XG5jb25zdCBSRVNUQ29udHJvbGxlciA9IHJlcXVpcmUoJ3BhcnNlL2xpYi9ub2RlL1JFU1RDb250cm9sbGVyJyk7XG5jb25zdCBVUkwgPSByZXF1aXJlKCd1cmwnKTtcbmNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpO1xuXG5mdW5jdGlvbiBnZXRTZXNzaW9uVG9rZW4ob3B0aW9ucykge1xuICBpZiAob3B0aW9ucyAmJiB0eXBlb2Ygb3B0aW9ucy5zZXNzaW9uVG9rZW4gPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIFBhcnNlLlByb21pc2UuYXMob3B0aW9ucy5zZXNzaW9uVG9rZW4pO1xuICB9XG4gIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKG51bGwpO1xufVxuXG5mdW5jdGlvbiBnZXRBdXRoKG9wdGlvbnMgPSB7fSwgY29uZmlnKSB7XG4gIGNvbnN0IGluc3RhbGxhdGlvbklkID0gb3B0aW9ucy5pbnN0YWxsYXRpb25JZCB8fCAnY2xvdWQnO1xuICBpZiAob3B0aW9ucy51c2VNYXN0ZXJLZXkpIHtcbiAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyhuZXcgQXV0aC5BdXRoKHtjb25maWcsIGlzTWFzdGVyOiB0cnVlLCBpbnN0YWxsYXRpb25JZCB9KSk7XG4gIH1cbiAgcmV0dXJuIGdldFNlc3Npb25Ub2tlbihvcHRpb25zKS50aGVuKChzZXNzaW9uVG9rZW4pID0+IHtcbiAgICBpZiAoc2Vzc2lvblRva2VuKSB7XG4gICAgICBvcHRpb25zLnNlc3Npb25Ub2tlbiA9IHNlc3Npb25Ub2tlbjtcbiAgICAgIHJldHVybiBBdXRoLmdldEF1dGhGb3JTZXNzaW9uVG9rZW4oe1xuICAgICAgICBjb25maWcsXG4gICAgICAgIHNlc3Npb25Ub2tlbjogc2Vzc2lvblRva2VuLFxuICAgICAgICBpbnN0YWxsYXRpb25JZFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKG5ldyBBdXRoLkF1dGgoeyBjb25maWcsIGluc3RhbGxhdGlvbklkIH0pKTtcbiAgICB9XG4gIH0pXG59XG5cbmZ1bmN0aW9uIFBhcnNlU2VydmVyUkVTVENvbnRyb2xsZXIoYXBwbGljYXRpb25JZCwgcm91dGVyKSB7XG4gIGZ1bmN0aW9uIGhhbmRsZVJlcXVlc3QobWV0aG9kLCBwYXRoLCBkYXRhID0ge30sIG9wdGlvbnMgPSB7fSkge1xuICAgIC8vIFN0b3JlIHRoZSBhcmd1bWVudHMsIGZvciBsYXRlciB1c2UgaWYgaW50ZXJuYWwgZmFpbHNcbiAgICBjb25zdCBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChhcHBsaWNhdGlvbklkKTtcbiAgICBjb25zdCBzZXJ2ZXJVUkwgPSBVUkwucGFyc2UoY29uZmlnLnNlcnZlclVSTCk7XG4gICAgaWYgKHBhdGguaW5kZXhPZihzZXJ2ZXJVUkwucGF0aCkgPT09IDApIHtcbiAgICAgIHBhdGggPSBwYXRoLnNsaWNlKHNlcnZlclVSTC5wYXRoLmxlbmd0aCwgcGF0aC5sZW5ndGgpO1xuICAgIH1cblxuICAgIGlmIChwYXRoWzBdICE9PSBcIi9cIikge1xuICAgICAgcGF0aCA9IFwiL1wiICsgcGF0aDtcbiAgICB9XG5cbiAgICBpZiAocGF0aCA9PT0gJy9iYXRjaCcpIHtcbiAgICAgIGNvbnN0IHByb21pc2VzID0gZGF0YS5yZXF1ZXN0cy5tYXAoKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGhhbmRsZVJlcXVlc3QocmVxdWVzdC5tZXRob2QsIHJlcXVlc3QucGF0aCwgcmVxdWVzdC5ib2R5LCBvcHRpb25zKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKHtzdWNjZXNzOiByZXNwb25zZX0pO1xuICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyh7ZXJyb3I6IHtjb2RlOiBlcnJvci5jb2RlLCBlcnJvcjogZXJyb3IubWVzc2FnZX19KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgfVxuXG4gICAgbGV0IHF1ZXJ5O1xuICAgIGlmIChtZXRob2QgPT09ICdHRVQnKSB7XG4gICAgICBxdWVyeSA9IGRhdGE7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQYXJzZS5Qcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGdldEF1dGgob3B0aW9ucywgY29uZmlnKS50aGVuKChhdXRoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICAgICAgYm9keTogZGF0YSxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICBpbmZvOiB7XG4gICAgICAgICAgICBhcHBsaWNhdGlvbklkOiBhcHBsaWNhdGlvbklkLFxuICAgICAgICAgICAgc2Vzc2lvblRva2VuOiBvcHRpb25zLnNlc3Npb25Ub2tlblxuICAgICAgICAgIH0sXG4gICAgICAgICAgcXVlcnlcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiByb3V0ZXIudHJ5Um91dGVSZXF1ZXN0KG1ldGhvZCwgcGF0aCwgcmVxdWVzdCk7XG4gICAgICAgIH0pLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZS5yZXNwb25zZSwgcmVzcG9uc2Uuc3RhdHVzLCByZXNwb25zZSk7XG4gICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IgJiZcbiAgICAgICAgICAgICAgZXJyLmNvZGUgPT0gUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OICYmXG4gICAgICAgICAgICAgIGVyci5tZXNzYWdlID09IGBjYW5ub3Qgcm91dGUgJHttZXRob2R9ICR7cGF0aH1gKSB7XG4gICAgICAgICAgICBSRVNUQ29udHJvbGxlci5yZXF1ZXN0LmFwcGx5KG51bGwsIGFyZ3MpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0sIHJlamVjdCk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gIHtcbiAgICByZXF1ZXN0OiBoYW5kbGVSZXF1ZXN0LFxuICAgIGFqYXg6IFJFU1RDb250cm9sbGVyLmFqYXhcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlcjtcbmV4cG9ydCB7IFBhcnNlU2VydmVyUkVTVENvbnRyb2xsZXIgfTtcbiJdfQ== \ No newline at end of file diff --git a/lib/PromiseRouter.js b/lib/PromiseRouter.js index 120ec91d54..e5eaf0b97c 100644 --- a/lib/PromiseRouter.js +++ b/lib/PromiseRouter.js @@ -215,4 +215,5 @@ function maskSensitiveUrl(req) { maskUrl = _logger2.default.maskSensitiveUrl(maskUrl); } return maskUrl; -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Qcm9taXNlUm91dGVyLmpzIl0sIm5hbWVzIjpbIkxheWVyIiwicmVxdWlyZSIsInZhbGlkYXRlUGFyYW1ldGVyIiwia2V5IiwidmFsdWUiLCJtYXRjaCIsIlByb21pc2VSb3V0ZXIiLCJjb25zdHJ1Y3RvciIsInJvdXRlcyIsImFwcElkIiwibW91bnRSb3V0ZXMiLCJtZXJnZSIsInJvdXRlciIsInJvdXRlIiwicHVzaCIsIm1ldGhvZCIsInBhdGgiLCJoYW5kbGVycyIsImhhbmRsZXIiLCJsZW5ndGgiLCJyZXEiLCJyZWR1Y2UiLCJwcm9taXNlIiwidGhlbiIsIlByb21pc2UiLCJyZXNvbHZlIiwibGF5ZXIiLCJwYXJhbXMiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsIm1vdW50T250byIsImV4cHJlc3NBcHAiLCJ0b0xvd2VyQ2FzZSIsIm1ha2VFeHByZXNzSGFuZGxlciIsImNhbGwiLCJleHByZXNzUm91dGVyIiwiZXhwcmVzcyIsIlJvdXRlciIsInRyeVJvdXRlUmVxdWVzdCIsInJlcXVlc3QiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9KU09OIiwicmVqZWN0IiwicHJvbWlzZUhhbmRsZXIiLCJyZXMiLCJuZXh0IiwidXJsIiwibWFza1NlbnNpdGl2ZVVybCIsImJvZHkiLCJhc3NpZ24iLCJoZWFkZXJzIiwibG9nIiwibG9nUmVxdWVzdCIsInJlc3VsdCIsInJlc3BvbnNlIiwibG9jYXRpb24iLCJ0ZXh0IiwiZXJyb3IiLCJsb2dSZXNwb25zZSIsInN0YXR1cyIsInNlbmQiLCJzZXQiLCJoZWFkZXIiLCJqc29uIiwiZSIsIm1hc2tVcmwiLCJvcmlnaW5hbFVybCIsInRvU3RyaW5nIiwic2hvdWxkTWFza1VybCIsImluY2x1ZGVzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFPQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQVZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFNQSxNQUFNQSxRQUFRQyxRQUFRLDBCQUFSLENB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YmFzZWQgb24gcHJvbWlzZXMgcmF0aGVyIHRoYW4gcmVxL3Jlcy9uZXh0LlxuLy8gVGhpcyBpcyBpbnRlbmRlZCB0byByZXBsYWNlIHRoZSB1c2Ugb2YgZXhwcmVzcy5Sb3V0ZXIgdG8gaGFuZGxlXG4vLyBzdWJzZWN0aW9ucyBvZiB0aGUgQVBJIHN1cmZhY2UuXG4vLyBUaGlzIHdpbGwgbWFrZSBpdCBlYXNpZXIgdG8gaGF2ZSBtZXRob2RzIGxpa2UgJ2JhdGNoJyB0aGF0XG4vLyB0aGVtc2VsdmVzIHVzZSBvdXIgcm91dGluZyBpbmZvcm1hdGlvbiwgd2l0aG91dCBkaXN0dXJiaW5nIGV4cHJlc3Ncbi8vIGNvbXBvbmVudHMgdGhhdCBleHRlcm5hbCBkZXZlbG9wZXJzIG1heSBiZSBtb2RpZnlpbmcuXG5cbmltcG9ydCBQYXJzZSAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgZXhwcmVzcyAgIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IGxvZyAgICAgICBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQge2luc3BlY3R9IGZyb20gJ3V0aWwnO1xuY29uc3QgTGF5ZXIgPSByZXF1aXJlKCdleHByZXNzL2xpYi9yb3V0ZXIvbGF5ZXInKTtcblxuZnVuY3Rpb24gdmFsaWRhdGVQYXJhbWV0ZXIoa2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5ID09ICdjbGFzc05hbWUnKSB7XG4gICAgaWYgKHZhbHVlLm1hdGNoKC9fP1tBLVphLXpdW0EtWmEtel8wLTldKi8pKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICB9IGVsc2UgaWYgKGtleSA9PSAnb2JqZWN0SWQnKSB7XG4gICAgaWYgKHZhbHVlLm1hdGNoKC9bQS1aYS16MC05XSsvKSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbn1cblxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQcm9taXNlUm91dGVyIHtcbiAgLy8gRWFjaCBlbnRyeSBzaG91bGQgYmUgYW4gb2JqZWN0IHdpdGg6XG4gIC8vIHBhdGg6IHRoZSBwYXRoIHRvIHJvdXRlLCBpbiBleHByZXNzIGZvcm1hdFxuICAvLyBtZXRob2Q6IHRoZSBIVFRQIG1ldGhvZCB0aGF0IHRoaXMgcm91dGUgaGFuZGxlcy5cbiAgLy8gICBNdXN0IGJlIG9uZSBvZjogUE9TVCwgR0VULCBQVVQsIERFTEVURVxuICAvLyBoYW5kbGVyOiBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgcmVxdWVzdCwgYW5kIHJldHVybnMgYSBwcm9taXNlLlxuICAvLyAgIFN1Y2Nlc3NmdWwgaGFuZGxlcnMgc2hvdWxkIHJlc29sdmUgdG8gYW4gb2JqZWN0IHdpdGggZmllbGRzOlxuICAvLyAgICAgc3RhdHVzOiBvcHRpb25hbC4gdGhlIGh0dHAgc3RhdHVzIGNvZGUuIGRlZmF1bHRzIHRvIDIwMFxuICAvLyAgICAgcmVzcG9uc2U6IGEganNvbiBvYmplY3Qgd2l0aCB0aGUgY29udGVudCBvZiB0aGUgcmVzcG9uc2VcbiAgLy8gICAgIGxvY2F0aW9uOiBvcHRpb25hbC4gYSBsb2NhdGlvbiBoZWFkZXJcbiAgY29uc3RydWN0b3Iocm91dGVzID0gW10sIGFwcElkKSB7XG4gICAgdGhpcy5yb3V0ZXMgPSByb3V0ZXM7XG4gICAgdGhpcy5hcHBJZCA9IGFwcElkO1xuICAgIHRoaXMubW91bnRSb3V0ZXMoKTtcbiAgfVxuXG4gIC8vIExlYXZlIHRoZSBvcHBvcnR1bml0eSB0b1xuICAvLyBzdWJjbGFzc2VzIHRvIG1vdW50IHRoZWlyIHJvdXRlcyBieSBvdmVycmlkaW5nXG4gIG1vdW50Um91dGVzKCkge31cblxuICAvLyBNZXJnZSB0aGUgcm91dGVzIGludG8gdGhpcyBvbmVcbiAgbWVyZ2Uocm91dGVyKSB7XG4gICAgZm9yICh2YXIgcm91dGUgb2Ygcm91dGVyLnJvdXRlcykge1xuICAgICAgdGhpcy5yb3V0ZXMucHVzaChyb3V0ZSk7XG4gICAgfVxuICB9XG5cbiAgcm91dGUobWV0aG9kLCBwYXRoLCAuLi5oYW5kbGVycykge1xuICAgIHN3aXRjaChtZXRob2QpIHtcbiAgICBjYXNlICdQT1NUJzpcbiAgICBjYXNlICdHRVQnOlxuICAgIGNhc2UgJ1BVVCc6XG4gICAgY2FzZSAnREVMRVRFJzpcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyAnY2Fubm90IHJvdXRlIG1ldGhvZDogJyArIG1ldGhvZDtcbiAgICB9XG5cbiAgICBsZXQgaGFuZGxlciA9IGhhbmRsZXJzWzBdO1xuXG4gICAgaWYgKGhhbmRsZXJzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGhhbmRsZXIgPSBmdW5jdGlvbihyZXEpIHtcbiAgICAgICAgcmV0dXJuIGhhbmRsZXJzLnJlZHVjZSgocHJvbWlzZSwgaGFuZGxlcikgPT4ge1xuICAgICAgICAgIHJldHVybiBwcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZXIocmVxKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSwgUHJvbWlzZS5yZXNvbHZlKCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucm91dGVzLnB1c2goe1xuICAgICAgcGF0aDogcGF0aCxcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgaGFuZGxlcjogaGFuZGxlcixcbiAgICAgIGxheWVyOiBuZXcgTGF5ZXIocGF0aCwgbnVsbCwgaGFuZGxlcilcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybnMgYW4gb2JqZWN0IHdpdGg6XG4gIC8vICAgaGFuZGxlcjogdGhlIGhhbmRsZXIgdGhhdCBzaG91bGQgZGVhbCB3aXRoIHRoaXMgcmVxdWVzdFxuICAvLyAgIHBhcmFtczogYW55IDotcGFyYW1zIHRoYXQgZ290IHBhcnNlZCBmcm9tIHRoZSBwYXRoXG4gIC8vIFJldHVybnMgdW5kZWZpbmVkIGlmIHRoZXJlIGlzIG5vIG1hdGNoLlxuICBtYXRjaChtZXRob2QsIHBhdGgpIHtcbiAgICBmb3IgKHZhciByb3V0ZSBvZiB0aGlzLnJvdXRlcykge1xuICAgICAgaWYgKHJvdXRlLm1ldGhvZCAhPSBtZXRob2QpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBsYXllciA9IHJvdXRlLmxheWVyIHx8IG5ldyBMYXllcihyb3V0ZS5wYXRoLCBudWxsLCByb3V0ZS5oYW5kbGVyKTtcbiAgICAgIGNvbnN0IG1hdGNoID0gbGF5ZXIubWF0Y2gocGF0aCk7XG4gICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gbGF5ZXIucGFyYW1zO1xuICAgICAgICBPYmplY3Qua2V5cyhwYXJhbXMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgIHBhcmFtc1trZXldID0gdmFsaWRhdGVQYXJhbWV0ZXIoa2V5LCBwYXJhbXNba2V5XSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4ge3BhcmFtczogcGFyYW1zLCBoYW5kbGVyOiByb3V0ZS5oYW5kbGVyfTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBNb3VudCB0aGUgcm91dGVzIG9uIHRoaXMgcm91dGVyIG9udG8gYW4gZXhwcmVzcyBhcHAgKG9yIGV4cHJlc3Mgcm91dGVyKVxuICBtb3VudE9udG8oZXhwcmVzc0FwcCkge1xuICAgIHRoaXMucm91dGVzLmZvckVhY2goKHJvdXRlKSA9PiB7XG4gICAgICBjb25zdCBtZXRob2QgPSByb3V0ZS5tZXRob2QudG9Mb3dlckNhc2UoKTtcbiAgICAgIGNvbnN0IGhhbmRsZXIgPSBtYWtlRXhwcmVzc0hhbmRsZXIodGhpcy5hcHBJZCwgcm91dGUuaGFuZGxlcik7XG4gICAgICBleHByZXNzQXBwW21ldGhvZF0uY2FsbChleHByZXNzQXBwLCByb3V0ZS5wYXRoLCBoYW5kbGVyKTtcbiAgICB9KTtcbiAgICByZXR1cm4gZXhwcmVzc0FwcDtcbiAgfVxuXG4gIGV4cHJlc3NSb3V0ZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMubW91bnRPbnRvKGV4cHJlc3MuUm91dGVyKCkpO1xuICB9XG5cbiAgdHJ5Um91dGVSZXF1ZXN0KG1ldGhvZCwgcGF0aCwgcmVxdWVzdCkge1xuICAgIHZhciBtYXRjaCA9IHRoaXMubWF0Y2gobWV0aG9kLCBwYXRoKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgJ2Nhbm5vdCByb3V0ZSAnICsgbWV0aG9kICsgJyAnICsgcGF0aCk7XG4gICAgfVxuICAgIHJlcXVlc3QucGFyYW1zID0gbWF0Y2gucGFyYW1zO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBtYXRjaC5oYW5kbGVyKHJlcXVlc3QpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICB9KTtcbiAgfVxufVxuXG4vLyBBIGhlbHBlciBmdW5jdGlvbiB0byBtYWtlIGFuIGV4cHJlc3MgaGFuZGxlciBvdXQgb2YgYSBhIHByb21pc2Vcbi8vIGhhbmRsZXIuXG4vLyBFeHByZXNzIGhhbmRsZXJzIHNob3VsZCBuZXZlciB0aHJvdzsgaWYgYSBwcm9taXNlIGhhbmRsZXIgdGhyb3dzIHdlXG4vLyBqdXN0IHRyZWF0IGl0IGxpa2UgaXQgcmVzb2x2ZWQgdG8gYW4gZXJyb3IuXG5mdW5jdGlvbiBtYWtlRXhwcmVzc0hhbmRsZXIoYXBwSWQsIHByb21pc2VIYW5kbGVyKSB7XG4gIHJldHVybiBmdW5jdGlvbihyZXEsIHJlcywgbmV4dCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1cmwgPSBtYXNrU2Vuc2l0aXZlVXJsKHJlcSk7XG4gICAgICBjb25zdCBib2R5ID0gT2JqZWN0LmFzc2lnbih7fSwgcmVxLmJvZHkpO1xuICAgICAgY29uc3QgbWV0aG9kID0gcmVxLm1ldGhvZDtcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSByZXEuaGVhZGVycztcbiAgICAgIGxvZy5sb2dSZXF1ZXN0KHtcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICB1cmwsXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIGJvZHlcbiAgICAgIH0pO1xuICAgICAgcHJvbWlzZUhhbmRsZXIocmVxKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgaWYgKCFyZXN1bHQucmVzcG9uc2UgJiYgIXJlc3VsdC5sb2NhdGlvbiAmJiAhcmVzdWx0LnRleHQpIHtcbiAgICAgICAgICBsb2cuZXJyb3IoJ3RoZSBoYW5kbGVyIGRpZCBub3QgaW5jbHVkZSBhIFwicmVzcG9uc2VcIiBvciBhIFwibG9jYXRpb25cIiBmaWVsZCcpO1xuICAgICAgICAgIHRocm93ICdjb250cm9sIHNob3VsZCBub3QgZ2V0IGhlcmUnO1xuICAgICAgICB9XG5cbiAgICAgICAgbG9nLmxvZ1Jlc3BvbnNlKHsgbWV0aG9kLCB1cmwsIHJlc3VsdCB9KTtcblxuICAgICAgICB2YXIgc3RhdHVzID0gcmVzdWx0LnN0YXR1cyB8fCAyMDA7XG4gICAgICAgIHJlcy5zdGF0dXMoc3RhdHVzKTtcblxuICAgICAgICBpZiAocmVzdWx0LnRleHQpIHtcbiAgICAgICAgICByZXMuc2VuZChyZXN1bHQudGV4dCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc3VsdC5sb2NhdGlvbikge1xuICAgICAgICAgIHJlcy5zZXQoJ0xvY2F0aW9uJywgcmVzdWx0LmxvY2F0aW9uKTtcbiAgICAgICAgICAvLyBPdmVycmlkZSB0aGUgZGVmYXVsdCBleHByZXNzanMgcmVzcG9uc2VcbiAgICAgICAgICAvLyBhcyBpdCBkb3VibGUgZW5jb2RlcyAlZW5jb2RlZCBjaGFycyBpbiBVUkxcbiAgICAgICAgICBpZiAoIXJlc3VsdC5yZXNwb25zZSkge1xuICAgICAgICAgICAgcmVzLnNlbmQoJ0ZvdW5kLiBSZWRpcmVjdGluZyB0byAnICsgcmVzdWx0LmxvY2F0aW9uKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdC5oZWFkZXJzKSB7XG4gICAgICAgICAgT2JqZWN0LmtleXMocmVzdWx0LmhlYWRlcnMpLmZvckVhY2goKGhlYWRlcikgPT4ge1xuICAgICAgICAgICAgcmVzLnNldChoZWFkZXIsIHJlc3VsdC5oZWFkZXJzW2hlYWRlcl0pO1xuICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgICAgcmVzLmpzb24ocmVzdWx0LnJlc3BvbnNlKTtcbiAgICAgIH0sIChlKSA9PiB7XG4gICAgICAgIGxvZy5lcnJvcihgRXJyb3IgZ2VuZXJhdGluZyByZXNwb25zZS4gJHtpbnNwZWN0KGUpfWAsIHtlcnJvcjogZX0pO1xuICAgICAgICBuZXh0KGUpO1xuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nLmVycm9yKGBFcnJvciBoYW5kbGluZyByZXF1ZXN0OiAke2luc3BlY3QoZSl9YCwge2Vycm9yOiBlfSk7XG4gICAgICBuZXh0KGUpO1xuICAgIH1cbiAgfVxufVxuXG5cbmZ1bmN0aW9uIG1hc2tTZW5zaXRpdmVVcmwocmVxKSB7XG4gIGxldCBtYXNrVXJsID0gcmVxLm9yaWdpbmFsVXJsLnRvU3RyaW5nKCk7XG4gIGNvbnN0IHNob3VsZE1hc2tVcmwgPSByZXEubWV0aG9kID09PSAnR0VUJyAmJiByZXEub3JpZ2luYWxVcmwuaW5jbHVkZXMoJy9sb2dpbicpXG4gICAgICAgICAgICAgICAgICAgICAgJiYgIXJlcS5vcmlnaW5hbFVybC5pbmNsdWRlcygnY2xhc3NlcycpO1xuICBpZiAoc2hvdWxkTWFza1VybCkge1xuICAgIG1hc2tVcmwgPSBsb2cubWFza1NlbnNpdGl2ZVVybChtYXNrVXJsKTtcbiAgfVxuICByZXR1cm4gbWFza1VybDtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Push/PushQueue.js b/lib/Push/PushQueue.js index 7771600888..17a550fea0 100644 --- a/lib/Push/PushQueue.js +++ b/lib/Push/PushQueue.js @@ -69,4 +69,5 @@ class PushQueue { }); } } -exports.PushQueue = PushQueue; \ No newline at end of file +exports.PushQueue = PushQueue; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL1B1c2hRdWV1ZS5qcyJdLCJuYW1lcyI6WyJQVVNIX0NIQU5ORUwiLCJERUZBVUxUX0JBVENIX1NJWkUiLCJQdXNoUXVldWUiLCJjb25zdHJ1Y3RvciIsImNvbmZpZyIsImNoYW5uZWwiLCJkZWZhdWx0UHVzaENoYW5uZWwiLCJiYXRjaFNpemUiLCJwYXJzZVB1Ymxpc2hlciIsIlBhcnNlTWVzc2FnZVF1ZXVlIiwiY3JlYXRlUHVibGlzaGVyIiwiUGFyc2UiLCJhcHBsaWNhdGlvbklkIiwiZW5xdWV1ZSIsImJvZHkiLCJ3aGVyZSIsImF1dGgiLCJwdXNoU3RhdHVzIiwibGltaXQiLCJvcmRlciIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsInJlc3QiLCJmaW5kIiwiY291bnQiLCJyZXN1bHRzIiwiY29tcGxldGUiLCJzZXRSdW5uaW5nIiwiTWF0aCIsImNlaWwiLCJza2lwIiwicXVlcnkiLCJwdXNoV29ya0l0ZW0iLCJvYmplY3RJZCIsInB1Ymxpc2giLCJKU09OIiwic3RyaW5naWZ5Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEsZUFBZSxtQkFBckI7QUFDQSxNQUFNQyxxQkFBcUIsR0FBM0I7O0FBRU8sTUFBTUMsU0FBTixDQUFnQjs7QUFLckI7QUFDQTtBQUNBQyxjQUFZQyxTQUFjLEVBQTFCLEVBQThCO0FBQzVCLFNBQUtDLE9BQUwsR0FBZUQsT0FBT0MsT0FBUCxJQUFrQkgsVUFBVUksa0JBQVYsRUFBakM7QUFDQSxTQUFLQyxTQUFMLEdBQWlCSCxPQUFPRyxTQUFQLElBQW9CTixrQkFBckM7QUFDQSxTQUFLTyxjQUFMLEdBQXNCQyxxQ0FBa0JDLGVBQWxCLENBQWtDTixNQUFsQyxDQUF0QjtBQUNEOztBQUVELFNBQU9FLGtCQUFQLEdBQTRCO0FBQzFCLFdBQVEsR0FBRUssZUFBTUMsYUFBYyxJQUFHWixZQUFhLEVBQTlDO0FBQ0Q7O0FBRURhLFVBQVFDLElBQVIsRUFBY0MsS0FBZCxFQUFxQlgsTUFBckIsRUFBNkJZLElBQTdCLEVBQW1DQyxVQUFuQyxFQUErQztBQUM3QyxVQUFNQyxRQUFRLEtBQUtYLFNBQW5COztBQUVBUSxZQUFRLG1DQUF1QkEsS0FBdkIsQ0FBUjs7QUFFQTtBQUNBLFVBQU1JLFFBQVEsVUFBZDtBQUNBLFdBQU9DLFFBQVFDLE9BQVIsR0FBa0JDLElBQWxCLENBQXVCLE1BQU07QUFDbEMsYUFBT0MsZUFBS0MsSUFBTCxDQUFVcEIsTUFBVixFQUNMWSxJQURLLEVBRUwsZUFGSyxFQUdMRCxLQUhLLEVBSUwsRUFBQ0csT0FBTyxDQUFSLEVBQVdPLE9BQU8sSUFBbEIsRUFKSyxDQUFQO0FBS0QsS0FOTSxFQU1KSCxJQU5JLENBTUMsQ0FBQyxFQUFDSSxPQUFELEVBQVVELEtBQVYsRUFBRCxLQUFzQjtBQUM1QixVQUFJLENBQUNDLE9BQUQsSUFBWUQsU0FBUyxDQUF6QixFQUE0QjtBQUMxQixlQUFPUixXQUFXVSxRQUFYLEVBQVA7QUFDRDtBQUNEVixpQkFBV1csVUFBWCxDQUFzQkMsS0FBS0MsSUFBTCxDQUFVTCxRQUFRUCxLQUFsQixDQUF0QjtBQUNBLFVBQUlhLE9BQU8sQ0FBWDtBQUNBLGFBQU9BLE9BQU9OLEtBQWQsRUFBcUI7QUFDbkIsY0FBTU8sUUFBUSxFQUFFakIsS0FBRjtBQUNaRyxlQURZO0FBRVphLGNBRlk7QUFHWlosZUFIWSxFQUFkOztBQUtBLGNBQU1jLGVBQWU7QUFDbkJuQixjQURtQjtBQUVuQmtCLGVBRm1CO0FBR25CZixzQkFBWSxFQUFFaUIsVUFBVWpCLFdBQVdpQixRQUF2QixFQUhPO0FBSW5CdEIseUJBQWVSLE9BQU9RO0FBSkgsU0FBckI7QUFNQSxhQUFLSixjQUFMLENBQW9CMkIsT0FBcEIsQ0FBNEIsS0FBSzlCLE9BQWpDLEVBQTBDK0IsS0FBS0MsU0FBTCxDQUFlSixZQUFmLENBQTFDO0FBQ0FGLGdCQUFRYixLQUFSO0FBQ0Q7QUFDRixLQTNCTSxDQUFQO0FBNEJEO0FBcERvQjtRQUFWaEIsUyxHQUFBQSxTIiwiZmlsZSI6IlB1c2hRdWV1ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlTWVzc2FnZVF1ZXVlIH0gICAgICBmcm9tICcuLi9QYXJzZU1lc3NhZ2VRdWV1ZSc7XG5pbXBvcnQgcmVzdCAgICAgICAgICAgICAgICAgICAgICAgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgeyBhcHBseURldmljZVRva2VuRXhpc3RzIH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5cbmNvbnN0IFBVU0hfQ0hBTk5FTCA9ICdwYXJzZS1zZXJ2ZXItcHVzaCc7XG5jb25zdCBERUZBVUxUX0JBVENIX1NJWkUgPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBQdXNoUXVldWUge1xuICBwYXJzZVB1Ymxpc2hlcjogT2JqZWN0O1xuICBjaGFubmVsOiBTdHJpbmc7XG4gIGJhdGNoU2l6ZTogTnVtYmVyO1xuXG4gIC8vIGNvbmZpZyBvYmplY3Qgb2YgdGhlIHB1Ymxpc2hlciwgcmlnaHQgbm93IGl0IG9ubHkgY29udGFpbnMgdGhlIHJlZGlzVVJMLFxuICAvLyBidXQgd2UgbWF5IGV4dGVuZCBpdCBsYXRlci5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBhbnkgPSB7fSkge1xuICAgIHRoaXMuY2hhbm5lbCA9IGNvbmZpZy5jaGFubmVsIHx8IFB1c2hRdWV1ZS5kZWZhdWx0UHVzaENoYW5uZWwoKTtcbiAgICB0aGlzLmJhdGNoU2l6ZSA9IGNvbmZpZy5iYXRjaFNpemUgfHwgREVGQVVMVF9CQVRDSF9TSVpFO1xuICAgIHRoaXMucGFyc2VQdWJsaXNoZXIgPSBQYXJzZU1lc3NhZ2VRdWV1ZS5jcmVhdGVQdWJsaXNoZXIoY29uZmlnKTtcbiAgfVxuXG4gIHN0YXRpYyBkZWZhdWx0UHVzaENoYW5uZWwoKSB7XG4gICAgcmV0dXJuIGAke1BhcnNlLmFwcGxpY2F0aW9uSWR9LSR7UFVTSF9DSEFOTkVMfWA7XG4gIH1cblxuICBlbnF1ZXVlKGJvZHksIHdoZXJlLCBjb25maWcsIGF1dGgsIHB1c2hTdGF0dXMpIHtcbiAgICBjb25zdCBsaW1pdCA9IHRoaXMuYmF0Y2hTaXplO1xuXG4gICAgd2hlcmUgPSBhcHBseURldmljZVRva2VuRXhpc3RzKHdoZXJlKTtcblxuICAgIC8vIE9yZGVyIGJ5IG9iamVjdElkIHNvIG5vIGltcGFjdCBvbiB0aGUgREJcbiAgICBjb25zdCBvcmRlciA9ICdvYmplY3RJZCc7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHJlc3QuZmluZChjb25maWcsXG4gICAgICAgIGF1dGgsXG4gICAgICAgICdfSW5zdGFsbGF0aW9uJyxcbiAgICAgICAgd2hlcmUsXG4gICAgICAgIHtsaW1pdDogMCwgY291bnQ6IHRydWV9KTtcbiAgICB9KS50aGVuKCh7cmVzdWx0cywgY291bnR9KSA9PiB7XG4gICAgICBpZiAoIXJlc3VsdHMgfHwgY291bnQgPT0gMCkge1xuICAgICAgICByZXR1cm4gcHVzaFN0YXR1cy5jb21wbGV0ZSgpO1xuICAgICAgfVxuICAgICAgcHVzaFN0YXR1cy5zZXRSdW5uaW5nKE1hdGguY2VpbChjb3VudCAvIGxpbWl0KSk7XG4gICAgICBsZXQgc2tpcCA9IDA7XG4gICAgICB3aGlsZSAoc2tpcCA8IGNvdW50KSB7XG4gICAgICAgIGNvbnN0IHF1ZXJ5ID0geyB3aGVyZSxcbiAgICAgICAgICBsaW1pdCxcbiAgICAgICAgICBza2lwLFxuICAgICAgICAgIG9yZGVyIH07XG5cbiAgICAgICAgY29uc3QgcHVzaFdvcmtJdGVtID0ge1xuICAgICAgICAgIGJvZHksXG4gICAgICAgICAgcXVlcnksXG4gICAgICAgICAgcHVzaFN0YXR1czogeyBvYmplY3RJZDogcHVzaFN0YXR1cy5vYmplY3RJZCB9LFxuICAgICAgICAgIGFwcGxpY2F0aW9uSWQ6IGNvbmZpZy5hcHBsaWNhdGlvbklkXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYXJzZVB1Ymxpc2hlci5wdWJsaXNoKHRoaXMuY2hhbm5lbCwgSlNPTi5zdHJpbmdpZnkocHVzaFdvcmtJdGVtKSk7XG4gICAgICAgIHNraXAgKz0gbGltaXQ7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Push/PushWorker.js b/lib/Push/PushWorker.js index 3777a451c9..b9046fdcb5 100644 --- a/lib/Push/PushWorker.js +++ b/lib/Push/PushWorker.js @@ -70,12 +70,6 @@ class PushWorker { } } - unsubscribe() { - if (this.subscriber) { - this.subscriber.unsubscribe(this.channel); - } - } - run({ body, query, pushStatus, applicationId, UTCOffset }) { const config = _Config2.default.get(applicationId); const auth = (0, _Auth.master)(config); @@ -87,8 +81,6 @@ class PushWorker { return pushStatus.trackSent(results); } return this.sendToAdapter(body, results, pushStatus, config, UTCOffset); - }, err => { - throw err; }); } @@ -147,4 +139,5 @@ class PushWorker { } exports.PushWorker = PushWorker; -exports.default = PushWorker; \ No newline at end of file +exports.default = PushWorker; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL1B1c2hXb3JrZXIuanMiXSwibmFtZXMiOlsidXRpbHMiLCJncm91cEJ5QmFkZ2UiLCJpbnN0YWxsYXRpb25zIiwicmVkdWNlIiwibWFwIiwiaW5zdGFsbGF0aW9uIiwiYmFkZ2UiLCJwdXNoIiwiUHVzaFdvcmtlciIsImNvbnN0cnVjdG9yIiwicHVzaEFkYXB0ZXIiLCJzdWJzY3JpYmVyQ29uZmlnIiwiQWRhcHRhYmxlQ29udHJvbGxlciIsInZhbGlkYXRlQWRhcHRlciIsIlB1c2hBZGFwdGVyIiwiYWRhcHRlciIsImNoYW5uZWwiLCJQdXNoUXVldWUiLCJkZWZhdWx0UHVzaENoYW5uZWwiLCJzdWJzY3JpYmVyIiwiUGFyc2VNZXNzYWdlUXVldWUiLCJjcmVhdGVTdWJzY3JpYmVyIiwic3Vic2NyaWJlIiwib24iLCJtZXNzYWdlU3RyIiwid29ya0l0ZW0iLCJKU09OIiwicGFyc2UiLCJnZXRBbmRSdW4iLCJydW4iLCJib2R5IiwicXVlcnkiLCJwdXNoU3RhdHVzIiwiYXBwbGljYXRpb25JZCIsIlVUQ09mZnNldCIsImNvbmZpZyIsIkNvbmZpZyIsImdldCIsImF1dGgiLCJ3aGVyZSIsImFwcGx5RGV2aWNlVG9rZW5FeGlzdHMiLCJvYmplY3RJZCIsInJlc3QiLCJmaW5kIiwidGhlbiIsInJlc3VsdHMiLCJsZW5ndGgiLCJ0cmFja1NlbnQiLCJzZW5kVG9BZGFwdGVyIiwibG9jYWxlcyIsImdldExvY2FsZXNGcm9tUHVzaCIsImJvZGllc1BlckxvY2FsZXMiLCJncm91cHBlZEluc3RhbGxhdGlvbnMiLCJncm91cEJ5TG9jYWxlSWRlbnRpZmllciIsInByb21pc2VzIiwiT2JqZWN0Iiwia2V5cyIsImxvY2FsZSIsIlByb21pc2UiLCJhbGwiLCJpc1B1c2hJbmNyZW1lbnRpbmciLCJsb2dnZXIiLCJ2ZXJib3NlIiwic2VuZCIsInVuZGVmaW5lZCIsImJhZGdlSW5zdGFsbGF0aW9uc01hcCIsInBheWxvYWQiLCJkYXRhIiwicGFyc2VJ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QVNwQyxJQUFULENBQWhCO0FBQ0FvQyxjQUFRQyxJQUFSLENBQWE3RCxLQUFiLEdBQXFCOEQsU0FBUzlELEtBQVQsQ0FBckI7QUFDQSxZQUFNSixnQkFBZ0IrRCxzQkFBc0IzRCxLQUF0QixDQUF0QjtBQUNBLGFBQU8sS0FBSzBDLGFBQUwsQ0FBbUJrQixPQUFuQixFQUE0QmhFLGFBQTVCLEVBQTJDOEIsVUFBM0MsRUFBdURHLE1BQXZELEVBQStERCxTQUEvRCxDQUFQO0FBQ0QsS0FMZ0IsQ0FBakI7QUFNQSxXQUFPd0IsUUFBUUMsR0FBUixDQUFZTCxRQUFaLENBQVA7QUFDRDs7QUFFRDFCLFlBQVVILFFBQVYsRUFBdUM7QUFDckMsUUFBSTRDLFFBQVEsSUFBWjtBQUNBLFFBQUksQ0FBQ0EsTUFBTWxELFVBQU4sQ0FBaUJVLEdBQXRCLEVBQTJCO0FBQ3pCLGFBQU93QyxNQUFNeEMsR0FBTixDQUFVSixRQUFWLENBQVA7QUFDRDtBQUNELFdBQU80QyxNQUFNbEQsVUFBTixDQUFpQlUsR0FBakIsQ0FBcUJKLFFBQXJCLEVBQStCbUIsSUFBL0IsQ0FBb0MsVUFBVTBCLE9BQVYsRUFBbUI7QUFDNUQsVUFBSUEsT0FBSixFQUFhO0FBQ1gsZUFBT0QsTUFBTXhDLEdBQU4sQ0FBVXlDLE9BQVYsRUFDSjFCLElBREksQ0FDQyxZQUFZO0FBQ2hCLGlCQUFPeUIsTUFBTXpDLFNBQU4sQ0FBZ0IwQyxPQUFoQixDQUFQO0FBQ0QsU0FISSxDQUFQO0FBSUQsT0FMRCxNQUtPO0FBQ0wsZUFBT1osUUFBUWEsT0FBUixFQUFQO0FBQ0Q7QUFDRixLQVRNLENBQVA7QUFVRDtBQXhGcUI7O1FBQVgvRCxVLEdBQUFBLFU7a0JBMkZFQSxVIiwiZmlsZSI6IlB1c2hXb3JrZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgZGVlcGNvcHkgICAgICAgICAgICAgICBmcm9tICdkZWVwY29weSc7XG5pbXBvcnQgQWRhcHRhYmxlQ29udHJvbGxlciAgICBmcm9tICcuLi9Db250cm9sbGVycy9BZGFwdGFibGVDb250cm9sbGVyJztcbmltcG9ydCB7IG1hc3RlciB9ICAgICAgICAgICAgIGZyb20gJy4uL0F1dGgnO1xuaW1wb3J0IENvbmZpZyAgICAgICAgICAgICAgICAgZnJvbSAnLi4vQ29uZmlnJztcbmltcG9ydCB7IFB1c2hBZGFwdGVyIH0gICAgICAgIGZyb20gJy4uL0FkYXB0ZXJzL1B1c2gvUHVzaEFkYXB0ZXInO1xuaW1wb3J0IHJlc3QgICAgICAgICAgICAgICAgICAgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgeyBwdXNoU3RhdHVzSGFuZGxlciB9ICBmcm9tICcuLi9TdGF0dXNIYW5kbGVyJztcbmltcG9ydCAqIGFzIHV0aWxzICAgICAgICAgICAgIGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgUGFyc2VNZXNzYWdlUXVldWUgfSAgZnJvbSAnLi4vUGFyc2VNZXNzYWdlUXVldWUnO1xuaW1wb3J0IHsgUHVzaFF1ZXVlIH0gICAgICAgICAgZnJvbSAnLi9QdXNoUXVldWUnO1xuaW1wb3J0IGxvZ2dlciAgICAgICAgICAgICAgICAgZnJvbSAnLi4vbG9nZ2VyJztcblxuZnVuY3Rpb24gZ3JvdXBCeUJhZGdlKGluc3RhbGxhdGlvbnMpIHtcbiAgcmV0dXJuIGluc3RhbGxhdGlvbnMucmVkdWNlKChtYXAsIGluc3RhbGxhdGlvbikgPT4ge1xuICAgIGNvbnN0IGJhZGdlID0gaW5zdGFsbGF0aW9uLmJhZGdlICsgJyc7XG4gICAgbWFwW2JhZGdlXSA9IG1hcFtiYWRnZV0gfHwgW107XG4gICAgbWFwW2JhZGdlXS5wdXNoKGluc3RhbGxhdGlvbik7XG4gICAgcmV0dXJuIG1hcDtcbiAgfSwge30pO1xufVxuXG5leHBvcnQgY2xhc3MgUHVzaFdvcmtlciB7XG4gIHN1YnNjcmliZXI6IGFueTtcbiAgYWRhcHRlcjogYW55O1xuICBjaGFubmVsOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHVzaEFkYXB0ZXI6IFB1c2hBZGFwdGVyLCBzdWJzY3JpYmVyQ29uZmlnOiBhbnkgPSB7fSkge1xuICAgIEFkYXB0YWJsZUNvbnRyb2xsZXIudmFsaWRhdGVBZGFwdGVyKHB1c2hBZGFwdGVyLCB0aGlzLCBQdXNoQWRhcHRlcik7XG4gICAgdGhpcy5hZGFwdGVyID0gcHVzaEFkYXB0ZXI7XG5cbiAgICB0aGlzLmNoYW5uZWwgPSBzdWJzY3JpYmVyQ29uZmlnLmNoYW5uZWwgfHwgUHVzaFF1ZXVlLmRlZmF1bHRQdXNoQ2hhbm5lbCgpO1xuICAgIHRoaXMuc3Vic2NyaWJlciA9IFBhcnNlTWVzc2FnZVF1ZXVlLmNyZWF0ZVN1YnNjcmliZXIoc3Vic2NyaWJlckNvbmZpZyk7XG4gICAgaWYgKHRoaXMuc3Vic2NyaWJlcikge1xuICAgICAgY29uc3Qgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlcjtcbiAgICAgIHN1YnNjcmliZXIuc3Vic2NyaWJlKHRoaXMuY2hhbm5lbCk7XG4gICAgICBzdWJzY3JpYmVyLm9uKCdtZXNzYWdlJywgKGNoYW5uZWwsIG1lc3NhZ2VTdHIpID0+IHtcbiAgICAgICAgY29uc3Qgd29ya0l0ZW0gPSBKU09OLnBhcnNlKG1lc3NhZ2VTdHIpO1xuICAgICAgICB0aGlzLmdldEFuZFJ1bih3b3JrSXRlbSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBydW4oeyBib2R5LCBxdWVyeSwgcHVzaFN0YXR1cywgYXBwbGljYXRpb25JZCwgVVRDT2Zmc2V0IH06IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChhcHBsaWNhdGlvbklkKTtcbiAgICBjb25zdCBhdXRoID0gbWFzdGVyKGNvbmZpZyk7XG4gICAgY29uc3Qgd2hlcmUgPSB1dGlscy5hcHBseURldmljZVRva2VuRXhpc3RzKHF1ZXJ5LndoZXJlKTtcbiAgICBkZWxldGUgcXVlcnkud2hlcmU7XG4gICAgcHVzaFN0YXR1cyA9IHB1c2hTdGF0dXNIYW5kbGVyKGNvbmZpZywgcHVzaFN0YXR1cy5vYmplY3RJZCk7XG4gICAgcmV0dXJuIHJlc3QuZmluZChjb25maWcsIGF1dGgsICdfSW5zdGFsbGF0aW9uJywgd2hlcmUsIHF1ZXJ5KS50aGVuKCh7cmVzdWx0c30pID0+IHtcbiAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgIHJldHVybiBwdXNoU3RhdHVzLnRyYWNrU2VudChyZXN1bHRzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnNlbmRUb0FkYXB0ZXIoYm9keSwgcmVzdWx0cywgcHVzaFN0YXR1cywgY29uZmlnLCBVVENPZmZzZXQpO1xuICAgIH0pO1xuICB9XG5cbiAgc2VuZFRvQWRhcHRlcihib2R5OiBhbnksIGluc3RhbGxhdGlvbnM6IGFueSwgcHVzaFN0YXR1czogYW55LCBjb25maWc6IENvbmZpZywgVVRDT2Zmc2V0OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbG9jYWxlcyBpbiB0aGUgcHVzaCBib2R5XG4gICAgY29uc3QgbG9jYWxlcyA9IHV0aWxzLmdldExvY2FsZXNGcm9tUHVzaChib2R5KTtcbiAgICBpZiAobG9jYWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBHZXQgYWxsIHRyYW5mb3JtZWQgYm9kaWVzIGZvciBlYWNoIGxvY2FsZVxuICAgICAgY29uc3QgYm9kaWVzUGVyTG9jYWxlcyA9IHV0aWxzLmJvZGllc1BlckxvY2FsZXMoYm9keSwgbG9jYWxlcyk7XG5cbiAgICAgIC8vIEdyb3VwIGluc3RhbGxhdGlvbnMgb24gdGhlIHNwZWNpZmllZCBsb2NhbGVzIChlbiwgZnIsIGRlZmF1bHQgZXRjLi4uKVxuICAgICAgY29uc3QgZ3JvdXBwZWRJbnN0YWxsYXRpb25zID0gdXRpbHMuZ3JvdXBCeUxvY2FsZUlkZW50aWZpZXIoaW5zdGFsbGF0aW9ucywgbG9jYWxlcyk7XG4gICAgICBjb25zdCBwcm9taXNlcyA9IE9iamVjdC5rZXlzKGdyb3VwcGVkSW5zdGFsbGF0aW9ucykubWFwKChsb2NhbGUpID0+IHtcbiAgICAgICAgY29uc3QgaW5zdGFsbGF0aW9ucyA9IGdyb3VwcGVkSW5zdGFsbGF0aW9uc1tsb2NhbGVdO1xuICAgICAgICBjb25zdCBib2R5ID0gYm9kaWVzUGVyTG9jYWxlc1tsb2NhbGVdO1xuICAgICAgICByZXR1cm4gdGhpcy5zZW5kVG9BZGFwdGVyKGJvZHksIGluc3RhbGxhdGlvbnMsIHB1c2hTdGF0dXMsIGNvbmZpZywgVVRDT2Zmc2V0KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICB9XG5cbiAgICBpZiAoIXV0aWxzLmlzUHVzaEluY3JlbWVudGluZyhib2R5KSkge1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoYFNlbmRpbmcgcHVzaCB0byAke2luc3RhbGxhdGlvbnMubGVuZ3RofWApO1xuICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5zZW5kKGJvZHksIGluc3RhbGxhdGlvbnMsIHB1c2hTdGF0dXMub2JqZWN0SWQpLnRoZW4oKHJlc3VsdHMpID0+IHtcbiAgICAgICAgcmV0dXJuIHB1c2hTdGF0dXMudHJhY2tTZW50KHJlc3VsdHMsIFVUQ09mZnNldCwgdW5kZWZpbmVkLCBpbnN0YWxsYXRpb25zLmxlbmd0aCAtIHJlc3VsdHMubGVuZ3RoKVxuICAgICAgICAgIC50aGVuKCgpID0+IHJlc3VsdHMpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ29sbGVjdCB0aGUgYmFkZ2VzIHRvIHJlZHVjZSB0aGUgIyBvZiBjYWxsc1xuICAgIGNvbnN0IGJhZGdlSW5zdGFsbGF0aW9uc01hcCA9IGdyb3VwQnlCYWRnZShpbnN0YWxsYXRpb25zKTtcblxuICAgIC8vIE1hcCB0aGUgb24gdGhlIGJhZGdlcyBjb3VudCBhbmQgcmV0dXJuIHRoZSBzZW5kIHJlc3VsdFxuICAgIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LmtleXMoYmFkZ2VJbnN0YWxsYXRpb25zTWFwKS5tYXAoKGJhZGdlKSA9PiB7XG4gICAgICBjb25zdCBwYXlsb2FkID0gZGVlcGNvcHkoYm9keSk7XG4gICAgICBwYXlsb2FkLmRhdGEuYmFkZ2UgPSBwYXJzZUludChiYWRnZSk7XG4gICAgICBjb25zdCBpbnN0YWxsYXRpb25zID0gYmFkZ2VJbnN0YWxsYXRpb25zTWFwW2JhZGdlXTtcbiAgICAgIHJldHVybiB0aGlzLnNlbmRUb0FkYXB0ZXIocGF5bG9hZCwgaW5zdGFsbGF0aW9ucywgcHVzaFN0YXR1cywgY29uZmlnLCBVVENPZmZzZXQpO1xuICAgIH0pO1xuICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gIH1cblxuICBnZXRBbmRSdW4od29ya0l0ZW06IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICBpZiAoIV90aGlzLnN1YnNjcmliZXIucnVuKSB7XG4gICAgICByZXR1cm4gX3RoaXMucnVuKHdvcmtJdGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIF90aGlzLnN1YnNjcmliZXIucnVuKHdvcmtJdGVtKS50aGVuKGZ1bmN0aW9uIChnb3RJdGVtKSB7XG4gICAgICBpZiAoZ290SXRlbSkge1xuICAgICAgICByZXR1cm4gX3RoaXMucnVuKGdvdEl0ZW0pXG4gICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzLmdldEFuZFJ1bihnb3RJdGVtKVxuICAgICAgICAgIH0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVzaFdvcmtlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Push/utils.js b/lib/Push/utils.js index a526977766..3fbc8f7581 100644 --- a/lib/Push/utils.js +++ b/lib/Push/utils.js @@ -23,7 +23,16 @@ var _deepcopy2 = _interopRequireDefault(_deepcopy); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function isPushIncrementing(body) { - return body.data && body.data.badge && typeof body.data.badge == 'string' && body.data.badge.toLowerCase() == "increment"; + 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']; @@ -130,4 +139,5 @@ function applyDeviceTokenExists(where) { where['deviceToken'] = { '$exists': true }; } return where; -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9QdXNoL3V0aWxzLmpzIl0sIm5hbWVzIjpbImlzUHVzaEluY3JlbWVudGluZyIsImdldExvY2FsZXNGcm9tUHVzaCIsInRyYW5zZm9ybVB1c2hCb2R5Rm9yTG9jYWxlIiwic3RyaXBMb2NhbGVzRnJvbUJvZHkiLCJib2RpZXNQZXJMb2NhbGVzIiwiZ3JvdXBCeUxvY2FsZUlkZW50aWZpZXIiLCJ2YWxpZGF0ZVB1c2hUeXBlIiwiYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyIsImJvZHkiLCJkYXRhIiwiYmFkZ2UiLCJ0b0xvd2VyQ2FzZSIsIl9fb3AiLCJOdW1iZXIiLCJhbW91bnQiLCJsb2NhbGl6YWJsZUtleXMiLCJTZXQiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwibWVtbyIsImtleSIsImZvckVhY2giLCJsb2NhbGl6YWJsZUtleSIsImluZGV4T2YiLCJwdXNoIiwic2xpY2UiLCJsZW5ndGgiLCJsb2NhbGUiLCJsb2NhbGVWYWx1ZSIsImxvY2FsZXMiLCJyZXN1bHQiLCJkZWZhdWx0IiwiaW5zdGFsbGF0aW9ucyIsIm1hcCIsImluc3RhbGxhdGlvbiIsImFkZGVkIiwibG9jYWxlSWRlbnRpZmllciIsIndoZXJlIiwidmFsaWRQdXNoVHlwZXMiLCJkZXZpY2VUeXBlRmllbGQiLCJkZXZpY2VUeXBlIiwiZGV2aWNlVHlwZXMiLCJBcnJheSIsImlzQXJyYXkiLCJjb25jYXQiLCJpIiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImhhc093blByb3BlcnR5Il0sIm1hcHBpbmdzIjoiOzs7OztRQUdnQkEsa0IsR0FBQUEsa0I7UUFnQkFDLGtCLEdBQUFBLGtCO1FBZUFDLDBCLEdBQUFBLDBCO1FBZUFDLG9CLEdBQUFBLG9CO1FBWUFDLGdCLEdBQUFBLGdCO1FBV0FDLHVCLEdBQUFBLHVCO1FBeUJBQyxnQixHQUFBQSxnQjtRQWlCQUMsc0IsR0FBQUEsc0I7O0FBbEhoQjs7OztBQUNBOzs7Ozs7QUFFTyxTQUFTUCxrQkFB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QWNKLGdCQUFnQixLQUFoQixDQUFkLENBQUosRUFBMkM7QUFDaERFLGdCQUFZRyxNQUFaLENBQW1CTCxnQkFBZ0IsS0FBaEIsQ0FBbkI7QUFDRDtBQUNELE9BQUssSUFBSU0sSUFBSSxDQUFiLEVBQWdCQSxJQUFJSixZQUFZZixNQUFoQyxFQUF3Q21CLEdBQXhDLEVBQTZDO0FBQzNDLFFBQUlMLGFBQWFDLFlBQVlJLENBQVosQ0FBakI7QUFDQSxRQUFJUCxlQUFlZixPQUFmLENBQXVCaUIsVUFBdkIsSUFBcUMsQ0FBekMsRUFBNEM7QUFDMUMsWUFBTSxJQUFJTSxlQUFNQyxLQUFWLENBQWdCRCxlQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKUixhQUFhLDhCQURULENBQU47QUFFRDtBQUNGO0FBQ0Y7O0FBRU0sU0FBU2xDLHNCQUFULENBQWdDK0IsS0FBaEMsRUFBdUM7QUFDNUNBLFVBQVEsd0JBQVNBLEtBQVQsQ0FBUjtBQUNBLE1BQUksQ0FBQ0EsTUFBTVksY0FBTixDQUFxQixhQUFyQixDQUFMLEVBQTBDO0FBQ3hDWixVQUFNLGFBQU4sSUFBdUIsRUFBQyxXQUFXLElBQVosRUFBdkI7QUFDRDtBQUNELFNBQU9BLEtBQVA7QUFDRCIsImZpbGUiOiJ1dGlscy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQYXJzZSAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBkZWVwY29weSBmcm9tICdkZWVwY29weSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1B1c2hJbmNyZW1lbnRpbmcoYm9keSkge1xuICBpZiAoIWJvZHkuZGF0YSB8fCAhYm9keS5kYXRhLmJhZGdlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgYmFkZ2UgPSBib2R5LmRhdGEuYmFkZ2U7XG4gIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ3N0cmluZycgJiYgYmFkZ2UudG9Mb3dlckNhc2UoKSA9PSBcImluY3JlbWVudFwiKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gdHlwZW9mIGJhZGdlID09ICdvYmplY3QnICYmIHR5cGVvZiBiYWRnZS5fX29wID09ICdzdHJpbmcnICYmXG4gICAgICAgICBiYWRnZS5fX29wLnRvTG93ZXJDYXNlKCkgPT0gXCJpbmNyZW1lbnRcIiAmJiBOdW1iZXIoYmFkZ2UuYW1vdW50KTtcbn1cblxuY29uc3QgbG9jYWxpemFibGVLZXlzID0gWydhbGVydCcsICd0aXRsZSddO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9jYWxlc0Zyb21QdXNoKGJvZHkpIHtcbiAgY29uc3QgZGF0YSA9IGJvZHkuZGF0YTtcbiAgaWYgKCFkYXRhKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiBbLi4ubmV3IFNldChPYmplY3Qua2V5cyhkYXRhKS5yZWR1Y2UoKG1lbW8sIGtleSkgPT4ge1xuICAgIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKChsb2NhbGl6YWJsZUtleSkgPT4ge1xuICAgICAgaWYgKGtleS5pbmRleE9mKGAke2xvY2FsaXphYmxlS2V5fS1gKSA9PSAwKSB7XG4gICAgICAgIG1lbW8ucHVzaChrZXkuc2xpY2UobG9jYWxpemFibGVLZXkubGVuZ3RoICsgMSkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBtZW1vO1xuICB9LCBbXSkpXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybVB1c2hCb2R5Rm9yTG9jYWxlKGJvZHksIGxvY2FsZSkge1xuICBjb25zdCBkYXRhID0gYm9keS5kYXRhO1xuICBpZiAoIWRhdGEpIHtcbiAgICByZXR1cm4gYm9keTtcbiAgfVxuICBib2R5ID0gZGVlcGNvcHkoYm9keSk7XG4gIGxvY2FsaXphYmxlS2V5cy5mb3JFYWNoKChrZXkpID0+IHtcbiAgICBjb25zdCBsb2NhbGVWYWx1ZSA9IGJvZHkuZGF0YVtgJHtrZXl9LSR7bG9jYWxlfWBdO1xuICAgIGlmIChsb2NhbGVWYWx1ZSkge1xuICAgICAgYm9keS5kYXRhW2tleV0gPSBsb2NhbGVWYWx1ZTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gc3RyaXBMb2NhbGVzRnJvbUJvZHkoYm9keSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcExvY2FsZXNGcm9tQm9keShib2R5KSB7XG4gIGlmICghYm9keS5kYXRhKSB7IHJldHVybiBib2R5OyB9XG4gIE9iamVjdC5rZXlzKGJvZHkuZGF0YSkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgbG9jYWxpemFibGVLZXlzLmZvckVhY2goKGxvY2FsaXphYmxlS2V5KSA9PiB7XG4gICAgICBpZiAoa2V5LmluZGV4T2YoYCR7bG9jYWxpemFibGVLZXl9LWApID09IDApIHtcbiAgICAgICAgZGVsZXRlIGJvZHkuZGF0YVtrZXldO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGJvZHk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBib2RpZXNQZXJMb2NhbGVzKGJvZHksIGxvY2FsZXMgPSBbXSkge1xuICAvLyBHZXQgYWxsIHRyYW5mb3JtZWQgYm9kaWVzIGZvciBlYWNoIGxvY2FsZVxuICBjb25zdCByZXN1bHQgPSBsb2NhbGVzLnJlZHVjZSgobWVtbywgbG9jYWxlKSA9PiB7XG4gICAgbWVtb1tsb2NhbGVdID0gdHJhbnNmb3JtUHVzaEJvZHlGb3JMb2NhbGUoYm9keSwgbG9jYWxlKTtcbiAgICByZXR1cm4gbWVtbztcbiAgfSwge30pO1xuICAvLyBTZXQgdGhlIGRlZmF1bHQgbG9jYWxlLCB3aXRoIHRoZSBzdHJpcHBlZCBib2R5XG4gIHJlc3VsdC5kZWZhdWx0ID0gc3RyaXBMb2NhbGVzRnJvbUJvZHkoYm9keSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBncm91cEJ5TG9jYWxlSWRlbnRpZmllcihpbnN0YWxsYXRpb25zLCBsb2NhbGVzID0gW10pIHtcbiAgcmV0dXJuIGluc3RhbGxhdGlvbnMucmVkdWNlKChtYXAsIGluc3RhbGxhdGlvbikgPT4ge1xuICAgIGxldCBhZGRlZCA9IGZhbHNlO1xuICAgIGxvY2FsZXMuZm9yRWFjaCgobG9jYWxlKSA9PiB7XG4gICAgICBpZiAoYWRkZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGluc3RhbGxhdGlvbi5sb2NhbGVJZGVudGlmaWVyICYmIGluc3RhbGxhdGlvbi5sb2NhbGVJZGVudGlmaWVyLmluZGV4T2YobG9jYWxlKSA9PT0gMCkge1xuICAgICAgICBhZGRlZCA9IHRydWU7XG4gICAgICAgIG1hcFtsb2NhbGVdID0gbWFwW2xvY2FsZV0gfHwgW107XG4gICAgICAgIG1hcFtsb2NhbGVdLnB1c2goaW5zdGFsbGF0aW9uKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoIWFkZGVkKSB7XG4gICAgICBtYXAuZGVmYXVsdC5wdXNoKGluc3RhbGxhdGlvbik7XG4gICAgfVxuICAgIHJldHVybiBtYXA7XG4gIH0sIHtkZWZhdWx0OiBbXX0pO1xufVxuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgdGhlIGRldmljZVR5cGUgcGFyYW1ldGVyIGluIHF1cnkgY29uZGl0aW9uIGlzIHZhbGlkIG9yIG5vdC5cbiAqIEBwYXJhbSB7T2JqZWN0fSB3aGVyZSBBIHF1ZXJ5IGNvbmRpdGlvblxuICogQHBhcmFtIHtBcnJheX0gdmFsaWRQdXNoVHlwZXMgQW4gYXJyYXkgb2YgdmFsaWQgcHVzaCB0eXBlcyhzdHJpbmcpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVB1c2hUeXBlKHdoZXJlID0ge30sIHZhbGlkUHVzaFR5cGVzID0gW10pIHtcbiAgdmFyIGRldmljZVR5cGVGaWVsZCA9IHdoZXJlLmRldmljZVR5cGUgfHwge307XG4gIHZhciBkZXZpY2VUeXBlcyA9IFtdO1xuICBpZiAodHlwZW9mIGRldmljZVR5cGVGaWVsZCA9PT0gJ3N0cmluZycpIHtcbiAgICBkZXZpY2VUeXBlcy5wdXNoKGRldmljZVR5cGVGaWVsZCk7XG4gIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShkZXZpY2VUeXBlRmllbGRbJyRpbiddKSkge1xuICAgIGRldmljZVR5cGVzLmNvbmNhdChkZXZpY2VUeXBlRmllbGRbJyRpbiddKTtcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGRldmljZVR5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGRldmljZVR5cGUgPSBkZXZpY2VUeXBlc1tpXTtcbiAgICBpZiAodmFsaWRQdXNoVHlwZXMuaW5kZXhPZihkZXZpY2VUeXBlKSA8IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGRldmljZVR5cGUgKyAnIGlzIG5vdCBzdXBwb3J0ZWQgcHVzaCB0eXBlLicpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyh3aGVyZSkge1xuICB3aGVyZSA9IGRlZXBjb3B5KHdoZXJlKTtcbiAgaWYgKCF3aGVyZS5oYXNPd25Qcm9wZXJ0eSgnZGV2aWNlVG9rZW4nKSkge1xuICAgIHdoZXJlWydkZXZpY2VUb2tlbiddID0geyckZXhpc3RzJzogdHJ1ZX07XG4gIH1cbiAgcmV0dXJuIHdoZXJlO1xufVxuIl19 \ No newline at end of file diff --git a/lib/RestQuery.js b/lib/RestQuery.js index ffa99c6c16..f73c134abe 100644 --- a/lib/RestQuery.js +++ b/lib/RestQuery.js @@ -26,11 +26,12 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl this.clientSDK = clientSDK; this.response = null; this.findOptions = {}; + this.isWrite = false; + if (!this.auth.isMaster) { - this.findOptions.acl = this.auth.user ? [this.auth.user.id] : null; if (this.className == '_Session') { - if (!this.findOptions.acl) { - throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'This session token is invalid.'); + if (!this.auth.user) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } this.restWhere = { '$and': [this.restWhere, { @@ -45,6 +46,7 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl } 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, @@ -88,6 +90,9 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl case 'count': this.doCount = true; break; + case 'includeAll': + this.includeAll = true; + break; case 'distinct': case 'pipeline': case 'skip': @@ -151,6 +156,8 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl RestQuery.prototype.execute = function (executeOptions) { return Promise.resolve().then(() => { return this.buildRestWhere(); + }).then(() => { + return this.handleIncludeAll(); }).then(() => { return this.runFind(executeOptions); }).then(() => { @@ -184,17 +191,28 @@ RestQuery.prototype.buildRestWhere = function () { }); }; +// Marks the query for a write attempt, so we read the proper ACL (write instead of read) +RestQuery.prototype.forWrite = function () { + this.isWrite = true; + return this; +}; + // Uses the Auth object to get the list of roles, adds the user id RestQuery.prototype.getUserAndRoleACL = function () { - if (this.auth.isMaster || !this.auth.user) { + if (this.auth.isMaster) { return Promise.resolve(); } - return this.auth.getUserRoles().then(roles => { - // Concat with the roles to prevent duplications on multiple calls - const aclSet = new Set([].concat(this.findOptions.acl, roles)); - this.findOptions.acl = Array.from(aclSet); + + 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. @@ -497,6 +515,9 @@ RestQuery.prototype.runFind = function (options = {}) { if (options.op) { findOptions.op = options.op; } + if (this.isWrite) { + findOptions.isWrite = true; + } return this.config.database.find(this.className, this.restWhere, findOptions).then(results => { if (this.className === '_User') { for (var result of results) { @@ -530,6 +551,29 @@ RestQuery.prototype.runCount = function () { }); }; +// 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])]; + } + }); +}; + // Augments this.response with data at the paths provided in this.include. RestQuery.prototype.handleInclude = function () { if (this.include.length == 0) { @@ -567,7 +611,18 @@ RestQuery.prototype.runAfterFindTrigger = function () { } // 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 => { - this.response.results = 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; + } }); }; @@ -753,4 +808,5 @@ function findObjectWithKey(root, key) { } } -module.exports = RestQuery; \ No newline at end of file +module.exports = RestQuery; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9SZXN0UXVlcnkuanMiXSwibmFtZXMiOlsiU2NoZW1hQ29udHJvbGxlciIsInJlcXVpcmUiLCJQYXJzZSIsInRyaWdnZXJzIiwiQWx3YXlzU2VsZWN0ZWRLZXlzIiwiUmVzdFF1ZXJ5IiwiY29uZmlnIiwiYXV0aCIsImNsYXNzTmFtZSIsInJlc3RXaGVyZSIsInJlc3RPcHRpb25zIiwiY2xpZW50U0RLIiwicmVzcG9uc2UiLCJmaW5kT3B0aW9ucyIsImlzV3JpdGUiLCJpc01hc3RlciIsInVzZXIiLCJFcnJvciIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsIl9fdHlwZSIsIm9iamVjdElkIiwiaWQiLCJkb0NvdW50IiwiaW5jbHVkZUFsbCIsImluY2x1ZGUiLCJoYXNPd25Qcm9wZXJ0eSIsImtleXNGb3JJbmNsdWRlIiwia2V5cyIsInNwbGl0IiwiZmlsdGVyIiwia2V5IiwibGVuZ3RoIiwibWFwIiwic2xpY2UiLCJsYXN0SW5kZXhPZiIsImpvaW4iLCJvcHRpb24iLCJjb25jYXQiLCJBcnJheSIsImZyb20iLCJTZXQiLCJmaWVsZHMiLCJvcmRlciIsInNvcnQiLCJyZWR1Y2UiLCJzb3J0TWFwIiwiZmllbGQiLCJ0cmltIiwic2NvcmUiLCIkbWV0YSIsInBhdGhzIiwicGF0aFNldCIsIm1lbW8iLCJwYXRoIiwiaW5kZXgiLCJwYXJ0cyIsIk9iamVjdCIsInMiLCJhIiwiYiIsInJlZGlyZWN0S2V5IiwicmVkaXJlY3RDbGFzc05hbWVGb3JLZXkiLCJyZWRpcmVjdENsYXNzTmFtZSIsIklOVkFMSURfSlNPTiIsInByb3RvdHlwZSIsImV4ZWN1dGUiLCJleGVjdXRlT3B0aW9ucyIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsImJ1aWxkUmVzdFdoZXJlIiwiaGFuZGxlSW5jbHVkZUFsbCIsInJ1bkZpbmQiLCJydW5Db3VudCIsImhhbmRsZUluY2x1ZGUiLCJydW5BZnRlckZpbmRUcmlnZ2VyIiwiZ2V0VXNlckFuZFJvbGVBQ0wiLCJ2YWxpZGF0ZUNsaWVudENsYXNzQ3JlYXRpb24iLCJyZXBsYWNlU2VsZWN0IiwicmVwbGFjZURvbnRTZWxlY3QiLCJyZXBsYWNlSW5RdWVyeSIsInJlcGxhY2VOb3RJblF1ZXJ5IiwicmVwbGFjZUVxdWFsaXR5IiwiZm9yV3JpdGUiLCJhY2wiLCJnZXRVc2VyUm9sZXMiLCJyb2xlcyIsImRhdGFiYXNlIiwibmV3Q2xhc3NOYW1lIiwiYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uIiwic3lzdGVtQ2xhc3NlcyIsImluZGV4T2YiLCJsb2FkU2NoZW1hIiwic2NoZW1hQ29udHJvbGxlciIsImhhc0NsYXNzIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsInRyYW5zZm9ybUluUXVlcnkiLCJpblF1ZXJ5T2JqZWN0IiwicmVzdWx0cyIsInZhbHVlcyIsInJlc3VsdCIsInB1c2giLCJpc0FycmF5IiwiZmluZE9iamVjdFdpdGhLZXkiLCJpblF1ZXJ5VmFsdWUiLCJ3aGVyZSIsIklOVkFMSURfUVVFUlkiLCJhZGRpdGlvbmFsT3B0aW9ucyIsInN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UiLCJyZWFkUHJlZmVyZW5jZSIsInN1YnF1ZXJ5IiwidHJhbnNmb3JtTm90SW5RdWVyeSIsIm5vdEluUXVlcnlPYmplY3QiLCJub3RJblF1ZXJ5VmFsdWUiLCJ0cmFuc2Zvcm1TZWxlY3QiLCJzZWxlY3RPYmplY3QiLCJvYmplY3RzIiwibyIsImkiLCJzZWxlY3RWYWx1ZSIsInF1ZXJ5IiwidHJhbnNmb3JtRG9udFNlbGVjdCIsImRvbnRTZWxlY3RPYmplY3QiLCJkb250U2VsZWN0VmFsdWUiLCJjbGVhblJlc3VsdE9mU2Vuc2l0aXZlVXNlckluZm8iLCJwYXNzd29yZCIsInVzZXJTZW5zaXRpdmVGaWVsZHMiLCJjbGVhblJlc3VsdEF1dGhEYXRhIiwiYXV0aERhdGEiLCJmb3JFYWNoIiwicHJvdmlkZXIiLCJyZXBsYWNlRXF1YWxpdHlDb25zdHJhaW50IiwiY29uc3RyYWludCIsImVxdWFsVG9PYmplY3QiLCJoYXNEaXJlY3RDb25zdHJhaW50IiwiaGFzT3BlcmF0b3JDb25zdHJhaW50Iiwib3B0aW9ucyIsImxpbWl0IiwiYXNzaWduIiwib3AiLCJmaW5kIiwiZmlsZXNDb250cm9sbGVyIiwiZXhwYW5kRmlsZXNJbk9iamVjdCIsInIiLCJjb3VudCIsInNraXAiLCJjIiwiZ2V0T25lU2NoZW1hIiwic2NoZW1hIiwiaW5jbHVkZUZpZWxkcyIsImtleUZpZWxkcyIsInR5cGUiLCJwYXRoUmVzcG9uc2UiLCJpbmNsdWRlUGF0aCIsIm5ld1Jlc3BvbnNlIiwiaGFzQWZ0ZXJGaW5kSG9vayIsInRyaWdnZXJFeGlzdHMiLCJUeXBlcyIsImFmdGVyRmluZCIsImFwcGxpY2F0aW9uSWQiLCJwaXBlbGluZSIsImRpc3RpbmN0IiwibWF5YmVSdW5BZnRlckZpbmRUcmlnZ2VyIiwib2JqZWN0IiwidG9KU09OIiwicG9pbnRlcnMiLCJmaW5kUG9pbnRlcnMiLCJwb2ludGVyc0hhc2giLCJwb2ludGVyIiwiYWRkIiwiaW5jbHVkZVJlc3RPcHRpb25zIiwia2V5U2V0Iiwic2V0Iiwia2V5UGF0aCIsInNpemUiLCJpbmNsdWRlUmVhZFByZWZlcmVuY2UiLCJxdWVyeVByb21pc2VzIiwib2JqZWN0SWRzIiwiYWxsIiwicmVzcG9uc2VzIiwicmVwbGFjZSIsImluY2x1ZGVSZXNwb25zZSIsIm9iaiIsInNlc3Npb25Ub2tlbiIsInJlc3AiLCJyZXBsYWNlUG9pbnRlcnMiLCJhbnN3ZXIiLCJ4Iiwic3Vib2JqZWN0IiwibmV3c3ViIiwicm9vdCIsIml0ZW0iLCJzdWJrZXkiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7O0FBRUEsSUFBSUEsbUJBQW1CQyxRQUFRLGdDQUFSLENBQXZCO0FBQ0EsSUFBSUMsUUFBUUQsUUFBUSxZQUFSLEVBQXNCQyxLQUFsQztBQUNBLE1BQU1DLFdBQVdGLFFBQVEsWUFBUixDQUFqQjs7QUFFQSxNQUFNRyxxQkFBcUIsQ0FBQyxVQUFELEVBQWEsV0FBYixFQUEwQixXQUExQixDQUEzQjtBQUNBO0FBQ0E7QUFD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QUNyQixXQUFPZ0ssSUFBUDtBQUNEO0FBQ0QsT0FBSyxJQUFJRSxNQUFULElBQW1CRixJQUFuQixFQUF5QjtBQUN2QixVQUFNSixTQUFTbkYsa0JBQWtCdUYsS0FBS0UsTUFBTCxDQUFsQixFQUFnQ2xLLEdBQWhDLENBQWY7QUFDQSxRQUFJNEosTUFBSixFQUFZO0FBQ1YsYUFBT0EsTUFBUDtBQUNEO0FBQ0Y7QUFDRjs7QUFFRE8sT0FBT0MsT0FBUCxHQUFpQjdMLFNBQWpCIiwiZmlsZSI6IlJlc3RRdWVyeS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFuIG9iamVjdCB0aGF0IGVuY2Fwc3VsYXRlcyBldmVyeXRoaW5nIHdlIG5lZWQgdG8gcnVuIGEgJ2ZpbmQnXG4vLyBvcGVyYXRpb24sIGVuY29kZWQgaW4gdGhlIFJFU1QgQVBJIGZvcm1hdC5cblxudmFyIFNjaGVtYUNvbnRyb2xsZXIgPSByZXF1aXJlKCcuL0NvbnRyb2xsZXJzL1NjaGVtYUNvbnRyb2xsZXInKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IHRyaWdnZXJzID0gcmVxdWlyZSgnLi90cmlnZ2VycycpO1xuXG5jb25zdCBBbHdheXNTZWxlY3RlZEtleXMgPSBbJ29iamVjdElkJywgJ2NyZWF0ZWRBdCcsICd1cGRhdGVkQXQnXTtcbi8vIHJlc3RPcHRpb25zIGNhbiBpbmNsdWRlOlxuLy8gICBza2lwXG4vLyAgIGxpbWl0XG4vLyAgIG9yZGVyXG4vLyAgIGNvdW50XG4vLyAgIGluY2x1ZGVcbi8vICAga2V5c1xuLy8gICByZWRpcmVjdENsYXNzTmFtZUZvcktleVxuZnVuY3Rpb24gUmVzdFF1ZXJ5KGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUgPSB7fSwgcmVzdE9wdGlvbnMgPSB7fSwgY2xpZW50U0RLKSB7XG5cbiAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gIHRoaXMuYXV0aCA9IGF1dGg7XG4gIHRoaXMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICB0aGlzLnJlc3RXaGVyZSA9IHJlc3RXaGVyZTtcbiAgdGhpcy5yZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zO1xuICB0aGlzLmNsaWVudFNESyA9IGNsaWVudFNESztcbiAgdGhpcy5yZXNwb25zZSA9IG51bGw7XG4gIHRoaXMuZmluZE9wdGlvbnMgPSB7fTtcbiAgdGhpcy5pc1dyaXRlID0gZmFsc2U7XG5cbiAgaWYgKCF0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICBpZiAodGhpcy5jbGFzc05hbWUgPT0gJ19TZXNzaW9uJykge1xuICAgICAgaWYgKCF0aGlzLmF1dGgudXNlcikge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICdJbnZhbGlkIHNlc3Npb24gdG9rZW4nKTtcbiAgICAgIH1cbiAgICAgIHRoaXMucmVzdFdoZXJlID0ge1xuICAgICAgICAnJGFuZCc6IFt0aGlzLnJlc3RXaGVyZSwge1xuICAgICAgICAgICd1c2VyJzoge1xuICAgICAgICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICAgICAgICBjbGFzc05hbWU6ICdfVXNlcicsXG4gICAgICAgICAgICBvYmplY3RJZDogdGhpcy5hdXRoLnVzZXIuaWRcbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHRoaXMuZG9Db3VudCA9IGZhbHNlO1xuICB0aGlzLmluY2x1ZGVBbGwgPSBmYWxzZTtcblxuICAvLyBUaGUgZm9ybWF0IGZvciB0aGlzLmluY2x1ZGUgaXMgbm90IHRoZSBzYW1lIGFzIHRoZSBmb3JtYXQgZm9yIHRoZVxuICAvLyBpbmNsdWRlIG9wdGlvbiAtIGl0J3MgdGhlIHBhdGhzIHdlIHNob3VsZCBpbmNsdWRlLCBpbiBvcmRlcixcbiAgLy8gc3RvcmVkIGFzIGFycmF5cywgdGFraW5nIGludG8gYWNjb3VudCB0aGF0IHdlIG5lZWQgdG8gaW5jbHVkZSBmb29cbiAgLy8gYmVmb3JlIGluY2x1ZGluZyBmb28uYmFyLiBBbHNvIGl0IHNob3VsZCBkZWR1cGUuXG4gIC8vIEZvciBleGFtcGxlLCBwYXNzaW5nIGFuIGFyZyBvZiBpbmNsdWRlPWZvby5iYXIsZm9vLmJheiBjb3VsZCBsZWFkIHRvXG4gIC8vIHRoaXMuaW5jbHVkZSA9IFtbJ2ZvbyddLCBbJ2ZvbycsICdiYXonXSwgWydmb28nLCAnYmFyJ11dXG4gIHRoaXMuaW5jbHVkZSA9IFtdO1xuXG4gIC8vIElmIHdlIGhhdmUga2V5cywgd2UgcHJvYmFibHkgd2FudCB0byBmb3JjZSBzb21lIGluY2x1ZGVzIChuLTEgbGV2ZWwpXG4gIC8vIFNlZSBpc3N1ZTogaHR0cHM6Ly9naXRodWIuY29tL3BhcnNlLWNvbW11bml0eS9wYXJzZS1zZXJ2ZXIvaXNzdWVzLzMxODVcbiAgaWYgKHJlc3RPcHRpb25zLmhhc093blByb3BlcnR5KCdrZXlzJykpIHtcbiAgICBjb25zdCBrZXlzRm9ySW5jbHVkZSA9IHJlc3RPcHRpb25zLmtleXMuc3BsaXQoJywnKS5maWx0ZXIoKGtleSkgPT4ge1xuICAgICAgLy8gQXQgbGVhc3QgMiBjb21wb25lbnRzXG4gICAgICByZXR1cm4ga2V5LnNwbGl0KFwiLlwiKS5sZW5ndGggPiAxO1xuICAgIH0pLm1hcCgoa2V5KSA9PiB7XG4gICAgICAvLyBTbGljZSB0aGUgbGFzdCBjb21wb25lbnQgKGEuYi5jIC0+IGEuYilcbiAgICAgIC8vIE90aGVyd2lzZSB3ZSdsbCBpbmNsdWRlIG9uZSBsZXZlbCB0b28gbXVjaC5cbiAgICAgIHJldHVybiBrZXkuc2xpY2UoMCwga2V5Lmxhc3RJbmRleE9mKFwiLlwiKSk7XG4gICAgfSkuam9pbignLCcpO1xuXG4gICAgLy8gQ29uY2F0IHRoZSBwb3NzaWJseSBwcmVzZW50IGluY2x1ZGUgc3RyaW5nIHdpdGggdGhlIG9uZSBmcm9tIHRoZSBrZXlzXG4gICAgLy8gRGVkdXAgLyBzb3J0aW5nIGlzIGhhbmRsZSBpbiAnaW5jbHVkZScgY2FzZS5cbiAgICBpZiAoa2V5c0ZvckluY2x1ZGUubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKCFyZXN0T3B0aW9ucy5pbmNsdWRlIHx8IHJlc3RPcHRpb25zLmluY2x1ZGUubGVuZ3RoID09IDApIHtcbiAgICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZSA9IGtleXNGb3JJbmNsdWRlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZSArPSBcIixcIiArIGtleXNGb3JJbmNsdWRlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZvciAodmFyIG9wdGlvbiBpbiByZXN0T3B0aW9ucykge1xuICAgIHN3aXRjaChvcHRpb24pIHtcbiAgICBjYXNlICdrZXlzJzoge1xuICAgICAgY29uc3Qga2V5cyA9IHJlc3RPcHRpb25zLmtleXMuc3BsaXQoJywnKS5jb25jYXQoQWx3YXlzU2VsZWN0ZWRLZXlzKTtcbiAgICAgIHRoaXMua2V5cyA9IEFycmF5LmZyb20obmV3IFNldChrZXlzKSk7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY2FzZSAnY291bnQnOlxuICAgICAgdGhpcy5kb0NvdW50ID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2luY2x1ZGVBbGwnOlxuICAgICAgdGhpcy5pbmNsdWRlQWxsID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2Rpc3RpbmN0JzpcbiAgICBjYXNlICdwaXBlbGluZSc6XG4gICAgY2FzZSAnc2tpcCc6XG4gICAgY2FzZSAnbGltaXQnOlxuICAgIGNhc2UgJ3JlYWRQcmVmZXJlbmNlJzpcbiAgICAgIHRoaXMuZmluZE9wdGlvbnNbb3B0aW9uXSA9IHJlc3RPcHRpb25zW29wdGlvbl07XG4gICAgICBicmVhaztcbiAgICBjYXNlICdvcmRlcic6XG4gICAgICB2YXIgZmllbGRzID0gcmVzdE9wdGlvbnMub3JkZXIuc3BsaXQoJywnKTtcbiAgICAgIHRoaXMuZmluZE9wdGlvbnMuc29ydCA9IGZpZWxkcy5yZWR1Y2UoKHNvcnRNYXAsIGZpZWxkKSA9PiB7XG4gICAgICAgIGZpZWxkID0gZmllbGQudHJpbSgpO1xuICAgICAgICBpZiAoZmllbGQgPT09ICckc2NvcmUnKSB7XG4gICAgICAgICAgc29ydE1hcC5zY29yZSA9IHskbWV0YTogJ3RleHRTY29yZSd9O1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkWzBdID09ICctJykge1xuICAgICAgICAgIHNvcnRNYXBbZmllbGQuc2xpY2UoMSldID0gLTE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc29ydE1hcFtmaWVsZF0gPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzb3J0TWFwO1xuICAgICAgfSwge30pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaW5jbHVkZSc6IHtcbiAgICAgIGNvbnN0IHBhdGhzID0gcmVzdE9wdGlvbnMuaW5jbHVkZS5zcGxpdCgnLCcpO1xuICAgICAgLy8gTG9hZCB0aGUgZXhpc3RpbmcgaW5jbHVkZXMgKGZyb20ga2V5cylcbiAgICAgIGNvbnN0IHBhdGhTZXQgPSBwYXRocy5yZWR1Y2UoKG1lbW8sIHBhdGgpID0+IHtcbiAgICAgICAgLy8gU3BsaXQgZWFjaCBwYXRocyBvbiAuIChhLmIuYyAtPiBbYSxiLGNdKVxuICAgICAgICAvLyByZWR1Y2UgdG8gY3JlYXRlIGFsbCBwYXRoc1xuICAgICAgICAvLyAoW2EsYixjXSAtPiB7YTogdHJ1ZSwgJ2EuYic6IHRydWUsICdhLmIuYyc6IHRydWV9KVxuICAgICAgICByZXR1cm4gcGF0aC5zcGxpdCgnLicpLnJlZHVjZSgobWVtbywgcGF0aCwgaW5kZXgsIHBhcnRzKSA9PiB7XG4gICAgICAgICAgbWVtb1twYXJ0cy5zbGljZSgwLCBpbmRleCArIDEpLmpvaW4oJy4nKV0gPSB0cnVlO1xuICAgICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgICB9LCBtZW1vKTtcbiAgICAgIH0sIHt9KTtcblxuICAgICAgdGhpcy5pbmNsdWRlID0gT2JqZWN0LmtleXMocGF0aFNldCkubWFwKChzKSA9PiB7XG4gICAgICAgIHJldHVybiBzLnNwbGl0KCcuJyk7XG4gICAgICB9KS5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgIHJldHVybiBhLmxlbmd0aCAtIGIubGVuZ3RoOyAvLyBTb3J0IGJ5IG51bWJlciBvZiBjb21wb25lbnRzXG4gICAgICB9KTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjYXNlICdyZWRpcmVjdENsYXNzTmFtZUZvcktleSc6XG4gICAgICB0aGlzLnJlZGlyZWN0S2V5ID0gcmVzdE9wdGlvbnMucmVkaXJlY3RDbGFzc05hbWVGb3JLZXk7XG4gICAgICB0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lID0gbnVsbDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2luY2x1ZGVSZWFkUHJlZmVyZW5jZSc6XG4gICAgY2FzZSAnc3VicXVlcnlSZWFkUHJlZmVyZW5jZSc6XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgJ2JhZCBvcHRpb246ICcgKyBvcHRpb24pO1xuICAgIH1cbiAgfVxufVxuXG4vLyBBIGNvbnZlbmllbnQgbWV0aG9kIHRvIHBlcmZvcm0gYWxsIHRoZSBzdGVwcyBvZiBwcm9jZXNzaW5nIGEgcXVlcnlcbi8vIGluIG9yZGVyLlxuLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSByZXNwb25zZSAtIGFuIG9iamVjdCB3aXRoIG9wdGlvbmFsIGtleXNcbi8vICdyZXN1bHRzJyBhbmQgJ2NvdW50Jy5cbi8vIFRPRE86IGNvbnNvbGlkYXRlIHRoZSByZXBsYWNlWCBmdW5jdGlvbnNcblJlc3RRdWVyeS5wcm90b3R5cGUuZXhlY3V0ZSA9IGZ1bmN0aW9uKGV4ZWN1dGVPcHRpb25zKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5idWlsZFJlc3RXaGVyZSgpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVJbmNsdWRlQWxsKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnJ1bkZpbmQoZXhlY3V0ZU9wdGlvbnMpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5ydW5Db3VudCgpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVJbmNsdWRlKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnJ1bkFmdGVyRmluZFRyaWdnZXIoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucmVzcG9uc2U7XG4gIH0pO1xufTtcblxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5idWlsZFJlc3RXaGVyZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VXNlckFuZFJvbGVBQ0woKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucmVkaXJlY3RDbGFzc05hbWVGb3JLZXkoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGVDbGllbnRDbGFzc0NyZWF0aW9uKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2VTZWxlY3QoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZURvbnRTZWxlY3QoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZUluUXVlcnkoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZU5vdEluUXVlcnkoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZUVxdWFsaXR5KCk7XG4gIH0pO1xufVxuXG4vLyBNYXJrcyB0aGUgcXVlcnkgZm9yIGEgd3JpdGUgYXR0ZW1wdCwgc28gd2UgcmVhZCB0aGUgcHJvcGVyIEFDTCAod3JpdGUgaW5zdGVhZCBvZiByZWFkKVxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5mb3JXcml0ZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmlzV3JpdGUgPSB0cnVlO1xuICByZXR1cm4gdGhpcztcbn1cblxuLy8gVXNlcyB0aGUgQXV0aCBvYmplY3QgdG8gZ2V0IHRoZSBsaXN0IG9mIHJvbGVzLCBhZGRzIHRoZSB1c2VyIGlkXG5SZXN0UXVlcnkucHJvdG90eXBlLmdldFVzZXJBbmRSb2xlQUNMID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICB0aGlzLmZpbmRPcHRpb25zLmFjbCA9IFsnKiddO1xuXG4gIGlmICh0aGlzLmF1dGgudXNlcikge1xuICAgIHJldHVybiB0aGlzLmF1dGguZ2V0VXNlclJvbGVzKCkudGhlbigocm9sZXMpID0+IHtcbiAgICAgIHRoaXMuZmluZE9wdGlvbnMuYWNsID0gdGhpcy5maW5kT3B0aW9ucy5hY2wuY29uY2F0KHJvbGVzLCBbdGhpcy5hdXRoLnVzZXIuaWRdKTtcbiAgICAgIHJldHVybjtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn07XG5cbi8vIENoYW5nZXMgdGhlIGNsYXNzTmFtZSBpZiByZWRpcmVjdENsYXNzTmFtZUZvcktleSBpcyBzZXQuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZS5cblJlc3RRdWVyeS5wcm90b3R5cGUucmVkaXJlY3RDbGFzc05hbWVGb3JLZXkgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLnJlZGlyZWN0S2V5KSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgLy8gV2UgbmVlZCB0byBjaGFuZ2UgdGhlIGNsYXNzIG5hbWUgYmFzZWQgb24gdGhlIHNjaGVtYVxuICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UucmVkaXJlY3RDbGFzc05hbWVGb3JLZXkodGhpcy5jbGFzc05hbWUsIHRoaXMucmVkaXJlY3RLZXkpXG4gICAgLnRoZW4oKG5ld0NsYXNzTmFtZSkgPT4ge1xuICAgICAgdGhpcy5jbGFzc05hbWUgPSBuZXdDbGFzc05hbWU7XG4gICAgICB0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lID0gbmV3Q2xhc3NOYW1lO1xuICAgIH0pO1xufTtcblxuLy8gVmFsaWRhdGVzIHRoaXMgb3BlcmF0aW9uIGFnYWluc3QgdGhlIGFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiBjb25maWcuXG5SZXN0UXVlcnkucHJvdG90eXBlLnZhbGlkYXRlQ2xpZW50Q2xhc3NDcmVhdGlvbiA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5jb25maWcuYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uID09PSBmYWxzZSAmJiAhdGhpcy5hdXRoLmlzTWFzdGVyXG4gICAgICAmJiBTY2hlbWFDb250cm9sbGVyLnN5c3RlbUNsYXNzZXMuaW5kZXhPZih0aGlzLmNsYXNzTmFtZSkgPT09IC0xKSB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLmxvYWRTY2hlbWEoKVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmhhc0NsYXNzKHRoaXMuY2xhc3NOYW1lKSlcbiAgICAgIC50aGVuKGhhc0NsYXNzID0+IHtcbiAgICAgICAgaWYgKGhhc0NsYXNzICE9PSB0cnVlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sXG4gICAgICAgICAgICAnVGhpcyB1c2VyIGlzIG5vdCBhbGxvd2VkIHRvIGFjY2VzcyAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25vbi1leGlzdGVudCBjbGFzczogJyArIHRoaXMuY2xhc3NOYW1lKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG59O1xuXG5mdW5jdGlvbiB0cmFuc2Zvcm1JblF1ZXJ5KGluUXVlcnlPYmplY3QsIGNsYXNzTmFtZSwgcmVzdWx0cykge1xuICB2YXIgdmFsdWVzID0gW107XG4gIGZvciAodmFyIHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgdmFsdWVzLnB1c2goe1xuICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgIG9iamVjdElkOiByZXN1bHQub2JqZWN0SWRcbiAgICB9KTtcbiAgfVxuICBkZWxldGUgaW5RdWVyeU9iamVjdFsnJGluUXVlcnknXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoaW5RdWVyeU9iamVjdFsnJGluJ10pKSB7XG4gICAgaW5RdWVyeU9iamVjdFsnJGluJ10gPSBpblF1ZXJ5T2JqZWN0WyckaW4nXS5jb25jYXQodmFsdWVzKTtcbiAgfSBlbHNlIHtcbiAgICBpblF1ZXJ5T2JqZWN0WyckaW4nXSA9IHZhbHVlcztcbiAgfVxufVxuXG4vLyBSZXBsYWNlcyBhICRpblF1ZXJ5IGNsYXVzZSBieSBydW5uaW5nIHRoZSBzdWJxdWVyeSwgaWYgdGhlcmUgaXMgYW5cbi8vICRpblF1ZXJ5IGNsYXVzZS5cbi8vIFRoZSAkaW5RdWVyeSBjbGF1c2UgdHVybnMgaW50byBhbiAkaW4gd2l0aCB2YWx1ZXMgdGhhdCBhcmUganVzdFxuLy8gcG9pbnRlcnMgdG8gdGhlIG9iamVjdHMgcmV0dXJuZWQgaW4gdGhlIHN1YnF1ZXJ5LlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZXBsYWNlSW5RdWVyeSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgaW5RdWVyeU9iamVjdCA9IGZpbmRPYmplY3RXaXRoS2V5KHRoaXMucmVzdFdoZXJlLCAnJGluUXVlcnknKTtcbiAgaWYgKCFpblF1ZXJ5T2JqZWN0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVGhlIGluUXVlcnkgdmFsdWUgbXVzdCBoYXZlIHByZWNpc2VseSB0d28ga2V5cyAtIHdoZXJlIGFuZCBjbGFzc05hbWVcbiAgdmFyIGluUXVlcnlWYWx1ZSA9IGluUXVlcnlPYmplY3RbJyRpblF1ZXJ5J107XG4gIGlmICghaW5RdWVyeVZhbHVlLndoZXJlIHx8ICFpblF1ZXJ5VmFsdWUuY2xhc3NOYW1lKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAnaW1wcm9wZXIgdXNhZ2Ugb2YgJGluUXVlcnknKTtcbiAgfVxuXG4gIGNvbnN0IGFkZGl0aW9uYWxPcHRpb25zID0ge1xuICAgIHJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5OiBpblF1ZXJ5VmFsdWUucmVkaXJlY3RDbGFzc05hbWVGb3JLZXksXG4gICAga2V5czogJ29iamVjdElkJ1xuICB9O1xuXG4gIGlmICh0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgdmFyIHN1YnF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShcbiAgICB0aGlzLmNvbmZpZywgdGhpcy5hdXRoLCBpblF1ZXJ5VmFsdWUuY2xhc3NOYW1lLFxuICAgIGluUXVlcnlWYWx1ZS53aGVyZSwgYWRkaXRpb25hbE9wdGlvbnMpO1xuICByZXR1cm4gc3VicXVlcnkuZXhlY3V0ZSgpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgdHJhbnNmb3JtSW5RdWVyeShpblF1ZXJ5T2JqZWN0LCBzdWJxdWVyeS5jbGFzc05hbWUsIHJlc3BvbnNlLnJlc3VsdHMpO1xuICAgIC8vIFJlY3Vyc2UgdG8gcmVwZWF0XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZUluUXVlcnkoKTtcbiAgfSk7XG59O1xuXG5mdW5jdGlvbiB0cmFuc2Zvcm1Ob3RJblF1ZXJ5KG5vdEluUXVlcnlPYmplY3QsIGNsYXNzTmFtZSwgcmVzdWx0cykge1xuICB2YXIgdmFsdWVzID0gW107XG4gIGZvciAodmFyIHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgdmFsdWVzLnB1c2goe1xuICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgIG9iamVjdElkOiByZXN1bHQub2JqZWN0SWRcbiAgICB9KTtcbiAgfVxuICBkZWxldGUgbm90SW5RdWVyeU9iamVjdFsnJG5vdEluUXVlcnknXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkobm90SW5RdWVyeU9iamVjdFsnJG5pbiddKSkge1xuICAgIG5vdEluUXVlcnlPYmplY3RbJyRuaW4nXSA9IG5vdEluUXVlcnlPYmplY3RbJyRuaW4nXS5jb25jYXQodmFsdWVzKTtcbiAgfSBlbHNlIHtcbiAgICBub3RJblF1ZXJ5T2JqZWN0WyckbmluJ10gPSB2YWx1ZXM7XG4gIH1cbn1cblxuLy8gUmVwbGFjZXMgYSAkbm90SW5RdWVyeSBjbGF1c2UgYnkgcnVubmluZyB0aGUgc3VicXVlcnksIGlmIHRoZXJlIGlzIGFuXG4vLyAkbm90SW5RdWVyeSBjbGF1c2UuXG4vLyBUaGUgJG5vdEluUXVlcnkgY2xhdXNlIHR1cm5zIGludG8gYSAkbmluIHdpdGggdmFsdWVzIHRoYXQgYXJlIGp1c3Rcbi8vIHBvaW50ZXJzIHRvIHRoZSBvYmplY3RzIHJldHVybmVkIGluIHRoZSBzdWJxdWVyeS5cblJlc3RRdWVyeS5wcm90b3R5cGUucmVwbGFjZU5vdEluUXVlcnkgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG5vdEluUXVlcnlPYmplY3QgPSBmaW5kT2JqZWN0V2l0aEtleSh0aGlzLnJlc3RXaGVyZSwgJyRub3RJblF1ZXJ5Jyk7XG4gIGlmICghbm90SW5RdWVyeU9iamVjdCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFRoZSBub3RJblF1ZXJ5IHZhbHVlIG11c3QgaGF2ZSBwcmVjaXNlbHkgdHdvIGtleXMgLSB3aGVyZSBhbmQgY2xhc3NOYW1lXG4gIHZhciBub3RJblF1ZXJ5VmFsdWUgPSBub3RJblF1ZXJ5T2JqZWN0Wyckbm90SW5RdWVyeSddO1xuICBpZiAoIW5vdEluUXVlcnlWYWx1ZS53aGVyZSB8fCAhbm90SW5RdWVyeVZhbHVlLmNsYXNzTmFtZSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgJ2ltcHJvcGVyIHVzYWdlIG9mICRub3RJblF1ZXJ5Jyk7XG4gIH1cblxuICBjb25zdCBhZGRpdGlvbmFsT3B0aW9ucyA9IHtcbiAgICByZWRpcmVjdENsYXNzTmFtZUZvcktleTogbm90SW5RdWVyeVZhbHVlLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5LFxuICAgIGtleXM6ICdvYmplY3RJZCdcbiAgfTtcblxuICBpZiAodGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgYWRkaXRpb25hbE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgfVxuXG4gIHZhciBzdWJxdWVyeSA9IG5ldyBSZXN0UXVlcnkoXG4gICAgdGhpcy5jb25maWcsIHRoaXMuYXV0aCwgbm90SW5RdWVyeVZhbHVlLmNsYXNzTmFtZSxcbiAgICBub3RJblF1ZXJ5VmFsdWUud2hlcmUsIGFkZGl0aW9uYWxPcHRpb25zKTtcbiAgcmV0dXJuIHN1YnF1ZXJ5LmV4ZWN1dGUoKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgIHRyYW5zZm9ybU5vdEluUXVlcnkobm90SW5RdWVyeU9iamVjdCwgc3VicXVlcnkuY2xhc3NOYW1lLCByZXNwb25zZS5yZXN1bHRzKTtcbiAgICAvLyBSZWN1cnNlIHRvIHJlcGVhdFxuICAgIHJldHVybiB0aGlzLnJlcGxhY2VOb3RJblF1ZXJ5KCk7XG4gIH0pO1xufTtcblxuY29uc3QgdHJhbnNmb3JtU2VsZWN0ID0gKHNlbGVjdE9iamVjdCwga2V5ICxvYmplY3RzKSA9PiB7XG4gIHZhciB2YWx1ZXMgPSBbXTtcbiAgZm9yICh2YXIgcmVzdWx0IG9mIG9iamVjdHMpIHtcbiAgICB2YWx1ZXMucHVzaChrZXkuc3BsaXQoJy4nKS5yZWR1Y2UoKG8saSk9Pm9baV0sIHJlc3VsdCkpO1xuICB9XG4gIGRlbGV0ZSBzZWxlY3RPYmplY3RbJyRzZWxlY3QnXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoc2VsZWN0T2JqZWN0WyckaW4nXSkpIHtcbiAgICBzZWxlY3RPYmplY3RbJyRpbiddID0gc2VsZWN0T2JqZWN0WyckaW4nXS5jb25jYXQodmFsdWVzKTtcbiAgfSBlbHNlIHtcbiAgICBzZWxlY3RPYmplY3RbJyRpbiddID0gdmFsdWVzO1xuICB9XG59XG5cbi8vIFJlcGxhY2VzIGEgJHNlbGVjdCBjbGF1c2UgYnkgcnVubmluZyB0aGUgc3VicXVlcnksIGlmIHRoZXJlIGlzIGFcbi8vICRzZWxlY3QgY2xhdXNlLlxuLy8gVGhlICRzZWxlY3QgY2xhdXNlIHR1cm5zIGludG8gYW4gJGluIHdpdGggdmFsdWVzIHNlbGVjdGVkIG91dCBvZlxuLy8gdGhlIHN1YnF1ZXJ5LlxuLy8gUmV0dXJucyBhIHBvc3NpYmxlLXByb21pc2UuXG5SZXN0UXVlcnkucHJvdG90eXBlLnJlcGxhY2VTZWxlY3QgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHNlbGVjdE9iamVjdCA9IGZpbmRPYmplY3RXaXRoS2V5KHRoaXMucmVzdFdoZXJlLCAnJHNlbGVjdCcpO1xuICBpZiAoIXNlbGVjdE9iamVjdCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFRoZSBzZWxlY3QgdmFsdWUgbXVzdCBoYXZlIHByZWNpc2VseSB0d28ga2V5cyAtIHF1ZXJ5IGFuZCBrZXlcbiAgdmFyIHNlbGVjdFZhbHVlID0gc2VsZWN0T2JqZWN0Wyckc2VsZWN0J107XG4gIC8vIGlPUyBTREsgZG9uJ3Qgc2VuZCB3aGVyZSBpZiBub3Qgc2V0LCBsZXQgaXQgcGFzc1xuICBpZiAoIXNlbGVjdFZhbHVlLnF1ZXJ5IHx8XG4gICAgICAhc2VsZWN0VmFsdWUua2V5IHx8XG4gICAgICB0eXBlb2Ygc2VsZWN0VmFsdWUucXVlcnkgIT09ICdvYmplY3QnIHx8XG4gICAgICAhc2VsZWN0VmFsdWUucXVlcnkuY2xhc3NOYW1lIHx8XG4gICAgICBPYmplY3Qua2V5cyhzZWxlY3RWYWx1ZSkubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAnaW1wcm9wZXIgdXNhZ2Ugb2YgJHNlbGVjdCcpO1xuICB9XG5cbiAgY29uc3QgYWRkaXRpb25hbE9wdGlvbnMgPSB7XG4gICAgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXk6IHNlbGVjdFZhbHVlLnF1ZXJ5LnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5LFxuICAgIGtleXM6IHNlbGVjdFZhbHVlLmtleVxuICB9O1xuXG4gIGlmICh0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5yZWFkUHJlZmVyZW5jZSA9IHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZTtcbiAgICBhZGRpdGlvbmFsT3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgdmFyIHN1YnF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShcbiAgICB0aGlzLmNvbmZpZywgdGhpcy5hdXRoLCBzZWxlY3RWYWx1ZS5xdWVyeS5jbGFzc05hbWUsXG4gICAgc2VsZWN0VmFsdWUucXVlcnkud2hlcmUsIGFkZGl0aW9uYWxPcHRpb25zKTtcbiAgcmV0dXJuIHN1YnF1ZXJ5LmV4ZWN1dGUoKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgIHRyYW5zZm9ybVNlbGVjdChzZWxlY3RPYmplY3QsIHNlbGVjdFZhbHVlLmtleSwgcmVzcG9uc2UucmVzdWx0cyk7XG4gICAgLy8gS2VlcCByZXBsYWNpbmcgJHNlbGVjdCBjbGF1c2VzXG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZVNlbGVjdCgpO1xuICB9KVxufTtcblxuY29uc3QgdHJhbnNmb3JtRG9udFNlbGVjdCA9IChkb250U2VsZWN0T2JqZWN0LCBrZXksIG9iamVjdHMpID0+IHtcbiAgdmFyIHZhbHVlcyA9IFtdO1xuICBmb3IgKHZhciByZXN1bHQgb2Ygb2JqZWN0cykge1xuICAgIHZhbHVlcy5wdXNoKGtleS5zcGxpdCgnLicpLnJlZHVjZSgobyxpKT0+b1tpXSwgcmVzdWx0KSk7XG4gIH1cbiAgZGVsZXRlIGRvbnRTZWxlY3RPYmplY3RbJyRkb250U2VsZWN0J107XG4gIGlmIChBcnJheS5pc0FycmF5KGRvbnRTZWxlY3RPYmplY3RbJyRuaW4nXSkpIHtcbiAgICBkb250U2VsZWN0T2JqZWN0WyckbmluJ10gPSBkb250U2VsZWN0T2JqZWN0WyckbmluJ10uY29uY2F0KHZhbHVlcyk7XG4gIH0gZWxzZSB7XG4gICAgZG9udFNlbGVjdE9iamVjdFsnJG5pbiddID0gdmFsdWVzO1xuICB9XG59XG5cbi8vIFJlcGxhY2VzIGEgJGRvbnRTZWxlY3QgY2xhdXNlIGJ5IHJ1bm5pbmcgdGhlIHN1YnF1ZXJ5LCBpZiB0aGVyZSBpcyBhXG4vLyAkZG9udFNlbGVjdCBjbGF1c2UuXG4vLyBUaGUgJGRvbnRTZWxlY3QgY2xhdXNlIHR1cm5zIGludG8gYW4gJG5pbiB3aXRoIHZhbHVlcyBzZWxlY3RlZCBvdXQgb2Zcbi8vIHRoZSBzdWJxdWVyeS5cbi8vIFJldHVybnMgYSBwb3NzaWJsZS1wcm9taXNlLlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZXBsYWNlRG9udFNlbGVjdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZG9udFNlbGVjdE9iamVjdCA9IGZpbmRPYmplY3RXaXRoS2V5KHRoaXMucmVzdFdoZXJlLCAnJGRvbnRTZWxlY3QnKTtcbiAgaWYgKCFkb250U2VsZWN0T2JqZWN0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVGhlIGRvbnRTZWxlY3QgdmFsdWUgbXVzdCBoYXZlIHByZWNpc2VseSB0d28ga2V5cyAtIHF1ZXJ5IGFuZCBrZXlcbiAgdmFyIGRvbnRTZWxlY3RWYWx1ZSA9IGRvbnRTZWxlY3RPYmplY3RbJyRkb250U2VsZWN0J107XG4gIGlmICghZG9udFNlbGVjdFZhbHVlLnF1ZXJ5IHx8XG4gICAgICAhZG9udFNlbGVjdFZhbHVlLmtleSB8fFxuICAgICAgdHlwZW9mIGRvbnRTZWxlY3RWYWx1ZS5xdWVyeSAhPT0gJ29iamVjdCcgfHxcbiAgICAgICFkb250U2VsZWN0VmFsdWUucXVlcnkuY2xhc3NOYW1lIHx8XG4gICAgICBPYmplY3Qua2V5cyhkb250U2VsZWN0VmFsdWUpLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgJ2ltcHJvcGVyIHVzYWdlIG9mICRkb250U2VsZWN0Jyk7XG4gIH1cbiAgY29uc3QgYWRkaXRpb25hbE9wdGlvbnMgPSB7XG4gICAgcmVkaXJlY3RDbGFzc05hbWVGb3JLZXk6IGRvbnRTZWxlY3RWYWx1ZS5xdWVyeS5yZWRpcmVjdENsYXNzTmFtZUZvcktleSxcbiAgICBrZXlzOiBkb250U2VsZWN0VmFsdWUua2V5XG4gIH07XG5cbiAgaWYgKHRoaXMucmVzdE9wdGlvbnMuc3VicXVlcnlSZWFkUHJlZmVyZW5jZSkge1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gdGhpcy5yZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICAgIGFkZGl0aW9uYWxPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPSB0aGlzLnJlc3RPcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICB2YXIgc3VicXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KFxuICAgIHRoaXMuY29uZmlnLCB0aGlzLmF1dGgsIGRvbnRTZWxlY3RWYWx1ZS5xdWVyeS5jbGFzc05hbWUsXG4gICAgZG9udFNlbGVjdFZhbHVlLnF1ZXJ5LndoZXJlLCBhZGRpdGlvbmFsT3B0aW9ucyk7XG4gIHJldHVybiBzdWJxdWVyeS5leGVjdXRlKCkudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICB0cmFuc2Zvcm1Eb250U2VsZWN0KGRvbnRTZWxlY3RPYmplY3QsIGRvbnRTZWxlY3RWYWx1ZS5rZXksIHJlc3BvbnNlLnJlc3VsdHMpO1xuICAgIC8vIEtlZXAgcmVwbGFjaW5nICRkb250U2VsZWN0IGNsYXVzZXNcbiAgICByZXR1cm4gdGhpcy5yZXBsYWNlRG9udFNlbGVjdCgpO1xuICB9KVxufTtcblxuY29uc3QgY2xlYW5SZXN1bHRPZlNlbnNpdGl2ZVVzZXJJbmZvID0gZnVuY3Rpb24gKHJlc3VsdCwgYXV0aCwgY29uZmlnKSB7XG4gIGRlbGV0ZSByZXN1bHQucGFzc3dvcmQ7XG5cbiAgaWYgKGF1dGguaXNNYXN0ZXIgfHwgKGF1dGgudXNlciAmJiBhdXRoLnVzZXIuaWQgPT09IHJlc3VsdC5vYmplY3RJZCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBmb3IgKGNvbnN0IGZpZWxkIG9mIGNvbmZpZy51c2VyU2Vuc2l0aXZlRmllbGRzKSB7XG4gICAgZGVsZXRlIHJlc3VsdFtmaWVsZF07XG4gIH1cbn07XG5cbmNvbnN0IGNsZWFuUmVzdWx0QXV0aERhdGEgPSBmdW5jdGlvbiAocmVzdWx0KSB7XG4gIGlmIChyZXN1bHQuYXV0aERhdGEpIHtcbiAgICBPYmplY3Qua2V5cyhyZXN1bHQuYXV0aERhdGEpLmZvckVhY2goKHByb3ZpZGVyKSA9PiB7XG4gICAgICBpZiAocmVzdWx0LmF1dGhEYXRhW3Byb3ZpZGVyXSA9PT0gbnVsbCkge1xuICAgICAgICBkZWxldGUgcmVzdWx0LmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChPYmplY3Qua2V5cyhyZXN1bHQuYXV0aERhdGEpLmxlbmd0aCA9PSAwKSB7XG4gICAgICBkZWxldGUgcmVzdWx0LmF1dGhEYXRhO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgcmVwbGFjZUVxdWFsaXR5Q29uc3RyYWludCA9IChjb25zdHJhaW50KSA9PiB7XG4gIGlmICh0eXBlb2YgY29uc3RyYWludCAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gY29uc3RyYWludDtcbiAgfVxuICBjb25zdCBlcXVhbFRvT2JqZWN0ID0ge307XG4gIGxldCBoYXNEaXJlY3RDb25zdHJhaW50ID0gZmFsc2U7XG4gIGxldCBoYXNPcGVyYXRvckNvbnN0cmFpbnQgPSBmYWxzZTtcbiAgZm9yIChjb25zdCBrZXkgaW4gY29uc3RyYWludCkge1xuICAgIGlmIChrZXkuaW5kZXhPZignJCcpICE9PSAwKSB7XG4gICAgICBoYXNEaXJlY3RDb25zdHJhaW50ID0gdHJ1ZTtcbiAgICAgIGVxdWFsVG9PYmplY3Rba2V5XSA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGFzT3BlcmF0b3JDb25zdHJhaW50ID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgaWYgKGhhc0RpcmVjdENvbnN0cmFpbnQgJiYgaGFzT3BlcmF0b3JDb25zdHJhaW50KSB7XG4gICAgY29uc3RyYWludFsnJGVxJ10gPSBlcXVhbFRvT2JqZWN0O1xuICAgIE9iamVjdC5rZXlzKGVxdWFsVG9PYmplY3QpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgZGVsZXRlIGNvbnN0cmFpbnRba2V5XTtcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY29uc3RyYWludDtcbn1cblxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5yZXBsYWNlRXF1YWxpdHkgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHR5cGVvZiB0aGlzLnJlc3RXaGVyZSAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgZm9yIChjb25zdCBrZXkgaW4gdGhpcy5yZXN0V2hlcmUpIHtcbiAgICB0aGlzLnJlc3RXaGVyZVtrZXldID0gcmVwbGFjZUVxdWFsaXR5Q29uc3RyYWludCh0aGlzLnJlc3RXaGVyZVtrZXldKTtcbiAgfVxufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3Igd2hldGhlciBpdCB3YXMgc3VjY2Vzc2Z1bC5cbi8vIFBvcHVsYXRlcyB0aGlzLnJlc3BvbnNlIHdpdGggYW4gb2JqZWN0IHRoYXQgb25seSBoYXMgJ3Jlc3VsdHMnLlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5ydW5GaW5kID0gZnVuY3Rpb24ob3B0aW9ucyA9IHt9KSB7XG4gIGlmICh0aGlzLmZpbmRPcHRpb25zLmxpbWl0ID09PSAwKSB7XG4gICAgdGhpcy5yZXNwb25zZSA9IHtyZXN1bHRzOiBbXX07XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIGNvbnN0IGZpbmRPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5maW5kT3B0aW9ucyk7XG4gIGlmICh0aGlzLmtleXMpIHtcbiAgICBmaW5kT3B0aW9ucy5rZXlzID0gdGhpcy5rZXlzLm1hcCgoa2V5KSA9PiB7XG4gICAgICByZXR1cm4ga2V5LnNwbGl0KCcuJylbMF07XG4gICAgfSk7XG4gIH1cbiAgaWYgKG9wdGlvbnMub3ApIHtcbiAgICBmaW5kT3B0aW9ucy5vcCA9IG9wdGlvbnMub3A7XG4gIH1cbiAgaWYgKHRoaXMuaXNXcml0ZSkge1xuICAgIGZpbmRPcHRpb25zLmlzV3JpdGUgPSB0cnVlO1xuICB9XG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS5maW5kKHRoaXMuY2xhc3NOYW1lLCB0aGlzLnJlc3RXaGVyZSwgZmluZE9wdGlvbnMpXG4gICAgLnRoZW4oKHJlc3VsdHMpID0+IHtcbiAgICAgIGlmICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICBmb3IgKHZhciByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgICAgICAgIGNsZWFuUmVzdWx0T2ZTZW5zaXRpdmVVc2VySW5mbyhyZXN1bHQsIHRoaXMuYXV0aCwgdGhpcy5jb25maWcpO1xuICAgICAgICAgIGNsZWFuUmVzdWx0QXV0aERhdGEocmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLmNvbmZpZy5maWxlc0NvbnRyb2xsZXIuZXhwYW5kRmlsZXNJbk9iamVjdCh0aGlzLmNvbmZpZywgcmVzdWx0cyk7XG5cbiAgICAgIGlmICh0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lKSB7XG4gICAgICAgIGZvciAodmFyIHIgb2YgcmVzdWx0cykge1xuICAgICAgICAgIHIuY2xhc3NOYW1lID0gdGhpcy5yZWRpcmVjdENsYXNzTmFtZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5yZXNwb25zZSA9IHtyZXN1bHRzOiByZXN1bHRzfTtcbiAgICB9KTtcbn07XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciB3aGV0aGVyIGl0IHdhcyBzdWNjZXNzZnVsLlxuLy8gUG9wdWxhdGVzIHRoaXMucmVzcG9uc2UuY291bnQgd2l0aCB0aGUgY291bnRcblJlc3RRdWVyeS5wcm90b3R5cGUucnVuQ291bnQgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLmRvQ291bnQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdGhpcy5maW5kT3B0aW9ucy5jb3VudCA9IHRydWU7XG4gIGRlbGV0ZSB0aGlzLmZpbmRPcHRpb25zLnNraXA7XG4gIGRlbGV0ZSB0aGlzLmZpbmRPcHRpb25zLmxpbWl0O1xuICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZCh0aGlzLmNsYXNzTmFtZSwgdGhpcy5yZXN0V2hlcmUsIHRoaXMuZmluZE9wdGlvbnMpXG4gICAgLnRoZW4oKGMpID0+IHtcbiAgICAgIHRoaXMucmVzcG9uc2UuY291bnQgPSBjO1xuICAgIH0pO1xufTtcblxuLy8gQXVnbWVudHMgdGhpcy5yZXNwb25zZSB3aXRoIGFsbCBwb2ludGVycyBvbiBhbiBvYmplY3RcblJlc3RRdWVyeS5wcm90b3R5cGUuaGFuZGxlSW5jbHVkZUFsbCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuaW5jbHVkZUFsbCkge1xuICAgIHJldHVybjtcbiAgfVxuICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSgpXG4gICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYSh0aGlzLmNsYXNzTmFtZSkpXG4gICAgLnRoZW4oc2NoZW1hID0+IHtcbiAgICAgIGNvbnN0IGluY2x1ZGVGaWVsZHMgPSBbXTtcbiAgICAgIGNvbnN0IGtleUZpZWxkcyA9IFtdO1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBzY2hlbWEuZmllbGRzKSB7XG4gICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlICYmIHNjaGVtYS5maWVsZHNbZmllbGRdLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICAgIGluY2x1ZGVGaWVsZHMucHVzaChbZmllbGRdKTtcbiAgICAgICAgICBrZXlGaWVsZHMucHVzaChmaWVsZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEFkZCBmaWVsZHMgdG8gaW5jbHVkZSwga2V5cywgcmVtb3ZlIGR1cHNcbiAgICAgIHRoaXMuaW5jbHVkZSA9IFsuLi5uZXcgU2V0KFsuLi50aGlzLmluY2x1ZGUsIC4uLmluY2x1ZGVGaWVsZHNdKV07XG4gICAgICAvLyBpZiB0aGlzLmtleXMgbm90IHNldCwgdGhlbiBhbGwga2V5cyBhcmUgYWxyZWFkeSBpbmNsdWRlZFxuICAgICAgaWYgKHRoaXMua2V5cykge1xuICAgICAgICB0aGlzLmtleXMgPSBbLi4ubmV3IFNldChbLi4udGhpcy5rZXlzLCAuLi5rZXlGaWVsZHNdKV07XG4gICAgICB9XG4gICAgfSk7XG59O1xuXG4vLyBBdWdtZW50cyB0aGlzLnJlc3BvbnNlIHdpdGggZGF0YSBhdCB0aGUgcGF0aHMgcHJvdmlkZWQgaW4gdGhpcy5pbmNsdWRlLlxuUmVzdFF1ZXJ5LnByb3RvdHlwZS5oYW5kbGVJbmNsdWRlID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmluY2x1ZGUubGVuZ3RoID09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgcGF0aFJlc3BvbnNlID0gaW5jbHVkZVBhdGgodGhpcy5jb25maWcsIHRoaXMuYXV0aCxcbiAgICB0aGlzLnJlc3BvbnNlLCB0aGlzLmluY2x1ZGVbMF0sIHRoaXMucmVzdE9wdGlvbnMpO1xuICBpZiAocGF0aFJlc3BvbnNlLnRoZW4pIHtcbiAgICByZXR1cm4gcGF0aFJlc3BvbnNlLnRoZW4oKG5ld1Jlc3BvbnNlKSA9PiB7XG4gICAgICB0aGlzLnJlc3BvbnNlID0gbmV3UmVzcG9uc2U7XG4gICAgICB0aGlzLmluY2x1ZGUgPSB0aGlzLmluY2x1ZGUuc2xpY2UoMSk7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVJbmNsdWRlKCk7XG4gICAgfSk7XG4gIH0gZWxzZSBpZiAodGhpcy5pbmNsdWRlLmxlbmd0aCA+IDApIHtcbiAgICB0aGlzLmluY2x1ZGUgPSB0aGlzLmluY2x1ZGUuc2xpY2UoMSk7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlSW5jbHVkZSgpO1xuICB9XG5cbiAgcmV0dXJuIHBhdGhSZXNwb25zZTtcbn07XG5cbi8vUmV0dXJucyBhIHByb21pc2Ugb2YgYSBwcm9jZXNzZWQgc2V0IG9mIHJlc3VsdHNcblJlc3RRdWVyeS5wcm90b3R5cGUucnVuQWZ0ZXJGaW5kVHJpZ2dlciA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMucmVzcG9uc2UpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gQXZvaWQgZG9pbmcgYW55IHNldHVwIGZvciB0cmlnZ2VycyBpZiB0aGVyZSBpcyBubyAnYWZ0ZXJGaW5kJyB0cmlnZ2VyIGZvciB0aGlzIGNsYXNzLlxuICBjb25zdCBoYXNBZnRlckZpbmRIb29rID0gdHJpZ2dlcnMudHJpZ2dlckV4aXN0cyh0aGlzLmNsYXNzTmFtZSwgdHJpZ2dlcnMuVHlwZXMuYWZ0ZXJGaW5kLCB0aGlzLmNvbmZpZy5hcHBsaWNhdGlvbklkKTtcbiAgaWYgKCFoYXNBZnRlckZpbmRIb29rKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIC8vIFNraXAgQWdncmVnYXRlIGFuZCBEaXN0aW5jdCBRdWVyaWVzXG4gIGlmICh0aGlzLmZpbmRPcHRpb25zLnBpcGVsaW5lIHx8IHRoaXMuZmluZE9wdGlvbnMuZGlzdGluY3QpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gUnVuIGFmdGVyRmluZCB0cmlnZ2VyIGFuZCBzZXQgdGhlIG5ldyByZXN1bHRzXG4gIHJldHVybiB0cmlnZ2Vycy5tYXliZVJ1bkFmdGVyRmluZFRyaWdnZXIodHJpZ2dlcnMuVHlwZXMuYWZ0ZXJGaW5kLCB0aGlzLmF1dGgsIHRoaXMuY2xhc3NOYW1lLHRoaXMucmVzcG9uc2UucmVzdWx0cywgdGhpcy5jb25maWcpLnRoZW4oKHJlc3VsdHMpID0+IHtcbiAgICAvLyBFbnN1cmUgd2UgcHJvcGVybHkgc2V0IHRoZSBjbGFzc05hbWUgYmFja1xuICAgIGlmICh0aGlzLnJlZGlyZWN0Q2xhc3NOYW1lKSB7XG4gICAgICB0aGlzLnJlc3BvbnNlLnJlc3VsdHMgPSByZXN1bHRzLm1hcCgob2JqZWN0KSA9PiB7XG4gICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiBQYXJzZS5PYmplY3QpIHtcbiAgICAgICAgICBvYmplY3QgPSBvYmplY3QudG9KU09OKCk7XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0LmNsYXNzTmFtZSA9IHRoaXMucmVkaXJlY3RDbGFzc05hbWU7XG4gICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZXNwb25zZS5yZXN1bHRzID0gcmVzdWx0cztcbiAgICB9XG4gIH0pO1xufTtcblxuLy8gQWRkcyBpbmNsdWRlZCB2YWx1ZXMgdG8gdGhlIHJlc3BvbnNlLlxuLy8gUGF0aCBpcyBhIGxpc3Qgb2YgZmllbGQgbmFtZXMuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYW4gYXVnbWVudGVkIHJlc3BvbnNlLlxuZnVuY3Rpb24gaW5jbHVkZVBhdGgoY29uZmlnLCBhdXRoLCByZXNwb25zZSwgcGF0aCwgcmVzdE9wdGlvbnMgPSB7fSkge1xuICB2YXIgcG9pbnRlcnMgPSBmaW5kUG9pbnRlcnMocmVzcG9uc2UucmVzdWx0cywgcGF0aCk7XG4gIGlmIChwb2ludGVycy5sZW5ndGggPT0gMCkge1xuICAgIHJldHVybiByZXNwb25zZTtcbiAgfVxuICBjb25zdCBwb2ludGVyc0hhc2ggPSB7fTtcbiAgZm9yICh2YXIgcG9pbnRlciBvZiBwb2ludGVycykge1xuICAgIGlmICghcG9pbnRlcikge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IGNsYXNzTmFtZSA9IHBvaW50ZXIuY2xhc3NOYW1lO1xuICAgIC8vIG9ubHkgaW5jbHVkZSB0aGUgZ29vZCBwb2ludGVyc1xuICAgIGlmIChjbGFzc05hbWUpIHtcbiAgICAgIHBvaW50ZXJzSGFzaFtjbGFzc05hbWVdID0gcG9pbnRlcnNIYXNoW2NsYXNzTmFtZV0gfHwgbmV3IFNldCgpO1xuICAgICAgcG9pbnRlcnNIYXNoW2NsYXNzTmFtZV0uYWRkKHBvaW50ZXIub2JqZWN0SWQpO1xuICAgIH1cbiAgfVxuICBjb25zdCBpbmNsdWRlUmVzdE9wdGlvbnMgPSB7fTtcbiAgaWYgKHJlc3RPcHRpb25zLmtleXMpIHtcbiAgICBjb25zdCBrZXlzID0gbmV3IFNldChyZXN0T3B0aW9ucy5rZXlzLnNwbGl0KCcsJykpO1xuICAgIGNvbnN0IGtleVNldCA9IEFycmF5LmZyb20oa2V5cykucmVkdWNlKChzZXQsIGtleSkgPT4ge1xuICAgICAgY29uc3Qga2V5UGF0aCA9IGtleS5zcGxpdCgnLicpO1xuICAgICAgbGV0IGkgPSAwO1xuICAgICAgZm9yIChpOyBpIDwgcGF0aC5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAocGF0aFtpXSAhPSBrZXlQYXRoW2ldKSB7XG4gICAgICAgICAgcmV0dXJuIHNldDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGkgPCBrZXlQYXRoLmxlbmd0aCkge1xuICAgICAgICBzZXQuYWRkKGtleVBhdGhbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNldDtcbiAgICB9LCBuZXcgU2V0KCkpO1xuICAgIGlmIChrZXlTZXQuc2l6ZSA+IDApIHtcbiAgICAgIGluY2x1ZGVSZXN0T3B0aW9ucy5rZXlzID0gQXJyYXkuZnJvbShrZXlTZXQpLmpvaW4oJywnKTtcbiAgICB9XG4gIH1cblxuICBpZiAocmVzdE9wdGlvbnMuaW5jbHVkZVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgaW5jbHVkZVJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gcmVzdE9wdGlvbnMuaW5jbHVkZVJlYWRQcmVmZXJlbmNlO1xuICAgIGluY2x1ZGVSZXN0T3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPSByZXN0T3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICBjb25zdCBxdWVyeVByb21pc2VzID0gT2JqZWN0LmtleXMocG9pbnRlcnNIYXNoKS5tYXAoKGNsYXNzTmFtZSkgPT4ge1xuICAgIGNvbnN0IG9iamVjdElkcyA9IEFycmF5LmZyb20ocG9pbnRlcnNIYXNoW2NsYXNzTmFtZV0pO1xuICAgIGxldCB3aGVyZTtcbiAgICBpZiAob2JqZWN0SWRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgd2hlcmUgPSB7J29iamVjdElkJzogb2JqZWN0SWRzWzBdfTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hlcmUgPSB7J29iamVjdElkJzogeyckaW4nOiBvYmplY3RJZHN9fTtcbiAgICB9XG4gICAgdmFyIHF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgd2hlcmUsIGluY2x1ZGVSZXN0T3B0aW9ucyk7XG4gICAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoe29wOiAnZ2V0J30pLnRoZW4oKHJlc3VsdHMpID0+IHtcbiAgICAgIHJlc3VsdHMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHRzKTtcbiAgICB9KVxuICB9KVxuXG4gIC8vIEdldCB0aGUgb2JqZWN0cyBmb3IgYWxsIHRoZXNlIG9iamVjdCBpZHNcbiAgcmV0dXJuIFByb21pc2UuYWxsKHF1ZXJ5UHJvbWlzZXMpLnRoZW4oKHJlc3BvbnNlcykgPT4ge1xuICAgIHZhciByZXBsYWNlID0gcmVzcG9uc2VzLnJlZHVjZSgocmVwbGFjZSwgaW5jbHVkZVJlc3BvbnNlKSA9PiB7XG4gICAgICBmb3IgKHZhciBvYmogb2YgaW5jbHVkZVJlc3BvbnNlLnJlc3VsdHMpIHtcbiAgICAgICAgb2JqLl9fdHlwZSA9ICdPYmplY3QnO1xuICAgICAgICBvYmouY2xhc3NOYW1lID0gaW5jbHVkZVJlc3BvbnNlLmNsYXNzTmFtZTtcblxuICAgICAgICBpZiAob2JqLmNsYXNzTmFtZSA9PSBcIl9Vc2VyXCIgJiYgIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgICBkZWxldGUgb2JqLnNlc3Npb25Ub2tlbjtcbiAgICAgICAgICBkZWxldGUgb2JqLmF1dGhEYXRhO1xuICAgICAgICB9XG4gICAgICAgIHJlcGxhY2Vbb2JqLm9iamVjdElkXSA9IG9iajtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXBsYWNlO1xuICAgIH0sIHt9KVxuXG4gICAgdmFyIHJlc3AgPSB7XG4gICAgICByZXN1bHRzOiByZXBsYWNlUG9pbnRlcnMocmVzcG9uc2UucmVzdWx0cywgcGF0aCwgcmVwbGFjZSlcbiAgICB9O1xuICAgIGlmIChyZXNwb25zZS5jb3VudCkge1xuICAgICAgcmVzcC5jb3VudCA9IHJlc3BvbnNlLmNvdW50O1xuICAgIH1cbiAgICByZXR1cm4gcmVzcDtcbiAgfSk7XG59XG5cbi8vIE9iamVjdCBtYXkgYmUgYSBsaXN0IG9mIFJFU1QtZm9ybWF0IG9iamVjdCB0byBmaW5kIHBvaW50ZXJzIGluLCBvclxuLy8gaXQgbWF5IGJlIGEgc2luZ2xlIG9iamVjdC5cbi8vIElmIHRoZSBwYXRoIHlpZWxkcyB0aGluZ3MgdGhhdCBhcmVuJ3QgcG9pbnRlcnMsIHRoaXMgdGhyb3dzIGFuIGVycm9yLlxuLy8gUGF0aCBpcyBhIGxpc3Qgb2YgZmllbGRzIHRvIHNlYXJjaCBpbnRvLlxuLy8gUmV0dXJucyBhIGxpc3Qgb2YgcG9pbnRlcnMgaW4gUkVTVCBmb3JtYXQuXG5mdW5jdGlvbiBmaW5kUG9pbnRlcnMob2JqZWN0LCBwYXRoKSB7XG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHZhciBhbnN3ZXIgPSBbXTtcbiAgICBmb3IgKHZhciB4IG9mIG9iamVjdCkge1xuICAgICAgYW5zd2VyID0gYW5zd2VyLmNvbmNhdChmaW5kUG9pbnRlcnMoeCwgcGF0aCkpO1xuICAgIH1cbiAgICByZXR1cm4gYW5zd2VyO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnIHx8ICFvYmplY3QpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBpZiAocGF0aC5sZW5ndGggPT0gMCkge1xuICAgIGlmIChvYmplY3QgPT09IG51bGwgfHwgb2JqZWN0Ll9fdHlwZSA9PSAnUG9pbnRlcicpIHtcbiAgICAgIHJldHVybiBbb2JqZWN0XTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgdmFyIHN1Ym9iamVjdCA9IG9iamVjdFtwYXRoWzBdXTtcbiAgaWYgKCFzdWJvYmplY3QpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgcmV0dXJuIGZpbmRQb2ludGVycyhzdWJvYmplY3QsIHBhdGguc2xpY2UoMSkpO1xufVxuXG4vLyBPYmplY3QgbWF5IGJlIGEgbGlzdCBvZiBSRVNULWZvcm1hdCBvYmplY3RzIHRvIHJlcGxhY2UgcG9pbnRlcnNcbi8vIGluLCBvciBpdCBtYXkgYmUgYSBzaW5nbGUgb2JqZWN0LlxuLy8gUGF0aCBpcyBhIGxpc3Qgb2YgZmllbGRzIHRvIHNlYXJjaCBpbnRvLlxuLy8gcmVwbGFjZSBpcyBhIG1hcCBmcm9tIG9iamVjdCBpZCAtPiBvYmplY3QuXG4vLyBSZXR1cm5zIHNvbWV0aGluZyBhbmFsb2dvdXMgdG8gb2JqZWN0LCBidXQgd2l0aCB0aGUgYXBwcm9wcmlhdGVcbi8vIHBvaW50ZXJzIGluZmxhdGVkLlxuZnVuY3Rpb24gcmVwbGFjZVBvaW50ZXJzKG9iamVjdCwgcGF0aCwgcmVwbGFjZSkge1xuICBpZiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICByZXR1cm4gb2JqZWN0Lm1hcCgob2JqKSA9PiByZXBsYWNlUG9pbnRlcnMob2JqLCBwYXRoLCByZXBsYWNlKSlcbiAgICAgIC5maWx0ZXIoKG9iaikgPT4gdHlwZW9mIG9iaiAhPT0gJ3VuZGVmaW5lZCcpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnIHx8ICFvYmplY3QpIHtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG5cbiAgaWYgKHBhdGgubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKG9iamVjdCAmJiBvYmplY3QuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgIHJldHVybiByZXBsYWNlW29iamVjdC5vYmplY3RJZF07XG4gICAgfVxuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICB2YXIgc3Vib2JqZWN0ID0gb2JqZWN0W3BhdGhbMF1dO1xuICBpZiAoIXN1Ym9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgdmFyIG5ld3N1YiA9IHJlcGxhY2VQb2ludGVycyhzdWJvYmplY3QsIHBhdGguc2xpY2UoMSksIHJlcGxhY2UpO1xuICB2YXIgYW5zd2VyID0ge307XG4gIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICBpZiAoa2V5ID09IHBhdGhbMF0pIHtcbiAgICAgIGFuc3dlcltrZXldID0gbmV3c3ViO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbnN3ZXJba2V5XSA9IG9iamVjdFtrZXldO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYW5zd2VyO1xufVxuXG4vLyBGaW5kcyBhIHN1Ym9iamVjdCB0aGF0IGhhcyB0aGUgZ2l2ZW4ga2V5LCBpZiB0aGVyZSBpcyBvbmUuXG4vLyBSZXR1cm5zIHVuZGVmaW5lZCBvdGhlcndpc2UuXG5mdW5jdGlvbiBmaW5kT2JqZWN0V2l0aEtleShyb290LCBrZXkpIHtcbiAgaWYgKHR5cGVvZiByb290ICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAocm9vdCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgZm9yICh2YXIgaXRlbSBvZiByb290KSB7XG4gICAgICBjb25zdCBhbnN3ZXIgPSBmaW5kT2JqZWN0V2l0aEtleShpdGVtLCBrZXkpO1xuICAgICAgaWYgKGFuc3dlcikge1xuICAgICAgICByZXR1cm4gYW5zd2VyO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAocm9vdCAmJiByb290W2tleV0pIHtcbiAgICByZXR1cm4gcm9vdDtcbiAgfVxuICBmb3IgKHZhciBzdWJrZXkgaW4gcm9vdCkge1xuICAgIGNvbnN0IGFuc3dlciA9IGZpbmRPYmplY3RXaXRoS2V5KHJvb3Rbc3Via2V5XSwga2V5KTtcbiAgICBpZiAoYW5zd2VyKSB7XG4gICAgICByZXR1cm4gYW5zd2VyO1xuICAgIH1cbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFJlc3RRdWVyeTtcbiJdfQ== \ No newline at end of file diff --git a/lib/RestWrite.js b/lib/RestWrite.js index fdebfca115..310612fe9a 100644 --- a/lib/RestWrite.js +++ b/lib/RestWrite.js @@ -286,10 +286,23 @@ RestWrite.prototype.findUsersWithAuthData = function (authData) { 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(r => { - results = r; + results = this.filteredObjectsByACL(r); 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'); @@ -917,7 +930,7 @@ RestWrite.prototype.runDatabaseOperation = function () { this.config.cacheController.role.clear(); } - if (this.className === '_User' && this.query && !this.auth.couldUpdateUserId(this.query.objectId)) { + if (this.className === '_User' && this.query && this.auth.isUnauthenticated()) { throw new Parse.Error(Parse.Error.SESSION_MISSING, `Cannot modify user ${this.query.objectId}.`); } @@ -934,7 +947,7 @@ RestWrite.prototype.runDatabaseOperation = function () { if (this.query) { // Force the user to not lockout // Matched with parse.com - if (this.className === '_User' && this.data.ACL) { + 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 @@ -1164,4 +1177,5 @@ RestWrite.prototype._updateResponseWithData = function (response, data) { exports.default = RestWrite; -module.exports = RestWrite; \ No newline at end of file +module.exports = RestWrite; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9SZXN0V3JpdGUuanMiXSwibmFtZXMiOlsiU2NoZW1hQ29udHJvbGxlciIsInJlcXVpcmUiLCJkZWVwY29weSIsIkF1dGgiLCJjcnlwdG9VdGlscyIsInBhc3N3b3JkQ3J5cHRvIiwiUGFyc2UiLCJ0cmlnZ2VycyIsIkNsaWVudFNESyIsIlJlc3RXcml0ZSIsImNvbmZpZyIsImF1dGgiLCJjbGFzc05hbWUiLCJxdWVyeSIsImRhdGEiLCJvcmlnaW5hbERhdGEiLCJjbGllbnRTREsiLCJvcHRpb25zIiwiaXNSZWFkT25seSIsIkVycm9yIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsInN0b3JhZ2UiLCJydW5PcHRpb25zIiwiYWxsb3dPYmplY3RJZCIsIm9iamVjdElkIiwiSU5WQUxJRF9LRVlfTkFNRSIsInJlc3BvbnNlIiwidXBkYXRlZEF0IiwiX2VuY29kZSIsIkRhdGUiLCJpc28iLCJwcm90b3R5cGUiLCJleGVjdXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aGVuIiwiZ2V0VXNlckFuZFJvbGVBQ0wiLCJ2YWxpZGF0ZUNsaWVudENsYXNzQ3JlYXRpb24iLCJoYW5kbGVJbnN0YWxsYXRpb24iLCJoYW5kbGVTZXNzaW9uIiwidmFsaWRhdGVBdXRoRGF0YSIsInJ1bkJlZm9yZVRyaWdnZXIiLCJ2YWxpZGF0ZVNjaGVtYSIsInNldFJlcXVpcmVkRmllbGRzSWZOZWVkZWQiLCJ0cmFuc2Zvcm1Vc2VyIiwiZXhwYW5kRmlsZXNGb3JFeGlzdGluZ09iamVjdHMiLCJkZXN0cm95RHVwbGljYXRlZFNlc3Npb25zIiwicnVuRGF0YWJhc2VPcGVyYXRpb24iLCJjcmVhdGVTZXNzaW9uVG9rZW5JZk5lZWRlZCIsImhhbmRsZUZvbGxvd3VwIiwicnVuQWZ0ZXJUcmlnZ2VyIiwiY2xlYW5Vc2VyQXV0aERhdGEiLCJpc01hc3RlciIsImFjbCIsInVzZXIiLCJnZXRVc2VyUm9sZXMiLCJyb2xlcyIsImNvbmNhdCIsImlkIiwiYWxsb3dDbGllbnRDbGFzc0NyZWF0aW9uIiwic3lzdGVtQ2xhc3NlcyIsImluZGV4T2YiLCJkYXRhYmFzZSIsImxvYWRTY2hlbWEiLCJzY2hlbWFDb250cm9sbGVyIiwiaGFzQ2xhc3MiLCJ2YWxpZGF0ZU9iamVjdCIsInRyaWdnZXJFeGlzdHMiLCJUeXBlcyIsImJlZm9yZVNhdmUiLCJhcHBsaWNhdGlvbklkIiwiZXh0cmFEYXRhIiwib3JpZ2luYWxPYmplY3QiLCJ1cGRhdGVkT2JqZWN0IiwiYnVpbGRVcGRhdGVkT2JqZWN0IiwiaW5mbGF0ZSIsIm1heWJlUnVuVHJpZ2dlciIsIm9iamVjdCIsImZpZWxkc0NoYW5nZWRCeVRyaWdnZXIiLCJfIiwicmVkdWNlIiwicmVzdWx0IiwidmFsdWUiLCJrZXkiLCJpc0VxdWFsIiwicHVzaCIsImNyZWF0ZWRBdCIsIm5ld09iamVjdElkIiwib2JqZWN0SWRTaXplIiwiYXV0aERhdGEiLCJ1c2VybmFtZSIsImlzRW1wdHkiLCJVU0VSTkFNRV9NSVNTSU5HIiwicGFzc3dvcmQiLCJQQVNTV09SRF9NSVNTSU5HIiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsInByb3ZpZGVycyIsImNhbkhhbmRsZUF1dGhEYXRhIiwiY2FuSGFuZGxlIiwicHJvdmlkZXIiLCJwcm92aWRlckF1dGhEYXRhIiwiaGFzVG9rZW4iLCJoYW5kbGVBdXRoRGF0YSIsIlVOU1VQUE9SVEVEX1NFUlZJQ0UiLCJoYW5kbGVBdXRoRGF0YVZhbGlkYXRpb24iLCJ2YWxpZGF0aW9ucyIsIm1hcCIsImF1dGhEYXRhTWFuYWdlciIsImdldFZhbGlkYXRvckZvclByb3ZpZGVyIiwiYWxsIiwiZmluZFVzZXJzV2l0aEF1dGhEYXRhIiwibWVtbyIsInF1ZXJ5S2V5IiwiZmlsdGVyIiwicSIsImZpbmRQcm9taXNlIiwiZmluZCIsImZpbHRlcmVkT2JqZWN0c0J5QUNMIiwib2JqZWN0cyIsIkFDTCIsInJlc3VsdHMiLCJyIiwiQUNDT1VOVF9BTFJFQURZX0xJTktFRCIsImpvaW4iLCJ1c2VyUmVzdWx0IiwibXV0YXRlZEF1dGhEYXRhIiwiZm9yRWFjaCIsInByb3ZpZGVyRGF0YSIsInVzZXJBdXRoRGF0YSIsImhhc011dGF0ZWRBdXRoRGF0YSIsInVzZXJJZCIsImxvY2F0aW9uIiwidXBkYXRlIiwicHJvbWlzZSIsImVycm9yIiwiUmVzdFF1ZXJ5IiwibWFzdGVyIiwiX190eXBlIiwic2Vzc2lvbiIsImNhY2hlQ29udHJvbGxlciIsImRlbCIsInNlc3Npb25Ub2tlbiIsInVuZGVmaW5lZCIsIl92YWxpZGF0ZVBhc3N3b3JkUG9saWN5IiwiaGFzaCIsImhhc2hlZFBhc3N3b3JkIiwiX2hhc2hlZF9wYXNzd29yZCIsIl92YWxpZGF0ZVVzZXJOYW1lIiwiX3ZhbGlkYXRlRW1haWwiLCJyYW5kb21TdHJpbmciLCJyZXNwb25zZVNob3VsZEhhdmVVc2VybmFtZSIsImxpbWl0IiwiVVNFUk5BTUVfVEFLRU4iLCJlbWFpbCIsIl9fb3AiLCJtYXRjaCIsInJlamVjdCIsIklOVkFMSURfRU1BSUxfQUREUkVTUyIsIkVNQUlMX1RBS0VOIiwidXNlckNvbnRyb2xsZXIiLCJzZXRFbWFpbFZlcmlmeVRva2VuIiwicGFzc3dvcmRQb2xpY3kiLCJfdmFsaWRhdGVQYXNzd29yZFJlcXVpcmVtZW50cyIsIl92YWxpZGF0ZVBhc3N3b3JkSGlzdG9yeSIsInBvbGljeUVycm9yIiwicGF0dGVyblZhbGlkYXRvciIsInZhbGlkYXRvckNhbGxiYWNrIiwiVkFMSURBVElPTl9FUlJPUiIsImRvTm90QWxsb3dVc2VybmFtZSIsIm1heFBhc3N3b3JkSGlzdG9yeSIsIm9sZFBhc3N3b3JkcyIsIl9wYXNzd29yZF9oaXN0b3J5IiwidGFrZSIsIm5ld1Bhc3N3b3JkIiwicHJvbWlzZXMiLCJjb21wYXJlIiwiY2F0Y2giLCJlcnIiLCJwcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsIiwidmVyaWZ5VXNlckVtYWlscyIsImNyZWF0ZVNlc3Npb25Ub2tlbiIsImluc3RhbGxhdGlvbklkIiwic2Vzc2lvbkRhdGEiLCJjcmVhdGVTZXNzaW9uIiwiY3JlYXRlZFdpdGgiLCJkZXN0cm95IiwicmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCIsInNlc3Npb25RdWVyeSIsImJpbmQiLCJzZW5kVmVyaWZpY2F0aW9uRW1haWwiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJhZGRpdGlvbmFsU2Vzc2lvbkRhdGEiLCJhY3Rpb24iLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJzdGF0dXMiLCJkZXZpY2VUb2tlbiIsInRvTG93ZXJDYXNlIiwiZGV2aWNlVHlwZSIsImlkTWF0Y2giLCJvYmplY3RJZE1hdGNoIiwiaW5zdGFsbGF0aW9uSWRNYXRjaCIsImRldmljZVRva2VuTWF0Y2hlcyIsIm9yUXVlcmllcyIsIk9CSkVDVF9OT1RfRk9VTkQiLCJkZWxRdWVyeSIsImFwcElkZW50aWZpZXIiLCJjb2RlIiwib2JqSWQiLCJmaWxlc0NvbnRyb2xsZXIiLCJleHBhbmRGaWxlc0luT2JqZWN0Iiwicm9sZSIsImNsZWFyIiwiaXNVbmF1dGhlbnRpY2F0ZWQiLCJTRVNTSU9OX01JU1NJTkciLCJkb3dubG9hZCIsImRvd25sb2FkTmFtZSIsIm5hbWUiLCJJTlZBTElEX0FDTCIsInJlYWQiLCJ3cml0ZSIsIm1heFBhc3N3b3JkQWdlIiwiX3Bhc3N3b3JkX2NoYW5nZWRfYXQiLCJkZWZlciIsInNoaWZ0IiwiX3VwZGF0ZVJlc3BvbnNlV2l0aERhdGEiLCJjcmVhdGUiLCJEVVBMSUNBVEVfVkFMVUUiLCJ1c2VySW5mbyIsImR1cGxpY2F0ZWRfZmllbGQiLCJoYXNBZnRlclNhdmVIb29rIiwiYWZ0ZXJTYXZlIiwiaGFzTGl2ZVF1ZXJ5IiwibGl2ZVF1ZXJ5Q29udHJvbGxlciIsIl9oYW5kbGVTYXZlUmVzcG9uc2UiLCJvbkFmdGVyU2F2ZSIsImxvZ2dlciIsIndhcm4iLCJtaWRkbGUiLCJtb3VudCIsInNhbml0aXplZERhdGEiLCJ0ZXN0IiwiX2RlY29kZSIsInNwbGl0dGVkS2V5Iiwic3BsaXQiLCJwYXJlbnRQcm9wIiwicGFyZW50VmFsIiwiZ2V0Iiwic2V0IiwiY2xpZW50U3VwcG9ydHNEZWxldGUiLCJzdXBwb3J0c0ZvcndhcmREZWxldGUiLCJmaWVsZE5hbWUiLCJkYXRhVmFsdWUiLCJoYXNPd25Qcm9wZXJ0eSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7OztBQWFBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBZkE7QUFDQTtBQUNBOztBQUVBLElBQUlBLG1CQUFtQkMsUUFBUSxnQ0FBUixDQUF2QjtBQUNBLElBQUlDLFdBQVdELFFBQVEsVUFBUixDQUFmOztBQUVBLE1BQU1FLE9BQU9GLFFBQVEsUUFBUixDQUFiO0FBQ0EsSUFBSUcsY0FBY0gsUUFBUSxlQUFSLENBQWxCO0FBQ0EsSUFBSUksaUJBQWlCSixRQUFRLFlBQVIsQ0FBckI7QUFDQSxJQUFJSyxRQUFRTCxRQUFRLFlBQVIsQ0FBWjtBQUNBLElBQUlNLFdBQVdOLFFBQVEsWUFBUixDQUFmO0FBQ0EsSUFBSU8sWUFBWVAsUUFBUSxhQUFSLENBQWhCOzs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTUSxTQUFULENBQW1CQyxNQUFuQixFQUEyQkMsSUFBM0IsRUFBaUNDLFNBQWpDLEVBQTRDQyxLQUE1QyxFQUFtREMsSUFBbkQsRUFBeURDLFlBQXpELEVBQXVFQyxTQUF2RSxFQUFrRkMsT0FBbEYsRUFBMkY7QUFDekYsTUFBSU4sS0FBS08sVUFBVCxFQUFxQjtBQUNuQixVQUFNLElBQUlaLE1BQU1hLEtBQVYsQ0FBZ0JiLE1BQU1hLEtBQU4sQ0FBWUMsbUJBQTVCLEVBQWlELCtEQUFqRCxDQUFOO0FBQ0Q7QUFDRCxPQUFLVixNQUFMLEdBQWNBLE1BQWQ7QUFDQSxPQUFLQyxJQUFMLEdBQVlBLElBQVo7QUFDQSxPQUFLQyxTQUFMLEdBQWlCQSxTQUFqQjtBQUNBLE9BQUtJLFNBQUwsR0FBaUJBLFNBQWpCO0FBQ0EsT0FBS0ssT0FBTCxHQUFlLEVBQWY7QUFDQSxPQUFLQyxVQUFMLEdBQWtCLEVBQWxCO0FBQ0EsUUFBTUMsZ0JBQWdCTixXQUFXQSxRQUFRTSxhQUFSLEtB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O0FBQ0EsT0FBS0ssT0FBTCxDQUFheUQsc0JBQWIsQ0FBb0NrRCxPQUFwQyxDQUE0QzRILGFBQWE7QUFDdkQsVUFBTUMsWUFBWS9PLEtBQUs4TyxTQUFMLENBQWxCOztBQUVBLFFBQUcsQ0FBQ2xPLFNBQVNvTyxjQUFULENBQXdCRixTQUF4QixDQUFKLEVBQXdDO0FBQ3RDbE8sZUFBU2tPLFNBQVQsSUFBc0JDLFNBQXRCO0FBQ0Q7O0FBRUQ7QUFDQSxRQUFJbk8sU0FBU2tPLFNBQVQsS0FBdUJsTyxTQUFTa08sU0FBVCxFQUFvQmhHLElBQS9DLEVBQXFEO0FBQ25ELGFBQU9sSSxTQUFTa08sU0FBVCxDQUFQO0FBQ0EsVUFBSUYsd0JBQXdCRyxVQUFVakcsSUFBVixJQUFrQixRQUE5QyxFQUF3RDtBQUN0RGxJLGlCQUFTa08sU0FBVCxJQUFzQkMsU0FBdEI7QUFDRDtBQUNGO0FBQ0YsR0FkRDtBQWVBLFNBQU9uTyxRQUFQO0FBQ0QsQ0FyQkQ7O2tCQXVCZWpCLFM7O0FBQ2ZzUCxPQUFPQyxPQUFQLEdBQWlCdlAsU0FBakIiLCJmaWxlIjoiUmVzdFdyaXRlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQSBSZXN0V3JpdGUgZW5jYXBzdWxhdGVzIGV2ZXJ5dGhpbmcgd2UgbmVlZCB0byBydW4gYW4gb3BlcmF0aW9uXG4vLyB0aGF0IHdyaXRlcyB0byB0aGUgZGF0YWJhc2UuXG4vLyBUaGlzIGNvdWxkIGJlIGVpdGhlciBhIFwiY3JlYXRlXCIgb3IgYW4gXCJ1cGRhdGVcIi5cblxudmFyIFNjaGVtYUNvbnRyb2xsZXIgPSByZXF1aXJlKCcuL0NvbnRyb2xsZXJzL1NjaGVtYUNvbnRyb2xsZXInKTtcbnZhciBkZWVwY29weSA9IHJlcXVpcmUoJ2RlZXBjb3B5Jyk7XG5cbmNvbnN0IEF1dGggPSByZXF1aXJlKCcuL0F1dGgnKTtcbnZhciBjcnlwdG9VdGlscyA9IHJlcXVpcmUoJy4vY3J5cHRvVXRpbHMnKTtcbnZhciBwYXNzd29yZENyeXB0byA9IHJlcXVpcmUoJy4vcGFzc3dvcmQnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKTtcbnZhciB0cmlnZ2VycyA9IHJlcXVpcmUoJy4vdHJpZ2dlcnMnKTtcbnZhciBDbGllbnRTREsgPSByZXF1aXJlKCcuL0NsaWVudFNESycpO1xuaW1wb3J0IFJlc3RRdWVyeSBmcm9tICcuL1Jlc3RRdWVyeSc7XG5pbXBvcnQgXyAgICAgICAgIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgbG9nZ2VyICAgIGZyb20gJy4vbG9nZ2VyJztcblxuLy8gcXVlcnkgYW5kIGRhdGEgYXJlIGJvdGggcHJvdmlkZWQgaW4gUkVTVCBBUEkgZm9ybWF0LiBTbyBkYXRhXG4vLyB0eXBlcyBhcmUgZW5jb2RlZCBieSBwbGFpbiBvbGQgb2JqZWN0cy5cbi8vIElmIHF1ZXJ5IGlzIG51bGwsIHRoaXMgaXMgYSBcImNyZWF0ZVwiIGFuZCB0aGUgZGF0YSBpbiBkYXRhIHNob3VsZCBiZVxuLy8gY3JlYXRlZC5cbi8vIE90aGVyd2lzZSB0aGlzIGlzIGFuIFwidXBkYXRlXCIgLSB0aGUgb2JqZWN0IG1hdGNoaW5nIHRoZSBxdWVyeVxuLy8gc2hvdWxkIGdldCB1cGRhdGVkIHdpdGggZGF0YS5cbi8vIFJlc3RXcml0ZSB3aWxsIGhhbmRsZSBvYmplY3RJZCwgY3JlYXRlZEF0LCBhbmQgdXBkYXRlZEF0IGZvclxuLy8gZXZlcnl0aGluZy4gSXQgYWxzbyBrbm93cyB0byB1c2UgdHJpZ2dlcnMgYW5kIHNwZWNpYWwgbW9kaWZpY2F0aW9uc1xuLy8gZm9yIHRoZSBfVXNlciBjbGFzcy5cbmZ1bmN0aW9uIFJlc3RXcml0ZShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgcXVlcnksIGRhdGEsIG9yaWdpbmFsRGF0YSwgY2xpZW50U0RLLCBvcHRpb25zKSB7XG4gIGlmIChhdXRoLmlzUmVhZE9ubHkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTiwgJ0Nhbm5vdCBwZXJmb3JtIGEgd3JpdGUgb3BlcmF0aW9uIHdoZW4gdXNpbmcgcmVhZE9ubHlNYXN0ZXJLZXknKTtcbiAgfVxuICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgdGhpcy5hdXRoID0gYXV0aDtcbiAgdGhpcy5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gIHRoaXMuY2xpZW50U0RLID0gY2xpZW50U0RLO1xuICB0aGlzLnN0b3JhZ2UgPSB7fTtcbiAgdGhpcy5ydW5PcHRpb25zID0ge307XG4gIGNvbnN0IGFsbG93T2JqZWN0SWQgPSBvcHRpb25zICYmIG9wdGlvbnMuYWxsb3dPYmplY3RJZCA9PT0gdHJ1ZTtcbiAgaWYgKCFxdWVyeSAmJiBkYXRhLm9iamVjdElkICYmICFhbGxvd09iamVjdElkKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsICdvYmplY3RJZCBpcyBhbiBpbnZhbGlkIGZpZWxkIG5hbWUuJyk7XG4gIH1cblxuICAvLyBXaGVuIHRoZSBvcGVyYXRpb24gaXMgY29tcGxldGUsIHRoaXMucmVzcG9uc2UgbWF5IGhhdmUgc2V2ZXJhbFxuICAvLyBmaWVsZHMuXG4gIC8vIHJlc3BvbnNlOiB0aGUgYWN0dWFsIGRhdGEgdG8gYmUgcmV0dXJuZWRcbiAgLy8gc3RhdHVzOiB0aGUgaHR0cCBzdGF0dXMgY29kZS4gaWYgbm90IHByZXNlbnQsIHRyZWF0ZWQgbGlrZSBhIDIwMFxuICAvLyBsb2NhdGlvbjogdGhlIGxvY2F0aW9uIGhlYWRlci4gaWYgbm90IHByZXNlbnQsIG5vIGxvY2F0aW9uIGhlYWRlclxuICB0aGlzLnJlc3BvbnNlID0gbnVsbDtcblxuICAvLyBQcm9jZXNzaW5nIHRoaXMgb3BlcmF0aW9uIG1heSBtdXRhdGUgb3VyIGRhdGEsIHNvIHdlIG9wZXJhdGUgb24gYVxuICAvLyBjb3B5XG4gIHRoaXMucXVlcnkgPSBkZWVwY29weShxdWVyeSk7XG4gIHRoaXMuZGF0YSA9IGRlZXBjb3B5KGRhdGEpO1xuICAvLyBXZSBuZXZlciBjaGFuZ2Ugb3JpZ2luYWxEYXRhLCBzbyB3ZSBkbyBub3QgbmVlZCBhIGRlZXAgY29weVxuICB0aGlzLm9yaWdpbmFsRGF0YSA9IG9yaWdpbmFsRGF0YTtcblxuICAvLyBUaGUgdGltZXN0YW1wIHdlJ2xsIHVzZSBmb3IgdGhpcyB3aG9sZSBvcGVyYXRpb25cbiAgdGhpcy51cGRhdGVkQXQgPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKCkpLmlzbztcbn1cblxuLy8gQSBjb252ZW5pZW50IG1ldGhvZCB0byBwZXJmb3JtIGFsbCB0aGUgc3RlcHMgb2YgcHJvY2Vzc2luZyB0aGVcbi8vIHdyaXRlLCBpbiBvcmRlci5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHtyZXNwb25zZSwgc3RhdHVzLCBsb2NhdGlvbn0gb2JqZWN0LlxuLy8gc3RhdHVzIGFuZCBsb2NhdGlvbiBhcmUgb3B0aW9uYWwuXG5SZXN0V3JpdGUucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLmdldFVzZXJBbmRSb2xlQUNMKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnZhbGlkYXRlQ2xpZW50Q2xhc3NDcmVhdGlvbigpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVJbnN0YWxsYXRpb24oKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlU2Vzc2lvbigpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy52YWxpZGF0ZUF1dGhEYXRhKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnJ1bkJlZm9yZVRyaWdnZXIoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGVTY2hlbWEoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0UmVxdWlyZWRGaWVsZHNJZk5lZWRlZCgpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy50cmFuc2Zvcm1Vc2VyKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLmV4cGFuZEZpbGVzRm9yRXhpc3RpbmdPYmplY3RzKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLmRlc3Ryb3lEdXBsaWNhdGVkU2Vzc2lvbnMoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucnVuRGF0YWJhc2VPcGVyYXRpb24oKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlU2Vzc2lvblRva2VuSWZOZWVkZWQoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlRm9sbG93dXAoKTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucnVuQWZ0ZXJUcmlnZ2VyKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLmNsZWFuVXNlckF1dGhEYXRhKCk7XG4gIH0pLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnJlc3BvbnNlO1xuICB9KVxufTtcblxuLy8gVXNlcyB0aGUgQXV0aCBvYmplY3QgdG8gZ2V0IHRoZSBsaXN0IG9mIHJvbGVzLCBhZGRzIHRoZSB1c2VyIGlkXG5SZXN0V3JpdGUucHJvdG90eXBlLmdldFVzZXJBbmRSb2xlQUNMID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICB0aGlzLnJ1bk9wdGlvbnMuYWNsID0gWycqJ107XG5cbiAgaWYgKHRoaXMuYXV0aC51c2VyKSB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5nZXRVc2VyUm9sZXMoKS50aGVuKChyb2xlcykgPT4ge1xuICAgICAgdGhpcy5ydW5PcHRpb25zLmFjbCA9IHRoaXMucnVuT3B0aW9ucy5hY2wuY29uY2F0KHJvbGVzLCBbdGhpcy5hdXRoLnVzZXIuaWRdKTtcbiAgICAgIHJldHVybjtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbn07XG5cbi8vIFZhbGlkYXRlcyB0aGlzIG9wZXJhdGlvbiBhZ2FpbnN0IHRoZSBhbGxvd0NsaWVudENsYXNzQ3JlYXRpb24gY29uZmlnLlxuUmVzdFdyaXRlLnByb3RvdHlwZS52YWxpZGF0ZUNsaWVudENsYXNzQ3JlYXRpb24gPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuY29uZmlnLmFsbG93Q2xpZW50Q2xhc3NDcmVhdGlvbiA9PT0gZmFsc2UgJiYgIXRoaXMuYXV0aC5pc01hc3RlclxuICAgICAgJiYgU2NoZW1hQ29udHJvbGxlci5zeXN0ZW1DbGFzc2VzLmluZGV4T2YodGhpcy5jbGFzc05hbWUpID09PSAtMSkge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS5sb2FkU2NoZW1hKClcbiAgICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4gc2NoZW1hQ29udHJvbGxlci5oYXNDbGFzcyh0aGlzLmNsYXNzTmFtZSkpXG4gICAgICAudGhlbihoYXNDbGFzcyA9PiB7XG4gICAgICAgIGlmIChoYXNDbGFzcyAhPT0gdHJ1ZSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgJ1RoaXMgdXNlciBpcyBub3QgYWxsb3dlZCB0byBhY2Nlc3MgJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdub24tZXhpc3RlbnQgY2xhc3M6ICcgKyB0aGlzLmNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxufTtcblxuLy8gVmFsaWRhdGVzIHRoaXMgb3BlcmF0aW9uIGFnYWluc3QgdGhlIHNjaGVtYS5cblJlc3RXcml0ZS5wcm90b3R5cGUudmFsaWRhdGVTY2hlbWEgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLnZhbGlkYXRlT2JqZWN0KHRoaXMuY2xhc3NOYW1lLCB0aGlzLmRhdGEsIHRoaXMucXVlcnksIHRoaXMucnVuT3B0aW9ucyk7XG59O1xuXG4vLyBSdW5zIGFueSBiZWZvcmVTYXZlIHRyaWdnZXJzIGFnYWluc3QgdGhpcyBvcGVyYXRpb24uXG4vLyBBbnkgY2hhbmdlIGxlYWRzIHRvIG91ciBkYXRhIGJlaW5nIG11dGF0ZWQuXG5SZXN0V3JpdGUucHJvdG90eXBlLnJ1bkJlZm9yZVRyaWdnZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMucmVzcG9uc2UpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBBdm9pZCBkb2luZyBhbnkgc2V0dXAgZm9yIHRyaWdnZXJzIGlmIHRoZXJlIGlzIG5vICdiZWZvcmVTYXZlJyB0cmlnZ2VyIGZvciB0aGlzIGNsYXNzLlxuICBpZiAoIXRyaWdnZXJzLnRyaWdnZXJFeGlzdHModGhpcy5jbGFzc05hbWUsIHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsIHRoaXMuY29uZmlnLmFwcGxpY2F0aW9uSWQpKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgLy8gQ2xvdWQgY29kZSBnZXRzIGEgYml0IG9mIGV4dHJhIGRhdGEgZm9yIGl0cyBvYmplY3RzXG4gIHZhciBleHRyYURhdGEgPSB7Y2xhc3NOYW1lOiB0aGlzLmNsYXNzTmFtZX07XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICBleHRyYURhdGEub2JqZWN0SWQgPSB0aGlzLnF1ZXJ5Lm9iamVjdElkO1xuICB9XG5cbiAgbGV0IG9yaWdpbmFsT2JqZWN0ID0gbnVsbDtcbiAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRoaXMuYnVpbGRVcGRhdGVkT2JqZWN0KGV4dHJhRGF0YSk7XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICAvLyBUaGlzIGlzIGFuIHVwZGF0ZSBmb3IgZXhpc3Rpbmcgb2JqZWN0LlxuICAgIG9yaWdpbmFsT2JqZWN0ID0gdHJpZ2dlcnMuaW5mbGF0ZShleHRyYURhdGEsIHRoaXMub3JpZ2luYWxEYXRhKTtcbiAgfVxuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdHJpZ2dlcnMubWF5YmVSdW5UcmlnZ2VyKHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsIHRoaXMuYXV0aCwgdXBkYXRlZE9iamVjdCwgb3JpZ2luYWxPYmplY3QsIHRoaXMuY29uZmlnKTtcbiAgfSkudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2Uub2JqZWN0KSB7XG4gICAgICB0aGlzLnN0b3JhZ2UuZmllbGRzQ2hhbmdlZEJ5VHJpZ2dlciA9IF8ucmVkdWNlKHJlc3BvbnNlLm9iamVjdCwgKHJlc3VsdCwgdmFsdWUsIGtleSkgPT4ge1xuICAgICAgICBpZiAoIV8uaXNFcXVhbCh0aGlzLmRhdGFba2V5XSwgdmFsdWUpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSwgW10pO1xuICAgICAgdGhpcy5kYXRhID0gcmVzcG9uc2Uub2JqZWN0O1xuICAgICAgLy8gV2Ugc2hvdWxkIGRlbGV0ZSB0aGUgb2JqZWN0SWQgZm9yIGFuIHVwZGF0ZSB3cml0ZVxuICAgICAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgICAgICBkZWxldGUgdGhpcy5kYXRhLm9iamVjdElkXG4gICAgICB9XG4gICAgfVxuICB9KTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuc2V0UmVxdWlyZWRGaWVsZHNJZk5lZWRlZCA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5kYXRhKSB7XG4gICAgLy8gQWRkIGRlZmF1bHQgZmllbGRzXG4gICAgdGhpcy5kYXRhLnVwZGF0ZWRBdCA9IHRoaXMudXBkYXRlZEF0O1xuICAgIGlmICghdGhpcy5xdWVyeSkge1xuICAgICAgdGhpcy5kYXRhLmNyZWF0ZWRBdCA9IHRoaXMudXBkYXRlZEF0O1xuXG4gICAgICAvLyBPbmx5IGFzc2lnbiBuZXcgb2JqZWN0SWQgaWYgd2UgYXJlIGNyZWF0aW5nIG5ldyBvYmplY3RcbiAgICAgIGlmICghdGhpcy5kYXRhLm9iamVjdElkKSB7XG4gICAgICAgIHRoaXMuZGF0YS5vYmplY3RJZCA9IGNyeXB0b1V0aWxzLm5ld09iamVjdElkKHRoaXMuY29uZmlnLm9iamVjdElkU2l6ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn07XG5cbi8vIFRyYW5zZm9ybXMgYXV0aCBkYXRhIGZvciBhIHVzZXIgb2JqZWN0LlxuLy8gRG9lcyBub3RoaW5nIGlmIHRoaXMgaXNuJ3QgYSB1c2VyIG9iamVjdC5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciB3aGVuIHdlJ3JlIGRvbmUgaWYgaXQgY2FuJ3QgZmluaXNoIHRoaXMgdGljay5cblJlc3RXcml0ZS5wcm90b3R5cGUudmFsaWRhdGVBdXRoRGF0YSA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIXRoaXMucXVlcnkgJiYgIXRoaXMuZGF0YS5hdXRoRGF0YSkge1xuICAgIGlmICh0eXBlb2YgdGhpcy5kYXRhLnVzZXJuYW1lICE9PSAnc3RyaW5nJyB8fCBfLmlzRW1wdHkodGhpcy5kYXRhLnVzZXJuYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlVTRVJOQU1FX01JU1NJTkcsXG4gICAgICAgICdiYWQgb3IgbWlzc2luZyB1c2VybmFtZScpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHRoaXMuZGF0YS5wYXNzd29yZCAhPT0gJ3N0cmluZycgfHwgXy5pc0VtcHR5KHRoaXMuZGF0YS5wYXNzd29yZCkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QQVNTV09SRF9NSVNTSU5HLFxuICAgICAgICAncGFzc3dvcmQgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXRoaXMuZGF0YS5hdXRoRGF0YSB8fCAhT2JqZWN0LmtleXModGhpcy5kYXRhLmF1dGhEYXRhKS5sZW5ndGgpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgYXV0aERhdGEgPSB0aGlzLmRhdGEuYXV0aERhdGE7XG4gIHZhciBwcm92aWRlcnMgPSBPYmplY3Qua2V5cyhhdXRoRGF0YSk7XG4gIGlmIChwcm92aWRlcnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGNhbkhhbmRsZUF1dGhEYXRhID0gcHJvdmlkZXJzLnJlZHVjZSgoY2FuSGFuZGxlLCBwcm92aWRlcikgPT4ge1xuICAgICAgdmFyIHByb3ZpZGVyQXV0aERhdGEgPSBhdXRoRGF0YVtwcm92aWRlcl07XG4gICAgICB2YXIgaGFzVG9rZW4gPSAocHJvdmlkZXJBdXRoRGF0YSAmJiBwcm92aWRlckF1dGhEYXRhLmlkKTtcbiAgICAgIHJldHVybiBjYW5IYW5kbGUgJiYgKGhhc1Rva2VuIHx8IHByb3ZpZGVyQXV0aERhdGEgPT0gbnVsbCk7XG4gICAgfSwgdHJ1ZSk7XG4gICAgaWYgKGNhbkhhbmRsZUF1dGhEYXRhKSB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVBdXRoRGF0YShhdXRoRGF0YSk7XG4gICAgfVxuICB9XG4gIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5VTlNVUFBPUlRFRF9TRVJWSUNFLFxuICAgICdUaGlzIGF1dGhlbnRpY2F0aW9uIG1ldGhvZCBpcyB1bnN1cHBvcnRlZC4nKTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuaGFuZGxlQXV0aERhdGFWYWxpZGF0aW9uID0gZnVuY3Rpb24oYXV0aERhdGEpIHtcbiAgY29uc3QgdmFsaWRhdGlvbnMgPSBPYmplY3Qua2V5cyhhdXRoRGF0YSkubWFwKChwcm92aWRlcikgPT4ge1xuICAgIGlmIChhdXRoRGF0YVtwcm92aWRlcl0gPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgY29uc3QgdmFsaWRhdGVBdXRoRGF0YSA9IHRoaXMuY29uZmlnLmF1dGhEYXRhTWFuYWdlci5nZXRWYWxpZGF0b3JGb3JQcm92aWRlcihwcm92aWRlcik7XG4gICAgaWYgKCF2YWxpZGF0ZUF1dGhEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVU5TVVBQT1JURURfU0VSVklDRSxcbiAgICAgICAgJ1RoaXMgYXV0aGVudGljYXRpb24gbWV0aG9kIGlzIHVuc3VwcG9ydGVkLicpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YVtwcm92aWRlcl0pO1xuICB9KTtcbiAgcmV0dXJuIFByb21pc2UuYWxsKHZhbGlkYXRpb25zKTtcbn1cblxuUmVzdFdyaXRlLnByb3RvdHlwZS5maW5kVXNlcnNXaXRoQXV0aERhdGEgPSBmdW5jdGlvbihhdXRoRGF0YSkge1xuICBjb25zdCBwcm92aWRlcnMgPSBPYmplY3Qua2V5cyhhdXRoRGF0YSk7XG4gIGNvbnN0IHF1ZXJ5ID0gcHJvdmlkZXJzLnJlZHVjZSgobWVtbywgcHJvdmlkZXIpID0+IHtcbiAgICBpZiAoIWF1dGhEYXRhW3Byb3ZpZGVyXSkge1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfVxuICAgIGNvbnN0IHF1ZXJ5S2V5ID0gYGF1dGhEYXRhLiR7cHJvdmlkZXJ9LmlkYDtcbiAgICBjb25zdCBxdWVyeSA9IHt9O1xuICAgIHF1ZXJ5W3F1ZXJ5S2V5XSA9IGF1dGhEYXRhW3Byb3ZpZGVyXS5pZDtcbiAgICBtZW1vLnB1c2gocXVlcnkpO1xuICAgIHJldHVybiBtZW1vO1xuICB9LCBbXSkuZmlsdGVyKChxKSA9PiB7XG4gICAgcmV0dXJuIHR5cGVvZiBxICE9PSAndW5kZWZpbmVkJztcbiAgfSk7XG5cbiAgbGV0IGZpbmRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKFtdKTtcbiAgaWYgKHF1ZXJ5Lmxlbmd0aCA+IDApIHtcbiAgICBmaW5kUHJvbWlzZSA9IHRoaXMuY29uZmlnLmRhdGFiYXNlLmZpbmQoXG4gICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgIHsnJG9yJzogcXVlcnl9LCB7fSlcbiAgfVxuXG4gIHJldHVybiBmaW5kUHJvbWlzZTtcbn1cblxuUmVzdFdyaXRlLnByb3RvdHlwZS5maWx0ZXJlZE9iamVjdHNCeUFDTCA9IGZ1bmN0aW9uKG9iamVjdHMpIHtcbiAgaWYgKHRoaXMuYXV0aC5pc01hc3Rlcikge1xuICAgIHJldHVybiBvYmplY3RzO1xuICB9XG4gIHJldHVybiBvYmplY3RzLmZpbHRlcigob2JqZWN0KSA9PiB7XG4gICAgaWYgKCFvYmplY3QuQUNMKSB7XG4gICAgICByZXR1cm4gdHJ1ZTsgLy8gbGVnYWN5IHVzZXJzIHRoYXQgaGF2ZSBubyBBQ0wgZmllbGQgb24gdGhlbVxuICAgIH1cbiAgICAvLyBSZWd1bGFyIHVzZXJzIHRoYXQgaGF2ZSBiZWVuIGxvY2tlZCBvdXQuXG4gICAgcmV0dXJuIG9iamVjdC5BQ0wgJiYgT2JqZWN0LmtleXMob2JqZWN0LkFDTCkubGVuZ3RoID4gMDtcbiAgfSk7XG59XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuaGFuZGxlQXV0aERhdGEgPSBmdW5jdGlvbihhdXRoRGF0YSkge1xuICBsZXQgcmVzdWx0cztcbiAgcmV0dXJuIHRoaXMuZmluZFVzZXJzV2l0aEF1dGhEYXRhKGF1dGhEYXRhKS50aGVuKChyKSA9PiB7XG4gICAgcmVzdWx0cyA9IHRoaXMuZmlsdGVyZWRPYmplY3RzQnlBQ0wocik7XG4gICAgaWYgKHJlc3VsdHMubGVuZ3RoID4gMSkge1xuICAgICAgLy8gTW9yZSB0aGFuIDEgdXNlciB3aXRoIHRoZSBwYXNzZWQgaWQnc1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkFDQ09VTlRfQUxSRUFEWV9MSU5LRUQsXG4gICAgICAgICd0aGlzIGF1dGggaXMgYWxyZWFkeSB1c2VkJyk7XG4gICAgfVxuXG4gICAgdGhpcy5zdG9yYWdlWydhdXRoUHJvdmlkZXInXSA9IE9iamVjdC5rZXlzKGF1dGhEYXRhKS5qb2luKCcsJyk7XG5cbiAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCB1c2VyUmVzdWx0ID0gcmVzdWx0c1swXTtcbiAgICAgIGNvbnN0IG11dGF0ZWRBdXRoRGF0YSA9IHt9O1xuICAgICAgT2JqZWN0LmtleXMoYXV0aERhdGEpLmZvckVhY2goKHByb3ZpZGVyKSA9PiB7XG4gICAgICAgIGNvbnN0IHByb3ZpZGVyRGF0YSA9IGF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgICAgY29uc3QgdXNlckF1dGhEYXRhID0gdXNlclJlc3VsdC5hdXRoRGF0YVtwcm92aWRlcl07XG4gICAgICAgIGlmICghXy5pc0VxdWFsKHByb3ZpZGVyRGF0YSwgdXNlckF1dGhEYXRhKSkge1xuICAgICAgICAgIG11dGF0ZWRBdXRoRGF0YVtwcm92aWRlcl0gPSBwcm92aWRlckRhdGE7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgY29uc3QgaGFzTXV0YXRlZEF1dGhEYXRhID0gT2JqZWN0LmtleXMobXV0YXRlZEF1dGhEYXRhKS5sZW5ndGggIT09IDA7XG4gICAgICBsZXQgdXNlcklkO1xuICAgICAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgICAgICB1c2VySWQgPSB0aGlzLnF1ZXJ5Lm9iamVjdElkO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmF1dGggJiYgdGhpcy5hdXRoLnVzZXIgJiYgdGhpcy5hdXRoLnVzZXIuaWQpIHtcbiAgICAgICAgdXNlcklkID0gdGhpcy5hdXRoLnVzZXIuaWQ7XG4gICAgICB9XG4gICAgICBpZiAoIXVzZXJJZCB8fCB1c2VySWQgPT09IHVzZXJSZXN1bHQub2JqZWN0SWQpIHsgLy8gbm8gdXNlciBtYWtpbmcgdGhlIGNhbGxcbiAgICAgICAgLy8gT1IgdGhlIHVzZXIgbWFraW5nIHRoZSBjYWxsIGlzIHRoZSByaWdodCBvbmVcbiAgICAgICAgLy8gTG9naW4gd2l0aCBhdXRoIGRhdGFcbiAgICAgICAgZGVsZXRlIHJlc3VsdHNbMF0ucGFzc3dvcmQ7XG5cbiAgICAgICAgLy8gbmVlZCB0byBzZXQgdGhlIG9iamVjdElkIGZpcnN0IG90aGVyd2lzZSBsb2NhdGlvbiBoYXMgdHJhaWxpbmcgdW5kZWZpbmVkXG4gICAgICAgIHRoaXMuZGF0YS5vYmplY3RJZCA9IHVzZXJSZXN1bHQub2JqZWN0SWQ7XG5cbiAgICAgICAgaWYgKCF0aGlzLnF1ZXJ5IHx8ICF0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7IC8vIHRoaXMgYSBsb2dpbiBjYWxsLCBubyB1c2VySWQgcGFzc2VkXG4gICAgICAgICAgdGhpcy5yZXNwb25zZSA9IHtcbiAgICAgICAgICAgIHJlc3BvbnNlOiB1c2VyUmVzdWx0LFxuICAgICAgICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24oKVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgd2UgZGlkbid0IGNoYW5nZSB0aGUgYXV0aCBkYXRhLCBqdXN0IGtlZXAgZ29pbmdcbiAgICAgICAgaWYgKCFoYXNNdXRhdGVkQXV0aERhdGEpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gV2UgaGF2ZSBhdXRoRGF0YSB0aGF0IGlzIHVwZGF0ZWQgb24gbG9naW5cbiAgICAgICAgLy8gdGhhdCBjYW4gaGFwcGVuIHdoZW4gdG9rZW4gYXJlIHJlZnJlc2hlZCxcbiAgICAgICAgLy8gV2Ugc2hvdWxkIHVwZGF0ZSB0aGUgdG9rZW4gYW5kIGxldCB0aGUgdXNlciBpblxuICAgICAgICAvLyBXZSBzaG91bGQgb25seSBjaGVjayB0aGUgbXV0YXRlZCBrZXlzXG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZUF1dGhEYXRhVmFsaWRhdGlvbihtdXRhdGVkQXV0aERhdGEpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIC8vIElGIHdlIGhhdmUgYSByZXNwb25zZSwgd2UnbGwgc2tpcCB0aGUgZGF0YWJhc2Ugb3BlcmF0aW9uIC8gYmVmb3JlU2F2ZSAvIGFmdGVyU2F2ZSBldGMuLi5cbiAgICAgICAgICAvLyB3ZSBuZWVkIHRvIHNldCBpdCB1cCB0aGVyZS5cbiAgICAgICAgICAvLyBXZSBhcmUgc3VwcG9zZWQgdG8gaGF2ZSBhIHJlc3BvbnNlIG9ubHkgb24gTE9HSU4gd2l0aCBhdXRoRGF0YSwgc28gd2Ugc2tpcCB0aG9zZVxuICAgICAgICAgIC8vIElmIHdlJ3JlIG5vdCBsb2dnaW5nIGluLCBidXQganVzdCB1cGRhdGluZyB0aGUgY3VycmVudCB1c2VyLCB3ZSBjYW4gc2FmZWx5IHNraXAgdGhhdCBwYXJ0XG4gICAgICAgICAgaWYgKHRoaXMucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgbmV3IGF1dGhEYXRhIGluIHRoZSByZXNwb25zZVxuICAgICAgICAgICAgT2JqZWN0LmtleXMobXV0YXRlZEF1dGhEYXRhKS5mb3JFYWNoKChwcm92aWRlcikgPT4ge1xuICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlLmF1dGhEYXRhW3Byb3ZpZGVyXSA9IG11dGF0ZWRBdXRoRGF0YVtwcm92aWRlcl07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIFJ1biB0aGUgREIgdXBkYXRlIGRpcmVjdGx5LCBhcyAnbWFzdGVyJ1xuICAgICAgICAgICAgLy8gSnVzdCB1cGRhdGUgdGhlIGF1dGhEYXRhIHBhcnRcbiAgICAgICAgICAgIC8vIFRoZW4gd2UncmUgZ29vZCBmb3IgdGhlIHVzZXIsIGVhcmx5IGV4aXQgb2Ygc29ydHNcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS51cGRhdGUodGhpcy5jbGFzc05hbWUsIHtvYmplY3RJZDogdGhpcy5kYXRhLm9iamVjdElkfSwge2F1dGhEYXRhOiBtdXRhdGVkQXV0aERhdGF9LCB7fSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAodXNlcklkKSB7XG4gICAgICAgIC8vIFRyeWluZyB0byB1cGRhdGUgYXV0aCBkYXRhIGJ1dCB1c2Vyc1xuICAgICAgICAvLyBhcmUgZGlmZmVyZW50XG4gICAgICAgIGlmICh1c2VyUmVzdWx0Lm9iamVjdElkICE9PSB1c2VySWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuQUNDT1VOVF9BTFJFQURZX0xJTktFRCxcbiAgICAgICAgICAgICd0aGlzIGF1dGggaXMgYWxyZWFkeSB1c2VkJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm8gYXV0aCBkYXRhIHdhcyBtdXRhdGVkLCBqdXN0IGtlZXAgZ29pbmdcbiAgICAgICAgaWYgKCFoYXNNdXRhdGVkQXV0aERhdGEpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlQXV0aERhdGFWYWxpZGF0aW9uKGF1dGhEYXRhKTtcbiAgfSk7XG59XG5cblxuLy8gVGhlIG5vbi10aGlyZC1wYXJ0eSBwYXJ0cyBvZiBVc2VyIHRyYW5zZm9ybWF0aW9uXG5SZXN0V3JpdGUucHJvdG90eXBlLnRyYW5zZm9ybVVzZXIgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICBpZiAodGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicpIHtcbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfVxuXG4gIGlmICghdGhpcy5hdXRoLmlzTWFzdGVyICYmIFwiZW1haWxWZXJpZmllZFwiIGluIHRoaXMuZGF0YSkge1xuICAgIGNvbnN0IGVycm9yID0gYENsaWVudHMgYXJlbid0IGFsbG93ZWQgdG8gbWFudWFsbHkgdXBkYXRlIGVtYWlsIHZlcmlmaWNhdGlvbi5gXG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sIGVycm9yKTtcbiAgfVxuXG4gIC8vIERvIG5vdCBjbGVhbnVwIHNlc3Npb24gaWYgb2JqZWN0SWQgaXMgbm90IHNldFxuICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLm9iamVjdElkKCkpIHtcbiAgICAvLyBJZiB3ZSdyZSB1cGRhdGluZyBhIF9Vc2VyIG9iamVjdCwgd2UgbmVlZCB0byBjbGVhciBvdXQgdGhlIGNhY2hlIGZvciB0aGF0IHVzZXIuIEZpbmQgYWxsIHRoZWlyXG4gICAgLy8gc2Vzc2lvbiB0b2tlbnMsIGFuZCByZW1vdmUgdGhlbSBmcm9tIHRoZSBjYWNoZS5cbiAgICBwcm9taXNlID0gbmV3IFJlc3RRdWVyeSh0aGlzLmNvbmZpZywgQXV0aC5tYXN0ZXIodGhpcy5jb25maWcpLCAnX1Nlc3Npb24nLCB7XG4gICAgICB1c2VyOiB7XG4gICAgICAgIF9fdHlwZTogXCJQb2ludGVyXCIsXG4gICAgICAgIGNsYXNzTmFtZTogXCJfVXNlclwiLFxuICAgICAgICBvYmplY3RJZDogdGhpcy5vYmplY3RJZCgpLFxuICAgICAgfVxuICAgIH0pLmV4ZWN1dGUoKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHJlc3VsdHMucmVzdWx0cy5mb3JFYWNoKHNlc3Npb24gPT4gdGhpcy5jb25maWcuY2FjaGVDb250cm9sbGVyLnVzZXIuZGVsKHNlc3Npb24uc2Vzc2lvblRva2VuKSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBwcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgIC8vIFRyYW5zZm9ybSB0aGUgcGFzc3dvcmRcbiAgICBpZiAodGhpcy5kYXRhLnBhc3N3b3JkID09PSB1bmRlZmluZWQpIHsgLy8gaWdub3JlIG9ubHkgaWYgdW5kZWZpbmVkLiBzaG91bGQgcHJvY2VlZCBpZiBlbXB0eSAoJycpXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucXVlcnkpIHtcbiAgICAgIHRoaXMuc3RvcmFnZVsnY2xlYXJTZXNzaW9ucyddID0gdHJ1ZTtcbiAgICAgIC8vIEdlbmVyYXRlIGEgbmV3IHNlc3Npb24gb25seSBpZiB0aGUgdXNlciByZXF1ZXN0ZWRcbiAgICAgIGlmICghdGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgICAgIHRoaXMuc3RvcmFnZVsnZ2VuZXJhdGVOZXdTZXNzaW9uJ10gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl92YWxpZGF0ZVBhc3N3b3JkUG9saWN5KCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gcGFzc3dvcmRDcnlwdG8uaGFzaCh0aGlzLmRhdGEucGFzc3dvcmQpLnRoZW4oKGhhc2hlZFBhc3N3b3JkKSA9PiB7XG4gICAgICAgIHRoaXMuZGF0YS5faGFzaGVkX3Bhc3N3b3JkID0gaGFzaGVkUGFzc3dvcmQ7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmRhdGEucGFzc3dvcmQ7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5fdmFsaWRhdGVVc2VyTmFtZSgpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5fdmFsaWRhdGVFbWFpbCgpO1xuICB9KTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuX3ZhbGlkYXRlVXNlck5hbWUgPSBmdW5jdGlvbiAoKSB7XG4gIC8vIENoZWNrIGZvciB1c2VybmFtZSB1bmlxdWVuZXNzXG4gIGlmICghdGhpcy5kYXRhLnVzZXJuYW1lKSB7XG4gICAgaWYgKCF0aGlzLnF1ZXJ5KSB7XG4gICAgICB0aGlzLmRhdGEudXNlcm5hbWUgPSBjcnlwdG9VdGlscy5yYW5kb21TdHJpbmcoMjUpO1xuICAgICAgdGhpcy5yZXNwb25zZVNob3VsZEhhdmVVc2VybmFtZSA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICAvLyBXZSBuZWVkIHRvIGEgZmluZCB0byBjaGVjayBmb3IgZHVwbGljYXRlIHVzZXJuYW1lIGluIGNhc2UgdGhleSBhcmUgbWlzc2luZyB0aGUgdW5pcXVlIGluZGV4IG9uIHVzZXJuYW1lc1xuICAvLyBUT0RPOiBDaGVjayBpZiB0aGVyZSBpcyBhIHVuaXF1ZSBpbmRleCwgYW5kIGlmIHNvLCBza2lwIHRoaXMgcXVlcnkuXG4gIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS5maW5kKFxuICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgIHt1c2VybmFtZTogdGhpcy5kYXRhLnVzZXJuYW1lLCBvYmplY3RJZDogeyckbmUnOiB0aGlzLm9iamVjdElkKCl9fSxcbiAgICB7bGltaXQ6IDF9XG4gICkudGhlbihyZXN1bHRzID0+IHtcbiAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVVNFUk5BTUVfVEFLRU4sICdBY2NvdW50IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIHVzZXJuYW1lLicpO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH0pO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5fdmFsaWRhdGVFbWFpbCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMuZGF0YS5lbWFpbCB8fCB0aGlzLmRhdGEuZW1haWwuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gVmFsaWRhdGUgYmFzaWMgZW1haWwgYWRkcmVzcyBmb3JtYXRcbiAgaWYgKCF0aGlzLmRhdGEuZW1haWwubWF0Y2goL14uK0AuKyQvKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9FTUFJTF9BRERSRVNTLCAnRW1haWwgYWRkcmVzcyBmb3JtYXQgaXMgaW52YWxpZC4nKSk7XG4gIH1cbiAgLy8gU2FtZSBwcm9ibGVtIGZvciBlbWFpbCBhcyBhYm92ZSBmb3IgdXNlcm5hbWVcbiAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLmZpbmQoXG4gICAgdGhpcy5jbGFzc05hbWUsXG4gICAge2VtYWlsOiB0aGlzLmRhdGEuZW1haWwsIG9iamVjdElkOiB7JyRuZSc6IHRoaXMub2JqZWN0SWQoKX19LFxuICAgIHtsaW1pdDogMX1cbiAgKS50aGVuKHJlc3VsdHMgPT4ge1xuICAgIGlmIChyZXN1bHRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5FTUFJTF9UQUtFTiwgJ0FjY291bnQgYWxyZWFkeSBleGlzdHMgZm9yIHRoaXMgZW1haWwgYWRkcmVzcy4nKTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgIXRoaXMuZGF0YS5hdXRoRGF0YSB8fFxuICAgICAgIU9iamVjdC5rZXlzKHRoaXMuZGF0YS5hdXRoRGF0YSkubGVuZ3RoIHx8XG4gICAgICBPYmplY3Qua2V5cyh0aGlzLmRhdGEuYXV0aERhdGEpLmxlbmd0aCA9PT0gMSAmJiBPYmplY3Qua2V5cyh0aGlzLmRhdGEuYXV0aERhdGEpWzBdID09PSAnYW5vbnltb3VzJ1xuICAgICkge1xuICAgICAgLy8gV2UgdXBkYXRlZCB0aGUgZW1haWwsIHNlbmQgYSBuZXcgdmFsaWRhdGlvblxuICAgICAgdGhpcy5zdG9yYWdlWydzZW5kVmVyaWZpY2F0aW9uRW1haWwnXSA9IHRydWU7XG4gICAgICB0aGlzLmNvbmZpZy51c2VyQ29udHJvbGxlci5zZXRFbWFpbFZlcmlmeVRva2VuKHRoaXMuZGF0YSk7XG4gICAgfVxuICB9KTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuX3ZhbGlkYXRlUGFzc3dvcmRQb2xpY3kgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCF0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeSlcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIHJldHVybiB0aGlzLl92YWxpZGF0ZVBhc3N3b3JkUmVxdWlyZW1lbnRzKCkudGhlbigoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbGlkYXRlUGFzc3dvcmRIaXN0b3J5KCk7XG4gIH0pO1xufTtcblxuXG5SZXN0V3JpdGUucHJvdG90eXBlLl92YWxpZGF0ZVBhc3N3b3JkUmVxdWlyZW1lbnRzID0gZnVuY3Rpb24oKSB7XG4gIC8vIGNoZWNrIGlmIHRoZSBwYXNzd29yZCBjb25mb3JtcyB0byB0aGUgZGVmaW5lZCBwYXNzd29yZCBwb2xpY3kgaWYgY29uZmlndXJlZFxuICBjb25zdCBwb2xpY3lFcnJvciA9ICdQYXNzd29yZCBkb2VzIG5vdCBtZWV0IHRoZSBQYXNzd29yZCBQb2xpY3kgcmVxdWlyZW1lbnRzLic7XG5cbiAgLy8gY2hlY2sgd2hldGhlciB0aGUgcGFzc3dvcmQgbWVldHMgdGhlIHBhc3N3b3JkIHN0cmVuZ3RoIHJlcXVpcmVtZW50c1xuICBpZiAodGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kucGF0dGVyblZhbGlkYXRvciAmJiAhdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kucGF0dGVyblZhbGlkYXRvcih0aGlzLmRhdGEucGFzc3dvcmQpIHx8XG4gICAgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kudmFsaWRhdG9yQ2FsbGJhY2sgJiYgIXRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5LnZhbGlkYXRvckNhbGxiYWNrKHRoaXMuZGF0YS5wYXNzd29yZCkpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsIHBvbGljeUVycm9yKSk7XG4gIH1cblxuICAvLyBjaGVjayB3aGV0aGVyIHBhc3N3b3JkIGNvbnRhaW4gdXNlcm5hbWVcbiAgaWYgKHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5LmRvTm90QWxsb3dVc2VybmFtZSA9PT0gdHJ1ZSkge1xuICAgIGlmICh0aGlzLmRhdGEudXNlcm5hbWUpIHsgLy8gdXNlcm5hbWUgaXMgbm90IHBhc3NlZCBkdXJpbmcgcGFzc3dvcmQgcmVzZXRcbiAgICAgIGlmICh0aGlzLmRhdGEucGFzc3dvcmQuaW5kZXhPZih0aGlzLmRhdGEudXNlcm5hbWUpID49IDApXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVkFMSURBVElPTl9FUlJPUiwgcG9saWN5RXJyb3IpKTtcbiAgICB9IGVsc2UgeyAvLyByZXRyaWV2ZSB0aGUgVXNlciBvYmplY3QgdXNpbmcgb2JqZWN0SWQgZHVyaW5nIHBhc3N3b3JkIHJlc2V0XG4gICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCB7b2JqZWN0SWQ6IHRoaXMub2JqZWN0SWQoKX0pXG4gICAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgICAgICB0aHJvdyB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0aGlzLmRhdGEucGFzc3dvcmQuaW5kZXhPZihyZXN1bHRzWzBdLnVzZXJuYW1lKSA+PSAwKVxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5WQUxJREFUSU9OX0VSUk9SLCBwb2xpY3lFcnJvcikpO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuX3ZhbGlkYXRlUGFzc3dvcmRIaXN0b3J5ID0gZnVuY3Rpb24oKSB7XG4gIC8vIGNoZWNrIHdoZXRoZXIgcGFzc3dvcmQgaXMgcmVwZWF0aW5nIGZyb20gc3BlY2lmaWVkIGhpc3RvcnlcbiAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5KSB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLmZpbmQoJ19Vc2VyJywge29iamVjdElkOiB0aGlzLm9iamVjdElkKCl9LCB7a2V5czogW1wiX3Bhc3N3b3JkX2hpc3RvcnlcIiwgXCJfaGFzaGVkX3Bhc3N3b3JkXCJdfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggIT0gMSkge1xuICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1c2VyID0gcmVzdWx0c1swXTtcbiAgICAgICAgbGV0IG9sZFBhc3N3b3JkcyA9IFtdO1xuICAgICAgICBpZiAodXNlci5fcGFzc3dvcmRfaGlzdG9yeSlcbiAgICAgICAgICBvbGRQYXNzd29yZHMgPSBfLnRha2UodXNlci5fcGFzc3dvcmRfaGlzdG9yeSwgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRIaXN0b3J5IC0gMSk7XG4gICAgICAgIG9sZFBhc3N3b3Jkcy5wdXNoKHVzZXIucGFzc3dvcmQpO1xuICAgICAgICBjb25zdCBuZXdQYXNzd29yZCA9IHRoaXMuZGF0YS5wYXNzd29yZDtcbiAgICAgICAgLy8gY29tcGFyZSB0aGUgbmV3IHBhc3N3b3JkIGhhc2ggd2l0aCBhbGwgb2xkIHBhc3N3b3JkIGhhc2hlc1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IG9sZFBhc3N3b3Jkcy5tYXAoZnVuY3Rpb24gKGhhc2gpIHtcbiAgICAgICAgICByZXR1cm4gcGFzc3dvcmRDcnlwdG8uY29tcGFyZShuZXdQYXNzd29yZCwgaGFzaCkudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzdWx0KSAvLyByZWplY3QgaWYgdGhlcmUgaXMgYSBtYXRjaFxuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXCJSRVBFQVRfUEFTU1dPUkRcIik7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgfSlcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHdhaXQgZm9yIGFsbCBjb21wYXJpc29ucyB0byBjb21wbGV0ZVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfSkuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICBpZiAoZXJyID09PSBcIlJFUEVBVF9QQVNTV09SRFwiKSAvLyBhIG1hdGNoIHdhcyBmb3VuZFxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5WQUxJREFUSU9OX0VSUk9SLCBgTmV3IHBhc3N3b3JkIHNob3VsZCBub3QgYmUgdGhlIHNhbWUgYXMgbGFzdCAke3RoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkSGlzdG9yeX0gcGFzc3dvcmRzLmApKTtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gIH1cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5jcmVhdGVTZXNzaW9uVG9rZW5JZk5lZWRlZCA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHRoaXMucXVlcnkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKCF0aGlzLnN0b3JhZ2VbJ2F1dGhQcm92aWRlciddIC8vIHNpZ251cCBjYWxsLCB3aXRoXG4gICAgICAmJiB0aGlzLmNvbmZpZy5wcmV2ZW50TG9naW5XaXRoVW52ZXJpZmllZEVtYWlsIC8vIG5vIGxvZ2luIHdpdGhvdXQgdmVyaWZpY2F0aW9uXG4gICAgICAmJiB0aGlzLmNvbmZpZy52ZXJpZnlVc2VyRW1haWxzKSB7IC8vIHZlcmlmaWNhdGlvbiBpcyBvblxuICAgIHJldHVybjsgLy8gZG8gbm90IGNyZWF0ZSB0aGUgc2Vzc2lvbiB0b2tlbiBpbiB0aGF0IGNhc2UhXG4gIH1cbiAgcmV0dXJuIHRoaXMuY3JlYXRlU2Vzc2lvblRva2VuKCk7XG59XG5cblJlc3RXcml0ZS5wcm90b3R5cGUuY3JlYXRlU2Vzc2lvblRva2VuID0gZnVuY3Rpb24oKSB7XG4gIC8vIGNsb3VkIGluc3RhbGxhdGlvbklkIGZyb20gQ2xvdWQgQ29kZSxcbiAgLy8gbmV2ZXIgY3JlYXRlIHNlc3Npb24gdG9rZW5zIGZyb20gdGhlcmUuXG4gIGlmICh0aGlzLmF1dGguaW5zdGFsbGF0aW9uSWQgJiYgdGhpcy5hdXRoLmluc3RhbGxhdGlvbklkID09PSAnY2xvdWQnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3Qge1xuICAgIHNlc3Npb25EYXRhLFxuICAgIGNyZWF0ZVNlc3Npb24sXG4gIH0gPSBBdXRoLmNyZWF0ZVNlc3Npb24odGhpcy5jb25maWcsIHtcbiAgICB1c2VySWQ6IHRoaXMub2JqZWN0SWQoKSxcbiAgICBjcmVhdGVkV2l0aDoge1xuICAgICAgJ2FjdGlvbic6IHRoaXMuc3RvcmFnZVsnYXV0aFByb3ZpZGVyJ10gPyAnbG9naW4nIDogJ3NpZ251cCcsXG4gICAgICAnYXV0aFByb3ZpZGVyJzogdGhpcy5zdG9yYWdlWydhdXRoUHJvdmlkZXInXSB8fCAncGFzc3dvcmQnXG4gICAgfSxcbiAgICBpbnN0YWxsYXRpb25JZDogdGhpcy5hdXRoLmluc3RhbGxhdGlvbklkLFxuICB9KTtcblxuICBpZiAodGhpcy5yZXNwb25zZSAmJiB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlKSB7XG4gICAgdGhpcy5yZXNwb25zZS5yZXNwb25zZS5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uRGF0YS5zZXNzaW9uVG9rZW47XG4gIH1cblxuICByZXR1cm4gY3JlYXRlU2Vzc2lvbigpO1xufVxuXG5SZXN0V3JpdGUucHJvdG90eXBlLmRlc3Ryb3lEdXBsaWNhdGVkU2Vzc2lvbnMgPSBmdW5jdGlvbigpIHtcbiAgLy8gT25seSBmb3IgX1Nlc3Npb24sIGFuZCBhdCBjcmVhdGlvbiB0aW1lXG4gIGlmICh0aGlzLmNsYXNzTmFtZSAhPSAnX1Nlc3Npb24nIHx8IHRoaXMucXVlcnkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gRGVzdHJveSB0aGUgc2Vzc2lvbnMgaW4gJ0JhY2tncm91bmQnXG4gIGNvbnN0IHtcbiAgICB1c2VyLFxuICAgIGluc3RhbGxhdGlvbklkLFxuICAgIHNlc3Npb25Ub2tlbixcbiAgfSA9IHRoaXMuZGF0YTtcbiAgaWYgKCF1c2VyIHx8ICFpbnN0YWxsYXRpb25JZCkgIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKCF1c2VyLm9iamVjdElkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRoaXMuY29uZmlnLmRhdGFiYXNlLmRlc3Ryb3koJ19TZXNzaW9uJywge1xuICAgIHVzZXIsXG4gICAgaW5zdGFsbGF0aW9uSWQsXG4gICAgc2Vzc2lvblRva2VuOiB7ICckbmUnOiBzZXNzaW9uVG9rZW4gfSxcbiAgfSk7XG59XG5cbi8vIEhhbmRsZXMgYW55IGZvbGxvd3VwIGxvZ2ljXG5SZXN0V3JpdGUucHJvdG90eXBlLmhhbmRsZUZvbGxvd3VwID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLnN0b3JhZ2UgJiYgdGhpcy5zdG9yYWdlWydjbGVhclNlc3Npb25zJ10gJiYgdGhpcy5jb25maWcucmV2b2tlU2Vzc2lvbk9uUGFzc3dvcmRSZXNldCkge1xuICAgIHZhciBzZXNzaW9uUXVlcnkgPSB7XG4gICAgICB1c2VyOiB7XG4gICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICBjbGFzc05hbWU6ICdfVXNlcicsXG4gICAgICAgIG9iamVjdElkOiB0aGlzLm9iamVjdElkKClcbiAgICAgIH1cbiAgICB9O1xuICAgIGRlbGV0ZSB0aGlzLnN0b3JhZ2VbJ2NsZWFyU2Vzc2lvbnMnXTtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZGVzdHJveSgnX1Nlc3Npb24nLCBzZXNzaW9uUXVlcnkpXG4gICAgICAudGhlbih0aGlzLmhhbmRsZUZvbGxvd3VwLmJpbmQodGhpcykpO1xuICB9XG5cbiAgaWYgKHRoaXMuc3RvcmFnZSAmJiB0aGlzLnN0b3JhZ2VbJ2dlbmVyYXRlTmV3U2Vzc2lvbiddKSB7XG4gICAgZGVsZXRlIHRoaXMuc3RvcmFnZVsnZ2VuZXJhdGVOZXdTZXNzaW9uJ107XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlU2Vzc2lvblRva2VuKClcbiAgICAgIC50aGVuKHRoaXMuaGFuZGxlRm9sbG93dXAuYmluZCh0aGlzKSk7XG4gIH1cblxuICBpZiAodGhpcy5zdG9yYWdlICYmIHRoaXMuc3RvcmFnZVsnc2VuZFZlcmlmaWNhdGlvbkVtYWlsJ10pIHtcbiAgICBkZWxldGUgdGhpcy5zdG9yYWdlWydzZW5kVmVyaWZpY2F0aW9uRW1haWwnXTtcbiAgICAvLyBGaXJlIGFuZCBmb3JnZXQhXG4gICAgdGhpcy5jb25maWcudXNlckNvbnRyb2xsZXIuc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHRoaXMuZGF0YSk7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlRm9sbG93dXAuYmluZCh0aGlzKTtcbiAgfVxufTtcblxuLy8gSGFuZGxlcyB0aGUgX1Nlc3Npb24gY2xhc3Mgc3BlY2lhbG5lc3MuXG4vLyBEb2VzIG5vdGhpbmcgaWYgdGhpcyBpc24ndCBhbiBfU2Vzc2lvbiBvYmplY3QuXG5SZXN0V3JpdGUucHJvdG90eXBlLmhhbmRsZVNlc3Npb24gPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMucmVzcG9uc2UgfHwgdGhpcy5jbGFzc05hbWUgIT09ICdfU2Vzc2lvbicpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIXRoaXMuYXV0aC51c2VyICYmICF0aGlzLmF1dGguaXNNYXN0ZXIpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgJ1Nlc3Npb24gdG9rZW4gcmVxdWlyZWQuJyk7XG4gIH1cblxuICAvLyBUT0RPOiBWZXJpZnkgcHJvcGVyIGVycm9yIHRvIHRocm93XG4gIGlmICh0aGlzLmRhdGEuQUNMKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsICdDYW5ub3Qgc2V0ICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAnQUNMIG9uIGEgU2Vzc2lvbi4nKTtcbiAgfVxuXG4gIGlmICh0aGlzLnF1ZXJ5KSB7XG4gICAgaWYgKHRoaXMuZGF0YS51c2VyICYmICF0aGlzLmF1dGguaXNNYXN0ZXIgJiYgdGhpcy5kYXRhLnVzZXIub2JqZWN0SWQgIT0gdGhpcy5hdXRoLnVzZXIuaWQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5kYXRhLnNlc3Npb25Ub2tlbikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUpO1xuICAgIH1cbiAgfVxuXG4gIGlmICghdGhpcy5xdWVyeSAmJiAhdGhpcy5hdXRoLmlzTWFzdGVyKSB7XG4gICAgY29uc3QgYWRkaXRpb25hbFNlc3Npb25EYXRhID0ge307XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuZGF0YSkge1xuICAgICAgaWYgKGtleSA9PT0gJ29iamVjdElkJyB8fCBrZXkgPT09ICd1c2VyJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGFkZGl0aW9uYWxTZXNzaW9uRGF0YVtrZXldID0gdGhpcy5kYXRhW2tleV07XG4gICAgfVxuXG4gICAgY29uc3QgeyBzZXNzaW9uRGF0YSwgY3JlYXRlU2Vzc2lvbiB9ID0gQXV0aC5jcmVhdGVTZXNzaW9uKHRoaXMuY29uZmlnLCB7XG4gICAgICB1c2VySWQ6IHRoaXMuYXV0aC51c2VyLmlkLFxuICAgICAgY3JlYXRlZFdpdGg6IHtcbiAgICAgICAgYWN0aW9uOiAnY3JlYXRlJyxcbiAgICAgIH0sXG4gICAgICBhZGRpdGlvbmFsU2Vzc2lvbkRhdGFcbiAgICB9KTtcblxuICAgIHJldHVybiBjcmVhdGVTZXNzaW9uKCkudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgaWYgKCFyZXN1bHRzLnJlc3BvbnNlKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgICAgJ0Vycm9yIGNyZWF0aW5nIHNlc3Npb24uJyk7XG4gICAgICB9XG4gICAgICBzZXNzaW9uRGF0YVsnb2JqZWN0SWQnXSA9IHJlc3VsdHMucmVzcG9uc2VbJ29iamVjdElkJ107XG4gICAgICB0aGlzLnJlc3BvbnNlID0ge1xuICAgICAgICBzdGF0dXM6IDIwMSxcbiAgICAgICAgbG9jYXRpb246IHJlc3VsdHMubG9jYXRpb24sXG4gICAgICAgIHJlc3BvbnNlOiBzZXNzaW9uRGF0YVxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxufTtcblxuLy8gSGFuZGxlcyB0aGUgX0luc3RhbGxhdGlvbiBjbGFzcyBzcGVjaWFsbmVzcy5cbi8vIERvZXMgbm90aGluZyBpZiB0aGlzIGlzbid0IGFuIGluc3RhbGxhdGlvbiBvYmplY3QuXG4vLyBJZiBhbiBpbnN0YWxsYXRpb24gaXMgZm91bmQsIHRoaXMgY2FuIG11dGF0ZSB0aGlzLnF1ZXJ5IGFuZCB0dXJuIGEgY3JlYXRlXG4vLyBpbnRvIGFuIHVwZGF0ZS5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciB3aGVuIHdlJ3JlIGRvbmUgaWYgaXQgY2FuJ3QgZmluaXNoIHRoaXMgdGljay5cblJlc3RXcml0ZS5wcm90b3R5cGUuaGFuZGxlSW5zdGFsbGF0aW9uID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLnJlc3BvbnNlIHx8IHRoaXMuY2xhc3NOYW1lICE9PSAnX0luc3RhbGxhdGlvbicpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIXRoaXMucXVlcnkgJiYgIXRoaXMuZGF0YS5kZXZpY2VUb2tlbiAmJiAhdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkICYmICF0aGlzLmF1dGguaW5zdGFsbGF0aW9uSWQpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTM1LFxuICAgICAgJ2F0IGxlYXN0IG9uZSBJRCBmaWVsZCAoZGV2aWNlVG9rZW4sIGluc3RhbGxhdGlvbklkKSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ211c3QgYmUgc3BlY2lmaWVkIGluIHRoaXMgb3BlcmF0aW9uJyk7XG4gIH1cblxuICAvLyBJZiB0aGUgZGV2aWNlIHRva2VuIGlzIDY0IGNoYXJhY3RlcnMgbG9uZywgd2UgYXNzdW1lIGl0IGlzIGZvciBpT1NcbiAgLy8gYW5kIGxvd2VyY2FzZSBpdC5cbiAgaWYgKHRoaXMuZGF0YS5kZXZpY2VUb2tlbiAmJiB0aGlzLmRhdGEuZGV2aWNlVG9rZW4ubGVuZ3RoID09IDY0KSB7XG4gICAgdGhpcy5kYXRhLmRldmljZVRva2VuID0gdGhpcy5kYXRhLmRldmljZVRva2VuLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICAvLyBXZSBsb3dlcmNhc2UgdGhlIGluc3RhbGxhdGlvbklkIGlmIHByZXNlbnRcbiAgaWYgKHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCkge1xuICAgIHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCA9IHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZC50b0xvd2VyQ2FzZSgpO1xuICB9XG5cbiAgbGV0IGluc3RhbGxhdGlvbklkID0gdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkO1xuXG4gIC8vIElmIGRhdGEuaW5zdGFsbGF0aW9uSWQgaXMgbm90IHNldCBhbmQgd2UncmUgbm90IG1hc3Rlciwgd2UgY2FuIGxvb2t1cCBpbiBhdXRoXG4gIGlmICghaW5zdGFsbGF0aW9uSWQgJiYgIXRoaXMuYXV0aC5pc01hc3Rlcikge1xuICAgIGluc3RhbGxhdGlvbklkID0gdGhpcy5hdXRoLmluc3RhbGxhdGlvbklkO1xuICB9XG5cbiAgaWYgKGluc3RhbGxhdGlvbklkKSB7XG4gICAgaW5zdGFsbGF0aW9uSWQgPSBpbnN0YWxsYXRpb25JZC50b0xvd2VyQ2FzZSgpO1xuICB9XG5cbiAgLy8gVXBkYXRpbmcgX0luc3RhbGxhdGlvbiBidXQgbm90IHVwZGF0aW5nIGFueXRoaW5nIGNyaXRpY2FsXG4gIGlmICh0aGlzLnF1ZXJ5ICYmICF0aGlzLmRhdGEuZGV2aWNlVG9rZW5cbiAgICAgICAgICAgICAgICAgICYmICFpbnN0YWxsYXRpb25JZCAmJiAhdGhpcy5kYXRhLmRldmljZVR5cGUpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gIHZhciBpZE1hdGNoOyAvLyBXaWxsIGJlIGEgbWF0Y2ggb24gZWl0aGVyIG9iamVjdElkIG9yIGluc3RhbGxhdGlvbklkXG4gIHZhciBvYmplY3RJZE1hdGNoO1xuICB2YXIgaW5zdGFsbGF0aW9uSWRNYXRjaDtcbiAgdmFyIGRldmljZVRva2VuTWF0Y2hlcyA9IFtdO1xuXG4gIC8vIEluc3RlYWQgb2YgaXNzdWluZyAzIHJlYWRzLCBsZXQncyBkbyBpdCB3aXRoIG9uZSBPUi5cbiAgY29uc3Qgb3JRdWVyaWVzID0gW107XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICBvclF1ZXJpZXMucHVzaCh7XG4gICAgICBvYmplY3RJZDogdGhpcy5xdWVyeS5vYmplY3RJZFxuICAgIH0pO1xuICB9XG4gIGlmIChpbnN0YWxsYXRpb25JZCkge1xuICAgIG9yUXVlcmllcy5wdXNoKHtcbiAgICAgICdpbnN0YWxsYXRpb25JZCc6IGluc3RhbGxhdGlvbklkXG4gICAgfSk7XG4gIH1cbiAgaWYgKHRoaXMuZGF0YS5kZXZpY2VUb2tlbikge1xuICAgIG9yUXVlcmllcy5wdXNoKHsnZGV2aWNlVG9rZW4nOiB0aGlzLmRhdGEuZGV2aWNlVG9rZW59KTtcbiAgfVxuXG4gIGlmIChvclF1ZXJpZXMubGVuZ3RoID09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm9taXNlID0gcHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZCgnX0luc3RhbGxhdGlvbicsIHtcbiAgICAgICckb3InOiBvclF1ZXJpZXNcbiAgICB9LCB7fSk7XG4gIH0pLnRoZW4oKHJlc3VsdHMpID0+IHtcbiAgICByZXN1bHRzLmZvckVhY2goKHJlc3VsdCkgPT4ge1xuICAgICAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCAmJiByZXN1bHQub2JqZWN0SWQgPT0gdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgICAgICBvYmplY3RJZE1hdGNoID0gcmVzdWx0O1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdC5pbnN0YWxsYXRpb25JZCA9PSBpbnN0YWxsYXRpb25JZCkge1xuICAgICAgICBpbnN0YWxsYXRpb25JZE1hdGNoID0gcmVzdWx0O1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdC5kZXZpY2VUb2tlbiA9PSB0aGlzLmRhdGEuZGV2aWNlVG9rZW4pIHtcbiAgICAgICAgZGV2aWNlVG9rZW5NYXRjaGVzLnB1c2gocmVzdWx0KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFNhbml0eSBjaGVja3Mgd2hlbiBydW5uaW5nIGEgcXVlcnlcbiAgICBpZiAodGhpcy5xdWVyeSAmJiB0aGlzLnF1ZXJ5Lm9iamVjdElkKSB7XG4gICAgICBpZiAoIW9iamVjdElkTWF0Y2gpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgJ09iamVjdCBub3QgZm91bmQgZm9yIHVwZGF0ZS4nKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQgJiYgb2JqZWN0SWRNYXRjaC5pbnN0YWxsYXRpb25JZCAmJlxuICAgICAgICAgIHRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCAhPT0gb2JqZWN0SWRNYXRjaC5pbnN0YWxsYXRpb25JZCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTM2LFxuICAgICAgICAgICdpbnN0YWxsYXRpb25JZCBtYXkgbm90IGJlIGNoYW5nZWQgaW4gdGhpcyAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ29wZXJhdGlvbicpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuZGF0YS5kZXZpY2VUb2tlbiAmJiBvYmplY3RJZE1hdGNoLmRldmljZVRva2VuICYmXG4gICAgICAgICAgdGhpcy5kYXRhLmRldmljZVRva2VuICE9PSBvYmplY3RJZE1hdGNoLmRldmljZVRva2VuICYmXG4gICAgICAgICAgIXRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCAmJiAhb2JqZWN0SWRNYXRjaC5pbnN0YWxsYXRpb25JZCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTM2LFxuICAgICAgICAgICdkZXZpY2VUb2tlbiBtYXkgbm90IGJlIGNoYW5nZWQgaW4gdGhpcyAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ29wZXJhdGlvbicpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuZGF0YS5kZXZpY2VUeXBlICYmIHRoaXMuZGF0YS5kZXZpY2VUeXBlICYmXG4gICAgICAgICAgdGhpcy5kYXRhLmRldmljZVR5cGUgIT09IG9iamVjdElkTWF0Y2guZGV2aWNlVHlwZSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTM2LFxuICAgICAgICAgICdkZXZpY2VUeXBlIG1heSBub3QgYmUgY2hhbmdlZCBpbiB0aGlzICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnb3BlcmF0aW9uJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCAmJiBvYmplY3RJZE1hdGNoKSB7XG4gICAgICBpZE1hdGNoID0gb2JqZWN0SWRNYXRjaDtcbiAgICB9XG5cbiAgICBpZiAoaW5zdGFsbGF0aW9uSWQgJiYgaW5zdGFsbGF0aW9uSWRNYXRjaCkge1xuICAgICAgaWRNYXRjaCA9IGluc3RhbGxhdGlvbklkTWF0Y2g7XG4gICAgfVxuICAgIC8vIG5lZWQgdG8gc3BlY2lmeSBkZXZpY2VUeXBlIG9ubHkgaWYgaXQncyBuZXdcbiAgICBpZiAoIXRoaXMucXVlcnkgJiYgIXRoaXMuZGF0YS5kZXZpY2VUeXBlICYmICFpZE1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTM1LFxuICAgICAgICAnZGV2aWNlVHlwZSBtdXN0IGJlIHNwZWNpZmllZCBpbiB0aGlzIG9wZXJhdGlvbicpO1xuICAgIH1cblxuICB9KS50aGVuKCgpID0+IHtcbiAgICBpZiAoIWlkTWF0Y2gpIHtcbiAgICAgIGlmICghZGV2aWNlVG9rZW5NYXRjaGVzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2UgaWYgKGRldmljZVRva2VuTWF0Y2hlcy5sZW5ndGggPT0gMSAmJlxuICAgICAgICAoIWRldmljZVRva2VuTWF0Y2hlc1swXVsnaW5zdGFsbGF0aW9uSWQnXSB8fCAhaW5zdGFsbGF0aW9uSWQpXG4gICAgICApIHtcbiAgICAgICAgLy8gU2luZ2xlIG1hdGNoIG9uIGRldmljZSB0b2tlbiBidXQgbm9uZSBvbiBpbnN0YWxsYXRpb25JZCwgYW5kIGVpdGhlclxuICAgICAgICAvLyB0aGUgcGFzc2VkIG9iamVjdCBvciB0aGUgbWF0Y2ggaXMgbWlzc2luZyBhbiBpbnN0YWxsYXRpb25JZCwgc28gd2VcbiAgICAgICAgLy8gY2FuIGp1c3QgcmV0dXJuIHRoZSBtYXRjaC5cbiAgICAgICAgcmV0dXJuIGRldmljZVRva2VuTWF0Y2hlc1swXVsnb2JqZWN0SWQnXTtcbiAgICAgIH0gZWxzZSBpZiAoIXRoaXMuZGF0YS5pbnN0YWxsYXRpb25JZCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTMyLFxuICAgICAgICAgICdNdXN0IHNwZWNpZnkgaW5zdGFsbGF0aW9uSWQgd2hlbiBkZXZpY2VUb2tlbiAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdtYXRjaGVzIG11bHRpcGxlIEluc3RhbGxhdGlvbiBvYmplY3RzJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBNdWx0aXBsZSBkZXZpY2UgdG9rZW4gbWF0Y2hlcyBhbmQgd2Ugc3BlY2lmaWVkIGFuIGluc3RhbGxhdGlvbiBJRCxcbiAgICAgICAgLy8gb3IgYSBzaW5nbGUgbWF0Y2ggd2hlcmUgYm90aCB0aGUgcGFzc2VkIGFuZCBtYXRjaGluZyBvYmplY3RzIGhhdmVcbiAgICAgICAgLy8gYW4gaW5zdGFsbGF0aW9uIElELiBUcnkgY2xlYW5pbmcgb3V0IG9sZCBpbnN0YWxsYXRpb25zIHRoYXQgbWF0Y2hcbiAgICAgICAgLy8gdGhlIGRldmljZVRva2VuLCBhbmQgcmV0dXJuIG5pbCB0byBzaWduYWwgdGhhdCBhIG5ldyBvYmplY3Qgc2hvdWxkXG4gICAgICAgIC8vIGJlIGNyZWF0ZWQuXG4gICAgICAgIHZhciBkZWxRdWVyeSA9IHtcbiAgICAgICAgICAnZGV2aWNlVG9rZW4nOiB0aGlzLmRhdGEuZGV2aWNlVG9rZW4sXG4gICAgICAgICAgJ2luc3RhbGxhdGlvbklkJzoge1xuICAgICAgICAgICAgJyRuZSc6IGluc3RhbGxhdGlvbklkXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5kYXRhLmFwcElkZW50aWZpZXIpIHtcbiAgICAgICAgICBkZWxRdWVyeVsnYXBwSWRlbnRpZmllciddID0gdGhpcy5kYXRhLmFwcElkZW50aWZpZXI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb25maWcuZGF0YWJhc2UuZGVzdHJveSgnX0luc3RhbGxhdGlvbicsIGRlbFF1ZXJ5KVxuICAgICAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgICAgaWYgKGVyci5jb2RlID09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgICAgLy8gbm8gZGVsZXRpb25zIHdlcmUgbWFkZS4gQ2FuIGJlIGlnbm9yZWQuXG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJldGhyb3cgdGhlIGVycm9yXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRldmljZVRva2VuTWF0Y2hlcy5sZW5ndGggPT0gMSAmJlxuICAgICAgICAhZGV2aWNlVG9rZW5NYXRjaGVzWzBdWydpbnN0YWxsYXRpb25JZCddKSB7XG4gICAgICAgIC8vIEV4YWN0bHkgb25lIGRldmljZSB0b2tlbiBtYXRjaCBhbmQgaXQgZG9lc24ndCBoYXZlIGFuIGluc3RhbGxhdGlvblxuICAgICAgICAvLyBJRC4gVGhpcyBpcyB0aGUgb25lIGNhc2Ugd2hlcmUgd2Ugd2FudCB0byBtZXJnZSB3aXRoIHRoZSBleGlzdGluZ1xuICAgICAgICAvLyBvYmplY3QuXG4gICAgICAgIGNvbnN0IGRlbFF1ZXJ5ID0ge29iamVjdElkOiBpZE1hdGNoLm9iamVjdElkfTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLmRlc3Ryb3koJ19JbnN0YWxsYXRpb24nLCBkZWxRdWVyeSlcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZGV2aWNlVG9rZW5NYXRjaGVzWzBdWydvYmplY3RJZCddO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyLmNvZGUgPT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCkge1xuICAgICAgICAgICAgICAvLyBubyBkZWxldGlvbnMgd2VyZSBtYWRlLiBDYW4gYmUgaWdub3JlZFxuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyByZXRocm93IHRoZSBlcnJvclxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuZGF0YS5kZXZpY2VUb2tlbiAmJlxuICAgICAgICAgIGlkTWF0Y2guZGV2aWNlVG9rZW4gIT0gdGhpcy5kYXRhLmRldmljZVRva2VuKSB7XG4gICAgICAgICAgLy8gV2UncmUgc2V0dGluZyB0aGUgZGV2aWNlIHRva2VuIG9uIGFuIGV4aXN0aW5nIGluc3RhbGxhdGlvbiwgc29cbiAgICAgICAgICAvLyB3ZSBzaG91bGQgdHJ5IGNsZWFuaW5nIG91dCBvbGQgaW5zdGFsbGF0aW9ucyB0aGF0IG1hdGNoIHRoaXNcbiAgICAgICAgICAvLyBkZXZpY2UgdG9rZW4uXG4gICAgICAgICAgY29uc3QgZGVsUXVlcnkgPSB7XG4gICAgICAgICAgICAnZGV2aWNlVG9rZW4nOiB0aGlzLmRhdGEuZGV2aWNlVG9rZW4sXG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyBXZSBoYXZlIGEgdW5pcXVlIGluc3RhbGwgSWQsIHVzZSB0aGF0IHRvIHByZXNlcnZlXG4gICAgICAgICAgLy8gdGhlIGludGVyZXN0aW5nIGluc3RhbGxhdGlvblxuICAgICAgICAgIGlmICh0aGlzLmRhdGEuaW5zdGFsbGF0aW9uSWQpIHtcbiAgICAgICAgICAgIGRlbFF1ZXJ5WydpbnN0YWxsYXRpb25JZCddID0ge1xuICAgICAgICAgICAgICAnJG5lJzogdGhpcy5kYXRhLmluc3RhbGxhdGlvbklkXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChpZE1hdGNoLm9iamVjdElkICYmIHRoaXMuZGF0YS5vYmplY3RJZFxuICAgICAgICAgICAgICAgICAgICAmJiBpZE1hdGNoLm9iamVjdElkID09IHRoaXMuZGF0YS5vYmplY3RJZCkge1xuICAgICAgICAgICAgLy8gd2UgcGFzc2VkIGFuIG9iamVjdElkLCBwcmVzZXJ2ZSB0aGF0IGluc3RhbGF0aW9uXG4gICAgICAgICAgICBkZWxRdWVyeVsnb2JqZWN0SWQnXSA9IHtcbiAgICAgICAgICAgICAgJyRuZSc6IGlkTWF0Y2gub2JqZWN0SWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gV2hhdCB0byBkbyBoZXJlPyBjYW4ndCByZWFsbHkgY2xlYW4gdXAgZXZlcnl0aGluZy4uLlxuICAgICAgICAgICAgcmV0dXJuIGlkTWF0Y2gub2JqZWN0SWQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0aGlzLmRhdGEuYXBwSWRlbnRpZmllcikge1xuICAgICAgICAgICAgZGVsUXVlcnlbJ2FwcElkZW50aWZpZXInXSA9IHRoaXMuZGF0YS5hcHBJZGVudGlmaWVyO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kZXN0cm95KCdfSW5zdGFsbGF0aW9uJywgZGVsUXVlcnkpXG4gICAgICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICAgICAgaWYgKGVyci5jb2RlID09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgICAgICAvLyBubyBkZWxldGlvbnMgd2VyZSBtYWRlLiBDYW4gYmUgaWdub3JlZC5cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLy8gcmV0aHJvdyB0aGUgZXJyb3JcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSW4gbm9uLW1lcmdlIHNjZW5hcmlvcywganVzdCByZXR1cm4gdGhlIGluc3RhbGxhdGlvbiBtYXRjaCBpZFxuICAgICAgICByZXR1cm4gaWRNYXRjaC5vYmplY3RJZDtcbiAgICAgIH1cbiAgICB9XG4gIH0pLnRoZW4oKG9iaklkKSA9PiB7XG4gICAgaWYgKG9iaklkKSB7XG4gICAgICB0aGlzLnF1ZXJ5ID0ge29iamVjdElkOiBvYmpJZH07XG4gICAgICBkZWxldGUgdGhpcy5kYXRhLm9iamVjdElkO1xuICAgICAgZGVsZXRlIHRoaXMuZGF0YS5jcmVhdGVkQXQ7XG4gICAgfVxuICAgIC8vIFRPRE86IFZhbGlkYXRlIG9wcyAoYWRkL3JlbW92ZSBvbiBjaGFubmVscywgJGluYyBvbiBiYWRnZSwgZXRjLilcbiAgfSk7XG4gIHJldHVybiBwcm9taXNlO1xufTtcblxuLy8gSWYgd2Ugc2hvcnQtY2lyY3V0ZWQgdGhlIG9iamVjdCByZXNwb25zZSAtIHRoZW4gd2UgbmVlZCB0byBtYWtlIHN1cmUgd2UgZXhwYW5kIGFsbCB0aGUgZmlsZXMsXG4vLyBzaW5jZSB0aGlzIG1pZ2h0IG5vdCBoYXZlIGEgcXVlcnksIG1lYW5pbmcgaXQgd29uJ3QgcmV0dXJuIHRoZSBmdWxsIHJlc3VsdCBiYWNrLlxuLy8gVE9ETzogKG5sdXRzZW5rbykgVGhpcyBzaG91bGQgZGllIHdoZW4gd2UgbW92ZSB0byBwZXItY2xhc3MgYmFzZWQgY29udHJvbGxlcnMgb24gX1Nlc3Npb24vX1VzZXJcblJlc3RXcml0ZS5wcm90b3R5cGUuZXhwYW5kRmlsZXNGb3JFeGlzdGluZ09iamVjdHMgPSBmdW5jdGlvbigpIHtcbiAgLy8gQ2hlY2sgd2hldGhlciB3ZSBoYXZlIGEgc2hvcnQtY2lyY3VpdGVkIHJlc3BvbnNlIC0gb25seSB0aGVuIHJ1biBleHBhbnNpb24uXG4gIGlmICh0aGlzLnJlc3BvbnNlICYmIHRoaXMucmVzcG9uc2UucmVzcG9uc2UpIHtcbiAgICB0aGlzLmNvbmZpZy5maWxlc0NvbnRyb2xsZXIuZXhwYW5kRmlsZXNJbk9iamVjdCh0aGlzLmNvbmZpZywgdGhpcy5yZXNwb25zZS5yZXNwb25zZSk7XG4gIH1cbn07XG5cblJlc3RXcml0ZS5wcm90b3R5cGUucnVuRGF0YWJhc2VPcGVyYXRpb24gPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMucmVzcG9uc2UpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAodGhpcy5jbGFzc05hbWUgPT09ICdfUm9sZScpIHtcbiAgICB0aGlzLmNvbmZpZy5jYWNoZUNvbnRyb2xsZXIucm9sZS5jbGVhcigpO1xuICB9XG5cbiAgaWYgKHRoaXMuY2xhc3NOYW1lID09PSAnX1VzZXInICYmXG4gICAgICB0aGlzLnF1ZXJ5ICYmXG4gICAgICB0aGlzLmF1dGguaXNVbmF1dGhlbnRpY2F0ZWQoKSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5TRVNTSU9OX01JU1NJTkcsIGBDYW5ub3QgbW9kaWZ5IHVzZXIgJHt0aGlzLnF1ZXJ5Lm9iamVjdElkfS5gKTtcbiAgfVxuXG4gIGlmICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Qcm9kdWN0JyAmJiB0aGlzLmRhdGEuZG93bmxvYWQpIHtcbiAgICB0aGlzLmRhdGEuZG93bmxvYWROYW1lID0gdGhpcy5kYXRhLmRvd25sb2FkLm5hbWU7XG4gIH1cblxuICAvLyBUT0RPOiBBZGQgYmV0dGVyIGRldGVjdGlvbiBmb3IgQUNMLCBlbnN1cmluZyBhIHVzZXIgY2FuJ3QgYmUgbG9ja2VkIGZyb21cbiAgLy8gICAgICAgdGhlaXIgb3duIHVzZXIgcmVjb3JkLlxuICBpZiAodGhpcy5kYXRhLkFDTCAmJiB0aGlzLmRhdGEuQUNMWycqdW5yZXNvbHZlZCddKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfQUNMLCAnSW52YWxpZCBBQ0wuJyk7XG4gIH1cblxuICBpZiAodGhpcy5xdWVyeSkge1xuICAgIC8vIEZvcmNlIHRoZSB1c2VyIHRvIG5vdCBsb2Nrb3V0XG4gICAgLy8gTWF0Y2hlZCB3aXRoIHBhcnNlLmNvbVxuICAgIGlmICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJiB0aGlzLmRhdGEuQUNMICYmIHRoaXMuYXV0aC5pc01hc3RlciAhPT0gdHJ1ZSkge1xuICAgICAgdGhpcy5kYXRhLkFDTFt0aGlzLnF1ZXJ5Lm9iamVjdElkXSA9IHsgcmVhZDogdHJ1ZSwgd3JpdGU6IHRydWUgfTtcbiAgICB9XG4gICAgLy8gdXBkYXRlIHBhc3N3b3JkIHRpbWVzdGFtcCBpZiB1c2VyIHBhc3N3b3JkIGlzIGJlaW5nIGNoYW5nZWRcbiAgICBpZiAodGhpcy5jbGFzc05hbWUgPT09ICdfVXNlcicgJiYgdGhpcy5kYXRhLl9oYXNoZWRfcGFzc3dvcmQgJiYgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kgJiYgdGhpcy5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRBZ2UpIHtcbiAgICAgIHRoaXMuZGF0YS5fcGFzc3dvcmRfY2hhbmdlZF9hdCA9IFBhcnNlLl9lbmNvZGUobmV3IERhdGUoKSk7XG4gICAgfVxuICAgIC8vIElnbm9yZSBjcmVhdGVkQXQgd2hlbiB1cGRhdGVcbiAgICBkZWxldGUgdGhpcy5kYXRhLmNyZWF0ZWRBdDtcblxuICAgIGxldCBkZWZlciA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIC8vIGlmIHBhc3N3b3JkIGhpc3RvcnkgaXMgZW5hYmxlZCB0aGVuIHNhdmUgdGhlIGN1cnJlbnQgcGFzc3dvcmQgdG8gaGlzdG9yeVxuICAgIGlmICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJyAmJiB0aGlzLmRhdGEuX2hhc2hlZF9wYXNzd29yZCAmJiB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeSAmJiB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkpIHtcbiAgICAgIGRlZmVyID0gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCB7b2JqZWN0SWQ6IHRoaXMub2JqZWN0SWQoKX0sIHtrZXlzOiBbXCJfcGFzc3dvcmRfaGlzdG9yeVwiLCBcIl9oYXNoZWRfcGFzc3dvcmRcIl19KS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggIT0gMSkge1xuICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1c2VyID0gcmVzdWx0c1swXTtcbiAgICAgICAgbGV0IG9sZFBhc3N3b3JkcyA9IFtdO1xuICAgICAgICBpZiAodXNlci5fcGFzc3dvcmRfaGlzdG9yeSkge1xuICAgICAgICAgIG9sZFBhc3N3b3JkcyA9IF8udGFrZSh1c2VyLl9wYXNzd29yZF9oaXN0b3J5LCB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkpO1xuICAgICAgICB9XG4gICAgICAgIC8vbi0xIHBhc3N3b3JkcyBnbyBpbnRvIGhpc3RvcnkgaW5jbHVkaW5nIGxhc3QgcGFzc3dvcmRcbiAgICAgICAgd2hpbGUgKG9sZFBhc3N3b3Jkcy5sZW5ndGggPiB0aGlzLmNvbmZpZy5wYXNzd29yZFBvbGljeS5tYXhQYXNzd29yZEhpc3RvcnkgLSAyKSB7XG4gICAgICAgICAgb2xkUGFzc3dvcmRzLnNoaWZ0KCk7XG4gICAgICAgIH1cbiAgICAgICAgb2xkUGFzc3dvcmRzLnB1c2godXNlci5wYXNzd29yZCk7XG4gICAgICAgIHRoaXMuZGF0YS5fcGFzc3dvcmRfaGlzdG9yeSA9IG9sZFBhc3N3b3JkcztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBkZWZlci50aGVuKCgpID0+IHtcbiAgICAgIC8vIFJ1biBhbiB1cGRhdGVcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5kYXRhYmFzZS51cGRhdGUodGhpcy5jbGFzc05hbWUsIHRoaXMucXVlcnksIHRoaXMuZGF0YSwgdGhpcy5ydW5PcHRpb25zKVxuICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgcmVzcG9uc2UudXBkYXRlZEF0ID0gdGhpcy51cGRhdGVkQXQ7XG4gICAgICAgICAgdGhpcy5fdXBkYXRlUmVzcG9uc2VXaXRoRGF0YShyZXNwb25zZSwgdGhpcy5kYXRhKTtcbiAgICAgICAgICB0aGlzLnJlc3BvbnNlID0geyByZXNwb25zZSB9O1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICAvLyBTZXQgdGhlIGRlZmF1bHQgQUNMIGFuZCBwYXNzd29yZCB0aW1lc3RhbXAgZm9yIHRoZSBuZXcgX1VzZXJcbiAgICBpZiAodGhpcy5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICAgIHZhciBBQ0wgPSB0aGlzLmRhdGEuQUNMO1xuICAgICAgLy8gZGVmYXVsdCBwdWJsaWMgci93IEFDTFxuICAgICAgaWYgKCFBQ0wpIHtcbiAgICAgICAgQUNMID0ge307XG4gICAgICAgIEFDTFsnKiddID0geyByZWFkOiB0cnVlLCB3cml0ZTogZmFsc2UgfTtcbiAgICAgIH1cbiAgICAgIC8vIG1ha2Ugc3VyZSB0aGUgdXNlciBpcyBub3QgbG9ja2VkIGRvd25cbiAgICAgIEFDTFt0aGlzLmRhdGEub2JqZWN0SWRdID0geyByZWFkOiB0cnVlLCB3cml0ZTogdHJ1ZSB9O1xuICAgICAgdGhpcy5kYXRhLkFDTCA9IEFDTDtcbiAgICAgIC8vIHBhc3N3b3JkIHRpbWVzdGFtcCB0byBiZSB1c2VkIHdoZW4gcGFzc3dvcmQgZXhwaXJ5IHBvbGljeSBpcyBlbmZvcmNlZFxuICAgICAgaWYgKHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5ICYmIHRoaXMuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlKSB7XG4gICAgICAgIHRoaXMuZGF0YS5fcGFzc3dvcmRfY2hhbmdlZF9hdCA9IFBhcnNlLl9lbmNvZGUobmV3IERhdGUoKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUnVuIGEgY3JlYXRlXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLmNyZWF0ZSh0aGlzLmNsYXNzTmFtZSwgdGhpcy5kYXRhLCB0aGlzLnJ1bk9wdGlvbnMpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAodGhpcy5jbGFzc05hbWUgIT09ICdfVXNlcicgfHwgZXJyb3IuY29kZSAhPT0gUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBRdWljayBjaGVjaywgaWYgd2Ugd2VyZSBhYmxlIHRvIGluZmVyIHRoZSBkdXBsaWNhdGVkIGZpZWxkIG5hbWVcbiAgICAgICAgaWYgKGVycm9yICYmIGVycm9yLnVzZXJJbmZvICYmIGVycm9yLnVzZXJJbmZvLmR1cGxpY2F0ZWRfZmllbGQgPT09ICd1c2VybmFtZScpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVVNFUk5BTUVfVEFLRU4sICdBY2NvdW50IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIHVzZXJuYW1lLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGVycm9yICYmIGVycm9yLnVzZXJJbmZvICYmIGVycm9yLnVzZXJJbmZvLmR1cGxpY2F0ZWRfZmllbGQgPT09ICdlbWFpbCcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRU1BSUxfVEFLRU4sICdBY2NvdW50IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIGVtYWlsIGFkZHJlc3MuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGlzIHdhcyBhIGZhaWxlZCB1c2VyIGNyZWF0aW9uIGR1ZSB0byB1c2VybmFtZSBvciBlbWFpbCBhbHJlYWR5IHRha2VuLCB3ZSBuZWVkIHRvXG4gICAgICAgIC8vIGNoZWNrIHdoZXRoZXIgaXQgd2FzIHVzZXJuYW1lIG9yIGVtYWlsIGFuZCByZXR1cm4gdGhlIGFwcHJvcHJpYXRlIGVycm9yLlxuICAgICAgICAvLyBGYWxsYmFjayB0byB0aGUgb3JpZ2luYWwgbWV0aG9kXG4gICAgICAgIC8vIFRPRE86IFNlZSBpZiB3ZSBjYW4gbGF0ZXIgZG8gdGhpcyB3aXRob3V0IGFkZGl0aW9uYWwgcXVlcmllcyBieSB1c2luZyBuYW1lZCBpbmRleGVzLlxuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZGF0YWJhc2UuZmluZChcbiAgICAgICAgICB0aGlzLmNsYXNzTmFtZSxcbiAgICAgICAgICB7IHVzZXJuYW1lOiB0aGlzLmRhdGEudXNlcm5hbWUsIG9iamVjdElkOiB7JyRuZSc6IHRoaXMub2JqZWN0SWQoKX0gfSxcbiAgICAgICAgICB7IGxpbWl0OiAxIH1cbiAgICAgICAgKVxuICAgICAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVVNFUk5BTUVfVEFLRU4sICdBY2NvdW50IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIHVzZXJuYW1lLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRhdGFiYXNlLmZpbmQoXG4gICAgICAgICAgICAgIHRoaXMuY2xhc3NOYW1lLFxuICAgICAgICAgICAgICB7IGVtYWlsOiB0aGlzLmRhdGEuZW1haWwsIG9iamVjdElkOiB7JyRuZSc6IHRoaXMub2JqZWN0SWQoKX0gfSxcbiAgICAgICAgICAgICAgeyBsaW1pdDogMSB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5FTUFJTF9UQUtFTiwgJ0FjY291bnQgYWxyZWFkeSBleGlzdHMgZm9yIHRoaXMgZW1haWwgYWRkcmVzcy4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsICdBIGR1cGxpY2F0ZSB2YWx1ZSBmb3IgYSBmaWVsZCB3aXRoIHVuaXF1ZSB2YWx1ZXMgd2FzIHByb3ZpZGVkJyk7XG4gICAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICByZXNwb25zZS5vYmplY3RJZCA9IHRoaXMuZGF0YS5vYmplY3RJZDtcbiAgICAgICAgcmVzcG9uc2UuY3JlYXRlZEF0ID0gdGhpcy5kYXRhLmNyZWF0ZWRBdDtcblxuICAgICAgICBpZiAodGhpcy5yZXNwb25zZVNob3VsZEhhdmVVc2VybmFtZSkge1xuICAgICAgICAgIHJlc3BvbnNlLnVzZXJuYW1lID0gdGhpcy5kYXRhLnVzZXJuYW1lO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3VwZGF0ZVJlc3BvbnNlV2l0aERhdGEocmVzcG9uc2UsIHRoaXMuZGF0YSk7XG4gICAgICAgIHRoaXMucmVzcG9uc2UgPSB7XG4gICAgICAgICAgc3RhdHVzOiAyMDEsXG4gICAgICAgICAgcmVzcG9uc2UsXG4gICAgICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24oKVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gIH1cbn07XG5cbi8vIFJldHVybnMgbm90aGluZyAtIGRvZXNuJ3Qgd2FpdCBmb3IgdGhlIHRyaWdnZXIuXG5SZXN0V3JpdGUucHJvdG90eXBlLnJ1bkFmdGVyVHJpZ2dlciA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMucmVzcG9uc2UgfHwgIXRoaXMucmVzcG9uc2UucmVzcG9uc2UpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBBdm9pZCBkb2luZyBhbnkgc2V0dXAgZm9yIHRyaWdnZXJzIGlmIHRoZXJlIGlzIG5vICdhZnRlclNhdmUnIHRyaWdnZXIgZm9yIHRoaXMgY2xhc3MuXG4gIGNvbnN0IGhhc0FmdGVyU2F2ZUhvb2sgPSB0cmlnZ2Vycy50cmlnZ2VyRXhpc3RzKHRoaXMuY2xhc3NOYW1lLCB0cmlnZ2Vycy5UeXBlcy5hZnRlclNhdmUsIHRoaXMuY29uZmlnLmFwcGxpY2F0aW9uSWQpO1xuICBjb25zdCBoYXNMaXZlUXVlcnkgPSB0aGlzLmNvbmZpZy5saXZlUXVlcnlDb250cm9sbGVyLmhhc0xpdmVRdWVyeSh0aGlzLmNsYXNzTmFtZSk7XG4gIGlmICghaGFzQWZ0ZXJTYXZlSG9vayAmJiAhaGFzTGl2ZVF1ZXJ5KSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgdmFyIGV4dHJhRGF0YSA9IHtjbGFzc05hbWU6IHRoaXMuY2xhc3NOYW1lfTtcbiAgaWYgKHRoaXMucXVlcnkgJiYgdGhpcy5xdWVyeS5vYmplY3RJZCkge1xuICAgIGV4dHJhRGF0YS5vYmplY3RJZCA9IHRoaXMucXVlcnkub2JqZWN0SWQ7XG4gIH1cblxuICAvLyBCdWlsZCB0aGUgb3JpZ2luYWwgb2JqZWN0LCB3ZSBvbmx5IGRvIHRoaXMgZm9yIGEgdXBkYXRlIHdyaXRlLlxuICBsZXQgb3JpZ2luYWxPYmplY3Q7XG4gIGlmICh0aGlzLnF1ZXJ5ICYmIHRoaXMucXVlcnkub2JqZWN0SWQpIHtcbiAgICBvcmlnaW5hbE9iamVjdCA9IHRyaWdnZXJzLmluZmxhdGUoZXh0cmFEYXRhLCB0aGlzLm9yaWdpbmFsRGF0YSk7XG4gIH1cblxuICAvLyBCdWlsZCB0aGUgaW5mbGF0ZWQgb2JqZWN0LCBkaWZmZXJlbnQgZnJvbSBiZWZvcmVTYXZlLCBvcmlnaW5hbERhdGEgaXMgbm90IGVtcHR5XG4gIC8vIHNpbmNlIGRldmVsb3BlcnMgY2FuIGNoYW5nZSBkYXRhIGluIHRoZSBiZWZvcmVTYXZlLlxuICBjb25zdCB1cGRhdGVkT2JqZWN0ID0gdGhpcy5idWlsZFVwZGF0ZWRPYmplY3QoZXh0cmFEYXRhKTtcbiAgdXBkYXRlZE9iamVjdC5faGFuZGxlU2F2ZVJlc3BvbnNlKHRoaXMucmVzcG9uc2UucmVzcG9uc2UsIHRoaXMucmVzcG9uc2Uuc3RhdHVzIHx8IDIwMCk7XG5cbiAgLy8gTm90aWZpeSBMaXZlUXVlcnlTZXJ2ZXIgaWYgcG9zc2libGVcbiAgdGhpcy5jb25maWcubGl2ZVF1ZXJ5Q29udHJvbGxlci5vbkFmdGVyU2F2ZSh1cGRhdGVkT2JqZWN0LmNsYXNzTmFtZSwgdXBkYXRlZE9iamVjdCwgb3JpZ2luYWxPYmplY3QpO1xuXG4gIC8vIFJ1biBhZnRlclNhdmUgdHJpZ2dlclxuICByZXR1cm4gdHJpZ2dlcnMubWF5YmVSdW5UcmlnZ2VyKHRyaWdnZXJzLlR5cGVzLmFmdGVyU2F2ZSwgdGhpcy5hdXRoLCB1cGRhdGVkT2JqZWN0LCBvcmlnaW5hbE9iamVjdCwgdGhpcy5jb25maWcpXG4gICAgLmNhdGNoKGZ1bmN0aW9uKGVycikge1xuICAgICAgbG9nZ2VyLndhcm4oJ2FmdGVyU2F2ZSBjYXVnaHQgYW4gZXJyb3InLCBlcnIpO1xuICAgIH0pXG59O1xuXG4vLyBBIGhlbHBlciB0byBmaWd1cmUgb3V0IHdoYXQgbG9jYXRpb24gdGhpcyBvcGVyYXRpb24gaGFwcGVucyBhdC5cblJlc3RXcml0ZS5wcm90b3R5cGUubG9jYXRpb24gPSBmdW5jdGlvbigpIHtcbiAgdmFyIG1pZGRsZSA9ICh0aGlzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJyA/ICcvdXNlcnMvJyA6XG4gICAgJy9jbGFzc2VzLycgKyB0aGlzLmNsYXNzTmFtZSArICcvJyk7XG4gIHJldHVybiB0aGlzLmNvbmZpZy5tb3VudCArIG1pZGRsZSArIHRoaXMuZGF0YS5vYmplY3RJZDtcbn07XG5cbi8vIEEgaGVscGVyIHRvIGdldCB0aGUgb2JqZWN0IGlkIGZvciB0aGlzIG9wZXJhdGlvbi5cbi8vIEJlY2F1c2UgaXQgY291bGQgYmUgZWl0aGVyIG9uIHRoZSBxdWVyeSBvciBvbiB0aGUgZGF0YVxuUmVzdFdyaXRlLnByb3RvdHlwZS5vYmplY3RJZCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5kYXRhLm9iamVjdElkIHx8IHRoaXMucXVlcnkub2JqZWN0SWQ7XG59O1xuXG4vLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgZGF0YSBhbmQgZGVsZXRlIGJhZCBrZXlzIChfYXV0aF9kYXRhLCBfaGFzaGVkX3Bhc3N3b3JkLi4uKVxuUmVzdFdyaXRlLnByb3RvdHlwZS5zYW5pdGl6ZWREYXRhID0gZnVuY3Rpb24oKSB7XG4gIGNvbnN0IGRhdGEgPSBPYmplY3Qua2V5cyh0aGlzLmRhdGEpLnJlZHVjZSgoZGF0YSwga2V5KSA9PiB7XG4gICAgLy8gUmVnZXhwIGNvbWVzIGZyb20gUGFyc2UuT2JqZWN0LnByb3RvdHlwZS52YWxpZGF0ZVxuICAgIGlmICghKC9eW0EtWmEtel1bMC05QS1aYS16X10qJC8pLnRlc3Qoa2V5KSkge1xuICAgICAgZGVsZXRlIGRhdGFba2V5XTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG4gIH0sIGRlZXBjb3B5KHRoaXMuZGF0YSkpO1xuICByZXR1cm4gUGFyc2UuX2RlY29kZSh1bmRlZmluZWQsIGRhdGEpO1xufVxuXG4vLyBSZXR1cm5zIGFuIHVwZGF0ZWQgY29weSBvZiB0aGUgb2JqZWN0XG5SZXN0V3JpdGUucHJvdG90eXBlLmJ1aWxkVXBkYXRlZE9iamVjdCA9IGZ1bmN0aW9uIChleHRyYURhdGEpIHtcbiAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRyaWdnZXJzLmluZmxhdGUoZXh0cmFEYXRhLCB0aGlzLm9yaWdpbmFsRGF0YSk7XG4gIE9iamVjdC5rZXlzKHRoaXMuZGF0YSkucmVkdWNlKGZ1bmN0aW9uIChkYXRhLCBrZXkpIHtcbiAgICBpZiAoa2V5LmluZGV4T2YoXCIuXCIpID4gMCkge1xuICAgICAgLy8gc3ViZG9jdW1lbnQga2V5IHdpdGggZG90IG5vdGF0aW9uICgneC55Jzp2ID0+ICd4Jzp7J3knOnZ9KVxuICAgICAgY29uc3Qgc3BsaXR0ZWRLZXkgPSBrZXkuc3BsaXQoXCIuXCIpO1xuICAgICAgY29uc3QgcGFyZW50UHJvcCA9IHNwbGl0dGVkS2V5WzBdO1xuICAgICAgbGV0IHBhcmVudFZhbCA9IHVwZGF0ZWRPYmplY3QuZ2V0KHBhcmVudFByb3ApO1xuICAgICAgaWYodHlwZW9mIHBhcmVudFZhbCAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcGFyZW50VmFsID0ge307XG4gICAgICB9XG4gICAgICBwYXJlbnRWYWxbc3BsaXR0ZWRLZXlbMV1dID0gZGF0YVtrZXldO1xuICAgICAgdXBkYXRlZE9iamVjdC5zZXQocGFyZW50UHJvcCwgcGFyZW50VmFsKTtcbiAgICAgIGRlbGV0ZSBkYXRhW2tleV07XG4gICAgfVxuICAgIHJldHVybiBkYXRhO1xuICB9LCBkZWVwY29weSh0aGlzLmRhdGEpKTtcblxuICB1cGRhdGVkT2JqZWN0LnNldCh0aGlzLnNhbml0aXplZERhdGEoKSk7XG4gIHJldHVybiB1cGRhdGVkT2JqZWN0O1xufTtcblxuUmVzdFdyaXRlLnByb3RvdHlwZS5jbGVhblVzZXJBdXRoRGF0YSA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5yZXNwb25zZSAmJiB0aGlzLnJlc3BvbnNlLnJlc3BvbnNlICYmIHRoaXMuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgY29uc3QgdXNlciA9IHRoaXMucmVzcG9uc2UucmVzcG9uc2U7XG4gICAgaWYgKHVzZXIuYXV0aERhdGEpIHtcbiAgICAgIE9iamVjdC5rZXlzKHVzZXIuYXV0aERhdGEpLmZvckVhY2goKHByb3ZpZGVyKSA9PiB7XG4gICAgICAgIGlmICh1c2VyLmF1dGhEYXRhW3Byb3ZpZGVyXSA9PT0gbnVsbCkge1xuICAgICAgICAgIGRlbGV0ZSB1c2VyLmF1dGhEYXRhW3Byb3ZpZGVyXTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoT2JqZWN0LmtleXModXNlci5hdXRoRGF0YSkubGVuZ3RoID09IDApIHtcbiAgICAgICAgZGVsZXRlIHVzZXIuYXV0aERhdGE7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5SZXN0V3JpdGUucHJvdG90eXBlLl91cGRhdGVSZXNwb25zZVdpdGhEYXRhID0gZnVuY3Rpb24ocmVzcG9uc2UsIGRhdGEpIHtcbiAgaWYgKF8uaXNFbXB0eSh0aGlzLnN0b3JhZ2UuZmllbGRzQ2hhbmdlZEJ5VHJpZ2dlcikpIHtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cbiAgY29uc3QgY2xpZW50U3VwcG9ydHNEZWxldGUgPSBDbGllbnRTREsuc3VwcG9ydHNGb3J3YXJkRGVsZXRlKHRoaXMuY2xpZW50U0RLKTtcbiAgdGhpcy5zdG9yYWdlLmZpZWxkc0NoYW5nZWRCeVRyaWdnZXIuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgIGNvbnN0IGRhdGFWYWx1ZSA9IGRhdGFbZmllbGROYW1lXTtcblxuICAgIGlmKCFyZXNwb25zZS5oYXNPd25Qcm9wZXJ0eShmaWVsZE5hbWUpKSB7XG4gICAgICByZXNwb25zZVtmaWVsZE5hbWVdID0gZGF0YVZhbHVlO1xuICAgIH1cblxuICAgIC8vIFN0cmlwcyBvcGVyYXRpb25zIGZyb20gcmVzcG9uc2VzXG4gICAgaWYgKHJlc3BvbnNlW2ZpZWxkTmFtZV0gJiYgcmVzcG9uc2VbZmllbGROYW1lXS5fX29wKSB7XG4gICAgICBkZWxldGUgcmVzcG9uc2VbZmllbGROYW1lXTtcbiAgICAgIGlmIChjbGllbnRTdXBwb3J0c0RlbGV0ZSAmJiBkYXRhVmFsdWUuX19vcCA9PSAnRGVsZXRlJykge1xuICAgICAgICByZXNwb25zZVtmaWVsZE5hbWVdID0gZGF0YVZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG4gIHJldHVybiByZXNwb25zZTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUmVzdFdyaXRlO1xubW9kdWxlLmV4cG9ydHMgPSBSZXN0V3JpdGU7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/AggregateRouter.js b/lib/Routers/AggregateRouter.js index 2a0519915e..367604e6ab 100644 --- a/lib/Routers/AggregateRouter.js +++ b/lib/Routers/AggregateRouter.js @@ -29,30 +29,30 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -const ALLOWED_KEYS = ['where', 'distinct', 'project', 'match', 'redact', 'limit', 'skip', 'unwind', 'group', 'sample', 'sort', 'geoNear', 'lookup', 'out', 'indexStats', 'facet', 'bucket', 'bucketAuto', 'sortByCount', 'addFields', 'replaceRoot', 'count', 'graphLookup']; +const BASE_KEYS = ['where', 'distinct']; + +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 _ClassesRouter2.default { handleFind(req) { const body = Object.assign(req.body, _ClassesRouter2.default.JSONFromQuery(req.query)); const options = {}; - const pipeline = []; - - for (const key in body) { - if (ALLOWED_KEYS.indexOf(key) === -1) { - throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: ${key}`); - } - if (key === 'group') { - if (body[key].hasOwnProperty('_id')) { - throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: group. Please use objectId instead of _id`); - } - if (!body[key].hasOwnProperty('objectId')) { - throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: group. objectId is required`); - } - body[key]._id = body[key].objectId; - delete body[key].objectId; + let pipeline = []; + + if (Array.isArray(body)) { + pipeline = body.map(stage => { + const stageName = Object.keys(stage)[0]; + return this.transformStage(stageName, stage); + }); + } else { + const stages = []; + for (const stageName in body) { + stages.push(this.transformStage(stageName, body)); } - pipeline.push({ [`$${key}`]: body[key] }); + pipeline = stages; } if (body.distinct) { options.distinct = String(body.distinct); @@ -71,6 +71,23 @@ class AggregateRouter extends _ClassesRouter2.default { }); } + transformStage(stageName, stage) { + if (ALLOWED_KEYS.indexOf(stageName) === -1) { + throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: ${stageName}`); + } + if (stageName === 'group') { + if (stage[stageName].hasOwnProperty('_id')) { + throw new _node2.default.Error(_node2.default.Error.INVALID_QUERY, `Invalid parameter for query: group. Please use objectId instead of _id`); + } + if (!stage[stageName].hasOwnProperty('objectId')) { + throw new _node2.default.Error(_node2.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); @@ -79,4 +96,5 @@ class AggregateRouter extends _ClassesRouter2.default { } exports.AggregateRouter = AggregateRouter; -exports.default = AggregateRouter; \ No newline at end of file +exports.default = AggregateRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0FnZ3JlZ2F0ZVJvdXRlci5qcyJdLCJuYW1lcyI6WyJtaWRkbGV3YXJlIiwiQkFTRV9LRVlTIiwiUElQRUxJTkVfS0VZUyIsIkFMTE9XRURfS0VZUyIsIkFnZ3JlZ2F0ZVJvdXRlciIsIkNsYXNzZXNSb3V0ZXIiLCJoYW5kbGVGaW5kIiwicmVxIiwiYm9keSIsIk9iamVjdCIsImFzc2lnbiIsIkpTT05Gcm9tUXVlcnkiLCJxdWVyeSIsIm9wdGlvbnMiLCJwaXBlbGluZSIsIkFycmF5IiwiaXNBcnJheSIsIm1hcCIsInN0YWdlIiwic3RhZ2VOYW1lIiwia2V5cyIsInRyYW5zZm9ybVN0YWdlIiwic3RhZ2VzIiwicHVzaCIsImRpc3RpbmN0IiwiU3RyaW5nIiwid2hlcmUiLCJKU09OIiwicGFyc2UiLCJyZXN0IiwiZmluZCIsImNvbmZpZyIsImF1dGgiLCJjbGFzc05hbWUiLCJpbmZvIiwiY2xpZW50U0RLIiwidGhlbiIsInJlc3BvbnNlIiwicmVzdWx0IiwicmVzdWx0cyIsIlVzZXJzUm91dGVyIiwicmVtb3ZlSGlkZGVuUHJvcGVydGllcyIsImluZGV4T2YiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9RVUVSWSIsImhhc093blByb3BlcnR5IiwiX2lkIiwib2JqZWN0SWQiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7O0FBQ0E7O0lBQVlBLFU7O0FBQ1o7Ozs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNQyxZQUFZLENBQUMsT0FBRCxFQUFVLFVBQVYsQ0FBbEI7O0FBRUEsTUFBTUMsZ0JBQWdCLENBQ3BCLFdBRG9CLEVBRXBCLFFBRm9CLEVBR3BCLFlBSG9CLEVBSXBCLFdBSm9CLEVBS3BCLE9BTG9CLEVBTXBCLFdBTm9CLEVBT3BCLE9BUG9CLEVBUXBCLFNBUm9CLEVBU3BCLGFBVG9CLEVBVXBCLE9BVm9CLEVB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QUksQ0FBQzNCLE1BQU1DLFNBQU4sRUFBaUIyQixjQUFqQixDQUFnQyxVQUFoQyxDQUFMLEVBQWtEO0FBQ2hELGNBQU0sSUFBSUgsZUFBTUMsS0FBVixDQUNKRCxlQUFNQyxLQUFOLENBQVlDLGFBRFIsRUFFSCwwREFGRyxDQUFOO0FBSUQ7QUFDRDNCLFlBQU1DLFNBQU4sRUFBaUI0QixHQUFqQixHQUF1QjdCLE1BQU1DLFNBQU4sRUFBaUI2QixRQUF4QztBQUNBLGFBQU85QixNQUFNQyxTQUFOLEVBQWlCNkIsUUFBeEI7QUFDRDtBQUNELFdBQU8sRUFBRSxDQUFFLElBQUc3QixTQUFVLEVBQWYsR0FBbUJELE1BQU1DLFNBQU4sQ0FBckIsRUFBUDtBQUNEOztBQUVEOEIsZ0JBQWM7QUFDWixTQUFLQyxLQUFMLENBQVcsS0FBWCxFQUFpQix1QkFBakIsRUFBMENsRCxXQUFXbUQsNkJBQXJELEVBQW9GNUMsT0FBTztBQUFFLGFBQU8sS0FBS0QsVUFBTCxDQUFnQkMsR0FBaEIsQ0FBUDtBQUE4QixLQUEzSDtBQUNEO0FBaEVnRDs7UUFBdENILGUsR0FBQUEsZTtrQkFtRUVBLGUiLCJmaWxlIjoiQWdncmVnYXRlUm91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IENsYXNzZXNSb3V0ZXIgZnJvbSAnLi9DbGFzc2VzUm91dGVyJztcbmltcG9ydCByZXN0IGZyb20gJy4uL3Jlc3QnO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5pbXBvcnQgUGFyc2UgICAgICAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBVc2Vyc1JvdXRlciAgIGZyb20gJy4vVXNlcnNSb3V0ZXInO1xuXG5jb25zdCBCQVNFX0tFWVMgPSBbJ3doZXJlJywgJ2Rpc3RpbmN0J107XG5cbmNvbnN0IFBJUEVMSU5FX0tFWVMgPSBbXG4gICdhZGRGaWVsZHMnLFxuICAnYnVja2V0JyxcbiAgJ2J1Y2tldEF1dG8nLFxuICAnY29sbFN0YXRzJyxcbiAgJ2NvdW50JyxcbiAgJ2N1cnJlbnRPcCcsXG4gICdmYWNldCcsXG4gICdnZW9OZWFyJyxcbiAgJ2dyYXBoTG9va3VwJyxcbiAgJ2dyb3VwJyxcbiAgJ2luZGV4U3RhdHMnLFxuICAnbGltaXQnLFxuICAnbGlzdExvY2FsU2Vzc2lvbnMnLFxuICAnbGlzdFNlc3Npb25zJyxcbiAgJ2xvb2t1cCcsXG4gICdtYXRjaCcsXG4gICdvdXQnLFxuICAncHJvamVjdCcsXG4gICdyZWRhY3QnLFxuICAncmVwbGFjZVJvb3QnLFxuICAnc2FtcGxlJyxcbiAgJ3NraXAnLFxuICAnc29ydCcsXG4gICdzb3J0QnlDb3VudCcsXG4gICd1bndpbmQnLFxuXTtcblxuY29uc3QgQUxMT1dFRF9LRVlTID0gWy4uLkJBU0VfS0VZUywgLi4uUElQRUxJTkVfS0VZU107XG5cbmV4cG9ydCBjbGFzcyBBZ2dyZWdhdGVSb3V0ZXIgZXh0ZW5kcyBDbGFzc2VzUm91dGVyIHtcblxuICBoYW5kbGVGaW5kKHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKHJlcS5ib2R5LCBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KSk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHt9O1xuICAgIGxldCBwaXBlbGluZSA9IFtdO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYm9keSkpIHtcbiAgICAgIHBpcGVsaW5lID0gYm9keS5tYXAoKHN0YWdlKSA9PiB7XG4gICAgICAgIGNvbnN0IHN0YWdlTmFtZSA9IE9iamVjdC5rZXlzKHN0YWdlKVswXTtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNmb3JtU3RhZ2Uoc3RhZ2VOYW1lLCBzdGFnZSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc3RhZ2VzID0gW107XG4gICAgICBmb3IgKGNvbnN0IHN0YWdlTmFtZSBpbiBib2R5KSB7XG4gICAgICAgIHN0YWdlcy5wdXNoKHRoaXMudHJhbnNmb3JtU3RhZ2Uoc3RhZ2VOYW1lLCBib2R5KSk7XG4gICAgICB9XG4gICAgICBwaXBlbGluZSA9IHN0YWdlcztcbiAgICB9XG4gICAgaWYgKGJvZHkuZGlzdGluY3QpIHtcbiAgICAgIG9wdGlvbnMuZGlzdGluY3QgPSBTdHJpbmcoYm9keS5kaXN0aW5jdCk7XG4gICAgfVxuICAgIG9wdGlvbnMucGlwZWxpbmUgPSBwaXBlbGluZTtcbiAgICBpZiAodHlwZW9mIGJvZHkud2hlcmUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBib2R5LndoZXJlID0gSlNPTi5wYXJzZShib2R5LndoZXJlKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3QuZmluZChyZXEuY29uZmlnLCByZXEuYXV0aCwgdGhpcy5jbGFzc05hbWUocmVxKSwgYm9keS53aGVyZSwgb3B0aW9ucywgcmVxLmluZm8uY2xpZW50U0RLKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgZm9yKGNvbnN0IHJlc3VsdCBvZiByZXNwb25zZS5yZXN1bHRzKSB7XG4gICAgICAgIGlmKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgVXNlcnNSb3V0ZXIucmVtb3ZlSGlkZGVuUHJvcGVydGllcyhyZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4geyByZXNwb25zZSB9O1xuICAgIH0pO1xuICB9XG5cbiAgdHJhbnNmb3JtU3RhZ2Uoc3RhZ2VOYW1lLCBzdGFnZSkge1xuICAgIGlmIChBTExPV0VEX0tFWVMuaW5kZXhPZihzdGFnZU5hbWUpID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICBgSW52YWxpZCBwYXJhbWV0ZXIgZm9yIHF1ZXJ5OiAke3N0YWdlTmFtZX1gXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoc3RhZ2VOYW1lID09PSAnZ3JvdXAnKSB7XG4gICAgICBpZiAoc3RhZ2Vbc3RhZ2VOYW1lXS5oYXNPd25Qcm9wZXJ0eSgnX2lkJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgYEludmFsaWQgcGFyYW1ldGVyIGZvciBxdWVyeTogZ3JvdXAuIFBsZWFzZSB1c2Ugb2JqZWN0SWQgaW5zdGVhZCBvZiBfaWRgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIXN0YWdlW3N0YWdlTmFtZV0uaGFzT3duUHJvcGVydHkoJ29iamVjdElkJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksXG4gICAgICAgICAgYEludmFsaWQgcGFyYW1ldGVyIGZvciBxdWVyeTogZ3JvdXAuIG9iamVjdElkIGlzIHJlcXVpcmVkYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgc3RhZ2Vbc3RhZ2VOYW1lXS5faWQgPSBzdGFnZVtzdGFnZU5hbWVdLm9iamVjdElkO1xuICAgICAgZGVsZXRlIHN0YWdlW3N0YWdlTmFtZV0ub2JqZWN0SWQ7XG4gICAgfVxuICAgIHJldHVybiB7IFtgJCR7c3RhZ2VOYW1lfWBdOiBzdGFnZVtzdGFnZU5hbWVdIH07XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCcvYWdncmVnYXRlLzpjbGFzc05hbWUnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7IH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEFnZ3JlZ2F0ZVJvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/AnalyticsRouter.js b/lib/Routers/AnalyticsRouter.js index 4cd6885171..6a74dd685e 100644 --- a/lib/Routers/AnalyticsRouter.js +++ b/lib/Routers/AnalyticsRouter.js @@ -28,4 +28,5 @@ class AnalyticsRouter extends _PromiseRouter2.default { this.route('POST', '/events/:eventName', trackEvent); } } -exports.AnalyticsRouter = AnalyticsRouter; \ No newline at end of file +exports.AnalyticsRouter = AnalyticsRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0FuYWx5dGljc1JvdXRlci5qcyJdLCJuYW1lcyI6WyJhcHBPcGVuZWQiLCJyZXEiLCJhbmFseXRpY3NDb250cm9sbGVyIiwiY29uZmlnIiwidHJhY2tFdmVudCIsIkFuYWx5dGljc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJtb3VudFJvdXRlcyIsInJvdXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7Ozs7OztBQUVBLFNBQVNBLFNBQVQsQ0FBbUJDLEdBQW5CLEVBQXdCO0FBQ3RCLFFBQU1DLHNCQUFzQkQsSUFBSUUsTUFBSixDQUFXRCxtQkFBdkM7QUFDQSxTQUFPQSxvQkFBb0JGLFNBQXBCLENBQThCQyxHQUE5QixDQUFQO0FBQ0QsQyxDQU5EOzs7QUFRQSxTQUFTRyxVQUFULENBQW9CSCxHQUFwQixFQUF5QjtBQUN2QixRQUFNQyxzQkFBc0JELElBQUlFLE1BQUosQ0FBV0QsbUJBQXZDO0FBQ0EsU0FBT0Esb0JBQW9CRSxVQUFwQixDQUErQkgsR0FBL0IsQ0FBUDtBQUNEOztBQUdNLE1BQU1JLGVBQU4sU0FBOEJDLHVCQUE5QixDQUE0QztBQUNqREMsZ0JBQWM7QUFDWixTQUFLQyxLQUFMLENBQVcsTUFBWCxFQUFrQixtQkFBbEIsRUFBdUNSLFNBQXZDO0FBQ0EsU0FBS1EsS0FBTCxDQUFXLE1BQVgsRUFBa0Isb0JBQWxCLEVBQXdDSixVQUF4QztBQUNEO0FBSmdEO1FBQXRDQyxlLEdBQUFBLGUiLCJmaWxlIjoiQW5hbHl0aWNzUm91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQW5hbHl0aWNzUm91dGVyLmpzXG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcblxuZnVuY3Rpb24gYXBwT3BlbmVkKHJlcSkge1xuICBjb25zdCBhbmFseXRpY3NDb250cm9sbGVyID0gcmVxLmNvbmZpZy5hbmFseXRpY3NDb250cm9sbGVyO1xuICByZXR1cm4gYW5hbHl0aWNzQ29udHJvbGxlci5hcHBPcGVuZWQocmVxKTtcbn1cblxuZnVuY3Rpb24gdHJhY2tFdmVudChyZXEpIHtcbiAgY29uc3QgYW5hbHl0aWNzQ29udHJvbGxlciA9IHJlcS5jb25maWcuYW5hbHl0aWNzQ29udHJvbGxlcjtcbiAgcmV0dXJuIGFuYWx5dGljc0NvbnRyb2xsZXIudHJhY2tFdmVudChyZXEpO1xufVxuXG5cbmV4cG9ydCBjbGFzcyBBbmFseXRpY3NSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsJy9ldmVudHMvQXBwT3BlbmVkJywgYXBwT3BlbmVkKTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywnL2V2ZW50cy86ZXZlbnROYW1lJywgdHJhY2tFdmVudCk7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/AudiencesRouter.js b/lib/Routers/AudiencesRouter.js index ce31014ea5..2a1bee314a 100644 --- a/lib/Routers/AudiencesRouter.js +++ b/lib/Routers/AudiencesRouter.js @@ -69,4 +69,5 @@ class AudiencesRouter extends _ClassesRouter2.default { } exports.AudiencesRouter = AudiencesRouter; -exports.default = AudiencesRouter; \ No newline at end of file +exports.default = AudiencesRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0F1ZGllbmNlc1JvdXRlci5qcyJdLCJuYW1lcyI6WyJtaWRkbGV3YXJlIiwiQXVkaWVuY2VzUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsImhhbmRsZUZpbmQiLCJyZXEiLCJib2R5IiwiT2JqZWN0IiwiYXNzaWduIiwiSlNPTkZyb21RdWVyeSIsInF1ZXJ5Iiwib3B0aW9ucyIsIm9wdGlvbnNGcm9tQm9keSIsInJlc3QiLCJmaW5kIiwiY29uZmlnIiwiYXV0aCIsIndoZXJlIiwiaW5mbyIsImNsaWVudFNESyIsInRoZW4iLCJyZXNwb25zZSIsInJlc3VsdHMiLCJmb3JFYWNoIiwiaXRlbSIsIkpTT04iLCJwYXJzZSIsImhhbmRsZUdldCIsImRhdGEiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJoYW5kbGVDcmVhdGUiLCJoYW5kbGVVcGRhdGUiLCJoYW5kbGVEZWxldGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7O0FBQ0E7O0lBQVlBLFU7Ozs7OztBQUVMLE1BQU1DLGVBQU4sU0FBOEJDLHVCQUE5QixDQUE0Qzs7QUFFakRDLGNBQVk7QUFDVixXQUFPLFdBQVA7QUFDRDs7QUFFREMsYUFBV0MsR0FBWCxFQUFnQjtBQUNkLFVBQU1DLE9BQU9DLE9BQU9DLE1BQVAsQ0FBY0gsSUFBSUMsSUFBbEIsRUFBd0JKLHdCQUFjTyxhQUFkLENBQTRCSixJQUFJSyxLQUFoQyxDQUF4QixDQUFiO0FBQ0EsVUFBTUMsVUFBVVQsd0JBQWNVLGVBQWQsQ0FBOEJOLElBQTlCLENBQWhCOztBQUVBLFdBQU9PLGVBQUtDLElBQUwsQ0FBVVQsSUFBSVUsTUFBZCxFQUFzQlYsSUFBSVcsSUFBMUIsRUFBZ0MsV0FBaEMsRUFBNkNWLEtBQUtXLEtBQWxELEVBQXlETixPQUF6RCxFQUFrRU4sSUFBSWEsSUFBSixDQUFTQyxTQUEzRSxFQUNKQyxJQURJLENBQ0VDLFFBQUQsSUFBYzs7QUFFbEJBLGVBQVNDLE9BQVQsQ0FBaUJDLE9BQWpCLENBQTBCQyxJQUFELElBQVU7QUFDakNBLGFBQUtkLEtBQUwsR0FBYWUsS0FBS0MsS0FBTCxDQUFXRixLQUFLZCxLQUFoQixDQUFiO0FBQ0QsT0FGRDs7QUFJQSxhQUFPLEVBQUNXLFVBQVVBLFFBQVgsRUFBUDtBQUNELEtBUkksQ0FBUDtBQVNEOztBQUVETSxZQUFVdEIsR0FBVixFQUFlO0FBQ2IsV0FBTyxNQUFNc0IsU0FBTixDQUFnQnRCLEdBQWhCLEVBQ0plLElBREksQ0FDRVEsSUFBRCxJQUFVO0FBQ2RBLFdBQUtQLFFBQUwsQ0FBY1gsS0FBZCxHQUFzQmUsS0FBS0MsS0FBTCxDQUFXRSxLQUFLUCxRQUFMLENBQWNYLEtBQXpCLENBQXRCOztBQUVBLGFBQU9rQixJQUFQO0FBQ0QsS0FMSSxDQUFQO0FBTUQ7O0FBRURDLGdCQUFjO0FBQ1osU0FBS0MsS0FBTCxDQUFXLEtBQVgsRUFBaUIsaUJBQWpCLEVBQW9DOUIsV0FBVytCLDZCQUEvQyxFQUE4RTFCLE9BQU87QUFBRSxhQUFPLEtBQUtELFVBQUwsQ0FBZ0JDLEdBQWhCLENBQVA7QUFBOEIsS0FBckg7QUFDQSxTQUFLeUIsS0FBTCxDQUFXLEtBQVgsRUFBaUIsMkJBQWpCLEVBQThDOUIsV0FBVytCLDZCQUF6RCxFQUF3RjFCLE9BQU87QUFBRSxhQUFPLEtBQUtzQixTQUFMLENBQWV0QixHQUFmLENBQVA7QUFBNkIsS0FBOUg7QUFDQSxTQUFLeUIsS0FBTCxDQUFXLE1BQVgsRUFBa0IsaUJBQWxCLEVBQXFDOUIsV0FBVytCLDZCQUFoRCxFQUErRTFCLE9BQU87QUFBRSxhQUFPLEtBQUsyQixZQUFMLENBQWtCM0IsR0FBbEIsQ0FBUDtBQUFnQyxLQUF4SDtBQUNBLFNBQUt5QixLQUFMLENBQVcsS0FBWCxFQUFpQiwyQkFBakIsRUFBOEM5QixXQUFXK0IsNkJBQXpELEVBQXdGMUIsT0FBTztBQUFFLGFBQU8sS0FBSzRCLFlBQUwsQ0FBa0I1QixHQUFsQixDQUFQO0FBQWdDLEtBQWpJO0FBQ0EsU0FBS3lCLEtBQUwsQ0FBVyxRQUFYLEVBQW9CLDJCQUFwQixFQUFpRDlCLFdBQVcrQiw2QkFBNUQsRUFBMkYxQixPQUFPO0FBQUUsYUFBTyxLQUFLNkIsWUFBTCxDQUFrQjdCLEdBQWxCLENBQVA7QUFBZ0MsS0FBcEk7QUFDRDtBQXBDZ0Q7O1FBQXRDSixlLEdBQUFBLGU7a0JBdUNFQSxlIiwiZmlsZSI6IkF1ZGllbmNlc1JvdXRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmUgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuXG5leHBvcnQgY2xhc3MgQXVkaWVuY2VzUm91dGVyIGV4dGVuZHMgQ2xhc3Nlc1JvdXRlciB7XG5cbiAgY2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnX0F1ZGllbmNlJztcbiAgfVxuXG4gIGhhbmRsZUZpbmQocmVxKSB7XG4gICAgY29uc3QgYm9keSA9IE9iamVjdC5hc3NpZ24ocmVxLmJvZHksIENsYXNzZXNSb3V0ZXIuSlNPTkZyb21RdWVyeShyZXEucXVlcnkpKTtcbiAgICBjb25zdCBvcHRpb25zID0gQ2xhc3Nlc1JvdXRlci5vcHRpb25zRnJvbUJvZHkoYm9keSk7XG5cbiAgICByZXR1cm4gcmVzdC5maW5kKHJlcS5jb25maWcsIHJlcS5hdXRoLCAnX0F1ZGllbmNlJywgYm9keS53aGVyZSwgb3B0aW9ucywgcmVxLmluZm8uY2xpZW50U0RLKVxuICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG5cbiAgICAgICAgcmVzcG9uc2UucmVzdWx0cy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgICAgaXRlbS5xdWVyeSA9IEpTT04ucGFyc2UoaXRlbS5xdWVyeSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB7cmVzcG9uc2U6IHJlc3BvbnNlfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlR2V0KHJlcSkge1xuICAgIHJldHVybiBzdXBlci5oYW5kbGVHZXQocmVxKVxuICAgICAgLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgICAgZGF0YS5yZXNwb25zZS5xdWVyeSA9IEpTT04ucGFyc2UoZGF0YS5yZXNwb25zZS5xdWVyeSk7XG5cbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0dFVCcsJy9wdXNoX2F1ZGllbmNlcycsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZUZpbmQocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywnL3B1c2hfYXVkaWVuY2VzLzpvYmplY3RJZCcsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZUdldChyZXEpOyB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywnL3B1c2hfYXVkaWVuY2VzJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlQ3JlYXRlKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BVVCcsJy9wdXNoX2F1ZGllbmNlcy86b2JqZWN0SWQnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGUocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnREVMRVRFJywnL3B1c2hfYXVkaWVuY2VzLzpvYmplY3RJZCcsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZURlbGV0ZShyZXEpOyB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBBdWRpZW5jZXNSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/ClassesRouter.js b/lib/Routers/ClassesRouter.js index d038344e8b..cec5df38d3 100644 --- a/lib/Routers/ClassesRouter.js +++ b/lib/Routers/ClassesRouter.js @@ -115,7 +115,7 @@ class ClassesRouter extends _PromiseRouter2.default { } static optionsFromBody(body) { - const allowConstraints = ['skip', 'limit', 'order', 'count', 'keys', 'include', 'redirectClassNameForKey', 'where']; + const allowConstraints = ['skip', 'limit', 'order', 'count', 'keys', 'include', 'includeAll', 'redirectClassNameForKey', 'where']; for (const key of Object.keys(body)) { if (allowConstraints.indexOf(key) === -1) { @@ -143,6 +143,9 @@ class ClassesRouter extends _PromiseRouter2.default { if (body.include) { options.include = String(body.include); } + if (body.includeAll) { + options.includeAll = true; + } return options; } @@ -166,4 +169,5 @@ class ClassesRouter extends _PromiseRouter2.default { } exports.ClassesRouter = ClassesRouter; -exports.default = ClassesRouter; \ No newline at end of file +exports.default = ClassesRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0NsYXNzZXNSb3V0ZXIuanMiXSwibmFtZXMiOlsiQUxMT1dFRF9HRVRfUVVFUllfS0VZUyIsIkNsYXNzZXNSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwiY2xhc3NOYW1lIiwicmVxIiwicGFyYW1zIiwiaGFuZGxlRmluZCIsImJvZHkiLCJPYmplY3QiLCJhc3NpZ24iLCJKU09ORnJvbVF1ZXJ5IiwicXVlcnkiLCJvcHRpb25zIiwib3B0aW9uc0Zyb21Cb2R5IiwiY29uZmlnIiwibWF4TGltaXQiLCJsaW1pdCIsIk51bWJlciIsInJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5IiwiU3RyaW5nIiwid2hlcmUiLCJKU09OIiwicGFyc2UiLCJyZXN0IiwiZmluZCIsImF1dGgiLCJpbmZvIiwiY2xpZW50U0RLIiwidGhlbiIsInJlc3BvbnNlIiwiaGFuZGxlR2V0Iiwia2V5Iiwia2V5cyIsImluZGV4T2YiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9RVUVSWSIsImluY2x1ZGUiLCJnZXQiLCJvYmplY3RJZCIsInJlc3VsdHMiLCJsZW5ndGgiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwic2Vzc2lvblRva2VuIiwidXNlciIsImlkIiwiaGFuZGxlQ3JlYXRlIiwiY3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwidXBkYXRlIiwiaGFuZGxlRGVsZXRlIiwiZGVsIiwianNvbiIsInZhbHVlIiwiXyIsImVudHJpZXMiLCJlIiwiYWxsb3dDb25zdHJhaW50cyIsInNraXAiLCJvcmRlciIsImNvdW50IiwiaW5jbHVkZUFsbCIsIm1vdW50Um91dGVzIiwicm91dGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEseUJBQXlCLENBQUMsTUFBRCxFQUFTLFNBQVQsQ0FBL0I7O0FBRU8sTUFBTUMsYUFBTixTQUE0QkMsdUJBQTVCLENBQTBDOztBQUUvQ0MsWUFBVUMsR0FBVixFQUFlO0FBQ2Is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LFlBQUwsQ0FBa0IxQyxHQUFsQixDQUFQO0FBQWdDLEtBQXJGO0FBQ0EsU0FBSzJELEtBQUwsQ0FBVyxLQUFYLEVBQWtCLCtCQUFsQixFQUFvRDNELEdBQUQsSUFBUztBQUFFLGFBQU8sS0FBSzRDLFlBQUwsQ0FBa0I1QyxHQUFsQixDQUFQO0FBQWdDLEtBQTlGO0FBQ0EsU0FBSzJELEtBQUwsQ0FBVyxRQUFYLEVBQXNCLCtCQUF0QixFQUF3RDNELEdBQUQsSUFBUztBQUFFLGFBQU8sS0FBSzhDLFlBQUwsQ0FBa0I5QyxHQUFsQixDQUFQO0FBQWdDLEtBQWxHO0FBQ0Q7QUF0SThDOztRQUFwQ0gsYSxHQUFBQSxhO2tCQXlJRUEsYSIsImZpbGUiOiJDbGFzc2VzUm91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCByZXN0ICAgICAgICAgIGZyb20gJy4uL3Jlc3QnO1xuaW1wb3J0IF8gICAgICAgICAgICAgZnJvbSAnbG9kYXNoJztcbmltcG9ydCBQYXJzZSAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuXG5jb25zdCBBTExPV0VEX0dFVF9RVUVSWV9LRVlTID0gWydrZXlzJywgJ2luY2x1ZGUnXTtcblxuZXhwb3J0IGNsYXNzIENsYXNzZXNSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcblxuICBjbGFzc05hbWUocmVxKSB7XG4gICAgcmV0dXJuIHJlcS5wYXJhbXMuY2xhc3NOYW1lO1xuICB9XG5cbiAgaGFuZGxlRmluZChyZXEpIHtcbiAgICBjb25zdCBib2R5ID0gT2JqZWN0LmFzc2lnbihyZXEuYm9keSwgQ2xhc3Nlc1JvdXRlci5KU09ORnJvbVF1ZXJ5KHJlcS5xdWVyeSkpO1xuICAgIGNvbnN0IG9wdGlvbnMgPSBDbGFzc2VzUm91dGVyLm9wdGlvbnNGcm9tQm9keShib2R5KTtcbiAgICBpZiAocmVxLmNvbmZpZy5tYXhMaW1pdCAmJiAoYm9keS5saW1pdCA+IHJlcS5jb25maWcubWF4TGltaXQpKSB7XG4gICAgICAvLyBTaWxlbnRseSByZXBsYWNlIHRoZSBsaW1pdCBvbiB0aGUgcXVlcnkgd2l0aCB0aGUgbWF4IGNvbmZpZ3VyZWRcbiAgICAgIG9wdGlvbnMubGltaXQgPSBOdW1iZXIocmVxLmNvbmZpZy5tYXhMaW1pdCk7XG4gICAgfVxuICAgIGlmIChib2R5LnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5KSB7XG4gICAgICBvcHRpb25zLnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5ID0gU3RyaW5nKGJvZHkucmVkaXJlY3RDbGFzc05hbWVGb3JLZXkpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkud2hlcmUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBib2R5LndoZXJlID0gSlNPTi5wYXJzZShib2R5LndoZXJlKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3QuZmluZChyZXEuY29uZmlnLCByZXEuYXV0aCwgdGhpcy5jbGFzc05hbWUocmVxKSwgYm9keS53aGVyZSwgb3B0aW9ucywgcmVxLmluZm8uY2xpZW50U0RLKVxuICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiByZXNwb25zZSB9O1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSB7cmVzcG9uc2V9IG9iamVjdC5cbiAgaGFuZGxlR2V0KHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKHJlcS5ib2R5LCBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KSk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoYm9keSkpIHtcbiAgICAgIGlmIChBTExPV0VEX0dFVF9RVUVSWV9LRVlTLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksICdJbXByb3BlciBlbmNvZGUgb2YgcGFyYW1ldGVyJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBib2R5LmtleXMgPT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMua2V5cyA9IGJvZHkua2V5cztcbiAgICB9XG4gICAgaWYgKGJvZHkuaW5jbHVkZSkge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlID0gU3RyaW5nKGJvZHkuaW5jbHVkZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3QuZ2V0KHJlcS5jb25maWcsIHJlcS5hdXRoLCB0aGlzLmNsYXNzTmFtZShyZXEpLCByZXEucGFyYW1zLm9iamVjdElkLCBvcHRpb25zLCByZXEuaW5mby5jbGllbnRTREspXG4gICAgICAudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKCFyZXNwb25zZS5yZXN1bHRzIHx8IHJlc3BvbnNlLnJlc3VsdHMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ09iamVjdCBub3QgZm91bmQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jbGFzc05hbWUocmVxKSA9PT0gXCJfVXNlclwiKSB7XG5cbiAgICAgICAgICBkZWxldGUgcmVzcG9uc2UucmVzdWx0c1swXS5zZXNzaW9uVG9rZW47XG5cbiAgICAgICAgICBjb25zdCB1c2VyID0gIHJlc3BvbnNlLnJlc3VsdHNbMF07XG5cbiAgICAgICAgICBpZiAocmVxLmF1dGgudXNlciAmJiB1c2VyLm9iamVjdElkID09IHJlcS5hdXRoLnVzZXIuaWQpIHtcbiAgICAgICAgICAgIC8vIEZvcmNlIHRoZSBzZXNzaW9uIHRva2VuXG4gICAgICAgICAgICByZXNwb25zZS5yZXN1bHRzWzBdLnNlc3Npb25Ub2tlbiA9IHJlcS5pbmZvLnNlc3Npb25Ub2tlbjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHJlc3BvbnNlLnJlc3VsdHNbMF0gfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlQ3JlYXRlKHJlcSkge1xuICAgIHJldHVybiByZXN0LmNyZWF0ZShyZXEuY29uZmlnLCByZXEuYXV0aCwgdGhpcy5jbGFzc05hbWUocmVxKSwgcmVxLmJvZHksIHJlcS5pbmZvLmNsaWVudFNESyk7XG4gIH1cblxuICBoYW5kbGVVcGRhdGUocmVxKSB7XG4gICAgY29uc3Qgd2hlcmUgPSB7IG9iamVjdElkOiByZXEucGFyYW1zLm9iamVjdElkIH1cbiAgICByZXR1cm4gcmVzdC51cGRhdGUocmVxLmNvbmZpZywgcmVxLmF1dGgsIHRoaXMuY2xhc3NOYW1lKHJlcSksIHdoZXJlLCByZXEuYm9keSwgcmVxLmluZm8uY2xpZW50U0RLKTtcbiAgfVxuXG4gIGhhbmRsZURlbGV0ZShyZXEpIHtcbiAgICByZXR1cm4gcmVzdC5kZWwocmVxLmNvbmZpZywgcmVxLmF1dGgsIHRoaXMuY2xhc3NOYW1lKHJlcSksIHJlcS5wYXJhbXMub2JqZWN0SWQsIHJlcS5pbmZvLmNsaWVudFNESylcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHtyZXNwb25zZToge319O1xuICAgICAgfSk7XG4gIH1cblxuICBzdGF0aWMgSlNPTkZyb21RdWVyeShxdWVyeSkge1xuICAgIGNvbnN0IGpzb24gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBfLmVudHJpZXMocXVlcnkpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBqc29uW2tleV0gPSBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAganNvbltrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBqc29uXG4gIH1cblxuICBzdGF0aWMgb3B0aW9uc0Zyb21Cb2R5KGJvZHkpIHtcbiAgICBjb25zdCBhbGxvd0NvbnN0cmFpbnRzID0gWydza2lwJywgJ2xpbWl0JywgJ29yZGVyJywgJ2NvdW50JywgJ2tleXMnLFxuICAgICAgJ2luY2x1ZGUnLCAnaW5jbHVkZUFsbCcsICdyZWRpcmVjdENsYXNzTmFtZUZvcktleScsICd3aGVyZSddO1xuXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoYm9keSkpIHtcbiAgICAgIGlmIChhbGxvd0NvbnN0cmFpbnRzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksIGBJbnZhbGlkIHBhcmFtZXRlciBmb3IgcXVlcnk6ICR7a2V5fWApO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBvcHRpb25zID0ge307XG4gICAgaWYgKGJvZHkuc2tpcCkge1xuICAgICAgb3B0aW9ucy5za2lwID0gTnVtYmVyKGJvZHkuc2tpcCk7XG4gICAgfVxuICAgIGlmIChib2R5LmxpbWl0IHx8IGJvZHkubGltaXQgPT09IDApIHtcbiAgICAgIG9wdGlvbnMubGltaXQgPSBOdW1iZXIoYm9keS5saW1pdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wdGlvbnMubGltaXQgPSBOdW1iZXIoMTAwKTtcbiAgICB9XG4gICAgaWYgKGJvZHkub3JkZXIpIHtcbiAgICAgIG9wdGlvbnMub3JkZXIgPSBTdHJpbmcoYm9keS5vcmRlcik7XG4gICAgfVxuICAgIGlmIChib2R5LmNvdW50KSB7XG4gICAgICBvcHRpb25zLmNvdW50ID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LmtleXMgPT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMua2V5cyA9IGJvZHkua2V5cztcbiAgICB9XG4gICAgaWYgKGJvZHkuaW5jbHVkZSkge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlID0gU3RyaW5nKGJvZHkuaW5jbHVkZSk7XG4gICAgfVxuICAgIGlmIChib2R5LmluY2x1ZGVBbGwpIHtcbiAgICAgIG9wdGlvbnMuaW5jbHVkZUFsbCA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBvcHRpb25zO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUnLCAocmVxKSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZUZpbmQocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUvOm9iamVjdElkJywgKHJlcSkgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVHZXQocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvY2xhc3Nlcy86Y2xhc3NOYW1lJywgKHJlcSkgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVDcmVhdGUocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUFVUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUvOm9iamVjdElkJywgKHJlcSkgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGUocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnREVMRVRFJywgICcvY2xhc3Nlcy86Y2xhc3NOYW1lLzpvYmplY3RJZCcsIChyZXEpID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlRGVsZXRlKHJlcSk7IH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IENsYXNzZXNSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/CloudCodeRouter.js b/lib/Routers/CloudCodeRouter.js index 69ff4066e4..5fb235b0c1 100644 --- a/lib/Routers/CloudCodeRouter.js +++ b/lib/Routers/CloudCodeRouter.js @@ -92,4 +92,5 @@ class CloudCodeRouter extends _PromiseRouter2.default { }); } } -exports.CloudCodeRouter = CloudCodeRouter; \ No newline at end of file +exports.CloudCodeRouter = CloudCodeRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0Nsb3VkQ29kZVJvdXRlci5qcyJdLCJuYW1lcyI6WyJ0cmlnZ2VycyIsInJlcXVpcmUiLCJtaWRkbGV3YXJlIiwiZm9ybWF0Sm9iU2NoZWR1bGUiLCJqb2Jfc2NoZWR1bGUiLCJzdGFydEFmdGVyIiwiRGF0ZSIsInRvSVNPU3RyaW5nIiwidmFsaWRhdGVKb2JTY2hlZHVsZSIsImNvbmZpZyIsImpvYnMiLCJnZXRKb2JzIiwiYXBwbGljYXRpb25JZCIsImpvYk5hbWUiLCJQYXJzZSIsIkVycm9yIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiQ2xvdWRDb2RlUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsIm1vdW50Um91dGVzIiwicm91dGUiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsImdldEpvYnNEYXRhIiwiY3JlYXRlSm9iIiwiZWRpdEpvYiIsImRlbGV0ZUpvYiIsInJlcSIsInJlc3QiLCJmaW5kIiwiYXV0aCIsInRoZW4iLCJzY2hlZHVsZWRKb2JzIiwicmVzcG9uc2UiLCJyZXN1bHRzIiwiaW5fdXNlIiwibWFwIiwiam9iIiwiT2JqZWN0Iiwia2V5cyIsImJvZHkiLCJjcmVhdGUiLCJjbGllbnQiLCJvYmplY3RJZCIsInBhcmFtcyIsInVwZGF0ZSIsImRlbCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBQ0EsTUFBTUEsV0FBa0JDLFFBQVEsYUFBUixDQUF4QjtBQUNBLE1BQU1DLGFBQWtCRCxRQUFRLGdCQUFSLENBQXhCOztBQUVBLFNBQVNFLGlCQUFULENBQTJCQyxZQUEzQixFQUF5QztBQUN2QyxNQUFJLE9BQU9BLGFBQWFDLFVBQXBCLEtBQW1DLFdBQXZDLEVBQW9EO0FBQ2xERCxpQkFBYUMsVUFBYixHQUEwQixJQUFJQyxJQUFKLEdBQVdDLFdBQVgsRUFBMUI7QUFDRDtBQUNELFNBQU9ILFlBQVA7QUFDRDs7QUFFRCxTQUFTSSxtQkFBVCxDQUE2QkMsTUFB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aEIsRUFBd0JpQixJQUFJRyxJQUE1QixFQUFrQyxjQUFsQyxFQUFrRCxFQUFFYSxRQUFGLEVBQWxELEVBQWdFdkMsa0JBQWtCQyxZQUFsQixDQUFoRSxFQUFpRzBCLElBQWpHLENBQXVHRSxRQUFELElBQWM7QUFDekgsYUFBTztBQUNMQTtBQURLLE9BQVA7QUFHRCxLQUpNLENBQVA7QUFLRDs7QUFFRCxTQUFPUCxTQUFQLENBQWlCQyxHQUFqQixFQUFzQjtBQUNwQixVQUFNLEVBQUVnQixRQUFGLEtBQWVoQixJQUFJaUIsTUFBekI7QUFDQSxXQUFPaEIsZUFBS2tCLEdBQUwsQ0FBU25CLElBQUlqQixNQUFiLEVBQXFCaUIsSUFBSUcsSUFBekIsRUFBK0IsY0FBL0IsRUFBK0NhLFFBQS9DLEVBQXlEWixJQUF6RCxDQUErREUsUUFBRCxJQUFjO0FBQ2pGLGFBQU87QUFDTEE7QUFESyxPQUFQO0FBR0QsS0FKTSxDQUFQO0FBS0Q7QUF0RGdEO1FBQXRDZixlLEdBQUFBLGUiLCJmaWxlIjoiQ2xvdWRDb2RlUm91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb21pc2VSb3V0ZXIgIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0IFBhcnNlICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IHJlc3QgICAgICAgICAgIGZyb20gJy4uL3Jlc3QnO1xuY29uc3QgdHJpZ2dlcnMgICAgICAgID0gcmVxdWlyZSgnLi4vdHJpZ2dlcnMnKTtcbmNvbnN0IG1pZGRsZXdhcmUgICAgICA9IHJlcXVpcmUoJy4uL21pZGRsZXdhcmVzJyk7XG5cbmZ1bmN0aW9uIGZvcm1hdEpvYlNjaGVkdWxlKGpvYl9zY2hlZHVsZSkge1xuICBpZiAodHlwZW9mIGpvYl9zY2hlZHVsZS5zdGFydEFmdGVyID09PSAndW5kZWZpbmVkJykge1xuICAgIGpvYl9zY2hlZHVsZS5zdGFydEFmdGVyID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICB9XG4gIHJldHVybiBqb2Jfc2NoZWR1bGU7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlSm9iU2NoZWR1bGUoY29uZmlnLCBqb2Jfc2NoZWR1bGUpIHtcbiAgY29uc3Qgam9icyA9IHRyaWdnZXJzLmdldEpvYnMoY29uZmlnLmFwcGxpY2F0aW9uSWQpIHx8IHt9O1xuICBpZiAoam9iX3NjaGVkdWxlLmpvYk5hbWUgJiYgIWpvYnNbam9iX3NjaGVkdWxlLmpvYk5hbWVdKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0Nhbm5vdCBTY2hlZHVsZSBhIGpvYiB0aGF0IGlzIG5vdCBkZXBsb3llZCcpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBDbG91ZENvZGVSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jbG91ZF9jb2RlL2pvYnMnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCBDbG91ZENvZGVSb3V0ZXIuZ2V0Sm9icyk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jbG91ZF9jb2RlL2pvYnMvZGF0YScsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIENsb3VkQ29kZVJvdXRlci5nZXRKb2JzRGF0YSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvY2xvdWRfY29kZS9qb2JzJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgQ2xvdWRDb2RlUm91dGVyLmNyZWF0ZUpvYik7XG4gICAgdGhpcy5yb3V0ZSgnUFVUJywgJy9jbG91ZF9jb2RlL2pvYnMvOm9iamVjdElkJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgQ2xvdWRDb2RlUm91dGVyLmVkaXRKb2IpO1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsICcvY2xvdWRfY29kZS9qb2JzLzpvYmplY3RJZCcsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIENsb3VkQ29kZVJvdXRlci5kZWxldGVKb2IpO1xuICB9XG5cbiAgc3RhdGljIGdldEpvYnMocmVxKSB7XG4gICAgcmV0dXJuIHJlc3QuZmluZChyZXEuY29uZmlnLCByZXEuYXV0aCwgJ19Kb2JTY2hlZHVsZScsIHt9LCB7fSkudGhlbigoc2NoZWR1bGVkSm9icykgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVzcG9uc2U6IHNjaGVkdWxlZEpvYnMucmVzdWx0c1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldEpvYnNEYXRhKHJlcSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG4gICAgY29uc3Qgam9icyA9IHRyaWdnZXJzLmdldEpvYnMoY29uZmlnLmFwcGxpY2F0aW9uSWQpIHx8IHt9O1xuICAgIHJldHVybiByZXN0LmZpbmQocmVxLmNvbmZpZywgcmVxLmF1dGgsICdfSm9iU2NoZWR1bGUnLCB7fSwge30pLnRoZW4oKHNjaGVkdWxlZEpvYnMpID0+IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHJlc3BvbnNlOiB7XG4gICAgICAgICAgaW5fdXNlOiBzY2hlZHVsZWRKb2JzLnJlc3VsdHMubWFwKChqb2IpID0+IGpvYi5qb2JOYW1lKSxcbiAgICAgICAgICBqb2JzOiBPYmplY3Qua2V5cyhqb2JzKSxcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVKb2IocmVxKSB7XG4gICAgY29uc3QgeyBqb2Jfc2NoZWR1bGUgfSA9IHJlcS5ib2R5O1xuICAgIHZhbGlkYXRlSm9iU2NoZWR1bGUocmVxLmNvbmZpZywgam9iX3NjaGVkdWxlKTtcbiAgICByZXR1cm4gcmVzdC5jcmVhdGUocmVxLmNvbmZpZywgcmVxLmF1dGgsICdfSm9iU2NoZWR1bGUnLCBmb3JtYXRKb2JTY2hlZHVsZShqb2Jfc2NoZWR1bGUpLCByZXEuY2xpZW50KTtcbiAgfVxuXG4gIHN0YXRpYyBlZGl0Sm9iKHJlcSkge1xuICAgIGNvbnN0IHsgb2JqZWN0SWQgfSA9IHJlcS5wYXJhbXM7XG4gICAgY29uc3QgeyBqb2Jfc2NoZWR1bGUgfSA9IHJlcS5ib2R5O1xuICAgIHZhbGlkYXRlSm9iU2NoZWR1bGUocmVxLmNvbmZpZywgam9iX3NjaGVkdWxlKTtcbiAgICByZXR1cm4gcmVzdC51cGRhdGUocmVxLmNvbmZpZywgcmVxLmF1dGgsICdfSm9iU2NoZWR1bGUnLCB7IG9iamVjdElkIH0sIGZvcm1hdEpvYlNjaGVkdWxlKGpvYl9zY2hlZHVsZSkpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICByZXNwb25zZVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGRlbGV0ZUpvYihyZXEpIHtcbiAgICBjb25zdCB7IG9iamVjdElkIH0gPSByZXEucGFyYW1zO1xuICAgIHJldHVybiByZXN0LmRlbChyZXEuY29uZmlnLCByZXEuYXV0aCwgJ19Kb2JTY2hlZHVsZScsIG9iamVjdElkKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVzcG9uc2VcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/lib/Routers/ExportRouter.js b/lib/Routers/ExportRouter.js index 0e834ae1e4..0645dc9841 100644 --- a/lib/Routers/ExportRouter.js +++ b/lib/Routers/ExportRouter.js @@ -209,4 +209,5 @@ class ExportRouter extends _PromiseRouter2.default { } exports.ExportRouter = ExportRouter; -exports.default = ExportRouter; \ No newline at end of file +exports.default = ExportRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0V4cG9ydFJvdXRlci5qcyJdLCJuYW1lcyI6WyJEZWZhdWx0RXhwb3J0RXhwb3J0UHJvZ3Jlc3NDb2xsZWN0aW9uTmFtZSIsInJlbGF0aW9uU2NoZW1hIiwiZmllbGRzIiwicmVsYXRlZElkIiwidHlwZSIsIm93bmluZ0lkIiwiRXhwb3J0Um91dGVyIiwiUHJvbWlzZVJvdXRlciIsImV4cG9ydENsYXNzUGFnZSIsInJlcSIsIm5hbWUiLCJqc29uRmlsZVN0cmVhbSIsIndoZXJlIiwic2tpcCIsImxpbWl0IiwiZGF0YWJhc2VDb250cm9sbGVyIiwiY29uZmlnIiwiZGF0YWJhc2UiLCJvcHRpb25zIiwiZmluZFByb21pc2UiLCJpbmRleE9mIiwiYWRhcHRlciIsImZpbmQiLCJyZXN0IiwiYXV0aCIsInRoZW4iLCJkYXRhIiwiQXJyYXkiLCJpc0FycmF5IiwicmVzdWx0cyIsImxlbmd0aCIsIndyaXRlIiwiSlNPTiIsInN0cmluZ2lmeSIsInN1YnN0ciIsInNsaWNlIiwiZXhwb3J0Q2xhc3MiLCJ0bXBKc29uRmlsZSIsInRtcCIsImZpbGVTeW5jIiwiZnMiLCJjcmVhdGVXcml0ZVN0cmVhbSIsImNvdW50IiwicmVzdWx0IiwiTnVtYmVyIiwiaXNJbnRlZ2VyIiwiaSIsInBhZ2VMaW1pdCIsInByb21pc2UiLCJQcm9taXNlIiwicmVzb2x2ZSIsImVuZCIsIm9uIiwiX25hbWUiLCJyZXBsYWNlIiwiaGFuZGxlRXhwb3J0UHJvZ3Jlc3MiLCJxdWVyeSIsIm1hc3RlcktleSIsImluZm8iLCJhcHBsaWNhdGlvbklkIiwiYXBwSWQiLCJyZXNwb25zZSIsImhhbmRsZUV4cG9ydCIsImVtYWlsQ29udHJvbGxlckFkYXB0ZXIiLCJlbWFpbEFkYXB0ZXIiLCJyZWplY3QiLCJFcnJvciIsImV4cG9ydFByb2dyZXNzIiwiaWQiLCJib2R5IiwiY3JlYXRlIiwibG9hZFNjaGVtYSIsImNsZWFyQ2FjaGUiLCJzY2hlbWFDb250cm9sbGVyIiwiZ2V0T25lU2NoZW1hIiwic2NoZW1hIiwiY2xhc3NOYW1lcyIsIk9iamVjdCIsImtleXMiLCJmb3JFYWNoIiwiZmllbGROYW1lIiwiZmllbGQiLCJwdXNoIiwicHJvbWlzc2VzIiwibWFwIiwiYWxsIiwianNvbkZpbGVzIiwidG1wWmlwRmlsZSIsInRtcFppcFN0cmVhbSIsInppcCIsInBpcGUiLCJhcHBlbmQiLCJyZWFkRmlsZVN5bmMiLCJyZW1vdmVDYWxsYmFjayIsImZpbmFsaXplIiwiYnVmIiwiemlwcGVkRmlsZSIsImZpbGVzQ29udHJvbGxlciIsImNyZWF0ZUZpbGUiLCJmaWxlRGF0YSIsInNlbmRNYWlsIiwidGV4dCIsInVybCIsImxpbmsiLCJ0byIsImZlZWRiYWNrRW1haWwiLCJzdWJqZWN0IiwiY2F0Y2giLCJlcnJvciIsImRlc3Ryb3kiLCJtb3VudFJvdXRlcyIsInJvdXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFDQTs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEsNENBQTRDLGlCQUFsRDtBQUNBLE1BQU1DLGlCQUFpQixFQUFFQyxRQUFRLEVBQUVDLFdBQVcsRUFBRUMsTUFBTSxRQUFSLEVBQWIsRUFBaUNDLFVBQVUsRUFBRUQsTUFBTSxRQUFSLEVBQTNDLEVBQVYsRUFBdkI7O0FBRU8sTUFBTUUsWUFBTixTQUEyQkMsdUJBQTNCLENBQXlDOztBQUU5Q0Msa0JBQWdCQyxHQUFoQixFQUFxQkMsSUFBckIsRUFBMkJDLGNBQTNCLEVBQTJDQyxLQUEzQyxFQUFrREMsSUFBbEQsRUFBd0RDLEtBQXhELEVBQStEOztBQUU3RCxVQUFNQyxxQkFBcUJOLElBQUlPLE1BQUosQ0FBV0MsUUFBdEM7O0FBRUEsVUFBTUMsVUFBVztBQUNmTCxVQURlO0FBRWZDO0FBRmUsS0FBakI7O0FBS0EsVUFBTUssY0FBY1QsS0FBS1UsT0FBTCxDQUFhLE9BQWIsTUFBMEIsQ0FBMUIsR0FDbEJMLG1CQUFtQk0sT0FBbkIsQ0FBMkJDLElBQTNCLENBQWdDWixJQUFo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LElBcEVILENBb0VRLE1BQU07QUFDVixhQUFPVixtQkFBbUI4RixPQUFuQixDQUEyQjdHLHlDQUEzQixFQUFzRW1FLGNBQXRFLENBQVA7QUFDRCxLQXRFSDs7QUF3RUEsV0FBT2xCLFFBQVFDLE9BQVIsQ0FBZ0IsRUFBQ1csVUFBVSxrRkFBWCxFQUFoQixDQUFQO0FBQ0Q7O0FBRURpRCxnQkFBYztBQUNaLFNBQUtDLEtBQUwsQ0FDRSxLQURGLEVBRUUsY0FGRixFQUdHdEcsR0FBRCxJQUFTO0FBQUUsYUFBTyxLQUFLcUQsWUFBTCxDQUFrQnJELEdBQWxCLENBQVA7QUFBZ0MsS0FIN0M7O0FBTUEsU0FBS3NHLEtBQUwsQ0FDRSxLQURGLEVBRUUsa0JBRkYsRUFHR3RHLEdBQUQsSUFBUztBQUFFLGFBQU8sS0FBSzhDLG9CQUFMLENBQTBCOUMsR0FBMUIsQ0FBUDtBQUF3QyxLQUhyRDtBQU1EO0FBdE02Qzs7UUFBbkNILFksR0FBQUEsWTtrQkF5TUVBLFkiLCJmaWxlIjoiRXhwb3J0Um91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb21pc2VSb3V0ZXIgICBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCB7IGxvYWRBZGFwdGVyIH0gZnJvbSAnLi4vQWRhcHRlcnMvQWRhcHRlckxvYWRlcic7XG5pbXBvcnQgcmVzdCAgICAgICAgICAgIGZyb20gJy4uL3Jlc3QnO1xuaW1wb3J0IGFyY2hpdmVyICAgICAgICBmcm9tICdhcmNoaXZlcic7XG5pbXBvcnQgdG1wICAgICAgICAgICAgIGZyb20gJ3RtcCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuXG5jb25zdCBEZWZhdWx0RXhwb3J0RXhwb3J0UHJvZ3Jlc3NDb2xsZWN0aW9uTmFtZSA9IFwiX0V4cG9ydFByb2dyZXNzXCI7XG5jb25zdCByZWxhdGlvblNjaGVtYSA9IHsgZmllbGRzOiB7IHJlbGF0ZWRJZDogeyB0eXBlOiAnU3RyaW5nJyB9LCBvd25pbmdJZDogeyB0eXBlOiAnU3RyaW5nJyB9IH0gfTtcblxuZXhwb3J0IGNsYXNzIEV4cG9ydFJvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuXG4gIGV4cG9ydENsYXNzUGFnZShyZXEsIG5hbWUsIGpzb25GaWxlU3RyZWFtLCB3aGVyZSwgc2tpcCwgbGltaXQpIHtcblxuICAgIGNvbnN0IGRhdGFiYXNlQ29udHJvbGxlciA9IHJlcS5jb25maWcuZGF0YWJhc2U7XG5cbiAgICBjb25zdCBvcHRpb25zID0gIHtcbiAgICAgIHNraXAsXG4gICAgICBsaW1pdFxuICAgIH07XG5cbiAgICBjb25zdCBmaW5kUHJvbWlzZSA9IG5hbWUuaW5kZXhPZignX0pvaW4nKSA9PT0gMCA/XG4gICAgICBkYXRhYmFzZUNvbnRyb2xsZXIuYWRhcHRlci5maW5kKG5hbWUsIHJlbGF0aW9uU2NoZW1hLCB3aGVyZSwgb3B0aW9ucylcbiAgICAgIDogcmVzdC5maW5kKHJlcS5jb25maWcsIHJlcS5hdXRoLCBuYW1lLCAgd2hlcmUsIG9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIGZpbmRQcm9taXNlXG4gICAgICAudGhlbigoZGF0YSkgPT4ge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgIGRhdGEgPSB7IHJlc3VsdHMgOiBkYXRhIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2tpcCAmJiBkYXRhLnJlc3VsdHMubGVuZ3RoKSB7XG4gICAgICAgICAganNvbkZpbGVTdHJlYW0ud3JpdGUoJyxcXG4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGpzb25GaWxlU3RyZWFtLndyaXRlKEpTT04uc3RyaW5naWZ5KGRhdGEucmVzdWx0cywgbnVsbCwgMikuc3Vic3RyKDEpLnNsaWNlKDAsLTEpKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgZXhwb3J0Q2xhc3MocmVxLCBkYXRhKSB7XG5cblxuICAgIGNvbnN0IGRhdGFiYXNlQ29udHJvbGxlciA9IHJlcS5jb25maWcuZGF0YWJhc2U7XG4gICAgY29uc3QgdG1wSnNvbkZpbGUgPSB0bXAuZmlsZVN5bmMoKTtcbiAgICBjb25zdCBqc29uRmlsZVN0cmVhbSA9IGZzLmNyZWF0ZVdyaXRlU3RyZWFtKHRtcEpzb25GaWxlLm5hbWUpO1xuXG4gICAganNvbkZpbGVTdHJlYW0ud3JpdGUoJ3tcXG5cInJlc3VsdHNcIiA6IFtcXG4nKTtcblxuICAgIGNvbnN0IGZpbmRQcm9taXNlID0gZGF0YS5uYW1lLmluZGV4T2YoJ19Kb2luJykgPT09IDAgP1xuICAgICAgZGF0YWJhc2VDb250cm9sbGVyLmFkYXB0ZXIuY291bnQoZGF0YS5uYW1lLCByZWxhdGlvblNjaGVtYSwgZGF0YS53aGVyZSlcbiAgICAgIDogcmVzdC5maW5kKHJlcS5jb25maWcsIHJlcS5hdXRoLCBkYXRhLm5hbWUsICBkYXRhLndoZXJlLCB7IGNvdW50OiB0cnVlLCBsaW1pdDogMCB9KTtcblxuICAgIHJldHVybiBmaW5kUHJvbWlzZVxuICAgICAgLnRoZW4oKHJlc3VsdCkgPT4ge1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHJlc3VsdCkpIHtcbiAgICAgICAgICByZXN1bHQgPSB7IGNvdW50OiByZXN1bHQgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgY29uc3QgcGFnZUxpbWl0ID0gMTAwMDtcbiAgICAgICAgbGV0IHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCByZXN1bHQuY291bnQ7IGkgKz0gcGFnZUxpbWl0KSB7XG5cbiAgICAgICAgICBjb25zdCBza2lwID0gaTtcbiAgICAgICAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cG9ydENsYXNzUGFnZShyZXEsIGRhdGEubmFtZSwganNvbkZpbGVTdHJlYW0sIGRhdGEud2hlcmUsIHNraXAsIHBhZ2VMaW1pdCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG5cbiAgICAgICAganNvbkZpbGVTdHJlYW0uZW5kKCddXFxufScpO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuXG4gICAgICAgICAganNvbkZpbGVTdHJlYW0ub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgICAgICAgdG1wSnNvbkZpbGUuX25hbWUgPSBgJHtkYXRhLm5hbWUucmVwbGFjZSgvOi9nLCfqnoknKX0uanNvbmA7XG5cbiAgICAgICAgICAgIHJlc29sdmUodG1wSnNvbkZpbGUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgfSk7XG4gIH1cblxuICBoYW5kbGVFeHBvcnRQcm9ncmVzcyhyZXEpIHtcblxuICAgIGNvbnN0IGRhdGFiYXNlQ29udHJvbGxlciA9IHJlcS5jb25maWcuZGF0YWJhc2U7XG5cbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIG1hc3RlcktleTogcmVxLmluZm8ubWFzdGVyS2V5LFxuICAgICAgYXBwbGljYXRpb25JZDogcmVxLmluZm8uYXBwSWRcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRhdGFiYXNlQ29udHJvbGxlci5maW5kKERlZmF1bHRFeHBvcnRFeHBvcnRQcm9ncmVzc0NvbGxlY3Rpb25OYW1lLCBxdWVyeSlcbiAgICAgIC50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICByZXR1cm4geyByZXNwb25zZSB9O1xuICAgICAgfSk7XG4gIH1cblxuICBoYW5kbGVFeHBvcnQocmVxKSB7XG5cbiAgICBjb25zdCBkYXRhYmFzZUNvbnRyb2xsZXIgPSByZXEuY29uZmlnLmRhdGFiYXNlO1xuXG4gICAgY29uc3QgZW1haWxDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKHJlcS5jb25maWcuZW1haWxBZGFwdGVyKTtcblxuICAgIGlmICghZW1haWxDb250cm9sbGVyQWRhcHRlcikge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignWW91IGhhdmUgdG8gc2V0dXAgYSBNYWlsIEFkYXB0ZXIuJykpO1xuICAgIH1cblxuICAgIGNvbnN0IGV4cG9ydFByb2dyZXNzID0ge1xuICAgICAgaWQ6IHJlcS5ib2R5Lm5hbWUsXG4gICAgICBtYXN0ZXJLZXk6IHJlcS5pbmZvLm1hc3RlcktleSxcbiAgICAgIGFwcGxpY2F0aW9uSWQ6IHJlcS5pbmZvLmFwcElkXG4gICAgfTtcblxuICAgIGRhdGFiYXNlQ29udHJvbGxlci5jcmVhdGUoRGVmYXVsdEV4cG9ydEV4cG9ydFByb2dyZXNzQ29sbGVjdGlvbk5hbWUsIGV4cG9ydFByb2dyZXNzKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gZGF0YWJhc2VDb250cm9sbGVyLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYShyZXEuYm9keS5uYW1lLCB0cnVlKSlcbiAgICAgIC50aGVuKChzY2hlbWEpID0+IHtcbiAgICAgICAgY29uc3QgY2xhc3NOYW1lcyA9IFsgcmVxLmJvZHkubmFtZSBdO1xuICAgICAgICBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKS5mb3JFYWNoKChmaWVsZE5hbWUpID0+IHtcbiAgICAgICAgICBjb25zdCBmaWVsZCA9IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXTtcblxuICAgICAgICAgIGlmIChmaWVsZC50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgICAgICBjbGFzc05hbWVzLnB1c2goYF9Kb2luOiR7ZmllbGROYW1lfToke3JlcS5ib2R5Lm5hbWV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBwcm9taXNzZXMgPSBjbGFzc05hbWVzLm1hcCgobmFtZSkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLmV4cG9ydENsYXNzKHJlcSwgeyBuYW1lIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzc2VzKVxuICAgICAgfSlcbiAgICAgIC50aGVuKChqc29uRmlsZXMpID0+IHtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICBjb25zdCB0bXBaaXBGaWxlID0gdG1wLmZpbGVTeW5jKCk7XG4gICAgICAgICAgY29uc3QgdG1wWmlwU3RyZWFtID0gZnMuY3JlYXRlV3JpdGVTdHJlYW0odG1wWmlwRmlsZS5uYW1lKTtcblxuICAgICAgICAgIGNvbnN0IHppcCAgPSBhcmNoaXZlcignemlwJyk7XG4gICAgICAgICAgemlwLnBpcGUodG1wWmlwU3RyZWFtKTtcblxuICAgICAgICAgIGpzb25GaWxlcy5mb3JFYWNoKHRtcEpzb25GaWxlID0+IHtcbiAgICAgICAgICAgIHppcC5hcHBlbmQoZnMucmVhZEZpbGVTeW5jKHRtcEpzb25GaWxlLm5hbWUpLCB7IG5hbWU6ICB0bXBKc29uRmlsZS5fbmFtZSB9KTtcbiAgICAgICAgICAgIHRtcEpzb25GaWxlLnJlbW92ZUNhbGxiYWNrKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICB6aXAuZmluYWxpemUoKTtcblxuICAgICAgICAgIHRtcFppcFN0cmVhbS5vbignY2xvc2UnLCAoKSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IGJ1ZiA9IGZzLnJlYWRGaWxlU3luYyh0bXBaaXBGaWxlLm5hbWUpO1xuICAgICAgICAgICAgdG1wWmlwRmlsZS5yZW1vdmVDYWxsYmFjaygpO1xuICAgICAgICAgICAgcmVzb2x2ZShidWYpO1xuXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICB9KVxuICAgICAgLnRoZW4oKHppcHBlZEZpbGUpID0+IHtcbiAgICAgICAgY29uc3QgZmlsZXNDb250cm9sbGVyID0gcmVxLmNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG4gICAgICAgIHJldHVybiBmaWxlc0NvbnRyb2xsZXIuY3JlYXRlRmlsZShyZXEuY29uZmlnLCByZXEuYm9keS5uYW1lLCB6aXBwZWRGaWxlLCAnYXBwbGljYXRpb24vemlwJyk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKGZpbGVEYXRhKSA9PiB7XG5cbiAgICAgICAgcmV0dXJuIGVtYWlsQ29udHJvbGxlckFkYXB0ZXIuc2VuZE1haWwoe1xuICAgICAgICAgIHRleHQ6IGBXZSBoYXZlIHN1Y2Nlc3NmdWxseSBleHBvcnRlZCB5b3VyIGRhdGEgZnJvbSB0aGUgY2xhc3MgJHtyZXEuYm9keS5uYW1lfS5cXG5cbiAgICAgICAgUGxlYXNlIGRvd25sb2FkIGZyb20gJHtmaWxlRGF0YS51cmx9YCxcbiAgICAgICAgICBsaW5rOiBmaWxlRGF0YS51cmwsXG4gICAgICAgICAgdG86IHJlcS5ib2R5LmZlZWRiYWNrRW1haWwsXG4gICAgICAgICAgc3ViamVjdDogJ0V4cG9ydCBjb21wbGV0ZWQnXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgcmV0dXJuIGVtYWlsQ29udHJvbGxlckFkYXB0ZXIuc2VuZE1haWwoe1xuICAgICAgICAgIHRleHQ6IGBXZSBjb3VsZCBub3QgZXhwb3J0IHlvdXIgZGF0YSB0byB0aGUgY2xhc3MgJHtyZXEuYm9keS5uYW1lfS4gRXJyb3I6ICR7ZXJyb3J9YCxcbiAgICAgICAgICB0bzogcmVxLmJvZHkuZmVlZGJhY2tFbWFpbCxcbiAgICAgICAgICBzdWJqZWN0OiAnRXhwb3J0IGZhaWxlZCdcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gZGF0YWJhc2VDb250cm9sbGVyLmRlc3Ryb3koRGVmYXVsdEV4cG9ydEV4cG9ydFByb2dyZXNzQ29sbGVjdGlvbk5hbWUsIGV4cG9ydFByb2dyZXNzKTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7cmVzcG9uc2U6ICdXZSBhcmUgZXhwb3J0aW5nIHlvdXIgZGF0YS4gWW91IHdpbGwgYmUgbm90aWZpZWQgYnkgZS1tYWlsIG9uY2UgaXQgaXMgY29tcGxldGVkLid9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoXG4gICAgICAnUFVUJyxcbiAgICAgICcvZXhwb3J0X2RhdGEnLFxuICAgICAgKHJlcSkgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVFeHBvcnQocmVxKTsgfVxuICAgICk7XG5cbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICAnL2V4cG9ydF9wcm9ncmVzcycsXG4gICAgICAocmVxKSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZUV4cG9ydFByb2dyZXNzKHJlcSk7IH1cbiAgICApO1xuXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRXhwb3J0Um91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/FeaturesRouter.js b/lib/Routers/FeaturesRouter.js index df7fe673b4..4a70a9d362 100644 --- a/lib/Routers/FeaturesRouter.js +++ b/lib/Routers/FeaturesRouter.js @@ -72,4 +72,5 @@ class FeaturesRouter extends _PromiseRouter2.default { }); } } -exports.FeaturesRouter = FeaturesRouter; \ No newline at end of file +exports.FeaturesRouter = FeaturesRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZlYXR1cmVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIm1pZGRsZXdhcmUiLCJGZWF0dXJlc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJyZXEiLCJmZWF0dXJlcyIsImdsb2JhbENvbmZpZyIsImNyZWF0ZSIsInJlYWQiLCJ1cGRhdGUiLCJkZWxldGUiLCJob29rcyIsImNsb3VkQ29kZSIsImpvYnMiLCJsb2dzIiwibGV2ZWwiLCJzaXplIiwib3JkZXIiLCJ1bnRpbCIsImZyb20iLCJwdXNoIiwiaW1tZWRpYXRlUHVzaCIsImNvbmZpZyIsImhhc1B1c2hTdXBwb3J0Iiwic2NoZWR1bGVkUHVzaCIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0Iiwic3RvcmVkUHVzaERhdGEiLCJwdXNoQXVkaWVuY2VzIiwibG9jYWxpemF0aW9uIiwic2NoZW1hcyIsImFkZEZpZWxkIiwicmVtb3ZlRmllbGQiLCJhZGRDbGFzcyIsInJlbW92ZUNsYXNzIiwiY2xlYXJBbGxEYXRhRnJvbUNsYXNzIiwiaW1wb3J0IiwiZXhwb3J0Q2xhc3MiLCJlZGl0Q2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiZWRpdFBvaW50ZXJQZXJtaXNzaW9ucyIsInJlc3BvbnNlIiwicGFyc2VTZXJ2ZXJWZXJzaW9uIiwidmVyc2lvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBQ0E7O0lBQVlBLFU7Ozs7OztBQUVMLE1BQU1DLGNBQU4sU0FBNkJDLHVCQUE3QixDQUEyQztBQUNoREMsZ0JBQWM7QUFDWixTQUFLQyxLQUFMLENBQVcsS0FBWCxFQUFpQixhQUFqQixFQUFnQ0osV0FBV0ssNkJBQTNDLEVBQTBFQyxPQUFPO0FBQy9FLFlBQU1DLFdBQVc7QUFDZkMsc0JBQWM7QUFDWkMsa0JBQVEsSUFESTtBQUVaQyxnQkFBTSxJQUZNO0FBR1pDLGtCQUFRLElBSEk7QUFJWkMsa0JBQVE7QUFKSSxTQURDO0FBT2ZDLGVBQU87QUFDTEosa0JBQVEsSUFESDtBQUVMQyxnQkFBTSxJQUZEO0FBR0xDLGtCQUFRLElBSEg7QUFJTEMsa0JBQVE7QUFKSCxTQVBRO0FBYWZFLG1CQUFXO0FBQ1RDLGdCQUFNO0FBREcsU0FiSTtBQWdCZkMsY0FBTTtBQUNKQyxpQkFBTyxJQURIO0FBRUpDLGdCQUFNLElBRkY7QUFHSkMsaUJBQU8sSUFISDtBQUlKQyxpQkFBTyxJQUpIO0FBS0pDLGdCQUFNO0FBTEYsU0FoQlM7QUF1QmZDLGNBQU07QUFDSkMseUJBQWVqQixJQUFJa0IsTUFBSixDQUFXQyxjQUR0QjtBQUVKQyx5QkFBZXBCLElBQUlrQixNQUFKLENBQVdHLHVCQUZ0QjtBQUdKQywwQkFBZ0J0QixJQUFJa0IsTUFBSixDQUFXQyxjQUh2QjtBQUlKSSx5QkFBZSxJQUpYO0FBS0pDLHdCQUFjO0FBTFYsU0F2QlM7QUE4QmZDLGlCQUFTO0FBQ1BDLG9CQUFVLElBREg7QUFFUEMsdUJBQWEsSUFGTjtBQUdQQyxvQkFBVSxJQUhIO0FBSVBDLHVCQUFhLElBSk47QUFLUEMsaUNBQXVCLElBTGhCO0FBTVBDLGtCQUFRLElBTkQ7QUFPUEMsdUJBQWEsSUFQTjtBQVFQQyxxQ0FBMkIsSUFScEI7QUFTUEMsa0NBQXdCO0FBVGpCO0FBOUJNLE9BQWpCOztBQTJDQSxhQUFPLEVBQUVDLFVBQVU7QUFDakJsQyxvQkFBVUEsUUFETztBQUVqQm1DLDhCQUFvQkM7QUFGSCxTQUFaLEVBQVA7QUFJRCxLQWhERDtBQWlERDtBQW5EK0M7UUFBckMxQyxjLEdBQUFBLGMiLCJmaWxlIjoiRmVhdHVyZXNSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB2ZXJzaW9uIH0gICAgIGZyb20gJy4uLy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciAgIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tIFwiLi4vbWlkZGxld2FyZXNcIjtcblxuZXhwb3J0IGNsYXNzIEZlYXR1cmVzUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0dFVCcsJy9zZXJ2ZXJJbmZvJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgcmVxID0+IHtcbiAgICAgIGNvbnN0IGZlYXR1cmVzID0ge1xuICAgICAgICBnbG9iYWxDb25maWc6IHtcbiAgICAgICAgICBjcmVhdGU6IHRydWUsXG4gICAgICAgICAgcmVhZDogdHJ1ZSxcbiAgICAgICAgICB1cGRhdGU6IHRydWUsXG4gICAgICAgICAgZGVsZXRlOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBob29rczoge1xuICAgICAgICAgIGNyZWF0ZTogdHJ1ZSxcbiAgICAgICAgICByZWFkOiB0cnVlLFxuICAgICAgICAgIHVwZGF0ZTogdHJ1ZSxcbiAgICAgICAgICBkZWxldGU6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIGNsb3VkQ29kZToge1xuICAgICAgICAgIGpvYnM6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIGxvZ3M6IHtcbiAgICAgICAgICBsZXZlbDogdHJ1ZSxcbiAgICAgICAgICBzaXplOiB0cnVlLFxuICAgICAgICAgIG9yZGVyOiB0cnVlLFxuICAgICAgICAgIHVudGlsOiB0cnVlLFxuICAgICAgICAgIGZyb206IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIHB1c2g6IHtcbiAgICAgICAgICBpbW1lZGlhdGVQdXNoOiByZXEuY29uZmlnLmhhc1B1c2hTdXBwb3J0LFxuICAgICAgICAgIHNjaGVkdWxlZFB1c2g6IHJlcS5jb25maWcuaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQsXG4gICAgICAgICAgc3RvcmVkUHVzaERhdGE6IHJlcS5jb25maWcuaGFzUHVzaFN1cHBvcnQsXG4gICAgICAgICAgcHVzaEF1ZGllbmNlczogdHJ1ZSxcbiAgICAgICAgICBsb2NhbGl6YXRpb246IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIHNjaGVtYXM6IHtcbiAgICAgICAgICBhZGRGaWVsZDogdHJ1ZSxcbiAgICAgICAgICByZW1vdmVGaWVsZDogdHJ1ZSxcbiAgICAgICAgICBhZGRDbGFzczogdHJ1ZSxcbiAgICAgICAgICByZW1vdmVDbGFzczogdHJ1ZSxcbiAgICAgICAgICBjbGVhckFsbERhdGFGcm9tQ2xhc3M6IHRydWUsXG4gICAgICAgICAgaW1wb3J0OiB0cnVlLFxuICAgICAgICAgIGV4cG9ydENsYXNzOiB0cnVlLFxuICAgICAgICAgIGVkaXRDbGFzc0xldmVsUGVybWlzc2lvbnM6IHRydWUsXG4gICAgICAgICAgZWRpdFBvaW50ZXJQZXJtaXNzaW9uczogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB7XG4gICAgICAgIGZlYXR1cmVzOiBmZWF0dXJlcyxcbiAgICAgICAgcGFyc2VTZXJ2ZXJWZXJzaW9uOiB2ZXJzaW9uLFxuICAgICAgfSB9O1xuICAgIH0pO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/FilesRouter.js b/lib/Routers/FilesRouter.js index 8ab5e94388..2bb887d417 100644 --- a/lib/Routers/FilesRouter.js +++ b/lib/Routers/FilesRouter.js @@ -202,4 +202,5 @@ function handleFileStream(stream, req, res, contentType) { } }); }); -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZpbGVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIk1pZGRsZXdhcmVzIiwiRmlsZXNSb3V0ZXIiLCJleHByZXNzUm91dGVyIiwibWF4VXBsb2FkU2l6ZSIsInJvdXRlciIsImV4cHJlc3MiLCJSb3V0ZXIiLCJnZXQiLCJnZXRIYW5kbGVyIiwicG9zdCIsInJlcSIsInJlcyIsIm5leHQiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9GSUxFX05BTUUiLCJhbGxvd0Nyb3NzRG9tYWluIiwiQm9keVBhcnNlciIsInJhdyIsInR5cGUiLCJsaW1pdCIsImhhbmRsZVBhcnNlSGVhZGVycyIsImNyZWF0ZUhhbmRsZXIiLCJkZWxldGUiLCJlbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwiZGVsZXRlSGFuZGxlciIsImNvbmZpZyIsIkNvbmZpZyIsInBhcmFtcyIsImFwcElkIiwiZmlsZXNDb250cm9sbGVyIiwiZmlsZW5hbWUiLCJjb250ZW50VHlwZSIsIm1pbWUiLCJnZXRUeXBlIiwiaXNGaWxlU3RyZWFtYWJsZSIsImdldEZpbGVTdHJlYW0iLCJ0aGVuIiwic3RyZWFtIiwiaGFuZGxlRmlsZVN0cmVhbSIsImNhdGNoIiwic3RhdHVzIiwic2V0IiwiZW5kIiwiZ2V0RmlsZURhdGEiLCJkYXRhIiwibGVuZ3RoIiwiYm9keSIsIkZJTEVfU0FWRV9FUlJPUiIsIm1hdGNoIiwiY3JlYXRlRmlsZSIsInJlc3VsdCIsInVybCIsImpzb24iLCJlIiwibG9nZ2VyIiwiZXJyb3IiLCJtZXNzYWdlIiwiZGVsZXRlRmlsZSIsIkZJTEVfREVMRVRFX0VSUk9SIiwiYWRhcHRlciIsImdldFJhbmdlIiwicGFydHMiLCJyZXBsYWNlIiwic3BsaXQiLCJzdGFydCIsInBhcnNlSW50IiwiYnVmZmVyX3NpemUiLCJub3RFbmRlZCIsIm5vdFN0YXJ0ZWQiLCJjb250ZW50TGVuZ3RoIiwid3JpdGVIZWFkIiwic2VlayIsImdyaWRGaWxlU3RyZWFtIiwiYnVmZmVyQXZhaWwiLCJyZW1haW5pbmdCeXRlc1RvV3JpdGUiLCJ0b3RhbEJ5dGVzV3JpdHRlbiIsIm9uIiwiYnVmZmVyIiwic2xpY2UiLCJ3cml0ZSIsImNsb3NlIiwiZGVzdHJveSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBQ0E7Ozs7QUFDQTs7SUFBWUEsVzs7QUFDWjs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7Ozs7QUFFTyxNQUFNQyxXQUFOLENBQWtCOztBQUV2QkMsZ0JBQWMsRUFBRUMsZ0JBQWdCLE1BQWxCLEtBQTZCLEVBQTNDLEVBQStDO0FBQzdDLFFBQUlDLFNBQVNDLGtCQUFRQyxNQUFSLEVBQWI7QUFDQUYsV0FBT0csR0FBUCxDQUFXLHlCQUFYLEVBQXNDLEtBQUtDLFVBQTNDOztBQUVBSixXQUFPSyxJQUFQLENBQVksUUFBWixFQUFzQixVQUFTQyxHQUFULEVBQWNDLEdBQWQsRUFBbUJDLElBQW5CLEVBQXlCO0FBQzdDQSxXQUFLLElBQUlDLGVBQU1DLEtBQVYsQ0FBZ0JELGVBQU1DLEtBQU4sQ0FBWUMsaUJBQTVCLEVBQ0gsd0JBREcsQ0FBTDtBQUVELEtBSEQ7O0FBS0FYLFdBQU9LLElBQVAsQ0FBWSxrQkFBWixFQUNFVCxZQUFZZ0IsZ0JBRGQsRUFFRUMscUJBQVdDLEdBQVgsQ0FBZSxFQUFDQyxNQUFNLE1BQU07QUFBRSxlQUFPLElBQVA7QUFBYyxPQUE3QixFQUErQkMsT0FBT2pCLGFBQXRDLEVBQWYsQ0FGRixFQUV5RTtBQUN2RUgsZ0JBQVlxQixrQkFIZCxFQUlFLEtBQUtDLGFBSlA7O0FBT0FsQixXQUFPbUIsTUFBUCxDQUFjLGtCQUFkLEVBQ0V2QixZQUFZZ0IsZ0JBRGQsRUFFRWhCLFlBQVlxQixrQkFGZCxFQUdFckIsWUFBWXdCLHNCQUhkLEVBSUUsS0FBS0MsYUFKUDtBQU1BLFdBQU9yQixNQUFQO0FBQ0Q7O0FBRURJLGFBQVdFLEdBQVgsRUFBZ0JDLEdBQWhCLEVBQXFCO0FBQ25CLFVBQU1lLFNBQVNDLGlCQUFPcEIsR0FBUCxDQUFXRyxJQUFJa0IsTUFBSixD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LE1BQVAsQ0FBYyxJQUFkLENBQXZCO0FBQ0EsUUFBSW9DLGNBQWMsQ0FBbEI7QUFDQSxRQUFJQyx3QkFBd0JMLGFBQTVCO0FBQ0EsUUFBSU0sb0JBQW9CLENBQXhCO0FBQ0E7QUFDQUgsbUJBQWVJLEVBQWYsQ0FBa0IsTUFBbEIsRUFBMEIsVUFBVWhDLElBQVYsRUFBZ0I7QUFDeEM2QixxQkFBZTdCLEtBQUtDLE1BQXBCO0FBQ0EsVUFBSTRCLGNBQWMsQ0FBbEIsRUFBcUI7QUFDbkI7QUFDQTtBQUNBLGNBQU1JLFNBQVNqQyxLQUFLa0MsS0FBTCxDQUFXLENBQVgsRUFBY0oscUJBQWQsQ0FBZjtBQUNBO0FBQ0FoRSxZQUFJcUUsS0FBSixDQUFVRixNQUFWO0FBQ0E7QUFDQUYsNkJBQXFCRSxPQUFPaEMsTUFBNUI7QUFDQTtBQUNBNkIsaUNBQXlCOUIsS0FBS0MsTUFBOUI7QUFDQTtBQUNBNEIsdUJBQWVJLE9BQU9oQyxNQUF0QjtBQUNEO0FBQ0Q7QUFDQTtBQUNBLFVBQUk4QixxQkFBcUJOLGFBQXpCLEVBQXdDO0FBQ3RDaEMsZUFBTzJDLEtBQVA7QUFDQXRFLFlBQUlnQyxHQUFKO0FBQ0EsYUFBS3VDLE9BQUw7QUFDRDtBQUNGLEtBdEJEO0FBdUJELEdBOUJEO0FBK0JEIiwiZmlsZSI6IkZpbGVzUm91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGV4cHJlc3MgICAgICAgICAgICAgZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgQm9keVBhcnNlciAgICAgICAgICBmcm9tICdib2R5LXBhcnNlcic7XG5pbXBvcnQgKiBhcyBNaWRkbGV3YXJlcyAgICBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5pbXBvcnQgUGFyc2UgICAgICAgICAgICAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBDb25maWcgICAgICAgICAgICAgIGZyb20gJy4uL0NvbmZpZyc7XG5pbXBvcnQgbWltZSAgICAgICAgICAgICAgICBmcm9tICdtaW1lJztcbmltcG9ydCBsb2dnZXIgICAgICAgICAgICAgIGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCBjbGFzcyBGaWxlc1JvdXRlciB7XG5cbiAgZXhwcmVzc1JvdXRlcih7IG1heFVwbG9hZFNpemUgPSAnMjBNYicgfSA9IHt9KSB7XG4gICAgdmFyIHJvdXRlciA9IGV4cHJlc3MuUm91dGVyKCk7XG4gICAgcm91dGVyLmdldCgnL2ZpbGVzLzphcHBJZC86ZmlsZW5hbWUnLCB0aGlzLmdldEhhbmRsZXIpO1xuXG4gICAgcm91dGVyLnBvc3QoJy9maWxlcycsIGZ1bmN0aW9uKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSxcbiAgICAgICAgJ0ZpbGVuYW1lIG5vdCBwcm92aWRlZC4nKSk7XG4gICAgfSk7XG5cbiAgICByb3V0ZXIucG9zdCgnL2ZpbGVzLzpmaWxlbmFtZScsXG4gICAgICBNaWRkbGV3YXJlcy5hbGxvd0Nyb3NzRG9tYWluLFxuICAgICAgQm9keVBhcnNlci5yYXcoe3R5cGU6ICgpID0+IHsgcmV0dXJuIHRydWU7IH0sIGxpbWl0OiBtYXhVcGxvYWRTaXplIH0pLCAvLyBBbGxvdyB1cGxvYWRzIHdpdGhvdXQgQ29udGVudC1UeXBlLCBvciB3aXRoIGFueSBDb250ZW50LVR5cGUuXG4gICAgICBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMsXG4gICAgICB0aGlzLmNyZWF0ZUhhbmRsZXJcbiAgICApO1xuXG4gICAgcm91dGVyLmRlbGV0ZSgnL2ZpbGVzLzpmaWxlbmFtZScsXG4gICAgICBNaWRkbGV3YXJlcy5hbGxvd0Nyb3NzRG9tYWluLFxuICAgICAgTWlkZGxld2FyZXMuaGFuZGxlUGFyc2VIZWFkZXJzLFxuICAgICAgTWlkZGxld2FyZXMuZW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIHRoaXMuZGVsZXRlSGFuZGxlclxuICAgICk7XG4gICAgcmV0dXJuIHJvdXRlcjtcbiAgfVxuXG4gIGdldEhhbmRsZXIocmVxLCByZXMpIHtcbiAgICBjb25zdCBjb25maWcgPSBDb25maWcuZ2V0KHJlcS5wYXJhbXMuYXBwSWQpO1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG4gICAgY29uc3QgZmlsZW5hbWUgPSByZXEucGFyYW1zLmZpbGVuYW1lO1xuICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gbWltZS5nZXRUeXBlKGZpbGVuYW1lKTtcbiAgICBpZiAoaXNGaWxlU3RyZWFtYWJsZShyZXEsIGZpbGVzQ29udHJvbGxlcikpIHtcbiAgICAgIGZpbGVzQ29udHJvbGxlci5nZXRGaWxlU3RyZWFtKGNvbmZpZywgZmlsZW5hbWUpLnRoZW4oKHN0cmVhbSkgPT4ge1xuICAgICAgICBoYW5kbGVGaWxlU3RyZWFtKHN0cmVhbSwgcmVxLCByZXMsIGNvbnRlbnRUeXBlKTtcbiAgICAgIH0pLmNhdGNoKCgpID0+IHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDQpO1xuICAgICAgICByZXMuc2V0KCdDb250ZW50LVR5cGUnLCAndGV4dC9wbGFpbicpO1xuICAgICAgICByZXMuZW5kKCdGaWxlIG5vdCBmb3VuZC4nKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBmaWxlc0NvbnRyb2xsZXIuZ2V0RmlsZURhdGEoY29uZmlnLCBmaWxlbmFtZSkudGhlbigoZGF0YSkgPT4ge1xuICAgICAgICByZXMuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5zZXQoJ0NvbnRlbnQtVHlwZScsIGNvbnRlbnRUeXBlKTtcbiAgICAgICAgcmVzLnNldCgnQ29udGVudC1MZW5ndGgnLCBkYXRhLmxlbmd0aCk7XG4gICAgICAgIHJlcy5lbmQoZGF0YSk7XG4gICAgICB9KS5jYXRjaCgoKSA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KTtcbiAgICAgICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgJ3RleHQvcGxhaW4nKTtcbiAgICAgICAgcmVzLmVuZCgnRmlsZSBub3QgZm91bmQuJyk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBjcmVhdGVIYW5kbGVyKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgaWYgKCFyZXEuYm9keSB8fCAhcmVxLmJvZHkubGVuZ3RoKSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsXG4gICAgICAgICdJbnZhbGlkIGZpbGUgdXBsb2FkLicpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocmVxLnBhcmFtcy5maWxlbmFtZS5sZW5ndGggPiAxMjgpIHtcbiAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICAnRmlsZW5hbWUgdG9vIGxvbmcuJykpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghcmVxLnBhcmFtcy5maWxlbmFtZS5tYXRjaCgvXltfYS16QS1aMC05XVthLXpBLVowLTlAXFwuXFwgfl8tXSokLykpIHtcbiAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICAnRmlsZW5hbWUgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzLicpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBmaWxlbmFtZSA9IHJlcS5wYXJhbXMuZmlsZW5hbWU7XG4gICAgY29uc3QgY29udGVudFR5cGUgPSByZXEuZ2V0KCdDb250ZW50LXR5cGUnKTtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG5cbiAgICBmaWxlc0NvbnRyb2xsZXIuY3JlYXRlRmlsZShjb25maWcsIGZpbGVuYW1lLCByZXEuYm9keSwgY29udGVudFR5cGUpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDEpO1xuICAgICAgcmVzLnNldCgnTG9jYXRpb24nLCByZXN1bHQudXJsKTtcbiAgICAgIHJlcy5qc29uKHJlc3VsdCk7XG4gICAgfSkuY2F0Y2goKGUpID0+IHtcbiAgICAgIGxvZ2dlci5lcnJvcihlLm1lc3NhZ2UsIGUpO1xuICAgICAgbmV4dChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLCAnQ291bGQgbm90IHN0b3JlIGZpbGUuJykpO1xuICAgIH0pO1xuICB9XG5cbiAgZGVsZXRlSGFuZGxlcihyZXEsIHJlcywgbmV4dCkge1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IHJlcS5jb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgIGZpbGVzQ29udHJvbGxlci5kZWxldGVGaWxlKHJlcS5jb25maWcsIHJlcS5wYXJhbXMuZmlsZW5hbWUpLnRoZW4oKCkgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApO1xuICAgICAgLy8gVE9ETzogcmV0dXJuIHVzZWZ1bCBKU09OIGhlcmU/XG4gICAgICByZXMuZW5kKCk7XG4gICAgfSkuY2F0Y2goKCkgPT4ge1xuICAgICAgbmV4dChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9ERUxFVEVfRVJST1IsXG4gICAgICAgICdDb3VsZCBub3QgZGVsZXRlIGZpbGUuJykpO1xuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzRmlsZVN0cmVhbWFibGUocmVxLCBmaWxlc0NvbnRyb2xsZXIpe1xuICByZXR1cm4gIHJlcS5nZXQoJ1JhbmdlJykgJiYgdHlwZW9mIGZpbGVzQ29udHJvbGxlci5hZGFwdGVyLmdldEZpbGVTdHJlYW0gPT09ICdmdW5jdGlvbic7XG59XG5cbmZ1bmN0aW9uIGdldFJhbmdlKHJlcSkge1xuICBjb25zdCBwYXJ0cyA9IHJlcS5nZXQoJ1JhbmdlJykucmVwbGFjZSgvYnl0ZXM9LywgXCJcIikuc3BsaXQoXCItXCIpO1xuICByZXR1cm4geyBzdGFydDogcGFyc2VJbnQocGFydHNbMF0sIDEwKSwgZW5kOiBwYXJzZUludChwYXJ0c1sxXSwgMTApIH07XG59XG5cbi8vIGhhbmRsZUZpbGVTdHJlYW0gaXMgbGljZW5jZWQgdW5kZXIgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbiA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlIChodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnkvNC4wLykuXG4vLyBBdXRob3I6IExFUk9JQiBhdCB3ZWlnaHRpbmdmb3JteXBpenphIChodHRwczovL3dlaWdodGluZ2Zvcm15cGl6emEud29yZHByZXNzLmNvbS8yMDE1LzA2LzI0L3N0cmVhbS1odG1sNS1tZWRpYS1jb250ZW50LWxpa2UtdmlkZW8tYXVkaW8tZnJvbS1tb25nb2RiLXVzaW5nLWV4cHJlc3MtYW5kLWdyaWRzdG9yZS8pLlxuZnVuY3Rpb24gaGFuZGxlRmlsZVN0cmVhbShzdHJlYW0sIHJlcSwgcmVzLCBjb250ZW50VHlwZSkge1xuICBjb25zdCBidWZmZXJfc2l6ZSA9IDEwMjQgKiAxMDI0OyAvLzEwMjRLYlxuICAvLyBSYW5nZSByZXF1ZXN0LCBwYXJ0aWFsbCBzdHJlYW0gdGhlIGZpbGVcbiAgbGV0IHtcbiAgICBzdGFydCwgZW5kXG4gIH0gPSBnZXRSYW5nZShyZXEpO1xuXG4gIGNvbnN0IG5vdEVuZGVkID0gKCFlbmQgJiYgZW5kICE9PSAwKTtcbiAgY29uc3Qgbm90U3RhcnRlZCA9ICghc3RhcnQgJiYgc3RhcnQgIT09IDApO1xuICAvLyBObyBlbmQgcHJvdmlkZWQsIHdlIHdhbnQgYWxsIGJ5dGVzXG4gIGlmIChub3RFbmRlZCkge1xuICAgIGVuZCA9IHN0cmVhbS5sZW5ndGggLSAxO1xuICB9XG4gIC8vIE5vIHN0YXJ0IHByb3ZpZGVkLCB3ZSdyZSByZWFkaW5nIGJhY2t3YXJkc1xuICBpZiAobm90U3RhcnRlZCkge1xuICAgIHN0YXJ0ID0gc3RyZWFtLmxlbmd0aCAtIGVuZDtcbiAgICBlbmQgPSBzdGFydCArIGVuZCAtIDE7XG4gIH1cblxuICAvLyBEYXRhIGV4Y2VlZHMgdGhlIGJ1ZmZlcl9zaXplLCBjYXBcbiAgaWYgKGVuZCAtIHN0YXJ0ID49IGJ1ZmZlcl9zaXplKSB7XG4gICAgZW5kID0gc3RhcnQgKyBidWZmZXJfc2l6ZSAtIDE7XG4gIH1cblxuICBjb25zdCBjb250ZW50TGVuZ3RoID0gKGVuZCAtIHN0YXJ0KSArIDE7XG5cbiAgcmVzLndyaXRlSGVhZCgyMDYsIHtcbiAgICAnQ29udGVudC1SYW5nZSc6ICdieXRlcyAnICsgc3RhcnQgKyAnLScgKyBlbmQgKyAnLycgKyBzdHJlYW0ubGVuZ3RoLFxuICAgICdBY2NlcHQtUmFuZ2VzJzogJ2J5dGVzJyxcbiAgICAnQ29udGVudC1MZW5ndGgnOiBjb250ZW50TGVuZ3RoLFxuICAgICdDb250ZW50LVR5cGUnOiBjb250ZW50VHlwZSxcbiAgfSk7XG5cbiAgc3RyZWFtLnNlZWsoc3RhcnQsIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBnZXQgZ3JpZEZpbGUgc3RyZWFtXG4gICAgY29uc3QgZ3JpZEZpbGVTdHJlYW0gPSBzdHJlYW0uc3RyZWFtKHRydWUpO1xuICAgIGxldCBidWZmZXJBdmFpbCA9IDA7XG4gICAgbGV0IHJlbWFpbmluZ0J5dGVzVG9Xcml0ZSA9IGNvbnRlbnRMZW5ndGg7XG4gICAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgICAvLyB3cml0ZSB0byByZXNwb25zZVxuICAgIGdyaWRGaWxlU3RyZWFtLm9uKCdkYXRhJywgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgIGJ1ZmZlckF2YWlsICs9IGRhdGEubGVuZ3RoO1xuICAgICAgaWYgKGJ1ZmZlckF2YWlsID4gMCkge1xuICAgICAgICAvLyBzbGljZSByZXR1cm5zIHRoZSBzYW1lIGJ1ZmZlciBpZiBvdmVyZmxvd2luZ1xuICAgICAgICAvLyBzYWZlIHRvIGNhbGwgaW4gYW55IGNhc2VcbiAgICAgICAgY29uc3QgYnVmZmVyID0gZGF0YS5zbGljZSgwLCByZW1haW5pbmdCeXRlc1RvV3JpdGUpO1xuICAgICAgICAvLyB3cml0ZSB0aGUgYnVmZmVyXG4gICAgICAgIHJlcy53cml0ZShidWZmZXIpO1xuICAgICAgICAvLyBpbmNyZW1lbnQgdG90YWxcbiAgICAgICAgdG90YWxCeXRlc1dyaXR0ZW4gKz0gYnVmZmVyLmxlbmd0aDtcbiAgICAgICAgLy8gZGVjcmVtZW50IHJlbWFpbmluZ1xuICAgICAgICByZW1haW5pbmdCeXRlc1RvV3JpdGUgLT0gZGF0YS5sZW5ndGg7XG4gICAgICAgIC8vIGRlY3JlbWVudCB0aGUgYXZhaWFsYmUgYnVmZmVyXG4gICAgICAgIGJ1ZmZlckF2YWlsIC09IGJ1ZmZlci5sZW5ndGg7XG4gICAgICB9XG4gICAgICAvLyBpbiBjYXNlIG9mIHNtYWxsIHNsaWNlcywgYWxsIHZhbHVlcyB3aWxsIGJlIGdvb2QgYXQgdGhhdCBwb2ludFxuICAgICAgLy8gd2UndmUgd3JpdHRlbiBlbm91Z2gsIGVuZC4uLlxuICAgICAgaWYgKHRvdGFsQnl0ZXNXcml0dGVuID49IGNvbnRlbnRMZW5ndGgpIHtcbiAgICAgICAgc3RyZWFtLmNsb3NlKCk7XG4gICAgICAgIHJlcy5lbmQoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuIl19 \ No newline at end of file diff --git a/lib/Routers/FunctionsRouter.js b/lib/Routers/FunctionsRouter.js index ef871f47bd..3c07a3cb91 100644 --- a/lib/Routers/FunctionsRouter.js +++ b/lib/Routers/FunctionsRouter.js @@ -106,6 +106,9 @@ class FunctionsRouter extends _PromiseRouter2.default { }, error: function (code, message) { if (!message) { + if (code instanceof Parse.Error) { + return reject(code); + } message = code; code = Parse.Error.SCRIPT_FAILED; } @@ -180,4 +183,5 @@ class FunctionsRouter extends _PromiseRouter2.default { } } } -exports.FunctionsRouter = FunctionsRouter; \ No newline at end of file +exports.FunctionsRouter = FunctionsRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0Z1bmN0aW9uc1JvdXRlci5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJ0cmlnZ2VycyIsInBhcnNlT2JqZWN0Iiwib2JqIiwiQXJyYXkiLCJpc0FycmF5IiwibWFwIiwiaXRlbSIsIl9fdHlwZSIsIk9iamVjdCIsImFzc2lnbiIsIkRhdGUiLCJpc28iLCJGaWxlIiwiZnJvbUpTT04iLCJwYXJzZVBhcmFtcyIsInBhcmFtcyIsIl8iLCJtYXBWYWx1ZXMiLCJGdW5jdGlvbnNSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsImhhbmRsZUNsb3VkRnVuY3Rpb24iLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsInJlcSIsImhhbmRsZUNsb3VkSm9iIiwiam9iTmFtZSIsImJvZHkiLCJhcHBsaWNhdGlvbklkIiwiY29uZmlnIiwiam9iSGFuZGxlciIsImpvYkZ1bmN0aW9uIiwiZ2V0Sm9iIiwiRXJyb3IiLCJTQ1JJUFRfRkFJTEVEIiwicXVlcnkiLCJyZXF1ZXN0IiwibG9nIiwibG9nZ2VyQ29udHJvbGxlciIsImhlYWRlcnMiLCJpcCIsInN0YXR1cyIsInN1Y2Nlc3MiLCJzZXRTdWNjZWVkZWQiLCJiaW5kIiwiZXJyb3IiLCJzZXRGYWlsZWQiLCJtZXNzYWdlIiwic2V0TWVzc2FnZSIsInNldFJ1bm5pbmciLCJ0aGVuIiwiam9iU3RhdHVzIiwiam9iSWQiLCJvYmplY3RJZCIsInByb2Nlc3MiLCJuZXh0VGljayIsInJlc3BvbnNlIiwiY3JlYXRlUmVzcG9uc2VPYmplY3QiLCJyZXNvbHZlIiwicmVqZWN0IiwicmVzdWx0IiwiX2VuY29kZSIsImNvZGUiLCJmdW5jdGlvbk5hbWUiLCJ0aGVGdW5jdGlvbiIsImdldEZ1bmN0aW9uIiwidGhlVmFsaWRhdG9yIiwiZ2V0VmFsaWRhdG9yIiwibWFzdGVyIiwiYXV0aCIsImlzTWFzdGVyIiwidXNlciIsImluc3RhbGxhdGlvbklkIiwiaW5mbyIsIlZBTElEQVRJT05fRVJST1IiLCJQcm9taXNlIiwidXNlclN0cmluZyIsImlkIiwidW5kZWZpbmVkIiwiY2xlYW5JbnB1dCIsImxvZ2dlciIsInRydW5jYXRlTG9nTWVzc2FnZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJjbGVhblJlc3VsdCIsImUiLCJqYXZhc2NyaXB0S2V5IiwibWFzdGVyS2V5Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBS0E7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUNBOzs7O0FBVEE7O0FBRUEsSUFBSUEsUUFBUUMsUUFBUSxZQUFSLEVBQXNCRCxLQUFsQztBQUFBLElBQ0VFLFdBQVdELFFBQVEsYUFBUixDQURiOztBQVNBLFNBQVNFLFdBQVQsQ0FBcUJDLEdBQXJCLEVBQTBCO0FBQ3hCLE1BQUlDLE1BQU1DLE9BQU4sQ0FBY0YsR0FBZCxDQUFKLEVBQXdCO0FBQ3RCLFdBQU9BLElBQUlHLEdBQUosQ0FBU0MsSUFBRCxJQUFVO0FBQ3ZCLGFBQU9MLFlBQVlLLElBQVosQ0FBUDtBQUNELEtBRk0sQ0FBUDtBQUdELEdBSkQsTUFJTyxJQUFJSixPQUFPQSxJQUFJSyxNQUFKLElBQWMsTUFBekIsRUFBaUM7QUFDdEMsV0FBT0MsT0FBT0MsTUFBUCxDQUFjLElBQUlDLElBQUosQ0FBU1IsSUFBSVMsR0FBYixDQUFkLEVBQWlDVCxHQUFqQyxDQUFQO0FBQ0QsR0FGTSxNQUVBLElBQUlBLE9BQU9BLElBQUlLLE1BQUosSUFBYyxNQUF6QixFQUFpQztBQUN0QyxXQUFPVCxNQUFNYyxJQUFOLENBQVdDLFFBQVgsQ0FBb0JYLEdBQXBCLENBQVA7QUFDRCxHQUZNLE1BRUEsSUFBSUEsT0FBTyxPQUFPQSxHQUFQLEtBQWUsUUFBMUIsRUFBb0M7QUFDekMsV0FBT1ksWUFBWVosR0FBWixDQUFQO0FBQ0QsR0FGTSxNQUVBO0FBQ0wsV0FBT0EsR0FBUDtBQUNEO0FBQ0Y7O0FBRUQsU0FBU1ksV0FBVCxDQUFxQkMsTUFBckIsRUFBNkI7QUFDM0IsU0FBT0MsaUJBQUVDLFNBQUYsQ0FB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LGlDQUFnQ2tCLFlBQWEsYUFBWWEsVUFBVyxvQkFBbUJHLFVBQVcsYUFBbkcsR0FBa0hHLEtBQUtDLFNBQUwsQ0FBZXRDLEtBQWYsQ0FEcEgsRUFFRTtBQUNFa0IsMEJBREY7QUFFRWxCLG1CQUZGO0FBR0U5QixvQkFIRjtBQUlFd0Qsb0JBQU1LO0FBSlIsYUFGRjtBQVNBakIsbUJBQU9kLEtBQVA7QUFDRCxXQVhELENBV0UsT0FBT3dDLENBQVAsRUFBVTtBQUNWMUIsbUJBQU8wQixDQUFQO0FBQ0Q7QUFDRixTQTlCYyxDQUFmO0FBK0JBO0FBQ0F2RixjQUFNOEIsYUFBTixHQUFzQkosSUFBSUssTUFBSixDQUFXRCxhQUFqQztBQUNBOUIsY0FBTXdGLGFBQU4sR0FBc0I5RCxJQUFJSyxNQUFKLENBQVd5RCxhQUFqQztBQUNBeEYsY0FBTXlGLFNBQU4sR0FBa0IvRCxJQUFJSyxNQUFKLENBQVcwRCxTQUE3QjtBQUNBdkIsb0JBQVk1QixPQUFaLEVBQXFCb0IsUUFBckI7QUFDRCxPQXZDTSxDQUFQO0FBd0NELEtBN0RELE1BNkRPO0FBQ0wsWUFBTSxJQUFJMUQsTUFBTW1DLEtBQVYsQ0FBZ0JuQyxNQUFNbUMsS0FBTixDQUFZQyxhQUE1QixFQUE0QyxzQkFBcUI2QixZQUFhLEdBQTlFLENBQU47QUFDRDtBQUNGO0FBN0lnRDtRQUF0QzdDLGUsR0FBQUEsZSIsImZpbGUiOiJGdW5jdGlvbnNSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBGdW5jdGlvbnNSb3V0ZXIuanNcblxudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlLFxuICB0cmlnZ2VycyA9IHJlcXVpcmUoJy4uL3RyaWdnZXJzJyk7XG5cbmltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0IHsgcHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MgfSBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5pbXBvcnQgeyBqb2JTdGF0dXNIYW5kbGVyIH0gZnJvbSAnLi4vU3RhdHVzSGFuZGxlcic7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyJztcblxuZnVuY3Rpb24gcGFyc2VPYmplY3Qob2JqKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gb2JqLm1hcCgoaXRlbSkgPT4ge1xuICAgICAgcmV0dXJuIHBhcnNlT2JqZWN0KGl0ZW0pO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKG9iaiAmJiBvYmouX190eXBlID09ICdEYXRlJykge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBEYXRlKG9iai5pc28pLCBvYmopO1xuICB9IGVsc2UgaWYgKG9iaiAmJiBvYmouX190eXBlID09ICdGaWxlJykge1xuICAgIHJldHVybiBQYXJzZS5GaWxlLmZyb21KU09OKG9iaik7XG4gIH0gZWxzZSBpZiAob2JqICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIHBhcnNlUGFyYW1zKG9iaik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVBhcmFtcyhwYXJhbXMpIHtcbiAgcmV0dXJuIF8ubWFwVmFsdWVzKHBhcmFtcywgcGFyc2VPYmplY3QpO1xufVxuXG5leHBvcnQgY2xhc3MgRnVuY3Rpb25zUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvZnVuY3Rpb25zLzpmdW5jdGlvbk5hbWUnLCBGdW5jdGlvbnNSb3V0ZXIuaGFuZGxlQ2xvdWRGdW5jdGlvbik7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvam9icy86am9iTmFtZScsIHByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCBmdW5jdGlvbihyZXEpIHtcbiAgICAgIHJldHVybiBGdW5jdGlvbnNSb3V0ZXIuaGFuZGxlQ2xvdWRKb2IocmVxKTtcbiAgICB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy9qb2JzJywgcHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIGZ1bmN0aW9uKHJlcSkge1xuICAgICAgcmV0dXJuIEZ1bmN0aW9uc1JvdXRlci5oYW5kbGVDbG91ZEpvYihyZXEpO1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGhhbmRsZUNsb3VkSm9iKHJlcSkge1xuICAgIGNvbnN0IGpvYk5hbWUgPSByZXEucGFyYW1zLmpvYk5hbWUgfHwgcmVxLmJvZHkuam9iTmFtZTtcbiAgICBjb25zdCBhcHBsaWNhdGlvbklkID0gcmVxLmNvbmZpZy5hcHBsaWNhdGlvbklkO1xuICAgIGNvbnN0IGpvYkhhbmRsZXIgPSBqb2JTdGF0dXNIYW5kbGVyKHJlcS5jb25maWcpO1xuICAgIGNvbnN0IGpvYkZ1bmN0aW9uID0gdHJpZ2dlcnMuZ2V0Sm9iKGpvYk5hbWUsIGFwcGxpY2F0aW9uSWQpO1xuICAgIGlmICgham9iRnVuY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVELCAnSW52YWxpZCBqb2IuJyk7XG4gICAgfVxuICAgIGxldCBwYXJhbXMgPSBPYmplY3QuYXNzaWduKHt9LCByZXEuYm9keSwgcmVxLnF1ZXJ5KTtcbiAgICBwYXJhbXMgPSBwYXJzZVBhcmFtcyhwYXJhbXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICBwYXJhbXM6IHBhcmFtcyxcbiAgICAgIGxvZzogcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyLFxuICAgICAgaGVhZGVyczogcmVxLmNvbmZpZy5oZWFkZXJzLFxuICAgICAgaXA6IHJlcS5jb25maWcuaXAsXG4gICAgICBqb2JOYW1lXG4gICAgfTtcbiAgICBjb25zdCBzdGF0dXMgPSB7XG4gICAgICBzdWNjZXNzOiBqb2JIYW5kbGVyLnNldFN1Y2NlZWRlZC5iaW5kKGpvYkhhbmRsZXIpLFxuICAgICAgZXJyb3I6IGpvYkhhbmRsZXIuc2V0RmFpbGVkLmJpbmQoam9iSGFuZGxlciksXG4gICAgICBtZXNzYWdlOiBqb2JIYW5kbGVyLnNldE1lc3NhZ2UuYmluZChqb2JIYW5kbGVyKVxuICAgIH1cbiAgICByZXR1cm4gam9iSGFuZGxlci5zZXRSdW5uaW5nKGpvYk5hbWUsIHBhcmFtcykudGhlbigoam9iU3RhdHVzKSA9PiB7XG4gICAgICByZXF1ZXN0LmpvYklkID0gam9iU3RhdHVzLm9iamVjdElkXG4gICAgICAvLyBydW4gdGhlIGZ1bmN0aW9uIGFzeW5jXG4gICAgICBwcm9jZXNzLm5leHRUaWNrKCgpID0+IHtcbiAgICAgICAgam9iRnVuY3Rpb24ocmVxdWVzdCwgc3RhdHVzKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdYLVBhcnNlLUpvYi1TdGF0dXMtSWQnOiBqb2JTdGF0dXMub2JqZWN0SWRcbiAgICAgICAgfSxcbiAgICAgICAgcmVzcG9uc2U6IHt9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlUmVzcG9uc2VPYmplY3QocmVzb2x2ZSwgcmVqZWN0LCBtZXNzYWdlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICByZXNwb25zZToge1xuICAgICAgICAgICAgcmVzdWx0OiBQYXJzZS5fZW5jb2RlKHJlc3VsdClcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiBmdW5jdGlvbihjb2RlLCBtZXNzYWdlKSB7XG4gICAgICAgIGlmICghbWVzc2FnZSkge1xuICAgICAgICAgIGlmIChjb2RlIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoY29kZSlcbiAgICAgICAgICB9XG4gICAgICAgICAgbWVzc2FnZSA9IGNvZGU7XG4gICAgICAgICAgY29kZSA9IFBhcnNlLkVycm9yLlNDUklQVF9GQUlMRUQ7XG4gICAgICAgIH1cbiAgICAgICAgcmVqZWN0KG5ldyBQYXJzZS5FcnJvcihjb2RlLCBtZXNzYWdlKSk7XG4gICAgICB9LFxuICAgICAgbWVzc2FnZTogbWVzc2FnZVxuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBoYW5kbGVDbG91ZEZ1bmN0aW9uKHJlcSkge1xuICAgIGNvbnN0IGZ1bmN0aW9uTmFtZSA9IHJlcS5wYXJhbXMuZnVuY3Rpb25OYW1lO1xuICAgIGNvbnN0IGFwcGxpY2F0aW9uSWQgPSByZXEuY29uZmlnLmFwcGxpY2F0aW9uSWQ7XG4gICAgY29uc3QgdGhlRnVuY3Rpb24gPSB0cmlnZ2Vycy5nZXRGdW5jdGlvbihmdW5jdGlvbk5hbWUsIGFwcGxpY2F0aW9uSWQpO1xuICAgIGNvbnN0IHRoZVZhbGlkYXRvciA9IHRyaWdnZXJzLmdldFZhbGlkYXRvcihyZXEucGFyYW1zLmZ1bmN0aW9uTmFtZSwgYXBwbGljYXRpb25JZCk7XG4gICAgaWYgKHRoZUZ1bmN0aW9uKSB7XG4gICAgICBsZXQgcGFyYW1zID0gT2JqZWN0LmFzc2lnbih7fSwgcmVxLmJvZHksIHJlcS5xdWVyeSk7XG4gICAgICBwYXJhbXMgPSBwYXJzZVBhcmFtcyhwYXJhbXMpO1xuICAgICAgdmFyIHJlcXVlc3QgPSB7XG4gICAgICAgIHBhcmFtczogcGFyYW1zLFxuICAgICAgICBtYXN0ZXI6IHJlcS5hdXRoICYmIHJlcS5hdXRoLmlzTWFzdGVyLFxuICAgICAgICB1c2VyOiByZXEuYXV0aCAmJiByZXEuYXV0aC51c2VyLFxuICAgICAgICBpbnN0YWxsYXRpb25JZDogcmVxLmluZm8uaW5zdGFsbGF0aW9uSWQsXG4gICAgICAgIGxvZzogcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyLFxuICAgICAgICBoZWFkZXJzOiByZXEuY29uZmlnLmhlYWRlcnMsXG4gICAgICAgIGlwOiByZXEuY29uZmlnLmlwLFxuICAgICAgICBmdW5jdGlvbk5hbWVcbiAgICAgIH07XG5cbiAgICAgIGlmICh0aGVWYWxpZGF0b3IgJiYgdHlwZW9mIHRoZVZhbGlkYXRvciA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGVWYWxpZGF0b3IocmVxdWVzdCk7XG4gICAgICAgIGlmICghcmVzdWx0KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsICdWYWxpZGF0aW9uIGZhaWxlZC4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBjb25zdCB1c2VyU3RyaW5nID0gKHJlcS5hdXRoICYmIHJlcS5hdXRoLnVzZXIpID8gcmVxLmF1dGgudXNlci5pZCA6IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgY2xlYW5JbnB1dCA9IGxvZ2dlci50cnVuY2F0ZUxvZ01lc3NhZ2UoSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIHZhciByZXNwb25zZSA9IEZ1bmN0aW9uc1JvdXRlci5jcmVhdGVSZXNwb25zZU9iamVjdCgocmVzdWx0KSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGNsZWFuUmVzdWx0ID0gbG9nZ2VyLnRydW5jYXRlTG9nTWVzc2FnZShKU09OLnN0cmluZ2lmeShyZXN1bHQucmVzcG9uc2UucmVzdWx0KSk7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgYFJhbiBjbG91ZCBmdW5jdGlvbiAke2Z1bmN0aW9uTmFtZX0gZm9yIHVzZXIgJHt1c2VyU3RyaW5nfSB3aXRoOlxcbiAgSW5wdXQ6ICR7Y2xlYW5JbnB1dCB9XFxuICBSZXN1bHQ6ICR7Y2xlYW5SZXN1bHQgfWAsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgICAgICAgIHVzZXI6IHVzZXJTdHJpbmcsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgYEZhaWxlZCBydW5uaW5nIGNsb3VkIGZ1bmN0aW9uICR7ZnVuY3Rpb25OYW1lfSBmb3IgdXNlciAke3VzZXJTdHJpbmd9IHdpdGg6XFxuICBJbnB1dDogJHtjbGVhbklucHV0fVxcbiAgRXJyb3I6IGAgKyBKU09OLnN0cmluZ2lmeShlcnJvciksXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgICAgICAgIHVzZXI6IHVzZXJTdHJpbmdcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIC8vIEZvcmNlIHRoZSBrZXlzIGJlZm9yZSB0aGUgZnVuY3Rpb24gY2FsbHMuXG4gICAgICAgIFBhcnNlLmFwcGxpY2F0aW9uSWQgPSByZXEuY29uZmlnLmFwcGxpY2F0aW9uSWQ7XG4gICAgICAgIFBhcnNlLmphdmFzY3JpcHRLZXkgPSByZXEuY29uZmlnLmphdmFzY3JpcHRLZXk7XG4gICAgICAgIFBhcnNlLm1hc3RlcktleSA9IHJlcS5jb25maWcubWFzdGVyS2V5O1xuICAgICAgICB0aGVGdW5jdGlvbihyZXF1ZXN0LCByZXNwb25zZSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlNDUklQVF9GQUlMRUQsIGBJbnZhbGlkIGZ1bmN0aW9uOiBcIiR7ZnVuY3Rpb25OYW1lfVwiYCk7XG4gICAgfVxuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/GlobalConfigRouter.js b/lib/Routers/GlobalConfigRouter.js index 140960dfe8..9cc462c784 100644 --- a/lib/Routers/GlobalConfigRouter.js +++ b/lib/Routers/GlobalConfigRouter.js @@ -58,4 +58,5 @@ class GlobalConfigRouter extends _PromiseRouter2.default { exports.GlobalConfigRouter = GlobalConfigRouter; // global_config.js -exports.default = GlobalConfigRouter; \ No newline at end of file +exports.default = GlobalConfigRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0dsb2JhbENvbmZpZ1JvdXRlci5qcyJdLCJuYW1lcyI6WyJtaWRkbGV3YXJlIiwiR2xvYmFsQ29uZmlnUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsImdldEdsb2JhbENvbmZpZyIsInJlcSIsImNvbmZpZyIsImRhdGFiYXNlIiwiZmluZCIsIm9iamVjdElkIiwibGltaXQiLCJ0aGVuIiwicmVzdWx0cyIsImxlbmd0aCIsInJlc3BvbnNlIiwicGFyYW1zIiwiZ2xvYmFsQ29uZmlnIiwidXBkYXRlR2xvYmFsQ29uZmlnIiwiYXV0aCIsImlzUmVhZE9ubHkiLCJQYXJzZSIsIkVycm9yIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsImJvZHkiLCJ1cGRhdGUiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwiYWNjIiwia2V5IiwidXBzZXJ0IiwicmVzdWx0IiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztJQUFZQSxVOzs7Ozs7QUFFTCxNQUFNQyxrQkFBTixTQUFpQ0MsdUJBQWpDLENBQStDO0FBQ3BEQyxrQkFBZ0JDLEdBQWhCLEVBQXFCO0FBQ25CLFdBQU9BLElBQUlDLE1BQUosQ0FBV0MsUUFBWCxDQUFvQkMsSUFBcEIsQ0FBeUIsZUFBekIsRUFBMEMsRUFBRUMsVUFBVSxHQUFaLEVBQTFDLEVBQTZELEVBQUVDLE9BQU8sQ0FBVCxFQUE3RCxFQUEyRUMsSUFBM0UsQ0FBaUZDLE9BQUQsSUFBYTtBQUNsRyxVQUFJQSxRQUFRQyxNQUFSLElBQWtCLENBQXRCLEVBQXlCO0FBQ3ZCO0FBQ0EsZUFBTyxFQUFFQyxVQUFVLEVBQUVDLFFBQVEsRUFBVixFQUFaLEVBQVA7QUFDRDtBQUNELFlBQU1DLGVBQWVKLFFBQVEsQ0FBUixDQUFyQjtBQUNBLGFBQU8sRUFBRUUsVUFBVSxFQUFFQyxRQUFRQyxhQUFhRCxNQUF2QixFQUFaLEVBQVA7QUFDRCxLQVBNLENBQVA7QUFRRDs7QUFFREUscUJBQW1CWixHQUFuQixFQUF3QjtBQUN0QixRQUFJQSxJQUFJYSxJQUFKLENBQVNDLFVBQWIsRUFBeUI7QUFDdkIsWUFBTSxJQUFJQyxlQUFNQyxLQUFWLENBQWdCRCxlQUFNQyxLQUFOLENBQVlDLG1CQUE1QixFQUFpRCwwREFBakQsQ0FBTjtBQUNEO0FBQ0QsVUFBTVAsU0FBU1YsSUFBSWtCLElBQUosQ0FBU1IsTUFBeEI7QUFDQTtBQUNBLFVBQU1TLFNBQVNDLE9BQU9DLElBQVAsQ0FBWVgsTUFBWixFQUFvQlksTUFBcEIsQ0FBMkIsQ0FBQ0MsR0FBRCxFQUFNQyxHQUFOLEtBQWM7QUFDdERELFVBQUssVUFBU0MsR0FBSSxFQUFsQixJQUF1QmQsT0FBT2MsR0FBUCxDQUF2QjtBQUNBLGFBQU9ELEdBQVA7QUFDRCxLQUhjLEVBR1osRUFIWSxDQUFmO0FBSUEsV0FBT3ZCLElBQUlDLE1BQUosQ0FBV0MsUUFBWCxDQUFvQmlCLE1BQXBCLENBQTJCLGVBQTNCLEVBQTRDLEVBQUNmLFVBQVUsR0FBWCxFQUE1QyxFQUE2RGUsTUFBN0QsRUFBcUUsRUFBQ00sUUFBUSxJQUFULEVBQXJFLEVBQXFGbkIsSUFBckYsQ0FBMEYsT0FBTyxFQUFFRyxVQUFVLEVBQUVpQixRQUFRLElBQVYsRUFBWixFQUFQLENBQTFGLENBQVA7QUFDRDs7QUFFREMsZ0JBQWM7QUFDWixTQUFLQyxLQUFMLENBQVcsS0FBWCxFQUFrQixTQUFsQixFQUE2QjVCLE9BQU87QUFBRSxhQUFPLEtBQUtELGVBQUwsQ0FBcUJDLEdBQXJCLENBQVA7QUFBa0MsS0FBeEU7QUFDQSxTQUFLNEIsS0FBTCxDQUFXLEtBQVgsRUFBa0IsU0FBbEIsRUFBNkJoQyxXQUFXaUMsNkJBQXhDLEVBQXVFN0IsT0FBTztBQUFFLGFBQU8sS0FBS1ksa0JBQUwsQ0FBd0JaLEdBQXhCLENBQVA7QUFBcUMsS0FBckg7QUFDRDtBQTVCbUQ7O1FBQXpDSCxrQixHQUFBQSxrQixFQUxiOztrQkFvQ2VBLGtCIiwiZmlsZSI6Ikdsb2JhbENvbmZpZ1JvdXRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIGdsb2JhbF9jb25maWcuanNcbmltcG9ydCBQYXJzZSAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciAgIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tIFwiLi4vbWlkZGxld2FyZXNcIjtcblxuZXhwb3J0IGNsYXNzIEdsb2JhbENvbmZpZ1JvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuICBnZXRHbG9iYWxDb25maWcocmVxKSB7XG4gICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2UuZmluZCgnX0dsb2JhbENvbmZpZycsIHsgb2JqZWN0SWQ6IFwiMVwiIH0sIHsgbGltaXQ6IDEgfSkudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoICE9IDEpIHtcbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgbm8gY29uZmlnIGluIHRoZSBkYXRhYmFzZSAtIHJldHVybiBlbXB0eSBjb25maWcuXG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB7IHBhcmFtczoge30gfSB9O1xuICAgICAgfVxuICAgICAgY29uc3QgZ2xvYmFsQ29uZmlnID0gcmVzdWx0c1swXTtcbiAgICAgIHJldHVybiB7IHJlc3BvbnNlOiB7IHBhcmFtczogZ2xvYmFsQ29uZmlnLnBhcmFtcyB9IH07XG4gICAgfSk7XG4gIH1cblxuICB1cGRhdGVHbG9iYWxDb25maWcocmVxKSB7XG4gICAgaWYgKHJlcS5hdXRoLmlzUmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCAncmVhZC1vbmx5IG1hc3RlcktleSBpc25cXCd0IGFsbG93ZWQgdG8gdXBkYXRlIHRoZSBjb25maWcuJyk7XG4gICAgfVxuICAgIGNvbnN0IHBhcmFtcyA9IHJlcS5ib2R5LnBhcmFtcztcbiAgICAvLyBUcmFuc2Zvcm0gaW4gZG90IG5vdGF0aW9uIHRvIG1ha2Ugc3VyZSBpdCB3b3Jrc1xuICAgIGNvbnN0IHVwZGF0ZSA9IE9iamVjdC5rZXlzKHBhcmFtcykucmVkdWNlKChhY2MsIGtleSkgPT4ge1xuICAgICAgYWNjW2BwYXJhbXMuJHtrZXl9YF0gPSBwYXJhbXNba2V5XTtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwge30pO1xuICAgIHJldHVybiByZXEuY29uZmlnLmRhdGFiYXNlLnVwZGF0ZSgnX0dsb2JhbENvbmZpZycsIHtvYmplY3RJZDogXCIxXCJ9LCB1cGRhdGUsIHt1cHNlcnQ6IHRydWV9KS50aGVuKCgpID0+ICh7IHJlc3BvbnNlOiB7IHJlc3VsdDogdHJ1ZSB9IH0pKTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvY29uZmlnJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuZ2V0R2xvYmFsQ29uZmlnKHJlcSkgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUFVUJywgJy9jb25maWcnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCByZXEgPT4geyByZXR1cm4gdGhpcy51cGRhdGVHbG9iYWxDb25maWcocmVxKSB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBHbG9iYWxDb25maWdSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/HooksRouter.js b/lib/Routers/HooksRouter.js index 07a6933ea2..3ec43a8bfb 100644 --- a/lib/Routers/HooksRouter.js +++ b/lib/Routers/HooksRouter.js @@ -114,4 +114,5 @@ class HooksRouter extends _PromiseRouter2.default { } exports.HooksRouter = HooksRouter; -exports.default = HooksRouter; \ No newline at end of file +exports.default = HooksRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0hvb2tzUm91dGVyLmpzIl0sIm5hbWVzIjpbIm1pZGRsZXdhcmUiLCJIb29rc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJjcmVhdGVIb29rIiwiYUhvb2siLCJjb25maWciLCJob29rc0NvbnRyb2xsZXIiLCJ0aGVuIiwiaG9vayIsInJlc3BvbnNlIiwidXBkYXRlSG9vayIsImhhbmRsZVBvc3QiLCJyZXEiLCJib2R5IiwiaGFuZGxlR2V0RnVuY3Rpb25zIiwicGFyYW1zIiwiZnVuY3Rpb25OYW1lIiwiZ2V0RnVuY3Rpb24iLCJmb3VuZEZ1bmN0aW9uIiwiUGFyc2UiLCJFcnJvciIsIlByb21pc2UiLCJyZXNvbHZlIiwiZ2V0RnVuY3Rpb25zIiwiZnVuY3Rpb25zIiwiZXJyIiwiaGFuZGxlR2V0VHJpZ2dlcnMiLCJjbGFzc05hbWUiLCJ0cmlnZ2VyTmFtZSIsImdldFRyaWdnZXIiLCJmb3VuZFRyaWdnZXIiLCJnZXRUcmlnZ2VycyIsInRyaWdnZXJzIiwiaGFuZGxlRGVsZXRlIiwiZGVsZXRlRnVuY3Rpb24iLCJkZWxldGVUcmlnZ2VyIiwiaGFuZGxlVXBkYXRlIiwidXJsIiwiaGFuZGxlUHV0IiwiX19vcCIsIm1vdW50Um91dGVzIiwicm91dGUiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsImJpbmQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7OztBQUNBOztJQUFZQSxVOzs7Ozs7QUFFTCxNQUFNQyxXQUFOLFNBQTBCQyx1QkFBMUIsQ0FBd0M7QUFDN0NDLGFBQVdDLEtBQVgsRUFBa0JDLE1BQWxCLEVBQTBCO0FBQ3hCLFdBQU9BLE9BQU9DLGVBQVAsQ0FBdUJILFVBQXZCLENBQWtDQyxLQUFsQyxFQUF5Q0csSUFBekMsQ0FBK0NDLElBQUQsS0FBVyxFQUFDQyxVQUFVRCxJQUFYLEVBQVgsQ0FBOUMsQ0FBUDtBQUNEOztBQUVERSxhQUFXTixLQUFYLEVBQWtCQyxNQUFsQixFQUEwQjtBQUN4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VyxHQUFBQSxXO2tCQStGRUEsVyIsImZpbGUiOiJIb29rc1JvdXRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlIH0gICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciAgIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tIFwiLi4vbWlkZGxld2FyZXNcIjtcblxuZXhwb3J0IGNsYXNzIEhvb2tzUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIGNyZWF0ZUhvb2soYUhvb2ssIGNvbmZpZykge1xuICAgIHJldHVybiBjb25maWcuaG9va3NDb250cm9sbGVyLmNyZWF0ZUhvb2soYUhvb2spLnRoZW4oKGhvb2spID0+ICh7cmVzcG9uc2U6IGhvb2t9KSk7XG4gIH1cblxuICB1cGRhdGVIb29rKGFIb29rLCBjb25maWcpIHtcbiAgICByZXR1cm4gIGNvbmZpZy5ob29rc0NvbnRyb2xsZXIudXBkYXRlSG9vayhhSG9vaykudGhlbigoaG9vaykgPT4gKHtyZXNwb25zZTogaG9va30pKTtcbiAgfVxuXG4gIGhhbmRsZVBvc3QocmVxKSB7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlSG9vayhyZXEuYm9keSwgcmVxLmNvbmZpZyk7XG4gIH1cblxuICBoYW5kbGVHZXRGdW5jdGlvbnMocmVxKSB7XG4gICAgdmFyIGhvb2tzQ29udHJvbGxlciA9IHJlcS5jb25maWcuaG9va3NDb250cm9sbGVyO1xuICAgIGlmIChyZXEucGFyYW1zLmZ1bmN0aW9uTmFtZSkge1xuICAgICAgcmV0dXJuIGhvb2tzQ29udHJvbGxlci5nZXRGdW5jdGlvbihyZXEucGFyYW1zLmZ1bmN0aW9uTmFtZSkudGhlbigoZm91bmRGdW5jdGlvbikgPT4ge1xuICAgICAgICBpZiAoIWZvdW5kRnVuY3Rpb24pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTQzLCBgbm8gZnVuY3Rpb24gbmFtZWQ6ICR7cmVxLnBhcmFtcy5mdW5jdGlvbk5hbWV9IGlzIGRlZmluZWRgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtyZXNwb25zZTogZm91bmRGdW5jdGlvbn0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhvb2tzQ29udHJvbGxlci5nZXRGdW5jdGlvbnMoKS50aGVuKChmdW5jdGlvbnMpID0+IHtcbiAgICAgIHJldHVybiB7IHJlc3BvbnNlOiBmdW5jdGlvbnMgfHwgW10gfTtcbiAgICB9LCAoZXJyKSA9PiB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSk7XG4gIH1cblxuICBoYW5kbGVHZXRUcmlnZ2VycyhyZXEpIHtcbiAgICB2YXIgaG9va3NDb250cm9sbGVyID0gcmVxLmNvbmZpZy5ob29rc0NvbnRyb2xsZXI7XG4gICAgaWYgKHJlcS5wYXJhbXMuY2xhc3NOYW1lICYmIHJlcS5wYXJhbXMudHJpZ2dlck5hbWUpIHtcblxuICAgICAgcmV0dXJuIGhvb2tzQ29udHJvbGxlci5nZXRUcmlnZ2VyKHJlcS5wYXJhbXMuY2xhc3NOYW1lLCByZXEucGFyYW1zLnRyaWdnZXJOYW1lKS50aGVuKChmb3VuZFRyaWdnZXIpID0+IHtcbiAgICAgICAgaWYgKCFmb3VuZFRyaWdnZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTQzLGBjbGFzcyAke3JlcS5wYXJhbXMuY2xhc3NOYW1lfSBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe3Jlc3BvbnNlOiBmb3VuZFRyaWdnZXJ9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBob29rc0NvbnRyb2xsZXIuZ2V0VHJpZ2dlcnMoKS50aGVuKCh0cmlnZ2VycykgPT4gKHsgcmVzcG9uc2U6IHRyaWdnZXJzIHx8IFtdIH0pKTtcbiAgfVxuXG4gIGhhbmRsZURlbGV0ZShyZXEpIHtcbiAgICB2YXIgaG9va3NDb250cm9sbGVyID0gcmVxLmNvbmZpZy5ob29rc0NvbnRyb2xsZXI7XG4gICAgaWYgKHJlcS5wYXJhbXMuZnVuY3Rpb25OYW1lKSB7XG4gICAgICByZXR1cm4gaG9va3NDb250cm9sbGVyLmRlbGV0ZUZ1bmN0aW9uKHJlcS5wYXJhbXMuZnVuY3Rpb25OYW1lKS50aGVuKCgpID0+ICh7cmVzcG9uc2U6IHt9fSkpXG5cbiAgICB9IGVsc2UgaWYgKHJlcS5wYXJhbXMuY2xhc3NOYW1lICYmIHJlcS5wYXJhbXMudHJpZ2dlck5hbWUpIHtcbiAgICAgIHJldHVybiBob29rc0NvbnRyb2xsZXIuZGVsZXRlVHJpZ2dlcihyZXEucGFyYW1zLmNsYXNzTmFtZSwgcmVxLnBhcmFtcy50cmlnZ2VyTmFtZSkudGhlbigoKSA9PiAoe3Jlc3BvbnNlOiB7fX0pKVxuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtyZXNwb25zZToge319KTtcbiAgfVxuXG4gIGhhbmRsZVVwZGF0ZShyZXEpIHtcbiAgICB2YXIgaG9vaztcbiAgICBpZiAocmVxLnBhcmFtcy5mdW5jdGlvbk5hbWUgJiYgcmVxLmJvZHkudXJsKSB7XG4gICAgICBob29rID0ge31cbiAgICAgIGhvb2suZnVuY3Rpb25OYW1lID0gcmVxLnBhcmFtcy5mdW5jdGlvbk5hbWU7XG4gICAgICBob29rLnVybCA9IHJlcS5ib2R5LnVybDtcbiAgICB9IGVsc2UgaWYgKHJlcS5wYXJhbXMuY2xhc3NOYW1lICYmIHJlcS5wYXJhbXMudHJpZ2dlck5hbWUgJiYgcmVxLmJvZHkudXJsKSB7XG4gICAgICBob29rID0ge31cbiAgICAgIGhvb2suY2xhc3NOYW1lID0gcmVxLnBhcmFtcy5jbGFzc05hbWU7XG4gICAgICBob29rLnRyaWdnZXJOYW1lID0gcmVxLnBhcmFtcy50cmlnZ2VyTmFtZTtcbiAgICAgIGhvb2sudXJsID0gcmVxLmJvZHkudXJsXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcigxNDMsIFwiaW52YWxpZCBob29rIGRlY2xhcmF0aW9uXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy51cGRhdGVIb29rKGhvb2ssIHJlcS5jb25maWcpO1xuICB9XG5cbiAgaGFuZGxlUHV0KHJlcSkge1xuICAgIHZhciBib2R5ID0gcmVxLmJvZHk7XG4gICAgaWYgKGJvZHkuX19vcCA9PSBcIkRlbGV0ZVwiKSB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlVXBkYXRlKHJlcSk7XG4gICAgfVxuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgICcvaG9va3MvZnVuY3Rpb25zJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgdGhpcy5oYW5kbGVHZXRGdW5jdGlvbnMuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgICcvaG9va3MvdHJpZ2dlcnMnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCB0aGlzLmhhbmRsZUdldFRyaWdnZXJzLmJpbmQodGhpcykpO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICAnL2hvb2tzL2Z1bmN0aW9ucy86ZnVuY3Rpb25OYW1lJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgdGhpcy5oYW5kbGVHZXRGdW5jdGlvbnMuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgICcvaG9va3MvdHJpZ2dlcnMvOmNsYXNzTmFtZS86dHJpZ2dlck5hbWUnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCB0aGlzLmhhbmRsZUdldFRyaWdnZXJzLmJpbmQodGhpcykpO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2hvb2tzL2Z1bmN0aW9ucycsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIHRoaXMuaGFuZGxlUG9zdC5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy9ob29rcy90cmlnZ2VycycsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIHRoaXMuaGFuZGxlUG9zdC5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCAgJy9ob29rcy9mdW5jdGlvbnMvOmZ1bmN0aW9uTmFtZScsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIHRoaXMuaGFuZGxlUHV0LmJpbmQodGhpcykpO1xuICAgIHRoaXMucm91dGUoJ1BVVCcsICAnL2hvb2tzL3RyaWdnZXJzLzpjbGFzc05hbWUvOnRyaWdnZXJOYW1lJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgdGhpcy5oYW5kbGVQdXQuYmluZCh0aGlzKSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSG9va3NSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/IAPValidationRouter.js b/lib/Routers/IAPValidationRouter.js index 0d03e91f41..93948f5c63 100644 --- a/lib/Routers/IAPValidationRouter.js +++ b/lib/Routers/IAPValidationRouter.js @@ -122,4 +122,5 @@ class IAPValidationRouter extends _PromiseRouter2.default { this.route("POST", "/validate_purchase", this.handleRequest); } } -exports.IAPValidationRouter = IAPValidationRouter; \ No newline at end of file +exports.IAPValidationRouter = IAPValidationRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0lBUFZhbGlkYXRpb25Sb3V0ZXIuanMiXSwibmFtZXMiOlsicmVxdWVzdCIsInJlcXVpcmUiLCJyZXN0IiwiSUFQX1NBTkRCT1hfVVJMIiwiSUFQX1BST0RVQ1RJT05fVVJMIiwiQVBQX1NUT1JFX0VSUk9SUyIsImFwcFN0b3JlRXJyb3IiLCJzdGF0dXMiLCJwYXJzZUludCIsImVycm9yU3RyaW5nIiwiZXJyb3IiLCJ2YWxpZGF0ZVdpdGhBcHBTdG9yZSIsInVybCIsInJlY2VpcHQiLCJQcm9taXNlIiwiZnVsZmlsbCIsInJlamVjdCIsInBvc3QiLCJib2R5IiwianNvbiIsImVyciIsInJlcyIsImdldEZpbGVGb3JQcm9kdWN0SWRlbnRpZmllciIsInByb2R1Y3RJZGVudGlmaWVyIiwicmVxIiwiZmluZCIsImNvbmZpZyIsImF1dGgiLCJ1bmRlZmluZWQiLCJpbmZvIiwiY2xpZW50U0RLIiwidGhlbiIsInJlc3VsdCIsInByb2R1Y3RzIiwicmVzdWx0cyIsImxlbmd0aCIsIlBhcnNlIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiZG93bmxvYWQiLCJyZXNvbHZlIiwicmVzcG9uc2UiLCJJQVBWYWxpZGF0aW9uUm91dGVyIiwiUHJvbWlzZVJvdXRlciIsImhhbmRsZVJlcXVlc3QiLCJJTlZBTElEX0pTT04iLCJiYXNlNjQiLCJwcm9jZXNzIiwiZW52IiwiVEVTVElORyIsImJ5cGFzc0FwcFN0b3JlVmFsaWRhdGlvbiIsInN1Y2Nlc3NDYWxsYmFjayIsImVycm9yQ2FsbGJhY2siLCJtb3VudFJvdXRlcyIsInJvdXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFHQTs7Ozs7O0FBRkEsSUFBSUEsVUFBVUMsUUFBUSxTQUFSLENBQWQ7QUFDQSxJQUFJQyxPQUFPRCxRQUFRLFNBQVIsQ0FBWDs7O0FBR0E7QUFDQSxNQUFNRSxrQkFBa0IsZ0RBQXhCO0FBQ0EsTUFBTUMscUJBQXFCLDRDQUEzQjs7QUFFQSxNQUFNQyxtQkFBbUI7QUFDdkIsU0FBTyw0REFEZ0I7QUFFdkIsU0FBTyxpRUFGZ0I7QUFHdkIsU0FBTyx5Q0FIZ0I7QUFJdkIsU0FBTywyRkFKZ0I7QUFLdkIsU0FBTyxnREFMZ0I7QUFNdkIsU0FBTyx5REFOZ0I7QUFPdkIsU0FBTyxxSkFQZ0I7QUFRdkIsU0FBTztBQVJnQixDQUF6Qjs7QUFXQSxTQUFTQyxhQUFULENBQXVCQyxNQUF2QixFQUErQjtBQUM3QkEsV0FBU0MsU0FBU0QsTUFBVCxDQUFUO0FBQ0EsTUFBSUUsY0FBY0osaUJBQWlCRSxNQUFqQixLQUE0QixnQkFBOUM7QUFDQSxTQUFPLEVBQUVBLFFBQVFBLE1BQVYsRUFBa0JHLE9BQU9ELFdBQXpCLEVBQVA7QUFDRDs7QUFFRCxTQUFTRSxvQkFBVCxDQUE4QkMsR0FBOUIsRUFBbUNDLE9BQW5DLEVBQTRDO0FBQzFDLFNBQU8sSUFBSUMsT0FBSixDQUFZLFVBQVNDLE9BQVQsRUFBa0JDLE1BQWxCLEVBQTBCO0FBQzNDaEIsWUFBUWlCLElBQVIsQ0FBYTtBQUNYTCxXQUFLQSxHQURNO0FBRVhNLFlBQU0sRUFBRSxnQkFBZ0JMLE9BQWxCLEVBRks7QUFHWE0sWUFBTTtBQUhLLEtBQWIsRUFJRyxVQUFTQyxHQUFULEVBQWNDLEdBQWQsRUFBbUJILElBQW5CLEVBQXlCO0FBQzFCLFVBQUlYLFNBQVNXLEtBQUtYLE1BQWxCO0FBQ0EsVUFBSUEsVUFBVSxDQUFkLEVBQWlCO0FBQ2Y7QUFDQSxlQUFPUSxTQUFQO0FBQ0Q7QUFDRDtBQUNBLGFBQU9DLE9BQU9FLElBQVAsQ0FBUDtBQUNELEtBWkQ7QUFhRCxHQWRNLENBQVA7QUFlRDs7QUFFRCxTQUFTSSwyQkFBVCxDQUFxQ0MsaUJBQXJDLEVBQXdEQyxHQUF4RCxFQUE2RDtBQUMzRCxTQUFPdEIsS0FBS3VCLElBQUwsQ0FBVUQsSUFBSUUsTUFBZCxFQUFzQkYsSUFBSUcsSUFBMUIsRUFBZ0MsVUFBaEMsRUFBNEMsRUFBRUosbUJBQW1CQSxpQkFBckIsRUFBNUMsRUFBc0ZLLFNBQXRGLEVBQWlHSixJQUFJSyxJQUFKLENBQVNDLFNBQTFHLEVBQXFIQyxJQUFySCxDQUEwSCxVQUFTQyxNQUFULEVBQWdCO0FBQy9JLFVBQU1DLFdBQVdELE9BQU9FLE9BQXhCO0FBQ0EsUUFBSSxDQUFDRCxRQUFELElBQWFBLFNBQVNFLE1BQVQsSUFBbUIsQ0FBcEMsRUFBdUM7QUFDckM7QUFDQSxZQUFNLElBQUlDLGVBQU1DLEtBQVYsQ0FBZ0JELGVBQU1DLEtBQU4sQ0FBWUMsZ0JBQTVCLEVBQThDLG1CQUE5QyxDQUFOO0FBQ0Q7O0FBRUQsUUFBSUMsV0FBV04sU0FBUyxDQUFULEVBQVlNLFFBQTNCO0FBQ0EsV0FBT3pCLFFBQVEwQixPQUFSLENBQWdCLEVBQUNDLFVBQVVGLFFBQVgsRUFBaEIsQ0FBUDtBQUNELEdBVE0sQ0FBUDtBQVVEOztBQUdNLE1BQU1HLG1CQUFOLFNBQWtDQyx1QkFBbEMsQ0FBZ0Q7O0FBRXJEQyxnQkFBY3BCLEdBQWQsRUFBbUI7QUFDakIsUUFBSVgsVUFBVVcsSUFBSU4sSUFBSixDQUFTTCxPQUF2QjtBQUNBLFVBQU1VLG9CQUFvQkMsSUFBSU4sSUFBSixDQUFTSyxpQkFBbkM7O0FBRUEsUUFBSSxDQUFDVixPQUFELElBQVksQ0FBRVUsaUJBQWxCLEVBQXFDO0FBQ25DO0FBQ0EsWUFBTSxJQUFJYSxlQUFNQyxLQUFWLENBQWdCRCxlQUFNQyxLQUFOLENBQVlRLFlBQTVCLEVBQTBDLHNDQUExQyxDQUFOO0FBQ0Q7O0FBRUQ7QUFDQTtBQUNBLFFBQUksT0FBT2hDLE9BQVAsSUFBa0IsUUFBdEIsRUFBZ0M7QUFDOUIsVUFBSUEsUUFBUSxRQUFSLEtBQXFCLE9BQXpCLEVBQWtDO0FBQ2hDQSxrQkFBVUEsUUFBUWlDLE1BQWxCO0FBQ0Q7QUFDRjs7QUFFRCxRQUFJQyxRQUFRQyxHQUFSLENBQVlDLE9BQVosSUFBdUIsR0FBdkIsSUFBOEJ6QixJQUFJTixJQUFKLENBQVNnQyx3QkFBM0MsRUFBcUU7QUFDbkUsYUFBTzVCLDRCQUE0QkMsaUJBQTVCLEVBQStDQyxHQUEvQyxDQUFQO0FBQ0Q7O0FBRUQsYUFBUzJCLGVBQVQsR0FBMkI7QUFDekIsYUFBTzdCLDRCQUE0QkMsaUJBQTVCLEVBQStDQyxHQUEvQyxDQUFQO0FBQ0Q7O0FBRUQsYUFBUzRCLGFBQVQsQ0FBdUIxQyxLQUF2QixFQUE4QjtBQUM1QixhQUFPSSxRQUFRMEIsT0FBUixDQUFnQixFQUFDQyxVQUFVbkMsY0FBY0ksTUFBTUgsTUFBcEIsQ0FBWCxFQUFoQixDQUFQO0FBQ0Q7O0FBRUQsV0FBT0kscUJBQXFCUCxrQkFBckIsRUFBeUNTLE9BQXpDLEVBQWtEa0IsSUFBbEQsQ0FBdUQsTUFBTTs7QUFFbEUsYUFBT29CLGlCQUFQO0FBRUQsS0FKTSxFQUlIekMsS0FBRCxJQUFXO0FBQ1osVUFBSUEsTUFBTUgsTUFBTixJQUFnQixLQUFwQixFQUEyQjtBQUN6QixlQUFPSSxxQkFBcUJSLGVBQXJCLEVBQXNDVSxPQUF0QyxFQUErQ2tCLElBQS9DLENBQW9ELE1BQU07QUFDL0QsaUJBQU9vQixpQkFBUDtBQUNELFNBRk0sRUFFSHpDLEtBQUQsSUFBVztBQUNaLGlCQUFPMEMsY0FBYzFDLEtBQWQsQ0FBUDtBQUNELFNBSk0sQ0FBUDtBQU1EOztBQUVELGFBQU8wQyxjQUFjMUMsS0FBZCxDQUFQO0FBQ0QsS0FmTSxDQUFQO0FBZ0JEOztBQUVEMkMsZ0JBQWM7QUFDWixTQUFLQyxLQUFMLENBQVcsTUFBWCxFQUFrQixvQkFBbEIsRUFBd0MsS0FBS1YsYUFBN0M7QUFDRDtBQW5Eb0Q7UUFBMUNGLG1CLEdBQUFBLG1CIiwiZmlsZSI6IklBUFZhbGlkYXRpb25Sb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbnZhciByZXF1ZXN0ID0gcmVxdWlyZShcInJlcXVlc3RcIik7XG52YXIgcmVzdCA9IHJlcXVpcmUoXCIuLi9yZXN0XCIpO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuXG4vLyBUT0RPIG1vdmUgdmFsaWRhdGlvbiBsb2dpYyBpbiBJQVBWYWxpZGF0aW9uQ29udHJvbGxlclxuY29uc3QgSUFQX1NBTkRCT1hfVVJMID0gXCJodHRwczovL3NhbmRib3guaXR1bmVzLmFwcGxlLmNvbS92ZXJpZnlSZWNlaXB0XCI7XG5jb25zdCBJQVBfUFJPRFVDVElPTl9VUkwgPSBcImh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vdmVyaWZ5UmVjZWlwdFwiO1xuXG5jb25zdCBBUFBfU1RPUkVfRVJST1JTID0ge1xuICAyMTAwMDogXCJUaGUgQXBwIFN0b3JlIGNvdWxkIG5vdCByZWFkIHRoZSBKU09OIG9iamVjdCB5b3UgcHJvdmlkZWQuXCIsXG4gIDIxMDAyOiBcIlRoZSBkYXRhIGluIHRoZSByZWNlaXB0LWRhdGEgcHJvcGVydHkgd2FzIG1hbGZvcm1lZCBvciBtaXNzaW5nLlwiLFxuICAyMTAwMzogXCJUaGUgcmVjZWlwdCBjb3VsZCBub3QgYmUgYXV0aGVudGljYXRlZC5cIixcbiAgMjEwMDQ6IFwiVGhlIHNoYXJlZCBzZWNyZXQgeW91IHByb3ZpZGVkIGRvZXMgbm90IG1hdGNoIHRoZSBzaGFyZWQgc2VjcmV0IG9uIGZpbGUgZm9yIHlvdXIgYWNjb3VudC5cIixcbiAgMjEwMDU6IFwiVGhlIHJlY2VpcHQgc2VydmVyIGlzIG5vdCBjdXJyZW50bHkgYXZhaWxhYmxlLlwiLFxuICAyMTAwNjogXCJUaGlzIHJlY2VpcHQgaXMgdmFsaWQgYnV0IHRoZSBzdWJzY3JpcHRpb24gaGFzIGV4cGlyZWQuXCIsXG4gIDIxMDA3OiBcIlRoaXMgcmVjZWlwdCBpcyBmcm9tIHRoZSB0ZXN0IGVudmlyb25tZW50LCBidXQgaXQgd2FzIHNlbnQgdG8gdGhlIHByb2R1Y3Rpb24gZW52aXJvbm1lbnQgZm9yIHZlcmlmaWNhdGlvbi4gU2VuZCBpdCB0byB0aGUgdGVzdCBlbnZpcm9ubWVudCBpbnN0ZWFkLlwiLFxuICAyMTAwODogXCJUaGlzIHJlY2VpcHQgaXMgZnJvbSB0aGUgcHJvZHVjdGlvbiBlbnZpcm9ubWVudCwgYnV0IGl0IHdhcyBzZW50IHRvIHRoZSB0ZXN0IGVudmlyb25tZW50IGZvciB2ZXJpZmljYXRpb24uIFNlbmQgaXQgdG8gdGhlIHByb2R1Y3Rpb24gZW52aXJvbm1lbnQgaW5zdGVhZC5cIlxufVxuXG5mdW5jdGlvbiBhcHBTdG9yZUVycm9yKHN0YXR1cykge1xuICBzdGF0dXMgPSBwYXJzZUludChzdGF0dXMpO1xuICB2YXIgZXJyb3JTdHJpbmcgPSBBUFBfU1RPUkVfRVJST1JTW3N0YXR1c10gfHwgXCJ1bmtub3duIGVycm9yLlwiO1xuICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cywgZXJyb3I6IGVycm9yU3RyaW5nIH1cbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVXaXRoQXBwU3RvcmUodXJsLCByZWNlaXB0KSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihmdWxmaWxsLCByZWplY3QpIHtcbiAgICByZXF1ZXN0LnBvc3Qoe1xuICAgICAgdXJsOiB1cmwsXG4gICAgICBib2R5OiB7IFwicmVjZWlwdC1kYXRhXCI6IHJlY2VpcHQgfSxcbiAgICAgIGpzb246IHRydWUsXG4gICAgfSwgZnVuY3Rpb24oZXJyLCByZXMsIGJvZHkpIHtcbiAgICAgIHZhciBzdGF0dXMgPSBib2R5LnN0YXR1cztcbiAgICAgIGlmIChzdGF0dXMgPT0gMCkge1xuICAgICAgICAvLyBObyBuZWVkIHRvIHBhc3MgYW55dGhpbmcsIHN0YXR1cyBpcyBPS1xuICAgICAgICByZXR1cm4gZnVsZmlsbCgpO1xuICAgICAgfVxuICAgICAgLy8gcmVjZWlwdCBpcyBmcm9tIHRlc3QgYW5kIHNob3VsZCBnbyB0byB0ZXN0XG4gICAgICByZXR1cm4gcmVqZWN0KGJvZHkpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0RmlsZUZvclByb2R1Y3RJZGVudGlmaWVyKHByb2R1Y3RJZGVudGlmaWVyLCByZXEpIHtcbiAgcmV0dXJuIHJlc3QuZmluZChyZXEuY29uZmlnLCByZXEuYXV0aCwgJ19Qcm9kdWN0JywgeyBwcm9kdWN0SWRlbnRpZmllcjogcHJvZHVjdElkZW50aWZpZXIgfSwgdW5kZWZpbmVkLCByZXEuaW5mby5jbGllbnRTREspLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXtcbiAgICBjb25zdCBwcm9kdWN0cyA9IHJlc3VsdC5yZXN1bHRzO1xuICAgIGlmICghcHJvZHVjdHMgfHwgcHJvZHVjdHMubGVuZ3RoICE9IDEpIHtcbiAgICAgIC8vIEVycm9yIG5vdCBmb3VuZCBvciB0b28gbWFueVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdPYmplY3Qgbm90IGZvdW5kLicpXG4gICAgfVxuXG4gICAgdmFyIGRvd25sb2FkID0gcHJvZHVjdHNbMF0uZG93bmxvYWQ7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7cmVzcG9uc2U6IGRvd25sb2FkfSk7XG4gIH0pO1xufVxuXG5cbmV4cG9ydCBjbGFzcyBJQVBWYWxpZGF0aW9uUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG5cbiAgaGFuZGxlUmVxdWVzdChyZXEpIHtcbiAgICBsZXQgcmVjZWlwdCA9IHJlcS5ib2R5LnJlY2VpcHQ7XG4gICAgY29uc3QgcHJvZHVjdElkZW50aWZpZXIgPSByZXEuYm9keS5wcm9kdWN0SWRlbnRpZmllcjtcblxuICAgIGlmICghcmVjZWlwdCB8fCAhIHByb2R1Y3RJZGVudGlmaWVyKSB7XG4gICAgICAvLyBUT0RPOiBFcnJvciwgbWFsZm9ybWVkIHJlcXVlc3RcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sIFwibWlzc2luZyByZWNlaXB0IG9yIHByb2R1Y3RJZGVudGlmaWVyXCIpO1xuICAgIH1cblxuICAgIC8vIFRyYW5zZm9ybSB0aGUgb2JqZWN0IGlmIHRoZXJlXG4gICAgLy8gb3RoZXJ3aXNlIGFzc3VtZSBpdCdzIGluIEJhc2U2NCBhbHJlYWR5XG4gICAgaWYgKHR5cGVvZiByZWNlaXB0ID09IFwib2JqZWN0XCIpIHtcbiAgICAgIGlmIChyZWNlaXB0W1wiX190eXBlXCJdID09IFwiQnl0ZXNcIikge1xuICAgICAgICByZWNlaXB0ID0gcmVjZWlwdC5iYXNlNjQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHByb2Nlc3MuZW52LlRFU1RJTkcgPT0gXCIxXCIgJiYgcmVxLmJvZHkuYnlwYXNzQXBwU3RvcmVWYWxpZGF0aW9uKSB7XG4gICAgICByZXR1cm4gZ2V0RmlsZUZvclByb2R1Y3RJZGVudGlmaWVyKHByb2R1Y3RJZGVudGlmaWVyLCByZXEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN1Y2Nlc3NDYWxsYmFjaygpIHtcbiAgICAgIHJldHVybiBnZXRGaWxlRm9yUHJvZHVjdElkZW50aWZpZXIocHJvZHVjdElkZW50aWZpZXIsIHJlcSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXJyb3JDYWxsYmFjayhlcnJvcikge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7cmVzcG9uc2U6IGFwcFN0b3JlRXJyb3IoZXJyb3Iuc3RhdHVzKSB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsaWRhdGVXaXRoQXBwU3RvcmUoSUFQX1BST0RVQ1RJT05fVVJMLCByZWNlaXB0KS50aGVuKCgpID0+IHtcblxuICAgICAgcmV0dXJuIHN1Y2Nlc3NDYWxsYmFjaygpO1xuXG4gICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICBpZiAoZXJyb3Iuc3RhdHVzID09IDIxMDA3KSB7XG4gICAgICAgIHJldHVybiB2YWxpZGF0ZVdpdGhBcHBTdG9yZShJQVBfU0FOREJPWF9VUkwsIHJlY2VpcHQpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiBzdWNjZXNzQ2FsbGJhY2soKTtcbiAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGVycm9yQ2FsbGJhY2soZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICB9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoXCJQT1NUXCIsXCIvdmFsaWRhdGVfcHVyY2hhc2VcIiwgdGhpcy5oYW5kbGVSZXF1ZXN0KTtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/lib/Routers/ImportRouter.js b/lib/Routers/ImportRouter.js index 726bda099b..2c16dbc5e2 100644 --- a/lib/Routers/ImportRouter.js +++ b/lib/Routers/ImportRouter.js @@ -205,4 +205,5 @@ class ImportRouter { } exports.ImportRouter = ImportRouter; -exports.default = ImportRouter; \ No newline at end of file +exports.default = ImportRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ltcG9ydFJvdXRlci5qcyJdLCJuYW1lcyI6WyJtaWRkbGV3YXJlcyIsIkltcG9ydFJvdXRlciIsImdldE9uZVNjaGVtYSIsInJlcSIsImNsYXNzTmFtZSIsInBhcmFtcyIsImNvbmZpZyIsImRhdGFiYXNlIiwibG9hZFNjaGVtYSIsImNsZWFyQ2FjaGUiLCJ0aGVuIiwic2NoZW1hQ29udHJvbGxlciIsImNhdGNoIiwiZXJyb3IiLCJ1bmRlZmluZWQiLCJQcm9taXNlIiwicmVqZWN0IiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfQ0xBU1NfTkFNRSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImltcG9ydFJlc3RPYmplY3QiLCJyZXN0T2JqZWN0IiwidGFyZ2V0Q2xhc3MiLCJyZXN0IiwidXBkYXRlIiwiYXV0aCIsIm9iamVjdElkIiwib3duaW5nSWQiLCJyZWxhdGlvbk5hbWUiLCJyZWxhdGVkSWQiLCJpbmZvIiwiY2xpZW50U0RLIiwiY29kZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJjcmVhdGVkQXQiLCJ1cGRhdGVkQXQiLCJjcmVhdGUiLCJhbGxvd09iamVjdElkIiwiZ2V0UmVzdE9iamVjdHMiLCJyZXNvbHZlIiwicmVzdE9iamVjdHMiLCJpbXBvcnRGaWxlIiwiSlNPTiIsInBhcnNlIiwiZmlsZSIsImJ1ZmZlciIsInRvU3RyaW5nIiwiZSIsIkFycmF5IiwiaXNBcnJheSIsInJlc3VsdHMiLCJyb3dzIiwiYm9keSIsImZlZWRiYWNrRW1haWwiLCJlbWFpbEFkYXB0ZXIiLCJoYW5kbGVJbXBvcnQiLCJlbWFpbENvbnRyb2xsZXJBZGFwdGVyIiwicHJvbWlzZSIsInJlc3BvbnNlIiwiZmllbGRzIiwiaGFzT3duUHJvcGVydHkiLCJ0eXBlIiwiYWxsIiwicmVkdWNlIiwiaXRlbSIsIm9iamVjdCIsImluZGV4IiwicGFnZUFycmF5IiwicHVzaCIsImJpbmQiLCJsZW5ndGgiLCJzbGljZSIsIm1haW5Qcm9taXNlIiwiY29uY2F0IiwibWFwIiwiZnVuYyIsInNlbmRNYWlsIiwidGV4dCIsInRvIiwic3ViamVjdCIsIndyYXBQcm9taXNlUmVxdWVzdCIsInJlcyIsImhhbmRsZXIiLCJkYXRhIiwianNvbiIsImVyciIsInN0YXR1cyIsInNlbmQiLCJtZXNzYWdlIiwiZXhwcmVzc1JvdXRlciIsInJvdXRlciIsImV4cHJlc3MiLCJSb3V0ZXIiLCJ1cGxvYWQiLCJwb3N0Iiwic2luZ2xlIiwiYWxsb3dDcm9zc0RvbWFpbiIsImhhbmRsZVBhcnNlSGVhZGVycyIsImVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOztBQUNBOztJQUFZQSxXOztBQUNaOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBRU8sTUFBTUMsWUFBTixDQUFtQjs7QUFFeEJDLGVBQWFDLEdBQWIsRUFBa0I7O0FBRWhCLFVBQU1DLFlBQVlELElBQUlFLE1BQUosQ0FBV0QsU0FBN0I7O0FBRUEsV0FBT0QsSUFBSUcsTUFBSixDQUFXQyxRQUFYLENBQW9CQyxVQUFwQixDQUErQixFQUFDQyxZQUFZLElBQWIsRUFBL0IsRUFDSkMsSUFESSxDQUNDQyxvQkFBb0JBLGlCQUFpQlQsWUFBakIsQ0FBOEJFLFNBQTlCLENBRHJCLEVBRUpRLEtBRkksQ0FFRUMsU0FBUztBQUNkLFVBQUlBLFVBQVVDLFNBQWQsRUFBeUI7QUFDdkIsZUFBT0MsUUFBUUMsTUFBUixDQUFlLElBQUlDLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ25CLFNBQVFmLFNBQVUsa0JBREMsQ0FBZixDQUFQO0FBRUQsT0FIRCxNQUdPO0FBQ0wsZUFBT1csUUFBUUMsTUFBUixDQUFlLElBQUlDLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUUscUJBQTVCLEVBQ3BCLHlCQURvQixDQUFmLENBQVA7QUFFRDtBQUNGLEtBVkksQ0FBUDtBQVdEOztBQUVEQyxtQkFBaUJsQixHQUFqQixFQUFzQm1CLFVBQXRCLEVB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QUdFakcsWUFBWWtHLGtCQUhkLEVBSUVsRyxZQUFZbUcsc0JBSmQsRUFLRSxDQUFDaEcsR0FBRCxFQUFNK0UsR0FBTixLQUFjLEtBQUtELGtCQUFMLENBQXdCOUUsR0FBeEIsRUFBNkIrRSxHQUE3QixFQUFrQyxLQUFLMUIsWUFBTCxDQUFrQmMsSUFBbEIsQ0FBdUIsSUFBdkIsQ0FBbEMsQ0FMaEI7O0FBUUEsV0FBT3FCLE1BQVA7QUFDRDtBQWhOdUI7O1FBQWIxRixZLEdBQUFBLFk7a0JBbU5FQSxZIiwiZmlsZSI6IkltcG9ydFJvdXRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBleHByZXNzICAgICAgICAgIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgbG9hZEFkYXB0ZXIgfSBmcm9tICcuLi9BZGFwdGVycy9BZGFwdGVyTG9hZGVyJztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmVzIGZyb20gJy4uL21pZGRsZXdhcmVzJztcbmltcG9ydCBtdWx0ZXIgICAgICAgICAgIGZyb20gJ211bHRlcic7XG5pbXBvcnQgcmVzdCAgICAgICAgICAgICBmcm9tICcuLi9yZXN0JztcbmltcG9ydCB7IFBhcnNlIH0gICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuXG5leHBvcnQgY2xhc3MgSW1wb3J0Um91dGVyIHtcblxuICBnZXRPbmVTY2hlbWEocmVxKSB7XG5cbiAgICBjb25zdCBjbGFzc05hbWUgPSByZXEucGFyYW1zLmNsYXNzTmFtZTtcblxuICAgIHJldHVybiByZXEuY29uZmlnLmRhdGFiYXNlLmxvYWRTY2hlbWEoe2NsZWFyQ2FjaGU6IHRydWV9KVxuICAgICAgLnRoZW4oc2NoZW1hQ29udHJvbGxlciA9PiBzY2hlbWFDb250cm9sbGVyLmdldE9uZVNjaGVtYShjbGFzc05hbWUpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSxcbiAgICAgICAgICAgIGBDbGFzcyAke2NsYXNzTmFtZX0gZG9lcyBub3QgZXhpc3QuYCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgICAgICAgJ0RhdGFiYXNlIGFkYXB0ZXIgZXJyb3IuJykpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIGltcG9ydFJlc3RPYmplY3QocmVxLCByZXN0T2JqZWN0LCB0YXJnZXRDbGFzcykge1xuICAgIGlmICh0YXJnZXRDbGFzcykge1xuICAgICAgcmV0dXJuIHJlc3QudXBkYXRlKHJlcS5jb25maWcsIHJlcS5hdXRoLCByZXEucGFyYW1zLmNsYXNzTmFtZSwge29iamVjdElkOiByZXN0T2JqZWN0Lm93bmluZ0lkfSwge1xuICAgICAgICBbcmVxLnBhcmFtcy5yZWxhdGlvbk5hbWVdOiB7XG4gICAgICAgICAgXCJfX29wXCI6IFwiQWRkUmVsYXRpb25cIixcbiAgICAgICAgICBcIm9iamVjdHNcIjogW3tcIl9fdHlwZVwiOiBcIlBvaW50ZXJcIiwgXCJjbGFzc05hbWVcIjogdGFyZ2V0Q2xhc3MsIFwib2JqZWN0SWRcIjogcmVzdE9iamVjdC5yZWxhdGVkSWR9XVxuICAgICAgICB9XG4gICAgICB9LCByZXEuaW5mby5jbGllbnRTREspXG4gICAgICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnT2JqZWN0IG5vdCBmb3VuZCcpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChyZXN0T2JqZWN0LmNyZWF0ZWRBdCkge1xuICAgICAgZGVsZXRlIHJlc3RPYmplY3QuY3JlYXRlZEF0O1xuICAgIH1cblxuICAgIGlmIChyZXN0T2JqZWN0LnVwZGF0ZWRBdCkge1xuICAgICAgZGVsZXRlIHJlc3RPYmplY3QudXBkYXRlZEF0O1xuICAgIH1cblxuICAgIGlmIChyZXN0T2JqZWN0Lm9iamVjdElkKSB7XG4gICAgICByZXR1cm4gcmVzdFxuICAgICAgICAudXBkYXRlKHJlcS5jb25maWcsIHJlcS5hdXRoLCByZXEucGFyYW1zLmNsYXNzTmFtZSwge29iamVjdElkOiByZXN0T2JqZWN0Lm9iamVjdElkfSwgcmVzdE9iamVjdCwgcmVxLmluZm8uY2xpZW50U0RLKVxuICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN0LmNyZWF0ZShcbiAgICAgICAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgICAgICAgcmVxLmF1dGgsXG4gICAgICAgICAgICAgIHJlcS5wYXJhbXMuY2xhc3NOYW1lLFxuICAgICAgICAgICAgICByZXN0T2JqZWN0LFxuICAgICAgICAgICAgICByZXEuaW5mby5jbGllbnRTREssXG4gICAgICAgICAgICAgIHthbGxvd09iamVjdElkOiB0cnVlfVxuICAgICAgICAgICAgKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3QuY3JlYXRlKHJlcS5jb25maWcsIHJlcS5hdXRoLCByZXEucGFyYW1zLmNsYXNzTmFtZSwgcmVzdE9iamVjdCk7XG4gIH1cblxuICBnZXRSZXN0T2JqZWN0cyhyZXEpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcblxuICAgICAgbGV0IHJlc3RPYmplY3RzID0gW107XG4gICAgICBsZXQgaW1wb3J0RmlsZTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgaW1wb3J0RmlsZSA9IEpTT04ucGFyc2UocmVxLmZpbGUuYnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBwYXJzZSBKU09OIGJhc2VkIG9uIHRoZSBmaWxlIHNlbnQnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaW1wb3J0RmlsZSkpIHtcbiAgICAgICAgcmVzdE9iamVjdHMgPSBpbXBvcnRGaWxlO1xuICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGltcG9ydEZpbGUucmVzdWx0cykpIHtcbiAgICAgICAgcmVzdE9iamVjdHMgPSBpbXBvcnRGaWxlLnJlc3VsdHM7XG4gICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaW1wb3J0RmlsZS5yb3dzKSkge1xuICAgICAgICByZXN0T2JqZWN0cyA9IGltcG9ydEZpbGUucm93cztcbiAgICAgIH1cblxuICAgICAgaWYgKCFyZXN0T2JqZWN0cykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGRhdGEgdG8gaW1wb3J0Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXEuYm9keS5mZWVkYmFja0VtYWlsKSB7XG4gICAgICAgIGlmICghcmVxLmNvbmZpZy5lbWFpbEFkYXB0ZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBoYXZlIHRvIHNldHVwIGEgTWFpbCBBZGFwdGVyLicpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJlc29sdmUocmVzdE9iamVjdHMpO1xuICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlSW1wb3J0KHJlcSkge1xuXG4gICAgY29uc3QgZW1haWxDb250cm9sbGVyQWRhcHRlciA9IGxvYWRBZGFwdGVyKHJlcS5jb25maWcuZW1haWxBZGFwdGVyKTtcblxuICAgIGxldCBwcm9taXNlID0gbnVsbDtcblxuICAgIGlmIChyZXEucGFyYW1zLnJlbGF0aW9uTmFtZSkge1xuICAgICAgcHJvbWlzZSA9IHRoaXMuZ2V0T25lU2NoZW1hKHJlcSlcbiAgICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKCFyZXNwb25zZS5maWVsZHMuaGFzT3duUHJvcGVydHkocmVxLnBhcmFtcy5yZWxhdGlvbk5hbWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlbGF0aW9uICR7cmVxLnBhcmFtcy5yZWxhdGlvbk5hbWV9IGRvZXMgbm90IGV4aXN0IGluICR7cmVxLnBhcmFtcy5jbGFzc05hbWV9LmApO1xuICAgICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuZmllbGRzW3JlcS5wYXJhbXMucmVsYXRpb25OYW1lXS50eXBlICE9PSAnUmVsYXRpb24nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsYXNzICR7cmVzcG9uc2UuZmllbGRzW3JlcS5wYXJhbXMucmVsYXRpb25OYW1lXS50YXJnZXRDbGFzc30gZG9lcyBub3QgaGF2ZSBSZWxhdGlvbiB0eXBlLmApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHRhcmdldENsYXNzID0gcmVzcG9uc2UuZmllbGRzW3JlcS5wYXJhbXMucmVsYXRpb25OYW1lXS50YXJnZXRDbGFzcztcblxuICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbdGhpcy5nZXRSZXN0T2JqZWN0cyhyZXEpLCB0YXJnZXRDbGFzc10pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBwcm9taXNlID0gUHJvbWlzZS5hbGwoW3RoaXMuZ2V0UmVzdE9iamVjdHMocmVxKV0pO1xuICAgIH1cblxuICAgIHByb21pc2UgPSBwcm9taXNlXG4gICAgICAudGhlbigoW3Jlc3RPYmplY3RzLCB0YXJnZXRDbGFzc10pID0+IHtcblxuICAgICAgICByZXR1cm4gcmVzdE9iamVjdHMucmVkdWNlKChpdGVtLCBvYmplY3QsIGluZGV4KSA9PiB7XG5cbiAgICAgICAgICBpdGVtLnBhZ2VBcnJheS5wdXNoKHRoaXMuaW1wb3J0UmVzdE9iamVjdC5iaW5kKHRoaXMsIHJlcSwgb2JqZWN0LCB0YXJnZXRDbGFzcykpO1xuXG4gICAgICAgICAgaWYgKGluZGV4ICYmIGluZGV4ICUgMTAwID09PSAwIHx8IGluZGV4ID09PSAocmVzdE9iamVjdHMubGVuZ3RoIC0gMSkpIHtcblxuICAgICAgICAgICAgY29uc3QgcGFnZUFycmF5ID0gaXRlbS5wYWdlQXJyYXkuc2xpY2UoMCk7XG4gICAgICAgICAgICBpdGVtLnBhZ2VBcnJheSA9IFtdO1xuXG4gICAgICAgICAgICBpdGVtLm1haW5Qcm9taXNlID0gaXRlbS5tYWluUHJvbWlzZVxuICAgICAgICAgICAgICAudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChyZXN1bHRzLmNvbmNhdChwYWdlQXJyYXkubWFwKGZ1bmMgPT4gZnVuYygpKSkpO1xuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICB9LCB7IHBhZ2VBcnJheTogW10sIG1haW5Qcm9taXNlIDogUHJvbWlzZS5yZXNvbHZlKFtdKSB9KS5tYWluUHJvbWlzZTtcbiAgICAgIH0pXG4gICAgICAudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgICBpZiAocmVxLmJvZHkuZmVlZGJhY2tFbWFpbCkge1xuICAgICAgICAgIGVtYWlsQ29udHJvbGxlckFkYXB0ZXIuc2VuZE1haWwoe1xuICAgICAgICAgICAgdGV4dDogYFdlIGhhdmUgc3VjY2Vzc2Z1bGx5IGltcG9ydGVkIHlvdXIgZGF0YSB0byB0aGUgY2xhc3MgJHtyZXEucGFyYW1zLmNsYXNzTmFtZX0ke3JlcS5wYXJhbXMucmVsYXRpb25OYW1lID8gJywgcmVsYXRpb24gJyArIHJlcS5wYXJhbXMucmVsYXRpb25OYW1lIDogJycgfS5gLFxuICAgICAgICAgICAgdG86IHJlcS5ib2R5LmZlZWRiYWNrRW1haWwsXG4gICAgICAgICAgICBzdWJqZWN0OiAnSW1wb3J0IGNvbXBsZXRlZCdcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgcmVzcG9uc2U6IHJlc3VsdHMgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChyZXEuYm9keS5mZWVkYmFja0VtYWlsKSB7XG4gICAgICAgICAgZW1haWxDb250cm9sbGVyQWRhcHRlci5zZW5kTWFpbCh7XG4gICAgICAgICAgICB0ZXh0OiBgV2UgY291bGQgbm90IGltcG9ydCB5b3VyIGRhdGEgdG8gdGhlIGNsYXNzICR7cmVxLnBhcmFtcy5jbGFzc05hbWV9JHtyZXEucGFyYW1zLnJlbGF0aW9uTmFtZSA/ICcsIHJlbGF0aW9uICcgKyByZXEucGFyYW1zLnJlbGF0aW9uTmFtZSA6ICcnIH0uIEVycm9yOiAke2Vycm9yfWAsXG4gICAgICAgICAgICB0bzogcmVxLmJvZHkuZmVlZGJhY2tFbWFpbCxcbiAgICAgICAgICAgIHN1YmplY3Q6ICdJbXBvcnQgZmFpbGVkJ1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgc2VydmVyIGVycm9yOiAnICsgZXJyb3IpO1xuICAgICAgICB9XG5cbiAgICAgIH0pO1xuXG4gICAgaWYgKHJlcS5ib2R5LmZlZWRiYWNrRW1haWwgJiYgZW1haWxDb250cm9sbGVyQWRhcHRlcikge1xuICAgICAgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSh7IHJlc3BvbnNlOiAnV2UgYXJlIGltcG9ydGluZyB5b3VyIGRhdGEuIFlvdSB3aWxsIGJlIG5vdGlmaWVkIGJ5IGUtbWFpbCBvbmNlIGl0IGlzIGNvbXBsZXRlZC4nIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgd3JhcFByb21pc2VSZXF1ZXN0KHJlcSwgcmVzLCBoYW5kbGVyKSB7XG4gICAgcmV0dXJuIGhhbmRsZXIocmVxKVxuICAgICAgLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgICAgcmVzLmpzb24oZGF0YSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDApLnNlbmQoeyBtZXNzYWdlOiBlcnIubWVzc2FnZSB9KTtcbiAgICAgIH0pXG4gIH1cblxuICBleHByZXNzUm91dGVyKCkge1xuICAgIGNvbnN0IHJvdXRlciA9IGV4cHJlc3MuUm91dGVyKCk7XG4gICAgY29uc3QgdXBsb2FkID0gbXVsdGVyKCk7XG5cbiAgICByb3V0ZXIucG9zdCgnL2ltcG9ydF9kYXRhLzpjbGFzc05hbWUnLFxuICAgICAgdXBsb2FkLnNpbmdsZSgnaW1wb3J0RmlsZScpLFxuICAgICAgbWlkZGxld2FyZXMuYWxsb3dDcm9zc0RvbWFpbixcbiAgICAgIG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlSGVhZGVycyxcbiAgICAgIG1pZGRsZXdhcmVzLmVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICAocmVxLCByZXMpID0+IHRoaXMud3JhcFByb21pc2VSZXF1ZXN0KHJlcSwgcmVzLCB0aGlzLmhhbmRsZUltcG9ydC5iaW5kKHRoaXMpKVxuICAgICk7XG5cbiAgICByb3V0ZXIucG9zdCgnL2ltcG9ydF9yZWxhdGlvbl9kYXRhLzpjbGFzc05hbWUvOnJlbGF0aW9uTmFtZScsXG4gICAgICB1cGxvYWQuc2luZ2xlKCdpbXBvcnRGaWxlJyksXG4gICAgICBtaWRkbGV3YXJlcy5hbGxvd0Nyb3NzRG9tYWluLFxuICAgICAgbWlkZGxld2FyZXMuaGFuZGxlUGFyc2VIZWFkZXJzLFxuICAgICAgbWlkZGxld2FyZXMuZW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIChyZXEsIHJlcykgPT4gdGhpcy53cmFwUHJvbWlzZVJlcXVlc3QocmVxLCByZXMsIHRoaXMuaGFuZGxlSW1wb3J0LmJpbmQodGhpcykpXG4gICAgKTtcblxuICAgIHJldHVybiByb3V0ZXI7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSW1wb3J0Um91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/InstallationsRouter.js b/lib/Routers/InstallationsRouter.js index becd25b183..83626aef3e 100644 --- a/lib/Routers/InstallationsRouter.js +++ b/lib/Routers/InstallationsRouter.js @@ -50,4 +50,5 @@ class InstallationsRouter extends _ClassesRouter2.default { } exports.InstallationsRouter = InstallationsRouter; -exports.default = InstallationsRouter; \ No newline at end of file +exports.default = InstallationsRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0luc3RhbGxhdGlvbnNSb3V0ZXIuanMiXSwibmFtZXMiOlsiSW5zdGFsbGF0aW9uc1JvdXRlciIsIkNsYXNzZXNSb3V0ZXIiLCJjbGFzc05hbWUiLCJoYW5kbGVGaW5kIiwicmVxIiwiYm9keSIsIk9iamVjdCIsImFzc2lnbiIsIkpTT05Gcm9tUXVlcnkiLCJxdWVyeSIsIm9wdGlvbnMiLCJvcHRpb25zRnJvbUJvZHkiLCJyZXN0IiwiZmluZCIsImNvbmZpZyIsImF1dGgiLCJ3aGVyZSIsImluZm8iLCJjbGllbnRTREsiLCJ0aGVuIiwicmVzcG9uc2UiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwiaGFuZGxlR2V0IiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBRUE7Ozs7QUFDQTs7Ozs7O0FBSEE7O0FBS08sTUFBTUEsbUJBQU4sU0FBa0NDLHVCQUFsQyxDQUFnRDtBQUNyREMsY0FBWTtBQUNWLFdBQU8sZUFBUDtBQUNEOztBQUVEQyxhQUFXQyxHQUFYLEVBQWdCO0FBQ2QsVUFBTUMsT0FBT0MsT0FBT0MsTUFBUCxDQUFjSCxJQUFJQyxJQUFsQixFQUF3Qkosd0JBQWNPLGFBQWQsQ0FBNEJKLElBQUlLLEtBQWhDLENBQXhCLENBQWI7QUFDQSxVQUFNQyxVQUFVVCx3QkFBY1UsZUFBZCxDQUE4Qk4sSUFBOUIsQ0FBaEI7QUFDQSxXQUFPTyxlQUFLQyxJQUFMLENBQVVULElBQUlVLE1BQWQsRUFBc0JWLElBQUlXLElBQTFCLEVBQ0wsZUFESyxFQUNZVixLQUFLVyxLQURqQixFQUN3Qk4sT0FEeEIsRUFDaUNOLElBQUlhLElBQUosQ0FBU0MsU0FEMUMsRUFFSkMsSUFGSSxDQUVFQyxRQUFELElBQWM7QUFDbEIsYUFBTyxFQUFDQSxVQUFVQSxRQUFYLEVBQVA7QUFDRCxLQUpJLENBQVA7QUFLRDs7QUFFREMsZ0JBQWM7QUFDWixTQUFLQyxLQUFMLENBQVcsS0FBWCxFQUFpQixnQkFBakIsRUFBbUNsQixPQUFPO0FBQUUsYUFBTyxLQUFLRCxVQUFMLENBQWdCQyxHQUFoQixDQUFQO0FBQThCLEtBQTFFO0FBQ0EsU0FBS2tCLEtBQUwsQ0FBVyxLQUFYLEVBQWlCLDBCQUFqQixFQUE2Q2xCLE9BQU87QUFBRSxhQUFPLEtBQUttQixTQUFMLENBQWVuQixHQUFmLENBQVA7QUFBNkIsS0FBbkY7QUFDQSxTQUFLa0IsS0FBTCxDQUFXLE1BQVgsRUFBa0IsZ0JBQWxCLEVBQW9DbEIsT0FBTztBQUFFLGFBQU8sS0FBS29CLFlBQUwsQ0FBa0JwQixHQUFsQixDQUFQO0FBQWdDLEtBQTdFO0FBQ0EsU0FBS2tCLEtBQUwsQ0FBVyxLQUFYLEVBQWlCLDBCQUFqQixFQUE2Q2xCLE9BQU87QUFBRSxhQUFPLEtBQUtxQixZQUFMLENBQWtCckIsR0FBbEIsQ0FBUDtBQUFnQyxLQUF0RjtBQUNBLFNBQUtrQixLQUFMLENBQVcsUUFBWCxFQUFvQiwwQkFBcEIsRUFBZ0RsQixPQUFPO0FBQUUsYUFBTyxLQUFLc0IsWUFBTCxDQUFrQnRCLEdBQWxCLENBQVA7QUFBZ0MsS0FBekY7QUFDRDtBQXJCb0Q7O1FBQTFDSixtQixHQUFBQSxtQjtrQkF3QkVBLG1CIiwiZmlsZSI6Ikluc3RhbGxhdGlvbnNSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBJbnN0YWxsYXRpb25zUm91dGVyLmpzXG5cbmltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcblxuZXhwb3J0IGNsYXNzIEluc3RhbGxhdGlvbnNSb3V0ZXIgZXh0ZW5kcyBDbGFzc2VzUm91dGVyIHtcbiAgY2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnX0luc3RhbGxhdGlvbic7XG4gIH1cblxuICBoYW5kbGVGaW5kKHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKHJlcS5ib2R5LCBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KSk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IENsYXNzZXNSb3V0ZXIub3B0aW9uc0Zyb21Cb2R5KGJvZHkpO1xuICAgIHJldHVybiByZXN0LmZpbmQocmVxLmNvbmZpZywgcmVxLmF1dGgsXG4gICAgICAnX0luc3RhbGxhdGlvbicsIGJvZHkud2hlcmUsIG9wdGlvbnMsIHJlcS5pbmZvLmNsaWVudFNESylcbiAgICAgIC50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICByZXR1cm4ge3Jlc3BvbnNlOiByZXNwb25zZX07XG4gICAgICB9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0dFVCcsJy9pbnN0YWxsYXRpb25zJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlRmluZChyZXEpOyB9KTtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCcvaW5zdGFsbGF0aW9ucy86b2JqZWN0SWQnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVHZXQocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsJy9pbnN0YWxsYXRpb25zJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlQ3JlYXRlKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BVVCcsJy9pbnN0YWxsYXRpb25zLzpvYmplY3RJZCcsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZVVwZGF0ZShyZXEpOyB9KTtcbiAgICB0aGlzLnJvdXRlKCdERUxFVEUnLCcvaW5zdGFsbGF0aW9ucy86b2JqZWN0SWQnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTsgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSW5zdGFsbGF0aW9uc1JvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/LogsRouter.js b/lib/Routers/LogsRouter.js index 99ed475a83..2f4cfee587 100644 --- a/lib/Routers/LogsRouter.js +++ b/lib/Routers/LogsRouter.js @@ -68,4 +68,5 @@ class LogsRouter extends _PromiseRouter2.default { } exports.LogsRouter = LogsRouter; -exports.default = LogsRouter; \ No newline at end of file +exports.default = LogsRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0xvZ3NSb3V0ZXIuanMiXSwibmFtZXMiOlsibWlkZGxld2FyZSIsIkxvZ3NSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwidmFsaWRhdGVSZXF1ZXN0IiwicmVxIiwiaGFuZGxlR0VUIiwiY29uZmlnIiwibG9nZ2VyQ29udHJvbGxlciIsIlBhcnNlIiwiRXJyb3IiLCJQVVNIX01JU0NPTkZJR1VSRUQiLCJmcm9tIiwicXVlcnkiLCJ1bnRpbCIsInNpemUiLCJuIiwib3JkZXIiLCJsZXZlbCIsIm9wdGlvbnMiLCJnZXRMb2dzIiwidGhlbiIsInJlc3VsdCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVzcG9uc2UiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7OztBQUNBOztJQUFZQSxVOzs7Ozs7QUFFTCxNQUFNQyxVQUFOLFNBQXlCQyx1QkFBekIsQ0FBdUM7O0FBRTVDQyxnQkFBYztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxLQUFYLEVBQWlCLFlBQWpCLEVBQStCSixXQUFXSyw2QkFBMUMsRUFBeUUsS0FBS0MsZUFBOUUsRUFBaUdDLEdBQUQsSUFBUztBQUN2RyxhQUFPLEtBQUtDLFNBQUwsQ0FBZUQsR0FBZixDQUFQO0FBQ0QsS0FGRDtBQUdEOztBQUVERCxrQkFBZ0JDLEdBQWhCLEVBQXFCO0FBQ25CLFFBQUksQ0FBQ0EsSUFBSUUsTUFBTCxJQUFlLENBQUNGLElBQUlFLE1BQUosQ0FBV0MsZ0JBQS9CLEVBQWlEO0FBQy9DLFlBQU0sSUFBSUMsWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZQyxrQkFBNUIsRUFDSixpQ0FESSxDQUFOO0FBRUQ7QUFDRjs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0FMLFlBQVVELEdBQVYsRUFBZTtBQUNiLFVBQU1PLE9BQU9QLElBQUlRLEtBQUosQ0FBVUQsSUFBdkI7QUFDQSxVQUFNRSxRQUFRVCxJQUFJUSxLQUFKLENBQVVDLEtBQXhCO0FBQ0EsUUFBSUMsT0FBT1YsSUFBSVEsS0FBSixDQUFVRSxJQUFyQjtBQUNBLFFBQUlWLElBQUlRLEtBQUosQ0FBVUcsQ0FBZCxFQUFpQjtBQUNmRCxhQUFPVixJQUFJUSxLQUFKLENBQVVHLENBQWpCO0FBQ0Q7O0FBRUQsVUFBTUMsUUFBUVosSUFBSVEsS0FBSixDQUFVSSxLQUF4QjtBQUNBLFVBQU1DLFFBQVFiLElBQUlRLEtBQUosQ0FBVUssS0FBeEI7QUFDQSxVQUFNQyxVQUFVO0FBQ2RQLFVBRGM7QUFFZEUsV0FGYztBQUdkQyxVQUhjO0FBSWRFLFdBSmM7QUFLZEM7QUFMYyxLQUFoQjs7QUFRQSxXQUFPYixJQUFJRSxNQUFKLENBQVdDLGdCQUFYLENBQTRCWSxPQUE1QixDQUFvQ0QsT0FBcEMsRUFBNkNFLElBQTdDLENBQW1EQyxNQUFELElBQVk7QUFDbkUsYUFBT0MsUUFBUUMsT0FBUixDQUFnQjtBQUNyQkMsa0JBQVVIO0FBRFcsT0FBaEIsQ0FBUDtBQUdELEtBSk0sQ0FBUDtBQUtEO0FBOUMyQzs7UUFBakN2QixVLEdBQUFBLFU7a0JBaURFQSxVIiwiZmlsZSI6IkxvZ3NSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9IGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgKiBhcyBtaWRkbGV3YXJlIGZyb20gXCIuLi9taWRkbGV3YXJlc1wiO1xuXG5leHBvcnQgY2xhc3MgTG9nc1JvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0dFVCcsJy9zY3JpcHRsb2cnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCB0aGlzLnZhbGlkYXRlUmVxdWVzdCwgIChyZXEpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUdFVChyZXEpO1xuICAgIH0pO1xuICB9XG5cbiAgdmFsaWRhdGVSZXF1ZXN0KHJlcSkge1xuICAgIGlmICghcmVxLmNvbmZpZyB8fCAhcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnTG9nZ2VyIGFkYXB0ZXIgaXMgbm90IGF2YWlsYWJsZScpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHtyZXNwb25zZX0gb2JqZWN0LlxuICAvLyBxdWVyeSBwYXJhbXM6XG4gIC8vIGxldmVsIChvcHRpb25hbCkgTGV2ZWwgb2YgbG9nZ2luZyB5b3Ugd2FudCB0byBxdWVyeSBmb3IgKGluZm8gfHwgZXJyb3IpXG4gIC8vIGZyb20gKG9wdGlvbmFsKSBTdGFydCB0aW1lIGZvciB0aGUgc2VhcmNoLiBEZWZhdWx0cyB0byAxIHdlZWsgYWdvLlxuICAvLyB1bnRpbCAob3B0aW9uYWwpIEVuZCB0aW1lIGZvciB0aGUgc2VhcmNoLiBEZWZhdWx0cyB0byBjdXJyZW50IHRpbWUuXG4gIC8vIG9yZGVyIChvcHRpb25hbCkgRGlyZWN0aW9uIG9mIHJlc3VsdHMgcmV0dXJuZWQsIGVpdGhlciDigJxhc2PigJ0gb3Ig4oCcZGVzY+KAnS4gRGVmYXVsdHMgdG8g4oCcZGVzY+KAnS5cbiAgLy8gc2l6ZSAob3B0aW9uYWwpIE51bWJlciBvZiByb3dzIHJldHVybmVkIGJ5IHNlYXJjaC4gRGVmYXVsdHMgdG8gMTBcbiAgLy8gbiBzYW1lIGFzIHNpemUsIG92ZXJyaWRlcyBzaXplIGlmIHNldFxuICBoYW5kbGVHRVQocmVxKSB7XG4gICAgY29uc3QgZnJvbSA9IHJlcS5xdWVyeS5mcm9tO1xuICAgIGNvbnN0IHVudGlsID0gcmVxLnF1ZXJ5LnVudGlsO1xuICAgIGxldCBzaXplID0gcmVxLnF1ZXJ5LnNpemU7XG4gICAgaWYgKHJlcS5xdWVyeS5uKSB7XG4gICAgICBzaXplID0gcmVxLnF1ZXJ5Lm47XG4gICAgfVxuXG4gICAgY29uc3Qgb3JkZXIgPSByZXEucXVlcnkub3JkZXJcbiAgICBjb25zdCBsZXZlbCA9IHJlcS5xdWVyeS5sZXZlbDtcbiAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgZnJvbSxcbiAgICAgIHVudGlsLFxuICAgICAgc2l6ZSxcbiAgICAgIG9yZGVyLFxuICAgICAgbGV2ZWxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlcS5jb25maWcubG9nZ2VyQ29udHJvbGxlci5nZXRMb2dzKG9wdGlvbnMpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgIHJlc3BvbnNlOiByZXN1bHRcbiAgICAgIH0pO1xuICAgIH0pXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTG9nc1JvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/PublicAPIRouter.js b/lib/Routers/PublicAPIRouter.js index ef29364807..fd848ff745 100644 --- a/lib/Routers/PublicAPIRouter.js +++ b/lib/Routers/PublicAPIRouter.js @@ -268,4 +268,5 @@ class PublicAPIRouter extends _PromiseRouter2.default { } exports.PublicAPIRouter = PublicAPIRouter; -exports.default = PublicAPIRouter; \ No newline at end of file +exports.default = PublicAPIRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1B1YmxpY0FQSVJvdXRlci5qcyJdLCJuYW1lcyI6WyJwdWJsaWNfaHRtbCIsInBhdGgiLCJyZXNvbHZlIiwiX19kaXJuYW1lIiwidmlld3MiLCJQdWJsaWNBUElSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwidmVyaWZ5RW1haWwiLCJyZXEiLCJ0b2tlbiIsInVzZXJuYW1lIiwicXVlcnkiLCJhcHBJZCIsInBhcmFtcyIsImNvbmZpZyIsIkNvbmZpZyIsImdldCIsImludmFsaWRSZXF1ZXN0IiwicHVibGljU2VydmVyVVJMIiwibWlzc2luZ1B1YmxpY1NlcnZlclVSTCIsImludmFsaWRMaW5rIiwidXNlckNvbnRyb2xsZXIiLCJ0aGVuIiwicXMiLCJzdHJpbmdpZnkiLCJQcm9taXNlIiwic3RhdHVzIiwibG9jYXRpb24iLCJ2ZXJpZnlFbWFpbFN1Y2Nlc3NVUkwiLCJpbnZhbGlkVmVyaWZpY2F0aW9uTGluayIsInJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsIiwiYm9keSIsImxpbmtTZW5kU3VjY2Vzc1VSTCIsImxpbmtTZW5kRmFpbFVSTCIsImNoYW5nZVBhc3N3b3JkIiwicmVqZWN0IiwiaWQiLCJ0ZXh0IiwiZnMiLCJyZWFkRmlsZSIsImVyciIsImRhdGEiLCJyZXBsYWNlIiwicmVxdWVzdFJlc2V0UGFzc3dvcmQiLCJjaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSIsImFwcGxpY2F0aW9uSWQiLCJhcHAiLCJhcHBOYW1lIiwiY2hvb3NlUGFzc3dvcmRVUkwiLCJyZXNldFBhc3N3b3JkIiwibmV3X3Bhc3N3b3JkIiwidXBkYXRlUGFzc3dvcmQiLCJwYXNzd29yZFJlc2V0U3VjY2Vzc1VSTCIsImVycm9yIiwiaW52YWxpZExpbmtVUkwiLCJpbnZhbGlkVmVyaWZpY2F0aW9uTGlua1VSTCIsIkVycm9yIiwibWVzc2FnZSIsInNldENvbmZpZyIsIm1vdW50Um91dGVzIiwicm91dGUiLCJleHByZXNzUm91dGVyIiwicm91dGVyIiwiZXhw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QUFMLENBQVcsS0FBWCxFQUFpQixxQ0FBakIsRUFDRXBELE9BQU87QUFBRSxXQUFLa0QsU0FBTCxDQUFlbEQsR0FBZjtBQUFxQixLQURoQyxFQUVFQSxPQUFPO0FBQUUsYUFBTyxLQUFLbUMsb0JBQUwsQ0FBMEJuQyxHQUExQixDQUFQO0FBQXdDLEtBRm5EO0FBR0Q7O0FBRURxRCxrQkFBZ0I7QUFDZCxVQUFNQyxTQUFTQyxrQkFBUUMsTUFBUixFQUFmO0FBQ0FGLFdBQU9HLEdBQVAsQ0FBVyxPQUFYLEVBQW9CRixrQkFBUUcsTUFBUixDQUFlbEUsV0FBZixDQUFwQjtBQUNBOEQsV0FBT0csR0FBUCxDQUFXLEdBQVgsRUFBZ0IsTUFBTUosYUFBTixFQUFoQjtBQUNBLFdBQU9DLE1BQVA7QUFDRDtBQTlOZ0Q7O1FBQXRDekQsZSxHQUFBQSxlO2tCQWlPRUEsZSIsImZpbGUiOiJQdWJsaWNBUElSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCBDb25maWcgZnJvbSAnLi4vQ29uZmlnJztcbmltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHFzIGZyb20gJ3F1ZXJ5c3RyaW5nJztcblxuY29uc3QgcHVibGljX2h0bWwgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcIi4uLy4uL3B1YmxpY19odG1sXCIpO1xuY29uc3Qgdmlld3MgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4vLi4vdmlld3MnKTtcblxuZXhwb3J0IGNsYXNzIFB1YmxpY0FQSVJvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuXG4gIHZlcmlmeUVtYWlsKHJlcSkge1xuICAgIGNvbnN0IHsgdG9rZW4sIHVzZXJuYW1lIH0gPSByZXEucXVlcnk7XG4gICAgY29uc3QgYXBwSWQgPSByZXEucGFyYW1zLmFwcElkO1xuICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoYXBwSWQpO1xuXG4gICAgaWYoIWNvbmZpZyl7XG4gICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgfVxuXG4gICAgaWYgKCFjb25maWcucHVibGljU2VydmVyVVJMKSB7XG4gICAgICByZXR1cm4gdGhpcy5taXNzaW5nUHVibGljU2VydmVyVVJMKCk7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlbiB8fCAhdXNlcm5hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlckNvbnRyb2xsZXIgPSBjb25maWcudXNlckNvbnRyb2xsZXI7XG4gICAgcmV0dXJuIHVzZXJDb250cm9sbGVyLnZlcmlmeUVtYWlsKHVzZXJuYW1lLCB0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICBjb25zdCBwYXJhbXMgPSBxcy5zdHJpbmdpZnkoe3VzZXJuYW1lfSk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcudmVyaWZ5RW1haWxTdWNjZXNzVVJMfT8ke3BhcmFtc31gXG4gICAgICB9KTtcbiAgICB9LCAoKT0+IHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRWZXJpZmljYXRpb25MaW5rKHJlcSk7XG4gICAgfSlcbiAgfVxuXG4gIHJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHJlcSkge1xuICAgIGNvbnN0IHVzZXJuYW1lID0gcmVxLmJvZHkudXNlcm5hbWU7XG4gICAgY29uc3QgYXBwSWQgPSByZXEucGFyYW1zLmFwcElkO1xuICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoYXBwSWQpO1xuXG4gICAgaWYoIWNvbmZpZyl7XG4gICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgfVxuXG4gICAgaWYgKCFjb25maWcucHVibGljU2VydmVyVVJMKSB7XG4gICAgICByZXR1cm4gdGhpcy5taXNzaW5nUHVibGljU2VydmVyVVJMKCk7XG4gICAgfVxuXG4gICAgaWYgKCF1c2VybmFtZSkge1xuICAgICAgcmV0dXJuIHRoaXMuaW52YWxpZExpbmsocmVxKTtcbiAgICB9XG5cbiAgICBjb25zdCB1c2VyQ29udHJvbGxlciA9IGNvbmZpZy51c2VyQ29udHJvbGxlcjtcblxuICAgIHJldHVybiB1c2VyQ29udHJvbGxlci5yZXNlbmRWZXJpZmljYXRpb25FbWFpbCh1c2VybmFtZSkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcubGlua1NlbmRTdWNjZXNzVVJMfWBcbiAgICAgIH0pO1xuICAgIH0sICgpPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgIHN0YXR1czogMzAyLFxuICAgICAgICBsb2NhdGlvbjogYCR7Y29uZmlnLmxpbmtTZW5kRmFpbFVSTH1gXG4gICAgICB9KTtcbiAgICB9KVxuICB9XG5cbiAgY2hhbmdlUGFzc3dvcmQocmVxKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQocmVxLnF1ZXJ5LmlkKTtcblxuICAgICAgaWYoIWNvbmZpZyl7XG4gICAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFjb25maWcucHVibGljU2VydmVyVVJMKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlKHtcbiAgICAgICAgICBzdGF0dXM6IDQwNCxcbiAgICAgICAgICB0ZXh0OiAnTm90IGZvdW5kLidcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICAvLyBTaG91bGQgd2Uga2VlcCB0aGUgZmlsZSBpbiBtZW1vcnkgb3IgbGVhdmUgbGlrZSB0aGF0P1xuICAgICAgZnMucmVhZEZpbGUocGF0aC5yZXNvbHZlKHZpZXdzLCBcImNob29zZV9wYXNzd29yZFwiKSwgJ3V0Zi04JywgKGVyciwgZGF0YSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEgPSBkYXRhLnJlcGxhY2UoXCJQQVJTRV9TRVJWRVJfVVJMXCIsIGAnJHtjb25maWcucHVibGljU2VydmVyVVJMfSdgKTtcbiAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgdGV4dDogZGF0YVxuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICByZXF1ZXN0UmVzZXRQYXNzd29yZChyZXEpIHtcblxuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG5cbiAgICBpZighY29uZmlnKXtcbiAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwpIHtcbiAgICAgIHJldHVybiB0aGlzLm1pc3NpbmdQdWJsaWNTZXJ2ZXJVUkwoKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IHVzZXJuYW1lLCB0b2tlbiB9ID0gcmVxLnF1ZXJ5O1xuXG4gICAgaWYgKCF1c2VybmFtZSB8fCAhdG9rZW4pIHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZy51c2VyQ29udHJvbGxlci5jaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSh1c2VybmFtZSwgdG9rZW4pLnRoZW4oKCkgPT4ge1xuICAgICAgY29uc3QgcGFyYW1zID0gcXMuc3RyaW5naWZ5KHt0b2tlbiwgaWQ6IGNvbmZpZy5hcHBsaWNhdGlvbklkLCB1c2VybmFtZSwgYXBwOiBjb25maWcuYXBwTmFtZSwgfSk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcuY2hvb3NlUGFzc3dvcmRVUkx9PyR7cGFyYW1zfWBcbiAgICAgIH0pXG4gICAgfSwgKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuaW52YWxpZExpbmsocmVxKTtcbiAgICB9KVxuICB9XG5cbiAgcmVzZXRQYXNzd29yZChyZXEpIHtcblxuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG5cbiAgICBpZighY29uZmlnKXtcbiAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwpIHtcbiAgICAgIHJldHVybiB0aGlzLm1pc3NpbmdQdWJsaWNTZXJ2ZXJVUkwoKTtcbiAgICB9XG5cbiAgICBjb25zdCB7XG4gICAgICB1c2VybmFtZSxcbiAgICAgIHRva2VuLFxuICAgICAgbmV3X3Bhc3N3b3JkXG4gICAgfSA9IHJlcS5ib2R5O1xuXG4gICAgaWYgKCF1c2VybmFtZSB8fCAhdG9rZW4gfHwgIW5ld19wYXNzd29yZCkge1xuICAgICAgcmV0dXJuIHRoaXMuaW52YWxpZExpbmsocmVxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29uZmlnLnVzZXJDb250cm9sbGVyLnVwZGF0ZVBhc3N3b3JkKHVzZXJuYW1lLCB0b2tlbiwgbmV3X3Bhc3N3b3JkKS50aGVuKCgpID0+IHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHFzLnN0cmluZ2lmeSh7dXNlcm5hbWU6IHVzZXJuYW1lfSk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICAgIGxvY2F0aW9uOiBgJHtjb25maWcucGFzc3dvcmRSZXNldFN1Y2Nlc3NVUkx9PyR7cGFyYW1zfWBcbiAgICAgIH0pO1xuICAgIH0sIChlcnIpID0+IHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHFzLnN0cmluZ2lmeSh7dXNlcm5hbWU6IHVzZXJuYW1lLCB0b2tlbjogdG9rZW4sIGlkOiBjb25maWcuYXBwbGljYXRpb25JZCwgZXJyb3I6ZXJyLCBhcHA6Y29uZmlnLmFwcE5hbWV9KTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICBzdGF0dXM6IDMwMixcbiAgICAgICAgbG9jYXRpb246IGAke2NvbmZpZy5jaG9vc2VQYXNzd29yZFVSTH0/JHtwYXJhbXN9YFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgfVxuXG4gIGludmFsaWRMaW5rKHJlcSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgc3RhdHVzOiAzMDIsXG4gICAgICBsb2NhdGlvbjogcmVxLmNvbmZpZy5pbnZhbGlkTGlua1VSTFxuICAgIH0pO1xuICB9XG5cbiAgaW52YWxpZFZlcmlmaWNhdGlvbkxpbmsocmVxKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcbiAgICBpZiAocmVxLnF1ZXJ5LnVzZXJuYW1lICYmIHJlcS5wYXJhbXMuYXBwSWQpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHFzLnN0cmluZ2lmeSh7dXNlcm5hbWU6IHJlcS5xdWVyeS51c2VybmFtZSwgYXBwSWQ6IHJlcS5wYXJhbXMuYXBwSWR9KTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICBzdGF0dXM6IDMwMixcbiAgICAgICAgbG9jYXRpb246IGAke2NvbmZpZy5pbnZhbGlkVmVyaWZpY2F0aW9uTGlua1VSTH0/JHtwYXJhbXN9YFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmludmFsaWRMaW5rKHJlcSk7XG4gICAgfVxuICB9XG5cbiAgbWlzc2luZ1B1YmxpY1NlcnZlclVSTCgpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgIHRleHQ6ICAnTm90IGZvdW5kLicsXG4gICAgICBzdGF0dXM6IDQwNFxuICAgIH0pO1xuICB9XG5cbiAgaW52YWxpZFJlcXVlc3QoKSB7XG4gICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoKTtcbiAgICBlcnJvci5zdGF0dXMgPSA0MDM7XG4gICAgZXJyb3IubWVzc2FnZSA9IFwidW5hdXRob3JpemVkXCI7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBzZXRDb25maWcocmVxKSB7XG4gICAgcmVxLmNvbmZpZyA9IENvbmZpZy5nZXQocmVxLnBhcmFtcy5hcHBJZCk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgbW91bnRSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywnL2FwcHMvOmFwcElkL3ZlcmlmeV9lbWFpbCcsXG4gICAgICByZXEgPT4geyB0aGlzLnNldENvbmZpZyhyZXEpIH0sXG4gICAgICByZXEgPT4geyByZXR1cm4gdGhpcy52ZXJpZnlFbWFpbChyZXEpOyB9KTtcblxuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2FwcHMvOmFwcElkL3Jlc2VuZF92ZXJpZmljYXRpb25fZW1haWwnLFxuICAgICAgcmVxID0+IHsgdGhpcy5zZXRDb25maWcocmVxKTsgfSxcbiAgICAgIHJlcSA9PiB7IHJldHVybiB0aGlzLnJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHJlcSk7IH0pO1xuXG4gICAgdGhpcy5yb3V0ZSgnR0VUJywnL2FwcHMvY2hvb3NlX3Bhc3N3b3JkJyxcbiAgICAgIHJlcSA9PiB7IHJldHVybiB0aGlzLmNoYW5nZVBhc3N3b3JkKHJlcSk7IH0pO1xuXG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsJy9hcHBzLzphcHBJZC9yZXF1ZXN0X3Bhc3N3b3JkX3Jlc2V0JyxcbiAgICAgIHJlcSA9PiB7IHRoaXMuc2V0Q29uZmlnKHJlcSkgfSxcbiAgICAgIHJlcSA9PiB7IHJldHVybiB0aGlzLnJlc2V0UGFzc3dvcmQocmVxKTsgfSk7XG5cbiAgICB0aGlzLnJvdXRlKCdHRVQnLCcvYXBwcy86YXBwSWQvcmVxdWVzdF9wYXNzd29yZF9yZXNldCcsXG4gICAgICByZXEgPT4geyB0aGlzLnNldENvbmZpZyhyZXEpIH0sXG4gICAgICByZXEgPT4geyByZXR1cm4gdGhpcy5yZXF1ZXN0UmVzZXRQYXNzd29yZChyZXEpOyB9KTtcbiAgfVxuXG4gIGV4cHJlc3NSb3V0ZXIoKSB7XG4gICAgY29uc3Qgcm91dGVyID0gZXhwcmVzcy5Sb3V0ZXIoKTtcbiAgICByb3V0ZXIudXNlKFwiL2FwcHNcIiwgZXhwcmVzcy5zdGF0aWMocHVibGljX2h0bWwpKTtcbiAgICByb3V0ZXIudXNlKFwiL1wiLCBzdXBlci5leHByZXNzUm91dGVyKCkpO1xuICAgIHJldHVybiByb3V0ZXI7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVibGljQVBJUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/PurgeRouter.js b/lib/Routers/PurgeRouter.js index 0577ab5951..0d626b9c67 100644 --- a/lib/Routers/PurgeRouter.js +++ b/lib/Routers/PurgeRouter.js @@ -13,6 +13,10 @@ var _middlewares = require('../middlewares'); var middleware = _interopRequireWildcard(_middlewares); +var _node = require('parse/node'); + +var _node2 = _interopRequireDefault(_node); + function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -21,7 +25,7 @@ class PurgeRouter extends _PromiseRouter2.default { handlePurge(req) { if (req.auth.isReadOnly) { - throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'read-only masterKey isn\'t allowed to purge a schema.'); + throw new _node2.default.Error(_node2.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; @@ -31,6 +35,11 @@ class PurgeRouter extends _PromiseRouter2.default { cacheAdapter.role.clear(); } return { response: {} }; + }).catch(error => { + if (!error || error && error.code === _node2.default.Error.OBJECT_NOT_FOUND) { + return { response: {} }; + } + throw error; }); } @@ -42,4 +51,5 @@ class PurgeRouter extends _PromiseRouter2.default { } exports.PurgeRouter = PurgeRouter; -exports.default = PurgeRouter; \ No newline at end of file +exports.default = PurgeRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1B1cmdlUm91dGVyLmpzIl0sIm5hbWVzIjpbIm1pZGRsZXdhcmUiLCJQdXJnZVJvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJoYW5kbGVQdXJnZSIsInJlcSIsImF1dGgiLCJpc1JlYWRPbmx5IiwiUGFyc2UiLCJFcnJvciIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJjb25maWciLCJkYXRhYmFzZSIsInB1cmdlQ29sbGVjdGlvbiIsInBhcmFtcyIsImNsYXNzTmFtZSIsInRoZW4iLCJjYWNoZUFkYXB0ZXIiLCJjYWNoZUNvbnRyb2xsZXIiLCJ1c2VyIiwiY2xlYXIiLCJyb2xlIiwicmVzcG9uc2UiLCJjYXRjaCIsImVycm9yIiwiY29kZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOztJQUFZQSxVOztBQUNaOzs7Ozs7OztBQUVPLE1BQU1DLFdBQU4sU0FBMEJDLHVCQUExQixDQUF3Qzs7QUFFN0NDLGNBQVlDLEdBQVosRUFBaUI7QUFDZixRQUFJQSxJQUFJQyxJQUFKLENBQVNDLFVBQWIsRUFBeUI7QUFDdkIsWUFBTSxJQUFJQyxlQUFNQyxLQUFWLENBQWdCRCxlQUFNQyxLQUFOLENBQVlDLG1CQUE1QixFQUFpRCx1REFBakQsQ0FBTjtBQUNEO0FBQ0QsV0FBT0wsSUFBSU0sTUFBSixDQUFXQyxRQUFYLENBQW9CQyxlQUFwQixDQUFvQ1IsSUFBSVMsTUFBSixDQUFXQyxTQUEvQyxFQUNKQyxJQURJLENBQ0MsTUFBTTtBQUNWLFVBQUlDLGVBQWVaLElBQUlNLE1BQUosQ0FBV08sZUFBOUI7QUFDQSxVQUFJYixJQUFJUyxNQUFKLENBQVdDLFNBQVgsSUFBd0IsVUFBNUIsRUFBd0M7QUFDdENFLHFCQUFhRSxJQUFiLENBQWtCQyxLQUFsQjtBQUNELE9BRkQsTUFFTyxJQUFJZixJQUFJUyxNQUFKLENBQVdDLFNBQVgsSUFBd0IsT0FBNUIsRUFBcUM7QUFDMUNFLHFCQUFhSSxJQUFiLENBQWtCRCxLQUFsQjtBQUNEO0FBQ0QsYUFBTyxFQUFDRSxVQUFVLEVBQVgsRUFBUDtBQUNELEtBVEksRUFTRkMsS0FURSxDQVNLQyxLQUFELElBQVc7QUFDbEIsVUFBSSxDQUFDQSxLQUFELElBQVdBLFNBQVNBLE1BQU1DLElBQU4sS0FBZWpCLGVBQU1DLEtBQU4sQ0FBWWlCLGdCQUFuRCxFQUFzRTtBQUNwRSxlQUFPLEVBQUNKLFVBQVUsRUFBWCxFQUFQO0FBQ0Q7QUFDRCxZQUFNRSxLQUFOO0FBQ0QsS0FkSSxDQUFQO0FBZUQ7O0FBRURHLGdCQUFjO0FBQ1osU0FBS0MsS0FBTCxDQUFXLFFBQVgsRUFBc0IsbUJBQXRCLEVBQTJDM0IsV0FBVzRCLDZCQUF0RCxFQUFzRnhCLEdBQUQsSUFBUztBQUFFLGFBQU8sS0FBS0QsV0FBTCxDQUFpQkMsR0FBakIsQ0FBUDtBQUErQixLQUEvSDtBQUNEO0FBekI0Qzs7UUFBbENILFcsR0FBQUEsVztrQkE0QkVBLFciLCJmaWxlIjoiUHVyZ2VSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmUgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuXG5leHBvcnQgY2xhc3MgUHVyZ2VSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcblxuICBoYW5kbGVQdXJnZShyZXEpIHtcbiAgICBpZiAocmVxLmF1dGguaXNSZWFkT25seSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sICdyZWFkLW9ubHkgbWFzdGVyS2V5IGlzblxcJ3QgYWxsb3dlZCB0byBwdXJnZSBhIHNjaGVtYS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2UucHVyZ2VDb2xsZWN0aW9uKHJlcS5wYXJhbXMuY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB2YXIgY2FjaGVBZGFwdGVyID0gcmVxLmNvbmZpZy5jYWNoZUNvbnRyb2xsZXI7XG4gICAgICAgIGlmIChyZXEucGFyYW1zLmNsYXNzTmFtZSA9PSAnX1Nlc3Npb24nKSB7XG4gICAgICAgICAgY2FjaGVBZGFwdGVyLnVzZXIuY2xlYXIoKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXEucGFyYW1zLmNsYXNzTmFtZSA9PSAnX1JvbGUnKSB7XG4gICAgICAgICAgY2FjaGVBZGFwdGVyLnJvbGUuY2xlYXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge3Jlc3BvbnNlOiB7fX07XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKCFlcnJvciB8fCAoZXJyb3IgJiYgZXJyb3IuY29kZSA9PT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCkpIHtcbiAgICAgICAgICByZXR1cm4ge3Jlc3BvbnNlOiB7fX07XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsICAnL3B1cmdlLzpjbGFzc05hbWUnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCAocmVxKSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZVB1cmdlKHJlcSk7IH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1cmdlUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/PushRouter.js b/lib/Routers/PushRouter.js index a0cb95c9cf..d6307add24 100644 --- a/lib/Routers/PushRouter.js +++ b/lib/Routers/PushRouter.js @@ -85,4 +85,5 @@ class PushRouter extends _PromiseRouter2.default { } exports.PushRouter = PushRouter; -exports.default = PushRouter; \ No newline at end of file +exports.default = PushRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1B1c2hSb3V0ZXIuanMiXSwibmFtZXMiOlsibWlkZGxld2FyZSIsIlB1c2hSb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwibW91bnRSb3V0ZXMiLCJyb3V0ZSIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwiaGFuZGxlUE9TVCIsInJlcSIsImF1dGgiLCJpc1JlYWRPbmx5IiwiUGFyc2UiLCJFcnJvciIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJwdXNoQ29udHJvbGxlciIsImNvbmZpZyIsIlBVU0hfTUlTQ09ORklHVVJFRCIsIndoZXJlIiwiZ2V0UXVlcnlDb25kaXRpb24iLCJyZXNvbHZlIiwicHJvbWlzZSIsIlByb21pc2UiLCJfcmVzb2x2ZSIsInB1c2hTdGF0dXNJZCIsInNlbmRQdXNoIiwiYm9keSIsIm9iamVjdElkIiwiaGVhZGVycyIsInJlc3BvbnNlIiwicmVzdWx0IiwiY2F0Y2giLCJlcnIiLCJsb2dnZXJDb250cm9sbGVyIiwiZXJyb3IiLCJoYXNXaGVyZSIsImhhc0NoYW5uZWxzIiwiY2hhbm5lbHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOztJQUFZQSxVOztBQUNaOzs7Ozs7QUFFTyxNQUFNQyxVQUFOLFNBQXlCQyx1QkFBekIsQ0FBdUM7O0FBRTVDQyxnQkFBYztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLE9BQW5CLEVBQTRCSixXQUFXSyw2QkFBdkMsRUFBc0VKLFdBQVdLLFVBQWpGO0FBQ0Q7O0FBRUQsU0FBT0EsVUFBUCxDQUFrQkMsR0FBbEIsRUFBdUI7QUFDckIsUUFBSUEsSUFBSUMsSUFBSixDQUFTQyxVQUFiLEVBQXlCO0FBQ3ZCLFlBQU0sSUFBSUMsWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZQyxtQkFBNUIsRUFBaUQsZ0VBQWpELENBQU47QUFDRDtBQUNELFVBQU1DLGlCQUFpQk4sSUFBSU8sTUFBSixDQUFXRCxjQUFsQztBQUNBLFFBQUksQ0FBQ0EsY0FBTCxFQUFxQjtBQUNuQixZQUFNLElBQUlILFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUksa0JBQTVCLEVBQWdELDRCQUFoRCxDQUFOO0FBQ0Q7O0FBRUQsVUFBTUMsUUFBUWYsV0FBV2dCLGlCQUFYLENBQTZCVixHQUE3QixDQUFkO0FBQ0EsUUFBSVcsT0FBSjtBQUNBLFVBQU1DLFVBQVUsSUFBSUMsT0FBSixDQUFhQyxRQUFELElBQWM7QUFDeENILGdCQUFVRyxRQUFWO0FBQ0QsS0FGZSxDQUFoQjtBQUdBLFFBQUlDLFlBQUo7QUFDQVQsbUJBQWVVLFFBQWYsQ0FBd0JoQixJQUFJaUIsSUFBNUIsRUFBa0NSLEtBQWxDLEVBQXlDVCxJQUFJTyxNQUE3QyxFQUFxRFAsSUFBSUMsSUFBekQsRUFBZ0VpQixRQUFELElBQWM7QUFDM0VILHFCQUFlRyxRQUFmO0FBQ0FQLGNBQVE7QUFDTlEsaUJBQVM7QUFDUCxvQ0FBMEJKO0FBRG5CLFNBREg7QUFJTkssa0JBQVU7QUFDUkMsa0JBQVE7QUFEQTtBQUpKLE9BQVI7QUFRRCxLQVZELEVBVUdDLEtBVkgsQ0FVVUMsR0FBRCxJQUFTO0FBQ2hCdkIsVUFBSU8sTUFBSixDQUFXaUIsZ0JBQVgsQ0FBNEJDLEtBQTVCLENBQW1DLGVBQWNWLFlBQWEsNEJBQTlELEVBQTJGUSxHQUEzRjtBQUNELEtBWkQ7QUFhQSxXQUFPWCxPQUFQO0FBQ0Q7O0FBRUQ7Ozs7O0FBS0EsU0FBT0YsaUJBQVAsQ0FBeUJWLEdBQXpCLEVBQThCO0FBQzVCLFVBQU1pQixPQUFPakIsSUFBSWlCLElBQUosSUFBWSxFQUF6QjtBQUNBLFVBQU1TLFdBQVcsT0FBT1QsS0FBS1IsS0FBWixLQUFzQixXQUF2QztBQUNBLFVBQU1rQixjQUFjLE9BQU9WLEtBQUtXLFFBQVosS0FBeUIsV0FBN0M7O0FBRUEsUUFBSW5CLEtBQUo7QUFDQSxRQUFJaUIsWUFBWUMsV0FBaEIsRUFBNkI7QUFDM0IsWUFBTSxJQUFJeEIsWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZSSxrQkFBNUIsRUFDSixxREFESSxDQUFOO0FBRUQsS0FIRCxNQUdPLElBQUlrQixRQUFKLEVBQWM7QUFDbkJqQixjQUFRUSxLQUFLUixLQUFiO0FBQ0QsS0FGTSxNQUVBLElBQUlrQixXQUFKLEVBQWlCO0FBQ3RCbEIsY0FBUTtBQUNOLG9CQUFZO0FBQ1YsaUJBQU9RLEtBQUtXO0FBREY7QUFETixPQUFSO0FBS0QsS0FOTSxNQU1BO0FBQ0wsWUFBTSxJQUFJekIsWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZSSxrQkFBNUIsRUFBZ0QsK0RBQWhELENBQU47QUFDRDtBQUNELFdBQU9DLEtBQVA7QUFDRDtBQS9EMkM7O1FBQWpDZixVLEdBQUFBLFU7a0JBa0VFQSxVIiwiZmlsZSI6IlB1c2hSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvbWlzZVJvdXRlciAgIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0ICogYXMgbWlkZGxld2FyZSBmcm9tIFwiLi4vbWlkZGxld2FyZXNcIjtcbmltcG9ydCB7IFBhcnNlIH0gICAgICAgZnJvbSBcInBhcnNlL25vZGVcIjtcblxuZXhwb3J0IGNsYXNzIFB1c2hSb3V0ZXIgZXh0ZW5kcyBQcm9taXNlUm91dGVyIHtcblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKFwiUE9TVFwiLCBcIi9wdXNoXCIsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIFB1c2hSb3V0ZXIuaGFuZGxlUE9TVCk7XG4gIH1cblxuICBzdGF0aWMgaGFuZGxlUE9TVChyZXEpIHtcbiAgICBpZiAocmVxLmF1dGguaXNSZWFkT25seSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sICdyZWFkLW9ubHkgbWFzdGVyS2V5IGlzblxcJ3QgYWxsb3dlZCB0byBzZW5kIHB1c2ggbm90aWZpY2F0aW9ucy4nKTtcbiAgICB9XG4gICAgY29uc3QgcHVzaENvbnRyb2xsZXIgPSByZXEuY29uZmlnLnB1c2hDb250cm9sbGVyO1xuICAgIGlmICghcHVzaENvbnRyb2xsZXIpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsICdQdXNoIGNvbnRyb2xsZXIgaXMgbm90IHNldCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHdoZXJlID0gUHVzaFJvdXRlci5nZXRRdWVyeUNvbmRpdGlvbihyZXEpO1xuICAgIGxldCByZXNvbHZlO1xuICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZSgoX3Jlc29sdmUpID0+IHtcbiAgICAgIHJlc29sdmUgPSBfcmVzb2x2ZTtcbiAgICB9KTtcbiAgICBsZXQgcHVzaFN0YXR1c0lkO1xuICAgIHB1c2hDb250cm9sbGVyLnNlbmRQdXNoKHJlcS5ib2R5LCB3aGVyZSwgcmVxLmNvbmZpZywgcmVxLmF1dGgsIChvYmplY3RJZCkgPT4ge1xuICAgICAgcHVzaFN0YXR1c0lkID0gb2JqZWN0SWQ7XG4gICAgICByZXNvbHZlKHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdYLVBhcnNlLVB1c2gtU3RhdHVzLUlkJzogcHVzaFN0YXR1c0lkXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3BvbnNlOiB7XG4gICAgICAgICAgcmVzdWx0OiB0cnVlXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIHJlcS5jb25maWcubG9nZ2VyQ29udHJvbGxlci5lcnJvcihgX1B1c2hTdGF0dXMgJHtwdXNoU3RhdHVzSWR9OiBlcnJvciB3aGlsZSBzZW5kaW5nIHB1c2hgLCBlcnIpO1xuICAgIH0pO1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBxdWVyeSBjb25kaXRpb24gZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxIEEgcmVxdWVzdCBvYmplY3RcbiAgICogQHJldHVybnMge09iamVjdH0gVGhlIHF1ZXJ5IGNvbmRpdGlvbiwgdGhlIHdoZXJlIGZpZWxkIGluIGEgcXVlcnkgYXBpIGNhbGxcbiAgICovXG4gIHN0YXRpYyBnZXRRdWVyeUNvbmRpdGlvbihyZXEpIHtcbiAgICBjb25zdCBib2R5ID0gcmVxLmJvZHkgfHwge307XG4gICAgY29uc3QgaGFzV2hlcmUgPSB0eXBlb2YgYm9keS53aGVyZSAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgY29uc3QgaGFzQ2hhbm5lbHMgPSB0eXBlb2YgYm9keS5jaGFubmVscyAhPT0gJ3VuZGVmaW5lZCc7XG5cbiAgICBsZXQgd2hlcmU7XG4gICAgaWYgKGhhc1doZXJlICYmIGhhc0NoYW5uZWxzKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnQ2hhbm5lbHMgYW5kIHF1ZXJ5IGNhbiBub3QgYmUgc2V0IGF0IHRoZSBzYW1lIHRpbWUuJyk7XG4gICAgfSBlbHNlIGlmIChoYXNXaGVyZSkge1xuICAgICAgd2hlcmUgPSBib2R5LndoZXJlO1xuICAgIH0gZWxzZSBpZiAoaGFzQ2hhbm5lbHMpIHtcbiAgICAgIHdoZXJlID0ge1xuICAgICAgICBcImNoYW5uZWxzXCI6IHtcbiAgICAgICAgICBcIiRpblwiOiBib2R5LmNoYW5uZWxzXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCwgJ1NlbmRpbmcgYSBwdXNoIHJlcXVpcmVzIGVpdGhlciBcImNoYW5uZWxzXCIgb3IgYSBcIndoZXJlXCIgcXVlcnkuJyk7XG4gICAgfVxuICAgIHJldHVybiB3aGVyZTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBQdXNoUm91dGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Routers/RolesRouter.js b/lib/Routers/RolesRouter.js index 05ae6cccf6..d4b6c8d864 100644 --- a/lib/Routers/RolesRouter.js +++ b/lib/Routers/RolesRouter.js @@ -36,4 +36,5 @@ class RolesRouter extends _ClassesRouter2.default { } exports.RolesRouter = RolesRouter; -exports.default = RolesRouter; \ No newline at end of file +exports.default = RolesRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1JvbGVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIlJvbGVzUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsIm1vdW50Um91dGVzIiwicm91dGUiLCJyZXEiLCJoYW5kbGVGaW5kIiwiaGFuZGxlR2V0IiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7Ozs7OztBQUVPLE1BQU1BLFdBQU4sU0FBMEJDLHVCQUExQixDQUF3QztBQUM3Q0MsY0FBWTtBQUNWLFdBQU8sT0FBUDtBQUNEOztBQUVEQyxnQkFBYztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxLQUFYLEVBQWlCLFFBQWpCLEVBQTJCQyxPQUFPO0FBQUUsYUFBTyxLQUFLQyxVQUFMLENBQWdCRCxHQUFoQixDQUFQO0FBQThCLEtBQWxFO0FBQ0EsU0FBS0QsS0FBTCxDQUFXLEtBQVgsRUFBaUIsa0JBQWpCLEVBQXFDQyxPQUFPO0FBQUUsYUFBTyxLQUFLRSxTQUFMLENBQWVGLEdBQWYsQ0FBUDtBQUE2QixLQUEzRTtBQUNBLFNBQUtELEtBQUwsQ0FBVyxNQUFYLEVBQWtCLFFBQWxCLEVBQTRCQyxPQUFPO0FBQUUsYUFBTyxLQUFLRyxZQUFMLENBQWtCSCxHQUFsQixDQUFQO0FBQWdDLEtBQXJFO0FBQ0EsU0FBS0QsS0FBTCxDQUFXLEtBQVgsRUFBaUIsa0JBQWpCLEVBQXFDQyxPQUFPO0FBQUUsYUFBTyxLQUFLSSxZQUFMLENBQWtCSixHQUFsQixDQUFQO0FBQWdDLEtBQTlFO0FBQ0EsU0FBS0QsS0FBTCxDQUFXLFFBQVgsRUFBb0Isa0JBQXBCLEVBQXdDQyxPQUFPO0FBQUUsYUFBTyxLQUFLSyxZQUFMLENBQWtCTCxHQUFsQixDQUFQO0FBQWdDLEtBQWpGO0FBQ0Q7QUFYNEM7O1FBQWxDTCxXLEdBQUFBLFc7a0JBY0VBLFciLCJmaWxlIjoiUm9sZXNSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5cbmV4cG9ydCBjbGFzcyBSb2xlc1JvdXRlciBleHRlbmRzIENsYXNzZXNSb3V0ZXIge1xuICBjbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdfUm9sZSc7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCcvcm9sZXMnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsJy9yb2xlcy86b2JqZWN0SWQnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVHZXQocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsJy9yb2xlcycsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZUNyZWF0ZShyZXEpOyB9KTtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCcvcm9sZXMvOm9iamVjdElkJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlVXBkYXRlKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsJy9yb2xlcy86b2JqZWN0SWQnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTsgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUm9sZXNSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/SchemasRouter.js b/lib/Routers/SchemasRouter.js index 01f909fcd6..3100be7b19 100644 --- a/lib/Routers/SchemasRouter.js +++ b/lib/Routers/SchemasRouter.js @@ -93,4 +93,5 @@ class SchemasRouter extends _PromiseRouter2.default { this.route('DELETE', '/schemas/:className', middleware.promiseEnforceMasterKeyAccess, deleteSchema); } } -exports.SchemasRouter = SchemasRouter; \ No newline at end of file +exports.SchemasRouter = SchemasRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1NjaGVtYXNSb3V0ZXIuanMiXSwibmFtZXMiOlsibWlkZGxld2FyZSIsIlBhcnNlIiwicmVxdWlyZSIsIlNjaGVtYUNvbnRyb2xsZXIiLCJjbGFzc05hbWVNaXNtYXRjaFJlc3BvbnNlIiwiYm9keUNsYXNzIiwicGF0aENsYXNzIiwiRXJyb3IiLCJJTlZBTElEX0NMQVNTX05BTUUiLCJnZXRBbGxTY2hlbWFzIiwicmVxIiwiY29uZmlnIiwiZGF0YWJhc2UiLCJsb2FkU2NoZW1hIiwiY2xlYXJDYWNoZSIsInRoZW4iLCJzY2hlbWFDb250cm9sbGVyIiwiZ2V0QWxsQ2xhc3NlcyIsInNjaGVtYXMiLCJyZXNwb25zZSIsInJlc3VsdHMiLCJnZXRPbmVTY2hlbWEiLCJjbGFzc05hbWUiLCJwYXJhbXMiLCJzY2hlbWEiLCJjYXRjaCIsImVycm9yIiwidW5kZWZpbmVkIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwiY3JlYXRlU2NoZW1hIiwiYXV0aCIsImlzUmVhZE9ubHkiLCJPUEVSQVRJT05fRk9SQklEREVOIiwiYm9keSIsInBhdGgiLCJhZGRDbGFzc0lmTm90RXhpc3RzIiwiZmllbGRzIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vZGlmeVNjaGVtYSIsInN1Ym1pdHRlZEZpZWxkcyIsInVwZGF0ZUNsYXNzIiwicmVzdWx0IiwiZGVsZXRlU2NoZW1hIiwiY2xhc3NOYW1lSXNWYWxpZCIsImludmFsaWRDbGFzc05hbWVNZXNzYWdlIiwiU2NoZW1hc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwicHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFLQTs7OztBQUNBOztJQUFZQSxVOzs7Ozs7QUFOWjs7QUFFQSxJQUFJQyxRQUFRQyxRQUFRLFlBQVIsRUFBc0JELEtBQWxDO0FBQUEsSUFDRUUsbUJBQW1CRCxRQUFRLGlDQUFS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WyIvLyBzY2hlbWFzLmpzXG5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZSxcbiAgU2NoZW1hQ29udHJvbGxlciA9IHJlcXVpcmUoJy4uL0NvbnRyb2xsZXJzL1NjaGVtYUNvbnRyb2xsZXInKTtcblxuaW1wb3J0IFByb21pc2VSb3V0ZXIgICBmcm9tICcuLi9Qcm9taXNlUm91dGVyJztcbmltcG9ydCAqIGFzIG1pZGRsZXdhcmUgZnJvbSBcIi4uL21pZGRsZXdhcmVzXCI7XG5cbmZ1bmN0aW9uIGNsYXNzTmFtZU1pc21hdGNoUmVzcG9uc2UoYm9keUNsYXNzLCBwYXRoQ2xhc3MpIHtcbiAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgIFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSxcbiAgICBgQ2xhc3MgbmFtZSBtaXNtYXRjaCBiZXR3ZWVuICR7Ym9keUNsYXNzfSBhbmQgJHtwYXRoQ2xhc3N9LmBcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2V0QWxsU2NoZW1hcyhyZXEpIHtcbiAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSh7IGNsZWFyQ2FjaGU6IHRydWV9KVxuICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4gc2NoZW1hQ29udHJvbGxlci5nZXRBbGxDbGFzc2VzKHRydWUpKVxuICAgIC50aGVuKHNjaGVtYXMgPT4gKHsgcmVzcG9uc2U6IHsgcmVzdWx0czogc2NoZW1hcyB9IH0pKTtcbn1cblxuZnVuY3Rpb24gZ2V0T25lU2NoZW1hKHJlcSkge1xuICBjb25zdCBjbGFzc05hbWUgPSByZXEucGFyYW1zLmNsYXNzTmFtZTtcbiAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2UubG9hZFNjaGVtYSh7IGNsZWFyQ2FjaGU6IHRydWV9KVxuICAgIC50aGVuKHNjaGVtYUNvbnRyb2xsZXIgPT4gc2NoZW1hQ29udHJvbGxlci5nZXRPbmVTY2hlbWEoY2xhc3NOYW1lLCB0cnVlKSlcbiAgICAudGhlbihzY2hlbWEgPT4gKHsgcmVzcG9uc2U6IHNjaGVtYSB9KSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaWYgKGVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSwgYENsYXNzICR7Y2xhc3NOYW1lfSBkb2VzIG5vdCBleGlzdC5gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsICdEYXRhYmFzZSBhZGFwdGVyIGVycm9yLicpO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVTY2hlbWEocmVxKSB7XG4gIGlmIChyZXEuYXV0aC5pc1JlYWRPbmx5KSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sICdyZWFkLW9ubHkgbWFzdGVyS2V5IGlzblxcJ3QgYWxsb3dlZCB0byBjcmVhdGUgYSBzY2hlbWEuJyk7XG4gIH1cbiAgaWYgKHJlcS5wYXJhbXMuY2xhc3NOYW1lICYmIHJlcS5ib2R5LmNsYXNzTmFtZSkge1xuICAgIGlmIChyZXEucGFyYW1zLmNsYXNzTmFtZSAhPSByZXEuYm9keS5jbGFzc05hbWUpIHtcbiAgICAgIHJldHVybiBjbGFzc05hbWVNaXNtYXRjaFJlc3BvbnNlKHJlcS5ib2R5LmNsYXNzTmFtZSwgcmVxLnBhcmFtcy5jbGFzc05hbWUpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGNsYXNzTmFtZSA9IHJlcS5wYXJhbXMuY2xhc3NOYW1lIHx8IHJlcS5ib2R5LmNsYXNzTmFtZTtcbiAgaWYgKCFjbGFzc05hbWUpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMTM1LCBgUE9TVCAke3JlcS5wYXRofSBuZWVkcyBhIGNsYXNzIG5hbWUuYCk7XG4gIH1cblxuICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZS5sb2FkU2NoZW1hKHsgY2xlYXJDYWNoZTogdHJ1ZX0pXG4gICAgLnRoZW4oc2NoZW1hID0+IHNjaGVtYS5hZGRDbGFzc0lmTm90RXhpc3RzKGNsYXNzTmFtZSwgcmVxLmJvZHkuZmllbGRzLCByZXEuYm9keS5jbGFzc0xldmVsUGVybWlzc2lvbnMsIHJlcS5ib2R5LmluZGV4ZXMpKVxuICAgIC50aGVuKHNjaGVtYSA9PiAoeyByZXNwb25zZTogc2NoZW1hIH0pKTtcbn1cblxuZnVuY3Rpb24gbW9kaWZ5U2NoZW1hKHJlcSkge1xuICBpZiAocmVxLmF1dGguaXNSZWFkT25seSkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCAncmVhZC1vbmx5IG1hc3RlcktleSBpc25cXCd0IGFsbG93ZWQgdG8gdXBkYXRlIGEgc2NoZW1hLicpO1xuICB9XG4gIGlmIChyZXEuYm9keS5jbGFzc05hbWUgJiYgcmVxLmJvZHkuY2xhc3NOYW1lICE9IHJlcS5wYXJhbXMuY2xhc3NOYW1lKSB7XG4gICAgcmV0dXJuIGNsYXNzTmFtZU1pc21hdGNoUmVzcG9uc2UocmVxLmJvZHkuY2xhc3NOYW1lLCByZXEucGFyYW1zLmNsYXNzTmFtZSk7XG4gIH1cblxuICBjb25zdCBzdWJtaXR0ZWRGaWVsZHMgPSByZXEuYm9keS5maWVsZHMgfHwge307XG4gIGNvbnN0IGNsYXNzTmFtZSA9IHJlcS5wYXJhbXMuY2xhc3NOYW1lO1xuXG4gIHJldHVybiByZXEuY29uZmlnLmRhdGFiYXNlLmxvYWRTY2hlbWEoeyBjbGVhckNhY2hlOiB0cnVlfSlcbiAgICAudGhlbihzY2hlbWEgPT4gc2NoZW1hLnVwZGF0ZUNsYXNzKGNsYXNzTmFtZSwgc3VibWl0dGVkRmllbGRzLCByZXEuYm9keS5jbGFzc0xldmVsUGVybWlzc2lvbnMsIHJlcS5ib2R5LmluZGV4ZXMsIHJlcS5jb25maWcuZGF0YWJhc2UpKVxuICAgIC50aGVuKHJlc3VsdCA9PiAoe3Jlc3BvbnNlOiByZXN1bHR9KSk7XG59XG5cbmNvbnN0IGRlbGV0ZVNjaGVtYSA9IHJlcSA9PiB7XG4gIGlmIChyZXEuYXV0aC5pc1JlYWRPbmx5KSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sICdyZWFkLW9ubHkgbWFzdGVyS2V5IGlzblxcJ3QgYWxsb3dlZCB0byBkZWxldGUgYSBzY2hlbWEuJyk7XG4gIH1cbiAgaWYgKCFTY2hlbWFDb250cm9sbGVyLmNsYXNzTmFtZUlzVmFsaWQocmVxLnBhcmFtcy5jbGFzc05hbWUpKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfQ0xBU1NfTkFNRSwgU2NoZW1hQ29udHJvbGxlci5pbnZhbGlkQ2xhc3NOYW1lTWVzc2FnZShyZXEucGFyYW1zLmNsYXNzTmFtZSkpO1xuICB9XG4gIHJldHVybiByZXEuY29uZmlnLmRhdGFiYXNlLmRlbGV0ZVNjaGVtYShyZXEucGFyYW1zLmNsYXNzTmFtZSlcbiAgICAudGhlbigoKSA9PiAoeyByZXNwb25zZToge30gfSkpO1xufVxuXG5leHBvcnQgY2xhc3MgU2NoZW1hc1JvdXRlciBleHRlbmRzIFByb21pc2VSb3V0ZXIge1xuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3NjaGVtYXMnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCBnZXRBbGxTY2hlbWFzKTtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3NjaGVtYXMvOmNsYXNzTmFtZScsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIGdldE9uZVNjaGVtYSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvc2NoZW1hcycsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIGNyZWF0ZVNjaGVtYSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvc2NoZW1hcy86Y2xhc3NOYW1lJywgbWlkZGxld2FyZS5wcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcywgY3JlYXRlU2NoZW1hKTtcbiAgICB0aGlzLnJvdXRlKCdQVVQnLCAnL3NjaGVtYXMvOmNsYXNzTmFtZScsIG1pZGRsZXdhcmUucHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsIG1vZGlmeVNjaGVtYSk7XG4gICAgdGhpcy5yb3V0ZSgnREVMRVRFJywgJy9zY2hlbWFzLzpjbGFzc05hbWUnLCBtaWRkbGV3YXJlLnByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzLCBkZWxldGVTY2hlbWEpO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Routers/SessionsRouter.js b/lib/Routers/SessionsRouter.js index 5a29c218aa..578db0d165 100644 --- a/lib/Routers/SessionsRouter.js +++ b/lib/Routers/SessionsRouter.js @@ -101,4 +101,5 @@ class SessionsRouter extends _ClassesRouter2.default { } exports.SessionsRouter = SessionsRouter; -exports.default = SessionsRouter; \ No newline at end of file +exports.default = SessionsRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1Nlc3Npb25zUm91dGVyLmpzIl0sIm5hbWVzIjpbIlNlc3Npb25zUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsImhhbmRsZU1lIiwicmVxIiwiaW5mbyIsInNlc3Npb25Ub2tlbiIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1NFU1NJT05fVE9LRU4iLCJyZXN0IiwiZmluZCIsImNvbmZpZyIsIkF1dGgiLCJtYXN0ZXIiLCJ1bmRlZmluZWQiLCJjbGllbnRTREsiLCJ0aGVuIiwicmVzcG9uc2UiLCJyZXN1bHRzIiwibGVuZ3RoIiwiaGFuZGxlVXBkYXRlVG9SZXZvY2FibGVTZXNzaW9uIiwidXNlciIsImF1dGgiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwic2Vzc2lvbkRhdGEiLCJjcmVhdGVTZXNzaW9uIiwidXNlcklkIiwiaWQiLCJjcmVhdGVkV2l0aCIsImluc3RhbGxhdGlvbklkIiwiZGF0YWJhc2UiLCJ1cGRhdGUiLCJvYmplY3RJZCIsIl9fb3AiLCJQcm9taXNlIiwicmVzb2x2ZSIsIm1vdW50Um91dGVzIiwicm91dGUiLCJoYW5kbGVGaW5kIiwiaGFuZGxlR2V0IiwiaGFuZGxlQ3JlYXRlIiwiaGFuZGxlVXBkYXRlIiwiaGFuZGxlRGVsZXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVPLE1BQU1BLGNBQU4sU0FBNkJDLHVCQUE3QixDQUEyQzs7QUFFaERDLGNBQVk7QUFDVixXQUFPLFVBQVA7QUFDRDs7QUFFREMsV0FBU0MsR0FBVCxFQUFjO0FBQ1o7QUFDQSxRQUFJLENBQUNBLElBQUlDLElBQUwsSUFBYSxDQUFDRCxJQUFJQyxJQUFKLENBQVNDLFlBQTNCLEVBQXlDO0FBQ3ZDLFlBQU0sSUFBSUMsZUFBTUMsS0FBVixDQUFnQkQsZUFBTUMsS0FBTixDQUFZQyxxQkFBNUIsRUFDSix5QkFESSxDQUFOO0FBRUQ7QUFDRCxXQUFPQyxlQUFLQyxJQUFMLENBQVVQLElBQUlRLE1BQWQsRUFBc0JDLGVBQUtDLE1BQUwsQ0FBWVYsSUFBSVEsTUFBaEIsQ0FBdEIsRUFBK0MsVUFBL0MsRUFBMkQsRUFBRU4sY0FBY0YsSUFBSUMsSUFBSixDQUFTQyxZQUF6QixFQUEzRCxFQUFvR1MsU0FBcEcsRUFBK0dYLElBQUlDLElBQUosQ0FBU1csU0FBeEgsRUFDSkMsSUFESSxDQUNFQyxRQUFELElBQWM7QUFDbEIsVUFBSSxDQUFDQSxTQUFTQyxPQUFWLElBQXFCRCxTQUFTQyxPQUFULENBQWlCQyxNQUFqQixJQUEyQixDQUFwRCxFQUF1RDtBQUNyRCxjQUFNLElBQUliLGVBQU1DLEtBQVYsQ0FBZ0JELGVBQU1DLEtBQU4sQ0FBWUMscUJBQTVCLEVBQ0osMEJBREksQ0FBTjtBQUVEO0FBQ0QsYUFBTztBQUNMUyxrQkFBVUEsU0FBU0MsT0FBVCxDQUFpQixDQUFqQjtBQURMLE9BQVA7QUFHRCxLQVRJLENBQVA7QUFVRDs7QUFFREUsaUNBQStCakIsR0FBL0IsRUFBb0M7QUFDbEMsVUFBTVEsU0FBU1IsSUFBSVEsTUFBbkI7QUFDQSxVQUFNVSxPQUFPbEIsSUFBSW1CLElBQUosQ0FBU0QsSUFBdEI7QUFDQTtBQUNBO0FBQ0EsUUFBSSxDQUFDQSxJQUFMLEVBQVc7QUFDVCxZQUFNLElBQUlmLGVBQU1DLEtBQVYsQ0FBZ0JELGVBQU1DLEtBQU4sQ0FBWWdCLGdCQUE1QixFQUE4QyxpQkFBOUMsQ0FBTjtBQUNEO0FBQ0QsVUFBTTtBQUNKQyxpQkFESTtBQUVKQztBQUZJLFFBR0ZiLGVBQUthLGFBQUwsQ0FBbUJkLE1BQW5CLEVBQTJCO0FBQzdCZSxjQUFRTCxLQUFLTSxFQURnQjtBQUU3QkMsbUJBQWE7QUFDWCxrQkFBVTtBQURDLE9BRmdCO0FBSzdCQyxzQkFBZ0IxQixJQUFJbUIsSUFBSixDQUFTTztBQUxJLEtBQTNCLENBSEo7O0FBV0EsV0FBT0osZ0JBQWdCVCxJQUFoQixDQUFxQixNQUFNO0FBQ2hDO0FBQ0EsYUFBT0wsT0FBT21CLFFBQVAsQ0FBZ0JDLE1BQWhCLENBQXVCLE9BQXZCLEVBQWdDO0FBQ3JDQyxrQkFBVVgsS0FBS007QUFEc0IsT0FBaEMsRUFFSjtBQUNEdEIsc0JBQWMsRUFBQzRCLE1BQU0sUUFBUDtBQURiLE9BRkksQ0FBUDtBQUtELEtBUE0sRUFPSmpCLElBUEksQ0FPQyxNQUFNO0FBQ1osYUFBT2tCLFFBQVFDLE9BQVIsQ0FBZ0IsRUFBRWxCLFVBQVVPLFdBQVosRUFBaEIsQ0FBUDtBQUNELEtBVE0sQ0FBUDtBQVVEOztBQUVEWSxnQkFBYztBQUNaLFNBQUtDLEtBQUwsQ0FBVyxLQUFYLEVBQWlCLGNBQWpCLEVBQWlDbEMsT0FBTztBQUFFLGFBQU8sS0FBS0QsUUFBTCxDQUFjQyxHQUFkLENBQVA7QUFBNEIsS0FBdEU7QUFDQSxTQUFLa0MsS0FBTCxDQUFXLEtBQVgsRUFBa0IsV0FBbEIsRUFBK0JsQyxPQUFPO0FBQUUsYUFBTyxLQUFLbUMsVUFBTCxDQUFnQm5DLEdBQWhCLENBQVA7QUFBOEIsS0FBdEU7QUFDQSxTQUFLa0MsS0FBTCxDQUFXLEtBQVgsRUFBa0IscUJBQWxCLEVBQXlDbEMsT0FBTztBQUFFLGFBQU8sS0FBS29DLFNBQUwsQ0FBZXBDLEdBQWYsQ0FBUDtBQUE2QixLQUEvRTtBQUNBLFNBQUtrQyxLQUFMLENBQVcsTUFBWCxFQUFtQixXQUFuQixFQUFnQ2xDLE9BQU87QUFBRSxhQUFPLEtBQUtxQyxZQUFMLENBQWtCckMsR0FBbEIsQ0FBUDtBQUFnQyxLQUF6RTtBQUNBLFNBQUtrQyxLQUFMLENBQVcsS0FBWCxFQUFrQixxQkFBbEIsRUFBeUNsQyxPQUFPO0FBQUUsYUFBTyxLQUFLc0MsWUFBTCxDQUFrQnRDLEdBQWxCLENBQVA7QUFBZ0MsS0FBbEY7QUFDQSxTQUFLa0MsS0FBTCxDQUFXLFFBQVgsRUFBcUIscUJBQXJCLEVBQTRDbEMsT0FBTztBQUFFLGFBQU8sS0FBS3VDLFlBQUwsQ0FBa0J2QyxHQUFsQixDQUFQO0FBQWdDLEtBQXJGO0FBQ0EsU0FBS2tDLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLDRCQUFuQixFQUFpRGxDLE9BQU87QUFBRSxhQUFPLEtBQUtpQiw4QkFBTCxDQUFvQ2pCLEdBQXBDLENBQVA7QUFBa0QsS0FBNUc7QUFDRDtBQS9EK0M7O1FBQXJDSixjLEdBQUFBLGM7a0JBa0VFQSxjIiwiZmlsZSI6IlNlc3Npb25zUm91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5pbXBvcnQgQ2xhc3Nlc1JvdXRlciBmcm9tICcuL0NsYXNzZXNSb3V0ZXInO1xuaW1wb3J0IFBhcnNlICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgcmVzdCAgICAgICAgICBmcm9tICcuLi9yZXN0JztcbmltcG9ydCBBdXRoICAgICAgICAgIGZyb20gJy4uL0F1dGgnO1xuXG5leHBvcnQgY2xhc3MgU2Vzc2lvbnNSb3V0ZXIgZXh0ZW5kcyBDbGFzc2VzUm91dGVyIHtcblxuICBjbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdfU2Vzc2lvbic7XG4gIH1cblxuICBoYW5kbGVNZShyZXEpIHtcbiAgICAvLyBUT0RPOiBWZXJpZnkgY29ycmVjdCBiZWhhdmlvclxuICAgIGlmICghcmVxLmluZm8gfHwgIXJlcS5pbmZvLnNlc3Npb25Ub2tlbikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTixcbiAgICAgICAgJ1Nlc3Npb24gdG9rZW4gcmVxdWlyZWQuJyk7XG4gICAgfVxuICAgIHJldHVybiByZXN0LmZpbmQocmVxLmNvbmZpZywgQXV0aC5tYXN0ZXIocmVxLmNvbmZpZyksICdfU2Vzc2lvbicsIHsgc2Vzc2lvblRva2VuOiByZXEuaW5mby5zZXNzaW9uVG9rZW4gfSwgdW5kZWZpbmVkLCByZXEuaW5mby5jbGllbnRTREspXG4gICAgICAudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKCFyZXNwb25zZS5yZXN1bHRzIHx8IHJlc3BvbnNlLnJlc3VsdHMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICAgJ1Nlc3Npb24gdG9rZW4gbm90IGZvdW5kLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVzcG9uc2U6IHJlc3BvbnNlLnJlc3VsdHNbMF1cbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlVXBkYXRlVG9SZXZvY2FibGVTZXNzaW9uKHJlcSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG4gICAgY29uc3QgdXNlciA9IHJlcS5hdXRoLnVzZXI7XG4gICAgLy8gSXNzdWUgIzI3MjBcbiAgICAvLyBDYWxsaW5nIHdpdGhvdXQgYSBzZXNzaW9uIHRva2VuIHdvdWxkIHJlc3VsdCBpbiBhIG5vdCBmb3VuZCB1c2VyXG4gICAgaWYgKCF1c2VyKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ2ludmFsaWQgc2Vzc2lvbicpO1xuICAgIH1cbiAgICBjb25zdCB7XG4gICAgICBzZXNzaW9uRGF0YSxcbiAgICAgIGNyZWF0ZVNlc3Npb25cbiAgICB9ID0gQXV0aC5jcmVhdGVTZXNzaW9uKGNvbmZpZywge1xuICAgICAgdXNlcklkOiB1c2VyLmlkLFxuICAgICAgY3JlYXRlZFdpdGg6IHtcbiAgICAgICAgJ2FjdGlvbic6ICd1cGdyYWRlJyxcbiAgICAgIH0sXG4gICAgICBpbnN0YWxsYXRpb25JZDogcmVxLmF1dGguaW5zdGFsbGF0aW9uSWQsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gY3JlYXRlU2Vzc2lvbigpLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gZGVsZXRlIHRoZSBzZXNzaW9uIHRva2VuLCB1c2UgdGhlIGRiIHRvIHNraXAgYmVmb3JlU2F2ZVxuICAgICAgcmV0dXJuIGNvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywge1xuICAgICAgICBvYmplY3RJZDogdXNlci5pZFxuICAgICAgfSwge1xuICAgICAgICBzZXNzaW9uVG9rZW46IHtfX29wOiAnRGVsZXRlJ31cbiAgICAgIH0pO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IHJlc3BvbnNlOiBzZXNzaW9uRGF0YSB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIG1vdW50Um91dGVzKCkge1xuICAgIHRoaXMucm91dGUoJ0dFVCcsJy9zZXNzaW9ucy9tZScsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZU1lKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvc2Vzc2lvbnMnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ0dFVCcsICcvc2Vzc2lvbnMvOm9iamVjdElkJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlR2V0KHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL3Nlc3Npb25zJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlQ3JlYXRlKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BVVCcsICcvc2Vzc2lvbnMvOm9iamVjdElkJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlVXBkYXRlKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsICcvc2Vzc2lvbnMvOm9iamVjdElkJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlRGVsZXRlKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL3VwZ3JhZGVUb1Jldm9jYWJsZVNlc3Npb24nLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGVUb1Jldm9jYWJsZVNlc3Npb24ocmVxKTsgfSlcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBTZXNzaW9uc1JvdXRlcjtcbiJdfQ== \ No newline at end of file diff --git a/lib/Routers/UsersRouter.js b/lib/Routers/UsersRouter.js index 8d3fec1132..529d645065 100644 --- a/lib/Routers/UsersRouter.js +++ b/lib/Routers/UsersRouter.js @@ -56,14 +56,109 @@ class UsersRouter extends _ClassesRouter2.default { } } + /** + * 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 _node2.default.Error(_node2.default.Error.USERNAME_MISSING, 'username/email is required.'); + } + if (!password) { + throw new _node2.default.Error(_node2.default.Error.PASSWORD_MISSING, 'password is required.'); + } + if (typeof password !== 'string' || email && typeof email !== 'string' || username && typeof username !== 'string') { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.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 _password2.default.compare(password, user.password); + }).then(correct => { + isValidPassword = correct; + const accountLockoutPolicy = new _AccountLockout2.default(user, req.config); + return accountLockoutPolicy.handleLoginAttempt(isValidPassword); + }).then(() => { + if (!isValidPassword) { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) { + throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + throw new _node2.default.Error(_node2.default.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } const sessionToken = req.info.sessionToken; return _rest2.default.find(req.config, _Auth2.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 _node2.default.Error(_node2.default.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + throw new _node2.default.Error(_node2.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. @@ -78,63 +173,10 @@ class UsersRouter extends _ClassesRouter2.default { } handleLogIn(req) { - // 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 _node2.default.Error(_node2.default.Error.USERNAME_MISSING, 'username/email is required.'); - } - if (!password) { - throw new _node2.default.Error(_node2.default.Error.PASSWORD_MISSING, 'password is required.'); - } - if (typeof password !== 'string' || email && typeof email !== 'string' || username && typeof username !== 'string') { - throw new _node2.default.Error(_node2.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 _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); - } + return this._authenticateUserFromRequest(req).then(res => { - 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]; - } - - if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) { - throw new _node2.default.Error(_node2.default.Error.EMAIL_NOT_FOUND, 'User email is not verified.'); - } - return _password2.default.compare(password, user.password); - }).then(correct => { - isValidPassword = correct; - const accountLockoutPolicy = new _AccountLockout2.default(user, req.config); - return accountLockoutPolicy.handleLoginAttempt(isValidPassword); - }).then(() => { - if (!isValidPassword) { - throw new _node2.default.Error(_node2.default.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); - } + user = res; // handle password expiry policy if (req.config.passwordPolicy && req.config.passwordPolicy.maxPasswordAge) { @@ -157,30 +199,18 @@ class UsersRouter extends _ClassesRouter2.default { } } - delete user.password; - // Remove hidden properties. UsersRouter.removeHiddenProperties(user); - // 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; - } - } const { sessionData, createSession - } = _Auth2.default.createSession(req.config, { userId: user.objectId, createdWith: { + } = _Auth2.default.createSession(req.config, { + userId: user.objectId, createdWith: { 'action': 'login', 'authProvider': 'password' - }, installationId: req.info.installationId }); + }, installationId: req.info.installationId + }); user.sessionToken = sessionData.sessionToken; @@ -192,6 +222,18 @@ class UsersRouter extends _ClassesRouter2.default { }); } + 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) { @@ -315,9 +357,13 @@ class UsersRouter extends _ClassesRouter2.default { this.route('POST', '/verificationEmailRequest', req => { return this.handleVerificationEmailRequest(req); }); + this.route('GET', '/verifyPassword', req => { + return this.handleVerifyPassword(req); + }); } } exports.UsersRouter = UsersRouter; // These methods handle the User-related routes. -exports.default = UsersRouter; \ No newline at end of file +exports.default = UsersRouter; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL1VzZXJzUm91dGVyLmpzIl0sIm5hbWVzIjpbIlVzZXJzUm91dGVyIiwiQ2xhc3Nlc1JvdXRlciIsImNsYXNzTmFtZSIsInJlbW92ZUhpZGRlblByb3BlcnRpZXMiLCJvYmoiLCJrZXkiLCJoYXNPd25Qcm9wZXJ0eSIsInRlc3QiLCJfYXV0aGVudGljYXRlVXNlckZyb21SZXF1ZXN0IiwicmVxIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJwYXlsb2FkIiwiYm9keSIsInVzZXJuYW1lIiwicXVlcnkiLCJlbWFpbCIsInBhc3N3b3JkIiwiUGFyc2UiLCJFcnJvciIsIlVTRVJOQU1FX01JU1NJTkciLCJQQVNTV09SRF9NSVNTSU5HIiwiT0JKRUNUX05PVF9GT1VORCIsInVzZXIiLCJpc1ZhbGlkUGFzc3dvcmQiLCIkb3IiLCJjb25maWciLCJkYXRhYmFzZSIsImZpbmQiLCJ0aGVuIiwicmVzdWx0cyIsImxlbmd0aCIsImxvZ2dlckNvbnRyb2xsZXIiLCJ3YXJuIiwiZmlsdGVyIiwicGFzc3dvcmRDcnlwdG8iLCJjb21wYXJlIiwiY29ycmVjdCIsImFjY291bnRMb2Nrb3V0UG9saWN5IiwiQWNjb3VudExvY2tvdXQiLCJoYW5kbGVMb2dpbkF0dGVtcHQiLCJhdXRoIiwiaXNNYXN0ZXIiLCJBQ0wiLCJPYmplY3QiLCJrZXlzIiwidmVyaWZ5VXNlckVtYWlscyIsInByZXZlbnRMb2dpbldpdGhVbnZlcmlmaWVkRW1haWwiLCJlbWFpbFZlcmlmaWVkIiwiRU1BSUxfTk9UX0ZPVU5EIiwiYXV0aERhdGEiLCJmb3JFYWNoIiwicHJvdmlkZXIiLCJjYXRjaCIsImVycm9yIiwiaGFuZGxlTWUiLCJpbmZvIiwic2Vzc2lvblRva2VuIiwiSU5WQUxJRF9TRVNTSU9OX1RPS0VOIiwicmVzdCIsIkF1dGgiLCJtYXN0ZXIiLCJpbmNsdWRlIiwiY2xpZW50U0RLIiwicmVzcG9uc2UiLCJoYW5kbGVMb2dJbiIsInJlcyIsInBhc3N3b3JkUG9saWN5IiwibWF4UGFzc3dvcmRBZ2UiLCJjaGFuZ2VkQXQiLCJfcGFzc3dvcmRfY2hhbmdlZF9hdCIsIkRhdGUiLCJ1cGRhdGUiLCJfZW5jb2RlIiwiX190eXBlIiwiaXNvIiwiZXhwaXJlc0F0IiwiZ2V0VGltZSIsInNlc3Npb25EYXRhIiwiY3JlYXRlU2Vzc2lvbiIsInVzZXJJZCIsIm9iamVjdElkIiwiY3JlYXRlZFdpdGgiLCJpbnN0YWxsYXRpb25JZCIsImZpbGVzQ29udHJvbGxlciIsImV4cGFuZEZpbGVzSW5PYmplY3QiLCJoYW5kbGVWZXJpZnlQYXNzd29yZCIsImhhbmRsZUxvZ091dCIsInN1Y2Nlc3MiLCJ1bmRlZmluZWQiLCJyZWNvcmRzIiwiZGVsIiwiX3Rocm93T25CYWRFbWFpbENvbmZpZyIsIkNvbmZpZyIsInZhbGlkYXRlRW1haWxDb25maWd1cmF0aW9uIiwiZW1haWxBZGFwdGVyIiwidXNlckNvbnRyb2xsZXIiLCJhZGFwdGVyIiwiYXBwTmFtZSIsInB1YmxpY1NlcnZlclVSTCIsImVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uIiwiZSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImhhbmRsZVJlc2V0UmVxdWVzdCIsIkVNQUlMX01JU1NJTkciLCJJTlZBTElEX0VNQUlMX0FERFJFU1MiLCJzZW5kUGFzc3dvcmRSZXNldEVtYWlsIiwiZXJyIiwiY29kZSIsImhhbmRsZVZlcmlmaWNhdGlvbkVtYWlsUmVxdWVzdCIsIk9USEVSX0NBVVNFIiwicmVnZW5lcmF0ZUVtYWlsVmVyaWZ5VG9rZW4iLCJzZW5kVmVyaWZpY2F0aW9uRW1haWwiLCJtb3VudFJvdXRlcyIsInJvdXRlIiwiaGFuZGxlRmluZCIsImhhbmRsZUNyZWF0ZSIsImhhbmRsZUdldCIsImhhbmRsZVVwZGF0ZSIsImhhbmRsZURlbGV0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFTyxNQUFNQSxXQUFO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QU87QUFBRSxhQUFPLEtBQUsrRyxZQUFMLENBQWtCL0csR0FBbEIsQ0FBUDtBQUFnQyxLQUFsRjtBQUNBLFNBQUswRyxLQUFMLENBQVcsS0FBWCxFQUFrQixRQUFsQixFQUE0QjFHLE9BQU87QUFBRSxhQUFPLEtBQUt5RCxXQUFMLENBQWlCekQsR0FBakIsQ0FBUDtBQUErQixLQUFwRTtBQUNBLFNBQUswRyxLQUFMLENBQVcsTUFBWCxFQUFtQixRQUFuQixFQUE2QjFHLE9BQU87QUFBRSxhQUFPLEtBQUt5RCxXQUFMLENBQWlCekQsR0FBakIsQ0FBUDtBQUErQixLQUFyRTtBQUNBLFNBQUswRyxLQUFMLENBQVcsTUFBWCxFQUFtQixTQUFuQixFQUE4QjFHLE9BQU87QUFBRSxhQUFPLEtBQUsrRSxZQUFMLENBQWtCL0UsR0FBbEIsQ0FBUDtBQUFnQyxLQUF2RTtBQUNBLFNBQUswRyxLQUFMLENBQVcsTUFBWCxFQUFtQix1QkFBbkIsRUFBNEMxRyxPQUFPO0FBQUUsYUFBTyxLQUFLK0Ysa0JBQUwsQ0FBd0IvRixHQUF4QixDQUFQO0FBQXNDLEtBQTNGO0FBQ0EsU0FBSzBHLEtBQUwsQ0FBVyxNQUFYLEVBQW1CLDJCQUFuQixFQUFnRDFHLE9BQU87QUFBRSxhQUFPLEtBQUtxRyw4QkFBTCxDQUFvQ3JHLEdBQXBDLENBQVA7QUFBa0QsS0FBM0c7QUFDQSxTQUFLMEcsS0FBTCxDQUFXLEtBQVgsRUFBa0IsaUJBQWxCLEVBQXFDMUcsT0FBTztBQUFFLGFBQU8sS0FBSzhFLG9CQUFMLENBQTBCOUUsR0FBMUIsQ0FBUDtBQUF3QyxLQUF0RjtBQUNEO0FBL1Q0Qzs7UUFBbENULFcsR0FBQUEsVyxFQVZiOztrQkE0VWVBLFciLCJmaWxlIjoiVXNlcnNSb3V0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGVzZSBtZXRob2RzIGhhbmRsZSB0aGUgVXNlci1yZWxhdGVkIHJvdXRlcy5cblxuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuaW1wb3J0IEFjY291bnRMb2Nrb3V0IGZyb20gJy4uL0FjY291bnRMb2Nrb3V0JztcbmltcG9ydCBDbGFzc2VzUm91dGVyIGZyb20gJy4vQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgcmVzdCBmcm9tICcuLi9yZXN0JztcbmltcG9ydCBBdXRoIGZyb20gJy4uL0F1dGgnO1xuaW1wb3J0IHBhc3N3b3JkQ3J5cHRvIGZyb20gJy4uL3Bhc3N3b3JkJztcblxuZXhwb3J0IGNsYXNzIFVzZXJzUm91dGVyIGV4dGVuZHMgQ2xhc3Nlc1JvdXRlciB7XG5cbiAgY2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnX1VzZXInO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYWxsIFwiX1wiIHByZWZpeGVkIHByb3BlcnRpZXMgZnJvbSBhbiBvYmplY3QsIGV4Y2VwdCBcIl9fdHlwZVwiXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogQW4gb2JqZWN0LlxuICAgKi9cbiAgc3RhdGljIHJlbW92ZUhpZGRlblByb3BlcnRpZXMob2JqKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIC8vIFJlZ2V4cCBjb21lcyBmcm9tIFBhcnNlLk9iamVjdC5wcm90b3R5cGUudmFsaWRhdGVcbiAgICAgICAgaWYgKGtleSAhPT0gXCJfX3R5cGVcIiAmJiAhKC9eW0EtWmEtel1bMC05QS1aYS16X10qJC8pLnRlc3Qoa2V5KSkge1xuICAgICAgICAgIGRlbGV0ZSBvYmpba2V5XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYSBwYXNzd29yZCByZXF1ZXN0IGluIGxvZ2luIGFuZCB2ZXJpZnlQYXNzd29yZFxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxIFRoZSByZXF1ZXN0XG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFVzZXIgb2JqZWN0XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfYXV0aGVudGljYXRlVXNlckZyb21SZXF1ZXN0KHJlcSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBVc2UgcXVlcnkgcGFyYW1ldGVycyBpbnN0ZWFkIGlmIHByb3ZpZGVkIGluIHVybFxuICAgICAgbGV0IHBheWxvYWQgPSByZXEuYm9keTtcbiAgICAgIGlmICghcGF5bG9hZC51c2VybmFtZSAmJiByZXEucXVlcnkudXNlcm5hbWUgfHwgIXBheWxvYWQuZW1haWwgJiYgcmVxLnF1ZXJ5LmVtYWlsKSB7XG4gICAgICAgIHBheWxvYWQgPSByZXEucXVlcnk7XG4gICAgICB9XG4gICAgICBjb25zdCB7XG4gICAgICAgIHVzZXJuYW1lLFxuICAgICAgICBlbWFpbCxcbiAgICAgICAgcGFzc3dvcmQsXG4gICAgICB9ID0gcGF5bG9hZDtcblxuICAgICAgLy8gVE9ETzogdXNlIHRoZSByaWdodCBlcnJvciBjb2RlcyAvIGRlc2NyaXB0aW9ucy5cbiAgICAgIGlmICghdXNlcm5hbWUgJiYgIWVtYWlsKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5VU0VSTkFNRV9NSVNTSU5HLCAndXNlcm5hbWUvZW1haWwgaXMgcmVxdWlyZWQuJyk7XG4gICAgICB9XG4gICAgICBpZiAoIXBhc3N3b3JkKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QQVNTV09SRF9NSVNTSU5HLCAncGFzc3dvcmQgaXMgcmVxdWlyZWQuJyk7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHBhc3N3b3JkICE9PSAnc3RyaW5nJ1xuICAgICAgICB8fCBlbWFpbCAmJiB0eXBlb2YgZW1haWwgIT09ICdzdHJpbmcnXG4gICAgICAgIHx8IHVzZXJuYW1lICYmIHR5cGVvZiB1c2VybmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdJbnZhbGlkIHVzZXJuYW1lL3Bhc3N3b3JkLicpO1xuICAgICAgfVxuXG4gICAgICBsZXQgdXNlcjtcbiAgICAgIGxldCBpc1ZhbGlkUGFzc3dvcmQgPSBmYWxzZTtcbiAgICAgIGxldCBxdWVyeTtcbiAgICAgIGlmIChlbWFpbCAmJiB1c2VybmFtZSkge1xuICAgICAgICBxdWVyeSA9IHsgZW1haWwsIHVzZXJuYW1lIH07XG4gICAgICB9IGVsc2UgaWYgKGVtYWlsKSB7XG4gICAgICAgIHF1ZXJ5ID0geyBlbWFpbCB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcXVlcnkgPSB7ICRvcjogW3sgdXNlcm5hbWUgfSwgeyBlbWFpbDogdXNlcm5hbWUgfV0gfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXEuY29uZmlnLmRhdGFiYXNlLmZpbmQoJ19Vc2VyJywgcXVlcnkpXG4gICAgICAgIC50aGVuKChyZXN1bHRzKSA9PiB7XG4gICAgICAgICAgaWYgKCFyZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdJbnZhbGlkIHVzZXJuYW1lL3Bhc3N3b3JkLicpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA+IDEpIHsgLy8gY29ybmVyIGNhc2Ugd2hlcmUgdXNlcjEgaGFzIHVzZXJuYW1lID09IHVzZXIyIGVtYWlsXG4gICAgICAgICAgICByZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIud2FybignVGhlcmUgaXMgYSB1c2VyIHdoaWNoIGVtYWlsIGlzIHRoZSBzYW1lIGFzIGFub3RoZXIgdXNlclxcJ3MgdXNlcm5hbWUsIGxvZ2dpbmcgaW4gYmFzZWQgb24gdXNlcm5hbWUnKTtcbiAgICAgICAgICAgIHVzZXIgPSByZXN1bHRzLmZpbHRlcigodXNlcikgPT4gdXNlci51c2VybmFtZSA9PT0gdXNlcm5hbWUpWzBdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1c2VyID0gcmVzdWx0c1swXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcGFzc3dvcmRDcnlwdG8uY29tcGFyZShwYXNzd29yZCwgdXNlci5wYXNzd29yZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKChjb3JyZWN0KSA9PiB7XG4gICAgICAgICAgaXNWYWxpZFBhc3N3b3JkID0gY29ycmVjdDtcbiAgICAgICAgICBjb25zdCBhY2NvdW50TG9ja291dFBvbGljeSA9IG5ldyBBY2NvdW50TG9ja291dCh1c2VyLCByZXEuY29uZmlnKTtcbiAgICAgICAgICByZXR1cm4gYWNjb3VudExvY2tvdXRQb2xpY3kuaGFuZGxlTG9naW5BdHRlbXB0KGlzVmFsaWRQYXNzd29yZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICBpZiAoIWlzVmFsaWRQYXNzd29yZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdJbnZhbGlkIHVzZXJuYW1lL3Bhc3N3b3JkLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBFbnN1cmUgdGhlIHVzZXIgaXNuJ3QgbG9ja2VkIG91dFxuICAgICAgICAgIC8vIEEgbG9ja2VkIG91dCB1c2VyIHdvbid0IGJlIGFibGUgdG8gbG9naW5cbiAgICAgICAgICAvLyBUbyBsb2NrIGEgdXNlciBvdXQsIGp1c3Qgc2V0IHRoZSBBQ0wgdG8gYG1hc3RlcktleWAgb25seSAgKHt9KS5cbiAgICAgICAgICAvLyBFbXB0eSBBQ0wgaXMgT0tcbiAgICAgICAgICBpZiAoIXJlcS5hdXRoLmlzTWFzdGVyICYmIHVzZXIuQUNMICYmIE9iamVjdC5rZXlzKHVzZXIuQUNMKS5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdJbnZhbGlkIHVzZXJuYW1lL3Bhc3N3b3JkLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocmVxLmNvbmZpZy52ZXJpZnlVc2VyRW1haWxzICYmIHJlcS5jb25maWcucHJldmVudExvZ2luV2l0aFVudmVyaWZpZWRFbWFpbCAmJiAhdXNlci5lbWFpbFZlcmlmaWVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRU1BSUxfTk9UX0ZPVU5ELCAnVXNlciBlbWFpbCBpcyBub3QgdmVyaWZpZWQuJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGVsZXRlIHVzZXIucGFzc3dvcmQ7XG5cbiAgICAgICAgICAvLyBTb21ldGltZXMgdGhlIGF1dGhEYXRhIHN0aWxsIGhhcyBudWxsIG9uIHRoYXQga2V5c1xuICAgICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wYXJzZS1jb21tdW5pdHkvcGFyc2Utc2VydmVyL2lzc3Vlcy85MzVcbiAgICAgICAgICBpZiAodXNlci5hdXRoRGF0YSkge1xuICAgICAgICAgICAgT2JqZWN0LmtleXModXNlci5hdXRoRGF0YSkuZm9yRWFjaCgocHJvdmlkZXIpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHVzZXIuYXV0aERhdGFbcHJvdmlkZXJdID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHVzZXIuYXV0aERhdGFbcHJvdmlkZXJdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChPYmplY3Qua2V5cyh1c2VyLmF1dGhEYXRhKS5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgICBkZWxldGUgdXNlci5hdXRoRGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh1c2VyKTtcbiAgICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlTWUocmVxKSB7XG4gICAgaWYgKCFyZXEuaW5mbyB8fCAhcmVxLmluZm8uc2Vzc2lvblRva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLCAnSW52YWxpZCBzZXNzaW9uIHRva2VuJyk7XG4gICAgfVxuICAgIGNvbnN0IHNlc3Npb25Ub2tlbiA9IHJlcS5pbmZvLnNlc3Npb25Ub2tlbjtcbiAgICByZXR1cm4gcmVzdC5maW5kKHJlcS5jb25maWcsIEF1dGgubWFzdGVyKHJlcS5jb25maWcpLCAnX1Nlc3Npb24nLFxuICAgICAgeyBzZXNzaW9uVG9rZW4gfSxcbiAgICAgIHsgaW5jbHVkZTogJ3VzZXInIH0sIHJlcS5pbmZvLmNsaWVudFNESylcbiAgICAgIC50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoIXJlc3BvbnNlLnJlc3VsdHMgfHxcbiAgICAgICAgICByZXNwb25zZS5yZXN1bHRzLmxlbmd0aCA9PSAwIHx8XG4gICAgICAgICAgIXJlc3BvbnNlLnJlc3VsdHNbMF0udXNlcikge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1NFU1NJT05fVE9LRU4sICdJbnZhbGlkIHNlc3Npb24gdG9rZW4nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB1c2VyID0gcmVzcG9uc2UucmVzdWx0c1swXS51c2VyO1xuICAgICAgICAgIC8vIFNlbmQgdG9rZW4gYmFjayBvbiB0aGUgbG9naW4sIGJlY2F1c2UgU0RLcyBleHBlY3QgdGhhdC5cbiAgICAgICAgICB1c2VyLnNlc3Npb25Ub2tlbiA9IHNlc3Npb25Ub2tlbjtcblxuICAgICAgICAgIC8vIFJlbW92ZSBoaWRkZW4gcHJvcGVydGllcy5cbiAgICAgICAgICBVc2Vyc1JvdXRlci5yZW1vdmVIaWRkZW5Qcm9wZXJ0aWVzKHVzZXIpO1xuXG4gICAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHVzZXIgfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBoYW5kbGVMb2dJbihyZXEpIHtcbiAgICBsZXQgdXNlcjtcbiAgICByZXR1cm4gdGhpcy5fYXV0aGVudGljYXRlVXNlckZyb21SZXF1ZXN0KHJlcSlcbiAgICAgIC50aGVuKChyZXMpID0+IHtcblxuICAgICAgICB1c2VyID0gcmVzO1xuXG4gICAgICAgIC8vIGhhbmRsZSBwYXNzd29yZCBleHBpcnkgcG9saWN5XG4gICAgICAgIGlmIChyZXEuY29uZmlnLnBhc3N3b3JkUG9saWN5ICYmIHJlcS5jb25maWcucGFzc3dvcmRQb2xpY3kubWF4UGFzc3dvcmRBZ2UpIHtcbiAgICAgICAgICBsZXQgY2hhbmdlZEF0ID0gdXNlci5fcGFzc3dvcmRfY2hhbmdlZF9hdDtcblxuICAgICAgICAgIGlmICghY2hhbmdlZEF0KSB7XG4gICAgICAgICAgICAvLyBwYXNzd29yZCB3YXMgY3JlYXRlZCBiZWZvcmUgZXhwaXJ5IHBvbGljeSB3YXMgZW5hYmxlZC5cbiAgICAgICAgICAgIC8vIHNpbXBseSB1cGRhdGUgX1VzZXIgb2JqZWN0IHNvIHRoYXQgaXQgd2lsbCBzdGFydCBlbmZvcmNpbmcgZnJvbSBub3dcbiAgICAgICAgICAgIGNoYW5nZWRBdCA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICByZXEuY29uZmlnLmRhdGFiYXNlLnVwZGF0ZSgnX1VzZXInLCB7IHVzZXJuYW1lOiB1c2VyLnVzZXJuYW1lIH0sXG4gICAgICAgICAgICAgIHsgX3Bhc3N3b3JkX2NoYW5nZWRfYXQ6IFBhcnNlLl9lbmNvZGUoY2hhbmdlZEF0KSB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY2hlY2sgd2hldGhlciB0aGUgcGFzc3dvcmQgaGFzIGV4cGlyZWRcbiAgICAgICAgICAgIGlmIChjaGFuZ2VkQXQuX190eXBlID09ICdEYXRlJykge1xuICAgICAgICAgICAgICBjaGFuZ2VkQXQgPSBuZXcgRGF0ZShjaGFuZ2VkQXQuaXNvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZXhwaXJ5IHRpbWUuXG4gICAgICAgICAgICBjb25zdCBleHBpcmVzQXQgPSBuZXcgRGF0ZShjaGFuZ2VkQXQuZ2V0VGltZSgpICsgODY0MDAwMDAgKiByZXEuY29uZmlnLnBhc3N3b3JkUG9saWN5Lm1heFBhc3N3b3JkQWdlKTtcbiAgICAgICAgICAgIGlmIChleHBpcmVzQXQgPCBuZXcgRGF0ZSgpKSAvLyBmYWlsIG9mIGN1cnJlbnQgdGltZSBpcyBwYXN0IHBhc3N3b3JkIGV4cGlyeSB0aW1lXG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnWW91ciBwYXNzd29yZCBoYXMgZXhwaXJlZC4gUGxlYXNlIHJlc2V0IHlvdXIgcGFzc3dvcmQuJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIGhpZGRlbiBwcm9wZXJ0aWVzLlxuICAgICAgICBVc2Vyc1JvdXRlci5yZW1vdmVIaWRkZW5Qcm9wZXJ0aWVzKHVzZXIpO1xuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBzZXNzaW9uRGF0YSxcbiAgICAgICAgICBjcmVhdGVTZXNzaW9uXG4gICAgICAgIH0gPSBBdXRoLmNyZWF0ZVNlc3Npb24ocmVxLmNvbmZpZywge1xuICAgICAgICAgIHVzZXJJZDogdXNlci5vYmplY3RJZCwgY3JlYXRlZFdpdGg6IHtcbiAgICAgICAgICAgICdhY3Rpb24nOiAnbG9naW4nLFxuICAgICAgICAgICAgJ2F1dGhQcm92aWRlcic6ICdwYXNzd29yZCdcbiAgICAgICAgICB9LCBpbnN0YWxsYXRpb25JZDogcmVxLmluZm8uaW5zdGFsbGF0aW9uSWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdXNlci5zZXNzaW9uVG9rZW4gPSBzZXNzaW9uRGF0YS5zZXNzaW9uVG9rZW47XG5cbiAgICAgICAgcmVxLmNvbmZpZy5maWxlc0NvbnRyb2xsZXIuZXhwYW5kRmlsZXNJbk9iamVjdChyZXEuY29uZmlnLCB1c2VyKTtcblxuICAgICAgICByZXR1cm4gY3JlYXRlU2Vzc2lvbigpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHVzZXIgfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlVmVyaWZ5UGFzc3dvcmQocmVxKSB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dGhlbnRpY2F0ZVVzZXJGcm9tUmVxdWVzdChyZXEpXG4gICAgICAudGhlbigodXNlcikgPT4ge1xuXG4gICAgICAgIC8vIFJlbW92ZSBoaWRkZW4gcHJvcGVydGllcy5cbiAgICAgICAgVXNlcnNSb3V0ZXIucmVtb3ZlSGlkZGVuUHJvcGVydGllcyh1c2VyKTtcblxuICAgICAgICByZXR1cm4geyByZXNwb25zZTogdXNlciB9O1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSk7XG4gIH1cblxuICBoYW5kbGVMb2dPdXQocmVxKSB7XG4gICAgY29uc3Qgc3VjY2VzcyA9IHsgcmVzcG9uc2U6IHt9IH07XG4gICAgaWYgKHJlcS5pbmZvICYmIHJlcS5pbmZvLnNlc3Npb25Ub2tlbikge1xuICAgICAgcmV0dXJuIHJlc3QuZmluZChyZXEuY29uZmlnLCBBdXRoLm1hc3RlcihyZXEuY29uZmlnKSwgJ19TZXNzaW9uJyxcbiAgICAgICAgeyBzZXNzaW9uVG9rZW46IHJlcS5pbmZvLnNlc3Npb25Ub2tlbiB9LCB1bmRlZmluZWQsIHJlcS5pbmZvLmNsaWVudFNES1xuICAgICAgKS50aGVuKChyZWNvcmRzKSA9PiB7XG4gICAgICAgIGlmIChyZWNvcmRzLnJlc3VsdHMgJiYgcmVjb3Jkcy5yZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybiByZXN0LmRlbChyZXEuY29uZmlnLCBBdXRoLm1hc3RlcihyZXEuY29uZmlnKSwgJ19TZXNzaW9uJyxcbiAgICAgICAgICAgIHJlY29yZHMucmVzdWx0c1swXS5vYmplY3RJZFxuICAgICAgICAgICkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHN1Y2Nlc3MpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc3VjY2Vzcyk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShzdWNjZXNzKTtcbiAgfVxuXG4gIF90aHJvd09uQmFkRW1haWxDb25maWcocmVxKSB7XG4gICAgdHJ5IHtcbiAgICAgIENvbmZpZy52YWxpZGF0ZUVtYWlsQ29uZmlndXJhdGlvbih7XG4gICAgICAgIGVtYWlsQWRhcHRlcjogcmVxLmNvbmZpZy51c2VyQ29udHJvbGxlci5hZGFwdGVyLFxuICAgICAgICBhcHBOYW1lOiByZXEuY29uZmlnLmFwcE5hbWUsXG4gICAgICAgIHB1YmxpY1NlcnZlclVSTDogcmVxLmNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwsXG4gICAgICAgIGVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uOiByZXEuY29uZmlnLmVtYWlsVmVyaWZ5VG9rZW5WYWxpZGl0eUR1cmF0aW9uXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAodHlwZW9mIGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIC8vIE1heWJlIHdlIG5lZWQgYSBCYWQgQ29uZmlndXJhdGlvbiBlcnJvciwgYnV0IHRoZSBTREtzIHdvbid0IHVuZGVyc3RhbmQgaXQuIEZvciBub3csIEludGVybmFsIFNlcnZlciBFcnJvci5cbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0FuIGFwcE5hbWUsIHB1YmxpY1NlcnZlclVSTCwgYW5kIGVtYWlsQWRhcHRlciBhcmUgcmVxdWlyZWQgZm9yIHBhc3N3b3JkIHJlc2V0IGFuZCBlbWFpbCB2ZXJpZmljYXRpb24gZnVuY3Rpb25hbGl0eS4nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlUmVzZXRSZXF1ZXN0KHJlcSkge1xuICAgIHRoaXMuX3Rocm93T25CYWRFbWFpbENvbmZpZyhyZXEpO1xuXG4gICAgY29uc3QgeyBlbWFpbCB9ID0gcmVxLmJvZHk7XG4gICAgaWYgKCFlbWFpbCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkVNQUlMX01JU1NJTkcsIFwieW91IG11c3QgcHJvdmlkZSBhbiBlbWFpbFwiKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBlbWFpbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0VNQUlMX0FERFJFU1MsICd5b3UgbXVzdCBwcm92aWRlIGEgdmFsaWQgZW1haWwgc3RyaW5nJyk7XG4gICAgfVxuICAgIGNvbnN0IHVzZXJDb250cm9sbGVyID0gcmVxLmNvbmZpZy51c2VyQ29udHJvbGxlcjtcbiAgICByZXR1cm4gdXNlckNvbnRyb2xsZXIuc2VuZFBhc3N3b3JkUmVzZXRFbWFpbChlbWFpbCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgcmVzcG9uc2U6IHt9XG4gICAgICB9KTtcbiAgICB9LCBlcnIgPT4ge1xuICAgICAgaWYgKGVyci5jb2RlID09PSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5FTUFJTF9OT1RfRk9VTkQsIGBObyB1c2VyIGZvdW5kIHdpdGggZW1haWwgJHtlbWFpbH0uYCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBoYW5kbGVWZXJpZmljYXRpb25FbWFpbFJlcXVlc3QocmVxKSB7XG4gICAgdGhpcy5fdGhyb3dPbkJhZEVtYWlsQ29uZmlnKHJlcSk7XG5cbiAgICBjb25zdCB7IGVtYWlsIH0gPSByZXEuYm9keTtcbiAgICBpZiAoIWVtYWlsKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRU1BSUxfTUlTU0lORywgJ3lvdSBtdXN0IHByb3ZpZGUgYW4gZW1haWwnKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBlbWFpbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0VNQUlMX0FERFJFU1MsICd5b3UgbXVzdCBwcm92aWRlIGEgdmFsaWQgZW1haWwgc3RyaW5nJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCB7IGVtYWlsOiBlbWFpbCB9KS50aGVuKChyZXN1bHRzKSA9PiB7XG4gICAgICBpZiAoIXJlc3VsdHMubGVuZ3RoIHx8IHJlc3VsdHMubGVuZ3RoIDwgMSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRU1BSUxfTk9UX0ZPVU5ELCBgTm8gdXNlciBmb3VuZCB3aXRoIGVtYWlsICR7ZW1haWx9YCk7XG4gICAgICB9XG4gICAgICBjb25zdCB1c2VyID0gcmVzdWx0c1swXTtcblxuICAgICAgLy8gcmVtb3ZlIHBhc3N3b3JkIGZpZWxkLCBtZXNzZXMgd2l0aCBzYXZpbmcgb24gcG9zdGdyZXNcbiAgICAgIGRlbGV0ZSB1c2VyLnBhc3N3b3JkO1xuXG4gICAgICBpZiAodXNlci5lbWFpbFZlcmlmaWVkKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PVEhFUl9DQVVTRSwgYEVtYWlsICR7ZW1haWx9IGlzIGFscmVhZHkgdmVyaWZpZWQuYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHVzZXJDb250cm9sbGVyID0gcmVxLmNvbmZpZy51c2VyQ29udHJvbGxlcjtcbiAgICAgIHJldHVybiB1c2VyQ29udHJvbGxlci5yZWdlbmVyYXRlRW1haWxWZXJpZnlUb2tlbih1c2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgdXNlckNvbnRyb2xsZXIuc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHVzZXIpO1xuICAgICAgICByZXR1cm4geyByZXNwb25zZToge30gfTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3VzZXJzJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlRmluZChyZXEpOyB9KTtcbiAgICB0aGlzLnJvdXRlKCdQT1NUJywgJy91c2VycycsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZUNyZWF0ZShyZXEpOyB9KTtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3VzZXJzL21lJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlTWUocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy91c2Vycy86b2JqZWN0SWQnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVHZXQocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUFVUJywgJy91c2Vycy86b2JqZWN0SWQnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVVcGRhdGUocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnREVMRVRFJywgJy91c2Vycy86b2JqZWN0SWQnLCByZXEgPT4geyByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9sb2dpbicsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZUxvZ0luKHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2xvZ2luJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlTG9nSW4ocmVxKTsgfSk7XG4gICAgdGhpcy5yb3V0ZSgnUE9TVCcsICcvbG9nb3V0JywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlTG9nT3V0KHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL3JlcXVlc3RQYXNzd29yZFJlc2V0JywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlUmVzZXRSZXF1ZXN0KHJlcSk7IH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL3ZlcmlmaWNhdGlvbkVtYWlsUmVxdWVzdCcsIHJlcSA9PiB7IHJldHVybiB0aGlzLmhhbmRsZVZlcmlmaWNhdGlvbkVtYWlsUmVxdWVzdChyZXEpOyB9KTtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL3ZlcmlmeVBhc3N3b3JkJywgcmVxID0+IHsgcmV0dXJuIHRoaXMuaGFuZGxlVmVyaWZ5UGFzc3dvcmQocmVxKTsgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgVXNlcnNSb3V0ZXI7XG4iXX0= \ No newline at end of file diff --git a/lib/StatusHandler.js b/lib/StatusHandler.js index 1abf9778a2..f5d6ef4f55 100644 --- a/lib/StatusHandler.js +++ b/lib/StatusHandler.js @@ -321,4 +321,5 @@ function pushStatusHandler(config, existingObjectId) { }); return Object.freeze(rval); -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9TdGF0dXNIYW5kbGVyLmpzIl0sIm5hbWVzIjpbImZsYXR0ZW4iLCJqb2JTdGF0dXNIYW5kbGVyIiwicHVzaFN0YXR1c0hhbmRsZXIiLCJQVVNIX1NUQVRVU19DT0xMRUNUSU9OIiwiSk9CX1NUQVRVU19DT0xMRUNUSU9OIiwiaW5jcmVtZW50T3AiLCJvYmplY3QiLCJrZXkiLCJhbW91bnQiLCJfX29wIiwiYXJyYXkiLCJmbGF0dGVuZWQiLCJpIiwibGVuZ3RoIiwiQXJyYXkiLCJpc0FycmF5IiwiY29uY2F0IiwicHVzaCIsInN0YXR1c0hhbmRsZXIiLCJjbGFzc05hbWUiLCJkYXRhYmFzZSIsImxhc3RQcm9taXNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJjcmVhdGUiLCJ0aGVuIiwidXBkYXRlIiwid2hlcmUiLCJPYmplY3QiLCJmcmVlemUiLCJyZXN0U3RhdHVzSGFuZGxlciIsImNvbmZpZyIsImF1dGgiLCJBdXRoIiwibWFzdGVyIiwicmVzdCIsInJlc3BvbnNlIiwiYXNzaWduIiwib2JqZWN0SWQiLCJqb2JTdGF0dXMiLCJvYmplY3RJZFNpemUiLCJoYW5kbGVyIiwic2V0UnVubmluZyIsImpvYk5hbWUiLCJwYXJhbXMiLCJub3ciLCJEYXRlIiwic3RhdHVzIiwic291cmNlIiwiY3JlYXRlZEF0IiwiQUNMIiwic2V0TWVzc2FnZSIsIm1lc3NhZ2UiLCJzZXRTdWNjZWVkZWQiLCJzZXRGaW5hbFN0YXR1cyIsInNldEZhaWxlZCIsInVuZGVmaW5lZCIsImZpbmlzaGVkQXQiLCJleGlzdGluZ09iamVjdElkIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJib2R5Iiwib3B0aW9ucyIsInB1c2hUaW1lIiwidG9JU09TdHJpbmciLCJoYXNPd25Qcm9wZXJ0eSIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0IiwicHVzaF90aW1lIiwibG9nZ2VyIiwid2FybiIsImRhdGEiLCJwYXlsb2FkU3RyaW5nIiwiSlNPTiIsInN0cmluZ2lmeSIsInB1c2hIYXNoIiwiYWxlcnQiLCJxdWVyeSIsInBheWxvYWQiLCJ0aXRsZSIsImV4cGlyeSIsImV4cGlyYXRpb25fdGltZSIsImV4cGlyYXRpb25faW50ZXJ2YWwiLCJudW1TZW50IiwicmVzdWx0IiwiYmF0Y2hlcyIsInZlcmJvc2UiLCJjb3VudCIsInRyYWNrU2VudCIsInJlc3VsdHMiLCJVVENPZmZzZXQiLCJjbGVhbnVwSW5zdGFsbGF0aW9ucyIsInByb2Nlc3MiLCJlbnYiLCJQQVJTRV9TRVJWRVJfQ0xFQU5VUF9JTlZBTElEX0lOU1RBTExBVElPTlMiLCJudW1GYWlsZWQiLCJkZXZpY2VzVG9SZW1vdmUiLCJyZWR1Y2UiLCJtZW1vIiwiZGV2aWNlIiwiZGV2aWNlVHlwZSIsInRyYW5zbWl0dGVkIiwib2Zmc2V0S2V5IiwiZXJyb3IiLCJkZXZpY2VUb2tlbiIsInRva2VuIiwiZm9yRWFjaCIsImluZm8iLCJhY2wiLCJtYW55IiwicmVzIiwiY29tcGxldGUiLCJmYWlsIiwiZXJyIiwiZXJyb3JNZXNzYWdlIiwicnZhbCIsImRlZmluZVByb3BlcnR5IiwiZ2V0Il0sIm1hcHBpbmdzIjoiOzs7OztRQWlCZ0JBLE8sR0FBQUEsTztRQXFFQUMsZ0IsR0FBQUEsZ0I7UUFxREFDLGlCLEdBQUFBLGlCOztBQTNJaEI7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBRUEsTUFBTUMseUJBQXlCLGFBQS9CO0FBQ0EsTUFBTUMsd0JBQXdCLFlBQTlCOztBQUVBLE1BQU1DLGNBQWMsVUFBU0MsU0FBUyxFQUFsQixFQUFzQkMsR0FBdEIsRUFBMkJDLFNBQVMsQ0FBcEMsRUFBdUM7QUFDekQsTUFBSSxDQUFDRixPQUFPQyxHQUFQLENBQUwsRUFBa0I7QUFDaEJELFdBQU9DLEdBQVAsSUFBYyxFQUFDRSxNQUFNLFdBQVAsRUFBb0JELFFBQVFBLE1BQTVCLEVBQWQ7QUFDRCxHQUZELE1BRU87QUFDTEYsV0FBT0MsR0FBUCxFQUFZQyxNQUFaLElBQXNCQSxNQUF0QjtBQUNEO0FBQ0QsU0FBT0YsT0FBT0MsR0FBUCxDQUFQO0FB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WSxRQUFGLEVBQWYsRUFBNkJaLE1BQTdCLENBQVA7QUFDRCxHQVREOztBQVdBLFFBQU13RixPQUFPO0FBQ1h0RCxjQURXO0FBRVhsQixjQUZXO0FBR1g2QyxhQUhXO0FBSVh1QixZQUpXO0FBS1hDO0FBTFcsR0FBYjs7QUFRQTtBQUNBbkYsU0FBT3VGLGNBQVAsQ0FBc0JELElBQXRCLEVBQTRCLFVBQTVCLEVBQXdDO0FBQ3RDRSxTQUFLLE1BQU05RTtBQUQyQixHQUF4Qzs7QUFJQSxTQUFPVixPQUFPQyxNQUFQLENBQWNxRixJQUFkLENBQVA7QUFDRCIsImZpbGUiOiJTdGF0dXNIYW5kbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbWQ1SGFzaCwgbmV3T2JqZWN0SWQgfSBmcm9tICcuL2NyeXB0b1V0aWxzJztcbmltcG9ydCB7IGxvZ2dlciB9ICAgICAgICAgICAgICAgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHJlc3QgICAgICAgICAgICAgICAgICAgICBmcm9tICcuL3Jlc3QnO1xuaW1wb3J0IEF1dGggICAgICAgICAgICAgICAgICAgICBmcm9tICcuL0F1dGgnO1xuXG5jb25zdCBQVVNIX1NUQVRVU19DT0xMRUNUSU9OID0gJ19QdXNoU3RhdHVzJztcbmNvbnN0IEpPQl9TVEFUVVNfQ09MTEVDVElPTiA9ICdfSm9iU3RhdHVzJztcblxuY29uc3QgaW5jcmVtZW50T3AgPSBmdW5jdGlvbihvYmplY3QgPSB7fSwga2V5LCBhbW91bnQgPSAxKSB7XG4gIGlmICghb2JqZWN0W2tleV0pIHtcbiAgICBvYmplY3Rba2V5XSA9IHtfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBhbW91bnR9XG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0W2tleV0uYW1vdW50ICs9IGFtb3VudDtcbiAgfVxuICByZXR1cm4gb2JqZWN0W2tleV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuKGFycmF5KSB7XG4gIHZhciBmbGF0dGVuZWQgPSBbXTtcbiAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShhcnJheVtpXSkpIHtcbiAgICAgIGZsYXR0ZW5lZCA9IGZsYXR0ZW5lZC5jb25jYXQoZmxhdHRlbihhcnJheVtpXSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmbGF0dGVuZWQucHVzaChhcnJheVtpXSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBmbGF0dGVuZWQ7XG59XG5cbmZ1bmN0aW9uIHN0YXR1c0hhbmRsZXIoY2xhc3NOYW1lLCBkYXRhYmFzZSkge1xuICBsZXQgbGFzdFByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICBmdW5jdGlvbiBjcmVhdGUob2JqZWN0KSB7XG4gICAgbGFzdFByb21pc2UgPSBsYXN0UHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBkYXRhYmFzZS5jcmVhdGUoY2xhc3NOYW1lLCBvYmplY3QpLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG9iamVjdCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGUod2hlcmUsIG9iamVjdCkge1xuICAgIGxhc3RQcm9taXNlID0gbGFzdFByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gZGF0YWJhc2UudXBkYXRlKGNsYXNzTmFtZSwgd2hlcmUsIG9iamVjdCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGxhc3RQcm9taXNlO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoe1xuICAgIGNyZWF0ZSxcbiAgICB1cGRhdGVcbiAgfSlcbn1cblxuZnVuY3Rpb24gcmVzdFN0YXR1c0hhbmRsZXIoY2xhc3NOYW1lLCBjb25maWcpIHtcbiAgbGV0IGxhc3RQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIGNvbnN0IGF1dGggPSBBdXRoLm1hc3Rlcihjb25maWcpO1xuICBmdW5jdGlvbiBjcmVhdGUob2JqZWN0KSB7XG4gICAgbGFzdFByb21pc2UgPSBsYXN0UHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiByZXN0LmNyZWF0ZShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgb2JqZWN0KVxuICAgICAgICAudGhlbigoeyByZXNwb25zZSB9KSA9PiB7XG4gICAgICAgICAgLy8gbWVyZ2UgdGhlIG9iamVjdHNcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKE9iamVjdC5hc3NpZ24oe30sIG9iamVjdCwgcmVzcG9uc2UpKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGxhc3RQcm9taXNlO1xuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlKHdoZXJlLCBvYmplY3QpIHtcbiAgICAvLyBUT0RPOiB3aGVuIHdlIGhhdmUgdXBkYXRlV2hlcmUsIHVzZSB0aGF0IGZvciBwcm9wZXIgaW50ZXJmYWNpbmdcbiAgICBsYXN0UHJvbWlzZSA9IGxhc3RQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHJlc3QudXBkYXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCB7IG9iamVjdElkOiB3aGVyZS5vYmplY3RJZCB9LCBvYmplY3QpXG4gICAgICAgIC50aGVuKCh7IHJlc3BvbnNlIH0pID0+IHtcbiAgICAgICAgICAvLyBtZXJnZSB0aGUgb2JqZWN0c1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoT2JqZWN0LmFzc2lnbih7fSwgb2JqZWN0LCByZXNwb25zZSkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdFByb21pc2U7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgY3JlYXRlLFxuICAgIHVwZGF0ZVxuICB9KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gam9iU3RhdHVzSGFuZGxlcihjb25maWcpIHtcbiAgbGV0IGpvYlN0YXR1cztcbiAgY29uc3Qgb2JqZWN0SWQgPSBuZXdPYmplY3RJZChjb25maWcub2JqZWN0SWRTaXplKTtcbiAgY29uc3QgZGF0YWJhc2UgPSBjb25maWcuZGF0YWJhc2U7XG4gIGNvbnN0IGhhbmRsZXIgPSBzdGF0dXNIYW5kbGVyKEpPQl9TVEFUVVNfQ09MTEVDVElPTiwgZGF0YWJhc2UpO1xuICBjb25zdCBzZXRSdW5uaW5nID0gZnVuY3Rpb24oam9iTmFtZSwgcGFyYW1zKSB7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICBqb2JTdGF0dXMgPSB7XG4gICAgICBvYmplY3RJZCxcbiAgICAgIGpvYk5hbWUsXG4gICAgICBwYXJhbXMsXG4gICAgICBzdGF0dXM6ICdydW5uaW5nJyxcbiAgICAgIHNvdXJjZTogJ2FwaScsXG4gICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgIC8vIGxvY2tkb3duIVxuICAgICAgQUNMOiB7fVxuICAgIH1cblxuICAgIHJldHVybiBoYW5kbGVyLmNyZWF0ZShqb2JTdGF0dXMpO1xuICB9XG5cbiAgY29uc3Qgc2V0TWVzc2FnZSA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICBpZiAoIW1lc3NhZ2UgfHwgdHlwZW9mIG1lc3NhZ2UgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHJldHVybiBoYW5kbGVyLnVwZGF0ZSh7IG9iamVjdElkIH0sIHsgbWVzc2FnZSB9KTtcbiAgfVxuXG4gIGNvbnN0IHNldFN1Y2NlZWRlZCA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICByZXR1cm4gc2V0RmluYWxTdGF0dXMoJ3N1Y2NlZWRlZCcsIG1lc3NhZ2UpO1xuICB9XG5cbiAgY29uc3Qgc2V0RmFpbGVkID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgIHJldHVybiBzZXRGaW5hbFN0YXR1cygnZmFpbGVkJywgbWVzc2FnZSk7XG4gIH1cblxuICBjb25zdCBzZXRGaW5hbFN0YXR1cyA9IGZ1bmN0aW9uKHN0YXR1cywgbWVzc2FnZSA9IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IGZpbmlzaGVkQXQgPSBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IHVwZGF0ZSA9IHsgc3RhdHVzLCBmaW5pc2hlZEF0IH07XG4gICAgaWYgKG1lc3NhZ2UgJiYgdHlwZW9mIG1lc3NhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICB1cGRhdGUubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgfVxuICAgIHJldHVybiBoYW5kbGVyLnVwZGF0ZSh7IG9iamVjdElkIH0sIHVwZGF0ZSk7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgc2V0UnVubmluZyxcbiAgICBzZXRTdWNjZWVkZWQsXG4gICAgc2V0TWVzc2FnZSxcbiAgICBzZXRGYWlsZWRcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwdXNoU3RhdHVzSGFuZGxlcihjb25maWcsIGV4aXN0aW5nT2JqZWN0SWQpIHtcblxuICBsZXQgcHVzaFN0YXR1cztcbiAgY29uc3QgZGF0YWJhc2UgPSBjb25maWcuZGF0YWJhc2U7XG4gIGNvbnN0IGhhbmRsZXIgPSByZXN0U3RhdHVzSGFuZGxlcihQVVNIX1NUQVRVU19DT0xMRUNUSU9OLCBjb25maWcpO1xuICBsZXQgb2JqZWN0SWQgPSBleGlzdGluZ09iamVjdElkO1xuICBjb25zdCBzZXRJbml0aWFsID0gZnVuY3Rpb24oYm9keSA9IHt9LCB3aGVyZSwgb3B0aW9ucyA9IHtzb3VyY2U6ICdyZXN0J30pIHtcbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIGxldCBwdXNoVGltZSA9IG5vdy50b0lTT1N0cmluZygpO1xuICAgIGxldCBzdGF0dXMgPSAncGVuZGluZyc7XG4gICAgaWYgKGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpKSB7XG4gICAgICBpZiAoY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0KSB7XG4gICAgICAgIHB1c2hUaW1lID0gYm9keS5wdXNoX3RpbWU7XG4gICAgICAgIHN0YXR1cyA9ICdzY2hlZHVsZWQnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1RyeWluZyB0byBzY2hlZHVsZSBhIHB1c2ggd2hpbGUgc2VydmVyIGlzIG5vdCBjb25maWd1cmVkLicpO1xuICAgICAgICBsb2dnZXIud2FybignUHVzaCB3aWxsIGJlIHNlbnQgaW1tZWRpYXRlbHknKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBkYXRhID0gIGJvZHkuZGF0YSB8fCB7fTtcbiAgICBjb25zdCBwYXlsb2FkU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgbGV0IHB1c2hIYXNoO1xuICAgIGlmICh0eXBlb2YgZGF0YS5hbGVydCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHB1c2hIYXNoID0gbWQ1SGFzaChkYXRhLmFsZXJ0KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLmFsZXJ0ID09PSAnb2JqZWN0Jykge1xuICAgICAgcHVzaEhhc2ggPSBtZDVIYXNoKEpTT04uc3RyaW5naWZ5KGRhdGEuYWxlcnQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHVzaEhhc2ggPSAnZDQxZDhjZDk4ZjAwYjIwNGU5ODAwOTk4ZWNmODQyN2UnO1xuICAgIH1cbiAgICBjb25zdCBvYmplY3QgPSB7XG4gICAgICBwdXNoVGltZSxcbiAgICAgIHF1ZXJ5OiBKU09OLnN0cmluZ2lmeSh3aGVyZSksXG4gICAgICBwYXlsb2FkOiBwYXlsb2FkU3RyaW5nLFxuICAgICAgc291cmNlOiBvcHRpb25zLnNvdXJjZSxcbiAgICAgIHRpdGxlOiBvcHRpb25zLnRpdGxlLFxuICAgICAgZXhwaXJ5OiBib2R5LmV4cGlyYXRpb25fdGltZSxcbiAgICAgIGV4cGlyYXRpb25faW50ZXJ2YWw6IGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCxcbiAgICAgIHN0YXR1czogc3RhdHVzLFxuICAgICAgbnVtU2VudDogMCxcbiAgICAgIHB1c2hIYXNoLFxuICAgICAgLy8gbG9ja2Rvd24hXG4gICAgICBBQ0w6IHt9XG4gICAgfVxuICAgIHJldHVybiBoYW5kbGVyLmNyZWF0ZShvYmplY3QpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgb2JqZWN0SWQgPSByZXN1bHQub2JqZWN0SWQ7XG4gICAgICBwdXNoU3RhdHVzID0ge1xuICAgICAgICBvYmplY3RJZFxuICAgICAgfTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocHVzaFN0YXR1cyk7XG4gICAgfSk7XG4gIH1cblxuICBjb25zdCBzZXRSdW5uaW5nID0gZnVuY3Rpb24oYmF0Y2hlcykge1xuICAgIGxvZ2dlci52ZXJib3NlKGBfUHVzaFN0YXR1cyAke29iamVjdElkfTogc2VuZGluZyBwdXNoIHRvIGluc3RhbGxhdGlvbnMgd2l0aCAlZCBiYXRjaGVzYCwgYmF0Y2hlcyk7XG4gICAgcmV0dXJuIGhhbmRsZXIudXBkYXRlKFxuICAgICAge1xuICAgICAgICBzdGF0dXM6XCJwZW5kaW5nXCIsXG4gICAgICAgIG9iamVjdElkOiBvYmplY3RJZFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgc3RhdHVzOiBcInJ1bm5pbmdcIixcbiAgICAgICAgY291bnQ6IGJhdGNoZXNcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgY29uc3QgdHJhY2tTZW50ID0gZnVuY3Rpb24ocmVzdWx0cywgVVRDT2Zmc2V0LCBjbGVhbnVwSW5zdGFsbGF0aW9ucyA9IHByb2Nlc3MuZW52LlBBUlNFX1NFUlZFUl9DTEVBTlVQX0lOVkFMSURfSU5TVEFMTEFUSU9OUykge1xuICAgIGNvbnN0IHVwZGF0ZSA9IHtcbiAgICAgIG51bVNlbnQ6IDAsXG4gICAgICBudW1GYWlsZWQ6IDBcbiAgICB9O1xuICAgIGNvbnN0IGRldmljZXNUb1JlbW92ZSA9IFtdO1xuICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdHMpKSB7XG4gICAgICByZXN1bHRzID0gZmxhdHRlbihyZXN1bHRzKTtcbiAgICAgIHJlc3VsdHMucmVkdWNlKChtZW1vLCByZXN1bHQpID0+IHtcbiAgICAgICAgLy8gQ2Fubm90IGhhbmRsZSB0aGF0XG4gICAgICAgIGlmICghcmVzdWx0IHx8ICFyZXN1bHQuZGV2aWNlIHx8ICFyZXN1bHQuZGV2aWNlLmRldmljZVR5cGUpIHtcbiAgICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZXZpY2VUeXBlID0gcmVzdWx0LmRldmljZS5kZXZpY2VUeXBlO1xuICAgICAgICBjb25zdCBrZXkgPSByZXN1bHQudHJhbnNtaXR0ZWQgPyBgc2VudFBlclR5cGUuJHtkZXZpY2VUeXBlfWAgOiBgZmFpbGVkUGVyVHlwZS4ke2RldmljZVR5cGV9YDtcbiAgICAgICAgbWVtb1trZXldID0gaW5jcmVtZW50T3AobWVtbywga2V5KTtcbiAgICAgICAgaWYgKHR5cGVvZiBVVENPZmZzZXQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgY29uc3Qgb2Zmc2V0S2V5ID0gcmVzdWx0LnRyYW5zbWl0dGVkID8gYHNlbnRQZXJVVENPZmZzZXQuJHtVVENPZmZzZXR9YCA6IGBmYWlsZWRQZXJVVENPZmZzZXQuJHtVVENPZmZzZXR9YDtcbiAgICAgICAgICBtZW1vW29mZnNldEtleV0gPSBpbmNyZW1lbnRPcChtZW1vLCBvZmZzZXRLZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHQudHJhbnNtaXR0ZWQpIHtcbiAgICAgICAgICBtZW1vLm51bVNlbnQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAocmVzdWx0ICYmIHJlc3VsdC5yZXNwb25zZSAmJiByZXN1bHQucmVzcG9uc2UuZXJyb3IgJiYgcmVzdWx0LmRldmljZSAmJiByZXN1bHQuZGV2aWNlLmRldmljZVRva2VuKSB7XG4gICAgICAgICAgICBjb25zdCB0b2tlbiA9IHJlc3VsdC5kZXZpY2UuZGV2aWNlVG9rZW47XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHJlc3VsdC5yZXNwb25zZS5lcnJvcjtcbiAgICAgICAgICAgIC8vIEdDTSBlcnJvcnNcbiAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ05vdFJlZ2lzdGVyZWQnIHx8IGVycm9yID09PSAnSW52YWxpZFJlZ2lzdHJhdGlvbicpIHtcbiAgICAgICAgICAgICAgZGV2aWNlc1RvUmVtb3ZlLnB1c2godG9rZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQVBOUyBlcnJvcnNcbiAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ1VucmVnaXN0ZXJlZCcgfHwgZXJyb3IgPT09ICdCYWREZXZpY2VUb2tlbicpIHtcbiAgICAgICAgICAgICAgZGV2aWNlc1RvUmVtb3ZlLnB1c2godG9rZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBtZW1vLm51bUZhaWxlZCsrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgfSwgdXBkYXRlKTtcbiAgICB9XG5cbiAgICBsb2dnZXIudmVyYm9zZShgX1B1c2hTdGF0dXMgJHtvYmplY3RJZH06IHNlbnQgcHVzaCEgJWQgc3VjY2VzcywgJWQgZmFpbHVyZXNgLCB1cGRhdGUubnVtU2VudCwgdXBkYXRlLm51bUZhaWxlZCk7XG4gICAgbG9nZ2VyLnZlcmJvc2UoYF9QdXNoU3RhdHVzICR7b2JqZWN0SWR9OiBuZWVkcyBjbGVhbnVwYCwgeyBkZXZpY2VzVG9SZW1vdmUgfSk7XG4gICAgWydudW1TZW50JywgJ251bUZhaWxlZCddLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgaWYgKHVwZGF0ZVtrZXldID4gMCkge1xuICAgICAgICB1cGRhdGVba2V5XSA9IHtcbiAgICAgICAgICBfX29wOiAnSW5jcmVtZW50JyxcbiAgICAgICAgICBhbW91bnQ6IHVwZGF0ZVtrZXldXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZWxldGUgdXBkYXRlW2tleV07XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAoZGV2aWNlc1RvUmVtb3ZlLmxlbmd0aCA+IDAgJiYgY2xlYW51cEluc3RhbGxhdGlvbnMpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGBSZW1vdmluZyBkZXZpY2UgdG9rZW5zIG9uICR7ZGV2aWNlc1RvUmVtb3ZlLmxlbmd0aH0gX0luc3RhbGxhdGlvbnNgKTtcbiAgICAgIGRhdGFiYXNlLnVwZGF0ZSgnX0luc3RhbGxhdGlvbicsIHsgZGV2aWNlVG9rZW46IHsgJyRpbic6IGRldmljZXNUb1JlbW92ZSB9fSwgeyBkZXZpY2VUb2tlbjoge1wiX19vcFwiOiBcIkRlbGV0ZVwifSB9LCB7XG4gICAgICAgIGFjbDogdW5kZWZpbmVkLFxuICAgICAgICBtYW55OiB0cnVlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBpbmRpY2F0ZSB0aGlzIGJhdGNoIGlzIGNvbXBsZXRlXG4gICAgaW5jcmVtZW50T3AodXBkYXRlLCAnY291bnQnLCAtMSk7XG5cbiAgICByZXR1cm4gaGFuZGxlci51cGRhdGUoeyBvYmplY3RJZCB9LCB1cGRhdGUpLnRoZW4oKHJlcykgPT4ge1xuICAgICAgaWYgKHJlcyAmJiByZXMuY291bnQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcGxldGUoKTtcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgY29uc3QgY29tcGxldGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gaGFuZGxlci51cGRhdGUoeyBvYmplY3RJZCB9LCB7XG4gICAgICBzdGF0dXM6ICdzdWNjZWVkZWQnLFxuICAgICAgY291bnQ6IHtfX29wOiAnRGVsZXRlJ31cbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0IGZhaWwgPSBmdW5jdGlvbihlcnIpIHtcbiAgICBpZiAodHlwZW9mIGVyciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVyciA9IHsgbWVzc2FnZTogZXJyIH07XG4gICAgfVxuICAgIGNvbnN0IHVwZGF0ZSA9IHtcbiAgICAgIGVycm9yTWVzc2FnZTogZXJyLFxuICAgICAgc3RhdHVzOiAnZmFpbGVkJ1xuICAgIH1cbiAgICByZXR1cm4gaGFuZGxlci51cGRhdGUoeyBvYmplY3RJZCB9LCB1cGRhdGUpO1xuICB9XG5cbiAgY29uc3QgcnZhbCA9IHtcbiAgICBzZXRJbml0aWFsLFxuICAgIHNldFJ1bm5pbmcsXG4gICAgdHJhY2tTZW50LFxuICAgIGNvbXBsZXRlLFxuICAgIGZhaWxcbiAgfTtcblxuICAvLyBkZWZpbmUgb2JqZWN0SWQgdG8gYmUgZHluYW1pY1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkocnZhbCwgXCJvYmplY3RJZFwiLCB7XG4gICAgZ2V0OiAoKSA9PiBvYmplY3RJZFxuICB9KTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShydmFsKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/TestUtils.js b/lib/TestUtils.js index df58b7ceca..362a662a72 100644 --- a/lib/TestUtils.js +++ b/lib/TestUtils.js @@ -11,17 +11,21 @@ var _cache2 = _interopRequireDefault(_cache); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -//Used by tests -function destroyAllDataPermanently() { +/** + * 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(_cache2.default.cache).map(appId => { const app = _cache2.default.get(appId); if (app.databaseController) { - return app.databaseController.deleteEverything(); + return app.databaseController.deleteEverything(fast); } else { return Promise.resolve(); } })); -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9UZXN0VXRpbHMuanMiXSwibmFtZXMiOlsiZGVzdHJveUFsbERhdGFQZXJtYW5lbnRseSIsImZhc3QiLCJwcm9jZXNzIiwiZW52IiwiVEVTVElORyIsIlByb21pc2UiLCJhbGwiLCJPYmplY3QiLCJrZXlzIiwiQXBwQ2FjaGUiLCJjYWNoZSIsIm1hcCIsImFwcElkIiwiYXBwIiwiZ2V0IiwiZGF0YWJhc2VDb250cm9sbGVyIiwiZGVsZXRlRXZlcnl0aGluZyIsInJlc29sdmUiXSwibWFwcGluZ3MiOiI7Ozs7O1FBTWdCQSx5QixHQUFBQSx5Qjs7QUFOaEI7Ozs7OztBQUVBOzs7O0FBSU8sU0FBU0EseUJBQVQsQ0FBbUNDLElBQW5DLEVBQXlDO0FBQzlDLE1BQUksQ0FBQ0MsUUFBUUMsR0FBUixDQUFZQyxPQUFqQixFQUEwQjtBQUN4QixVQUFNLG9DQUFOO0FBQ0Q7QUFDRCxTQUFPQyxRQUFRQyxHQUFSLENBQVlDLE9BQU9DLElBQVAsQ0FBWUMsZ0JBQVNDLEtBQXJCLEVBQTRCQyxHQUE1QixDQUFnQ0MsU0FBUztBQUMxRCxVQUFNQyxNQUFNSixnQkFBU0ssR0FBVCxDQUFhRixLQUFiLENBQVo7QUFDQSxRQUFJQyxJQUFJRSxrQkFBUixFQUE0QjtBQUMxQixhQUFPRixJQUFJRSxrQkFBSixDQUF1QkMsZ0JBQXZCLENBQXdDZixJQUF4QyxDQUFQO0FBQ0QsS0FGRCxNQUVPO0FBQ0wsYUFBT0ksUUFBUVksT0FBUixFQUFQO0FBQ0Q7QUFDRixHQVBrQixDQUFaLENBQVA7QUFRRCIsImZpbGUiOiJUZXN0VXRpbHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQXBwQ2FjaGUgZnJvbSAnLi9jYWNoZSc7XG5cbi8qKlxuICogRGVzdHJveXMgYWxsIGRhdGEgaW4gdGhlIGRhdGFiYXNlXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGZhc3Qgc2V0IHRvIHRydWUgaWYgaXQncyBvayB0byBqdXN0IGRyb3Agb2JqZWN0cyBhbmQgbm90IGluZGV4ZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXN0cm95QWxsRGF0YVBlcm1hbmVudGx5KGZhc3QpIHtcbiAgaWYgKCFwcm9jZXNzLmVudi5URVNUSU5HKSB7XG4gICAgdGhyb3cgJ09ubHkgc3VwcG9ydGVkIGluIHRlc3QgZW52aXJvbm1lbnQnO1xuICB9XG4gIHJldHVybiBQcm9taXNlLmFsbChPYmplY3Qua2V5cyhBcHBDYWNoZS5jYWNoZSkubWFwKGFwcElkID0+IHtcbiAgICBjb25zdCBhcHAgPSBBcHBDYWNoZS5nZXQoYXBwSWQpO1xuICAgIGlmIChhcHAuZGF0YWJhc2VDb250cm9sbGVyKSB7XG4gICAgICByZXR1cm4gYXBwLmRhdGFiYXNlQ29udHJvbGxlci5kZWxldGVFdmVyeXRoaW5nKGZhc3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICB9KSk7XG59XG4iXX0= \ No newline at end of file diff --git a/lib/batch.js b/lib/batch.js index 1d95e529c0..fa94002648 100644 --- a/lib/batch.js +++ b/lib/batch.js @@ -95,4 +95,5 @@ function handleBatch(router, req) { module.exports = { mountOnto, makeBatchRoutingPathFunction -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9iYXRjaC5qcyJdLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJ1cmwiLCJwYXRoIiwiYmF0Y2hQYXRoIiwibW91bnRPbnRvIiwicm91dGVyIiwicm91dGUiLCJyZXEiLCJoYW5kbGVCYXRjaCIsInBhcnNlVVJMIiwiVVJMIiwicGFyc2UiLCJ1bmRlZmluZWQiLCJtYWtlQmF0Y2hSb3V0aW5nUGF0aEZ1bmN0aW9uIiwib3JpZ2luYWxVcmwiLCJzZXJ2ZXJVUkwiLCJwdWJsaWNTZXJ2ZXJVUkwiLCJhcGlQcmVmaXhMZW5ndGgiLCJsZW5ndGgiLCJhcGlQcmVmaXgiLCJzbGljZSIsIm1ha2VSb3V0YWJsZVBhdGgiLCJyZXF1ZXN0UGF0aCIsIkVycm9yIiwiSU5WQUxJRF9KU09OIiwicG9zaXgiLCJqb2luIiwibG9jYWxQYXRoIiwicHVibGljUGF0aCIsIm5ld1BhdGgiLCJBcnJheSIsImlzQXJyYXkiLCJib2R5IiwicmVxdWVzdHMiLCJlbmRzV2l0aCIsImNvbmZpZyIsInByb21pc2VzIiwibWFwIiwicmVzdFJlcXVlc3QiLCJyb3V0YWJsZVBhdGgiLCJyZXF1ZXN0IiwiYXV0aCIsImluZm8iLCJ0cnlSb3V0ZVJlcXVlc3QiLCJtZXRob2QiLCJ0aGVuIiwicmVzcG9uc2UiLCJzdWNjZXNzIiwiZXJyb3IiLCJjb2RlIiwibWVzc2FnZSIsIlByb21pc2UiLCJhbGwiLCJyZXN1bHRzIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQSxNQUFNQSxRQUFRQyxRQUFRLFlBQVIsRUFBc0JELEtBQXBDO0FBQ0EsTUFBTUUsTUFBTUQsUUFBUSxLQUFSLENBQVo7QUFDQSxNQUFNRSxPQUFPRixRQUFRLE1BQVIsQ0FBYjtBQUNBO0FBQ0EsTUFBTUcsWUFBWSxRQUFsQjs7QUFFQTtBQUNBLFNBQVNDLFNBQVQsQ0FBbUJDLE1BQW5CLEVBQTJCO0FBQ3pCQSxTQUFPQyxLQUFQLENBQWEsTUFBYixFQUFxQkgsU0FBckIsRUFBaUNJLEdBQUQs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RkU7QUFHZE0sWUFBTWxDLElBQUlrQyxJQUhJO0FBSWRDLFlBQU1uQyxJQUFJbUM7QUFKSSxLQUFoQjs7QUFPQSxXQUFPckMsT0FBT3NDLGVBQVAsQ0FBdUJMLFlBQVlNLE1BQW5DLEVBQTJDTCxZQUEzQyxFQUF5REMsT0FBekQsRUFBa0VLLElBQWxFLENBQXdFQyxRQUFELElBQWM7QUFDMUYsYUFBTyxFQUFDQyxTQUFTRCxTQUFTQSxRQUFuQixFQUFQO0FBQ0QsS0FGTSxFQUVIRSxLQUFELElBQVc7QUFDWixhQUFPLEVBQUNBLE9BQU8sRUFBQ0MsTUFBTUQsTUFBTUMsSUFBYixFQUFtQkQsT0FBT0EsTUFBTUUsT0FBaEMsRUFBUixFQUFQO0FBQ0QsS0FKTSxDQUFQO0FBS0QsR0FmZ0IsQ0FBakI7O0FBaUJBLFNBQU9DLFFBQVFDLEdBQVIsQ0FBWWhCLFFBQVosRUFBc0JTLElBQXRCLENBQTRCUSxPQUFELElBQWE7QUFDN0MsV0FBTyxFQUFDUCxVQUFVTyxPQUFYLEVBQVA7QUFDRCxHQUZNLENBQVA7QUFHRDs7QUFFREMsT0FBT0MsT0FBUCxHQUFpQjtBQUNmbkQsV0FEZTtBQUVmUztBQUZlLENBQWpCIiwiZmlsZSI6ImJhdGNoLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2U7XG5jb25zdCB1cmwgPSByZXF1aXJlKCd1cmwnKTtcbmNvbnN0IHBhdGggPSByZXF1aXJlKCdwYXRoJyk7XG4vLyBUaGVzZSBtZXRob2RzIGhhbmRsZSBiYXRjaCByZXF1ZXN0cy5cbmNvbnN0IGJhdGNoUGF0aCA9ICcvYmF0Y2gnO1xuXG4vLyBNb3VudHMgYSBiYXRjaC1oYW5kbGVyIG9udG8gYSBQcm9taXNlUm91dGVyLlxuZnVuY3Rpb24gbW91bnRPbnRvKHJvdXRlcikge1xuICByb3V0ZXIucm91dGUoJ1BPU1QnLCBiYXRjaFBhdGgsIChyZXEpID0+IHtcbiAgICByZXR1cm4gaGFuZGxlQmF0Y2gocm91dGVyLCByZXEpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gcGFyc2VVUkwoVVJMKSB7XG4gIGlmICh0eXBlb2YgVVJMID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiB1cmwucGFyc2UoVVJMKVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIG1ha2VCYXRjaFJvdXRpbmdQYXRoRnVuY3Rpb24ob3JpZ2luYWxVcmwsIHNlcnZlclVSTCwgcHVibGljU2VydmVyVVJMKSB7XG4gIHNlcnZlclVSTCA9IHNlcnZlclVSTCA/IHBhcnNlVVJMKHNlcnZlclVSTCkgOiB1bmRlZmluZWQ7XG4gIHB1YmxpY1NlcnZlclVSTCA9IHB1YmxpY1NlcnZlclVSTCA/IHBhcnNlVVJMKHB1YmxpY1NlcnZlclVSTCkgOiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgYXBpUHJlZml4TGVuZ3RoID0gb3JpZ2luYWxVcmwubGVuZ3RoIC0gYmF0Y2hQYXRoLmxlbmd0aDtcbiAgbGV0IGFwaVByZWZpeCA9IG9yaWdpbmFsVXJsLnNsaWNlKDAsIGFwaVByZWZpeExlbmd0aCk7XG5cbiAgY29uc3QgbWFrZVJvdXRhYmxlUGF0aCA9IGZ1bmN0aW9uKHJlcXVlc3RQYXRoKSB7XG4gICAgLy8gVGhlIHJvdXRhYmxlUGF0aCBpcyB0aGUgcGF0aCBtaW51cyB0aGUgYXBpIHByZWZpeFxuICAgIGlmIChyZXF1ZXN0UGF0aC5zbGljZSgwLCBhcGlQcmVmaXgubGVuZ3RoKSAhPSBhcGlQcmVmaXgpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAnY2Fubm90IHJvdXRlIGJhdGNoIHBhdGggJyArIHJlcXVlc3RQYXRoKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGgucG9zaXguam9pbignLycsIHJlcXVlc3RQYXRoLnNsaWNlKGFwaVByZWZpeC5sZW5ndGgpKTtcbiAgfVxuXG4gIGlmIChzZXJ2ZXJVUkwgJiYgcHVibGljU2VydmVyVVJMXG4gICAgICAgICYmIChzZXJ2ZXJVUkwucGF0aCAhPSBwdWJsaWNTZXJ2ZXJVUkwucGF0aCkpIHtcbiAgICBjb25zdCBsb2NhbFBhdGggPSBzZXJ2ZXJVUkwucGF0aDtcbiAgICBjb25zdCBwdWJsaWNQYXRoID0gcHVibGljU2VydmVyVVJMLnBhdGg7XG4gICAgLy8gT3ZlcnJpZGUgdGhlIGFwaSBwcmVmaXhcbiAgICBhcGlQcmVmaXggPSBsb2NhbFBhdGg7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHJlcXVlc3RQYXRoKSB7XG4gICAgICAvLyBCdWlsZCB0aGUgbmV3IHBhdGggYnkgcmVtb3ZpbmcgdGhlIHB1YmxpYyBwYXRoXG4gICAgICAvLyBhbmQgam9pbmluZyB3aXRoIHRoZSBsb2NhbCBwYXRoXG4gICAgICBjb25zdCBuZXdQYXRoID0gcGF0aC5wb3NpeC5qb2luKCcvJywgbG9jYWxQYXRoLCAnLycgLCByZXF1ZXN0UGF0aC5zbGljZShwdWJsaWNQYXRoLmxlbmd0aCkpO1xuICAgICAgLy8gVXNlIHRoZSBtZXRob2QgZm9yIGxvY2FsIHJvdXRpbmdcbiAgICAgIHJldHVybiBtYWtlUm91dGFibGVQYXRoKG5ld1BhdGgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtYWtlUm91dGFibGVQYXRoO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSB7cmVzcG9uc2V9IG9iamVjdC5cbi8vIFRPRE86IHBhc3MgYWxvbmcgYXV0aCBjb3JyZWN0bHlcbmZ1bmN0aW9uIGhhbmRsZUJhdGNoKHJvdXRlciwgcmVxKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShyZXEuYm9keS5yZXF1ZXN0cykpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgJ3JlcXVlc3RzIG11c3QgYmUgYW4gYXJyYXknKTtcbiAgfVxuXG4gIC8vIFRoZSBiYXRjaCBwYXRocyBhcmUgYWxsIGZyb20gdGhlIHJvb3Qgb2Ygb3VyIGRvbWFpbi5cbiAgLy8gVGhhdCBtZWFucyB0aGV5IGluY2x1ZGUgdGhlIEFQSSBwcmVmaXgsIHRoYXQgdGhlIEFQSSBpcyBtb3VudGVkXG4gIC8vIHRvLiBIb3dldmVyLCBvdXIgcHJvbWlzZSByb3V0ZXIgZG9lcyBub3Qgcm91dGUgdGhlIGFwaSBwcmVmaXguIFNvXG4gIC8vIHdlIG5lZWQgdG8gZmlndXJlIG91dCB0aGUgQVBJIHByZWZpeCwgc28gdGhhdCB3ZSBjYW4gc3RyaXAgaXRcbiAgLy8gZnJvbSBhbGwgdGhlIHN1YnJlcXVlc3RzLlxuICBpZiAoIXJlcS5vcmlnaW5hbFVybC5lbmRzV2l0aChiYXRjaFBhdGgpKSB7XG4gICAgdGhyb3cgJ2ludGVybmFsIHJvdXRpbmcgcHJvYmxlbSAtIGV4cGVjdGVkIHVybCB0byBlbmQgd2l0aCBiYXRjaCc7XG4gIH1cblxuICBjb25zdCBtYWtlUm91dGFibGVQYXRoID0gbWFrZUJhdGNoUm91dGluZ1BhdGhGdW5jdGlvbihyZXEub3JpZ2luYWxVcmwsIHJlcS5jb25maWcuc2VydmVyVVJMLCByZXEuY29uZmlnLnB1YmxpY1NlcnZlclVSTCk7XG5cbiAgY29uc3QgcHJvbWlzZXMgPSByZXEuYm9keS5yZXF1ZXN0cy5tYXAoKHJlc3RSZXF1ZXN0KSA9PiB7XG4gICAgY29uc3Qgcm91dGFibGVQYXRoID0gbWFrZVJvdXRhYmxlUGF0aChyZXN0UmVxdWVzdC5wYXRoKTtcbiAgICAvLyBDb25zdHJ1Y3QgYSByZXF1ZXN0IHRoYXQgd2UgY2FuIHNlbmQgdG8gYSBoYW5kbGVyXG4gICAgY29uc3QgcmVxdWVzdCA9IHtcbiAgICAgIGJvZHk6IHJlc3RSZXF1ZXN0LmJvZHksXG4gICAgICBjb25maWc6IHJlcS5jb25maWcsXG4gICAgICBhdXRoOiByZXEuYXV0aCxcbiAgICAgIGluZm86IHJlcS5pbmZvXG4gICAgfTtcblxuICAgIHJldHVybiByb3V0ZXIudHJ5Um91dGVSZXF1ZXN0KHJlc3RSZXF1ZXN0Lm1ldGhvZCwgcm91dGFibGVQYXRoLCByZXF1ZXN0KS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgcmV0dXJuIHtzdWNjZXNzOiByZXNwb25zZS5yZXNwb25zZX07XG4gICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICByZXR1cm4ge2Vycm9yOiB7Y29kZTogZXJyb3IuY29kZSwgZXJyb3I6IGVycm9yLm1lc3NhZ2V9fTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKChyZXN1bHRzKSA9PiB7XG4gICAgcmV0dXJuIHtyZXNwb25zZTogcmVzdWx0c307XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgbW91bnRPbnRvLFxuICBtYWtlQmF0Y2hSb3V0aW5nUGF0aEZ1bmN0aW9uXG59O1xuIl19 \ No newline at end of file diff --git a/lib/cache.js b/lib/cache.js index 51641150c3..92644217c4 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -8,4 +8,5 @@ exports.AppCache = undefined; var _InMemoryCache = require('./Adapters/Cache/InMemoryCache'); var AppCache = exports.AppCache = new _InMemoryCache.InMemoryCache({ ttl: NaN }); -exports.default = AppCache; \ No newline at end of file +exports.default = AppCache; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jYWNoZS5qcyJdLCJuYW1lcyI6WyJBcHBDYWNoZSIsIkluTWVtb3J5Q2FjaGUiLCJ0dGwiLCJOYU4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFFTyxJQUFJQSw4QkFBVyxJQUFJQyw0QkFBSixDQUFrQixFQUFDQyxLQUFLQyxHQUFOLEVBQWxCLENBQWY7a0JBQ1FILFEiLCJmaWxlIjoiY2FjaGUuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luTWVtb3J5Q2FjaGV9IGZyb20gJy4vQWRhcHRlcnMvQ2FjaGUvSW5NZW1vcnlDYWNoZSc7XG5cbmV4cG9ydCB2YXIgQXBwQ2FjaGUgPSBuZXcgSW5NZW1vcnlDYWNoZSh7dHRsOiBOYU59KTtcbmV4cG9ydCBkZWZhdWx0IEFwcENhY2hlO1xuIl19 \ 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 index 094e37ca72..c054a8d9cf 100644 --- a/lib/cli/definitions/parse-live-query-server.js +++ b/lib/cli/definitions/parse-live-query-server.js @@ -4,4 +4,5 @@ Object.defineProperty(exports, "__esModule", { value: true }); const LiveQueryServerOptions = require('../../Options/Definitions').LiveQueryServerOptions; -exports.default = LiveQueryServerOptions; \ No newline at end of file +exports.default = LiveQueryServerOptions; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvZGVmaW5pdGlvbnMvcGFyc2UtbGl2ZS1xdWVyeS1zZXJ2ZXIuanMiXSwibmFtZXMiOlsiTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyIsInJlcXVpcmUiXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsTUFBTUEseUJBQXlCQyxRQUFRLDJCQUFSLEVBQXFDRCxzQkFBcEU7a0JBQ2VBLHNCIiwiZmlsZSI6InBhcnNlLWxpdmUtcXVlcnktc2VydmVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucyA9IHJlcXVpcmUoJy4uLy4uL09wdGlvbnMvRGVmaW5pdGlvbnMnKS5MaXZlUXVlcnlTZXJ2ZXJPcHRpb25zO1xuZXhwb3J0IGRlZmF1bHQgTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucztcbiJdfQ== \ No newline at end of file diff --git a/lib/cli/definitions/parse-server.js b/lib/cli/definitions/parse-server.js index f9dbfe85ac..c88be41cfd 100644 --- a/lib/cli/definitions/parse-server.js +++ b/lib/cli/definitions/parse-server.js @@ -4,4 +4,5 @@ Object.defineProperty(exports, "__esModule", { value: true }); const ParseServerDefinitions = require('../../Options/Definitions').ParseServerOptions; -exports.default = ParseServerDefinitions; \ No newline at end of file +exports.default = ParseServerDefinitions; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvZGVmaW5pdGlvbnMvcGFyc2Utc2VydmVyLmpzIl0sIm5hbWVzIjpbIlBhcnNlU2VydmVyRGVmaW5pdGlvbnMiLCJyZXF1aXJlIiwiUGFyc2VTZXJ2ZXJPcHRpb25zIl0sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE1BQU1BLHlCQUF5QkMsUUFBUSwyQkFBUixFQUFxQ0Msa0JBQXBFO2tCQUNlRixzQiIsImZpbGUiOiJwYXJzZS1zZXJ2ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBQYXJzZVNlcnZlckRlZmluaXRpb25zID0gcmVxdWlyZSgnLi4vLi4vT3B0aW9ucy9EZWZpbml0aW9ucycpLlBhcnNlU2VydmVyT3B0aW9ucztcbmV4cG9ydCBkZWZhdWx0IFBhcnNlU2VydmVyRGVmaW5pdGlvbnM7XG4iXX0= \ No newline at end of file diff --git a/lib/cli/parse-live-query-server.js b/lib/cli/parse-live-query-server.js index 4adcd0ea43..327821e629 100644 --- a/lib/cli/parse-live-query-server.js +++ b/lib/cli/parse-live-query-server.js @@ -18,4 +18,5 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de logOptions(); _index.ParseServer.createLiveQueryServer(undefined, options); } -}); \ No newline at end of file +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGkvcGFyc2UtbGl2ZS1xdWVyeS1zZXJ2ZXIuanMiXSwibmFtZXMiOlsiZGVmaW5pdGlvbnMiLCJzdGFydCIsInByb2dyYW0iLCJvcHRpb25zIiwibG9nT3B0aW9ucyIsIlBhcnNlU2VydmVyIiwiY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyIiwidW5kZWZpbmVkIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUVBLHNCQUFPO0FBQ0xBLDZDQURLO0FBRUxDLFNBQU8sVUFBU0MsT0FBVCxFQUFrQkMsT0FBbEIsRUFBMkJDLFVBQTNCLEVBQXVDO0FBQzVDQTtBQUNBQyx1QkFBWUMscUJBQVosQ0FBa0NDLFNBQWxDLEVBQTZDSixPQUE3QztBQUNEO0FBTEksQ0FBUCIsImZpbGUiOiJwYXJzZS1saXZlLXF1ZXJ5LXNlcnZlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBkZWZpbml0aW9ucyBmcm9tICcuL2RlZmluaXRpb25zL3BhcnNlLWxpdmUtcXVlcnktc2VydmVyJztcbmltcG9ydCBydW5uZXIgZnJvbSAnLi91dGlscy9ydW5uZXInO1xuaW1wb3J0IHsgUGFyc2VTZXJ2ZXIgfSBmcm9tICcuLi9pbmRleCc7XG5cbnJ1bm5lcih7XG4gIGRlZmluaXRpb25zLFxuICBzdGFydDogZnVuY3Rpb24ocHJvZ3JhbSwgb3B0aW9ucywgbG9nT3B0aW9ucykge1xuICAgIGxvZ09wdGlvbnMoKTtcbiAgICBQYXJzZVNlcnZlci5jcmVhdGVMaXZlUXVlcnlTZXJ2ZXIodW5kZWZpbmVkLCBvcHRpb25zKTtcbiAgfVxufSlcbiJdfQ== \ No newline at end of file diff --git a/lib/cli/parse-server.js b/lib/cli/parse-server.js index 125396c70c..c3430c1de2 100755 --- a/lib/cli/parse-server.js +++ b/lib/cli/parse-server.js @@ -95,4 +95,5 @@ const help = function () { } }); -/* eslint-enable no-console */ \ No newline at end of file +/* eslint-enable no-console */ +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGkvcGFyc2Utc2VydmVyLmpzIl0sIm5hbWVzIjpbImhlbHAiLCJjb25zb2xlIiwibG9nIiwiZGVmaW5pdGlvbnMiLCJ1c2FnZSIsInN0YXJ0IiwicHJvZ3JhbSIsIm9wdGlvbnMiLCJsb2dPcHRpb25zIiwiYXBwSWQiLCJtYXN0ZXJLZXkiLCJvdXRwdXRIZWxwIiwiZXJyb3IiLCJwcm9jZXNzIiwiZXhpdCIsImxpdmVRdWVyeSIsImNsYXNzTmFtZXMiLCJyZWRpc1VSTCIsImNsdXN0ZXIiLCJudW1DUFVzIiwib3MiLCJjcHVzIiwibGVuZ3RoIiwiaXNNYXN0ZXIiLCJpIiwiZm9yayIsIm9uIiwid29ya2VyIiwiY29kZSIsInBpZCIsIlBhcnNlU2VydmVyIiwic2VydmVyVVJMIl0sIm1hcHBpbmdzIjoiOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVBLE1BQU1BLE9BQU8sWUFBVTtBQUNyQkMsVUFBUUMsR0FBUixDQUFZLHNCQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxFQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxrREFBWjtBQUNBRCxVQUFRQyxHQUFSLENBQVksdURBQVo7QUFDQUQsVUFBUUMsR0FBUixDQUFZLEVBQVo7QUFDQUQsVUFBUUMsR0FBUixDQUFZLEVBQVo7QUFDQUQsVUFBUUMsR0FBUixDQUFZLHdCQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxFQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSx3Q0FBWjtBQUNBRCxVQUFRQyxHQUFSLENBQVksZ0ZBQVo7QUFDQUQsVUFBUUMsR0FBUixDQUFZLGdGQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxFQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxFQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxVQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxFQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSx3Q0FBWjtBQUNBRCxVQUFRQyxHQUFSLENBQVksbUZBQVo7QUFDQUQsVUFBUUMsR0FBUixDQUFZLG1GQUFaO0FBQ0FELFVBQVFDLEdBQVIsQ0FBWSxFQUFaO0FBQ0QsQ0FwQkQsQyxDQVBBOzs7QUE2QkEsc0JBQU87QUFDTEMsb0NBREs7QUFFTEgsTUFGSztBQUdMSSxTQUFPLHdDQUhGO0FBSUxDLFNBQU8sVUFBU0MsT0FBVCxFQUFrQkMsT0FBbEIsRUFBMkJDLFVBQTNCLEVBQXVDO0FBQzVDLFFBQUksQ0FBQ0QsUUFBUUUsS0FBVCxJQUFrQixDQUFDRixRQUFRRyxTQUEvQixFQUEwQztBQUN4Q0osY0FBUUssVUFBUjtBQUNBVixjQUFRVyxLQUFSLENBQWMsRUFBZDtBQUNBWCxjQUFRVyxLQUFSLENBQWMsNERBQWQ7QUFDQVgsY0FBUVcsS0FBUixDQUFjLEVBQWQ7QUFDQUMsY0FBUUMsSUFBUixDQUFhLENBQWI7QUFDRDs7QUFFRCxRQUFJUCxRQUFRLHNCQUFSLENBQUosRUFBcUM7QUFDbkNBLGNBQVFRLFNBQVIsR0FBb0JSLFFBQVFRLFNBQVIsSUFBcUIsRUFBekM7QUFDQVIsY0FBUVEsU0FBUixDQUFrQkMsVUFBbEIsR0FBK0JULFFBQVEsc0JBQVIsQ0FBL0I7QUFDQSxhQUFPQSxRQUFRLHNCQUFSLENBQVA7QUFDRDtBQUNELFFBQUlBLFFBQVEsb0JBQVIsQ0FBSixFQUFtQztBQUNqQ0EsY0FBUVEsU0FBUixHQUFvQlIsUUFBUVEsU0FBUixJQUFxQixFQUF6QztBQUNBUixjQUFRUSxTQUFSLENBQWtCRSxRQUFsQixHQUE2QlYsUUFBUSxvQkFBUixDQUE3QjtBQUNBLGFBQU9BLFFBQVEsb0JBQVIsQ0FBUDtBQUNEOztBQUVELFFBQUlBLFFBQVFXLE9BQVosRUFBcUI7QUFDbkIsWUFBTUMsVUFBVSxPQUFPWixRQUFRVyxPQUFmLEtBQTJCLFFBQTNCLEdBQXNDWCxRQUFRVyxPQUE5QyxHQUF3REUsYUFBR0MsSUFBSCxHQUFVQyxNQUFsRjtBQUNBLFVBQUlKLGtCQUFRSyxRQUFaLEVBQXNCO0FBQ3BCZjtBQUNBLGFBQUksSUFBSWdCLElBQUksQ0FBWixFQUFlQSxJQUFJTCxPQUFuQixFQUE0QkssR0FBNUIsRUFBaUM7QUFDL0JOLDRCQUFRTyxJQUFSO0FBQ0Q7QUFDRFAsMEJBQVFRLEVBQVIsQ0FBVyxNQUFYLEVBQW1CLENBQUNDLE1BQUQsRUFBU0MsSUFBVCxLQUFrQjtBQUNuQzNCLGtCQUFRQyxHQUFSLENBQWEsVUFBU3lCLE9BQU9kLE9BQVAsQ0FBZWdCLEdBQUksVUFBU0QsSUFBSyxpQkFBdkQ7QUFDQVYsNEJBQVFPLElBQVI7QUFDRCxTQUhEO0FBSUQsT0FURCxNQVNPO0FBQ0xLLHdCQUFZekIsS0FBWixDQUFrQkUsT0FBbEIsRUFBMkIsTUFBTTtBQUMvQk4sa0JBQVFDLEdBQVIsQ0FBWSxNQUFNVyxRQUFRZ0IsR0FBZCxHQUFvQiw0QkFBcEIsR0FBbUR0QixRQUFRd0IsU0FBdkU7QUFDRCxTQUZEO0FBR0Q7QUFDRixLQWhCRCxNQWdCTztBQUNMRCxzQkFBWXpCLEtBQVosQ0FBa0JFLE9BQWxCLEVBQTJCLE1BQU07QUFDL0JDO0FBQ0FQLGdCQUFRQyxHQUFSLENBQVksRUFBWjtBQUNBRCxnQkFBUUMsR0FBUixDQUFZLE1BQU1XLFFBQVFnQixHQUFkLEdBQW9CLDRCQUFwQixHQUFtRHRCLFFBQVF3QixTQUF2RTtBQUNELE9BSkQ7QUFLRDtBQUNGO0FBL0NJLENBQVA7O0FBa0RBIiwiZmlsZSI6InBhcnNlLXNlcnZlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbmltcG9ydCBQYXJzZVNlcnZlciBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgZGVmaW5pdGlvbnMgZnJvbSAnLi9kZWZpbml0aW9ucy9wYXJzZS1zZXJ2ZXInO1xuaW1wb3J0IGNsdXN0ZXIgZnJvbSAnY2x1c3Rlcic7XG5pbXBvcnQgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHJ1bm5lciBmcm9tICcuL3V0aWxzL3J1bm5lcic7XG5cbmNvbnN0IGhlbHAgPSBmdW5jdGlvbigpe1xuICBjb25zb2xlLmxvZygnICBHZXQgU3RhcnRlZCBndWlkZTonKTtcbiAgY29uc29sZS5sb2coJycpO1xuICBjb25zb2xlLmxvZygnICAgIFBsZWFzZSBoYXZlIGEgbG9vayBhdCB0aGUgZ2V0IHN0YXJ0ZWQgZ3VpZGUhJyk7XG4gIGNvbnNvbGUubG9nKCcgICAgaHR0cDovL2RvY3MucGFyc2VwbGF0Zm9ybS5vcmcvcGFyc2Utc2VydmVyL2d1aWRlLycpO1xuICBjb25zb2xlLmxvZygnJyk7XG4gIGNvbnNvbGUubG9nKCcnKTtcbiAgY29uc29sZS5sb2coJyAgVXNhZ2Ugd2l0aCBucG0gc3RhcnQnKTtcbiAgY29uc29sZS5sb2coJycpO1xuICBjb25zb2xlLmxvZygnICAgICQgbnBtIHN0YXJ0IC0tIHBhdGgvdG8vY29uZmlnLmpzb24nKTtcbiAgY29uc29sZS5sb2coJyAgICAkIG5wbSBzdGFydCAtLSAtLWFwcElkIEFQUF9JRCAtLW1hc3RlcktleSBNQVNURVJfS0VZIC0tc2VydmVyVVJMIHNlcnZlclVSTCcpO1xuICBjb25zb2xlLmxvZygnICAgICQgbnBtIHN0YXJ0IC0tIC0tYXBwSWQgQVBQX0lEIC0tbWFzdGVyS2V5IE1BU1RFUl9LRVkgLS1zZXJ2ZXJVUkwgc2VydmVyVVJMJyk7XG4gIGNvbnNvbGUubG9nKCcnKTtcbiAgY29uc29sZS5sb2coJycpO1xuICBjb25zb2xlLmxvZygnICBVc2FnZTonKTtcbiAgY29uc29sZS5sb2coJycpO1xuICBjb25zb2xlLmxvZygnICAgICQgcGFyc2Utc2VydmVyIHBhdGgvdG8vY29uZmlnLmpzb24nKTtcbiAgY29uc29sZS5sb2coJyAgICAkIHBhcnNlLXNlcnZlciAtLSAtLWFwcElkIEFQUF9JRCAtLW1hc3RlcktleSBNQVNURVJfS0VZIC0tc2VydmVyVVJMIHNlcnZlclVSTCcpO1xuICBjb25zb2xlLmxvZygnICAgICQgcGFyc2Utc2VydmVyIC0tIC0tYXBwSWQgQVBQX0lEIC0tbWFzdGVyS2V5IE1BU1RFUl9LRVkgLS1zZXJ2ZXJVUkwgc2VydmVyVVJMJyk7XG4gIGNvbnNvbGUubG9nKCcnKTtcbn07XG5cbnJ1bm5lcih7XG4gIGRlZmluaXRpb25zLFxuICBoZWxwLFxuICB1c2FnZTogJ1tvcHRpb25zXSA8cGF0aC90by9jb25maWd1cmF0aW9uLmpzb24+JyxcbiAgc3RhcnQ6IGZ1bmN0aW9uKHByb2dyYW0sIG9wdGlvbnMsIGxvZ09wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMuYXBwSWQgfHwgIW9wdGlvbnMubWFzdGVyS2V5KSB7XG4gICAgICBwcm9ncmFtLm91dHB1dEhlbHAoKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJcIik7XG4gICAgICBjb25zb2xlLmVycm9yKCdcXHUwMDFiWzMxbUVSUk9SOiBhcHBJZCBhbmQgbWFzdGVyS2V5IGFyZSByZXF1aXJlZFxcdTAwMWJbMG0nKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJcIik7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnNbXCJsaXZlUXVlcnkuY2xhc3NOYW1lc1wiXSkge1xuICAgICAgb3B0aW9ucy5saXZlUXVlcnkgPSBvcHRpb25zLmxpdmVRdWVyeSB8fCB7fTtcbiAgICAgIG9wdGlvbnMubGl2ZVF1ZXJ5LmNsYXNzTmFtZXMgPSBvcHRpb25zW1wibGl2ZVF1ZXJ5LmNsYXNzTmFtZXNcIl07XG4gICAgICBkZWxldGUgb3B0aW9uc1tcImxpdmVRdWVyeS5jbGFzc05hbWVzXCJdO1xuICAgIH1cbiAgICBpZiAob3B0aW9uc1tcImxpdmVRdWVyeS5yZWRpc1VSTFwiXSkge1xuICAgICAgb3B0aW9ucy5saXZlUXVlcnkgPSBvcHRpb25zLmxpdmVRdWVyeSB8fCB7fTtcbiAgICAgIG9wdGlvbnMubGl2ZVF1ZXJ5LnJlZGlzVVJMID0gb3B0aW9uc1tcImxpdmVRdWVyeS5yZWRpc1VSTFwiXTtcbiAgICAgIGRlbGV0ZSBvcHRpb25zW1wibGl2ZVF1ZXJ5LnJlZGlzVVJMXCJdO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmNsdXN0ZXIpIHtcbiAgICAgIGNvbnN0IG51bUNQVXMgPSB0eXBlb2Ygb3B0aW9ucy5jbHVzdGVyID09PSAnbnVtYmVyJyA/IG9wdGlvbnMuY2x1c3RlciA6IG9zLmNwdXMoKS5sZW5ndGg7XG4gICAgICBpZiAoY2x1c3Rlci5pc01hc3Rlcikge1xuICAgICAgICBsb2dPcHRpb25zKCk7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBudW1DUFVzOyBpKyspIHtcbiAgICAgICAgICBjbHVzdGVyLmZvcmsoKTtcbiAgICAgICAgfVxuICAgICAgICBjbHVzdGVyLm9uKCdleGl0JywgKHdvcmtlciwgY29kZSkgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGB3b3JrZXIgJHt3b3JrZXIucHJvY2Vzcy5waWR9IGRpZWQgKCR7Y29kZX0pLi4uIFJlc3RhcnRpbmdgKTtcbiAgICAgICAgICBjbHVzdGVyLmZvcmsoKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBQYXJzZVNlcnZlci5zdGFydChvcHRpb25zLCAoKSA9PiB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ1snICsgcHJvY2Vzcy5waWQgKyAnXSBwYXJzZS1zZXJ2ZXIgcnVubmluZyBvbiAnICsgb3B0aW9ucy5zZXJ2ZXJVUkwpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgUGFyc2VTZXJ2ZXIuc3RhcnQob3B0aW9ucywgKCkgPT4ge1xuICAgICAgICBsb2dPcHRpb25zKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgY29uc29sZS5sb2coJ1snICsgcHJvY2Vzcy5waWQgKyAnXSBwYXJzZS1zZXJ2ZXIgcnVubmluZyBvbiAnICsgb3B0aW9ucy5zZXJ2ZXJVUkwpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG59KTtcblxuLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG4iXX0= \ No newline at end of file diff --git a/lib/cli/utils/commander.js b/lib/cli/utils/commander.js index 3059e45614..251df935cd 100644 --- a/lib/cli/utils/commander.js +++ b/lib/cli/utils/commander.js @@ -137,4 +137,5 @@ _commander.Command.prototype.getOptions = function () { }; exports.default = new _commander.Command(); -/* eslint-enable no-console */ \ No newline at end of file +/* eslint-enable no-console */ +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvdXRpbHMvY29tbWFuZGVyLmpzIl0sIm5hbWVzIjpbIl9kZWZpbml0aW9ucyIsIl9yZXZlcnNlRGVmaW5pdGlvbnMiLCJfZGVmYXVsdHMiLCJDb21tYW5kIiwicHJvdG90eXBlIiwibG9hZERlZmluaXRpb25zIiwiZGVmaW5pdGlvbnMiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwicHJvZ3JhbSIsIm9wdCIsImFkZGl0aW9uYWxPcHRpb25zIiwicmVxdWlyZWQiLCJvcHRpb24iLCJoZWxwIiwiYWN0aW9uIiwib2JqZWN0Iiwia2V5IiwidmFsdWUiLCJlbnYiLCJkZWZzIiwiZGVmYXVsdCIsIm9uIiwiY29uc29sZSIsImxvZyIsImZvckVhY2giLCJwYXJzZUVudmlyb25tZW50Iiwib3B0aW9ucyIsIm9yaWdpbmFsS2V5IiwicGFyc2VDb25maWdGaWxlIiwiYXJncyIsImxlbmd0aCIsImpzb25QYXRoIiwicGF0aCIsInJlc29sdmUiLCJqc29uQ29uZmlnIiwicmVxdWlyZSIsImFwcHMiLCJzZXRWYWx1ZXNJZk5lZWRlZCIsImhhc093blByb3BlcnR5IiwiX3BhcnNlIiwicGFyc2UiLCJlbnZPcHRpb25zIiwiZnJvbUZpbGUiLCJnZXRPcHRpb25zIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQTs7QUFDQTs7Ozs7O0FBRkE7QUFHQSxJQUFJQSxZQUFKO0FBQ0EsSUFBSUMsbUJBQUo7QUFDQSxJQUFJQyxTQUFKOztBQUVBQyxtQkFBUUMsU0FBUixDQUFrQkMsZUFBbEIsR0FBb0MsVUFBU0MsV0FBVCxFQUFzQjtBQUN4RE4saUJBQWVNLFdBQWY7O0FBRUFDLFNBQU9DLElBQVAsQ0FBWUYsV0FBWixFQUF5QkcsTUFBekIsQ0FBZ0MsQ0FBQ0MsT0FBRCxFQUFVQyxHQUFWLEtBQWtCO0FBQ2hELFFBQUksT0FBT0wsWUFBWUssR0FBWixDQUFQLElBQTJCLFFBQS9CLEVBQXlDO0FBQ3ZDLFlBQU1DLG9CQUFvQk4sWUFBWUssR0FBWixDQUEx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LENBQWtCc0MsS0FBbEIsR0FBMEIsVUFBU1gsSUFBVCxFQUFlWCxHQUFmLEVBQW9CO0FBQzVDLE9BQUtxQixNQUFMLENBQVlWLElBQVo7QUFDQTtBQUNBLFFBQU1ZLGFBQWFoQixpQkFBaUJQLEdBQWpCLENBQW5CO0FBQ0EsUUFBTXdCLFdBQVdkLGdCQUFnQixJQUFoQixDQUFqQjtBQUNBO0FBQ0EsT0FBS1MsaUJBQUwsQ0FBdUJJLFVBQXZCO0FBQ0E7QUFDQSxPQUFLSixpQkFBTCxDQUF1QkssUUFBdkI7QUFDQTtBQUNBLE9BQUtMLGlCQUFMLENBQXVCckMsU0FBdkI7QUFDRCxDQVhEOztBQWFBQyxtQkFBUUMsU0FBUixDQUFrQnlDLFVBQWxCLEdBQStCLFlBQVc7QUFDeEMsU0FBT3RDLE9BQU9DLElBQVAsQ0FBWVIsWUFBWixFQUEwQlMsTUFBMUIsQ0FBaUMsQ0FBQ21CLE9BQUQsRUFBVVYsR0FBVixLQUFrQjtBQUN4RCxRQUFJLE9BQU8sS0FBS0EsR0FBTCxDQUFQLEtBQXFCLFdBQXpCLEVBQXNDO0FBQ3BDVSxjQUFRVixHQUFSLElBQWUsS0FBS0EsR0FBTCxDQUFmO0FBQ0Q7QUFDRCxXQUFPVSxPQUFQO0FBQ0QsR0FMTSxFQUtKLEVBTEksQ0FBUDtBQU1ELENBUEQ7O2tCQVNlLElBQUl6QixrQkFBSixFO0FBQ2YiLCJmaWxlIjoiY29tbWFuZGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmxldCBfZGVmaW5pdGlvbnM7XG5sZXQgX3JldmVyc2VEZWZpbml0aW9ucztcbmxldCBfZGVmYXVsdHM7XG5cbkNvbW1hbmQucHJvdG90eXBlLmxvYWREZWZpbml0aW9ucyA9IGZ1bmN0aW9uKGRlZmluaXRpb25zKSB7XG4gIF9kZWZpbml0aW9ucyA9IGRlZmluaXRpb25zO1xuXG4gIE9iamVjdC5rZXlzKGRlZmluaXRpb25zKS5yZWR1Y2UoKHByb2dyYW0sIG9wdCkgPT4ge1xuICAgIGlmICh0eXBlb2YgZGVmaW5pdGlvbnNbb3B0XSA9PSBcIm9iamVjdFwiKSB7XG4gICAgICBjb25zdCBhZGRpdGlvbmFsT3B0aW9ucyA9IGRlZmluaXRpb25zW29wdF07XG4gICAgICBpZiAoYWRkaXRpb25hbE9wdGlvbnMucmVxdWlyZWQgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIHByb2dyYW0ub3B0aW9uKGAtLSR7b3B0fSA8JHtvcHR9PmAsIGFkZGl0aW9uYWxPcHRpb25zLmhlbHAsIGFkZGl0aW9uYWxPcHRpb25zLmFjdGlvbik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gcHJvZ3JhbS5vcHRpb24oYC0tJHtvcHR9IFske29wdH1dYCwgYWRkaXRpb25hbE9wdGlvbnMuaGVscCwgYWRkaXRpb25hbE9wdGlvbnMuYWN0aW9uKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHByb2dyYW0ub3B0aW9uKGAtLSR7b3B0fSBbJHtvcHR9XWApO1xuICB9LCB0aGlzKTtcblxuICBfcmV2ZXJzZURlZmluaXRpb25zID0gT2JqZWN0LmtleXMoZGVmaW5pdGlvbnMpLnJlZHVjZSgob2JqZWN0LCBrZXkpID0+IHtcbiAgICBsZXQgdmFsdWUgPSBkZWZpbml0aW9uc1trZXldO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gXCJvYmplY3RcIikge1xuICAgICAgdmFsdWUgPSB2YWx1ZS5lbnY7XG4gICAgfVxuICAgIGlmICh2YWx1ZSkge1xuICAgICAgb2JqZWN0W3ZhbHVlXSA9IGtleTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdDtcbiAgfSwge30pO1xuXG4gIF9kZWZhdWx0cyA9IE9iamVjdC5rZXlzKGRlZmluaXRpb25zKS5yZWR1Y2UoKGRlZnMsIG9wdCkgPT4ge1xuICAgIGlmKF9kZWZpbml0aW9uc1tvcHRdLmRlZmF1bHQpIHtcbiAgICAgIGRlZnNbb3B0XSA9IF9kZWZpbml0aW9uc1tvcHRdLmRlZmF1bHQ7XG4gICAgfVxuICAgIHJldHVybiBkZWZzO1xuICB9LCB7fSk7XG5cbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgdGhpcy5vbignLS1oZWxwJywgZnVuY3Rpb24oKXtcbiAgICBjb25zb2xlLmxvZygnICBDb25maWd1cmUgRnJvbSBFbnZpcm9ubWVudDonKTtcbiAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgT2JqZWN0LmtleXMoX3JldmVyc2VEZWZpbml0aW9ucykuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhgICAgICQgJHtrZXl9PScke19yZXZlcnNlRGVmaW5pdGlvbnNba2V5XX0nYCk7XG4gICAgfSk7XG4gICAgY29uc29sZS5sb2coJycpO1xuICB9KTtcbn07XG5cbmZ1bmN0aW9uIHBhcnNlRW52aXJvbm1lbnQoZW52ID0ge30pIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKF9yZXZlcnNlRGVmaW5pdGlvbnMpLnJlZHVjZSgob3B0aW9ucywga2V5KSA9PiB7XG4gICAgaWYgKGVudltrZXldKSB7XG4gICAgICBjb25zdCBvcmlnaW5hbEtleSA9IF9yZXZlcnNlRGVmaW5pdGlvbnNba2V5XTtcbiAgICAgIGxldCBhY3Rpb24gPSAob3B0aW9uKSA9PiAob3B0aW9uKTtcbiAgICAgIGlmICh0eXBlb2YgX2RlZmluaXRpb25zW29yaWdpbmFsS2V5XSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBhY3Rpb24gPSBfZGVmaW5pdGlvbnNbb3JpZ2luYWxLZXldLmFjdGlvbiB8fCBhY3Rpb247XG4gICAgICB9XG4gICAgICBvcHRpb25zW19yZXZlcnNlRGVmaW5pdGlvbnNba2V5XV0gPSBhY3Rpb24oZW52W2tleV0pO1xuICAgIH1cbiAgICByZXR1cm4gb3B0aW9ucztcbiAgfSwge30pO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNvbmZpZ0ZpbGUocHJvZ3JhbSkge1xuICBsZXQgb3B0aW9ucyA9IHt9O1xuICBpZiAocHJvZ3JhbS5hcmdzLmxlbmd0aCA+IDApIHtcbiAgICBsZXQganNvblBhdGggPSBwcm9ncmFtLmFyZ3NbMF07XG4gICAganNvblBhdGggPSBwYXRoLnJlc29sdmUoanNvblBhdGgpO1xuICAgIGNvbnN0IGpzb25Db25maWcgPSByZXF1aXJlKGpzb25QYXRoKTtcbiAgICBpZiAoanNvbkNvbmZpZy5hcHBzKSB7XG4gICAgICBpZiAoanNvbkNvbmZpZy5hcHBzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgJ011bHRpcGxlIGFwcHMgYXJlIG5vdCBzdXBwb3J0ZWQnO1xuICAgICAgfVxuICAgICAgb3B0aW9ucyA9IGpzb25Db25maWcuYXBwc1swXTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3B0aW9ucyA9IGpzb25Db25maWc7XG4gICAgfVxuICAgIE9iamVjdC5rZXlzKG9wdGlvbnMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSBvcHRpb25zW2tleV07XG4gICAgICBpZiAoIV9kZWZpbml0aW9uc1trZXldKSB7XG4gICAgICAgIHRocm93IGBlcnJvcjogdW5rbm93biBvcHRpb24gJHtrZXl9YDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFjdGlvbiA9IF9kZWZpbml0aW9uc1trZXldLmFjdGlvbjtcbiAgICAgIGlmIChhY3Rpb24pIHtcbiAgICAgICAgb3B0aW9uc1trZXldID0gYWN0aW9uKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjb25zb2xlLmxvZyhgQ29uZmlndXJhdGlvbiBsb2FkZWQgZnJvbSAke2pzb25QYXRofWApXG4gIH1cbiAgcmV0dXJuIG9wdGlvbnM7XG59XG5cbkNvbW1hbmQucHJvdG90eXBlLnNldFZhbHVlc0lmTmVlZGVkID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICBPYmplY3Qua2V5cyhvcHRpb25zKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICBpZiAoIXRoaXMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgdGhpc1trZXldID0gb3B0aW9uc1trZXldO1xuICAgIH1cbiAgfSk7XG59O1xuXG5Db21tYW5kLnByb3RvdHlwZS5fcGFyc2UgPSBDb21tYW5kLnByb3RvdHlwZS5wYXJzZTtcblxuQ29tbWFuZC5wcm90b3R5cGUucGFyc2UgPSBmdW5jdGlvbihhcmdzLCBlbnYpIHtcbiAgdGhpcy5fcGFyc2UoYXJncyk7XG4gIC8vIFBhcnNlIHRoZSBlbnZpcm9ubWVudCBmaXJzdFxuICBjb25zdCBlbnZPcHRpb25zID0gcGFyc2VFbnZpcm9ubWVudChlbnYpO1xuICBjb25zdCBmcm9tRmlsZSA9IHBhcnNlQ29uZmlnRmlsZSh0aGlzKTtcbiAgLy8gTG9hZCB0aGUgZW52IGlmIG5vdCBwYXNzZWQgZnJvbSBjb21tYW5kIGxpbmVcbiAgdGhpcy5zZXRWYWx1ZXNJZk5lZWRlZChlbnZPcHRpb25zKTtcbiAgLy8gTG9hZCBmcm9tIGZpbGUgdG8gb3ZlcnJpZGVcbiAgdGhpcy5zZXRWYWx1ZXNJZk5lZWRlZChmcm9tRmlsZSk7XG4gIC8vIExhc3Qgc2V0IHRoZSBkZWZhdWx0c1xuICB0aGlzLnNldFZhbHVlc0lmTmVlZGVkKF9kZWZhdWx0cyk7XG59O1xuXG5Db21tYW5kLnByb3RvdHlwZS5nZXRPcHRpb25zID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhfZGVmaW5pdGlvbnMpLnJlZHVjZSgob3B0aW9ucywga2V5KSA9PiB7XG4gICAgaWYgKHR5cGVvZiB0aGlzW2tleV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBvcHRpb25zW2tleV0gPSB0aGlzW2tleV07XG4gICAgfVxuICAgIHJldHVybiBvcHRpb25zO1xuICB9LCB7fSk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBuZXcgQ29tbWFuZCgpO1xuLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG4iXX0= \ No newline at end of file diff --git a/lib/cli/utils/runner.js b/lib/cli/utils/runner.js index 0f38ab9e2e..3775f3eb2d 100644 --- a/lib/cli/utils/runner.js +++ b/lib/cli/utils/runner.js @@ -50,4 +50,5 @@ function logStartupOptions(options) { console.log(`${key}: ${value}`); /* eslint-enable no-console */ } -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvdXRpbHMvcnVubmVyLmpzIl0sIm5hbWVzIjpbImRlZmluaXRpb25zIiwiaGVscCIsInVzYWdlIiwic3RhcnQiLCJwcm9ncmFtIiwibG9hZERlZmluaXRpb25zIiwib24iLCJwYXJzZSIsInByb2Nlc3MiLCJhcmd2IiwiZW52Iiwib3B0aW9ucyIsImdldE9wdGlvbnMiLCJsb2dTdGFydHVwT3B0aW9ucyIsImtleSIsInZhbHVlIiwiSlNPTiIsInN0cmluZ2lmeSIsImUiLCJjb25zdHJ1Y3RvciIsIm5hbWUiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7a0JBd0JlLFVBQVM7QUFDdEJBLGFBRHNCO0FBRXRCQyxNQUZzQjtBQUd0QkMsT0FIc0I7QUFJdEJDO0FBSnNCLENBQVQsRUFLWjtBQUNEQyxzQkFBUUMsZUFBUixDQUF3QkwsV0FBeEI7QUFDQSxNQUFJRSxLQUFKLEVBQVc7QUFDVEUsd0JBQVFGLEtBQVIsQ0FBY0EsS0FBZDtBQUNEO0FBQ0QsTUFBSUQsSUFBSixFQUFVO0FBQ1JHLHdCQUFRRSxFQUFSLENBQVcsUUFBWCxFQUFxQkwsSUFBckI7QUFDRDtBQUNERyxzQkFBUUcsS0FBUixDQUFjQyxRQUFRQyxJQUF0QixFQUE0QkQsUUFBUUUsR0FBcEM7O0FBRUEsUUFBTUMsVUFBVVAsb0JBQVFRLFVBQVIsRUFBaEI7QUFDQVQsUUFBTUMsbUJBQU4sRUFBZU8sT0FBZixFQUF3QixZQUFXO0FBQ2pDRSxzQkFBa0JGLE9BQWxCO0FBQ0QsR0FGRDtBQUdELEM7O0FBMUNEOzs7Ozs7QUFFQSxTQUFTRSxpQkFBVCxDQUEyQkYsT0FBM0IsRUFBb0M7QUFDbEMsT0FBSyxNQUFNRyxHQUFYLElBQWtCSCxPQUFsQixFQUEyQjtBQUN6QixRQUFJSSxRQUFRSixRQUFRRyxHQUFSLENBQVo7QUFDQSxRQUFJQSxPQUFPLFdBQVgsRUFBd0I7QUFDdEJDLGNBQVEsZ0JBQVI7QUFDRDtBQUNELFFBQUksT0FBT0EsS0FBUCxLQUFpQixRQUFyQixFQUErQjtBQUM3QixVQUFJO0FBQ0ZBLGdCQUFRQyxLQUFLQyxTQUFMLENBQWVGLEtBQWYsQ0FBUjtBQUNELE9BRkQsQ0FFRSxPQUFNRyxDQUFOLEVBQVM7QUFDVCxZQUFJSCxTQUFTQSxNQUFNSSxXQUFmLElBQThCSixNQUFNSSxXQUFOLENBQWtCQyxJQUFwRCxFQUEwRDtBQUN4REwsa0JBQVFBLE1BQU1JLFdBQU4sQ0FBa0JDLElBQTFCO0FBQ0Q7QUFDRjtBQUNGO0FBQ0Q7QUFDQUMsWUFBUUMsR0FBUixDQUFhLEdBQUVSLEdBQUksS0FBSUMsS0FBTSxFQUE3QjtBQUNBO0FBQ0Q7QUFDRiIsImZpbGUiOiJydW5uZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCBwcm9ncmFtIGZyb20gJy4vY29tbWFuZGVyJztcblxuZnVuY3Rpb24gbG9nU3RhcnR1cE9wdGlvbnMob3B0aW9ucykge1xuICBmb3IgKGNvbnN0IGtleSBpbiBvcHRpb25zKSB7XG4gICAgbGV0IHZhbHVlID0gb3B0aW9uc1trZXldO1xuICAgIGlmIChrZXkgPT0gXCJtYXN0ZXJLZXlcIikge1xuICAgICAgdmFsdWUgPSBcIioqKlJFREFDVEVEKioqXCI7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YWx1ZSA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKVxuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGlmICh2YWx1ZSAmJiB2YWx1ZS5jb25zdHJ1Y3RvciAmJiB2YWx1ZS5jb25zdHJ1Y3Rvci5uYW1lKSB7XG4gICAgICAgICAgdmFsdWUgPSB2YWx1ZS5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbiAgICBjb25zb2xlLmxvZyhgJHtrZXl9OiAke3ZhbHVlfWApO1xuICAgIC8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKHtcbiAgZGVmaW5pdGlvbnMsXG4gIGhlbHAsXG4gIHVzYWdlLFxuICBzdGFydFxufSkge1xuICBwcm9ncmFtLmxvYWREZWZpbml0aW9ucyhkZWZpbml0aW9ucyk7XG4gIGlmICh1c2FnZSkge1xuICAgIHByb2dyYW0udXNhZ2UodXNhZ2UpO1xuICB9XG4gIGlmIChoZWxwKSB7XG4gICAgcHJvZ3JhbS5vbignLS1oZWxwJywgaGVscCk7XG4gIH1cbiAgcHJvZ3JhbS5wYXJzZShwcm9jZXNzLmFyZ3YsIHByb2Nlc3MuZW52KTtcblxuICBjb25zdCBvcHRpb25zID0gcHJvZ3JhbS5nZXRPcHRpb25zKCk7XG4gIHN0YXJ0KHByb2dyYW0sIG9wdGlvbnMsIGZ1bmN0aW9uKCkge1xuICAgIGxvZ1N0YXJ0dXBPcHRpb25zKG9wdGlvbnMpO1xuICB9KTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/cloud-code/HTTPResponse.js b/lib/cloud-code/HTTPResponse.js index 47fd6e9d44..f44701e71d 100644 --- a/lib/cloud-code/HTTPResponse.js +++ b/lib/cloud-code/HTTPResponse.js @@ -53,4 +53,5 @@ class HTTPResponse { }); } } -exports.default = HTTPResponse; \ No newline at end of file +exports.default = HTTPResponse; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1jb2RlL0hUVFBSZXNwb25zZS5qcyJdLCJuYW1lcyI6WyJIVFRQUmVzcG9uc2UiLCJjb25zdHJ1Y3RvciIsInJlc3BvbnNlIiwiYm9keSIsIl90ZXh0IiwiX2RhdGEiLCJzdGF0dXMiLCJzdGF0dXNDb2RlIiwiaGVhZGVycyIsImNvb2tpZXMiLCJCdWZmZXIiLCJpc0J1ZmZlciIsImJ1ZmZlciIsImdldFRleHQiLCJ0b1N0cmluZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJnZXREYXRhIiwicGFyc2UiLCJlIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXQiLCJlbnVtZXJhYmxlIl0sIm1hcHBpbmdzIjoiOzs7OztBQUNlLE1BQU1BLFlBQU4sQ0FBbUI7QUFDaENDLGNBQVlDLFFBQVosRUFBc0JDLElBQXRCLEVBQTRCO0FBQzFCLFFBQUlDLEtBQUosRUFBV0MsS0FBWDtBQUNBLFNBQUtDLE1BQUwsR0FBY0osU0FBU0ssVUFBdkI7QUFDQSxTQUFLQyxPQUFMLEdBQWVOLFNBQVNNLE9BQVQsSUFBb0IsRUFBbkM7QUFDQSxTQUFLQyxPQUFMLEdBQWUsS0FBS0QsT0FBTCxDQUFhLFlBQWIsQ0FBZjs7QUFFQSxRQUFJLE9BQU9MLElBQVAsSUFBZSxRQUFuQixFQUE2QjtBQUMzQkMsY0FBUUQsSUFBUjtBQUNELEtBRkQsTUFFTyxJQUFJTyxPQUFPQyxRQUFQLENBQWdCUixJQUFoQixDQUFKLEVBQTJCO0FBQ2hDLFdBQUtTLE1BQUwsR0FBY1QsSUFBZDtBQUNELEtBRk0sTUFFQSxJQUFJLE9BQU9BLElBQVAsSUFBZSxRQUFuQixFQUE2QjtBQUNsQ0UsY0FBUUYsSUFBUjtBQUNEOztBQUVELFVBQU1VLFVBQVUsTUFBTTtBQUNwQixVQUFJLENBQUNULEtBQUQsSUFBVSxLQUFLUSxNQUFuQixFQUEyQjtBQUN6QlIsZ0JBQVEsS0FBS1EsTUFBTCxDQUFZRSxRQUFaLENBQXFCLE9BQXJCLENBQVI7QUFDRCxPQUZELE1BRU8sSUFBSSxDQUFDVixLQUFELElBQVVDLEtBQWQsRUFBcUI7QUFDMUJELGdCQUFRVyxLQUFLQyxTQUFMLENBQWVYLEtBQWYsQ0FBUjtBQUNEO0FBQ0QsYUFBT0QsS0FBUDtBQUNELEtBUEQ7O0FBU0EsVUFBTWEsVUFBVSxNQUFNO0FBQ3BCLFVBQUksQ0FBQ1osS0FBTCxFQUFZO0FBQ1YsWUFBSTtBQUNGQSxrQkFBUVUsS0FBS0csS0FBTCxDQUFXTCxTQUFYLENBQVI7QUFDRCxTQUZELENBRUUsT0FBT00sQ0FBUCxFQUFVLENBQUUsS0FBTztBQUN0QjtBQUNELGFBQU9kLEtBQVA7QUFDRCxLQVBEOztBQVNBZSxXQUFPQyxjQUFQLENBQXNCLElBQXRCLEVBQTRCLE1BQTVCLEVBQW9DO0FBQ2xDQyxXQUFLLE1BQU07QUFBRSxlQUFPbkIsSUFBUDtBQUFhO0FBRFEsS0FBcEM7O0FBSUFpQixXQUFPQyxjQUFQLENBQXNCLElBQXRCLEVBQTRCLE1BQTVCLEVBQW9DO0FBQ2xDRSxrQkFBWSxJQURzQjtBQUVsQ0QsV0FBS1Q7QUFGNkIsS0FBcEM7O0FBS0FPLFdBQU9DLGNBQVAsQ0FBc0IsSUFBdEIsRUFBNEIsTUFBNUIsRUFBb0M7QUFDbENFLGtCQUFZLElBRHNCO0FBRWxDRCxXQUFLTDtBQUY2QixLQUFwQztBQUlEO0FBOUMrQjtrQkFBYmpCLFkiLCJmaWxlIjoiSFRUUFJlc3BvbnNlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBIVFRQUmVzcG9uc2Uge1xuICBjb25zdHJ1Y3RvcihyZXNwb25zZSwgYm9keSkge1xuICAgIGxldCBfdGV4dCwgX2RhdGE7XG4gICAgdGhpcy5zdGF0dXMgPSByZXNwb25zZS5zdGF0dXNDb2RlO1xuICAgIHRoaXMuaGVhZGVycyA9IHJlc3BvbnNlLmhlYWRlcnMgfHwge307XG4gICAgdGhpcy5jb29raWVzID0gdGhpcy5oZWFkZXJzW1wic2V0LWNvb2tpZVwiXTtcblxuICAgIGlmICh0eXBlb2YgYm9keSA9PSAnc3RyaW5nJykge1xuICAgICAgX3RleHQgPSBib2R5O1xuICAgIH0gZWxzZSBpZiAoQnVmZmVyLmlzQnVmZmVyKGJvZHkpKSB7XG4gICAgICB0aGlzLmJ1ZmZlciA9IGJvZHk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgYm9keSA9PSAnb2JqZWN0Jykge1xuICAgICAgX2RhdGEgPSBib2R5O1xuICAgIH1cblxuICAgIGNvbnN0IGdldFRleHQgPSAoKSA9PiB7XG4gICAgICBpZiAoIV90ZXh0ICYmIHRoaXMuYnVmZmVyKSB7XG4gICAgICAgIF90ZXh0ID0gdGhpcy5idWZmZXIudG9TdHJpbmcoJ3V0Zi04Jyk7XG4gICAgICB9IGVsc2UgaWYgKCFfdGV4dCAmJiBfZGF0YSkge1xuICAgICAgICBfdGV4dCA9IEpTT04uc3RyaW5naWZ5KF9kYXRhKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBfdGV4dDtcbiAgICB9XG5cbiAgICBjb25zdCBnZXREYXRhID0gKCkgPT4ge1xuICAgICAgaWYgKCFfZGF0YSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIF9kYXRhID0gSlNPTi5wYXJzZShnZXRUZXh0KCkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7IC8qICovIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBfZGF0YTtcbiAgICB9XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ2JvZHknLCB7XG4gICAgICBnZXQ6ICgpID0+IHsgcmV0dXJuIGJvZHkgfVxuICAgIH0pO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICd0ZXh0Jywge1xuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogZ2V0VGV4dFxuICAgIH0pO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkYXRhJywge1xuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogZ2V0RGF0YVxuICAgIH0pO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/cloud-code/Parse.Cloud.js b/lib/cloud-code/Parse.Cloud.js index f33baa9116..ab85c206a4 100644 --- a/lib/cloud-code/Parse.Cloud.js +++ b/lib/cloud-code/Parse.Cloud.js @@ -69,4 +69,5 @@ ParseCloud.useMasterKey = () => { ParseCloud.httpRequest = require("./httpRequest"); -module.exports = ParseCloud; \ No newline at end of file +module.exports = ParseCloud; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1jb2RlL1BhcnNlLkNsb3VkLmpzIl0sIm5hbWVzIjpbInRyaWdnZXJzIiwiZ2V0Q2xhc3NOYW1lIiwicGFyc2VDbGFzcyIsImNsYXNzTmFtZSIsIlBhcnNlQ2xvdWQiLCJkZWZpbmUiLCJmdW5jdGlvbk5hbWUiLCJoYW5kbGVyIiwidmFsaWRhdGlvbkhhbmRsZXIiLCJhZGRGdW5jdGlvbiIsIlBhcnNlIiwiYXBwbGljYXRpb25JZCIsImpvYiIsImFkZEpvYiIsImJlZm9yZVNhdmUiLCJhZGRUcmlnZ2VyIiwiVHlwZXMiLCJiZWZvcmVEZWxldGUiLCJhZnRlclNhdmUiLCJhZnRlckRlbGV0ZSIsImJlZm9yZUZpbmQiLCJhZnRlckZpbmQiLCJvbkxpdmVRdWVyeUV2ZW50IiwiYWRkTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVyIiwiX3JlbW92ZUFsbEhvb2tzIiwiX3VucmVnaXN0ZXJBbGwiLCJ1c2VNYXN0ZXJLZXkiLCJjb25zb2xlIiwid2FybiIsImh0dHBSZXF1ZXN0IiwicmVxdWlyZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7O0FBQ0E7O0lBQVlBLFE7Ozs7QUFFWixTQUFTQyxZQUFULENBQXNCQyxVQUF0QixFQUFrQztBQUNoQyxNQUFJQSxjQUFjQSxXQUFXQyxTQUE3QixFQUF3QztBQUN0QyxXQUFPRCxXQUFXQyxTQUFsQjtBQUNEO0FBQ0QsU0FBT0QsVUFBUDtBQUNEOztBQUVELElBQUlFLGFBQWEsRUFBakI7QUFDQUEsV0FBV0MsTUFBWCxHQUFvQixVQUFTQyxZQUFULEVBQXVCQyxPQUF2QixFQUFnQ0MsaUJBQWhDLEVBQW1EO0FBQ3JFUixXQUFTUyxXQUFULENBQXFCSCxZQUFyQixFQUFtQ0MsT0FBbkMsRUFBNENDLGlCQUE1QyxFQUErREUsWUFBTUMsYUFBckU7QUFDRCxDQUZEOztBQUlBUCxXQUFXUSxHQUFYLEdBQWlCLFVBQVNOLFlBQVQsRUFBdUJDLE9BQXZCLEVBQWdDO0FBQy9DUCxXQUFTYSxNQUFULENBQWdCUCxZQUFoQixFQUE4QkMsT0FBOUIsRUFBdUNHLFlBQU1DLGFBQTdDO0FBQ0QsQ0FGRDs7QUFJQVAsV0FBV1UsVUFBWCxHQUF3QixVQUFTWixVQUFULEVBQXFCSyxPQUFyQixFQUE4QjtBQUNwRCxNQUFJSixZQUFZRixhQUFhQyxVQUFiLENBQWhCO0FBQ0FGLFdBQVNlLFVBQVQsQ0FBb0JmLFNBQVNnQixLQUFULENBQWVGLFVBQW5DLEVBQStDWCxTQUEvQyxFQUEwREksT0FBMUQsRUFBbUVHLFlBQU1DLGFBQXpFO0FBQ0QsQ0FIRDs7QUFLQVAsV0FBV2EsWUFBWCxHQUEwQixVQUFTZixVQUFULEVBQXFCSyxPQUFyQixFQUE4QjtBQUN0RCxNQUFJSixZQUFZRixhQUFhQyxVQUFiLENBQWhCO0FBQ0FGLFdBQVNlLFVBQVQsQ0FBb0JmLFNBQVNnQixLQUFULENBQWVDLFlBQW5DLEVBQWlEZCxTQUFqRCxFQUE0REksT0FBNUQsRUFBcUVHLFlBQU1DLGFBQTNFO0FBQ0QsQ0FIRDs7QUFLQVAsV0FBV2MsU0FBWCxHQUF1QixVQUFTaEIsVUFBVCxFQUFxQkssT0FBckIsRUFBOEI7QUFDbkQsTUFBSUosWUFBWUYsYUFBYUMsVUFBYixDQUFoQjtBQUNBRixXQUFTZSxVQUFULENBQW9CZixTQUFTZ0IsS0FBVCxDQUFlRSxTQUFuQyxFQUE4Q2YsU0FBOUMsRUFBeURJLE9BQXpELEVBQWtFRyxZQUFNQyxhQUF4RTtBQUNELENBSEQ7O0FBS0FQLFdBQVdlLFdBQVgsR0FBeUIsVUFBU2pCLFVBQVQsRUFBcUJLLE9BQXJCLEVBQThCO0FBQ3JELE1BQUlKLFlBQVlGLGFBQWFDLFVBQWIsQ0FBaEI7QUFDQUYsV0FBU2UsVUFBVCxDQUFvQmYsU0FBU2dCLEtBQVQsQ0FBZUcsV0FBbkMsRUFBZ0RoQixTQUFoRCxFQUEyREksT0FBM0QsRUFBb0VHLFlBQU1DLGFBQTFFO0FBQ0QsQ0FIRDs7QUFLQVAsV0FBV2dCLFVBQVgsR0FBd0IsVUFBU2xCLFVBQVQsRUFBcUJLLE9BQXJCLEVBQThCO0FBQ3BELE1BQUlKLFlBQVlGLGFBQWFDLFVBQWIsQ0FBaEI7QUFDQUYsV0FBU2UsVUFBVCxDQUFvQmYsU0FBU2dCLEtBQVQsQ0FBZUksVUFBbkMsRUFBK0NqQixTQUEvQyxFQUEwREksT0FBMUQsRUFBbUVHLFlBQU1DLGFBQXpFO0FBQ0QsQ0FIRDs7QUFLQVAsV0FBV2lCLFNBQVgsR0FBdUIsVUFBU25CLFVBQVQsRUFBcUJLLE9BQXJCLEVBQThCO0FBQ25ELFFBQU1KLFlBQVlGLGFBQWFDLFVBQWIsQ0FBbEI7QUFDQUYsV0FBU2UsVUFBVCxDQUFvQmYsU0FBU2dCLEtBQVQsQ0FBZUssU0FBbkMsRUFBOENsQixTQUE5QyxFQUF5REksT0FBekQsRUFBa0VHLFlBQU1DLGFBQXhFO0FBQ0QsQ0FIRDs7QUFLQVAsV0FBV2tCLGdCQUFYLEdBQThCLFVBQVNmLE9BQVQsRUFBa0I7QUFDOUNQLFdBQVN1Qix3QkFBVCxDQUFrQ2hCLE9BQWxDLEVBQTJDRyxZQUFNQyxhQUFqRDtBQUNELENBRkQ7O0FBSUFQLFdBQVdvQixlQUFYLEdBQTZCLE1BQU07QUFDakN4QixXQUFTeUIsY0FBVDtBQUNELENBRkQ7O0FBSUFyQixXQUFXc0IsWUFBWCxHQUEwQixNQUFNO0FBQzlCO0FBQ0FDLFVBQVFDLElBQVIsQ0FBYSw0TkFBYjtBQUNELENBSEQ7O0FBS0F4QixXQUFXeUIsV0FBWCxHQUF5QkMsUUFBUSxlQUFSLENBQXpCOztBQUVBQyxPQUFPQyxPQUFQLEdBQWlCNUIsVUFBakIiLCJmaWxlIjoiUGFyc2UuQ2xvdWQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9ICAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCAqIGFzIHRyaWdnZXJzIGZyb20gJy4uL3RyaWdnZXJzJztcblxuZnVuY3Rpb24gZ2V0Q2xhc3NOYW1lKHBhcnNlQ2xhc3MpIHtcbiAgaWYgKHBhcnNlQ2xhc3MgJiYgcGFyc2VDbGFzcy5jbGFzc05hbWUpIHtcbiAgICByZXR1cm4gcGFyc2VDbGFzcy5jbGFzc05hbWU7XG4gIH1cbiAgcmV0dXJuIHBhcnNlQ2xhc3M7XG59XG5cbnZhciBQYXJzZUNsb3VkID0ge307XG5QYXJzZUNsb3VkLmRlZmluZSA9IGZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgaGFuZGxlciwgdmFsaWRhdGlvbkhhbmRsZXIpIHtcbiAgdHJpZ2dlcnMuYWRkRnVuY3Rpb24oZnVuY3Rpb25OYW1lLCBoYW5kbGVyLCB2YWxpZGF0aW9uSGFuZGxlciwgUGFyc2UuYXBwbGljYXRpb25JZCk7XG59O1xuXG5QYXJzZUNsb3VkLmpvYiA9IGZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgaGFuZGxlcikge1xuICB0cmlnZ2Vycy5hZGRKb2IoZnVuY3Rpb25OYW1lLCBoYW5kbGVyLCBQYXJzZS5hcHBsaWNhdGlvbklkKTtcbn07XG5cblBhcnNlQ2xvdWQuYmVmb3JlU2F2ZSA9IGZ1bmN0aW9uKHBhcnNlQ2xhc3MsIGhhbmRsZXIpIHtcbiAgdmFyIGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShwYXJzZUNsYXNzKTtcbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcih0cmlnZ2Vycy5UeXBlcy5iZWZvcmVTYXZlLCBjbGFzc05hbWUsIGhhbmRsZXIsIFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xufTtcblxuUGFyc2VDbG91ZC5iZWZvcmVEZWxldGUgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIHZhciBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUocGFyc2VDbGFzcyk7XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIodHJpZ2dlcnMuVHlwZXMuYmVmb3JlRGVsZXRlLCBjbGFzc05hbWUsIGhhbmRsZXIsIFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xufTtcblxuUGFyc2VDbG91ZC5hZnRlclNhdmUgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIHZhciBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUocGFyc2VDbGFzcyk7XG4gIHRyaWdnZXJzLmFkZFRyaWdnZXIodHJpZ2dlcnMuVHlwZXMuYWZ0ZXJTYXZlLCBjbGFzc05hbWUsIGhhbmRsZXIsIFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xufTtcblxuUGFyc2VDbG91ZC5hZnRlckRlbGV0ZSA9IGZ1bmN0aW9uKHBhcnNlQ2xhc3MsIGhhbmRsZXIpIHtcbiAgdmFyIGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShwYXJzZUNsYXNzKTtcbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcih0cmlnZ2Vycy5UeXBlcy5hZnRlckRlbGV0ZSwgY2xhc3NOYW1lLCBoYW5kbGVyLCBQYXJzZS5hcHBsaWNhdGlvbklkKTtcbn07XG5cblBhcnNlQ2xvdWQuYmVmb3JlRmluZCA9IGZ1bmN0aW9uKHBhcnNlQ2xhc3MsIGhhbmRsZXIpIHtcbiAgdmFyIGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShwYXJzZUNsYXNzKTtcbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcih0cmlnZ2Vycy5UeXBlcy5iZWZvcmVGaW5kLCBjbGFzc05hbWUsIGhhbmRsZXIsIFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xufTtcblxuUGFyc2VDbG91ZC5hZnRlckZpbmQgPSBmdW5jdGlvbihwYXJzZUNsYXNzLCBoYW5kbGVyKSB7XG4gIGNvbnN0IGNsYXNzTmFtZSA9IGdldENsYXNzTmFtZShwYXJzZUNsYXNzKTtcbiAgdHJpZ2dlcnMuYWRkVHJpZ2dlcih0cmlnZ2Vycy5UeXBlcy5hZnRlckZpbmQsIGNsYXNzTmFtZSwgaGFuZGxlciwgUGFyc2UuYXBwbGljYXRpb25JZCk7XG59O1xuXG5QYXJzZUNsb3VkLm9uTGl2ZVF1ZXJ5RXZlbnQgPSBmdW5jdGlvbihoYW5kbGVyKSB7XG4gIHRyaWdnZXJzLmFkZExpdmVRdWVyeUV2ZW50SGFuZGxlcihoYW5kbGVyLCBQYXJzZS5hcHBsaWNhdGlvbklkKTtcbn07XG5cblBhcnNlQ2xvdWQuX3JlbW92ZUFsbEhvb2tzID0gKCkgPT4ge1xuICB0cmlnZ2Vycy5fdW5yZWdpc3RlckFsbCgpO1xufVxuXG5QYXJzZUNsb3VkLnVzZU1hc3RlcktleSA9ICgpID0+IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gIGNvbnNvbGUud2FybihcIlBhcnNlLkNsb3VkLnVzZU1hc3RlcktleSBpcyBkZXByZWNhdGVkIChhbmQgaGFzIG5vIGVmZmVjdCBhbnltb3JlKSBvbiBwYXJzZS1zZXJ2ZXIsIHBsZWFzZSByZWZlciB0byB0aGUgY2xvdWQgY29kZSBtaWdyYXRpb24gbm90ZXM6IGh0dHA6Ly9kb2NzLnBhcnNlcGxhdGZvcm0ub3JnL3BhcnNlLXNlcnZlci9ndWlkZS8jbWFzdGVyLWtleS1tdXN0LWJlLXBhc3NlZC1leHBsaWNpdGx5XCIpXG59XG5cblBhcnNlQ2xvdWQuaHR0cFJlcXVlc3QgPSByZXF1aXJlKFwiLi9odHRwUmVxdWVzdFwiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBQYXJzZUNsb3VkO1xuIl19 \ No newline at end of file diff --git a/lib/cloud-code/httpRequest.js b/lib/cloud-code/httpRequest.js index 64188f20dc..f72234e262 100644 --- a/lib/cloud-code/httpRequest.js +++ b/lib/cloud-code/httpRequest.js @@ -98,4 +98,5 @@ module.exports = function (options) { return promise; }; -module.exports.encodeBody = encodeBody; \ No newline at end of file +module.exports.encodeBody = encodeBody; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1jb2RlL2h0dHBSZXF1ZXN0LmpzIl0sIm5hbWVzIjpbImVuY29kZUJvZHkiLCJib2R5IiwiaGVhZGVycyIsImNvbnRlbnRUeXBlS2V5cyIsIk9iamVjdCIsImtleXMiLCJmaWx0ZXIiLCJrZXkiLCJtYXRjaCIsImxlbmd0aCIsInF1ZXJ5c3RyaW5nIiwic3RyaW5naWZ5IiwibG9nIiwiZXJyb3IiLCJjb250ZW50VHlwZSIsIkpTT04iLCJtb2R1bGUiLCJleHBvcnRzIiwib3B0aW9ucyIsInByb21pc2UiLCJQYXJzZSIsIlByb21pc2UiLCJjYWxsYmFja3MiLCJzdWNjZXNzIiwidXJpIiwiYXNzaWduIiwiZm9sbG93UmVkaXJlY3QiLCJmb2xsb3dSZWRpcmVjdHMiLCJwYXJhbXMiLCJxcyIsInBhcnNlIiwiZW5jb2RpbmciLCJyZXNwb25zZSIsInJlamVjdCIsImh0dHBSZXNwb25zZSIsIkhUVFBSZXNwb25zZSIsInN0YXR1cyIsInJlc29sdmUiXSwibWFwcGluZ3MiOiI7O0FBQUE7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBRUEsSUFBSUEsYUFBYSxVQUFTLEVBQUNDLElBQUQsRUFBT0MsVUFBVSxFQUFqQixFQUFULEVBQStCO0FBQzlDLE1BQUksT0FBT0QsSUFBUCxLQUFnQixRQUFwQixFQUE4QjtBQUM1QixXQUFPLEVBQUNBLElBQUQsRUFBT0MsT0FBUCxFQUFQO0FBQ0Q7QUFDRCxNQUFJQyxrQkFBa0JDLE9BQU9DLElBQVAsQ0FBWUgsT0FBWixFQUFxQkksTUFBckIsQ0FBNkJDLEdBQUQsSUFBUztBQUN6RCxXQUFPQSxJQUFJQyxLQUFKLENBQVUsZUFBVixLQUE4QixJQUFyQztBQUNELEdBRnFCLENBQXRCOztBQUlBLE1BQUlMLGdCQUFnQk0sTUFBaEIsSUFBMEIsQ0FBOUIsRUFBaUM7QUFDL0I7QUFDQTs7QUFFQVIsV0FBT1Msc0JBQVlDLFNBQVosQ0FBc0JWLElBQXRCLENBQVA7QUFDQUMsWUFBUSxjQUFSLElBQTBCLG1DQUExQjtBQUNELEdBTkQsTUFNTztBQUNMO0FBQ0EsUUFBSUMsZ0JBQWdCTSxNQUFoQixHQUF5QixDQUE3QixFQUFnQztBQUM5QkcsdUJBQUlDLEtBQUosQ0FBVSx5QkFBVixFQUFxQyx3Q0FBckM7QUFDRDtBQUNEO0FBQ0EsUUFBSUMsY0FBY1gsZ0JBQWdCLENBQWhCLENBQWxCO0FBQ0EsUUFBSUQsUUFBUVksV0FBUixFQUFxQk4sS0FBckIsQ0FBMkIsb0JBQTNCLENBQUosRUFBc0Q7QUFDcERQLGFBQU9jLEtBQUtKLFNBQUwsQ0FBZVYsSUFBZixDQUFQO0FBQ0QsS0FGRCxNQUVPLElBQUdDLFFBQVFZLFdBQVIsRUFBcUJOLEtBQXJCLENBQTJCLHFDQUEzQixDQUFILEVBQXNFO0FBQzNFUCxhQUFPUyxzQkFBWUMsU0FBWixDQUFzQlYsSUFBdEIsQ0FBUDtBQUNEO0FBQ0Y7QUFDRCxTQUFPLEVBQUNBLElBQUQsRUFBT0MsT0FBUCxFQUFQO0FBQ0QsQ0E1QkQ7O0FBOEJBYyxPQUFPQyxPQUFQLEdBQWlCLFVBQVNDLE9BQVQsRUFBa0I7QUFDakMsTUFBSUMsVUFBVSxJQUFJQyxlQUFNQyxPQUFWLEVBQWQ7QUFDQSxNQUFJQyxZQUFZO0FBQ2RDLGFBQVNMLFFBQVFLLE9BREg7QUFFZFYsV0FBT0ssUUFBUUw7QUFGRCxHQUFoQjtBQUlBLFNBQU9LLFFBQVFLLE9BQWY7QUFDQSxTQUFPTCxRQUFRTCxLQUFmO0FBQ0EsU0FBT0ssUUFBUU0sR0FBZixDQVJpQyxDQVFiO0FBQ3BCTixZQUFVZCxPQUFPcUIsTUFBUCxDQUFjUCxPQUFkLEVBQXdCbEIsV0FBV2tCLE9BQVgsQ0FBeEIsQ0FBVjtBQUNBO0FBQ0FBLFVBQVFRLGNBQVIsR0FBeUJSLFFBQVFTLGVBQVIsSUFBMkIsSUFBcEQ7QUFDQTtBQUNBLE1BQUksT0FBT1QsUUFBUVUsTUFBZixLQUEwQixRQUE5QixFQUF3QztBQUN0Q1YsWUFBUVcsRUFBUixHQUFhWCxRQUFRVSxNQUFyQjtBQUNELEdBRkQsTUFFTyxJQUFJLE9BQU9WLFFBQVFVLE1BQWYsS0FBMEIsUUFBOUIsRUFBd0M7QUFDN0NWLFlBQVFXLEVBQVIsR0FBYW5CLHNCQUFZb0IsS0FBWixDQUFrQlosUUFBUVUsTUFBMUIsQ0FBYjtBQUNEO0FBQ0Q7QUFDQVYsVUFBUWEsUUFBUixHQUFtQixJQUFuQjs7QUFFQSx5QkFBUWIsT0FBUixFQUFpQixDQUFDTCxLQUFELEVBQVFtQixRQUFSLEVBQWtCL0IsSUFBbEIsS0FBMkI7QUFDMUMsUUFBSVksS0FBSixFQUFXO0FBQ1QsVUFBSVMsVUFBVVQsS0FBZCxFQUFxQjtBQUNuQlMsa0JBQVVULEtBQVYsQ0FBZ0JBLEtBQWhCO0FBQ0Q7QUFDRCxhQUFPTSxRQUFRYyxNQUFSLENBQWVwQixLQUFmLENBQVA7QUFDRDtBQUNELFVBQU1xQixlQUFlLElBQUlDLHNCQUFKLENBQWlCSCxRQUFqQixFQUEyQi9CLElBQTNCLENBQXJCOztBQUVBO0FBQ0EsUUFBSWlDLGFBQWFFLE1BQWIsR0FBc0IsR0FBdEIsSUFBNkJGLGFBQWFFLE1BQWIsSUFBdUIsR0FBeEQsRUFBNkQ7QUFDM0QsVUFBSWQsVUFBVVQsS0FBZCxFQUFxQjtBQUNuQlMsa0JBQVVULEtBQVYsQ0FBZ0JxQixZQUFoQjtBQUNEO0FBQ0QsYUFBT2YsUUFBUWMsTUFBUixDQUFlQyxZQUFmLENBQVA7QUFDRCxLQUxELE1BS087QUFDTCxVQUFJWixVQUFVQyxPQUFkLEVBQXVCO0FBQ3JCRCxrQkFBVUMsT0FBVixDQUFrQlcsWUFBbEI7QUFDRDtBQUNELGFBQU9mLFFBQVFrQixPQUFSLENBQWdCSCxZQUFoQixDQUFQO0FBQ0Q7QUFDRixHQXJCRDtBQXNCQSxTQUFPZixPQUFQO0FBQ0QsQ0E1Q0Q7O0FBOENBSCxPQUFPQyxPQUFQLENBQWVqQixVQUFmLEdBQTRCQSxVQUE1QiIsImZpbGUiOiJodHRwUmVxdWVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCByZXF1ZXN0IGZyb20gJ3JlcXVlc3QnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IEhUVFBSZXNwb25zZSBmcm9tICcuL0hUVFBSZXNwb25zZSc7XG5pbXBvcnQgcXVlcnlzdHJpbmcgZnJvbSAncXVlcnlzdHJpbmcnO1xuaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXInO1xuXG52YXIgZW5jb2RlQm9keSA9IGZ1bmN0aW9uKHtib2R5LCBoZWFkZXJzID0ge319KSB7XG4gIGlmICh0eXBlb2YgYm9keSAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4ge2JvZHksIGhlYWRlcnN9O1xuICB9XG4gIHZhciBjb250ZW50VHlwZUtleXMgPSBPYmplY3Qua2V5cyhoZWFkZXJzKS5maWx0ZXIoKGtleSkgPT4ge1xuICAgIHJldHVybiBrZXkubWF0Y2goL2NvbnRlbnQtdHlwZS9pKSAhPSBudWxsO1xuICB9KTtcblxuICBpZiAoY29udGVudFR5cGVLZXlzLmxlbmd0aCA9PSAwKSB7XG4gICAgLy8gbm8gY29udGVudCB0eXBlXG4gICAgLy8gIEFzIHBlciBodHRwczovL3BhcnNlLmNvbS9kb2NzL2Nsb3VkY29kZS9ndWlkZSNjbG91ZC1jb2RlLWFkdmFuY2VkLXNlbmRpbmctYS1wb3N0LXJlcXVlc3QgdGhlIGRlZmF1bHQgZW5jb2RpbmcgaXMgc3VwcG9zZWRseSB4LXd3dy1mb3JtLXVybGVuY29kZWRcblxuICAgIGJvZHkgPSBxdWVyeXN0cmluZy5zdHJpbmdpZnkoYm9keSk7XG4gICAgaGVhZGVyc1snQ29udGVudC1UeXBlJ10gPSAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJztcbiAgfSBlbHNlIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmIChjb250ZW50VHlwZUtleXMubGVuZ3RoID4gMSkge1xuICAgICAgbG9nLmVycm9yKCdQYXJzZS5DbG91ZC5odHRwUmVxdWVzdCcsICdtdWx0aXBsZSBjb250ZW50LXR5cGUgaGVhZGVycyBhcmUgc2V0LicpO1xuICAgIH1cbiAgICAvLyBUaGVyZSBtYXliZSBtYW55LCB3ZSdsbCBqdXN0IHRha2UgdGhlIDFzdCBvbmVcbiAgICB2YXIgY29udGVudFR5cGUgPSBjb250ZW50VHlwZUtleXNbMF07XG4gICAgaWYgKGhlYWRlcnNbY29udGVudFR5cGVdLm1hdGNoKC9hcHBsaWNhdGlvblxcL2pzb24vaSkpIHtcbiAgICAgIGJvZHkgPSBKU09OLnN0cmluZ2lmeShib2R5KTtcbiAgICB9IGVsc2UgaWYoaGVhZGVyc1tjb250ZW50VHlwZV0ubWF0Y2goL2FwcGxpY2F0aW9uXFwveC13d3ctZm9ybS11cmxlbmNvZGVkL2kpKSB7XG4gICAgICBib2R5ID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KGJvZHkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4ge2JvZHksIGhlYWRlcnN9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgdmFyIHByb21pc2UgPSBuZXcgUGFyc2UuUHJvbWlzZSgpO1xuICB2YXIgY2FsbGJhY2tzID0ge1xuICAgIHN1Y2Nlc3M6IG9wdGlvbnMuc3VjY2VzcyxcbiAgICBlcnJvcjogb3B0aW9ucy5lcnJvclxuICB9O1xuICBkZWxldGUgb3B0aW9ucy5zdWNjZXNzO1xuICBkZWxldGUgb3B0aW9ucy5lcnJvcjtcbiAgZGVsZXRlIG9wdGlvbnMudXJpOyAvLyBub3Qgc3VwcG9ydGVkXG4gIG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKG9wdGlvbnMsICBlbmNvZGVCb2R5KG9wdGlvbnMpKTtcbiAgLy8gc2V0IGZvbGxvdyByZWRpcmVjdHMgdG8gZmFsc2UgYnkgZGVmYXVsdFxuICBvcHRpb25zLmZvbGxvd1JlZGlyZWN0ID0gb3B0aW9ucy5mb2xsb3dSZWRpcmVjdHMgPT0gdHJ1ZTtcbiAgLy8gc3VwcG9ydCBwYXJhbXMgb3B0aW9uc1xuICBpZiAodHlwZW9mIG9wdGlvbnMucGFyYW1zID09PSAnb2JqZWN0Jykge1xuICAgIG9wdGlvbnMucXMgPSBvcHRpb25zLnBhcmFtcztcbiAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucy5wYXJhbXMgPT09ICdzdHJpbmcnKSB7XG4gICAgb3B0aW9ucy5xcyA9IHF1ZXJ5c3RyaW5nLnBhcnNlKG9wdGlvbnMucGFyYW1zKTtcbiAgfVxuICAvLyBmb3JjZSB0aGUgcmVzcG9uc2UgYXMgYSBidWZmZXJcbiAgb3B0aW9ucy5lbmNvZGluZyA9IG51bGw7XG5cbiAgcmVxdWVzdChvcHRpb25zLCAoZXJyb3IsIHJlc3BvbnNlLCBib2R5KSA9PiB7XG4gICAgaWYgKGVycm9yKSB7XG4gICAgICBpZiAoY2FsbGJhY2tzLmVycm9yKSB7XG4gICAgICAgIGNhbGxiYWNrcy5lcnJvcihlcnJvcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuICAgIH1cbiAgICBjb25zdCBodHRwUmVzcG9uc2UgPSBuZXcgSFRUUFJlc3BvbnNlKHJlc3BvbnNlLCBib2R5KTtcblxuICAgIC8vIENvbnNpZGVyIDwyMDAgJiYgPj0gNDAwIGFzIGVycm9yc1xuICAgIGlmIChodHRwUmVzcG9uc2Uuc3RhdHVzIDwgMjAwIHx8IGh0dHBSZXNwb25zZS5zdGF0dXMgPj0gNDAwKSB7XG4gICAgICBpZiAoY2FsbGJhY2tzLmVycm9yKSB7XG4gICAgICAgIGNhbGxiYWNrcy5lcnJvcihodHRwUmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByb21pc2UucmVqZWN0KGh0dHBSZXNwb25zZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChjYWxsYmFja3Muc3VjY2Vzcykge1xuICAgICAgICBjYWxsYmFja3Muc3VjY2VzcyhodHRwUmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByb21pc2UucmVzb2x2ZShodHRwUmVzcG9uc2UpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBwcm9taXNlO1xufTtcblxubW9kdWxlLmV4cG9ydHMuZW5jb2RlQm9keSA9IGVuY29kZUJvZHk7XG4iXX0= \ No newline at end of file diff --git a/lib/cryptoUtils.js b/lib/cryptoUtils.js index 1eae0aab4c..dbe462a569 100644 --- a/lib/cryptoUtils.js +++ b/lib/cryptoUtils.js @@ -55,4 +55,5 @@ function newToken() { function md5Hash(string) { return (0, _crypto.createHash)('md5').update(string).digest('hex'); -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jcnlwdG9VdGlscy5qcyJdLCJuYW1lcyI6WyJyYW5kb21IZXhTdHJpbmciLCJyYW5kb21TdHJpbmciLCJuZXdPYmplY3RJZCIsIm5ld1Rva2VuIiwibWQ1SGFzaCIsInNpemUiLCJFcnJvciIsInRvU3RyaW5nIiwiY2hhcnMiLCJvYmplY3RJZCIsImJ5dGVzIiwiaSIsImxlbmd0aCIsInJlYWRVSW50OCIsInN0cmluZyIsInVwZGF0ZSIsImRpZ2VzdCJdLCJtYXBwaW5ncyI6Ijs7Ozs7UUFLZ0JBLGUsR0FBQUEsZTtRQWdCQUMsWSxHQUFBQSxZO1FBZ0JBQyxXLEdBQUFBLFc7UUFLQUMsUSxHQUFBQSxRO1FBSUFDLE8sR0FBQUEsTzs7QUE1Q2hCOztBQUVBO0FBQ08sU0FBU0osZUFBVCxDQUF5QkssSUFBekIsRUFBK0M7QUFDcEQsTUFBSUEsU0FBUyxDQUFiLEVBQWdCO0FBQ2QsVUFBTSxJQUFJQyxLQUFKLENBQVUseUNBQVYsQ0FBTjtBQUNEO0FBQ0QsTUFBSUQsT0FBTyxDQUFQLEtBQWEsQ0FBakIsRUFBb0I7QUFDbEIsVUFBTSxJQUFJQyxLQUFKLENBQVUsOENBQVYsQ0FBTjtBQUNEO0FBQ0QsU0FBTyx5QkFBWUQsT0FBTyxDQUFuQixFQUFzQkUsUUFBdEIsQ0FBK0IsS0FBL0IsQ0FBUDtBQUNEOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU04sWUFBVCxDQUFzQkksSUFBdEIsRUFBNEM7QUFDakQsTUFBSUEsU0FBUyxDQUFiLEVBQWdCO0FBQ2QsVUFBTSxJQUFJQyxLQUFKLENBQVUsc0NBQVYsQ0FBTjtBQUNEO0FBQ0QsUUFBTUUsUUFBUywrQkFDRiw0QkFERSxHQUVGLFlBRmI7QUFHQSxNQUFJQyxXQUFXLEVBQWY7QUFDQSxRQUFNQyxRQUFRLHlCQUFZTCxJQUFaLENBQWQ7QUFDQSxPQUFLLElBQUlNLElBQUksQ0FBYixFQUFnQkEsSUFBSUQsTUFBTUUsTUFBMUIsRUFBa0MsRUFBRUQsQ0FBcEMsRUFBdUM7QUFDckNGLGdCQUFZRCxNQUFNRSxNQUFNRyxTQUFOLENBQWdCRixDQUFoQixJQUFxQkgsTUFBTUksTUFBakMsQ0FBWjtBQUNEO0FBQ0QsU0FBT0gsUUFBUDtBQUNEOztBQUVEO0FBQ08sU0FBU1AsV0FBVCxDQUFxQkcsT0FBZSxFQUFwQyxFQUFnRDtBQUNyRCxTQUFPSixhQUFhSSxJQUFiLENBQVA7QUFDRDs7QUFFRDtBQUNPLFNBQVNGLFFBQVQsR0FBNEI7QUFDakMsU0FBT0gsZ0JBQWdCLEVBQWhCLENBQVA7QUFDRDs7QUFFTSxTQUFTSSxPQUFULENBQWlCVSxNQUFqQixFQUF5QztBQUM5QyxTQUFPLHdCQUFXLEtBQVgsRUFBa0JDLE1BQWxCLENBQXlCRCxNQUF6QixFQUFpQ0UsTUFBakMsQ0FBd0MsS0FBeEMsQ0FBUDtBQUNEIiwiZmlsZSI6ImNyeXB0b1V0aWxzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuaW1wb3J0IHsgcmFuZG9tQnl0ZXMsIGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuXG4vLyBSZXR1cm5zIGEgbmV3IHJhbmRvbSBoZXggc3RyaW5nIG9mIHRoZSBnaXZlbiBldmVuIHNpemUuXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tSGV4U3RyaW5nKHNpemU6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChzaXplID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdaZXJvLWxlbmd0aCByYW5kb21IZXhTdHJpbmcgaXMgdXNlbGVzcy4nKTtcbiAgfVxuICBpZiAoc2l6ZSAlIDIgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3JhbmRvbUhleFN0cmluZyBzaXplIG11c3QgYmUgZGl2aXNpYmxlIGJ5IDIuJylcbiAgfVxuICByZXR1cm4gcmFuZG9tQnl0ZXMoc2l6ZSAvIDIpLnRvU3RyaW5nKCdoZXgnKTtcbn1cblxuLy8gUmV0dXJucyBhIG5ldyByYW5kb20gYWxwaGFudW1lcmljIHN0cmluZyBvZiB0aGUgZ2l2ZW4gc2l6ZS5cbi8vXG4vLyBOb3RlOiB0byBzaW1wbGlmeSBpbXBsZW1lbnRhdGlvbiwgdGhlIHJlc3VsdCBoYXMgc2xpZ2h0IG1vZHVsbyBiaWFzLFxuLy8gYmVjYXVzZSBjaGFycyBsZW5ndGggb2YgNjIgZG9lc24ndCBkaXZpZGUgdGhlIG51bWJlciBvZiBhbGwgYnl0ZXNcbi8vICgyNTYpIGV2ZW5seS4gU3VjaCBiaWFzIGlzIGFjY2VwdGFibGUgZm9yIG1vc3QgY2FzZXMgd2hlbiB0aGUgb3V0cHV0XG4vLyBsZW5ndGggaXMgbG9uZyBlbm91Z2ggYW5kIGRvZXNuJ3QgbmVlZCB0byBiZSB1bmlmb3JtLlxuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbVN0cmluZyhzaXplOiBudW1iZXIpOiBzdHJpbmcge1xuICBpZiAoc2l6ZSA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignWmVyby1sZW5ndGggcmFuZG9tU3RyaW5nIGlzIHVzZWxlc3MuJyk7XG4gIH1cbiAgY29uc3QgY2hhcnMgPSAoJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaJyArXG4gICAgICAgICAgICAgICAnYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXonICtcbiAgICAgICAgICAgICAgICcwMTIzNDU2Nzg5Jyk7XG4gIGxldCBvYmplY3RJZCA9ICcnO1xuICBjb25zdCBieXRlcyA9IHJhbmRvbUJ5dGVzKHNpemUpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgKytpKSB7XG4gICAgb2JqZWN0SWQgKz0gY2hhcnNbYnl0ZXMucmVhZFVJbnQ4KGkpICUgY2hhcnMubGVuZ3RoXTtcbiAgfVxuICByZXR1cm4gb2JqZWN0SWQ7XG59XG5cbi8vIFJldHVybnMgYSBuZXcgcmFuZG9tIGFscGhhbnVtZXJpYyBzdHJpbmcgc3VpdGFibGUgZm9yIG9iamVjdCBJRC5cbmV4cG9ydCBmdW5jdGlvbiBuZXdPYmplY3RJZChzaXplOiBudW1iZXIgPSAxMCk6IHN0cmluZyB7XG4gIHJldHVybiByYW5kb21TdHJpbmcoc2l6ZSk7XG59XG5cbi8vIFJldHVybnMgYSBuZXcgcmFuZG9tIGhleCBzdHJpbmcgc3VpdGFibGUgZm9yIHNlY3VyZSB0b2tlbnMuXG5leHBvcnQgZnVuY3Rpb24gbmV3VG9rZW4oKTogc3RyaW5nIHtcbiAgcmV0dXJuIHJhbmRvbUhleFN0cmluZygzMik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZDVIYXNoKHN0cmluZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGNyZWF0ZUhhc2goJ21kNScpLnVwZGF0ZShzdHJpbmcpLmRpZ2VzdCgnaGV4Jyk7XG59XG4iXX0= \ No newline at end of file diff --git a/lib/defaults.js b/lib/defaults.js index 2fadaeaee0..e9e7fc83ca 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -40,4 +40,5 @@ const computedDefaults = { }; exports.default = Object.assign({}, DefinitionDefaults, computedDefaults); -const DefaultMongoURI = exports.DefaultMongoURI = DefinitionDefaults.databaseURI; \ No newline at end of file +const DefaultMongoURI = exports.DefaultMongoURI = DefinitionDefaults.databaseURI; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9kZWZhdWx0cy5qcyJdLCJuYW1lcyI6WyJQYXJzZVNlcnZlck9wdGlvbnMiLCJyZXF1aXJlIiwibG9nc0ZvbGRlciIsImZvbGRlciIsInByb2Nlc3MiLCJlbnYiLCJURVNUSU5HIiwiUEFSU0VfU0VSVkVSX0xPR1NfRk9MREVSIiwidmVyYm9zZSIsImxldmVsIiwiVkVSQk9TRSIsInVuZGVmaW5lZCIsIkRlZmluaXRpb25EZWZhdWx0cyIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJtZW1vIiwia2V5IiwiZGVmIiwiaGFzT3duUHJvcGVydHkiLCJkZWZhdWx0IiwiY29tcHV0ZWREZWZhdWx0cyIsImpzb25Mb2dzIiwiSlNPTl9MT0dTIiwiYXNzaWduIiwiRGVmYXVsdE1vbmdvVVJJIiwiZGF0YWJhc2VVUkkiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQSxNQUFNLEVBQUVBLGtCQUFGLEtBQXlCQyxRQUFRLHVCQUFSLENBQS9CO0FBQ0EsTUFBTUMsYUFBYSxDQUFDLE1BQU07QUFDeEIsTUFBSUMsU0FBUyxTQUFiO0FBQ0EsTUFBSSxPQUFPQyxPQUFQLEtBQW1CLFdBQW5CLElBQWtDQSxRQUFRQyxHQUFSLENBQVlDLE9BQVosS0FBd0IsR0FBOUQsRUFBbUU7QUFDakVILGFBQVMsY0FBVDtBQUNEO0FBQ0QsTUFBSUMsUUFBUUMsR0FBUixDQUFZRSx3QkFBaEIsRUFBMEM7QUFDeENKLGFBQVMseUJBQVdDLFFBQVFDLEdBQVIsQ0FBWUUsd0JBQXZCLENBQVQ7QUFDRDtBQUNELFNBQU9KLE1BQVA7QUFDRCxDQVRrQixHQUFuQjs7QUFXQSxNQUFNLEVBQUVLLE9BQUYsRUFBV0MsS0FBWCxLQUFxQixDQUFDLE1BQU07QUFDaEMsUUFBTUQsVUFBVUosUUFBUUMsR0FBUixDQUFZSyxPQUFaLEdBQXNCLElBQXRCLEdBQTZCLEtBQTdDO0FBQ0EsU0FBTyxFQUFFRixPQUFGLEVBQVdDLE9BQU9ELFVBQVUsU0FBVixHQUFzQkcsU0FBeEMsRUFBUDtBQUNELENBSDBCLEdBQTNCOztBQU1BLE1BQU1DLHFCQUFxQkMsT0FBT0MsSUFBUCxDQUFZZCxrQkFBWixFQUFnQ2UsTUFBaEMsQ0FBdUMsQ0FBQ0MsSUFBRCxFQUFPQyxHQUFQLEtBQWU7QUFDL0UsUUFBTUMsTUFBTWxCLG1CQUFtQmlCLEdBQW5CLENBQVo7QUFDQSxNQUFJQyxJQUFJQyxjQUFKLENBQW1CLFNBQW5CLENBQUosRUFBbUM7QUFDakNILFNBQUtDLEdBQUwsSUFBWUMsSUFBSUUsT0FBaEI7QUFDRDtBQUNELFNBQU9KLElBQVA7QUFDRCxDQU4wQixFQU14QixFQU53QixDQUEzQjs7QUFRQSxNQUFNSyxtQkFBbUI7QUFDdkJDLFlBQVVsQixRQUFRQyxHQUFSLENBQVlrQixTQUFaLElBQXlCLEtBRFo7QUFFdkJyQixZQUZ1QjtBQUd2Qk0sU0FIdUI7QUFJdkJDO0FBSnVCLENBQXpCOztrQkFPZUksT0FBT1csTUFBUCxDQUFjLEVBQWQsRUFBa0JaLGtCQUFsQixFQUFzQ1MsZ0JBQXRDLEM7QUFDUixNQUFNSSw0Q0FBa0JiLG1CQUFtQmMsV0FBM0MiLCJmaWxlIjoiZGVmYXVsdHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBudWxsUGFyc2VyIH0gZnJvbSAnLi9PcHRpb25zL3BhcnNlcnMnO1xuY29uc3QgeyBQYXJzZVNlcnZlck9wdGlvbnMgfSA9IHJlcXVpcmUoJy4vT3B0aW9ucy9EZWZpbml0aW9ucycpO1xuY29uc3QgbG9nc0ZvbGRlciA9ICgoKSA9PiB7XG4gIGxldCBmb2xkZXIgPSAnLi9sb2dzLyc7XG4gIGlmICh0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgcHJvY2Vzcy5lbnYuVEVTVElORyA9PT0gJzEnKSB7XG4gICAgZm9sZGVyID0gJy4vdGVzdF9sb2dzLydcbiAgfVxuICBpZiAocHJvY2Vzcy5lbnYuUEFSU0VfU0VSVkVSX0xPR1NfRk9MREVSKSB7XG4gICAgZm9sZGVyID0gbnVsbFBhcnNlcihwcm9jZXNzLmVudi5QQVJTRV9TRVJWRVJfTE9HU19GT0xERVIpO1xuICB9XG4gIHJldHVybiBmb2xkZXI7XG59KSgpO1xuXG5jb25zdCB7IHZlcmJvc2UsIGxldmVsIH0gPSAoKCkgPT4ge1xuICBjb25zdCB2ZXJib3NlID0gcHJvY2Vzcy5lbnYuVkVSQk9TRSA/IHRydWUgOiBmYWxzZTtcbiAgcmV0dXJuIHsgdmVyYm9zZSwgbGV2ZWw6IHZlcmJvc2UgPyAndmVyYm9zZScgOiB1bmRlZmluZWQgfVxufSkoKTtcblxuXG5jb25zdCBEZWZpbml0aW9uRGVmYXVsdHMgPSBPYmplY3Qua2V5cyhQYXJzZVNlcnZlck9wdGlvbnMpLnJlZHVjZSgobWVtbywga2V5KSA9PiB7XG4gIGNvbnN0IGRlZiA9IFBhcnNlU2VydmVyT3B0aW9uc1trZXldO1xuICBpZiAoZGVmLmhhc093blByb3BlcnR5KCdkZWZhdWx0JykpIHtcbiAgICBtZW1vW2tleV0gPSBkZWYuZGVmYXVsdDtcbiAgfVxuICByZXR1cm4gbWVtbztcbn0sIHt9KTtcblxuY29uc3QgY29tcHV0ZWREZWZhdWx0cyA9IHtcbiAganNvbkxvZ3M6IHByb2Nlc3MuZW52LkpTT05fTE9HUyB8fCBmYWxzZSxcbiAgbG9nc0ZvbGRlcixcbiAgdmVyYm9zZSxcbiAgbGV2ZWwsXG59XG5cbmV4cG9ydCBkZWZhdWx0IE9iamVjdC5hc3NpZ24oe30sIERlZmluaXRpb25EZWZhdWx0cywgY29tcHV0ZWREZWZhdWx0cyk7XG5leHBvcnQgY29uc3QgRGVmYXVsdE1vbmdvVVJJID0gRGVmaW5pdGlvbkRlZmF1bHRzLmRhdGFiYXNlVVJJO1xuIl19 \ No newline at end of file diff --git a/lib/deprecated.js b/lib/deprecated.js index f808c611c6..39b1ef5b00 100644 --- a/lib/deprecated.js +++ b/lib/deprecated.js @@ -8,4 +8,5 @@ function useExternal(name, moduleName) { return function () { throw `${name} is not provided by parse-server anymore; please install ${moduleName}`; }; -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXByZWNhdGVkLmpzIl0sIm5hbWVzIjpbInVzZUV4dGVybmFsIiwibmFtZSIsIm1vZHVsZU5hbWUiXSwibWFwcGluZ3MiOiI7Ozs7O1FBQWdCQSxXLEdBQUFBLFc7QUFBVCxTQUFTQSxXQUFULENBQXFCQyxJQUFyQixFQUEyQkMsVUFBM0IsRUFBdUM7QUFDNUMsU0FBTyxZQUFXO0FBQ2hCLFVBQU8sR0FBRUQsSUFBSyw0REFBMkRDLFVBQVcsRUFBcEY7QUFDRCxHQUZEO0FBR0QiLCJmaWxlIjoiZGVwcmVjYXRlZC5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiB1c2VFeHRlcm5hbChuYW1lLCBtb2R1bGVOYW1lKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB0aHJvdyBgJHtuYW1lfSBpcyBub3QgcHJvdmlkZWQgYnkgcGFyc2Utc2VydmVyIGFueW1vcmU7IHBsZWFzZSBpbnN0YWxsICR7bW9kdWxlTmFtZX1gO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index b3ba2ad882..2b088a859a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -74,4 +74,5 @@ exports.RedisCacheAdapter = _RedisCacheAdapter2.default; exports.LRUCacheAdapter = _LRUCache2.default; exports.TestUtils = TestUtils; exports.PushWorker = _PushWorker.PushWorker; -exports.ParseServer = _ParseServer; \ No newline at end of file +exports.ParseServer = _ParseServer; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6WyJUZXN0VXRpbHMiLCJfUGFyc2VTZXJ2ZXIiLCJvcHRpb25zIiwic2VydmVyIiwiUGFyc2VTZXJ2ZXIiLCJhcHAiLCJjcmVhdGVMaXZlUXVlcnlTZXJ2ZXIiLCJzdGFydCIsIkdDU0FkYXB0ZXIiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsIm1vZHVsZSIsImV4cG9ydHMiLCJnZXQiLCJnZXRMb2dnZXIiLCJTM0FkYXB0ZXIiLCJGaWxlU3lzdGVtQWRhcHRlciIsIkluTWVtb3J5Q2FjaGVBZGFwdGVyIiwiTnVsbENhY2hlQWRhcHRlciIsIlJlZGlzQ2FjaGVBZGFwdGVyIiwiTFJVQ2FjaGVBZGFwdGVyIiwiUHVzaFdvcmtlciJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7O0lBQVlBLFM7O0FBQ1o7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7OztBQUVBO0FBQ0EsTUFBTUMsZUFBZSxVQUFTQyxPQUFULEVBQXNDO0FBQ3pELFFBQU1DLFNBQVMsSUFBSUMscUJBQUosQ0FBZ0JGLE9BQWhCLENBQWY7QUFDQSxTQUFPQyxPQUFPRSxHQUFkO0FBQ0QsQ0FIRDtBQUlBO0FBQ0FKLGFBQWFLLHFCQUFiLEdBQXFDRixzQkFBWUUscUJBQWpEO0FBQ0FMLGFBQWFNLEtBQWIsR0FBcUJILHNCQUFZRyxLQUFqQzs7QUFFQSxNQUFNQyxhQUFhLDZCQUFZLFlBQVosRUFBMEIsMEJBQTFCLENBQW5COztBQUVBQyxPQUFPQyxjQUFQLENBQXNCQyxPQUFPQyxPQUE3QixFQUFzQyxRQUF0QyxFQUFnRDtBQUM5Q0MsT0FBS0M7QUFEeUMsQ0FBaEQ7O2tCQUllVixxQjtRQUViVyxTLEdBQUFBLHdCO1FBQ0FQLFUsR0FBQUEsVTtRQUNBUSxpQixHQUFBQSx3QjtRQUNBQyxvQixHQUFBQSw4QjtRQUNBQyxnQixHQUFBQSwwQjtRQUNBQyxpQixHQUFBQSwyQjtRQUNBQyxlLEdBQUFBLGtCO1FBQ0FwQixTLEdBQUFBLFM7UUFDQXFCLFUsR0FBQUEsc0I7UUFDZ0JqQixXLEdBQWhCSCxZIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlU2VydmVyICAgICAgICAgIGZyb20gJy4vUGFyc2VTZXJ2ZXInO1xuaW1wb3J0IFMzQWRhcHRlciAgICAgICAgICAgIGZyb20gJ0BwYXJzZS9zMy1maWxlcy1hZGFwdGVyJ1xuaW1wb3J0IEZpbGVTeXN0ZW1BZGFwdGVyICAgIGZyb20gJ0BwYXJzZS9mcy1maWxlcy1hZGFwdGVyJ1xuaW1wb3J0IEluTWVtb3J5Q2FjaGVBZGFwdGVyIGZyb20gJy4vQWRhcHRlcnMvQ2FjaGUvSW5NZW1vcnlDYWNoZUFkYXB0ZXInXG5pbXBvcnQgTnVsbENhY2hlQWRhcHRlciAgICAgZnJvbSAnLi9BZGFwdGVycy9DYWNoZS9OdWxsQ2FjaGVBZGFwdGVyJ1xuaW1wb3J0IFJlZGlzQ2FjaGVBZGFwdGVyICAgIGZyb20gJy4vQWRhcHRlcnMvQ2FjaGUvUmVkaXNDYWNoZUFkYXB0ZXInXG5pbXBvcnQgTFJVQ2FjaGVBZGFwdGVyICAgICAgZnJvbSAnLi9BZGFwdGVycy9DYWNoZS9MUlVDYWNoZS5qcydcbmltcG9ydCAqIGFzIFRlc3RVdGlscyAgICAgICBmcm9tICcuL1Rlc3RVdGlscyc7XG5pbXBvcnQgeyB1c2VFeHRlcm5hbCB9ICAgICAgZnJvbSAnLi9kZXByZWNhdGVkJztcbmltcG9ydCB7IGdldExvZ2dlciB9ICAgICAgICBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgeyBQdXNoV29ya2VyIH0gICAgICAgZnJvbSAnLi9QdXNoL1B1c2hXb3JrZXInO1xuaW1wb3J0IHsgUGFyc2VTZXJ2ZXJPcHRpb25zIH0gICAgZnJvbSAnLi9PcHRpb25zJztcblxuLy8gRmFjdG9yeSBmdW5jdGlvblxuY29uc3QgX1BhcnNlU2VydmVyID0gZnVuY3Rpb24ob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKSB7XG4gIGNvbnN0IHNlcnZlciA9IG5ldyBQYXJzZVNlcnZlcihvcHRpb25zKTtcbiAgcmV0dXJuIHNlcnZlci5hcHA7XG59XG4vLyBNb3VudCB0aGUgY3JlYXRlIGxpdmVRdWVyeVNlcnZlclxuX1BhcnNlU2VydmVyLmNyZWF0ZUxpdmVRdWVyeVNlcnZlciA9IFBhcnNlU2VydmVyLmNyZWF0ZUxpdmVRdWVyeVNlcnZlcjtcbl9QYXJzZVNlcnZlci5zdGFydCA9IFBhcnNlU2VydmVyLnN0YXJ0O1xuXG5jb25zdCBHQ1NBZGFwdGVyID0gdXNlRXh0ZXJuYWwoJ0dDU0FkYXB0ZXInLCAnQHBhcnNlL2djcy1maWxlcy1hZGFwdGVyJyk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUuZXhwb3J0cywgJ2xvZ2dlcicsIHtcbiAgZ2V0OiBnZXRMb2dnZXJcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBQYXJzZVNlcnZlcjtcbmV4cG9ydCB7XG4gIFMzQWRhcHRlcixcbiAgR0NTQWRhcHRlcixcbiAgRmlsZVN5c3RlbUFkYXB0ZXIsXG4gIEluTWVtb3J5Q2FjaGVBZGFwdGVyLFxuICBOdWxsQ2FjaGVBZGFwdGVyLFxuICBSZWRpc0NhY2hlQWRhcHRlcixcbiAgTFJVQ2FjaGVBZGFwdGVyLFxuICBUZXN0VXRpbHMsXG4gIFB1c2hXb3JrZXIsXG4gIF9QYXJzZVNlcnZlciBhcyBQYXJzZVNlcnZlclxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/logger.js b/lib/logger.js index 1f9e6dea5e..1513a6a52c 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -44,4 +44,5 @@ Object.defineProperty(module.exports, 'default', { // for: `import { logger } from './logger'` Object.defineProperty(module.exports, 'logger', { get: getLogger -}); \ No newline at end of file +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9sb2dnZXIuanMiXSwibmFtZXMiOlsic2V0TG9nZ2VyIiwiZ2V0TG9nZ2VyIiwiZGVmYXVsdExvZ2dlciIsIm9wdGlvbnMiLCJsb2dzRm9sZGVyIiwiZGVmYXVsdHMiLCJqc29uTG9ncyIsInZlcmJvc2UiLCJzaWxlbnQiLCJhZGFwdGVyIiwiV2luc3RvbkxvZ2dlckFkYXB0ZXIiLCJMb2dnZXJDb250cm9sbGVyIiwibG9nZ2VyIiwiYUxvZ2dlciIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwibW9kdWxlIiwiZXhwb3J0cyIsImdldCJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O1FBaUJnQkEsUyxHQUFBQSxTO1FBSUFDLFMsR0FBQUEsUzs7QUFwQmhCOzs7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCLFFBQU1DLFVBQVU7QUFDZEMsZ0JBQVlDLG1CQUFTRCxVQURQO0FBRWRFLGNBQVVELG1CQUFTQyxRQUZMO0FBR2RDLGFBQVNGLG1CQUFTRSxPQUhKO0FBSWRDLFlBQVFILG1CQUFTRyxNQUpILEVBQWhCO0FBS0EsUUFBTUMsVUFBVSxJQUFJQywwQ0FBSixDQUF5QlAsT0FBekIsQ0FBaEI7QUFDQSxTQUFPLElBQUlRLGtDQUFKLENBQXFCRixPQUFyQixFQUE4QixJQUE5QixFQUFvQ04sT0FBcEMsQ0FBUDtBQUNEOztBQUVELElBQUlTLFNBQVNWLGVBQWI7O0FBRU8sU0FBU0YsU0FBVCxDQUFtQmEsT0FBbkIsRUFBNEI7QUFDakNELFdBQVNDLE9BQVQ7QUFDRDs7QUFFTSxTQUFTWixTQUFULEdBQXFCO0FBQzFCLFNBQU9XLE1BQVA7QUFDRDs7QUFFRDtBQUNBRSxPQUFPQyxjQUFQLENBQXNCQyxPQUFPQyxPQUE3QixFQUFzQyxTQUF0QyxFQUFpRDtBQUMvQ0MsT0FBS2pCO0FBRDBDLENBQWpEOztBQUlBO0FBQ0FhLE9BQU9DLGNBQVAsQ0FBc0JDLE9BQU9DLE9BQTdCLEVBQXNDLFFBQXRDLEVBQWdEO0FBQzlDQyxPQUFLakI7QUFEeUMsQ0FBaEQiLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuaW1wb3J0IGRlZmF1bHRzIGZyb20gJy4vZGVmYXVsdHMnO1xuaW1wb3J0IHsgV2luc3RvbkxvZ2dlckFkYXB0ZXIgfSBmcm9tICcuL0FkYXB0ZXJzL0xvZ2dlci9XaW5zdG9uTG9nZ2VyQWRhcHRlcic7XG5pbXBvcnQgeyBMb2dnZXJDb250cm9sbGVyIH0gICAgIGZyb20gJy4vQ29udHJvbGxlcnMvTG9nZ2VyQ29udHJvbGxlcic7XG5cbmZ1bmN0aW9uIGRlZmF1bHRMb2dnZXIoKSB7XG4gIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgbG9nc0ZvbGRlcjogZGVmYXVsdHMubG9nc0ZvbGRlcixcbiAgICBqc29uTG9nczogZGVmYXVsdHMuanNvbkxvZ3MsXG4gICAgdmVyYm9zZTogZGVmYXVsdHMudmVyYm9zZSxcbiAgICBzaWxlbnQ6IGRlZmF1bHRzLnNpbGVudCB9O1xuICBjb25zdCBhZGFwdGVyID0gbmV3IFdpbnN0b25Mb2dnZXJBZGFwdGVyKG9wdGlvbnMpO1xuICByZXR1cm4gbmV3IExvZ2dlckNvbnRyb2xsZXIoYWRhcHRlciwgbnVsbCwgb3B0aW9ucyk7XG59XG5cbmxldCBsb2dnZXIgPSBkZWZhdWx0TG9nZ2VyKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRMb2dnZXIoYUxvZ2dlcikge1xuICBsb2dnZXIgPSBhTG9nZ2VyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9nZ2VyKCkge1xuICByZXR1cm4gbG9nZ2VyO1xufVxuXG4vLyBmb3I6IGBpbXBvcnQgbG9nZ2VyIGZyb20gJy4vbG9nZ2VyJ2Bcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUuZXhwb3J0cywgJ2RlZmF1bHQnLCB7XG4gIGdldDogZ2V0TG9nZ2VyXG59KTtcblxuLy8gZm9yOiBgaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInYFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZS5leHBvcnRzLCAnbG9nZ2VyJywge1xuICBnZXQ6IGdldExvZ2dlclxufSk7XG4iXX0= \ No newline at end of file diff --git a/lib/middlewares.js b/lib/middlewares.js index 4b336419f7..d24c026bd9 100644 --- a/lib/middlewares.js +++ b/lib/middlewares.js @@ -268,7 +268,7 @@ function allowCrossDomain(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-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, X-CSRF-Token'); - + 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); @@ -304,6 +304,9 @@ function handleParseErrors(err, req, res, next) { res.status(httpStatus); res.json({ code: err.code, error: err.message }); _logger2.default.error(err.message, err); + if (req.config && req.config.enableExpressErrorHandler) { + next(err); + } } else if (err.status && err.message) { res.status(err.status); res.json({ error: err.message }); @@ -341,4 +344,5 @@ function promiseEnforceMasterKeyAccess(request) { function invalidRequest(req, res) { res.status(403); res.end('{"error":"unauthorized"}'); -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9taWRkbGV3YXJlcy5qcyJdLCJuYW1lcyI6WyJoYW5kbGVQYXJzZUhlYWRlcnMiLCJhbGxvd0Nyb3NzRG9tYWluIiwiYWxsb3dNZXRob2RPdmVycmlkZSIsImhhbmRsZVBhcnNlRXJyb3JzIiwiZW5mb3JjZU1hc3RlcktleUFjY2VzcyIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwicmVxIiwicmVzIiwibmV4dCIsIm1vdW50UGF0aExlbmd0aCIsIm9yaWdpbmFsVXJsIiwibGVuZ3RoIiwidXJsIiwibW91bnRQYXRoIiwic2xpY2UiLCJtb3VudCIsInByb3RvY29sIiwiZ2V0IiwiaW5mbyIsImFwcElkIiwic2Vzc2lvblRva2VuIiwibWFzdGVyS2V5IiwiaW5zdGFsbGF0aW9uSWQiLCJjbGllbnRLZXkiLCJqYXZhc2NyaXB0S2V5IiwiZG90TmV0S2V5IiwicmVzdEFQSUtleSIsImNsaWVudFZlcnNpb24iLCJiYXNpY0F1dGgiLCJodHRwQXV0aCIsImJhc2ljQXV0aEFwcElkIiwiQXBwQ2FjaGUiLCJib2R5IiwiX25vQm9keSIsImZpbGVWaWFKU09OIiwiQnVmZmVyIiwiSlNPTiIsInBhcnNlIiwiX1Jldm9jYWJsZVNlc3Npb24iLCJfQXBwbGljYXRpb25JZCIsIl9KYXZhU2NyaXB0S2V5IiwiX0NsaWVudFZlcnNpb24iLCJfSW5zdGFsbGF0aW9uSWQiLCJfU2Vzc2lvblRva2VuIiwiX01hc3RlcktleSIsIl9Db250ZW50VHlwZSIsImhlYWRlcnMiLCJpbnZhbGlkUmVxdWVzdCIsImNsaWVudFNESyIsIkNsaWVudFNESyIsImZyb21TdHJpbmciLCJiYXNlNjQiLCJjbGllbnRJcCIsImdldENsaWVudElwIiwiYXBwIiwiY29uZmlnIiwiQ29uZmlnIiwiaXAiLCJtYXN0ZXJLZXlJcHMiLCJpbmRleE9mIiwiaXNNYXN0ZXIiLCJhdXRoIiwiQXV0aCIsImlzUmVhZE9ubHlNYXN0ZXIiLCJyZWFkT25seU1hc3RlcktleSIsImlzUmVhZE9ubHkiLCJrZXlzIiwib25lS2V5Q29uZmlndXJlZCIsInNvbWUiLCJrZXkiLCJ1bmRlZmluZWQiLCJvbmVLZXlNYXRjaGVzIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aGVuIiwiZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbiIsImdldEF1dGhGb3JTZXNzaW9uVG9rZW4iLCJjYXRjaCIsImVycm9yIiwiUGFyc2UiLCJFcnJvciIsImxvZyIsIlVOS05PV05fRVJST1IiLCJzcGxpdCIsImNvbm5lY3Rpb24iLCJyZW1vdGVBZGRyZXNzIiwic29ja2V0IiwiYXV0aG9yaXphdGlvbiIsImhlYWRlciIsImF1dGhQcmVmaXgiLCJtYXRjaCIsInRvTG93ZXJDYXNlIiwiZW5jb2RlZEF1dGgiLCJzdWJzdHJpbmciLCJjcmVkZW50aWFscyIsImRlY29kZUJhc2U2NCIsImpzS2V5UHJlZml4IiwibWF0Y2hLZXkiLCJzdHIiLCJ0b1N0cmluZyIsIm1ldGhvZCIsInNlbmRTdGF0dXMiLCJfbWV0aG9kIiwib3JpZ2luYWxNZXRob2QiLCJlcnIiLCJodHRwU3RhdHVzIiwiY29kZSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsIk9CSkVDVF9OT1RfRk9VTkQiLCJzdGF0dXMiLCJqc29uIiwibWVzc2FnZSIsImVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXIiLCJzdGFjayIsImVuZCIsInJlcXVlc3QiXSwibWFwcGluZ3MiOiI7Ozs7O1FBYWdCQSxrQixHQUFBQSxrQjtRQXdPQUMsZ0IsR0FBQUEsZ0I7UUFjQUMsbUIsR0FBQUEsbUI7UUFTQUMsaUIsR0FBQUEsaUI7UUFxQ0FDLHNCLEdBQUFBLHNCO1FBU0FDLDZCLEdBQUFBLDZCOztBQTFUaEI7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxTQUFTTCxrQkFBVCxDQUE0Qk0sR0FBNUIsRUFBaUNDLEdBQWpDLEVBQXNDQyxJQUF0QyxFQUE0QztBQUNqRCxNQUFJQyxrQkFBa0JILElBQUlJLFdBQUosQ0FBZ0JDLE1BQWhCLEdBQXlCTCxJQUFJTSxHQUFKLENBQVFELE1BQXZEO0FBQ0EsTUFBSUUsWUFBWVAsSUFBSUksV0FBSixDQUFnQkksS0FBaEIsQ0FBc0IsQ0FBdEIsRUFBeUJMLGVBQXpCLENBQWhCO0FBQ0EsTUFBSU0sUUFBUVQsSUFBSVUsUUFBSixHQUFlLEtBQWYsR0FBdUJWLElBQUlXLEdBQUosQ0FBUSxNQUFSLENBQXZCLEdBQXlDSixTQUFyRDs7QUFFQSxNQUFJSyxPQUFPO0FBQ1RDLFdBQU9iLElBQUlXLEdBQUosQ0FBUSx3QkFBUixDQURFO0FBRVRHLGtCQUFjZCxJQUFJVyxHQUFKLENBQVEsdUJBQVIsQ0FGTDtBQUdUSSxlQUFXZixJQUFJVyxHQUFKLENBQVEsb0JBQVIsQ0FIRjtBQUlUSyxvQkFBZ0JoQixJQUFJVyxHQUFKLENBQVEseUJBQVIsQ0FKUDtBQUtUTSxlQUFXakIsSUFBSVcsR0FBSixDQUFRLG9CQUFSLENBTEY7QUFNVE8sbUJBQWVsQixJQUFJVyxHQUFKLENBQVEsd0JBQVIsQ0FOTjtBQU9UUSxlQUFXbkIsSUFBSVcsR0FBSixDQUFRLHFCQUFSLENBUEY7QUFRVFMsZ0JBQVlwQixJQUFJVyxHQUFKLENBQVEsc0JBQVIsQ0FSSDtBQVNUVSxtQkFBZXJCLElBQUlXLEdBQUosQ0FBUSx3QkFBUjtBQVROLEdBQVg7O0FBWUEsTUFBSVcsWUFBWUMsU0FBU3ZCLEdBQVQsQ0FBaEI7O0FBRUEsTUFBSXNCLFNBQUosRUFBZTtBQUNiLFFBQUlFLGlCQUFpQkYsVUFBVVQsS0FBL0I7QUFDQSxRQUFJWSxnQkFBU2QsR0FBVCxDQUFhYSxjQUFiLENBQUosRUFBa0M7QUFDaENaLFdBQUtDLEtBQUwsR0FBYVcsY0FBYjtBQUNBWixXQUFLRyxTQUFMLEdBQWlCTyxVQUFVUCxTQUFWLElBQXVCSCxLQUFLRyxTQUE3QztBQUNBSCxXQUFLTSxhQUFMLEdBQXFCSSxVQUFVSixhQUFWLElBQTJCTixLQUFLTSxhQUFyRDtBQUNEO0FBQ0Y7O0FBRUQsTUFBSWxCLElBQUkwQixJQUFSLEVBQWM7QUFDWjtBQUNBO0FBQ0EsV0FBTzFCLElBQUkwQixJQUFKLENBQVNDLE9BQWhCO0FBQ0Q7O0FBRUQsTUFBSUMsY0FBYyxLQUFsQjs7QUFFQSxNQUFJLENBQUNoQixLQUFLQyxLQUFOLElBQWUsQ0FBQ1ksZ0JBQVNkLEdBQVQsQ0FBYUMsS0FBS0MsS0FBbEIsQ0FBcEIsRUFBOEM7QUFDNUM7QUFDQSxRQUFJYixJQUFJMEIsSUFBSixZQUFvQkcsTUFBeEIsRUFBZ0M7QUFDOUI7QUFDQTtBQUNBN0IsVUFBSTBCLElBQUosR0FBV0ksS0FBS0MsS0FBTCxDQUFXL0IsSUFBSTBCLElBQWYsQ0FBWDtBQUNBRSxvQkFBYyxJQUFkO0FBQ0Q7O0FBRUQsUUFBSTVCLElBQUkwQixJQUFSLEVBQWM7QUFDWixhQUFPMUIsSUFBSTBCLElBQUosQ0FBU00saUJBQWhCO0FBQ0Q7O0FBRUQsUUFBSWhDLElBQUkwQixJQUFKLElBQ0YxQixJQUFJMEIsSUFBSixDQUFTTyxjQURQLElBRUZSLGdCQUFTZCxHQUFULENBQWFYLElBQUkwQixJQUFKLENBQVNPLGNBQXRCLENBRkUsS0FHRCxDQUFDckIsS0FBS0csU0FBTixJQUFtQlUsZ0JBQVNkLEdBQVQsQ0FBYVgsSUFBSTBCLElBQUosQ0FBU08sY0FBdEIsRUFBc0NsQixTQUF0QyxLQUFvREgsS0FBS0csU0FIM0UsQ0FBSixFQUlFO0FBQ0FILFdBQUtDLEtBQUwsR0FBYWIsSUFBSTBCLElBQUosQ0FBU08sY0FBdEI7QUFDQXJCLFdBQUtNLGFBQUwsR0FBcUJsQixJQUFJMEIsSUFBSixDQUFTUSxjQUFULElBQTJCLEVBQWhEO0FBQ0EsYUFBT2xDLElBQUkwQixJQUFKLENBQVNPLGNBQWhCO0FBQ0EsYUFBT2pDLElBQUkwQixJQUFKLENBQVNRLGNBQWhCO0FBQ0E7QUFDQTtBQUNBLFVBQUlsQyxJQUFJMEIsSUFBSixDQUFTUyxjQUFiLEVBQTZCO0FBQzNCdkIsYUFBS1MsYUFBTCxHQUFxQnJCLElBQUkwQixJQUFKLENBQVNTLGNBQTlCO0FBQ0EsZUFBT25DLElBQUkwQixJQUFKLENBQVNTLGNBQWhCO0FBQ0Q7QUFDRCxVQUFJbkMsSUFBSTBCLElBQUosQ0FBU1UsZUFBYixFQUE4QjtBQUM1QnhCLGFBQUtJLGNBQUwsR0FBc0JoQixJQUFJMEIsSUFBSixDQUFTVSxlQUEvQjtBQUNBLGVBQU9wQyxJQUFJMEIsSUFBSixDQUFTVSxlQUFoQjtBQUNEO0FBQ0QsVUFBSXBDLElBQUkwQixJQUFKLENBQVNXLGFBQWIsRUFBNEI7QUFDMUJ6QixhQUFLRSxZQUFMLEdBQW9CZCxJQUFJMEIsSUFBSixDQUFTVyxhQUE3QjtBQUNBLGVBQU9yQyxJQUFJMEIsSUFBSixDQUFTVyxhQUFoQjtBQUNEO0FBQ0QsVUFBSXJDLElBQUkwQixJQUFKLENBQVNZLFVBQWIsRUFBeUI7QUFDdkIxQixhQUFLRyxTQUFMLEdBQWlCZixJQUFJMEIsSUFBSixDQUFTWSxVQUExQjtBQUNBLGVBQU90QyxJQUFJMEIsSUFBSixDQUFTWSxVQUFoQjtBQUNEO0FBQ0QsVUFBSXRDLElBQUkwQixJQUFKLENBQVNhLFlBQWIsRUFBMkI7QUFDekJ2QyxZQUFJd0MsT0FBSixDQUFZLGNBQVosSUFBOEJ4QyxJQUFJMEIsSUFBSixDQUFTYSxZQUF2QztBQUNBLGVBQU92QyxJQUFJMEIsSUFBSixDQUFTYSxZQUFoQjtBQUNEO0FBQ0YsS0EvQkQsTUErQk87QUFDTCxhQUFPRSxlQUFlekMsR0FBZixFQUFvQkMsR0FBcEIsQ0FBUDtBQUNEO0FBQ0Y7O0FBRUQsTUFBSVcsS0FBS1MsYUFBVCxFQUF3QjtBQUN0QlQsU0FBSzhCLFNBQUwsR0FBaUJDLG9CQUFVQyxVQUFWLENBQXFCaEMsS0FBS1MsYUFBMUIsQ0FBakI7QUFDRDs7QUFFRCxNQUFJTyxXQUFKLEVBQWlCO0FBQ2Y7QUFDQSxRQUFJaUIsU0FBUzdDLElBQUkwQixJQUFKLENBQVNtQixNQUF0QjtBQUNBN0MsUUFBSTBCLElBQUosR0FBVyxJQUFJRyxNQUFKLENBQVdnQixNQUFYLEVBQW1CLFFBQW5CLENBQVg7QUFDRDs7QUFFRCxRQUFNQyxXQUFXQyxZQUFZL0MsR0FBWixDQUFqQjs7QUFFQVksT0FBS29DLEdBQUwsR0FBV3ZCLGdCQUFTZCxHQUFULENBQWFDLEtBQUtDLEtBQWxCLENBQVg7QUFDQWIsTUFBSWlELE1BQUosR0FBYUMsaUJBQU92QyxHQUFQLENBQVdDLEtBQUtDLEtBQWhCLEVBQXVCSixLQUF2QixDQUFiO0FBQ0FULE1BQUlpRCxNQUFKLENBQVdULE9BQVgsR0FBcUJ4QyxJQUFJd0MsT0FBSixJQUFlLEVBQXBDO0FBQ0F4QyxNQUFJaUQsTUFBSixDQUFXRSxFQUFYLEdBQWdCTCxRQUFoQjtBQUNBOUMsTUFBSVksSUFBSixHQUFXQSxJQUFYOztBQUVBLE1BQUlBLEtBQUtHLFNBQUwsSUFBa0JmLElBQUlpRCxNQUFKLENBQVdHLFlBQTdCLElBQTZDcEQsSUFBSWlELE1BQUosQ0FBV0csWUFBWCxDQUF3Qi9DLE1BQXhCLEtBQW1DLENBQWhGLElBQXFGTCxJQUFJaUQsTUFBSixDQUFXRyxZQUFYLENBQXdCQyxPQUF4QixDQUFnQ1AsUUFBaEMsTUFBOEMsQ0FBQyxDQUF4SSxFQUEySTtBQUN6SSxXQUFPTCxlQUFlekMsR0FBZixFQUFvQkMsR0FBcEIsQ0FBUDtBQUNEOztBQUVELE1BQUlxRCxXQUFZMUMsS0FBS0csU0FBTCxLQUFtQmYsSUFBSWlELE1BQUosQ0FBV2xDLFNBQTlDOztBQUVBLE1BQUl1QyxRQUFKLEVBQWM7QUFDWnRELFFBQUl1RCxJQUFKLEdBQVcsSUFBSUEsZUFBS0MsSUFBVCxDQUFjLEVBQUVQLFFBQVFqRCxJQUFJaUQsTUFBZCxFQUFzQmpDLGdCQUFnQkosS0FBS0ksY0FBM0MsRUFBMkRzQyxVQUFVLElBQXJFLEVBQWQsQ0FBWDtBQUNBcEQ7QUFDQTtBQUNEOztBQUVELE1BQUl1RCxtQkFBb0I3QyxLQUFLRyxTQUFMLEtBQW1CZixJQUFJaUQsTUFBSixDQUFXUyxpQkFBdEQ7QUFDQSxNQUFJLE9BQU8xRCxJQUFJaUQsTUFBSixDQUFXUyxpQkFBbEIsSUFBdUMsV0FBdkMsSUFBc0QxRCxJQUFJaUQsTUFBSixDQUFXUyxpQkFBakUsSUFBc0ZELGdCQUExRixFQUE0RztBQUMxR3pELFFBQUl1RCxJQUFKLEdBQVcsSUFBSUEsZUFBS0MsSUFBVCxDQUFjLEVBQUVQLFFBQVFqRCxJQUFJaUQsTUFBZCxFQUFzQmpDLGdCQUFnQkosS0FBS0ksY0FBM0MsRUFBMkRzQyxVQUFVLElBQXJFLEVBQTJFSyxZQUFZLElBQXZGLEVBQWQsQ0FBWDtBQUNBekQ7QUFDQTtBQUNEOztBQUVEO0FBQ0E7QUFDQSxRQUFNMEQsT0FBTyxDQUFDLFdBQUQsRUFBYyxlQUFkLEVBQStCLFdBQS9CLEVBQTRDLFlBQTVDLENBQWI7QUFDQSxRQUFNQyxtQkFBbUJELEtBQUtFLElBQUwsQ0FBVSxVQUFTQyxHQUFULEVBQWM7QUFDL0MsV0FBTy9ELElBQUlpRCxNQUFKLENBQVdjLEdBQVgsTUFBb0JDLFNBQTNCO0FBQ0QsR0FGd0IsQ0FBekI7QUFHQSxRQUFNQyxnQkFBZ0JMLEtBQUtFLElBQUwsQ0FBVSxVQUFTQyxHQUFULEVBQWE7QUFDM0MsV0FBTy9ELElBQUlpRCxNQUFKLENBQVdjLEdBQVgsTUFBb0JDLFNBQXBCLElBQWlDcEQsS0FBS21ELEdBQUwsTUFBYy9ELElBQUlpRCxNQUFKLENBQVdjLEdBQVgsQ0FBdEQ7QUFDRCxHQUZxQixDQUF0Qjs7QUFJQSxNQUFJRixvQkFBb0IsQ0FBQ0ksYUFBekIsRUFBd0M7QUFDdEMsV0FBT3hCLGVBQWV6QyxHQUFmLEVBQW9CQyxHQUFwQixDQUFQO0FBQ0Q7O0FBRUQsTUFBSUQsSUFBSU0sR0FBSixJQUFXLFFBQWYsRUFBeUI7QUFDdkIsV0FBT00sS0FBS0UsWUFBWjtBQUNEOztBQUVELE1BQUksQ0FBQ0YsS0FBS0UsWUFBVixFQUF3QjtBQUN0QmQsUUFBSXVELElBQUosR0FBVyxJQUFJQSxlQUFLQyxJQUFULENBQWMsRUFBRVAsUUFBUWpELElBQUlpRCxNQUFkLEVBQXNCakMsZ0JBQWdCSixLQUFLSSxjQUEzQyxFQUEyRHNDLFVBQVUsS0FBckUsRUFBZCxDQUFYO0FBQ0FwRDtBQUNBO0FBQ0Q7O0FBRUQsU0FBT2dFLFFBQVFDLE9BQVIsR0FBa0JDLElBQWxCLENBQXVCLE1BQU07QUFDbEM7QUFDQSxRQUFJeEQsS0FBS0UsWUFBTCxJQUNBZCxJQUFJTSxHQUFKLEtBQVksNEJBRFosSUFFQU0sS0FBS0UsWUFBTCxDQUFrQnVDLE9BQWxCLENBQTBCLElBQTFCLEtBQW1DLENBRnZDLEVBRTBDO0FBQ3hDLGFBQU9FLGVBQUtjLDRCQUFMLENBQWtDLEVBQUVwQixRQUFRakQsSUFBSWlELE1BQWQsRUFBc0JqQyxnQkFBZ0JKLEtBQUtJLGNBQTNDLEVBQTJERixjQUFjRixLQUFLRSxZQUE5RSxFQUFsQyxDQUFQO0FBQ0QsS0FKRCxNQUlPO0FBQ0wsYUFBT3lDLGVBQUtlLHNCQUFMLENBQTRCLEVBQUVyQixRQUFRakQsSUFBSWlELE1BQWQsRUFBc0JqQyxnQkFBZ0JKLEtBQUtJLGNBQTNDLEVBQTJERixjQUFjRixLQUFLRSxZQUE5RSxFQUE1QixDQUFQO0FBQ0Q7QUFDRixHQVRNLEVBU0pzRCxJQVRJLENBU0ViLElBQUQsSUFBVTtBQUNoQixRQUFJQSxJQUFKLEVBQVU7QUFDUnZELFVBQUl1RCxJQUFKLEdBQVdBLElBQVg7QUFDQXJEO0FBQ0Q7QUFDRixHQWRNLEVBZUpxRSxLQWZJLENBZUdDLEtBQUQsSUFBVztBQUNoQixRQUFHQSxpQkFBaUJDLGVBQU1DLEtBQTFCLEVBQWlDO0FBQy9CeEUsV0FBS3NFLEtBQUw7QUFDQTtBQUNELEtBSEQsTUFJSztBQUNIO0FBQ0FHLHVCQUFJSCxLQUFKLENBQVUscUNBQVYsRUFBaURBLEtBQWpEO0FBQ0EsWUFBTSxJQUFJQyxlQUFNQyxLQUFWLENBQWdCRCxlQUFNQyxLQUFOLENBQVlFLGFBQTVCLEVBQTJDSixLQUEzQyxDQUFOO0FBQ0Q7QUFDRixHQXpCSSxDQUFQO0FBMEJEOztBQUVELFNBQVN6QixXQUFULENBQXFCL0MsR0FBckIsRUFBeUI7QUFDdkIsTUFBSUEsSUFBSXdDLE9BQUosQ0FBWSxpQkFBWixDQUFKLEVBQW9DO0FBQ2xDO0FBQ0EsV0FBT3hDLElBQUl3QyxPQUFKLENBQVksaUJBQVosRUFBK0JxQyxLQUEvQixDQUFxQyxHQUFyQyxFQUEwQyxDQUExQyxDQUFQO0FBQ0QsR0FIRCxNQUdPLElBQUk3RSxJQUFJOEUsVUFBSixJQUFrQjlFLElBQUk4RSxVQUFKLENBQWVDLGFBQXJDLEVBQW9EO0FBQ3pEO0FBQ0EsV0FBTy9FLElBQUk4RSxVQUFKLENBQWVDLGFBQXRCO0FBQ0QsR0FITSxNQUdBLElBQUkvRSxJQUFJZ0YsTUFBUixFQUFnQjtBQUNyQjtBQUNBLFdBQU9oRixJQUFJZ0YsTUFBSixDQUFXRCxhQUFsQjtBQUNELEdBSE0sTUFHQSxJQUFJL0UsSUFBSThFLFVBQUosSUFBa0I5RSxJQUFJOEUsVUFBSixDQUFlRSxNQUFyQyxFQUE2QztBQUNsRDtBQUNBLFdBQU9oRixJQUFJOEUsVUFBSixDQUFlRSxNQUFmLENBQXNCRCxhQUE3QjtBQUNELEdBSE0sTUFHQTtBQUNMO0FBQ0EsV0FBTy9FLElBQUltRCxFQUFYO0FBQ0Q7QUFDRjs7QUFFRCxTQUFTNUIsUUFBVCxDQUFrQnZCLEdBQWxCLEVBQXVCO0FBQ3JCLE1BQUksQ0FBQyxDQUFDQSxJQUFJQSxHQUFKLElBQVdBLEdBQVosRUFBaUJ3QyxPQUFqQixDQUF5QnlDLGFBQTlCLEVBQ0U7O0FBRUYsTUFBSUMsU0FBUyxDQUFDbEYsSUFBSUEsR0FBSixJQUFXQSxHQUFaLEVBQWlCd0MsT0FBakIsQ0FBeUJ5QyxhQUF0QztBQUNBLE1BQUlwRSxLQUFKLEVBQVdFLFNBQVgsRUFBc0JHLGFBQXRCOztBQUVBO0FBQ0EsTUFBSWlFLGFBQWEsUUFBakI7O0FBRUEsTUFBSUMsUUFBUUYsT0FBT0csV0FBUCxHQUFxQmhDLE9BQXJCLENBQTZCOEIsVUFBN0IsQ0FBWjs7QUFFQSxNQUFJQyxTQUFTLENBQWIsRUFBZ0I7QUFDZCxRQUFJRSxjQUFjSixPQUFPSyxTQUFQLENBQWlCSixXQUFXOUUsTUFBNUIsRUFBb0M2RSxPQUFPN0UsTUFBM0MsQ0FBbEI7QUFDQSxRQUFJbUYsY0FBY0MsYUFBYUgsV0FBYixFQUEwQlQsS0FBMUIsQ0FBZ0MsR0FBaEMsQ0FBbEI7O0FBRUEsUUFBSVcsWUFBWW5GLE1BQVosSUFBc0IsQ0FBMUIsRUFBNkI7QUFDM0JRLGNBQVEyRSxZQUFZLENBQVosQ0FBUjtBQUNBLFVBQUl6QixNQUFNeUIsWUFBWSxDQUFaLENBQVY7O0FBRUEsVUFBSUUsY0FBYyxpQkFBbEI7O0FBRUEsVUFBSUMsV0FBVzVCLElBQUlWLE9BQUosQ0FBWXFDLFdBQVosQ0FBZjtBQUNBLFVBQUlDLFlBQVksQ0FBaEIsRUFBbUI7QUFDakJ6RSx3QkFBZ0I2QyxJQUFJd0IsU0FBSixDQUFjRyxZQUFZckYsTUFBMUIsRUFBa0MwRCxJQUFJMUQsTUFBdEMsQ0FBaEI7QUFDRCxPQUZELE1BR0s7QUFDSFUsb0JBQVlnRCxHQUFaO0FBQ0Q7QUFDRjtBQUNGOztBQUVELFNBQU8sRUFBQ2xELE9BQU9BLEtBQVIsRUFBZUUsV0FBV0EsU0FBMUIsRUFBcUNHLGVBQWVBLGFBQXBELEVBQVA7QUFDRDs7QUFFRCxTQUFTdUUsWUFBVCxDQUFzQkcsR0FBdEIsRUFBMkI7QUFDekIsU0FBTyxJQUFJL0QsTUFBSixDQUFXK0QsR0FBWCxFQUFnQixRQUFoQixFQUEwQkMsUUFBMUIsRUFBUDtBQUNEOztBQUVNLFNBQVNsRyxnQkFBVCxDQUEwQkssR0FBMUIsRUFBK0JDLEdBQS9CLEVBQW9DQyxJQUFwQyxFQUEwQztBQUMvQ0QsTUFBSWlGLE1BQUosQ0FBVyw2QkFBWCxFQUEwQyxHQUExQztBQUNBakYsTUFBSWlGLE1BQUosQ0FBVyw4QkFBWCxFQUEyQyw2QkFBM0M7QUFDQWpGLE1BQUlpRixNQUFKLENBQVcsOEJBQVgsRUFBMkMsa05BQTNDO0FBQ0FqRixNQUFJaUYsTUFBSixDQUFXLCtCQUFYLEVBQTRDLCtDQUE1QztBQUNBO0FBQ0EsTUFBSSxhQUFhbEYsSUFBSThGLE1BQXJCLEVBQTZCO0FBQzNCN0YsUUFBSThGLFVBQUosQ0FBZSxHQUFmO0FBQ0QsR0FGRCxNQUdLO0FBQ0g3RjtBQUNEO0FBQ0Y7O0FBRU0sU0FBU04sbUJBQVQsQ0FBNkJJLEdBQTdCLEVBQWtDQyxHQUFsQyxFQUF1Q0MsSUFBdkMsRUFBNkM7QUFDbEQsTUFBSUYsSUFBSThGLE1BQUosS0FBZSxNQUFmLElBQXlCOUYsSUFBSTBCLElBQUosQ0FBU3NFLE9BQXRDLEVBQStDO0FBQzdDaEcsUUFBSWlHLGNBQUosR0FBcUJqRyxJQUFJOEYsTUFBekI7QUFDQTlGLFFBQUk4RixNQUFKLEdBQWE5RixJQUFJMEIsSUFBSixDQUFTc0UsT0FBdEI7QUFDQSxXQUFPaEcsSUFBSTBCLElBQUosQ0FBU3NFLE9BQWhCO0FBQ0Q7QUFDRDlGO0FBQ0Q7O0FBRU0sU0FBU0wsaUJBQVQsQ0FBMkJxRyxHQUEzQixFQUFnQ2xHLEdBQWhDLEVBQXFDQyxHQUFyQyxFQUEwQ0MsSUFBMUMsRUFBZ0Q7QUFDckQsTUFBSWdHLGVBQWV6QixlQUFNQyxLQUF6QixFQUFnQztBQUM5QixRQUFJeUIsVUFBSjtBQUNBO0FBQ0EsWUFBUUQsSUFBSUUsSUFBWjtBQUNBLFdBQUszQixlQUFNQyxLQUFOLENBQVkyQixxQkFBakI7QUFDRUYscUJBQWEsR0FBYjtBQUNBO0FBQ0YsV0FBSzFCLGVBQU1DLEtBQU4sQ0FBWTRCLGdCQUFqQjtBQUNFSCxxQkFBYSxHQUFiO0FBQ0E7QUFDRjtBQUNFQSxxQkFBYSxHQUFiO0FBUkY7O0FBV0FsRyxRQUFJc0csTUFBSixDQUFXSixVQUFYO0FBQ0FsRyxRQUFJdUcsSUFBSixDQUFTLEVBQUVKLE1BQU1GLElBQUlFLElBQVosRUFBa0I1QixPQUFPMEIsSUFBSU8sT0FBN0IsRUFBVDtBQUNBOUIscUJBQUlILEtBQUosQ0FBVTBCLElBQUlPLE9BQWQsRUFBdUJQLEdBQXZCO0FBQ0EsUUFBSWxHLElBQUlpRCxNQUFKLElBQWNqRCxJQUFJaUQsTUFBSixDQUFXeUQseUJBQTdCLEVBQXdEO0FBQ3REeEcsV0FBS2dHLEdBQUw7QUFDRDtBQUNGLEdBcEJELE1Bb0JPLElBQUlBLElBQUlLLE1BQUosSUFBY0wsSUFBSU8sT0FBdEIsRUFBK0I7QUFDcEN4RyxRQUFJc0csTUFBSixDQUFXTCxJQUFJSyxNQUFmO0FBQ0F0RyxRQUFJdUcsSUFBSixDQUFTLEVBQUVoQyxPQUFPMEIsSUFBSU8sT0FBYixFQUFUO0FBQ0F2RyxTQUFLZ0csR0FBTDtBQUNELEdBSk0sTUFJQTtBQUNMdkIscUJBQUlILEtBQUosQ0FBVSxpQ0FBVixFQUE2QzBCLEdBQTdDLEVBQWtEQSxJQUFJUyxLQUF0RDtBQUNBMUcsUUFBSXNHLE1BQUosQ0FBVyxHQUFYO0FBQ0F0RyxRQUFJdUcsSUFBSixDQUFTO0FBQ1BKLFlBQU0zQixlQUFNQyxLQUFOLENBQVkyQixxQkFEWDtBQUVQSSxlQUFTO0FBRkYsS0FBVDtBQUlBdkcsU0FBS2dHLEdBQUw7QUFDRDtBQUVGOztBQUVNLFNBQVNwRyxzQkFBVCxDQUFnQ0UsR0FBaEMsRUFBcUNDLEdBQXJDLEVBQTBDQyxJQUExQyxFQUFnRDtBQUNyRCxNQUFJLENBQUNGLElBQUl1RCxJQUFKLENBQVNELFFBQWQsRUFBd0I7QUFDdEJyRCxRQUFJc0csTUFBSixDQUFXLEdBQVg7QUFDQXRHLFFBQUkyRyxHQUFKLENBQVEsa0RBQVI7QUFDQTtBQUNEO0FBQ0QxRztBQUNEOztBQUVNLFNBQVNILDZCQUFULENBQXVDOEcsT0FBdkMsRUFBZ0Q7QUFDckQsTUFBSSxDQUFDQSxRQUFRdEQsSUFBUixDQUFhRCxRQUFsQixFQUE0QjtBQUMxQixVQUFNa0IsUUFBUSxJQUFJRSxLQUFKLEVBQWQ7QUFDQUYsVUFBTStCLE1BQU4sR0FBZSxHQUFmO0FBQ0EvQixVQUFNaUMsT0FBTixHQUFnQixzQ0FBaEI7QUFDQSxVQUFNakMsS0FBTjtBQUNEO0FBQ0QsU0FBT04sUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQsU0FBUzFCLGNBQVQsQ0FBd0J6QyxHQUF4QixFQUE2QkMsR0FBN0IsRUFBa0M7QUFDaENBLE1BQUlzRyxNQUFKLENBQVcsR0FBWDtBQUNBdEcsTUFBSTJHLEdBQUosQ0FBUSwwQkFBUjtBQUNEIiwiZmlsZSI6Im1pZGRsZXdhcmVzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEFwcENhY2hlIGZyb20gJy4vY2FjaGUnO1xuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgYXV0aCBmcm9tICcuL0F1dGgnO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuL0NvbmZpZyc7XG5pbXBvcnQgQ2xpZW50U0RLIGZyb20gJy4vQ2xpZW50U0RLJztcblxuLy8gQ2hlY2tzIHRoYXQgdGhlIHJlcXVlc3QgaXMgYXV0aG9yaXplZCBmb3IgdGhpcyBhcHAgYW5kIGNoZWNrcyB1c2VyXG4vLyBhdXRoIHRvby5cbi8vIFRoZSBib2R5cGFyc2VyIHNob3VsZCBydW4gYmVmb3JlIHRoaXMgbWlkZGxld2FyZS5cbi8vIEFkZHMgaW5mbyB0byB0aGUgcmVxdWVzdDpcbi8vIHJlcS5jb25maWcgLSB0aGUgQ29uZmlnIGZvciB0aGlzIGFwcFxuLy8gcmVxLmF1dGggLSB0aGUgQXV0aCBmb3IgdGhpcyByZXF1ZXN0XG5leHBvcnQgZnVuY3Rpb24gaGFuZGxlUGFyc2VIZWFkZXJzKHJlcSwgcmVzLCBuZXh0KSB7XG4gIHZhciBtb3VudFBhdGhMZW5ndGggPSByZXEub3JpZ2luYWxVcmwubGVuZ3RoIC0gcmVxLnVybC5sZW5ndGg7XG4gIHZhciBtb3VudFBhdGggPSByZXEub3JpZ2luYWxVcmwuc2xpY2UoMCwgbW91bnRQYXRoTGVuZ3RoKTtcbiAgdmFyIG1vdW50ID0gcmVxLnByb3RvY29sICsgJzovLycgKyByZXEuZ2V0KCdob3N0JykgKyBtb3VudFBhdGg7XG5cbiAgdmFyIGluZm8gPSB7XG4gICAgYXBwSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtQXBwbGljYXRpb24tSWQnKSxcbiAgICBzZXNzaW9uVG9rZW46IHJlcS5nZXQoJ1gtUGFyc2UtU2Vzc2lvbi1Ub2tlbicpLFxuICAgIG1hc3RlcktleTogcmVxLmdldCgnWC1QYXJzZS1NYXN0ZXItS2V5JyksXG4gICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtSW5zdGFsbGF0aW9uLUlkJyksXG4gICAgY2xpZW50S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1LZXknKSxcbiAgICBqYXZhc2NyaXB0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUphdmFzY3JpcHQtS2V5JyksXG4gICAgZG90TmV0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLVdpbmRvd3MtS2V5JyksXG4gICAgcmVzdEFQSUtleTogcmVxLmdldCgnWC1QYXJzZS1SRVNULUFQSS1LZXknKSxcbiAgICBjbGllbnRWZXJzaW9uOiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1WZXJzaW9uJylcbiAgfTtcblxuICB2YXIgYmFzaWNBdXRoID0gaHR0cEF1dGgocmVxKTtcblxuICBpZiAoYmFzaWNBdXRoKSB7XG4gICAgdmFyIGJhc2ljQXV0aEFwcElkID0gYmFzaWNBdXRoLmFwcElkO1xuICAgIGlmIChBcHBDYWNoZS5nZXQoYmFzaWNBdXRoQXBwSWQpKSB7XG4gICAgICBpbmZvLmFwcElkID0gYmFzaWNBdXRoQXBwSWQ7XG4gICAgICBpbmZvLm1hc3RlcktleSA9IGJhc2ljQXV0aC5tYXN0ZXJLZXkgfHwgaW5mby5tYXN0ZXJLZXk7XG4gICAgICBpbmZvLmphdmFzY3JpcHRLZXkgPSBiYXNpY0F1dGguamF2YXNjcmlwdEtleSB8fCBpbmZvLmphdmFzY3JpcHRLZXk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlcS5ib2R5KSB7XG4gICAgLy8gVW5pdHkgU0RLIHNlbmRzIGEgX25vQm9keSBrZXkgd2hpY2ggbmVlZHMgdG8gYmUgcmVtb3ZlZC5cbiAgICAvLyBVbmNsZWFyIGF0IHRoaXMgcG9pbnQgaWYgYWN0aW9uIG5lZWRzIHRvIGJlIHRha2VuLlxuICAgIGRlbGV0ZSByZXEuYm9keS5fbm9Cb2R5O1xuICB9XG5cbiAgdmFyIGZpbGVWaWFKU09OID0gZmFsc2U7XG5cbiAgaWYgKCFpbmZvLmFwcElkIHx8ICFBcHBDYWNoZS5nZXQoaW5mby5hcHBJZCkpIHtcbiAgICAvLyBTZWUgaWYgd2UgY2FuIGZpbmQgdGhlIGFwcCBpZCBvbiB0aGUgYm9keS5cbiAgICBpZiAocmVxLmJvZHkgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgIC8vIFRoZSBvbmx5IGNoYW5jZSB0byBmaW5kIHRoZSBhcHAgaWQgaXMgaWYgdGhpcyBpcyBhIGZpbGVcbiAgICAgIC8vIHVwbG9hZCB0aGF0IGFjdHVhbGx5IGlzIGEgSlNPTiBib2R5LiBTbyB0cnkgdG8gcGFyc2UgaXQuXG4gICAgICByZXEuYm9keSA9IEpTT04ucGFyc2UocmVxLmJvZHkpO1xuICAgICAgZmlsZVZpYUpTT04gPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZXEuYm9keSkge1xuICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9SZXZvY2FibGVTZXNzaW9uO1xuICAgIH1cblxuICAgIGlmIChyZXEuYm9keSAmJlxuICAgICAgcmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQgJiZcbiAgICAgIEFwcENhY2hlLmdldChyZXEuYm9keS5fQXBwbGljYXRpb25JZCkgJiZcbiAgICAgICghaW5mby5tYXN0ZXJLZXkgfHwgQXBwQ2FjaGUuZ2V0KHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkKS5tYXN0ZXJLZXkgPT09IGluZm8ubWFzdGVyS2V5KVxuICAgICkge1xuICAgICAgaW5mby5hcHBJZCA9IHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkO1xuICAgICAgaW5mby5qYXZhc2NyaXB0S2V5ID0gcmVxLmJvZHkuX0phdmFTY3JpcHRLZXkgfHwgJyc7XG4gICAgICBkZWxldGUgcmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQ7XG4gICAgICBkZWxldGUgcmVxLmJvZHkuX0phdmFTY3JpcHRLZXk7XG4gICAgICAvLyBUT0RPOiB0ZXN0IHRoYXQgdGhlIFJFU1QgQVBJIGZvcm1hdHMgZ2VuZXJhdGVkIGJ5IHRoZSBvdGhlclxuICAgICAgLy8gU0RLcyBhcmUgaGFuZGxlZCBva1xuICAgICAgaWYgKHJlcS5ib2R5Ll9DbGllbnRWZXJzaW9uKSB7XG4gICAgICAgIGluZm8uY2xpZW50VmVyc2lvbiA9IHJlcS5ib2R5Ll9DbGllbnRWZXJzaW9uO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX0NsaWVudFZlcnNpb247XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX0luc3RhbGxhdGlvbklkKSB7XG4gICAgICAgIGluZm8uaW5zdGFsbGF0aW9uSWQgPSByZXEuYm9keS5fSW5zdGFsbGF0aW9uSWQ7XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fSW5zdGFsbGF0aW9uSWQ7XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX1Nlc3Npb25Ub2tlbikge1xuICAgICAgICBpbmZvLnNlc3Npb25Ub2tlbiA9IHJlcS5ib2R5Ll9TZXNzaW9uVG9rZW47XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fU2Vzc2lvblRva2VuO1xuICAgICAgfVxuICAgICAgaWYgKHJlcS5ib2R5Ll9NYXN0ZXJLZXkpIHtcbiAgICAgICAgaW5mby5tYXN0ZXJLZXkgPSByZXEuYm9keS5fTWFzdGVyS2V5O1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX01hc3RlcktleTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXEuYm9keS5fQ29udGVudFR5cGUpIHtcbiAgICAgICAgcmVxLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddID0gcmVxLmJvZHkuX0NvbnRlbnRUeXBlO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX0NvbnRlbnRUeXBlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChpbmZvLmNsaWVudFZlcnNpb24pIHtcbiAgICBpbmZvLmNsaWVudFNESyA9IENsaWVudFNESy5mcm9tU3RyaW5nKGluZm8uY2xpZW50VmVyc2lvbik7XG4gIH1cblxuICBpZiAoZmlsZVZpYUpTT04pIHtcbiAgICAvLyBXZSBuZWVkIHRvIHJlcG9wdWxhdGUgcmVxLmJvZHkgd2l0aCBhIGJ1ZmZlclxuICAgIHZhciBiYXNlNjQgPSByZXEuYm9keS5iYXNlNjQ7XG4gICAgcmVxLmJvZHkgPSBuZXcgQnVmZmVyKGJhc2U2NCwgJ2Jhc2U2NCcpO1xuICB9XG5cbiAgY29uc3QgY2xpZW50SXAgPSBnZXRDbGllbnRJcChyZXEpO1xuXG4gIGluZm8uYXBwID0gQXBwQ2FjaGUuZ2V0KGluZm8uYXBwSWQpO1xuICByZXEuY29uZmlnID0gQ29uZmlnLmdldChpbmZvLmFwcElkLCBtb3VudCk7XG4gIHJlcS5jb25maWcuaGVhZGVycyA9IHJlcS5oZWFkZXJzIHx8IHt9O1xuICByZXEuY29uZmlnLmlwID0gY2xpZW50SXA7XG4gIHJlcS5pbmZvID0gaW5mbztcblxuICBpZiAoaW5mby5tYXN0ZXJLZXkgJiYgcmVxLmNvbmZpZy5tYXN0ZXJLZXlJcHMgJiYgcmVxLmNvbmZpZy5tYXN0ZXJLZXlJcHMubGVuZ3RoICE9PSAwICYmIHJlcS5jb25maWcubWFzdGVyS2V5SXBzLmluZGV4T2YoY2xpZW50SXApID09PSAtMSkge1xuICAgIHJldHVybiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcyk7XG4gIH1cblxuICB2YXIgaXNNYXN0ZXIgPSAoaW5mby5tYXN0ZXJLZXkgPT09IHJlcS5jb25maWcubWFzdGVyS2V5KTtcblxuICBpZiAoaXNNYXN0ZXIpIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoeyBjb25maWc6IHJlcS5jb25maWcsIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLCBpc01hc3RlcjogdHJ1ZSB9KTtcbiAgICBuZXh0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGlzUmVhZE9ubHlNYXN0ZXIgPSAoaW5mby5tYXN0ZXJLZXkgPT09IHJlcS5jb25maWcucmVhZE9ubHlNYXN0ZXJLZXkpO1xuICBpZiAodHlwZW9mIHJlcS5jb25maWcucmVhZE9ubHlNYXN0ZXJLZXkgIT0gJ3VuZGVmaW5lZCcgJiYgcmVxLmNvbmZpZy5yZWFkT25seU1hc3RlcktleSAmJiBpc1JlYWRPbmx5TWFzdGVyKSB7XG4gICAgcmVxLmF1dGggPSBuZXcgYXV0aC5BdXRoKHsgY29uZmlnOiByZXEuY29uZmlnLCBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCwgaXNNYXN0ZXI6IHRydWUsIGlzUmVhZE9ubHk6IHRydWUgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIENsaWVudCBrZXlzIGFyZSBub3QgcmVxdWlyZWQgaW4gcGFyc2Utc2VydmVyLCBidXQgaWYgYW55IGhhdmUgYmVlbiBjb25maWd1cmVkIGluIHRoZSBzZXJ2ZXIsIHZhbGlkYXRlIHRoZW1cbiAgLy8gIHRvIHByZXNlcnZlIG9yaWdpbmFsIGJlaGF2aW9yLlxuICBjb25zdCBrZXlzID0gW1wiY2xpZW50S2V5XCIsIFwiamF2YXNjcmlwdEtleVwiLCBcImRvdE5ldEtleVwiLCBcInJlc3RBUElLZXlcIl07XG4gIGNvbnN0IG9uZUtleUNvbmZpZ3VyZWQgPSBrZXlzLnNvbWUoZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIHJlcS5jb25maWdba2V5XSAhPT0gdW5kZWZpbmVkO1xuICB9KTtcbiAgY29uc3Qgb25lS2V5TWF0Y2hlcyA9IGtleXMuc29tZShmdW5jdGlvbihrZXkpe1xuICAgIHJldHVybiByZXEuY29uZmlnW2tleV0gIT09IHVuZGVmaW5lZCAmJiBpbmZvW2tleV0gPT09IHJlcS5jb25maWdba2V5XTtcbiAgfSk7XG5cbiAgaWYgKG9uZUtleUNvbmZpZ3VyZWQgJiYgIW9uZUtleU1hdGNoZXMpIHtcbiAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICB9XG5cbiAgaWYgKHJlcS51cmwgPT0gXCIvbG9naW5cIikge1xuICAgIGRlbGV0ZSBpbmZvLnNlc3Npb25Ub2tlbjtcbiAgfVxuXG4gIGlmICghaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoeyBjb25maWc6IHJlcS5jb25maWcsIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLCBpc01hc3RlcjogZmFsc2UgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAvLyBoYW5kbGUgdGhlIHVwZ3JhZGVUb1Jldm9jYWJsZVNlc3Npb24gcGF0aCBvbiBpdCdzIG93blxuICAgIGlmIChpbmZvLnNlc3Npb25Ub2tlbiAmJlxuICAgICAgICByZXEudXJsID09PSAnL3VwZ3JhZGVUb1Jldm9jYWJsZVNlc3Npb24nICYmXG4gICAgICAgIGluZm8uc2Vzc2lvblRva2VuLmluZGV4T2YoJ3I6JykgIT0gMCkge1xuICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbih7IGNvbmZpZzogcmVxLmNvbmZpZywgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4gfSlcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvclNlc3Npb25Ub2tlbih7IGNvbmZpZzogcmVxLmNvbmZpZywgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4gfSlcbiAgICB9XG4gIH0pLnRoZW4oKGF1dGgpID0+IHtcbiAgICBpZiAoYXV0aCkge1xuICAgICAgcmVxLmF1dGggPSBhdXRoO1xuICAgICAgbmV4dCgpO1xuICAgIH1cbiAgfSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIFBhcnNlLkVycm9yKSB7XG4gICAgICAgIG5leHQoZXJyb3IpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgLy8gVE9ETzogRGV0ZXJtaW5lIHRoZSBjb3JyZWN0IGVycm9yIHNjZW5hcmlvLlxuICAgICAgICBsb2cuZXJyb3IoJ2Vycm9yIGdldHRpbmcgYXV0aCBmb3Igc2Vzc2lvblRva2VuJywgZXJyb3IpO1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVU5LTk9XTl9FUlJPUiwgZXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRDbGllbnRJcChyZXEpe1xuICBpZiAocmVxLmhlYWRlcnNbJ3gtZm9yd2FyZGVkLWZvciddKSB7XG4gICAgLy8gdHJ5IHRvIGdldCBmcm9tIHgtZm9yd2FyZWQtZm9yIGlmIGl0IHNldCAoYmVoaW5kIHJldmVyc2UgcHJveHkpXG4gICAgcmV0dXJuIHJlcS5oZWFkZXJzWyd4LWZvcndhcmRlZC1mb3InXS5zcGxpdCgnLCcpWzBdO1xuICB9IGVsc2UgaWYgKHJlcS5jb25uZWN0aW9uICYmIHJlcS5jb25uZWN0aW9uLnJlbW90ZUFkZHJlc3MpIHtcbiAgICAvLyBubyBwcm94eSwgdHJ5IGdldHRpbmcgZnJvbSBjb25uZWN0aW9uLnJlbW90ZUFkZHJlc3NcbiAgICByZXR1cm4gcmVxLmNvbm5lY3Rpb24ucmVtb3RlQWRkcmVzcztcbiAgfSBlbHNlIGlmIChyZXEuc29ja2V0KSB7XG4gICAgLy8gdHJ5IHRvIGdldCBpdCBmcm9tIHJlcS5zb2NrZXRcbiAgICByZXR1cm4gcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzO1xuICB9IGVsc2UgaWYgKHJlcS5jb25uZWN0aW9uICYmIHJlcS5jb25uZWN0aW9uLnNvY2tldCkge1xuICAgIC8vIHRyeSB0byBnZXQgaXQgZm9ybSB0aGUgY29ubmVjdGlvbi5zb2NrZXRcbiAgICByZXR1cm4gcmVxLmNvbm5lY3Rpb24uc29ja2V0LnJlbW90ZUFkZHJlc3M7XG4gIH0gZWxzZSB7XG4gICAgLy8gaWYgbm9uIGFib3ZlLCBmYWxsYmFjay5cbiAgICByZXR1cm4gcmVxLmlwO1xuICB9XG59XG5cbmZ1bmN0aW9uIGh0dHBBdXRoKHJlcSkge1xuICBpZiAoIShyZXEucmVxIHx8IHJlcSkuaGVhZGVycy5hdXRob3JpemF0aW9uKVxuICAgIHJldHVybiA7XG5cbiAgdmFyIGhlYWRlciA9IChyZXEucmVxIHx8IHJlcSkuaGVhZGVycy5hdXRob3JpemF0aW9uO1xuICB2YXIgYXBwSWQsIG1hc3RlcktleSwgamF2YXNjcmlwdEtleTtcblxuICAvLyBwYXJzZSBoZWFkZXJcbiAgdmFyIGF1dGhQcmVmaXggPSAnYmFzaWMgJztcblxuICB2YXIgbWF0Y2ggPSBoZWFkZXIudG9Mb3dlckNhc2UoKS5pbmRleE9mKGF1dGhQcmVmaXgpO1xuXG4gIGlmIChtYXRjaCA9PSAwKSB7XG4gICAgdmFyIGVuY29kZWRBdXRoID0gaGVhZGVyLnN1YnN0cmluZyhhdXRoUHJlZml4Lmxlbmd0aCwgaGVhZGVyLmxlbmd0aCk7XG4gICAgdmFyIGNyZWRlbnRpYWxzID0gZGVjb2RlQmFzZTY0KGVuY29kZWRBdXRoKS5zcGxpdCgnOicpO1xuXG4gICAgaWYgKGNyZWRlbnRpYWxzLmxlbmd0aCA9PSAyKSB7XG4gICAgICBhcHBJZCA9IGNyZWRlbnRpYWxzWzBdO1xuICAgICAgdmFyIGtleSA9IGNyZWRlbnRpYWxzWzFdO1xuXG4gICAgICB2YXIganNLZXlQcmVmaXggPSAnamF2YXNjcmlwdC1rZXk9JztcblxuICAgICAgdmFyIG1hdGNoS2V5ID0ga2V5LmluZGV4T2YoanNLZXlQcmVmaXgpXG4gICAgICBpZiAobWF0Y2hLZXkgPT0gMCkge1xuICAgICAgICBqYXZhc2NyaXB0S2V5ID0ga2V5LnN1YnN0cmluZyhqc0tleVByZWZpeC5sZW5ndGgsIGtleS5sZW5ndGgpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIG1hc3RlcktleSA9IGtleTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4ge2FwcElkOiBhcHBJZCwgbWFzdGVyS2V5OiBtYXN0ZXJLZXksIGphdmFzY3JpcHRLZXk6IGphdmFzY3JpcHRLZXl9O1xufVxuXG5mdW5jdGlvbiBkZWNvZGVCYXNlNjQoc3RyKSB7XG4gIHJldHVybiBuZXcgQnVmZmVyKHN0ciwgJ2Jhc2U2NCcpLnRvU3RyaW5nKClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFsbG93Q3Jvc3NEb21haW4ocmVxLCByZXMsIG5leHQpIHtcbiAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgJyonKTtcbiAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcycsICdHRVQsUFVULFBPU1QsREVMRVRFLE9QVElPTlMnKTtcbiAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycycsICdYLVBhcnNlLU1hc3Rlci1LZXksIFgtUGFyc2UtUkVTVC1BUEktS2V5LCBYLVBhcnNlLUphdmFzY3JpcHQtS2V5LCBYLVBhcnNlLUFwcGxpY2F0aW9uLUlkLCBYLVBhcnNlLUNsaWVudC1WZXJzaW9uLCBYLVBhcnNlLVNlc3Npb24tVG9rZW4sIFgtUmVxdWVzdGVkLVdpdGgsIFgtUGFyc2UtUmV2b2NhYmxlLVNlc3Npb24sIENvbnRlbnQtVHlwZSwgWC1DU1JGLVRva2VuJyk7XG4gIHJlcy5oZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUV4cG9zZS1IZWFkZXJzJywgJ1gtUGFyc2UtSm9iLVN0YXR1cy1JZCwgWC1QYXJzZS1QdXNoLVN0YXR1cy1JZCcpO1xuICAvLyBpbnRlcmNlcHQgT1BUSU9OUyBtZXRob2RcbiAgaWYgKCdPUFRJT05TJyA9PSByZXEubWV0aG9kKSB7XG4gICAgcmVzLnNlbmRTdGF0dXMoMjAwKTtcbiAgfVxuICBlbHNlIHtcbiAgICBuZXh0KCk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFsbG93TWV0aG9kT3ZlcnJpZGUocmVxLCByZXMsIG5leHQpIHtcbiAgaWYgKHJlcS5tZXRob2QgPT09ICdQT1NUJyAmJiByZXEuYm9keS5fbWV0aG9kKSB7XG4gICAgcmVxLm9yaWdpbmFsTWV0aG9kID0gcmVxLm1ldGhvZDtcbiAgICByZXEubWV0aG9kID0gcmVxLmJvZHkuX21ldGhvZDtcbiAgICBkZWxldGUgcmVxLmJvZHkuX21ldGhvZDtcbiAgfVxuICBuZXh0KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYW5kbGVQYXJzZUVycm9ycyhlcnIsIHJlcSwgcmVzLCBuZXh0KSB7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgIGxldCBodHRwU3RhdHVzO1xuICAgIC8vIFRPRE86IGZpbGwgb3V0IHRoaXMgbWFwcGluZ1xuICAgIHN3aXRjaCAoZXJyLmNvZGUpIHtcbiAgICBjYXNlIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUjpcbiAgICAgIGh0dHBTdGF0dXMgPSA1MDA7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQ6XG4gICAgICBodHRwU3RhdHVzID0gNDA0O1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGh0dHBTdGF0dXMgPSA0MDA7XG4gICAgfVxuXG4gICAgcmVzLnN0YXR1cyhodHRwU3RhdHVzKTtcbiAgICByZXMuanNvbih7IGNvZGU6IGVyci5jb2RlLCBlcnJvcjogZXJyLm1lc3NhZ2UgfSk7XG4gICAgbG9nLmVycm9yKGVyci5tZXNzYWdlLCBlcnIpO1xuICAgIGlmIChyZXEuY29uZmlnICYmIHJlcS5jb25maWcuZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlcikge1xuICAgICAgbmV4dChlcnIpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChlcnIuc3RhdHVzICYmIGVyci5tZXNzYWdlKSB7XG4gICAgcmVzLnN0YXR1cyhlcnIuc3RhdHVzKTtcbiAgICByZXMuanNvbih7IGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICBuZXh0KGVycik7XG4gIH0gZWxzZSB7XG4gICAgbG9nLmVycm9yKCdVbmNhdWdodCBpbnRlcm5hbCBzZXJ2ZXIgZXJyb3IuJywgZXJyLCBlcnIuc3RhY2spO1xuICAgIHJlcy5zdGF0dXMoNTAwKTtcbiAgICByZXMuanNvbih7XG4gICAgICBjb2RlOiBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICBtZXNzYWdlOiAnSW50ZXJuYWwgc2VydmVyIGVycm9yLidcbiAgICB9KTtcbiAgICBuZXh0KGVycik7XG4gIH1cblxufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5mb3JjZU1hc3RlcktleUFjY2VzcyhyZXEsIHJlcywgbmV4dCkge1xuICBpZiAoIXJlcS5hdXRoLmlzTWFzdGVyKSB7XG4gICAgcmVzLnN0YXR1cyg0MDMpO1xuICAgIHJlcy5lbmQoJ3tcImVycm9yXCI6XCJ1bmF1dGhvcml6ZWQ6IG1hc3RlciBrZXkgaXMgcmVxdWlyZWRcIn0nKTtcbiAgICByZXR1cm47XG4gIH1cbiAgbmV4dCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MocmVxdWVzdCkge1xuICBpZiAoIXJlcXVlc3QuYXV0aC5pc01hc3Rlcikge1xuICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKCk7XG4gICAgZXJyb3Iuc3RhdHVzID0gNDAzO1xuICAgIGVycm9yLm1lc3NhZ2UgPSBcInVuYXV0aG9yaXplZDogbWFzdGVyIGtleSBpcyByZXF1aXJlZFwiO1xuICAgIHRocm93IGVycm9yO1xuICB9XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuZnVuY3Rpb24gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpIHtcbiAgcmVzLnN0YXR1cyg0MDMpO1xuICByZXMuZW5kKCd7XCJlcnJvclwiOlwidW5hdXRob3JpemVkXCJ9Jyk7XG59XG4iXX0= \ No newline at end of file diff --git a/lib/password.js b/lib/password.js index 729a07b272..763c292ade 100644 --- a/lib/password.js +++ b/lib/password.js @@ -26,4 +26,5 @@ function compare(password, hashedPassword) { module.exports = { hash: hash, compare: compare -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9wYXNzd29yZC5qcyJdLCJuYW1lcyI6WyJiY3J5cHQiLCJyZXF1aXJlIiwiZSIsImhhc2giLCJwYXNzd29yZCIsImNvbXBhcmUiLCJoYXNoZWRQYXNzd29yZCIsIlByb21pc2UiLCJyZXNvbHZlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0EsSUFBSUEsU0FBU0MsUUFBUSxVQUFSLENBQWI7O0FBRUEsSUFBSTtBQUNGRCxXQUFTQyxRQUFRLFFBQVIsQ0FBVDtBQUNELENBRkQsQ0FFRSxPQUFNQyxDQUFOLEVBQVMsQ0FBUyxDQUFsQixDQUFXOztBQUViO0FBQ0EsU0FBU0MsSUFBVCxDQUFjQyxRQUFkLEVBQXdCO0FBQ3RCLFNBQU9KLE9BQU9HLElBQVAsQ0FBWUMsUUFBWixFQUFzQixFQUF0QixDQUFQO0FBQ0Q7O0FBRUQ7QUFDQTtBQUNBLFNBQVNDLE9BQVQsQ0FBaUJELFFBQWpCLEVBQTJCRSxjQUEzQixFQUEyQztBQUN6QztBQUNBLE1BQUksQ0FBQ0YsUUFBRCxJQUFhLENBQUNFLGNBQWxCLEVBQWtDO0FBQ2hDLFdBQU9DLFFBQVFDLE9BQVIsQ0FBZ0IsS0FBaEIsQ0FBUDtBQUNEO0FBQ0QsU0FBT1IsT0FBT0ssT0FBUCxDQUFlRCxRQUFmLEVBQXlCRSxjQUF6QixDQUFQO0FBQ0Q7O0FBRURHLE9BQU9DLE9BQVAsR0FBaUI7QUFDZlAsUUFBTUEsSUFEUztBQUVmRSxXQUFTQTtBQUZNLENBQWpCIiwiZmlsZSI6InBhc3N3b3JkLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVG9vbHMgZm9yIGVuY3J5cHRpbmcgYW5kIGRlY3J5cHRpbmcgcGFzc3dvcmRzLlxuLy8gQmFzaWNhbGx5IHByb21pc2UtZnJpZW5kbHkgd3JhcHBlcnMgZm9yIGJjcnlwdC5cbnZhciBiY3J5cHQgPSByZXF1aXJlKCdiY3J5cHRqcycpO1xuXG50cnkge1xuICBiY3J5cHQgPSByZXF1aXJlKCdiY3J5cHQnKTtcbn0gY2F0Y2goZSkgeyAvKiAqLyB9XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIGhhc2hlZCBwYXNzd29yZCBzdHJpbmcuXG5mdW5jdGlvbiBoYXNoKHBhc3N3b3JkKSB7XG4gIHJldHVybiBiY3J5cHQuaGFzaChwYXNzd29yZCwgMTApO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3Igd2hldGhlciB0aGlzIHBhc3N3b3JkIGNvbXBhcmVzIHRvIGVxdWFsIHRoaXNcbi8vIGhhc2hlZCBwYXNzd29yZC5cbmZ1bmN0aW9uIGNvbXBhcmUocGFzc3dvcmQsIGhhc2hlZFBhc3N3b3JkKSB7XG4gIC8vIENhbm5vdCBiY3J5cHQgY29tcGFyZSB3aGVuIG9uZSBpcyB1bmRlZmluZWRcbiAgaWYgKCFwYXNzd29yZCB8fCAhaGFzaGVkUGFzc3dvcmQpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbiAgfVxuICByZXR1cm4gYmNyeXB0LmNvbXBhcmUocGFzc3dvcmQsIGhhc2hlZFBhc3N3b3JkKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGhhc2g6IGhhc2gsXG4gIGNvbXBhcmU6IGNvbXBhcmVcbn07XG4iXX0= \ No newline at end of file diff --git a/lib/requiredParameter.js b/lib/requiredParameter.js index 844b5a0749..2360480310 100644 --- a/lib/requiredParameter.js +++ b/lib/requiredParameter.js @@ -6,4 +6,5 @@ Object.defineProperty(exports, "__esModule", { exports.default = errorMessage => { throw errorMessage; -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9yZXF1aXJlZFBhcmFtZXRlci5qcyJdLCJuYW1lcyI6WyJlcnJvck1lc3NhZ2UiXSwibWFwcGluZ3MiOiI7Ozs7OztrQkFDZ0JBLFlBQUQsSUFBK0I7QUFBRSxRQUFNQSxZQUFOO0FBQW9CLEMiLCJmaWxlIjoicmVxdWlyZWRQYXJhbWV0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQGZsb3cgKi9cbmV4cG9ydCBkZWZhdWx0IChlcnJvck1lc3NhZ2U6IHN0cmluZyk6IGFueSA9PiB7IHRocm93IGVycm9yTWVzc2FnZSB9XG4iXX0= \ No newline at end of file diff --git a/lib/rest.js b/lib/rest.js index ffe0e0326a..85df55ffbd 100644 --- a/lib/rest.js +++ b/lib/rest.js @@ -1,11 +1,5 @@ 'use strict'; -var _Auth = require('./Auth'); - -var _Auth2 = _interopRequireDefault(_Auth); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - // 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 @@ -17,7 +11,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de var Parse = require('parse/node').Parse; - var RestQuery = require('./RestQuery'); var RestWrite = require('./RestWrite'); var triggers = require('./triggers'); @@ -61,8 +54,8 @@ function del(config, auth, className, objectId) { throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad objectId'); } - if (className === '_User' && !auth.couldUpdateUserId(objectId)) { - throw new Parse.Error(Parse.Error.SESSION_MISSING, 'insufficient auth to delete user'); + if (className === '_User' && auth.isUnauthenticated()) { + throw new Parse.Error(Parse.Error.SESSION_MISSING, 'Insufficient auth to delete user'); } enforceRoleSecurity('delete', className, auth); @@ -73,13 +66,13 @@ function del(config, auth, className, objectId) { const hasTriggers = checkTriggers(className, config, ['beforeDelete', 'afterDelete']); const hasLiveQuery = checkLiveQuery(className, config); if (hasTriggers || hasLiveQuery || className == '_Session') { - return find(config, _Auth2.default.master(config), className, { objectId: objectId }).then(response => { + return new RestQuery(config, auth, className, { objectId }).forWrite().execute().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'); + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } } var cacheAdapter = config.cacheController; @@ -114,6 +107,8 @@ function del(config, auth, className, objectId) { }, options); }).then(() => { return triggers.maybeRunTrigger(triggers.Types.afterDelete, auth, inflatedObject, null, config); + }).catch(error => { + handleSessionMissingError(error, className, auth); }); } @@ -134,20 +129,29 @@ function update(config, auth, className, restWhere, restObject, clientSDK) { const hasTriggers = checkTriggers(className, config, ['beforeSave', 'afterSave']); const hasLiveQuery = checkLiveQuery(className, config); if (hasTriggers || hasLiveQuery) { - return find(config, _Auth2.default.master(config), className, restWhere); + // Do not use find, as it runs the before finds + return new RestQuery(config, auth, className, restWhere).forWrite().execute(); } return Promise.resolve({}); - }).then(response => { + }).then(({ results }) => { var originalRestObject; - if (response && response.results && response.results.length) { - originalRestObject = response.results[0]; + if (results && results.length) { + originalRestObject = results[0]; } - - var write = new RestWrite(config, auth, className, restWhere, restObject, originalRestObject, clientSDK); - return write.execute(); + return new RestWrite(config, auth, className, restWhere, restObject, originalRestObject, clientSDK).execute(); + }).catch(error => { + handleSessionMissingError(error, className, auth); }); } +function handleSessionMissingError(error, className) { + // If we're trying to update a user without / with bad session token + if (className === '_User' && error.code === Parse.Error.OBJECT_NOT_FOUND) { + 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) { @@ -177,4 +181,5 @@ module.exports = { find, get, update -}; \ No newline at end of file +}; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9yZXN0LmpzIl0sIm5hbWVzIjpbIlBhcnNlIiwicmVxdWlyZSIsIlJlc3RRdWVyeSIsIlJlc3RXcml0ZSIsInRyaWdnZXJzIiwiY2hlY2tUcmlnZ2VycyIsImNsYXNzTmFtZSIsImNvbmZpZyIsInR5cGVzIiwic29tZSIsInRyaWdnZXJUeXBlIiwiZ2V0VHJpZ2dlciIsIlR5cGVzIiwiYXBwbGljYXRpb25JZCIsImNoZWNrTGl2ZVF1ZXJ5IiwibGl2ZVF1ZXJ5Q29udHJvbGxlciIsImhhc0xpdmVRdWVyeSIsImZpbmQiLCJhdXRoIiwicmVzdFdoZXJlIiwicmVzdE9wdGlvbnMiLCJjbGllbnRTREsiLCJlbmZvcmNlUm9sZVNlY3VyaXR5IiwibWF5YmVSdW5RdWVyeVRyaWdnZXIiLCJiZWZvcmVGaW5kIiwidGhlbiIsInJlc3VsdCIsInF1ZXJ5IiwiZXhlY3V0ZSIsImdldCIsIm9iamVjdElkIiwiZGVsIiwiRXJyb3IiLCJJTlZBTElEX0pTT04iLCJpc1VuYXV0aGVudGljYXRlZCIsIlNFU1NJT05fTUlTU0lORyIsImluZmxhdGVkT2JqZWN0IiwiUHJvbWlzZSIsInJlc29sdmUiLCJoYXNUcmlnZ2VycyIsImZvcldyaXRlIiwicmVzcG9uc2UiLCJyZXN1bHRzIiwibGVuZ3RoIiwiZmlyc3RSZXN1bHQiLCJpc01hc3RlciIsInVzZXIiLCJpZCIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsImNhY2hlQWRhcHRlciIsImNhY2hlQ29udHJvbGxlciIsInNlc3Npb25Ub2tlbiIsIk9iamVjdCIsImZyb21KU09OIiwib25BZnRlckRlbGV0ZSIsIm1heWJlUnVuVHJpZ2dlciIsImJlZm9yZURlbGV0ZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJnZXRVc2VyUm9sZXMiLCJvcHRpb25zIiwiYWNsIiwicHVzaCIsImNvbmNhdCIsInVzZXJSb2xlcyIsImRhdGFiYXNlIiwiZGVzdHJveSIsImFmdGVyRGVsZXRlIiwiY2F0Y2giLCJlcnJvciIsImhhbmRsZVNlc3Npb25NaXNzaW5nRXJyb3IiLCJjcmVhdGUiLCJyZXN0T2JqZWN0Iiwid3JpdGUiLCJ1cGRhdGUiLCJvcmlnaW5hbFJlc3RPYmplY3QiLCJjb2RlIiwiY2xhc3Nlc1dpdGhNYXN0ZXJPbmx5QWNjZXNzIiwibWV0aG9kIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsImluZGV4T2YiLCJpc1JlYWRPbmx5IiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLElBQUlBLFFBQVFDLFFBQVEsWUFBUixFQUFzQkQsS0FBbEM7O0FBRUEsSUFBSUUsWUFBWUQsUUFBUSxhQUFSLENBQWhCO0FBQ0EsSUFBSUUsWUFBWUYsUUFBUSxhQUFSLENBQWhCO0FBQ0EsSUFBSUcsV0FBV0gsUUFBUSxZQUFSLENBQWY7O0FBRUEsU0FBU0ksYUFBVCxDQUF1QkMsU0FBdkIsRUFBa0NDLE1BQWxDLEVBQTBDQyxLQUExQyxFQUFpRDtBQUMvQyxTQUFPQSxNQUFNQyxJQUFOLENBQVlDLFdBQUQsSUFBaUI7QUFDakMsV0FBT04sU0FBU08sVUFBVCxDQUFvQkwsU0FBcEIsRUFBK0JGLFNBQVNRLEtBQVQsQ0FBZUYsV0FBZixDQUEvQixFQUE0REgsT0FBT00sYUFBbkUsQ0FBUDtBQUNELEdBRk0sQ0FBUDtBQUdEOztBQUVELFNBQVNDLGNBQVQsQ0FBd0JSLFNBQXhCLEVBQW1DQyxNQUFuQyxFQUEyQztBQUN6QyxTQUFPQSxPQUFPUSxtQkFBUCxJQUE4QlIsT0FBT1EsbUJBQVAsQ0FBMkJDLFlBQTNCLENBQXdDVixTQUF4QyxDQUFyQztBQUNEOztBQUVEO0FBQ0EsU0FBU1csSUFBVCxDQUFjVixNQUFkLEVBQXNCVyxJQUF0QixFQUE0QlosU0FBNUIsRUFBdUNhLFNBQXZDLEVBQWtEQyxXQUFsRCxFQUErREMsU0FBL0QsRUFBMEU7QUFDeEVDLHNCQUFvQixNQUFwQixFQUE0QmhCLFNBQTVCLEVBQXVDWSxJQUF2QztBQUNBLFNBQU9kLFNBQVNtQixvQkFB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QU1nQyxLQUFOLENBQVk4QyxtQkFBNUIsRUFBaURWLEtBQWpELENBQU47QUFDRDs7QUFFRDtBQUNBLE1BQUlsRCxLQUFLOEQsVUFBTCxLQUFvQkgsV0FBVyxRQUFYLElBQXVCQSxXQUFXLFFBQWxDLElBQThDQSxXQUFXLFFBQTdFLENBQUosRUFBNEY7QUFDMUYsVUFBTVQsUUFBUyxvREFBbURTLE1BQU8sYUFBekU7QUFDQSxVQUFNLElBQUk3RSxNQUFNZ0MsS0FBVixDQUFnQmhDLE1BQU1nQyxLQUFOLENBQVk4QyxtQkFBNUIsRUFBaURWLEtBQWpELENBQU47QUFDRDtBQUNGOztBQUVEYSxPQUFPQyxPQUFQLEdBQWlCO0FBQ2ZaLFFBRGU7QUFFZnZDLEtBRmU7QUFHZmQsTUFIZTtBQUlmWSxLQUplO0FBS2Y0QztBQUxlLENBQWpCIiwiZmlsZSI6InJlc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGlzIGZpbGUgY29udGFpbnMgaGVscGVycyBmb3IgcnVubmluZyBvcGVyYXRpb25zIGluIFJFU1QgZm9ybWF0LlxuLy8gVGhlIGdvYWwgaXMgdGhhdCBoYW5kbGVycyB0aGF0IGV4cGxpY2l0bHkgaGFuZGxlIGFuIGV4cHJlc3Mgcm91dGVcbi8vIHNob3VsZCBqdXN0IGJlIHNoYWxsb3cgd3JhcHBlcnMgYXJvdW5kIHRoaW5ncyBpbiB0aGlzIGZpbGUsIGJ1dFxuLy8gdGhlc2UgZnVuY3Rpb25zIHNob3VsZCBub3QgZXhwbGljaXRseSBkZXBlbmQgb24gdGhlIHJlcXVlc3Rcbi8vIG9iamVjdC5cbi8vIFRoaXMgbWVhbnMgdGhhdCBvbmUgb2YgdGhlc2UgaGFuZGxlcnMgY2FuIHN1cHBvcnQgbXVsdGlwbGVcbi8vIHJvdXRlcy4gVGhhdCdzIHVzZWZ1bCBmb3IgdGhlIHJvdXRlcyB0aGF0IGRvIHJlYWxseSBzaW1pbGFyXG4vLyB0aGluZ3MuXG5cbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcblxudmFyIFJlc3RRdWVyeSA9IHJlcXVpcmUoJy4vUmVzdFF1ZXJ5Jyk7XG52YXIgUmVzdFdyaXRlID0gcmVxdWlyZSgnLi9SZXN0V3JpdGUnKTtcbnZhciB0cmlnZ2VycyA9IHJlcXVpcmUoJy4vdHJpZ2dlcnMnKTtcblxuZnVuY3Rpb24gY2hlY2tUcmlnZ2VycyhjbGFzc05hbWUsIGNvbmZpZywgdHlwZXMpIHtcbiAgcmV0dXJuIHR5cGVzLnNvbWUoKHRyaWdnZXJUeXBlKSA9PiB7XG4gICAgcmV0dXJuIHRyaWdnZXJzLmdldFRyaWdnZXIoY2xhc3NOYW1lLCB0cmlnZ2Vycy5UeXBlc1t0cmlnZ2VyVHlwZV0sIGNvbmZpZy5hcHBsaWNhdGlvbklkKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrTGl2ZVF1ZXJ5KGNsYXNzTmFtZSwgY29uZmlnKSB7XG4gIHJldHVybiBjb25maWcubGl2ZVF1ZXJ5Q29udHJvbGxlciAmJiBjb25maWcubGl2ZVF1ZXJ5Q29udHJvbGxlci5oYXNMaXZlUXVlcnkoY2xhc3NOYW1lKVxufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYW4gb2JqZWN0IHdpdGggb3B0aW9uYWwga2V5cyAncmVzdWx0cycgYW5kICdjb3VudCcuXG5mdW5jdGlvbiBmaW5kKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUsIHJlc3RPcHRpb25zLCBjbGllbnRTREspIHtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZmluZCcsIGNsYXNzTmFtZSwgYXV0aCk7XG4gIHJldHVybiB0cmlnZ2Vycy5tYXliZVJ1blF1ZXJ5VHJpZ2dlcih0cmlnZ2Vycy5UeXBlcy5iZWZvcmVGaW5kLCBjbGFzc05hbWUsIHJlc3RXaGVyZSwgcmVzdE9wdGlvbnMsIGNvbmZpZywgYXV0aCkudGhlbigocmVzdWx0KSA9PiB7XG4gICAgcmVzdFdoZXJlID0gcmVzdWx0LnJlc3RXaGVyZSB8fCByZXN0V2hlcmU7XG4gICAgcmVzdE9wdGlvbnMgPSByZXN1bHQucmVzdE9wdGlvbnMgfHwgcmVzdE9wdGlvbnM7XG4gICAgY29uc3QgcXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUsIHJlc3RPcHRpb25zLCBjbGllbnRTREspO1xuICAgIHJldHVybiBxdWVyeS5leGVjdXRlKCk7XG4gIH0pO1xufVxuXG4vLyBnZXQgaXMganVzdCBsaWtlIGZpbmQgYnV0IG9ubHkgcXVlcmllcyBhbiBvYmplY3RJZC5cbmNvbnN0IGdldCA9IChjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgb2JqZWN0SWQsIHJlc3RPcHRpb25zLCBjbGllbnRTREspID0+IHtcbiAgdmFyIHJlc3RXaGVyZSA9IHsgb2JqZWN0SWQgfTtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZ2V0JywgY2xhc3NOYW1lLCBhdXRoKTtcbiAgcmV0dXJuIHRyaWdnZXJzLm1heWJlUnVuUXVlcnlUcmlnZ2VyKHRyaWdnZXJzLlR5cGVzLmJlZm9yZUZpbmQsIGNsYXNzTmFtZSwgcmVzdFdoZXJlLCByZXN0T3B0aW9ucywgY29uZmlnLCBhdXRoLCB0cnVlKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICByZXN0V2hlcmUgPSByZXN1bHQucmVzdFdoZXJlIHx8IHJlc3RXaGVyZTtcbiAgICByZXN0T3B0aW9ucyA9IHJlc3VsdC5yZXN0T3B0aW9ucyB8fCByZXN0T3B0aW9ucztcbiAgICBjb25zdCBxdWVyeSA9IG5ldyBSZXN0UXVlcnkoY29uZmlnLCBhdXRoLCBjbGFzc05hbWUsIHJlc3RXaGVyZSwgcmVzdE9wdGlvbnMsIGNsaWVudFNESyk7XG4gICAgcmV0dXJuIHF1ZXJ5LmV4ZWN1dGUoKTtcbiAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZG9lc24ndCByZXNvbHZlIHRvIGFueSB1c2VmdWwgdmFsdWUuXG5mdW5jdGlvbiBkZWwoY29uZmlnLCBhdXRoLCBjbGFzc05hbWUsIG9iamVjdElkKSB7XG4gIGlmICh0eXBlb2Ygb2JqZWN0SWQgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICdiYWQgb2JqZWN0SWQnKTtcbiAgfVxuXG4gIGlmIChjbGFzc05hbWUgPT09ICdfVXNlcicgJiYgYXV0aC5pc1VuYXV0aGVudGljYXRlZCgpKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlNFU1NJT05fTUlTU0lORyxcbiAgICAgICdJbnN1ZmZpY2llbnQgYXV0aCB0byBkZWxldGUgdXNlcicpO1xuICB9XG5cbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnZGVsZXRlJywgY2xhc3NOYW1lLCBhdXRoKTtcblxuICB2YXIgaW5mbGF0ZWRPYmplY3Q7XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgIGNvbnN0IGhhc1RyaWdnZXJzID0gY2hlY2tUcmlnZ2VycyhjbGFzc05hbWUsIGNvbmZpZywgWydiZWZvcmVEZWxldGUnLCAnYWZ0ZXJEZWxldGUnXSk7XG4gICAgY29uc3QgaGFzTGl2ZVF1ZXJ5ID0gY2hlY2tMaXZlUXVlcnkoY2xhc3NOYW1lLCBjb25maWcpO1xuICAgIGlmIChoYXNUcmlnZ2VycyB8fCBoYXNMaXZlUXVlcnkgfHwgY2xhc3NOYW1lID09ICdfU2Vzc2lvbicpIHtcbiAgICAgIHJldHVybiBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCB7IG9iamVjdElkIH0pXG4gICAgICAgIC5mb3JXcml0ZSgpXG4gICAgICAgIC5leGVjdXRlKClcbiAgICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLnJlc3VsdHMgJiYgcmVzcG9uc2UucmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0UmVzdWx0ID0gcmVzcG9uc2UucmVzdWx0c1swXTtcbiAgICAgICAgICAgIGZpcnN0UmVzdWx0LmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgICAgICAgICAgIGlmIChjbGFzc05hbWUgPT09ICdfU2Vzc2lvbicgJiYgIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgICAgICAgICAgaWYgKCFhdXRoLnVzZXIgfHwgZmlyc3RSZXN1bHQudXNlci5vYmplY3RJZCAhPT0gYXV0aC51c2VyLmlkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTiwgJ0ludmFsaWQgc2Vzc2lvbiB0b2tlbicpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY2FjaGVBZGFwdGVyID0gY29uZmlnLmNhY2hlQ29udHJvbGxlcjtcbiAgICAgICAgICAgIGNhY2hlQWRhcHRlci51c2VyLmRlbChmaXJzdFJlc3VsdC5zZXNzaW9uVG9rZW4pO1xuICAgICAgICAgICAgaW5mbGF0ZWRPYmplY3QgPSBQYXJzZS5PYmplY3QuZnJvbUpTT04oZmlyc3RSZXN1bHQpO1xuICAgICAgICAgICAgLy8gTm90aWZ5IExpdmVRdWVyeSBzZXJ2ZXIgaWYgcG9zc2libGVcbiAgICAgICAgICAgIGNvbmZpZy5saXZlUXVlcnlDb250cm9sbGVyLm9uQWZ0ZXJEZWxldGUoaW5mbGF0ZWRPYmplY3QuY2xhc3NOYW1lLCBpbmZsYXRlZE9iamVjdCk7XG4gICAgICAgICAgICByZXR1cm4gdHJpZ2dlcnMubWF5YmVSdW5UcmlnZ2VyKHRyaWdnZXJzLlR5cGVzLmJlZm9yZURlbGV0ZSwgYXV0aCwgaW5mbGF0ZWRPYmplY3QsIG51bGwsICBjb25maWcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAgICdPYmplY3Qgbm90IGZvdW5kIGZvciBkZWxldGUuJyk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgfSkudGhlbigoKSA9PiB7XG4gICAgaWYgKCFhdXRoLmlzTWFzdGVyKSB7XG4gICAgICByZXR1cm4gYXV0aC5nZXRVc2VyUm9sZXMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfSkudGhlbigoKSA9PiB7XG4gICAgdmFyIG9wdGlvbnMgPSB7fTtcbiAgICBpZiAoIWF1dGguaXNNYXN0ZXIpIHtcbiAgICAgIG9wdGlvbnMuYWNsID0gWycqJ107XG4gICAgICBpZiAoYXV0aC51c2VyKSB7XG4gICAgICAgIG9wdGlvbnMuYWNsLnB1c2goYXV0aC51c2VyLmlkKTtcbiAgICAgICAgb3B0aW9ucy5hY2wgPSBvcHRpb25zLmFjbC5jb25jYXQoYXV0aC51c2VyUm9sZXMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb25maWcuZGF0YWJhc2UuZGVzdHJveShjbGFzc05hbWUsIHtcbiAgICAgIG9iamVjdElkOiBvYmplY3RJZFxuICAgIH0sIG9wdGlvbnMpO1xuICB9KS50aGVuKCgpID0+IHtcbiAgICByZXR1cm4gdHJpZ2dlcnMubWF5YmVSdW5UcmlnZ2VyKHRyaWdnZXJzLlR5cGVzLmFmdGVyRGVsZXRlLCBhdXRoLCBpbmZsYXRlZE9iamVjdCwgbnVsbCwgY29uZmlnKTtcbiAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgaGFuZGxlU2Vzc2lvbk1pc3NpbmdFcnJvcihlcnJvciwgY2xhc3NOYW1lLCBhdXRoKTtcbiAgfSk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIGZvciBhIHtyZXNwb25zZSwgc3RhdHVzLCBsb2NhdGlvbn0gb2JqZWN0LlxuZnVuY3Rpb24gY3JlYXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0T2JqZWN0LCBjbGllbnRTREssIG9wdGlvbnMpIHtcbiAgZW5mb3JjZVJvbGVTZWN1cml0eSgnY3JlYXRlJywgY2xhc3NOYW1lLCBhdXRoKTtcbiAgdmFyIHdyaXRlID0gbmV3IFJlc3RXcml0ZShjb25maWcsIGF1dGgsIGNsYXNzTmFtZSwgbnVsbCwgcmVzdE9iamVjdCwgbnVsbCwgY2xpZW50U0RLLCBvcHRpb25zKTtcbiAgcmV0dXJuIHdyaXRlLmV4ZWN1dGUoKTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBjb250YWlucyB0aGUgZmllbGRzIG9mIHRoZSB1cGRhdGUgdGhhdCB0aGVcbi8vIFJFU1QgQVBJIGlzIHN1cHBvc2VkIHRvIHJldHVybi5cbi8vIFVzdWFsbHksIHRoaXMgaXMganVzdCB1cGRhdGVkQXQuXG5mdW5jdGlvbiB1cGRhdGUoY29uZmlnLCBhdXRoLCBjbGFzc05hbWUsIHJlc3RXaGVyZSwgcmVzdE9iamVjdCwgY2xpZW50U0RLKSB7XG4gIGVuZm9yY2VSb2xlU2VjdXJpdHkoJ3VwZGF0ZScsIGNsYXNzTmFtZSwgYXV0aCk7XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgIGNvbnN0IGhhc1RyaWdnZXJzID0gY2hlY2tUcmlnZ2VycyhjbGFzc05hbWUsIGNvbmZpZywgWydiZWZvcmVTYXZlJywgJ2FmdGVyU2F2ZSddKTtcbiAgICBjb25zdCBoYXNMaXZlUXVlcnkgPSBjaGVja0xpdmVRdWVyeShjbGFzc05hbWUsIGNvbmZpZyk7XG4gICAgaWYgKGhhc1RyaWdnZXJzIHx8IGhhc0xpdmVRdWVyeSkge1xuICAgICAgLy8gRG8gbm90IHVzZSBmaW5kLCBhcyBpdCBydW5zIHRoZSBiZWZvcmUgZmluZHNcbiAgICAgIHJldHVybiBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUpXG4gICAgICAgIC5mb3JXcml0ZSgpXG4gICAgICAgIC5leGVjdXRlKCk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xuICB9KS50aGVuKCh7IHJlc3VsdHMgfSkgPT4ge1xuICAgIHZhciBvcmlnaW5hbFJlc3RPYmplY3Q7XG4gICAgaWYgKHJlc3VsdHMgJiYgcmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgIG9yaWdpbmFsUmVzdE9iamVjdCA9IHJlc3VsdHNbMF07XG4gICAgfVxuICAgIHJldHVybiBuZXcgUmVzdFdyaXRlKGNvbmZpZywgYXV0aCwgY2xhc3NOYW1lLCByZXN0V2hlcmUsIHJlc3RPYmplY3QsIG9yaWdpbmFsUmVzdE9iamVjdCwgY2xpZW50U0RLKVxuICAgICAgLmV4ZWN1dGUoKTtcbiAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgaGFuZGxlU2Vzc2lvbk1pc3NpbmdFcnJvcihlcnJvciwgY2xhc3NOYW1lLCBhdXRoKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVNlc3Npb25NaXNzaW5nRXJyb3IoZXJyb3IsIGNsYXNzTmFtZSkge1xuICAvLyBJZiB3ZSdyZSB0cnlpbmcgdG8gdXBkYXRlIGEgdXNlciB3aXRob3V0IC8gd2l0aCBiYWQgc2Vzc2lvbiB0b2tlblxuICBpZiAoY2xhc3NOYW1lID09PSAnX1VzZXInXG4gICAgICAmJiBlcnJvci5jb2RlID09PSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlNFU1NJT05fTUlTU0lORywgJ0luc3VmZmljaWVudCBhdXRoLicpO1xuICB9XG4gIHRocm93IGVycm9yO1xufVxuXG5jb25zdCBjbGFzc2VzV2l0aE1hc3Rlck9ubHlBY2Nlc3MgPSBbJ19Kb2JTdGF0dXMnLCAnX1B1c2hTdGF0dXMnLCAnX0hvb2tzJywgJ19HbG9iYWxDb25maWcnLCAnX0pvYlNjaGVkdWxlJ107XG4vLyBEaXNhbGxvd2luZyBhY2Nlc3MgdG8gdGhlIF9Sb2xlIGNvbGxlY3Rpb24gZXhjZXB0IGJ5IG1hc3RlciBrZXlcbmZ1bmN0aW9uIGVuZm9yY2VSb2xlU2VjdXJpdHkobWV0aG9kLCBjbGFzc05hbWUsIGF1dGgpIHtcbiAgaWYgKGNsYXNzTmFtZSA9PT0gJ19JbnN0YWxsYXRpb24nICYmICFhdXRoLmlzTWFzdGVyKSB7XG4gICAgaWYgKG1ldGhvZCA9PT0gJ2RlbGV0ZScgfHwgbWV0aG9kID09PSAnZmluZCcpIHtcbiAgICAgIGNvbnN0IGVycm9yID0gYENsaWVudHMgYXJlbid0IGFsbG93ZWQgdG8gcGVyZm9ybSB0aGUgJHttZXRob2R9IG9wZXJhdGlvbiBvbiB0aGUgaW5zdGFsbGF0aW9uIGNvbGxlY3Rpb24uYFxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sIGVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvL2FsbCB2b2xhdGlsZUNsYXNzZXMgYXJlIG1hc3RlcktleSBvbmx5XG4gIGlmKGNsYXNzZXNXaXRoTWFzdGVyT25seUFjY2Vzcy5pbmRleE9mKGNsYXNzTmFtZSkgPj0gMCAmJiAhYXV0aC5pc01hc3Rlcil7XG4gICAgY29uc3QgZXJyb3IgPSBgQ2xpZW50cyBhcmVuJ3QgYWxsb3dlZCB0byBwZXJmb3JtIHRoZSAke21ldGhvZH0gb3BlcmF0aW9uIG9uIHRoZSAke2NsYXNzTmFtZX0gY29sbGVjdGlvbi5gXG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sIGVycm9yKTtcbiAgfVxuXG4gIC8vIHJlYWRPbmx5IG1hc3RlcktleSBpcyBub3QgYWxsb3dlZFxuICBpZiAoYXV0aC5pc1JlYWRPbmx5ICYmIChtZXRob2QgPT09ICdkZWxldGUnIHx8IG1ldGhvZCA9PT0gJ2NyZWF0ZScgfHwgbWV0aG9kID09PSAndXBkYXRlJykpIHtcbiAgICBjb25zdCBlcnJvciA9IGByZWFkLW9ubHkgbWFzdGVyS2V5IGlzbid0IGFsbG93ZWQgdG8gcGVyZm9ybSB0aGUgJHttZXRob2R9IG9wZXJhdGlvbi5gXG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sIGVycm9yKTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgY3JlYXRlLFxuICBkZWwsXG4gIGZpbmQsXG4gIGdldCxcbiAgdXBkYXRlXG59O1xuIl19 \ No newline at end of file diff --git a/lib/triggers.js b/lib/triggers.js index 2c32e35ae2..8fc535ff07 100644 --- a/lib/triggers.js +++ b/lib/triggers.js @@ -252,6 +252,9 @@ function getResponseObject(request, resolve, reject) { }, error: function (code, message) { if (!message) { + if (code instanceof _node2.default.Error) { + return reject(code); + } message = code; code = _node2.default.Error.SCRIPT_FAILED; } @@ -468,4 +471,5 @@ function runLiveQueryEventHandlers(data, applicationId = _node2.default.applicat return; } _triggerStore[applicationId].LiveQuery.forEach(handler => handler(data)); -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy90cmlnZ2Vycy5qcyJdLCJuYW1lcyI6WyJhZGRGdW5jdGlvbiIsImFkZEpvYiIsImFkZFRyaWdnZXIiLCJhZGRMaXZlUXVlcnlFdmVudEhhbmRsZXIiLCJyZW1vdmVGdW5jdGlvbiIsInJlbW92ZVRyaWdnZXIiLCJfdW5yZWdpc3RlckFsbCIsImdldFRyaWdnZXIiLCJ0cmlnZ2VyRXhpc3RzIiwiZ2V0RnVuY3Rpb24iLCJnZXRKb2IiLCJnZXRKb2JzIiwiZ2V0VmFsaWRhdG9yIiwiZ2V0UmVxdWVzdE9iamVjdCIsImdldFJlcXVlc3RRdWVyeU9iamVjdCIsImdldFJlc3BvbnNlT2JqZWN0IiwibWF5YmVSdW5BZnRlckZpbmRUcmlnZ2VyIiwibWF5YmVSdW5RdWVyeVRyaWdnZXIiLCJtYXliZVJ1blRyaWdnZXIiLCJpbmZsYXRlIiwicnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyIsIlR5cGVzIiwiYmVmb3JlU2F2ZSIsImFmdGVyU2F2ZSIsImJlZm9yZURlbGV0ZSIsImFmdGVyRGVsZXRlIiwiYmVmb3JlRmluZCIsImFmdGVyRmluZCIsImJhc2VTdG9yZSIsIlZhbGlkYXRvcnMiLCJGdW5jdGlvbnMiLCJKb2JzIiwiTGl2ZVF1ZXJ5IiwiVHJpZ2dlcnMiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwiYmFzZSIsImtleSIsImZyZWV6ZSIsInZhbGlkYXRlQ2xhc3NOYW1lRm9yVHJpZ2dlcnMiLCJjbGFzc05hbWUiLCJ0eXBlIiwicmVzdHJpY3RlZENsYXNzTmFtZXMiLCJpbmRleE9mIiwiX3RyaWdnZXJTdG9yZSIsImZ1bmN0aW9uTmFtZSIsImhhbmRsZXIiLCJ2YWxpZGF0aW9uSGFuZGxlciIsImFwcGxpY2F0aW9uSWQiLCJQYXJzZSIsImpvYk5hbWUiLCJwdXNoIiwiZm9yRWFjaCIsImFwcElkIiwidHJpZ2dlclR5cGUiLCJtYW5hZ2VyIiwidW5kZWZpbmVkIiwiYXV0aCIsInBhcnNlT2JqZWN0Iiwib3JpZ2luYWxQYXJzZU9iamVjdCIsImNvbmZpZyIsInJlcXVlc3QiLCJ0cmlnZ2VyTmFtZSIsIm9iamVjdCIsIm1hc3RlciIsImxvZyIsImxvZ2dlckNvbnRyb2xsZXIiLCJoZWFkZXJzIiwiaXAiLCJvcmlnaW5hbCIsImlzTWFzdGVyIiwidXNlciIsImluc3RhbGxhdGlvbklkIiwicXVlcnkiLCJjb3VudCIsImlzR2V0IiwicmVzb2x2ZSIsInJlamVjdCIsInN1Y2Nlc3MiLCJyZXNwb25zZSIsIm9iamVjdHMiLCJtYXAiLCJ0b0pTT04iLCJlcXVhbHMiLCJfZ2V0U2F2ZUpTT04iLCJlcnJvciIsImNvZGUiLCJtZXNzYWdlIiwiRXJyb3IiLCJTQ1JJUFRfRkFJTEVEIiwic2NyaXB0RXJyb3IiLCJ1c2VySWRGb3JMb2ciLCJpZCIsImxvZ1RyaWdnZXJBZnRlckhvb2siLCJpbnB1dCIsImNsZWFuSW5wdXQiLCJsb2dnZXIiLCJ0cnVuY2F0ZUxvZ01lc3NhZ2UiLCJKU09OIiwic3RyaW5naWZ5IiwiaW5mbyIsImxvZ1RyaWdnZXJTdWNjZXNzQmVmb3JlSG9vayIsInJlc3VsdCIsImNsZWFuUmVzdWx0IiwibG9nVHJpZ2dlckVycm9yQmVmb3JlSG9vayIsIlByb21pc2UiLCJ0cmlnZ2VyIiwiZnJvbUpTT04iLCJ0cmlnZ2VyUHJvbWlzZSIsInRoZW4iLCJwcm9taXNlUmVzdWx0cyIsInJlc3VsdHMiLCJyZXN0V2hlcmUiLCJyZXN0T3B0aW9ucyIsInBhcnNlUXVlcnkiLCJRdWVyeSIsIl93aGVyZSIsImluY2x1ZGUiLCJsZW5ndGgiLCJfaW5jbHVkZSIsInNwbGl0Iiwic2tpcCIsIl9za2lwIiwibGltaXQiLCJfbGltaXQiLCJyZXF1ZXN0T2JqZWN0IiwicXVlcnlSZXN1bHQiLCJqc29uUXVlcnkiLCJ3aGVyZSIsIm9yZGVyIiwicmVhZFByZWZlcmVuY2UiLCJpbmNsdWRlUmVhZFByZWZlcmVuY2UiLCJzdWJxdWVyeVJlYWRQcmVmZXJlbmNlIiwiZXJyIiwiamF2YXNjcmlwdEtleSIsIm1hc3RlcktleSIsImRhdGEiLCJyZXN0T2JqZWN0IiwiY29w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QUFaLEVBQXhELEVBQThFekIsSUFBOUU7QUFDQSxVQUFHbUQsa0JBQWtCLE9BQU9BLGVBQWVDLElBQXRCLEtBQStCLFVBQXBELEVBQWdFO0FBQzlELGVBQU9ELGVBQWVDLElBQWYsQ0FBb0JqQyxPQUFwQixFQUE2QkEsT0FBN0IsQ0FBUDtBQUNELE9BRkQsTUFHSztBQUNILGVBQU9BLFNBQVA7QUFDRDtBQUNGO0FBQ0YsR0FsQ00sQ0FBUDtBQW1DRDs7QUFFRDtBQUNBO0FBQ08sU0FBUzFELE9BQVQsQ0FBaUJzSCxJQUFqQixFQUF1QkMsVUFBdkIsRUFBbUM7QUFDeEMsTUFBSUMsT0FBTyxPQUFPRixJQUFQLElBQWUsUUFBZixHQUEwQkEsSUFBMUIsR0FBaUMsRUFBQ2hHLFdBQVdnRyxJQUFaLEVBQTVDO0FBQ0EsT0FBSyxJQUFJbkcsR0FBVCxJQUFnQm9HLFVBQWhCLEVBQTRCO0FBQzFCQyxTQUFLckcsR0FBTCxJQUFZb0csV0FBV3BHLEdBQVgsQ0FBWjtBQUNEO0FBQ0QsU0FBT1ksZUFBTWhCLE1BQU4sQ0FBYTBFLFFBQWIsQ0FBc0IrQixJQUF0QixDQUFQO0FBQ0Q7O0FBRU0sU0FBU3ZILHlCQUFULENBQW1DcUgsSUFBbkMsRUFBeUN4RixnQkFBZ0JDLGVBQU1ELGFBQS9ELEVBQThFO0FBQ25GLE1BQUksQ0FBQ0osYUFBRCxJQUFrQixDQUFDQSxjQUFjSSxhQUFkLENBQW5CLElBQW1ELENBQUNKLGNBQWNJLGFBQWQsRUFBNkJqQixTQUFyRixFQUFnRztBQUFFO0FBQVM7QUFDM0dhLGdCQUFjSSxhQUFkLEVBQTZCakIsU0FBN0IsQ0FBdUNxQixPQUF2QyxDQUFnRE4sT0FBRCxJQUFhQSxRQUFRMEYsSUFBUixDQUE1RDtBQUNEIiwiZmlsZSI6InRyaWdnZXJzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdHJpZ2dlcnMuanNcbmltcG9ydCBQYXJzZSAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcblxuZXhwb3J0IGNvbnN0IFR5cGVzID0ge1xuICBiZWZvcmVTYXZlOiAnYmVmb3JlU2F2ZScsXG4gIGFmdGVyU2F2ZTogJ2FmdGVyU2F2ZScsXG4gIGJlZm9yZURlbGV0ZTogJ2JlZm9yZURlbGV0ZScsXG4gIGFmdGVyRGVsZXRlOiAnYWZ0ZXJEZWxldGUnLFxuICBiZWZvcmVGaW5kOiAnYmVmb3JlRmluZCcsXG4gIGFmdGVyRmluZDogJ2FmdGVyRmluZCdcbn07XG5cbmNvbnN0IGJhc2VTdG9yZSA9IGZ1bmN0aW9uKCkge1xuICBjb25zdCBWYWxpZGF0b3JzID0ge307XG4gIGNvbnN0IEZ1bmN0aW9ucyA9IHt9O1xuICBjb25zdCBKb2JzID0ge307XG4gIGNvbnN0IExpdmVRdWVyeSA9IFtdO1xuICBjb25zdCBUcmlnZ2VycyA9IE9iamVjdC5rZXlzKFR5cGVzKS5yZWR1Y2UoZnVuY3Rpb24oYmFzZSwga2V5KXtcbiAgICBiYXNlW2tleV0gPSB7fTtcbiAgICByZXR1cm4gYmFzZTtcbiAgfSwge30pO1xuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKHtcbiAgICBGdW5jdGlvbnMsXG4gICAgSm9icyxcbiAgICBWYWxpZGF0b3JzLFxuICAgIFRyaWdnZXJzLFxuICAgIExpdmVRdWVyeSxcbiAgfSk7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZUNsYXNzTmFtZUZvclRyaWdnZXJzKGNsYXNzTmFtZSwgdHlwZSkge1xuICBjb25zdCByZXN0cmljdGVkQ2xhc3NOYW1lcyA9IFsgJ19TZXNzaW9uJyBdO1xuICBpZiAocmVzdHJpY3RlZENsYXNzTmFtZXMuaW5kZXhPZihjbGFzc05hbWUpICE9IC0xKSB7XG4gICAgdGhyb3cgYFRyaWdnZXJzIGFyZSBub3Qgc3VwcG9ydGVkIGZvciAke2NsYXNzTmFtZX0gY2xhc3MuYDtcbiAgfVxuICBpZiAodHlwZSA9PSBUeXBlcy5iZWZvcmVTYXZlICYmIGNsYXNzTmFtZSA9PT0gJ19QdXNoU3RhdHVzJykge1xuICAgIC8vIF9QdXNoU3RhdHVzIHVzZXMgdW5kb2N1bWVudGVkIG5lc3RlZCBrZXkgaW5jcmVtZW50IG9wc1xuICAgIC8vIGFsbG93aW5nIGJlZm9yZVNhdmUgd291bGQgbWVzcyB1cCB0aGUgb2JqZWN0cyBiaWcgdGltZVxuICAgIC8vIFRPRE86IEFsbG93IHByb3BlciBkb2N1bWVudGVkIHdheSBvZiB1c2luZyBuZXN0ZWQgaW5jcmVtZW50IG9wc1xuICAgIHRocm93ICdPbmx5IGFmdGVyU2F2ZSBpcyBhbGxvd2VkIG9uIF9QdXNoU3RhdHVzJztcbiAgfVxuICByZXR1cm4gY2xhc3NOYW1lO1xufVxuXG5jb25zdCBfdHJpZ2dlclN0b3JlID0ge307XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRGdW5jdGlvbihmdW5jdGlvbk5hbWUsIGhhbmRsZXIsIHZhbGlkYXRpb25IYW5kbGVyLCBhcHBsaWNhdGlvbklkKSB7XG4gIGFwcGxpY2F0aW9uSWQgPSBhcHBsaWNhdGlvbklkIHx8IFBhcnNlLmFwcGxpY2F0aW9uSWQ7XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0gPSAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXSB8fCBiYXNlU3RvcmUoKTtcbiAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXS5GdW5jdGlvbnNbZnVuY3Rpb25OYW1lXSA9IGhhbmRsZXI7XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0uVmFsaWRhdG9yc1tmdW5jdGlvbk5hbWVdID0gdmFsaWRhdGlvbkhhbmRsZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRKb2Ioam9iTmFtZSwgaGFuZGxlciwgYXBwbGljYXRpb25JZCkge1xuICBhcHBsaWNhdGlvbklkID0gYXBwbGljYXRpb25JZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICBfdHJpZ2dlclN0b3JlW2FwcGxpY2F0aW9uSWRdID0gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0gfHwgYmFzZVN0b3JlKCk7XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0uSm9ic1tqb2JOYW1lXSA9IGhhbmRsZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRUcmlnZ2VyKHR5cGUsIGNsYXNzTmFtZSwgaGFuZGxlciwgYXBwbGljYXRpb25JZCkge1xuICB2YWxpZGF0ZUNsYXNzTmFtZUZvclRyaWdnZXJzKGNsYXNzTmFtZSwgdHlwZSk7XG4gIGFwcGxpY2F0aW9uSWQgPSBhcHBsaWNhdGlvbklkIHx8IFBhcnNlLmFwcGxpY2F0aW9uSWQ7XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0gPSAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXSB8fCBiYXNlU3RvcmUoKTtcbiAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXS5UcmlnZ2Vyc1t0eXBlXVtjbGFzc05hbWVdID0gaGFuZGxlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZExpdmVRdWVyeUV2ZW50SGFuZGxlcihoYW5kbGVyLCBhcHBsaWNhdGlvbklkKSB7XG4gIGFwcGxpY2F0aW9uSWQgPSBhcHBsaWNhdGlvbklkIHx8IFBhcnNlLmFwcGxpY2F0aW9uSWQ7XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0gPSAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXSB8fCBiYXNlU3RvcmUoKTtcbiAgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXS5MaXZlUXVlcnkucHVzaChoYW5kbGVyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgYXBwbGljYXRpb25JZCkge1xuICBhcHBsaWNhdGlvbklkID0gYXBwbGljYXRpb25JZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICBkZWxldGUgX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXS5GdW5jdGlvbnNbZnVuY3Rpb25OYW1lXVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlVHJpZ2dlcih0eXBlLCBjbGFzc05hbWUsIGFwcGxpY2F0aW9uSWQpIHtcbiAgYXBwbGljYXRpb25JZCA9IGFwcGxpY2F0aW9uSWQgfHwgUGFyc2UuYXBwbGljYXRpb25JZDtcbiAgZGVsZXRlIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0uVHJpZ2dlcnNbdHlwZV1bY2xhc3NOYW1lXVxufVxuXG5leHBvcnQgZnVuY3Rpb24gX3VucmVnaXN0ZXJBbGwoKSB7XG4gIE9iamVjdC5rZXlzKF90cmlnZ2VyU3RvcmUpLmZvckVhY2goYXBwSWQgPT4gZGVsZXRlIF90cmlnZ2VyU3RvcmVbYXBwSWRdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRyaWdnZXIoY2xhc3NOYW1lLCB0cmlnZ2VyVHlwZSwgYXBwbGljYXRpb25JZCkge1xuICBpZiAoIWFwcGxpY2F0aW9uSWQpIHtcbiAgICB0aHJvdyBcIk1pc3NpbmcgQXBwbGljYXRpb25JRFwiO1xuICB9XG4gIHZhciBtYW5hZ2VyID0gX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXVxuICBpZiAobWFuYWdlclxuICAgICYmIG1hbmFnZXIuVHJpZ2dlcnNcbiAgICAmJiBtYW5hZ2VyLlRyaWdnZXJzW3RyaWdnZXJUeXBlXVxuICAgICYmIG1hbmFnZXIuVHJpZ2dlcnNbdHJpZ2dlclR5cGVdW2NsYXNzTmFtZV0pIHtcbiAgICByZXR1cm4gbWFuYWdlci5UcmlnZ2Vyc1t0cmlnZ2VyVHlwZV1bY2xhc3NOYW1lXTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJpZ2dlckV4aXN0cyhjbGFzc05hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBhcHBsaWNhdGlvbklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIChnZXRUcmlnZ2VyKGNsYXNzTmFtZSwgdHlwZSwgYXBwbGljYXRpb25JZCkgIT0gdW5kZWZpbmVkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZ1bmN0aW9uKGZ1bmN0aW9uTmFtZSwgYXBwbGljYXRpb25JZCkge1xuICB2YXIgbWFuYWdlciA9IF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF07XG4gIGlmIChtYW5hZ2VyICYmIG1hbmFnZXIuRnVuY3Rpb25zKSB7XG4gICAgcmV0dXJuIG1hbmFnZXIuRnVuY3Rpb25zW2Z1bmN0aW9uTmFtZV07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEpvYihqb2JOYW1lLCBhcHBsaWNhdGlvbklkKSB7XG4gIHZhciBtYW5hZ2VyID0gX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXTtcbiAgaWYgKG1hbmFnZXIgJiYgbWFuYWdlci5Kb2JzKSB7XG4gICAgcmV0dXJuIG1hbmFnZXIuSm9ic1tqb2JOYW1lXTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Sm9icyhhcHBsaWNhdGlvbklkKSB7XG4gIHZhciBtYW5hZ2VyID0gX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXTtcbiAgaWYgKG1hbmFnZXIgJiYgbWFuYWdlci5Kb2JzKSB7XG4gICAgcmV0dXJuIG1hbmFnZXIuSm9icztcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWYWxpZGF0b3IoZnVuY3Rpb25OYW1lLCBhcHBsaWNhdGlvbklkKSB7XG4gIHZhciBtYW5hZ2VyID0gX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXTtcbiAgaWYgKG1hbmFnZXIgJiYgbWFuYWdlci5WYWxpZGF0b3JzKSB7XG4gICAgcmV0dXJuIG1hbmFnZXIuVmFsaWRhdG9yc1tmdW5jdGlvbk5hbWVdO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXF1ZXN0T2JqZWN0KHRyaWdnZXJUeXBlLCBhdXRoLCBwYXJzZU9iamVjdCwgb3JpZ2luYWxQYXJzZU9iamVjdCwgY29uZmlnKSB7XG4gIHZhciByZXF1ZXN0ID0ge1xuICAgIHRyaWdnZXJOYW1lOiB0cmlnZ2VyVHlwZSxcbiAgICBvYmplY3Q6IHBhcnNlT2JqZWN0LFxuICAgIG1hc3RlcjogZmFsc2UsXG4gICAgbG9nOiBjb25maWcubG9nZ2VyQ29udHJvbGxlcixcbiAgICBoZWFkZXJzOiBjb25maWcuaGVhZGVycyxcbiAgICBpcDogY29uZmlnLmlwLFxuICB9O1xuXG4gIGlmIChvcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgcmVxdWVzdC5vcmlnaW5hbCA9IG9yaWdpbmFsUGFyc2VPYmplY3Q7XG4gIH1cblxuICBpZiAoIWF1dGgpIHtcbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuICBpZiAoYXV0aC5pc01hc3Rlcikge1xuICAgIHJlcXVlc3RbJ21hc3RlciddID0gdHJ1ZTtcbiAgfVxuICBpZiAoYXV0aC51c2VyKSB7XG4gICAgcmVxdWVzdFsndXNlciddID0gYXV0aC51c2VyO1xuICB9XG4gIGlmIChhdXRoLmluc3RhbGxhdGlvbklkKSB7XG4gICAgcmVxdWVzdFsnaW5zdGFsbGF0aW9uSWQnXSA9IGF1dGguaW5zdGFsbGF0aW9uSWQ7XG4gIH1cbiAgcmV0dXJuIHJlcXVlc3Q7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXF1ZXN0UXVlcnlPYmplY3QodHJpZ2dlclR5cGUsIGF1dGgsIHF1ZXJ5LCBjb3VudCwgY29uZmlnLCBpc0dldCkge1xuICBpc0dldCA9ICEhaXNHZXQ7XG5cbiAgdmFyIHJlcXVlc3QgPSB7XG4gICAgdHJpZ2dlck5hbWU6IHRyaWdnZXJUeXBlLFxuICAgIHF1ZXJ5LFxuICAgIG1hc3RlcjogZmFsc2UsXG4gICAgY291bnQsXG4gICAgbG9nOiBjb25maWcubG9nZ2VyQ29udHJvbGxlcixcbiAgICBpc0dldCxcbiAgICBoZWFkZXJzOiBjb25maWcuaGVhZGVycyxcbiAgICBpcDogY29uZmlnLmlwLFxuICB9O1xuXG4gIGlmICghYXV0aCkge1xuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG4gIGlmIChhdXRoLmlzTWFzdGVyKSB7XG4gICAgcmVxdWVzdFsnbWFzdGVyJ10gPSB0cnVlO1xuICB9XG4gIGlmIChhdXRoLnVzZXIpIHtcbiAgICByZXF1ZXN0Wyd1c2VyJ10gPSBhdXRoLnVzZXI7XG4gIH1cbiAgaWYgKGF1dGguaW5zdGFsbGF0aW9uSWQpIHtcbiAgICByZXF1ZXN0WydpbnN0YWxsYXRpb25JZCddID0gYXV0aC5pbnN0YWxsYXRpb25JZDtcbiAgfVxuICByZXR1cm4gcmVxdWVzdDtcbn1cblxuLy8gQ3JlYXRlcyB0aGUgcmVzcG9uc2Ugb2JqZWN0LCBhbmQgdXNlcyB0aGUgcmVxdWVzdCBvYmplY3QgdG8gcGFzcyBkYXRhXG4vLyBUaGUgQVBJIHdpbGwgY2FsbCB0aGlzIHdpdGggUkVTVCBBUEkgZm9ybWF0dGVkIG9iamVjdHMsIHRoaXMgd2lsbFxuLy8gdHJhbnNmb3JtIHRoZW0gdG8gUGFyc2UuT2JqZWN0IGluc3RhbmNlcyBleHBlY3RlZCBieSBDbG91ZCBDb2RlLlxuLy8gQW55IGNoYW5nZXMgbWFkZSB0byB0aGUgb2JqZWN0IGluIGEgYmVmb3JlU2F2ZSB3aWxsIGJlIGluY2x1ZGVkLlxuZXhwb3J0IGZ1bmN0aW9uIGdldFJlc3BvbnNlT2JqZWN0KHJlcXVlc3QsIHJlc29sdmUsIHJlamVjdCkge1xuICByZXR1cm4ge1xuICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICBpZiAocmVxdWVzdC50cmlnZ2VyTmFtZSA9PT0gVHlwZXMuYWZ0ZXJGaW5kKSB7XG4gICAgICAgIGlmKCFyZXNwb25zZSl7XG4gICAgICAgICAgcmVzcG9uc2UgPSByZXF1ZXN0Lm9iamVjdHM7XG4gICAgICAgIH1cbiAgICAgICAgcmVzcG9uc2UgPSByZXNwb25zZS5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICByZXR1cm4gb2JqZWN0LnRvSlNPTigpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHRoZSBKU09OIHJlc3BvbnNlXG4gICAgICBpZiAocmVzcG9uc2UgJiYgIXJlcXVlc3Qub2JqZWN0LmVxdWFscyhyZXNwb25zZSlcbiAgICAgICAgICAmJiByZXF1ZXN0LnRyaWdnZXJOYW1lID09PSBUeXBlcy5iZWZvcmVTYXZlKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlKHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICBpZiAocmVxdWVzdC50cmlnZ2VyTmFtZSA9PT0gVHlwZXMuYmVmb3JlU2F2ZSkge1xuICAgICAgICByZXNwb25zZVsnb2JqZWN0J10gPSByZXF1ZXN0Lm9iamVjdC5fZ2V0U2F2ZUpTT04oKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXNvbHZlKHJlc3BvbnNlKTtcbiAgICB9LFxuICAgIGVycm9yOiBmdW5jdGlvbihjb2RlLCBtZXNzYWdlKSB7XG4gICAgICBpZiAoIW1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKGNvZGUgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgICAgICAgIHJldHVybiByZWplY3QoY29kZSlcbiAgICAgICAgfVxuICAgICAgICBtZXNzYWdlID0gY29kZTtcbiAgICAgICAgY29kZSA9IFBhcnNlLkVycm9yLlNDUklQVF9GQUlMRUQ7XG4gICAgICB9XG4gICAgICB2YXIgc2NyaXB0RXJyb3IgPSBuZXcgUGFyc2UuRXJyb3IoY29kZSwgbWVzc2FnZSk7XG4gICAgICByZXR1cm4gcmVqZWN0KHNjcmlwdEVycm9yKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gdXNlcklkRm9yTG9nKGF1dGgpIHtcbiAgcmV0dXJuIChhdXRoICYmIGF1dGgudXNlcikgPyBhdXRoLnVzZXIuaWQgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGxvZ1RyaWdnZXJBZnRlckhvb2sodHJpZ2dlclR5cGUsIGNsYXNzTmFtZSwgaW5wdXQsIGF1dGgpIHtcbiAgY29uc3QgY2xlYW5JbnB1dCA9IGxvZ2dlci50cnVuY2F0ZUxvZ01lc3NhZ2UoSlNPTi5zdHJpbmdpZnkoaW5wdXQpKTtcbiAgbG9nZ2VyLmluZm8oYCR7dHJpZ2dlclR5cGV9IHRyaWdnZXJlZCBmb3IgJHtjbGFzc05hbWV9IGZvciB1c2VyICR7dXNlcklkRm9yTG9nKGF1dGgpfTpcXG4gIElucHV0OiAke2NsZWFuSW5wdXR9YCwge1xuICAgIGNsYXNzTmFtZSxcbiAgICB0cmlnZ2VyVHlwZSxcbiAgICB1c2VyOiB1c2VySWRGb3JMb2coYXV0aClcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGxvZ1RyaWdnZXJTdWNjZXNzQmVmb3JlSG9vayh0cmlnZ2VyVHlwZSwgY2xhc3NOYW1lLCBpbnB1dCwgcmVzdWx0LCBhdXRoKSB7XG4gIGNvbnN0IGNsZWFuSW5wdXQgPSBsb2dnZXIudHJ1bmNhdGVMb2dNZXNzYWdlKEpTT04uc3RyaW5naWZ5KGlucHV0KSk7XG4gIGNvbnN0IGNsZWFuUmVzdWx0ID0gbG9nZ2VyLnRydW5jYXRlTG9nTWVzc2FnZShKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgbG9nZ2VyLmluZm8oYCR7dHJpZ2dlclR5cGV9IHRyaWdnZXJlZCBmb3IgJHtjbGFzc05hbWV9IGZvciB1c2VyICR7dXNlcklkRm9yTG9nKGF1dGgpfTpcXG4gIElucHV0OiAke2NsZWFuSW5wdXR9XFxuICBSZXN1bHQ6ICR7Y2xlYW5SZXN1bHR9YCwge1xuICAgIGNsYXNzTmFtZSxcbiAgICB0cmlnZ2VyVHlwZSxcbiAgICB1c2VyOiB1c2VySWRGb3JMb2coYXV0aClcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGxvZ1RyaWdnZXJFcnJvckJlZm9yZUhvb2sodHJpZ2dlclR5cGUsIGNsYXNzTmFtZSwgaW5wdXQsIGF1dGgsIGVycm9yKSB7XG4gIGNvbnN0IGNsZWFuSW5wdXQgPSBsb2dnZXIudHJ1bmNhdGVMb2dNZXNzYWdlKEpTT04uc3RyaW5naWZ5KGlucHV0KSk7XG4gIGxvZ2dlci5lcnJvcihgJHt0cmlnZ2VyVHlwZX0gZmFpbGVkIGZvciAke2NsYXNzTmFtZX0gZm9yIHVzZXIgJHt1c2VySWRGb3JMb2coYXV0aCl9OlxcbiAgSW5wdXQ6ICR7Y2xlYW5JbnB1dH1cXG4gIEVycm9yOiAke0pTT04uc3RyaW5naWZ5KGVycm9yKX1gLCB7XG4gICAgY2xhc3NOYW1lLFxuICAgIHRyaWdnZXJUeXBlLFxuICAgIGVycm9yLFxuICAgIHVzZXI6IHVzZXJJZEZvckxvZyhhdXRoKVxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1heWJlUnVuQWZ0ZXJGaW5kVHJpZ2dlcih0cmlnZ2VyVHlwZSwgYXV0aCwgY2xhc3NOYW1lLCBvYmplY3RzLCBjb25maWcpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCB0cmlnZ2VyID0gZ2V0VHJpZ2dlcihjbGFzc05hbWUsIHRyaWdnZXJUeXBlLCBjb25maWcuYXBwbGljYXRpb25JZCk7XG4gICAgaWYgKCF0cmlnZ2VyKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgIH1cbiAgICBjb25zdCByZXF1ZXN0ID0gZ2V0UmVxdWVzdE9iamVjdCh0cmlnZ2VyVHlwZSwgYXV0aCwgbnVsbCwgbnVsbCwgY29uZmlnKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGdldFJlc3BvbnNlT2JqZWN0KHJlcXVlc3QsXG4gICAgICBvYmplY3QgPT4ge1xuICAgICAgICByZXNvbHZlKG9iamVjdCk7XG4gICAgICB9LFxuICAgICAgZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgbG9nVHJpZ2dlclN1Y2Nlc3NCZWZvcmVIb29rKHRyaWdnZXJUeXBlLCBjbGFzc05hbWUsICdBZnRlckZpbmQnLCBKU09OLnN0cmluZ2lmeShvYmplY3RzKSwgYXV0aCk7XG4gICAgcmVxdWVzdC5vYmplY3RzID0gb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgIC8vc2V0dGluZyB0aGUgY2xhc3MgbmFtZSB0byB0cmFuc2Zvcm0gaW50byBwYXJzZSBvYmplY3RcbiAgICAgIG9iamVjdC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgICByZXR1cm4gUGFyc2UuT2JqZWN0LmZyb21KU09OKG9iamVjdCk7XG4gICAgfSk7XG4gICAgY29uc3QgdHJpZ2dlclByb21pc2UgPSB0cmlnZ2VyKHJlcXVlc3QsIHJlc3BvbnNlKTtcbiAgICBpZiAodHJpZ2dlclByb21pc2UgJiYgdHlwZW9mIHRyaWdnZXJQcm9taXNlLnRoZW4gPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgcmV0dXJuIHRyaWdnZXJQcm9taXNlLnRoZW4ocHJvbWlzZVJlc3VsdHMgPT4ge1xuICAgICAgICBpZihwcm9taXNlUmVzdWx0cykge1xuICAgICAgICAgIHJlc29sdmUocHJvbWlzZVJlc3VsdHMpO1xuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVELCBcIkFmdGVyRmluZCBleHBlY3QgcmVzdWx0cyB0byBiZSByZXR1cm5lZCBpbiB0aGUgcHJvbWlzZVwiKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSkudGhlbigocmVzdWx0cykgPT4ge1xuICAgIGxvZ1RyaWdnZXJBZnRlckhvb2sodHJpZ2dlclR5cGUsIGNsYXNzTmFtZSwgSlNPTi5zdHJpbmdpZnkocmVzdWx0cyksIGF1dGgpO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1heWJlUnVuUXVlcnlUcmlnZ2VyKHRyaWdnZXJUeXBlLCBjbGFzc05hbWUsIHJlc3RXaGVyZSwgcmVzdE9wdGlvbnMsIGNvbmZpZywgYXV0aCwgaXNHZXQpIHtcbiAgY29uc3QgdHJpZ2dlciA9IGdldFRyaWdnZXIoY2xhc3NOYW1lLCB0cmlnZ2VyVHlwZSwgY29uZmlnLmFwcGxpY2F0aW9uSWQpO1xuICBpZiAoIXRyaWdnZXIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgIHJlc3RXaGVyZSxcbiAgICAgIHJlc3RPcHRpb25zXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCBwYXJzZVF1ZXJ5ID0gbmV3IFBhcnNlLlF1ZXJ5KGNsYXNzTmFtZSk7XG4gIGlmIChyZXN0V2hlcmUpIHtcbiAgICBwYXJzZVF1ZXJ5Ll93aGVyZSA9IHJlc3RXaGVyZTtcbiAgfVxuICBsZXQgY291bnQgPSBmYWxzZTtcbiAgaWYgKHJlc3RPcHRpb25zKSB7XG4gICAgaWYgKHJlc3RPcHRpb25zLmluY2x1ZGUgJiYgcmVzdE9wdGlvbnMuaW5jbHVkZS5sZW5ndGggPiAwKSB7XG4gICAgICBwYXJzZVF1ZXJ5Ll9pbmNsdWRlID0gcmVzdE9wdGlvbnMuaW5jbHVkZS5zcGxpdCgnLCcpO1xuICAgIH1cbiAgICBpZiAocmVzdE9wdGlvbnMuc2tpcCkge1xuICAgICAgcGFyc2VRdWVyeS5fc2tpcCA9IHJlc3RPcHRpb25zLnNraXA7XG4gICAgfVxuICAgIGlmIChyZXN0T3B0aW9ucy5saW1pdCkge1xuICAgICAgcGFyc2VRdWVyeS5fbGltaXQgPSByZXN0T3B0aW9ucy5saW1pdDtcbiAgICB9XG4gICAgY291bnQgPSAhIXJlc3RPcHRpb25zLmNvdW50O1xuICB9XG4gIGNvbnN0IHJlcXVlc3RPYmplY3QgPSBnZXRSZXF1ZXN0UXVlcnlPYmplY3QodHJpZ2dlclR5cGUsIGF1dGgsIHBhcnNlUXVlcnksIGNvdW50LCBjb25maWcsIGlzR2V0KTtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgIHJldHVybiB0cmlnZ2VyKHJlcXVlc3RPYmplY3QpO1xuICB9KS50aGVuKChyZXN1bHQpID0+IHtcbiAgICBsZXQgcXVlcnlSZXN1bHQgPSBwYXJzZVF1ZXJ5O1xuICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0IGluc3RhbmNlb2YgUGFyc2UuUXVlcnkpIHtcbiAgICAgIHF1ZXJ5UmVzdWx0ID0gcmVzdWx0O1xuICAgIH1cbiAgICBjb25zdCBqc29uUXVlcnkgPSBxdWVyeVJlc3VsdC50b0pTT04oKTtcbiAgICBpZiAoanNvblF1ZXJ5LndoZXJlKSB7XG4gICAgICByZXN0V2hlcmUgPSBqc29uUXVlcnkud2hlcmU7XG4gICAgfVxuICAgIGlmIChqc29uUXVlcnkubGltaXQpIHtcbiAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICByZXN0T3B0aW9ucy5saW1pdCA9IGpzb25RdWVyeS5saW1pdDtcbiAgICB9XG4gICAgaWYgKGpzb25RdWVyeS5za2lwKSB7XG4gICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgcmVzdE9wdGlvbnMuc2tpcCA9IGpzb25RdWVyeS5za2lwO1xuICAgIH1cbiAgICBpZiAoanNvblF1ZXJ5LmluY2x1ZGUpIHtcbiAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICByZXN0T3B0aW9ucy5pbmNsdWRlID0ganNvblF1ZXJ5LmluY2x1ZGU7XG4gICAgfVxuICAgIGlmIChqc29uUXVlcnkua2V5cykge1xuICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgIHJlc3RPcHRpb25zLmtleXMgPSBqc29uUXVlcnkua2V5cztcbiAgICB9XG4gICAgaWYgKGpzb25RdWVyeS5vcmRlcikge1xuICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgIHJlc3RPcHRpb25zLm9yZGVyID0ganNvblF1ZXJ5Lm9yZGVyO1xuICAgIH1cbiAgICBpZiAocmVxdWVzdE9iamVjdC5yZWFkUHJlZmVyZW5jZSkge1xuICAgICAgcmVzdE9wdGlvbnMgPSByZXN0T3B0aW9ucyB8fCB7fTtcbiAgICAgIHJlc3RPcHRpb25zLnJlYWRQcmVmZXJlbmNlID0gcmVxdWVzdE9iamVjdC5yZWFkUHJlZmVyZW5jZTtcbiAgICB9XG4gICAgaWYgKHJlcXVlc3RPYmplY3QuaW5jbHVkZVJlYWRQcmVmZXJlbmNlKSB7XG4gICAgICByZXN0T3B0aW9ucyA9IHJlc3RPcHRpb25zIHx8IHt9O1xuICAgICAgcmVzdE9wdGlvbnMuaW5jbHVkZVJlYWRQcmVmZXJlbmNlID0gcmVxdWVzdE9iamVjdC5pbmNsdWRlUmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIGlmIChyZXF1ZXN0T2JqZWN0LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UpIHtcbiAgICAgIHJlc3RPcHRpb25zID0gcmVzdE9wdGlvbnMgfHwge307XG4gICAgICByZXN0T3B0aW9ucy5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlID0gcmVxdWVzdE9iamVjdC5zdWJxdWVyeVJlYWRQcmVmZXJlbmNlO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgcmVzdFdoZXJlLFxuICAgICAgcmVzdE9wdGlvbnNcbiAgICB9O1xuICB9LCAoZXJyKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBlcnIgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoMSwgZXJyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfSk7XG59XG5cbi8vIFRvIGJlIHVzZWQgYXMgcGFydCBvZiB0aGUgcHJvbWlzZSBjaGFpbiB3aGVuIHNhdmluZy9kZWxldGluZyBhbiBvYmplY3Rcbi8vIFdpbGwgcmVzb2x2ZSBzdWNjZXNzZnVsbHkgaWYgbm8gdHJpZ2dlciBpcyBjb25maWd1cmVkXG4vLyBSZXNvbHZlcyB0byBhbiBvYmplY3QsIGVtcHR5IG9yIGNvbnRhaW5pbmcgYW4gb2JqZWN0IGtleS4gQSBiZWZvcmVTYXZlXG4vLyB0cmlnZ2VyIHdpbGwgc2V0IHRoZSBvYmplY3Qga2V5IHRvIHRoZSByZXN0IGZvcm1hdCBvYmplY3QgdG8gc2F2ZS5cbi8vIG9yaWdpbmFsUGFyc2VPYmplY3QgaXMgb3B0aW9uYWwsIHdlIG9ubHkgbmVlZCB0aGF0IGZvciBiZWZvcmUvYWZ0ZXJTYXZlIGZ1bmN0aW9uc1xuZXhwb3J0IGZ1bmN0aW9uIG1heWJlUnVuVHJpZ2dlcih0cmlnZ2VyVHlwZSwgYXV0aCwgcGFyc2VPYmplY3QsIG9yaWdpbmFsUGFyc2VPYmplY3QsIGNvbmZpZykge1xuICBpZiAoIXBhcnNlT2JqZWN0KSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gIH1cbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgdHJpZ2dlciA9IGdldFRyaWdnZXIocGFyc2VPYmplY3QuY2xhc3NOYW1lLCB0cmlnZ2VyVHlwZSwgY29uZmlnLmFwcGxpY2F0aW9uSWQpO1xuICAgIGlmICghdHJpZ2dlcikgcmV0dXJuIHJlc29sdmUoKTtcbiAgICB2YXIgcmVxdWVzdCA9IGdldFJlcXVlc3RPYmplY3QodHJpZ2dlclR5cGUsIGF1dGgsIHBhcnNlT2JqZWN0LCBvcmlnaW5hbFBhcnNlT2JqZWN0LCBjb25maWcpO1xuICAgIHZhciByZXNwb25zZSA9IGdldFJlc3BvbnNlT2JqZWN0KHJlcXVlc3QsIChvYmplY3QpID0+IHtcbiAgICAgIGxvZ1RyaWdnZXJTdWNjZXNzQmVmb3JlSG9vayhcbiAgICAgICAgdHJpZ2dlclR5cGUsIHBhcnNlT2JqZWN0LmNsYXNzTmFtZSwgcGFyc2VPYmplY3QudG9KU09OKCksIG9iamVjdCwgYXV0aCk7XG4gICAgICByZXNvbHZlKG9iamVjdCk7XG4gICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICBsb2dUcmlnZ2VyRXJyb3JCZWZvcmVIb29rKFxuICAgICAgICB0cmlnZ2VyVHlwZSwgcGFyc2VPYmplY3QuY2xhc3NOYW1lLCBwYXJzZU9iamVjdC50b0pTT04oKSwgYXV0aCwgZXJyb3IpO1xuICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICB9KTtcbiAgICAvLyBGb3JjZSB0aGUgY3VycmVudCBQYXJzZSBhcHAgYmVmb3JlIHRoZSB0cmlnZ2VyXG4gICAgUGFyc2UuYXBwbGljYXRpb25JZCA9IGNvbmZpZy5hcHBsaWNhdGlvbklkO1xuICAgIFBhcnNlLmphdmFzY3JpcHRLZXkgPSBjb25maWcuamF2YXNjcmlwdEtleSB8fCAnJztcbiAgICBQYXJzZS5tYXN0ZXJLZXkgPSBjb25maWcubWFzdGVyS2V5O1xuXG4gICAgLy8gQWZ0ZXJTYXZlIGFuZCBhZnRlckRlbGV0ZSB0cmlnZ2VycyBjYW4gcmV0dXJuIGEgcHJvbWlzZSwgd2hpY2ggaWYgdGhleVxuICAgIC8vIGRvLCBuZWVkcyB0byBiZSByZXNvbHZlZCBiZWZvcmUgdGhpcyBwcm9taXNlIGlzIHJlc29sdmVkLFxuICAgIC8vIHNvIHRyaWdnZXIgZXhlY3V0aW9uIGlzIHN5bmNlZCB3aXRoIFJlc3RXcml0ZS5leGVjdXRlKCkgY2FsbC5cbiAgICAvLyBJZiB0cmlnZ2VycyBkbyBub3QgcmV0dXJuIGEgcHJvbWlzZSwgdGhleSBjYW4gcnVuIGFzeW5jIGNvZGUgcGFyYWxsZWxcbiAgICAvLyB0byB0aGUgUmVzdFdyaXRlLmV4ZWN1dGUoKSBjYWxsLlxuICAgIHZhciB0cmlnZ2VyUHJvbWlzZSA9IHRyaWdnZXIocmVxdWVzdCwgcmVzcG9uc2UpO1xuICAgIGlmKHRyaWdnZXJUeXBlID09PSBUeXBlcy5hZnRlclNhdmUgfHwgdHJpZ2dlclR5cGUgPT09IFR5cGVzLmFmdGVyRGVsZXRlKVxuICAgIHtcbiAgICAgIGxvZ1RyaWdnZXJBZnRlckhvb2sodHJpZ2dlclR5cGUsIHBhcnNlT2JqZWN0LmNsYXNzTmFtZSwgcGFyc2VPYmplY3QudG9KU09OKCksIGF1dGgpO1xuICAgICAgaWYodHJpZ2dlclByb21pc2UgJiYgdHlwZW9mIHRyaWdnZXJQcm9taXNlLnRoZW4gPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICByZXR1cm4gdHJpZ2dlclByb21pc2UudGhlbihyZXNvbHZlLCByZXNvbHZlKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG59XG5cbi8vIENvbnZlcnRzIGEgUkVTVC1mb3JtYXQgb2JqZWN0IHRvIGEgUGFyc2UuT2JqZWN0XG4vLyBkYXRhIGlzIGVpdGhlciBjbGFzc05hbWUgb3IgYW4gb2JqZWN0XG5leHBvcnQgZnVuY3Rpb24gaW5mbGF0ZShkYXRhLCByZXN0T2JqZWN0KSB7XG4gIHZhciBjb3B5ID0gdHlwZW9mIGRhdGEgPT0gJ29iamVjdCcgPyBkYXRhIDoge2NsYXNzTmFtZTogZGF0YX07XG4gIGZvciAodmFyIGtleSBpbiByZXN0T2JqZWN0KSB7XG4gICAgY29weVtrZXldID0gcmVzdE9iamVjdFtrZXldO1xuICB9XG4gIHJldHVybiBQYXJzZS5PYmplY3QuZnJvbUpTT04oY29weSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKGRhdGEsIGFwcGxpY2F0aW9uSWQgPSBQYXJzZS5hcHBsaWNhdGlvbklkKSB7XG4gIGlmICghX3RyaWdnZXJTdG9yZSB8fCAhX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXSB8fCAhX3RyaWdnZXJTdG9yZVthcHBsaWNhdGlvbklkXS5MaXZlUXVlcnkpIHsgcmV0dXJuOyB9XG4gIF90cmlnZ2VyU3RvcmVbYXBwbGljYXRpb25JZF0uTGl2ZVF1ZXJ5LmZvckVhY2goKGhhbmRsZXIpID0+IGhhbmRsZXIoZGF0YSkpO1xufVxuIl19 \ No newline at end of file diff --git a/lib/vendor/mongodbUrl.js b/lib/vendor/mongodbUrl.js index 091ed8e742..2714315f99 100644 --- a/lib/vendor/mongodbUrl.js +++ b/lib/vendor/mongodbUrl.js @@ -921,4 +921,5 @@ function encodeAuth(str) { if (lastPos === 0) return str; if (lastPos < str.length) return out + str.slice(lastPos); return out; -} \ No newline at end of file +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92ZW5kb3IvbW9uZ29kYlVybC5qcyJdLCJuYW1lcyI6WyJwdW55Y29kZSIsInJlcXVpcmUiLCJleHBvcnRzIiwicGFyc2UiLCJ1cmxQYXJzZSIsInJlc29sdmUiLCJ1cmxSZXNvbHZlIiwicmVzb2x2ZU9iamVjdCIsInVybFJlc29sdmVPYmplY3QiLCJmb3JtYXQiLCJ1cmxGb3JtYXQiLCJVcmwiLCJwcm90b2NvbCIsInNsYXNoZXMiLCJhdXRoIiwiaG9zdCIsInBvcnQiLCJob3N0bmFtZSIsImhhc2giLCJzZWFyY2giLCJxdWVyeSIsInBhdGhuYW1lIiwicGF0aCIsImhyZWYiLCJwcm90b2NvbFBhdHRlcm4iLCJwb3J0UGF0dGVybiIsInNpbXBsZVBhdGhQYXR0ZXJuIiwiaG9zdG5hbWVNYXhMZW4iLCJ1bnNhZmVQcm90b2NvbCIsImhvc3RsZXNzUHJvdG9jb2wiLCJzbGFzaGVkUHJvdG9jb2wiLCJxdWVyeXN0cmluZyIsInVybCIsInBhcnNlUXVlcnlTdHJpbmciLCJzbGFzaGVzRGVub3RlSG9zdCIsInUiLCJwcm90b3R5cGUiLCJUeXBlRXJyb3IiLCJoYXNIYXNoIiwic3RhcnQiLCJlbmQiLCJyZXN0IiwibGFzdFBvcyIsImkiLCJpbldzIiwic3BsaXQiLCJsZW5ndGgiLCJjb2RlIiwiY2hhckNvZGVBdCIsImlzV3MiLCJzbGljZSIsInNpbXBsZVBhdGgiLCJleGVjIiwicHJvdG8iLCJsb3dlclByb3RvIiwidG9Mb3dlckNhc2UiLCJ0ZXN0IiwiaG9zdEVuZCIsImF0U2lnbiIsIm5vbkhvc3QiLCJkZWNvZGVVUklDb21wb25lbnQiLCJwYXJzZUhvc3QiLCJpcHY2SG9zdG5hbWUiLCJyZXN1bHQiLCJ2YWxpZGF0ZUhvc3RuYW1lIiwidW5kZWZpbmVkIiwidG9BU0NJSSIsInAiLCJoIiwiYXV0b0VzY2FwZVN0ciIsInF1ZXN0aW9uSWR4IiwiaGFzaElkeCIsImZpcnN0SWR4IiwicyIsInNlbGYiLCJuZXdSZXN0Iiwib2JqIiwiY2FsbCIsImVuY29kZUF1dGgiLCJpbmRleE9mIiwic3RyaW5naWZ5IiwibmV3UGF0aG5hbWUiLCJyZXBsYWNlIiwic291cmNlIiwicmVsYXRpdmUiLCJyZWwiLCJ0a2V5cyIsIk9iamVjdCIsImtleXMiLCJ0ayIsInRrZXkiLCJya2V5cyIsInJrIiwicmtleSIsInYiLCJrIiwicmVsUGF0aCIsInNoaWZ0IiwidW5zaGlmdCIsImpvaW4iLCJpc1NvdXJjZUFicyIsImNoYXJBdCIsImlzUmVsQWJzIiwibXVzdEVuZEFicyIsInJlbW92ZUFsbERvdHMiLCJzcmNQYXRoIiwicHN5Y2hvdGljIiwicG9wIiwiY29uY2F0IiwiYXV0aEluSG9zdCIsImxhc3QiLCJoYXNUcmFpbGluZ1NsYXNoIiwidXAiLCJzcGxpY2VPbmUiLCJzdWJzdHIiLCJwdXNoIiwiaXNBYnNvbHV0ZSIsImxpc3QiLCJpbmRleCIsIm4iLCJoZXhUYWJsZSIsIkFycmF5IiwidG9TdHJpbmciLCJ0b1VwcGVyQ2FzZSIsInN0ciIsIm91dCIsImMiLCJjMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxNQUFNQSxXQUFXQyxRQUFRLFVBQVIsQ0FBakI7O0FBRUFDLFFBQVFDLEtBQVIsR0FBZ0JDLFFBQWhCO0FBQ0FGLFFBQVFHLE9BQVIsR0FBa0JDLFVBQWxCO0FBQ0FKLFFBQVFLLGFBQVIsR0FBd0JDLGdCQUF4QjtBQUNBTixRQUFRTyxNQUFSLEdBQWlCQyxTQUFqQjs7QUFFQVIsUUFBUVMsR0FBUixHQUFjQSxHQUFkOztBQUVBLFNBQVNBLEdBQVQsR0FBZTtBQUNiLE9BQUtDLFFBQUwsR0FBZ0IsSUFBaEI7QUFDQSxPQUFLQyxPQUFMLEdBQWUsSUFBZjtBQUNBLE9BQUtDLElBQUwsR0FBWSxJQUFaO0FBQ0EsT0FBS0MsSUFBTCxHQUFZLElBQVo7QUFDQSxPQUFLQyxJQUFMLEdBQVksSUFBWjtBQUNBLE9BQUtDLFFBQUwsR0FBZ0IsSUFBaEI7QUFDQSxPQUFLQyxJQUFMLEdBQVksSUFBWjtBQUNBLE9BQUtD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dEIsSUFDQU4sU0FBUyxPQUFTTSxLQUFLLENBQU4sR0FBVyxJQUE1QixDQURBLEdBRUFOLFNBQVMsT0FBUU0sSUFBSSxJQUFyQixDQUZQO0FBR0E7QUFDRDtBQUNEO0FBQ0EsTUFBRW5GLENBQUY7QUFDQSxRQUFJb0YsRUFBSjtBQUNBLFFBQUlwRixJQUFJaUYsSUFBSTlFLE1BQVosRUFDRWlGLEtBQUtILElBQUk1RSxVQUFKLENBQWVMLENBQWYsSUFBb0IsS0FBekIsQ0FERixLQUdFb0YsS0FBSyxDQUFMO0FBQ0ZELFFBQUksV0FBWSxDQUFDQSxJQUFJLEtBQUwsS0FBZSxFQUFoQixHQUFzQkMsRUFBakMsQ0FBSjtBQUNBRixXQUFPTCxTQUFTLE9BQVFNLEtBQUssRUFBdEIsSUFDQU4sU0FBUyxPQUFTTSxLQUFLLEVBQU4sR0FBWSxJQUE3QixDQURBLEdBRUFOLFNBQVMsT0FBU00sS0FBSyxDQUFOLEdBQVcsSUFBNUIsQ0FGQSxHQUdBTixTQUFTLE9BQVFNLElBQUksSUFBckIsQ0FIUDtBQUlEO0FBQ0QsTUFBSXBGLFlBQVksQ0FBaEIsRUFDRSxPQUFPa0YsR0FBUDtBQUNGLE1BQUlsRixVQUFVa0YsSUFBSTlFLE1BQWxCLEVBQ0UsT0FBTytFLE1BQU1ELElBQUkxRSxLQUFKLENBQVVSLE9BQVYsQ0FBYjtBQUNGLFNBQU9tRixHQUFQO0FBQ0QiLCJmaWxlIjoibW9uZ29kYlVybC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEEgc2xpZ2h0bHkgcGF0Y2hlZCB2ZXJzaW9uIG9mIG5vZGUncyB1cmwgbW9kdWxlLCB3aXRoIHN1cHBvcnQgZm9yIG1vbmdvZGI6Ly9cbi8vIHVyaXMuXG4vL1xuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2RlanMvbm9kZS9ibG9iL21hc3Rlci9MSUNFTlNFIGZvciBsaWNlbnNpbmdcbi8vIGluZm9ybWF0aW9uXG5cbid1c2Ugc3RyaWN0JztcblxuY29uc3QgcHVueWNvZGUgPSByZXF1aXJlKCdwdW55Y29kZScpO1xuXG5leHBvcnRzLnBhcnNlID0gdXJsUGFyc2U7XG5leHBvcnRzLnJlc29sdmUgPSB1cmxSZXNvbHZlO1xuZXhwb3J0cy5yZXNvbHZlT2JqZWN0ID0gdXJsUmVzb2x2ZU9iamVjdDtcbmV4cG9ydHMuZm9ybWF0ID0gdXJsRm9ybWF0O1xuXG5leHBvcnRzLlVybCA9IFVybDtcblxuZnVuY3Rpb24gVXJsKCkge1xuICB0aGlzLnByb3RvY29sID0gbnVsbDtcbiAgdGhpcy5zbGFzaGVzID0gbnVsbDtcbiAgdGhpcy5hdXRoID0gbnVsbDtcbiAgdGhpcy5ob3N0ID0gbnVsbDtcbiAgdGhpcy5wb3J0ID0gbnVsbDtcbiAgdGhpcy5ob3N0bmFtZSA9IG51bGw7XG4gIHRoaXMuaGFzaCA9IG51bGw7XG4gIHRoaXMuc2VhcmNoID0gbnVsbDtcbiAgdGhpcy5xdWVyeSA9IG51bGw7XG4gIHRoaXMucGF0aG5hbWUgPSBudWxsO1xuICB0aGlzLnBhdGggPSBudWxsO1xuICB0aGlzLmhyZWYgPSBudWxsO1xufVxuXG4vLyBSZWZlcmVuY2U6IFJGQyAzOTg2LCBSRkMgMTgwOCwgUkZDIDIzOTZcblxuLy8gZGVmaW5lIHRoZXNlIGhlcmUgc28gYXQgbGVhc3QgdGhleSBvbmx5IGhhdmUgdG8gYmVcbi8vIGNvbXBpbGVkIG9uY2Ugb24gdGhlIGZpcnN0IG1vZHVsZSBsb2FkLlxuY29uc3QgcHJvdG9jb2xQYXR0ZXJuID0gL14oW2EtejAtOS4rLV0rOikvaTtcbmNvbnN0IHBvcnRQYXR0ZXJuID0gLzpbMC05XSokLztcblxuLy8gU3BlY2lhbCBjYXNlIGZvciBhIHNpbXBsZSBwYXRoIFVSTFxuY29uc3Qgc2ltcGxlUGF0aFBhdHRlcm4gPSAvXihcXC9cXC8/KD8hXFwvKVteXFw/XFxzXSopKFxcP1teXFxzXSopPyQvO1xuXG5jb25zdCBob3N0bmFtZU1heExlbiA9IDI1NTtcbi8vIHByb3RvY29scyB0aGF0IGNhbiBhbGxvdyBcInVuc2FmZVwiIGFuZCBcInVud2lzZVwiIGNoYXJzLlxuY29uc3QgdW5zYWZlUHJvdG9jb2wgPSB7XG4gICdqYXZhc2NyaXB0JzogdHJ1ZSxcbiAgJ2phdmFzY3JpcHQ6JzogdHJ1ZVxufTtcbi8vIHByb3RvY29scyB0aGF0IG5ldmVyIGhhdmUgYSBob3N0bmFtZS5cbmNvbnN0IGhvc3RsZXNzUHJvdG9jb2wgPSB7XG4gICdqYXZhc2NyaXB0JzogdHJ1ZSxcbiAgJ2phdmFzY3JpcHQ6JzogdHJ1ZVxufTtcbi8vIHByb3RvY29scyB0aGF0IGFsd2F5cyBjb250YWluIGEgLy8gYml0LlxuY29uc3Qgc2xhc2hlZFByb3RvY29sID0ge1xuICAnaHR0cCc6IHRydWUsXG4gICdodHRwOic6IHRydWUsXG4gICdodHRwcyc6IHRydWUsXG4gICdodHRwczonOiB0cnVlLFxuICAnZnRwJzogdHJ1ZSxcbiAgJ2Z0cDonOiB0cnVlLFxuICAnZ29waGVyJzogdHJ1ZSxcbiAgJ2dvcGhlcjonOiB0cnVlLFxuICAnZmlsZSc6IHRydWUsXG4gICdmaWxlOic6IHRydWVcbn07XG5jb25zdCBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJyk7XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5mdW5jdGlvbiB1cmxQYXJzZSh1cmwsIHBhcnNlUXVlcnlTdHJpbmcsIHNsYXNoZXNEZW5vdGVIb3N0KSB7XG4gIGlmICh1cmwgaW5zdGFuY2VvZiBVcmwpIHJldHVybiB1cmw7XG5cbiAgdmFyIHUgPSBuZXcgVXJsKCk7XG4gIHUucGFyc2UodXJsLCBwYXJzZVF1ZXJ5U3RyaW5nLCBzbGFzaGVzRGVub3RlSG9zdCk7XG4gIHJldHVybiB1O1xufVxuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogaW1wcm92ZSBjb3ZlcmFnZSAqL1xuVXJsLnByb3RvdHlwZS5wYXJzZSA9IGZ1bmN0aW9uKHVybCwgcGFyc2VRdWVyeVN0cmluZywgc2xhc2hlc0Rlbm90ZUhvc3QpIHtcbiAgaWYgKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignUGFyYW1ldGVyIFwidXJsXCIgbXVzdCBiZSBhIHN0cmluZywgbm90ICcgKyB0eXBlb2YgdXJsKTtcbiAgfVxuXG4gIC8vIENvcHkgY2hyb21lLCBJRSwgb3BlcmEgYmFja3NsYXNoLWhhbmRsaW5nIGJlaGF2aW9yLlxuICAvLyBCYWNrIHNsYXNoZXMgYmVmb3JlIHRoZSBxdWVyeSBzdHJpbmcgZ2V0IGNvbnZlcnRlZCB0byBmb3J3YXJkIHNsYXNoZXNcbiAgLy8gU2VlOiBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9MjU5MTZcbiAgdmFyIGhhc0hhc2ggPSBmYWxzZTtcbiAgdmFyIHN0YXJ0ID0gLTE7XG4gIHZhciBlbmQgPSAtMTtcbiAgdmFyIHJlc3QgPSAnJztcbiAgdmFyIGxhc3RQb3MgPSAwO1xuICB2YXIgaSA9IDA7XG4gIGZvciAodmFyIGluV3MgPSBmYWxzZSwgc3BsaXQgPSBmYWxzZTsgaSA8IHVybC5sZW5ndGg7ICsraSkge1xuICAgIGNvbnN0IGNvZGUgPSB1cmwuY2hhckNvZGVBdChpKTtcblxuICAgIC8vIEZpbmQgZmlyc3QgYW5kIGxhc3Qgbm9uLXdoaXRlc3BhY2UgY2hhcmFjdGVycyBmb3IgdHJpbW1pbmdcbiAgICBjb25zdCBpc1dzID0gY29kZSA9PT0gMzIvKiAqLyB8fFxuICAgICAgICAgICAgICAgICBjb2RlID09PSA5LypcXHQqLyB8fFxuICAgICAgICAgICAgICAgICBjb2RlID09PSAxMy8qXFxyKi8gfHxcbiAgICAgICAgICAgICAgICAgY29kZSA9PT0gMTAvKlxcbiovIHx8XG4gICAgICAgICAgICAgICAgIGNvZGUgPT09IDEyLypcXGYqLyB8fFxuICAgICAgICAgICAgICAgICBjb2RlID09PSAxNjAvKlxcdTAwQTAqLyB8fFxuICAgICAgICAgICAgICAgICBjb2RlID09PSA2NTI3OS8qXFx1RkVGRiovO1xuICAgIGlmIChzdGFydCA9PT0gLTEpIHtcbiAgICAgIGlmIChpc1dzKVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIGxhc3RQb3MgPSBzdGFydCA9IGk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChpbldzKSB7XG4gICAgICAgIGlmICghaXNXcykge1xuICAgICAgICAgIGVuZCA9IC0xO1xuICAgICAgICAgIGluV3MgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpc1dzKSB7XG4gICAgICAgIGVuZCA9IGk7XG4gICAgICAgIGluV3MgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE9ubHkgY29udmVydCBiYWNrc2xhc2hlcyB3aGlsZSB3ZSBoYXZlbid0IHNlZW4gYSBzcGxpdCBjaGFyYWN0ZXJcbiAgICBpZiAoIXNwbGl0KSB7XG4gICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgIGNhc2UgMzU6IC8vICcjJ1xuICAgICAgICBoYXNIYXNoID0gdHJ1ZTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoXG4gICAgICBjYXNlIDYzOiAvLyAnPydcbiAgICAgICAgc3BsaXQgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgOTI6IC8vICdcXFxcJ1xuICAgICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICAgIHJlc3QgKz0gdXJsLnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgICByZXN0ICs9ICcvJztcbiAgICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKCFoYXNIYXNoICYmIGNvZGUgPT09IDM1LyojKi8pIHtcbiAgICAgIGhhc0hhc2ggPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8vIENoZWNrIGlmIHN0cmluZyB3YXMgbm9uLWVtcHR5IChpbmNsdWRpbmcgc3RyaW5ncyB3aXRoIG9ubHkgd2hpdGVzcGFjZSlcbiAgaWYgKHN0YXJ0ICE9PSAtMSkge1xuICAgIGlmIChsYXN0UG9zID09PSBzdGFydCkge1xuICAgICAgLy8gV2UgZGlkbid0IGNvbnZlcnQgYW55IGJhY2tzbGFzaGVzXG5cbiAgICAgIGlmIChlbmQgPT09IC0xKSB7XG4gICAgICAgIGlmIChzdGFydCA9PT0gMClcbiAgICAgICAgICByZXN0ID0gdXJsO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgcmVzdCA9IHVybC5zbGljZShzdGFydCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN0ID0gdXJsLnNsaWNlKHN0YXJ0LCBlbmQpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZW5kID09PSAtMSAmJiBsYXN0UG9zIDwgdXJsLmxlbmd0aCkge1xuICAgICAgLy8gV2UgY29udmVydGVkIHNvbWUgYmFja3NsYXNoZXMgYW5kIGhhdmUgb25seSBwYXJ0IG9mIHRoZSBlbnRpcmUgc3RyaW5nXG4gICAgICByZXN0ICs9IHVybC5zbGljZShsYXN0UG9zKTtcbiAgICB9IGVsc2UgaWYgKGVuZCAhPT0gLTEgJiYgbGFzdFBvcyA8IGVuZCkge1xuICAgICAgLy8gV2UgY29udmVydGVkIHNvbWUgYmFja3NsYXNoZXMgYW5kIGhhdmUgb25seSBwYXJ0IG9mIHRoZSBlbnRpcmUgc3RyaW5nXG4gICAgICByZXN0ICs9IHVybC5zbGljZShsYXN0UG9zLCBlbmQpO1xuICAgIH1cbiAgfVxuXG4gIGlmICghc2xhc2hlc0Rlbm90ZUhvc3QgJiYgIWhhc0hhc2gpIHtcbiAgICAvLyBUcnkgZmFzdCBwYXRoIHJlZ2V4cFxuICAgIGNvbnN0IHNpbXBsZVBhdGggPSBzaW1wbGVQYXRoUGF0dGVybi5leGVjKHJlc3QpO1xuICAgIGlmIChzaW1wbGVQYXRoKSB7XG4gICAgICB0aGlzLnBhdGggPSByZXN0O1xuICAgICAgdGhpcy5ocmVmID0gcmVzdDtcbiAgICAgIHRoaXMucGF0aG5hbWUgPSBzaW1wbGVQYXRoWzFdO1xuICAgICAgaWYgKHNpbXBsZVBhdGhbMl0pIHtcbiAgICAgICAgdGhpcy5zZWFyY2ggPSBzaW1wbGVQYXRoWzJdO1xuICAgICAgICBpZiAocGFyc2VRdWVyeVN0cmluZykge1xuICAgICAgICAgIHRoaXMucXVlcnkgPSBxdWVyeXN0cmluZy5wYXJzZSh0aGlzLnNlYXJjaC5zbGljZSgxKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5xdWVyeSA9IHRoaXMuc2VhcmNoLnNsaWNlKDEpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHBhcnNlUXVlcnlTdHJpbmcpIHtcbiAgICAgICAgdGhpcy5zZWFyY2ggPSAnJztcbiAgICAgICAgdGhpcy5xdWVyeSA9IHt9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9XG5cbiAgdmFyIHByb3RvID0gcHJvdG9jb2xQYXR0ZXJuLmV4ZWMocmVzdCk7XG4gIGlmIChwcm90bykge1xuICAgIHByb3RvID0gcHJvdG9bMF07XG4gICAgdmFyIGxvd2VyUHJvdG8gPSBwcm90by50b0xvd2VyQ2FzZSgpO1xuICAgIHRoaXMucHJvdG9jb2wgPSBsb3dlclByb3RvO1xuICAgIHJlc3QgPSByZXN0LnNsaWNlKHByb3RvLmxlbmd0aCk7XG4gIH1cblxuICAvLyBmaWd1cmUgb3V0IGlmIGl0J3MgZ290IGEgaG9zdFxuICAvLyB1c2VyQHNlcnZlciBpcyAqYWx3YXlzKiBpbnRlcnByZXRlZCBhcyBhIGhvc3RuYW1lLCBhbmQgdXJsXG4gIC8vIHJlc29sdXRpb24gd2lsbCB0cmVhdCAvL2Zvby9iYXIgYXMgaG9zdD1mb28scGF0aD1iYXIgYmVjYXVzZSB0aGF0J3NcbiAgLy8gaG93IHRoZSBicm93c2VyIHJlc29sdmVzIHJlbGF0aXZlIFVSTHMuXG4gIGlmIChzbGFzaGVzRGVub3RlSG9zdCB8fCBwcm90byB8fCAvXlxcL1xcL1teQFxcL10rQFteQFxcL10rLy50ZXN0KHJlc3QpKSB7XG4gICAgdmFyIHNsYXNoZXMgPSByZXN0LmNoYXJDb2RlQXQoMCkgPT09IDQ3LyovKi8gJiZcbiAgICAgICAgICAgICAgICAgIHJlc3QuY2hhckNvZGVBdCgxKSA9PT0gNDcvKi8qLztcbiAgICBpZiAoc2xhc2hlcyAmJiAhKHByb3RvICYmIGhvc3RsZXNzUHJvdG9jb2xbcHJvdG9dKSkge1xuICAgICAgcmVzdCA9IHJlc3Quc2xpY2UoMik7XG4gICAgICB0aGlzLnNsYXNoZXMgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICghaG9zdGxlc3NQcm90b2NvbFtwcm90b10gJiZcbiAgICAgIChzbGFzaGVzIHx8IChwcm90byAmJiAhc2xhc2hlZFByb3RvY29sW3Byb3RvXSkpKSB7XG5cbiAgICAvLyB0aGVyZSdzIGEgaG9zdG5hbWUuXG4gICAgLy8gdGhlIGZpcnN0IGluc3RhbmNlIG9mIC8sID8sIDssIG9yICMgZW5kcyB0aGUgaG9zdC5cbiAgICAvL1xuICAgIC8vIElmIHRoZXJlIGlzIGFuIEAgaW4gdGhlIGhvc3RuYW1lLCB0aGVuIG5vbi1ob3N0IGNoYXJzICphcmUqIGFsbG93ZWRcbiAgICAvLyB0byB0aGUgbGVmdCBvZiB0aGUgbGFzdCBAIHNpZ24sIHVubGVzcyBzb21lIGhvc3QtZW5kaW5nIGNoYXJhY3RlclxuICAgIC8vIGNvbWVzICpiZWZvcmUqIHRoZSBALXNpZ24uXG4gICAgLy8gVVJMcyBhcmUgb2Jub3hpb3VzLlxuICAgIC8vXG4gICAgLy8gZXg6XG4gICAgLy8gaHR0cDovL2FAYkBjLyA9PiB1c2VyOmFAYiBob3N0OmNcbiAgICAvLyBodHRwOi8vYUBiP0BjID0+IHVzZXI6YSBob3N0OmIgcGF0aDovP0BjXG5cbiAgICAvLyB2MC4xMiBUT0RPKGlzYWFjcyk6IFRoaXMgaXMgbm90IHF1aXRlIGhvdyBDaHJvbWUgZG9lcyB0aGluZ3MuXG4gICAgLy8gUmV2aWV3IG91ciB0ZXN0IGNhc2UgYWdhaW5zdCBicm93c2VycyBtb3JlIGNvbXByZWhlbnNpdmVseS5cblxuICAgIHZhciBob3N0RW5kID0gLTE7XG4gICAgdmFyIGF0U2lnbiA9IC0xO1xuICAgIHZhciBub25Ib3N0ID0gLTE7XG4gICAgZm9yIChpID0gMDsgaSA8IHJlc3QubGVuZ3RoOyArK2kpIHtcbiAgICAgIHN3aXRjaCAocmVzdC5jaGFyQ29kZUF0KGkpKSB7XG4gICAgICBjYXNlIDk6ICAgLy8gJ1xcdCdcbiAgICAgIGNhc2UgMTA6ICAvLyAnXFxuJ1xuICAgICAgY2FzZSAxMzogIC8vICdcXHInXG4gICAgICBjYXNlIDMyOiAgLy8gJyAnXG4gICAgICBjYXNlIDM0OiAgLy8gJ1wiJ1xuICAgICAgY2FzZSAzNzogIC8vICclJ1xuICAgICAgY2FzZSAzOTogIC8vICdcXCcnXG4gICAgICBjYXNlIDU5OiAgLy8gJzsnXG4gICAgICBjYXNlIDYwOiAgLy8gJzwnXG4gICAgICBjYXNlIDYyOiAgLy8gJz4nXG4gICAgICBjYXNlIDkyOiAgLy8gJ1xcXFwnXG4gICAgICBjYXNlIDk0OiAgLy8gJ14nXG4gICAgICBjYXNlIDk2OiAgLy8gJ2AnXG4gICAgICBjYXNlIDEyMzogLy8gJ3snXG4gICAgICBjYXNlIDEyNDogLy8gJ3wnXG4gICAgICBjYXNlIDEyNTogLy8gJ30nXG4gICAgICAgIC8vIENoYXJhY3RlcnMgdGhhdCBhcmUgbmV2ZXIgZXZlciBhbGxvd2VkIGluIGEgaG9zdG5hbWUgZnJvbSBSRkMgMjM5NlxuICAgICAgICBpZiAobm9uSG9zdCA9PT0gLTEpXG4gICAgICAgICAgbm9uSG9zdCA9IGk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzNTogLy8gJyMnXG4gICAgICBjYXNlIDQ3OiAvLyAnLydcbiAgICAgIGNhc2UgNjM6IC8vICc/J1xuICAgICAgICAvLyBGaW5kIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBhbnkgaG9zdC1lbmRpbmcgY2hhcmFjdGVyc1xuICAgICAgICBpZiAobm9uSG9zdCA9PT0gLTEpXG4gICAgICAgICAgbm9uSG9zdCA9IGk7XG4gICAgICAgIGhvc3RFbmQgPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNjQ6IC8vICdAJ1xuICAgICAgICAvLyBBdCB0aGlzIHBvaW50LCBlaXRoZXIgd2UgaGF2ZSBhbiBleHBsaWNpdCBwb2ludCB3aGVyZSB0aGVcbiAgICAgICAgLy8gYXV0aCBwb3J0aW9uIGNhbm5vdCBnbyBwYXN0LCBvciB0aGUgbGFzdCBAIGNoYXIgaXMgdGhlIGRlY2lkZXIuXG4gICAgICAgIGF0U2lnbiA9IGk7XG4gICAgICAgIG5vbkhvc3QgPSAtMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoaG9zdEVuZCAhPT0gLTEpXG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBzdGFydCA9IDA7XG4gICAgaWYgKGF0U2lnbiAhPT0gLTEpIHtcbiAgICAgIHRoaXMuYXV0aCA9IGRlY29kZVVSSUNvbXBvbmVudChyZXN0LnNsaWNlKDAsIGF0U2lnbikpO1xuICAgICAgc3RhcnQgPSBhdFNpZ24gKyAxO1xuICAgIH1cbiAgICBpZiAobm9uSG9zdCA9PT0gLTEpIHtcbiAgICAgIHRoaXMuaG9zdCA9IHJlc3Quc2xpY2Uoc3RhcnQpO1xuICAgICAgcmVzdCA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmhvc3QgPSByZXN0LnNsaWNlKHN0YXJ0LCBub25Ib3N0KTtcbiAgICAgIHJlc3QgPSByZXN0LnNsaWNlKG5vbkhvc3QpO1xuICAgIH1cblxuICAgIC8vIHB1bGwgb3V0IHBvcnQuXG4gICAgdGhpcy5wYXJzZUhvc3QoKTtcblxuICAgIC8vIHdlJ3ZlIGluZGljYXRlZCB0aGF0IHRoZXJlIGlzIGEgaG9zdG5hbWUsXG4gICAgLy8gc28gZXZlbiBpZiBpdCdzIGVtcHR5LCBpdCBoYXMgdG8gYmUgcHJlc2VudC5cbiAgICBpZiAodHlwZW9mIHRoaXMuaG9zdG5hbWUgIT09ICdzdHJpbmcnKVxuICAgICAgdGhpcy5ob3N0bmFtZSA9ICcnO1xuXG4gICAgdmFyIGhvc3RuYW1lID0gdGhpcy5ob3N0bmFtZTtcblxuICAgIC8vIGlmIGhvc3RuYW1lIGJlZ2lucyB3aXRoIFsgYW5kIGVuZHMgd2l0aCBdXG4gICAgLy8gYXNzdW1lIHRoYXQgaXQncyBhbiBJUHY2IGFkZHJlc3MuXG4gICAgdmFyIGlwdjZIb3N0bmFtZSA9IGhvc3RuYW1lLmNoYXJDb2RlQXQoMCkgPT09IDkxLypbKi8gJiZcbiAgICAgICAgICAgICAgICAgICAgICAgaG9zdG5hbWUuY2hhckNvZGVBdChob3N0bmFtZS5sZW5ndGggLSAxKSA9PT0gOTMvKl0qLztcblxuICAgIC8vIHZhbGlkYXRlIGEgbGl0dGxlLlxuICAgIGlmICghaXB2Nkhvc3RuYW1lKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSB2YWxpZGF0ZUhvc3RuYW1lKHRoaXMsIHJlc3QsIGhvc3RuYW1lKTtcbiAgICAgIGlmIChyZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgICAgcmVzdCA9IHJlc3VsdDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5ob3N0bmFtZS5sZW5ndGggPiBob3N0bmFtZU1heExlbikge1xuICAgICAgdGhpcy5ob3N0bmFtZSA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBob3N0bmFtZXMgYXJlIGFsd2F5cyBsb3dlciBjYXNlLlxuICAgICAgdGhpcy5ob3N0bmFtZSA9IHRoaXMuaG9zdG5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICB9XG5cbiAgICBpZiAoIWlwdjZIb3N0bmFtZSkge1xuICAgICAgLy8gSUROQSBTdXBwb3J0OiBSZXR1cm5zIGEgcHVueWNvZGVkIHJlcHJlc2VudGF0aW9uIG9mIFwiZG9tYWluXCIuXG4gICAgICAvLyBJdCBvbmx5IGNvbnZlcnRzIHBhcnRzIG9mIHRoZSBkb21haW4gbmFtZSB0aGF0XG4gICAgICAvLyBoYXZlIG5vbi1BU0NJSSBjaGFyYWN0ZXJzLCBpLmUuIGl0IGRvZXNuJ3QgbWF0dGVyIGlmXG4gICAgICAvLyB5b3UgY2FsbCBpdCB3aXRoIGEgZG9tYWluIHRoYXQgYWxyZWFkeSBpcyBBU0NJSS1vbmx5LlxuICAgICAgdGhpcy5ob3N0bmFtZSA9IHB1bnljb2RlLnRvQVNDSUkodGhpcy5ob3N0bmFtZSk7XG4gICAgfVxuXG4gICAgdmFyIHAgPSB0aGlzLnBvcnQgPyAnOicgKyB0aGlzLnBvcnQgOiAnJztcbiAgICB2YXIgaCA9IHRoaXMuaG9zdG5hbWUgfHwgJyc7XG4gICAgdGhpcy5ob3N0ID0gaCArIHA7XG5cbiAgICAvLyBzdHJpcCBbIGFuZCBdIGZyb20gdGhlIGhvc3RuYW1lXG4gICAgLy8gdGhlIGhvc3QgZmllbGQgc3RpbGwgcmV0YWlucyB0aGVtLCB0aG91Z2hcbiAgICBpZiAoaXB2Nkhvc3RuYW1lKSB7XG4gICAgICB0aGlzLmhvc3RuYW1lID0gdGhpcy5ob3N0bmFtZS5zbGljZSgxLCAtMSk7XG4gICAgICBpZiAocmVzdFswXSAhPT0gJy8nKSB7XG4gICAgICAgIHJlc3QgPSAnLycgKyByZXN0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIG5vdyByZXN0IGlzIHNldCB0byB0aGUgcG9zdC1ob3N0IHN0dWZmLlxuICAvLyBjaG9wIG9mZiBhbnkgZGVsaW0gY2hhcnMuXG4gIGlmICghdW5zYWZlUHJvdG9jb2xbbG93ZXJQcm90b10pIHtcbiAgICAvLyBGaXJzdCwgbWFrZSAxMDAlIHN1cmUgdGhhdCBhbnkgXCJhdXRvRXNjYXBlXCIgY2hhcnMgZ2V0XG4gICAgLy8gZXNjYXBlZCwgZXZlbiBpZiBlbmNvZGVVUklDb21wb25lbnQgZG9lc24ndCB0aGluayB0aGV5XG4gICAgLy8gbmVlZCB0byBiZS5cbiAgICBjb25zdCByZXN1bHQgPSBhdXRvRXNjYXBlU3RyKHJlc3QpO1xuICAgIGlmIChyZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3QgPSByZXN1bHQ7XG4gIH1cblxuICB2YXIgcXVlc3Rpb25JZHggPSAtMTtcbiAgdmFyIGhhc2hJZHggPSAtMTtcbiAgZm9yIChpID0gMDsgaSA8IHJlc3QubGVuZ3RoOyArK2kpIHtcbiAgICBjb25zdCBjb2RlID0gcmVzdC5jaGFyQ29kZUF0KGkpO1xuICAgIGlmIChjb2RlID09PSAzNS8qIyovKSB7XG4gICAgICB0aGlzLmhhc2ggPSByZXN0LnNsaWNlKGkpO1xuICAgICAgaGFzaElkeCA9IGk7XG4gICAgICBicmVhaztcbiAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDYzLyo/Ki8gJiYgcXVlc3Rpb25JZHggPT09IC0xKSB7XG4gICAgICBxdWVzdGlvbklkeCA9IGk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHF1ZXN0aW9uSWR4ICE9PSAtMSkge1xuICAgIGlmIChoYXNoSWR4ID09PSAtMSkge1xuICAgICAgdGhpcy5zZWFyY2ggPSByZXN0LnNsaWNlKHF1ZXN0aW9uSWR4KTtcbiAgICAgIHRoaXMucXVlcnkgPSByZXN0LnNsaWNlKHF1ZXN0aW9uSWR4ICsgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2VhcmNoID0gcmVzdC5zbGljZShxdWVzdGlvbklkeCwgaGFzaElkeCk7XG4gICAgICB0aGlzLnF1ZXJ5ID0gcmVzdC5zbGljZShxdWVzdGlvbklkeCArIDEsIGhhc2hJZHgpO1xuICAgIH1cbiAgICBpZiAocGFyc2VRdWVyeVN0cmluZykge1xuICAgICAgdGhpcy5xdWVyeSA9IHF1ZXJ5c3RyaW5nLnBhcnNlKHRoaXMucXVlcnkpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChwYXJzZVF1ZXJ5U3RyaW5nKSB7XG4gICAgLy8gbm8gcXVlcnkgc3RyaW5nLCBidXQgcGFyc2VRdWVyeVN0cmluZyBzdGlsbCByZXF1ZXN0ZWRcbiAgICB0aGlzLnNlYXJjaCA9ICcnO1xuICAgIHRoaXMucXVlcnkgPSB7fTtcbiAgfVxuXG4gIHZhciBmaXJzdElkeCA9IChxdWVzdGlvbklkeCAhPT0gLTEgJiZcbiAgICAgICAgICAgICAgICAgIChoYXNoSWR4ID09PSAtMSB8fCBxdWVzdGlvbklkeCA8IGhhc2hJZHgpXG4gICAgPyBxdWVzdGlvbklkeFxuICAgIDogaGFzaElkeCk7XG4gIGlmIChmaXJzdElkeCA9PT0gLTEpIHtcbiAgICBpZiAocmVzdC5sZW5ndGggPiAwKVxuICAgICAgdGhpcy5wYXRobmFtZSA9IHJlc3Q7XG4gIH0gZWxzZSBpZiAoZmlyc3RJZHggPiAwKSB7XG4gICAgdGhpcy5wYXRobmFtZSA9IHJlc3Quc2xpY2UoMCwgZmlyc3RJZHgpO1xuICB9XG4gIGlmIChzbGFzaGVkUHJvdG9jb2xbbG93ZXJQcm90b10gJiZcbiAgICAgIHRoaXMuaG9zdG5hbWUgJiYgIXRoaXMucGF0aG5hbWUpIHtcbiAgICB0aGlzLnBhdGhuYW1lID0gJy8nO1xuICB9XG5cbiAgLy8gdG8gc3VwcG9ydCBodHRwLnJlcXVlc3RcbiAgaWYgKHRoaXMucGF0aG5hbWUgfHwgdGhpcy5zZWFyY2gpIHtcbiAgICBjb25zdCBwID0gdGhpcy5wYXRobmFtZSB8fCAnJztcbiAgICBjb25zdCBzID0gdGhpcy5zZWFyY2ggfHwgJyc7XG4gICAgdGhpcy5wYXRoID0gcCArIHM7XG4gIH1cblxuICAvLyBmaW5hbGx5LCByZWNvbnN0cnVjdCB0aGUgaHJlZiBiYXNlZCBvbiB3aGF0IGhhcyBiZWVuIHZhbGlkYXRlZC5cbiAgdGhpcy5ocmVmID0gdGhpcy5mb3JtYXQoKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogaW1wcm92ZSBjb3ZlcmFnZSAqL1xuZnVuY3Rpb24gdmFsaWRhdGVIb3N0bmFtZShzZWxmLCByZXN0LCBob3N0bmFtZSkge1xuICBmb3IgKHZhciBpID0gMCwgbGFzdFBvczsgaSA8PSBob3N0bmFtZS5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjb2RlO1xuICAgIGlmIChpIDwgaG9zdG5hbWUubGVuZ3RoKVxuICAgICAgY29kZSA9IGhvc3RuYW1lLmNoYXJDb2RlQXQoaSk7XG4gICAgaWYgKGNvZGUgPT09IDQ2LyouKi8gfHwgaSA9PT0gaG9zdG5hbWUubGVuZ3RoKSB7XG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKSB7XG4gICAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDYzKSB7XG4gICAgICAgICAgc2VsZi5ob3N0bmFtZSA9IGhvc3RuYW1lLnNsaWNlKDAsIGxhc3RQb3MgKyA2Myk7XG4gICAgICAgICAgcmV0dXJuICcvJyArIGhvc3RuYW1lLnNsaWNlKGxhc3RQb3MgKyA2MykgKyByZXN0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2UgaWYgKChjb2RlID49IDQ4LyowKi8gJiYgY29kZSA8PSA1Ny8qOSovKSB8fFxuICAgICAgICAgICAgICAgKGNvZGUgPj0gOTcvKmEqLyAmJiBjb2RlIDw9IDEyMi8qeiovKSB8fFxuICAgICAgICAgICAgICAgY29kZSA9PT0gNDUvKi0qLyB8fFxuICAgICAgICAgICAgICAgKGNvZGUgPj0gNjUvKkEqLyAmJiBjb2RlIDw9IDkwLypaKi8pIHx8XG4gICAgICAgICAgICAgICBjb2RlID09PSA0My8qKyovIHx8XG4gICAgICAgICAgICAgICBjb2RlID09PSA5NS8qXyovIHx8XG4gICAgICAgICAgICAgICAvKiBCRUdJTiBNT05HTyBVUkkgUEFUQ0ggKi9cbiAgICAgICAgICAgICAgIGNvZGUgPT09IDQ0LyosKi8gfHxcbiAgICAgICAgICAgICAgIGNvZGUgPT09IDU4Lyo6Ki8gfHxcbiAgICAgICAgICAgICAgIC8qIEVORCBNT05HTyBVUkkgUEFUQ0ggKi9cbiAgICAgICAgICAgICAgIGNvZGUgPiAxMjcpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICAvLyBJbnZhbGlkIGhvc3QgY2hhcmFjdGVyXG4gICAgc2VsZi5ob3N0bmFtZSA9IGhvc3RuYW1lLnNsaWNlKDAsIGkpO1xuICAgIGlmIChpIDwgaG9zdG5hbWUubGVuZ3RoKVxuICAgICAgcmV0dXJuICcvJyArIGhvc3RuYW1lLnNsaWNlKGkpICsgcmVzdDtcbiAgICBicmVhaztcbiAgfVxufVxuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogaW1wcm92ZSBjb3ZlcmFnZSAqL1xuZnVuY3Rpb24gYXV0b0VzY2FwZVN0cihyZXN0KSB7XG4gIHZhciBuZXdSZXN0ID0gJyc7XG4gIHZhciBsYXN0UG9zID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgLy8gQXV0b21hdGljYWxseSBlc2NhcGUgYWxsIGRlbGltaXRlcnMgYW5kIHVud2lzZSBjaGFyYWN0ZXJzIGZyb20gUkZDIDIzOTZcbiAgICAvLyBBbHNvIGVzY2FwZSBzaW5nbGUgcXVvdGVzIGluIGNhc2Ugb2YgYW4gWFNTIGF0dGFja1xuICAgIHN3aXRjaCAocmVzdC5jaGFyQ29kZUF0KGkpKSB7XG4gICAgY2FzZSA5OiAgIC8vICdcXHQnXG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdSZXN0ICs9ICclMDknO1xuICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAxMDogIC8vICdcXG4nXG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdSZXN0ICs9ICclMEEnO1xuICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAxMzogIC8vICdcXHInXG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdSZXN0ICs9ICclMEQnO1xuICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAzMjogIC8vICcgJ1xuICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMClcbiAgICAgICAgbmV3UmVzdCArPSByZXN0LnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgbmV3UmVzdCArPSAnJTIwJztcbiAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMzQ6ICAvLyAnXCInXG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdSZXN0ICs9ICclMjInO1xuICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAzOTogIC8vICdcXCcnXG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdSZXN0ICs9ICclMjcnO1xuICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA2MDogIC8vICc8J1xuICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMClcbiAgICAgICAgbmV3UmVzdCArPSByZXN0LnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgbmV3UmVzdCArPSAnJTNDJztcbiAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNjI6ICAvLyAnPidcbiAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApXG4gICAgICAgIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgIG5ld1Jlc3QgKz0gJyUzRSc7XG4gICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDkyOiAgLy8gJ1xcXFwnXG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdSZXN0ICs9ICclNUMnO1xuICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA5NDogIC8vICdeJ1xuICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMClcbiAgICAgICAgbmV3UmVzdCArPSByZXN0LnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgbmV3UmVzdCArPSAnJTVFJztcbiAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgOTY6ICAvLyAnYCdcbiAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApXG4gICAgICAgIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgIG5ld1Jlc3QgKz0gJyU2MCc7XG4gICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDEyMzogLy8gJ3snXG4gICAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgICBuZXdSZXN0ICs9IHJlc3Quc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdSZXN0ICs9ICclN0InO1xuICAgICAgbGFzdFBvcyA9IGkgKyAxO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAxMjQ6IC8vICd8J1xuICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMClcbiAgICAgICAgbmV3UmVzdCArPSByZXN0LnNsaWNlKGxhc3RQb3MsIGkpO1xuICAgICAgbmV3UmVzdCArPSAnJTdDJztcbiAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMTI1OiAvLyAnfSdcbiAgICAgIGlmIChpIC0gbGFzdFBvcyA+IDApXG4gICAgICAgIG5ld1Jlc3QgKz0gcmVzdC5zbGljZShsYXN0UG9zLCBpKTtcbiAgICAgIG5ld1Jlc3QgKz0gJyU3RCc7XG4gICAgICBsYXN0UG9zID0gaSArIDE7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgaWYgKGxhc3RQb3MgPT09IDApXG4gICAgcmV0dXJuO1xuICBpZiAobGFzdFBvcyA8IHJlc3QubGVuZ3RoKVxuICAgIHJldHVybiBuZXdSZXN0ICsgcmVzdC5zbGljZShsYXN0UG9zKTtcbiAgZWxzZVxuICAgIHJldHVybiBuZXdSZXN0O1xufVxuXG4vLyBmb3JtYXQgYSBwYXJzZWQgb2JqZWN0IGludG8gYSB1cmwgc3RyaW5nXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogaW1wcm92ZSBjb3ZlcmFnZSAqL1xuZnVuY3Rpb24gdXJsRm9ybWF0KG9iaikge1xuICAvLyBlbnN1cmUgaXQncyBhbiBvYmplY3QsIGFuZCBub3QgYSBzdHJpbmcgdXJsLlxuICAvLyBJZiBpdCdzIGFuIG9iaiwgdGhpcyBpcyBhIG5vLW9wLlxuICAvLyB0aGlzIHdheSwgeW91IGNhbiBjYWxsIHVybF9mb3JtYXQoKSBvbiBzdHJpbmdzXG4gIC8vIHRvIGNsZWFuIHVwIHBvdGVudGlhbGx5IHdvbmt5IHVybHMuXG4gIGlmICh0eXBlb2Ygb2JqID09PSAnc3RyaW5nJykgb2JqID0gdXJsUGFyc2Uob2JqKTtcblxuICBlbHNlIGlmICh0eXBlb2Ygb2JqICE9PSAnb2JqZWN0JyB8fCBvYmogPT09IG51bGwpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignUGFyYW1ldGVyIFwidXJsT2JqXCIgbXVzdCBiZSBhbiBvYmplY3QsIG5vdCAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iaiA9PT0gbnVsbCA/ICdudWxsJyA6IHR5cGVvZiBvYmopO1xuXG4gIGVsc2UgaWYgKCEob2JqIGluc3RhbmNlb2YgVXJsKSkgcmV0dXJuIFVybC5wcm90b3R5cGUuZm9ybWF0LmNhbGwob2JqKTtcblxuICByZXR1cm4gb2JqLmZvcm1hdCgpO1xufVxuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogaW1wcm92ZSBjb3ZlcmFnZSAqL1xuVXJsLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGF1dGggPSB0aGlzLmF1dGggfHwgJyc7XG4gIGlmIChhdXRoKSB7XG4gICAgYXV0aCA9IGVuY29kZUF1dGgoYXV0aCk7XG4gICAgYXV0aCArPSAnQCc7XG4gIH1cblxuICB2YXIgcHJvdG9jb2wgPSB0aGlzLnByb3RvY29sIHx8ICcnO1xuICB2YXIgcGF0aG5hbWUgPSB0aGlzLnBhdGhuYW1lIHx8ICcnO1xuICB2YXIgaGFzaCA9IHRoaXMuaGFzaCB8fCAnJztcbiAgdmFyIGhvc3QgPSBmYWxzZTtcbiAgdmFyIHF1ZXJ5ID0gJyc7XG5cbiAgaWYgKHRoaXMuaG9zdCkge1xuICAgIGhvc3QgPSBhdXRoICsgdGhpcy5ob3N0O1xuICB9IGVsc2UgaWYgKHRoaXMuaG9zdG5hbWUpIHtcbiAgICBob3N0ID0gYXV0aCArICh0aGlzLmhvc3RuYW1lLmluZGV4T2YoJzonKSA9PT0gLTEgP1xuICAgICAgdGhpcy5ob3N0bmFtZSA6XG4gICAgICAnWycgKyB0aGlzLmhvc3RuYW1lICsgJ10nKTtcbiAgICBpZiAodGhpcy5wb3J0KSB7XG4gICAgICBob3N0ICs9ICc6JyArIHRoaXMucG9ydDtcbiAgICB9XG4gIH1cblxuICBpZiAodGhpcy5xdWVyeSAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5xdWVyeSA9PT0gJ29iamVjdCcpXG4gICAgcXVlcnkgPSBxdWVyeXN0cmluZy5zdHJpbmdpZnkodGhpcy5xdWVyeSk7XG5cbiAgdmFyIHNlYXJjaCA9IHRoaXMuc2VhcmNoIHx8IChxdWVyeSAmJiAoJz8nICsgcXVlcnkpKSB8fCAnJztcblxuICBpZiAocHJvdG9jb2wgJiYgcHJvdG9jb2wuY2hhckNvZGVBdChwcm90b2NvbC5sZW5ndGggLSAxKSAhPT0gNTgvKjoqLylcbiAgICBwcm90b2NvbCArPSAnOic7XG5cbiAgdmFyIG5ld1BhdGhuYW1lID0gJyc7XG4gIHZhciBsYXN0UG9zID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRobmFtZS5sZW5ndGg7ICsraSkge1xuICAgIHN3aXRjaCAocGF0aG5hbWUuY2hhckNvZGVBdChpKSkge1xuICAgIGNhc2UgMzU6IC8vICcjJ1xuICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMClcbiAgICAgICAgbmV3UGF0aG5hbWUgKz0gcGF0aG5hbWUuc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdQYXRobmFtZSArPSAnJTIzJztcbiAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNjM6IC8vICc/J1xuICAgICAgaWYgKGkgLSBsYXN0UG9zID4gMClcbiAgICAgICAgbmV3UGF0aG5hbWUgKz0gcGF0aG5hbWUuc2xpY2UobGFzdFBvcywgaSk7XG4gICAgICBuZXdQYXRobmFtZSArPSAnJTNGJztcbiAgICAgIGxhc3RQb3MgPSBpICsgMTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBpZiAobGFzdFBvcyA+IDApIHtcbiAgICBpZiAobGFzdFBvcyAhPT0gcGF0aG5hbWUubGVuZ3RoKVxuICAgICAgcGF0aG5hbWUgPSBuZXdQYXRobmFtZSArIHBhdGhuYW1lLnNsaWNlKGxhc3RQb3MpO1xuICAgIGVsc2VcbiAgICAgIHBhdGhuYW1lID0gbmV3UGF0aG5hbWU7XG4gIH1cblxuICAvLyBvbmx5IHRoZSBzbGFzaGVkUHJvdG9jb2xzIGdldCB0aGUgLy8uICBOb3QgbWFpbHRvOiwgeG1wcDosIGV0Yy5cbiAgLy8gdW5sZXNzIHRoZXkgaGFkIHRoZW0gdG8gYmVnaW4gd2l0aC5cbiAgaWYgKHRoaXMuc2xhc2hlcyB8fFxuICAgICAgKCFwcm90b2NvbCB8fCBzbGFzaGVkUHJvdG9jb2xbcHJvdG9jb2xdKSAmJiBob3N0ICE9PSBmYWxzZSkge1xuICAgIGhvc3QgPSAnLy8nICsgKGhvc3QgfHwgJycpO1xuICAgIGlmIChwYXRobmFtZSAmJiBwYXRobmFtZS5jaGFyQ29kZUF0KDApICE9PSA0Ny8qLyovKVxuICAgICAgcGF0aG5hbWUgPSAnLycgKyBwYXRobmFtZTtcbiAgfSBlbHNlIGlmICghaG9zdCkge1xuICAgIGhvc3QgPSAnJztcbiAgfVxuXG4gIHNlYXJjaCA9IHNlYXJjaC5yZXBsYWNlKCcjJywgJyUyMycpO1xuXG4gIGlmIChoYXNoICYmIGhhc2guY2hhckNvZGVBdCgwKSAhPT0gMzUvKiMqLykgaGFzaCA9ICcjJyArIGhhc2g7XG4gIGlmIChzZWFyY2ggJiYgc2VhcmNoLmNoYXJDb2RlQXQoMCkgIT09IDYzLyo/Ki8pIHNlYXJjaCA9ICc/JyArIHNlYXJjaDtcblxuICByZXR1cm4gcHJvdG9jb2wgKyBob3N0ICsgcGF0aG5hbWUgKyBzZWFyY2ggKyBoYXNoO1xufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cbmZ1bmN0aW9uIHVybFJlc29sdmUoc291cmNlLCByZWxhdGl2ZSkge1xuICByZXR1cm4gdXJsUGFyc2Uoc291cmNlLCBmYWxzZSwgdHJ1ZSkucmVzb2x2ZShyZWxhdGl2ZSk7XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5VcmwucHJvdG90eXBlLnJlc29sdmUgPSBmdW5jdGlvbihyZWxhdGl2ZSkge1xuICByZXR1cm4gdGhpcy5yZXNvbHZlT2JqZWN0KHVybFBhcnNlKHJlbGF0aXZlLCBmYWxzZSwgdHJ1ZSkpLmZvcm1hdCgpO1xufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cbmZ1bmN0aW9uIHVybFJlc29sdmVPYmplY3Qoc291cmNlLCByZWxhdGl2ZSkge1xuICBpZiAoIXNvdXJjZSkgcmV0dXJuIHJlbGF0aXZlO1xuICByZXR1cm4gdXJsUGFyc2Uoc291cmNlLCBmYWxzZSwgdHJ1ZSkucmVzb2x2ZU9iamVjdChyZWxhdGl2ZSk7XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBpbXByb3ZlIGNvdmVyYWdlICovXG5VcmwucHJvdG90eXBlLnJlc29sdmVPYmplY3QgPSBmdW5jdGlvbihyZWxhdGl2ZSkge1xuICBpZiAodHlwZW9mIHJlbGF0aXZlID09PSAnc3RyaW5nJykge1xuICAgIHZhciByZWwgPSBuZXcgVXJsKCk7XG4gICAgcmVsLnBhcnNlKHJlbGF0aXZlLCBmYWxzZSwgdHJ1ZSk7XG4gICAgcmVsYXRpdmUgPSByZWw7XG4gIH1cblxuICB2YXIgcmVzdWx0ID0gbmV3IFVybCgpO1xuICB2YXIgdGtleXMgPSBPYmplY3Qua2V5cyh0aGlzKTtcbiAgZm9yICh2YXIgdGsgPSAwOyB0ayA8IHRrZXlzLmxlbmd0aDsgdGsrKykge1xuICAgIHZhciB0a2V5ID0gdGtleXNbdGtdO1xuICAgIHJlc3VsdFt0a2V5XSA9IHRoaXNbdGtleV07XG4gIH1cblxuICAvLyBoYXNoIGlzIGFsd2F5cyBvdmVycmlkZGVuLCBubyBtYXR0ZXIgd2hhdC5cbiAgLy8gZXZlbiBocmVmPVwiXCIgd2lsbCByZW1vdmUgaXQuXG4gIHJlc3VsdC5oYXNoID0gcmVsYXRpdmUuaGFzaDtcblxuICAvLyBpZiB0aGUgcmVsYXRpdmUgdXJsIGlzIGVtcHR5LCB0aGVuIHRoZXJlJ3Mgbm90aGluZyBsZWZ0IHRvIGRvIGhlcmUuXG4gIGlmIChyZWxhdGl2ZS5ocmVmID09PSAnJykge1xuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBocmVmcyBsaWtlIC8vZm9vL2JhciBhbHdheXMgY3V0IHRvIHRoZSBwcm90b2NvbC5cbiAgaWYgKHJlbGF0aXZlLnNsYXNoZXMgJiYgIXJlbGF0aXZlLnByb3RvY29sKSB7XG4gICAgLy8gdGFrZSBldmVyeXRoaW5nIGV4Y2VwdCB0aGUgcHJvdG9jb2wgZnJvbSByZWxhdGl2ZVxuICAgIHZhciBya2V5cyA9IE9iamVjdC5rZXlzKHJlbGF0aXZlKTtcbiAgICBmb3IgKHZhciByayA9IDA7IHJrIDwgcmtleXMubGVuZ3RoOyByaysrKSB7XG4gICAgICB2YXIgcmtleSA9IHJrZXlzW3JrXTtcbiAgICAgIGlmIChya2V5ICE9PSAncHJvdG9jb2wnKVxuICAgICAgICByZXN1bHRbcmtleV0gPSByZWxhdGl2ZVtya2V5XTtcbiAgICB9XG5cbiAgICAvL3VybFBhcnNlIGFwcGVuZHMgdHJhaWxpbmcgLyB0byB1cmxzIGxpa2UgaHR0cDovL3d3dy5leGFtcGxlLmNvbVxuICAgIGlmIChzbGFzaGVkUHJvdG9jb2xbcmVzdWx0LnByb3RvY29sXSAmJlxuICAgICAgICByZXN1bHQuaG9zdG5hbWUgJiYgIXJlc3VsdC5wYXRobmFtZSkge1xuICAgICAgcmVzdWx0LnBhdGggPSByZXN1bHQucGF0aG5hbWUgPSAnLyc7XG4gICAgfVxuXG4gICAgcmVzdWx0LmhyZWYgPSByZXN1bHQuZm9ybWF0KCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGlmIChyZWxhdGl2ZS5wcm90b2NvbCAmJiByZWxhdGl2ZS5wcm90b2NvbCAhPT0gcmVzdWx0LnByb3RvY29sKSB7XG4gICAgLy8gaWYgaXQncyBhIGtub3duIHVybCBwcm90b2NvbCwgdGhlbiBjaGFuZ2luZ1xuICAgIC8vIHRoZSBwcm90b2NvbCBkb2VzIHdlaXJkIHRoaW5nc1xuICAgIC8vIGZpcnN0LCBpZiBpdCdzIG5vdCBmaWxlOiwgdGhlbiB3ZSBNVVNUIGhhdmUgYSBob3N0LFxuICAgIC8vIGFuZCBpZiB0aGVyZSB3YXMgYSBwYXRoXG4gICAgLy8gdG8gYmVnaW4gd2l0aCwgdGhlbiB3ZSBNVVNUIGhhdmUgYSBwYXRoLlxuICAgIC8vIGlmIGl0IGlzIGZpbGU6LCB0aGVuIHRoZSBob3N0IGlzIGRyb3BwZWQsXG4gICAgLy8gYmVjYXVzZSB0aGF0J3Mga25vd24gdG8gYmUgaG9zdGxlc3MuXG4gICAgLy8gYW55dGhpbmcgZWxzZSBpcyBhc3N1bWVkIHRvIGJlIGFic29sdXRlLlxuICAgIGlmICghc2xhc2hlZFByb3RvY29sW3JlbGF0aXZlLnByb3RvY29sXSkge1xuICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhyZWxhdGl2ZSk7XG4gICAgICBmb3IgKHZhciB2ID0gMDsgdiA8IGtleXMubGVuZ3RoOyB2KyspIHtcbiAgICAgICAgdmFyIGsgPSBrZXlzW3ZdO1xuICAgICAgICByZXN1bHRba10gPSByZWxhdGl2ZVtrXTtcbiAgICAgIH1cbiAgICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICByZXN1bHQucHJvdG9jb2wgPSByZWxhdGl2ZS5wcm90b2NvbDtcbiAgICBpZiAoIXJlbGF0aXZlLmhvc3QgJiZcbiAgICAgICAgIS9eZmlsZTo/JC8udGVzdChyZWxhdGl2ZS5wcm90b2NvbCkgJiZcbiAgICAgICAgIWhvc3RsZXNzUHJvdG9jb2xbcmVsYXRpdmUucHJvdG9jb2xdKSB7XG4gICAgICBjb25zdCByZWxQYXRoID0gKHJlbGF0aXZlLnBhdGhuYW1lIHx8ICcnKS5zcGxpdCgnLycpO1xuICAgICAgd2hpbGUgKHJlbFBhdGgubGVuZ3RoICYmICEocmVsYXRpdmUuaG9zdCA9IHJlbFBhdGguc2hpZnQoKSkpO1xuICAgICAgaWYgKCFyZWxhdGl2ZS5ob3N0KSByZWxhdGl2ZS5ob3N0ID0gJyc7XG4gICAgICBpZiAoIXJlbGF0aXZlLmhvc3RuYW1lKSByZWxhdGl2ZS5ob3N0bmFtZSA9ICcnO1xuICAgICAgaWYgKHJlbFBhdGhbMF0gIT09ICcnKSByZWxQYXRoLnVuc2hpZnQoJycpO1xuICAgICAgaWYgKHJlbFBhdGgubGVuZ3RoIDwgMikgcmVsUGF0aC51bnNoaWZ0KCcnKTtcbiAgICAgIHJlc3VsdC5wYXRobmFtZSA9IHJlbFBhdGguam9pbignLycpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQucGF0aG5hbWUgPSByZWxhdGl2ZS5wYXRobmFtZTtcbiAgICB9XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgICByZXN1bHQuaG9zdCA9IHJlbGF0aXZlLmhvc3QgfHwgJyc7XG4gICAgcmVzdWx0LmF1dGggPSByZWxhdGl2ZS5hdXRoO1xuICAgIHJlc3VsdC5ob3N0bmFtZSA9IHJlbGF0aXZlLmhvc3RuYW1lIHx8IHJlbGF0aXZlLmhvc3Q7XG4gICAgcmVzdWx0LnBvcnQgPSByZWxhdGl2ZS5wb3J0O1xuICAgIC8vIHRvIHN1cHBvcnQgaHR0cC5yZXF1ZXN0XG4gICAgaWYgKHJlc3VsdC5wYXRobmFtZSB8fCByZXN1bHQuc2VhcmNoKSB7XG4gICAgICB2YXIgcCA9IHJlc3VsdC5wYXRobmFtZSB8fCAnJztcbiAgICAgIHZhciBzID0gcmVzdWx0LnNlYXJjaCB8fCAnJztcbiAgICAgIHJlc3VsdC5wYXRoID0gcCArIHM7XG4gICAgfVxuICAgIHJlc3VsdC5zbGFzaGVzID0gcmVzdWx0LnNsYXNoZXMgfHwgcmVsYXRpdmUuc2xhc2hlcztcbiAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgdmFyIGlzU291cmNlQWJzID0gKHJlc3VsdC5wYXRobmFtZSAmJiByZXN1bHQucGF0aG5hbWUuY2hhckF0KDApID09PSAnLycpO1xuICB2YXIgaXNSZWxBYnMgPSAoXG4gICAgcmVsYXRpdmUuaG9zdCB8fFxuICAgICAgcmVsYXRpdmUucGF0aG5hbWUgJiYgcmVsYXRpdmUucGF0aG5hbWUuY2hhckF0KDApID09PSAnLydcbiAgKTtcbiAgdmFyIG11c3RFbmRBYnMgPSAoaXNSZWxBYnMgfHwgaXNTb3VyY2VBYnMgfHxcbiAgICAgICAgICAgICAgICAgICAgKHJlc3VsdC5ob3N0ICYmIHJlbGF0aXZlLnBhdGhuYW1lKSk7XG4gIHZhciByZW1vdmVBbGxEb3RzID0gbXVzdEVuZEFicztcbiAgdmFyIHNyY1BhdGggPSByZXN1bHQucGF0aG5hbWUgJiYgcmVzdWx0LnBhdGhuYW1lLnNwbGl0KCcvJykgfHwgW107XG4gIHZhciByZWxQYXRoID0gcmVsYXRpdmUucGF0aG5hbWUgJiYgcmVsYXRpdmUucGF0aG5hbWUuc3BsaXQoJy8nKSB8fCBbXTtcbiAgdmFyIHBzeWNob3RpYyA9IHJlc3VsdC5wcm90b2NvbCAmJiAhc2xhc2hlZFByb3RvY29sW3Jlc3VsdC5wcm90b2NvbF07XG5cbiAgLy8gaWYgdGhlIHVybCBpcyBhIG5vbi1zbGFzaGVkIHVybCwgdGhlbiByZWxhdGl2ZVxuICAvLyBsaW5rcyBsaWtlIC4uLy4uIHNob3VsZCBiZSBhYmxlXG4gIC8vIHRvIGNyYXdsIHVwIHRvIHRoZSBob3N0bmFtZSwgYXMgd2VsbC4gIFRoaXMgaXMgc3RyYW5nZS5cbiAgLy8gcmVzdWx0LnByb3RvY29sIGhhcyBhbHJlYWR5IGJlZW4gc2V0IGJ5IG5vdy5cbiAgLy8gTGF0ZXIgb24sIHB1dCB0aGUgZmlyc3QgcGF0aCBwYXJ0IGludG8gdGhlIGhvc3QgZmllbGQuXG4gIGlmIChwc3ljaG90aWMpIHtcbiAgICByZXN1bHQuaG9zdG5hbWUgPSAnJztcbiAgICByZXN1bHQucG9ydCA9IG51bGw7XG4gICAgaWYgKHJlc3VsdC5ob3N0KSB7XG4gICAgICBpZiAoc3JjUGF0aFswXSA9PT0gJycpIHNyY1BhdGhbMF0gPSByZXN1bHQuaG9zdDtcbiAgICAgIGVsc2Ugc3JjUGF0aC51bnNoaWZ0KHJlc3VsdC5ob3N0KTtcbiAgICB9XG4gICAgcmVzdWx0Lmhvc3QgPSAnJztcbiAgICBpZiAocmVsYXRpdmUucHJvdG9jb2wpIHtcbiAgICAgIHJlbGF0aXZlLmhvc3RuYW1lID0gbnVsbDtcbiAgICAgIHJlbGF0aXZlLnBvcnQgPSBudWxsO1xuICAgICAgaWYgKHJlbGF0aXZlLmhvc3QpIHtcbiAgICAgICAgaWYgKHJlbFBhdGhbMF0gPT09ICcnKSByZWxQYXRoWzBdID0gcmVsYXRpdmUuaG9zdDtcbiAgICAgICAgZWxzZSByZWxQYXRoLnVuc2hpZnQocmVsYXRpdmUuaG9zdCk7XG4gICAgICB9XG4gICAgICByZWxhdGl2ZS5ob3N0ID0gbnVsbDtcbiAgICB9XG4gICAgbXVzdEVuZEFicyA9IG11c3RFbmRBYnMgJiYgKHJlbFBhdGhbMF0gPT09ICcnIHx8IHNyY1BhdGhbMF0gPT09ICcnKTtcbiAgfVxuXG4gIGlmIChpc1JlbEFicykge1xuICAgIC8vIGl0J3MgYWJzb2x1dGUuXG4gICAgcmVzdWx0Lmhvc3QgPSAocmVsYXRpdmUuaG9zdCB8fCByZWxhdGl2ZS5ob3N0ID09PSAnJykgP1xuICAgICAgcmVsYXRpdmUuaG9zdCA6IHJlc3VsdC5ob3N0O1xuICAgIHJlc3VsdC5ob3N0bmFtZSA9IChyZWxhdGl2ZS5ob3N0bmFtZSB8fCByZWxhdGl2ZS5ob3N0bmFtZSA9PT0gJycpID9cbiAgICAgIHJlbGF0aXZlLmhvc3RuYW1lIDogcmVzdWx0Lmhvc3RuYW1lO1xuICAgIHJlc3VsdC5zZWFyY2ggPSByZWxhdGl2ZS5zZWFyY2g7XG4gICAgcmVzdWx0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XG4gICAgc3JjUGF0aCA9IHJlbFBhdGg7XG4gICAgLy8gZmFsbCB0aHJvdWdoIHRvIHRoZSBkb3QtaGFuZGxpbmcgYmVsb3cuXG4gIH0gZWxzZSBpZiAocmVsUGF0aC5sZW5ndGgpIHtcbiAgICAvLyBpdCdzIHJlbGF0aXZlXG4gICAgLy8gdGhyb3cgYXdheSB0aGUgZXhpc3RpbmcgZmlsZSwgYW5kIHRha2UgdGhlIG5ldyBwYXRoIGluc3RlYWQuXG4gICAgaWYgKCFzcmNQYXRoKSBzcmNQYXRoID0gW107XG4gICAgc3JjUGF0aC5wb3AoKTtcbiAgICBzcmNQYXRoID0gc3JjUGF0aC5jb25jYXQocmVsUGF0aCk7XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgfSBlbHNlIGlmIChyZWxhdGl2ZS5zZWFyY2ggIT09IG51bGwgJiYgcmVsYXRpdmUuc2VhcmNoICE9PSB1bmRlZmluZWQpIHtcbiAgICAvLyBqdXN0IHB1bGwgb3V0IHRoZSBzZWFyY2guXG4gICAgLy8gbGlrZSBocmVmPSc/Zm9vJy5cbiAgICAvLyBQdXQgdGhpcyBhZnRlciB0aGUgb3RoZXIgdHdvIGNhc2VzIGJlY2F1c2UgaXQgc2ltcGxpZmllcyB0aGUgYm9vbGVhbnNcbiAgICBpZiAocHN5Y2hvdGljKSB7XG4gICAgICByZXN1bHQuaG9zdG5hbWUgPSByZXN1bHQuaG9zdCA9IHNyY1BhdGguc2hpZnQoKTtcbiAgICAgIC8vb2NjYXNpb25hbGx5IHRoZSBhdXRoIGNhbiBnZXQgc3R1Y2sgb25seSBpbiBob3N0XG4gICAgICAvL3RoaXMgZXNwZWNpYWxseSBoYXBwZW5zIGluIGNhc2VzIGxpa2VcbiAgICAgIC8vdXJsLnJlc29sdmVPYmplY3QoJ21haWx0bzpsb2NhbDFAZG9tYWluMScsICdsb2NhbDJAZG9tYWluMicpXG4gICAgICBjb25zdCBhdXRoSW5Ib3N0ID0gcmVzdWx0Lmhvc3QgJiYgcmVzdWx0Lmhvc3QuaW5kZXhPZignQCcpID4gMCA/XG4gICAgICAgIHJlc3VsdC5ob3N0LnNwbGl0KCdAJykgOiBmYWxzZTtcbiAgICAgIGlmIChhdXRoSW5Ib3N0KSB7XG4gICAgICAgIHJlc3VsdC5hdXRoID0gYXV0aEluSG9zdC5zaGlmdCgpO1xuICAgICAgICByZXN1bHQuaG9zdCA9IHJlc3VsdC5ob3N0bmFtZSA9IGF1dGhJbkhvc3Quc2hpZnQoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgICAvL3RvIHN1cHBvcnQgaHR0cC5yZXF1ZXN0XG4gICAgaWYgKHJlc3VsdC5wYXRobmFtZSAhPT0gbnVsbCB8fCByZXN1bHQuc2VhcmNoICE9PSBudWxsKSB7XG4gICAgICByZXN1bHQucGF0aCA9IChyZXN1bHQucGF0aG5hbWUgPyByZXN1bHQucGF0aG5hbWUgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAocmVzdWx0LnNlYXJjaCA/IHJlc3VsdC5zZWFyY2ggOiAnJyk7XG4gICAgfVxuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBpZiAoIXNyY1BhdGgubGVuZ3RoKSB7XG4gICAgLy8gbm8gcGF0aCBhdCBhbGwuICBlYXN5LlxuICAgIC8vIHdlJ3ZlIGFscmVhZHkgaGFuZGxlZCB0aGUgb3RoZXIgc3R1ZmYgYWJvdmUuXG4gICAgcmVzdWx0LnBhdGhuYW1lID0gbnVsbDtcbiAgICAvL3RvIHN1cHBvcnQgaHR0cC5yZXF1ZXN0XG4gICAgaWYgKHJlc3VsdC5zZWFyY2gpIHtcbiAgICAgIHJlc3VsdC5wYXRoID0gJy8nICsgcmVzdWx0LnNlYXJjaDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0LnBhdGggPSBudWxsO1xuICAgIH1cbiAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gaWYgYSB1cmwgRU5EcyBpbiAuIG9yIC4uLCB0aGVuIGl0IG11c3QgZ2V0IGEgdHJhaWxpbmcgc2xhc2guXG4gIC8vIGhvd2V2ZXIsIGlmIGl0IGVuZHMgaW4gYW55dGhpbmcgZWxzZSBub24tc2xhc2h5LFxuICAvLyB0aGVuIGl0IG11c3QgTk9UIGdldCBhIHRyYWlsaW5nIHNsYXNoLlxuICB2YXIgbGFzdCA9IHNyY1BhdGguc2xpY2UoLTEpWzBdO1xuICB2YXIgaGFzVHJhaWxpbmdTbGFzaCA9IChcbiAgICAocmVzdWx0Lmhvc3QgfHwgcmVsYXRpdmUuaG9zdCB8fCBzcmNQYXRoLmxlbmd0aCA+IDEpICYmXG4gICAgICAobGFzdCA9PT0gJy4nIHx8IGxhc3QgPT09ICcuLicpIHx8IGxhc3QgPT09ICcnKTtcblxuICAvLyBzdHJpcCBzaW5nbGUgZG90cywgcmVzb2x2ZSBkb3VibGUgZG90cyB0byBwYXJlbnQgZGlyXG4gIC8vIGlmIHRoZSBwYXRoIHRyaWVzIHRvIGdvIGFib3ZlIHRoZSByb290LCBgdXBgIGVuZHMgdXAgPiAwXG4gIHZhciB1cCA9IDA7XG4gIGZvciAodmFyIGkgPSBzcmNQYXRoLmxlbmd0aDsgaSA+PSAwOyBpLS0pIHtcbiAgICBsYXN0ID0gc3JjUGF0aFtpXTtcbiAgICBpZiAobGFzdCA9PT0gJy4nKSB7XG4gICAgICBzcGxpY2VPbmUoc3JjUGF0aCwgaSk7XG4gICAgfSBlbHNlIGlmIChsYXN0ID09PSAnLi4nKSB7XG4gICAgICBzcGxpY2VPbmUoc3JjUGF0aCwgaSk7XG4gICAgICB1cCsrO1xuICAgIH0gZWxzZSBpZiAodXApIHtcbiAgICAgIHNwbGljZU9uZShzcmNQYXRoLCBpKTtcbiAgICAgIHVwLS07XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlIHBhdGggaXMgYWxsb3dlZCB0byBnbyBhYm92ZSB0aGUgcm9vdCwgcmVzdG9yZSBsZWFkaW5nIC4uc1xuICBpZiAoIW11c3RFbmRBYnMgJiYgIXJlbW92ZUFsbERvdHMpIHtcbiAgICBmb3IgKDsgdXAtLTsgdXApIHtcbiAgICAgIHNyY1BhdGgudW5zaGlmdCgnLi4nKTtcbiAgICB9XG4gIH1cblxuICBpZiAobXVzdEVuZEFicyAmJiBzcmNQYXRoWzBdICE9PSAnJyAmJlxuICAgICAgKCFzcmNQYXRoWzBdIHx8IHNyY1BhdGhbMF0uY2hhckF0KDApICE9PSAnLycpKSB7XG4gICAgc3JjUGF0aC51bnNoaWZ0KCcnKTtcbiAgfVxuXG4gIGlmIChoYXNUcmFpbGluZ1NsYXNoICYmIChzcmNQYXRoLmpvaW4oJy8nKS5zdWJzdHIoLTEpICE9PSAnLycpKSB7XG4gICAgc3JjUGF0aC5wdXNoKCcnKTtcbiAgfVxuXG4gIHZhciBpc0Fic29sdXRlID0gc3JjUGF0aFswXSA9PT0gJycgfHxcbiAgICAgIChzcmNQYXRoWzBdICYmIHNyY1BhdGhbMF0uY2hhckF0KDApID09PSAnLycpO1xuXG4gIC8vIHB1dCB0aGUgaG9zdCBiYWNrXG4gIGlmIChwc3ljaG90aWMpIHtcbiAgICByZXN1bHQuaG9zdG5hbWUgPSByZXN1bHQuaG9zdCA9IGlzQWJzb2x1dGUgPyAnJyA6XG4gICAgICBzcmNQYXRoLmxlbmd0aCA/IHNyY1BhdGguc2hpZnQoKSA6ICcnO1xuICAgIC8vb2NjYXNpb25hbGx5IHRoZSBhdXRoIGNhbiBnZXQgc3R1Y2sgb25seSBpbiBob3N0XG4gICAgLy90aGlzIGVzcGVjaWFsbHkgaGFwcGVucyBpbiBjYXNlcyBsaWtlXG4gICAgLy91cmwucmVzb2x2ZU9iamVjdCgnbWFpbHRvOmxvY2FsMUBkb21haW4xJywgJ2xvY2FsMkBkb21haW4yJylcbiAgICBjb25zdCBhdXRoSW5Ib3N0ID0gcmVzdWx0Lmhvc3QgJiYgcmVzdWx0Lmhvc3QuaW5kZXhPZignQCcpID4gMCA/XG4gICAgICByZXN1bHQuaG9zdC5zcGxpdCgnQCcpIDogZmFsc2U7XG4gICAgaWYgKGF1dGhJbkhvc3QpIHtcbiAgICAgIHJlc3VsdC5hdXRoID0gYXV0aEluSG9zdC5zaGlmdCgpO1xuICAgICAgcmVzdWx0Lmhvc3QgPSByZXN1bHQuaG9zdG5hbWUgPSBhdXRoSW5Ib3N0LnNoaWZ0KCk7XG4gICAgfVxuICB9XG5cbiAgbXVzdEVuZEFicyA9IG11c3RFbmRBYnMgfHwgKHJlc3VsdC5ob3N0ICYmIHNyY1BhdGgubGVuZ3RoKTtcblxuICBpZiAobXVzdEVuZEFicyAmJiAhaXNBYnNvbHV0ZSkge1xuICAgIHNyY1BhdGgudW5zaGlmdCgnJyk7XG4gIH1cblxuICBpZiAoIXNyY1BhdGgubGVuZ3RoKSB7XG4gICAgcmVzdWx0LnBhdGhuYW1lID0gbnVsbDtcbiAgICByZXN1bHQucGF0aCA9IG51bGw7XG4gIH0gZWxzZSB7XG4gICAgcmVzdWx0LnBhdGhuYW1lID0gc3JjUGF0aC5qb2luKCcvJyk7XG4gIH1cblxuICAvL3RvIHN1cHBvcnQgcmVxdWVzdC5odHRwXG4gIGlmIChyZXN1bHQucGF0aG5hbWUgIT09IG51bGwgfHwgcmVzdWx0LnNlYXJjaCAhPT0gbnVsbCkge1xuICAgIHJlc3VsdC5wYXRoID0gKHJlc3VsdC5wYXRobmFtZSA/IHJlc3VsdC5wYXRobmFtZSA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAocmVzdWx0LnNlYXJjaCA/IHJlc3VsdC5zZWFyY2ggOiAnJyk7XG4gIH1cbiAgcmVzdWx0LmF1dGggPSByZWxhdGl2ZS5hdXRoIHx8IHJlc3VsdC5hdXRoO1xuICByZXN1bHQuc2xhc2hlcyA9IHJlc3VsdC5zbGFzaGVzIHx8IHJlbGF0aXZlLnNsYXNoZXM7XG4gIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICByZXR1cm4gcmVzdWx0O1xufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cblVybC5wcm90b3R5cGUucGFyc2VIb3N0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBob3N0ID0gdGhpcy5ob3N0O1xuICB2YXIgcG9ydCA9IHBvcnRQYXR0ZXJuLmV4ZWMoaG9zdCk7XG4gIGlmIChwb3J0KSB7XG4gICAgcG9ydCA9IHBvcnRbMF07XG4gICAgaWYgKHBvcnQgIT09ICc6Jykge1xuICAgICAgdGhpcy5wb3J0ID0gcG9ydC5zbGljZSgxKTtcbiAgICB9XG4gICAgaG9zdCA9IGhvc3Quc2xpY2UoMCwgaG9zdC5sZW5ndGggLSBwb3J0Lmxlbmd0aCk7XG4gIH1cbiAgaWYgKGhvc3QpIHRoaXMuaG9zdG5hbWUgPSBob3N0O1xufTtcblxuLy8gQWJvdXQgMS41eCBmYXN0ZXIgdGhhbiB0aGUgdHdvLWFyZyB2ZXJzaW9uIG9mIEFycmF5I3NwbGljZSgpLlxuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbnZhciBoZXhUYWJsZSA9IG5ldyBBcnJheSgyNTYpO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSlcbiAgaGV4VGFibGVbaV0gPSAnJScgKyAoKGkgPCAxNiA/ICcwJyA6ICcnKSArIGkudG9TdHJpbmcoMTYpKS50b1VwcGVyQ2FzZSgpO1xuLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGltcHJvdmUgY292ZXJhZ2UgKi9cbmZ1bmN0aW9uIGVuY29kZUF1dGgoc3RyKSB7XG4gIC8vIGZhc3RlciBlbmNvZGVVUklDb21wb25lbnQgYWx0ZXJuYXRpdmUgZm9yIGVuY29kaW5nIGF1dGggdXJpIGNvbXBvbmVudHNcbiAgdmFyIG91dCA9ICcnO1xuICB2YXIgbGFzdFBvcyA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGMgPSBzdHIuY2hhckNvZGVBdChpKTtcblxuICAgIC8vIFRoZXNlIGNoYXJhY3RlcnMgZG8gbm90IG5lZWQgZXNjYXBpbmc6XG4gICAgLy8gISAtIC4gXyB+XG4gICAgLy8gJyAoICkgKiA6XG4gICAgLy8gZGlnaXRzXG4gICAgLy8gYWxwaGEgKHVwcGVyY2FzZSlcbiAgICAvLyBhbHBoYSAobG93ZXJjYXNlKVxuICAgIGlmIChjID09PSAweDIxIHx8IGMgPT09IDB4MkQgfHwgYyA9PT0gMHgyRSB8fCBjID09PSAweDVGIHx8IGMgPT09IDB4N0UgfHxcbiAgICAgICAgKGMgPj0gMHgyNyAmJiBjIDw9IDB4MkEpIHx8XG4gICAgICAgIChjID49IDB4MzAgJiYgYyA8PSAweDNBKSB8fFxuICAgICAgICAoYyA+PSAweDQxICYmIGMgPD0gMHg1QSkgfHxcbiAgICAgICAgKGMgPj0gMHg2MSAmJiBjIDw9IDB4N0EpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoaSAtIGxhc3RQb3MgPiAwKVxuICAgICAgb3V0ICs9IHN0ci5zbGljZShsYXN0UG9zLCBpKTtcblxuICAgIGxhc3RQb3MgPSBpICsgMTtcblxuICAgIC8vIE90aGVyIEFTQ0lJIGNoYXJhY3RlcnNcbiAgICBpZiAoYyA8IDB4ODApIHtcbiAgICAgIG91dCArPSBoZXhUYWJsZVtjXTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE11bHRpLWJ5dGUgY2hhcmFjdGVycyAuLi5cbiAgICBpZiAoYyA8IDB4ODAwKSB7XG4gICAgICBvdXQgKz0gaGV4VGFibGVbMHhDMCB8IChjID4+IDYpXSArIGhleFRhYmxlWzB4ODAgfCAoYyAmIDB4M0YpXTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoYyA8IDB4RDgwMCB8fCBjID49IDB4RTAwMCkge1xuICAgICAgb3V0ICs9IGhleFRhYmxlWzB4RTAgfCAoYyA+PiAxMildICtcbiAgICAgICAgICAgICBoZXhUYWJsZVsweDgwIHwgKChjID4+IDYpICYgMHgzRildICtcbiAgICAgICAgICAgICBoZXhUYWJsZVsweDgwIHwgKGMgJiAweDNGKV07XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgLy8gU3Vycm9nYXRlIHBhaXJcbiAgICArK2k7XG4gICAgdmFyIGMyO1xuICAgIGlmIChpIDwgc3RyLmxlbmd0aClcbiAgICAgIGMyID0gc3RyLmNoYXJDb2RlQXQoaSkgJiAweDNGRjtcbiAgICBlbHNlXG4gICAgICBjMiA9IDA7XG4gICAgYyA9IDB4MTAwMDAgKyAoKChjICYgMHgzRkYpIDw8IDEwKSB8IGMyKTtcbiAgICBvdXQgKz0gaGV4VGFibGVbMHhGMCB8IChjID4+IDE4KV0gK1xuICAgICAgICAgICBoZXhUYWJsZVsweDgwIHwgKChjID4+IDEyKSAmIDB4M0YpXSArXG4gICAgICAgICAgIGhleFRhYmxlWzB4ODAgfCAoKGMgPj4gNikgJiAweDNGKV0gK1xuICAgICAgICAgICBoZXhUYWJsZVsweDgwIHwgKGMgJiAweDNGKV07XG4gIH1cbiAgaWYgKGxhc3RQb3MgPT09IDApXG4gICAgcmV0dXJuIHN0cjtcbiAgaWYgKGxhc3RQb3MgPCBzdHIubGVuZ3RoKVxuICAgIHJldHVybiBvdXQgKyBzdHIuc2xpY2UobGFzdFBvcyk7XG4gIHJldHVybiBvdXQ7XG59XG4iXX0= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..ca05b338ff --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12280 @@ +{ + "name": "parse-server", + "version": "2.8.4", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", + "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0-beta.44" + } + }, + "@babel/generator": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", + "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.44", + "jsesc": "2.5.1", + "lodash": "4.17.5", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", + "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.44", + "@babel/template": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", + "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.44" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", + "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.44" + } + }, + "@babel/highlight": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", + "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.0.0-beta.49.tgz", + "integrity": "sha1-lE0MW6KBK7FZ7b0iZ0Ov0mUXm9w=", + "dev": true + }, + "@babel/template": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", + "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "lodash": "4.17.5" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true + } + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", + "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.44", + "@babel/generator": "7.0.0-beta.44", + "@babel/helper-function-name": "7.0.0-beta.44", + "@babel/helper-split-export-declaration": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "debug": "3.1.0", + "globals": "11.5.0", + "invariant": "2.2.4", + "lodash": "4.17.5" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true + }, + "globals": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.5.0.tgz", + "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", + "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@parse/fs-files-adapter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.0.1.tgz", + "integrity": "sha1-do94QIPo+Wc+9GPhmaG+X4N7QWU=" + }, + "@parse/node-gcm": { + "version": "0.14.12", + "resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-0.14.12.tgz", + "integrity": "sha512-fIXlY5LNR0VcPpFvwMvvczpByPNKxbCgMt/B3LwQqBjBCUJj/yEhBSePGUz2Kk+zOoj05v3KnG7ca+wZcAbh5A==", + "requires": { + "debug": "3.1.0", + "lodash": "4.17.5", + "request": "2.85.0" + } + }, + "@parse/push-adapter": { + "version": "3.0.0-alpha2", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.0.0-alpha2.tgz", + "integrity": "sha1-a7LNC/XbpL/8vzQykDDHPaOJ3mI=", + "requires": { + "@parse/node-gcm": "0.14.12", + "apn": "3.0.0-alpha1", + "npmlog": "4.1.2", + "parse": "1.11.1" + } + }, + "@parse/s3-files-adapter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-1.2.1.tgz", + "integrity": "sha1-2dN8zoXj1CsogqX/J4m+wbF+xnU=", + "requires": { + "aws-sdk": "2.235.1" + } + }, + "@parse/simple-mailgun-adapter": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@parse/simple-mailgun-adapter/-/simple-mailgun-adapter-1.0.2.tgz", + "integrity": "sha1-uLW54Yg02MNtQ1KX7aZiTzoOnjU=", + "requires": { + "mailgun-js": "0.18.0" + } + }, + "@semantic-release/error": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-2.2.0.tgz", + "integrity": "sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg==", + "dev": true + }, + "@semantic-release/git": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-4.0.3.tgz", + "integrity": "sha512-XvW9mq4eegS5kQ4nNbgQjMC6AOO+9Oy6H+8iRTPCRkpJElhtecPUu/gqriZXEF/qqGXF891JKA3onCUjEwwWuQ==", + "dev": true, + "requires": { + "@semantic-release/error": "2.2.0", + "aggregate-error": "1.0.0", + "debug": "3.1.0", + "dir-glob": "2.0.0", + "execa": "0.10.0", + "fs-extra": "6.0.1", + "lodash": "4.17.5", + "micromatch": "3.1.10", + "p-reduce": "1.0.0" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", + "dev": true + }, + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "dev": true, + "requires": { + "acorn": "5.7.1" + } + }, + "adm-zip": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz", + "integrity": "sha1-hgbCy/HEJs6MjsABdER/1Jtur8E=" + }, + "agent-base": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", + "integrity": "sha1-mDi1wzkrliutAx5qTF4QJKvsRc4=", + "requires": { + "es6-promisify": "5.0.0" + } + }, + "aggregate-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-1.0.0.tgz", + "integrity": "sha1-iINE2tAiCnLjr1CQYRf0h3GSX6w=", + "dev": true, + "requires": { + "clean-stack": "1.3.0", + "indent-string": "3.2.0" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ampersand-events": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ampersand-events/-/ampersand-events-2.0.2.tgz", + "integrity": "sha1-9AK8LhgwX6vZldvc07cFe73X00c=", + "dev": true, + "requires": { + "ampersand-version": "1.0.2", + "lodash": "4.17.5" + } + }, + "ampersand-state": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/ampersand-state/-/ampersand-state-5.0.3.tgz", + "integrity": "sha512-sr904K5zvw6mkGjFHhTcfBIdpoJ6mn/HrFg7OleRmBpw3apLb3Z0gVrgRTb7kK1wOLI34vs4S+IXqNHUeqWCzw==", + "dev": true, + "requires": { + "ampersand-events": "2.0.2", + "ampersand-version": "1.0.2", + "array-next": "0.0.1", + "key-tree-store": "1.3.0", + "lodash": "4.17.5" + } + }, + "ampersand-version": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ampersand-version/-/ampersand-version-1.0.2.tgz", + "integrity": "sha1-/489TOrE0yzNg/a9Zpc5f3tZ4sA=", + "dev": true, + "requires": { + "find-root": "0.1.2", + "through2": "0.6.5" + } + }, + "ansi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", + "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", + "dev": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "apn": { + "version": "3.0.0-alpha1", + "resolved": "https://registry.npmjs.org/apn/-/apn-3.0.0-alpha1.tgz", + "integrity": "sha512-o/wVNAxaQ7eegLZ69rtNEgiIQFngPClOAFFsVowsBDjVIaFsRccI+kfTda6rmVuiMSiGBMurlX01jyMNlO+AXQ==", + "requires": { + "debug": "3.1.0", + "jsonwebtoken": "8.2.1", + "node-forge": "0.7.5", + "verror": "1.10.0" + } + }, + "append-field": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-0.1.0.tgz", + "integrity": "sha1-bdxY+gg8e8VF08WZWygwzCNm1Eo=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archiver": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz", + "integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=", + "requires": { + "archiver-utils": "1.3.0", + "async": "2.6.0", + "buffer-crc32": "0.2.13", + "glob": "7.1.2", + "lodash": "4.17.5", + "readable-stream": "2.3.6", + "tar-stream": "1.6.1", + "walkdir": "0.0.11", + "zip-stream": "1.2.0" + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lazystream": "1.0.0", + "lodash": "4.17.5", + "normalize-path": "2.1.1", + "readable-stream": "2.3.6" + } + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-next": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-next/-/array-next-0.0.1.tgz", + "integrity": "sha1-5eRmCkwn/agVH/d2QnXQCQAGK+E=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true, + "optional": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", + "integrity": "sha1-wgdX/nLucSeOoP89h+XCyjDZ7fg=" + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.5" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "dev": true + }, + "aws-sdk": { + "version": "2.235.1", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.235.1.tgz", + "integrity": "sha1-uJXalIK7XZCy9UxFIDt6PBwrfOo=", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.8", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.1.0", + "xml2js": "0.4.17", + "xmlbuilder": "4.2.1" + }, + "dependencies": { + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.16.0", + "convert-source-map": "1.5.1", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.5", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.5", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.3.tgz", + "integrity": "sha512-0HeSTtaXg/Em7FCUWxwOT+KeFSO1O7LuRuzhk7g+1BjwdlQGlHq4OyMi3GqGxrNfEq8jEi6Hmt5ylEQUhurgiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.44", + "@babel/traverse": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.5", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.6", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "2.11.3", + "invariant": "2.2.4", + "semver": "5.5.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.6", + "home-or-tmp": "2.0.0", + "lodash": "4.17.5", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.6", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.5" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.5" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-3.0.0.tgz", + "integrity": "sha512-gjicxsD4e5U3nH0EqiEb5y+fKpsZ7F52wcnmNfu45nxnolWVAYh7NgbdfilY+5x1v6cLspxmzz4hf+ju2pFxhA==", + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.2" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.5" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "2.3.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "optional": true, + "requires": { + "minipass": "2.3.3" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.1", + "bundled": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.23", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.2", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.1", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.8", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.5", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.4", + "bundled": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.3", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "optional": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, + "bcrypt-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", + "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "1.6.16" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + } + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "optional": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000836", + "electron-to-chromium": "1.3.45" + } + }, + "bson": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.6.tgz", + "integrity": "sha512-D8zmlb46xfuK2gGvKmUjIklQEouN2nQ0LEHHeZ/NoHM2LDiMk2EYzZ5Ntw/Urk+bgMDosOZxaRzXxvhI5TcAVQ==" + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "1.3.0", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "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-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "buffer-writer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", + "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" + }, + "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.14" + }, + "dependencies": { + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30000836", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000836.tgz", + "integrity": "sha512-DlVR8sVTKDgd7t95U0shX3g7MeJ/DOjKOhUcaiXqnVmnO5sG4Tn2rLVOkVfPUJgnQNxnGe8/4GK0dGSI+AagQw==", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "dev": true, + "requires": { + "get-proxy": "2.1.0", + "isurl": "1.0.0", + "tunnel-agent": "0.6.0", + "url-to-options": "1.0.1" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-serializer": "0.1.0", + "entities": "1.1.1", + "htmlparser2": "3.9.2", + "lodash.assignin": "4.2.0", + "lodash.bind": "4.2.1", + "lodash.defaults": "4.2.0", + "lodash.filter": "4.6.0", + "lodash.flatten": "4.4.0", + "lodash.foreach": "4.5.0", + "lodash.map": "4.6.0", + "lodash.merge": "4.6.1", + "lodash.pick": "4.4.0", + "lodash.reduce": "4.6.0", + "lodash.reject": "4.6.0", + "lodash.some": "4.6.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "ci-info": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", + "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "clean-stack": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", + "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=", + "dev": true + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", + "integrity": "sha1-dfpfcowwjMSsWUsF4GzF2A2szYY=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45", + "memoizee": "0.3.10", + "timers-ext": "0.1.5" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "clui": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/clui/-/clui-0.3.6.tgz", + "integrity": "sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==", + "dev": true, + "requires": { + "cli-color": "0.3.2" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "requires": { + "buffer-crc32": "0.2.13", + "crc32-stream": "2.0.0", + "normalize-path": "2.1.1", + "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.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "dev": true, + "requires": { + "ini": "1.3.5", + "proto-list": "1.2.4" + } + }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.2.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "connected-domain": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz", + "integrity": "sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM=", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", + "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "5.2.0" + }, + "dependencies": { + "buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.0.tgz", + "integrity": "sha512-nUJyfChH7PMJy75eRDCCKtszSEFokUNXC1hNVSe+o+VdcgvDPLs20k3v8UXI8ruRYAJiYtyRea8mYyqPxoHWDw==", + "requires": { + "base64-js": "1.3.0", + "ieee754": "1.1.8" + } + } + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "requires": { + "crc": "3.8.0", + "readable-stream": "2.3.6" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-env": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", + "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", + "dev": true, + "requires": { + "cross-spawn": "6.0.5", + "is-windows": "1.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.5.1", + "nth-check": "1.0.1" + } + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "0.10.45" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "dev": true, + "requires": { + "decompress-tar": "4.1.1", + "decompress-tarbz2": "4.1.1", + "decompress-targz": "4.1.1", + "decompress-unzip": "4.0.1", + "graceful-fs": "4.1.11", + "make-dir": "1.2.0", + "pify": "2.3.0", + "strip-dirs": "2.1.0" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "1.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "requires": { + "file-type": "5.2.0", + "is-stream": "1.1.0", + "tar-stream": "1.6.1" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "requires": { + "decompress-tar": "4.1.1", + "file-type": "6.2.0", + "is-stream": "1.1.0", + "seek-bzip": "1.0.5", + "unbzip2-stream": "1.2.5" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "requires": { + "decompress-tar": "4.1.1", + "file-type": "5.2.0", + "is-stream": "1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dev": true, + "requires": { + "file-type": "3.9.0", + "get-stream": "2.3.1", + "pify": "2.3.0", + "yauzl": "2.10.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + } + } + }, + "deep-diff": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.1.tgz", + "integrity": "sha512-Vkn+eQK6H63gObVi3KWmPMb4RdzMpfdp5t0HNppq8Oc7xbwmvBy5BIHsEYSXOiS9Lr/W+3lF020zyPTsGfea4g==", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "deepcopy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-1.0.0.tgz", + "integrity": "sha512-WJrecobaoqqgQHtvRI2/VCzWoWXPAnFYyAkF/spmL46lZMnd0gW0gLGuyeFVSrqt2B3s0oEEj6i+j2L/2QiS4g==", + "requires": { + "type-detect": "4.0.8" + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "requires": { + "ast-types": "0.11.3", + "escodegen": "1.9.1", + "esprima": "3.1.3" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "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.14", + "streamsearch": "0.1.2" + }, + "dependencies": { + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + } + }, + "docopt": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz", + "integrity": "sha1-so6eIiDaXsSffqW7JKR3h0Be6xE=", + "dev": true + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, + "downcache": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/downcache/-/downcache-0.0.9.tgz", + "integrity": "sha1-eQuwQkaJE2EVzpPyqhWUbG2AbQ4=", + "dev": true, + "requires": { + "extend": "3.0.1", + "graceful-fs": "4.1.11", + "limiter": "1.1.3", + "mkdirp": "0.5.1", + "npmlog": "2.0.4", + "request": "2.85.0", + "rimraf": "2.6.2" + }, + "dependencies": { + "gauge": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", + "dev": true, + "requires": { + "ansi": "0.3.1", + "has-unicode": "2.0.1", + "lodash.pad": "4.5.1", + "lodash.padend": "4.6.1", + "lodash.padstart": "4.6.1" + } + }, + "npmlog": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", + "dev": true, + "requires": { + "ansi": "0.3.1", + "are-we-there-yet": "1.1.4", + "gauge": "1.2.7" + } + } + } + }, + "download": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", + "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==", + "dev": true, + "requires": { + "caw": "2.0.1", + "content-disposition": "0.5.2", + "decompress": "4.2.0", + "ext-name": "5.0.0", + "file-type": "5.2.0", + "filenamify": "2.1.0", + "get-stream": "3.0.0", + "got": "7.1.0", + "make-dir": "1.2.0", + "p-event": "1.3.0", + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", + "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "electron-to-chromium": { + "version": "1.3.45", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.45.tgz", + "integrity": "sha1-RYrBscXHYM6IEaFtK/vZfsMLr7g=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45", + "es6-symbol": "3.1.1" + }, + "dependencies": { + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.45" + } + } + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "4.2.4" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45" + }, + "dependencies": { + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.45" + } + } + } + }, + "es6-weak-map": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", + "integrity": "sha1-cGzvnpmqI2undmwjnIueKG6n0ig=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45", + "es6-iterator": "0.1.3", + "es6-symbol": "2.0.1" + }, + "dependencies": { + "es6-iterator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "integrity": "sha1-1vWLjE/EE8JJtLqhl2j45NfIlE4=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45", + "es6-symbol": "2.0.1" + } + }, + "es6-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "integrity": "sha1-dhtcZ8/U8dGK+yNPaR1nhoLLO/M=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45" + } + } + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", + "integrity": "sha1-264X75bI5L7bE1b0UE+kzC98t+I=", + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" + } + }, + "eslint": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.0.0.tgz", + "integrity": "sha512-MA0YWJLeK7BPEBxJCINvKnQdKpeTwbac3Xonh0PPFjWYZkowZf+Xl30lJWJ/BWOqFQdAdPcyOh0aBqlbH6ojAg==", + "dev": true, + "requires": { + "ajv": "6.5.1", + "babel-code-frame": "6.26.0", + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "4.0.0", + "eslint-visitor-keys": "1.0.0", + "espree": "4.0.0", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "3.3.10", + "imurmurhash": "0.1.4", + "inquirer": "5.2.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.5", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "string.prototype.matchall": "2.0.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.3", + "text-table": "0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.1.tgz", + "integrity": "sha512-pgZos1vgOHDiC7gKNbZW8eKvCnNXARv2oqrGQT7Hzbq5Azp7aZG6DJzADnkuSq7RH6qkXp4J/m68yPX/2uBHyQ==", + "dev": true, + "requires": { + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "eslint-plugin-flowtype": { + "version": "2.46.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.46.3.tgz", + "integrity": "sha512-VpnNeC4E6t2E2NCw8Oveda91p8CPEaujZURC1KhHe4lBRZJla3o0DVvZu1QGXQZO1ZJ4vUmy3TCp95PqGvIZgQ==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "dev": true, + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "4.1.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45" + }, + "dependencies": { + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.45" + } + } + } + }, + "event-stream": { + "version": "3.3.4", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + }, + "dependencies": { + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2.3.8" + } + } + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "dev": true, + "requires": { + "cross-spawn": "6.0.5", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "optional": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "optional": true, + "requires": { + "fill-range": "2.2.4" + } + }, + "express": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", + "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "requires": { + "accepts": "1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.0", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.3", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.1", + "serve-static": "1.13.1", + "setprototypeof": "1.1.0", + "statuses": "1.3.1", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } + } + }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "requires": { + "ext-list": "2.2.2", + "sort-keys-length": "1.0.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.23", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true, + "optional": true + }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "dev": true + }, + "filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "dev": true, + "requires": { + "filename-reserved-regex": "2.0.0", + "strip-outer": "1.0.1", + "trim-repeated": "1.0.0" + } + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "optional": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.0.0", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } + } + }, + "find-root": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-0.1.2.tgz", + "integrity": "sha1-mNImfP8ZFsyvJ0OzoO6oHXnX3NE=", + "dev": true + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "flow-bin": { + "version": "0.76.0", + "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.76.0.tgz", + "integrity": "sha512-ywyEEEDYuItrkpx9HqRhuY78rXYbaWiNZSWgaI0KUGGeOldaTEbCZXosspxTEKqmQTCBW1/02Z2K0kC9C6hqzQ==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "optional": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "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==" + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.2" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.3.tgz", + "integrity": "sha512-X+57O5YkDTiEQGiw8i7wYc2nQgweIekqkepI8Q3y4wVlurgBt2SuwxTeYUYMZIGpLZH3r/TsMjczCMXE5ZOt7Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.9.1" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", + "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "minipass": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", + "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", + "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", + "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz", + "integrity": "sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA=", + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.8", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", + "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", + "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "tar": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", + "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "dev": true + } + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.14", + "xregexp": "2.0.0" + }, + "dependencies": { + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "1.2.0" + } + }, + "get-mongodb-version": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-mongodb-version/-/get-mongodb-version-1.0.0.tgz", + "integrity": "sha1-pSTTu1Ph6Ff84Jt0DSQB5HVWKqM=", + "dev": true, + "requires": { + "debug": "2.6.9", + "lodash.startswith": "4.2.1", + "minimist": "1.2.0", + "mongodb": "2.2.35", + "which": "1.3.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mongodb": { + "version": "2.2.35", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.35.tgz", + "integrity": "sha1-zRta+KlGPj+aeH+ls9BVZVeXMPk=", + "dev": true, + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.19", + "readable-stream": "2.2.7" + } + }, + "mongodb-core": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.19.tgz", + "integrity": "sha1-APvV5aNXN2O5Fxz9hE5gqPKjoYs=", + "dev": true, + "requires": { + "bson": "1.0.6", + "require_optional": "1.0.1" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "dev": true, + "requires": { + "npm-conf": "1.1.3" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", + "integrity": "sha1-29ysrNjGCKODFoaTaBF2l6FjHFk=", + "requires": { + "data-uri-to-buffer": "1.2.0", + "debug": "2.6.9", + "extend": "3.0.1", + "file-uri-to-path": "1.0.0", + "ftp": "0.3.10", + "readable-stream": "2.3.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "optional": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "1.3.5" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.5", + "minimatch": "3.0.4" + } + }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "requires": { + "has-symbol-support-x": "1.4.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.2", + "domutils": "1.5.1", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.5.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha1-5IIb7vWyFCogJr1zkm/lN2McVAU=", + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha1-UVUpcPoE1yPgTFbQQXjD+SWSu8A=", + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.5", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "intersect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/intersect/-/intersect-1.0.1.tgz", + "integrity": "sha1-MyZQ4QhU2MCsWMGSvcJ6i/fnoww=" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-ci": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", + "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "dev": true, + "requires": { + "ci-info": "1.1.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true, + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "optional": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-mongodb-running": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/is-mongodb-running/-/is-mongodb-running-0.0.1.tgz", + "integrity": "sha1-7QdQhQ3uaj6X50ZX+6nm+jvTEmI=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "debug": "2.6.9", + "figures": "1.7.0", + "lodash": "3.10.1", + "lsof": "0.1.0", + "minimist": "1.2.0", + "ps-node": "0.0.5" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "dev": true + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha1-dkZiRnH9fqVYzNmieVGC8pWPGyQ=", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", + "dev": true + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true, + "optional": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true, + "optional": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.3" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-2.1.0.tgz", + "integrity": "sha512-3ly7GAJiPKqgbGKh2s01ysk3jd/egpE1i84PYu3BvPkssqrKMXZY9KRGX0mfZ+cmCfTR1IFVnnn/tDHxTer4nA==", + "dev": true, + "requires": { + "@babel/generator": "7.0.0-beta.49", + "@babel/parser": "7.0.0-beta.49", + "@babel/template": "7.0.0-beta.49", + "@babel/traverse": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49", + "istanbul-lib-coverage": "1.2.0", + "semver": "5.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.49.tgz", + "integrity": "sha1-vs2AVIJzREDJ0TfkbXc0DmTX9Rs=", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0-beta.49" + } + }, + "@babel/generator": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.49.tgz", + "integrity": "sha1-6c/9qROZaszseTu8JauRvBnQv3o=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.49", + "jsesc": "2.5.1", + "lodash": "4.17.5", + "source-map": "0.5.7", + "trim-right": "1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.49.tgz", + "integrity": "sha1-olwRGbnwNSeGcBJuAiXAMEHI3jI=", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.49", + "@babel/template": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.49.tgz", + "integrity": "sha1-z1Aj8y0q2S0Ic3STnOwJUby1FEE=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.49" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.49.tgz", + "integrity": "sha1-QNeO2glo0BGxxShm5XRs+yPldUg=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.49" + } + }, + "@babel/highlight": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.49.tgz", + "integrity": "sha1-lr3GtD4TSCASumaRsQGEktOWIsw=", + "dev": true, + "requires": { + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "@babel/template": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.49.tgz", + "integrity": "sha1-44q+ghfLl5P0YaUwbXrXRdg+HSc=", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.49", + "@babel/parser": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49", + "lodash": "4.17.5" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.49.tgz", + "integrity": "sha1-TypzaCoYM07WYl0QCo0nMZ98LWg=", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.49", + "@babel/generator": "7.0.0-beta.49", + "@babel/helper-function-name": "7.0.0-beta.49", + "@babel/helper-split-export-declaration": "7.0.0-beta.49", + "@babel/parser": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49", + "debug": "3.1.0", + "globals": "11.5.0", + "invariant": "2.2.4", + "lodash": "4.17.5" + } + }, + "@babel/types": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.49.tgz", + "integrity": "sha1-t+Oxw/TUz+Eb34yJ8e/V4WF7h6Y=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "globals": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.5.0.tgz", + "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "jasmine": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.1.0.tgz", + "integrity": "sha1-K9Wf1+xuwOistk4J9Fpo7SrRlSo=", + "dev": true, + "requires": { + "glob": "7.1.2", + "jasmine-core": "3.1.0" + } + }, + "jasmine-core": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz", + "integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", + "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "dev": true, + "requires": { + "colors": "1.1.2" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + } + } + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonwebtoken": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.2.1.tgz", + "integrity": "sha1-Mz7jmqjyOPMvpBaT56L7fkL4KzE=", + "requires": { + "jws": "3.1.5", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.once": "4.1.1", + "ms": "2.1.1", + "xtend": "4.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=" + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jwa": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", + "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.10", + "safe-buffer": "5.1.2" + } + }, + "jws": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", + "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "requires": { + "jwa": "1.1.6", + "safe-buffer": "5.1.2" + } + }, + "key-tree-store": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/key-tree-store/-/key-tree-store-1.3.0.tgz", + "integrity": "sha1-XqKa/CUppCWThDfWlVtxTOapeR8=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "4.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "2.3.6" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "limiter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.3.tgz", + "integrity": "sha512-zrycnIMsLw/3ZxTbW7HCez56rcFGecWTx5OZNplzcXUUmJLmoYArC6qdJzmAN5BWiNXGcpjhF9RQ1HSv5zebEw==", + "dev": true + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", + "dev": true + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "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 + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=", + "dev": true + }, + "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 + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", + "dev": true + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "dev": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "lodash.pad": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", + "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=", + "dev": true + }, + "lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "lodash.startswith": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz", + "integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "0.10.45" + } + }, + "lsof": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lsof/-/lsof-0.1.0.tgz", + "integrity": "sha1-rALU2HYGIB8TZLr7FcSRz9WuMJI=", + "dev": true + }, + "mailgun-js": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", + "integrity": "sha1-gf7QxmpBHT/2xDVIYa0hOHr8+qo=", + "requires": { + "async": "2.6.0", + "debug": "3.1.0", + "form-data": "2.3.2", + "inflection": "1.12.0", + "is-stream": "1.1.0", + "path-proxy": "1.0.0", + "promisify-call": "2.0.4", + "proxy-agent": "3.0.0", + "tsscmp": "1.0.5" + } + }, + "make-dir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha1-bWpJ7q1KrilsU7vzoaAIvWyJRps=", + "dev": true, + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "manakin": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/manakin/-/manakin-0.5.1.tgz", + "integrity": "sha1-xKcRb2sA3z1fGjetPKUV0iBlplg=" + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true, + "optional": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memoizee": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", + "integrity": "sha1-TsoNiu057J0Bf0xcLy9kMvQuXI8=", + "dev": true, + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45", + "es6-weak-map": "0.1.4", + "event-emitter": "0.3.5", + "lru-queue": "0.1.0", + "next-tick": "0.2.2", + "timers-ext": "0.1.5" + }, + "dependencies": { + "next-tick": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0=", + "dev": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha1-sWIcVNY7l8R9PP5/chX31kUXw2k=" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mongodb": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.1.1.tgz", + "integrity": "sha512-GU9oWK4pi8PC7NyGiwjFMwZyMqwGWoMEMvM0LZh7UKW/FFAqgmZKjjriD+5MEOCDUJE2dtHX93/K5UtDxO0otg==", + "requires": { + "mongodb-core": "3.1.0" + } + }, + "mongodb-core": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.0.tgz", + "integrity": "sha512-qRjG62Fu//CZhkgn0jA/k8jh5MhACIq8cOJUryH6sck87pgt+C222MSD02tsCq5zNo/B6ZFHtNodZ2qpf8E86g==", + "requires": { + "bson": "1.0.6", + "require_optional": "1.0.1", + "saslprep": "1.0.0" + } + }, + "mongodb-dbpath": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/mongodb-dbpath/-/mongodb-dbpath-0.0.1.tgz", + "integrity": "sha1-4BMsZ3sbncgwBFEW0Yrbf2kk8XU=", + "dev": true, + "requires": { + "async": "1.5.2", + "debug": "2.6.9", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "untildify": "1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "untildify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-1.0.0.tgz", + "integrity": "sha1-TYAx0YBvT718QrAjeq8hNoYmJjU=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + } + } + }, + "mongodb-download-url": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-0.3.3.tgz", + "integrity": "sha1-46ilSPE+sg9aDN+GPLwGNCGjk0w=", + "dev": true, + "requires": { + "async": "2.6.0", + "debug": "2.6.9", + "lodash.defaults": "4.2.0", + "minimist": "1.2.0", + "mongodb-version-list": "1.0.0", + "request": "2.85.0", + "semver": "5.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "mongodb-runner": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-4.0.0.tgz", + "integrity": "sha512-ln20t36NelSvzUTvi6ywzisUNvn/UMajM0ydYEET/Gd3/jd4Pm0B8xR2tRTSnjnHvUZhGyD+3reWKnqN3C310A==", + "dev": true, + "requires": { + "async": "2.6.0", + "clui": "0.3.6", + "debug": "3.1.0", + "fs-extra": "4.0.3", + "is-mongodb-running": "0.0.1", + "lodash.defaults": "4.2.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "mongodb": "3.1.1", + "mongodb-dbpath": "0.0.1", + "mongodb-tools": "github:mongodb-js/mongodb-tools#df761df21175f2c521c78b8e011a1532569f0dca", + "mongodb-version-manager": "1.1.3", + "untildify": "3.0.3", + "which": "1.3.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "mongodb-tools": { + "version": "github:mongodb-js/mongodb-tools#df761df21175f2c521c78b8e011a1532569f0dca", + "dev": true, + "requires": { + "debug": "2.6.9", + "lodash": "3.10.1", + "mkdirp": "0.5.0", + "mongodb-core": "2.1.19", + "rimraf": "2.2.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mongodb-core": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.19.tgz", + "integrity": "sha512-Jt4AtWUkpuW03kRdYGxga4O65O1UHlFfvvInslEfLlGi+zDMxbBe3J2NVmN9qPJ957Mn6Iz0UpMtV80cmxCVxw==", + "dev": true, + "requires": { + "bson": "1.0.6", + "require_optional": "1.0.1" + } + }, + "rimraf": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", + "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=", + "dev": true + } + } + }, + "mongodb-version-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mongodb-version-list/-/mongodb-version-list-1.0.0.tgz", + "integrity": "sha1-8lAxz83W8UWx3o/OKk6+wCiLtKQ=", + "dev": true, + "requires": { + "cheerio": "0.22.0", + "debug": "2.6.9", + "downcache": "0.0.9", + "fs-extra": "1.0.0", + "minimist": "1.2.0", + "semver": "5.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "mongodb-version-manager": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/mongodb-version-manager/-/mongodb-version-manager-1.1.3.tgz", + "integrity": "sha512-EInfE8Uu4umFHnFr1+kjvxaC8n0v2HR9WEJ659FxOITStOMzzvFvKw88j4m//rK85rAKk6aZ+Kx29tRTcatrkA==", + "dev": true, + "requires": { + "ampersand-state": "5.0.3", + "async": "2.6.0", + "chalk": "2.4.1", + "debug": "3.1.0", + "docopt": "0.6.2", + "download": "6.2.5", + "figures": "2.0.0", + "fs-extra": "4.0.3", + "get-mongodb-version": "1.0.0", + "lodash.defaults": "4.2.0", + "lodash.difference": "4.5.0", + "mongodb-download-url": "0.3.3", + "mongodb-version-list": "1.0.0", + "semver": "5.5.0", + "tildify": "1.2.0", + "untildify": "3.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.3.1.tgz", + "integrity": "sha512-JHdEoxkA/5NgZRo91RNn4UT+HdcJV9XUo01DTkKC7vo1erNIngtuaw9Y0WI8RdTlyi+wMIbunflhghzVLuGJyw==", + "requires": { + "append-field": "0.1.0", + "busboy": "0.2.14", + "concat-stream": "1.6.2", + "mkdirp": "0.5.1", + "object-assign": "3.0.0", + "on-finished": "2.3.0", + "type-is": "1.6.16", + "xtend": "4.0.1" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + } + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "optional": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha1-h59xUMstq3pHElkGbBBO7m4Pp8I=", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "dev": true + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "dev": true + }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==" + }, + "nodemon": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.1.tgz", + "integrity": "sha512-zKKrRcn5htBkPz6N5SiFLG8kneJxhW//zO7/RB08TaQgBZrbmjUlORBy6ALIbpwwp+Q8F9mWbnbkJXh6rjlALA==", + "dev": true, + "requires": { + "chokidar": "2.0.4", + "debug": "3.1.0", + "ignore-by-default": "1.0.1", + "minimatch": "3.0.4", + "pstree.remy": "1.1.0", + "semver": "5.5.0", + "supports-color": "5.4.0", + "touch": "3.1.0", + "undefsafe": "2.0.2", + "update-notifier": "2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.3", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.1.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "requires": { + "config-chain": "1.1.11", + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "nyc": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-12.0.2.tgz", + "integrity": "sha1-ikpO1pCWbBHsWH/4fuoMEsl0upk=", + "dev": true, + "requires": { + "archy": "1.0.0", + "arrify": "1.0.1", + "caching-transform": "1.0.1", + "convert-source-map": "1.5.1", + "debug-log": "1.0.1", + "default-require-extensions": "1.0.0", + "find-cache-dir": "0.1.1", + "find-up": "2.1.0", + "foreground-child": "1.5.6", + "glob": "7.1.2", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-hook": "1.1.0", + "istanbul-lib-instrument": "2.1.0", + "istanbul-lib-report": "1.1.3", + "istanbul-lib-source-maps": "1.2.5", + "istanbul-reports": "1.4.1", + "md5-hex": "1.3.0", + "merge-source-map": "1.1.0", + "micromatch": "3.1.10", + "mkdirp": "0.5.1", + "resolve-from": "2.0.0", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "spawn-wrap": "1.4.2", + "test-exclude": "4.2.1", + "yargs": "11.1.0", + "yargs-parser": "8.1.0" + }, + "dependencies": { + "align-text": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "requires": { + "default-require-extensions": "1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "bundled": true, + "dev": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "async": { + "version": "1.5.2", + "bundled": true, + "dev": true + }, + "atob": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "base": { + "version": "0.11.2", + "bundled": true, + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "caching-transform": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "md5-hex": "1.3.0", + "mkdirp": "0.5.1", + "write-file-atomic": "1.3.4" + } + }, + "camelcase": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "class-utils": { + "version": "0.3.6", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "cliui": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "commondir": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "bundled": true, + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "cross-spawn": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.1.3", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, + "define-property": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "error-ex": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "fill-range": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "find-cache-dir": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "4.0.2", + "signal-exit": "3.0.2" + } + }, + "fragment-cache": { + "version": "0.2.1", + "bundled": true, + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "get-value": { + "version": "2.0.6", + "bundled": true, + "dev": true + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "bundled": true, + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hosted-git-info": { + "version": "2.6.0", + "bundled": true, + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-odd": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "bundled": true, + "dev": true + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "append-transform": "0.4.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + } + }, + "istanbul-reports": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "requires": { + "handlebars": "4.0.11" + } + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "bundled": true, + "dev": true + } + } + }, + "longest": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "map-cache": { + "version": "0.2.2", + "bundled": true, + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "md5-o-matic": "0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "merge-source-map": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true, + "dev": true + } + } + }, + "micromatch": { + "version": "3.1.10", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "nanomatch": { + "version": "1.2.9", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.pick": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "pascalcase": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "regex-not": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true, + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "ret": { + "version": "0.1.15", + "bundled": true, + "dev": true + }, + "right-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-regex": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "set-value": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "slide": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true, + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "bundled": true, + "dev": true, + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "bundled": true, + "dev": true + }, + "spawn-wrap": { + "version": "1.4.2", + "bundled": true, + "dev": true, + "requires": { + "foreground-child": "1.5.6", + "mkdirp": "0.5.1", + "os-homedir": "1.0.2", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "which": "1.3.1" + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "split-string": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "static-extend": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "test-exclude": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "3.1.10", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, + "to-object-path": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, + "uglify-js": { + "version": "2.8.29", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "union-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "bundled": true, + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "bundled": true, + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "bundled": true, + "dev": true + }, + "use": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "window-size": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true, + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "11.1.0", + "bundled": true, + "dev": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "8.1.0", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + } + } + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "optional": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true + }, + "p-event": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", + "integrity": "sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=", + "dev": true, + "requires": { + "p-timeout": "1.2.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "requires": { + "p-finally": "1.0.0" + } + }, + "pac-proxy-agent": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", + "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0", + "get-uri": "2.0.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "pac-resolver": "3.0.0", + "raw-body": "2.3.3", + "socks-proxy-agent": "3.0.1" + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "requires": { + "co": "4.6.0", + "degenerator": "1.0.4", + "ip": "1.1.5", + "netmask": "1.0.6", + "thunkify": "2.1.2" + } + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" + }, + "dependencies": { + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + } + } + }, + "packet-reader": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", + "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=" + }, + "parse": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/parse/-/parse-1.11.1.tgz", + "integrity": "sha1-VY5TnULZ+4khDggiCdbzsD1frtU=", + "requires": { + "babel-runtime": "6.26.0", + "ws": "3.3.3", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" + } + } + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "optional": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "requires": { + "inflection": "1.3.8" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=" + } + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pg": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.4.3.tgz", + "integrity": "sha1-97b5P1NA7MJZavu5ShPj1rYJg0s=", + "requires": { + "buffer-writer": "1.0.1", + "packet-reader": "0.3.1", + "pg-connection-string": "0.1.3", + "pg-pool": "2.0.3", + "pg-types": "1.12.1", + "pgpass": "1.0.2", + "semver": "4.3.2" + }, + "dependencies": { + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + } + } + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" + }, + "pg-minify": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-0.5.4.tgz", + "integrity": "sha512-GHB2v4OiMHDgwiHH86ZWNfvgEPVijrnfuWLQocseX6Zlf30k+x0imA65zBy4skIpEwfBBEplIEEKP4n3q9KkVA==" + }, + "pg-pool": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.3.tgz", + "integrity": "sha1-wCIDLIlJ8xKk+R+2QJzgQHa+Mlc=" + }, + "pg-promise": { + "version": "8.4.5", + "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-8.4.5.tgz", + "integrity": "sha512-0KqI14s/y/KN142T+ingQugXwz8OZGkZIQESXLEN1Ei1kq9sZWpatAGNO6/Vr9tsZp6UN4a0V9YsHaLUszNyxw==", + "requires": { + "manakin": "0.5.1", + "pg": "7.4.3", + "pg-minify": "0.5.4", + "spex": "2.0.2" + } + }, + "pg-types": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", + "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", + "requires": { + "postgres-array": "1.0.2", + "postgres-bytea": "1.0.0", + "postgres-date": "1.0.3", + "postgres-interval": "1.1.1" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "1.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postgres-array": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz", + "integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg=" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", + "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=" + }, + "postgres-interval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.1.tgz", + "integrity": "sha1-rNsPiXtLHG5JbZ1OCoU+HEKPBvA=", + "requires": { + "xtend": "4.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true, + "optional": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "promisify-call": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", + "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", + "requires": { + "with-callback": "1.0.2" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.0.tgz", + "integrity": "sha1-9naOICiJsihdOZBtOpR2hBb49xM=", + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.2", + "pac-proxy-agent": "2.0.2", + "proxy-from-env": "1.0.0", + "socks-proxy-agent": "3.0.1" + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" + }, + "ps-node": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.0.5.tgz", + "integrity": "sha1-hWe8VKX4MbRd2eAOWpwJVqr58ZY=", + "dev": true, + "requires": { + "table-parser": "1.0.1" + } + }, + "ps-tree": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", + "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=", + "dev": true, + "requires": { + "event-stream": "3.3.4" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pstree.remy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.0.tgz", + "integrity": "sha512-q5I5vLRMVtdWa8n/3UEzZX7Lfghzrg9eG2IKk2ENLSofKRCXVqMvMUHxCKgXNaqH/8ebhBxrqftHWnyTFweJ5Q==", + "dev": true, + "requires": { + "ps-tree": "1.1.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "dev": true, + "optional": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true, + "optional": true + } + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" + } + }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "requires": { + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.5", + "redis-parser": "2.6.0" + } + }, + "redis-commands": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", + "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==" + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "optional": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", + "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "dev": true, + "requires": { + "define-properties": "1.1.2" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "1.2.8", + "safe-buffer": "5.1.2" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "1.2.8" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "request-promise": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz", + "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.4" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } + } + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.5.0" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rxjs": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", + "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saslprep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.0.tgz", + "integrity": "sha512-5lvKUEQ7lAN5/vPl5d3k8FQeDbEamu9kizfATfLLWV5h6Mkh1xcieR1FSsJkcSRUk49lF2tAW8gzXWVwtwZVhw==", + "optional": true + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true, + "requires": { + "commander": "2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + } + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "5.5.0" + } + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.3", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } + } + }, + "serve-static": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", + "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.1" + } + }, + "socks": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", + "integrity": "sha1-Lq58+OKoLTRWV2FTmn+XGMVhdlk=", + "requires": { + "agent-base": "4.2.0", + "socks": "1.1.10" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "dev": true, + "requires": { + "sort-keys": "1.1.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha1-etD1k/IoFZjoVN+A8ZquS5LXoRo=", + "dev": true, + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spex": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/spex/-/spex-2.0.2.tgz", + "integrity": "sha512-LU6TS3qTEpRth+FnNs/fIWEmridYN7JmaN2k1Jk31XVC4ex7+wYxiHMnKguRxS7oKjbOFl4H6seeWNDFFgkVRg==" + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2.3.8" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "0.1.1" + } + }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string.prototype.matchall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", + "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "regexp.prototype.flags": "1.2.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "requires": { + "is-natural-number": "4.0.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + }, + "table": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "6.5.1", + "ajv-keywords": "3.2.0", + "chalk": "2.4.1", + "lodash": "4.17.5", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.1.tgz", + "integrity": "sha512-pgZos1vgOHDiC7gKNbZW8eKvCnNXARv2oqrGQT7Hzbq5Azp7aZG6DJzADnkuSq7RH6qkXp4J/m68yPX/2uBHyQ==", + "dev": true, + "requires": { + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "table-parser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-1.0.1.tgz", + "integrity": "sha512-LtOZVj3mBWk9ChtZmYy1NCSgWshClqoCzgcj0r0VRY+xm9N4ii2NZyLHVbFhGrWsxVt5uPiVeaZDePoD3krrGA==", + "dev": true, + "requires": { + "@semantic-release/git": "4.0.3", + "connected-domain": "1.0.0" + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", + "xtend": "4.0.1" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "0.7.0" + }, + "dependencies": { + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "timers-ext": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", + "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", + "dev": true, + "requires": { + "es5-ext": "0.10.45", + "next-tick": "1.0.0" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "1.0.10" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tv4": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", + "integrity": "sha1-0CDIRvrdUMhVq7JeuuzGj8EPeWM=" + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "unbzip2-stream": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz", + "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==", + "dev": true, + "requires": { + "buffer": "3.6.0", + "through": "2.3.8" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "dev": true + }, + "buffer": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "dev": true, + "requires": { + "base64-js": "0.0.8", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + } + } + }, + "undefsafe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", + "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", + "dev": true, + "requires": { + "debug": "2.6.9" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", + "dev": true + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "1.3.0", + "chalk": "2.4.1", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha1-FHFr8D/f79AwQK71jYtLhfOnxUQ=", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "dev": true + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "uws": { + "version": "10.148.1", + "resolved": "https://registry.npmjs.org/uws/-/uws-10.148.1.tgz", + "integrity": "sha1-/Rp5z2EYo4jgob7YoTlwMNLE/Sw=", + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "walkdir": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", + "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=" + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", + "requires": { + "string-width": "1.0.2" + } + }, + "widest-line": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", + "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "dev": true, + "requires": { + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "winston": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.1.tgz", + "integrity": "sha1-o6kmUQVWQmPGeFtFg7jIrKJv3tY=", + "requires": { + "async": "1.0.0", + "colors": "1.0.3", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "stack-trace": "0.0.10" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + } + } + }, + "winston-daily-rotate-file": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-1.7.2.tgz", + "integrity": "sha1-ZQK/opeCT9mC2l5WR8dThXjS+aA=", + "requires": { + "mkdirp": "0.5.1" + } + }, + "with-callback": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", + "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "ws": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz", + "integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==", + "requires": { + "async-limiter": "1.0.0" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, + "xml2js": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "requires": { + "sax": "1.2.1", + "xmlbuilder": "4.2.1" + } + }, + "xmlbuilder": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", + "requires": { + "lodash": "4.17.5" + } + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.1.0" + } + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "requires": { + "archiver-utils": "1.3.0", + "compress-commons": "1.2.2", + "lodash": "4.17.5", + "readable-stream": "2.3.6" + } + } + } +} diff --git a/package.json b/package.json index a0b13451cb..52ee34d99f 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "parse-server", - "version": "2.7.4", + "version": "2.8.4", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { "type": "git", - "url": "https://github.com/ParsePlatform/parse-server" + "url": "https://github.com/parse-community/parse-server" }, "files": [ "bin/", @@ -14,38 +14,39 @@ "views/", "LICENSE", "PATENTS", + "postinstall.js", "README.md" ], "license": "BSD-3-Clause", "dependencies": { "@parse/fs-files-adapter": "1.0.1", - "@parse/push-adapter": "2.0.2", + "@parse/push-adapter": "3.0.0-alpha2", "@parse/s3-files-adapter": "1.2.1", - "@parse/simple-mailgun-adapter": "1.0.1", + "@parse/simple-mailgun-adapter": "1.0.2", "adm-zip": "0.4.7", "archiver": "1.3.0", "bcryptjs": "2.4.3", - "body-parser": "1.18.2", - "commander": "2.15.0", - "deepcopy": "0.6.3", + "body-parser": "1.18.3", + "commander": "2.16.0", + "deepcopy": "1.0.0", "express": "4.16.2", "intersect": "1.0.1", "lodash": "4.17.5", "lru-cache": "4.1.2", - "mime": "2.2.0", - "mongodb": "3.0.4", - "multer": "1.3.0", + "mime": "2.3.1", + "mongodb": "3.1.1", + "multer": "^1.3.1", "parse": "1.11.1", - "pg-promise": "8.2.1", + "pg-promise": "8.4.5", "redis": "2.8.0", - "request": "2.83.0", + "request": "2.85.0", "semver": "5.5.0", "tmp": "0.0.33", "tv4": "1.3.0", "uuid": "^3.1.0", "winston": "2.4.1", "winston-daily-rotate-file": "1.7.2", - "ws": "5.0.0" + "ws": "6.0.0" }, "devDependencies": { "babel-cli": "6.26.0", @@ -55,38 +56,41 @@ "babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-preset-env": "1.6.1", "bcrypt-nodejs": "0.0.3", - "cross-env": "5.1.4", - "deep-diff": "0.3.8", - "eslint": "^4.9.0", + "cross-env": "5.2.0", + "deep-diff": "1.0.1", + "eslint": "^5.0.0", "eslint-plugin-flowtype": "^2.39.1", - "flow-bin": "^0.67.1", - "gaze": "1.1.2", + "flow-bin": "^0.76.0", + "gaze": "1.1.3", "jasmine": "3.1.0", "jasmine-spec-reporter": "^4.1.0", - "mongodb-runner": "3.6.1", - "nodemon": "1.17.1", - "nyc": "^11.0.2", - "request-promise": "4.2.2" + "mongodb-runner": "4.0.0", + "nodemon": "1.18.1", + "nyc": "^12.0.2", + "request-promise": "4.2.2", + "supports-color": "^5.4.0" }, "scripts": { "dev": "npm run build && node bin/dev", "lint": "flow && eslint --cache ./", "build": "babel src/ -d lib/ --copy-files", + "watch": "babel --watch src/ -d lib/ --copy-files", "pretest": "npm run lint", "test": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 TESTING=1 jasmine", "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 TESTING=1 nyc jasmine", "start": "node ./bin/parse-server", - "prepublish": "npm run build" + "prepare": "npm run build", + "postinstall": "node -p 'require(\"./postinstall.js\")()'" }, "engines": { - "node": ">=6.11.4" + "node": ">= 8" }, "bin": { "parse-server": "./bin/parse-server" }, "optionalDependencies": { - "bcrypt": "1.0.3", - "uws": "^9.14.0" + "bcrypt": "3.0.0", + "uws": "10.148.1" }, "collective": { "type": "opencollective", diff --git a/postinstall.js b/postinstall.js new file mode 100644 index 0000000000..fef1fb31ff --- /dev/null +++ b/postinstall.js @@ -0,0 +1,50 @@ +const pkg = require('./package.json'); + +const version = parseFloat(process.version.substr(1)); +const minimum = parseFloat(pkg.engines.node.match(/\d+/g).join('.')); + +module.exports = function () { + const openCollective = ` + 1111111111 + 1111111111111111 + 1111111111111111111111 + 11111111111111111111111111 + 111111111111111 11111111 + 1111111111111 111111 + 1111111111111 111111111 111111 + 111111111111 11111111111 111111 + 1111111111111 11111111111 111111 + 1111111111111 1111111111 111111 + 1111111111111111111111111 1111111 + 11111111 11111111 + 111111 1111111111111111111 + 11111 11111 111111111111111111 + 11111 11111111111111111 + 111111 111111111111111111 + 11111111111111111111111111 + 1111111111111111111111 + 111111111111111111 + 11111111111 + + + Thanks for installing parse 🙏 + Please consider donating to our open collective + to help us maintain this package. + + 👉 https://opencollective.com/parse-server + + `; + process.stdout.write(openCollective); + if (version >= minimum) { + process.exit(0); + } + + const errorMessage = ` + ⚠️ parse-server requires at least node@${minimum}! + You have node@${version} + + `; + + process.stdout.write(errorMessage); + process.exit(1); +}; diff --git a/resources/npm-git.sh b/resources/npm-git.sh deleted file mode 100755 index c538b77fd7..0000000000 --- a/resources/npm-git.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -e - -# This script maintains a git branch which mirrors master but in a form that -# what will eventually be deployed to npm, allowing npm dependencies to use: -# -# "parse-server": "parseplatform/parse-server#latest" -# - -# From: https://github.com/graphql/graphql-js/blob/master/resources/npm-git.sh - -BUILD_DIR=latest -BRANCH="${TRAVIS_BRANCH}" -TARGET="latest" -if [ "$BRANCH" != "master" ]; -then - TARGET="$BRANCH-preview" -fi - -npm run build - -mkdir -p $BUILD_DIR - -cp package.json $BUILD_DIR/ -cp README.md $BUILD_DIR/ -cp LICENSE $BUILD_DIR/ -cp PATENTS $BUILD_DIR/ -cp CHANGELOG.md $BUILD_DIR/ -cp -R lib $BUILD_DIR -cp -R bin $BUILD_DIR -cp -R public_html $BUILD_DIR -cp -R views $BUILD_DIR - -cd $BUILD_DIR -git init -git config user.name "Travis CI" -git config user.email "github@fb.com" -git add . -git commit -m "Deploy $BRANCH to $TARGET branch" -git push --force --quiet "https://${GH_TOKEN}@github.com/parse-community/parse-server.git" master:$TARGET diff --git a/spec/.babelrc b/spec/.babelrc new file mode 100644 index 0000000000..a611705cd0 --- /dev/null +++ b/spec/.babelrc @@ -0,0 +1,14 @@ +{ + "plugins": [ + "transform-object-rest-spread" + ], + "presets": [ + ["env", { + "targets": { + "node": "8" + } + }] + ], + "sourceMaps": "inline", + "retainLines": true +} diff --git a/spec/AccountLockoutPolicy.spec.js b/spec/AccountLockoutPolicy.spec.js index 94d3067258..099b762c79 100644 --- a/spec/AccountLockoutPolicy.spec.js +++ b/spec/AccountLockoutPolicy.spec.js @@ -1,6 +1,6 @@ "use strict"; -const Config = require("../src/Config"); +const Config = require("../lib/Config"); const loginWithWrongCredentialsShouldFail = function(username, password) { return new Promise((resolve, reject) => { diff --git a/spec/AdaptableController.spec.js b/spec/AdaptableController.spec.js index 2bb61adde5..3e4ab74468 100644 --- a/spec/AdaptableController.spec.js +++ b/spec/AdaptableController.spec.js @@ -1,7 +1,7 @@ -const AdaptableController = require("../src/Controllers/AdaptableController").AdaptableController; -const FilesAdapter = require("../src/Adapters/Files/FilesAdapter").default; -const FilesController = require("../src/Controllers/FilesController").FilesController; +const AdaptableController = require("../lib/Controllers/AdaptableController").AdaptableController; +const FilesAdapter = require("../lib/Adapters/Files/FilesAdapter").default; +const FilesController = require("../lib/Controllers/FilesController").FilesController; const MockController = function(options) { AdaptableController.call(this, options); @@ -70,7 +70,7 @@ describe("AdaptableController", ()=>{ done(); }); - it("should accept an object adapter", (done) => { + it("should accept an prototype based object adapter", (done) => { function AGoodAdapter() {} AGoodAdapter.prototype.createFile = function() { }; AGoodAdapter.prototype.deleteFile = function() { }; diff --git a/spec/AdapterLoader.spec.js b/spec/AdapterLoader.spec.js index 7afec6fd67..334232f4a7 100644 --- a/spec/AdapterLoader.spec.js +++ b/spec/AdapterLoader.spec.js @@ -1,9 +1,9 @@ -const loadAdapter = require("../src/Adapters/AdapterLoader").loadAdapter; +const loadAdapter = require("../lib/Adapters/AdapterLoader").loadAdapter; const FilesAdapter = require("@parse/fs-files-adapter").default; const S3Adapter = require("@parse/s3-files-adapter").default; const ParsePushAdapter = require("@parse/push-adapter").default; -const Config = require('../src/Config'); +const Config = require('../lib/Config'); describe("AdapterLoader", ()=>{ @@ -33,7 +33,7 @@ describe("AdapterLoader", ()=>{ }); it("should instantiate an adapter from string that is module", (done) => { - const adapterPath = require('path').resolve("./src/Adapters/Files/FilesAdapter"); + const adapterPath = require('path').resolve("./lib/Adapters/Files/FilesAdapter"); const adapter = loadAdapter({ adapter: adapterPath }); diff --git a/spec/AudienceRouter.spec.js b/spec/AudienceRouter.spec.js index d5e635d665..6b977b8f31 100644 --- a/spec/AudienceRouter.spec.js +++ b/spec/AudienceRouter.spec.js @@ -1,7 +1,7 @@ -const auth = require('../src/Auth'); -const Config = require('../src/Config'); -const rest = require('../src/rest'); -const AudiencesRouter = require('../src/Routers/AudiencesRouter').AudiencesRouter; +const auth = require('../lib/Auth'); +const Config = require('../lib/Config'); +const rest = require('../lib/rest'); +const AudiencesRouter = require('../lib/Routers/AudiencesRouter').AudiencesRouter; describe('AudiencesRouter', () => { it('uses find condition from request.body', (done) => { diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 5802f72d31..a4d97639f0 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -1,5 +1,5 @@ describe('Auth', () => { - const Auth = require('../src/Auth.js').Auth; + const Auth = require('../lib/Auth.js').Auth; describe('getUserRoles', () => { let auth; diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index ad77d0b7c7..f7d1d645c1 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -1,13 +1,13 @@ const request = require('request'); -const Config = require("../src/Config"); -const defaultColumns = require('../src/Controllers/SchemaController').defaultColumns; -const authenticationLoader = require('../src/Adapters/Auth'); +const Config = require("../lib/Config"); +const defaultColumns = require('../lib/Controllers/SchemaController').defaultColumns; +const authenticationLoader = require('../lib/Adapters/Auth'); const path = require('path'); describe('AuthenticationProviders', function() { ["facebook", "facebookaccountkit", "github", "instagram", "google", "linkedin", "meetup", "twitter", "janrainengage", "janraincapture", "vkontakte"].map(function(providerName){ it("Should validate structure of " + providerName, (done) => { - const provider = require("../src/Adapters/Auth/" + providerName); + const provider = require("../lib/Adapters/Auth/" + providerName); jequal(typeof provider.validateAuthData, "function"); jequal(typeof provider.validateAppId, "function"); const authDataPromise = provider.validateAuthData({}, {}); @@ -301,7 +301,7 @@ describe('AuthenticationProviders', function() { }) }); - it('properly loads custom adapter module object', (done) => { + it('properly loads custom adapter module object (again)', (done) => { const authenticationHandler = authenticationLoader({ customAuthentication: { module: path.resolve('./spec/support/CustomAuthFunction.js'), options: { token: 'valid-token' }} }); diff --git a/spec/CLI.spec.js b/spec/CLI.spec.js index 066bd64455..36056fd1f5 100644 --- a/spec/CLI.spec.js +++ b/spec/CLI.spec.js @@ -1,7 +1,7 @@ 'use strict'; -import commander from '../src/cli/utils/commander'; -import definitions from '../src/cli/definitions/parse-server'; -import liveQueryDefinitions from '../src/cli/definitions/parse-live-query-server'; +const commander = require('../lib/cli/utils/commander').default; +const definitions = require('../lib/cli/definitions/parse-server').default; +const liveQueryDefinitions = require('../lib/cli/definitions/parse-live-query-server').default; const testDefinitions = { 'arg0': 'PROGRAM_ARG_0', @@ -173,7 +173,7 @@ describe('LiveQuery definitions', () => { if (typeof definition.env !== 'undefined') { expect(typeof definition.env).toBe('string'); } - expect(typeof definition.help).toBe('string'); + expect(typeof definition.help).toBe('string', `help for ${key} should be a string`); if (typeof definition.required !== 'undefined') { expect(typeof definition.required).toBe('boolean'); } diff --git a/spec/CacheController.spec.js b/spec/CacheController.spec.js index 219dc89dd8..ec37ae6b2b 100644 --- a/spec/CacheController.spec.js +++ b/spec/CacheController.spec.js @@ -1,4 +1,4 @@ -const CacheController = require('../src/Controllers/CacheController.js').default; +const CacheController = require('../lib/Controllers/CacheController.js').default; describe('CacheController', function() { let FakeCacheAdapter; diff --git a/spec/Client.spec.js b/spec/Client.spec.js index 403c8e5aef..b95b673d6f 100644 --- a/spec/Client.spec.js +++ b/spec/Client.spec.js @@ -1,5 +1,5 @@ -const Client = require('../src/LiveQuery/Client').Client; -const ParseWebSocket = require('../src/LiveQuery/ParseWebSocketServer').ParseWebSocket; +const Client = require('../lib/LiveQuery/Client').Client; +const ParseWebSocket = require('../lib/LiveQuery/ParseWebSocketServer').ParseWebSocket; describe('Client', function() { it('can be initialized', function() { diff --git a/spec/ClientSDK.spec.js b/spec/ClientSDK.spec.js index 90766a8590..3825681748 100644 --- a/spec/ClientSDK.spec.js +++ b/spec/ClientSDK.spec.js @@ -1,4 +1,4 @@ -const ClientSDK = require('../src/ClientSDK'); +const ClientSDK = require('../lib/ClientSDK'); describe('ClientSDK', () => { it('should properly parse the SDK versions', () => { diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 98e52e056e..978aa9c3aa 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1,7 +1,7 @@ "use strict" const Parse = require("parse/node"); const rp = require('request-promise'); -const InMemoryCacheAdapter = require('../src/Adapters/Cache/InMemoryCacheAdapter').InMemoryCacheAdapter; +const InMemoryCacheAdapter = require('../lib/Adapters/Cache/InMemoryCacheAdapter').InMemoryCacheAdapter; describe('Cloud Code', () => { it('can load absolute cloud code file', done => { @@ -983,7 +983,7 @@ describe('Cloud Code', () => { TODO: fix for Postgres trying to delete a field that doesn't exists doesn't play nice */ - it_exclude_dbs(['postgres'])('should fully delete objects when using `unset` with beforeSave (regression test for #1840)', done => { + it_exclude_dbs(['postgres'])('should fully delete objects when using `unset` and `set` with beforeSave (regression test for #1840)', done => { const TestObject = Parse.Object.extend('TestObject'); const BeforeSaveObject = Parse.Object.extend('BeforeSaveChanged'); diff --git a/spec/CloudCodeLogger.spec.js b/spec/CloudCodeLogger.spec.js index 7289136169..ce4c59bc35 100644 --- a/spec/CloudCodeLogger.spec.js +++ b/spec/CloudCodeLogger.spec.js @@ -1,5 +1,5 @@ -const LoggerController = require('../src/Controllers/LoggerController').LoggerController; -const WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; +const LoggerController = require('../lib/Controllers/LoggerController').LoggerController; +const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; const fs = require('fs'); const loremFile = __dirname + '/support/lorem.txt'; diff --git a/spec/DatabaseController.spec.js b/spec/DatabaseController.spec.js index 43e85ccf87..fe9ee8069e 100644 --- a/spec/DatabaseController.spec.js +++ b/spec/DatabaseController.spec.js @@ -1,4 +1,4 @@ -const DatabaseController = require('../src/Controllers/DatabaseController.js'); +const DatabaseController = require('../lib/Controllers/DatabaseController.js'); const validateQuery = DatabaseController._validateQuery; describe('DatabaseController', function() { diff --git a/spec/EmailVerificationToken.spec.js b/spec/EmailVerificationToken.spec.js index b6e05a29e2..0585831aee 100644 --- a/spec/EmailVerificationToken.spec.js +++ b/spec/EmailVerificationToken.spec.js @@ -2,7 +2,7 @@ const request = require('request'); const requestp = require('request-promise'); -const Config = require('../src/Config'); +const Config = require('../lib/Config'); describe("Email Verification Token Expiration: ", () => { diff --git a/spec/EnableExpressErrorHandler.spec.js b/spec/EnableExpressErrorHandler.spec.js new file mode 100644 index 0000000000..648e986c2a --- /dev/null +++ b/spec/EnableExpressErrorHandler.spec.js @@ -0,0 +1,66 @@ +const ParseServer = require("../lib/index"); +const express = require('express'); +const rp = require('request-promise'); + +describe('Enable express error handler', () => { + + it('should call the default handler in case of error, like updating a non existing object', done => { + const serverUrl = "http://localhost:12667/parse" + const appId = "anOtherTestApp"; + const masterKey = "anOtherTestMasterKey"; + let server; + + let lastError; + + const parseServer = ParseServer.ParseServer(Object.assign({}, + defaultConfiguration, { + appId: appId, + masterKey: masterKey, + serverURL: serverUrl, + enableExpressErrorHandler: true, + __indexBuildCompletionCallbackForTests: promise => { + promise.then(() => { + expect(Parse.applicationId).toEqual("anOtherTestApp"); + const app = express(); + app.use('/parse', parseServer); + + server = app.listen(12667); + + app.use(function (err, req, res, next) { + next; + lastError = err; + }) + + rp({ + method: 'PUT', + uri: serverUrl + '/classes/AnyClass/nonExistingId', + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': masterKey + }, + body: { someField: "blablabla" }, + json: true + }).then(() => { + fail('Should throw error'); + }).catch(e => { + expect(e).toBeDefined(); + const reqError = e.error; + expect(reqError).toBeDefined(); + expect(lastError).toBeDefined(); + + expect(lastError.code).toEqual(101) + expect(lastError.message).toEqual('Object not found.') + + expect(lastError.code).toEqual(reqError.code); + expect(lastError.message).toEqual(reqError.error); + }).then(() => { + server.close(done); + }); + }) + } + } + )); + }); + +}); + diff --git a/spec/EnableSingleSchemaCache.spec.js b/spec/EnableSingleSchemaCache.spec.js index 2638c56e46..386d186a3e 100644 --- a/spec/EnableSingleSchemaCache.spec.js +++ b/spec/EnableSingleSchemaCache.spec.js @@ -1,6 +1,6 @@ -const auth = require('../src/Auth'); -const Config = require('../src/Config'); -const rest = require('../src/rest'); +const auth = require('../lib/Auth'); +const Config = require('../lib/Config'); +const rest = require('../lib/rest'); describe('Enable single schema cache', () => { beforeEach((done) => { diff --git a/spec/EventEmitterPubSub.spec.js b/spec/EventEmitterPubSub.spec.js index 2ac94e4f88..99b4f51df4 100644 --- a/spec/EventEmitterPubSub.spec.js +++ b/spec/EventEmitterPubSub.spec.js @@ -1,4 +1,4 @@ -const EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; +const EventEmitterPubSub = require('../lib/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; describe('EventEmitterPubSub', function() { it('can publish and subscribe', function() { diff --git a/spec/FilesController.spec.js b/spec/FilesController.spec.js index 3cb5f3e3fa..21432793a6 100644 --- a/spec/FilesController.spec.js +++ b/spec/FilesController.spec.js @@ -1,8 +1,8 @@ -const LoggerController = require('../src/Controllers/LoggerController').LoggerController; -const WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; -const GridStoreAdapter = require("../src/Adapters/Files/GridStoreAdapter").GridStoreAdapter; -const Config = require("../src/Config"); -const FilesController = require('../src/Controllers/FilesController').default; +const LoggerController = require('../lib/Controllers/LoggerController').LoggerController; +const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; +const GridStoreAdapter = require("../lib/Adapters/Files/GridStoreAdapter").GridStoreAdapter; +const Config = require("../lib/Config"); +const FilesController = require('../lib/Controllers/FilesController').default; const mockAdapter = { createFile: () => { @@ -14,13 +14,13 @@ const mockAdapter = { } // Small additional tests to improve overall coverage -describe("FilesController",() =>{ +describe("FilesController", () => { it("should properly expand objects", (done) => { const config = Config.get(Parse.applicationId); const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse'); const filesController = new FilesController(gridStoreAdapter) - const result = filesController.expandFilesInObject(config, function(){}); + const result = filesController.expandFilesInObject(config, function () { }); expect(result).toBeUndefined(); @@ -43,7 +43,7 @@ describe("FilesController",() =>{ reconfigureServer({ filesAdapter: mockAdapter }) .then(() => new Promise(resolve => setTimeout(resolve, 1000))) - .then(() => new Parse.File("yolo.txt", [1,2,3], "text/plain").save()) + .then(() => new Parse.File("yolo.txt", [1, 2, 3], "text/plain").save()) .then( () => done.fail('should not succeed'), () => setImmediate(() => Parse.Promise.as('done')) @@ -62,4 +62,40 @@ describe("FilesController",() =>{ done(); }); }); + + it("should add a unique hash to the file name when the preserveFileName option is false", (done) => { + + const config = Config.get(Parse.applicationId) + const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse') + spyOn(gridStoreAdapter, 'createFile') + gridStoreAdapter.createFile.and.returnValue(Promise.resolve()) + const fileName = 'randomFileName.pdf' + const regexEscapedFileName = fileName.replace(/\./g, "\\$&") + const filesController = new FilesController(gridStoreAdapter, null, { preserveFileName: false }) + + filesController.createFile(config, fileName) + + expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1) + expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toMatch(`^.{32}_${regexEscapedFileName}$`) + + done(); + }); + + it("should not add a unique hash to the file name when the preserveFileName option is true", (done) => { + + const config = Config.get(Parse.applicationId) + const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse') + spyOn(gridStoreAdapter, 'createFile') + gridStoreAdapter.createFile.and.returnValue(Promise.resolve()) + const fileName = 'randomFileName.pdf' + const filesController = new FilesController(gridStoreAdapter, null, { preserveFileName: true }) + + filesController.createFile(config, fileName) + + expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1) + expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toEqual(fileName) + + done(); + }); + }); diff --git a/spec/GridStoreAdapter.js b/spec/GridStoreAdapter.js index 2cc16fdbbd..d408430dfd 100644 --- a/spec/GridStoreAdapter.js +++ b/spec/GridStoreAdapter.js @@ -1,9 +1,9 @@ const MongoClient = require("mongodb").MongoClient; const GridStore = require("mongodb").GridStore; -const GridStoreAdapter = require("../src/Adapters/Files/GridStoreAdapter").GridStoreAdapter; -const Config = require("../src/Config"); -const FilesController = require('../src/Controllers/FilesController').default; +const GridStoreAdapter = require("../lib/Adapters/Files/GridStoreAdapter").GridStoreAdapter; +const Config = require("../lib/Config"); +const FilesController = require('../lib/Controllers/FilesController').default; // Small additional tests to improve overall coverage diff --git a/spec/HTTPRequest.spec.js b/spec/HTTPRequest.spec.js index 5ea67f2619..7ccabd1d01 100644 --- a/spec/HTTPRequest.spec.js +++ b/spec/HTTPRequest.spec.js @@ -1,42 +1,52 @@ 'use strict'; -const httpRequest = require("../src/cloud-code/httpRequest"), - HTTPResponse = require('../src/cloud-code/HTTPResponse').default, +const httpRequest = require("../lib/cloud-code/httpRequest"), + HTTPResponse = require('../lib/cloud-code/HTTPResponse').default, bodyParser = require('body-parser'), express = require("express"); const port = 13371; const httpRequestServer = "http://localhost:" + port; -const app = express(); -app.use(bodyParser.json({ 'type': '*/*' })); -app.get("/hello", function(req, res){ - res.json({response: "OK"}); -}); - -app.get("/404", function(req, res){ - res.status(404); - res.send("NO"); -}); +function startServer(done) { + const app = express(); + app.use(bodyParser.json({ 'type': '*/*' })); + app.get("/hello", function(req, res){ + res.json({response: "OK"}); + }); -app.get("/301", function(req, res){ - res.status(301); - res.location("/hello"); - res.send(); -}); + app.get("/404", function(req, res){ + res.status(404); + res.send("NO"); + }); -app.post('/echo', function(req, res){ - res.json(req.body); -}); + app.get("/301", function(req, res){ + res.status(301); + res.location("/hello"); + res.send(); + }); -app.get('/qs', function(req, res){ - res.json(req.query); -}); + app.post('/echo', function(req, res){ + res.json(req.body); + }); -app.listen(13371); + app.get('/qs', function(req, res){ + res.json(req.query); + }); + return app.listen(13371, undefined, done); +} describe("httpRequest", () => { + let server; + beforeAll((done) => { + server = startServer(done); + }); + + afterAll((done) => { + server.close(done); + }); + it("should do /hello", (done) => { httpRequest({ url: httpRequestServer + "/hello" @@ -122,21 +132,6 @@ describe("httpRequest", () => { }); }) - it("should fail on 404", (done) => { - httpRequest({ - url: httpRequestServer + "/404", - }).then(function(){ - fail("should not succeed"); - done(); - }, function(httpResponse){ - expect(httpResponse.status).toBe(404); - expect(httpResponse.buffer).toEqual(new Buffer('NO')); - expect(httpResponse.text).toEqual('NO'); - expect(httpResponse.data).toBe(undefined); - done(); - }) - }) - it("should post on echo", (done) => { let calls = 0; httpRequest({ @@ -204,6 +199,7 @@ describe("httpRequest", () => { it("should fail gracefully", (done) => { httpRequest({ url: "http://not a good url", + timeout: 10, success: function() { fail("should not succeed"); done(); diff --git a/spec/InMemoryCache.spec.js b/spec/InMemoryCache.spec.js index c5c7cd3810..c8f015497a 100644 --- a/spec/InMemoryCache.spec.js +++ b/spec/InMemoryCache.spec.js @@ -1,4 +1,4 @@ -const InMemoryCache = require('../src/Adapters/Cache/InMemoryCache').default; +const InMemoryCache = require('../lib/Adapters/Cache/InMemoryCache').default; describe('InMemoryCache', function() { @@ -28,7 +28,7 @@ describe('InMemoryCache', function() { let value = cache.get(KEY); expect(value).toEqual(VALUE); - wait(BASE_TTL.ttl * 2).then(() => { + wait(BASE_TTL.ttl * 10).then(() => { value = cache.get(KEY) expect(value).toEqual(null); done(); diff --git a/spec/InMemoryCacheAdapter.spec.js b/spec/InMemoryCacheAdapter.spec.js index ac041a7533..9bf49f087c 100644 --- a/spec/InMemoryCacheAdapter.spec.js +++ b/spec/InMemoryCacheAdapter.spec.js @@ -1,4 +1,4 @@ -const InMemoryCacheAdapter = require('../src/Adapters/Cache/InMemoryCacheAdapter').default; +const InMemoryCacheAdapter = require('../lib/Adapters/Cache/InMemoryCacheAdapter').default; describe('InMemoryCacheAdapter', function() { const KEY = 'hello'; diff --git a/spec/InstallationsRouter.spec.js b/spec/InstallationsRouter.spec.js index 47dd6df290..7337096735 100644 --- a/spec/InstallationsRouter.spec.js +++ b/spec/InstallationsRouter.spec.js @@ -1,7 +1,7 @@ -const auth = require('../src/Auth'); -const Config = require('../src/Config'); -const rest = require('../src/rest'); -const InstallationsRouter = require('../src/Routers/InstallationsRouter').InstallationsRouter; +const auth = require('../lib/Auth'); +const Config = require('../lib/Config'); +const rest = require('../lib/rest'); +const InstallationsRouter = require('../lib/Routers/InstallationsRouter').InstallationsRouter; describe('InstallationsRouter', () => { it('uses find condition from request.body', (done) => { diff --git a/spec/JobSchedule.spec.js b/spec/JobSchedule.spec.js index bd8ca3070b..def48e180f 100644 --- a/spec/JobSchedule.spec.js +++ b/spec/JobSchedule.spec.js @@ -50,11 +50,11 @@ describe('JobSchedule', () => { rp.put(Parse.serverURL + '/cloud_code/jobs/jobId', defaultOptions).then(done.fail, () => done()); }); - it('should reject access when not using masterKey (PUT /jobs/id)', (done) => { + it('should reject access when not using masterKey (DELETE /jobs/id)', (done) => { rp.del(Parse.serverURL + '/cloud_code/jobs/jobId', defaultOptions).then(done.fail, () => done()); }); - it('should allow access when using masterKey (/jobs)', (done) => { + it('should allow access when using masterKey (GET /jobs)', (done) => { rp.get(Parse.serverURL + '/cloud_code/jobs', masterKeyOptions).then(done, done.fail); }); diff --git a/spec/Logger.spec.js b/spec/Logger.spec.js index ee35e353fe..bd268fa78e 100644 --- a/spec/Logger.spec.js +++ b/spec/Logger.spec.js @@ -1,4 +1,4 @@ -const logging = require('../src/Adapters/Logger/WinstonLogger'); +const logging = require('../lib/Adapters/Logger/WinstonLogger'); const winston = require('winston'); class TestTransport extends winston.Transport { diff --git a/spec/LoggerController.spec.js b/spec/LoggerController.spec.js index 4a8e63f4d3..36306b662a 100644 --- a/spec/LoggerController.spec.js +++ b/spec/LoggerController.spec.js @@ -1,8 +1,8 @@ -const LoggerController = require('../src/Controllers/LoggerController').LoggerController; -const WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; +const LoggerController = require('../lib/Controllers/LoggerController').LoggerController; +const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; describe('LoggerController', () => { - it('can check process a query without throwing', (done) => { + it('can process an empty query without throwing', (done) => { // Make mock request const query = {}; @@ -37,7 +37,7 @@ describe('LoggerController', () => { done(); }); - it('can process a query without throwing', (done) => { + it('can process an ascending query without throwing', (done) => { // Make mock request const query = { from: "2016-01-01Z00:00:00", @@ -58,7 +58,7 @@ describe('LoggerController', () => { done(); }); - it('can check process a query without throwing', (done) => { + it('can process a descending query without throwing', (done) => { // Make mock request const query = { from: "2016-01-01", diff --git a/spec/LogsRouter.spec.js b/spec/LogsRouter.spec.js index 65c8b62f5b..38de9ac318 100644 --- a/spec/LogsRouter.spec.js +++ b/spec/LogsRouter.spec.js @@ -1,9 +1,9 @@ 'use strict'; const request = require('request'); -const LogsRouter = require('../src/Routers/LogsRouter').LogsRouter; -const LoggerController = require('../src/Controllers/LoggerController').LoggerController; -const WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; +const LogsRouter = require('../lib/Routers/LogsRouter').LogsRouter; +const LoggerController = require('../lib/Controllers/LoggerController').LoggerController; +const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; const loggerController = new LoggerController(new WinstonLoggerAdapter()); diff --git a/spec/Middlewares.spec.js b/spec/Middlewares.spec.js index 0b1ea593f3..32e44a3cc8 100644 --- a/spec/Middlewares.spec.js +++ b/spec/Middlewares.spec.js @@ -1,5 +1,5 @@ -const middlewares = require('../src/middlewares'); -const AppCache = require('../src/cache').AppCache; +const middlewares = require('../lib/middlewares'); +const AppCache = require('../lib/cache').AppCache; describe('middlewares', () => { @@ -290,4 +290,16 @@ describe('middlewares', () => { middlewares.handleParseHeaders(fakeReq, fakeRes); expect(fakeRes.status).toHaveBeenCalledWith(403); }); + + it('should properly expose the headers', () => { + const headers = {}; + const res = { + header: (key, value) => { + headers[key] = value + } + }; + middlewares.allowCrossDomain({}, res, () => {}); + expect(Object.keys(headers).length).toBe(4); + expect(headers['Access-Control-Expose-Headers']).toBe('X-Parse-Job-Status-Id, X-Parse-Push-Status-Id'); + }); }); diff --git a/spec/MongoSchemaCollectionAdapter.spec.js b/spec/MongoSchemaCollectionAdapter.spec.js index f5f75442f6..fe3d842a53 100644 --- a/spec/MongoSchemaCollectionAdapter.spec.js +++ b/spec/MongoSchemaCollectionAdapter.spec.js @@ -1,6 +1,6 @@ 'use strict'; -const MongoSchemaCollection = require('../src/Adapters/Storage/Mongo/MongoSchemaCollection').default; +const MongoSchemaCollection = require('../lib/Adapters/Storage/Mongo/MongoSchemaCollection').default; describe('MongoSchemaCollection', () => { it('can transform legacy _client_permissions keys to parse format', done => { diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index b263f70dad..d46c925308 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -1,6 +1,6 @@ 'use strict'; -import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter'; +const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; const { MongoClient } = require('mongodb'); const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase'; @@ -61,7 +61,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 }, @@ -90,8 +90,8 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }, (err) => { expect(err.name).toEqual('MongoError'); - expect(err.code).toEqual(50); - expect(err.message).toEqual('operation exceeded time limit'); + expect(err.code).toEqual(96); + expect(err.message).toContain('operation exceeded time limit'); done(); } ); diff --git a/spec/MongoTransform.spec.js b/spec/MongoTransform.spec.js index 5489d95223..c38346c123 100644 --- a/spec/MongoTransform.spec.js +++ b/spec/MongoTransform.spec.js @@ -1,7 +1,7 @@ // These tests are unit tests designed to only test transform.js. "use strict"; -const transform = require('../src/Adapters/Storage/Mongo/MongoTransform'); +const transform = require('../lib/Adapters/Storage/Mongo/MongoTransform'); const dd = require('deep-diff'); const mongodb = require('mongodb'); @@ -24,7 +24,7 @@ describe('parseObjectToMongoObjectForCreate', () => { done(); }); - it('built-in timestamps', (done) => { + it('built-in timestamps with date', (done) => { const input = { createdAt: "2015-10-06T21:24:50.332Z", updatedAt: "2015-10-06T21:24:50.332Z" @@ -353,6 +353,41 @@ describe('parseObjectToMongoObjectForCreate', () => { expect(output.ts.iso).toEqual('2017-01-18T00:00:00.000Z'); done(); }); + + it('$regex in $all list', (done) => { + const input = { + arrayField: {'$all': [{$regex: '^\\Qone\\E'}, {$regex: '^\\Qtwo\\E'}, {$regex: '^\\Qthree\\E'}]}, + }; + const outputValue = { + arrayField: {'$all': [/^\Qone\E/, /^\Qtwo\E/, /^\Qthree\E/]}, + }; + + const output = transform.transformWhere(null, input); + jequal(outputValue.arrayField, output.arrayField); + done(); + }); + + it('$regex in $all list must be { $regex: "string" }', (done) => { + const input = { + arrayField: {'$all': [{$regex: 1}]}, + }; + + expect(() => { + transform.transformWhere(null, input) + }).toThrow(); + done(); + }); + + it('all values in $all must be $regex (start with string) or non $regex (start with string)', (done) => { + const input = { + arrayField: {'$all': [{$regex: '^\\Qone\\E'}, {$unknown: '^\\Qtwo\\E'}]}, + }; + + expect(() => { + transform.transformWhere(null, input) + }).toThrow(); + done(); + }); }); describe('transformUpdate', () => { diff --git a/spec/NullCacheAdapter.spec.js b/spec/NullCacheAdapter.spec.js index d1d6b0a91e..04d4cdcd68 100644 --- a/spec/NullCacheAdapter.spec.js +++ b/spec/NullCacheAdapter.spec.js @@ -1,4 +1,4 @@ -const NullCacheAdapter = require('../src/Adapters/Cache/NullCacheAdapter').default; +const NullCacheAdapter = require('../lib/Adapters/Cache/NullCacheAdapter').default; describe('NullCacheAdapter', function() { const KEY = 'hello'; diff --git a/spec/OAuth1.spec.js b/spec/OAuth1.spec.js index 31b683163c..ed74bfb9e8 100644 --- a/spec/OAuth1.spec.js +++ b/spec/OAuth1.spec.js @@ -1,4 +1,4 @@ -const OAuth = require("../src/Adapters/Auth/OAuth1Client"); +const OAuth = require("../lib/Adapters/Auth/OAuth1Client"); describe('OAuth', function() { it("Nonce should have right length", (done) => { diff --git a/spec/ParseACL.spec.js b/spec/ParseACL.spec.js index 8398ccba94..3069bd12b5 100644 --- a/spec/ParseACL.spec.js +++ b/spec/ParseACL.spec.js @@ -1,8 +1,8 @@ // This is a port of the test suite: // hungry/js/test/parse_acl_test.js -const rest = require('../src/rest'); -const Config = require('../src/Config'); -const auth = require('../src/Auth'); +const rest = require('../lib/rest'); +const Config = require('../lib/Config'); +const auth = require('../lib/Auth'); describe('Parse.ACL', () => { it("acl must be valid", (done) => { diff --git a/spec/ParseAPI.spec.js b/spec/ParseAPI.spec.js index de16ebb737..5d3861fe42 100644 --- a/spec/ParseAPI.spec.js +++ b/spec/ParseAPI.spec.js @@ -5,9 +5,9 @@ const request = require('request'); const rp = require('request-promise'); const Parse = require("parse/node"); -const Config = require('../src/Config'); -const SchemaController = require('../src/Controllers/SchemaController'); -const TestUtils = require('../src/TestUtils'); +const Config = require('../lib/Config'); +const SchemaController = require('../lib/Controllers/SchemaController'); +const TestUtils = require('../lib/TestUtils'); const userSchema = SchemaController.convertSchemaToAdapterSchema({ className: '_User', fields: Object.assign({}, SchemaController.defaultColumns._Default, SchemaController.defaultColumns._User) }); @@ -975,6 +975,25 @@ describe('miscellaneous', function() { }); }); + it('test beforeDelete with locked down ACL', async () => { + let called = false; + Parse.Cloud.beforeDelete('GameScore', (req, res) => { + called = true; + res.success(); + }); + const object = new Parse.Object('GameScore'); + object.setACL(new Parse.ACL()); + await object.save(); + const objects = await new Parse.Query('GameScore').find(); + expect(objects.length).toBe(0); + try { + await object.destroy(); + } catch(e) { + expect(e.code).toBe(Parse.Error.OBJECT_NOT_FOUND); + } + expect(called).toBe(false); + }); + it('test cloud function query parameters', (done) => { Parse.Cloud.define('echoParams', (req, res) => { res.success(req.params); @@ -1493,6 +1512,11 @@ describe('miscellaneous', function() { }); }); + it('purge empty class', (done) => { + const testSchema = new Parse.Schema('UnknownClass'); + testSchema.purge().then(done).catch(done.fail); + }); + it('should not update schema beforeSave #2672', (done) => { Parse.Cloud.beforeSave('MyObject', (request, response) => { if (request.object.get('secret')) { diff --git a/spec/ParseCloudCodePublisher.spec.js b/spec/ParseCloudCodePublisher.spec.js index 00e6a87943..1c242d9d7d 100644 --- a/spec/ParseCloudCodePublisher.spec.js +++ b/spec/ParseCloudCodePublisher.spec.js @@ -1,4 +1,4 @@ -const ParseCloudCodePublisher = require('../src/LiveQuery/ParseCloudCodePublisher').ParseCloudCodePublisher; +const ParseCloudCodePublisher = require('../lib/LiveQuery/ParseCloudCodePublisher').ParseCloudCodePublisher; const Parse = require('parse/node'); describe('ParseCloudCodePublisher', function() { @@ -14,7 +14,7 @@ describe('ParseCloudCodePublisher', function() { on: jasmine.createSpy('on') }) }; - jasmine.mockLibrary('../src/LiveQuery/ParsePubSub', 'ParsePubSub', mockParsePubSub); + jasmine.mockLibrary('../lib/LiveQuery/ParsePubSub', 'ParsePubSub', mockParsePubSub); done(); }); @@ -22,7 +22,7 @@ describe('ParseCloudCodePublisher', function() { const config = {} new ParseCloudCodePublisher(config); - const ParsePubSub = require('../src/LiveQuery/ParsePubSub').ParsePubSub; + const ParsePubSub = require('../lib/LiveQuery/ParsePubSub').ParsePubSub; expect(ParsePubSub.createPublisher).toHaveBeenCalledWith(config); }); @@ -64,6 +64,6 @@ describe('ParseCloudCodePublisher', function() { }); afterEach(function(){ - jasmine.restoreLibrary('../src/LiveQuery/ParsePubSub', 'ParsePubSub'); + jasmine.restoreLibrary('../lib/LiveQuery/ParsePubSub', 'ParsePubSub'); }); }); diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index 9f19a87119..d5f7d38c7f 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -632,24 +632,6 @@ describe('Parse.File testing', () => { }); }); - it('fails to upload without a file name', done => { - const headers = { - 'Content-Type': 'application/octet-stream', - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest' - }; - request.post({ - headers: headers, - url: 'http://localhost:8378/1/files/', - body: 'yolo', - }, (error, response, body) => { - expect(error).toBe(null); - expect(response.statusCode).toBe(400); - expect(body).toEqual('{"code":122,"error":"Filename not provided."}'); - done(); - }); - }); - it('fails to delete an unkown file', done => { const headers = { 'Content-Type': 'application/octet-stream', diff --git a/spec/ParseGeoPoint.spec.js b/spec/ParseGeoPoint.spec.js index 66915c7f80..ec6ec79295 100644 --- a/spec/ParseGeoPoint.spec.js +++ b/spec/ParseGeoPoint.spec.js @@ -496,6 +496,116 @@ describe('Parse.GeoPoint testing', () => { }, done.fail); }); + it('supports withinPolygon Polygon object', (done) => { + const inbound = new Parse.GeoPoint(1.5, 1.5); + const onbound = new Parse.GeoPoint(10, 10); + const outbound = new Parse.GeoPoint(20, 20); + const obj1 = new Parse.Object('Polygon', {location: inbound}); + const obj2 = new Parse.Object('Polygon', {location: onbound}); + const obj3 = new Parse.Object('Polygon', {location: outbound}); + const polygon = { + __type: 'Polygon', + coordinates: [ + [0, 0], + [10, 0], + [10, 10], + [0, 10], + [0, 0] + ] + } + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const where = { + location: { + $geoWithin: { + $polygon: polygon + } + } + }; + return rp.post({ + url: Parse.serverURL + '/classes/Polygon', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + expect(resp.results.length).toBe(2); + done(); + }, done.fail); + }); + + it('invalid Polygon object withinPolygon', (done) => { + const point = new Parse.GeoPoint(1.5, 1.5); + const obj = new Parse.Object('Polygon', {location: point}); + const polygon = { + __type: 'Polygon', + coordinates: [ + [0, 0], + [10, 0], + ] + } + obj.save().then(() => { + const where = { + location: { + $geoWithin: { + $polygon: polygon + } + } + }; + return rp.post({ + url: Parse.serverURL + '/classes/Polygon', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + fail(`no request should succeed: ${JSON.stringify(resp)}`); + done(); + }).catch((err) => { + expect(err.error.code).toEqual(Parse.Error.INVALID_JSON); + done(); + }); + }); + + it('out of bounds Polygon object withinPolygon', (done) => { + const point = new Parse.GeoPoint(1.5, 1.5); + const obj = new Parse.Object('Polygon', {location: point}); + const polygon = { + __type: 'Polygon', + coordinates: [ + [0, 0], + [181, 0], + [0, 10] + ] + } + obj.save().then(() => { + const where = { + location: { + $geoWithin: { + $polygon: polygon + } + } + }; + return rp.post({ + url: Parse.serverURL + '/classes/Polygon', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + fail(`no request should succeed: ${JSON.stringify(resp)}`); + done(); + }).catch((err) => { + expect(err.error.code).toEqual(1); + done(); + }); + }); + it('invalid input withinPolygon', (done) => { const point = new Parse.GeoPoint(1.5, 1.5); const obj = new Parse.Object('Polygon', {location: point}); diff --git a/spec/ParseGlobalConfig.spec.js b/spec/ParseGlobalConfig.spec.js index 46f9c0785c..2e1032a670 100644 --- a/spec/ParseGlobalConfig.spec.js +++ b/spec/ParseGlobalConfig.spec.js @@ -1,7 +1,7 @@ 'use strict'; const request = require('request'); -const Config = require('../src/Config'); +const Config = require('../lib/Config'); describe('a GlobalConfig', () => { beforeEach(done => { diff --git a/spec/ParseHooks.spec.js b/spec/ParseHooks.spec.js index 86dcd8e600..5b8900395c 100644 --- a/spec/ParseHooks.spec.js +++ b/spec/ParseHooks.spec.js @@ -1,20 +1,28 @@ "use strict"; /* global describe, it, expect, fail, Parse */ const request = require('request'); -const triggers = require('../src/triggers'); -const HooksController = require('../src/Controllers/HooksController').default; +const triggers = require('../lib/triggers'); +const HooksController = require('../lib/Controllers/HooksController').default; const express = require("express"); const bodyParser = require('body-parser'); const port = 12345; const hookServerURL = "http://localhost:" + port; -const AppCache = require('../src/cache').AppCache; - -const app = express(); -app.use(bodyParser.json({ 'type': '*/*' })) -app.listen(12345); +const AppCache = require('../lib/cache').AppCache; describe('Hooks', () => { + let server; + let app; + beforeAll((done) => { + app = express(); + app.use(bodyParser.json({ 'type': '*/*' })) + server = app.listen(12345, undefined, done); + }); + + afterAll((done) => { + server.close(done); + }); + it("should have no hooks registered", (done) => { Parse.Hooks.getFunctions().then((res) => { expect(res.constructor).toBe(Array.prototype.constructor); @@ -328,7 +336,7 @@ describe('Hooks', () => { }); }); - it("should run the function on the test server", (done) => { + it("should run the function on the test server (error handling)", (done) => { app.post("/SomeFunctionError", function(req, res) { res.json({error: {code: 1337, error: "hacking that one!"}}); diff --git a/spec/ParseInstallation.spec.js b/spec/ParseInstallation.spec.js index 9102291bcc..853262087f 100644 --- a/spec/ParseInstallation.spec.js +++ b/spec/ParseInstallation.spec.js @@ -2,15 +2,15 @@ // These tests check the Installations functionality of the REST API. // Ported from installation_collection_test.go -const auth = require('../src/Auth'); -const Config = require('../src/Config'); +const auth = require('../lib/Auth'); +const Config = require('../lib/Config'); const Parse = require('parse/node').Parse; -const rest = require('../src/rest'); +const rest = require('../lib/rest'); const request = require("request"); let config; let database; -const defaultColumns = require('../src/Controllers/SchemaController').defaultColumns; +const defaultColumns = require('../lib/Controllers/SchemaController').defaultColumns; const delay = function delay(delay) { return new Promise(resolve => setTimeout(resolve, delay)); diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js index 9f3477476a..6defef456d 100644 --- a/spec/ParseLiveQueryServer.spec.js +++ b/spec/ParseLiveQueryServer.spec.js @@ -1,6 +1,6 @@ const Parse = require('parse/node'); -const ParseLiveQueryServer = require('../src/LiveQuery/ParseLiveQueryServer').ParseLiveQueryServer; -const ParseServer = require('../src/ParseServer').default; +const ParseLiveQueryServer = require('../lib/LiveQuery/ParseLiveQueryServer').ParseLiveQueryServer; +const ParseServer = require('../lib/ParseServer').default; // Global mock info const queryHashValue = 'hash'; @@ -11,7 +11,7 @@ describe('ParseLiveQueryServer', function() { beforeEach(function(done) { // Mock ParseWebSocketServer const mockParseWebSocketServer = jasmine.createSpy('ParseWebSocketServer'); - jasmine.mockLibrary('../src/LiveQuery/ParseWebSocketServer', 'ParseWebSocketServer', mockParseWebSocketServer); + jasmine.mockLibrary('../lib/LiveQuery/ParseWebSocketServer', 'ParseWebSocketServer', mockParseWebSocketServer); // Mock Client const mockClient = function(id, socket, hasMasterKey) { this.pushConnect = jasmine.createSpy('pushConnect'); @@ -28,19 +28,19 @@ describe('ParseLiveQueryServer', function() { this.hasMasterKey = hasMasterKey; } mockClient.pushError = jasmine.createSpy('pushError'); - jasmine.mockLibrary('../src/LiveQuery/Client', 'Client', mockClient); + jasmine.mockLibrary('../lib/LiveQuery/Client', 'Client', mockClient); // Mock Subscription const mockSubscriotion = function() { this.addClientSubscription = jasmine.createSpy('addClientSubscription'); this.deleteClientSubscription = jasmine.createSpy('deleteClientSubscription'); } - jasmine.mockLibrary('../src/LiveQuery/Subscription', 'Subscription', mockSubscriotion); + jasmine.mockLibrary('../lib/LiveQuery/Subscription', 'Subscription', mockSubscriotion); // Mock queryHash const mockQueryHash = jasmine.createSpy('matchesQuery').and.returnValue(queryHashValue); - jasmine.mockLibrary('../src/LiveQuery/QueryTools', 'queryHash', mockQueryHash); + jasmine.mockLibrary('../lib/LiveQuery/QueryTools', 'queryHash', mockQueryHash); // Mock matchesQuery const mockMatchesQuery = jasmine.createSpy('matchesQuery').and.returnValue(true); - jasmine.mockLibrary('../src/LiveQuery/QueryTools', 'matchesQuery', mockMatchesQuery); + jasmine.mockLibrary('../lib/LiveQuery/QueryTools', 'matchesQuery', mockMatchesQuery); // Mock ParsePubSub const mockParsePubSub = { createPublisher: function() { @@ -56,7 +56,7 @@ describe('ParseLiveQueryServer', function() { } } }; - jasmine.mockLibrary('../src/LiveQuery/ParsePubSub', 'ParsePubSub', mockParsePubSub); + jasmine.mockLibrary('../lib/LiveQuery/ParsePubSub', 'ParsePubSub', mockParsePubSub); // Make mock SessionTokenCache const mockSessionTokenCache = function(){ this.getUserId = function(sessionToken){ @@ -69,7 +69,7 @@ describe('ParseLiveQueryServer', function() { return Parse.Promise.as(testUserId); }; }; - jasmine.mockLibrary('../src/LiveQuery/SessionTokenCache', 'SessionTokenCache', mockSessionTokenCache); + jasmine.mockLibrary('../lib/LiveQuery/SessionTokenCache', 'SessionTokenCache', mockSessionTokenCache); done(); }); @@ -102,46 +102,47 @@ describe('ParseLiveQueryServer', function() { parseLiveQueryServer.server.close(done); }); - it('can be initialized through ParseServer without liveQueryServerOptions', function(done) { - const parseServer = ParseServer.start({ - appId: 'hello', - masterKey: 'world', - port: 22345, - mountPath: '/1', - serverURL: 'http://localhost:12345/1', - liveQuery: { - classNames: ['Yolo'] - }, - startLiveQueryServer: true + describe_only_db('mongo')('initialization', () => { + it('can be initialized through ParseServer without liveQueryServerOptions', function(done) { + const parseServer = ParseServer.start({ + appId: 'hello', + masterKey: 'world', + port: 22345, + mountPath: '/1', + serverURL: 'http://localhost:12345/1', + liveQuery: { + classNames: ['Yolo'] + }, + startLiveQueryServer: true + }); + + expect(parseServer.liveQueryServer).not.toBeUndefined(); + expect(parseServer.liveQueryServer.server).toBe(parseServer.server); + parseServer.server.close(() => done()); }); - expect(parseServer.liveQueryServer).not.toBeUndefined(); - expect(parseServer.liveQueryServer.server).toBe(parseServer.server); - parseServer.server.close(() => done()); - }); + it('can be initialized through ParseServer with liveQueryServerOptions', function(done) { + const parseServer = ParseServer.start({ + appId: 'hello', + masterKey: 'world', + port: 22346, + mountPath: '/1', + serverURL: 'http://localhost:12345/1', + liveQuery: { + classNames: ['Yolo'] + }, + liveQueryServerOptions: { + port: 22347, + } + }); - it('can be initialized through ParseServer with liveQueryServerOptions', function(done) { - const parseServer = ParseServer.start({ - appId: 'hello', - masterKey: 'world', - port: 22346, - mountPath: '/1', - serverURL: 'http://localhost:12345/1', - liveQuery: { - classNames: ['Yolo'] - }, - liveQueryServerOptions: { - port: 22347, - } + expect(parseServer.liveQueryServer).not.toBeUndefined(); + expect(parseServer.liveQueryServer.server).not.toBe(parseServer.server); + parseServer.liveQueryServer.server.close(); + parseServer.server.close(() => done()); }); - - expect(parseServer.liveQueryServer).not.toBeUndefined(); - expect(parseServer.liveQueryServer.server).not.toBe(parseServer.server); - parseServer.liveQueryServer.server.close(); - parseServer.server.close(() => done()); }); - it('can handle connect command', function() { const parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {}); const parseWebSocket = { @@ -166,7 +167,7 @@ describe('ParseLiveQueryServer', function() { }; parseLiveQueryServer._handleSubscribe(incompleteParseConn, {}); - const Client = require('../src/LiveQuery/Client').Client; + const Client = require('../lib/LiveQuery/Client').Client; expect(Client.pushError).toHaveBeenCalled(); }); @@ -272,7 +273,7 @@ describe('ParseLiveQueryServer', function() { }; parseLiveQueryServer._handleUnsubscribe(incompleteParseConn, {}); - const Client = require('../src/LiveQuery/Client').Client; + const Client = require('../lib/LiveQuery/Client').Client; expect(Client.pushError).toHaveBeenCalled(); }); @@ -283,7 +284,7 @@ describe('ParseLiveQueryServer', function() { }; parseLiveQueryServer._handleUnsubscribe(parseWebSocket, {}); - const Client = require('../src/LiveQuery/Client').Client; + const Client = require('../lib/LiveQuery/Client').Client; expect(Client.pushError).toHaveBeenCalled(); }); @@ -298,7 +299,7 @@ describe('ParseLiveQueryServer', function() { }; parseLiveQueryServer._handleUnsubscribe(parseWebSocket, {}); - const Client = require('../src/LiveQuery/Client').Client; + const Client = require('../lib/LiveQuery/Client').Client; expect(Client.pushError).toHaveBeenCalled(); }); @@ -444,7 +445,7 @@ describe('ParseLiveQueryServer', function() { const invalidRequest = '{}'; // Trigger message event parseWebSocket.emit('message', invalidRequest); - const Client = require('../src/LiveQuery/Client').Client; + const Client = require('../lib/LiveQuery/Client').Client; expect(Client.pushError).toHaveBeenCalled(); }); @@ -460,7 +461,7 @@ describe('ParseLiveQueryServer', function() { const unknownRequest = '{"op":"unknown"}'; // Trigger message event parseWebSocket.emit('message', unknownRequest); - const Client = require('../src/LiveQuery/Client').Client; + const Client = require('../lib/LiveQuery/Client').Client; expect(Client.pushError).toHaveBeenCalled(); }); @@ -787,7 +788,7 @@ describe('ParseLiveQueryServer', function() { const parseObject = {}; expect(parseLiveQueryServer._matchesSubscription(parseObject, subscription)).toBe(true); // Make sure matchesQuery is called - const matchesQuery = require('../src/LiveQuery/QueryTools').matchesQuery; + const matchesQuery = require('../lib/LiveQuery/QueryTools').matchesQuery; expect(matchesQuery).toHaveBeenCalledWith(parseObject, subscription.query); }); @@ -1208,18 +1209,18 @@ describe('ParseLiveQueryServer', function() { }); afterEach(function(){ - jasmine.restoreLibrary('../src/LiveQuery/ParseWebSocketServer', 'ParseWebSocketServer'); - jasmine.restoreLibrary('../src/LiveQuery/Client', 'Client'); - jasmine.restoreLibrary('../src/LiveQuery/Subscription', 'Subscription'); - jasmine.restoreLibrary('../src/LiveQuery/QueryTools', 'queryHash'); - jasmine.restoreLibrary('../src/LiveQuery/QueryTools', 'matchesQuery'); - jasmine.restoreLibrary('../src/LiveQuery/ParsePubSub', 'ParsePubSub'); - jasmine.restoreLibrary('../src/LiveQuery/SessionTokenCache', 'SessionTokenCache'); + jasmine.restoreLibrary('../lib/LiveQuery/ParseWebSocketServer', 'ParseWebSocketServer'); + jasmine.restoreLibrary('../lib/LiveQuery/Client', 'Client'); + jasmine.restoreLibrary('../lib/LiveQuery/Subscription', 'Subscription'); + jasmine.restoreLibrary('../lib/LiveQuery/QueryTools', 'queryHash'); + jasmine.restoreLibrary('../lib/LiveQuery/QueryTools', 'matchesQuery'); + jasmine.restoreLibrary('../lib/LiveQuery/ParsePubSub', 'ParsePubSub'); + jasmine.restoreLibrary('../lib/LiveQuery/SessionTokenCache', 'SessionTokenCache'); }); // Helper functions to add mock client and subscription to a liveQueryServer function addMockClient(parseLiveQueryServer, clientId) { - const Client = require('../src/LiveQuery/Client').Client; + const Client = require('../lib/LiveQuery/Client').Client; const client = new Client(clientId, {}); parseLiveQueryServer.clients.set(clientId, client); return client; diff --git a/spec/ParseObject.spec.js b/spec/ParseObject.spec.js index aedf251118..954d21a6f4 100644 --- a/spec/ParseObject.spec.js +++ b/spec/ParseObject.spec.js @@ -1980,4 +1980,31 @@ describe('Parse.Object testing', () => { done(); }) }); + + it ('Update object field should store exactly same sent object', async (done) => { + let object = new TestObject(); + + // Set initial data + object.set("jsonData", { a: "b" }); + object = await object.save(); + equal(object.get('jsonData'), { a: "b" }); + + // Set empty JSON + object.set("jsonData", {}); + object = await object.save(); + equal(object.get('jsonData'), {}); + + // Set new JSON data + object.unset('jsonData') + object.set("jsonData", { c: "d" }); + object = await object.save(); + equal(object.get('jsonData'), { c: "d" }); + + // Fetch object from server + object = await object.fetch() + console.log(object.id, object.get('jsonData')) + equal(object.get('jsonData'), { c: "d" }); + + done(); + }); }); diff --git a/spec/ParsePolygon.spec.js b/spec/ParsePolygon.spec.js index 25d4edffa3..2527a09e55 100644 --- a/spec/ParsePolygon.spec.js +++ b/spec/ParsePolygon.spec.js @@ -1,5 +1,5 @@ const TestObject = Parse.Object.extend('TestObject'); -import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter'; +const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase'; const rp = require('request-promise'); const defaultHeaders = { @@ -8,6 +8,9 @@ const defaultHeaders = { } 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]]; @@ -128,144 +131,150 @@ describe('Parse.Polygon testing', () => { }, done.fail); }); - 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 polygon1 = new Parse.Polygon(points1); - const polygon2 = new Parse.Polygon(points2); - const polygon3 = new Parse.Polygon(points3); - const obj1 = new TestObject({location: polygon1}); - const obj2 = new TestObject({location: polygon2}); - const obj3 = new TestObject({location: polygon3}); - Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 0.5, longitude: 0.5 } + describe('with location', () => { + 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 polygon1 = new Parse.Polygon(points1); + const polygon2 = new Parse.Polygon(points2); + const polygon3 = new Parse.Polygon(points3); + const obj1 = new TestObject({location: polygon1}); + const obj2 = new TestObject({location: polygon2}); + const obj3 = new TestObject({location: polygon3}); + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 0.5, longitude: 0.5 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then((resp) => { - expect(resp.results.length).toBe(2); - done(); - }, done.fail); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + expect(resp.results.length).toBe(2); + done(); + }, done.fail); + }); - it('polygonContain query no reverse input (Regression test for #4608)', (done) => { - const points1 = [[.25,0],[.25,1.25],[.75,1.25],[.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); - const obj1 = new TestObject({location: polygon1}); - const obj2 = new TestObject({location: polygon2}); - const obj3 = new TestObject({location: polygon3}); - Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 0.5, longitude:1.0 } + it('polygonContain query no reverse input (Regression test for #4608)', (done) => { + const points1 = [[.25,0],[.25,1.25],[.75,1.25],[.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); + const obj1 = new TestObject({location: polygon1}); + const obj2 = new TestObject({location: polygon2}); + const obj3 = new TestObject({location: polygon3}); + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 0.5, longitude:1.0 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then((resp) => { - expect(resp.results.length).toBe(2); - done(); - }, done.fail); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + expect(resp.results.length).toBe(2); + done(); + }, done.fail); + }); - it('polygonContain query real data (Regression test for #4608)', (done) => { - const detroit = [[42.631655189280224,-83.78406753121705],[42.633047793854814,-83.75333640366955],[42.61625254348911,-83.75149921669944],[42.61526926650296,-83.78161794858735],[42.631655189280224,-83.78406753121705]]; - const polygon = new Parse.Polygon(detroit); - const obj = new TestObject({location: polygon}); - obj.save().then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 42.624599, longitude:-83.770162 } + it('polygonContain query real data (Regression test for #4608)', (done) => { + const detroit = [[42.631655189280224,-83.78406753121705],[42.633047793854814,-83.75333640366955],[42.61625254348911,-83.75149921669944],[42.61526926650296,-83.78161794858735],[42.631655189280224,-83.78406753121705]]; + const polygon = new Parse.Polygon(detroit); + const obj = new TestObject({location: polygon}); + obj.save().then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 42.624599, longitude:-83.770162 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then((resp) => { - expect(resp.results.length).toBe(1); - done(); - }, done.fail); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + expect(resp.results.length).toBe(1); + done(); + }, done.fail); + }); - it('polygonContain invalid input', (done) => { - const points = [[0,0],[0,1],[1,1],[1,0]]; - const polygon = new Parse.Polygon(points); - const obj = new TestObject({location: polygon}); - obj.save().then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 181, longitude: 181 } + it('polygonContain invalid input', (done) => { + const points = [[0,0],[0,1],[1,1],[1,0]]; + const polygon = new Parse.Polygon(points); + const obj = new TestObject({location: polygon}); + obj.save().then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 181, longitude: 181 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then(done.fail, () => done()); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then(done.fail, () => done()); + }); - it('polygonContain invalid geoPoint', (done) => { - const points = [[0,0],[0,1],[1,1],[1,0]]; - const polygon = new Parse.Polygon(points); - const obj = new TestObject({location: polygon}); - obj.save().then(() => { - const where = { - location: { - $geoIntersects: { - $point: [] + it('polygonContain invalid geoPoint', (done) => { + const points = [[0,0],[0,1],[1,1],[1,0]]; + const polygon = new Parse.Polygon(points); + const obj = new TestObject({location: polygon}); + obj.save().then(() => { + const where = { + location: { + $geoIntersects: { + $point: [] + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then(done.fail, () => done()); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then(done.fail, () => done()); + }); }); }); 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]]; // testings against REST API, use raw formats @@ -314,7 +323,7 @@ describe_only_db('mongo')('Parse.Polygon testing', () => { }); it('polygon coordinates reverse input', (done) => { - const Config = require('../src/Config'); + const Config = require('../lib/Config'); const config = Config.get('test'); // When stored the first point should be the last point diff --git a/spec/ParsePubSub.spec.js b/spec/ParsePubSub.spec.js index 3c7014f7d2..fe8db147d6 100644 --- a/spec/ParsePubSub.spec.js +++ b/spec/ParsePubSub.spec.js @@ -1,4 +1,4 @@ -const ParsePubSub = require('../src/LiveQuery/ParsePubSub').ParsePubSub; +const ParsePubSub = require('../lib/LiveQuery/ParsePubSub').ParsePubSub; describe('ParsePubSub', function() { @@ -8,13 +8,13 @@ describe('ParsePubSub', function() { createPublisher: jasmine.createSpy('createPublisherRedis'), createSubscriber: jasmine.createSpy('createSubscriberRedis') }; - jasmine.mockLibrary('../src/Adapters/PubSub/RedisPubSub', 'RedisPubSub', mockRedisPubSub); + jasmine.mockLibrary('../lib/Adapters/PubSub/RedisPubSub', 'RedisPubSub', mockRedisPubSub); // Mock EventEmitterPubSub const mockEventEmitterPubSub = { createPublisher: jasmine.createSpy('createPublisherEventEmitter'), createSubscriber: jasmine.createSpy('createSubscriberEventEmitter') }; - jasmine.mockLibrary('../src/Adapters/PubSub/EventEmitterPubSub', 'EventEmitterPubSub', mockEventEmitterPubSub); + jasmine.mockLibrary('../lib/Adapters/PubSub/EventEmitterPubSub', 'EventEmitterPubSub', mockEventEmitterPubSub); done(); }); @@ -23,8 +23,8 @@ describe('ParsePubSub', function() { redisURL: 'redisURL' }); - const RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; - const EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; + const RedisPubSub = require('../lib/Adapters/PubSub/RedisPubSub').RedisPubSub; + const EventEmitterPubSub = require('../lib/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; expect(RedisPubSub.createPublisher).toHaveBeenCalledWith({redisURL: 'redisURL'}); expect(EventEmitterPubSub.createPublisher).not.toHaveBeenCalled(); }); @@ -32,8 +32,8 @@ describe('ParsePubSub', function() { it('can create event emitter publisher', function() { ParsePubSub.createPublisher({}); - const RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; - const EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; + const RedisPubSub = require('../lib/Adapters/PubSub/RedisPubSub').RedisPubSub; + const EventEmitterPubSub = require('../lib/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; expect(RedisPubSub.createPublisher).not.toHaveBeenCalled(); expect(EventEmitterPubSub.createPublisher).toHaveBeenCalled(); }); @@ -43,8 +43,8 @@ describe('ParsePubSub', function() { redisURL: 'redisURL' }); - const RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; - const EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; + const RedisPubSub = require('../lib/Adapters/PubSub/RedisPubSub').RedisPubSub; + const EventEmitterPubSub = require('../lib/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; expect(RedisPubSub.createSubscriber).toHaveBeenCalledWith({redisURL: 'redisURL'}); expect(EventEmitterPubSub.createSubscriber).not.toHaveBeenCalled(); }); @@ -52,8 +52,8 @@ describe('ParsePubSub', function() { it('can create event emitter subscriber', function() { ParsePubSub.createSubscriber({}); - const RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; - const EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; + const RedisPubSub = require('../lib/Adapters/PubSub/RedisPubSub').RedisPubSub; + const EventEmitterPubSub = require('../lib/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; expect(RedisPubSub.createSubscriber).not.toHaveBeenCalled(); expect(EventEmitterPubSub.createSubscriber).toHaveBeenCalled(); }); @@ -73,8 +73,8 @@ describe('ParsePubSub', function() { }); expect(adapter.createSubscriber).toHaveBeenCalled(); - const RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; - const EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; + const RedisPubSub = require('../lib/Adapters/PubSub/RedisPubSub').RedisPubSub; + const EventEmitterPubSub = require('../lib/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; expect(RedisPubSub.createSubscriber).not.toHaveBeenCalled(); expect(EventEmitterPubSub.createSubscriber).not.toHaveBeenCalled(); expect(RedisPubSub.createPublisher).not.toHaveBeenCalled(); @@ -100,8 +100,8 @@ describe('ParsePubSub', function() { }); expect(adapter.createSubscriber).toHaveBeenCalled(); - const RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; - const EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; + const RedisPubSub = require('../lib/Adapters/PubSub/RedisPubSub').RedisPubSub; + const EventEmitterPubSub = require('../lib/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; expect(RedisPubSub.createSubscriber).not.toHaveBeenCalled(); expect(EventEmitterPubSub.createSubscriber).not.toHaveBeenCalled(); expect(RedisPubSub.createPublisher).not.toHaveBeenCalled(); @@ -109,7 +109,7 @@ describe('ParsePubSub', function() { }); afterEach(function(){ - jasmine.restoreLibrary('../src/Adapters/PubSub/RedisPubSub', 'RedisPubSub'); - jasmine.restoreLibrary('../src/Adapters/PubSub/EventEmitterPubSub', 'EventEmitterPubSub'); + jasmine.restoreLibrary('../lib/Adapters/PubSub/RedisPubSub', 'RedisPubSub'); + jasmine.restoreLibrary('../lib/Adapters/PubSub/EventEmitterPubSub', 'EventEmitterPubSub'); }); }); diff --git a/spec/ParseQuery.Aggregate.spec.js b/spec/ParseQuery.Aggregate.spec.js index dade21ca47..d3e1d19e7c 100644 --- a/spec/ParseQuery.Aggregate.spec.js +++ b/spec/ParseQuery.Aggregate.spec.js @@ -13,6 +13,10 @@ const masterKeyOptions = { json: true } +const PointerObject = Parse.Object.extend({ + className: "PointerObject" +}); + const loadTestData = () => { const data1 = {score: 10, name: 'foo', sender: {group: 'A'}, views: 900, size: ['S', 'M']}; const data2 = {score: 10, name: 'foo', sender: {group: 'A'}, views: 800, size: ['M', 'L']}; @@ -160,6 +164,124 @@ describe('Parse.Query Aggregate testing', () => { }); }); + it('group by date object transform', (done) => { + const obj1 = new TestObject(); + const obj2 = new TestObject(); + const obj3 = new TestObject(); + const pipeline = [{ + group: { + objectId: { day: { $dayOfMonth: "$updatedAt" }, month: { $month: "$createdAt" }, year: { $year: "$createdAt" } }, + count: { $sum: 1 } + } + }]; + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + const createdAt = new Date(obj1.createdAt); + expect(results[0].objectId.day).toEqual(createdAt.getUTCDate()); + expect(results[0].objectId.month).toEqual(createdAt.getMonth() + 1); + expect(results[0].objectId.year).toEqual(createdAt.getUTCFullYear()); + done(); + }); + }); + + it_exclude_dbs(['postgres'])('group and multiply transform', (done) => { + const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 }); + const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 }); + const pipeline = [{ + group: { + objectId: null, + total: { $sum: { $multiply: [ '$quantity', '$price' ] } } + } + }]; + Parse.Object.saveAll([obj1, obj2]).then(() => { + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toEqual(1); + expect(results[0].total).toEqual(45); + done(); + }); + }); + + it_exclude_dbs(['postgres'])('project and multiply transform', (done) => { + const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 }); + const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 }); + const pipeline = [ + { + match: { quantity: { $exists: true } } + }, + { + project: { + name: 1, + total: { $multiply: [ '$quantity', '$price' ] } + } + } + ]; + Parse.Object.saveAll([obj1, obj2]).then(() => { + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toEqual(2); + if (results[0].name === 'item a') { + expect(results[0].total).toEqual(20); + expect(results[1].total).toEqual(25); + } + else { + expect(results[0].total).toEqual(25); + expect(results[1].total).toEqual(20); + } + done(); + }); + }); + + it_exclude_dbs(['postgres'])('project without objectId transform', (done) => { + const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 }); + const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 }); + const pipeline = [ + { + match: { quantity: { $exists: true } } + }, + { + project: { + objectId: 0, + total: { $multiply: [ '$quantity', '$price' ] } + } + }, + { + sort: { total: 1 } + } + ]; + Parse.Object.saveAll([obj1, obj2]).then(() => { + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toEqual(2); + expect(results[0].total).toEqual(20); + expect(results[0].objectId).toEqual(undefined); + expect(results[1].total).toEqual(25); + expect(results[1].objectId).toEqual(undefined); + done(); + }); + }); + + it_exclude_dbs(['postgres'])('project updatedAt only transform', (done) => { + const pipeline = [{ + project: { objectId: 0, updatedAt: 1 } + }]; + const query = new Parse.Query(TestObject); + query.aggregate(pipeline).then((results) => { + expect(results.length).toEqual(4); + for (let i = 0; i < results.length; i++) { + const item = results[i]; + expect(item.hasOwnProperty('updatedAt')).toEqual(true); + expect(item.hasOwnProperty('objectId')).toEqual(false); + } + done(); + }); + }); + it_exclude_dbs(['postgres'])('cannot group by date field (excluding createdAt and updatedAt)', (done) => { const obj1 = new TestObject({ dateField: new Date(1990, 11, 1) }); const obj2 = new TestObject({ dateField: new Date(1990, 5, 1) }); @@ -173,7 +295,7 @@ describe('Parse.Query Aggregate testing', () => { Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { const query = new Parse.Query(TestObject); return query.aggregate(pipeline); - }).then(done.fail).catch((error) => { + }).then(done).catch((error) => { expect(error.code).toEqual(Parse.Error.INVALID_QUERY); done(); }); @@ -335,6 +457,27 @@ describe('Parse.Query Aggregate testing', () => { }).catch(done.fail); }); + it('match comparison date query', (done) => { + const today = new Date(); + const yesterday = new Date(); + const tomorrow = new Date(); + yesterday.setDate(today.getDate() - 1); + tomorrow.setDate(today.getDate() + 1); + const obj1 = new TestObject({ dateField: yesterday }); + const obj2 = new TestObject({ dateField: today }); + const obj3 = new TestObject({ dateField: tomorrow }); + const pipeline = [ + { match: { dateField: { $lt: tomorrow } } } + ]; + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toBe(2); + done(); + }); + }); + it('match comparison query', (done) => { const options = Object.assign({}, masterKeyOptions, { body: { @@ -448,8 +591,8 @@ describe('Parse.Query Aggregate testing', () => { }); it('match pointer query', (done) => { - const pointer1 = new TestObject(); - const pointer2 = new TestObject(); + const pointer1 = new PointerObject(); + const pointer2 = new PointerObject(); const obj1 = new TestObject({ pointer: pointer1 }); const obj2 = new TestObject({ pointer: pointer2 }); const obj3 = new TestObject({ pointer: pointer1 }); @@ -470,6 +613,96 @@ describe('Parse.Query Aggregate testing', () => { }); }); + it_exclude_dbs(['postgres'])('match exists query', (done) => { + const pipeline = [ + { match: { score: { $exists: true } } } + ]; + const query = new Parse.Query(TestObject); + query.aggregate(pipeline).then((results) => { + expect(results.length).toEqual(4); + done(); + }); + }); + + it('match date query - createdAt', (done) => { + const obj1 = new TestObject(); + const obj2 = new TestObject(); + + Parse.Object.saveAll([obj1, obj2]).then(() => { + const now = new Date(); + const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + const pipeline = [ + { match: { 'createdAt': { $gte: today } } } + ]; + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + // Four objects were created initially, we added two more. + expect(results.length).toEqual(6); + done(); + }); + }); + + it('match date query - updatedAt', (done) => { + const obj1 = new TestObject(); + const obj2 = new TestObject(); + + Parse.Object.saveAll([obj1, obj2]).then(() => { + const now = new Date(); + const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + const pipeline = [ + { match: { 'updatedAt': { $gte: today } } } + ]; + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + // Four objects were added initially, we added two more. + expect(results.length).toEqual(6); + done(); + }); + }); + + it('match date query - empty', (done) => { + const obj1 = new TestObject(); + const obj2 = new TestObject(); + + Parse.Object.saveAll([obj1, obj2]).then(() => { + const now = new Date(); + const future = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate()); + const pipeline = [ + { match: { 'createdAt': future } } + ]; + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toEqual(0); + done(); + }); + }); + + it_exclude_dbs(['postgres'])('match pointer with operator query', (done) => { + const pointer = new PointerObject(); + + const obj1 = new TestObject({ pointer }); + const obj2 = new TestObject({ pointer }); + const obj3 = new TestObject(); + + Parse.Object.saveAll([pointer, obj1, obj2, obj3]).then(() => { + const pipeline = [ + { match: { pointer: { $exists: true } } } + ]; + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toEqual(2); + expect(results[0].pointer.objectId).toEqual(pointer.id); + expect(results[1].pointer.objectId).toEqual(pointer.id); + expect(results.some(result => result.objectId === obj1.id)).toEqual(true); + expect(results.some(result => result.objectId === obj2.id)).toEqual(true); + done(); + }); + }); + it('project query', (done) => { const options = Object.assign({}, masterKeyOptions, { body: { @@ -508,6 +741,26 @@ describe('Parse.Query Aggregate testing', () => { }).catch(done.fail); }); + it('project pointer query', (done) => { + const pointer = new PointerObject(); + const obj = new TestObject({ pointer, name: 'hello' }); + + obj.save().then(() => { + const pipeline = [ + { match: { objectId: obj.id } }, + { project: { pointer: 1, name: 1, createdAt: 1 } } + ]; + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toEqual(1); + expect(results[0].name).toEqual('hello'); + expect(results[0].createdAt).not.toBe(undefined); + expect(results[0].pointer.objectId).toEqual(pointer.id); + done(); + }); + }); + it('project with group query', (done) => { const options = Object.assign({}, masterKeyOptions, { body: { @@ -618,8 +871,8 @@ describe('Parse.Query Aggregate testing', () => { }); it('distinct pointer', (done) => { - const pointer1 = new TestObject(); - const pointer2 = new TestObject(); + const pointer1 = new PointerObject(); + const pointer2 = new PointerObject(); const obj1 = new TestObject({ pointer: pointer1 }); const obj2 = new TestObject({ pointer: pointer2 }); const obj3 = new TestObject({ pointer: pointer1 }); @@ -740,4 +993,47 @@ describe('Parse.Query Aggregate testing', () => { fail(err); }); }); + + it_exclude_dbs(['postgres'])('aggregate allow multiple of same stage', (done) => { + const pointer1 = new TestObject({ value: 1}); + const pointer2 = new TestObject({ value: 2}); + const pointer3 = new TestObject({ value: 3}); + + const obj1 = new TestObject({ pointer: pointer1, name: 'Hello' }); + const obj2 = new TestObject({ pointer: pointer2, name: 'Hello' }); + const obj3 = new TestObject({ pointer: pointer3, name: 'World' }); + + const options = Object.assign({}, masterKeyOptions, { + body: [{ + match: { name: "Hello" }, + }, { + // Transform className$objectId to objectId and store in new field tempPointer + project: { + tempPointer: { $substr: [ "$_p_pointer", 11, -1 ] }, // Remove TestObject$ + }, + }, { + // Left Join, replace objectId stored in tempPointer with an actual object + lookup: { + from: "test_TestObject", + localField: "tempPointer", + foreignField: "_id", + as: "tempPointer" + }, + }, { + // lookup returns an array, Deconstructs an array field to objects + unwind: { + path: "$tempPointer", + }, + }, { + match : { "tempPointer.value" : 2 }, + }] + }); + Parse.Object.saveAll([pointer1, pointer2, pointer3, obj1, obj2, obj3]).then(() => { + return rp.get(Parse.serverURL + '/aggregate/TestObject', options); + }).then((resp) => { + expect(resp.results.length).toEqual(1); + expect(resp.results[0].tempPointer.value).toEqual(2); + done(); + }); + }); }); diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index 9116410742..eac29c9268 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -1,8 +1,8 @@ 'use strict'; -import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter'; +const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase'; -import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter'; +const PostgresStorageAdapter = require('../lib/Adapters/Storage/Postgres/PostgresStorageAdapter').default; const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database'; const Parse = require('parse/node'); const rp = require('request-promise'); @@ -280,7 +280,7 @@ describe('Parse.Query Full Text Search testing', () => { }); }); -describe_only_db('mongo')('Parse.Query Full Text Search testing', () => { +describe_only_db('mongo')('[mongodb] Parse.Query Full Text Search testing', () => { it('fullTextSearch: does not create text index if compound index exist', (done) => { fullTextHelper().then(() => { return databaseAdapter.dropAllIndexes('TestObject'); @@ -451,7 +451,7 @@ describe_only_db('mongo')('Parse.Query Full Text Search testing', () => { }); }); -describe_only_db('postgres')('Parse.Query Full Text Search testing', () => { +describe_only_db('postgres')('[postgres] Parse.Query Full Text Search testing', () => { it('fullTextSearch: $diacriticSensitive - false', (done) => { fullTextHelper().then(() => { const where = { diff --git a/spec/ParseQuery.spec.js b/spec/ParseQuery.spec.js index 662b58fa5c..694b870f71 100644 --- a/spec/ParseQuery.spec.js +++ b/spec/ParseQuery.spec.js @@ -5,6 +5,18 @@ 'use strict'; const Parse = require('parse/node'); +const rp = require('request-promise'); + +const masterKeyHeaders = { + 'X-Parse-Application-Id': 'test', + 'X-Parse-Rest-API-Key': 'test', + 'X-Parse-Master-Key': 'test' +} + +const masterKeyOptions = { + headers: masterKeyHeaders, + json: true +} describe('Parse.Query testing', () => { it("basic query", function(done) { @@ -497,6 +509,354 @@ describe('Parse.Query testing', () => { }); }); + it('containsAllStartingWith should match all strings that starts with string', (done) => { + + const object = new Parse.Object('Object'); + object.set('strings', ['the', 'brown', 'lazy', 'fox', 'jumps']); + const object2 = new Parse.Object('Object'); + object2.set('strings', ['the', 'brown', 'fox', 'jumps']); + const object3 = new Parse.Object('Object'); + object3.set('strings', ['over', 'the', 'lazy', 'dog']); + + const objectList = [object, object2, object3]; + + Parse.Object.saveAll(objectList).then((results) => { + equal(objectList.length, results.length); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [ + {$regex: '\^\\Qthe\\E'}, + {$regex: '\^\\Qfox\\E'}, + {$regex: '\^\\Qlazy\\E'} + ] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }) + .then(function (results) { + equal(results.results.length, 1); + arrayContains(results.results, object); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [ + {$regex: '\^\\Qthe\\E'}, + {$regex: '\^\\Qlazy\\E'} + ] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }) + .then(function (results) { + equal(results.results.length, 2); + arrayContains(results.results, object); + arrayContains(results.results, object3); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [ + {$regex: '\^\\Qhe\\E'}, + {$regex: '\^\\Qlazy\\E'} + ] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }) + .then(function (results) { + equal(results.results.length, 0); + + done(); + }); + }); + }); + + it('containsAllStartingWith values must be all of type starting with regex', (done) => { + + const object = new Parse.Object('Object'); + object.set('strings', ['the', 'brown', 'lazy', 'fox', 'jumps']); + + object.save().then(() => { + equal(object.isNew(), false); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [ + {$regex: '\^\\Qthe\\E'}, + {$regex: '\^\\Qlazy\\E'}, + {$regex: '\^\\Qfox\\E'}, + {$unknown: /unknown/} + ] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }) + .then(function () { + }, function () { + done(); + }); + }); + + it('containsAllStartingWith empty array values should return empty results', (done) => { + + const object = new Parse.Object('Object'); + object.set('strings', ['the', 'brown', 'lazy', 'fox', 'jumps']); + + object.save().then(() => { + equal(object.isNew(), false); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }) + .then(function (results) { + equal(results.results.length, 0); + done(); + }, function () { + }); + }); + + it('containsAllStartingWith single empty value returns empty results', (done) => { + + const object = new Parse.Object('Object'); + object.set('strings', ['the', 'brown', 'lazy', 'fox', 'jumps']); + + object.save().then(() => { + equal(object.isNew(), false); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [ {} ] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }) + .then(function (results) { + equal(results.results.length, 0); + done(); + }, function () { + }); + }); + + it('containsAllStartingWith single regex value should return corresponding matching results', (done) => { + + const object = new Parse.Object('Object'); + object.set('strings', ['the', 'brown', 'lazy', 'fox', 'jumps']); + const object2 = new Parse.Object('Object'); + object2.set('strings', ['the', 'brown', 'fox', 'jumps']); + const object3 = new Parse.Object('Object'); + object3.set('strings', ['over', 'the', 'lazy', 'dog']); + + const objectList = [object, object2, object3]; + + Parse.Object.saveAll(objectList).then((results) => { + equal(objectList.length, results.length); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [ {$regex: '\^\\Qlazy\\E'} ] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }) + .then(function (results) { + equal(results.results.length, 2); + done(); + }, function () { + }); + }); + + it('containsAllStartingWith single invalid regex returns empty results', (done) => { + + const object = new Parse.Object('Object'); + object.set('strings', ['the', 'brown', 'lazy', 'fox', 'jumps']); + + object.save().then(() => { + equal(object.isNew(), false); + + return require('request-promise').get({ + url: Parse.serverURL + "/classes/Object", + json: { + where: { + strings: { + $all: [ {$unknown: '\^\\Qlazy\\E'} ] + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }) + .then(function (results) { + equal(results.results.length, 0); + done(); + }, function () { + }); + }); + + it('containedBy pointer array', (done) => { + const objects = Array.from(Array(10).keys()).map((idx) => { + const obj = new Parse.Object('Object'); + obj.set('key', idx); + return obj; + }); + + const parent = new Parse.Object('Parent'); + const parent2 = new Parse.Object('Parent'); + const parent3 = new Parse.Object('Parent'); + + Parse.Object.saveAll(objects).then(() => { + // [0, 1, 2] + parent.set('objects', objects.slice(0, 3)); + + const shift = objects.shift(); + // [2, 0] + parent2.set('objects', [objects[1], shift]); + + // [1, 2, 3, 4] + parent3.set('objects', objects.slice(1, 4)); + + return Parse.Object.saveAll([parent, parent2, parent3]); + }).then(() => { + // [1, 2, 3, 4, 5, 6, 7, 8, 9] + const pointers = objects.map(object => object.toPointer()); + + // Return all Parent where all parent.objects are contained in objects + return rp.get({ + url: Parse.serverURL + "/classes/Parent", + json: { + where: { + objects: { + $containedBy: pointers + } + } + }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((results) => { + expect(results.results[0].objectId).not.toBeUndefined(); + expect(results.results[0].objectId).toBe(parent3.id); + expect(results.results.length).toBe(1); + done(); + }); + }); + + + it('containedBy number array', (done) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { numbers: { $containedBy: [1, 2, 3, 4, 5, 6, 7, 8, 9] } }, + } + }); + const obj1 = new TestObject({ numbers: [0, 1, 2] }); + const obj2 = new TestObject({ numbers: [2, 0] }); + const obj3 = new TestObject({ numbers: [1, 2, 3, 4] }); + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + return rp.get(Parse.serverURL + "/classes/TestObject", options); + }).then((results) => { + expect(results.results[0].objectId).not.toBeUndefined(); + expect(results.results[0].objectId).toBe(obj3.id); + expect(results.results.length).toBe(1); + done(); + }); + }); + + it('containedBy empty array', (done) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { numbers: { $containedBy: [] } }, + } + }); + const obj1 = new TestObject({ numbers: [0, 1, 2] }); + const obj2 = new TestObject({ numbers: [2, 0] }); + const obj3 = new TestObject({ numbers: [1, 2, 3, 4] }); + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + return rp.get(Parse.serverURL + "/classes/TestObject", options); + }).then((results) => { + expect(results.results.length).toBe(0); + done(); + }); + }); + + it('containedBy invalid query', (done) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { objects: { $containedBy: 1234 } }, + } + }); + const obj = new TestObject(); + obj.save().then(() => { + return rp.get(Parse.serverURL + "/classes/TestObject", options); + }).then(done.fail).catch((error) => { + equal(error.error.code, Parse.Error.INVALID_JSON); + equal(error.error.error, 'bad $containedBy: should be an array'); + done(); + }); + }); + const BoxedNumber = Parse.Object.extend({ className: "BoxedNumber" }); @@ -570,6 +930,38 @@ describe('Parse.Query testing', () => { }); }); + it("lessThan zero queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.lessThan('number', 0); + return query.find(); + }).then((results) => { + equal(results.length, 3); + done(); + }); + }); + + it("lessThanOrEqualTo zero queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.lessThanOrEqualTo('number', 0); + return query.find(); + }).then((results) => { + equal(results.length, 4); + done(); + }); + }); + it("greaterThan queries", function(done) { const makeBoxedNumber = function(i) { return new BoxedNumber({ number: i }); @@ -606,6 +998,38 @@ describe('Parse.Query testing', () => { }); }); + it("greaterThan zero queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.greaterThan('number', 0); + return query.find(); + }).then((results) => { + equal(results.length, 1); + done(); + }); + }); + + it("greaterThanOrEqualTo zero queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.greaterThanOrEqualTo('number', 0); + return query.find(); + }).then((results) => { + equal(results.length, 2); + done(); + }); + }); + it("lessThanOrEqualTo greaterThanOrEqualTo queries", function(done) { const makeBoxedNumber = function(i) { return new BoxedNumber({ number: i }); @@ -662,6 +1086,101 @@ describe('Parse.Query testing', () => { }); }); + it("notEqualTo zero queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.notEqualTo('number', 0); + return query.find(); + }).then((results) => { + equal(results.length, 4); + done(); + }); + }); + + it("equalTo zero queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.equalTo('number', 0); + return query.find(); + }).then((results) => { + equal(results.length, 1); + done(); + }); + }); + + it("number equalTo boolean queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.equalTo('number', false); + return query.find(); + }).then((results) => { + equal(results.length, 0); + done(); + }); + }); + + it("equalTo false queries", (done) => { + const obj1 = new TestObject({ field: false }); + const obj2 = new TestObject({ field: true }); + Parse.Object.saveAll([obj1, obj2]).then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('field', false); + return query.find(); + }).then((results) => { + equal(results.length, 1); + done(); + }); + }); + + it("where $eq false queries (rest)", (done) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { field: { $eq: false } }, + } + }); + const obj1 = new TestObject({ field: false }); + const obj2 = new TestObject({ field: true }); + Parse.Object.saveAll([obj1, obj2]).then(() => { + rp.get(Parse.serverURL + '/classes/TestObject', options) + .then((resp) => { + equal(resp.results.length, 1); + done(); + }); + }) + }); + + it("where $eq null queries (rest)", (done) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { field: { $eq: null } }, + } + }); + const obj1 = new TestObject({ field: false }); + const obj2 = new TestObject({ field: null }); + Parse.Object.saveAll([obj1, obj2]).then(() => { + rp.get(Parse.serverURL + '/classes/TestObject', options) + .then((resp) => { + equal(resp.results.length, 1); + done(); + }); + }) + }); + it("containedIn queries", function(done) { const makeBoxedNumber = function(i) { return new BoxedNumber({ number: i }); @@ -680,6 +1199,40 @@ describe('Parse.Query testing', () => { }); }); + it("containedIn false queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.containedIn('number', false); + return query.find(); + }).then(done.fail).catch((error) => { + equal(error.code, Parse.Error.INVALID_JSON); + equal(error.message, 'bad $in value'); + done(); + }); + }); + + it("notContainedIn false queries", (done) => { + const makeBoxedNumber = (i) => { + return new BoxedNumber({ number: i }); + }; + const numbers = [-3, -2, -1, 0, 1]; + const boxedNumbers = numbers.map(makeBoxedNumber); + Parse.Object.saveAll(boxedNumbers).then(() => { + const query = new Parse.Query(BoxedNumber); + query.notContainedIn('number', false); + return query.find(); + }).then(done.fail).catch((error) => { + equal(error.code, Parse.Error.INVALID_JSON); + equal(error.message, 'bad $nin value'); + done(); + }); + }); + it("notContainedIn queries", function(done) { const makeBoxedNumber = function(i) { return new BoxedNumber({ number: i }); @@ -985,6 +1538,90 @@ describe('Parse.Query testing', () => { }); }); + it('can order on an object string field', function (done) { + const testSet = [ + { sortField: { value: "Z" } }, + { sortField: { value: "A" } }, + { sortField: { value: "M" } }, + ]; + + const objects = testSet.map(e => new Parse.Object('Test', e)); + Parse.Object.saveAll(objects) + .then(() => new Parse.Query('Test').addDescending('sortField.value').first()) + .then((result) => { + expect(result.get('sortField').value).toBe("Z"); + return new Parse.Query('Test').addAscending('sortField.value').first() + }) + .then((result) => { + expect(result.get('sortField').value).toBe("A"); + done(); + }) + .catch(done.fail); + }); + + it('can order on an object string field (level 2)', function (done) { + const testSet = [ + { sortField: { value: { field: "Z" } } }, + { sortField: { value: { field: "A" } } }, + { sortField: { value: { field: "M" } } }, + ]; + + const objects = testSet.map(e => new Parse.Object('Test', e)); + Parse.Object.saveAll(objects) + .then(() => new Parse.Query('Test').addDescending('sortField.value.field').first()) + .then((result) => { + expect(result.get('sortField').value.field).toBe("Z"); + return new Parse.Query('Test').addAscending('sortField.value.field').first() + }) + .then((result) => { + expect(result.get('sortField').value.field).toBe("A"); + done(); + }) + .catch(done.fail); + }); + + it('can order on an object number field', function (done) { + const testSet = [ + { sortField: { value: 10 } }, + { sortField: { value: 1 } }, + { sortField: { value: 5 } }, + ]; + + const objects = testSet.map(e => new Parse.Object('Test', e)); + Parse.Object.saveAll(objects) + .then(() => new Parse.Query('Test').addDescending('sortField.value').first()) + .then((result) => { + expect(result.get('sortField').value).toBe(10); + return new Parse.Query('Test').addAscending('sortField.value').first() + }) + .then((result) => { + expect(result.get('sortField').value).toBe(1); + done(); + }) + .catch(done.fail); + }); + + it('can order on an object number field (level 2)', function (done) { + const testSet = [ + { sortField: { value: { field: 10 } } }, + { sortField: { value: { field: 1 } } }, + { sortField: { value: { field: 5 } } }, + ]; + + const objects = testSet.map(e => new Parse.Object('Test', e)); + Parse.Object.saveAll(objects) + .then(() => new Parse.Query('Test').addDescending('sortField.value.field').first()) + .then((result) => { + expect(result.get('sortField').value.field).toBe(10); + return new Parse.Query('Test').addAscending('sortField.value.field').first() + }) + .then((result) => { + expect(result.get('sortField').value.field).toBe(1); + done(); + }) + .catch(done.fail); + }); + it("order by ascending number then descending string", function(done) { const strings = ["a", "b", "c", "d"]; const makeBoxedNumber = function(num, i) { @@ -1387,7 +2024,7 @@ describe('Parse.Query testing', () => { query.find(expectError(Parse.Error.INVALID_QUERY, 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], function() { @@ -2014,6 +2651,63 @@ describe('Parse.Query testing', () => { }); }); + it('$nor valid query', (done) => { + const objects = Array.from(Array(10).keys()).map((rating) => { + return new TestObject({ 'rating': rating }); + }); + + const highValue = 5; + const lowValue = 3; + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { + $nor: [ + { rating : { $gt : highValue } }, + { rating : { $lte : lowValue } }, + ] + }, + } + }); + + Parse.Object.saveAll(objects).then(() => { + return rp.get(Parse.serverURL + "/classes/TestObject", options); + }).then((results) => { + expect(results.results.length).toBe(highValue - lowValue); + expect(results.results.every(res => res.rating > lowValue && res.rating <= highValue)).toBe(true); + done(); + }); + }); + + it('$nor invalid query - empty array', (done) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { $nor: [] }, + } + }); + const obj = new TestObject(); + obj.save().then(() => { + return rp.get(Parse.serverURL + "/classes/TestObject", options); + }).then(done.fail).catch((error) => { + equal(error.error.code, Parse.Error.INVALID_QUERY); + done(); + }); + }); + + it('$nor invalid query - wrong type', (done) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { $nor: 1337 }, + } + }); + const obj = new TestObject(); + obj.save().then(() => { + return rp.get(Parse.serverURL + "/classes/TestObject", options); + }).then(done.fail).catch((error) => { + equal(error.error.code, Parse.Error.INVALID_QUERY); + done(); + }); + }); + it("dontSelect query", function(done) { const RestaurantObject = Parse.Object.extend("Restaurant"); const PersonObject = Parse.Object.extend("Person"); @@ -2990,6 +3684,75 @@ describe('Parse.Query testing', () => { }); }); + it('includeAll', (done) => { + const child1 = new TestObject({ foo: 'bar', name: 'ac' }); + const child2 = new TestObject({ foo: 'baz', name: 'flo' }); + const child3 = new TestObject({ foo: 'bad', name: 'mo' }); + const parent = new Container({ child1, child2, child3 }); + Parse.Object.saveAll([parent, child1, child2, child3]).then(() => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { objectId: parent.id }, + includeAll: true, + } + }); + return rp.get(Parse.serverURL + "/classes/Container", options); + }).then((resp) => { + const result = resp.results[0]; + equal(result.child1.foo, 'bar'); + equal(result.child2.foo, 'baz'); + equal(result.child3.foo, 'bad'); + equal(result.child1.name, 'ac'); + equal(result.child2.name, 'flo'); + equal(result.child3.name, 'mo'); + done(); + }); + }); + + it('select nested keys 2 level includeAll', (done) => { + const Foobar = new Parse.Object('Foobar'); + const BarBaz = new Parse.Object('Barbaz'); + const Bazoo = new Parse.Object('Bazoo'); + const Tang = new Parse.Object('Tang'); + + Bazoo.set('some', 'thing'); + Bazoo.set('otherSome', 'value'); + Bazoo.save().then(() => { + BarBaz.set('key', 'value'); + BarBaz.set('otherKey', 'value'); + BarBaz.set('bazoo', Bazoo); + return BarBaz.save(); + }).then(() => { + Tang.set('clan', 'wu'); + return Tang.save(); + }).then(() => { + Foobar.set('foo', 'bar'); + Foobar.set('fizz', 'buzz'); + Foobar.set('barBaz', BarBaz); + Foobar.set('group', Tang); + return Foobar.save(); + }).then((savedFoobar) => { + const options = Object.assign({}, masterKeyOptions, { + body: { + where: { objectId: savedFoobar.id }, + includeAll: true, + keys: 'fizz,barBaz.key,barBaz.bazoo.some', + } + }); + return rp.get(Parse.serverURL + "/classes/Foobar", options); + }).then((resp) => { + const result = resp.results[0]; + equal(result.group.clan, 'wu'); + equal(result.foo, undefined); + equal(result.fizz, 'buzz'); + equal(result.barBaz.key, 'value'); + equal(result.barBaz.otherKey, undefined); + equal(result.barBaz.bazoo.some, 'thing'); + equal(result.barBaz.bazoo.otherSome, undefined); + done(); + }) + }); + it('select nested keys 2 level without include (issue #3185)', function(done) { const Foobar = new Parse.Object('Foobar'); const BarBaz = new Parse.Object('Barbaz'); @@ -3291,4 +4054,106 @@ describe('Parse.Query testing', () => { }) }); + it('withJSON supports geoWithin.centerSphere', (done) => { + const inbound = new Parse.GeoPoint(1.5, 1.5); + const onbound = new Parse.GeoPoint(10, 10); + const outbound = new Parse.GeoPoint(20, 20); + const obj1 = new Parse.Object('TestObject', {location: inbound}); + const obj2 = new Parse.Object('TestObject', {location: onbound}); + const obj3 = new Parse.Object('TestObject', {location: outbound}); + const center = new Parse.GeoPoint(0, 0); + const distanceInKilometers = 1569 + 1; // 1569km is the approximate distance between {0, 0} and {10, 10}. + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const q = new Parse.Query(TestObject); + const jsonQ = q.toJSON(); + jsonQ.where.location = { + '$geoWithin': { + '$centerSphere': [ + center, + distanceInKilometers / 6371.0 + ] + } + }; + q.withJSON(jsonQ); + return q.find(); + }).then(results => { + equal(results.length, 2); + const q = new Parse.Query(TestObject); + const jsonQ = q.toJSON(); + jsonQ.where.location = { + '$geoWithin': { + '$centerSphere': [ + [0, 0], + distanceInKilometers / 6371.0 + ] + } + }; + q.withJSON(jsonQ); + return q.find(); + }).then(results => { + equal(results.length, 2); + done(); + }).catch(error => { + fail(error); + done(); + }); + }); + + it('withJSON with geoWithin.centerSphere fails without parameters', (done) => { + const q = new Parse.Query(TestObject); + const jsonQ = q.toJSON(); + jsonQ.where.location = { + '$geoWithin': { + '$centerSphere': [ + ] + } + }; + q.withJSON(jsonQ); + q.find(expectError(Parse.Error.INVALID_JSON, done)); + }); + + it('withJSON with geoWithin.centerSphere fails with invalid distance', (done) => { + const q = new Parse.Query(TestObject); + const jsonQ = q.toJSON(); + jsonQ.where.location = { + '$geoWithin': { + '$centerSphere': [ + [0, 0], + 'invalid_distance' + ] + } + }; + q.withJSON(jsonQ); + q.find(expectError(Parse.Error.INVALID_JSON, done)); + }); + + it('withJSON with geoWithin.centerSphere fails with invalid coordinate', (done) => { + const q = new Parse.Query(TestObject); + const jsonQ = q.toJSON(); + jsonQ.where.location = { + '$geoWithin': { + '$centerSphere': [ + [-190,-190], + 1 + ] + } + }; + q.withJSON(jsonQ); + q.find(expectError(undefined, done)); + }); + + it('withJSON with geoWithin.centerSphere fails with invalid geo point', (done) => { + const q = new Parse.Query(TestObject); + const jsonQ = q.toJSON(); + jsonQ.where.location = { + '$geoWithin': { + '$centerSphere': [ + {'longitude': 0, 'dummytude': 0}, + 1 + ] + } + }; + q.withJSON(jsonQ); + q.find(expectError(undefined, done)); + }); }); diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index ad5ba361df..c780781995 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -801,4 +801,37 @@ describe('Parse.Relation testing', () => { done(); }); }); + + it('ensures beforeFind on relation doesnt side effect', (done) => { + const parent = new Parse.Object('Parent'); + const child = new Parse.Object('Child'); + child.save().then(() => { + parent.relation('children').add(child); + return parent.save(); + }).then(() => { + // We need to use a new reference otherwise the JS SDK remembers the className for a relation + // After saves or finds + const otherParent = new Parse.Object('Parent'); + otherParent.id = parent.id; + return otherParent.relation('children').query().find(); + }).then((children) => { + // Without an after find all is good, all results have been redirected with proper className + children.forEach((child) => expect(child.className).toBe('Child')); + // Setup the afterFind + Parse.Cloud.afterFind('Child', (req) => { + return Promise.resolve(req.objects.map((child) => { + child.set('afterFound', true); + return child; + })); + }); + const otherParent = new Parse.Object('Parent'); + otherParent.id = parent.id; + return otherParent.relation('children').query().find(); + }).then((children) => { + children.forEach((child) => { + expect(child.className).toBe('Child'); + expect(child.get('afterFound')).toBe(true); + }); + }).then(done).catch(done.fail); + }); }); diff --git a/spec/ParseRole.spec.js b/spec/ParseRole.spec.js index b9d315060a..21b430dbfe 100644 --- a/spec/ParseRole.spec.js +++ b/spec/ParseRole.spec.js @@ -2,9 +2,9 @@ // Roles are not accessible without the master key, so they are not intended // for use by clients. We can manually test them using the master key. -const RestQuery = require("../src/RestQuery"); -const Auth = require("../src/Auth").Auth; -const Config = require("../src/Config"); +const RestQuery = require("../lib/RestQuery"); +const Auth = require("../lib/Auth").Auth; +const Config = require("../lib/Config"); describe('Parse Role testing', () => { it('Do a bunch of basic role testing', done => { diff --git a/spec/ParseServer.spec.js b/spec/ParseServer.spec.js index c5f945a238..121ba4ae94 100644 --- a/spec/ParseServer.spec.js +++ b/spec/ParseServer.spec.js @@ -1,19 +1,26 @@ 'use strict'; /* Tests for ParseServer.js */ const express = require('express'); -import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter'; -import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter'; -import ParseServer from '../src/ParseServer'; +const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; +const PostgresStorageAdapter = require('../lib/Adapters/Storage/Postgres/PostgresStorageAdapter').default; +const ParseServer = require('../lib/ParseServer').default; describe('Server Url Checks', () => { - const app = express(); - app.get('/health', function(req, res){ - res.json({ - status: 'ok' + let server; + beforeAll((done) => { + const app = express(); + app.get('/health', function(req, res){ + res.json({ + status: 'ok' + }); }); + server = app.listen(13376, undefined, done); + }); + + afterAll((done) => { + server.close(done); }); - app.listen(13376); it('validate good server url', (done) => { Parse.serverURL = 'http://localhost:13376'; diff --git a/spec/ParseServerRESTController.spec.js b/spec/ParseServerRESTController.spec.js index a33244c0ba..4759d1a551 100644 --- a/spec/ParseServerRESTController.spec.js +++ b/spec/ParseServerRESTController.spec.js @@ -1,5 +1,5 @@ -const ParseServerRESTController = require('../src/ParseServerRESTController').ParseServerRESTController; -const ParseServer = require('../src/ParseServer').default; +const ParseServerRESTController = require('../lib/ParseServerRESTController').ParseServerRESTController; +const ParseServer = require('../lib/ParseServer').default; const Parse = require('parse/node').Parse; let RESTController; diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index f714cf90a0..3e34700810 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -7,9 +7,10 @@ "use strict"; +const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; const request = require('request'); -const passwordCrypto = require('../src/password'); -const Config = require('../src/Config'); +const passwordCrypto = require('../lib/password'); +const Config = require('../lib/Config'); const rp = require('request-promise'); function verifyACL(user) { @@ -100,7 +101,7 @@ describe('Parse.User testing', () => { }); }); - it('user login with non-string username with REST API', (done) => { + it('user login with non-string username with REST API (again)', (done) => { Parse.User.signUp('asdf', 'zxcv', null, { success: () => { return rp.post({ @@ -213,6 +214,106 @@ describe('Parse.User testing', () => { }) }); + it('should let masterKey lockout user', (done) => { + const user = new Parse.User(); + const ACL = new Parse.ACL(); + ACL.setPublicReadAccess(false); + ACL.setPublicWriteAccess(false); + user.setUsername('asdf'); + user.setPassword('zxcv'); + user.setACL(ACL); + user.signUp().then(() => { + return Parse.User.logIn("asdf", "zxcv"); + }).then((user) => { + equal(user.get("username"), "asdf"); + // Lock the user down + const ACL = new Parse.ACL(); + user.setACL(ACL); + return user.save(null, { useMasterKey: true }); + }).then(() => { + expect(user.getACL().getPublicReadAccess()).toBe(false); + return Parse.User.logIn("asdf", "zxcv"); + }).then(done.fail).catch((err) => { + expect(err.message).toBe('Invalid username/password.'); + expect(err.code).toBe(Parse.Error.OBJECT_NOT_FOUND); + done(); + }); + }); + + it_only_db('mongo')('should let legacy users without ACL login', async() => { + const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase'; + const adapter = new MongoStorageAdapter({ collectionPrefix: 'test_', uri: databaseURI }); + await adapter.connect(); + await adapter.database.dropDatabase(); + delete adapter.connectionPromise; + + const user = new Parse.User(); + await user.signUp({ + username: 'newUser', + password: 'password', + }); + + const collection = await adapter._adaptiveCollection('_User'); + await collection.insertOne({ + // the hashed password is 'password' hashed + "_hashed_password": "$2b$10$mJ2ca2UbCM9hlojYHZxkQe8pyEXe5YMg0nMdvP4AJBeqlTEZJ6/Uu", + "_session_token": "xxx", + "email": "xxx@a.b", + "username": "oldUser", + "emailVerified": true, + "_email_verify_token": "yyy", + }); + + // get the 2 users + const users = await collection.find(); + expect(users.length).toBe(2); + + const aUser = await Parse.User.logIn('oldUser', 'password'); + expect(aUser).not.toBeUndefined(); + + const newUser = await Parse.User.logIn('newUser', 'password'); + expect(newUser).not.toBeUndefined(); + }); + + it('should be let masterKey lock user out with authData', (done) => { + let objectId; + let sessionToken; + + rp.post({ + url: 'http://localhost:8378/1/classes/_User', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest', + }, + json: { key: "value", authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}} + }).then((body) => { + objectId = body.objectId; + sessionToken = body.sessionToken; + expect(sessionToken).toBeDefined(); + expect(objectId).toBeDefined(); + const user = new Parse.User(); + user.id = objectId; + const ACL = new Parse.ACL(); + user.setACL(ACL); + return user.save(null, { useMasterKey: true }); + }).then(() => { + // update the user + const options = { + url: `http://localhost:8378/1/classes/_User/`, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest', + }, + json: { key: "otherValue", authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}} + } + return rp.post(options); + }).then((res) => { + // Because the user is locked out, this should behave as creating a new user + expect(res.objectId).not.toEqual(objectId); + }).then(done) + .catch(done.fail); + }); + it("user login with files", (done) => { const file = new Parse.File("yolo.txt", [1,2,3], "text/plain"); file.save().then((file) => { @@ -424,6 +525,71 @@ describe('Parse.User testing', () => { }); }); + it('never locks himself up', async () => { + const user = new Parse.User(); + await user.signUp({ + username: 'username', + password: 'password' + }); + user.setACL(new Parse.ACL()); + await user.save(); + await user.fetch(); + expect(user.getACL().getReadAccess(user)).toBe(true); + expect(user.getACL().getWriteAccess(user)).toBe(true); + const publicReadACL = new Parse.ACL(); + publicReadACL.setPublicReadAccess(true); + + // Create an administrator role with a single admin user + const role = new Parse.Role('admin', publicReadACL); + const admin = new Parse.User(); + await admin.signUp({ + username: 'admin', + password: 'admin', + }); + role.getUsers().add(admin); + await role.save(null, { useMasterKey: true }); + + // Grant the admins write rights on the user + const acl = user.getACL(); + acl.setRoleWriteAccess(role, true); + acl.setRoleReadAccess(role, true); + + // Update with the masterKey just to be sure + await user.save({ ACL: acl }, { useMasterKey: true }); + + // Try to update from admin... should all work fine + await user.save({ key: 'fromAdmin'}, { sessionToken: admin.getSessionToken() }); + await user.fetch(); + expect(user.toJSON().key).toEqual('fromAdmin'); + + // Try to save when logged out (public) + let failed = false; + try { + // Ensure no session token is sent + await Parse.User.logOut(); + await user.save({ key: 'fromPublic'}); + } catch(e) { + failed = true; + expect(e.code).toBe(Parse.Error.SESSION_MISSING); + } + expect({ failed }).toEqual({ failed: true }); + + // Try to save with a random user, should fail + failed = false; + const anyUser = new Parse.User(); + await anyUser.signUp({ + username: 'randomUser', + password: 'password' + }); + try { + await user.save({ key: 'fromAnyUser'}); + } catch(e) { + failed = true; + expect(e.code).toBe(Parse.Error.SESSION_MISSING); + } + expect({ failed }).toEqual({ failed: true }); + }); + it("current user", (done) => { const user = new Parse.User(); user.set("password", "asdf"); @@ -1722,7 +1888,7 @@ describe('Parse.User testing', () => { }); }); - it('should fail linking with existing', (done) => { + it('should fail linking with existing through REST', (done) => { const provider = getMockFacebookProvider(); Parse.User._registerAuthenticationProvider(provider); Parse.User._logInWith("facebook", { @@ -2278,7 +2444,7 @@ describe('Parse.User testing', () => { }, (error, response, body) => { expect(error).toBe(null); const b = JSON.parse(body); - expect(b.error).toBe('invalid session token'); + expect(b.error).toBe('Invalid session token'); request.put({ headers: { 'X-Parse-Application-Id': 'test', @@ -2370,7 +2536,7 @@ describe('Parse.User testing', () => { expect(error).toBe(null); const b = JSON.parse(body); expect(b.code).toEqual(209); - expect(b.error).toBe('invalid session token'); + expect(b.error).toBe('Invalid session token'); done(); }); }); @@ -2412,7 +2578,7 @@ describe('Parse.User testing', () => { }, (error,response,body) => { const b = JSON.parse(body); expect(b.code).toEqual(209); - expect(b.error).toBe('invalid session token'); + expect(b.error).toBe('Invalid session token'); done(); }); }); @@ -2449,7 +2615,7 @@ describe('Parse.User testing', () => { done(); }, function(err) { expect(err.code).toBe(Parse.Error.INVALID_SESSION_TOKEN); - expect(err.message).toBe('invalid session token'); + expect(err.message).toBe('Invalid session token'); done(); }); }); @@ -2525,7 +2691,7 @@ describe('Parse.User testing', () => { }); }); - it("invalid session tokens are rejected", (done) => { + it("Invalid session tokens are rejected", (done) => { Parse.User.signUp("asdf", "zxcv", null, { success: function() { request.get({ @@ -2538,7 +2704,7 @@ describe('Parse.User testing', () => { }, }, (error, response, body) => { expect(body.code).toBe(209); - expect(body.error).toBe('invalid session token'); + expect(body.error).toBe('Invalid session token'); done(); }) } @@ -3515,14 +3681,18 @@ describe('Parse.User testing', () => { email: 'yo@lo.com' }).then(() => { const token = user.getSessionToken(); - const promises = []; - while(promises.length != 5) { - promises.push(Parse.User.logIn('yolo', 'yolo').then((res) => { - // ensure a new session token is generated at each login - expect(res.getSessionToken()).not.toBe(token); - })); - } - return Promise.all(promises); + let promise = Promise.resolve(); + let count = 0; + while(count < 5) { + promise = promise.then(() => { + return Parse.User.logIn('yolo', 'yolo').then((res) => { + // ensure a new session token is generated at each login + expect(res.getSessionToken()).not.toBe(token); + }); + }); + count++; + } + return promise; }).then(() => { // wait because session destruction is not synchronous return new Promise((resolve) => { @@ -3536,4 +3706,36 @@ describe('Parse.User testing', () => { expect(results.length).toBe(1); }).then(done, done.fail); }); + + describe('issue #4897', () => { + it_only_db('mongo')("should be able to login with a legacy user (no ACL)", async () => { + // This issue is a side effect of the locked users and legacy users which don't have ACL's + // In this scenario, a legacy user wasn't be able to login as there's no ACL on it + const database = Config.get(Parse.applicationId).database; + const collection = await database.adapter._adaptiveCollection('_User'); + await collection.insertOne({ + "_id": "ABCDEF1234", + "name": "", + "email": "", + "username": "", + "_hashed_password": "", + "_auth_data_facebook": { + "id": "8675309", + "access_token": "jenny" + }, + "sessionToken": "", + }); + const provider = getMockFacebookProvider(); + Parse.User._registerAuthenticationProvider(provider); + const model = await Parse.User._logInWith("facebook", {}); + expect(model.id).toBe('ABCDEF1234'); + ok(model instanceof Parse.User, "Model should be a Parse.User"); + strictEqual(Parse.User.current(), model); + ok(model.extended(), "Should have used subclass."); + strictEqual(provider.authData.id, provider.synchronizedUserId); + strictEqual(provider.authData.access_token, provider.synchronizedAuthToken); + strictEqual(provider.authData.expiration_date, provider.synchronizedExpiration); + ok(model._isLinked("facebook"), "User should be linked to facebook"); + }); + }); }); diff --git a/spec/ParseWebSocket.spec.js b/spec/ParseWebSocket.spec.js index bd61807a01..b72dd28434 100644 --- a/spec/ParseWebSocket.spec.js +++ b/spec/ParseWebSocket.spec.js @@ -1,4 +1,4 @@ -const ParseWebSocket = require('../src/LiveQuery/ParseWebSocketServer').ParseWebSocket; +const ParseWebSocket = require('../lib/LiveQuery/ParseWebSocketServer').ParseWebSocket; describe('ParseWebSocket', function() { diff --git a/spec/ParseWebSocketServer.spec.js b/spec/ParseWebSocketServer.spec.js index a16f6a0104..b1b1ae5ad8 100644 --- a/spec/ParseWebSocketServer.spec.js +++ b/spec/ParseWebSocketServer.spec.js @@ -1,4 +1,4 @@ -const ParseWebSocketServer = require('../src/LiveQuery/ParseWebSocketServer').ParseWebSocketServer; +const ParseWebSocketServer = require('../lib/LiveQuery/ParseWebSocketServer').ParseWebSocketServer; describe('ParseWebSocketServer', function() { diff --git a/spec/PointerPermissions.spec.js b/spec/PointerPermissions.spec.js index 32830059bc..5c83365062 100644 --- a/spec/PointerPermissions.spec.js +++ b/spec/PointerPermissions.spec.js @@ -1,5 +1,5 @@ 'use strict'; -const Config = require('../src/Config'); +const Config = require('../lib/Config'); describe('Pointer Permissions', () => { diff --git a/spec/PostgresConfigParser.spec.js b/spec/PostgresConfigParser.spec.js index 0d41f320b5..4b966b1e2a 100644 --- a/spec/PostgresConfigParser.spec.js +++ b/spec/PostgresConfigParser.spec.js @@ -1,4 +1,4 @@ -const parser = require('../src/Adapters/Storage/Postgres/PostgresConfigParser'); +const parser = require('../lib/Adapters/Storage/Postgres/PostgresConfigParser'); const queryParamTests = { 'a=1&b=2': { a: '1', b: '2' }, diff --git a/spec/PostgresInitOptions.spec.js b/spec/PostgresInitOptions.spec.js index 1297963ad3..f870b3b7de 100644 --- a/spec/PostgresInitOptions.spec.js +++ b/spec/PostgresInitOptions.spec.js @@ -1,27 +1,19 @@ const Parse = require('parse/node').Parse; -import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter'; +const PostgresStorageAdapter = require('../lib/Adapters/Storage/Postgres/PostgresStorageAdapter').default; const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database'; -const ParseServer = require("../src/index"); +const ParseServer = require("../lib/index"); const express = require('express'); //public schema const databaseOptions1 = { initOptions: { - connect: function (client, dc, isFresh) { - if (isFresh) { - client.query('SET search_path = public'); - } - } + schema: 'public' } }; //not exists schema const databaseOptions2 = { initOptions: { - connect: function (client, dc, isFresh) { - if (isFresh) { - client.query('SET search_path = not_exists_schema'); - } - } + schema: 'not_exists_schema' } }; diff --git a/spec/PostgresStorageAdapter.spec.js b/spec/PostgresStorageAdapter.spec.js index 1ba24f6515..d54cb9f2a8 100644 --- a/spec/PostgresStorageAdapter.spec.js +++ b/spec/PostgresStorageAdapter.spec.js @@ -1,4 +1,4 @@ -import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter'; +const PostgresStorageAdapter = require('../lib/Adapters/Storage/Postgres/PostgresStorageAdapter').default; const databaseURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database'; const getColumns = (client, className) => { diff --git a/spec/PromiseRouter.spec.js b/spec/PromiseRouter.spec.js index d0ce63b0eb..7dc0b1a234 100644 --- a/spec/PromiseRouter.spec.js +++ b/spec/PromiseRouter.spec.js @@ -1,4 +1,4 @@ -const PromiseRouter = require("../src/PromiseRouter").default; +const PromiseRouter = require("../lib/PromiseRouter").default; describe("PromiseRouter", () => { it("should properly handle rejects", (done) => { diff --git a/spec/PushController.spec.js b/spec/PushController.spec.js index 60dc4619b4..059f0d6632 100644 --- a/spec/PushController.spec.js +++ b/spec/PushController.spec.js @@ -1,8 +1,8 @@ "use strict"; -const PushController = require('../src/Controllers/PushController').PushController; -const StatusHandler = require('../src/StatusHandler'); -const Config = require('../src/Config'); -const validatePushType = require('../src/Push/utils').validatePushType; +const PushController = require('../lib/Controllers/PushController').PushController; +const StatusHandler = require('../lib/StatusHandler'); +const Config = require('../lib/Config'); +const validatePushType = require('../lib/Push/utils').validatePushType; const successfulTransmissions = function(body, installations) { @@ -245,6 +245,84 @@ describe('PushController', () => { }); }); + it('properly increment badges by more than 1', (done) => { + const pushAdapter = { + send: function(body, installations) { + const badge = body.data.badge; + installations.forEach((installation) => { + expect(installation.badge).toEqual(badge); + expect(installation.originalBadge + 3).toEqual(installation.badge); + }) + return successfulTransmissions(body, installations); + }, + getValidPushTypes: function() { + return ["ios", "android"]; + } + } + const payload = {data:{ + alert: "Hello World!", + badge: { __op: 'Increment', amount: 3 }, + }} + const installations = []; + while(installations.length != 10) { + const installation = new Parse.Object("_Installation"); + installation.set("installationId", "installation_" + installations.length); + installation.set("deviceToken","device_token_" + installations.length) + installation.set("badge", installations.length); + installation.set("originalBadge", installations.length); + installation.set("deviceType", "ios"); + installations.push(installation); + } + + while(installations.length != 15) { + const installation = new Parse.Object("_Installation"); + installation.set("installationId", "installation_" + installations.length); + installation.set("deviceToken","device_token_" + installations.length); + installation.set("badge", installations.length); + installation.set("originalBadge", installations.length); + installation.set("deviceType", "android"); + installations.push(installation); + } + const config = Config.get(Parse.applicationId); + const auth = { + isMaster: true + } + + const pushController = new PushController(); + reconfigureServer({ + push: { adapter: pushAdapter } + }).then(() => { + return Parse.Object.saveAll(installations) + }).then(() => { + return pushController.sendPush(payload, {}, config, auth); + }).then(() => { + // Wait so the push is completed. + return new Promise((resolve) => { setTimeout(() => { resolve(); }, 1000); }); + }).then(() => { + // Check we actually sent 15 pushes. + const query = new Parse.Query('_PushStatus'); + return query.find({ useMasterKey: true }) + }).then((results) => { + expect(results.length).toBe(1); + const pushStatus = results[0]; + expect(pushStatus.get('numSent')).toBe(15); + }).then(() => { + // Check that the installations were actually updated. + const query = new Parse.Query('_Installation'); + return query.find({ useMasterKey: true }) + }).then((results) => { + expect(results.length).toBe(15); + for (let i = 0; i < 15; i++) { + const installation = results[i]; + expect(installation.get('badge')).toBe(parseInt(installation.get('originalBadge')) + 3); + } + done() + }).catch((err) => { + jfail(err); + done(); + }); + }); + it('properly set badges to 1', (done) => { const pushAdapter = { diff --git a/spec/PushQueue.spec.js b/spec/PushQueue.spec.js index 3e9aedae98..1bf282203d 100644 --- a/spec/PushQueue.spec.js +++ b/spec/PushQueue.spec.js @@ -1,5 +1,5 @@ -import Config from "../src/Config"; -import {PushQueue} from "../src/Push/PushQueue"; +const Config = require("../lib/Config"); +const {PushQueue} = require("../lib/Push/PushQueue"); describe('PushQueue', () => { describe('With a defined channel', () => { diff --git a/spec/PushRouter.spec.js b/spec/PushRouter.spec.js index 6a942498ea..70781fc137 100644 --- a/spec/PushRouter.spec.js +++ b/spec/PushRouter.spec.js @@ -1,4 +1,4 @@ -const PushRouter = require('../src/Routers/PushRouter').PushRouter; +const PushRouter = require('../lib/Routers/PushRouter').PushRouter; const request = require('request'); describe('PushRouter', () => { diff --git a/spec/PushWorker.spec.js b/spec/PushWorker.spec.js index 43d49ac5bc..9234a28d77 100644 --- a/spec/PushWorker.spec.js +++ b/spec/PushWorker.spec.js @@ -1,8 +1,8 @@ -const PushWorker = require('../src').PushWorker; -const PushUtils = require('../src/Push/utils'); -const Config = require('../src/Config'); -const { pushStatusHandler } = require('../src/StatusHandler'); -const rest = require('../src/rest'); +const PushWorker = require('../lib').PushWorker; +const PushUtils = require('../lib/Push/utils'); +const Config = require('../lib/Config'); +const { pushStatusHandler } = require('../lib/StatusHandler'); +const rest = require('../lib/rest'); describe('PushWorker', () => { it('should run with small batch', (done) => { @@ -90,6 +90,10 @@ describe('PushWorker', () => { expect(locales).toEqual(['fr']); }); + it('should handle empty body data', () => { + expect(PushUtils.getLocalesFromPush({})).toEqual([]); + }); + it('transforms body appropriately', () => { const cleanBody = PushUtils.transformPushBodyForLocale({ data: { diff --git a/spec/QueryTools.spec.js b/spec/QueryTools.spec.js index 7069725214..9c5acf1f73 100644 --- a/spec/QueryTools.spec.js +++ b/spec/QueryTools.spec.js @@ -1,7 +1,7 @@ const Parse = require('parse/node'); -const Id = require('../src/LiveQuery/Id'); -const QueryTools = require('../src/LiveQuery/QueryTools'); +const Id = require('../lib/LiveQuery/Id'); +const QueryTools = require('../lib/LiveQuery/QueryTools'); const queryHash = QueryTools.queryHash; const matchesQuery = QueryTools.matchesQuery; diff --git a/spec/ReadPreferenceOption.spec.js b/spec/ReadPreferenceOption.spec.js index c25dec0f01..bfbc1525fd 100644 --- a/spec/ReadPreferenceOption.spec.js +++ b/spec/ReadPreferenceOption.spec.js @@ -3,7 +3,7 @@ const Parse = require('parse/node'); const ReadPreference = require('mongodb').ReadPreference; const rp = require('request-promise'); -const Config = require("../src/Config"); +const Config = require("../lib/Config"); describe_only_db('mongo')('Read preference option', () => { it('should find in primary by default', (done) => { @@ -27,17 +27,56 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference = null; databaseAdapter.database.serverConfig.cursor.calls.all().forEach((call) => { if (call.args[0].indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[2].readPreference.preference; + myObjectReadPreference = true; + expect(call.args[2].readPreference.preference).toBe(ReadPreference.PRIMARY); } }); - expect(myObjectReadPreference).toEqual(ReadPreference.PRIMARY); + expect(myObjectReadPreference).toBe(true); done(); }); }); }); + it('should preserve the read preference set (#4831)', async () => { + const { MongoStorageAdapter } = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter'); + const adapterOptions = { + uri: 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase', + mongoOptions: { + readPreference: ReadPreference.NEAREST, + } + }; + await reconfigureServer({ databaseAdapter: new MongoStorageAdapter(adapterOptions) }); + + const databaseAdapter = (Config.get(Parse.applicationId)).database.adapter; + + const obj0 = new Parse.Object('MyObject'); + obj0.set('boolKey', false); + const obj1 = new Parse.Object('MyObject'); + obj1.set('boolKey', true); + + await Parse.Object.saveAll([obj0, obj1]) + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); + + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); + + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach((call) => { + if (call.args[0].indexOf('MyObject') >= 0) { + myObjectReadPreference = true; + expect(call.args[2].readPreference.preference).toBe(ReadPreference.NEAREST); + } + }); + + expect(myObjectReadPreference).toBe(true); + }); + it('should change read preference in the beforeFind trigger', (done) => { const databaseAdapter = (Config.get(Parse.applicationId)).database.adapter; @@ -442,18 +481,20 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference2 = null; databaseAdapter.database.serverConfig.cursor.calls.all().forEach((call) => { if (call.args[0].indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[2].readPreference.preference; + myObjectReadPreference0 = true; + expect(call.args[2].readPreference.preference).toBe(ReadPreference.PRIMARY); } if (call.args[0].indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[2].readPreference.preference; + myObjectReadPreference1 = true; + expect(call.args[2].readPreference.preference).toBe(ReadPreference.PRIMARY); } if (call.args[0].indexOf('MyObject2') >= 0) { myObjectReadPreference2 = call.args[2].readPreference.preference; } }); - expect(myObjectReadPreference0).toEqual(ReadPreference.PRIMARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.PRIMARY); + expect(myObjectReadPreference0).toBe(true); + expect(myObjectReadPreference1).toBe(true); expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY); done(); @@ -555,18 +596,20 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference2 = null; databaseAdapter.database.serverConfig.cursor.calls.all().forEach((call) => { if (call.args[0].indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[2].readPreference.preference; + myObjectReadPreference0 = true; + expect(call.args[2].readPreference.preference).toBe(ReadPreference.PRIMARY); } if (call.args[0].indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[2].readPreference.preference; + myObjectReadPreference1 = true; + expect(call.args[2].readPreference.preference).toBe(ReadPreference.PRIMARY); } if (call.args[0].indexOf('MyObject2') >= 0) { myObjectReadPreference2 = call.args[2].readPreference.preference; } }); - expect(myObjectReadPreference0).toEqual(ReadPreference.PRIMARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.PRIMARY); + expect(myObjectReadPreference0).toBe(true); + expect(myObjectReadPreference1).toBe(true); expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY); done(); diff --git a/spec/RedisCacheAdapter.spec.js b/spec/RedisCacheAdapter.spec.js index 4669d341a3..956e342701 100644 --- a/spec/RedisCacheAdapter.spec.js +++ b/spec/RedisCacheAdapter.spec.js @@ -1,4 +1,4 @@ -const RedisCacheAdapter = require('../src/Adapters/Cache/RedisCacheAdapter').default; +const RedisCacheAdapter = require('../lib/Adapters/Cache/RedisCacheAdapter').default; /* To run this test part of the complete suite set PARSE_SERVER_TEST_CACHE='redis' diff --git a/spec/RedisPubSub.spec.js b/spec/RedisPubSub.spec.js index 32497b576b..8530a95c0c 100644 --- a/spec/RedisPubSub.spec.js +++ b/spec/RedisPubSub.spec.js @@ -1,4 +1,4 @@ -const RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; +const RedisPubSub = require('../lib/Adapters/PubSub/RedisPubSub').RedisPubSub; describe('RedisPubSub', function() { diff --git a/spec/RestQuery.spec.js b/spec/RestQuery.spec.js index 5d1c888163..1b39af2ba8 100644 --- a/spec/RestQuery.spec.js +++ b/spec/RestQuery.spec.js @@ -1,8 +1,8 @@ 'use strict' // These tests check the "find" functionality of the REST API. -const auth = require('../src/Auth'); -const Config = require('../src/Config'); -const rest = require('../src/rest'); +const auth = require('../lib/Auth'); +const Config = require('../lib/Config'); +const rest = require('../lib/rest'); const querystring = require('querystring'); const rp = require('request-promise'); diff --git a/spec/RevocableSessionsUpgrade.spec.js b/spec/RevocableSessionsUpgrade.spec.js index f9d87536bd..8b546695a8 100644 --- a/spec/RevocableSessionsUpgrade.spec.js +++ b/spec/RevocableSessionsUpgrade.spec.js @@ -1,4 +1,4 @@ -const Config = require('../src/Config'); +const Config = require('../lib/Config'); const sessionToken = 'legacySessionToken'; const rp = require('request-promise'); const Parse = require('parse/node'); diff --git a/spec/Schema.spec.js b/spec/Schema.spec.js index c00f930c6c..c2f738e693 100644 --- a/spec/Schema.spec.js +++ b/spec/Schema.spec.js @@ -1,7 +1,7 @@ 'use strict'; -const Config = require('../src/Config'); -const SchemaController = require('../src/Controllers/SchemaController'); +const Config = require('../lib/Config'); +const SchemaController = require('../lib/Controllers/SchemaController'); const dd = require('deep-diff'); let config; diff --git a/spec/SchemaCache.spec.js b/spec/SchemaCache.spec.js index ffbe918399..7d4e54b09c 100644 --- a/spec/SchemaCache.spec.js +++ b/spec/SchemaCache.spec.js @@ -1,6 +1,6 @@ -const CacheController = require('../src/Controllers/CacheController.js').default; -const InMemoryCacheAdapter = require('../src/Adapters/Cache/InMemoryCacheAdapter').default; -const SchemaCache = require('../src/Controllers/SchemaCache').default; +const CacheController = require('../lib/Controllers/CacheController.js').default; +const InMemoryCacheAdapter = require('../lib/Adapters/Cache/InMemoryCacheAdapter').default; +const SchemaCache = require('../lib/Controllers/SchemaCache').default; describe('SchemaCache', () => { let cacheController; diff --git a/spec/SessionTokenCache.spec.js b/spec/SessionTokenCache.spec.js index 316e55da63..9e230116fb 100644 --- a/spec/SessionTokenCache.spec.js +++ b/spec/SessionTokenCache.spec.js @@ -1,4 +1,4 @@ -const SessionTokenCache = require('../src/LiveQuery/SessionTokenCache').SessionTokenCache; +const SessionTokenCache = require('../lib/LiveQuery/SessionTokenCache').SessionTokenCache; describe('SessionTokenCache', function() { diff --git a/spec/Subscription.spec.js b/spec/Subscription.spec.js index 9fe20179b1..0d06ef304f 100644 --- a/spec/Subscription.spec.js +++ b/spec/Subscription.spec.js @@ -1,9 +1,9 @@ -const Subscription = require('../src/LiveQuery/Subscription').Subscription; +const Subscription = require('../lib/LiveQuery/Subscription').Subscription; let logger; describe('Subscription', function() { beforeEach(function() { - logger = require('../src/logger').logger; + logger = require('../lib/logger').logger; spyOn(logger, 'error').and.callThrough(); }); diff --git a/spec/TwitterAuth.spec.js b/spec/TwitterAuth.spec.js index d98297f745..4845bde7ad 100644 --- a/spec/TwitterAuth.spec.js +++ b/spec/TwitterAuth.spec.js @@ -1,4 +1,4 @@ -const twitter = require('../src/Adapters/Auth/twitter'); +const twitter = require('../lib/Adapters/Auth/twitter'); describe('Twitter Auth', () => { it('should use the proper configuration', () => { diff --git a/spec/Uniqueness.spec.js b/spec/Uniqueness.spec.js index 0789037953..25394cafcf 100644 --- a/spec/Uniqueness.spec.js +++ b/spec/Uniqueness.spec.js @@ -1,7 +1,7 @@ 'use strict'; const Parse = require("parse/node"); -const Config = require('../src/Config'); +const Config = require('../lib/Config'); describe('Uniqueness', function() { it('fail when create duplicate value in unique field', done => { diff --git a/spec/UserController.spec.js b/spec/UserController.spec.js index 4588091f15..0b55346d40 100644 --- a/spec/UserController.spec.js +++ b/spec/UserController.spec.js @@ -1,6 +1,6 @@ -const UserController = require('../src/Controllers/UserController').UserController; +const UserController = require('../lib/Controllers/UserController').UserController; const emailAdapter = require('./MockEmailAdapter') -const AppCache = require('../src/cache').AppCache; +const AppCache = require('../lib/cache').AppCache; describe('UserController', () => { const user = { diff --git a/spec/UserPII.spec.js b/spec/UserPII.spec.js index ef0ebe0946..f581f5a4a6 100644 --- a/spec/UserPII.spec.js +++ b/spec/UserPII.spec.js @@ -3,7 +3,7 @@ const Parse = require('parse/node'); const request = require('request-promise'); -// const Config = require('../src/Config'); +// const Config = require('../lib/Config'); const EMAIL = 'foo@bar.com'; const ZIP = '10001'; diff --git a/spec/ValidationAndPasswordsReset.spec.js b/spec/ValidationAndPasswordsReset.spec.js index 99367a0bbd..3cc1b1a2fe 100644 --- a/spec/ValidationAndPasswordsReset.spec.js +++ b/spec/ValidationAndPasswordsReset.spec.js @@ -2,7 +2,7 @@ const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions'); const request = require('request'); -const Config = require("../src/Config"); +const Config = require("../lib/Config"); describe("Custom Pages, Email Verification, Password Reset", () => { it("should set the custom pages", (done) => { diff --git a/spec/VerifyUserPassword.spec.js b/spec/VerifyUserPassword.spec.js new file mode 100644 index 0000000000..28bd7c38c3 --- /dev/null +++ b/spec/VerifyUserPassword.spec.js @@ -0,0 +1,494 @@ +"use strict"; + +const rp = require('request-promise'); +const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions'); + +const verifyPassword = function (login, password, isEmail = false) { + const body = (!isEmail) ? { username: login, password } : { email: login, password }; + return rp.get({ + url: Parse.serverURL + '/verifyPassword', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest' + }, + body, + json: true + }).then((res) => res) + .catch((err) => err); +}; + +const isAccountLockoutError = function (username, password, duration, waitTime) { + return new Promise((resolve, reject) => { + setTimeout(() => { + Parse.User.logIn(username, password) + .then(() => reject('login should have failed')) + .catch(err => { + if (err.message === 'Your account is locked due to multiple failed login attempts. Please try again after ' + duration + ' minute(s)') { + resolve(); + } else { + reject(err); + } + }); + }, waitTime); + }); +}; + +describe("Verify User Password", () => { + it('fails to verify password when masterKey has locked out user', (done) => { + const user = new Parse.User(); + const ACL = new Parse.ACL(); + ACL.setPublicReadAccess(false); + ACL.setPublicWriteAccess(false); + user.setUsername('testuser'); + user.setPassword('mypass'); + user.setACL(ACL); + user.signUp().then(() => { + return Parse.User.logIn('testuser', 'mypass'); + }).then((user) => { + equal(user.get('username'), 'testuser'); + // Lock the user down + const ACL = new Parse.ACL(); + user.setACL(ACL); + return user.save(null, { useMasterKey: true }); + }).then(() => { + expect(user.getACL().getPublicReadAccess()).toBe(false); + return rp.get({ + url: Parse.serverURL + '/verifyPassword', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest' + }, + qs: { + username: 'testuser', + password: 'mypass', + } + }); + }).then((res) => { + fail(res); + done(); + }).catch((err) => { + expect(err.statusCode).toBe(404); + expect(err.error).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }); + }); + it('fails to verify password when username is not provided in query string REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return rp.get({ + url: Parse.serverURL + '/verifyPassword', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest' + }, + qs: { + username: '', + password: 'mypass', + } + }); + }).then((res) => { + fail(res); + done(); + }).catch((err) => { + expect(err.statusCode).toBe(400); + expect(err.error).toMatch('{"code":200,"error":"username/email is required."}'); + done(); + }); + }); + it('fails to verify password when email is not provided in query string REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return rp.get({ + url: Parse.serverURL + '/verifyPassword', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest' + }, + qs: { + email: '', + password: 'mypass', + } + }); + }).then((res) => { + fail(res); + done(); + }).catch((err) => { + expect(err.statusCode).toBe(400); + expect(err.error).toMatch('{"code":200,"error":"username/email is required."}'); + done(); + }); + }); + it('fails to verify password when username is not provided with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('', 'mypass'); + }).then((res) => { + expect(res.statusCode).toBe(400); + expect(JSON.stringify(res.error)).toMatch('{"code":200,"error":"username/email is required."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when email is not provided with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('', 'mypass', true); + }).then((res) => { + expect(res.statusCode).toBe(400); + expect(JSON.stringify(res.error)).toMatch('{"code":200,"error":"username/email is required."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when password is not provided with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('testuser', ''); + }).then((res) => { + expect(res.statusCode).toBe(400); + expect(JSON.stringify(res.error)).toMatch('{"code":201,"error":"password is required."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when username matches but password does not match hash with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('testuser', 'wrong password'); + }).then((res) => { + expect(res.statusCode).toBe(404); + expect(JSON.stringify(res.error)).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when email matches but password does not match hash with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('my@user.com', 'wrong password', true); + }).then((res) => { + expect(res.statusCode).toBe(404); + expect(JSON.stringify(res.error)).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when typeof username does not equal string REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword(123, 'mypass'); + }).then((res) => { + expect(res.statusCode).toBe(404); + expect(JSON.stringify(res.error)).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when typeof email does not equal string REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword(123, 'mypass', true); + }).then((res) => { + expect(res.statusCode).toBe(404); + expect(JSON.stringify(res.error)).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when typeof password does not equal string REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('my@user.com', 123, true); + }).then((res) => { + expect(res.statusCode).toBe(404); + expect(JSON.stringify(res.error)).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when username cannot be found REST API', (done) => { + verifyPassword('mytestuser', 'mypass') + .then((res) => { + expect(res.statusCode).toBe(404); + expect(JSON.stringify(res.error)).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when email cannot be found REST API', (done) => { + verifyPassword('my@user.com', 'mypass', true) + .then((res) => { + expect(res.statusCode).toBe(404); + expect(JSON.stringify(res.error)).toMatch('{"code":101,"error":"Invalid username/password."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('fails to verify password when preventLoginWithUnverifiedEmail is set to true REST API', (done) => { + reconfigureServer({ + publicServerURL: "http://localhost:8378/", + appName: 'emailVerify', + verifyUserEmails: true, + preventLoginWithUnverifiedEmail: true, + emailAdapter: MockEmailAdapterWithOptions({ + fromAddress: 'parse@example.com', + apiKey: 'k', + domain: 'd', + }), + }).then(() => { + const user = new Parse.User(); + return user.save({ + username: 'unverified-user', + password: 'mypass', + email: 'unverified-email@user.com' + }); + }).then(() => { + return verifyPassword('unverified-email@user.com', 'mypass', true); + }).then((res) => { + expect(res.statusCode).toBe(400); + expect(JSON.stringify(res.error)).toMatch('{"code":205,"error":"User email is not verified."}'); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('verify password lock account if failed verify password attempts are above threshold', done => { + reconfigureServer({ + appName: 'lockout threshold', + accountLockout: { + duration: 1, + threshold: 2 + }, + publicServerURL: "http://localhost:8378/" + }) + .then(() => { + const user = new Parse.User(); + return user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }) + }) + .then(() => { + return verifyPassword('testuser', 'wrong password'); + }) + .then(() => { + return verifyPassword('testuser', 'wrong password'); + }) + .then(() => { + return verifyPassword('testuser', 'wrong password'); + }) + .then(() => { + return isAccountLockoutError('testuser', 'wrong password', 1, 1); + }) + .then(() => { + done(); + }) + .catch(err => { + fail('lock account after failed login attempts test failed: ' + JSON.stringify(err)); + done(); + }); + }); + it('succeed in verifying password when username and email are provided and password matches hash with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return rp.get({ + url: Parse.serverURL + '/verifyPassword', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest' + }, + body: { + username: 'testuser', + email: 'my@user.com', + password: 'mypass' + }, + json: true + }).then((res) => res) + .catch((err) => err); + }).then((res) => { + expect(typeof res).toBe('object'); + expect(typeof res['objectId']).toEqual('string'); + expect(res.hasOwnProperty('sessionToken')).toEqual(false); + expect(res.hasOwnProperty('password')).toEqual(false); + done(); + }).catch((err) => { + fail(err); + done(); + }); + }); + it('succeed in verifying password when username and password matches hash with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('testuser', 'mypass'); + }).then((res) => { + expect(typeof res).toBe('object'); + expect(typeof res['objectId']).toEqual('string'); + expect(res.hasOwnProperty('sessionToken')).toEqual(false); + expect(res.hasOwnProperty('password')).toEqual(false); + done(); + }); + }); + it('succeed in verifying password when email and password matches hash with json payload REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return verifyPassword('my@user.com', 'mypass', true); + }).then((res) => { + expect(typeof res).toBe('object'); + expect(typeof res['objectId']).toEqual('string'); + expect(res.hasOwnProperty('sessionToken')).toEqual(false); + expect(res.hasOwnProperty('password')).toEqual(false); + done(); + }); + }); + it('succeed to verify password when username and password provided in query string REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return rp.get({ + url: Parse.serverURL + '/verifyPassword', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest' + }, + qs: { + username: 'testuser', + password: 'mypass', + } + }); + }).then((res) => { + expect(typeof res).toBe('string'); + const body = JSON.parse(res); + expect(typeof body['objectId']).toEqual('string'); + expect(body.hasOwnProperty('sessionToken')).toEqual(false); + expect(body.hasOwnProperty('password')).toEqual(false); + done(); + }); + }); + it('succeed to verify password when email and password provided in query string REST API', (done) => { + const user = new Parse.User(); + user.save({ + username: 'testuser', + password: 'mypass', + email: 'my@user.com' + }).then(() => { + return rp.get({ + url: Parse.serverURL + '/verifyPassword', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest' + }, + qs: { + email: 'my@user.com', + password: 'mypass', + } + }); + }).then((res) => { + expect(typeof res).toBe('string'); + const body = JSON.parse(res); + expect(typeof body['objectId']).toEqual('string'); + expect(body.hasOwnProperty('sessionToken')).toEqual(false); + expect(body.hasOwnProperty('password')).toEqual(false); + done(); + }); + }); + it('succeed to verify password with username when user1 has username === user2 email REST API', (done) => { + const user1 = new Parse.User(); + user1.save({ + username: 'email@user.com', + password: 'mypass1', + email: '1@user.com' + }).then(() => { + const user2 = new Parse.User(); + return user2.save({ + username: 'user2', + password: 'mypass2', + email: 'email@user.com' + }); + }).then(() => { + return verifyPassword('email@user.com', 'mypass1'); + }).then((res) => { + expect(typeof res).toBe('object'); + expect(typeof res['objectId']).toEqual('string'); + expect(res.hasOwnProperty('sessionToken')).toEqual(false); + expect(res.hasOwnProperty('password')).toEqual(false); + done(); + }); + }); +}) diff --git a/spec/WinstonLoggerAdapter.spec.js b/spec/WinstonLoggerAdapter.spec.js index 555a3feeeb..da450b6388 100644 --- a/spec/WinstonLoggerAdapter.spec.js +++ b/spec/WinstonLoggerAdapter.spec.js @@ -1,6 +1,6 @@ 'use strict'; -const WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; +const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; const request = require('request'); describe('info logs', () => { diff --git a/spec/batch.spec.js b/spec/batch.spec.js index b789b92b35..0cc36796ab 100644 --- a/spec/batch.spec.js +++ b/spec/batch.spec.js @@ -1,4 +1,4 @@ -const batch = require('../src/batch'); +const batch = require('../lib/batch'); const originalURL = '/parse/batch'; const serverURL = 'http://localhost:1234/parse'; diff --git a/spec/cryptoUtils.spec.js b/spec/cryptoUtils.spec.js index effa73b9fd..8270e052cf 100644 --- a/spec/cryptoUtils.spec.js +++ b/spec/cryptoUtils.spec.js @@ -1,4 +1,4 @@ -const cryptoUtils = require('../src/cryptoUtils'); +const cryptoUtils = require('../lib/cryptoUtils'); function givesUniqueResults(fn, iterations) { const results = {}; diff --git a/spec/helper.js b/spec/helper.js index 7b9c2153eb..adcee4494b 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -1,11 +1,11 @@ "use strict" // Sets up a Parse API server for testing. const SpecReporter = require('jasmine-spec-reporter').SpecReporter; - +const supportsColor = require('supports-color'); jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 5000; jasmine.getEnv().clearReporters(); -jasmine.getEnv().addReporter(new SpecReporter()); +jasmine.getEnv().addReporter(new SpecReporter({ colors: { enabled: supportsColor.stdout }, spec: { displayDuration: true }})); global.on_db = (db, callback, elseCallback) => { if (process.env.PARSE_SERVER_TEST_DB == db) { @@ -23,15 +23,15 @@ if (global._babelPolyfill) { process.exit(1); } -const cache = require('../src/cache').default; -const ParseServer = require('../src/index').ParseServer; +const cache = require('../lib/cache').default; +const ParseServer = require('../lib/index').ParseServer; const path = require('path'); -const TestUtils = require('../src/TestUtils'); -const GridStoreAdapter = require('../src/Adapters/Files/GridStoreAdapter').GridStoreAdapter; +const TestUtils = require('../lib/TestUtils'); +const GridStoreAdapter = require('../lib/Adapters/Files/GridStoreAdapter').GridStoreAdapter; const FSAdapter = require('@parse/fs-files-adapter'); -import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter'; -import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter'; -const RedisCacheAdapter = require('../src/Adapters/Cache/RedisCacheAdapter').default; +const PostgresStorageAdapter = require('../lib/Adapters/Storage/Postgres/PostgresStorageAdapter').default; +const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; +const RedisCacheAdapter = require('../lib/Adapters/Cache/RedisCacheAdapter').default; const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase'; const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database'; @@ -114,7 +114,6 @@ if (process.env.PARSE_SERVER_TEST_CACHE === 'redis') { } const openConnections = {}; - // Set up a default API server for testing with default configuration. let server; @@ -173,7 +172,7 @@ beforeEach(done => { throw error; } } - TestUtils.destroyAllDataPermanently() + TestUtils.destroyAllDataPermanently(true) .catch(error => { // For tests that connect to their own mongo, there won't be any data to delete. if (error.message === 'ns not found' || error.message.startsWith('connect ECONNREFUSED')) { @@ -197,7 +196,7 @@ afterEach(function(done) { fail('There were open connections to the server left after the test finished'); } on_db('postgres', () => { - TestUtils.destroyAllDataPermanently().then(done, done); + TestUtils.destroyAllDataPermanently(true).then(done, done); }, done); }; Parse.Cloud._removeAllHooks(); @@ -217,7 +216,14 @@ afterEach(function(done) { }); }) .then(() => Parse.User.logOut()) - .then(afterLogOut, afterLogOut) + .then(() => {}, () => {}) // swallow errors + .then(() => { + // Connection close events are not immediate on node 10+... wait a bit + return new Promise((resolve) => { + setTimeout(resolve, 0); + }); + }) + .then(afterLogOut) }); const TestObject = Parse.Object.extend({ @@ -287,11 +293,13 @@ function expectError(errorCode, callback) { error: function(obj, e) { // Some methods provide 2 parameters. e = e || obj; - if (!e) { - fail('expected a specific error but got a blank error'); - return; + if (errorCode !== undefined) { + if (!e) { + fail('expected a specific error but got a blank error'); + return; + } + expect(e.code).toEqual(errorCode, e.message); } - expect(e.code).toEqual(errorCode, e.message); if (callback) { callback(e); } @@ -410,7 +418,7 @@ global.it_exclude_dbs = excluded => { } global.it_only_db = db => { - if (process.env.PARSE_SERVER_TEST_DB === db) { + if (process.env.PARSE_SERVER_TEST_DB === db || !process.env.PARSE_SERVER_TEST_DB && db == 'mongo') { return it; } else { return xit; @@ -431,7 +439,7 @@ global.describe_only_db = db => { } else if (!process.env.PARSE_SERVER_TEST_DB && db == 'mongo') { return describe; } else { - return () => {}; + return xdescribe; } } diff --git a/spec/index.spec.js b/spec/index.spec.js index 335a8ac3fc..f962a4f06c 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -2,11 +2,11 @@ const request = require('request'); const parseServerPackage = require('../package.json'); const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions'); -const ParseServer = require("../src/index"); -const Config = require('../src/Config'); +const ParseServer = require("../lib/index"); +const Config = require('../lib/Config'); const express = require('express'); -import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter'; +const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; describe('server', () => { it('requires a master key and app id', done => { diff --git a/spec/parsers.spec.js b/spec/parsers.spec.js index e6313bb091..9249c0fa6f 100644 --- a/spec/parsers.spec.js +++ b/spec/parsers.spec.js @@ -1,4 +1,4 @@ -import { +const { numberParser, numberOrBoolParser, booleanParser, @@ -6,7 +6,7 @@ import { arrayParser, moduleOrObjectParser, nullParser, -} from '../src/Options/parsers'; +} = require('../lib/Options/parsers'); describe('parsers', () => { it('parses correctly with numberParser', () => { diff --git a/spec/rest.spec.js b/spec/rest.spec.js index af6ce8c41f..fae39b18e9 100644 --- a/spec/rest.spec.js +++ b/spec/rest.spec.js @@ -1,10 +1,10 @@ "use strict"; // These tests check the "create" / "update" functionality of the REST API. -const auth = require('../src/Auth'); -const Config = require('../src/Config'); +const auth = require('../lib/Auth'); +const Config = require('../lib/Config'); const Parse = require('parse/node').Parse; -const rest = require('../src/rest'); -const RestWrite = require('../src/RestWrite'); +const rest = require('../lib/rest'); +const RestWrite = require('../lib/RestWrite'); const request = require('request'); const rp = require('request-promise'); diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index a5a8256d84..e8ec3de67b 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -4,7 +4,7 @@ const Parse = require('parse/node').Parse; const request = require('request'); const rp = require('request-promise'); const dd = require('deep-diff'); -const Config = require('../src/Config'); +const Config = require('../lib/Config'); let config; @@ -262,21 +262,6 @@ describe('schemas', () => { }); }); - it('asks for the master key if you use the rest key', done => { - request.post({ - url: 'http://localhost:8378/1/schemas', - json: true, - headers: restKeyHeaders, - body: { - className: 'MyClass', - }, - }, (error, response, body) => { - expect(response.statusCode).toEqual(403); - expect(body.error).toEqual('unauthorized: master key is required'); - done(); - }); - }); - it('sends an error if you use mismatching class names', done => { request.post({ url: 'http://localhost:8378/1/schemas/A', @@ -1212,7 +1197,7 @@ describe('schemas', () => { }) }); - it('should throw with invalid * (spaces)', done => { + it('should throw with invalid * (spaces before)', done => { request.post({ url: 'http://localhost:8378/1/schemas/AClass', headers: masterKeyHeaders, @@ -1230,7 +1215,7 @@ describe('schemas', () => { }) }); - it('should throw with invalid * (spaces)', done => { + it('should throw with invalid * (spaces after)', done => { request.post({ url: 'http://localhost:8378/1/schemas/AClass', headers: masterKeyHeaders, @@ -1248,7 +1233,7 @@ describe('schemas', () => { }) }); - it('should throw with invalid value', done => { + it('should throw if permission is number', done => { request.post({ url: 'http://localhost:8378/1/schemas/AClass', headers: masterKeyHeaders, @@ -1266,7 +1251,7 @@ describe('schemas', () => { }) }); - it('should throw with invalid value', done => { + it('should throw if permission is empty string', done => { request.post({ url: 'http://localhost:8378/1/schemas/AClass', headers: masterKeyHeaders, @@ -1787,11 +1772,9 @@ describe('schemas', () => { 'delete': {}, 'addField': {}, }); - console.log(res); }).then(done).catch(done.fail); }); - it('regression test for #2246', done => { const profile = new Parse.Object('UserProfile'); const user = new Parse.User(); @@ -1828,133 +1811,89 @@ describe('schemas', () => { }); }); - it('cannot create index if field does not exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + describe('index management', () => { + beforeEach(() => require('../lib/TestUtils').destroyAllDataPermanently()); + it('cannot create index if field does not exist', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - indexes: { - name1: { aString: 1}, + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { aString: 1}, + } } - } - }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Field aString does not exist, cannot add index.'); - done(); - }); - }) - }); + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Field aString does not exist, cannot add index.'); + done(); + }); + }) + }); - it('cannot create compound index if field does not exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('can create index on default field', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'} - }, - indexes: { - name1: { aString: 1, bString: 1}, + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { createdAt: 1}, + } } - } - }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Field bString does not exist, cannot add index.'); - done(); - }); - }) - }); - - it('allows add index when you create a class', done => { - request.post({ - url: 'http://localhost:8378/1/schemas', - headers: masterKeyHeaders, - json: true, - body: { - className: "NewClass", - fields: { - aString: {type: 'String'} - }, - indexes: { - name1: { aString: 1}, - }, - } - }, (error, response, body) => { - expect(body).toEqual({ - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'} - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - name1: { aString: 1}, - }, - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toBe(2); - done(); - }); + }, (error, response, body) => { + expect(body.indexes.name1).toEqual({ createdAt: 1}); + done(); + }); + }) }); - }); - it('empty index returns nothing', done => { - request.post({ - url: 'http://localhost:8378/1/schemas', - headers: masterKeyHeaders, - json: true, - body: { - className: "NewClass", - fields: { - aString: {type: 'String'} - }, - indexes: {}, - } - }, (error, response, body) => { - expect(body).toEqual({ - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'} - }, - classLevelPermissions: defaultClassLevelPermissions, - }); - done(); + it('cannot create compound index if field does not exist', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + fields: { + aString: {type: 'String'} + }, + indexes: { + name1: { aString: 1, bString: 1}, + } + } + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Field bString does not exist, cannot add index.'); + done(); + }); + }) }); - }); - it('lets you add indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ - url: 'http://localhost:8378/1/schemas/NewClass', + it('allows add index when you create a class', done => { + request.post({ + url: 'http://localhost:8378/1/schemas', headers: masterKeyHeaders, json: true, body: { + className: "NewClass", fields: { aString: {type: 'String'} }, @@ -1963,7 +1902,7 @@ describe('schemas', () => { }, } }, (error, response, body) => { - expect(dd(body, { + expect(body).toEqual({ className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -1974,164 +1913,134 @@ describe('schemas', () => { }, classLevelPermissions: defaultClassLevelPermissions, indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - } - })).toEqual(undefined); - request.get({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - }, (error, response, body) => { - expect(body).toEqual({ - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'} - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(2); - done(); - }); + name1: { aString: 1}, + }, + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toBe(2); + done(); }); }); - }) - }); + }); - it('lets you add multiple indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ - url: 'http://localhost:8378/1/schemas/NewClass', + it('empty index returns nothing', done => { + request.post({ + url: 'http://localhost:8378/1/schemas', headers: masterKeyHeaders, json: true, body: { + className: "NewClass", fields: { - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, + aString: {type: 'String'} }, - indexes: { - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1, dString: 1 }, - } + indexes: {}, } }, (error, response, body) => { - expect(dd(body, { + expect(body).toEqual({ className: 'NewClass', fields: { ACL: {type: 'ACL'}, createdAt: {type: 'Date'}, updatedAt: {type: 'Date'}, objectId: {type: 'String'}, - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, + aString: {type: 'String'} }, classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1, dString: 1 }, - } - })).toEqual(undefined); - request.get({ + }); + done(); + }); + }); + + it('lets you add indexes', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: {}, + }, () => { + request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, + body: { + fields: { + aString: {type: 'String'} + }, + indexes: { + name1: { aString: 1}, + }, + } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, createdAt: {type: 'Date'}, updatedAt: {type: 'Date'}, objectId: {type: 'String'}, - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, + aString: {type: 'String'} }, classLevelPermissions: defaultClassLevelPermissions, indexes: { _id_: { _id: 1 }, name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1, dString: 1 }, - }, - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(4); - done(); + } + })).toEqual(undefined); + request.get({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'} + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name1: { aString: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(2); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('lets you delete indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('lets you add multiple indexes', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 }, - } - } - }, (error, response, body) => { - expect(dd(body, { - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'}, - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - } - })).toEqual(undefined); + body: {}, + }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, indexes: { - name1: { __op: 'Delete' } + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1, dString: 1 }, } } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2139,76 +2048,145 @@ describe('schemas', () => { updatedAt: {type: 'Date'}, objectId: {type: 'String'}, aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, }, classLevelPermissions: defaultClassLevelPermissions, indexes: { _id_: { _id: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1, dString: 1 }, } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(1); - done(); + })).toEqual(undefined); + request.get({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1, dString: 1 }, + }, + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(4); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('lets you delete multiple indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('lets you delete indexes', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, - } - } - }, (error, response, body) => { - expect(dd(body, { - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + fields: { + aString: {type: 'String'}, + }, + indexes: { + name1: { aString: 1 }, + } } - })).toEqual(undefined); + }, (error, response, body) => { + expect(dd(body, { + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name1: { aString: 1 }, + } + })).toEqual(undefined); + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { __op: 'Delete' } + } + } + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(1); + done(); + }); + }); + }); + }) + }); + + it('lets you delete multiple indexes', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: {}, + }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + }, indexes: { - name1: { __op: 'Delete' }, - name2: { __op: 'Delete' }, + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1 }, } } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2222,76 +2200,74 @@ describe('schemas', () => { classLevelPermissions: defaultClassLevelPermissions, indexes: { _id_: { _id: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, name3: { cString: 1 }, } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(2); - done(); + })).toEqual(undefined); + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { __op: 'Delete' }, + name2: { __op: 'Delete' }, + } + } + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name3: { cString: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(2); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('lets you add and delete indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('lets you add and delete indexes', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, - } - } - }, (error, response, body) => { - expect(dd(body, { - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, - } - })).toEqual(undefined); + body: {}, + }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, indexes: { - name1: { __op: 'Delete' }, - name2: { __op: 'Delete' }, - name4: { dString: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1 }, } } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2306,150 +2282,183 @@ describe('schemas', () => { classLevelPermissions: defaultClassLevelPermissions, indexes: { _id_: { _id: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, name3: { cString: 1 }, - name4: { dString: 1 }, } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(3); - done(); + })).toEqual(undefined); + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { __op: 'Delete' }, + name2: { __op: 'Delete' }, + name4: { dString: 1 }, + } + } + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name3: { cString: 1 }, + name4: { dString: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(3); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('cannot delete index that does not exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('cannot delete index that does not exist', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - indexes: { - unknownIndex: { __op: 'Delete' } + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + unknownIndex: { __op: 'Delete' } + } } - } - }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Index unknownIndex does not exist, cannot delete.'); - done(); - }); - }) - }); + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Index unknownIndex does not exist, cannot delete.'); + done(); + }); + }) + }); - it('cannot update index that exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('cannot update index that exist', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 } - } - } + body: {}, }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + }, indexes: { - name1: { field2: 1 } + name1: { aString: 1 } } } + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { field2: 1 } + } + } + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Index name1 exists, cannot update.'); + done(); + }); + }); + }) + }); + + it_exclude_dbs(['postgres'])('get indexes on startup', (done) => { + const obj = new Parse.Object('TestObject'); + obj.save().then(() => { + return reconfigureServer({ + appId: 'test', + restAPIKey: 'test', + publicServerURL: 'http://localhost:8378/1', + }); + }).then(() => { + request.get({ + url: 'http://localhost:8378/1/schemas/TestObject', + headers: masterKeyHeaders, + json: true, }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Index name1 exists, cannot update.'); + expect(body.indexes._id_).toBeDefined(); done(); }); }); - }) - }); + }); - it_exclude_dbs(['postgres'])('get indexes on startup', (done) => { - const obj = new Parse.Object('TestObject'); - obj.save().then(() => { - return reconfigureServer({ - appId: 'test', - restAPIKey: 'test', - publicServerURL: 'http://localhost:8378/1', - }); - }).then(() => { - request.get({ - url: 'http://localhost:8378/1/schemas/TestObject', - headers: masterKeyHeaders, - json: true, - }, (error, response, body) => { - expect(body.indexes._id_).toBeDefined(); - done(); + it_exclude_dbs(['postgres'])('get compound indexes on startup', (done) => { + const obj = new Parse.Object('TestObject'); + obj.set('subject', 'subject'); + obj.set('comment', 'comment'); + obj.save().then(() => { + return config.database.adapter.createIndex('TestObject', {subject: 'text', comment: 'text'}); + }).then(() => { + return reconfigureServer({ + appId: 'test', + restAPIKey: 'test', + publicServerURL: 'http://localhost:8378/1', + }); + }).then(() => { + request.get({ + url: 'http://localhost:8378/1/schemas/TestObject', + headers: masterKeyHeaders, + json: true, + }, (error, response, body) => { + expect(body.indexes._id_).toBeDefined(); + expect(body.indexes._id_._id).toEqual(1); + expect(body.indexes.subject_text_comment_text).toBeDefined(); + expect(body.indexes.subject_text_comment_text.subject).toEqual('text'); + expect(body.indexes.subject_text_comment_text.comment).toEqual('text'); + done(); + }); }); }); - }); - it_exclude_dbs(['postgres'])('get compound indexes on startup', (done) => { - const obj = new Parse.Object('TestObject'); - obj.set('subject', 'subject'); - obj.set('comment', 'comment'); - obj.save().then(() => { - return config.database.adapter.createIndex('TestObject', {subject: 'text', comment: 'text'}); - }).then(() => { - return reconfigureServer({ - appId: 'test', - restAPIKey: 'test', - publicServerURL: 'http://localhost:8378/1', - }); - }).then(() => { - request.get({ - url: 'http://localhost:8378/1/schemas/TestObject', - headers: masterKeyHeaders, - json: true, - }, (error, response, body) => { - expect(body.indexes._id_).toBeDefined(); - expect(body.indexes._id_._id).toEqual(1); - expect(body.indexes.subject_text_comment_text).toBeDefined(); - expect(body.indexes.subject_text_comment_text.subject).toEqual('text'); - expect(body.indexes.subject_text_comment_text.comment).toEqual('text'); + it_exclude_dbs(['postgres'])('cannot update to duplicate value on unique index', (done) => { + const index = { + code: 1 + }; + const obj1 = new Parse.Object('UniqueIndexClass'); + obj1.set('code', 1); + const obj2 = new Parse.Object('UniqueIndexClass'); + obj2.set('code', 2); + const adapter = config.database.adapter; + adapter._adaptiveCollection('UniqueIndexClass').then(collection => { + return collection._ensureSparseUniqueIndexInBackground(index); + }).then(() => { + return obj1.save(); + }).then(() => { + return obj2.save(); + }).then(() => { + obj1.set('code', 2); + return obj1.save(); + }).then(done.fail).catch((error) => { + expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE); done(); }); }); }); - - it_exclude_dbs(['postgres'])('cannot update to duplicate value on unique index', (done) => { - const index = { - code: 1 - }; - const obj1 = new Parse.Object('UniqueIndexClass'); - obj1.set('code', 1); - const obj2 = new Parse.Object('UniqueIndexClass'); - obj2.set('code', 2); - const adapter = config.database.adapter; - adapter._adaptiveCollection('UniqueIndexClass').then(collection => { - return collection._ensureSparseUniqueIndexInBackground(index); - }).then(() => { - return obj1.save(); - }).then(() => { - return obj2.save(); - }).then(() => { - obj1.set('code', 2); - return obj1.save(); - }).then(done.fail).catch((error) => { - expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE); - done(); - }); - }); }); diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json index 3f247853a2..1fff21a70f 100644 --- a/spec/support/jasmine.json +++ b/spec/support/jasmine.json @@ -4,7 +4,6 @@ "*spec.js" ], "helpers": [ - "../node_modules/babel-core/register.js", "helper.js" ], "random": false diff --git a/spec/testing-routes.js b/spec/testing-routes.js index ac982ffce8..29cb6cf5f6 100644 --- a/spec/testing-routes.js +++ b/spec/testing-routes.js @@ -1,11 +1,11 @@ // testing-routes.js -import AppCache from '../src/cache'; -import * as middlewares from '../src/middlewares'; -import { ParseServer } from '../src/index'; -import { Parse } from 'parse/node'; +const AppCache = require('../lib/cache').default; +const middlewares = require('../lib/middlewares'); +const { ParseServer } = require('../lib/index'); +const { Parse } = require('parse/node'); const express = require('express'), - cryptoUtils = require('../src/cryptoUtils'); + cryptoUtils = require('../lib/cryptoUtils'); const router = express.Router(); diff --git a/src/Adapters/Auth/facebook.js b/src/Adapters/Auth/facebook.js index ab846e43e6..b36f59017c 100644 --- a/src/Adapters/Auth/facebook.js +++ b/src/Adapters/Auth/facebook.js @@ -37,7 +37,7 @@ function validateAppId(appIds, authData) { // A promisey wrapper for FB graph requests. function graphRequest(path) { return new Promise(function(resolve, reject) { - https.get('https://graph.facebook.com/v2.5/' + path, function(res) { + https.get('https://graph.facebook.com/' + path, function(res) { var data = ''; res.on('data', function(chunk) { data += chunk; diff --git a/src/Adapters/Auth/vkontakte.js b/src/Adapters/Auth/vkontakte.js index 8c9bd5efc8..b43b60f189 100644 --- a/src/Adapters/Auth/vkontakte.js +++ b/src/Adapters/Auth/vkontakte.js @@ -10,7 +10,7 @@ var logger = require('../../logger').default; function validateAuthData(authData, params) { return vkOAuth2Request(params).then(function (response) { if (response && response.access_token) { - return request("api.vk.com", "method/secure.checkToken?token=" + authData.access_token + "&client_secret=" + params.appSecret + "&access_token=" + response.access_token).then(function (response) { + return request("api.vk.com", "method/secure.checkToken?token=" + authData.access_token + "&client_secret=" + params.appSecret + "&access_token=" + response.access_token + "&v=5.59").then(function (response) { if (response && response.response && response.response.user_id == authData.id) { return; } diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index e1db8b93b2..333efb314c 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -161,7 +161,7 @@ export class MongoStorageAdapter implements StorageAdapter { return this.connectionPromise; } - handleError(error: ?Error): Promise { + handleError(error: ?(Error | Parse.Error)): Promise { if (error && error.code === 13) { // Unauthorized error delete this.client; delete this.database; @@ -313,11 +313,9 @@ export class MongoStorageAdapter implements StorageAdapter { .catch(err => this.handleError(err)); } - // Delete all data known to this adapter. Used for testing. - deleteAllClasses() { + deleteAllClasses(fast: boolean) { return storageAdapterAllCollections(this) - .then(collections => Promise.all(collections.map(collection => collection.drop()))) - .catch(err => this.handleError(err)); + .then(collections => Promise.all(collections.map(collection => fast ? collection.remove({}) : collection.drop()))); } // Remove the column and all the data. For Relations, the _Join collection is handled @@ -557,26 +555,17 @@ export class MongoStorageAdapter implements StorageAdapter { aggregate(className: string, schema: any, pipeline: any, readPreference: ?string) { let isPointerField = false; pipeline = pipeline.map((stage) => { - if (stage.$group && stage.$group._id && (typeof stage.$group._id === 'string')) { - const field = stage.$group._id.substring(1); - if (schema.fields[field] && schema.fields[field].type === 'Pointer') { + 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; - stage.$group._id = `$_p_${field}`; } } if (stage.$match) { - for (const field in stage.$match) { - if (schema.fields[field] && schema.fields[field].type === 'Pointer') { - const transformMatch = { [`_p_${field}`] : `${className}$${stage.$match[field]}` }; - stage.$match = transformMatch; - } - if (field === 'objectId') { - const transformMatch = Object.assign({}, stage.$match); - transformMatch._id = stage.$match[field]; - delete transformMatch.objectId; - stage.$match = transformMatch; - } - } + stage.$match = this._parseAggregateArgs(schema, stage.$match); + } + if (stage.$project) { + stage.$project = this._parseAggregateProjectArgs(schema, stage.$project); } return stage; }); @@ -608,6 +597,130 @@ export class MongoStorageAdapter implements StorageAdapter { .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: any, pipeline: any): any { + 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: any, pipeline: any): any { + 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: any, pipeline: any): any { + 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: any): any { + 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: ?string): ?string { switch (readPreference) { case 'PRIMARY': @@ -626,8 +739,6 @@ export class MongoStorageAdapter implements StorageAdapter { readPreference = ReadPreference.NEAREST; break; case undefined: - // this is to match existing tests, which were failing as mongodb@3.0 don't report readPreference anymore - readPreference = ReadPreference.PRIMARY; break; default: throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Not supported read preference.'); diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index a5cbe1f195..453bddef70 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -123,6 +123,44 @@ const transformKeyValueForUpdate = (className, restKey, restValue, parseFormatSc 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"); @@ -209,9 +247,9 @@ function transformQueryKeyValue(className, key, value, schema) { case '_perishable_token': case '_email_verify_token': return {key, value} case '$or': - return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema))}; case '$and': - return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, schema))}; + case '$nor': + return {key: key, value: value.map(subQuery => transformWhere(className, subQuery, schema))}; case 'lastUsed': if (valueAsDate(value)) { return {key: '_last_used', value: valueAsDate(value)} @@ -252,6 +290,9 @@ function transformQueryKeyValue(className, key, value, schema) { if (transformedConstraint.$text) { return {key: '$text', value: transformedConstraint.$text}; } + if (transformedConstraint.$elemMatch) { + return { key: '$nor', value: [{ [key]: transformedConstraint }] }; + } return {key, value: transformedConstraint}; } @@ -469,6 +510,8 @@ const transformInteriorAtom = (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; } @@ -740,6 +783,13 @@ function transformConstraint(constraint, field) { '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': @@ -750,6 +800,19 @@ function transformConstraint(constraint, field) { 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; @@ -842,29 +905,70 @@ function transformConstraint(constraint, field) { case '$geoWithin': { const polygon = constraint[key]['$polygon']; - if (!(polygon instanceof Array)) { - throw new Parse.Error( - Parse.Error.INVALID_JSON, - 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints' - ); - } - if (polygon.length < 3) { - throw new Parse.Error( - Parse.Error.INVALID_JSON, - 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints' - ); - } - const points = polygon.map((point) => { - if (!GeoPointCoder.isValidJSON(point)) { - throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value'); + 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 { - Parse.GeoPoint._validate(point.latitude, point.longitude); + throw new Parse.Error( + Parse.Error.INVALID_JSON, + 'bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint\'s' + ); } - return [point.longitude, point.latitude]; - }); - answer[key] = { - '$polygon': points - }; + 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': { diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index ef005c595c..2df5abb66d 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -233,7 +233,13 @@ const joinTablesForSchema = (schema) => { return list; } -const buildWhereClause = ({ schema, query, index }) => { +interface WhereClause { + pattern: string; + values: Array; + sorts: Array; +} + +const buildWhereClause = ({ schema, query, index }): WhereClause => { const patterns = []; let values = []; const sorts = []; @@ -287,13 +293,20 @@ const buildWhereClause = ({ schema, query, index }) => { index += 2; } else if (typeof fieldValue === 'boolean') { patterns.push(`$${index}:name = $${index + 1}`); - values.push(fieldName, fieldValue); + // 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 (fieldName === '$or' || fieldName === '$and') { + } else if (['$or', '$nor', '$and'].includes(fieldName)) { const clauses = []; const clauseValues = []; fieldValue.forEach((subQuery) => { @@ -304,8 +317,11 @@ const buildWhereClause = ({ schema, query, index }) => { index += clause.values.length; } }); - const orOrAnd = fieldName === '$or' ? ' OR ' : ' AND '; - patterns.push(`(${clauses.join(orOrAnd)})`); + + const orOrAnd = fieldName === '$and' ? ' AND ' : ' OR '; + const not = fieldName === '$nor' ? ' NOT ' : ''; + + patterns.push(`${not}(${clauses.join(orOrAnd)})`); values.push(...clauseValues); } @@ -329,11 +345,16 @@ const buildWhereClause = ({ schema, query, index }) => { values.push(fieldName, fieldValue.$ne); index += 2; } - - if (fieldValue.$eq) { - patterns.push(`$${index}:name = $${index + 1}`); - values.push(fieldName, fieldValue.$eq); - index += 2; + if (fieldValue.$eq !== undefined) { + if (fieldValue.$eq === null) { + patterns.push(`$${index}:name IS NULL`); + values.push(fieldName); + index += 1; + } else { + patterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.$eq); + index += 2; + } } const isInOrNin = Array.isArray(fieldValue.$in) || Array.isArray(fieldValue.$nin); if (Array.isArray(fieldValue.$in) && @@ -393,10 +414,27 @@ const buildWhereClause = ({ schema, query, index }) => { if (fieldValue.$nin) { createConstraint(_.flatMap(fieldValue.$nin, elt => elt), true); } + } else if(typeof fieldValue.$in !== 'undefined') { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $in value'); + } else if (typeof fieldValue.$nin !== 'undefined') { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $nin value'); } if (Array.isArray(fieldValue.$all) && isArrayField) { - patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`); + if (isAnyValueRegexStartsWith(fieldValue.$all)) { + if (!isAllValuesRegexOrNone(fieldValue.$all)) { + throw new Parse.Error(Parse.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; } @@ -411,6 +449,20 @@ const buildWhereClause = ({ schema, query, index }) => { index += 1; } + if (fieldValue.$containedBy) { + const arr = fieldValue.$containedBy; + if (!(arr instanceof Array)) { + throw new Parse.Error( + Parse.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'; @@ -483,21 +535,60 @@ const buildWhereClause = ({ schema, query, index }) => { index += 2; } + if (fieldValue.$geoWithin && fieldValue.$geoWithin.$centerSphere) { + const centerSphere = fieldValue.$geoWithin.$centerSphere; + 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'); + } + 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; - if (!(polygon instanceof Array)) { - throw new Parse.Error( - Parse.Error.INVALID_JSON, - 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints' - ); - } - if (polygon.length < 3) { + 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 contain at least 3 GeoPoints' + 'bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint\'s' ); } - const points = polygon.map((point) => { + points = points.map((point) => { + if (point instanceof Array && point.length === 2) { + Parse.GeoPoint._validate(point[1], point[0]); + return `(${point[0]}, ${point[1]})`; + } if (typeof point !== 'object' || point.__type !== 'GeoPoint') { throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value'); } else { @@ -578,7 +669,7 @@ const buildWhereClause = ({ schema, query, index }) => { } Object.keys(ParseToPosgresComparator).forEach(cmp => { - if (fieldValue[cmp]) { + if (fieldValue[cmp] || fieldValue[cmp] === 0) { const pgComparator = ParseToPosgresComparator[cmp]; patterns.push(`$${index}:name ${pgComparator} $${index + 1}`); values.push(fieldName, toPostgresValue(fieldValue[cmp])); @@ -595,6 +686,9 @@ const buildWhereClause = ({ schema, query, index }) => { } export class PostgresStorageAdapter implements StorageAdapter { + + canSortOnJoinTables: boolean; + // Private _collectionPrefix: string; _client: any; @@ -609,6 +703,7 @@ export class PostgresStorageAdapter implements StorageAdapter { const { client, pgp } = createClient(uri, databaseOptions); this._client = client; this._pgp = pgp; + this.canSortOnJoinTables = false; } handleShutdown() { @@ -846,7 +941,7 @@ export class PostgresStorageAdapter implements StorageAdapter { return this._client.task('delete-all-classes', function * (t) { try { const results = yield t.any('SELECT * FROM "_SCHEMA"'); - const joins = results.reduce((list, schema) => { + const joins = results.reduce((list: Array, schema: any) => { return list.concat(joinTablesForSchema(schema.schema)); }, []); const classes = ['_SCHEMA', '_PushStatus', '_JobStatus', '_JobSchedule', '_Hooks', '_GlobalConfig', '_Audience', ...results.map(result => result.className), ...joins]; @@ -879,7 +974,7 @@ export class PostgresStorageAdapter implements StorageAdapter { // Returns a Promise. deleteFields(className: string, schema: SchemaType, fieldNames: string[]): Promise { debug('deleteFields', className, fieldNames); - fieldNames = fieldNames.reduce((list, fieldName) => { + fieldNames = fieldNames.reduce((list: Array, fieldName: string) => { const field = schema.fields[fieldName] if (field.type !== 'Relation') { list.push(fieldName); @@ -1133,14 +1228,14 @@ export class PostgresStorageAdapter implements StorageAdapter { } else if (fieldName == 'authData') { // This recursively sets the json_object // Only 1 level deep - const generate = (jsonb, key, value) => { + const generate = (jsonb: string, key: string, value: any) => { 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 update = Object.keys(fieldValue).reduce((lastKey: string, key: string) => { const str = generate(lastKey, `$${index}::text`, `$${index + 1}::jsonb`) index += 2; let value = fieldValue[key]; @@ -1243,17 +1338,17 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - const keysToDelete = Object.keys(originalUpdate).filter(k => { + const keysToDelete: Array = 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) => { + const deletePatterns = keysToDelete.reduce((p: string, c: string, i: number) => { return p + ` - '$${index + 1 + i}:value'`; }, ''); - updatePatterns.push(`$${index}:name = ( COALESCE($${index}:name, '{}'::jsonb) ${deletePatterns} ${incrementPatterns} || $${index + 1 + keysToDelete.length}::jsonb )`); + updatePatterns.push(`$${index}:name = ('{}'::jsonb ${deletePatterns} ${incrementPatterns} || $${index + 1 + keysToDelete.length}::jsonb )`); values.push(fieldName, ...keysToDelete, JSON.stringify(fieldValue)); index += 2 + keysToDelete.length; @@ -1326,11 +1421,12 @@ export class PostgresStorageAdapter implements StorageAdapter { if (sort) { const sortCopy: any = 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 `"${key}" ASC`; + return `${transformKey} ASC`; } - return `"${key}" DESC`; + return `${transformKey} DESC`; }).join(); sortPattern = sort !== undefined && Object.keys(sort).length > 0 ? `ORDER BY ${sorting}` : ''; } @@ -1540,7 +1636,7 @@ export class PostgresStorageAdapter implements StorageAdapter { aggregate(className: string, schema: any, pipeline: any) { debug('aggregate', className, pipeline); const values = [className]; - let index = 2; + let index: number = 2; let columns: string[] = []; let countField = null; let groupValues = null; @@ -1732,6 +1828,7 @@ export class PostgresStorageAdapter implements StorageAdapter { t.none(sql.array.addUnique), t.none(sql.array.remove), t.none(sql.array.containsAll), + t.none(sql.array.containsAllRegex), t.none(sql.array.contains) ]); }); @@ -1836,6 +1933,40 @@ function processRegexPattern(s) { 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 => { if (c.match(/[0-9a-zA-Z]/) !== null) { @@ -1879,4 +2010,13 @@ function literalizeRegexPart(s: string) { ); } +var GeoPointCoder = { + isValidJSON(value) { + return (typeof value === 'object' && + value !== null && + value.__type === 'GeoPoint' + ); + } +}; + export default PostgresStorageAdapter; diff --git a/src/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql b/src/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql new file mode 100644 index 0000000000..7ca5853a9f --- /dev/null +++ b/src/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/src/Adapters/Storage/Postgres/sql/array/contains-all.sql b/src/Adapters/Storage/Postgres/sql/array/contains-all.sql index 24355bc732..8db1ca0e7b 100644 --- a/src/Adapters/Storage/Postgres/sql/array/contains-all.sql +++ b/src/Adapters/Storage/Postgres/sql/array/contains-all.sql @@ -7,5 +7,8 @@ CREATE OR REPLACE FUNCTION array_contains_all( IMMUTABLE STRICT AS $function$ - SELECT RES.CNT = jsonb_array_length("values") FROM (SELECT COUNT(*) as CNT FROM jsonb_array_elements("array") as elt WHERE elt IN (SELECT jsonb_array_elements("values"))) as RES; + 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/src/Adapters/Storage/Postgres/sql/index.js b/src/Adapters/Storage/Postgres/sql/index.js index 5ddfb036cf..6bcd560d13 100644 --- a/src/Adapters/Storage/Postgres/sql/index.js +++ b/src/Adapters/Storage/Postgres/sql/index.js @@ -9,6 +9,7 @@ module.exports = { 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: { diff --git a/src/Adapters/Storage/StorageAdapter.js b/src/Adapters/Storage/StorageAdapter.js index 4123117d8e..ed2c2e0701 100644 --- a/src/Adapters/Storage/StorageAdapter.js +++ b/src/Adapters/Storage/StorageAdapter.js @@ -24,12 +24,14 @@ export type UpdateQueryOptions = { export type FullQueryOptions = QueryOptions & UpdateQueryOptions; export interface StorageAdapter { + canSortOnJoinTables: boolean; + classExists(className: string): Promise; setClassLevelPermissions(className: string, clps: any): Promise; createClass(className: string, schema: SchemaType): Promise; addFieldIfNotExists(className: string, fieldName: string, type: any): Promise; deleteClass(className: string): Promise; - deleteAllClasses(): Promise; + deleteAllClasses(fast: boolean): Promise; deleteFields(className: string, schema: SchemaType, fieldNames: Array): Promise; getAllClasses(): Promise; getClass(className: string): Promise; diff --git a/src/Auth.js b/src/Auth.js index 1cb2e96563..8658f13025 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -21,14 +21,14 @@ function Auth({ config, isMaster = false, isReadOnly = false, user, installation // Whether this auth could possibly modify the given user id. // It still could be forbidden via ACLs even if this returns true. -Auth.prototype.couldUpdateUserId = function(userId) { +Auth.prototype.isUnauthenticated = function() { if (this.isMaster) { - return true; + return false; } - if (this.user && this.user.id === userId) { - return true; + if (this.user) { + return false; } - return false; + return true; }; // A helper to get a master-level Auth object @@ -64,7 +64,7 @@ var getAuthForSessionToken = function({ config, sessionToken, installationId } = return query.execute().then((response) => { var results = response.results; if (results.length !== 1 || !results[0]['user']) { - throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } var now = new Date(), diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 786e69ac05..372be94f81 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -50,7 +50,7 @@ const transformObjectACL = ({ ACL, ...result }) => { return result; } -const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count']; +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; @@ -111,6 +111,14 @@ const validateQuery = (query: any): void => { } } + if (query.$nor) { + if (query.$nor instanceof Array && query.$nor.length > 0) { + query.$nor.forEach(validateQuery); + } else { + throw new Parse.Error(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') { @@ -147,6 +155,7 @@ const filterSensitiveData = (isMaster, aclGroup, className, object) => { 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; @@ -285,6 +294,16 @@ const untransformObjectACL = ({_rperm, _wperm, ...output}) => { 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: string): string => { + return fieldName.split('.')[0] +} + const relationSchema = { fields: { relatedId: { type: 'String' }, owningId: { type: 'String' } } }; class DatabaseController { @@ -402,13 +421,13 @@ class DatabaseController { if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name for update: ${fieldName}`); } - fieldName = fieldName.split('.')[0]; - if (!SchemaController.fieldNameIsValid(fieldName) && !isSpecialUpdateKey(fieldName)) { + const rootFieldName = getRootFieldName(fieldName); + if (!SchemaController.fieldNameIsValid(rootFieldName) && !isSpecialUpdateKey(rootFieldName)) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name for update: ${fieldName}`); } }); - for (const updateOperation: any in update) { - if (Object.keys(updateOperation).some(innerKey => innerKey.includes('$') || innerKey.includes('.'))) { + for (const updateOperation in update) { + if (update[updateOperation] && typeof update[updateOperation] === 'object' && Object.keys(update[updateOperation]).some(innerKey => innerKey.includes('$') || innerKey.includes('.'))) { throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); } } @@ -635,11 +654,16 @@ class DatabaseController { } // Won't delete collections in the system namespace - // Returns a promise. - deleteEverything() { + /** + * 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: boolean = false): Promise { this.schemaPromise = null; return Promise.all([ - this.adapter.deleteAllClasses(), + this.adapter.deleteAllClasses(fast), this.schemaCache.clear() ]); } @@ -850,7 +874,8 @@ class DatabaseController { op, distinct, pipeline, - readPreference + readPreference, + isWrite, }: any = {}): Promise { const isMaster = acl === undefined; const aclGroup = acl || []; @@ -891,7 +916,8 @@ class DatabaseController { if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Cannot sort by ${fieldName}`); } - if (!SchemaController.fieldNameIsValid(fieldName)) { + const rootFieldName = getRootFieldName(fieldName); + if (!SchemaController.fieldNameIsValid(rootFieldName)) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}.`); } }); @@ -910,7 +936,11 @@ class DatabaseController { } } if (!isMaster) { - query = addReadACL(query, aclGroup); + if (isWrite) { + query = addWriteACL(query, aclGroup); + } else { + query = addReadACL(query, aclGroup); + } } validateQuery(query); if (count) { diff --git a/src/Controllers/FilesController.js b/src/Controllers/FilesController.js index 2ea83412db..16cd2ac79c 100644 --- a/src/Controllers/FilesController.js +++ b/src/Controllers/FilesController.js @@ -2,7 +2,7 @@ import { randomHexString } from '../cryptoUtils'; import AdaptableController from './AdaptableController'; import { FilesAdapter } from '../Adapters/Files/FilesAdapter'; -import path from 'path'; +import path from 'path'; import mime from 'mime'; 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}-.*"); @@ -25,9 +25,11 @@ export class FilesController extends AdaptableController { contentType = mime.getType(filename); } - filename = randomHexString(32) + '_' + filename; + if (!this.options.preserveFileName) { + filename = randomHexString(32) + '_' + filename; + } - var location = this.adapter.getFileLocation(config, filename); + const location = this.adapter.getFileLocation(config, filename); return this.adapter.createFile(filename, data, contentType).then(() => { return Promise.resolve({ url: location, diff --git a/src/Controllers/HooksController.js b/src/Controllers/HooksController.js index 70598bb125..db87c57153 100644 --- a/src/Controllers/HooksController.js +++ b/src/Controllers/HooksController.js @@ -6,8 +6,14 @@ import * as Parse from "parse/node"; // @flow-disable-next import * as request from "request"; import { logger } from '../logger'; +import http from 'http'; +import https from 'https'; const DefaultHooksCollectionName = "_Hooks"; +const HTTPAgents = { + http: new http.Agent({ keepAlive: true }), + https: new https.Agent({ keepAlive: true }), +} export class HooksController { _applicationId:string; @@ -177,9 +183,12 @@ function wrapToHTTPRequest(hook, key) { headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(jsonBody) + body: JSON.stringify(jsonBody), }; + const agent = hook.url.startsWith('https') ? HTTPAgents['https'] : HTTPAgents['http']; + jsonRequest.agent = agent; + if (key) { jsonRequest.headers['X-Parse-Webhook-Key'] = key; } else { diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index 416b0ea4ff..8b645a3680 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -44,10 +44,13 @@ export class PushController { 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'"; + throw "Invalid value for badge, expected number or 'Increment' or {increment: number}"; } // Force filtering on only valid device tokens diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index 45d1cf9c27..cff25e043b 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -536,6 +536,8 @@ export default class SchemaController { 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); @@ -567,7 +569,7 @@ export default class SchemaController { return Promise.all(promises); }) .then(() => this.setPermissions(className, classLevelPermissions, newSchema)) - .then(() => this._dbAdapter.setIndexesWithSchemaFormat(className, indexes, schema.indexes, newSchema)) + .then(() => this._dbAdapter.setIndexesWithSchemaFormat(className, indexes, schema.indexes, fullNewSchema)) .then(() => this.reloadData({ clearCache: true })) //TODO: Move this logic into the database adapter .then(() => { diff --git a/src/Controllers/index.js b/src/Controllers/index.js index 7f0288a481..a1958cc983 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -82,6 +82,7 @@ export function getFilesController(options: ParseServerOptions): FilesController databaseURI, filesAdapter, databaseAdapter, + preserveFileName, } = options; if (!filesAdapter && databaseAdapter) { throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.'; @@ -89,7 +90,7 @@ export function getFilesController(options: ParseServerOptions): FilesController const filesControllerAdapter = loadAdapter(filesAdapter, () => { return new GridStoreAdapter(databaseURI); }); - return new FilesController(filesControllerAdapter, appId); + return new FilesController(filesControllerAdapter, appId, { preserveFileName }); } export function getUserController(options: ParseServerOptions): UserController { @@ -149,7 +150,7 @@ export function getDatabaseController(options: ParseServerOptions, cacheControll export function getHooksController(options: ParseServerOptions, databaseController: DatabaseController): HooksController { const { appId, - webhookKey + webhookKey, } = options; return new HooksController(appId, databaseController, webhookKey); } @@ -228,4 +229,3 @@ export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOption }); } } - diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 8a58da95dc..dec6284841 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -135,6 +135,12 @@ module.exports.ParseServerOptions = { "env": "PARSE_SERVER_FILE_KEY", "help": "Key for your files" }, + "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 + }, "userSensitiveFields": { "env": "PARSE_SERVER_USER_SENSITIVE_FIELDS", "help": "Personally identifiable information fields in the user table the should be removed for non-authorized users.", @@ -262,6 +268,12 @@ module.exports.ParseServerOptions = { "action": parsers.booleanParser, "default": false }, + "enableExpressErrorHandler": { + "env": "PARSE_SERVER_ENABLE_EXPRESS_ERROR_HANDLER", + "help": "Enables the default express error handler for all errors", + "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", diff --git a/src/Options/index.js b/src/Options/index.js index e4f6c24dfb..07f0c06ba1 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -64,6 +64,9 @@ export interface ParseServerOptions { webhookKey: ?string; /* Key for your files */ fileKey: ?string; + /* Enable (or disable) the addition of a unique hash to the file names + :ENV: PARSE_SERVER_PRESERVE_FILE_NAME */ + preserveFileName: ?boolean; // = false /* Personally identifiable information fields in the user table the should be removed for non-authorized users. */ userSensitiveFields: ?string[]; // = ["email"] /* Enable (or disable) anon users, defaults to true @@ -114,6 +117,8 @@ export interface ParseServerOptions { cacheMaxSize : ?number; // = 10000 /* 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. */ enableSingleSchemaCache: ?boolean; // = false + /* Enables the default express error handler for all errors */ + enableExpressErrorHandler: ?boolean; // = false /* Sets the number of characters in generated object id's, default 10 */ objectIdSize: ?number; // = 10 /* The port to run the ParseServer. defaults to 1337. diff --git a/src/Push/PushWorker.js b/src/Push/PushWorker.js index 2f05194176..9b16baac7f 100644 --- a/src/Push/PushWorker.js +++ b/src/Push/PushWorker.js @@ -42,13 +42,7 @@ export class PushWorker { } } - unsubscribe(): void { - if (this.subscriber) { - this.subscriber.unsubscribe(this.channel); - } - } - - run({ body, query, pushStatus, applicationId, UTCOffset }: any): Promise { + run({ body, query, pushStatus, applicationId, UTCOffset }: any): Promise { const config = Config.get(applicationId); const auth = master(config); const where = utils.applyDeviceTokenExists(query.where); @@ -59,12 +53,10 @@ export class PushWorker { return pushStatus.trackSent(results); } return this.sendToAdapter(body, results, pushStatus, config, UTCOffset); - }, err => { - throw err; }); } - sendToAdapter(body: any, installations: any, pushStatus: any, config: Config, UTCOffset: any): Promise { + sendToAdapter(body: any, installations: any, pushStatus: any, config: Config, UTCOffset: any): Promise { // Check if we have locales in the push body const locales = utils.getLocalesFromPush(body); if (locales.length > 0) { @@ -102,7 +94,7 @@ export class PushWorker { return Promise.all(promises); } - getAndRun(workItem: any): Promise { + getAndRun(workItem: any): Promise { var _this = this; if (!_this.subscriber.run) { return _this.run(workItem); diff --git a/src/Push/utils.js b/src/Push/utils.js index ed33a66a14..f9b1a4118f 100644 --- a/src/Push/utils.js +++ b/src/Push/utils.js @@ -2,10 +2,17 @@ import Parse from 'parse/node'; import deepcopy from 'deepcopy'; export function isPushIncrementing(body) { - return body.data && - body.data.badge && - typeof body.data.badge == 'string' && - body.data.badge.toLowerCase() == "increment" + 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']; diff --git a/src/RestQuery.js b/src/RestQuery.js index 6899b13f21..db21043bcc 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -24,12 +24,13 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl this.clientSDK = clientSDK; this.response = null; this.findOptions = {}; + this.isWrite = false; + if (!this.auth.isMaster) { - this.findOptions.acl = this.auth.user ? [this.auth.user.id] : null; if (this.className == '_Session') { - if (!this.findOptions.acl) { + if (!this.auth.user) { throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, - 'This session token is invalid.'); + 'Invalid session token'); } this.restWhere = { '$and': [this.restWhere, { @@ -44,6 +45,7 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl } 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, @@ -86,6 +88,9 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl case 'count': this.doCount = true; break; + case 'includeAll': + this.includeAll = true; + break; case 'distinct': case 'pipeline': case 'skip': @@ -149,6 +154,8 @@ function RestQuery(config, auth, className, restWhere = {}, restOptions = {}, cl RestQuery.prototype.execute = function(executeOptions) { return Promise.resolve().then(() => { return this.buildRestWhere(); + }).then(() => { + return this.handleIncludeAll(); }).then(() => { return this.runFind(executeOptions); }).then(() => { @@ -182,17 +189,28 @@ RestQuery.prototype.buildRestWhere = function() { }); } +// Marks the query for a write attempt, so we read the proper ACL (write instead of read) +RestQuery.prototype.forWrite = function() { + this.isWrite = true; + return this; +} + // Uses the Auth object to get the list of roles, adds the user id RestQuery.prototype.getUserAndRoleACL = function() { - if (this.auth.isMaster || !this.auth.user) { + if (this.auth.isMaster) { return Promise.resolve(); } - return this.auth.getUserRoles().then((roles) => { - // Concat with the roles to prevent duplications on multiple calls - const aclSet = new Set([].concat(this.findOptions.acl, roles)); - this.findOptions.acl = Array.from(aclSet); + + 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. @@ -521,6 +539,9 @@ RestQuery.prototype.runFind = function(options = {}) { if (options.op) { findOptions.op = options.op; } + if (this.isWrite) { + findOptions.isWrite = true; + } return this.config.database.find(this.className, this.restWhere, findOptions) .then((results) => { if (this.className === '_User') { @@ -556,6 +577,31 @@ RestQuery.prototype.runCount = function() { }); }; +// 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])]; + } + }); +}; + // Augments this.response with data at the paths provided in this.include. RestQuery.prototype.handleInclude = function() { if (this.include.length == 0) { @@ -594,7 +640,18 @@ RestQuery.prototype.runAfterFindTrigger = function() { } // 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) => { - this.response.results = 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; + } }); }; diff --git a/src/RestWrite.js b/src/RestWrite.js index 82f21edf3e..2a8bb2df0e 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -279,11 +279,23 @@ RestWrite.prototype.findUsersWithAuthData = function(authData) { 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((r) => { - results = r; + results = this.filteredObjectsByACL(r); if (results.length > 1) { // More than 1 user with the passed id's throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, @@ -964,7 +976,7 @@ RestWrite.prototype.runDatabaseOperation = function() { if (this.className === '_User' && this.query && - !this.auth.couldUpdateUserId(this.query.objectId)) { + this.auth.isUnauthenticated()) { throw new Parse.Error(Parse.Error.SESSION_MISSING, `Cannot modify user ${this.query.objectId}.`); } @@ -981,7 +993,7 @@ RestWrite.prototype.runDatabaseOperation = function() { if (this.query) { // Force the user to not lockout // Matched with parse.com - if (this.className === '_User' && this.data.ACL) { + 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 diff --git a/src/Routers/AggregateRouter.js b/src/Routers/AggregateRouter.js index 8f4e859b6d..c99436f380 100644 --- a/src/Routers/AggregateRouter.js +++ b/src/Routers/AggregateRouter.js @@ -4,60 +4,56 @@ import * as middleware from '../middlewares'; import Parse from 'parse/node'; import UsersRouter from './UsersRouter'; -const ALLOWED_KEYS = [ - 'where', - 'distinct', - 'project', +const BASE_KEYS = ['where', 'distinct']; + +const PIPELINE_KEYS = [ + 'addFields', + 'bucket', + 'bucketAuto', + 'collStats', + 'count', + 'currentOp', + 'facet', + 'geoNear', + 'graphLookup', + 'group', + 'indexStats', + 'limit', + 'listLocalSessions', + 'listSessions', + 'lookup', 'match', + 'out', + 'project', 'redact', - 'limit', - 'skip', - 'unwind', - 'group', + 'replaceRoot', 'sample', + 'skip', 'sort', - 'geoNear', - 'lookup', - 'out', - 'indexStats', - 'facet', - 'bucket', - 'bucketAuto', 'sortByCount', - 'addFields', - 'replaceRoot', - 'count', - 'graphLookup', + 'unwind', ]; +const ALLOWED_KEYS = [...BASE_KEYS, ...PIPELINE_KEYS]; + export class AggregateRouter extends ClassesRouter { handleFind(req) { const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query)); const options = {}; - const pipeline = []; + let pipeline = []; - for (const key in body) { - if (ALLOWED_KEYS.indexOf(key) === -1) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, `Invalid parameter for query: ${key}`); + if (Array.isArray(body)) { + pipeline = body.map((stage) => { + const stageName = Object.keys(stage)[0]; + return this.transformStage(stageName, stage); + }); + } else { + const stages = []; + for (const stageName in body) { + stages.push(this.transformStage(stageName, body)); } - if (key === 'group') { - if (body[key].hasOwnProperty('_id')) { - throw new Parse.Error( - Parse.Error.INVALID_QUERY, - `Invalid parameter for query: group. Please use objectId instead of _id` - ); - } - if (!body[key].hasOwnProperty('objectId')) { - throw new Parse.Error( - Parse.Error.INVALID_QUERY, - `Invalid parameter for query: group. objectId is required` - ); - } - body[key]._id = body[key].objectId; - delete body[key].objectId; - } - pipeline.push({ [`$${key}`]: body[key] }); + pipeline = stages; } if (body.distinct) { options.distinct = String(body.distinct); @@ -76,6 +72,32 @@ export class AggregateRouter extends ClassesRouter { }); } + transformStage(stageName, stage) { + if (ALLOWED_KEYS.indexOf(stageName) === -1) { + throw new Parse.Error( + Parse.Error.INVALID_QUERY, + `Invalid parameter for query: ${stageName}` + ); + } + if (stageName === 'group') { + if (stage[stageName].hasOwnProperty('_id')) { + throw new Parse.Error( + Parse.Error.INVALID_QUERY, + `Invalid parameter for query: group. Please use objectId instead of _id` + ); + } + if (!stage[stageName].hasOwnProperty('objectId')) { + throw new Parse.Error( + Parse.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); }); } diff --git a/src/Routers/ClassesRouter.js b/src/Routers/ClassesRouter.js index a9cb49333f..e7205015b8 100644 --- a/src/Routers/ClassesRouter.js +++ b/src/Routers/ClassesRouter.js @@ -100,7 +100,7 @@ export class ClassesRouter extends PromiseRouter { static optionsFromBody(body) { const allowConstraints = ['skip', 'limit', 'order', 'count', 'keys', - 'include', 'redirectClassNameForKey', 'where']; + 'include', 'includeAll', 'redirectClassNameForKey', 'where']; for (const key of Object.keys(body)) { if (allowConstraints.indexOf(key) === -1) { @@ -128,6 +128,9 @@ export class ClassesRouter extends PromiseRouter { if (body.include) { options.include = String(body.include); } + if (body.includeAll) { + options.includeAll = true; + } return options; } diff --git a/src/Routers/FunctionsRouter.js b/src/Routers/FunctionsRouter.js index f3ea4d3872..1bb077acd7 100644 --- a/src/Routers/FunctionsRouter.js +++ b/src/Routers/FunctionsRouter.js @@ -89,6 +89,9 @@ export class FunctionsRouter extends PromiseRouter { }, error: function(code, message) { if (!message) { + if (code instanceof Parse.Error) { + return reject(code) + } message = code; code = Parse.Error.SCRIPT_FAILED; } diff --git a/src/Routers/PurgeRouter.js b/src/Routers/PurgeRouter.js index 8c2a340da9..b9009453c6 100644 --- a/src/Routers/PurgeRouter.js +++ b/src/Routers/PurgeRouter.js @@ -1,5 +1,6 @@ import PromiseRouter from '../PromiseRouter'; import * as middleware from '../middlewares'; +import Parse from 'parse/node'; export class PurgeRouter extends PromiseRouter { @@ -16,6 +17,11 @@ export class PurgeRouter extends PromiseRouter { cacheAdapter.role.clear(); } return {response: {}}; + }).catch((error) => { + if (!error || (error && error.code === Parse.Error.OBJECT_NOT_FOUND)) { + return {response: {}}; + } + throw error; }); } diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index c18be9ae79..3c8690ea50 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -1,11 +1,11 @@ // These methods handle the User-related routes. -import Parse from 'parse/node'; -import Config from '../Config'; +import Parse from 'parse/node'; +import Config from '../Config'; import AccountLockout from '../AccountLockout'; -import ClassesRouter from './ClassesRouter'; -import rest from '../rest'; -import Auth from '../Auth'; +import ClassesRouter from './ClassesRouter'; +import rest from '../rest'; +import Auth from '../Auth'; import passwordCrypto from '../password'; export class UsersRouter extends ClassesRouter { @@ -18,7 +18,7 @@ export class UsersRouter extends ClassesRouter { * Removes all "_" prefixed properties from an object, except "__type" * @param {Object} obj An object. */ - static removeHiddenProperties (obj) { + static removeHiddenProperties(obj) { for (var key in obj) { if (obj.hasOwnProperty(key)) { // Regexp comes from Parse.Object.prototype.validate @@ -29,9 +29,108 @@ export class UsersRouter extends ClassesRouter { } } + /** + * 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 Parse.Error(Parse.Error.USERNAME_MISSING, 'username/email is required.'); + } + if (!password) { + throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'password is required.'); + } + if (typeof password !== 'string' + || email && typeof email !== 'string' + || username && typeof username !== 'string') { + throw new Parse.Error(Parse.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 Parse.Error(Parse.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 passwordCrypto.compare(password, user.password); + }) + .then((correct) => { + isValidPassword = correct; + const accountLockoutPolicy = new AccountLockout(user, req.config); + return accountLockoutPolicy.handleLoginAttempt(isValidPassword); + }) + .then(() => { + if (!isValidPassword) { + throw new Parse.Error(Parse.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 Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); + } + if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) { + throw new Parse.Error(Parse.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 Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } const sessionToken = req.info.sessionToken; return rest.find(req.config, Auth.master(req.config), '_Session', @@ -41,7 +140,7 @@ export class UsersRouter extends ClassesRouter { if (!response.results || response.results.length == 0 || !response.results[0].user) { - throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token'); + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } else { const user = response.results[0].user; // Send token back on the login, because SDKs expect that. @@ -56,67 +155,11 @@ export class UsersRouter extends ClassesRouter { } handleLogIn(req) { - // 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 Parse.Error(Parse.Error.USERNAME_MISSING, 'username/email is required.'); - } - if (!password) { - throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'password is required.'); - } - if (typeof password !== 'string' - || email && typeof email !== 'string' - || username && typeof username !== 'string') { - throw new Parse.Error(Parse.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 Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); - } + return this._authenticateUserFromRequest(req) + .then((res) => { - 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]; - } - - if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) { - throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.'); - } - return passwordCrypto.compare(password, user.password); - }) - .then((correct) => { - isValidPassword = correct; - const accountLockoutPolicy = new AccountLockout(user, req.config); - return accountLockoutPolicy.handleLoginAttempt(isValidPassword); - }) - .then(() => { - if (!isValidPassword) { - throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.'); - } + user = res; // handle password expiry policy if (req.config.passwordPolicy && req.config.passwordPolicy.maxPasswordAge) { @@ -126,8 +169,8 @@ export class UsersRouter extends ClassesRouter { // 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: Parse._encode(changedAt)}); + req.config.database.update('_User', { username: user.username }, + { _password_changed_at: Parse._encode(changedAt) }); } else { // check whether the password has expired if (changedAt.__type == 'Date') { @@ -140,43 +183,45 @@ export class UsersRouter extends ClassesRouter { } } - delete user.password; - // Remove hidden properties. UsersRouter.removeHiddenProperties(user); - // 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; - } - } const { sessionData, createSession - } = Auth.createSession(req.config, { userId: user.objectId, createdWith: { - 'action': 'login', - 'authProvider': 'password' - }, installationId: req.info.installationId }); + } = Auth.createSession(req.config, { + userId: user.objectId, createdWith: { + 'action': 'login', + 'authProvider': 'password' + }, installationId: req.info.installationId + }); user.sessionToken = sessionData.sessionToken; req.config.filesController.expandFilesInObject(req.config, user); return createSession(); - }).then(() => { + }) + .then(() => { + 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: {}}; + const success = { response: {} }; if (req.info && req.info.sessionToken) { return rest.find(req.config, Auth.master(req.config), '_Session', { sessionToken: req.info.sessionToken }, undefined, req.info.clientSDK @@ -281,6 +326,7 @@ export class UsersRouter extends ClassesRouter { 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); }); } } diff --git a/src/TestUtils.js b/src/TestUtils.js index b0ebf4cf5b..ef2fdee81e 100644 --- a/src/TestUtils.js +++ b/src/TestUtils.js @@ -1,14 +1,17 @@ import AppCache from './cache'; -//Used by tests -export function destroyAllDataPermanently() { +/** + * Destroys all data in the database + * @param {boolean} fast set to true if it's ok to just drop objects and not indexes. + */ +export function destroyAllDataPermanently(fast) { if (!process.env.TESTING) { throw 'Only supported in test environment'; } return Promise.all(Object.keys(AppCache.cache).map(appId => { const app = AppCache.get(appId); if (app.databaseController) { - return app.databaseController.deleteEverything(); + return app.databaseController.deleteEverything(fast); } else { return Promise.resolve(); } diff --git a/src/middlewares.js b/src/middlewares.js index 18bcaa11a3..aa8f6755e1 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -247,7 +247,7 @@ export function allowCrossDomain(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-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, X-CSRF-Token'); - + 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); @@ -284,6 +284,9 @@ export function handleParseErrors(err, req, res, next) { res.status(httpStatus); res.json({ code: err.code, error: err.message }); log.error(err.message, err); + if (req.config && req.config.enableExpressErrorHandler) { + next(err); + } } else if (err.status && err.message) { res.status(err.status); res.json({ error: err.message }); diff --git a/src/rest.js b/src/rest.js index cbfacbcca6..33b22c7378 100644 --- a/src/rest.js +++ b/src/rest.js @@ -8,7 +8,6 @@ // things. var Parse = require('parse/node').Parse; -import Auth from './Auth'; var RestQuery = require('./RestQuery'); var RestWrite = require('./RestWrite'); @@ -54,9 +53,9 @@ function del(config, auth, className, objectId) { 'bad objectId'); } - if (className === '_User' && !auth.couldUpdateUserId(objectId)) { + if (className === '_User' && auth.isUnauthenticated()) { throw new Parse.Error(Parse.Error.SESSION_MISSING, - 'insufficient auth to delete user'); + 'Insufficient auth to delete user'); } enforceRoleSecurity('delete', className, auth); @@ -67,14 +66,16 @@ function del(config, auth, className, objectId) { const hasTriggers = checkTriggers(className, config, ['beforeDelete', 'afterDelete']); const hasLiveQuery = checkLiveQuery(className, config); if (hasTriggers || hasLiveQuery || className == '_Session') { - return find(config, Auth.master(config), className, {objectId: objectId}) + return new RestQuery(config, auth, className, { objectId }) + .forWrite() + .execute() .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'); + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token'); } } var cacheAdapter = config.cacheController; @@ -110,6 +111,8 @@ function del(config, auth, className, objectId) { }, options); }).then(() => { return triggers.maybeRunTrigger(triggers.Types.afterDelete, auth, inflatedObject, null, config); + }).catch((error) => { + handleSessionMissingError(error, className, auth); }); } @@ -130,20 +133,33 @@ function update(config, auth, className, restWhere, restObject, clientSDK) { const hasTriggers = checkTriggers(className, config, ['beforeSave', 'afterSave']); const hasLiveQuery = checkLiveQuery(className, config); if (hasTriggers || hasLiveQuery) { - return find(config, Auth.master(config), className, restWhere); + // Do not use find, as it runs the before finds + return new RestQuery(config, auth, className, restWhere) + .forWrite() + .execute(); } return Promise.resolve({}); - }).then((response) => { + }).then(({ results }) => { var originalRestObject; - if (response && response.results && response.results.length) { - originalRestObject = response.results[0]; + if (results && results.length) { + originalRestObject = results[0]; } - - var write = new RestWrite(config, auth, className, restWhere, restObject, originalRestObject, clientSDK); - return write.execute(); + return new RestWrite(config, auth, className, restWhere, restObject, originalRestObject, clientSDK) + .execute(); + }).catch((error) => { + handleSessionMissingError(error, className, auth); }); } +function handleSessionMissingError(error, className) { + // If we're trying to update a user without / with bad session token + if (className === '_User' + && error.code === Parse.Error.OBJECT_NOT_FOUND) { + 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) { diff --git a/src/triggers.js b/src/triggers.js index f8f0e6e89f..cb9d1b0caf 100644 --- a/src/triggers.js +++ b/src/triggers.js @@ -224,6 +224,9 @@ export function getResponseObject(request, resolve, reject) { }, error: function(code, message) { if (!message) { + if (code instanceof Parse.Error) { + return reject(code) + } message = code; code = Parse.Error.SCRIPT_FAILED; } From 96c51d27ca4a27dc2b4f1df88475967fa95c534b Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Wed, 5 Sep 2018 16:30:59 -0300 Subject: [PATCH 04/73] Avoid mongodb warning using useNewUrlParser --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 333efb314c..d057af3981 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -119,6 +119,7 @@ export class MongoStorageAdapter implements StorageAdapter { this._uri = uri; this._collectionPrefix = collectionPrefix; this._mongoOptions = mongoOptions; + this._mongoOptions.useNewUrlParser = true; // MaxTimeMS is not a global MongoDB client option, it is applied per operation. this._maxTimeMS = mongoOptions.maxTimeMS; From cce9bae7e3fc1ef1c1e1032fd8b34d50dd738017 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Wed, 12 Sep 2018 11:28:31 -0300 Subject: [PATCH 05/73] Add background true to MongoCollection --- .gitignore | 2 ++ lib/Adapters/Storage/Mongo/MongoCollection.js | 2 +- src/Adapters/Storage/Mongo/MongoCollection.js | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8f1edaabbf..37a3c5268d 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ node_modules # Folder created by FileSystemAdapter /files + +*.orig diff --git a/lib/Adapters/Storage/Mongo/MongoCollection.js b/lib/Adapters/Storage/Mongo/MongoCollection.js index 7e9c22c2b6..01a51e74f2 100644 --- a/lib/Adapters/Storage/Mongo/MongoCollection.js +++ b/lib/Adapters/Storage/Mongo/MongoCollection.js @@ -36,7 +36,7 @@ class MongoCollection { var index = {}; index[key] = '2d'; - return this._mongoCollection.createIndex(index) + return this._mongoCollection.createIndex(index, { background: true }) // Retry, but just once. .then(() => this._rawFind(query, { skip, limit, sort, keys, maxTimeMS, readPreference })); }); diff --git a/src/Adapters/Storage/Mongo/MongoCollection.js b/src/Adapters/Storage/Mongo/MongoCollection.js index 128395121b..245a03483a 100644 --- a/src/Adapters/Storage/Mongo/MongoCollection.js +++ b/src/Adapters/Storage/Mongo/MongoCollection.js @@ -33,7 +33,7 @@ export default class MongoCollection { var index = {}; index[key] = '2d'; - return this._mongoCollection.createIndex(index) + return this._mongoCollection.createIndex(index, {background: true}) // Retry, but just once. .then(() => this._rawFind(query, { skip, limit, sort, keys, maxTimeMS, readPreference })); }); From ed8b34762e6f3d87a28d95347cdde146e9642b91 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Wed, 26 Sep 2018 11:41:25 -0300 Subject: [PATCH 06/73] Better push performance --- src/Controllers/PushController.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index 8b645a3680..f58fb67ad6 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 { @@ -58,6 +59,8 @@ export class PushController { badgeUpdate = () => { // Build a real RestQuery so we can use it in RestWrite const restQuery = new RestQuery(config, master(config), '_Installation', updateWhere); + // change $exists for $ne null for better performance + if (restQuery.restWhere && restQuery.restWhere.deviceToken && restQuery.restWhere.deviceToken['$exists']) restQuery.restWhere.deviceToken = {$ne: null} return restQuery.buildRestWhere().then(() => { const write = new RestWrite(config, master(config), '_Installation', restQuery.restWhere, restUpdate); write.runOptions.many = true; @@ -70,7 +73,15 @@ export class PushController { return pushStatus.setInitial(body, where); }).then(() => { onPushStatusSaved(pushStatus.objectId); - return badgeUpdate(); + const promise = badgeUpdate(); + // add this to ignore badge update errors as default + if (!config.stopOnBadgeUpdateError) { + promise.catch(err => { + logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`) + logger.error(err) + }) + } + return promise }).then(() => { // Update audience lastUsed and timesUsed if (body.audience_id) { From ee51f58520982b5dcd996494318c0f527bf9ff9b Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Wed, 26 Sep 2018 12:09:08 -0300 Subject: [PATCH 07/73] Better push performance --- lib/Adapters/Storage/Mongo/MongoCollection.js | 2 +- .../Storage/Mongo/MongoStorageAdapter.js | 3 ++- lib/Controllers/PushController.js | 16 ++++++++++++++-- package-lock.json | 14 +++++++------- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/Adapters/Storage/Mongo/MongoCollection.js b/lib/Adapters/Storage/Mongo/MongoCollection.js index 2407f49262..d04ad9b414 100644 --- a/lib/Adapters/Storage/Mongo/MongoCollection.js +++ b/lib/Adapters/Storage/Mongo/MongoCollection.js @@ -110,4 +110,4 @@ class MongoCollection { } } exports.default = MongoCollection; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJtb25nb2RiIiwicmVxdWlyZSIsIkNvbGxlY3Rpb24iLCJNb25nb0NvbGxlY3Rpb24iLCJjb25zdHJ1Y3RvciIsIm1vbmdvQ29sbGVjdGlvbiIsIl9tb25nb0NvbGxlY3Rpb24iLCJmaW5kIiwicXVlcnkiLCJza2lwIiwibGltaXQiLCJzb3J0Iiwia2V5cyIsIm1heFRpbWVNUyIsInJlYWRQcmVmZXJlbmNlIiwiJHNjb3JlIiwic2NvcmUiLCIkbWV0YSIsIl9yYXdGaW5kIiwiY2F0Y2giLCJlcnJvciIsImNvZGUiLCJtZXNzYWdlIiwibWF0Y2giLCJrZXkiLCJpbmRleCIsImNyZWF0ZUluZGV4IiwidGhlbiIsImZpbmRPcGVyYXRpb24iLCJwcm9qZWN0IiwidG9BcnJheSIsImNvdW50IiwiY291bnRPcGVyYXRpb24iLCJkaXN0aW5jdCIsImZpZWxkIiwiYWdncmVnYXRlIiwicGlwZWxpbmUiLCJpbnNlcnRPbmUiLCJvYmplY3QiLCJ1cHNlcnRPbmUiLCJ1cGRhdGUiLCJ1cHNlcnQiLCJ1cGRhdGVPbmUiLCJ1cGRhdGVNYW55IiwiZGVsZXRlTWFueSIsIl9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZCIsImluZGV4UmVxdWVzdCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZW5zdXJlSW5kZXgiLCJ1bmlxdWUiLCJiYWNrZ3JvdW5kIiwic3BhcnNlIiwiZHJvcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxNQUFNQSxVQUFVQyxRQUFRLFNBQVIsQ0FBaEI7QUFDQSxNQUFNQyxhQUFhRixRQUFRRSxVQUEzQjs7QUFFZSxNQUFNQyxlQUFOLENBQXNCOztBQUduQ0MsY0FBWUMsZUFBWixFQUF3QztBQUN0QyxTQUFLQyxnQkFBTCxHQUF3QkQsZUFBeEI7QUFDRDs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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LFNBQU87QUFDTCxXQUFPLEtBQUtoRCxnQkFBTCxDQUFzQmdELElBQXRCLEVBQVA7QUFDRDtBQXhHa0M7a0JBQWhCbkQsZSIsImZpbGUiOiJNb25nb0NvbGxlY3Rpb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgQ29sbGVjdGlvbiA9IG1vbmdvZGIuQ29sbGVjdGlvbjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTW9uZ29Db2xsZWN0aW9uIHtcbiAgX21vbmdvQ29sbGVjdGlvbjpDb2xsZWN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKG1vbmdvQ29sbGVjdGlvbjpDb2xsZWN0aW9uKSB7XG4gICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uID0gbW9uZ29Db2xsZWN0aW9uO1xuICB9XG5cbiAgLy8gRG9lcyBhIGZpbmQgd2l0aCBcInNtYXJ0IGluZGV4aW5nXCIuXG4gIC8vIEN1cnJlbnRseSB0aGlzIGp1c3QgbWVhbnMsIGlmIGl0IG5lZWRzIGEgZ2VvaW5kZXggYW5kIHRoZXJlIGlzXG4gIC8vIG5vbmUsIHRoZW4gYnVpbGQgdGhlIGdlb2luZGV4LlxuICAvLyBUaGlzIGNvdWxkIGJlIGltcHJvdmVkIGEgbG90IGJ1dCBpdCdzIG5vdCBjbGVhciBpZiB0aGF0J3MgYSBnb29kXG4gIC8vIGlkZWEuIE9yIGV2ZW4gaWYgdGhpcyBiZWhhdmlvciBpcyBhIGdvb2QgaWRlYS5cbiAgZmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICAvLyBTdXBwb3J0IGZvciBGdWxsIFRleHQgU2VhcmNoIC0gJHRleHRcbiAgICBpZihrZXlzICYmIGtleXMuJHNjb3JlKSB7XG4gICAgICBkZWxldGUga2V5cy4kc2NvcmU7XG4gICAgICBrZXlzLnNjb3JlID0geyRtZXRhOiAndGV4dFNjb3JlJ307XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9yYXdGaW5kKHF1ZXJ5LCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvLyBDaGVjayBmb3IgXCJubyBnZW9pbmRleFwiIGVycm9yXG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9IDE3MDA3ICYmICFlcnJvci5tZXNzYWdlLm1hdGNoKC91bmFibGUgdG8gZmluZCBpbmRleCBmb3IgLmdlb05lYXIvKSkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZpZ3VyZSBvdXQgd2hhdCBrZXkgbmVlZHMgYW4gaW5kZXhcbiAgICAgICAgY29uc3Qga2V5ID0gZXJyb3IubWVzc2FnZS5tYXRjaCgvZmllbGQ9KFtBLVphLXpfMC05XSspIC8pWzFdO1xuICAgICAgICBpZiAoIWtleSkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluZGV4ID0ge307XG4gICAgICAgIGluZGV4W2tleV0gPSAnMmQnO1xuICAgICAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4KGluZGV4KVxuICAgICAgICAgIC8vIFJldHJ5LCBidXQganVzdCBvbmNlLlxuICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuX3Jhd0ZpbmQocXVlcnksIHsgc2tpcCwgbGltaXQsIHNvcnQsIGtleXMsIG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSkpO1xuICAgICAgfSk7XG4gIH1cblxuICBfcmF3RmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICBsZXQgZmluZE9wZXJhdGlvbiA9IHRoaXMuX21vbmdvQ29sbGVjdGlvblxuICAgICAgLmZpbmQocXVlcnksIHsgc2tpcCwgbGltaXQsIHNvcnQsIHJlYWRQcmVmZXJlbmNlIH0pXG5cbiAgICBpZiAoa2V5cykge1xuICAgICAgZmluZE9wZXJhdGlvbiA9IGZpbmRPcGVyYXRpb24ucHJvamVjdChrZXlzKTtcbiAgICB9XG5cbiAgICBpZiAobWF4VGltZU1TKSB7XG4gICAgICBmaW5kT3BlcmF0aW9uID0gZmluZE9wZXJhdGlvbi5tYXhUaW1lTVMobWF4VGltZU1TKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmluZE9wZXJhdGlvbi50b0FycmF5KCk7XG4gIH1cblxuICBjb3VudChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICBjb25zdCBjb3VudE9wZXJhdGlvbiA9IHRoaXMuX21vbmdvQ29sbGVjdGlvbi5jb3VudChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9KTtcblxuICAgIHJldHVybiBjb3VudE9wZXJhdGlvbjtcbiAgfVxuXG4gIGRpc3RpbmN0KGZpZWxkLCBxdWVyeSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uZGlzdGluY3QoZmllbGQsIHF1ZXJ5KTtcbiAgfVxuXG4gIGFnZ3JlZ2F0ZShwaXBlbGluZSwgeyBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0gPSB7fSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uYWdncmVnYXRlKHBpcGVsaW5lLCB7IG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSkudG9BcnJheSgpO1xuICB9XG5cbiAgaW5zZXJ0T25lKG9iamVjdCkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uaW5zZXJ0T25lKG9iamVjdCk7XG4gIH1cblxuICAvLyBBdG9taWNhbGx5IHVwZGF0ZXMgZGF0YSBpbiB0aGUgZGF0YWJhc2UgZm9yIGEgc2luZ2xlIChmaXJzdCkgb2JqZWN0IHRoYXQgbWF0Y2hlZCB0aGUgcXVlcnlcbiAgLy8gSWYgdGhlcmUgaXMgbm90aGluZyB0aGF0IG1hdGNoZXMgdGhlIHF1ZXJ5IC0gZG9lcyBpbnNlcnRcbiAgLy8gUG9zdGdyZXMgTm90ZTogYElOU0VSVCAuLi4gT04gQ09ORkxJQ1QgVVBEQVRFYCB0aGF0IGlzIGF2YWlsYWJsZSBzaW5jZSA5LjUuXG4gIHVwc2VydE9uZShxdWVyeSwgdXBkYXRlKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi51cGRhdGUocXVlcnksIHVwZGF0ZSwgeyB1cHNlcnQ6IHRydWUgfSlcbiAgfVxuXG4gIHVwZGF0ZU9uZShxdWVyeSwgdXBkYXRlKSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi51cGRhdGVPbmUocXVlcnksIHVwZGF0ZSk7XG4gIH1cblxuICB1cGRhdGVNYW55KHF1ZXJ5LCB1cGRhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLnVwZGF0ZU1hbnkocXVlcnksIHVwZGF0ZSk7XG4gIH1cblxuICBkZWxldGVNYW55KHF1ZXJ5KSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5kZWxldGVNYW55KHF1ZXJ5KTtcbiAgfVxuXG4gIF9lbnN1cmVTcGFyc2VVbmlxdWVJbmRleEluQmFja2dyb3VuZChpbmRleFJlcXVlc3QpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmVuc3VyZUluZGV4KGluZGV4UmVxdWVzdCwgeyB1bmlxdWU6IHRydWUsIGJhY2tncm91bmQ6IHRydWUsIHNwYXJzZTogdHJ1ZSB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZHJvcCgpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmRyb3AoKTtcbiAgfVxufVxuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJtb25nb2RiIiwicmVxdWlyZSIsIkNvbGxlY3Rpb24iLCJNb25nb0NvbGxlY3Rpb24iLCJjb25zdHJ1Y3RvciIsIm1vbmdvQ29sbGVjdGlvbiIsIl9tb25nb0NvbGxlY3Rpb24iLCJmaW5kIiwicXVlcnkiLCJza2lwIiwibGltaXQiLCJzb3J0Iiwia2V5cyIsIm1heFRpbWVNUyIsInJlYWRQcmVmZXJlbmNlIiwiJHNjb3JlIiwic2NvcmUiLCIkbWV0YSIsIl9yYXdGaW5kIiwiY2F0Y2giLCJlcnJvciIsImNvZGUiLCJtZXNzYWdlIiwibWF0Y2giLCJrZXkiLCJpbmRleCIsImNyZWF0ZUluZGV4IiwiYmFja2dyb3VuZCIsInRoZW4iLCJmaW5kT3BlcmF0aW9uIiwicHJvamVjdCIsInRvQXJyYXkiLCJjb3VudCIsImNvdW50T3BlcmF0aW9uIiwiZGlzdGluY3QiLCJmaWVsZCIsImFnZ3JlZ2F0ZSIsInBpcGVsaW5lIiwiaW5zZXJ0T25lIiwib2JqZWN0IiwidXBzZXJ0T25lIiwidXBkYXRlIiwidXBzZXJ0IiwidXBkYXRlT25lIiwidXBkYXRlTWFueSIsImRlbGV0ZU1hbnkiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJpbmRleFJlcXVlc3QiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsImVuc3VyZUluZGV4IiwidW5pcXVlIiwic3BhcnNlIiwiZHJvcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxNQUFNQSxVQUFVQyxRQUFRLFNBQVIsQ0FBaEI7QUFDQSxNQUFNQyxhQUFhRixRQUFRRSxVQUEzQjs7QUFFZSxNQUFNQyxlQUFOLENBQXNCOztBQUduQ0MsY0FBWUMsZUFBWixFQUF3QztBQUN0QyxTQUFLQyxnQkFBTCxHQUF3QkQsZUFBeEI7QUFDRDs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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RixPQU5EO0FBT0QsS0FSTSxDQUFQO0FBU0Q7O0FBRURLLFNBQU87QUFDTCxXQUFPLEtBQUtoRCxnQkFBTCxDQUFzQmdELElBQXRCLEVBQVA7QUFDRDtBQXhHa0M7a0JBQWhCbkQsZSIsImZpbGUiOiJNb25nb0NvbGxlY3Rpb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgQ29sbGVjdGlvbiA9IG1vbmdvZGIuQ29sbGVjdGlvbjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTW9uZ29Db2xsZWN0aW9uIHtcbiAgX21vbmdvQ29sbGVjdGlvbjpDb2xsZWN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKG1vbmdvQ29sbGVjdGlvbjpDb2xsZWN0aW9uKSB7XG4gICAgdGhpcy5fbW9uZ29Db2xsZWN0aW9uID0gbW9uZ29Db2xsZWN0aW9uO1xuICB9XG5cbiAgLy8gRG9lcyBhIGZpbmQgd2l0aCBcInNtYXJ0IGluZGV4aW5nXCIuXG4gIC8vIEN1cnJlbnRseSB0aGlzIGp1c3QgbWVhbnMsIGlmIGl0IG5lZWRzIGEgZ2VvaW5kZXggYW5kIHRoZXJlIGlzXG4gIC8vIG5vbmUsIHRoZW4gYnVpbGQgdGhlIGdlb2luZGV4LlxuICAvLyBUaGlzIGNvdWxkIGJlIGltcHJvdmVkIGEgbG90IGJ1dCBpdCdzIG5vdCBjbGVhciBpZiB0aGF0J3MgYSBnb29kXG4gIC8vIGlkZWEuIE9yIGV2ZW4gaWYgdGhpcyBiZWhhdmlvciBpcyBhIGdvb2QgaWRlYS5cbiAgZmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9ID0ge30pIHtcbiAgICAvLyBTdXBwb3J0IGZvciBGdWxsIFRleHQgU2VhcmNoIC0gJHRleHRcbiAgICBpZihrZXlzICYmIGtleXMuJHNjb3JlKSB7XG4gICAgICBkZWxldGUga2V5cy4kc2NvcmU7XG4gICAgICBrZXlzLnNjb3JlID0geyRtZXRhOiAndGV4dFNjb3JlJ307XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9yYXdGaW5kKHF1ZXJ5LCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvLyBDaGVjayBmb3IgXCJubyBnZW9pbmRleFwiIGVycm9yXG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9IDE3MDA3ICYmICFlcnJvci5tZXNzYWdlLm1hdGNoKC91bmFibGUgdG8gZmluZCBpbmRleCBmb3IgLmdlb05lYXIvKSkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZpZ3VyZSBvdXQgd2hhdCBrZXkgbmVlZHMgYW4gaW5kZXhcbiAgICAgICAgY29uc3Qga2V5ID0gZXJyb3IubWVzc2FnZS5tYXRjaCgvZmllbGQ9KFtBLVphLXpfMC05XSspIC8pWzFdO1xuICAgICAgICBpZiAoIWtleSkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluZGV4ID0ge307XG4gICAgICAgIGluZGV4W2tleV0gPSAnMmQnO1xuICAgICAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4KGluZGV4LCB7YmFja2dyb3VuZDogdHJ1ZX0pXG4gICAgICAgICAgLy8gUmV0cnksIGJ1dCBqdXN0IG9uY2UuXG4gICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fcmF3RmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9KSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIF9yYXdGaW5kKHF1ZXJ5LCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0gPSB7fSkge1xuICAgIGxldCBmaW5kT3BlcmF0aW9uID0gdGhpcy5fbW9uZ29Db2xsZWN0aW9uXG4gICAgICAuZmluZChxdWVyeSwgeyBza2lwLCBsaW1pdCwgc29ydCwgcmVhZFByZWZlcmVuY2UgfSlcblxuICAgIGlmIChrZXlzKSB7XG4gICAgICBmaW5kT3BlcmF0aW9uID0gZmluZE9wZXJhdGlvbi5wcm9qZWN0KGtleXMpO1xuICAgIH1cblxuICAgIGlmIChtYXhUaW1lTVMpIHtcbiAgICAgIGZpbmRPcGVyYXRpb24gPSBmaW5kT3BlcmF0aW9uLm1heFRpbWVNUyhtYXhUaW1lTVMpO1xuICAgIH1cblxuICAgIHJldHVybiBmaW5kT3BlcmF0aW9uLnRvQXJyYXkoKTtcbiAgfVxuXG4gIGNvdW50KHF1ZXJ5LCB7IHNraXAsIGxpbWl0LCBzb3J0LCBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0gPSB7fSkge1xuICAgIGNvbnN0IGNvdW50T3BlcmF0aW9uID0gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmNvdW50KHF1ZXJ5LCB7IHNraXAsIGxpbWl0LCBzb3J0LCBtYXhUaW1lTVMsIHJlYWRQcmVmZXJlbmNlIH0pO1xuXG4gICAgcmV0dXJuIGNvdW50T3BlcmF0aW9uO1xuICB9XG5cbiAgZGlzdGluY3QoZmllbGQsIHF1ZXJ5KSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5kaXN0aW5jdChmaWVsZCwgcXVlcnkpO1xuICB9XG5cbiAgYWdncmVnYXRlKHBpcGVsaW5lLCB7IG1heFRpbWVNUywgcmVhZFByZWZlcmVuY2UgfSA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5hZ2dyZWdhdGUocGlwZWxpbmUsIHsgbWF4VGltZU1TLCByZWFkUHJlZmVyZW5jZSB9KS50b0FycmF5KCk7XG4gIH1cblxuICBpbnNlcnRPbmUob2JqZWN0KSB7XG4gICAgcmV0dXJuIHRoaXMuX21vbmdvQ29sbGVjdGlvbi5pbnNlcnRPbmUob2JqZWN0KTtcbiAgfVxuXG4gIC8vIEF0b21pY2FsbHkgdXBkYXRlcyBkYXRhIGluIHRoZSBkYXRhYmFzZSBmb3IgYSBzaW5nbGUgKGZpcnN0KSBvYmplY3QgdGhhdCBtYXRjaGVkIHRoZSBxdWVyeVxuICAvLyBJZiB0aGVyZSBpcyBub3RoaW5nIHRoYXQgbWF0Y2hlcyB0aGUgcXVlcnkgLSBkb2VzIGluc2VydFxuICAvLyBQb3N0Z3JlcyBOb3RlOiBgSU5TRVJUIC4uLiBPTiBDT05GTElDVCBVUERBVEVgIHRoYXQgaXMgYXZhaWxhYmxlIHNpbmNlIDkuNS5cbiAgdXBzZXJ0T25lKHF1ZXJ5LCB1cGRhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLnVwZGF0ZShxdWVyeSwgdXBkYXRlLCB7IHVwc2VydDogdHJ1ZSB9KVxuICB9XG5cbiAgdXBkYXRlT25lKHF1ZXJ5LCB1cGRhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLnVwZGF0ZU9uZShxdWVyeSwgdXBkYXRlKTtcbiAgfVxuXG4gIHVwZGF0ZU1hbnkocXVlcnksIHVwZGF0ZSkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24udXBkYXRlTWFueShxdWVyeSwgdXBkYXRlKTtcbiAgfVxuXG4gIGRlbGV0ZU1hbnkocXVlcnkpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9uZ29Db2xsZWN0aW9uLmRlbGV0ZU1hbnkocXVlcnkpO1xuICB9XG5cbiAgX2Vuc3VyZVNwYXJzZVVuaXF1ZUluZGV4SW5CYWNrZ3JvdW5kKGluZGV4UmVxdWVzdCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLl9tb25nb0NvbGxlY3Rpb24uZW5zdXJlSW5kZXgoaW5kZXhSZXF1ZXN0LCB7IHVuaXF1ZTogdHJ1ZSwgYmFja2dyb3VuZDogdHJ1ZSwgc3BhcnNlOiB0cnVlIH0sIChlcnJvcikgPT4ge1xuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBkcm9wKCkge1xuICAgIHJldHVybiB0aGlzLl9tb25nb0NvbGxlY3Rpb24uZHJvcCgpO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js index dbd8421b3c..a1a20c35c1 100644 --- a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -127,6 +127,7 @@ class MongoStorageAdapter { this._uri = uri; this._collectionPrefix = collectionPrefix; this._mongoOptions = mongoOptions; + this._mongoOptions.useNewUrlParser = true; // MaxTimeMS is not a global MongoDB client option, it is applied per operation. this._maxTimeMS = mongoOptions.maxTimeMS; @@ -769,4 +770,4 @@ class MongoStorageAdapter { exports.MongoStorageAdapter = MongoStorageAdapter; exports.default = MongoStorageAdapter; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsibW9uZ29kYiIsInJlcXVpcmUiLCJNb25nb0NsaWVudCIsIlJlYWRQcmVmZXJlbmNlIiwiTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSIsInN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMiLCJtb25nb0FkYXB0ZXIiLCJjb25uZWN0IiwidGhlbiIsImRhdGFiYXNlIiwiY29sbGVjdGlvbnMiLCJmaWx0ZXIiLCJjb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwibWF0Y2giLCJjb2xsZWN0aW9uTmFtZSIsImluZGV4T2YiLCJfY29sbGVjdGlvblByZWZpeCIsImNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEiLCJzY2hlbWEiLCJmaWVsZHMiLCJfcnBlcm0iLCJfd3Blcm0iLCJjbGFzc05hbWUiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vbmdvT2JqZWN0IiwiX2lkIiwib2JqZWN0SWQiLCJ1cGRhdGVkQXQiLCJjcmVhdGVkQXQiLCJfbWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJmaWVsZE5hbWUiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJjbGFzc19wZXJtaXNzaW9ucyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJNb25nb1N0b3JhZ2VBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJ1cmkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsImNvbGxlY3Rpb25QcmVmaXgiLCJtb25nb09wdGlvbnMiLCJfdXJpIiwiX21vbmdvT3B0aW9ucyIsIl9tYXhUaW1lTVMiLCJtYXhUaW1lTVMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiY29ubmVjdGlvblByb21pc2UiLCJlbmNvZGVkVXJpIiwiY2xpZW50Iiwib3B0aW9ucyIsInMiLCJkYiIsImRiTmFtZSIsIm9uIiwiY2F0Y2giLCJlcnIiLCJQcm9taXNlIiwicmVqZWN0IiwiaGFuZGxlRXJyb3IiLCJlcnJvciIsImNvZGUiLCJsb2dnZXIiLCJoYW5kbGVTaHV0ZG93biIsImNsb3NlIiwiX2FkYXB0aXZlQ29sbGVjdGlvbiIsIm5hbWUiLCJyYXdDb2xsZWN0aW9uIiwiTW9uZ29Db2xsZWN0aW9uIiwiX3NjaGVtYUNvbGxlY3Rpb24iLCJjbGFzc0V4aXN0cyIsImxpc3RDb2xsZWN0aW9ucyIsInRvQXJyYXkiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2NoZW1hQ29sbGVjdGlvbiIsInVwZGF0ZVNjaGVtYSIsIiRzZXQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJyZXNvbHZlIiwiX2lkXyIsImRlbGV0ZVByb21pc2VzIiwiaW5zZXJ0ZWRJbmRleGVzIiwiZm9yRWFjaCIsImZpZWxkIiwiX19vcCIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1FVRVJZIiwicHJvbWlzZSIsImRyb3BJbmRleCIsInB1c2giLCJrZXkiLCJoYXNPd25Qcm9wZXJ0eSIsImluc2VydFByb21pc2UiLCJjcmVhdGVJbmRleGVzIiwiYWxsIiwic2V0SW5kZXhlc0Zyb21Nb25nbyIsImdldEluZGV4ZXMiLCJyZWR1Y2UiLCJvYmoiLCJpbmRleCIsIl9mdHMiLCJfZnRzeCIsIndlaWdodHMiLCJjcmVhdGVDbGFzcyIsImluc2VydFNjaGVtYSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJ0eXBlIiwiY3JlYXRlSW5kZXhlc0lmTmVlZGVkIiwiZGVsZXRlQ2xhc3MiLCJkcm9wIiwibWVzc2FnZSIsImZpbmRBbmREZWxldGVTY2hlbWEiLCJkZWxldGVBbGxDbGFzc2VzIiwiZmFzdCIsIm1hcCIsInJlbW92ZSIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJtb25nb0Zvcm1hdE5hbWVzIiwiY29sbGVjdGlvblVwZGF0ZSIsInNjaGVtYVVwZGF0ZSIsInVwZGF0ZU1hbnkiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hc0NvbGxlY3Rpb24iLCJfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEiLCJnZXRDbGFzcyIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0IiwiaW5zZXJ0T25lIiwiRFVQTElDQVRFX1ZBTFVFIiwidW5kZXJseWluZ0Vycm9yIiwibWF0Y2hlcyIsIkFycmF5IiwiaXNBcnJheSIsInVzZXJJbmZvIiwiZHVwbGljYXRlZF9maWVsZCIsImRlbGV0ZU9iamVjdHNCeVF1ZXJ5IiwicXVlcnkiLCJtb25nb1doZXJlIiwiZGVsZXRlTWFueSIsInJlc3VsdCIsIm4iLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cGRhdGUiLCJtb25nb1VwZGF0ZSIsImZpbmRPbmVBbmRVcGRhdGUiLCJfbW9uZ29Db2xsZWN0aW9uIiwiZmluZEFuZE1vZGlmeSIsIm5ldyIsInZhbHVlIiwidXBzZXJ0T25lT2JqZWN0IiwidXBzZXJ0T25lIiwiZmluZCIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJyZWFkUHJlZmVyZW5jZSIsIm1vbmdvU29ydCIsIl8iLCJtYXBLZXlzIiwibW9uZ29LZXlzIiwibWVtbyIsIl9wYXJzZVJlYWRQcmVmZXJlbmNlIiwiY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZCIsIm9iamVjdHMiLCJlbnN1cmVVbmlxdWVuZXNzIiwiaW5kZXhDcmVhdGlvblJlcXVlc3QiLCJtb25nb0ZpZWxkTmFtZXMiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJfcmF3RmluZCIsImNvdW50IiwiZGlzdGluY3QiLCJpc1BvaW50ZXJGaWVsZCIsInN1YnN0cmluZyIsImFnZ3JlZ2F0ZSIsInBpcGVsaW5lIiwic3RhZ2UiLCIkZ3JvdXAiLCJfcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3MiLCIkbWF0Y2giLCJfcGFyc2VBZ2dyZWdhdGVBcmdzIiwiJHByb2plY3QiLCJfcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyIsInJlc3VsdHMiLCJzcGxpdCIsImlzRW1wdHkiLCJyZXR1cm5WYWx1ZSIsInRhcmdldENsYXNzIiwiX2NvbnZlcnRUb0RhdGUiLCJEYXRlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJjcmVhdGVJbmRleCIsImJhY2tncm91bmQiLCIkdGV4dCIsImluZGV4TmFtZSIsInRleHRJbmRleCIsImRyb3BBbGxJbmRleGVzIiwiZHJvcEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsImNsYXNzZXMiLCJwcm9taXNlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFLQTs7QUFJQTs7QUFTQTs7OztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7OztBQUxBOztBQUVBOzs7QUFLQTtBQUNBLE1BQU1BLFVBQVVDLFFBQVEsU0FBUixDQUFoQjtBQUNBLE1BQU1DLGNBQWNGLFFBQVFFLFdBQTVCO0FBQ0EsTUFBTUMsaUJBQWlCSCxRQUFRRyxjQUEvQjs7QUFFQSxNQUFNQyw0QkFBNEIsU0FBbEM7O0FBRUEsTUFBTUMsK0JBQStCQyxnQkFBZ0I7QUFDbkQsU0FBT0EsYUFBYUMsT0FBYixHQUNKQyxJQURJLENBQ0MsTUFBTUYsYUFBYUcsUUFBYixDQUFzQkMsV0FBdEIsRUFEUCxFQUVKRixJQUZJLENBRUNFLGVBQWU7QUFDbkIsV0FBT0EsWUFBWUMsTUFBWixDQUFtQkMsY0FBYztBQUN0QyxVQUFJQSxXQUFXQyxTQUFYLENBQXFCQyxLQUFyQixDQUEyQixZQUEzQixDQUFKLEVBQThDO0FBQzVDLGVBQU8sS0FB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TCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRURvQyxZQUFVNUUsU0FBVixFQUE2QnVGLEtBQTdCLEVBQXlDO0FBQ3ZDLFdBQU8sS0FBS3RDLG1CQUFMLENBQXlCakQsU0FBekIsRUFDSmYsSUFESSxDQUNDSSxjQUFjQSxXQUFXb0osZ0JBQVgsQ0FBNEI3RCxTQUE1QixDQUFzQ1csS0FBdEMsQ0FEZixFQUVKaEQsS0FGSSxDQUVFQyxPQUFPLEtBQUtHLFdBQUwsQ0FBaUJILEdBQWpCLENBRlQsQ0FBUDtBQUdEOztBQUVEd0osaUJBQWVoTSxTQUFmLEVBQWtDO0FBQ2hDLFdBQU8sS0FBS2lELG1CQUFMLENBQXlCakQsU0FBekIsRUFDSmYsSUFESSxDQUNDSSxjQUFjQSxXQUFXb0osZ0JBQVgsQ0FBNEJ3RCxXQUE1QixFQURmLEVBRUoxSixLQUZJLENBRUVDLE9BQU8sS0FBS0csV0FBTCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRUQwSiw0QkFBd0M7QUFDdEMsV0FBTyxLQUFLcEYsYUFBTCxHQUNKN0gsSUFESSxDQUNFa04sT0FBRCxJQUFhO0FBQ2pCLFlBQU1DLFdBQVdELFFBQVE3RixHQUFSLENBQWExRyxNQUFELElBQVk7QUFDdkMsZUFBTyxLQUFLdUYsbUJBQUwsQ0FBeUJ2RixPQUFPSSxTQUFoQyxDQUFQO0FBQ0QsT0FGZ0IsQ0FBakI7QUFHQSxhQUFPeUMsUUFBUXlDLEdBQVIsQ0FBWWtILFFBQVosQ0FBUDtBQUNELEtBTkksRUFPSjdKLEtBUEksQ0FPRUMsT0FBTyxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQVBULENBQVA7QUFRRDtBQXZ0QndEOztRQUE5Q3JCLG1CLEdBQUFBLG1CO2tCQTB0QkVBLG1CIiwiZmlsZSI6Ik1vbmdvU3RvcmFnZUFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuaW1wb3J0IE1vbmdvQ29sbGVjdGlvbiAgICAgICBmcm9tICcuL01vbmdvQ29sbGVjdGlvbic7XG5pbXBvcnQgTW9uZ29TY2hlbWFDb2xsZWN0aW9uIGZyb20gJy4vTW9uZ29TY2hlbWFDb2xsZWN0aW9uJztcbmltcG9ydCB7IFN0b3JhZ2VBZGFwdGVyIH0gICAgZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHR5cGUgeyBTY2hlbWFUeXBlLFxuICBRdWVyeVR5cGUsXG4gIFN0b3JhZ2VDbGFzcyxcbiAgUXVlcnlPcHRpb25zIH0gZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHtcbiAgcGFyc2UgYXMgcGFyc2VVcmwsXG4gIGZvcm1hdCBhcyBmb3JtYXRVcmwsXG59IGZyb20gJy4uLy4uLy4uL3ZlbmRvci9tb25nb2RiVXJsJztcbmltcG9ydCB7XG4gIHBhcnNlT2JqZWN0VG9Nb25nb09iamVjdEZvckNyZWF0ZSxcbiAgbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0LFxuICB0cmFuc2Zvcm1LZXksXG4gIHRyYW5zZm9ybVdoZXJlLFxuICB0cmFuc2Zvcm1VcGRhdGUsXG4gIHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcsXG59IGZyb20gJy4vTW9uZ29UcmFuc2Zvcm0nO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgUGFyc2UgICAgICAgICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgXyAgICAgICAgICAgICAgICAgICAgIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgZGVmYXVsdHMgICAgICAgICAgICAgIGZyb20gJy4uLy4uLy4uL2RlZmF1bHRzJztcbmltcG9ydCBsb2dnZXIgICAgICAgICAgICAgICAgZnJvbSAnLi4vLi4vLi4vbG9nZ2VyJztcblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5jb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgTW9uZ29DbGllbnQgPSBtb25nb2RiLk1vbmdvQ2xpZW50O1xuY29uc3QgUmVhZFByZWZlcmVuY2UgPSBtb25nb2RiLlJlYWRQcmVmZXJlbmNlO1xuXG5jb25zdCBNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lID0gJ19TQ0hFTUEnO1xuXG5jb25zdCBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zID0gbW9uZ29BZGFwdGVyID0+IHtcbiAgcmV0dXJuIG1vbmdvQWRhcHRlci5jb25uZWN0KClcbiAgICAudGhlbigoKSA9PiBtb25nb0FkYXB0ZXIuZGF0YWJhc2UuY29sbGVjdGlvbnMoKSlcbiAgICAudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbnMuZmlsdGVyKGNvbGxlY3Rpb24gPT4ge1xuICAgICAgICBpZiAoY29sbGVjdGlvbi5uYW1lc3BhY2UubWF0Y2goL1xcLnN5c3RlbVxcLi8pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IElmIHlvdSBoYXZlIG9uZSBhcHAgd2l0aCBhIGNvbGxlY3Rpb24gcHJlZml4IHRoYXQgaGFwcGVucyB0byBiZSBhIHByZWZpeCBvZiBhbm90aGVyXG4gICAgICAgIC8vIGFwcHMgcHJlZml4LCB0aGlzIHdpbGwgZ28gdmVyeSB2ZXJ5IGJhZGx5LiBXZSBzaG91bGQgZml4IHRoYXQgc29tZWhvdy5cbiAgICAgICAgcmV0dXJuIChjb2xsZWN0aW9uLmNvbGxlY3Rpb25OYW1lLmluZGV4T2YobW9uZ29BZGFwdGVyLl9jb2xsZWN0aW9uUHJlZml4KSA9PSAwKTtcbiAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5jb25zdCBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hID0gKHsuLi5zY2hlbWF9KSA9PiB7XG4gIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9ycGVybTtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3dwZXJtO1xuXG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgLy8gTGVnYWN5IG1vbmdvIGFkYXB0ZXIga25vd3MgYWJvdXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBwYXNzd29yZCBhbmQgX2hhc2hlZF9wYXNzd29yZC5cbiAgICAvLyBGdXR1cmUgZGF0YWJhc2UgYWRhcHRlcnMgd2lsbCBvbmx5IGtub3cgYWJvdXQgX2hhc2hlZF9wYXNzd29yZC5cbiAgICAvLyBOb3RlOiBQYXJzZSBTZXJ2ZXIgd2lsbCBicmluZyBiYWNrIHBhc3N3b3JkIHdpdGggaW5qZWN0RGVmYXVsdFNjaGVtYSwgc28gd2UgZG9uJ3QgbmVlZFxuICAgIC8vIHRvIGFkZCBfaGFzaGVkX3Bhc3N3b3JkIGJhY2sgZXZlci5cbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkO1xuICB9XG5cbiAgcmV0dXJuIHNjaGVtYTtcbn1cblxuLy8gUmV0dXJucyB7IGNvZGUsIGVycm9yIH0gaWYgaW52YWxpZCwgb3IgeyByZXN1bHQgfSwgYW4gb2JqZWN0XG4vLyBzdWl0YWJsZSBmb3IgaW5zZXJ0aW5nIGludG8gX1NDSEVNQSBjb2xsZWN0aW9uLCBvdGhlcndpc2UuXG5jb25zdCBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWVBbmRDTFAgPSAoZmllbGRzLCBjbGFzc05hbWUsIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucywgaW5kZXhlcykgPT4ge1xuICBjb25zdCBtb25nb09iamVjdCA9IHtcbiAgICBfaWQ6IGNsYXNzTmFtZSxcbiAgICBvYmplY3RJZDogJ3N0cmluZycsXG4gICAgdXBkYXRlZEF0OiAnc3RyaW5nJyxcbiAgICBjcmVhdGVkQXQ6ICdzdHJpbmcnLFxuICAgIF9tZXRhZGF0YTogdW5kZWZpbmVkLFxuICB9O1xuXG4gIGZvciAoY29uc3QgZmllbGROYW1lIGluIGZpZWxkcykge1xuICAgIG1vbmdvT2JqZWN0W2ZpZWxkTmFtZV0gPSBNb25nb1NjaGVtYUNvbGxlY3Rpb24ucGFyc2VGaWVsZFR5cGVUb01vbmdvRmllbGRUeXBlKGZpZWxkc1tmaWVsZE5hbWVdKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgY2xhc3NMZXZlbFBlcm1pc3Npb25zICE9PSAndW5kZWZpbmVkJykge1xuICAgIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSA9IG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSB8fCB7fTtcbiAgICBpZiAoIWNsYXNzTGV2ZWxQZXJtaXNzaW9ucykge1xuICAgICAgZGVsZXRlIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YS5jbGFzc19wZXJtaXNzaW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zID0gY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgIH1cbiAgfVxuXG4gIGlmIChpbmRleGVzICYmIHR5cGVvZiBpbmRleGVzID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyhpbmRleGVzKS5sZW5ndGggPiAwKSB7XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhID0gbW9uZ29PYmplY3QuX21ldGFkYXRhIHx8IHt9O1xuICAgIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YS5pbmRleGVzID0gaW5kZXhlcztcbiAgfVxuXG4gIGlmICghbW9uZ29PYmplY3QuX21ldGFkYXRhKSB7IC8vIGNsZWFudXAgdGhlIHVudXNlZCBfbWV0YWRhdGFcbiAgICBkZWxldGUgbW9uZ29PYmplY3QuX21ldGFkYXRhO1xuICB9XG5cbiAgcmV0dXJuIG1vbmdvT2JqZWN0O1xufVxuXG5cbmV4cG9ydCBjbGFzcyBNb25nb1N0b3JhZ2VBZGFwdGVyIGltcGxlbWVudHMgU3RvcmFnZUFkYXB0ZXIge1xuICAvLyBQcml2YXRlXG4gIF91cmk6IHN0cmluZztcbiAgX2NvbGxlY3Rpb25QcmVmaXg6IHN0cmluZztcbiAgX21vbmdvT3B0aW9uczogT2JqZWN0O1xuICAvLyBQdWJsaWNcbiAgY29ubmVjdGlvblByb21pc2U6IFByb21pc2U8YW55PjtcbiAgZGF0YWJhc2U6IGFueTtcbiAgY2xpZW50OiBNb25nb0NsaWVudDtcbiAgX21heFRpbWVNUzogP251bWJlcjtcbiAgY2FuU29ydE9uSm9pblRhYmxlczogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcih7XG4gICAgdXJpID0gZGVmYXVsdHMuRGVmYXVsdE1vbmdvVVJJLFxuICAgIGNvbGxlY3Rpb25QcmVmaXggPSAnJyxcbiAgICBtb25nb09wdGlvbnMgPSB7fSxcbiAgfTogYW55KSB7XG4gICAgdGhpcy5fdXJpID0gdXJpO1xuICAgIHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggPSBjb2xsZWN0aW9uUHJlZml4O1xuICAgIHRoaXMuX21vbmdvT3B0aW9ucyA9IG1vbmdvT3B0aW9ucztcblxuICAgIC8vIE1heFRpbWVNUyBpcyBub3QgYSBnbG9iYWwgTW9uZ29EQiBjbGllbnQgb3B0aW9uLCBpdCBpcyBhcHBsaWVkIHBlciBvcGVyYXRpb24uXG4gICAgdGhpcy5fbWF4VGltZU1TID0gbW9uZ29PcHRpb25zLm1heFRpbWVNUztcbiAgICB0aGlzLmNhblNvcnRPbkpvaW5UYWJsZXMgPSB0cnVlO1xuICAgIGRlbGV0ZSBtb25nb09wdGlvbnMubWF4VGltZU1TO1xuICB9XG5cbiAgY29ubmVjdCgpIHtcbiAgICBpZiAodGhpcy5jb25uZWN0aW9uUHJvbWlzZSkge1xuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgfVxuXG4gICAgLy8gcGFyc2luZyBhbmQgcmUtZm9ybWF0dGluZyBjYXVzZXMgdGhlIGF1dGggdmFsdWUgKGlmIHRoZXJlKSB0byBnZXQgVVJJXG4gICAgLy8gZW5jb2RlZFxuICAgIGNvbnN0IGVuY29kZWRVcmkgPSBmb3JtYXRVcmwocGFyc2VVcmwodGhpcy5fdXJpKSk7XG5cbiAgICB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlID0gTW9uZ29DbGllbnQuY29ubmVjdChlbmNvZGVkVXJpLCB0aGlzLl9tb25nb09wdGlvbnMpLnRoZW4oY2xpZW50ID0+IHtcbiAgICAgIC8vIFN0YXJ0aW5nIG1vbmdvREIgMy4wLCB0aGUgTW9uZ29DbGllbnQuY29ubmVjdCBkb24ndCByZXR1cm4gYSBEQiBhbnltb3JlIGJ1dCBhIGNsaWVudFxuICAgICAgLy8gRm9ydHVuYXRlbHksIHdlIGNhbiBnZXQgYmFjayB0aGUgb3B0aW9ucyBhbmQgdXNlIHRoZW0gdG8gc2VsZWN0IHRoZSBwcm9wZXIgREIuXG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbW9uZ29kYi9ub2RlLW1vbmdvZGItbmF0aXZlL2Jsb2IvMmMzNWQ3NmYwODU3NDIyNWI4ZGIwMmQ3YmVmNjg3MTIzZTZiYjAxOC9saWIvbW9uZ29fY2xpZW50LmpzI0w4ODVcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSBjbGllbnQucy5vcHRpb25zO1xuICAgICAgY29uc3QgZGF0YWJhc2UgPSBjbGllbnQuZGIob3B0aW9ucy5kYk5hbWUpO1xuICAgICAgaWYgKCFkYXRhYmFzZSkge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZGF0YWJhc2Uub24oJ2Vycm9yJywgKCkgPT4ge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIH0pO1xuICAgICAgZGF0YWJhc2Uub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jbGllbnQgPSBjbGllbnQ7XG4gICAgICB0aGlzLmRhdGFiYXNlID0gZGF0YWJhc2U7XG4gICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgZGVsZXRlIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICB9XG5cbiAgaGFuZGxlRXJyb3I8VD4oZXJyb3I6ID8oRXJyb3IgfCBQYXJzZS5FcnJvcikpOiBQcm9taXNlPFQ+IHtcbiAgICBpZiAoZXJyb3IgJiYgZXJyb3IuY29kZSA9PT0gMTMpIHsgLy8gVW5hdXRob3JpemVkIGVycm9yXG4gICAgICBkZWxldGUgdGhpcy5jbGllbnQ7XG4gICAgICBkZWxldGUgdGhpcy5kYXRhYmFzZTtcbiAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgbG9nZ2VyLmVycm9yKCdSZWNlaXZlZCB1bmF1dGhvcml6ZWQgZXJyb3InLCB7IGVycm9yOiBlcnJvciB9KTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBoYW5kbGVTaHV0ZG93bigpIHtcbiAgICBpZiAoIXRoaXMuY2xpZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2xpZW50LmNsb3NlKGZhbHNlKTtcbiAgfVxuXG4gIF9hZGFwdGl2ZUNvbGxlY3Rpb24obmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdCgpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmRhdGFiYXNlLmNvbGxlY3Rpb24odGhpcy5fY29sbGVjdGlvblByZWZpeCArIG5hbWUpKVxuICAgICAgLnRoZW4ocmF3Q29sbGVjdGlvbiA9PiBuZXcgTW9uZ29Db2xsZWN0aW9uKHJhd0NvbGxlY3Rpb24pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgX3NjaGVtYUNvbGxlY3Rpb24oKTogUHJvbWlzZTxNb25nb1NjaGVtYUNvbGxlY3Rpb24+IHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KClcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lKSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gbmV3IE1vbmdvU2NoZW1hQ29sbGVjdGlvbihjb2xsZWN0aW9uKSk7XG4gIH1cblxuICBjbGFzc0V4aXN0cyhuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5kYXRhYmFzZS5saXN0Q29sbGVjdGlvbnMoeyBuYW1lOiB0aGlzLl9jb2xsZWN0aW9uUHJlZml4ICsgbmFtZSB9KS50b0FycmF5KCk7XG4gICAgfSkudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbnMubGVuZ3RoID4gMDtcbiAgICB9KS5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWU6IHN0cmluZywgQ0xQczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgJHNldDogeyAnX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zJzogQ0xQcyB9XG4gICAgICB9KSkuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWU6IHN0cmluZywgc3VibWl0dGVkSW5kZXhlczogYW55LCBleGlzdGluZ0luZGV4ZXM6IGFueSA9IHt9LCBmaWVsZHM6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChzdWJtaXR0ZWRJbmRleGVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKGV4aXN0aW5nSW5kZXhlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICBleGlzdGluZ0luZGV4ZXMgPSB7IF9pZF86IHsgX2lkOiAxfSB9O1xuICAgIH1cbiAgICBjb25zdCBkZWxldGVQcm9taXNlcyA9IFtdO1xuICAgIGNvbnN0IGluc2VydGVkSW5kZXhlcyA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEluZGV4ZXMpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb25zdCBmaWVsZCA9IHN1Ym1pdHRlZEluZGV4ZXNbbmFtZV07XG4gICAgICBpZiAoZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW5kZXggJHtuYW1lfSBleGlzdHMsIGNhbm5vdCB1cGRhdGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4aXN0aW5nSW5kZXhlc1tuYW1lXSAmJiBmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgYEluZGV4ICR7bmFtZX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBkZWxldGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuZHJvcEluZGV4KGNsYXNzTmFtZSwgbmFtZSk7XG4gICAgICAgIGRlbGV0ZVByb21pc2VzLnB1c2gocHJvbWlzZSk7XG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0luZGV4ZXNbbmFtZV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBPYmplY3Qua2V5cyhmaWVsZCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgIGlmICghZmllbGRzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgRmllbGQgJHtrZXl9IGRvZXMgbm90IGV4aXN0LCBjYW5ub3QgYWRkIGluZGV4LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGV4aXN0aW5nSW5kZXhlc1tuYW1lXSA9IGZpZWxkO1xuICAgICAgICBpbnNlcnRlZEluZGV4ZXMucHVzaCh7XG4gICAgICAgICAga2V5OiBmaWVsZCxcbiAgICAgICAgICBuYW1lLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBsZXQgaW5zZXJ0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIGlmIChpbnNlcnRlZEluZGV4ZXMubGVuZ3RoID4gMCkge1xuICAgICAgaW5zZXJ0UHJvbWlzZSA9IHRoaXMuY3JlYXRlSW5kZXhlcyhjbGFzc05hbWUsIGluc2VydGVkSW5kZXhlcyk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLmFsbChkZWxldGVQcm9taXNlcylcbiAgICAgIC50aGVuKCgpID0+IGluc2VydFByb21pc2UpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuaW5kZXhlcyc6ICBleGlzdGluZ0luZGV4ZXMgfVxuICAgICAgfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBzZXRJbmRleGVzRnJvbU1vbmdvKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0SW5kZXhlcyhjbGFzc05hbWUpLnRoZW4oKGluZGV4ZXMpID0+IHtcbiAgICAgIGluZGV4ZXMgPSBpbmRleGVzLnJlZHVjZSgob2JqLCBpbmRleCkgPT4ge1xuICAgICAgICBpZiAoaW5kZXgua2V5Ll9mdHMpIHtcbiAgICAgICAgICBkZWxldGUgaW5kZXgua2V5Ll9mdHM7XG4gICAgICAgICAgZGVsZXRlIGluZGV4LmtleS5fZnRzeDtcbiAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIGluZGV4LndlaWdodHMpIHtcbiAgICAgICAgICAgIGluZGV4LmtleVtmaWVsZF0gPSAndGV4dCc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG9ialtpbmRleC5uYW1lXSA9IGluZGV4LmtleTtcbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgIH0sIHt9KTtcbiAgICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuaW5kZXhlcyc6IGluZGV4ZXMgfVxuICAgICAgICB9KSk7XG4gICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKVxuICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgLy8gSWdub3JlIGlmIGNvbGxlY3Rpb24gbm90IGZvdW5kXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb09iamVjdCA9IG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZUFuZENMUChzY2hlbWEuZmllbGRzLCBjbGFzc05hbWUsIHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMsIHNjaGVtYS5pbmRleGVzKTtcbiAgICBtb25nb09iamVjdC5faWQgPSBjbGFzc05hbWU7XG4gICAgcmV0dXJuIHRoaXMuc2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQoY2xhc3NOYW1lLCBzY2hlbWEuaW5kZXhlcywge30sIHNjaGVtYS5maWVsZHMpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uaW5zZXJ0U2NoZW1hKG1vbmdvT2JqZWN0KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGFkZEZpZWxkSWZOb3RFeGlzdHMoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uYWRkRmllbGRJZk5vdEV4aXN0cyhjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSkpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmNyZWF0ZUluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBEcm9wcyBhIGNvbGxlY3Rpb24uIFJlc29sdmVzIHdpdGggdHJ1ZSBpZiBpdCB3YXMgYSBQYXJzZSBTY2hlbWEgKGVnLiBfVXNlciwgQ3VzdG9tLCBldGMuKVxuICAvLyBhbmQgcmVzb2x2ZXMgd2l0aCBmYWxzZSBpZiBpdCB3YXNuJ3QgKGVnLiBhIGpvaW4gdGFibGUpLiBSZWplY3RzIGlmIGRlbGV0aW9uIHdhcyBpbXBvc3NpYmxlLlxuICBkZWxldGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmRyb3AoKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAvLyAnbnMgbm90IGZvdW5kJyBtZWFucyBjb2xsZWN0aW9uIHdhcyBhbHJlYWR5IGdvbmUuIElnbm9yZSBkZWxldGlvbiBhdHRlbXB0LlxuICAgICAgICBpZiAoZXJyb3IubWVzc2FnZSA9PSAnbnMgbm90IGZvdW5kJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgLy8gV2UndmUgZHJvcHBlZCB0aGUgY29sbGVjdGlvbiwgbm93IHJlbW92ZSB0aGUgX1NDSEVNQSBkb2N1bWVudFxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLmZpbmRBbmREZWxldGVTY2hlbWEoY2xhc3NOYW1lKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRlbGV0ZUFsbENsYXNzZXMoZmFzdDogYm9vbGVhbikge1xuICAgIHJldHVybiBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zKHRoaXMpXG4gICAgICAudGhlbihjb2xsZWN0aW9ucyA9PiBQcm9taXNlLmFsbChjb2xsZWN0aW9ucy5tYXAoY29sbGVjdGlvbiA9PiBmYXN0ID8gY29sbGVjdGlvbi5yZW1vdmUoe30pIDogY29sbGVjdGlvbi5kcm9wKCkpKSk7XG4gIH1cblxuICAvLyBSZW1vdmUgdGhlIGNvbHVtbiBhbmQgYWxsIHRoZSBkYXRhLiBGb3IgUmVsYXRpb25zLCB0aGUgX0pvaW4gY29sbGVjdGlvbiBpcyBoYW5kbGVkXG4gIC8vIHNwZWNpYWxseSwgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBkZWxldGUgX0pvaW4gY29sdW1ucy4gSXQgc2hvdWxkLCBob3dldmVyLCBpbmRpY2F0ZVxuICAvLyB0aGF0IHRoZSByZWxhdGlvbiBmaWVsZHMgZG9lcyBub3QgZXhpc3QgYW55bW9yZS4gSW4gbW9uZ28sIHRoaXMgbWVhbnMgcmVtb3ZpbmcgaXQgZnJvbVxuICAvLyB0aGUgX1NDSEVNQSBjb2xsZWN0aW9uLiAgVGhlcmUgc2hvdWxkIGJlIG5vIGFjdHVhbCBkYXRhIGluIHRoZSBjb2xsZWN0aW9uIHVuZGVyIHRoZSBzYW1lIG5hbWVcbiAgLy8gYXMgdGhlIHJlbGF0aW9uIGNvbHVtbiwgc28gaXQncyBmaW5lIHRvIGF0dGVtcHQgdG8gZGVsZXRlIGl0LiBJZiB0aGUgZmllbGRzIGxpc3RlZCB0byBiZVxuICAvLyBkZWxldGVkIGRvIG5vdCBleGlzdCwgdGhpcyBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIHN1Y2Nlc3NmdWxseSBhbnl3YXlzLiBDaGVja2luZyBmb3JcbiAgLy8gYXR0ZW1wdHMgdG8gZGVsZXRlIG5vbi1leGlzdGVudCBmaWVsZHMgaXMgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIFBhcnNlIFNlcnZlci5cblxuICAvLyBQb2ludGVyIGZpZWxkIG5hbWVzIGFyZSBwYXNzZWQgZm9yIGxlZ2FjeSByZWFzb25zOiB0aGUgb3JpZ2luYWwgbW9uZ29cbiAgLy8gZm9ybWF0IHN0b3JlZCBwb2ludGVyIGZpZWxkIG5hbWVzIGRpZmZlcmVudGx5IGluIHRoZSBkYXRhYmFzZSwgYW5kIHRoZXJlZm9yZVxuICAvLyBuZWVkZWQgdG8ga25vdyB0aGUgdHlwZSBvZiB0aGUgZmllbGQgYmVmb3JlIGl0IGNvdWxkIGRlbGV0ZSBpdC4gRnV0dXJlIGRhdGFiYXNlXG4gIC8vIGFkYXB0ZXJzIHNob3VsZCBpZ25vcmUgdGhlIHBvaW50ZXJGaWVsZE5hbWVzIGFyZ3VtZW50LiBBbGwgdGhlIGZpZWxkIG5hbWVzIGFyZSBpblxuICAvLyBmaWVsZE5hbWVzLCB0aGV5IHNob3cgdXAgYWRkaXRpb25hbGx5IGluIHRoZSBwb2ludGVyRmllbGROYW1lcyBkYXRhYmFzZSBmb3IgdXNlXG4gIC8vIGJ5IHRoZSBtb25nbyBhZGFwdGVyLCB3aGljaCBkZWFscyB3aXRoIHRoZSBsZWdhY3kgbW9uZ28gZm9ybWF0LlxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gaXMgbm90IG9ibGlnYXRlZCB0byBkZWxldGUgZmllbGRzIGF0b21pY2FsbHkuIEl0IGlzIGdpdmVuIHRoZSBmaWVsZFxuICAvLyBuYW1lcyBpbiBhIGxpc3Qgc28gdGhhdCBkYXRhYmFzZXMgdGhhdCBhcmUgY2FwYWJsZSBvZiBkZWxldGluZyBmaWVsZHMgYXRvbWljYWxseVxuICAvLyBtYXkgZG8gc28uXG5cbiAgLy8gUmV0dXJucyBhIFByb21pc2UuXG4gIGRlbGV0ZUZpZWxkcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBmaWVsZE5hbWVzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IG1vbmdvRm9ybWF0TmFtZXMgPSBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuIGBfcF8ke2ZpZWxkTmFtZX1gXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZmllbGROYW1lO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGNvbnN0IGNvbGxlY3Rpb25VcGRhdGUgPSB7ICckdW5zZXQnIDoge30gfTtcbiAgICBtb25nb0Zvcm1hdE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb2xsZWN0aW9uVXBkYXRlWyckdW5zZXQnXVtuYW1lXSA9IG51bGw7XG4gICAgfSk7XG5cbiAgICBjb25zdCBzY2hlbWFVcGRhdGUgPSB7ICckdW5zZXQnIDoge30gfTtcbiAgICBmaWVsZE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBzY2hlbWFVcGRhdGVbJyR1bnNldCddW25hbWVdID0gbnVsbDtcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLnVwZGF0ZU1hbnkoe30sIGNvbGxlY3Rpb25VcGRhdGUpKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHNjaGVtYVVwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBSZXR1cm4gYSBwcm9taXNlIGZvciBhbGwgc2NoZW1hcyBrbm93biB0byB0aGlzIGFkYXB0ZXIsIGluIFBhcnNlIGZvcm1hdC4gSW4gY2FzZSB0aGVcbiAgLy8gc2NoZW1hcyBjYW5ub3QgYmUgcmV0cmlldmVkLCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMuIFJlcXVpcmVtZW50cyBmb3IgdGhlXG4gIC8vIHJlamVjdGlvbiByZWFzb24gYXJlIFRCRC5cbiAgZ2V0QWxsQ2xhc3NlcygpOiBQcm9taXNlPFN0b3JhZ2VDbGFzc1tdPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKS50aGVuKHNjaGVtYXNDb2xsZWN0aW9uID0+IHNjaGVtYXNDb2xsZWN0aW9uLl9mZXRjaEFsbFNjaGVtYXNGcm9tX1NDSEVNQSgpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgdGhlIHNjaGVtYSB3aXRoIHRoZSBnaXZlbiBuYW1lLCBpbiBQYXJzZSBmb3JtYXQuIElmXG4gIC8vIHRoaXMgYWRhcHRlciBkb2Vzbid0IGtub3cgYWJvdXQgdGhlIHNjaGVtYSwgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMgd2l0aFxuICAvLyB1bmRlZmluZWQgYXMgdGhlIHJlYXNvbi5cbiAgZ2V0Q2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFN0b3JhZ2VDbGFzcz4ge1xuICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgIC50aGVuKHNjaGVtYXNDb2xsZWN0aW9uID0+IHNjaGVtYXNDb2xsZWN0aW9uLl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BKGNsYXNzTmFtZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBUT0RPOiBBcyB5ZXQgbm90IHBhcnRpY3VsYXJseSB3ZWxsIHNwZWNpZmllZC4gQ3JlYXRlcyBhbiBvYmplY3QuIE1heWJlIHNob3VsZG4ndCBldmVuIG5lZWQgdGhlIHNjaGVtYSxcbiAgLy8gYW5kIHNob3VsZCBpbmZlciBmcm9tIHRoZSB0eXBlLiBPciBtYXliZSBkb2VzIG5lZWQgdGhlIHNjaGVtYSBmb3IgdmFsaWRhdGlvbnMuIE9yIG1heWJlIG5lZWRzXG4gIC8vIHRoZSBzY2hlbWEgb25seSBmb3IgdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQuIFdlJ2xsIGZpZ3VyZSB0aGF0IG91dCBsYXRlci5cbiAgY3JlYXRlT2JqZWN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIG9iamVjdDogYW55KSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvT2JqZWN0ID0gcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlKGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmluc2VydE9uZShtb25nb09iamVjdCkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTEwMDApIHsgLy8gRHVwbGljYXRlIHZhbHVlXG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnKTtcbiAgICAgICAgICBlcnIudW5kZXJseWluZ0Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgaWYgKGVycm9yLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBlcnJvci5tZXNzYWdlLm1hdGNoKC9pbmRleDpbXFxzYS16QS1aMC05X1xcLVxcLl0rXFwkPyhbYS16QS1aXy1dKylfMS8pO1xuICAgICAgICAgICAgaWYgKG1hdGNoZXMgJiYgQXJyYXkuaXNBcnJheShtYXRjaGVzKSkge1xuICAgICAgICAgICAgICBlcnIudXNlckluZm8gPSB7IGR1cGxpY2F0ZWRfZmllbGQ6IG1hdGNoZXNbMV0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgLy8gSWYgbm8gb2JqZWN0cyBtYXRjaCwgcmVqZWN0IHdpdGggT0JKRUNUX05PVF9GT1VORC4gSWYgb2JqZWN0cyBhcmUgZm91bmQgYW5kIGRlbGV0ZWQsIHJlc29sdmUgd2l0aCB1bmRlZmluZWQuXG4gIC8vIElmIHRoZXJlIGlzIHNvbWUgb3RoZXIgZXJyb3IsIHJlamVjdCB3aXRoIElOVEVSTkFMX1NFUlZFUl9FUlJPUi5cbiAgZGVsZXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4ge1xuICAgICAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZGVsZXRlTWFueShtb25nb1doZXJlKVxuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKVxuICAgICAgLnRoZW4oKHsgcmVzdWx0IH0pID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdC5uID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdPYmplY3Qgbm90IGZvdW5kLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0sICgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0RhdGFiYXNlIGFkYXB0ZXIgZXJyb3InKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgdXBkYXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29VcGRhdGUgPSB0cmFuc2Zvcm1VcGRhdGUoY2xhc3NOYW1lLCB1cGRhdGUsIHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29XaGVyZSA9IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24udXBkYXRlTWFueShtb25nb1doZXJlLCBtb25nb1VwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBBdG9taWNhbGx5IGZpbmRzIGFuZCB1cGRhdGVzIGFuIG9iamVjdCBiYXNlZCBvbiBxdWVyeS5cbiAgLy8gUmV0dXJuIHZhbHVlIG5vdCBjdXJyZW50bHkgd2VsbCBzcGVjaWZpZWQuXG4gIGZpbmRPbmVBbmRVcGRhdGUoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29VcGRhdGUgPSB0cmFuc2Zvcm1VcGRhdGUoY2xhc3NOYW1lLCB1cGRhdGUsIHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29XaGVyZSA9IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5maW5kQW5kTW9kaWZ5KG1vbmdvV2hlcmUsIFtdLCBtb25nb1VwZGF0ZSwgeyBuZXc6IHRydWUgfSkpXG4gICAgICAudGhlbihyZXN1bHQgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgcmVzdWx0LnZhbHVlLCBzY2hlbWEpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDExMDAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBIb3BlZnVsbHkgd2UgY2FuIGdldCByaWQgb2YgdGhpcy4gSXQncyBvbmx5IHVzZWQgZm9yIGNvbmZpZyBhbmQgaG9va3MuXG4gIHVwc2VydE9uZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB1cGRhdGU6IGFueSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi51cHNlcnRPbmUobW9uZ29XaGVyZSwgbW9uZ29VcGRhdGUpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gRXhlY3V0ZXMgYSBmaW5kLiBBY2NlcHRzOiBjbGFzc05hbWUsIHF1ZXJ5IGluIFBhcnNlIGZvcm1hdCwgYW5kIHsgc2tpcCwgbGltaXQsIHNvcnQgfS5cbiAgZmluZChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCByZWFkUHJlZmVyZW5jZSB9OiBRdWVyeU9wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1NvcnQgPSBfLm1hcEtleXMoc29ydCwgKHZhbHVlLCBmaWVsZE5hbWUpID0+IHRyYW5zZm9ybUtleShjbGFzc05hbWUsIGZpZWxkTmFtZSwgc2NoZW1hKSk7XG4gICAgY29uc3QgbW9uZ29LZXlzID0gXy5yZWR1Y2Uoa2V5cywgKG1lbW8sIGtleSkgPT4ge1xuICAgICAgbWVtb1t0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBrZXksIHNjaGVtYSldID0gMTtcbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH0sIHt9KTtcblxuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5maW5kKG1vbmdvV2hlcmUsIHtcbiAgICAgICAgc2tpcCxcbiAgICAgICAgbGltaXQsXG4gICAgICAgIHNvcnQ6IG1vbmdvU29ydCxcbiAgICAgICAga2V5czogbW9uZ29LZXlzLFxuICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICB9KSlcbiAgICAgIC50aGVuKG9iamVjdHMgPT4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSB1bmlxdWUgaW5kZXguIFVuaXF1ZSBpbmRleGVzIG9uIG51bGxhYmxlIGZpZWxkcyBhcmUgbm90IGFsbG93ZWQuIFNpbmNlIHdlIGRvbid0XG4gIC8vIGN1cnJlbnRseSBrbm93IHdoaWNoIGZpZWxkcyBhcmUgbnVsbGFibGUgYW5kIHdoaWNoIGFyZW4ndCwgd2UgaWdub3JlIHRoYXQgY3JpdGVyaWEuXG4gIC8vIEFzIHN1Y2gsIHdlIHNob3VsZG4ndCBleHBvc2UgdGhpcyBmdW5jdGlvbiB0byB1c2VycyBvZiBwYXJzZSB1bnRpbCB3ZSBoYXZlIGFuIG91dC1vZi1iYW5kXG4gIC8vIFdheSBvZiBkZXRlcm1pbmluZyBpZiBhIGZpZWxkIGlzIG51bGxhYmxlLiBVbmRlZmluZWQgZG9lc24ndCBjb3VudCBhZ2FpbnN0IHVuaXF1ZW5lc3MsXG4gIC8vIHdoaWNoIGlzIHdoeSB3ZSB1c2Ugc3BhcnNlIGluZGV4ZXMuXG4gIGVuc3VyZVVuaXF1ZW5lc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgZmllbGROYW1lczogc3RyaW5nW10pIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgaW5kZXhDcmVhdGlvblJlcXVlc3QgPSB7fTtcbiAgICBjb25zdCBtb25nb0ZpZWxkTmFtZXMgPSBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT4gdHJhbnNmb3JtS2V5KGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpKTtcbiAgICBtb25nb0ZpZWxkTmFtZXMuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaW5kZXhDcmVhdGlvblJlcXVlc3RbZmllbGROYW1lXSA9IDE7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX2Vuc3VyZVNwYXJzZVVuaXF1ZUluZGV4SW5CYWNrZ3JvdW5kKGluZGV4Q3JlYXRpb25SZXF1ZXN0KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsICdUcmllZCB0byBlbnN1cmUgZmllbGQgdW5pcXVlbmVzcyBmb3IgYSBjbGFzcyB0aGF0IGFscmVhZHkgaGFzIGR1cGxpY2F0ZXMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVXNlZCBpbiB0ZXN0c1xuICBfcmF3RmluZChjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IFF1ZXJ5VHlwZSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKS50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5maW5kKHF1ZXJ5LCB7XG4gICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICB9KSkuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGNvdW50LlxuICBjb3VudChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCByZWFkUHJlZmVyZW5jZTogP3N0cmluZykge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICByZWFkUHJlZmVyZW5jZSA9IHRoaXMuX3BhcnNlUmVhZFByZWZlcmVuY2UocmVhZFByZWZlcmVuY2UpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmNvdW50KHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSksIHtcbiAgICAgICAgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMsXG4gICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkaXN0aW5jdChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCBmaWVsZE5hbWU6IHN0cmluZykge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBpc1BvaW50ZXJGaWVsZCA9IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1BvaW50ZXInO1xuICAgIGlmIChpc1BvaW50ZXJGaWVsZCkge1xuICAgICAgZmllbGROYW1lID0gYF9wXyR7ZmllbGROYW1lfWBcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uZGlzdGluY3QoZmllbGROYW1lLCB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpKSlcbiAgICAgIC50aGVuKG9iamVjdHMgPT4ge1xuICAgICAgICBvYmplY3RzID0gb2JqZWN0cy5maWx0ZXIoKG9iaikgPT4gb2JqICE9IG51bGwpO1xuICAgICAgICByZXR1cm4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZmllbGROYW1lLnN1YnN0cmluZygzKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nKHNjaGVtYSwgZmllbGQsIG9iamVjdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGFnZ3JlZ2F0ZShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnksIHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKSB7XG4gICAgbGV0IGlzUG9pbnRlckZpZWxkID0gZmFsc2U7XG4gICAgcGlwZWxpbmUgPSBwaXBlbGluZS5tYXAoKHN0YWdlKSA9PiB7XG4gICAgICBpZiAoc3RhZ2UuJGdyb3VwKSB7XG4gICAgICAgIHN0YWdlLiRncm91cCA9IHRoaXMuX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzKHNjaGVtYSwgc3RhZ2UuJGdyb3VwKTtcbiAgICAgICAgaWYgKHN0YWdlLiRncm91cC5faWQgJiYgKHR5cGVvZiBzdGFnZS4kZ3JvdXAuX2lkID09PSAnc3RyaW5nJykgJiYgc3RhZ2UuJGdyb3VwLl9pZC5pbmRleE9mKCckX3BfJykgPj0gMCkge1xuICAgICAgICAgIGlzUG9pbnRlckZpZWxkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRtYXRjaCkge1xuICAgICAgICBzdGFnZS4kbWF0Y2ggPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hLCBzdGFnZS4kbWF0Y2gpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRwcm9qZWN0KSB7XG4gICAgICAgIHN0YWdlLiRwcm9qZWN0ID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyhzY2hlbWEsIHN0YWdlLiRwcm9qZWN0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdGFnZTtcbiAgICB9KTtcbiAgICByZWFkUHJlZmVyZW5jZSA9IHRoaXMuX3BhcnNlUmVhZFByZWZlcmVuY2UocmVhZFByZWZlcmVuY2UpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmFnZ3JlZ2F0ZShwaXBlbGluZSwgeyByZWFkUHJlZmVyZW5jZSwgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMgfSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTYwMDYpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHJlc3VsdHMuZm9yRWFjaChyZXN1bHQgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQuaGFzT3duUHJvcGVydHkoJ19pZCcpKSB7XG4gICAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQgJiYgcmVzdWx0Ll9pZCkge1xuICAgICAgICAgICAgICByZXN1bHQuX2lkID0gcmVzdWx0Ll9pZC5zcGxpdCgnJCcpWzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdC5faWQgPT0gbnVsbCB8fCBfLmlzRW1wdHkocmVzdWx0Ll9pZCkpIHtcbiAgICAgICAgICAgICAgcmVzdWx0Ll9pZCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQub2JqZWN0SWQgPSByZXN1bHQuX2lkO1xuICAgICAgICAgICAgZGVsZXRlIHJlc3VsdC5faWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiBvYmplY3RzLm1hcChvYmplY3QgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCByZWN1cnNpdmVseSB0cmF2ZXJzZSB0aGUgcGlwZWxpbmUgYW5kIGNvbnZlcnQgYW55IFBvaW50ZXIgb3IgRGF0ZSBjb2x1bW5zLlxuICAvLyBJZiB3ZSBkZXRlY3QgYSBwb2ludGVyIGNvbHVtbiB3ZSB3aWxsIHJlbmFtZSB0aGUgY29sdW1uIGJlaW5nIHF1ZXJpZWQgZm9yIHRvIG1hdGNoIHRoZSBjb2x1bW5cbiAgLy8gaW4gdGhlIGRhdGFiYXNlLiBXZSBhbHNvIG1vZGlmeSB0aGUgdmFsdWUgdG8gd2hhdCB3ZSBleHBlY3QgdGhlIHZhbHVlIHRvIGJlIGluIHRoZSBkYXRhYmFzZVxuICAvLyBhcyB3ZWxsLlxuICAvLyBGb3IgZGF0ZXMsIHRoZSBkcml2ZXIgZXhwZWN0cyBhIERhdGUgb2JqZWN0LCBidXQgd2UgaGF2ZSBhIHN0cmluZyBjb21pbmcgaW4uIFNvIHdlJ2xsIGNvbnZlcnRcbiAgLy8gdGhlIHN0cmluZyB0byBhIERhdGUgc28gdGhlIGRyaXZlciBjYW4gcGVyZm9ybSB0aGUgbmVjZXNzYXJ5IGNvbXBhcmlzb24uXG4gIC8vXG4gIC8vIFRoZSBnb2FsIG9mIHRoaXMgbWV0aG9kIGlzIHRvIGxvb2sgZm9yIHRoZSBcImxlYXZlc1wiIG9mIHRoZSBwaXBlbGluZSBhbmQgZGV0ZXJtaW5lIGlmIGl0IG5lZWRzXG4gIC8vIHRvIGJlIGNvbnZlcnRlZC4gVGhlIHBpcGVsaW5lIGNhbiBoYXZlIGEgZmV3IGRpZmZlcmVudCBmb3Jtcy4gRm9yIG1vcmUgZGV0YWlscywgc2VlOlxuICAvLyAgICAgaHR0cHM6Ly9kb2NzLm1vbmdvZGIuY29tL21hbnVhbC9yZWZlcmVuY2Uvb3BlcmF0b3IvYWdncmVnYXRpb24vXG4gIC8vXG4gIC8vIElmIHRoZSBwaXBlbGluZSBpcyBhbiBhcnJheSwgaXQgbWVhbnMgd2UgYXJlIHByb2JhYmx5IHBhcnNpbmcgYW4gJyRhbmQnIG9yICckb3InIG9wZXJhdG9yLiBJblxuICAvLyB0aGF0IGNhc2Ugd2UgbmVlZCB0byBsb29wIHRocm91Z2ggYWxsIG9mIGl0J3MgY2hpbGRyZW4gdG8gZmluZCB0aGUgY29sdW1ucyBiZWluZyBvcGVyYXRlZCBvbi5cbiAgLy8gSWYgdGhlIHBpcGVsaW5lIGlzIGFuIG9iamVjdCwgdGhlbiB3ZSdsbCBsb29wIHRocm91Z2ggdGhlIGtleXMgY2hlY2tpbmcgdG8gc2VlIGlmIHRoZSBrZXkgbmFtZVxuICAvLyBtYXRjaGVzIG9uZSBvZiB0aGUgc2NoZW1hIGNvbHVtbnMuIElmIGl0IGRvZXMgbWF0Y2ggYSBjb2x1bW4gYW5kIHRoZSBjb2x1bW4gaXMgYSBQb2ludGVyIG9yXG4gIC8vIGEgRGF0ZSwgdGhlbiB3ZSdsbCBjb252ZXJ0IHRoZSB2YWx1ZSBhcyBkZXNjcmliZWQgYWJvdmUuXG4gIC8vXG4gIC8vIEFzIG11Y2ggYXMgSSBoYXRlIHJlY3Vyc2lvbi4uLnRoaXMgc2VlbWVkIGxpa2UgYSBnb29kIGZpdCBmb3IgaXQuIFdlJ3JlIGVzc2VudGlhbGx5IHRyYXZlcnNpbmdcbiAgLy8gZG93biBhIHRyZWUgdG8gZmluZCBhIFwibGVhZiBub2RlXCIgYW5kIGNoZWNraW5nIHRvIHNlZSBpZiBpdCBuZWVkcyB0byBiZSBjb252ZXJ0ZWQuXG4gIF9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnkpOiBhbnkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHBpcGVsaW5lKSkge1xuICAgICAgcmV0dXJuIHBpcGVsaW5lLm1hcCgodmFsdWUpID0+IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHZhbHVlKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBwaXBlbGluZVtmaWVsZF0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBQYXNzIG9iamVjdHMgZG93biB0byBNb25nb0RCLi4udGhpcyBpcyBtb3JlIHRoYW4gbGlrZWx5IGFuICRleGlzdHMgb3BlcmF0b3IuXG4gICAgICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IHBpcGVsaW5lW2ZpZWxkXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWVbYF9wXyR7ZmllbGR9YF0gPSBgJHtzY2hlbWEuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzc30kJHtwaXBlbGluZVtmaWVsZF19YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ0RhdGUnKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fY29udmVydFRvRGF0ZShwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2lkJ10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2NyZWF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfdXBkYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHBpcGVsaW5lO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgb25lIGFib3ZlLiBSYXRoZXIgdGhhbiB0cnlpbmcgdG8gY29tYmluZSB0aGVzZVxuICAvLyB0d28gZnVuY3Rpb25zIGFuZCBtYWtpbmcgdGhlIGNvZGUgZXZlbiBoYXJkZXIgdG8gdW5kZXJzdGFuZCwgSSBkZWNpZGVkIHRvIHNwbGl0IGl0IHVwLiBUaGVcbiAgLy8gZGlmZmVyZW5jZSB3aXRoIHRoaXMgZnVuY3Rpb24gaXMgd2UgYXJlIG5vdCB0cmFuc2Zvcm1pbmcgdGhlIHZhbHVlcywgb25seSB0aGUga2V5cyBvZiB0aGVcbiAgLy8gcGlwZWxpbmUuXG4gIF9wYXJzZUFnZ3JlZ2F0ZVByb2plY3RBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbYF9wXyR7ZmllbGR9YF0gPSBwaXBlbGluZVtmaWVsZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hLCBwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19pZCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19jcmVhdGVkX2F0J10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX3VwZGF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgdHdvIGFib3ZlLiBNb25nb0RCICRncm91cCBhZ2dyZWdhdGUgbG9va3MgbGlrZTpcbiAgLy8gICAgIHsgJGdyb3VwOiB7IF9pZDogPGV4cHJlc3Npb24+LCA8ZmllbGQxPjogeyA8YWNjdW11bGF0b3IxPiA6IDxleHByZXNzaW9uMT4gfSwgLi4uIH0gfVxuICAvLyBUaGUgPGV4cHJlc3Npb24+IGNvdWxkIGJlIGEgY29sdW1uIG5hbWUsIHByZWZpeGVkIHdpdGggdGhlICckJyBjaGFyYWN0ZXIuIFdlJ2xsIGxvb2sgZm9yXG4gIC8vIHRoZXNlIDxleHByZXNzaW9uPiBhbmQgY2hlY2sgdG8gc2VlIGlmIGl0IGlzIGEgJ1BvaW50ZXInIG9yIGlmIGl0J3Mgb25lIG9mIGNyZWF0ZWRBdCxcbiAgLy8gdXBkYXRlZEF0IG9yIG9iamVjdElkIGFuZCBjaGFuZ2UgaXQgYWNjb3JkaW5nbHkuXG4gIF9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSk6IGFueSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICByZXR1cm4gcGlwZWxpbmUubWFwKCh2YWx1ZSkgPT4gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCB2YWx1ZSkpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTtcbiAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCBwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgZmllbGQgPSBwaXBlbGluZS5zdWJzdHJpbmcoMSk7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgIHJldHVybiBgJF9wXyR7ZmllbGR9YDtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuICckX2NyZWF0ZWRfYXQnO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm4gJyRfdXBkYXRlZF9hdCc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwaXBlbGluZTtcbiAgfVxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBhdHRlbXB0IHRvIGNvbnZlcnQgdGhlIHByb3ZpZGVkIHZhbHVlIHRvIGEgRGF0ZSBvYmplY3QuIFNpbmNlIHRoaXMgaXMgcGFydFxuICAvLyBvZiBhbiBhZ2dyZWdhdGlvbiBwaXBlbGluZSwgdGhlIHZhbHVlIGNhbiBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgaXQgY2FuIGJlIGFub3RoZXIgb2JqZWN0IHdpdGhcbiAgLy8gYW4gb3BlcmF0b3IgaW4gaXQgKGxpa2UgJGd0LCAkbHQsIGV0YykuIEJlY2F1c2Ugb2YgdGhpcyBJIGZlbHQgaXQgd2FzIGVhc2llciB0byBtYWtlIHRoaXMgYVxuICAvLyByZWN1cnNpdmUgbWV0aG9kIHRvIHRyYXZlcnNlIGRvd24gdG8gdGhlIFwibGVhZiBub2RlXCIgd2hpY2ggaXMgZ29pbmcgdG8gYmUgdGhlIHN0cmluZy5cbiAgX2NvbnZlcnRUb0RhdGUodmFsdWU6IGFueSk6IGFueSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fVxuICAgIGZvciAoY29uc3QgZmllbGQgaW4gdmFsdWUpIHtcbiAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX2NvbnZlcnRUb0RhdGUodmFsdWVbZmllbGRdKVxuICAgIH1cbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cblxuICBfcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZTogP3N0cmluZyk6ID9zdHJpbmcge1xuICAgIHN3aXRjaCAocmVhZFByZWZlcmVuY2UpIHtcbiAgICBjYXNlICdQUklNQVJZJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1BSSU1BUllfUFJFRkVSUkVEJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWV9QUkVGRVJSRUQ7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdTRUNPTkRBUlknOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5TRUNPTkRBUlk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdTRUNPTkRBUllfUFJFRkVSUkVEJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuU0VDT05EQVJZX1BSRUZFUlJFRDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ05FQVJFU1QnOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5ORUFSRVNUO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSB1bmRlZmluZWQ6XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksICdOb3Qgc3VwcG9ydGVkIHJlYWQgcHJlZmVyZW5jZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgcGVyZm9ybUluaXRpYWxpemF0aW9uKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4KGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleDogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5jcmVhdGVJbmRleChpbmRleCwge2JhY2tncm91bmQ6IHRydWV9KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4ZXMoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4ZXM6IGFueSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uY3JlYXRlSW5kZXhlcyhpbmRleGVzLCB7YmFja2dyb3VuZDogdHJ1ZX0pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZywgdHlwZTogYW55KSB7XG4gICAgaWYgKHR5cGUgJiYgdHlwZS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgIGNvbnN0IGluZGV4ID0ge1xuICAgICAgICBbZmllbGROYW1lXTogJzJkc3BoZXJlJ1xuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUluZGV4KGNsYXNzTmFtZSwgaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBjcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogUXVlcnlUeXBlLCBzY2hlbWE6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvcihjb25zdCBmaWVsZE5hbWUgaW4gcXVlcnkpIHtcbiAgICAgIGlmICghcXVlcnlbZmllbGROYW1lXSB8fCAhcXVlcnlbZmllbGROYW1lXS4kdGV4dCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4aXN0aW5nSW5kZXhlcyA9IHNjaGVtYS5pbmRleGVzO1xuICAgICAgZm9yIChjb25zdCBrZXkgaW4gZXhpc3RpbmdJbmRleGVzKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gZXhpc3RpbmdJbmRleGVzW2tleV07XG4gICAgICAgIGlmIChpbmRleC5oYXNPd25Qcm9wZXJ0eShmaWVsZE5hbWUpKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBpbmRleE5hbWUgPSBgJHtmaWVsZE5hbWV9X3RleHRgO1xuICAgICAgY29uc3QgdGV4dEluZGV4ID0ge1xuICAgICAgICBbaW5kZXhOYW1lXTogeyBbZmllbGROYW1lXTogJ3RleHQnIH1cbiAgICAgIH07XG4gICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWUsIHRleHRJbmRleCwgZXhpc3RpbmdJbmRleGVzLCBzY2hlbWEuZmllbGRzKVxuICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDg1KSB7IC8vIEluZGV4IGV4aXN0IHdpdGggZGlmZmVyZW50IG9wdGlvbnNcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNGcm9tTW9uZ28oY2xhc3NOYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBnZXRJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5pbmRleGVzKCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wSW5kZXgoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmRyb3BJbmRleChpbmRleCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wQWxsSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uZHJvcEluZGV4ZXMoKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzKCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QWxsQ2xhc3NlcygpXG4gICAgICAudGhlbigoY2xhc3NlcykgPT4ge1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IGNsYXNzZXMubWFwKChzY2hlbWEpID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzRnJvbU1vbmdvKHNjaGVtYS5jbGFzc05hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTW9uZ29TdG9yYWdlQWRhcHRlcjtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsibW9uZ29kYiIsInJlcXVpcmUiLCJNb25nb0NsaWVudCIsIlJlYWRQcmVmZXJlbmNlIiwiTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSIsInN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMiLCJtb25nb0FkYXB0ZXIiLCJjb25uZWN0IiwidGhlbiIsImRhdGFiYXNlIiwiY29sbGVjdGlvbnMiLCJmaWx0ZXIiLCJjb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwibWF0Y2giLCJjb2xsZWN0aW9uTmFtZSIsImluZGV4T2YiLCJfY29sbGVjdGlvblByZWZpeCIsImNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEiLCJzY2hlbWEiLCJmaWVsZHMiLCJfcnBlcm0iLCJfd3Blcm0iLCJjbGFzc05hbWUiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vbmdvT2JqZWN0IiwiX2lkIiwib2JqZWN0SWQiLCJ1cGRhdGVkQXQiLCJjcmVhdGVkQXQiLCJfbWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJmaWVsZE5hbWUiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJjbGFzc19wZXJtaXNzaW9ucyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJNb25nb1N0b3JhZ2VBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJ1cmkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsImNvbGxlY3Rpb25QcmVmaXgiLCJtb25nb09wdGlvbnMiLCJfdXJpIiwiX21vbmdvT3B0aW9ucyIsInVzZU5ld1VybFBhcnNlciIsIl9tYXhUaW1lTVMiLCJtYXhUaW1lTVMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiY29ubmVjdGlvblByb21pc2UiLCJlbmNvZGVkVXJpIiwiY2xpZW50Iiwib3B0aW9ucyIsInMiLCJkYiIsImRiTmFtZSIsIm9uIiwiY2F0Y2giLCJlcnIiLCJQcm9taXNlIiwicmVqZWN0IiwiaGFuZGxlRXJyb3IiLCJlcnJvciIsImNvZGUiLCJsb2dnZXIiLCJoYW5kbGVTaHV0ZG93biIsImNsb3NlIiwiX2FkYXB0aXZlQ29sbGVjdGlvbiIsIm5hbWUiLCJyYXdDb2xsZWN0aW9uIiwiTW9uZ29Db2xsZWN0aW9uIiwiX3NjaGVtYUNvbGxlY3Rpb24iLCJjbGFzc0V4aXN0cyIsImxpc3RDb2xsZWN0aW9ucyIsInRvQXJyYXkiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2NoZW1hQ29sbGVjdGlvbiIsInVwZGF0ZVNjaGVtYSIsIiRzZXQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJyZXNvbHZlIiwiX2lkXyIsImRlbGV0ZVByb21pc2VzIiwiaW5zZXJ0ZWRJbmRleGVzIiwiZm9yRWFjaCIsImZpZWxkIiwiX19vcCIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1FVRVJZIiwicHJvbWlzZSIsImRyb3BJbmRleCIsInB1c2giLCJrZXkiLCJoYXNPd25Qcm9wZXJ0eSIsImluc2VydFByb21pc2UiLCJjcmVhdGVJbmRleGVzIiwiYWxsIiwic2V0SW5kZXhlc0Zyb21Nb25nbyIsImdldEluZGV4ZXMiLCJyZWR1Y2UiLCJvYmoiLCJpbmRleCIsIl9mdHMiLCJfZnRzeCIsIndlaWdodHMiLCJjcmVhdGVDbGFzcyIsImluc2VydFNjaGVtYSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJ0eXBlIiwiY3JlYXRlSW5kZXhlc0lmTmVlZGVkIiwiZGVsZXRlQ2xhc3MiLCJkcm9wIiwibWVzc2FnZSIsImZpbmRBbmREZWxldGVTY2hlbWEiLCJkZWxldGVBbGxDbGFzc2VzIiwiZmFzdCIsIm1hcCIsInJlbW92ZSIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJtb25nb0Zvcm1hdE5hbWVzIiwiY29sbGVjdGlvblVwZGF0ZSIsInNjaGVtYVVwZGF0ZSIsInVwZGF0ZU1hbnkiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hc0NvbGxlY3Rpb24iLCJfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEiLCJnZXRDbGFzcyIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0IiwiaW5zZXJ0T25lIiwiRFVQTElDQVRFX1ZBTFVFIiwidW5kZXJseWluZ0Vycm9yIiwibWF0Y2hlcyIsIkFycmF5IiwiaXNBcnJheSIsInVzZXJJbmZvIiwiZHVwbGljYXRlZF9maWVsZCIsImRlbGV0ZU9iamVjdHNCeVF1ZXJ5IiwicXVlcnkiLCJtb25nb1doZXJlIiwiZGVsZXRlTWFueSIsInJlc3VsdCIsIm4iLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cGRhdGUiLCJtb25nb1VwZGF0ZSIsImZpbmRPbmVBbmRVcGRhdGUiLCJfbW9uZ29Db2xsZWN0aW9uIiwiZmluZEFuZE1vZGlmeSIsIm5ldyIsInZhbHVlIiwidXBzZXJ0T25lT2JqZWN0IiwidXBzZXJ0T25lIiwiZmluZCIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJyZWFkUHJlZmVyZW5jZSIsIm1vbmdvU29ydCIsIl8iLCJtYXBLZXlzIiwibW9uZ29LZXlzIiwibWVtbyIsIl9wYXJzZVJlYWRQcmVmZXJlbmNlIiwiY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZCIsIm9iamVjdHMiLCJlbnN1cmVVbmlxdWVuZXNzIiwiaW5kZXhDcmVhdGlvblJlcXVlc3QiLCJtb25nb0ZpZWxkTmFtZXMiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJfcmF3RmluZCIsImNvdW50IiwiZGlzdGluY3QiLCJpc1BvaW50ZXJGaWVsZCIsInN1YnN0cmluZyIsImFnZ3JlZ2F0ZSIsInBpcGVsaW5lIiwic3RhZ2UiLCIkZ3JvdXAiLCJfcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3MiLCIkbWF0Y2giLCJfcGFyc2VBZ2dyZWdhdGVBcmdzIiwiJHByb2plY3QiLCJfcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyIsInJlc3VsdHMiLCJzcGxpdCIsImlzRW1wdHkiLCJyZXR1cm5WYWx1ZSIsInRhcmdldENsYXNzIiwiX2NvbnZlcnRUb0RhdGUiLCJEYXRlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJjcmVhdGVJbmRleCIsImJhY2tncm91bmQiLCIkdGV4dCIsImluZGV4TmFtZSIsInRleHRJbmRleCIsImRyb3BBbGxJbmRleGVzIiwiZHJvcEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsImNsYXNzZXMiLCJwcm9taXNlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFLQTs7QUFJQTs7QUFTQTs7OztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7OztBQUxBOztBQUVBOzs7QUFLQTtBQUNBLE1BQU1BLFVBQVVDLFFBQVEsU0FBUixDQUFoQjtBQUNBLE1BQU1DLGNBQWNGLFFBQVFFLFdBQTVCO0FBQ0EsTUFBTUMsaUJBQWlCSCxRQUFRRyxjQUEvQjs7QUFFQSxNQUFNQyw0QkFBNEIsU0FBbEM7O0FBRUEsTUFBTUMsK0JBQStCQyxnQkFBZ0I7QUFDbkQsU0FBT0EsYUFBYUMsT0FBYixHQUNKQyxJQURJLENBQ0MsTUFBTUYsYUFBYUcsUUFBYixDQUFzQkMsV0FBdEIsRUFEUCxFQUVKRixJQUZJLENBRUNFLGVBQWU7QUFDbkIsV0FBT0EsWUFBWUMsTUFBWixDQUFtQkMsY0FBYztBQUN0QyxVQUFJQSxXQUFXQyxTQUFYLENBQXFCQyxLQUFyQixDQUEyQixZQUEzQixDQUFKLEVB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SixnQkFBWCxDQUE0QnRJLE9BQTVCLEVBRGYsRUFFSm9DLEtBRkksQ0FFRUMsT0FBTyxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQUZULENBQVA7QUFHRDs7QUFFRG9DLFlBQVU3RSxTQUFWLEVBQTZCd0YsS0FBN0IsRUFBeUM7QUFDdkMsV0FBTyxLQUFLdEMsbUJBQUwsQ0FBeUJsRCxTQUF6QixFQUNKZixJQURJLENBQ0NJLGNBQWNBLFdBQVdxSixnQkFBWCxDQUE0QjdELFNBQTVCLENBQXNDVyxLQUF0QyxDQURmLEVBRUpoRCxLQUZJLENBRUVDLE9BQU8sS0FBS0csV0FBTCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRUR3SixpQkFBZWpNLFNBQWYsRUFBa0M7QUFDaEMsV0FBTyxLQUFLa0QsbUJBQUwsQ0FBeUJsRCxTQUF6QixFQUNKZixJQURJLENBQ0NJLGNBQWNBLFdBQVdxSixnQkFBWCxDQUE0QndELFdBQTVCLEVBRGYsRUFFSjFKLEtBRkksQ0FFRUMsT0FBTyxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQUZULENBQVA7QUFHRDs7QUFFRDBKLDRCQUF3QztBQUN0QyxXQUFPLEtBQUtwRixhQUFMLEdBQ0o5SCxJQURJLENBQ0VtTixPQUFELElBQWE7QUFDakIsWUFBTUMsV0FBV0QsUUFBUTdGLEdBQVIsQ0FBYTNHLE1BQUQsSUFBWTtBQUN2QyxlQUFPLEtBQUt3RixtQkFBTCxDQUF5QnhGLE9BQU9JLFNBQWhDLENBQVA7QUFDRCxPQUZnQixDQUFqQjtBQUdBLGFBQU8wQyxRQUFReUMsR0FBUixDQUFZa0gsUUFBWixDQUFQO0FBQ0QsS0FOSSxFQU9KN0osS0FQSSxDQU9FQyxPQUFPLEtBQUtHLFdBQUwsQ0FBaUJILEdBQWpCLENBUFQsQ0FBUDtBQVFEO0FBeHRCd0Q7O1FBQTlDdEIsbUIsR0FBQUEsbUI7a0JBMnRCRUEsbUIiLCJmaWxlIjoiTW9uZ29TdG9yYWdlQWRhcHRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG5pbXBvcnQgTW9uZ29Db2xsZWN0aW9uICAgICAgIGZyb20gJy4vTW9uZ29Db2xsZWN0aW9uJztcbmltcG9ydCBNb25nb1NjaGVtYUNvbGxlY3Rpb24gZnJvbSAnLi9Nb25nb1NjaGVtYUNvbGxlY3Rpb24nO1xuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSAgICBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgdHlwZSB7IFNjaGVtYVR5cGUsXG4gIFF1ZXJ5VHlwZSxcbiAgU3RvcmFnZUNsYXNzLFxuICBRdWVyeU9wdGlvbnMgfSBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQge1xuICBwYXJzZSBhcyBwYXJzZVVybCxcbiAgZm9ybWF0IGFzIGZvcm1hdFVybCxcbn0gZnJvbSAnLi4vLi4vLi4vdmVuZG9yL21vbmdvZGJVcmwnO1xuaW1wb3J0IHtcbiAgcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlLFxuICBtb25nb09iamVjdFRvUGFyc2VPYmplY3QsXG4gIHRyYW5zZm9ybUtleSxcbiAgdHJhbnNmb3JtV2hlcmUsXG4gIHRyYW5zZm9ybVVwZGF0ZSxcbiAgdHJhbnNmb3JtUG9pbnRlclN0cmluZyxcbn0gZnJvbSAnLi9Nb25nb1RyYW5zZm9ybSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBQYXJzZSAgICAgICAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBfICAgICAgICAgICAgICAgICAgICAgZnJvbSAnbG9kYXNoJztcbmltcG9ydCBkZWZhdWx0cyAgICAgICAgICAgICAgZnJvbSAnLi4vLi4vLi4vZGVmYXVsdHMnO1xuaW1wb3J0IGxvZ2dlciAgICAgICAgICAgICAgICBmcm9tICcuLi8uLi8uLi9sb2dnZXInO1xuXG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmNvbnN0IG1vbmdvZGIgPSByZXF1aXJlKCdtb25nb2RiJyk7XG5jb25zdCBNb25nb0NsaWVudCA9IG1vbmdvZGIuTW9uZ29DbGllbnQ7XG5jb25zdCBSZWFkUHJlZmVyZW5jZSA9IG1vbmdvZGIuUmVhZFByZWZlcmVuY2U7XG5cbmNvbnN0IE1vbmdvU2NoZW1hQ29sbGVjdGlvbk5hbWUgPSAnX1NDSEVNQSc7XG5cbmNvbnN0IHN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMgPSBtb25nb0FkYXB0ZXIgPT4ge1xuICByZXR1cm4gbW9uZ29BZGFwdGVyLmNvbm5lY3QoKVxuICAgIC50aGVuKCgpID0+IG1vbmdvQWRhcHRlci5kYXRhYmFzZS5jb2xsZWN0aW9ucygpKVxuICAgIC50aGVuKGNvbGxlY3Rpb25zID0+IHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9ucy5maWx0ZXIoY29sbGVjdGlvbiA9PiB7XG4gICAgICAgIGlmIChjb2xsZWN0aW9uLm5hbWVzcGFjZS5tYXRjaCgvXFwuc3lzdGVtXFwuLykpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogSWYgeW91IGhhdmUgb25lIGFwcCB3aXRoIGEgY29sbGVjdGlvbiBwcmVmaXggdGhhdCBoYXBwZW5zIHRvIGJlIGEgcHJlZml4IG9mIGFub3RoZXJcbiAgICAgICAgLy8gYXBwcyBwcmVmaXgsIHRoaXMgd2lsbCBnbyB2ZXJ5IHZlcnkgYmFkbHkuIFdlIHNob3VsZCBmaXggdGhhdCBzb21laG93LlxuICAgICAgICByZXR1cm4gKGNvbGxlY3Rpb24uY29sbGVjdGlvbk5hbWUuaW5kZXhPZihtb25nb0FkYXB0ZXIuX2NvbGxlY3Rpb25QcmVmaXgpID09IDApO1xuICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmNvbnN0IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEgPSAoey4uLnNjaGVtYX0pID0+IHtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3JwZXJtO1xuICBkZWxldGUgc2NoZW1hLmZpZWxkcy5fd3Blcm07XG5cbiAgaWYgKHNjaGVtYS5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICAvLyBMZWdhY3kgbW9uZ28gYWRhcHRlciBrbm93cyBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHBhc3N3b3JkIGFuZCBfaGFzaGVkX3Bhc3N3b3JkLlxuICAgIC8vIEZ1dHVyZSBkYXRhYmFzZSBhZGFwdGVycyB3aWxsIG9ubHkga25vdyBhYm91dCBfaGFzaGVkX3Bhc3N3b3JkLlxuICAgIC8vIE5vdGU6IFBhcnNlIFNlcnZlciB3aWxsIGJyaW5nIGJhY2sgcGFzc3dvcmQgd2l0aCBpbmplY3REZWZhdWx0U2NoZW1hLCBzbyB3ZSBkb24ndCBuZWVkXG4gICAgLy8gdG8gYWRkIF9oYXNoZWRfcGFzc3dvcmQgYmFjayBldmVyLlxuICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9oYXNoZWRfcGFzc3dvcmQ7XG4gIH1cblxuICByZXR1cm4gc2NoZW1hO1xufVxuXG4vLyBSZXR1cm5zIHsgY29kZSwgZXJyb3IgfSBpZiBpbnZhbGlkLCBvciB7IHJlc3VsdCB9LCBhbiBvYmplY3Rcbi8vIHN1aXRhYmxlIGZvciBpbnNlcnRpbmcgaW50byBfU0NIRU1BIGNvbGxlY3Rpb24sIG90aGVyd2lzZS5cbmNvbnN0IG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZUFuZENMUCA9IChmaWVsZHMsIGNsYXNzTmFtZSwgY2xhc3NMZXZlbFBlcm1pc3Npb25zLCBpbmRleGVzKSA9PiB7XG4gIGNvbnN0IG1vbmdvT2JqZWN0ID0ge1xuICAgIF9pZDogY2xhc3NOYW1lLFxuICAgIG9iamVjdElkOiAnc3RyaW5nJyxcbiAgICB1cGRhdGVkQXQ6ICdzdHJpbmcnLFxuICAgIGNyZWF0ZWRBdDogJ3N0cmluZycsXG4gICAgX21ldGFkYXRhOiB1bmRlZmluZWQsXG4gIH07XG5cbiAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gZmllbGRzKSB7XG4gICAgbW9uZ29PYmplY3RbZmllbGROYW1lXSA9IE1vbmdvU2NoZW1hQ29sbGVjdGlvbi5wYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUoZmllbGRzW2ZpZWxkTmFtZV0pO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjbGFzc0xldmVsUGVybWlzc2lvbnMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhID0gbW9uZ29PYmplY3QuX21ldGFkYXRhIHx8IHt9O1xuICAgIGlmICghY2xhc3NMZXZlbFBlcm1pc3Npb25zKSB7XG4gICAgICBkZWxldGUgbW9uZ29PYmplY3QuX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zO1xuICAgIH0gZWxzZSB7XG4gICAgICBtb25nb09iamVjdC5fbWV0YWRhdGEuY2xhc3NfcGVybWlzc2lvbnMgPSBjbGFzc0xldmVsUGVybWlzc2lvbnM7XG4gICAgfVxuICB9XG5cbiAgaWYgKGluZGV4ZXMgJiYgdHlwZW9mIGluZGV4ZXMgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKGluZGV4ZXMpLmxlbmd0aCA+IDApIHtcbiAgICBtb25nb09iamVjdC5fbWV0YWRhdGEgPSBtb25nb09iamVjdC5fbWV0YWRhdGEgfHwge307XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmluZGV4ZXMgPSBpbmRleGVzO1xuICB9XG5cbiAgaWYgKCFtb25nb09iamVjdC5fbWV0YWRhdGEpIHsgLy8gY2xlYW51cCB0aGUgdW51c2VkIF9tZXRhZGF0YVxuICAgIGRlbGV0ZSBtb25nb09iamVjdC5fbWV0YWRhdGE7XG4gIH1cblxuICByZXR1cm4gbW9uZ29PYmplY3Q7XG59XG5cblxuZXhwb3J0IGNsYXNzIE1vbmdvU3RvcmFnZUFkYXB0ZXIgaW1wbGVtZW50cyBTdG9yYWdlQWRhcHRlciB7XG4gIC8vIFByaXZhdGVcbiAgX3VyaTogc3RyaW5nO1xuICBfY29sbGVjdGlvblByZWZpeDogc3RyaW5nO1xuICBfbW9uZ29PcHRpb25zOiBPYmplY3Q7XG4gIC8vIFB1YmxpY1xuICBjb25uZWN0aW9uUHJvbWlzZTogUHJvbWlzZTxhbnk+O1xuICBkYXRhYmFzZTogYW55O1xuICBjbGllbnQ6IE1vbmdvQ2xpZW50O1xuICBfbWF4VGltZU1TOiA/bnVtYmVyO1xuICBjYW5Tb3J0T25Kb2luVGFibGVzOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHtcbiAgICB1cmkgPSBkZWZhdWx0cy5EZWZhdWx0TW9uZ29VUkksXG4gICAgY29sbGVjdGlvblByZWZpeCA9ICcnLFxuICAgIG1vbmdvT3B0aW9ucyA9IHt9LFxuICB9OiBhbnkpIHtcbiAgICB0aGlzLl91cmkgPSB1cmk7XG4gICAgdGhpcy5fY29sbGVjdGlvblByZWZpeCA9IGNvbGxlY3Rpb25QcmVmaXg7XG4gICAgdGhpcy5fbW9uZ29PcHRpb25zID0gbW9uZ29PcHRpb25zO1xuICAgIHRoaXMuX21vbmdvT3B0aW9ucy51c2VOZXdVcmxQYXJzZXIgPSB0cnVlO1xuXG4gICAgLy8gTWF4VGltZU1TIGlzIG5vdCBhIGdsb2JhbCBNb25nb0RCIGNsaWVudCBvcHRpb24sIGl0IGlzIGFwcGxpZWQgcGVyIG9wZXJhdGlvbi5cbiAgICB0aGlzLl9tYXhUaW1lTVMgPSBtb25nb09wdGlvbnMubWF4VGltZU1TO1xuICAgIHRoaXMuY2FuU29ydE9uSm9pblRhYmxlcyA9IHRydWU7XG4gICAgZGVsZXRlIG1vbmdvT3B0aW9ucy5tYXhUaW1lTVM7XG4gIH1cblxuICBjb25uZWN0KCkge1xuICAgIGlmICh0aGlzLmNvbm5lY3Rpb25Qcm9taXNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICB9XG5cbiAgICAvLyBwYXJzaW5nIGFuZCByZS1mb3JtYXR0aW5nIGNhdXNlcyB0aGUgYXV0aCB2YWx1ZSAoaWYgdGhlcmUpIHRvIGdldCBVUklcbiAgICAvLyBlbmNvZGVkXG4gICAgY29uc3QgZW5jb2RlZFVyaSA9IGZvcm1hdFVybChwYXJzZVVybCh0aGlzLl91cmkpKTtcblxuICAgIHRoaXMuY29ubmVjdGlvblByb21pc2UgPSBNb25nb0NsaWVudC5jb25uZWN0KGVuY29kZWRVcmksIHRoaXMuX21vbmdvT3B0aW9ucykudGhlbihjbGllbnQgPT4ge1xuICAgICAgLy8gU3RhcnRpbmcgbW9uZ29EQiAzLjAsIHRoZSBNb25nb0NsaWVudC5jb25uZWN0IGRvbid0IHJldHVybiBhIERCIGFueW1vcmUgYnV0IGEgY2xpZW50XG4gICAgICAvLyBGb3J0dW5hdGVseSwgd2UgY2FuIGdldCBiYWNrIHRoZSBvcHRpb25zIGFuZCB1c2UgdGhlbSB0byBzZWxlY3QgdGhlIHByb3BlciBEQi5cbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb25nb2RiL25vZGUtbW9uZ29kYi1uYXRpdmUvYmxvYi8yYzM1ZDc2ZjA4NTc0MjI1YjhkYjAyZDdiZWY2ODcxMjNlNmJiMDE4L2xpYi9tb25nb19jbGllbnQuanMjTDg4NVxuICAgICAgY29uc3Qgb3B0aW9ucyA9IGNsaWVudC5zLm9wdGlvbnM7XG4gICAgICBjb25zdCBkYXRhYmFzZSA9IGNsaWVudC5kYihvcHRpb25zLmRiTmFtZSk7XG4gICAgICBpZiAoIWRhdGFiYXNlKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBkYXRhYmFzZS5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgfSk7XG4gICAgICBkYXRhYmFzZS5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgfSk7XG4gICAgICB0aGlzLmNsaWVudCA9IGNsaWVudDtcbiAgICAgIHRoaXMuZGF0YWJhc2UgPSBkYXRhYmFzZTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gIH1cblxuICBoYW5kbGVFcnJvcjxUPihlcnJvcjogPyhFcnJvciB8IFBhcnNlLkVycm9yKSk6IFByb21pc2U8VD4ge1xuICAgIGlmIChlcnJvciAmJiBlcnJvci5jb2RlID09PSAxMykgeyAvLyBVbmF1dGhvcml6ZWQgZXJyb3JcbiAgICAgIGRlbGV0ZSB0aGlzLmNsaWVudDtcbiAgICAgIGRlbGV0ZSB0aGlzLmRhdGFiYXNlO1xuICAgICAgZGVsZXRlIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1JlY2VpdmVkIHVuYXV0aG9yaXplZCBlcnJvcicsIHsgZXJyb3I6IGVycm9yIH0pO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuXG4gIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGlmICghdGhpcy5jbGllbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jbGllbnQuY2xvc2UoZmFsc2UpO1xuICB9XG5cbiAgX2FkYXB0aXZlQ29sbGVjdGlvbihuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KClcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuZGF0YWJhc2UuY29sbGVjdGlvbih0aGlzLl9jb2xsZWN0aW9uUHJlZml4ICsgbmFtZSkpXG4gICAgICAudGhlbihyYXdDb2xsZWN0aW9uID0+IG5ldyBNb25nb0NvbGxlY3Rpb24ocmF3Q29sbGVjdGlvbikpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBfc2NoZW1hQ29sbGVjdGlvbigpOiBQcm9taXNlPE1vbmdvU2NoZW1hQ29sbGVjdGlvbj4ge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3QoKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKE1vbmdvU2NoZW1hQ29sbGVjdGlvbk5hbWUpKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBuZXcgTW9uZ29TY2hlbWFDb2xsZWN0aW9uKGNvbGxlY3Rpb24pKTtcbiAgfVxuXG4gIGNsYXNzRXhpc3RzKG5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3QoKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmRhdGFiYXNlLmxpc3RDb2xsZWN0aW9ucyh7IG5hbWU6IHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggKyBuYW1lIH0pLnRvQXJyYXkoKTtcbiAgICB9KS50aGVuKGNvbGxlY3Rpb25zID0+IHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9ucy5sZW5ndGggPiAwO1xuICAgIH0pLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgc2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKGNsYXNzTmFtZTogc3RyaW5nLCBDTFBzOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuY2xhc3NfcGVybWlzc2lvbnMnOiBDTFBzIH1cbiAgICAgIH0pKS5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KGNsYXNzTmFtZTogc3RyaW5nLCBzdWJtaXR0ZWRJbmRleGVzOiBhbnksIGV4aXN0aW5nSW5kZXhlczogYW55ID0ge30sIGZpZWxkczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHN1Ym1pdHRlZEluZGV4ZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICBpZiAoT2JqZWN0LmtleXMoZXhpc3RpbmdJbmRleGVzKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGV4aXN0aW5nSW5kZXhlcyA9IHsgX2lkXzogeyBfaWQ6IDF9IH07XG4gICAgfVxuICAgIGNvbnN0IGRlbGV0ZVByb21pc2VzID0gW107XG4gICAgY29uc3QgaW5zZXJ0ZWRJbmRleGVzID0gW107XG4gICAgT2JqZWN0LmtleXMoc3VibWl0dGVkSW5kZXhlcykuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkID0gc3VibWl0dGVkSW5kZXhlc1tuYW1lXTtcbiAgICAgIGlmIChleGlzdGluZ0luZGV4ZXNbbmFtZV0gJiYgZmllbGQuX19vcCAhPT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksIGBJbmRleCAke25hbWV9IGV4aXN0cywgY2Fubm90IHVwZGF0ZS5gKTtcbiAgICAgIH1cbiAgICAgIGlmICghZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW5kZXggJHtuYW1lfSBkb2VzIG5vdCBleGlzdCwgY2Fubm90IGRlbGV0ZS5gKTtcbiAgICAgIH1cbiAgICAgIGlmIChmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5kcm9wSW5kZXgoY2xhc3NOYW1lLCBuYW1lKTtcbiAgICAgICAgZGVsZXRlUHJvbWlzZXMucHVzaChwcm9taXNlKTtcbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nSW5kZXhlc1tuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGZpZWxkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKCFmaWVsZHMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksIGBGaWVsZCAke2tleX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBhZGQgaW5kZXguYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZXhpc3RpbmdJbmRleGVzW25hbWVdID0gZmllbGQ7XG4gICAgICAgIGluc2VydGVkSW5kZXhlcy5wdXNoKHtcbiAgICAgICAgICBrZXk6IGZpZWxkLFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGxldCBpbnNlcnRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgaWYgKGluc2VydGVkSW5kZXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICBpbnNlcnRQcm9taXNlID0gdGhpcy5jcmVhdGVJbmRleGVzKGNsYXNzTmFtZSwgaW5zZXJ0ZWRJbmRleGVzKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKGRlbGV0ZVByb21pc2VzKVxuICAgICAgLnRoZW4oKCkgPT4gaW5zZXJ0UHJvbWlzZSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKSlcbiAgICAgIC50aGVuKHNjaGVtYUNvbGxlY3Rpb24gPT4gc2NoZW1hQ29sbGVjdGlvbi51cGRhdGVTY2hlbWEoY2xhc3NOYW1lLCB7XG4gICAgICAgICRzZXQ6IHsgJ19tZXRhZGF0YS5pbmRleGVzJzogIGV4aXN0aW5nSW5kZXhlcyB9XG4gICAgICB9KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldEluZGV4ZXNGcm9tTW9uZ28oY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRJbmRleGVzKGNsYXNzTmFtZSkudGhlbigoaW5kZXhlcykgPT4ge1xuICAgICAgaW5kZXhlcyA9IGluZGV4ZXMucmVkdWNlKChvYmosIGluZGV4KSA9PiB7XG4gICAgICAgIGlmIChpbmRleC5rZXkuX2Z0cykge1xuICAgICAgICAgIGRlbGV0ZSBpbmRleC5rZXkuX2Z0cztcbiAgICAgICAgICBkZWxldGUgaW5kZXgua2V5Ll9mdHN4O1xuICAgICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gaW5kZXgud2VpZ2h0cykge1xuICAgICAgICAgICAgaW5kZXgua2V5W2ZpZWxkXSA9ICd0ZXh0JztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgb2JqW2luZGV4Lm5hbWVdID0gaW5kZXgua2V5O1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgfSwge30pO1xuICAgICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAgICRzZXQ6IHsgJ19tZXRhZGF0YS5pbmRleGVzJzogaW5kZXhlcyB9XG4gICAgICAgIH0pKTtcbiAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpXG4gICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICAvLyBJZ25vcmUgaWYgY29sbGVjdGlvbiBub3QgZm91bmRcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gIH1cblxuICBjcmVhdGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvT2JqZWN0ID0gbW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQKHNjaGVtYS5maWVsZHMsIGNsYXNzTmFtZSwgc2NoZW1hLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucywgc2NoZW1hLmluZGV4ZXMpO1xuICAgIG1vbmdvT2JqZWN0Ll9pZCA9IGNsYXNzTmFtZTtcbiAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWUsIHNjaGVtYS5pbmRleGVzLCB7fSwgc2NoZW1hLmZpZWxkcylcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKSlcbiAgICAgIC50aGVuKHNjaGVtYUNvbGxlY3Rpb24gPT4gc2NoZW1hQ29sbGVjdGlvbi5pbnNlcnRTY2hlbWEobW9uZ29PYmplY3QpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgYWRkRmllbGRJZk5vdEV4aXN0cyhjbGFzc05hbWU6IHN0cmluZywgZmllbGROYW1lOiBzdHJpbmcsIHR5cGU6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgIC50aGVuKHNjaGVtYUNvbGxlY3Rpb24gPT4gc2NoZW1hQ29sbGVjdGlvbi5hZGRGaWVsZElmTm90RXhpc3RzKGNsYXNzTmFtZSwgZmllbGROYW1lLCB0eXBlKSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuY3JlYXRlSW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZSwgZmllbGROYW1lLCB0eXBlKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIERyb3BzIGEgY29sbGVjdGlvbi4gUmVzb2x2ZXMgd2l0aCB0cnVlIGlmIGl0IHdhcyBhIFBhcnNlIFNjaGVtYSAoZWcuIF9Vc2VyLCBDdXN0b20sIGV0Yy4pXG4gIC8vIGFuZCByZXNvbHZlcyB3aXRoIGZhbHNlIGlmIGl0IHdhc24ndCAoZWcuIGEgam9pbiB0YWJsZSkuIFJlamVjdHMgaWYgZGVsZXRpb24gd2FzIGltcG9zc2libGUuXG4gIGRlbGV0ZUNsYXNzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uZHJvcCgpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIC8vICducyBub3QgZm91bmQnIG1lYW5zIGNvbGxlY3Rpb24gd2FzIGFscmVhZHkgZ29uZS4gSWdub3JlIGRlbGV0aW9uIGF0dGVtcHQuXG4gICAgICAgIGlmIChlcnJvci5tZXNzYWdlID09ICducyBub3QgZm91bmQnKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAvLyBXZSd2ZSBkcm9wcGVkIHRoZSBjb2xsZWN0aW9uLCBub3cgcmVtb3ZlIHRoZSBfU0NIRU1BIGRvY3VtZW50XG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uZmluZEFuZERlbGV0ZVNjaGVtYShjbGFzc05hbWUpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgZGVsZXRlQWxsQ2xhc3NlcyhmYXN0OiBib29sZWFuKSB7XG4gICAgcmV0dXJuIHN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnModGhpcylcbiAgICAgIC50aGVuKGNvbGxlY3Rpb25zID0+IFByb21pc2UuYWxsKGNvbGxlY3Rpb25zLm1hcChjb2xsZWN0aW9uID0+IGZhc3QgPyBjb2xsZWN0aW9uLnJlbW92ZSh7fSkgOiBjb2xsZWN0aW9uLmRyb3AoKSkpKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSB0aGUgY29sdW1uIGFuZCBhbGwgdGhlIGRhdGEuIEZvciBSZWxhdGlvbnMsIHRoZSBfSm9pbiBjb2xsZWN0aW9uIGlzIGhhbmRsZWRcbiAgLy8gc3BlY2lhbGx5LCB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IGRlbGV0ZSBfSm9pbiBjb2x1bW5zLiBJdCBzaG91bGQsIGhvd2V2ZXIsIGluZGljYXRlXG4gIC8vIHRoYXQgdGhlIHJlbGF0aW9uIGZpZWxkcyBkb2VzIG5vdCBleGlzdCBhbnltb3JlLiBJbiBtb25nbywgdGhpcyBtZWFucyByZW1vdmluZyBpdCBmcm9tXG4gIC8vIHRoZSBfU0NIRU1BIGNvbGxlY3Rpb24uICBUaGVyZSBzaG91bGQgYmUgbm8gYWN0dWFsIGRhdGEgaW4gdGhlIGNvbGxlY3Rpb24gdW5kZXIgdGhlIHNhbWUgbmFtZVxuICAvLyBhcyB0aGUgcmVsYXRpb24gY29sdW1uLCBzbyBpdCdzIGZpbmUgdG8gYXR0ZW1wdCB0byBkZWxldGUgaXQuIElmIHRoZSBmaWVsZHMgbGlzdGVkIHRvIGJlXG4gIC8vIGRlbGV0ZWQgZG8gbm90IGV4aXN0LCB0aGlzIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gc3VjY2Vzc2Z1bGx5IGFueXdheXMuIENoZWNraW5nIGZvclxuICAvLyBhdHRlbXB0cyB0byBkZWxldGUgbm9uLWV4aXN0ZW50IGZpZWxkcyBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgUGFyc2UgU2VydmVyLlxuXG4gIC8vIFBvaW50ZXIgZmllbGQgbmFtZXMgYXJlIHBhc3NlZCBmb3IgbGVnYWN5IHJlYXNvbnM6IHRoZSBvcmlnaW5hbCBtb25nb1xuICAvLyBmb3JtYXQgc3RvcmVkIHBvaW50ZXIgZmllbGQgbmFtZXMgZGlmZmVyZW50bHkgaW4gdGhlIGRhdGFiYXNlLCBhbmQgdGhlcmVmb3JlXG4gIC8vIG5lZWRlZCB0byBrbm93IHRoZSB0eXBlIG9mIHRoZSBmaWVsZCBiZWZvcmUgaXQgY291bGQgZGVsZXRlIGl0LiBGdXR1cmUgZGF0YWJhc2VcbiAgLy8gYWRhcHRlcnMgc2hvdWxkIGlnbm9yZSB0aGUgcG9pbnRlckZpZWxkTmFtZXMgYXJndW1lbnQuIEFsbCB0aGUgZmllbGQgbmFtZXMgYXJlIGluXG4gIC8vIGZpZWxkTmFtZXMsIHRoZXkgc2hvdyB1cCBhZGRpdGlvbmFsbHkgaW4gdGhlIHBvaW50ZXJGaWVsZE5hbWVzIGRhdGFiYXNlIGZvciB1c2VcbiAgLy8gYnkgdGhlIG1vbmdvIGFkYXB0ZXIsIHdoaWNoIGRlYWxzIHdpdGggdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQuXG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBub3Qgb2JsaWdhdGVkIHRvIGRlbGV0ZSBmaWVsZHMgYXRvbWljYWxseS4gSXQgaXMgZ2l2ZW4gdGhlIGZpZWxkXG4gIC8vIG5hbWVzIGluIGEgbGlzdCBzbyB0aGF0IGRhdGFiYXNlcyB0aGF0IGFyZSBjYXBhYmxlIG9mIGRlbGV0aW5nIGZpZWxkcyBhdG9taWNhbGx5XG4gIC8vIG1heSBkbyBzby5cblxuICAvLyBSZXR1cm5zIGEgUHJvbWlzZS5cbiAgZGVsZXRlRmllbGRzKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGZpZWxkTmFtZXM6IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgbW9uZ29Gb3JtYXROYW1lcyA9IGZpZWxkTmFtZXMubWFwKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm4gYF9wXyR7ZmllbGROYW1lfWBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmaWVsZE5hbWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29uc3QgY29sbGVjdGlvblVwZGF0ZSA9IHsgJyR1bnNldCcgOiB7fSB9O1xuICAgIG1vbmdvRm9ybWF0TmFtZXMuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgIGNvbGxlY3Rpb25VcGRhdGVbJyR1bnNldCddW25hbWVdID0gbnVsbDtcbiAgICB9KTtcblxuICAgIGNvbnN0IHNjaGVtYVVwZGF0ZSA9IHsgJyR1bnNldCcgOiB7fSB9O1xuICAgIGZpZWxkTmFtZXMuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgIHNjaGVtYVVwZGF0ZVsnJHVuc2V0J11bbmFtZV0gPSBudWxsO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24udXBkYXRlTWFueSh7fSwgY29sbGVjdGlvblVwZGF0ZSkpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwgc2NoZW1hVXBkYXRlKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFJldHVybiBhIHByb21pc2UgZm9yIGFsbCBzY2hlbWFzIGtub3duIHRvIHRoaXMgYWRhcHRlciwgaW4gUGFyc2UgZm9ybWF0LiBJbiBjYXNlIHRoZVxuICAvLyBzY2hlbWFzIGNhbm5vdCBiZSByZXRyaWV2ZWQsIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVqZWN0cy4gUmVxdWlyZW1lbnRzIGZvciB0aGVcbiAgLy8gcmVqZWN0aW9uIHJlYXNvbiBhcmUgVEJELlxuICBnZXRBbGxDbGFzc2VzKCk6IFByb21pc2U8U3RvcmFnZUNsYXNzW10+IHtcbiAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpLnRoZW4oc2NoZW1hc0NvbGxlY3Rpb24gPT4gc2NoZW1hc0NvbGxlY3Rpb24uX2ZldGNoQWxsU2NoZW1hc0Zyb21fU0NIRU1BKCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBSZXR1cm4gYSBwcm9taXNlIGZvciB0aGUgc2NoZW1hIHdpdGggdGhlIGdpdmVuIG5hbWUsIGluIFBhcnNlIGZvcm1hdC4gSWZcbiAgLy8gdGhpcyBhZGFwdGVyIGRvZXNuJ3Qga25vdyBhYm91dCB0aGUgc2NoZW1hLCByZXR1cm4gYSBwcm9taXNlIHRoYXQgcmVqZWN0cyB3aXRoXG4gIC8vIHVuZGVmaW5lZCBhcyB0aGUgcmVhc29uLlxuICBnZXRDbGFzcyhjbGFzc05hbWU6IHN0cmluZyk6IFByb21pc2U8U3RvcmFnZUNsYXNzPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hc0NvbGxlY3Rpb24gPT4gc2NoZW1hc0NvbGxlY3Rpb24uX2ZldGNoT25lU2NoZW1hRnJvbV9TQ0hFTUEoY2xhc3NOYW1lKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFRPRE86IEFzIHlldCBub3QgcGFydGljdWxhcmx5IHdlbGwgc3BlY2lmaWVkLiBDcmVhdGVzIGFuIG9iamVjdC4gTWF5YmUgc2hvdWxkbid0IGV2ZW4gbmVlZCB0aGUgc2NoZW1hLFxuICAvLyBhbmQgc2hvdWxkIGluZmVyIGZyb20gdGhlIHR5cGUuIE9yIG1heWJlIGRvZXMgbmVlZCB0aGUgc2NoZW1hIGZvciB2YWxpZGF0aW9ucy4gT3IgbWF5YmUgbmVlZHNcbiAgLy8gdGhlIHNjaGVtYSBvbmx5IGZvciB0aGUgbGVnYWN5IG1vbmdvIGZvcm1hdC4gV2UnbGwgZmlndXJlIHRoYXQgb3V0IGxhdGVyLlxuICBjcmVhdGVPYmplY3QoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgb2JqZWN0OiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29PYmplY3QgPSBwYXJzZU9iamVjdFRvTW9uZ29PYmplY3RGb3JDcmVhdGUoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uaW5zZXJ0T25lKG1vbmdvT2JqZWN0KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkgeyAvLyBEdXBsaWNhdGUgdmFsdWVcbiAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLCAnQSBkdXBsaWNhdGUgdmFsdWUgZm9yIGEgZmllbGQgd2l0aCB1bmlxdWUgdmFsdWVzIHdhcyBwcm92aWRlZCcpO1xuICAgICAgICAgIGVyci51bmRlcmx5aW5nRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICBpZiAoZXJyb3IubWVzc2FnZSkge1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlcyA9IGVycm9yLm1lc3NhZ2UubWF0Y2goL2luZGV4OltcXHNhLXpBLVowLTlfXFwtXFwuXStcXCQ/KFthLXpBLVpfLV0rKV8xLyk7XG4gICAgICAgICAgICBpZiAobWF0Y2hlcyAmJiBBcnJheS5pc0FycmF5KG1hdGNoZXMpKSB7XG4gICAgICAgICAgICAgIGVyci51c2VySW5mbyA9IHsgZHVwbGljYXRlZF9maWVsZDogbWF0Y2hlc1sxXSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gUmVtb3ZlIGFsbCBvYmplY3RzIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIFBhcnNlIFF1ZXJ5LlxuICAvLyBJZiBubyBvYmplY3RzIG1hdGNoLCByZWplY3Qgd2l0aCBPQkpFQ1RfTk9UX0ZPVU5ELiBJZiBvYmplY3RzIGFyZSBmb3VuZCBhbmQgZGVsZXRlZCwgcmVzb2x2ZSB3aXRoIHVuZGVmaW5lZC5cbiAgLy8gSWYgdGhlcmUgaXMgc29tZSBvdGhlciBlcnJvciwgcmVqZWN0IHdpdGggSU5URVJOQUxfU0VSVkVSX0VSUk9SLlxuICBkZWxldGVPYmplY3RzQnlRdWVyeShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiB7XG4gICAgICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbi5kZWxldGVNYW55KG1vbmdvV2hlcmUpXG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpXG4gICAgICAudGhlbigoeyByZXN1bHQgfSkgPT4ge1xuICAgICAgICBpZiAocmVzdWx0Lm4gPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ09iamVjdCBub3QgZm91bmQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSwgKCkgPT4ge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLCAnRGF0YWJhc2UgYWRhcHRlciBlcnJvcicpO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBBcHBseSB0aGUgdXBkYXRlIHRvIGFsbCBvYmplY3RzIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIFBhcnNlIFF1ZXJ5LlxuICB1cGRhdGVPYmplY3RzQnlRdWVyeShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB1cGRhdGU6IGFueSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi51cGRhdGVNYW55KG1vbmdvV2hlcmUsIG1vbmdvVXBkYXRlKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIEF0b21pY2FsbHkgZmluZHMgYW5kIHVwZGF0ZXMgYW4gb2JqZWN0IGJhc2VkIG9uIHF1ZXJ5LlxuICAvLyBSZXR1cm4gdmFsdWUgbm90IGN1cnJlbnRseSB3ZWxsIHNwZWNpZmllZC5cbiAgZmluZE9uZUFuZFVwZGF0ZShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB1cGRhdGU6IGFueSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmZpbmRBbmRNb2RpZnkobW9uZ29XaGVyZSwgW10sIG1vbmdvVXBkYXRlLCB7IG5ldzogdHJ1ZSB9KSlcbiAgICAgIC50aGVuKHJlc3VsdCA9PiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCByZXN1bHQudmFsdWUsIHNjaGVtYSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTEwMDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLCAnQSBkdXBsaWNhdGUgdmFsdWUgZm9yIGEgZmllbGQgd2l0aCB1bmlxdWUgdmFsdWVzIHdhcyBwcm92aWRlZCcpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIEhvcGVmdWxseSB3ZSBjYW4gZ2V0IHJpZCBvZiB0aGlzLiBJdCdzIG9ubHkgdXNlZCBmb3IgY29uZmlnIGFuZCBob29rcy5cbiAgdXBzZXJ0T25lT2JqZWN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIHVwZGF0ZTogYW55KSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvVXBkYXRlID0gdHJhbnNmb3JtVXBkYXRlKGNsYXNzTmFtZSwgdXBkYXRlLCBzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLnVwc2VydE9uZShtb25nb1doZXJlLCBtb25nb1VwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGZpbmQuIEFjY2VwdHM6IGNsYXNzTmFtZSwgcXVlcnkgaW4gUGFyc2UgZm9ybWF0LCBhbmQgeyBza2lwLCBsaW1pdCwgc29ydCB9LlxuICBmaW5kKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIHsgc2tpcCwgbGltaXQsIHNvcnQsIGtleXMsIHJlYWRQcmVmZXJlbmNlIH06IFF1ZXJ5T3B0aW9ucyk6IFByb21pc2U8YW55PiB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvU29ydCA9IF8ubWFwS2V5cyhzb3J0LCAodmFsdWUsIGZpZWxkTmFtZSkgPT4gdHJhbnNmb3JtS2V5KGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpKTtcbiAgICBjb25zdCBtb25nb0tleXMgPSBfLnJlZHVjZShrZXlzLCAobWVtbywga2V5KSA9PiB7XG4gICAgICBtZW1vW3RyYW5zZm9ybUtleShjbGFzc05hbWUsIGtleSwgc2NoZW1hKV0gPSAxO1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfSwge30pO1xuXG4gICAgcmVhZFByZWZlcmVuY2UgPSB0aGlzLl9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gdGhpcy5jcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmZpbmQobW9uZ29XaGVyZSwge1xuICAgICAgICBza2lwLFxuICAgICAgICBsaW1pdCxcbiAgICAgICAgc29ydDogbW9uZ29Tb3J0LFxuICAgICAgICBrZXlzOiBtb25nb0tleXMsXG4gICAgICAgIG1heFRpbWVNUzogdGhpcy5fbWF4VGltZU1TLFxuICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgIH0pKVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiBvYmplY3RzLm1hcChvYmplY3QgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIHVuaXF1ZSBpbmRleC4gVW5pcXVlIGluZGV4ZXMgb24gbnVsbGFibGUgZmllbGRzIGFyZSBub3QgYWxsb3dlZC4gU2luY2Ugd2UgZG9uJ3RcbiAgLy8gY3VycmVudGx5IGtub3cgd2hpY2ggZmllbGRzIGFyZSBudWxsYWJsZSBhbmQgd2hpY2ggYXJlbid0LCB3ZSBpZ25vcmUgdGhhdCBjcml0ZXJpYS5cbiAgLy8gQXMgc3VjaCwgd2Ugc2hvdWxkbid0IGV4cG9zZSB0aGlzIGZ1bmN0aW9uIHRvIHVzZXJzIG9mIHBhcnNlIHVudGlsIHdlIGhhdmUgYW4gb3V0LW9mLWJhbmRcbiAgLy8gV2F5IG9mIGRldGVybWluaW5nIGlmIGEgZmllbGQgaXMgbnVsbGFibGUuIFVuZGVmaW5lZCBkb2Vzbid0IGNvdW50IGFnYWluc3QgdW5pcXVlbmVzcyxcbiAgLy8gd2hpY2ggaXMgd2h5IHdlIHVzZSBzcGFyc2UgaW5kZXhlcy5cbiAgZW5zdXJlVW5pcXVlbmVzcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBmaWVsZE5hbWVzOiBzdHJpbmdbXSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBpbmRleENyZWF0aW9uUmVxdWVzdCA9IHt9O1xuICAgIGNvbnN0IG1vbmdvRmllbGROYW1lcyA9IGZpZWxkTmFtZXMubWFwKGZpZWxkTmFtZSA9PiB0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHNjaGVtYSkpO1xuICAgIG1vbmdvRmllbGROYW1lcy5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpbmRleENyZWF0aW9uUmVxdWVzdFtmaWVsZE5hbWVdID0gMTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQoaW5kZXhDcmVhdGlvblJlcXVlc3QpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDExMDAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ1RyaWVkIHRvIGVuc3VyZSBmaWVsZCB1bmlxdWVuZXNzIGZvciBhIGNsYXNzIHRoYXQgYWxyZWFkeSBoYXMgZHVwbGljYXRlcy4nKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBVc2VkIGluIHRlc3RzXG4gIF9yYXdGaW5kKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogUXVlcnlUeXBlKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmZpbmQocXVlcnksIHtcbiAgICAgIG1heFRpbWVNUzogdGhpcy5fbWF4VGltZU1TLFxuICAgIH0pKS5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIEV4ZWN1dGVzIGEgY291bnQuXG4gIGNvdW50KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uY291bnQodHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKSwge1xuICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICB9KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRpc3RpbmN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIGZpZWxkTmFtZTogc3RyaW5nKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IGlzUG9pbnRlckZpZWxkID0gc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcic7XG4gICAgaWYgKGlzUG9pbnRlckZpZWxkKSB7XG4gICAgICBmaWVsZE5hbWUgPSBgX3BfJHtmaWVsZE5hbWV9YFxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5kaXN0aW5jdChmaWVsZE5hbWUsIHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSkpKVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiB7XG4gICAgICAgIG9iamVjdHMgPSBvYmplY3RzLmZpbHRlcigob2JqKSA9PiBvYmogIT0gbnVsbCk7XG4gICAgICAgIHJldHVybiBvYmplY3RzLm1hcChvYmplY3QgPT4ge1xuICAgICAgICAgIGlmIChpc1BvaW50ZXJGaWVsZCkge1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSBmaWVsZE5hbWUuc3Vic3RyaW5nKDMpO1xuICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcoc2NoZW1hLCBmaWVsZCwgb2JqZWN0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgYWdncmVnYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSwgcmVhZFByZWZlcmVuY2U6ID9zdHJpbmcpIHtcbiAgICBsZXQgaXNQb2ludGVyRmllbGQgPSBmYWxzZTtcbiAgICBwaXBlbGluZSA9IHBpcGVsaW5lLm1hcCgoc3RhZ2UpID0+IHtcbiAgICAgIGlmIChzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgc3RhZ2UuJGdyb3VwID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCBzdGFnZS4kZ3JvdXApO1xuICAgICAgICBpZiAoc3RhZ2UuJGdyb3VwLl9pZCAmJiAodHlwZW9mIHN0YWdlLiRncm91cC5faWQgPT09ICdzdHJpbmcnKSAmJiBzdGFnZS4kZ3JvdXAuX2lkLmluZGV4T2YoJyRfcF8nKSA+PSAwKSB7XG4gICAgICAgICAgaXNQb2ludGVyRmllbGQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgIHN0YWdlLiRtYXRjaCA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHN0YWdlLiRtYXRjaCk7XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJHByb2plY3QpIHtcbiAgICAgICAgc3RhZ2UuJHByb2plY3QgPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZVByb2plY3RBcmdzKHNjaGVtYSwgc3RhZ2UuJHByb2plY3QpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0YWdlO1xuICAgIH0pO1xuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uYWdncmVnYXRlKHBpcGVsaW5lLCB7IHJlYWRQcmVmZXJlbmNlLCBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyB9KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxNjAwNikge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgcmVzdWx0cy5mb3JFYWNoKHJlc3VsdCA9PiB7XG4gICAgICAgICAgaWYgKHJlc3VsdC5oYXNPd25Qcm9wZXJ0eSgnX2lkJykpIHtcbiAgICAgICAgICAgIGlmIChpc1BvaW50ZXJGaWVsZCAmJiByZXN1bHQuX2lkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdC5faWQgPSByZXN1bHQuX2lkLnNwbGl0KCckJylbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0Ll9pZCA9PSBudWxsIHx8IF8uaXNFbXB0eShyZXN1bHQuX2lkKSkge1xuICAgICAgICAgICAgICByZXN1bHQuX2lkID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdC5vYmplY3RJZCA9IHJlc3VsdC5faWQ7XG4gICAgICAgICAgICBkZWxldGUgcmVzdWx0Ll9pZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgIH0pXG4gICAgICAudGhlbihvYmplY3RzID0+IG9iamVjdHMubWFwKG9iamVjdCA9PiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSkpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIHJlY3Vyc2l2ZWx5IHRyYXZlcnNlIHRoZSBwaXBlbGluZSBhbmQgY29udmVydCBhbnkgUG9pbnRlciBvciBEYXRlIGNvbHVtbnMuXG4gIC8vIElmIHdlIGRldGVjdCBhIHBvaW50ZXIgY29sdW1uIHdlIHdpbGwgcmVuYW1lIHRoZSBjb2x1bW4gYmVpbmcgcXVlcmllZCBmb3IgdG8gbWF0Y2ggdGhlIGNvbHVtblxuICAvLyBpbiB0aGUgZGF0YWJhc2UuIFdlIGFsc28gbW9kaWZ5IHRoZSB2YWx1ZSB0byB3aGF0IHdlIGV4cGVjdCB0aGUgdmFsdWUgdG8gYmUgaW4gdGhlIGRhdGFiYXNlXG4gIC8vIGFzIHdlbGwuXG4gIC8vIEZvciBkYXRlcywgdGhlIGRyaXZlciBleHBlY3RzIGEgRGF0ZSBvYmplY3QsIGJ1dCB3ZSBoYXZlIGEgc3RyaW5nIGNvbWluZyBpbi4gU28gd2UnbGwgY29udmVydFxuICAvLyB0aGUgc3RyaW5nIHRvIGEgRGF0ZSBzbyB0aGUgZHJpdmVyIGNhbiBwZXJmb3JtIHRoZSBuZWNlc3NhcnkgY29tcGFyaXNvbi5cbiAgLy9cbiAgLy8gVGhlIGdvYWwgb2YgdGhpcyBtZXRob2QgaXMgdG8gbG9vayBmb3IgdGhlIFwibGVhdmVzXCIgb2YgdGhlIHBpcGVsaW5lIGFuZCBkZXRlcm1pbmUgaWYgaXQgbmVlZHNcbiAgLy8gdG8gYmUgY29udmVydGVkLiBUaGUgcGlwZWxpbmUgY2FuIGhhdmUgYSBmZXcgZGlmZmVyZW50IGZvcm1zLiBGb3IgbW9yZSBkZXRhaWxzLCBzZWU6XG4gIC8vICAgICBodHRwczovL2RvY3MubW9uZ29kYi5jb20vbWFudWFsL3JlZmVyZW5jZS9vcGVyYXRvci9hZ2dyZWdhdGlvbi9cbiAgLy9cbiAgLy8gSWYgdGhlIHBpcGVsaW5lIGlzIGFuIGFycmF5LCBpdCBtZWFucyB3ZSBhcmUgcHJvYmFibHkgcGFyc2luZyBhbiAnJGFuZCcgb3IgJyRvcicgb3BlcmF0b3IuIEluXG4gIC8vIHRoYXQgY2FzZSB3ZSBuZWVkIHRvIGxvb3AgdGhyb3VnaCBhbGwgb2YgaXQncyBjaGlsZHJlbiB0byBmaW5kIHRoZSBjb2x1bW5zIGJlaW5nIG9wZXJhdGVkIG9uLlxuICAvLyBJZiB0aGUgcGlwZWxpbmUgaXMgYW4gb2JqZWN0LCB0aGVuIHdlJ2xsIGxvb3AgdGhyb3VnaCB0aGUga2V5cyBjaGVja2luZyB0byBzZWUgaWYgdGhlIGtleSBuYW1lXG4gIC8vIG1hdGNoZXMgb25lIG9mIHRoZSBzY2hlbWEgY29sdW1ucy4gSWYgaXQgZG9lcyBtYXRjaCBhIGNvbHVtbiBhbmQgdGhlIGNvbHVtbiBpcyBhIFBvaW50ZXIgb3JcbiAgLy8gYSBEYXRlLCB0aGVuIHdlJ2xsIGNvbnZlcnQgdGhlIHZhbHVlIGFzIGRlc2NyaWJlZCBhYm92ZS5cbiAgLy9cbiAgLy8gQXMgbXVjaCBhcyBJIGhhdGUgcmVjdXJzaW9uLi4udGhpcyBzZWVtZWQgbGlrZSBhIGdvb2QgZml0IGZvciBpdC4gV2UncmUgZXNzZW50aWFsbHkgdHJhdmVyc2luZ1xuICAvLyBkb3duIGEgdHJlZSB0byBmaW5kIGEgXCJsZWFmIG5vZGVcIiBhbmQgY2hlY2tpbmcgdG8gc2VlIGlmIGl0IG5lZWRzIHRvIGJlIGNvbnZlcnRlZC5cbiAgX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSk6IGFueSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICByZXR1cm4gcGlwZWxpbmUubWFwKCh2YWx1ZSkgPT4gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYSwgdmFsdWUpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwaXBlbGluZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGNvbnN0IHJldHVyblZhbHVlID0ge307XG4gICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIHBpcGVsaW5lKSB7XG4gICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHBpcGVsaW5lW2ZpZWxkXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIFBhc3Mgb2JqZWN0cyBkb3duIHRvIE1vbmdvREIuLi50aGlzIGlzIG1vcmUgdGhhbiBsaWtlbHkgYW4gJGV4aXN0cyBvcGVyYXRvci5cbiAgICAgICAgICAgIHJldHVyblZhbHVlW2BfcF8ke2ZpZWxkfWBdID0gcGlwZWxpbmVbZmllbGRdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IGAke3NjaGVtYS5maWVsZHNbZmllbGRdLnRhcmdldENsYXNzfSQke3BpcGVsaW5lW2ZpZWxkXX1gO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnRGF0ZScpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9jb252ZXJ0VG9EYXRlKHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYSwgcGlwZWxpbmVbZmllbGRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWVsZCA9PT0gJ29iamVjdElkJykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfaWQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfY3JlYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbJ191cGRhdGVkX2F0J10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gcGlwZWxpbmU7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIHNsaWdodGx5IGRpZmZlcmVudCB0aGFuIHRoZSBvbmUgYWJvdmUuIFJhdGhlciB0aGFuIHRyeWluZyB0byBjb21iaW5lIHRoZXNlXG4gIC8vIHR3byBmdW5jdGlvbnMgYW5kIG1ha2luZyB0aGUgY29kZSBldmVuIGhhcmRlciB0byB1bmRlcnN0YW5kLCBJIGRlY2lkZWQgdG8gc3BsaXQgaXQgdXAuIFRoZVxuICAvLyBkaWZmZXJlbmNlIHdpdGggdGhpcyBmdW5jdGlvbiBpcyB3ZSBhcmUgbm90IHRyYW5zZm9ybWluZyB0aGUgdmFsdWVzLCBvbmx5IHRoZSBrZXlzIG9mIHRoZVxuICAvLyBwaXBlbGluZS5cbiAgX3BhcnNlQWdncmVnYXRlUHJvamVjdEFyZ3Moc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnkpOiBhbnkge1xuICAgIGNvbnN0IHJldHVyblZhbHVlID0ge307XG4gICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGRdICYmIHNjaGVtYS5maWVsZHNbZmllbGRdLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IHBpcGVsaW5lW2ZpZWxkXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChmaWVsZCA9PT0gJ29iamVjdElkJykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX2lkJ10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX2NyZWF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgIHJldHVyblZhbHVlWydfdXBkYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIHNsaWdodGx5IGRpZmZlcmVudCB0aGFuIHRoZSB0d28gYWJvdmUuIE1vbmdvREIgJGdyb3VwIGFnZ3JlZ2F0ZSBsb29rcyBsaWtlOlxuICAvLyAgICAgeyAkZ3JvdXA6IHsgX2lkOiA8ZXhwcmVzc2lvbj4sIDxmaWVsZDE+OiB7IDxhY2N1bXVsYXRvcjE+IDogPGV4cHJlc3Npb24xPiB9LCAuLi4gfSB9XG4gIC8vIFRoZSA8ZXhwcmVzc2lvbj4gY291bGQgYmUgYSBjb2x1bW4gbmFtZSwgcHJlZml4ZWQgd2l0aCB0aGUgJyQnIGNoYXJhY3Rlci4gV2UnbGwgbG9vayBmb3JcbiAgLy8gdGhlc2UgPGV4cHJlc3Npb24+IGFuZCBjaGVjayB0byBzZWUgaWYgaXQgaXMgYSAnUG9pbnRlcicgb3IgaWYgaXQncyBvbmUgb2YgY3JlYXRlZEF0LFxuICAvLyB1cGRhdGVkQXQgb3Igb2JqZWN0SWQgYW5kIGNoYW5nZSBpdCBhY2NvcmRpbmdseS5cbiAgX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShwaXBlbGluZSkpIHtcbiAgICAgIHJldHVybiBwaXBlbGluZS5tYXAoKHZhbHVlKSA9PiB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWEsIHZhbHVlKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCBmaWVsZCA9IHBpcGVsaW5lLnN1YnN0cmluZygxKTtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuIGAkX3BfJHtmaWVsZH1gO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICByZXR1cm4gJyRfY3JlYXRlZF9hdCc7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgIHJldHVybiAnJF91cGRhdGVkX2F0JztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBpcGVsaW5lO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGF0dGVtcHQgdG8gY29udmVydCB0aGUgcHJvdmlkZWQgdmFsdWUgdG8gYSBEYXRlIG9iamVjdC4gU2luY2UgdGhpcyBpcyBwYXJ0XG4gIC8vIG9mIGFuIGFnZ3JlZ2F0aW9uIHBpcGVsaW5lLCB0aGUgdmFsdWUgY2FuIGVpdGhlciBiZSBhIHN0cmluZyBvciBpdCBjYW4gYmUgYW5vdGhlciBvYmplY3Qgd2l0aFxuICAvLyBhbiBvcGVyYXRvciBpbiBpdCAobGlrZSAkZ3QsICRsdCwgZXRjKS4gQmVjYXVzZSBvZiB0aGlzIEkgZmVsdCBpdCB3YXMgZWFzaWVyIHRvIG1ha2UgdGhpcyBhXG4gIC8vIHJlY3Vyc2l2ZSBtZXRob2QgdG8gdHJhdmVyc2UgZG93biB0byB0aGUgXCJsZWFmIG5vZGVcIiB3aGljaCBpcyBnb2luZyB0byBiZSB0aGUgc3RyaW5nLlxuICBfY29udmVydFRvRGF0ZSh2YWx1ZTogYW55KTogYW55IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9XG4gICAgZm9yIChjb25zdCBmaWVsZCBpbiB2YWx1ZSkge1xuICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fY29udmVydFRvRGF0ZSh2YWx1ZVtmaWVsZF0pXG4gICAgfVxuICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgfVxuXG4gIF9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKTogP3N0cmluZyB7XG4gICAgc3dpdGNoIChyZWFkUHJlZmVyZW5jZSkge1xuICAgIGNhc2UgJ1BSSU1BUlknOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5QUklNQVJZO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnUFJJTUFSWV9QUkVGRVJSRUQnOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5QUklNQVJZX1BSRUZFUlJFRDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1NFQ09OREFSWSc6XG4gICAgICByZWFkUHJlZmVyZW5jZSA9IFJlYWRQcmVmZXJlbmNlLlNFQ09OREFSWTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1NFQ09OREFSWV9QUkVGRVJSRUQnOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5TRUNPTkRBUllfUFJFRkVSUkVEO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnTkVBUkVTVCc6XG4gICAgICByZWFkUHJlZmVyZW5jZSA9IFJlYWRQcmVmZXJlbmNlLk5FQVJFU1Q7XG4gICAgICBicmVhaztcbiAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgJ05vdCBzdXBwb3J0ZWQgcmVhZCBwcmVmZXJlbmNlLicpO1xuICAgIH1cbiAgICByZXR1cm4gcmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICBwZXJmb3JtSW5pdGlhbGl6YXRpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXgoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4KGluZGV4LCB7YmFja2dyb3VuZDogdHJ1ZX0pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZywgaW5kZXhlczogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5jcmVhdGVJbmRleGVzKGluZGV4ZXMsIHtiYWNrZ3JvdW5kOiB0cnVlfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBjcmVhdGVJbmRleGVzSWZOZWVkZWQoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpIHtcbiAgICBpZiAodHlwZSAmJiB0eXBlLnR5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgY29uc3QgaW5kZXggPSB7XG4gICAgICAgIFtmaWVsZE5hbWVdOiAnMmRzcGhlcmUnXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlSW5kZXgoY2xhc3NOYW1lLCBpbmRleCk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNyZWF0ZVRleHRJbmRleGVzSWZOZWVkZWQoY2xhc3NOYW1lOiBzdHJpbmcsIHF1ZXJ5OiBRdWVyeVR5cGUsIHNjaGVtYTogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZm9yKGNvbnN0IGZpZWxkTmFtZSBpbiBxdWVyeSkge1xuICAgICAgaWYgKCFxdWVyeVtmaWVsZE5hbWVdIHx8ICFxdWVyeVtmaWVsZE5hbWVdLiR0ZXh0KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZXhpc3RpbmdJbmRleGVzID0gc2NoZW1hLmluZGV4ZXM7XG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiBleGlzdGluZ0luZGV4ZXMpIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBleGlzdGluZ0luZGV4ZXNba2V5XTtcbiAgICAgICAgaWYgKGluZGV4Lmhhc093blByb3BlcnR5KGZpZWxkTmFtZSkpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IGluZGV4TmFtZSA9IGAke2ZpZWxkTmFtZX1fdGV4dGA7XG4gICAgICBjb25zdCB0ZXh0SW5kZXggPSB7XG4gICAgICAgIFtpbmRleE5hbWVdOiB7IFtmaWVsZE5hbWVdOiAndGV4dCcgfVxuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KGNsYXNzTmFtZSwgdGV4dEluZGV4LCBleGlzdGluZ0luZGV4ZXMsIHNjaGVtYS5maWVsZHMpXG4gICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gODUpIHsgLy8gSW5kZXggZXhpc3Qgd2l0aCBkaWZmZXJlbnQgb3B0aW9uc1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V0SW5kZXhlc0Zyb21Nb25nbyhjbGFzc05hbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGdldEluZGV4ZXMoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmluZGV4ZXMoKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRyb3BJbmRleChjbGFzc05hbWU6IHN0cmluZywgaW5kZXg6IGFueSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uZHJvcEluZGV4KGluZGV4KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRyb3BBbGxJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5kcm9wSW5kZXhlcygpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgdXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMoKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRBbGxDbGFzc2VzKClcbiAgICAgIC50aGVuKChjbGFzc2VzKSA9PiB7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gY2xhc3Nlcy5tYXAoKHNjaGVtYSkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNGcm9tTW9uZ28oc2NoZW1hLmNsYXNzTmFtZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBNb25nb1N0b3JhZ2VBZGFwdGVyO1xuIl19 \ No newline at end of file diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js index 9c783a58fd..1a65f7260d 100644 --- a/lib/Controllers/PushController.js +++ b/lib/Controllers/PushController.js @@ -21,6 +21,8 @@ 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 { @@ -72,6 +74,8 @@ class PushController { badgeUpdate = () => { // Build a real RestQuery so we can use it in RestWrite const restQuery = new _RestQuery2.default(config, (0, _Auth.master)(config), '_Installation', updateWhere); + // change $exists for $ne null for better performance + if (restQuery.restWhere && restQuery.restWhere.deviceToken && restQuery.restWhere.deviceToken['$exists']) restQuery.restWhere.deviceToken = { $ne: null }; return restQuery.buildRestWhere().then(() => { const write = new _RestWrite2.default(config, (0, _Auth.master)(config), '_Installation', restQuery.restWhere, restUpdate); write.runOptions.many = true; @@ -84,7 +88,15 @@ class PushController { return pushStatus.setInitial(body, where); }).then(() => { onPushStatusSaved(pushStatus.objectId); - return badgeUpdate(); + const promise = badgeUpdate(); + // add this to ignore badge update errors as default + if (!config.stopOnBadgeUpdateError) { + promise.catch(err => { + _logger.logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`); + _logger.logger.error(err); + }); + } + return promise; }).then(() => { // Update audience lastUsed and timesUsed if (body.audience_id) { @@ -212,4 +224,4 @@ class PushController { exports.PushController = PushController; exports.default = PushController; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJidWlsZFJlc3RXaGVyZSIsInRoZW4iLCJ3cml0ZSIsIlJlc3RXcml0ZSIsInJlc3RXaGVyZSIsInJ1bk9wdGlvbnMiLCJtYW55IiwiZXhlY3V0ZSIsInB1c2hTdGF0dXMiLCJzZXRJbml0aWFsIiwib2JqZWN0SWQiLCJhdWRpZW5jZV9pZCIsImF1ZGllbmNlSWQiLCJ1cGRhdGVBdWRpZW5jZSIsImxhc3RVc2VkIiwiX190eXBlIiwiaXNvIiwidG9JU09TdHJpbmciLCJ0aW1lc1VzZWQiLCJoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCIsInB1c2hDb250cm9sbGVyUXVldWUiLCJlbnF1ZXVlIiwiY2F0Y2giLCJlcnIiLCJmYWlsIiwiaGFzRXhwaXJhdGlvblRpbWUiLCJleHBpcmF0aW9uVGltZVBhcmFtIiwiZXhwaXJhdGlvblRpbWUiLCJpc0Zpbml0ZSIsImhhc0V4cGlyYXRpb25JbnRlcnZhbCIsImV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIiwiaGFzUHVzaFRpbWUiLCJwdXNoVGltZVBhcmFtIiwiaXNMb2NhbFRpbWUiLCJwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50Iiwib2Zmc2V0UGF0dGVybiIsImluZGV4T2YiLCJsZW5ndGgiLCJ0ZXN0IiwiaXNvU3RyaW5nIiwic3Vic3RyaW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsY0FBTixDQUFxQjs7QUFFMUJDLFdBQVNDLE9BQU8sRUFBaEIsRUFBb0JDLFFBQVEsRUFBNUIsRUFBZ0NDLE1BQWhDLEVBQXdDQyxJQUF4QyxFQUE4Q0Msb0JBQW9CLE1BQU0sQ0FBRSxDQUExRSxFQUE0RUMsTUFBTSxJQUFJQyxJQUFKLEVBQWxGLEVBQThGO0FBQzVGLFFBQUksQ0FBQ0osT0FBT0ssY0FBWixFQUE0QjtBQUMxQixZQUFNLElBQUlDLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0osNEJBREksQ0FBTjtBQUVEOztBQUVEO0FBQ0FWLFNBQUtXLGVBQUwsR0FBdUJiLGVBQWVjLGlCQUFmLENBQWlDWixJQUFqQyxDQUF2QjtBQUNBQSxTQUFLYSxtQkFBTCxHQUEyQmYsZUFBZWdCLHFCQUFmLENBQXFDZCxJQUFyQyxDQUEzQjtBQUNBLFFBQUlBLEtBQUtXLGVBQUwsSUFBd0JYLEtBQUthLG1CQUFqQyxFQUFzRDtBQUNwRCxZQUFNLElBQUlMLFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKLDREQUZJLENBQU47QUFHRDs7QUFFRDtBQUNBLFFBQUlWLEtBQUthLG1CQUFMLElBQTRCLENBQUNiLEtBQUtlLGNBQUwsQ0FBb0IsV0FBcEIsQ0FBakMsRUFBbUU7QUFDakUsWUFBTUMsUUFBUWhCLEtBQUthLG1CQUFMLEdBQTJCLElBQXpDO0FBQ0FiLFdBQUtXLGVBQUws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LENBQW9CLENBQXBCLEVBQXVCRCxVQUFVSCxPQUFWLENBQWtCLEdBQWxCLENBQXZCLENBQVA7QUFDRDtBQUNELFdBQU9uRCxLQUFLZ0MsV0FBTCxFQUFQO0FBQ0Q7QUFoTXlCOztRQUFmdEQsYyxHQUFBQSxjO2tCQW1NRUEsYyIsImZpbGUiOiJQdXNoQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlIH0gICAgICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFJlc3RRdWVyeSAgICAgICAgICAgICAgZnJvbSAnLi4vUmVzdFF1ZXJ5JztcbmltcG9ydCBSZXN0V3JpdGUgICAgICAgICAgICAgIGZyb20gJy4uL1Jlc3RXcml0ZSc7XG5pbXBvcnQgeyBtYXN0ZXIgfSAgICAgICAgICAgICBmcm9tICcuLi9BdXRoJztcbmltcG9ydCB7IHB1c2hTdGF0dXNIYW5kbGVyIH0gIGZyb20gJy4uL1N0YXR1c0hhbmRsZXInO1xuaW1wb3J0IHsgYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyB9IGZyb20gJy4uL1B1c2gvdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgUHVzaENvbnRyb2xsZXIge1xuXG4gIHNlbmRQdXNoKGJvZHkgPSB7fSwgd2hlcmUgPSB7fSwgY29uZmlnLCBhdXRoLCBvblB1c2hTdGF0dXNTYXZlZCA9ICgpID0+IHt9LCBub3cgPSBuZXcgRGF0ZSgpKSB7XG4gICAgaWYgKCFjb25maWcuaGFzUHVzaFN1cHBvcnQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdNaXNzaW5nIHB1c2ggY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIFJlcGxhY2UgdGhlIGV4cGlyYXRpb25fdGltZSBhbmQgcHVzaF90aW1lIHdpdGggYSB2YWxpZCBVbml4IGVwb2NoIG1pbGxpc2Vjb25kcyB0aW1lXG4gICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uVGltZShib2R5KTtcbiAgICBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSk7XG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl90aW1lICYmIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdCb3RoIGV4cGlyYXRpb25fdGltZSBhbmQgZXhwaXJhdGlvbl9pbnRlcnZhbCBjYW5ub3QgYmUgc2V0Jyk7XG4gICAgfVxuXG4gICAgLy8gSW1tZWRpYXRlIHB1c2hcbiAgICBpZiAoYm9keS5leHBpcmF0aW9uX2ludGVydmFsICYmICFib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKSkge1xuICAgICAgY29uc3QgdHRsTXMgPSBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgKiAxMDAwO1xuICAgICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSAobmV3IERhdGUobm93LnZhbHVlT2YoKSArIHR0bE1zKSkudmFsdWVPZigpO1xuICAgIH1cblxuICAgIGNvbnN0IHB1c2hUaW1lID0gUHVzaENvbnRyb2xsZXIuZ2V0UHVzaFRpbWUoYm9keSk7XG4gICAgaWYgKHB1c2hUaW1lICYmIHB1c2hUaW1lLmRhdGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBib2R5WydwdXNoX3RpbWUnXSA9IFB1c2hDb250cm9sbGVyLmZvcm1hdFB1c2hUaW1lKHB1c2hUaW1lKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBJZiB0aGUgcmVxIGNhbiBwYXNzIHRoZSBjaGVja2luZywgd2UgcmV0dXJuIGltbWVkaWF0ZWx5IGluc3RlYWQgb2Ygd2FpdGluZ1xuICAgIC8vIHB1c2hlcyB0byBiZSBzZW50LiBXZSBwcm9iYWJseSBjaGFuZ2UgdGhpcyBiZWhhdmlvdXIgaW4gdGhlIGZ1dHVyZS5cbiAgICBsZXQgYmFkZ2VVcGRhdGUgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYgKGJvZHkuZGF0YSAmJiBib2R5LmRhdGEuYmFkZ2UpIHtcbiAgICAgIGNvbnN0IGJhZGdlID0gYm9keS5kYXRhLmJhZGdlO1xuICAgICAgbGV0IHJlc3RVcGRhdGUgPSB7fTtcbiAgICAgIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ3N0cmluZycgJiYgYmFkZ2UudG9Mb3dlckNhc2UoKSA9PT0gJ2luY3JlbWVudCcpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogMSB9IH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGJhZGdlID09ICdvYmplY3QnICYmIHR5cGVvZiBiYWRnZS5fX29wID09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICAgICAgIGJhZGdlLl9fb3AudG9Mb3dlckNhc2UoKSA9PSAnaW5jcmVtZW50JyAmJiBOdW1iZXIoYmFkZ2UuYW1vdW50KSkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBiYWRnZS5hbW91bnQgfSB9XG4gICAgICB9IGVsc2UgaWYgKE51bWJlcihiYWRnZSkpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IGJhZGdlIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IFwiSW52YWxpZCB2YWx1ZSBmb3IgYmFkZ2UsIGV4cGVjdGVkIG51bWJlciBvciAnSW5jcmVtZW50JyBvciB7aW5jcmVtZW50OiBudW1iZXJ9XCI7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvcmNlIGZpbHRlcmluZyBvbiBvbmx5IHZhbGlkIGRldmljZSB0b2tlbnNcbiAgICAgIGNvbnN0IHVwZGF0ZVdoZXJlID0gYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyh3aGVyZSk7XG4gICAgICBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgICAgLy8gQnVpbGQgYSByZWFsIFJlc3RRdWVyeSBzbyB3ZSBjYW4gdXNlIGl0IGluIFJlc3RXcml0ZVxuICAgICAgICBjb25zdCByZXN0UXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgdXBkYXRlV2hlcmUpO1xuICAgICAgICByZXR1cm4gcmVzdFF1ZXJ5LmJ1aWxkUmVzdFdoZXJlKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgcmVzdFF1ZXJ5LnJlc3RXaGVyZSwgcmVzdFVwZGF0ZSk7XG4gICAgICAgICAgd3JpdGUucnVuT3B0aW9ucy5tYW55ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcHVzaFN0YXR1cyA9IHB1c2hTdGF0dXNIYW5kbGVyKGNvbmZpZyk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHB1c2hTdGF0dXMuc2V0SW5pdGlhbChib2R5LCB3aGVyZSk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBvblB1c2hTdGF0dXNTYXZlZChwdXNoU3RhdHVzLm9iamVjdElkKTtcbiAgICAgIHJldHVybiBiYWRnZVVwZGF0ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gVXBkYXRlIGF1ZGllbmNlIGxhc3RVc2VkIGFuZCB0aW1lc1VzZWRcbiAgICAgIGlmIChib2R5LmF1ZGllbmNlX2lkKSB7XG4gICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgIHZhciB1cGRhdGVBdWRpZW5jZSA9IHtcbiAgICAgICAgICBsYXN0VXNlZDogeyBfX3R5cGU6IFwiRGF0ZVwiLCBpc286IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSB9LFxuICAgICAgICAgIHRpbWVzVXNlZDogeyBfX29wOiBcIkluY3JlbWVudFwiLCBcImFtb3VudFwiOiAxIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfQXVkaWVuY2UnLCB7b2JqZWN0SWQ6IGF1ZGllbmNlSWR9LCB1cGRhdGVBdWRpZW5jZSk7XG4gICAgICAgIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgIH1cbiAgICAgIC8vIERvbid0IHdhaXQgZm9yIHRoZSBhdWRpZW5jZSB1cGRhdGUgcHJvbWlzZSB0byByZXNvbHZlLlxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpICYmIGNvbmZpZy5oYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShib2R5LCB3aGVyZSwgY29uZmlnLCBhdXRoLCBwdXNoU3RhdHVzKTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5mYWlsKGVycikudGhlbigoKSA9PiB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBleHBpcmF0aW9uIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgZXhwaXJhdGlvbiB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldEV4cGlyYXRpb25UaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNFeHBpcmF0aW9uVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25fdGltZScpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvblRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV4cGlyYXRpb25UaW1lUGFyYW0gPSBib2R5WydleHBpcmF0aW9uX3RpbWUnXTtcbiAgICB2YXIgZXhwaXJhdGlvblRpbWU7XG4gICAgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwaXJhdGlvblRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGV4cGlyYXRpb25UaW1lID0gbmV3IERhdGUoZXhwaXJhdGlvblRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZXhwaXJhdGlvblRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIGV4cGlyYXRpb25UaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZXhwaXJhdGlvblRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBib2R5WydleHBpcmF0aW9uX3RpbWUnXSArICcgaXMgbm90IHZhbGlkIHRpbWUuJyk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uVGltZS52YWx1ZU9mKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkgPSB7fSkge1xuICAgIGNvbnN0IGhhc0V4cGlyYXRpb25JbnRlcnZhbCA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25faW50ZXJ2YWwnKTtcbiAgICBpZiAoIWhhc0V4cGlyYXRpb25JbnRlcnZhbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25faW50ZXJ2YWwnXTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtICE9PSAnbnVtYmVyJyB8fCBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBgZXhwaXJhdGlvbl9pbnRlcnZhbCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAwYCk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcHVzaCB0aW1lIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcXVlc3QgQSByZXF1ZXN0IG9iamVjdFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfHVuZGVmaW5lZH0gVGhlIHB1c2ggdGltZSBpZiBpdCBleGlzdHMgaW4gdGhlIHJlcXVlc3RcbiAgICovXG4gIHN0YXRpYyBnZXRQdXNoVGltZShib2R5ID0ge30pIHtcbiAgICB2YXIgaGFzUHVzaFRpbWUgPSBib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKTtcbiAgICBpZiAoIWhhc1B1c2hUaW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBwdXNoVGltZVBhcmFtID0gYm9keVsncHVzaF90aW1lJ107XG4gICAgdmFyIGRhdGU7XG4gICAgdmFyIGlzTG9jYWxUaW1lID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlzTG9jYWxUaW1lID0gIVB1c2hDb250cm9sbGVyLnB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbSk7XG4gICAgICBkYXRlID0gbmV3IERhdGUocHVzaFRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgcHVzaFRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIHB1c2hUaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZGF0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0ZSxcbiAgICAgIGlzTG9jYWxUaW1lLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgSVNPODYwMSBmb3JtYXR0ZWQgZGF0ZSBjb250YWlucyBhIHRpbWV6b25lIGNvbXBvbmVudFxuICAgKiBAcGFyYW0gcHVzaFRpbWVQYXJhbSB7c3RyaW5nfVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50KHB1c2hUaW1lUGFyYW06IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG9mZnNldFBhdHRlcm4gPSAvKC4rKShbKy1dKVxcZFxcZDpcXGRcXGQkLztcbiAgICByZXR1cm4gcHVzaFRpbWVQYXJhbS5pbmRleE9mKCdaJykgPT09IHB1c2hUaW1lUGFyYW0ubGVuZ3RoIC0gMSAvLyAyMDA3LTA0LTA1VDEyOjMwWlxuICAgICAgfHwgb2Zmc2V0UGF0dGVybi50ZXN0KHB1c2hUaW1lUGFyYW0pOyAvLyAyMDA3LTA0LTA1VDEyOjMwLjAwMCswMjowMCwgMjAwNy0wNC0wNVQxMjozMC4wMDAtMDI6MDBcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGRhdGUgdG8gSVNPIGZvcm1hdCBpbiBVVEMgdGltZSBhbmQgc3RyaXBzIHRoZSB0aW1lem9uZSBpZiBgaXNMb2NhbFRpbWVgIGlzIHRydWVcbiAgICogQHBhcmFtIGRhdGUge0RhdGV9XG4gICAqIEBwYXJhbSBpc0xvY2FsVGltZSB7Ym9vbGVhbn1cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBmb3JtYXRQdXNoVGltZSh7IGRhdGUsIGlzTG9jYWxUaW1lIH06IHsgZGF0ZTogRGF0ZSwgaXNMb2NhbFRpbWU6IGJvb2xlYW4gfSkge1xuICAgIGlmIChpc0xvY2FsVGltZSkgeyAvLyBTdHJpcCAnWidcbiAgICAgIGNvbnN0IGlzb1N0cmluZyA9IGRhdGUudG9JU09TdHJpbmcoKTtcbiAgICAgIHJldHVybiBpc29TdHJpbmcuc3Vic3RyaW5nKDAsIGlzb1N0cmluZy5pbmRleE9mKCdaJykpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hDb250cm9sbGVyO1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJyZXN0V2hlcmUiLCJkZXZpY2VUb2tlbiIsIiRuZSIsImJ1aWxkUmVzdFdoZXJlIiwidGhlbiIsIndyaXRlIiwiUmVzdFdyaXRlIiwicnVuT3B0aW9ucyIsIm1hbnkiLCJleGVjdXRlIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJvYmplY3RJZCIsInByb21pc2UiLCJzdG9wT25CYWRnZVVwZGF0ZUVycm9yIiwiY2F0Y2giLCJlcnIiLCJsb2dnZXIiLCJpbmZvIiwiZXJyb3IiLCJhdWRpZW5jZV9pZCIsImF1ZGllbmNlSWQiLCJ1cGRhdGVBdWRpZW5jZSIsImxhc3RVc2VkIiwiX190eXBlIiwiaXNvIiwidG9JU09TdHJpbmciLCJ0aW1lc1VzZWQiLCJoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCIsInB1c2hDb250cm9sbGVyUXVldWUiLCJlbnF1ZXVlIiwiZmFpbCIsImhhc0V4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvblRpbWVQYXJhbSIsImV4cGlyYXRpb25UaW1lIiwiaXNGaW5pdGUiLCJoYXNFeHBpcmF0aW9uSW50ZXJ2YWwiLCJleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSIsImhhc1B1c2hUaW1lIiwicHVzaFRpbWVQYXJhbSIsImlzTG9jYWxUaW1lIiwicHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudCIsIm9mZnNldFBhdHRlcm4iLCJpbmRleE9mIiwibGVuZ3RoIiwidGVzdCIsImlzb1N0cmluZyIsInN1YnN0cmluZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLGNBQU4sQ0FBcUI7O0FBRTFCQyxXQUFTQyxPQUFPLEVBQWhCLEVBQW9CQyxRQUFRLEVBQTVCLEVBQWdDQyxNQUFoQyxFQUF3Q0MsSUFBeEMsRUFBOENDLG9CQUFvQixNQUFNLENBQUUsQ0FBMUUsRUFBNEVDLE1BQU0sSUFBSUMsSUFBSixFQUFsRixFQUE4RjtBQUM1RixRQUFJLENBQUNKLE9BQU9LLGNBQVosRUFBNEI7QUFDMUIsWUFBTSxJQUFJQyxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKLDRCQURJLENBQU47QUFFRDs7QUFFRDtBQUNBVixTQUFLVyxlQUFMLEdBQXVCYixlQUFlYyxpQkFBZixDQUFpQ1osSUFBakMsQ0FBdkI7QUFDQUEsU0FBS2EsbUJBQUwsR0FBMkJmLGVBQWVnQixxQkFBZixDQUFxQ2QsSUFBckMsQ0FBM0I7QUFDQSxRQUFJQSxLQUFLVyxlQUFMLElBQXdCWCxLQUFLYSxtQkFBakMsRUFBc0Q7QUFDcEQsWUFBTSxJQUFJTCxZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRFIsRUFFSiw0REFGSSxDQUFOO0FBR0Q7O0FBRUQ7QUFDQSxRQUFJVixLQUFLYSxtQkFBTCxJQUE0QixDQUFDYixLQUFLZSxjQUFM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SlYsS0FBSyxXQUFMLElBQW9CLHFCQURoQixDQUFOO0FBRUQ7O0FBRUQsV0FBTztBQUNMb0IsVUFESztBQUVMdUQ7QUFGSyxLQUFQO0FBSUQ7O0FBRUQ7Ozs7O0FBS0EsU0FBT0MsNEJBQVAsQ0FBb0NGLGFBQXBDLEVBQW9FO0FBQ2xFLFVBQU1HLGdCQUFnQixzQkFBdEI7QUFDQSxXQUFPSCxjQUFjSSxPQUFkLENBQXNCLEdBQXRCLE1BQStCSixjQUFjSyxNQUFkLEdBQXVCLENBQXRELENBQXdEO0FBQXhELE9BQ0ZGLGNBQWNHLElBQWQsQ0FBbUJOLGFBQW5CLENBREwsQ0FGa0UsQ0FHMUI7QUFDekM7O0FBRUQ7Ozs7OztBQU1BLFNBQU9yRCxjQUFQLENBQXNCLEVBQUVELElBQUYsRUFBUXVELFdBQVIsRUFBdEIsRUFBbUY7QUFDakYsUUFBSUEsV0FBSixFQUFpQjtBQUFFO0FBQ2pCLFlBQU1NLFlBQVk3RCxLQUFLeUMsV0FBTCxFQUFsQjtBQUNBLGFBQU9vQixVQUFVQyxTQUFWLENBQW9CLENBQXBCLEVBQXVCRCxVQUFVSCxPQUFWLENBQWtCLEdBQWxCLENBQXZCLENBQVA7QUFDRDtBQUNELFdBQU8xRCxLQUFLeUMsV0FBTCxFQUFQO0FBQ0Q7QUExTXlCOztRQUFmL0QsYyxHQUFBQSxjO2tCQTZNRUEsYyIsImZpbGUiOiJQdXNoQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlIH0gICAgICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFJlc3RRdWVyeSAgICAgICAgICAgICAgZnJvbSAnLi4vUmVzdFF1ZXJ5JztcbmltcG9ydCBSZXN0V3JpdGUgICAgICAgICAgICAgIGZyb20gJy4uL1Jlc3RXcml0ZSc7XG5pbXBvcnQgeyBtYXN0ZXIgfSAgICAgICAgICAgICBmcm9tICcuLi9BdXRoJztcbmltcG9ydCB7IHB1c2hTdGF0dXNIYW5kbGVyIH0gIGZyb20gJy4uL1N0YXR1c0hhbmRsZXInO1xuaW1wb3J0IHsgYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyB9IGZyb20gJy4uL1B1c2gvdXRpbHMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gICAgICAgICAgICAgICBmcm9tICcuLi9sb2dnZXInO1xuXG5leHBvcnQgY2xhc3MgUHVzaENvbnRyb2xsZXIge1xuXG4gIHNlbmRQdXNoKGJvZHkgPSB7fSwgd2hlcmUgPSB7fSwgY29uZmlnLCBhdXRoLCBvblB1c2hTdGF0dXNTYXZlZCA9ICgpID0+IHt9LCBub3cgPSBuZXcgRGF0ZSgpKSB7XG4gICAgaWYgKCFjb25maWcuaGFzUHVzaFN1cHBvcnQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdNaXNzaW5nIHB1c2ggY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIFJlcGxhY2UgdGhlIGV4cGlyYXRpb25fdGltZSBhbmQgcHVzaF90aW1lIHdpdGggYSB2YWxpZCBVbml4IGVwb2NoIG1pbGxpc2Vjb25kcyB0aW1lXG4gICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uVGltZShib2R5KTtcbiAgICBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSk7XG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl90aW1lICYmIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdCb3RoIGV4cGlyYXRpb25fdGltZSBhbmQgZXhwaXJhdGlvbl9pbnRlcnZhbCBjYW5ub3QgYmUgc2V0Jyk7XG4gICAgfVxuXG4gICAgLy8gSW1tZWRpYXRlIHB1c2hcbiAgICBpZiAoYm9keS5leHBpcmF0aW9uX2ludGVydmFsICYmICFib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKSkge1xuICAgICAgY29uc3QgdHRsTXMgPSBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgKiAxMDAwO1xuICAgICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSAobmV3IERhdGUobm93LnZhbHVlT2YoKSArIHR0bE1zKSkudmFsdWVPZigpO1xuICAgIH1cblxuICAgIGNvbnN0IHB1c2hUaW1lID0gUHVzaENvbnRyb2xsZXIuZ2V0UHVzaFRpbWUoYm9keSk7XG4gICAgaWYgKHB1c2hUaW1lICYmIHB1c2hUaW1lLmRhdGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBib2R5WydwdXNoX3RpbWUnXSA9IFB1c2hDb250cm9sbGVyLmZvcm1hdFB1c2hUaW1lKHB1c2hUaW1lKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBJZiB0aGUgcmVxIGNhbiBwYXNzIHRoZSBjaGVja2luZywgd2UgcmV0dXJuIGltbWVkaWF0ZWx5IGluc3RlYWQgb2Ygd2FpdGluZ1xuICAgIC8vIHB1c2hlcyB0byBiZSBzZW50LiBXZSBwcm9iYWJseSBjaGFuZ2UgdGhpcyBiZWhhdmlvdXIgaW4gdGhlIGZ1dHVyZS5cbiAgICBsZXQgYmFkZ2VVcGRhdGUgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYgKGJvZHkuZGF0YSAmJiBib2R5LmRhdGEuYmFkZ2UpIHtcbiAgICAgIGNvbnN0IGJhZGdlID0gYm9keS5kYXRhLmJhZGdlO1xuICAgICAgbGV0IHJlc3RVcGRhdGUgPSB7fTtcbiAgICAgIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ3N0cmluZycgJiYgYmFkZ2UudG9Mb3dlckNhc2UoKSA9PT0gJ2luY3JlbWVudCcpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogMSB9IH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGJhZGdlID09ICdvYmplY3QnICYmIHR5cGVvZiBiYWRnZS5fX29wID09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICAgICAgIGJhZGdlLl9fb3AudG9Mb3dlckNhc2UoKSA9PSAnaW5jcmVtZW50JyAmJiBOdW1iZXIoYmFkZ2UuYW1vdW50KSkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBiYWRnZS5hbW91bnQgfSB9XG4gICAgICB9IGVsc2UgaWYgKE51bWJlcihiYWRnZSkpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IGJhZGdlIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IFwiSW52YWxpZCB2YWx1ZSBmb3IgYmFkZ2UsIGV4cGVjdGVkIG51bWJlciBvciAnSW5jcmVtZW50JyBvciB7aW5jcmVtZW50OiBudW1iZXJ9XCI7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvcmNlIGZpbHRlcmluZyBvbiBvbmx5IHZhbGlkIGRldmljZSB0b2tlbnNcbiAgICAgIGNvbnN0IHVwZGF0ZVdoZXJlID0gYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyh3aGVyZSk7XG4gICAgICBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgICAgLy8gQnVpbGQgYSByZWFsIFJlc3RRdWVyeSBzbyB3ZSBjYW4gdXNlIGl0IGluIFJlc3RXcml0ZVxuICAgICAgICBjb25zdCByZXN0UXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgdXBkYXRlV2hlcmUpO1xuICAgICAgICAvLyBjaGFuZ2UgJGV4aXN0cyBmb3IgJG5lIG51bGwgZm9yIGJldHRlciBwZXJmb3JtYW5jZVxuICAgICAgICBpZiAocmVzdFF1ZXJ5LnJlc3RXaGVyZSAmJiByZXN0UXVlcnkucmVzdFdoZXJlLmRldmljZVRva2VuICYmIHJlc3RRdWVyeS5yZXN0V2hlcmUuZGV2aWNlVG9rZW5bJyRleGlzdHMnXSkgcmVzdFF1ZXJ5LnJlc3RXaGVyZS5kZXZpY2VUb2tlbiA9IHskbmU6IG51bGx9XG4gICAgICAgIHJldHVybiByZXN0UXVlcnkuYnVpbGRSZXN0V2hlcmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICBjb25zdCB3cml0ZSA9IG5ldyBSZXN0V3JpdGUoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19JbnN0YWxsYXRpb24nLCByZXN0UXVlcnkucmVzdFdoZXJlLCByZXN0VXBkYXRlKTtcbiAgICAgICAgICB3cml0ZS5ydW5PcHRpb25zLm1hbnkgPSB0cnVlO1xuICAgICAgICAgIHJldHVybiB3cml0ZS5leGVjdXRlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBwdXNoU3RhdHVzID0gcHVzaFN0YXR1c0hhbmRsZXIoY29uZmlnKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5zZXRJbml0aWFsKGJvZHksIHdoZXJlKTtcbiAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgIG9uUHVzaFN0YXR1c1NhdmVkKHB1c2hTdGF0dXMub2JqZWN0SWQpO1xuICAgICAgY29uc3QgcHJvbWlzZSA9IGJhZGdlVXBkYXRlKCk7XG4gICAgICAvLyBhZGQgdGhpcyB0byBpZ25vcmUgYmFkZ2UgdXBkYXRlIGVycm9ycyBhcyBkZWZhdWx0XG4gICAgICBpZiAoIWNvbmZpZy5zdG9wT25CYWRnZVVwZGF0ZUVycm9yKSB7XG4gICAgICAgIHByb21pc2UuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICBsb2dnZXIuaW5mbyhgQmFkZ2UgdXBkYXRlIGVycm9yIHdpbGwgYmUgaWdub3JlZCBmb3IgcHVzaCBzdGF0dXMgJHtwdXNoU3RhdHVzLm9iamVjdElkfWApXG4gICAgICAgICAgbG9nZ2VyLmVycm9yKGVycilcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICAgIHJldHVybiBwcm9taXNlXG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAvLyBVcGRhdGUgYXVkaWVuY2UgbGFzdFVzZWQgYW5kIHRpbWVzVXNlZFxuICAgICAgaWYgKGJvZHkuYXVkaWVuY2VfaWQpIHtcbiAgICAgICAgY29uc3QgYXVkaWVuY2VJZCA9IGJvZHkuYXVkaWVuY2VfaWQ7XG5cbiAgICAgICAgdmFyIHVwZGF0ZUF1ZGllbmNlID0ge1xuICAgICAgICAgIGxhc3RVc2VkOiB7IF9fdHlwZTogXCJEYXRlXCIsIGlzbzogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH0sXG4gICAgICAgICAgdGltZXNVc2VkOiB7IF9fb3A6IFwiSW5jcmVtZW50XCIsIFwiYW1vdW50XCI6IDEgfVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB3cml0ZSA9IG5ldyBSZXN0V3JpdGUoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19BdWRpZW5jZScsIHtvYmplY3RJZDogYXVkaWVuY2VJZH0sIHVwZGF0ZUF1ZGllbmNlKTtcbiAgICAgICAgd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgfVxuICAgICAgLy8gRG9uJ3Qgd2FpdCBmb3IgdGhlIGF1ZGllbmNlIHVwZGF0ZSBwcm9taXNlIHRvIHJlc29sdmUuXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBpZiAoYm9keS5oYXNPd25Qcm9wZXJ0eSgncHVzaF90aW1lJykgJiYgY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0KSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb25maWcucHVzaENvbnRyb2xsZXJRdWV1ZS5lbnF1ZXVlKGJvZHksIHdoZXJlLCBjb25maWcsIGF1dGgsIHB1c2hTdGF0dXMpO1xuICAgIH0pLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIHJldHVybiBwdXNoU3RhdHVzLmZhaWwoZXJyKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGV4cGlyYXRpb24gdGltZSBmcm9tIHRoZSByZXF1ZXN0IGJvZHkuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSByZXF1ZXN0IEEgcmVxdWVzdCBvYmplY3RcbiAgICogQHJldHVybnMge051bWJlcnx1bmRlZmluZWR9IFRoZSBleHBpcmF0aW9uIHRpbWUgaWYgaXQgZXhpc3RzIGluIHRoZSByZXF1ZXN0XG4gICAqL1xuICBzdGF0aWMgZ2V0RXhwaXJhdGlvblRpbWUoYm9keSA9IHt9KSB7XG4gICAgdmFyIGhhc0V4cGlyYXRpb25UaW1lID0gYm9keS5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJhdGlvbl90aW1lJyk7XG4gICAgaWYgKCFoYXNFeHBpcmF0aW9uVGltZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgZXhwaXJhdGlvblRpbWVQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25fdGltZSddO1xuICAgIHZhciBleHBpcmF0aW9uVGltZTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25UaW1lUGFyYW0gPT09ICdudW1iZXInKSB7XG4gICAgICBleHBpcmF0aW9uVGltZSA9IG5ldyBEYXRlKGV4cGlyYXRpb25UaW1lUGFyYW0gKiAxMDAwKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsnZXhwaXJhdGlvbl90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cbiAgICAvLyBDaGVjayBleHBpcmF0aW9uVGltZSBpcyB2YWxpZCBvciBub3QsIGlmIGl0IGlzIG5vdCB2YWxpZCwgZXhwaXJhdGlvblRpbWUgaXMgTmFOXG4gICAgaWYgKCFpc0Zpbml0ZShleHBpcmF0aW9uVGltZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4cGlyYXRpb25UaW1lLnZhbHVlT2YoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSA9IHt9KSB7XG4gICAgY29uc3QgaGFzRXhwaXJhdGlvbkludGVydmFsID0gYm9keS5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJhdGlvbl9pbnRlcnZhbCcpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvbkludGVydmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtID0gYm9keVsnZXhwaXJhdGlvbl9pbnRlcnZhbCddO1xuICAgIGlmICh0eXBlb2YgZXhwaXJhdGlvbkludGVydmFsUGFyYW0gIT09ICdudW1iZXInIHx8IGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGBleHBpcmF0aW9uX2ludGVydmFsIG11c3QgYmUgYSBudW1iZXIgZ3JlYXRlciB0aGFuIDBgKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBwdXNoIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgcHVzaCB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldFB1c2hUaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNQdXNoVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpO1xuICAgIGlmICghaGFzUHVzaFRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHB1c2hUaW1lUGFyYW0gPSBib2R5WydwdXNoX3RpbWUnXTtcbiAgICB2YXIgZGF0ZTtcbiAgICB2YXIgaXNMb2NhbFRpbWUgPSB0cnVlO1xuXG4gICAgaWYgKHR5cGVvZiBwdXNoVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZGF0ZSA9IG5ldyBEYXRlKHB1c2hUaW1lUGFyYW0gKiAxMDAwKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwdXNoVGltZVBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgaXNMb2NhbFRpbWUgPSAhUHVzaENvbnRyb2xsZXIucHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudChwdXNoVGltZVBhcmFtKTtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cbiAgICAvLyBDaGVjayBwdXNoVGltZSBpcyB2YWxpZCBvciBub3QsIGlmIGl0IGlzIG5vdCB2YWxpZCwgcHVzaFRpbWUgaXMgTmFOXG4gICAgaWYgKCFpc0Zpbml0ZShkYXRlKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkYXRlLFxuICAgICAgaXNMb2NhbFRpbWUsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYSBJU084NjAxIGZvcm1hdHRlZCBkYXRlIGNvbnRhaW5zIGEgdGltZXpvbmUgY29tcG9uZW50XG4gICAqIEBwYXJhbSBwdXNoVGltZVBhcmFtIHtzdHJpbmd9XG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIHB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb2Zmc2V0UGF0dGVybiA9IC8oLispKFsrLV0pXFxkXFxkOlxcZFxcZCQvO1xuICAgIHJldHVybiBwdXNoVGltZVBhcmFtLmluZGV4T2YoJ1onKSA9PT0gcHVzaFRpbWVQYXJhbS5sZW5ndGggLSAxIC8vIDIwMDctMDQtMDVUMTI6MzBaXG4gICAgICB8fCBvZmZzZXRQYXR0ZXJuLnRlc3QocHVzaFRpbWVQYXJhbSk7IC8vIDIwMDctMDQtMDVUMTI6MzAuMDAwKzAyOjAwLCAyMDA3LTA0LTA1VDEyOjMwLjAwMC0wMjowMFxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgZGF0ZSB0byBJU08gZm9ybWF0IGluIFVUQyB0aW1lIGFuZCBzdHJpcHMgdGhlIHRpbWV6b25lIGlmIGBpc0xvY2FsVGltZWAgaXMgdHJ1ZVxuICAgKiBAcGFyYW0gZGF0ZSB7RGF0ZX1cbiAgICogQHBhcmFtIGlzTG9jYWxUaW1lIHtib29sZWFufVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgc3RhdGljIGZvcm1hdFB1c2hUaW1lKHsgZGF0ZSwgaXNMb2NhbFRpbWUgfTogeyBkYXRlOiBEYXRlLCBpc0xvY2FsVGltZTogYm9vbGVhbiB9KSB7XG4gICAgaWYgKGlzTG9jYWxUaW1lKSB7IC8vIFN0cmlwICdaJ1xuICAgICAgY29uc3QgaXNvU3RyaW5nID0gZGF0ZS50b0lTT1N0cmluZygpO1xuICAgICAgcmV0dXJuIGlzb1N0cmluZy5zdWJzdHJpbmcoMCwgaXNvU3RyaW5nLmluZGV4T2YoJ1onKSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRlLnRvSVNPU3RyaW5nKCk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVzaENvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ca05b338ff..861010fdf7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1231,25 +1231,25 @@ }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", "dev": true }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", "dev": true }, "babel-plugin-syntax-flow": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", "dev": true }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "dev": true }, @@ -5531,7 +5531,7 @@ "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha1-5IIb7vWyFCogJr1zkm/lN2McVAU=", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "requires": { "agent-base": "4.2.0", "debug": "3.1.0" @@ -5550,7 +5550,7 @@ "https-proxy-agent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha1-UVUpcPoE1yPgTFbQQXjD+SWSu8A=", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "requires": { "agent-base": "4.2.0", "debug": "3.1.0" @@ -6709,7 +6709,7 @@ "mailgun-js": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", - "integrity": "sha1-gf7QxmpBHT/2xDVIYa0hOHr8+qo=", + "integrity": "sha512-o0P6jjZlx5CQj12tvVgDTbgjTqVN0+5h6/6P1+3c6xmozVKBwniQ6Qt3MkCSF0+ueVTbobAfWyGpWRZMJu8t1g==", "requires": { "async": "2.6.0", "debug": "3.1.0", From 450192ca0ac7c9fe2b43838ff43b79ab21496596 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Wed, 26 Sep 2018 13:03:56 -0300 Subject: [PATCH 08/73] Fix ignore badge update error --- src/Controllers/PushController.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index f58fb67ad6..77829d216e 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -73,15 +73,12 @@ export class PushController { return pushStatus.setInitial(body, where); }).then(() => { onPushStatusSaved(pushStatus.objectId); - const promise = badgeUpdate(); + return badgeUpdate(); + }).catch(err => { // add this to ignore badge update errors as default - if (!config.stopOnBadgeUpdateError) { - promise.catch(err => { - logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`) - logger.error(err) - }) - } - return promise + if (config.stopOnBadgeUpdateError) throw err + logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`) + logger.error(err) }).then(() => { // Update audience lastUsed and timesUsed if (body.audience_id) { From 805e468d5a4f24b668c47d574aaa453898a75a34 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Thu, 27 Sep 2018 09:30:41 -0300 Subject: [PATCH 09/73] Fix ignore badge update error --- src/Controllers/PushController.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index 77829d216e..ee5242cb1e 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -78,7 +78,8 @@ export class PushController { // 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.error(err) + logger.info(err && err.stack && err.stack.toString() || err.toString()) + return Promise.resolve() }).then(() => { // Update audience lastUsed and timesUsed if (body.audience_id) { From bf63d1b7f9dc80d64dd27539c5cc860d8ff31498 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Thu, 27 Sep 2018 10:34:58 -0300 Subject: [PATCH 10/73] Fix ignore badge update error --- src/Controllers/PushController.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index ee5242cb1e..dff15322be 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -73,13 +73,9 @@ export class PushController { 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.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`) - logger.info(err && err.stack && err.stack.toString() || err.toString()) - return Promise.resolve() + if (config.stopOnBadgeUpdateError) return badgeUpdate(); + logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`); + return Promise.resolve(); }).then(() => { // Update audience lastUsed and timesUsed if (body.audience_id) { From 2dc05c1ef25e1533082c0fbb7c8682209895361c Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Thu, 27 Sep 2018 10:35:15 -0300 Subject: [PATCH 11/73] Fix ignore badge update error --- lib/Controllers/PushController.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js index 1a65f7260d..40d6340998 100644 --- a/lib/Controllers/PushController.js +++ b/lib/Controllers/PushController.js @@ -88,15 +88,9 @@ class PushController { return pushStatus.setInitial(body, where); }).then(() => { onPushStatusSaved(pushStatus.objectId); - const promise = badgeUpdate(); - // add this to ignore badge update errors as default - if (!config.stopOnBadgeUpdateError) { - promise.catch(err => { - _logger.logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`); - _logger.logger.error(err); - }); - } - return promise; + if (config.stopOnBadgeUpdateError) return badgeUpdate(); + _logger.logger.info(`Badge update error will be ignored for push status ${pushStatus.objectId}`); + return Promise.resolve(); }).then(() => { // Update audience lastUsed and timesUsed if (body.audience_id) { @@ -224,4 +218,4 @@ class PushController { exports.PushController = PushController; exports.default = PushController; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJyZXN0V2hlcmUiLCJkZXZpY2VUb2tlbiIsIiRuZSIsImJ1aWxkUmVzdFdoZXJlIiwidGhlbiIsIndyaXRlIiwiUmVzdFdyaXRlIiwicnVuT3B0aW9ucyIsIm1hbnkiLCJleGVjdXRlIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJvYmplY3RJZCIsInByb21pc2UiLCJzdG9wT25CYWRnZVVwZGF0ZUVycm9yIiwiY2F0Y2giLCJlcnIiLCJsb2dnZXIiLCJpbmZvIiwiZXJyb3IiLCJhdWRpZW5jZV9pZCIsImF1ZGllbmNlSWQiLCJ1cGRhdGVBdWRpZW5jZSIsImxhc3RVc2VkIiwiX190eXBlIiwiaXNvIiwidG9JU09TdHJpbmciLCJ0aW1lc1VzZWQiLCJoYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCIsInB1c2hDb250cm9sbGVyUXVldWUiLCJlbnF1ZXVlIiwiZmFpbCIsImhhc0V4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvblRpbWVQYXJhbSIsImV4cGlyYXRpb25UaW1lIiwiaXNGaW5pdGUiLCJoYXNFeHBpcmF0aW9uSW50ZXJ2YWwiLCJleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSIsImhhc1B1c2hUaW1lIiwicHVzaFRpbWVQYXJhbSIsImlzTG9jYWxUaW1lIiwicHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudCIsIm9mZnNldFBhdHRlcm4iLCJpbmRleE9mIiwibGVuZ3RoIiwidGVzdCIsImlzb1N0cmluZyIsInN1YnN0cmluZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLGNBQU4sQ0FBcUI7O0FBRTFCQyxXQUFTQyxPQUFPLEVBQWhCLEVBQW9CQyxRQUFRLEVBQTVCLEVBQWdDQyxNQUFoQyxFQUF3Q0MsSUFBeEMsRUFBOENDLG9CQUFvQixNQUFNLENBQUUsQ0FBMUUsRUFBNEVDLE1BQU0sSUFBSUMsSUFBSixFQUFsRixFQUE4RjtBQUM1RixRQUFJLENBQUNKLE9BQU9LLGNBQVosRUFBNEI7QUFDMUIsWUFBTSxJQUFJQyxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKLDRCQURJLENBQU47QUFFRDs7QUFFRDtBQUNBVixTQUFLVyxlQUFMLEdBQXVCYixlQUFlYyxpQkFBZixDQUFpQ1osSUFBakMsQ0FBdkI7QUFDQUEsU0FBS2EsbUJBQUwsR0FBMkJmLGVBQWVnQixxQkFBZixDQUFxQ2QsSUFBckMsQ0FBM0I7QUFDQSxRQUFJQSxLQUFLVyxlQUFMLElBQXdCWCxLQUFLYSxtQkFBakMsRUFBc0Q7QUFDcEQsWUFBTSxJQUFJTCxZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRFIsRUFFSiw0REFGSSxDQUFOO0FBR0Q7O0FBRUQ7QUFDQSxRQUFJVixLQUFLYSxtQkFBTCxJQUE0QixDQUFDYixLQUFLZSxjQUFM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SlYsS0FBSyxXQUFMLElBQW9CLHFCQURoQixDQUFOO0FBRUQ7O0FBRUQsV0FBTztBQUNMb0IsVUFESztBQUVMdUQ7QUFGSyxLQUFQO0FBSUQ7O0FBRUQ7Ozs7O0FBS0EsU0FBT0MsNEJBQVAsQ0FBb0NGLGFBQXBDLEVBQW9FO0FBQ2xFLFVBQU1HLGdCQUFnQixzQkFBdEI7QUFDQSxXQUFPSCxjQUFjSSxPQUFkLENBQXNCLEdBQXRCLE1BQStCSixjQUFjSyxNQUFkLEdBQXVCLENBQXRELENBQXdEO0FBQXhELE9BQ0ZGLGNBQWNHLElBQWQsQ0FBbUJOLGFBQW5CLENBREwsQ0FGa0UsQ0FHMUI7QUFDekM7O0FBRUQ7Ozs7OztBQU1BLFNBQU9yRCxjQUFQLENBQXNCLEVBQUVELElBQUYsRUFBUXVELFdBQVIsRUFBdEIsRUFBbUY7QUFDakYsUUFBSUEsV0FBSixFQUFpQjtBQUFFO0FBQ2pCLFlBQU1NLFlBQVk3RCxLQUFLeUMsV0FBTCxFQUFsQjtBQUNBLGFBQU9vQixVQUFVQyxTQUFWLENBQW9CLENBQXBCLEVBQXVCRCxVQUFVSCxPQUFWLENBQWtCLEdBQWxCLENBQXZCLENBQVA7QUFDRDtBQUNELFdBQU8xRCxLQUFLeUMsV0FBTCxFQUFQO0FBQ0Q7QUExTXlCOztRQUFmL0QsYyxHQUFBQSxjO2tCQTZNRUEsYyIsImZpbGUiOiJQdXNoQ29udHJvbGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlIH0gICAgICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFJlc3RRdWVyeSAgICAgICAgICAgICAgZnJvbSAnLi4vUmVzdFF1ZXJ5JztcbmltcG9ydCBSZXN0V3JpdGUgICAgICAgICAgICAgIGZyb20gJy4uL1Jlc3RXcml0ZSc7XG5pbXBvcnQgeyBtYXN0ZXIgfSAgICAgICAgICAgICBmcm9tICcuLi9BdXRoJztcbmltcG9ydCB7IHB1c2hTdGF0dXNIYW5kbGVyIH0gIGZyb20gJy4uL1N0YXR1c0hhbmRsZXInO1xuaW1wb3J0IHsgYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyB9IGZyb20gJy4uL1B1c2gvdXRpbHMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gICAgICAgICAgICAgICBmcm9tICcuLi9sb2dnZXInO1xuXG5leHBvcnQgY2xhc3MgUHVzaENvbnRyb2xsZXIge1xuXG4gIHNlbmRQdXNoKGJvZHkgPSB7fSwgd2hlcmUgPSB7fSwgY29uZmlnLCBhdXRoLCBvblB1c2hTdGF0dXNTYXZlZCA9ICgpID0+IHt9LCBub3cgPSBuZXcgRGF0ZSgpKSB7XG4gICAgaWYgKCFjb25maWcuaGFzUHVzaFN1cHBvcnQpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdNaXNzaW5nIHB1c2ggY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIFJlcGxhY2UgdGhlIGV4cGlyYXRpb25fdGltZSBhbmQgcHVzaF90aW1lIHdpdGggYSB2YWxpZCBVbml4IGVwb2NoIG1pbGxpc2Vjb25kcyB0aW1lXG4gICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uVGltZShib2R5KTtcbiAgICBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgPSBQdXNoQ29udHJvbGxlci5nZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSk7XG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl90aW1lICYmIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgICdCb3RoIGV4cGlyYXRpb25fdGltZSBhbmQgZXhwaXJhdGlvbl9pbnRlcnZhbCBjYW5ub3QgYmUgc2V0Jyk7XG4gICAgfVxuXG4gICAgLy8gSW1tZWRpYXRlIHB1c2hcbiAgICBpZiAoYm9keS5leHBpcmF0aW9uX2ludGVydmFsICYmICFib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKSkge1xuICAgICAgY29uc3QgdHRsTXMgPSBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgKiAxMDAwO1xuICAgICAgYm9keS5leHBpcmF0aW9uX3RpbWUgPSAobmV3IERhdGUobm93LnZhbHVlT2YoKSArIHR0bE1zKSkudmFsdWVPZigpO1xuICAgIH1cblxuICAgIGNvbnN0IHB1c2hUaW1lID0gUHVzaENvbnRyb2xsZXIuZ2V0UHVzaFRpbWUoYm9keSk7XG4gICAgaWYgKHB1c2hUaW1lICYmIHB1c2hUaW1lLmRhdGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBib2R5WydwdXNoX3RpbWUnXSA9IFB1c2hDb250cm9sbGVyLmZvcm1hdFB1c2hUaW1lKHB1c2hUaW1lKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBJZiB0aGUgcmVxIGNhbiBwYXNzIHRoZSBjaGVja2luZywgd2UgcmV0dXJuIGltbWVkaWF0ZWx5IGluc3RlYWQgb2Ygd2FpdGluZ1xuICAgIC8vIHB1c2hlcyB0byBiZSBzZW50LiBXZSBwcm9iYWJseSBjaGFuZ2UgdGhpcyBiZWhhdmlvdXIgaW4gdGhlIGZ1dHVyZS5cbiAgICBsZXQgYmFkZ2VVcGRhdGUgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYgKGJvZHkuZGF0YSAmJiBib2R5LmRhdGEuYmFkZ2UpIHtcbiAgICAgIGNvbnN0IGJhZGdlID0gYm9keS5kYXRhLmJhZGdlO1xuICAgICAgbGV0IHJlc3RVcGRhdGUgPSB7fTtcbiAgICAgIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ3N0cmluZycgJiYgYmFkZ2UudG9Mb3dlckNhc2UoKSA9PT0gJ2luY3JlbWVudCcpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogMSB9IH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGJhZGdlID09ICdvYmplY3QnICYmIHR5cGVvZiBiYWRnZS5fX29wID09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICAgICAgIGJhZGdlLl9fb3AudG9Mb3dlckNhc2UoKSA9PSAnaW5jcmVtZW50JyAmJiBOdW1iZXIoYmFkZ2UuYW1vdW50KSkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiBiYWRnZS5hbW91bnQgfSB9XG4gICAgICB9IGVsc2UgaWYgKE51bWJlcihiYWRnZSkpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IGJhZGdlIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IFwiSW52YWxpZCB2YWx1ZSBmb3IgYmFkZ2UsIGV4cGVjdGVkIG51bWJlciBvciAnSW5jcmVtZW50JyBvciB7aW5jcmVtZW50OiBudW1iZXJ9XCI7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvcmNlIGZpbHRlcmluZyBvbiBvbmx5IHZhbGlkIGRldmljZSB0b2tlbnNcbiAgICAgIGNvbnN0IHVwZGF0ZVdoZXJlID0gYXBwbHlEZXZpY2VUb2tlbkV4aXN0cyh3aGVyZSk7XG4gICAgICBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgICAgLy8gQnVpbGQgYSByZWFsIFJlc3RRdWVyeSBzbyB3ZSBjYW4gdXNlIGl0IGluIFJlc3RXcml0ZVxuICAgICAgICBjb25zdCByZXN0UXVlcnkgPSBuZXcgUmVzdFF1ZXJ5KGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgdXBkYXRlV2hlcmUpO1xuICAgICAgICAvLyBjaGFuZ2UgJGV4aXN0cyBmb3IgJG5lIG51bGwgZm9yIGJldHRlciBwZXJmb3JtYW5jZVxuICAgICAgICBpZiAocmVzdFF1ZXJ5LnJlc3RXaGVyZSAmJiByZXN0UXVlcnkucmVzdFdoZXJlLmRldmljZVRva2VuICYmIHJlc3RRdWVyeS5yZXN0V2hlcmUuZGV2aWNlVG9rZW5bJyRleGlzdHMnXSkgcmVzdFF1ZXJ5LnJlc3RXaGVyZS5kZXZpY2VUb2tlbiA9IHskbmU6IG51bGx9XG4gICAgICAgIHJldHVybiByZXN0UXVlcnkuYnVpbGRSZXN0V2hlcmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICBjb25zdCB3cml0ZSA9IG5ldyBSZXN0V3JpdGUoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19JbnN0YWxsYXRpb24nLCByZXN0UXVlcnkucmVzdFdoZXJlLCByZXN0VXBkYXRlKTtcbiAgICAgICAgICB3cml0ZS5ydW5PcHRpb25zLm1hbnkgPSB0cnVlO1xuICAgICAgICAgIHJldHVybiB3cml0ZS5leGVjdXRlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBwdXNoU3RhdHVzID0gcHVzaFN0YXR1c0hhbmRsZXIoY29uZmlnKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5zZXRJbml0aWFsKGJvZHksIHdoZXJlKTtcbiAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgIG9uUHVzaFN0YXR1c1NhdmVkKHB1c2hTdGF0dXMub2JqZWN0SWQpO1xuICAgICAgY29uc3QgcHJvbWlzZSA9IGJhZGdlVXBkYXRlKCk7XG4gICAgICAvLyBhZGQgdGhpcyB0byBpZ25vcmUgYmFkZ2UgdXBkYXRlIGVycm9ycyBhcyBkZWZhdWx0XG4gICAgICBpZiAoIWNvbmZpZy5zdG9wT25CYWRnZVVwZGF0ZUVycm9yKSB7XG4gICAgICAgIHByb21pc2UuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICBsb2dnZXIuaW5mbyhgQmFkZ2UgdXBkYXRlIGVycm9yIHdpbGwgYmUgaWdub3JlZCBmb3IgcHVzaCBzdGF0dXMgJHtwdXNoU3RhdHVzLm9iamVjdElkfWApXG4gICAgICAgICAgbG9nZ2VyLmVycm9yKGVycilcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICAgIHJldHVybiBwcm9taXNlXG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAvLyBVcGRhdGUgYXVkaWVuY2UgbGFzdFVzZWQgYW5kIHRpbWVzVXNlZFxuICAgICAgaWYgKGJvZHkuYXVkaWVuY2VfaWQpIHtcbiAgICAgICAgY29uc3QgYXVkaWVuY2VJZCA9IGJvZHkuYXVkaWVuY2VfaWQ7XG5cbiAgICAgICAgdmFyIHVwZGF0ZUF1ZGllbmNlID0ge1xuICAgICAgICAgIGxhc3RVc2VkOiB7IF9fdHlwZTogXCJEYXRlXCIsIGlzbzogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH0sXG4gICAgICAgICAgdGltZXNVc2VkOiB7IF9fb3A6IFwiSW5jcmVtZW50XCIsIFwiYW1vdW50XCI6IDEgfVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB3cml0ZSA9IG5ldyBSZXN0V3JpdGUoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19BdWRpZW5jZScsIHtvYmplY3RJZDogYXVkaWVuY2VJZH0sIHVwZGF0ZUF1ZGllbmNlKTtcbiAgICAgICAgd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgfVxuICAgICAgLy8gRG9uJ3Qgd2FpdCBmb3IgdGhlIGF1ZGllbmNlIHVwZGF0ZSBwcm9taXNlIHRvIHJlc29sdmUuXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBpZiAoYm9keS5oYXNPd25Qcm9wZXJ0eSgncHVzaF90aW1lJykgJiYgY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0KSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb25maWcucHVzaENvbnRyb2xsZXJRdWV1ZS5lbnF1ZXVlKGJvZHksIHdoZXJlLCBjb25maWcsIGF1dGgsIHB1c2hTdGF0dXMpO1xuICAgIH0pLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIHJldHVybiBwdXNoU3RhdHVzLmZhaWwoZXJyKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGV4cGlyYXRpb24gdGltZSBmcm9tIHRoZSByZXF1ZXN0IGJvZHkuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSByZXF1ZXN0IEEgcmVxdWVzdCBvYmplY3RcbiAgICogQHJldHVybnMge051bWJlcnx1bmRlZmluZWR9IFRoZSBleHBpcmF0aW9uIHRpbWUgaWYgaXQgZXhpc3RzIGluIHRoZSByZXF1ZXN0XG4gICAqL1xuICBzdGF0aWMgZ2V0RXhwaXJhdGlvblRpbWUoYm9keSA9IHt9KSB7XG4gICAgdmFyIGhhc0V4cGlyYXRpb25UaW1lID0gYm9keS5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJhdGlvbl90aW1lJyk7XG4gICAgaWYgKCFoYXNFeHBpcmF0aW9uVGltZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgZXhwaXJhdGlvblRpbWVQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25fdGltZSddO1xuICAgIHZhciBleHBpcmF0aW9uVGltZTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25UaW1lUGFyYW0gPT09ICdudW1iZXInKSB7XG4gICAgICBleHBpcmF0aW9uVGltZSA9IG5ldyBEYXRlKGV4cGlyYXRpb25UaW1lUGFyYW0gKiAxMDAwKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsnZXhwaXJhdGlvbl90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cbiAgICAvLyBDaGVjayBleHBpcmF0aW9uVGltZSBpcyB2YWxpZCBvciBub3QsIGlmIGl0IGlzIG5vdCB2YWxpZCwgZXhwaXJhdGlvblRpbWUgaXMgTmFOXG4gICAgaWYgKCFpc0Zpbml0ZShleHBpcmF0aW9uVGltZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4cGlyYXRpb25UaW1lLnZhbHVlT2YoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSA9IHt9KSB7XG4gICAgY29uc3QgaGFzRXhwaXJhdGlvbkludGVydmFsID0gYm9keS5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJhdGlvbl9pbnRlcnZhbCcpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvbkludGVydmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtID0gYm9keVsnZXhwaXJhdGlvbl9pbnRlcnZhbCddO1xuICAgIGlmICh0eXBlb2YgZXhwaXJhdGlvbkludGVydmFsUGFyYW0gIT09ICdudW1iZXInIHx8IGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGBleHBpcmF0aW9uX2ludGVydmFsIG11c3QgYmUgYSBudW1iZXIgZ3JlYXRlciB0aGFuIDBgKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBwdXNoIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgcHVzaCB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldFB1c2hUaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNQdXNoVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpO1xuICAgIGlmICghaGFzUHVzaFRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHB1c2hUaW1lUGFyYW0gPSBib2R5WydwdXNoX3RpbWUnXTtcbiAgICB2YXIgZGF0ZTtcbiAgICB2YXIgaXNMb2NhbFRpbWUgPSB0cnVlO1xuXG4gICAgaWYgKHR5cGVvZiBwdXNoVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZGF0ZSA9IG5ldyBEYXRlKHB1c2hUaW1lUGFyYW0gKiAxMDAwKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwdXNoVGltZVBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgaXNMb2NhbFRpbWUgPSAhUHVzaENvbnRyb2xsZXIucHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudChwdXNoVGltZVBhcmFtKTtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cbiAgICAvLyBDaGVjayBwdXNoVGltZSBpcyB2YWxpZCBvciBub3QsIGlmIGl0IGlzIG5vdCB2YWxpZCwgcHVzaFRpbWUgaXMgTmFOXG4gICAgaWYgKCFpc0Zpbml0ZShkYXRlKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkYXRlLFxuICAgICAgaXNMb2NhbFRpbWUsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYSBJU084NjAxIGZvcm1hdHRlZCBkYXRlIGNvbnRhaW5zIGEgdGltZXpvbmUgY29tcG9uZW50XG4gICAqIEBwYXJhbSBwdXNoVGltZVBhcmFtIHtzdHJpbmd9XG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIHB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb2Zmc2V0UGF0dGVybiA9IC8oLispKFsrLV0pXFxkXFxkOlxcZFxcZCQvO1xuICAgIHJldHVybiBwdXNoVGltZVBhcmFtLmluZGV4T2YoJ1onKSA9PT0gcHVzaFRpbWVQYXJhbS5sZW5ndGggLSAxIC8vIDIwMDctMDQtMDVUMTI6MzBaXG4gICAgICB8fCBvZmZzZXRQYXR0ZXJuLnRlc3QocHVzaFRpbWVQYXJhbSk7IC8vIDIwMDctMDQtMDVUMTI6MzAuMDAwKzAyOjAwLCAyMDA3LTA0LTA1VDEyOjMwLjAwMC0wMjowMFxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgZGF0ZSB0byBJU08gZm9ybWF0IGluIFVUQyB0aW1lIGFuZCBzdHJpcHMgdGhlIHRpbWV6b25lIGlmIGBpc0xvY2FsVGltZWAgaXMgdHJ1ZVxuICAgKiBAcGFyYW0gZGF0ZSB7RGF0ZX1cbiAgICogQHBhcmFtIGlzTG9jYWxUaW1lIHtib29sZWFufVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgc3RhdGljIGZvcm1hdFB1c2hUaW1lKHsgZGF0ZSwgaXNMb2NhbFRpbWUgfTogeyBkYXRlOiBEYXRlLCBpc0xvY2FsVGltZTogYm9vbGVhbiB9KSB7XG4gICAgaWYgKGlzTG9jYWxUaW1lKSB7IC8vIFN0cmlwICdaJ1xuICAgICAgY29uc3QgaXNvU3RyaW5nID0gZGF0ZS50b0lTT1N0cmluZygpO1xuICAgICAgcmV0dXJuIGlzb1N0cmluZy5zdWJzdHJpbmcoMCwgaXNvU3RyaW5nLmluZGV4T2YoJ1onKSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRlLnRvSVNPU3RyaW5nKCk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVzaENvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJyZXN0V2hlcmUiLCJkZXZpY2VUb2tlbiIsIiRuZSIsImJ1aWxkUmVzdFdoZXJlIiwidGhlbiIsIndyaXRlIiwiUmVzdFdyaXRlIiwicnVuT3B0aW9ucyIsIm1hbnkiLCJleGVjdXRlIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJvYmplY3RJZCIsInN0b3BPbkJhZGdlVXBkYXRlRXJyb3IiLCJsb2dnZXIiLCJpbmZvIiwiYXVkaWVuY2VfaWQiLCJhdWRpZW5jZUlkIiwidXBkYXRlQXVkaWVuY2UiLCJsYXN0VXNlZCIsIl9fdHlwZSIsImlzbyIsInRvSVNPU3RyaW5nIiwidGltZXNVc2VkIiwiaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQiLCJwdXNoQ29udHJvbGxlclF1ZXVlIiwiZW5xdWV1ZSIsImNhdGNoIiwiZXJyIiwiZmFpbCIsImhhc0V4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvblRpbWVQYXJhbSIsImV4cGlyYXRpb25UaW1lIiwiaXNGaW5pdGUiLCJoYXNFeHBpcmF0aW9uSW50ZXJ2YWwiLCJleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSIsImhhc1B1c2hUaW1lIiwicHVzaFRpbWVQYXJhbSIsImlzTG9jYWxUaW1lIiwicHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudCIsIm9mZnNldFBhdHRlcm4iLCJpbmRleE9mIiwibGVuZ3RoIiwidGVzdCIsImlzb1N0cmluZyIsInN1YnN0cmluZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLGNBQU4sQ0FBcUI7O0FBRTFCQyxXQUFTQyxPQUFPLEVBQWhCLEVBQW9CQyxRQUFRLEVBQTVCLEVBQWdDQyxNQUFoQyxFQUF3Q0MsSUFBeEMsRUFBOENDLG9CQUFvQixNQUFNLENBQUUsQ0FBMUUsRUFBNEVDLE1BQU0sSUFBSUMsSUFBSixFQUFsRixFQUE4RjtBQUM1RixRQUFJLENBQUNKLE9BQU9LLGNBQVosRUFBNEI7QUFDMUIsWUFBTSxJQUFJQyxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKLDRCQURJLENBQU47QUFFRDs7QUFFRDtBQUNBVixTQUFLVyxlQUFMLEdBQXVCYixlQUFlYyxpQkFBZixDQUFpQ1osSUFBakMsQ0FBdkI7QUFDQUEsU0FBS2EsbUJBQUwsR0FBMkJmLGVBQWVnQixxQkFBZixDQUFxQ2QsSUFBckMsQ0FBM0I7QUFDQSxRQUFJQSxLQUFLVyxlQUFMLElBQXdCWCxLQUFLYSxtQkFBakMsRUFBc0Q7QUFDcEQsWUFBTSxJQUFJTCxZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRFIsRUFFSiw0REFGSSxDQUFOO0FBR0Q7O0FBRUQ7QUFDQSxRQUFJVixLQUFLYSxtQkFBTCxJQUE0QixDQUFDYixLQUFLZSxjQUFMLENBQW9CLFdBQXBCLENBQWpD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QU9DLDRCQUFQLENBQW9DRixhQUFwQyxFQUFvRTtBQUNsRSxVQUFNRyxnQkFBZ0Isc0JBQXRCO0FBQ0EsV0FBT0gsY0FBY0ksT0FBZCxDQUFzQixHQUF0QixNQUErQkosY0FBY0ssTUFBZCxHQUF1QixDQUF0RCxDQUF3RDtBQUF4RCxPQUNGRixjQUFjRyxJQUFkLENBQW1CTixhQUFuQixDQURMLENBRmtFLENBRzFCO0FBQ3pDOztBQUVEOzs7Ozs7QUFNQSxTQUFPbkQsY0FBUCxDQUFzQixFQUFFRCxJQUFGLEVBQVFxRCxXQUFSLEVBQXRCLEVBQW1GO0FBQ2pGLFFBQUlBLFdBQUosRUFBaUI7QUFBRTtBQUNqQixZQUFNTSxZQUFZM0QsS0FBS3FDLFdBQUwsRUFBbEI7QUFDQSxhQUFPc0IsVUFBVUMsU0FBVixDQUFvQixDQUFwQixFQUF1QkQsVUFBVUgsT0FBVixDQUFrQixHQUFsQixDQUF2QixDQUFQO0FBQ0Q7QUFDRCxXQUFPeEQsS0FBS3FDLFdBQUwsRUFBUDtBQUNEO0FBcE15Qjs7UUFBZjNELGMsR0FBQUEsYztrQkF1TUVBLGMiLCJmaWxlIjoiUHVzaENvbnRyb2xsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9ICAgICAgICAgICAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBSZXN0UXVlcnkgICAgICAgICAgICAgIGZyb20gJy4uL1Jlc3RRdWVyeSc7XG5pbXBvcnQgUmVzdFdyaXRlICAgICAgICAgICAgICBmcm9tICcuLi9SZXN0V3JpdGUnO1xuaW1wb3J0IHsgbWFzdGVyIH0gICAgICAgICAgICAgZnJvbSAnLi4vQXV0aCc7XG5pbXBvcnQgeyBwdXNoU3RhdHVzSGFuZGxlciB9ICBmcm9tICcuLi9TdGF0dXNIYW5kbGVyJztcbmltcG9ydCB7IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMgfSBmcm9tICcuLi9QdXNoL3V0aWxzJztcbmltcG9ydCB7IGxvZ2dlciB9ICAgICAgICAgICAgICAgZnJvbSAnLi4vbG9nZ2VyJztcblxuZXhwb3J0IGNsYXNzIFB1c2hDb250cm9sbGVyIHtcblxuICBzZW5kUHVzaChib2R5ID0ge30sIHdoZXJlID0ge30sIGNvbmZpZywgYXV0aCwgb25QdXNoU3RhdHVzU2F2ZWQgPSAoKSA9PiB7fSwgbm93ID0gbmV3IERhdGUoKSkge1xuICAgIGlmICghY29uZmlnLmhhc1B1c2hTdXBwb3J0KSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnTWlzc2luZyBwdXNoIGNvbmZpZ3VyYXRpb24nKTtcbiAgICB9XG5cbiAgICAvLyBSZXBsYWNlIHRoZSBleHBpcmF0aW9uX3RpbWUgYW5kIHB1c2hfdGltZSB3aXRoIGEgdmFsaWQgVW5peCBlcG9jaCBtaWxsaXNlY29uZHMgdGltZVxuICAgIGJvZHkuZXhwaXJhdGlvbl90aW1lID0gUHVzaENvbnRyb2xsZXIuZ2V0RXhwaXJhdGlvblRpbWUoYm9keSk7XG4gICAgYm9keS5leHBpcmF0aW9uX2ludGVydmFsID0gUHVzaENvbnRyb2xsZXIuZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkpO1xuICAgIGlmIChib2R5LmV4cGlyYXRpb25fdGltZSAmJiBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnQm90aCBleHBpcmF0aW9uX3RpbWUgYW5kIGV4cGlyYXRpb25faW50ZXJ2YWwgY2Fubm90IGJlIHNldCcpO1xuICAgIH1cblxuICAgIC8vIEltbWVkaWF0ZSBwdXNoXG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCAmJiAhYm9keS5oYXNPd25Qcm9wZXJ0eSgncHVzaF90aW1lJykpIHtcbiAgICAgIGNvbnN0IHR0bE1zID0gYm9keS5leHBpcmF0aW9uX2ludGVydmFsICogMTAwMDtcbiAgICAgIGJvZHkuZXhwaXJhdGlvbl90aW1lID0gKG5ldyBEYXRlKG5vdy52YWx1ZU9mKCkgKyB0dGxNcykpLnZhbHVlT2YoKTtcbiAgICB9XG5cbiAgICBjb25zdCBwdXNoVGltZSA9IFB1c2hDb250cm9sbGVyLmdldFB1c2hUaW1lKGJvZHkpO1xuICAgIGlmIChwdXNoVGltZSAmJiBwdXNoVGltZS5kYXRlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgYm9keVsncHVzaF90aW1lJ10gPSBQdXNoQ29udHJvbGxlci5mb3JtYXRQdXNoVGltZShwdXNoVGltZSk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogSWYgdGhlIHJlcSBjYW4gcGFzcyB0aGUgY2hlY2tpbmcsIHdlIHJldHVybiBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIHdhaXRpbmdcbiAgICAvLyBwdXNoZXMgdG8gYmUgc2VudC4gV2UgcHJvYmFibHkgY2hhbmdlIHRoaXMgYmVoYXZpb3VyIGluIHRoZSBmdXR1cmUuXG4gICAgbGV0IGJhZGdlVXBkYXRlID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIGlmIChib2R5LmRhdGEgJiYgYm9keS5kYXRhLmJhZGdlKSB7XG4gICAgICBjb25zdCBiYWRnZSA9IGJvZHkuZGF0YS5iYWRnZTtcbiAgICAgIGxldCByZXN0VXBkYXRlID0ge307XG4gICAgICBpZiAodHlwZW9mIGJhZGdlID09ICdzdHJpbmcnICYmIGJhZGdlLnRvTG93ZXJDYXNlKCkgPT09ICdpbmNyZW1lbnQnKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiB7IF9fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IDEgfSB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBiYWRnZSA9PSAnb2JqZWN0JyAmJiB0eXBlb2YgYmFkZ2UuX19vcCA9PSAnc3RyaW5nJyAmJlxuICAgICAgICAgICAgICAgICBiYWRnZS5fX29wLnRvTG93ZXJDYXNlKCkgPT0gJ2luY3JlbWVudCcgJiYgTnVtYmVyKGJhZGdlLmFtb3VudCkpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogYmFkZ2UuYW1vdW50IH0gfVxuICAgICAgfSBlbHNlIGlmIChOdW1iZXIoYmFkZ2UpKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiBiYWRnZSB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBcIkludmFsaWQgdmFsdWUgZm9yIGJhZGdlLCBleHBlY3RlZCBudW1iZXIgb3IgJ0luY3JlbWVudCcgb3Ige2luY3JlbWVudDogbnVtYmVyfVwiO1xuICAgICAgfVxuXG4gICAgICAvLyBGb3JjZSBmaWx0ZXJpbmcgb24gb25seSB2YWxpZCBkZXZpY2UgdG9rZW5zXG4gICAgICBjb25zdCB1cGRhdGVXaGVyZSA9IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMod2hlcmUpO1xuICAgICAgYmFkZ2VVcGRhdGUgPSAoKSA9PiB7XG4gICAgICAgIC8vIEJ1aWxkIGEgcmVhbCBSZXN0UXVlcnkgc28gd2UgY2FuIHVzZSBpdCBpbiBSZXN0V3JpdGVcbiAgICAgICAgY29uc3QgcmVzdFF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShjb25maWcsIG1hc3Rlcihjb25maWcpLCAnX0luc3RhbGxhdGlvbicsIHVwZGF0ZVdoZXJlKTtcbiAgICAgICAgLy8gY2hhbmdlICRleGlzdHMgZm9yICRuZSBudWxsIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICAgICAgaWYgKHJlc3RRdWVyeS5yZXN0V2hlcmUgJiYgcmVzdFF1ZXJ5LnJlc3RXaGVyZS5kZXZpY2VUb2tlbiAmJiByZXN0UXVlcnkucmVzdFdoZXJlLmRldmljZVRva2VuWyckZXhpc3RzJ10pIHJlc3RRdWVyeS5yZXN0V2hlcmUuZGV2aWNlVG9rZW4gPSB7JG5lOiBudWxsfVxuICAgICAgICByZXR1cm4gcmVzdFF1ZXJ5LmJ1aWxkUmVzdFdoZXJlKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgcmVzdFF1ZXJ5LnJlc3RXaGVyZSwgcmVzdFVwZGF0ZSk7XG4gICAgICAgICAgd3JpdGUucnVuT3B0aW9ucy5tYW55ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcHVzaFN0YXR1cyA9IHB1c2hTdGF0dXNIYW5kbGVyKGNvbmZpZyk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHB1c2hTdGF0dXMuc2V0SW5pdGlhbChib2R5LCB3aGVyZSk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBvblB1c2hTdGF0dXNTYXZlZChwdXNoU3RhdHVzLm9iamVjdElkKTtcbiAgICAgIGlmIChjb25maWcuc3RvcE9uQmFkZ2VVcGRhdGVFcnJvcikgcmV0dXJuIGJhZGdlVXBkYXRlKCk7XG4gICAgICBsb2dnZXIuaW5mbyhgQmFkZ2UgdXBkYXRlIGVycm9yIHdpbGwgYmUgaWdub3JlZCBmb3IgcHVzaCBzdGF0dXMgJHtwdXNoU3RhdHVzLm9iamVjdElkfWApO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gVXBkYXRlIGF1ZGllbmNlIGxhc3RVc2VkIGFuZCB0aW1lc1VzZWRcbiAgICAgIGlmIChib2R5LmF1ZGllbmNlX2lkKSB7XG4gICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgIHZhciB1cGRhdGVBdWRpZW5jZSA9IHtcbiAgICAgICAgICBsYXN0VXNlZDogeyBfX3R5cGU6IFwiRGF0ZVwiLCBpc286IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSB9LFxuICAgICAgICAgIHRpbWVzVXNlZDogeyBfX29wOiBcIkluY3JlbWVudFwiLCBcImFtb3VudFwiOiAxIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfQXVkaWVuY2UnLCB7b2JqZWN0SWQ6IGF1ZGllbmNlSWR9LCB1cGRhdGVBdWRpZW5jZSk7XG4gICAgICAgIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgIH1cbiAgICAgIC8vIERvbid0IHdhaXQgZm9yIHRoZSBhdWRpZW5jZSB1cGRhdGUgcHJvbWlzZSB0byByZXNvbHZlLlxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpICYmIGNvbmZpZy5oYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShib2R5LCB3aGVyZSwgY29uZmlnLCBhdXRoLCBwdXNoU3RhdHVzKTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5mYWlsKGVycikudGhlbigoKSA9PiB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBleHBpcmF0aW9uIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgZXhwaXJhdGlvbiB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldEV4cGlyYXRpb25UaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNFeHBpcmF0aW9uVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25fdGltZScpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvblRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV4cGlyYXRpb25UaW1lUGFyYW0gPSBib2R5WydleHBpcmF0aW9uX3RpbWUnXTtcbiAgICB2YXIgZXhwaXJhdGlvblRpbWU7XG4gICAgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwaXJhdGlvblRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGV4cGlyYXRpb25UaW1lID0gbmV3IERhdGUoZXhwaXJhdGlvblRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZXhwaXJhdGlvblRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIGV4cGlyYXRpb25UaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZXhwaXJhdGlvblRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBib2R5WydleHBpcmF0aW9uX3RpbWUnXSArICcgaXMgbm90IHZhbGlkIHRpbWUuJyk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uVGltZS52YWx1ZU9mKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkgPSB7fSkge1xuICAgIGNvbnN0IGhhc0V4cGlyYXRpb25JbnRlcnZhbCA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25faW50ZXJ2YWwnKTtcbiAgICBpZiAoIWhhc0V4cGlyYXRpb25JbnRlcnZhbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25faW50ZXJ2YWwnXTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtICE9PSAnbnVtYmVyJyB8fCBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBgZXhwaXJhdGlvbl9pbnRlcnZhbCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAwYCk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcHVzaCB0aW1lIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcXVlc3QgQSByZXF1ZXN0IG9iamVjdFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfHVuZGVmaW5lZH0gVGhlIHB1c2ggdGltZSBpZiBpdCBleGlzdHMgaW4gdGhlIHJlcXVlc3RcbiAgICovXG4gIHN0YXRpYyBnZXRQdXNoVGltZShib2R5ID0ge30pIHtcbiAgICB2YXIgaGFzUHVzaFRpbWUgPSBib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKTtcbiAgICBpZiAoIWhhc1B1c2hUaW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBwdXNoVGltZVBhcmFtID0gYm9keVsncHVzaF90aW1lJ107XG4gICAgdmFyIGRhdGU7XG4gICAgdmFyIGlzTG9jYWxUaW1lID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlzTG9jYWxUaW1lID0gIVB1c2hDb250cm9sbGVyLnB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbSk7XG4gICAgICBkYXRlID0gbmV3IERhdGUocHVzaFRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgcHVzaFRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIHB1c2hUaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZGF0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0ZSxcbiAgICAgIGlzTG9jYWxUaW1lLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgSVNPODYwMSBmb3JtYXR0ZWQgZGF0ZSBjb250YWlucyBhIHRpbWV6b25lIGNvbXBvbmVudFxuICAgKiBAcGFyYW0gcHVzaFRpbWVQYXJhbSB7c3RyaW5nfVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50KHB1c2hUaW1lUGFyYW06IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG9mZnNldFBhdHRlcm4gPSAvKC4rKShbKy1dKVxcZFxcZDpcXGRcXGQkLztcbiAgICByZXR1cm4gcHVzaFRpbWVQYXJhbS5pbmRleE9mKCdaJykgPT09IHB1c2hUaW1lUGFyYW0ubGVuZ3RoIC0gMSAvLyAyMDA3LTA0LTA1VDEyOjMwWlxuICAgICAgfHwgb2Zmc2V0UGF0dGVybi50ZXN0KHB1c2hUaW1lUGFyYW0pOyAvLyAyMDA3LTA0LTA1VDEyOjMwLjAwMCswMjowMCwgMjAwNy0wNC0wNVQxMjozMC4wMDAtMDI6MDBcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGRhdGUgdG8gSVNPIGZvcm1hdCBpbiBVVEMgdGltZSBhbmQgc3RyaXBzIHRoZSB0aW1lem9uZSBpZiBgaXNMb2NhbFRpbWVgIGlzIHRydWVcbiAgICogQHBhcmFtIGRhdGUge0RhdGV9XG4gICAqIEBwYXJhbSBpc0xvY2FsVGltZSB7Ym9vbGVhbn1cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBmb3JtYXRQdXNoVGltZSh7IGRhdGUsIGlzTG9jYWxUaW1lIH06IHsgZGF0ZTogRGF0ZSwgaXNMb2NhbFRpbWU6IGJvb2xlYW4gfSkge1xuICAgIGlmIChpc0xvY2FsVGltZSkgeyAvLyBTdHJpcCAnWidcbiAgICAgIGNvbnN0IGlzb1N0cmluZyA9IGRhdGUudG9JU09TdHJpbmcoKTtcbiAgICAgIHJldHVybiBpc29TdHJpbmcuc3Vic3RyaW5nKDAsIGlzb1N0cmluZy5pbmRleE9mKCdaJykpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hDb250cm9sbGVyO1xuIl19 \ No newline at end of file From 037329f63bf826831846d287a8a888a9f8b1a057 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Thu, 27 Sep 2018 12:10:34 -0300 Subject: [PATCH 12/73] Fix ignore badge update error --- lib/Controllers/PushController.js | 8 ++++++-- src/Controllers/PushController.js | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js index 40d6340998..6432bc8ed1 100644 --- a/lib/Controllers/PushController.js +++ b/lib/Controllers/PushController.js @@ -88,8 +88,12 @@ class PushController { return pushStatus.setInitial(body, where); }).then(() => { onPushStatusSaved(pushStatus.objectId); - if (config.stopOnBadgeUpdateError) return badgeUpdate(); + 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 @@ -218,4 +222,4 @@ class PushController { exports.PushController = PushController; exports.default = PushController; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJyZXN0V2hlcmUiLCJkZXZpY2VUb2tlbiIsIiRuZSIsImJ1aWxkUmVzdFdoZXJlIiwidGhlbiIsIndyaXRlIiwiUmVzdFdyaXRlIiwicnVuT3B0aW9ucyIsIm1hbnkiLCJleGVjdXRlIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJvYmplY3RJZCIsInN0b3BPbkJhZGdlVXBkYXRlRXJyb3IiLCJsb2dnZXIiLCJpbmZvIiwiYXVkaWVuY2VfaWQiLCJhdWRpZW5jZUlkIiwidXBkYXRlQXVkaWVuY2UiLCJsYXN0VXNlZCIsIl9fdHlwZSIsImlzbyIsInRvSVNPU3RyaW5nIiwidGltZXNVc2VkIiwiaGFzUHVzaFNjaGVkdWxlZFN1cHBvcnQiLCJwdXNoQ29udHJvbGxlclF1ZXVlIiwiZW5xdWV1ZSIsImNhdGNoIiwiZXJyIiwiZmFpbCIsImhhc0V4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvblRpbWVQYXJhbSIsImV4cGlyYXRpb25UaW1lIiwiaXNGaW5pdGUiLCJoYXNFeHBpcmF0aW9uSW50ZXJ2YWwiLCJleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSIsImhhc1B1c2hUaW1lIiwicHVzaFRpbWVQYXJhbSIsImlzTG9jYWxUaW1lIiwicHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudCIsIm9mZnNldFBhdHRlcm4iLCJpbmRleE9mIiwibGVuZ3RoIiwidGVzdCIsImlzb1N0cmluZyIsInN1YnN0cmluZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVPLE1BQU1BLGNBQU4sQ0FBcUI7O0FBRTFCQyxXQUFTQyxPQUFPLEVBQWhCLEVBQW9CQyxRQUFRLEVBQTVCLEVBQWdDQyxNQUFoQyxFQUF3Q0MsSUFBeEMsRUFBOENDLG9CQUFvQixNQUFNLENBQUUsQ0FBMUUsRUFBNEVDLE1BQU0sSUFBSUMsSUFBSixFQUFsRixFQUE4RjtBQUM1RixRQUFJLENBQUNKLE9BQU9LLGNBQVosRUFBNEI7QUFDMUIsWUFBTSxJQUFJQyxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKLDRCQURJLENBQU47QUFFRDs7QUFFRDtBQUNBVixTQUFLVyxlQUFMLEdBQXVCYixlQUFlYyxpQkFBZixDQUFpQ1osSUFBakMsQ0FBdkI7QUFDQUEsU0FBS2EsbUJBQUwsR0FBMkJmLGVBQWVnQixxQkFBZixDQUFxQ2QsSUFBckMsQ0FBM0I7QUFDQSxRQUFJQSxLQUFLVyxlQUFMLElBQXdCWCxLQUFLYSxtQkFBakMsRUFBc0Q7QUFDcEQsWUFBTSxJQUFJTCxZQUFNQyxLQUFWLENBQ0pELFlBQU1DLEtBQU4sQ0FBWUMsa0JBRFIsRUFFSiw0REFGSSxDQUFOO0FBR0Q7O0FBRUQ7QUFDQSxRQUFJVixLQUFLYSxtQkFBTCxJQUE0QixDQUFDYixLQUFLZSxjQUFMLENBQW9CLFdBQXBCLENBQWpD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QU9DLDRCQUFQLENBQW9DRixhQUFwQyxFQUFvRTtBQUNsRSxVQUFNRyxnQkFBZ0Isc0JBQXRCO0FBQ0EsV0FBT0gsY0FBY0ksT0FBZCxDQUFzQixHQUF0QixNQUErQkosY0FBY0ssTUFBZCxHQUF1QixDQUF0RCxDQUF3RDtBQUF4RCxPQUNGRixjQUFjRyxJQUFkLENBQW1CTixhQUFuQixDQURMLENBRmtFLENBRzFCO0FBQ3pDOztBQUVEOzs7Ozs7QUFNQSxTQUFPbkQsY0FBUCxDQUFzQixFQUFFRCxJQUFGLEVBQVFxRCxXQUFSLEVBQXRCLEVBQW1GO0FBQ2pGLFFBQUlBLFdBQUosRUFBaUI7QUFBRTtBQUNqQixZQUFNTSxZQUFZM0QsS0FBS3FDLFdBQUwsRUFBbEI7QUFDQSxhQUFPc0IsVUFBVUMsU0FBVixDQUFvQixDQUFwQixFQUF1QkQsVUFBVUgsT0FBVixDQUFrQixHQUFsQixDQUF2QixDQUFQO0FBQ0Q7QUFDRCxXQUFPeEQsS0FBS3FDLFdBQUwsRUFBUDtBQUNEO0FBcE15Qjs7UUFBZjNELGMsR0FBQUEsYztrQkF1TUVBLGMiLCJmaWxlIjoiUHVzaENvbnRyb2xsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9ICAgICAgICAgICAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBSZXN0UXVlcnkgICAgICAgICAgICAgIGZyb20gJy4uL1Jlc3RRdWVyeSc7XG5pbXBvcnQgUmVzdFdyaXRlICAgICAgICAgICAgICBmcm9tICcuLi9SZXN0V3JpdGUnO1xuaW1wb3J0IHsgbWFzdGVyIH0gICAgICAgICAgICAgZnJvbSAnLi4vQXV0aCc7XG5pbXBvcnQgeyBwdXNoU3RhdHVzSGFuZGxlciB9ICBmcm9tICcuLi9TdGF0dXNIYW5kbGVyJztcbmltcG9ydCB7IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMgfSBmcm9tICcuLi9QdXNoL3V0aWxzJztcbmltcG9ydCB7IGxvZ2dlciB9ICAgICAgICAgICAgICAgZnJvbSAnLi4vbG9nZ2VyJztcblxuZXhwb3J0IGNsYXNzIFB1c2hDb250cm9sbGVyIHtcblxuICBzZW5kUHVzaChib2R5ID0ge30sIHdoZXJlID0ge30sIGNvbmZpZywgYXV0aCwgb25QdXNoU3RhdHVzU2F2ZWQgPSAoKSA9PiB7fSwgbm93ID0gbmV3IERhdGUoKSkge1xuICAgIGlmICghY29uZmlnLmhhc1B1c2hTdXBwb3J0KSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnTWlzc2luZyBwdXNoIGNvbmZpZ3VyYXRpb24nKTtcbiAgICB9XG5cbiAgICAvLyBSZXBsYWNlIHRoZSBleHBpcmF0aW9uX3RpbWUgYW5kIHB1c2hfdGltZSB3aXRoIGEgdmFsaWQgVW5peCBlcG9jaCBtaWxsaXNlY29uZHMgdGltZVxuICAgIGJvZHkuZXhwaXJhdGlvbl90aW1lID0gUHVzaENvbnRyb2xsZXIuZ2V0RXhwaXJhdGlvblRpbWUoYm9keSk7XG4gICAgYm9keS5leHBpcmF0aW9uX2ludGVydmFsID0gUHVzaENvbnRyb2xsZXIuZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkpO1xuICAgIGlmIChib2R5LmV4cGlyYXRpb25fdGltZSAmJiBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnQm90aCBleHBpcmF0aW9uX3RpbWUgYW5kIGV4cGlyYXRpb25faW50ZXJ2YWwgY2Fubm90IGJlIHNldCcpO1xuICAgIH1cblxuICAgIC8vIEltbWVkaWF0ZSBwdXNoXG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCAmJiAhYm9keS5oYXNPd25Qcm9wZXJ0eSgncHVzaF90aW1lJykpIHtcbiAgICAgIGNvbnN0IHR0bE1zID0gYm9keS5leHBpcmF0aW9uX2ludGVydmFsICogMTAwMDtcbiAgICAgIGJvZHkuZXhwaXJhdGlvbl90aW1lID0gKG5ldyBEYXRlKG5vdy52YWx1ZU9mKCkgKyB0dGxNcykpLnZhbHVlT2YoKTtcbiAgICB9XG5cbiAgICBjb25zdCBwdXNoVGltZSA9IFB1c2hDb250cm9sbGVyLmdldFB1c2hUaW1lKGJvZHkpO1xuICAgIGlmIChwdXNoVGltZSAmJiBwdXNoVGltZS5kYXRlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgYm9keVsncHVzaF90aW1lJ10gPSBQdXNoQ29udHJvbGxlci5mb3JtYXRQdXNoVGltZShwdXNoVGltZSk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogSWYgdGhlIHJlcSBjYW4gcGFzcyB0aGUgY2hlY2tpbmcsIHdlIHJldHVybiBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIHdhaXRpbmdcbiAgICAvLyBwdXNoZXMgdG8gYmUgc2VudC4gV2UgcHJvYmFibHkgY2hhbmdlIHRoaXMgYmVoYXZpb3VyIGluIHRoZSBmdXR1cmUuXG4gICAgbGV0IGJhZGdlVXBkYXRlID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIGlmIChib2R5LmRhdGEgJiYgYm9keS5kYXRhLmJhZGdlKSB7XG4gICAgICBjb25zdCBiYWRnZSA9IGJvZHkuZGF0YS5iYWRnZTtcbiAgICAgIGxldCByZXN0VXBkYXRlID0ge307XG4gICAgICBpZiAodHlwZW9mIGJhZGdlID09ICdzdHJpbmcnICYmIGJhZGdlLnRvTG93ZXJDYXNlKCkgPT09ICdpbmNyZW1lbnQnKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiB7IF9fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IDEgfSB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBiYWRnZSA9PSAnb2JqZWN0JyAmJiB0eXBlb2YgYmFkZ2UuX19vcCA9PSAnc3RyaW5nJyAmJlxuICAgICAgICAgICAgICAgICBiYWRnZS5fX29wLnRvTG93ZXJDYXNlKCkgPT0gJ2luY3JlbWVudCcgJiYgTnVtYmVyKGJhZGdlLmFtb3VudCkpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogYmFkZ2UuYW1vdW50IH0gfVxuICAgICAgfSBlbHNlIGlmIChOdW1iZXIoYmFkZ2UpKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiBiYWRnZSB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBcIkludmFsaWQgdmFsdWUgZm9yIGJhZGdlLCBleHBlY3RlZCBudW1iZXIgb3IgJ0luY3JlbWVudCcgb3Ige2luY3JlbWVudDogbnVtYmVyfVwiO1xuICAgICAgfVxuXG4gICAgICAvLyBGb3JjZSBmaWx0ZXJpbmcgb24gb25seSB2YWxpZCBkZXZpY2UgdG9rZW5zXG4gICAgICBjb25zdCB1cGRhdGVXaGVyZSA9IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMod2hlcmUpO1xuICAgICAgYmFkZ2VVcGRhdGUgPSAoKSA9PiB7XG4gICAgICAgIC8vIEJ1aWxkIGEgcmVhbCBSZXN0UXVlcnkgc28gd2UgY2FuIHVzZSBpdCBpbiBSZXN0V3JpdGVcbiAgICAgICAgY29uc3QgcmVzdFF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShjb25maWcsIG1hc3Rlcihjb25maWcpLCAnX0luc3RhbGxhdGlvbicsIHVwZGF0ZVdoZXJlKTtcbiAgICAgICAgLy8gY2hhbmdlICRleGlzdHMgZm9yICRuZSBudWxsIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICAgICAgaWYgKHJlc3RRdWVyeS5yZXN0V2hlcmUgJiYgcmVzdFF1ZXJ5LnJlc3RXaGVyZS5kZXZpY2VUb2tlbiAmJiByZXN0UXVlcnkucmVzdFdoZXJlLmRldmljZVRva2VuWyckZXhpc3RzJ10pIHJlc3RRdWVyeS5yZXN0V2hlcmUuZGV2aWNlVG9rZW4gPSB7JG5lOiBudWxsfVxuICAgICAgICByZXR1cm4gcmVzdFF1ZXJ5LmJ1aWxkUmVzdFdoZXJlKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgcmVzdFF1ZXJ5LnJlc3RXaGVyZSwgcmVzdFVwZGF0ZSk7XG4gICAgICAgICAgd3JpdGUucnVuT3B0aW9ucy5tYW55ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcHVzaFN0YXR1cyA9IHB1c2hTdGF0dXNIYW5kbGVyKGNvbmZpZyk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHB1c2hTdGF0dXMuc2V0SW5pdGlhbChib2R5LCB3aGVyZSk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBvblB1c2hTdGF0dXNTYXZlZChwdXNoU3RhdHVzLm9iamVjdElkKTtcbiAgICAgIGlmIChjb25maWcuc3RvcE9uQmFkZ2VVcGRhdGVFcnJvcikgcmV0dXJuIGJhZGdlVXBkYXRlKCk7XG4gICAgICBsb2dnZXIuaW5mbyhgQmFkZ2UgdXBkYXRlIGVycm9yIHdpbGwgYmUgaWdub3JlZCBmb3IgcHVzaCBzdGF0dXMgJHtwdXNoU3RhdHVzLm9iamVjdElkfWApO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gVXBkYXRlIGF1ZGllbmNlIGxhc3RVc2VkIGFuZCB0aW1lc1VzZWRcbiAgICAgIGlmIChib2R5LmF1ZGllbmNlX2lkKSB7XG4gICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgIHZhciB1cGRhdGVBdWRpZW5jZSA9IHtcbiAgICAgICAgICBsYXN0VXNlZDogeyBfX3R5cGU6IFwiRGF0ZVwiLCBpc286IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSB9LFxuICAgICAgICAgIHRpbWVzVXNlZDogeyBfX29wOiBcIkluY3JlbWVudFwiLCBcImFtb3VudFwiOiAxIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfQXVkaWVuY2UnLCB7b2JqZWN0SWQ6IGF1ZGllbmNlSWR9LCB1cGRhdGVBdWRpZW5jZSk7XG4gICAgICAgIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgIH1cbiAgICAgIC8vIERvbid0IHdhaXQgZm9yIHRoZSBhdWRpZW5jZSB1cGRhdGUgcHJvbWlzZSB0byByZXNvbHZlLlxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpICYmIGNvbmZpZy5oYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShib2R5LCB3aGVyZSwgY29uZmlnLCBhdXRoLCBwdXNoU3RhdHVzKTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5mYWlsKGVycikudGhlbigoKSA9PiB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBleHBpcmF0aW9uIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgZXhwaXJhdGlvbiB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldEV4cGlyYXRpb25UaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNFeHBpcmF0aW9uVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25fdGltZScpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvblRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV4cGlyYXRpb25UaW1lUGFyYW0gPSBib2R5WydleHBpcmF0aW9uX3RpbWUnXTtcbiAgICB2YXIgZXhwaXJhdGlvblRpbWU7XG4gICAgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwaXJhdGlvblRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGV4cGlyYXRpb25UaW1lID0gbmV3IERhdGUoZXhwaXJhdGlvblRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZXhwaXJhdGlvblRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIGV4cGlyYXRpb25UaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZXhwaXJhdGlvblRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBib2R5WydleHBpcmF0aW9uX3RpbWUnXSArICcgaXMgbm90IHZhbGlkIHRpbWUuJyk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uVGltZS52YWx1ZU9mKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkgPSB7fSkge1xuICAgIGNvbnN0IGhhc0V4cGlyYXRpb25JbnRlcnZhbCA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25faW50ZXJ2YWwnKTtcbiAgICBpZiAoIWhhc0V4cGlyYXRpb25JbnRlcnZhbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25faW50ZXJ2YWwnXTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtICE9PSAnbnVtYmVyJyB8fCBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBgZXhwaXJhdGlvbl9pbnRlcnZhbCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAwYCk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcHVzaCB0aW1lIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcXVlc3QgQSByZXF1ZXN0IG9iamVjdFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfHVuZGVmaW5lZH0gVGhlIHB1c2ggdGltZSBpZiBpdCBleGlzdHMgaW4gdGhlIHJlcXVlc3RcbiAgICovXG4gIHN0YXRpYyBnZXRQdXNoVGltZShib2R5ID0ge30pIHtcbiAgICB2YXIgaGFzUHVzaFRpbWUgPSBib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKTtcbiAgICBpZiAoIWhhc1B1c2hUaW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBwdXNoVGltZVBhcmFtID0gYm9keVsncHVzaF90aW1lJ107XG4gICAgdmFyIGRhdGU7XG4gICAgdmFyIGlzTG9jYWxUaW1lID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlzTG9jYWxUaW1lID0gIVB1c2hDb250cm9sbGVyLnB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbSk7XG4gICAgICBkYXRlID0gbmV3IERhdGUocHVzaFRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgcHVzaFRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIHB1c2hUaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZGF0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0ZSxcbiAgICAgIGlzTG9jYWxUaW1lLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgSVNPODYwMSBmb3JtYXR0ZWQgZGF0ZSBjb250YWlucyBhIHRpbWV6b25lIGNvbXBvbmVudFxuICAgKiBAcGFyYW0gcHVzaFRpbWVQYXJhbSB7c3RyaW5nfVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50KHB1c2hUaW1lUGFyYW06IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG9mZnNldFBhdHRlcm4gPSAvKC4rKShbKy1dKVxcZFxcZDpcXGRcXGQkLztcbiAgICByZXR1cm4gcHVzaFRpbWVQYXJhbS5pbmRleE9mKCdaJykgPT09IHB1c2hUaW1lUGFyYW0ubGVuZ3RoIC0gMSAvLyAyMDA3LTA0LTA1VDEyOjMwWlxuICAgICAgfHwgb2Zmc2V0UGF0dGVybi50ZXN0KHB1c2hUaW1lUGFyYW0pOyAvLyAyMDA3LTA0LTA1VDEyOjMwLjAwMCswMjowMCwgMjAwNy0wNC0wNVQxMjozMC4wMDAtMDI6MDBcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGRhdGUgdG8gSVNPIGZvcm1hdCBpbiBVVEMgdGltZSBhbmQgc3RyaXBzIHRoZSB0aW1lem9uZSBpZiBgaXNMb2NhbFRpbWVgIGlzIHRydWVcbiAgICogQHBhcmFtIGRhdGUge0RhdGV9XG4gICAqIEBwYXJhbSBpc0xvY2FsVGltZSB7Ym9vbGVhbn1cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBmb3JtYXRQdXNoVGltZSh7IGRhdGUsIGlzTG9jYWxUaW1lIH06IHsgZGF0ZTogRGF0ZSwgaXNMb2NhbFRpbWU6IGJvb2xlYW4gfSkge1xuICAgIGlmIChpc0xvY2FsVGltZSkgeyAvLyBTdHJpcCAnWidcbiAgICAgIGNvbnN0IGlzb1N0cmluZyA9IGRhdGUudG9JU09TdHJpbmcoKTtcbiAgICAgIHJldHVybiBpc29TdHJpbmcuc3Vic3RyaW5nKDAsIGlzb1N0cmluZy5pbmRleE9mKCdaJykpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hDb250cm9sbGVyO1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJyZXN0V2hlcmUiLCJkZXZpY2VUb2tlbiIsIiRuZSIsImJ1aWxkUmVzdFdoZXJlIiwidGhlbiIsIndyaXRlIiwiUmVzdFdyaXRlIiwicnVuT3B0aW9ucyIsIm1hbnkiLCJleGVjdXRlIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJvYmplY3RJZCIsImNhdGNoIiwiZXJyIiwic3RvcE9uQmFkZ2VVcGRhdGVFcnJvciIsImxvZ2dlciIsImluZm8iLCJzdGFjayIsInRvU3RyaW5nIiwibWVzc2FnZSIsImF1ZGllbmNlX2lkIiwiYXVkaWVuY2VJZCIsInVwZGF0ZUF1ZGllbmNlIiwibGFzdFVzZWQiLCJfX3R5cGUiLCJpc28iLCJ0b0lTT1N0cmluZyIsInRpbWVzVXNlZCIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0IiwicHVzaENvbnRyb2xsZXJRdWV1ZSIsImVucXVldWUiLCJmYWlsIiwiaGFzRXhwaXJhdGlvblRpbWUiLCJleHBpcmF0aW9uVGltZVBhcmFtIiwiZXhwaXJhdGlvblRpbWUiLCJpc0Zpbml0ZSIsImhhc0V4cGlyYXRpb25JbnRlcnZhbCIsImV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIiwiaGFzUHVzaFRpbWUiLCJwdXNoVGltZVBhcmFtIiwiaXNMb2NhbFRpbWUiLCJwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50Iiwib2Zmc2V0UGF0dGVybiIsImluZGV4T2YiLCJsZW5ndGgiLCJ0ZXN0IiwiaXNvU3RyaW5nIiwic3Vic3RyaW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsY0FBTixDQUFxQjs7QUFFMUJDLFdBQVNDLE9BQU8sRUFBaEIsRUFBb0JDLFFBQVEsRUFBNUIsRUFBZ0NDLE1BQWhDLEVBQXdDQyxJQUF4QyxFQUE4Q0Msb0JBQW9CLE1BQU0sQ0FBRSxDQUExRSxFQUE0RUMsTUFBTSxJQUFJQyxJQUFKLEVBQWxGLEVBQThGO0FBQzVGLFFBQUksQ0FBQ0osT0FBT0ssY0FBWixFQUE0QjtBQUMxQixZQUFNLElBQUlDLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0osNEJBREksQ0FBTjtBQUVEOztBQUVEO0FBQ0FWLFNBQUtXLGVBQUwsR0FBdUJiLGVBQWVjLGlCQUFmLENBQWlDWixJQUFqQyxDQUF2QjtBQUNBQSxTQUFLYSxtQkFBTCxHQUEyQmYsZUFBZWdCLHFCQUFmLENBQXFDZCxJQUFyQyxDQUEzQjtBQUNBLFFBQUlBLEtBQUtXLGVBQUwsSUFBd0JYLEtBQUthLG1CQUFqQyxFQUFzRDtBQUNwRCxZQUFNLElBQUlMLFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKLDREQUZJLENBQU47QUFHRDs7QUFFRDtBQUNBLFFBQUlWLEtBQUthLG1CQUFMLElBQTRCLENBQUNi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QUFDRDtBQUNBLFFBQUksQ0FBQ3VFLFNBQVNuRCxJQUFULENBQUwsRUFBcUI7QUFDbkIsWUFBTSxJQUFJWixZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKVixLQUFLLFdBQUwsSUFBb0IscUJBRGhCLENBQU47QUFFRDs7QUFFRCxXQUFPO0FBQ0xvQixVQURLO0FBRUx3RDtBQUZLLEtBQVA7QUFJRDs7QUFFRDs7Ozs7QUFLQSxTQUFPQyw0QkFBUCxDQUFvQ0YsYUFBcEMsRUFBb0U7QUFDbEUsVUFBTUcsZ0JBQWdCLHNCQUF0QjtBQUNBLFdBQU9ILGNBQWNJLE9BQWQsQ0FBc0IsR0FBdEIsTUFBK0JKLGNBQWNLLE1BQWQsR0FBdUIsQ0FBdEQsQ0FBd0Q7QUFBeEQsT0FDRkYsY0FBY0csSUFBZCxDQUFtQk4sYUFBbkIsQ0FETCxDQUZrRSxDQUcxQjtBQUN6Qzs7QUFFRDs7Ozs7O0FBTUEsU0FBT3RELGNBQVAsQ0FBc0IsRUFBRUQsSUFBRixFQUFRd0QsV0FBUixFQUF0QixFQUFtRjtBQUNqRixRQUFJQSxXQUFKLEVBQWlCO0FBQUU7QUFDakIsWUFBTU0sWUFBWTlELEtBQUswQyxXQUFMLEVBQWxCO0FBQ0EsYUFBT29CLFVBQVVDLFNBQVYsQ0FBb0IsQ0FBcEIsRUFBdUJELFVBQVVILE9BQVYsQ0FBa0IsR0FBbEIsQ0FBdkIsQ0FBUDtBQUNEO0FBQ0QsV0FBTzNELEtBQUswQyxXQUFMLEVBQVA7QUFDRDtBQXhNeUI7O1FBQWZoRSxjLEdBQUFBLGM7a0JBMk1FQSxjIiwiZmlsZSI6IlB1c2hDb250cm9sbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2UgfSAgICAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgUmVzdFF1ZXJ5ICAgICAgICAgICAgICBmcm9tICcuLi9SZXN0UXVlcnknO1xuaW1wb3J0IFJlc3RXcml0ZSAgICAgICAgICAgICAgZnJvbSAnLi4vUmVzdFdyaXRlJztcbmltcG9ydCB7IG1hc3RlciB9ICAgICAgICAgICAgIGZyb20gJy4uL0F1dGgnO1xuaW1wb3J0IHsgcHVzaFN0YXR1c0hhbmRsZXIgfSAgZnJvbSAnLi4vU3RhdHVzSGFuZGxlcic7XG5pbXBvcnQgeyBhcHBseURldmljZVRva2VuRXhpc3RzIH0gZnJvbSAnLi4vUHVzaC91dGlscyc7XG5pbXBvcnQgeyBsb2dnZXIgfSAgICAgICAgICAgICAgIGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCBjbGFzcyBQdXNoQ29udHJvbGxlciB7XG5cbiAgc2VuZFB1c2goYm9keSA9IHt9LCB3aGVyZSA9IHt9LCBjb25maWcsIGF1dGgsIG9uUHVzaFN0YXR1c1NhdmVkID0gKCkgPT4ge30sIG5vdyA9IG5ldyBEYXRlKCkpIHtcbiAgICBpZiAoIWNvbmZpZy5oYXNQdXNoU3VwcG9ydCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgJ01pc3NpbmcgcHVzaCBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gUmVwbGFjZSB0aGUgZXhwaXJhdGlvbl90aW1lIGFuZCBwdXNoX3RpbWUgd2l0aCBhIHZhbGlkIFVuaXggZXBvY2ggbWlsbGlzZWNvbmRzIHRpbWVcbiAgICBib2R5LmV4cGlyYXRpb25fdGltZSA9IFB1c2hDb250cm9sbGVyLmdldEV4cGlyYXRpb25UaW1lKGJvZHkpO1xuICAgIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCA9IFB1c2hDb250cm9sbGVyLmdldEV4cGlyYXRpb25JbnRlcnZhbChib2R5KTtcbiAgICBpZiAoYm9keS5leHBpcmF0aW9uX3RpbWUgJiYgYm9keS5leHBpcmF0aW9uX2ludGVydmFsKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgJ0JvdGggZXhwaXJhdGlvbl90aW1lIGFuZCBleHBpcmF0aW9uX2ludGVydmFsIGNhbm5vdCBiZSBzZXQnKTtcbiAgICB9XG5cbiAgICAvLyBJbW1lZGlhdGUgcHVzaFxuICAgIGlmIChib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgJiYgIWJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpKSB7XG4gICAgICBjb25zdCB0dGxNcyA9IGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCAqIDEwMDA7XG4gICAgICBib2R5LmV4cGlyYXRpb25fdGltZSA9IChuZXcgRGF0ZShub3cudmFsdWVPZigpICsgdHRsTXMpKS52YWx1ZU9mKCk7XG4gICAgfVxuXG4gICAgY29uc3QgcHVzaFRpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRQdXNoVGltZShib2R5KTtcbiAgICBpZiAocHVzaFRpbWUgJiYgcHVzaFRpbWUuZGF0ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGJvZHlbJ3B1c2hfdGltZSddID0gUHVzaENvbnRyb2xsZXIuZm9ybWF0UHVzaFRpbWUocHVzaFRpbWUpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IElmIHRoZSByZXEgY2FuIHBhc3MgdGhlIGNoZWNraW5nLCB3ZSByZXR1cm4gaW1tZWRpYXRlbHkgaW5zdGVhZCBvZiB3YWl0aW5nXG4gICAgLy8gcHVzaGVzIHRvIGJlIHNlbnQuIFdlIHByb2JhYmx5IGNoYW5nZSB0aGlzIGJlaGF2aW91ciBpbiB0aGUgZnV0dXJlLlxuICAgIGxldCBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBpZiAoYm9keS5kYXRhICYmIGJvZHkuZGF0YS5iYWRnZSkge1xuICAgICAgY29uc3QgYmFkZ2UgPSBib2R5LmRhdGEuYmFkZ2U7XG4gICAgICBsZXQgcmVzdFVwZGF0ZSA9IHt9O1xuICAgICAgaWYgKHR5cGVvZiBiYWRnZSA9PSAnc3RyaW5nJyAmJiBiYWRnZS50b0xvd2VyQ2FzZSgpID09PSAnaW5jcmVtZW50Jykge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiAxIH0gfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ29iamVjdCcgJiYgdHlwZW9mIGJhZGdlLl9fb3AgPT0gJ3N0cmluZycgJiZcbiAgICAgICAgICAgICAgICAgYmFkZ2UuX19vcC50b0xvd2VyQ2FzZSgpID09ICdpbmNyZW1lbnQnICYmIE51bWJlcihiYWRnZS5hbW91bnQpKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiB7IF9fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IGJhZGdlLmFtb3VudCB9IH1cbiAgICAgIH0gZWxzZSBpZiAoTnVtYmVyKGJhZGdlKSkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogYmFkZ2UgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgXCJJbnZhbGlkIHZhbHVlIGZvciBiYWRnZSwgZXhwZWN0ZWQgbnVtYmVyIG9yICdJbmNyZW1lbnQnIG9yIHtpbmNyZW1lbnQ6IG51bWJlcn1cIjtcbiAgICAgIH1cblxuICAgICAgLy8gRm9yY2UgZmlsdGVyaW5nIG9uIG9ubHkgdmFsaWQgZGV2aWNlIHRva2Vuc1xuICAgICAgY29uc3QgdXBkYXRlV2hlcmUgPSBhcHBseURldmljZVRva2VuRXhpc3RzKHdoZXJlKTtcbiAgICAgIGJhZGdlVXBkYXRlID0gKCkgPT4ge1xuICAgICAgICAvLyBCdWlsZCBhIHJlYWwgUmVzdFF1ZXJ5IHNvIHdlIGNhbiB1c2UgaXQgaW4gUmVzdFdyaXRlXG4gICAgICAgIGNvbnN0IHJlc3RRdWVyeSA9IG5ldyBSZXN0UXVlcnkoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19JbnN0YWxsYXRpb24nLCB1cGRhdGVXaGVyZSk7XG4gICAgICAgIC8vIGNoYW5nZSAkZXhpc3RzIGZvciAkbmUgbnVsbCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAgICAgIGlmIChyZXN0UXVlcnkucmVzdFdoZXJlICYmIHJlc3RRdWVyeS5yZXN0V2hlcmUuZGV2aWNlVG9rZW4gJiYgcmVzdFF1ZXJ5LnJlc3RXaGVyZS5kZXZpY2VUb2tlblsnJGV4aXN0cyddKSByZXN0UXVlcnkucmVzdFdoZXJlLmRldmljZVRva2VuID0geyRuZTogbnVsbH1cbiAgICAgICAgcmV0dXJuIHJlc3RRdWVyeS5idWlsZFJlc3RXaGVyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdyaXRlID0gbmV3IFJlc3RXcml0ZShjb25maWcsIG1hc3Rlcihjb25maWcpLCAnX0luc3RhbGxhdGlvbicsIHJlc3RRdWVyeS5yZXN0V2hlcmUsIHJlc3RVcGRhdGUpO1xuICAgICAgICAgIHdyaXRlLnJ1bk9wdGlvbnMubWFueSA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHB1c2hTdGF0dXMgPSBwdXNoU3RhdHVzSGFuZGxlcihjb25maWcpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBwdXNoU3RhdHVzLnNldEluaXRpYWwoYm9keSwgd2hlcmUpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgb25QdXNoU3RhdHVzU2F2ZWQocHVzaFN0YXR1cy5vYmplY3RJZCk7XG4gICAgICByZXR1cm4gYmFkZ2VVcGRhdGUoKTtcbiAgICB9KS5jYXRjaChlcnIgPT4ge1xuICAgICAgLy8gYWRkIHRoaXMgdG8gaWdub3JlIGJhZGdlIHVwZGF0ZSBlcnJvcnMgYXMgZGVmYXVsdFxuICAgICAgaWYgKGNvbmZpZy5zdG9wT25CYWRnZVVwZGF0ZUVycm9yKSB0aHJvdyBlcnI7XG4gICAgICBsb2dnZXIuaW5mbyhgQmFkZ2UgdXBkYXRlIGVycm9yIHdpbGwgYmUgaWdub3JlZCBmb3IgcHVzaCBzdGF0dXMgJHtwdXNoU3RhdHVzLm9iamVjdElkfWApO1xuICAgICAgbG9nZ2VyLmluZm8oZXJyICYmIGVyci5zdGFjayAmJiBlcnIuc3RhY2sudG9TdHJpbmcoKSB8fCBlcnIgJiYgZXJyLm1lc3NhZ2UgfHwgZXJyLnRvU3RyaW5nKCkpO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gVXBkYXRlIGF1ZGllbmNlIGxhc3RVc2VkIGFuZCB0aW1lc1VzZWRcbiAgICAgIGlmIChib2R5LmF1ZGllbmNlX2lkKSB7XG4gICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgIHZhciB1cGRhdGVBdWRpZW5jZSA9IHtcbiAgICAgICAgICBsYXN0VXNlZDogeyBfX3R5cGU6IFwiRGF0ZVwiLCBpc286IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSB9LFxuICAgICAgICAgIHRpbWVzVXNlZDogeyBfX29wOiBcIkluY3JlbWVudFwiLCBcImFtb3VudFwiOiAxIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfQXVkaWVuY2UnLCB7b2JqZWN0SWQ6IGF1ZGllbmNlSWR9LCB1cGRhdGVBdWRpZW5jZSk7XG4gICAgICAgIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgIH1cbiAgICAgIC8vIERvbid0IHdhaXQgZm9yIHRoZSBhdWRpZW5jZSB1cGRhdGUgcHJvbWlzZSB0byByZXNvbHZlLlxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpICYmIGNvbmZpZy5oYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShib2R5LCB3aGVyZSwgY29uZmlnLCBhdXRoLCBwdXNoU3RhdHVzKTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5mYWlsKGVycikudGhlbigoKSA9PiB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBleHBpcmF0aW9uIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgZXhwaXJhdGlvbiB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldEV4cGlyYXRpb25UaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNFeHBpcmF0aW9uVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25fdGltZScpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvblRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV4cGlyYXRpb25UaW1lUGFyYW0gPSBib2R5WydleHBpcmF0aW9uX3RpbWUnXTtcbiAgICB2YXIgZXhwaXJhdGlvblRpbWU7XG4gICAgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwaXJhdGlvblRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGV4cGlyYXRpb25UaW1lID0gbmV3IERhdGUoZXhwaXJhdGlvblRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZXhwaXJhdGlvblRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIGV4cGlyYXRpb25UaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZXhwaXJhdGlvblRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBib2R5WydleHBpcmF0aW9uX3RpbWUnXSArICcgaXMgbm90IHZhbGlkIHRpbWUuJyk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uVGltZS52YWx1ZU9mKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkgPSB7fSkge1xuICAgIGNvbnN0IGhhc0V4cGlyYXRpb25JbnRlcnZhbCA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25faW50ZXJ2YWwnKTtcbiAgICBpZiAoIWhhc0V4cGlyYXRpb25JbnRlcnZhbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25faW50ZXJ2YWwnXTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtICE9PSAnbnVtYmVyJyB8fCBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBgZXhwaXJhdGlvbl9pbnRlcnZhbCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAwYCk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcHVzaCB0aW1lIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcXVlc3QgQSByZXF1ZXN0IG9iamVjdFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfHVuZGVmaW5lZH0gVGhlIHB1c2ggdGltZSBpZiBpdCBleGlzdHMgaW4gdGhlIHJlcXVlc3RcbiAgICovXG4gIHN0YXRpYyBnZXRQdXNoVGltZShib2R5ID0ge30pIHtcbiAgICB2YXIgaGFzUHVzaFRpbWUgPSBib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKTtcbiAgICBpZiAoIWhhc1B1c2hUaW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBwdXNoVGltZVBhcmFtID0gYm9keVsncHVzaF90aW1lJ107XG4gICAgdmFyIGRhdGU7XG4gICAgdmFyIGlzTG9jYWxUaW1lID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlzTG9jYWxUaW1lID0gIVB1c2hDb250cm9sbGVyLnB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbSk7XG4gICAgICBkYXRlID0gbmV3IERhdGUocHVzaFRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgcHVzaFRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIHB1c2hUaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZGF0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0ZSxcbiAgICAgIGlzTG9jYWxUaW1lLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgSVNPODYwMSBmb3JtYXR0ZWQgZGF0ZSBjb250YWlucyBhIHRpbWV6b25lIGNvbXBvbmVudFxuICAgKiBAcGFyYW0gcHVzaFRpbWVQYXJhbSB7c3RyaW5nfVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50KHB1c2hUaW1lUGFyYW06IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG9mZnNldFBhdHRlcm4gPSAvKC4rKShbKy1dKVxcZFxcZDpcXGRcXGQkLztcbiAgICByZXR1cm4gcHVzaFRpbWVQYXJhbS5pbmRleE9mKCdaJykgPT09IHB1c2hUaW1lUGFyYW0ubGVuZ3RoIC0gMSAvLyAyMDA3LTA0LTA1VDEyOjMwWlxuICAgICAgfHwgb2Zmc2V0UGF0dGVybi50ZXN0KHB1c2hUaW1lUGFyYW0pOyAvLyAyMDA3LTA0LTA1VDEyOjMwLjAwMCswMjowMCwgMjAwNy0wNC0wNVQxMjozMC4wMDAtMDI6MDBcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGRhdGUgdG8gSVNPIGZvcm1hdCBpbiBVVEMgdGltZSBhbmQgc3RyaXBzIHRoZSB0aW1lem9uZSBpZiBgaXNMb2NhbFRpbWVgIGlzIHRydWVcbiAgICogQHBhcmFtIGRhdGUge0RhdGV9XG4gICAqIEBwYXJhbSBpc0xvY2FsVGltZSB7Ym9vbGVhbn1cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBmb3JtYXRQdXNoVGltZSh7IGRhdGUsIGlzTG9jYWxUaW1lIH06IHsgZGF0ZTogRGF0ZSwgaXNMb2NhbFRpbWU6IGJvb2xlYW4gfSkge1xuICAgIGlmIChpc0xvY2FsVGltZSkgeyAvLyBTdHJpcCAnWidcbiAgICAgIGNvbnN0IGlzb1N0cmluZyA9IGRhdGUudG9JU09TdHJpbmcoKTtcbiAgICAgIHJldHVybiBpc29TdHJpbmcuc3Vic3RyaW5nKDAsIGlzb1N0cmluZy5pbmRleE9mKCdaJykpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hDb250cm9sbGVyO1xuIl19 \ No newline at end of file diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index dff15322be..b374ec721f 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -73,8 +73,12 @@ export class PushController { return pushStatus.setInitial(body, where); }).then(() => { onPushStatusSaved(pushStatus.objectId); - if (config.stopOnBadgeUpdateError) 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 From f387c9eb47fc9479e4d945b114ea36d6579556fc Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Thu, 27 Sep 2018 12:11:28 -0300 Subject: [PATCH 13/73] Fix ignore badge update error --- lib/Controllers/PushController.js | 16 ++++++++-------- src/Controllers/PushController.js | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/Controllers/PushController.js b/lib/Controllers/PushController.js index 6432bc8ed1..6f1f16cd80 100644 --- a/lib/Controllers/PushController.js +++ b/lib/Controllers/PushController.js @@ -88,13 +88,13 @@ class PushController { 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(); + 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) { @@ -222,4 +222,4 @@ class PushController { exports.PushController = PushController; exports.default = PushController; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJyZXN0V2hlcmUiLCJkZXZpY2VUb2tlbiIsIiRuZSIsImJ1aWxkUmVzdFdoZXJlIiwidGhlbiIsIndyaXRlIiwiUmVzdFdyaXRlIiwicnVuT3B0aW9ucyIsIm1hbnkiLCJleGVjdXRlIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJvYmplY3RJZCIsImNhdGNoIiwiZXJyIiwic3RvcE9uQmFkZ2VVcGRhdGVFcnJvciIsImxvZ2dlciIsImluZm8iLCJzdGFjayIsInRvU3RyaW5nIiwibWVzc2FnZSIsImF1ZGllbmNlX2lkIiwiYXVkaWVuY2VJZCIsInVwZGF0ZUF1ZGllbmNlIiwibGFzdFVzZWQiLCJfX3R5cGUiLCJpc28iLCJ0b0lTT1N0cmluZyIsInRpbWVzVXNlZCIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0IiwicHVzaENvbnRyb2xsZXJRdWV1ZSIsImVucXVldWUiLCJmYWlsIiwiaGFzRXhwaXJhdGlvblRpbWUiLCJleHBpcmF0aW9uVGltZVBhcmFtIiwiZXhwaXJhdGlvblRpbWUiLCJpc0Zpbml0ZSIsImhhc0V4cGlyYXRpb25JbnRlcnZhbCIsImV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIiwiaGFzUHVzaFRpbWUiLCJwdXNoVGltZVBhcmFtIiwiaXNMb2NhbFRpbWUiLCJwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50Iiwib2Zmc2V0UGF0dGVybiIsImluZGV4T2YiLCJsZW5ndGgiLCJ0ZXN0IiwiaXNvU3RyaW5nIiwic3Vic3RyaW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsY0FBTixDQUFxQjs7QUFFMUJDLFdBQVNDLE9BQU8sRUFBaEIsRUFBb0JDLFFBQVEsRUFBNUIsRUFBZ0NDLE1BQWhDLEVBQXdDQyxJQUF4QyxFQUE4Q0Msb0JBQW9CLE1BQU0sQ0FBRSxDQUExRSxFQUE0RUMsTUFBTSxJQUFJQyxJQUFKLEVBQWxGLEVBQThGO0FBQzVGLFFBQUksQ0FBQ0osT0FBT0ssY0FBWixFQUE0QjtBQUMxQixZQUFNLElBQUlDLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0osNEJBREksQ0FBTjtBQUVEOztBQUVEO0FBQ0FWLFNBQUtXLGVBQUwsR0FBdUJiLGVBQWVjLGlCQUFmLENBQWlDWixJQUFqQyxDQUF2QjtBQUNBQSxTQUFLYSxtQkFBTCxHQUEyQmYsZUFBZWdCLHFCQUFmLENBQXFDZCxJQUFyQyxDQUEzQjtBQUNBLFFBQUlBLEtBQUtXLGVBQUwsSUFBd0JYLEtBQUthLG1CQUFqQyxFQUFzRDtBQUNwRCxZQUFNLElBQUlMLFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKLDREQUZJLENBQU47QUFHRDs7QUFFRDtBQUNBLFFBQUlWLEtBQUthLG1CQUFMLElBQTRCLENBQUNi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QUFDRDtBQUNBLFFBQUksQ0FBQ3VFLFNBQVNuRCxJQUFULENBQUwsRUFBcUI7QUFDbkIsWUFBTSxJQUFJWixZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKVixLQUFLLFdBQUwsSUFBb0IscUJBRGhCLENBQU47QUFFRDs7QUFFRCxXQUFPO0FBQ0xvQixVQURLO0FBRUx3RDtBQUZLLEtBQVA7QUFJRDs7QUFFRDs7Ozs7QUFLQSxTQUFPQyw0QkFBUCxDQUFvQ0YsYUFBcEMsRUFBb0U7QUFDbEUsVUFBTUcsZ0JBQWdCLHNCQUF0QjtBQUNBLFdBQU9ILGNBQWNJLE9BQWQsQ0FBc0IsR0FBdEIsTUFBK0JKLGNBQWNLLE1BQWQsR0FBdUIsQ0FBdEQsQ0FBd0Q7QUFBeEQsT0FDRkYsY0FBY0csSUFBZCxDQUFtQk4sYUFBbkIsQ0FETCxDQUZrRSxDQUcxQjtBQUN6Qzs7QUFFRDs7Ozs7O0FBTUEsU0FBT3RELGNBQVAsQ0FBc0IsRUFBRUQsSUFBRixFQUFRd0QsV0FBUixFQUF0QixFQUFtRjtBQUNqRixRQUFJQSxXQUFKLEVBQWlCO0FBQUU7QUFDakIsWUFBTU0sWUFBWTlELEtBQUswQyxXQUFMLEVBQWxCO0FBQ0EsYUFBT29CLFVBQVVDLFNBQVYsQ0FBb0IsQ0FBcEIsRUFBdUJELFVBQVVILE9BQVYsQ0FBa0IsR0FBbEIsQ0FBdkIsQ0FBUDtBQUNEO0FBQ0QsV0FBTzNELEtBQUswQyxXQUFMLEVBQVA7QUFDRDtBQXhNeUI7O1FBQWZoRSxjLEdBQUFBLGM7a0JBMk1FQSxjIiwiZmlsZSI6IlB1c2hDb250cm9sbGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyc2UgfSAgICAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgUmVzdFF1ZXJ5ICAgICAgICAgICAgICBmcm9tICcuLi9SZXN0UXVlcnknO1xuaW1wb3J0IFJlc3RXcml0ZSAgICAgICAgICAgICAgZnJvbSAnLi4vUmVzdFdyaXRlJztcbmltcG9ydCB7IG1hc3RlciB9ICAgICAgICAgICAgIGZyb20gJy4uL0F1dGgnO1xuaW1wb3J0IHsgcHVzaFN0YXR1c0hhbmRsZXIgfSAgZnJvbSAnLi4vU3RhdHVzSGFuZGxlcic7XG5pbXBvcnQgeyBhcHBseURldmljZVRva2VuRXhpc3RzIH0gZnJvbSAnLi4vUHVzaC91dGlscyc7XG5pbXBvcnQgeyBsb2dnZXIgfSAgICAgICAgICAgICAgIGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCBjbGFzcyBQdXNoQ29udHJvbGxlciB7XG5cbiAgc2VuZFB1c2goYm9keSA9IHt9LCB3aGVyZSA9IHt9LCBjb25maWcsIGF1dGgsIG9uUHVzaFN0YXR1c1NhdmVkID0gKCkgPT4ge30sIG5vdyA9IG5ldyBEYXRlKCkpIHtcbiAgICBpZiAoIWNvbmZpZy5oYXNQdXNoU3VwcG9ydCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgJ01pc3NpbmcgcHVzaCBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gUmVwbGFjZSB0aGUgZXhwaXJhdGlvbl90aW1lIGFuZCBwdXNoX3RpbWUgd2l0aCBhIHZhbGlkIFVuaXggZXBvY2ggbWlsbGlzZWNvbmRzIHRpbWVcbiAgICBib2R5LmV4cGlyYXRpb25fdGltZSA9IFB1c2hDb250cm9sbGVyLmdldEV4cGlyYXRpb25UaW1lKGJvZHkpO1xuICAgIGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCA9IFB1c2hDb250cm9sbGVyLmdldEV4cGlyYXRpb25JbnRlcnZhbChib2R5KTtcbiAgICBpZiAoYm9keS5leHBpcmF0aW9uX3RpbWUgJiYgYm9keS5leHBpcmF0aW9uX2ludGVydmFsKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgJ0JvdGggZXhwaXJhdGlvbl90aW1lIGFuZCBleHBpcmF0aW9uX2ludGVydmFsIGNhbm5vdCBiZSBzZXQnKTtcbiAgICB9XG5cbiAgICAvLyBJbW1lZGlhdGUgcHVzaFxuICAgIGlmIChib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwgJiYgIWJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpKSB7XG4gICAgICBjb25zdCB0dGxNcyA9IGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCAqIDEwMDA7XG4gICAgICBib2R5LmV4cGlyYXRpb25fdGltZSA9IChuZXcgRGF0ZShub3cudmFsdWVPZigpICsgdHRsTXMpKS52YWx1ZU9mKCk7XG4gICAgfVxuXG4gICAgY29uc3QgcHVzaFRpbWUgPSBQdXNoQ29udHJvbGxlci5nZXRQdXNoVGltZShib2R5KTtcbiAgICBpZiAocHVzaFRpbWUgJiYgcHVzaFRpbWUuZGF0ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGJvZHlbJ3B1c2hfdGltZSddID0gUHVzaENvbnRyb2xsZXIuZm9ybWF0UHVzaFRpbWUocHVzaFRpbWUpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IElmIHRoZSByZXEgY2FuIHBhc3MgdGhlIGNoZWNraW5nLCB3ZSByZXR1cm4gaW1tZWRpYXRlbHkgaW5zdGVhZCBvZiB3YWl0aW5nXG4gICAgLy8gcHVzaGVzIHRvIGJlIHNlbnQuIFdlIHByb2JhYmx5IGNoYW5nZSB0aGlzIGJlaGF2aW91ciBpbiB0aGUgZnV0dXJlLlxuICAgIGxldCBiYWRnZVVwZGF0ZSA9ICgpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBpZiAoYm9keS5kYXRhICYmIGJvZHkuZGF0YS5iYWRnZSkge1xuICAgICAgY29uc3QgYmFkZ2UgPSBib2R5LmRhdGEuYmFkZ2U7XG4gICAgICBsZXQgcmVzdFVwZGF0ZSA9IHt9O1xuICAgICAgaWYgKHR5cGVvZiBiYWRnZSA9PSAnc3RyaW5nJyAmJiBiYWRnZS50b0xvd2VyQ2FzZSgpID09PSAnaW5jcmVtZW50Jykge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiAxIH0gfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYmFkZ2UgPT0gJ29iamVjdCcgJiYgdHlwZW9mIGJhZGdlLl9fb3AgPT0gJ3N0cmluZycgJiZcbiAgICAgICAgICAgICAgICAgYmFkZ2UuX19vcC50b0xvd2VyQ2FzZSgpID09ICdpbmNyZW1lbnQnICYmIE51bWJlcihiYWRnZS5hbW91bnQpKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiB7IF9fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IGJhZGdlLmFtb3VudCB9IH1cbiAgICAgIH0gZWxzZSBpZiAoTnVtYmVyKGJhZGdlKSkge1xuICAgICAgICByZXN0VXBkYXRlID0geyBiYWRnZTogYmFkZ2UgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgXCJJbnZhbGlkIHZhbHVlIGZvciBiYWRnZSwgZXhwZWN0ZWQgbnVtYmVyIG9yICdJbmNyZW1lbnQnIG9yIHtpbmNyZW1lbnQ6IG51bWJlcn1cIjtcbiAgICAgIH1cblxuICAgICAgLy8gRm9yY2UgZmlsdGVyaW5nIG9uIG9ubHkgdmFsaWQgZGV2aWNlIHRva2Vuc1xuICAgICAgY29uc3QgdXBkYXRlV2hlcmUgPSBhcHBseURldmljZVRva2VuRXhpc3RzKHdoZXJlKTtcbiAgICAgIGJhZGdlVXBkYXRlID0gKCkgPT4ge1xuICAgICAgICAvLyBCdWlsZCBhIHJlYWwgUmVzdFF1ZXJ5IHNvIHdlIGNhbiB1c2UgaXQgaW4gUmVzdFdyaXRlXG4gICAgICAgIGNvbnN0IHJlc3RRdWVyeSA9IG5ldyBSZXN0UXVlcnkoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19JbnN0YWxsYXRpb24nLCB1cGRhdGVXaGVyZSk7XG4gICAgICAgIC8vIGNoYW5nZSAkZXhpc3RzIGZvciAkbmUgbnVsbCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAgICAgIGlmIChyZXN0UXVlcnkucmVzdFdoZXJlICYmIHJlc3RRdWVyeS5yZXN0V2hlcmUuZGV2aWNlVG9rZW4gJiYgcmVzdFF1ZXJ5LnJlc3RXaGVyZS5kZXZpY2VUb2tlblsnJGV4aXN0cyddKSByZXN0UXVlcnkucmVzdFdoZXJlLmRldmljZVRva2VuID0geyRuZTogbnVsbH1cbiAgICAgICAgcmV0dXJuIHJlc3RRdWVyeS5idWlsZFJlc3RXaGVyZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdyaXRlID0gbmV3IFJlc3RXcml0ZShjb25maWcsIG1hc3Rlcihjb25maWcpLCAnX0luc3RhbGxhdGlvbicsIHJlc3RRdWVyeS5yZXN0V2hlcmUsIHJlc3RVcGRhdGUpO1xuICAgICAgICAgIHdyaXRlLnJ1bk9wdGlvbnMubWFueSA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHB1c2hTdGF0dXMgPSBwdXNoU3RhdHVzSGFuZGxlcihjb25maWcpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBwdXNoU3RhdHVzLnNldEluaXRpYWwoYm9keSwgd2hlcmUpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgb25QdXNoU3RhdHVzU2F2ZWQocHVzaFN0YXR1cy5vYmplY3RJZCk7XG4gICAgICByZXR1cm4gYmFkZ2VVcGRhdGUoKTtcbiAgICB9KS5jYXRjaChlcnIgPT4ge1xuICAgICAgLy8gYWRkIHRoaXMgdG8gaWdub3JlIGJhZGdlIHVwZGF0ZSBlcnJvcnMgYXMgZGVmYXVsdFxuICAgICAgaWYgKGNvbmZpZy5zdG9wT25CYWRnZVVwZGF0ZUVycm9yKSB0aHJvdyBlcnI7XG4gICAgICBsb2dnZXIuaW5mbyhgQmFkZ2UgdXBkYXRlIGVycm9yIHdpbGwgYmUgaWdub3JlZCBmb3IgcHVzaCBzdGF0dXMgJHtwdXNoU3RhdHVzLm9iamVjdElkfWApO1xuICAgICAgbG9nZ2VyLmluZm8oZXJyICYmIGVyci5zdGFjayAmJiBlcnIuc3RhY2sudG9TdHJpbmcoKSB8fCBlcnIgJiYgZXJyLm1lc3NhZ2UgfHwgZXJyLnRvU3RyaW5nKCkpO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gVXBkYXRlIGF1ZGllbmNlIGxhc3RVc2VkIGFuZCB0aW1lc1VzZWRcbiAgICAgIGlmIChib2R5LmF1ZGllbmNlX2lkKSB7XG4gICAgICAgIGNvbnN0IGF1ZGllbmNlSWQgPSBib2R5LmF1ZGllbmNlX2lkO1xuXG4gICAgICAgIHZhciB1cGRhdGVBdWRpZW5jZSA9IHtcbiAgICAgICAgICBsYXN0VXNlZDogeyBfX3R5cGU6IFwiRGF0ZVwiLCBpc286IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSB9LFxuICAgICAgICAgIHRpbWVzVXNlZDogeyBfX29wOiBcIkluY3JlbWVudFwiLCBcImFtb3VudFwiOiAxIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfQXVkaWVuY2UnLCB7b2JqZWN0SWQ6IGF1ZGllbmNlSWR9LCB1cGRhdGVBdWRpZW5jZSk7XG4gICAgICAgIHdyaXRlLmV4ZWN1dGUoKTtcbiAgICAgIH1cbiAgICAgIC8vIERvbid0IHdhaXQgZm9yIHRoZSBhdWRpZW5jZSB1cGRhdGUgcHJvbWlzZSB0byByZXNvbHZlLlxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpICYmIGNvbmZpZy5oYXNQdXNoU2NoZWR1bGVkU3VwcG9ydCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29uZmlnLnB1c2hDb250cm9sbGVyUXVldWUuZW5xdWV1ZShib2R5LCB3aGVyZSwgY29uZmlnLCBhdXRoLCBwdXNoU3RhdHVzKTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICByZXR1cm4gcHVzaFN0YXR1cy5mYWlsKGVycikudGhlbigoKSA9PiB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBleHBpcmF0aW9uIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgZXhwaXJhdGlvbiB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldEV4cGlyYXRpb25UaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNFeHBpcmF0aW9uVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25fdGltZScpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvblRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV4cGlyYXRpb25UaW1lUGFyYW0gPSBib2R5WydleHBpcmF0aW9uX3RpbWUnXTtcbiAgICB2YXIgZXhwaXJhdGlvblRpbWU7XG4gICAgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwaXJhdGlvblRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGV4cGlyYXRpb25UaW1lID0gbmV3IERhdGUoZXhwaXJhdGlvblRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZXhwaXJhdGlvblRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIGV4cGlyYXRpb25UaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZXhwaXJhdGlvblRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBib2R5WydleHBpcmF0aW9uX3RpbWUnXSArICcgaXMgbm90IHZhbGlkIHRpbWUuJyk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uVGltZS52YWx1ZU9mKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkgPSB7fSkge1xuICAgIGNvbnN0IGhhc0V4cGlyYXRpb25JbnRlcnZhbCA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25faW50ZXJ2YWwnKTtcbiAgICBpZiAoIWhhc0V4cGlyYXRpb25JbnRlcnZhbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25faW50ZXJ2YWwnXTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtICE9PSAnbnVtYmVyJyB8fCBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICBgZXhwaXJhdGlvbl9pbnRlcnZhbCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAwYCk7XG4gICAgfVxuICAgIHJldHVybiBleHBpcmF0aW9uSW50ZXJ2YWxQYXJhbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcHVzaCB0aW1lIGZyb20gdGhlIHJlcXVlc3QgYm9keS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHJlcXVlc3QgQSByZXF1ZXN0IG9iamVjdFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfHVuZGVmaW5lZH0gVGhlIHB1c2ggdGltZSBpZiBpdCBleGlzdHMgaW4gdGhlIHJlcXVlc3RcbiAgICovXG4gIHN0YXRpYyBnZXRQdXNoVGltZShib2R5ID0ge30pIHtcbiAgICB2YXIgaGFzUHVzaFRpbWUgPSBib2R5Lmhhc093blByb3BlcnR5KCdwdXNoX3RpbWUnKTtcbiAgICBpZiAoIWhhc1B1c2hUaW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBwdXNoVGltZVBhcmFtID0gYm9keVsncHVzaF90aW1lJ107XG4gICAgdmFyIGRhdGU7XG4gICAgdmFyIGlzTG9jYWxUaW1lID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtICogMTAwMCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcHVzaFRpbWVQYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlzTG9jYWxUaW1lID0gIVB1c2hDb250cm9sbGVyLnB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbSk7XG4gICAgICBkYXRlID0gbmV3IERhdGUocHVzaFRpbWVQYXJhbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgcHVzaFRpbWUgaXMgdmFsaWQgb3Igbm90LCBpZiBpdCBpcyBub3QgdmFsaWQsIHB1c2hUaW1lIGlzIE5hTlxuICAgIGlmICghaXNGaW5pdGUoZGF0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ3B1c2hfdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0ZSxcbiAgICAgIGlzTG9jYWxUaW1lLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgSVNPODYwMSBmb3JtYXR0ZWQgZGF0ZSBjb250YWlucyBhIHRpbWV6b25lIGNvbXBvbmVudFxuICAgKiBAcGFyYW0gcHVzaFRpbWVQYXJhbSB7c3RyaW5nfVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50KHB1c2hUaW1lUGFyYW06IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG9mZnNldFBhdHRlcm4gPSAvKC4rKShbKy1dKVxcZFxcZDpcXGRcXGQkLztcbiAgICByZXR1cm4gcHVzaFRpbWVQYXJhbS5pbmRleE9mKCdaJykgPT09IHB1c2hUaW1lUGFyYW0ubGVuZ3RoIC0gMSAvLyAyMDA3LTA0LTA1VDEyOjMwWlxuICAgICAgfHwgb2Zmc2V0UGF0dGVybi50ZXN0KHB1c2hUaW1lUGFyYW0pOyAvLyAyMDA3LTA0LTA1VDEyOjMwLjAwMCswMjowMCwgMjAwNy0wNC0wNVQxMjozMC4wMDAtMDI6MDBcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGRhdGUgdG8gSVNPIGZvcm1hdCBpbiBVVEMgdGltZSBhbmQgc3RyaXBzIHRoZSB0aW1lem9uZSBpZiBgaXNMb2NhbFRpbWVgIGlzIHRydWVcbiAgICogQHBhcmFtIGRhdGUge0RhdGV9XG4gICAqIEBwYXJhbSBpc0xvY2FsVGltZSB7Ym9vbGVhbn1cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBmb3JtYXRQdXNoVGltZSh7IGRhdGUsIGlzTG9jYWxUaW1lIH06IHsgZGF0ZTogRGF0ZSwgaXNMb2NhbFRpbWU6IGJvb2xlYW4gfSkge1xuICAgIGlmIChpc0xvY2FsVGltZSkgeyAvLyBTdHJpcCAnWidcbiAgICAgIGNvbnN0IGlzb1N0cmluZyA9IGRhdGUudG9JU09TdHJpbmcoKTtcbiAgICAgIHJldHVybiBpc29TdHJpbmcuc3Vic3RyaW5nKDAsIGlzb1N0cmluZy5pbmRleE9mKCdaJykpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1c2hDb250cm9sbGVyO1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db250cm9sbGVycy9QdXNoQ29udHJvbGxlci5qcyJdLCJuYW1lcyI6WyJQdXNoQ29udHJvbGxlciIsInNlbmRQdXNoIiwiYm9keSIsIndoZXJlIiwiY29uZmlnIiwiYXV0aCIsIm9uUHVzaFN0YXR1c1NhdmVkIiwibm93IiwiRGF0ZSIsImhhc1B1c2hTdXBwb3J0IiwiUGFyc2UiLCJFcnJvciIsIlBVU0hfTUlTQ09ORklHVVJFRCIsImV4cGlyYXRpb25fdGltZSIsImdldEV4cGlyYXRpb25UaW1lIiwiZXhwaXJhdGlvbl9pbnRlcnZhbCIsImdldEV4cGlyYXRpb25JbnRlcnZhbCIsImhhc093blByb3BlcnR5IiwidHRsTXMiLCJ2YWx1ZU9mIiwicHVzaFRpbWUiLCJnZXRQdXNoVGltZSIsImRhdGUiLCJmb3JtYXRQdXNoVGltZSIsImJhZGdlVXBkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJkYXRhIiwiYmFkZ2UiLCJyZXN0VXBkYXRlIiwidG9Mb3dlckNhc2UiLCJfX29wIiwiYW1vdW50IiwiTnVtYmVyIiwidXBkYXRlV2hlcmUiLCJyZXN0UXVlcnkiLCJSZXN0UXVlcnkiLCJyZXN0V2hlcmUiLCJkZXZpY2VUb2tlbiIsIiRuZSIsImJ1aWxkUmVzdFdoZXJlIiwidGhlbiIsIndyaXRlIiwiUmVzdFdyaXRlIiwicnVuT3B0aW9ucyIsIm1hbnkiLCJleGVjdXRlIiwicHVzaFN0YXR1cyIsInNldEluaXRpYWwiLCJvYmplY3RJZCIsImNhdGNoIiwiZXJyIiwic3RvcE9uQmFkZ2VVcGRhdGVFcnJvciIsImxvZ2dlciIsImluZm8iLCJzdGFjayIsInRvU3RyaW5nIiwibWVzc2FnZSIsImF1ZGllbmNlX2lkIiwiYXVkaWVuY2VJZCIsInVwZGF0ZUF1ZGllbmNlIiwibGFzdFVzZWQiLCJfX3R5cGUiLCJpc28iLCJ0b0lTT1N0cmluZyIsInRpbWVzVXNlZCIsImhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0IiwicHVzaENvbnRyb2xsZXJRdWV1ZSIsImVucXVldWUiLCJmYWlsIiwiaGFzRXhwaXJhdGlvblRpbWUiLCJleHBpcmF0aW9uVGltZVBhcmFtIiwiZXhwaXJhdGlvblRpbWUiLCJpc0Zpbml0ZSIsImhhc0V4cGlyYXRpb25JbnRlcnZhbCIsImV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIiwiaGFzUHVzaFRpbWUiLCJwdXNoVGltZVBhcmFtIiwiaXNMb2NhbFRpbWUiLCJwdXNoVGltZUhhc1RpbWV6b25lQ29tcG9uZW50Iiwib2Zmc2V0UGF0dGVybiIsImluZGV4T2YiLCJsZW5ndGgiLCJ0ZXN0IiwiaXNvU3RyaW5nIiwic3Vic3RyaW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRU8sTUFBTUEsY0FBTixDQUFxQjs7QUFFMUJDLFdBQVNDLE9BQU8sRUFBaEIsRUFBb0JDLFFBQVEsRUFBNUIsRUFBZ0NDLE1BQWhDLEVBQXdDQyxJQUF4QyxFQUE4Q0Msb0JBQW9CLE1BQU0sQ0FBRSxDQUExRSxFQUE0RUMsTUFBTSxJQUFJQyxJQUFKLEVBQWxGLEVBQThGO0FBQzVGLFFBQUksQ0FBQ0osT0FBT0ssY0FBWixFQUE0QjtBQUMxQixZQUFNLElBQUlDLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0osNEJBREksQ0FBTjtBQUVEOztBQUVEO0FBQ0FWLFNBQUtXLGVBQUwsR0FBdUJiLGVBQWVjLGlCQUFmLENBQWlDWixJQUFqQyxDQUF2QjtBQUNBQSxTQUFLYSxtQkFBTCxHQUEyQmYsZUFBZWdCLHFCQUFmLENBQXFDZCxJQUFyQyxDQUEzQjtBQUNBLFFBQUlBLEtBQUtXLGVBQUwsSUFBd0JYLEtBQUthLG1CQUFqQyxFQUFzRDtBQUNwRCxZQUFNLElBQUlMLFlBQU1DLEtBQVYsQ0FDSkQsWUFBTUMsS0FBTixDQUFZQyxrQkFEUixFQUVKLDREQUZJLENBQU47QUFHRDs7QUFFRDtBQUNBLFFBQUlWLEtBQUthLG1CQUFMLElBQTRCLENBQUNiLEtBQUtlLGNBQUwsQ0FBb0IsV0FBcEIsQ0FBakMsRUFBbUU7QUFDakUsWUFBTUMsUUFBUWhCLEtBQUthLG1CQUFMLEdBQTJCLElBQXpDO0FBQ0FiLFdBQUtXLGVBQUwsR0FBd0IsSUFBSUwsSUFBSixDQUFTRCxJQUFJWSxPQUFKLEtBQWdCRCxLQUF6QixDQUFELENBQWtDQyxPQUFsQyxFQUF2QjtBQUNEOztBQUVELFVBQU1DLFdBQVdwQixlQUFlcUIsV0FBZixDQUEyQm5CLElBQTNCLENBQWpCO0FBQ0EsUUFBSWtCLFlBQVlBLFNBQVNFLElBQVQsS0FBa0IsV0FBbEMsRUFBK0M7QUFDN0NwQixXQUFLLFdBQUwsSUFBb0JGLGVBQWV1QixjQUFmLENBQThCSCxRQUE5QixDQUFwQjtBQUNEOztBQUVEO0FBQ0E7QUFDQSxRQUFJSSxjQUFjLE1BQU07QUFDdEIsYUFBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0QsS0FGRDs7QUFJQSxRQUFJeEIsS0FBS3lCLElBQUwsSUFBYXpCLEtBQUt5QixJQUFMLENBQVVDLEtBQTNCLEVBQWtDO0FBQ2hDLFlBQU1BLFFBQVExQixLQUFLeUIsSUFBTCxDQUFVQyxLQUF4QjtBQUNBLFVBQUlDLGFBQWEsRUFBakI7QUFDQSxVQUFJLE9BQU9ELEtBQVAsSUFBZ0IsUUFBaEIsSUFBNEJBLE1BQU1FLFdBQU4sT0FBd0IsV0FBeEQsRUFBcUU7QUFDbkVELHFCQUFhLEVBQUVELE9BQU8sRUFBRUcsTUFBTSxXQUFSLEVBQXFCQyxRQUFRLENBQTdCLEVBQVQsRUFBYjtBQUNELE9BRkQsTUFFTyxJQUFJLE9BQU9KLEtBQVAsSUFBZ0IsUUFBaEIsSUFBNEIsT0FBT0EsTUFBTUcsSUFBYixJQUFxQixRQUFqRCxJQUNBSCxNQUFNRyxJQUFOLENBQVdELFdBQVgsTUFBNEIsV0FENUIsSUFDMkNHLE9BQU9MLE1BQU1JLE1BQWIsQ0FEL0MsRUFDcUU7QUFDMUVILHFCQUFhLEVBQUVELE9BQU8sRUFBRUcsTUFBTSxXQUFSLEVBQXFCQyxRQUFRSixNQUFNSSxNQUFuQyxFQUFULEVBQWI7QUFDRCxPQUhNLE1BR0EsSUFBSUMsT0FBT0wsS0FBUCxDQUFKLEVBQW1CO0FBQ3hCQyxxQkFBYSxFQUFFRCxPQUFPQSxLQUFULEVBQWI7QUFDRCxPQUZNLE1BRUE7QUFDTCxjQUFNLGdGQUFOO0FBQ0Q7O0FBRUQ7QUFDQSxZQUFNTSxjQUFjLG1DQUF1Qi9CLEtBQXZCLENBQXBCO0FBQ0FxQixvQkFBYyxNQUFNO0FBQ2xCO0FBQ0EsY0FBTVcsWUFBWSxJQUFJQyxtQkFBSixDQUFjaEMsTUFBZCxFQUFzQixrQkFBT0EsTUFBUCxDQUF0QixFQUFzQyxlQUF0QyxFQUF1RDhCLFdBQXZELENBQWxCO0FBQ0E7QUFDQSxZQUFJQyxVQUFVRSxTQUFWLElBQXVCRixVQUFVRSxTQUFWLENBQW9CQyxXQUEzQyxJQUEwREgsVUFBVUUsU0FBVixDQUFvQkMsV0FBcEIsQ0FBZ0MsU0FBaEMsQ0FBOUQsRUFBMEdILFVBQVVFLFNBQVYsQ0FBb0JDLFdBQXBCLEdBQWtDLEVBQUNDLEtBQUssSUFBTixFQUFsQztBQUMxRyxlQUFPSixVQUFVSyxjQUFWLEdBQTJCQyxJQUEzQixDQUFnQyxNQUFNO0FBQzNDLGdCQUFNQyxRQUFRLElBQUlDLG1CQUFKLENBQWN2QyxNQUFkLEVBQXNCLGtCQUFPQSxNQUFQLENBQXRCLEVBQXNDLGVBQXRDLEVBQXVEK0IsVUFBVUUsU0FBakUsRUFBNEVSLFVBQTVFLENBQWQ7QUFDQWEsZ0JBQU1FLFVBQU4sQ0FBaUJDLElBQWpCLEdBQXdCLElBQXhCO0FBQ0EsaUJBQU9ILE1BQU1JLE9BQU4sRUFBUDtBQUNELFNBSk0sQ0FBUDtBQUtELE9BVkQ7QUFXRDtBQUNELFVBQU1DLGFBQWEsc0NBQWtCM0MsTUFBbEIsQ0FBbkI7QUFDQSxXQUFPcUIsUUFBUUMsT0FBUixHQUFrQmUsSUFBbEIsQ0FBdUIsTUFBTTtBQUNsQyxhQUFPTSxXQUFXQyxVQUFYLENBQXNCOUMsSUFBdEIsRUFBNEJDLEtBQTVCLENBQVA7QUFDRCxLQUZNLEVBRUpzQyxJQUZJLENBRUMsTUFBTTtBQUNabkMsd0JBQWtCeUMsV0FBV0UsUUFBN0I7QUFDQSxhQUFPekIsY0FBYzBCLEtBQWQsQ0FBb0JDLE9BQU87QUFDaEM7QUFDQSxZQUFJL0MsT0FBT2dELHNCQUFYLEVBQW1DLE1BQU1ELEdBQU47QUFDbkNFLHVCQUFPQyxJQUFQLENBQWEsc0RBQXFEUCxXQUFXRSxRQUFTLEVBQXRGO0FBQ0FJLHVCQUFPQyxJQUFQLENBQVlILE9BQU9BLElBQUlJLEtBQVgsSUFBb0JKLElBQUlJLEtBQUosQ0FBVUMsUUFBVixFQUFwQixJQUE0Q0wsT0FBT0EsSUFBSU0sT0FBdkQsSUFBa0VOLElBQUlLLFFBQUosRUFBOUU7QUFDQSxlQUFPL0IsUUFBUUMsT0FBUixFQUFQO0FBQ0QsT0FOTSxDQUFQO0FBT0QsS0FYTSxFQVdKZSxJQVhJLENBV0MsTUFBTTtBQUNaO0FBQ0EsVUFBSXZDLEtBQUt3RCxXQUFULEVBQXNCO0FBQ3BCLGNBQU1DLGFBQWF6RCxLQUFLd0QsV0FBeEI7O0FBRUEsWUFBSUUsaUJBQWlCO0FBQ25CQyxvQkFBVSxFQUFFQyxRQUFRLE1BQVYsRUFBa0JDLEtBQUssSUFBSXZELElBQUosR0FBV3dELFdBQVgsRUFBdkIsRUFEUztBQUVuQkMscUJBQVcsRUFBRWxDLE1BQU0sV0FBUixFQUFxQixVQUFVLENBQS9CO0FBRlEsU0FBckI7QUFJQSxjQUFNVyxRQUFRLElBQUlDLG1CQUFKLENBQWN2QyxNQUFkLEVBQXNCLGtCQUFPQSxNQUFQLENBQXRCLEVBQXNDLFdBQXRDLEVBQW1ELEVBQUM2QyxVQUFVVSxVQUFYLEVBQW5ELEVBQTJFQyxjQUEzRSxDQUFkO0FBQ0FsQixjQUFNSSxPQUFOO0FBQ0Q7QUFDRDtBQUNBLGFBQU9yQixRQUFRQyxPQUFSLEVBQVA7QUFDRCxLQXpCTSxFQXlCSmUsSUF6QkksQ0F5QkMsTUFBTTtBQUNaLFVBQUl2QyxLQUFLZSxjQUFMLENBQW9CLFdBQXBCLEtBQW9DYixPQUFPOEQsdUJBQS9DLEVBQXdFO0FBQ3RFLGVBQU96QyxRQUFRQyxPQUFSLEVBQVA7QUFDRDtBQUNELGFBQU90QixPQUFPK0QsbUJBQVAsQ0FBMkJDLE9BQTNCLENBQW1DbEUsSUFBbkMsRUFBeUNDLEtBQXpDLEVBQWdEQyxNQUFoRCxFQUF3REMsSUFBeEQsRUFBOEQwQyxVQUE5RCxDQUFQO0FBQ0QsS0E5Qk0sRUE4QkpHLEtBOUJJLENBOEJHQyxHQUFELElBQVM7QUFDaEIsYUFBT0osV0FBV3NCLElBQVgsQ0FBZ0JsQixHQUFoQixFQUFxQlYsSUFBckIsQ0FBMEIsTUFBTTtBQUNyQyxjQUFNVSxHQUFOO0FBQ0QsT0FGTSxDQUFQO0FBR0QsS0FsQ00sQ0FBUDtBQW1DRDs7QUFFRDs7Ozs7QUFLQSxTQUFPckMsaUJBQVAsQ0FBeUJaLE9BQU8sRUFBaEMsRUFBb0M7QUFDbEMsUUFBSW9FLG9CQUFvQnBFLEtBQUtlLGNBQUwsQ0FBb0IsaUJBQXBCLENBQXhCO0FBQ0EsUUFBSSxDQUFDcUQsaUJBQUwsRUFBd0I7QUFDdEI7QUFDRDtBQUNELFFBQUlDLHNCQUFzQnJFLEtBQUssaUJBQUwsQ0FBMUI7QUFDQSxRQUFJc0UsY0FBSjtBQUNBLFFBQUksT0FBT0QsbUJBQVAsS0FBK0IsUUFBbkMsRUFBNkM7QUFDM0NDLHVCQUFpQixJQUFJaEUsSUFBSixDQUFTK0Qsc0JBQXNCLElBQS9CLENBQWpCO0FBQ0QsS0FGRCxNQUVPLElBQUksT0FBT0EsbUJBQVAsS0FBK0IsUUFBbkMsRUFBNkM7QUFDbERDLHVCQUFpQixJQUFJaEUsSUFBSixDQUFTK0QsbUJBQVQsQ0FBakI7QUFDRCxLQUZNLE1BRUE7QUFDTCxZQUFNLElBQUk3RCxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKVixLQUFLLGlCQUFMLElBQTBCLHFCQUR0QixDQUFOO0FBRUQ7QUFDRDtBQUNBLFFBQUksQ0FBQ3VFLFNBQVNELGNBQVQsQ0FBTCxFQUErQjtBQUM3QixZQUFNLElBQUk5RCxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKVixLQUFLLGlCQUFMLElBQTBCLHFCQUR0QixDQUFOO0FBRUQ7QUFDRCxXQUFPc0UsZUFBZXJELE9BQWYsRUFBUDtBQUNEOztBQUVELFNBQU9ILHFCQUFQLENBQTZCZCxPQUFPLEVBQXBDLEVBQXdDO0FBQ3RDLFVBQU13RSx3QkFBd0J4RSxLQUFLZSxjQUFMLENBQW9CLHFCQUFwQixDQUE5QjtBQUNBLFFBQUksQ0FBQ3lELHFCQUFMLEVBQTRCO0FBQzFCO0FBQ0Q7O0FBRUQsUUFBSUMsMEJBQTBCekUsS0FBSyxxQkFBTCxDQUE5QjtBQUNBLFFBQUksT0FBT3lFLHVCQUFQLEtBQW1DLFFBQW5DLElBQStDQSwyQkFBMkIsQ0FBOUUsRUFBaUY7QUFDL0UsWUFBTSxJQUFJakUsWUFBTUMsS0FBVixDQUFnQkQsWUFBTUMsS0FBTixDQUFZQyxrQkFBNUIsRUFDSCxxREFERyxDQUFOO0FBRUQ7QUFDRCxXQUFPK0QsdUJBQVA7QUFDRDs7QUFFRDs7Ozs7QUFLQSxTQUFPdEQsV0FBUCxDQUFtQm5CLE9BQU8sRUFBMUIsRUFBOEI7QUFDNUIsUUFBSTBFLGNBQWMxRSxLQUFLZSxjQUFMLENBQW9CLFdBQXBCLENBQWxCO0FBQ0EsUUFBSSxDQUFDMkQsV0FBTCxFQUFrQjtBQUNoQjtBQUNEO0FBQ0QsUUFBSUMsZ0JBQWdCM0UsS0FBSyxXQUFMLENBQXBCO0FBQ0EsUUFBSW9CLElBQUo7QUFDQSxRQUFJd0QsY0FBYyxJQUFsQjs7QUFFQSxRQUFJLE9BQU9ELGFBQVAsS0FBeUIsUUFBN0IsRUFBdUM7QUFDckN2RCxhQUFPLElBQUlkLElBQUosQ0FBU3FFLGdCQUFnQixJQUF6QixDQUFQO0FBQ0QsS0FGRCxNQUVPLElBQUksT0FBT0EsYUFBUCxLQUF5QixRQUE3QixFQUF1QztBQUM1Q0Msb0JBQWMsQ0FBQzlFLGVBQWUrRSw0QkFBZixDQUE0Q0YsYUFBNUMsQ0FBZjtBQUNBdkQsYUFBTyxJQUFJZCxJQUFKLENBQVNxRSxhQUFULENBQVA7QUFDRCxLQUhNLE1BR0E7QUFDTCxZQUFNLElBQUluRSxZQUFNQyxLQUFWLENBQWdCRCxZQUFNQyxLQUFOLENBQVlDLGtCQUE1QixFQUNKVixLQUFLLFdBQUwsSUFBb0IscUJBRGhCLENBQU47QUFFRDtBQUNEO0FBQ0EsUUFBSSxDQUFDdUUsU0FBU25ELElBQVQsQ0FBTCxFQUFxQjtBQUNuQixZQUFNLElBQUlaLFlBQU1DLEtBQVYsQ0FBZ0JELFlBQU1DLEtBQU4sQ0FBWUMsa0JBQTVCLEVBQ0pWLEtBQUssV0FBTCxJQUFvQixxQkFEaEIsQ0FBTjtBQUVEOztBQUVELFdBQU87QUFDTG9CLFVBREs7QUFFTHdEO0FBRkssS0FBUDtBQUlEOztBQUVEOzs7OztBQUtBLFNBQU9DLDRCQUFQLENBQW9DRixhQUFwQyxFQUFvRTtBQUNsRSxVQUFNRyxnQkFBZ0Isc0JBQXRCO0FBQ0EsV0FBT0gsY0FBY0ksT0FBZCxDQUFzQixHQUF0QixNQUErQkosY0FBY0ssTUFBZCxHQUF1QixDQUF0RCxDQUF3RDtBQUF4RCxPQUNGRixjQUFjRyxJQUFkLENBQW1CTixhQUFuQixDQURMLENBRmtFLENBRzFCO0FBQ3pDOztBQUVEOzs7Ozs7QUFNQSxTQUFPdEQsY0FBUCxDQUFzQixFQUFFRCxJQUFGLEVBQVF3RCxXQUFSLEVBQXRCLEVBQW1GO0FBQ2pGLFFBQUlBLFdBQUosRUFBaUI7QUFBRTtBQUNqQixZQUFNTSxZQUFZOUQsS0FBSzBDLFdBQUwsRUFBbEI7QUFDQSxhQUFPb0IsVUFBVUMsU0FBVixDQUFvQixDQUFwQixFQUF1QkQsVUFBVUgsT0FBVixDQUFrQixHQUFsQixDQUF2QixDQUFQO0FBQ0Q7QUFDRCxXQUFPM0QsS0FBSzBDLFdBQUwsRUFBUDtBQUNEO0FBeE15Qjs7UUFBZmhFLGMsR0FBQUEsYztrQkEyTUVBLGMiLCJmaWxlIjoiUHVzaENvbnRyb2xsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXJzZSB9ICAgICAgICAgICAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBSZXN0UXVlcnkgICAgICAgICAgICAgIGZyb20gJy4uL1Jlc3RRdWVyeSc7XG5pbXBvcnQgUmVzdFdyaXRlICAgICAgICAgICAgICBmcm9tICcuLi9SZXN0V3JpdGUnO1xuaW1wb3J0IHsgbWFzdGVyIH0gICAgICAgICAgICAgZnJvbSAnLi4vQXV0aCc7XG5pbXBvcnQgeyBwdXNoU3RhdHVzSGFuZGxlciB9ICBmcm9tICcuLi9TdGF0dXNIYW5kbGVyJztcbmltcG9ydCB7IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMgfSBmcm9tICcuLi9QdXNoL3V0aWxzJztcbmltcG9ydCB7IGxvZ2dlciB9ICAgICAgICAgICAgICAgZnJvbSAnLi4vbG9nZ2VyJztcblxuZXhwb3J0IGNsYXNzIFB1c2hDb250cm9sbGVyIHtcblxuICBzZW5kUHVzaChib2R5ID0ge30sIHdoZXJlID0ge30sIGNvbmZpZywgYXV0aCwgb25QdXNoU3RhdHVzU2F2ZWQgPSAoKSA9PiB7fSwgbm93ID0gbmV3IERhdGUoKSkge1xuICAgIGlmICghY29uZmlnLmhhc1B1c2hTdXBwb3J0KSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnTWlzc2luZyBwdXNoIGNvbmZpZ3VyYXRpb24nKTtcbiAgICB9XG5cbiAgICAvLyBSZXBsYWNlIHRoZSBleHBpcmF0aW9uX3RpbWUgYW5kIHB1c2hfdGltZSB3aXRoIGEgdmFsaWQgVW5peCBlcG9jaCBtaWxsaXNlY29uZHMgdGltZVxuICAgIGJvZHkuZXhwaXJhdGlvbl90aW1lID0gUHVzaENvbnRyb2xsZXIuZ2V0RXhwaXJhdGlvblRpbWUoYm9keSk7XG4gICAgYm9keS5leHBpcmF0aW9uX2ludGVydmFsID0gUHVzaENvbnRyb2xsZXIuZ2V0RXhwaXJhdGlvbkludGVydmFsKGJvZHkpO1xuICAgIGlmIChib2R5LmV4cGlyYXRpb25fdGltZSAmJiBib2R5LmV4cGlyYXRpb25faW50ZXJ2YWwpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuUFVTSF9NSVNDT05GSUdVUkVELFxuICAgICAgICAnQm90aCBleHBpcmF0aW9uX3RpbWUgYW5kIGV4cGlyYXRpb25faW50ZXJ2YWwgY2Fubm90IGJlIHNldCcpO1xuICAgIH1cblxuICAgIC8vIEltbWVkaWF0ZSBwdXNoXG4gICAgaWYgKGJvZHkuZXhwaXJhdGlvbl9pbnRlcnZhbCAmJiAhYm9keS5oYXNPd25Qcm9wZXJ0eSgncHVzaF90aW1lJykpIHtcbiAgICAgIGNvbnN0IHR0bE1zID0gYm9keS5leHBpcmF0aW9uX2ludGVydmFsICogMTAwMDtcbiAgICAgIGJvZHkuZXhwaXJhdGlvbl90aW1lID0gKG5ldyBEYXRlKG5vdy52YWx1ZU9mKCkgKyB0dGxNcykpLnZhbHVlT2YoKTtcbiAgICB9XG5cbiAgICBjb25zdCBwdXNoVGltZSA9IFB1c2hDb250cm9sbGVyLmdldFB1c2hUaW1lKGJvZHkpO1xuICAgIGlmIChwdXNoVGltZSAmJiBwdXNoVGltZS5kYXRlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgYm9keVsncHVzaF90aW1lJ10gPSBQdXNoQ29udHJvbGxlci5mb3JtYXRQdXNoVGltZShwdXNoVGltZSk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogSWYgdGhlIHJlcSBjYW4gcGFzcyB0aGUgY2hlY2tpbmcsIHdlIHJldHVybiBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIHdhaXRpbmdcbiAgICAvLyBwdXNoZXMgdG8gYmUgc2VudC4gV2UgcHJvYmFibHkgY2hhbmdlIHRoaXMgYmVoYXZpb3VyIGluIHRoZSBmdXR1cmUuXG4gICAgbGV0IGJhZGdlVXBkYXRlID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIGlmIChib2R5LmRhdGEgJiYgYm9keS5kYXRhLmJhZGdlKSB7XG4gICAgICBjb25zdCBiYWRnZSA9IGJvZHkuZGF0YS5iYWRnZTtcbiAgICAgIGxldCByZXN0VXBkYXRlID0ge307XG4gICAgICBpZiAodHlwZW9mIGJhZGdlID09ICdzdHJpbmcnICYmIGJhZGdlLnRvTG93ZXJDYXNlKCkgPT09ICdpbmNyZW1lbnQnKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiB7IF9fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IDEgfSB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBiYWRnZSA9PSAnb2JqZWN0JyAmJiB0eXBlb2YgYmFkZ2UuX19vcCA9PSAnc3RyaW5nJyAmJlxuICAgICAgICAgICAgICAgICBiYWRnZS5fX29wLnRvTG93ZXJDYXNlKCkgPT0gJ2luY3JlbWVudCcgJiYgTnVtYmVyKGJhZGdlLmFtb3VudCkpIHtcbiAgICAgICAgcmVzdFVwZGF0ZSA9IHsgYmFkZ2U6IHsgX19vcDogJ0luY3JlbWVudCcsIGFtb3VudDogYmFkZ2UuYW1vdW50IH0gfVxuICAgICAgfSBlbHNlIGlmIChOdW1iZXIoYmFkZ2UpKSB7XG4gICAgICAgIHJlc3RVcGRhdGUgPSB7IGJhZGdlOiBiYWRnZSB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBcIkludmFsaWQgdmFsdWUgZm9yIGJhZGdlLCBleHBlY3RlZCBudW1iZXIgb3IgJ0luY3JlbWVudCcgb3Ige2luY3JlbWVudDogbnVtYmVyfVwiO1xuICAgICAgfVxuXG4gICAgICAvLyBGb3JjZSBmaWx0ZXJpbmcgb24gb25seSB2YWxpZCBkZXZpY2UgdG9rZW5zXG4gICAgICBjb25zdCB1cGRhdGVXaGVyZSA9IGFwcGx5RGV2aWNlVG9rZW5FeGlzdHMod2hlcmUpO1xuICAgICAgYmFkZ2VVcGRhdGUgPSAoKSA9PiB7XG4gICAgICAgIC8vIEJ1aWxkIGEgcmVhbCBSZXN0UXVlcnkgc28gd2UgY2FuIHVzZSBpdCBpbiBSZXN0V3JpdGVcbiAgICAgICAgY29uc3QgcmVzdFF1ZXJ5ID0gbmV3IFJlc3RRdWVyeShjb25maWcsIG1hc3Rlcihjb25maWcpLCAnX0luc3RhbGxhdGlvbicsIHVwZGF0ZVdoZXJlKTtcbiAgICAgICAgLy8gY2hhbmdlICRleGlzdHMgZm9yICRuZSBudWxsIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICAgICAgaWYgKHJlc3RRdWVyeS5yZXN0V2hlcmUgJiYgcmVzdFF1ZXJ5LnJlc3RXaGVyZS5kZXZpY2VUb2tlbiAmJiByZXN0UXVlcnkucmVzdFdoZXJlLmRldmljZVRva2VuWyckZXhpc3RzJ10pIHJlc3RRdWVyeS5yZXN0V2hlcmUuZGV2aWNlVG9rZW4gPSB7JG5lOiBudWxsfVxuICAgICAgICByZXR1cm4gcmVzdFF1ZXJ5LmJ1aWxkUmVzdFdoZXJlKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgd3JpdGUgPSBuZXcgUmVzdFdyaXRlKGNvbmZpZywgbWFzdGVyKGNvbmZpZyksICdfSW5zdGFsbGF0aW9uJywgcmVzdFF1ZXJ5LnJlc3RXaGVyZSwgcmVzdFVwZGF0ZSk7XG4gICAgICAgICAgd3JpdGUucnVuT3B0aW9ucy5tYW55ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcHVzaFN0YXR1cyA9IHB1c2hTdGF0dXNIYW5kbGVyKGNvbmZpZyk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIHB1c2hTdGF0dXMuc2V0SW5pdGlhbChib2R5LCB3aGVyZSk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBvblB1c2hTdGF0dXNTYXZlZChwdXNoU3RhdHVzLm9iamVjdElkKTtcbiAgICAgIHJldHVybiBiYWRnZVVwZGF0ZSgpLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIC8vIGFkZCB0aGlzIHRvIGlnbm9yZSBiYWRnZSB1cGRhdGUgZXJyb3JzIGFzIGRlZmF1bHRcbiAgICAgICAgaWYgKGNvbmZpZy5zdG9wT25CYWRnZVVwZGF0ZUVycm9yKSB0aHJvdyBlcnI7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBCYWRnZSB1cGRhdGUgZXJyb3Igd2lsbCBiZSBpZ25vcmVkIGZvciBwdXNoIHN0YXR1cyAke3B1c2hTdGF0dXMub2JqZWN0SWR9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKGVyciAmJiBlcnIuc3RhY2sgJiYgZXJyLnN0YWNrLnRvU3RyaW5nKCkgfHwgZXJyICYmIGVyci5tZXNzYWdlIHx8IGVyci50b1N0cmluZygpKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAvLyBVcGRhdGUgYXVkaWVuY2UgbGFzdFVzZWQgYW5kIHRpbWVzVXNlZFxuICAgICAgaWYgKGJvZHkuYXVkaWVuY2VfaWQpIHtcbiAgICAgICAgY29uc3QgYXVkaWVuY2VJZCA9IGJvZHkuYXVkaWVuY2VfaWQ7XG5cbiAgICAgICAgdmFyIHVwZGF0ZUF1ZGllbmNlID0ge1xuICAgICAgICAgIGxhc3RVc2VkOiB7IF9fdHlwZTogXCJEYXRlXCIsIGlzbzogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH0sXG4gICAgICAgICAgdGltZXNVc2VkOiB7IF9fb3A6IFwiSW5jcmVtZW50XCIsIFwiYW1vdW50XCI6IDEgfVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB3cml0ZSA9IG5ldyBSZXN0V3JpdGUoY29uZmlnLCBtYXN0ZXIoY29uZmlnKSwgJ19BdWRpZW5jZScsIHtvYmplY3RJZDogYXVkaWVuY2VJZH0sIHVwZGF0ZUF1ZGllbmNlKTtcbiAgICAgICAgd3JpdGUuZXhlY3V0ZSgpO1xuICAgICAgfVxuICAgICAgLy8gRG9uJ3Qgd2FpdCBmb3IgdGhlIGF1ZGllbmNlIHVwZGF0ZSBwcm9taXNlIHRvIHJlc29sdmUuXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfSkudGhlbigoKSA9PiB7XG4gICAgICBpZiAoYm9keS5oYXNPd25Qcm9wZXJ0eSgncHVzaF90aW1lJykgJiYgY29uZmlnLmhhc1B1c2hTY2hlZHVsZWRTdXBwb3J0KSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb25maWcucHVzaENvbnRyb2xsZXJRdWV1ZS5lbnF1ZXVlKGJvZHksIHdoZXJlLCBjb25maWcsIGF1dGgsIHB1c2hTdGF0dXMpO1xuICAgIH0pLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIHJldHVybiBwdXNoU3RhdHVzLmZhaWwoZXJyKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGV4cGlyYXRpb24gdGltZSBmcm9tIHRoZSByZXF1ZXN0IGJvZHkuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSByZXF1ZXN0IEEgcmVxdWVzdCBvYmplY3RcbiAgICogQHJldHVybnMge051bWJlcnx1bmRlZmluZWR9IFRoZSBleHBpcmF0aW9uIHRpbWUgaWYgaXQgZXhpc3RzIGluIHRoZSByZXF1ZXN0XG4gICAqL1xuICBzdGF0aWMgZ2V0RXhwaXJhdGlvblRpbWUoYm9keSA9IHt9KSB7XG4gICAgdmFyIGhhc0V4cGlyYXRpb25UaW1lID0gYm9keS5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJhdGlvbl90aW1lJyk7XG4gICAgaWYgKCFoYXNFeHBpcmF0aW9uVGltZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgZXhwaXJhdGlvblRpbWVQYXJhbSA9IGJvZHlbJ2V4cGlyYXRpb25fdGltZSddO1xuICAgIHZhciBleHBpcmF0aW9uVGltZTtcbiAgICBpZiAodHlwZW9mIGV4cGlyYXRpb25UaW1lUGFyYW0gPT09ICdudW1iZXInKSB7XG4gICAgICBleHBpcmF0aW9uVGltZSA9IG5ldyBEYXRlKGV4cGlyYXRpb25UaW1lUGFyYW0gKiAxMDAwKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBpcmF0aW9uVGltZVBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgZXhwaXJhdGlvblRpbWUgPSBuZXcgRGF0ZShleHBpcmF0aW9uVGltZVBhcmFtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsnZXhwaXJhdGlvbl90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cbiAgICAvLyBDaGVjayBleHBpcmF0aW9uVGltZSBpcyB2YWxpZCBvciBub3QsIGlmIGl0IGlzIG5vdCB2YWxpZCwgZXhwaXJhdGlvblRpbWUgaXMgTmFOXG4gICAgaWYgKCFpc0Zpbml0ZShleHBpcmF0aW9uVGltZSkpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGJvZHlbJ2V4cGlyYXRpb25fdGltZSddICsgJyBpcyBub3QgdmFsaWQgdGltZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4cGlyYXRpb25UaW1lLnZhbHVlT2YoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXRFeHBpcmF0aW9uSW50ZXJ2YWwoYm9keSA9IHt9KSB7XG4gICAgY29uc3QgaGFzRXhwaXJhdGlvbkludGVydmFsID0gYm9keS5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJhdGlvbl9pbnRlcnZhbCcpO1xuICAgIGlmICghaGFzRXhwaXJhdGlvbkludGVydmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtID0gYm9keVsnZXhwaXJhdGlvbl9pbnRlcnZhbCddO1xuICAgIGlmICh0eXBlb2YgZXhwaXJhdGlvbkludGVydmFsUGFyYW0gIT09ICdudW1iZXInIHx8IGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5QVVNIX01JU0NPTkZJR1VSRUQsXG4gICAgICAgIGBleHBpcmF0aW9uX2ludGVydmFsIG11c3QgYmUgYSBudW1iZXIgZ3JlYXRlciB0aGFuIDBgKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4cGlyYXRpb25JbnRlcnZhbFBhcmFtO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBwdXNoIHRpbWUgZnJvbSB0aGUgcmVxdWVzdCBib2R5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBBIHJlcXVlc3Qgb2JqZWN0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ8dW5kZWZpbmVkfSBUaGUgcHVzaCB0aW1lIGlmIGl0IGV4aXN0cyBpbiB0aGUgcmVxdWVzdFxuICAgKi9cbiAgc3RhdGljIGdldFB1c2hUaW1lKGJvZHkgPSB7fSkge1xuICAgIHZhciBoYXNQdXNoVGltZSA9IGJvZHkuaGFzT3duUHJvcGVydHkoJ3B1c2hfdGltZScpO1xuICAgIGlmICghaGFzUHVzaFRpbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHB1c2hUaW1lUGFyYW0gPSBib2R5WydwdXNoX3RpbWUnXTtcbiAgICB2YXIgZGF0ZTtcbiAgICB2YXIgaXNMb2NhbFRpbWUgPSB0cnVlO1xuXG4gICAgaWYgKHR5cGVvZiBwdXNoVGltZVBhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgZGF0ZSA9IG5ldyBEYXRlKHB1c2hUaW1lUGFyYW0gKiAxMDAwKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwdXNoVGltZVBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgaXNMb2NhbFRpbWUgPSAhUHVzaENvbnRyb2xsZXIucHVzaFRpbWVIYXNUaW1lem9uZUNvbXBvbmVudChwdXNoVGltZVBhcmFtKTtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShwdXNoVGltZVBhcmFtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cbiAgICAvLyBDaGVjayBwdXNoVGltZSBpcyB2YWxpZCBvciBub3QsIGlmIGl0IGlzIG5vdCB2YWxpZCwgcHVzaFRpbWUgaXMgTmFOXG4gICAgaWYgKCFpc0Zpbml0ZShkYXRlKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBVU0hfTUlTQ09ORklHVVJFRCxcbiAgICAgICAgYm9keVsncHVzaF90aW1lJ10gKyAnIGlzIG5vdCB2YWxpZCB0aW1lLicpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkYXRlLFxuICAgICAgaXNMb2NhbFRpbWUsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYSBJU084NjAxIGZvcm1hdHRlZCBkYXRlIGNvbnRhaW5zIGEgdGltZXpvbmUgY29tcG9uZW50XG4gICAqIEBwYXJhbSBwdXNoVGltZVBhcmFtIHtzdHJpbmd9XG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIHB1c2hUaW1lSGFzVGltZXpvbmVDb21wb25lbnQocHVzaFRpbWVQYXJhbTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb2Zmc2V0UGF0dGVybiA9IC8oLispKFsrLV0pXFxkXFxkOlxcZFxcZCQvO1xuICAgIHJldHVybiBwdXNoVGltZVBhcmFtLmluZGV4T2YoJ1onKSA9PT0gcHVzaFRpbWVQYXJhbS5sZW5ndGggLSAxIC8vIDIwMDctMDQtMDVUMTI6MzBaXG4gICAgICB8fCBvZmZzZXRQYXR0ZXJuLnRlc3QocHVzaFRpbWVQYXJhbSk7IC8vIDIwMDctMDQtMDVUMTI6MzAuMDAwKzAyOjAwLCAyMDA3LTA0LTA1VDEyOjMwLjAwMC0wMjowMFxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgZGF0ZSB0byBJU08gZm9ybWF0IGluIFVUQyB0aW1lIGFuZCBzdHJpcHMgdGhlIHRpbWV6b25lIGlmIGBpc0xvY2FsVGltZWAgaXMgdHJ1ZVxuICAgKiBAcGFyYW0gZGF0ZSB7RGF0ZX1cbiAgICogQHBhcmFtIGlzTG9jYWxUaW1lIHtib29sZWFufVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgc3RhdGljIGZvcm1hdFB1c2hUaW1lKHsgZGF0ZSwgaXNMb2NhbFRpbWUgfTogeyBkYXRlOiBEYXRlLCBpc0xvY2FsVGltZTogYm9vbGVhbiB9KSB7XG4gICAgaWYgKGlzTG9jYWxUaW1lKSB7IC8vIFN0cmlwICdaJ1xuICAgICAgY29uc3QgaXNvU3RyaW5nID0gZGF0ZS50b0lTT1N0cmluZygpO1xuICAgICAgcmV0dXJuIGlzb1N0cmluZy5zdWJzdHJpbmcoMCwgaXNvU3RyaW5nLmluZGV4T2YoJ1onKSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRlLnRvSVNPU3RyaW5nKCk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVzaENvbnRyb2xsZXI7XG4iXX0= \ No newline at end of file diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index b374ec721f..e0ede9d906 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -73,13 +73,13 @@ export class PushController { 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.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(); + 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 if (body.audience_id) { From c505d7b0162524953233dc3129a45ebf94594670 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Tue, 16 Oct 2018 16:48:44 -0300 Subject: [PATCH 14/73] Build --- lib/Adapters/Storage/Mongo/MongoStorageAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js index dbd8421b3c..a1a20c35c1 100644 --- a/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -127,6 +127,7 @@ class MongoStorageAdapter { this._uri = uri; this._collectionPrefix = collectionPrefix; this._mongoOptions = mongoOptions; + this._mongoOptions.useNewUrlParser = true; // MaxTimeMS is not a global MongoDB client option, it is applied per operation. this._maxTimeMS = mongoOptions.maxTimeMS; @@ -769,4 +770,4 @@ class MongoStorageAdapter { exports.MongoStorageAdapter = MongoStorageAdapter; exports.default = MongoStorageAdapter; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsibW9uZ29kYiIsInJlcXVpcmUiLCJNb25nb0NsaWVudCIsIlJlYWRQcmVmZXJlbmNlIiwiTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSIsInN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMiLCJtb25nb0FkYXB0ZXIiLCJjb25uZWN0IiwidGhlbiIsImRhdGFiYXNlIiwiY29sbGVjdGlvbnMiLCJmaWx0ZXIiLCJjb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwibWF0Y2giLCJjb2xsZWN0aW9uTmFtZSIsImluZGV4T2YiLCJfY29sbGVjdGlvblByZWZpeCIsImNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEiLCJzY2hlbWEiLCJmaWVsZHMiLCJfcnBlcm0iLCJfd3Blcm0iLCJjbGFzc05hbWUiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vbmdvT2JqZWN0IiwiX2lkIiwib2JqZWN0SWQiLCJ1cGRhdGVkQXQiLCJjcmVhdGVkQXQiLCJfbWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJmaWVsZE5hbWUiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJjbGFzc19wZXJtaXNzaW9ucyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJNb25nb1N0b3JhZ2VBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJ1cmkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsImNvbGxlY3Rpb25QcmVmaXgiLCJtb25nb09wdGlvbnMiLCJfdXJpIiwiX21vbmdvT3B0aW9ucyIsIl9tYXhUaW1lTVMiLCJtYXhUaW1lTVMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiY29ubmVjdGlvblByb21pc2UiLCJlbmNvZGVkVXJpIiwiY2xpZW50Iiwib3B0aW9ucyIsInMiLCJkYiIsImRiTmFtZSIsIm9uIiwiY2F0Y2giLCJlcnIiLCJQcm9taXNlIiwicmVqZWN0IiwiaGFuZGxlRXJyb3IiLCJlcnJvciIsImNvZGUiLCJsb2dnZXIiLCJoYW5kbGVTaHV0ZG93biIsImNsb3NlIiwiX2FkYXB0aXZlQ29sbGVjdGlvbiIsIm5hbWUiLCJyYXdDb2xsZWN0aW9uIiwiTW9uZ29Db2xsZWN0aW9uIiwiX3NjaGVtYUNvbGxlY3Rpb24iLCJjbGFzc0V4aXN0cyIsImxpc3RDb2xsZWN0aW9ucyIsInRvQXJyYXkiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2NoZW1hQ29sbGVjdGlvbiIsInVwZGF0ZVNjaGVtYSIsIiRzZXQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJyZXNvbHZlIiwiX2lkXyIsImRlbGV0ZVByb21pc2VzIiwiaW5zZXJ0ZWRJbmRleGVzIiwiZm9yRWFjaCIsImZpZWxkIiwiX19vcCIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1FVRVJZIiwicHJvbWlzZSIsImRyb3BJbmRleCIsInB1c2giLCJrZXkiLCJoYXNPd25Qcm9wZXJ0eSIsImluc2VydFByb21pc2UiLCJjcmVhdGVJbmRleGVzIiwiYWxsIiwic2V0SW5kZXhlc0Zyb21Nb25nbyIsImdldEluZGV4ZXMiLCJyZWR1Y2UiLCJvYmoiLCJpbmRleCIsIl9mdHMiLCJfZnRzeCIsIndlaWdodHMiLCJjcmVhdGVDbGFzcyIsImluc2VydFNjaGVtYSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJ0eXBlIiwiY3JlYXRlSW5kZXhlc0lmTmVlZGVkIiwiZGVsZXRlQ2xhc3MiLCJkcm9wIiwibWVzc2FnZSIsImZpbmRBbmREZWxldGVTY2hlbWEiLCJkZWxldGVBbGxDbGFzc2VzIiwiZmFzdCIsIm1hcCIsInJlbW92ZSIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJtb25nb0Zvcm1hdE5hbWVzIiwiY29sbGVjdGlvblVwZGF0ZSIsInNjaGVtYVVwZGF0ZSIsInVwZGF0ZU1hbnkiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hc0NvbGxlY3Rpb24iLCJfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEiLCJnZXRDbGFzcyIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0IiwiaW5zZXJ0T25lIiwiRFVQTElDQVRFX1ZBTFVFIiwidW5kZXJseWluZ0Vycm9yIiwibWF0Y2hlcyIsIkFycmF5IiwiaXNBcnJheSIsInVzZXJJbmZvIiwiZHVwbGljYXRlZF9maWVsZCIsImRlbGV0ZU9iamVjdHNCeVF1ZXJ5IiwicXVlcnkiLCJtb25nb1doZXJlIiwiZGVsZXRlTWFueSIsInJlc3VsdCIsIm4iLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cGRhdGUiLCJtb25nb1VwZGF0ZSIsImZpbmRPbmVBbmRVcGRhdGUiLCJfbW9uZ29Db2xsZWN0aW9uIiwiZmluZEFuZE1vZGlmeSIsIm5ldyIsInZhbHVlIiwidXBzZXJ0T25lT2JqZWN0IiwidXBzZXJ0T25lIiwiZmluZCIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJyZWFkUHJlZmVyZW5jZSIsIm1vbmdvU29ydCIsIl8iLCJtYXBLZXlzIiwibW9uZ29LZXlzIiwibWVtbyIsIl9wYXJzZVJlYWRQcmVmZXJlbmNlIiwiY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZCIsIm9iamVjdHMiLCJlbnN1cmVVbmlxdWVuZXNzIiwiaW5kZXhDcmVhdGlvblJlcXVlc3QiLCJtb25nb0ZpZWxkTmFtZXMiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJfcmF3RmluZCIsImNvdW50IiwiZGlzdGluY3QiLCJpc1BvaW50ZXJGaWVsZCIsInN1YnN0cmluZyIsImFnZ3JlZ2F0ZSIsInBpcGVsaW5lIiwic3RhZ2UiLCIkZ3JvdXAiLCJfcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3MiLCIkbWF0Y2giLCJfcGFyc2VBZ2dyZWdhdGVBcmdzIiwiJHByb2plY3QiLCJfcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyIsInJlc3VsdHMiLCJzcGxpdCIsImlzRW1wdHkiLCJyZXR1cm5WYWx1ZSIsInRhcmdldENsYXNzIiwiX2NvbnZlcnRUb0RhdGUiLCJEYXRlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJjcmVhdGVJbmRleCIsImJhY2tncm91bmQiLCIkdGV4dCIsImluZGV4TmFtZSIsInRleHRJbmRleCIsImRyb3BBbGxJbmRleGVzIiwiZHJvcEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsImNsYXNzZXMiLCJwcm9taXNlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFLQTs7QUFJQTs7QUFTQTs7OztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7OztBQUxBOztBQUVBOzs7QUFLQTtBQUNBLE1BQU1BLFVBQVVDLFFBQVEsU0FBUixDQUFoQjtBQUNBLE1BQU1DLGNBQWNGLFFBQVFFLFdBQTVCO0FBQ0EsTUFBTUMsaUJBQWlCSCxRQUFRRyxjQUEvQjs7QUFFQSxNQUFNQyw0QkFBNEIsU0FBbEM7O0FBRUEsTUFBTUMsK0JBQStCQyxnQkFBZ0I7QUFDbkQsU0FBT0EsYUFBYUMsT0FBYixHQUNKQyxJQURJLENBQ0MsTUFBTUYsYUFBYUcsUUFBYixDQUFzQkMsV0FBdEIsRUFEUCxFQUVKRixJQUZJLENBRUNFLGVBQWU7QUFDbkIsV0FBT0EsWUFBWUMsTUFBWixDQUFtQkMsY0FBYztBQUN0QyxVQUFJQSxXQUFXQyxTQUFYLENBQXFCQyxLQUFyQixDQUEyQixZQUEzQixDQUFKLEVBQThDO0FBQzVDLGVBQU8sS0FB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TCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRURvQyxZQUFVNUUsU0FBVixFQUE2QnVGLEtBQTdCLEVBQXlDO0FBQ3ZDLFdBQU8sS0FBS3RDLG1CQUFMLENBQXlCakQsU0FBekIsRUFDSmYsSUFESSxDQUNDSSxjQUFjQSxXQUFXb0osZ0JBQVgsQ0FBNEI3RCxTQUE1QixDQUFzQ1csS0FBdEMsQ0FEZixFQUVKaEQsS0FGSSxDQUVFQyxPQUFPLEtBQUtHLFdBQUwsQ0FBaUJILEdBQWpCLENBRlQsQ0FBUDtBQUdEOztBQUVEd0osaUJBQWVoTSxTQUFmLEVBQWtDO0FBQ2hDLFdBQU8sS0FBS2lELG1CQUFMLENBQXlCakQsU0FBekIsRUFDSmYsSUFESSxDQUNDSSxjQUFjQSxXQUFXb0osZ0JBQVgsQ0FBNEJ3RCxXQUE1QixFQURmLEVBRUoxSixLQUZJLENBRUVDLE9BQU8sS0FBS0csV0FBTCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRUQwSiw0QkFBd0M7QUFDdEMsV0FBTyxLQUFLcEYsYUFBTCxHQUNKN0gsSUFESSxDQUNFa04sT0FBRCxJQUFhO0FBQ2pCLFlBQU1DLFdBQVdELFFBQVE3RixHQUFSLENBQWExRyxNQUFELElBQVk7QUFDdkMsZUFBTyxLQUFLdUYsbUJBQUwsQ0FBeUJ2RixPQUFPSSxTQUFoQyxDQUFQO0FBQ0QsT0FGZ0IsQ0FBakI7QUFHQSxhQUFPeUMsUUFBUXlDLEdBQVIsQ0FBWWtILFFBQVosQ0FBUDtBQUNELEtBTkksRUFPSjdKLEtBUEksQ0FPRUMsT0FBTyxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQVBULENBQVA7QUFRRDtBQXZ0QndEOztRQUE5Q3JCLG1CLEdBQUFBLG1CO2tCQTB0QkVBLG1CIiwiZmlsZSI6Ik1vbmdvU3RvcmFnZUFkYXB0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuaW1wb3J0IE1vbmdvQ29sbGVjdGlvbiAgICAgICBmcm9tICcuL01vbmdvQ29sbGVjdGlvbic7XG5pbXBvcnQgTW9uZ29TY2hlbWFDb2xsZWN0aW9uIGZyb20gJy4vTW9uZ29TY2hlbWFDb2xsZWN0aW9uJztcbmltcG9ydCB7IFN0b3JhZ2VBZGFwdGVyIH0gICAgZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHR5cGUgeyBTY2hlbWFUeXBlLFxuICBRdWVyeVR5cGUsXG4gIFN0b3JhZ2VDbGFzcyxcbiAgUXVlcnlPcHRpb25zIH0gZnJvbSAnLi4vU3RvcmFnZUFkYXB0ZXInO1xuaW1wb3J0IHtcbiAgcGFyc2UgYXMgcGFyc2VVcmwsXG4gIGZvcm1hdCBhcyBmb3JtYXRVcmwsXG59IGZyb20gJy4uLy4uLy4uL3ZlbmRvci9tb25nb2RiVXJsJztcbmltcG9ydCB7XG4gIHBhcnNlT2JqZWN0VG9Nb25nb09iamVjdEZvckNyZWF0ZSxcbiAgbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0LFxuICB0cmFuc2Zvcm1LZXksXG4gIHRyYW5zZm9ybVdoZXJlLFxuICB0cmFuc2Zvcm1VcGRhdGUsXG4gIHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcsXG59IGZyb20gJy4vTW9uZ29UcmFuc2Zvcm0nO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgUGFyc2UgICAgICAgICAgICAgICAgIGZyb20gJ3BhcnNlL25vZGUnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgXyAgICAgICAgICAgICAgICAgICAgIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgZGVmYXVsdHMgICAgICAgICAgICAgIGZyb20gJy4uLy4uLy4uL2RlZmF1bHRzJztcbmltcG9ydCBsb2dnZXIgICAgICAgICAgICAgICAgZnJvbSAnLi4vLi4vLi4vbG9nZ2VyJztcblxuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5jb25zdCBtb25nb2RiID0gcmVxdWlyZSgnbW9uZ29kYicpO1xuY29uc3QgTW9uZ29DbGllbnQgPSBtb25nb2RiLk1vbmdvQ2xpZW50O1xuY29uc3QgUmVhZFByZWZlcmVuY2UgPSBtb25nb2RiLlJlYWRQcmVmZXJlbmNlO1xuXG5jb25zdCBNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lID0gJ19TQ0hFTUEnO1xuXG5jb25zdCBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zID0gbW9uZ29BZGFwdGVyID0+IHtcbiAgcmV0dXJuIG1vbmdvQWRhcHRlci5jb25uZWN0KClcbiAgICAudGhlbigoKSA9PiBtb25nb0FkYXB0ZXIuZGF0YWJhc2UuY29sbGVjdGlvbnMoKSlcbiAgICAudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbnMuZmlsdGVyKGNvbGxlY3Rpb24gPT4ge1xuICAgICAgICBpZiAoY29sbGVjdGlvbi5uYW1lc3BhY2UubWF0Y2goL1xcLnN5c3RlbVxcLi8pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE86IElmIHlvdSBoYXZlIG9uZSBhcHAgd2l0aCBhIGNvbGxlY3Rpb24gcHJlZml4IHRoYXQgaGFwcGVucyB0byBiZSBhIHByZWZpeCBvZiBhbm90aGVyXG4gICAgICAgIC8vIGFwcHMgcHJlZml4LCB0aGlzIHdpbGwgZ28gdmVyeSB2ZXJ5IGJhZGx5LiBXZSBzaG91bGQgZml4IHRoYXQgc29tZWhvdy5cbiAgICAgICAgcmV0dXJuIChjb2xsZWN0aW9uLmNvbGxlY3Rpb25OYW1lLmluZGV4T2YobW9uZ29BZGFwdGVyLl9jb2xsZWN0aW9uUHJlZml4KSA9PSAwKTtcbiAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5jb25zdCBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hID0gKHsuLi5zY2hlbWF9KSA9PiB7XG4gIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9ycGVybTtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3dwZXJtO1xuXG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgLy8gTGVnYWN5IG1vbmdvIGFkYXB0ZXIga25vd3MgYWJvdXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBwYXNzd29yZCBhbmQgX2hhc2hlZF9wYXNzd29yZC5cbiAgICAvLyBGdXR1cmUgZGF0YWJhc2UgYWRhcHRlcnMgd2lsbCBvbmx5IGtub3cgYWJvdXQgX2hhc2hlZF9wYXNzd29yZC5cbiAgICAvLyBOb3RlOiBQYXJzZSBTZXJ2ZXIgd2lsbCBicmluZyBiYWNrIHBhc3N3b3JkIHdpdGggaW5qZWN0RGVmYXVsdFNjaGVtYSwgc28gd2UgZG9uJ3QgbmVlZFxuICAgIC8vIHRvIGFkZCBfaGFzaGVkX3Bhc3N3b3JkIGJhY2sgZXZlci5cbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkO1xuICB9XG5cbiAgcmV0dXJuIHNjaGVtYTtcbn1cblxuLy8gUmV0dXJucyB7IGNvZGUsIGVycm9yIH0gaWYgaW52YWxpZCwgb3IgeyByZXN1bHQgfSwgYW4gb2JqZWN0XG4vLyBzdWl0YWJsZSBmb3IgaW5zZXJ0aW5nIGludG8gX1NDSEVNQSBjb2xsZWN0aW9uLCBvdGhlcndpc2UuXG5jb25zdCBtb25nb1NjaGVtYUZyb21GaWVsZHNBbmRDbGFzc05hbWVBbmRDTFAgPSAoZmllbGRzLCBjbGFzc05hbWUsIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucywgaW5kZXhlcykgPT4ge1xuICBjb25zdCBtb25nb09iamVjdCA9IHtcbiAgICBfaWQ6IGNsYXNzTmFtZSxcbiAgICBvYmplY3RJZDogJ3N0cmluZycsXG4gICAgdXBkYXRlZEF0OiAnc3RyaW5nJyxcbiAgICBjcmVhdGVkQXQ6ICdzdHJpbmcnLFxuICAgIF9tZXRhZGF0YTogdW5kZWZpbmVkLFxuICB9O1xuXG4gIGZvciAoY29uc3QgZmllbGROYW1lIGluIGZpZWxkcykge1xuICAgIG1vbmdvT2JqZWN0W2ZpZWxkTmFtZV0gPSBNb25nb1NjaGVtYUNvbGxlY3Rpb24ucGFyc2VGaWVsZFR5cGVUb01vbmdvRmllbGRUeXBlKGZpZWxkc1tmaWVsZE5hbWVdKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgY2xhc3NMZXZlbFBlcm1pc3Npb25zICE9PSAndW5kZWZpbmVkJykge1xuICAgIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSA9IG1vbmdvT2JqZWN0Ll9tZXRhZGF0YSB8fCB7fTtcbiAgICBpZiAoIWNsYXNzTGV2ZWxQZXJtaXNzaW9ucykge1xuICAgICAgZGVsZXRlIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YS5jbGFzc19wZXJtaXNzaW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zID0gY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgIH1cbiAgfVxuXG4gIGlmIChpbmRleGVzICYmIHR5cGVvZiBpbmRleGVzID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyhpbmRleGVzKS5sZW5ndGggPiAwKSB7XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhID0gbW9uZ29PYmplY3QuX21ldGFkYXRhIHx8IHt9O1xuICAgIG1vbmdvT2JqZWN0Ll9tZXRhZGF0YS5pbmRleGVzID0gaW5kZXhlcztcbiAgfVxuXG4gIGlmICghbW9uZ29PYmplY3QuX21ldGFkYXRhKSB7IC8vIGNsZWFudXAgdGhlIHVudXNlZCBfbWV0YWRhdGFcbiAgICBkZWxldGUgbW9uZ29PYmplY3QuX21ldGFkYXRhO1xuICB9XG5cbiAgcmV0dXJuIG1vbmdvT2JqZWN0O1xufVxuXG5cbmV4cG9ydCBjbGFzcyBNb25nb1N0b3JhZ2VBZGFwdGVyIGltcGxlbWVudHMgU3RvcmFnZUFkYXB0ZXIge1xuICAvLyBQcml2YXRlXG4gIF91cmk6IHN0cmluZztcbiAgX2NvbGxlY3Rpb25QcmVmaXg6IHN0cmluZztcbiAgX21vbmdvT3B0aW9uczogT2JqZWN0O1xuICAvLyBQdWJsaWNcbiAgY29ubmVjdGlvblByb21pc2U6IFByb21pc2U8YW55PjtcbiAgZGF0YWJhc2U6IGFueTtcbiAgY2xpZW50OiBNb25nb0NsaWVudDtcbiAgX21heFRpbWVNUzogP251bWJlcjtcbiAgY2FuU29ydE9uSm9pblRhYmxlczogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcih7XG4gICAgdXJpID0gZGVmYXVsdHMuRGVmYXVsdE1vbmdvVVJJLFxuICAgIGNvbGxlY3Rpb25QcmVmaXggPSAnJyxcbiAgICBtb25nb09wdGlvbnMgPSB7fSxcbiAgfTogYW55KSB7XG4gICAgdGhpcy5fdXJpID0gdXJpO1xuICAgIHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggPSBjb2xsZWN0aW9uUHJlZml4O1xuICAgIHRoaXMuX21vbmdvT3B0aW9ucyA9IG1vbmdvT3B0aW9ucztcblxuICAgIC8vIE1heFRpbWVNUyBpcyBub3QgYSBnbG9iYWwgTW9uZ29EQiBjbGllbnQgb3B0aW9uLCBpdCBpcyBhcHBsaWVkIHBlciBvcGVyYXRpb24uXG4gICAgdGhpcy5fbWF4VGltZU1TID0gbW9uZ29PcHRpb25zLm1heFRpbWVNUztcbiAgICB0aGlzLmNhblNvcnRPbkpvaW5UYWJsZXMgPSB0cnVlO1xuICAgIGRlbGV0ZSBtb25nb09wdGlvbnMubWF4VGltZU1TO1xuICB9XG5cbiAgY29ubmVjdCgpIHtcbiAgICBpZiAodGhpcy5jb25uZWN0aW9uUHJvbWlzZSkge1xuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgfVxuXG4gICAgLy8gcGFyc2luZyBhbmQgcmUtZm9ybWF0dGluZyBjYXVzZXMgdGhlIGF1dGggdmFsdWUgKGlmIHRoZXJlKSB0byBnZXQgVVJJXG4gICAgLy8gZW5jb2RlZFxuICAgIGNvbnN0IGVuY29kZWRVcmkgPSBmb3JtYXRVcmwocGFyc2VVcmwodGhpcy5fdXJpKSk7XG5cbiAgICB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlID0gTW9uZ29DbGllbnQuY29ubmVjdChlbmNvZGVkVXJpLCB0aGlzLl9tb25nb09wdGlvbnMpLnRoZW4oY2xpZW50ID0+IHtcbiAgICAgIC8vIFN0YXJ0aW5nIG1vbmdvREIgMy4wLCB0aGUgTW9uZ29DbGllbnQuY29ubmVjdCBkb24ndCByZXR1cm4gYSBEQiBhbnltb3JlIGJ1dCBhIGNsaWVudFxuICAgICAgLy8gRm9ydHVuYXRlbHksIHdlIGNhbiBnZXQgYmFjayB0aGUgb3B0aW9ucyBhbmQgdXNlIHRoZW0gdG8gc2VsZWN0IHRoZSBwcm9wZXIgREIuXG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbW9uZ29kYi9ub2RlLW1vbmdvZGItbmF0aXZlL2Jsb2IvMmMzNWQ3NmYwODU3NDIyNWI4ZGIwMmQ3YmVmNjg3MTIzZTZiYjAxOC9saWIvbW9uZ29fY2xpZW50LmpzI0w4ODVcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSBjbGllbnQucy5vcHRpb25zO1xuICAgICAgY29uc3QgZGF0YWJhc2UgPSBjbGllbnQuZGIob3B0aW9ucy5kYk5hbWUpO1xuICAgICAgaWYgKCFkYXRhYmFzZSkge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZGF0YWJhc2Uub24oJ2Vycm9yJywgKCkgPT4ge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIH0pO1xuICAgICAgZGF0YWJhc2Uub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jbGllbnQgPSBjbGllbnQ7XG4gICAgICB0aGlzLmRhdGFiYXNlID0gZGF0YWJhc2U7XG4gICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgZGVsZXRlIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICB9XG5cbiAgaGFuZGxlRXJyb3I8VD4oZXJyb3I6ID8oRXJyb3IgfCBQYXJzZS5FcnJvcikpOiBQcm9taXNlPFQ+IHtcbiAgICBpZiAoZXJyb3IgJiYgZXJyb3IuY29kZSA9PT0gMTMpIHsgLy8gVW5hdXRob3JpemVkIGVycm9yXG4gICAgICBkZWxldGUgdGhpcy5jbGllbnQ7XG4gICAgICBkZWxldGUgdGhpcy5kYXRhYmFzZTtcbiAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgbG9nZ2VyLmVycm9yKCdSZWNlaXZlZCB1bmF1dGhvcml6ZWQgZXJyb3InLCB7IGVycm9yOiBlcnJvciB9KTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBoYW5kbGVTaHV0ZG93bigpIHtcbiAgICBpZiAoIXRoaXMuY2xpZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2xpZW50LmNsb3NlKGZhbHNlKTtcbiAgfVxuXG4gIF9hZGFwdGl2ZUNvbGxlY3Rpb24obmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdCgpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmRhdGFiYXNlLmNvbGxlY3Rpb24odGhpcy5fY29sbGVjdGlvblByZWZpeCArIG5hbWUpKVxuICAgICAgLnRoZW4ocmF3Q29sbGVjdGlvbiA9PiBuZXcgTW9uZ29Db2xsZWN0aW9uKHJhd0NvbGxlY3Rpb24pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgX3NjaGVtYUNvbGxlY3Rpb24oKTogUHJvbWlzZTxNb25nb1NjaGVtYUNvbGxlY3Rpb24+IHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KClcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihNb25nb1NjaGVtYUNvbGxlY3Rpb25OYW1lKSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gbmV3IE1vbmdvU2NoZW1hQ29sbGVjdGlvbihjb2xsZWN0aW9uKSk7XG4gIH1cblxuICBjbGFzc0V4aXN0cyhuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5kYXRhYmFzZS5saXN0Q29sbGVjdGlvbnMoeyBuYW1lOiB0aGlzLl9jb2xsZWN0aW9uUHJlZml4ICsgbmFtZSB9KS50b0FycmF5KCk7XG4gICAgfSkudGhlbihjb2xsZWN0aW9ucyA9PiB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbnMubGVuZ3RoID4gMDtcbiAgICB9KS5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldENsYXNzTGV2ZWxQZXJtaXNzaW9ucyhjbGFzc05hbWU6IHN0cmluZywgQ0xQczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgJHNldDogeyAnX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zJzogQ0xQcyB9XG4gICAgICB9KSkuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWU6IHN0cmluZywgc3VibWl0dGVkSW5kZXhlczogYW55LCBleGlzdGluZ0luZGV4ZXM6IGFueSA9IHt9LCBmaWVsZHM6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChzdWJtaXR0ZWRJbmRleGVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKGV4aXN0aW5nSW5kZXhlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICBleGlzdGluZ0luZGV4ZXMgPSB7IF9pZF86IHsgX2lkOiAxfSB9O1xuICAgIH1cbiAgICBjb25zdCBkZWxldGVQcm9taXNlcyA9IFtdO1xuICAgIGNvbnN0IGluc2VydGVkSW5kZXhlcyA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEluZGV4ZXMpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb25zdCBmaWVsZCA9IHN1Ym1pdHRlZEluZGV4ZXNbbmFtZV07XG4gICAgICBpZiAoZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW5kZXggJHtuYW1lfSBleGlzdHMsIGNhbm5vdCB1cGRhdGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4aXN0aW5nSW5kZXhlc1tuYW1lXSAmJiBmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgYEluZGV4ICR7bmFtZX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBkZWxldGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuZHJvcEluZGV4KGNsYXNzTmFtZSwgbmFtZSk7XG4gICAgICAgIGRlbGV0ZVByb21pc2VzLnB1c2gocHJvbWlzZSk7XG4gICAgICAgIGRlbGV0ZSBleGlzdGluZ0luZGV4ZXNbbmFtZV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBPYmplY3Qua2V5cyhmaWVsZCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgIGlmICghZmllbGRzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgRmllbGQgJHtrZXl9IGRvZXMgbm90IGV4aXN0LCBjYW5ub3QgYWRkIGluZGV4LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGV4aXN0aW5nSW5kZXhlc1tuYW1lXSA9IGZpZWxkO1xuICAgICAgICBpbnNlcnRlZEluZGV4ZXMucHVzaCh7XG4gICAgICAgICAga2V5OiBmaWVsZCxcbiAgICAgICAgICBuYW1lLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBsZXQgaW5zZXJ0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIGlmIChpbnNlcnRlZEluZGV4ZXMubGVuZ3RoID4gMCkge1xuICAgICAgaW5zZXJ0UHJvbWlzZSA9IHRoaXMuY3JlYXRlSW5kZXhlcyhjbGFzc05hbWUsIGluc2VydGVkSW5kZXhlcyk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLmFsbChkZWxldGVQcm9taXNlcylcbiAgICAgIC50aGVuKCgpID0+IGluc2VydFByb21pc2UpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuaW5kZXhlcyc6ICBleGlzdGluZ0luZGV4ZXMgfVxuICAgICAgfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBzZXRJbmRleGVzRnJvbU1vbmdvKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0SW5kZXhlcyhjbGFzc05hbWUpLnRoZW4oKGluZGV4ZXMpID0+IHtcbiAgICAgIGluZGV4ZXMgPSBpbmRleGVzLnJlZHVjZSgob2JqLCBpbmRleCkgPT4ge1xuICAgICAgICBpZiAoaW5kZXgua2V5Ll9mdHMpIHtcbiAgICAgICAgICBkZWxldGUgaW5kZXgua2V5Ll9mdHM7XG4gICAgICAgICAgZGVsZXRlIGluZGV4LmtleS5fZnRzeDtcbiAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIGluZGV4LndlaWdodHMpIHtcbiAgICAgICAgICAgIGluZGV4LmtleVtmaWVsZF0gPSAndGV4dCc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG9ialtpbmRleC5uYW1lXSA9IGluZGV4LmtleTtcbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgIH0sIHt9KTtcbiAgICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHtcbiAgICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuaW5kZXhlcyc6IGluZGV4ZXMgfVxuICAgICAgICB9KSk7XG4gICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKVxuICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgLy8gSWdub3JlIGlmIGNvbGxlY3Rpb24gbm90IGZvdW5kXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb09iamVjdCA9IG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZUFuZENMUChzY2hlbWEuZmllbGRzLCBjbGFzc05hbWUsIHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMsIHNjaGVtYS5pbmRleGVzKTtcbiAgICBtb25nb09iamVjdC5faWQgPSBjbGFzc05hbWU7XG4gICAgcmV0dXJuIHRoaXMuc2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQoY2xhc3NOYW1lLCBzY2hlbWEuaW5kZXhlcywge30sIHNjaGVtYS5maWVsZHMpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uaW5zZXJ0U2NoZW1hKG1vbmdvT2JqZWN0KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGFkZEZpZWxkSWZOb3RFeGlzdHMoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uYWRkRmllbGRJZk5vdEV4aXN0cyhjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSkpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLmNyZWF0ZUluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIGZpZWxkTmFtZSwgdHlwZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBEcm9wcyBhIGNvbGxlY3Rpb24uIFJlc29sdmVzIHdpdGggdHJ1ZSBpZiBpdCB3YXMgYSBQYXJzZSBTY2hlbWEgKGVnLiBfVXNlciwgQ3VzdG9tLCBldGMuKVxuICAvLyBhbmQgcmVzb2x2ZXMgd2l0aCBmYWxzZSBpZiBpdCB3YXNuJ3QgKGVnLiBhIGpvaW4gdGFibGUpLiBSZWplY3RzIGlmIGRlbGV0aW9uIHdhcyBpbXBvc3NpYmxlLlxuICBkZWxldGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmRyb3AoKSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAvLyAnbnMgbm90IGZvdW5kJyBtZWFucyBjb2xsZWN0aW9uIHdhcyBhbHJlYWR5IGdvbmUuIElnbm9yZSBkZWxldGlvbiBhdHRlbXB0LlxuICAgICAgICBpZiAoZXJyb3IubWVzc2FnZSA9PSAnbnMgbm90IGZvdW5kJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgLy8gV2UndmUgZHJvcHBlZCB0aGUgY29sbGVjdGlvbiwgbm93IHJlbW92ZSB0aGUgX1NDSEVNQSBkb2N1bWVudFxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLmZpbmRBbmREZWxldGVTY2hlbWEoY2xhc3NOYW1lKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRlbGV0ZUFsbENsYXNzZXMoZmFzdDogYm9vbGVhbikge1xuICAgIHJldHVybiBzdG9yYWdlQWRhcHRlckFsbENvbGxlY3Rpb25zKHRoaXMpXG4gICAgICAudGhlbihjb2xsZWN0aW9ucyA9PiBQcm9taXNlLmFsbChjb2xsZWN0aW9ucy5tYXAoY29sbGVjdGlvbiA9PiBmYXN0ID8gY29sbGVjdGlvbi5yZW1vdmUoe30pIDogY29sbGVjdGlvbi5kcm9wKCkpKSk7XG4gIH1cblxuICAvLyBSZW1vdmUgdGhlIGNvbHVtbiBhbmQgYWxsIHRoZSBkYXRhLiBGb3IgUmVsYXRpb25zLCB0aGUgX0pvaW4gY29sbGVjdGlvbiBpcyBoYW5kbGVkXG4gIC8vIHNwZWNpYWxseSwgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBkZWxldGUgX0pvaW4gY29sdW1ucy4gSXQgc2hvdWxkLCBob3dldmVyLCBpbmRpY2F0ZVxuICAvLyB0aGF0IHRoZSByZWxhdGlvbiBmaWVsZHMgZG9lcyBub3QgZXhpc3QgYW55bW9yZS4gSW4gbW9uZ28sIHRoaXMgbWVhbnMgcmVtb3ZpbmcgaXQgZnJvbVxuICAvLyB0aGUgX1NDSEVNQSBjb2xsZWN0aW9uLiAgVGhlcmUgc2hvdWxkIGJlIG5vIGFjdHVhbCBkYXRhIGluIHRoZSBjb2xsZWN0aW9uIHVuZGVyIHRoZSBzYW1lIG5hbWVcbiAgLy8gYXMgdGhlIHJlbGF0aW9uIGNvbHVtbiwgc28gaXQncyBmaW5lIHRvIGF0dGVtcHQgdG8gZGVsZXRlIGl0LiBJZiB0aGUgZmllbGRzIGxpc3RlZCB0byBiZVxuICAvLyBkZWxldGVkIGRvIG5vdCBleGlzdCwgdGhpcyBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIHN1Y2Nlc3NmdWxseSBhbnl3YXlzLiBDaGVja2luZyBmb3JcbiAgLy8gYXR0ZW1wdHMgdG8gZGVsZXRlIG5vbi1leGlzdGVudCBmaWVsZHMgaXMgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIFBhcnNlIFNlcnZlci5cblxuICAvLyBQb2ludGVyIGZpZWxkIG5hbWVzIGFyZSBwYXNzZWQgZm9yIGxlZ2FjeSByZWFzb25zOiB0aGUgb3JpZ2luYWwgbW9uZ29cbiAgLy8gZm9ybWF0IHN0b3JlZCBwb2ludGVyIGZpZWxkIG5hbWVzIGRpZmZlcmVudGx5IGluIHRoZSBkYXRhYmFzZSwgYW5kIHRoZXJlZm9yZVxuICAvLyBuZWVkZWQgdG8ga25vdyB0aGUgdHlwZSBvZiB0aGUgZmllbGQgYmVmb3JlIGl0IGNvdWxkIGRlbGV0ZSBpdC4gRnV0dXJlIGRhdGFiYXNlXG4gIC8vIGFkYXB0ZXJzIHNob3VsZCBpZ25vcmUgdGhlIHBvaW50ZXJGaWVsZE5hbWVzIGFyZ3VtZW50LiBBbGwgdGhlIGZpZWxkIG5hbWVzIGFyZSBpblxuICAvLyBmaWVsZE5hbWVzLCB0aGV5IHNob3cgdXAgYWRkaXRpb25hbGx5IGluIHRoZSBwb2ludGVyRmllbGROYW1lcyBkYXRhYmFzZSBmb3IgdXNlXG4gIC8vIGJ5IHRoZSBtb25nbyBhZGFwdGVyLCB3aGljaCBkZWFscyB3aXRoIHRoZSBsZWdhY3kgbW9uZ28gZm9ybWF0LlxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gaXMgbm90IG9ibGlnYXRlZCB0byBkZWxldGUgZmllbGRzIGF0b21pY2FsbHkuIEl0IGlzIGdpdmVuIHRoZSBmaWVsZFxuICAvLyBuYW1lcyBpbiBhIGxpc3Qgc28gdGhhdCBkYXRhYmFzZXMgdGhhdCBhcmUgY2FwYWJsZSBvZiBkZWxldGluZyBmaWVsZHMgYXRvbWljYWxseVxuICAvLyBtYXkgZG8gc28uXG5cbiAgLy8gUmV0dXJucyBhIFByb21pc2UuXG4gIGRlbGV0ZUZpZWxkcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBmaWVsZE5hbWVzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IG1vbmdvRm9ybWF0TmFtZXMgPSBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuIGBfcF8ke2ZpZWxkTmFtZX1gXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZmllbGROYW1lO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGNvbnN0IGNvbGxlY3Rpb25VcGRhdGUgPSB7ICckdW5zZXQnIDoge30gfTtcbiAgICBtb25nb0Zvcm1hdE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb2xsZWN0aW9uVXBkYXRlWyckdW5zZXQnXVtuYW1lXSA9IG51bGw7XG4gICAgfSk7XG5cbiAgICBjb25zdCBzY2hlbWFVcGRhdGUgPSB7ICckdW5zZXQnIDoge30gfTtcbiAgICBmaWVsZE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBzY2hlbWFVcGRhdGVbJyR1bnNldCddW25hbWVdID0gbnVsbDtcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLnVwZGF0ZU1hbnkoe30sIGNvbGxlY3Rpb25VcGRhdGUpKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpKVxuICAgICAgLnRoZW4oc2NoZW1hQ29sbGVjdGlvbiA9PiBzY2hlbWFDb2xsZWN0aW9uLnVwZGF0ZVNjaGVtYShjbGFzc05hbWUsIHNjaGVtYVVwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBSZXR1cm4gYSBwcm9taXNlIGZvciBhbGwgc2NoZW1hcyBrbm93biB0byB0aGlzIGFkYXB0ZXIsIGluIFBhcnNlIGZvcm1hdC4gSW4gY2FzZSB0aGVcbiAgLy8gc2NoZW1hcyBjYW5ub3QgYmUgcmV0cmlldmVkLCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMuIFJlcXVpcmVtZW50cyBmb3IgdGhlXG4gIC8vIHJlamVjdGlvbiByZWFzb24gYXJlIFRCRC5cbiAgZ2V0QWxsQ2xhc3NlcygpOiBQcm9taXNlPFN0b3JhZ2VDbGFzc1tdPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKS50aGVuKHNjaGVtYXNDb2xsZWN0aW9uID0+IHNjaGVtYXNDb2xsZWN0aW9uLl9mZXRjaEFsbFNjaGVtYXNGcm9tX1NDSEVNQSgpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgdGhlIHNjaGVtYSB3aXRoIHRoZSBnaXZlbiBuYW1lLCBpbiBQYXJzZSBmb3JtYXQuIElmXG4gIC8vIHRoaXMgYWRhcHRlciBkb2Vzbid0IGtub3cgYWJvdXQgdGhlIHNjaGVtYSwgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMgd2l0aFxuICAvLyB1bmRlZmluZWQgYXMgdGhlIHJlYXNvbi5cbiAgZ2V0Q2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFN0b3JhZ2VDbGFzcz4ge1xuICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgIC50aGVuKHNjaGVtYXNDb2xsZWN0aW9uID0+IHNjaGVtYXNDb2xsZWN0aW9uLl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BKGNsYXNzTmFtZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBUT0RPOiBBcyB5ZXQgbm90IHBhcnRpY3VsYXJseSB3ZWxsIHNwZWNpZmllZC4gQ3JlYXRlcyBhbiBvYmplY3QuIE1heWJlIHNob3VsZG4ndCBldmVuIG5lZWQgdGhlIHNjaGVtYSxcbiAgLy8gYW5kIHNob3VsZCBpbmZlciBmcm9tIHRoZSB0eXBlLiBPciBtYXliZSBkb2VzIG5lZWQgdGhlIHNjaGVtYSBmb3IgdmFsaWRhdGlvbnMuIE9yIG1heWJlIG5lZWRzXG4gIC8vIHRoZSBzY2hlbWEgb25seSBmb3IgdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQuIFdlJ2xsIGZpZ3VyZSB0aGF0IG91dCBsYXRlci5cbiAgY3JlYXRlT2JqZWN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIG9iamVjdDogYW55KSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvT2JqZWN0ID0gcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlKGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmluc2VydE9uZShtb25nb09iamVjdCkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTEwMDApIHsgLy8gRHVwbGljYXRlIHZhbHVlXG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnKTtcbiAgICAgICAgICBlcnIudW5kZXJseWluZ0Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgaWYgKGVycm9yLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBlcnJvci5tZXNzYWdlLm1hdGNoKC9pbmRleDpbXFxzYS16QS1aMC05X1xcLVxcLl0rXFwkPyhbYS16QS1aXy1dKylfMS8pO1xuICAgICAgICAgICAgaWYgKG1hdGNoZXMgJiYgQXJyYXkuaXNBcnJheShtYXRjaGVzKSkge1xuICAgICAgICAgICAgICBlcnIudXNlckluZm8gPSB7IGR1cGxpY2F0ZWRfZmllbGQ6IG1hdGNoZXNbMV0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgLy8gSWYgbm8gb2JqZWN0cyBtYXRjaCwgcmVqZWN0IHdpdGggT0JKRUNUX05PVF9GT1VORC4gSWYgb2JqZWN0cyBhcmUgZm91bmQgYW5kIGRlbGV0ZWQsIHJlc29sdmUgd2l0aCB1bmRlZmluZWQuXG4gIC8vIElmIHRoZXJlIGlzIHNvbWUgb3RoZXIgZXJyb3IsIHJlamVjdCB3aXRoIElOVEVSTkFMX1NFUlZFUl9FUlJPUi5cbiAgZGVsZXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4ge1xuICAgICAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZGVsZXRlTWFueShtb25nb1doZXJlKVxuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKVxuICAgICAgLnRoZW4oKHsgcmVzdWx0IH0pID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdC5uID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdPYmplY3Qgbm90IGZvdW5kLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH0sICgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0RhdGFiYXNlIGFkYXB0ZXIgZXJyb3InKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgdXBkYXRlT2JqZWN0c0J5UXVlcnkoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29VcGRhdGUgPSB0cmFuc2Zvcm1VcGRhdGUoY2xhc3NOYW1lLCB1cGRhdGUsIHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29XaGVyZSA9IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24udXBkYXRlTWFueShtb25nb1doZXJlLCBtb25nb1VwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBBdG9taWNhbGx5IGZpbmRzIGFuZCB1cGRhdGVzIGFuIG9iamVjdCBiYXNlZCBvbiBxdWVyeS5cbiAgLy8gUmV0dXJuIHZhbHVlIG5vdCBjdXJyZW50bHkgd2VsbCBzcGVjaWZpZWQuXG4gIGZpbmRPbmVBbmRVcGRhdGUoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgcXVlcnk6IFF1ZXJ5VHlwZSwgdXBkYXRlOiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29VcGRhdGUgPSB0cmFuc2Zvcm1VcGRhdGUoY2xhc3NOYW1lLCB1cGRhdGUsIHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29XaGVyZSA9IHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5maW5kQW5kTW9kaWZ5KG1vbmdvV2hlcmUsIFtdLCBtb25nb1VwZGF0ZSwgeyBuZXc6IHRydWUgfSkpXG4gICAgICAudGhlbihyZXN1bHQgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgcmVzdWx0LnZhbHVlLCBzY2hlbWEpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDExMDAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBIb3BlZnVsbHkgd2UgY2FuIGdldCByaWQgb2YgdGhpcy4gSXQncyBvbmx5IHVzZWQgZm9yIGNvbmZpZyBhbmQgaG9va3MuXG4gIHVwc2VydE9uZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB1cGRhdGU6IGFueSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi51cHNlcnRPbmUobW9uZ29XaGVyZSwgbW9uZ29VcGRhdGUpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gRXhlY3V0ZXMgYSBmaW5kLiBBY2NlcHRzOiBjbGFzc05hbWUsIHF1ZXJ5IGluIFBhcnNlIGZvcm1hdCwgYW5kIHsgc2tpcCwgbGltaXQsIHNvcnQgfS5cbiAgZmluZChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB7IHNraXAsIGxpbWl0LCBzb3J0LCBrZXlzLCByZWFkUHJlZmVyZW5jZSB9OiBRdWVyeU9wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1NvcnQgPSBfLm1hcEtleXMoc29ydCwgKHZhbHVlLCBmaWVsZE5hbWUpID0+IHRyYW5zZm9ybUtleShjbGFzc05hbWUsIGZpZWxkTmFtZSwgc2NoZW1hKSk7XG4gICAgY29uc3QgbW9uZ29LZXlzID0gXy5yZWR1Y2Uoa2V5cywgKG1lbW8sIGtleSkgPT4ge1xuICAgICAgbWVtb1t0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBrZXksIHNjaGVtYSldID0gMTtcbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH0sIHt9KTtcblxuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZChjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5maW5kKG1vbmdvV2hlcmUsIHtcbiAgICAgICAgc2tpcCxcbiAgICAgICAgbGltaXQsXG4gICAgICAgIHNvcnQ6IG1vbmdvU29ydCxcbiAgICAgICAga2V5czogbW9uZ29LZXlzLFxuICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICB9KSlcbiAgICAgIC50aGVuKG9iamVjdHMgPT4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSB1bmlxdWUgaW5kZXguIFVuaXF1ZSBpbmRleGVzIG9uIG51bGxhYmxlIGZpZWxkcyBhcmUgbm90IGFsbG93ZWQuIFNpbmNlIHdlIGRvbid0XG4gIC8vIGN1cnJlbnRseSBrbm93IHdoaWNoIGZpZWxkcyBhcmUgbnVsbGFibGUgYW5kIHdoaWNoIGFyZW4ndCwgd2UgaWdub3JlIHRoYXQgY3JpdGVyaWEuXG4gIC8vIEFzIHN1Y2gsIHdlIHNob3VsZG4ndCBleHBvc2UgdGhpcyBmdW5jdGlvbiB0byB1c2VycyBvZiBwYXJzZSB1bnRpbCB3ZSBoYXZlIGFuIG91dC1vZi1iYW5kXG4gIC8vIFdheSBvZiBkZXRlcm1pbmluZyBpZiBhIGZpZWxkIGlzIG51bGxhYmxlLiBVbmRlZmluZWQgZG9lc24ndCBjb3VudCBhZ2FpbnN0IHVuaXF1ZW5lc3MsXG4gIC8vIHdoaWNoIGlzIHdoeSB3ZSB1c2Ugc3BhcnNlIGluZGV4ZXMuXG4gIGVuc3VyZVVuaXF1ZW5lc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgZmllbGROYW1lczogc3RyaW5nW10pIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgaW5kZXhDcmVhdGlvblJlcXVlc3QgPSB7fTtcbiAgICBjb25zdCBtb25nb0ZpZWxkTmFtZXMgPSBmaWVsZE5hbWVzLm1hcChmaWVsZE5hbWUgPT4gdHJhbnNmb3JtS2V5KGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpKTtcbiAgICBtb25nb0ZpZWxkTmFtZXMuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaW5kZXhDcmVhdGlvblJlcXVlc3RbZmllbGROYW1lXSA9IDE7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX2Vuc3VyZVNwYXJzZVVuaXF1ZUluZGV4SW5CYWNrZ3JvdW5kKGluZGV4Q3JlYXRpb25SZXF1ZXN0KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsICdUcmllZCB0byBlbnN1cmUgZmllbGQgdW5pcXVlbmVzcyBmb3IgYSBjbGFzcyB0aGF0IGFscmVhZHkgaGFzIGR1cGxpY2F0ZXMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVXNlZCBpbiB0ZXN0c1xuICBfcmF3RmluZChjbGFzc05hbWU6IHN0cmluZywgcXVlcnk6IFF1ZXJ5VHlwZSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKS50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5maW5kKHF1ZXJ5LCB7XG4gICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICB9KSkuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGNvdW50LlxuICBjb3VudChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCByZWFkUHJlZmVyZW5jZTogP3N0cmluZykge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICByZWFkUHJlZmVyZW5jZSA9IHRoaXMuX3BhcnNlUmVhZFByZWZlcmVuY2UocmVhZFByZWZlcmVuY2UpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmNvdW50KHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSksIHtcbiAgICAgICAgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMsXG4gICAgICAgIHJlYWRQcmVmZXJlbmNlLFxuICAgICAgfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkaXN0aW5jdChjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCBmaWVsZE5hbWU6IHN0cmluZykge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBpc1BvaW50ZXJGaWVsZCA9IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1BvaW50ZXInO1xuICAgIGlmIChpc1BvaW50ZXJGaWVsZCkge1xuICAgICAgZmllbGROYW1lID0gYF9wXyR7ZmllbGROYW1lfWBcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uZGlzdGluY3QoZmllbGROYW1lLCB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpKSlcbiAgICAgIC50aGVuKG9iamVjdHMgPT4ge1xuICAgICAgICBvYmplY3RzID0gb2JqZWN0cy5maWx0ZXIoKG9iaikgPT4gb2JqICE9IG51bGwpO1xuICAgICAgICByZXR1cm4gb2JqZWN0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZmllbGROYW1lLnN1YnN0cmluZygzKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nKHNjaGVtYSwgZmllbGQsIG9iamVjdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGFnZ3JlZ2F0ZShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnksIHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKSB7XG4gICAgbGV0IGlzUG9pbnRlckZpZWxkID0gZmFsc2U7XG4gICAgcGlwZWxpbmUgPSBwaXBlbGluZS5tYXAoKHN0YWdlKSA9PiB7XG4gICAgICBpZiAoc3RhZ2UuJGdyb3VwKSB7XG4gICAgICAgIHN0YWdlLiRncm91cCA9IHRoaXMuX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzKHNjaGVtYSwgc3RhZ2UuJGdyb3VwKTtcbiAgICAgICAgaWYgKHN0YWdlLiRncm91cC5faWQgJiYgKHR5cGVvZiBzdGFnZS4kZ3JvdXAuX2lkID09PSAnc3RyaW5nJykgJiYgc3RhZ2UuJGdyb3VwLl9pZC5pbmRleE9mKCckX3BfJykgPj0gMCkge1xuICAgICAgICAgIGlzUG9pbnRlckZpZWxkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRtYXRjaCkge1xuICAgICAgICBzdGFnZS4kbWF0Y2ggPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hLCBzdGFnZS4kbWF0Y2gpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRwcm9qZWN0KSB7XG4gICAgICAgIHN0YWdlLiRwcm9qZWN0ID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyhzY2hlbWEsIHN0YWdlLiRwcm9qZWN0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdGFnZTtcbiAgICB9KTtcbiAgICByZWFkUHJlZmVyZW5jZSA9IHRoaXMuX3BhcnNlUmVhZFByZWZlcmVuY2UocmVhZFByZWZlcmVuY2UpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmFnZ3JlZ2F0ZShwaXBlbGluZSwgeyByZWFkUHJlZmVyZW5jZSwgbWF4VGltZU1TOiB0aGlzLl9tYXhUaW1lTVMgfSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTYwMDYpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHJlc3VsdHMuZm9yRWFjaChyZXN1bHQgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQuaGFzT3duUHJvcGVydHkoJ19pZCcpKSB7XG4gICAgICAgICAgICBpZiAoaXNQb2ludGVyRmllbGQgJiYgcmVzdWx0Ll9pZCkge1xuICAgICAgICAgICAgICByZXN1bHQuX2lkID0gcmVzdWx0Ll9pZC5zcGxpdCgnJCcpWzFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdC5faWQgPT0gbnVsbCB8fCBfLmlzRW1wdHkocmVzdWx0Ll9pZCkpIHtcbiAgICAgICAgICAgICAgcmVzdWx0Ll9pZCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQub2JqZWN0SWQgPSByZXN1bHQuX2lkO1xuICAgICAgICAgICAgZGVsZXRlIHJlc3VsdC5faWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiBvYmplY3RzLm1hcChvYmplY3QgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCByZWN1cnNpdmVseSB0cmF2ZXJzZSB0aGUgcGlwZWxpbmUgYW5kIGNvbnZlcnQgYW55IFBvaW50ZXIgb3IgRGF0ZSBjb2x1bW5zLlxuICAvLyBJZiB3ZSBkZXRlY3QgYSBwb2ludGVyIGNvbHVtbiB3ZSB3aWxsIHJlbmFtZSB0aGUgY29sdW1uIGJlaW5nIHF1ZXJpZWQgZm9yIHRvIG1hdGNoIHRoZSBjb2x1bW5cbiAgLy8gaW4gdGhlIGRhdGFiYXNlLiBXZSBhbHNvIG1vZGlmeSB0aGUgdmFsdWUgdG8gd2hhdCB3ZSBleHBlY3QgdGhlIHZhbHVlIHRvIGJlIGluIHRoZSBkYXRhYmFzZVxuICAvLyBhcyB3ZWxsLlxuICAvLyBGb3IgZGF0ZXMsIHRoZSBkcml2ZXIgZXhwZWN0cyBhIERhdGUgb2JqZWN0LCBidXQgd2UgaGF2ZSBhIHN0cmluZyBjb21pbmcgaW4uIFNvIHdlJ2xsIGNvbnZlcnRcbiAgLy8gdGhlIHN0cmluZyB0byBhIERhdGUgc28gdGhlIGRyaXZlciBjYW4gcGVyZm9ybSB0aGUgbmVjZXNzYXJ5IGNvbXBhcmlzb24uXG4gIC8vXG4gIC8vIFRoZSBnb2FsIG9mIHRoaXMgbWV0aG9kIGlzIHRvIGxvb2sgZm9yIHRoZSBcImxlYXZlc1wiIG9mIHRoZSBwaXBlbGluZSBhbmQgZGV0ZXJtaW5lIGlmIGl0IG5lZWRzXG4gIC8vIHRvIGJlIGNvbnZlcnRlZC4gVGhlIHBpcGVsaW5lIGNhbiBoYXZlIGEgZmV3IGRpZmZlcmVudCBmb3Jtcy4gRm9yIG1vcmUgZGV0YWlscywgc2VlOlxuICAvLyAgICAgaHR0cHM6Ly9kb2NzLm1vbmdvZGIuY29tL21hbnVhbC9yZWZlcmVuY2Uvb3BlcmF0b3IvYWdncmVnYXRpb24vXG4gIC8vXG4gIC8vIElmIHRoZSBwaXBlbGluZSBpcyBhbiBhcnJheSwgaXQgbWVhbnMgd2UgYXJlIHByb2JhYmx5IHBhcnNpbmcgYW4gJyRhbmQnIG9yICckb3InIG9wZXJhdG9yLiBJblxuICAvLyB0aGF0IGNhc2Ugd2UgbmVlZCB0byBsb29wIHRocm91Z2ggYWxsIG9mIGl0J3MgY2hpbGRyZW4gdG8gZmluZCB0aGUgY29sdW1ucyBiZWluZyBvcGVyYXRlZCBvbi5cbiAgLy8gSWYgdGhlIHBpcGVsaW5lIGlzIGFuIG9iamVjdCwgdGhlbiB3ZSdsbCBsb29wIHRocm91Z2ggdGhlIGtleXMgY2hlY2tpbmcgdG8gc2VlIGlmIHRoZSBrZXkgbmFtZVxuICAvLyBtYXRjaGVzIG9uZSBvZiB0aGUgc2NoZW1hIGNvbHVtbnMuIElmIGl0IGRvZXMgbWF0Y2ggYSBjb2x1bW4gYW5kIHRoZSBjb2x1bW4gaXMgYSBQb2ludGVyIG9yXG4gIC8vIGEgRGF0ZSwgdGhlbiB3ZSdsbCBjb252ZXJ0IHRoZSB2YWx1ZSBhcyBkZXNjcmliZWQgYWJvdmUuXG4gIC8vXG4gIC8vIEFzIG11Y2ggYXMgSSBoYXRlIHJlY3Vyc2lvbi4uLnRoaXMgc2VlbWVkIGxpa2UgYSBnb29kIGZpdCBmb3IgaXQuIFdlJ3JlIGVzc2VudGlhbGx5IHRyYXZlcnNpbmdcbiAgLy8gZG93biBhIHRyZWUgdG8gZmluZCBhIFwibGVhZiBub2RlXCIgYW5kIGNoZWNraW5nIHRvIHNlZSBpZiBpdCBuZWVkcyB0byBiZSBjb252ZXJ0ZWQuXG4gIF9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnkpOiBhbnkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHBpcGVsaW5lKSkge1xuICAgICAgcmV0dXJuIHBpcGVsaW5lLm1hcCgodmFsdWUpID0+IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHZhbHVlKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBwaXBlbGluZVtmaWVsZF0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBQYXNzIG9iamVjdHMgZG93biB0byBNb25nb0RCLi4udGhpcyBpcyBtb3JlIHRoYW4gbGlrZWx5IGFuICRleGlzdHMgb3BlcmF0b3IuXG4gICAgICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IHBpcGVsaW5lW2ZpZWxkXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWVbYF9wXyR7ZmllbGR9YF0gPSBgJHtzY2hlbWEuZmllbGRzW2ZpZWxkXS50YXJnZXRDbGFzc30kJHtwaXBlbGluZVtmaWVsZF19YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ0RhdGUnKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fY29udmVydFRvRGF0ZShwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2lkJ10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVsnX2NyZWF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfdXBkYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHBpcGVsaW5lO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgb25lIGFib3ZlLiBSYXRoZXIgdGhhbiB0cnlpbmcgdG8gY29tYmluZSB0aGVzZVxuICAvLyB0d28gZnVuY3Rpb25zIGFuZCBtYWtpbmcgdGhlIGNvZGUgZXZlbiBoYXJkZXIgdG8gdW5kZXJzdGFuZCwgSSBkZWNpZGVkIHRvIHNwbGl0IGl0IHVwLiBUaGVcbiAgLy8gZGlmZmVyZW5jZSB3aXRoIHRoaXMgZnVuY3Rpb24gaXMgd2UgYXJlIG5vdCB0cmFuc2Zvcm1pbmcgdGhlIHZhbHVlcywgb25seSB0aGUga2V5cyBvZiB0aGVcbiAgLy8gcGlwZWxpbmUuXG4gIF9wYXJzZUFnZ3JlZ2F0ZVByb2plY3RBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbYF9wXyR7ZmllbGR9YF0gPSBwaXBlbGluZVtmaWVsZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUFyZ3Moc2NoZW1hLCBwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoZmllbGQgPT09ICdvYmplY3RJZCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19pZCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbJ19jcmVhdGVkX2F0J10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX3VwZGF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiB0aGUgdHdvIGFib3ZlLiBNb25nb0RCICRncm91cCBhZ2dyZWdhdGUgbG9va3MgbGlrZTpcbiAgLy8gICAgIHsgJGdyb3VwOiB7IF9pZDogPGV4cHJlc3Npb24+LCA8ZmllbGQxPjogeyA8YWNjdW11bGF0b3IxPiA6IDxleHByZXNzaW9uMT4gfSwgLi4uIH0gfVxuICAvLyBUaGUgPGV4cHJlc3Npb24+IGNvdWxkIGJlIGEgY29sdW1uIG5hbWUsIHByZWZpeGVkIHdpdGggdGhlICckJyBjaGFyYWN0ZXIuIFdlJ2xsIGxvb2sgZm9yXG4gIC8vIHRoZXNlIDxleHByZXNzaW9uPiBhbmQgY2hlY2sgdG8gc2VlIGlmIGl0IGlzIGEgJ1BvaW50ZXInIG9yIGlmIGl0J3Mgb25lIG9mIGNyZWF0ZWRBdCxcbiAgLy8gdXBkYXRlZEF0IG9yIG9iamVjdElkIGFuZCBjaGFuZ2UgaXQgYWNjb3JkaW5nbHkuXG4gIF9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSk6IGFueSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICByZXR1cm4gcGlwZWxpbmUubWFwKCh2YWx1ZSkgPT4gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCB2YWx1ZSkpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTtcbiAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gcGlwZWxpbmUpIHtcbiAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCBwaXBlbGluZVtmaWVsZF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBpcGVsaW5lID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgZmllbGQgPSBwaXBlbGluZS5zdWJzdHJpbmcoMSk7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZF0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZF0udHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICAgIHJldHVybiBgJF9wXyR7ZmllbGR9YDtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT0gJ2NyZWF0ZWRBdCcpIHtcbiAgICAgICAgcmV0dXJuICckX2NyZWF0ZWRfYXQnO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PSAndXBkYXRlZEF0Jykge1xuICAgICAgICByZXR1cm4gJyRfdXBkYXRlZF9hdCc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwaXBlbGluZTtcbiAgfVxuXG4gIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBhdHRlbXB0IHRvIGNvbnZlcnQgdGhlIHByb3ZpZGVkIHZhbHVlIHRvIGEgRGF0ZSBvYmplY3QuIFNpbmNlIHRoaXMgaXMgcGFydFxuICAvLyBvZiBhbiBhZ2dyZWdhdGlvbiBwaXBlbGluZSwgdGhlIHZhbHVlIGNhbiBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgaXQgY2FuIGJlIGFub3RoZXIgb2JqZWN0IHdpdGhcbiAgLy8gYW4gb3BlcmF0b3IgaW4gaXQgKGxpa2UgJGd0LCAkbHQsIGV0YykuIEJlY2F1c2Ugb2YgdGhpcyBJIGZlbHQgaXQgd2FzIGVhc2llciB0byBtYWtlIHRoaXMgYVxuICAvLyByZWN1cnNpdmUgbWV0aG9kIHRvIHRyYXZlcnNlIGRvd24gdG8gdGhlIFwibGVhZiBub2RlXCIgd2hpY2ggaXMgZ29pbmcgdG8gYmUgdGhlIHN0cmluZy5cbiAgX2NvbnZlcnRUb0RhdGUodmFsdWU6IGFueSk6IGFueSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fVxuICAgIGZvciAoY29uc3QgZmllbGQgaW4gdmFsdWUpIHtcbiAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX2NvbnZlcnRUb0RhdGUodmFsdWVbZmllbGRdKVxuICAgIH1cbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cblxuICBfcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZTogP3N0cmluZyk6ID9zdHJpbmcge1xuICAgIHN3aXRjaCAocmVhZFByZWZlcmVuY2UpIHtcbiAgICBjYXNlICdQUklNQVJZJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1BSSU1BUllfUFJFRkVSUkVEJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuUFJJTUFSWV9QUkVGRVJSRUQ7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdTRUNPTkRBUlknOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5TRUNPTkRBUlk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdTRUNPTkRBUllfUFJFRkVSUkVEJzpcbiAgICAgIHJlYWRQcmVmZXJlbmNlID0gUmVhZFByZWZlcmVuY2UuU0VDT05EQVJZX1BSRUZFUlJFRDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ05FQVJFU1QnOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5ORUFSRVNUO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSB1bmRlZmluZWQ6XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksICdOb3Qgc3VwcG9ydGVkIHJlYWQgcHJlZmVyZW5jZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlYWRQcmVmZXJlbmNlO1xuICB9XG5cbiAgcGVyZm9ybUluaXRpYWxpemF0aW9uKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4KGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleDogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5jcmVhdGVJbmRleChpbmRleCwge2JhY2tncm91bmQ6IHRydWV9KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGNyZWF0ZUluZGV4ZXMoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4ZXM6IGFueSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uY3JlYXRlSW5kZXhlcyhpbmRleGVzLCB7YmFja2dyb3VuZDogdHJ1ZX0pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZywgdHlwZTogYW55KSB7XG4gICAgaWYgKHR5cGUgJiYgdHlwZS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgIGNvbnN0IGluZGV4ID0ge1xuICAgICAgICBbZmllbGROYW1lXTogJzJkc3BoZXJlJ1xuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUluZGV4KGNsYXNzTmFtZSwgaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBjcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogUXVlcnlUeXBlLCBzY2hlbWE6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvcihjb25zdCBmaWVsZE5hbWUgaW4gcXVlcnkpIHtcbiAgICAgIGlmICghcXVlcnlbZmllbGROYW1lXSB8fCAhcXVlcnlbZmllbGROYW1lXS4kdGV4dCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4aXN0aW5nSW5kZXhlcyA9IHNjaGVtYS5pbmRleGVzO1xuICAgICAgZm9yIChjb25zdCBrZXkgaW4gZXhpc3RpbmdJbmRleGVzKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gZXhpc3RpbmdJbmRleGVzW2tleV07XG4gICAgICAgIGlmIChpbmRleC5oYXNPd25Qcm9wZXJ0eShmaWVsZE5hbWUpKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBpbmRleE5hbWUgPSBgJHtmaWVsZE5hbWV9X3RleHRgO1xuICAgICAgY29uc3QgdGV4dEluZGV4ID0ge1xuICAgICAgICBbaW5kZXhOYW1lXTogeyBbZmllbGROYW1lXTogJ3RleHQnIH1cbiAgICAgIH07XG4gICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWUsIHRleHRJbmRleCwgZXhpc3RpbmdJbmRleGVzLCBzY2hlbWEuZmllbGRzKVxuICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDg1KSB7IC8vIEluZGV4IGV4aXN0IHdpdGggZGlmZmVyZW50IG9wdGlvbnNcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNGcm9tTW9uZ28oY2xhc3NOYW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBnZXRJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5pbmRleGVzKCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wSW5kZXgoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmRyb3BJbmRleChpbmRleCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBkcm9wQWxsSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uZHJvcEluZGV4ZXMoKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHVwZGF0ZVNjaGVtYVdpdGhJbmRleGVzKCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QWxsQ2xhc3NlcygpXG4gICAgICAudGhlbigoY2xhc3NlcykgPT4ge1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IGNsYXNzZXMubWFwKChzY2hlbWEpID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzRnJvbU1vbmdvKHNjaGVtYS5jbGFzc05hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTW9uZ29TdG9yYWdlQWRhcHRlcjtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvU3RvcmFnZUFkYXB0ZXIuanMiXSwibmFtZXMiOlsibW9uZ29kYiIsInJlcXVpcmUiLCJNb25nb0NsaWVudCIsIlJlYWRQcmVmZXJlbmNlIiwiTW9uZ29TY2hlbWFDb2xsZWN0aW9uTmFtZSIsInN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMiLCJtb25nb0FkYXB0ZXIiLCJjb25uZWN0IiwidGhlbiIsImRhdGFiYXNlIiwiY29sbGVjdGlvbnMiLCJmaWx0ZXIiLCJjb2xsZWN0aW9uIiwibmFtZXNwYWNlIiwibWF0Y2giLCJjb2xsZWN0aW9uTmFtZSIsImluZGV4T2YiLCJfY29sbGVjdGlvblByZWZpeCIsImNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEiLCJzY2hlbWEiLCJmaWVsZHMiLCJfcnBlcm0iLCJfd3Blcm0iLCJjbGFzc05hbWUiLCJfaGFzaGVkX3Bhc3N3b3JkIiwibW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiaW5kZXhlcyIsIm1vbmdvT2JqZWN0IiwiX2lkIiwib2JqZWN0SWQiLCJ1cGRhdGVkQXQiLCJjcmVhdGVkQXQiLCJfbWV0YWRhdGEiLCJ1bmRlZmluZWQiLCJmaWVsZE5hbWUiLCJNb25nb1NjaGVtYUNvbGxlY3Rpb24iLCJwYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUiLCJjbGFzc19wZXJtaXNzaW9ucyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJNb25nb1N0b3JhZ2VBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJ1cmkiLCJkZWZhdWx0cyIsIkRlZmF1bHRNb25nb1VSSSIsImNvbGxlY3Rpb25QcmVmaXgiLCJtb25nb09wdGlvbnMiLCJfdXJpIiwiX21vbmdvT3B0aW9ucyIsInVzZU5ld1VybFBhcnNlciIsIl9tYXhUaW1lTVMiLCJtYXhUaW1lTVMiLCJjYW5Tb3J0T25Kb2luVGFibGVzIiwiY29ubmVjdGlvblByb21pc2UiLCJlbmNvZGVkVXJpIiwiY2xpZW50Iiwib3B0aW9ucyIsInMiLCJkYiIsImRiTmFtZSIsIm9uIiwiY2F0Y2giLCJlcnIiLCJQcm9taXNlIiwicmVqZWN0IiwiaGFuZGxlRXJyb3IiLCJlcnJvciIsImNvZGUiLCJsb2dnZXIiLCJoYW5kbGVTaHV0ZG93biIsImNsb3NlIiwiX2FkYXB0aXZlQ29sbGVjdGlvbiIsIm5hbWUiLCJyYXdDb2xsZWN0aW9uIiwiTW9uZ29Db2xsZWN0aW9uIiwiX3NjaGVtYUNvbGxlY3Rpb24iLCJjbGFzc0V4aXN0cyIsImxpc3RDb2xsZWN0aW9ucyIsInRvQXJyYXkiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwic2NoZW1hQ29sbGVjdGlvbiIsInVwZGF0ZVNjaGVtYSIsIiRzZXQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJyZXNvbHZlIiwiX2lkXyIsImRlbGV0ZVByb21pc2VzIiwiaW5zZXJ0ZWRJbmRleGVzIiwiZm9yRWFjaCIsImZpZWxkIiwiX19vcCIsIlBhcnNlIiwiRXJyb3IiLCJJTlZBTElEX1FVRVJZIiwicHJvbWlzZSIsImRyb3BJbmRleCIsInB1c2giLCJrZXkiLCJoYXNPd25Qcm9wZXJ0eSIsImluc2VydFByb21pc2UiLCJjcmVhdGVJbmRleGVzIiwiYWxsIiwic2V0SW5kZXhlc0Zyb21Nb25nbyIsImdldEluZGV4ZXMiLCJyZWR1Y2UiLCJvYmoiLCJpbmRleCIsIl9mdHMiLCJfZnRzeCIsIndlaWdodHMiLCJjcmVhdGVDbGFzcyIsImluc2VydFNjaGVtYSIsImFkZEZpZWxkSWZOb3RFeGlzdHMiLCJ0eXBlIiwiY3JlYXRlSW5kZXhlc0lmTmVlZGVkIiwiZGVsZXRlQ2xhc3MiLCJkcm9wIiwibWVzc2FnZSIsImZpbmRBbmREZWxldGVTY2hlbWEiLCJkZWxldGVBbGxDbGFzc2VzIiwiZmFzdCIsIm1hcCIsInJlbW92ZSIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJtb25nb0Zvcm1hdE5hbWVzIiwiY29sbGVjdGlvblVwZGF0ZSIsInNjaGVtYVVwZGF0ZSIsInVwZGF0ZU1hbnkiLCJnZXRBbGxDbGFzc2VzIiwic2NoZW1hc0NvbGxlY3Rpb24iLCJfZmV0Y2hBbGxTY2hlbWFzRnJvbV9TQ0hFTUEiLCJnZXRDbGFzcyIsIl9mZXRjaE9uZVNjaGVtYUZyb21fU0NIRU1BIiwiY3JlYXRlT2JqZWN0Iiwib2JqZWN0IiwiaW5zZXJ0T25lIiwiRFVQTElDQVRFX1ZBTFVFIiwidW5kZXJseWluZ0Vycm9yIiwibWF0Y2hlcyIsIkFycmF5IiwiaXNBcnJheSIsInVzZXJJbmZvIiwiZHVwbGljYXRlZF9maWVsZCIsImRlbGV0ZU9iamVjdHNCeVF1ZXJ5IiwicXVlcnkiLCJtb25nb1doZXJlIiwiZGVsZXRlTWFueSIsInJlc3VsdCIsIm4iLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiSU5URVJOQUxfU0VSVkVSX0VSUk9SIiwidXBkYXRlT2JqZWN0c0J5UXVlcnkiLCJ1cGRhdGUiLCJtb25nb1VwZGF0ZSIsImZpbmRPbmVBbmRVcGRhdGUiLCJfbW9uZ29Db2xsZWN0aW9uIiwiZmluZEFuZE1vZGlmeSIsIm5ldyIsInZhbHVlIiwidXBzZXJ0T25lT2JqZWN0IiwidXBzZXJ0T25lIiwiZmluZCIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJyZWFkUHJlZmVyZW5jZSIsIm1vbmdvU29ydCIsIl8iLCJtYXBLZXlzIiwibW9uZ29LZXlzIiwibWVtbyIsIl9wYXJzZVJlYWRQcmVmZXJlbmNlIiwiY3JlYXRlVGV4dEluZGV4ZXNJZk5lZWRlZCIsIm9iamVjdHMiLCJlbnN1cmVVbmlxdWVuZXNzIiwiaW5kZXhDcmVhdGlvblJlcXVlc3QiLCJtb25nb0ZpZWxkTmFtZXMiLCJfZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQiLCJfcmF3RmluZCIsImNvdW50IiwiZGlzdGluY3QiLCJpc1BvaW50ZXJGaWVsZCIsInN1YnN0cmluZyIsImFnZ3JlZ2F0ZSIsInBpcGVsaW5lIiwic3RhZ2UiLCIkZ3JvdXAiLCJfcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3MiLCIkbWF0Y2giLCJfcGFyc2VBZ2dyZWdhdGVBcmdzIiwiJHByb2plY3QiLCJfcGFyc2VBZ2dyZWdhdGVQcm9qZWN0QXJncyIsInJlc3VsdHMiLCJzcGxpdCIsImlzRW1wdHkiLCJyZXR1cm5WYWx1ZSIsInRhcmdldENsYXNzIiwiX2NvbnZlcnRUb0RhdGUiLCJEYXRlIiwiUFJJTUFSWSIsIlBSSU1BUllfUFJFRkVSUkVEIiwiU0VDT05EQVJZIiwiU0VDT05EQVJZX1BSRUZFUlJFRCIsIk5FQVJFU1QiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJjcmVhdGVJbmRleCIsImJhY2tncm91bmQiLCIkdGV4dCIsImluZGV4TmFtZSIsInRleHRJbmRleCIsImRyb3BBbGxJbmRleGVzIiwiZHJvcEluZGV4ZXMiLCJ1cGRhdGVTY2hlbWFXaXRoSW5kZXhlcyIsImNsYXNzZXMiLCJwcm9taXNlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFLQTs7QUFJQTs7QUFTQTs7OztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7OztBQUxBOztBQUVBOzs7QUFLQTtBQUNBLE1BQU1BLFVBQVVDLFFBQVEsU0FBUixDQUFoQjtBQUNBLE1BQU1DLGNBQWNGLFFBQVFFLFdBQTVCO0FBQ0EsTUFBTUMsaUJBQWlCSCxRQUFRRyxjQUEvQjs7QUFFQSxNQUFNQyw0QkFBNEIsU0FBbEM7O0FBRUEsTUFBTUMsK0JBQStCQyxnQkFBZ0I7QUFDbkQsU0FBT0EsYUFBYUMsT0FBYixHQUNKQyxJQURJLENBQ0MsTUFBTUYsYUFBYUcsUUFBYixDQUFzQkMsV0FBdEIsRUFEUCxFQUVKRixJQUZJLENBRUNFLGVBQWU7QUFDbkIsV0FBT0EsWUFBWUMsTUFBWixDQUFtQkMsY0FBYztBQUN0QyxVQUFJQSxXQUFXQyxTQUFYLENBQXFCQyxLQUFyQixDQUEyQixZQUEzQixDQUFKLEVB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SixnQkFBWCxDQUE0QnRJLE9BQTVCLEVBRGYsRUFFSm9DLEtBRkksQ0FFRUMsT0FBTyxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQUZULENBQVA7QUFHRDs7QUFFRG9DLFlBQVU3RSxTQUFWLEVBQTZCd0YsS0FBN0IsRUFBeUM7QUFDdkMsV0FBTyxLQUFLdEMsbUJBQUwsQ0FBeUJsRCxTQUF6QixFQUNKZixJQURJLENBQ0NJLGNBQWNBLFdBQVdxSixnQkFBWCxDQUE0QjdELFNBQTVCLENBQXNDVyxLQUF0QyxDQURmLEVBRUpoRCxLQUZJLENBRUVDLE9BQU8sS0FBS0csV0FBTCxDQUFpQkgsR0FBakIsQ0FGVCxDQUFQO0FBR0Q7O0FBRUR3SixpQkFBZWpNLFNBQWYsRUFBa0M7QUFDaEMsV0FBTyxLQUFLa0QsbUJBQUwsQ0FBeUJsRCxTQUF6QixFQUNKZixJQURJLENBQ0NJLGNBQWNBLFdBQVdxSixnQkFBWCxDQUE0QndELFdBQTVCLEVBRGYsRUFFSjFKLEtBRkksQ0FFRUMsT0FBTyxLQUFLRyxXQUFMLENBQWlCSCxHQUFqQixDQUZULENBQVA7QUFHRDs7QUFFRDBKLDRCQUF3QztBQUN0QyxXQUFPLEtBQUtwRixhQUFMLEdBQ0o5SCxJQURJLENBQ0VtTixPQUFELElBQWE7QUFDakIsWUFBTUMsV0FBV0QsUUFBUTdGLEdBQVIsQ0FBYTNHLE1BQUQsSUFBWTtBQUN2QyxlQUFPLEtBQUt3RixtQkFBTCxDQUF5QnhGLE9BQU9JLFNBQWhDLENBQVA7QUFDRCxPQUZnQixDQUFqQjtBQUdBLGFBQU8wQyxRQUFReUMsR0FBUixDQUFZa0gsUUFBWixDQUFQO0FBQ0QsS0FOSSxFQU9KN0osS0FQSSxDQU9FQyxPQUFPLEtBQUtHLFdBQUwsQ0FBaUJILEdBQWpCLENBUFQsQ0FBUDtBQVFEO0FBeHRCd0Q7O1FBQTlDdEIsbUIsR0FBQUEsbUI7a0JBMnRCRUEsbUIiLCJmaWxlIjoiTW9uZ29TdG9yYWdlQWRhcHRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG5pbXBvcnQgTW9uZ29Db2xsZWN0aW9uICAgICAgIGZyb20gJy4vTW9uZ29Db2xsZWN0aW9uJztcbmltcG9ydCBNb25nb1NjaGVtYUNvbGxlY3Rpb24gZnJvbSAnLi9Nb25nb1NjaGVtYUNvbGxlY3Rpb24nO1xuaW1wb3J0IHsgU3RvcmFnZUFkYXB0ZXIgfSAgICBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQgdHlwZSB7IFNjaGVtYVR5cGUsXG4gIFF1ZXJ5VHlwZSxcbiAgU3RvcmFnZUNsYXNzLFxuICBRdWVyeU9wdGlvbnMgfSBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5pbXBvcnQge1xuICBwYXJzZSBhcyBwYXJzZVVybCxcbiAgZm9ybWF0IGFzIGZvcm1hdFVybCxcbn0gZnJvbSAnLi4vLi4vLi4vdmVuZG9yL21vbmdvZGJVcmwnO1xuaW1wb3J0IHtcbiAgcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlLFxuICBtb25nb09iamVjdFRvUGFyc2VPYmplY3QsXG4gIHRyYW5zZm9ybUtleSxcbiAgdHJhbnNmb3JtV2hlcmUsXG4gIHRyYW5zZm9ybVVwZGF0ZSxcbiAgdHJhbnNmb3JtUG9pbnRlclN0cmluZyxcbn0gZnJvbSAnLi9Nb25nb1RyYW5zZm9ybSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBQYXJzZSAgICAgICAgICAgICAgICAgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBfICAgICAgICAgICAgICAgICAgICAgZnJvbSAnbG9kYXNoJztcbmltcG9ydCBkZWZhdWx0cyAgICAgICAgICAgICAgZnJvbSAnLi4vLi4vLi4vZGVmYXVsdHMnO1xuaW1wb3J0IGxvZ2dlciAgICAgICAgICAgICAgICBmcm9tICcuLi8uLi8uLi9sb2dnZXInO1xuXG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmNvbnN0IG1vbmdvZGIgPSByZXF1aXJlKCdtb25nb2RiJyk7XG5jb25zdCBNb25nb0NsaWVudCA9IG1vbmdvZGIuTW9uZ29DbGllbnQ7XG5jb25zdCBSZWFkUHJlZmVyZW5jZSA9IG1vbmdvZGIuUmVhZFByZWZlcmVuY2U7XG5cbmNvbnN0IE1vbmdvU2NoZW1hQ29sbGVjdGlvbk5hbWUgPSAnX1NDSEVNQSc7XG5cbmNvbnN0IHN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnMgPSBtb25nb0FkYXB0ZXIgPT4ge1xuICByZXR1cm4gbW9uZ29BZGFwdGVyLmNvbm5lY3QoKVxuICAgIC50aGVuKCgpID0+IG1vbmdvQWRhcHRlci5kYXRhYmFzZS5jb2xsZWN0aW9ucygpKVxuICAgIC50aGVuKGNvbGxlY3Rpb25zID0+IHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9ucy5maWx0ZXIoY29sbGVjdGlvbiA9PiB7XG4gICAgICAgIGlmIChjb2xsZWN0aW9uLm5hbWVzcGFjZS5tYXRjaCgvXFwuc3lzdGVtXFwuLykpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogSWYgeW91IGhhdmUgb25lIGFwcCB3aXRoIGEgY29sbGVjdGlvbiBwcmVmaXggdGhhdCBoYXBwZW5zIHRvIGJlIGEgcHJlZml4IG9mIGFub3RoZXJcbiAgICAgICAgLy8gYXBwcyBwcmVmaXgsIHRoaXMgd2lsbCBnbyB2ZXJ5IHZlcnkgYmFkbHkuIFdlIHNob3VsZCBmaXggdGhhdCBzb21laG93LlxuICAgICAgICByZXR1cm4gKGNvbGxlY3Rpb24uY29sbGVjdGlvbk5hbWUuaW5kZXhPZihtb25nb0FkYXB0ZXIuX2NvbGxlY3Rpb25QcmVmaXgpID09IDApO1xuICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmNvbnN0IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEgPSAoey4uLnNjaGVtYX0pID0+IHtcbiAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX3JwZXJtO1xuICBkZWxldGUgc2NoZW1hLmZpZWxkcy5fd3Blcm07XG5cbiAgaWYgKHNjaGVtYS5jbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICAvLyBMZWdhY3kgbW9uZ28gYWRhcHRlciBrbm93cyBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHBhc3N3b3JkIGFuZCBfaGFzaGVkX3Bhc3N3b3JkLlxuICAgIC8vIEZ1dHVyZSBkYXRhYmFzZSBhZGFwdGVycyB3aWxsIG9ubHkga25vdyBhYm91dCBfaGFzaGVkX3Bhc3N3b3JkLlxuICAgIC8vIE5vdGU6IFBhcnNlIFNlcnZlciB3aWxsIGJyaW5nIGJhY2sgcGFzc3dvcmQgd2l0aCBpbmplY3REZWZhdWx0U2NoZW1hLCBzbyB3ZSBkb24ndCBuZWVkXG4gICAgLy8gdG8gYWRkIF9oYXNoZWRfcGFzc3dvcmQgYmFjayBldmVyLlxuICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl9oYXNoZWRfcGFzc3dvcmQ7XG4gIH1cblxuICByZXR1cm4gc2NoZW1hO1xufVxuXG4vLyBSZXR1cm5zIHsgY29kZSwgZXJyb3IgfSBpZiBpbnZhbGlkLCBvciB7IHJlc3VsdCB9LCBhbiBvYmplY3Rcbi8vIHN1aXRhYmxlIGZvciBpbnNlcnRpbmcgaW50byBfU0NIRU1BIGNvbGxlY3Rpb24sIG90aGVyd2lzZS5cbmNvbnN0IG1vbmdvU2NoZW1hRnJvbUZpZWxkc0FuZENsYXNzTmFtZUFuZENMUCA9IChmaWVsZHMsIGNsYXNzTmFtZSwgY2xhc3NMZXZlbFBlcm1pc3Npb25zLCBpbmRleGVzKSA9PiB7XG4gIGNvbnN0IG1vbmdvT2JqZWN0ID0ge1xuICAgIF9pZDogY2xhc3NOYW1lLFxuICAgIG9iamVjdElkOiAnc3RyaW5nJyxcbiAgICB1cGRhdGVkQXQ6ICdzdHJpbmcnLFxuICAgIGNyZWF0ZWRBdDogJ3N0cmluZycsXG4gICAgX21ldGFkYXRhOiB1bmRlZmluZWQsXG4gIH07XG5cbiAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gZmllbGRzKSB7XG4gICAgbW9uZ29PYmplY3RbZmllbGROYW1lXSA9IE1vbmdvU2NoZW1hQ29sbGVjdGlvbi5wYXJzZUZpZWxkVHlwZVRvTW9uZ29GaWVsZFR5cGUoZmllbGRzW2ZpZWxkTmFtZV0pO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjbGFzc0xldmVsUGVybWlzc2lvbnMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhID0gbW9uZ29PYmplY3QuX21ldGFkYXRhIHx8IHt9O1xuICAgIGlmICghY2xhc3NMZXZlbFBlcm1pc3Npb25zKSB7XG4gICAgICBkZWxldGUgbW9uZ29PYmplY3QuX21ldGFkYXRhLmNsYXNzX3Blcm1pc3Npb25zO1xuICAgIH0gZWxzZSB7XG4gICAgICBtb25nb09iamVjdC5fbWV0YWRhdGEuY2xhc3NfcGVybWlzc2lvbnMgPSBjbGFzc0xldmVsUGVybWlzc2lvbnM7XG4gICAgfVxuICB9XG5cbiAgaWYgKGluZGV4ZXMgJiYgdHlwZW9mIGluZGV4ZXMgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKGluZGV4ZXMpLmxlbmd0aCA+IDApIHtcbiAgICBtb25nb09iamVjdC5fbWV0YWRhdGEgPSBtb25nb09iamVjdC5fbWV0YWRhdGEgfHwge307XG4gICAgbW9uZ29PYmplY3QuX21ldGFkYXRhLmluZGV4ZXMgPSBpbmRleGVzO1xuICB9XG5cbiAgaWYgKCFtb25nb09iamVjdC5fbWV0YWRhdGEpIHsgLy8gY2xlYW51cCB0aGUgdW51c2VkIF9tZXRhZGF0YVxuICAgIGRlbGV0ZSBtb25nb09iamVjdC5fbWV0YWRhdGE7XG4gIH1cblxuICByZXR1cm4gbW9uZ29PYmplY3Q7XG59XG5cblxuZXhwb3J0IGNsYXNzIE1vbmdvU3RvcmFnZUFkYXB0ZXIgaW1wbGVtZW50cyBTdG9yYWdlQWRhcHRlciB7XG4gIC8vIFByaXZhdGVcbiAgX3VyaTogc3RyaW5nO1xuICBfY29sbGVjdGlvblByZWZpeDogc3RyaW5nO1xuICBfbW9uZ29PcHRpb25zOiBPYmplY3Q7XG4gIC8vIFB1YmxpY1xuICBjb25uZWN0aW9uUHJvbWlzZTogUHJvbWlzZTxhbnk+O1xuICBkYXRhYmFzZTogYW55O1xuICBjbGllbnQ6IE1vbmdvQ2xpZW50O1xuICBfbWF4VGltZU1TOiA/bnVtYmVyO1xuICBjYW5Tb3J0T25Kb2luVGFibGVzOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHtcbiAgICB1cmkgPSBkZWZhdWx0cy5EZWZhdWx0TW9uZ29VUkksXG4gICAgY29sbGVjdGlvblByZWZpeCA9ICcnLFxuICAgIG1vbmdvT3B0aW9ucyA9IHt9LFxuICB9OiBhbnkpIHtcbiAgICB0aGlzLl91cmkgPSB1cmk7XG4gICAgdGhpcy5fY29sbGVjdGlvblByZWZpeCA9IGNvbGxlY3Rpb25QcmVmaXg7XG4gICAgdGhpcy5fbW9uZ29PcHRpb25zID0gbW9uZ29PcHRpb25zO1xuICAgIHRoaXMuX21vbmdvT3B0aW9ucy51c2VOZXdVcmxQYXJzZXIgPSB0cnVlO1xuXG4gICAgLy8gTWF4VGltZU1TIGlzIG5vdCBhIGdsb2JhbCBNb25nb0RCIGNsaWVudCBvcHRpb24sIGl0IGlzIGFwcGxpZWQgcGVyIG9wZXJhdGlvbi5cbiAgICB0aGlzLl9tYXhUaW1lTVMgPSBtb25nb09wdGlvbnMubWF4VGltZU1TO1xuICAgIHRoaXMuY2FuU29ydE9uSm9pblRhYmxlcyA9IHRydWU7XG4gICAgZGVsZXRlIG1vbmdvT3B0aW9ucy5tYXhUaW1lTVM7XG4gIH1cblxuICBjb25uZWN0KCkge1xuICAgIGlmICh0aGlzLmNvbm5lY3Rpb25Qcm9taXNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICB9XG5cbiAgICAvLyBwYXJzaW5nIGFuZCByZS1mb3JtYXR0aW5nIGNhdXNlcyB0aGUgYXV0aCB2YWx1ZSAoaWYgdGhlcmUpIHRvIGdldCBVUklcbiAgICAvLyBlbmNvZGVkXG4gICAgY29uc3QgZW5jb2RlZFVyaSA9IGZvcm1hdFVybChwYXJzZVVybCh0aGlzLl91cmkpKTtcblxuICAgIHRoaXMuY29ubmVjdGlvblByb21pc2UgPSBNb25nb0NsaWVudC5jb25uZWN0KGVuY29kZWRVcmksIHRoaXMuX21vbmdvT3B0aW9ucykudGhlbihjbGllbnQgPT4ge1xuICAgICAgLy8gU3RhcnRpbmcgbW9uZ29EQiAzLjAsIHRoZSBNb25nb0NsaWVudC5jb25uZWN0IGRvbid0IHJldHVybiBhIERCIGFueW1vcmUgYnV0IGEgY2xpZW50XG4gICAgICAvLyBGb3J0dW5hdGVseSwgd2UgY2FuIGdldCBiYWNrIHRoZSBvcHRpb25zIGFuZCB1c2UgdGhlbSB0byBzZWxlY3QgdGhlIHByb3BlciBEQi5cbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb25nb2RiL25vZGUtbW9uZ29kYi1uYXRpdmUvYmxvYi8yYzM1ZDc2ZjA4NTc0MjI1YjhkYjAyZDdiZWY2ODcxMjNlNmJiMDE4L2xpYi9tb25nb19jbGllbnQuanMjTDg4NVxuICAgICAgY29uc3Qgb3B0aW9ucyA9IGNsaWVudC5zLm9wdGlvbnM7XG4gICAgICBjb25zdCBkYXRhYmFzZSA9IGNsaWVudC5kYihvcHRpb25zLmRiTmFtZSk7XG4gICAgICBpZiAoIWRhdGFiYXNlKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBkYXRhYmFzZS5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgfSk7XG4gICAgICBkYXRhYmFzZS5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmNvbm5lY3Rpb25Qcm9taXNlO1xuICAgICAgfSk7XG4gICAgICB0aGlzLmNsaWVudCA9IGNsaWVudDtcbiAgICAgIHRoaXMuZGF0YWJhc2UgPSBkYXRhYmFzZTtcbiAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBkZWxldGUgdGhpcy5jb25uZWN0aW9uUHJvbWlzZTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gIH1cblxuICBoYW5kbGVFcnJvcjxUPihlcnJvcjogPyhFcnJvciB8IFBhcnNlLkVycm9yKSk6IFByb21pc2U8VD4ge1xuICAgIGlmIChlcnJvciAmJiBlcnJvci5jb2RlID09PSAxMykgeyAvLyBVbmF1dGhvcml6ZWQgZXJyb3JcbiAgICAgIGRlbGV0ZSB0aGlzLmNsaWVudDtcbiAgICAgIGRlbGV0ZSB0aGlzLmRhdGFiYXNlO1xuICAgICAgZGVsZXRlIHRoaXMuY29ubmVjdGlvblByb21pc2U7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1JlY2VpdmVkIHVuYXV0aG9yaXplZCBlcnJvcicsIHsgZXJyb3I6IGVycm9yIH0pO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuXG4gIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGlmICghdGhpcy5jbGllbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jbGllbnQuY2xvc2UoZmFsc2UpO1xuICB9XG5cbiAgX2FkYXB0aXZlQ29sbGVjdGlvbihuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0KClcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuZGF0YWJhc2UuY29sbGVjdGlvbih0aGlzLl9jb2xsZWN0aW9uUHJlZml4ICsgbmFtZSkpXG4gICAgICAudGhlbihyYXdDb2xsZWN0aW9uID0+IG5ldyBNb25nb0NvbGxlY3Rpb24ocmF3Q29sbGVjdGlvbikpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBfc2NoZW1hQ29sbGVjdGlvbigpOiBQcm9taXNlPE1vbmdvU2NoZW1hQ29sbGVjdGlvbj4ge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3QoKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKE1vbmdvU2NoZW1hQ29sbGVjdGlvbk5hbWUpKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBuZXcgTW9uZ29TY2hlbWFDb2xsZWN0aW9uKGNvbGxlY3Rpb24pKTtcbiAgfVxuXG4gIGNsYXNzRXhpc3RzKG5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3QoKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmRhdGFiYXNlLmxpc3RDb2xsZWN0aW9ucyh7IG5hbWU6IHRoaXMuX2NvbGxlY3Rpb25QcmVmaXggKyBuYW1lIH0pLnRvQXJyYXkoKTtcbiAgICB9KS50aGVuKGNvbGxlY3Rpb25zID0+IHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9ucy5sZW5ndGggPiAwO1xuICAgIH0pLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgc2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKGNsYXNzTmFtZTogc3RyaW5nLCBDTFBzOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAkc2V0OiB7ICdfbWV0YWRhdGEuY2xhc3NfcGVybWlzc2lvbnMnOiBDTFBzIH1cbiAgICAgIH0pKS5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KGNsYXNzTmFtZTogc3RyaW5nLCBzdWJtaXR0ZWRJbmRleGVzOiBhbnksIGV4aXN0aW5nSW5kZXhlczogYW55ID0ge30sIGZpZWxkczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHN1Ym1pdHRlZEluZGV4ZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICBpZiAoT2JqZWN0LmtleXMoZXhpc3RpbmdJbmRleGVzKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGV4aXN0aW5nSW5kZXhlcyA9IHsgX2lkXzogeyBfaWQ6IDF9IH07XG4gICAgfVxuICAgIGNvbnN0IGRlbGV0ZVByb21pc2VzID0gW107XG4gICAgY29uc3QgaW5zZXJ0ZWRJbmRleGVzID0gW107XG4gICAgT2JqZWN0LmtleXMoc3VibWl0dGVkSW5kZXhlcykuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkID0gc3VibWl0dGVkSW5kZXhlc1tuYW1lXTtcbiAgICAgIGlmIChleGlzdGluZ0luZGV4ZXNbbmFtZV0gJiYgZmllbGQuX19vcCAhPT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksIGBJbmRleCAke25hbWV9IGV4aXN0cywgY2Fubm90IHVwZGF0ZS5gKTtcbiAgICAgIH1cbiAgICAgIGlmICghZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW5kZXggJHtuYW1lfSBkb2VzIG5vdCBleGlzdCwgY2Fubm90IGRlbGV0ZS5gKTtcbiAgICAgIH1cbiAgICAgIGlmIChmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5kcm9wSW5kZXgoY2xhc3NOYW1lLCBuYW1lKTtcbiAgICAgICAgZGVsZXRlUHJvbWlzZXMucHVzaChwcm9taXNlKTtcbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nSW5kZXhlc1tuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGZpZWxkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKCFmaWVsZHMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfUVVFUlksIGBGaWVsZCAke2tleX0gZG9lcyBub3QgZXhpc3QsIGNhbm5vdCBhZGQgaW5kZXguYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZXhpc3RpbmdJbmRleGVzW25hbWVdID0gZmllbGQ7XG4gICAgICAgIGluc2VydGVkSW5kZXhlcy5wdXNoKHtcbiAgICAgICAgICBrZXk6IGZpZWxkLFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGxldCBpbnNlcnRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgaWYgKGluc2VydGVkSW5kZXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICBpbnNlcnRQcm9taXNlID0gdGhpcy5jcmVhdGVJbmRleGVzKGNsYXNzTmFtZSwgaW5zZXJ0ZWRJbmRleGVzKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKGRlbGV0ZVByb21pc2VzKVxuICAgICAgLnRoZW4oKCkgPT4gaW5zZXJ0UHJvbWlzZSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKSlcbiAgICAgIC50aGVuKHNjaGVtYUNvbGxlY3Rpb24gPT4gc2NoZW1hQ29sbGVjdGlvbi51cGRhdGVTY2hlbWEoY2xhc3NOYW1lLCB7XG4gICAgICAgICRzZXQ6IHsgJ19tZXRhZGF0YS5pbmRleGVzJzogIGV4aXN0aW5nSW5kZXhlcyB9XG4gICAgICB9KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIHNldEluZGV4ZXNGcm9tTW9uZ28oY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRJbmRleGVzKGNsYXNzTmFtZSkudGhlbigoaW5kZXhlcykgPT4ge1xuICAgICAgaW5kZXhlcyA9IGluZGV4ZXMucmVkdWNlKChvYmosIGluZGV4KSA9PiB7XG4gICAgICAgIGlmIChpbmRleC5rZXkuX2Z0cykge1xuICAgICAgICAgIGRlbGV0ZSBpbmRleC5rZXkuX2Z0cztcbiAgICAgICAgICBkZWxldGUgaW5kZXgua2V5Ll9mdHN4O1xuICAgICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gaW5kZXgud2VpZ2h0cykge1xuICAgICAgICAgICAgaW5kZXgua2V5W2ZpZWxkXSA9ICd0ZXh0JztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgb2JqW2luZGV4Lm5hbWVdID0gaW5kZXgua2V5O1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgfSwge30pO1xuICAgICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwge1xuICAgICAgICAgICRzZXQ6IHsgJ19tZXRhZGF0YS5pbmRleGVzJzogaW5kZXhlcyB9XG4gICAgICAgIH0pKTtcbiAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpXG4gICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICAvLyBJZ25vcmUgaWYgY29sbGVjdGlvbiBub3QgZm91bmRcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gIH1cblxuICBjcmVhdGVDbGFzcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvT2JqZWN0ID0gbW9uZ29TY2hlbWFGcm9tRmllbGRzQW5kQ2xhc3NOYW1lQW5kQ0xQKHNjaGVtYS5maWVsZHMsIGNsYXNzTmFtZSwgc2NoZW1hLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucywgc2NoZW1hLmluZGV4ZXMpO1xuICAgIG1vbmdvT2JqZWN0Ll9pZCA9IGNsYXNzTmFtZTtcbiAgICByZXR1cm4gdGhpcy5zZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdChjbGFzc05hbWUsIHNjaGVtYS5pbmRleGVzLCB7fSwgc2NoZW1hLmZpZWxkcylcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKSlcbiAgICAgIC50aGVuKHNjaGVtYUNvbGxlY3Rpb24gPT4gc2NoZW1hQ29sbGVjdGlvbi5pbnNlcnRTY2hlbWEobW9uZ29PYmplY3QpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgYWRkRmllbGRJZk5vdEV4aXN0cyhjbGFzc05hbWU6IHN0cmluZywgZmllbGROYW1lOiBzdHJpbmcsIHR5cGU6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKClcbiAgICAgIC50aGVuKHNjaGVtYUNvbGxlY3Rpb24gPT4gc2NoZW1hQ29sbGVjdGlvbi5hZGRGaWVsZElmTm90RXhpc3RzKGNsYXNzTmFtZSwgZmllbGROYW1lLCB0eXBlKSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuY3JlYXRlSW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZSwgZmllbGROYW1lLCB0eXBlKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIERyb3BzIGEgY29sbGVjdGlvbi4gUmVzb2x2ZXMgd2l0aCB0cnVlIGlmIGl0IHdhcyBhIFBhcnNlIFNjaGVtYSAoZWcuIF9Vc2VyLCBDdXN0b20sIGV0Yy4pXG4gIC8vIGFuZCByZXNvbHZlcyB3aXRoIGZhbHNlIGlmIGl0IHdhc24ndCAoZWcuIGEgam9pbiB0YWJsZSkuIFJlamVjdHMgaWYgZGVsZXRpb24gd2FzIGltcG9zc2libGUuXG4gIGRlbGV0ZUNsYXNzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uZHJvcCgpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIC8vICducyBub3QgZm91bmQnIG1lYW5zIGNvbGxlY3Rpb24gd2FzIGFscmVhZHkgZ29uZS4gSWdub3JlIGRlbGV0aW9uIGF0dGVtcHQuXG4gICAgICAgIGlmIChlcnJvci5tZXNzYWdlID09ICducyBub3QgZm91bmQnKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAvLyBXZSd2ZSBkcm9wcGVkIHRoZSBjb2xsZWN0aW9uLCBub3cgcmVtb3ZlIHRoZSBfU0NIRU1BIGRvY3VtZW50XG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24uZmluZEFuZERlbGV0ZVNjaGVtYShjbGFzc05hbWUpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgZGVsZXRlQWxsQ2xhc3NlcyhmYXN0OiBib29sZWFuKSB7XG4gICAgcmV0dXJuIHN0b3JhZ2VBZGFwdGVyQWxsQ29sbGVjdGlvbnModGhpcylcbiAgICAgIC50aGVuKGNvbGxlY3Rpb25zID0+IFByb21pc2UuYWxsKGNvbGxlY3Rpb25zLm1hcChjb2xsZWN0aW9uID0+IGZhc3QgPyBjb2xsZWN0aW9uLnJlbW92ZSh7fSkgOiBjb2xsZWN0aW9uLmRyb3AoKSkpKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSB0aGUgY29sdW1uIGFuZCBhbGwgdGhlIGRhdGEuIEZvciBSZWxhdGlvbnMsIHRoZSBfSm9pbiBjb2xsZWN0aW9uIGlzIGhhbmRsZWRcbiAgLy8gc3BlY2lhbGx5LCB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IGRlbGV0ZSBfSm9pbiBjb2x1bW5zLiBJdCBzaG91bGQsIGhvd2V2ZXIsIGluZGljYXRlXG4gIC8vIHRoYXQgdGhlIHJlbGF0aW9uIGZpZWxkcyBkb2VzIG5vdCBleGlzdCBhbnltb3JlLiBJbiBtb25nbywgdGhpcyBtZWFucyByZW1vdmluZyBpdCBmcm9tXG4gIC8vIHRoZSBfU0NIRU1BIGNvbGxlY3Rpb24uICBUaGVyZSBzaG91bGQgYmUgbm8gYWN0dWFsIGRhdGEgaW4gdGhlIGNvbGxlY3Rpb24gdW5kZXIgdGhlIHNhbWUgbmFtZVxuICAvLyBhcyB0aGUgcmVsYXRpb24gY29sdW1uLCBzbyBpdCdzIGZpbmUgdG8gYXR0ZW1wdCB0byBkZWxldGUgaXQuIElmIHRoZSBmaWVsZHMgbGlzdGVkIHRvIGJlXG4gIC8vIGRlbGV0ZWQgZG8gbm90IGV4aXN0LCB0aGlzIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gc3VjY2Vzc2Z1bGx5IGFueXdheXMuIENoZWNraW5nIGZvclxuICAvLyBhdHRlbXB0cyB0byBkZWxldGUgbm9uLWV4aXN0ZW50IGZpZWxkcyBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgUGFyc2UgU2VydmVyLlxuXG4gIC8vIFBvaW50ZXIgZmllbGQgbmFtZXMgYXJlIHBhc3NlZCBmb3IgbGVnYWN5IHJlYXNvbnM6IHRoZSBvcmlnaW5hbCBtb25nb1xuICAvLyBmb3JtYXQgc3RvcmVkIHBvaW50ZXIgZmllbGQgbmFtZXMgZGlmZmVyZW50bHkgaW4gdGhlIGRhdGFiYXNlLCBhbmQgdGhlcmVmb3JlXG4gIC8vIG5lZWRlZCB0byBrbm93IHRoZSB0eXBlIG9mIHRoZSBmaWVsZCBiZWZvcmUgaXQgY291bGQgZGVsZXRlIGl0LiBGdXR1cmUgZGF0YWJhc2VcbiAgLy8gYWRhcHRlcnMgc2hvdWxkIGlnbm9yZSB0aGUgcG9pbnRlckZpZWxkTmFtZXMgYXJndW1lbnQuIEFsbCB0aGUgZmllbGQgbmFtZXMgYXJlIGluXG4gIC8vIGZpZWxkTmFtZXMsIHRoZXkgc2hvdyB1cCBhZGRpdGlvbmFsbHkgaW4gdGhlIHBvaW50ZXJGaWVsZE5hbWVzIGRhdGFiYXNlIGZvciB1c2VcbiAgLy8gYnkgdGhlIG1vbmdvIGFkYXB0ZXIsIHdoaWNoIGRlYWxzIHdpdGggdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQuXG5cbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBub3Qgb2JsaWdhdGVkIHRvIGRlbGV0ZSBmaWVsZHMgYXRvbWljYWxseS4gSXQgaXMgZ2l2ZW4gdGhlIGZpZWxkXG4gIC8vIG5hbWVzIGluIGEgbGlzdCBzbyB0aGF0IGRhdGFiYXNlcyB0aGF0IGFyZSBjYXBhYmxlIG9mIGRlbGV0aW5nIGZpZWxkcyBhdG9taWNhbGx5XG4gIC8vIG1heSBkbyBzby5cblxuICAvLyBSZXR1cm5zIGEgUHJvbWlzZS5cbiAgZGVsZXRlRmllbGRzKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGZpZWxkTmFtZXM6IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgbW9uZ29Gb3JtYXROYW1lcyA9IGZpZWxkTmFtZXMubWFwKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm4gYF9wXyR7ZmllbGROYW1lfWBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmaWVsZE5hbWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29uc3QgY29sbGVjdGlvblVwZGF0ZSA9IHsgJyR1bnNldCcgOiB7fSB9O1xuICAgIG1vbmdvRm9ybWF0TmFtZXMuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgIGNvbGxlY3Rpb25VcGRhdGVbJyR1bnNldCddW25hbWVdID0gbnVsbDtcbiAgICB9KTtcblxuICAgIGNvbnN0IHNjaGVtYVVwZGF0ZSA9IHsgJyR1bnNldCcgOiB7fSB9O1xuICAgIGZpZWxkTmFtZXMuZm9yRWFjaChuYW1lID0+IHtcbiAgICAgIHNjaGVtYVVwZGF0ZVsnJHVuc2V0J11bbmFtZV0gPSBudWxsO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24udXBkYXRlTWFueSh7fSwgY29sbGVjdGlvblVwZGF0ZSkpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLl9zY2hlbWFDb2xsZWN0aW9uKCkpXG4gICAgICAudGhlbihzY2hlbWFDb2xsZWN0aW9uID0+IHNjaGVtYUNvbGxlY3Rpb24udXBkYXRlU2NoZW1hKGNsYXNzTmFtZSwgc2NoZW1hVXBkYXRlKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFJldHVybiBhIHByb21pc2UgZm9yIGFsbCBzY2hlbWFzIGtub3duIHRvIHRoaXMgYWRhcHRlciwgaW4gUGFyc2UgZm9ybWF0LiBJbiBjYXNlIHRoZVxuICAvLyBzY2hlbWFzIGNhbm5vdCBiZSByZXRyaWV2ZWQsIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVqZWN0cy4gUmVxdWlyZW1lbnRzIGZvciB0aGVcbiAgLy8gcmVqZWN0aW9uIHJlYXNvbiBhcmUgVEJELlxuICBnZXRBbGxDbGFzc2VzKCk6IFByb21pc2U8U3RvcmFnZUNsYXNzW10+IHtcbiAgICByZXR1cm4gdGhpcy5fc2NoZW1hQ29sbGVjdGlvbigpLnRoZW4oc2NoZW1hc0NvbGxlY3Rpb24gPT4gc2NoZW1hc0NvbGxlY3Rpb24uX2ZldGNoQWxsU2NoZW1hc0Zyb21fU0NIRU1BKCkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBSZXR1cm4gYSBwcm9taXNlIGZvciB0aGUgc2NoZW1hIHdpdGggdGhlIGdpdmVuIG5hbWUsIGluIFBhcnNlIGZvcm1hdC4gSWZcbiAgLy8gdGhpcyBhZGFwdGVyIGRvZXNuJ3Qga25vdyBhYm91dCB0aGUgc2NoZW1hLCByZXR1cm4gYSBwcm9taXNlIHRoYXQgcmVqZWN0cyB3aXRoXG4gIC8vIHVuZGVmaW5lZCBhcyB0aGUgcmVhc29uLlxuICBnZXRDbGFzcyhjbGFzc05hbWU6IHN0cmluZyk6IFByb21pc2U8U3RvcmFnZUNsYXNzPiB7XG4gICAgcmV0dXJuIHRoaXMuX3NjaGVtYUNvbGxlY3Rpb24oKVxuICAgICAgLnRoZW4oc2NoZW1hc0NvbGxlY3Rpb24gPT4gc2NoZW1hc0NvbGxlY3Rpb24uX2ZldGNoT25lU2NoZW1hRnJvbV9TQ0hFTUEoY2xhc3NOYW1lKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIFRPRE86IEFzIHlldCBub3QgcGFydGljdWxhcmx5IHdlbGwgc3BlY2lmaWVkLiBDcmVhdGVzIGFuIG9iamVjdC4gTWF5YmUgc2hvdWxkbid0IGV2ZW4gbmVlZCB0aGUgc2NoZW1hLFxuICAvLyBhbmQgc2hvdWxkIGluZmVyIGZyb20gdGhlIHR5cGUuIE9yIG1heWJlIGRvZXMgbmVlZCB0aGUgc2NoZW1hIGZvciB2YWxpZGF0aW9ucy4gT3IgbWF5YmUgbmVlZHNcbiAgLy8gdGhlIHNjaGVtYSBvbmx5IGZvciB0aGUgbGVnYWN5IG1vbmdvIGZvcm1hdC4gV2UnbGwgZmlndXJlIHRoYXQgb3V0IGxhdGVyLlxuICBjcmVhdGVPYmplY3QoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgb2JqZWN0OiBhbnkpIHtcbiAgICBzY2hlbWEgPSBjb252ZXJ0UGFyc2VTY2hlbWFUb01vbmdvU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgbW9uZ29PYmplY3QgPSBwYXJzZU9iamVjdFRvTW9uZ29PYmplY3RGb3JDcmVhdGUoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uaW5zZXJ0T25lKG1vbmdvT2JqZWN0KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxMTAwMCkgeyAvLyBEdXBsaWNhdGUgdmFsdWVcbiAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLCAnQSBkdXBsaWNhdGUgdmFsdWUgZm9yIGEgZmllbGQgd2l0aCB1bmlxdWUgdmFsdWVzIHdhcyBwcm92aWRlZCcpO1xuICAgICAgICAgIGVyci51bmRlcmx5aW5nRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICBpZiAoZXJyb3IubWVzc2FnZSkge1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlcyA9IGVycm9yLm1lc3NhZ2UubWF0Y2goL2luZGV4OltcXHNhLXpBLVowLTlfXFwtXFwuXStcXCQ/KFthLXpBLVpfLV0rKV8xLyk7XG4gICAgICAgICAgICBpZiAobWF0Y2hlcyAmJiBBcnJheS5pc0FycmF5KG1hdGNoZXMpKSB7XG4gICAgICAgICAgICAgIGVyci51c2VySW5mbyA9IHsgZHVwbGljYXRlZF9maWVsZDogbWF0Y2hlc1sxXSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gUmVtb3ZlIGFsbCBvYmplY3RzIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIFBhcnNlIFF1ZXJ5LlxuICAvLyBJZiBubyBvYmplY3RzIG1hdGNoLCByZWplY3Qgd2l0aCBPQkpFQ1RfTk9UX0ZPVU5ELiBJZiBvYmplY3RzIGFyZSBmb3VuZCBhbmQgZGVsZXRlZCwgcmVzb2x2ZSB3aXRoIHVuZGVmaW5lZC5cbiAgLy8gSWYgdGhlcmUgaXMgc29tZSBvdGhlciBlcnJvciwgcmVqZWN0IHdpdGggSU5URVJOQUxfU0VSVkVSX0VSUk9SLlxuICBkZWxldGVPYmplY3RzQnlRdWVyeShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiB7XG4gICAgICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbi5kZWxldGVNYW55KG1vbmdvV2hlcmUpXG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpXG4gICAgICAudGhlbigoeyByZXN1bHQgfSkgPT4ge1xuICAgICAgICBpZiAocmVzdWx0Lm4gPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ09iamVjdCBub3QgZm91bmQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSwgKCkgPT4ge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLCAnRGF0YWJhc2UgYWRhcHRlciBlcnJvcicpO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBBcHBseSB0aGUgdXBkYXRlIHRvIGFsbCBvYmplY3RzIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIFBhcnNlIFF1ZXJ5LlxuICB1cGRhdGVPYmplY3RzQnlRdWVyeShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB1cGRhdGU6IGFueSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi51cGRhdGVNYW55KG1vbmdvV2hlcmUsIG1vbmdvVXBkYXRlKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIEF0b21pY2FsbHkgZmluZHMgYW5kIHVwZGF0ZXMgYW4gb2JqZWN0IGJhc2VkIG9uIHF1ZXJ5LlxuICAvLyBSZXR1cm4gdmFsdWUgbm90IGN1cnJlbnRseSB3ZWxsIHNwZWNpZmllZC5cbiAgZmluZE9uZUFuZFVwZGF0ZShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBxdWVyeTogUXVlcnlUeXBlLCB1cGRhdGU6IGFueSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1VwZGF0ZSA9IHRyYW5zZm9ybVVwZGF0ZShjbGFzc05hbWUsIHVwZGF0ZSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb25nb1doZXJlID0gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmZpbmRBbmRNb2RpZnkobW9uZ29XaGVyZSwgW10sIG1vbmdvVXBkYXRlLCB7IG5ldzogdHJ1ZSB9KSlcbiAgICAgIC50aGVuKHJlc3VsdCA9PiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCByZXN1bHQudmFsdWUsIHNjaGVtYSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gMTEwMDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLCAnQSBkdXBsaWNhdGUgdmFsdWUgZm9yIGEgZmllbGQgd2l0aCB1bmlxdWUgdmFsdWVzIHdhcyBwcm92aWRlZCcpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIEhvcGVmdWxseSB3ZSBjYW4gZ2V0IHJpZCBvZiB0aGlzLiBJdCdzIG9ubHkgdXNlZCBmb3IgY29uZmlnIGFuZCBob29rcy5cbiAgdXBzZXJ0T25lT2JqZWN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIHVwZGF0ZTogYW55KSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvVXBkYXRlID0gdHJhbnNmb3JtVXBkYXRlKGNsYXNzTmFtZSwgdXBkYXRlLCBzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLnVwc2VydE9uZShtb25nb1doZXJlLCBtb25nb1VwZGF0ZSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBFeGVjdXRlcyBhIGZpbmQuIEFjY2VwdHM6IGNsYXNzTmFtZSwgcXVlcnkgaW4gUGFyc2UgZm9ybWF0LCBhbmQgeyBza2lwLCBsaW1pdCwgc29ydCB9LlxuICBmaW5kKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIHsgc2tpcCwgbGltaXQsIHNvcnQsIGtleXMsIHJlYWRQcmVmZXJlbmNlIH06IFF1ZXJ5T3B0aW9ucyk6IFByb21pc2U8YW55PiB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvV2hlcmUgPSB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHF1ZXJ5LCBzY2hlbWEpO1xuICAgIGNvbnN0IG1vbmdvU29ydCA9IF8ubWFwS2V5cyhzb3J0LCAodmFsdWUsIGZpZWxkTmFtZSkgPT4gdHJhbnNmb3JtS2V5KGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpKTtcbiAgICBjb25zdCBtb25nb0tleXMgPSBfLnJlZHVjZShrZXlzLCAobWVtbywga2V5KSA9PiB7XG4gICAgICBtZW1vW3RyYW5zZm9ybUtleShjbGFzc05hbWUsIGtleSwgc2NoZW1hKV0gPSAxO1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfSwge30pO1xuXG4gICAgcmVhZFByZWZlcmVuY2UgPSB0aGlzLl9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gdGhpcy5jcmVhdGVUZXh0SW5kZXhlc0lmTmVlZGVkKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSlcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmZpbmQobW9uZ29XaGVyZSwge1xuICAgICAgICBza2lwLFxuICAgICAgICBsaW1pdCxcbiAgICAgICAgc29ydDogbW9uZ29Tb3J0LFxuICAgICAgICBrZXlzOiBtb25nb0tleXMsXG4gICAgICAgIG1heFRpbWVNUzogdGhpcy5fbWF4VGltZU1TLFxuICAgICAgICByZWFkUHJlZmVyZW5jZSxcbiAgICAgIH0pKVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiBvYmplY3RzLm1hcChvYmplY3QgPT4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIHVuaXF1ZSBpbmRleC4gVW5pcXVlIGluZGV4ZXMgb24gbnVsbGFibGUgZmllbGRzIGFyZSBub3QgYWxsb3dlZC4gU2luY2Ugd2UgZG9uJ3RcbiAgLy8gY3VycmVudGx5IGtub3cgd2hpY2ggZmllbGRzIGFyZSBudWxsYWJsZSBhbmQgd2hpY2ggYXJlbid0LCB3ZSBpZ25vcmUgdGhhdCBjcml0ZXJpYS5cbiAgLy8gQXMgc3VjaCwgd2Ugc2hvdWxkbid0IGV4cG9zZSB0aGlzIGZ1bmN0aW9uIHRvIHVzZXJzIG9mIHBhcnNlIHVudGlsIHdlIGhhdmUgYW4gb3V0LW9mLWJhbmRcbiAgLy8gV2F5IG9mIGRldGVybWluaW5nIGlmIGEgZmllbGQgaXMgbnVsbGFibGUuIFVuZGVmaW5lZCBkb2Vzbid0IGNvdW50IGFnYWluc3QgdW5pcXVlbmVzcyxcbiAgLy8gd2hpY2ggaXMgd2h5IHdlIHVzZSBzcGFyc2UgaW5kZXhlcy5cbiAgZW5zdXJlVW5pcXVlbmVzcyhjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBmaWVsZE5hbWVzOiBzdHJpbmdbXSkge1xuICAgIHNjaGVtYSA9IGNvbnZlcnRQYXJzZVNjaGVtYVRvTW9uZ29TY2hlbWEoc2NoZW1hKTtcbiAgICBjb25zdCBpbmRleENyZWF0aW9uUmVxdWVzdCA9IHt9O1xuICAgIGNvbnN0IG1vbmdvRmllbGROYW1lcyA9IGZpZWxkTmFtZXMubWFwKGZpZWxkTmFtZSA9PiB0cmFuc2Zvcm1LZXkoY2xhc3NOYW1lLCBmaWVsZE5hbWUsIHNjaGVtYSkpO1xuICAgIG1vbmdvRmllbGROYW1lcy5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpbmRleENyZWF0aW9uUmVxdWVzdFtmaWVsZE5hbWVdID0gMTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fZW5zdXJlU3BhcnNlVW5pcXVlSW5kZXhJbkJhY2tncm91bmQoaW5kZXhDcmVhdGlvblJlcXVlc3QpKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDExMDAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgJ1RyaWVkIHRvIGVuc3VyZSBmaWVsZCB1bmlxdWVuZXNzIGZvciBhIGNsYXNzIHRoYXQgYWxyZWFkeSBoYXMgZHVwbGljYXRlcy4nKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICAvLyBVc2VkIGluIHRlc3RzXG4gIF9yYXdGaW5kKGNsYXNzTmFtZTogc3RyaW5nLCBxdWVyeTogUXVlcnlUeXBlKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLmZpbmQocXVlcnksIHtcbiAgICAgIG1heFRpbWVNUzogdGhpcy5fbWF4VGltZU1TLFxuICAgIH0pKS5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIC8vIEV4ZWN1dGVzIGEgY291bnQuXG4gIGNvdW50KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uY291bnQodHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCBxdWVyeSwgc2NoZW1hKSwge1xuICAgICAgICBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyxcbiAgICAgICAgcmVhZFByZWZlcmVuY2UsXG4gICAgICB9KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRpc3RpbmN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIGZpZWxkTmFtZTogc3RyaW5nKSB7XG4gICAgc2NoZW1hID0gY29udmVydFBhcnNlU2NoZW1hVG9Nb25nb1NjaGVtYShzY2hlbWEpO1xuICAgIGNvbnN0IGlzUG9pbnRlckZpZWxkID0gc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcic7XG4gICAgaWYgKGlzUG9pbnRlckZpZWxkKSB7XG4gICAgICBmaWVsZE5hbWUgPSBgX3BfJHtmaWVsZE5hbWV9YFxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5kaXN0aW5jdChmaWVsZE5hbWUsIHRyYW5zZm9ybVdoZXJlKGNsYXNzTmFtZSwgcXVlcnksIHNjaGVtYSkpKVxuICAgICAgLnRoZW4ob2JqZWN0cyA9PiB7XG4gICAgICAgIG9iamVjdHMgPSBvYmplY3RzLmZpbHRlcigob2JqKSA9PiBvYmogIT0gbnVsbCk7XG4gICAgICAgIHJldHVybiBvYmplY3RzLm1hcChvYmplY3QgPT4ge1xuICAgICAgICAgIGlmIChpc1BvaW50ZXJGaWVsZCkge1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSBmaWVsZE5hbWUuc3Vic3RyaW5nKDMpO1xuICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcoc2NoZW1hLCBmaWVsZCwgb2JqZWN0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWUsIG9iamVjdCwgc2NoZW1hKTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgYWdncmVnYXRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSwgcmVhZFByZWZlcmVuY2U6ID9zdHJpbmcpIHtcbiAgICBsZXQgaXNQb2ludGVyRmllbGQgPSBmYWxzZTtcbiAgICBwaXBlbGluZSA9IHBpcGVsaW5lLm1hcCgoc3RhZ2UpID0+IHtcbiAgICAgIGlmIChzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgc3RhZ2UuJGdyb3VwID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVHcm91cEFyZ3Moc2NoZW1hLCBzdGFnZS4kZ3JvdXApO1xuICAgICAgICBpZiAoc3RhZ2UuJGdyb3VwLl9pZCAmJiAodHlwZW9mIHN0YWdlLiRncm91cC5faWQgPT09ICdzdHJpbmcnKSAmJiBzdGFnZS4kZ3JvdXAuX2lkLmluZGV4T2YoJyRfcF8nKSA+PSAwKSB7XG4gICAgICAgICAgaXNQb2ludGVyRmllbGQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgIHN0YWdlLiRtYXRjaCA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHN0YWdlLiRtYXRjaCk7XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJHByb2plY3QpIHtcbiAgICAgICAgc3RhZ2UuJHByb2plY3QgPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZVByb2plY3RBcmdzKHNjaGVtYSwgc3RhZ2UuJHByb2plY3QpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0YWdlO1xuICAgIH0pO1xuICAgIHJlYWRQcmVmZXJlbmNlID0gdGhpcy5fcGFyc2VSZWFkUHJlZmVyZW5jZShyZWFkUHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uYWdncmVnYXRlKHBpcGVsaW5lLCB7IHJlYWRQcmVmZXJlbmNlLCBtYXhUaW1lTVM6IHRoaXMuX21heFRpbWVNUyB9KSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlID09PSAxNjAwNikge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgcmVzdWx0cy5mb3JFYWNoKHJlc3VsdCA9PiB7XG4gICAgICAgICAgaWYgKHJlc3VsdC5oYXNPd25Qcm9wZXJ0eSgnX2lkJykpIHtcbiAgICAgICAgICAgIGlmIChpc1BvaW50ZXJGaWVsZCAmJiByZXN1bHQuX2lkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdC5faWQgPSByZXN1bHQuX2lkLnNwbGl0KCckJylbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0Ll9pZCA9PSBudWxsIHx8IF8uaXNFbXB0eShyZXN1bHQuX2lkKSkge1xuICAgICAgICAgICAgICByZXN1bHQuX2lkID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdC5vYmplY3RJZCA9IHJlc3VsdC5faWQ7XG4gICAgICAgICAgICBkZWxldGUgcmVzdWx0Ll9pZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgIH0pXG4gICAgICAudGhlbihvYmplY3RzID0+IG9iamVjdHMubWFwKG9iamVjdCA9PiBtb25nb09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSkpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIHJlY3Vyc2l2ZWx5IHRyYXZlcnNlIHRoZSBwaXBlbGluZSBhbmQgY29udmVydCBhbnkgUG9pbnRlciBvciBEYXRlIGNvbHVtbnMuXG4gIC8vIElmIHdlIGRldGVjdCBhIHBvaW50ZXIgY29sdW1uIHdlIHdpbGwgcmVuYW1lIHRoZSBjb2x1bW4gYmVpbmcgcXVlcmllZCBmb3IgdG8gbWF0Y2ggdGhlIGNvbHVtblxuICAvLyBpbiB0aGUgZGF0YWJhc2UuIFdlIGFsc28gbW9kaWZ5IHRoZSB2YWx1ZSB0byB3aGF0IHdlIGV4cGVjdCB0aGUgdmFsdWUgdG8gYmUgaW4gdGhlIGRhdGFiYXNlXG4gIC8vIGFzIHdlbGwuXG4gIC8vIEZvciBkYXRlcywgdGhlIGRyaXZlciBleHBlY3RzIGEgRGF0ZSBvYmplY3QsIGJ1dCB3ZSBoYXZlIGEgc3RyaW5nIGNvbWluZyBpbi4gU28gd2UnbGwgY29udmVydFxuICAvLyB0aGUgc3RyaW5nIHRvIGEgRGF0ZSBzbyB0aGUgZHJpdmVyIGNhbiBwZXJmb3JtIHRoZSBuZWNlc3NhcnkgY29tcGFyaXNvbi5cbiAgLy9cbiAgLy8gVGhlIGdvYWwgb2YgdGhpcyBtZXRob2QgaXMgdG8gbG9vayBmb3IgdGhlIFwibGVhdmVzXCIgb2YgdGhlIHBpcGVsaW5lIGFuZCBkZXRlcm1pbmUgaWYgaXQgbmVlZHNcbiAgLy8gdG8gYmUgY29udmVydGVkLiBUaGUgcGlwZWxpbmUgY2FuIGhhdmUgYSBmZXcgZGlmZmVyZW50IGZvcm1zLiBGb3IgbW9yZSBkZXRhaWxzLCBzZWU6XG4gIC8vICAgICBodHRwczovL2RvY3MubW9uZ29kYi5jb20vbWFudWFsL3JlZmVyZW5jZS9vcGVyYXRvci9hZ2dyZWdhdGlvbi9cbiAgLy9cbiAgLy8gSWYgdGhlIHBpcGVsaW5lIGlzIGFuIGFycmF5LCBpdCBtZWFucyB3ZSBhcmUgcHJvYmFibHkgcGFyc2luZyBhbiAnJGFuZCcgb3IgJyRvcicgb3BlcmF0b3IuIEluXG4gIC8vIHRoYXQgY2FzZSB3ZSBuZWVkIHRvIGxvb3AgdGhyb3VnaCBhbGwgb2YgaXQncyBjaGlsZHJlbiB0byBmaW5kIHRoZSBjb2x1bW5zIGJlaW5nIG9wZXJhdGVkIG9uLlxuICAvLyBJZiB0aGUgcGlwZWxpbmUgaXMgYW4gb2JqZWN0LCB0aGVuIHdlJ2xsIGxvb3AgdGhyb3VnaCB0aGUga2V5cyBjaGVja2luZyB0byBzZWUgaWYgdGhlIGtleSBuYW1lXG4gIC8vIG1hdGNoZXMgb25lIG9mIHRoZSBzY2hlbWEgY29sdW1ucy4gSWYgaXQgZG9lcyBtYXRjaCBhIGNvbHVtbiBhbmQgdGhlIGNvbHVtbiBpcyBhIFBvaW50ZXIgb3JcbiAgLy8gYSBEYXRlLCB0aGVuIHdlJ2xsIGNvbnZlcnQgdGhlIHZhbHVlIGFzIGRlc2NyaWJlZCBhYm92ZS5cbiAgLy9cbiAgLy8gQXMgbXVjaCBhcyBJIGhhdGUgcmVjdXJzaW9uLi4udGhpcyBzZWVtZWQgbGlrZSBhIGdvb2QgZml0IGZvciBpdC4gV2UncmUgZXNzZW50aWFsbHkgdHJhdmVyc2luZ1xuICAvLyBkb3duIGEgdHJlZSB0byBmaW5kIGEgXCJsZWFmIG5vZGVcIiBhbmQgY2hlY2tpbmcgdG8gc2VlIGlmIGl0IG5lZWRzIHRvIGJlIGNvbnZlcnRlZC5cbiAgX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWE6IGFueSwgcGlwZWxpbmU6IGFueSk6IGFueSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGlwZWxpbmUpKSB7XG4gICAgICByZXR1cm4gcGlwZWxpbmUubWFwKCh2YWx1ZSkgPT4gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYSwgdmFsdWUpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwaXBlbGluZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGNvbnN0IHJldHVyblZhbHVlID0ge307XG4gICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIHBpcGVsaW5lKSB7XG4gICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHBpcGVsaW5lW2ZpZWxkXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIFBhc3Mgb2JqZWN0cyBkb3duIHRvIE1vbmdvREIuLi50aGlzIGlzIG1vcmUgdGhhbiBsaWtlbHkgYW4gJGV4aXN0cyBvcGVyYXRvci5cbiAgICAgICAgICAgIHJldHVyblZhbHVlW2BfcF8ke2ZpZWxkfWBdID0gcGlwZWxpbmVbZmllbGRdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IGAke3NjaGVtYS5maWVsZHNbZmllbGRdLnRhcmdldENsYXNzfSQke3BpcGVsaW5lW2ZpZWxkXX1gO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnRGF0ZScpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9jb252ZXJ0VG9EYXRlKHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fcGFyc2VBZ2dyZWdhdGVBcmdzKHNjaGVtYSwgcGlwZWxpbmVbZmllbGRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWVsZCA9PT0gJ29iamVjdElkJykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfaWQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICAgIHJldHVyblZhbHVlWydfY3JlYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVbJ191cGRhdGVkX2F0J10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gcGlwZWxpbmU7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIHNsaWdodGx5IGRpZmZlcmVudCB0aGFuIHRoZSBvbmUgYWJvdmUuIFJhdGhlciB0aGFuIHRyeWluZyB0byBjb21iaW5lIHRoZXNlXG4gIC8vIHR3byBmdW5jdGlvbnMgYW5kIG1ha2luZyB0aGUgY29kZSBldmVuIGhhcmRlciB0byB1bmRlcnN0YW5kLCBJIGRlY2lkZWQgdG8gc3BsaXQgaXQgdXAuIFRoZVxuICAvLyBkaWZmZXJlbmNlIHdpdGggdGhpcyBmdW5jdGlvbiBpcyB3ZSBhcmUgbm90IHRyYW5zZm9ybWluZyB0aGUgdmFsdWVzLCBvbmx5IHRoZSBrZXlzIG9mIHRoZVxuICAvLyBwaXBlbGluZS5cbiAgX3BhcnNlQWdncmVnYXRlUHJvamVjdEFyZ3Moc2NoZW1hOiBhbnksIHBpcGVsaW5lOiBhbnkpOiBhbnkge1xuICAgIGNvbnN0IHJldHVyblZhbHVlID0ge307XG4gICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGRdICYmIHNjaGVtYS5maWVsZHNbZmllbGRdLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm5WYWx1ZVtgX3BfJHtmaWVsZH1gXSA9IHBpcGVsaW5lW2ZpZWxkXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVyblZhbHVlW2ZpZWxkXSA9IHRoaXMuX3BhcnNlQWdncmVnYXRlQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChmaWVsZCA9PT0gJ29iamVjdElkJykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX2lkJ10gPSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICAgIGRlbGV0ZSByZXR1cm5WYWx1ZVtmaWVsZF07XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICByZXR1cm5WYWx1ZVsnX2NyZWF0ZWRfYXQnXSA9IHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgICAgZGVsZXRlIHJldHVyblZhbHVlW2ZpZWxkXTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgIHJldHVyblZhbHVlWydfdXBkYXRlZF9hdCddID0gcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgICBkZWxldGUgcmV0dXJuVmFsdWVbZmllbGRdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIHNsaWdodGx5IGRpZmZlcmVudCB0aGFuIHRoZSB0d28gYWJvdmUuIE1vbmdvREIgJGdyb3VwIGFnZ3JlZ2F0ZSBsb29rcyBsaWtlOlxuICAvLyAgICAgeyAkZ3JvdXA6IHsgX2lkOiA8ZXhwcmVzc2lvbj4sIDxmaWVsZDE+OiB7IDxhY2N1bXVsYXRvcjE+IDogPGV4cHJlc3Npb24xPiB9LCAuLi4gfSB9XG4gIC8vIFRoZSA8ZXhwcmVzc2lvbj4gY291bGQgYmUgYSBjb2x1bW4gbmFtZSwgcHJlZml4ZWQgd2l0aCB0aGUgJyQnIGNoYXJhY3Rlci4gV2UnbGwgbG9vayBmb3JcbiAgLy8gdGhlc2UgPGV4cHJlc3Npb24+IGFuZCBjaGVjayB0byBzZWUgaWYgaXQgaXMgYSAnUG9pbnRlcicgb3IgaWYgaXQncyBvbmUgb2YgY3JlYXRlZEF0LFxuICAvLyB1cGRhdGVkQXQgb3Igb2JqZWN0SWQgYW5kIGNoYW5nZSBpdCBhY2NvcmRpbmdseS5cbiAgX3BhcnNlQWdncmVnYXRlR3JvdXBBcmdzKHNjaGVtYTogYW55LCBwaXBlbGluZTogYW55KTogYW55IHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShwaXBlbGluZSkpIHtcbiAgICAgIHJldHVybiBwaXBlbGluZS5tYXAoKHZhbHVlKSA9PiB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWEsIHZhbHVlKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBwaXBlbGluZSkge1xuICAgICAgICByZXR1cm5WYWx1ZVtmaWVsZF0gPSB0aGlzLl9wYXJzZUFnZ3JlZ2F0ZUdyb3VwQXJncyhzY2hlbWEsIHBpcGVsaW5lW2ZpZWxkXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcGlwZWxpbmUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCBmaWVsZCA9IHBpcGVsaW5lLnN1YnN0cmluZygxKTtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuIGAkX3BfJHtmaWVsZH1gO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZCA9PSAnY3JlYXRlZEF0Jykge1xuICAgICAgICByZXR1cm4gJyRfY3JlYXRlZF9hdCc7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkID09ICd1cGRhdGVkQXQnKSB7XG4gICAgICAgIHJldHVybiAnJF91cGRhdGVkX2F0JztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBpcGVsaW5lO1xuICB9XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGF0dGVtcHQgdG8gY29udmVydCB0aGUgcHJvdmlkZWQgdmFsdWUgdG8gYSBEYXRlIG9iamVjdC4gU2luY2UgdGhpcyBpcyBwYXJ0XG4gIC8vIG9mIGFuIGFnZ3JlZ2F0aW9uIHBpcGVsaW5lLCB0aGUgdmFsdWUgY2FuIGVpdGhlciBiZSBhIHN0cmluZyBvciBpdCBjYW4gYmUgYW5vdGhlciBvYmplY3Qgd2l0aFxuICAvLyBhbiBvcGVyYXRvciBpbiBpdCAobGlrZSAkZ3QsICRsdCwgZXRjKS4gQmVjYXVzZSBvZiB0aGlzIEkgZmVsdCBpdCB3YXMgZWFzaWVyIHRvIG1ha2UgdGhpcyBhXG4gIC8vIHJlY3Vyc2l2ZSBtZXRob2QgdG8gdHJhdmVyc2UgZG93biB0byB0aGUgXCJsZWFmIG5vZGVcIiB3aGljaCBpcyBnb2luZyB0byBiZSB0aGUgc3RyaW5nLlxuICBfY29udmVydFRvRGF0ZSh2YWx1ZTogYW55KTogYW55IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9XG4gICAgZm9yIChjb25zdCBmaWVsZCBpbiB2YWx1ZSkge1xuICAgICAgcmV0dXJuVmFsdWVbZmllbGRdID0gdGhpcy5fY29udmVydFRvRGF0ZSh2YWx1ZVtmaWVsZF0pXG4gICAgfVxuICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgfVxuXG4gIF9wYXJzZVJlYWRQcmVmZXJlbmNlKHJlYWRQcmVmZXJlbmNlOiA/c3RyaW5nKTogP3N0cmluZyB7XG4gICAgc3dpdGNoIChyZWFkUHJlZmVyZW5jZSkge1xuICAgIGNhc2UgJ1BSSU1BUlknOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5QUklNQVJZO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnUFJJTUFSWV9QUkVGRVJSRUQnOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5QUklNQVJZX1BSRUZFUlJFRDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1NFQ09OREFSWSc6XG4gICAgICByZWFkUHJlZmVyZW5jZSA9IFJlYWRQcmVmZXJlbmNlLlNFQ09OREFSWTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1NFQ09OREFSWV9QUkVGRVJSRUQnOlxuICAgICAgcmVhZFByZWZlcmVuY2UgPSBSZWFkUHJlZmVyZW5jZS5TRUNPTkRBUllfUFJFRkVSUkVEO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnTkVBUkVTVCc6XG4gICAgICByZWFkUHJlZmVyZW5jZSA9IFJlYWRQcmVmZXJlbmNlLk5FQVJFU1Q7XG4gICAgICBicmVhaztcbiAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSwgJ05vdCBzdXBwb3J0ZWQgcmVhZCBwcmVmZXJlbmNlLicpO1xuICAgIH1cbiAgICByZXR1cm4gcmVhZFByZWZlcmVuY2U7XG4gIH1cblxuICBwZXJmb3JtSW5pdGlhbGl6YXRpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXgoY2xhc3NOYW1lOiBzdHJpbmcsIGluZGV4OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmNyZWF0ZUluZGV4KGluZGV4LCB7YmFja2dyb3VuZDogdHJ1ZX0pKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgY3JlYXRlSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZywgaW5kZXhlczogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5jcmVhdGVJbmRleGVzKGluZGV4ZXMsIHtiYWNrZ3JvdW5kOiB0cnVlfSkpXG4gICAgICAuY2F0Y2goZXJyID0+IHRoaXMuaGFuZGxlRXJyb3IoZXJyKSk7XG4gIH1cblxuICBjcmVhdGVJbmRleGVzSWZOZWVkZWQoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpIHtcbiAgICBpZiAodHlwZSAmJiB0eXBlLnR5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgY29uc3QgaW5kZXggPSB7XG4gICAgICAgIFtmaWVsZE5hbWVdOiAnMmRzcGhlcmUnXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlSW5kZXgoY2xhc3NOYW1lLCBpbmRleCk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGNyZWF0ZVRleHRJbmRleGVzSWZOZWVkZWQoY2xhc3NOYW1lOiBzdHJpbmcsIHF1ZXJ5OiBRdWVyeVR5cGUsIHNjaGVtYTogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZm9yKGNvbnN0IGZpZWxkTmFtZSBpbiBxdWVyeSkge1xuICAgICAgaWYgKCFxdWVyeVtmaWVsZE5hbWVdIHx8ICFxdWVyeVtmaWVsZE5hbWVdLiR0ZXh0KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZXhpc3RpbmdJbmRleGVzID0gc2NoZW1hLmluZGV4ZXM7XG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiBleGlzdGluZ0luZGV4ZXMpIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBleGlzdGluZ0luZGV4ZXNba2V5XTtcbiAgICAgICAgaWYgKGluZGV4Lmhhc093blByb3BlcnR5KGZpZWxkTmFtZSkpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IGluZGV4TmFtZSA9IGAke2ZpZWxkTmFtZX1fdGV4dGA7XG4gICAgICBjb25zdCB0ZXh0SW5kZXggPSB7XG4gICAgICAgIFtpbmRleE5hbWVdOiB7IFtmaWVsZE5hbWVdOiAndGV4dCcgfVxuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KGNsYXNzTmFtZSwgdGV4dEluZGV4LCBleGlzdGluZ0luZGV4ZXMsIHNjaGVtYS5maWVsZHMpXG4gICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gODUpIHsgLy8gSW5kZXggZXhpc3Qgd2l0aCBkaWZmZXJlbnQgb3B0aW9uc1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V0SW5kZXhlc0Zyb21Nb25nbyhjbGFzc05hbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIGdldEluZGV4ZXMoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRhcHRpdmVDb2xsZWN0aW9uKGNsYXNzTmFtZSlcbiAgICAgIC50aGVuKGNvbGxlY3Rpb24gPT4gY29sbGVjdGlvbi5fbW9uZ29Db2xsZWN0aW9uLmluZGV4ZXMoKSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRyb3BJbmRleChjbGFzc05hbWU6IHN0cmluZywgaW5kZXg6IGFueSkge1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGl2ZUNvbGxlY3Rpb24oY2xhc3NOYW1lKVxuICAgICAgLnRoZW4oY29sbGVjdGlvbiA9PiBjb2xsZWN0aW9uLl9tb25nb0NvbGxlY3Rpb24uZHJvcEluZGV4KGluZGV4KSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxuXG4gIGRyb3BBbGxJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkYXB0aXZlQ29sbGVjdGlvbihjbGFzc05hbWUpXG4gICAgICAudGhlbihjb2xsZWN0aW9uID0+IGNvbGxlY3Rpb24uX21vbmdvQ29sbGVjdGlvbi5kcm9wSW5kZXhlcygpKVxuICAgICAgLmNhdGNoKGVyciA9PiB0aGlzLmhhbmRsZUVycm9yKGVycikpO1xuICB9XG5cbiAgdXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMoKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRBbGxDbGFzc2VzKClcbiAgICAgIC50aGVuKChjbGFzc2VzKSA9PiB7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gY2xhc3Nlcy5tYXAoKHNjaGVtYSkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLnNldEluZGV4ZXNGcm9tTW9uZ28oc2NoZW1hLmNsYXNzTmFtZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnIpKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBNb25nb1N0b3JhZ2VBZGFwdGVyO1xuIl19 \ No newline at end of file From cab9edf94d7a0312048ef18f6ce8251aef5eed26 Mon Sep 17 00:00:00 2001 From: Ricardo Paiva Date: Wed, 31 Oct 2018 13:46:13 -0300 Subject: [PATCH 15/73] Merge from 3.1.0 --- .babelrc | 6 +- .eslintrc.json | 2 +- .github/ISSUE_TEMPLATE.md | 12 +- .../ISSUE_TEMPLATE/---parse-server-3-0-0.md | 54 + .../ISSUE_TEMPLATE/---push-notifications.md | 44 + .github/ISSUE_TEMPLATE/---report-an-issue.md | 6 +- .github/stale.yml | 19 + .gitignore | 4 + .prettierrc | 3 + .travis.yml | 11 +- 3.0.0.md | 226 + CHANGELOG.md | 65 +- README.md | 17 +- bin/dev | 41 +- jsdoc-conf.json | 23 + lib/AccountLockout.js | 78 +- lib/Adapters/AdapterLoader.js | 38 +- lib/Adapters/Analytics/AnalyticsAdapter.js | 34 +- lib/Adapters/Auth/AuthAdapter.js | 12 +- lib/Adapters/Auth/OAuth1Client.js | 114 +- lib/Adapters/Auth/facebook.js | 42 +- lib/Adapters/Auth/facebookaccountkit.js | 44 +- lib/Adapters/Auth/github.js | 49 +- lib/Adapters/Auth/google.js | 46 +- lib/Adapters/Auth/httpsRequest.js | 47 + lib/Adapters/Auth/index.js | 75 +- lib/Adapters/Auth/instagram.js | 35 +- lib/Adapters/Auth/janraincapture.js | 44 +- lib/Adapters/Auth/janrainengage.js | 56 +- lib/Adapters/Auth/linkedin.js | 45 +- lib/Adapters/Auth/meetup.js | 47 +- lib/Adapters/Auth/qq.js | 60 +- lib/Adapters/Auth/spotify.js | 52 +- lib/Adapters/Auth/twitter.js | 25 +- lib/Adapters/Auth/vkontakte.js | 48 +- lib/Adapters/Auth/wechat.js | 39 +- lib/Adapters/Auth/weibo.js | 68 +- lib/Adapters/Cache/CacheAdapter.js | 35 +- lib/Adapters/Cache/InMemoryCache.js | 17 +- lib/Adapters/Cache/InMemoryCacheAdapter.js | 15 +- lib/Adapters/Cache/LRUCache.js | 23 +- lib/Adapters/Cache/NullCacheAdapter.js | 9 +- lib/Adapters/Cache/RedisCacheAdapter.js | 28 +- lib/Adapters/Email/MailAdapter.js | 24 +- lib/Adapters/Files/FilesAdapter.js | 66 +- lib/Adapters/Files/GridFSBucketAdapter.js | 101 + lib/Adapters/Files/GridStoreAdapter.js | 47 +- lib/Adapters/Logger/LoggerAdapter.js | 38 +- lib/Adapters/Logger/WinstonLogger.js | 97 +- lib/Adapters/Logger/WinstonLoggerAdapter.js | 27 +- lib/Adapters/MessageQueue/EventEmitterMQ.js | 26 +- lib/Adapters/PubSub/EventEmitterPubSub.js | 21 +- lib/Adapters/PubSub/PubSubAdapter.js | 39 + lib/Adapters/PubSub/RedisPubSub.js | 68 +- lib/Adapters/Push/PushAdapter.js | 23 +- lib/Adapters/Storage/Mongo/MongoCollection.js | 115 +- .../Storage/Mongo/MongoSchemaCollection.js | 192 +- .../Storage/Mongo/MongoStorageAdapter.js | 352 +- lib/Adapters/Storage/Mongo/MongoTransform.js | 664 +- .../Storage/Postgres/PostgresClient.js | 11 +- .../Storage/Postgres/PostgresConfigParser.js | 10 +- .../Postgres/PostgresStorageAdapter.js | 871 +- lib/Adapters/Storage/Postgres/sql/index.js | 13 +- lib/Adapters/Storage/StorageAdapter.js | 2 +- lib/Auth.js | 351 +- lib/ClientSDK.js | 12 +- lib/Config.js | 81 +- lib/Controllers/AdaptableController.js | 31 +- lib/Controllers/AnalyticsController.js | 34 +- lib/Controllers/CacheController.js | 27 +- lib/Controllers/DatabaseController.js | 514 +- lib/Controllers/FilesController.js | 51 +- lib/Controllers/HooksController.js | 140 +- lib/Controllers/LiveQueryController.js | 36 +- lib/Controllers/LoggerController.js | 78 +- lib/Controllers/PushController.js | 134 +- lib/Controllers/SchemaCache.js | 29 +- lib/Controllers/SchemaController.js | 955 +- lib/Controllers/UserController.js | 171 +- lib/Controllers/index.js | 135 +- lib/Controllers/types.js | 2 +- lib/LiveQuery/Client.js | 36 +- lib/LiveQuery/Id.js | 9 +- lib/LiveQuery/ParseCloudCodePublisher.js | 33 +- lib/LiveQuery/ParseLiveQueryServer.js | 583 +- lib/LiveQuery/ParsePubSub.js | 19 +- lib/LiveQuery/ParseWebSocketServer.js | 27 +- lib/LiveQuery/QueryTools.js | 117 +- lib/LiveQuery/RequestSchema.js | 190 +- lib/LiveQuery/SessionTokenCache.js | 55 +- lib/LiveQuery/Subscription.js | 25 +- lib/LiveQuery/equalObjects.js | 17 +- lib/Options/Definitions.js | 763 +- lib/Options/docs.js | 94 + lib/Options/index.js | 16 +- lib/Options/parsers.js | 18 +- lib/ParseMessageQueue.js | 17 +- lib/ParseServer.js | 249 +- lib/ParseServerRESTController.js | 55 +- lib/PromiseRouter.js | 95 +- lib/Push/PushQueue.js | 50 +- lib/Push/PushWorker.js | 107 +- lib/Push/utils.js | 52 +- lib/RestQuery.js | 366 +- lib/RestWrite.js | 627 +- lib/Routers/AggregateRouter.js | 132 +- lib/Routers/AnalyticsRouter.js | 18 +- lib/Routers/AudiencesRouter.js | 39 +- lib/Routers/ClassesRouter.js | 88 +- lib/Routers/CloudCodeRouter.js | 55 +- lib/Routers/ExportRouter.js | 122 +- lib/Routers/FeaturesRouter.js | 29 +- lib/Routers/FilesRouter.js | 140 +- lib/Routers/FunctionsRouter.js | 189 +- lib/Routers/GlobalConfigRouter.js | 66 +- lib/Routers/HooksRouter.js | 74 +- lib/Routers/IAPValidationRouter.js | 114 +- lib/Routers/ImportRouter.js | 90 +- lib/Routers/InstallationsRouter.js | 33 +- lib/Routers/LogsRouter.js | 33 +- lib/Routers/PublicAPIRouter.js | 120 +- lib/Routers/PurgeRouter.js | 43 +- lib/Routers/PushRouter.js | 37 +- lib/Routers/RolesRouter.js | 16 +- lib/Routers/SchemasRouter.js | 63 +- lib/Routers/SessionsRouter.js | 58 +- lib/Routers/UsersRouter.js | 241 +- lib/StatusHandler.js | 137 +- lib/TestUtils.js | 14 +- lib/batch.js | 59 +- lib/cache.js | 16 +- .../definitions/parse-live-query-server.js | 10 +- lib/cli/definitions/parse-server.js | 10 +- lib/cli/parse-live-query-server.js | 19 +- lib/cli/parse-server.js | 68 +- lib/cli/utils/commander.js | 68 +- lib/cli/utils/runner.js | 61 +- lib/cloud-code/HTTPResponse.js | 28 +- lib/cloud-code/Parse.Cloud.js | 240 +- lib/cloud-code/httpRequest.js | 210 +- lib/cryptoUtils.js | 23 +- lib/defaults.js | 36 +- lib/deprecated.js | 3 +- lib/index.js | 117 +- lib/logger.js | 26 +- lib/middlewares.js | 155 +- lib/password.js | 17 +- lib/request.js | 4 + lib/requiredParameter.js | 7 +- lib/rest.js | 87 +- lib/triggers.js | 290 +- lib/vendor/README.md | 6 +- lib/vendor/mongodbUrl.js | 439 +- package-lock.json | 7693 ++++++++--------- package.json | 74 +- release_docs.sh | 28 + resources/buildConfigDefinitions.js | 62 +- spec/.babelrc | 0 spec/.eslintrc.json | 3 +- spec/AccountLockoutPolicy.spec.js | 197 +- spec/AdaptableController.spec.js | 47 +- spec/AdapterLoader.spec.js | 90 +- spec/AggregateRouter.spec.js | 82 + spec/Analytics.spec.js | 102 +- spec/AudienceRouter.spec.js | 382 +- spec/Auth.spec.js | 176 +- spec/AuthenticationAdapters.spec.js | 562 +- spec/CLI.spec.js | 144 +- spec/CacheController.spec.js | 17 +- spec/Client.spec.js | 82 +- spec/ClientSDK.spec.js | 44 +- spec/CloudCode.spec.js | 1939 +++-- spec/CloudCodeLogger.spec.js | 281 +- spec/DatabaseController.spec.js | 58 +- spec/EmailVerificationToken.spec.js | 549 +- spec/EnableExpressErrorHandler.spec.js | 71 +- spec/EnableSingleSchemaCache.spec.js | 67 +- spec/EventEmitterPubSub.spec.js | 3 +- spec/FilesController.spec.js | 120 +- spec/GridFSBucketStorageAdapter.spec.js | 67 + spec/GridStoreAdapter.js | 87 - spec/GridStoreAdapter.spec.js | 99 + spec/HTTPRequest.spec.js | 267 +- spec/InMemoryCache.spec.js | 17 +- spec/InMemoryCacheAdapter.spec.js | 36 +- spec/InstallationsRouter.spec.js | 192 +- spec/JobSchedule.spec.js | 278 +- spec/Logger.spec.js | 40 +- spec/LoggerController.spec.js | 82 +- spec/LogsRouter.spec.js | 163 +- spec/Middlewares.spec.js | 118 +- spec/MockAdapter.js | 2 +- spec/MockEmailAdapter.js | 4 +- spec/MockEmailAdapterWithOptions.js | 10 +- spec/MockPushAdapter.js | 2 +- spec/MongoSchemaCollectionAdapter.spec.js | 79 +- spec/MongoStorageAdapter.spec.js | 117 +- spec/MongoTransform.spec.js | 374 +- spec/NullCacheAdapter.spec.js | 21 +- spec/OAuth1.spec.js | 151 +- spec/Parse.Push.spec.js | 586 +- spec/ParseACL.spec.js | 1901 ++-- spec/ParseAPI.spec.js | 1803 ++-- spec/ParseCloudCodePublisher.spec.js | 31 +- spec/ParseFile.spec.js | 917 +- spec/ParseGeoPoint.spec.js | 1184 ++- spec/ParseGlobalConfig.spec.js | 242 +- spec/ParseHooks.spec.js | 1044 ++- spec/ParseInstallation.spec.js | 1132 ++- spec/ParseLiveQueryServer.spec.js | 1270 ++- spec/ParseObject.spec.js | 3083 +++---- spec/ParsePolygon.spec.js | 589 +- spec/ParsePubSub.spec.js | 92 +- spec/ParseQuery.Aggregate.spec.js | 1345 +-- spec/ParseQuery.FullTextSearch.spec.js | 977 ++- spec/ParseQuery.spec.js | 5605 ++++++------ spec/ParseRelation.spec.js | 1225 +-- spec/ParseRole.spec.js | 934 +- spec/ParseServer.spec.js | 39 +- spec/ParseServerRESTController.spec.js | 292 +- spec/ParseSession.spec.js | 196 +- spec/ParseUser.spec.js | 5469 ++++++------ spec/ParseWebSocket.spec.js | 12 +- spec/ParseWebSocketServer.spec.js | 16 +- spec/PasswordPolicy.spec.js | 1970 +++-- spec/PointerPermissions.spec.js | 1229 ++- spec/PostgresConfigParser.spec.js | 29 +- spec/PostgresInitOptions.spec.js | 85 +- spec/PostgresStorageAdapter.spec.js | 43 +- spec/PromiseRouter.spec.js | 50 +- spec/PublicAPI.spec.js | 180 +- spec/PurchaseValidation.spec.js | 314 +- spec/PushController.spec.js | 1898 ++-- spec/PushQueue.spec.js | 42 +- spec/PushRouter.spec.js | 77 +- spec/PushWorker.spec.js | 534 +- spec/QueryTools.spec.js | 149 +- spec/ReadPreferenceOption.spec.js | 531 +- spec/RedisCacheAdapter.spec.js | 34 +- spec/RedisPubSub.spec.js | 13 +- spec/RestQuery.spec.js | 470 +- spec/RevocableSessionsUpgrade.spec.js | 164 +- spec/Schema.spec.js | 1849 ++-- spec/SchemaCache.spec.js | 67 +- spec/SessionTokenCache.spec.js | 39 +- spec/Subscription.spec.js | 69 +- spec/TwitterAuth.spec.js | 113 +- spec/Uniqueness.spec.js | 74 +- spec/UserController.spec.js | 87 +- spec/UserPII.spec.js | 524 +- spec/ValidationAndPasswordsReset.spec.js | 1088 +-- spec/VerifyUserPassword.spec.js | 857 +- spec/WinstonLoggerAdapter.spec.js | 124 +- spec/batch.spec.js | 28 +- spec/cloud/cloudCodeAbsoluteFile.js | 4 +- spec/cloud/cloudCodeRelativeFile.js | 4 +- spec/configs/CLIConfig.json | 0 spec/configs/CLIConfigApps.json | 13 +- spec/configs/CLIConfigFail.json | 0 spec/configs/CLIConfigFailTooManyApps.json | 24 +- spec/configs/CLIConfigUnknownArg.json | 0 spec/cryptoUtils.spec.js | 8 +- spec/features.spec.js | 16 +- spec/helper.js | 245 +- spec/index.spec.js | 449 +- spec/myoauth.js | 4 +- spec/parsers.spec.js | 24 +- spec/rest.spec.js | 845 +- spec/schemas.spec.js | 3152 ++++--- spec/support/CustomAuth.js | 5 +- spec/support/CustomAuthFunction.js | 7 +- spec/support/CustomMiddleware.js | 2 +- spec/support/jasmine.json | 8 +- spec/support/lorem.txt | 0 spec/testing-routes.js | 49 +- src/AccountLockout.js | 91 +- src/Adapters/AdapterLoader.js | 19 +- src/Adapters/Analytics/AnalyticsAdapter.js | 21 +- src/Adapters/Auth/AuthAdapter.js | 1 - src/Adapters/Auth/OAuth1Client.js | 172 +- src/Adapters/Auth/facebook.js | 64 +- src/Adapters/Auth/facebookaccountkit.js | 87 +- src/Adapters/Auth/github.js | 53 +- src/Adapters/Auth/google.js | 78 +- src/Adapters/Auth/httpsRequest.js | 41 + src/Adapters/Auth/index.js | 68 +- src/Adapters/Auth/instagram.js | 29 +- src/Adapters/Auth/janraincapture.js | 38 +- src/Adapters/Auth/janrainengage.js | 61 +- src/Adapters/Auth/linkedin.js | 58 +- src/Adapters/Auth/meetup.js | 51 +- src/Adapters/Auth/qq.js | 54 +- src/Adapters/Auth/spotify.js | 72 +- src/Adapters/Auth/twitter.js | 38 +- src/Adapters/Auth/vkontakte.js | 78 +- src/Adapters/Auth/wechat.js | 32 +- src/Adapters/Auth/weibo.js | 58 +- src/Adapters/Cache/CacheAdapter.js | 18 +- src/Adapters/Cache/InMemoryCache.js | 10 +- src/Adapters/Cache/InMemoryCacheAdapter.js | 5 +- src/Adapters/Cache/LRUCache.js | 10 +- src/Adapters/Cache/NullCacheAdapter.js | 5 +- src/Adapters/Cache/RedisCacheAdapter.js | 11 +- src/Adapters/Email/MailAdapter.js | 12 +- src/Adapters/Files/FilesAdapter.js | 28 +- src/Adapters/Files/GridFSBucketAdapter.js | 95 + src/Adapters/Files/GridStoreAdapter.js | 70 +- src/Adapters/Logger/LoggerAdapter.js | 26 +- src/Adapters/Logger/WinstonLogger.js | 69 +- src/Adapters/Logger/WinstonLoggerAdapter.js | 7 +- src/Adapters/MessageQueue/EventEmitterMQ.js | 12 +- src/Adapters/PubSub/EventEmitterPubSub.js | 12 +- src/Adapters/PubSub/PubSubAdapter.js | 49 + src/Adapters/PubSub/RedisPubSub.js | 58 +- src/Adapters/Push/PushAdapter.js | 14 +- src/Adapters/Storage/Mongo/MongoCollection.js | 101 +- .../Storage/Mongo/MongoSchemaCollection.js | 211 +- .../Storage/Mongo/MongoStorageAdapter.js | 620 +- src/Adapters/Storage/Mongo/MongoTransform.js | 1857 ++-- .../Storage/Postgres/PostgresClient.js | 1 - .../Storage/Postgres/PostgresConfigParser.js | 25 +- .../Postgres/PostgresStorageAdapter.js | 1384 +-- src/Adapters/Storage/Postgres/sql/index.js | 9 +- src/Adapters/Storage/StorageAdapter.js | 93 +- src/Auth.js | 383 +- src/ClientSDK.js | 12 +- src/Config.js | 167 +- src/Controllers/AdaptableController.js | 34 +- src/Controllers/AnalyticsController.js | 34 +- src/Controllers/CacheController.js | 4 +- src/Controllers/DatabaseController.js | 1123 ++- src/Controllers/FilesController.js | 22 +- src/Controllers/HooksController.js | 179 +- src/Controllers/LiveQueryController.js | 39 +- src/Controllers/LoggerController.js | 100 +- src/Controllers/PushController.js | 190 +- src/Controllers/SchemaCache.js | 29 +- src/Controllers/SchemaController.js | 1221 ++- src/Controllers/UserController.js | 231 +- src/Controllers/index.js | 217 +- src/Controllers/types.js | 30 +- src/LiveQuery/Client.js | 40 +- src/LiveQuery/ParseCloudCodePublisher.js | 16 +- src/LiveQuery/ParseLiveQueryServer.js | 577 +- src/LiveQuery/ParsePubSub.js | 28 +- src/LiveQuery/ParseWebSocketServer.js | 12 +- src/LiveQuery/QueryTools.js | 258 +- src/LiveQuery/RequestSchema.js | 202 +- src/LiveQuery/SessionTokenCache.js | 64 +- src/LiveQuery/Subscription.js | 10 +- src/LiveQuery/equalObjects.js | 4 +- src/Options/Definitions.js | 795 +- src/Options/docs.js | 92 + src/Options/index.js | 194 +- src/Options/parsers.js | 14 +- src/ParseMessageQueue.js | 24 +- src/ParseServer.js | 225 +- src/ParseServerRESTController.js | 89 +- src/PromiseRouter.js | 128 +- src/Push/PushQueue.js | 64 +- src/Push/PushWorker.js | 101 +- src/Push/utils.js | 88 +- src/RestQuery.js | 575 +- src/RestWrite.js | 1211 ++- src/Routers/AggregateRouter.js | 103 +- src/Routers/AnalyticsRouter.js | 5 +- src/Routers/AudiencesRouter.js | 77 +- src/Routers/ClassesRouter.js | 129 +- src/Routers/CloudCodeRouter.js | 118 +- src/Routers/FeaturesRouter.js | 109 +- src/Routers/FilesRouter.js | 161 +- src/Routers/FunctionsRouter.js | 171 +- src/Routers/GlobalConfigRouter.js | 46 +- src/Routers/HooksRouter.js | 143 +- src/Routers/IAPValidationRouter.js | 139 +- src/Routers/InstallationsRouter.js | 40 +- src/Routers/LogsRouter.js | 31 +- src/Routers/PublicAPIRouter.js | 236 +- src/Routers/PurgeRouter.js | 25 +- src/Routers/PushRouter.js | 74 +- src/Routers/RolesRouter.js | 21 +- src/Routers/SchemasRouter.js | 119 +- src/Routers/SessionsRouter.js | 93 +- src/Routers/UsersRouter.js | 321 +- src/StatusHandler.js | 165 +- src/TestUtils.js | 18 +- src/batch.js | 58 +- src/cache.js | 4 +- .../definitions/parse-live-query-server.js | 3 +- src/cli/definitions/parse-server.js | 3 +- src/cli/parse-live-query-server.js | 4 +- src/cli/parse-server.js | 59 +- src/cli/utils/commander.js | 32 +- src/cli/utils/runner.js | 16 +- src/cloud-code/HTTPResponse.js | 28 +- src/cloud-code/Parse.Cloud.js | 276 +- src/cloud-code/httpRequest.js | 171 +- src/cryptoUtils.js | 11 +- src/defaults.js | 24 +- src/deprecated.js | 2 +- src/index.js | 30 +- src/logger.js | 9 +- src/middlewares.js | 153 +- src/password.js | 6 +- src/request.js | 1 + src/requiredParameter.js | 4 +- src/rest.js | 315 +- src/triggers.js | 522 +- src/vendor/README.md | 6 +- src/vendor/mongodbUrl.js | 580 +- 410 files changed, 55917 insertions(+), 41215 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/---parse-server-3-0-0.md create mode 100644 .github/stale.yml create mode 100644 .prettierrc create mode 100644 3.0.0.md create mode 100644 jsdoc-conf.json create mode 100644 lib/Adapters/Auth/httpsRequest.js create mode 100644 lib/Adapters/Files/GridFSBucketAdapter.js create mode 100644 lib/Adapters/PubSub/PubSubAdapter.js create mode 100644 lib/Options/docs.js create mode 100644 lib/request.js create mode 100755 release_docs.sh mode change 100644 => 100755 spec/.babelrc mode change 100644 => 100755 spec/.eslintrc.json mode change 100644 => 100755 spec/AccountLockoutPolicy.spec.js mode change 100644 => 100755 spec/AdaptableController.spec.js mode change 100644 => 100755 spec/AdapterLoader.spec.js create mode 100755 spec/AggregateRouter.spec.js mode change 100644 => 100755 spec/Analytics.spec.js mode change 100644 => 100755 spec/AudienceRouter.spec.js mode change 100644 => 100755 spec/Auth.spec.js mode change 100644 => 100755 spec/AuthenticationAdapters.spec.js mode change 100644 => 100755 spec/CLI.spec.js mode change 100644 => 100755 spec/CacheController.spec.js mode change 100644 => 100755 spec/Client.spec.js mode change 100644 => 100755 spec/ClientSDK.spec.js mode change 100644 => 100755 spec/CloudCode.spec.js mode change 100644 => 100755 spec/CloudCodeLogger.spec.js mode change 100644 => 100755 spec/DatabaseController.spec.js mode change 100644 => 100755 spec/EmailVerificationToken.spec.js mode change 100644 => 100755 spec/EnableExpressErrorHandler.spec.js mode change 100644 => 100755 spec/EnableSingleSchemaCache.spec.js mode change 100644 => 100755 spec/EventEmitterPubSub.spec.js mode change 100644 => 100755 spec/FilesController.spec.js create mode 100755 spec/GridFSBucketStorageAdapter.spec.js delete mode 100644 spec/GridStoreAdapter.js create mode 100755 spec/GridStoreAdapter.spec.js mode change 100644 => 100755 spec/HTTPRequest.spec.js mode change 100644 => 100755 spec/InMemoryCache.spec.js mode change 100644 => 100755 spec/InMemoryCacheAdapter.spec.js mode change 100644 => 100755 spec/InstallationsRouter.spec.js mode change 100644 => 100755 spec/JobSchedule.spec.js mode change 100644 => 100755 spec/Logger.spec.js mode change 100644 => 100755 spec/LoggerController.spec.js mode change 100644 => 100755 spec/LogsRouter.spec.js mode change 100644 => 100755 spec/Middlewares.spec.js mode change 100644 => 100755 spec/MockAdapter.js mode change 100644 => 100755 spec/MockEmailAdapter.js mode change 100644 => 100755 spec/MockEmailAdapterWithOptions.js mode change 100644 => 100755 spec/MockPushAdapter.js mode change 100644 => 100755 spec/MongoSchemaCollectionAdapter.spec.js mode change 100644 => 100755 spec/MongoStorageAdapter.spec.js mode change 100644 => 100755 spec/MongoTransform.spec.js mode change 100644 => 100755 spec/NullCacheAdapter.spec.js mode change 100644 => 100755 spec/OAuth1.spec.js mode change 100644 => 100755 spec/Parse.Push.spec.js mode change 100644 => 100755 spec/ParseACL.spec.js mode change 100644 => 100755 spec/ParseAPI.spec.js mode change 100644 => 100755 spec/ParseCloudCodePublisher.spec.js mode change 100644 => 100755 spec/ParseFile.spec.js mode change 100644 => 100755 spec/ParseGeoPoint.spec.js mode change 100644 => 100755 spec/ParseGlobalConfig.spec.js mode change 100644 => 100755 spec/ParseHooks.spec.js mode change 100644 => 100755 spec/ParseInstallation.spec.js mode change 100644 => 100755 spec/ParseLiveQueryServer.spec.js mode change 100644 => 100755 spec/ParseObject.spec.js mode change 100644 => 100755 spec/ParsePolygon.spec.js mode change 100644 => 100755 spec/ParsePubSub.spec.js mode change 100644 => 100755 spec/ParseQuery.Aggregate.spec.js mode change 100644 => 100755 spec/ParseQuery.FullTextSearch.spec.js mode change 100644 => 100755 spec/ParseQuery.spec.js mode change 100644 => 100755 spec/ParseRelation.spec.js mode change 100644 => 100755 spec/ParseRole.spec.js mode change 100644 => 100755 spec/ParseServer.spec.js mode change 100644 => 100755 spec/ParseServerRESTController.spec.js mode change 100644 => 100755 spec/ParseSession.spec.js mode change 100644 => 100755 spec/ParseUser.spec.js mode change 100644 => 100755 spec/ParseWebSocket.spec.js mode change 100644 => 100755 spec/ParseWebSocketServer.spec.js mode change 100644 => 100755 spec/PasswordPolicy.spec.js mode change 100644 => 100755 spec/PointerPermissions.spec.js mode change 100644 => 100755 spec/PostgresConfigParser.spec.js mode change 100644 => 100755 spec/PostgresInitOptions.spec.js mode change 100644 => 100755 spec/PostgresStorageAdapter.spec.js mode change 100644 => 100755 spec/PromiseRouter.spec.js mode change 100644 => 100755 spec/PublicAPI.spec.js mode change 100644 => 100755 spec/PurchaseValidation.spec.js mode change 100644 => 100755 spec/PushController.spec.js mode change 100644 => 100755 spec/PushQueue.spec.js mode change 100644 => 100755 spec/PushRouter.spec.js mode change 100644 => 100755 spec/PushWorker.spec.js mode change 100644 => 100755 spec/QueryTools.spec.js mode change 100644 => 100755 spec/ReadPreferenceOption.spec.js mode change 100644 => 100755 spec/RedisCacheAdapter.spec.js mode change 100644 => 100755 spec/RedisPubSub.spec.js mode change 100644 => 100755 spec/RestQuery.spec.js mode change 100644 => 100755 spec/RevocableSessionsUpgrade.spec.js mode change 100644 => 100755 spec/Schema.spec.js mode change 100644 => 100755 spec/SchemaCache.spec.js mode change 100644 => 100755 spec/SessionTokenCache.spec.js mode change 100644 => 100755 spec/Subscription.spec.js mode change 100644 => 100755 spec/TwitterAuth.spec.js mode change 100644 => 100755 spec/Uniqueness.spec.js mode change 100644 => 100755 spec/UserController.spec.js mode change 100644 => 100755 spec/UserPII.spec.js mode change 100644 => 100755 spec/ValidationAndPasswordsReset.spec.js mode change 100644 => 100755 spec/VerifyUserPassword.spec.js mode change 100644 => 100755 spec/WinstonLoggerAdapter.spec.js mode change 100644 => 100755 spec/batch.spec.js mode change 100644 => 100755 spec/cloud/cloudCodeAbsoluteFile.js mode change 100644 => 100755 spec/cloud/cloudCodeRelativeFile.js mode change 100644 => 100755 spec/configs/CLIConfig.json mode change 100644 => 100755 spec/configs/CLIConfigApps.json mode change 100644 => 100755 spec/configs/CLIConfigFail.json mode change 100644 => 100755 spec/configs/CLIConfigFailTooManyApps.json mode change 100644 => 100755 spec/configs/CLIConfigUnknownArg.json mode change 100644 => 100755 spec/cryptoUtils.spec.js mode change 100644 => 100755 spec/features.spec.js mode change 100644 => 100755 spec/helper.js mode change 100644 => 100755 spec/index.spec.js mode change 100644 => 100755 spec/myoauth.js mode change 100644 => 100755 spec/parsers.spec.js mode change 100644 => 100755 spec/rest.spec.js mode change 100644 => 100755 spec/schemas.spec.js mode change 100644 => 100755 spec/support/CustomAuth.js mode change 100644 => 100755 spec/support/CustomAuthFunction.js mode change 100644 => 100755 spec/support/CustomMiddleware.js mode change 100644 => 100755 spec/support/jasmine.json mode change 100644 => 100755 spec/support/lorem.txt mode change 100644 => 100755 spec/testing-routes.js create mode 100644 src/Adapters/Auth/httpsRequest.js create mode 100644 src/Adapters/Files/GridFSBucketAdapter.js create mode 100644 src/Adapters/PubSub/PubSubAdapter.js create mode 100644 src/Options/docs.js create mode 100644 src/request.js diff --git a/.babelrc b/.babelrc index c8c8069f1d..1eb1208aa6 100644 --- a/.babelrc +++ b/.babelrc @@ -1,10 +1,10 @@ { "plugins": [ - "transform-flow-strip-types", - "transform-object-rest-spread" + "@babel/plugin-transform-flow-strip-types", + "@babel/plugin-proposal-object-rest-spread" ], "presets": [ - ["env", { + ["@babel/preset-env", { "targets": { "node": "8" } diff --git a/.eslintrc.json b/.eslintrc.json index 2a14b903f9..7c2b937b7c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -14,7 +14,7 @@ "sourceType": "module" }, "rules": { - "indent": ["error", 2], + "indent": ["error", 2, { "SwitchCase": 1 }], "linebreak-style": ["error", "unix"], "no-trailing-spaces": 2, "eol-last": 2, diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 4de30ac7c8..6d82dd37ab 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,3 +1,5 @@ + ### 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 diff --git a/.github/ISSUE_TEMPLATE/---parse-server-3-0-0.md b/.github/ISSUE_TEMPLATE/---parse-server-3-0-0.md new file mode 100644 index 0000000000..b74b3e67b0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---parse-server-3-0-0.md @@ -0,0 +1,54 @@ +--- +name: "\U0001F525 parse-server 3.0.0" +about: Report an issue while migrating to parse-server 3.0.0 + +--- + + + +# Before opening the issue please ensure that you have: + +- [ ] [Read the migration guide](https://github.com/parse-community/parse-server/blob/master/3.0.0.md) to parse-server 3.0.0 +- [ ] [Read the migration guide](https://github.com/parse-community/Parse-SDK-JS/blob/master/2.0.0.md) to Parse SDK JS 2.0.0 + +### Issue Description + + + +### Steps to reproduce + + + +### Expected Results + + + +### Actual Outcome + + + +### 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 + + diff --git a/.github/ISSUE_TEMPLATE/---push-notifications.md b/.github/ISSUE_TEMPLATE/---push-notifications.md index 3466cb9c1d..78afe51052 100644 --- a/.github/ISSUE_TEMPLATE/---push-notifications.md +++ b/.github/ISSUE_TEMPLATE/---push-notifications.md @@ -4,4 +4,48 @@ about: Issues with setting up or delivering push notifications --- + + +### Issue Description + + + +### Push Configuration + +Please provide a copy of your `push` configuration here, obfuscating any sensitive part. + +### 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 + + diff --git a/.github/ISSUE_TEMPLATE/---report-an-issue.md b/.github/ISSUE_TEMPLATE/---report-an-issue.md index b5bdc244a4..b729f9525a 100644 --- a/.github/ISSUE_TEMPLATE/---report-an-issue.md +++ b/.github/ISSUE_TEMPLATE/---report-an-issue.md @@ -6,7 +6,11 @@ about: Report an issue on parse-server