UNPKG

jsii-release

Version:

Release jsii modules to multiple package managers

290 lines • 38.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CodeArtifactRepo = void 0; const client_codeartifact_1 = require("@aws-sdk/client-codeartifact"); const sleep_1 = require("../help/sleep"); const COLLECT_BY_TAG = 'collect-by'; const REPO_LIFETIME_MS = 24 * 3600 * 1000; // One day /** * A CodeArtifact repository */ class CodeArtifactRepo { /** * Create a CodeArtifact repo with a random name */ static async createRandom(options = {}) { const qualifier = Math.random().toString(36).replace(/[^a-z0-9]+/g, ''); const repo = new CodeArtifactRepo(`test-${qualifier}`, options); await repo.create(); return repo; } /** * Create a CodeArtifact repository with a given name */ static async createWithName(name, options = {}) { const repo = new CodeArtifactRepo(name, options); await repo.create(); return repo; } /** * Reference an existing CodeArtifact repository */ static existing(repositoryName, options = {}) { return new CodeArtifactRepo(repositoryName, options); } /** * Garbage collect repositories */ static async gc(options = {}) { if (!await CodeArtifactRepo.existing('*dummy*').domainExists()) { return; } const codeArtifact = new client_codeartifact_1.CodeartifactClient({ credentials: options.credentials, }); let nextToken; do { const page = await retryThrottled(() => codeArtifact.send(new client_codeartifact_1.ListRepositoriesCommand({ nextToken }))); for (const repo of page.repositories ?? []) { const tags = await retryThrottled(() => codeArtifact.send(new client_codeartifact_1.ListTagsForResourceCommand({ resourceArn: repo.arn }))); const collectable = tags?.tags?.find(t => t.key === COLLECT_BY_TAG && Number(t.value) < Date.now()); if (collectable) { // eslint-disable-next-line no-console console.error('Deleting', repo.name); await retryThrottled(() => codeArtifact.send(new client_codeartifact_1.DeleteRepositoryCommand({ domain: repo.domainName, repository: repo.name, }))); } } nextToken = page.nextToken; } while (nextToken); } constructor(repositoryName, options = {}) { this.repositoryName = repositoryName; this.npmUpstream = 'npm-upstream'; this.pypiUpstream = 'pypi-upstream'; this.nugetUpstream = 'nuget-upstream'; this.mavenUpstream = 'maven-upstream'; this.domain = CodeArtifactRepo.DEFAULT_DOMAIN; this.codeArtifact = new client_codeartifact_1.CodeartifactClient({ credentials: options.credentials }); // Letting the compiler infer the types in this way is the only way to get it to typecheck this.send = (command) => retryThrottled(() => this.codeArtifact.send(command)); } /** * Create the repository */ async create() { await this.ensureDomain(); await this.ensureUpstreams(); await this.ensureRepository(this.repositoryName, { description: 'Testing repository', upstreams: [ this.npmUpstream, this.pypiUpstream, this.nugetUpstream, this.mavenUpstream, ], tags: { [COLLECT_BY_TAG]: `${Date.now() + REPO_LIFETIME_MS}`, }, }); } /** * Absorb old login information */ setLoginInformation(loginInfo) { if (loginInfo.repositoryName !== this.repositoryName) { throw new Error(`This login info seems to be for a different repo. '${this.repositoryName}' != '${loginInfo.repositoryName}'`); } this._loginInformation = loginInfo; } async login() { if (this._loginInformation) { return this._loginInformation; } const durationSeconds = 12 * 3600; const authToken = await this.send(new client_codeartifact_1.GetAuthorizationTokenCommand({ domain: this.domain, durationSeconds })); this._loginInformation = { // eslint-disable-next-line max-len authToken: authToken.authorizationToken, expirationTimeMs: authToken.expiration?.getTime() ?? (Date.now() + durationSeconds * 1000), repositoryName: this.repositoryName, npmEndpoint: (await this.send(new client_codeartifact_1.GetRepositoryEndpointCommand({ domain: this.domain, repository: this.repositoryName, format: 'npm' }))).repositoryEndpoint, mavenEndpoint: (await this.send(new client_codeartifact_1.GetRepositoryEndpointCommand({ domain: this.domain, repository: this.repositoryName, format: 'maven' }))).repositoryEndpoint, nugetEndpoint: (await this.send(new client_codeartifact_1.GetRepositoryEndpointCommand({ domain: this.domain, repository: this.repositoryName, format: 'nuget' }))).repositoryEndpoint, pypiEndpoint: (await this.send(new client_codeartifact_1.GetRepositoryEndpointCommand({ domain: this.domain, repository: this.repositoryName, format: 'pypi' }))).repositoryEndpoint, }; return this._loginInformation; } async delete() { try { await this.send(new client_codeartifact_1.DeleteRepositoryCommand({ domain: this.domain, repository: this.repositoryName, })); // eslint-disable-next-line no-console console.error('Deleted', this.repositoryName); } catch (e) { if (!isResourceNotFoundException(e)) { throw e; } // Okay } } /** * List all packages and mark them as "allow upstream versions". * * If we don't do this and we publish `foo@2.3.4-rc.0`, then we can't * download `foo@2.3.0` anymore because by default CodeArtifact will * block different versions from the same package. */ async markAllUpstreamAllow() { for await (const pkg of this.listPackages({ upstream: 'BLOCK' })) { await this.send(new client_codeartifact_1.PutPackageOriginConfigurationCommand({ domain: this.domain, repository: this.repositoryName, format: pkg.format, package: pkg.package, namespace: pkg.namespace, restrictions: { publish: 'ALLOW', upstream: 'ALLOW', }, })); } } async ensureDomain() { if (await this.domainExists()) { return; } await this.send(new client_codeartifact_1.CreateDomainCommand({ domain: this.domain, tags: [{ key: 'testing', value: 'true' }], })); } async ensureUpstreams() { await this.ensureRepository(this.npmUpstream, { description: 'The upstream repository for NPM', external: 'public:npmjs', }); await this.ensureRepository(this.mavenUpstream, { description: 'The upstream repository for Maven', external: 'public:maven-central', }); await this.ensureRepository(this.nugetUpstream, { description: 'The upstream repository for NuGet', external: 'public:nuget-org', }); await this.ensureRepository(this.pypiUpstream, { description: 'The upstream repository for PyPI', external: 'public:pypi', }); } async ensureRepository(name, options) { if (await this.repositoryExists(name)) { return; } await this.send(new client_codeartifact_1.CreateRepositoryCommand({ domain: this.domain, repository: name, description: options?.description, upstreams: options?.upstreams?.map(repositoryName => ({ repositoryName })), tags: options?.tags ? Object.entries(options.tags).map(([key, value]) => ({ key, value })) : undefined, })); if (options?.external) { const externalConnection = options.external; await retry(() => this.send(new client_codeartifact_1.AssociateExternalConnectionCommand({ domain: this.domain, repository: name, externalConnection, }))); } } async domainExists() { try { await this.send(new client_codeartifact_1.DescribeDomainCommand({ domain: this.domain })); return true; } catch (e) { if (!isResourceNotFoundException(e)) { throw e; } return false; } } async repositoryExists(name) { try { await this.send(new client_codeartifact_1.DescribeRepositoryCommand({ domain: this.domain, repository: name })); return true; } catch (e) { if (!isResourceNotFoundException(e)) { throw e; } return false; } } async *listPackages(filter = {}) { let response = await this.send(new client_codeartifact_1.ListPackagesCommand({ domain: this.domain, repository: this.repositoryName, ...filter, })); while (true) { for (const p of response.packages ?? []) { yield p; } if (!response.nextToken) { break; } response = await this.send(new client_codeartifact_1.ListPackagesCommand({ domain: this.domain, repository: this.repositoryName, ...filter, nextToken: response.nextToken, })); } } } exports.CodeArtifactRepo = CodeArtifactRepo; CodeArtifactRepo.DEFAULT_DOMAIN = 'publib-ca'; async function retry(block) { let attempts = 3; while (true) { try { return await block(); } catch (e) { if (attempts-- === 0) { throw e; } // eslint-disable-next-line no-console console.debug(e.message); await (0, sleep_1.sleep)(500); } } } async function retryThrottled(block) { let time = 100; let attempts = 15; while (true) { try { return await block(); } catch (e) { // eslint-disable-next-line no-console console.debug(e); if (!(e instanceof client_codeartifact_1.ThrottlingException) || --attempts === 0) { throw e; } await (0, sleep_1.sleep)(Math.floor(Math.random() * time)); time *= 2; } } } function isResourceNotFoundException(x) { return x instanceof client_codeartifact_1.ResourceNotFoundException; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZWFydGlmYWN0LXJlcG8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29kZWFydGlmYWN0L2NvZGVhcnRpZmFjdC1yZXBvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNFQUFxZDtBQUVyZCx5Q0FBc0M7QUFFdEMsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDO0FBQ3BDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVO0FBTXJEOztHQUVHO0FBQ0gsTUFBYSxnQkFBZ0I7SUFHM0I7O09BRUc7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxVQUFtQyxFQUFFO1FBQ3BFLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUV4RSxNQUFNLElBQUksR0FBRyxJQUFJLGdCQUFnQixDQUFDLFFBQVEsU0FBUyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEUsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDcEIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxJQUFZLEVBQUUsVUFBbUMsRUFBRTtRQUNwRixNQUFNLElBQUksR0FBRyxJQUFJLGdCQUFnQixDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNqRCxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNwQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxRQUFRLENBQUMsY0FBc0IsRUFBRSxVQUFtQyxFQUFFO1FBQ2xGLE9BQU8sSUFBSSxnQkFBZ0IsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENB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QUFZLCtDQUF5QixDQUFDO0FBQ2hELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBc3NvY2lhdGVFeHRlcm5hbENvbm5lY3Rpb25Db21tYW5kLCBDb2RlYXJ0aWZhY3RDbGllbnQsIENyZWF0ZURvbWFpbkNvbW1hbmQsIENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kLCBEZWxldGVSZXBvc2l0b3J5Q29tbWFuZCwgRGVzY3JpYmVEb21haW5Db21tYW5kLCBEZXNjcmliZVJlcG9zaXRvcnlDb21tYW5kLCBHZXRBdXRob3JpemF0aW9uVG9rZW5Db21tYW5kLCBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kLCBMaXN0UGFja2FnZXNDb21tYW5kLCBMaXN0UGFja2FnZXNDb21tYW5kSW5wdXQsIExpc3RSZXBvc2l0b3JpZXNDb21tYW5kLCBMaXN0VGFnc0ZvclJlc291cmNlQ29tbWFuZCwgUHV0UGFja2FnZU9yaWdpbkNvbmZpZ3VyYXRpb25Db21tYW5kLCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCBUaHJvdHRsaW5nRXhjZXB0aW9uIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNvZGVhcnRpZmFjdCc7XG5pbXBvcnQgeyBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlciB9IGZyb20gJ0Bhd3Mtc2RrL3R5cGVzJztcbmltcG9ydCB7IHNsZWVwIH0gZnJvbSAnLi4vaGVscC9zbGVlcCc7XG5cbmNvbnN0IENPTExFQ1RfQllfVEFHID0gJ2NvbGxlY3QtYnknO1xuY29uc3QgUkVQT19MSUZFVElNRV9NUyA9IDI0ICogMzYwMCAqIDEwMDA7IC8vIE9uZSBkYXlcblxuZXhwb3J0IGludGVyZmFjZSBDb2RlQXJ0aWZhY3RSZXBvT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNyZWRlbnRpYWxzPzogQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXI7XG59XG5cbi8qKlxuICogQSBDb2RlQXJ0aWZhY3QgcmVwb3NpdG9yeVxuICovXG5leHBvcnQgY2xhc3MgQ29kZUFydGlmYWN0UmVwbyB7XG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9ET01BSU4gPSAncHVibGliLWNhJztcblxuICAvKipcbiAgICogQ3JlYXRlIGEgQ29kZUFydGlmYWN0IHJlcG8gd2l0aCBhIHJhbmRvbSBuYW1lXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGNyZWF0ZVJhbmRvbShvcHRpb25zOiBDb2RlQXJ0aWZhY3RSZXBvT3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgcXVhbGlmaWVyID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikucmVwbGFjZSgvW15hLXowLTldKy9nLCAnJyk7XG5cbiAgICBjb25zdCByZXBvID0gbmV3IENvZGVBcnRpZmFjdFJlcG8oYHRlc3QtJHtxdWFsaWZpZXJ9YCwgb3B0aW9ucyk7XG4gICAgYXdhaXQgcmVwby5jcmVhdGUoKTtcbiAgICByZXR1cm4gcmVwbztcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDb2RlQXJ0aWZhY3QgcmVwb3NpdG9yeSB3aXRoIGEgZ2l2ZW4gbmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhc3luYyBjcmVhdGVXaXRoTmFtZShuYW1lOiBzdHJpbmcsIG9wdGlvbnM6IENvZGVBcnRpZmFjdFJlcG9PcHRpb25zID0ge30pIHtcbiAgICBjb25zdCByZXBvID0gbmV3IENvZGVBcnRpZmFjdFJlcG8obmFtZSwgb3B0aW9ucyk7XG4gICAgYXdhaXQgcmVwby5jcmVhdGUoKTtcbiAgICByZXR1cm4gcmVwbztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWZlcmVuY2UgYW4gZXhpc3RpbmcgQ29kZUFydGlmYWN0IHJlcG9zaXRvcnlcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZXhpc3RpbmcocmVwb3NpdG9yeU5hbWU6IHN0cmluZywgb3B0aW9uczogQ29kZUFydGlmYWN0UmVwb09wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgQ29kZUFydGlmYWN0UmVwbyhyZXBvc2l0b3J5TmFtZSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogR2FyYmFnZSBjb2xsZWN0IHJlcG9zaXRvcmllc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhc3luYyBnYyhvcHRpb25zOiBDb2RlQXJ0aWZhY3RSZXBvT3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKCFhd2FpdCBDb2RlQXJ0aWZhY3RSZXBvLmV4aXN0aW5nKCcqZHVtbXkqJykuZG9tYWluRXhpc3RzKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb2RlQXJ0aWZhY3QgPSBuZXcgQ29kZWFydGlmYWN0Q2xpZW50KHtcbiAgICAgIGNyZWRlbnRpYWxzOiBvcHRpb25zLmNyZWRlbnRpYWxzLFxuICAgIH0pO1xuXG4gICAgbGV0IG5leHRUb2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGRvIHtcbiAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCByZXRyeVRocm90dGxlZCgoKSA9PiBjb2RlQXJ0aWZhY3Quc2VuZChuZXcgTGlzdFJlcG9zaXRvcmllc0NvbW1hbmQoeyBuZXh0VG9rZW4gfSkpKTtcblxuICAgICAgZm9yIChjb25zdCByZXBvIG9mIHBhZ2UucmVwb3NpdG9yaWVzID8/IFtdKSB7XG4gICAgICAgIGNvbnN0IHRhZ3MgPSBhd2FpdCByZXRyeVRocm90dGxlZCgoKSA9PiBjb2RlQXJ0aWZhY3Quc2VuZChuZXcgTGlzdFRhZ3NGb3JSZXNvdXJjZUNvbW1hbmQoeyByZXNvdXJjZUFybjogcmVwby5hcm4hIH0pKSk7XG4gICAgICAgIGNvbnN0IGNvbGxlY3RhYmxlID0gdGFncz8udGFncz8uZmluZCh0ID0+IHQua2V5ID09PSBDT0xMRUNUX0JZX1RBRyAmJiBOdW1iZXIodC52YWx1ZSkgPCBEYXRlLm5vdygpKTtcbiAgICAgICAgaWYgKGNvbGxlY3RhYmxlKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdEZWxldGluZycsIHJlcG8ubmFtZSk7XG4gICAgICAgICAgYXdhaXQgcmV0cnlUaHJvdHRsZWQoKCkgPT4gY29kZUFydGlmYWN0LnNlbmQobmV3IERlbGV0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogcmVwby5kb21haW5OYW1lISxcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IHJlcG8ubmFtZSEsXG4gICAgICAgICAgfSkpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBuZXh0VG9rZW4gPSBwYWdlLm5leHRUb2tlbjtcbiAgICB9IHdoaWxlIChuZXh0VG9rZW4pO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IG5wbVVwc3RyZWFtID0gJ25wbS11cHN0cmVhbSc7XG4gIHB1YmxpYyByZWFkb25seSBweXBpVXBzdHJlYW0gPSAncHlwaS11cHN0cmVhbSc7XG4gIHB1YmxpYyByZWFkb25seSBudWdldFVwc3RyZWFtID0gJ251Z2V0LXVwc3RyZWFtJztcbiAgcHVibGljIHJlYWRvbmx5IG1hdmVuVXBzdHJlYW0gPSAnbWF2ZW4tdXBzdHJlYW0nO1xuICBwdWJsaWMgcmVhZG9ubHkgZG9tYWluID0gQ29kZUFydGlmYWN0UmVwby5ERUZBVUxUX0RPTUFJTjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvZGVBcnRpZmFjdDtcblxuICBwcml2YXRlIF9sb2dpbkluZm9ybWF0aW9uOiBMb2dpbkluZm9ybWF0aW9uIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHJlYWRvbmx5IHNlbmQ6IENvZGVhcnRpZmFjdENsaWVudFsnc2VuZCddO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHJlYWRvbmx5IHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcsXG4gICAgb3B0aW9uczogQ29kZUFydGlmYWN0UmVwb09wdGlvbnMgPSB7fSxcbiAgKSB7XG4gICAgdGhpcy5jb2RlQXJ0aWZhY3QgPSBuZXcgQ29kZWFydGlmYWN0Q2xpZW50KHsgY3JlZGVudGlhbHM6IG9wdGlvbnMuY3JlZGVudGlhbHMgfSk7XG5cbiAgICAvLyBMZXR0aW5nIHRoZSBjb21waWxlciBpbmZlciB0aGUgdHlwZXMgaW4gdGhpcyB3YXkgaXMgdGhlIG9ubHkgd2F5IHRvIGdldCBpdCB0byB0eXBlY2hlY2tcbiAgICB0aGlzLnNlbmQgPSAoY29tbWFuZCkgPT4gcmV0cnlUaHJvdHRsZWQoKCkgPT4gdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChjb21tYW5kKSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIHRoZSByZXBvc2l0b3J5XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgY3JlYXRlKCkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlRG9tYWluKCk7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVVcHN0cmVhbXMoKTtcblxuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLnJlcG9zaXRvcnlOYW1lLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1Rlc3RpbmcgcmVwb3NpdG9yeScsXG4gICAgICB1cHN0cmVhbXM6IFtcbiAgICAgICAgdGhpcy5ucG1VcHN0cmVhbSxcbiAgICAgICAgdGhpcy5weXBpVXBzdHJlYW0sXG4gICAgICAgIHRoaXMubnVnZXRVcHN0cmVhbSxcbiAgICAgICAgdGhpcy5tYXZlblVwc3RyZWFtLFxuICAgICAgXSxcbiAgICAgIHRhZ3M6IHtcbiAgICAgICAgW0NPTExFQ1RfQllfVEFHXTogYCR7RGF0ZS5ub3coKSArIFJFUE9fTElGRVRJTUVfTVN9YCxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQWJzb3JiIG9sZCBsb2dpbiBpbmZvcm1hdGlvblxuICAgKi9cbiAgcHVibGljIHNldExvZ2luSW5mb3JtYXRpb24obG9naW5JbmZvOiBMb2dpbkluZm9ybWF0aW9uKSB7XG4gICAgaWYgKGxvZ2luSW5mby5yZXBvc2l0b3J5TmFtZSAhPT0gdGhpcy5yZXBvc2l0b3J5TmFtZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGlzIGxvZ2luIGluZm8gc2VlbXMgdG8gYmUgZm9yIGEgZGlmZmVyZW50IHJlcG8uICcke3RoaXMucmVwb3NpdG9yeU5hbWV9JyAhPSAnJHtsb2dpbkluZm8ucmVwb3NpdG9yeU5hbWV9J2ApO1xuICAgIH1cbiAgICB0aGlzLl9sb2dpbkluZm9ybWF0aW9uID0gbG9naW5JbmZvO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGxvZ2luKCk6IFByb21pc2U8TG9naW5JbmZvcm1hdGlvbj4ge1xuICAgIGlmICh0aGlzLl9sb2dpbkluZm9ybWF0aW9uKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbG9naW5JbmZvcm1hdGlvbjtcbiAgICB9XG5cbiAgICBjb25zdCBkdXJhdGlvblNlY29uZHMgPSAxMiAqIDM2MDA7XG4gICAgY29uc3QgYXV0aFRva2VuID0gYXdhaXQgdGhpcy5zZW5kKG5ldyBHZXRBdXRob3JpemF0aW9uVG9rZW5Db21tYW5kKHsgZG9tYWluOiB0aGlzLmRvbWFpbiwgZHVyYXRpb25TZWNvbmRzIH0pKTtcblxuICAgIHRoaXMuX2xvZ2luSW5mb3JtYXRpb24gPSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgYXV0aFRva2VuOiBhdXRoVG9rZW4uYXV0aG9yaXphdGlvblRva2VuISxcbiAgICAgIGV4cGlyYXRpb25UaW1lTXM6IGF1dGhUb2tlbi5leHBpcmF0aW9uPy5nZXRUaW1lKCkgPz8gKERhdGUubm93KCkgKyBkdXJhdGlvblNlY29uZHMgKiAxMDAwKSxcbiAgICAgIHJlcG9zaXRvcnlOYW1lOiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgbnBtRW5kcG9pbnQ6IChhd2FpdCB0aGlzLnNlbmQobmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoeyBkb21haW46IHRoaXMuZG9tYWluLCByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLCBmb3JtYXQ6ICducG0nIH0pKSkucmVwb3NpdG9yeUVuZHBvaW50ISxcbiAgICAgIG1hdmVuRW5kcG9pbnQ6IChhd2FpdCB0aGlzLnNlbmQobmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoeyBkb21haW46IHRoaXMuZG9tYWluLCByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLCBmb3JtYXQ6ICdtYXZlbicgfSkpKS5yZXBvc2l0b3J5RW5kcG9pbnQhLFxuICAgICAgbnVnZXRFbmRwb2ludDogKGF3YWl0IHRoaXMuc2VuZChuZXcgR2V0UmVwb3NpdG9yeUVuZHBvaW50Q29tbWFuZCh7IGRvbWFpbjogdGhpcy5kb21haW4sIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsIGZvcm1hdDogJ251Z2V0JyB9KSkpLnJlcG9zaXRvcnlFbmRwb2ludCEsXG4gICAgICBweXBpRW5kcG9pbnQ6IChhd2FpdCB0aGlzLnNlbmQobmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoeyBkb21haW46IHRoaXMuZG9tYWluLCByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLCBmb3JtYXQ6ICdweXBpJyB9KSkpLnJlcG9zaXRvcnlFbmRwb2ludCEsXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5fbG9naW5JbmZvcm1hdGlvbjtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkZWxldGUoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuc2VuZChuZXcgRGVsZXRlUmVwb3NpdG9yeUNvbW1hbmQoe1xuICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgfSkpO1xuXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS5lcnJvcignRGVsZXRlZCcsIHRoaXMucmVwb3NpdG9yeU5hbWUpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKCFpc1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24oZSkpIHsgdGhyb3cgZTsgfVxuICAgICAgLy8gT2theVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0IGFsbCBwYWNrYWdlcyBhbmQgbWFyayB0aGVtIGFzIFwiYWxsb3cgdXBzdHJlYW0gdmVyc2lvbnNcIi5cbiAgICpcbiAgICogSWYgd2UgZG9uJ3QgZG8gdGhpcyBhbmQgd2UgcHVibGlzaCBgZm9vQDIuMy40LXJjLjBgLCB0aGVuIHdlIGNhbid0XG4gICAqIGRvd25sb2FkIGBmb29AMi4zLjBgIGFueW1vcmUgYmVjYXVzZSBieSBkZWZhdWx0IENvZGVBcnRpZmFjdCB3aWxsXG4gICAqIGJsb2NrIGRpZmZlcmVudCB2ZXJzaW9ucyBmcm9tIHRoZSBzYW1lIHBhY2thZ2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbWFya0FsbFVwc3RyZWFtQWxsb3coKSB7XG4gICAgZm9yIGF3YWl0IChjb25zdCBwa2cgb2YgdGhpcy5saXN0UGFja2FnZXMoeyB1cHN0cmVhbTogJ0JMT0NLJyB9KSkge1xuICAgICAgYXdhaXQgdGhpcy5zZW5kKG5ldyBQdXRQYWNrYWdlT3JpZ2luQ29uZmlndXJhdGlvbkNvbW1hbmQoe1xuICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuXG4gICAgICAgIGZvcm1hdDogcGtnLmZvcm1hdCEsXG4gICAgICAgIHBhY2thZ2U6IHBrZy5wYWNrYWdlISxcbiAgICAgICAgbmFtZXNwYWNlOiBwa2cubmFtZXNwYWNlISxcbiAgICAgICAgcmVzdHJpY3Rpb25zOiB7XG4gICAgICAgICAgcHVibGlzaDogJ0FMTE9XJyxcbiAgICAgICAgICB1cHN0cmVhbTogJ0FMTE9XJyxcbiAgICAgICAgfSxcbiAgICAgIH0pKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZURvbWFpbigpIHtcbiAgICBpZiAoYXdhaXQgdGhpcy5kb21haW5FeGlzdHMoKSkgeyByZXR1cm47IH1cbiAgICBhd2FpdCB0aGlzLnNlbmQobmV3IENyZWF0ZURvbWFpbkNvbW1hbmQoe1xuICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgIHRhZ3M6IFt7IGtleTogJ3Rlc3RpbmcnLCB2YWx1ZTogJ3RydWUnIH1dLFxuICAgIH0pKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlVXBzdHJlYW1zKCkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLm5wbVVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBOUE0nLFxuICAgICAgZXh0ZXJuYWw6ICdwdWJsaWM6bnBtanMnLFxuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLm1hdmVuVXBzdHJlYW0sIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHVwc3RyZWFtIHJlcG9zaXRvcnkgZm9yIE1hdmVuJyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOm1hdmVuLWNlbnRyYWwnLFxuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLm51Z2V0VXBzdHJlYW0sIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHVwc3RyZWFtIHJlcG9zaXRvcnkgZm9yIE51R2V0JyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOm51Z2V0LW9yZycsXG4gICAgfSk7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZXBvc2l0b3J5KHRoaXMucHlwaVVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBQeVBJJyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOnB5cGknLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVSZXBvc2l0b3J5KG5hbWU6IHN0cmluZywgb3B0aW9ucz86IHtcbiAgICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgICByZWFkb25seSBleHRlcm5hbD86IHN0cmluZztcbiAgICByZWFkb25seSB1cHN0cmVhbXM/OiBzdHJpbmdbXTtcbiAgICByZWFkb25seSB0YWdzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgfSkge1xuICAgIGlmIChhd2FpdCB0aGlzLnJlcG9zaXRvcnlFeGlzdHMobmFtZSkpIHsgcmV0dXJuOyB9XG5cbiAgICBhd2FpdCB0aGlzLnNlbmQobmV3IENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICByZXBvc2l0b3J5OiBuYW1lLFxuICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnM/LmRlc2NyaXB0aW9uLFxuICAgICAgdXBzdHJlYW1zOiBvcHRpb25zPy51cHN0cmVhbXM/Lm1hcChyZXBvc2l0b3J5TmFtZSA9PiAoeyByZXBvc2l0b3J5TmFtZSB9KSksXG4gICAgICB0YWdzOiBvcHRpb25zPy50YWdzID8gT2JqZWN0LmVudHJpZXMob3B0aW9ucy50YWdzKS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gKHsga2V5LCB2YWx1ZSB9KSkgOiB1bmRlZmluZWQsXG4gICAgfSkpO1xuXG4gICAgaWYgKG9wdGlvbnM/LmV4dGVybmFsKSB7XG4gICAgICBjb25zdCBleHRlcm5hbENvbm5lY3Rpb24gPSBvcHRpb25zLmV4dGVybmFsO1xuICAgICAgYXdhaXQgcmV0cnkoKCkgPT4gdGhpcy5zZW5kKG5ldyBBc3NvY2lhdGVFeHRlcm5hbENvbm5lY3Rpb25Db21tYW5kKHtcbiAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgcmVwb3NpdG9yeTogbmFtZSxcbiAgICAgICAgZXh0ZXJuYWxDb25uZWN0aW9uLFxuICAgICAgfSkpKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRvbWFpbkV4aXN0cygpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5zZW5kKG5ldyBEZXNjcmliZURvbWFpbkNvbW1hbmQoeyBkb21haW46IHRoaXMuZG9tYWluIH0pKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKCFpc1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24oZSkpIHsgdGhyb3cgZTsgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVwb3NpdG9yeUV4aXN0cyhuYW1lOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5zZW5kKG5ldyBEZXNjcmliZVJlcG9zaXRvcnlDb21tYW5kKHsgZG9tYWluOiB0aGlzLmRvbWFpbiwgcmVwb3NpdG9yeTogbmFtZSB9KSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmICghaXNSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uKGUpKSB7IHRocm93IGU7IH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jKiBsaXN0UGFja2FnZXMoZmlsdGVyOiBQaWNrPExpc3RQYWNrYWdlc0NvbW1hbmRJbnB1dCwgJ3Vwc3RyZWFtJ3wncHVibGlzaCd8J2Zvcm1hdCc+ID0ge30pIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNlbmQobmV3IExpc3RQYWNrYWdlc0NvbW1hbmQoe1xuICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAuLi5maWx0ZXIsXG4gICAgfSkpO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGZvciAoY29uc3QgcCBvZiByZXNwb25zZS5wYWNrYWdlcyA/PyBbXSkge1xuICAgICAgICB5aWVsZCBwO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXJlc3BvbnNlLm5leHRUb2tlbikge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNlbmQobmV3IExpc3RQYWNrYWdlc0NvbW1hbmQoe1xuICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAuLi5maWx0ZXIsXG4gICAgICAgIG5leHRUb2tlbjogcmVzcG9uc2UubmV4dFRva2VuLFxuICAgICAgfSkpO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZXRyeTxBPihibG9jazogKCkgPT4gUHJvbWlzZTxBPikge1xuICBsZXQgYXR0ZW1wdHMgPSAzO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgYmxvY2soKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChhdHRlbXB0cy0tID09PSAwKSB7IHRocm93IGU7IH1cbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmRlYnVnKGUubWVzc2FnZSk7XG4gICAgICBhd2FpdCBzbGVlcCg1MDApO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZXRyeVRocm90dGxlZDxBPihibG9jazogKCkgPT4gUHJvbWlzZTxBPikge1xuICBsZXQgdGltZSA9IDEwMDtcbiAgbGV0IGF0dGVtcHRzID0gMTU7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBibG9jaygpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUuZGVidWcoZSk7XG5cbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBUaHJvdHRsaW5nRXhjZXB0aW9uKSB8fCAtLWF0dGVtcHRzID09PSAwKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHNsZWVwKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHRpbWUpKTtcbiAgICAgIHRpbWUgKj0gMjtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBMb2dpbkluZm9ybWF0aW9uIHtcbiAgcmVhZG9ubHkgYXV0aFRva2VuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGV4cGlyYXRpb25UaW1lTXM6IG51bWJlcjtcbiAgcmVhZG9ubHkgcmVwb3NpdG9yeU5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgbnBtRW5kcG9pbnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgbWF2ZW5FbmRwb2ludDogc3RyaW5nO1xuICByZWFkb25seSBudWdldEVuZHBvaW50OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHB5cGlFbmRwb2ludDogc3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24oeDogYW55KTogeCBpcyBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uO1xufSJdfQ==