projen
Version:
CDK for software projects
317 lines • 41.5 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GithubWorkflow = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const node_path_1 = require("node:path");
const case_1 = require("case");
const _resolve_1 = require("../_resolve");
const component_1 = require("../component");
const util_1 = require("../util");
const yaml_1 = require("../yaml");
/**
* Workflow for GitHub.
*
* A workflow is a configurable automated process made up of one or more jobs.
*
* @see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions
*/
class GithubWorkflow extends component_1.Component {
/**
* @param github The GitHub component of the project this workflow belongs to.
* @param name The name of the workflow, displayed under the repository's "Actions" tab.
* @param options Additional options to configure the workflow.
*/
constructor(github, name, options = {}) {
super(github.project, `${new.target.name}#${name}`);
this.events = {};
this.jobs = {};
const defaultConcurrency = {
cancelInProgress: false,
group: "${{ github.workflow }}",
};
this.name = name;
this.concurrency = options.limitConcurrency
? (0, util_1.deepMerge)([
defaultConcurrency,
options.concurrencyOptions,
])
: undefined;
this.projenCredentials = github.projenCredentials;
this.actions = github.actions;
this.env = options.env;
const workflowsEnabled = github.workflowsEnabled || options.force;
if (workflowsEnabled) {
const fileName = options.fileName ?? `${name.toLocaleLowerCase()}.yml`;
const extension = (0, node_path_1.extname)(fileName).toLowerCase();
if (![".yml", ".yaml"].includes(extension)) {
throw new Error(`GitHub Workflow files must have either a .yml or .yaml file extension, got: ${fileName}`);
}
this.file = new yaml_1.YamlFile(this.project, `.github/workflows/${fileName}`, {
obj: () => this.renderWorkflow(),
// GitHub needs to read the file from the repository in order to work.
committed: true,
});
}
}
/**
* Add events to triggers the workflow.
*
* @param events The event(s) to trigger the workflow.
*/
on(events) {
this.events = {
...this.events,
...events,
};
}
/**
* Adds a single job to the workflow.
* @param id The job name (unique within the workflow)
* @param job The job specification
*/
addJob(id, job) {
this.addJobs({ [id]: job });
}
/**
* Add jobs to the workflow.
*
* @param jobs Jobs to add.
*/
addJobs(jobs) {
verifyJobConstraints(jobs);
this.jobs = {
...this.jobs,
...jobs,
};
}
/**
* Get a single job from the workflow.
* @param id The job name (unique within the workflow)
*/
getJob(id) {
return this.jobs[id];
}
/**
* Updates a single job to the workflow.
* @param id The job name (unique within the workflow)
*/
updateJob(id, job) {
this.updateJobs({ [id]: job });
}
/**
* Updates jobs for this worklow
* Does a complete replace, it does not try to merge the jobs
*
* @param jobs Jobs to update.
*/
updateJobs(jobs) {
verifyJobConstraints(jobs);
const newJobIds = Object.keys(jobs);
const updatedJobs = Object.entries(this.jobs).map(([jobId, job]) => {
if (newJobIds.includes(jobId)) {
return [jobId, jobs[jobId]];
}
return [jobId, job];
});
this.jobs = {
...Object.fromEntries(updatedJobs),
};
}
/**
* Removes a single job to the workflow.
* @param id The job name (unique within the workflow)
*/
removeJob(id) {
const updatedJobs = Object.entries(this.jobs).filter(([jobId]) => jobId !== id);
this.jobs = {
...Object.fromEntries(updatedJobs),
};
}
renderWorkflow() {
return {
name: this.name,
"run-name": this.runName,
on: snakeCaseKeys(this.events),
concurrency: this.concurrency
? {
group: this.concurrency?.group,
"cancel-in-progress": this.concurrency.cancelInProgress,
}
: undefined,
env: this.env,
jobs: renderJobs(this.jobs, this.actions),
};
}
}
exports.GithubWorkflow = GithubWorkflow;
_a = JSII_RTTI_SYMBOL_1;
GithubWorkflow[_a] = { fqn: "projen.github.GithubWorkflow", version: "0.93.0" };
function snakeCaseKeys(obj) {
if (typeof obj !== "object" || obj == null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(snakeCaseKeys);
}
const result = {};
for (let [k, v] of Object.entries(obj)) {
if (typeof v === "object" && v != null) {
v = snakeCaseKeys(v);
}
result[(0, case_1.snake)(k)] = v;
}
return result;
}
function renderJobs(jobs, actions) {
const result = {};
for (const [name, job] of Object.entries(jobs)) {
result[name] = renderJob(job);
}
return result;
/** @see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions */
function renderJob(job) {
const steps = new Array();
// https://docs.github.com/en/actions/using-workflows/reusing-workflows#supported-keywords-for-jobs-that-call-a-reusable-workflow
if ("uses" in job) {
return {
name: job.name,
needs: arrayOrScalar(job.needs),
if: job.if,
permissions: (0, util_1.kebabCaseKeys)(job.permissions),
concurrency: job.concurrency,
uses: job.uses,
with: job.with,
secrets: job.secrets,
strategy: renderJobStrategy(job.strategy),
};
}
if (job.tools) {
steps.push(...setupTools(job.tools));
}
const userDefinedSteps = (0, util_1.kebabCaseKeys)((0, _resolve_1.resolve)(job.steps), false);
steps.push(...userDefinedSteps);
return {
name: job.name,
needs: arrayOrScalar(job.needs),
"runs-on": arrayOrScalar(job.runsOnGroup) ?? arrayOrScalar(job.runsOn),
permissions: (0, util_1.kebabCaseKeys)(job.permissions),
environment: job.environment,
concurrency: job.concurrency,
outputs: renderJobOutputs(job.outputs),
env: job.env,
defaults: (0, util_1.kebabCaseKeys)(job.defaults),
if: job.if,
steps: steps.map(renderStep),
"timeout-minutes": job.timeoutMinutes,
strategy: renderJobStrategy(job.strategy),
"continue-on-error": job.continueOnError,
container: job.container,
services: job.services,
};
}
function renderJobOutputs(output) {
if (output == null) {
return undefined;
}
const rendered = {};
for (const [name, { stepId, outputName }] of Object.entries(output)) {
rendered[name] = `\${{ steps.${stepId}.outputs.${outputName} }}`;
}
return rendered;
}
function renderJobStrategy(strategy) {
if (strategy == null) {
return undefined;
}
const rendered = {
"max-parallel": strategy.maxParallel,
"fail-fast": strategy.failFast,
};
if (strategy.matrix) {
const matrix = {
include: strategy.matrix.include,
exclude: strategy.matrix.exclude,
};
for (const [key, values] of Object.entries(strategy.matrix.domain ?? {})) {
if (key in matrix) {
// A domain key was set to `include`, or `exclude`:
throw new Error(`Illegal job strategy matrix key: ${key}`);
}
matrix[key] = values;
}
rendered.matrix = matrix;
}
return rendered;
}
function renderStep(step) {
return {
name: step.name,
id: step.id,
if: step.if,
uses: step.uses && actions.get(step.uses),
env: step.env,
run: step.run,
with: step.with,
"continue-on-error": step.continueOnError,
"timeout-minutes": step.timeoutMinutes,
"working-directory": step.workingDirectory,
};
}
}
function arrayOrScalar(arr) {
if (!Array.isArray(arr)) {
return arr;
}
if (arr == null || arr.length === 0) {
return arr;
}
if (arr.length === 1) {
return arr[0];
}
return arr;
}
function setupTools(tools) {
const steps = [];
if (tools.java) {
steps.push({
uses: "actions/setup-java@v4",
with: { distribution: "corretto", "java-version": tools.java.version },
});
}
if (tools.node) {
steps.push({
uses: "actions/setup-node@v4",
with: { "node-version": tools.node.version },
});
}
if (tools.python) {
steps.push({
uses: "actions/setup-python@v5",
with: { "python-version": tools.python.version },
});
}
if (tools.go) {
steps.push({
uses: "actions/setup-go@v5",
with: { "go-version": tools.go.version },
});
}
if (tools.dotnet) {
steps.push({
uses: "actions/setup-dotnet@v4",
with: { "dotnet-version": tools.dotnet.version },
});
}
return steps;
}
function verifyJobConstraints(jobs) {
// verify that job has a "permissions" statement to ensure workflow can
// operate in repos with default tokens set to readonly
for (const [id, job] of Object.entries(jobs)) {
if (!job.permissions) {
throw new Error(`${id}: all workflow jobs must have a "permissions" clause to ensure workflow can operate in restricted repositories`);
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2Zsb3dzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2dpdGh1Yi93b3JrZmxvd3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx5Q0FBb0M7QUFDcEMsK0JBQTZCO0FBSzdCLDBDQUFzQztBQUN0Qyw0Q0FBeUM7QUFDekMsa0NBQW1EO0FBQ25ELGtDQUFtQztBQXlFbkM7Ozs7OztHQU1HO0FBQ0gsTUFBYSxjQUFlLFNBQVEscUJBQVM7SUFnRDNDOzs7O09BSUc7SUFDSCxZQUNFLE1BQWMsRUFDZCxJQUFZLEVBQ1osVUFBaUMsRUFBRTtRQUVuQyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7UUFoQjlDLFdBQU0sR0FBdUIsRUFBRSxDQUFDO1FBQ2hDLFNBQUksR0FHUixFQUFFLENBQUM7UUFjTCxNQUFNLGtCQUFrQixHQUF1QjtZQUM3QyxnQkFBZ0IsRUFBRSxLQUFLO1lBQ3ZCLEtBQUssRUFBRSx3QkFBd0I7U0FDaEMsQ0FBQztRQUVGLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLGdCQUFnQjtZQUN6QyxDQUFDLENBQUUsSUFBQSxnQkFBUyxFQUFDO2dCQUNULGtCQUFrQjtnQkFDbEIsT0FBTyxDQUFDLGtCQUFrQjthQUMzQixDQUF3QjtZQUMzQixDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ2QsSUFBSSxDQUFDLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUNsRCxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7UUFFOUIsSUFBSSxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDO1FBRXZCLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixJQUFJLE9BQU8s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LHlCQUF5QjtZQUMvQixJQUFJLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtTQUNqRCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FDM0IsSUFBMEU7SUFFMUUsdUVBQXVFO0lBQ3ZFLHVEQUF1RDtJQUN2RCxLQUFLLE1BQU0sQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzdDLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLEtBQUssQ0FDYixHQUFHLEVBQUUsZ0hBQWdILENBQ3RILENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleHRuYW1lIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgc25ha2UgfSBmcm9tIFwiY2FzZVwiO1xuaW1wb3J0IHsgR2l0SHViQWN0aW9uc1Byb3ZpZGVyIH0gZnJvbSBcIi4vYWN0aW9ucy1wcm92aWRlclwiO1xuaW1wb3J0IHsgR2l0SHViIH0gZnJvbSBcIi4vZ2l0aHViXCI7XG5pbXBvcnQgeyBHaXRodWJDcmVkZW50aWFscyB9IGZyb20gXCIuL2dpdGh1Yi1jcmVkZW50aWFsc1wiO1xuaW1wb3J0ICogYXMgd29ya2Zsb3dzIGZyb20gXCIuL3dvcmtmbG93cy1tb2RlbFwiO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCIuLi9fcmVzb2x2ZVwiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHsgZGVlcE1lcmdlLCBrZWJhYkNhc2VLZXlzIH0gZnJvbSBcIi4uL3V0aWxcIjtcbmltcG9ydCB7IFlhbWxGaWxlIH0gZnJvbSBcIi4uL3lhbWxcIjtcblxuLyoqXG4gKiBPcHRpb25zIGZvciBgY29uY3VycmVuY3lgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbmN1cnJlbmN5T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBDb25jdXJyZW5jeSBncm91cCBjb250cm9scyB3aGljaCB3b3JrZmxvdyBydW5zIHdpbGwgc2hhcmUgdGhlIHNhbWUgY29uY3VycmVuY3kgbGltaXQuXG4gICAqIEZvciBleGFtcGxlLCBpZiB5b3Ugc3BlY2lmeSBgJHt7IGdpdGh1Yi53b3JrZmxvdyB9fS0ke3sgZ2l0aHViLnJlZiB9fWAsIHdvcmtmbG93IHJ1bnMgdHJpZ2dlcmVkXG4gICAqIG9uIHRoZSBzYW1lIGJyYW5jaCBjYW5ub3QgcnVuIGNvbmN1cnJlbnR5LCBidXQgd29ya2Zsb3dzIHJ1bnMgdHJpZ2dlcmVkIG9uIGRpZmZlcmVudCBicmFuY2hlcyBjYW4uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gJHt7IGdpdGh1Yi53b3JrZmxvdyB9fVxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5naXRodWIuY29tL2VuL2FjdGlvbnMvd3JpdGluZy13b3JrZmxvd3MvY2hvb3Npbmctd2hhdC15b3VyLXdvcmtmbG93LWRvZXMvdXNpbmctY29uY3VycmVuY3kjZXhhbXBsZS1jb25jdXJyZW5jeS1ncm91cHNcbiAgICovXG4gIHJlYWRvbmx5IGdyb3VwPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVuIGEgd29ya2Zsb3cgaXMgdHJpZ2dlcmVkIHdoaWxlIGFub3RoZXIgb25lIChpbiB0aGUgc2FtZSBncm91cCkgaXMgcnVubmluZywgc2hvdWxkIEdpdEh1YiBjYW5jZWxcbiAgICogdGhlIHJ1bm5pbmcgd29ya2Zsb3c/XG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjYW5jZWxJblByb2dyZXNzPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgR2l0aHViV29ya2Zsb3dgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdpdGh1YldvcmtmbG93T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBGb3JjZSB0aGUgY3JlYXRpb24gb2YgdGhlIHdvcmtmbG93IGV2ZW4gaWYgYHdvcmtmbG93c2AgaXMgZGlzYWJsZWQgaW4gYEdpdEh1YmAuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBmb3JjZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBjb25jdXJyZW5jeSBsaW1pdGF0aW9ucy4gVXNlIGBjb25jdXJyZW5jeU9wdGlvbnNgIHRvIGNvbmZpZ3VyZSBzcGVjaWZpYyBub24gZGVmYXVsdCB2YWx1ZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBsaW1pdENvbmN1cnJlbmN5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29uY3VycmVuY3kgZW5zdXJlcyB0aGF0IG9ubHkgYSBzaW5nbGUgam9iIG9yIHdvcmtmbG93IHVzaW5nIHRoZSBzYW1lIGNvbmN1cnJlbmN5IGdyb3VwIHdpbGwgcnVuIGF0IGEgdGltZS4gQ3VycmVudGx5IGluIGJldGEuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0geyBncm91cDogJHt7IGdpdGh1Yi53b3JrZmxvdyB9fSwgY2FuY2VsSW5Qcm9ncmVzczogZmFsc2UgfVxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5naXRodWIuY29tL2VuL2FjdGlvbnMvbGVhcm4tZ2l0aHViLWFjdGlvbnMvd29ya2Zsb3ctc3ludGF4LWZvci1naXRodWItYWN0aW9ucyNjb25jdXJyZW5jeVxuICAgKi9cbiAgcmVhZG9ubHkgY29uY3VycmVuY3lPcHRpb25zPzogQ29uY3VycmVuY3lPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGVudmlyb25tZW50IHZhcmlhYmxlcyB0byBzZXQgZm9yIHRoZSB3b3JrZmxvdy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhZGRpdGlvbmFsIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICAgKi9cbiAgcmVhZG9ubHkgZW52PzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuICAvKipcbiAgICogU2V0IGEgY3VzdG9tIGZpbGUgbmFtZSBmb3IgdGhlIHdvcmtmbG93IGRlZmluaXRpb24gZmlsZS4gTXVzdCBpbmNsdWRlIGVpdGhlciBhIC55bWwgb3IgLnlhbWwgZmlsZSBleHRlbnNpb24uXG4gICAqXG4gICAqIFVzZSB0aGlzIG9wdGlvbiB0byBzZXQgYSBmaWxlIG5hbWUgZm9yIHRoZSB3b3JrZmxvdyBmaWxlLCB0aGF0IGlzIGRpZmZlcmVudCB0aGFuIHRoZSBkaXNwbGF5IG5hbWUuXG4gICAqXG4gICAqIEBleGFtcGxlIFwiYnVpbGQtbmV3LnltbFwiXG4gICAqIEBleGFtcGxlIFwibXktd29ya2Zsb3cueWFtbFwiXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYSBwYXRoLXNhZmUgdmVyc2lvbiBvZiB0aGUgd29ya2Zsb3cgbmFtZSBwbHVzIHRoZSAueW1sIGZpbGUgZW5kaW5nLCBlLmcuIGJ1aWxkLnltbFxuICAgKi9cbiAgcmVhZG9ubHkgZmlsZU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogV29ya2Zsb3cgZm9yIEdpdEh1Yi5cbiAqXG4gKiBBIHdvcmtmbG93IGlzIGEgY29uZmlndXJhYmxlIGF1dG9tYXRlZCBwcm9jZXNzIG1hZGUgdXAgb2Ygb25lIG9yIG1vcmUgam9icy5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5naXRodWIuY29tL2VuL2FjdGlvbnMvcmVmZXJlbmNlL3dvcmtmbG93LXN5bnRheC1mb3ItZ2l0aHViLWFjdGlvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIEdpdGh1YldvcmtmbG93IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSB3b3JrZmxvdy4gR2l0SHViIGRpc3BsYXlzIHRoZSBuYW1lcyBvZiB5b3VyIHdvcmtmbG93cyB1bmRlciB5b3VyIHJlcG9zaXRvcnknc1xuICAgKiBcIkFjdGlvbnNcIiB0YWIuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmdpdGh1Yi5jb20vZW4vYWN0aW9ucy93cml0aW5nLXdvcmtmbG93cy93b3JrZmxvdy1zeW50YXgtZm9yLWdpdGh1Yi1hY3Rpb25zI25hbWVcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBjb25jdXJyZW5jeSBjb25maWd1cmF0aW9uIG9mIHRoZSB3b3JrZmxvdy4gdW5kZWZpbmVkIG1lYW5zIG5vIGNvbmN1cnJlbmN5IGxpbWl0YXRpb25zLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNvbmN1cnJlbmN5PzogQ29uY3VycmVuY3lPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGVudmlyb25tZW50IHZhcmlhYmxlcyB0byBzZXQgZm9yIHRoZSB3b3JrZmxvdy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBlbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gIC8qKlxuICAgKiBUaGUgd29ya2Zsb3cgWUFNTCBmaWxlLiBNYXkgbm90IGV4aXN0IGlmIGB3b3JrZmxvd3NFbmFibGVkYCBpcyBmYWxzZSBvbiBgR2l0SHViYC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBmaWxlOiBZYW1sRmlsZSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogR2l0SHViIEFQSSBhdXRoZW50aWNhdGlvbiBtZXRob2QgdXNlZCBieSBwcm9qZW4gd29ya2Zsb3dzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHByb2plbkNyZWRlbnRpYWxzOiBHaXRodWJDcmVkZW50aWFscztcblxuICAvKipcbiAgICogVGhlIG5hbWUgZm9yIHdvcmtmbG93IHJ1bnMgZ2VuZXJhdGVkIGZyb20gdGhlIHdvcmtmbG93LiBHaXRIdWIgZGlzcGxheXMgdGhlXG4gICAqIHdvcmtmbG93IHJ1biBuYW1lIGluIHRoZSBsaXN0IG9mIHdvcmtmbG93IHJ1bnMgb24geW91ciByZXBvc2l0b3J5J3NcbiAgICogXCJBY3Rpb25zXCIgdGFiLiBJZiBgcnVuLW5hbWVgIGlzIG9taXR0ZWQgb3IgaXMgb25seSB3aGl0ZXNwYWNlLCB0aGVuIHRoZSBydW5cbiAgICogbmFtZSBpcyBzZXQgdG8gZXZlbnQtc3BlY2lmaWMgaW5mb3JtYXRpb24gZm9yIHRoZSB3b3JrZmxvdyBydW4uIEZvclxuICAgKiBleGFtcGxlLCBmb3IgYSB3b3JrZmxvdyB0cmlnZ2VyZWQgYnkgYSBgcHVzaGAgb3IgYHB1bGxfcmVxdWVzdGAgZXZlbnQsIGl0XG4gICAqIGlzIHNldCBhcyB0aGUgY29tbWl0IG1lc3NhZ2UuXG4gICAqXG4gICAqIFRoaXMgdmFsdWUgY2FuIGluY2x1ZGUgZXhwcmVzc2lvbnMgYW5kIGNhbiByZWZlcmVuY2UgYGdpdGh1YmAgYW5kIGBpbnB1dHNgXG4gICAqIGNvbnRleHRzLlxuICAgKi9cbiAgcHVibGljIHJ1bk5hbWU/OiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBhY3Rpb25zOiBHaXRIdWJBY3Rpb25zUHJvdmlkZXI7XG4gIHByaXZhdGUgZXZlbnRzOiB3b3JrZmxvd3MuVHJpZ2dlcnMgPSB7fTtcbiAgcHJpdmF0ZSBqb2JzOiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIHdvcmtmbG93cy5Kb2IgfCB3b3JrZmxvd3MuSm9iQ2FsbGluZ1JldXNhYmxlV29ya2Zsb3dcbiAgPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0gZ2l0aHViIFRoZSBHaXRIdWIgY29tcG9uZW50IG9mIHRoZSBwcm9qZWN0IHRoaXMgd29ya2Zsb3cgYmVsb25ncyB0by5cbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIHdvcmtmbG93LCBkaXNwbGF5ZWQgdW5kZXIgdGhlIHJlcG9zaXRvcnkncyBcIkFjdGlvbnNcIiB0YWIuXG4gICAqIEBwYXJhbSBvcHRpb25zIEFkZGl0aW9uYWwgb3B0aW9ucyB0byBjb25maWd1cmUgdGhlIHdvcmtmbG93LlxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgZ2l0aHViOiBHaXRIdWIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIG9wdGlvbnM6IEdpdGh1YldvcmtmbG93T3B0aW9ucyA9IHt9XG4gICkge1xuICAgIHN1cGVyKGdpdGh1Yi5wcm9qZWN0LCBgJHtuZXcudGFyZ2V0Lm5hbWV9IyR7bmFtZX1gKTtcblxuICAgIGNvbnN0IGRlZmF1bHRDb25jdXJyZW5jeTogQ29uY3VycmVuY3lPcHRpb25zID0ge1xuICAgICAgY2FuY2VsSW5Qcm9ncmVzczogZmFsc2UsXG4gICAgICBncm91cDogXCIke3sgZ2l0aHViLndvcmtmbG93IH19XCIsXG4gICAgfTtcblxuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgdGhpcy5jb25jdXJyZW5jeSA9IG9wdGlvbnMubGltaXRDb25jdXJyZW5jeVxuICAgICAgPyAoZGVlcE1lcmdlKFtcbiAgICAgICAgICBkZWZhdWx0Q29uY3VycmVuY3ksXG4gICAgICAgICAgb3B0aW9ucy5jb25jdXJyZW5jeU9wdGlvbnMsXG4gICAgICAgIF0pIGFzIENvbmN1cnJlbmN5T3B0aW9ucylcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIHRoaXMucHJvamVuQ3JlZGVudGlhbHMgPSBnaXRodWIucHJvamVuQ3JlZGVudGlhbHM7XG4gICAgdGhpcy5hY3Rpb25zID0gZ2l0aHViLmFjdGlvbnM7XG5cbiAgICB0aGlzLmVudiA9IG9wdGlvbnMuZW52O1xuXG4gICAgY29uc3Qgd29ya2Zsb3dzRW5hYmxlZCA9IGdpdGh1Yi53b3JrZmxvd3NFbmFibGVkIHx8IG9wdGlvbnMuZm9yY2U7XG5cbiAgICBpZiAod29ya2Zsb3dzRW5hYmxlZCkge1xuICAgICAgY29uc3QgZmlsZU5hbWUgPSBvcHRpb25zLmZpbGVOYW1lID8/IGAke25hbWUudG9Mb2NhbGVMb3dlckNhc2UoKX0ueW1sYDtcbiAgICAgIGNvbnN0IGV4dGVuc2lvbiA9IGV4dG5hbWUoZmlsZU5hbWUpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgIGlmICghW1wiLnltbFwiLCBcIi55YW1sXCJdLmluY2x1ZGVzKGV4dGVuc2lvbikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBHaXRIdWIgV29ya2Zsb3cgZmlsZXMgbXVzdCBoYXZlIGVpdGhlciBhIC55bWwgb3IgLnlhbWwgZmlsZSBleHRlbnNpb24sIGdvdDogJHtmaWxlTmFtZX1gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZmlsZSA9IG5ldyBZYW1sRmlsZSh0aGlzLnByb2plY3QsIGAuZ2l0aHViL3dvcmtmbG93cy8ke2ZpbGVOYW1lfWAsIHtcbiAgICAgICAgb2JqOiAoKSA9PiB0aGlzLnJlbmRlcldvcmtmbG93KCksXG4gICAgICAgIC8vIEdpdEh1YiBuZWVkcyB0byByZWFkIHRoZSBmaWxlIGZyb20gdGhlIHJlcG9zaXRvcnkgaW4gb3JkZXIgdG8gd29yay5cbiAgICAgICAgY29tbWl0dGVkOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBldmVudHMgdG8gdHJpZ2dlcnMgdGhlIHdvcmtmbG93LlxuICAgKlxuICAgKiBAcGFyYW0gZXZlbnRzIFRoZSBldmVudChzKSB0byB0cmlnZ2VyIHRoZSB3b3JrZmxvdy5cbiAgICovXG4gIHB1YmxpYyBvbihldmVudHM6IHdvcmtmbG93cy5UcmlnZ2Vycykge1xuICAgIHRoaXMuZXZlbnRzID0ge1xuICAgICAgLi4udGhpcy5ldmVudHMsXG4gICAgICAuLi5ldmVudHMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgc2luZ2xlIGpvYiB0byB0aGUgd29ya2Zsb3cuXG4gICAqIEBwYXJhbSBpZCBUaGUgam9iIG5hbWUgKHVuaXF1ZSB3aXRoaW4gdGhlIHdvcmtmbG93KVxuICAgKiBAcGFyYW0gam9iIFRoZSBqb2Igc3BlY2lmaWNhdGlvblxuICAgKi9cbiAgcHVibGljIGFkZEpvYihcbiAgICBpZDogc3RyaW5nLFxuICAgIGpvYjogd29ya2Zsb3dzLkpvYiB8IHdvcmtmbG93cy5Kb2JDYWxsaW5nUmV1c2FibGVXb3JrZmxvd1xuICApOiB2b2lkIHtcbiAgICB0aGlzLmFkZEpvYnMoeyBbaWRdOiBqb2IgfSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGpvYnMgdG8gdGhlIHdvcmtmbG93LlxuICAgKlxuICAgKiBAcGFyYW0gam9icyBKb2JzIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBhZGRKb2JzKFxuICAgIGpvYnM6IFJlY29yZDxzdHJpbmcsIHdvcmtmbG93cy5Kb2IgfCB3b3JrZmxvd3MuSm9iQ2FsbGluZ1JldXNhYmxlV29ya2Zsb3c+XG4gICkge1xuICAgIHZlcmlmeUpvYkNvbnN0cmFpbnRzKGpvYnMpO1xuXG4gICAgdGhpcy5qb2JzID0ge1xuICAgICAgLi4udGhpcy5qb2JzLFxuICAgICAgLi4uam9icyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIHNpbmdsZSBqb2IgZnJvbSB0aGUgd29ya2Zsb3cuXG4gICAqIEBwYXJhbSBpZCBUaGUgam9iIG5hbWUgKHVuaXF1ZSB3aXRoaW4gdGhlIHdvcmtmbG93KVxuICAgKi9cbiAgcHVibGljIGdldEpvYihcbiAgICBpZDogc3RyaW5nXG4gICk6IHdvcmtmbG93cy5Kb2IgfCB3b3JrZmxvd3MuSm9iQ2FsbGluZ1JldXNhYmxlV29ya2Zsb3cge1xuICAgIHJldHVybiB0aGlzLmpvYnNbaWRdO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgYSBzaW5nbGUgam9iIHRvIHRoZSB3b3JrZmxvdy5cbiAgICogQHBhcmFtIGlkIFRoZSBqb2IgbmFtZSAodW5pcXVlIHdpdGhpbiB0aGUgd29ya2Zsb3cpXG4gICAqL1xuICBwdWJsaWMgdXBkYXRlSm9iKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgam9iOiB3b3JrZmxvd3MuSm9iIHwgd29ya2Zsb3dzLkpvYkNhbGxpbmdSZXVzYWJsZVdvcmtmbG93XG4gICkge1xuICAgIHRoaXMudXBkYXRlSm9icyh7IFtpZF06IGpvYiB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIGpvYnMgZm9yIHRoaXMgd29ya2xvd1xuICAgKiBEb2VzIGEgY29tcGxldGUgcmVwbGFjZSwgaXQgZG9lcyBub3QgdHJ5IHRvIG1lcmdlIHRoZSBqb2JzXG4gICAqXG4gICAqIEBwYXJhbSBqb2JzIEpvYnMgdG8gdXBkYXRlLlxuICAgKi9cbiAgcHVibGljIHVwZGF0ZUpvYnMoXG4gICAgam9iczogUmVjb3JkPHN0cmluZywgd29ya2Zsb3dzLkpvYiB8IHdvcmtmbG93cy5Kb2JDYWxsaW5nUmV1c2FibGVXb3JrZmxvdz5cbiAgKSB7XG4gICAgdmVyaWZ5Sm9iQ29uc3RyYWludHMoam9icyk7XG5cbiAgICBjb25zdCBuZXdKb2JJZHMgPSBPYmplY3Qua2V5cyhqb2JzKTtcbiAgICBjb25zdCB1cGRhdGVkSm9icyA9IE9iamVjdC5lbnRyaWVzKHRoaXMuam9icykubWFwKChbam9iSWQsIGpvYl0pID0+IHtcbiAgICAgIGlmIChuZXdKb2JJZHMuaW5jbHVkZXMoam9iSWQpKSB7XG4gICAgICAgIHJldHVybiBbam9iSWQsIGpvYnNbam9iSWRdXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBbam9iSWQsIGpvYl07XG4gICAgfSk7XG4gICAgdGhpcy5qb2JzID0ge1xuICAgICAgLi4uT2JqZWN0LmZyb21FbnRyaWVzKHVwZGF0ZWRKb2JzKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSBzaW5nbGUgam9iIHRvIHRoZSB3b3JrZmxvdy5cbiAgICogQHBhcmFtIGlkIFRoZSBqb2IgbmFtZSAodW5pcXVlIHdpdGhpbiB0aGUgd29ya2Zsb3cpXG4gICAqL1xuICBwdWJsaWMgcmVtb3ZlSm9iKGlkOiBzdHJpbmcpIHtcbiAgICBjb25zdCB1cGRhdGVkSm9icyA9IE9iamVjdC5lbnRyaWVzKHRoaXMuam9icykuZmlsdGVyKFxuICAgICAgKFtqb2JJZF0pID0+IGpvYklkICE9PSBpZFxuICAgICk7XG4gICAgdGhpcy5qb2JzID0ge1xuICAgICAgLi4uT2JqZWN0LmZyb21FbnRyaWVzKHVwZGF0ZWRKb2JzKSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJXb3JrZmxvdygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgXCJydW4tbmFtZVwiOiB0aGlzLnJ1bk5hbWUsXG4gICAgICBvbjogc25ha2VDYXNlS2V5cyh0aGlzLmV2ZW50cyksXG4gICAgICBjb25jdXJyZW5jeTogdGhpcy5jb25jdXJyZW5jeVxuICAgICAgICA/IHtcbiAgICAgICAgICAgIGdyb3VwOiB0aGlzLmNvbmN1cnJlbmN5Py5ncm91cCxcbiAgICAgICAgICAgIFwiY2FuY2VsLWluLXByb2dyZXNzXCI6IHRoaXMuY29uY3VycmVuY3kuY2FuY2VsSW5Qcm9ncmVzcyxcbiAgICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgZW52OiB0aGlzLmVudixcbiAgICAgIGpvYnM6IHJlbmRlckpvYnModGhpcy5qb2JzLCB0aGlzLmFjdGlvbnMpLFxuICAgIH07XG4gIH1cbn1cblxuZnVuY3Rpb24gc25ha2VDYXNlS2V5czxUID0gdW5rbm93bj4ob2JqOiBUKTogVCB7XG4gIGlmICh0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiIHx8IG9iaiA9PSBudWxsKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gb2JqLm1hcChzbmFrZUNhc2VLZXlzKSBhcyBhbnk7XG4gIH1cblxuICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gIGZvciAobGV0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhvYmopKSB7XG4gICAgaWYgKHR5cGVvZiB2ID09PSBcIm9iamVjdFwiICYmIHYgIT0gbnVsbCkge1xuICAgICAgdiA9IHNuYWtlQ2FzZUtleXModik7XG4gICAgfVxuICAgIHJlc3VsdFtzbmFrZShrKV0gPSB2O1xuICB9XG4gIHJldHVybiByZXN1bHQgYXMgYW55O1xufVxuXG5mdW5jdGlvbiByZW5kZXJKb2JzKFxuICBqb2JzOiBSZWNvcmQ8c3RyaW5nLCB3b3JrZmxvd3MuSm9iIHwgd29ya2Zsb3dzLkpvYkNhbGxpbmdSZXVzYWJsZVdvcmtmbG93PixcbiAgYWN0aW9uczogR2l0SHViQWN0aW9uc1Byb3ZpZGVyXG4pIHtcbiAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICBmb3IgKGNvbnN0IFtuYW1lLCBqb2JdIG9mIE9iamVjdC5lbnRyaWVzKGpvYnMpKSB7XG4gICAgcmVzdWx0W25hbWVdID0gcmVuZGVySm9iKGpvYik7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcblxuICAvKiogQHNlZSBodHRwczovL2RvY3MuZ2l0aHViLmNvbS9lbi9hY3Rpb25zL3JlZmVyZW5jZS93b3JrZmxvdy1zeW50YXgtZm9yLWdpdGh1Yi1hY3Rpb25zICovXG4gIGZ1bmN0aW9uIHJlbmRlckpvYihcbiAgICBqb2I6IHdvcmtmbG93cy5Kb2IgfCB3b3JrZmxvd3MuSm9iQ2FsbGluZ1JldXNhYmxlV29ya2Zsb3dcbiAgKSB7XG4gICAgY29uc3Qgc3RlcHMgPSBuZXcgQXJyYXk8d29ya2Zsb3dzLkpvYlN0ZXA+KCk7XG5cbiAgICAvLyBodHRwczovL2RvY3MuZ2l0aHViLmNvbS9lbi9hY3Rpb25zL3VzaW5nLXdvcmtmbG93cy9yZXVzaW5nLXdvcmtmbG93cyNzdXBwb3J0ZWQta2V5d29yZHMtZm9yLWpvYnMtdGhhdC1jYWxsLWEtcmV1c2FibGUtd29ya2Zsb3dcbiAgICBpZiAoXCJ1c2VzXCIgaW4gam9iKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBqb2IubmFtZSxcbiAgICAgICAgbmVlZHM6IGFycmF5T3JTY2FsYXIoam9iLm5lZWRzKSxcbiAgICAgICAgaWY6IGpvYi5pZixcbiAgICAgICAgcGVybWlzc2lvbnM6IGtlYmFiQ2FzZUtleXMoam9iLnBlcm1pc3Npb25zKSxcbiAgICAgICAgY29uY3VycmVuY3k6IGpvYi5jb25jdXJyZW5jeSxcbiAgICAgICAgdXNlczogam9iLnVzZXMsXG4gICAgICAgIHdpdGg6IGpvYi53aXRoLFxuICAgICAgICBzZWNyZXRzOiBqb2Iuc2VjcmV0cyxcbiAgICAgICAgc3RyYXRlZ3k6IHJlbmRlckpvYlN0cmF0ZWd5KGpvYi5zdHJhdGVneSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChqb2IudG9vbHMpIHtcbiAgICAgIHN0ZXBzLnB1c2goLi4uc2V0dXBUb29scyhqb2IudG9vbHMpKTtcbiAgICB9XG5cbiAgICBjb25zdCB1c2VyRGVmaW5lZFN0ZXBzID0ga2ViYWJDYXNlS2V5cyhyZXNvbHZlKGpvYi5zdGVwcyksIGZhbHNlKTtcbiAgICBzdGVwcy5wdXNoKC4uLnVzZXJEZWZpbmVkU3RlcHMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IGpvYi5uYW1lLFxuICAgICAgbmVlZHM6IGFycmF5T3JTY2FsYXIoam9iLm5lZWRzKSxcbiAgICAgIFwicnVucy1vblwiOiBhcnJheU9yU2NhbGFyKGpvYi5ydW5zT25Hcm91cCkgPz8gYXJyYXlPclNjYWxhcihqb2IucnVuc09uKSxcbiAgICAgIHBlcm1pc3Npb25zOiBrZWJhYkNhc2VLZXlzKGpvYi5wZXJtaXNzaW9ucyksXG4gICAgICBlbnZpcm9ubWVudDogam9iLmVudmlyb25tZW50LFxuICAgICAgY29uY3VycmVuY3k6IGpvYi5jb25jdXJyZW5jeSxcbiAgICAgIG91dHB1dHM6IHJlbmRlckpvYk91dHB1dHMoam9iLm91dHB1dHMpLFxuICAgICAgZW52OiBqb2IuZW52LFxuICAgICAgZGVmYXVsdHM6IGtlYmFiQ2FzZUtleXMoam9iLmRlZmF1bHRzKSxcbiAgICAgIGlmOiBqb2IuaWYsXG4gICAgICBzdGVwczogc3RlcHMubWFwKHJlbmRlclN0ZXApLFxuICAgICAgXCJ0aW1lb3V0LW1pbnV0ZXNcIjogam9iLnRpbWVvdXRNaW51dGVzLFxuICAgICAgc3RyYXRlZ3k6IHJlbmRlckpvYlN0cmF0ZWd5KGpvYi5zdHJhdGVneSksXG4gICAgICBcImNvbnRpbnVlLW9uLWVycm9yXCI6IGpvYi5jb250aW51ZU9uRXJyb3IsXG4gICAgICBjb250YWluZXI6IGpvYi5jb250YWluZXIsXG4gICAgICBzZXJ2aWNlczogam9iLnNlcnZpY2VzLFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiByZW5kZXJKb2JPdXRwdXRzKG91dHB1dDogd29ya2Zsb3dzLkpvYltcIm91dHB1dHNcIl0pIHtcbiAgICBpZiAob3V0cHV0ID09IG51bGwpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVuZGVyZWQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCB7IHN0ZXBJZCwgb3V0cHV0TmFtZSB9XSBvZiBPYmplY3QuZW50cmllcyhvdXRwdXQpKSB7XG4gICAgICByZW5kZXJlZFtuYW1lXSA9IGBcXCR7eyBzdGVwcy4ke3N0ZXBJZH0ub3V0cHV0cy4ke291dHB1dE5hbWV9IH19YDtcbiAgICB9XG4gICAgcmV0dXJuIHJlbmRlcmVkO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVuZGVySm9iU3RyYXRlZ3koc3RyYXRlZ3k6IHdvcmtmbG93cy5Kb2JbXCJzdHJhdGVneVwiXSkge1xuICAgIGlmIChzdHJhdGVneSA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHJlbmRlcmVkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICAgIFwibWF4LXBhcmFsbGVsXCI6IHN0cmF0ZWd5Lm1heFBhcmFsbGVsLFxuICAgICAgXCJmYWlsLWZhc3RcIjogc3RyYXRlZ3kuZmFpbEZhc3QsXG4gICAgfTtcblxuICAgIGlmIChzdHJhdGVneS5tYXRyaXgpIHtcbiAgICAgIGNvbnN0IG1hdHJpeDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7XG4gICAgICAgIGluY2x1ZGU6IHN0cmF0ZWd5Lm1hdHJpeC5pbmNsdWRlLFxuICAgICAgICBleGNsdWRlOiBzdHJhdGVneS5tYXRyaXguZXhjbHVkZSxcbiAgICAgIH07XG4gICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlc10gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICAgIHN0cmF0ZWd5Lm1hdHJpeC5kb21haW4gPz8ge31cbiAgICAgICkpIHtcbiAgICAgICAgaWYgKGtleSBpbiBtYXRyaXgpIHtcbiAgICAgICAgICAvLyBBIGRvbWFpbiBrZXkgd2FzIHNldCB0byBgaW5jbHVkZWAsIG9yIGBleGNsdWRlYDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYElsbGVnYWwgam9iIHN0cmF0ZWd5IG1hdHJpeCBrZXk6ICR7a2V5fWApO1xuICAgICAgICB9XG4gICAgICAgIG1hdHJpeFtrZXldID0gdmFsdWVzO1xuICAgICAgfVxuICAgICAgcmVuZGVyZWQubWF0cml4ID0gbWF0cml4O1xuICAgIH1cblxuICAgIHJldHVybiByZW5kZXJlZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbmRlclN0ZXAoc3RlcDogd29ya2Zsb3dzLkpvYlN0ZXApIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogc3RlcC5uYW1lLFxuICAgICAgaWQ6IHN0ZXAuaWQsXG4gICAgICBpZjogc3RlcC5pZixcbiAgICAgIHVzZXM6IHN0ZXAudXNlcyAmJiBhY3Rpb25zLmdldChzdGVwLnVzZXMpLFxuICAgICAgZW52OiBzdGVwLmVudixcbiAgICAgIHJ1bjogc3RlcC5ydW4sXG4gICAgICB3aXRoOiBzdGVwLndpdGgsXG4gICAgICBcImNvbnRpbnVlLW9uLWVycm9yXCI6IHN0ZXAuY29udGludWVPbkVycm9yLFxuICAgICAgXCJ0aW1lb3V0LW1pbnV0ZXNcIjogc3RlcC50aW1lb3V0TWludXRlcyxcbiAgICAgIFwid29ya2luZy1kaXJlY3RvcnlcIjogc3RlcC53b3JraW5nRGlyZWN0b3J5LFxuICAgIH07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXJyYXlPclNjYWxhcjxUPihhcnI6IFQgfCBUW10gfCB1bmRlZmluZWQpOiBUIHwgVFtdIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KGFycikpIHtcbiAgICByZXR1cm4gYXJyO1xuICB9XG4gIGlmIChhcnIgPT0gbnVsbCB8fCBhcnIubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGFycjtcbiAgfVxuICBpZiAoYXJyLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiBhcnJbMF07XG4gIH1cbiAgcmV0dXJuIGFycjtcbn1cblxuZnVuY3Rpb24gc2V0dXBUb29scyh0b29sczogd29ya2Zsb3dzLlRvb2xzKSB7XG4gIGNvbnN0IHN0ZXBzOiB3b3JrZmxvd3MuSm9iU3RlcFtdID0gW107XG5cbiAgaWYgKHRvb2xzLmphdmEpIHtcbiAgICBzdGVwcy5wdXNoKHtcbiAgICAgIHVzZXM6IFwiYWN0aW9ucy9zZXR1cC1qYXZhQHY0XCIsXG4gICAgICB3aXRoOiB7IGRpc3RyaWJ1dGlvbjogXCJjb3JyZXR0b1wiLCBcImphdmEtdmVyc2lvblwiOiB0b29scy5qYXZhLnZlcnNpb24gfSxcbiAgICB9KTtcbiAgfVxuXG4gIGlmICh0b29scy5ub2RlKSB7XG4gICAgc3RlcHMucHVzaCh7XG4gICAgICB1c2VzOiBcImFjdGlvbnMvc2V0dXAtbm9kZUB2NFwiLFxuICAgICAgd2l0aDogeyBcIm5vZGUtdmVyc2lvblwiOiB0b29scy5ub2RlLnZlcnNpb24gfSxcbiAgICB9KTtcbiAgfVxuXG4gIGlmICh0b29scy5weXRob24pIHtcbiAgICBzdGVwcy5wdXNoKHtcbiAgICAgIHVzZXM6IFwiYWN0aW9ucy9zZXR1cC1weXRob25AdjVcIixcbiAgICAgIHdpdGg6IHsgXCJweXRob24tdmVyc2lvblwiOiB0b29scy5weXRob24udmVyc2lvbiB9LFxuICAgIH0pO1xuICB9XG5cbiAgaWYgKHRvb2xzLmdvKSB7XG4gICAgc3RlcHMucHVzaCh7XG4gICAgICB1c2VzOiBcImFjdGlvbnMvc2V0dXAtZ29AdjVcIixcbiAgICAgIHdpdGg6IHsgXCJnby12ZXJzaW9uXCI6IHRvb2xzLmdvLnZlcnNpb24gfSxcbiAgICB9KTtcbiAgfVxuXG4gIGlmICh0b29scy5kb3RuZXQpIHtcbiAgICBzdGVwcy5wdXNoKHtcbiAgICAgIHVzZXM6IFwiYWN0aW9ucy9zZXR1cC1kb3RuZXRAdjRcIixcbiAgICAgIHdpdGg6IHsgXCJkb3RuZXQtdmVyc2lvblwiOiB0b29scy5kb3RuZXQudmVyc2lvbiB9LFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0ZXBzO1xufVxuXG5mdW5jdGlvbiB2ZXJpZnlKb2JDb25zdHJhaW50cyhcbiAgam9iczogUmVjb3JkPHN0cmluZywgd29ya2Zsb3dzLkpvYiB8IHdvcmtmbG93cy5Kb2JDYWxsaW5nUmV1c2FibGVXb3JrZmxvdz5cbikge1xuICAvLyB2ZXJpZnkgdGhhdCBqb2IgaGFzIGEgXCJwZXJtaXNzaW9uc1wiIHN0YXRlbWVudCB0byBlbnN1cmUgd29ya2Zsb3cgY2FuXG4gIC8vIG9wZXJhdGUgaW4gcmVwb3Mgd2l0aCBkZWZhdWx0IHRva2VucyBzZXQgdG8gcmVhZG9ubHlcbiAgZm9yIChjb25zdCBbaWQsIGpvYl0gb2YgT2JqZWN0LmVudHJpZXMoam9icykpIHtcbiAgICBpZiAoIWpvYi5wZXJtaXNzaW9ucykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtpZH06IGFsbCB3b3JrZmxvdyBqb2JzIG11c3QgaGF2ZSBhIFwicGVybWlzc2lvbnNcIiBjbGF1c2UgdG8gZW5zdXJlIHdvcmtmbG93IGNhbiBvcGVyYXRlIGluIHJlc3RyaWN0ZWQgcmVwb3NpdG9yaWVzYFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==