@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
184 lines • 22.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.synthesize = void 0;
const cxapi = require("@aws-cdk/cx-api");
const annotations_1 = require("../annotations");
const aspect_1 = require("../aspect");
const stack_1 = require("../stack");
const stage_1 = require("../stage");
const metadata_resource_1 = require("./metadata-resource");
const prepare_app_1 = require("./prepare-app");
const tree_metadata_1 = require("./tree-metadata");
function synthesize(root, options = {}) {
// we start by calling "synth" on all nested assemblies (which will take care of all their children)
synthNestedAssemblies(root, options);
invokeAspects(root);
injectMetadataResources(root);
// This is mostly here for legacy purposes as the framework itself does not use prepare anymore.
prepareTree(root);
// resolve references
prepare_app_1.prepareApp(root);
// give all children an opportunity to validate now that we've finished prepare
if (!options.skipValidation) {
validateTree(root);
}
// in unit tests, we support creating free-standing stacks, so we create the
// assembly builder here.
const builder = stage_1.Stage.isStage(root)
? root._assemblyBuilder
: new cxapi.CloudAssemblyBuilder(options.outdir);
// next, we invoke "onSynthesize" on all of our children. this will allow
// stacks to add themselves to the synthesized cloud assembly.
synthesizeTree(root, builder);
return builder.buildAssembly();
}
exports.synthesize = synthesize;
/**
* Find Assemblies inside the construct and call 'synth' on them
*
* (They will in turn recurse again)
*/
function synthNestedAssemblies(root, options) {
for (const child of root.node.children) {
if (stage_1.Stage.isStage(child)) {
child.synth(options);
}
else {
synthNestedAssemblies(child, options);
}
}
}
/**
* Invoke aspects on the given construct tree.
*
* Aspects are not propagated across Assembly boundaries. The same Aspect will not be invoked
* twice for the same construct.
*/
function invokeAspects(root) {
const invokedByPath = {};
let nestedAspectWarning = false;
recurse(root, []);
function recurse(construct, inheritedAspects) {
const node = construct.node;
const aspects = aspect_1.Aspects.of(construct);
const allAspectsHere = [...inheritedAspects !== null && inheritedAspects !== void 0 ? inheritedAspects : [], ...aspects.aspects];
const nodeAspectsCount = aspects.aspects.length;
for (const aspect of allAspectsHere) {
let invoked = invokedByPath[node.path];
if (!invoked) {
invoked = invokedByPath[node.path] = [];
}
if (invoked.includes(aspect)) {
continue;
}
aspect.visit(construct);
// if an aspect was added to the node while invoking another aspect it will not be invoked, emit a warning
// the `nestedAspectWarning` flag is used to prevent the warning from being emitted for every child
if (!nestedAspectWarning && nodeAspectsCount !== aspects.aspects.length) {
annotations_1.Annotations.of(construct).addWarning('We detected an Aspect was added via another Aspect, and will not be applied');
nestedAspectWarning = true;
}
// mark as invoked for this node
invoked.push(aspect);
}
for (const child of construct.node.children) {
if (!stage_1.Stage.isStage(child)) {
recurse(child, allAspectsHere);
}
}
}
}
/**
* Prepare all constructs in the given construct tree in post-order.
*
* Stop at Assembly boundaries.
*/
function prepareTree(root) {
visit(root, 'post', construct => construct.onPrepare());
}
/**
* Find all stacks and add Metadata Resources to all of them
*
* There is no good generic place to do this. Can't do it in the constructor
* (because adding a child construct makes it impossible to set context on the
* node), and the generic prepare phase is deprecated.
*
* Only do this on [parent] stacks (not nested stacks), don't do this when
* disabled by the user.
*
* Also, only when running via the CLI. If we do it unconditionally,
* all unit tests everywhere are going to break massively. I've spent a day
* fixing our own, but downstream users would be affected just as badly.
*
* Stop at Assembly boundaries.
*/
function injectMetadataResources(root) {
visit(root, 'post', construct => {
if (!stack_1.Stack.isStack(construct) || !construct._versionReportingEnabled) {
return;
}
// Because of https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/assert/lib/synth-utils.ts#L74
// synthesize() may be called more than once on a stack in unit tests, and the below would break
// if we execute it a second time. Guard against the constructs already existing.
const CDKMetadata = 'CDKMetadata';
if (construct.node.tryFindChild(CDKMetadata)) {
return;
}
new metadata_resource_1.MetadataResource(construct, CDKMetadata);
});
}
/**
* Synthesize children in post-order into the given builder
*
* Stop at Assembly boundaries.
*/
function synthesizeTree(root, builder) {
visit(root, 'post', construct => {
const session = {
outdir: builder.outdir,
assembly: builder,
};
if (stack_1.Stack.isStack(construct)) {
construct.synthesizer.synthesize(session);
}
else if (construct instanceof tree_metadata_1.TreeMetadata) {
construct._synthesizeTree(session);
}
// this will soon be deprecated and removed in 2.x
// see https://github.com/aws/aws-cdk-rfcs/issues/192
construct.onSynthesize(session);
});
}
/**
* Validate all constructs in the given construct tree
*/
function validateTree(root) {
const errors = new Array();
visit(root, 'pre', construct => {
for (const message of construct.onValidate()) {
errors.push({ message, source: construct });
}
});
if (errors.length > 0) {
const errorList = errors.map(e => `[${e.source.node.path}] ${e.message}`).join('\n ');
throw new Error(`Validation failed with the following errors:\n ${errorList}`);
}
}
/**
* Visit the given construct tree in either pre or post order, stopping at Assemblies
*/
function visit(root, order, cb) {
if (order === 'pre') {
cb(root);
}
for (const child of root.node.children) {
if (stage_1.Stage.isStage(child)) {
continue;
}
visit(child, order, cb);
}
if (order === 'post') {
cb(root);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ludGhlc2lzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3ludGhlc2lzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUF5QztBQUV6QyxnREFBNkM7QUFDN0Msc0NBQTZDO0FBRTdDLG9DQUFpQztBQUNqQyxvQ0FBd0Q7QUFDeEQsMkRBQXVEO0FBQ3ZELCtDQUEyQztBQUMzQyxtREFBK0M7QUFFL0MsU0FBZ0IsVUFBVSxDQUFDLElBQWdCLEVBQUUsVUFBNEIsRUFBRztJQUMxRSxvR0FBb0c7SUFDcEcscUJBQXFCLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRXJDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVwQix1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU5QixnR0FBZ0c7SUFDaEcsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWxCLHFCQUFxQjtJQUNyQix3QkFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWpCLCtFQUErRTtJQUMvRSxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRTtRQUMzQixZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDcEI7SUFFRCw0RUFBNEU7SUFDNUUseUJBQXlCO0lBQ3pCLE1BQU0sT0FBTyxHQUFHLGFBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCO1FBQ3ZCLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFbkQseUVBQXlFO0lBQ3pFLDhEQUE4RDtJQUM5RCxjQUFjLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRTlCLE9BQU8sT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDO0FBQ2pDLENBQUM7QUE5QkQsZ0NBOEJDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMscUJBQXFCLENBQUMsSUFBZ0IsRUFBRSxPQUE4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QyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQ3JCLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdkYsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsU0FBUyxFQUFFLENBQUMsQ0FBQztLQUNqRjtBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsS0FBSyxDQUFDLElBQWdCLEVBQUUsS0FBcUIsRUFBRSxFQUEyQztJQUNqRyxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUU7UUFDbkIsRUFBRSxDQUFDLElBQWtDLENBQUMsQ0FBQztLQUN4QztJQUVELEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7UUFDdEMsSUFBSSxhQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQUUsU0FBUztTQUFFO1FBQ3ZDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQ3pCO0lBRUQsSUFBSSxLQUFLLEtBQUssTUFBTSxFQUFFO1FBQ3BCLEVBQUUsQ0FBQyxJQUFrQyxDQUFDLENBQUM7S0FDeEM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbm5vdGF0aW9ucyB9IGZyb20gJy4uL2Fubm90YXRpb25zJztcbmltcG9ydCB7IEFzcGVjdHMsIElBc3BlY3QgfSBmcm9tICcuLi9hc3BlY3QnO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0LCBTeW50aGVzaXNPcHRpb25zLCBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICcuLi9jb25zdHJ1Y3QtY29tcGF0JztcbmltcG9ydCB7IFN0YWNrIH0gZnJvbSAnLi4vc3RhY2snO1xuaW1wb3J0IHsgU3RhZ2UsIFN0YWdlU3ludGhlc2lzT3B0aW9ucyB9IGZyb20gJy4uL3N0YWdlJztcbmltcG9ydCB7IE1ldGFkYXRhUmVzb3VyY2UgfSBmcm9tICcuL21ldGFkYXRhLXJlc291cmNlJztcbmltcG9ydCB7IHByZXBhcmVBcHAgfSBmcm9tICcuL3ByZXBhcmUtYXBwJztcbmltcG9ydCB7IFRyZWVNZXRhZGF0YSB9IGZyb20gJy4vdHJlZS1tZXRhZGF0YSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzeW50aGVzaXplKHJvb3Q6IElDb25zdHJ1Y3QsIG9wdGlvbnM6IFN5bnRoZXNpc09wdGlvbnMgPSB7IH0pOiBjeGFwaS5DbG91ZEFzc2VtYmx5IHtcbiAgLy8gd2Ugc3RhcnQgYnkgY2FsbGluZyBcInN5bnRoXCIgb24gYWxsIG5lc3RlZCBhc3NlbWJsaWVzICh3aGljaCB3aWxsIHRha2UgY2FyZSBvZiBhbGwgdGhlaXIgY2hpbGRyZW4pXG4gIHN5bnRoTmVzdGVkQXNzZW1ibGllcyhyb290LCBvcHRpb25zKTtcblxuICBpbnZva2VBc3BlY3RzKHJvb3QpO1xuXG4gIGluamVjdE1ldGFkYXRhUmVzb3VyY2VzKHJvb3QpO1xuXG4gIC8vIFRoaXMgaXMgbW9zdGx5IGhlcmUgZm9yIGxlZ2FjeSBwdXJwb3NlcyBhcyB0aGUgZnJhbWV3b3JrIGl0c2VsZiBkb2VzIG5vdCB1c2UgcHJlcGFyZSBhbnltb3JlLlxuICBwcmVwYXJlVHJlZShyb290KTtcblxuICAvLyByZXNvbHZlIHJlZmVyZW5jZXNcbiAgcHJlcGFyZUFwcChyb290KTtcblxuICAvLyBnaXZlIGFsbCBjaGlsZHJlbiBhbiBvcHBvcnR1bml0eSB0byB2YWxpZGF0ZSBub3cgdGhhdCB3ZSd2ZSBmaW5pc2hlZCBwcmVwYXJlXG4gIGlmICghb3B0aW9ucy5za2lwVmFsaWRhdGlvbikge1xuICAgIHZhbGlkYXRlVHJlZShyb290KTtcbiAgfVxuXG4gIC8vIGluIHVuaXQgdGVzdHMsIHdlIHN1cHBvcnQgY3JlYXRpbmcgZnJlZS1zdGFuZGluZyBzdGFja3MsIHNvIHdlIGNyZWF0ZSB0aGVcbiAgLy8gYXNzZW1ibHkgYnVpbGRlciBoZXJlLlxuICBjb25zdCBidWlsZGVyID0gU3RhZ2UuaXNTdGFnZShyb290KVxuICAgID8gcm9vdC5fYXNzZW1ibHlCdWlsZGVyXG4gICAgOiBuZXcgY3hhcGkuQ2xvdWRBc3NlbWJseUJ1aWxkZXIob3B0aW9ucy5vdXRkaXIpO1xuXG4gIC8vIG5leHQsIHdlIGludm9rZSBcIm9uU3ludGhlc2l6ZVwiIG9uIGFsbCBvZiBvdXIgY2hpbGRyZW4uIHRoaXMgd2lsbCBhbGxvd1xuICAvLyBzdGFja3MgdG8gYWRkIHRoZW1zZWx2ZXMgdG8gdGhlIHN5bnRoZXNpemVkIGNsb3VkIGFzc2VtYmx5LlxuICBzeW50aGVzaXplVHJlZShyb290LCBidWlsZGVyKTtcblxuICByZXR1cm4gYnVpbGRlci5idWlsZEFzc2VtYmx5KCk7XG59XG5cbi8qKlxuICogRmluZCBBc3NlbWJsaWVzIGluc2lkZSB0aGUgY29uc3RydWN0IGFuZCBjYWxsICdzeW50aCcgb24gdGhlbVxuICpcbiAqIChUaGV5IHdpbGwgaW4gdHVybiByZWN1cnNlIGFnYWluKVxuICovXG5mdW5jdGlvbiBzeW50aE5lc3RlZEFzc2VtYmxpZXMocm9vdDogSUNvbnN0cnVjdCwgb3B0aW9uczogU3RhZ2VTeW50aGVzaXNPcHRpb25zKSB7XG4gIGZvciAoY29uc3QgY2hpbGQgb2Ygcm9vdC5ub2RlLmNoaWxkcmVuKSB7XG4gICAgaWYgKFN0YWdlLmlzU3RhZ2UoY2hpbGQpKSB7XG4gICAgICBjaGlsZC5zeW50aChvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3ludGhOZXN0ZWRBc3NlbWJsaWVzKGNoaWxkLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBJbnZva2UgYXNwZWN0cyBvbiB0aGUgZ2l2ZW4gY29uc3RydWN0IHRyZWUuXG4gKlxuICogQXNwZWN0cyBhcmUgbm90IHByb3BhZ2F0ZWQgYWNyb3NzIEFzc2VtYmx5IGJvdW5kYXJpZXMuIFRoZSBzYW1lIEFzcGVjdCB3aWxsIG5vdCBiZSBpbnZva2VkXG4gKiB0d2ljZSBmb3IgdGhlIHNhbWUgY29uc3RydWN0LlxuICovXG5mdW5jdGlvbiBpbnZva2VBc3BlY3RzKHJvb3Q6IElDb25zdHJ1Y3QpIHtcbiAgY29uc3QgaW52b2tlZEJ5UGF0aDogeyBbbm9kZVBhdGg6IHN0cmluZ106IElBc3BlY3RbXSB9ID0geyB9O1xuXG4gIGxldCBuZXN0ZWRBc3BlY3RXYXJuaW5nID0gZmFsc2U7XG4gIHJlY3Vyc2Uocm9vdCwgW10pO1xuXG4gIGZ1bmN0aW9uIHJlY3Vyc2UoY29uc3RydWN0OiBJQ29uc3RydWN0LCBpbmhlcml0ZWRBc3BlY3RzOiBjb25zdHJ1Y3RzLklBc3BlY3RbXSkge1xuICAgIGNvbnN0IG5vZGUgPSBjb25zdHJ1Y3Qubm9kZTtcbiAgICBjb25zdCBhc3BlY3RzID0gQXNwZWN0cy5vZihjb25zdHJ1Y3QpO1xuICAgIGNvbnN0IGFsbEFzcGVjdHNIZXJlID0gWy4uLmluaGVyaXRlZEFzcGVjdHMgPz8gW10sIC4uLmFzcGVjdHMuYXNwZWN0c107XG4gICAgY29uc3Qgbm9kZUFzcGVjdHNDb3VudCA9IGFzcGVjdHMuYXNwZWN0cy5sZW5ndGg7XG4gICAgZm9yIChjb25zdCBhc3BlY3Qgb2YgYWxsQXNwZWN0c0hlcmUpIHtcbiAgICAgIGxldCBpbnZva2VkID0gaW52b2tlZEJ5UGF0aFtub2RlLnBhdGhdO1xuICAgICAgaWYgKCFpbnZva2VkKSB7XG4gICAgICAgIGludm9rZWQgPSBpbnZva2VkQnlQYXRoW25vZGUucGF0aF0gPSBbXTtcbiAgICAgIH1cblxuICAgICAgaWYgKGludm9rZWQuaW5jbHVkZXMoYXNwZWN0KSkgeyBjb250aW51ZTsgfVxuXG4gICAgICBhc3BlY3QudmlzaXQoY29uc3RydWN0KTtcblxuICAgICAgLy8gaWYgYW4gYXNwZWN0IHdhcyBhZGRlZCB0byB0aGUgbm9kZSB3aGlsZSBpbnZva2luZyBhbm90aGVyIGFzcGVjdCBpdCB3aWxsIG5vdCBiZSBpbnZva2VkLCBlbWl0IGEgd2FybmluZ1xuICAgICAgLy8gdGhlIGBuZXN0ZWRBc3BlY3RXYXJuaW5nYCBmbGFnIGlzIHVzZWQgdG8gcHJldmVudCB0aGUgd2FybmluZyBmcm9tIGJlaW5nIGVtaXR0ZWQgZm9yIGV2ZXJ5IGNoaWxkXG4gICAgICBpZiAoIW5lc3RlZEFzcGVjdFdhcm5pbmcgJiYgbm9kZUFzcGVjdHNDb3VudCAhPT0gYXNwZWN0cy5hc3BlY3RzLmxlbmd0aCkge1xuICAgICAgICBBbm5vdGF0aW9ucy5vZihjb25zdHJ1Y3QpLmFkZFdhcm5pbmcoJ1dlIGRldGVjdGVkIGFuIEFzcGVjdCB3YXMgYWRkZWQgdmlhIGFub3RoZXIgQXNwZWN0LCBhbmQgd2lsbCBub3QgYmUgYXBwbGllZCcpO1xuICAgICAgICBuZXN0ZWRBc3BlY3RXYXJuaW5nID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gbWFyayBhcyBpbnZva2VkIGZvciB0aGlzIG5vZGVcbiAgICAgIGludm9rZWQucHVzaChhc3BlY3QpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgY29uc3RydWN0Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIGlmICghU3RhZ2UuaXNTdGFnZShjaGlsZCkpIHtcbiAgICAgICAgcmVjdXJzZShjaGlsZCwgYWxsQXNwZWN0c0hlcmUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFByZXBhcmUgYWxsIGNvbnN0cnVjdHMgaW4gdGhlIGdpdmVuIGNvbnN0cnVjdCB0cmVlIGluIHBvc3Qtb3JkZXIuXG4gKlxuICogU3RvcCBhdCBBc3NlbWJseSBib3VuZGFyaWVzLlxuICovXG5mdW5jdGlvbiBwcmVwYXJlVHJlZShyb290OiBJQ29uc3RydWN0KSB7XG4gIHZpc2l0KHJvb3QsICdwb3N0JywgY29uc3RydWN0ID0+IGNvbnN0cnVjdC5vblByZXBhcmUoKSk7XG59XG5cbi8qKlxuICogRmluZCBhbGwgc3RhY2tzIGFuZCBhZGQgTWV0YWRhdGEgUmVzb3VyY2VzIHRvIGFsbCBvZiB0aGVtXG4gKlxuICogVGhlcmUgaXMgbm8gZ29vZCBnZW5lcmljIHBsYWNlIHRvIGRvIHRoaXMuIENhbid0IGRvIGl0IGluIHRoZSBjb25zdHJ1Y3RvclxuICogKGJlY2F1c2UgYWRkaW5nIGEgY2hpbGQgY29uc3RydWN0IG1ha2VzIGl0IGltcG9zc2libGUgdG8gc2V0IGNvbnRleHQgb24gdGhlXG4gKiBub2RlKSwgYW5kIHRoZSBnZW5lcmljIHByZXBhcmUgcGhhc2UgaXMgZGVwcmVjYXRlZC5cbiAqXG4gKiBPbmx5IGRvIHRoaXMgb24gW3BhcmVudF0gc3RhY2tzIChub3QgbmVzdGVkIHN0YWNrcyksIGRvbid0IGRvIHRoaXMgd2hlblxuICogZGlzYWJsZWQgYnkgdGhlIHVzZXIuXG4gKlxuICogQWxzbywgb25seSB3aGVuIHJ1bm5pbmcgdmlhIHRoZSBDTEkuIElmIHdlIGRvIGl0IHVuY29uZGl0aW9uYWxseSxcbiAqIGFsbCB1bml0IHRlc3RzIGV2ZXJ5d2hlcmUgYXJlIGdvaW5nIHRvIGJyZWFrIG1hc3NpdmVseS4gSSd2ZSBzcGVudCBhIGRheVxuICogZml4aW5nIG91ciBvd24sIGJ1dCBkb3duc3RyZWFtIHVzZXJzIHdvdWxkIGJlIGFmZmVjdGVkIGp1c3QgYXMgYmFkbHkuXG4gKlxuICogU3RvcCBhdCBBc3NlbWJseSBib3VuZGFyaWVzLlxuICovXG5mdW5jdGlvbiBpbmplY3RNZXRhZGF0YVJlc291cmNlcyhyb290OiBJQ29uc3RydWN0KSB7XG4gIHZpc2l0KHJvb3QsICdwb3N0JywgY29uc3RydWN0ID0+IHtcbiAgICBpZiAoIVN0YWNrLmlzU3RhY2soY29uc3RydWN0KSB8fCAhY29uc3RydWN0Ll92ZXJzaW9uUmVwb3J0aW5nRW5hYmxlZCkgeyByZXR1cm47IH1cblxuICAgIC8vIEJlY2F1c2Ugb2YgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2Jsb2IvbWFzdGVyL3BhY2thZ2VzL0Bhd3MtY2RrL2Fzc2VydC9saWIvc3ludGgtdXRpbHMudHMjTDc0XG4gICAgLy8gc3ludGhlc2l6ZSgpIG1heSBiZSBjYWxsZWQgbW9yZSB0aGFuIG9uY2Ugb24gYSBzdGFjayBpbiB1bml0IHRlc3RzLCBhbmQgdGhlIGJlbG93IHdvdWxkIGJyZWFrXG4gICAgLy8gaWYgd2UgZXhlY3V0ZSBpdCBhIHNlY29uZCB0aW1lLiBHdWFyZCBhZ2FpbnN0IHRoZSBjb25zdHJ1Y3RzIGFscmVhZHkgZXhpc3RpbmcuXG4gICAgY29uc3QgQ0RLTWV0YWRhdGEgPSAnQ0RLTWV0YWRhdGEnO1xuICAgIGlmIChjb25zdHJ1Y3Qubm9kZS50cnlGaW5kQ2hpbGQoQ0RLTWV0YWRhdGEpKSB7IHJldHVybjsgfVxuXG4gICAgbmV3IE1ldGFkYXRhUmVzb3VyY2UoY29uc3RydWN0LCBDREtNZXRhZGF0YSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFN5bnRoZXNpemUgY2hpbGRyZW4gaW4gcG9zdC1vcmRlciBpbnRvIHRoZSBnaXZlbiBidWlsZGVyXG4gKlxuICogU3RvcCBhdCBBc3NlbWJseSBib3VuZGFyaWVzLlxuICovXG5mdW5jdGlvbiBzeW50aGVzaXplVHJlZShyb290OiBJQ29uc3RydWN0LCBidWlsZGVyOiBjeGFwaS5DbG91ZEFzc2VtYmx5QnVpbGRlcikge1xuICB2aXNpdChyb290LCAncG9zdCcsIGNvbnN0cnVjdCA9PiB7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IHtcbiAgICAgIG91dGRpcjogYnVpbGRlci5vdXRkaXIsXG4gICAgICBhc3NlbWJseTogYnVpbGRlcixcbiAgICB9O1xuXG4gICAgaWYgKFN0YWNrLmlzU3RhY2soY29uc3RydWN0KSkge1xuICAgICAgY29uc3RydWN0LnN5bnRoZXNpemVyLnN5bnRoZXNpemUoc2Vzc2lvbik7XG4gICAgfSBlbHNlIGlmIChjb25zdHJ1Y3QgaW5zdGFuY2VvZiBUcmVlTWV0YWRhdGEpIHtcbiAgICAgIGNvbnN0cnVjdC5fc3ludGhlc2l6ZVRyZWUoc2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLy8gdGhpcyB3aWxsIHNvb24gYmUgZGVwcmVjYXRlZCBhbmQgcmVtb3ZlZCBpbiAyLnhcbiAgICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrLXJmY3MvaXNzdWVzLzE5MlxuICAgIGNvbnN0cnVjdC5vblN5bnRoZXNpemUoc2Vzc2lvbik7XG4gIH0pO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGFsbCBjb25zdHJ1Y3RzIGluIHRoZSBnaXZlbiBjb25zdHJ1Y3QgdHJlZVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVRyZWUocm9vdDogSUNvbnN0cnVjdCkge1xuICBjb25zdCBlcnJvcnMgPSBuZXcgQXJyYXk8VmFsaWRhdGlvbkVycm9yPigpO1xuXG4gIHZpc2l0KHJvb3QsICdwcmUnLCBjb25zdHJ1Y3QgPT4ge1xuICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiBjb25zdHJ1Y3Qub25WYWxpZGF0ZSgpKSB7XG4gICAgICBlcnJvcnMucHVzaCh7IG1lc3NhZ2UsIHNvdXJjZTogY29uc3RydWN0IGFzIHVua25vd24gYXMgQ29uc3RydWN0IH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgZXJyb3JMaXN0ID0gZXJyb3JzLm1hcChlID0+IGBbJHtlLnNvdXJjZS5ub2RlLnBhdGh9XSAke2UubWVzc2FnZX1gKS5qb2luKCdcXG4gICcpO1xuICAgIHRocm93IG5ldyBFcnJvcihgVmFsaWRhdGlvbiBmYWlsZWQgd2l0aCB0aGUgZm9sbG93aW5nIGVycm9yczpcXG4gICR7ZXJyb3JMaXN0fWApO1xuICB9XG59XG5cbi8qKlxuICogVmlzaXQgdGhlIGdpdmVuIGNvbnN0cnVjdCB0cmVlIGluIGVpdGhlciBwcmUgb3IgcG9zdCBvcmRlciwgc3RvcHBpbmcgYXQgQXNzZW1ibGllc1xuICovXG5mdW5jdGlvbiB2aXNpdChyb290OiBJQ29uc3RydWN0LCBvcmRlcjogJ3ByZScgfCAncG9zdCcsIGNiOiAoeDogSVByb3RlY3RlZENvbnN0cnVjdE1ldGhvZHMpID0+IHZvaWQpIHtcbiAgaWYgKG9yZGVyID09PSAncHJlJykge1xuICAgIGNiKHJvb3QgYXMgSVByb3RlY3RlZENvbnN0cnVjdE1ldGhvZHMpO1xuICB9XG5cbiAgZm9yIChjb25zdCBjaGlsZCBvZiByb290Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICBpZiAoU3RhZ2UuaXNTdGFnZShjaGlsZCkpIHsgY29udGludWU7IH1cbiAgICB2aXNpdChjaGlsZCwgb3JkZXIsIGNiKTtcbiAgfVxuXG4gIGlmIChvcmRlciA9PT0gJ3Bvc3QnKSB7XG4gICAgY2Iocm9vdCBhcyBJUHJvdGVjdGVkQ29uc3RydWN0TWV0aG9kcyk7XG4gIH1cbn1cblxuLyoqXG4gKiBJbnRlcmZhY2Ugd2hpY2ggcHJvdmlkZXMgYWNjZXNzIHRvIHNwZWNpYWwgbWV0aG9kcyBvZiBDb25zdHJ1Y3RcbiAqXG4gKiBAZXhwZXJpbWVudGFsXG4gKi9cbmludGVyZmFjZSBJUHJvdGVjdGVkQ29uc3RydWN0TWV0aG9kcyBleHRlbmRzIElDb25zdHJ1Y3Qge1xuICAvKipcbiAgICogTWV0aG9kIHRoYXQgZ2V0cyBjYWxsZWQgd2hlbiBhIGNvbnN0cnVjdCBzaG91bGQgc3ludGhlc2l6ZSBpdHNlbGYgdG8gYW4gYXNzZW1ibHlcbiAgICovXG4gIG9uU3ludGhlc2l6ZShzZXNzaW9uOiBjb25zdHJ1Y3RzLklTeW50aGVzaXNTZXNzaW9uKTogdm9pZDtcblxuICAvKipcbiAgICogTWV0aG9kIHRoYXQgZ2V0cyBjYWxsZWQgdG8gdmFsaWRhdGUgYSBjb25zdHJ1Y3RcbiAgICovXG4gIG9uVmFsaWRhdGUoKTogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0aGF0IGdldHMgY2FsbGVkIHRvIHByZXBhcmUgYSBjb25zdHJ1Y3RcbiAgICovXG4gIG9uUHJlcGFyZSgpOiB2b2lkO1xufVxuIl19