@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
257 lines • 34.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolvedTypeHint = exports.RememberingTokenResolver = exports.findTokens = exports.resolve = exports.ResolutionTypeHint = exports.INTRINSIC_KEY_PREFIX = void 0;
const resolvable_1 = require("../resolvable");
const encoding_1 = require("./encoding");
const token_map_1 = require("./token-map");
// This file should not be exported to consumers, resolving should happen through Construct.resolve()
const tokenMap = token_map_1.TokenMap.instance();
/**
* Resolved complex values will have a type hint applied.
*
* The type hint will be based on the type of the input value that was resolved.
*
* If the value was encoded, the type hint will be the type of the encoded value. In case
* of a plain `IResolvable`, a type hint of 'string' will be assumed.
*/
const RESOLUTION_TYPEHINT_SYM = Symbol.for('@aws-cdk/core.resolvedTypeHint');
/**
* Prefix used for intrinsic keys
*
* If a key with this prefix is found in an object, the actual value of the
* key doesn't matter. The value of this key will be an `[ actualKey, actualValue ]`
* tuple, and the `actualKey` will be a value which otherwise couldn't be represented
* in the types of `string | number | symbol`, which are the only possible JavaScript
* object keys.
*/
exports.INTRINSIC_KEY_PREFIX = '$IntrinsicKey$';
/**
* Type hints for resolved values
*/
var ResolutionTypeHint;
(function (ResolutionTypeHint) {
ResolutionTypeHint["STRING"] = "string";
ResolutionTypeHint["NUMBER"] = "number";
ResolutionTypeHint["LIST"] = "list";
})(ResolutionTypeHint = exports.ResolutionTypeHint || (exports.ResolutionTypeHint = {}));
/**
* Resolves an object by evaluating all tokens and removing any undefined or empty objects or arrays.
* Values can only be primitives, arrays or tokens. Other objects (i.e. with methods) will be rejected.
*
* @param obj The object to resolve.
* @param prefix Prefix key path components for diagnostics.
*/
function resolve(obj, options) {
const prefix = options.prefix || [];
const pathName = '/' + prefix.join('/');
/**
* Make a new resolution context
*/
function makeContext(appendPath) {
const newPrefix = appendPath !== undefined ? prefix.concat([appendPath]) : options.prefix;
let postProcessor;
const context = {
preparing: options.preparing,
scope: options.scope,
documentPath: newPrefix ?? [],
registerPostProcessor(pp) { postProcessor = pp; },
resolve(x, changeOptions) { return resolve(x, { ...options, ...changeOptions, prefix: newPrefix }); },
};
return [context, { postProcess(x) { return postProcessor ? postProcessor.postProcess(x, context) : x; } }];
}
// protect against cyclic references by limiting depth.
if (prefix.length > 200) {
throw new Error('Unable to resolve object tree with circular reference. Path: ' + pathName);
}
// whether to leave the empty elements when resolving - false by default
const leaveEmpty = options.removeEmpty === false;
//
// undefined
//
if (typeof (obj) === 'undefined') {
return undefined;
}
//
// null
//
if (obj === null) {
return null;
}
//
// functions - not supported (only tokens are supported)
//
if (typeof (obj) === 'function') {
throw new Error(`Trying to resolve a non-data object. Only token are supported for lazy evaluation. Path: ${pathName}. Object: ${obj}`);
}
//
// string - potentially replace all stringified Tokens
//
if (typeof (obj) === 'string') {
// If this is a "list element" Token, it should never occur by itself in string context
if (encoding_1.TokenString.forListToken(obj).test()) {
throw new Error('Found an encoded list token string in a scalar string context. Use \'Fn.select(0, list)\' (not \'list[0]\') to extract elements from token lists.');
}
// Otherwise look for a stringified Token in this object
const str = encoding_1.TokenString.forString(obj);
if (str.test()) {
const fragments = str.split(tokenMap.lookupToken.bind(tokenMap));
return tagResolvedValue(options.resolver.resolveString(fragments, makeContext()[0]), ResolutionTypeHint.STRING);
}
return obj;
}
//
// number - potentially decode Tokenized number
//
if (typeof (obj) === 'number') {
return tagResolvedValue(resolveNumberToken(obj, makeContext()[0]), ResolutionTypeHint.NUMBER);
}
//
// primitives - as-is
//
if (typeof (obj) !== 'object' || obj instanceof Date) {
return obj;
}
//
// arrays - resolve all values, remove undefined and remove empty arrays
//
if (Array.isArray(obj)) {
if (encoding_1.containsListTokenElement(obj)) {
return tagResolvedValue(options.resolver.resolveList(obj, makeContext()[0]), ResolutionTypeHint.LIST);
}
const arr = obj
.map((x, i) => makeContext(`${i}`)[0].resolve(x))
.filter(x => leaveEmpty || typeof (x) !== 'undefined');
return arr;
}
//
// tokens - invoke 'resolve' and continue to resolve recursively
//
if (encoding_1.unresolved(obj)) {
const [context, postProcessor] = makeContext();
const ret = tagResolvedValue(options.resolver.resolveToken(obj, context, postProcessor), ResolutionTypeHint.STRING);
return ret;
}
//
// objects - deep-resolve all values
//
// Must not be a Construct at this point, otherwise you probably made a typo
// mistake somewhere and resolve will get into an infinite loop recursing into
// child.parent <---> parent.children
if (isConstruct(obj)) {
throw new Error('Trying to resolve() a Construct at ' + pathName);
}
const result = {};
let intrinsicKeyCtr = 0;
for (const key of Object.keys(obj)) {
const value = makeContext(String(key))[0].resolve(obj[key]);
// skip undefined
if (typeof (value) === 'undefined') {
if (leaveEmpty) {
result[key] = undefined;
}
continue;
}
// Simple case -- not an unresolved key
if (!encoding_1.unresolved(key)) {
result[key] = value;
continue;
}
const resolvedKey = makeContext()[0].resolve(key);
if (typeof (resolvedKey) === 'string') {
result[resolvedKey] = value;
}
else {
if (!options.allowIntrinsicKeys) {
// eslint-disable-next-line max-len
throw new Error(`"${String(key)}" is used as the key in a map so must resolve to a string, but it resolves to: ${JSON.stringify(resolvedKey)}. Consider using "CfnJson" to delay resolution to deployment-time`);
}
// Can't represent this object in a JavaScript key position, but we can store it
// in value position. Use a unique symbol as the key.
result[`${exports.INTRINSIC_KEY_PREFIX}${intrinsicKeyCtr++}`] = [resolvedKey, value];
}
}
// Because we may be called to recurse on already resolved values (that already have type hints applied)
// and we just copied those values into a fresh object, be sure to retain any type hints.
const previousTypeHint = resolvedTypeHint(obj);
return previousTypeHint ? tagResolvedValue(result, previousTypeHint) : result;
}
exports.resolve = resolve;
/**
* Find all Tokens that are used in the given structure
*/
function findTokens(scope, fn) {
const resolver = new RememberingTokenResolver(new resolvable_1.StringConcat());
resolve(fn(), { scope, prefix: [], resolver, preparing: true });
return resolver.tokens;
}
exports.findTokens = findTokens;
/**
* Remember all Tokens encountered while resolving
*/
class RememberingTokenResolver extends resolvable_1.DefaultTokenResolver {
constructor() {
super(...arguments);
this.tokensSeen = new Set();
}
resolveToken(t, context, postProcessor) {
this.tokensSeen.add(t);
return super.resolveToken(t, context, postProcessor);
}
resolveString(s, context) {
const ret = super.resolveString(s, context);
return ret;
}
get tokens() {
return Array.from(this.tokensSeen);
}
}
exports.RememberingTokenResolver = RememberingTokenResolver;
/**
* Determine whether an object is a Construct
*
* Not in 'construct.ts' because that would lead to a dependency cycle via 'uniqueid.ts',
* and this is a best-effort protection against a common programming mistake anyway.
*/
function isConstruct(x) {
return x._children !== undefined && x._metadata !== undefined;
}
function resolveNumberToken(x, context) {
const token = token_map_1.TokenMap.instance().lookupNumberToken(x);
if (token === undefined) {
return x;
}
return context.resolve(token);
}
/**
* Apply a type hint to a resolved value
*
* The type hint will only be applied to objects.
*
* These type hints are used for correct JSON-ification of intrinsic values.
*/
function tagResolvedValue(value, typeHint) {
if (typeof value !== 'object' || value == null) {
return value;
}
Object.defineProperty(value, RESOLUTION_TYPEHINT_SYM, {
value: typeHint,
configurable: true,
});
return value;
}
/**
* Return the type hint from the given value
*
* If the value is not a resolved value (i.e, the result of resolving a token),
* `undefined` will be returned.
*
* These type hints are used for correct JSON-ification of intrinsic values.
*/
function resolvedTypeHint(value) {
if (typeof value !== 'object' || value == null) {
return undefined;
}
return value[RESOLUTION_TYPEHINT_SYM];
}
exports.resolvedTypeHint = resolvedTypeHint;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb2x2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc29sdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsOENBQThKO0FBRTlKLHlDQUErRTtBQUMvRSwyQ0FBdUM7QUFNdkMscUdBQXFHO0FBQ3JHLE1BQU0sUUFBUSxHQUFHLG9CQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7QUFFckM7Ozs7Ozs7R0FPRztBQUNILE1BQU0sdUJBQXVCLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO0FBRTdFOzs7Ozs7OztHQVFHO0FBQ1UsUUFBQSxvQkFBb0IsR0FBRyxnQkFBZ0IsQ0FBQztBQUVyRDs7R0FFRztBQUNILElBQVksa0JBSVg7QUFKRCxXQUFZLGtCQUFrQjtJQUM1Qix1Q0FBaUIsQ0FBQTtJQUNqQix1Q0FBaUIsQ0FBQTtJQUNqQixtQ0FBYSxDQUFBO0FBQ2YsQ0FBQyxFQUpXLGtCQUFrQixHQUFsQiwwQkFBa0IsS0FBbEIsMEJBQWtCLFFBSTdCO0FBc0REOzs7Ozs7R0FNRztBQUNILFNBQWdCLE9BQU8sQ0FBQyxHQUFRLEVBQUUsT0FBd0I7SUFDeEQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFDcEMsTUFBTSxRQUFRLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFeEM7O09BRUc7SUFDSCxTQUFTLFdBQVcsQ0FBQyxVQUFtQjtRQUN0QyxNQUFNLFNBQVMsR0FBRyxVQUFVLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUUxRixJQUFJLGFBQXlDLENBQUM7UUFFOUMsTUFBTSxPQUFPLEdBQW9CO1lBQy9CLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixLQUFLLEVB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QUF1QixDQUFDLENBQUM7QUFDeEMsQ0FBQztBQUhELDRDQUdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUNvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgRGVmYXVsdFRva2VuUmVzb2x2ZXIsIElQb3N0UHJvY2Vzc29yLCBJUmVzb2x2YWJsZSwgSVJlc29sdmVDb250ZXh0LCBJVG9rZW5SZXNvbHZlciwgUmVzb2x2ZUNoYW5nZUNvbnRleHRPcHRpb25zLCBTdHJpbmdDb25jYXQgfSBmcm9tICcuLi9yZXNvbHZhYmxlJztcbmltcG9ydCB7IFRva2VuaXplZFN0cmluZ0ZyYWdtZW50cyB9IGZyb20gJy4uL3N0cmluZy1mcmFnbWVudHMnO1xuaW1wb3J0IHsgY29udGFpbnNMaXN0VG9rZW5FbGVtZW50LCBUb2tlblN0cmluZywgdW5yZXNvbHZlZCB9IGZyb20gJy4vZW5jb2RpbmcnO1xuaW1wb3J0IHsgVG9rZW5NYXAgfSBmcm9tICcuL3Rva2VuLW1hcCc7XG5cbi8vIHYyIC0gbGVhdmUgdGhpcyBhcyBhIHNlcGFyYXRlIHNlY3Rpb24gc28gaXQgcmVkdWNlcyBtZXJnZSBjb25mbGljdHMgd2hlbiBjb21wYXQgaXMgcmVtb3ZlZFxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9vcmRlclxuaW1wb3J0IHsgSUNvbnN0cnVjdCBhcyBJQ29yZUNvbnN0cnVjdCB9IGZyb20gJy4uL2NvbnN0cnVjdC1jb21wYXQnO1xuXG4vLyBUaGlzIGZpbGUgc2hvdWxkIG5vdCBiZSBleHBvcnRlZCB0byBjb25zdW1lcnMsIHJlc29sdmluZyBzaG91bGQgaGFwcGVuIHRocm91Z2ggQ29uc3RydWN0LnJlc29sdmUoKVxuY29uc3QgdG9rZW5NYXAgPSBUb2tlbk1hcC5pbnN0YW5jZSgpO1xuXG4vKipcbiAqIFJlc29sdmVkIGNvbXBsZXggdmFsdWVzIHdpbGwgaGF2ZSBhIHR5cGUgaGludCBhcHBsaWVkLlxuICpcbiAqIFRoZSB0eXBlIGhpbnQgd2lsbCBiZSBiYXNlZCBvbiB0aGUgdHlwZSBvZiB0aGUgaW5wdXQgdmFsdWUgdGhhdCB3YXMgcmVzb2x2ZWQuXG4gKlxuICogSWYgdGhlIHZhbHVlIHdhcyBlbmNvZGVkLCB0aGUgdHlwZSBoaW50IHdpbGwgYmUgdGhlIHR5cGUgb2YgdGhlIGVuY29kZWQgdmFsdWUuIEluIGNhc2VcbiAqIG9mIGEgcGxhaW4gYElSZXNvbHZhYmxlYCwgYSB0eXBlIGhpbnQgb2YgJ3N0cmluZycgd2lsbCBiZSBhc3N1bWVkLlxuICovXG5jb25zdCBSRVNPTFVUSU9OX1RZUEVISU5UX1NZTSA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUucmVzb2x2ZWRUeXBlSGludCcpO1xuXG4vKipcbiAqIFByZWZpeCB1c2VkIGZvciBpbnRyaW5zaWMga2V5c1xuICpcbiAqIElmIGEga2V5IHdpdGggdGhpcyBwcmVmaXggaXMgZm91bmQgaW4gYW4gb2JqZWN0LCB0aGUgYWN0dWFsIHZhbHVlIG9mIHRoZVxuICoga2V5IGRvZXNuJ3QgbWF0dGVyLiBUaGUgdmFsdWUgb2YgdGhpcyBrZXkgd2lsbCBiZSBhbiBgWyBhY3R1YWxLZXksIGFjdHVhbFZhbHVlIF1gXG4gKiB0dXBsZSwgYW5kIHRoZSBgYWN0dWFsS2V5YCB3aWxsIGJlIGEgdmFsdWUgd2hpY2ggb3RoZXJ3aXNlIGNvdWxkbid0IGJlIHJlcHJlc2VudGVkXG4gKiBpbiB0aGUgdHlwZXMgb2YgYHN0cmluZyB8IG51bWJlciB8IHN5bWJvbGAsIHdoaWNoIGFyZSB0aGUgb25seSBwb3NzaWJsZSBKYXZhU2NyaXB0XG4gKiBvYmplY3Qga2V5cy5cbiAqL1xuZXhwb3J0IGNvbnN0IElOVFJJTlNJQ19LRVlfUFJFRklYID0gJyRJbnRyaW5zaWNLZXkkJztcblxuLyoqXG4gKiBUeXBlIGhpbnRzIGZvciByZXNvbHZlZCB2YWx1ZXNcbiAqL1xuZXhwb3J0IGVudW0gUmVzb2x1dGlvblR5cGVIaW50IHtcbiAgU1RSSU5HID0gJ3N0cmluZycsXG4gIE5VTUJFUiA9ICdudW1iZXInLFxuICBMSVNUID0gJ2xpc3QnLFxufVxuXG4vKipcbiAqIE9wdGlvbnMgdG8gdGhlIHJlc29sdmUoKSBvcGVyYXRpb25cbiAqXG4gKiBOT1QgdGhlIHNhbWUgYXMgdGhlIFJlc29sdmVDb250ZXh0OyBSZXNvbHZlQ29udGV4dCBpcyBleHBvc2VkIHRvIFRva2VuXG4gKiBpbXBsZW1lbnRvcnMgYW5kIHJlc29sdXRpb24gaG9va3MsIHdoZXJlYXMgdGhpcyBzdHJ1Y3QgaXMganVzdCB0byBidW5kbGVcbiAqIGEgbnVtYmVyIG9mIHRoaW5ncyB0aGF0IHdvdWxkIG90aGVyd2lzZSBiZSBhcmd1bWVudHMgdG8gcmVzb2x2ZSgpIGluIGFcbiAqIHJlYWRhYmxlIHdheS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJUmVzb2x2ZU9wdGlvbnMge1xuICBzY29wZTogSUNvbnN0cnVjdDtcbiAgcHJlcGFyaW5nOiBib29sZWFuO1xuICByZXNvbHZlcjogSVRva2VuUmVzb2x2ZXI7XG4gIHByZWZpeD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyBpbnRyaW5zaWNzIGluIGtleXMgb2YgYW4gb2JqZWN0XG4gICAqXG4gICAqIEJlY2F1c2Uga2V5cyBvZiBhbiBvYmplY3QgbXVzdCBiZSBzdHJpbmdzLCBhIChyZXNvbHZlZCkgaW50cmluc2ljLCB3aGljaFxuICAgKiBpcyBhbiBvYmplY3QsIGNhbm5vdCBiZSBzdG9yZWQgaW4gdGhhdCBwb3NpdGlvbi4gQnkgZGVmYXVsdCwgd2UgcmVqZWN0IHRoZXNlXG4gICAqIGludHJpbnNpY3MgaWYgd2UgZW5jb3VudGVyIHRoZW0uXG4gICAqXG4gICAqIElmIHRoaXMgaXMgc2V0IHRvIGB0cnVlYCwgaW4gb3JkZXIgdG8gc3RvcmUgdGhlIGNvbXBsZXggdmFsdWUgaW4gYSBtYXAsXG4gICAqIGtleXMgdGhhdCBoYXBwZW4gdG8gZXZhbHVhdGUgdG8gaW50cmluc2ljcyB3aWxsIGJlIGFkZGVkIHdpdGggYSB1bmlxdWUga2V5XG4gICAqIGlkZW50aWZpZWQgYnkgYW4gdW5jb21taW5nIHByZWZpeCwgbWFwcGVkIHRvIGEgdHVwbGUgdGhhdCByZXByZXNlbnRzIHRoZVxuICAgKiBhY3R1YWwga2V5L3ZhbHVlLXBhaXIuIFRoZSBtYXAgd2lsbCBsb29rIGxpa2UgdGhpczpcbiAgICpcbiAgICoge1xuICAgKiAgICAnJEludHJpbnNpY0tleSQwJzogWyB7IFJlZjogLi4uIH0sICd2YWx1ZTEnIF0sXG4gICAqICAgICckSW50cmluc2ljS2V5JDEnOiBbIHsgUmVmOiAuLi4gfSwgJ3ZhbHVlMicgXSxcbiAgICogICAgJ3JlZ3VsYXJLZXknOiAndmFsdWUzJyxcbiAgICogICAgLi4uXG4gICAqIH1cbiAgICpcbiAgICogQ2FsbGVycyBzaG91bGQgb25seSBzZXQgdGhpcyBvcHRpb24gdG8gYHRydWVgIGlmIHRoZXkgYXJlIHByZXBhcmVkIHRvIGRlYWwgd2l0aFxuICAgKiB0aGUgb2JqZWN0IGluIHRoaXMgd2VpcmQgc2hhcGUsIGFuZCBtYXNzYWdlIGl0IGJhY2sgaW50byBhIGNvcnJlY3Qgb2JqZWN0IGFmdGVyd2FyZHMuXG4gICAqXG4gICAqIChBIHJlZ3VsYXIgYnV0IHVuY29tbW9uIHN0cmluZyB3YXMgY2hvc2VuIG92ZXIgc29tZXRoaW5nIGxpa2Ugc3ltYm9scyBvclxuICAgKiBvdGhlciB3YXlzIG9mIHRhZ2dpbmcgdGhlIGV4dHJhIHZhbHVlcyBpbiBvcmRlciB0byBzaW1wbGlmeSB0aGUgaW1wbGVtZW50YXRpb24gd2hpY2hcbiAgICogbWFpbnRhaW5zIHRoZSBkZXNpcmVkIGJlaGF2aW9yIGByZXNvbHZlKHJlc29sdmUoeCkpID09IHJlc29sdmUoeClgKS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGFsbG93SW50cmluc2ljS2V5cz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gcmVtb3ZlIHVuZGVmaW5lZCBlbGVtZW50cyBmcm9tIGFycmF5cyBhbmQgb2JqZWN0cyB3aGVuIHJlc29sdmluZy5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVtb3ZlRW1wdHk/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFJlc29sdmVzIGFuIG9iamVjdCBieSBldmFsdWF0aW5nIGFsbCB0b2tlbnMgYW5kIHJlbW92aW5nIGFueSB1bmRlZmluZWQgb3IgZW1wdHkgb2JqZWN0cyBvciBhcnJheXMuXG4gKiBWYWx1ZXMgY2FuIG9ubHkgYmUgcHJpbWl0aXZlcywgYXJyYXlzIG9yIHRva2Vucy4gT3RoZXIgb2JqZWN0cyAoaS5lLiB3aXRoIG1ldGhvZHMpIHdpbGwgYmUgcmVqZWN0ZWQuXG4gKlxuICogQHBhcmFtIG9iaiBUaGUgb2JqZWN0IHRvIHJlc29sdmUuXG4gKiBAcGFyYW0gcHJlZml4IFByZWZpeCBrZXkgcGF0aCBjb21wb25lbnRzIGZvciBkaWFnbm9zdGljcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmUob2JqOiBhbnksIG9wdGlvbnM6IElSZXNvbHZlT3B0aW9ucyk6IGFueSB7XG4gIGNvbnN0IHByZWZpeCA9IG9wdGlvbnMucHJlZml4IHx8IFtdO1xuICBjb25zdCBwYXRoTmFtZSA9ICcvJyArIHByZWZpeC5qb2luKCcvJyk7XG5cbiAgLyoqXG4gICAqIE1ha2UgYSBuZXcgcmVzb2x1dGlvbiBjb250ZXh0XG4gICAqL1xuICBmdW5jdGlvbiBtYWtlQ29udGV4dChhcHBlbmRQYXRoPzogc3RyaW5nKTogW0lSZXNvbHZlQ29udGV4dCwgSVBvc3RQcm9jZXNzb3JdIHtcbiAgICBjb25zdCBuZXdQcmVmaXggPSBhcHBlbmRQYXRoICE9PSB1bmRlZmluZWQgPyBwcmVmaXguY29uY2F0KFthcHBlbmRQYXRoXSkgOiBvcHRpb25zLnByZWZpeDtcblxuICAgIGxldCBwb3N0UHJvY2Vzc29yOiBJUG9zdFByb2Nlc3NvciB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGNvbnRleHQ6IElSZXNvbHZlQ29udGV4dCA9IHtcbiAgICAgIHByZXBhcmluZzogb3B0aW9ucy5wcmVwYXJpbmcsXG4gICAgICBzY29wZTogb3B0aW9ucy5zY29wZSBhcyBJQ29yZUNvbnN0cnVjdCxcbiAgICAgIGRvY3VtZW50UGF0aDogbmV3UHJlZml4ID8/IFtdLFxuICAgICAgcmVnaXN0ZXJQb3N0UHJvY2Vzc29yKHBwKSB7IHBvc3RQcm9jZXNzb3IgPSBwcDsgfSxcbiAgICAgIHJlc29sdmUoeDogYW55LCBjaGFuZ2VPcHRpb25zPzogUmVzb2x2ZUNoYW5nZUNvbnRleHRPcHRpb25zKSB7IHJldHVybiByZXNvbHZlKHgsIHsgLi4ub3B0aW9ucywgLi4uY2hhbmdlT3B0aW9ucywgcHJlZml4OiBuZXdQcmVmaXggfSk7IH0sXG4gICAgfTtcblxuICAgIHJldHVybiBbY29udGV4dCwgeyBwb3N0UHJvY2Vzcyh4KSB7IHJldHVybiBwb3N0UHJvY2Vzc29yID8gcG9zdFByb2Nlc3Nvci5wb3N0UHJvY2Vzcyh4LCBjb250ZXh0KSA6IHg7IH0gfV07XG4gIH1cblxuICAvLyBwcm90ZWN0IGFnYWluc3QgY3ljbGljIHJlZmVyZW5jZXMgYnkgbGltaXRpbmcgZGVwdGguXG4gIGlmIChwcmVmaXgubGVuZ3RoID4gMjAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gcmVzb2x2ZSBvYmplY3QgdHJlZSB3aXRoIGNpcmN1bGFyIHJlZmVyZW5jZS4gUGF0aDogJyArIHBhdGhOYW1lKTtcbiAgfVxuXG4gIC8vIHdoZXRoZXIgdG8gbGVhdmUgdGhlIGVtcHR5IGVsZW1lbnRzIHdoZW4gcmVzb2x2aW5nIC0gZmFsc2UgYnkgZGVmYXVsdFxuICBjb25zdCBsZWF2ZUVtcHR5ID0gb3B0aW9ucy5yZW1vdmVFbXB0eSA9PT0gZmFsc2U7XG5cbiAgLy9cbiAgLy8gdW5kZWZpbmVkXG4gIC8vXG5cbiAgaWYgKHR5cGVvZihvYmopID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvL1xuICAvLyBudWxsXG4gIC8vXG5cbiAgaWYgKG9iaiA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy9cbiAgLy8gZnVuY3Rpb25zIC0gbm90IHN1cHBvcnRlZCAob25seSB0b2tlbnMgYXJlIHN1cHBvcnRlZClcbiAgLy9cblxuICBpZiAodHlwZW9mKG9iaikgPT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRyeWluZyB0byByZXNvbHZlIGEgbm9uLWRhdGEgb2JqZWN0LiBPbmx5IHRva2VuIGFyZSBzdXBwb3J0ZWQgZm9yIGxhenkgZXZhbHVhdGlvbi4gUGF0aDogJHtwYXRoTmFtZX0uIE9iamVjdDogJHtvYmp9YCk7XG4gIH1cblxuICAvL1xuICAvLyBzdHJpbmcgLSBwb3RlbnRpYWxseSByZXBsYWNlIGFsbCBzdHJpbmdpZmllZCBUb2tlbnNcbiAgLy9cbiAgaWYgKHR5cGVvZihvYmopID09PSAnc3RyaW5nJykge1xuICAgIC8vIElmIHRoaXMgaXMgYSBcImxpc3QgZWxlbWVudFwiIFRva2VuLCBpdCBzaG91bGQgbmV2ZXIgb2NjdXIgYnkgaXRzZWxmIGluIHN0cmluZyBjb250ZXh0XG4gICAgaWYgKFRva2VuU3RyaW5nLmZvckxpc3RUb2tlbihvYmopLnRlc3QoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGb3VuZCBhbiBlbmNvZGVkIGxpc3QgdG9rZW4gc3RyaW5nIGluIGEgc2NhbGFyIHN0cmluZyBjb250ZXh0LiBVc2UgXFwnRm4uc2VsZWN0KDAsIGxpc3QpXFwnIChub3QgXFwnbGlzdFswXVxcJykgdG8gZXh0cmFjdCBlbGVtZW50cyBmcm9tIHRva2VuIGxpc3RzLicpO1xuICAgIH1cblxuICAgIC8vIE90aGVyd2lzZSBsb29rIGZvciBhIHN0cmluZ2lmaWVkIFRva2VuIGluIHRoaXMgb2JqZWN0XG4gICAgY29uc3Qgc3RyID0gVG9rZW5TdHJpbmcuZm9yU3RyaW5nKG9iaik7XG4gICAgaWYgKHN0ci50ZXN0KCkpIHtcbiAgICAgIGNvbnN0IGZyYWdtZW50cyA9IHN0ci5zcGxpdCh0b2tlbk1hcC5sb29rdXBUb2tlbi5iaW5kKHRva2VuTWFwKSk7XG4gICAgICByZXR1cm4gdGFnUmVzb2x2ZWRWYWx1ZShvcHRpb25zLnJlc29sdmVyLnJlc29sdmVTdHJpbmcoZnJhZ21lbnRzLCBtYWtlQ29udGV4dCgpWzBdKSwgUmVzb2x1dGlvblR5cGVIaW50LlNUUklORyk7XG4gICAgfVxuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICAvL1xuICAvLyBudW1iZXIgLSBwb3RlbnRpYWxseSBkZWNvZGUgVG9rZW5pemVkIG51bWJlclxuICAvL1xuICBpZiAodHlwZW9mKG9iaikgPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIHRhZ1Jlc29sdmVkVmFsdWUocmVzb2x2ZU51bWJlclRva2VuKG9iaiwgbWFrZUNvbnRleHQoKVswXSksIFJlc29sdXRpb25UeXBlSGludC5OVU1CRVIpO1xuICB9XG5cbiAgLy9cbiAgLy8gcHJpbWl0aXZlcyAtIGFzLWlzXG4gIC8vXG5cbiAgaWYgKHR5cGVvZihvYmopICE9PSAnb2JqZWN0JyB8fCBvYmogaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIC8vXG4gIC8vIGFycmF5cyAtIHJlc29sdmUgYWxsIHZhbHVlcywgcmVtb3ZlIHVuZGVmaW5lZCBhbmQgcmVtb3ZlIGVtcHR5IGFycmF5c1xuICAvL1xuXG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICBpZiAoY29udGFpbnNMaXN0VG9rZW5FbGVtZW50KG9iaikpIHtcbiAgICAgIHJldHVybiB0YWdSZXNvbHZlZFZhbHVlKG9wdGlvbnMucmVzb2x2ZXIucmVzb2x2ZUxpc3Qob2JqLCBtYWtlQ29udGV4dCgpWzBdKSwgUmVzb2x1dGlvblR5cGVIaW50LkxJU1QpO1xuICAgIH1cblxuICAgIGNvbnN0IGFyciA9IG9ialxuICAgICAgLm1hcCgoeCwgaSkgPT4gbWFrZUNvbnRleHQoYCR7aX1gKVswXS5yZXNvbHZlKHgpKVxuICAgICAgLmZpbHRlcih4ID0+IGxlYXZlRW1wdHkgfHwgdHlwZW9mKHgpICE9PSAndW5kZWZpbmVkJyk7XG5cbiAgICByZXR1cm4gYXJyO1xuICB9XG5cbiAgLy9cbiAgLy8gdG9rZW5zIC0gaW52b2tlICdyZXNvbHZlJyBhbmQgY29udGludWUgdG8gcmVzb2x2ZSByZWN1cnNpdmVseVxuICAvL1xuXG4gIGlmICh1bnJlc29sdmVkKG9iaikpIHtcbiAgICBjb25zdCBbY29udGV4dCwgcG9zdFByb2Nlc3Nvcl0gPSBtYWtlQ29udGV4dCgpO1xuICAgIGNvbnN0IHJldCA9IHRhZ1Jlc29sdmVkVmFsdWUob3B0aW9ucy5yZXNvbHZlci5yZXNvbHZlVG9rZW4ob2JqLCBjb250ZXh0LCBwb3N0UHJvY2Vzc29yKSwgUmVzb2x1dGlvblR5cGVIaW50LlNUUklORyk7XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIC8vXG4gIC8vIG9iamVjdHMgLSBkZWVwLXJlc29sdmUgYWxsIHZhbHVlc1xuICAvL1xuXG4gIC8vIE11c3Qgbm90IGJlIGEgQ29uc3RydWN0IGF0IHRoaXMgcG9pbnQsIG90aGVyd2lzZSB5b3UgcHJvYmFibHkgbWFkZSBhIHR5cG9cbiAgLy8gbWlzdGFrZSBzb21ld2hlcmUgYW5kIHJlc29sdmUgd2lsbCBnZXQgaW50byBhbiBpbmZpbml0ZSBsb29wIHJlY3Vyc2luZyBpbnRvXG4gIC8vIGNoaWxkLnBhcmVudCA8LS0tPiBwYXJlbnQuY2hpbGRyZW5cbiAgaWYgKGlzQ29uc3RydWN0KG9iaikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyeWluZyB0byByZXNvbHZlKCkgYSBDb25zdHJ1Y3QgYXQgJyArIHBhdGhOYW1lKTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdDogYW55ID0geyB9O1xuICBsZXQgaW50cmluc2ljS2V5Q3RyID0gMDtcbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMob2JqKSkge1xuICAgIGNvbnN0IHZhbHVlID0gbWFrZUNvbnRleHQoU3RyaW5nKGtleSkpWzBdLnJlc29sdmUob2JqW2tleV0pO1xuXG4gICAgLy8gc2tpcCB1bmRlZmluZWRcbiAgICBpZiAodHlwZW9mKHZhbHVlKSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmIChsZWF2ZUVtcHR5KSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gU2ltcGxlIGNhc2UgLS0gbm90IGFuIHVucmVzb2x2ZWQga2V5XG4gICAgaWYgKCF1bnJlc29sdmVkKGtleSkpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvbHZlZEtleSA9IG1ha2VDb250ZXh0KClbMF0ucmVzb2x2ZShrZXkpO1xuICAgIGlmICh0eXBlb2YocmVzb2x2ZWRLZXkpID09PSAnc3RyaW5nJykge1xuICAgICAgcmVzdWx0W3Jlc29sdmVkS2V5XSA9IHZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIW9wdGlvbnMuYWxsb3dJbnRyaW5zaWNLZXlzKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgXCIke1N0cmluZyhrZXkpfVwiIGlzIHVzZWQgYXMgdGhlIGtleSBpbiBhIG1hcCBzbyBtdXN0IHJlc29sdmUgdG8gYSBzdHJpbmcsIGJ1dCBpdCByZXNvbHZlcyB0bzogJHtKU09OLnN0cmluZ2lmeShyZXNvbHZlZEtleSl9LiBDb25zaWRlciB1c2luZyBcIkNmbkpzb25cIiB0byBkZWxheSByZXNvbHV0aW9uIHRvIGRlcGxveW1lbnQtdGltZWApO1xuICAgICAgfVxuXG4gICAgICAvLyBDYW4ndCByZXByZXNlbnQgdGhpcyBvYmplY3QgaW4gYSBKYXZhU2NyaXB0IGtleSBwb3NpdGlvbiwgYnV0IHdlIGNhbiBzdG9yZSBpdFxuICAgICAgLy8gaW4gdmFsdWUgcG9zaXRpb24uIFVzZSBhIHVuaXF1ZSBzeW1ib2wgYXMgdGhlIGtleS5cbiAgICAgIHJlc3VsdFtgJHtJTlRSSU5TSUNfS0VZX1BSRUZJWH0ke2ludHJpbnNpY0tleUN0cisrfWBdID0gW3Jlc29sdmVkS2V5LCB2YWx1ZV07XG4gICAgfVxuICB9XG5cbiAgLy8gQmVjYXVzZSB3ZSBtYXkgYmUgY2FsbGVkIHRvIHJlY3Vyc2Ugb24gYWxyZWFkeSByZXNvbHZlZCB2YWx1ZXMgKHRoYXQgYWxyZWFkeSBoYXZlIHR5cGUgaGludHMgYXBwbGllZClcbiAgLy8gYW5kIHdlIGp1c3QgY29waWVkIHRob3NlIHZhbHVlcyBpbnRvIGEgZnJlc2ggb2JqZWN0LCBiZSBzdXJlIHRvIHJldGFpbiBhbnkgdHlwZSBoaW50cy5cbiAgY29uc3QgcHJldmlvdXNUeXBlSGludCA9IHJlc29sdmVkVHlwZUhpbnQob2JqKTtcbiAgcmV0dXJuIHByZXZpb3VzVHlwZUhpbnQgPyB0YWdSZXNvbHZlZFZhbHVlKHJlc3VsdCwgcHJldmlvdXNUeXBlSGludCkgOiByZXN1bHQ7XG59XG5cbi8qKlxuICogRmluZCBhbGwgVG9rZW5zIHRoYXQgYXJlIHVzZWQgaW4gdGhlIGdpdmVuIHN0cnVjdHVyZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFRva2VucyhzY29wZTogSUNvbnN0cnVjdCwgZm46ICgpID0+IGFueSk6IElSZXNvbHZhYmxlW10ge1xuICBjb25zdCByZXNvbHZlciA9IG5ldyBSZW1lbWJlcmluZ1Rva2VuUmVzb2x2ZXIobmV3IFN0cmluZ0NvbmNhdCgpKTtcblxuICByZXNvbHZlKGZuKCksIHsgc2NvcGUsIHByZWZpeDogW10sIHJlc29sdmVyLCBwcmVwYXJpbmc6IHRydWUgfSk7XG5cbiAgcmV0dXJuIHJlc29sdmVyLnRva2Vucztcbn1cblxuLyoqXG4gKiBSZW1lbWJlciBhbGwgVG9rZW5zIGVuY291bnRlcmVkIHdoaWxlIHJlc29sdmluZ1xuICovXG5leHBvcnQgY2xhc3MgUmVtZW1iZXJpbmdUb2tlblJlc29sdmVyIGV4dGVuZHMgRGVmYXVsdFRva2VuUmVzb2x2ZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IHRva2Vuc1NlZW4gPSBuZXcgU2V0PElSZXNvbHZhYmxlPigpO1xuXG4gIHB1YmxpYyByZXNvbHZlVG9rZW4odDogSVJlc29sdmFibGUsIGNvbnRleHQ6IElSZXNvbHZlQ29udGV4dCwgcG9zdFByb2Nlc3NvcjogSVBvc3RQcm9jZXNzb3IpIHtcbiAgICB0aGlzLnRva2Vuc1NlZW4uYWRkKHQpO1xuICAgIHJldHVybiBzdXBlci5yZXNvbHZlVG9rZW4odCwgY29udGV4dCwgcG9zdFByb2Nlc3Nvcik7XG4gIH1cblxuICBwdWJsaWMgcmVzb2x2ZVN0cmluZyhzOiBUb2tlbml6ZWRTdHJpbmdGcmFnbWVudHMsIGNvbnRleHQ6IElSZXNvbHZlQ29udGV4dCkge1xuICAgIGNvbnN0IHJldCA9IHN1cGVyLnJlc29sdmVTdHJpbmcocywgY29udGV4dCk7XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdG9rZW5zKCk6IElSZXNvbHZhYmxlW10ge1xuICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMudG9rZW5zU2Vlbik7XG4gIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciBhbiBvYmplY3QgaXMgYSBDb25zdHJ1Y3RcbiAqXG4gKiBOb3QgaW4gJ2NvbnN0cnVjdC50cycgYmVjYXVzZSB0aGF0IHdvdWxkIGxlYWQgdG8gYSBkZXBlbmRlbmN5IGN5Y2xlIHZpYSAndW5pcXVlaWQudHMnLFxuICogYW5kIHRoaXMgaXMgYSBiZXN0LWVmZm9ydCBwcm90ZWN0aW9uIGFnYWluc3QgYSBjb21tb24gcHJvZ3JhbW1pbmcgbWlzdGFrZSBhbnl3YXkuXG4gKi9cbmZ1bmN0aW9uIGlzQ29uc3RydWN0KHg6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4geC5fY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiB4Ll9tZXRhZGF0YSAhPT0gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyVG9rZW4oeDogbnVtYmVyLCBjb250ZXh0OiBJUmVzb2x2ZUNvbnRleHQpOiBhbnkge1xuICBjb25zdCB0b2tlbiA9IFRva2VuTWFwLmluc3RhbmNlKCkubG9va3VwTnVtYmVyVG9rZW4oeCk7XG4gIGlmICh0b2tlbiA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB4OyB9XG4gIHJldHVybiBjb250ZXh0LnJlc29sdmUodG9rZW4pO1xufVxuXG4vKipcbiAqIEFwcGx5IGEgdHlwZSBoaW50IHRvIGEgcmVzb2x2ZWQgdmFsdWVcbiAqXG4gKiBUaGUgdHlwZSBoaW50IHdpbGwgb25seSBiZSBhcHBsaWVkIHRvIG9iamVjdHMuXG4gKlxuICogVGhlc2UgdHlwZSBoaW50cyBhcmUgdXNlZCBmb3IgY29ycmVjdCBKU09OLWlmaWNhdGlvbiBvZiBpbnRyaW5zaWMgdmFsdWVzLlxuICovXG5mdW5jdGlvbiB0YWdSZXNvbHZlZFZhbHVlKHZhbHVlOiBhbnksIHR5cGVIaW50OiBSZXNvbHV0aW9uVHlwZUhpbnQpOiBhbnkge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JyB8fCB2YWx1ZSA9PSBudWxsKSB7IHJldHVybiB2YWx1ZTsgfVxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkodmFsdWUsIFJFU09MVVRJT05fVFlQRUhJTlRfU1lNLCB7XG4gICAgdmFsdWU6IHR5cGVIaW50LFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgfSk7XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLyoqXG4gKiBSZXR1cm4gdGhlIHR5cGUgaGludCBmcm9tIHRoZSBnaXZlbiB2YWx1ZVxuICpcbiAqIElmIHRoZSB2YWx1ZSBpcyBub3QgYSByZXNvbHZlZCB2YWx1ZSAoaS5lLCB0aGUgcmVzdWx0IG9mIHJlc29sdmluZyBhIHRva2VuKSxcbiAqIGB1bmRlZmluZWRgIHdpbGwgYmUgcmV0dXJuZWQuXG4gKlxuICogVGhlc2UgdHlwZSBoaW50cyBhcmUgdXNlZCBmb3IgY29ycmVjdCBKU09OLWlmaWNhdGlvbiBvZiBpbnRyaW5zaWMgdmFsdWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZWRUeXBlSGludCh2YWx1ZTogYW55KTogUmVzb2x1dGlvblR5cGVIaW50IHwgdW5kZWZpbmVkIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcgfHwgdmFsdWUgPT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gIHJldHVybiB2YWx1ZVtSRVNPTFVUSU9OX1RZUEVISU5UX1NZTV07XG59XG4iXX0=
;