@aws/pdk
Version:
All documentation is located at: https://aws.github.io/aws-pdk
371 lines • 66.8 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeSafeWebSocketApiProject = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0 */
const path = require("path");
const monorepo_1 = require("../../monorepo");
const projen_1 = require("projen");
const javascript_1 = require("projen/lib/javascript");
const generate_1 = require("./codegen/generate");
const languages_1 = require("./languages");
/**
* Project for a Type Safe WebSocket API, defined using Smithy or OpenAPI.
*
* Generates a CDK construct to deploy your API, as well as client and server code to help build your API quickly.
*
* @experimental
* @pjid type-safe-ws-api
*/
class TypeSafeWebSocketApiProject extends projen_1.Project {
constructor(options) {
super(options);
this.getNxWorkspace = (options) => {
return options.parent ? monorepo_1.NxWorkspace.of(options.parent) : undefined;
};
const nxWorkspace = this.getNxWorkspace(options);
const isNxWorkspace = this.parent &&
(monorepo_1.ProjectUtils.isNamedInstanceOf(this.parent, monorepo_1.MonorepoTsProject) ||
monorepo_1.ProjectUtils.isNamedInstanceOf(this.parent, monorepo_1.MonorepoJavaProject) ||
monorepo_1.ProjectUtils.isNamedInstanceOf(this.parent, monorepo_1.MonorepoPythonProject));
const handlerLanguages = [...new Set(options.handlers?.languages ?? [])];
// Try to infer monorepo default release branch, otherwise default to mainline unless overridden
const defaultReleaseBranch = nxWorkspace?.affected.defaultBase ?? "mainline";
const packageManager = this.parent && monorepo_1.ProjectUtils.isNamedInstanceOf(this.parent, javascript_1.NodeProject)
? this.parent.package.packageManager
: javascript_1.NodePackageManager.PNPM;
// API Definition project containing the model
const modelDir = "model";
const parsedSpecFile = ".api.json";
const asyncApiSpecFile = ".asyncapi.json";
this.model = (0, generate_1.generateAsyncModelProject)({
parent: nxWorkspace ? this.parent : this,
outdir: nxWorkspace ? path.join(options.outdir, modelDir) : modelDir,
name: `${options.name}-model`,
modelLanguage: options.model.language,
modelOptions: options.model.options,
handlerLanguages,
packageManager,
defaultReleaseBranch,
parsedSpecFile,
asyncApiSpecFile,
});
const modelProject = [
this.model.openapi,
this.model.smithy,
this.model.typeSpec,
].filter((m) => m)[0];
// Ensure we always generate a runtime project for the infrastructure language, regardless of what was specified by
// the user. Likewise we generate a runtime project for any handler languages specified
const runtimeLanguages = [
...new Set([
...(options.runtime?.languages ?? []),
options.infrastructure.language,
...(options.handlers?.languages ?? []),
]),
];
// TODO: Delete when python/java support is implemented
if (runtimeLanguages.includes(languages_1.Language.JAVA) ||
runtimeLanguages.includes(languages_1.Language.PYTHON)) {
const errorMessages = [
...(runtimeLanguages.includes(languages_1.Language.PYTHON)
? [
"Python is not supported by Type Safe WebSocket API. Please +1 this issue if needed: https://github.com/aws/aws-pdk/issues/741",
]
: []),
...(runtimeLanguages.includes(languages_1.Language.JAVA)
? [
"Java is not supported by Type Safe WebSocket API. Please +1 this issue if needed: https://github.com/aws/aws-pdk/issues/740",
]
: []),
];
throw new Error(errorMessages.join("\n"));
}
const generatedDir = "generated";
const runtimeDir = path.join(generatedDir, "runtime");
const runtimeDirRelativeToParent = nxWorkspace
? path.join(options.outdir, runtimeDir)
: runtimeDir;
// Path from a generated package directory (eg api/generated/runtime/typescript) to the model dir (ie api/model)
const relativePathToModelDirFromGeneratedPackageDir = path.relative(path.join(this.outdir, runtimeDir, "language"), path.join(this.outdir, modelDir));
const parsedSpecRelativeToGeneratedPackageDir = path.join(relativePathToModelDirFromGeneratedPackageDir, this.model.parsedSpecFile);
// Declare the generated runtime projects
const generatedRuntimeProjects = (0, generate_1.generateAsyncRuntimeProjects)(runtimeLanguages, {
parent: nxWorkspace ? this.parent : this,
parentPackageName: this.name,
generatedCodeDir: runtimeDirRelativeToParent,
isWithinMonorepo: isNxWorkspace,
// Spec path relative to each generated runtime dir
parsedSpecPath: parsedSpecRelativeToGeneratedPackageDir,
typescriptOptions: {
defaultReleaseBranch,
packageManager,
...options.runtime?.options?.typescript,
},
pythonOptions: {
authorName: "APJ Cope",
authorEmail: "apj-cope@amazon.com",
version: "0.0.0",
...options.runtime?.options?.python,
},
javaOptions: {
version: "0.0.0",
...options.runtime?.options?.java,
},
});
const documentationFormats = [
...new Set(options.documentation?.formats ?? []),
];
const docsDir = path.join(generatedDir, "documentation");
const docsDirRelativeToParent = nxWorkspace
? path.join(options.outdir, docsDir)
: docsDir;
// AsyncAPI specification is used for WebSocket documentation generation
const asyncapiJsonFilePathRelativeToGeneratedPackageDir = path.join(relativePathToModelDirFromGeneratedPackageDir, this.model.asyncApiSpecFile);
const generatedDocs = (0, generate_1.generateDocsProjects)(documentationFormats, {
parent: nxWorkspace ? this.parent : this,
parentPackageName: this.name,
generatedDocsDir: docsDirRelativeToParent,
// Spec path relative to each generated doc format dir
parsedSpecPath: asyncapiJsonFilePathRelativeToGeneratedPackageDir,
asyncDocumentationOptions: options.documentation?.options,
});
// Documentation projects use AsyncAPI generator which can intermittently fail
// when executed in parallel to other AsyncAPI generator commands. We protect against this
// by ensuring documentation projects are built sequentially.
const docProjects = Object.values(generatedDocs);
docProjects.forEach((docProject, i) => {
if (docProjects[i - 1]) {
monorepo_1.NxProject.ensure(docProjects[i - 1]).addImplicitDependency(docProject);
}
});
this.documentation = {
html: generatedDocs[languages_1.WebSocketDocumentationFormat.HTML],
markdown: generatedDocs[languages_1.WebSocketDocumentationFormat.MARKDOWN],
};
const librarySet = new Set(options.library?.libraries ?? []);
// Hooks depend on client, so always add the client if we specified hooks
if (librarySet.has(languages_1.WebSocketLibrary.TYPESCRIPT_WEBSOCKET_HOOKS)) {
librarySet.add(languages_1.WebSocketLibrary.TYPESCRIPT_WEBSOCKET_CLIENT);
}
const libraries = [...librarySet];
const libraryDir = path.join(generatedDir, "libraries");
const libraryDirRelativeToParent = nxWorkspace
? path.join(options.outdir, libraryDir)
: libraryDir;
// Declare the generated runtime projects
const generatedLibraryProjects = (0, generate_1.generateAsyncLibraryProjects)(libraries, {
parent: nxWorkspace ? this.parent : this,
parentPackageName: this.name,
generatedCodeDir: libraryDirRelativeToParent,
isWithinMonorepo: isNxWorkspace,
// Spec path relative to each generated library dir
parsedSpecPath: parsedSpecRelativeToGeneratedPackageDir,
typescriptWebSocketClientOptions: {
defaultReleaseBranch,
packageManager,
...options.library?.options?.typescriptWebSocketClient,
},
typescriptWebSocketHooksOptions: {
defaultReleaseBranch,
clientPackageName: options.library?.options?.typescriptWebSocketClient?.name,
packageManager,
...options.library?.options?.typescriptWebSocketHooks,
},
});
// Ensure the generated runtime, libraries and docs projects have a dependency on the model project
if (this.parent) {
[
...Object.values(generatedRuntimeProjects),
...Object.values(generatedDocs),
...Object.values(generatedLibraryProjects),
].forEach((project) => {
monorepo_1.NxProject.ensure(project).addImplicitDependency(modelProject);
});
}
this.runtime = {
typescript: generatedRuntimeProjects[languages_1.Language.TYPESCRIPT]
? generatedRuntimeProjects[languages_1.Language.TYPESCRIPT]
: undefined,
java: generatedRuntimeProjects[languages_1.Language.JAVA]
? generatedRuntimeProjects[languages_1.Language.JAVA]
: undefined,
python: generatedRuntimeProjects[languages_1.Language.PYTHON]
? generatedRuntimeProjects[languages_1.Language.PYTHON]
: undefined,
};
this.library = {
typescriptWebSocketClient: generatedLibraryProjects[languages_1.WebSocketLibrary.TYPESCRIPT_WEBSOCKET_CLIENT]
? generatedLibraryProjects[languages_1.WebSocketLibrary.TYPESCRIPT_WEBSOCKET_CLIENT]
: undefined,
typescriptWebSocketHooks: generatedLibraryProjects[languages_1.WebSocketLibrary.TYPESCRIPT_WEBSOCKET_HOOKS]
? generatedLibraryProjects[languages_1.WebSocketLibrary.TYPESCRIPT_WEBSOCKET_HOOKS]
: undefined,
};
// For the hooks library, add a dependency on the client
if (this.library.typescriptWebSocketHooks &&
this.library.typescriptWebSocketClient) {
this.library.typescriptWebSocketHooks.addDeps(this.library.typescriptWebSocketClient.package.packageName);
}
const handlersDir = "handlers";
const handlersDirRelativeToParent = nxWorkspace
? path.join(options.outdir, handlersDir)
: handlersDir;
const relativePathToModelDirFromHandlersDir = path.relative(path.join(this.outdir, handlersDir, "language"), path.join(this.outdir, modelDir));
const parsedSpecRelativeToHandlersDir = path.join(relativePathToModelDirFromHandlersDir, this.model.parsedSpecFile);
// Declare the generated handlers projects
const generatedHandlersProjects = (0, generate_1.generateAsyncHandlersProjects)(handlerLanguages, {
parent: nxWorkspace ? this.parent : this,
parentPackageName: this.name,
generatedCodeDir: handlersDirRelativeToParent,
isWithinMonorepo: isNxWorkspace,
// Spec path relative to each generated handlers package dir
parsedSpecPath: parsedSpecRelativeToHandlersDir,
typescriptOptions: {
defaultReleaseBranch,
packageManager,
...options.handlers?.options?.typescript,
},
pythonOptions: {
authorName: "APJ Cope",
authorEmail: "apj-cope@amazon.com",
version: "0.0.0",
...options.handlers?.options?.python,
},
javaOptions: {
version: "0.0.0",
...options.handlers?.options?.java,
},
generatedRuntimes: {
typescript: this.runtime.typescript,
python: this.runtime.python,
java: this.runtime.java,
},
});
this.handlers = {
typescript: generatedHandlersProjects[languages_1.Language.TYPESCRIPT]
? generatedHandlersProjects[languages_1.Language.TYPESCRIPT]
: undefined,
java: generatedHandlersProjects[languages_1.Language.JAVA]
? generatedHandlersProjects[languages_1.Language.JAVA]
: undefined,
python: generatedHandlersProjects[languages_1.Language.PYTHON]
? generatedHandlersProjects[languages_1.Language.PYTHON]
: undefined,
};
// Ensure the handlers project depends on the appropriate runtime projects
if (this.handlers.typescript) {
monorepo_1.NxProject.ensure(this.handlers.typescript).addImplicitDependency(this.runtime.typescript);
}
if (this.handlers.java) {
monorepo_1.NxProject.ensure(this.handlers.java).addImplicitDependency(this.runtime.java);
}
if (this.handlers.python) {
monorepo_1.NxProject.ensure(this.handlers.python).addImplicitDependency(this.runtime.python);
}
const infraDir = path.join(generatedDir, "infrastructure");
const infraDirRelativeToParent = nxWorkspace
? path.join(options.outdir, infraDir)
: infraDir;
// Infrastructure project
const infraProject = (0, generate_1.generateAsyncInfraProject)(options.infrastructure.language, {
parent: nxWorkspace ? this.parent : this,
parentPackageName: this.name,
generatedCodeDir: infraDirRelativeToParent,
isWithinMonorepo: isNxWorkspace,
// Spec path relative to each generated infra package dir
parsedSpecPath: parsedSpecRelativeToGeneratedPackageDir,
typescriptOptions: {
defaultReleaseBranch,
packageManager,
...options.infrastructure.options?.typescript,
},
pythonOptions: {
authorName: "APJ Cope",
authorEmail: "apj-cope@amazon.com",
version: "0.0.0",
...options.infrastructure.options?.python,
},
javaOptions: {
version: "0.0.0",
...options.infrastructure.options?.java,
},
generatedRuntimes: {
typescript: this.runtime.typescript,
python: this.runtime.python,
java: this.runtime.java,
},
generatedHandlers: {
typescript: this.handlers.typescript,
python: this.handlers.python,
java: this.handlers.java,
},
});
const infraProjects = {};
// Add implicit dependencies and assign the appropriate infrastructure project member
switch (options.infrastructure.language) {
case languages_1.Language.JAVA:
monorepo_1.NxProject.ensure(infraProject).addImplicitDependency(this.runtime.java);
infraProjects.java = infraProject;
break;
case languages_1.Language.PYTHON:
monorepo_1.NxProject.ensure(infraProject).addImplicitDependency(this.runtime.python);
infraProjects.python = infraProject;
break;
case languages_1.Language.TYPESCRIPT:
monorepo_1.NxProject.ensure(infraProject).addImplicitDependency(this.runtime.typescript);
infraProjects.typescript = infraProject;
break;
default:
throw new Error(`Unknown infrastructure language ${options.infrastructure.language}`);
}
this.infrastructure = infraProjects;
monorepo_1.NxProject.ensure(infraProject).addImplicitDependency(modelProject);
// Expose collections of projects
const allRuntimes = Object.values(generatedRuntimeProjects);
const allInfrastructure = [infraProject];
const allLibraries = Object.values(generatedLibraryProjects);
const allDocumentation = Object.values(generatedDocs);
const allHandlers = Object.values(generatedHandlersProjects);
this.all = {
model: [modelProject],
runtimes: allRuntimes,
infrastructure: allInfrastructure,
libraries: allLibraries,
documentation: allDocumentation,
handlers: allHandlers,
projects: [
modelProject,
...allRuntimes,
...allInfrastructure,
...allLibraries,
...allDocumentation,
...allHandlers,
],
};
if (!nxWorkspace) {
// Add a task for the non-monorepo case to build the projects in the right order
[
modelProject,
...Object.values(generatedRuntimeProjects),
infraProject,
...Object.values(generatedLibraryProjects),
...Object.values(generatedDocs),
].forEach((project) => {
this.compileTask.exec("npx projen build", {
cwd: path.relative(this.outdir, project.outdir),
});
});
}
// Add the README as a sample file which the user may edit
new projen_1.SampleFile(this, "README.md", {
sourcePath: path.resolve(__dirname, "..", "..", "samples", "type-safe-api", "readme", "TYPE_SAFE_API.md"),
});
}
}
exports.TypeSafeWebSocketApiProject = TypeSafeWebSocketApiProject;
_a = JSII_RTTI_SYMBOL_1;
TypeSafeWebSocketApiProject[_a] = { fqn: "@aws/pdk.type_safe_api.TypeSafeWebSocketApiProject", version: "0.26.14" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZS1zYWZlLXdlYnNvY2tldC1hcGktcHJvamVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInR5cGUtc2FmZS13ZWJzb2NrZXQtYXBpLXByb2plY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtzQ0FDc0M7QUFDdEMsNkJBQTZCO0FBQzdCLDRDQU91QjtBQUN2QixtQ0FBNkQ7QUFFN0Qsc0RBQXdFO0FBR3hFLGlEQU80QjtBQU81QiwyQ0FJcUI7QUF3SHJCOzs7Ozs7O0dBT0c7QUFDSCxNQUFhLDJCQUE0QixTQUFRLGdCQUFPO0lBK0J0RCxZQUFZLE9BQTJDO1FBQ3JELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQThjVCxtQkFBYyxHQUFHLENBQ3ZCLE9BQTJDLEVBQ2xCLEVBQUU7WUFDM0IsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxzQkFBVyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUNyRSxDQUFDLENBQUM7UUFoZEEsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqRCxNQUFNLGFBQWEsR0FDakIsSUFBSSxDQUFDLE1BQU07WUFDWCxDQUFDLHVCQUFZLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSw0QkFBaUIsQ0FBQztnQkFDN0QsdUJBQVksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLDhCQUFtQixDQUFDO2dCQUNoRSx1QkFBWSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsZ0NBQXFCLENBQUMsQ0FBQyxDQUFDO1FBRXhFLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsU0FBUyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFekUsZ0dBQWdH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O2FBQ2hDLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO29CQUN4QyxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUM7aUJBQ2hELENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELDBEQUEwRDtRQUMxRCxJQUFJLG1CQUFVLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUNoQyxVQUFVLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FDdEIsU0FBUyxFQUNULElBQUksRUFDSixJQUFJLEVBQ0osU0FBUyxFQUNULGVBQWUsRUFDZixRQUFRLEVBQ1Isa0JBQWtCLENBQ25CO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUE1ZUgsa0VBbWZDIiwic291cmNlc0NvbnRlbnQiOlsiLyohIENvcHlyaWdodCBbQW1hem9uLmNvbV0oaHR0cDovL2FtYXpvbi5jb20vKSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wICovXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQge1xuICBNb25vcmVwb1RzUHJvamVjdCxcbiAgTW9ub3JlcG9KYXZhUHJvamVjdCxcbiAgTW9ub3JlcG9QeXRob25Qcm9qZWN0LFxuICBOeFByb2plY3QsXG4gIE54V29ya3NwYWNlLFxuICBQcm9qZWN0VXRpbHMsXG59IGZyb20gXCJAYXdzL21vbm9yZXBvXCI7XG5pbXBvcnQgeyBQcm9qZWN0LCBQcm9qZWN0T3B0aW9ucywgU2FtcGxlRmlsZSB9IGZyb20gXCJwcm9qZW5cIjtcbmltcG9ydCB7IEphdmFQcm9qZWN0IH0gZnJvbSBcInByb2plbi9saWIvamF2YVwiO1xuaW1wb3J0IHsgTm9kZVBhY2thZ2VNYW5hZ2VyLCBOb2RlUHJvamVjdCB9IGZyb20gXCJwcm9qZW4vbGliL2phdmFzY3JpcHRcIjtcbmltcG9ydCB7IFB5dGhvblByb2plY3QgfSBmcm9tIFwicHJvamVuL2xpYi9weXRob25cIjtcbmltcG9ydCB7IFR5cGVTY3JpcHRQcm9qZWN0IH0gZnJvbSBcInByb2plbi9saWIvdHlwZXNjcmlwdFwiO1xuaW1wb3J0IHtcbiAgZ2VuZXJhdGVEb2NzUHJvamVjdHMsXG4gIGdlbmVyYXRlQXN5bmNSdW50aW1lUHJvamVjdHMsXG4gIGdlbmVyYXRlQXN5bmNIYW5kbGVyc1Byb2plY3RzLFxuICBnZW5lcmF0ZUFzeW5jSW5mcmFQcm9qZWN0LFxuICBnZW5lcmF0ZUFzeW5jTGlicmFyeVByb2plY3RzLFxuICBnZW5lcmF0ZUFzeW5jTW9kZWxQcm9qZWN0LFxufSBmcm9tIFwiLi9jb2RlZ2VuL2dlbmVyYXRlXCI7XG5pbXBvcnQgeyBHZW5lcmF0ZWRKYXZhQXN5bmNIYW5kbGVyc1Byb2plY3QgfSBmcm9tIFwiLi9jb2RlZ2VuL2hhbmRsZXJzL2dlbmVyYXRlZC1qYXZhLWFzeW5jLWhhbmRsZXJzLXByb2plY3RcIjtcbmltcG9ydCB7IEdlbmVyYXRlZFB5dGhvbkFzeW5jSGFuZGxlcnNQcm9qZWN0IH0gZnJvbSBcIi4vY29kZWdlbi9oYW5kbGVycy9nZW5lcmF0ZWQtcHl0aG9uLWFzeW5jLWhhbmRsZXJzLXByb2plY3RcIjtcbmltcG9ydCB7IEdlbmVyYXRlZFR5cGVzY3JpcHRBc3luY0hhbmRsZXJzUHJvamVjdCB9IGZyb20gXCIuL2NvZGVnZW4vaGFuZGxlcnMvZ2VuZXJhdGVkLXR5cGVzY3JpcHQtYXN5bmMtaGFuZGxlcnMtcHJvamVjdFwiO1xuaW1wb3J0IHsgR2VuZXJhdGVkSmF2YUFzeW5jUnVudGltZVByb2plY3QgfSBmcm9tIFwiLi9jb2RlZ2VuL3J1bnRpbWUvZ2VuZXJhdGVkLWphdmEtYXN5bmMtcnVudGltZS1wcm9qZWN0XCI7XG5pbXBvcnQgeyBHZW5lcmF0ZWRQeXRob25Bc3luY1J1bnRpbWVQcm9qZWN0IH0gZnJvbSBcIi4vY29kZWdlbi9ydW50aW1lL2dlbmVyYXRlZC1weXRob24tYXN5bmMtcnVudGltZS1wcm9qZWN0XCI7XG5pbXBvcnQgeyBHZW5lcmF0ZWRUeXBlc2NyaXB0QXN5bmNSdW50aW1lUHJvamVjdCB9IGZyb20gXCIuL2NvZGVnZW4vcnVudGltZS9nZW5lcmF0ZWQtdHlwZXNjcmlwdC1hc3luYy1ydW50aW1lLXByb2plY3RcIjtcbmltcG9ydCB7XG4gIExhbmd1YWdlLFxuICBXZWJTb2NrZXREb2N1bWVudGF0aW9uRm9ybWF0LFxuICBXZWJTb2NrZXRMaWJyYXJ5LFxufSBmcm9tIFwiLi9sYW5ndWFnZXNcIjtcbmltcG9ydCB7IE1vZGVsQ29uZmlndXJhdGlvbiB9IGZyb20gXCIuL3R5cGUtc2FmZS1hcGktcHJvamVjdFwiO1xuaW1wb3J0IHtcbiAgR2VuZXJhdGVkUnVudGltZUNvZGVPcHRpb25zLFxuICBHZW5lcmF0ZWRDb2RlUHJvamVjdHMsXG4gIEdlbmVyYXRlZEluZnJhc3RydWN0dXJlQ29kZU9wdGlvbnMsXG4gIEdlbmVyYXRlZEhhbmRsZXJzQ29kZU9wdGlvbnMsXG4gIFByb2plY3RDb2xsZWN0aW9ucyxcbiAgR2VuZXJhdGVkV2ViU29ja2V0TGlicmFyeU9wdGlvbnMsXG4gIEdlbmVyYXRlZFdlYlNvY2tldExpYnJhcnlQcm9qZWN0cyxcbiAgR2VuZXJhdGVkV2ViU29ja2V0RG9jdW1lbnRhdGlvblByb2plY3RzLFxuICBHZW5lcmF0ZWRXZWJTb2NrZXREb2N1bWVudGF0aW9uT3B0aW9ucyxcbiAgV2ViU29ja2V0TW9kZWxQcm9qZWN0LFxufSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIGdlbmVyYXRlZCBydW50aW1lIHByb2plY3RzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV2ViU29ja2V0UnVudGltZUNvbmZpZ3VyYXRpb24ge1xuICAvKipcbiAgICogVGhlIGxhbmd1YWdlcyB0aGF0IHJ1bnRpbWUgcHJvamVjdHMgd2lsbCBiZSBnZW5lcmF0ZWQgaW4uIFRoZXNlIHByb2plY3RzIGNhbiBiZSB1c2VkIHRvIHByb3ZpZGUgdHlwZSBzYWZldHkgZm9yXG4gICAqIGJvdGggY2xpZW50IGFuZCBzZXJ2ZXIgcHJvamVjdHMuXG4gICAqL1xuICByZWFkb25seSBsYW5ndWFnZXM6IExhbmd1YWdlW107XG4gIC8qKlxuICAgKiBPcHRpb25zIGZvciB0aGUgZ2VuZXJhdGVkIHJ1bnRpbWVzLiBOb3RlIHRoYXQgb25seSBvcHRpb25zIHByb3ZpZGVkIGZvciB0aGUgc3BlY2lmaWVkIGxhbmd1YWdlcyB3aWxsIGFwcGx5LlxuICAgKi9cbiAgcmVhZG9ubHkgb3B0aW9ucz86IEdlbmVyYXRlZFJ1bnRpbWVDb2RlT3B0aW9ucztcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciBnZW5lcmF0ZWQgaW5mcmFzdHJ1Y3R1cmVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJTb2NrZXRJbmZyYXN0cnVjdHVyZUNvbmZpZ3VyYXRpb24ge1xuICAvKipcbiAgICogVGhlIGxhbmd1YWdlIHRvIGdlbmVyYXRlIHRoZSB0eXBlLXNhZmUgQ0RLIGluZnJhc3RydWN0dXJlIGluXG4gICAqL1xuICByZWFkb25seSBsYW5ndWFnZTogTGFuZ3VhZ2U7XG4gIC8qKlxuICAgKiBPcHRpb25zIGZvciB0aGUgaW5mcmFzdHJ1Y3R1cmUgcGFja2FnZS4gTm90ZSB0aGF0IG9ubHkgdGhvc2UgcHJvdmlkZWQgZm9yIHRoZSBzcGVjaWZpZWQgbGFuZ3VhZ2Ugd2lsbCBhcHBseS5cbiAgICovXG4gIHJlYWRvbmx5IG9wdGlvbnM/OiBHZW5lcmF0ZWRJbmZyYXN0cnVjdHVyZUNvZGVPcHRpb25zO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIGdlbmVyYXRlZCBsYW1iZGEgaGFuZGxlcnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJTb2NrZXRIYW5kbGVyc0NvbmZpZ3VyYXRpb24ge1xuICAvKipcbiAgICogVGhlIGxhbmd1YWdlcyBsYW1iZGEgaGFuZGxlcnMgYXJlIHdyaXR0ZW4gaW4uIFNwZWNpZnkgbXVsdGlwbGUgbGFuZ3VhZ2VzIGlmIHlvdSB3aXNoIHRvIGltcGxlbWVudCBkaWZmZXJlbnQgb3BlcmF0aW9uc1xuICAgKiBhcyBBV1MgTGFtYmRhIGZ1bmN0aW9ucyBpbiBkaWZmZXJlbnQgbGFuZ3VhZ2VzLlxuICAgKi9cbiAgcmVhZG9ubHkgbGFuZ3VhZ2VzOiBMYW5ndWFnZVtdO1xuICAvKipcbiAgICogT3B0aW9ucyBmb3IgdGhlIGluZnJhc3RydWN0dXJlIHBhY2thZ2UuIE5vdGUgdGhhdCBvbmx5IHRob3NlIHByb3ZpZGVkIGZvciB0aGUgc3BlY2lmaWVkIGxhbmd1YWdlIHdpbGwgYXBwbHkuXG4gICAqL1xuICByZWFkb25seSBvcHRpb25zPzogR2VuZXJhdGVkSGFuZGxlcnNDb2RlT3B0aW9ucztcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciBnZW5lcmF0ZWQgZG9jdW1lbnRhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdlYlNvY2tldERvY3VtZW50YXRpb25Db25maWd1cmF0aW9uIHtcbiAgLyoqXG4gICAqIEZvcm1hdHMgZm9yIGdlbmVyYXRlZCBkb2N1bWVudGF0aW9uXG4gICAqL1xuICByZWFkb25seSBmb3JtYXRzOiBXZWJTb2NrZXREb2N1bWVudGF0aW9uRm9ybWF0W107XG4gIC8qKlxuICAgKiBPcHRpb25zIGZvciB0aGUgZ2VuZXJhdGVkIGRvY3VtZW50YXRpb24gcHJvamVjdHMuIE5vdGUgdGhhdCBvbmx5IHRob3NlIHByb3ZpZGVkIGZvciB0aGUgc3BlY2lmaWVkIGZvcm1hdHMgd2lsbCBhcHBseVxuICAgKi9cbiAgcmVhZG9ubHkgb3B0aW9ucz86IEdlbmVyYXRlZFdlYlNvY2tldERvY3VtZW50YXRpb25PcHRpb25zO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIGdlbmVyYXRlZCBsaWJyYXJpZXNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJTb2NrZXRMaWJyYXJ5Q29uZmlndXJhdGlvbiB7XG4gIC8qKlxuICAgKiBUaGUgbGlicmFyaWVzIHRvIGdlbmVyYXRlXG4gICAqL1xuICByZWFkb25seSBsaWJyYXJpZXM6IFdlYlNvY2tldExpYnJhcnlbXTtcbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIHRoZSBnZW5lcmF0ZWQgbGlicmFyeSBwYWNrYWdlLiBOb3RlIHRoYXQgb25seSBvcHRpb25zIGZvciB0aGUgc3BlY2lmaWVkIGxpYnJhcmllcyB3aWxsIGFwcGx5XG4gICAqL1xuICByZWFkb25seSBvcHRpb25zPzogR2VuZXJhdGVkV2ViU29ja2V0TGlicmFyeU9wdGlvbnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHlwZVNhZmVXZWJTb2NrZXRBcGlNb2RlbENvbmZpZ3VyYXRpb25cbiAgZXh0ZW5kcyBNb2RlbENvbmZpZ3VyYXRpb24ge31cblxuLyoqXG4gKiBPcHRpb25zIGZvciB0aGUgVHlwZVNhZmVXZWJTb2NrZXRBcGlQcm9qZWN0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHlwZVNhZmVXZWJTb2NrZXRBcGlQcm9qZWN0T3B0aW9ucyBleHRlbmRzIFByb2plY3RPcHRpb25zIHtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBBUEkgbW9kZWxcbiAgICovXG4gIHJlYWRvbmx5IG1vZGVsOiBUeXBlU2FmZVdlYlNvY2tldEFwaU1vZGVsQ29uZmlndXJhdGlvbjtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIGdlbmVyYXRlZCBydW50aW1lIHByb2plY3RzIChjb250YWluaW5nIHR5cGVzLCBjbGllbnRzIGFuZCBzZXJ2ZXIgY29kZSlcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnRpbWU/OiBXZWJTb2NrZXRSdW50aW1lQ29uZmlndXJhdGlvbjtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIGdlbmVyYXRlZCBpbmZyYXN0cnVjdHVyZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5mcmFzdHJ1Y3R1cmU6IFdlYlNvY2tldEluZnJhc3RydWN0dXJlQ29uZmlndXJhdGlvbjtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIGxhbWJkYSBoYW5kbGVycyBmb3IgaW1wbGVtZW50aW5nIHRoZSBBUElcbiAgICovXG4gIHJlYWRvbmx5IGhhbmRsZXJzPzogV2ViU29ja2V0SGFuZGxlcnNDb25maWd1cmF0aW9uO1xuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiBmb3IgZ2VuZXJhdGVkIGRvY3VtZW50YXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGRvY3VtZW50YXRpb24/OiBXZWJTb2NrZXREb2N1bWVudGF0aW9uQ29uZmlndXJhdGlvbjtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIGdlbmVyYXRlZCBsaWJyYXJpZXMuIFRoZXNlIGluY2x1ZGUgY2xpZW50cyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB5b3VyIHdlYnNvY2tldCBBUElcbiAgICovXG4gIHJlYWRvbmx5IGxpYnJhcnk/OiBXZWJTb2NrZXRMaWJyYXJ5Q29uZmlndXJhdGlvbjtcbn1cblxuLyoqXG4gKiBQcm9qZWN0IGZvciBhIFR5cGUgU2FmZSBXZWJTb2NrZXQgQVBJLCBkZWZpbmVkIHVzaW5nIFNtaXRoeSBvciBPcGVuQVBJLlxuICpcbiAqIEdlbmVyYXRlcyBhIENESyBjb25zdHJ1Y3QgdG8gZGVwbG95IHlvdXIgQVBJLCBhcyB3ZWxsIGFzIGNsaWVudCBhbmQgc2VydmVyIGNvZGUgdG8gaGVscCBidWlsZCB5b3VyIEFQSSBxdWlja2x5LlxuICpcbiAqIEBleHBlcmltZW50YWxcbiAqIEBwamlkIHR5cGUtc2FmZS13cy1hcGlcbiAqL1xuZXhwb3J0IGNsYXNzIFR5cGVTYWZlV2ViU29ja2V0QXBpUHJvamVjdCBleHRlbmRzIFByb2plY3Qge1xuICAvKipcbiAgICogUHJvamVjdCBmb3IgdGhlIGFwaSBtb2RlbC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBtb2RlbDogV2ViU29ja2V0TW9kZWxQcm9qZWN0O1xuICAvKipcbiAgICogR2VuZXJhdGVkIHJ1bnRpbWUgcHJvamVjdHMuIFdoZW4gYHJ1bnRpbWUubGFuZ3VhZ2VzYCBpbmNsdWRlcyB0aGUgY29ycmVzcG9uZGluZyBsYW5ndWFnZSwgdGhlIHByb2plY3QgY2FuIGJlXG4gICAqIGFzc3VtZWQgdG8gYmUgZGVmaW5lZC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBydW50aW1lOiBHZW5lcmF0ZWRDb2RlUHJvamVjdHM7XG4gIC8qKlxuICAgKiBHZW5lcmF0ZWQgaW5mcmFzdHJ1Y3R1cmUgcHJvamVjdHMuIE9ubHkgdGhlIHByb3BlcnR5IGNvcnJlc3BvbmRpbmcgdG8gYGluZnJhc3RydWN0dXJlLmxhbmd1YWdlYCB3aWxsIGJlIGRlZmluZWQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaW5mcmFzdHJ1Y3R1cmU6IEdlbmVyYXRlZENvZGVQcm9qZWN0cztcbiAgLyoqXG4gICAqIExhbWJkYSBoYW5kbGVycyBwcm9qZWN0cy4gT25seSB0aGUgcHJvcGVydGllcyBjb3JyZXNwb25kaW5nIHRvIGBoYW5kbGVycy5sYW5ndWFnZXNgIHdpbGwgYmUgZGVmaW5lZC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBoYW5kbGVyczogR2VuZXJhdGVkQ29kZVByb2plY3RzO1xuICAvKipcbiAgICogR2VuZXJhdGVkIGxpYnJhcnkgcHJvamVjdHMuIE9ubHkgdGhlIHByb3BlcnRpZXMgY29ycmVzcG9uZGluZyB0byBzcGVjaWZpZWQgYGxpYnJhcnkubGlicmFyaWVzYCB3aWxsIGJlIGRlZmluZWQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbGlicmFyeTogR2VuZXJhdGVkV2ViU29ja2V0TGlicmFyeVByb2plY3RzO1xuICAvKipcbiAgICogR2VuZXJhdGVkIGRvY3VtZW50YXRpb24gcHJvamVjdHMuIE9ubHkgdGhlIHByb3BlcnRpZXMgY29ycmVzcG9uZGluZyB0byBzcGVjaWZpZWQgYGRvY3VtZW50YXRpb24uZm9ybWF0c2Agd2lsbCBiZSBkZWZpbmVkLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRvY3VtZW50YXRpb246IEdlbmVyYXRlZFdlYlNvY2tldERvY3VtZW50YXRpb25Qcm9qZWN0cztcbiAgLyoqXG4gICAqIENvbGxlY3Rpb25zIG9mIGFsbCBzdWItcHJvamVjdHMgbWFuYWdlZCBieSB0aGlzIHByb2plY3RcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhbGw6IFByb2plY3RDb2xsZWN0aW9ucztcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBUeXBlU2FmZVdlYlNvY2tldEFwaVByb2plY3RPcHRpb25zKSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG5cbiAgICBjb25zdCBueFdvcmtzcGFjZSA9IHRoaXMuZ2V0TnhXb3Jrc3BhY2Uob3B0aW9ucyk7XG5cbiAgICBjb25zdCBpc054V29ya3NwYWNlID1cbiAgICAgIHRoaXMucGFyZW50ICYmXG4gICAgICAoUHJvamVjdFV0aWxzLmlzTmFtZWRJbnN0YW5jZU9mKHRoaXMucGFyZW50LCBNb25vcmVwb1RzUHJvamVjdCkgfHxcbiAgICAgICAgUHJvamVjdFV0aWxzLmlzTmFtZWRJbnN0YW5jZU9mKHRoaXMucGFyZW50LCBNb25vcmVwb0phdmFQcm9qZWN0KSB8fFxuICAgICAgICBQcm9qZWN0VXRpbHMuaXNOYW1lZEluc3RhbmNlT2YodGhpcy5wYXJlbnQsIE1vbm9yZXBvUHl0aG9uUHJvamVjdCkpO1xuXG4gICAgY29uc3QgaGFuZGxlckxhbmd1YWdlcyA9IFsuLi5uZXcgU2V0KG9wdGlvbnMuaGFuZGxlcnM/Lmxhbmd1YWdlcyA/PyBbXSldO1xuXG4gICAgLy8gVHJ5IHRvIGluZmVyIG1vbm9yZXBvIGRlZmF1bHQgcmVsZWFzZSBicmFuY2gsIG90aGVyd2lzZSBkZWZhdWx0IHRvIG1haW5saW5lIHVubGVzcyBvdmVycmlkZGVuXG4gICAgY29uc3QgZGVmYXVsdFJlbGVhc2VCcmFuY2ggPVxuICAgICAgbnhXb3Jrc3BhY2U/LmFmZmVjdGVkLmRlZmF1bHRCYXNlID8/IFwibWFpbmxpbmVcIjtcbiAgICBjb25zdCBwYWNrYWdlTWFuYWdlciA9XG4gICAgICB0aGlzLnBhcmVudCAmJiBQcm9qZWN0VXRpbHMuaXNOYW1lZEluc3RhbmNlT2YodGhpcy5wYXJlbnQsIE5vZGVQcm9qZWN0KVxuICAgICAgICA/IHRoaXMucGFyZW50LnBhY2thZ2UucGFja2FnZU1hbmFnZXJcbiAgICAgICAgOiBOb2RlUGFja2FnZU1hbmFnZXIuUE5QTTtcblxuICAgIC8vIEFQSSBEZWZpbml0aW9uIHByb2plY3QgY29udGFpbmluZyB0aGUgbW9kZWxcbiAgICBjb25zdCBtb2RlbERpciA9IFwibW9kZWxcIjtcbiAgICBjb25zdCBwYXJzZWRTcGVjRmlsZSA9IFwiLmFwaS5qc29uXCI7XG4gICAgY29uc3QgYXN5bmNBcGlTcGVjRmlsZSA9IFwiLmFzeW5jYXBpLmpzb25cIjtcbiAgICB0aGlzLm1vZGVsID0gZ2VuZXJhdGVBc3luY01vZGVsUHJvamVjdCh7XG4gICAgICBwYXJlbnQ6IG54V29ya3NwYWNlID8gdGhpcy5wYXJlbnQgOiB0aGlzLFxuICAgICAgb3V0ZGlyOiBueFdvcmtzcGFjZSA/IHBhdGguam9pbihvcHRpb25zLm91dGRpciEsIG1vZGVsRGlyKSA6IG1vZGVsRGlyLFxuICAgICAgbmFtZTogYCR7b3B0aW9ucy5uYW1lfS1tb2RlbGAsXG4gICAgICBtb2RlbExhbmd1YWdlOiBvcHRpb25zLm1vZGVsLmxhbmd1YWdlLFxuICAgICAgbW9kZWxPcHRpb25zOiBvcHRpb25zLm1vZGVsLm9wdGlvbnMsXG4gICAgICBoYW5kbGVyTGFuZ3VhZ2VzLFxuICAgICAgcGFja2FnZU1hbmFnZXIsXG4gICAgICBkZWZhdWx0UmVsZWFzZUJyYW5jaCxcbiAgICAgIHBhcnNlZFNwZWNGaWxlLFxuICAgICAgYXN5bmNBcGlTcGVjRmlsZSxcbiAgICB9KTtcbiAgICBjb25zdCBtb2RlbFByb2plY3QgPSBbXG4gICAgICB0aGlzLm1vZGVsLm9wZW5hcGksXG4gICAgICB0aGlzLm1vZGVsLnNtaXRoeSxcbiAgICAgIHRoaXMubW9kZWwudHlwZVNwZWMsXG4gICAgXS5maWx0ZXIoKG0pID0+IG0pWzBdIGFzIFByb2plY3Q7XG5cbiAgICAvLyBFbnN1cmUgd2UgYWx3YXlzIGdlbmVyYXRlIGEgcnVudGltZSBwcm9qZWN0IGZvciB0aGUgaW5mcmFzdHJ1Y3R1cmUgbGFuZ3VhZ2UsIHJlZ2FyZGxlc3Mgb2Ygd2hhdCB3YXMgc3BlY2lmaWVkIGJ5XG4gICAgLy8gdGhlIHVzZXIuIExpa2V3aXNlIHdlIGdlbmVyYXRlIGEgcnVudGltZSBwcm9qZWN0IGZvciBhbnkgaGFuZGxlciBsYW5ndWFnZXMgc3BlY2lmaWVkXG4gICAgY29uc3QgcnVudGltZUxhbmd1YWdlcyA9IFtcbiAgICAgIC4uLm5ldyBTZXQoW1xuICAgICAgICAuLi4ob3B0aW9ucy5ydW50aW1lPy5sYW5ndWFnZXMgPz8gW10pLFxuICAgICAgICBvcHRpb25zLmluZnJhc3RydWN0dXJlLmxhbmd1YWdlLFxuICAgICAgICAuLi4ob3B0aW9ucy5oYW5kbGVycz8ubGFuZ3VhZ2VzID8/IFtdKSxcbiAgICAgIF0pLFxuICAgIF07XG5cbiAgICAvLyBUT0RPOiBEZWxldGUgd2hlbiBweXRob24vamF2YSBzdXBwb3J0IGlzIGltcGxlbWVudGVkXG4gICAgaWYgKFxuICAgICAgcnVudGltZUxhbmd1YWdlcy5pbmNsdWRlcyhMYW5ndWFnZS5KQVZBKSB8fFxuICAgICAgcnVudGltZUxhbmd1YWdlcy5pbmNsdWRlcyhMYW5ndWFnZS5QWVRIT04pXG4gICAgKSB7XG4gICAgICBjb25zdCBlcnJvck1lc3NhZ2VzID0gW1xuICAgICAgICAuLi4ocnVudGltZUxhbmd1YWdlcy5pbmNsdWRlcyhMYW5ndWFnZS5QWVRIT04pXG4gICAgICAgICAgPyBbXG4gICAgICAgICAgICAgIFwiUHl0aG9uIGlzIG5vdCBzdXBwb3J0ZWQgYnkgVHlwZSBTYWZlIFdlYlNvY2tldCBBUEkuIFBsZWFzZSArMSB0aGlzIGlzc3VlIGlmIG5lZWRlZDogaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtcGRrL2lzc3Vlcy83NDFcIixcbiAgICAgICAgICAgIF1cbiAgICAgICAgICA6IFtdKSxcbiAgICAgICAgLi4uKHJ1bnRpbWVMYW5ndWFnZXMuaW5jbHVkZXMoTGFuZ3VhZ2UuSkFWQSlcbiAgICAgICAgICA/IFtcbiAgICAgICAgICAgICAgXCJKYXZhIGlzIG5vdCBzdXBwb3J0ZWQgYnkgVHlwZSBTYWZlIFdlYlNvY2tldCBBUEkuIFBsZWFzZSArMSB0aGlzIGlzc3VlIGlmIG5lZWRlZDogaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtcGRrL2lzc3Vlcy83NDBcIixcbiAgICAgICAgICAgIF1cbiAgICAgICAgICA6IFtdKSxcbiAgICAgIF07XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlcy5qb2luKFwiXFxuXCIpKTtcbiAgICB9XG5cbiAgICBjb25zdCBnZW5lcmF0ZWREaXIgPSBcImdlbmVyYXRlZFwiO1xuICAgIGNvbnN0IHJ1bnRpbWVEaXIgPSBwYXRoLmpvaW4oZ2VuZXJhdGVkRGlyLCBcInJ1bnRpbWVcIik7XG4gICAgY29uc3QgcnVudGltZURpclJlbGF0aXZlVG9QYXJlbnQgPSBueFdvcmtzcGFjZVxuICAgICAgPyBwYXRoLmpvaW4ob3B0aW9ucy5vdXRkaXIhLCBydW50aW1lRGlyKVxuICAgICAgOiBydW50aW1lRGlyO1xuXG4gICAgLy8gUGF0aCBmcm9tIGEgZ2VuZXJhdGVkIHBhY2thZ2UgZGlyZWN0b3J5IChlZyBhcGkvZ2VuZXJhdGVkL3J1bnRpbWUvdHlwZXNjcmlwdCkgdG8gdGhlIG1vZGVsIGRpciAoaWUgYXBpL21vZGVsKVxuICAgIGNvbnN0IHJlbGF0aXZlUGF0aFRvTW9kZWxEaXJGcm9tR2VuZXJhdGVkUGFja2FnZURpciA9IHBhdGgucmVsYXRpdmUoXG4gICAgICBwYXRoLmpvaW4odGhpcy5vdXRkaXIsIHJ1bnRpbWVEaXIsIFwibGFuZ3VhZ2VcIiksXG4gICAgICBwYXRoLmpvaW4odGhpcy5vdXRkaXIsIG1vZGVsRGlyKVxuICAgICk7XG4gICAgY29uc3QgcGFyc2VkU3BlY1JlbGF0aXZlVG9HZW5lcmF0ZWRQYWNrYWdlRGlyID0gcGF0aC5qb2luKFxuICAgICAgcmVsYXRpdmVQYXRoVG9Nb2RlbERpckZyb21HZW5lcmF0ZWRQYWNrYWdlRGlyLFxuICAgICAgdGhpcy5tb2RlbC5wYXJzZWRTcGVjRmlsZVxuICAgICk7XG5cbiAgICAvLyBEZWNsYXJlIHRoZSBnZW5lcmF0ZWQgcnVudGltZSBwcm9qZWN0c1xuICAgIGNvbnN0IGdlbmVyYXRlZFJ1bnRpbWVQcm9qZWN0cyA9IGdlbmVyYXRlQXN5bmNSdW50aW1lUHJvamVjdHMoXG4gICAgICBydW50aW1lTGFuZ3VhZ2VzLFxuICAgICAge1xuICAgICAgICBwYXJlbnQ6IG54V29ya3NwYWNlID8gdGhpcy5wYXJlbnQhIDogdGhpcyxcbiAgICAgICAgcGFyZW50UGFja2FnZU5hbWU6IHRoaXMubmFtZSxcbiAgICAgICAgZ2VuZXJhdGVkQ29kZURpcjogcnVudGltZURpclJlbGF0aXZlVG9QYXJlbnQsXG4gICAgICAgIGlzV2l0aGluTW9ub3JlcG86IGlzTnhXb3Jrc3BhY2UsXG4gICAgICAgIC8vIFNwZWMgcGF0aCByZWxhdGl2ZSB0byBlYWNoIGdlbmVyYXRlZCBydW50aW1lIGRpclxuICAgICAgICBwYXJzZWRTcGVjUGF0aDogcGFyc2VkU3BlY1JlbGF0aXZlVG9HZW5lcmF0ZWRQYWNrYWdlRGlyLFxuICAgICAgICB0eXBlc2NyaXB0T3B0aW9uczoge1xuICAgICAgICAgIGRlZmF1bHRSZWxlYXNlQnJhbmNoLFxuICAgICAgICAgIHBhY2thZ2VNYW5hZ2VyLFxuICAgICAgICAgIC4uLm9wdGlvbnMucnVudGltZT8ub3B0aW9ucz8udHlwZXNjcmlwdCxcbiAgICAgICAgfSxcbiAgICAgICAgcHl0aG9uT3B0aW9uczoge1xuICAgICAgICAgIGF1dGhvck5hbWU6IFwiQVBKIENvcGVcIixcbiAgICAgICAgICBhdXRob3JFbWFpbDogXCJhcGotY29wZUBhbWF6b24uY29tXCIsXG4gICAgICAgICAgdmVyc2lvbjogXCIwLjAuMFwiLFxuICAgICAgICAgIC4uLm9wdGlvbnMucnVudGltZT8ub3B0aW9ucz8ucHl0aG9uLFxuICAgICAgICB9LFxuICAgICAgICBqYXZhT3B0aW9uczoge1xuICAgICAgICAgIHZlcnNpb246IFwiMC4wLjBcIixcbiAgICAgICAgICAuLi5vcHRpb25zLnJ1bnRpbWU/Lm9wdGlvbnM/LmphdmEsXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgKTtc