UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

224 lines 31.4 kB
"use strict"; // ---------------------------------------------------- // CROSS REFERENCES // ---------------------------------------------------- Object.defineProperty(exports, "__esModule", { value: true }); exports.referenceNestedStackValueInParent = exports.resolveReferences = void 0; const cfn_element_1 = require("../cfn-element"); const cfn_output_1 = require("../cfn-output"); const cfn_parameter_1 = require("../cfn-parameter"); const names_1 = require("../names"); const stack_1 = require("../stack"); const token_1 = require("../token"); const cfn_reference_1 = require("./cfn-reference"); const resolve_1 = require("./resolve"); /** * This is called from the App level to resolve all references defined. Each * reference is resolved based on it's consumption context. */ function resolveReferences(scope) { const edges = findAllReferences(scope); for (const { source, value } of edges) { const consumer = stack_1.Stack.of(source); // resolve the value in the context of the consumer if (!value.hasValueForStack(consumer)) { const resolved = resolveValue(consumer, value); value.assignValueForStack(consumer, resolved); } } } exports.resolveReferences = resolveReferences; /** * Resolves the value for `reference` in the context of `consumer`. */ function resolveValue(consumer, reference) { const producer = stack_1.Stack.of(reference.target); // produce and consumer stacks are the same, we can just return the value itself. if (producer === consumer) { return reference; } // unsupported: stacks from different apps if (producer.node.root !== consumer.node.root) { throw new Error('Cannot reference across apps. Consuming and producing stacks must be defined within the same CDK app.'); } // unsupported: stacks are not in the same environment if (producer.environment !== consumer.environment) { throw new Error(`Stack "${consumer.node.path}" cannot consume a cross reference from stack "${producer.node.path}". ` + 'Cross stack references are only supported for stacks deployed to the same environment or between nested stacks and their parent stack'); } // ---------------------------------------------------------------------- // consumer is nested in the producer (directly or indirectly) // ---------------------------------------------------------------------- // if the consumer is nested within the producer (directly or indirectly), // wire through a CloudFormation parameter and then resolve the reference with // the parent stack as the consumer. if (consumer.nestedStackParent && isNested(consumer, producer)) { const parameterValue = resolveValue(consumer.nestedStackParent, reference); return createNestedStackParameter(consumer, reference, parameterValue); } // ---------------------------------------------------------------------- // producer is a nested stack // ---------------------------------------------------------------------- // if the producer is nested, always publish the value through a // cloudformation output and resolve recursively with the Fn::GetAtt // of the output in the parent stack. // one might ask, if the consumer is not a parent of the producer, // why not just use export/import? the reason is that we cannot // generate an "export name" from a nested stack because the export // name must contain the stack name to ensure uniqueness, and we // don't know the stack name of a nested stack before we deploy it. // therefore, we can only export from a top-level stack. if (producer.nested) { const outputValue = createNestedStackOutput(producer, reference); return resolveValue(consumer, outputValue); } // ---------------------------------------------------------------------- // export/import // ---------------------------------------------------------------------- // export the value through a cloudformation "export name" and use an // Fn::ImportValue in the consumption site. // add a dependency between the producer and the consumer. dependency logic // will take care of applying the dependency at the right level (e.g. the // top-level stacks). consumer.addDependency(producer, `${consumer.node.path} -> ${reference.target.node.path}.${reference.displayName}`); return createImportValue(reference); } /** * Finds all the CloudFormation references in a construct tree. */ function findAllReferences(root) { const result = new Array(); for (const consumer of root.node.findAll()) { // include only CfnElements (i.e. resources) if (!cfn_element_1.CfnElement.isCfnElement(consumer)) { continue; } try { const tokens = resolve_1.findTokens(consumer, () => consumer._toCloudFormation()); // iterate over all the tokens (e.g. intrinsic functions, lazies, etc) that // were found in the cloudformation representation of this resource. for (const token of tokens) { // include only CfnReferences (i.e. "Ref" and "Fn::GetAtt") if (!cfn_reference_1.CfnReference.isCfnReference(token)) { continue; } result.push({ source: consumer, value: token, }); } } catch (e) { // Note: it might be that the properties of the CFN object aren't valid. // This will usually be preventatively caught in a construct's validate() // and turned into a nicely descriptive error, but we're running prepare() // before validate(). Swallow errors that occur because the CFN layer // doesn't validate completely. // // This does make the assumption that the error will not be rectified, // but the error will be thrown later on anyway. If the error doesn't // get thrown down the line, we may miss references. if (e.type === 'CfnSynthesisError') { continue; } throw e; } } return result; } // ------------------------------------------------------------------------------------------------ // export/import // ------------------------------------------------------------------------------------------------ /** * Imports a value from another stack by creating an "Output" with an "ExportName" * and returning an "Fn::ImportValue" token. */ function createImportValue(reference) { const exportingStack = stack_1.Stack.of(reference.target); const importExpr = exportingStack.exportValue(reference); // I happen to know this returns a Fn.importValue() which implements Intrinsic. return token_1.Tokenization.reverseCompleteString(importExpr); } // ------------------------------------------------------------------------------------------------ // nested stacks // ------------------------------------------------------------------------------------------------ /** * Adds a CloudFormation parameter to a nested stack and assigns it with the * value of the reference. */ function createNestedStackParameter(nested, reference, value) { const paramId = generateUniqueId(nested, reference, 'reference-to-'); let param = nested.node.tryFindChild(paramId); if (!param) { param = new cfn_parameter_1.CfnParameter(nested, paramId, { type: 'String' }); // Ugly little hack until we move NestedStack to this module. if (!('setParameter' in nested)) { throw new Error('assertion failed: nested stack should have a "setParameter" method'); } nested.setParameter(param.logicalId, token_1.Token.asString(value)); } return param.value; } /** * Adds a CloudFormation output to a nested stack and returns an "Fn::GetAtt" * intrinsic that can be used to reference this output in the parent stack. */ function createNestedStackOutput(producer, reference) { const outputId = generateUniqueId(producer, reference); let output = producer.node.tryFindChild(outputId); if (!output) { output = new cfn_output_1.CfnOutput(producer, outputId, { value: token_1.Token.asString(reference) }); } if (!producer.nestedStackResource) { throw new Error('assertion failed'); } return producer.nestedStackResource.getAtt(`Outputs.${output.logicalId}`); } /** * Translate a Reference into a nested stack into a value in the parent stack * * Will create Outputs along the chain of Nested Stacks, and return the final `{ Fn::GetAtt }`. */ function referenceNestedStackValueInParent(reference, targetStack) { let currentStack = stack_1.Stack.of(reference.target); if (currentStack !== targetStack && !isNested(currentStack, targetStack)) { throw new Error(`Referenced resource must be in stack '${targetStack.node.path}', got '${reference.target.node.path}'`); } while (currentStack !== targetStack) { reference = createNestedStackOutput(stack_1.Stack.of(reference.target), reference); currentStack = stack_1.Stack.of(reference.target); } return reference; } exports.referenceNestedStackValueInParent = referenceNestedStackValueInParent; /** * @returns true if this stack is a direct or indirect parent of the nested * stack `nested`. * * If `child` is not a nested stack, always returns `false` because it can't * have a parent, dah. */ function isNested(nested, parent) { // if the parent is a direct parent if (nested.nestedStackParent === parent) { return true; } // we reached a top-level (non-nested) stack without finding the parent if (!nested.nestedStackParent) { return false; } // recurse with the child's direct parent return isNested(nested.nestedStackParent, parent); } /** * Generates a unique id for a `Reference` * @param stack A stack used to resolve tokens * @param ref The reference * @param prefix Optional prefix for the id * @returns A unique id */ function generateUniqueId(stack, ref, prefix = '') { // we call "resolve()" to ensure that tokens do not creep in (for example, if the reference display name includes tokens) return stack.resolve(`${prefix}${names_1.Names.nodeUniqueId(ref.target.node)}${ref.displayName}`); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVmcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlZnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHVEQUF1RDtBQUN2RCxtQkFBbUI7QUFDbkIsdURBQXVEOzs7QUFFdkQsZ0RBQTRDO0FBQzVDLDhDQUEwQztBQUMxQyxvREFBZ0Q7QUFFaEQsb0NBQWlDO0FBR2pDLG9DQUFpQztBQUNqQyxvQ0FBK0M7QUFDL0MsbURBQStDO0FBRS9DLHVDQUF1QztBQUV2Qzs7O0dBR0c7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxLQUFpQjtJQUNqRCxNQUFNLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV2QyxLQUFLLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksS0FBSyxFQUFFO1FBQ3JDLE1BQU0sUUFBUSxHQUFHLGFBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbEMsbURBQW1EO1FBQ25ELElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDckMsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMvQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1NBQy9DO0tBQ0Y7QUFDSCxDQUFDO0FBWkQsOENBWUM7QUFFRDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFFBQWUsRUFBRSxTQUF1QjtJQUM1RCxNQUFNLFFBQVEsR0FBRyxhQUFLLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUU1QyxpRkFBaUY7SUFDakYsSUFBSSxRQUFRLEtBQUssUUFBUSxFQUFFO1FBQ3pCLE9BQU8sU0FBUyxDQUFDO0tBQ2xCO0lBRUQsMENBQTBDO0lBQzFDLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLElBQUksQ0FB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QU8sWUFBWSxLQUFLLFdBQVcsRUFBRTtRQUNuQyxTQUFTLEdBQUcsdUJBQXVCLENBQUMsYUFBSyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDM0UsWUFBWSxHQUFHLGFBQUssQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzNDO0lBRUQsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQVpELDhFQVlDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxRQUFRLENBQUMsTUFBYSxFQUFFLE1BQWE7SUFDNUMsbUNBQW1DO0lBQ25DLElBQUksTUFBTSxDQUFDLGlCQUFpQixLQUFLLE1BQU0sRUFBRTtRQUN2QyxPQUFPLElBQUksQ0FBQztLQUNiO0lBRUQsdUVBQXVFO0lBQ3ZFLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLEVBQUU7UUFDN0IsT0FBTyxLQUFLLENBQUM7S0FDZDtJQUVELHlDQUF5QztJQUN6QyxPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsZ0JBQWdCLENBQUMsS0FBWSxFQUFFLEdBQWMsRUFBRSxNQUFNLEdBQUcsRUFBRTtJQUNqRSx5SEFBeUg7SUFDekgsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsTUFBTSxHQUFHLGFBQUssQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztBQUM1RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gQ1JPU1MgUkVGRVJFTkNFU1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5pbXBvcnQgeyBDZm5FbGVtZW50IH0gZnJvbSAnLi4vY2ZuLWVsZW1lbnQnO1xuaW1wb3J0IHsgQ2ZuT3V0cHV0IH0gZnJvbSAnLi4vY2ZuLW91dHB1dCc7XG5pbXBvcnQgeyBDZm5QYXJhbWV0ZXIgfSBmcm9tICcuLi9jZm4tcGFyYW1ldGVyJztcbmltcG9ydCB7IElDb25zdHJ1Y3QgfSBmcm9tICcuLi9jb25zdHJ1Y3QtY29tcGF0JztcbmltcG9ydCB7IE5hbWVzIH0gZnJvbSAnLi4vbmFtZXMnO1xuaW1wb3J0IHsgUmVmZXJlbmNlIH0gZnJvbSAnLi4vcmVmZXJlbmNlJztcbmltcG9ydCB7IElSZXNvbHZhYmxlIH0gZnJvbSAnLi4vcmVzb2x2YWJsZSc7XG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJy4uL3N0YWNrJztcbmltcG9ydCB7IFRva2VuLCBUb2tlbml6YXRpb24gfSBmcm9tICcuLi90b2tlbic7XG5pbXBvcnQgeyBDZm5SZWZlcmVuY2UgfSBmcm9tICcuL2Nmbi1yZWZlcmVuY2UnO1xuaW1wb3J0IHsgSW50cmluc2ljIH0gZnJvbSAnLi9pbnRyaW5zaWMnO1xuaW1wb3J0IHsgZmluZFRva2VucyB9IGZyb20gJy4vcmVzb2x2ZSc7XG5cbi8qKlxuICogVGhpcyBpcyBjYWxsZWQgZnJvbSB0aGUgQXBwIGxldmVsIHRvIHJlc29sdmUgYWxsIHJlZmVyZW5jZXMgZGVmaW5lZC4gRWFjaFxuICogcmVmZXJlbmNlIGlzIHJlc29sdmVkIGJhc2VkIG9uIGl0J3MgY29uc3VtcHRpb24gY29udGV4dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVSZWZlcmVuY2VzKHNjb3BlOiBJQ29uc3RydWN0KTogdm9pZCB7XG4gIGNvbnN0IGVkZ2VzID0gZmluZEFsbFJlZmVyZW5jZXMoc2NvcGUpO1xuXG4gIGZvciAoY29uc3QgeyBzb3VyY2UsIHZhbHVlIH0gb2YgZWRnZXMpIHtcbiAgICBjb25zdCBjb25zdW1lciA9IFN0YWNrLm9mKHNvdXJjZSk7XG5cbiAgICAvLyByZXNvbHZlIHRoZSB2YWx1ZSBpbiB0aGUgY29udGV4dCBvZiB0aGUgY29uc3VtZXJcbiAgICBpZiAoIXZhbHVlLmhhc1ZhbHVlRm9yU3RhY2soY29uc3VtZXIpKSB7XG4gICAgICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVWYWx1ZShjb25zdW1lciwgdmFsdWUpO1xuICAgICAgdmFsdWUuYXNzaWduVmFsdWVGb3JTdGFjayhjb25zdW1lciwgcmVzb2x2ZWQpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSB2YWx1ZSBmb3IgYHJlZmVyZW5jZWAgaW4gdGhlIGNvbnRleHQgb2YgYGNvbnN1bWVyYC5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVZhbHVlKGNvbnN1bWVyOiBTdGFjaywgcmVmZXJlbmNlOiBDZm5SZWZlcmVuY2UpOiBJUmVzb2x2YWJsZSB7XG4gIGNvbnN0IHByb2R1Y2VyID0gU3RhY2sub2YocmVmZXJlbmNlLnRhcmdldCk7XG5cbiAgLy8gcHJvZHVjZSBhbmQgY29uc3VtZXIgc3RhY2tzIGFyZSB0aGUgc2FtZSwgd2UgY2FuIGp1c3QgcmV0dXJuIHRoZSB2YWx1ZSBpdHNlbGYuXG4gIGlmIChwcm9kdWNlciA9PT0gY29uc3VtZXIpIHtcbiAgICByZXR1cm4gcmVmZXJlbmNlO1xuICB9XG5cbiAgLy8gdW5zdXBwb3J0ZWQ6IHN0YWNrcyBmcm9tIGRpZmZlcmVudCBhcHBzXG4gIGlmIChwcm9kdWNlci5ub2RlLnJvb3QgIT09IGNvbnN1bWVyLm5vZGUucm9vdCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHJlZmVyZW5jZSBhY3Jvc3MgYXBwcy4gQ29uc3VtaW5nIGFuZCBwcm9kdWNpbmcgc3RhY2tzIG11c3QgYmUgZGVmaW5lZCB3aXRoaW4gdGhlIHNhbWUgQ0RLIGFwcC4nKTtcbiAgfVxuXG4gIC8vIHVuc3VwcG9ydGVkOiBzdGFja3MgYXJlIG5vdCBpbiB0aGUgc2FtZSBlbnZpcm9ubWVudFxuICBpZiAocHJvZHVjZXIuZW52aXJvbm1lbnQgIT09IGNvbnN1bWVyLmVudmlyb25tZW50KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYFN0YWNrIFwiJHtjb25zdW1lci5ub2RlLnBhdGh9XCIgY2Fubm90IGNvbnN1bWUgYSBjcm9zcyByZWZlcmVuY2UgZnJvbSBzdGFjayBcIiR7cHJvZHVjZXIubm9kZS5wYXRofVwiLiBgICtcbiAgICAgICdDcm9zcyBzdGFjayByZWZlcmVuY2VzIGFyZSBvbmx5IHN1cHBvcnRlZCBmb3Igc3RhY2tzIGRlcGxveWVkIHRvIHRoZSBzYW1lIGVudmlyb25tZW50IG9yIGJldHdlZW4gbmVzdGVkIHN0YWNrcyBhbmQgdGhlaXIgcGFyZW50IHN0YWNrJyk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIGNvbnN1bWVyIGlzIG5lc3RlZCBpbiB0aGUgcHJvZHVjZXIgKGRpcmVjdGx5IG9yIGluZGlyZWN0bHkpXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBpZiB0aGUgY29uc3VtZXIgaXMgbmVzdGVkIHdpdGhpbiB0aGUgcHJvZHVjZXIgKGRpcmVjdGx5IG9yIGluZGlyZWN0bHkpLFxuICAvLyB3aXJlIHRocm91Z2ggYSBDbG91ZEZvcm1hdGlvbiBwYXJhbWV0ZXIgYW5kIHRoZW4gcmVzb2x2ZSB0aGUgcmVmZXJlbmNlIHdpdGhcbiAgLy8gdGhlIHBhcmVudCBzdGFjayBhcyB0aGUgY29uc3VtZXIuXG4gIGlmIChjb25zdW1lci5uZXN0ZWRTdGFja1BhcmVudCAmJiBpc05lc3RlZChjb25zdW1lciwgcHJvZHVjZXIpKSB7XG4gICAgY29uc3QgcGFyYW1ldGVyVmFsdWUgPSByZXNvbHZlVmFsdWUoY29uc3VtZXIubmVzdGVkU3RhY2tQYXJlbnQsIHJlZmVyZW5jZSk7XG4gICAgcmV0dXJuIGNyZWF0ZU5lc3RlZFN0YWNrUGFyYW1ldGVyKGNvbnN1bWVyLCByZWZlcmVuY2UsIHBhcmFtZXRlclZhbHVlKTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gcHJvZHVjZXIgaXMgYSBuZXN0ZWQgc3RhY2tcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIGlmIHRoZSBwcm9kdWNlciBpcyBuZXN0ZWQsIGFsd2F5cyBwdWJsaXNoIHRoZSB2YWx1ZSB0aHJvdWdoIGFcbiAgLy8gY2xvdWRmb3JtYXRpb24gb3V0cHV0IGFuZCByZXNvbHZlIHJlY3Vyc2l2ZWx5IHdpdGggdGhlIEZuOjpHZXRBdHRcbiAgLy8gb2YgdGhlIG91dHB1dCBpbiB0aGUgcGFyZW50IHN0YWNrLlxuXG4gIC8vIG9uZSBtaWdodCBhc2ssIGlmIHRoZSBjb25zdW1lciBpcyBub3QgYSBwYXJlbnQgb2YgdGhlIHByb2R1Y2VyLFxuICAvLyB3aHkgbm90IGp1c3QgdXNlIGV4cG9ydC9pbXBvcnQ/IHRoZSByZWFzb24gaXMgdGhhdCB3ZSBjYW5ub3RcbiAgLy8gZ2VuZXJhdGUgYW4gXCJleHBvcnQgbmFtZVwiIGZyb20gYSBuZXN0ZWQgc3RhY2sgYmVjYXVzZSB0aGUgZXhwb3J0XG4gIC8vIG5hbWUgbXVzdCBjb250YWluIHRoZSBzdGFjayBuYW1lIHRvIGVuc3VyZSB1bmlxdWVuZXNzLCBhbmQgd2VcbiAgLy8gZG9uJ3Qga25vdyB0aGUgc3RhY2sgbmFtZSBvZiBhIG5lc3RlZCBzdGFjayBiZWZvcmUgd2UgZGVwbG95IGl0LlxuICAvLyB0aGVyZWZvcmUsIHdlIGNhbiBvbmx5IGV4cG9ydCBmcm9tIGEgdG9wLWxldmVsIHN0YWNrLlxuICBpZiAocHJvZHVjZXIubmVzdGVkKSB7XG4gICAgY29uc3Qgb3V0cHV0VmFsdWUgPSBjcmVhdGVOZXN0ZWRTdGFja091dHB1dChwcm9kdWNlciwgcmVmZXJlbmNlKTtcbiAgICByZXR1cm4gcmVzb2x2ZVZhbHVlKGNvbnN1bWVyLCBvdXRwdXRWYWx1ZSk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIGV4cG9ydC9pbXBvcnRcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIGV4cG9ydCB0aGUgdmFsdWUgdGhyb3VnaCBhIGNsb3VkZm9ybWF0aW9uIFwiZXhwb3J0IG5hbWVcIiBhbmQgdXNlIGFuXG4gIC8vIEZuOjpJbXBvcnRWYWx1ZSBpbiB0aGUgY29uc3VtcHRpb24gc2l0ZS5cblxuICAvLyBhZGQgYSBkZXBlbmRlbmN5IGJldHdlZW4gdGhlIHByb2R1Y2VyIGFuZCB0aGUgY29uc3VtZXIuIGRlcGVuZGVuY3kgbG9naWNcbiAgLy8gd2lsbCB0YWtlIGNhcmUgb2YgYXBwbHlpbmcgdGhlIGRlcGVuZGVuY3kgYXQgdGhlIHJpZ2h0IGxldmVsIChlLmcuIHRoZVxuICAvLyB0b3AtbGV2ZWwgc3RhY2tzKS5cbiAgY29uc3VtZXIuYWRkRGVwZW5kZW5jeShwcm9kdWNlcixcbiAgICBgJHtjb25zdW1lci5ub2RlLnBhdGh9IC0+ICR7cmVmZXJlbmNlLnRhcmdldC5ub2RlLnBhdGh9LiR7cmVmZXJlbmNlLmRpc3BsYXlOYW1lfWApO1xuXG4gIHJldHVybiBjcmVhdGVJbXBvcnRWYWx1ZShyZWZlcmVuY2UpO1xufVxuXG4vKipcbiAqIEZpbmRzIGFsbCB0aGUgQ2xvdWRGb3JtYXRpb24gcmVmZXJlbmNlcyBpbiBhIGNvbnN0cnVjdCB0cmVlLlxuICovXG5mdW5jdGlvbiBmaW5kQWxsUmVmZXJlbmNlcyhyb290OiBJQ29uc3RydWN0KSB7XG4gIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheTx7IHNvdXJjZTogQ2ZuRWxlbWVudCwgdmFsdWU6IENmblJlZmVyZW5jZSB9PigpO1xuICBmb3IgKGNvbnN0IGNvbnN1bWVyIG9mIHJvb3Qubm9kZS5maW5kQWxsKCkpIHtcblxuICAgIC8vIGluY2x1ZGUgb25seSBDZm5FbGVtZW50cyAoaS5lLiByZXNvdXJjZXMpXG4gICAgaWYgKCFDZm5FbGVtZW50LmlzQ2ZuRWxlbWVudChjb25zdW1lcikpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB0b2tlbnMgPSBmaW5kVG9rZW5zKGNvbnN1bWVyLCAoKSA9PiBjb25zdW1lci5fdG9DbG91ZEZvcm1hdGlvbigpKTtcblxuICAgICAgLy8gaXRlcmF0ZSBvdmVyIGFsbCB0aGUgdG9rZW5zIChlLmcuIGludHJpbnNpYyBmdW5jdGlvbnMsIGxhemllcywgZXRjKSB0aGF0XG4gICAgICAvLyB3ZXJlIGZvdW5kIGluIHRoZSBjbG91ZGZvcm1hdGlvbiByZXByZXNlbnRhdGlvbiBvZiB0aGlzIHJlc291cmNlLlxuICAgICAgZm9yIChjb25zdCB0b2tlbiBvZiB0b2tlbnMpIHtcblxuICAgICAgICAvLyBpbmNsdWRlIG9ubHkgQ2ZuUmVmZXJlbmNlcyAoaS5lLiBcIlJlZlwiIGFuZCBcIkZuOjpHZXRBdHRcIilcbiAgICAgICAgaWYgKCFDZm5SZWZlcmVuY2UuaXNDZm5SZWZlcmVuY2UodG9rZW4pKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgICAgc291cmNlOiBjb25zdW1lcixcbiAgICAgICAgICB2YWx1ZTogdG9rZW4sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIE5vdGU6IGl0IG1pZ2h0IGJlIHRoYXQgdGhlIHByb3BlcnRpZXMgb2YgdGhlIENGTiBvYmplY3QgYXJlbid0IHZhbGlkLlxuICAgICAgLy8gVGhpcyB3aWxsIHVzdWFsbHkgYmUgcHJldmVudGF0aXZlbHkgY2F1Z2h0IGluIGEgY29uc3RydWN0J3MgdmFsaWRhdGUoKVxuICAgICAgLy8gYW5kIHR1cm5lZCBpbnRvIGEgbmljZWx5IGRlc2NyaXB0aXZlIGVycm9yLCBidXQgd2UncmUgcnVubmluZyBwcmVwYXJlKClcbiAgICAgIC8vIGJlZm9yZSB2YWxpZGF0ZSgpLiBTd2FsbG93IGVycm9ycyB0aGF0IG9jY3VyIGJlY2F1c2UgdGhlIENGTiBsYXllclxuICAgICAgLy8gZG9lc24ndCB2YWxpZGF0ZSBjb21wbGV0ZWx5LlxuICAgICAgLy9cbiAgICAgIC8vIFRoaXMgZG9lcyBtYWtlIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIGVycm9yIHdpbGwgbm90IGJlIHJlY3RpZmllZCxcbiAgICAgIC8vIGJ1dCB0aGUgZXJyb3Igd2lsbCBiZSB0aHJvd24gbGF0ZXIgb24gYW55d2F5LiBJZiB0aGUgZXJyb3IgZG9lc24ndFxuICAgICAgLy8gZ2V0IHRocm93biBkb3duIHRoZSBsaW5lLCB3ZSBtYXkgbWlzcyByZWZlcmVuY2VzLlxuICAgICAgaWYgKGUudHlwZSA9PT0gJ0NmblN5bnRoZXNpc0Vycm9yJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIGV4cG9ydC9pbXBvcnRcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEltcG9ydHMgYSB2YWx1ZSBmcm9tIGFub3RoZXIgc3RhY2sgYnkgY3JlYXRpbmcgYW4gXCJPdXRwdXRcIiB3aXRoIGFuIFwiRXhwb3J0TmFtZVwiXG4gKiBhbmQgcmV0dXJuaW5nIGFuIFwiRm46OkltcG9ydFZhbHVlXCIgdG9rZW4uXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUltcG9ydFZhbHVlKHJlZmVyZW5jZTogUmVmZXJlbmNlKTogSW50cmluc2ljIHtcbiAgY29uc3QgZXhwb3J0aW5nU3RhY2sgPSBTdGFjay5vZihyZWZlcmVuY2UudGFyZ2V0KTtcblxuICBjb25zdCBpbXBvcnRFeHByID0gZXhwb3J0aW5nU3RhY2suZXhwb3J0VmFsdWUocmVmZXJlbmNlKTtcblxuICAvLyBJIGhhcHBlbiB0byBrbm93IHRoaXMgcmV0dXJucyBhIEZuLmltcG9ydFZhbHVlKCkgd2hpY2ggaW1wbGVtZW50cyBJbnRyaW5zaWMuXG4gIHJldHVybiBUb2tlbml6YXRpb24ucmV2ZXJzZUNvbXBsZXRlU3RyaW5nKGltcG9ydEV4cHIpIGFzIEludHJpbnNpYztcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBuZXN0ZWQgc3RhY2tzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBBZGRzIGEgQ2xvdWRGb3JtYXRpb24gcGFyYW1ldGVyIHRvIGEgbmVzdGVkIHN0YWNrIGFuZCBhc3NpZ25zIGl0IHdpdGggdGhlXG4gKiB2YWx1ZSBvZiB0aGUgcmVmZXJlbmNlLlxuICovXG5mdW5jdGlvbiBjcmVhdGVOZXN0ZWRTdGFja1BhcmFtZXRlcihuZXN0ZWQ6IFN0YWNrLCByZWZlcmVuY2U6IENmblJlZmVyZW5jZSwgdmFsdWU6IElSZXNvbHZhYmxlKSB7XG4gIGNvbnN0IHBhcmFtSWQgPSBnZW5lcmF0ZVVuaXF1ZUlkKG5lc3RlZCwgcmVmZXJlbmNlLCAncmVmZXJlbmNlLXRvLScpO1xuICBsZXQgcGFyYW0gPSBuZXN0ZWQubm9kZS50cnlGaW5kQ2hpbGQocGFyYW1JZCkgYXMgQ2ZuUGFyYW1ldGVyO1xuICBpZiAoIXBhcmFtKSB7XG4gICAgcGFyYW0gPSBuZXcgQ2ZuUGFyYW1ldGVyKG5lc3RlZCwgcGFyYW1JZCwgeyB0eXBlOiAnU3RyaW5nJyB9KTtcblxuICAgIC8vIFVnbHkgbGl0dGxlIGhhY2sgdW50aWwgd2UgbW92ZSBOZXN0ZWRTdGFjayB0byB0aGlzIG1vZHVsZS5cbiAgICBpZiAoISgnc2V0UGFyYW1ldGVyJyBpbiBuZXN0ZWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Fzc2VydGlvbiBmYWlsZWQ6IG5lc3RlZCBzdGFjayBzaG91bGQgaGF2ZSBhIFwic2V0UGFyYW1ldGVyXCIgbWV0aG9kJyk7XG4gICAgfVxuXG4gICAgKG5lc3RlZCBhcyBhbnkpLnNldFBhcmFtZXRlcihwYXJhbS5sb2dpY2FsSWQsIFRva2VuLmFzU3RyaW5nKHZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gcGFyYW0udmFsdWUgYXMgQ2ZuUmVmZXJlbmNlO1xufVxuXG4vKipcbiAqIEFkZHMgYSBDbG91ZEZvcm1hdGlvbiBvdXRwdXQgdG8gYSBuZXN0ZWQgc3RhY2sgYW5kIHJldHVybnMgYW4gXCJGbjo6R2V0QXR0XCJcbiAqIGludHJpbnNpYyB0aGF0IGNhbiBiZSB1c2VkIHRvIHJlZmVyZW5jZSB0aGlzIG91dHB1dCBpbiB0aGUgcGFyZW50IHN0YWNrLlxuICovXG5mdW5jdGlvbiBjcmVhdGVOZXN0ZWRTdGFja091dHB1dChwcm9kdWNlcjogU3RhY2ssIHJlZmVyZW5jZTogUmVmZXJlbmNlKTogQ2ZuUmVmZXJlbmNlIHtcbiAgY29uc3Qgb3V0cHV0SWQgPSBnZW5lcmF0ZVVuaXF1ZUlkKHByb2R1Y2VyLCByZWZlcmVuY2UpO1xuICBsZXQgb3V0cHV0ID0gcHJvZHVjZXIubm9kZS50cnlGaW5kQ2hpbGQob3V0cHV0SWQpIGFzIENmbk91dHB1dDtcbiAgaWYgKCFvdXRwdXQpIHtcbiAgICBvdXRwdXQgPSBuZXcgQ2ZuT3V0cHV0KHByb2R1Y2VyLCBvdXRwdXRJZCwgeyB2YWx1ZTogVG9rZW4uYXNTdHJpbmcocmVmZXJlbmNlKSB9KTtcbiAgfVxuXG4gIGlmICghcHJvZHVjZXIubmVzdGVkU3RhY2tSZXNvdXJjZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignYXNzZXJ0aW9uIGZhaWxlZCcpO1xuICB9XG5cbiAgcmV0dXJuIHByb2R1Y2VyLm5lc3RlZFN0YWNrUmVzb3VyY2UuZ2V0QXR0KGBPdXRwdXRzLiR7b3V0cHV0LmxvZ2ljYWxJZH1gKSBhcyBDZm5SZWZlcmVuY2U7XG59XG5cbi8qKlxuICogVHJhbnNsYXRlIGEgUmVmZXJlbmNlIGludG8gYSBuZXN0ZWQgc3RhY2sgaW50byBhIHZhbHVlIGluIHRoZSBwYXJlbnQgc3RhY2tcbiAqXG4gKiBXaWxsIGNyZWF0ZSBPdXRwdXRzIGFsb25nIHRoZSBjaGFpbiBvZiBOZXN0ZWQgU3RhY2tzLCBhbmQgcmV0dXJuIHRoZSBmaW5hbCBgeyBGbjo6R2V0QXR0IH1gLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVmZXJlbmNlTmVzdGVkU3RhY2tWYWx1ZUluUGFyZW50KHJlZmVyZW5jZTogUmVmZXJlbmNlLCB0YXJnZXRTdGFjazogU3RhY2spIHtcbiAgbGV0IGN1cnJlbnRTdGFjayA9IFN0YWNrLm9mKHJlZmVyZW5jZS50YXJnZXQpO1xuICBpZiAoY3VycmVudFN0YWNrICE9PSB0YXJnZXRTdGFjayAmJiAhaXNOZXN0ZWQoY3VycmVudFN0YWNrLCB0YXJnZXRTdGFjaykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFJlZmVyZW5jZWQgcmVzb3VyY2UgbXVzdCBiZSBpbiBzdGFjayAnJHt0YXJnZXRTdGFjay5ub2RlLnBhdGh9JywgZ290ICcke3JlZmVyZW5jZS50YXJnZXQubm9kZS5wYXRofSdgKTtcbiAgfVxuXG4gIHdoaWxlIChjdXJyZW50U3RhY2sgIT09IHRhcmdldFN0YWNrKSB7XG4gICAgcmVmZXJlbmNlID0gY3JlYXRlTmVzdGVkU3RhY2tPdXRwdXQoU3RhY2sub2YocmVmZXJlbmNlLnRhcmdldCksIHJlZmVyZW5jZSk7XG4gICAgY3VycmVudFN0YWNrID0gU3RhY2sub2YocmVmZXJlbmNlLnRhcmdldCk7XG4gIH1cblxuICByZXR1cm4gcmVmZXJlbmNlO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHRydWUgaWYgdGhpcyBzdGFjayBpcyBhIGRpcmVjdCBvciBpbmRpcmVjdCBwYXJlbnQgb2YgdGhlIG5lc3RlZFxuICogc3RhY2sgYG5lc3RlZGAuXG4gKlxuICogSWYgYGNoaWxkYCBpcyBub3QgYSBuZXN0ZWQgc3RhY2ssIGFsd2F5cyByZXR1cm5zIGBmYWxzZWAgYmVjYXVzZSBpdCBjYW4ndFxuICogaGF2ZSBhIHBhcmVudCwgZGFoLlxuICovXG5mdW5jdGlvbiBpc05lc3RlZChuZXN0ZWQ6IFN0YWNrLCBwYXJlbnQ6IFN0YWNrKTogYm9vbGVhbiB7XG4gIC8vIGlmIHRoZSBwYXJlbnQgaXMgYSBkaXJlY3QgcGFyZW50XG4gIGlmIChuZXN0ZWQubmVzdGVkU3RhY2tQYXJlbnQgPT09IHBhcmVudCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gd2UgcmVhY2hlZCBhIHRvcC1sZXZlbCAobm9uLW5lc3RlZCkgc3RhY2sgd2l0aG91dCBmaW5kaW5nIHRoZSBwYXJlbnRcbiAgaWYgKCFuZXN0ZWQubmVzdGVkU3RhY2tQYXJlbnQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyByZWN1cnNlIHdpdGggdGhlIGNoaWxkJ3MgZGlyZWN0IHBhcmVudFxuICByZXR1cm4gaXNOZXN0ZWQobmVzdGVkLm5lc3RlZFN0YWNrUGFyZW50LCBwYXJlbnQpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBpZCBmb3IgYSBgUmVmZXJlbmNlYFxuICogQHBhcmFtIHN0YWNrIEEgc3RhY2sgdXNlZCB0byByZXNvbHZlIHRva2Vuc1xuICogQHBhcmFtIHJlZiBUaGUgcmVmZXJlbmNlXG4gKiBAcGFyYW0gcHJlZml4IE9wdGlvbmFsIHByZWZpeCBmb3IgdGhlIGlkXG4gKiBAcmV0dXJucyBBIHVuaXF1ZSBpZFxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZVVuaXF1ZUlkKHN0YWNrOiBTdGFjaywgcmVmOiBSZWZlcmVuY2UsIHByZWZpeCA9ICcnKSB7XG4gIC8vIHdlIGNhbGwgXCJyZXNvbHZlKClcIiB0byBlbnN1cmUgdGhhdCB0b2tlbnMgZG8gbm90IGNyZWVwIGluIChmb3IgZXhhbXBsZSwgaWYgdGhlIHJlZmVyZW5jZSBkaXNwbGF5IG5hbWUgaW5jbHVkZXMgdG9rZW5zKVxuICByZXR1cm4gc3RhY2sucmVzb2x2ZShgJHtwcmVmaXh9JHtOYW1lcy5ub2RlVW5pcXVlSWQocmVmLnRhcmdldC5ub2RlKX0ke3JlZi5kaXNwbGF5TmFtZX1gKTtcbn0iXX0=