UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

269 lines 34.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NoticeFilter = exports.CachedDataSource = exports.WebsiteNoticeDataSource = exports.formatNotices = exports.filterNotices = exports.generateMessage = exports.displayNotices = exports.refreshNotices = void 0; const https = require("https"); const path = require("path"); const fs = require("fs-extra"); const semver = require("semver"); const logging_1 = require("./logging"); const tree_1 = require("./tree"); const util_1 = require("./util"); const directories_1 = require("./util/directories"); const version_1 = require("./version"); const CACHE_FILE_PATH = path.join((0, directories_1.cdkCacheDir)(), 'notices.json'); async function refreshNotices() { const dataSource = dataSourceReference(false); return dataSource.fetch(); } exports.refreshNotices = refreshNotices; async function displayNotices(props) { const dataSource = dataSourceReference(props.ignoreCache ?? false); (0, logging_1.print)(await generateMessage(dataSource, props)); return 0; } exports.displayNotices = displayNotices; async function generateMessage(dataSource, props) { const data = await dataSource.fetch(); const filteredNotices = filterNotices(data, { outdir: props.outdir, acknowledgedIssueNumbers: new Set(props.acknowledgedIssueNumbers), }); if (filteredNotices.length > 0) { const individualMessages = formatNotices(filteredNotices); return finalMessage(individualMessages, filteredNotices[0].issueNumber); } return ''; } exports.generateMessage = generateMessage; function dataSourceReference(ignoreCache) { return new CachedDataSource(CACHE_FILE_PATH, new WebsiteNoticeDataSource(), ignoreCache); } function finalMessage(individualMessages, exampleNumber) { return [ '\nNOTICES (What\'s this? https://github.com/aws/aws-cdk/wiki/CLI-Notices)', ...individualMessages, `If you don’t want to see a notice anymore, use "cdk acknowledge <id>". For example, "cdk acknowledge ${exampleNumber}".`, ].join('\n\n'); } function filterNotices(data, options) { const filter = new NoticeFilter({ cliVersion: options.cliVersion ?? (0, version_1.versionNumber)(), acknowledgedIssueNumbers: options.acknowledgedIssueNumbers ?? new Set(), tree: (0, tree_1.loadTreeFromDir)(options.outdir ?? 'cdk.out'), }); return data.filter(notice => filter.apply(notice)); } exports.filterNotices = filterNotices; function formatNotices(data) { return data.map(formatNotice); } exports.formatNotices = formatNotices; class WebsiteNoticeDataSource { fetch() { const timeout = 3000; return new Promise((resolve, reject) => { let req; let timer = setTimeout(() => { if (req) { req.destroy(new Error('Request timed out')); } }, timeout); timer.unref(); try { req = https.get('https://cli.cdk.dev-tools.aws.dev/notices.json', res => { if (res.statusCode === 200) { res.setEncoding('utf8'); let rawData = ''; res.on('data', (chunk) => { rawData += chunk; }); res.on('end', () => { try { const data = JSON.parse(rawData).notices; if (!data) { throw new Error("'notices' key is missing"); } (0, logging_1.debug)('Notices refreshed'); resolve(data ?? []); } catch (e) { reject(new Error(`Failed to parse notices: ${e.message}`)); } }); res.on('error', e => { reject(new Error(`Failed to fetch notices: ${e.message}`)); }); } else { reject(new Error(`Failed to fetch notices. Status code: ${res.statusCode}`)); } }); req.on('error', reject); } catch (e) { reject(new Error(`HTTPS 'get' call threw an error: ${e.message}`)); } }); } } exports.WebsiteNoticeDataSource = WebsiteNoticeDataSource; const TIME_TO_LIVE_SUCCESS = 60 * 60 * 1000; // 1 hour const TIME_TO_LIVE_ERROR = 1 * 60 * 1000; // 1 minute class CachedDataSource { constructor(fileName, dataSource, skipCache) { this.fileName = fileName; this.dataSource = dataSource; this.skipCache = skipCache; } async fetch() { const cachedData = await this.load(); const data = cachedData.notices; const expiration = cachedData.expiration ?? 0; if (Date.now() > expiration || this.skipCache) { const freshData = await this.fetchInner(); await this.save(freshData); return freshData.notices; } else { (0, logging_1.debug)(`Reading cached notices from ${this.fileName}`); return data; } } async fetchInner() { try { return { expiration: Date.now() + TIME_TO_LIVE_SUCCESS, notices: await this.dataSource.fetch(), }; } catch (e) { (0, logging_1.debug)(`Could not refresh notices: ${e}`); return { expiration: Date.now() + TIME_TO_LIVE_ERROR, notices: [], }; } } async load() { const defaultValue = { expiration: 0, notices: [], }; try { return fs.existsSync(this.fileName) ? await fs.readJSON(this.fileName) : defaultValue; } catch (e) { (0, logging_1.debug)(`Failed to load notices from cache: ${e}`); return defaultValue; } } async save(cached) { try { await fs.writeJSON(this.fileName, cached); } catch (e) { (0, logging_1.debug)(`Failed to store notices in the cache: ${e}`); } } } exports.CachedDataSource = CachedDataSource; class NoticeFilter { constructor(props) { this.props = props; this.acknowledgedIssueNumbers = props.acknowledgedIssueNumbers; } /** * Returns true iff we should show this notice. */ apply(notice) { if (this.acknowledgedIssueNumbers.has(notice.issueNumber)) { return false; } return this.applyVersion(notice, 'cli', this.props.cliVersion) || match(resolveAliases(notice.components), this.props.tree); } /** * Returns true iff we should show the notice. */ applyVersion(notice, name, compareToVersion) { if (compareToVersion === undefined) { return false; } const affectedComponent = notice.components.find(component => component.name === name); const affectedRange = affectedComponent?.version; return affectedRange != null && semver.satisfies(compareToVersion, affectedRange); } } exports.NoticeFilter = NoticeFilter; /** * Some component names are aliases to actual component names. For example "framework" * is an alias for either the core library (v1) or the whole CDK library (v2). * * This function converts all aliases to their actual counterpart names, to be used to * match against the construct tree. * * @param components a list of components. Components whose name is an alias will be * transformed and all others will be left intact. */ function resolveAliases(components) { return (0, util_1.flatMap)(components, component => { if (component.name === 'framework') { return [{ name: '@aws-cdk/core.', version: component.version, }, { name: 'aws-cdk-lib.', version: component.version, }]; } else { return [component]; } }); } function formatNotice(notice) { const componentsValue = notice.components.map(c => `${c.name}: ${c.version}`).join(', '); return [ `${notice.issueNumber}\t${notice.title}`, formatOverview(notice.overview), `\tAffected versions: ${componentsValue}`, `\tMore information at: https://github.com/aws/aws-cdk/issues/${notice.issueNumber}`, ].join('\n\n') + '\n'; } function formatOverview(text) { const wrap = (s) => s.replace(/(?![^\n]{1,60}$)([^\n]{1,60})\s/g, '$1\n'); const heading = 'Overview: '; const separator = `\n\t${' '.repeat(heading.length)}`; const content = wrap(text) .split('\n') .join(separator); return '\t' + heading + content; } /** * Whether any component in the tree matches any component in the query. * A match happens when: * * 1. The version of the node matches the version in the query, interpreted * as a semver range. * * 2. The name in the query is a prefix of the node name when the query ends in '.', * or the two names are exactly the same, otherwise. */ function match(query, tree) { return (0, tree_1.some)(tree, node => { return query.some(component => compareNames(component.name, node.constructInfo?.fqn) && compareVersions(component.version, node.constructInfo?.version)); }); function compareNames(pattern, target) { if (target == null) { return false; } return pattern.endsWith('.') ? target.startsWith(pattern) : pattern === target; } function compareVersions(pattern, target) { return semver.satisfies(target ?? '', pattern); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm5vdGljZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsK0JBQStCO0FBQy9CLDZCQUE2QjtBQUM3QiwrQkFBK0I7QUFDL0IsaUNBQWlDO0FBQ2pDLHVDQUF5QztBQUN6QyxpQ0FBa0U7QUFDbEUsaUNBQWlDO0FBQ2pDLG9EQUFpRDtBQUNqRCx1Q0FBMEM7QUFFMUMsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFBLHlCQUFXLEdBQUUsRUFBRSxjQUFjLENBQUMsQ0FBQztBQXVCMUQsS0FBSyxVQUFVLGNBQWM7SUFDbEMsTUFBTSxVQUFVLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDOUMsT0FBTyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7QUFDNUIsQ0FBQztBQUhELHdDQUdDO0FBRU0sS0FBSyxVQUFVLGNBQWMsQ0FBQyxLQUEwQjtJQUM3RCxNQUFNLFVBQVUsR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsV0FBVyxJQUFJLEtBQUssQ0FBQyxDQUFDO0lBQ25FLElBQUEsZUFBSyxFQUFDLE1BQU0sZUFBZSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ2hELE9BQU8sQ0FBQyxDQUFDO0FBQ1gsQ0FBQztBQUpELHdDQUlDO0FBRU0sS0FBSyxVQUFVLGVBQWUsQ0FBQyxVQUE0QixFQUFFLEtBQTBCO0lBQzVGLE1BQU0sSUFBSSxHQUFHLE1BQU0sVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3RDLE1BQU0sZUFBZSxHQUFHLGFBQWEsQ0FBQyxJQUFJLEVBQUU7UUFDMUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1FBQ3BCLHdCQUF3QixFQUFFLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQztLQUNsRSxDQUFDLENBQUM7SUFFSCxJQUFJLGVBQWUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxF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Qy9ELElBQUksTUFBTSxJQUFJLElBQUksRUFBRTtZQUFFLE9BQU8sS0FBSyxDQUFDO1NBQUU7UUFDckMsT0FBTyxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEtBQUssTUFBTSxDQUFDO0lBQ2pGLENBQUM7SUFFRCxTQUFTLGVBQWUsQ0FBQyxPQUFlLEVBQUUsTUFBMEI7UUFDbEUsT0FBTyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDakQsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDbGllbnRSZXF1ZXN0IH0gZnJvbSAnaHR0cCc7XG5pbXBvcnQgKiBhcyBodHRwcyBmcm9tICdodHRwcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0ICogYXMgc2VtdmVyIGZyb20gJ3NlbXZlcic7XG5pbXBvcnQgeyBkZWJ1ZywgcHJpbnQgfSBmcm9tICcuL2xvZ2dpbmcnO1xuaW1wb3J0IHsgc29tZSwgQ29uc3RydWN0VHJlZU5vZGUsIGxvYWRUcmVlRnJvbURpciB9IGZyb20gJy4vdHJlZSc7XG5pbXBvcnQgeyBmbGF0TWFwIH0gZnJvbSAnLi91dGlsJztcbmltcG9ydCB7IGNka0NhY2hlRGlyIH0gZnJvbSAnLi91dGlsL2RpcmVjdG9yaWVzJztcbmltcG9ydCB7IHZlcnNpb25OdW1iZXIgfSBmcm9tICcuL3ZlcnNpb24nO1xuXG5jb25zdCBDQUNIRV9GSUxFX1BBVEggPSBwYXRoLmpvaW4oY2RrQ2FjaGVEaXIoKSwgJ25vdGljZXMuanNvbicpO1xuXG5leHBvcnQgaW50ZXJmYWNlIERpc3BsYXlOb3RpY2VzUHJvcHMge1xuICAvKipcbiAgICogVGhlIGNsb3VkIGFzc2VtYmx5IGRpcmVjdG9yeS4gVXN1YWxseSAnY2RrLm91dCcuXG4gICAqL1xuICByZWFkb25seSBvdXRkaXI6IHN0cmluZztcblxuICAvKipcbiAgICogSXNzdWUgbnVtYmVycyBvZiBub3RpY2VzIHRoYXQgaGF2ZSBiZWVuIGFja25vd2xlZGdlZCBieSBhIHVzZXJcbiAgICogb2YgdGhlIGN1cnJlbnQgQ0RLIHJlcG9zaXRvcnkuIFRoZXNlIG5vdGljZXMgd2lsbCBiZSBza2lwcGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgYWNrbm93bGVkZ2VkSXNzdWVOdW1iZXJzOiBudW1iZXJbXTtcblxuICAvKipcbiAgICogV2hldGhlciBjYWNoZWQgbm90aWNlcyBzaG91bGQgYmUgaWdub3JlZC4gU2V0dGluZyB0aGlzIHByb3BlcnR5XG4gICAqIHRvIHRydWUgd2lsbCBmb3JjZSB0aGUgQ0xJIHRvIGRvd25sb2FkIGZyZXNoIGRhdGFcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGlnbm9yZUNhY2hlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZnJlc2hOb3RpY2VzKCkge1xuICBjb25zdCBkYXRhU291cmNlID0gZGF0YVNvdXJjZVJlZmVyZW5jZShmYWxzZSk7XG4gIHJldHVybiBkYXRhU291cmNlLmZldGNoKCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkaXNwbGF5Tm90aWNlcyhwcm9wczogRGlzcGxheU5vdGljZXNQcm9wcykge1xuICBjb25zdCBkYXRhU291cmNlID0gZGF0YVNvdXJjZVJlZmVyZW5jZShwcm9wcy5pZ25vcmVDYWNoZSA/PyBmYWxzZSk7XG4gIHByaW50KGF3YWl0IGdlbmVyYXRlTWVzc2FnZShkYXRhU291cmNlLCBwcm9wcykpO1xuICByZXR1cm4gMDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlTWVzc2FnZShkYXRhU291cmNlOiBOb3RpY2VEYXRhU291cmNlLCBwcm9wczogRGlzcGxheU5vdGljZXNQcm9wcykge1xuICBjb25zdCBkYXRhID0gYXdhaXQgZGF0YVNvdXJjZS5mZXRjaCgpO1xuICBjb25zdCBmaWx0ZXJlZE5vdGljZXMgPSBmaWx0ZXJOb3RpY2VzKGRhdGEsIHtcbiAgICBvdXRkaXI6IHByb3BzLm91dGRpcixcbiAgICBhY2tub3dsZWRnZWRJc3N1ZU51bWJlcnM6IG5ldyBTZXQocHJvcHMuYWNrbm93bGVkZ2VkSXNzdWVOdW1iZXJzKSxcbiAgfSk7XG5cbiAgaWYgKGZpbHRlcmVkTm90aWNlcy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgaW5kaXZpZHVhbE1lc3NhZ2VzID0gZm9ybWF0Tm90aWNlcyhmaWx0ZXJlZE5vdGljZXMpO1xuICAgIHJldHVybiBmaW5hbE1lc3NhZ2UoaW5kaXZpZHVhbE1lc3NhZ2VzLCBmaWx0ZXJlZE5vdGljZXNbMF0uaXNzdWVOdW1iZXIpO1xuICB9XG4gIHJldHVybiAnJztcbn1cblxuZnVuY3Rpb24gZGF0YVNvdXJjZVJlZmVyZW5jZShpZ25vcmVDYWNoZTogYm9vbGVhbik6IE5vdGljZURhdGFTb3VyY2Uge1xuICByZXR1cm4gbmV3IENhY2hlZERhdGFTb3VyY2UoQ0FDSEVfRklMRV9QQVRILCBuZXcgV2Vic2l0ZU5vdGljZURhdGFTb3VyY2UoKSwgaWdub3JlQ2FjaGUpO1xufVxuXG5mdW5jdGlvbiBmaW5hbE1lc3NhZ2UoaW5kaXZpZHVhbE1lc3NhZ2VzOiBzdHJpbmdbXSwgZXhhbXBsZU51bWJlcjogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIFtcbiAgICAnXFxuTk9USUNFUyAgICAgICAgIChXaGF0XFwncyB0aGlzPyBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvd2lraS9DTEktTm90aWNlcyknLFxuICAgIC4uLmluZGl2aWR1YWxNZXNzYWdlcyxcbiAgICBgSWYgeW91IGRvbuKAmXQgd2FudCB0byBzZWUgYSBub3RpY2UgYW55bW9yZSwgdXNlIFwiY2RrIGFja25vd2xlZGdlIDxpZD5cIi4gRm9yIGV4YW1wbGUsIFwiY2RrIGFja25vd2xlZGdlICR7ZXhhbXBsZU51bWJlcn1cIi5gLFxuICBdLmpvaW4oJ1xcblxcbicpO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbHRlck5vdGljZU9wdGlvbnMge1xuICBvdXRkaXI/OiBzdHJpbmcsXG4gIGNsaVZlcnNpb24/OiBzdHJpbmcsXG4gIGZyYW1ld29ya1ZlcnNpb24/OiBzdHJpbmcsXG4gIGFja25vd2xlZGdlZElzc3VlTnVtYmVycz86IFNldDxudW1iZXI+LFxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyTm90aWNlcyhkYXRhOiBOb3RpY2VbXSwgb3B0aW9uczogRmlsdGVyTm90aWNlT3B0aW9ucyk6IE5vdGljZVtdIHtcbiAgY29uc3QgZmlsdGVyID0gbmV3IE5vdGljZUZpbHRlcih7XG4gICAgY2xpVmVyc2lvbjogb3B0aW9ucy5jbGlWZXJzaW9uID8/IHZlcnNpb25OdW1iZXIoKSxcbiAgICBhY2tub3dsZWRnZWRJc3N1ZU51bWJlcnM6IG9wdGlvbnMuYWNrbm93bGVkZ2VkSXNzdWVOdW1iZXJzID8/IG5ldyBTZXQoKSxcbiAgICB0cmVlOiBsb2FkVHJlZUZyb21EaXIob3B0aW9ucy5vdXRkaXIgPz8gJ2Nkay5vdXQnKSxcbiAgfSk7XG4gIHJldHVybiBkYXRhLmZpbHRlcihub3RpY2UgPT4gZmlsdGVyLmFwcGx5KG5vdGljZSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0Tm90aWNlcyhkYXRhOiBOb3RpY2VbXSk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIGRhdGEubWFwKGZvcm1hdE5vdGljZSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcG9uZW50IHtcbiAgbmFtZTogc3RyaW5nO1xuICB2ZXJzaW9uOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTm90aWNlIHtcbiAgdGl0bGU6IHN0cmluZztcbiAgaXNzdWVOdW1iZXI6IG51bWJlcjtcbiAgb3ZlcnZpZXc6IHN0cmluZztcbiAgY29tcG9uZW50czogQ29tcG9uZW50W107XG4gIHNjaGVtYVZlcnNpb246IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOb3RpY2VEYXRhU291cmNlIHtcbiAgZmV0Y2goKTogUHJvbWlzZTxOb3RpY2VbXT4sXG59XG5cbmV4cG9ydCBjbGFzcyBXZWJzaXRlTm90aWNlRGF0YVNvdXJjZSBpbXBsZW1lbnRzIE5vdGljZURhdGFTb3VyY2Uge1xuICBmZXRjaCgpOiBQcm9taXNlPE5vdGljZVtdPiB7XG4gICAgY29uc3QgdGltZW91dCA9IDMwMDA7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGxldCByZXE6IENsaWVudFJlcXVlc3QgfCB1bmRlZmluZWQ7XG5cbiAgICAgIGxldCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZiAocmVxKSB7XG4gICAgICAgICAgcmVxLmRlc3Ryb3kobmV3IEVycm9yKCdSZXF1ZXN0IHRpbWVkIG91dCcpKTtcbiAgICAgICAgfVxuICAgICAgfSwgdGltZW91dCk7XG5cbiAgICAgIHRpbWVyLnVucmVmKCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHJlcSA9IGh0dHBzLmdldCgnaHR0cHM6Ly9jbGkuY2RrLmRldi10b29scy5hd3MuZGV2L25vdGljZXMuanNvbicsXG4gICAgICAgICAgcmVzID0+IHtcbiAgICAgICAgICAgIGlmIChyZXMuc3RhdHVzQ29kZSA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgIHJlcy5zZXRFbmNvZGluZygndXRmOCcpO1xuICAgICAgICAgICAgICBsZXQgcmF3RGF0YSA9ICcnO1xuICAgICAgICAgICAgICByZXMub24oJ2RhdGEnLCAoY2h1bmspID0+IHtcbiAgICAgICAgICAgICAgICByYXdEYXRhICs9IGNodW5rO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmVzLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBKU09OLnBhcnNlKHJhd0RhdGEpLm5vdGljZXMgYXMgTm90aWNlW107XG4gICAgICAgICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiJ25vdGljZXMnIGtleSBpcyBtaXNzaW5nXCIpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgZGVidWcoJ05vdGljZXMgcmVmcmVzaGVkJyk7XG4gICAgICAgICAgICAgICAgICByZXNvbHZlKGRhdGEgPz8gW10pO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIHBhcnNlIG5vdGljZXM6ICR7ZS5tZXNzYWdlfWApKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXMub24oJ2Vycm9yJywgZSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGZldGNoIG5vdGljZXM6ICR7ZS5tZXNzYWdlfWApKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggbm90aWNlcy4gU3RhdHVzIGNvZGU6ICR7cmVzLnN0YXR1c0NvZGV9YCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICByZXEub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGBIVFRQUyAnZ2V0JyBjYWxsIHRocmV3IGFuIGVycm9yOiAke2UubWVzc2FnZX1gKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cblxuaW50ZXJmYWNlIENhY2hlZE5vdGljZXMge1xuICBleHBpcmF0aW9uOiBudW1iZXIsXG4gIG5vdGljZXM6IE5vdGljZVtdLFxufVxuXG5jb25zdCBUSU1FX1RPX0xJVkVfU1VDQ0VTUyA9IDYwICogNjAgKiAxMDAwOyAvLyAxIGhvdXJcbmNvbnN0IFRJTUVfVE9fTElWRV9FUlJPUiA9IDEgKiA2MCAqIDEwMDA7IC8vIDEgbWludXRlXG5cbmV4cG9ydCBjbGFzcyBDYWNoZWREYXRhU291cmNlIGltcGxlbWVudHMgTm90aWNlRGF0YVNvdXJjZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZmlsZU5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRhdGFTb3VyY2U6IE5vdGljZURhdGFTb3VyY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSBza2lwQ2FjaGU/OiBib29sZWFuKSB7XG4gIH1cblxuICBhc3luYyBmZXRjaCgpOiBQcm9taXNlPE5vdGljZVtdPiB7XG4gICAgY29uc3QgY2FjaGVkRGF0YSA9IGF3YWl0IHRoaXMubG9hZCgpO1xuICAgIGNvbnN0IGRhdGEgPSBjYWNoZWREYXRhLm5vdGljZXM7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IGNhY2hlZERhdGEuZXhwaXJhdGlvbiA/PyAwO1xuXG4gICAgaWYgKERhdGUubm93KCkgPiBleHBpcmF0aW9uIHx8IHRoaXMuc2tpcENhY2hlKSB7XG4gICAgICBjb25zdCBmcmVzaERhdGEgPSBhd2FpdCB0aGlzLmZldGNoSW5uZXIoKTtcbiAgICAgIGF3YWl0IHRoaXMuc2F2ZShmcmVzaERhdGEpO1xuICAgICAgcmV0dXJuIGZyZXNoRGF0YS5ub3RpY2VzO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWJ1ZyhgUmVhZGluZyBjYWNoZWQgbm90aWNlcyBmcm9tICR7dGhpcy5maWxlTmFtZX1gKTtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hJbm5lcigpOiBQcm9taXNlPENhY2hlZE5vdGljZXM+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZXhwaXJhdGlvbjogRGF0ZS5ub3coKSArIFRJTUVfVE9fTElWRV9TVUNDRVNTLFxuICAgICAgICBub3RpY2VzOiBhd2FpdCB0aGlzLmRhdGFTb3VyY2UuZmV0Y2goKSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZGVidWcoYENvdWxkIG5vdCByZWZyZXNoIG5vdGljZXM6ICR7ZX1gKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGV4cGlyYXRpb246IERhdGUubm93KCkgKyBUSU1FX1RPX0xJVkVfRVJST1IsXG4gICAgICAgIG5vdGljZXM6IFtdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWQoKTogUHJvbWlzZTxDYWNoZWROb3RpY2VzPiB7XG4gICAgY29uc3QgZGVmYXVsdFZhbHVlID0ge1xuICAgICAgZXhwaXJhdGlvbjogMCxcbiAgICAgIG5vdGljZXM6IFtdLFxuICAgIH07XG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZzLmV4aXN0c1N5bmModGhpcy5maWxlTmFtZSlcbiAgICAgICAgPyBhd2FpdCBmcy5yZWFkSlNPTih0aGlzLmZpbGVOYW1lKSBhcyBDYWNoZWROb3RpY2VzXG4gICAgICAgIDogZGVmYXVsdFZhbHVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGRlYnVnKGBGYWlsZWQgdG8gbG9hZCBub3RpY2VzIGZyb20gY2FjaGU6ICR7ZX1gKTtcbiAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzYXZlKGNhY2hlZDogQ2FjaGVkTm90aWNlcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmcy53cml0ZUpTT04odGhpcy5maWxlTmFtZSwgY2FjaGVkKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBkZWJ1ZyhgRmFpbGVkIHRvIHN0b3JlIG5vdGljZXMgaW4gdGhlIGNhY2hlOiAke2V9YCk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTm90aWNlRmlsdGVyUHJvcHMge1xuICBjbGlWZXJzaW9uOiBzdHJpbmcsXG4gIGFja25vd2xlZGdlZElzc3VlTnVtYmVyczogU2V0PG51bWJlcj4sXG4gIHRyZWU6IENvbnN0cnVjdFRyZWVOb2RlLFxufVxuXG5leHBvcnQgY2xhc3MgTm90aWNlRmlsdGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBhY2tub3dsZWRnZWRJc3N1ZU51bWJlcnM6IFNldDxudW1iZXI+O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IE5vdGljZUZpbHRlclByb3BzKSB7XG4gICAgdGhpcy5hY2tub3dsZWRnZWRJc3N1ZU51bWJlcnMgPSBwcm9wcy5hY2tub3dsZWRnZWRJc3N1ZU51bWJlcnM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmZiB3ZSBzaG91bGQgc2hvdyB0aGlzIG5vdGljZS5cbiAgICovXG4gIGFwcGx5KG5vdGljZTogTm90aWNlKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuYWNrbm93bGVkZ2VkSXNzdWVOdW1iZXJzLmhhcyhub3RpY2UuaXNzdWVOdW1iZXIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYXBwbHlWZXJzaW9uKG5vdGljZSwgJ2NsaScsIHRoaXMucHJvcHMuY2xpVmVyc2lvbikgfHxcbiAgICAgIG1hdGNoKHJlc29sdmVBbGlhc2VzKG5vdGljZS5jb21wb25lbnRzKSwgdGhpcy5wcm9wcy50cmVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWZmIHdlIHNob3VsZCBzaG93IHRoZSBub3RpY2UuXG4gICAqL1xuICBwcml2YXRlIGFwcGx5VmVyc2lvbihub3RpY2U6IE5vdGljZSwgbmFtZTogc3RyaW5nLCBjb21wYXJlVG9WZXJzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICBpZiAoY29tcGFyZVRvVmVyc2lvbiA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiBmYWxzZTsgfVxuXG4gICAgY29uc3QgYWZmZWN0ZWRDb21wb25lbnQgPSBub3RpY2UuY29tcG9uZW50cy5maW5kKGNvbXBvbmVudCA9PiBjb21wb25lbnQubmFtZSA9PT0gbmFtZSk7XG4gICAgY29uc3QgYWZmZWN0ZWRSYW5nZSA9IGFmZmVjdGVkQ29tcG9uZW50Py52ZXJzaW9uO1xuICAgIHJldHVybiBhZmZlY3RlZFJhbmdlICE9IG51bGwgJiYgc2VtdmVyLnNhdGlzZmllcyhjb21wYXJlVG9WZXJzaW9uLCBhZmZlY3RlZFJhbmdlKTtcbiAgfVxufVxuXG4vKipcbiAqIFNvbWUgY29tcG9uZW50IG5hbWVzIGFyZSBhbGlhc2VzIHRvIGFjdHVhbCBjb21wb25lbnQgbmFtZXMuIEZvciBleGFtcGxlIFwiZnJhbWV3b3JrXCJcbiAqIGlzIGFuIGFsaWFzIGZvciBlaXRoZXIgdGhlIGNvcmUgbGlicmFyeSAodjEpIG9yIHRoZSB3aG9sZSBDREsgbGlicmFyeSAodjIpLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gY29udmVydHMgYWxsIGFsaWFzZXMgdG8gdGhlaXIgYWN0dWFsIGNvdW50ZXJwYXJ0IG5hbWVzLCB0byBiZSB1c2VkIHRvXG4gKiBtYXRjaCBhZ2FpbnN0IHRoZSBjb25zdHJ1Y3QgdHJlZS5cbiAqXG4gKiBAcGFyYW0gY29tcG9uZW50cyBhIGxpc3Qgb2YgY29tcG9uZW50cy4gQ29tcG9uZW50cyB3aG9zZSBuYW1lIGlzIGFuIGFsaWFzIHdpbGwgYmVcbiAqIHRyYW5zZm9ybWVkIGFuZCBhbGwgb3RoZXJzIHdpbGwgYmUgbGVmdCBpbnRhY3QuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVBbGlhc2VzKGNvbXBvbmVudHM6IENvbXBvbmVudFtdKTogQ29tcG9uZW50W10ge1xuICByZXR1cm4gZmxhdE1hcChjb21wb25lbnRzLCBjb21wb25lbnQgPT4ge1xuICAgIGlmIChjb21wb25lbnQubmFtZSA9PT0gJ2ZyYW1ld29yaycpIHtcbiAgICAgIHJldHVybiBbe1xuICAgICAgICBuYW1lOiAnQGF3cy1jZGsvY29yZS4nLFxuICAgICAgICB2ZXJzaW9uOiBjb21wb25lbnQudmVyc2lvbixcbiAgICAgIH0sIHtcbiAgICAgICAgbmFtZTogJ2F3cy1jZGstbGliLicsXG4gICAgICAgIHZlcnNpb246IGNvbXBvbmVudC52ZXJzaW9uLFxuICAgICAgfV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBbY29tcG9uZW50XTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBmb3JtYXROb3RpY2Uobm90aWNlOiBOb3RpY2UpOiBzdHJpbmcge1xuICBjb25zdCBjb21wb25lbnRzVmFsdWUgPSBub3RpY2UuY29tcG9uZW50cy5tYXAoYyA9PiBgJHtjLm5hbWV9OiAke2MudmVyc2lvbn1gKS5qb2luKCcsICcpO1xuICByZXR1cm4gW1xuICAgIGAke25vdGljZS5pc3N1ZU51bWJlcn1cXHQke25vdGljZS50aXRsZX1gLFxuICAgIGZvcm1hdE92ZXJ2aWV3KG5vdGljZS5vdmVydmlldyksXG4gICAgYFxcdEFmZmVjdGVkIHZlcnNpb25zOiAke2NvbXBvbmVudHNWYWx1ZX1gLFxuICAgIGBcXHRNb3JlIGluZm9ybWF0aW9uIGF0OiBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvaXNzdWVzLyR7bm90aWNlLmlzc3VlTnVtYmVyfWAsXG4gIF0uam9pbignXFxuXFxuJykgKyAnXFxuJztcbn1cblxuZnVuY3Rpb24gZm9ybWF0T3ZlcnZpZXcodGV4dDogc3RyaW5nKSB7XG4gIGNvbnN0IHdyYXAgPSAoczogc3RyaW5nKSA9PiBzLnJlcGxhY2UoLyg/IVteXFxuXXsxLDYwfSQpKFteXFxuXXsxLDYwfSlcXHMvZywgJyQxXFxuJyk7XG5cbiAgY29uc3QgaGVhZGluZyA9ICdPdmVydmlldzogJztcbiAgY29uc3Qgc2VwYXJhdG9yID0gYFxcblxcdCR7JyAnLnJlcGVhdChoZWFkaW5nLmxlbmd0aCl9YDtcbiAgY29uc3QgY29udGVudCA9IHdyYXAodGV4dClcbiAgICAuc3BsaXQoJ1xcbicpXG4gICAgLmpvaW4oc2VwYXJhdG9yKTtcblxuICByZXR1cm4gJ1xcdCcgKyBoZWFkaW5nICsgY29udGVudDtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGFueSBjb21wb25lbnQgaW4gdGhlIHRyZWUgbWF0Y2hlcyBhbnkgY29tcG9uZW50IGluIHRoZSBxdWVyeS5cbiAqIEEgbWF0Y2ggaGFwcGVucyB3aGVuOlxuICpcbiAqIDEuIFRoZSB2ZXJzaW9uIG9mIHRoZSBub2RlIG1hdGNoZXMgdGhlIHZlcnNpb24gaW4gdGhlIHF1ZXJ5LCBpbnRlcnByZXRlZFxuICogYXMgYSBzZW12ZXIgcmFuZ2UuXG4gKlxuICogMi4gVGhlIG5hbWUgaW4gdGhlIHF1ZXJ5IGlzIGEgcHJlZml4IG9mIHRoZSBub2RlIG5hbWUgd2hlbiB0aGUgcXVlcnkgZW5kcyBpbiAnLicsXG4gKiBvciB0aGUgdHdvIG5hbWVzIGFyZSBleGFjdGx5IHRoZSBzYW1lLCBvdGhlcndpc2UuXG4gKi9cbmZ1bmN0aW9uIG1hdGNoKHF1ZXJ5OiBDb21wb25lbnRbXSwgdHJlZTogQ29uc3RydWN0VHJlZU5vZGUpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNvbWUodHJlZSwgbm9kZSA9PiB7XG4gICAgcmV0dXJuIHF1ZXJ5LnNvbWUoY29tcG9uZW50ID0+XG4gICAgICBjb21wYXJlTmFtZXMoY29tcG9uZW50Lm5hbWUsIG5vZGUuY29uc3RydWN0SW5mbz8uZnFuKSAmJlxuICAgICAgY29tcGFyZVZlcnNpb25zKGNvbXBvbmVudC52ZXJzaW9uLCBub2RlLmNvbnN0cnVjdEluZm8/LnZlcnNpb24pKTtcbiAgfSk7XG5cbiAgZnVuY3Rpb24gY29tcGFyZU5hbWVzKHBhdHRlcm46IHN0cmluZywgdGFyZ2V0OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBpZiAodGFyZ2V0ID09IG51bGwpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgcmV0dXJuIHBhdHRlcm4uZW5kc1dpdGgoJy4nKSA/IHRhcmdldC5zdGFydHNXaXRoKHBhdHRlcm4pIDogcGF0dGVybiA9PT0gdGFyZ2V0O1xuICB9XG5cbiAgZnVuY3Rpb24gY29tcGFyZVZlcnNpb25zKHBhdHRlcm46IHN0cmluZywgdGFyZ2V0OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gc2VtdmVyLnNhdGlzZmllcyh0YXJnZXQgPz8gJycsIHBhdHRlcm4pO1xuICB9XG59XG4iXX0=