@axway/amplify-cli-utils
Version:
Common utils for Axway CLI packages
428 lines (367 loc) • 38.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "AmplifySDK", {
enumerable: true,
get: function () {
return _amplifySdk.default;
}
});
Object.defineProperty(exports, "Config", {
enumerable: true,
get: function () {
return _amplifyConfig.Config;
}
});
Object.defineProperty(exports, "Telemetry", {
enumerable: true,
get: function () {
return _amplifySdk.Telemetry;
}
});
exports.buildParams = exports.buildAuthParams = buildAuthParams;
exports.checkForUpdate = checkForUpdate;
Object.defineProperty(exports, "createNPMRequestArgs", {
enumerable: true,
get: function () {
return _request.createNPMRequestArgs;
}
});
Object.defineProperty(exports, "createRequestClient", {
enumerable: true,
get: function () {
return _request.createRequestClient;
}
});
Object.defineProperty(exports, "createRequestOptions", {
enumerable: true,
get: function () {
return _request.createRequestOptions;
}
});
exports.createTable = createTable;
exports.environments = void 0;
exports.getAuthConfigEnvSpecifier = getAuthConfigEnvSpecifier;
exports.hlVer = hlVer;
exports.initPlatformAccount = initPlatformAccount;
exports.initSDK = initSDK;
exports.isHeadless = isHeadless;
Object.defineProperty(exports, "loadConfig", {
enumerable: true,
get: function () {
return _amplifyConfig.default;
}
});
exports.telemetry = exports.request = exports.locations = void 0;
var _sourceMapSupport = _interopRequireDefault(require("source-map-support"));
var _amplifySdk = _interopRequireWildcard(require("@axway/amplify-sdk"));
var _boxen = _interopRequireDefault(require("boxen"));
var _checkKit = _interopRequireDefault(require("check-kit"));
var _fs = _interopRequireDefault(require("fs"));
var _amplifyConfig = _interopRequireWildcard(require("@axway/amplify-config"));
var _snooplogg = _interopRequireDefault(require("snooplogg"));
var _cliTable = _interopRequireDefault(require("cli-table3"));
var _cliKit = require("cli-kit");
var _request = require("./request.js");
var environments = _interopRequireWildcard(require("./environments.js"));
exports.environments = environments;
var locations = _interopRequireWildcard(require("./locations.js"));
exports.locations = locations;
var request = _interopRequireWildcard(require("@axway/amplify-request"));
exports.request = request;
var telemetry = _interopRequireWildcard(require("./telemetry.js"));
exports.telemetry = telemetry;
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* istanbul ignore if */
if (!Error.prepareStackTrace) {
_sourceMapSupport.default.install();
}
const {
warn
} = (0, _snooplogg.default)('amplify-cli-utils');
const {
cyan,
gray,
green
} = _snooplogg.default.chalk;
/**
* Constructs a parameters object to pass into an Auth instance.
*
* @param {Object} [opts] - User option overrides.
* @param {Config} [config] - The Amplify config object.
* @returns {Object}
*/
async function buildAuthParams(opts = {}, config) {
if (!opts || typeof opts !== 'object') {
throw new Error('Expected options to be an object');
}
if (!config) {
config = await (0, _amplifyConfig.default)();
}
const env = environments.resolve(opts.env || (await config.get('env')));
const {
clientId,
realm
} = env.auth;
const params = {};
const props = {
baseUrl: undefined,
clientId,
clientSecret: undefined,
env: env.name,
interactiveLoginTimeout: undefined,
homeDir: locations.axwayHome,
password: undefined,
persistSecrets: undefined,
platformUrl: undefined,
realm,
secretFile: undefined,
serverHost: undefined,
serverPort: undefined,
serviceAccount: undefined,
tokenRefreshThreshold: 15 * 60,
// 15 minutes
tokenStore: undefined,
tokenStoreDir: locations.axwayHome,
tokenStoreType: undefined,
username: undefined
};
for (const prop of Object.keys(props)) {
params[prop] = opts[prop] !== undefined ? opts[prop] : await config.get(`auth.${prop}`, props[prop]);
} // detect if we're headless and default token store type to `file`
if (params.tokenStoreType === undefined && isHeadless()) {
params.tokenStoreType = 'file';
await config.set('auth.tokenStoreType', 'file');
try {
await config.save();
} catch (err) {
warn(err);
}
}
params.requestOptions = (0, _request.createRequestOptions)(opts, config);
return params;
} // `buildParams()` is too ambiguous, so it was renamed to `buildAuthParams()`, but we still need to
// maintain backwards compatibility
/**
* Checks if a new version of an npm package is available and returns a string with the formatted
* update message.
*
* @param {Object} [opts] - Check update and request configuration options.
* @param {Number} [opts.checkInterval=3600000] - The amount of time in milliseconds before
* checking for an update. Defaults to 1 hour.
* @param {String} [opts.cwd] - The current working directory used to locate the `package.json` if
* `pkg` is not specified.
* @param {String} [opts.distTag='latest'] - The tag to check for the latest version.
* @param {Boolean} [opts.force=false] - Forces an update check.
* @param {String} [opts.metaDir] - The directory to store package update information.
* @param {Object|String} [opts.pkg] - The parsed `package.json`, path to the package.json file, or
* falsey and it will scan parent directories looking for a package.json.
* @param {String} [opts.registryUrl] - The npm registry URL. By default, it will autodetect the
* URL based on the package name/scope.
* @param {Number} [opts.timeout=1000] - The number of milliseconds to wait to query npm before
* timing out.
* @param {Config} [config] - An Amplify Config instance. If not specified, the config is loaded
* from disk.
* @returns {String}
*/
async function checkForUpdate(opts, config) {
opts = (0, _request.createRequestOptions)(opts, config || (await (0, _amplifyConfig.default)()));
const {
current,
latest,
name,
updateAvailable
} = await (0, _checkKit.default)(opts);
if (updateAvailable) {
const msg = `Update available ${gray(current)} → ${green(latest)}\nRun ${cyan(`npm i -g ${name}`)} to update`;
return (0, _boxen.default)(msg, {
align: 'center',
borderColor: 'yellow',
borderStyle: 'round',
margin: {
bottom: 1,
left: 4,
right: 4,
top: 1
},
padding: {
bottom: 1,
left: 4,
right: 4,
top: 1
}
});
}
}
/**
* Creates a table with default styles and padding.
*
* @param {Array.<String>} head - One or more headings.
* @param {Number} [indent] - The number of spaces to indent the table.
* @returns {Table}
*/
function createTable(head, indent = 0) {
return new _cliTable.default({
chars: {
bottom: '',
'bottom-left': '',
'bottom-mid': '',
'bottom-right': '',
left: ' '.repeat(indent),
'left-mid': '',
mid: '',
'mid-mid': '',
middle: ' ',
right: '',
'right-mid': '',
top: '',
'top-left': '',
'top-mid': '',
'top-right': ''
},
head: Array.isArray(head) ? head.map(_cliKit.ansi.toUpperCase) : head,
style: {
border: [],
head: [],
'padding-left': 0,
'padding-right': 0
}
});
}
/**
* Resovles the "auth.*" config key based on your environment. This is used to get or set the
* default account and org.
*
* @param {String} env - The resolved environment name.
* @returns {String}
*
* @example
* await config.get(`${getAuthConfigEnvSpecifier(sdk.env.name)}.defaultAccount`);
*/
function getAuthConfigEnvSpecifier(env) {
return !env || env === 'prod' ? 'auth' : `auth.environment.${env}`;
}
/**
* Highlights the difference between two versions.
*
* @param {String} toVer - The latest version.
* @param {String} fromVer - The current version.
* @returns {String}
*/
function hlVer(toVer, fromVer) {
const {
green
} = _snooplogg.default.styles;
const version = [];
let [from, fromTag] = fromVer.split(/-(.+)/);
from = from.replace(/[^.\d]/g, '').split('.').map(x => parseInt(x));
let [to, toTag] = toVer.split(/-(.+)/);
const toMatch = to.match(/^([^\d]+)?(.+)$/);
to = (toMatch ? toMatch[2] : to).split('.').map(x => parseInt(x));
const tag = () => {
if (toTag) {
const toNum = toTag.match(/\d+$/);
const fromNum = fromTag && fromTag.match(/\d+$/);
if (fromNum && parseInt(fromNum[0]) >= parseInt(toNum)) {
return `-${toTag}`;
} else {
return green(`-${toTag}`);
}
}
return '';
};
while (to.length) {
if (to[0] > from[0]) {
if (version.length) {
return (toMatch && toMatch[1] || '') + version.concat(green(to.join('.') + tag())).join('.');
}
return green((toMatch && toMatch[1] || '') + to.join('.') + tag());
}
version.push(to.shift());
from.shift();
}
return (toMatch && toMatch[1] || '') + version.join('.') + tag();
}
/**
* Initializes the Amplify SDK, loads an account, and finds the default org id.
*
* @param {String} [accountName] - The name of the platform account to use.
* @param {String} [org] - The name, id, or guid of the default organization.
* @param {String} [env] - The environment name.
* @param {boolean} [bypassPlatformAccountCheck] - Optional parameter to bypass check if the account is platform
* @returns {Promise<Object>}
*/
async function initPlatformAccount(accountName, org, env, bypassPlatformAccountCheck = false) {
const {
config,
sdk
} = await initSDK({
env
});
const authConfigEnvSpecifier = getAuthConfigEnvSpecifier(sdk.env.name);
const account = await sdk.auth.find(accountName || (await config.get(`${authConfigEnvSpecifier}.defaultAccount`)));
if (accountName) {
if (!account) {
throw new Error(`Account "${accountName}" not found`);
} else if (!bypassPlatformAccountCheck && !account.isPlatform) {
throw new Error(`Account "${accountName}" is not a platform account\n\nTo login, run: axway auth login`);
}
} else if (!account || !bypassPlatformAccountCheck && !account.isPlatform) {
throw new Error('You must be logged into a platform account\n\nTo login, run: axway auth login');
}
if (org) {
org = await sdk.org.find(account, org);
} else {
try {
// check the config for a default org for this account
org = await sdk.org.find(account, await config.get(`${authConfigEnvSpecifier}.defaultOrg.${account.hash}`));
} catch (err) {
// default org was stale, auto detect the default from the account orgs
org = await sdk.org.find(account);
}
}
return {
account,
config,
org,
sdk
};
}
/**
* Loads the config and creates an Amplify SDK object, then returns both of them.
*
* @param {Object} [opts] - SDK options including `env` and auth options.
* @param {Object} [config] - The Amplify await config. If not passed in, the config file is loaded.
* @returns {Object} Returns an object containing the Axway CLI config and an initialized
* Amplify SDK instance.
*/
async function initSDK(opts = {}, config) {
if (!config) {
config = await (0, _amplifyConfig.default)();
}
return {
config,
sdk: new _amplifySdk.default(await buildAuthParams(opts, config))
};
}
/**
* Detects if the current terminal is headless (e.g. a Docker container or SSH session).
*
* @returns {Boolean}
*/
function isHeadless() {
try {
if (process.platform === 'linux' && (process.env.SSH_TTY || !process.env.DISPLAY || /docker|lxc/.test(_fs.default.readFileSync('/proc/1/cgroup', 'utf8')))) {
return true;
}
if (process.platform === 'darwin' && process.env.SSH_TTY) {
return true;
}
} catch (e) {// do nothing
}
return false;
}
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6WyJFcnJvciIsInByZXBhcmVTdGFja1RyYWNlIiwic291cmNlTWFwU3VwcG9ydCIsImluc3RhbGwiLCJ3YXJuIiwiY3lhbiIsImdyYXkiLCJncmVlbiIsInNub29wbG9nZyIsImNoYWxrIiwiYnVpbGRBdXRoUGFyYW1zIiwib3B0cyIsImNvbmZpZyIsImVudiIsImVudmlyb25tZW50cyIsInJlc29sdmUiLCJnZXQiLCJjbGllbnRJZCIsInJlYWxtIiwiYXV0aCIsInBhcmFtcyIsInByb3BzIiwiYmFzZVVybCIsInVuZGVmaW5lZCIsImNsaWVudFNlY3JldCIsIm5hbWUiLCJpbnRlcmFjdGl2ZUxvZ2luVGltZW91dCIsImhvbWVEaXIiLCJsb2NhdGlvbnMiLCJheHdheUhvbWUiLCJwYXNzd29yZCIsInBlcnNpc3RTZWNyZXRzIiwicGxhdGZvcm1VcmwiLCJzZWNyZXRGaWxlIiwic2VydmVySG9zdCIsInNlcnZlclBvcnQiLCJzZXJ2aWNlQWNjb3VudCIsInRva2VuUmVmcmVzaFRocmVzaG9sZCIsInRva2VuU3RvcmUiLCJ0b2tlblN0b3JlRGlyIiwidG9rZW5TdG9yZVR5cGUiLCJ1c2VybmFtZSIsInByb3AiLCJPYmplY3QiLCJrZXlzIiwiaXNIZWFkbGVzcyIsInNldCIsInNhdmUiLCJlcnIiLCJyZXF1ZXN0T3B0aW9ucyIsImNoZWNrRm9yVXBkYXRlIiwiY3VycmVudCIsImxhdGVzdCIsInVwZGF0ZUF2YWlsYWJsZSIsIm1zZyIsImFsaWduIiwiYm9yZGVyQ29sb3IiLCJib3JkZXJTdHlsZSIsIm1hcmdpbiIsImJvdHRvbSIsImxlZnQiLCJyaWdodCIsInRvcCIsInBhZGRpbmciLCJjcmVhdGVUYWJsZSIsImhlYWQiLCJpbmRlbnQiLCJUYWJsZSIsImNoYXJzIiwicmVwZWF0IiwibWlkIiwibWlkZGxlIiwiQXJyYXkiLCJpc0FycmF5IiwibWFwIiwiYW5zaSIsInRvVXBwZXJDYXNlIiwic3R5bGUiLCJib3JkZXIiLCJnZXRBdXRoQ29uZmlnRW52U3BlY2lmaWVyIiwiaGxWZXIiLCJ0b1ZlciIsImZyb21WZXIiLCJzdHlsZXMiLCJ2ZXJzaW9uIiwiZnJvbSIsImZyb21UYWciLCJzcGxpdCIsInJlcGxhY2UiLCJ4IiwicGFyc2VJbnQiLCJ0byIsInRvVGFnIiwidG9NYXRjaCIsIm1hdGNoIiwidGFnIiwidG9OdW0iLCJmcm9tTnVtIiwibGVuZ3RoIiwiY29uY2F0Iiwiam9pbiIsInB1c2giLCJzaGlmdCIsImluaXRQbGF0Zm9ybUFjY291bnQiLCJhY2NvdW50TmFtZSIsIm9yZyIsImJ5cGFzc1BsYXRmb3JtQWNjb3VudENoZWNrIiwic2RrIiwiaW5pdFNESyIsImF1dGhDb25maWdFbnZTcGVjaWZpZXIiLCJhY2NvdW50IiwiZmluZCIsImlzUGxhdGZvcm0iLCJoYXNoIiwiQW1wbGlmeVNESyIsInByb2Nlc3MiLCJwbGF0Zm9ybSIsIlNTSF9UVFkiLCJESVNQTEFZIiwidGVzdCIsImZzIiwicmVhZEZpbGVTeW5jIiwiZSJdLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzb3VyY2VNYXBTdXBwb3J0IGZyb20gJ3NvdXJjZS1tYXAtc3VwcG9ydCc7XG4vKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbmlmICghRXJyb3IucHJlcGFyZVN0YWNrVHJhY2UpIHtcblx0c291cmNlTWFwU3VwcG9ydC5pbnN0YWxsKCk7XG59XG5cbmltcG9ydCBBbXBsaWZ5U0RLLCB7IFRlbGVtZXRyeSB9IGZyb20gJ0BheHdheS9hbXBsaWZ5LXNkayc7XG5pbXBvcnQgYm94ZW4gZnJvbSAnYm94ZW4nO1xuaW1wb3J0IGNoZWNrIGZyb20gJ2NoZWNrLWtpdCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IGxvYWRDb25maWcsIHsgQ29uZmlnIH0gZnJvbSAnQGF4d2F5L2FtcGxpZnktY29uZmlnJztcbmltcG9ydCBzbm9vcGxvZ2cgZnJvbSAnc25vb3Bsb2dnJztcbmltcG9ydCBUYWJsZSBmcm9tICdjbGktdGFibGUzJztcbmltcG9ydCB7IGFuc2kgfSBmcm9tICdjbGkta2l0JztcbmltcG9ydCB7IGNyZWF0ZU5QTVJlcXVlc3RBcmdzLCBjcmVhdGVSZXF1ZXN0Q2xpZW50LCBjcmVhdGVSZXF1ZXN0T3B0aW9ucyB9IGZyb20gJy4vcmVxdWVzdC5qcyc7XG5pbXBvcnQgKiBhcyBlbnZpcm9ubWVudHMgZnJvbSAnLi9lbnZpcm9ubWVudHMuanMnO1xuaW1wb3J0ICogYXMgbG9jYXRpb25zIGZyb20gJy4vbG9jYXRpb25zLmpzJztcbmltcG9ydCAqIGFzIHJlcXVlc3QgZnJvbSAnQGF4d2F5L2FtcGxpZnktcmVxdWVzdCc7XG5pbXBvcnQgKiBhcyB0ZWxlbWV0cnkgZnJvbSAnLi90ZWxlbWV0cnkuanMnO1xuXG5leHBvcnQge1xuXHRBbXBsaWZ5U0RLLFxuXHRDb25maWcsXG5cdGNyZWF0ZU5QTVJlcXVlc3RBcmdzLFxuXHRjcmVhdGVSZXF1ZXN0Q2xpZW50LFxuXHRjcmVhdGVSZXF1ZXN0T3B0aW9ucyxcblx0ZW52aXJvbm1lbnRzLFxuXHRsb2FkQ29uZmlnLFxuXHRsb2NhdGlvbnMsXG5cdHJlcXVlc3QsXG5cdFRlbGVtZXRyeSxcblx0dGVsZW1ldHJ5XG59O1xuXG5jb25zdCB7IHdhcm4gfSA9IHNub29wbG9nZygnYW1wbGlmeS1jbGktdXRpbHMnKTtcbmNvbnN0IHsgY3lhbiwgZ3JheSwgZ3JlZW4gfSA9IHNub29wbG9nZy5jaGFsaztcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgcGFyYW1ldGVycyBvYmplY3QgdG8gcGFzcyBpbnRvIGFuIEF1dGggaW5zdGFuY2UuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRzXSAtIFVzZXIgb3B0aW9uIG92ZXJyaWRlcy5cbiAqIEBwYXJhbSB7Q29uZmlnfSBbY29uZmlnXSAtIFRoZSBBbXBsaWZ5IGNvbmZpZyBvYmplY3QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYnVpbGRBdXRoUGFyYW1zKG9wdHMgPSB7fSwgY29uZmlnKSB7XG5cdGlmICghb3B0cyB8fCB0eXBlb2Ygb3B0cyAhPT0gJ29iamVjdCcpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdGVkIG9wdGlvbnMgdG8gYmUgYW4gb2JqZWN0Jyk7XG5cdH1cblxuXHRpZiAoIWNvbmZpZykge1xuXHRcdGNvbmZpZyA9IGF3YWl0IGxvYWRDb25maWcoKTtcblx0fVxuXG5cdGNvbnN0IGVudiA9IGVudmlyb25tZW50cy5yZXNvbHZlKG9wdHMuZW52IHx8IGF3YWl0IGNvbmZpZy5nZXQoJ2VudicpKTtcblxuXHRjb25zdCB7IGNsaWVudElkLCByZWFsbSB9ID0gZW52LmF1dGg7XG5cdGNvbnN0IHBhcmFtcyA9IHt9O1xuXHRjb25zdCBwcm9wcyA9IHtcblx0XHRiYXNlVXJsOiAgICAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuXHRcdGNsaWVudElkLFxuXHRcdGNsaWVudFNlY3JldDogICAgICAgICAgICB1bmRlZmluZWQsXG5cdFx0ZW52OiAgICAgICAgICAgICAgICAgICAgIGVudi5uYW1lLFxuXHRcdGludGVyYWN0aXZlTG9naW5UaW1lb3V0OiB1bmRlZmluZWQsXG5cdFx0aG9tZURpcjogICAgICAgICAgICAgICAgIGxvY2F0aW9ucy5heHdheUhvbWUsXG5cdFx0cGFzc3dvcmQ6ICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcblx0XHRwZXJzaXN0U2VjcmV0czogICAgICAgICAgdW5kZWZpbmVkLFxuXHRcdHBsYXRmb3JtVXJsOiAgICAgICAgICAgICB1bmRlZmluZWQsXG5cdFx0cmVhbG0sXG5cdFx0c2VjcmV0RmlsZTogICAgICAgICAgICAgIHVuZGVmaW5lZCxcblx0XHRzZXJ2ZXJIb3N0OiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuXHRcdHNlcnZlclBvcnQ6ICAgICAgICAgICAgICB1bmRlZmluZWQsXG5cdFx0c2VydmljZUFjY291bnQ6ICAgICAgICAgIHVuZGVmaW5lZCxcblx0XHR0b2tlblJlZnJlc2hUaHJlc2hvbGQ6ICAgMTUgKiA2MCwgLy8gMTUgbWludXRlc1xuXHRcdHRva2VuU3RvcmU6ICAgICAgICAgICAgICB1bmRlZmluZWQsXG5cdFx0dG9rZW5TdG9yZURpcjogICAgICAgICAgIGxvY2F0aW9ucy5heHdheUhvbWUsXG5cdFx0dG9rZW5TdG9yZVR5cGU6ICAgICAgICAgIHVuZGVmaW5lZCxcblx0XHR1c2VybmFtZTogICAgICAgICAgICAgICAgdW5kZWZpbmVkXG5cdH07XG5cblx0Zm9yIChjb25zdCBwcm9wIG9mIE9iamVjdC5rZXlzKHByb3BzKSkge1xuXHRcdHBhcmFtc1twcm9wXSA9IG9wdHNbcHJvcF0gIT09IHVuZGVmaW5lZCA/IG9wdHNbcHJvcF0gOiBhd2FpdCBjb25maWcuZ2V0KGBhdXRoLiR7cHJvcH1gLCBwcm9wc1twcm9wXSk7XG5cdH1cblxuXHQvLyBkZXRlY3QgaWYgd2UncmUgaGVhZGxlc3MgYW5kIGRlZmF1bHQgdG9rZW4gc3RvcmUgdHlwZSB0byBgZmlsZWBcblx0aWYgKHBhcmFtcy50b2tlblN0b3JlVHlwZSA9PT0gdW5kZWZpbmVkICYmIGlzSGVhZGxlc3MoKSkge1xuXHRcdHBhcmFtcy50b2tlblN0b3JlVHlwZSA9ICdmaWxlJztcblx0XHRhd2FpdCBjb25maWcuc2V0KCdhdXRoLnRva2VuU3RvcmVUeXBlJywgJ2ZpbGUnKTtcblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgY29uZmlnLnNhdmUoKTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdHdhcm4oZXJyKTtcblx0XHR9XG5cdH1cblxuXHRwYXJhbXMucmVxdWVzdE9wdGlvbnMgPSBjcmVhdGVSZXF1ZXN0T3B0aW9ucyhvcHRzLCBjb25maWcpO1xuXG5cdHJldHVybiBwYXJhbXM7XG59XG5cbi8vIGBidWlsZFBhcmFtcygpYCBpcyB0b28gYW1iaWd1b3VzLCBzbyBpdCB3YXMgcmVuYW1lZCB0byBgYnVpbGRBdXRoUGFyYW1zKClgLCBidXQgd2Ugc3RpbGwgbmVlZCB0b1xuLy8gbWFpbnRhaW4gYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbmV4cG9ydCB7IGJ1aWxkQXV0aFBhcmFtcyBhcyBidWlsZFBhcmFtcyB9O1xuXG4vKipcbiAqIENoZWNrcyBpZiBhIG5ldyB2ZXJzaW9uIG9mIGFuIG5wbSBwYWNrYWdlIGlzIGF2YWlsYWJsZSBhbmQgcmV0dXJucyBhIHN0cmluZyB3aXRoIHRoZSBmb3JtYXR0ZWRcbiAqIHVwZGF0ZSBtZXNzYWdlLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0c10gLSBDaGVjayB1cGRhdGUgYW5kIHJlcXVlc3QgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRzLmNoZWNrSW50ZXJ2YWw9MzYwMDAwMF0gLSBUaGUgYW1vdW50IG9mIHRpbWUgaW4gbWlsbGlzZWNvbmRzIGJlZm9yZVxuICogY2hlY2tpbmcgZm9yIGFuIHVwZGF0ZS4gRGVmYXVsdHMgdG8gMSBob3VyLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRzLmN3ZF0gLSBUaGUgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSB1c2VkIHRvIGxvY2F0ZSB0aGUgYHBhY2thZ2UuanNvbmAgaWZcbiAqIGBwa2dgIGlzIG5vdCBzcGVjaWZpZWQuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdHMuZGlzdFRhZz0nbGF0ZXN0J10gLSBUaGUgdGFnIHRvIGNoZWNrIGZvciB0aGUgbGF0ZXN0IHZlcnNpb24uXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRzLmZvcmNlPWZhbHNlXSAtIEZvcmNlcyBhbiB1cGRhdGUgY2hlY2suXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdHMubWV0YURpcl0gLSBUaGUgZGlyZWN0b3J5IHRvIHN0b3JlIHBhY2thZ2UgdXBkYXRlIGluZm9ybWF0aW9uLlxuICogQHBhcmFtIHtPYmplY3R8U3RyaW5nfSBbb3B0cy5wa2ddIC0gVGhlIHBhcnNlZCBgcGFja2FnZS5qc29uYCwgcGF0aCB0byB0aGUgcGFja2FnZS5qc29uIGZpbGUsIG9yXG4gKiBmYWxzZXkgYW5kIGl0IHdpbGwgc2NhbiBwYXJlbnQgZGlyZWN0b3JpZXMgbG9va2luZyBmb3IgYSBwYWNrYWdlLmpzb24uXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdHMucmVnaXN0cnlVcmxdIC0gVGhlIG5wbSByZWdpc3RyeSBVUkwuIEJ5IGRlZmF1bHQsIGl0IHdpbGwgYXV0b2RldGVjdCB0aGVcbiAqIFVSTCBiYXNlZCBvbiB0aGUgcGFja2FnZSBuYW1lL3Njb3BlLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRzLnRpbWVvdXQ9MTAwMF0gLSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB3YWl0IHRvIHF1ZXJ5IG5wbSBiZWZvcmVcbiAqIHRpbWluZyBvdXQuXG4gKiBAcGFyYW0ge0NvbmZpZ30gW2NvbmZpZ10gLSBBbiBBbXBsaWZ5IENvbmZpZyBpbnN0YW5jZS4gSWYgbm90IHNwZWNpZmllZCwgdGhlIGNvbmZpZyBpcyBsb2FkZWRcbiAqIGZyb20gZGlzay5cbiAqIEByZXR1cm5zIHtTdHJpbmd9XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjaGVja0ZvclVwZGF0ZShvcHRzLCBjb25maWcpIHtcblx0b3B0cyA9IGNyZWF0ZVJlcXVlc3RPcHRpb25zKG9wdHMsIGNvbmZpZyB8fCBhd2FpdCBsb2FkQ29uZmlnKCkpO1xuXG5cdGNvbnN0IHtcblx0XHRjdXJyZW50LFxuXHRcdGxhdGVzdCxcblx0XHRuYW1lLFxuXHRcdHVwZGF0ZUF2YWlsYWJsZVxuXHR9ID0gYXdhaXQgY2hlY2sob3B0cyk7XG5cblx0aWYgKHVwZGF0ZUF2YWlsYWJsZSkge1xuXHRcdGNvbnN0IG1zZyA9IGBVcGRhdGUgYXZhaWxhYmxlICR7Z3JheShjdXJyZW50KX0g4oaSICR7Z3JlZW4obGF0ZXN0KX1cXG5SdW4gJHtjeWFuKGBucG0gaSAtZyAke25hbWV9YCl9IHRvIHVwZGF0ZWA7XG5cdFx0cmV0dXJuIGJveGVuKG1zZywge1xuXHRcdFx0YWxpZ246ICdjZW50ZXInLFxuXHRcdFx0Ym9yZGVyQ29sb3I6ICd5ZWxsb3cnLFxuXHRcdFx0Ym9yZGVyU3R5bGU6ICdyb3VuZCcsXG5cdFx0XHRtYXJnaW46IHsgYm90dG9tOiAxLCBsZWZ0OiA0LCByaWdodDogNCwgdG9wOiAxIH0sXG5cdFx0XHRwYWRkaW5nOiB7IGJvdHRvbTogMSwgbGVmdDogNCwgcmlnaHQ6IDQsIHRvcDogMSB9XG5cdFx0fSk7XG5cdH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgdGFibGUgd2l0aCBkZWZhdWx0IHN0eWxlcyBhbmQgcGFkZGluZy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5LjxTdHJpbmc+fSBoZWFkIC0gT25lIG9yIG1vcmUgaGVhZGluZ3MuXG4gKiBAcGFyYW0ge051bWJlcn0gW2luZGVudF0gLSBUaGUgbnVtYmVyIG9mIHNwYWNlcyB0byBpbmRlbnQgdGhlIHRhYmxlLlxuICogQHJldHVybnMge1RhYmxlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVGFibGUoaGVhZCwgaW5kZW50ID0gMCkge1xuXHRyZXR1cm4gbmV3IFRhYmxlKHtcblx0XHRjaGFyczoge1xuXHRcdFx0Ym90dG9tOiAnJywgJ2JvdHRvbS1sZWZ0JzogJycsICdib3R0b20tbWlkJzogJycsICdib3R0b20tcmlnaHQnOiAnJyxcblx0XHRcdGxlZnQ6ICcgJy5yZXBlYXQoaW5kZW50KSwgJ2xlZnQtbWlkJzogJycsXG5cdFx0XHRtaWQ6ICcnLCAnbWlkLW1pZCc6ICcnLCBtaWRkbGU6ICcgICcsXG5cdFx0XHRyaWdodDogJycsICdyaWdodC1taWQnOiAnJyxcblx0XHRcdHRvcDogJycsICd0b3AtbGVmdCc6ICcnLCAndG9wLW1pZCc6ICcnLCAndG9wLXJpZ2h0JzogJydcblx0XHR9LFxuXHRcdGhlYWQ6IEFycmF5LmlzQXJyYXkoaGVhZCkgPyBoZWFkLm1hcChhbnNpLnRvVXBwZXJDYXNlKSA6IGhlYWQsXG5cdFx0c3R5bGU6IHtcblx0XHRcdGJvcmRlcjogW10sXG5cdFx0XHRoZWFkOiBbXSxcblx0XHRcdCdwYWRkaW5nLWxlZnQnOiAwLFxuXHRcdFx0J3BhZGRpbmctcmlnaHQnOiAwXG5cdFx0fVxuXHR9KTtcbn1cblxuLyoqXG4gKiBSZXNvdmxlcyB0aGUgXCJhdXRoLipcIiBjb25maWcga2V5IGJhc2VkIG9uIHlvdXIgZW52aXJvbm1lbnQuIFRoaXMgaXMgdXNlZCB0byBnZXQgb3Igc2V0IHRoZVxuICogZGVmYXVsdCBhY2NvdW50IGFuZCBvcmcuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGVudiAtIFRoZSByZXNvbHZlZCBlbnZpcm9ubWVudCBuYW1lLlxuICogQHJldHVybnMge1N0cmluZ31cbiAqXG4gKiBAZXhhbXBsZVxuICogICBhd2FpdCBjb25maWcuZ2V0KGAke2dldEF1dGhDb25maWdFbnZTcGVjaWZpZXIoc2RrLmVudi5uYW1lKX0uZGVmYXVsdEFjY291bnRgKTtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEF1dGhDb25maWdFbnZTcGVjaWZpZXIoZW52KSB7XG5cdHJldHVybiAhZW52IHx8IGVudiA9PT0gJ3Byb2QnID8gJ2F1dGgnIDogYGF1dGguZW52aXJvbm1lbnQuJHtlbnZ9YDtcbn1cblxuLyoqXG4gKiBIaWdobGlnaHRzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdHdvIHZlcnNpb25zLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB0b1ZlciAtIFRoZSBsYXRlc3QgdmVyc2lvbi5cbiAqIEBwYXJhbSB7U3RyaW5nfSBmcm9tVmVyIC0gVGhlIGN1cnJlbnQgdmVyc2lvbi5cbiAqIEByZXR1cm5zIHtTdHJpbmd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBobFZlcih0b1ZlciwgZnJvbVZlcikge1xuXHRjb25zdCB7IGdyZWVuIH0gPSBzbm9vcGxvZ2cuc3R5bGVzO1xuXHRjb25zdCB2ZXJzaW9uID0gW107XG5cblx0bGV0IFsgZnJvbSwgZnJvbVRhZyBdID0gZnJvbVZlci5zcGxpdCgvLSguKykvKTtcblx0ZnJvbSA9IGZyb20ucmVwbGFjZSgvW14uXFxkXS9nLCAnJykuc3BsaXQoJy4nKS5tYXAoeCA9PiBwYXJzZUludCh4KSk7XG5cblx0bGV0IFsgdG8sIHRvVGFnIF0gPSB0b1Zlci5zcGxpdCgvLSguKykvKTtcblx0Y29uc3QgdG9NYXRjaCA9IHRvLm1hdGNoKC9eKFteXFxkXSspPyguKykkLyk7XG5cdHRvID0gKHRvTWF0Y2ggPyB0b01hdGNoWzJdIDogdG8pLnNwbGl0KCcuJykubWFwKHggPT4gcGFyc2VJbnQoeCkpO1xuXG5cdGNvbnN0IHRhZyA9ICgpID0+IHtcblx0XHRpZiAodG9UYWcpIHtcblx0XHRcdGNvbnN0IHRvTnVtID0gdG9UYWcubWF0Y2goL1xcZCskLyk7XG5cdFx0XHRjb25zdCBmcm9tTnVtID0gZnJvbVRhZyAmJiBmcm9tVGFnLm1hdGNoKC9cXGQrJC8pO1xuXHRcdFx0aWYgKGZyb21OdW0gJiYgcGFyc2VJbnQoZnJvbU51bVswXSkgPj0gcGFyc2VJbnQodG9OdW0pKSB7XG5cdFx0XHRcdHJldHVybiBgLSR7dG9UYWd9YDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiBncmVlbihgLSR7dG9UYWd9YCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAnJztcblx0fTtcblxuXHR3aGlsZSAodG8ubGVuZ3RoKSB7XG5cdFx0aWYgKHRvWzBdID4gZnJvbVswXSkge1xuXHRcdFx0aWYgKHZlcnNpb24ubGVuZ3RoKSB7XG5cdFx0XHRcdHJldHVybiAodG9NYXRjaCAmJiB0b01hdGNoWzFdIHx8ICcnKSArIHZlcnNpb24uY29uY2F0KGdyZWVuKHRvLmpvaW4oJy4nKSArIHRhZygpKSkuam9pbignLicpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGdyZWVuKCh0b01hdGNoICYmIHRvTWF0Y2hbMV0gfHwgJycpICsgdG8uam9pbignLicpICsgdGFnKCkpO1xuXHRcdH1cblx0XHR2ZXJzaW9uLnB1c2godG8uc2hpZnQoKSk7XG5cdFx0ZnJvbS5zaGlmdCgpO1xuXHR9XG5cblx0cmV0dXJuICh0b01hdGNoICYmIHRvTWF0Y2hbMV0gfHwgJycpICsgdmVyc2lvbi5qb2luKCcuJykgKyB0YWcoKTtcbn1cblxuLyoqXG4gKiBJbml0aWFsaXplcyB0aGUgQW1wbGlmeSBTREssIGxvYWRzIGFuIGFjY291bnQsIGFuZCBmaW5kcyB0aGUgZGVmYXVsdCBvcmcgaWQuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IFthY2NvdW50TmFtZV0gLSBUaGUgbmFtZSBvZiB0aGUgcGxhdGZvcm0gYWNjb3VudCB0byB1c2UuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29yZ10gLSBUaGUgbmFtZSwgaWQsIG9yIGd1aWQgb2YgdGhlIGRlZmF1bHQgb3JnYW5pemF0aW9uLlxuICogQHBhcmFtIHtTdHJpbmd9IFtlbnZdIC0gVGhlIGVudmlyb25tZW50IG5hbWUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtieXBhc3NQbGF0Zm9ybUFjY291bnRDaGVja10gLSBPcHRpb25hbCBwYXJhbWV0ZXIgdG8gYnlwYXNzIGNoZWNrIGlmIHRoZSBhY2NvdW50IGlzIHBsYXRmb3JtXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5pdFBsYXRmb3JtQWNjb3VudChhY2NvdW50TmFtZSwgb3JnLCBlbnYsIGJ5cGFzc1BsYXRmb3JtQWNjb3VudENoZWNrID0gZmFsc2UpIHtcblx0Y29uc3QgeyBjb25maWcsIHNkayB9ID0gYXdhaXQgaW5pdFNESyh7IGVudiB9KTtcblx0Y29uc3QgYXV0aENvbmZpZ0VudlNwZWNpZmllciA9IGdldEF1dGhDb25maWdFbnZTcGVjaWZpZXIoc2RrLmVudi5uYW1lKTtcblx0Y29uc3QgYWNjb3VudCA9IGF3YWl0IHNkay5hdXRoLmZpbmQoYWNjb3VudE5hbWUgfHwgYXdhaXQgY29uZmlnLmdldChgJHthdXRoQ29uZmlnRW52U3BlY2lmaWVyfS5kZWZhdWx0QWNjb3VudGApKTtcblxuXHRpZiAoYWNjb3VudE5hbWUpIHtcblx0XHRpZiAoIWFjY291bnQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgQWNjb3VudCBcIiR7YWNjb3VudE5hbWV9XCIgbm90IGZvdW5kYCk7XG5cdFx0fSBlbHNlIGlmICghYnlwYXNzUGxhdGZvcm1BY2NvdW50Q2hlY2sgJiYgIWFjY291bnQuaXNQbGF0Zm9ybSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBBY2NvdW50IFwiJHthY2NvdW50TmFtZX1cIiBpcyBub3QgYSBwbGF0Zm9ybSBhY2NvdW50XFxuXFxuVG8gbG9naW4sIHJ1bjogYXh3YXkgYXV0aCBsb2dpbmApO1xuXHRcdH1cblx0fSBlbHNlIGlmICghYWNjb3VudCB8fCAoIWJ5cGFzc1BsYXRmb3JtQWNjb3VudENoZWNrICYmICFhY2NvdW50LmlzUGxhdGZvcm0pKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdZb3UgbXVzdCBiZSBsb2dnZWQgaW50byBhIHBsYXRmb3JtIGFjY291bnRcXG5cXG5UbyBsb2dpbiwgcnVuOiBheHdheSBhdXRoIGxvZ2luJyk7XG5cdH1cblxuXHRpZiAob3JnKSB7XG5cdFx0b3JnID0gYXdhaXQgc2RrLm9yZy5maW5kKGFjY291bnQsIG9yZyk7XG5cdH0gZWxzZSB7XG5cdFx0dHJ5IHtcblx0XHRcdC8vIGNoZWNrIHRoZSBjb25maWcgZm9yIGEgZGVmYXVsdCBvcmcgZm9yIHRoaXMgYWNjb3VudFxuXHRcdFx0b3JnID0gYXdhaXQgc2RrLm9yZy5maW5kKGFjY291bnQsIGF3YWl0IGNvbmZpZy5nZXQoYCR7YXV0aENvbmZpZ0VudlNwZWNpZmllcn0uZGVmYXVsdE9yZy4ke2FjY291bnQuaGFzaH1gKSk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHQvLyBkZWZhdWx0IG9yZyB3YXMgc3RhbGUsIGF1dG8gZGV0ZWN0IHRoZSBkZWZhdWx0IGZyb20gdGhlIGFjY291bnQgb3Jnc1xuXHRcdFx0b3JnID0gYXdhaXQgc2RrLm9yZy5maW5kKGFjY291bnQpO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiB7XG5cdFx0YWNjb3VudCxcblx0XHRjb25maWcsXG5cdFx0b3JnLFxuXHRcdHNka1xuXHR9O1xufVxuXG4vKipcbiAqIExvYWRzIHRoZSBjb25maWcgYW5kIGNyZWF0ZXMgYW4gQW1wbGlmeSBTREsgb2JqZWN0LCB0aGVuIHJldHVybnMgYm90aCBvZiB0aGVtLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0c10gLSBTREsgb3B0aW9ucyBpbmNsdWRpbmcgYGVudmAgYW5kIGF1dGggb3B0aW9ucy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbY29uZmlnXSAtIFRoZSBBbXBsaWZ5IGF3YWl0IGNvbmZpZy4gSWYgbm90IHBhc3NlZCBpbiwgdGhlIGNvbmZpZyBmaWxlIGlzIGxvYWRlZC5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIEF4d2F5IENMSSBjb25maWcgYW5kIGFuIGluaXRpYWxpemVkXG4gKiBBbXBsaWZ5IFNESyBpbnN0YW5jZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluaXRTREsob3B0cyA9IHt9LCBjb25maWcpIHtcblx0aWYgKCFjb25maWcpIHtcblx0XHRjb25maWcgPSBhd2FpdCBsb2FkQ29uZmlnKCk7XG5cdH1cblx0cmV0dXJuIHtcblx0XHRjb25maWcsXG5cdFx0c2RrOiBuZXcgQW1wbGlmeVNESyhhd2FpdCBidWlsZEF1dGhQYXJhbXMob3B0cywgY29uZmlnKSlcblx0fTtcbn1cblxuLyoqXG4gKiBEZXRlY3RzIGlmIHRoZSBjdXJyZW50IHRlcm1pbmFsIGlzIGhlYWRsZXNzIChlLmcuIGEgRG9ja2VyIGNvbnRhaW5lciBvciBTU0ggc2Vzc2lvbikuXG4gKlxuICogQHJldHVybnMge0Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0hlYWRsZXNzKCkge1xuXHR0cnkge1xuXHRcdGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnbGludXgnICYmIChwcm9jZXNzLmVudi5TU0hfVFRZIHx8ICFwcm9jZXNzLmVudi5ESVNQTEFZIHx8IC9kb2NrZXJ8bHhjLy50ZXN0KGZzLnJlYWRGaWxlU3luYygnL3Byb2MvMS9jZ3JvdXAnLCAndXRmOCcpKSkpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ2RhcndpbicgJiYgcHJvY2Vzcy5lbnYuU1NIX1RUWSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHR9IGNhdGNoIChlKSB7XG5cdFx0Ly8gZG8gbm90aGluZ1xuXHR9XG5cblx0cmV0dXJuIGZhbHNlO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7O0FBTUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7Ozs7Ozs7QUFqQkE7QUFDQSxJQUFJLENBQUNBLEtBQUssQ0FBQ0MsaUJBQVgsRUFBOEI7RUFDN0JDLDBCQUFpQkMsT0FBakI7QUFDQTs7QUE4QkQsTUFBTTtFQUFFQztBQUFGLElBQVcsd0JBQVUsbUJBQVYsQ0FBakI7QUFDQSxNQUFNO0VBQUVDLElBQUY7RUFBUUMsSUFBUjtFQUFjQztBQUFkLElBQXdCQyxtQkFBVUMsS0FBeEM7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDTyxlQUFlQyxlQUFmLENBQStCQyxJQUFJLEdBQUcsRUFBdEMsRUFBMENDLE1BQTFDLEVBQWtEO0VBQ3hELElBQUksQ0FBQ0QsSUFBRCxJQUFTLE9BQU9BLElBQVAsS0FBZ0IsUUFBN0IsRUFBdUM7SUFDdEMsTUFBTSxJQUFJWCxLQUFKLENBQVUsa0NBQVYsQ0FBTjtFQUNBOztFQUVELElBQUksQ0FBQ1ksTUFBTCxFQUFhO0lBQ1pBLE1BQU0sR0FBRyxNQUFNLDZCQUFmO0VBQ0E7O0VBRUQsTUFBTUMsR0FBRyxHQUFHQyxZQUFZLENBQUNDLE9BQWIsQ0FBcUJKLElBQUksQ0FBQ0UsR0FBTCxLQUFZLE1BQU1ELE1BQU0sQ0FBQ0ksR0FBUCxDQUFXLEtBQVgsQ0FBbEIsQ0FBckIsQ0FBWjtFQUVBLE1BQU07SUFBRUMsUUFBRjtJQUFZQztFQUFaLElBQXNCTCxHQUFHLENBQUNNLElBQWhDO0VBQ0EsTUFBTUMsTUFBTSxHQUFHLEVBQWY7RUFDQSxNQUFNQyxLQUFLLEdBQUc7SUFDYkMsT0FBTyxFQUFrQkMsU0FEWjtJQUViTixRQUZhO0lBR2JPLFlBQVksRUFBYUQsU0FIWjtJQUliVixHQUFHLEVBQXNCQSxHQUFHLENBQUNZLElBSmhCO0lBS2JDLHVCQUF1QixFQUFFSCxTQUxaO0lBTWJJLE9BQU8sRUFBa0JDLFNBQVMsQ0FBQ0MsU0FOdEI7SUFPYkMsUUFBUSxFQUFpQlAsU0FQWjtJQVFiUSxjQUFjLEVBQVdSLFNBUlo7SUFTYlMsV0FBVyxFQUFjVCxTQVRaO0lBVWJMLEtBVmE7SUFXYmUsVUFBVSxFQUFlVixTQVhaO0lBWWJXLFVBQVUsRUFBZVgsU0FaWjtJQWFiWSxVQUFVLEVBQWVaLFNBYlo7SUFjYmEsY0FBYyxFQUFXYixTQWRaO0lBZWJjLHFCQUFxQixFQUFJLEtBQUssRUFmakI7SUFlcUI7SUFDbENDLFVBQVUsRUFBZWYsU0FoQlo7SUFpQmJnQixhQUFhLEVBQVlYLFNBQVMsQ0FBQ0MsU0FqQnRCO0lBa0JiVyxjQUFjLEVBQVdqQixTQWxCWjtJQW1CYmtCLFFBQVEsRUFBaUJsQjtFQW5CWixDQUFkOztFQXNCQSxLQUFLLE1BQU1tQixJQUFYLElBQW1CQyxNQUFNLENBQUNDLElBQVAsQ0FBWXZCLEtBQVosQ0FBbkIsRUFBdUM7SUFDdENELE1BQU0sQ0FBQ3NCLElBQUQsQ0FBTixHQUFlL0IsSUFBSSxDQUFDK0IsSUFBRCxDQUFKLEtBQWVuQixTQUFmLEdBQTJCWixJQUFJLENBQUMrQixJQUFELENBQS9CLEdBQXdDLE1BQU05QixNQUFNLENBQUNJLEdBQVAsQ0FBWSxRQUFPMEIsSUFBSyxFQUF4QixFQUEyQnJCLEtBQUssQ0FBQ3FCLElBQUQsQ0FBaEMsQ0FBN0Q7RUFDQSxDQXJDdUQsQ0F1Q3hEOzs7RUFDQSxJQUFJdEIsTUFBTSxDQUFDb0IsY0FBUCxLQUEwQmpCLFNBQTFCLElBQXVDc0IsVUFBVSxFQUFyRCxFQUF5RDtJQUN4RHpCLE1BQU0sQ0FBQ29CLGNBQVAsR0FBd0IsTUFBeEI7SUFDQSxNQUFNNUIsTUFBTSxDQUFDa0MsR0FBUCxDQUFXLHFCQUFYLEVBQWtDLE1BQWxDLENBQU47O0lBQ0EsSUFBSTtNQUNILE1BQU1sQyxNQUFNLENBQUNtQyxJQUFQLEVBQU47SUFDQSxDQUZELENBRUUsT0FBT0MsR0FBUCxFQUFZO01BQ2I1QyxJQUFJLENBQUM0QyxHQUFELENBQUo7SUFDQTtFQUNEOztFQUVENUIsTUFBTSxDQUFDNkIsY0FBUCxHQUF3QixtQ0FBcUJ0QyxJQUFyQixFQUEyQkMsTUFBM0IsQ0FBeEI7RUFFQSxPQUFPUSxNQUFQO0FBQ0EsQyxDQUVEO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sZUFBZThCLGNBQWYsQ0FBOEJ2QyxJQUE5QixFQUFvQ0MsTUFBcEMsRUFBNEM7RUFDbERELElBQUksR0FBRyxtQ0FBcUJBLElBQXJCLEVBQTJCQyxNQUFNLEtBQUksTUFBTSw2QkFBVixDQUFqQyxDQUFQO0VBRUEsTUFBTTtJQUNMdUMsT0FESztJQUVMQyxNQUZLO0lBR0wzQixJQUhLO0lBSUw0QjtFQUpLLElBS0YsTUFBTSx1QkFBTTFDLElBQU4sQ0FMVjs7RUFPQSxJQUFJMEMsZUFBSixFQUFxQjtJQUNwQixNQUFNQyxHQUFHLEdBQUksb0JBQW1CaEQsSUFBSSxDQUFDNkMsT0FBRCxDQUFVLE1BQUs1QyxLQUFLLENBQUM2QyxNQUFELENBQVMsU0FBUS9DLElBQUksQ0FBRSxZQUFXb0IsSUFBSyxFQUFsQixDQUFxQixZQUFsRztJQUNBLE9BQU8sb0JBQU02QixHQUFOLEVBQVc7TUFDakJDLEtBQUssRUFBRSxRQURVO01BRWpCQyxXQUFXLEVBQUUsUUFGSTtNQUdqQkMsV0FBVyxFQUFFLE9BSEk7TUFJakJDLE1BQU0sRUFBRTtRQUFFQyxNQUFNLEVBQUUsQ0FBVjtRQUFhQyxJQUFJLEVBQUUsQ0FBbkI7UUFBc0JDLEtBQUssRUFBRSxDQUE3QjtRQUFnQ0MsR0FBRyxFQUFFO01BQXJDLENBSlM7TUFLakJDLE9BQU8sRUFBRTtRQUFFSixNQUFNLEVBQUUsQ0FBVjtRQUFhQyxJQUFJLEVBQUUsQ0FBbkI7UUFBc0JDLEtBQUssRUFBRSxDQUE3QjtRQUFnQ0MsR0FBRyxFQUFFO01BQXJDO0lBTFEsQ0FBWCxDQUFQO0VBT0E7QUFDRDtBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTRSxXQUFULENBQXFCQyxJQUFyQixFQUEyQkMsTUFBTSxHQUFHLENBQXBDLEVBQXVDO0VBQzdDLE9BQU8sSUFBSUMsaUJBQUosQ0FBVTtJQUNoQkMsS0FBSyxFQUFFO01BQ05ULE1BQU0sRUFBRSxFQURGO01BQ00sZUFBZSxFQURyQjtNQUN5QixjQUFjLEVBRHZDO01BQzJDLGdCQUFnQixFQUQzRDtNQUVOQyxJQUFJLEVBQUUsSUFBSVMsTUFBSixDQUFXSCxNQUFYLENBRkE7TUFFb0IsWUFBWSxFQUZoQztNQUdOSSxHQUFHLEVBQUUsRUFIQztNQUdHLFdBQVcsRUFIZDtNQUdrQkMsTUFBTSxFQUFFLElBSDFCO01BSU5WLEtBQUssRUFBRSxFQUpEO01BSUssYUFBYSxFQUpsQjtNQUtOQyxHQUFHLEVBQUUsRUFMQztNQUtHLFlBQVksRUFMZjtNQUttQixXQUFXLEVBTDlCO01BS2tDLGFBQWE7SUFML0MsQ0FEUztJQVFoQkcsSUFBSSxFQUFFTyxLQUFLLENBQUNDLE9BQU4sQ0FBY1IsSUFBZCxJQUFzQkEsSUFBSSxDQUFDUyxHQUFMLENBQVNDLGFBQUtDLFdBQWQsQ0FBdEIsR0FBbURYLElBUnpDO0lBU2hCWSxLQUFLLEVBQUU7TUFDTkMsTUFBTSxFQUFFLEVBREY7TUFFTmIsSUFBSSxFQUFFLEVBRkE7TUFHTixnQkFBZ0IsQ0FIVjtNQUlOLGlCQUFpQjtJQUpYO0VBVFMsQ0FBVixDQUFQO0FBZ0JBO0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNPLFNBQVNjLHlCQUFULENBQW1DbEUsR0FBbkMsRUFBd0M7RUFDOUMsT0FBTyxDQUFDQSxHQUFELElBQVFBLEdBQUcsS0FBSyxNQUFoQixHQUF5QixNQUF6QixHQUFtQyxvQkFBbUJBLEdBQUksRUFBakU7QUFDQTtBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTbUUsS0FBVCxDQUFlQyxLQUFmLEVBQXNCQyxPQUF0QixFQUErQjtFQUNyQyxNQUFNO0lBQUUzRTtFQUFGLElBQVlDLG1CQUFVMkUsTUFBNUI7RUFDQSxNQUFNQyxPQUFPLEdBQUcsRUFBaEI7RUFFQSxJQUFJLENBQUVDLElBQUYsRUFBUUMsT0FBUixJQUFvQkosT0FBTyxDQUFDSyxLQUFSLENBQWMsT0FBZCxDQUF4QjtFQUNBRixJQUFJLEdBQUdBLElBQUksQ0FBQ0csT0FBTCxDQUFhLFNBQWIsRUFBd0IsRUFBeEIsRUFBNEJELEtBQTVCLENBQWtDLEdBQWxDLEVBQXVDYixHQUF2QyxDQUEyQ2UsQ0FBQyxJQUFJQyxRQUFRLENBQUNELENBQUQsQ0FBeEQsQ0FBUDtFQUVBLElBQUksQ0FBRUUsRUFBRixFQUFNQyxLQUFOLElBQWdCWCxLQUFLLENBQUNNLEtBQU4sQ0FBWSxPQUFaLENBQXBCO0VBQ0EsTUFBTU0sT0FBTyxHQUFHRixFQUFFLENBQUNHLEtBQUgsQ0FBUyxpQkFBVCxDQUFoQjtFQUNBSCxFQUFFLEdBQUcsQ0FBQ0UsT0FBTyxHQUFHQSxPQUFPLENBQUMsQ0FBRCxDQUFWLEdBQWdCRixFQUF4QixFQUE0QkosS0FBNUIsQ0FBa0MsR0FBbEMsRUFBdUNiLEdBQXZDLENBQTJDZSxDQUFDLElBQUlDLFFBQVEsQ0FBQ0QsQ0FBRCxDQUF4RCxDQUFMOztFQUVBLE1BQU1NLEdBQUcsR0FBRyxNQUFNO0lBQ2pCLElBQUlILEtBQUosRUFBVztNQUNWLE1BQU1JLEtBQUssR0FBR0osS0FBSyxDQUFDRSxLQUFOLENBQVksTUFBWixDQUFkO01BQ0EsTUFBTUcsT0FBTyxHQUFHWCxPQUFPLElBQUlBLE9BQU8sQ0FBQ1EsS0FBUixDQUFjLE1BQWQsQ0FBM0I7O01BQ0EsSUFBSUcsT0FBTyxJQUFJUCxRQUFRLENBQUNPLE9BQU8sQ0FBQyxDQUFELENBQVIsQ0FBUixJQUF3QlAsUUFBUSxDQUFDTSxLQUFELENBQS9DLEVBQXdEO1FBQ3ZELE9BQVEsSUFBR0osS0FBTSxFQUFqQjtNQUNBLENBRkQsTUFFTztRQUNOLE9BQU9yRixLQUFLLENBQUUsSUFBR3FGLEtBQU0sRUFBWCxDQUFaO01BQ0E7SUFDRDs7SUFDRCxPQUFPLEVBQVA7RUFDQSxDQVhEOztFQWFBLE9BQU9ELEVBQUUsQ0FBQ08sTUFBVixFQUFrQjtJQUNqQixJQUFJUCxFQUFFLENBQUMsQ0FBRCxDQUFGLEdBQVFOLElBQUksQ0FBQyxDQUFELENBQWhCLEVBQXFCO01BQ3BCLElBQUlELE9BQU8sQ0FBQ2MsTUFBWixFQUFvQjtRQUNuQixPQUFPLENBQUNMLE9BQU8sSUFBSUEsT0FBTyxDQUFDLENBQUQsQ0FBbEIsSUFBeUIsRUFBMUIsSUFBZ0NULE9BQU8sQ0FBQ2UsTUFBUixDQUFlNUYsS0FBSyxDQUFDb0YsRUFBRSxDQUFDUyxJQUFILENBQVEsR0FBUixJQUFlTCxHQUFHLEVBQW5CLENBQXBCLEVBQTRDSyxJQUE1QyxDQUFpRCxHQUFqRCxDQUF2QztNQUNBOztNQUNELE9BQU83RixLQUFLLENBQUMsQ0FBQ3NGLE9BQU8sSUFBSUEsT0FBTyxDQUFDLENBQUQsQ0FBbEIsSUFBeUIsRUFBMUIsSUFBZ0NGLEVBQUUsQ0FBQ1MsSUFBSCxDQUFRLEdBQVIsQ0FBaEMsR0FBK0NMLEdBQUcsRUFBbkQsQ0FBWjtJQUNBOztJQUNEWCxPQUFPLENBQUNpQixJQUFSLENBQWFWLEVBQUUsQ0FBQ1csS0FBSCxFQUFiO0lBQ0FqQixJQUFJLENBQUNpQixLQUFMO0VBQ0E7O0VBRUQsT0FBTyxDQUFDVCxPQUFPLElBQUlBLE9BQU8sQ0FBQyxDQUFELENBQWxCLElBQXlCLEVBQTFCLElBQWdDVCxPQUFPLENBQUNnQixJQUFSLENBQWEsR0FBYixDQUFoQyxHQUFvREwsR0FBRyxFQUE5RDtBQUNBO0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxlQUFlUSxtQkFBZixDQUFtQ0MsV0FBbkMsRUFBZ0RDLEdBQWhELEVBQXFENUYsR0FBckQsRUFBMEQ2RiwwQkFBMEIsR0FBRyxLQUF2RixFQUE4RjtFQUNwRyxNQUFNO0lBQUU5RixNQUFGO0lBQVUrRjtFQUFWLElBQWtCLE1BQU1DLE9BQU8sQ0FBQztJQUFFL0Y7RUFBRixDQUFELENBQXJDO0VBQ0EsTUFBTWdHLHNCQUFzQixHQUFHOUIseUJBQXlCLENBQUM0QixHQUFHLENBQUM5RixHQUFKLENBQVFZLElBQVQsQ0FBeEQ7RUFDQSxNQUFNcUYsT0FBTyxHQUFHLE1BQU1ILEdBQUcsQ0FBQ3hGLElBQUosQ0FBUzRGLElBQVQsQ0FBY1AsV0FBVyxLQUFJLE1BQU01RixNQUFNLENBQUNJLEdBQVAsQ0FBWSxHQUFFNkYsc0JBQXVCLGlCQUFyQyxDQUFWLENBQXpCLENBQXRCOztFQUVBLElBQUlMLFdBQUosRUFBaUI7SUFDaEIsSUFBSSxDQUFDTSxPQUFMLEVBQWM7TUFDYixNQUFNLElBQUk5RyxLQUFKLENBQVcsWUFBV3dHLFdBQVksYUFBbEMsQ0FBTjtJQUNBLENBRkQsTUFFTyxJQUFJLENBQUNFLDBCQUFELElBQStCLENBQUNJLE9BQU8sQ0FBQ0UsVUFBNUMsRUFBd0Q7TUFDOUQsTUFBTSxJQUFJaEgsS0FBSixDQUFXLFlBQVd3RyxXQUFZLGdFQUFsQyxDQUFOO0lBQ0E7RUFDRCxDQU5ELE1BTU8sSUFBSSxDQUFDTSxPQUFELElBQWEsQ0FBQ0osMEJBQUQsSUFBK0IsQ0FBQ0ksT0FBTyxDQUFDRSxVQUF6RCxFQUFzRTtJQUM1RSxNQUFNLElBQUloSCxLQUFKLENBQVUsK0VBQVYsQ0FBTjtFQUNBOztFQUVELElBQUl5RyxHQUFKLEVBQVM7SUFDUkEsR0FBRyxHQUFHLE1BQU1FLEdBQUcsQ0FBQ0YsR0FBSixDQUFRTSxJQUFSLENBQWFELE9BQWIsRUFBc0JMLEdBQXRCLENBQVo7RUFDQSxDQUZELE1BRU87SUFDTixJQUFJO01BQ0g7TUFDQUEsR0FBRyxHQUFHLE1BQU1FLEdBQUcsQ0FBQ0YsR0FBSixDQUFRTSxJQUFSLENBQWFELE9BQWIsRUFBc0IsTUFBTWxHLE1BQU0sQ0FBQ0ksR0FBUCxDQUFZLEdBQUU2RixzQkFBdUIsZUFBY0MsT0FBTyxDQUFDRyxJQUFLLEVBQWhFLENBQTVCLENBQVo7SUFDQSxDQUhELENBR0UsT0FBT2pFLEdBQVAsRUFBWTtNQUNiO01BQ0F5RCxHQUFHLEdBQUcsTUFBTUUsR0FBRyxDQUFDRixHQUFKLENBQVFNLElBQVIsQ0FBYUQsT0FBYixDQUFaO0lBQ0E7RUFDRDs7RUFFRCxPQUFPO0lBQ05BLE9BRE07SUFFTmxHLE1BRk07SUFHTjZGLEdBSE07SUFJTkU7RUFKTSxDQUFQO0FBTUE7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxlQUFlQyxPQUFmLENBQXVCakcsSUFBSSxHQUFHLEVBQTlCLEVBQWtDQyxNQUFsQyxFQUEwQztFQUNoRCxJQUFJLENBQUNBLE1BQUwsRUFBYTtJQUNaQSxNQUFNLEdBQUcsTUFBTSw2QkFBZjtFQUNBOztFQUNELE9BQU87SUFDTkEsTUFETTtJQUVOK0YsR0FBRyxFQUFFLElBQUlPLG1CQUFKLENBQWUsTUFBTXhHLGVBQWUsQ0FBQ0MsSUFBRCxFQUFPQyxNQUFQLENBQXBDO0VBRkMsQ0FBUDtBQUlBO0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU2lDLFVBQVQsR0FBc0I7RUFDNUIsSUFBSTtJQUNILElBQUlzRSxPQUFPLENBQUNDLFFBQVIsS0FBcUIsT0FBckIsS0FBaUNELE9BQU8sQ0FBQ3RHLEdBQVIsQ0FBWXdHLE9BQVosSUFBdUIsQ0FBQ0YsT0FBTyxDQUFDdEcsR0FBUixDQUFZeUcsT0FBcEMsSUFBK0MsYUFBYUMsSUFBYixDQUFrQkMsWUFBR0MsWUFBSCxDQUFnQixnQkFBaEIsRUFBa0MsTUFBbEMsQ0FBbEIsQ0FBaEYsQ0FBSixFQUFtSjtNQUNsSixPQUFPLElBQVA7SUFDQTs7SUFDRCxJQUFJTixPQUFPLENBQUNDLFFBQVIsS0FBcUIsUUFBckIsSUFBaUNELE9BQU8sQ0FBQ3RHLEdBQVIsQ0FBWXdHLE9BQWpELEVBQTBEO01BQ3pELE9BQU8sSUFBUDtJQUNBO0VBQ0QsQ0FQRCxDQU9FLE9BQU9LLENBQVAsRUFBVSxDQUNYO0VBQ0E7O0VBRUQsT0FBTyxLQUFQO0FBQ0EifQ==