projen
Version:
CDK for software projects
234 lines (226 loc) • 31.9 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AwsCdkTypeScriptApp = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const fs = require("fs");
const path = require("path");
const auto_discover_1 = require("./auto-discover");
const awscdk_deps_js_1 = require("./awscdk-deps-js");
const cdk_config_1 = require("./cdk-config");
const cdk_tasks_1 = require("./cdk-tasks");
const integ_runner_1 = require("./integ-runner");
const component_1 = require("../component");
const dependencies_1 = require("../dependencies");
const javascript_1 = require("../javascript");
const typescript_1 = require("../typescript");
/**
* AWS CDK app in TypeScript
*
* @pjid awscdk-app-ts
*/
class AwsCdkTypeScriptApp extends typescript_1.TypeScriptAppProject {
/**
* The CDK version this app is using.
*/
get cdkVersion() {
return this.cdkDeps.cdkVersion;
}
constructor(options) {
super({
...options,
sampleCode: false,
bundlerOptions: {
...options.bundlerOptions,
// we invoke the "bundle" task as part of the build step in cdk.json so
// we don't want it to be added to the pre-compile phase.
runBundleTask: javascript_1.RunBundleTask.MANUAL,
},
});
this.cdkDeps = new awscdk_deps_js_1.AwsCdkDepsJs(this, {
dependencyType: dependencies_1.DependencyType.RUNTIME,
...options,
});
this.appEntrypoint = options.appEntrypoint ?? "main.ts";
// CLI
this.addDevDeps(`aws-cdk@${this.cdkDeps.cdkCliVersion}`);
// no compile step because we do all of it in typescript directly
this.compileTask.reset();
this.cdkTasks = new cdk_tasks_1.CdkTasks(this);
// add synth to the build
this.postCompileTask.spawn(this.cdkTasks.synthSilent);
const tsConfigFile = this.tsconfig?.fileName;
if (!tsConfigFile) {
throw new Error("Expecting tsconfig.json");
}
this.cdkConfig = new cdk_config_1.CdkConfig(this, {
featureFlags: this.cdkDeps.cdkMajorVersion < 2,
buildCommand: this.runTaskCommand(this.bundler.bundleTask),
watchIncludes: [`${this.srcdir}/**/*.ts`, `${this.testdir}/**/*.ts`],
watchExcludes: [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
],
...options,
app: this.getCdkApp(options),
});
this.gitignore.exclude(".parcel-cache/");
this.npmignore?.exclude(`${this.cdkConfig.cdkout}/`);
this.npmignore?.exclude(".cdk.staging/");
if (this.tsconfig) {
this.tsconfig.exclude.push(this.cdkConfig.cdkout);
}
this.addDevDeps("ts-node");
if (options.sampleCode ?? true) {
new SampleCode(this, this.cdkDeps.cdkMajorVersion);
}
new auto_discover_1.AutoDiscover(this, {
srcdir: this.srcdir,
testdir: this.testdir,
lambdaOptions: options.lambdaOptions,
tsconfigPath: this.tsconfigDev.fileName,
cdkDeps: this.cdkDeps,
lambdaAutoDiscover: options.lambdaAutoDiscover ?? true,
edgeLambdaAutoDiscover: options.edgeLambdaAutoDiscover ?? true,
lambdaExtensionAutoDiscover: options.lambdaExtensionAutoDiscover ?? true,
integrationTestAutoDiscover: options.integrationTestAutoDiscover ?? true,
});
if (options.experimentalIntegRunner) {
new integ_runner_1.IntegRunner(this);
}
}
/**
* Adds an AWS CDK module dependencies
* @param modules The list of modules to depend on
*/
addCdkDependency(...modules) {
return this.cdkDeps.addV1Dependencies(...modules);
}
getCdkApp(options) {
if (options.app && options.appEntrypoint) {
throw new Error("Only one of 'app' or 'appEntrypoint' can be specified");
}
// prefer an explicitly provided app command
if (options.app) {
return options.app;
}
const appEntrypoint = path.posix.join(this.srcdir, this.appEntrypoint);
const tsNodeConfig = this.tsconfig?.fileName
? ` -P ${this.tsconfig?.fileName}`
: "";
const tsNodeApp = `ts-node${tsNodeConfig} --prefer-ts-exts ${appEntrypoint}`;
switch (this.package.packageManager) {
case javascript_1.NodePackageManager.BUN:
const bunTsConfig = this.tsconfig?.fileName
? ` --tsconfig-override=${this.tsconfig?.fileName}`
: "";
const bunEntrypoint = ensureRelativePathPrefix(appEntrypoint);
// https://bun.sh/docs/cli/run
// bun can run ts files directly
return `bun run${bunTsConfig} ${bunEntrypoint}`;
case javascript_1.NodePackageManager.PNPM:
case javascript_1.NodePackageManager.YARN_CLASSIC:
case javascript_1.NodePackageManager.YARN:
case javascript_1.NodePackageManager.YARN_BERRY:
case javascript_1.NodePackageManager.YARN2:
// use npx with also for yarn & pnpm due to reported issues
// @see https://github.com/projen/projen/issues/4180
return `npx ${tsNodeApp}`;
default:
return `npx ${tsNodeApp}`;
}
}
}
exports.AwsCdkTypeScriptApp = AwsCdkTypeScriptApp;
_a = JSII_RTTI_SYMBOL_1;
AwsCdkTypeScriptApp[_a] = { fqn: "projen.awscdk.AwsCdkTypeScriptApp", version: "0.91.29" };
/**
* Ensures a path is properly prefixed with './' if it's a relative path
* @param {string} filePath - The path to normalize
* @returns {string} - The normalized path
*/
function ensureRelativePathPrefix(filePath) {
// If it's already an absolute path, return as is
if (path.isAbsolute(filePath)) {
return filePath;
}
// If it already starts with ./ or ../, return as is
if (filePath.startsWith("./") || filePath.startsWith("../")) {
return filePath;
}
// Otherwise, add ./ prefix
return `./${filePath}`;
}
class SampleCode extends component_1.Component {
constructor(project, cdkMajorVersion) {
super(project);
this.cdkMajorVersion = cdkMajorVersion;
this.appProject = project;
}
synthesize() {
const outdir = this.project.outdir;
const srcdir = path.join(outdir, this.appProject.srcdir);
if (fs.existsSync(srcdir) &&
fs.readdirSync(srcdir).filter((x) => x.endsWith(".ts"))) {
return;
}
const srcImports = new Array();
if (this.cdkMajorVersion < 2) {
srcImports.push("import { App, Construct, Stack, StackProps } from '@aws-cdk/core';");
}
else {
srcImports.push("import { App, Stack, StackProps } from 'aws-cdk-lib';");
srcImports.push("import { Construct } from 'constructs';");
}
const srcCode = `${srcImports.join("\n")}
export class MyStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps = {}) {
super(scope, id, props);
// define resources here...
}
}
// for development, use account/region from cdk cli
const devEnv = {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
};
const app = new App();
new MyStack(app, '${this.project.name}-dev', { env: devEnv });
// new MyStack(app, '${this.project.name}-prod', { env: prodEnv });
app.synth();`;
fs.mkdirSync(srcdir, { recursive: true });
fs.writeFileSync(path.join(srcdir, this.appProject.appEntrypoint), srcCode);
const testdir = path.join(outdir, this.appProject.testdir);
if (fs.existsSync(testdir) &&
fs.readdirSync(testdir).filter((x) => x.endsWith(".ts"))) {
return;
}
const testImports = new Array();
if (this.cdkMajorVersion < 2) {
testImports.push("import { App } from '@aws-cdk/core';");
testImports.push("import { Template } from '@aws-cdk/assertions';");
}
else {
testImports.push("import { App } from 'aws-cdk-lib';");
testImports.push("import { Template } from 'aws-cdk-lib/assertions';");
}
const appEntrypointName = path.basename(this.appProject.appEntrypoint, ".ts");
const testCode = `${testImports.join("\n")}
import { MyStack } from '../${this.appProject.srcdir}/${appEntrypointName}';
test('Snapshot', () => {
const app = new App();
const stack = new MyStack(app, 'test');
const template = Template.fromStack(stack);
expect(template.toJSON()).toMatchSnapshot();
});`;
fs.mkdirSync(testdir, { recursive: true });
fs.writeFileSync(path.join(testdir, `${appEntrypointName}.test.ts`), testCode);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzY2RrLWFwcC10cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hd3NjZGsvYXdzY2RrLWFwcC10cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFDN0IsbURBQStDO0FBRS9DLHFEQUFnRDtBQUNoRCw2Q0FBaUU7QUFDakUsMkNBQXVDO0FBQ3ZDLGlEQUE2QztBQUU3Qyw0Q0FBeUM7QUFDekMsa0RBQWlEO0FBQ2pELDhDQUFrRTtBQUNsRSw4Q0FBK0U7QUFxRS9FOzs7O0dBSUc7QUFDSCxNQUFhLG1CQUFvQixTQUFRLGlDQUFvQjtJQUMzRDs7T0FFRztJQUNILElBQVcsVUFBVTtRQUNuQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQ2pDLENBQUM7SUFtQkQsWUFBWSxPQUFtQztRQUM3QyxLQUFLLENBQUM7WUFDSixHQUFHLE9BQU87WUFDVixVQUFVLEVBQUUsS0FBSztZQUNqQixjQUFjLEVBQUU7Z0JBQ2QsR0FBRyxPQUFPLENBQUMsY0FBYztnQkFFekIsdUVBQXVFO2dCQUN2RSx5REFBeUQ7Z0JBQ3pELGFBQWEsRUFBRSwwQkFBYSxDQUFDLE1BQU07YUFDcEM7U0FDRixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksNkJBQVksQ0FBQyxJQUFJLEVBQUU7WUFDcEMsY0FBYyxFQUFFLDZCQUFjLENBQUMsT0FBTztZQUN0QyxHQUFHLE9BQU87U0FDWCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLElBQUksU0FBUyxDQUFDO1FBRXhELE1BQU07UUFDTixJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBRXpELGlFQUFpRTtRQUNqRSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRXpCLElB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RUFDeEQsQ0FBQztZQUNELE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztRQUN4QyxJQUFJLElBQUksQ0FBQyxlQUFlLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsV0FBVyxDQUFDLElBQUksQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1lBQ3pELFdBQVcsQ0FBQyxJQUFJLENBQUMsaURBQWlELENBQUMsQ0FBQztRQUN0RSxDQUFDO2FBQU0sQ0FBQztZQUNOLFdBQVcsQ0FBQyxJQUFJLENBQUMsb0NBQW9DLENBQUMsQ0FBQztZQUN2RCxXQUFXLENBQUMsSUFBSSxDQUFDLG9EQUFvRCxDQUFDLENBQUM7UUFDekUsQ0FBQztRQUVELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FDckMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQzdCLEtBQUssQ0FDTixDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQzs4QkFDaEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLElBQUksaUJBQWlCOzs7Ozs7OztJQVFyRSxDQUFDO1FBRUQsRUFBRSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMzQyxFQUFFLENBQUMsYUFBYSxDQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsaUJBQWlCLFVBQVUsQ0FBQyxFQUNsRCxRQUFRLENBQ1QsQ0FBQztJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgQXV0b0Rpc2NvdmVyIH0gZnJvbSBcIi4vYXV0by1kaXNjb3ZlclwiO1xuaW1wb3J0IHsgQXdzQ2RrRGVwcywgQXdzQ2RrRGVwc0NvbW1vbk9wdGlvbnMgfSBmcm9tIFwiLi9hd3NjZGstZGVwc1wiO1xuaW1wb3J0IHsgQXdzQ2RrRGVwc0pzIH0gZnJvbSBcIi4vYXdzY2RrLWRlcHMtanNcIjtcbmltcG9ydCB7IENka0NvbmZpZywgQ2RrQ29uZmlnQ29tbW9uT3B0aW9ucyB9IGZyb20gXCIuL2Nkay1jb25maWdcIjtcbmltcG9ydCB7IENka1Rhc2tzIH0gZnJvbSBcIi4vY2RrLXRhc2tzXCI7XG5pbXBvcnQgeyBJbnRlZ1J1bm5lciB9IGZyb20gXCIuL2ludGVnLXJ1bm5lclwiO1xuaW1wb3J0IHsgTGFtYmRhRnVuY3Rpb25Db21tb25PcHRpb25zIH0gZnJvbSBcIi4vbGFtYmRhLWZ1bmN0aW9uXCI7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tIFwiLi4vY29tcG9uZW50XCI7XG5pbXBvcnQgeyBEZXBlbmRlbmN5VHlwZSB9IGZyb20gXCIuLi9kZXBlbmRlbmNpZXNcIjtcbmltcG9ydCB7IE5vZGVQYWNrYWdlTWFuYWdlciwgUnVuQnVuZGxlVGFzayB9IGZyb20gXCIuLi9qYXZhc2NyaXB0XCI7XG5pbXBvcnQgeyBUeXBlU2NyaXB0QXBwUHJvamVjdCwgVHlwZVNjcmlwdFByb2plY3RPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzY3JpcHRcIjtcblxuZXhwb3J0IGludGVyZmFjZSBBd3NDZGtUeXBlU2NyaXB0QXBwT3B0aW9uc1xuICBleHRlbmRzIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyxcbiAgICBDZGtDb25maWdDb21tb25PcHRpb25zLFxuICAgIEF3c0Nka0RlcHNDb21tb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBDREsgYXBwJ3MgZW50cnlwb2ludCAocmVsYXRpdmUgdG8gdGhlIHNvdXJjZSBkaXJlY3RvcnksIHdoaWNoIGlzXG4gICAqIFwic3JjXCIgYnkgZGVmYXVsdCkuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwibWFpbi50c1wiXG4gICAqL1xuICByZWFkb25seSBhcHBFbnRyeXBvaW50Pzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGNvbW1hbmQgbGluZSB0byBleGVjdXRlIGluIG9yZGVyIHRvIHN5bnRoZXNpemUgdGhlIENESyBhcHBsaWNhdGlvblxuICAgKiAobGFuZ3VhZ2Ugc3BlY2lmaWMpLlxuICAgKi9cbiAgcmVhZG9ubHkgYXBwPzogc3RyaW5nO1xuICAvKipcbiAgICogQXV0b21hdGljYWxseSBhZGRzIGFuIGBhd3NjZGsuTGFtYmRhRnVuY3Rpb25gIGZvciBlYWNoIGAubGFtYmRhLnRzYCBoYW5kbGVyXG4gICAqIGluIHlvdXIgc291cmNlIHRyZWUuIElmIHRoaXMgaXMgZGlzYWJsZWQsIHlvdSBjYW4gbWFudWFsbHkgYWRkIGFuXG4gICAqIGBhd3NjZGsuQXV0b0Rpc2NvdmVyYCBjb21wb25lbnQgdG8geW91ciBwcm9qZWN0LlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBsYW1iZGFBdXRvRGlzY292ZXI/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBdXRvbWF0aWNhbGx5IGFkZHMgYW4gYGNsb3VkZnJvbnQuZXhwZXJpbWVudGFsLkVkZ2VGdW5jdGlvbmAgZm9yIGVhY2hcbiAgICogYC5lZGdlLWxhbWJkYS50c2AgaGFuZGxlciBpbiB5b3VyIHNvdXJjZSB0cmVlLiBJZiB0aGlzIGlzIGRpc2FibGVkLCB5b3UgY2FuXG4gICAqIG1hbnVhbGx5IGFkZCBhbiBgYXdzY2RrLkF1dG9EaXNjb3ZlcmAgY29tcG9uZW50IHRvIHlvdXIgcHJvamVjdC5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZWRnZUxhbWJkYUF1dG9EaXNjb3Zlcj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEF1dG9tYXRpY2FsbHkgYWRkcyBhbiBgYXdzY2RrLkxhbWJkYUV4dGVuc2lvbmAgZm9yIGVhY2ggYC5sYW1iZGEtZXh0ZW5zaW9uLnRzYFxuICAgKiBlbnRyeXBvaW50IGluIHlvdXIgc291cmNlIHRyZWUuIElmIHRoaXMgaXMgZGlzYWJsZWQsIHlvdSBjYW4gbWFudWFsbHkgYWRkIGFuXG4gICAqIGBhd3NjZGsuQXV0b0Rpc2NvdmVyYCBjb21wb25lbnQgdG8geW91ciBwcm9qZWN0XG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGxhbWJkYUV4dGVuc2lvbkF1dG9EaXNjb3Zlcj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEF1dG9tYXRpY2FsbHkgZGlzY292ZXJzIGFuZCBjcmVhdGVzIGludGVncmF0aW9uIHRlc3RzIGZvciBlYWNoIGAuaW50ZWcudHNgXG4gICAqIGZpbGUgaW4gdW5kZXIgeW91ciB0ZXN0IGRpcmVjdG9yeS5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZWdyYXRpb25UZXN0QXV0b0Rpc2NvdmVyPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRW5hYmxlIGV4cGVyaW1lbnRhbCBzdXBwb3J0IGZvciB0aGUgQVdTIENESyBpbnRlZy1ydW5uZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqIEBleHBlcmltZW50YWxcbiAgICovXG4gIHJlYWRvbmx5IGV4cGVyaW1lbnRhbEludGVnUnVubmVyPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29tbW9uIG9wdGlvbnMgZm9yIGFsbCBBV1MgTGFtYmRhIGZ1bmN0aW9ucy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZWZhdWx0IG9wdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGxhbWJkYU9wdGlvbnM/OiBMYW1iZGFGdW5jdGlvbkNvbW1vbk9wdGlvbnM7XG59XG5cbi8qKlxuICogQVdTIENESyBhcHAgaW4gVHlwZVNjcmlwdFxuICpcbiAqIEBwamlkIGF3c2Nkay1hcHAtdHNcbiAqL1xuZXhwb3J0IGNsYXNzIEF3c0Nka1R5cGVTY3JpcHRBcHAgZXh0ZW5kcyBUeXBlU2NyaXB0QXBwUHJvamVjdCB7XG4gIC8qKlxuICAgKiBUaGUgQ0RLIHZlcnNpb24gdGhpcyBhcHAgaXMgdXNpbmcuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGNka1ZlcnNpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2RrRGVwcy5jZGtWZXJzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBDREsgYXBwIGVudHJ5cG9pbnRcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhcHBFbnRyeXBvaW50OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENvbW1vbiBDREsgdGFza3MuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY2RrVGFza3M6IENka1Rhc2tzO1xuXG4gIC8qKlxuICAgKiBjZGsuanNvbiBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNka0NvbmZpZzogQ2RrQ29uZmlnO1xuXG4gIHB1YmxpYyByZWFkb25seSBjZGtEZXBzOiBBd3NDZGtEZXBzO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IEF3c0Nka1R5cGVTY3JpcHRBcHBPcHRpb25zKSB7XG4gICAgc3VwZXIoe1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHNhbXBsZUNvZGU6IGZhbHNlLFxuICAgICAgYnVuZGxlck9wdGlvbnM6IHtcbiAgICAgICAgLi4ub3B0aW9ucy5idW5kbGVyT3B0aW9ucyxcblxuICAgICAgICAvLyB3ZSBpbnZva2UgdGhlIFwiYnVuZGxlXCIgdGFzayBhcyBwYXJ0IG9mIHRoZSBidWlsZCBzdGVwIGluIGNkay5qc29uIHNvXG4gICAgICAgIC8vIHdlIGRvbid0IHdhbnQgaXQgdG8gYmUgYWRkZWQgdG8gdGhlIHByZS1jb21waWxlIHBoYXNlLlxuICAgICAgICBydW5CdW5kbGVUYXNrOiBSdW5CdW5kbGVUYXNrLk1BTlVBTCxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgdGhpcy5jZGtEZXBzID0gbmV3IEF3c0Nka0RlcHNKcyh0aGlzLCB7XG4gICAgICBkZXBlbmRlbmN5VHlwZTogRGVwZW5kZW5jeVR5cGUuUlVOVElNRSxcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBFbnRyeXBvaW50ID0gb3B0aW9ucy5hcHBFbnRyeXBvaW50ID8/IFwibWFpbi50c1wiO1xuXG4gICAgLy8gQ0xJXG4gICAgdGhpcy5hZGREZXZEZXBzKGBhd3MtY2RrQCR7dGhpcy5jZGtEZXBzLmNka0NsaVZlcnNpb259YCk7XG5cbiAgICAvLyBubyBjb21waWxlIHN0ZXAgYmVjYXVzZSB3ZSBkbyBhbGwgb2YgaXQgaW4gdHlwZXNjcmlwdCBkaXJlY3RseVxuICAgIHRoaXMuY29tcGlsZVRhc2sucmVzZXQoKTtcblxuICAgIHRoaXMuY2RrVGFza3MgPSBuZXcgQ2RrVGFza3ModGhpcyk7XG5cbiAgICAvLyBhZGQgc3ludGggdG8gdGhlIGJ1aWxkXG4gICAgdGhpcy5wb3N0Q29tcGlsZVRhc2suc3Bhd24odGhpcy5jZGtUYXNrcy5zeW50aFNpbGVudCk7XG5cbiAgICBjb25zdCB0c0NvbmZpZ0ZpbGUgPSB0aGlzLnRzY29uZmlnPy5maWxlTmFtZTtcbiAgICBpZiAoIXRzQ29uZmlnRmlsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRXhwZWN0aW5nIHRzY29uZmlnLmpzb25cIik7XG4gICAgfVxuXG4gICAgdGhpcy5jZGtDb25maWcgPSBuZXcgQ2RrQ29uZmlnKHRoaXMsIHtcbiAgICAgIGZlYXR1cmVGbGFnczogdGhpcy5jZGtEZXBzLmNka01ham9yVmVyc2lvbiA8IDIsXG4gICAgICBidWlsZENvbW1hbmQ6IHRoaXMucnVuVGFza0NvbW1hbmQodGhpcy5idW5kbGVyLmJ1bmRsZVRhc2spLFxuICAgICAgd2F0Y2hJbmNsdWRlczogW2Ake3RoaXMuc3JjZGlyfS8qKi8qLnRzYCwgYCR7dGhpcy50ZXN0ZGlyfS8qKi8qLnRzYF0sXG4gICAgICB3YXRjaEV4Y2x1ZGVzOiBbXG4gICAgICAgIFwiUkVBRE1FLm1kXCIsXG4gICAgICAgIFwiY2RrKi5qc29uXCIsXG4gICAgICAgIFwiKiovKi5kLnRzXCIsXG4gICAgICAgIFwiKiovKi5qc1wiLFxuICAgICAgICBcInRzY29uZmlnLmpzb25cIixcbiAgICAgICAgXCJwYWNrYWdlKi5qc29uXCIsXG4gICAgICAgIFwieWFybi5sb2NrXCIsXG4gICAgICAgIFwibm9kZV9tb2R1bGVzXCIsXG4gICAgICBdLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIGFwcDogdGhpcy5nZXRDZGtBcHAob3B0aW9ucyksXG4gICAgfSk7XG5cbiAgICB0aGlzLmdpdGlnbm9yZS5leGNsdWRlKFwiLnBhcmNlbC1jYWNoZS9cIik7XG5cbiAgICB0aGlzLm5wbWlnbm9yZT8uZXhjbHVkZShgJHt0aGlzLmNka0NvbmZpZy5jZGtvdXR9L2ApO1xuICAgIHRoaXMubnBtaWdub3JlPy5leGNsdWRlKFwiLmNkay5zdGFnaW5nL1wiKTtcblxuICAgIGlmICh0aGlzLnRzY29uZmlnKSB7XG4gICAgICB0aGlzLnRzY29uZmlnLmV4Y2x1ZGUucHVzaCh0aGlzLmNka0NvbmZpZy5jZGtvdXQpO1xuICAgIH1cblxuICAgIHRoaXMuYWRkRGV2RGVwcyhcInRzLW5vZGVcIik7XG4gICAgaWYgKG9wdGlvbnMuc2FtcGxlQ29kZSA/PyB0cnVlKSB7XG4gICAgICBuZXcgU2FtcGxlQ29kZSh0aGlzLCB0aGlzLmNka0RlcHMuY2RrTWFqb3JWZXJzaW9uKTtcbiAgICB9XG5cbiAgICBuZXcgQXV0b0Rpc2NvdmVyKHRoaXMsIHtcbiAgICAgIHNyY2RpcjogdGhpcy5zcmNkaXIsXG4gICAgICB0ZXN0ZGlyOiB0aGlzLnRlc3RkaXIsXG4gICAgICBsYW1iZGFPcHRpb25zOiBvcHRpb25zLmxhbWJkYU9wdGlvbnMsXG4gICAgICB0c2NvbmZpZ1BhdGg6IHRoaXMudHNjb25maWdEZXYuZmlsZU5hbWUsXG4gICAgICBjZGtEZXBzOiB0aGlzLmNka0RlcHMsXG4gICAgICBsYW1iZGFBdXRvRGlzY292ZXI6IG9wdGlvbnMubGFtYmRhQXV0b0Rpc2NvdmVyID8/IHRydWUsXG4gICAgICBlZGdlTGFtYmRhQXV0b0Rpc2NvdmVyOiBvcHRpb25zLmVkZ2VMYW1iZGFBdXRvRGlzY292ZXIgPz8gdHJ1ZSxcbiAgICAgIGxhbWJkYUV4dGVuc2lvbkF1dG9EaXNjb3Zlcjogb3B0aW9ucy5sYW1iZGFFeHRlbnNpb25BdXRvRGlzY292ZXIgPz8gdHJ1ZSxcbiAgICAgIGludGVncmF0aW9uVGVzdEF1dG9EaXNjb3Zlcjogb3B0aW9ucy5pbnRlZ3JhdGlvblRlc3RBdXRvRGlzY292ZXIgPz8gdHJ1ZSxcbiAgICB9KTtcblxuICAgIGlmIChvcHRpb25zLmV4cGVyaW1lbnRhbEludGVnUnVubmVyKSB7XG4gICAgICBuZXcgSW50ZWdSdW5uZXIodGhpcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gQVdTIENESyBtb2R1bGUgZGVwZW5kZW5jaWVzXG4gICAqIEBwYXJhbSBtb2R1bGVzIFRoZSBsaXN0IG9mIG1vZHVsZXMgdG8gZGVwZW5kIG9uXG4gICAqL1xuICBwdWJsaWMgYWRkQ2RrRGVwZW5kZW5jeSguLi5tb2R1bGVzOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiB0aGlzLmNka0RlcHMuYWRkVjFEZXBlbmRlbmNpZXMoLi4ubW9kdWxlcyk7XG4gIH1cblxuICBwcml2YXRlIGdldENka0FwcChvcHRpb25zOiBBd3NDZGtUeXBlU2NyaXB0QXBwT3B0aW9ucyk6IHN0cmluZyB7XG4gICAgaWYgKG9wdGlvbnMuYXBwICYmIG9wdGlvbnMuYXBwRW50cnlwb2ludCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiT25seSBvbmUgb2YgJ2FwcCcgb3IgJ2FwcEVudHJ5cG9pbnQnIGNhbiBiZSBzcGVjaWZpZWRcIik7XG4gICAgfVxuXG4gICAgLy8gcHJlZmVyIGFuIGV4cGxpY2l0bHkgcHJvdmlkZWQgYXBwIGNvbW1hbmRcbiAgICBpZiAob3B0aW9ucy5hcHApIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmFwcDtcbiAgICB9XG5cbiAgICBjb25zdCBhcHBFbnRyeXBvaW50ID0gcGF0aC5wb3NpeC5qb2luKHRoaXMuc3JjZGlyLCB0aGlzLmFwcEVudHJ5cG9pbnQpO1xuXG4gICAgY29uc3QgdHNOb2RlQ29uZmlnID0gdGhpcy50c2NvbmZpZz8uZmlsZU5hbWVcbiAgICAgID8gYCAtUCAke3RoaXMudHNjb25maWc/LmZpbGVOYW1lfWBcbiAgICAgIDogXCJcIjtcbiAgICBjb25zdCB0c05vZGVBcHAgPSBgdHMtbm9kZSR7dHNOb2RlQ29uZmlnfSAtLXByZWZlci10cy1leHRzICR7YXBwRW50cnlwb2ludH1gO1xuXG4gICAgc3dpdGNoICh0aGlzLnBhY2thZ2UucGFja2FnZU1hbmFnZXIpIHtcbiAgICAgIGNhc2UgTm9kZVBhY2thZ2VNYW5hZ2VyLkJVTjpcbiAgICAgICAgY29uc3QgYnVuVHNDb25maWcgPSB0aGlzLnRzY29uZmlnPy5maWxlTmFtZVxuICAgICAgICAgID8gYCAtLXRzY29uZmlnLW92ZXJyaWRlPSR7dGhpcy50c2NvbmZpZz8uZmlsZU5hbWV9YFxuICAgICAgICAgIDogXCJcIjtcbiAgICAgICAgY29uc3QgYnVuRW50cnlwb2ludCA9IGVuc3VyZVJlbGF0aXZlUGF0aFByZWZpeChhcHBFbnRyeXBvaW50KTtcblxuICAgICAgICAvLyBodHRwczovL2J1bi5zaC9kb2NzL2NsaS9ydW5cbiAgICAgICAgLy8gYnVuIGNhbiBydW4gdHMgZmlsZXMgZGlyZWN0bHlcbiAgICAgICAgcmV0dXJuIGBidW4gcnVuJHtidW5Uc0NvbmZpZ30gJHtidW5FbnRyeXBvaW50fWA7XG4gICAgICBjYXNlIE5vZGVQYWNrYWdlTWFuYWdlci5QTlBNOlxuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuWUFSTl9DTEFTU0lDOlxuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuWUFSTjpcbiAgICAgIGNhc2UgTm9kZVBhY2thZ2VNYW5hZ2VyLllBUk5fQkVSUlk6XG4gICAgICBjYXNlIE5vZGVQYWNrYWdlTWFuYWdlci5ZQVJOMjpcbiAgICAgICAgLy8gdXNlIG5weCB3aXRoIGFsc28gZm9yIHlhcm4gJiBwbnBtIGR1ZSB0byByZXBvcnRlZCBpc3N1ZXNcbiAgICAgICAgLy8gQHNlZSBodHRwczovL2dpdGh1Yi5jb20vcHJvamVuL3Byb2plbi9pc3N1ZXMvNDE4MFxuICAgICAgICByZXR1cm4gYG5weCAke3RzTm9kZUFwcH1gO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIGBucHggJHt0c05vZGVBcHB9YDtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBFbnN1cmVzIGEgcGF0aCBpcyBwcm9wZXJseSBwcmVmaXhlZCB3aXRoICcuLycgaWYgaXQncyBhIHJlbGF0aXZlIHBhdGhcbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlUGF0aCAtIFRoZSBwYXRoIHRvIG5vcm1hbGl6ZVxuICogQHJldHVybnMge3N0cmluZ30gLSBUaGUgbm9ybWFsaXplZCBwYXRoXG4gKi9cbmZ1bmN0aW9uIGVuc3VyZVJlbGF0aXZlUGF0aFByZWZpeChmaWxlUGF0aDogc3RyaW5nKSB7XG4gIC8vIElmIGl0J3MgYWxyZWFkeSBhbiBhYnNvbHV0ZSBwYXRoLCByZXR1cm4gYXMgaXNcbiAgaWYgKHBhdGguaXNBYnNvbHV0ZShmaWxlUGF0aCkpIHtcbiAgICByZXR1cm4gZmlsZVBhdGg7XG4gIH1cblxuICAvLyBJZiBpdCBhbHJlYWR5IHN0YXJ0cyB3aXRoIC4vIG9yIC4uLywgcmV0dXJuIGFzIGlzXG4gIGlmIChmaWxlUGF0aC5zdGFydHNXaXRoKFwiLi9cIikgfHwgZmlsZVBhdGguc3RhcnRzV2l0aChcIi4uL1wiKSkge1xuICAgIHJldHVybiBmaWxlUGF0aDtcbiAgfVxuXG4gIC8vIE90aGVyd2lzZSwgYWRkIC4vIHByZWZpeFxuICByZXR1cm4gYC4vJHtmaWxlUGF0aH1gO1xufVxuXG5jbGFzcyBTYW1wbGVDb2RlIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBhcHBQcm9qZWN0OiBBd3NDZGtUeXBlU2NyaXB0QXBwO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb2plY3Q6IEF3c0Nka1R5cGVTY3JpcHRBcHAsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjZGtNYWpvclZlcnNpb246IG51bWJlclxuICApIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcbiAgICB0aGlzLmFwcFByb2plY3QgPSBwcm9qZWN0O1xuICB9XG5cbiAgcHVibGljIHN5bnRoZXNpemUoKSB7XG4gICAgY29uc3Qgb3V0ZGlyID0gdGhpcy5wcm9qZWN0Lm91dGRpcjtcbiAgICBjb25zdCBzcmNkaXIgPSBwYXRoLmpvaW4ob3V0ZGlyLCB0aGlzLmFwcFByb2plY3Quc3JjZGlyKTtcbiAgICBpZiAoXG4gICAgICBmcy5leGlzdHNTeW5jKHNyY2RpcikgJiZcbiAgICAgIGZzLnJlYWRkaXJTeW5jKHNyY2RpcikuZmlsdGVyKCh4KSA9PiB4LmVuZHNXaXRoKFwiLnRzXCIpKVxuICAgICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHNyY0ltcG9ydHMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICAgIGlmICh0aGlzLmNka01ham9yVmVyc2lvbiA8IDIpIHtcbiAgICAgIHNyY0ltcG9ydHMucHVzaChcbiAgICAgICAgXCJpbXBvcnQgeyBBcHAsIENvbnN0cnVjdCwgU3RhY2ssIFN0YWNrUHJvcHMgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcIlxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3JjSW1wb3J0cy5wdXNoKFwiaW1wb3J0IHsgQXBwLCBTdGFjaywgU3RhY2tQcm9wcyB9IGZyb20gJ2F3cy1jZGstbGliJztcIik7XG4gICAgICBzcmNJbXBvcnRzLnB1c2goXCJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcIik7XG4gICAgfVxuXG4gICAgY29uc3Qgc3JjQ29kZSA9IGAke3NyY0ltcG9ydHMuam9pbihcIlxcblwiKX1cblxuZXhwb3J0IGNsYXNzIE15U3RhY2sgZXh0ZW5kcyBTdGFjayB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBTdGFja1Byb3BzID0ge30pIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcblxuICAgIC8vIGRlZmluZSByZXNvdXJjZXMgaGVyZS4uLlxuICB9XG59XG5cbi8vIGZvciBkZXZlbG9wbWVudCwgdXNlIGFjY291bnQvcmVnaW9uIGZyb20gY2RrIGNsaVxuY29uc3QgZGV2RW52ID0ge1xuICBhY2NvdW50OiBwcm9jZXNzLmVudi5DREtfREVGQVVMVF9BQ0NPVU5ULFxuICByZWdpb246IHByb2Nlc3MuZW52LkNES19ERUZBVUxUX1JFR0lPTixcbn07XG5cbmNvbnN0IGFwcCA9IG5ldyBBcHAoKTtcblxubmV3IE15U3RhY2soYXBwLCAnJHt0aGlzLnByb2plY3QubmFtZX0tZGV2JywgeyBlbnY6IGRldkVudiB9KTtcbi8vIG5ldyBNeVN0YWNrKGFwcCwgJyR7dGhpcy5wcm9qZWN0Lm5hbWV9LXByb2QnLCB7IGVudjogcHJvZEVudiB9KTtcblxuYXBwLnN5bnRoKCk7YDtcblxuICAgIGZzLm1rZGlyU3luYyhzcmNkaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKHNyY2RpciwgdGhpcy5hcHBQcm9qZWN0LmFwcEVudHJ5cG9pbnQpLCBzcmNDb2RlKTtcblxuICAgIGNvbnN0IHRlc3RkaXIgPSBwYXRoLmpvaW4ob3V0ZGlyLCB0aGlzLmFwcFByb2plY3QudGVzdGRpcik7XG4gICAgaWYgKFxuICAgICAgZnMuZXhpc3RzU3luYyh0ZXN0ZGlyKSAmJlxuICAgICAgZnMucmVhZGRpclN5bmModGVzdGRpcikuZmlsdGVyKCh4KSA9PiB4LmVuZHNXaXRoKFwiLnRzXCIpKVxuICAgICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRlc3RJbXBvcnRzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBpZiAodGhpcy5jZGtNYWpvclZlcnNpb24gPCAyKSB7XG4gICAgICB0ZXN0SW1wb3J0cy5wdXNoKFwiaW1wb3J0IHsgQXBwIH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XCIpO1xuICAgICAgdGVzdEltcG9ydHMucHVzaChcImltcG9ydCB7IFRlbXBsYXRlIH0gZnJvbSAnQGF3cy1jZGsvYXNzZXJ0aW9ucyc7XCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0ZXN0SW1wb3J0cy5wdXNoKFwiaW1wb3J0IHsgQXBwIH0gZnJvbSAnYXdzLWNkay1saWInO1wiKTtcbiAgICAgIHRlc3RJbXBvcnRzLnB1c2goXCJpbXBvcnQgeyBUZW1wbGF0ZSB9IGZyb20gJ2F3cy1jZGstbGliL2Fzc2VydGlvbnMnO1wiKTtcbiAgICB9XG5cbiAgICBjb25zdCBhcHBFbnRyeXBvaW50TmFtZSA9IHBhdGguYmFzZW5hbWUoXG4gICAgICB0aGlzLmFwcFByb2plY3QuYXBwRW50cnlwb2ludCxcbiAgICAgIFwiLnRzXCJcbiAgICApO1xuICAgIGNvbnN0IHRlc3RDb2RlID0gYCR7dGVzdEltcG9ydHMuam9pbihcIlxcblwiKX1cbmltcG9ydCB7IE15U3RhY2sgfSBmcm9tICcuLi8ke3RoaXMuYXBwUHJvamVjdC5zcmNkaXJ9LyR7YXBwRW50cnlwb2ludE5hbWV9JztcblxudGVzdCgnU25hcHNob3QnLCAoKSA9PiB7XG4gIGNvbnN0IGFwcCA9IG5ldyBBcHAoKTtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgTXlTdGFjayhhcHAsICd0ZXN0Jyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICBleHBlY3QodGVtcGxhdGUudG9KU09OKCkpLnRvTWF0Y2hTbmFwc2hvdCgpO1xufSk7YDtcblxuICAgIGZzLm1rZGlyU3luYyh0ZXN0ZGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKFxuICAgICAgcGF0aC5qb2luKHRlc3RkaXIsIGAke2FwcEVudHJ5cG9pbnROYW1lfS50ZXN0LnRzYCksXG4gICAgICB0ZXN0Q29kZVxuICAgICk7XG4gIH1cbn1cbiJdfQ==