@grnsft/if
Version:
Impact Framework
130 lines • 16.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAggregationInfoFor = exports.storeAggregationMetrics = exports.aggregate = void 0;
const consts_1 = require("@grnsft/if-core/consts");
const debug_logger_1 = require("../../common/util/debug-logger");
const logger_1 = require("../../common/util/logger");
const aggregation_helper_1 = require("../util/aggregation-helper");
const log_memoize_1 = require("../util/log-memoize");
const strings_1 = require("../config/strings");
const { AGGREGATING_NODE, AGGREGATING_OUTPUTS, UNKNOWN_PARAM, CHECKING_AGGREGATION_METHOD, } = strings_1.STRINGS;
/**
* Gets `i`th element from all children outputs and collects them in single array.
*/
const getIthElementsFromChildren = (children, i) => {
const values = Object.values(children);
return values.map((value) => {
const output = value.outputs;
return output[i];
});
};
/**
* 1. Gets the i'th element from each childrens outputs (treating children as rows and we are after a column of data).
* 2. Now we just aggregate over the `ithSliceOfOutputs` the same as we did for the normal outputs.
*/
const temporalAggregation = (node, metrics) => {
const outputs = [];
const values = Object.values(node.children);
for (let i = 0; i < values[0].outputs.length; i++) {
const ithSliceOfOutputs = getIthElementsFromChildren(node.children, i);
outputs.push((0, aggregation_helper_1.aggregateOutputsIntoOne)(ithSliceOfOutputs, metrics, true));
}
return outputs;
};
/**
* Navigates the tree depth first, bottom up,
* left to right aggregating the component nodes and then the grouping nodes will be aggregated
* only when all their child nodes have been aggregated.
* 1. Aggregates all the children.
* 2. At this point you can be positive all your children have been aggregated and so you can now work on aggregating yourself.
* 3. It's component node, аggregates just the outputs of THIS component node (horizontal/component aggregation).
* 4. Else it's grouping node, first does temporal aggregation. This assumes everything is on the same time-grid.
* The outputs of the grouping node are the aggregated time bucketed outputs of it's children.
* 5. Now a grouping node has it's own outputs, it can horizotnally aggregate them.
*/
const aggregateNode = (node, aggregationParams) => {
const metrics = aggregationParams.metrics;
const type = aggregationParams.type;
if (node.children) {
for (const child in node.children) {
console.debug(AGGREGATING_NODE(child));
aggregateNode(node.children[child], aggregationParams);
}
}
if (!node.children) {
/** `time` aggregation is the new name of `horizontal`. */
if (type === 'horizontal' || type === 'time' || type === 'both') {
node.aggregated = (0, aggregation_helper_1.aggregateOutputsIntoOne)(node.outputs, metrics);
}
}
else {
/** `component` aggregation is the new name of `vertical`. */
if (type === 'vertical' || type === 'component' || type === 'both') {
const outputs = temporalAggregation(node, metrics);
node.outputs = outputs;
node.aggregated = (0, aggregation_helper_1.aggregateOutputsIntoOne)(outputs, metrics);
}
}
};
/**
* If aggregation is disabled, then returns given `tree`.
* Otherwise creates copy of the tree, then applies aggregation to it.
*/
const aggregate = (tree, aggregationParams) => {
console.debug(AGGREGATING_OUTPUTS);
if (!aggregationParams || !aggregationParams.type) {
return tree;
}
const copyOfTree = structuredClone(tree);
aggregateNode(copyOfTree, aggregationParams);
return copyOfTree;
};
exports.aggregate = aggregate;
/**
* Gets or stores aggregation metrics.
*/
const storeAggregationMetrics = (aggregationMetrics) => {
if (aggregationMetrics) {
metricManager.metrics = {
...metricManager.metrics,
...aggregationMetrics,
};
}
return metricManager.metrics;
};
exports.storeAggregationMetrics = storeAggregationMetrics;
/**
* Creates an encapsulated object to retrieve the metrics.
*/
const metricManager = (() => {
let metric;
const manager = {
get metrics() {
return metric;
},
set metrics(value) {
metric = value;
},
};
return manager;
})();
/**
* Returns aggregation method for given `metric`.
*/
const getAggregationInfoFor = (metric) => {
debug_logger_1.debugLogger.setExecutingPluginName();
(0, log_memoize_1.memoizedLog)(console.debug, '\n');
(0, log_memoize_1.memoizedLog)(console.debug, CHECKING_AGGREGATION_METHOD(metric));
const aggregationMetricsStorage = (0, exports.storeAggregationMetrics)();
if (aggregationMetricsStorage &&
Object.keys(aggregationMetricsStorage).includes(metric)) {
return aggregationMetricsStorage[metric];
}
(0, log_memoize_1.memoizedLog)(logger_1.logger.warn, UNKNOWN_PARAM(metric));
return {
time: consts_1.AGGREGATION_METHODS[3],
component: consts_1.AGGREGATION_METHODS[3],
};
};
exports.getAggregationInfoFor = getAggregationInfoFor;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdncmVnYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2lmLXJ1bi9saWIvYWdncmVnYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1EQUEyRDtBQUczRCxpRUFBMkQ7QUFDM0QscURBQWdEO0FBT2hELG1FQUFtRTtBQUNuRSxxREFBZ0Q7QUFFaEQsK0NBQTBDO0FBRTFDLE1BQU0sRUFDSixnQkFBZ0IsRUFDaEIsbUJBQW1CLEVBQ25CLGFBQWEsRUFDYiwyQkFBMkIsR0FDNUIsR0FBRyxpQkFBTyxDQUFDO0FBRVo7O0dBRUc7QUFDSCxNQUFNLDBCQUEwQixHQUFHLENBQUMsUUFBYSxFQUFFLENBQVMsRUFBRSxFQUFFO0lBQzlELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFdkMsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBVSxFQUFFLEVBQUU7UUFDL0IsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUU3QixPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxJQUFTLEVBQUUsT0FBaUIsRUFBRSxFQUFFO0lBQzNELE1BQU0sT0FBTyxHQUFtQixFQUFFLENBQUM7SUFDbkMsTUFBTSxNQUFNLEdBQVEsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFakQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ2pELE1BQU0saUJBQWlCLEdBQUcsMEJBQTBCLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENB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QUMsRUFBRSxDQUFDO0FBRUw7O0dBRUc7QUFDSSxNQUFNLHFCQUFxQixHQUFHLENBQUMsTUFBYyxFQUFFLEVBQUU7SUFDdEQsMEJBQVcsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO0lBQ3JDLElBQUEseUJBQVcsRUFBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pDLElBQUEseUJBQVcsRUFBQyxPQUFPLENBQUMsS0FBSyxFQUFFLDJCQUEyQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDaEUsTUFBTSx5QkFBeUIsR0FBRyxJQUFBLCtCQUF1QixHQUFFLENBQUM7SUFFNUQsSUFDRSx5QkFBeUI7UUFDekIsTUFBTSxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFDdkQ7UUFDQSxPQUFPLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzFDO0lBRUQsSUFBQSx5QkFBVyxFQUFDLGVBQU0sQ0FBQyxJQUFJLEVBQUUsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFFaEQsT0FBTztRQUNMLElBQUksRUFBRSw0QkFBbUIsQ0FBQyxDQUFDLENBQUM7UUFDNUIsU0FBUyxFQUFFLDRCQUFtQixDQUFDLENBQUMsQ0FBQztLQUNsQyxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBbkJXLFFBQUEscUJBQXFCLHlCQW1CaEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0FHR1JFR0FUSU9OX01FVEhPRFN9IGZyb20gJ0Bncm5zZnQvaWYtY29yZS9jb25zdHMnO1xuaW1wb3J0IHtQbHVnaW5QYXJhbXN9IGZyb20gJ0Bncm5zZnQvaWYtY29yZS90eXBlcyc7XG5cbmltcG9ydCB7ZGVidWdMb2dnZXJ9IGZyb20gJy4uLy4uL2NvbW1vbi91dGlsL2RlYnVnLWxvZ2dlcic7XG5pbXBvcnQge2xvZ2dlcn0gZnJvbSAnLi4vLi4vY29tbW9uL3V0aWwvbG9nZ2VyJztcbmltcG9ydCB7XG4gIEFnZ3JlZ2F0aW9uUGFyYW1zLFxuICBBZ2dyZWdhdGlvblBhcmFtc1N1cmUsXG4gIEFnZ3JlZ2F0aW9uTWV0cmljc1dpdGhNZXRob2QsXG59IGZyb20gJy4uLy4uL2NvbW1vbi90eXBlcy9tYW5pZmVzdCc7XG5cbmltcG9ydCB7YWdncmVnYXRlT3V0cHV0c0ludG9PbmV9IGZyb20gJy4uL3V0aWwvYWdncmVnYXRpb24taGVscGVyJztcbmltcG9ydCB7bWVtb2l6ZWRMb2d9IGZyb20gJy4uL3V0aWwvbG9nLW1lbW9pemUnO1xuXG5pbXBvcnQge1NUUklOR1N9IGZyb20gJy4uL2NvbmZpZy9zdHJpbmdzJztcblxuY29uc3Qge1xuICBBR0dSRUdBVElOR19OT0RFLFxuICBBR0dSRUdBVElOR19PVVRQVVRTLFxuICBVTktOT1dOX1BBUkFNLFxuICBDSEVDS0lOR19BR0dSRUdBVElPTl9NRVRIT0QsXG59ID0gU1RSSU5HUztcblxuLyoqXG4gKiBHZXRzIGBpYHRoIGVsZW1lbnQgZnJvbSBhbGwgY2hpbGRyZW4gb3V0cHV0cyBhbmQgY29sbGVjdHMgdGhlbSBpbiBzaW5nbGUgYXJyYXkuXG4gKi9cbmNvbnN0IGdldEl0aEVsZW1lbnRzRnJvbUNoaWxkcmVuID0gKGNoaWxkcmVuOiBhbnksIGk6IG51bWJlcikgPT4ge1xuICBjb25zdCB2YWx1ZXMgPSBPYmplY3QudmFsdWVzKGNoaWxkcmVuKTtcblxuICByZXR1cm4gdmFsdWVzLm1hcCgodmFsdWU6IGFueSkgPT4ge1xuICAgIGNvbnN0IG91dHB1dCA9IHZhbHVlLm91dHB1dHM7XG5cbiAgICByZXR1cm4gb3V0cHV0W2ldO1xuICB9KTtcbn07XG5cbi8qKlxuICogMS4gR2V0cyB0aGUgaSd0aCBlbGVtZW50IGZyb20gZWFjaCBjaGlsZHJlbnMgb3V0cHV0cyAodHJlYXRpbmcgY2hpbGRyZW4gYXMgcm93cyBhbmQgd2UgYXJlIGFmdGVyIGEgY29sdW1uIG9mIGRhdGEpLlxuICogMi4gTm93IHdlIGp1c3QgYWdncmVnYXRlIG92ZXIgdGhlIGBpdGhTbGljZU9mT3V0cHV0c2AgdGhlIHNhbWUgYXMgd2UgZGlkIGZvciB0aGUgbm9ybWFsIG91dHB1dHMuXG4gKi9cbmNvbnN0IHRlbXBvcmFsQWdncmVnYXRpb24gPSAobm9kZTogYW55LCBtZXRyaWNzOiBzdHJpbmdbXSkgPT4ge1xuICBjb25zdCBvdXRwdXRzOiBQbHVnaW5QYXJhbXNbXSA9IFtdO1xuICBjb25zdCB2YWx1ZXM6IGFueSA9IE9iamVjdC52YWx1ZXMobm9kZS5jaGlsZHJlbik7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx1ZXNbMF0ub3V0cHV0cy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGl0aFNsaWNlT2ZPdXRwdXRzID0gZ2V0SXRoRWxlbWVudHNGcm9tQ2hpbGRyZW4obm9kZS5jaGlsZHJlbiwgaSk7XG4gICAgb3V0cHV0cy5wdXNoKGFnZ3JlZ2F0ZU91dHB1dHNJbnRvT25lKGl0aFNsaWNlT2ZPdXRwdXRzLCBtZXRyaWNzLCB0cnVlKSk7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0cztcbn07XG5cbi8qKlxuICogTmF2aWdhdGVzIHRoZSB0cmVlIGRlcHRoIGZpcnN0LCBib3R0b20gdXAsXG4gKiAgbGVmdCB0byByaWdodCBhZ2dyZWdhdGluZyB0aGUgY29tcG9uZW50IG5vZGVzIGFuZCB0aGVuIHRoZSBncm91cGluZyBub2RlcyB3aWxsIGJlIGFnZ3JlZ2F0ZWRcbiAqICBvbmx5IHdoZW4gYWxsIHRoZWlyIGNoaWxkIG5vZGVzIGhhdmUgYmVlbiBhZ2dyZWdhdGVkLlxuICogMS4gQWdncmVnYXRlcyBhbGwgdGhlIGNoaWxkcmVuLlxuICogMi4gQXQgdGhpcyBwb2ludCB5b3UgY2FuIGJlIHBvc2l0aXZlIGFsbCB5b3VyIGNoaWxkcmVuIGhhdmUgYmVlbiBhZ2dyZWdhdGVkIGFuZCBzbyB5b3UgY2FuIG5vdyB3b3JrIG9uIGFnZ3JlZ2F0aW5nIHlvdXJzZWxmLlxuICogMy4gSXQncyBjb21wb25lbnQgbm9kZSwg0LBnZ3JlZ2F0ZXMganVzdCB0aGUgb3V0cHV0cyBvZiBUSElTIGNvbXBvbmVudCBub2RlIChob3Jpem9udGFsL2NvbXBvbmVudCBhZ2dyZWdhdGlvbikuXG4gKiA0LiBFbHNlIGl0J3MgZ3JvdXBpbmcgbm9kZSwgZmlyc3QgZG9lcyB0ZW1wb3JhbCBhZ2dyZWdhdGlvbi4gVGhpcyBhc3N1bWVzIGV2ZXJ5dGhpbmcgaXMgb24gdGhlIHNhbWUgdGltZS1ncmlkLlxuICogICAgVGhlIG91dHB1dHMgb2YgdGhlIGdyb3VwaW5nIG5vZGUgYXJlIHRoZSBhZ2dyZWdhdGVkIHRpbWUgYnVja2V0ZWQgb3V0cHV0cyBvZiBpdCdzIGNoaWxkcmVuLlxuICogNS4gTm93IGEgZ3JvdXBpbmcgbm9kZSBoYXMgaXQncyBvd24gb3V0cHV0cywgaXQgY2FuIGhvcml6b3RuYWxseSBhZ2dyZWdhdGUgdGhlbS5cbiAqL1xuY29uc3QgYWdncmVnYXRlTm9kZSA9IChub2RlOiBhbnksIGFnZ3JlZ2F0aW9uUGFyYW1zOiBBZ2dyZWdhdGlvblBhcmFtc1N1cmUpID0+IHtcbiAgY29uc3QgbWV0cmljcyA9IGFnZ3JlZ2F0aW9uUGFyYW1zIS5tZXRyaWNzO1xuICBjb25zdCB0eXBlID0gYWdncmVnYXRpb25QYXJhbXMhLnR5cGU7XG5cbiAgaWYgKG5vZGUuY2hpbGRyZW4pIHtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIGluIG5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoQUdHUkVHQVRJTkdfTk9ERShjaGlsZCkpO1xuXG4gICAgICBhZ2dyZWdhdGVOb2RlKG5vZGUuY2hpbGRyZW5bY2hpbGRdLCBhZ2dyZWdhdGlvblBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFub2RlLmNoaWxkcmVuKSB7XG4gICAgLyoqIGB0aW1lYCBhZ2dyZWdhdGlvbiBpcyB0aGUgbmV3IG5hbWUgb2YgYGhvcml6b250YWxgLiAqL1xuICAgIGlmICh0eXBlID09PSAnaG9yaXpvbnRhbCcgfHwgdHlwZSA9PT0gJ3RpbWUnIHx8IHR5cGUgPT09ICdib3RoJykge1xuICAgICAgbm9kZS5hZ2dyZWdhdGVkID0gYWdncmVnYXRlT3V0cHV0c0ludG9PbmUobm9kZS5vdXRwdXRzLCBtZXRyaWNzKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLyoqIGBjb21wb25lbnRgIGFnZ3JlZ2F0aW9uIGlzIHRoZSBuZXcgbmFtZSBvZiBgdmVydGljYWxgLiAqL1xuICAgIGlmICh0eXBlID09PSAndmVydGljYWwnIHx8IHR5cGUgPT09ICdjb21wb25lbnQnIHx8IHR5cGUgPT09ICdib3RoJykge1xuICAgICAgY29uc3Qgb3V0cHV0cyA9IHRlbXBvcmFsQWdncmVnYXRpb24obm9kZSwgbWV0cmljcyk7XG4gICAgICBub2RlLm91dHB1dHMgPSBvdXRwdXRzO1xuICAgICAgbm9kZS5hZ2dyZWdhdGVkID0gYWdncmVnYXRlT3V0cHV0c0ludG9PbmUob3V0cHV0cywgbWV0cmljcyk7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIElmIGFnZ3JlZ2F0aW9uIGlzIGRpc2FibGVkLCB0aGVuIHJldHVybnMgZ2l2ZW4gYHRyZWVgLlxuICogT3RoZXJ3aXNlIGNyZWF0ZXMgY29weSBvZiB0aGUgdHJlZSwgdGhlbiBhcHBsaWVzIGFnZ3JlZ2F0aW9uIHRvIGl0LlxuICovXG5leHBvcnQgY29uc3QgYWdncmVnYXRlID0gKHRyZWU6IGFueSwgYWdncmVnYXRpb25QYXJhbXM6IEFnZ3JlZ2F0aW9uUGFyYW1zKSA9PiB7XG4gIGNvbnNvbGUuZGVidWcoQUdHUkVHQVRJTkdfT1VUUFVUUyk7XG5cbiAgaWYgKCFhZ2dyZWdhdGlvblBhcmFtcyB8fCAhYWdncmVnYXRpb25QYXJhbXMudHlwZSkge1xuICAgIHJldHVybiB0cmVlO1xuICB9XG5cbiAgY29uc3QgY29weU9mVHJlZSA9IHN0cnVjdHVyZWRDbG9uZSh0cmVlKTtcbiAgYWdncmVnYXRlTm9kZShjb3B5T2ZUcmVlLCBhZ2dyZWdhdGlvblBhcmFtcyk7XG5cbiAgcmV0dXJuIGNvcHlPZlRyZWU7XG59O1xuXG4vKipcbiAqIEdldHMgb3Igc3RvcmVzIGFnZ3JlZ2F0aW9uIG1ldHJpY3MuXG4gKi9cbmV4cG9ydCBjb25zdCBzdG9yZUFnZ3JlZ2F0aW9uTWV0cmljcyA9IChcbiAgYWdncmVnYXRpb25NZXRyaWNzPzogQWdncmVnYXRpb25NZXRyaWNzV2l0aE1ldGhvZFxuKSA9PiB7XG4gIGlmIChhZ2dyZWdhdGlvbk1ldHJpY3MpIHtcbiAgICBtZXRyaWNNYW5hZ2VyLm1ldHJpY3MgPSB7XG4gICAgICAuLi5tZXRyaWNNYW5hZ2VyLm1ldHJpY3MsXG4gICAgICAuLi5hZ2dyZWdhdGlvbk1ldHJpY3MsXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBtZXRyaWNNYW5hZ2VyLm1ldHJpY3M7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gZW5jYXBzdWxhdGVkIG9iamVjdCB0byByZXRyaWV2ZSB0aGUgbWV0cmljcy5cbiAqL1xuY29uc3QgbWV0cmljTWFuYWdlciA9ICgoKSA9PiB7XG4gIGxldCBtZXRyaWM6IEFnZ3JlZ2F0aW9uTWV0cmljc1dpdGhNZXRob2Q7XG5cbiAgY29uc3QgbWFuYWdlciA9IHtcbiAgICBnZXQgbWV0cmljcygpIHtcbiAgICAgIHJldHVybiBtZXRyaWM7XG4gICAgfSxcbiAgICBzZXQgbWV0cmljcyh2YWx1ZTogQWdncmVnYXRpb25NZXRyaWNzV2l0aE1ldGhvZCkge1xuICAgICAgbWV0cmljID0gdmFsdWU7XG4gICAgfSxcbiAgfTtcblxuICByZXR1cm4gbWFuYWdlcjtcbn0pKCk7XG5cbi8qKlxuICogUmV0dXJucyBhZ2dyZWdhdGlvbiBtZXRob2QgZm9yIGdpdmVuIGBtZXRyaWNgLlxuICovXG5leHBvcnQgY29uc3QgZ2V0QWdncmVnYXRpb25JbmZvRm9yID0gKG1ldHJpYzogc3RyaW5nKSA9PiB7XG4gIGRlYnVnTG9nZ2VyLnNldEV4ZWN1dGluZ1BsdWdpbk5hbWUoKTtcbiAgbWVtb2l6ZWRMb2coY29uc29sZS5kZWJ1ZywgJ1xcbicpO1xuICBtZW1vaXplZExvZyhjb25zb2xlLmRlYnVnLCBDSEVDS0lOR19BR0dSRUdBVElPTl9NRVRIT0QobWV0cmljKSk7XG4gIGNvbnN0IGFnZ3JlZ2F0aW9uTWV0cmljc1N0b3JhZ2UgPSBzdG9yZUFnZ3JlZ2F0aW9uTWV0cmljcygpO1xuXG4gIGlmIChcbiAgICBhZ2dyZWdhdGlvbk1ldHJpY3NTdG9yYWdlICYmXG4gICAgT2JqZWN0LmtleXMoYWdncmVnYXRpb25NZXRyaWNzU3RvcmFnZSkuaW5jbHVkZXMobWV0cmljKVxuICApIHtcbiAgICByZXR1cm4gYWdncmVnYXRpb25NZXRyaWNzU3RvcmFnZVttZXRyaWNdO1xuICB9XG5cbiAgbWVtb2l6ZWRMb2cobG9nZ2VyLndhcm4sIFVOS05PV05fUEFSQU0obWV0cmljKSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0aW1lOiBBR0dSRUdBVElPTl9NRVRIT0RTWzNdLFxuICAgIGNvbXBvbmVudDogQUdHUkVHQVRJT05fTUVUSE9EU1szXSxcbiAgfTtcbn07XG4iXX0=