@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
208 lines • 24.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const lazy_1 = require("../lazy");
const reference_1 = require("../reference");
const resolvable_1 = require("../resolvable");
const token_1 = require("../token");
const intrinsic_1 = require("./intrinsic");
const resolve_1 = require("./resolve");
/**
* Routines that know how to do operations at the CloudFormation document language level
*/
class CloudFormationLang {
/**
* Turn an arbitrary structure potentially containing Tokens into a JSON string.
*
* Returns a Token which will evaluate to CloudFormation expression that
* will be evaluated by CloudFormation to the JSON representation of the
* input structure.
*
* All Tokens substituted in this way must return strings, or the evaluation
* in CloudFormation will fail.
*
* @param obj The object to stringify
* @param space Indentation to use (default: no pretty-printing)
*/
static toJSON(obj, space) {
// This works in two stages:
//
// First, resolve everything. This gets rid of the lazy evaluations, evaluation
// to the real types of things (for example, would a function return a string, an
// intrinsic, or a number? We have to resolve to know).
//
// We then to through the returned result, identify things that evaluated to
// CloudFormation intrinsics, and re-wrap those in Tokens that have a
// toJSON() method returning their string representation. If we then call
// JSON.stringify() on that result, that gives us essentially the same
// string that we started with, except with the non-token characters quoted.
//
// {"field": "${TOKEN}"} --> {\"field\": \"${TOKEN}\"}
//
// A final resolve() on that string (done by the framework) will yield the string
// we're after.
//
// Resolving and wrapping are done in go using the resolver framework.
class IntrinsincWrapper extends resolvable_1.DefaultTokenResolver {
constructor() {
super(CLOUDFORMATION_CONCAT);
}
resolveToken(t, context, postProcess) {
// Return References directly, so their type is maintained and the references will
// continue to work. Only while preparing, because we do need the final value of the
// token while resolving.
if (reference_1.Reference.isReference(t) && context.preparing) {
return wrap(t);
}
// Deep-resolve and wrap. This is necessary for Lazy tokens so we can see "inside" them.
return wrap(super.resolveToken(t, context, postProcess));
}
resolveString(fragments, context) {
return wrap(super.resolveString(fragments, context));
}
resolveList(l, context) {
return wrap(super.resolveList(l, context));
}
}
// We need a ResolveContext to get started so return a Token
return lazy_1.Lazy.stringValue({ produce: (ctx) => JSON.stringify(resolve_1.resolve(obj, {
preparing: ctx.preparing,
scope: ctx.scope,
resolver: new IntrinsincWrapper(),
}), undefined, space),
});
function wrap(value) {
return isIntrinsic(value) ? new JsonToken(deepQuoteStringsForJSON(value)) : value;
}
}
/**
* Produce a CloudFormation expression to concat two arbitrary expressions when resolving
*/
static concat(left, right) {
if (left === undefined && right === undefined) {
return '';
}
const parts = new Array();
if (left !== undefined) {
parts.push(left);
}
if (right !== undefined) {
parts.push(right);
}
// Some case analysis to produce minimal expressions
if (parts.length === 1) {
return parts[0];
}
if (parts.length === 2 && typeof parts[0] === 'string' && typeof parts[1] === 'string') {
return parts[0] + parts[1];
}
// Otherwise return a Join intrinsic (already in the target document language to avoid taking
// circular dependencies on FnJoin & friends)
return { 'Fn::Join': ['', minimalCloudFormationJoin('', parts)] };
}
}
exports.CloudFormationLang = CloudFormationLang;
/**
* Token that also stringifies in the toJSON() operation.
*/
class JsonToken extends intrinsic_1.Intrinsic {
/**
* Special handler that gets called when JSON.stringify() is used.
*/
toJSON() {
return this.toString();
}
}
/**
* Deep escape strings for use in a JSON context
*/
function deepQuoteStringsForJSON(x) {
if (typeof x === 'string') {
// Whenever we escape a string we strip off the outermost quotes
// since we're already in a quoted context.
const stringified = JSON.stringify(x);
return stringified.substring(1, stringified.length - 1);
}
if (Array.isArray(x)) {
return x.map(deepQuoteStringsForJSON);
}
if (typeof x === 'object') {
for (const key of Object.keys(x)) {
x[key] = deepQuoteStringsForJSON(x[key]);
}
}
return x;
}
const CLOUDFORMATION_CONCAT = {
join(left, right) {
return CloudFormationLang.concat(left, right);
},
};
/**
* Default Token resolver for CloudFormation templates
*/
exports.CLOUDFORMATION_TOKEN_RESOLVER = new resolvable_1.DefaultTokenResolver(CLOUDFORMATION_CONCAT);
/**
* Do an intelligent CloudFormation join on the given values, producing a minimal expression
*/
function minimalCloudFormationJoin(delimiter, values) {
let i = 0;
while (i < values.length) {
const el = values[i];
if (isSplicableFnJoinIntrinsic(el)) {
values.splice(i, 1, ...el['Fn::Join'][1]);
}
else if (i > 0 && isPlainString(values[i - 1]) && isPlainString(values[i])) {
values[i - 1] += delimiter + values[i];
values.splice(i, 1);
}
else {
i += 1;
}
}
return values;
function isPlainString(obj) {
return typeof obj === 'string' && !token_1.Token.isUnresolved(obj);
}
function isSplicableFnJoinIntrinsic(obj) {
if (!isIntrinsic(obj)) {
return false;
}
if (Object.keys(obj)[0] !== 'Fn::Join') {
return false;
}
const [delim, list] = obj['Fn::Join'];
if (delim !== delimiter) {
return false;
}
if (token_1.Token.isUnresolved(list)) {
return false;
}
if (!Array.isArray(list)) {
return false;
}
return true;
}
}
exports.minimalCloudFormationJoin = minimalCloudFormationJoin;
/**
* Return whether the given value represents a CloudFormation intrinsic
*/
function isIntrinsic(x) {
if (Array.isArray(x) || x === null || typeof x !== 'object') {
return false;
}
const keys = Object.keys(x);
if (keys.length !== 1) {
return false;
}
return keys[0] === 'Ref' || isNameOfCloudFormationIntrinsic(keys[0]);
}
function isNameOfCloudFormationIntrinsic(name) {
if (!name.startsWith('Fn::')) {
return false;
}
// these are 'fake' intrinsics, only usable inside the parameter overrides of a CFN CodePipeline Action
return name !== 'Fn::GetArtifactAtt' && name !== 'Fn::GetParam';
}
exports.isNameOfCloudFormationIntrinsic = isNameOfCloudFormationIntrinsic;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvdWRmb3JtYXRpb24tbGFuZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsb3VkZm9ybWF0aW9uLWxhbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQ0FBK0I7QUFDL0IsNENBQXlDO0FBQ3pDLDhDQUEwSDtBQUUxSCxvQ0FBaUM7QUFDakMsMkNBQXdDO0FBQ3hDLHVDQUFvQztBQUVwQzs7R0FFRztBQUNILE1BQWEsa0JBQWtCO0lBQzdCOzs7Ozs7Ozs7Ozs7T0FZRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBUSxFQUFFLEtBQWM7UUFDM0MsNEJBQTRCO1FBQzVCLEVBQUU7UUFDRiwrRUFBK0U7UUFDL0UsaUZBQWlGO1FBQ2pGLHVEQUF1RDtRQUN2RCxFQUFFO1FBQ0YsNEVBQTRFO1FBQzVFLHFFQUFxRTtRQUNyRSx5RUFBeUU7UUFDekUsc0VBQXNFO1FBQ3RFLDRFQUE0RTtRQUM1RSxFQUFFO1FBQ0YseURBQXlEO1FBQ3pELEVBQUU7UUFDRixpRkFBaUY7UUFDakYsZUFBZTtRQUNmLEVBQUU7UUFDRixzRUFBc0U7UUFDdEUsTUFBTSxpQkFBa0IsU0FBUSxpQ0FBb0I7WUFDbEQ7Z0JBQ0UsS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDL0IsQ0FBQztZQUVNLFlBQVksQ0FBQyxDQUFjLEVBQUUsT0FBd0IsRUFBRSxXQUEyQjtnQkFDdkYsa0ZBQWtGO2dCQUNsRixvRkFBb0Y7Z0JBQ3BGLHlCQUF5QjtnQkFDekIsSUFBSSxxQkFBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFO29CQUFFLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUFFO2dCQUV0RSx3RkFBd0Y7Z0JBQ3hGLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO1lBQzNELENBQUM7WUFDTSxhQUFhLENB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SSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUFFLE9BQU8sS0FBSyxDQUFDO0tBQUU7SUFFOUUsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQUUsT0FBTyxLQUFLLENBQUM7S0FBRTtJQUV4QyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLElBQUksK0JBQStCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdkUsQ0FBQztBQUVELFNBQWdCLCtCQUErQixDQUFDLElBQVk7SUFDMUQsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDNUIsT0FBTyxLQUFLLENBQUM7S0FDZDtJQUNELHVHQUF1RztJQUN2RyxPQUFPLElBQUksS0FBSyxvQkFBb0IsSUFBSSxJQUFJLEtBQUssY0FBYyxDQUFDO0FBQ2xFLENBQUM7QUFORCwwRUFNQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExhenkgfSBmcm9tICcuLi9sYXp5JztcbmltcG9ydCB7IFJlZmVyZW5jZSB9IGZyb20gJy4uL3JlZmVyZW5jZSc7XG5pbXBvcnQgeyBEZWZhdWx0VG9rZW5SZXNvbHZlciwgSUZyYWdtZW50Q29uY2F0ZW5hdG9yLCBJUG9zdFByb2Nlc3NvciwgSVJlc29sdmFibGUsIElSZXNvbHZlQ29udGV4dCB9IGZyb20gJy4uL3Jlc29sdmFibGUnO1xuaW1wb3J0IHsgVG9rZW5pemVkU3RyaW5nRnJhZ21lbnRzIH0gZnJvbSAnLi4vc3RyaW5nLWZyYWdtZW50cyc7XG5pbXBvcnQgeyBUb2tlbiB9IGZyb20gJy4uL3Rva2VuJztcbmltcG9ydCB7IEludHJpbnNpYyB9IGZyb20gJy4vaW50cmluc2ljJztcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tICcuL3Jlc29sdmUnO1xuXG4vKipcbiAqIFJvdXRpbmVzIHRoYXQga25vdyBob3cgdG8gZG8gb3BlcmF0aW9ucyBhdCB0aGUgQ2xvdWRGb3JtYXRpb24gZG9jdW1lbnQgbGFuZ3VhZ2UgbGV2ZWxcbiAqL1xuZXhwb3J0IGNsYXNzIENsb3VkRm9ybWF0aW9uTGFuZyB7XG4gIC8qKlxuICAgKiBUdXJuIGFuIGFyYml0cmFyeSBzdHJ1Y3R1cmUgcG90ZW50aWFsbHkgY29udGFpbmluZyBUb2tlbnMgaW50byBhIEpTT04gc3RyaW5nLlxuICAgKlxuICAgKiBSZXR1cm5zIGEgVG9rZW4gd2hpY2ggd2lsbCBldmFsdWF0ZSB0byBDbG91ZEZvcm1hdGlvbiBleHByZXNzaW9uIHRoYXRcbiAgICogd2lsbCBiZSBldmFsdWF0ZWQgYnkgQ2xvdWRGb3JtYXRpb24gdG8gdGhlIEpTT04gcmVwcmVzZW50YXRpb24gb2YgdGhlXG4gICAqIGlucHV0IHN0cnVjdHVyZS5cbiAgICpcbiAgICogQWxsIFRva2VucyBzdWJzdGl0dXRlZCBpbiB0aGlzIHdheSBtdXN0IHJldHVybiBzdHJpbmdzLCBvciB0aGUgZXZhbHVhdGlvblxuICAgKiBpbiBDbG91ZEZvcm1hdGlvbiB3aWxsIGZhaWwuXG4gICAqXG4gICAqIEBwYXJhbSBvYmogVGhlIG9iamVjdCB0byBzdHJpbmdpZnlcbiAgICogQHBhcmFtIHNwYWNlIEluZGVudGF0aW9uIHRvIHVzZSAoZGVmYXVsdDogbm8gcHJldHR5LXByaW50aW5nKVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyB0b0pTT04ob2JqOiBhbnksIHNwYWNlPzogbnVtYmVyKTogc3RyaW5nIHtcbiAgICAvLyBUaGlzIHdvcmtzIGluIHR3byBzdGFnZXM6XG4gICAgLy9cbiAgICAvLyBGaXJzdCwgcmVzb2x2ZSBldmVyeXRoaW5nLiBUaGlzIGdldHMgcmlkIG9mIHRoZSBsYXp5IGV2YWx1YXRpb25zLCBldmFsdWF0aW9uXG4gICAgLy8gdG8gdGhlIHJlYWwgdHlwZXMgb2YgdGhpbmdzIChmb3IgZXhhbXBsZSwgd291bGQgYSBmdW5jdGlvbiByZXR1cm4gYSBzdHJpbmcsIGFuXG4gICAgLy8gaW50cmluc2ljLCBvciBhIG51bWJlcj8gV2UgaGF2ZSB0byByZXNvbHZlIHRvIGtub3cpLlxuICAgIC8vXG4gICAgLy8gV2UgdGhlbiB0byB0aHJvdWdoIHRoZSByZXR1cm5lZCByZXN1bHQsIGlkZW50aWZ5IHRoaW5ncyB0aGF0IGV2YWx1YXRlZCB0b1xuICAgIC8vIENsb3VkRm9ybWF0aW9uIGludHJpbnNpY3MsIGFuZCByZS13cmFwIHRob3NlIGluIFRva2VucyB0aGF0IGhhdmUgYVxuICAgIC8vIHRvSlNPTigpIG1ldGhvZCByZXR1cm5pbmcgdGhlaXIgc3RyaW5nIHJlcHJlc2VudGF0aW9uLiBJZiB3ZSB0aGVuIGNhbGxcbiAgICAvLyBKU09OLnN0cmluZ2lmeSgpIG9uIHRoYXQgcmVzdWx0LCB0aGF0IGdpdmVzIHVzIGVzc2VudGlhbGx5IHRoZSBzYW1lXG4gICAgLy8gc3RyaW5nIHRoYXQgd2Ugc3RhcnRlZCB3aXRoLCBleGNlcHQgd2l0aCB0aGUgbm9uLXRva2VuIGNoYXJhY3RlcnMgcXVvdGVkLlxuICAgIC8vXG4gICAgLy8gICAge1wiZmllbGRcIjogXCIke1RPS0VOfVwifSAtLT4ge1xcXCJmaWVsZFxcXCI6IFxcXCIke1RPS0VOfVxcXCJ9XG4gICAgLy9cbiAgICAvLyBBIGZpbmFsIHJlc29sdmUoKSBvbiB0aGF0IHN0cmluZyAoZG9uZSBieSB0aGUgZnJhbWV3b3JrKSB3aWxsIHlpZWxkIHRoZSBzdHJpbmdcbiAgICAvLyB3ZSdyZSBhZnRlci5cbiAgICAvL1xuICAgIC8vIFJlc29sdmluZyBhbmQgd3JhcHBpbmcgYXJlIGRvbmUgaW4gZ28gdXNpbmcgdGhlIHJlc29sdmVyIGZyYW1ld29yay5cbiAgICBjbGFzcyBJbnRyaW5zaW5jV3JhcHBlciBleHRlbmRzIERlZmF1bHRUb2tlblJlc29sdmVyIHtcbiAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcihDTE9VREZPUk1BVElPTl9DT05DQVQpO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgcmVzb2x2ZVRva2VuKHQ6IElSZXNvbHZhYmxlLCBjb250ZXh0OiBJUmVzb2x2ZUNvbnRleHQsIHBvc3RQcm9jZXNzOiBJUG9zdFByb2Nlc3Nvcikge1xuICAgICAgICAvLyBSZXR1cm4gUmVmZXJlbmNlcyBkaXJlY3RseSwgc28gdGhlaXIgdHlwZSBpcyBtYWludGFpbmVkIGFuZCB0aGUgcmVmZXJlbmNlcyB3aWxsXG4gICAgICAgIC8vIGNvbnRpbnVlIHRvIHdvcmsuIE9ubHkgd2hpbGUgcHJlcGFyaW5nLCBiZWNhdXNlIHdlIGRvIG5lZWQgdGhlIGZpbmFsIHZhbHVlIG9mIHRoZVxuICAgICAgICAvLyB0b2tlbiB3aGlsZSByZXNvbHZpbmcuXG4gICAgICAgIGlmIChSZWZlcmVuY2UuaXNSZWZlcmVuY2UodCkgJiYgY29udGV4dC5wcmVwYXJpbmcpIHsgcmV0dXJuIHdyYXAodCk7IH1cblxuICAgICAgICAvLyBEZWVwLXJlc29sdmUgYW5kIHdyYXAuIFRoaXMgaXMgbmVjZXNzYXJ5IGZvciBMYXp5IHRva2VucyBzbyB3ZSBjYW4gc2VlIFwiaW5zaWRlXCIgdGhlbS5cbiAgICAgICAgcmV0dXJuIHdyYXAoc3VwZXIucmVzb2x2ZVRva2VuKHQsIGNvbnRleHQsIHBvc3RQcm9jZXNzKSk7XG4gICAgICB9XG4gICAgICBwdWJsaWMgcmVzb2x2ZVN0cmluZyhmcmFnbWVudHM6IFRva2VuaXplZFN0cmluZ0ZyYWdtZW50cywgY29udGV4dDogSVJlc29sdmVDb250ZXh0KSB7XG4gICAgICAgIHJldHVybiB3cmFwKHN1cGVyLnJlc29sdmVTdHJpbmcoZnJhZ21lbnRzLCBjb250ZXh0KSk7XG4gICAgICB9XG4gICAgICBwdWJsaWMgcmVzb2x2ZUxpc3QobDogc3RyaW5nW10sIGNvbnRleHQ6IElSZXNvbHZlQ29udGV4dCkge1xuICAgICAgICByZXR1cm4gd3JhcChzdXBlci5yZXNvbHZlTGlzdChsLCBjb250ZXh0KSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gV2UgbmVlZCBhIFJlc29sdmVDb250ZXh0IHRvIGdldCBzdGFydGVkIHNvIHJldHVybiBhIFRva2VuXG4gICAgcmV0dXJuIExhenkuc3RyaW5nVmFsdWUoeyBwcm9kdWNlOiAoY3R4OiBJUmVzb2x2ZUNvbnRleHQpID0+XG4gICAgICBKU09OLnN0cmluZ2lmeShyZXNvbHZlKG9iaiwge1xuICAgICAgICBwcmVwYXJpbmc6IGN0eC5wcmVwYXJpbmcsXG4gICAgICAgIHNjb3BlOiBjdHguc2NvcGUsXG4gICAgICAgIHJlc29sdmVyOiBuZXcgSW50cmluc2luY1dyYXBwZXIoKSxcbiAgICAgIH0pLCB1bmRlZmluZWQsIHNwYWNlKSxcbiAgICB9KTtcblxuICAgIGZ1bmN0aW9uIHdyYXAodmFsdWU6IGFueSk6IGFueSB7XG4gICAgICByZXR1cm4gaXNJbnRyaW5zaWModmFsdWUpID8gbmV3IEpzb25Ub2tlbihkZWVwUXVvdGVTdHJpbmdzRm9ySlNPTih2YWx1ZSkpIDogdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByb2R1Y2UgYSBDbG91ZEZvcm1hdGlvbiBleHByZXNzaW9uIHRvIGNvbmNhdCB0d28gYXJiaXRyYXJ5IGV4cHJlc3Npb25zIHdoZW4gcmVzb2x2aW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbmNhdChsZWZ0OiBhbnkgfCB1bmRlZmluZWQsIHJpZ2h0OiBhbnkgfCB1bmRlZmluZWQpOiBhbnkge1xuICAgIGlmIChsZWZ0ID09PSB1bmRlZmluZWQgJiYgcmlnaHQgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gJyc7IH1cblxuICAgIGNvbnN0IHBhcnRzID0gbmV3IEFycmF5PGFueT4oKTtcbiAgICBpZiAobGVmdCAhPT0gdW5kZWZpbmVkKSB7IHBhcnRzLnB1c2gobGVmdCk7IH1cbiAgICBpZiAocmlnaHQgIT09IHVuZGVmaW5lZCkgeyBwYXJ0cy5wdXNoKHJpZ2h0KTsgfVxuXG4gICAgLy8gU29tZSBjYXNlIGFuYWx5c2lzIHRvIHByb2R1Y2UgbWluaW1hbCBleHByZXNzaW9uc1xuICAgIGlmIChwYXJ0cy5sZW5ndGggPT09IDEpIHsgcmV0dXJuIHBhcnRzWzBdOyB9XG4gICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMiAmJiB0eXBlb2YgcGFydHNbMF0gPT09ICdzdHJpbmcnICYmIHR5cGVvZiBwYXJ0c1sxXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBwYXJ0c1swXSArIHBhcnRzWzFdO1xuICAgIH1cblxuICAgIC8vIE90aGVyd2lzZSByZXR1cm4gYSBKb2luIGludHJpbnNpYyAoYWxyZWFkeSBpbiB0aGUgdGFyZ2V0IGRvY3VtZW50IGxhbmd1YWdlIHRvIGF2b2lkIHRha2luZ1xuICAgIC8vIGNpcmN1bGFyIGRlcGVuZGVuY2llcyBvbiBGbkpvaW4gJiBmcmllbmRzKVxuICAgIHJldHVybiB7ICdGbjo6Sm9pbic6IFsnJywgbWluaW1hbENsb3VkRm9ybWF0aW9uSm9pbignJywgcGFydHMpXSB9O1xuICB9XG59XG5cbi8qKlxuICogVG9rZW4gdGhhdCBhbHNvIHN0cmluZ2lmaWVzIGluIHRoZSB0b0pTT04oKSBvcGVyYXRpb24uXG4gKi9cbmNsYXNzIEpzb25Ub2tlbiBleHRlbmRzIEludHJpbnNpYyB7XG4gIC8qKlxuICAgKiBTcGVjaWFsIGhhbmRsZXIgdGhhdCBnZXRzIGNhbGxlZCB3aGVuIEpTT04uc3RyaW5naWZ5KCkgaXMgdXNlZC5cbiAgICovXG4gIHB1YmxpYyB0b0pTT04oKSB7XG4gICAgcmV0dXJuIHRoaXMudG9TdHJpbmcoKTtcbiAgfVxufVxuXG4vKipcbiAqIERlZXAgZXNjYXBlIHN0cmluZ3MgZm9yIHVzZSBpbiBhIEpTT04gY29udGV4dFxuICovXG5mdW5jdGlvbiBkZWVwUXVvdGVTdHJpbmdzRm9ySlNPTih4OiBhbnkpOiBhbnkge1xuICBpZiAodHlwZW9mIHggPT09ICdzdHJpbmcnKSB7XG4gICAgLy8gV2hlbmV2ZXIgd2UgZXNjYXBlIGEgc3RyaW5nIHdlIHN0cmlwIG9mZiB0aGUgb3V0ZXJtb3N0IHF1b3Rlc1xuICAgIC8vIHNpbmNlIHdlJ3JlIGFscmVhZHkgaW4gYSBxdW90ZWQgY29udGV4dC5cbiAgICBjb25zdCBzdHJpbmdpZmllZCA9IEpTT04uc3RyaW5naWZ5KHgpO1xuICAgIHJldHVybiBzdHJpbmdpZmllZC5zdWJzdHJpbmcoMSwgc3RyaW5naWZpZWQubGVuZ3RoIC0gMSk7XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheSh4KSkge1xuICAgIHJldHVybiB4Lm1hcChkZWVwUXVvdGVTdHJpbmdzRm9ySlNPTik7XG4gIH1cblxuICBpZiAodHlwZW9mIHggPT09ICdvYmplY3QnKSB7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoeCkpIHtcbiAgICAgIHhba2V5XSA9IGRlZXBRdW90ZVN0cmluZ3NGb3JKU09OKHhba2V5XSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHg7XG59XG5cbmNvbnN0IENMT1VERk9STUFUSU9OX0NPTkNBVDogSUZyYWdtZW50Q29uY2F0ZW5hdG9yID0ge1xuICBqb2luKGxlZnQ6IGFueSwgcmlnaHQ6IGFueSkge1xuICAgIHJldHVybiBDbG91ZEZvcm1hdGlvbkxhbmcuY29uY2F0KGxlZnQsIHJpZ2h0KTtcbiAgfSxcbn07XG5cbi8qKlxuICogRGVmYXVsdCBUb2tlbiByZXNvbHZlciBmb3IgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGVzXG4gKi9cbmV4cG9ydCBjb25zdCBDTE9VREZPUk1BVElPTl9UT0tFTl9SRVNPTFZFUiA9IG5ldyBEZWZhdWx0VG9rZW5SZXNvbHZlcihDTE9VREZPUk1BVElPTl9DT05DQVQpO1xuXG4vKipcbiAqIERvIGFuIGludGVsbGlnZW50IENsb3VkRm9ybWF0aW9uIGpvaW4gb24gdGhlIGdpdmVuIHZhbHVlcywgcHJvZHVjaW5nIGEgbWluaW1hbCBleHByZXNzaW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtaW5pbWFsQ2xvdWRGb3JtYXRpb25Kb2luKGRlbGltaXRlcjogc3RyaW5nLCB2YWx1ZXM6IGFueVtdKTogYW55W10ge1xuICBsZXQgaSA9IDA7XG4gIHdoaWxlIChpIDwgdmFsdWVzLmxlbmd0aCkge1xuICAgIGNvbnN0IGVsID0gdmFsdWVzW2ldO1xuICAgIGlmIChpc1NwbGljYWJsZUZuSm9pbkludHJpbnNpYyhlbCkpIHtcbiAgICAgIHZhbHVlcy5zcGxpY2UoaSwgMSwgLi4uZWxbJ0ZuOjpKb2luJ11bMV0pO1xuICAgIH0gZWxzZSBpZiAoaSA+IDAgJiYgaXNQbGFpblN0cmluZyh2YWx1ZXNbaSAtIDFdKSAmJiBpc1BsYWluU3RyaW5nKHZhbHVlc1tpXSkpIHtcbiAgICAgIHZhbHVlc1tpIC0gMV0gKz0gZGVsaW1pdGVyICsgdmFsdWVzW2ldO1xuICAgICAgdmFsdWVzLnNwbGljZShpLCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaSArPSAxO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB2YWx1ZXM7XG5cbiAgZnVuY3Rpb24gaXNQbGFpblN0cmluZyhvYmo6IGFueSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSAnc3RyaW5nJyAmJiAhVG9rZW4uaXNVbnJlc29sdmVkKG9iaik7XG4gIH1cblxuICBmdW5jdGlvbiBpc1NwbGljYWJsZUZuSm9pbkludHJpbnNpYyhvYmo6IGFueSk6IGJvb2xlYW4ge1xuICAgIGlmICghaXNJbnRyaW5zaWMob2JqKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgICBpZiAoT2JqZWN0LmtleXMob2JqKVswXSAhPT0gJ0ZuOjpKb2luJykgeyByZXR1cm4gZmFsc2U7ICB9XG5cbiAgICBjb25zdCBbIGRlbGltLCBsaXN0IF0gPSBvYmpbJ0ZuOjpKb2luJ107XG4gICAgaWYgKGRlbGltICE9PSBkZWxpbWl0ZXIpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKGxpc3QpKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIGlmICghQXJyYXkuaXNBcnJheShsaXN0KSkgeyByZXR1cm4gZmFsc2U7IH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgdGhlIGdpdmVuIHZhbHVlIHJlcHJlc2VudHMgYSBDbG91ZEZvcm1hdGlvbiBpbnRyaW5zaWNcbiAqL1xuZnVuY3Rpb24gaXNJbnRyaW5zaWMoeDogYW55KSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHgpIHx8IHggPT09IG51bGwgfHwgdHlwZW9mIHggIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfVxuXG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyh4KTtcbiAgaWYgKGtleXMubGVuZ3RoICE9PSAxKSB7IHJldHVybiBmYWxzZTsgfVxuXG4gIHJldHVybiBrZXlzWzBdID09PSAnUmVmJyB8fCBpc05hbWVPZkNsb3VkRm9ybWF0aW9uSW50cmluc2ljKGtleXNbMF0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNOYW1lT2ZDbG91ZEZvcm1hdGlvbkludHJpbnNpYyhuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKCFuYW1lLnN0YXJ0c1dpdGgoJ0ZuOjonKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyB0aGVzZSBhcmUgJ2Zha2UnIGludHJpbnNpY3MsIG9ubHkgdXNhYmxlIGluc2lkZSB0aGUgcGFyYW1ldGVyIG92ZXJyaWRlcyBvZiBhIENGTiBDb2RlUGlwZWxpbmUgQWN0aW9uXG4gIHJldHVybiBuYW1lICE9PSAnRm46OkdldEFydGlmYWN0QXR0JyAmJiBuYW1lICE9PSAnRm46OkdldFBhcmFtJztcbn1cbiJdfQ==