1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.MetricSet = exports.allMetricsGraphJson = void 0;
|
4 | const drop_empty_object_at_the_end_of_an_array_token_1 = require("./drop-empty-object-at-the-end-of-an-array-token");
|
5 | const env_tokens_1 = require("./env-tokens");
|
6 | const metric_util_1 = require("./metric-util");
|
7 | const object_1 = require("./object");
|
8 | /**
|
9 | * Return the JSON structure which represents these metrics in a graph.
|
10 | *
|
11 | * Depending on the metric type (stat or expression), one `Metric` object
|
12 | * can render to multiple time series.
|
13 | *
|
14 | * - Top-level metrics will be rendered visibly, additionally added metrics will
|
15 | * be rendered invisibly.
|
16 | * - IDs used in math expressions need to be either globally unique, or refer to the same
|
17 | * metric object.
|
18 | *
|
19 | * This will be called by GraphWidget, no need for clients to call this.
|
20 | */
|
21 | function allMetricsGraphJson(left, right) {
|
22 | // Add metrics to a set which will automatically expand them recursively,
|
23 | // making sure to retain conflicting the visible one on conflicting metrics objects.
|
24 | const mset = new MetricSet();
|
25 | mset.addTopLevel('left', ...left);
|
26 | mset.addTopLevel('right', ...right);
|
27 | // Render all metrics from the set.
|
28 | return mset.entries.map(entry => new drop_empty_object_at_the_end_of_an_array_token_1.DropEmptyObjectAtTheEndOfAnArray(metricGraphJson(entry.metric, entry.tag, entry.id)));
|
29 | }
|
30 | exports.allMetricsGraphJson = allMetricsGraphJson;
|
31 | function metricGraphJson(metric, yAxis, id) {
|
32 | const config = metric.toMetricConfig();
|
33 | const ret = [];
|
34 | const options = { ...config.renderingProperties };
|
35 | metric_util_1.dispatchMetric(metric, {
|
36 | withStat(stat) {
|
37 | ret.push(stat.namespace, stat.metricName);
|
38 | // Dimensions
|
39 | for (const dim of (stat.dimensions || [])) {
|
40 | ret.push(dim.name, dim.value);
|
41 | }
|
42 | // Metric attributes that are rendered to graph options
|
43 | if (stat.account) {
|
44 | options.accountId = env_tokens_1.accountIfDifferentFromStack(stat.account);
|
45 | }
|
46 | if (stat.region) {
|
47 | options.region = env_tokens_1.regionIfDifferentFromStack(stat.region);
|
48 | }
|
49 | if (stat.period && stat.period.toSeconds() !== 300) {
|
50 | options.period = stat.period.toSeconds();
|
51 | }
|
52 | if (stat.statistic && stat.statistic !== 'Average') {
|
53 | options.stat = stat.statistic;
|
54 | }
|
55 | },
|
56 | withExpression(expr) {
|
57 | options.expression = expr.expression;
|
58 | if (expr.searchAccount) {
|
59 | options.accountId = env_tokens_1.accountIfDifferentFromStack(expr.searchAccount);
|
60 | }
|
61 | if (expr.searchRegion) {
|
62 | options.region = env_tokens_1.regionIfDifferentFromStack(expr.searchRegion);
|
63 | }
|
64 | if (expr.period && expr.period !== 300) {
|
65 | options.period = expr.period;
|
66 | }
|
67 | },
|
68 | });
|
69 | // Options
|
70 | if (!yAxis) {
|
71 | options.visible = false;
|
72 | }
|
73 | if (yAxis !== 'left') {
|
74 | options.yAxis = yAxis;
|
75 | }
|
76 | if (id) {
|
77 | options.id = id;
|
78 | }
|
79 | if (options.visible !== false && options.expression && !options.label) {
|
80 | // Label may be '' or undefined.
|
81 | //
|
82 | // If undefined, we'll render the expression as the label, to suppress
|
83 | // the default behavior of CW where it would render the metric
|
84 | // id as label, which we (inelegantly) generate to be something like "metric_alias0".
|
85 | //
|
86 | // For array expressions (returning more than 1 TS) users may sometimes want to
|
87 | // suppress the label completely. For those cases, we'll accept the empty string,
|
88 | // and not render a label at all.
|
89 | options.label = options.label === '' ? undefined : metric.toString();
|
90 | }
|
91 | const renderedOpts = object_1.dropUndefined(options);
|
92 | if (Object.keys(renderedOpts).length !== 0) {
|
93 | ret.push(renderedOpts);
|
94 | }
|
95 | return ret;
|
96 | }
|
97 | /**
|
98 | * Contain a set of metrics, expanding math expressions
|
99 | *
|
100 | * "Primary" metrics (added via a top-level call) can be tagged with an additional value.
|
101 | */
|
102 | class MetricSet {
|
103 | constructor() {
|
104 | this.metrics = new Array();
|
105 | this.metricById = new Map();
|
106 | this.metricByKey = new Map();
|
107 | }
|
108 | /**
|
109 | * Add the given set of metrics to this set
|
110 | */
|
111 | addTopLevel(tag, ...metrics) {
|
112 | for (const metric of metrics) {
|
113 | this.addOne(metric, tag);
|
114 | }
|
115 | }
|
116 | /**
|
117 | * Access all the accumulated timeseries entries
|
118 | */
|
119 | get entries() {
|
120 | return this.metrics;
|
121 | }
|
122 | /**
|
123 | * Add a metric into the set
|
124 | *
|
125 | * The id may not be the same as a previous metric added, unless it's the same metric.
|
126 | *
|
127 | * It can be made visible, in which case the new "metric" object replaces the old
|
128 | * one (and the new ones "renderingPropertieS" will be honored instead of the old
|
129 | * one's).
|
130 | */
|
131 | addOne(metric, tag, id) {
|
132 | const key = metric_util_1.metricKey(metric);
|
133 | let existingEntry;
|
134 | // Try lookup existing by id if we have one
|
135 | if (id) {
|
136 | existingEntry = this.metricById.get(id);
|
137 | if (existingEntry && metric_util_1.metricKey(existingEntry.metric) !== key) {
|
138 | throw new Error(`Cannot have two different metrics share the same id ('${id}') in one Alarm or Graph. Rename one of them.`);
|
139 | }
|
140 | }
|
141 | if (!existingEntry) {
|
142 | // Try lookup by metric if we didn't find one by id
|
143 | existingEntry = this.metricByKey.get(key);
|
144 | // If the one we found already has an id, it must be different from the id
|
145 | // we're trying to add and we want to add a new metric. Pretend we didn't
|
146 | // find one.
|
147 | if (existingEntry?.id && id) {
|
148 | existingEntry = undefined;
|
149 | }
|
150 | }
|
151 | // Create a new entry if we didn't find one so far
|
152 | let entry;
|
153 | if (existingEntry) {
|
154 | entry = existingEntry;
|
155 | }
|
156 | else {
|
157 | entry = { metric };
|
158 | this.metrics.push(entry);
|
159 | this.metricByKey.set(key, entry);
|
160 | }
|
161 | // If it didn't have an id but now we do, add one
|
162 | if (!entry.id && id) {
|
163 | entry.id = id;
|
164 | this.metricById.set(id, entry);
|
165 | }
|
166 | // If it didn't have a tag but now we do, add one
|
167 | if (!entry.tag && tag) {
|
168 | entry.tag = tag;
|
169 | }
|
170 | // Recurse and add children
|
171 | const conf = metric.toMetricConfig();
|
172 | if (conf.mathExpression) {
|
173 | for (const [subId, subMetric] of Object.entries(conf.mathExpression.usingMetrics)) {
|
174 | this.addOne(subMetric, undefined, subId);
|
175 | }
|
176 | }
|
177 | }
|
178 | }
|
179 | exports.MetricSet = MetricSet;
|
180 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVuZGVyaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFIQUFvRztBQUNwRyw2Q0FBdUY7QUFDdkYsK0NBQTBEO0FBQzFELHFDQUF5QztBQUV6Qzs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxTQUFnQixtQkFBbUIsQ0FBQyxJQUFlLEVBQUUsS0FBZ0I7SUFDbkUseUVBQXlFO0lBQ3pFLG9GQUFvRjtJQUNwRixNQUFNLElBQUksR0FBRyxJQUFJLFNBQVMsRUFBVSxDQUFDO0lBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQztJQUVwQyxtQ0FBbUM7SUFDbkMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksaUZBQWdDLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzdILENBQUM7QUFURCxrREFTQztBQUVELFNBQVMsZUFBZSxDQUFDLE1BQWUsRUFBRSxLQUFjLEVBQUUsRUFBVztJQUNuRSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7SUFFdkMsTUFBTSxHQUFHLEdBQVUsRUFBRSxDQUFDO0lBQ3RCLE1BQU0sT0FBTyxHQUFRLEVBQUUsR0FBRyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUV2RCw0QkFBYyxDQUFDLE1BQU0sRUFBRTtRQUNyQixRQUFRLENBQUMsSUFBSTtZQUNYLEdBQUcsQ0FBQyxJQUFJLENBQ04sSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLENBQUMsVUFBVSxDQUNoQixDQUFDO1lBRUYsYUFB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YUFBYSxFQUFFO1lBQ2pCLEtBQUssR0FBRyxhQUFhLENBQUM7U0FDdkI7YUFBTTtZQUNMLEtBQUssR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUNsQztRQUVELGlEQUFpRDtRQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDbkIsS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFDZCxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDaEM7UUFFRCxpREFBaUQ7UUFDakQsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksR0FBRyxFQUFFO1lBQ3JCLEtBQUssQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1NBQ2pCO1FBRUQsMkJBQTJCO1FBQzNCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUNyQyxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7WUFDdkIsS0FBSyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsRUFBRTtnQkFDakYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQzFDO1NBQ0Y7S0FDRjtDQUNGO0FBbEZELDhCQWtGQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElNZXRyaWMgfSBmcm9tICcuLi9tZXRyaWMtdHlwZXMnO1xuaW1wb3J0IHsgRHJvcEVtcHR5T2JqZWN0QXRUaGVFbmRPZkFuQXJyYXkgfSBmcm9tICcuL2Ryb3AtZW1wdHktb2JqZWN0LWF0LXRoZS1lbmQtb2YtYW4tYXJyYXktdG9rZW4nO1xuaW1wb3J0IHsgYWNjb3VudElmRGlmZmVyZW50RnJvbVN0YWNrLCByZWdpb25JZkRpZmZlcmVudEZyb21TdGFjayB9IGZyb20gJy4vZW52LXRva2Vucyc7XG5pbXBvcnQgeyBkaXNwYXRjaE1ldHJpYywgbWV0cmljS2V5IH0gZnJvbSAnLi9tZXRyaWMtdXRpbCc7XG5pbXBvcnQgeyBkcm9wVW5kZWZpbmVkIH0gZnJvbSAnLi9vYmplY3QnO1xuXG4vKipcbiAqIFJldHVybiB0aGUgSlNPTiBzdHJ1Y3R1cmUgd2hpY2ggcmVwcmVzZW50cyB0aGVzZSBtZXRyaWNzIGluIGEgZ3JhcGguXG4gKlxuICogRGVwZW5kaW5nIG9uIHRoZSBtZXRyaWMgdHlwZSAoc3RhdCBvciBleHByZXNzaW9uKSwgb25lIGBNZXRyaWNgIG9iamVjdFxuICogY2FuIHJlbmRlciB0byBtdWx0aXBsZSB0aW1lIHNlcmllcy5cbiAqXG4gKiAtIFRvcC1sZXZlbCBtZXRyaWNzIHdpbGwgYmUgcmVuZGVyZWQgdmlzaWJseSwgYWRkaXRpb25hbGx5IGFkZGVkIG1ldHJpY3Mgd2lsbFxuICogICBiZSByZW5kZXJlZCBpbnZpc2libHkuXG4gKiAtIElEcyB1c2VkIGluIG1hdGggZXhwcmVzc2lvbnMgbmVlZCB0byBiZSBlaXRoZXIgZ2xvYmFsbHkgdW5pcXVlLCBvciByZWZlciB0byB0aGUgc2FtZVxuICogICBtZXRyaWMgb2JqZWN0LlxuICpcbiAqIFRoaXMgd2lsbCBiZSBjYWxsZWQgYnkgR3JhcGhXaWRnZXQsIG5vIG5lZWQgZm9yIGNsaWVudHMgdG8gY2FsbCB0aGlzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYWxsTWV0cmljc0dyYXBoSnNvbihsZWZ0OiBJTWV0cmljW10sIHJpZ2h0OiBJTWV0cmljW10pOiBhbnlbXSB7XG4gIC8vIEFkZCBtZXRyaWNzIHRvIGEgc2V0IHdoaWNoIHdpbGwgYXV0b21hdGljYWxseSBleHBhbmQgdGhlbSByZWN1cnNpdmVseSxcbiAgLy8gbWFraW5nIHN1cmUgdG8gcmV0YWluIGNvbmZsaWN0aW5nIHRoZSB2aXNpYmxlIG9uZSBvbiBjb25mbGljdGluZyBtZXRyaWNzIG9iamVjdHMuXG4gIGNvbnN0IG1zZXQgPSBuZXcgTWV0cmljU2V0PHN0cmluZz4oKTtcbiAgbXNldC5hZGRUb3BMZXZlbCgnbGVmdCcsIC4uLmxlZnQpO1xuICBtc2V0LmFkZFRvcExldmVsKCdyaWdodCcsIC4uLnJpZ2h0KTtcblxuICAvLyBSZW5kZXIgYWxsIG1ldHJpY3MgZnJvbSB0aGUgc2V0LlxuICByZXR1cm4gbXNldC5lbnRyaWVzLm1hcChlbnRyeSA9PiBuZXcgRHJvcEVtcHR5T2JqZWN0QXRUaGVFbmRPZkFuQXJyYXkobWV0cmljR3JhcGhKc29uKGVudHJ5Lm1ldHJpYywgZW50cnkudGFnLCBlbnRyeS5pZCkpKTtcbn1cblxuZnVuY3Rpb24gbWV0cmljR3JhcGhKc29uKG1ldHJpYzogSU1ldHJpYywgeUF4aXM/OiBzdHJpbmcsIGlkPzogc3RyaW5nKSB7XG4gIGNvbnN0IGNvbmZpZyA9IG1ldHJpYy50b01ldHJpY0NvbmZpZygpO1xuXG4gIGNvbnN0IHJldDogYW55W10gPSBbXTtcbiAgY29uc3Qgb3B0aW9uczogYW55ID0geyAuLi5jb25maWcucmVuZGVyaW5nUHJvcGVydGllcyB9O1xuXG4gIGRpc3BhdGNoTWV0cmljKG1ldHJpYywge1xuICAgIHdpdGhTdGF0KHN0YXQpIHtcbiAgICAgIHJldC5wdXNoKFxuICAgICAgICBzdGF0Lm5hbWVzcGFjZSxcbiAgICAgICAgc3RhdC5tZXRyaWNOYW1lLFxuICAgICAgKTtcblxuICAgICAgLy8gRGltZW5zaW9uc1xuICAgICAgZm9yIChjb25zdCBkaW0gb2YgKHN0YXQuZGltZW5zaW9ucyB8fCBbXSkpIHtcbiAgICAgICAgcmV0LnB1c2goZGltLm5hbWUsIGRpbS52YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIE1ldHJpYyBhdHRyaWJ1dGVzIHRoYXQgYXJlIHJlbmRlcmVkIHRvIGdyYXBoIG9wdGlvbnNcbiAgICAgIGlmIChzdGF0LmFjY291bnQpIHsgb3B0aW9ucy5hY2NvdW50SWQgPSBhY2NvdW50SWZEaWZmZXJlbnRGcm9tU3RhY2soc3RhdC5hY2NvdW50KTsgfVxuICAgICAgaWYgKHN0YXQucmVnaW9uKSB7IG9wdGlvbnMucmVnaW9uID0gcmVnaW9uSWZEaWZmZXJlbnRGcm9tU3RhY2soc3RhdC5yZWdpb24pOyB9XG4gICAgICBpZiAoc3RhdC5wZXJpb2QgJiYgc3RhdC5wZXJpb2QudG9TZWNvbmRzKCkgIT09IDMwMCkgeyBvcHRpb25zLnBlcmlvZCA9IHN0YXQucGVyaW9kLnRvU2Vjb25kcygpOyB9XG4gICAgICBpZiAoc3RhdC5zdGF0aXN0aWMgJiYgc3RhdC5zdGF0aXN0aWMgIT09ICdBdmVyYWdlJykgeyBvcHRpb25zLnN0YXQgPSBzdGF0LnN0YXRpc3RpYzsgfVxuICAgIH0sXG5cbiAgICB3aXRoRXhwcmVzc2lvbihleHByKSB7XG4gICAgICBvcHRpb25zLmV4cHJlc3Npb24gPSBleHByLmV4cHJlc3Npb247XG4gICAgICBpZiAoZXhwci5zZWFyY2hBY2NvdW50KSB7IG9wdGlvbnMuYWNjb3VudElkID0gYWNjb3VudElmRGlmZmVyZW50RnJvbVN0YWNrKGV4cHIuc2VhcmNoQWNjb3VudCk7IH1cbiAgICAgIGlmIChleHByLnNlYXJjaFJlZ2lvbikgeyBvcHRpb25zLnJlZ2lvbiA9IHJlZ2lvbklmRGlmZmVyZW50RnJvbVN0YWNrKGV4cHIuc2VhcmNoUmVnaW9uKTsgfVxuICAgICAgaWYgKGV4cHIucGVyaW9kICYmIGV4cHIucGVyaW9kICE9PSAzMDApIHsgb3B0aW9ucy5wZXJpb2QgPSBleHByLnBlcmlvZDsgfVxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIE9wdGlvbnNcbiAgaWYgKCF5QXhpcykgeyBvcHRpb25zLnZpc2libGUgPSBmYWxzZTsgfVxuICBpZiAoeUF4aXMgIT09ICdsZWZ0JykgeyBvcHRpb25zLnlBeGlzID0geUF4aXM7IH1cbiAgaWYgKGlkKSB7IG9wdGlvbnMuaWQgPSBpZDsgfVxuXG4gIGlmIChvcHRpb25zLnZpc2libGUgIT09IGZhbHNlICYmIG9wdGlvbnMuZXhwcmVzc2lvbiAmJiAhb3B0aW9ucy5sYWJlbCkge1xuICAgIC8vIExhYmVsIG1heSBiZSAnJyBvciB1bmRlZmluZWQuXG4gICAgLy9cbiAgICAvLyBJZiB1bmRlZmluZWQsIHdlJ2xsIHJlbmRlciB0aGUgZXhwcmVzc2lvbiBhcyB0aGUgbGFiZWwsIHRvIHN1cHByZXNzXG4gICAgLy8gdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgQ1cgd2hlcmUgaXQgd291bGQgcmVuZGVyIHRoZSBtZXRyaWNcbiAgICAvLyBpZCBhcyBsYWJlbCwgd2hpY2ggd2UgKGluZWxlZ2FudGx5KSBnZW5lcmF0ZSB0byBiZSBzb21ldGhpbmcgbGlrZSBcIm1ldHJpY19hbGlhczBcIi5cbiAgICAvL1xuICAgIC8vIEZvciBhcnJheSBleHByZXNzaW9ucyAocmV0dXJuaW5nIG1vcmUgdGhhbiAxIFRTKSB1c2VycyBtYXkgc29tZXRpbWVzIHdhbnQgdG9cbiAgICAvLyBzdXBwcmVzcyB0aGUgbGFiZWwgY29tcGxldGVseS4gRm9yIHRob3NlIGNhc2VzLCB3ZSdsbCBhY2NlcHQgdGhlIGVtcHR5IHN0cmluZyxcbiAgICAvLyBhbmQgbm90IHJlbmRlciBhIGxhYmVsIGF0IGFsbC5cbiAgICBvcHRpb25zLmxhYmVsID0gb3B0aW9ucy5sYWJlbCA9PT0gJycgPyB1bmRlZmluZWQgOiBtZXRyaWMudG9TdHJpbmcoKTtcbiAgfVxuXG4gIGNvbnN0IHJlbmRlcmVkT3B0cyA9IGRyb3BVbmRlZmluZWQob3B0aW9ucyk7XG5cbiAgaWYgKE9iamVjdC5rZXlzKHJlbmRlcmVkT3B0cykubGVuZ3RoICE9PSAwKSB7XG4gICAgcmV0LnB1c2gocmVuZGVyZWRPcHRzKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIEEgc2luZ2xlIG1ldHJpYyBpbiBhIE1ldHJpY1NldFxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1ldHJpY0VudHJ5PEE+IHtcbiAgLyoqXG4gICAqIFRoZSBtZXRyaWMgb2JqZWN0XG4gICAqL1xuICByZWFkb25seSBtZXRyaWM6IElNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFRoZSB0YWcsIGFkZGVkIGlmIHRoZSBvYmplY3QgaXMgYSBwcmltYXJ5IG1ldHJpY1xuICAgKi9cbiAgdGFnPzogQTtcblxuICAvKipcbiAgICogSUQgZm9yIHRoaXMgbWV0cmljIG9iamVjdFxuICAgKi9cbiAgaWQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ29udGFpbiBhIHNldCBvZiBtZXRyaWNzLCBleHBhbmRpbmcgbWF0aCBleHByZXNzaW9uc1xuICpcbiAqIFwiUHJpbWFyeVwiIG1ldHJpY3MgKGFkZGVkIHZpYSBhIHRvcC1sZXZlbCBjYWxsKSBjYW4gYmUgdGFnZ2VkIHdpdGggYW4gYWRkaXRpb25hbCB2YWx1ZS5cbiAqL1xuZXhwb3J0IGNsYXNzIE1ldHJpY1NldDxBPiB7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWV0cmljcyA9IG5ldyBBcnJheTxNZXRyaWNFbnRyeTxBPj4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBtZXRyaWNCeUlkID0gbmV3IE1hcDxzdHJpbmcsIE1ldHJpY0VudHJ5PEE+PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IG1ldHJpY0J5S2V5ID0gbmV3IE1hcDxzdHJpbmcsIE1ldHJpY0VudHJ5PEE+PigpO1xuXG4gIC8qKlxuICAgKiBBZGQgdGhlIGdpdmVuIHNldCBvZiBtZXRyaWNzIHRvIHRoaXMgc2V0XG4gICAqL1xuICBwdWJsaWMgYWRkVG9wTGV2ZWwodGFnOiBBLCAuLi5tZXRyaWNzOiBJTWV0cmljW10pIHtcbiAgICBmb3IgKGNvbnN0IG1ldHJpYyBvZiBtZXRyaWNzKSB7XG4gICAgICB0aGlzLmFkZE9uZShtZXRyaWMsIHRhZyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFjY2VzcyBhbGwgdGhlIGFjY3VtdWxhdGVkIHRpbWVzZXJpZXMgZW50cmllc1xuICAgKi9cbiAgcHVibGljIGdldCBlbnRyaWVzKCk6IFJlYWRvbmx5QXJyYXk8TWV0cmljRW50cnk8QT4+IHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWNzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIG1ldHJpYyBpbnRvIHRoZSBzZXRcbiAgICpcbiAgICogVGhlIGlkIG1heSBub3QgYmUgdGhlIHNhbWUgYXMgYSBwcmV2aW91cyBtZXRyaWMgYWRkZWQsIHVubGVzcyBpdCdzIHRoZSBzYW1lIG1ldHJpYy5cbiAgICpcbiAgICogSXQgY2FuIGJlIG1hZGUgdmlzaWJsZSwgaW4gd2hpY2ggY2FzZSB0aGUgbmV3IFwibWV0cmljXCIgb2JqZWN0IHJlcGxhY2VzIHRoZSBvbGRcbiAgICogb25lIChhbmQgdGhlIG5ldyBvbmVzIFwicmVuZGVyaW5nUHJvcGVydGllU1wiIHdpbGwgYmUgaG9ub3JlZCBpbnN0ZWFkIG9mIHRoZSBvbGRcbiAgICogb25lJ3MpLlxuICAgKi9cbiAgcHJpdmF0ZSBhZGRPbmUobWV0cmljOiBJTWV0cmljLCB0YWc/OiBBLCBpZD86IHN0cmluZykge1xuICAgIGNvbnN0IGtleSA9IG1ldHJpY0tleShtZXRyaWMpO1xuXG4gICAgbGV0IGV4aXN0aW5nRW50cnk6IE1ldHJpY0VudHJ5PEE+IHwgdW5kZWZpbmVkO1xuXG4gICAgLy8gVHJ5IGxvb2t1cCBleGlzdGluZyBieSBpZCBpZiB3ZSBoYXZlIG9uZVxuICAgIGlmIChpZCkge1xuICAgICAgZXhpc3RpbmdFbnRyeSA9IHRoaXMubWV0cmljQnlJZC5nZXQoaWQpO1xuICAgICAgaWYgKGV4aXN0aW5nRW50cnkgJiYgbWV0cmljS2V5KGV4aXN0aW5nRW50cnkubWV0cmljKSAhPT0ga2V5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGhhdmUgdHdvIGRpZmZlcmVudCBtZXRyaWNzIHNoYXJlIHRoZSBzYW1lIGlkICgnJHtpZH0nKSBpbiBvbmUgQWxhcm0gb3IgR3JhcGguIFJlbmFtZSBvbmUgb2YgdGhlbS5gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWV4aXN0aW5nRW50cnkpIHtcbiAgICAgIC8vIFRyeSBsb29rdXAgYnkgbWV0cmljIGlmIHdlIGRpZG4ndCBmaW5kIG9uZSBieSBpZFxuICAgICAgZXhpc3RpbmdFbnRyeSA9IHRoaXMubWV0cmljQnlLZXkuZ2V0KGtleSk7XG5cbiAgICAgIC8vIElmIHRoZSBvbmUgd2UgZm91bmQgYWxyZWFkeSBoYXMgYW4gaWQsIGl0IG11c3QgYmUgZGlmZmVyZW50IGZyb20gdGhlIGlkXG4gICAgICAvLyB3ZSdyZSB0cnlpbmcgdG8gYWRkIGFuZCB3ZSB3YW50IHRvIGFkZCBhIG5ldyBtZXRyaWMuIFByZXRlbmQgd2UgZGlkbid0XG4gICAgICAvLyBmaW5kIG9uZS5cbiAgICAgIGlmIChleGlzdGluZ0VudHJ5Py5pZCAmJiBpZCkgeyBleGlzdGluZ0VudHJ5ID0gdW5kZWZpbmVkOyB9XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIGEgbmV3IGVudHJ5IGlmIHdlIGRpZG4ndCBmaW5kIG9uZSBzbyBmYXJcbiAgICBsZXQgZW50cnk7XG4gICAgaWYgKGV4aXN0aW5nRW50cnkpIHtcbiAgICAgIGVudHJ5ID0gZXhpc3RpbmdFbnRyeTtcbiAgICB9IGVsc2Uge1xuICAgICAgZW50cnkgPSB7IG1ldHJpYyB9O1xuICAgICAgdGhpcy5tZXRyaWNzLnB1c2goZW50cnkpO1xuICAgICAgdGhpcy5tZXRyaWNCeUtleS5zZXQoa2V5LCBlbnRyeSk7XG4gICAgfVxuXG4gICAgLy8gSWYgaXQgZGlkbid0IGhhdmUgYW4gaWQgYnV0IG5vdyB3ZSBkbywgYWRkIG9uZVxuICAgIGlmICghZW50cnkuaWQgJiYgaWQpIHtcbiAgICAgIGVudHJ5LmlkID0gaWQ7XG4gICAgICB0aGlzLm1ldHJpY0J5SWQuc2V0KGlkLCBlbnRyeSk7XG4gICAgfVxuXG4gICAgLy8gSWYgaXQgZGlkbid0IGhhdmUgYSB0YWcgYnV0IG5vdyB3ZSBkbywgYWRkIG9uZVxuICAgIGlmICghZW50cnkudGFnICYmIHRhZykge1xuICAgICAgZW50cnkudGFnID0gdGFnO1xuICAgIH1cblxuICAgIC8vIFJlY3Vyc2UgYW5kIGFkZCBjaGlsZHJlblxuICAgIGNvbnN0IGNvbmYgPSBtZXRyaWMudG9NZXRyaWNDb25maWcoKTtcbiAgICBpZiAoY29uZi5tYXRoRXhwcmVzc2lvbikge1xuICAgICAgZm9yIChjb25zdCBbc3ViSWQsIHN1Yk1ldHJpY10gb2YgT2JqZWN0LmVudHJpZXMoY29uZi5tYXRoRXhwcmVzc2lvbi51c2luZ01ldHJpY3MpKSB7XG4gICAgICAgIHRoaXMuYWRkT25lKHN1Yk1ldHJpYywgdW5kZWZpbmVkLCBzdWJJZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0= |
\ | No newline at end of file |